OSDN Git Service

Clean up handling of ARM IR instruction "mov".
authorKarl Schimpf <kschimpf@google.com>
Fri, 22 Jan 2016 23:15:50 +0000 (15:15 -0800)
committerKarl Schimpf <kschimpf@google.com>
Fri, 22 Jan 2016 23:15:50 +0000 (15:15 -0800)
Also adds VMOVSR instruction to the integrated ARM assembler.

BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334
R=jpp@chromium.org, stichnot@chromium.org

Review URL: https://codereview.chromium.org/1596613002 .

src/DartARM32/assembler_arm.cc
src/DartARM32/assembler_arm.h
src/IceAssemblerARM32.cpp
src/IceAssemblerARM32.h
src/IceInstARM32.cpp
src/IceInstARM32.h
tests_lit/assembler/arm32/vmov-cast.ll [new file with mode: 0644]

index 31889cd..ebf413e 100644 (file)
@@ -604,9 +604,8 @@ void Assembler::nop(Condition cond) {
                      B25 | B24 | B21 | (0xf << 12);
   Emit(encoding);
 }
-#endif
-
 
+// Moved to ARM32::AssemblerARM32::vmovsr().
 void Assembler::vmovsr(SRegister sn, Register rt, Condition cond) {
   ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(sn != kNoSRegister);
@@ -621,7 +620,7 @@ void Assembler::vmovsr(SRegister sn, Register rt, Condition cond) {
                      ((static_cast<int32_t>(sn) & 1)*B7) | B4;
   Emit(encoding);
 }
-
+#endif
 
 void Assembler::vmovrs(Register rt, SRegister sn, Condition cond) {
   ASSERT(TargetCPUFeatures::vfp_supported());
index ade252e..e79f459 100644 (file)
@@ -617,7 +617,10 @@ class Assembler : public ValueObject {
   }
 
   // Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
+#if 0
+  // Moved to ARM32::AssemblerARM32::vmovsr().
   void vmovsr(SRegister sn, Register rt, Condition cond = AL);
+#endif
   void vmovrs(Register rt, SRegister sn, Condition cond = AL);
   void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL);
   void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL);
index eec12cb..00f2a80 100644 (file)
@@ -199,6 +199,7 @@ IValueT getEncodedGPRegNum(const Variable *Var) {
 }
 
 IValueT getEncodedSRegNum(const Variable *Var) {
+  assert(Var->hasReg());
   return RegARM32::getEncodedSReg(Var->getRegNum());
 }
 
@@ -2378,6 +2379,27 @@ void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress,
   emitInst(Encoding);
 }
 
+void AssemblerARM32::vmovsr(const Operand *OpSn, const Operand *OpRt,
+                            CondARM32::Cond Cond) {
+  // VMOV (between ARM core register and single-precision register)
+  //   ARM seciont A8.8.343, encoding A1.
+  //
+  //   vmov<c> <Sn>, <Rt>
+  //
+  // cccc1110000onnnntttt1010N0010000 where cccc=Cond, nnnnN = Sn, and tttt=Rt.
+  constexpr const char *Vmovsr = "vmovsr";
+  IValueT Sn = encodeSRegister(OpSn, "Sn", Vmovsr);
+  IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovsr);
+  assert(Sn < RegARM32::getNumSRegs());
+  assert(Rt < RegARM32::getNumGPRegs());
+  assert(CondARM32::isDefined(Cond));
+  AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+  IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B27 | B26 |
+                     B25 | B11 | B9 | B4 | (getXXXXInRegXXXXY(Sn) << 16) |
+                     (Rt << kRdShift) | (getYInRegXXXXY(Sn) << 7);
+  emitInst(Encoding);
+}
+
 void AssemblerARM32::vmuls(const Operand *OpSd, const Operand *OpSn,
                            const Operand *OpSm, CondARM32::Cond Cond) {
   // VMUL (floating-point) - ARM section A8.8.351, encoding A2:
index 8af82eb..f7654b2 100644 (file)
@@ -382,6 +382,8 @@ public:
     vldrs(OpSd, OpAddress, Cond, TInfo);
   }
 
+  void vmovsr(const Operand *OpSn, const Operand *OpRt, CondARM32::Cond Cond);
+
   void vmuld(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
              CondARM32::Cond Cond);
 
index da71166..1eeb19a 100644 (file)
@@ -1124,6 +1124,30 @@ void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
   Src0->emit(Func);
 }
 
+void InstARM32Mov::emitIASCoreVFPMove(const Cfg *Func) const {
+  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+  Operand *Src0 = getSrc(0);
+  if (!llvm::isa<Variable>(Src0))
+    // TODO(kschimpf) Handle moving constants into registers.
+    return Asm->setNeedsTextFixup();
+
+  // Move register to register.
+  Variable *Dest = getDest();
+  switch (Dest->getType()) {
+  default:
+    // TODO(kschimpf): Fill this out more.
+    return Asm->setNeedsTextFixup();
+  case IceType_f32:
+    switch (Src0->getType()) {
+    default:
+      // TODO(kschimpf): Fill this out more?
+      return Asm->setNeedsTextFixup();
+    case IceType_i32:
+      return Asm->vmovsr(Dest, Src0, getPredicate());
+    }
+  }
+}
+
 void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const {
   auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
   Variable *Dest = getDest();
@@ -1137,12 +1161,16 @@ void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const {
     llvm::report_fatal_error("mov can't load.");
   }
 
+  if (isMoveBetweenCoreAndVFPRegisters(Dest, Src0))
+    return emitIASCoreVFPMove(Func);
+
   const Type DestTy = Dest->getType();
-  const bool DestIsVector = isVectorType(DestTy);
-  const bool DestIsScalarFP = isScalarFloatingType(DestTy);
-  const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0);
-  if (DestIsVector || DestIsScalarFP || CoreVFPMove)
+  if (isScalarFloatingType(DestTy))
+    return Asm->setNeedsTextFixup();
+
+  if (isVectorType(DestTy))
     return Asm->setNeedsTextFixup();
+
   return Asm->mov(Dest, Src0, getPredicate());
 }
 
index 6a9aa35..9a30d26 100644 (file)
@@ -1340,6 +1340,7 @@ private:
   void emitSingleDestSingleSource(const Cfg *Func) const;
 
   void emitIASSingleDestSingleSource(const Cfg *Func) const;
+  void emitIASCoreVFPMove(const Cfg *Func) const;
 
   Variable *DestHi = nullptr;
 };
diff --git a/tests_lit/assembler/arm32/vmov-cast.ll b/tests_lit/assembler/arm32/vmov-cast.ll
new file mode 100644 (file)
index 0000000..2fa59d1
--- /dev/null
@@ -0,0 +1,45 @@
+; Show that we know how to translate vmov for casts.
+
+; NOTE: Restricts S register to one that will better test S register encodings.
+
+; REQUIRES: allow_dump
+
+; Compile using standalone assembler.
+; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
+; RUN:   -reg-use s20,s22,d20,d22 \
+; RUN:   | FileCheck %s --check-prefix=ASM
+
+; Show bytes in assembled standalone code.
+; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
+; RUN:   --args -Om1 \
+; RUN:   -reg-use s20,s22,d20,d22 \
+; RUN:   | FileCheck %s --check-prefix=DIS
+
+; Compile using integrated assembler.
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
+; RUN:   -reg-use s20,s22,d20,d22 \
+; RUN:   | FileCheck %s --check-prefix=IASM
+
+; Show bytes in assembled integrated code.
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
+; RUN:   --args -Om1 \
+; RUN:   -reg-use s20,s22,d20,d22 \
+; RUN:   | FileCheck %s --check-prefix=DIS
+
+define internal float @castToFloat(i32 %a) {
+; ASM-LABEL: castToFloat:
+; DIS-LABEL: 00000000 <castToFloat>:
+; IASM-LABEL: castToFloat:
+
+entry:
+; ASM: .LcastToFloat$entry:
+; IASM: .LcastToFloat$entry:
+
+  %0 = bitcast i32 %a to float
+
+; ASM:          vmov    s20, r0
+; DIS:  10:     ee0a0a10
+; IASM-NOT:     vmov
+
+  ret float %0
+}