diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index e2b16d85347..bb9debd7696 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -167,11 +167,13 @@ def t2am_imm8s4_offset : Operand { } // t2addrmode_so_reg := reg + (reg << imm2) +def t2addrmode_so_reg_asmoperand : AsmOperandClass {let Name="T2MemRegOffset";} def t2addrmode_so_reg : Operand, ComplexPattern { let PrintMethod = "printT2AddrModeSoRegOperand"; let EncoderMethod = "getT2AddrModeSORegOpValue"; let DecoderMethod = "DecodeT2AddrModeSOReg"; + let ParserMatchClass = t2addrmode_so_reg_asmoperand; let MIOperandInfo = (ops GPR:$base, rGPR:$offsreg, i32imm:$offsimm); } @@ -3709,3 +3711,9 @@ def : t2InstAlias<"ldrb${p} $Rt, $addr", (t2LDRBi12 rGPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>; def : t2InstAlias<"ldrh${p} $Rt, $addr", (t2LDRHi12 rGPR:$Rt, t2addrmode_imm12:$addr, pred:$p)>; +def : t2InstAlias<"ldr${p} $Rt, $addr", + (t2LDRs GPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>; +def : t2InstAlias<"ldrb${p} $Rt, $addr", + (t2LDRBs rGPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>; +def : t2InstAlias<"ldrh${p} $Rt, $addr", + (t2LDRHs rGPR:$Rt, t2addrmode_so_reg:$addr, pred:$p)>; diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 9efdd421f0c..6df2d56ff2c 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -680,6 +680,16 @@ public: return false; return true; } + bool isT2MemRegOffset() const { + if (Kind != Memory || !Mem.OffsetRegNum || Mem.isNegative) + return false; + // Only lsl #{0, 1, 2, 3} allowed. + if (Mem.ShiftType == ARM_AM::no_shift) + return true; + if (Mem.ShiftType != ARM_AM::lsl || Mem.ShiftImm > 3) + return false; + return true; + } bool isMemThumbRR() const { // Thumb reg+reg addressing is simple. Just two registers, a base and // an offset. No shifts, negations or any other complicating factors. @@ -844,7 +854,6 @@ public: ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, RegShiftedImm.ShiftImm))); } - void addShifterImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) | @@ -1145,6 +1154,13 @@ public: Inst.addOperand(MCOperand::CreateImm(Val)); } + void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const { + assert(N == 3 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); + Inst.addOperand(MCOperand::CreateReg(Mem.OffsetRegNum)); + Inst.addOperand(MCOperand::CreateImm(Mem.ShiftImm)); + } + void addMemThumbRROperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateReg(Mem.BaseRegNum)); diff --git a/test/MC/ARM/basic-thumb2-instructions.s b/test/MC/ARM/basic-thumb2-instructions.s index d23b565540e..25141dbcb2e 100644 --- a/test/MC/ARM/basic-thumb2-instructions.s +++ b/test/MC/ARM/basic-thumb2-instructions.s @@ -539,6 +539,24 @@ _func: @ fixup A - offset: 0, value: _foo, kind: fixup_t2_ldst_pcrel_12 +@------------------------------------------------------------------------------ +@ LDR(register) +@------------------------------------------------------------------------------ + ldr r1, [r8, r1] + ldr.w r4, [r5, r2] + ldr r6, [r0, r2, lsl #3] + ldr r8, [r8, r2, lsl #2] + ldr r7, [sp, r2, lsl #1] + ldr r7, [sp, r2, lsl #0] + +@ CHECK: ldr.w r1, [r8, r1] @ encoding: [0x58,0xf8,0x01,0x10] +@ CHECK: ldr.w r4, [r5, r2] @ encoding: [0x55,0xf8,0x02,0x40] +@ CHECK: ldr.w r6, [r0, r2, lsl #3] @ encoding: [0x50,0xf8,0x32,0x60] +@ CHECK: ldr.w r8, [r8, r2, lsl #2] @ encoding: [0x58,0xf8,0x22,0x80] +@ CHECK: ldr.w r7, [sp, r2, lsl #1] @ encoding: [0x5d,0xf8,0x12,0x70] +@ CHECK: ldr.w r7, [sp, r2] @ encoding: [0x5d,0xf8,0x02,0x70] + + @------------------------------------------------------------------------------ @ LDRB(immediate) @------------------------------------------------------------------------------