Coverage Report

Created: 2026-11-12 06:22

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