Expand .cprestore directive to multiple instructions if the offset does not fit

in a 16-bit field.

llvm-svn: 146469
This commit is contained in:
Akira Hatanaka 2011-12-13 03:09:05 +00:00
parent e41963ce47
commit 5e9d16cb53
3 changed files with 35 additions and 16 deletions

View File

@ -96,19 +96,17 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
if (!OutStreamer.hasRawTextSupport()) {
// Lower CPLOAD and CPRESTORE
if (Opc == Mips::CPLOAD) {
if (Opc == Mips::CPLOAD)
MCInstLowering.LowerCPLOAD(MI, MCInsts);
for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin(); I
!= MCInsts.end(); ++I)
else if (Opc == Mips::CPRESTORE)
MCInstLowering.LowerCPRESTORE(MI, MCInsts);
if (!MCInsts.empty()) {
for (SmallVector<MCInst, 4>::iterator I = MCInsts.begin();
I != MCInsts.end(); ++I)
OutStreamer.EmitInstruction(*I);
return;
}
if (Opc == Mips::CPRESTORE) {
MCInstLowering.LowerCPRESTORE(MI, TmpInst0);
OutStreamer.EmitInstruction(TmpInst0);
return;
}
}
OutStreamer.EmitInstruction(TmpInst0);

View File

@ -137,14 +137,35 @@ void MipsMCInstLower::LowerCPLOAD(const MachineInstr *MI,
}
// Lower ".cprestore offset" to "sw $gp, offset($sp)".
void MipsMCInstLower::LowerCPRESTORE(const MachineInstr *MI, MCInst &OutMI) {
OutMI.clear();
OutMI.setOpcode(Mips::SW);
OutMI.addOperand(MCOperand::CreateReg(Mips::GP));
OutMI.addOperand(MCOperand::CreateReg(Mips::SP));
void MipsMCInstLower::LowerCPRESTORE(const MachineInstr *MI,
SmallVector<MCInst, 4>& MCInsts) {
const MachineOperand &MO = MI->getOperand(0);
assert(MO.isImm() && "CPRESTORE's operand must be an immediate.");
OutMI.addOperand(MCOperand::CreateImm(MO.getImm()));
unsigned Offset = MO.getImm(), Reg = Mips::SP;
MCInst Sw;
if (Offset >= 0x8000) {
unsigned Hi = (Offset >> 16) + ((Offset & 0x8000) != 0);
Offset &= 0xffff;
Reg = Mips::AT;
// lui at,hi
// addu at,at,sp
MCInsts.resize(2);
MCInsts[0].setOpcode(Mips::LUi);
MCInsts[0].addOperand(MCOperand::CreateReg(Mips::AT));
MCInsts[0].addOperand(MCOperand::CreateImm(Hi));
MCInsts[1].setOpcode(Mips::ADDu);
MCInsts[1].addOperand(MCOperand::CreateReg(Mips::AT));
MCInsts[1].addOperand(MCOperand::CreateReg(Mips::AT));
MCInsts[1].addOperand(MCOperand::CreateReg(Mips::SP));
}
Sw.setOpcode(Mips::SW);
Sw.addOperand(MCOperand::CreateReg(Mips::GP));
Sw.addOperand(MCOperand::CreateReg(Reg));
Sw.addOperand(MCOperand::CreateImm(Offset));
MCInsts.push_back(Sw);
}
MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO,

View File

@ -36,7 +36,7 @@ public:
MipsAsmPrinter &asmprinter);
void Lower(const MachineInstr *MI, MCInst &OutMI) const;
void LowerCPLOAD(const MachineInstr *MI, SmallVector<MCInst, 4>& MCInsts);
void LowerCPRESTORE(const MachineInstr *MI, MCInst &OutMI);
void LowerCPRESTORE(const MachineInstr *MI, SmallVector<MCInst, 4>& MCInsts);
void LowerUnalignedLoadStore(const MachineInstr *MI,
SmallVector<MCInst, 4>& MCInsts);
private: