LLVM API Documentation
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"