diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 3b77cdbdff1..4d842e72c49 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -2007,16 +2007,18 @@ multiclass AI3_ldridx op, bit op20, string opc, InstrItinClass itin> { let Inst{19-16} = addr{12-9}; // Rn let Inst{11-8} = addr{7-4}; // imm7_4/zero let Inst{3-0} = addr{3-0}; // imm3_0/Rm + let AsmMatchConverter = "cvtLdWriteBackRegAddrMode3"; } def _POST : AI3ldstidx { + (ins addr_offset_none:$addr, am3offset:$offset), + IndexModePost, LdMiscFrm, itin, + opc, "\t$Rt, $addr, $offset", "$addr.base = $Rn_wb", + []> { bits<10> offset; - bits<4> Rn; + bits<4> addr; let Inst{23} = offset{8}; // U bit let Inst{22} = offset{9}; // 1 == imm8, 0 == Rm - let Inst{19-16} = Rn; + let Inst{19-16} = addr; let Inst{11-8} = offset{7-4}; // imm7_4/zero let Inst{3-0} = offset{3-0}; // imm3_0/Rm } diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 72ab7ea595d..85e3f1a82f2 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -131,6 +131,8 @@ class ARMAsmParser : public MCTargetAsmParser { const SmallVectorImpl &); bool cvtLdrdPre(MCInst &Inst, unsigned Opcode, const SmallVectorImpl &); + bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &); bool validateInstruction(MCInst &Inst, const SmallVectorImpl &Ops); @@ -2202,6 +2204,21 @@ cvtLdrdPre(MCInst &Inst, unsigned Opcode, return true; } +/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst. +/// Needed here because the Asm Gen Matcher can't handle properly tied operands +/// when they refer multiple MIOperands inside a single one. +bool ARMAsmParser:: +cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &Operands) { + ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); + // Create a writeback register dummy placeholder. + Inst.addOperand(MCOperand::CreateImm(0)); + ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3); + ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); + return true; +} + + /// Parse an ARM memory expression, return false if successful else return true /// or an error. The first token must be a '[' when called. bool ARMAsmParser:: diff --git a/test/MC/ARM/arm-memory-instructions.s b/test/MC/ARM/arm-memory-instructions.s index fd313944cc1..022d7a32e19 100644 --- a/test/MC/ARM/arm-memory-instructions.s +++ b/test/MC/ARM/arm-memory-instructions.s @@ -139,7 +139,23 @@ _func: ldrd r1, r2, [r8], r12 ldrd r1, r2, [r8], -r12 - ldrd r3, r4, [r1, r3] @ encoding: [0xd3,0x30,0x81,0xe1] - ldrd r4, r5, [r7, r2]! @ encoding: [0xd2,0x40,0xa7,0xe1] - ldrd r1, r2, [r8], r12 @ encoding: [0xdc,0x10,0x88,0xe0] - ldrd r1, r2, [r8], -r12 @ encoding: [0xdc,0x10,0x08,0xe0] +@ CHECK: ldrd r3, r4, [r1, r3] @ encoding: [0xd3,0x30,0x81,0xe1] +@ CHECK: ldrd r4, r5, [r7, r2]! @ encoding: [0xd2,0x40,0xa7,0xe1] +@ CHECK: ldrd r1, r2, [r8], r12 @ encoding: [0xdc,0x10,0x88,0xe0] +@ CHECK: ldrd r1, r2, [r8], -r12 @ encoding: [0xdc,0x10,0x08,0xe0] + + +@------------------------------------------------------------------------------ +@ LDRH (immediate) +@------------------------------------------------------------------------------ + ldrh r3, [r4] + ldrh r2, [r7, #4] + ldrh r1, [r8, #64]! + ldrh r12, [sp], #4 + +@ CHECK: ldrh r3, [r4] @ encoding: [0xb0,0x30,0xd4,0xe1] +@ CHECK: ldrh r2, [r7, #4] @ encoding: [0xb4,0x20,0xd7,0xe1] +@ CHECK: ldrh r1, [r8, #64]! @ encoding: [0xb0,0x14,0xf8,0xe1] +@ CHECK: ldrh r12, [sp], #4 @ encoding: [0xb4,0xc0,0xdd,0xe0] + +