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