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, ...@@ -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) { void Assembler::Lsl(Register rd, Register rm, Register rs, Condition cond) {
mov(rd, Operand(rm, LSL, rs), 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, void Assembler::Lsr(Register rd, Register rm, const Operand& shift_imm,
Condition cond) { Condition cond) {
ASSERT(shift_imm.type() == 1); ASSERT(shift_imm.type() == 1);
...@@ -2616,10 +2616,11 @@ void Assembler::Lsr(Register rd, Register rm, const Operand& shift_imm, ...@@ -2616,10 +2616,11 @@ void Assembler::Lsr(Register rd, Register rm, const Operand& shift_imm,
mov(rd, Operand(rm, LSR, shift), cond); mov(rd, Operand(rm, LSR, shift), cond);
} }
// Moved to ARM32::AssemblerARM32::lsr()
void Assembler::Lsr(Register rd, Register rm, Register rs, Condition cond) { void Assembler::Lsr(Register rd, Register rm, Register rs, Condition cond) {
mov(rd, Operand(rm, LSR, rs), cond); mov(rd, Operand(rm, LSR, rs), cond);
} }
#endif
void Assembler::Asr(Register rd, Register rm, const Operand& shift_imm, void Assembler::Asr(Register rd, Register rm, const Operand& shift_imm,
......
...@@ -964,10 +964,12 @@ class Assembler : public ValueObject { ...@@ -964,10 +964,12 @@ class Assembler : public ValueObject {
Condition cond = AL); Condition cond = AL);
// Moved to ARM32::AssemblerARM32::lsl() // Moved to ARM32::AssemblerARM32::lsl()
void Lsl(Register rd, Register rm, Register rs, Condition cond = AL); 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, void Lsr(Register rd, Register rm, const Operand& shift_imm,
Condition cond = AL); Condition cond = AL);
// Moved to ARM32::AssemblerARM32::lsr()
void Lsr(Register rd, Register rm, Register rs, Condition cond = AL); void Lsr(Register rd, Register rm, Register rs, Condition cond = AL);
#endif
void Asr(Register rd, Register rm, const Operand& shift_imm, void Asr(Register rd, Register rm, const Operand& shift_imm,
Condition cond = AL); Condition cond = AL);
void Asr(Register rd, Register rm, Register rs, 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, ...@@ -1122,50 +1122,63 @@ void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
} }
} }
void AssemblerARM32::lsl(const Operand *OpRd, const Operand *OpRm, void AssemblerARM32::emitShift(const CondARM32::Cond Cond,
const Operand *OpSrc1, bool SetFlags, const OperandARM32::ShiftKind Shift,
CondARM32::Cond Cond) { const Operand *OpRd, const Operand *OpRm,
constexpr const char *LslName = "lsl"; const Operand *OpSrc1, const bool SetFlags,
IValueT Rd = encodeRegister(OpRd, "Rd", LslName); const char *InstName) {
IValueT Rm = encodeRegister(OpRm, "Rm", LslName); constexpr IValueT ShiftOpcode = B3 | B2 | B0; // 1101
IValueT Rd = encodeRegister(OpRd, "Rd", InstName);
IValueT Rm = encodeRegister(OpRm, "Rm", InstName);
IValueT Value; IValueT Value;
switch (encodeOperand(OpSrc1, Value)) { switch (encodeOperand(OpSrc1, Value)) {
default: default:
llvm::report_fatal_error(std::string(LslName) + llvm::report_fatal_error(std::string(InstName) +
": Last operand not understood"); ": Last operand not understood");
case EncodedAsShiftImm5: { case EncodedAsShiftImm5: {
// LSL (immediate) - ARM section A8.8.94, encoding A1: // XXX (immediate)
// lsl{s}<c> <Rd>, <Rm>, #imm5 // xxx{s}<c> <Rd>, <Rm>, #imm5
// //
// cccc0001101s0000ddddiiiii000mmmm where cccc=Cond, s=SetFlags, dddd=Rd, // cccc0001101s0000ddddiiiii000mmmm where cccc=Cond, s=SetFlags, dddd=Rd,
// iiiii=imm5, and mmmm=Rm. // iiiii=imm5, and mmmm=Rm.
constexpr IValueT LslOpcode = B3 | B2 | B0; // 1101 constexpr IValueT Rn = 0; // Rn field is not used.
constexpr IValueT Rn = 0; // Rn field is not used. Value = Value | (Rm << kRmShift) | (Shift << kShiftShift);
Value = Value | (Rm << kRmShift); emitType01(Cond, kInstTypeDataRegShift, ShiftOpcode, SetFlags, Rn, Rd,
emitType01(Cond, kInstTypeDataRegShift, LslOpcode, SetFlags, Rn, Rd, Value, Value, RdIsPcAndSetFlags, InstName);
RdIsPcAndSetFlags, LslName);
return; return;
} }
case EncodedAsRegister: { case EncodedAsRegister: {
// LSL (register) - ARM section A8.8.95, encoding A1: // XXX (register)
// lsl{S}<c> <Rd>, <Rm>, <Rs> // xxx{S}<c> <Rd>, <Rm>, <Rs>
// //
// cccc0001101s0000ddddssss0001mmmm where cccc=Cond, s=SetFlags, dddd=Rd, // cccc0001101s0000ddddssss0001mmmm where cccc=Cond, s=SetFlags, dddd=Rd,
// mmmm=Rm, and ssss=Rs. // mmmm=Rm, and ssss=Rs.
constexpr IValueT LslOpcode = B3 | B2 | B0; // 1101 constexpr IValueT Rn = 0; // Rn field is not used.
constexpr IValueT Rn = 0; // Rn field is not used. IValueT Rs = encodeRegister(OpSrc1, "Rs", InstName);
IValueT Rs = encodeRegister(OpSrc1, "Rs", LslName); verifyRegNotPc(Rd, "Rd", InstName);
verifyRegNotPc(Rd, "Rd", LslName); verifyRegNotPc(Rm, "Rm", InstName);
verifyRegNotPc(Rm, "Rm", LslName); verifyRegNotPc(Rs, "Rs", InstName);
verifyRegNotPc(Rs, "Rs", LslName); emitType01(Cond, kInstTypeDataRegShift, ShiftOpcode, SetFlags, Rn, Rd,
emitType01(Cond, kInstTypeDataRegShift, LslOpcode, SetFlags, Rn, Rd, encodeShiftRotateReg(Rm, Shift, Rs), NoChecks, InstName);
encodeShiftRotateReg(Rm, OperandARM32::kNoShift, Rs), NoChecks,
LslName);
return; 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, void AssemblerARM32::mov(const Operand *OpRd, const Operand *OpSrc,
CondARM32::Cond Cond) { CondARM32::Cond Cond) {
// MOV (register) - ARM section A8.8.104, encoding A1: // MOV (register) - ARM section A8.8.104, encoding A1:
......
...@@ -222,6 +222,9 @@ public: ...@@ -222,6 +222,9 @@ public:
void lsl(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, void lsl(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond); 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 mov(const Operand *OpRd, const Operand *OpSrc, CondARM32::Cond Cond);
void movw(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: ...@@ -376,6 +379,14 @@ private:
void emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn, void emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd, IValueT Rn,
IValueT Rm, IValueT Rs, bool SetFlags, const char *InstName); 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 // Implements various forms of Unsigned extend value, using pattern
// ccccxxxxxxxxnnnnddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode, // ccccxxxxxxxxnnnnddddrr000111mmmm where cccc=Cond, xxxxxxxx<<20=Opcode,
// nnnn=Rn, dddd=Rd, rr=Rotation, and mmmm=Rm. // nnnn=Rn, dddd=Rd, rr=Rotation, and mmmm=Rm.
......
...@@ -492,6 +492,13 @@ template <> void InstARM32Lsl::emitIAS(const Cfg *Func) const { ...@@ -492,6 +492,13 @@ template <> void InstARM32Lsl::emitIAS(const Cfg *Func) const {
emitUsingTextFixup(Func); 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 { template <> void InstARM32Orr::emitIAS(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Asm->orr(getDest(), getSrc(0), getSrc(1), SetFlags, getPredicate()); 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