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