MipsMCCodeEmitter.cpp revision 4f8dc7b17accf4f2ec953b80b2cc79786207492e
1//===-- MipsMCCodeEmitter.cpp - Convert Mips code to machine code ---------===// 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 implements the MipsMCCodeEmitter class. 11// 12//===----------------------------------------------------------------------===// 13// 14#define DEBUG_TYPE "mccodeemitter" 15#include "MCTargetDesc/MipsBaseInfo.h" 16#include "MCTargetDesc/MipsFixupKinds.h" 17#include "MCTargetDesc/MipsMCTargetDesc.h" 18#include "llvm/ADT/APFloat.h" 19#include "llvm/ADT/Statistic.h" 20#include "llvm/MC/MCCodeEmitter.h" 21#include "llvm/MC/MCExpr.h" 22#include "llvm/MC/MCInst.h" 23#include "llvm/MC/MCInstrInfo.h" 24#include "llvm/MC/MCRegisterInfo.h" 25#include "llvm/MC/MCSubtargetInfo.h" 26#include "llvm/Support/raw_ostream.h" 27 28using namespace llvm; 29 30namespace { 31class MipsMCCodeEmitter : public MCCodeEmitter { 32 MipsMCCodeEmitter(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT 33 void operator=(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT 34 const MCInstrInfo &MCII; 35 const MCSubtargetInfo &STI; 36 MCContext &Ctx; 37 38public: 39 MipsMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, 40 MCContext &ctx) : MCII(mcii), STI(sti) , Ctx(ctx) {} 41 42 ~MipsMCCodeEmitter() {} 43 44 void EmitByte(unsigned char C, raw_ostream &OS) const { 45 OS << (char)C; 46 } 47 48 void EmitInstruction(uint64_t Val, unsigned Size, raw_ostream &OS) const { 49 // Output the instruction encoding in little endian byte order. 50 for (unsigned i = 0; i != Size; ++i) { 51 EmitByte(Val & 255, OS); 52 Val >>= 8; 53 } 54 } 55 56 void EncodeInstruction(const MCInst &MI, raw_ostream &OS, 57 SmallVectorImpl<MCFixup> &Fixups) const; 58 59 // getBinaryCodeForInstr - TableGen'erated function for getting the 60 // binary encoding for an instruction. 61 uint64_t getBinaryCodeForInstr(const MCInst &MI, 62 SmallVectorImpl<MCFixup> &Fixups) const; 63 64 // getBranchJumpOpValue - Return binary encoding of the jump 65 // target operand. If the machine operand requires relocation, 66 // record the relocation and return zero. 67 unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, 68 SmallVectorImpl<MCFixup> &Fixups) const; 69 70 // getBranchTargetOpValue - Return binary encoding of the branch 71 // target operand. If the machine operand requires relocation, 72 // record the relocation and return zero. 73 unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 74 SmallVectorImpl<MCFixup> &Fixups) const; 75 76 // getMachineOpValue - Return binary encoding of operand. If the machin 77 // operand requires relocation, record the relocation and return zero. 78 unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, 79 SmallVectorImpl<MCFixup> &Fixups) const; 80 81 unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, 82 SmallVectorImpl<MCFixup> &Fixups) const; 83 unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo, 84 SmallVectorImpl<MCFixup> &Fixups) const; 85 unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo, 86 SmallVectorImpl<MCFixup> &Fixups) const; 87 88}; // class MipsMCCodeEmitter 89} // namespace 90 91MCCodeEmitter *llvm::createMipsMCCodeEmitter(const MCInstrInfo &MCII, 92 const MCSubtargetInfo &STI, 93 MCContext &Ctx) 94{ 95 return new MipsMCCodeEmitter(MCII, STI, Ctx); 96} 97 98/// EncodeInstruction - Emit the instruction. 99/// Size the instruction (currently only 4 bytes 100void MipsMCCodeEmitter:: 101EncodeInstruction(const MCInst &MI, raw_ostream &OS, 102 SmallVectorImpl<MCFixup> &Fixups) const 103{ 104 uint32_t Binary = getBinaryCodeForInstr(MI, Fixups); 105 106 // Check for unimplemented opcodes. 107 // Unfortunately in MIPS both NOT and SLL will come in with Binary == 0 108 // so we have to special check for them. 109 unsigned Opcode = MI.getOpcode(); 110 if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary) 111 llvm_unreachable("unimplemented opcode in EncodeInstruction()"); 112 113 const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 114 uint64_t TSFlags = Desc.TSFlags; 115 116 // Pseudo instructions don't get encoded and shouldn't be here 117 // in the first place! 118 if ((TSFlags & MipsII::FormMask) == MipsII::Pseudo) 119 llvm_unreachable("Pseudo opcode found in EncodeInstruction()"); 120 121 // For now all instructions are 4 bytes 122 int Size = 4; // FIXME: Have Desc.getSize() return the correct value! 123 124 EmitInstruction(Binary, Size, OS); 125} 126 127/// getBranchTargetOpValue - Return binary encoding of the branch 128/// target operand. If the machine operand requires relocation, 129/// record the relocation and return zero. 130unsigned MipsMCCodeEmitter:: 131getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 132 SmallVectorImpl<MCFixup> &Fixups) const { 133 134 const MCOperand &MO = MI.getOperand(OpNo); 135 assert(MO.isExpr() && "getBranchTargetOpValue expects only expressions"); 136 137 const MCExpr *Expr = MO.getExpr(); 138 Fixups.push_back(MCFixup::Create(0, Expr, 139 MCFixupKind(Mips::fixup_Mips_PC16))); 140 return 0; 141} 142 143/// getJumpTargetOpValue - Return binary encoding of the jump 144/// target operand. If the machine operand requires relocation, 145/// record the relocation and return zero. 146unsigned MipsMCCodeEmitter:: 147getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, 148 SmallVectorImpl<MCFixup> &Fixups) const { 149 150 const MCOperand &MO = MI.getOperand(OpNo); 151 assert(MO.isExpr() && "getJumpTargetOpValue expects only expressions"); 152 153 const MCExpr *Expr = MO.getExpr(); 154 Fixups.push_back(MCFixup::Create(0, Expr, 155 MCFixupKind(Mips::fixup_Mips_26))); 156 return 0; 157} 158 159/// getMachineOpValue - Return binary encoding of operand. If the machine 160/// operand requires relocation, record the relocation and return zero. 161unsigned MipsMCCodeEmitter:: 162getMachineOpValue(const MCInst &MI, const MCOperand &MO, 163 SmallVectorImpl<MCFixup> &Fixups) const { 164 if (MO.isReg()) { 165 unsigned Reg = MO.getReg(); 166 unsigned RegNo = getMipsRegisterNumbering(Reg); 167 return RegNo; 168 } else if (MO.isImm()) { 169 return static_cast<unsigned>(MO.getImm()); 170 } else if (MO.isFPImm()) { 171 return static_cast<unsigned>(APFloat(MO.getFPImm()) 172 .bitcastToAPInt().getHiBits(32).getLimitedValue()); 173 } else if (MO.isExpr()) { 174 const MCExpr *Expr = MO.getExpr(); 175 MCExpr::ExprKind Kind = Expr->getKind(); 176 unsigned Ret = 0; 177 178 if (Kind == MCExpr::Binary) { 179 const MCBinaryExpr *BE = static_cast<const MCBinaryExpr*>(Expr); 180 Expr = BE->getLHS(); 181 Kind = Expr->getKind(); 182 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(BE->getRHS()); 183 assert((Kind == MCExpr::SymbolRef) && CE && 184 "Binary expression must be sym+const."); 185 Ret = CE->getValue(); 186 } 187 188 if (Kind == MCExpr::SymbolRef) { 189 Mips::Fixups FixupKind; 190 191 switch(cast<MCSymbolRefExpr>(Expr)->getKind()) { 192 case MCSymbolRefExpr::VK_Mips_GPREL: 193 FixupKind = Mips::fixup_Mips_GPREL16; 194 break; 195 case MCSymbolRefExpr::VK_Mips_GOT_CALL: 196 FixupKind = Mips::fixup_Mips_CALL16; 197 break; 198 case MCSymbolRefExpr::VK_Mips_GOT16: 199 FixupKind = Mips::fixup_Mips_GOT_Global; 200 break; 201 case MCSymbolRefExpr::VK_Mips_GOT: 202 FixupKind = Mips::fixup_Mips_GOT_Local; 203 break; 204 case MCSymbolRefExpr::VK_Mips_ABS_HI: 205 FixupKind = Mips::fixup_Mips_HI16; 206 break; 207 case MCSymbolRefExpr::VK_Mips_ABS_LO: 208 FixupKind = Mips::fixup_Mips_LO16; 209 break; 210 case MCSymbolRefExpr::VK_Mips_TLSGD: 211 FixupKind = Mips::fixup_Mips_TLSGD; 212 break; 213 case MCSymbolRefExpr::VK_Mips_TLSLDM: 214 FixupKind = Mips::fixup_Mips_TLSLDM; 215 break; 216 case MCSymbolRefExpr::VK_Mips_DTPREL_HI: 217 FixupKind = Mips::fixup_Mips_DTPREL_HI; 218 break; 219 case MCSymbolRefExpr::VK_Mips_DTPREL_LO: 220 FixupKind = Mips::fixup_Mips_DTPREL_LO; 221 break; 222 case MCSymbolRefExpr::VK_Mips_GOTTPREL: 223 FixupKind = Mips::fixup_Mips_GOTTPREL; 224 break; 225 case MCSymbolRefExpr::VK_Mips_TPREL_HI: 226 FixupKind = Mips::fixup_Mips_TPREL_HI; 227 break; 228 case MCSymbolRefExpr::VK_Mips_TPREL_LO: 229 FixupKind = Mips::fixup_Mips_TPREL_LO; 230 break; 231 default: 232 return Ret; 233 } // switch 234 Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind))); 235 } // if SymbolRef 236 // All of the information is in the fixup. 237 return Ret; 238 } 239 llvm_unreachable("Unable to encode MCOperand!"); 240} 241 242/// getMemEncoding - Return binary encoding of memory related operand. 243/// If the offset operand requires relocation, record the relocation. 244unsigned 245MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, 246 SmallVectorImpl<MCFixup> &Fixups) const { 247 // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. 248 assert(MI.getOperand(OpNo).isReg()); 249 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups) << 16; 250 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups); 251 252 return (OffBits & 0xFFFF) | RegBits; 253} 254 255unsigned 256MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo, 257 SmallVectorImpl<MCFixup> &Fixups) const { 258 assert(MI.getOperand(OpNo).isImm()); 259 unsigned SizeEncoding = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups); 260 return SizeEncoding - 1; 261} 262 263// FIXME: should be called getMSBEncoding 264// 265unsigned 266MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo, 267 SmallVectorImpl<MCFixup> &Fixups) const { 268 assert(MI.getOperand(OpNo-1).isImm()); 269 assert(MI.getOperand(OpNo).isImm()); 270 unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups); 271 unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups); 272 273 return Position + Size - 1; 274} 275 276#include "MipsGenMCCodeEmitter.inc" 277 278