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 21 using namespace llvm; 22 23 #define DEBUG_TYPE "mccodeemitter" 24 25 namespace { 26 class SystemZMCCodeEmitter : public MCCodeEmitter { 27 const MCInstrInfo &MCII; 28 MCContext &Ctx; 29 30 public: 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 42 private: 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 uint64_t getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum, 74 SmallVectorImpl<MCFixup> &Fixups, 75 const MCSubtargetInfo &STI) const; 76 77 // Operand OpNum of MI needs a PC-relative fixup of kind Kind at 78 // Offset bytes from the start of MI. Add the fixup to Fixups 79 // and return the in-place addend, which since we're a RELA target 80 // is always 0. If AllowTLS is true and optional operand OpNum + 1 81 // is present, also emit a TLS call fixup for it. 82 uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum, 83 SmallVectorImpl<MCFixup> &Fixups, 84 unsigned Kind, int64_t Offset, 85 bool AllowTLS) const; 86 87 uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum, 88 SmallVectorImpl<MCFixup> &Fixups, 89 const MCSubtargetInfo &STI) const { 90 return getPCRelEncoding(MI, OpNum, Fixups, 91 SystemZ::FK_390_PC16DBL, 2, false); 92 } 93 uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum, 94 SmallVectorImpl<MCFixup> &Fixups, 95 const MCSubtargetInfo &STI) const { 96 return getPCRelEncoding(MI, OpNum, Fixups, 97 SystemZ::FK_390_PC32DBL, 2, false); 98 } 99 uint64_t getPC16DBLTLSEncoding(const MCInst &MI, unsigned OpNum, 100 SmallVectorImpl<MCFixup> &Fixups, 101 const MCSubtargetInfo &STI) const { 102 return getPCRelEncoding(MI, OpNum, Fixups, 103 SystemZ::FK_390_PC16DBL, 2, true); 104 } 105 uint64_t getPC32DBLTLSEncoding(const MCInst &MI, unsigned OpNum, 106 SmallVectorImpl<MCFixup> &Fixups, 107 const MCSubtargetInfo &STI) const { 108 return getPCRelEncoding(MI, OpNum, Fixups, 109 SystemZ::FK_390_PC32DBL, 2, true); 110 } 111 }; 112 } // end anonymous namespace 113 114 MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII, 115 const MCRegisterInfo &MRI, 116 MCContext &Ctx) { 117 return new SystemZMCCodeEmitter(MCII, Ctx); 118 } 119 120 void SystemZMCCodeEmitter:: 121 EncodeInstruction(const MCInst &MI, raw_ostream &OS, 122 SmallVectorImpl<MCFixup> &Fixups, 123 const MCSubtargetInfo &STI) const { 124 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 125 unsigned Size = MCII.get(MI.getOpcode()).getSize(); 126 // Big-endian insertion of Size bytes. 127 unsigned ShiftValue = (Size * 8) - 8; 128 for (unsigned I = 0; I != Size; ++I) { 129 OS << uint8_t(Bits >> ShiftValue); 130 ShiftValue -= 8; 131 } 132 } 133 134 uint64_t SystemZMCCodeEmitter:: 135 getMachineOpValue(const MCInst &MI, const MCOperand &MO, 136 SmallVectorImpl<MCFixup> &Fixups, 137 const MCSubtargetInfo &STI) const { 138 if (MO.isReg()) 139 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 140 if (MO.isImm()) 141 return static_cast<uint64_t>(MO.getImm()); 142 llvm_unreachable("Unexpected operand type!"); 143 } 144 145 uint64_t SystemZMCCodeEmitter:: 146 getBDAddr12Encoding(const MCInst &MI, unsigned OpNum, 147 SmallVectorImpl<MCFixup> &Fixups, 148 const MCSubtargetInfo &STI) const { 149 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 150 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 151 assert(isUInt<4>(Base) && isUInt<12>(Disp)); 152 return (Base << 12) | Disp; 153 } 154 155 uint64_t SystemZMCCodeEmitter:: 156 getBDAddr20Encoding(const MCInst &MI, unsigned OpNum, 157 SmallVectorImpl<MCFixup> &Fixups, 158 const MCSubtargetInfo &STI) const { 159 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 160 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 161 assert(isUInt<4>(Base) && isInt<20>(Disp)); 162 return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12); 163 } 164 165 uint64_t SystemZMCCodeEmitter:: 166 getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum, 167 SmallVectorImpl<MCFixup> &Fixups, 168 const MCSubtargetInfo &STI) const { 169 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 170 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 171 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); 172 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index)); 173 return (Index << 16) | (Base << 12) | Disp; 174 } 175 176 uint64_t SystemZMCCodeEmitter:: 177 getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum, 178 SmallVectorImpl<MCFixup> &Fixups, 179 const MCSubtargetInfo &STI) const { 180 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 181 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 182 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); 183 assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index)); 184 return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8) 185 | ((Disp & 0xff000) >> 12); 186 } 187 188 uint64_t SystemZMCCodeEmitter:: 189 getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum, 190 SmallVectorImpl<MCFixup> &Fixups, 191 const MCSubtargetInfo &STI) const { 192 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 193 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 194 uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1; 195 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len)); 196 return (Len << 16) | (Base << 12) | Disp; 197 } 198 199 uint64_t SystemZMCCodeEmitter:: 200 getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum, 201 SmallVectorImpl<MCFixup> &Fixups, 202 const MCSubtargetInfo &STI) const { 203 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 204 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 205 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); 206 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<5>(Index)); 207 return (Index << 16) | (Base << 12) | Disp; 208 } 209 210 uint64_t 211 SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum, 212 SmallVectorImpl<MCFixup> &Fixups, 213 unsigned Kind, int64_t Offset, 214 bool AllowTLS) const { 215 const MCOperand &MO = MI.getOperand(OpNum); 216 const MCExpr *Expr; 217 if (MO.isImm()) 218 Expr = MCConstantExpr::Create(MO.getImm() + Offset, Ctx); 219 else { 220 Expr = MO.getExpr(); 221 if (Offset) { 222 // The operand value is relative to the start of MI, but the fixup 223 // is relative to the operand field itself, which is Offset bytes 224 // into MI. Add Offset to the relocation value to cancel out 225 // this difference. 226 const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx); 227 Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx); 228 } 229 } 230 Fixups.push_back(MCFixup::Create(Offset, Expr, (MCFixupKind)Kind)); 231 232 // Output the fixup for the TLS marker if present. 233 if (AllowTLS && OpNum + 1 < MI.getNumOperands()) { 234 const MCOperand &MOTLS = MI.getOperand(OpNum + 1); 235 Fixups.push_back(MCFixup::Create(0, MOTLS.getExpr(), 236 (MCFixupKind)SystemZ::FK_390_TLS_CALL)); 237 } 238 return 0; 239 } 240 241 #include "SystemZGenMCCodeEmitter.inc" 242