Coverage Report

Created: 2025-07-01 07:03

/src/capstonenext/arch/Sparc/SparcDisassembler.c
Line
Count
Source (jump to first uncovered line)
1
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
2
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
3
/*    Rot127 <unisono@quyllur.org> 2022-2023 */
4
/* Automatically translated source file from LLVM. */
5
6
/* LLVM-commit: <commit> */
7
/* LLVM-tag: <tag> */
8
9
/* Only small edits allowed. */
10
/* For multiple similar edits, please create a Patch for the translator. */
11
12
/* Capstone's C++ file translator: */
13
/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */
14
15
//===- SparcDisassembler.cpp - Disassembler for Sparc -----------*- C++ -*-===//
16
//
17
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
18
// See https://llvm.org/LICENSE.txt for license information.
19
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
20
//
21
//===----------------------------------------------------------------------===//
22
//
23
// This file is part of the Sparc Disassembler.
24
//
25
//===----------------------------------------------------------------------===//
26
27
#include <stdio.h>
28
#include <string.h>
29
#include <stdlib.h>
30
#include <capstone/platform.h>
31
32
#include "../../MCDisassembler.h"
33
#include "../../MCFixedLenDisassembler.h"
34
#include "SparcDisassemblerExtension.h"
35
#include "SparcLinkage.h"
36
#include "SparcMapping.h"
37
#include "SparcMCTargetDesc.h"
38
#define CONCAT(a, b) CONCAT_(a, b)
39
#define CONCAT_(a, b) a##_##b
40
41
#define DEBUG_TYPE "sparc-disassembler"
42
43
static const unsigned IntRegDecoderTable[] = {
44
  Sparc_G0, Sparc_G1, Sparc_G2, Sparc_G3, Sparc_G4, Sparc_G5, Sparc_G6, Sparc_G7,
45
  Sparc_O0, Sparc_O1, Sparc_O2, Sparc_O3, Sparc_O4, Sparc_O5, Sparc_O6, Sparc_O7,
46
  Sparc_L0, Sparc_L1, Sparc_L2, Sparc_L3, Sparc_L4, Sparc_L5, Sparc_L6, Sparc_L7,
47
  Sparc_I0, Sparc_I1, Sparc_I2, Sparc_I3, Sparc_I4, Sparc_I5, Sparc_I6, Sparc_I7
48
};
49
50
static const unsigned FPRegDecoderTable[] = {
51
  Sparc_F0, Sparc_F1, Sparc_F2, Sparc_F3, Sparc_F4, Sparc_F5, Sparc_F6, Sparc_F7,
52
  Sparc_F8, Sparc_F9, Sparc_F10, Sparc_F11, Sparc_F12, Sparc_F13, Sparc_F14, Sparc_F15,
53
  Sparc_F16, Sparc_F17, Sparc_F18, Sparc_F19, Sparc_F20, Sparc_F21, Sparc_F22, Sparc_F23,
54
  Sparc_F24, Sparc_F25, Sparc_F26, Sparc_F27, Sparc_F28, Sparc_F29, Sparc_F30, Sparc_F31
55
};
56
57
static const unsigned DFPRegDecoderTable[] = {
58
  Sparc_D0, Sparc_D16, Sparc_D1,  Sparc_D17, Sparc_D2,  Sparc_D18, Sparc_D3,  Sparc_D19,
59
  Sparc_D4, Sparc_D20, Sparc_D5,  Sparc_D21, Sparc_D6,  Sparc_D22, Sparc_D7,  Sparc_D23,
60
  Sparc_D8, Sparc_D24, Sparc_D9,  Sparc_D25, Sparc_D10, Sparc_D26, Sparc_D11, Sparc_D27,
61
  Sparc_D12, Sparc_D28, Sparc_D13, Sparc_D29, Sparc_D14, Sparc_D30, Sparc_D15, Sparc_D31
62
};
63
64
static const unsigned QFPRegDecoderTable[] = {
65
  Sparc_Q0, Sparc_Q8,  ~0U, ~0U, Sparc_Q1, Sparc_Q9,  ~0U, ~0U,
66
  Sparc_Q2, Sparc_Q10, ~0U, ~0U, Sparc_Q3, Sparc_Q11, ~0U, ~0U,
67
  Sparc_Q4, Sparc_Q12, ~0U, ~0U, Sparc_Q5, Sparc_Q13, ~0U, ~0U,
68
  Sparc_Q6, Sparc_Q14, ~0U, ~0U, Sparc_Q7, Sparc_Q15, ~0U, ~0U
69
};
70
71
static const unsigned FCCRegDecoderTable[] = { Sparc_FCC0, Sparc_FCC1, Sparc_FCC2,
72
                 Sparc_FCC3 };
73
74
static const unsigned ASRRegDecoderTable[] = {
75
  Sparc_Y,    Sparc_ASR1,  Sparc_ASR2,  Sparc_ASR3, Sparc_ASR4,  Sparc_ASR5,  Sparc_ASR6,
76
  Sparc_ASR7,  Sparc_ASR8,  Sparc_ASR9,  Sparc_ASR10, Sparc_ASR11, Sparc_ASR12, Sparc_ASR13,
77
  Sparc_ASR14, Sparc_ASR15, Sparc_ASR16, Sparc_ASR17, Sparc_ASR18, Sparc_ASR19, Sparc_ASR20,
78
  Sparc_ASR21, Sparc_ASR22, Sparc_ASR23, Sparc_ASR24, Sparc_ASR25, Sparc_ASR26, Sparc_ASR27,
79
  Sparc_ASR28, Sparc_ASR29, Sparc_ASR30, Sparc_ASR31
80
};
81
82
static const unsigned PRRegDecoderTable[] = {
83
  Sparc_TPC,      Sparc_TNPC,    Sparc_TSTATE,  Sparc_TT,      Sparc_TICK,
84
  Sparc_TBA,      Sparc_PSTATE,    Sparc_TL,  Sparc_PIL,       Sparc_CWP,
85
  Sparc_CANSAVE, Sparc_CANRESTORE, Sparc_CLEANWIN, Sparc_OTHERWIN, Sparc_WSTATE
86
};
87
88
static const uint16_t IntPairDecoderTable[] = {
89
  Sparc_G0_G1, Sparc_G2_G3, Sparc_G4_G5, Sparc_G6_G7, Sparc_O0_O1, Sparc_O2_O3,
90
  Sparc_O4_O5, Sparc_O6_O7, Sparc_L0_L1, Sparc_L2_L3, Sparc_L4_L5, Sparc_L6_L7,
91
  Sparc_I0_I1, Sparc_I2_I3, Sparc_I4_I5, Sparc_I6_I7,
92
};
93
94
static const unsigned CPRegDecoderTable[] = {
95
  Sparc_C0, Sparc_C1, Sparc_C2, Sparc_C3, Sparc_C4, Sparc_C5, Sparc_C6, Sparc_C7,
96
  Sparc_C8, Sparc_C9, Sparc_C10, Sparc_C11, Sparc_C12, Sparc_C13, Sparc_C14, Sparc_C15,
97
  Sparc_C16, Sparc_C17, Sparc_C18, Sparc_C19, Sparc_C20, Sparc_C21, Sparc_C22, Sparc_C23,
98
  Sparc_C24, Sparc_C25, Sparc_C26, Sparc_C27, Sparc_C28, Sparc_C29, Sparc_C30, Sparc_C31
99
};
100
101
static const uint16_t CPPairDecoderTable[] = {
102
  Sparc_C0_C1,   Sparc_C2_C3, Sparc_C4_C5,   Sparc_C6_C7, Sparc_C8_C9,   Sparc_C10_C11,
103
  Sparc_C12_C13, Sparc_C14_C15, Sparc_C16_C17, Sparc_C18_C19, Sparc_C20_C21, Sparc_C22_C23,
104
  Sparc_C24_C25, Sparc_C26_C27, Sparc_C28_C29, Sparc_C30_C31
105
};
106
107
static DecodeStatus DecodeDisp19(MCInst *Inst, uint32_t ImmVal,
108
                 uint64_t Address,
109
                 const void *Decoder)
110
4.16k
{
111
4.16k
  int64_t BranchTarget = Address + (SignExtend64(ImmVal, 19) * 4);
112
4.16k
  MCOperand_CreateImm0(Inst, BranchTarget);
113
4.16k
  return MCDisassembler_Success;
114
4.16k
}
115
116
static DecodeStatus DecodeDisp16(MCInst *Inst, uint32_t ImmVal,
117
                 uint64_t Address,
118
                 const void *Decoder)
119
975
{
120
975
  int64_t BranchTarget = Address + (SignExtend64(ImmVal, 16) * 4);
121
975
  MCOperand_CreateImm0(Inst, BranchTarget);
122
975
  return MCDisassembler_Success;
123
975
}
124
125
static DecodeStatus DecodeDisp22(MCInst *Inst, uint32_t ImmVal,
126
                 uint64_t Address,
127
                 const void *Decoder)
128
1.71k
{
129
1.71k
  int64_t BranchTarget = Address + (SignExtend64(ImmVal, 22) * 4);
130
1.71k
  MCOperand_CreateImm0(Inst, BranchTarget);
131
1.71k
  return MCDisassembler_Success;
132
1.71k
}
133
134
static DecodeStatus DecodeIntRegsRegisterClass(MCInst *Inst, unsigned RegNo,
135
                 uint64_t Address,
136
                 const void *Decoder)
137
48.1k
{
138
48.1k
  if (RegNo > 31)
139
0
    return MCDisassembler_Fail;
140
48.1k
  unsigned Reg = IntRegDecoderTable[RegNo];
141
48.1k
  MCOperand_CreateReg0(Inst, (Reg));
142
48.1k
  return MCDisassembler_Success;
143
48.1k
}
144
145
static DecodeStatus DecodeI64RegsRegisterClass(MCInst *Inst, unsigned RegNo,
146
                 uint64_t Address,
147
                 const void *Decoder)
148
3.85k
{
149
3.85k
  return DecodeIntRegsRegisterClass(Inst, RegNo, Address, Decoder);
150
3.85k
}
151
152
// This is used for the type "ptr_rc", which is either IntRegs or I64Regs
153
// depending on SparcRegisterInfo::getPointerRegClass.
154
static DecodeStatus DecodePointerLikeRegClass0(MCInst *Inst, unsigned RegNo,
155
                 uint64_t Address,
156
                 const void *Decoder)
157
7.87k
{
158
7.87k
  return DecodeIntRegsRegisterClass(Inst, RegNo, Address, Decoder);
159
7.87k
}
160
161
static DecodeStatus DecodeFPRegsRegisterClass(MCInst *Inst, unsigned RegNo,
162
                uint64_t Address,
163
                const void *Decoder)
164
5.02k
{
165
5.02k
  if (RegNo > 31)
166
0
    return MCDisassembler_Fail;
167
5.02k
  unsigned Reg = FPRegDecoderTable[RegNo];
168
5.02k
  MCOperand_CreateReg0(Inst, (Reg));
169
5.02k
  return MCDisassembler_Success;
170
5.02k
}
171
172
static DecodeStatus DecodeDFPRegsRegisterClass(MCInst *Inst, unsigned RegNo,
173
                 uint64_t Address,
174
                 const void *Decoder)
175
4.45k
{
176
4.45k
  if (RegNo > 31)
177
0
    return MCDisassembler_Fail;
178
4.45k
  unsigned Reg = DFPRegDecoderTable[RegNo];
179
4.45k
  MCOperand_CreateReg0(Inst, (Reg));
180
4.45k
  return MCDisassembler_Success;
181
4.45k
}
182
183
static DecodeStatus DecodeQFPRegsRegisterClass(MCInst *Inst, unsigned RegNo,
184
                 uint64_t Address,
185
                 const void *Decoder)
186
3.39k
{
187
3.39k
  if (RegNo > 31)
188
0
    return MCDisassembler_Fail;
189
190
3.39k
  unsigned Reg = QFPRegDecoderTable[RegNo];
191
3.39k
  if (Reg == ~0U)
192
40
    return MCDisassembler_Fail;
193
3.35k
  MCOperand_CreateReg0(Inst, (Reg));
194
3.35k
  return MCDisassembler_Success;
195
3.39k
}
196
197
static DecodeStatus DecodeCoprocRegsRegisterClass(MCInst *Inst, unsigned RegNo,
198
              uint64_t Address,
199
              const void *Decoder)
200
27
{
201
27
  if (RegNo > 31)
202
0
    return MCDisassembler_Fail;
203
27
  unsigned Reg = CPRegDecoderTable[RegNo];
204
27
  MCOperand_CreateReg0(Inst, (Reg));
205
27
  return MCDisassembler_Success;
206
27
}
207
208
static DecodeStatus DecodeFCCRegsRegisterClass(MCInst *Inst, unsigned RegNo,
209
                 uint64_t Address,
210
                 const void *Decoder)
211
9.41k
{
212
9.41k
  if (RegNo > 3)
213
5
    return MCDisassembler_Fail;
214
9.40k
  MCOperand_CreateReg0(Inst, (FCCRegDecoderTable[RegNo]));
215
9.40k
  return MCDisassembler_Success;
216
9.41k
}
217
218
static DecodeStatus DecodeASRRegsRegisterClass(MCInst *Inst, unsigned RegNo,
219
                 uint64_t Address,
220
                 const void *Decoder)
221
51
{
222
51
  if (RegNo > 31)
223
0
    return MCDisassembler_Fail;
224
51
  MCOperand_CreateReg0(Inst, (ASRRegDecoderTable[RegNo]));
225
51
  return MCDisassembler_Success;
226
51
}
227
228
static DecodeStatus DecodePRRegsRegisterClass(MCInst *Inst, unsigned RegNo,
229
                uint64_t Address,
230
                const void *Decoder)
231
18
{
232
18
  if (RegNo >= ARR_SIZE(PRRegDecoderTable))
233
3
    return MCDisassembler_Fail;
234
15
  MCOperand_CreateReg0(Inst, (PRRegDecoderTable[RegNo]));
235
15
  return MCDisassembler_Success;
236
18
}
237
238
static DecodeStatus DecodeIntPairRegisterClass(MCInst *Inst, unsigned RegNo,
239
                 uint64_t Address,
240
                 const void *Decoder)
241
166
{
242
166
  DecodeStatus S = MCDisassembler_Success;
243
244
166
  if (RegNo > 31)
245
0
    return MCDisassembler_Fail;
246
247
166
  if ((RegNo & 1))
248
80
    S = MCDisassembler_SoftFail;
249
250
166
  unsigned RegisterPair = IntPairDecoderTable[RegNo / 2];
251
166
  MCOperand_CreateReg0(Inst, (RegisterPair));
252
166
  return S;
253
166
}
254
255
static DecodeStatus DecodeCoprocPairRegisterClass(MCInst *Inst, unsigned RegNo,
256
              uint64_t Address,
257
              const void *Decoder)
258
25
{
259
25
  if (RegNo > 31)
260
0
    return MCDisassembler_Fail;
261
262
25
  unsigned RegisterPair = CPPairDecoderTable[RegNo / 2];
263
25
  MCOperand_CreateReg0(Inst, (RegisterPair));
264
25
  return MCDisassembler_Success;
265
25
}
266
267
static DecodeStatus DecodeCall(MCInst *Inst, unsigned insn, uint64_t Address,
268
             const void *Decoder);
269
static DecodeStatus DecodeSIMM13(MCInst *Inst, unsigned insn, uint64_t Address,
270
         const void *Decoder);
271
272
#include "SparcGenDisassemblerTables.inc"
273
274
static DecodeStatus getInstruction(MCInst *Instr, uint64_t *Size, const uint8_t *Bytes,
275
          size_t BytesLen, uint64_t Address, SStream *CStream)
276
27.8k
{
277
27.8k
  if (BytesLen < 4) {
278
369
    return MCDisassembler_Fail;
279
369
  }
280
27.5k
  uint32_t Insn = readBytes32(Instr, Bytes);
281
282
27.5k
  DecodeStatus Result = MCDisassembler_Fail;
283
  // Calling the auto-generated decoder function.
284
27.5k
  if (Sparc_getFeatureBits(Instr->csh->mode, Sparc_FeatureV9)) {
285
24.8k
    Result = decodeInstruction_4(DecoderTableSparcV932, Instr, Insn,
286
24.8k
               Address, NULL);
287
24.8k
  } else {
288
2.61k
    Result = decodeInstruction_4(DecoderTableSparcV832, Instr, Insn,
289
2.61k
               Address, NULL);
290
2.61k
  }
291
27.5k
  if (Result != MCDisassembler_Fail) {
292
273
    *Size = 4;
293
273
    return Result;
294
273
  }
295
296
27.2k
  Result = decodeInstruction_4(DecoderTableSparc32, Instr, Insn, Address,
297
27.2k
             NULL);
298
299
27.2k
  if (Result != MCDisassembler_Fail) {
300
27.0k
    *Size = 4;
301
27.0k
    return Result;
302
27.0k
  }
303
304
183
  return MCDisassembler_Fail;
305
27.2k
}
306
307
static bool tryAddingSymbolicOperand(int64_t Value, bool isBranch,
308
             uint64_t Address, uint64_t Offset,
309
             uint64_t Width, MCInst *MI,
310
             const void *Decoder)
311
4.73k
{
312
  // Capstone doesn't support symbols.
313
4.73k
  return false;
314
4.73k
}
315
316
static DecodeStatus DecodeCall(MCInst *MI, unsigned insn, uint64_t Address,
317
             const void *Decoder)
318
4.73k
{
319
4.73k
  unsigned Offset = fieldFromInstruction_4(insn, 0, 30);
320
4.73k
  int64_t CallTarget = Address + (SignExtend64(Offset, 30) * 4);
321
4.73k
  if (!tryAddingSymbolicOperand(CallTarget, false, Address, 0, 30, MI,
322
4.73k
              Decoder))
323
4.73k
    MCOperand_CreateImm0(MI, CallTarget);
324
4.73k
  return MCDisassembler_Success;
325
4.73k
}
326
327
static DecodeStatus DecodeSIMM13(MCInst *MI, unsigned insn, uint64_t Address,
328
         const void *Decoder)
329
2.37k
{
330
2.37k
  CS_ASSERT(isUIntN(13, insn));
331
2.37k
  MCOperand_CreateImm0(MI, (SignExtend64((insn), 13)));
332
2.37k
  return MCDisassembler_Success;
333
2.37k
}
334
335
DecodeStatus Sparc_LLVM_getInstruction(csh handle, const uint8_t *Bytes,
336
             size_t ByteLen, MCInst *MI, uint16_t *Size,
337
27.8k
             uint64_t Address, void *Info) {
338
27.8k
  uint64_t s = 0;
339
27.8k
  DecodeStatus status = getInstruction(MI, &s, Bytes, ByteLen, Address, NULL);
340
27.8k
  *Size = (uint16_t) s;
341
27.8k
  return status;
342
27.8k
}