diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp')
-rw-r--r-- | contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp b/contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp index b6dfadce14e9..821392e1d45f 100644 --- a/contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp @@ -18,10 +18,10 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineOperand.h" +#include "llvm/IR/Mangler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" -#include "llvm/Target/Mangler.h" using namespace llvm; @@ -151,7 +151,75 @@ MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO, return MCOperand(); } +MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1, + MachineBasicBlock *BB2, + MCSymbolRefExpr::VariantKind Kind) const { + const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::Create(BB1->getSymbol(), *Ctx); + const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::Create(BB2->getSymbol(), *Ctx); + const MCBinaryExpr *Sub = MCBinaryExpr::CreateSub(Sym1, Sym2, *Ctx); + + return MCOperand::CreateExpr(MipsMCExpr::Create(Kind, Sub, *Ctx)); +} + +void MipsMCInstLower:: +lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const { + OutMI.setOpcode(Mips::LUi); + + // Lower register operand. + OutMI.addOperand(LowerOperand(MI->getOperand(0))); + + // Create %hi($tgt-$baltgt). + OutMI.addOperand(createSub(MI->getOperand(1).getMBB(), + MI->getOperand(2).getMBB(), + MCSymbolRefExpr::VK_Mips_ABS_HI)); +} + +void MipsMCInstLower:: +lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, int Opcode, + MCSymbolRefExpr::VariantKind Kind) const { + OutMI.setOpcode(Opcode); + + // Lower two register operands. + for (unsigned I = 0, E = 2; I != E; ++I) { + const MachineOperand &MO = MI->getOperand(I); + OutMI.addOperand(LowerOperand(MO)); + } + + // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt). + OutMI.addOperand(createSub(MI->getOperand(2).getMBB(), + MI->getOperand(3).getMBB(), Kind)); +} + +bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI, + MCInst &OutMI) const { + switch (MI->getOpcode()) { + default: + return false; + case Mips::LONG_BRANCH_LUi: + lowerLongBranchLUi(MI, OutMI); + return true; + case Mips::LONG_BRANCH_ADDiu: + lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu, + MCSymbolRefExpr::VK_Mips_ABS_LO); + return true; + case Mips::LONG_BRANCH_DADDiu: + unsigned TargetFlags = MI->getOperand(2).getTargetFlags(); + if (TargetFlags == MipsII::MO_ABS_HI) + lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, + MCSymbolRefExpr::VK_Mips_ABS_HI); + else if (TargetFlags == MipsII::MO_ABS_LO) + lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, + MCSymbolRefExpr::VK_Mips_ABS_LO); + else + report_fatal_error("Unexpected flags for LONG_BRANCH_DADDiu"); + return true; + } +} + void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { + if (lowerLongBranch(MI, OutMI)) + return; + OutMI.setOpcode(MI->getOpcode()); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { |