LLVM API Documentation

PPCMCCodeEmitter.cpp
Go to the documentation of this file.
00001 //===-- PPCMCCodeEmitter.cpp - Convert PPC code to machine code -----------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the PPCMCCodeEmitter class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #define DEBUG_TYPE "mccodeemitter"
00015 #include "MCTargetDesc/PPCMCTargetDesc.h"
00016 #include "MCTargetDesc/PPCFixupKinds.h"
00017 #include "llvm/ADT/Statistic.h"
00018 #include "llvm/MC/MCCodeEmitter.h"
00019 #include "llvm/MC/MCContext.h"
00020 #include "llvm/MC/MCExpr.h"
00021 #include "llvm/MC/MCInst.h"
00022 #include "llvm/MC/MCInstrInfo.h"
00023 #include "llvm/MC/MCSubtargetInfo.h"
00024 #include "llvm/Support/ErrorHandling.h"
00025 #include "llvm/Support/raw_ostream.h"
00026 using namespace llvm;
00027 
00028 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
00029 
00030 namespace {
00031 class PPCMCCodeEmitter : public MCCodeEmitter {
00032   PPCMCCodeEmitter(const PPCMCCodeEmitter &) LLVM_DELETED_FUNCTION;
00033   void operator=(const PPCMCCodeEmitter &) LLVM_DELETED_FUNCTION;
00034 
00035   const MCSubtargetInfo &STI;
00036   const MCContext &CTX;
00037   Triple TT;
00038 
00039 public:
00040   PPCMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
00041                    MCContext &ctx)
00042     : STI(sti), CTX(ctx), TT(STI.getTargetTriple()) {
00043   }
00044   
00045   ~PPCMCCodeEmitter() {}
00046 
00047   unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
00048                                SmallVectorImpl<MCFixup> &Fixups) const;
00049   unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo,
00050                              SmallVectorImpl<MCFixup> &Fixups) const;
00051   unsigned getS16ImmEncoding(const MCInst &MI, unsigned OpNo,
00052                              SmallVectorImpl<MCFixup> &Fixups) const;
00053   unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo,
00054                             SmallVectorImpl<MCFixup> &Fixups) const;
00055   unsigned getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
00056                              SmallVectorImpl<MCFixup> &Fixups) const;
00057   unsigned getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
00058                              SmallVectorImpl<MCFixup> &Fixups) const;
00059   unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
00060                                SmallVectorImpl<MCFixup> &Fixups) const;
00061 
00062   /// getMachineOpValue - Return binary encoding of operand. If the machine
00063   /// operand requires relocation, record the relocation and return zero.
00064   unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
00065                              SmallVectorImpl<MCFixup> &Fixups) const;
00066   
00067   // getBinaryCodeForInstr - TableGen'erated function for getting the
00068   // binary encoding for an instruction.
00069   uint64_t getBinaryCodeForInstr(const MCInst &MI,
00070                                  SmallVectorImpl<MCFixup> &Fixups) const;
00071   void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
00072                          SmallVectorImpl<MCFixup> &Fixups) const {
00073     uint64_t Bits = getBinaryCodeForInstr(MI, Fixups);
00074 
00075     // BL8_NOP etc. all have a size of 8 because of the following 'nop'.
00076     unsigned Size = 4; // FIXME: Have Desc.getSize() return the correct value!
00077     unsigned Opcode = MI.getOpcode();
00078     if (Opcode == PPC::BL8_NOP || Opcode == PPC::BLA8_NOP ||
00079         Opcode == PPC::BL8_NOP_TLSGD || Opcode == PPC::BL8_NOP_TLSLD)
00080       Size = 8;
00081     
00082     // Output the constant in big endian byte order.
00083     int ShiftValue = (Size * 8) - 8;
00084     for (unsigned i = 0; i != Size; ++i) {
00085       OS << (char)(Bits >> ShiftValue);
00086       Bits <<= 8;
00087     }
00088     
00089     ++MCNumEmitted;  // Keep track of the # of mi's emitted.
00090   }
00091   
00092 };
00093   
00094 } // end anonymous namespace
00095   
00096 MCCodeEmitter *llvm::createPPCMCCodeEmitter(const MCInstrInfo &MCII,
00097                                             const MCRegisterInfo &MRI,
00098                                             const MCSubtargetInfo &STI,
00099                                             MCContext &Ctx) {
00100   return new PPCMCCodeEmitter(MCII, STI, Ctx);
00101 }
00102 
00103 unsigned PPCMCCodeEmitter::
00104 getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
00105                     SmallVectorImpl<MCFixup> &Fixups) const {
00106   const MCOperand &MO = MI.getOperand(OpNo);
00107   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
00108   
00109   // Add a fixup for the branch target.
00110   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
00111                                    (MCFixupKind)PPC::fixup_ppc_br24));
00112 
00113   // For special TLS calls, add another fixup for the symbol.  Apparently
00114   // BL8_NOP, BL8_NOP_TLSGD, and BL8_NOP_TLSLD are sufficiently
00115   // similar that TblGen will not generate a separate case for the latter
00116   // two, so this is the only way to get the extra fixup generated.
00117   unsigned Opcode = MI.getOpcode();
00118   if (Opcode == PPC::BL8_NOP_TLSGD || Opcode == PPC::BL8_NOP_TLSLD) {
00119     const MCOperand &MO2 = MI.getOperand(OpNo+1);
00120     Fixups.push_back(MCFixup::Create(0, MO2.getExpr(),
00121                                      (MCFixupKind)PPC::fixup_ppc_nofixup));
00122   }
00123   return 0;
00124 }
00125 
00126 unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
00127                                      SmallVectorImpl<MCFixup> &Fixups) const {
00128   const MCOperand &MO = MI.getOperand(OpNo);
00129   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
00130 
00131   // Add a fixup for the branch target.
00132   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
00133                                    (MCFixupKind)PPC::fixup_ppc_brcond14));
00134   return 0;
00135 }
00136 
00137 unsigned PPCMCCodeEmitter::getS16ImmEncoding(const MCInst &MI, unsigned OpNo,
00138                                        SmallVectorImpl<MCFixup> &Fixups) const {
00139   const MCOperand &MO = MI.getOperand(OpNo);
00140   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
00141   
00142   // Add a fixup for the branch target.
00143   Fixups.push_back(MCFixup::Create(2, MO.getExpr(),
00144                                    (MCFixupKind)PPC::fixup_ppc_half16));
00145   return 0;
00146 }
00147 
00148 unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
00149                                             SmallVectorImpl<MCFixup> &Fixups) const {
00150   // Encode (imm, reg) as a memri, which has the low 16-bits as the
00151   // displacement and the next 5 bits as the register #.
00152   assert(MI.getOperand(OpNo+1).isReg());
00153   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups) << 16;
00154   
00155   const MCOperand &MO = MI.getOperand(OpNo);
00156   if (MO.isImm())
00157     return (getMachineOpValue(MI, MO, Fixups) & 0xFFFF) | RegBits;
00158   
00159   // Add a fixup for the displacement field.
00160   Fixups.push_back(MCFixup::Create(2, MO.getExpr(),
00161                                    (MCFixupKind)PPC::fixup_ppc_half16));
00162   return RegBits;
00163 }
00164 
00165 
00166 unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
00167                                        SmallVectorImpl<MCFixup> &Fixups) const {
00168   // Encode (imm, reg) as a memrix, which has the low 14-bits as the
00169   // displacement and the next 5 bits as the register #.
00170   assert(MI.getOperand(OpNo+1).isReg());
00171   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups) << 14;
00172   
00173   const MCOperand &MO = MI.getOperand(OpNo);
00174   if (MO.isImm())
00175     return ((getMachineOpValue(MI, MO, Fixups) >> 2) & 0x3FFF) | RegBits;
00176   
00177   // Add a fixup for the displacement field.
00178   Fixups.push_back(MCFixup::Create(2, MO.getExpr(),
00179                                    (MCFixupKind)PPC::fixup_ppc_half16ds));
00180   return RegBits;
00181 }
00182 
00183 
00184 unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
00185                                        SmallVectorImpl<MCFixup> &Fixups) const {
00186   const MCOperand &MO = MI.getOperand(OpNo);
00187   if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups);
00188   
00189   // Add a fixup for the TLS register, which simply provides a relocation
00190   // hint to the linker that this statement is part of a relocation sequence.
00191   // Return the thread-pointer register's encoding.
00192   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
00193                                    (MCFixupKind)PPC::fixup_ppc_tlsreg));
00194   return CTX.getRegisterInfo().getEncodingValue(PPC::X13);
00195 }
00196 
00197 unsigned PPCMCCodeEmitter::
00198 get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
00199                     SmallVectorImpl<MCFixup> &Fixups) const {
00200   const MCOperand &MO = MI.getOperand(OpNo);
00201   assert((MI.getOpcode() == PPC::MTCRF || 
00202           MI.getOpcode() == PPC::MFOCRF ||
00203           MI.getOpcode() == PPC::MTCRF8) &&
00204          (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
00205   return 0x80 >> CTX.getRegisterInfo().getEncodingValue(MO.getReg());
00206 }
00207 
00208 
00209 unsigned PPCMCCodeEmitter::
00210 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
00211                   SmallVectorImpl<MCFixup> &Fixups) const {
00212   if (MO.isReg()) {
00213     // MTCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
00214     // The GPR operand should come through here though.
00215     assert((MI.getOpcode() != PPC::MTCRF && MI.getOpcode() != PPC::MFOCRF) ||
00216            MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
00217     return CTX.getRegisterInfo().getEncodingValue(MO.getReg());
00218   }
00219   
00220   assert(MO.isImm() &&
00221          "Relocation required in an instruction that we cannot encode!");
00222   return MO.getImm();
00223 }
00224 
00225 
00226 #include "PPCGenMCCodeEmitter.inc"