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/SystemZMCFixups.h"
15 #include "MCTargetDesc/SystemZMCTargetDesc.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:
SystemZMCCodeEmitter(const MCInstrInfo & mcii,MCContext & ctx)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 // Called by the TableGen code to get the binary encoding of an address.
65 // The index or length, if any, is encoded first, followed by the base,
66 // followed by the displacement. In a 20-bit displacement,
67 // the low 12 bits are encoded before the high 8 bits.
68 uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
69 SmallVectorImpl<MCFixup> &Fixups,
70 const MCSubtargetInfo &STI) const;
71 uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
72 SmallVectorImpl<MCFixup> &Fixups,
73 const MCSubtargetInfo &STI) const;
74 uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
75 SmallVectorImpl<MCFixup> &Fixups,
76 const MCSubtargetInfo &STI) const;
77 uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
78 SmallVectorImpl<MCFixup> &Fixups,
79 const MCSubtargetInfo &STI) const;
80 uint64_t getBDLAddr12Len4Encoding(const MCInst &MI, unsigned OpNum,
81 SmallVectorImpl<MCFixup> &Fixups,
82 const MCSubtargetInfo &STI) const;
83 uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
84 SmallVectorImpl<MCFixup> &Fixups,
85 const MCSubtargetInfo &STI) const;
86 uint64_t getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum,
87 SmallVectorImpl<MCFixup> &Fixups,
88 const MCSubtargetInfo &STI) const;
89 uint64_t getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
90 SmallVectorImpl<MCFixup> &Fixups,
91 const MCSubtargetInfo &STI) const;
92
93 // Operand OpNum of MI needs a PC-relative fixup of kind Kind at
94 // Offset bytes from the start of MI. Add the fixup to Fixups
95 // and return the in-place addend, which since we're a RELA target
96 // is always 0. If AllowTLS is true and optional operand OpNum + 1
97 // is present, also emit a TLS call fixup for it.
98 uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,
99 SmallVectorImpl<MCFixup> &Fixups,
100 unsigned Kind, int64_t Offset,
101 bool AllowTLS) const;
102
getPC16DBLEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const103 uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,
104 SmallVectorImpl<MCFixup> &Fixups,
105 const MCSubtargetInfo &STI) const {
106 return getPCRelEncoding(MI, OpNum, Fixups,
107 SystemZ::FK_390_PC16DBL, 2, false);
108 }
getPC32DBLEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const109 uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,
110 SmallVectorImpl<MCFixup> &Fixups,
111 const MCSubtargetInfo &STI) const {
112 return getPCRelEncoding(MI, OpNum, Fixups,
113 SystemZ::FK_390_PC32DBL, 2, false);
114 }
getPC16DBLTLSEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const115 uint64_t getPC16DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
116 SmallVectorImpl<MCFixup> &Fixups,
117 const MCSubtargetInfo &STI) const {
118 return getPCRelEncoding(MI, OpNum, Fixups,
119 SystemZ::FK_390_PC16DBL, 2, true);
120 }
getPC32DBLTLSEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const121 uint64_t getPC32DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
122 SmallVectorImpl<MCFixup> &Fixups,
123 const MCSubtargetInfo &STI) const {
124 return getPCRelEncoding(MI, OpNum, Fixups,
125 SystemZ::FK_390_PC32DBL, 2, true);
126 }
getPC12DBLBPPEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const127 uint64_t getPC12DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
128 SmallVectorImpl<MCFixup> &Fixups,
129 const MCSubtargetInfo &STI) const {
130 return getPCRelEncoding(MI, OpNum, Fixups,
131 SystemZ::FK_390_PC12DBL, 1, false);
132 }
getPC16DBLBPPEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const133 uint64_t getPC16DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
134 SmallVectorImpl<MCFixup> &Fixups,
135 const MCSubtargetInfo &STI) const {
136 return getPCRelEncoding(MI, OpNum, Fixups,
137 SystemZ::FK_390_PC16DBL, 4, false);
138 }
getPC24DBLBPPEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const139 uint64_t getPC24DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
140 SmallVectorImpl<MCFixup> &Fixups,
141 const MCSubtargetInfo &STI) const {
142 return getPCRelEncoding(MI, OpNum, Fixups,
143 SystemZ::FK_390_PC24DBL, 3, false);
144 }
145
146 private:
147 uint64_t computeAvailableFeatures(const FeatureBitset &FB) const;
148 void verifyInstructionPredicates(const MCInst &MI,
149 uint64_t AvailableFeatures) const;
150 };
151
152 } // end anonymous namespace
153
154 void SystemZMCCodeEmitter::
encodeInstruction(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const155 encodeInstruction(const MCInst &MI, raw_ostream &OS,
156 SmallVectorImpl<MCFixup> &Fixups,
157 const MCSubtargetInfo &STI) const {
158 verifyInstructionPredicates(MI,
159 computeAvailableFeatures(STI.getFeatureBits()));
160
161 uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
162 unsigned Size = MCII.get(MI.getOpcode()).getSize();
163 // Big-endian insertion of Size bytes.
164 unsigned ShiftValue = (Size * 8) - 8;
165 for (unsigned I = 0; I != Size; ++I) {
166 OS << uint8_t(Bits >> ShiftValue);
167 ShiftValue -= 8;
168 }
169 }
170
171 uint64_t SystemZMCCodeEmitter::
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const172 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
173 SmallVectorImpl<MCFixup> &Fixups,
174 const MCSubtargetInfo &STI) const {
175 if (MO.isReg())
176 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
177 if (MO.isImm())
178 return static_cast<uint64_t>(MO.getImm());
179 llvm_unreachable("Unexpected operand type!");
180 }
181
182 uint64_t SystemZMCCodeEmitter::
getBDAddr12Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const183 getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
184 SmallVectorImpl<MCFixup> &Fixups,
185 const MCSubtargetInfo &STI) const {
186 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
187 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
188 assert(isUInt<4>(Base) && isUInt<12>(Disp));
189 return (Base << 12) | Disp;
190 }
191
192 uint64_t SystemZMCCodeEmitter::
getBDAddr20Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const193 getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
194 SmallVectorImpl<MCFixup> &Fixups,
195 const MCSubtargetInfo &STI) const {
196 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
197 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
198 assert(isUInt<4>(Base) && isInt<20>(Disp));
199 return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12);
200 }
201
202 uint64_t SystemZMCCodeEmitter::
getBDXAddr12Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const203 getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
204 SmallVectorImpl<MCFixup> &Fixups,
205 const MCSubtargetInfo &STI) const {
206 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
207 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
208 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
209 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index));
210 return (Index << 16) | (Base << 12) | Disp;
211 }
212
213 uint64_t SystemZMCCodeEmitter::
getBDXAddr20Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const214 getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
215 SmallVectorImpl<MCFixup> &Fixups,
216 const MCSubtargetInfo &STI) const {
217 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
218 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
219 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
220 assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index));
221 return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8)
222 | ((Disp & 0xff000) >> 12);
223 }
224
225 uint64_t SystemZMCCodeEmitter::
getBDLAddr12Len4Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const226 getBDLAddr12Len4Encoding(const MCInst &MI, unsigned OpNum,
227 SmallVectorImpl<MCFixup> &Fixups,
228 const MCSubtargetInfo &STI) const {
229 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
230 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
231 uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
232 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len));
233 return (Len << 16) | (Base << 12) | Disp;
234 }
235
236 uint64_t SystemZMCCodeEmitter::
getBDLAddr12Len8Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const237 getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
238 SmallVectorImpl<MCFixup> &Fixups,
239 const MCSubtargetInfo &STI) const {
240 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
241 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
242 uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
243 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len));
244 return (Len << 16) | (Base << 12) | Disp;
245 }
246
247 uint64_t SystemZMCCodeEmitter::
getBDRAddr12Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const248 getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum,
249 SmallVectorImpl<MCFixup> &Fixups,
250 const MCSubtargetInfo &STI) const {
251 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
252 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
253 uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
254 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len));
255 return (Len << 16) | (Base << 12) | Disp;
256 }
257
258 uint64_t SystemZMCCodeEmitter::
getBDVAddr12Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const259 getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
260 SmallVectorImpl<MCFixup> &Fixups,
261 const MCSubtargetInfo &STI) const {
262 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
263 uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
264 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
265 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<5>(Index));
266 return (Index << 16) | (Base << 12) | Disp;
267 }
268
269 uint64_t
getPCRelEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,unsigned Kind,int64_t Offset,bool AllowTLS) const270 SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
271 SmallVectorImpl<MCFixup> &Fixups,
272 unsigned Kind, int64_t Offset,
273 bool AllowTLS) const {
274 const MCOperand &MO = MI.getOperand(OpNum);
275 const MCExpr *Expr;
276 if (MO.isImm())
277 Expr = MCConstantExpr::create(MO.getImm() + Offset, Ctx);
278 else {
279 Expr = MO.getExpr();
280 if (Offset) {
281 // The operand value is relative to the start of MI, but the fixup
282 // is relative to the operand field itself, which is Offset bytes
283 // into MI. Add Offset to the relocation value to cancel out
284 // this difference.
285 const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx);
286 Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx);
287 }
288 }
289 Fixups.push_back(MCFixup::create(Offset, Expr, (MCFixupKind)Kind));
290
291 // Output the fixup for the TLS marker if present.
292 if (AllowTLS && OpNum + 1 < MI.getNumOperands()) {
293 const MCOperand &MOTLS = MI.getOperand(OpNum + 1);
294 Fixups.push_back(MCFixup::create(0, MOTLS.getExpr(),
295 (MCFixupKind)SystemZ::FK_390_TLS_CALL));
296 }
297 return 0;
298 }
299
300 #define ENABLE_INSTR_PREDICATE_VERIFIER
301 #include "SystemZGenMCCodeEmitter.inc"
302
createSystemZMCCodeEmitter(const MCInstrInfo & MCII,const MCRegisterInfo & MRI,MCContext & Ctx)303 MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,
304 const MCRegisterInfo &MRI,
305 MCContext &Ctx) {
306 return new SystemZMCCodeEmitter(MCII, Ctx);
307 }
308