1 //===-- SystemZMCCodeEmitter.cpp - Convert SystemZ code to machine code ---===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the SystemZMCCodeEmitter class.
11 //===----------------------------------------------------------------------===//
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"
31 #define DEBUG_TYPE "mccodeemitter"
35 class SystemZMCCodeEmitter
: public MCCodeEmitter
{
36 const MCInstrInfo
&MCII
;
40 SystemZMCCodeEmitter(const MCInstrInfo
&mcii
, MCContext
&ctx
)
41 : MCII(mcii
), Ctx(ctx
) {
44 ~SystemZMCCodeEmitter() override
= default;
46 // OVerride MCCodeEmitter.
47 void encodeInstruction(const MCInst
&MI
, raw_ostream
&OS
,
48 SmallVectorImpl
<MCFixup
> &Fixups
,
49 const MCSubtargetInfo
&STI
) const override
;
52 // Automatically generated by TableGen.
53 uint64_t getBinaryCodeForInstr(const MCInst
&MI
,
54 SmallVectorImpl
<MCFixup
> &Fixups
,
55 const MCSubtargetInfo
&STI
) const;
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;
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;
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;
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);
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);
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);
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);
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);
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);
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);
146 FeatureBitset
computeAvailableFeatures(const FeatureBitset
&FB
) const;
148 verifyInstructionPredicates(const MCInst
&MI
,
149 const FeatureBitset
&AvailableFeatures
) const;
152 } // end anonymous namespace
154 void SystemZMCCodeEmitter::
155 encodeInstruction(const MCInst
&MI
, raw_ostream
&OS
,
156 SmallVectorImpl
<MCFixup
> &Fixups
,
157 const MCSubtargetInfo
&STI
) const {
158 verifyInstructionPredicates(MI
,
159 computeAvailableFeatures(STI
.getFeatureBits()));
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
);
171 uint64_t SystemZMCCodeEmitter::
172 getMachineOpValue(const MCInst
&MI
, const MCOperand
&MO
,
173 SmallVectorImpl
<MCFixup
> &Fixups
,
174 const MCSubtargetInfo
&STI
) const {
176 return Ctx
.getRegisterInfo()->getEncodingValue(MO
.getReg());
178 return static_cast<uint64_t>(MO
.getImm());
179 llvm_unreachable("Unexpected operand type!");
182 uint64_t SystemZMCCodeEmitter::
183 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
;
192 uint64_t SystemZMCCodeEmitter::
193 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);
202 uint64_t SystemZMCCodeEmitter::
203 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
;
213 uint64_t SystemZMCCodeEmitter::
214 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);
225 uint64_t SystemZMCCodeEmitter::
226 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
;
236 uint64_t SystemZMCCodeEmitter::
237 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
;
247 uint64_t SystemZMCCodeEmitter::
248 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
;
258 uint64_t SystemZMCCodeEmitter::
259 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
;
270 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
);
277 Expr
= MCConstantExpr::create(MO
.getImm() + Offset
, Ctx
);
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
285 const MCExpr
*OffsetExpr
= MCConstantExpr::create(Offset
, Ctx
);
286 Expr
= MCBinaryExpr::createAdd(Expr
, OffsetExpr
, Ctx
);
289 Fixups
.push_back(MCFixup::create(Offset
, Expr
, (MCFixupKind
)Kind
));
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
));
300 #define ENABLE_INSTR_PREDICATE_VERIFIER
301 #include "SystemZGenMCCodeEmitter.inc"
303 MCCodeEmitter
*llvm::createSystemZMCCodeEmitter(const MCInstrInfo
&MCII
,
304 const MCRegisterInfo
&MRI
,
306 return new SystemZMCCodeEmitter(MCII
, Ctx
);