Commit b3e2574c by Karl Schimpf

Add VSUB{S,D} instructions to the integrated ARM assembler.

Also adds missing test case for the VADDD instruction. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1568623003 .
parent 4cba1cbb
......@@ -977,19 +977,19 @@ void Assembler::vaddd(DRegister dd, DRegister dn, DRegister dm,
Condition cond) {
EmitVFPddd(cond, B21 | B20, dd, dn, dm);
}
#endif
// Moved to Arm32::AssemblerARM32::vmuls()
void Assembler::vsubs(SRegister sd, SRegister sn, SRegister sm,
Condition cond) {
EmitVFPsss(cond, B21 | B20 | B6, sd, sn, sm);
}
// Moved to Arm32::AssemblerARM32::vmuld()
void Assembler::vsubd(DRegister dd, DRegister dn, DRegister dm,
Condition cond) {
EmitVFPddd(cond, B21 | B20 | B6, dd, dn, dm);
}
#endif
void Assembler::vmuls(SRegister sd, SRegister sn, SRegister sm,
Condition cond) {
......
......@@ -655,8 +655,12 @@ class Assembler : public ValueObject {
#endif
void vaddqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
void vaddqs(QRegister qd, QRegister qn, QRegister qm);
#if 0
// Moved to Arm32::AssemblerARM32::vsubs()
void vsubs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
// Moved to Arm32::AssemblerARM32::vsubd()
void vsubd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
#endif
void vsubqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
void vsubqs(QRegister qd, QRegister qn, QRegister qm);
void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
......
......@@ -2071,6 +2071,36 @@ void AssemblerARM32::vaddd(const Operand *OpDd, const Operand *OpDn,
emitVFPddd(Cond, VadddOpcode, Dd, Dn, Dm);
}
void AssemblerARM32::vsubs(const Operand *OpSd, const Operand *OpSn,
const Operand *OpSm, CondARM32::Cond Cond) {
// VSUB (floating-point) - ARM section A8.8.415, encoding A2:
// vsub<c>.f32 <Sd>, <Sn>, <Sm>
//
// cccc11100D11nnnndddd101sN1M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn,
// and mmmmM=Rm.
constexpr const char *Vadds = "vsubs";
IValueT Sd = encodeSRegister(OpSd, "Sd", Vadds);
IValueT Sn = encodeSRegister(OpSn, "Sn", Vadds);
IValueT Sm = encodeSRegister(OpSm, "Sm", Vadds);
constexpr IValueT VaddsOpcode = B21 | B20 | B6;
emitVFPsss(Cond, VaddsOpcode, Sd, Sn, Sm);
}
void AssemblerARM32::vsubd(const Operand *OpDd, const Operand *OpDn,
const Operand *OpDm, CondARM32::Cond Cond) {
// VSUB (floating-point) - ARM section A8.8.415, encoding A2:
// vadd<c>.f64 <Dd>, <Dn>, <Dm>
//
// cccc11100D11nnnndddd101sN1M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn,
// and Mmmmm=Rm.
constexpr const char *Vaddd = "vsubd";
IValueT Dd = encodeDRegister(OpDd, "Dd", Vaddd);
IValueT Dn = encodeDRegister(OpDn, "Dn", Vaddd);
IValueT Dm = encodeDRegister(OpDm, "Dm", Vaddd);
constexpr IValueT VadddOpcode = B21 | B20 | B6;
emitVFPddd(Cond, VadddOpcode, Dd, Dn, Dm);
}
void AssemblerARM32::emitVStackOp(CondARM32::Cond Cond, IValueT Opcode,
const Variable *OpBaseReg,
SizeT NumConsecRegs) {
......
......@@ -330,6 +330,12 @@ public:
void vpush(const Variable *OpBaseReg, SizeT NumConsecRegs,
CondARM32::Cond Cond);
void vsubd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
CondARM32::Cond Cond);
void vsubs(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
CondARM32::Cond Cond);
static bool classof(const Assembler *Asm) {
return Asm->getKind() == Asm_ARM32;
}
......
......@@ -612,8 +612,25 @@ template <> void InstARM32Vadd::emitIAS(const Cfg *Func) const {
Asm->vaddd(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
break;
}
if (Asm->needsTextFixup())
emitUsingTextFixup(Func);
assert(!Asm->needsTextFixup());
}
template <> void InstARM32Vsub::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
const Variable *Dest = getDest();
switch (Dest->getType()) {
default:
// TODO(kschimpf) Figure if more cases are needed.
Asm->setNeedsTextFixup();
break;
case IceType_f32:
Asm->vsubs(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
break;
case IceType_f64:
Asm->vsubd(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
break;
}
assert(!Asm->needsTextFixup());
}
InstARM32Call::InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
......
......@@ -20,14 +20,14 @@
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -O2 | FileCheck %s --check-prefix=DIS
define internal float @testVadd(float %v1, float %v2) {
; ASM-LABEL: testVadd:
; DIS-LABEL: 00000000 <testVadd>:
; IASM-LABEL: testVadd:
define internal float @testVaddFloat(float %v1, float %v2) {
; ASM-LABEL: testVaddFloat:
; DIS-LABEL: 00000000 <testVaddFloat>:
; IASM-LABEL: testVaddFloat:
entry:
; ASM-NEXT: .LtestVadd$entry:
; IASM-NEXT: .LtestVadd$entry:
; ASM-NEXT: .LtestVaddFloat$entry:
; IASM-NEXT: .LtestVaddFloat$entry:
%res = fadd float %v1, %v2
......@@ -40,3 +40,24 @@ entry:
ret float %res
}
define internal double @testVaddDouble(double %v1, double %v2) {
; ASM-LABEL: testVaddDouble:
; DIS-LABEL: 00000010 <testVaddDouble>:
; IASM-LABEL: testVaddDouble:
entry:
; ASM-NEXT: .LtestVaddDouble$entry:
; IASM-NEXT: .LtestVaddDouble$entry:
%res = fadd double %v1, %v2
; ASM-NEXT: vadd.f64 d0, d0, d1
; DIS-NEXT: 10: ee300b01
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0xb
; IASM-NEXT: .byte 0x30
; IASM-NEXT: .byte 0xee
ret double %res
}
; Show that we know how to translate vsub.
; 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 float @testVsubFloat(float %v1, float %v2) {
; ASM-LABEL: testVsubFloat:
; DIS-LABEL: 00000000 <testVsubFloat>:
; IASM-LABEL: testVsubFloat:
entry:
; ASM-NEXT: .LtestVsubFloat$entry:
; IASM-NEXT: .LtestVsubFloat$entry:
%res = fsub float %v1, %v2
; ASM-NEXT: vsub.f32 s0, s0, s1
; DIS-NEXT: 0: ee300a60
; IASM-NEXT: .byte 0x60
; IASM-NEXT: .byte 0xa
; IASM-NEXT: .byte 0x30
; IASM-NEXT: .byte 0xee
ret float %res
}
define internal double @testVsubDouble(double %v1, double %v2) {
; ASM-LABEL: testVsubDouble:
; DIS-LABEL: 00000010 <testVsubDouble>:
; IASM-LABEL: testVsubDouble:
entry:
; ASM-NEXT: .LtestVsubDouble$entry:
; IASM-NEXT: .LtestVsubDouble$entry:
%res = fsub double %v1, %v2
; ASM-NEXT: vsub.f64 d0, d0, d1
; DIS-NEXT: 10: ee300b41
; IASM-NEXT: .byte 0x41
; IASM-NEXT: .byte 0xb
; IASM-NEXT: .byte 0x30
; IASM-NEXT: .byte 0xee
ret double %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