Coverage Report

Created: 2025-07-01 07:03

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