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 #include "MCTargetDesc/PPCMCTargetDesc.h"
     15 #include "MCTargetDesc/PPCFixupKinds.h"
     16 #include "llvm/ADT/Statistic.h"
     17 #include "llvm/MC/MCAsmInfo.h"
     18 #include "llvm/MC/MCCodeEmitter.h"
     19 #include "llvm/MC/MCContext.h"
     20 #include "llvm/MC/MCExpr.h"
     21 #include "llvm/MC/MCInst.h"
     22 #include "llvm/MC/MCInstrInfo.h"
     23 #include "llvm/MC/MCRegisterInfo.h"
     24 #include "llvm/MC/MCSubtargetInfo.h"
     25 #include "llvm/Support/EndianStream.h"
     26 #include "llvm/Support/ErrorHandling.h"
     27 #include "llvm/Support/raw_ostream.h"
     28 #include "llvm/Target/TargetOpcodes.h"
     29 using namespace llvm;
     30 
     31 #define DEBUG_TYPE "mccodeemitter"
     32 
     33 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
     34 
     35 namespace {
     36 class PPCMCCodeEmitter : public MCCodeEmitter {
     37   PPCMCCodeEmitter(const PPCMCCodeEmitter &) = delete;
     38   void operator=(const PPCMCCodeEmitter &) = delete;
     39 
     40   const MCInstrInfo &MCII;
     41   const MCContext &CTX;
     42   bool IsLittleEndian;
     43 
     44 public:
     45   PPCMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
     46       : MCII(mcii), CTX(ctx),
     47         IsLittleEndian(ctx.getAsmInfo()->isLittleEndian()) {}
     48 
     49   ~PPCMCCodeEmitter() override {}
     50 
     51   unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
     52                                SmallVectorImpl<MCFixup> &Fixups,
     53                                const MCSubtargetInfo &STI) const;
     54   unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo,
     55                              SmallVectorImpl<MCFixup> &Fixups,
     56                              const MCSubtargetInfo &STI) const;
     57   unsigned getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo,
     58                                   SmallVectorImpl<MCFixup> &Fixups,
     59                                   const MCSubtargetInfo &STI) const;
     60   unsigned getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo,
     61                                 SmallVectorImpl<MCFixup> &Fixups,
     62                                 const MCSubtargetInfo &STI) const;
     63   unsigned getImm16Encoding(const MCInst &MI, unsigned OpNo,
     64                              SmallVectorImpl<MCFixup> &Fixups,
     65                              const MCSubtargetInfo &STI) const;
     66   unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo,
     67                             SmallVectorImpl<MCFixup> &Fixups,
     68                             const MCSubtargetInfo &STI) const;
     69   unsigned getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
     70                              SmallVectorImpl<MCFixup> &Fixups,
     71                              const MCSubtargetInfo &STI) const;
     72   unsigned getMemRIX16Encoding(const MCInst &MI, unsigned OpNo,
     73                                SmallVectorImpl<MCFixup> &Fixups,
     74                                const MCSubtargetInfo &STI) const;
     75   unsigned getSPE8DisEncoding(const MCInst &MI, unsigned OpNo,
     76                               SmallVectorImpl<MCFixup> &Fixups,
     77                               const MCSubtargetInfo &STI) const;
     78   unsigned getSPE4DisEncoding(const MCInst &MI, unsigned OpNo,
     79                               SmallVectorImpl<MCFixup> &Fixups,
     80                               const MCSubtargetInfo &STI) const;
     81   unsigned getSPE2DisEncoding(const MCInst &MI, unsigned OpNo,
     82                               SmallVectorImpl<MCFixup> &Fixups,
     83                               const MCSubtargetInfo &STI) const;
     84   unsigned getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
     85                              SmallVectorImpl<MCFixup> &Fixups,
     86                              const MCSubtargetInfo &STI) const;
     87   unsigned getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
     88                               SmallVectorImpl<MCFixup> &Fixups,
     89                               const MCSubtargetInfo &STI) const;
     90   unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
     91                                SmallVectorImpl<MCFixup> &Fixups,
     92                                const MCSubtargetInfo &STI) const;
     93 
     94   /// getMachineOpValue - Return binary encoding of operand. If the machine
     95   /// operand requires relocation, record the relocation and return zero.
     96   unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
     97                              SmallVectorImpl<MCFixup> &Fixups,
     98                              const MCSubtargetInfo &STI) const;
     99 
    100   // getBinaryCodeForInstr - TableGen'erated function for getting the
    101   // binary encoding for an instruction.
    102   uint64_t getBinaryCodeForInstr(const MCInst &MI,
    103                                  SmallVectorImpl<MCFixup> &Fixups,
    104                                  const MCSubtargetInfo &STI) const;
    105   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
    106                          SmallVectorImpl<MCFixup> &Fixups,
    107                          const MCSubtargetInfo &STI) const override {
    108     unsigned Opcode = MI.getOpcode();
    109     const MCInstrDesc &Desc = MCII.get(Opcode);
    110 
    111     uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
    112 
    113     // Output the constant in big/little endian byte order.
    114     unsigned Size = Desc.getSize();
    115     switch (Size) {
    116     case 0:
    117       break;
    118     case 4:
    119       if (IsLittleEndian) {
    120         support::endian::Writer<support::little>(OS).write<uint32_t>(Bits);
    121       } else {
    122         support::endian::Writer<support::big>(OS).write<uint32_t>(Bits);
    123       }
    124       break;
    125     case 8:
    126       // If we emit a pair of instructions, the first one is
    127       // always in the top 32 bits, even on little-endian.
    128       if (IsLittleEndian) {
    129         uint64_t Swapped = (Bits << 32) | (Bits >> 32);
    130         support::endian::Writer<support::little>(OS).write<uint64_t>(Swapped);
    131       } else {
    132         support::endian::Writer<support::big>(OS).write<uint64_t>(Bits);
    133       }
    134       break;
    135     default:
    136       llvm_unreachable ("Invalid instruction size");
    137     }
    138 
    139     ++MCNumEmitted;  // Keep track of the # of mi's emitted.
    140   }
    141 
    142 };
    143 
    144 } // end anonymous namespace
    145 
    146 MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII,
    147                                             const MCRegisterInfo &MRI,
    148                                             MCContext &Ctx) {
    149   return new PPCMCCodeEmitter(MCII, Ctx);
    150 }
    151 
    152 unsigned PPCMCCodeEmitter::
    153 getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
    154                     SmallVectorImpl<MCFixup> &Fixups,
    155                     const MCSubtargetInfo &STI) const {
    156   const MCOperand &MO = MI.getOperand(OpNo);
    157   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
    158 
    159   // Add a fixup for the branch target.
    160   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
    161                                    (MCFixupKind)PPC::fixup_ppc_br24));
    162   return 0;
    163 }
    164 
    165 unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
    166                                      SmallVectorImpl<MCFixup> &Fixups,
    167                                      const MCSubtargetInfo &STI) const {
    168   const MCOperand &MO = MI.getOperand(OpNo);
    169   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
    170 
    171   // Add a fixup for the branch target.
    172   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
    173                                    (MCFixupKind)PPC::fixup_ppc_brcond14));
    174   return 0;
    175 }
    176 
    177 unsigned PPCMCCodeEmitter::
    178 getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo,
    179                        SmallVectorImpl<MCFixup> &Fixups,
    180                        const MCSubtargetInfo &STI) const {
    181   const MCOperand &MO = MI.getOperand(OpNo);
    182   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
    183 
    184   // Add a fixup for the branch target.
    185   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
    186                                    (MCFixupKind)PPC::fixup_ppc_br24abs));
    187   return 0;
    188 }
    189 
    190 unsigned PPCMCCodeEmitter::
    191 getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo,
    192                      SmallVectorImpl<MCFixup> &Fixups,
    193                      const MCSubtargetInfo &STI) const {
    194   const MCOperand &MO = MI.getOperand(OpNo);
    195   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
    196 
    197   // Add a fixup for the branch target.
    198   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
    199                                    (MCFixupKind)PPC::fixup_ppc_brcond14abs));
    200   return 0;
    201 }
    202 
    203 unsigned PPCMCCodeEmitter::getImm16Encoding(const MCInst &MI, unsigned OpNo,
    204                                        SmallVectorImpl<MCFixup> &Fixups,
    205                                        const MCSubtargetInfo &STI) const {
    206   const MCOperand &MO = MI.getOperand(OpNo);
    207   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
    208 
    209   // Add a fixup for the immediate field.
    210   Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
    211                                    (MCFixupKind)PPC::fixup_ppc_half16));
    212   return 0;
    213 }
    214 
    215 unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
    216                                             SmallVectorImpl<MCFixup> &Fixups,
    217                                             const MCSubtargetInfo &STI) const {
    218   // Encode (imm, reg) as a memri, which has the low 16-bits as the
    219   // displacement and the next 5 bits as the register #.
    220   assert(MI.getOperand(OpNo+1).isReg());
    221   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 16;
    222 
    223   const MCOperand &MO = MI.getOperand(OpNo);
    224   if (MO.isImm())
    225     return (getMachineOpValue(MI, MO, Fixups, STI) & 0xFFFF) | RegBits;
    226 
    227   // Add a fixup for the displacement field.
    228   Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
    229                                    (MCFixupKind)PPC::fixup_ppc_half16));
    230   return RegBits;
    231 }
    232 
    233 
    234 unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
    235                                        SmallVectorImpl<MCFixup> &Fixups,
    236                                        const MCSubtargetInfo &STI) const {
    237   // Encode (imm, reg) as a memrix, which has the low 14-bits as the
    238   // displacement and the next 5 bits as the register #.
    239   assert(MI.getOperand(OpNo+1).isReg());
    240   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 14;
    241 
    242   const MCOperand &MO = MI.getOperand(OpNo);
    243   if (MO.isImm())
    244     return ((getMachineOpValue(MI, MO, Fixups, STI) >> 2) & 0x3FFF) | RegBits;
    245 
    246   // Add a fixup for the displacement field.
    247   Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
    248                                    (MCFixupKind)PPC::fixup_ppc_half16ds));
    249   return RegBits;
    250 }
    251 
    252 unsigned PPCMCCodeEmitter::getMemRIX16Encoding(const MCInst &MI, unsigned OpNo,
    253                                        SmallVectorImpl<MCFixup> &Fixups,
    254                                        const MCSubtargetInfo &STI) const {
    255   // Encode (imm, reg) as a memrix16, which has the low 12-bits as the
    256   // displacement and the next 5 bits as the register #.
    257   assert(MI.getOperand(OpNo+1).isReg());
    258   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 12;
    259 
    260   const MCOperand &MO = MI.getOperand(OpNo);
    261   assert(MO.isImm());
    262 
    263   return ((getMachineOpValue(MI, MO, Fixups, STI) >> 4) & 0xFFF) | RegBits;
    264 }
    265 
    266 unsigned PPCMCCodeEmitter::getSPE8DisEncoding(const MCInst &MI, unsigned OpNo,
    267                                               SmallVectorImpl<MCFixup> &Fixups,
    268                                               const MCSubtargetInfo &STI)
    269                                               const {
    270   // Encode (imm, reg) as a spe8dis, which has the low 5-bits of (imm / 8)
    271   // as the displacement and the next 5 bits as the register #.
    272   assert(MI.getOperand(OpNo+1).isReg());
    273   uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
    274 
    275   const MCOperand &MO = MI.getOperand(OpNo);
    276   assert(MO.isImm());
    277   uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 3;
    278   return reverseBits(Imm | RegBits) >> 22;
    279 }
    280 
    281 
    282 unsigned PPCMCCodeEmitter::getSPE4DisEncoding(const MCInst &MI, unsigned OpNo,
    283                                               SmallVectorImpl<MCFixup> &Fixups,
    284                                               const MCSubtargetInfo &STI)
    285                                               const {
    286   // Encode (imm, reg) as a spe4dis, which has the low 5-bits of (imm / 4)
    287   // as the displacement and the next 5 bits as the register #.
    288   assert(MI.getOperand(OpNo+1).isReg());
    289   uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
    290 
    291   const MCOperand &MO = MI.getOperand(OpNo);
    292   assert(MO.isImm());
    293   uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 2;
    294   return reverseBits(Imm | RegBits) >> 22;
    295 }
    296 
    297 
    298 unsigned PPCMCCodeEmitter::getSPE2DisEncoding(const MCInst &MI, unsigned OpNo,
    299                                               SmallVectorImpl<MCFixup> &Fixups,
    300                                               const MCSubtargetInfo &STI)
    301                                               const {
    302   // Encode (imm, reg) as a spe2dis, which has the low 5-bits of (imm / 2)
    303   // as the displacement and the next 5 bits as the register #.
    304   assert(MI.getOperand(OpNo+1).isReg());
    305   uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
    306 
    307   const MCOperand &MO = MI.getOperand(OpNo);
    308   assert(MO.isImm());
    309   uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 1;
    310   return reverseBits(Imm | RegBits) >> 22;
    311 }
    312 
    313 
    314 unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
    315                                        SmallVectorImpl<MCFixup> &Fixups,
    316                                        const MCSubtargetInfo &STI) const {
    317   const MCOperand &MO = MI.getOperand(OpNo);
    318   if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups, STI);
    319 
    320   // Add a fixup for the TLS register, which simply provides a relocation
    321   // hint to the linker that this statement is part of a relocation sequence.
    322   // Return the thread-pointer register's encoding.
    323   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
    324                                    (MCFixupKind)PPC::fixup_ppc_nofixup));
    325   const Triple &TT = STI.getTargetTriple();
    326   bool isPPC64 = TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le;
    327   return CTX.getRegisterInfo()->getEncodingValue(isPPC64 ? PPC::X13 : PPC::R2);
    328 }
    329 
    330 unsigned PPCMCCodeEmitter::getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
    331                                        SmallVectorImpl<MCFixup> &Fixups,
    332                                        const MCSubtargetInfo &STI) const {
    333   // For special TLS calls, we need two fixups; one for the branch target
    334   // (__tls_get_addr), which we create via getDirectBrEncoding as usual,
    335   // and one for the TLSGD or TLSLD symbol, which is emitted here.
    336   const MCOperand &MO = MI.getOperand(OpNo+1);
    337   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
    338                                    (MCFixupKind)PPC::fixup_ppc_nofixup));
    339   return getDirectBrEncoding(MI, OpNo, Fixups, STI);
    340 }
    341 
    342 unsigned PPCMCCodeEmitter::
    343 get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
    344                     SmallVectorImpl<MCFixup> &Fixups,
    345                     const MCSubtargetInfo &STI) const {
    346   const MCOperand &MO = MI.getOperand(OpNo);
    347   assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 ||
    348           MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) &&
    349          (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
    350   return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
    351 }
    352 
    353 
    354 unsigned PPCMCCodeEmitter::
    355 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
    356                   SmallVectorImpl<MCFixup> &Fixups,
    357                   const MCSubtargetInfo &STI) const {
    358   if (MO.isReg()) {
    359     // MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
    360     // The GPR operand should come through here though.
    361     assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 &&
    362             MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) ||
    363            MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
    364     return CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
    365   }
    366 
    367   assert(MO.isImm() &&
    368          "Relocation required in an instruction that we cannot encode!");
    369   return MO.getImm();
    370 }
    371 
    372 
    373 #include "PPCGenMCCodeEmitter.inc"
    374