Skip to content

Commit 0c97e76

Browse files
Tim NorthoverTim Northover
authored andcommitted
Fix the handling of edge cases in ARM shifted operands.
This patch fixes load/store instructions to handle less common cases like "asr #32", "rrx" properly throughout the MC layer. Patch by Chris Lidbury. llvm-svn: 164455
1 parent 6cba23a commit 0c97e76

File tree

6 files changed

+151
-8
lines changed

6 files changed

+151
-8
lines changed

llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4444,6 +4444,12 @@ bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
44444444
((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
44454445
((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
44464446
return Error(Loc, "immediate shift value out of range");
4447+
// If <ShiftTy> #0, turn it into a no_shift.
4448+
if (Imm == 0)
4449+
St = ARM_AM::lsl;
4450+
// For consistency, treat lsr #32 and asr #32 as having immediate value 0.
4451+
if (Imm == 32)
4452+
Imm = 0;
44474453
Amount = Imm;
44484454
}
44494455

llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,6 +1523,8 @@ DecodeAddrMode2IdxInstruction(MCInst &Inst, unsigned Insn,
15231523
return MCDisassembler::Fail;
15241524
}
15251525
unsigned amt = fieldFromInstruction(Insn, 7, 5);
1526+
if (Opc == ARM_AM::ror && amt == 0)
1527+
Opc = ARM_AM::rrx;
15261528
unsigned imm = ARM_AM::getAM2Opc(Op, amt, Opc, idx_mode);
15271529

15281530
Inst.addOperand(MCOperand::CreateImm(imm));
@@ -1564,6 +1566,9 @@ static DecodeStatus DecodeSORegMemOperand(MCInst &Inst, unsigned Val,
15641566
break;
15651567
}
15661568

1569+
if (ShOp == ARM_AM::ror && imm == 0)
1570+
ShOp = ARM_AM::rrx;
1571+
15671572
if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder)))
15681573
return MCDisassembler::Fail;
15691574
if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))

llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,27 @@ using namespace llvm;
2929
///
3030
/// getSORegOffset returns an integer from 0-31, representing '32' as 0.
3131
static unsigned translateShiftImm(unsigned imm) {
32+
// lsr #32 and asr #32 exist, but should be encoded as a 0.
33+
assert((imm & ~0x1f) == 0 && "Invalid shift encoding");
34+
3235
if (imm == 0)
3336
return 32;
3437
return imm;
3538
}
3639

40+
/// Prints the shift value with an immediate value.
41+
static void printRegImmShift(raw_ostream &O, ARM_AM::ShiftOpc ShOpc,
42+
unsigned ShImm) {
43+
if (ShOpc == ARM_AM::no_shift || (ShOpc == ARM_AM::lsl && !ShImm))
44+
return;
45+
O << ", ";
46+
47+
assert (!(ShOpc == ARM_AM::ror && !ShImm) && "Cannot have ror #0");
48+
O << getShiftOpcStr(ShOpc);
49+
50+
if (ShOpc != ARM_AM::rrx)
51+
O << " #" << translateShiftImm(ShImm);
52+
}
3753

3854
ARMInstPrinter::ARMInstPrinter(const MCAsmInfo &MAI,
3955
const MCInstrInfo &MII,
@@ -319,10 +335,8 @@ void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,
319335
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
320336
<< getRegisterName(MO2.getReg());
321337

322-
if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
323-
O << ", "
324-
<< ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
325-
<< " #" << ShImm;
338+
printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO3.getImm()),
339+
ARM_AM::getAM2Offset(MO3.getImm()));
326340
O << "]";
327341
}
328342

@@ -403,10 +417,8 @@ void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
403417
O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
404418
<< getRegisterName(MO1.getReg());
405419

406-
if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
407-
O << ", "
408-
<< ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
409-
<< " #" << ShImm;
420+
printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO2.getImm()),
421+
ARM_AM::getAM2Offset(MO2.getImm()));
410422
}
411423

412424
//===--------------------------------------------------------------------===//

llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -934,6 +934,10 @@ getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,
934934
ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(MO2.getImm());
935935
unsigned SBits = getShiftOp(ShOp);
936936

937+
// While "lsr #32" and "asr #32" exist, they are encoded with a 0 in the shift
938+
// amount. However, it would be an easy mistake to make so check here.
939+
assert((ShImm & ~0x1f) == 0 && "Out of range shift amount");
940+
937941
// {16-13} = Rn
938942
// {12} = isAdd
939943
// {11-0} = shifter

llvm/test/MC/ARM/arm-shift-encoding.s

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
@ RUN: llvm-mc -mcpu=cortex-a8 -triple armv7 -show-encoding < %s | FileCheck %s
2+
3+
ldr r0, [r0, r0]
4+
ldr r0, [r0, r0, lsr #32]
5+
ldr r0, [r0, r0, lsr #16]
6+
ldr r0, [r0, r0, lsl #0]
7+
ldr r0, [r0, r0, lsl #16]
8+
ldr r0, [r0, r0, asr #32]
9+
ldr r0, [r0, r0, asr #16]
10+
ldr r0, [r0, r0, rrx]
11+
ldr r0, [r0, r0, ror #16]
12+
13+
@ CHECK: ldr r0, [r0, r0] @ encoding: [0x00,0x00,0x90,0xe7]
14+
@ CHECK: ldr r0, [r0, r0, lsr #32] @ encoding: [0x20,0x00,0x90,0xe7]
15+
@ CHECK: ldr r0, [r0, r0, lsr #16] @ encoding: [0x20,0x08,0x90,0xe7]
16+
@ CHECK: ldr r0, [r0, r0] @ encoding: [0x00,0x00,0x90,0xe7]
17+
@ CHECK: ldr r0, [r0, r0, lsl #16] @ encoding: [0x00,0x08,0x90,0xe7]
18+
@ CHECK: ldr r0, [r0, r0, asr #32] @ encoding: [0x40,0x00,0x90,0xe7]
19+
@ CHECK: ldr r0, [r0, r0, asr #16] @ encoding: [0x40,0x08,0x90,0xe7]
20+
@ CHECK: ldr r0, [r0, r0, rrx] @ encoding: [0x60,0x00,0x90,0xe7]
21+
@ CHECK: ldr r0, [r0, r0, ror #16] @ encoding: [0x60,0x08,0x90,0xe7]
22+
23+
pld [r0, r0]
24+
pld [r0, r0, lsr #32]
25+
pld [r0, r0, lsr #16]
26+
pld [r0, r0, lsl #0]
27+
pld [r0, r0, lsl #16]
28+
pld [r0, r0, asr #32]
29+
pld [r0, r0, asr #16]
30+
pld [r0, r0, rrx]
31+
pld [r0, r0, ror #16]
32+
33+
@ CHECK: [r0, r0] @ encoding: [0x00,0xf0,0xd0,0xf7]
34+
@ CHECK: [r0, r0, lsr #32] @ encoding: [0x20,0xf0,0xd0,0xf7]
35+
@ CHECK: [r0, r0, lsr #16] @ encoding: [0x20,0xf8,0xd0,0xf7]
36+
@ CHECK: [r0, r0] @ encoding: [0x00,0xf0,0xd0,0xf7]
37+
@ CHECK: [r0, r0, lsl #16] @ encoding: [0x00,0xf8,0xd0,0xf7]
38+
@ CHECK: [r0, r0, asr #32] @ encoding: [0x40,0xf0,0xd0,0xf7]
39+
@ CHECK: [r0, r0, asr #16] @ encoding: [0x40,0xf8,0xd0,0xf7]
40+
@ CHECK: [r0, r0, rrx] @ encoding: [0x60,0xf0,0xd0,0xf7]
41+
@ CHECK: [r0, r0, ror #16] @ encoding: [0x60,0xf8,0xd0,0xf7]
42+
43+
str r0, [r0, r0]
44+
str r0, [r0, r0, lsr #32]
45+
str r0, [r0, r0, lsr #16]
46+
str r0, [r0, r0, lsl #0]
47+
str r0, [r0, r0, lsl #16]
48+
str r0, [r0, r0, asr #32]
49+
str r0, [r0, r0, asr #16]
50+
str r0, [r0, r0, rrx]
51+
str r0, [r0, r0, ror #16]
52+
53+
@ CHECK: str r0, [r0, r0] @ encoding: [0x00,0x00,0x80,0xe7]
54+
@ CHECK: str r0, [r0, r0, lsr #32] @ encoding: [0x20,0x00,0x80,0xe7]
55+
@ CHECK: str r0, [r0, r0, lsr #16] @ encoding: [0x20,0x08,0x80,0xe7]
56+
@ CHECK: str r0, [r0, r0] @ encoding: [0x00,0x00,0x80,0xe7]
57+
@ CHECK: str r0, [r0, r0, lsl #16] @ encoding: [0x00,0x08,0x80,0xe7]
58+
@ CHECK: str r0, [r0, r0, asr #32] @ encoding: [0x40,0x00,0x80,0xe7]
59+
@ CHECK: str r0, [r0, r0, asr #16] @ encoding: [0x40,0x08,0x80,0xe7]
60+
@ CHECK: str r0, [r0, r0, rrx] @ encoding: [0x60,0x00,0x80,0xe7]
61+
@ CHECK: str r0, [r0, r0, ror #16] @ encoding: [0x60,0x08,0x80,0xe7]
62+
63+
@ Uses printAddrMode2OffsetOperand(), used by LDRBT_POST_IMM LDRBT_POST_REG
64+
@ LDRB_POST_IMM LDRB_POST_REG LDRT_POST_IMM LDRT_POST_REG LDR_POST_IMM
65+
@ LDR_POST_REG STRBT_POST_IMM STRBT_POST_REG STRB_POST_IMM STRB_POST_REG
66+
@ STRT_POST_IMM STRT_POST_REG STR_POST_IMM STR_POST_REG
67+
68+
ldr r0, [r1], r2, rrx
69+
ldr r3, [r4], r5, ror #0
70+
str r6, [r7], r8, lsl #0
71+
str r9, [r10], r11
72+
73+
@ CHECK: ldr r0, [r1], r2, rrx @ encoding: [0x62,0x00,0x91,0xe6]
74+
@ CHECK: ldr r3, [r4], r5 @ encoding: [0x05,0x30,0x94,0xe6]
75+
@ CHECK: str r6, [r7], r8 @ encoding: [0x08,0x60,0x87,0xe6]
76+
@ CHECK: str r9, [r10], r11 @ encoding: [0x0b,0x90,0x8a,0xe6]

llvm/test/MC/ARM/diagnostics.s

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,47 @@
4747
@ CHECK-ERRORS: error: immediate shift value out of range
4848
@ CHECK-ERRORS: adc r4, r5, r6, ror #32
4949

50+
@ Out of range shift immediate values for load/store.
51+
str r1, [r2, r3, lsl #invalid]
52+
ldr r4, [r5], r6, lsl #-1
53+
pld r4, [r5, r6, lsl #32]
54+
str r4, [r5], r6, lsr #-1
55+
ldr r4, [r5, r6, lsr #33]
56+
pld r4, [r5, r6, asr #-1]
57+
str r4, [r5, r6, asr #33]
58+
ldr r4, [r5, r6, ror #-1]
59+
pld r4, [r5, r6, ror #32]
60+
pld r4, [r5, r6, rrx #0]
5061

62+
@ CHECK-ERRORS: error: shift amount must be an immediate
63+
@ CHECK-ERRORS: str r1, [r2, r3, lsl #invalid]
64+
@ CHECK-ERRORS: ^
65+
@ CHECK-ERRORS: error: immediate shift value out of range
66+
@ CHECK-ERRORS: ldr r4, [r5], r6, lsl #-1
67+
@ CHECK-ERRORS: ^
68+
@ CHECK-ERRORS: error: immediate shift value out of range
69+
@ CHECK-ERRORS: pld r4, [r5, r6, lsl #32]
70+
@ CHECK-ERRORS: ^
71+
@ CHECK-ERRORS: error: immediate shift value out of range
72+
@ CHECK-ERRORS: str r4, [r5], r6, lsr #-1
73+
@ CHECK-ERRORS: ^
74+
@ CHECK-ERRORS: error: immediate shift value out of range
75+
@ CHECK-ERRORS: ldr r4, [r5, r6, lsr #33]
76+
@ CHECK-ERRORS: ^
77+
@ CHECK-ERRORS: error: immediate shift value out of range
78+
@ CHECK-ERRORS: pld r4, [r5, r6, asr #-1]
79+
@ CHECK-ERRORS: ^
80+
@ CHECK-ERRORS: error: immediate shift value out of range
81+
@ CHECK-ERRORS: str r4, [r5, r6, asr #33]
82+
@ CHECK-ERRORS: ^
83+
@ CHECK-ERRORS: error: immediate shift value out of range
84+
@ CHECK-ERRORS: ldr r4, [r5, r6, ror #-1]
85+
@ CHECK-ERRORS: ^
86+
@ CHECK-ERRORS: error: immediate shift value out of range
87+
@ CHECK-ERRORS: pld r4, [r5, r6, ror #32]
88+
@ CHECK-ERRORS: error: ']' expected
89+
@ CHECK-ERRORS: pld r4, [r5, r6, rrx #0]
90+
5191
@ Out of range 16-bit immediate on BKPT
5292
bkpt #65536
5393

0 commit comments

Comments
 (0)