1//===-- SystemZMCCodeEmitter.cpp - Convert SystemZ 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 SystemZMCCodeEmitter class. 11// 12//===----------------------------------------------------------------------===// 13 14#include "MCTargetDesc/SystemZMCTargetDesc.h" 15#include "MCTargetDesc/SystemZMCFixups.h" 16#include "llvm/MC/MCCodeEmitter.h" 17#include "llvm/MC/MCContext.h" 18#include "llvm/MC/MCExpr.h" 19#include "llvm/MC/MCInstrInfo.h" 20 21using namespace llvm; 22 23#define DEBUG_TYPE "mccodeemitter" 24 25namespace { 26class SystemZMCCodeEmitter : public MCCodeEmitter { 27 const MCInstrInfo &MCII; 28 MCContext &Ctx; 29 30public: 31 SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) 32 : MCII(mcii), Ctx(ctx) { 33 } 34 35 ~SystemZMCCodeEmitter() override {} 36 37 // OVerride MCCodeEmitter. 38 void EncodeInstruction(const MCInst &MI, raw_ostream &OS, 39 SmallVectorImpl<MCFixup> &Fixups, 40 const MCSubtargetInfo &STI) const override; 41 42private: 43 // Automatically generated by TableGen. 44 uint64_t getBinaryCodeForInstr(const MCInst &MI, 45 SmallVectorImpl<MCFixup> &Fixups, 46 const MCSubtargetInfo &STI) const; 47 48 // Called by the TableGen code to get the binary encoding of operand 49 // MO in MI. Fixups is the list of fixups against MI. 50 uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO, 51 SmallVectorImpl<MCFixup> &Fixups, 52 const MCSubtargetInfo &STI) const; 53 54 // Called by the TableGen code to get the binary encoding of an address. 55 // The index or length, if any, is encoded first, followed by the base, 56 // followed by the displacement. In a 20-bit displacement, 57 // the low 12 bits are encoded before the high 8 bits. 58 uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum, 59 SmallVectorImpl<MCFixup> &Fixups, 60 const MCSubtargetInfo &STI) const; 61 uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum, 62 SmallVectorImpl<MCFixup> &Fixups, 63 const MCSubtargetInfo &STI) const; 64 uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum, 65 SmallVectorImpl<MCFixup> &Fixups, 66 const MCSubtargetInfo &STI) const; 67 uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum, 68 SmallVectorImpl<MCFixup> &Fixups, 69 const MCSubtargetInfo &STI) const; 70 uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum, 71 SmallVectorImpl<MCFixup> &Fixups, 72 const MCSubtargetInfo &STI) const; 73 74 // Operand OpNum of MI needs a PC-relative fixup of kind Kind at 75 // Offset bytes from the start of MI. Add the fixup to Fixups 76 // and return the in-place addend, which since we're a RELA target 77 // is always 0. If AllowTLS is true and optional operand OpNum + 1 78 // is present, also emit a TLS call fixup for it. 79 uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum, 80 SmallVectorImpl<MCFixup> &Fixups, 81 unsigned Kind, int64_t Offset, 82 bool AllowTLS) const; 83 84 uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum, 85 SmallVectorImpl<MCFixup> &Fixups, 86 const MCSubtargetInfo &STI) const { 87 return getPCRelEncoding(MI, OpNum, Fixups, 88 SystemZ::FK_390_PC16DBL, 2, false); 89 } 90 uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum, 91 SmallVectorImpl<MCFixup> &Fixups, 92 const MCSubtargetInfo &STI) const { 93 return getPCRelEncoding(MI, OpNum, Fixups, 94 SystemZ::FK_390_PC32DBL, 2, false); 95 } 96 uint64_t getPC16DBLTLSEncoding(const MCInst &MI, unsigned OpNum, 97 SmallVectorImpl<MCFixup> &Fixups, 98 const MCSubtargetInfo &STI) const { 99 return getPCRelEncoding(MI, OpNum, Fixups, 100 SystemZ::FK_390_PC16DBL, 2, true); 101 } 102 uint64_t getPC32DBLTLSEncoding(const MCInst &MI, unsigned OpNum, 103 SmallVectorImpl<MCFixup> &Fixups, 104 const MCSubtargetInfo &STI) const { 105 return getPCRelEncoding(MI, OpNum, Fixups, 106 SystemZ::FK_390_PC32DBL, 2, true); 107 } 108}; 109} // end anonymous namespace 110 111MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII, 112 const MCRegisterInfo &MRI, 113 MCContext &Ctx) { 114 return new SystemZMCCodeEmitter(MCII, Ctx); 115} 116 117void SystemZMCCodeEmitter:: 118EncodeInstruction(const MCInst &MI, raw_ostream &OS, 119 SmallVectorImpl<MCFixup> &Fixups, 120 const MCSubtargetInfo &STI) const { 121 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 122 unsigned Size = MCII.get(MI.getOpcode()).getSize(); 123 // Big-endian insertion of Size bytes. 124 unsigned ShiftValue = (Size * 8) - 8; 125 for (unsigned I = 0; I != Size; ++I) { 126 OS << uint8_t(Bits >> ShiftValue); 127 ShiftValue -= 8; 128 } 129} 130 131uint64_t SystemZMCCodeEmitter:: 132getMachineOpValue(const MCInst &MI, const MCOperand &MO, 133 SmallVectorImpl<MCFixup> &Fixups, 134 const MCSubtargetInfo &STI) const { 135 if (MO.isReg()) 136 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 137 if (MO.isImm()) 138 return static_cast<uint64_t>(MO.getImm()); 139 llvm_unreachable("Unexpected operand type!"); 140} 141 142uint64_t SystemZMCCodeEmitter:: 143getBDAddr12Encoding(const MCInst &MI, unsigned OpNum, 144 SmallVectorImpl<MCFixup> &Fixups, 145 const MCSubtargetInfo &STI) const { 146 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 147 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 148 assert(isUInt<4>(Base) && isUInt<12>(Disp)); 149 return (Base << 12) | Disp; 150} 151 152uint64_t SystemZMCCodeEmitter:: 153getBDAddr20Encoding(const MCInst &MI, unsigned OpNum, 154 SmallVectorImpl<MCFixup> &Fixups, 155 const MCSubtargetInfo &STI) const { 156 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 157 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 158 assert(isUInt<4>(Base) && isInt<20>(Disp)); 159 return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12); 160} 161 162uint64_t SystemZMCCodeEmitter:: 163getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum, 164 SmallVectorImpl<MCFixup> &Fixups, 165 const MCSubtargetInfo &STI) const { 166 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 167 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 168 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); 169 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index)); 170 return (Index << 16) | (Base << 12) | Disp; 171} 172 173uint64_t SystemZMCCodeEmitter:: 174getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum, 175 SmallVectorImpl<MCFixup> &Fixups, 176 const MCSubtargetInfo &STI) const { 177 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 178 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 179 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); 180 assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index)); 181 return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8) 182 | ((Disp & 0xff000) >> 12); 183} 184 185uint64_t SystemZMCCodeEmitter:: 186getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum, 187 SmallVectorImpl<MCFixup> &Fixups, 188 const MCSubtargetInfo &STI) const { 189 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 190 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 191 uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1; 192 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len)); 193 return (Len << 16) | (Base << 12) | Disp; 194} 195 196uint64_t 197SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum, 198 SmallVectorImpl<MCFixup> &Fixups, 199 unsigned Kind, int64_t Offset, 200 bool AllowTLS) const { 201 const MCOperand &MO = MI.getOperand(OpNum); 202 const MCExpr *Expr; 203 if (MO.isImm()) 204 Expr = MCConstantExpr::Create(MO.getImm() + Offset, Ctx); 205 else { 206 Expr = MO.getExpr(); 207 if (Offset) { 208 // The operand value is relative to the start of MI, but the fixup 209 // is relative to the operand field itself, which is Offset bytes 210 // into MI. Add Offset to the relocation value to cancel out 211 // this difference. 212 const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx); 213 Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx); 214 } 215 } 216 Fixups.push_back(MCFixup::Create(Offset, Expr, (MCFixupKind)Kind)); 217 218 // Output the fixup for the TLS marker if present. 219 if (AllowTLS && OpNum + 1 < MI.getNumOperands()) { 220 const MCOperand &MOTLS = MI.getOperand(OpNum + 1); 221 Fixups.push_back(MCFixup::Create(0, MOTLS.getExpr(), 222 (MCFixupKind)SystemZ::FK_390_TLS_CALL)); 223 } 224 return 0; 225} 226 227#include "SystemZGenMCCodeEmitter.inc" 228