Coverage Report

Created: 2023-12-08 06:05

/src/capstonenext/arch/PowerPC/PPCInstPrinter.c
Line
Count
Source (jump to first uncovered line)
1
/* Capstone Disassembly Engine, http://www.capstone-engine.org */
2
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2022, */
3
/*    Rot127 <unisono@quyllur.org> 2022-2023 */
4
/* Automatically translated source file from LLVM. */
5
6
/* LLVM-commit: <commit> */
7
/* LLVM-tag: <tag> */
8
9
/* Only small edits allowed. */
10
/* For multiple similar edits, please create a Patch for the translator. */
11
12
/* Capstone's C++ file translator: */
13
/* https://github.com/capstone-engine/capstone/tree/next/suite/auto-sync */
14
15
//===-- PPCInstPrinter.cpp - Convert PPC MCInst to assembly syntax --------===//
16
//
17
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
18
// See https://llvm.org/LICENSE.txt for license information.
19
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
20
//
21
//===----------------------------------------------------------------------===//
22
//
23
// This class prints an PPC MCInst to a .s file.
24
//
25
//===----------------------------------------------------------------------===//
26
27
#include <capstone/platform.h>
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <string.h>
31
32
#include "../../LEB128.h"
33
#include "../../Mapping.h"
34
#include "../../MCInst.h"
35
#include "../../MCInstPrinter.h"
36
#include "../../MCInstrDesc.h"
37
#include "../../MCRegisterInfo.h"
38
#include "PPCInstrInfo.h"
39
#include "PPCInstPrinter.h"
40
#include "PPCLinkage.h"
41
#include "PPCMCTargetDesc.h"
42
#include "PPCMapping.h"
43
#include "PPCPredicates.h"
44
#include "PPCRegisterInfo.h"
45
46
#define CONCAT(a, b) CONCAT_(a, b)
47
#define CONCAT_(a, b) a##_##b
48
49
#define DEBUG_TYPE "asm-printer"
50
51
// Static function declarations. These are functions which have the same identifiers
52
// over all architectures. Therefor they need to be static.
53
static void printCustomAliasOperand(MCInst *MI, uint64_t Address,
54
            unsigned OpIdx, unsigned PrintMethodIdx,
55
            SStream *O);
56
static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
57
static void printPredicateOperand(MCInst *MI, unsigned OpNo, SStream *O,
58
          const char *Modifier);
59
static void printInst(MCInst *MI, uint64_t Address, const char *Annot,
60
          SStream *O);
61
62
#define PRINT_ALIAS_INSTR
63
#include "PPCGenAsmWriter.inc"
64
65
static void printInst(MCInst *MI, uint64_t Address, const char *Annot,
66
          SStream *O)
67
50.9k
{
68
50.9k
  bool isAlias = false;
69
50.9k
  bool useAliasDetails = false;
70
  // Customize printing of the addis instruction on AIX. When an operand is a
71
  // symbol reference, the instruction syntax is changed to look like a load
72
  // operation, i.e:
73
  //     Transform:  addis $rD, $rA, $src --> addis $rD, $src($rA).
74
50.9k
  if (PPC_getFeatureBits(MI->csh->mode, PPC_FeatureModernAIXAs) &&
75
50.9k
      (MCInst_getOpcode(MI) == PPC_ADDIS8 ||
76
0
       MCInst_getOpcode(MI) == PPC_ADDIS) &&
77
50.9k
      MCOperand_isExpr(MCInst_getOperand(MI, (2)))) {
78
0
    SStream_concat0(O, "\taddis ");
79
0
    printOperand(MI, 0, O);
80
0
    SStream_concat0(O, ", ");
81
0
    printOperand(MI, 2, O);
82
0
    SStream_concat0(O, "(");
83
0
    printOperand(MI, 1, O);
84
0
    SStream_concat0(O, ")");
85
0
    return;
86
0
  }
87
88
  // Check if the last operand is an expression with the variant kind
89
  // VK_PPC_PCREL_OPT. If this is the case then this is a linker optimization
90
  // relocation and the .reloc directive needs to be added.
91
50.9k
  unsigned LastOp = MCInst_getNumOperands(MI) - 1;
92
50.9k
  if (MCInst_getNumOperands(MI) > 1) {
93
49.1k
    MCOperand *Operand = MCInst_getOperand(MI, (LastOp));
94
49.1k
    if (MCOperand_isExpr(Operand)) {
95
0
      assert(0 && "Expressions not supported.");
96
0
    }
97
49.1k
  }
98
99
  // Check for slwi/srwi mnemonics.
100
50.9k
  if (MCInst_getOpcode(MI) == PPC_RLWINM) {
101
1.38k
    unsigned char SH = MCOperand_getImm(MCInst_getOperand(MI, (2)));
102
1.38k
    unsigned char MB = MCOperand_getImm(MCInst_getOperand(MI, (3)));
103
1.38k
    unsigned char ME = MCOperand_getImm(MCInst_getOperand(MI, (4)));
104
1.38k
    bool useSubstituteMnemonic = false;
105
1.38k
    if (SH <= 31 && MB == 0 && ME == (31 - SH)) {
106
330
      SStream_concat0(O, "slwi ");
107
330
      useSubstituteMnemonic = true;
108
330
    }
109
1.38k
    if (SH <= 31 && MB == (32 - SH) && ME == 31) {
110
12
      SStream_concat0(O, "srwi ");
111
12
      useSubstituteMnemonic = true;
112
12
      SH = 32 - SH;
113
12
    }
114
1.38k
    useAliasDetails |= map_use_alias_details(MI);
115
1.38k
    map_set_fill_detail_ops(MI, useAliasDetails &&
116
1.38k
                useSubstituteMnemonic);
117
1.38k
    if (useSubstituteMnemonic) {
118
342
      isAlias |= true;
119
342
      MCInst_setIsAlias(MI, isAlias);
120
121
342
      printOperand(MI, 0, O);
122
342
      SStream_concat0(O, ", ");
123
342
      printOperand(MI, 1, O);
124
342
      SStream_concat(O, "%s", ", ");
125
342
      printUInt32(O, (unsigned int)SH);
126
342
      PPC_insert_detail_op_imm_at(MI, 2, SH, CS_AC_READ);
127
128
342
      if (useAliasDetails)
129
342
        return;
130
342
    }
131
1.38k
  }
132
133
50.6k
  if (MCInst_getOpcode(MI) == PPC_RLDICR ||
134
50.6k
      MCInst_getOpcode(MI) == PPC_RLDICR_32) {
135
131
    unsigned char SH = MCOperand_getImm(MCInst_getOperand(MI, (2)));
136
131
    unsigned char ME = MCOperand_getImm(MCInst_getOperand(MI, (3)));
137
138
131
    useAliasDetails |= map_use_alias_details(MI);
139
131
    map_set_fill_detail_ops(MI, useAliasDetails && 63 - SH == ME);
140
    // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH
141
131
    if (63 - SH == ME) {
142
42
      isAlias |= true;
143
42
      MCInst_setIsAlias(MI, isAlias);
144
42
      SStream_concat0(O, "sldi ");
145
42
      printOperand(MI, 0, O);
146
42
      SStream_concat0(O, ", ");
147
42
      printOperand(MI, 1, O);
148
42
      SStream_concat(O, "%s", ", ");
149
42
      printUInt32(O, (unsigned int)SH);
150
42
      PPC_insert_detail_op_imm_at(MI, 2, SH, CS_AC_READ);
151
152
42
      if (useAliasDetails)
153
42
        return;
154
42
    }
155
131
  }
156
157
  // dcbt[st] is printed manually here because:
158
  //  1. The assembly syntax is different between embedded and server targets
159
  //  2. We must print the short mnemonics for TH == 0 because the
160
  //     embedded/server syntax default will not be stable across assemblers
161
  //  The syntax for dcbt is:
162
  //    dcbt ra, rb, th [server]
163
  //    dcbt th, ra, rb [embedded]
164
  //  where th can be omitted when it is 0. dcbtst is the same.
165
  // On AIX, only emit the extended mnemonics for dcbt and dcbtst if
166
  // the "modern assembler" is available.
167
50.5k
  if ((MCInst_getOpcode(MI) == PPC_DCBT ||
168
50.5k
       MCInst_getOpcode(MI) == PPC_DCBTST) &&
169
50.5k
      (!PPC_getFeatureBits(MI->csh->mode, PPC_FeatureModernAIXAs))) {
170
104
    unsigned char TH = MCOperand_getImm(MCInst_getOperand(MI, (0)));
171
104
    SStream_concat0(O, "\tdcbt");
172
104
    if (MCInst_getOpcode(MI) == PPC_DCBTST)
173
34
      SStream_concat0(O, "st");
174
104
    if (TH == 16)
175
21
      SStream_concat0(O, "t");
176
104
    SStream_concat0(O, " ");
177
178
104
    bool IsBookE =
179
104
      PPC_getFeatureBits(MI->csh->mode, PPC_FeatureBookE);
180
104
    if (IsBookE && TH != 0 && TH != 16) {
181
0
      SStream_concat(O, "%s", (unsigned int)TH);
182
0
      SStream_concat0(O, ", ");
183
0
      PPC_set_detail_op_imm(MI, 0, TH);
184
0
    }
185
104
    set_mem_access(MI, true);
186
104
    printOperand(MI, 1, O);
187
104
    SStream_concat0(O, ", ");
188
104
    printOperand(MI, 2, O);
189
104
    set_mem_access(MI, false);
190
191
104
    if (!IsBookE && TH != 0 && TH != 16) {
192
24
      SStream_concat(O, "%s", ", ");
193
24
      printUInt32(O, (unsigned int)TH);
194
24
      PPC_set_detail_op_imm(MI, 0, TH);
195
24
    }
196
197
104
    return;
198
104
  }
199
200
50.4k
  if (MCInst_getOpcode(MI) == PPC_DCBF) {
201
679
    unsigned char L = MCOperand_getImm(MCInst_getOperand(MI, (0)));
202
679
    if (!L || L == 1 || L == 3 || L == 4 || L == 6) {
203
657
      SStream_concat0(O, "\tdcb");
204
657
      if (L != 6)
205
632
        SStream_concat0(O, "f");
206
657
      if (L == 1)
207
17
        SStream_concat0(O, "l");
208
657
      if (L == 3)
209
548
        SStream_concat0(O, "lp");
210
657
      if (L == 4)
211
52
        SStream_concat0(O, "ps");
212
657
      if (L == 6)
213
25
        SStream_concat0(O, "stps");
214
657
      SStream_concat0(O, " ");
215
216
657
      printOperand(MI, 1, O);
217
657
      SStream_concat0(O, ", ");
218
657
      printOperand(MI, 2, O);
219
220
657
      return;
221
657
    }
222
679
  }
223
224
  // isAlias/useAliasDetails could have been set before.
225
49.7k
  useAliasDetails |= map_use_alias_details(MI);
226
49.7k
  map_set_fill_detail_ops(MI, useAliasDetails);
227
49.7k
  isAlias |= printAliasInstr(MI, Address, O);
228
49.7k
  MCInst_setIsAlias(MI, isAlias);
229
230
49.7k
  if (!isAlias || !useAliasDetails) {
231
39.7k
    map_set_fill_detail_ops(MI, true);
232
39.7k
    if (isAlias)
233
0
      SStream_Close(O);
234
39.7k
    printInstruction(MI, Address, O);
235
39.7k
    if (isAlias)
236
0
      SStream_Open(O);
237
39.7k
  }
238
49.7k
}
239
240
void printPredicateOperand(MCInst *MI, unsigned OpNo, SStream *O,
241
         const char *Modifier)
242
0
{
243
0
  add_cs_detail(MI, PPC_OP_GROUP_PredicateOperand, OpNo, Modifier);
244
0
  unsigned Code = MCOperand_getImm(MCInst_getOperand(MI, (OpNo)));
245
246
0
  if (strcmp(Modifier, "cc") == 0) {
247
0
    switch ((PPC_Predicate)Code) {
248
0
    default:
249
0
      assert(0 && "Invalid predicate code");
250
0
    case PPC_PRED_LT_MINUS:
251
0
    case PPC_PRED_LT_PLUS:
252
0
    case PPC_PRED_LT:
253
0
      SStream_concat0(O, "lt");
254
0
      return;
255
0
    case PPC_PRED_LE_MINUS:
256
0
    case PPC_PRED_LE_PLUS:
257
0
    case PPC_PRED_LE:
258
0
      SStream_concat0(O, "le");
259
0
      return;
260
0
    case PPC_PRED_EQ_MINUS:
261
0
    case PPC_PRED_EQ_PLUS:
262
0
    case PPC_PRED_EQ:
263
0
      SStream_concat0(O, "eq");
264
0
      return;
265
0
    case PPC_PRED_GE_MINUS:
266
0
    case PPC_PRED_GE_PLUS:
267
0
    case PPC_PRED_GE:
268
0
      SStream_concat0(O, "ge");
269
0
      return;
270
0
    case PPC_PRED_GT_MINUS:
271
0
    case PPC_PRED_GT_PLUS:
272
0
    case PPC_PRED_GT:
273
0
      SStream_concat0(O, "gt");
274
0
      return;
275
0
    case PPC_PRED_NE_MINUS:
276
0
    case PPC_PRED_NE_PLUS:
277
0
    case PPC_PRED_NE:
278
0
      SStream_concat0(O, "ne");
279
0
      return;
280
0
    case PPC_PRED_UN_MINUS:
281
0
    case PPC_PRED_UN_PLUS:
282
0
    case PPC_PRED_UN:
283
0
      SStream_concat0(O, "un");
284
0
      return;
285
0
    case PPC_PRED_NU_MINUS:
286
0
    case PPC_PRED_NU_PLUS:
287
0
    case PPC_PRED_NU:
288
0
      SStream_concat0(O, "nu");
289
0
      return;
290
0
    case PPC_PRED_BIT_SET:
291
0
    case PPC_PRED_BIT_UNSET:
292
0
      assert(0 && "Invalid use of bit predicate code");
293
0
    }
294
0
    assert(0 && "Invalid predicate code");
295
0
  }
296
297
0
  if (strcmp(Modifier, "pm") == 0) {
298
0
    switch ((PPC_Predicate)Code) {
299
0
    default:
300
0
      assert(0 && "Invalid predicate code");
301
0
    case PPC_PRED_LT:
302
0
    case PPC_PRED_LE:
303
0
    case PPC_PRED_EQ:
304
0
    case PPC_PRED_GE:
305
0
    case PPC_PRED_GT:
306
0
    case PPC_PRED_NE:
307
0
    case PPC_PRED_UN:
308
0
    case PPC_PRED_NU:
309
0
      return;
310
0
    case PPC_PRED_LT_MINUS:
311
0
    case PPC_PRED_LE_MINUS:
312
0
    case PPC_PRED_EQ_MINUS:
313
0
    case PPC_PRED_GE_MINUS:
314
0
    case PPC_PRED_GT_MINUS:
315
0
    case PPC_PRED_NE_MINUS:
316
0
    case PPC_PRED_UN_MINUS:
317
0
    case PPC_PRED_NU_MINUS:
318
0
      SStream_concat0(O, "-");
319
0
      return;
320
0
    case PPC_PRED_LT_PLUS:
321
0
    case PPC_PRED_LE_PLUS:
322
0
    case PPC_PRED_EQ_PLUS:
323
0
    case PPC_PRED_GE_PLUS:
324
0
    case PPC_PRED_GT_PLUS:
325
0
    case PPC_PRED_NE_PLUS:
326
0
    case PPC_PRED_UN_PLUS:
327
0
    case PPC_PRED_NU_PLUS:
328
0
      SStream_concat0(O, "+");
329
0
      return;
330
0
    case PPC_PRED_BIT_SET:
331
0
    case PPC_PRED_BIT_UNSET:
332
0
      assert(0 && "Invalid use of bit predicate code");
333
0
    }
334
0
    assert(0 && "Invalid predicate code");
335
0
  }
336
337
0
  printOperand(MI, OpNo + 1, O);
338
0
}
339
340
void printATBitsAsHint(MCInst *MI, unsigned OpNo, SStream *O)
341
0
{
342
0
  add_cs_detail(MI, PPC_OP_GROUP_ATBitsAsHint, OpNo);
343
0
  unsigned Code = MCOperand_getImm(MCInst_getOperand(MI, (OpNo)));
344
0
  if (Code == 2)
345
0
    SStream_concat0(O, "-");
346
0
  else if (Code == 3)
347
0
    SStream_concat0(O, "+");
348
0
}
349
350
void printU1ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
351
1.13k
{
352
1.13k
  add_cs_detail(MI, PPC_OP_GROUP_U1ImmOperand, OpNo);
353
1.13k
  unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo)));
354
355
1.13k
  printUInt32(O, (unsigned int)Value);
356
1.13k
}
357
358
void printU2ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
359
515
{
360
515
  add_cs_detail(MI, PPC_OP_GROUP_U2ImmOperand, OpNo);
361
515
  unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo)));
362
363
515
  printUInt32(O, (unsigned int)Value);
364
515
}
365
366
void printU3ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
367
1.08k
{
368
1.08k
  add_cs_detail(MI, PPC_OP_GROUP_U3ImmOperand, OpNo);
369
1.08k
  unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo)));
370
371
1.08k
  printUInt32(O, (unsigned int)Value);
372
1.08k
}
373
374
void printU4ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
375
589
{
376
589
  add_cs_detail(MI, PPC_OP_GROUP_U4ImmOperand, OpNo);
377
589
  unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo)));
378
379
589
  printUInt32(O, (unsigned int)Value);
380
589
}
381
382
void printS5ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
383
18
{
384
18
  add_cs_detail(MI, PPC_OP_GROUP_S5ImmOperand, OpNo);
385
18
  int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo)));
386
18
  Value = SignExtend32((Value), 5);
387
18
  printInt32(O, (int)Value);
388
18
}
389
390
void printImmZeroOperand(MCInst *MI, unsigned OpNo, SStream *O)
391
136
{
392
136
  add_cs_detail(MI, PPC_OP_GROUP_ImmZeroOperand, OpNo);
393
136
  unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo)));
394
395
136
  printUInt32(O, (unsigned int)Value);
396
136
}
397
398
void printU5ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
399
11.0k
{
400
11.0k
  add_cs_detail(MI, PPC_OP_GROUP_U5ImmOperand, OpNo);
401
11.0k
  unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo)));
402
403
11.0k
  printUInt32(O, (unsigned int)Value);
404
11.0k
}
405
406
void printU6ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
407
1.08k
{
408
1.08k
  add_cs_detail(MI, PPC_OP_GROUP_U6ImmOperand, OpNo);
409
1.08k
  unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo)));
410
411
1.08k
  printUInt32(O, (unsigned int)Value);
412
1.08k
}
413
414
void printU7ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
415
93
{
416
93
  add_cs_detail(MI, PPC_OP_GROUP_U7ImmOperand, OpNo);
417
93
  unsigned int Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo)));
418
419
93
  printUInt32(O, (unsigned int)Value);
420
93
}
421
422
// Operands of BUILD_VECTOR are signed and we use this to print operands
423
// of XXSPLTIB which are unsigned. So we simply truncate to 8 bits and
424
// print as unsigned.
425
void printU8ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
426
88
{
427
88
  add_cs_detail(MI, PPC_OP_GROUP_U8ImmOperand, OpNo);
428
88
  unsigned char Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo)));
429
88
  printUInt32(O, (unsigned int)Value);
430
88
}
431
432
void printU10ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
433
19
{
434
19
  add_cs_detail(MI, PPC_OP_GROUP_U10ImmOperand, OpNo);
435
19
  unsigned short Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo)));
436
437
19
  printUInt32(O, (unsigned short)Value);
438
19
}
439
440
void printU12ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
441
519
{
442
519
  add_cs_detail(MI, PPC_OP_GROUP_U12ImmOperand, OpNo);
443
519
  unsigned short Value = MCOperand_getImm(MCInst_getOperand(MI, (OpNo)));
444
445
519
  printUInt32(O, (unsigned short)Value);
446
519
}
447
448
void printS12ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
449
885
{
450
885
  add_cs_detail(MI, PPC_OP_GROUP_S12ImmOperand, OpNo);
451
885
  if (MCOperand_isImm(MCInst_getOperand(MI, OpNo))) {
452
885
    int Imm = (int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
453
885
    Imm = SignExtend32(Imm, 12);
454
885
    printInt32(O, Imm);
455
885
  } else
456
0
    printOperand(MI, OpNo, O);
457
885
}
458
459
void printMemRegImmPS(MCInst *MI, unsigned OpNo, SStream *O)
460
885
{
461
885
  set_mem_access(MI, true);
462
463
885
  printS12ImmOperand(MI, OpNo, O);
464
885
  SStream_concat0(O, "(");
465
885
  printOperand(MI, OpNo + 1, O);
466
885
  SStream_concat0(O, ")");
467
468
885
  set_mem_access(MI, false);
469
885
}
470
471
void printS16ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
472
17.2k
{
473
17.2k
  add_cs_detail(MI, PPC_OP_GROUP_S16ImmOperand, OpNo);
474
17.2k
  if (MCOperand_isImm(MCInst_getOperand(MI, (OpNo))))
475
17.2k
    printInt32(O, (short)MCOperand_getImm(
476
17.2k
              MCInst_getOperand(MI, (OpNo))));
477
0
  else
478
0
    printOperand(MI, OpNo, O);
479
17.2k
}
480
481
void printS34ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
482
246
{
483
246
  add_cs_detail(MI, PPC_OP_GROUP_S34ImmOperand, OpNo);
484
246
  if (MCOperand_isImm(MCInst_getOperand(MI, (OpNo)))) {
485
246
    long long Value =
486
246
      MCOperand_getImm(MCInst_getOperand(MI, (OpNo)));
487
488
246
    printInt64(O, (long long)Value);
489
246
  } else
490
0
    printOperand(MI, OpNo, O);
491
246
}
492
493
void printU16ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
494
4.99k
{
495
4.99k
  add_cs_detail(MI, PPC_OP_GROUP_U16ImmOperand, OpNo);
496
4.99k
  if (MCOperand_isImm(MCInst_getOperand(MI, (OpNo))))
497
4.99k
    printUInt32(O, (unsigned short)MCOperand_getImm(
498
4.99k
               MCInst_getOperand(MI, (OpNo))));
499
0
  else
500
0
    printOperand(MI, OpNo, O);
501
4.99k
}
502
503
void printBranchOperand(MCInst *MI, uint64_t Address, unsigned OpNo, SStream *O)
504
5.67k
{
505
5.67k
  add_cs_detail(MI, PPC_OP_GROUP_BranchOperand, OpNo);
506
5.67k
  if (!MCOperand_isImm(MCInst_getOperand(MI, (OpNo))))
507
0
    return printOperand(MI, OpNo, O);
508
5.67k
  int32_t Imm = SignExtend32(
509
5.67k
    ((unsigned)MCOperand_getImm(MCInst_getOperand(MI, (OpNo)))
510
5.67k
     << 2),
511
5.67k
    32);
512
5.67k
  if (!MI->csh->PrintBranchImmNotAsAddress) {
513
5.67k
    uint64_t Target = Address + Imm;
514
5.67k
    if (!IS_64BIT(MI->csh->mode))
515
1.27k
      Target &= 0xffffffff;
516
5.67k
    printUInt64(O, (Target));
517
5.67k
  } else {
518
    // Branches can take an immediate operand. This is used by the branch
519
    // selection pass to print, for example `.+8` (for ELF) or `$+8` (for
520
    // AIX) to express an eight byte displacement from the program counter.
521
0
    if (!PPC_getFeatureBits(MI->csh->mode, PPC_FeatureModernAIXAs))
522
0
      SStream_concat0(O, ".");
523
0
    else
524
0
      SStream_concat0(O, "$");
525
526
0
    if (Imm >= 0)
527
0
      SStream_concat0(O, "+");
528
0
    printInt32(O, Imm);
529
0
  }
530
5.67k
}
531
532
void printAbsBranchOperand(MCInst *MI, unsigned OpNo, SStream *O)
533
2.51k
{
534
2.51k
  add_cs_detail(MI, PPC_OP_GROUP_AbsBranchOperand, OpNo);
535
2.51k
  if (!MCOperand_isImm(MCInst_getOperand(MI, (OpNo))))
536
0
    return printOperand(MI, OpNo, O);
537
538
2.51k
  printInt32(O, SignExtend32(((unsigned)MCOperand_getImm(
539
2.51k
              MCInst_getOperand(MI, (OpNo)))
540
2.51k
            << 2),
541
2.51k
           32));
542
2.51k
}
543
544
void printcrbitm(MCInst *MI, unsigned OpNo, SStream *O)
545
46
{
546
46
  add_cs_detail(MI, PPC_OP_GROUP_crbitm, OpNo);
547
46
  unsigned CCReg = MCOperand_getReg(MCInst_getOperand(MI, (OpNo)));
548
46
  unsigned RegNo;
549
46
  switch (CCReg) {
550
0
  default:
551
0
    assert(0 && "Unknown CR register");
552
15
  case PPC_CR0:
553
15
    RegNo = 0;
554
15
    break;
555
0
  case PPC_CR1:
556
0
    RegNo = 1;
557
0
    break;
558
0
  case PPC_CR2:
559
0
    RegNo = 2;
560
0
    break;
561
11
  case PPC_CR3:
562
11
    RegNo = 3;
563
11
    break;
564
0
  case PPC_CR4:
565
0
    RegNo = 4;
566
0
    break;
567
18
  case PPC_CR5:
568
18
    RegNo = 5;
569
18
    break;
570
0
  case PPC_CR6:
571
0
    RegNo = 6;
572
0
    break;
573
2
  case PPC_CR7:
574
2
    RegNo = 7;
575
2
    break;
576
46
  }
577
46
  printUInt32(O, (0x80 >> RegNo));
578
46
}
579
580
void printMemRegImm(MCInst *MI, unsigned OpNo, SStream *O)
581
12.0k
{
582
12.0k
  set_mem_access(MI, true);
583
12.0k
  add_cs_detail(MI, PPC_OP_GROUP_MemRegImm, OpNo);
584
12.0k
  printS16ImmOperand(MI, OpNo, O);
585
12.0k
  SStream_concat0(O, "(");
586
587
12.0k
  if (MCOperand_getReg(MCInst_getOperand(MI, (OpNo + 1))) == PPC_R0)
588
0
    SStream_concat0(O, "0");
589
12.0k
  else
590
12.0k
    printOperand(MI, OpNo + 1, O);
591
12.0k
  SStream_concat0(O, ")");
592
12.0k
  set_mem_access(MI, false);
593
12.0k
}
594
595
void printMemRegImmHash(MCInst *MI, unsigned OpNo, SStream *O)
596
78
{
597
78
  set_mem_access(MI, true);
598
78
  add_cs_detail(MI, PPC_OP_GROUP_MemRegImmHash, OpNo);
599
78
  printInt32(O, MCOperand_getImm(MCInst_getOperand(MI, (OpNo))));
600
78
  SStream_concat0(O, "(");
601
602
78
  printOperand(MI, OpNo + 1, O);
603
78
  SStream_concat0(O, ")");
604
78
  set_mem_access(MI, false);
605
78
}
606
607
void printMemRegImm34PCRel(MCInst *MI, unsigned OpNo, SStream *O)
608
126
{
609
126
  set_mem_access(MI, true);
610
126
  add_cs_detail(MI, PPC_OP_GROUP_MemRegImm34PCRel, OpNo);
611
126
  printS34ImmOperand(MI, OpNo, O);
612
126
  SStream_concat0(O, "(");
613
614
126
  printImmZeroOperand(MI, OpNo + 1, O);
615
126
  SStream_concat0(O, ")");
616
126
  set_mem_access(MI, false);
617
126
}
618
619
void printMemRegImm34(MCInst *MI, unsigned OpNo, SStream *O)
620
89
{
621
89
  set_mem_access(MI, true);
622
89
  add_cs_detail(MI, PPC_OP_GROUP_MemRegImm34, OpNo);
623
89
  printS34ImmOperand(MI, OpNo, O);
624
89
  SStream_concat0(O, "(");
625
626
89
  printOperand(MI, OpNo + 1, O);
627
89
  SStream_concat0(O, ")");
628
89
  set_mem_access(MI, false);
629
89
}
630
631
void printMemRegReg(MCInst *MI, unsigned OpNo, SStream *O)
632
1.73k
{
633
1.73k
  set_mem_access(MI, true);
634
1.73k
  add_cs_detail(MI, PPC_OP_GROUP_MemRegReg, OpNo);
635
  // When used as the base register, r0 reads constant zero rather than
636
  // the value contained in the register.  For this reason, the darwin
637
  // assembler requires that we print r0 as 0 (no r) when used as the base.
638
1.73k
  if (MCOperand_getReg(MCInst_getOperand(MI, (OpNo))) == PPC_R0)
639
0
    SStream_concat0(O, "0");
640
1.73k
  else
641
1.73k
    printOperand(MI, OpNo, O);
642
1.73k
  SStream_concat0(O, ", ");
643
1.73k
  printOperand(MI, OpNo + 1, O);
644
1.73k
  set_mem_access(MI, false);
645
1.73k
}
646
647
void printTLSCall(MCInst *MI, unsigned OpNo, SStream *O)
648
0
{
649
0
  add_cs_detail(MI, PPC_OP_GROUP_TLSCall, OpNo);
650
651
  // Expresion logic removed.
652
653
0
  set_mem_access(MI, true);
654
0
  SStream_concat0(O, "(");
655
656
0
  printOperand(MI, OpNo + 1, O);
657
0
  SStream_concat0(O, ")");
658
0
  set_mem_access(MI, false);
659
0
}
660
661
/// showRegistersWithPercentPrefix - Check if this register name should be
662
/// printed with a percentage symbol as prefix.
663
bool showRegistersWithPercentPrefix(const MCInst *MI, const char *RegName)
664
99.8k
{
665
99.8k
  if ((MI->csh->syntax & CS_OPT_SYNTAX_NOREGNAME) ||
666
99.8k
      !(MI->csh->syntax & CS_OPT_SYNTAX_PERCENT) ||
667
99.8k
      PPC_getFeatureBits(MI->csh->mode, PPC_FeatureModernAIXAs))
668
99.8k
    return false;
669
670
0
  switch (RegName[0]) {
671
0
  default:
672
0
    return false;
673
0
  case 'r':
674
0
  case 'f':
675
0
  case 'q':
676
0
  case 'v':
677
0
  case 'c':
678
0
    return true;
679
0
  }
680
0
}
681
682
/// getVerboseConditionalRegName - This method expands the condition register
683
/// when requested explicitly or targetting Darwin.
684
const char *getVerboseConditionRegName(const MCInst *MI, unsigned RegNum,
685
               unsigned RegEncoding)
686
99.8k
{
687
99.8k
  if (MI->csh->syntax & CS_OPT_SYNTAX_NOREGNAME)
688
0
    return NULL;
689
99.8k
  if (RegNum < PPC_CR0EQ || RegNum > PPC_CR7UN)
690
91.9k
    return NULL;
691
7.88k
  const char *CRBits[] = {
692
7.88k
    "lt",     "gt", "eq",     "un", "4*cr1+lt",
693
7.88k
    "4*cr1+gt", "4*cr1+eq", "4*cr1+un", "4*cr2+lt", "4*cr2+gt",
694
7.88k
    "4*cr2+eq", "4*cr2+un", "4*cr3+lt", "4*cr3+gt", "4*cr3+eq",
695
7.88k
    "4*cr3+un", "4*cr4+lt", "4*cr4+gt", "4*cr4+eq", "4*cr4+un",
696
7.88k
    "4*cr5+lt", "4*cr5+gt", "4*cr5+eq", "4*cr5+un", "4*cr6+lt",
697
7.88k
    "4*cr6+gt", "4*cr6+eq", "4*cr6+un", "4*cr7+lt", "4*cr7+gt",
698
7.88k
    "4*cr7+eq", "4*cr7+un"
699
7.88k
  };
700
7.88k
  return CRBits[RegEncoding];
701
99.8k
}
702
703
// showRegistersWithPrefix - This method determines whether registers
704
// should be number-only or include the prefix.
705
bool showRegistersWithPrefix(const MCInst *MI)
706
99.8k
{
707
99.8k
  return !(MI->csh->syntax & CS_OPT_SYNTAX_NOREGNAME);
708
99.8k
}
709
710
void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
711
100k
{
712
100k
  add_cs_detail(MI, PPC_OP_GROUP_Operand, OpNo);
713
100k
  MCOperand *Op = MCInst_getOperand(MI, (OpNo));
714
100k
  if (MCOperand_isReg(Op)) {
715
99.8k
    unsigned Reg = MCOperand_getReg(Op);
716
99.8k
    if (!MI->csh->ShowVSRNumsAsVR)
717
99.8k
      Reg = PPCInstrInfo_getRegNumForOperand(
718
99.8k
        &PPCInsts[MCInst_getOpcode(MI)], Reg, OpNo);
719
720
99.8k
    const char *RegName;
721
99.8k
    RegName = getVerboseConditionRegName(
722
99.8k
      MI, Reg, MI->MRI->RegEncodingTable[Reg]);
723
99.8k
    if (RegName == NULL)
724
91.9k
      RegName = getRegisterName(Reg);
725
99.8k
    if (showRegistersWithPercentPrefix(MI, RegName))
726
0
      SStream_concat0(O, "%");
727
99.8k
    if (!showRegistersWithPrefix(MI))
728
0
      RegName = PPCRegisterInfo_stripRegisterPrefix(RegName);
729
730
99.8k
    SStream_concat0(O, RegName);
731
99.8k
    return;
732
99.8k
  }
733
734
656
  if (MCOperand_isImm(Op)) {
735
656
    printInt64(O, MCOperand_getImm(Op));
736
656
    return;
737
656
  }
738
656
}
739
740
const char *PPC_LLVM_getRegisterName(unsigned RegNo)
741
36.6k
{
742
36.6k
  return getRegisterName(RegNo);
743
36.6k
}
744
745
void PPC_LLVM_printInst(MCInst *MI, uint64_t Address, const char *Annot,
746
      SStream *O)
747
50.9k
{
748
50.9k
  printInst(MI, Address, Annot, O);
749
50.9k
}