diff options
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 28 | ||||
| -rw-r--r-- | llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp | 4 | ||||
| -rw-r--r-- | llvm/test/MC/ARM/arm-shift-encoding.s | 76 | ||||
| -rw-r--r-- | llvm/test/MC/ARM/diagnostics.s | 40 | 
6 files changed, 151 insertions, 8 deletions
| diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 3e68a0b865a..bc711dc35f0 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -4444,6 +4444,12 @@ bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,          ((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 <ShiftTy> #0, turn it into a no_shift. +    if (Imm == 0) +      St = ARM_AM::lsl; +    // For consistency, treat lsr #32 and asr #32 as having immediate value 0. +    if (Imm == 32) +      Imm = 0;      Amount = Imm;    } diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index 57642e1924e..bf0dabb4a0f 100644 --- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -1523,6 +1523,8 @@ DecodeAddrMode2IdxInstruction(MCInst &Inst, unsigned Insn,          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 @@ static DecodeStatus DecodeSORegMemOperand(MCInst &Inst, unsigned Val,        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))) diff --git a/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index 8b9109ec986..60f92f82d40 100644 --- a/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/llvm/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -29,11 +29,27 @@ using namespace llvm;  ///  /// getSORegOffset returns an integer from 0-31, representing '32' as 0.  static unsigned translateShiftImm(unsigned imm) { +  // lsr #32 and asr #32 exist, but should be encoded as a 0. +  assert((imm & ~0x1f) == 0 && "Invalid shift encoding"); +    if (imm == 0)      return 32;    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, @@ -319,10 +335,8 @@ void ARMInstPrinter::printAM2PreOrOffsetIndexOp(const MCInst *MI, unsigned Op,      << 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 +417,8 @@ void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,    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()));  }  //===--------------------------------------------------------------------===// diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp index dde72853540..d0e127a8f33 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMMCCodeEmitter.cpp @@ -934,6 +934,10 @@ getLdStSORegOpValue(const MCInst &MI, unsigned OpIdx,    ARM_AM::ShiftOpc ShOp = ARM_AM::getAM2ShiftOpc(MO2.getImm());    unsigned SBits = getShiftOp(ShOp); +  // While "lsr #32" and "asr #32" exist, they are encoded with a 0 in the shift +  // amount. However, it would be an easy mistake to make so check here. +  assert((ShImm & ~0x1f) == 0 && "Out of range shift amount"); +    // {16-13} = Rn    // {12}    = isAdd    // {11-0}  = shifter diff --git a/llvm/test/MC/ARM/arm-shift-encoding.s b/llvm/test/MC/ARM/arm-shift-encoding.s new file mode 100644 index 00000000000..c849380ff2b --- /dev/null +++ b/llvm/test/MC/ARM/arm-shift-encoding.s @@ -0,0 +1,76 @@ +@ RUN: llvm-mc -mcpu=cortex-a8 -triple armv7 -show-encoding < %s | FileCheck %s + +	ldr r0, [r0, r0] +	ldr r0, [r0, r0, lsr #32] +	ldr r0, [r0, r0, lsr #16] +	ldr r0, [r0, r0, lsl #0] +	ldr r0, [r0, r0, lsl #16] +	ldr r0, [r0, r0, asr #32] +	ldr r0, [r0, r0, asr #16] +	ldr r0, [r0, r0, rrx] +	ldr r0, [r0, r0, ror #16] + +@ CHECK: ldr r0, [r0, r0]          @ encoding: [0x00,0x00,0x90,0xe7] +@ CHECK: ldr r0, [r0, r0, lsr #32] @ encoding: [0x20,0x00,0x90,0xe7] +@ CHECK: ldr r0, [r0, r0, lsr #16] @ encoding: [0x20,0x08,0x90,0xe7] +@ CHECK: ldr r0, [r0, r0]          @ encoding: [0x00,0x00,0x90,0xe7] +@ CHECK: ldr r0, [r0, r0, lsl #16] @ encoding: [0x00,0x08,0x90,0xe7] +@ CHECK: ldr r0, [r0, r0, asr #32] @ encoding: [0x40,0x00,0x90,0xe7] +@ CHECK: ldr r0, [r0, r0, asr #16] @ encoding: [0x40,0x08,0x90,0xe7] +@ CHECK: ldr r0, [r0, r0, rrx]     @ encoding: [0x60,0x00,0x90,0xe7] +@ CHECK: ldr r0, [r0, r0, ror #16] @ encoding: [0x60,0x08,0x90,0xe7] + +	pld [r0, r0] +	pld [r0, r0, lsr #32] +	pld [r0, r0, lsr #16] +	pld [r0, r0, lsl #0] +	pld [r0, r0, lsl #16] +	pld [r0, r0, asr #32] +	pld [r0, r0, asr #16] +	pld [r0, r0, rrx] +	pld [r0, r0, ror #16] + +@ CHECK: [r0, r0]          @ encoding: [0x00,0xf0,0xd0,0xf7] +@ CHECK: [r0, r0, lsr #32] @ encoding: [0x20,0xf0,0xd0,0xf7] +@ CHECK: [r0, r0, lsr #16] @ encoding: [0x20,0xf8,0xd0,0xf7] +@ CHECK: [r0, r0]          @ encoding: [0x00,0xf0,0xd0,0xf7] +@ CHECK: [r0, r0, lsl #16] @ encoding: [0x00,0xf8,0xd0,0xf7] +@ CHECK: [r0, r0, asr #32] @ encoding: [0x40,0xf0,0xd0,0xf7] +@ CHECK: [r0, r0, asr #16] @ encoding: [0x40,0xf8,0xd0,0xf7] +@ CHECK: [r0, r0, rrx]     @ encoding: [0x60,0xf0,0xd0,0xf7] +@ CHECK: [r0, r0, ror #16] @ encoding: [0x60,0xf8,0xd0,0xf7] + +	str r0, [r0, r0] +	str r0, [r0, r0, lsr #32] +	str r0, [r0, r0, lsr #16] +	str r0, [r0, r0, lsl #0] +	str r0, [r0, r0, lsl #16] +	str r0, [r0, r0, asr #32] +	str r0, [r0, r0, asr #16] +	str r0, [r0, r0, rrx] +	str r0, [r0, r0, ror #16] + +@ CHECK: str r0, [r0, r0]          @ encoding: [0x00,0x00,0x80,0xe7] +@ CHECK: str r0, [r0, r0, lsr #32] @ encoding: [0x20,0x00,0x80,0xe7] +@ CHECK: str r0, [r0, r0, lsr #16] @ encoding: [0x20,0x08,0x80,0xe7] +@ CHECK: str r0, [r0, r0]          @ encoding: [0x00,0x00,0x80,0xe7] +@ CHECK: str r0, [r0, r0, lsl #16] @ encoding: [0x00,0x08,0x80,0xe7] +@ CHECK: str r0, [r0, r0, asr #32] @ encoding: [0x40,0x00,0x80,0xe7] +@ CHECK: str r0, [r0, r0, asr #16] @ encoding: [0x40,0x08,0x80,0xe7] +@ CHECK: str r0, [r0, r0, rrx]     @ encoding: [0x60,0x00,0x80,0xe7] +@ CHECK: str r0, [r0, r0, ror #16] @ encoding: [0x60,0x08,0x80,0xe7] + +@ Uses printAddrMode2OffsetOperand(), used by LDRBT_POST_IMM LDRBT_POST_REG +@ LDRB_POST_IMM LDRB_POST_REG LDRT_POST_IMM LDRT_POST_REG LDR_POST_IMM +@ LDR_POST_REG STRBT_POST_IMM STRBT_POST_REG STRB_POST_IMM STRB_POST_REG +@ STRT_POST_IMM STRT_POST_REG STR_POST_IMM STR_POST_REG + +	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] diff --git a/llvm/test/MC/ARM/diagnostics.s b/llvm/test/MC/ARM/diagnostics.s index 499e0550135..ad4d9ab9b5e 100644 --- a/llvm/test/MC/ARM/diagnostics.s +++ b/llvm/test/MC/ARM/diagnostics.s @@ -47,7 +47,47 @@  @ CHECK-ERRORS: error: immediate shift value out of range  @ 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 | 

