1750ecec7SAkira Hatanaka //===-- MipsMCCodeEmitter.cpp - Convert Mips code to machine code ---------===// 2750ecec7SAkira Hatanaka // 3750ecec7SAkira Hatanaka // The LLVM Compiler Infrastructure 4750ecec7SAkira Hatanaka // 5750ecec7SAkira Hatanaka // This file is distributed under the University of Illinois Open Source 6750ecec7SAkira Hatanaka // License. See LICENSE.TXT for details. 7750ecec7SAkira Hatanaka // 8750ecec7SAkira Hatanaka //===----------------------------------------------------------------------===// 9750ecec7SAkira Hatanaka // 10750ecec7SAkira Hatanaka // This file implements the MipsMCCodeEmitter class. 11750ecec7SAkira Hatanaka // 12750ecec7SAkira Hatanaka //===----------------------------------------------------------------------===// 13750ecec7SAkira Hatanaka // 14750ecec7SAkira Hatanaka #define DEBUG_TYPE "mccodeemitter" 15*c85e3ff3SBruno Cardoso Lopes #include "MCTargetDesc/MipsBaseInfo.h" 16*c85e3ff3SBruno Cardoso Lopes #include "MCTargetDesc/MipsFixupKinds.h" 17*c85e3ff3SBruno Cardoso Lopes #include "MCTargetDesc/MipsMCTargetDesc.h" 18*c85e3ff3SBruno Cardoso Lopes #include "llvm/ADT/APFloat.h" 19*c85e3ff3SBruno Cardoso Lopes #include "llvm/ADT/Statistic.h" 20750ecec7SAkira Hatanaka #include "llvm/MC/MCCodeEmitter.h" 21750ecec7SAkira Hatanaka #include "llvm/MC/MCExpr.h" 22750ecec7SAkira Hatanaka #include "llvm/MC/MCInst.h" 23750ecec7SAkira Hatanaka #include "llvm/MC/MCInstrInfo.h" 24750ecec7SAkira Hatanaka #include "llvm/MC/MCRegisterInfo.h" 25750ecec7SAkira Hatanaka #include "llvm/MC/MCSubtargetInfo.h" 26750ecec7SAkira Hatanaka #include "llvm/Support/raw_ostream.h" 27750ecec7SAkira Hatanaka 28750ecec7SAkira Hatanaka using namespace llvm; 29750ecec7SAkira Hatanaka 30750ecec7SAkira Hatanaka namespace { 31750ecec7SAkira Hatanaka class MipsMCCodeEmitter : public MCCodeEmitter { 32750ecec7SAkira Hatanaka MipsMCCodeEmitter(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT 33750ecec7SAkira Hatanaka void operator=(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT 34750ecec7SAkira Hatanaka const MCInstrInfo &MCII; 35750ecec7SAkira Hatanaka const MCSubtargetInfo &STI; 36*c85e3ff3SBruno Cardoso Lopes MCContext &Ctx; 37750ecec7SAkira Hatanaka 38750ecec7SAkira Hatanaka public: 39750ecec7SAkira Hatanaka MipsMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti, 40*c85e3ff3SBruno Cardoso Lopes MCContext &ctx) : MCII(mcii), STI(sti) , Ctx(ctx) {} 41750ecec7SAkira Hatanaka 42750ecec7SAkira Hatanaka ~MipsMCCodeEmitter() {} 43750ecec7SAkira Hatanaka 44*c85e3ff3SBruno Cardoso Lopes void EmitByte(unsigned char C, raw_ostream &OS) const { 45*c85e3ff3SBruno Cardoso Lopes OS << (char)C; 46750ecec7SAkira Hatanaka } 47*c85e3ff3SBruno Cardoso Lopes 48*c85e3ff3SBruno Cardoso Lopes void EmitInstruction(uint64_t Val, unsigned Size, raw_ostream &OS) const { 49*c85e3ff3SBruno Cardoso Lopes // Output the instruction encoding in little endian byte order. 50*c85e3ff3SBruno Cardoso Lopes for (unsigned i = 0; i != Size; ++i) { 51*c85e3ff3SBruno Cardoso Lopes EmitByte(Val & 255, OS); 52*c85e3ff3SBruno Cardoso Lopes Val >>= 8; 53*c85e3ff3SBruno Cardoso Lopes } 54*c85e3ff3SBruno Cardoso Lopes } 55*c85e3ff3SBruno Cardoso Lopes 56*c85e3ff3SBruno Cardoso Lopes void EncodeInstruction(const MCInst &MI, raw_ostream &OS, 57*c85e3ff3SBruno Cardoso Lopes SmallVectorImpl<MCFixup> &Fixups) const; 58*c85e3ff3SBruno Cardoso Lopes 59*c85e3ff3SBruno Cardoso Lopes // getBinaryCodeForInstr - TableGen'erated function for getting the 60*c85e3ff3SBruno Cardoso Lopes // binary encoding for an instruction. 61*c85e3ff3SBruno Cardoso Lopes unsigned getBinaryCodeForInstr(const MCInst &MI, 62*c85e3ff3SBruno Cardoso Lopes SmallVectorImpl<MCFixup> &Fixups) const; 63*c85e3ff3SBruno Cardoso Lopes 64*c85e3ff3SBruno Cardoso Lopes // getBranchJumpOpValue - Return binary encoding of the jump 65*c85e3ff3SBruno Cardoso Lopes // target operand. If the machine operand requires relocation, 66*c85e3ff3SBruno Cardoso Lopes // record the relocation and return zero. 67*c85e3ff3SBruno Cardoso Lopes unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, 68*c85e3ff3SBruno Cardoso Lopes SmallVectorImpl<MCFixup> &Fixups) const; 69*c85e3ff3SBruno Cardoso Lopes 70*c85e3ff3SBruno Cardoso Lopes // getBranchTargetOpValue - Return binary encoding of the branch 71*c85e3ff3SBruno Cardoso Lopes // target operand. If the machine operand requires relocation, 72*c85e3ff3SBruno Cardoso Lopes // record the relocation and return zero. 73*c85e3ff3SBruno Cardoso Lopes unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 74*c85e3ff3SBruno Cardoso Lopes SmallVectorImpl<MCFixup> &Fixups) const; 75*c85e3ff3SBruno Cardoso Lopes 76*c85e3ff3SBruno Cardoso Lopes // getMachineOpValue - Return binary encoding of operand. If the machin 77*c85e3ff3SBruno Cardoso Lopes // operand requires relocation, record the relocation and return zero. 78*c85e3ff3SBruno Cardoso Lopes unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO, 79*c85e3ff3SBruno Cardoso Lopes SmallVectorImpl<MCFixup> &Fixups) const; 80*c85e3ff3SBruno Cardoso Lopes 81*c85e3ff3SBruno Cardoso Lopes unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, 82*c85e3ff3SBruno Cardoso Lopes SmallVectorImpl<MCFixup> &Fixups) const; 83*c85e3ff3SBruno Cardoso Lopes unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo, 84*c85e3ff3SBruno Cardoso Lopes SmallVectorImpl<MCFixup> &Fixups) const; 85*c85e3ff3SBruno Cardoso Lopes unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo, 86*c85e3ff3SBruno Cardoso Lopes SmallVectorImpl<MCFixup> &Fixups) const; 87*c85e3ff3SBruno Cardoso Lopes 88750ecec7SAkira Hatanaka }; // class MipsMCCodeEmitter 89750ecec7SAkira Hatanaka } // namespace 90750ecec7SAkira Hatanaka 91750ecec7SAkira Hatanaka MCCodeEmitter *llvm::createMipsMCCodeEmitter(const MCInstrInfo &MCII, 92750ecec7SAkira Hatanaka const MCSubtargetInfo &STI, 93*c85e3ff3SBruno Cardoso Lopes MCContext &Ctx) 94*c85e3ff3SBruno Cardoso Lopes { 95750ecec7SAkira Hatanaka return new MipsMCCodeEmitter(MCII, STI, Ctx); 96750ecec7SAkira Hatanaka } 97*c85e3ff3SBruno Cardoso Lopes 98*c85e3ff3SBruno Cardoso Lopes /// EncodeInstruction - Emit the instruction. 99*c85e3ff3SBruno Cardoso Lopes /// Size the instruction (currently only 4 bytes 100*c85e3ff3SBruno Cardoso Lopes void MipsMCCodeEmitter:: 101*c85e3ff3SBruno Cardoso Lopes EncodeInstruction(const MCInst &MI, raw_ostream &OS, 102*c85e3ff3SBruno Cardoso Lopes SmallVectorImpl<MCFixup> &Fixups) const 103*c85e3ff3SBruno Cardoso Lopes { 104*c85e3ff3SBruno Cardoso Lopes uint32_t Binary = getBinaryCodeForInstr(MI, Fixups); 105*c85e3ff3SBruno Cardoso Lopes 106*c85e3ff3SBruno Cardoso Lopes // Check for unimplemented opcodes. 107*c85e3ff3SBruno Cardoso Lopes // Unfortunately in MIPS both NOT and SLL will come in with Binary == 0 108*c85e3ff3SBruno Cardoso Lopes // so we have to special check for them. 109*c85e3ff3SBruno Cardoso Lopes unsigned Opcode = MI.getOpcode(); 110*c85e3ff3SBruno Cardoso Lopes if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary) 111*c85e3ff3SBruno Cardoso Lopes llvm_unreachable("unimplemented opcode in EncodeInstruction()"); 112*c85e3ff3SBruno Cardoso Lopes 113*c85e3ff3SBruno Cardoso Lopes const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); 114*c85e3ff3SBruno Cardoso Lopes uint64_t TSFlags = Desc.TSFlags; 115*c85e3ff3SBruno Cardoso Lopes 116*c85e3ff3SBruno Cardoso Lopes // Pseudo instructions don't get encoded and shouldn't be here 117*c85e3ff3SBruno Cardoso Lopes // in the first place! 118*c85e3ff3SBruno Cardoso Lopes if ((TSFlags & MipsII::FormMask) == MipsII::Pseudo) 119*c85e3ff3SBruno Cardoso Lopes llvm_unreachable("Pseudo opcode found in EncodeInstruction()"); 120*c85e3ff3SBruno Cardoso Lopes 121*c85e3ff3SBruno Cardoso Lopes // For now all instructions are 4 bytes 122*c85e3ff3SBruno Cardoso Lopes int Size = 4; // FIXME: Have Desc.getSize() return the correct value! 123*c85e3ff3SBruno Cardoso Lopes 124*c85e3ff3SBruno Cardoso Lopes EmitInstruction(Binary, Size, OS); 125*c85e3ff3SBruno Cardoso Lopes } 126*c85e3ff3SBruno Cardoso Lopes 127*c85e3ff3SBruno Cardoso Lopes /// getBranchTargetOpValue - Return binary encoding of the branch 128*c85e3ff3SBruno Cardoso Lopes /// target operand. If the machine operand requires relocation, 129*c85e3ff3SBruno Cardoso Lopes /// record the relocation and return zero. 130*c85e3ff3SBruno Cardoso Lopes unsigned MipsMCCodeEmitter:: 131*c85e3ff3SBruno Cardoso Lopes getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, 132*c85e3ff3SBruno Cardoso Lopes SmallVectorImpl<MCFixup> &Fixups) const { 133*c85e3ff3SBruno Cardoso Lopes 134*c85e3ff3SBruno Cardoso Lopes const MCOperand &MO = MI.getOperand(OpNo); 135*c85e3ff3SBruno Cardoso Lopes assert(MO.isExpr() && "getBranchTargetOpValue expects only expressions"); 136*c85e3ff3SBruno Cardoso Lopes 137*c85e3ff3SBruno Cardoso Lopes const MCExpr *Expr = MO.getExpr(); 138*c85e3ff3SBruno Cardoso Lopes Fixups.push_back(MCFixup::Create(0, Expr, 139*c85e3ff3SBruno Cardoso Lopes MCFixupKind(Mips::fixup_Mips_PC16))); 140*c85e3ff3SBruno Cardoso Lopes return 0; 141*c85e3ff3SBruno Cardoso Lopes } 142*c85e3ff3SBruno Cardoso Lopes 143*c85e3ff3SBruno Cardoso Lopes /// getJumpTargetOpValue - Return binary encoding of the jump 144*c85e3ff3SBruno Cardoso Lopes /// target operand. If the machine operand requires relocation, 145*c85e3ff3SBruno Cardoso Lopes /// record the relocation and return zero. 146*c85e3ff3SBruno Cardoso Lopes unsigned MipsMCCodeEmitter:: 147*c85e3ff3SBruno Cardoso Lopes getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, 148*c85e3ff3SBruno Cardoso Lopes SmallVectorImpl<MCFixup> &Fixups) const { 149*c85e3ff3SBruno Cardoso Lopes 150*c85e3ff3SBruno Cardoso Lopes const MCOperand &MO = MI.getOperand(OpNo); 151*c85e3ff3SBruno Cardoso Lopes assert(MO.isExpr() && "getJumpTargetOpValue expects only expressions"); 152*c85e3ff3SBruno Cardoso Lopes 153*c85e3ff3SBruno Cardoso Lopes const MCExpr *Expr = MO.getExpr(); 154*c85e3ff3SBruno Cardoso Lopes Fixups.push_back(MCFixup::Create(0, Expr, 155*c85e3ff3SBruno Cardoso Lopes MCFixupKind(Mips::fixup_Mips_26))); 156*c85e3ff3SBruno Cardoso Lopes return 0; 157*c85e3ff3SBruno Cardoso Lopes } 158*c85e3ff3SBruno Cardoso Lopes 159*c85e3ff3SBruno Cardoso Lopes /// getMachineOpValue - Return binary encoding of operand. If the machine 160*c85e3ff3SBruno Cardoso Lopes /// operand requires relocation, record the relocation and return zero. 161*c85e3ff3SBruno Cardoso Lopes unsigned MipsMCCodeEmitter:: 162*c85e3ff3SBruno Cardoso Lopes getMachineOpValue(const MCInst &MI, const MCOperand &MO, 163*c85e3ff3SBruno Cardoso Lopes SmallVectorImpl<MCFixup> &Fixups) const { 164*c85e3ff3SBruno Cardoso Lopes if (MO.isReg()) { 165*c85e3ff3SBruno Cardoso Lopes unsigned Reg = MO.getReg(); 166*c85e3ff3SBruno Cardoso Lopes unsigned RegNo = getMipsRegisterNumbering(Reg); 167*c85e3ff3SBruno Cardoso Lopes return RegNo; 168*c85e3ff3SBruno Cardoso Lopes } else if (MO.isImm()) { 169*c85e3ff3SBruno Cardoso Lopes return static_cast<unsigned>(MO.getImm()); 170*c85e3ff3SBruno Cardoso Lopes } else if (MO.isFPImm()) { 171*c85e3ff3SBruno Cardoso Lopes return static_cast<unsigned>(APFloat(MO.getFPImm()) 172*c85e3ff3SBruno Cardoso Lopes .bitcastToAPInt().getHiBits(32).getLimitedValue()); 173*c85e3ff3SBruno Cardoso Lopes } else if (MO.isExpr()) { 174*c85e3ff3SBruno Cardoso Lopes const MCExpr *Expr = MO.getExpr(); 175*c85e3ff3SBruno Cardoso Lopes MCExpr::ExprKind Kind = Expr->getKind(); 176*c85e3ff3SBruno Cardoso Lopes if (Kind == MCExpr::SymbolRef) { 177*c85e3ff3SBruno Cardoso Lopes Mips::Fixups FixupKind = Mips::fixup_Mips_NONE; 178*c85e3ff3SBruno Cardoso Lopes MCSymbolRefExpr::VariantKind SymRefKind = 179*c85e3ff3SBruno Cardoso Lopes cast<MCSymbolRefExpr>(Expr)->getKind(); 180*c85e3ff3SBruno Cardoso Lopes switch(SymRefKind) { 181*c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_GPREL: 182*c85e3ff3SBruno Cardoso Lopes FixupKind = Mips::fixup_Mips_GPREL16; 183*c85e3ff3SBruno Cardoso Lopes break; 184*c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_GOT_CALL: 185*c85e3ff3SBruno Cardoso Lopes FixupKind = Mips::fixup_Mips_CALL16; 186*c85e3ff3SBruno Cardoso Lopes break; 187*c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_GOT: 188*c85e3ff3SBruno Cardoso Lopes FixupKind = Mips::fixup_Mips_GOT16; 189*c85e3ff3SBruno Cardoso Lopes break; 190*c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_ABS_HI: 191*c85e3ff3SBruno Cardoso Lopes FixupKind = Mips::fixup_Mips_HI16; 192*c85e3ff3SBruno Cardoso Lopes break; 193*c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_ABS_LO: 194*c85e3ff3SBruno Cardoso Lopes FixupKind = Mips::fixup_Mips_LO16; 195*c85e3ff3SBruno Cardoso Lopes break; 196*c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_TLSGD: 197*c85e3ff3SBruno Cardoso Lopes FixupKind = Mips::fixup_Mips_TLSGD; 198*c85e3ff3SBruno Cardoso Lopes break; 199*c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_GOTTPREL: 200*c85e3ff3SBruno Cardoso Lopes FixupKind = Mips::fixup_Mips_GOTTPREL; 201*c85e3ff3SBruno Cardoso Lopes break; 202*c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_TPREL_HI: 203*c85e3ff3SBruno Cardoso Lopes FixupKind = Mips::fixup_Mips_TPREL_HI; 204*c85e3ff3SBruno Cardoso Lopes break; 205*c85e3ff3SBruno Cardoso Lopes case MCSymbolRefExpr::VK_Mips_TPREL_LO: 206*c85e3ff3SBruno Cardoso Lopes FixupKind = Mips::fixup_Mips_TPREL_LO; 207*c85e3ff3SBruno Cardoso Lopes break; 208*c85e3ff3SBruno Cardoso Lopes default: 209*c85e3ff3SBruno Cardoso Lopes return 0; 210*c85e3ff3SBruno Cardoso Lopes } // switch 211*c85e3ff3SBruno Cardoso Lopes Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind))); 212*c85e3ff3SBruno Cardoso Lopes } // if SymbolRef 213*c85e3ff3SBruno Cardoso Lopes // All of the information is in the fixup. 214*c85e3ff3SBruno Cardoso Lopes return 0; 215*c85e3ff3SBruno Cardoso Lopes } 216*c85e3ff3SBruno Cardoso Lopes llvm_unreachable("Unable to encode MCOperand!"); 217*c85e3ff3SBruno Cardoso Lopes // Not reached 218*c85e3ff3SBruno Cardoso Lopes return 0; 219*c85e3ff3SBruno Cardoso Lopes } 220*c85e3ff3SBruno Cardoso Lopes 221*c85e3ff3SBruno Cardoso Lopes /// getMemEncoding - Return binary encoding of memory related operand. 222*c85e3ff3SBruno Cardoso Lopes /// If the offset operand requires relocation, record the relocation. 223*c85e3ff3SBruno Cardoso Lopes unsigned 224*c85e3ff3SBruno Cardoso Lopes MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, 225*c85e3ff3SBruno Cardoso Lopes SmallVectorImpl<MCFixup> &Fixups) const { 226*c85e3ff3SBruno Cardoso Lopes // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. 227*c85e3ff3SBruno Cardoso Lopes assert(MI.getOperand(OpNo).isReg()); 228*c85e3ff3SBruno Cardoso Lopes unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups) << 16; 229*c85e3ff3SBruno Cardoso Lopes unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups); 230*c85e3ff3SBruno Cardoso Lopes 231*c85e3ff3SBruno Cardoso Lopes return (OffBits & 0xFFFF) | RegBits; 232*c85e3ff3SBruno Cardoso Lopes } 233*c85e3ff3SBruno Cardoso Lopes 234*c85e3ff3SBruno Cardoso Lopes unsigned 235*c85e3ff3SBruno Cardoso Lopes MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo, 236*c85e3ff3SBruno Cardoso Lopes SmallVectorImpl<MCFixup> &Fixups) const { 237*c85e3ff3SBruno Cardoso Lopes // FIXME: implement 238*c85e3ff3SBruno Cardoso Lopes return 0; 239*c85e3ff3SBruno Cardoso Lopes } 240*c85e3ff3SBruno Cardoso Lopes 241*c85e3ff3SBruno Cardoso Lopes unsigned 242*c85e3ff3SBruno Cardoso Lopes MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo, 243*c85e3ff3SBruno Cardoso Lopes SmallVectorImpl<MCFixup> &Fixups) const { 244*c85e3ff3SBruno Cardoso Lopes // FIXME: implement 245*c85e3ff3SBruno Cardoso Lopes return 0; 246*c85e3ff3SBruno Cardoso Lopes } 247*c85e3ff3SBruno Cardoso Lopes 248*c85e3ff3SBruno Cardoso Lopes #include "MipsGenMCCodeEmitter.inc" 249*c85e3ff3SBruno Cardoso Lopes 250