OSDN Git Service

Add VMULS and VMULD instructions to integrated ARM assembler.
authorKarl Schimpf <kschimpf@google.com>
Thu, 7 Jan 2016 21:46:20 +0000 (13:46 -0800)
committerKarl Schimpf <kschimpf@google.com>
Thu, 7 Jan 2016 21:46:20 +0000 (13:46 -0800)
BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334
R=stichnot@chromium.org

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

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

index cd471a6..d51a9d3 100644 (file)
@@ -991,6 +991,7 @@ void Assembler::vsubd(DRegister dd, DRegister dn, DRegister dm,
 }
 #endif
 
+#if 0
 void Assembler::vmuls(SRegister sd, SRegister sn, SRegister sm,
                       Condition cond) {
   EmitVFPsss(cond, B21, sd, sn, sm);
@@ -1001,7 +1002,7 @@ void Assembler::vmuld(DRegister dd, DRegister dn, DRegister dm,
                       Condition cond) {
   EmitVFPddd(cond, B21, dd, dn, dm);
 }
-
+#endif
 
 void Assembler::vmlas(SRegister sd, SRegister sn, SRegister sm,
                       Condition cond) {
index 01ce7ec..470a352 100644 (file)
@@ -663,8 +663,12 @@ class Assembler : public ValueObject {
 #endif
   void vsubqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
   void vsubqs(QRegister qd, QRegister qn, QRegister qm);
+#if 0
+  // Moved to Arm32::AssemblerARM32::vmuls()
   void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
+  // Moved to Arm32::AssemblerARM32::vmuld()
   void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
+#endif
   void vmulqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
   void vmulqs(QRegister qd, QRegister qn, QRegister qm);
   void vshlqi(OperandSize sz, QRegister qd, QRegister qm, QRegister qn);
index 18dadaa..2a3cb1a 100644 (file)
@@ -2101,6 +2101,36 @@ void AssemblerARM32::vdivd(const Operand *OpDd, const Operand *OpDn,
   emitVFPddd(Cond, VdivdOpcode, Dd, Dn, Dm);
 }
 
+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:
+  //   vmul<c>.f32 <Sd>, <Sn>, <Sm>
+  //
+  // cccc11100D10nnnndddd101sN0M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn,
+  // and mmmmM=Rm.
+  constexpr const char *Vmuls = "vmuls";
+  IValueT Sd = encodeSRegister(OpSd, "Sd", Vmuls);
+  IValueT Sn = encodeSRegister(OpSn, "Sn", Vmuls);
+  IValueT Sm = encodeSRegister(OpSm, "Sm", Vmuls);
+  constexpr IValueT VmulsOpcode = B21;
+  emitVFPsss(Cond, VmulsOpcode, Sd, Sn, Sm);
+}
+
+void AssemblerARM32::vmuld(const Operand *OpDd, const Operand *OpDn,
+                           const Operand *OpDm, CondARM32::Cond Cond) {
+  // VMUL (floating-point) - ARM section A8.8.351, encoding A2:
+  //   vmul<c>.f64 <Dd>, <Dn>, <Dm>
+  //
+  // cccc11100D10nnnndddd101sN0M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn,
+  // and Mmmmm=Rm.
+  constexpr const char *Vmuld = "vmuld";
+  IValueT Dd = encodeDRegister(OpDd, "Dd", Vmuld);
+  IValueT Dn = encodeDRegister(OpDn, "Dn", Vmuld);
+  IValueT Dm = encodeDRegister(OpDm, "Dm", Vmuld);
+  constexpr IValueT VmuldOpcode = B21;
+  emitVFPddd(Cond, VmuldOpcode, Dd, Dn, Dm);
+}
+
 void AssemblerARM32::vsubs(const Operand *OpSd, const Operand *OpSn,
                            const Operand *OpSm, CondARM32::Cond Cond) {
   // VSUB (floating-point) - ARM section A8.8.415, encoding A2:
index da5ccd0..86a6807 100644 (file)
@@ -330,6 +330,12 @@ public:
   void vdivs(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
              CondARM32::Cond Cond);
 
+  void vmuld(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
+             CondARM32::Cond Cond);
+
+  void vmuls(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
+             CondARM32::Cond Cond);
+
   void vpop(const Variable *OpBaseReg, SizeT NumConsecRegs,
             CondARM32::Cond Cond);
 
index 59edde3..211798f 100644 (file)
@@ -651,6 +651,24 @@ template <> void InstARM32Vsub::emitIAS(const Cfg *Func) const {
   assert(!Asm->needsTextFixup());
 }
 
+template <> void InstARM32Vmul::emitIAS(const Cfg *Func) const {
+  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+  const Variable *Dest = getDest();
+  switch (Dest->getType()) {
+  default:
+    // TODO(kschimpf) Figure if more cases are needed.
+    Asm->setNeedsTextFixup();
+    break;
+  case IceType_f32:
+    Asm->vmuls(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
+    break;
+  case IceType_f64:
+    Asm->vmuld(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
+    break;
+  }
+  assert(!Asm->needsTextFixup());
+}
+
 InstARM32Call::InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
     : InstARM32(Func, InstARM32::Call, 1, Dest) {
   HasSideEffects = true;
diff --git a/tests_lit/assembler/arm32/vmul.ll b/tests_lit/assembler/arm32/vmul.ll
new file mode 100644 (file)
index 0000000..7d53279
--- /dev/null
@@ -0,0 +1,63 @@
+; Show that we know how to translate vmul.
+
+; 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 float @testVmulFloat(float %a, float %b) {
+; ASM-LABEL: testVmulFloat:
+; DIS-LABEL: 00000000 <testVmulFloat>:
+; IASM-LABEL: testVmulFloat:
+
+entry:
+; ASM-NEXT: .LtestVmulFloat$entry:
+; IASM-NEXT: .LtestVmulFloat$entry:
+
+  %mul = fmul float %a, %b
+
+; ASM-NEXT:    vmul.f32        s0, s0, s1
+; DIS-NEXT:    0:       ee200a20
+; IASM-NEXT:    .byte 0x20
+; IASM-NEXT:    .byte 0xa
+; IASM-NEXT:    .byte 0x20
+; IASM-NEXT:    .byte 0xee
+
+  ret float %mul
+}
+
+define internal double @testVmulDouble(double %a, double %b) {
+; ASM-LABEL: testVmulDouble:
+; DIS-LABEL: 00000010 <testVmulDouble>:
+; IASM-LABEL: testVmulDouble:
+
+entry:
+; ASM-NEXT: .LtestVmulDouble$entry:
+; IASM-NEXT: .LtestVmulDouble$entry:
+
+  %mul = fmul double %a, %b
+
+; ASM-NEXT:    vmul.f64        d0, d0, d1
+; DIS-NEXT:   10:       ee200b01
+; IASM-NEXT:    .byte 0x1
+; IASM-NEXT:    .byte 0xb
+; IASM-NEXT:    .byte 0x20
+; IASM-NEXT:    .byte 0xee
+
+  ret double %mul
+}