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/MipsDirectObjLower.h"
     17 #include "MCTargetDesc/MipsFixupKinds.h"
     18 #include "MCTargetDesc/MipsMCTargetDesc.h"
     19 #include "llvm/ADT/APFloat.h"
     20 #include "llvm/ADT/Statistic.h"
     21 #include "llvm/MC/MCCodeEmitter.h"
     22 #include "llvm/MC/MCContext.h"
     23 #include "llvm/MC/MCExpr.h"
     24 #include "llvm/MC/MCInst.h"
     25 #include "llvm/MC/MCInstrInfo.h"
     26 #include "llvm/MC/MCRegisterInfo.h"
     27 #include "llvm/MC/MCSubtargetInfo.h"
     28 #include "llvm/Support/raw_ostream.h"
     29 
     30 using namespace llvm;
     31 
     32 namespace {
     33 class MipsMCCodeEmitter : public MCCodeEmitter {
     34   MipsMCCodeEmitter(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION;
     35   void operator=(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION;
     36   const MCInstrInfo &MCII;
     37   MCContext &Ctx;
     38   bool IsLittleEndian;
     39 
     40 public:
     41   MipsMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_,
     42                     const MCSubtargetInfo &sti, bool IsLittle) :
     43     MCII(mcii), Ctx(Ctx_), IsLittleEndian(IsLittle) {}
     44 
     45   ~MipsMCCodeEmitter() {}
     46 
     47   void EmitByte(unsigned char C, raw_ostream &OS) const {
     48     OS << (char)C;
     49   }
     50 
     51   void EmitInstruction(uint64_t Val, unsigned Size, raw_ostream &OS) const {
     52     // Output the instruction encoding in little endian byte order.
     53     for (unsigned i = 0; i < Size; ++i) {
     54       unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8;
     55       EmitByte((Val >> Shift) & 0xff, OS);
     56     }
     57   }
     58 
     59   void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
     60                          SmallVectorImpl<MCFixup> &Fixups) const;
     61 
     62   // getBinaryCodeForInstr - TableGen'erated function for getting the
     63   // binary encoding for an instruction.
     64   uint64_t getBinaryCodeForInstr(const MCInst &MI,
     65                                  SmallVectorImpl<MCFixup> &Fixups) const;
     66 
     67   // getBranchJumpOpValue - Return binary encoding of the jump
     68   // target operand. If the machine operand requires relocation,
     69   // record the relocation and return zero.
     70    unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
     71                                  SmallVectorImpl<MCFixup> &Fixups) const;
     72 
     73    // getBranchTargetOpValue - Return binary encoding of the branch
     74    // target operand. If the machine operand requires relocation,
     75    // record the relocation and return zero.
     76   unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
     77                                   SmallVectorImpl<MCFixup> &Fixups) const;
     78 
     79    // getMachineOpValue - Return binary encoding of operand. If the machin
     80    // operand requires relocation, record the relocation and return zero.
     81   unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
     82                              SmallVectorImpl<MCFixup> &Fixups) const;
     83 
     84   unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
     85                           SmallVectorImpl<MCFixup> &Fixups) const;
     86   unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
     87                               SmallVectorImpl<MCFixup> &Fixups) const;
     88   unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
     89                               SmallVectorImpl<MCFixup> &Fixups) const;
     90 
     91 }; // class MipsMCCodeEmitter
     92 }  // namespace
     93 
     94 MCCodeEmitter *llvm::createMipsMCCodeEmitterEB(const MCInstrInfo &MCII,
     95                                                const MCRegisterInfo &MRI,
     96                                                const MCSubtargetInfo &STI,
     97                                                MCContext &Ctx)
     98 {
     99   return new MipsMCCodeEmitter(MCII, Ctx, STI, false);
    100 }
    101 
    102 MCCodeEmitter *llvm::createMipsMCCodeEmitterEL(const MCInstrInfo &MCII,
    103                                                const MCRegisterInfo &MRI,
    104                                                const MCSubtargetInfo &STI,
    105                                                MCContext &Ctx)
    106 {
    107   return new MipsMCCodeEmitter(MCII, Ctx, STI, true);
    108 }
    109 
    110 /// EncodeInstruction - Emit the instruction.
    111 /// Size the instruction (currently only 4 bytes
    112 void MipsMCCodeEmitter::
    113 EncodeInstruction(const MCInst &MI, raw_ostream &OS,
    114                   SmallVectorImpl<MCFixup> &Fixups) const
    115 {
    116 
    117   // Non-pseudo instructions that get changed for direct object
    118   // only based on operand values.
    119   // If this list of instructions get much longer we will move
    120   // the check to a function call. Until then, this is more efficient.
    121   MCInst TmpInst = MI;
    122   switch (MI.getOpcode()) {
    123   // If shift amount is >= 32 it the inst needs to be lowered further
    124   case Mips::DSLL:
    125   case Mips::DSRL:
    126   case Mips::DSRA:
    127     Mips::LowerLargeShift(TmpInst);
    128     break;
    129     // Double extract instruction is chosen by pos and size operands
    130   case Mips::DEXT:
    131   case Mips::DINS:
    132     Mips::LowerDextDins(TmpInst);
    133   }
    134 
    135   uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups);
    136 
    137   // Check for unimplemented opcodes.
    138   // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0
    139   // so we have to special check for them.
    140   unsigned Opcode = TmpInst.getOpcode();
    141   if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary)
    142     llvm_unreachable("unimplemented opcode in EncodeInstruction()");
    143 
    144   const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode());
    145 
    146   // Get byte count of instruction
    147   unsigned Size = Desc.getSize();
    148   if (!Size)
    149     llvm_unreachable("Desc.getSize() returns 0");
    150 
    151   EmitInstruction(Binary, Size, OS);
    152 }
    153 
    154 /// getBranchTargetOpValue - Return binary encoding of the branch
    155 /// target operand. If the machine operand requires relocation,
    156 /// record the relocation and return zero.
    157 unsigned MipsMCCodeEmitter::
    158 getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
    159                        SmallVectorImpl<MCFixup> &Fixups) const {
    160 
    161   const MCOperand &MO = MI.getOperand(OpNo);
    162 
    163   // If the destination is an immediate, we have nothing to do.
    164   if (MO.isImm()) return MO.getImm();
    165   assert(MO.isExpr() &&
    166          "getBranchTargetOpValue expects only expressions or immediates");
    167 
    168   const MCExpr *Expr = MO.getExpr();
    169   Fixups.push_back(MCFixup::Create(0, Expr,
    170                                    MCFixupKind(Mips::fixup_Mips_PC16)));
    171   return 0;
    172 }
    173 
    174 /// getJumpTargetOpValue - Return binary encoding of the jump
    175 /// target operand. If the machine operand requires relocation,
    176 /// record the relocation and return zero.
    177 unsigned MipsMCCodeEmitter::
    178 getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
    179                      SmallVectorImpl<MCFixup> &Fixups) const {
    180 
    181   const MCOperand &MO = MI.getOperand(OpNo);
    182   // If the destination is an immediate, we have nothing to do.
    183   if (MO.isImm()) return MO.getImm();
    184   assert(MO.isExpr() &&
    185          "getJumpTargetOpValue expects only expressions or an immediate");
    186 
    187   const MCExpr *Expr = MO.getExpr();
    188   Fixups.push_back(MCFixup::Create(0, Expr,
    189                                    MCFixupKind(Mips::fixup_Mips_26)));
    190   return 0;
    191 }
    192 
    193 /// getMachineOpValue - Return binary encoding of operand. If the machine
    194 /// operand requires relocation, record the relocation and return zero.
    195 unsigned MipsMCCodeEmitter::
    196 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
    197                   SmallVectorImpl<MCFixup> &Fixups) const {
    198   if (MO.isReg()) {
    199     unsigned Reg = MO.getReg();
    200     unsigned RegNo = Ctx.getRegisterInfo().getEncodingValue(Reg);
    201     return RegNo;
    202   } else if (MO.isImm()) {
    203     return static_cast<unsigned>(MO.getImm());
    204   } else if (MO.isFPImm()) {
    205     return static_cast<unsigned>(APFloat(MO.getFPImm())
    206         .bitcastToAPInt().getHiBits(32).getLimitedValue());
    207   }
    208 
    209   // MO must be an Expr.
    210   assert(MO.isExpr());
    211 
    212   const MCExpr *Expr = MO.getExpr();
    213   MCExpr::ExprKind Kind = Expr->getKind();
    214 
    215   if (Kind == MCExpr::Binary) {
    216     Expr = static_cast<const MCBinaryExpr*>(Expr)->getLHS();
    217     Kind = Expr->getKind();
    218   }
    219 
    220   assert (Kind == MCExpr::SymbolRef);
    221 
    222   Mips::Fixups FixupKind = Mips::Fixups(0);
    223 
    224   switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
    225   default: llvm_unreachable("Unknown fixup kind!");
    226     break;
    227   case MCSymbolRefExpr::VK_Mips_GPOFF_HI :
    228     FixupKind = Mips::fixup_Mips_GPOFF_HI;
    229     break;
    230   case MCSymbolRefExpr::VK_Mips_GPOFF_LO :
    231     FixupKind = Mips::fixup_Mips_GPOFF_LO;
    232     break;
    233   case MCSymbolRefExpr::VK_Mips_GOT_PAGE :
    234     FixupKind = Mips::fixup_Mips_GOT_PAGE;
    235     break;
    236   case MCSymbolRefExpr::VK_Mips_GOT_OFST :
    237     FixupKind = Mips::fixup_Mips_GOT_OFST;
    238     break;
    239   case MCSymbolRefExpr::VK_Mips_GOT_DISP :
    240     FixupKind = Mips::fixup_Mips_GOT_DISP;
    241     break;
    242   case MCSymbolRefExpr::VK_Mips_GPREL:
    243     FixupKind = Mips::fixup_Mips_GPREL16;
    244     break;
    245   case MCSymbolRefExpr::VK_Mips_GOT_CALL:
    246     FixupKind = Mips::fixup_Mips_CALL16;
    247     break;
    248   case MCSymbolRefExpr::VK_Mips_GOT16:
    249     FixupKind = Mips::fixup_Mips_GOT_Global;
    250     break;
    251   case MCSymbolRefExpr::VK_Mips_GOT:
    252     FixupKind = Mips::fixup_Mips_GOT_Local;
    253     break;
    254   case MCSymbolRefExpr::VK_Mips_ABS_HI:
    255     FixupKind = Mips::fixup_Mips_HI16;
    256     break;
    257   case MCSymbolRefExpr::VK_Mips_ABS_LO:
    258     FixupKind = Mips::fixup_Mips_LO16;
    259     break;
    260   case MCSymbolRefExpr::VK_Mips_TLSGD:
    261     FixupKind = Mips::fixup_Mips_TLSGD;
    262     break;
    263   case MCSymbolRefExpr::VK_Mips_TLSLDM:
    264     FixupKind = Mips::fixup_Mips_TLSLDM;
    265     break;
    266   case MCSymbolRefExpr::VK_Mips_DTPREL_HI:
    267     FixupKind = Mips::fixup_Mips_DTPREL_HI;
    268     break;
    269   case MCSymbolRefExpr::VK_Mips_DTPREL_LO:
    270     FixupKind = Mips::fixup_Mips_DTPREL_LO;
    271     break;
    272   case MCSymbolRefExpr::VK_Mips_GOTTPREL:
    273     FixupKind = Mips::fixup_Mips_GOTTPREL;
    274     break;
    275   case MCSymbolRefExpr::VK_Mips_TPREL_HI:
    276     FixupKind = Mips::fixup_Mips_TPREL_HI;
    277     break;
    278   case MCSymbolRefExpr::VK_Mips_TPREL_LO:
    279     FixupKind = Mips::fixup_Mips_TPREL_LO;
    280     break;
    281   case MCSymbolRefExpr::VK_Mips_HIGHER:
    282     FixupKind = Mips::fixup_Mips_HIGHER;
    283     break;
    284   case MCSymbolRefExpr::VK_Mips_HIGHEST:
    285     FixupKind = Mips::fixup_Mips_HIGHEST;
    286     break;
    287   case MCSymbolRefExpr::VK_Mips_GOT_HI16:
    288     FixupKind = Mips::fixup_Mips_GOT_HI16;
    289     break;
    290   case MCSymbolRefExpr::VK_Mips_GOT_LO16:
    291     FixupKind = Mips::fixup_Mips_GOT_LO16;
    292     break;
    293   case MCSymbolRefExpr::VK_Mips_CALL_HI16:
    294     FixupKind = Mips::fixup_Mips_CALL_HI16;
    295     break;
    296   case MCSymbolRefExpr::VK_Mips_CALL_LO16:
    297     FixupKind = Mips::fixup_Mips_CALL_LO16;
    298     break;
    299   } // switch
    300 
    301   Fixups.push_back(MCFixup::Create(0, MO.getExpr(), MCFixupKind(FixupKind)));
    302 
    303   // All of the information is in the fixup.
    304   return 0;
    305 }
    306 
    307 /// getMemEncoding - Return binary encoding of memory related operand.
    308 /// If the offset operand requires relocation, record the relocation.
    309 unsigned
    310 MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
    311                                   SmallVectorImpl<MCFixup> &Fixups) const {
    312   // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
    313   assert(MI.getOperand(OpNo).isReg());
    314   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups) << 16;
    315   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups);
    316 
    317   return (OffBits & 0xFFFF) | RegBits;
    318 }
    319 
    320 unsigned
    321 MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
    322                                       SmallVectorImpl<MCFixup> &Fixups) const {
    323   assert(MI.getOperand(OpNo).isImm());
    324   unsigned SizeEncoding = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups);
    325   return SizeEncoding - 1;
    326 }
    327 
    328 // FIXME: should be called getMSBEncoding
    329 //
    330 unsigned
    331 MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
    332                                       SmallVectorImpl<MCFixup> &Fixups) const {
    333   assert(MI.getOperand(OpNo-1).isImm());
    334   assert(MI.getOperand(OpNo).isImm());
    335   unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups);
    336   unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups);
    337 
    338   return Position + Size - 1;
    339 }
    340 
    341 #include "MipsGenMCCodeEmitter.inc"
    342 
    343