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