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);
B11 | B9 | B4;
Emit(encoding);
}
-
+#endif
void Assembler::vmstat(Condition cond) {
vmrs(APSR, cond);
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
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>
//
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:
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);
"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;
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); }
--- /dev/null
+; 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
+}