Coverage Report

Created: 2026-03-11 06:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonev5/arch/PowerPC/PPCInstPrinter.c
Line
Count
Source
1
//===-- PPCInstPrinter.cpp - Convert PPC MCInst to assembly syntax --------===//
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 class prints an PPC MCInst to a .s file.
11
//
12
//===----------------------------------------------------------------------===//
13
14
/* Capstone Disassembly Engine */
15
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */
16
17
#ifdef CAPSTONE_HAS_POWERPC
18
19
#include <stdio.h>
20
#include <stdlib.h>
21
#include <string.h>
22
23
#include "PPCInstPrinter.h"
24
#include "PPCPredicates.h"
25
#include "../../MCInst.h"
26
#include "../../utils.h"
27
#include "../../SStream.h"
28
#include "../../MCRegisterInfo.h"
29
#include "../../MathExtras.h"
30
#include "PPCMapping.h"
31
32
#ifndef CAPSTONE_DIET
33
static const char *getRegisterName(unsigned RegNo);
34
#endif
35
36
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
37
static void printInstruction(MCInst *MI, SStream *O);
38
static void printAbsBranchOperand(MCInst *MI, unsigned OpNo, SStream *O);
39
static char *printAliasInstr(MCInst *MI, SStream *OS, MCRegisterInfo *MRI);
40
static char *printAliasBcc(MCInst *MI, SStream *OS, void *info);
41
static void printCustomAliasOperand(MCInst *MI, unsigned OpIdx,
42
    unsigned PrintMethodIdx, SStream *OS);
43
44
#if 0
45
static void printRegName(SStream *OS, unsigned RegNo)
46
{
47
  char *RegName = getRegisterName(RegNo);
48
49
  if (RegName[0] == 'q' /* QPX */) {
50
    // The system toolchain on the BG/Q does not understand QPX register names
51
    // in .cfi_* directives, so print the name of the floating-point
52
    // subregister instead.
53
    RegName[0] = 'f';
54
  }
55
56
  SStream_concat0(OS, RegName);
57
}
58
#endif
59
60
static void set_mem_access(MCInst *MI, bool status)
61
27.7k
{
62
27.7k
  if (MI->csh->detail != CS_OPT_ON)
63
0
    return;
64
65
27.7k
  MI->csh->doing_mem = status;
66
67
27.7k
  if (status) {
68
13.8k
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_MEM;
69
13.8k
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].mem.base = PPC_REG_INVALID;
70
13.8k
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].mem.disp = 0;
71
13.8k
  } else {
72
    // done, create the next operand slot
73
13.8k
    MI->flat_insn->detail->ppc.op_count++;
74
13.8k
  }
75
27.7k
}
76
77
void PPC_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
78
96.5k
{
79
96.5k
  if (((cs_struct *)ud)->detail != CS_OPT_ON)
80
0
    return;
81
82
  // check if this insn has branch hint
83
96.5k
  if (strrchr(insn->mnemonic, '+') != NULL && !strstr(insn_asm, ".+")) {
84
2.94k
    insn->detail->ppc.bh = PPC_BH_PLUS;
85
93.5k
  } else if (strrchr(insn->mnemonic, '-') != NULL) {
86
1.17k
    insn->detail->ppc.bh = PPC_BH_MINUS;
87
1.17k
  }
88
89
96.5k
  if (strrchr(insn->mnemonic, '.') != NULL) {
90
7.03k
    insn->detail->ppc.update_cr0 = true;
91
7.03k
  }
92
96.5k
}
93
94
#define GET_INSTRINFO_ENUM
95
#include "PPCGenInstrInfo.inc"
96
97
#define GET_REGINFO_ENUM
98
#include "PPCGenRegisterInfo.inc"
99
100
static void op_addBC(MCInst *MI, unsigned int bc)
101
2.93k
{
102
2.93k
  if (MI->csh->detail) {
103
2.93k
    MI->flat_insn->detail->ppc.bc = (ppc_bc)bc;
104
2.93k
  }
105
2.93k
}
106
107
1.14k
#define CREQ (0)
108
540
#define CRGT (1)
109
1.39k
#define CRLT (2)
110
1.79k
#define CRUN (3)
111
112
static int getBICRCond(int bi)
113
4.86k
{
114
4.86k
  return (bi - PPC_CR0EQ) >> 3;
115
4.86k
}
116
117
static int getBICR(int bi)
118
4.86k
{
119
4.86k
  return ((bi - PPC_CR0EQ) & 7) + PPC_CR0;
120
4.86k
}
121
122
static void op_addReg(MCInst *MI, unsigned int reg)
123
1.48k
{
124
1.48k
  if (MI->csh->detail) {
125
1.48k
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_REG;
126
1.48k
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].reg = reg;
127
1.48k
    MI->flat_insn->detail->ppc.op_count++;
128
1.48k
  }
129
1.48k
}
130
131
static void add_CRxx(MCInst *MI, ppc_reg reg)
132
1.51k
{
133
1.51k
  if (MI->csh->detail) {
134
1.51k
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_REG;
135
1.51k
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].reg = reg;
136
1.51k
    MI->flat_insn->detail->ppc.op_count++;
137
1.51k
  }
138
1.51k
}
139
140
static char *printAliasBcc(MCInst *MI, SStream *OS, void *info)
141
94.2k
{
142
94.2k
#define GETREGCLASS_CONTAIN(_class, _reg) MCRegisterClass_contains(MCRegisterInfo_getRegClass(MRI, _class), MCOperand_getReg(MCInst_getOperand(MI, _reg)))
143
94.2k
  SStream ss;
144
94.2k
  const char *opCode;
145
94.2k
  char *tmp, *AsmMnem, *AsmOps, *c;
146
94.2k
  int OpIdx, PrintMethodIdx;
147
94.2k
  int decCtr = false, needComma = false;
148
94.2k
  MCRegisterInfo *MRI = (MCRegisterInfo *)info;
149
150
94.2k
  SStream_Init(&ss);
151
152
94.2k
  switch (MCInst_getOpcode(MI)) {
153
87.0k
    default: return NULL;
154
2.62k
    case PPC_gBC:
155
2.62k
         opCode = "b%s";
156
2.62k
         break;
157
1.87k
    case PPC_gBCA:
158
1.87k
         opCode = "b%sa";
159
1.87k
         break;
160
38
    case PPC_gBCCTR:
161
38
         opCode = "b%sctr";
162
38
         break;
163
203
    case PPC_gBCCTRL:
164
203
         opCode = "b%sctrl";
165
203
         break;
166
1.18k
    case PPC_gBCL:
167
1.18k
         opCode = "b%sl";
168
1.18k
         break;
169
1.14k
    case PPC_gBCLA:
170
1.14k
         opCode = "b%sla";
171
1.14k
         break;
172
76
    case PPC_gBCLR:
173
76
         opCode = "b%slr";
174
76
         break;
175
46
    case PPC_gBCLRL:
176
46
         opCode = "b%slrl";
177
46
         break;
178
94.2k
  }
179
180
7.18k
  if (MCInst_getNumOperands(MI) == 3 &&
181
7.18k
      MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
182
7.18k
      (MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 0) &&
183
7.18k
      (MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 1)) {
184
1.22k
    SStream_concat(&ss, opCode, "dnzf");
185
1.22k
    decCtr = true;
186
1.22k
  }
187
188
7.18k
  if (MCInst_getNumOperands(MI) == 3 &&
189
7.18k
      MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
190
7.18k
      (MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 2) &&
191
5.96k
      (MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 3)) {
192
601
    SStream_concat(&ss, opCode, "dzf");
193
601
    decCtr = true;
194
601
  }
195
196
7.18k
  if (MCInst_getNumOperands(MI) == 3 &&
197
7.18k
      MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
198
7.18k
      (MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 4) &&
199
5.36k
      (MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 7) &&
200
1.23k
      MCOperand_isReg(MCInst_getOperand(MI, 1)) &&
201
1.23k
      GETREGCLASS_CONTAIN(PPC_CRBITRCRegClassID, 1)) {
202
1.23k
    int cr = getBICRCond(MCOperand_getReg(MCInst_getOperand(MI, 1)));
203
204
1.23k
    switch(cr) {
205
113
      case CREQ:
206
113
        SStream_concat(&ss, opCode, "ne");
207
113
        break;
208
13
      case CRGT:
209
13
        SStream_concat(&ss, opCode, "le");
210
13
        break;
211
302
      case CRLT:
212
302
        SStream_concat(&ss, opCode, "ge");
213
302
        break;
214
804
      case CRUN:
215
804
        SStream_concat(&ss, opCode, "ns");
216
804
        break;
217
1.23k
    }
218
219
1.23k
    if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 6)
220
423
      SStream_concat0(&ss, "-");
221
222
1.23k
    if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 7)
223
241
      SStream_concat0(&ss, "+");
224
225
1.23k
    decCtr = false;
226
1.23k
  }
227
228
7.18k
  if (MCInst_getNumOperands(MI) == 3 &&
229
7.18k
      MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
230
7.18k
      (MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 8) &&
231
4.13k
      (MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 9)) {
232
273
    SStream_concat(&ss, opCode, "dnzt");
233
273
    decCtr = true;
234
273
  }
235
236
7.18k
  if (MCInst_getNumOperands(MI) == 3 &&
237
7.18k
      MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
238
7.18k
      (MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 10) &&
239
3.85k
      (MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 11)) {
240
838
    SStream_concat(&ss, opCode, "dzt");
241
838
    decCtr = true;
242
838
  }
243
244
7.18k
  if (MCInst_getNumOperands(MI) == 3 &&
245
7.18k
      MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
246
7.18k
      (MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 12) &&
247
3.01k
      (MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 15) &&
248
699
      MCOperand_isReg(MCInst_getOperand(MI, 1)) &&
249
699
      GETREGCLASS_CONTAIN(PPC_CRBITRCRegClassID, 1)) {
250
699
    int cr = getBICRCond(MCOperand_getReg(MCInst_getOperand(MI, 1)));
251
252
699
    switch(cr) {
253
257
      case CREQ:
254
257
        SStream_concat(&ss, opCode, "eq");
255
257
        break;
256
102
      case CRGT:
257
102
        SStream_concat(&ss, opCode, "gt");
258
102
        break;
259
135
      case CRLT:
260
135
        SStream_concat(&ss, opCode, "lt");
261
135
        break;
262
205
      case CRUN:
263
205
        SStream_concat(&ss, opCode, "so");
264
205
        break;
265
699
    }
266
267
699
    if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 14)
268
96
      SStream_concat0(&ss, "-");
269
270
699
    if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 15)
271
393
      SStream_concat0(&ss, "+");
272
273
699
    decCtr = false;
274
699
  }
275
276
7.18k
  if (MCInst_getNumOperands(MI) == 3 &&
277
7.18k
      MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
278
7.18k
      ((MCOperand_getImm(MCInst_getOperand(MI, 0)) & 0x12)== 16)) {
279
708
    SStream_concat(&ss, opCode, "dnz");
280
281
708
    if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 24)
282
199
      SStream_concat0(&ss, "-");
283
284
708
    if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 25)
285
136
      SStream_concat0(&ss, "+");
286
287
708
    needComma = false;
288
708
  }
289
290
7.18k
  if (MCInst_getNumOperands(MI) == 3 &&
291
7.18k
      MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
292
7.18k
      ((MCOperand_getImm(MCInst_getOperand(MI, 0)) & 0x12)== 18)) {
293
1.61k
    SStream_concat(&ss, opCode, "dz");
294
295
1.61k
    if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 26)
296
186
      SStream_concat0(&ss, "-");
297
298
1.61k
    if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 27)
299
185
      SStream_concat0(&ss, "+");
300
301
1.61k
    needComma = false;
302
1.61k
  }
303
304
7.18k
  if (MCOperand_isReg(MCInst_getOperand(MI, 1)) &&
305
7.18k
      GETREGCLASS_CONTAIN(PPC_CRBITRCRegClassID, 1) &&
306
7.18k
      MCOperand_isImm(MCInst_getOperand(MI, 0)) &&
307
7.18k
      (MCOperand_getImm(MCInst_getOperand(MI, 0)) < 16)) {
308
4.86k
    int cr = getBICR(MCOperand_getReg(MCInst_getOperand(MI, 1)));
309
310
4.86k
    if (decCtr) {
311
2.93k
      int cd;
312
2.93k
      needComma = true;
313
2.93k
      SStream_concat0(&ss, " ");
314
315
2.93k
      if (cr > PPC_CR0) {
316
1.41k
        SStream_concat(&ss, "4*cr%d+", cr - PPC_CR0);
317
1.41k
      }
318
319
2.93k
      cd = getBICRCond(MCOperand_getReg(MCInst_getOperand(MI, 1)));
320
2.93k
      switch(cd) {
321
772
        case CREQ:
322
772
          SStream_concat0(&ss, "eq");
323
772
          if (cr <= PPC_CR0)
324
224
            add_CRxx(MI, PPC_REG_CR0EQ);
325
772
          op_addBC(MI, PPC_BC_EQ);
326
772
          break;
327
425
        case CRGT:
328
425
          SStream_concat0(&ss, "gt");
329
425
          if (cr <= PPC_CR0)
330
366
            add_CRxx(MI, PPC_REG_CR0GT);
331
425
          op_addBC(MI, PPC_BC_GT);
332
425
          break;
333
955
        case CRLT:
334
955
          SStream_concat0(&ss, "lt");
335
955
          if (cr <= PPC_CR0)
336
592
            add_CRxx(MI, PPC_REG_CR0LT);
337
955
          op_addBC(MI, PPC_BC_LT);
338
955
          break;
339
781
        case CRUN:
340
781
          SStream_concat0(&ss, "so");
341
781
          if (cr <= PPC_CR0)
342
334
            add_CRxx(MI, PPC_REG_CR0UN);
343
781
          op_addBC(MI, PPC_BC_SO);
344
781
          break;
345
2.93k
      }
346
347
2.93k
      if (cr > PPC_CR0) {
348
1.41k
        if (MI->csh->detail) {
349
1.41k
          MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_REG;
350
1.41k
          MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 1));
351
1.41k
          MI->flat_insn->detail->ppc.op_count++;
352
1.41k
        }
353
1.41k
      }
354
2.93k
    } else {
355
1.93k
      if (cr > PPC_CR0) {
356
1.48k
        needComma = true;
357
1.48k
        SStream_concat(&ss, " cr%d", cr - PPC_CR0);
358
1.48k
        op_addReg(MI, PPC_REG_CR0 + cr - PPC_CR0);
359
1.48k
      }
360
1.93k
    }
361
4.86k
  }
362
363
7.18k
  if (MCOperand_isImm(MCInst_getOperand(MI, 2)) &&
364
7.18k
      MCOperand_getImm(MCInst_getOperand(MI, 2)) != 0) {
365
6.76k
    if (needComma)
366
4.23k
      SStream_concat0(&ss, ",");
367
368
6.76k
    SStream_concat0(&ss, " $\xFF\x03\x01");
369
6.76k
  }
370
371
7.18k
  tmp = cs_strdup(ss.buffer);
372
7.18k
  AsmMnem = tmp;
373
42.2k
  for(AsmOps = tmp; *AsmOps; AsmOps++) {
374
42.0k
    if (*AsmOps == ' ' || *AsmOps == '\t') {
375
6.94k
      *AsmOps = '\0';
376
6.94k
      AsmOps++;
377
6.94k
      break;
378
6.94k
    }
379
42.0k
  }
380
381
7.18k
  SStream_concat0(OS, AsmMnem);
382
7.18k
  if (*AsmOps) {
383
6.94k
    SStream_concat0(OS, "\t");
384
41.0k
    for (c = AsmOps; *c; c++) {
385
34.0k
      if (*c == '$') {
386
6.76k
        c += 1;
387
6.76k
        if (*c == (char)0xff) {
388
6.76k
          c += 1;
389
6.76k
          OpIdx = *c - 1;
390
6.76k
          c += 1;
391
6.76k
          PrintMethodIdx = *c - 1;
392
6.76k
          printCustomAliasOperand(MI, OpIdx, PrintMethodIdx, OS);
393
6.76k
        } else
394
0
          printOperand(MI, *c - 1, OS);
395
27.2k
      } else {
396
27.2k
        SStream_concat1(OS, *c);
397
27.2k
      }
398
34.0k
    }
399
6.94k
  }
400
401
7.18k
  return tmp;
402
7.18k
}
403
404
static bool isBOCTRBranch(unsigned int op)
405
94.2k
{
406
94.2k
  return ((op >= PPC_BDNZ) && (op <= PPC_BDZp));
407
94.2k
}
408
409
void PPC_printInst(MCInst *MI, SStream *O, void *Info)
410
96.5k
{
411
96.5k
  char *mnem;
412
96.5k
  unsigned int opcode = MCInst_getOpcode(MI);
413
96.5k
  memset(O->buffer, 0, sizeof(O->buffer));
414
415
  // printf("opcode = %u\n", opcode);
416
417
  // Check for slwi/srwi mnemonics.
418
96.5k
  if (opcode == PPC_RLWINM) {
419
1.99k
    unsigned char SH = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 2));
420
1.99k
    unsigned char MB = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 3));
421
1.99k
    unsigned char ME = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 4));
422
1.99k
    bool useSubstituteMnemonic = false;
423
424
1.99k
    if (SH <= 31 && MB == 0 && ME == (31 - SH)) {
425
377
      SStream_concat0(O, "slwi\t");
426
377
      MCInst_setOpcodePub(MI, PPC_INS_SLWI);
427
377
      useSubstituteMnemonic = true;
428
377
    }
429
430
1.99k
    if (SH <= 31 && MB == (32 - SH) && ME == 31) {
431
201
      SStream_concat0(O, "srwi\t");
432
201
      MCInst_setOpcodePub(MI, PPC_INS_SRWI);
433
201
      useSubstituteMnemonic = true;
434
201
      SH = 32 - SH;
435
201
    }
436
437
1.99k
    if (useSubstituteMnemonic) {
438
578
      printOperand(MI, 0, O);
439
578
      SStream_concat0(O, ", ");
440
578
      printOperand(MI, 1, O);
441
442
578
      if (SH > HEX_THRESHOLD)
443
203
        SStream_concat(O, ", 0x%x", (unsigned int)SH);
444
375
      else
445
375
        SStream_concat(O, ", %u", (unsigned int)SH);
446
447
578
      if (MI->csh->detail) {
448
578
        cs_ppc *ppc = &MI->flat_insn->detail->ppc;
449
450
578
        ppc->operands[ppc->op_count].type = PPC_OP_IMM;
451
578
        ppc->operands[ppc->op_count].imm = SH;
452
578
        ++ppc->op_count;
453
578
      }
454
455
578
      return;
456
578
    }
457
1.99k
  }
458
459
95.9k
  if ((opcode == PPC_OR || opcode == PPC_OR8) &&
460
251
      MCOperand_getReg(MCInst_getOperand(MI, 1)) == MCOperand_getReg(MCInst_getOperand(MI, 2))) {
461
220
    SStream_concat0(O, "mr\t");
462
220
    MCInst_setOpcodePub(MI, PPC_INS_MR);
463
464
220
    printOperand(MI, 0, O);
465
220
    SStream_concat0(O, ", ");
466
220
    printOperand(MI, 1, O);
467
468
220
    return;
469
220
  }
470
471
95.7k
  if (opcode == PPC_RLDICR ||
472
95.4k
      opcode == PPC_RLDICR_32) {
473
338
    unsigned char SH = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 2));
474
338
    unsigned char ME = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 3));
475
476
    // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH
477
338
    if (63 - SH == ME) {
478
88
      SStream_concat0(O, "sldi\t");
479
88
      MCInst_setOpcodePub(MI, PPC_INS_SLDI);
480
481
88
      printOperand(MI, 0, O);
482
88
      SStream_concat0(O, ", ");
483
88
      printOperand(MI, 1, O);
484
485
88
      if (SH > HEX_THRESHOLD)
486
14
        SStream_concat(O, ", 0x%x", (unsigned int)SH);
487
74
      else
488
74
        SStream_concat(O, ", %u", (unsigned int)SH);
489
490
88
      if (MI->csh->detail) {
491
88
        cs_ppc *ppc = &MI->flat_insn->detail->ppc;
492
493
88
        ppc->operands[ppc->op_count].type = PPC_OP_IMM;
494
88
        ppc->operands[ppc->op_count].imm = SH;
495
88
        ++ppc->op_count;
496
88
      }
497
498
499
88
      return;
500
88
    }
501
338
  }
502
503
  // dcbt[st] is printed manually here because:
504
  //  1. The assembly syntax is different between embedded and server targets
505
  //  2. We must print the short mnemonics for TH == 0 because the
506
  //     embedded/server syntax default will not be stable across assemblers
507
  //  The syntax for dcbt is:
508
  //    dcbt ra, rb, th [server]
509
  //    dcbt th, ra, rb [embedded]
510
  //  where th can be omitted when it is 0. dcbtst is the same.
511
95.6k
  if (opcode == PPC_DCBT || opcode == PPC_DCBTST) {
512
242
    unsigned char TH = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 0));
513
514
242
    SStream_concat0(O, "dcbt");
515
242
    MCInst_setOpcodePub(MI, PPC_INS_DCBT);
516
517
242
    if (opcode == PPC_DCBTST) {
518
85
      SStream_concat0(O, "st");
519
85
      MCInst_setOpcodePub(MI, PPC_INS_DCBTST);
520
85
    }
521
522
242
    if (TH == 16) {
523
42
      SStream_concat0(O, "t");
524
42
      MCInst_setOpcodePub(MI, PPC_INS_DCBTSTT);
525
42
    }
526
527
242
    SStream_concat0(O, "\t");
528
529
242
    if (MI->csh->mode & CS_MODE_BOOKE && TH != 0 && TH != 16) {
530
0
      if (TH > HEX_THRESHOLD)
531
0
        SStream_concat(O, "0x%x, ", (unsigned int)TH);
532
0
      else
533
0
        SStream_concat(O, "%u, ", (unsigned int)TH);
534
535
0
      if (MI->csh->detail) {
536
0
        cs_ppc *ppc = &MI->flat_insn->detail->ppc;
537
538
0
        ppc->operands[ppc->op_count].type = PPC_OP_IMM;
539
0
        ppc->operands[ppc->op_count].imm = TH;
540
0
        ++ppc->op_count;
541
0
      }
542
0
    }
543
544
242
    printOperand(MI, 1, O);
545
242
    SStream_concat0(O, ", ");
546
242
    printOperand(MI, 2, O);
547
548
242
    if (!(MI->csh->mode & CS_MODE_BOOKE) && TH != 0 && TH != 16) {
549
90
      if (TH > HEX_THRESHOLD)
550
20
        SStream_concat(O, ", 0x%x", (unsigned int)TH);
551
70
      else
552
70
        SStream_concat(O, ", %u", (unsigned int)TH);
553
554
90
      if (MI->csh->detail) {
555
90
        cs_ppc *ppc = &MI->flat_insn->detail->ppc;
556
557
90
        ppc->operands[ppc->op_count].type = PPC_OP_IMM;
558
90
        ppc->operands[ppc->op_count].imm = TH;
559
90
        ++ppc->op_count;
560
90
      }
561
90
    }
562
563
242
    return;
564
242
  }
565
566
95.4k
  if (opcode == PPC_DCBF) {
567
1.27k
    unsigned char L = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 0));
568
569
1.27k
    if (!L || L == 1 || L == 3) {
570
1.16k
      SStream_concat0(O, "dcbf");
571
1.16k
      MCInst_setOpcodePub(MI, PPC_INS_DCBF);
572
573
1.16k
      if (L == 1 || L == 3) {
574
1.06k
        SStream_concat0(O, "l");
575
1.06k
        MCInst_setOpcodePub(MI, PPC_INS_DCBFL);
576
1.06k
      }
577
578
1.16k
      if (L == 3) {
579
1.02k
        SStream_concat0(O, "p");
580
1.02k
        MCInst_setOpcodePub(MI, PPC_INS_DCBFLP);
581
1.02k
      }
582
583
1.16k
      SStream_concat0(O, "\t");
584
585
1.16k
      printOperand(MI, 1, O);
586
1.16k
      SStream_concat0(O, ", ");
587
1.16k
      printOperand(MI, 2, O);
588
589
1.16k
      return;
590
1.16k
    }
591
1.27k
  }
592
593
94.2k
  if (opcode == PPC_B || opcode == PPC_BA || opcode == PPC_BL ||
594
93.0k
      opcode == PPC_BLA) {
595
1.60k
    int64_t bd = MCOperand_getImm(MCInst_getOperand(MI, 0));
596
1.60k
    bd = SignExtend64(bd, 24);
597
1.60k
    MCOperand_setImm(MCInst_getOperand(MI, 0), bd);
598
1.60k
  }
599
600
94.2k
  if (opcode == PPC_gBC || opcode == PPC_gBCA || opcode == PPC_gBCL ||
601
88.5k
      opcode == PPC_gBCLA) {
602
6.82k
    int64_t bd = MCOperand_getImm(MCInst_getOperand(MI, 2));
603
6.82k
    bd = SignExtend64(bd, 14);
604
6.82k
    MCOperand_setImm(MCInst_getOperand(MI, 2), bd);
605
6.82k
  }
606
607
94.2k
  if (isBOCTRBranch(MCInst_getOpcode(MI))) {
608
1.12k
    if (MCOperand_isImm(MCInst_getOperand(MI,0))) {
609
1.01k
      int64_t bd = MCOperand_getImm(MCInst_getOperand(MI, 0));
610
1.01k
      bd = SignExtend64(bd, 14);
611
1.01k
      MCOperand_setImm(MCInst_getOperand(MI, 0), bd);
612
1.01k
    }
613
1.12k
  }
614
615
94.2k
  mnem = printAliasBcc(MI, O, Info);
616
94.2k
  if (!mnem)
617
87.0k
    mnem = printAliasInstr(MI, O, Info);
618
619
94.2k
  if (mnem != NULL) {
620
32.9k
    if (strlen(mnem) > 0) {
621
      // check to remove the last letter of ('.', '-', '+')
622
32.9k
      if (mnem[strlen(mnem) - 1] == '-' || mnem[strlen(mnem) - 1] == '+' || mnem[strlen(mnem) - 1] == '.')
623
3.05k
        mnem[strlen(mnem) - 1] = '\0';
624
625
32.9k
            MCInst_setOpcodePub(MI, PPC_map_insn(mnem));
626
627
32.9k
            if (MI->csh->detail) {
628
32.9k
        struct ppc_alias alias;
629
630
32.9k
        if (PPC_alias_insn(mnem, &alias)) {
631
1.93k
          MI->flat_insn->detail->ppc.bc = (ppc_bc)alias.cc;
632
1.93k
        }
633
32.9k
            }
634
32.9k
    }
635
636
32.9k
    cs_mem_free(mnem);
637
32.9k
  } else
638
61.2k
    printInstruction(MI, O);
639
640
94.2k
  const char *mnem_end = strchr(O->buffer, ' ');
641
94.2k
  unsigned mnem_len = 0;
642
94.2k
  if (mnem_end)
643
90.2k
    mnem_len = mnem_end - O->buffer;
644
94.2k
  if (!mnem_end || mnem_len >= sizeof(MI->flat_insn->mnemonic))
645
4.02k
    mnem_len = sizeof(MI->flat_insn->mnemonic) - 1;
646
647
94.2k
  memset(MI->flat_insn->mnemonic, 0, sizeof(MI->flat_insn->mnemonic));
648
94.2k
  memcpy(MI->flat_insn->mnemonic, O->buffer, mnem_len);
649
94.2k
}
650
651
// FIXME
652
enum ppc_bc_hint {
653
  PPC_BC_LT_MINUS = (0 << 5) | 14,
654
  PPC_BC_LE_MINUS = (1 << 5) |  6,
655
  PPC_BC_EQ_MINUS = (2 << 5) | 14,
656
  PPC_BC_GE_MINUS = (0 << 5) |  6,
657
  PPC_BC_GT_MINUS = (1 << 5) | 14,
658
  PPC_BC_NE_MINUS = (2 << 5) |  6,
659
  PPC_BC_UN_MINUS = (3 << 5) | 14,
660
  PPC_BC_NU_MINUS = (3 << 5) |  6,
661
  PPC_BC_LT_PLUS  = (0 << 5) | 15,
662
  PPC_BC_LE_PLUS  = (1 << 5) |  7,
663
  PPC_BC_EQ_PLUS  = (2 << 5) | 15,
664
  PPC_BC_GE_PLUS  = (0 << 5) |  7,
665
  PPC_BC_GT_PLUS  = (1 << 5) | 15,
666
  PPC_BC_NE_PLUS  = (2 << 5) |  7,
667
  PPC_BC_UN_PLUS  = (3 << 5) | 15,
668
  PPC_BC_NU_PLUS  = (3 << 5) |  7,
669
};
670
671
// FIXME
672
// normalize CC to remove _MINUS & _PLUS
673
static int cc_normalize(int cc)
674
0
{
675
0
  switch(cc) {
676
0
    default: return cc;
677
0
    case PPC_BC_LT_MINUS: return PPC_BC_LT;
678
0
    case PPC_BC_LE_MINUS: return PPC_BC_LE;
679
0
    case PPC_BC_EQ_MINUS: return PPC_BC_EQ;
680
0
    case PPC_BC_GE_MINUS: return PPC_BC_GE;
681
0
    case PPC_BC_GT_MINUS: return PPC_BC_GT;
682
0
    case PPC_BC_NE_MINUS: return PPC_BC_NE;
683
0
    case PPC_BC_UN_MINUS: return PPC_BC_UN;
684
0
    case PPC_BC_NU_MINUS: return PPC_BC_NU;
685
0
    case PPC_BC_LT_PLUS : return PPC_BC_LT;
686
0
    case PPC_BC_LE_PLUS : return PPC_BC_LE;
687
0
    case PPC_BC_EQ_PLUS : return PPC_BC_EQ;
688
0
    case PPC_BC_GE_PLUS : return PPC_BC_GE;
689
0
    case PPC_BC_GT_PLUS : return PPC_BC_GT;
690
0
    case PPC_BC_NE_PLUS : return PPC_BC_NE;
691
0
    case PPC_BC_UN_PLUS : return PPC_BC_UN;
692
0
    case PPC_BC_NU_PLUS : return PPC_BC_NU;
693
0
  }
694
0
}
695
696
static void printPredicateOperand(MCInst *MI, unsigned OpNo,
697
    SStream *O, const char *Modifier)
698
0
{
699
0
  unsigned Code = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
700
701
0
  MI->flat_insn->detail->ppc.bc = (ppc_bc)cc_normalize(Code);
702
703
0
  if (!strcmp(Modifier, "cc")) {
704
0
    switch ((ppc_predicate)Code) {
705
0
      default:  // unreachable
706
0
      case PPC_PRED_LT_MINUS:
707
0
      case PPC_PRED_LT_PLUS:
708
0
      case PPC_PRED_LT:
709
0
        SStream_concat0(O, "lt");
710
0
        return;
711
0
      case PPC_PRED_LE_MINUS:
712
0
      case PPC_PRED_LE_PLUS:
713
0
      case PPC_PRED_LE:
714
0
        SStream_concat0(O, "le");
715
0
        return;
716
0
      case PPC_PRED_EQ_MINUS:
717
0
      case PPC_PRED_EQ_PLUS:
718
0
      case PPC_PRED_EQ:
719
0
        SStream_concat0(O, "eq");
720
0
        return;
721
0
      case PPC_PRED_GE_MINUS:
722
0
      case PPC_PRED_GE_PLUS:
723
0
      case PPC_PRED_GE:
724
0
        SStream_concat0(O, "ge");
725
0
        return;
726
0
      case PPC_PRED_GT_MINUS:
727
0
      case PPC_PRED_GT_PLUS:
728
0
      case PPC_PRED_GT:
729
0
        SStream_concat0(O, "gt");
730
0
        return;
731
0
      case PPC_PRED_NE_MINUS:
732
0
      case PPC_PRED_NE_PLUS:
733
0
      case PPC_PRED_NE:
734
0
        SStream_concat0(O, "ne");
735
0
        return;
736
0
      case PPC_PRED_UN_MINUS:
737
0
      case PPC_PRED_UN_PLUS:
738
0
      case PPC_PRED_UN:
739
0
        SStream_concat0(O, "un");
740
0
        return;
741
0
      case PPC_PRED_NU_MINUS:
742
0
      case PPC_PRED_NU_PLUS:
743
0
      case PPC_PRED_NU:
744
0
        SStream_concat0(O, "nu");
745
0
        return;
746
0
      case PPC_PRED_BIT_SET:
747
0
      case PPC_PRED_BIT_UNSET:
748
        // llvm_unreachable("Invalid use of bit predicate code");
749
0
        SStream_concat0(O, "invalid-predicate");
750
0
        return;
751
0
    }
752
0
  }
753
754
0
  if (!strcmp(Modifier, "pm")) {
755
0
    switch ((ppc_predicate)Code) {
756
0
      case PPC_PRED_LT:
757
0
      case PPC_PRED_LE:
758
0
      case PPC_PRED_EQ:
759
0
      case PPC_PRED_GE:
760
0
      case PPC_PRED_GT:
761
0
      case PPC_PRED_NE:
762
0
      case PPC_PRED_UN:
763
0
      case PPC_PRED_NU:
764
0
        return;
765
0
      case PPC_PRED_LT_MINUS:
766
0
      case PPC_PRED_LE_MINUS:
767
0
      case PPC_PRED_EQ_MINUS:
768
0
      case PPC_PRED_GE_MINUS:
769
0
      case PPC_PRED_GT_MINUS:
770
0
      case PPC_PRED_NE_MINUS:
771
0
      case PPC_PRED_UN_MINUS:
772
0
      case PPC_PRED_NU_MINUS:
773
0
        SStream_concat0(O, "-");
774
0
        return;
775
0
      case PPC_PRED_LT_PLUS:
776
0
      case PPC_PRED_LE_PLUS:
777
0
      case PPC_PRED_EQ_PLUS:
778
0
      case PPC_PRED_GE_PLUS:
779
0
      case PPC_PRED_GT_PLUS:
780
0
      case PPC_PRED_NE_PLUS:
781
0
      case PPC_PRED_UN_PLUS:
782
0
      case PPC_PRED_NU_PLUS:
783
0
        SStream_concat0(O, "+");
784
0
        return;
785
0
      case PPC_PRED_BIT_SET:
786
0
      case PPC_PRED_BIT_UNSET:
787
        // llvm_unreachable("Invalid use of bit predicate code");
788
0
        SStream_concat0(O, "invalid-predicate");
789
0
        return;
790
0
      default:  // unreachable
791
0
        return;
792
0
    }
793
    // llvm_unreachable("Invalid predicate code");
794
0
  }
795
796
  //assert(StringRef(Modifier) == "reg" &&
797
  //    "Need to specify 'cc', 'pm' or 'reg' as predicate op modifier!");
798
0
  printOperand(MI, OpNo + 1, O);
799
0
}
800
801
static void printATBitsAsHint(MCInst *MI, unsigned OpNo, SStream *O)
802
0
{
803
0
  unsigned Code = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
804
805
0
  if (Code == 2) {
806
0
    SStream_concat0(O, "-");
807
0
  } else if (Code == 3) {
808
0
    SStream_concat0(O, "+");
809
0
  }
810
0
}
811
812
static void printU1ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
813
738
{
814
738
  unsigned int Value = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
815
816
  // assert(Value <= 1 && "Invalid u1imm argument!");
817
818
738
  printUInt32(O, Value);
819
820
738
  if (MI->csh->detail) {
821
738
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
822
738
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
823
738
    MI->flat_insn->detail->ppc.op_count++;
824
738
  }
825
738
}
826
827
static void printU2ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
828
1.53k
{
829
1.53k
  unsigned int Value = (int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
830
  //assert(Value <= 3 && "Invalid u2imm argument!");
831
832
1.53k
  printUInt32(O, Value);
833
834
1.53k
  if (MI->csh->detail) {
835
1.53k
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
836
1.53k
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
837
1.53k
    MI->flat_insn->detail->ppc.op_count++;
838
1.53k
  }
839
1.53k
}
840
841
static void printU3ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
842
175
{
843
175
  unsigned int Value = (int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
844
  //assert(Value <= 8 && "Invalid u3imm argument!");
845
846
175
  printUInt32(O, Value);
847
848
175
  if (MI->csh->detail) {
849
175
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
850
175
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
851
175
    MI->flat_insn->detail->ppc.op_count++;
852
175
  }
853
175
}
854
855
static void printU4ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
856
899
{
857
899
  unsigned int Value = (int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
858
  //assert(Value <= 15 && "Invalid u4imm argument!");
859
860
899
  printUInt32(O, Value);
861
862
899
  if (MI->csh->detail) {
863
899
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
864
899
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
865
899
    MI->flat_insn->detail->ppc.op_count++;
866
899
  }
867
899
}
868
869
static void printS5ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
870
73
{
871
73
  int Value = (int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
872
73
  Value = SignExtend32(Value, 5);
873
874
73
  printInt32(O, Value);
875
876
73
  if (MI->csh->detail) {
877
73
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
878
73
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
879
73
    MI->flat_insn->detail->ppc.op_count++;
880
73
  }
881
73
}
882
883
static void printU5ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
884
18.2k
{
885
18.2k
  unsigned int Value = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
886
887
  //assert(Value <= 31 && "Invalid u5imm argument!");
888
18.2k
  printUInt32(O, Value);
889
890
18.2k
  if (MI->csh->detail) {
891
18.2k
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
892
18.2k
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
893
18.2k
    MI->flat_insn->detail->ppc.op_count++;
894
18.2k
  }
895
18.2k
}
896
897
static void printU6ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
898
3.12k
{
899
3.12k
  unsigned int Value = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
900
901
  //assert(Value <= 63 && "Invalid u6imm argument!");
902
3.12k
  printUInt32(O, Value);
903
904
3.12k
  if (MI->csh->detail) {
905
3.12k
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
906
3.12k
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
907
3.12k
    MI->flat_insn->detail->ppc.op_count++;
908
3.12k
  }
909
3.12k
}
910
911
static void printU7ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
912
281
{
913
281
  unsigned int Value = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
914
915
  //assert(Value <= 127 && "Invalid u7imm argument!");
916
281
  printUInt32(O, Value);
917
918
281
  if (MI->csh->detail) {
919
281
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
920
281
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
921
281
    MI->flat_insn->detail->ppc.op_count++;
922
281
  }
923
281
}
924
925
// Operands of BUILD_VECTOR are signed and we use this to print operands
926
// of XXSPLTIB which are unsigned. So we simply truncate to 8 bits and
927
// print as unsigned.
928
static void printU8ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
929
58
{
930
58
  unsigned int Value = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
931
932
58
  printUInt32(O, Value);
933
934
58
  if (MI->csh->detail) {
935
58
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
936
58
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
937
58
    MI->flat_insn->detail->ppc.op_count++;
938
58
  }
939
58
}
940
941
static void printU10ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
942
48
{
943
48
  unsigned int Value = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
944
945
  //assert(Value <= 1023 && "Invalid u10imm argument!");
946
48
  printUInt32(O, Value);
947
948
48
  if (MI->csh->detail) {
949
48
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
950
48
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
951
48
    MI->flat_insn->detail->ppc.op_count++;
952
48
  }
953
48
}
954
955
static void printS12ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
956
0
{
957
0
  if (MCOperand_isImm(MCInst_getOperand(MI, OpNo))) {
958
0
    int Imm = (int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
959
0
    Imm = SignExtend32(Imm, 12);
960
961
0
    printInt32(O, Imm);
962
963
0
    if (MI->csh->detail) {
964
0
      if (MI->csh->doing_mem) {
965
0
                MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].mem.disp = Imm;
966
0
      } else {
967
0
                MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
968
0
                MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Imm;
969
0
                MI->flat_insn->detail->ppc.op_count++;
970
0
            }
971
0
    }
972
0
  } else
973
0
    printOperand(MI, OpNo, O);
974
0
}
975
976
static void printU12ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
977
609
{
978
609
  unsigned short Value = (unsigned short)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
979
980
  // assert(Value <= 4095 && "Invalid u12imm argument!");
981
982
609
  printUInt32(O, Value);
983
984
609
  if (MI->csh->detail) {
985
609
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
986
609
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
987
609
    MI->flat_insn->detail->ppc.op_count++;
988
609
  }
989
609
}
990
991
static void printS16ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
992
26.8k
{
993
26.8k
  if (MCOperand_isImm(MCInst_getOperand(MI, OpNo))) {
994
26.8k
    short Imm = (short)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
995
26.8k
    printInt32(O, Imm);
996
997
26.8k
    if (MI->csh->detail) {
998
26.8k
      if (MI->csh->doing_mem) {
999
13.8k
                MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].mem.disp = Imm;
1000
13.8k
      } else {
1001
12.9k
                MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
1002
12.9k
                MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Imm;
1003
12.9k
                MI->flat_insn->detail->ppc.op_count++;
1004
12.9k
            }
1005
26.8k
    }
1006
26.8k
  } else
1007
0
    printOperand(MI, OpNo, O);
1008
26.8k
}
1009
1010
static void printU16ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
1011
4.34k
{
1012
4.34k
  if (MCOperand_isImm(MCInst_getOperand(MI, OpNo))) {
1013
4.34k
    unsigned short Imm = (unsigned short)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
1014
4.34k
    printUInt32(O, Imm);
1015
1016
4.34k
    if (MI->csh->detail) {
1017
4.34k
      MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
1018
4.34k
      MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Imm;
1019
4.34k
      MI->flat_insn->detail->ppc.op_count++;
1020
4.34k
    }
1021
4.34k
  } else
1022
0
    printOperand(MI, OpNo, O);
1023
4.34k
}
1024
1025
static void printBranchOperand(MCInst *MI, unsigned OpNo, SStream *O)
1026
7.66k
{
1027
7.66k
  if (!MCOperand_isImm(MCInst_getOperand(MI, OpNo))) {
1028
0
    printOperand(MI, OpNo, O);
1029
1030
0
    return;
1031
0
  }
1032
1033
  // Branches can take an immediate operand.  This is used by the branch
1034
  // selection pass to print .+8, an eight byte displacement from the PC.
1035
  // O << ".+";
1036
7.66k
  printAbsBranchOperand(MI, OpNo, O);
1037
7.66k
}
1038
1039
static void printAbsBranchOperand(MCInst *MI, unsigned OpNo, SStream *O)
1040
9.38k
{
1041
9.38k
  int64_t imm;
1042
1043
9.38k
  if (!MCOperand_isImm(MCInst_getOperand(MI, OpNo))) {
1044
0
    printOperand(MI, OpNo, O);
1045
1046
0
    return;
1047
0
  }
1048
1049
9.38k
  imm = SignExtend32(MCOperand_getImm(MCInst_getOperand(MI, OpNo)) * 4, 32);
1050
  //imm = MCOperand_getImm(MCInst_getOperand(MI, OpNo)) * 4;
1051
1052
9.38k
  if (!PPC_abs_branch(MI->csh, MCInst_getOpcode(MI))) {
1053
4.70k
    imm += MI->address;
1054
4.70k
  }
1055
1056
9.38k
  printUInt64(O, imm);
1057
1058
9.38k
  if (MI->csh->detail) {
1059
9.38k
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
1060
9.38k
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = imm;
1061
9.38k
    MI->flat_insn->detail->ppc.op_count++;
1062
9.38k
  }
1063
9.38k
}
1064
1065
static void printcrbitm(MCInst *MI, unsigned OpNo, SStream *O)
1066
1.21k
{
1067
1.21k
  unsigned RegNo;
1068
1.21k
  unsigned CCReg = MCOperand_getReg(MCInst_getOperand(MI, OpNo));
1069
1070
1.21k
  switch (CCReg) {
1071
0
    default: // llvm_unreachable("Unknown CR register");
1072
313
    case PPC_CR0: RegNo = 0; break;
1073
136
    case PPC_CR1: RegNo = 1; break;
1074
109
    case PPC_CR2: RegNo = 2; break;
1075
136
    case PPC_CR3: RegNo = 3; break;
1076
170
    case PPC_CR4: RegNo = 4; break;
1077
41
    case PPC_CR5: RegNo = 5; break;
1078
173
    case PPC_CR6: RegNo = 6; break;
1079
133
    case PPC_CR7: RegNo = 7; break;
1080
1.21k
  }
1081
1082
1.21k
  printUInt32(O, 0x80 >> RegNo);
1083
1.21k
}
1084
1085
static void printMemRegImm(MCInst *MI, unsigned OpNo, SStream *O)
1086
23.2k
{
1087
23.2k
  set_mem_access(MI, true);
1088
1089
23.2k
  printS16ImmOperand(MI, OpNo, O);
1090
1091
23.2k
  SStream_concat0(O, "(");
1092
1093
23.2k
  if (MCOperand_getReg(MCInst_getOperand(MI, OpNo + 1)) == PPC_R0)
1094
0
    SStream_concat0(O, "0");
1095
23.2k
  else
1096
23.2k
    printOperand(MI, OpNo + 1, O);
1097
1098
23.2k
  SStream_concat0(O, ")");
1099
1100
23.2k
  set_mem_access(MI, false);
1101
23.2k
}
1102
1103
static void printPSMemRegImm(MCInst *MI, unsigned OpNo, SStream *O)
1104
0
{
1105
0
  set_mem_access(MI, true);
1106
1107
0
  printS12ImmOperand(MI, OpNo, O);
1108
1109
0
  SStream_concat0(O, "(");
1110
0
  printOperand(MI, OpNo + 1, O);
1111
0
  SStream_concat0(O, ")");
1112
1113
0
  set_mem_access(MI, false);
1114
0
}
1115
1116
static void printMemRegReg(MCInst *MI, unsigned OpNo, SStream *O)
1117
4.56k
{
1118
  // When used as the base register, r0 reads constant zero rather than
1119
  // the value contained in the register.  For this reason, the darwin
1120
  // assembler requires that we print r0 as 0 (no r) when used as the base.
1121
4.56k
  if (MCOperand_getReg(MCInst_getOperand(MI, OpNo)) == PPC_R0)
1122
0
    SStream_concat0(O, "0");
1123
4.56k
  else
1124
4.56k
    printOperand(MI, OpNo, O);
1125
4.56k
  SStream_concat0(O, ", ");
1126
1127
4.56k
  printOperand(MI, OpNo + 1, O);
1128
4.56k
}
1129
1130
static void printTLSCall(MCInst *MI, unsigned OpNo, SStream *O)
1131
0
{
1132
0
  set_mem_access(MI, true);
1133
  //printBranchOperand(MI, OpNo, O);
1134
1135
  // On PPC64, VariantKind is VK_None, but on PPC32, it's VK_PLT, and it must
1136
  // come at the _end_ of the expression.
1137
1138
0
  SStream_concat0(O, "(");
1139
0
  printOperand(MI, OpNo + 1, O);
1140
0
  SStream_concat0(O, ")");
1141
1142
0
  set_mem_access(MI, false);
1143
0
}
1144
1145
/// stripRegisterPrefix - This method strips the character prefix from a
1146
/// register name so that only the number is left.  Used by for linux asm.
1147
static char *stripRegisterPrefix(const char *RegName)
1148
0
{
1149
0
  switch (RegName[0]) {
1150
0
    case 'r':
1151
0
    case 'f':
1152
0
    case 'q': // for QPX
1153
0
    case 'v':
1154
0
      if (RegName[1] == 's')
1155
0
        return cs_strdup(RegName + 2);
1156
1157
0
      return cs_strdup(RegName + 1);
1158
0
    case 'c':
1159
0
      if (RegName[1] == 'r') {
1160
        // skip the first 2 letters "cr"
1161
0
        char *name = cs_strdup(RegName + 2);
1162
1163
        // also strip the last 2 letters
1164
0
        if(strlen(name) > 2)
1165
0
          name[strlen(name) - 2] = '\0';
1166
1167
0
        return name;
1168
0
      }
1169
0
  }
1170
1171
0
  return cs_strdup(RegName);
1172
0
}
1173
1174
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
1175
169k
{
1176
169k
  MCOperand *Op = MCInst_getOperand(MI, OpNo);
1177
169k
  if (MCOperand_isReg(Op)) {
1178
164k
    unsigned reg = MCOperand_getReg(Op);
1179
164k
#ifndef CAPSTONE_DIET
1180
164k
    const char *RegName = getRegisterName(reg);
1181
1182
    // printf("reg = %u (%s)\n", reg, RegName);
1183
1184
    // convert internal register ID to public register ID
1185
164k
    reg = PPC_name_reg(RegName);
1186
1187
    // The linux and AIX assembler does not take register prefixes.
1188
164k
    if (MI->csh->syntax == CS_OPT_SYNTAX_NOREGNAME) {
1189
0
      char *name = stripRegisterPrefix(RegName);
1190
0
      SStream_concat0(O, name);
1191
0
      cs_mem_free(name);
1192
0
    } else
1193
164k
      SStream_concat0(O, RegName);
1194
164k
#endif
1195
1196
164k
    if (MI->csh->detail) {
1197
164k
      if (MI->csh->doing_mem) {
1198
13.8k
        MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].mem.base = reg;
1199
150k
      } else {
1200
150k
        MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_REG;
1201
150k
        MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].reg = reg;
1202
150k
        MI->flat_insn->detail->ppc.op_count++;
1203
150k
      }
1204
164k
    }
1205
1206
164k
    return;
1207
164k
  }
1208
1209
5.25k
  if (MCOperand_isImm(Op)) {
1210
5.25k
    int32_t imm = (int32_t)MCOperand_getImm(Op);
1211
5.25k
    printInt32(O, imm);
1212
1213
5.25k
    if (MI->csh->detail) {
1214
5.25k
      if (MI->csh->doing_mem) {
1215
0
        MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].mem.disp = (int32_t)imm;
1216
5.25k
      } else {
1217
5.25k
        MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
1218
5.25k
        MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = imm;
1219
5.25k
        MI->flat_insn->detail->ppc.op_count++;
1220
5.25k
      }
1221
5.25k
    }
1222
5.25k
  }
1223
5.25k
}
1224
1225
static void op_addImm(MCInst *MI, int v)
1226
231
{
1227
231
  if (MI->csh->detail) {
1228
231
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
1229
231
    MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = v;
1230
231
    MI->flat_insn->detail->ppc.op_count++;
1231
231
  }
1232
231
}
1233
1234
#define PRINT_ALIAS_INSTR
1235
#include "PPCGenRegisterName.inc"
1236
#include "PPCGenAsmWriter.inc"
1237
1238
#endif