Commit f4d0a7a5 by Karl Schimpf

Add LSL (register, immediate) to ARM integrated assembler.

Also does some clean up on emitType01 methods (making optional argument explicit, and moving rule checks to the lowest level). BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=jpp@chromium.org Review URL: https://codereview.chromium.org/1456783003 .
parent 3f6b47d5
......@@ -2596,7 +2596,8 @@ void Assembler::MoveRegister(Register rd, Register rm, Condition cond) {
}
}
#if 0
// Moved to ARM32::AssemblerARM32::lsl()
void Assembler::Lsl(Register rd, Register rm, const Operand& shift_imm,
Condition cond) {
ASSERT(shift_imm.type() == 1);
......@@ -2604,10 +2605,11 @@ void Assembler::Lsl(Register rd, Register rm, const Operand& shift_imm,
mov(rd, Operand(rm, LSL, shift_imm.encoding()), cond);
}
// Moved to ARM32::AssemblerARM32::lsl()
void Assembler::Lsl(Register rd, Register rm, Register rs, Condition cond) {
mov(rd, Operand(rm, LSL, rs), cond);
}
#endif
void Assembler::Lsr(Register rd, Register rm, const Operand& shift_imm,
......
......@@ -158,7 +158,7 @@ class Operand : public ValueObject {
encoding_ = static_cast<uint32_t>(rm);
}
// Moved to encodeShiftRotateImm5()
// Moved to encodeShiftRotateImm5() in IceAssemblerARM32.cpp
// Data-processing operands - Logical shift/rotate by immediate.
Operand(Register rm, Shift shift, uint32_t shift_imm) {
ASSERT(shift_imm < (1 << kShiftImmBits));
......@@ -167,8 +167,8 @@ class Operand : public ValueObject {
static_cast<uint32_t>(shift) << kShiftShift |
static_cast<uint32_t>(rm);
}
#endif
// Moved to encodeShiftRotateReg() in IceAssemblerARM32.cpp
// Data-processing operands - Logical shift/rotate by register.
Operand(Register rm, Shift shift, Register rs) {
type_ = 0;
......@@ -177,7 +177,6 @@ class Operand : public ValueObject {
static_cast<uint32_t>(rm);
}
#if 0
// Already defined as ARM32::OperandARM32FlexImm::canHoldImm().
static bool CanHold(uint32_t immediate, Operand* o) {
// Avoid the more expensive test for frequent small immediate values.
......@@ -956,9 +955,13 @@ class Assembler : public ValueObject {
// Convenience shift instructions. Use mov instruction with shifter operand
// for variants setting the status flags.
#if 0
// Moved to ARM32::AssemblerARM32::lsl()
void Lsl(Register rd, Register rm, const Operand& shift_imm,
Condition cond = AL);
// Moved to ARM32::AssemblerARM32::lsl()
void Lsl(Register rd, Register rm, Register rs, Condition cond = AL);
#endif
void Lsr(Register rd, Register rm, const Operand& shift_imm,
Condition cond = AL);
void Lsr(Register rd, Register rm, Register rs, Condition cond = AL);
......
......@@ -223,6 +223,9 @@ public:
ldr(OpRt, OpAddress, Cond, TInfo);
}
void lsl(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond);
void mov(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
void movw(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
......@@ -312,28 +315,27 @@ private:
void emitInst(IValueT Value) { Buffer.emit<IValueT>(Value); }
// List of possible checks to apply when calling emitType01() (below).
enum EmitChecks { NoChecks, RdIsPcAndSetFlags };
// Pattern cccctttoooosnnnnddddiiiiiiiiiiii where cccc=Cond, ttt=Type,
// oooo=Opcode, nnnn=Rn, dddd=Rd, iiiiiiiiiiii=imm12 (See ARM section A5.2.3).
// s=SetFlags, oooo=Opcode, nnnn=Rn, dddd=Rd, iiiiiiiiiiii=imm12 (See ARM
// section A5.2.3).
void emitType01(CondARM32::Cond Cond, IValueT Type, IValueT Opcode,
bool SetCc, IValueT Rn, IValueT Rd, IValueT imm12);
// List of possible checks to apply when calling emitType01() (below).
enum Type01Checks {
NoChecks,
RdIsPcAndSetFlags,
};
bool SetFlags, IValueT Rn, IValueT Rd, IValueT imm12,
EmitChecks RuleChecks);
// Converts appropriate representation on a data operation, and then calls
// emitType01 above.
void emitType01(IValueT Opcode, const Operand *OpRd, const Operand *OpRn,
const Operand *OpSrc1, bool SetFlags, CondARM32::Cond Cond,
Type01Checks RuleChecks = RdIsPcAndSetFlags);
EmitChecks RuleChecks);
// Same as above, but the value for Rd and Rn have already been converted
// into instruction values.
void emitType01(IValueT Opcode, IValueT OpRd, IValueT OpRn,
const Operand *OpSrc1, bool SetFlags, CondARM32::Cond Cond,
Type01Checks RuleChecks = RdIsPcAndSetFlags);
EmitChecks RuleChecks);
void emitType05(CondARM32::Cond COnd, int32_t Offset, bool Link);
......@@ -356,9 +358,9 @@ private:
IValueT Rm);
// Pattern ccccxxxxxxxfnnnnddddssss1001mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,
// mmmm=Rm, ssss=Rs, f=SetCc, and xxxxxxx=Opcode.
// mmmm=Rm, ssss=Rs, f=SetFlags and xxxxxxx=Opcode.
void emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn,
IValueT Rm, IValueT Rs, bool SetCc);
IValueT Rm, IValueT Rs, bool SetFlags);
// Implements various forms of Unsigned extend value, using pattern
// ccccxxxxxxxxnnnnddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode,
......
......@@ -485,6 +485,13 @@ template <> void InstARM32Eor::emitIAS(const Cfg *Func) const {
emitUsingTextFixup(Func);
}
template <> void InstARM32Lsl::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Asm->lsl(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
if (Asm->needsTextFixup())
emitUsingTextFixup(Func);
}
template <> void InstARM32Orr::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Asm->orr(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate());
......
; Show that we know how to translate lsl.
; 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 i32 @_Z8testUdivhh(i32 %a, i32 %b) {
; ASM-LABEL:_Z8testUdivhh:
; DIS-LABEL:00000000 <_Z8testUdivhh>:
; IASM-LABEL:_Z8testUdivhh:
entry:
; ASM-NEXT:.L_Z8testUdivhh$entry:
; ASM-NEXT: push {lr}
; DIS-NEXT: 0: e52de004
; IASM-NEXT:.L_Z8testUdivhh$entry:
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0xe0
; IASM-NEXT: .byte 0x2d
; IASM-NEXT: .byte 0xe5
%b.arg_trunc = trunc i32 %b to i8
%a.arg_trunc = trunc i32 %a to i8
%div3 = udiv i8 %a.arg_trunc, %b.arg_trunc
; ASM-NEXT: sub sp, sp, #12
; DIS-NEXT: 4: e24dd00c
; IASM-NEXT: .byte 0xc
; IASM-NEXT: .byte 0xd0
; IASM-NEXT: .byte 0x4d
; IASM-NEXT: .byte 0xe2
; ASM-NEXT: lsls r2, r1, #24
; DIS-NEXT: 8: e1b02c01
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0x2c
; IASM-NEXT: .byte 0xb0
; IASM-NEXT: .byte 0xe1
%div3.ret_ext = zext i8 %div3 to i32
ret i32 %div3.ret_ext
}
define internal i32 @_Z7testShljj(i32 %a, i32 %b) {
; ASM-LABEL:_Z7testShljj:
; DIS-LABEL:00000030 <_Z7testShljj>:
; IASM-LABEL:_Z7testShljj:
entry:
; ASM-NEXT:.L_Z7testShljj$entry:
; IASM-NEXT:.L_Z7testShljj$entry:
%shl = shl i32 %a, %b
; ASM-NEXT: lsl r0, r0, r1
; DIS-NEXT: 30: e1a00110
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0xe1
ret i32 %shl
}
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