Commit dca86741 by Karl Schimpf

Add RSB instruction to the ARM integrated assembler.

Adds RSB (immediate) and RSB (register) to the ARM integrated assembler. Also moves udiv method to corresponding (sorted) position in cpp file. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1494433005 .
parent 7cfe9a0f
......@@ -202,17 +202,17 @@ void Assembler::eor(Register rd, Register rn, Operand o, Condition cond) {
void Assembler::sub(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), SUB, 0, rn, rd, o);
}
#endif
// Moved to ARM32::AssemberARM32::rsb()
void Assembler::rsb(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), RSB, 0, rn, rd, o);
}
// Moved to ARM32::AssemberARM32::rsb()
void Assembler::rsbs(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), RSB, 1, rn, rd, o);
}
#if 0
// Moved to ARM32::AssemberARM32::add()
void Assembler::add(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), ADD, 0, rn, rd, o);
......
......@@ -459,12 +459,11 @@ class Assembler : public ValueObject {
// Moved to ARM32::AssemberARM32::sub()
void sub(Register rd, Register rn, Operand o, Condition cond = AL);
void subs(Register rd, Register rn, Operand o, Condition cond = AL);
#endif
// Moved to ARM32::AssemberARM32::rsb()
void rsb(Register rd, Register rn, Operand o, Condition cond = AL);
void rsbs(Register rd, Register rn, Operand o, Condition cond = AL);
#if 0
// Moved to ARM32::AssemblerARM32::add()
void add(Register rd, Register rn, Operand o, Condition cond = AL);
......
......@@ -1477,23 +1477,24 @@ void AssemblerARM32::mul(const Operand *OpRd, const Operand *OpRn,
MulName);
}
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>
void AssemblerARM32::rsb(const Operand *OpRd, const Operand *OpRn,
const Operand *OpSrc1, bool SetFlags,
CondARM32::Cond Cond) {
// RSB (immediate) - ARM section A8.8.152, encoding A1.
// rsb{s}<c> <Rd>, <Rn>, #<RotatedImm8>
//
// cccc01110011dddd1111mmmm0001nnnn where cccc=Cond, dddd=Rd, nnnn=Rn, and
// mmmm=Rm.
constexpr const char *UdivName = "udiv";
IValueT Rd = encodeRegister(OpRd, "Rd", UdivName);
IValueT Rn = encodeRegister(OpRn, "Rn", UdivName);
IValueT Rm = encodeRegister(OpSrc1, "Rm", UdivName);
verifyRegNotPc(Rd, "Rd", UdivName);
verifyRegNotPc(Rn, "Rn", UdivName);
verifyRegNotPc(Rm, "Rm", UdivName);
// Assembler registers rd, rn, rm are encoded as rn, rm, rs.
constexpr IValueT UdivOpcode = B21;
emitDivOp(Cond, UdivOpcode, Rd, Rn, Rm, UdivName);
// cccc0010011snnnnddddiiiiiiiiiiii where cccc=Cond, dddd=Rd, nnnn=Rn,
// s=setFlags and iiiiiiiiiiii defines the RotatedImm8 value.
//
// RSB (register) - ARM section A8.8.163, encoding A1.
// rsb{s}<c> <Rd>, <Rn>, <Rm>{, <Shift>}
//
// cccc0000011snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
// mmmm=Rm, iiiii=shift, tt==ShiftKind, and s=SetFlags.
constexpr const char *RsbName = "rsb";
constexpr IValueT RsbOpcode = B1 | B0; // 0011
emitType01(Cond, RsbOpcode, OpRd, OpRn, OpSrc1, SetFlags, RdIsPcAndSetFlags,
RsbName);
}
void AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn,
......@@ -1505,7 +1506,7 @@ void AssemblerARM32::sub(const Operand *OpRd, const Operand *OpRn,
// sub{s}<c> <Rd>, sp, <Rm>{, <Shift>}
//
// cccc0000010snnnnddddiiiiitt0mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
// mmmm=Rm, iiiiii=shift, tt=ShiftKind, and s=SetFlags.
// mmmm=Rm, iiiii=shift, tt=ShiftKind, and s=SetFlags.
//
// Sub (Immediate) - ARM section A8.8.222, encoding A1:
// sub{s}<c> <Rd>, <Rn>, #<RotatedImm8>
......@@ -1538,6 +1539,25 @@ void AssemblerARM32::tst(const Operand *OpRn, const Operand *OpSrc1,
emitCompareOp(Cond, TstOpcode, OpRn, OpSrc1, TstName);
}
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.
constexpr const char *UdivName = "udiv";
IValueT Rd = encodeRegister(OpRd, "Rd", UdivName);
IValueT Rn = encodeRegister(OpRn, "Rn", UdivName);
IValueT Rm = encodeRegister(OpSrc1, "Rm", UdivName);
verifyRegNotPc(Rd, "Rd", UdivName);
verifyRegNotPc(Rn, "Rn", UdivName);
verifyRegNotPc(Rm, "Rm", UdivName);
// Assembler registers rd, rn, rm are encoded as rn, rm, rs.
constexpr IValueT UdivOpcode = B21;
emitDivOp(Cond, UdivOpcode, Rd, Rn, Rm, UdivName);
}
void AssemblerARM32::umull(const Operand *OpRdLo, const Operand *OpRdHi,
const Operand *OpRn, const Operand *OpRm,
CondARM32::Cond Cond) {
......
......@@ -249,6 +249,9 @@ public:
// Note: Registers is a bitset, where bit n corresponds to register Rn.
void pushList(const IValueT Registers, CondARM32::Cond Cond);
void rsb(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond);
void sbc(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond);
......
......@@ -506,6 +506,13 @@ template <> void InstARM32Mul::emitIAS(const Cfg *Func) const {
emitUsingTextFixup(Func);
}
template <> void InstARM32Rsb::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Asm->rsb(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
if (Asm->needsTextFixup())
emitUsingTextFixup(Func);
}
template <> void InstARM32Sbc::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Asm->sbc(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
......
; Show that we know how to translate rsb. Uses shl as example, because it
; uses rsb for type i64
; REQUIRES: allow_dump
; 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 i64 @shiftLeft(i64 %v, i64 %l) {
; ASM-LABEL:shiftLeft:
; DIS-LABEL:00000000 <shiftLeft>:
; IASM-LABEL:shiftLeft:
entry:
; ASM-NEXT:.LshiftLeft$entry:
; IASM-NEXT:.LshiftLeft$entry:
; ASM-NEXT: sub sp, sp, #24
; DIS-NEXT: 0: e24dd018
; IASM-NEXT: .byte 0x18
; IASM-NEXT: .byte 0xd0
; IASM-NEXT: .byte 0x4d
; IASM-NEXT: .byte 0xe2
; ASM-NEXT: str r0, [sp, #20]
; ASM-NEXT: # [sp, #20] = def.pseudo
; DIS-NEXT: 4: e58d0014
; IASM-NEXT: .byte 0x14
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: mov r0, r1
; DIS-NEXT: 8: e1a00001
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0xe1
; ASM-NEXT: str r0, [sp, #16]
; ASM-NEXT: # [sp, #16] = def.pseudo
; DIS-NEXT: c: e58d0010
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: mov r0, r2
; DIS-NEXT: 10: e1a00002
; IASM-NEXT: .byte 0x2
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0xe1
; ASM-NEXT: str r0, [sp, #12]
; ASM-NEXT: # [sp, #12] = def.pseudo
; DIS-NEXT: 14: e58d000c
; IASM-NEXT: .byte 0xc
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: mov r0, r3
; DIS-NEXT: 18: e1a00003
; IASM-NEXT: .byte 0x3
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0xe1
; ASM-NEXT: str r0, [sp, #8]
; ASM-NEXT: # [sp, #8] = def.pseudo
; DIS-NEXT: 1c: e58d0008
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
%result = shl i64 %v, %l
; ASM-NEXT: ldr r0, [sp, #20]
; DIS-NEXT: 20: e59d0014
; IASM-NEXT: .byte 0x14
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: ldr r1, [sp, #16]
; DIS-NEXT: 24: e59d1010
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; ASM-NEXT: ldr r2, [sp, #12]
; DIS-NEXT: 28: e59d200c
; IASM-NEXT: .byte 0xc
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; ****** Here is the example of rsb *****
; ASM-NEXT: rsb r3, r2, #32
; DIS-NEXT: 2c: e2623020
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x30
; IASM-NEXT: .byte 0x62
; IASM-NEXT: .byte 0xe2
ret i64 %result
}
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