1 //===-- SystemZMCCodeEmitter.cpp - Convert SystemZ code to machine code ---===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the SystemZMCCodeEmitter class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "MCTargetDesc/SystemZMCFixups.h" 14 #include "MCTargetDesc/SystemZMCTargetDesc.h" 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/MC/MCCodeEmitter.h" 17 #include "llvm/MC/MCContext.h" 18 #include "llvm/MC/MCExpr.h" 19 #include "llvm/MC/MCFixup.h" 20 #include "llvm/MC/MCInst.h" 21 #include "llvm/MC/MCInstrInfo.h" 22 #include "llvm/MC/MCRegisterInfo.h" 23 #include "llvm/MC/MCSubtargetInfo.h" 24 #include "llvm/Support/ErrorHandling.h" 25 #include "llvm/Support/raw_ostream.h" 26 #include <cassert> 27 #include <cstdint> 28 29 using namespace llvm; 30 31 #define DEBUG_TYPE "mccodeemitter" 32 33 namespace { 34 35 class SystemZMCCodeEmitter : public MCCodeEmitter { 36 const MCInstrInfo &MCII; 37 MCContext &Ctx; 38 39 public: 40 SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) 41 : MCII(mcii), Ctx(ctx) { 42 } 43 44 ~SystemZMCCodeEmitter() override = default; 45 46 // OVerride MCCodeEmitter. 47 void encodeInstruction(const MCInst &MI, raw_ostream &OS, 48 SmallVectorImpl<MCFixup> &Fixups, 49 const MCSubtargetInfo &STI) const override; 50 51 private: 52 // Automatically generated by TableGen. 53 uint64_t getBinaryCodeForInstr(const MCInst &MI, 54 SmallVectorImpl<MCFixup> &Fixups, 55 const MCSubtargetInfo &STI) const; 56 57 // Called by the TableGen code to get the binary encoding of operand 58 // MO in MI. Fixups is the list of fixups against MI. 59 uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO, 60 SmallVectorImpl<MCFixup> &Fixups, 61 const MCSubtargetInfo &STI) const; 62 63 // Called by the TableGen code to get the binary encoding of an address. 64 // The index or length, if any, is encoded first, followed by the base, 65 // followed by the displacement. In a 20-bit displacement, 66 // the low 12 bits are encoded before the high 8 bits. 67 uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum, 68 SmallVectorImpl<MCFixup> &Fixups, 69 const MCSubtargetInfo &STI) const; 70 uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum, 71 SmallVectorImpl<MCFixup> &Fixups, 72 const MCSubtargetInfo &STI) const; 73 uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum, 74 SmallVectorImpl<MCFixup> &Fixups, 75 const MCSubtargetInfo &STI) const; 76 uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum, 77 SmallVectorImpl<MCFixup> &Fixups, 78 const MCSubtargetInfo &STI) const; 79 uint64_t getBDLAddr12Len4Encoding(const MCInst &MI, unsigned OpNum, 80 SmallVectorImpl<MCFixup> &Fixups, 81 const MCSubtargetInfo &STI) const; 82 uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum, 83 SmallVectorImpl<MCFixup> &Fixups, 84 const MCSubtargetInfo &STI) const; 85 uint64_t getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum, 86 SmallVectorImpl<MCFixup> &Fixups, 87 const MCSubtargetInfo &STI) const; 88 uint64_t getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum, 89 SmallVectorImpl<MCFixup> &Fixups, 90 const MCSubtargetInfo &STI) const; 91 92 // Operand OpNum of MI needs a PC-relative fixup of kind Kind at 93 // Offset bytes from the start of MI. Add the fixup to Fixups 94 // and return the in-place addend, which since we're a RELA target 95 // is always 0. If AllowTLS is true and optional operand OpNum + 1 96 // is present, also emit a TLS call fixup for it. 97 uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum, 98 SmallVectorImpl<MCFixup> &Fixups, 99 unsigned Kind, int64_t Offset, 100 bool AllowTLS) const; 101 102 uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum, 103 SmallVectorImpl<MCFixup> &Fixups, 104 const MCSubtargetInfo &STI) const { 105 return getPCRelEncoding(MI, OpNum, Fixups, 106 SystemZ::FK_390_PC16DBL, 2, false); 107 } 108 uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum, 109 SmallVectorImpl<MCFixup> &Fixups, 110 const MCSubtargetInfo &STI) const { 111 return getPCRelEncoding(MI, OpNum, Fixups, 112 SystemZ::FK_390_PC32DBL, 2, false); 113 } 114 uint64_t getPC16DBLTLSEncoding(const MCInst &MI, unsigned OpNum, 115 SmallVectorImpl<MCFixup> &Fixups, 116 const MCSubtargetInfo &STI) const { 117 return getPCRelEncoding(MI, OpNum, Fixups, 118 SystemZ::FK_390_PC16DBL, 2, true); 119 } 120 uint64_t getPC32DBLTLSEncoding(const MCInst &MI, unsigned OpNum, 121 SmallVectorImpl<MCFixup> &Fixups, 122 const MCSubtargetInfo &STI) const { 123 return getPCRelEncoding(MI, OpNum, Fixups, 124 SystemZ::FK_390_PC32DBL, 2, true); 125 } 126 uint64_t getPC12DBLBPPEncoding(const MCInst &MI, unsigned OpNum, 127 SmallVectorImpl<MCFixup> &Fixups, 128 const MCSubtargetInfo &STI) const { 129 return getPCRelEncoding(MI, OpNum, Fixups, 130 SystemZ::FK_390_PC12DBL, 1, false); 131 } 132 uint64_t getPC16DBLBPPEncoding(const MCInst &MI, unsigned OpNum, 133 SmallVectorImpl<MCFixup> &Fixups, 134 const MCSubtargetInfo &STI) const { 135 return getPCRelEncoding(MI, OpNum, Fixups, 136 SystemZ::FK_390_PC16DBL, 4, false); 137 } 138 uint64_t getPC24DBLBPPEncoding(const MCInst &MI, unsigned OpNum, 139 SmallVectorImpl<MCFixup> &Fixups, 140 const MCSubtargetInfo &STI) const { 141 return getPCRelEncoding(MI, OpNum, Fixups, 142 SystemZ::FK_390_PC24DBL, 3, false); 143 } 144 145 private: 146 uint64_t computeAvailableFeatures(const FeatureBitset &FB) const; 147 void verifyInstructionPredicates(const MCInst &MI, 148 uint64_t AvailableFeatures) const; 149 }; 150 151 } // end anonymous namespace 152 153 void SystemZMCCodeEmitter:: 154 encodeInstruction(const MCInst &MI, raw_ostream &OS, 155 SmallVectorImpl<MCFixup> &Fixups, 156 const MCSubtargetInfo &STI) const { 157 verifyInstructionPredicates(MI, 158 computeAvailableFeatures(STI.getFeatureBits())); 159 160 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 161 unsigned Size = MCII.get(MI.getOpcode()).getSize(); 162 // Big-endian insertion of Size bytes. 163 unsigned ShiftValue = (Size * 8) - 8; 164 for (unsigned I = 0; I != Size; ++I) { 165 OS << uint8_t(Bits >> ShiftValue); 166 ShiftValue -= 8; 167 } 168 } 169 170 uint64_t SystemZMCCodeEmitter:: 171 getMachineOpValue(const MCInst &MI, const MCOperand &MO, 172 SmallVectorImpl<MCFixup> &Fixups, 173 const MCSubtargetInfo &STI) const { 174 if (MO.isReg()) 175 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 176 if (MO.isImm()) 177 return static_cast<uint64_t>(MO.getImm()); 178 llvm_unreachable("Unexpected operand type!"); 179 } 180 181 uint64_t SystemZMCCodeEmitter:: 182 getBDAddr12Encoding(const MCInst &MI, unsigned OpNum, 183 SmallVectorImpl<MCFixup> &Fixups, 184 const MCSubtargetInfo &STI) const { 185 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 186 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 187 assert(isUInt<4>(Base) && isUInt<12>(Disp)); 188 return (Base << 12) | Disp; 189 } 190 191 uint64_t SystemZMCCodeEmitter:: 192 getBDAddr20Encoding(const MCInst &MI, unsigned OpNum, 193 SmallVectorImpl<MCFixup> &Fixups, 194 const MCSubtargetInfo &STI) const { 195 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 196 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 197 assert(isUInt<4>(Base) && isInt<20>(Disp)); 198 return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12); 199 } 200 201 uint64_t SystemZMCCodeEmitter:: 202 getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum, 203 SmallVectorImpl<MCFixup> &Fixups, 204 const MCSubtargetInfo &STI) const { 205 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 206 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 207 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); 208 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index)); 209 return (Index << 16) | (Base << 12) | Disp; 210 } 211 212 uint64_t SystemZMCCodeEmitter:: 213 getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum, 214 SmallVectorImpl<MCFixup> &Fixups, 215 const MCSubtargetInfo &STI) const { 216 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 217 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 218 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); 219 assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index)); 220 return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8) 221 | ((Disp & 0xff000) >> 12); 222 } 223 224 uint64_t SystemZMCCodeEmitter:: 225 getBDLAddr12Len4Encoding(const MCInst &MI, unsigned OpNum, 226 SmallVectorImpl<MCFixup> &Fixups, 227 const MCSubtargetInfo &STI) const { 228 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 229 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 230 uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1; 231 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len)); 232 return (Len << 16) | (Base << 12) | Disp; 233 } 234 235 uint64_t SystemZMCCodeEmitter:: 236 getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum, 237 SmallVectorImpl<MCFixup> &Fixups, 238 const MCSubtargetInfo &STI) const { 239 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 240 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 241 uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1; 242 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len)); 243 return (Len << 16) | (Base << 12) | Disp; 244 } 245 246 uint64_t SystemZMCCodeEmitter:: 247 getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum, 248 SmallVectorImpl<MCFixup> &Fixups, 249 const MCSubtargetInfo &STI) const { 250 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 251 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 252 uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); 253 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len)); 254 return (Len << 16) | (Base << 12) | Disp; 255 } 256 257 uint64_t SystemZMCCodeEmitter:: 258 getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum, 259 SmallVectorImpl<MCFixup> &Fixups, 260 const MCSubtargetInfo &STI) const { 261 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 262 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 263 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); 264 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<5>(Index)); 265 return (Index << 16) | (Base << 12) | Disp; 266 } 267 268 uint64_t 269 SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum, 270 SmallVectorImpl<MCFixup> &Fixups, 271 unsigned Kind, int64_t Offset, 272 bool AllowTLS) const { 273 const MCOperand &MO = MI.getOperand(OpNum); 274 const MCExpr *Expr; 275 if (MO.isImm()) 276 Expr = MCConstantExpr::create(MO.getImm() + Offset, Ctx); 277 else { 278 Expr = MO.getExpr(); 279 if (Offset) { 280 // The operand value is relative to the start of MI, but the fixup 281 // is relative to the operand field itself, which is Offset bytes 282 // into MI. Add Offset to the relocation value to cancel out 283 // this difference. 284 const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx); 285 Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx); 286 } 287 } 288 Fixups.push_back(MCFixup::create(Offset, Expr, (MCFixupKind)Kind)); 289 290 // Output the fixup for the TLS marker if present. 291 if (AllowTLS && OpNum + 1 < MI.getNumOperands()) { 292 const MCOperand &MOTLS = MI.getOperand(OpNum + 1); 293 Fixups.push_back(MCFixup::create(0, MOTLS.getExpr(), 294 (MCFixupKind)SystemZ::FK_390_TLS_CALL)); 295 } 296 return 0; 297 } 298 299 #define ENABLE_INSTR_PREDICATE_VERIFIER 300 #include "SystemZGenMCCodeEmitter.inc" 301 302 MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII, 303 const MCRegisterInfo &MRI, 304 MCContext &Ctx) { 305 return new SystemZMCCodeEmitter(MCII, Ctx); 306 } 307