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 getSPE8DisEncoding(const MCInst &MI, unsigned OpNo,
     73                               SmallVectorImpl<MCFixup> &Fixups,
     74                               const MCSubtargetInfo &STI) const;
     75   unsigned getSPE4DisEncoding(const MCInst &MI, unsigned OpNo,
     76                               SmallVectorImpl<MCFixup> &Fixups,
     77                               const MCSubtargetInfo &STI) const;
     78   unsigned getSPE2DisEncoding(const MCInst &MI, unsigned OpNo,
     79                               SmallVectorImpl<MCFixup> &Fixups,
     80                               const MCSubtargetInfo &STI) const;
     81   unsigned getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
     82                              SmallVectorImpl<MCFixup> &Fixups,
     83                              const MCSubtargetInfo &STI) const;
     84   unsigned getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
     85                               SmallVectorImpl<MCFixup> &Fixups,
     86                               const MCSubtargetInfo &STI) const;
     87   unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
     88                                SmallVectorImpl<MCFixup> &Fixups,
     89                                const MCSubtargetInfo &STI) const;
     90 
     91   /// getMachineOpValue - Return binary encoding of operand. If the machine
     92   /// operand requires relocation, record the relocation and return zero.
     93   unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
     94                              SmallVectorImpl<MCFixup> &Fixups,
     95                              const MCSubtargetInfo &STI) const;
     96 
     97   // getBinaryCodeForInstr - TableGen'erated function for getting the
     98   // binary encoding for an instruction.
     99   uint64_t getBinaryCodeForInstr(const MCInst &MI,
    100                                  SmallVectorImpl<MCFixup> &Fixups,
    101                                  const MCSubtargetInfo &STI) const;
    102   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
    103                          SmallVectorImpl<MCFixup> &Fixups,
    104                          const MCSubtargetInfo &STI) const override {
    105     // For fast-isel, a float COPY_TO_REGCLASS can survive this long.
    106     // It's just a nop to keep the register classes happy, so don't
    107     // generate anything.
    108     unsigned Opcode = MI.getOpcode();
    109     const MCInstrDesc &Desc = MCII.get(Opcode);
    110     if (Opcode == TargetOpcode::COPY_TO_REGCLASS)
    111       return;
    112 
    113     uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
    114 
    115     // Output the constant in big/little endian byte order.
    116     unsigned Size = Desc.getSize();
    117     switch (Size) {
    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 
    253 unsigned PPCMCCodeEmitter::getSPE8DisEncoding(const MCInst &MI, unsigned OpNo,
    254                                               SmallVectorImpl<MCFixup> &Fixups,
    255                                               const MCSubtargetInfo &STI)
    256                                               const {
    257   // Encode (imm, reg) as a spe8dis, which has the low 5-bits of (imm / 8)
    258   // as the displacement and the next 5 bits as the register #.
    259   assert(MI.getOperand(OpNo+1).isReg());
    260   uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
    261 
    262   const MCOperand &MO = MI.getOperand(OpNo);
    263   assert(MO.isImm());
    264   uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 3;
    265   return reverseBits(Imm | RegBits) >> 22;
    266 }
    267 
    268 
    269 unsigned PPCMCCodeEmitter::getSPE4DisEncoding(const MCInst &MI, unsigned OpNo,
    270                                               SmallVectorImpl<MCFixup> &Fixups,
    271                                               const MCSubtargetInfo &STI)
    272                                               const {
    273   // Encode (imm, reg) as a spe4dis, which has the low 5-bits of (imm / 4)
    274   // as the displacement and the next 5 bits as the register #.
    275   assert(MI.getOperand(OpNo+1).isReg());
    276   uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
    277 
    278   const MCOperand &MO = MI.getOperand(OpNo);
    279   assert(MO.isImm());
    280   uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 2;
    281   return reverseBits(Imm | RegBits) >> 22;
    282 }
    283 
    284 
    285 unsigned PPCMCCodeEmitter::getSPE2DisEncoding(const MCInst &MI, unsigned OpNo,
    286                                               SmallVectorImpl<MCFixup> &Fixups,
    287                                               const MCSubtargetInfo &STI)
    288                                               const {
    289   // Encode (imm, reg) as a spe2dis, which has the low 5-bits of (imm / 2)
    290   // as the displacement and the next 5 bits as the register #.
    291   assert(MI.getOperand(OpNo+1).isReg());
    292   uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
    293 
    294   const MCOperand &MO = MI.getOperand(OpNo);
    295   assert(MO.isImm());
    296   uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 1;
    297   return reverseBits(Imm | RegBits) >> 22;
    298 }
    299 
    300 
    301 unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
    302                                        SmallVectorImpl<MCFixup> &Fixups,
    303                                        const MCSubtargetInfo &STI) const {
    304   const MCOperand &MO = MI.getOperand(OpNo);
    305   if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups, STI);
    306 
    307   // Add a fixup for the TLS register, which simply provides a relocation
    308   // hint to the linker that this statement is part of a relocation sequence.
    309   // Return the thread-pointer register's encoding.
    310   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
    311                                    (MCFixupKind)PPC::fixup_ppc_nofixup));
    312   const Triple &TT = STI.getTargetTriple();
    313   bool isPPC64 = TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le;
    314   return CTX.getRegisterInfo()->getEncodingValue(isPPC64 ? PPC::X13 : PPC::R2);
    315 }
    316 
    317 unsigned PPCMCCodeEmitter::getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
    318                                        SmallVectorImpl<MCFixup> &Fixups,
    319                                        const MCSubtargetInfo &STI) const {
    320   // For special TLS calls, we need two fixups; one for the branch target
    321   // (__tls_get_addr), which we create via getDirectBrEncoding as usual,
    322   // and one for the TLSGD or TLSLD symbol, which is emitted here.
    323   const MCOperand &MO = MI.getOperand(OpNo+1);
    324   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
    325                                    (MCFixupKind)PPC::fixup_ppc_nofixup));
    326   return getDirectBrEncoding(MI, OpNo, Fixups, STI);
    327 }
    328 
    329 unsigned PPCMCCodeEmitter::
    330 get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
    331                     SmallVectorImpl<MCFixup> &Fixups,
    332                     const MCSubtargetInfo &STI) const {
    333   const MCOperand &MO = MI.getOperand(OpNo);
    334   assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 ||
    335           MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) &&
    336          (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
    337   return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
    338 }
    339 
    340 
    341 unsigned PPCMCCodeEmitter::
    342 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
    343                   SmallVectorImpl<MCFixup> &Fixups,
    344                   const MCSubtargetInfo &STI) const {
    345   if (MO.isReg()) {
    346     // MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
    347     // The GPR operand should come through here though.
    348     assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 &&
    349             MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) ||
    350            MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
    351     return CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
    352   }
    353 
    354   assert(MO.isImm() &&
    355          "Relocation required in an instruction that we cannot encode!");
    356   return MO.getImm();
    357 }
    358 
    359 
    360 #include "PPCGenMCCodeEmitter.inc"
    361