Coverage Report

Created: 2025-05-26 06:32

/src/bloaty/third_party/capstone/arch/PowerPC/PPCDisassembler.c
Line
Count
Source (jump to first uncovered line)
1
//===------ PPCDisassembler.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_POWERPC
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 "PPCDisassembler.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
#define GET_REGINFO_ENUM
32
#include "PPCGenRegisterInfo.inc"
33
34
35
// FIXME: These can be generated by TableGen from the existing register
36
// encoding values!
37
38
static const unsigned CRRegs[] = {
39
  PPC_CR0, PPC_CR1, PPC_CR2, PPC_CR3,
40
  PPC_CR4, PPC_CR5, PPC_CR6, PPC_CR7
41
};
42
43
static const unsigned CRBITRegs[] = {
44
  PPC_CR0LT, PPC_CR0GT, PPC_CR0EQ, PPC_CR0UN,
45
  PPC_CR1LT, PPC_CR1GT, PPC_CR1EQ, PPC_CR1UN,
46
  PPC_CR2LT, PPC_CR2GT, PPC_CR2EQ, PPC_CR2UN,
47
  PPC_CR3LT, PPC_CR3GT, PPC_CR3EQ, PPC_CR3UN,
48
  PPC_CR4LT, PPC_CR4GT, PPC_CR4EQ, PPC_CR4UN,
49
  PPC_CR5LT, PPC_CR5GT, PPC_CR5EQ, PPC_CR5UN,
50
  PPC_CR6LT, PPC_CR6GT, PPC_CR6EQ, PPC_CR6UN,
51
  PPC_CR7LT, PPC_CR7GT, PPC_CR7EQ, PPC_CR7UN
52
};
53
54
static const unsigned FRegs[] = {
55
  PPC_F0, PPC_F1, PPC_F2, PPC_F3,
56
  PPC_F4, PPC_F5, PPC_F6, PPC_F7,
57
  PPC_F8, PPC_F9, PPC_F10, PPC_F11,
58
  PPC_F12, PPC_F13, PPC_F14, PPC_F15,
59
  PPC_F16, PPC_F17, PPC_F18, PPC_F19,
60
  PPC_F20, PPC_F21, PPC_F22, PPC_F23,
61
  PPC_F24, PPC_F25, PPC_F26, PPC_F27,
62
  PPC_F28, PPC_F29, PPC_F30, PPC_F31
63
};
64
65
static const unsigned VRegs[] = {
66
  PPC_V0, PPC_V1, PPC_V2, PPC_V3,
67
  PPC_V4, PPC_V5, PPC_V6, PPC_V7,
68
  PPC_V8, PPC_V9, PPC_V10, PPC_V11,
69
  PPC_V12, PPC_V13, PPC_V14, PPC_V15,
70
  PPC_V16, PPC_V17, PPC_V18, PPC_V19,
71
  PPC_V20, PPC_V21, PPC_V22, PPC_V23,
72
  PPC_V24, PPC_V25, PPC_V26, PPC_V27,
73
  PPC_V28, PPC_V29, PPC_V30, PPC_V31
74
};
75
76
static const unsigned VSRegs[] = {
77
  PPC_VSL0, PPC_VSL1, PPC_VSL2, PPC_VSL3,
78
  PPC_VSL4, PPC_VSL5, PPC_VSL6, PPC_VSL7,
79
  PPC_VSL8, PPC_VSL9, PPC_VSL10, PPC_VSL11,
80
  PPC_VSL12, PPC_VSL13, PPC_VSL14, PPC_VSL15,
81
  PPC_VSL16, PPC_VSL17, PPC_VSL18, PPC_VSL19,
82
  PPC_VSL20, PPC_VSL21, PPC_VSL22, PPC_VSL23,
83
  PPC_VSL24, PPC_VSL25, PPC_VSL26, PPC_VSL27,
84
  PPC_VSL28, PPC_VSL29, PPC_VSL30, PPC_VSL31,
85
86
  PPC_VSH0, PPC_VSH1, PPC_VSH2, PPC_VSH3,
87
  PPC_VSH4, PPC_VSH5, PPC_VSH6, PPC_VSH7,
88
  PPC_VSH8, PPC_VSH9, PPC_VSH10, PPC_VSH11,
89
  PPC_VSH12, PPC_VSH13, PPC_VSH14, PPC_VSH15,
90
  PPC_VSH16, PPC_VSH17, PPC_VSH18, PPC_VSH19,
91
  PPC_VSH20, PPC_VSH21, PPC_VSH22, PPC_VSH23,
92
  PPC_VSH24, PPC_VSH25, PPC_VSH26, PPC_VSH27,
93
  PPC_VSH28, PPC_VSH29, PPC_VSH30, PPC_VSH31
94
};
95
96
static const unsigned VSFRegs[] = {
97
  PPC_F0, PPC_F1, PPC_F2, PPC_F3,
98
  PPC_F4, PPC_F5, PPC_F6, PPC_F7,
99
  PPC_F8, PPC_F9, PPC_F10, PPC_F11,
100
  PPC_F12, PPC_F13, PPC_F14, PPC_F15,
101
  PPC_F16, PPC_F17, PPC_F18, PPC_F19,
102
  PPC_F20, PPC_F21, PPC_F22, PPC_F23,
103
  PPC_F24, PPC_F25, PPC_F26, PPC_F27,
104
  PPC_F28, PPC_F29, PPC_F30, PPC_F31,
105
106
  PPC_VF0, PPC_VF1, PPC_VF2, PPC_VF3,
107
  PPC_VF4, PPC_VF5, PPC_VF6, PPC_VF7,
108
  PPC_VF8, PPC_VF9, PPC_VF10, PPC_VF11,
109
  PPC_VF12, PPC_VF13, PPC_VF14, PPC_VF15,
110
  PPC_VF16, PPC_VF17, PPC_VF18, PPC_VF19,
111
  PPC_VF20, PPC_VF21, PPC_VF22, PPC_VF23,
112
  PPC_VF24, PPC_VF25, PPC_VF26, PPC_VF27,
113
  PPC_VF28, PPC_VF29, PPC_VF30, PPC_VF31
114
};
115
116
static const unsigned GPRegs[] = {
117
  PPC_R0, PPC_R1, PPC_R2, PPC_R3,
118
  PPC_R4, PPC_R5, PPC_R6, PPC_R7,
119
  PPC_R8, PPC_R9, PPC_R10, PPC_R11,
120
  PPC_R12, PPC_R13, PPC_R14, PPC_R15,
121
  PPC_R16, PPC_R17, PPC_R18, PPC_R19,
122
  PPC_R20, PPC_R21, PPC_R22, PPC_R23,
123
  PPC_R24, PPC_R25, PPC_R26, PPC_R27,
124
  PPC_R28, PPC_R29, PPC_R30, PPC_R31
125
};
126
127
static const unsigned GP0Regs[] = {
128
  PPC_ZERO, PPC_R1, PPC_R2, PPC_R3,
129
  PPC_R4, PPC_R5, PPC_R6, PPC_R7,
130
  PPC_R8, PPC_R9, PPC_R10, PPC_R11,
131
  PPC_R12, PPC_R13, PPC_R14, PPC_R15,
132
  PPC_R16, PPC_R17, PPC_R18, PPC_R19,
133
  PPC_R20, PPC_R21, PPC_R22, PPC_R23,
134
  PPC_R24, PPC_R25, PPC_R26, PPC_R27,
135
  PPC_R28, PPC_R29, PPC_R30, PPC_R31
136
};
137
138
static const unsigned G8Regs[] = {
139
  PPC_X0, PPC_X1, PPC_X2, PPC_X3,
140
  PPC_X4, PPC_X5, PPC_X6, PPC_X7,
141
  PPC_X8, PPC_X9, PPC_X10, PPC_X11,
142
  PPC_X12, PPC_X13, PPC_X14, PPC_X15,
143
  PPC_X16, PPC_X17, PPC_X18, PPC_X19,
144
  PPC_X20, PPC_X21, PPC_X22, PPC_X23,
145
  PPC_X24, PPC_X25, PPC_X26, PPC_X27,
146
  PPC_X28, PPC_X29, PPC_X30, PPC_X31
147
};
148
149
static const unsigned QFRegs[] = {
150
  PPC_QF0, PPC_QF1, PPC_QF2, PPC_QF3,
151
  PPC_QF4, PPC_QF5, PPC_QF6, PPC_QF7,
152
  PPC_QF8, PPC_QF9, PPC_QF10, PPC_QF11,
153
  PPC_QF12, PPC_QF13, PPC_QF14, PPC_QF15,
154
  PPC_QF16, PPC_QF17, PPC_QF18, PPC_QF19,
155
  PPC_QF20, PPC_QF21, PPC_QF22, PPC_QF23,
156
  PPC_QF24, PPC_QF25, PPC_QF26, PPC_QF27,
157
  PPC_QF28, PPC_QF29, PPC_QF30, PPC_QF31
158
};
159
160
static uint64_t getFeatureBits(int feature)
161
0
{
162
  // enable all features
163
0
  return (uint64_t)-1;
164
0
}
165
166
static DecodeStatus decodeRegisterClass(MCInst *Inst, uint64_t RegNo,
167
    const unsigned *Regs)
168
0
{
169
  // assert(RegNo < N && "Invalid register number");
170
0
  MCOperand_CreateReg0(Inst, Regs[RegNo]);
171
0
  return MCDisassembler_Success;
172
0
}
173
174
static DecodeStatus DecodeCRRCRegisterClass(MCInst *Inst, uint64_t RegNo,
175
    uint64_t Address,
176
    const void *Decoder)
177
0
{
178
0
  return decodeRegisterClass(Inst, RegNo, CRRegs);
179
0
}
180
181
static DecodeStatus DecodeCRBITRCRegisterClass(MCInst *Inst, uint64_t RegNo,
182
    uint64_t Address,
183
    const void *Decoder)
184
0
{
185
0
  return decodeRegisterClass(Inst, RegNo, CRBITRegs);
186
0
}
187
188
static DecodeStatus DecodeF4RCRegisterClass(MCInst *Inst, uint64_t RegNo,
189
    uint64_t Address,
190
    const void *Decoder)
191
0
{
192
0
  return decodeRegisterClass(Inst, RegNo, FRegs);
193
0
}
194
195
static DecodeStatus DecodeF8RCRegisterClass(MCInst *Inst, uint64_t RegNo,
196
    uint64_t Address,
197
    const void *Decoder)
198
0
{
199
0
  return decodeRegisterClass(Inst, RegNo, FRegs);
200
0
}
201
202
static DecodeStatus DecodeVRRCRegisterClass(MCInst *Inst, uint64_t RegNo,
203
    uint64_t Address,
204
    const void *Decoder)
205
0
{
206
0
  return decodeRegisterClass(Inst, RegNo, VRegs);
207
0
}
208
209
static DecodeStatus DecodeVSRCRegisterClass(MCInst *Inst, uint64_t RegNo,
210
    uint64_t Address,
211
    const void *Decoder)
212
0
{
213
0
  return decodeRegisterClass(Inst, RegNo, VSRegs);
214
0
}
215
216
static DecodeStatus DecodeVSFRCRegisterClass(MCInst *Inst, uint64_t RegNo,
217
    uint64_t Address,
218
    const void *Decoder)
219
0
{
220
0
  return decodeRegisterClass(Inst, RegNo, VSFRegs);
221
0
}
222
223
static DecodeStatus DecodeGPRCRegisterClass(MCInst *Inst, uint64_t RegNo,
224
    uint64_t Address,
225
    const void *Decoder)
226
0
{
227
0
  return decodeRegisterClass(Inst, RegNo, GPRegs);
228
0
}
229
230
static DecodeStatus DecodeGPRC_NOR0RegisterClass(MCInst *Inst, uint64_t RegNo,
231
    uint64_t Address,
232
    const void *Decoder)
233
0
{
234
0
  return decodeRegisterClass(Inst, RegNo, GP0Regs);
235
0
}
236
237
static DecodeStatus DecodeG8RCRegisterClass(MCInst *Inst, uint64_t RegNo,
238
    uint64_t Address,
239
    const void *Decoder)
240
0
{
241
0
  return decodeRegisterClass(Inst, RegNo, G8Regs);
242
0
}
243
244
0
#define DecodePointerLikeRegClass0 DecodeGPRCRegisterClass
245
0
#define DecodePointerLikeRegClass1 DecodeGPRC_NOR0RegisterClass
246
247
static DecodeStatus DecodeQFRCRegisterClass(MCInst *Inst, uint64_t RegNo,
248
    uint64_t Address,
249
    const void *Decoder)
250
0
{
251
0
  return decodeRegisterClass(Inst, RegNo, QFRegs);
252
0
}
253
254
0
#define DecodeQSRCRegisterClass DecodeQFRCRegisterClass
255
0
#define DecodeQBRCRegisterClass DecodeQFRCRegisterClass
256
257
static DecodeStatus decodeUImmOperand(MCInst *Inst, uint64_t Imm,
258
    int64_t Address, const void *Decoder, unsigned N)
259
0
{
260
  //assert(isUInt<N>(Imm) && "Invalid immediate");
261
0
  MCOperand_CreateImm0(Inst, Imm);
262
0
  return MCDisassembler_Success;
263
0
}
264
265
static DecodeStatus decodeSImmOperand(MCInst *Inst, uint64_t Imm,
266
    int64_t Address, const void *Decoder, unsigned N)
267
0
{
268
  // assert(isUInt<N>(Imm) && "Invalid immediate");
269
0
  MCOperand_CreateImm0(Inst, SignExtend64(Imm, N));
270
0
  return MCDisassembler_Success;
271
0
}
272
273
274
#define GET_INSTRINFO_ENUM
275
#include "PPCGenInstrInfo.inc"
276
277
static DecodeStatus decodeMemRIOperands(MCInst *Inst, uint64_t Imm,
278
    int64_t Address, const void *Decoder)
279
0
{
280
  // Decode the memri field (imm, reg), which has the low 16-bits as the
281
  // displacement and the next 5 bits as the register #.
282
283
0
  uint64_t Base = Imm >> 16;
284
0
  uint64_t Disp = Imm & 0xFFFF;
285
286
  // assert(Base < 32 && "Invalid base register");
287
0
  if (Base >= 32)
288
0
    return MCDisassembler_Fail;
289
290
0
  switch (MCInst_getOpcode(Inst)) {
291
0
    default: break;
292
0
    case PPC_LBZU:
293
0
    case PPC_LHAU:
294
0
    case PPC_LHZU:
295
0
    case PPC_LWZU:
296
0
    case PPC_LFSU:
297
0
    case PPC_LFDU:
298
         // Add the tied output operand.
299
0
         MCOperand_CreateReg0(Inst, GP0Regs[Base]);
300
0
         break;
301
0
    case PPC_STBU:
302
0
    case PPC_STHU:
303
0
    case PPC_STWU:
304
0
    case PPC_STFSU:
305
0
    case PPC_STFDU:
306
0
         MCInst_insert0(Inst, 0, MCOperand_CreateReg1(Inst, GP0Regs[Base]));
307
0
         break;
308
0
  }
309
310
0
  MCOperand_CreateImm0(Inst, SignExtend64(Disp, 16));
311
0
  MCOperand_CreateReg0(Inst, GP0Regs[Base]);
312
0
  return MCDisassembler_Success;
313
0
}
314
315
static DecodeStatus decodeMemRIXOperands(MCInst *Inst, uint64_t Imm,
316
    int64_t Address, const void *Decoder)
317
0
{
318
  // Decode the memrix field (imm, reg), which has the low 14-bits as the
319
  // displacement and the next 5 bits as the register #.
320
321
0
  uint64_t Base = Imm >> 14;
322
0
  uint64_t Disp = Imm & 0x3FFF;
323
324
  // assert(Base < 32 && "Invalid base register");
325
326
0
  if (MCInst_getOpcode(Inst) == PPC_LDU)
327
    // Add the tied output operand.
328
0
    MCOperand_CreateReg0(Inst, GP0Regs[Base]);
329
0
  else if (MCInst_getOpcode(Inst) == PPC_STDU)
330
0
    MCInst_insert0(Inst, 0, MCOperand_CreateReg1(Inst, GP0Regs[Base]));
331
332
0
  MCOperand_CreateImm0(Inst, SignExtend64(Disp << 2, 16));
333
0
  MCOperand_CreateReg0(Inst, GP0Regs[Base]);
334
0
  return MCDisassembler_Success;
335
0
}
336
337
static DecodeStatus decodeCRBitMOperand(MCInst *Inst, uint64_t Imm,
338
    int64_t Address, const void *Decoder)
339
0
{
340
  // The cr bit encoding is 0x80 >> cr_reg_num.
341
342
0
  unsigned Zeros = CountTrailingZeros_64(Imm);
343
  // assert(Zeros < 8 && "Invalid CR bit value");
344
0
  if (Zeros >=8)
345
0
    return MCDisassembler_Fail;
346
347
0
  MCOperand_CreateReg0(Inst, CRRegs[7 - Zeros]);
348
0
  return MCDisassembler_Success;
349
0
}
350
351
#include "PPCGenDisassemblerTables.inc"
352
353
static DecodeStatus getInstruction(MCInst *MI,
354
    const uint8_t *code, size_t code_len,
355
    uint16_t *Size,
356
    uint64_t Address, MCRegisterInfo *MRI)
357
0
{
358
0
  uint32_t insn;
359
0
  DecodeStatus result;
360
  // Get the four bytes of the instruction.
361
0
  if (code_len < 4) {
362
    // not enough data
363
0
    *Size = 0;
364
0
    return MCDisassembler_Fail;
365
0
  }
366
367
  // The instruction is big-endian encoded.
368
0
  if (MODE_IS_BIG_ENDIAN(MI->csh->mode))
369
0
    insn = ((uint32_t) code[0] << 24) | (code[1] << 16) |
370
0
      (code[2] <<  8) | (code[3] <<  0);
371
0
  else
372
0
    insn = ((uint32_t) code[3] << 24) | (code[2] << 16) |
373
0
      (code[1] <<  8) | (code[0] <<  0);
374
375
0
  if (MI->flat_insn->detail) {
376
0
    memset(MI->flat_insn->detail, 0, offsetof(cs_detail, ppc)+sizeof(cs_ppc));
377
0
  }
378
379
0
  if (MI->csh->mode & CS_MODE_QPX) {
380
0
    result = decodeInstruction_4(DecoderTableQPX32, MI, insn, Address, 4);
381
0
    if (result != MCDisassembler_Fail) {
382
0
      *Size = 4;
383
0
      return result;
384
0
    }
385
386
0
    MCInst_clear(MI);
387
0
  }
388
389
0
  result = decodeInstruction_4(DecoderTable32, MI, insn, Address, 4);
390
0
  if (result != MCDisassembler_Fail) {
391
0
    *Size = 4;
392
0
    return result;
393
0
  }
394
395
  // report error
396
0
  MCInst_clear(MI);
397
0
  *Size = 0;
398
0
  return MCDisassembler_Fail;
399
0
}
400
401
bool PPC_getInstruction(csh ud, const uint8_t *code, size_t code_len,
402
    MCInst *instr, uint16_t *size, uint64_t address, void *info)
403
0
{
404
0
  DecodeStatus status = getInstruction(instr,
405
0
      code, code_len,
406
0
      size,
407
0
      address, (MCRegisterInfo *)info);
408
409
0
  return status == MCDisassembler_Success;
410
0
}
411
412
#define GET_REGINFO_MC_DESC
413
#include "PPCGenRegisterInfo.inc"
414
void PPC_init(MCRegisterInfo *MRI)
415
0
{
416
  /*
417
     InitMCRegisterInfo(PPCRegDesc, 310, RA, PC,
418
     PPCMCRegisterClasses, 23,
419
     PPCRegUnitRoots,
420
     138,
421
     PPCRegDiffLists,
422
     PPCLaneMaskLists,
423
     PPCRegStrings,
424
     PPCRegClassStrings,
425
     PPCSubRegIdxLists,
426
     8,
427
     PPCSubRegIdxRanges,
428
     PPCRegEncodingTable);
429
   */
430
431
432
0
  MCRegisterInfo_InitMCRegisterInfo(MRI, PPCRegDesc, 310,
433
0
      0, 0,
434
0
      PPCMCRegisterClasses, 23,
435
0
      0, 0,
436
0
      PPCRegDiffLists,
437
0
      0,
438
0
      PPCSubRegIdxLists, 8,
439
0
      0);
440
0
}
441
442
#endif