Coverage Report

Created: 2024-08-21 06:24

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