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