LLVM API Documentation

SystemZMCCodeEmitter.cpp
Go to the documentation of this file.
00001 //===-- SystemZMCCodeEmitter.cpp - Convert SystemZ 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 SystemZMCCodeEmitter class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "MCTargetDesc/SystemZMCTargetDesc.h"
00015 #include "MCTargetDesc/SystemZMCFixups.h"
00016 #include "llvm/MC/MCCodeEmitter.h"
00017 #include "llvm/MC/MCContext.h"
00018 #include "llvm/MC/MCExpr.h"
00019 #include "llvm/MC/MCInstrInfo.h"
00020 
00021 using namespace llvm;
00022 
00023 #define DEBUG_TYPE "mccodeemitter"
00024 
00025 namespace {
00026 class SystemZMCCodeEmitter : public MCCodeEmitter {
00027   const MCInstrInfo &MCII;
00028   MCContext &Ctx;
00029 
00030 public:
00031   SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
00032     : MCII(mcii), Ctx(ctx) {
00033   }
00034 
00035   ~SystemZMCCodeEmitter() {}
00036 
00037   // OVerride MCCodeEmitter.
00038   void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
00039                          SmallVectorImpl<MCFixup> &Fixups,
00040                          const MCSubtargetInfo &STI) const override;
00041 
00042 private:
00043   // Automatically generated by TableGen.
00044   uint64_t getBinaryCodeForInstr(const MCInst &MI,
00045                                  SmallVectorImpl<MCFixup> &Fixups,
00046                                  const MCSubtargetInfo &STI) const;
00047 
00048   // Called by the TableGen code to get the binary encoding of operand
00049   // MO in MI.  Fixups is the list of fixups against MI.
00050   uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
00051                              SmallVectorImpl<MCFixup> &Fixups,
00052                              const MCSubtargetInfo &STI) const;
00053 
00054   // Called by the TableGen code to get the binary encoding of an address.
00055   // The index or length, if any, is encoded first, followed by the base,
00056   // followed by the displacement.  In a 20-bit displacement,
00057   // the low 12 bits are encoded before the high 8 bits.
00058   uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
00059                                SmallVectorImpl<MCFixup> &Fixups,
00060                                const MCSubtargetInfo &STI) const;
00061   uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
00062                                SmallVectorImpl<MCFixup> &Fixups,
00063                                const MCSubtargetInfo &STI) const;
00064   uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
00065                                 SmallVectorImpl<MCFixup> &Fixups,
00066                                 const MCSubtargetInfo &STI) const;
00067   uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
00068                                 SmallVectorImpl<MCFixup> &Fixups,
00069                                 const MCSubtargetInfo &STI) const;
00070   uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
00071                                     SmallVectorImpl<MCFixup> &Fixups,
00072                                     const MCSubtargetInfo &STI) const;
00073 
00074   // Operand OpNum of MI needs a PC-relative fixup of kind Kind at
00075   // Offset bytes from the start of MI.  Add the fixup to Fixups
00076   // and return the in-place addend, which since we're a RELA target
00077   // is always 0.
00078   uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,
00079                             SmallVectorImpl<MCFixup> &Fixups,
00080                             unsigned Kind, int64_t Offset) const;
00081 
00082   uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,
00083                               SmallVectorImpl<MCFixup> &Fixups,
00084                               const MCSubtargetInfo &STI) const {
00085     return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC16DBL, 2);
00086   }
00087   uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,
00088                               SmallVectorImpl<MCFixup> &Fixups,
00089                               const MCSubtargetInfo &STI) const {
00090     return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC32DBL, 2);
00091   }
00092 };
00093 } // end anonymous namespace
00094 
00095 MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,
00096                                                 const MCRegisterInfo &MRI,
00097                                                 const MCSubtargetInfo &MCSTI,
00098                                                 MCContext &Ctx) {
00099   return new SystemZMCCodeEmitter(MCII, Ctx);
00100 }
00101 
00102 void SystemZMCCodeEmitter::
00103 EncodeInstruction(const MCInst &MI, raw_ostream &OS,
00104                   SmallVectorImpl<MCFixup> &Fixups,
00105                   const MCSubtargetInfo &STI) const {
00106   uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
00107   unsigned Size = MCII.get(MI.getOpcode()).getSize();
00108   // Big-endian insertion of Size bytes.
00109   unsigned ShiftValue = (Size * 8) - 8;
00110   for (unsigned I = 0; I != Size; ++I) {
00111     OS << uint8_t(Bits >> ShiftValue);
00112     ShiftValue -= 8;
00113   }
00114 }
00115 
00116 uint64_t SystemZMCCodeEmitter::
00117 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
00118                   SmallVectorImpl<MCFixup> &Fixups,
00119                   const MCSubtargetInfo &STI) const {
00120   if (MO.isReg())
00121     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
00122   if (MO.isImm())
00123     return static_cast<uint64_t>(MO.getImm());
00124   llvm_unreachable("Unexpected operand type!");
00125 }
00126 
00127 uint64_t SystemZMCCodeEmitter::
00128 getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
00129                     SmallVectorImpl<MCFixup> &Fixups,
00130                     const MCSubtargetInfo &STI) const {
00131   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
00132   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
00133   assert(isUInt<4>(Base) && isUInt<12>(Disp));
00134   return (Base << 12) | Disp;
00135 }
00136 
00137 uint64_t SystemZMCCodeEmitter::
00138 getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
00139                     SmallVectorImpl<MCFixup> &Fixups,
00140                     const MCSubtargetInfo &STI) const {
00141   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
00142   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
00143   assert(isUInt<4>(Base) && isInt<20>(Disp));
00144   return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12);
00145 }
00146 
00147 uint64_t SystemZMCCodeEmitter::
00148 getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
00149                      SmallVectorImpl<MCFixup> &Fixups,
00150                      const MCSubtargetInfo &STI) const {
00151   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
00152   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
00153   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
00154   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index));
00155   return (Index << 16) | (Base << 12) | Disp;
00156 }
00157 
00158 uint64_t SystemZMCCodeEmitter::
00159 getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
00160                      SmallVectorImpl<MCFixup> &Fixups,
00161                      const MCSubtargetInfo &STI) const {
00162   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
00163   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
00164   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
00165   assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index));
00166   return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8)
00167     | ((Disp & 0xff000) >> 12);
00168 }
00169 
00170 uint64_t SystemZMCCodeEmitter::
00171 getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
00172                          SmallVectorImpl<MCFixup> &Fixups,
00173                          const MCSubtargetInfo &STI) const {
00174   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
00175   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
00176   uint64_t Len  = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
00177   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len));
00178   return (Len << 16) | (Base << 12) | Disp;
00179 }
00180 
00181 uint64_t
00182 SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
00183                                        SmallVectorImpl<MCFixup> &Fixups,
00184                                        unsigned Kind, int64_t Offset) const {
00185   const MCOperand &MO = MI.getOperand(OpNum);
00186   const MCExpr *Expr;
00187   if (MO.isImm())
00188     Expr = MCConstantExpr::Create(MO.getImm() + Offset, Ctx);
00189   else {
00190     Expr = MO.getExpr();
00191     if (Offset) {
00192       // The operand value is relative to the start of MI, but the fixup
00193       // is relative to the operand field itself, which is Offset bytes
00194       // into MI.  Add Offset to the relocation value to cancel out
00195       // this difference.
00196       const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx);
00197       Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx);
00198     }
00199   }
00200   Fixups.push_back(MCFixup::Create(Offset, Expr, (MCFixupKind)Kind));
00201   return 0;
00202 }
00203 
00204 #include "SystemZGenMCCodeEmitter.inc"