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