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() {} 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 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 111 MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII, 112 const MCRegisterInfo &MRI, 113 const MCSubtargetInfo &MCSTI, 114 MCContext &Ctx) { 115 return new SystemZMCCodeEmitter(MCII, Ctx); 116 } 117 118 void SystemZMCCodeEmitter:: 119 EncodeInstruction(const MCInst &MI, raw_ostream &OS, 120 SmallVectorImpl<MCFixup> &Fixups, 121 const MCSubtargetInfo &STI) const { 122 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); 123 unsigned Size = MCII.get(MI.getOpcode()).getSize(); 124 // Big-endian insertion of Size bytes. 125 unsigned ShiftValue = (Size * 8) - 8; 126 for (unsigned I = 0; I != Size; ++I) { 127 OS << uint8_t(Bits >> ShiftValue); 128 ShiftValue -= 8; 129 } 130 } 131 132 uint64_t SystemZMCCodeEmitter:: 133 getMachineOpValue(const MCInst &MI, const MCOperand &MO, 134 SmallVectorImpl<MCFixup> &Fixups, 135 const MCSubtargetInfo &STI) const { 136 if (MO.isReg()) 137 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); 138 if (MO.isImm()) 139 return static_cast<uint64_t>(MO.getImm()); 140 llvm_unreachable("Unexpected operand type!"); 141 } 142 143 uint64_t SystemZMCCodeEmitter:: 144 getBDAddr12Encoding(const MCInst &MI, unsigned OpNum, 145 SmallVectorImpl<MCFixup> &Fixups, 146 const MCSubtargetInfo &STI) const { 147 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 148 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 149 assert(isUInt<4>(Base) && isUInt<12>(Disp)); 150 return (Base << 12) | Disp; 151 } 152 153 uint64_t SystemZMCCodeEmitter:: 154 getBDAddr20Encoding(const MCInst &MI, unsigned OpNum, 155 SmallVectorImpl<MCFixup> &Fixups, 156 const MCSubtargetInfo &STI) const { 157 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 158 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 159 assert(isUInt<4>(Base) && isInt<20>(Disp)); 160 return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12); 161 } 162 163 uint64_t SystemZMCCodeEmitter:: 164 getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum, 165 SmallVectorImpl<MCFixup> &Fixups, 166 const MCSubtargetInfo &STI) const { 167 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 168 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 169 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); 170 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index)); 171 return (Index << 16) | (Base << 12) | Disp; 172 } 173 174 uint64_t SystemZMCCodeEmitter:: 175 getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum, 176 SmallVectorImpl<MCFixup> &Fixups, 177 const MCSubtargetInfo &STI) const { 178 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 179 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 180 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); 181 assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index)); 182 return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8) 183 | ((Disp & 0xff000) >> 12); 184 } 185 186 uint64_t SystemZMCCodeEmitter:: 187 getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum, 188 SmallVectorImpl<MCFixup> &Fixups, 189 const MCSubtargetInfo &STI) const { 190 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); 191 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); 192 uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1; 193 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len)); 194 return (Len << 16) | (Base << 12) | Disp; 195 } 196 197 uint64_t 198 SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum, 199 SmallVectorImpl<MCFixup> &Fixups, 200 unsigned Kind, int64_t Offset, 201 bool AllowTLS) const { 202 const MCOperand &MO = MI.getOperand(OpNum); 203 const MCExpr *Expr; 204 if (MO.isImm()) 205 Expr = MCConstantExpr::Create(MO.getImm() + Offset, Ctx); 206 else { 207 Expr = MO.getExpr(); 208 if (Offset) { 209 // The operand value is relative to the start of MI, but the fixup 210 // is relative to the operand field itself, which is Offset bytes 211 // into MI. Add Offset to the relocation value to cancel out 212 // this difference. 213 const MCExpr *OffsetExpr = MCConstantExpr::Create(Offset, Ctx); 214 Expr = MCBinaryExpr::CreateAdd(Expr, OffsetExpr, Ctx); 215 } 216 } 217 Fixups.push_back(MCFixup::Create(Offset, Expr, (MCFixupKind)Kind)); 218 219 // Output the fixup for the TLS marker if present. 220 if (AllowTLS && OpNum + 1 < MI.getNumOperands()) { 221 const MCOperand &MOTLS = MI.getOperand(OpNum + 1); 222 Fixups.push_back(MCFixup::Create(0, MOTLS.getExpr(), 223 (MCFixupKind)SystemZ::FK_390_TLS_CALL)); 224 } 225 return 0; 226 } 227 228 #include "SystemZGenMCCodeEmitter.inc" 229