MipsMCInstLower.cpp revision e3d3572e282733bd7aa5ac14115ed0804174e426
1//===-- MipsMCInstLower.cpp - Convert Mips MachineInstr to MCInst ---------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file contains code to lower Mips MachineInstrs to their corresponding 11// MCInst records. 12// 13//===----------------------------------------------------------------------===// 14 15#include "MipsAsmPrinter.h" 16#include "MipsInstrInfo.h" 17#include "MipsMCInstLower.h" 18#include "MCTargetDesc/MipsBaseInfo.h" 19#include "llvm/CodeGen/MachineFunction.h" 20#include "llvm/CodeGen/MachineInstr.h" 21#include "llvm/CodeGen/MachineOperand.h" 22#include "llvm/MC/MCContext.h" 23#include "llvm/MC/MCExpr.h" 24#include "llvm/MC/MCInst.h" 25#include "llvm/Target/Mangler.h" 26 27using namespace llvm; 28 29MipsMCInstLower::MipsMCInstLower(Mangler *mang, const MachineFunction &mf, 30 MipsAsmPrinter &asmprinter) 31 : Ctx(mf.getContext()), Mang(mang), AsmPrinter(asmprinter) {} 32 33MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, 34 MachineOperandType MOTy, 35 unsigned Offset) const { 36 MCSymbolRefExpr::VariantKind Kind; 37 const MCSymbol *Symbol; 38 39 switch(MO.getTargetFlags()) { 40 default: assert(0 && "Invalid target flag!"); 41 case MipsII::MO_NO_FLAG: Kind = MCSymbolRefExpr::VK_None; break; 42 case MipsII::MO_GPREL: Kind = MCSymbolRefExpr::VK_Mips_GPREL; break; 43 case MipsII::MO_GOT_CALL: Kind = MCSymbolRefExpr::VK_Mips_GOT_CALL; break; 44 case MipsII::MO_GOT16: Kind = MCSymbolRefExpr::VK_Mips_GOT16; break; 45 case MipsII::MO_GOT: Kind = MCSymbolRefExpr::VK_Mips_GOT; break; 46 case MipsII::MO_ABS_HI: Kind = MCSymbolRefExpr::VK_Mips_ABS_HI; break; 47 case MipsII::MO_ABS_LO: Kind = MCSymbolRefExpr::VK_Mips_ABS_LO; break; 48 case MipsII::MO_TLSGD: Kind = MCSymbolRefExpr::VK_Mips_TLSGD; break; 49 case MipsII::MO_GOTTPREL: Kind = MCSymbolRefExpr::VK_Mips_GOTTPREL; break; 50 case MipsII::MO_TPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_TPREL_HI; break; 51 case MipsII::MO_TPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_TPREL_LO; break; 52 case MipsII::MO_GPOFF_HI: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_HI; break; 53 case MipsII::MO_GPOFF_LO: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_LO; break; 54 case MipsII::MO_GOT_DISP: Kind = MCSymbolRefExpr::VK_Mips_GOT_DISP; break; 55 case MipsII::MO_GOT_PAGE: Kind = MCSymbolRefExpr::VK_Mips_GOT_PAGE; break; 56 case MipsII::MO_GOT_OFST: Kind = MCSymbolRefExpr::VK_Mips_GOT_OFST; break; 57 } 58 59 switch (MOTy) { 60 case MachineOperand::MO_MachineBasicBlock: 61 Symbol = MO.getMBB()->getSymbol(); 62 break; 63 64 case MachineOperand::MO_GlobalAddress: 65 Symbol = Mang->getSymbol(MO.getGlobal()); 66 break; 67 68 case MachineOperand::MO_BlockAddress: 69 Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()); 70 break; 71 72 case MachineOperand::MO_ExternalSymbol: 73 Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName()); 74 break; 75 76 case MachineOperand::MO_JumpTableIndex: 77 Symbol = AsmPrinter.GetJTISymbol(MO.getIndex()); 78 break; 79 80 case MachineOperand::MO_ConstantPoolIndex: 81 Symbol = AsmPrinter.GetCPISymbol(MO.getIndex()); 82 if (MO.getOffset()) 83 Offset += MO.getOffset(); 84 break; 85 86 default: 87 llvm_unreachable("<unknown operand type>"); 88 } 89 90 const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol, Kind, Ctx); 91 92 if (!Offset) 93 return MCOperand::CreateExpr(MCSym); 94 95 // Assume offset is never negative. 96 assert(Offset > 0); 97 98 const MCConstantExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx); 99 const MCBinaryExpr *AddExpr = MCBinaryExpr::CreateAdd(MCSym, OffsetExpr, Ctx); 100 return MCOperand::CreateExpr(AddExpr); 101} 102 103// Lower ".cpload $reg" to 104// "lui $gp, %hi(_gp_disp)" 105// "addiu $gp, $gp, %lo(_gp_disp)" 106// "addu $gp. $gp, $reg" 107void MipsMCInstLower::LowerCPLOAD(const MachineInstr *MI, 108 SmallVector<MCInst, 4>& MCInsts) { 109 MCInst Lui, Addiu, Addu; 110 StringRef SymName("_gp_disp"); 111 const MCSymbol *Symbol = Ctx.GetOrCreateSymbol(SymName); 112 const MCSymbolRefExpr *MCSym; 113 114 // lui $gp, %hi(_gp_disp) 115 Lui.setOpcode(Mips::LUi); 116 Lui.addOperand(MCOperand::CreateReg(Mips::GP)); 117 MCSym = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_Mips_ABS_HI, Ctx); 118 Lui.addOperand(MCOperand::CreateExpr(MCSym)); 119 MCInsts.push_back(Lui); 120 121 // addiu $gp, $gp, %lo(_gp_disp) 122 Addiu.setOpcode(Mips::ADDiu); 123 Addiu.addOperand(MCOperand::CreateReg(Mips::GP)); 124 Addiu.addOperand(MCOperand::CreateReg(Mips::GP)); 125 MCSym = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_Mips_ABS_LO, Ctx); 126 Addiu.addOperand(MCOperand::CreateExpr(MCSym)); 127 MCInsts.push_back(Addiu); 128 129 // addu $gp. $gp, $reg 130 Addu.setOpcode(Mips::ADDu); 131 Addu.addOperand(MCOperand::CreateReg(Mips::GP)); 132 Addu.addOperand(MCOperand::CreateReg(Mips::GP)); 133 const MachineOperand &MO = MI->getOperand(0); 134 assert(MO.isReg() && "CPLOAD's operand must be a register."); 135 Addu.addOperand(MCOperand::CreateReg(MO.getReg())); 136 MCInsts.push_back(Addu); 137} 138 139// Lower ".cprestore offset" to "sw $gp, offset($sp)". 140void MipsMCInstLower::LowerCPRESTORE(const MachineInstr *MI, MCInst &OutMI) { 141 OutMI.clear(); 142 OutMI.setOpcode(Mips::SW); 143 OutMI.addOperand(MCOperand::CreateReg(Mips::GP)); 144 OutMI.addOperand(MCOperand::CreateReg(Mips::SP)); 145 const MachineOperand &MO = MI->getOperand(0); 146 assert(MO.isImm() && "CPRESTORE's operand must be an immediate."); 147 OutMI.addOperand(MCOperand::CreateImm(MO.getImm())); 148} 149 150MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO, 151 unsigned offset) const { 152 MachineOperandType MOTy = MO.getType(); 153 154 switch (MOTy) { 155 default: 156 assert(0 && "unknown operand type"); 157 break; 158 case MachineOperand::MO_Register: 159 // Ignore all implicit register operands. 160 if (MO.isImplicit()) break; 161 return MCOperand::CreateReg(MO.getReg()); 162 case MachineOperand::MO_Immediate: 163 return MCOperand::CreateImm(MO.getImm() + offset); 164 case MachineOperand::MO_MachineBasicBlock: 165 case MachineOperand::MO_GlobalAddress: 166 case MachineOperand::MO_ExternalSymbol: 167 case MachineOperand::MO_JumpTableIndex: 168 case MachineOperand::MO_ConstantPoolIndex: 169 case MachineOperand::MO_BlockAddress: 170 return LowerSymbolOperand(MO, MOTy, offset); 171 } 172 173 return MCOperand(); 174} 175 176void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 177 OutMI.setOpcode(MI->getOpcode()); 178 179 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 180 const MachineOperand &MO = MI->getOperand(i); 181 MCOperand MCOp = LowerOperand(MO); 182 183 if (MCOp.isValid()) 184 OutMI.addOperand(MCOp); 185 } 186} 187 188void MipsMCInstLower::LowerUnalignedLoadStore(const MachineInstr *MI, 189 SmallVector<MCInst, 190 4>& MCInsts) { 191 unsigned Opc = MI->getOpcode(); 192 MCInst instr1, instr2, instr3, move; 193 194 bool two_instructions = false; 195 196 assert(MI->getNumOperands() == 3); 197 assert(MI->getOperand(0).isReg()); 198 assert(MI->getOperand(1).isReg()); 199 200 MCOperand target = LowerOperand(MI->getOperand(0)); 201 MCOperand base = LowerOperand(MI->getOperand(1)); 202 MCOperand atReg = MCOperand::CreateReg(Mips::AT); 203 MCOperand zeroReg = MCOperand::CreateReg(Mips::ZERO); 204 205 MachineOperand unloweredName = MI->getOperand(2); 206 MCOperand name = LowerOperand(unloweredName); 207 208 move.setOpcode(Mips::ADDu); 209 move.addOperand(target); 210 move.addOperand(atReg); 211 move.addOperand(zeroReg); 212 213 switch (Opc) { 214 case Mips::ULW: { 215 // FIXME: only works for little endian right now 216 MCOperand adj_name = LowerOperand(unloweredName, 3); 217 if (base.getReg() == (target.getReg())) { 218 instr1.setOpcode(Mips::LWL); 219 instr1.addOperand(atReg); 220 instr1.addOperand(base); 221 instr1.addOperand(adj_name); 222 instr2.setOpcode(Mips::LWR); 223 instr2.addOperand(atReg); 224 instr2.addOperand(base); 225 instr2.addOperand(name); 226 instr3 = move; 227 } else { 228 two_instructions = true; 229 instr1.setOpcode(Mips::LWL); 230 instr1.addOperand(target); 231 instr1.addOperand(base); 232 instr1.addOperand(adj_name); 233 instr2.setOpcode(Mips::LWR); 234 instr2.addOperand(target); 235 instr2.addOperand(base); 236 instr2.addOperand(name); 237 } 238 break; 239 } 240 case Mips::ULHu: { 241 // FIXME: only works for little endian right now 242 MCOperand adj_name = LowerOperand(unloweredName, 1); 243 instr1.setOpcode(Mips::LBu); 244 instr1.addOperand(atReg); 245 instr1.addOperand(base); 246 instr1.addOperand(adj_name); 247 instr2.setOpcode(Mips::LBu); 248 instr2.addOperand(target); 249 instr2.addOperand(base); 250 instr2.addOperand(name); 251 instr3.setOpcode(Mips::INS); 252 instr3.addOperand(target); 253 instr3.addOperand(atReg); 254 instr3.addOperand(MCOperand::CreateImm(0x8)); 255 instr3.addOperand(MCOperand::CreateImm(0x18)); 256 break; 257 } 258 259 case Mips::USW: { 260 // FIXME: only works for little endian right now 261 assert (base.getReg() != target.getReg()); 262 two_instructions = true; 263 MCOperand adj_name = LowerOperand(unloweredName, 3); 264 instr1.setOpcode(Mips::SWL); 265 instr1.addOperand(target); 266 instr1.addOperand(base); 267 instr1.addOperand(adj_name); 268 instr2.setOpcode(Mips::SWR); 269 instr2.addOperand(target); 270 instr2.addOperand(base); 271 instr2.addOperand(name); 272 break; 273 } 274 case Mips::USH: { 275 MCOperand adj_name = LowerOperand(unloweredName, 1); 276 instr1.setOpcode(Mips::SB); 277 instr1.addOperand(target); 278 instr1.addOperand(base); 279 instr1.addOperand(name); 280 instr2.setOpcode(Mips::SRL); 281 instr2.addOperand(atReg); 282 instr2.addOperand(target); 283 instr2.addOperand(MCOperand::CreateImm(8)); 284 instr3.setOpcode(Mips::SB); 285 instr3.addOperand(atReg); 286 instr3.addOperand(base); 287 instr3.addOperand(adj_name); 288 break; 289 } 290 default: 291 // FIXME: need to add others 292 assert(0 && "unaligned instruction not processed"); 293 } 294 295 MCInsts.push_back(instr1); 296 MCInsts.push_back(instr2); 297 if (!two_instructions) MCInsts.push_back(instr3); 298} 299 300