LLVM 17.0.0git
SystemZMCCodeEmitter.cpp
Go to the documentation of this file.
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
15#include "SystemZInstrInfo.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"
27#include <cassert>
28#include <cstdint>
29
30using namespace llvm;
31
32#define DEBUG_TYPE "mccodeemitter"
33
34namespace {
35
36class SystemZMCCodeEmitter : public MCCodeEmitter {
37 const MCInstrInfo &MCII;
38 MCContext &Ctx;
39
40 mutable unsigned MemOpsEmitted;
41
42public:
43 SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
44 : MCII(mcii), Ctx(ctx) {
45 }
46
47 ~SystemZMCCodeEmitter() override = default;
48
49 // OVerride MCCodeEmitter.
52 const MCSubtargetInfo &STI) const override;
53
54private:
55 // Automatically generated by TableGen.
56 uint64_t getBinaryCodeForInstr(const MCInst &MI,
58 const MCSubtargetInfo &STI) const;
59
60 // Called by the TableGen code to get the binary encoding of operand
61 // MO in MI. Fixups is the list of fixups against MI.
62 uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
64 const MCSubtargetInfo &STI) const;
65
66 // Return the displacement value for the OpNum operand. If it is a symbol,
67 // add a fixup for it and return 0.
68 uint64_t getDispOpValue(const MCInst &MI, unsigned OpNum,
70 SystemZ::FixupKind Kind) const;
71
72 // Called by the TableGen code to get the binary encoding of an address.
73 // The index or length, if any, is encoded first, followed by the base,
74 // followed by the displacement. In a 20-bit displacement,
75 // the low 12 bits are encoded before the high 8 bits.
76 uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
78 const MCSubtargetInfo &STI) const;
79 uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
81 const MCSubtargetInfo &STI) const;
82 uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
84 const MCSubtargetInfo &STI) const;
85 uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
87 const MCSubtargetInfo &STI) const;
88 uint64_t getBDLAddr12Len4Encoding(const MCInst &MI, unsigned OpNum,
90 const MCSubtargetInfo &STI) const;
91 uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
93 const MCSubtargetInfo &STI) const;
94 uint64_t getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum,
96 const MCSubtargetInfo &STI) const;
97 uint64_t getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
99 const MCSubtargetInfo &STI) const;
100
101 // Operand OpNum of MI needs a PC-relative fixup of kind Kind at
102 // Offset bytes from the start of MI. Add the fixup to Fixups
103 // and return the in-place addend, which since we're a RELA target
104 // is always 0. If AllowTLS is true and optional operand OpNum + 1
105 // is present, also emit a TLS call fixup for it.
106 uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,
108 unsigned Kind, int64_t Offset,
109 bool AllowTLS) const;
110
111 uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,
113 const MCSubtargetInfo &STI) const {
114 return getPCRelEncoding(MI, OpNum, Fixups,
115 SystemZ::FK_390_PC16DBL, 2, false);
116 }
117 uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,
119 const MCSubtargetInfo &STI) const {
120 return getPCRelEncoding(MI, OpNum, Fixups,
121 SystemZ::FK_390_PC32DBL, 2, false);
122 }
123 uint64_t getPC16DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
125 const MCSubtargetInfo &STI) const {
126 return getPCRelEncoding(MI, OpNum, Fixups,
127 SystemZ::FK_390_PC16DBL, 2, true);
128 }
129 uint64_t getPC32DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
131 const MCSubtargetInfo &STI) const {
132 return getPCRelEncoding(MI, OpNum, Fixups,
133 SystemZ::FK_390_PC32DBL, 2, true);
134 }
135 uint64_t getPC12DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
137 const MCSubtargetInfo &STI) const {
138 return getPCRelEncoding(MI, OpNum, Fixups,
139 SystemZ::FK_390_PC12DBL, 1, false);
140 }
141 uint64_t getPC16DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
143 const MCSubtargetInfo &STI) const {
144 return getPCRelEncoding(MI, OpNum, Fixups,
145 SystemZ::FK_390_PC16DBL, 4, false);
146 }
147 uint64_t getPC24DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
149 const MCSubtargetInfo &STI) const {
150 return getPCRelEncoding(MI, OpNum, Fixups,
151 SystemZ::FK_390_PC24DBL, 3, false);
152 }
153};
154
155} // end anonymous namespace
156
157void SystemZMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
159 const MCSubtargetInfo &STI) const {
160 MemOpsEmitted = 0;
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
171uint64_t SystemZMCCodeEmitter::
172getMachineOpValue(const MCInst &MI, const MCOperand &MO,
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
182uint64_t SystemZMCCodeEmitter::
183getDispOpValue(const MCInst &MI, unsigned OpNum,
185 SystemZ::FixupKind Kind) const {
186 const MCOperand &MO = MI.getOperand(OpNum);
187 if (MO.isImm()) {
188 ++MemOpsEmitted;
189 return static_cast<uint64_t>(MO.getImm());
190 }
191 if (MO.isExpr()) {
192 // All instructions follow the pattern where the first displacement has a
193 // 2 bytes offset, and the second one 4 bytes.
194 unsigned ByteOffs = MemOpsEmitted++ == 0 ? 2 : 4;
195 Fixups.push_back(MCFixup::create(ByteOffs, MO.getExpr(), (MCFixupKind)Kind,
196 MI.getLoc()));
197 assert(Fixups.size() <= 2 && "More than two memory operands in MI?");
198 return 0;
199 }
200 llvm_unreachable("Unexpected operand type!");
201}
202
203uint64_t SystemZMCCodeEmitter::
204getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
206 const MCSubtargetInfo &STI) const {
207 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
208 uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
209 assert(isUInt<4>(Base) && isUInt<12>(Disp));
210 return (Base << 12) | Disp;
211}
212
213uint64_t SystemZMCCodeEmitter::
214getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
216 const MCSubtargetInfo &STI) const {
217 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
218 uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_20);
219 assert(isUInt<4>(Base) && isInt<20>(Disp));
220 return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12);
221}
222
223uint64_t SystemZMCCodeEmitter::
224getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
226 const MCSubtargetInfo &STI) const {
227 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
228 uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
229 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
230 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index));
231 return (Index << 16) | (Base << 12) | Disp;
232}
233
234uint64_t SystemZMCCodeEmitter::
235getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
237 const MCSubtargetInfo &STI) const {
238 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
239 uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_20);
240 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
241 assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index));
242 return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8)
243 | ((Disp & 0xff000) >> 12);
244}
245
246uint64_t SystemZMCCodeEmitter::
247getBDLAddr12Len4Encoding(const MCInst &MI, unsigned OpNum,
249 const MCSubtargetInfo &STI) const {
250 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
251 uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
252 uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
253 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len));
254 return (Len << 16) | (Base << 12) | Disp;
255}
256
257uint64_t SystemZMCCodeEmitter::
258getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
260 const MCSubtargetInfo &STI) const {
261 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
262 uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
263 uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
264 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len));
265 return (Len << 16) | (Base << 12) | Disp;
266}
267
268uint64_t SystemZMCCodeEmitter::
269getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum,
271 const MCSubtargetInfo &STI) const {
272 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
273 uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
274 uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
275 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len));
276 return (Len << 16) | (Base << 12) | Disp;
277}
278
279uint64_t SystemZMCCodeEmitter::
280getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
282 const MCSubtargetInfo &STI) const {
283 uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
284 uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
285 uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
286 assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<5>(Index));
287 return (Index << 16) | (Base << 12) | Disp;
288}
289
291SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
293 unsigned Kind, int64_t Offset,
294 bool AllowTLS) const {
295 SMLoc Loc = MI.getLoc();
296 const MCOperand &MO = MI.getOperand(OpNum);
297 const MCExpr *Expr;
298 if (MO.isImm())
299 Expr = MCConstantExpr::create(MO.getImm() + Offset, Ctx);
300 else {
301 Expr = MO.getExpr();
302 if (Offset) {
303 // The operand value is relative to the start of MI, but the fixup
304 // is relative to the operand field itself, which is Offset bytes
305 // into MI. Add Offset to the relocation value to cancel out
306 // this difference.
307 const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx);
308 Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx);
309 }
310 }
311 Fixups.push_back(MCFixup::create(Offset, Expr, (MCFixupKind)Kind, Loc));
312
313 // Output the fixup for the TLS marker if present.
314 if (AllowTLS && OpNum + 1 < MI.getNumOperands()) {
315 const MCOperand &MOTLS = MI.getOperand(OpNum + 1);
316 Fixups.push_back(MCFixup::create(
317 0, MOTLS.getExpr(), (MCFixupKind)SystemZ::FK_390_TLS_CALL, Loc));
318 }
319 return 0;
320}
321
322#include "SystemZGenMCCodeEmitter.inc"
323
325 MCContext &Ctx) {
326 return new SystemZMCCodeEmitter(MCII, Ctx);
327}
uint64_t Size
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
This file defines the SmallVector class.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:525
MCCodeEmitter - Generic instruction encoding interface.
Definition: MCCodeEmitter.h:21
virtual void encodeInstruction(const MCInst &Inst, raw_ostream &OS, SmallVectorImpl< MCFixup > &Fixups, const MCSubtargetInfo &STI) const =0
EncodeInstruction - Encode the given Inst to bytes on the output stream OS.
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
Context object for machine code objects.
Definition: MCContext.h:76
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
Definition: MCFixup.h:87
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
Interface to description of machine instruction set.
Definition: MCInstrInfo.h:26
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
int64_t getImm() const
Definition: MCInst.h:80
bool isImm() const
Definition: MCInst.h:62
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69
bool isReg() const
Definition: MCInst.h:61
const MCExpr * getExpr() const
Definition: MCInst.h:114
bool isExpr() const
Definition: MCInst.h:65
Generic base class for all target subtargets.
Represents a location in source code.
Definition: SMLoc.h:23
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:406
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:21
MCCodeEmitter * createSystemZMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)