Commit 6c7181c5 by Karl Schimpf

Add vcvt<c>.f32.f64 and vcvt<c>.f64.32 to ARM.

Adds vcvt<c>.f32.f64 and vcvt<c>.f64.32 to the ARM integrated assembler. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1567623008 .
parent 426a21e1
...@@ -1069,7 +1069,8 @@ void Assembler::vsqrtd(DRegister dd, DRegister dm, Condition cond) { ...@@ -1069,7 +1069,8 @@ void Assembler::vsqrtd(DRegister dd, DRegister dm, Condition cond) {
EmitVFPddd(cond, B23 | B21 | B20 | B16 | B7 | B6, dd, D0, dm); EmitVFPddd(cond, B23 | B21 | B20 | B16 | B7 | B6, dd, D0, dm);
} }
#if 0
// Moved to ARM32::AssemblerARM32::emitVFPsd
void Assembler::EmitVFPsd(Condition cond, int32_t opcode, void Assembler::EmitVFPsd(Condition cond, int32_t opcode,
SRegister sd, DRegister dm) { SRegister sd, DRegister dm) {
ASSERT(TargetCPUFeatures::vfp_supported()); ASSERT(TargetCPUFeatures::vfp_supported());
...@@ -1085,7 +1086,7 @@ void Assembler::EmitVFPsd(Condition cond, int32_t opcode, ...@@ -1085,7 +1086,7 @@ void Assembler::EmitVFPsd(Condition cond, int32_t opcode,
Emit(encoding); Emit(encoding);
} }
// Moved to ARM32::AssemblerARM32::emitVFPds
void Assembler::EmitVFPds(Condition cond, int32_t opcode, void Assembler::EmitVFPds(Condition cond, int32_t opcode,
DRegister dd, SRegister sm) { DRegister dd, SRegister sm) {
ASSERT(TargetCPUFeatures::vfp_supported()); ASSERT(TargetCPUFeatures::vfp_supported());
...@@ -1101,15 +1102,16 @@ void Assembler::EmitVFPds(Condition cond, int32_t opcode, ...@@ -1101,15 +1102,16 @@ void Assembler::EmitVFPds(Condition cond, int32_t opcode,
Emit(encoding); Emit(encoding);
} }
// Moved to ARM32::AssemblerARM32::vcvtsd().
void Assembler::vcvtsd(SRegister sd, DRegister dm, Condition cond) { void Assembler::vcvtsd(SRegister sd, DRegister dm, Condition cond) {
EmitVFPsd(cond, B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6, sd, dm); EmitVFPsd(cond, B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6, sd, dm);
} }
// Moved to ARM32::AssemblerARM32::vcvtds().
void Assembler::vcvtds(DRegister dd, SRegister sm, Condition cond) { void Assembler::vcvtds(DRegister dd, SRegister sm, Condition cond) {
EmitVFPds(cond, B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6, dd, sm); EmitVFPds(cond, B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6, dd, sm);
} }
#endif
void Assembler::vcvtis(SRegister sd, SRegister sm, Condition cond) { void Assembler::vcvtis(SRegister sd, SRegister sm, Condition cond) {
......
...@@ -714,8 +714,12 @@ class Assembler : public ValueObject { ...@@ -714,8 +714,12 @@ class Assembler : public ValueObject {
void vsqrts(SRegister sd, SRegister sm, Condition cond = AL); void vsqrts(SRegister sd, SRegister sm, Condition cond = AL);
void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL); void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL);
#if 0
// Moved to ARM32::AssemblerARM32::vcvtsd
void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL); void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL);
// Moved to ARM32::AssemblerARM32:vcvtds
void vcvtds(DRegister dd, SRegister sm, Condition cond = AL); void vcvtds(DRegister dd, SRegister sm, Condition cond = AL);
#endif
void vcvtis(SRegister sd, SRegister sm, Condition cond = AL); void vcvtis(SRegister sd, SRegister sm, Condition cond = AL);
void vcvtid(SRegister sd, DRegister dm, Condition cond = AL); void vcvtid(SRegister sd, DRegister dm, Condition cond = AL);
void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL); void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL);
...@@ -1280,17 +1284,19 @@ class Assembler : public ValueObject { ...@@ -1280,17 +1284,19 @@ class Assembler : public ValueObject {
DRegister dd, DRegister dd,
DRegister dn, DRegister dn,
DRegister dm); DRegister dm);
#endif
// Moved to ARM32::AssemblerARM32::emitVFPsd
void EmitVFPsd(Condition cond, void EmitVFPsd(Condition cond,
int32_t opcode, int32_t opcode,
SRegister sd, SRegister sd,
DRegister dm); DRegister dm);
// Moved to ARM32::AssemblerARM32::emitVFPds
void EmitVFPds(Condition cond, void EmitVFPds(Condition cond,
int32_t opcode, int32_t opcode,
DRegister dd, DRegister dd,
SRegister sm); SRegister sm);
#endif
void EmitSIMDqqq(int32_t opcode, OperandSize sz, void EmitSIMDqqq(int32_t opcode, OperandSize sz,
QRegister qd, QRegister qn, QRegister qm); QRegister qd, QRegister qn, QRegister qm);
......
...@@ -2071,6 +2071,53 @@ void AssemblerARM32::vaddd(const Operand *OpDd, const Operand *OpDn, ...@@ -2071,6 +2071,53 @@ void AssemblerARM32::vaddd(const Operand *OpDd, const Operand *OpDn,
emitVFPddd(Cond, VadddOpcode, Dd, Dn, Dm); emitVFPddd(Cond, VadddOpcode, Dd, Dn, Dm);
} }
void AssemblerARM32::emitVFPsd(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd,
IValueT Dm) {
assert(Sd < RegARM32::getNumSRegs());
assert(Dm < RegARM32::getNumDRegs());
assert(CondARM32::isDefined(Cond));
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9;
const IValueT Encoding =
Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) |
(getYInRegXXXXY(Sd) << 22) | (getXXXXInRegXXXXY(Sd) << 12) |
(getYInRegYXXXX(Dm) << 5) | getXXXXInRegYXXXX(Dm);
emitInst(Encoding);
}
void AssemblerARM32::vcvtsd(const Operand *OpSd, const Operand *OpDm,
CondARM32::Cond Cond) {
constexpr const char *Vcvtsd = "vctsd";
IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtsd);
IValueT Dm = encodeDRegister(OpDm, "Dm", Vcvtsd);
constexpr IValueT VcvtsdOpcode =
B23 | B21 | B20 | B18 | B17 | B16 | B8 | B7 | B6;
emitVFPsd(Cond, VcvtsdOpcode, Sd, Dm);
}
void AssemblerARM32::emitVFPds(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd,
IValueT Sm) {
assert(Dd < RegARM32::getNumDRegs());
assert(Sm < RegARM32::getNumSRegs());
assert(CondARM32::isDefined(Cond));
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
constexpr IValueT VFPOpcode = B27 | B26 | B25 | B11 | B9;
const IValueT Encoding =
Opcode | VFPOpcode | (encodeCondition(Cond) << kConditionShift) |
(getYInRegYXXXX(Dd) << 22) | (getXXXXInRegYXXXX(Dd) << 12) |
(getYInRegXXXXY(Sm) << 5) | getXXXXInRegXXXXY(Sm);
emitInst(Encoding);
}
void AssemblerARM32::vcvtds(const Operand *OpDd, const Operand *OpSm,
CondARM32::Cond Cond) {
constexpr const char *Vcvtds = "Vctds";
IValueT Dd = encodeDRegister(OpDd, "Dd", Vcvtds);
IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtds);
constexpr IValueT VcvtdsOpcode = B23 | B21 | B20 | B18 | B17 | B16 | B7 | B6;
emitVFPds(Cond, VcvtdsOpcode, Dd, Sm);
}
void AssemblerARM32::vdivs(const Operand *OpSd, const Operand *OpSn, void AssemblerARM32::vdivs(const Operand *OpSd, const Operand *OpSn,
const Operand *OpSm, CondARM32::Cond Cond) { const Operand *OpSm, CondARM32::Cond Cond) {
// VDIV (floating-point) - ARM section A8.8.283, encoding A2: // VDIV (floating-point) - ARM section A8.8.283, encoding A2:
......
...@@ -324,6 +324,10 @@ public: ...@@ -324,6 +324,10 @@ 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 vcvtsd(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond);
void vcvtds(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond);
void vdivd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm, void vdivd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
CondARM32::Cond Cond); CondARM32::Cond Cond);
...@@ -448,6 +452,14 @@ private: ...@@ -448,6 +452,14 @@ private:
void emitVStackOp(CondARM32::Cond Cond, IValueT Opcode, void emitVStackOp(CondARM32::Cond Cond, IValueT Opcode,
const Variable *OpBaseReg, SizeT NumConsecRegs); const Variable *OpBaseReg, SizeT NumConsecRegs);
// Pattern cccc111xxDxxxxxxdddd101xxxMxmmmm where cccc=Cond, ddddD=Sd,
// Mmmmm=Dm, and xx0xxxxxxdddd000xxx0x0000=Opcode.
void emitVFPsd(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd, IValueT Dm);
// Pattern cccc111xxDxxxxxxdddd101xxxMxmmmm where cccc=Cond, Ddddd=Dd,
// mmmmM=Sm, and xx0xxxxxxdddd000xxx0x0000=Opcode.
void emitVFPds(CondARM32::Cond Cond, IValueT Opcode, IValueT Dd, IValueT Sm);
// Pattern cccc011100x1dddd1111mmmm0001nnn where cccc=Cond, // Pattern cccc011100x1dddd1111mmmm0001nnn where cccc=Cond,
// x=Opcode, dddd=Rd, nnnn=Rn, mmmm=Rm. // x=Opcode, dddd=Rd, nnnn=Rn, mmmm=Rm.
void emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn, void emitDivOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn,
......
...@@ -1882,6 +1882,24 @@ void InstARM32Vcvt::emit(const Cfg *Func) const { ...@@ -1882,6 +1882,24 @@ void InstARM32Vcvt::emit(const Cfg *Func) const {
getSrc(0)->emit(Func); getSrc(0)->emit(Func);
} }
void InstARM32Vcvt::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
switch (Variant) {
case S2d:
Asm->vcvtds(getDest(), getSrc(0), getPredicate());
break;
case D2s:
Asm->vcvtsd(getDest(), getSrc(0), getPredicate());
break;
default:
// TODO(kschimpf): Fill in other variants.
Asm->setNeedsTextFixup();
break;
}
if (Asm->needsTextFixup())
emitUsingTextFixup(Func);
}
void InstARM32Vcvt::dump(const Cfg *Func) const { void InstARM32Vcvt::dump(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
......
...@@ -1233,6 +1233,7 @@ public: ...@@ -1233,6 +1233,7 @@ public:
InstARM32Vcvt(Func, Dest, Src, Variant, Predicate); InstARM32Vcvt(Func, Dest, Src, Variant, 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, Vcvt); } static bool classof(const Inst *Inst) { return isClassof(Inst, Vcvt); }
......
; Show that we know how to translate vcvt between float and double.
; 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 double @testVcvtFloatToDouble(float %v) {
; ASM-LABEL: testVcvtFloatToDouble:
; DIS-LABEL: 00000000 <testVcvtFloatToDouble>:
; IASM-LABEL: testVcvtFloatToDouble:
entry:
; ASM-NEXT: .LtestVcvtFloatToDouble$entry:
; IASM-NEXT: .LtestVcvtFloatToDouble$entry:
%res = fpext float %v to double
; ASM-NEXT: vcvt.f64.f32 d0, s0
; DIS-NEXT: 0: eeb70ac0
; IASM-NEXT: .byte 0xc0
; IASM-NEXT: .byte 0xa
; IASM-NEXT: .byte 0xb7
; IASM-NEXT: .byte 0xee
ret double %res
}
define internal float @testVcvtDoubleToFloat(double %v) {
; ASM-LABEL: testVcvtDoubleToFloat:
; DIS-LABEL: 00000010 <testVcvtDoubleToFloat>:
; IASM-LABEL: testVcvtDoubleToFloat:
entry:
; ASM-NEXT: .LtestVcvtDoubleToFloat$entry:
; IASM-NEXT: .LtestVcvtDoubleToFloat$entry:
%res = fptrunc double %v to float
; ASM-NEXT: vcvt.f32.f64 s0, d0
; DIS-NEXT: 10: eeb70bc0
; IASM-NEXT: .byte 0xc0
; IASM-NEXT: .byte 0xb
; IASM-NEXT: .byte 0xb7
; IASM-NEXT: .byte 0xee
ret float %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