MipsMCInstLower.cpp revision bb481f882093fb738d2bb15610c79364bada5496
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: llvm_unreachable("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_TLSLDM: Kind = MCSymbolRefExpr::VK_Mips_TLSLDM; break; 50 case MipsII::MO_DTPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_HI; break; 51 case MipsII::MO_DTPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_LO; break; 52 case MipsII::MO_GOTTPREL: Kind = MCSymbolRefExpr::VK_Mips_GOTTPREL; break; 53 case MipsII::MO_TPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_TPREL_HI; break; 54 case MipsII::MO_TPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_TPREL_LO; break; 55 case MipsII::MO_GPOFF_HI: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_HI; break; 56 case MipsII::MO_GPOFF_LO: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_LO; break; 57 case MipsII::MO_GOT_DISP: Kind = MCSymbolRefExpr::VK_Mips_GOT_DISP; break; 58 case MipsII::MO_GOT_PAGE: Kind = MCSymbolRefExpr::VK_Mips_GOT_PAGE; break; 59 case MipsII::MO_GOT_OFST: Kind = MCSymbolRefExpr::VK_Mips_GOT_OFST; break; 60 } 61 62 switch (MOTy) { 63 case MachineOperand::MO_MachineBasicBlock: 64 Symbol = MO.getMBB()->getSymbol(); 65 break; 66 67 case MachineOperand::MO_GlobalAddress: 68 Symbol = Mang->getSymbol(MO.getGlobal()); 69 break; 70 71 case MachineOperand::MO_BlockAddress: 72 Symbol = AsmPrinter.GetBlockAddressSymbol(MO.getBlockAddress()); 73 break; 74 75 case MachineOperand::MO_ExternalSymbol: 76 Symbol = AsmPrinter.GetExternalSymbolSymbol(MO.getSymbolName()); 77 break; 78 79 case MachineOperand::MO_JumpTableIndex: 80 Symbol = AsmPrinter.GetJTISymbol(MO.getIndex()); 81 break; 82 83 case MachineOperand::MO_ConstantPoolIndex: 84 Symbol = AsmPrinter.GetCPISymbol(MO.getIndex()); 85 if (MO.getOffset()) 86 Offset += MO.getOffset(); 87 break; 88 89 default: 90 llvm_unreachable("<unknown operand type>"); 91 } 92 93 const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol, Kind, Ctx); 94 95 if (!Offset) 96 return MCOperand::CreateExpr(MCSym); 97 98 // Assume offset is never negative. 99 assert(Offset > 0); 100 101 const MCConstantExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx); 102 const MCBinaryExpr *AddExpr = MCBinaryExpr::CreateAdd(MCSym, OffsetExpr, Ctx); 103 return MCOperand::CreateExpr(AddExpr); 104} 105 106// Lower ".cpload $reg" to 107// "lui $gp, %hi(_gp_disp)" 108// "addiu $gp, $gp, %lo(_gp_disp)" 109// "addu $gp. $gp, $reg" 110void MipsMCInstLower::LowerCPLOAD(const MachineInstr *MI, 111 SmallVector<MCInst, 4>& MCInsts) { 112 MCInst Lui, Addiu, Addu; 113 StringRef SymName("_gp_disp"); 114 const MCSymbol *Symbol = Ctx.GetOrCreateSymbol(SymName); 115 const MCSymbolRefExpr *MCSym; 116 117 // lui $gp, %hi(_gp_disp) 118 Lui.setOpcode(Mips::LUi); 119 Lui.addOperand(MCOperand::CreateReg(Mips::GP)); 120 MCSym = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_Mips_ABS_HI, Ctx); 121 Lui.addOperand(MCOperand::CreateExpr(MCSym)); 122 MCInsts.push_back(Lui); 123 124 // addiu $gp, $gp, %lo(_gp_disp) 125 Addiu.setOpcode(Mips::ADDiu); 126 Addiu.addOperand(MCOperand::CreateReg(Mips::GP)); 127 Addiu.addOperand(MCOperand::CreateReg(Mips::GP)); 128 MCSym = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_Mips_ABS_LO, Ctx); 129 Addiu.addOperand(MCOperand::CreateExpr(MCSym)); 130 MCInsts.push_back(Addiu); 131 132 // addu $gp. $gp, $reg 133 Addu.setOpcode(Mips::ADDu); 134 Addu.addOperand(MCOperand::CreateReg(Mips::GP)); 135 Addu.addOperand(MCOperand::CreateReg(Mips::GP)); 136 const MachineOperand &MO = MI->getOperand(0); 137 assert(MO.isReg() && "CPLOAD's operand must be a register."); 138 Addu.addOperand(MCOperand::CreateReg(MO.getReg())); 139 MCInsts.push_back(Addu); 140} 141 142// Lower ".cprestore offset" to "sw $gp, offset($sp)". 143void MipsMCInstLower::LowerCPRESTORE(const MachineInstr *MI, 144 SmallVector<MCInst, 4>& MCInsts) { 145 const MachineOperand &MO = MI->getOperand(0); 146 assert(MO.isImm() && "CPRESTORE's operand must be an immediate."); 147 unsigned Offset = MO.getImm(), Reg = Mips::SP; 148 MCInst Sw; 149 150 if (Offset >= 0x8000) { 151 unsigned Hi = (Offset >> 16) + ((Offset & 0x8000) != 0); 152 Offset &= 0xffff; 153 Reg = Mips::AT; 154 155 // lui at,hi 156 // addu at,at,sp 157 MCInsts.resize(2); 158 MCInsts[0].setOpcode(Mips::LUi); 159 MCInsts[0].addOperand(MCOperand::CreateReg(Mips::AT)); 160 MCInsts[0].addOperand(MCOperand::CreateImm(Hi)); 161 MCInsts[1].setOpcode(Mips::ADDu); 162 MCInsts[1].addOperand(MCOperand::CreateReg(Mips::AT)); 163 MCInsts[1].addOperand(MCOperand::CreateReg(Mips::AT)); 164 MCInsts[1].addOperand(MCOperand::CreateReg(Mips::SP)); 165 } 166 167 Sw.setOpcode(Mips::SW); 168 Sw.addOperand(MCOperand::CreateReg(Mips::GP)); 169 Sw.addOperand(MCOperand::CreateReg(Reg)); 170 Sw.addOperand(MCOperand::CreateImm(Offset)); 171 MCInsts.push_back(Sw); 172} 173 174MCOperand MipsMCInstLower::LowerOperand(const MachineOperand& MO, 175 unsigned offset) const { 176 MachineOperandType MOTy = MO.getType(); 177 178 switch (MOTy) { 179 default: llvm_unreachable("unknown operand type"); 180 case MachineOperand::MO_Register: 181 // Ignore all implicit register operands. 182 if (MO.isImplicit()) break; 183 return MCOperand::CreateReg(MO.getReg()); 184 case MachineOperand::MO_Immediate: 185 return MCOperand::CreateImm(MO.getImm() + offset); 186 case MachineOperand::MO_MachineBasicBlock: 187 case MachineOperand::MO_GlobalAddress: 188 case MachineOperand::MO_ExternalSymbol: 189 case MachineOperand::MO_JumpTableIndex: 190 case MachineOperand::MO_ConstantPoolIndex: 191 case MachineOperand::MO_BlockAddress: 192 return LowerSymbolOperand(MO, MOTy, offset); 193 case MachineOperand::MO_RegisterMask: 194 break; 195 } 196 197 return MCOperand(); 198} 199 200void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 201 OutMI.setOpcode(MI->getOpcode()); 202 203 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 204 const MachineOperand &MO = MI->getOperand(i); 205 MCOperand MCOp = LowerOperand(MO); 206 207 if (MCOp.isValid()) 208 OutMI.addOperand(MCOp); 209 } 210} 211 212void MipsMCInstLower::LowerUnalignedLoadStore(const MachineInstr *MI, 213 SmallVector<MCInst, 214 4>& MCInsts) { 215 unsigned Opc = MI->getOpcode(); 216 MCInst Instr1, Instr2, Instr3, Move; 217 218 bool TwoInstructions = false; 219 220 assert(MI->getNumOperands() == 3); 221 assert(MI->getOperand(0).isReg()); 222 assert(MI->getOperand(1).isReg()); 223 224 MCOperand Target = LowerOperand(MI->getOperand(0)); 225 MCOperand Base = LowerOperand(MI->getOperand(1)); 226 MCOperand ATReg = MCOperand::CreateReg(Mips::AT); 227 MCOperand ZeroReg = MCOperand::CreateReg(Mips::ZERO); 228 229 MachineOperand UnLoweredName = MI->getOperand(2); 230 MCOperand Name = LowerOperand(UnLoweredName); 231 232 Move.setOpcode(Mips::ADDu); 233 Move.addOperand(Target); 234 Move.addOperand(ATReg); 235 Move.addOperand(ZeroReg); 236 237 switch (Opc) { 238 case Mips::ULW: { 239 // FIXME: only works for little endian right now 240 MCOperand AdjName = LowerOperand(UnLoweredName, 3); 241 if (Base.getReg() == (Target.getReg())) { 242 Instr1.setOpcode(Mips::LWL); 243 Instr1.addOperand(ATReg); 244 Instr1.addOperand(Base); 245 Instr1.addOperand(AdjName); 246 Instr2.setOpcode(Mips::LWR); 247 Instr2.addOperand(ATReg); 248 Instr2.addOperand(Base); 249 Instr2.addOperand(Name); 250 Instr3 = Move; 251 } else { 252 TwoInstructions = true; 253 Instr1.setOpcode(Mips::LWL); 254 Instr1.addOperand(Target); 255 Instr1.addOperand(Base); 256 Instr1.addOperand(AdjName); 257 Instr2.setOpcode(Mips::LWR); 258 Instr2.addOperand(Target); 259 Instr2.addOperand(Base); 260 Instr2.addOperand(Name); 261 } 262 break; 263 } 264 case Mips::ULHu: { 265 // FIXME: only works for little endian right now 266 MCOperand AdjName = LowerOperand(UnLoweredName, 1); 267 Instr1.setOpcode(Mips::LBu); 268 Instr1.addOperand(ATReg); 269 Instr1.addOperand(Base); 270 Instr1.addOperand(AdjName); 271 Instr2.setOpcode(Mips::LBu); 272 Instr2.addOperand(Target); 273 Instr2.addOperand(Base); 274 Instr2.addOperand(Name); 275 Instr3.setOpcode(Mips::INS); 276 Instr3.addOperand(Target); 277 Instr3.addOperand(ATReg); 278 Instr3.addOperand(MCOperand::CreateImm(0x8)); 279 Instr3.addOperand(MCOperand::CreateImm(0x18)); 280 break; 281 } 282 283 case Mips::USW: { 284 // FIXME: only works for little endian right now 285 assert (Base.getReg() != Target.getReg()); 286 TwoInstructions = true; 287 MCOperand AdjName = LowerOperand(UnLoweredName, 3); 288 Instr1.setOpcode(Mips::SWL); 289 Instr1.addOperand(Target); 290 Instr1.addOperand(Base); 291 Instr1.addOperand(AdjName); 292 Instr2.setOpcode(Mips::SWR); 293 Instr2.addOperand(Target); 294 Instr2.addOperand(Base); 295 Instr2.addOperand(Name); 296 break; 297 } 298 case Mips::USH: { 299 MCOperand AdjName = LowerOperand(UnLoweredName, 1); 300 Instr1.setOpcode(Mips::SB); 301 Instr1.addOperand(Target); 302 Instr1.addOperand(Base); 303 Instr1.addOperand(Name); 304 Instr2.setOpcode(Mips::SRL); 305 Instr2.addOperand(ATReg); 306 Instr2.addOperand(Target); 307 Instr2.addOperand(MCOperand::CreateImm(8)); 308 Instr3.setOpcode(Mips::SB); 309 Instr3.addOperand(ATReg); 310 Instr3.addOperand(Base); 311 Instr3.addOperand(AdjName); 312 break; 313 } 314 default: 315 // FIXME: need to add others 316 llvm_unreachable("unaligned instruction not processed"); 317 } 318 319 MCInsts.push_back(Instr1); 320 MCInsts.push_back(Instr2); 321 if (!TwoInstructions) MCInsts.push_back(Instr3); 322} 323 324// Convert 325// "setgp01 $reg" 326// to 327// "lui $reg, %hi(_gp_disp)" 328// "addiu $reg, $reg, %lo(_gp_disp)" 329void MipsMCInstLower::LowerSETGP01(const MachineInstr *MI, 330 SmallVector<MCInst, 4>& MCInsts) { 331 const MachineOperand &MO = MI->getOperand(0); 332 assert(MO.isReg()); 333 MCOperand RegOpnd = MCOperand::CreateReg(MO.getReg()); 334 StringRef SymName("_gp_disp"); 335 const MCSymbol *Sym = Ctx.GetOrCreateSymbol(SymName); 336 const MCSymbolRefExpr *MCSym; 337 338 MCInsts.resize(2); 339 340 MCSym = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_Mips_ABS_HI, Ctx); 341 MCInsts[0].setOpcode(Mips::LUi); 342 MCInsts[0].addOperand(RegOpnd); 343 MCInsts[0].addOperand(MCOperand::CreateExpr(MCSym)); 344 MCSym = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_Mips_ABS_LO, Ctx); 345 MCInsts[1].setOpcode(Mips::ADDiu); 346 MCInsts[1].addOperand(RegOpnd); 347 MCInsts[1].addOperand(RegOpnd); 348 MCInsts[1].addOperand(MCOperand::CreateExpr(MCSym)); 349} 350