Coverage Report

Created: 2023-12-08 06:05

/src/capstonenext/arch/PowerPC/PPCMapping.c
Line
Count
Source (jump to first uncovered line)
1
/* Capstone Disassembly Engine */
2
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */
3
4
#include "capstone/ppc.h"
5
#ifdef CAPSTONE_HAS_POWERPC
6
7
#include <stdio.h> // debug
8
#include <string.h>
9
10
#include "../../cs_simple_types.h"
11
#include "../../Mapping.h"
12
#include "../../MCDisassembler.h"
13
#include "../../utils.h"
14
15
#include "PPCLinkage.h"
16
#include "PPCMapping.h"
17
#include "PPCMCTargetDesc.h"
18
19
#define GET_REGINFO_MC_DESC
20
#include "PPCGenRegisterInfo.inc"
21
22
void PPC_init_mri(MCRegisterInfo *MRI)
23
1.92k
{
24
1.92k
  MCRegisterInfo_InitMCRegisterInfo(MRI, PPCRegDesc, PPC_REG_ENDING, 0, 0,
25
1.92k
            PPCMCRegisterClasses,
26
1.92k
            ARR_SIZE(PPCMCRegisterClasses), 0, 0,
27
1.92k
            PPCRegDiffLists, 0, PPCSubRegIdxLists,
28
1.92k
            ARR_SIZE(PPCSubRegIdxLists),
29
1.92k
            PPCRegEncodingTable);
30
1.92k
}
31
32
const char *PPC_reg_name(csh handle, unsigned int reg)
33
36.6k
{
34
36.6k
  if (reg > PPC_REG_INVALID && reg < PPC_REG_ENDING)
35
36.6k
    return PPC_LLVM_getRegisterName(reg);
36
0
  return NULL;
37
36.6k
}
38
39
// given internal insn id, return public instruction info
40
void PPC_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
41
50.9k
{
42
  // We do this after Instruction disassembly.
43
50.9k
}
44
45
#ifndef CAPSTONE_DIET
46
47
static const char *const insn_name_maps[] = {
48
#include "PPCGenCSMappingInsnName.inc"
49
};
50
51
static const name_map insn_alias_mnem_map[] = {
52
#include "PPCGenCSAliasMnemMap.inc"
53
  { PPC_INS_ALIAS_SLWI, "slwi" },
54
  { PPC_INS_ALIAS_SRWI, "srwi" },
55
  { PPC_INS_ALIAS_SLDI, "sldi" },
56
  { PPC_INS_ALIAS_END, NULL },
57
};
58
59
#endif
60
61
const char *PPC_insn_name(csh handle, unsigned int id)
62
50.9k
{
63
50.9k
#ifndef CAPSTONE_DIET
64
50.9k
  if (id < PPC_INS_ALIAS_END && id > PPC_INS_ALIAS_BEGIN) {
65
0
    if (id - PPC_INS_ALIAS_BEGIN >= ARR_SIZE(insn_alias_mnem_map))
66
0
      return NULL;
67
68
0
    return insn_alias_mnem_map[id - PPC_INS_ALIAS_BEGIN - 1].name;
69
0
  }
70
50.9k
  if (id >= PPC_INS_ENDING)
71
0
    return NULL;
72
73
50.9k
  return insn_name_maps[id];
74
#else
75
  return NULL;
76
#endif
77
50.9k
}
78
79
#ifndef CAPSTONE_DIET
80
static const name_map group_name_maps[] = {
81
  // generic groups
82
  { PPC_GRP_INVALID, NULL },
83
  { PPC_GRP_JUMP, "jump" },
84
  { PPC_GRP_CALL, "call" },
85
  { PPC_GRP_INT, "int" },
86
  { PPC_GRP_PRIVILEGE, "privilege" },
87
  { PPC_GRP_BRANCH_RELATIVE, "branch_relative" },
88
89
// architecture-specific groups
90
#include "PPCGenCSFeatureName.inc"
91
};
92
#endif
93
94
const char *PPC_group_name(csh handle, unsigned int id)
95
24.1k
{
96
24.1k
#ifndef CAPSTONE_DIET
97
24.1k
  return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
98
#else
99
  return NULL;
100
#endif
101
24.1k
}
102
103
const insn_map ppc_insns[] = {
104
#include "PPCGenCSMappingInsn.inc"
105
};
106
107
void PPC_check_updates_cr0(MCInst *MI)
108
52.2k
{
109
52.2k
#ifndef CAPSTONE_DIET
110
52.2k
  if (!detail_is_set(MI))
111
0
    return;
112
52.2k
  cs_detail *detail = get_detail(MI);
113
65.2k
  for (int i = 0; i < detail->regs_write_count; ++i) {
114
15.7k
    if (detail->regs_write[i] == 0)
115
0
      return;
116
15.7k
    if (detail->regs_write[i] == PPC_REG_CR0) {
117
2.77k
      PPC_get_detail(MI)->update_cr0 = true;
118
2.77k
      return;
119
2.77k
    }
120
15.7k
  }
121
52.2k
#endif // CAPSTONE_DIET
122
52.2k
}
123
124
/// Parses and adds the branch predicate information and the BH field.
125
static void PPC_add_branch_predicates(MCInst *MI, const uint8_t *Bytes,
126
              size_t BytesLen)
127
52.2k
{
128
52.2k
  if (!detail_is_set(MI))
129
0
    return;
130
52.2k
#ifndef CAPSTONE_DIET
131
52.2k
  assert(MI && Bytes);
132
52.2k
  if (BytesLen < 4)
133
711
    return;
134
135
51.5k
  ppc_insn_form form = ppc_insns[MI->Opcode].suppl_info.ppc.form;
136
51.5k
  bool b_form = ppc_is_b_form(form);
137
51.5k
  if (!(b_form || form == PPC_INSN_FORM_XLFORM_2))
138
43.8k
    return;
139
140
7.65k
  uint32_t Inst = readBytes32(MI, Bytes);
141
142
7.65k
  uint8_t bi = 0;
143
7.65k
  if (b_form)
144
7.52k
    bi = (Inst & PPC_INSN_FORM_B_BI_MASK) >> 16;
145
133
  else
146
133
    bi = (Inst & PPC_INSN_FORM_XL_BI_MASK) >> 16;
147
148
7.65k
  uint8_t bo = 0;
149
7.65k
  if (b_form)
150
7.52k
    bo = (Inst & PPC_INSN_FORM_B_BO_MASK) >> 21;
151
133
  else
152
133
    bo = (Inst & PPC_INSN_FORM_XL_BO_MASK) >> 21;
153
154
7.65k
  PPC_get_detail(MI)->bc.bo = bo;
155
7.65k
  PPC_get_detail(MI)->bc.bi = bi;
156
7.65k
  PPC_get_detail(MI)->bc.crX_bit = bi % 4;
157
7.65k
  PPC_get_detail(MI)->bc.crX = PPC_REG_CR0 + (bi / 4);
158
7.65k
  PPC_get_detail(MI)->bc.hint = PPC_get_hint(bo);
159
7.65k
  PPC_get_detail(MI)->bc.pred_cr = PPC_get_branch_pred(bi, bo, true);
160
7.65k
  PPC_get_detail(MI)->bc.pred_ctr = PPC_get_branch_pred(bi, bo, false);
161
162
7.65k
  if (ppc_is_b_form(form))
163
7.52k
    return;
164
165
133
  uint8_t bh = (Inst & PPC_INSN_FORM_XL_BH_MASK) >> 11;
166
133
  uint16_t xo = (Inst & PPC_INSN_FORM_XL_XO_MASK) >> 1;
167
  // Pre-defined values for XO fields (PowerISA v3.1B)
168
133
  uint16_t bcctr_xo_field = 528;
169
133
  uint16_t bctar_xo_field = 560;
170
133
  bool cond = (xo == bcctr_xo_field || xo == bctar_xo_field);
171
133
  switch (bh) {
172
0
  default:
173
0
    assert(0 && "Invalid BH value.");
174
56
  case 0b00:
175
56
    PPC_get_detail(MI)->bc.bh = cond ? PPC_BH_NO_SUBROUTINE_RET :
176
56
               PPC_BH_SUBROUTINE_RET;
177
56
    break;
178
56
  case 0b01:
179
56
    PPC_get_detail(MI)->bc.bh = cond ? PPC_BH_RESERVED :
180
56
               PPC_BH_NO_SUBROUTINE_RET;
181
56
    break;
182
11
  case 0b10:
183
11
    PPC_get_detail(MI)->bc.bh = PPC_BH_RESERVED;
184
11
    break;
185
10
  case 0b11:
186
10
    PPC_get_detail(MI)->bc.bh = PPC_BH_NOT_PREDICTABLE;
187
10
    break;
188
133
  }
189
133
#endif // CAPSTONE_DIET
190
133
}
191
192
void PPC_set_instr_map_data(MCInst *MI, const uint8_t *Bytes, size_t BytesLen)
193
52.2k
{
194
52.2k
  map_cs_id(MI, ppc_insns, ARR_SIZE(ppc_insns));
195
52.2k
  map_implicit_reads(MI, ppc_insns);
196
52.2k
  map_implicit_writes(MI, ppc_insns);
197
52.2k
  map_groups(MI, ppc_insns);
198
52.2k
  PPC_add_branch_predicates(MI, Bytes, BytesLen);
199
52.2k
  PPC_check_updates_cr0(MI);
200
52.2k
}
201
202
/// Inialize PPCs detail.
203
void PPC_init_cs_detail(MCInst *MI)
204
52.2k
{
205
52.2k
  if (!detail_is_set(MI))
206
0
    return;
207
52.2k
  memset(get_detail(MI), 0, offsetof(cs_detail, ppc) + sizeof(cs_ppc));
208
52.2k
  PPC_get_detail(MI)->bc.bi = UINT8_MAX;
209
52.2k
  PPC_get_detail(MI)->bc.bo = UINT8_MAX;
210
52.2k
  PPC_get_detail(MI)->bc.crX = PPC_REG_INVALID;
211
52.2k
  PPC_get_detail(MI)->bc.crX_bit = PPC_BI_INVALID;
212
52.2k
  PPC_get_detail(MI)->bc.pred_cr = PPC_PRED_INVALID;
213
52.2k
  PPC_get_detail(MI)->bc.pred_ctr = PPC_PRED_INVALID;
214
52.2k
  PPC_get_detail(MI)->bc.hint = PPC_BR_NOT_GIVEN;
215
52.2k
  PPC_get_detail(MI)->bc.bh = PPC_BH_INVALID;
216
52.2k
}
217
218
void PPC_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info)
219
50.9k
{
220
50.9k
  MI->MRI = (MCRegisterInfo *)info;
221
50.9k
  MI->fillDetailOps = detail_is_set(MI);
222
50.9k
  MI->flat_insn->usesAliasDetails = map_use_alias_details(MI);
223
50.9k
  PPC_LLVM_printInst(MI, MI->address, "", O);
224
50.9k
  map_set_alias_id(MI, O, insn_alias_mnem_map,
225
50.9k
       ARR_SIZE(insn_alias_mnem_map));
226
50.9k
}
227
228
bool PPC_getInstruction(csh handle, const uint8_t *bytes, size_t bytes_len,
229
      MCInst *instr, uint16_t *size, uint64_t address,
230
      void *info)
231
52.2k
{
232
52.2k
  PPC_init_cs_detail(instr);
233
52.2k
  DecodeStatus result = PPC_LLVM_getInstruction(
234
52.2k
    handle, bytes, bytes_len, instr, size, address, info);
235
52.2k
  PPC_set_instr_map_data(instr, bytes, bytes_len);
236
52.2k
  return result != MCDisassembler_Fail;
237
52.2k
}
238
239
bool PPC_getFeatureBits(unsigned int mode, unsigned int feature)
240
222k
{
241
222k
  if ((feature == PPC_FeatureQPX) && (mode & CS_MODE_QPX) == 0) {
242
26.2k
    return false;
243
196k
  } else if ((feature == PPC_FeatureSPE) && (mode & CS_MODE_SPE) == 0) {
244
26.2k
    return false;
245
170k
  } else if ((feature == PPC_FeatureBookE) &&
246
170k
       (mode & CS_MODE_BOOKE) == 0) {
247
120
    return false;
248
170k
  } else if ((feature == PPC_FeaturePS) && (mode & CS_MODE_PS) == 0) {
249
15.8k
    return false;
250
15.8k
  }
251
252
  // No AIX support for now.
253
154k
  if (feature == PPC_FeatureModernAIXAs || feature == PPC_AIXOS)
254
51.2k
    return false;
255
  // TODO Make it optional
256
102k
  if (feature == PPC_FeatureMSYNC)
257
72
    return false;
258
259
  // By default support everything
260
102k
  return true;
261
102k
}
262
263
static const map_insn_ops insn_operands[] = {
264
#include "PPCGenCSMappingInsnOp.inc"
265
};
266
267
/// @brief Handles memory operands.
268
/// @param MI The MCInst.
269
/// @param OpNum The operand index.
270
static void handle_memory_operand(MCInst *MI, unsigned OpNum)
271
18.1k
{
272
18.1k
  cs_op_type op_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM;
273
274
  // If this is called from printOperand() we do not know if a
275
  // register is a base or an offset reg (imm is always disponent).
276
  // So we assume the base register is always added before the offset register
277
  // and set the flag appropriately.
278
18.1k
  bool is_off_reg =
279
18.1k
    ((op_type == CS_OP_REG) &&
280
18.1k
     PPC_get_detail_op(MI, 0)->mem.base != PPC_REG_INVALID);
281
18.1k
  PPC_set_detail_op_mem(MI, OpNum, MCInst_getOpVal(MI, OpNum),
282
18.1k
            is_off_reg);
283
18.1k
}
284
285
static void add_cs_detail_general(MCInst *MI, ppc_op_group op_group,
286
          unsigned OpNum)
287
162k
{
288
162k
  if (!detail_is_set(MI))
289
0
    return;
290
291
162k
  switch (op_group) {
292
0
  default:
293
0
    printf("General operand group %d not handled!\n", op_group);
294
0
    return;
295
100k
  case PPC_OP_GROUP_Operand: {
296
100k
    cs_op_type op_type = map_get_op_type(MI, OpNum);
297
298
    // Check for memory operands emitted via printOperand()
299
100k
    if (doing_mem(MI) && !(op_type & CS_OP_MEM)) {
300
      // Close previous memory operand
301
63
      set_mem_access(MI, false);
302
100k
    } else if (doing_mem(MI) || (op_type & CS_OP_MEM)) {
303
      // The memory operands use printOperand() to
304
      // emit their register and immediates.
305
18.1k
      if (!doing_mem(MI))
306
766
        set_mem_access(MI, true);
307
18.1k
      handle_memory_operand(MI, OpNum);
308
18.1k
      return;
309
18.1k
    }
310
311
82.2k
    assert((op_type & CS_OP_MEM) ==
312
82.2k
           0); // doing_mem should have been true.
313
314
82.2k
    if (op_type == CS_OP_REG)
315
81.6k
      PPC_set_detail_op_reg(MI, OpNum,
316
81.6k
                MCInst_getOpVal(MI, OpNum));
317
656
    else if (op_type == CS_OP_IMM)
318
656
      PPC_set_detail_op_imm(MI, OpNum,
319
656
                MCInst_getOpVal(MI, OpNum));
320
0
    else
321
0
      assert(0 && "Operand type not handled.");
322
82.2k
    break;
323
82.2k
  }
324
82.2k
  case PPC_OP_GROUP_ImmZeroOperand:
325
1.26k
  case PPC_OP_GROUP_U1ImmOperand:
326
1.78k
  case PPC_OP_GROUP_U2ImmOperand:
327
2.86k
  case PPC_OP_GROUP_U3ImmOperand:
328
3.45k
  case PPC_OP_GROUP_U4ImmOperand:
329
14.4k
  case PPC_OP_GROUP_U5ImmOperand:
330
15.5k
  case PPC_OP_GROUP_U6ImmOperand:
331
15.6k
  case PPC_OP_GROUP_U7ImmOperand:
332
15.7k
  case PPC_OP_GROUP_U8ImmOperand:
333
15.7k
  case PPC_OP_GROUP_U10ImmOperand:
334
16.2k
  case PPC_OP_GROUP_U12ImmOperand:
335
16.2k
    PPC_set_detail_op_imm(MI, OpNum,
336
16.2k
              (uint32_t)MCInst_getOpVal(MI, OpNum));
337
16.2k
    break;
338
4.99k
  case PPC_OP_GROUP_U16ImmOperand:
339
4.99k
    if (!MCOperand_isImm(MCInst_getOperand(MI, OpNum)))
340
      // Handled in printOperand()
341
0
      return;
342
4.99k
    PPC_set_detail_op_imm(MI, OpNum,
343
4.99k
              (uint32_t)MCInst_getOpVal(MI, OpNum));
344
4.99k
    break;
345
18
  case PPC_OP_GROUP_S5ImmOperand: {
346
18
    int Imm = MCOperand_getImm(MCInst_getOperand(MI, (OpNum)));
347
18
    Imm = SignExtend32((Imm), 5);
348
18
    PPC_set_detail_op_imm(MI, OpNum, Imm);
349
18
    break;
350
4.99k
  }
351
885
  case PPC_OP_GROUP_S12ImmOperand: {
352
885
    int64_t Imm = SignExtend64(
353
885
      MCOperand_getImm(MCInst_getOperand(MI, (OpNum))), 12);
354
885
    if (doing_mem(MI)) {
355
885
      PPC_set_detail_op_mem(MI, OpNum, Imm, true);
356
885
      break;
357
885
    }
358
0
    PPC_set_detail_op_imm(MI, OpNum, Imm);
359
0
    break;
360
885
  }
361
17.2k
  case PPC_OP_GROUP_S16ImmOperand: {
362
17.2k
    if (!MCOperand_isImm(MCInst_getOperand(MI, OpNum)))
363
      // Handled in printOperand()
364
0
      return;
365
17.2k
    int16_t Imm = MCOperand_getImm(MCInst_getOperand(MI, (OpNum)));
366
17.2k
    if (doing_mem(MI)) {
367
12.0k
      PPC_set_detail_op_mem(MI, OpNum, Imm, true);
368
12.0k
      break;
369
12.0k
    }
370
5.21k
    PPC_set_detail_op_imm(MI, OpNum, Imm);
371
5.21k
    break;
372
17.2k
  }
373
246
  case PPC_OP_GROUP_S34ImmOperand: {
374
246
    if (!MCOperand_isImm(MCInst_getOperand(MI, OpNum)))
375
      // Handled in printOperand()
376
0
      return;
377
246
    int64_t Imm = MCOperand_getImm(MCInst_getOperand(MI, (OpNum)));
378
246
    if (doing_mem(MI)) {
379
215
      PPC_set_detail_op_mem(MI, OpNum, Imm, true);
380
215
      break;
381
215
    }
382
31
    PPC_set_detail_op_imm(MI, OpNum, Imm);
383
31
    break;
384
246
  }
385
0
  case PPC_OP_GROUP_ATBitsAsHint: {
386
0
    PPC_get_detail(MI)->bc.hint =
387
0
      (ppc_br_hint)MCInst_getOpVal(MI, OpNum);
388
0
    break;
389
246
  }
390
2.51k
  case PPC_OP_GROUP_AbsBranchOperand: {
391
2.51k
    if (!MCOperand_isImm(MCInst_getOperand(MI, OpNum)))
392
      // Handled in printOperand()
393
0
      return;
394
2.51k
    unsigned Val = MCInst_getOpVal(MI, OpNum) << 2;
395
2.51k
    int32_t Imm = SignExtend32(Val, 32);
396
2.51k
    PPC_get_detail_op(MI, 0)->type = PPC_OP_IMM;
397
2.51k
    PPC_get_detail_op(MI, 0)->imm = Imm;
398
2.51k
    PPC_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
399
2.51k
    PPC_inc_op_count(MI);
400
2.51k
    break;
401
2.51k
  }
402
0
  case PPC_OP_GROUP_TLSCall:
403
    // Handled in PPCInstPrinter and printOperand.
404
0
    return;
405
46
  case PPC_OP_GROUP_crbitm: {
406
46
    unsigned CCReg = MCInst_getOpVal(MI, OpNum);
407
46
    PPC_set_detail_op_reg(MI, OpNum, CCReg);
408
46
    break;
409
2.51k
  }
410
5.67k
  case PPC_OP_GROUP_BranchOperand: {
411
5.67k
    if (!MCOperand_isImm(MCInst_getOperand(MI, (OpNum))))
412
      // Handled in printOperand()
413
0
      return;
414
5.67k
    int32_t Imm = SignExtend32(
415
5.67k
      ((unsigned)MCInst_getOpVal(MI, (OpNum)) << 2), 32);
416
5.67k
    uint64_t Address = MI->address + Imm;
417
5.67k
    if (IS_32BIT(MI->csh->mode))
418
1.27k
      Address &= 0xffffffff;
419
5.67k
    PPC_get_detail_op(MI, 0)->type = PPC_OP_IMM;
420
5.67k
    PPC_get_detail_op(MI, 0)->imm = Address;
421
5.67k
    PPC_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
422
5.67k
    PPC_inc_op_count(MI);
423
5.67k
    break;
424
5.67k
  }
425
  // Memory operands have their `set_mem_access()` calls
426
  // in PPCInstPrinter.
427
12.0k
  case PPC_OP_GROUP_MemRegImm:
428
13.7k
  case PPC_OP_GROUP_MemRegReg: {
429
    // These cases print 0 if the base register is R0.
430
    // So no printOperand() function is called.
431
    // We must handle the zero case here.
432
13.7k
    unsigned OpNumReg = 0;
433
13.7k
    if (op_group == PPC_OP_GROUP_MemRegImm)
434
12.0k
      OpNumReg = OpNum + 1;
435
1.73k
    else
436
1.73k
      OpNumReg = OpNum;
437
438
13.7k
    MCOperand *Op = MCInst_getOperand(MI, OpNumReg);
439
13.7k
    if (MCOperand_isReg(Op) && MCOperand_getReg(Op) == PPC_R0) {
440
0
      PPC_get_detail_op(MI, 0)->mem.base = PPC_REG_ZERO;
441
0
      PPC_get_detail_op(MI, 0)->type = PPC_OP_MEM;
442
0
      PPC_get_detail_op(MI, 0)->access =
443
0
        map_get_op_access(MI, OpNum);
444
0
    }
445
13.7k
    break;
446
12.0k
  }
447
78
  case PPC_OP_GROUP_MemRegImmHash:
448
167
  case PPC_OP_GROUP_MemRegImm34:
449
293
  case PPC_OP_GROUP_MemRegImm34PCRel:
450
    // Handled in other printOperand functions.
451
293
    break;
452
162k
  }
453
162k
}
454
455
/// Fills cs_detail with the data of the operand.
456
/// Calls to this function should not be added by hand! Please checkout the
457
/// patch `AddCSDetail` of the CppTranslator.
458
void PPC_add_cs_detail(MCInst *MI, ppc_op_group op_group, va_list args)
459
162k
{
460
162k
  if (!detail_is_set(MI) || !map_fill_detail_ops(MI))
461
0
    return;
462
463
162k
  switch (op_group) {
464
0
  default:
465
0
    printf("Operand group %d not handled!\n", op_group);
466
0
    return;
467
0
  case PPC_OP_GROUP_PredicateOperand: {
468
0
    unsigned OpNum = va_arg(args, unsigned);
469
0
    const char *Modifier = va_arg(args, const char *);
470
0
    if ((strcmp(Modifier, "cc") == 0) ||
471
0
        (strcmp(Modifier, "pm") == 0)) {
472
0
      unsigned Val = MCInst_getOpVal(MI, OpNum);
473
0
      unsigned bo = Val & 0x1f;
474
0
      unsigned bi = (Val & 0x1e0) >> 5;
475
0
      PPC_get_detail(MI)->bc.bo = bo;
476
0
      PPC_get_detail(MI)->bc.bi = bi;
477
0
      PPC_get_detail(MI)->bc.crX_bit = bi % 4;
478
0
      PPC_get_detail(MI)->bc.crX = PPC_REG_CR0 + (bi / 4);
479
0
      PPC_get_detail(MI)->bc.pred_cr =
480
0
        PPC_get_branch_pred(bi, bo, true);
481
0
      PPC_get_detail(MI)->bc.pred_ctr =
482
0
        PPC_get_branch_pred(bi, bo, false);
483
0
      PPC_get_detail(MI)->bc.hint = PPC_get_hint(bo);
484
0
    }
485
0
    return;
486
0
  }
487
885
  case PPC_OP_GROUP_S12ImmOperand:
488
101k
  case PPC_OP_GROUP_Operand:
489
103k
  case PPC_OP_GROUP_MemRegReg:
490
104k
  case PPC_OP_GROUP_U6ImmOperand:
491
115k
  case PPC_OP_GROUP_U5ImmOperand:
492
127k
  case PPC_OP_GROUP_MemRegImm:
493
144k
  case PPC_OP_GROUP_S16ImmOperand:
494
144k
  case PPC_OP_GROUP_U2ImmOperand:
495
149k
  case PPC_OP_GROUP_U16ImmOperand:
496
155k
  case PPC_OP_GROUP_BranchOperand:
497
158k
  case PPC_OP_GROUP_AbsBranchOperand:
498
159k
  case PPC_OP_GROUP_U1ImmOperand:
499
159k
  case PPC_OP_GROUP_TLSCall:
500
160k
  case PPC_OP_GROUP_U3ImmOperand:
501
160k
  case PPC_OP_GROUP_S5ImmOperand:
502
160k
  case PPC_OP_GROUP_MemRegImmHash:
503
161k
  case PPC_OP_GROUP_U4ImmOperand:
504
161k
  case PPC_OP_GROUP_U10ImmOperand:
505
161k
  case PPC_OP_GROUP_crbitm:
506
161k
  case PPC_OP_GROUP_S34ImmOperand:
507
161k
  case PPC_OP_GROUP_ImmZeroOperand:
508
161k
  case PPC_OP_GROUP_MemRegImm34:
509
161k
  case PPC_OP_GROUP_MemRegImm34PCRel:
510
161k
  case PPC_OP_GROUP_U8ImmOperand:
511
162k
  case PPC_OP_GROUP_U12ImmOperand:
512
162k
  case PPC_OP_GROUP_U7ImmOperand:
513
162k
  case PPC_OP_GROUP_ATBitsAsHint: {
514
162k
    unsigned OpNum = va_arg(args, unsigned);
515
162k
    add_cs_detail_general(MI, op_group, OpNum);
516
162k
    return;
517
162k
  }
518
162k
  }
519
162k
}
520
521
void PPC_set_detail_op_mem(MCInst *MI, unsigned OpNum, uint64_t Val,
522
         bool is_off_reg)
523
31.2k
{
524
31.2k
  if (!detail_is_set(MI))
525
0
    return;
526
527
31.2k
  assert(map_get_op_type(MI, OpNum) & CS_OP_MEM);
528
31.2k
  cs_op_type secondary_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM;
529
530
31.2k
  switch (secondary_type) {
531
0
  default:
532
0
    assert(0 && "Secondary type not supported yet.");
533
18.1k
  case CS_OP_REG:
534
18.1k
    if (is_off_reg) {
535
2.50k
      PPC_get_detail_op(MI, 0)->mem.offset = Val;
536
2.50k
      if (PPC_get_detail_op(MI, 0)->mem.base != PPC_REG_INVALID)
537
2.50k
        set_mem_access(MI, false);
538
15.6k
    }  else {
539
15.6k
      PPC_get_detail_op(MI, 0)->mem.base = Val;
540
15.6k
      if (MCInst_opIsTying(MI, OpNum))
541
0
        map_add_implicit_write(MI, MCInst_getOpVal(MI, OpNum));
542
15.6k
    }
543
18.1k
    break;
544
13.1k
  case CS_OP_IMM:
545
13.1k
    PPC_get_detail_op(MI, 0)->mem.disp = Val;
546
13.1k
    if (PPC_get_detail_op(MI, 0)->mem.base != PPC_REG_INVALID)
547
0
      set_mem_access(MI, false);
548
13.1k
    break;
549
31.2k
  }
550
551
31.2k
  PPC_get_detail_op(MI, 0)->type = PPC_OP_MEM;
552
31.2k
  PPC_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
553
31.2k
}
554
555
/// Adds a register PPC operand at position OpNum and increases the op_count by
556
/// one.
557
void PPC_set_detail_op_reg(MCInst *MI, unsigned OpNum, ppc_reg Reg)
558
81.6k
{
559
81.6k
  if (!detail_is_set(MI))
560
0
    return;
561
81.6k
  assert(!(map_get_op_type(MI, OpNum) & CS_OP_MEM));
562
81.6k
  assert(map_get_op_type(MI, OpNum) == CS_OP_REG);
563
564
81.6k
  PPC_get_detail_op(MI, 0)->type = PPC_OP_REG;
565
81.6k
  PPC_get_detail_op(MI, 0)->reg = Reg;
566
81.6k
  PPC_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
567
81.6k
  PPC_inc_op_count(MI);
568
81.6k
}
569
570
/// Adds an immediate PPC operand at position OpNum and increases the op_count
571
/// by one.
572
void PPC_set_detail_op_imm(MCInst *MI, unsigned OpNum, int64_t Imm)
573
27.2k
{
574
27.2k
  if (!detail_is_set(MI))
575
0
    return;
576
27.2k
  assert(!(map_get_op_type(MI, OpNum) & CS_OP_MEM));
577
27.2k
  assert(map_get_op_type(MI, OpNum) == CS_OP_IMM);
578
579
27.2k
  PPC_get_detail_op(MI, 0)->type = PPC_OP_IMM;
580
27.2k
  PPC_get_detail_op(MI, 0)->imm = Imm;
581
27.2k
  PPC_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
582
27.2k
  PPC_inc_op_count(MI);
583
27.2k
}
584
585
void PPC_set_mem_access(MCInst *MI, bool status)
586
33.3k
{
587
33.3k
  if (!detail_is_set(MI))
588
0
    return;
589
33.3k
  if ((!status && !doing_mem(MI)) || (status && doing_mem(MI)))
590
1.88k
    return; // Nothing to do
591
592
31.5k
  set_doing_mem(MI, status);
593
31.5k
  if (status) {
594
15.7k
    PPC_get_detail_op(MI, 0)->type = PPC_OP_MEM;
595
15.7k
    PPC_get_detail_op(MI, 0)->mem.base = PPC_REG_INVALID;
596
15.7k
    PPC_get_detail_op(MI, 0)->mem.offset = PPC_REG_INVALID;
597
15.7k
    PPC_get_detail_op(MI, 0)->mem.disp = 0;
598
599
15.7k
#ifndef CAPSTONE_DIET
600
15.7k
    uint8_t access =
601
15.7k
      map_get_op_access(MI, PPC_get_detail(MI)->op_count);
602
15.7k
    PPC_get_detail_op(MI, 0)->access = access;
603
15.7k
#endif
604
15.7k
  } else {
605
    // done, select the next operand slot
606
15.7k
    PPC_inc_op_count(MI);
607
15.7k
  }
608
31.5k
}
609
610
void PPC_setup_op(cs_ppc_op *op)
611
384
{
612
384
  memset(op, 0, sizeof(cs_ppc_op));
613
384
  op->type = PPC_OP_INVALID;
614
384
}
615
616
/// Inserts a immediate to the detail operands at @index.
617
/// Already present operands are moved.
618
void PPC_insert_detail_op_imm_at(MCInst *MI, unsigned index, int64_t Val,
619
         cs_ac_type access)
620
384
{
621
384
  if (!detail_is_set(MI) || !map_fill_detail_ops(MI))
622
0
    return;
623
624
384
  assert(PPC_get_detail(MI)->op_count < PPC_NUM_OPS);
625
626
384
  cs_ppc_op op;
627
384
  PPC_setup_op(&op);
628
384
  op.type = PPC_OP_IMM;
629
384
  op.imm = Val;
630
384
  op.access = access;
631
632
384
  cs_ppc_op *ops = PPC_get_detail(MI)->operands;
633
384
  int i = PPC_get_detail(MI)->op_count - 1;
634
1.14k
  for (; i >= 0; --i) {
635
762
    ops[i + 1] = ops[i];
636
762
    if (i == index)
637
6
      break;
638
762
  }
639
384
  ops[index] = op;
640
384
  PPC_inc_op_count(MI);
641
384
}
642
643
#endif