diff options
author | Jim Grosbach <grosbach@apple.com> | 2011-10-24 21:45:13 +0000 |
---|---|---|
committer | Jim Grosbach <grosbach@apple.com> | 2011-10-24 21:45:13 +0000 |
commit | 10b90a9bbf7dcae1568c03a03f9606f5395f2144 (patch) | |
tree | 36680fbe6bc814e3894e8b96ac92e548a5d30a83 /lib | |
parent | 0135fe1854bef035efea1e3113dc6a127ef6e51e (diff) | |
download | external_llvm-10b90a9bbf7dcae1568c03a03f9606f5395f2144.zip external_llvm-10b90a9bbf7dcae1568c03a03f9606f5395f2144.tar.gz external_llvm-10b90a9bbf7dcae1568c03a03f9606f5395f2144.tar.bz2 |
ARM refactor am6offset usage for VLD1.
Split am6offset into fixed and register offset variants so the instruction
encodings are explicit rather than relying an a magic reg0 marker.
Needed to being able to parse these.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@142853 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/ARM/ARMBaseInstrInfo.cpp | 24 | ||||
-rw-r--r-- | lib/Target/ARM/ARMExpandPseudoInsts.cpp | 38 | ||||
-rw-r--r-- | lib/Target/ARM/ARMISelDAGToDAG.cpp | 42 | ||||
-rw-r--r-- | lib/Target/ARM/ARMInstrNEON.td | 85 | ||||
-rw-r--r-- | lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 63 |
5 files changed, 181 insertions, 71 deletions
diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 24cd228..211f937 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -2401,10 +2401,14 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, case ARM::VLD1q16: case ARM::VLD1q32: case ARM::VLD1q64: - case ARM::VLD1q8_UPD: - case ARM::VLD1q16_UPD: - case ARM::VLD1q32_UPD: - case ARM::VLD1q64_UPD: + case ARM::VLD1q8wb_fixed: + case ARM::VLD1q16wb_fixed: + case ARM::VLD1q32wb_fixed: + case ARM::VLD1q64wb_fixed: + case ARM::VLD1q8wb_register: + case ARM::VLD1q16wb_register: + case ARM::VLD1q32wb_register: + case ARM::VLD1q64wb_register: case ARM::VLD2d8: case ARM::VLD2d16: case ARM::VLD2d32: @@ -2562,10 +2566,14 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, case ARM::VLD1q16Pseudo: case ARM::VLD1q32Pseudo: case ARM::VLD1q64Pseudo: - case ARM::VLD1q8Pseudo_UPD: - case ARM::VLD1q16Pseudo_UPD: - case ARM::VLD1q32Pseudo_UPD: - case ARM::VLD1q64Pseudo_UPD: + case ARM::VLD1q8PseudoWB_register: + case ARM::VLD1q16PseudoWB_register: + case ARM::VLD1q32PseudoWB_register: + case ARM::VLD1q64PseudoWB_register: + case ARM::VLD1q8PseudoWB_fixed: + case ARM::VLD1q16PseudoWB_fixed: + case ARM::VLD1q32PseudoWB_fixed: + case ARM::VLD1q64PseudoWB_fixed: case ARM::VLD2d8Pseudo: case ARM::VLD2d16Pseudo: case ARM::VLD2d32Pseudo: diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp index 77bad0c..c8f9756 100644 --- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -102,7 +102,7 @@ namespace { unsigned PseudoOpc; unsigned RealOpc; bool IsLoad; - bool HasWriteBack; + bool HasWritebackOperand; NEONRegSpacing RegSpacing; unsigned char NumRegs; // D registers loaded or stored unsigned char RegElts; // elements per D register; used for lane ops @@ -148,13 +148,17 @@ static const NEONLdStTableEntry NEONLdStTable[] = { { ARM::VLD1d64TPseudo_UPD, ARM::VLD1d64T_UPD, true, true, SingleSpc, 3, 1 ,false}, { ARM::VLD1q16Pseudo, ARM::VLD1q16, true, false, SingleSpc, 2, 4 ,false}, -{ ARM::VLD1q16Pseudo_UPD, ARM::VLD1q16_UPD, true, true, SingleSpc, 2, 4 ,false}, +{ ARM::VLD1q16PseudoWB_fixed, ARM::VLD1q16wb_fixed,true,false,SingleSpc, 2, 4 ,false}, +{ ARM::VLD1q16PseudoWB_register, ARM::VLD1q16wb_register, true, true, SingleSpc, 2, 4 ,false}, { ARM::VLD1q32Pseudo, ARM::VLD1q32, true, false, SingleSpc, 2, 2 ,false}, -{ ARM::VLD1q32Pseudo_UPD, ARM::VLD1q32_UPD, true, true, SingleSpc, 2, 2 ,false}, +{ ARM::VLD1q32PseudoWB_fixed, ARM::VLD1q32wb_fixed,true,false,SingleSpc, 2, 2 ,false}, +{ ARM::VLD1q32PseudoWB_register, ARM::VLD1q32wb_register, true, true, SingleSpc, 2, 2 ,false}, { ARM::VLD1q64Pseudo, ARM::VLD1q64, true, false, SingleSpc, 2, 1 ,false}, -{ ARM::VLD1q64Pseudo_UPD, ARM::VLD1q64_UPD, true, true, SingleSpc, 2, 1 ,false}, +{ ARM::VLD1q64PseudoWB_fixed, ARM::VLD1q64wb_fixed,true,false,SingleSpc, 2, 2 ,false}, +{ ARM::VLD1q64PseudoWB_register, ARM::VLD1q64wb_register, true, true, SingleSpc, 2, 1 ,false}, { ARM::VLD1q8Pseudo, ARM::VLD1q8, true, false, SingleSpc, 2, 8 ,false}, -{ ARM::VLD1q8Pseudo_UPD, ARM::VLD1q8_UPD, true, true, SingleSpc, 2, 8 ,false}, +{ ARM::VLD1q8PseudoWB_fixed, ARM::VLD1q8wb_fixed,true,false, SingleSpc, 2, 8 ,false}, +{ ARM::VLD1q8PseudoWB_register, ARM::VLD1q8wb_register,true,true,SingleSpc,2,8,false}, { ARM::VLD2DUPd16Pseudo, ARM::VLD2DUPd16, true, false, SingleSpc, 2, 4,true}, { ARM::VLD2DUPd16Pseudo_UPD, ARM::VLD2DUPd16_UPD, true, true, SingleSpc, 2, 4,true}, @@ -436,14 +440,14 @@ void ARMExpandPseudo::ExpandVLD(MachineBasicBlock::iterator &MBBI) { if (NumRegs > 3 && TableEntry->copyAllListRegs) MIB.addReg(D3, RegState::Define | getDeadRegState(DstIsDead)); - if (TableEntry->HasWriteBack) + if (TableEntry->HasWritebackOperand) MIB.addOperand(MI.getOperand(OpIdx++)); // Copy the addrmode6 operands. MIB.addOperand(MI.getOperand(OpIdx++)); MIB.addOperand(MI.getOperand(OpIdx++)); // Copy the am6offset operand. - if (TableEntry->HasWriteBack) + if (TableEntry->HasWritebackOperand) MIB.addOperand(MI.getOperand(OpIdx++)); // For an instruction writing double-spaced subregs, the pseudo instruction @@ -488,14 +492,14 @@ void ARMExpandPseudo::ExpandVST(MachineBasicBlock::iterator &MBBI) { MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(TableEntry->RealOpc)); unsigned OpIdx = 0; - if (TableEntry->HasWriteBack) + if (TableEntry->HasWritebackOperand) MIB.addOperand(MI.getOperand(OpIdx++)); // Copy the addrmode6 operands. MIB.addOperand(MI.getOperand(OpIdx++)); MIB.addOperand(MI.getOperand(OpIdx++)); // Copy the am6offset operand. - if (TableEntry->HasWriteBack) + if (TableEntry->HasWritebackOperand) MIB.addOperand(MI.getOperand(OpIdx++)); bool SrcIsKill = MI.getOperand(OpIdx).isKill(); @@ -565,14 +569,14 @@ void ARMExpandPseudo::ExpandLaneOp(MachineBasicBlock::iterator &MBBI) { MIB.addReg(D3, RegState::Define | getDeadRegState(DstIsDead)); } - if (TableEntry->HasWriteBack) + if (TableEntry->HasWritebackOperand) MIB.addOperand(MI.getOperand(OpIdx++)); // Copy the addrmode6 operands. MIB.addOperand(MI.getOperand(OpIdx++)); MIB.addOperand(MI.getOperand(OpIdx++)); // Copy the am6offset operand. - if (TableEntry->HasWriteBack) + if (TableEntry->HasWritebackOperand) MIB.addOperand(MI.getOperand(OpIdx++)); // Grab the super-register source. @@ -1068,10 +1072,14 @@ bool ARMExpandPseudo::ExpandMI(MachineBasicBlock &MBB, case ARM::VLD1q16Pseudo: case ARM::VLD1q32Pseudo: case ARM::VLD1q64Pseudo: - case ARM::VLD1q8Pseudo_UPD: - case ARM::VLD1q16Pseudo_UPD: - case ARM::VLD1q32Pseudo_UPD: - case ARM::VLD1q64Pseudo_UPD: + case ARM::VLD1q8PseudoWB_register: + case ARM::VLD1q16PseudoWB_register: + case ARM::VLD1q32PseudoWB_register: + case ARM::VLD1q64PseudoWB_register: + case ARM::VLD1q8PseudoWB_fixed: + case ARM::VLD1q16PseudoWB_fixed: + case ARM::VLD1q32PseudoWB_fixed: + case ARM::VLD1q64PseudoWB_fixed: case ARM::VLD2d8Pseudo: case ARM::VLD2d16Pseudo: case ARM::VLD2d32Pseudo: diff --git a/lib/Target/ARM/ARMISelDAGToDAG.cpp b/lib/Target/ARM/ARMISelDAGToDAG.cpp index ca777bd..8a1b618 100644 --- a/lib/Target/ARM/ARMISelDAGToDAG.cpp +++ b/lib/Target/ARM/ARMISelDAGToDAG.cpp @@ -1549,6 +1549,23 @@ SDValue ARMDAGToDAGISel::GetVLDSTAlign(SDValue Align, unsigned NumVecs, return CurDAG->getTargetConstant(Alignment, MVT::i32); } +// Get the register stride update opcode of a VLD/VST instruction that +// is otherwise equivalent to the given fixed stride updating instruction. +static unsigned getVLDSTRegisterUpdateOpcode(unsigned Opc) { + switch (Opc) { + default: break; + case ARM::VLD1d8wb_fixed: return ARM::VLD1d8wb_register; + case ARM::VLD1d16wb_fixed: return ARM::VLD1d16wb_register; + case ARM::VLD1d32wb_fixed: return ARM::VLD1d32wb_register; + case ARM::VLD1d64wb_fixed: return ARM::VLD1d64wb_register; + case ARM::VLD1q8wb_fixed: return ARM::VLD1q8wb_register; + case ARM::VLD1q16wb_fixed: return ARM::VLD1q16wb_register; + case ARM::VLD1q32wb_fixed: return ARM::VLD1q32wb_register; + case ARM::VLD1q64wb_fixed: return ARM::VLD1q64wb_register; + } + return Opc; // If not one we handle, return it unchanged. +} + SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs, unsigned *DOpcodes, unsigned *QOpcodes0, unsigned *QOpcodes1) { @@ -1612,7 +1629,14 @@ SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, bool isUpdating, unsigned NumVecs, Ops.push_back(Align); if (isUpdating) { SDValue Inc = N->getOperand(AddrOpIdx + 1); - Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc); + // FIXME: VLD1 fixed increment doesn't need Reg0. Remove the reg0 + // case entirely when the rest are updated to that form, too. + // Do that before committing this change. Likewise, the opcode + // update call will become unconditional. + if (NumVecs == 1 && !isa<ConstantSDNode>(Inc.getNode())) + Opc = getVLDSTRegisterUpdateOpcode(Opc); + if (NumVecs != 1 || !isa<ConstantSDNode>(Inc.getNode())) + Ops.push_back(isa<ConstantSDNode>(Inc.getNode()) ? Reg0 : Inc); } Ops.push_back(Pred); Ops.push_back(Reg0); @@ -2750,16 +2774,18 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) { } case ARMISD::VLD1_UPD: { - unsigned DOpcodes[] = { ARM::VLD1d8_UPD, ARM::VLD1d16_UPD, - ARM::VLD1d32_UPD, ARM::VLD1d64_UPD }; - unsigned QOpcodes[] = { ARM::VLD1q8Pseudo_UPD, ARM::VLD1q16Pseudo_UPD, - ARM::VLD1q32Pseudo_UPD, ARM::VLD1q64Pseudo_UPD }; + unsigned DOpcodes[] = { ARM::VLD1d8wb_fixed, ARM::VLD1d16wb_fixed, + ARM::VLD1d32wb_fixed, ARM::VLD1d64wb_fixed }; + unsigned QOpcodes[] = { ARM::VLD1q8PseudoWB_fixed, + ARM::VLD1q16PseudoWB_fixed, + ARM::VLD1q32PseudoWB_fixed, + ARM::VLD1q64PseudoWB_fixed }; return SelectVLD(N, true, 1, DOpcodes, QOpcodes, 0); } case ARMISD::VLD2_UPD: { unsigned DOpcodes[] = { ARM::VLD2d8Pseudo_UPD, ARM::VLD2d16Pseudo_UPD, - ARM::VLD2d32Pseudo_UPD, ARM::VLD1q64Pseudo_UPD }; + ARM::VLD2d32Pseudo_UPD, ARM::VLD1q64PseudoWB_fixed}; unsigned QOpcodes[] = { ARM::VLD2q8Pseudo_UPD, ARM::VLD2q16Pseudo_UPD, ARM::VLD2q32Pseudo_UPD }; return SelectVLD(N, true, 2, DOpcodes, QOpcodes, 0); @@ -2767,7 +2793,7 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) { case ARMISD::VLD3_UPD: { unsigned DOpcodes[] = { ARM::VLD3d8Pseudo_UPD, ARM::VLD3d16Pseudo_UPD, - ARM::VLD3d32Pseudo_UPD, ARM::VLD1d64TPseudo_UPD }; + ARM::VLD3d32Pseudo_UPD, ARM::VLD1q64PseudoWB_fixed}; unsigned QOpcodes0[] = { ARM::VLD3q8Pseudo_UPD, ARM::VLD3q16Pseudo_UPD, ARM::VLD3q32Pseudo_UPD }; @@ -2779,7 +2805,7 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) { case ARMISD::VLD4_UPD: { unsigned DOpcodes[] = { ARM::VLD4d8Pseudo_UPD, ARM::VLD4d16Pseudo_UPD, - ARM::VLD4d32Pseudo_UPD, ARM::VLD1d64QPseudo_UPD }; + ARM::VLD4d32Pseudo_UPD, ARM::VLD1q64PseudoWB_fixed}; unsigned QOpcodes0[] = { ARM::VLD4q8Pseudo_UPD, ARM::VLD4q16Pseudo_UPD, ARM::VLD4q32Pseudo_UPD }; diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td index 1efe681..9bea53b 100644 --- a/lib/Target/ARM/ARMInstrNEON.td +++ b/lib/Target/ARM/ARMInstrNEON.td @@ -259,6 +259,14 @@ class VLDQWBPseudo<InstrItinClass itin> : PseudoNLdSt<(outs QPR:$dst, GPR:$wb), (ins addrmode6:$addr, am6offset:$offset), itin, "$addr.addr = $wb">; +class VLDQWBfixedPseudo<InstrItinClass itin> + : PseudoNLdSt<(outs QPR:$dst, GPR:$wb), + (ins addrmode6:$addr), itin, + "$addr.addr = $wb">; +class VLDQWBregisterPseudo<InstrItinClass itin> + : PseudoNLdSt<(outs QPR:$dst, GPR:$wb), + (ins addrmode6:$addr, rGPR:$offset), itin, + "$addr.addr = $wb">; class VLDQQPseudo<InstrItinClass itin> : PseudoNLdSt<(outs QQPR:$dst), (ins addrmode6:$addr), itin, "">; class VLDQQWBPseudo<InstrItinClass itin> @@ -309,37 +317,58 @@ def VLD1q32Pseudo : VLDQPseudo<IIC_VLD1x2>; def VLD1q64Pseudo : VLDQPseudo<IIC_VLD1x2>; // ...with address register writeback: -class VLD1DWB<bits<4> op7_4, string Dt> - : NLdSt<0,0b10,0b0111,op7_4, (outs DPR:$Vd, GPR:$wb), - (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD1u, - "vld1", Dt, "\\{$Vd\\}, $Rn$Rm", - "$Rn.addr = $wb", []> { - let Inst{4} = Rn{4}; - let DecoderMethod = "DecodeVLDInstruction"; +multiclass VLD1DWB<bits<4> op7_4, string Dt> { + def _fixed : NLdSt<0,0b10, 0b0111,op7_4, (outs VecListOneD:$Vd, GPR:$wb), + (ins addrmode6:$Rn), IIC_VLD1u, + "vld1", Dt, "$Vd, $Rn!", + "$Rn.addr = $wb", []> { + let Rm = 0b1101; // NLdSt will assign to the right encoding bits. + let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLDInstruction"; + } + def _register : NLdSt<0,0b10,0b0111,op7_4, (outs VecListOneD:$Vd, GPR:$wb), + (ins addrmode6:$Rn, rGPR:$Rm), IIC_VLD1u, + "vld1", Dt, "$Vd, $Rn, $Rm", + "$Rn.addr = $wb", []> { + let Inst{4} = Rn{4}; + let DecoderMethod = "DecodeVLDInstruction"; + } } -class VLD1QWB<bits<4> op7_4, string Dt> - : NLdSt<0,0b10,0b1010,op7_4, (outs VecListTwoD:$Vd, GPR:$wb), - (ins addrmode6:$Rn, am6offset:$Rm), IIC_VLD1x2u, - "vld1", Dt, "$Vd, $Rn$Rm", - "$Rn.addr = $wb", []> { - let Inst{5-4} = Rn{5-4}; - let DecoderMethod = "DecodeVLDInstruction"; +multiclass VLD1QWB<bits<4> op7_4, string Dt> { + def _fixed : NLdSt<0,0b10,0b1010,op7_4, (outs VecListTwoD:$Vd, GPR:$wb), + (ins addrmode6:$Rn), IIC_VLD1x2u, + "vld1", Dt, "$Vd, $Rn!", + "$Rn.addr = $wb", []> { + let Rm = 0b1101; // NLdSt will assign to the right encoding bits. + let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; + } + def _register : NLdSt<0,0b10,0b1010,op7_4, (outs VecListTwoD:$Vd, GPR:$wb), + (ins addrmode6:$Rn, rGPR:$Rm), IIC_VLD1x2u, + "vld1", Dt, "$Vd, $Rn, $Rm", + "$Rn.addr = $wb", []> { + let Inst{5-4} = Rn{5-4}; + let DecoderMethod = "DecodeVLDInstruction"; + } } -def VLD1d8_UPD : VLD1DWB<{0,0,0,?}, "8">; -def VLD1d16_UPD : VLD1DWB<{0,1,0,?}, "16">; -def VLD1d32_UPD : VLD1DWB<{1,0,0,?}, "32">; -def VLD1d64_UPD : VLD1DWB<{1,1,0,?}, "64">; - -def VLD1q8_UPD : VLD1QWB<{0,0,?,?}, "8">; -def VLD1q16_UPD : VLD1QWB<{0,1,?,?}, "16">; -def VLD1q32_UPD : VLD1QWB<{1,0,?,?}, "32">; -def VLD1q64_UPD : VLD1QWB<{1,1,?,?}, "64">; - -def VLD1q8Pseudo_UPD : VLDQWBPseudo<IIC_VLD1x2u>; -def VLD1q16Pseudo_UPD : VLDQWBPseudo<IIC_VLD1x2u>; -def VLD1q32Pseudo_UPD : VLDQWBPseudo<IIC_VLD1x2u>; -def VLD1q64Pseudo_UPD : VLDQWBPseudo<IIC_VLD1x2u>; +defm VLD1d8wb : VLD1DWB<{0,0,0,?}, "8">; +defm VLD1d16wb : VLD1DWB<{0,1,0,?}, "16">; +defm VLD1d32wb : VLD1DWB<{1,0,0,?}, "32">; +defm VLD1d64wb : VLD1DWB<{1,1,0,?}, "64">; +defm VLD1q8wb : VLD1QWB<{0,0,?,?}, "8">; +defm VLD1q16wb : VLD1QWB<{0,1,?,?}, "16">; +defm VLD1q32wb : VLD1QWB<{1,0,?,?}, "32">; +defm VLD1q64wb : VLD1QWB<{1,1,?,?}, "64">; + +def VLD1q8PseudoWB_fixed : VLDQWBfixedPseudo<IIC_VLD1x2u>; +def VLD1q16PseudoWB_fixed : VLDQWBfixedPseudo<IIC_VLD1x2u>; +def VLD1q32PseudoWB_fixed : VLDQWBfixedPseudo<IIC_VLD1x2u>; +def VLD1q64PseudoWB_fixed : VLDQWBfixedPseudo<IIC_VLD1x2u>; +def VLD1q8PseudoWB_register : VLDQWBregisterPseudo<IIC_VLD1x2u>; +def VLD1q16PseudoWB_register : VLDQWBregisterPseudo<IIC_VLD1x2u>; +def VLD1q32PseudoWB_register : VLDQWBregisterPseudo<IIC_VLD1x2u>; +def VLD1q64PseudoWB_register : VLDQWBregisterPseudo<IIC_VLD1x2u>; // ...with 3 registers class VLD1D3<bits<4> op7_4, string Dt> diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index bc9a09f..d6b9260 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -2054,14 +2054,22 @@ static DecodeStatus DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Insn, // Writeback operand switch (Inst.getOpcode()) { - case ARM::VLD1d8_UPD: - case ARM::VLD1d16_UPD: - case ARM::VLD1d32_UPD: - case ARM::VLD1d64_UPD: - case ARM::VLD1q8_UPD: - case ARM::VLD1q16_UPD: - case ARM::VLD1q32_UPD: - case ARM::VLD1q64_UPD: + case ARM::VLD1d8wb_fixed: + case ARM::VLD1d16wb_fixed: + case ARM::VLD1d32wb_fixed: + case ARM::VLD1d64wb_fixed: + case ARM::VLD1d8wb_register: + case ARM::VLD1d16wb_register: + case ARM::VLD1d32wb_register: + case ARM::VLD1d64wb_register: + case ARM::VLD1q8wb_fixed: + case ARM::VLD1q16wb_fixed: + case ARM::VLD1q32wb_fixed: + case ARM::VLD1q64wb_fixed: + case ARM::VLD1q8wb_register: + case ARM::VLD1q16wb_register: + case ARM::VLD1q32wb_register: + case ARM::VLD1q64wb_register: case ARM::VLD1d8T_UPD: case ARM::VLD1d16T_UPD: case ARM::VLD1d32T_UPD: @@ -2103,11 +2111,42 @@ static DecodeStatus DecodeVLDInstruction(llvm::MCInst &Inst, unsigned Insn, return MCDisassembler::Fail; // AddrMode6 Offset (register) - if (Rm == 0xD) - Inst.addOperand(MCOperand::CreateReg(0)); - else if (Rm != 0xF) { - if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder))) + switch (Inst.getOpcode()) { + default: + // The below have been updated to have explicit am6offset split + // between fixed and register offset. For those instructions not + // yet updated, we need to add an additional reg0 operand for the + // fixed variant. + // + // The fixed offset encodes as Rm == 0xd, so we check for that. + if (Rm == 0xd) { + Inst.addOperand(MCOperand::CreateReg(0)); + break; + } + // Fall through to handle the register offset variant. + case ARM::VLD1d8wb_fixed: + case ARM::VLD1d16wb_fixed: + case ARM::VLD1d32wb_fixed: + case ARM::VLD1d64wb_fixed: + case ARM::VLD1d8wb_register: + case ARM::VLD1d16wb_register: + case ARM::VLD1d32wb_register: + case ARM::VLD1d64wb_register: + case ARM::VLD1q8wb_fixed: + case ARM::VLD1q16wb_fixed: + case ARM::VLD1q32wb_fixed: + case ARM::VLD1q64wb_fixed: + case ARM::VLD1q8wb_register: + case ARM::VLD1q16wb_register: + case ARM::VLD1q32wb_register: + case ARM::VLD1q64wb_register: + // The fixed offset post-increment encodes Rm == 0xd. The no-writeback + // variant encodes Rm == 0xf. Anything else is a register offset post- + // increment and we need to add the register operand to the instruction. + if (Rm != 0xD && Rm != 0xF && + !Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder))) return MCDisassembler::Fail; + break; } return S; |