OSDN Git Service

Add vcvt<c>.f32.f64 and vcvt<c>.f64.32 to ARM.
authorKarl Schimpf <kschimpf@google.com>
Fri, 8 Jan 2016 15:31:08 +0000 (07:31 -0800)
committerKarl Schimpf <kschimpf@google.com>
Fri, 8 Jan 2016 15:31:08 +0000 (07:31 -0800)
Adds vcvt<c>.f32.f64 and vcvt<c>.f64.32 to the ARM integrated
assembler.

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

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

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/vcvt_f32_f64.ll [new file with mode: 0644]

index d51a9d3..990c083 100644 (file)
@@ -1069,7 +1069,8 @@ void Assembler::vsqrtd(DRegister dd, DRegister dm, Condition cond) {
   EmitVFPddd(cond, B23 | B21 | B20 | B16 | B7 | B6, dd, D0, dm);
 }
 
-
+#if 0
+// Moved to ARM32::AssemblerARM32::emitVFPsd
 void Assembler::EmitVFPsd(Condition cond, int32_t opcode,
                           SRegister sd, DRegister dm) {
   ASSERT(TargetCPUFeatures::vfp_supported());
@@ -1085,7 +1086,7 @@ void Assembler::EmitVFPsd(Condition cond, int32_t opcode,
   Emit(encoding);
 }
 
-
+// Moved to ARM32::AssemblerARM32::emitVFPds
 void Assembler::EmitVFPds(Condition cond, int32_t opcode,
                           DRegister dd, SRegister sm) {
   ASSERT(TargetCPUFeatures::vfp_supported());
@@ -1101,15 +1102,16 @@ void Assembler::EmitVFPds(Condition cond, int32_t opcode,
   Emit(encoding);
 }
 
-
+// Moved to ARM32::AssemblerARM32::vcvtsd().
 void Assembler::vcvtsd(SRegister sd, DRegister dm, Condition cond) {
   EmitVFPsd(cond, B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6, sd, dm);
 }
 
-
+// Moved to ARM32::AssemblerARM32::vcvtds().
 void Assembler::vcvtds(DRegister dd, SRegister sm, Condition cond) {
   EmitVFPds(cond, B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6, dd, sm);
 }
+#endif
 
 
 void Assembler::vcvtis(SRegister sd, SRegister sm, Condition cond) {
index 470a352..e103282 100644 (file)
@@ -714,8 +714,12 @@ class Assembler : public ValueObject {
   void vsqrts(SRegister sd, SRegister sm, Condition cond = AL);
   void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL);
 
+#if 0
+  // Moved to ARM32::AssemblerARM32::vcvtsd
   void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL);
+  // Moved to ARM32::AssemblerARM32:vcvtds
   void vcvtds(DRegister dd, SRegister sm, Condition cond = AL);
+#endif
   void vcvtis(SRegister sd, SRegister sm, Condition cond = AL);
   void vcvtid(SRegister sd, DRegister dm, Condition cond = AL);
   void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL);
@@ -1280,17 +1284,19 @@ class Assembler : public ValueObject {
                   DRegister dd,
                   DRegister dn,
                   DRegister dm);
-#endif
 
+  // Moved to ARM32::AssemblerARM32::emitVFPsd
   void EmitVFPsd(Condition cond,
                  int32_t opcode,
                  SRegister sd,
                  DRegister dm);
 
+  // Moved to ARM32::AssemblerARM32::emitVFPds
   void EmitVFPds(Condition cond,
                  int32_t opcode,
                  DRegister dd,
                  SRegister sm);
+#endif
 
   void EmitSIMDqqq(int32_t opcode, OperandSize sz,
                    QRegister qd, QRegister qn, QRegister qm);
index 2a3cb1a..8ee3297 100644 (file)
@@ -2071,6 +2071,53 @@ void AssemblerARM32::vaddd(const Operand *OpDd, const Operand *OpDn,
   emitVFPddd(Cond, VadddOpcode, Dd, Dn, Dm);
 }
 
+void AssemblerARM32::emitVFPsd(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd,
+                               IValueT Dm) {
+  assert(Sd < RegARM32::getNumSRegs());
+  assert(Dm < RegARM32::getNumDRegs());
+  assert(CondARM32::isDefined(Cond));
+  AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+  constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9;
+  const IValueT Encoding =
+      Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) |
+      (getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sd) << 12) |
+      (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm);
+  emitInst(Encoding);
+}
+
+void AssemblerARM32::vcvtsd(const Operand *OpSd, const Operand *OpDm,
+                            CondARM32::Cond Cond) {
+  constexpr const char *Vcvtsd = "vctsd";
+  IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtsd);
+  IValueT Dm = encodeDRegister(OpDm, "Dm", Vcvtsd);
+  constexpr IValueT VcvtsdOpcode =
+      B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6;
+  emitVFPsd(Cond, VcvtsdOpcode, Sd, Dm);
+}
+
+void AssemblerARM32::emitVFPds(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd,
+                               IValueT Sm) {
+  assert(Dd < RegARM32::getNumDRegs());
+  assert(Sm < RegARM32::getNumSRegs());
+  assert(CondARM32::isDefined(Cond));
+  AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+  constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9;
+  const IValueT Encoding =
+      Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) |
+      (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dd) << 12) |
+      (getYInRegXXXXY(Sm) << 5) | getXXXXInRegXXXXY(Sm);
+  emitInst(Encoding);
+}
+
+void AssemblerARM32::vcvtds(const Operand *OpDd, const Operand *OpSm,
+                            CondARM32::Cond Cond) {
+  constexpr const char *Vcvtds = "Vctds";
+  IValueT Dd = encodeDRegister(OpDd, "Dd", Vcvtds);
+  IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtds);
+  constexpr IValueT VcvtdsOpcode = B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6;
+  emitVFPds(Cond, VcvtdsOpcode, Dd, Sm);
+}
+
 void AssemblerARM32::vdivs(const Operand *OpSd, const Operand *OpSn,
                            const Operand *OpSm, CondARM32::Cond Cond) {
   // VDIV (floating-point) - ARM section A8.8.283, encoding A2:
index 86a6807..f81fd6d 100644 (file)
@@ -324,6 +324,10 @@ public:
   void vadds(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
              CondARM32::Cond Cond);
 
+  void vcvtsd(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond);
+
+  void vcvtds(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond);
+
   void vdivd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
              CondARM32::Cond Cond);
 
@@ -448,6 +452,14 @@ private:
   void emitVStackOp(CondARM32::Cond Cond, IValueT Opcode,
                     const Variable *OpBaseReg, SizeT NumConsecRegs);
 
+  // Pattern cccc111xxDxxxxxxdddd101xxxMxmmmm where cccc=Cond, ddddD=Sd,
+  // Mmmmm=Dm, and xx0xxxxxxdddd000xxx0x0000=Opcode.
+  void emitVFPsd(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd, IValueT Dm);
+
+  // Pattern cccc111xxDxxxxxxdddd101xxxMxmmmm where cccc=Cond, Ddddd=Dd,
+  // mmmmM=Sm, and xx0xxxxxxdddd000xxx0x0000=Opcode.
+  void emitVFPds(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd, IValueT Sm);
+
   // Pattern cccc011100x1dddd1111mmmm0001nnn where cccc=Cond,
   // x=Opcode, dddd=Rd, nnnn=Rn, mmmm=Rm.
   void emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn,
index 211798f..2560b7c 100644 (file)
@@ -1882,6 +1882,24 @@ void InstARM32Vcvt::emit(const Cfg *Func) const {
   getSrc(0)->emit(Func);
 }
 
+void InstARM32Vcvt::emitIAS(const Cfg *Func) const {
+  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+  switch (Variant) {
+  case S2d:
+    Asm->vcvtds(getDest(), getSrc(0), getPredicate());
+    break;
+  case D2s:
+    Asm->vcvtsd(getDest(), getSrc(0), getPredicate());
+    break;
+  default:
+    // TODO(kschimpf): Fill in other variants.
+    Asm->setNeedsTextFixup();
+    break;
+  }
+  if (Asm->needsTextFixup())
+    emitUsingTextFixup(Func);
+}
+
 void InstARM32Vcvt::dump(const Cfg *Func) const {
   if (!BuildDefs::dump())
     return;
index 46e27de..c069d34 100644 (file)
@@ -1233,6 +1233,7 @@ public:
         InstARM32Vcvt(Func, Dest, Src, Variant, Predicate);
   }
   void emit(const Cfg *Func) const override;
+  void emitIAS(const Cfg *Func) const override;
   void dump(const Cfg *Func) const override;
   static bool classof(const Inst *Inst) { return isClassof(Inst, Vcvt); }
 
diff --git a/tests_lit/assembler/arm32/vcvt_f32_f64.ll b/tests_lit/assembler/arm32/vcvt_f32_f64.ll
new file mode 100644 (file)
index 0000000..e320588
--- /dev/null
@@ -0,0 +1,62 @@
+; Show that we know how to translate vcvt between float and double.
+
+; NOTE: We use -O2 to get rid of memory stores.
+
+; REQUIRES: allow_dump
+
+; Compile using standalone assembler.
+; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -O2 \
+; RUN:   | FileCheck %s --check-prefix=ASM
+
+; Show bytes in assembled standalone code.
+; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
+; RUN:   --args -O2 | FileCheck %s --check-prefix=DIS
+
+; Compile using integrated assembler.
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -O2 \
+; RUN:   | FileCheck %s --check-prefix=IASM
+
+; Show bytes in assembled integrated code.
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
+; RUN:   --args -O2 | FileCheck %s --check-prefix=DIS
+
+define internal double @testVcvtFloatToDouble(float %v) {
+; ASM-LABEL: testVcvtFloatToDouble:
+; DIS-LABEL: 00000000 <testVcvtFloatToDouble>:
+; IASM-LABEL: testVcvtFloatToDouble:
+
+entry:
+; ASM-NEXT: .LtestVcvtFloatToDouble$entry:
+; IASM-NEXT: .LtestVcvtFloatToDouble$entry:
+
+  %res = fpext float %v to double
+
+; ASM-NEXT:    vcvt.f64.f32    d0, s0
+; DIS-NEXT:    0:      eeb70ac0
+; IASM-NEXT:   .byte 0xc0
+; IASM-NEXT:   .byte 0xa
+; IASM-NEXT:   .byte 0xb7
+; IASM-NEXT:   .byte 0xee
+
+  ret double %res
+}
+
+define internal float @testVcvtDoubleToFloat(double %v) {
+; ASM-LABEL: testVcvtDoubleToFloat:
+; DIS-LABEL: 00000010 <testVcvtDoubleToFloat>:
+; IASM-LABEL: testVcvtDoubleToFloat:
+
+entry:
+; ASM-NEXT: .LtestVcvtDoubleToFloat$entry:
+; IASM-NEXT: .LtestVcvtDoubleToFloat$entry:
+
+  %res = fptrunc double %v to float
+; ASM-NEXT:    vcvt.f32.f64    s0, d0
+; DIS-NEXT:   10:      eeb70bc0
+; IASM-NEXT:   .byte 0xc0
+; IASM-NEXT:   .byte 0xb
+; IASM-NEXT:   .byte 0xb7
+; IASM-NEXT:   .byte 0xee
+
+  ret float %res
+}