diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td index 9e79047b465..6937392bdef 100644 --- a/lib/Target/ARM/ARMInstrNEON.td +++ b/lib/Target/ARM/ARMInstrNEON.td @@ -218,9 +218,9 @@ class VLD1DWB op7_4, string Dt> "vld1", Dt, "\\{$dst\\}, $addr$offset", "$addr.addr = $wb", []>; class VLD1QWB op7_4, string Dt> - : NLdSt<0,0b10,0b1010,op7_4, (outs QPR:$dst, GPR:$wb), + : NLdSt<0,0b10,0b1010,op7_4, (outs DPR:$dst1, DPR:$dst2, GPR:$wb), (ins addrmode6:$addr, am6offset:$offset), IIC_VLD2, - "vld1", Dt, "${dst:dregpair}, $addr$offset", + "vld1", Dt, "\\{$dst1, $dst2\\}, $addr$offset", "$addr.addr = $wb", []>; def VLD1d8_UPD : VLD1DWB<0b0000, "8">; @@ -675,8 +675,9 @@ class VST1DWB op7_4, string Dt> "vst1", Dt, "\\{$src\\}, $addr$offset", "$addr.addr = $wb", []>; class VST1QWB op7_4, string Dt> : NLdSt<0, 0b00, 0b1010, op7_4, (outs GPR:$wb), - (ins addrmode6:$addr, am6offset:$offset, QPR:$src), IIC_VST, - "vst1", Dt, "${src:dregpair}, $addr$offset", "$addr.addr = $wb", []>; + (ins addrmode6:$addr, am6offset:$offset, DPR:$src1, DPR:$src2), + IIC_VST, "vst1", Dt, "\\{$src1, $src2\\}, $addr$offset", + "$addr.addr = $wb", []>; def VST1d8_UPD : VST1DWB<0b0000, "8">; def VST1d16_UPD : VST1DWB<0b0100, "16">; diff --git a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp index ef4897e7db4..000108a7cc7 100644 --- a/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp @@ -29,73 +29,27 @@ using namespace llvm; #undef MachineInstr #undef ARMAsmPrinter -static unsigned NextReg(unsigned Reg) { - switch (Reg) { +// Get the constituent sub-regs for a dregpair from a Q register. +static std::pair GetDRegPair(unsigned QReg) { + switch (QReg) { default: assert(0 && "Unexpected register enum"); - - case ARM::D0: - return ARM::D1; - case ARM::D1: - return ARM::D2; - case ARM::D2: - return ARM::D3; - case ARM::D3: - return ARM::D4; - case ARM::D4: - return ARM::D5; - case ARM::D5: - return ARM::D6; - case ARM::D6: - return ARM::D7; - case ARM::D7: - return ARM::D8; - case ARM::D8: - return ARM::D9; - case ARM::D9: - return ARM::D10; - case ARM::D10: - return ARM::D11; - case ARM::D11: - return ARM::D12; - case ARM::D12: - return ARM::D13; - case ARM::D13: - return ARM::D14; - case ARM::D14: - return ARM::D15; - case ARM::D15: - return ARM::D16; - case ARM::D16: - return ARM::D17; - case ARM::D17: - return ARM::D18; - case ARM::D18: - return ARM::D19; - case ARM::D19: - return ARM::D20; - case ARM::D20: - return ARM::D21; - case ARM::D21: - return ARM::D22; - case ARM::D22: - return ARM::D23; - case ARM::D23: - return ARM::D24; - case ARM::D24: - return ARM::D25; - case ARM::D25: - return ARM::D26; - case ARM::D26: - return ARM::D27; - case ARM::D27: - return ARM::D28; - case ARM::D28: - return ARM::D29; - case ARM::D29: - return ARM::D30; - case ARM::D30: - return ARM::D31; + case ARM::Q0: return std::pair(ARM::D0, ARM::D1); + case ARM::Q1: return std::pair(ARM::D2, ARM::D3); + case ARM::Q2: return std::pair(ARM::D4, ARM::D5); + case ARM::Q3: return std::pair(ARM::D6, ARM::D7); + case ARM::Q4: return std::pair(ARM::D8, ARM::D9); + case ARM::Q5: return std::pair(ARM::D10, ARM::D11); + case ARM::Q6: return std::pair(ARM::D12, ARM::D13); + case ARM::Q7: return std::pair(ARM::D14, ARM::D15); + case ARM::Q8: return std::pair(ARM::D16, ARM::D17); + case ARM::Q9: return std::pair(ARM::D18, ARM::D19); + case ARM::Q10: return std::pair(ARM::D20, ARM::D21); + case ARM::Q11: return std::pair(ARM::D22, ARM::D23); + case ARM::Q12: return std::pair(ARM::D24, ARM::D25); + case ARM::Q13: return std::pair(ARM::D26, ARM::D27); + case ARM::Q14: return std::pair(ARM::D28, ARM::D29); + case ARM::Q15: return std::pair(ARM::D30, ARM::D31); } } @@ -189,19 +143,11 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, if (Op.isReg()) { unsigned Reg = Op.getReg(); if (Modifier && strcmp(Modifier, "dregpair") == 0) { - O << '{' << getRegisterName(Reg) << ", " - << getRegisterName(NextReg(Reg)) << '}'; -#if 0 - // FIXME: Breaks e.g. ARM/vmul.ll. - assert(0); - /* - unsigned DRegLo = TRI->getSubReg(Reg, ARM::dsub_0); - unsigned DRegHi = TRI->getSubReg(Reg, ARM::dsub_1); - O << '{' - << getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi) - << '}';*/ -#endif + std::pair dregpair = GetDRegPair(Reg); + O << '{' << getRegisterName(dregpair.first) << ", " + << getRegisterName(dregpair.second) << '}'; } else if (Modifier && strcmp(Modifier, "lane") == 0) { + // FIXME assert(0); /* unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg); diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp index 9f493b9aee0..edfb20766ce 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp @@ -79,22 +79,9 @@ const char *ARMUtils::OpcodeName(unsigned Opcode) { } // Return the register enum Based on RegClass and the raw register number. -// For DRegPair, see comments below. // FIXME: Auto-gened? -static unsigned getRegisterEnum(BO B, unsigned RegClassID, unsigned RawRegister, - bool DRegPair = false) { - - if (DRegPair && RegClassID == ARM::QPRRegClassID) { - // LLVM expects { Dd, Dd+1 } to form a super register; this is not specified - // in the ARM Architecture Manual as far as I understand it (A8.6.307). - // Therefore, we morph the RegClassID to be the sub register class and don't - // subsequently transform the RawRegister encoding when calculating RegNum. - // - // See also ARMinstPrinter::printOperand() wrt "dregpair" modifier part - // where this workaround is meant for. - RegClassID = ARM::DPRRegClassID; - } - +static unsigned +getRegisterEnum(BO B, unsigned RegClassID, unsigned RawRegister) { // For this purpose, we can treat rGPR as if it were GPR. if (RegClassID == ARM::rGPRRegClassID) RegClassID = ARM::GPRRegClassID; @@ -2201,22 +2188,6 @@ static unsigned decodeN3VImm(uint32_t insn) { return (insn >> 8) & 0xF; } -static bool UseDRegPair(unsigned Opcode) { - switch (Opcode) { - default: - return false; - case ARM::VLD1q8_UPD: - case ARM::VLD1q16_UPD: - case ARM::VLD1q32_UPD: - case ARM::VLD1q64_UPD: - case ARM::VST1q8_UPD: - case ARM::VST1q16_UPD: - case ARM::VST1q32_UPD: - case ARM::VST1q64_UPD: - return true; - } -} - // VLD* // D[d] D[d2] ... Rn [TIED_TO Rn] align [Rm] // VLD*LN* @@ -2243,10 +2214,9 @@ static bool DisassembleNLdSt0(MCInst &MI, unsigned Opcode, uint32_t insn, // We have homogeneous NEON registers for Load/Store. unsigned RegClass = 0; - bool DRegPair = UseDRegPair(Opcode); // Double-spaced registers have increments of 2. - unsigned Inc = (DblSpaced || DRegPair) ? 2 : 1; + unsigned Inc = DblSpaced ? 2 : 1; unsigned Rn = decodeRn(insn); unsigned Rm = decodeRm(insn); @@ -2292,7 +2262,7 @@ static bool DisassembleNLdSt0(MCInst &MI, unsigned Opcode, uint32_t insn, RegClass = OpInfo[OpIdx].RegClass; while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) { MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, RegClass, Rd, DRegPair))); + getRegisterEnum(B, RegClass, Rd))); Rd += Inc; ++OpIdx; } @@ -2311,7 +2281,7 @@ static bool DisassembleNLdSt0(MCInst &MI, unsigned Opcode, uint32_t insn, while (OpIdx < NumOps && (unsigned)OpInfo[OpIdx].RegClass == RegClass) { MI.addOperand(MCOperand::CreateReg( - getRegisterEnum(B, RegClass, Rd, DRegPair))); + getRegisterEnum(B, RegClass, Rd))); Rd += Inc; ++OpIdx; } diff --git a/test/MC/Disassembler/neon-tests.txt b/test/MC/Disassembler/neon-tests.txt index 826ff2272ef..35d4bd4da9e 100644 --- a/test/MC/Disassembler/neon-tests.txt +++ b/test/MC/Disassembler/neon-tests.txt @@ -9,10 +9,12 @@ # CHECK: vdup.32 q3, d1[0] 0x41 0x6c 0xb4 0xf3 -# VLD1q8_UPD (with ${dst:dregpair} operand) # CHECK: vld1.8 {d17, d18}, [r6], r5 0x05 0x1a 0x66 0xf4 +# CHECK: vld1.8 {d17, d18, d19}, [r6], r5 +0x05 0x16 0x66 0xf4 + # CHECK: vld4.8 {d0, d1, d2, d3}, [r2], r7 0x07 0x00 0x22 0xf4