EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm);
}
-
+#if 0
+// Moved to ARM23::AssemblerARM32::vcmps().
void Assembler::vcmps(SRegister sd, SRegister sm, Condition cond) {
EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm);
}
-
+// Moved to ARM23::AssemblerARM32::vcmpd().
void Assembler::vcmpd(DRegister dd, DRegister dm, Condition cond) {
EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm);
}
-
+// Moved to ARM23::AssemblerARM32::vcmpsz().
void Assembler::vcmpsz(SRegister sd, Condition cond) {
EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0);
}
-
+// Moved to ARM23::AssemblerARM32::vcmpdz().
void Assembler::vcmpdz(DRegister dd, Condition cond) {
EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0);
}
-
+#endif
void Assembler::vmrs(Register rd, Condition cond) {
ASSERT(TargetCPUFeatures::vfp_supported());
void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL);
void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL);
+#if 0
+ // Moved to ARM23::AssemblerARM32::vcmps().
void vcmps(SRegister sd, SRegister sm, Condition cond = AL);
+ // Moved to ARM23::AssemblerARM32::vcmpd().
void vcmpd(DRegister dd, DRegister dm, Condition cond = AL);
+ // Moved to ARM23::AssemblerARM32::vcmpsz().
void vcmpsz(SRegister sd, Condition cond = AL);
+ // Moved to ARM23::AssemblerARM32::vcmpdz().
void vcmpdz(DRegister dd, Condition cond = AL);
+#endif
+
void vmrs(Register rd, Condition cond = AL);
void vmstat(Condition cond = AL);
const IValueT Encoding =
Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) |
(getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) |
- (getXXXXInRegYXXXX(Dn) << 12) | (getYInRegYXXXX(Dn) << 7) |
+ (getXXXXInRegYXXXX(Dd) << 12) | (getYInRegYXXXX(Dn) << 7) |
(getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm);
emitInst(Encoding);
}
emitVFPddd(Cond, VadddOpcode, Dd, Dn, Dm);
}
+void AssemblerARM32::vcmpd(const Operand *OpDd, const Operand *OpDm,
+ CondARM32::Cond Cond) {
+ constexpr const char *Vcmpd = "vcmpd";
+ IValueT Dd = encodeDRegister(OpDd, "Dd", Vcmpd);
+ IValueT Dm = encodeDRegister(OpDm, "Dm", Vcmpd);
+ constexpr IValueT VcmpdOpcode = B23 | B21 | B20 | B18 | B6;
+ constexpr IValueT Dn = 0;
+ emitVFPddd(Cond, VcmpdOpcode, Dd, Dn, Dm);
+}
+
+void AssemblerARM32::vcmpdz(const Operand *OpDd, CondARM32::Cond Cond) {
+ constexpr const char *Vcmpdz = "vcmpdz";
+ IValueT Dd = encodeDRegister(OpDd, "Dd", Vcmpdz);
+ constexpr IValueT VcmpdzOpcode = B23 | B21 | B20 | B18 | B16 | B6;
+ constexpr IValueT Dn = 0;
+ constexpr IValueT Dm = 0;
+ emitVFPddd(Cond, VcmpdzOpcode, Dd, Dn, Dm);
+}
+
+void AssemblerARM32::vcmps(const Operand *OpSd, const Operand *OpSm,
+ CondARM32::Cond Cond) {
+ constexpr const char *Vcmps = "vcmps";
+ IValueT Sd = encodeSRegister(OpSd, "Sd", Vcmps);
+ IValueT Sm = encodeSRegister(OpSm, "Sm", Vcmps);
+ constexpr IValueT VcmpsOpcode = B23 | B21 | B20 | B18 | B6;
+ constexpr IValueT Sn = 0;
+ emitVFPsss(Cond, VcmpsOpcode, Sd, Sn, Sm);
+}
+
+void AssemblerARM32::vcmpsz(const Operand *OpSd, CondARM32::Cond Cond) {
+ constexpr const char *Vcmpsz = "vcmps";
+ IValueT Sd = encodeSRegister(OpSd, "Sd", Vcmpsz);
+ constexpr IValueT VcmpszOpcode = B23 | B21 | B20 | B18 | B16 | B6;
+ constexpr IValueT Sn = 0;
+ constexpr IValueT Sm = 0;
+ emitVFPsss(Cond, VcmpszOpcode, Sd, Sn, Sm);
+}
+
void AssemblerARM32::emitVFPsd(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd,
IValueT Dm) {
assert(Sd < RegARM32::getNumSRegs());
void vadds(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
CondARM32::Cond Cond);
+ void vcmpd(const Operand *OpDd, const Operand *OpDm, CondARM32::Cond cond);
+
+ // Second argument of compare is zero (+0.0).
+ void vcmpdz(const Operand *OpDd, CondARM32::Cond cond);
+
+ void vcmps(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond cond);
+
+ // Second argument of compare is zero (+0.0).
+ void vcmpsz(const Operand *OpSd, 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);
getSrc(1)->emit(Func);
}
+void InstARM32Vcmp::emitIAS(const Cfg *Func) const {
+ assert(getSrcSize() == 2);
+ const Operand *Src0 = getSrc(0);
+ const Type Ty = Src0->getType();
+ const Operand *Src1 = getSrc(1);
+ const CondARM32::Cond Cond = getPredicate();
+ auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+ if (llvm::isa<OperandARM32FlexFpZero>(Src1)) {
+ switch (Ty) {
+ case IceType_f32:
+ Asm->vcmpsz(Src0, Cond);
+ break;
+ case IceType_f64:
+ Asm->vcmpdz(Src0, Cond);
+ break;
+ default:
+ llvm::report_fatal_error("Vcvt on non floating value");
+ }
+ } else {
+ switch (Ty) {
+ case IceType_f32:
+ Asm->vcmps(Src0, Src1, Cond);
+ break;
+ case IceType_f64:
+ Asm->vcmpd(Src0, Src1, Cond);
+ break;
+ default:
+ llvm::report_fatal_error("Vcvt on non floating value");
+ }
+ }
+ assert(!Asm->needsTextFixup());
+}
+
void InstARM32Vcmp::dump(const Cfg *Func) const {
if (!BuildDefs::dump())
return;
InstARM32Vcmp(Func, Src0, Src1, 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, Vcmp); }
--- /dev/null
+; Show that we know how to translate vcmp.
+
+; REQUIRES: allow_dump
+
+; TODO(kschimpf): Use include registers for compare instructions, so that the
+; test is less brittle.
+
+; 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 | 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 | FileCheck %s --check-prefix=DIS
+
+define internal i32 @vcmpFloat(float %v1, float %v2) {
+; ASM-LABEL: vcmpFloat:
+; DIS-LABEL: 00000000 <vcmpFloat>:
+; IASM-LABEL: vcmpFloat:
+
+entry:
+; ASM-NEXT: .LvcmpFloat$entry:
+; IASM-NEXT: .LvcmpFloat$entry:
+
+ %cmp = fcmp olt float %v1, %v2
+
+; ASM: vcmp.f32 s0, s1
+; DIS: 14: eeb40a60
+; IASM-NOT: vcmp
+
+ %res = zext i1 %cmp to i32
+ ret i32 %res
+}
+
+define internal i32 @vcmpFloatToZero(float %v) {
+; ASM-LABEL: vcmpFloatToZero:
+; DIS-LABEL: 00000040 <vcmpFloatToZero>:
+; IASM-LABEL: vcmpFloatToZero:
+
+entry:
+; ASM-NEXT: .LvcmpFloatToZero$entry:
+; IASM-NEXT: .LvcmpFloatToZero$entry:
+
+ %cmp = fcmp olt float %v, 0.0
+
+; ASM: vcmp.f32 s0, #0.0
+; DIS: 4c: eeb50a40
+; IASM-NOT: vcmp
+
+ %res = zext i1 %cmp to i32
+ ret i32 %res
+}
+
+define internal i32 @vcmpDouble(double %v1, double %v2) {
+; ASM-LABEL: vcmpDouble:
+; DIS-LABEL: 00000080 <vcmpDouble>:
+; IASM-LABEL: vcmpDouble:
+
+entry:
+; ASM-NEXT: .LvcmpDouble$entry:
+; IASM-NEXT: .LvcmpDouble$entry:
+
+ %cmp = fcmp olt double %v1, %v2
+
+; ASM: vcmp.f64 d31, d30
+; DIS: 94: eef4fb6e
+; IASM-NOT: vcmp
+
+ %res = zext i1 %cmp to i32
+ ret i32 %res
+}
+
+define internal i32 @vcmpDoubleToZero(double %v) {
+; ASM-LABEL: vcmpDoubleToZero:
+; DIS-LABEL: 000000c0 <vcmpDoubleToZero>:
+; IASM-LABEL: vcmpDoubleToZero:
+
+entry:
+; ASM-NEXT: .LvcmpDoubleToZero$entry:
+; IASM-NEXT: .LvcmpDoubleToZero$entry:
+
+ %cmp = fcmp olt double %v, 0.0
+
+; ASM: vcmp.f64 d31, #0.0
+; DIS: cc: eef5fb40
+; IASM-NOT: vcmp
+
+ %res = zext i1 %cmp to i32
+ ret i32 %res
+}