Index: lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp =================================================================== --- lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp (revision 163390) +++ lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp (working copy) @@ -34,7 +34,20 @@ return imm; } +/// Prints the shift value with an immediate value. +static void printRegImmShift(raw_ostream &O, ARM_AM::ShiftOpc ShOpc, + unsigned ShImm) { + if (ShOpc == ARM_AM::no_shift || (ShOpc == ARM_AM::lsl && !ShImm)) + return; + O << ", "; + assert (!(ShOpc == ARM_AM::ror && !ShImm) && "Cannot have ror #0"); + O << getShiftOpcStr(ShOpc); + + if (ShOpc != ARM_AM::rrx) + O << " #" << translateShiftImm(ShImm); +} + ARMInstPrinter::ARMInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI, @@ -319,10 +332,8 @@ << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm())) << getRegisterName(MO2.getReg()); - if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm())) - O << ", " - << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm())) - << " #" << ShImm; + printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO3.getImm()), + ARM_AM::getAM2Offset(MO3.getImm())); O << "]"; } @@ -403,10 +414,9 @@ O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm())) << getRegisterName(MO1.getReg()); - if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm())) - O << ", " - << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm())) - << " #" << ShImm; + printRegImmShift(O, ARM_AM::getAM2ShiftOpc(MO2.getImm()), + ARM_AM::getAM2Offset(MO2.getImm())); + } //===--------------------------------------------------------------------===// Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp (revision 163390) +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp (working copy) @@ -4439,6 +4439,12 @@ ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) || ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32)) return Error(Loc, "immediate shift value out of range"); + // If #0, turn it into a no_shift. + if (Imm == 0) + St = ARM_AM::lsl; + if (Imm == 32) + Imm = 0; Amount = Imm; } Index: lib/Target/ARM/Disassembler/ARMDisassembler.cpp =================================================================== --- lib/Target/ARM/Disassembler/ARMDisassembler.cpp (revision 163390) +++ lib/Target/ARM/Disassembler/ARMDisassembler.cpp (working copy) @@ -1523,6 +1523,8 @@ return MCDisassembler::Fail; } unsigned amt = fieldFromInstruction(Insn, 7, 5); + if (Opc == ARM_AM::ror && amt == 0) + Opc = ARM_AM::rrx; unsigned imm = ARM_AM::getAM2Opc(Op, amt, Opc, idx_mode); Inst.addOperand(MCOperand::CreateImm(imm)); @@ -1564,6 +1566,9 @@ break; } + if (ShOp == ARM_AM::ror && imm == 0) + ShOp = ARM_AM::rrx; + if (!Check(S, DecodeGPRRegisterClass(Inst, Rn, Address, Decoder))) return MCDisassembler::Fail; if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder))) Index: test/MC/ARM/arm-shift-encoding.s =================================================================== --- test/MC/ARM/arm-shift-encoding.s (revision 0) +++ test/MC/ARM/arm-shift-encoding.s (revision 0) @@ -0,0 +1,71 @@ +@ RUN: llvm-mc -mcpu=cortex-a8 -triple armv7 -show-encoding < %s | FileCheck %s + + ldr r0, [r0, r0] + ldr r1, [r8, r9, lsr #32] + ldr r2, [r7, pc, lsr #16] + ldr r3, [r6, r10, lsl #0] + ldr r4, [r5, lr, lsl #16] + ldr r5, [r4, r11, asr #32] + ldr r6, [r3, sp, asr #16] + ldr r7, [r2, r12, rrx] + ldr r8, [r1, r0, ror #16] + +@ CHECK: ldr r0, [r0, r0] @ encoding: [0x00,0x00,0x90,0xe7] +@ CHECK: ldr r1, [r8, r9, lsr #32] @ encoding: [0x29,0x10,0x98,0xe7] +@ CHECK: ldr r2, [r7, pc, lsr #16] @ encoding: [0x2f,0x28,0x97,0xe7] +@ CHECK: ldr r3, [r6, r10] @ encoding: [0x0a,0x30,0x96,0xe7] +@ CHECK: ldr r4, [r5, lr, lsl #16] @ encoding: [0x0e,0x48,0x95,0xe7] +@ CHECK: ldr r5, [r4, r11, asr #32] @ encoding: [0x4b,0x50,0x94,0xe7] +@ CHECK: ldr r6, [r3, sp, asr #16] @ encoding: [0x4d,0x68,0x93,0xe7] +@ CHECK: ldr r7, [r2, r12, rrx] @ encoding: [0x6c,0x70,0x92,0xe7] +@ CHECK: ldr r8, [r1, r0, ror #16] @ encoding: [0x60,0x88,0x91,0xe7] + + pld [r1, pc] + pld [r2, lr, lsr #32] + pld [r3, sp, lsr #16] + pld [r4, r12, lsl #0] + pld [r5, r11, lsl #16] + pld [r6, r10, asr #32] + pld [r7, r9, asr #16] + pld [r8, r8, rrx] + pld [r9, r7, ror #16] + +@ CHECK: [r1, pc] @ encoding: [0x0f,0xf0,0xd1,0xf7] +@ CHECK: [r2, lr, lsr #32] @ encoding: [0x2e,0xf0,0xd2,0xf7] +@ CHECK: [r3, sp, lsr #16] @ encoding: [0x2d,0xf8,0xd3,0xf7] +@ CHECK: [r4, r12] @ encoding: [0x0c,0xf0,0xd4,0xf7] +@ CHECK: [r5, r11, lsl #16] @ encoding: [0x0b,0xf8,0xd5,0xf7] +@ CHECK: [r6, r10, asr #32] @ encoding: [0x4a,0xf0,0xd6,0xf7] +@ CHECK: [r7, r9, asr #16] @ encoding: [0x49,0xf8,0xd7,0xf7] +@ CHECK: [r8, r8, rrx] @ encoding: [0x68,0xf0,0xd8,0xf7] +@ CHECK: [r9, r7, ror #16] @ encoding: [0x67,0xf8,0xd9,0xf7] + + str r1, [r0, r3] + str r3, [r2, r4, lsr #32] + str r5, [r4, r5, lsr #16] + str r7, [r6, r6, lsl #0] + str r9, [r8, r7, lsl #16] + str r11, [r10, r8, asr #32] + str sp, [r12, r9, asr #16] + str r0, [lr, r10, rrx] + str pc, [r0, r11, ror #16] + +@ CHECK: str r1, [r0, r3] @ encoding: [0x03,0x10,0x80,0xe7] +@ CHECK: str r3, [r2, r4, lsr #32] @ encoding: [0x24,0x30,0x82,0xe7] +@ CHECK: str r5, [r4, r5, lsr #16] @ encoding: [0x25,0x58,0x84,0xe7] +@ CHECK: str r7, [r6, r6] @ encoding: [0x06,0x70,0x86,0xe7] +@ CHECK: str r9, [r8, r7, lsl #16] @ encoding: [0x07,0x98,0x88,0xe7] +@ CHECK: str r11, [r10, r8, asr #32] @ encoding: [0x48,0xb0,0x8a,0xe7] +@ CHECK: str sp, [r12, r9, asr #16] @ encoding: [0x49,0xd8,0x8c,0xe7] +@ CHECK: str r0, [lr, r10, rrx] @ encoding: [0x6a,0x00,0x8e,0xe7] +@ CHECK: str pc, [r0, r11, ror #16] @ encoding: [0x6b,0xf8,0x80,0xe7] + + ldr r0, [r1], r2, rrx + ldr r3, [r4], r5, ror #0 + str r6, [r7], r8, lsl #0 + str r9, [r10], r11 + +@ CHECK: ldr r0, [r1], r2, rrx @ encoding: [0x62,0x00,0x91,0xe6] +@ CHECK: ldr r3, [r4], r5 @ encoding: [0x05,0x30,0x94,0xe6] +@ CHECK: str r6, [r7], r8 @ encoding: [0x08,0x60,0x87,0xe6] +@ CHECK: str r9, [r10], r11 @ encoding: [0x0b,0x90,0x8a,0xe6] Index: test/MC/ARM/diagnostics.s =================================================================== --- test/MC/ARM/diagnostics.s (revision 163390) +++ test/MC/ARM/diagnostics.s (working copy) @@ -48,6 +48,48 @@ @ CHECK-ERRORS: adc r4, r5, r6, ror #32 + @ Out of range shift immediate values for load/store. + str r1, [r2, r3, lsl #invalid] + ldr r4, [r5], r6, lsl #-1 + pld r4, [r5, r6, lsl #32] + str r4, [r5], r6, lsr #-1 + ldr r4, [r5, r6, lsr #33] + pld r4, [r5, r6, asr #-1] + str r4, [r5, r6, asr #33] + ldr r4, [r5, r6, ror #-1] + pld r4, [r5, r6, ror #32] + pld r4, [r5, r6, rrx #0] + +@ CHECK-ERRORS: error: shift amount must be an immediate +@ CHECK-ERRORS: str r1, [r2, r3, lsl #invalid] +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: ldr r4, [r5], r6, lsl #-1 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: pld r4, [r5, r6, lsl #32] +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: str r4, [r5], r6, lsr #-1 +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: ldr r4, [r5, r6, lsr #33] +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: pld r4, [r5, r6, asr #-1] +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: str r4, [r5, r6, asr #33] +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: ldr r4, [r5, r6, ror #-1] +@ CHECK-ERRORS: ^ +@ CHECK-ERRORS: error: immediate shift value out of range +@ CHECK-ERRORS: pld r4, [r5, r6, ror #32] +@ CHECK-ERRORS: error: ']' expected +@ CHECK-ERRORS: pld r4, [r5, r6, rrx #0] + + @ Out of range 16-bit immediate on BKPT bkpt #65536