1 //===-- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ---------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains code to lower Mips MachineInstrs to their corresponding
13 //===----------------------------------------------------------------------===//
14 #include "MipsMCInstLower.h"
15 #include "MCTargetDesc/MipsBaseInfo.h"
16 #include "MipsAsmPrinter.h"
17 #include "MipsInstrInfo.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineInstr.h"
20 #include "llvm/CodeGen/MachineOperand.h"
21 #include "llvm/IR/Mangler.h"
22 #include "llvm/MC/MCContext.h"
23 #include "llvm/MC/MCExpr.h"
24 #include "llvm/MC/MCInst.h"
25 #include "llvm/MC/MCStreamer.h"
29 MipsMCInstLower::MipsMCInstLower(MipsAsmPrinter &asmprinter)
30 : AsmPrinter(asmprinter) {}
32 void MipsMCInstLower::Initialize(MCContext *C) {
36 MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
37 MachineOperandType MOTy,
38 unsigned Offset) const {
39 MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
40 MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None;
42 const MCSymbol *Symbol;
44 switch(MO.getTargetFlags()) {
46 llvm_unreachable("Invalid target flag!");
47 case MipsII::MO_NO_FLAG:
49 case MipsII::MO_GPREL:
50 TargetKind = MipsMCExpr::MEK_GPREL;
52 case MipsII::MO_GOT_CALL:
53 TargetKind = MipsMCExpr::MEK_GOT_CALL;
56 TargetKind = MipsMCExpr::MEK_GOT;
58 case MipsII::MO_ABS_HI:
59 TargetKind = MipsMCExpr::MEK_HI;
61 case MipsII::MO_ABS_LO:
62 TargetKind = MipsMCExpr::MEK_LO;
64 case MipsII::MO_TLSGD:
65 TargetKind = MipsMCExpr::MEK_TLSGD;
67 case MipsII::MO_TLSLDM:
68 TargetKind = MipsMCExpr::MEK_TLSLDM;
70 case MipsII::MO_DTPREL_HI:
71 TargetKind = MipsMCExpr::MEK_DTPREL_HI;
73 case MipsII::MO_DTPREL_LO:
74 TargetKind = MipsMCExpr::MEK_DTPREL_LO;
76 case MipsII::MO_GOTTPREL:
77 TargetKind = MipsMCExpr::MEK_GOTTPREL;
79 case MipsII::MO_TPREL_HI:
80 TargetKind = MipsMCExpr::MEK_TPREL_HI;
82 case MipsII::MO_TPREL_LO:
83 TargetKind = MipsMCExpr::MEK_TPREL_LO;
85 case MipsII::MO_GPOFF_HI:
86 TargetKind = MipsMCExpr::MEK_HI;
89 case MipsII::MO_GPOFF_LO:
90 TargetKind = MipsMCExpr::MEK_LO;
93 case MipsII::MO_GOT_DISP:
94 TargetKind = MipsMCExpr::MEK_GOT_DISP;
96 case MipsII::MO_GOT_HI16:
97 TargetKind = MipsMCExpr::MEK_GOT_HI16;
99 case MipsII::MO_GOT_LO16:
100 TargetKind = MipsMCExpr::MEK_GOT_LO16;
102 case MipsII::MO_GOT_PAGE:
103 TargetKind = MipsMCExpr::MEK_GOT_PAGE;
105 case MipsII::MO_GOT_OFST:
106 TargetKind = MipsMCExpr::MEK_GOT_OFST;
108 case MipsII::MO_HIGHER:
109 TargetKind = MipsMCExpr::MEK_HIGHER;
111 case MipsII::MO_HIGHEST:
112 TargetKind = MipsMCExpr::MEK_HIGHEST;
114 case MipsII::MO_CALL_HI16:
115 TargetKind = MipsMCExpr::MEK_CALL_HI16;
117 case MipsII::MO_CALL_LO16:
118 TargetKind = MipsMCExpr::MEK_CALL_LO16;
123 case MachineOperand::MO_MachineBasicBlock:
124 Symbol = MO.getMBB()->getSymbol();
127 case MachineOperand::MO_GlobalAddress:
128 Symbol = AsmPrinter.getSymbol(MO.getGlobal());
129 Offset += MO.getOffset();
132 case MachineOperand::MO_BlockAddress:
133 Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress());
134 Offset += MO.getOffset();
137 case MachineOperand::MO_ExternalSymbol:
138 Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName());
139 Offset += MO.getOffset();
142 case MachineOperand::MO_MCSymbol:
143 Symbol = MO.getMCSymbol();
144 Offset += MO.getOffset();
147 case MachineOperand::MO_JumpTableIndex:
148 Symbol = AsmPrinter.GetJTISymbol(MO.getIndex());
151 case MachineOperand::MO_ConstantPoolIndex:
152 Symbol = AsmPrinter.GetCPISymbol(MO.getIndex());
153 Offset += MO.getOffset();
157 llvm_unreachable("<unknown operand type>");
160 const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
163 // Assume offset is never negative.
166 Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx),
171 Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx);
172 else if (TargetKind != MipsMCExpr::MEK_None)
173 Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx);
175 return MCOperand::createExpr(Expr);
178 MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
179 unsigned offset) const {
180 MachineOperandType MOTy = MO.getType();
183 default: llvm_unreachable("unknown operand type");
184 case MachineOperand::MO_Register:
185 // Ignore all implicit register operands.
186 if (MO.isImplicit()) break;
187 return MCOperand::createReg(MO.getReg());
188 case MachineOperand::MO_Immediate:
189 return MCOperand::createImm(MO.getImm() + offset);
190 case MachineOperand::MO_MachineBasicBlock:
191 case MachineOperand::MO_GlobalAddress:
192 case MachineOperand::MO_ExternalSymbol:
193 case MachineOperand::MO_MCSymbol:
194 case MachineOperand::MO_JumpTableIndex:
195 case MachineOperand::MO_ConstantPoolIndex:
196 case MachineOperand::MO_BlockAddress:
197 return LowerSymbolOperand(MO, MOTy, offset);
198 case MachineOperand::MO_RegisterMask:
205 MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
206 MachineBasicBlock *BB2,
207 MipsMCExpr::MipsExprKind Kind) const {
208 const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx);
209 const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx);
210 const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx);
212 return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx));
215 void MipsMCInstLower::
216 lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
217 OutMI.setOpcode(Mips::LUi);
219 // Lower register operand.
220 OutMI.addOperand(LowerOperand(MI->getOperand(0)));
222 // Create %hi($tgt-$baltgt).
223 OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
224 MI->getOperand(2).getMBB(),
225 MipsMCExpr::MEK_HI));
228 void MipsMCInstLower::lowerLongBranchADDiu(
229 const MachineInstr *MI, MCInst &OutMI, int Opcode,
230 MipsMCExpr::MipsExprKind Kind) const {
231 OutMI.setOpcode(Opcode);
233 // Lower two register operands.
234 for (unsigned I = 0, E = 2; I != E; ++I) {
235 const MachineOperand &MO = MI->getOperand(I);
236 OutMI.addOperand(LowerOperand(MO));
239 // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt).
240 OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
241 MI->getOperand(3).getMBB(), Kind));
244 bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
245 MCInst &OutMI) const {
246 switch (MI->getOpcode()) {
249 case Mips::LONG_BRANCH_LUi:
250 lowerLongBranchLUi(MI, OutMI);
252 case Mips::LONG_BRANCH_ADDiu:
253 lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu, MipsMCExpr::MEK_LO);
255 case Mips::LONG_BRANCH_DADDiu:
256 unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
257 if (TargetFlags == MipsII::MO_ABS_HI)
258 lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, MipsMCExpr::MEK_HI);
259 else if (TargetFlags == MipsII::MO_ABS_LO)
260 lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, MipsMCExpr::MEK_LO);
262 report_fatal_error("Unexpected flags for LONG_BRANCH_DADDiu");
267 void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
268 if (lowerLongBranch(MI, OutMI))
271 OutMI.setOpcode(MI->getOpcode());
273 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
274 const MachineOperand &MO = MI->getOperand(i);
275 MCOperand MCOp = LowerOperand(MO);
278 OutMI.addOperand(MCOp);