diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td index 579f3835bcc..343dee55622 100644 --- a/lib/Target/ARM/ARMInstrFormats.td +++ b/lib/Target/ARM/ARMInstrFormats.td @@ -680,35 +680,6 @@ class AI3sthpr pattern> - : I { - let Inst{4} = 1; - let Inst{5} = 1; // H bit - let Inst{6} = 1; // S bit - let Inst{7} = 1; - let Inst{20} = 0; // L bit - let Inst{21} = 1; // W bit - let Inst{24} = 1; // P bit - let Inst{27-25} = 0b000; -} - -// Post-indexed stores -class AI3stdpo pattern> - : I { - let Inst{4} = 1; - let Inst{5} = 1; // H bit - let Inst{6} = 1; // S bit - let Inst{7} = 1; - let Inst{20} = 0; // L bit - let Inst{21} = 0; // W bit - let Inst{24} = 0; // P bit - let Inst{27-25} = 0b000; -} - // addrmode4 instructions class AXI4 pattern> diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index c8eb0257313..df86d12266e 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -2369,42 +2369,35 @@ def STRH_POST: AI3stridx<0b1011, 0, 0, (outs GPR:$Rn_wb), [(set GPR:$Rn_wb, (post_truncsti16 GPR:$Rt, GPR:$Rn, am3offset:$offset))]>; -// For disassembly only let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 in { -def STRD_PRE : AI3stdpr<(outs GPR:$base_wb), - (ins GPR:$src1, GPR:$src2, GPR:$base, am3offset:$offset), - StMiscFrm, IIC_iStore_d_ru, - "strd", "\t$src1, $src2, [$base, $offset]!", - "$base = $base_wb", []> { - bits<4> src1; - bits<4> base; - bits<10> offset; - let Inst{23} = offset{8}; // U bit - let Inst{22} = offset{9}; // 1 == imm8, 0 == Rm - let Inst{19-16} = base; - let Inst{15-12} = src1; - let Inst{11-8} = offset{7-4}; - let Inst{3-0} = offset{3-0}; - +def STRD_PRE : AI3ldstidx<0b1111, 0, 1, 1, (outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rt2, addrmode3:$addr), + IndexModePre, StMiscFrm, IIC_iStore_d_ru, + "strd", "\t$Rt, $Rt2, $addr!", + "$addr.base = $Rn_wb", []> { + bits<14> addr; + let Inst{23} = addr{8}; // U bit + let Inst{22} = addr{13}; // 1 == imm8, 0 == Rm + 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 DecoderMethod = "DecodeAddrMode3Instruction"; + let AsmMatchConverter = "cvtStrdPre"; } -// For disassembly only -def STRD_POST: AI3stdpo<(outs GPR:$base_wb), - (ins GPR:$src1, GPR:$src2, GPR:$base, am3offset:$offset), - StMiscFrm, IIC_iStore_d_ru, - "strd", "\t$src1, $src2, [$base], $offset", - "$base = $base_wb", []> { - bits<4> src1; - bits<4> base; +def STRD_POST: AI3ldstidx<0b1111, 0, 1, 0, (outs GPR:$Rn_wb), + (ins GPR:$Rt, GPR:$Rt2, addr_offset_none:$addr, + am3offset:$offset), + IndexModePost, StMiscFrm, IIC_iStore_d_ru, + "strd", "\t$Rt, $Rt2, $addr, $offset", + "$addr.base = $Rn_wb", []> { bits<10> offset; - let Inst{23} = offset{8}; // U bit - let Inst{22} = offset{9}; // 1 == imm8, 0 == Rm - let Inst{19-16} = base; - let Inst{15-12} = src1; - let Inst{11-8} = offset{7-4}; - let Inst{3-0} = offset{3-0}; - + bits<4> addr; + let Inst{23} = offset{8}; // U bit + let Inst{22} = offset{9}; // 1 == imm8, 0 == Rm + 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 let DecoderMethod = "DecodeAddrMode3Instruction"; } } // mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1 diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 31d2b807edf..fc8a4847014 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -133,6 +133,8 @@ class ARMAsmParser : public MCTargetAsmParser { const SmallVectorImpl &); bool cvtLdrdPre(MCInst &Inst, unsigned Opcode, const SmallVectorImpl &); + bool cvtStrdPre(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &); bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode, const SmallVectorImpl &); @@ -2224,6 +2226,24 @@ cvtLdrdPre(MCInst &Inst, unsigned Opcode, return true; } +/// cvtStrdPre - 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:: +cvtStrdPre(MCInst &Inst, unsigned Opcode, + const SmallVectorImpl &Operands) { + // Create a writeback register dummy placeholder. + Inst.addOperand(MCOperand::CreateImm(0)); + // Rt, Rt2 + ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1); + ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1); + // addr + ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3); + // pred + ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2); + 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. @@ -2850,7 +2870,15 @@ validateInstruction(MCInst &Inst, "destination operands must be sequential"); return false; } - case ARM::STRD: + case ARM::STRD: { + // Rt2 must be Rt + 1. + unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg()); + unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg()); + if (Rt2 != Rt + 1) + return Error(Operands[3]->getStartLoc(), + "source operands must be sequential"); + return false; + } case ARM::STRD_PRE: case ARM::STRD_POST: case ARM::STREXD: { @@ -2858,7 +2886,7 @@ validateInstruction(MCInst &Inst, unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg()); unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg()); if (Rt2 != Rt + 1) - return Error(Operands[4]->getStartLoc(), + return Error(Operands[3]->getStartLoc(), "source operands must be sequential"); return false; } diff --git a/test/MC/ARM/arm-memory-instructions.s b/test/MC/ARM/arm-memory-instructions.s index 8af12063e02..49b4216f888 100644 --- a/test/MC/ARM/arm-memory-instructions.s +++ b/test/MC/ARM/arm-memory-instructions.s @@ -389,3 +389,42 @@ _func: @ CHECK: strbt r5, [r6], #-13 @ encoding: [0x0d,0x50,0x66,0xe4] @ CHECK: strbt r4, [r9], r5 @ encoding: [0x05,0x40,0xe9,0xe6] @ CHECK: strbt r3, [r8], -r2, lsl #3 @ encoding: [0x82,0x31,0x68,0xe6] + + +@------------------------------------------------------------------------------ +@ STRD (immediate) +@------------------------------------------------------------------------------ + strd r1, r2, [r4] + strd r2, r3, [r6, #1] + strd r3, r4, [r7, #22]! + strd r4, r5, [r8], #7 + strd r5, r6, [sp], #0 + strd r6, r7, [lr], #+0 + strd r7, r8, [r9], #-0 + +@ CHECK: strd r1, r2, [r4] @ encoding: [0xf0,0x10,0xc4,0xe1] +@ CHECK: strd r2, r3, [r6, #1] @ encoding: [0xf1,0x20,0xc6,0xe1] +@ CHECK: strd r3, r4, [r7, #22]! @ encoding: [0xf6,0x31,0xe7,0xe1] +@ CHECK: strd r4, r5, [r8], #7 @ encoding: [0xf7,0x40,0xc8,0xe0] +@ CHECK: strd r5, r6, [sp], #0 @ encoding: [0xf0,0x50,0xcd,0xe0] +@ CHECK: strd r6, r7, [lr], #0 @ encoding: [0xf0,0x60,0xce,0xe0] +@ CHECK: strd r7, r8, [r9], #-0 @ encoding: [0xf0,0x70,0x49,0xe0] + + +@------------------------------------------------------------------------------ +@ FIXME: STRD (label) +@------------------------------------------------------------------------------ + +@------------------------------------------------------------------------------ +@ STRD (register) +@------------------------------------------------------------------------------ + strd r8, r9, [r4, r1] + strd r7, r8, [r3, r9]! + strd r6, r7, [r5], r8 + strd r5, r6, [r12], -r10 + +@ CHECK: strd r8, r9, [r4, r1] @ encoding: [0xf1,0x80,0x84,0xe1] +@ CHECK: strd r7, r8, [r3, r9]! @ encoding: [0xf9,0x70,0xa3,0xe1] +@ CHECK: strd r6, r7, [r5], r8 @ encoding: [0xf8,0x60,0x85,0xe0] +@ CHECK: strd r5, r6, [r12], -r10 @ encoding: [0xfa,0x50,0x0c,0xe0] +