OSDN Git Service

Add the VMRS instruction to the integrated ARM assembler.
authorKarl Schimpf <kschimpf@google.com>
Mon, 25 Jan 2016 17:17:26 +0000 (09:17 -0800)
committerKarl Schimpf <kschimpf@google.com>
Mon, 25 Jan 2016 17:17:26 +0000 (09:17 -0800)
Note: Only adds the APSR_nzcv register form of the instruction.

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

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

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

index ebf413e..0eef894 100644 (file)
@@ -1171,8 +1171,8 @@ void Assembler::vcmpsz(SRegister sd, Condition cond) {
 void Assembler::vcmpdz(DRegister dd, Condition cond) {
   EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0);
 }
-#endif
 
+// APSR_nzcv version moved to ARM32::AssemblerARM32::vmrsAPSR_nzcv()
 void Assembler::vmrs(Register rd, Condition cond) {
   ASSERT(TargetCPUFeatures::vfp_supported());
   ASSERT(cond != kNoCondition);
@@ -1182,7 +1182,7 @@ void Assembler::vmrs(Register rd, Condition cond) {
                      B11 | B9 | B4;
   Emit(encoding);
 }
-
+#endif
 
 void Assembler::vmstat(Condition cond) {
   vmrs(APSR, cond);
index e79f459..c50fe4d 100644 (file)
@@ -755,9 +755,10 @@ class Assembler : public ValueObject {
   void vcmpsz(SRegister sd, Condition cond = AL);
   // Moved to ARM23::AssemblerARM32::vcmpdz().
   void vcmpdz(DRegister dd, Condition cond = AL);
-#endif
 
+  // APSR_nzcv version moved to ARM32::AssemblerARM32::vmrsAPSR_nzcv()
   void vmrs(Register rd, Condition cond = AL);
+#endif
   void vmstat(Condition cond = AL);
 
   // Duplicates the operand of size sz at index idx from dm to all elements of
index 00f2a80..61ce367 100644 (file)
@@ -2382,7 +2382,7 @@ void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress,
 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.
+  //   ARM section A8.8.343, encoding A1.
   //
   //   vmov<c> <Sn>, <Rt>
   //
@@ -2400,6 +2400,20 @@ void AssemblerARM32::vmovsr(const Operand *OpSn, const Operand *OpRt,
   emitInst(Encoding);
 }
 
+void AssemblerARM32::vmrsAPSR_nzcv(CondARM32::Cond Cond) {
+  // MVRS - ARM section A*.8.348, encoding A1:
+  //   vmrs<c> APSR_nzcv, FPSCR
+  //
+  // cccc111011110001tttt101000010000 where tttt=0x15 (i.e. when Rt=pc, use
+  // APSR_nzcv instead).
+  assert(CondARM32::isDefined(Cond));
+  IValueT Encoding = B27 | B26 | B25 | B23 | B22 | B21 | B20 | B16 | B15 | B14 |
+                     B13 | B12 | B11 | B9 | B4 |
+                     (encodeCondition(Cond) << kConditionShift);
+  AssemblerBuffer::EnsureCapacity ensured(&Buffer);
+  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 f7654b2..2710e58 100644 (file)
@@ -384,6 +384,9 @@ public:
 
   void vmovsr(const Operand *OpSn, const Operand *OpRt, CondARM32::Cond Cond);
 
+  // Uses APSR_nzcv as register
+  void vmrsAPSR_nzcv(CondARM32::Cond Cond);
+
   void vmuld(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
              CondARM32::Cond Cond);
 
index 1eeb19a..5f4991f 100644 (file)
@@ -1998,6 +1998,12 @@ void InstARM32Vmrs::emit(const Cfg *Func) const {
                                      "FPSCR";
 }
 
+void InstARM32Vmrs::emitIAS(const Cfg *Func) const {
+  auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+  Asm->vmrsAPSR_nzcv(getPredicate());
+  assert(!Asm->needsTextFixup());
+}
+
 void InstARM32Vmrs::dump(const Cfg *Func) const {
   if (!BuildDefs::dump())
     return;
index 9a30d26..6dba05f 100644 (file)
@@ -1383,6 +1383,7 @@ public:
     return new (Func->allocate<InstARM32Vmrs>()) InstARM32Vmrs(Func, 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, Vmrs); }
 
diff --git a/tests_lit/assembler/arm32/vmrs.ll b/tests_lit/assembler/arm32/vmrs.ll
new file mode 100644 (file)
index 0000000..85763b1
--- /dev/null
@@ -0,0 +1,38 @@
+; Test the "vmrs APSR_nzcv, FPSCR" form of the VMRS instruction.
+
+; REQUIRES: allow_dump
+
+; Compile using standalone assembler.
+; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
+; 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:   | FileCheck %s --check-prefix=DIS
+
+; Compile using integrated assembler.
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
+; 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:   | FileCheck %s --check-prefix=DIS
+
+define internal i32 @testVmrsASPR_nzcv() {
+; ASM-LABEL: testVmrsASPR_nzcv:
+; DIS-LABEL: 00000000 <testVmrsASPR_nzcv>:
+
+entry:
+; ASM: .LtestVmrsASPR_nzcv$entry:
+
+  %test = fcmp olt float 0.0, 0.0
+
+; ASM:  vmrs    APSR_nzcv, FPSCR
+; DIS:   18:    eef1fa10
+; IASM-NOT: vmrs
+
+  %result = zext i1 %test to i32
+  ret i32 %result
+}