Coverage Report

Created: 2025-11-11 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/keystone/llvm/lib/Target/Sparc/MCTargetDesc/SparcMCCodeEmitter.cpp
Line
Count
Source
1
//===-- SparcMCCodeEmitter.cpp - Convert Sparc 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 SparcMCCodeEmitter class.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "SparcMCExpr.h"
15
#include "MCTargetDesc/SparcFixupKinds.h"
16
#include "SparcMCTargetDesc.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/MCRegisterInfo.h"
22
#include "llvm/MC/MCSymbol.h"
23
#include "llvm/MC/MCAsmInfo.h"
24
#include "llvm/Support/raw_ostream.h"
25
#include "llvm/Support/EndianStream.h"
26
27
using namespace llvm_ks;
28
29
#define DEBUG_TYPE "mccodeemitter"
30
31
32
namespace {
33
class SparcMCCodeEmitter : public MCCodeEmitter {
34
  SparcMCCodeEmitter(const SparcMCCodeEmitter &) = delete;
35
  void operator=(const SparcMCCodeEmitter &) = delete;
36
  MCContext &Ctx;
37
38
public:
39
11.6k
  SparcMCCodeEmitter(MCContext &ctx): Ctx(ctx) {}
40
41
0
  ~SparcMCCodeEmitter() override {}
42
43
  void encodeInstruction(MCInst &MI, raw_ostream &OS,
44
                         SmallVectorImpl<MCFixup> &Fixups,
45
                         const MCSubtargetInfo &STI,
46
                         unsigned int &KsError) const override;
47
48
  // getBinaryCodeForInstr - TableGen'erated function for getting the
49
  // binary encoding for an instruction.
50
  uint64_t getBinaryCodeForInstr(const MCInst &MI,
51
                                 SmallVectorImpl<MCFixup> &Fixups,
52
                                 const MCSubtargetInfo &STI) const;
53
54
  /// getMachineOpValue - Return binary encoding of operand. If the machine
55
  /// operand requires relocation, record the relocation and return zero.
56
  unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
57
                             SmallVectorImpl<MCFixup> &Fixups,
58
                             const MCSubtargetInfo &STI) const;
59
60
  unsigned getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
61
                             SmallVectorImpl<MCFixup> &Fixups,
62
                             const MCSubtargetInfo &STI) const;
63
  unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
64
                             SmallVectorImpl<MCFixup> &Fixups,
65
                             const MCSubtargetInfo &STI) const;
66
  unsigned getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
67
                                      SmallVectorImpl<MCFixup> &Fixups,
68
                                      const MCSubtargetInfo &STI) const;
69
  unsigned getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
70
                                       SmallVectorImpl<MCFixup> &Fixups,
71
                                       const MCSubtargetInfo &STI) const;
72
73
};
74
} // end anonymous namespace
75
76
MCCodeEmitter *llvm_ks::createSparcMCCodeEmitter(const MCInstrInfo &MCII,
77
                                              const MCRegisterInfo &MRI,
78
11.6k
                                              MCContext &Ctx) {
79
11.6k
  return new SparcMCCodeEmitter(Ctx);
80
11.6k
}
81
82
void SparcMCCodeEmitter::encodeInstruction(MCInst &MI, raw_ostream &OS,
83
                                           SmallVectorImpl<MCFixup> &Fixups,
84
                                           const MCSubtargetInfo &STI,
85
                                           unsigned int &KsError) const
86
3.94k
{
87
3.94k
  unsigned Bits = getBinaryCodeForInstr(MI, Fixups, STI);
88
89
3.94k
  KsError = 0;
90
91
3.94k
  if (Ctx.getAsmInfo()->isLittleEndian()) {
92
    // Output the bits in little-endian byte order.
93
3.37k
    support::endian::Writer<support::little>(OS).write<uint32_t>(Bits);
94
3.37k
  } else {
95
    // Output the bits in big-endian byte order.
96
573
    support::endian::Writer<support::big>(OS).write<uint32_t>(Bits);
97
573
  }
98
3.94k
  unsigned tlsOpNo = 0;
99
3.94k
  switch (MI.getOpcode()) {
100
3.94k
  default: break;
101
3.94k
  case SP::TLS_CALL:   tlsOpNo = 1; break;
102
0
  case SP::TLS_ADDrr:
103
0
  case SP::TLS_ADDXrr:
104
0
  case SP::TLS_LDrr:
105
0
  case SP::TLS_LDXrr:  tlsOpNo = 3; break;
106
3.94k
  }
107
3.94k
  if (tlsOpNo != 0) {
108
0
    const MCOperand &MO = MI.getOperand(tlsOpNo);
109
0
    uint64_t op = getMachineOpValue(MI, MO, Fixups, STI);
110
0
    assert(op == 0 && "Unexpected operand value!");
111
0
    (void)op; // suppress warning.
112
0
  }
113
114
  // Keystone: update Inst.Address to point to the next instruction
115
3.94k
  MI.setAddress(MI.getAddress() + 4);
116
3.94k
}
117
118
119
unsigned SparcMCCodeEmitter::
120
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
121
                  SmallVectorImpl<MCFixup> &Fixups,
122
                  const MCSubtargetInfo &STI) const
123
6.12k
{
124
6.12k
  if (MO.isReg())
125
3.35k
    return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
126
127
2.77k
  if (MO.isImm())
128
2.77k
    return MO.getImm();
129
130
2.77k
  assert(MO.isExpr());
131
1
  const MCExpr *Expr = MO.getExpr();
132
1
  if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(Expr)) {
133
1
    MCFixupKind Kind = (MCFixupKind)SExpr->getFixupKind();
134
1
    Fixups.push_back(MCFixup::create(0, Expr, Kind));
135
1
    return 0;
136
1
  }
137
138
0
  int64_t Res;
139
0
  if (Expr->evaluateAsAbsolute(Res))
140
0
    return Res;
141
142
0
  llvm_unreachable("Unhandled expression!");
143
0
  return 0;
144
0
}
145
146
unsigned SparcMCCodeEmitter::
147
getCallTargetOpValue(const MCInst &MI, unsigned OpNo,
148
                     SmallVectorImpl<MCFixup> &Fixups,
149
24
                     const MCSubtargetInfo &STI) const {
150
24
  const MCOperand &MO = MI.getOperand(OpNo);
151
152
24
  if (MO.isImm())
153
1
      return MO.getImm() - MI.getAddress();
154
155
23
  if (MO.isReg())
156
0
    return getMachineOpValue(MI, MO, Fixups, STI);
157
158
23
  if (MI.getOpcode() == SP::TLS_CALL) {
159
    // No fixups for __tls_get_addr. Will emit for fixups for tls_symbol in
160
    // encodeInstruction.
161
0
#ifndef NDEBUG
162
    // Verify that the callee is actually __tls_get_addr.
163
0
    const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr());
164
0
    assert(SExpr && SExpr->getSubExpr()->getKind() == MCExpr::SymbolRef &&
165
0
           "Unexpected expression in TLS_CALL");
166
0
    const MCSymbolRefExpr *SymExpr = cast<MCSymbolRefExpr>(SExpr->getSubExpr());
167
0
    assert(SymExpr->getSymbol().getName() == "__tls_get_addr" &&
168
0
           "Unexpected function for TLS_CALL");
169
0
#endif
170
0
    return 0;
171
0
  }
172
173
23
  MCFixupKind fixupKind = (MCFixupKind)Sparc::fixup_sparc_call30;
174
175
23
  if (const SparcMCExpr *SExpr = dyn_cast<SparcMCExpr>(MO.getExpr())) {
176
0
    if (SExpr->getKind() == SparcMCExpr::VK_Sparc_WPLT30)
177
0
      fixupKind = (MCFixupKind)Sparc::fixup_sparc_wplt30;
178
0
  }
179
180
23
  Fixups.push_back(MCFixup::create(0, MO.getExpr(), fixupKind));
181
182
23
  return 0;
183
23
}
184
185
unsigned SparcMCCodeEmitter::
186
getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
187
                  SmallVectorImpl<MCFixup> &Fixups,
188
2.63k
                  const MCSubtargetInfo &STI) const {
189
2.63k
  const MCOperand &MO = MI.getOperand(OpNo);
190
191
2.63k
  if (MO.isImm())
192
168
      return (MO.getImm() - MI.getAddress()) / 4;
193
194
2.46k
  if (MO.isReg())
195
0
    return getMachineOpValue(MI, MO, Fixups, STI);
196
197
2.46k
  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
198
2.46k
                                   (MCFixupKind)Sparc::fixup_sparc_br22));
199
2.46k
  return 0;
200
2.46k
}
201
202
unsigned SparcMCCodeEmitter::
203
getBranchPredTargetOpValue(const MCInst &MI, unsigned OpNo,
204
                           SmallVectorImpl<MCFixup> &Fixups,
205
2
                           const MCSubtargetInfo &STI) const {
206
2
  const MCOperand &MO = MI.getOperand(OpNo);
207
2
  if (MO.isReg() || MO.isImm())
208
1
    return getMachineOpValue(MI, MO, Fixups, STI);
209
210
1
  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
211
1
                                   (MCFixupKind)Sparc::fixup_sparc_br19));
212
1
  return 0;
213
2
}
214
unsigned SparcMCCodeEmitter::
215
getBranchOnRegTargetOpValue(const MCInst &MI, unsigned OpNo,
216
                           SmallVectorImpl<MCFixup> &Fixups,
217
0
                           const MCSubtargetInfo &STI) const {
218
0
  const MCOperand &MO = MI.getOperand(OpNo);
219
0
  if (MO.isReg() || MO.isImm())
220
0
    return getMachineOpValue(MI, MO, Fixups, STI);
221
222
0
  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
223
0
                                   (MCFixupKind)Sparc::fixup_sparc_br16_2));
224
0
  Fixups.push_back(MCFixup::create(0, MO.getExpr(),
225
0
                                   (MCFixupKind)Sparc::fixup_sparc_br16_14));
226
227
0
  return 0;
228
0
}
229
230
231
232
#include "SparcGenMCCodeEmitter.inc"