Commit cd5e07ec by Karl Schimpf

Add VCMP{s,sz,d,dz} Instructions to ARM integrated assembler.

Also fixes bug in emitVFPddd. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1564393002 .
parent c411dbf1
...@@ -1153,26 +1153,27 @@ void Assembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) { ...@@ -1153,26 +1153,27 @@ void Assembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) {
EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm); 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) { void Assembler::vcmps(SRegister sd, SRegister sm, Condition cond) {
EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm); EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm);
} }
// Moved to ARM23::AssemblerARM32::vcmpd().
void Assembler::vcmpd(DRegister dd, DRegister dm, Condition cond) { void Assembler::vcmpd(DRegister dd, DRegister dm, Condition cond) {
EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm); EmitVFPddd(cond, B23 | B21 | B20 | B18 | B6, dd, D0, dm);
} }
// Moved to ARM23::AssemblerARM32::vcmpsz().
void Assembler::vcmpsz(SRegister sd, Condition cond) { void Assembler::vcmpsz(SRegister sd, Condition cond) {
EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0); EmitVFPsss(cond, B23 | B21 | B20 | B18 | B16 | B6, sd, S0, S0);
} }
// Moved to ARM23::AssemblerARM32::vcmpdz().
void Assembler::vcmpdz(DRegister dd, Condition cond) { void Assembler::vcmpdz(DRegister dd, Condition cond) {
EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0); EmitVFPddd(cond, B23 | B21 | B20 | B18 | B16 | B6, dd, D0, D0);
} }
#endif
void Assembler::vmrs(Register rd, Condition cond) { void Assembler::vmrs(Register rd, Condition cond) {
ASSERT(TargetCPUFeatures::vfp_supported()); ASSERT(TargetCPUFeatures::vfp_supported());
......
...@@ -729,10 +729,17 @@ class Assembler : public ValueObject { ...@@ -729,10 +729,17 @@ class Assembler : public ValueObject {
void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL); void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL);
void vcvtdu(DRegister dd, 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); void vcmps(SRegister sd, SRegister sm, Condition cond = AL);
// Moved to ARM23::AssemblerARM32::vcmpd().
void vcmpd(DRegister dd, DRegister dm, Condition cond = AL); void vcmpd(DRegister dd, DRegister dm, Condition cond = AL);
// Moved to ARM23::AssemblerARM32::vcmpsz().
void vcmpsz(SRegister sd, Condition cond = AL); void vcmpsz(SRegister sd, Condition cond = AL);
// Moved to ARM23::AssemblerARM32::vcmpdz().
void vcmpdz(DRegister dd, Condition cond = AL); void vcmpdz(DRegister dd, Condition cond = AL);
#endif
void vmrs(Register rd, Condition cond = AL); void vmrs(Register rd, Condition cond = AL);
void vmstat(Condition cond = AL); void vmstat(Condition cond = AL);
......
...@@ -1010,7 +1010,7 @@ void AssemblerARM32::emitVFPddd(CondARM32::Cond Cond, IValueT Opcode, ...@@ -1010,7 +1010,7 @@ void AssemblerARM32::emitVFPddd(CondARM32::Cond Cond, IValueT Opcode,
const IValueT Encoding = const IValueT Encoding =
Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) | Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) |
(getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) | (getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dn) << 16) |
(getXXXXInRegYXXXX(Dn) << 12) | (getYInRegYXXXX(Dn) << 7) | (getXXXXInRegYXXXX(Dd) << 12) | (getYInRegYXXXX(Dn) << 7) |
(getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm); (getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm);
emitInst(Encoding); emitInst(Encoding);
} }
...@@ -2071,6 +2071,44 @@ void AssemblerARM32::vaddd(const Operand *OpDd, const Operand *OpDn, ...@@ -2071,6 +2071,44 @@ void AssemblerARM32::vaddd(const Operand *OpDd, const Operand *OpDn,
emitVFPddd(Cond, VadddOpcode, Dd, Dn, Dm); 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, void AssemblerARM32::emitVFPsd(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd,
IValueT Dm) { IValueT Dm) {
assert(Sd < RegARM32::getNumSRegs()); assert(Sd < RegARM32::getNumSRegs());
......
...@@ -318,6 +318,16 @@ public: ...@@ -318,6 +318,16 @@ public:
void vadds(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm, void vadds(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
CondARM32::Cond Cond); 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 vcvtsd(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond);
void vcvtds(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond); void vcvtds(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond);
......
...@@ -1864,6 +1864,39 @@ void InstARM32Vcmp::emit(const Cfg *Func) const { ...@@ -1864,6 +1864,39 @@ void InstARM32Vcmp::emit(const Cfg *Func) const {
getSrc(1)->emit(Func); 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 { void InstARM32Vcmp::dump(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
......
...@@ -1362,6 +1362,7 @@ public: ...@@ -1362,6 +1362,7 @@ public:
InstARM32Vcmp(Func, Src0, Src1, Predicate); InstARM32Vcmp(Func, Src0, Src1, Predicate);
} }
void emit(const Cfg *Func) const override; void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override; void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Vcmp); } static bool classof(const Inst *Inst) { return isClassof(Inst, Vcmp); }
......
; 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
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment