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
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>
28
29using namespace llvm;
30
31#define DEBUG_TYPE "mccodeemitter"
32
33namespace {
34
35class SystemZMCCodeEmitter : public MCCodeEmitter {
36  const MCInstrInfo &MCII;
37  MCContext &Ctx;
38
39public:
40  SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
41    : MCII(mcii), Ctx(ctx) {
42  }
43
44  ~SystemZMCCodeEmitter() override = default;
45
46  // OVerride MCCodeEmitter.
47  void encodeInstruction(const MCInst &MI, raw_ostream &OS,
48                         SmallVectorImpl<MCFixup> &Fixups,
49                         const MCSubtargetInfo &STI) const override;
50
51private:
52  // Automatically generated by TableGen.
53  uint64_t getBinaryCodeForInstr(const MCInst &MI,
54                                 SmallVectorImpl<MCFixup> &Fixups,
55                                 const MCSubtargetInfo &STI) const;
56
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;
62
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;
91
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;
101
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);
107  }
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);
113  }
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);
119  }
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);
125  }
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);
131  }
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);
137  }
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);
143  }
144
145private:
146  FeatureBitset computeAvailableFeatures(const FeatureBitset &FB) const;
147  void
148  verifyInstructionPredicates(const MCInst &MI,
149                              const FeatureBitset &AvailableFeatures) const;
150};
151
152} // end anonymous namespace
153
154void SystemZMCCodeEmitter::
155encodeInstruction(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
171uint64_t SystemZMCCodeEmitter::
172getMachineOpValue(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
182uint64_t SystemZMCCodeEmitter::
183getBDAddr12Encoding(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
192uint64_t SystemZMCCodeEmitter::
193getBDAddr20Encoding(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
202uint64_t SystemZMCCodeEmitter::
203getBDXAddr12Encoding(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
213uint64_t SystemZMCCodeEmitter::
214getBDXAddr20Encoding(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
225uint64_t SystemZMCCodeEmitter::
226getBDLAddr12Len4Encoding(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
236uint64_t SystemZMCCodeEmitter::
237getBDLAddr12Len8Encoding(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
247uint64_t SystemZMCCodeEmitter::
248getBDRAddr12Encoding(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
258uint64_t SystemZMCCodeEmitter::
259getBDVAddr12Encoding(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
269uint64_t
270SystemZMCCodeEmitter::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
303MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,
304                                                const MCRegisterInfo &MRI,
305                                                MCContext &Ctx) {
306  return new SystemZMCCodeEmitter(MCII, Ctx);
307}
308