Commit 4ddce702 by Karl Schimpf

Implement LSR instructions for the integrated ARM assembler.

Also factors out the body of method lsl() to emitShift(), so that all forms of shift instructions can use the same code. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1501073002 .
parent d880f0e2
......@@ -2603,8 +2603,8 @@ void Assembler::Lsl(Register rd, Register rm, const Operand& shift_imm,
void Assembler::Lsl(Register rd, Register rm, Register rs, Condition cond) {
mov(rd, Operand(rm, LSL, rs), cond);
}
#endif
// Moved to ARM32::AssemblerARM32::lsr()
void Assembler::Lsr(Register rd, Register rm, const Operand& shift_imm,
Condition cond) {
ASSERT(shift_imm.type() == 1);
......@@ -2616,10 +2616,11 @@ void Assembler::Lsr(Register rd, Register rm, const Operand& shift_imm,
mov(rd, Operand(rm, LSR, shift), cond);
}
// Moved to ARM32::AssemblerARM32::lsr()
void Assembler::Lsr(Register rd, Register rm, Register rs, Condition cond) {
mov(rd, Operand(rm, LSR, rs), cond);
}
#endif
void Assembler::Asr(Register rd, Register rm, const Operand& shift_imm,
......
......@@ -964,10 +964,12 @@ class Assembler : public ValueObject {
Condition cond = AL);
// Moved to ARM32::AssemblerARM32::lsl()
void Lsl(Register rd, Register rm, Register rs, Condition cond = AL);
#endif
// Moved to ARM32::AssemblerARM32::lsr()
void Lsr(Register rd, Register rm, const Operand& shift_imm,
Condition cond = AL);
// Moved to ARM32::AssemblerARM32::lsr()
void Lsr(Register rd, Register rm, Register rs, Condition cond = AL);
#endif
void Asr(Register rd, Register rm, const Operand& shift_imm,
Condition cond = AL);
void Asr(Register rd, Register rm, Register rs, Condition cond = AL);
......
......@@ -1122,50 +1122,63 @@ void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
}
}
void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm,
const Operand *OpSrc1, bool SetFlags,
CondARM32::Cond Cond) {
constexpr const char *LslName = "lsl";
IValueT Rd = encodeRegister(OpRd, "Rd", LslName);
IValueT Rm = encodeRegister(OpRm, "Rm", LslName);
void AssemblerARM32::emitShift(const CondARM32::Cond Cond,
const OperandARM32::ShiftKind Shift,
const Operand *OpRd, const Operand *OpRm,
const Operand *OpSrc1, const bool SetFlags,
const char *InstName) {
constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101
IValueT Rd = encodeRegister(OpRd, "Rd", InstName);
IValueT Rm = encodeRegister(OpRm, "Rm", InstName);
IValueT Value;
switch (encodeOperand(OpSrc1, Value)) {
default:
llvm::report_fatal_error(std::string(LslName) +
llvm::report_fatal_error(std::string(InstName) +
": Last operand not understood");
case EncodedAsShiftImm5: {
// LSL (immediate) - ARM section A8.8.94, encoding A1:
// lsl{s}<c> <Rd>, <Rm>, #imm5
// XXX (immediate)
// xxx{s}<c> <Rd>, <Rm>, #imm5
//
// cccc0001101s0000ddddiiiii000mmmm where cccc=Cond, s=SetFlags, dddd=Rd,
// iiiii=imm5, and mmmm=Rm.
constexpr IValueT LslOpcode = B3 | B2 | B0; // 1101
constexpr IValueT Rn = 0; // Rn field is not used.
Value = Value | (Rm << kRmShift);
emitType01(Cond, kInstTypeDataRegShift, LslOpcode, SetFlags, Rn, Rd, Value,
RdIsPcAndSetFlags, LslName);
Value = Value | (Rm << kRmShift) | (Shift << kShiftShift);
emitType01(Cond, kInstTypeDataRegShift, ShiftOpcode, SetFlags, Rn, Rd,
Value, RdIsPcAndSetFlags, InstName);
return;
}
case EncodedAsRegister: {
// LSL (register) - ARM section A8.8.95, encoding A1:
// lsl{S}<c> <Rd>, <Rm>, <Rs>
// XXX (register)
// xxx{S}<c> <Rd>, <Rm>, <Rs>
//
// cccc0001101s0000ddddssss0001mmmm where cccc=Cond, s=SetFlags, dddd=Rd,
// mmmm=Rm, and ssss=Rs.
constexpr IValueT LslOpcode = B3 | B2 | B0; // 1101
constexpr IValueT Rn = 0; // Rn field is not used.
IValueT Rs = encodeRegister(OpSrc1, "Rs", LslName);
verifyRegNotPc(Rd, "Rd", LslName);
verifyRegNotPc(Rm, "Rm", LslName);
verifyRegNotPc(Rs, "Rs", LslName);
emitType01(Cond, kInstTypeDataRegShift, LslOpcode, SetFlags, Rn, Rd,
encodeShiftRotateReg(Rm, OperandARM32::kNoShift, Rs), NoChecks,
LslName);
IValueT Rs = encodeRegister(OpSrc1, "Rs", InstName);
verifyRegNotPc(Rd, "Rd", InstName);
verifyRegNotPc(Rm, "Rm", InstName);
verifyRegNotPc(Rs, "Rs", InstName);
emitType01(Cond, kInstTypeDataRegShift, ShiftOpcode, SetFlags, Rn, Rd,
encodeShiftRotateReg(Rm, Shift, Rs), NoChecks, InstName);
return;
}
}
}
void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm,
const Operand *OpSrc1, bool SetFlags,
CondARM32::Cond Cond) {
constexpr const char *LslName = "lsl";
emitShift(Cond, OperandARM32::LSL, OpRd, OpRm, OpSrc1, SetFlags, LslName);
}
void AssemblerARM32::lsr(const Operand *OpRd, const Operand *OpRm,
const Operand *OpSrc1, bool SetFlags,
CondARM32::Cond Cond) {
constexpr const char *LsrName = "lsr";
emitShift(Cond, OperandARM32::LSR, OpRd, OpRm, OpSrc1, SetFlags, LsrName);
}
void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc,
CondARM32::Cond Cond) {
// MOV (register) - ARM section A8.8.104, encoding A1:
......
......@@ -222,6 +222,9 @@ public:
void lsl(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond);
void lsr(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);
......@@ -376,6 +379,14 @@ private:
void emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn,
IValueT Rm, IValueT Rs, bool SetFlags, const char *InstName);
// Pattern cccc0001101s0000ddddxxxxxtt0mmmm where cccc=Cond, s=SetFlags,
// dddd=Rd, mmmm=Rm, tt=Shift, and xxxxx is defined by OpSrc1. OpSrc1 defines
// either xxxxx=Imm5, or xxxxx=ssss0 where ssss=Rs.
void emitShift(const CondARM32::Cond Cond,
const OperandARM32::ShiftKind Shift, const Operand *OpRd,
const Operand *OpRm, const Operand *OpSrc1,
const bool SetFlags, const char *InstName);
// Implements various forms of Unsigned extend value, using pattern
// ccccxxxxxxxxnnnnddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode,
// nnnn=Rn, dddd=Rd, rr=Rotation, and mmmm=Rm.
......
......@@ -492,6 +492,13 @@ template <> void InstARM32Lsl::emitIAS(const Cfg *Func) const {
emitUsingTextFixup(Func);
}
template <> void InstARM32Lsr::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Asm->lsr(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 lsr.
; 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 @LshrAmt(i32 %a) {
; ASM-LABEL:LshrAmt:
; DIS-LABEL:00000000 <LshrAmt>:
; IASM-LABEL:LshrAmt:
entry:
; ASM-NEXT:.LLshrAmt$entry:
; IASM-NEXT:.LLshrAmt$entry:
%v = lshr i32 %a, 23
; ASM-NEXT: lsr r0, r0, #23
; DIS-NEXT: 0: e1a00ba0
; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0xb
; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0xe1
ret i32 %v
}
define internal i32 @LshrReg(i32 %a, i32 %b) {
; ASM-LABEL:LshrReg:
; DIS-LABEL:00000010 <LshrReg>:
; IASM-LABEL:LshrReg:
entry:
; ASM-NEXT:.LLshrReg$entry:
; IASM-NEXT:.LLshrReg$entry:
%v = lshr i32 %a, %b
; ASM-NEXT: lsr r0, r0, r1
; DIS-NEXT: 10: e1a00130
; IASM-NEXT: .byte 0x30
; IASM-NEXT: .byte 0x1
; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0xe1
ret i32 %v
}
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