Coverage Report

Created: 2025-07-14 06:17

/src/keystone/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp
Line
Count
Source (jump to first uncovered line)
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/SystemZMCTargetDesc.h"
15
#include "MCTargetDesc/SystemZMCFixups.h"
16
#include "llvm/MC/MCCodeEmitter.h"
17
#include "llvm/MC/MCContext.h"
18
#include "llvm/MC/MCExpr.h"
19
#include "llvm/MC/MCInst.h"
20
#include "llvm/MC/MCInstrInfo.h"
21
#include "llvm/MC/MCRegisterInfo.h"
22
23
using namespace llvm_ks;
24
25
#define DEBUG_TYPE "mccodeemitter"
26
27
namespace {
28
class SystemZMCCodeEmitter : public MCCodeEmitter {
29
  const MCInstrInfo &MCII;
30
  MCContext &Ctx;
31
32
public:
33
  SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
34
38
    : MCII(mcii), Ctx(ctx) {
35
38
  }
36
37
0
  ~SystemZMCCodeEmitter() override {}
38
39
  // OVerride MCCodeEmitter.
40
  void encodeInstruction(MCInst &MI, raw_ostream &OS,
41
                         SmallVectorImpl<MCFixup> &Fixups,
42
                         const MCSubtargetInfo &STI,
43
                         unsigned int &KsError) const override;
44
45
private:
46
  // Automatically generated by TableGen.
47
  uint64_t getBinaryCodeForInstr(const MCInst &MI,
48
                                 SmallVectorImpl<MCFixup> &Fixups,
49
                                 const MCSubtargetInfo &STI) const;
50
51
  // Called by the TableGen code to get the binary encoding of operand
52
  // MO in MI.  Fixups is the list of fixups against MI.
53
  uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
54
                             SmallVectorImpl<MCFixup> &Fixups,
55
                             const MCSubtargetInfo &STI) const;
56
57
  // Called by the TableGen code to get the binary encoding of an address.
58
  // The index or length, if any, is encoded first, followed by the base,
59
  // followed by the displacement.  In a 20-bit displacement,
60
  // the low 12 bits are encoded before the high 8 bits.
61
  uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
62
                               SmallVectorImpl<MCFixup> &Fixups,
63
                               const MCSubtargetInfo &STI) const;
64
  uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
65
                               SmallVectorImpl<MCFixup> &Fixups,
66
                               const MCSubtargetInfo &STI) const;
67
  uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
68
                                SmallVectorImpl<MCFixup> &Fixups,
69
                                const MCSubtargetInfo &STI) const;
70
  uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
71
                                SmallVectorImpl<MCFixup> &Fixups,
72
                                const MCSubtargetInfo &STI) const;
73
  uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
74
                                    SmallVectorImpl<MCFixup> &Fixups,
75
                                    const MCSubtargetInfo &STI) const;
76
  uint64_t getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
77
                                SmallVectorImpl<MCFixup> &Fixups,
78
                                const MCSubtargetInfo &STI) const;
79
80
  // Operand OpNum of MI needs a PC-relative fixup of kind Kind at
81
  // Offset bytes from the start of MI.  Add the fixup to Fixups
82
  // and return the in-place addend, which since we're a RELA target
83
  // is always 0.  If AllowTLS is true and optional operand OpNum + 1
84
  // is present, also emit a TLS call fixup for it.
85
  uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,
86
                            SmallVectorImpl<MCFixup> &Fixups,
87
                            unsigned Kind, int64_t Offset,
88
                            bool AllowTLS) const;
89
90
  uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,
91
                              SmallVectorImpl<MCFixup> &Fixups,
92
0
                              const MCSubtargetInfo &STI) const {
93
0
    return getPCRelEncoding(MI, OpNum, Fixups,
94
0
                            SystemZ::FK_390_PC16DBL, 2, false);
95
0
  }
96
  uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,
97
                              SmallVectorImpl<MCFixup> &Fixups,
98
0
                              const MCSubtargetInfo &STI) const {
99
0
    return getPCRelEncoding(MI, OpNum, Fixups,
100
0
                            SystemZ::FK_390_PC32DBL, 2, false);
101
0
  }
102
  uint64_t getPC16DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
103
                                 SmallVectorImpl<MCFixup> &Fixups,
104
0
                                 const MCSubtargetInfo &STI) const {
105
0
    return getPCRelEncoding(MI, OpNum, Fixups,
106
0
                            SystemZ::FK_390_PC16DBL, 2, true);
107
0
  }
108
  uint64_t getPC32DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
109
                                 SmallVectorImpl<MCFixup> &Fixups,
110
0
                                 const MCSubtargetInfo &STI) const {
111
0
    return getPCRelEncoding(MI, OpNum, Fixups,
112
0
                            SystemZ::FK_390_PC32DBL, 2, true);
113
0
  }
114
};
115
} // end anonymous namespace
116
117
MCCodeEmitter *llvm_ks::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,
118
                                                const MCRegisterInfo &MRI,
119
38
                                                MCContext &Ctx) {
120
38
  return new SystemZMCCodeEmitter(MCII, Ctx);
121
38
}
122
123
void SystemZMCCodeEmitter::
124
encodeInstruction(MCInst &MI, raw_ostream &OS,
125
                  SmallVectorImpl<MCFixup> &Fixups,
126
                  const MCSubtargetInfo &STI,
127
                  unsigned int &KsError) const
128
0
{
129
0
  uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
130
0
  unsigned Size = MCII.get(MI.getOpcode()).getSize();
131
132
0
  KsError = 0;
133
  // Big-endian insertion of Size bytes.
134
0
  unsigned ShiftValue = (Size * 8) - 8;
135
0
  for (unsigned I = 0; I != Size; ++I) {
136
0
    OS << uint8_t(Bits >> ShiftValue);
137
0
    ShiftValue -= 8;
138
0
  }
139
140
  // Keystone: update Inst.Address to point to the next instruction
141
0
  MI.setAddress(MI.getAddress() + Size);
142
0
}
143
144
uint64_t SystemZMCCodeEmitter::
145
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
146
                  SmallVectorImpl<MCFixup> &Fixups,
147
0
                  const MCSubtargetInfo &STI) const {
148
0
  if (MO.isReg())
149
0
    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
150
0
  if (MO.isImm())
151
0
    return static_cast<uint64_t>(MO.getImm());
152
0
  llvm_unreachable("Unexpected operand type!");
153
0
}
154
155
uint64_t SystemZMCCodeEmitter::
156
getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
157
                    SmallVectorImpl<MCFixup> &Fixups,
158
0
                    const MCSubtargetInfo &STI) const {
159
0
  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
160
0
  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
161
0
  assert(isUInt<4>(Base) && isUInt<12>(Disp));
162
0
  return (Base << 12) | Disp;
163
0
}
164
165
uint64_t SystemZMCCodeEmitter::
166
getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
167
                    SmallVectorImpl<MCFixup> &Fixups,
168
0
                    const MCSubtargetInfo &STI) const {
169
0
  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
170
0
  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
171
0
  assert(isUInt<4>(Base) && isInt<20>(Disp));
172
0
  return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12);
173
0
}
174
175
uint64_t SystemZMCCodeEmitter::
176
getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
177
                     SmallVectorImpl<MCFixup> &Fixups,
178
0
                     const MCSubtargetInfo &STI) const {
179
0
  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
180
0
  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
181
0
  uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
182
0
  assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index));
183
0
  return (Index << 16) | (Base << 12) | Disp;
184
0
}
185
186
uint64_t SystemZMCCodeEmitter::
187
getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
188
                     SmallVectorImpl<MCFixup> &Fixups,
189
0
                     const MCSubtargetInfo &STI) const {
190
0
  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
191
0
  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
192
0
  uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
193
0
  assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index));
194
0
  return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8)
195
0
    | ((Disp & 0xff000) >> 12);
196
0
}
197
198
uint64_t SystemZMCCodeEmitter::
199
getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
200
                         SmallVectorImpl<MCFixup> &Fixups,
201
0
                         const MCSubtargetInfo &STI) const {
202
0
  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
203
0
  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
204
0
  uint64_t Len  = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
205
0
  assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len));
206
0
  return (Len << 16) | (Base << 12) | Disp;
207
0
}
208
209
uint64_t SystemZMCCodeEmitter::
210
getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
211
                     SmallVectorImpl<MCFixup> &Fixups,
212
0
                     const MCSubtargetInfo &STI) const {
213
0
  uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
214
0
  uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
215
0
  uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
216
0
  assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<5>(Index));
217
0
  return (Index << 16) | (Base << 12) | Disp;
218
0
}
219
220
uint64_t
221
SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
222
                                       SmallVectorImpl<MCFixup> &Fixups,
223
                                       unsigned Kind, int64_t Offset,
224
0
                                       bool AllowTLS) const {
225
0
  const MCOperand &MO = MI.getOperand(OpNum);
226
0
  const MCExpr *Expr;
227
0
  if (MO.isImm())
228
0
    Expr = MCConstantExpr::create(MO.getImm() + Offset - MI.getAddress(), Ctx);
229
0
  else {
230
0
    Expr = MO.getExpr();
231
0
    if (Offset) {
232
      // The operand value is relative to the start of MI, but the fixup
233
      // is relative to the operand field itself, which is Offset bytes
234
      // into MI.  Add Offset to the relocation value to cancel out
235
      // this difference.
236
0
      const MCExpr *AddrExpr = MCConstantExpr::create(-MI.getAddress(), Ctx);
237
0
      Expr = MCBinaryExpr::createAdd(Expr, AddrExpr, Ctx);
238
0
      const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx);
239
0
      Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx);
240
0
    }
241
0
  }
242
0
  Fixups.push_back(MCFixup::create(Offset, Expr, (MCFixupKind)Kind));
243
244
  // Output the fixup for the TLS marker if present.
245
0
  if (AllowTLS && OpNum + 1 < MI.getNumOperands()) {
246
0
    const MCOperand &MOTLS = MI.getOperand(OpNum + 1);
247
0
    Fixups.push_back(MCFixup::create(0, MOTLS.getExpr(),
248
0
                                     (MCFixupKind)SystemZ::FK_390_TLS_CALL));
249
0
  }
250
0
  return 0;
251
0
}
252
253
#include "SystemZGenMCCodeEmitter.inc"