Coverage Report

Created: 2026-11-12 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonev5/arch/Sparc/SparcDisassembler.c
Line
Count
Source
1
//===------ SparcDisassembler.cpp - Disassembler for PowerPC ------*- C++ -*-===//
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
/* Capstone Disassembly Engine */
11
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */
12
13
#ifdef CAPSTONE_HAS_SPARC
14
15
#include <stdio.h>  // DEBUG
16
#include <stdlib.h>
17
#include <string.h>
18
19
#include "../../cs_priv.h"
20
#include "../../utils.h"
21
22
#include "SparcDisassembler.h"
23
24
#include "../../MCInst.h"
25
#include "../../MCInstrDesc.h"
26
#include "../../MCFixedLenDisassembler.h"
27
#include "../../MCRegisterInfo.h"
28
#include "../../MCDisassembler.h"
29
#include "../../MathExtras.h"
30
31
32
#define GET_REGINFO_MC_DESC
33
#define GET_REGINFO_ENUM
34
#include "SparcGenRegisterInfo.inc"
35
36
#define GET_INSTRINFO_ENUM
37
#include "SparcGenInstrInfo.inc"
38
static const unsigned IntRegDecoderTable[] = {
39
  SP_G0,  SP_G1,  SP_G2,  SP_G3,
40
  SP_G4,  SP_G5,  SP_G6,  SP_G7,
41
  SP_O0,  SP_O1,  SP_O2,  SP_O3,
42
  SP_O4,  SP_O5,  SP_O6,  SP_O7,
43
  SP_L0,  SP_L1,  SP_L2,  SP_L3,
44
  SP_L4,  SP_L5,  SP_L6,  SP_L7,
45
  SP_I0,  SP_I1,  SP_I2,  SP_I3,
46
  SP_I4,  SP_I5,  SP_I6,  SP_I7
47
};
48
49
static const unsigned FPRegDecoderTable[] = {
50
  SP_F0,   SP_F1,   SP_F2,   SP_F3,
51
  SP_F4,   SP_F5,   SP_F6,   SP_F7,
52
  SP_F8,   SP_F9,   SP_F10,  SP_F11,
53
  SP_F12,  SP_F13,  SP_F14,  SP_F15,
54
  SP_F16,  SP_F17,  SP_F18,  SP_F19,
55
  SP_F20,  SP_F21,  SP_F22,  SP_F23,
56
  SP_F24,  SP_F25,  SP_F26,  SP_F27,
57
  SP_F28,  SP_F29,  SP_F30,  SP_F31
58
};
59
60
static const unsigned DFPRegDecoderTable[] = {
61
  SP_D0,   SP_D16,  SP_D1,   SP_D17,
62
  SP_D2,   SP_D18,  SP_D3,   SP_D19,
63
  SP_D4,   SP_D20,  SP_D5,   SP_D21,
64
  SP_D6,   SP_D22,  SP_D7,   SP_D23,
65
  SP_D8,   SP_D24,  SP_D9,   SP_D25,
66
  SP_D10,  SP_D26,  SP_D11,  SP_D27,
67
  SP_D12,  SP_D28,  SP_D13,  SP_D29,
68
  SP_D14,  SP_D30,  SP_D15,  SP_D31
69
};
70
71
static const unsigned QFPRegDecoderTable[] = {
72
  SP_Q0,  SP_Q8,   ~0U,  ~0U,
73
  SP_Q1,  SP_Q9,   ~0U,  ~0U,
74
  SP_Q2,  SP_Q10,  ~0U,  ~0U,
75
  SP_Q3,  SP_Q11,  ~0U,  ~0U,
76
  SP_Q4,  SP_Q12,  ~0U,  ~0U,
77
  SP_Q5,  SP_Q13,  ~0U,  ~0U,
78
  SP_Q6,  SP_Q14,  ~0U,  ~0U,
79
  SP_Q7,  SP_Q15,  ~0U,  ~0U
80
};
81
82
static const unsigned FCCRegDecoderTable[] = {
83
  SP_FCC0, SP_FCC1, SP_FCC2, SP_FCC3
84
};
85
86
static uint64_t getFeatureBits(int mode)
87
88.1k
{
88
  // support everything
89
88.1k
  return (uint64_t)-1;
90
88.1k
}
91
92
static DecodeStatus DecodeIntRegsRegisterClass(MCInst *Inst, unsigned RegNo,
93
    uint64_t Address, const void *Decoder)
94
48.0k
{
95
48.0k
  unsigned Reg;
96
97
48.0k
  if (RegNo > 31)
98
0
    return MCDisassembler_Fail;
99
100
48.0k
  Reg = IntRegDecoderTable[RegNo];
101
48.0k
  MCOperand_CreateReg0(Inst, Reg);
102
103
48.0k
  return MCDisassembler_Success;
104
48.0k
}
105
106
static DecodeStatus DecodeI64RegsRegisterClass(MCInst *Inst, unsigned RegNo,
107
    uint64_t Address, const void *Decoder)
108
9.55k
{
109
9.55k
  unsigned Reg;
110
111
9.55k
  if (RegNo > 31)
112
0
    return MCDisassembler_Fail;
113
114
9.55k
  Reg = IntRegDecoderTable[RegNo];
115
9.55k
  MCOperand_CreateReg0(Inst, Reg);
116
117
9.55k
  return MCDisassembler_Success;
118
9.55k
}
119
120
static DecodeStatus DecodeFPRegsRegisterClass(MCInst *Inst, unsigned RegNo,
121
    uint64_t Address, const void *Decoder)
122
8.92k
{
123
8.92k
  unsigned Reg;
124
125
8.92k
  if (RegNo > 31)
126
0
    return MCDisassembler_Fail;
127
128
8.92k
  Reg = FPRegDecoderTable[RegNo];
129
8.92k
  MCOperand_CreateReg0(Inst, Reg);
130
131
8.92k
  return MCDisassembler_Success;
132
8.92k
}
133
134
static DecodeStatus DecodeDFPRegsRegisterClass(MCInst *Inst, unsigned RegNo,
135
    uint64_t Address, const void *Decoder)
136
8.78k
{
137
8.78k
  unsigned Reg;
138
139
8.78k
  if (RegNo > 31)
140
0
    return MCDisassembler_Fail;
141
142
8.78k
  Reg = DFPRegDecoderTable[RegNo];
143
8.78k
  MCOperand_CreateReg0(Inst, Reg);
144
145
8.78k
  return MCDisassembler_Success;
146
8.78k
}
147
148
static DecodeStatus DecodeQFPRegsRegisterClass(MCInst *Inst, unsigned RegNo,
149
    uint64_t Address, const void *Decoder)
150
7.63k
{
151
7.63k
  unsigned Reg;
152
153
7.63k
  if (RegNo > 31)
154
0
    return MCDisassembler_Fail;
155
156
7.63k
  Reg = QFPRegDecoderTable[RegNo];
157
7.63k
  if (Reg == ~0U)
158
22
    return MCDisassembler_Fail;
159
160
7.61k
  MCOperand_CreateReg0(Inst, Reg);
161
162
7.61k
  return MCDisassembler_Success;
163
7.63k
}
164
165
static DecodeStatus DecodeFCCRegsRegisterClass(MCInst *Inst, unsigned RegNo,
166
    uint64_t Address, const void *Decoder)
167
12.1k
{
168
12.1k
  if (RegNo > 3)
169
3
    return MCDisassembler_Fail;
170
171
12.1k
  MCOperand_CreateReg0(Inst, FCCRegDecoderTable[RegNo]);
172
173
12.1k
  return MCDisassembler_Success;
174
12.1k
}
175
176
177
static DecodeStatus DecodeLoadInt(MCInst *Inst, unsigned insn, uint64_t Address,
178
    const void *Decoder);
179
static DecodeStatus DecodeLoadFP(MCInst *Inst, unsigned insn, uint64_t Address,
180
    const void *Decoder);
181
static DecodeStatus DecodeLoadDFP(MCInst *Inst, unsigned insn, uint64_t Address,
182
    const void *Decoder);
183
static DecodeStatus DecodeLoadQFP(MCInst *Inst, unsigned insn, uint64_t Address,
184
    const void *Decoder);
185
static DecodeStatus DecodeStoreInt(MCInst *Inst, unsigned insn,
186
    uint64_t Address, const void *Decoder);
187
static DecodeStatus DecodeStoreFP(MCInst *Inst, unsigned insn,
188
    uint64_t Address, const void *Decoder);
189
static DecodeStatus DecodeStoreDFP(MCInst *Inst, unsigned insn,
190
    uint64_t Address, const void *Decoder);
191
static DecodeStatus DecodeStoreQFP(MCInst *Inst, unsigned insn,
192
    uint64_t Address, const void *Decoder);
193
static DecodeStatus DecodeCall(MCInst *Inst, unsigned insn,
194
    uint64_t Address, const void *Decoder);
195
static DecodeStatus DecodeSIMM13(MCInst *Inst, unsigned insn,
196
    uint64_t Address, const void *Decoder);
197
static DecodeStatus DecodeJMPL(MCInst *Inst, unsigned insn, uint64_t Address,
198
    const void *Decoder);
199
static DecodeStatus DecodeReturn(MCInst *MI, unsigned insn, uint64_t Address,
200
    const void *Decoder);
201
static DecodeStatus DecodeSWAP(MCInst *Inst, unsigned insn, uint64_t Address,
202
    const void *Decoder);
203
204
205
#define GET_SUBTARGETINFO_ENUM
206
#include "SparcGenSubtargetInfo.inc"
207
#include "SparcGenDisassemblerTables.inc"
208
209
static DecodeStatus decodeMemFallback(MCInst *MI, uint32_t insn, uint64_t Address);
210
211
/// readInstruction - read four bytes and return 32 bit word.
212
static DecodeStatus readInstruction32(const uint8_t *code, size_t len, uint32_t *Insn)
213
88.7k
{
214
88.7k
  if (len < 4)
215
    // not enough data
216
636
    return MCDisassembler_Fail;
217
218
  // Encoded as a big-endian 32-bit word in the stream.
219
88.1k
  *Insn = (code[3] <<  0) |
220
88.1k
    (code[2] <<  8) |
221
88.1k
    (code[1] << 16) |
222
88.1k
    ((uint32_t) code[0] << 24);
223
224
88.1k
  return MCDisassembler_Success;
225
88.7k
}
226
227
bool Sparc_getInstruction(csh ud, const uint8_t *code, size_t code_len, MCInst *MI,
228
    uint16_t *size, uint64_t address, void *info)
229
88.7k
{
230
88.7k
  uint32_t Insn;
231
88.7k
  DecodeStatus Result;
232
  
233
88.7k
  Result = readInstruction32(code, code_len, &Insn);
234
88.7k
  if (Result == MCDisassembler_Fail)
235
636
    return false;
236
237
88.1k
  if (MI->flat_insn->detail) {
238
88.1k
    memset(MI->flat_insn->detail, 0, offsetof(cs_detail, sparc)+sizeof(cs_sparc));
239
88.1k
  }
240
241
88.1k
  Result = decodeInstruction_4(DecoderTableSparc32, MI, Insn, address,
242
88.1k
      (MCRegisterInfo *)info, 0);
243
88.1k
  if (Result == MCDisassembler_Fail)
244
868
    Result = decodeMemFallback(MI, Insn, address);
245
88.1k
  if (Result != MCDisassembler_Fail) {
246
87.8k
    *size = 4;
247
87.8k
    return true;
248
87.8k
  }
249
250
241
  return false;
251
88.1k
}
252
253
typedef DecodeStatus (*DecodeFunc)(MCInst *MI, unsigned insn, uint64_t Address,
254
    const void *Decoder);
255
256
static DecodeStatus DecodeMem(MCInst *MI, unsigned insn, uint64_t Address,
257
    const void *Decoder,
258
    bool isLoad, DecodeFunc DecodeRD)
259
5.01k
{
260
5.01k
  DecodeStatus status;
261
5.01k
  unsigned rd = fieldFromInstruction_4(insn, 25, 5);
262
5.01k
  unsigned rs1 = fieldFromInstruction_4(insn, 14, 5);
263
5.01k
  bool isImm = fieldFromInstruction_4(insn, 13, 1) != 0;
264
5.01k
  unsigned rs2 = 0;
265
5.01k
  unsigned simm13 = 0;
266
267
5.01k
  if (isImm)
268
2.96k
    simm13 = SignExtend32(fieldFromInstruction_4(insn, 0, 13), 13);
269
2.04k
  else
270
2.04k
    rs2 = fieldFromInstruction_4(insn, 0, 5);
271
272
5.01k
  if (isLoad) {
273
2.80k
    status = DecodeRD(MI, rd, Address, Decoder);
274
2.80k
    if (status != MCDisassembler_Success)
275
2
      return status;
276
2.80k
  }
277
278
  // Decode rs1.
279
5.00k
  status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder);
280
5.00k
  if (status != MCDisassembler_Success)
281
0
    return status;
282
283
  // Decode imm|rs2.
284
5.00k
  if (isImm)
285
2.96k
    MCOperand_CreateImm0(MI, simm13);
286
2.04k
  else {
287
2.04k
    status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder);
288
2.04k
    if (status != MCDisassembler_Success)
289
0
      return status;
290
2.04k
  }
291
292
5.00k
  if (!isLoad) {
293
2.20k
    status = DecodeRD(MI, rd, Address, Decoder);
294
2.20k
    if (status != MCDisassembler_Success)
295
2
      return status;
296
2.20k
  }
297
298
5.00k
  return MCDisassembler_Success;
299
5.00k
}
300
301
static DecodeStatus DecodeLoadInt(MCInst *Inst, unsigned insn, uint64_t Address,
302
    const void *Decoder)
303
753
{
304
753
  return DecodeMem(Inst, insn, Address, Decoder, true,
305
753
      DecodeIntRegsRegisterClass);
306
753
}
307
308
// An odd register pair is undefined; round it down like LLVM does.
309
static DecodeStatus DecodeIntPairRegisterClass(MCInst *Inst, unsigned RegNo,
310
    uint64_t Address, const void *Decoder)
311
522
{
312
522
  return DecodeIntRegsRegisterClass(Inst, RegNo & ~1U, Address, Decoder);
313
522
}
314
315
// The generated table predates LLVM's integer LDD, STD and LDSTUB.
316
static DecodeStatus decodeMemFallback(MCInst *MI, uint32_t insn, uint64_t Address)
317
868
{
318
868
  bool isImm = fieldFromInstruction_4(insn, 13, 1);
319
868
  if (fieldFromInstruction_4(insn, 30, 2) != 3)
320
181
    return MCDisassembler_Fail;
321
687
  if (!isImm && fieldFromInstruction_4(insn, 5, 8))
322
33
    return MCDisassembler_Fail;
323
324
654
  switch (fieldFromInstruction_4(insn, 19, 6)) {
325
261
  case 0x03:
326
261
    MCInst_setOpcode(MI, isImm ? SP_LDDri : SP_LDDrr);
327
261
    return DecodeMem(MI, insn, Address, NULL, true, DecodeIntPairRegisterClass);
328
261
  case 0x07:
329
261
    MCInst_setOpcode(MI, isImm ? SP_STDri : SP_STDrr);
330
261
    return DecodeMem(MI, insn, Address, NULL, false, DecodeIntPairRegisterClass);
331
105
  case 0x0d:
332
105
    MCInst_setOpcode(MI, isImm ? SP_LDSTUBri : SP_LDSTUBrr);
333
105
    return DecodeLoadInt(MI, insn, Address, NULL);
334
27
  default:
335
27
    return MCDisassembler_Fail;
336
654
  }
337
654
}
338
339
static DecodeStatus DecodeLoadFP(MCInst *Inst, unsigned insn, uint64_t Address,
340
    const void *Decoder)
341
645
{
342
645
  return DecodeMem(Inst, insn, Address, Decoder, true,
343
645
      DecodeFPRegsRegisterClass);
344
645
}
345
346
static DecodeStatus DecodeLoadDFP(MCInst *Inst, unsigned insn, uint64_t Address,
347
    const void *Decoder)
348
748
{
349
748
  return DecodeMem(Inst, insn, Address, Decoder, true,
350
748
      DecodeDFPRegsRegisterClass);
351
748
}
352
353
static DecodeStatus DecodeLoadQFP(MCInst *Inst, unsigned insn, uint64_t Address,
354
    const void *Decoder)
355
400
{
356
400
  return DecodeMem(Inst, insn, Address, Decoder, true,
357
400
      DecodeQFPRegsRegisterClass);
358
400
}
359
360
static DecodeStatus DecodeStoreInt(MCInst *Inst, unsigned insn,
361
    uint64_t Address, const void *Decoder)
362
419
{
363
419
  return DecodeMem(Inst, insn, Address, Decoder, false,
364
419
      DecodeIntRegsRegisterClass);
365
419
}
366
367
static DecodeStatus DecodeStoreFP(MCInst *Inst, unsigned insn, uint64_t Address,
368
    const void *Decoder)
369
713
{
370
713
  return DecodeMem(Inst, insn, Address, Decoder, false,
371
713
      DecodeFPRegsRegisterClass);
372
713
}
373
374
static DecodeStatus DecodeStoreDFP(MCInst *Inst, unsigned insn,
375
    uint64_t Address, const void *Decoder)
376
505
{
377
505
  return DecodeMem(Inst, insn, Address, Decoder, false,
378
505
      DecodeDFPRegsRegisterClass);
379
505
}
380
381
static DecodeStatus DecodeStoreQFP(MCInst *Inst, unsigned insn,
382
    uint64_t Address, const void *Decoder)
383
305
{
384
305
  return DecodeMem(Inst, insn, Address, Decoder, false,
385
305
      DecodeQFPRegsRegisterClass);
386
305
}
387
388
static DecodeStatus DecodeCall(MCInst *MI, unsigned insn,
389
    uint64_t Address, const void *Decoder)
390
7.13k
{
391
7.13k
  unsigned tgt = fieldFromInstruction_4(insn, 0, 30);
392
7.13k
  tgt <<= 2;
393
394
7.13k
  MCOperand_CreateImm0(MI, tgt);
395
396
7.13k
  return MCDisassembler_Success;
397
7.13k
}
398
399
static DecodeStatus DecodeSIMM13(MCInst *MI, unsigned insn,
400
    uint64_t Address, const void *Decoder)
401
2.43k
{
402
2.43k
  unsigned tgt = SignExtend32(fieldFromInstruction_4(insn, 0, 13), 13);
403
404
2.43k
  MCOperand_CreateImm0(MI, tgt);
405
406
2.43k
  return MCDisassembler_Success;
407
2.43k
}
408
409
static DecodeStatus DecodeJMPL(MCInst *MI, unsigned insn, uint64_t Address,
410
    const void *Decoder)
411
1.65k
{
412
1.65k
  DecodeStatus status;
413
1.65k
  unsigned rd = fieldFromInstruction_4(insn, 25, 5);
414
1.65k
  unsigned rs1 = fieldFromInstruction_4(insn, 14, 5);
415
1.65k
  unsigned isImm = fieldFromInstruction_4(insn, 13, 1);
416
1.65k
  unsigned rs2 = 0;
417
1.65k
  unsigned simm13 = 0;
418
419
1.65k
  if (isImm)
420
1.29k
    simm13 = SignExtend32(fieldFromInstruction_4(insn, 0, 13), 13);
421
360
  else
422
360
    rs2 = fieldFromInstruction_4(insn, 0, 5);
423
424
  // Decode RD.
425
1.65k
  status = DecodeIntRegsRegisterClass(MI, rd, Address, Decoder);
426
1.65k
  if (status != MCDisassembler_Success)
427
0
    return status;
428
429
  // Decode RS1.
430
1.65k
  status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder);
431
1.65k
  if (status != MCDisassembler_Success)
432
0
    return status;
433
434
  // Decode RS1 | SIMM13.
435
1.65k
  if (isImm)
436
1.29k
    MCOperand_CreateImm0(MI, simm13);
437
360
  else {
438
360
    status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder);
439
360
    if (status != MCDisassembler_Success)
440
0
      return status;
441
360
  }
442
443
1.65k
  return MCDisassembler_Success;
444
1.65k
}
445
446
static DecodeStatus DecodeReturn(MCInst *MI, unsigned insn, uint64_t Address,
447
    const void *Decoder)
448
580
{
449
580
  DecodeStatus status;
450
580
  unsigned rs1 = fieldFromInstruction_4(insn, 14, 5);
451
580
  unsigned isImm = fieldFromInstruction_4(insn, 13, 1);
452
580
  unsigned rs2 = 0;
453
580
  unsigned simm13 = 0;
454
580
  if (isImm)
455
375
    simm13 = SignExtend32(fieldFromInstruction_4(insn, 0, 13), 13);
456
205
  else
457
205
    rs2 = fieldFromInstruction_4(insn, 0, 5);
458
459
  // Decode RS1.
460
580
  status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder);
461
580
  if (status != MCDisassembler_Success)
462
0
    return status;
463
464
  // Decode RS2 | SIMM13.
465
580
  if (isImm)
466
375
    MCOperand_CreateImm0(MI, simm13);
467
205
  else {
468
205
    status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder);
469
205
    if (status != MCDisassembler_Success)
470
0
      return status;
471
205
  }
472
473
580
  return MCDisassembler_Success;
474
580
}
475
476
static DecodeStatus DecodeSWAP(MCInst *MI, unsigned insn, uint64_t Address,
477
    const void *Decoder)
478
462
{
479
462
  DecodeStatus status;
480
462
  unsigned rd = fieldFromInstruction_4(insn, 25, 5);
481
462
  unsigned rs1 = fieldFromInstruction_4(insn, 14, 5);
482
462
  unsigned isImm = fieldFromInstruction_4(insn, 13, 1);
483
462
  unsigned rs2 = 0;
484
462
  unsigned simm13 = 0;
485
486
462
  if (isImm)
487
268
    simm13 = SignExtend32(fieldFromInstruction_4(insn, 0, 13), 13);
488
194
  else
489
194
    rs2 = fieldFromInstruction_4(insn, 0, 5);
490
491
  // Decode RD.
492
462
  status = DecodeIntRegsRegisterClass(MI, rd, Address, Decoder);
493
462
  if (status != MCDisassembler_Success)
494
0
    return status;
495
496
  // Decode RS1.
497
462
  status = DecodeIntRegsRegisterClass(MI, rs1, Address, Decoder);
498
462
  if (status != MCDisassembler_Success)
499
0
    return status;
500
501
  // Decode RS1 | SIMM13.
502
462
  if (isImm)
503
268
    MCOperand_CreateImm0(MI, simm13);
504
194
  else {
505
194
    status = DecodeIntRegsRegisterClass(MI, rs2, Address, Decoder);
506
194
    if (status != MCDisassembler_Success)
507
0
      return status;
508
194
  }
509
510
462
  return MCDisassembler_Success;
511
462
}
512
513
void Sparc_init(MCRegisterInfo *MRI)
514
2.60k
{
515
  /*
516
  InitMCRegisterInfo(SparcRegDesc, 119, RA, PC,
517
      SparcMCRegisterClasses, 8,
518
      SparcRegUnitRoots,
519
      86,
520
      SparcRegDiffLists,
521
      SparcRegStrings,
522
      SparcSubRegIdxLists,
523
      7,
524
      SparcSubRegIdxRanges,
525
      SparcRegEncodingTable);
526
  */
527
528
2.60k
  MCRegisterInfo_InitMCRegisterInfo(MRI, SparcRegDesc, 119,
529
2.60k
      0, 0,
530
2.60k
      SparcMCRegisterClasses, 8,
531
2.60k
      0, 0,
532
2.60k
      SparcRegDiffLists,
533
2.60k
      0,
534
2.60k
      SparcSubRegIdxLists, 7,
535
2.60k
      0);
536
2.60k
}
537
538
#endif