diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 75a109e2c3c..ee824699e76 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -2282,12 +2282,6 @@ let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1 in { def LDRD : AI3ld<0b1101, 0, (outs GPR:$Rt, GPR:$Rt2), (ins addrmode3:$addr), LdMiscFrm, IIC_iLoad_d_r, "ldrd", "\t$Rt, $Rt2, $addr", []>, Requires<[IsARM, HasV5TE]>; - - // GNU Assembler extension (compatibility) - let isAsmParserOnly = 1 in - def LDRD_PAIR : AI3ld<0b1101, 0, (outs GPRPairOp:$Rt), (ins addrmode3:$addr), - LdMiscFrm, IIC_iLoad_d_r, "ldrd", "\t$Rt, $addr", []>, - Requires<[IsARM, HasV5TE]>; } def LDA : AIldracq<0b00, (outs GPR:$Rt), (ins addr_offset_none:$addr), @@ -2557,14 +2551,6 @@ let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in { Requires<[IsARM, HasV5TE]> { let Inst{21} = 0; } - - // GNU Assembler extension (compatibility) - let isAsmParserOnly = 1 in - def STRD_PAIR : AI3str<0b1111, (outs), (ins GPRPairOp:$Rt, addrmode3:$addr), - StMiscFrm, IIC_iStore_d_r, "strd", "\t$Rt, $addr", []>, - Requires<[IsARM, HasV5TE]> { - let Inst{21} = 0; - } } // Indexed stores diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 9c57a244fdb..8550641c63d 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -5404,21 +5404,24 @@ bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } // GNU Assembler extension (compatibility) - if ((Mnemonic == "ldrd" || Mnemonic == "strd") && !isThumb() && - Operands.size() == 4) { - ARMOperand *Op = static_cast(Operands[2]); - assert(Op->isReg() && "expected register argument"); + if ((Mnemonic == "ldrd" || Mnemonic == "strd")) { + ARMOperand *Op2 = static_cast(Operands[2]); + ARMOperand *Op3 = static_cast(Operands[3]); + if (Op3->isMem()) { + assert(Op2->isReg() && "expected register argument"); - unsigned SuperReg = MRI->getMatchingSuperReg( - Op->getReg(), ARM::gsub_0, &MRI->getRegClass(ARM::GPRPairRegClassID)); + unsigned SuperReg = MRI->getMatchingSuperReg( + Op2->getReg(), ARM::gsub_0, &MRI->getRegClass(ARM::GPRPairRegClassID)); - assert(SuperReg && "expected register pair"); + assert(SuperReg && "expected register pair"); - unsigned PairedReg = MRI->getSubReg(SuperReg, ARM::gsub_1); + unsigned PairedReg = MRI->getSubReg(SuperReg, ARM::gsub_1); - Operands.insert(Operands.begin() + 3, - ARMOperand::CreateReg(PairedReg, Op->getStartLoc(), - Op->getEndLoc())); + Operands.insert(Operands.begin() + 3, + ARMOperand::CreateReg(PairedReg, + Op2->getStartLoc(), + Op2->getEndLoc())); + } } // FIXME: As said above, this is all a pretty gross hack. This instruction diff --git a/test/MC/ARM/ldrd-strd-gnu-arm-bad-imm.s b/test/MC/ARM/ldrd-strd-gnu-arm-bad-imm.s new file mode 100644 index 00000000000..fbe459c4168 --- /dev/null +++ b/test/MC/ARM/ldrd-strd-gnu-arm-bad-imm.s @@ -0,0 +1,9 @@ +@ RUN: not llvm-mc -triple=armv7-linux-gnueabi %s 2>&1 | FileCheck %s +.text +@ CHECK: error: instruction requires: thumb2 +@ CHECK: ldrd r0, [r0, #512] + ldrd r0, [r0, #512] + +@ CHECK: error: instruction requires: thumb2 +@ CHECK: strd r0, [r0, #512] + strd r0, [r0, #512] diff --git a/test/MC/ARM/ldrd-strd-gnu-arm.s b/test/MC/ARM/ldrd-strd-gnu-arm.s new file mode 100644 index 00000000000..57d21c7a146 --- /dev/null +++ b/test/MC/ARM/ldrd-strd-gnu-arm.s @@ -0,0 +1,20 @@ +@ PR18921 +@ RUN: llvm-mc -triple=armv7-linux-gnueabi -show-encoding < %s | FileCheck %s +.text + +@ CHECK-NOT: .code 16 + + +@ CHECK: ldrd r0, r1, [r10, #32]! @ encoding: [0xd0,0x02,0xea,0xe1] +@ CHECK: ldrd r0, r1, [r10], #32 @ encoding: [0xd0,0x02,0xca,0xe0] +@ CHECK: ldrd r0, r1, [r10, #32] @ encoding: [0xd0,0x02,0xca,0xe1] + ldrd r0, [r10, #32]! + ldrd r0, [r10], #32 + ldrd r0, [r10, #32] + +@ CHECK: strd r0, r1, [r10, #32]! @ encoding: [0xf0,0x02,0xea,0xe1] +@ CHECK: strd r0, r1, [r10], #32 @ encoding: [0xf0,0x02,0xca,0xe0] +@ CHECK: strd r0, r1, [r10, #32] @ encoding: [0xf0,0x02,0xca,0xe1] + strd r0, [r10, #32]! + strd r0, [r10], #32 + strd r0, [r10, #32] diff --git a/test/MC/ARM/ldrd-strd-gnu-thumb-bad-regs.s b/test/MC/ARM/ldrd-strd-gnu-thumb-bad-regs.s new file mode 100644 index 00000000000..9d81a27f0ca --- /dev/null +++ b/test/MC/ARM/ldrd-strd-gnu-thumb-bad-regs.s @@ -0,0 +1,10 @@ +@ RUN: not llvm-mc -triple=armv7-linux-gnueabi %s 2>&1 | FileCheck %s +.text +.thumb +@ CHECK: error: invalid operand for instruction +@ CHECK: ldrd r12, [r0, #512] + ldrd r12, [r0, #512] + +@ CHECK: error: invalid operand for instruction +@ CHECK: strd r12, [r0, #512] + strd r12, [r0, #512] diff --git a/test/MC/ARM/ldrd-strd-gnu-thumb.s b/test/MC/ARM/ldrd-strd-gnu-thumb.s new file mode 100644 index 00000000000..67d2aa7f548 --- /dev/null +++ b/test/MC/ARM/ldrd-strd-gnu-thumb.s @@ -0,0 +1,20 @@ +@ PR18921 +@ RUN: llvm-mc -triple=armv7-linux-gnueabi -show-encoding < %s | FileCheck %s +.text +.thumb + +@ CHECK: .code 16 + +@ CHECK: ldrd r0, r1, [r10, #512]! @ encoding: [0xfa,0xe9,0x80,0x01] +@ CHECK: ldrd r0, r1, [r10], #512 @ encoding: [0xfa,0xe8,0x80,0x01] +@ CHECK: ldrd r0, r1, [r10, #512] @ encoding: [0xda,0xe9,0x80,0x01] + ldrd r0, [r10, #512]! + ldrd r0, [r10], #512 + ldrd r0, [r10, #512] + +@ CHECK: strd r0, r1, [r10, #512]! @ encoding: [0xea,0xe9,0x80,0x01] +@ CHECK: strd r0, r1, [r10], #512 @ encoding: [0xea,0xe8,0x80,0x01] +@ CHECK: strd r0, r1, [r10, #512] @ encoding: [0xca,0xe9,0x80,0x01] + strd r0, [r10, #512]! + strd r0, [r10], #512 + strd r0, [r10, #512]