[InstCombine] Signed saturation patterns
[llvm-complete.git] / lib / Target / SystemZ / MCTargetDesc / SystemZMCCodeEmitter.cpp
bloba5ccf4f68ffdf35d01ad30927d9821ed79771154
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.
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"
26 #include <cassert>
27 #include <cstdint>
29 using namespace llvm;
31 #define DEBUG_TYPE "mccodeemitter"
33 namespace {
35 class SystemZMCCodeEmitter : public MCCodeEmitter {
36 const MCInstrInfo &MCII;
37 MCContext &Ctx;
39 public:
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;
51 private:
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);
145 private:
146 FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const;
147 void
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);
167 ShiftValue -= 8;
171 uint64_t SystemZMCCodeEmitter::
172 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!");
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;
269 uint64_t
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);
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);
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));
297 return 0;
300 #define ENABLE_INSTR_PREDICATE_VERIFIER
301 #include "SystemZGenMCCodeEmitter.inc"
303 MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,
304 const MCRegisterInfo &MRI,
305 MCContext &Ctx) {
306 return new SystemZMCCodeEmitter(MCII, Ctx);