Home | History | Annotate | Download | only in MCTargetDesc
      1 //===-- PPCMCCodeEmitter.cpp - Convert PPC 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 PPCMCCodeEmitter class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #define DEBUG_TYPE "mccodeemitter"
     15 #include "MCTargetDesc/PPCMCTargetDesc.h"
     16 #include "MCTargetDesc/PPCBaseInfo.h"
     17 #include "MCTargetDesc/PPCFixupKinds.h"
     18 #include "llvm/ADT/Statistic.h"
     19 #include "llvm/MC/MCCodeEmitter.h"
     20 #include "llvm/MC/MCExpr.h"
     21 #include "llvm/MC/MCInst.h"
     22 #include "llvm/MC/MCInstrInfo.h"
     23 #include "llvm/MC/MCSubtargetInfo.h"
     24 #include "llvm/Support/ErrorHandling.h"
     25 #include "llvm/Support/raw_ostream.h"
     26 using namespace llvm;
     27 
     28 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
     29 
     30 namespace {
     31 class PPCMCCodeEmitter : public MCCodeEmitter {
     32   PPCMCCodeEmitter(const PPCMCCodeEmitter &) LLVM_DELETED_FUNCTION;
     33   void operator=(const PPCMCCodeEmitter &) LLVM_DELETED_FUNCTION;
     34 
     35   const MCSubtargetInfo &STI;
     36   Triple TT;
     37 
     38 public:
     39   PPCMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
     40                    MCContext &ctx)
     41     : STI(sti), TT(STI.getTargetTriple()) {
     42   }
     43 
     44   ~PPCMCCodeEmitter() {}
     45 
     46   bool is64BitMode() const {
     47     return (STI.getFeatureBits() & PPC::Feature64Bit) != 0;
     48   }
     49 
     50   bool isSVR4ABI() const {
     51     return TT.isMacOSX() == 0;
     52   }
     53 
     54   unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
     55                                SmallVectorImpl<MCFixup> &Fixups) const;
     56   unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo,
     57                              SmallVectorImpl<MCFixup> &Fixups) const;
     58   unsigned getHA16Encoding(const MCInst &MI, unsigned OpNo,
     59                            SmallVectorImpl<MCFixup> &Fixups) const;
     60   unsigned getLO16Encoding(const MCInst &MI, unsigned OpNo,
     61                            SmallVectorImpl<MCFixup> &Fixups) const;
     62   unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo,
     63                             SmallVectorImpl<MCFixup> &Fixups) const;
     64   unsigned getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
     65                              SmallVectorImpl<MCFixup> &Fixups) const;
     66   unsigned getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
     67                              SmallVectorImpl<MCFixup> &Fixups) const;
     68   unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
     69                                SmallVectorImpl<MCFixup> &Fixups) const;
     70 
     71   /// getMachineOpValue - Return binary encoding of operand. If the machine
     72   /// operand requires relocation, record the relocation and return zero.
     73   unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
     74                              SmallVectorImpl<MCFixup> &Fixups) const;
     75 
     76   // getBinaryCodeForInstr - TableGen'erated function for getting the
     77   // binary encoding for an instruction.
     78   uint64_t getBinaryCodeForInstr(const MCInst &MI,
     79                                  SmallVectorImpl<MCFixup> &Fixups) const;
     80   void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
     81                          SmallVectorImpl<MCFixup> &Fixups) const {
     82     uint64_t Bits = getBinaryCodeForInstr(MI, Fixups);
     83 
     84     // BL8_NOP_ELF, BLA8_NOP_ELF, etc., all have a size of 8 because of the
     85     // following 'nop'.
     86     unsigned Size = 4; // FIXME: Have Desc.getSize() return the correct value!
     87     unsigned Opcode = MI.getOpcode();
     88     if (Opcode == PPC::BL8_NOP_ELF || Opcode == PPC::BLA8_NOP_ELF ||
     89         Opcode == PPC::BL8_NOP_ELF_TLSGD || Opcode == PPC::BL8_NOP_ELF_TLSLD)
     90       Size = 8;
     91 
     92     // Output the constant in big endian byte order.
     93     int ShiftValue = (Size * 8) - 8;
     94     for (unsigned i = 0; i != Size; ++i) {
     95       OS << (char)(Bits >> ShiftValue);
     96       Bits <<= 8;
     97     }
     98 
     99     ++MCNumEmitted;  // Keep track of the # of mi's emitted.
    100   }
    101 
    102 };
    103 
    104 } // end anonymous namespace
    105 
    106 MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII,
    107                                             const MCRegisterInfo &MRI,
    108                                             const MCSubtargetInfo &STI,
    109                                             MCContext &Ctx) {
    110   return new PPCMCCodeEmitter(MCII, STI, Ctx);
    111 }
    112 
    113 unsigned PPCMCCodeEmitter::
    114 getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
    115                     SmallVectorImpl<MCFixup> &Fixups) const {
    116   const MCOperand &MO = MI.getOperand(OpNo);
    117   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
    118 
    119   // Add a fixup for the branch target.
    120   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
    121                                    (MCFixupKind)PPC::fixup_ppc_br24));
    122 
    123   // For special TLS calls, add another fixup for the symbol.  Apparently
    124   // BL8_NOP_ELF, BL8_NOP_ELF_TLSGD, and BL8_NOP_ELF_TLSLD are sufficiently
    125   // similar that TblGen will not generate a separate case for the latter
    126   // two, so this is the only way to get the extra fixup generated.
    127   unsigned Opcode = MI.getOpcode();
    128   if (Opcode == PPC::BL8_NOP_ELF_TLSGD || Opcode == PPC::BL8_NOP_ELF_TLSLD) {
    129     const MCOperand &MO2 = MI.getOperand(OpNo+1);
    130     Fixups.push_back(MCFixup::Create(0, MO2.getExpr(),
    131                                      (MCFixupKind)PPC::fixup_ppc_nofixup));
    132   }
    133   return 0;
    134 }
    135 
    136 unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
    137                                      SmallVectorImpl<MCFixup> &Fixups) const {
    138   const MCOperand &MO = MI.getOperand(OpNo);
    139   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
    140 
    141   // Add a fixup for the branch target.
    142   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
    143                                    (MCFixupKind)PPC::fixup_ppc_brcond14));
    144   return 0;
    145 }
    146 
    147 unsigned PPCMCCodeEmitter::getHA16Encoding(const MCInst &MI, unsigned OpNo,
    148                                        SmallVectorImpl<MCFixup> &Fixups) const {
    149   const MCOperand &MO = MI.getOperand(OpNo);
    150   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
    151 
    152   // Add a fixup for the branch target.
    153   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
    154                                    (MCFixupKind)PPC::fixup_ppc_ha16));
    155   return 0;
    156 }
    157 
    158 unsigned PPCMCCodeEmitter::getLO16Encoding(const MCInst &MI, unsigned OpNo,
    159                                        SmallVectorImpl<MCFixup> &Fixups) const {
    160   const MCOperand &MO = MI.getOperand(OpNo);
    161   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
    162 
    163   // Add a fixup for the branch target.
    164   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
    165                                    (MCFixupKind)PPC::fixup_ppc_lo16));
    166   return 0;
    167 }
    168 
    169 unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
    170                                             SmallVectorImpl<MCFixup> &Fixups) const {
    171   // Encode (imm, reg) as a memri, which has the low 16-bits as the
    172   // displacement and the next 5 bits as the register #.
    173   assert(MI.getOperand(OpNo+1).isReg());
    174   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups) << 16;
    175 
    176   const MCOperand &MO = MI.getOperand(OpNo);
    177   if (MO.isImm())
    178     return (getMachineOpValue(MI, MO, Fixups) & 0xFFFF) | RegBits;
    179 
    180   // Add a fixup for the displacement field.
    181   if (isSVR4ABI() && is64BitMode())
    182     Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
    183                                      (MCFixupKind)PPC::fixup_ppc_toc16));
    184   else
    185     Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
    186                                      (MCFixupKind)PPC::fixup_ppc_lo16));
    187   return RegBits;
    188 }
    189 
    190 
    191 unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
    192                                        SmallVectorImpl<MCFixup> &Fixups) const {
    193   // Encode (imm, reg) as a memrix, which has the low 14-bits as the
    194   // displacement and the next 5 bits as the register #.
    195   assert(MI.getOperand(OpNo+1).isReg());
    196   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups) << 14;
    197 
    198   const MCOperand &MO = MI.getOperand(OpNo);
    199   if (MO.isImm())
    200     return (getMachineOpValue(MI, MO, Fixups) & 0x3FFF) | RegBits;
    201 
    202   // Add a fixup for the branch target.
    203   if (isSVR4ABI() && is64BitMode())
    204     Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
    205                                      (MCFixupKind)PPC::fixup_ppc_toc16_ds));
    206   else
    207     Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
    208                                      (MCFixupKind)PPC::fixup_ppc_lo14));
    209   return RegBits;
    210 }
    211 
    212 
    213 unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
    214                                        SmallVectorImpl<MCFixup> &Fixups) const {
    215   const MCOperand &MO = MI.getOperand(OpNo);
    216   if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups);
    217 
    218   // Add a fixup for the TLS register, which simply provides a relocation
    219   // hint to the linker that this statement is part of a relocation sequence.
    220   // Return the thread-pointer register's encoding.
    221   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
    222                                    (MCFixupKind)PPC::fixup_ppc_tlsreg));
    223   return getPPCRegisterNumbering(PPC::X13);
    224 }
    225 
    226 unsigned PPCMCCodeEmitter::
    227 get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
    228                     SmallVectorImpl<MCFixup> &Fixups) const {
    229   const MCOperand &MO = MI.getOperand(OpNo);
    230   assert((MI.getOpcode() == PPC::MTCRF ||
    231           MI.getOpcode() == PPC::MFOCRF ||
    232           MI.getOpcode() == PPC::MTCRF8) &&
    233          (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
    234   return 0x80 >> getPPCRegisterNumbering(MO.getReg());
    235 }
    236 
    237 
    238 unsigned PPCMCCodeEmitter::
    239 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
    240                   SmallVectorImpl<MCFixup> &Fixups) const {
    241   if (MO.isReg()) {
    242     // MTCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
    243     // The GPR operand should come through here though.
    244     assert((MI.getOpcode() != PPC::MTCRF && MI.getOpcode() != PPC::MFOCRF) ||
    245            MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
    246     return getPPCRegisterNumbering(MO.getReg());
    247   }
    248 
    249   assert(MO.isImm() &&
    250          "Relocation required in an instruction that we cannot encode!");
    251   return MO.getImm();
    252 }
    253 
    254 
    255 #include "PPCGenMCCodeEmitter.inc"
    256