From 73fe34a3ee866867d5028f4a9afa2c3b8efebcba Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Tue, 16 Nov 2010 01:16:36 +0000 Subject: [PATCH] Encode the multi-load/store instructions with their respective modes ('ia', 'db', 'ib', 'da') instead of having that mode as a separate field in the instruction. It's more convenient for the asm parser and much more readable for humans. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@119310 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMBaseInstrInfo.cpp | 215 ++++++++----- lib/Target/ARM/ARMExpandPseudoInsts.cpp | 29 +- lib/Target/ARM/ARMInstrInfo.td | 90 ++---- lib/Target/ARM/ARMInstrNEON.td | 16 +- lib/Target/ARM/ARMInstrThumb.td | 40 +-- lib/Target/ARM/ARMInstrThumb2.td | 80 +---- lib/Target/ARM/ARMInstrVFP.td | 119 ++----- lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 303 ++++++++++++++---- .../ARM/Disassembler/ARMDisassemblerCore.cpp | 32 +- .../ARM/Disassembler/ThumbDisassemblerCore.h | 71 ++-- lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp | 60 ++-- lib/Target/ARM/Thumb2SizeReduction.cpp | 43 +-- utils/TableGen/ARMDecoderEmitter.cpp | 10 +- 13 files changed, 567 insertions(+), 541 deletions(-) diff --git a/lib/Target/ARM/ARMBaseInstrInfo.cpp b/lib/Target/ARM/ARMBaseInstrInfo.cpp index 9bda8fd7011..89b21027336 100644 --- a/lib/Target/ARM/ARMBaseInstrInfo.cpp +++ b/lib/Target/ARM/ARMBaseInstrInfo.cpp @@ -697,10 +697,9 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, .addReg(SrcReg, getKillRegState(isKill)) .addMemOperand(MMO)); } else { - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMQ)) + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMQIA)) .addReg(SrcReg, getKillRegState(isKill)) .addFrameIndex(FI) - .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)) .addMemOperand(MMO)); } break; @@ -715,9 +714,8 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, .addMemOperand(MMO)); } else { MachineInstrBuilder MIB = - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMD)) - .addFrameIndex(FI) - .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia))) + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMDIA)) + .addFrameIndex(FI)) .addMemOperand(MMO); MIB = AddDReg(MIB, SrcReg, ARM::dsub_0, getKillRegState(isKill), TRI); MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0, TRI); @@ -727,9 +725,8 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, break; case ARM::QQQQPRRegClassID: { MachineInstrBuilder MIB = - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMD)) - .addFrameIndex(FI) - .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia))) + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VSTMDIA)) + .addFrameIndex(FI)) .addMemOperand(MMO); MIB = AddDReg(MIB, SrcReg, ARM::dsub_0, getKillRegState(isKill), TRI); MIB = AddDReg(MIB, SrcReg, ARM::dsub_1, 0, TRI); @@ -781,10 +778,8 @@ ARMBaseInstrInfo::isStoreToStackSlot(const MachineInstr *MI, return MI->getOperand(2).getReg(); } break; - case ARM::VSTMQ: + case ARM::VSTMQIA: if (MI->getOperand(1).isFI() && - MI->getOperand(2).isImm() && - MI->getOperand(2).getImm() == ARM_AM::getAM4ModeImm(ARM_AM::ia) && MI->getOperand(0).getSubReg() == 0) { FrameIndex = MI->getOperand(1).getIndex(); return MI->getOperand(0).getReg(); @@ -841,9 +836,8 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, .addFrameIndex(FI).addImm(16) .addMemOperand(MMO)); } else { - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMQ), DestReg) + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMQIA), DestReg) .addFrameIndex(FI) - .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)) .addMemOperand(MMO)); } break; @@ -855,9 +849,8 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, .addMemOperand(MMO)); } else { MachineInstrBuilder MIB = - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMD)) - .addFrameIndex(FI) - .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia))) + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMDIA)) + .addFrameIndex(FI)) .addMemOperand(MMO); MIB = AddDReg(MIB, DestReg, ARM::dsub_0, RegState::Define, TRI); MIB = AddDReg(MIB, DestReg, ARM::dsub_1, RegState::Define, TRI); @@ -867,9 +860,8 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, break; case ARM::QQQQPRRegClassID: { MachineInstrBuilder MIB = - AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMD)) - .addFrameIndex(FI) - .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia))) + AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDMDIA)) + .addFrameIndex(FI)) .addMemOperand(MMO); MIB = AddDReg(MIB, DestReg, ARM::dsub_0, RegState::Define, TRI); MIB = AddDReg(MIB, DestReg, ARM::dsub_1, RegState::Define, TRI); @@ -921,10 +913,8 @@ ARMBaseInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, return MI->getOperand(0).getReg(); } break; - case ARM::VLDMQ: + case ARM::VLDMQIA: if (MI->getOperand(1).isFI() && - MI->getOperand(2).isImm() && - MI->getOperand(2).getImm() == ARM_AM::getAM4ModeImm(ARM_AM::ia) && MI->getOperand(0).getSubReg() == 0) { FrameIndex = MI->getOperand(1).getIndex(); return MI->getOperand(0).getReg(); @@ -1583,46 +1573,75 @@ ARMBaseInstrInfo::getNumMicroOps(const InstrItineraryData *ItinData, default: llvm_unreachable("Unexpected multi-uops instruction!"); break; - case ARM::VLDMQ: - case ARM::VSTMQ: + case ARM::VLDMQIA: + case ARM::VLDMQDB: + case ARM::VSTMQIA: + case ARM::VSTMQDB: return 2; // The number of uOps for load / store multiple are determined by the number // registers. + // // On Cortex-A8, each pair of register loads / stores can be scheduled on the // same cycle. The scheduling for the first load / store must be done // separately by assuming the the address is not 64-bit aligned. + // // On Cortex-A9, the formula is simply (#reg / 2) + (#reg % 2). If the address - // is not 64-bit aligned, then AGU would take an extra cycle. - // For VFP / NEON load / store multiple, the formula is - // (#reg / 2) + (#reg % 2) + 1. - case ARM::VLDMD: - case ARM::VLDMS: - case ARM::VLDMD_UPD: - case ARM::VLDMS_UPD: - case ARM::VSTMD: - case ARM::VSTMS: - case ARM::VSTMD_UPD: - case ARM::VSTMS_UPD: { + // is not 64-bit aligned, then AGU would take an extra cycle. For VFP / NEON + // load / store multiple, the formula is (#reg / 2) + (#reg % 2) + 1. + case ARM::VLDMDIA: + case ARM::VLDMDDB: + case ARM::VLDMDIA_UPD: + case ARM::VLDMDDB_UPD: + case ARM::VLDMSIA: + case ARM::VLDMSDB: + case ARM::VLDMSIA_UPD: + case ARM::VLDMSDB_UPD: + case ARM::VSTMDIA: + case ARM::VSTMDDB: + case ARM::VSTMDIA_UPD: + case ARM::VSTMDDB_UPD: + case ARM::VSTMSIA: + case ARM::VSTMSDB: + case ARM::VSTMSIA_UPD: + case ARM::VSTMSDB_UPD: { unsigned NumRegs = MI->getNumOperands() - Desc.getNumOperands(); return (NumRegs / 2) + (NumRegs % 2) + 1; } - case ARM::LDM_RET: - case ARM::LDM: - case ARM::LDM_UPD: - case ARM::STM: - case ARM::STM_UPD: - case ARM::tLDM: - case ARM::tLDM_UPD: - case ARM::tSTM_UPD: + + case ARM::LDMIA_RET: + case ARM::LDMIA: + case ARM::LDMDA: + case ARM::LDMDB: + case ARM::LDMIB: + case ARM::LDMIA_UPD: + case ARM::LDMDA_UPD: + case ARM::LDMDB_UPD: + case ARM::LDMIB_UPD: + case ARM::STMIA: + case ARM::STMDA: + case ARM::STMDB: + case ARM::STMIB: + case ARM::STMIA_UPD: + case ARM::STMDA_UPD: + case ARM::STMDB_UPD: + case ARM::STMIB_UPD: + case ARM::tLDMIA: + case ARM::tLDMIA_UPD: + case ARM::tSTMIA: + case ARM::tSTMIA_UPD: case ARM::tPOP_RET: case ARM::tPOP: case ARM::tPUSH: - case ARM::t2LDM_RET: - case ARM::t2LDM: - case ARM::t2LDM_UPD: - case ARM::t2STM: - case ARM::t2STM_UPD: { + case ARM::t2LDMIA_RET: + case ARM::t2LDMIA: + case ARM::t2LDMDB: + case ARM::t2LDMIA_UPD: + case ARM::t2LDMDB_UPD: + case ARM::t2STMIA: + case ARM::t2STMDB: + case ARM::t2STMIA_UPD: + case ARM::t2STMDB_UPD: { unsigned NumRegs = MI->getNumOperands() - Desc.getNumOperands() + 1; if (Subtarget.isCortexA8()) { if (NumRegs < 4) @@ -1669,13 +1688,17 @@ ARMBaseInstrInfo::getVLDMDefCycle(const InstrItineraryData *ItinData, } else if (Subtarget.isCortexA9()) { DefCycle = RegNo; bool isSLoad = false; + switch (DefTID.getOpcode()) { default: break; - case ARM::VLDMS: - case ARM::VLDMS_UPD: + case ARM::VLDMSIA: + case ARM::VLDMSDB: + case ARM::VLDMSIA_UPD: + case ARM::VLDMSDB_UPD: isSLoad = true; break; } + // If there are odd number of 'S' registers or if it's not 64-bit aligned, // then it takes an extra cycle. if ((isSLoad && (RegNo % 2)) || DefAlign < 8) @@ -1741,13 +1764,17 @@ ARMBaseInstrInfo::getVSTMUseCycle(const InstrItineraryData *ItinData, } else if (Subtarget.isCortexA9()) { UseCycle = RegNo; bool isSStore = false; + switch (UseTID.getOpcode()) { default: break; - case ARM::VSTMS: - case ARM::VSTMS_UPD: + case ARM::VSTMSIA: + case ARM::VSTMSDB: + case ARM::VSTMSIA_UPD: + case ARM::VSTMSDB_UPD: isSStore = true; break; } + // If there are odd number of 'S' registers or if it's not 64-bit aligned, // then it takes an extra cycle. if ((isSStore && (RegNo % 2)) || UseAlign < 8) @@ -1810,27 +1837,39 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, default: DefCycle = ItinData->getOperandCycle(DefClass, DefIdx); break; - case ARM::VLDMD: - case ARM::VLDMS: - case ARM::VLDMD_UPD: - case ARM::VLDMS_UPD: { + + case ARM::VLDMDIA: + case ARM::VLDMDDB: + case ARM::VLDMDIA_UPD: + case ARM::VLDMDDB_UPD: + case ARM::VLDMSIA: + case ARM::VLDMSDB: + case ARM::VLDMSIA_UPD: + case ARM::VLDMSDB_UPD: DefCycle = getVLDMDefCycle(ItinData, DefTID, DefClass, DefIdx, DefAlign); break; - } - case ARM::LDM_RET: - case ARM::LDM: - case ARM::LDM_UPD: - case ARM::tLDM: - case ARM::tLDM_UPD: + + case ARM::LDMIA_RET: + case ARM::LDMIA: + case ARM::LDMDA: + case ARM::LDMDB: + case ARM::LDMIB: + case ARM::LDMIA_UPD: + case ARM::LDMDA_UPD: + case ARM::LDMDB_UPD: + case ARM::LDMIB_UPD: + case ARM::tLDMIA: + case ARM::tLDMIA_UPD: case ARM::tPUSH: - case ARM::t2LDM_RET: - case ARM::t2LDM: - case ARM::t2LDM_UPD: { + case ARM::t2LDMIA_RET: + case ARM::t2LDMIA: + case ARM::t2LDMDB: + case ARM::t2LDMIA_UPD: + case ARM::t2LDMDB_UPD: LdmBypass = 1; DefCycle = getLDMDefCycle(ItinData, DefTID, DefClass, DefIdx, DefAlign); break; } - } if (DefCycle == -1) // We can't seem to determine the result latency of the def, assume it's 2. @@ -1841,24 +1880,37 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, default: UseCycle = ItinData->getOperandCycle(UseClass, UseIdx); break; - case ARM::VSTMD: - case ARM::VSTMS: - case ARM::VSTMD_UPD: - case ARM::VSTMS_UPD: { + + case ARM::VSTMDIA: + case ARM::VSTMDDB: + case ARM::VSTMDIA_UPD: + case ARM::VSTMDDB_UPD: + case ARM::VSTMSIA: + case ARM::VSTMSDB: + case ARM::VSTMSIA_UPD: + case ARM::VSTMSDB_UPD: UseCycle = getVSTMUseCycle(ItinData, UseTID, UseClass, UseIdx, UseAlign); break; - } - case ARM::STM: - case ARM::STM_UPD: - case ARM::tSTM_UPD: + + case ARM::STMIA: + case ARM::STMDA: + case ARM::STMDB: + case ARM::STMIB: + case ARM::STMIA_UPD: + case ARM::STMDA_UPD: + case ARM::STMDB_UPD: + case ARM::STMIB_UPD: + case ARM::tSTMIA: + case ARM::tSTMIA_UPD: case ARM::tPOP_RET: case ARM::tPOP: - case ARM::t2STM: - case ARM::t2STM_UPD: { + case ARM::t2STMIA: + case ARM::t2STMDB: + case ARM::t2STMIA_UPD: + case ARM::t2STMDB_UPD: UseCycle = getSTMUseCycle(ItinData, UseTID, UseClass, UseIdx, UseAlign); break; } - } if (UseCycle == -1) // Assume it's read in the first stage. @@ -1873,8 +1925,9 @@ ARMBaseInstrInfo::getOperandLatency(const InstrItineraryData *ItinData, UseClass, UseIdx)) --UseCycle; } else if (ItinData->hasPipelineForwarding(DefClass, DefIdx, - UseClass, UseIdx)) + UseClass, UseIdx)) { --UseCycle; + } } return UseCycle; @@ -2040,8 +2093,10 @@ int ARMBaseInstrInfo::getInstrLatency(const InstrItineraryData *ItinData, switch (Opcode) { default: return ItinData->getStageLatency(get(Opcode).getSchedClass()); - case ARM::VLDMQ: - case ARM::VSTMQ: + case ARM::VLDMQIA: + case ARM::VLDMQDB: + case ARM::VSTMQIA: + case ARM::VSTMQDB: return 2; } } diff --git a/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/lib/Target/ARM/ARMExpandPseudoInsts.cpp index f38c452fce1..a6fbe724037 100644 --- a/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -782,24 +782,30 @@ bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) { break; } - case ARM::VLDMQ: { + case ARM::VLDMQIA: + case ARM::VLDMQDB: { + unsigned NewOpc = (Opcode == ARM::VLDMQIA) ? ARM::VLDMDIA : ARM::VLDMDDB; MachineInstrBuilder MIB = - BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::VLDMD)); + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc)); unsigned OpIdx = 0; + // Grab the Q register destination. bool DstIsDead = MI.getOperand(OpIdx).isDead(); unsigned DstReg = MI.getOperand(OpIdx++).getReg(); - // Copy the addrmode4 operands. - MIB.addOperand(MI.getOperand(OpIdx++)); + + // Copy the source register. MIB.addOperand(MI.getOperand(OpIdx++)); + // Copy the predicate operands. MIB.addOperand(MI.getOperand(OpIdx++)); MIB.addOperand(MI.getOperand(OpIdx++)); + // Add the destination operands (D subregs). unsigned D0 = TRI->getSubReg(DstReg, ARM::dsub_0); unsigned D1 = TRI->getSubReg(DstReg, ARM::dsub_1); MIB.addReg(D0, RegState::Define | getDeadRegState(DstIsDead)) .addReg(D1, RegState::Define | getDeadRegState(DstIsDead)); + // Add an implicit def for the super-register. MIB.addReg(DstReg, RegState::ImplicitDefine | getDeadRegState(DstIsDead)); TransferImpOps(MI, MIB, MIB); @@ -807,26 +813,33 @@ bool ARMExpandPseudo::ExpandMBB(MachineBasicBlock &MBB) { break; } - case ARM::VSTMQ: { + case ARM::VSTMQIA: + case ARM::VSTMQDB: { + unsigned NewOpc = (Opcode == ARM::VSTMQIA) ? ARM::VSTMDIA : ARM::VSTMDDB; MachineInstrBuilder MIB = - BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(ARM::VSTMD)); + BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(NewOpc)); unsigned OpIdx = 0; + // Grab the Q register source. bool SrcIsKill = MI.getOperand(OpIdx).isKill(); unsigned SrcReg = MI.getOperand(OpIdx++).getReg(); - // Copy the addrmode4 operands. - MIB.addOperand(MI.getOperand(OpIdx++)); + + // Copy the destination register. MIB.addOperand(MI.getOperand(OpIdx++)); + // Copy the predicate operands. MIB.addOperand(MI.getOperand(OpIdx++)); MIB.addOperand(MI.getOperand(OpIdx++)); + // Add the source operands (D subregs). unsigned D0 = TRI->getSubReg(SrcReg, ARM::dsub_0); unsigned D1 = TRI->getSubReg(SrcReg, ARM::dsub_1); MIB.addReg(D0).addReg(D1); + if (SrcIsKill) // Add an implicit kill for the Q register. (*MIB).addRegisterKilled(SrcReg, TRI, true); + TransferImpOps(MI, MIB, MIB); MI.eraseFromParent(); break; diff --git a/lib/Target/ARM/ARMInstrInfo.td b/lib/Target/ARM/ARMInstrInfo.td index 5a68c565bb1..0c7c0b8aab9 100644 --- a/lib/Target/ARM/ARMInstrInfo.td +++ b/lib/Target/ARM/ARMInstrInfo.td @@ -1194,18 +1194,6 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { } } -// FIXME: remove when we have a way to marking a MI with these properties. -// FIXME: Should pc be an implicit operand like PICADD, etc? -let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, - hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in - def LDM_RET : AXI4ld<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$mode, pred:$p, - reglist:$dsts, variable_ops), - IndexModeUpd, LdStMulFrm, IIC_iLoad_mBr, - "ldm${mode}${p}\t$Rn!, $dsts", - "$Rn = $wb", []> { - let Inst{21} = 1; -} - // On non-Darwin platforms R9 is callee-saved. let isCall = 1, Defs = [R0, R1, R2, R3, R12, LR, @@ -1797,23 +1785,23 @@ def STRHT: AI3sthpo<(outs GPR:$base_wb), multiclass arm_ldst_mult { - def ia : + def IA : AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), IndexModeNone, f, itin, - !strconcat(asm, "${p}\t$Rn, $regs"), "", []> { + !strconcat(asm, "ia${p}\t$Rn, $regs"), "", []> { let Inst{24-23} = 0b01; // Increment After let Inst{21} = 0; // No writeback let Inst{20} = L_bit; } - def ia_UPD : + def IA_UPD : AXI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), IndexModeUpd, f, itin_upd, - !strconcat(asm, "${p}\t$Rn!, $regs"), "$Rn = $wb", []> { + !strconcat(asm, "ia${p}\t$Rn!, $regs"), "$Rn = $wb", []> { let Inst{24-23} = 0b01; // Increment After - let Inst{21} = 1; // No writeback + let Inst{21} = 1; // Writeback let Inst{20} = L_bit; } - def da : + def DA : AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), IndexModeNone, f, itin, !strconcat(asm, "da${p}\t$Rn, $regs"), "", []> { @@ -1821,15 +1809,15 @@ multiclass arm_ldst_mult { let Inst{24-23} = 0b00; // Decrement After - let Inst{21} = 1; // No writeback + let Inst{21} = 1; // Writeback let Inst{20} = L_bit; } - def db : + def DB : AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), IndexModeNone, f, itin, !strconcat(asm, "db${p}\t$Rn, $regs"), "", []> { @@ -1837,15 +1825,15 @@ multiclass arm_ldst_mult { let Inst{24-23} = 0b10; // Decrement Before - let Inst{21} = 1; // No writeback + let Inst{21} = 1; // Writeback let Inst{20} = L_bit; } - def ib : + def IB : AXI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), IndexModeNone, f, itin, !strconcat(asm, "ib${p}\t$Rn, $regs"), "", []> { @@ -1853,17 +1841,16 @@ multiclass arm_ldst_mult { let Inst{24-23} = 0b11; // Increment Before - let Inst{21} = 1; // No writeback + let Inst{21} = 1; // Writeback let Inst{20} = L_bit; } } -/* TODO: let neverHasSideEffects = 1 in { let mayLoad = 1, hasExtraDefRegAllocReq = 1 in @@ -1873,45 +1860,24 @@ let mayStore = 1, hasExtraSrcRegAllocReq = 1 in defm STM : arm_ldst_mult<"stm", 0, LdStMulFrm, IIC_iStore_m, IIC_iStore_mu>; } // neverHasSideEffects -*/ -let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1, - isCodeGenOnly = 1 in { -def LDM : AXI4ld<(outs), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$dsts, variable_ops), - IndexModeNone, LdStMulFrm, IIC_iLoad_m, - "ldm${amode}${p}\t$Rn, $dsts", "", []> { - let Inst{21} = 0; -} +// Load / Store Multiple Mnemnoic Aliases +def : MnemonicAlias<"ldm", "ldmia">; +def : MnemonicAlias<"stm", "stmia">; -def LDM_UPD : AXI4ld<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$dsts, variable_ops), - IndexModeUpd, LdStMulFrm, IIC_iLoad_mu, - "ldm${amode}${p}\t$Rn!, $dsts", - "$Rn = $wb", []> { - let Inst{21} = 1; +// FIXME: remove when we have a way to marking a MI with these properties. +// FIXME: Should pc be an implicit operand like PICADD, etc? +let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, + hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in +def LDMIA_RET : AXI4ld<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, + reglist:$dsts, variable_ops), + IndexModeUpd, LdStMulFrm, IIC_iLoad_mBr, + "ldmia${p}\t$Rn!, $dsts", + "$Rn = $wb", []> { + let Inst{24-23} = 0b01; // Increment After + let Inst{21} = 1; // Writeback } -} // mayLoad, neverHasSideEffects, hasExtraDefRegAllocReq -let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1, - isCodeGenOnly = 1 in { -def STM : AXI4st<(outs), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$srcs, variable_ops), - IndexModeNone, LdStMulFrm, IIC_iStore_m, - "stm${amode}${p}\t$Rn, $srcs", "", []> { - let Inst{21} = 0; -} - -def STM_UPD : AXI4st<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$srcs, variable_ops), - IndexModeUpd, LdStMulFrm, IIC_iStore_mu, - "stm${amode}${p}\t$Rn!, $srcs", - "$Rn = $wb", []> { - bits<4> p; - let Inst{31-28} = p; - let Inst{21} = 1; -} -} // mayStore, neverHasSideEffects, hasExtraSrcRegAllocReq //===----------------------------------------------------------------------===// // Move Instructions. diff --git a/lib/Target/ARM/ARMInstrNEON.td b/lib/Target/ARM/ARMInstrNEON.td index d3e83f42b1c..f9a1d0dae69 100644 --- a/lib/Target/ARM/ARMInstrNEON.td +++ b/lib/Target/ARM/ARMInstrNEON.td @@ -142,15 +142,23 @@ def nModImm : Operand { // Use VLDM to load a Q register as a D register pair. // This is a pseudo instruction that is expanded to VLDMD after reg alloc. -def VLDMQ - : PseudoVFPLdStM<(outs QPR:$dst), (ins GPR:$Rn, ldstm_mode:$mode), +def VLDMQIA + : PseudoVFPLdStM<(outs QPR:$dst), (ins GPR:$Rn), + IIC_fpLoad_m, "", + [(set QPR:$dst, (v2f64 (load GPR:$Rn)))]>; +def VLDMQDB + : PseudoVFPLdStM<(outs QPR:$dst), (ins GPR:$Rn), IIC_fpLoad_m, "", [(set QPR:$dst, (v2f64 (load GPR:$Rn)))]>; // Use VSTM to store a Q register as a D register pair. // This is a pseudo instruction that is expanded to VSTMD after reg alloc. -def VSTMQ - : PseudoVFPLdStM<(outs), (ins QPR:$src, GPR:$Rn, ldstm_mode:$mode), +def VSTMQIA + : PseudoVFPLdStM<(outs), (ins QPR:$src, GPR:$Rn), + IIC_fpStore_m, "", + [(store (v2f64 QPR:$src), GPR:$Rn)]>; +def VSTMQDB + : PseudoVFPLdStM<(outs), (ins QPR:$src, GPR:$Rn), IIC_fpStore_m, "", [(store (v2f64 QPR:$src), GPR:$Rn)]>; diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 2d387bb3949..d7a22a48424 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -539,17 +539,17 @@ def tSpill : T1pIs<(outs), (ins tGPR:$src, t_addrmode_sp:$addr), IIC_iStore_i, multiclass thumb_ldst_mult T1Enc, bit L_bit> { - def ia : + def IA : T1I<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), - itin, !strconcat(asm, "${p}\t$Rn, $regs"), []>, + itin, !strconcat(asm, "ia${p}\t$Rn, $regs"), []>, T1Encoding; - def ia_UPD : + def IA_UPD : T1It<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), - itin_upd, !strconcat(asm, "${p}\t$Rn!, $regs"), "$Rn = $wb", []>, + itin_upd, !strconcat(asm, "ia${p}\t$Rn!, $regs"), "$Rn = $wb", []>, T1Encoding; } -/* TODO: Uncommented, this causes a decoding conflict. +// These require base address to be written back or one of the loaded regs. let neverHasSideEffects = 1 in { let mayLoad = 1, hasExtraDefRegAllocReq = 1 in @@ -561,36 +561,6 @@ defm tSTM : thumb_ldst_mult<"stm", IIC_iStore_m, IIC_iStore_mu, {1,1,0,0,0,?}, 0>; } // neverHasSideEffects -*/ - -// These require base address to be written back or one of the loaded regs. -let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1, - isCodeGenOnly = 1 in { -def tLDM : T1I<(outs), - (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, reglist:$dsts, - variable_ops), - IIC_iLoad_m, - "ldm${amode}${p}\t$Rn, $dsts", []>, - T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53 - -def tLDM_UPD : T1It<(outs tGPR:$wb), - (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, reglist:$dsts, - variable_ops), - IIC_iLoad_m, - "ldm${amode}${p}\t$Rn!, $dsts", - "$Rn = $wb", []>, - T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53 -} // mayLoad, neverHasSideEffects = 1, hasExtraDefRegAllocReq - -let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1, - isCodeGenOnly = 1 in -def tSTM_UPD : T1It<(outs tGPR:$wb), - (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, reglist:$srcs, - variable_ops), - IIC_iStore_mu, - "stm${amode}${p}\t$Rn!, $srcs", - "$Rn = $wb", []>, - T1Encoding<{1,1,0,0,0,?}>; // A6.2 & A8.6.189 let mayLoad = 1, Uses = [SP], Defs = [SP], hasExtraDefRegAllocReq = 1 in def tPOP : T1I<(outs), (ins pred:$p, reglist:$dsts, variable_ops), diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 9d09019dba1..e9d5212a462 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -1501,9 +1501,9 @@ defm t2PLI : T2Ipl<0, 1, "pli">, Requires<[IsThumb2,HasV7]>; multiclass thumb2_ldst_mult { - def ia : + def IA : T2XI<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), - itin, !strconcat(asm, "${p}.w\t$Rn, $regs"), []> { + itin, !strconcat(asm, "ia${p}.w\t$Rn, $regs"), []> { bits<4> Rn; bits<16> regs; @@ -1516,9 +1516,9 @@ multiclass thumb2_ldst_mult { + itin_upd, !strconcat(asm, "ia${p}.w\t$Rn!, $regs"), "$Rn = $wb", []> { bits<4> Rn; bits<16> regs; @@ -1531,7 +1531,7 @@ multiclass thumb2_ldst_mult { bits<4> Rn; @@ -1546,7 +1546,7 @@ multiclass thumb2_ldst_mult { bits<4> Rn; @@ -1563,7 +1563,6 @@ multiclass thumb2_ldst_mult; } // neverHasSideEffects -*/ -let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1, - isCodeGenOnly = 1 in { -def t2LDM : T2XI<(outs), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$dsts, variable_ops), IIC_iLoad_m, - "ldm${amode}${p}.w\t$Rn, $dsts", []> { - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b00; - let Inst{24-23} = {?, ?}; // IA: '01', DB: '10' - let Inst{22} = 0; - let Inst{21} = 0; // The W bit. - let Inst{20} = 1; // Load -} - -def t2LDM_UPD : T2XIt<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$dsts, variable_ops), - IIC_iLoad_mu, - "ldm${amode}${p}.w\t$Rn!, $dsts", - "$Rn = $wb", []> { - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b00; - let Inst{24-23} = {?, ?}; // IA: '01', DB: '10' - let Inst{22} = 0; - let Inst{21} = 1; // The W bit. - let Inst{20} = 1; // Load -} -} // mayLoad, neverHasSideEffects, hasExtraDefRegAllocReq - -let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1, - isCodeGenOnly = 1 in { -def t2STM : T2XI<(outs), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$srcs, variable_ops), IIC_iStore_m, - "stm${amode}${p}.w\t$Rn, $srcs", []> { - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b00; - let Inst{24-23} = {?, ?}; // IA: '01', DB: '10' - let Inst{22} = 0; - let Inst{21} = 0; // The W bit. - let Inst{20} = 0; // Store -} - -def t2STM_UPD : T2XIt<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$srcs, variable_ops), - IIC_iStore_m, - "stm${amode}${p}.w\t$Rn!, $srcs", - "$Rn = $wb", []> { - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b00; - let Inst{24-23} = {?, ?}; // IA: '01', DB: '10' - let Inst{22} = 0; - let Inst{21} = 1; // The W bit. - let Inst{20} = 0; // Store -} -} // mayStore, neverHasSideEffects, hasExtraSrcRegAllocReq //===----------------------------------------------------------------------===// // Move Instructions. @@ -2814,17 +2759,14 @@ let Defs = // FIXME: Should pc be an implicit operand like PICADD, etc? let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1, hasExtraDefRegAllocReq = 1, isCodeGenOnly = 1 in - def t2LDM_RET: T2XIt<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, +def t2LDMIA_RET: T2XIt<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$dsts, variable_ops), IIC_iLoad_mBr, - "ldm${amode}${p}.w\t$Rn!, $dsts", + "ldmia${p}.w\t$Rn!, $dsts", "$Rn = $wb", []> { - let Inst{31-27} = 0b11101; - let Inst{26-25} = 0b00; - let Inst{24-23} = {?, ?}; // IA: '01', DB: '10' - let Inst{22} = 0; - let Inst{21} = 1; // The W bit. - let Inst{20} = 1; // Load + let Inst{24-23} = 0b01; // IA: '01', DB: '10' + let Inst{21} = 1; // The W bit. + let Inst{20} = 1; // Load } let isBranch = 1, isTerminator = 1, isBarrier = 1 in { diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td index e4048dd8860..a9c99a191cb 100644 --- a/lib/Target/ARM/ARMInstrVFP.td +++ b/lib/Target/ARM/ARMInstrVFP.td @@ -74,25 +74,26 @@ def VSTRS : ASI5<0b1101, 0b00, (outs), (ins SPR:$Sd, addrmode5:$addr), // Load / store multiple Instructions. // -multiclass vfp_ldst_d_mult { - def ia : +multiclass vfp_ldst_mult { + // Double Precision + def DIA : AXDI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), IndexModeNone, itin, - !strconcat(asm, "${p}\t$Rn, $regs"), "", []> { + !strconcat(asm, "ia${p}\t$Rn, $regs"), "", []> { let Inst{24-23} = 0b01; // Increment After let Inst{21} = 0; // No writeback let Inst{20} = L_bit; } - def ia_UPD : + def DIA_UPD : AXDI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), IndexModeUpd, itin_upd, - !strconcat(asm, "${p}\t$Rn!, $regs"), "$Rn = $wb", []> { + !strconcat(asm, "ia${p}\t$Rn!, $regs"), "$Rn = $wb", []> { let Inst{24-23} = 0b01; // Increment After let Inst{21} = 1; // Writeback let Inst{20} = L_bit; } - def db : + def DDB : AXDI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), IndexModeNone, itin, !strconcat(asm, "db${p}\t$Rn, $regs"), "", []> { @@ -100,7 +101,7 @@ multiclass vfp_ldst_d_mult { @@ -108,27 +109,25 @@ multiclass vfp_ldst_d_mult { - def ia : + // Single Precision + def SIA : AXSI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), IndexModeNone, itin, - !strconcat(asm, "${p}\t$Rn, $regs"), "", []> { + !strconcat(asm, "ia${p}\t$Rn, $regs"), "", []> { let Inst{24-23} = 0b01; // Increment After let Inst{21} = 0; // No writeback let Inst{20} = L_bit; } - def ia_UPD : + def SIA_UPD : AXSI4<(outs GPR:$wb), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), IndexModeUpd, itin_upd, - !strconcat(asm, "${p}\t$Rn!, $regs"), "$Rn = $wb", []> { + !strconcat(asm, "ia${p}\t$Rn!, $regs"), "$Rn = $wb", []> { let Inst{24-23} = 0b01; // Increment After let Inst{21} = 1; // Writeback let Inst{20} = L_bit; } - def db : + def SDB : AXSI4<(outs), (ins GPR:$Rn, pred:$p, reglist:$regs, variable_ops), IndexModeNone, itin, !strconcat(asm, "db${p}\t$Rn, $regs"), "", []> { @@ -136,7 +135,7 @@ multiclass vfp_ldst_s_mult { @@ -148,92 +147,14 @@ multiclass vfp_ldst_s_mult; -defm VLDMS : vfp_ldst_s_mult<"vldm", 1, IIC_fpLoad_m, IIC_fpLoad_mu>; -} // mayLoad, hasExtraDefRegAllocReq +let mayLoad = 1, hasExtraDefRegAllocReq = 1 in +defm VLDM : vfp_ldst_mult<"vldm", 1, IIC_fpLoad_m, IIC_fpLoad_mu>; -let mayStore = 1, hasExtraSrcRegAllocReq = 1 in { -defm VSTMD : vfp_ldst_d_mult<"vstm", 0, IIC_fpLoad_m, IIC_fpLoad_mu>; -defm VSTMS : vfp_ldst_s_mult<"vstm", 0, IIC_fpLoad_m, IIC_fpLoad_mu>; -} // mayStore, hasExtraSrcRegAllocReq +let mayStore = 1, hasExtraSrcRegAllocReq = 1 in +defm VSTM : vfp_ldst_mult<"vstm", 0, IIC_fpLoad_m, IIC_fpLoad_mu>; } // neverHasSideEffects -let mayLoad = 1, neverHasSideEffects = 1, hasExtraDefRegAllocReq = 1, - isCodeGenOnly = 1 in { -def VLDMD : AXDI4<(outs), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$dsts, variable_ops), - IndexModeNone, IIC_fpLoad_m, - "vldm${amode}${p}\t$Rn, $dsts", "", []> { - let Inst{21} = 0; // wback = (W == '1') - let Inst{20} = 1; // Load -} - -def VLDMS : AXSI4<(outs), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$dsts, variable_ops), - IndexModeNone, IIC_fpLoad_m, - "vldm${amode}${p}\t$Rn, $dsts", "", []> { - let Inst{21} = 0; // wback = (W == '1') - let Inst{20} = 1; // Load -} - -def VLDMD_UPD : AXDI4<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$dsts, variable_ops), - IndexModeUpd, IIC_fpLoad_mu, - "vldm${amode}${p}\t$Rn!, $dsts", - "$Rn = $wb", []> { - let Inst{21} = 1; // wback = (W == '1') - let Inst{20} = 1; // Load -} - -def VLDMS_UPD : AXSI4<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$dsts, variable_ops), - IndexModeUpd, IIC_fpLoad_mu, - "vldm${amode}${p}\t$Rn!, $dsts", - "$Rn = $wb", []> { - let Inst{21} = 1; // wback = (W == '1') - let Inst{20} = 1; // Load -} -} // mayLoad, neverHasSideEffects, hasExtraDefRegAllocReq - -let mayStore = 1, neverHasSideEffects = 1, hasExtraSrcRegAllocReq = 1, - isCodeGenOnly = 1 in { -def VSTMD : AXDI4<(outs), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$srcs, variable_ops), - IndexModeNone, IIC_fpStore_m, - "vstm${amode}${p}\t$Rn, $srcs", "", []> { - let Inst{21} = 0; // wback = (W == '1') - let Inst{20} = 0; // Store -} - -def VSTMS : AXSI4<(outs), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$srcs, variable_ops), IndexModeNone, - IIC_fpStore_m, - "vstm${amode}${p}\t$Rn, $srcs", "", []> { - let Inst{21} = 0; // wback = (W == '1') - let Inst{20} = 0; // Store -} - -def VSTMD_UPD : AXDI4<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$srcs, variable_ops), - IndexModeUpd, IIC_fpStore_mu, - "vstm${amode}${p}\t$Rn!, $srcs", - "$Rn = $wb", []> { - let Inst{21} = 1; // wback = (W == '1') - let Inst{20} = 0; // Store -} - -def VSTMS_UPD : AXSI4<(outs GPR:$wb), (ins GPR:$Rn, ldstm_mode:$amode, pred:$p, - reglist:$srcs, variable_ops), - IndexModeUpd, IIC_fpStore_mu, - "vstm${amode}${p}\t$Rn!, $srcs", - "$Rn = $wb", []> { - let Inst{21} = 1; // wback = (W == '1') - let Inst{20} = 0; // Store -} -} // mayStore, neverHasSideEffects, hasExtraSrcRegAllocReq - // FLDMX, FSTMX - mixing S/D registers for pre-armv6 cores //===----------------------------------------------------------------------===// diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp index bda92e6e68c..10dfd16fe94 100644 --- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -128,39 +128,119 @@ namespace { char ARMLoadStoreOpt::ID = 0; } -static int getLoadStoreMultipleOpcode(int Opcode) { +static int getLoadStoreMultipleOpcode(int Opcode, ARM_AM::AMSubMode Mode) { switch (Opcode) { + default: llvm_unreachable("Unhandled opcode!"); case ARM::LDRi12: ++NumLDMGened; - return ARM::LDM; + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::LDMIA; + case ARM_AM::da: return ARM::LDMDA; + case ARM_AM::db: return ARM::LDMDB; + case ARM_AM::ib: return ARM::LDMIB; + } + break; case ARM::STRi12: ++NumSTMGened; - return ARM::STM; + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::STMIA; + case ARM_AM::da: return ARM::STMDA; + case ARM_AM::db: return ARM::STMDB; + case ARM_AM::ib: return ARM::STMIB; + } + break; case ARM::t2LDRi8: case ARM::t2LDRi12: ++NumLDMGened; - return ARM::t2LDM; + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::t2LDMIA; + case ARM_AM::db: return ARM::t2LDMDB; + } + break; case ARM::t2STRi8: case ARM::t2STRi12: ++NumSTMGened; - return ARM::t2STM; + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::t2STMIA; + case ARM_AM::db: return ARM::t2STMDB; + } + break; case ARM::VLDRS: ++NumVLDMGened; - return ARM::VLDMS; + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::VLDMSIA; + case ARM_AM::db: return ARM::VLDMSDB; + } + break; case ARM::VSTRS: ++NumVSTMGened; - return ARM::VSTMS; + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::VSTMSIA; + case ARM_AM::db: return ARM::VSTMSDB; + } + break; case ARM::VLDRD: ++NumVLDMGened; - return ARM::VLDMD; + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::VLDMDIA; + case ARM_AM::db: return ARM::VLDMDDB; + } + break; case ARM::VSTRD: ++NumVSTMGened; - return ARM::VSTMD; - default: llvm_unreachable("Unhandled opcode!"); + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::VSTMDIA; + case ARM_AM::db: return ARM::VSTMDDB; + } + break; } + return 0; } +static ARM_AM::AMSubMode getLoadStoreMultipleSubMode(int Opcode) { + switch (Opcode) { + default: llvm_unreachable("Unhandled opcode!"); + case ARM::LDMIA: + case ARM::STMIA: + case ARM::t2LDMIA: + case ARM::t2STMIA: + case ARM::VLDMSIA: + case ARM::VSTMSIA: + case ARM::VLDMDIA: + case ARM::VSTMDIA: + return ARM_AM::ia; + + case ARM::LDMDA: + case ARM::STMDA: + return ARM_AM::da; + + case ARM::LDMDB: + case ARM::STMDB: + case ARM::t2LDMDB: + case ARM::t2STMDB: + case ARM::VLDMSDB: + case ARM::VSTMSDB: + case ARM::VLDMDDB: + case ARM::VSTMDDB: + return ARM_AM::db; + + case ARM::LDMIB: + case ARM::STMIB: + return ARM_AM::ib; + } + + return ARM_AM::bad_am_submode; +} + static bool isT2i32Load(unsigned Opc) { return Opc == ARM::t2LDRi12 || Opc == ARM::t2LDRi8; } @@ -245,10 +325,10 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB, bool isDef = (isi32Load(Opcode) || Opcode == ARM::VLDRS || Opcode == ARM::VLDRD); - Opcode = getLoadStoreMultipleOpcode(Opcode); + Opcode = getLoadStoreMultipleOpcode(Opcode, Mode); MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(Opcode)) .addReg(Base, getKillRegState(BaseKill)) - .addImm(ARM_AM::getAM4ModeImm(Mode)).addImm(Pred).addReg(PredReg); + .addImm(Pred).addReg(PredReg); for (unsigned i = 0; i != NumRegs; ++i) MIB = MIB.addReg(Regs[i].first, getDefRegState(isDef) | getKillRegState(Regs[i].second)); @@ -452,31 +532,109 @@ static inline unsigned getLSMultipleTransferSize(MachineInstr *MI) { case ARM::VLDRD: case ARM::VSTRD: return 8; - case ARM::LDM: - case ARM::STM: - case ARM::t2LDM: - case ARM::t2STM: - case ARM::VLDMS: - case ARM::VSTMS: + case ARM::LDMIA: + case ARM::LDMDA: + case ARM::LDMDB: + case ARM::LDMIB: + case ARM::STMIA: + case ARM::STMDA: + case ARM::STMDB: + case ARM::STMIB: + case ARM::t2LDMIA: + case ARM::t2LDMDB: + case ARM::t2STMIA: + case ARM::t2STMDB: + case ARM::VLDMSIA: + case ARM::VLDMSDB: + case ARM::VSTMSIA: + case ARM::VSTMSDB: return (MI->getNumOperands() - MI->getDesc().getNumOperands() + 1) * 4; - case ARM::VLDMD: - case ARM::VSTMD: + case ARM::VLDMDIA: + case ARM::VLDMDDB: + case ARM::VSTMDIA: + case ARM::VSTMDDB: return (MI->getNumOperands() - MI->getDesc().getNumOperands() + 1) * 8; } } -static unsigned getUpdatingLSMultipleOpcode(unsigned Opc) { +static unsigned getUpdatingLSMultipleOpcode(unsigned Opc, + ARM_AM::AMSubMode Mode) { switch (Opc) { - case ARM::LDM: return ARM::LDM_UPD; - case ARM::STM: return ARM::STM_UPD; - case ARM::t2LDM: return ARM::t2LDM_UPD; - case ARM::t2STM: return ARM::t2STM_UPD; - case ARM::VLDMS: return ARM::VLDMS_UPD; - case ARM::VLDMD: return ARM::VLDMD_UPD; - case ARM::VSTMS: return ARM::VSTMS_UPD; - case ARM::VSTMD: return ARM::VSTMD_UPD; default: llvm_unreachable("Unhandled opcode!"); + case ARM::LDMIA: + case ARM::LDMDA: + case ARM::LDMDB: + case ARM::LDMIB: + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::LDMIA_UPD; + case ARM_AM::ib: return ARM::LDMIB_UPD; + case ARM_AM::da: return ARM::LDMDA_UPD; + case ARM_AM::db: return ARM::LDMDB_UPD; + } + break; + case ARM::STMIA: + case ARM::STMDA: + case ARM::STMDB: + case ARM::STMIB: + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::STMIA_UPD; + case ARM_AM::ib: return ARM::STMIB_UPD; + case ARM_AM::da: return ARM::STMDA_UPD; + case ARM_AM::db: return ARM::STMDB_UPD; + } + break; + case ARM::t2LDMIA: + case ARM::t2LDMDB: + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::t2LDMIA_UPD; + case ARM_AM::db: return ARM::t2LDMDB_UPD; + } + break; + case ARM::t2STMIA: + case ARM::t2STMDB: + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::t2STMIA_UPD; + case ARM_AM::db: return ARM::t2STMDB_UPD; + } + break; + case ARM::VLDMSIA: + case ARM::VLDMSDB: + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::VLDMSIA_UPD; + case ARM_AM::db: return ARM::VLDMSDB_UPD; + } + break; + case ARM::VLDMDIA: + case ARM::VLDMDDB: + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::VLDMDIA_UPD; + case ARM_AM::db: return ARM::VLDMDDB_UPD; + } + break; + case ARM::VSTMSIA: + case ARM::VSTMSDB: + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::VSTMSIA_UPD; + case ARM_AM::db: return ARM::VSTMSDB_UPD; + } + break; + case ARM::VSTMDIA: + case ARM::VSTMDDB: + switch (Mode) { + default: llvm_unreachable("Unhandled submode!"); + case ARM_AM::ia: return ARM::VSTMDIA_UPD; + case ARM_AM::db: return ARM::VSTMDDB_UPD; + } + break; } + return 0; } @@ -505,16 +663,14 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineBasicBlock &MBB, int Opcode = MI->getOpcode(); DebugLoc dl = MI->getDebugLoc(); - bool DoMerge = false; - ARM_AM::AMSubMode Mode = ARM_AM::ia; - // Can't use an updating ld/st if the base register is also a dest // register. e.g. ldmdb r0!, {r0, r1, r2}. The behavior is undefined. - for (unsigned i = 3, e = MI->getNumOperands(); i != e; ++i) { + for (unsigned i = 2, e = MI->getNumOperands(); i != e; ++i) if (MI->getOperand(i).getReg() == Base) return false; - } - Mode = ARM_AM::getAM4SubMode(MI->getOperand(1).getImm()); + + bool DoMerge = false; + ARM_AM::AMSubMode Mode = getLoadStoreMultipleSubMode(Opcode); // Try merging with the previous instruction. MachineBasicBlock::iterator BeginMBBI = MBB.begin(); @@ -560,15 +716,16 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineBasicBlock &MBB, if (!DoMerge) return false; - unsigned NewOpc = getUpdatingLSMultipleOpcode(Opcode); + unsigned NewOpc = getUpdatingLSMultipleOpcode(Opcode, Mode); MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII->get(NewOpc)) .addReg(Base, getDefRegState(true)) // WB base register .addReg(Base, getKillRegState(BaseKill)) - .addImm(ARM_AM::getAM4ModeImm(Mode)) .addImm(Pred).addReg(PredReg); + // Transfer the rest of operands. - for (unsigned OpNum = 4, e = MI->getNumOperands(); OpNum != e; ++OpNum) + for (unsigned OpNum = 3, e = MI->getNumOperands(); OpNum != e; ++OpNum) MIB.addOperand(MI->getOperand(OpNum)); + // Transfer memoperands. (*MIB).setMemRefs(MI->memoperands_begin(), MI->memoperands_end()); @@ -576,14 +733,21 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineBasicBlock &MBB, return true; } -static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc) { +static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc, + ARM_AM::AddrOpc Mode) { switch (Opc) { - case ARM::LDRi12: return ARM::LDR_PRE; - case ARM::STRi12: return ARM::STR_PRE; - case ARM::VLDRS: return ARM::VLDMS_UPD; - case ARM::VLDRD: return ARM::VLDMD_UPD; - case ARM::VSTRS: return ARM::VSTMS_UPD; - case ARM::VSTRD: return ARM::VSTMD_UPD; + case ARM::LDRi12: + return ARM::LDR_PRE; + case ARM::STRi12: + return ARM::STR_PRE; + case ARM::VLDRS: + return Mode == ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD; + case ARM::VLDRD: + return Mode == ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD; + case ARM::VSTRS: + return Mode == ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD; + case ARM::VSTRD: + return Mode == ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD; case ARM::t2LDRi8: case ARM::t2LDRi12: return ARM::t2LDR_PRE; @@ -595,14 +759,21 @@ static unsigned getPreIndexedLoadStoreOpcode(unsigned Opc) { return 0; } -static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc) { +static unsigned getPostIndexedLoadStoreOpcode(unsigned Opc, + ARM_AM::AddrOpc Mode) { switch (Opc) { - case ARM::LDRi12: return ARM::LDR_POST; - case ARM::STRi12: return ARM::STR_POST; - case ARM::VLDRS: return ARM::VLDMS_UPD; - case ARM::VLDRD: return ARM::VLDMD_UPD; - case ARM::VSTRS: return ARM::VSTMS_UPD; - case ARM::VSTRD: return ARM::VSTMD_UPD; + case ARM::LDRi12: + return ARM::LDR_POST; + case ARM::STRi12: + return ARM::STR_POST; + case ARM::VLDRS: + return Mode == ARM_AM::add ? ARM::VLDMSIA_UPD : ARM::VLDMSDB_UPD; + case ARM::VLDRD: + return Mode == ARM_AM::add ? ARM::VLDMDIA_UPD : ARM::VLDMDDB_UPD; + case ARM::VSTRS: + return Mode == ARM_AM::add ? ARM::VSTMSIA_UPD : ARM::VSTMSDB_UPD; + case ARM::VSTRD: + return Mode == ARM_AM::add ? ARM::VSTMDIA_UPD : ARM::VSTMDDB_UPD; case ARM::t2LDRi8: case ARM::t2LDRi12: return ARM::t2LDR_POST; @@ -664,7 +835,7 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB, DoMerge = true; } if (DoMerge) { - NewOpc = getPreIndexedLoadStoreOpcode(Opcode); + NewOpc = getPreIndexedLoadStoreOpcode(Opcode, AddSub); MBB.erase(PrevMBBI); } } @@ -683,7 +854,7 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB, DoMerge = true; } if (DoMerge) { - NewOpc = getPostIndexedLoadStoreOpcode(Opcode); + NewOpc = getPostIndexedLoadStoreOpcode(Opcode, AddSub); if (NextMBBI == I) { Advance = true; ++I; @@ -696,12 +867,9 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB, return false; unsigned Offset = 0; - if (isAM5) - Offset = ARM_AM::getAM4ModeImm(AddSub == ARM_AM::sub ? - ARM_AM::db : ARM_AM::ia); - else if (isAM2) + if (isAM2) Offset = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift); - else + else if (!isAM5) Offset = AddSub == ARM_AM::sub ? -Bytes : Bytes; if (isAM5) { @@ -713,7 +881,6 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB, BuildMI(MBB, MBBI, dl, TII->get(NewOpc)) .addReg(Base, getDefRegState(true)) // WB base register .addReg(Base, getKillRegState(isLd ? BaseKill : false)) - .addImm(Offset) .addImm(Pred).addReg(PredReg) .addReg(MO.getReg(), (isLd ? getDefRegState(true) : getKillRegState(MO.isKill()))); @@ -897,12 +1064,11 @@ bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB, // Ascending register numbers and no offset. It's safe to change it to a // ldm or stm. unsigned NewOpc = (isLd) - ? (isT2 ? ARM::t2LDM : ARM::LDM) - : (isT2 ? ARM::t2STM : ARM::STM); + ? (isT2 ? ARM::t2LDMIA : ARM::LDMIA) + : (isT2 ? ARM::t2STMIA : ARM::STMIA); if (isLd) { BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc)) .addReg(BaseReg, getKillRegState(BaseKill)) - .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)) .addImm(Pred).addReg(PredReg) .addReg(EvenReg, getDefRegState(isLd) | getDeadRegState(EvenDeadKill)) .addReg(OddReg, getDefRegState(isLd) | getDeadRegState(OddDeadKill)); @@ -910,7 +1076,6 @@ bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB, } else { BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc)) .addReg(BaseReg, getKillRegState(BaseKill)) - .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)) .addImm(Pred).addReg(PredReg) .addReg(EvenReg, getKillRegState(EvenDeadKill) | getUndefRegState(EvenUndef)) @@ -1164,12 +1329,16 @@ bool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &MBB) { MBBI->getOpcode() == ARM::tBX_RET || MBBI->getOpcode() == ARM::MOVPCLR)) { MachineInstr *PrevMI = prior(MBBI); - if (PrevMI->getOpcode() == ARM::LDM_UPD || - PrevMI->getOpcode() == ARM::t2LDM_UPD) { + unsigned Opcode = PrevMI->getOpcode(); + if (Opcode == ARM::LDMIA_UPD || Opcode == ARM::LDMDA_UPD || + Opcode == ARM::LDMDB_UPD || Opcode == ARM::LDMIB_UPD || + Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD) { MachineOperand &MO = PrevMI->getOperand(PrevMI->getNumOperands()-1); if (MO.getReg() != ARM::LR) return false; - unsigned NewOpc = isThumb2 ? ARM::t2LDM_RET : ARM::LDM_RET; + unsigned NewOpc = (isThumb2 ? ARM::t2LDMIA_RET : ARM::LDMIA_RET); + assert(((isThumb2 && Opcode == ARM::t2LDMIA_UPD) || + Opcode == ARM::LDMIA_UPD) && "Unsupported multiple load-return!"); PrevMI->setDesc(TII->get(NewOpc)); MO.setReg(ARM::PC); PrevMI->copyImplicitOps(&*MBBI); diff --git a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp index aeeb8cdf49a..2e8b3df6ebb 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp @@ -1306,30 +1306,28 @@ static bool DisassembleLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { assert(NumOps >= 5 && "LdStMulFrm expects NumOps >= 5"); - - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; + NumOpsAdded = 0; unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn)); // Writeback to base, if necessary. - if (Opcode == ARM::LDM_UPD || Opcode == ARM::STM_UPD) { + if (Opcode == ARM::LDMIA_UPD || Opcode == ARM::STMIA_UPD || + Opcode == ARM::LDMDA_UPD || Opcode == ARM::STMDA_UPD || + Opcode == ARM::LDMDB_UPD || Opcode == ARM::STMDB_UPD || + Opcode == ARM::LDMIB_UPD || Opcode == ARM::STMIB_UPD) { MI.addOperand(MCOperand::CreateReg(Base)); - ++OpIdx; + ++NumOpsAdded; } + // Add the base register operand. MI.addOperand(MCOperand::CreateReg(Base)); - ARM_AM::AMSubMode SubMode = getAMSubModeForBits(getPUBits(insn)); - MI.addOperand(MCOperand::CreateImm(ARM_AM::getAM4ModeImm(SubMode))); - // Handling the two predicate operands before the reglist. int64_t CondVal = insn >> ARMII::CondShift; MI.addOperand(MCOperand::CreateImm(CondVal == 0xF ? 0xE : CondVal)); MI.addOperand(MCOperand::CreateReg(ARM::CPSR)); - OpIdx += 4; + NumOpsAdded += 3; // Fill the variadic part of reglist. unsigned RegListBits = insn & ((1 << 16) - 1); @@ -1337,7 +1335,7 @@ static bool DisassembleLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, if ((RegListBits >> i) & 1) { MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, i))); - ++OpIdx; + ++NumOpsAdded; } } @@ -1882,8 +1880,10 @@ static bool DisassembleVFPLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn)); // Writeback to base, if necessary. - if (Opcode == ARM::VLDMD_UPD || Opcode == ARM::VLDMS_UPD || - Opcode == ARM::VSTMD_UPD || Opcode == ARM::VSTMS_UPD) { + if (Opcode == ARM::VLDMDIA_UPD || Opcode == ARM::VLDMSIA_UPD || + Opcode == ARM::VLDMDDB_UPD || Opcode == ARM::VLDMSDB_UPD || + Opcode == ARM::VSTMDIA_UPD || Opcode == ARM::VSTMSIA_UPD || + Opcode == ARM::VSTMDDB_UPD || Opcode == ARM::VSTMSDB_UPD) { MI.addOperand(MCOperand::CreateReg(Base)); ++OpIdx; } @@ -1906,8 +1906,10 @@ static bool DisassembleVFPLdStMulFrm(MCInst &MI, unsigned Opcode, uint32_t insn, OpIdx += 4; - bool isSPVFP = (Opcode == ARM::VLDMS || Opcode == ARM::VLDMS_UPD || - Opcode == ARM::VSTMS || Opcode == ARM::VSTMS_UPD); + bool isSPVFP = (Opcode == ARM::VLDMSIA || Opcode == ARM::VLDMSDB || + Opcode == ARM::VLDMSIA_UPD || Opcode == ARM::VLDMSDB_UPD || + Opcode == ARM::VSTMSIA || Opcode == ARM::VSTMSDB || + Opcode == ARM::VSTMSIA_UPD || Opcode == ARM::VSTMSDB_UPD); unsigned RegClassID = isSPVFP ? ARM::SPRRegClassID : ARM::DPRRegClassID; // Extract Dd/Sd. diff --git a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h index 6ed29494216..3725c4d9c02 100644 --- a/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h +++ b/lib/Target/ARM/Disassembler/ThumbDisassemblerCore.h @@ -833,40 +833,32 @@ static bool DisassembleThumb1Misc(MCInst &MI, unsigned Opcode, uint32_t insn, // A8.6.53 LDM / LDMIA // A8.6.189 STM / STMIA // -// tLDM_UPD/tSTM_UPD: tRt tRt AM4ModeImm Pred-Imm Pred-CCR register_list -// tLDM: tRt AM4ModeImm Pred-Imm Pred-CCR register_list +// tLDMIA_UPD/tSTMIA_UPD: tRt tRt AM4ModeImm Pred-Imm Pred-CCR register_list +// tLDMIA: tRt AM4ModeImm Pred-Imm Pred-CCR register_list static bool DisassembleThumb1LdStMul(bool Ld, MCInst &MI, unsigned Opcode, - uint32_t insn, unsigned short NumOps, unsigned &NumOpsAdded, BO B) { - - assert((Opcode == ARM::tLDM || Opcode == ARM::tLDM_UPD || - Opcode == ARM::tSTM_UPD) && "Unexpected opcode"); - - unsigned &OpIdx = NumOpsAdded; + uint32_t insn, unsigned short NumOps, + unsigned &NumOpsAdded, BO B) { + assert((Opcode == ARM::tLDMIA || Opcode == ARM::tLDMIA_UPD || + Opcode == ARM::tSTMIA_UPD) && "Unexpected opcode"); unsigned tRt = getT1tRt(insn); - - OpIdx = 0; + NumOpsAdded = 0; // WB register, if necessary. - if (Opcode == ARM::tLDM_UPD || Opcode == ARM::tSTM_UPD) { + if (Opcode == ARM::tLDMIA_UPD || Opcode == ARM::tSTMIA_UPD) { MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, tRt))); - ++OpIdx; + ++NumOpsAdded; } MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, tRt))); - ++OpIdx; - - // A8.6.53 LDM / LDMIA / LDMFD - Encoding T1 - // A8.6.53 STM / STMIA / STMEA - Encoding T1 - MI.addOperand(MCOperand::CreateImm(ARM_AM::getAM4ModeImm(ARM_AM::ia))); - ++OpIdx; + ++NumOpsAdded; // Handling the two predicate operands before the reglist. - if (B->DoPredicateOperands(MI, Opcode, insn, NumOps)) - OpIdx += 2; - else { + if (B->DoPredicateOperands(MI, Opcode, insn, NumOps)) { + NumOpsAdded += 2; + } else { DEBUG(errs() << "Expected predicate operands not found.\n"); return false; } @@ -874,13 +866,12 @@ static bool DisassembleThumb1LdStMul(bool Ld, MCInst &MI, unsigned Opcode, unsigned RegListBits = slice(insn, 7, 0); // Fill the variadic part of reglist. - for (unsigned i = 0; i < 8; ++i) { + for (unsigned i = 0; i < 8; ++i) if ((RegListBits >> i) & 1) { MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::tGPRRegClassID, i))); - ++OpIdx; + ++NumOpsAdded; } - } return true; } @@ -1122,34 +1113,31 @@ static bool DisassembleThumb2LdStMul(MCInst &MI, unsigned Opcode, uint32_t insn, if (Thumb2RFEOpcode(Opcode)) return DisassembleThumb2RFE(MI, Opcode, insn, NumOps, NumOpsAdded, B); - assert((Opcode == ARM::t2LDM || Opcode == ARM::t2LDM_UPD || - Opcode == ARM::t2STM || Opcode == ARM::t2STM_UPD) + assert((Opcode == ARM::t2LDMIA || Opcode == ARM::t2LDMIA_UPD || + Opcode == ARM::t2LDMDB || Opcode == ARM::t2LDMDB_UPD || + Opcode == ARM::t2STMIA || Opcode == ARM::t2STMIA_UPD || + Opcode == ARM::t2STMDB || Opcode == ARM::t2STMDB_UPD) && "Unexpected opcode"); assert(NumOps >= 5 && "Thumb2 LdStMul expects NumOps >= 5"); - unsigned &OpIdx = NumOpsAdded; - - OpIdx = 0; + NumOpsAdded = 0; unsigned Base = getRegisterEnum(B, ARM::GPRRegClassID, decodeRn(insn)); // Writeback to base. - if (Opcode == ARM::t2LDM_UPD || Opcode == ARM::t2STM_UPD) { + if (Opcode == ARM::t2LDMIA_UPD || Opcode == ARM::t2LDMDB_UPD || + Opcode == ARM::t2STMIA_UPD || Opcode == ARM::t2STMDB_UPD) { MI.addOperand(MCOperand::CreateReg(Base)); - ++OpIdx; + ++NumOpsAdded; } MI.addOperand(MCOperand::CreateReg(Base)); - ++OpIdx; - - ARM_AM::AMSubMode SubMode = getAMSubModeForBits(getPUBits(insn)); - MI.addOperand(MCOperand::CreateImm(ARM_AM::getAM4ModeImm(SubMode))); - ++OpIdx; + ++NumOpsAdded; // Handling the two predicate operands before the reglist. - if (B->DoPredicateOperands(MI, Opcode, insn, NumOps)) - OpIdx += 2; - else { + if (B->DoPredicateOperands(MI, Opcode, insn, NumOps)) { + NumOpsAdded += 2; + } else { DEBUG(errs() << "Expected predicate operands not found.\n"); return false; } @@ -1157,13 +1145,12 @@ static bool DisassembleThumb2LdStMul(MCInst &MI, unsigned Opcode, uint32_t insn, unsigned RegListBits = insn & ((1 << 16) - 1); // Fill the variadic part of reglist. - for (unsigned i = 0; i < 16; ++i) { + for (unsigned i = 0; i < 16; ++i) if ((RegListBits >> i) & 1) { MI.addOperand(MCOperand::CreateReg(getRegisterEnum(B, ARM::GPRRegClassID, i))); - ++OpIdx; + ++NumOpsAdded; } - } return true; } diff --git a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp index f54398cb302..f865b146b8f 100644 --- a/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp +++ b/lib/Target/ARM/InstPrinter/ARMInstPrinter.cpp @@ -63,55 +63,43 @@ void ARMInstPrinter::printInst(const MCInst *MI, raw_ostream &O) { } // A8.6.123 PUSH - if ((Opcode == ARM::STM_UPD || Opcode == ARM::t2STM_UPD) && + if ((Opcode == ARM::STMDB_UPD || Opcode == ARM::t2STMDB_UPD) && MI->getOperand(0).getReg() == ARM::SP) { - const MCOperand &MO1 = MI->getOperand(2); - if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) { - O << '\t' << "push"; - printPredicateOperand(MI, 3, O); - O << '\t'; - printRegisterList(MI, 5, O); - return; - } + O << '\t' << "push"; + printPredicateOperand(MI, 2, O); + O << '\t'; + printRegisterList(MI, 4, O); + return; } // A8.6.122 POP - if ((Opcode == ARM::LDM_UPD || Opcode == ARM::t2LDM_UPD) && + if ((Opcode == ARM::LDMIA_UPD || Opcode == ARM::t2LDMIA_UPD) && MI->getOperand(0).getReg() == ARM::SP) { - const MCOperand &MO1 = MI->getOperand(2); - if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) { - O << '\t' << "pop"; - printPredicateOperand(MI, 3, O); - O << '\t'; - printRegisterList(MI, 5, O); - return; - } + O << '\t' << "pop"; + printPredicateOperand(MI, 2, O); + O << '\t'; + printRegisterList(MI, 4, O); + return; } // A8.6.355 VPUSH - if ((Opcode == ARM::VSTMS_UPD || Opcode == ARM::VSTMD_UPD) && + if ((Opcode == ARM::VSTMSDB_UPD || Opcode == ARM::VSTMDDB_UPD) && MI->getOperand(0).getReg() == ARM::SP) { - const MCOperand &MO1 = MI->getOperand(2); - if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) { - O << '\t' << "vpush"; - printPredicateOperand(MI, 3, O); - O << '\t'; - printRegisterList(MI, 5, O); - return; - } + O << '\t' << "vpush"; + printPredicateOperand(MI, 2, O); + O << '\t'; + printRegisterList(MI, 4, O); + return; } // A8.6.354 VPOP - if ((Opcode == ARM::VLDMS_UPD || Opcode == ARM::VLDMD_UPD) && + if ((Opcode == ARM::VLDMSIA_UPD || Opcode == ARM::VLDMDIA_UPD) && MI->getOperand(0).getReg() == ARM::SP) { - const MCOperand &MO1 = MI->getOperand(2); - if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) { - O << '\t' << "vpop"; - printPredicateOperand(MI, 3, O); - O << '\t'; - printRegisterList(MI, 5, O); - return; - } + O << '\t' << "vpop"; + printPredicateOperand(MI, 2, O); + O << '\t'; + printRegisterList(MI, 4, O); + return; } printInstruction(MI, O); diff --git a/lib/Target/ARM/Thumb2SizeReduction.cpp b/lib/Target/ARM/Thumb2SizeReduction.cpp index 67768e5068e..4e82c57dcaa 100644 --- a/lib/Target/ARM/Thumb2SizeReduction.cpp +++ b/lib/Target/ARM/Thumb2SizeReduction.cpp @@ -121,11 +121,11 @@ namespace { { ARM::t2STRHi12,ARM::tSTRH, 0, 5, 0, 1, 0, 0,0, 1 }, { ARM::t2STRHs, ARM::tSTRH, 0, 0, 0, 1, 0, 0,0, 1 }, - { ARM::t2LDM, ARM::tLDM, 0, 0, 0, 1, 1, 1,1, 1 }, - { ARM::t2LDM_RET,0, ARM::tPOP_RET, 0, 0, 1, 1, 1,1, 1 }, - { ARM::t2LDM_UPD,ARM::tLDM_UPD,ARM::tPOP, 0, 0, 1, 1, 1,1, 1 }, + { ARM::t2LDMIA, ARM::tLDMIA, 0, 0, 0, 1, 1, 1,1, 1 }, + { ARM::t2LDMIA_RET,0, ARM::tPOP_RET, 0, 0, 1, 1, 1,1, 1 }, + { ARM::t2LDMIA_UPD,ARM::tLDMIA_UPD,ARM::tPOP,0, 0, 1, 1, 1,1, 1 }, // ARM::t2STM (with no basereg writeback) has no Thumb1 equivalent - { ARM::t2STM_UPD,ARM::tSTM_UPD,ARM::tPUSH, 0, 0, 1, 1, 1,1, 1 }, + { ARM::t2STMIA_UPD,ARM::tSTMIA_UPD,ARM::tPUSH,0, 0, 1, 1, 1,1, 1 }, }; class Thumb2SizeReduce : public MachineFunctionPass { @@ -233,9 +233,10 @@ Thumb2SizeReduce::VerifyPredAndCC(MachineInstr *MI, const ReduceEntry &Entry, static bool VerifyLowRegs(MachineInstr *MI) { unsigned Opc = MI->getOpcode(); - bool isPCOk = (Opc == ARM::t2LDM_RET || Opc == ARM::t2LDM || - Opc == ARM::t2LDM_UPD); - bool isLROk = (Opc == ARM::t2STM_UPD); + bool isPCOk = (Opc == ARM::t2LDMIA_RET || Opc == ARM::t2LDMIA || + Opc == ARM::t2LDMDB || Opc == ARM::t2LDMIA_UPD || + Opc == ARM::t2LDMDB_UPD); + bool isLROk = (Opc == ARM::t2STMIA_UPD || Opc == ARM::t2STMDB_UPD); bool isSPOk = isPCOk || isLROk || (Opc == ARM::t2ADDrSPi); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &MO = MI->getOperand(i); @@ -275,6 +276,7 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI, unsigned Opc = Entry.NarrowOpc1; unsigned OpNum = 3; // First 'rest' of operands. uint8_t ImmLimit = Entry.Imm1Limit; + switch (Entry.WideOpc) { default: llvm_unreachable("Unexpected Thumb2 load / store opcode!"); @@ -310,10 +312,10 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI, HasShift = true; OpNum = 4; break; - case ARM::t2LDM: { + case ARM::t2LDMIA: + case ARM::t2LDMDB: { unsigned BaseReg = MI->getOperand(0).getReg(); - ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(1).getImm()); - if (!isARMLowRegister(BaseReg) || Mode != ARM_AM::ia) + if (!isARMLowRegister(BaseReg) || Entry.WideOpc != ARM::t2LDMIA) return false; // For the non-writeback version (this one), the base register must be // one of the registers being loaded. @@ -331,26 +333,29 @@ Thumb2SizeReduce::ReduceLoadStore(MachineBasicBlock &MBB, MachineInstr *MI, isLdStMul = true; break; } - case ARM::t2LDM_RET: { + case ARM::t2LDMIA_RET: { unsigned BaseReg = MI->getOperand(1).getReg(); if (BaseReg != ARM::SP) return false; Opc = Entry.NarrowOpc2; // tPOP_RET - OpNum = 3; + OpNum = 2; isLdStMul = true; break; } - case ARM::t2LDM_UPD: - case ARM::t2STM_UPD: { + case ARM::t2LDMIA_UPD: + case ARM::t2LDMDB_UPD: + case ARM::t2STMIA_UPD: + case ARM::t2STMDB_UPD: { OpNum = 0; unsigned BaseReg = MI->getOperand(1).getReg(); - ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MI->getOperand(2).getImm()); if (BaseReg == ARM::SP && - ((Entry.WideOpc == ARM::t2LDM_UPD && Mode == ARM_AM::ia) || - (Entry.WideOpc == ARM::t2STM_UPD && Mode == ARM_AM::db))) { + (Entry.WideOpc == ARM::t2LDMIA_UPD || + Entry.WideOpc == ARM::t2STMDB_UPD)) { Opc = Entry.NarrowOpc2; // tPOP or tPUSH - OpNum = 3; - } else if (!isARMLowRegister(BaseReg) || Mode != ARM_AM::ia) { + OpNum = 2; + } else if (!isARMLowRegister(BaseReg) || + (Entry.WideOpc != ARM::t2LDMIA_UPD && + Entry.WideOpc != ARM::t2STMIA_UPD)) { return false; } isLdStMul = true; diff --git a/utils/TableGen/ARMDecoderEmitter.cpp b/utils/TableGen/ARMDecoderEmitter.cpp index 533fca0db0a..b5f3299f88d 100644 --- a/utils/TableGen/ARMDecoderEmitter.cpp +++ b/utils/TableGen/ARMDecoderEmitter.cpp @@ -1629,10 +1629,10 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( // operations in order to work around some performance issues. if (Name.find("_sfp") != std::string::npos) return false; - // LDM_RET is a special case of LDM (Load Multiple) where the registers + // LDMIA_RET is a special case of LDM (Load Multiple) where the registers // loaded include the PC, causing a branch to a loaded address. Ignore - // the LDM_RET instruction when decoding. - if (Name == "LDM_RET") return false; + // the LDMIA_RET instruction when decoding. + if (Name == "LDMIA_RET") return false; // Bcc is in a more generic form than B. Ignore B when decoding. if (Name == "B") return false; @@ -1726,7 +1726,7 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( // // tBfar conflicts with tBLr9 // tCMNz conflicts with tCMN (with assembly format strings being equal) - // tPOP_RET/t2LDM_RET conflict with tPOP/t2LDM (ditto) + // tPOP_RET/t2LDMIA_RET conflict with tPOP/t2LDM (ditto) // tMOVCCi conflicts with tMOVi8 // tMOVCCr conflicts with tMOVgpr2gpr // tBR_JTr conflicts with tBRIND @@ -1739,7 +1739,7 @@ bool ARMDecoderEmitter::ARMDEBackend::populateInstruction( /* Name == "tCMNz" || */ Name == "tCMPzi8" || Name == "tCMPzr" || Name == "tCMPzhir" || /* Name == "t2CMNzrr" || Name == "t2CMNzrs" || Name == "t2CMNzri" || */ Name == "t2CMPzrr" || Name == "t2CMPzrs" || - Name == "t2CMPzri" || Name == "tPOP_RET" || Name == "t2LDM_RET" || + Name == "t2CMPzri" || Name == "tPOP_RET" || Name == "t2LDMIA_RET" || Name == "tMOVCCi" || Name == "tMOVCCr" || Name == "tBR_JTr" || Name == "tSpill" || Name == "tLDRcp" || Name == "tRestore" || Name == "t2LEApcrelJT" || Name == "t2MOVCCi16") -- 2.34.1