Coverage Report

Created: 2025-07-18 06:59

/src/keystone/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- PPCMCCodeEmitter.cpp - Convert PPC 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 PPCMCCodeEmitter class.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "MCTargetDesc/PPCMCTargetDesc.h"
15
#include "MCTargetDesc/PPCFixupKinds.h"
16
#include "llvm/MC/MCAsmInfo.h"
17
#include "llvm/MC/MCCodeEmitter.h"
18
#include "llvm/MC/MCContext.h"
19
#include "llvm/MC/MCExpr.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/EndianStream.h"
25
#include "llvm/Support/ErrorHandling.h"
26
#include "llvm/Support/raw_ostream.h"
27
28
using namespace llvm_ks;
29
30
#define DEBUG_TYPE "mccodeemitter"
31
32
namespace {
33
class PPCMCCodeEmitter : public MCCodeEmitter {
34
  PPCMCCodeEmitter(const PPCMCCodeEmitter &) = delete;
35
  void operator=(const PPCMCCodeEmitter &) = delete;
36
37
  const MCInstrInfo &MCII;
38
  const MCContext &CTX;
39
  bool IsLittleEndian;
40
41
public:
42
  PPCMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
43
5.54k
      : MCII(mcii), CTX(ctx),
44
5.54k
        IsLittleEndian(ctx.getAsmInfo()->isLittleEndian()) {}
45
46
0
  ~PPCMCCodeEmitter() override {}
47
48
  unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
49
                               SmallVectorImpl<MCFixup> &Fixups,
50
                               const MCSubtargetInfo &STI) const;
51
  unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo,
52
                             SmallVectorImpl<MCFixup> &Fixups,
53
                             const MCSubtargetInfo &STI) const;
54
  unsigned getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo,
55
                                  SmallVectorImpl<MCFixup> &Fixups,
56
                                  const MCSubtargetInfo &STI) const;
57
  unsigned getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo,
58
                                SmallVectorImpl<MCFixup> &Fixups,
59
                                const MCSubtargetInfo &STI) const;
60
  unsigned getImm16Encoding(const MCInst &MI, unsigned OpNo,
61
                             SmallVectorImpl<MCFixup> &Fixups,
62
                             const MCSubtargetInfo &STI) const;
63
  unsigned getMemRIEncoding(const MCInst &MI, unsigned OpNo,
64
                            SmallVectorImpl<MCFixup> &Fixups,
65
                            const MCSubtargetInfo &STI) const;
66
  unsigned getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
67
                             SmallVectorImpl<MCFixup> &Fixups,
68
                             const MCSubtargetInfo &STI) const;
69
  unsigned getSPE8DisEncoding(const MCInst &MI, unsigned OpNo,
70
                              SmallVectorImpl<MCFixup> &Fixups,
71
                              const MCSubtargetInfo &STI) const;
72
  unsigned getSPE4DisEncoding(const MCInst &MI, unsigned OpNo,
73
                              SmallVectorImpl<MCFixup> &Fixups,
74
                              const MCSubtargetInfo &STI) const;
75
  unsigned getSPE2DisEncoding(const MCInst &MI, unsigned OpNo,
76
                              SmallVectorImpl<MCFixup> &Fixups,
77
                              const MCSubtargetInfo &STI) const;
78
  unsigned getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
79
                             SmallVectorImpl<MCFixup> &Fixups,
80
                             const MCSubtargetInfo &STI) const;
81
  unsigned getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
82
                              SmallVectorImpl<MCFixup> &Fixups,
83
                              const MCSubtargetInfo &STI) const;
84
  unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
85
                               SmallVectorImpl<MCFixup> &Fixups,
86
                               const MCSubtargetInfo &STI) const;
87
88
  /// getMachineOpValue - Return binary encoding of operand. If the machine
89
  /// operand requires relocation, record the relocation and return zero.
90
  unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
91
                             SmallVectorImpl<MCFixup> &Fixups,
92
                             const MCSubtargetInfo &STI) const;
93
  
94
  // getBinaryCodeForInstr - TableGen'erated function for getting the
95
  // binary encoding for an instruction.
96
  uint64_t getBinaryCodeForInstr(const MCInst &MI,
97
                                 SmallVectorImpl<MCFixup> &Fixups,
98
                                 const MCSubtargetInfo &STI) const;
99
  void encodeInstruction(MCInst &MI, raw_ostream &OS,
100
                         SmallVectorImpl<MCFixup> &Fixups,
101
                         const MCSubtargetInfo &STI,
102
30.6k
                         unsigned int &KsError) const override {
103
30.6k
    unsigned Opcode = MI.getOpcode();
104
30.6k
    const MCInstrDesc &Desc = MCII.get(Opcode);
105
106
30.6k
    uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
107
108
30.6k
    KsError = 0;
109
110
    // Output the constant in big/little endian byte order.
111
30.6k
    unsigned Size = Desc.getSize();
112
30.6k
    switch (Size) {
113
30.6k
    case 4:
114
30.6k
      if (IsLittleEndian) {
115
1.00k
        support::endian::Writer<support::little>(OS).write<uint32_t>(Bits);
116
29.6k
      } else {
117
29.6k
        support::endian::Writer<support::big>(OS).write<uint32_t>(Bits);
118
29.6k
      }
119
30.6k
      break;
120
0
    case 8:
121
      // If we emit a pair of instructions, the first one is
122
      // always in the top 32 bits, even on little-endian.
123
0
      if (IsLittleEndian) {
124
0
        uint64_t Swapped = (Bits << 32) | (Bits >> 32);
125
0
        support::endian::Writer<support::little>(OS).write<uint64_t>(Swapped);
126
0
      } else {
127
0
        support::endian::Writer<support::big>(OS).write<uint64_t>(Bits);
128
0
      }
129
0
      break;
130
0
    default:
131
0
      llvm_unreachable ("Invalid instruction size");
132
30.6k
    }
133
134
    // Keystone: update Inst.Address to point to the next instruction
135
30.6k
    MI.setAddress(MI.getAddress() + Size);
136
30.6k
  }
137
  
138
};
139
  
140
} // end anonymous namespace
141
142
MCCodeEmitter *llvm_ks::createPPCMCCodeEmitter(const MCInstrInfo &MCII,
143
                                            const MCRegisterInfo &MRI,
144
5.54k
                                            MCContext &Ctx) {
145
5.54k
  return new PPCMCCodeEmitter(MCII, Ctx);
146
5.54k
}
147
148
unsigned PPCMCCodeEmitter::
149
getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
150
                    SmallVectorImpl<MCFixup> &Fixups,
151
2.37k
                    const MCSubtargetInfo &STI) const {
152
2.37k
  const MCOperand &MO = MI.getOperand(OpNo);
153
154
2.37k
  if (MO.isImm())
155
61
      return (MO.getImm() * 4 - MI.getAddress()) / 4;
156
157
2.31k
  if (MO.isReg())
158
0
      return getMachineOpValue(MI, MO, Fixups, STI);
159
  
160
  // Add a fixup for the branch target.
161
2.31k
  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
162
2.31k
                                   (MCFixupKind)PPC::fixup_ppc_br24));
163
2.31k
  return 0;
164
2.31k
}
165
166
unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
167
                                     SmallVectorImpl<MCFixup> &Fixups,
168
24.9k
                                     const MCSubtargetInfo &STI) const {
169
24.9k
  const MCOperand &MO = MI.getOperand(OpNo);
170
171
24.9k
  if (MO.isImm())
172
496
      return (MO.getImm() * 4 - MI.getAddress()) / 4;
173
174
24.4k
  if (MO.isReg())
175
0
      return getMachineOpValue(MI, MO, Fixups, STI);
176
177
  // Add a fixup for the branch target.
178
24.4k
  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
179
24.4k
                                   (MCFixupKind)PPC::fixup_ppc_brcond14));
180
24.4k
  return 0;
181
24.4k
}
182
183
unsigned PPCMCCodeEmitter::
184
getAbsDirectBrEncoding(const MCInst &MI, unsigned OpNo,
185
                       SmallVectorImpl<MCFixup> &Fixups,
186
68
                       const MCSubtargetInfo &STI) const {
187
68
  const MCOperand &MO = MI.getOperand(OpNo);
188
68
  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
189
190
  // Add a fixup for the branch target.
191
63
  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
192
63
                                   (MCFixupKind)PPC::fixup_ppc_br24abs));
193
63
  return 0;
194
68
}
195
196
unsigned PPCMCCodeEmitter::
197
getAbsCondBrEncoding(const MCInst &MI, unsigned OpNo,
198
                     SmallVectorImpl<MCFixup> &Fixups,
199
1.10k
                     const MCSubtargetInfo &STI) const {
200
1.10k
  const MCOperand &MO = MI.getOperand(OpNo);
201
1.10k
  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
202
203
  // Add a fixup for the branch target.
204
883
  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
205
883
                                   (MCFixupKind)PPC::fixup_ppc_brcond14abs));
206
883
  return 0;
207
1.10k
}
208
209
unsigned PPCMCCodeEmitter::getImm16Encoding(const MCInst &MI, unsigned OpNo,
210
                                       SmallVectorImpl<MCFixup> &Fixups,
211
251
                                       const MCSubtargetInfo &STI) const {
212
251
  const MCOperand &MO = MI.getOperand(OpNo);
213
251
  if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI);
214
  
215
  // Add a fixup for the immediate field.
216
126
  Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
217
126
                                   (MCFixupKind)PPC::fixup_ppc_half16));
218
126
  return 0;
219
251
}
220
221
unsigned PPCMCCodeEmitter::getMemRIEncoding(const MCInst &MI, unsigned OpNo,
222
                                            SmallVectorImpl<MCFixup> &Fixups,
223
28
                                            const MCSubtargetInfo &STI) const {
224
  // Encode (imm, reg) as a memri, which has the low 16-bits as the
225
  // displacement and the next 5 bits as the register #.
226
28
  assert(MI.getOperand(OpNo+1).isReg());
227
28
  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 16;
228
  
229
28
  const MCOperand &MO = MI.getOperand(OpNo);
230
28
  if (MO.isImm())
231
8
    return (getMachineOpValue(MI, MO, Fixups, STI) & 0xFFFF) | RegBits;
232
  
233
  // Add a fixup for the displacement field.
234
20
  Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
235
20
                                   (MCFixupKind)PPC::fixup_ppc_half16));
236
20
  return RegBits;
237
28
}
238
239
240
unsigned PPCMCCodeEmitter::getMemRIXEncoding(const MCInst &MI, unsigned OpNo,
241
                                       SmallVectorImpl<MCFixup> &Fixups,
242
181
                                       const MCSubtargetInfo &STI) const {
243
  // Encode (imm, reg) as a memrix, which has the low 14-bits as the
244
  // displacement and the next 5 bits as the register #.
245
181
  assert(MI.getOperand(OpNo+1).isReg());
246
181
  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 14;
247
  
248
181
  const MCOperand &MO = MI.getOperand(OpNo);
249
181
  if (MO.isImm())
250
8
    return ((getMachineOpValue(MI, MO, Fixups, STI) >> 2) & 0x3FFF) | RegBits;
251
  
252
  // Add a fixup for the displacement field.
253
173
  Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
254
173
                                   (MCFixupKind)PPC::fixup_ppc_half16ds));
255
173
  return RegBits;
256
181
}
257
258
259
unsigned PPCMCCodeEmitter::getSPE8DisEncoding(const MCInst &MI, unsigned OpNo,
260
                                              SmallVectorImpl<MCFixup> &Fixups,
261
                                              const MCSubtargetInfo &STI)
262
0
                                              const {
263
  // Encode (imm, reg) as a spe8dis, which has the low 5-bits of (imm / 8)
264
  // as the displacement and the next 5 bits as the register #.
265
0
  assert(MI.getOperand(OpNo+1).isReg());
266
0
  uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
267
268
0
  const MCOperand &MO = MI.getOperand(OpNo);
269
0
  assert(MO.isImm());
270
0
  uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 3;
271
0
  return reverseBits(Imm | RegBits) >> 22;
272
0
}
273
274
275
unsigned PPCMCCodeEmitter::getSPE4DisEncoding(const MCInst &MI, unsigned OpNo,
276
                                              SmallVectorImpl<MCFixup> &Fixups,
277
                                              const MCSubtargetInfo &STI)
278
0
                                              const {
279
  // Encode (imm, reg) as a spe4dis, which has the low 5-bits of (imm / 4)
280
  // as the displacement and the next 5 bits as the register #.
281
0
  assert(MI.getOperand(OpNo+1).isReg());
282
0
  uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
283
284
0
  const MCOperand &MO = MI.getOperand(OpNo);
285
0
  assert(MO.isImm());
286
0
  uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 2;
287
0
  return reverseBits(Imm | RegBits) >> 22;
288
0
}
289
290
291
unsigned PPCMCCodeEmitter::getSPE2DisEncoding(const MCInst &MI, unsigned OpNo,
292
                                              SmallVectorImpl<MCFixup> &Fixups,
293
                                              const MCSubtargetInfo &STI)
294
0
                                              const {
295
  // Encode (imm, reg) as a spe2dis, which has the low 5-bits of (imm / 2)
296
  // as the displacement and the next 5 bits as the register #.
297
0
  assert(MI.getOperand(OpNo+1).isReg());
298
0
  uint32_t RegBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI) << 5;
299
300
0
  const MCOperand &MO = MI.getOperand(OpNo);
301
0
  assert(MO.isImm());
302
0
  uint32_t Imm = getMachineOpValue(MI, MO, Fixups, STI) >> 1;
303
0
  return reverseBits(Imm | RegBits) >> 22;
304
0
}
305
306
307
unsigned PPCMCCodeEmitter::getTLSRegEncoding(const MCInst &MI, unsigned OpNo,
308
                                       SmallVectorImpl<MCFixup> &Fixups,
309
0
                                       const MCSubtargetInfo &STI) const {
310
0
  const MCOperand &MO = MI.getOperand(OpNo);
311
0
  if (MO.isReg()) return getMachineOpValue(MI, MO, Fixups, STI);
312
  
313
  // Add a fixup for the TLS register, which simply provides a relocation
314
  // hint to the linker that this statement is part of a relocation sequence.
315
  // Return the thread-pointer register's encoding.
316
0
  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
317
0
                                   (MCFixupKind)PPC::fixup_ppc_nofixup));
318
0
  const Triple &TT = STI.getTargetTriple();
319
0
  bool isPPC64 = TT.getArch() == Triple::ppc64 || TT.getArch() == Triple::ppc64le;
320
0
  return CTX.getRegisterInfo()->getEncodingValue(isPPC64 ? PPC::X13 : PPC::R2);
321
0
}
322
323
unsigned PPCMCCodeEmitter::getTLSCallEncoding(const MCInst &MI, unsigned OpNo,
324
                                       SmallVectorImpl<MCFixup> &Fixups,
325
14
                                       const MCSubtargetInfo &STI) const {
326
  // For special TLS calls, we need two fixups; one for the branch target
327
  // (__tls_get_addr), which we create via getDirectBrEncoding as usual,
328
  // and one for the TLSGD or TLSLD symbol, which is emitted here.
329
14
  const MCOperand &MO = MI.getOperand(OpNo+1);
330
14
  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
331
14
                                   (MCFixupKind)PPC::fixup_ppc_nofixup));
332
14
  return getDirectBrEncoding(MI, OpNo, Fixups, STI);
333
14
}
334
335
unsigned PPCMCCodeEmitter::
336
get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
337
                    SmallVectorImpl<MCFixup> &Fixups,
338
0
                    const MCSubtargetInfo &STI) const {
339
0
  const MCOperand &MO = MI.getOperand(OpNo);
340
0
  assert((MI.getOpcode() == PPC::MTOCRF || MI.getOpcode() == PPC::MTOCRF8 ||
341
0
          MI.getOpcode() == PPC::MFOCRF || MI.getOpcode() == PPC::MFOCRF8) &&
342
0
         (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
343
0
  return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
344
0
}
345
346
347
unsigned PPCMCCodeEmitter::
348
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
349
                  SmallVectorImpl<MCFixup> &Fixups,
350
54.2k
                  const MCSubtargetInfo &STI) const {
351
54.2k
  if (MO.isReg()) {
352
    // MTOCRF/MFOCRF should go through get_crbitm_encoding for the CR operand.
353
    // The GPR operand should come through here though.
354
28.2k
    assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 &&
355
28.2k
            MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) ||
356
28.2k
           MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
357
28.2k
    return CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
358
28.2k
  }
359
  
360
26.0k
  assert(MO.isImm() &&
361
26.0k
         "Relocation required in an instruction that we cannot encode!");
362
26.0k
  return MO.getImm();
363
26.0k
}
364
365
366
#include "PPCGenMCCodeEmitter.inc"