Commit 1c28550f by Karl Schimpf

Add UDIV to ARM integrated assembler.

parent 955bfdc7
......@@ -469,14 +469,12 @@ void Assembler::EmitDivOp(Condition cond, int32_t opcode,
void Assembler::sdiv(Register rd, Register rn, Register rm, Condition cond) {
EmitDivOp(cond, 0, rd, rn, rm);
}
#endif
// Moved to ARM32::AssemblerARM32::udiv()
void Assembler::udiv(Register rd, Register rn, Register rm, Condition cond) {
EmitDivOp(cond, B21 , rd, rn, rm);
}
#if 0
// Moved to ARM32::AssemblerARM32::ldr()
void Assembler::ldr(Register rd, Address ad, Condition cond) {
EmitMemOp(cond, true, false, rd, ad);
......
......@@ -529,10 +529,9 @@ class Assembler : public ValueObject {
#if 0
// Moved to ARM32::AssemblerARM32::sdiv()
void sdiv(Register rd, Register rn, Register rm, Condition cond = AL);
#endif
// Moved to ARM32::AssemblerARM32::udiv()
void udiv(Register rd, Register rn, Register rm, Condition cond = AL);
#if 0
// Moved to ARM32::AssemblerARM32::ldr()
// Load/store instructions.
void ldr(Register rd, Address ad, Condition cond = AL);
......
......@@ -844,6 +844,30 @@ void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn,
emitMulOp(Cond, MulOpcode, RegARM32::Encoded_Reg_r0, Rd, Rn, Rm, SetFlags);
}
void AssemblerARM32::udiv(const Operand *OpRd, const Operand *OpRn,
const Operand *OpSrc1, CondARM32::Cond Cond) {
// UDIV - ARM section A8.8.248, encoding A1.
// udiv<c> <Rd>, <Rn>, <Rm>
//
// cccc01110011dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and
// mmmm=Rm.
IValueT Rd;
if (decodeOperand(OpRd, Rd) != DecodedAsRegister)
return setNeedsTextFixup();
IValueT Rn;
if (decodeOperand(OpRn, Rn) != DecodedAsRegister)
return setNeedsTextFixup();
IValueT Rm;
if (decodeOperand(OpSrc1, Rm) != DecodedAsRegister)
return setNeedsTextFixup();
if (Rd == RegARM32::Encoded_Reg_pc || Rn == RegARM32::Encoded_Reg_pc ||
Rm == RegARM32::Encoded_Reg_pc)
llvm::report_fatal_error("Sdiv instruction unpredictable on pc");
// Assembler registers rd, rn, rm are encoded as rn, rm, rs.
constexpr IValueT Opcode = B21;
emitDivOp(Cond, Opcode, Rd, Rn, Rm);
}
void AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn,
const Operand *OpSrc1, bool SetFlags,
CondARM32::Cond Cond) {
......
......@@ -178,6 +178,9 @@ public:
void sub(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond);
void udiv(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
CondARM32::Cond Cond);
static bool classof(const Assembler *Asm) {
return Asm->getKind() == Asm_ARM32;
}
......
......@@ -408,6 +408,14 @@ template <> void InstARM32Sub::emitIAS(const Cfg *Func) const {
emitUsingTextFixup(Func);
}
template <> void InstARM32Udiv::emitIAS(const Cfg *Func) const {
assert(!SetFlags);
ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Asm->udiv(getDest(), getSrc(0), getSrc(1), getPredicate());
if (Asm->needsTextFixup())
emitUsingTextFixup(Func);
}
InstARM32Call::InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
: InstARM32(Func, InstARM32::Call, 1, Dest) {
HasSideEffects = true;
......
; Show that we know how to translate udiv
; 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 -mattr=hwdiv-arm \
; 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 -mattr=hwdiv-arm | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -O2 -mattr=hwdiv-arm \
; 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 -mattr=hwdiv-arm | FileCheck %s --check-prefix=DIS
define internal i32 @UdivTwoRegs(i32 %a, i32 %b) {
%v = udiv i32 %a, %b
ret i32 %v
}
; ASM-LABEL:UdivTwoRegs:
; ASM-NEXT:.LUdivTwoRegs$__0:
; ASM-NEXT: tst r1, r1
; ASM-NEXT: bne .LUdivTwoRegs$local$__0
; ASM-NEXT: .long 0xe7fedef0
; ASM-NEXT:.LUdivTwoRegs$local$__0:
; ASM-NEXT: udiv r0, r0, r1
; ASM-NEXT: bx lr
; DIS-LABEL:00000000 <UdivTwoRegs>:
; DIS-NEXT: 0: e1110001
; DIS-NEXT: 4: 1a000000
; DIS-NEXT: 8: e7fedef0
; DIS-NEXT: c: e730f110
; DIS-NEXT: 10: e12fff1e
; IASM-LABEL:UdivTwoRegs:
; IASM-NEXT:.LUdivTwoRegs$__0:
; IASM-NEXT: tst r1, r1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x1a
; IASM-NEXT: .long 0xe7fedef0
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0xf1
; IASM-NEXT: .byte 0x30
; IASM-NEXT: .byte 0xe7
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
; IASM-NEXT: .byte 0xe1
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