Rizin
unix-like reverse engineering framework and cli tools
PPCInstPrinter.c
Go to the documentation of this file.
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, const MCRegisterInfo *MRI);
38 static void printAbsBranchOperand(MCInst *MI, unsigned OpNo, SStream *O);
39 static char *printAliasInstr(MCInst *MI, SStream *OS, void *info);
40 static char *printAliasInstrEx(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 {
62  if (MI->csh->detail != CS_OPT_ON)
63  return;
64 
65  MI->csh->doing_mem = status;
66 
67  if (status) {
68  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_MEM;
69  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].mem.base = PPC_REG_INVALID;
70  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].mem.disp = 0;
71  } else {
72  // done, create the next operand slot
73  MI->flat_insn->detail->ppc.op_count++;
74  }
75 }
76 
77 void PPC_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
78 {
79  if (((cs_struct *)ud)->detail != CS_OPT_ON)
80  return;
81 
82  // check if this insn has branch hint
83  if (strrchr(insn_asm, '+') != NULL && !strstr(insn_asm, ".+")) {
84  insn->detail->ppc.bh = PPC_BH_PLUS;
85  } else if (strrchr(insn_asm, '-') != NULL) {
86  insn->detail->ppc.bh = PPC_BH_MINUS;
87  }
88 }
89 
90 #define GET_INSTRINFO_ENUM
91 #include "PPCGenInstrInfo.inc"
92 
93 static int isBOCTRBranch(unsigned int op)
94 {
95  return ((op >= PPC_BDNZ) && (op <= PPC_BDZp));
96 }
97 
98 void PPC_printInst(MCInst *MI, SStream *O, void *Info)
99 {
100  char *mnem;
101 
102  // Check for slwi/srwi mnemonics.
103  if (MCInst_getOpcode(MI) == PPC_RLWINM) {
104  unsigned char SH = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 2));
105  unsigned char MB = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 3));
106  unsigned char ME = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 4));
107  bool useSubstituteMnemonic = false;
108 
109  if (SH <= 31 && MB == 0 && ME == (31-SH)) {
110  SStream_concat0(O, "slwi\t");
112  useSubstituteMnemonic = true;
113  }
114 
115  if (SH <= 31 && MB == (32-SH) && ME == 31) {
116  SStream_concat0(O, "srwi\t");
118  useSubstituteMnemonic = true;
119  SH = 32-SH;
120  }
121 
122  if (useSubstituteMnemonic) {
123  printOperand(MI, 0, O);
124  SStream_concat0(O, ", ");
125  printOperand(MI, 1, O);
126  if (SH > HEX_THRESHOLD)
127  SStream_concat(O, ", 0x%x", (unsigned int)SH);
128  else
129  SStream_concat(O, ", %u", (unsigned int)SH);
130 
131  if (MI->csh->detail) {
132  cs_ppc *ppc = &MI->flat_insn->detail->ppc;
133 
134  ppc->operands[ppc->op_count].type = PPC_OP_IMM;
135  ppc->operands[ppc->op_count].imm = SH;
136  ++ppc->op_count;
137  }
138 
139  return;
140  }
141  }
142 
143  if ((MCInst_getOpcode(MI) == PPC_OR || MCInst_getOpcode(MI) == PPC_OR8) &&
145  SStream_concat0(O, "mr\t");
147  printOperand(MI, 0, O);
148  SStream_concat0(O, ", ");
149  printOperand(MI, 1, O);
150  return;
151  }
152 
153  if (MCInst_getOpcode(MI) == PPC_RLDICR) {
154  unsigned char SH = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 2));
155  unsigned char ME = (unsigned char)MCOperand_getImm(MCInst_getOperand(MI, 3));
156  // rldicr RA, RS, SH, 63-SH == sldi RA, RS, SH
157  if (63-SH == ME) {
158  SStream_concat0(O, "sldi\t");
160  printOperand(MI, 0, O);
161  SStream_concat0(O, ", ");
162  printOperand(MI, 1, O);
163  if (SH > HEX_THRESHOLD)
164  SStream_concat(O, ", 0x%x", (unsigned int)SH);
165  else
166  SStream_concat(O, ", %u", (unsigned int)SH);
167 
168  return;
169  }
170  }
171 
172  if ((MCInst_getOpcode(MI) == PPC_gBC)||(MCInst_getOpcode(MI) == PPC_gBCA)||
173  (MCInst_getOpcode(MI) == PPC_gBCL)||(MCInst_getOpcode(MI) == PPC_gBCLA)) {
175  bd = SignExtend64(bd, 14);
177  }
178 
179  if (isBOCTRBranch(MCInst_getOpcode(MI))) {
180  if (MCOperand_isImm(MCInst_getOperand(MI,0))) {
182  bd = SignExtend64(bd, 14);
184  }
185  }
186 
187  if ((MCInst_getOpcode(MI) == PPC_B)||(MCInst_getOpcode(MI) == PPC_BA)||
188  (MCInst_getOpcode(MI) == PPC_BL)||(MCInst_getOpcode(MI) == PPC_BLA)) {
190  bd = SignExtend64(bd, 24);
192  }
193 
194  // consider our own alias instructions first
195  mnem = printAliasInstrEx(MI, O, Info);
196  if (!mnem)
197  mnem = printAliasInstr(MI, O, Info);
198 
199  if (mnem != NULL) {
200  if (strlen(mnem) > 0) {
201  // check to remove the last letter of ('.', '-', '+')
202  if (mnem[strlen(mnem) - 1] == '-' || mnem[strlen(mnem) - 1] == '+' || mnem[strlen(mnem) - 1] == '.')
203  mnem[strlen(mnem) - 1] = '\0';
204 
206 
207  if (MI->csh->detail) {
208  struct ppc_alias alias;
209 
210  if (PPC_alias_insn(mnem, &alias)) {
211  MI->flat_insn->detail->ppc.bc = (ppc_bc)alias.cc;
212  }
213  }
214  }
215 
216  cs_mem_free(mnem);
217  } else
218  printInstruction(MI, O, NULL);
219 }
220 
221 enum ppc_bc_hint {
222  PPC_BC_LT_MINUS = (0 << 5) | 14,
223  PPC_BC_LE_MINUS = (1 << 5) | 6,
224  PPC_BC_EQ_MINUS = (2 << 5) | 14,
225  PPC_BC_GE_MINUS = (0 << 5) | 6,
226  PPC_BC_GT_MINUS = (1 << 5) | 14,
227  PPC_BC_NE_MINUS = (2 << 5) | 6,
228  PPC_BC_UN_MINUS = (3 << 5) | 14,
229  PPC_BC_NU_MINUS = (3 << 5) | 6,
230  PPC_BC_LT_PLUS = (0 << 5) | 15,
231  PPC_BC_LE_PLUS = (1 << 5) | 7,
232  PPC_BC_EQ_PLUS = (2 << 5) | 15,
233  PPC_BC_GE_PLUS = (0 << 5) | 7,
234  PPC_BC_GT_PLUS = (1 << 5) | 15,
235  PPC_BC_NE_PLUS = (2 << 5) | 7,
236  PPC_BC_UN_PLUS = (3 << 5) | 15,
237  PPC_BC_NU_PLUS = (3 << 5) | 7,
238 };
239 
240 // normalize CC to remove _MINUS & _PLUS
241 static int cc_normalize(int cc)
242 {
243  switch(cc) {
244  default: return cc;
245  case PPC_BC_LT_MINUS: return PPC_BC_LT;
246  case PPC_BC_LE_MINUS: return PPC_BC_LE;
247  case PPC_BC_EQ_MINUS: return PPC_BC_EQ;
248  case PPC_BC_GE_MINUS: return PPC_BC_GE;
249  case PPC_BC_GT_MINUS: return PPC_BC_GT;
250  case PPC_BC_NE_MINUS: return PPC_BC_NE;
251  case PPC_BC_UN_MINUS: return PPC_BC_UN;
252  case PPC_BC_NU_MINUS: return PPC_BC_NU;
253  case PPC_BC_LT_PLUS : return PPC_BC_LT;
254  case PPC_BC_LE_PLUS : return PPC_BC_LE;
255  case PPC_BC_EQ_PLUS : return PPC_BC_EQ;
256  case PPC_BC_GE_PLUS : return PPC_BC_GE;
257  case PPC_BC_GT_PLUS : return PPC_BC_GT;
258  case PPC_BC_NE_PLUS : return PPC_BC_NE;
259  case PPC_BC_UN_PLUS : return PPC_BC_UN;
260  case PPC_BC_NU_PLUS : return PPC_BC_NU;
261  }
262 }
263 
264 static void printPredicateOperand(MCInst *MI, unsigned OpNo,
265  SStream *O, const char *Modifier)
266 {
267  unsigned Code = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
268 
269  MI->flat_insn->detail->ppc.bc = (ppc_bc)cc_normalize(Code);
270 
271  if (!strcmp(Modifier, "cc")) {
272  switch ((ppc_predicate)Code) {
273  default: // unreachable
274  case PPC_PRED_LT_MINUS:
275  case PPC_PRED_LT_PLUS:
276  case PPC_PRED_LT:
277  SStream_concat0(O, "lt");
278  return;
279  case PPC_PRED_LE_MINUS:
280  case PPC_PRED_LE_PLUS:
281  case PPC_PRED_LE:
282  SStream_concat0(O, "le");
283  return;
284  case PPC_PRED_EQ_MINUS:
285  case PPC_PRED_EQ_PLUS:
286  case PPC_PRED_EQ:
287  SStream_concat0(O, "eq");
288  return;
289  case PPC_PRED_GE_MINUS:
290  case PPC_PRED_GE_PLUS:
291  case PPC_PRED_GE:
292  SStream_concat0(O, "ge");
293  return;
294  case PPC_PRED_GT_MINUS:
295  case PPC_PRED_GT_PLUS:
296  case PPC_PRED_GT:
297  SStream_concat0(O, "gt");
298  return;
299  case PPC_PRED_NE_MINUS:
300  case PPC_PRED_NE_PLUS:
301  case PPC_PRED_NE:
302  SStream_concat0(O, "ne");
303  return;
304  case PPC_PRED_UN_MINUS:
305  case PPC_PRED_UN_PLUS:
306  case PPC_PRED_UN:
307  SStream_concat0(O, "un");
308  return;
309  case PPC_PRED_NU_MINUS:
310  case PPC_PRED_NU_PLUS:
311  case PPC_PRED_NU:
312  SStream_concat0(O, "nu");
313  return;
314  case PPC_PRED_BIT_SET:
315  case PPC_PRED_BIT_UNSET:
316  // llvm_unreachable("Invalid use of bit predicate code");
317  SStream_concat0(O, "invalid-predicate");
318  return;
319  }
320  }
321 
322  if (!strcmp(Modifier, "pm")) {
323  switch ((ppc_predicate)Code) {
324  case PPC_PRED_LT:
325  case PPC_PRED_LE:
326  case PPC_PRED_EQ:
327  case PPC_PRED_GE:
328  case PPC_PRED_GT:
329  case PPC_PRED_NE:
330  case PPC_PRED_UN:
331  case PPC_PRED_NU:
332  return;
333  case PPC_PRED_LT_MINUS:
334  case PPC_PRED_LE_MINUS:
335  case PPC_PRED_EQ_MINUS:
336  case PPC_PRED_GE_MINUS:
337  case PPC_PRED_GT_MINUS:
338  case PPC_PRED_NE_MINUS:
339  case PPC_PRED_UN_MINUS:
340  case PPC_PRED_NU_MINUS:
341  SStream_concat0(O, "-");
342  return;
343  case PPC_PRED_LT_PLUS:
344  case PPC_PRED_LE_PLUS:
345  case PPC_PRED_EQ_PLUS:
346  case PPC_PRED_GE_PLUS:
347  case PPC_PRED_GT_PLUS:
348  case PPC_PRED_NE_PLUS:
349  case PPC_PRED_UN_PLUS:
350  case PPC_PRED_NU_PLUS:
351  SStream_concat0(O, "+");
352  return;
353  case PPC_PRED_BIT_SET:
354  case PPC_PRED_BIT_UNSET:
355  // llvm_unreachable("Invalid use of bit predicate code");
356  SStream_concat0(O, "invalid-predicate");
357  return;
358  default: // unreachable
359  return;
360  }
361  // llvm_unreachable("Invalid predicate code");
362  }
363 
364  //assert(StringRef(Modifier) == "reg" &&
365  // "Need to specify 'cc', 'pm' or 'reg' as predicate op modifier!");
366  printOperand(MI, OpNo + 1, O);
367 }
368 
369 static void printU2ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
370 {
371  unsigned int Value = (int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
372  //assert(Value <= 3 && "Invalid u2imm argument!");
373 
374  if (Value > HEX_THRESHOLD)
375  SStream_concat(O, "0x%x", Value);
376  else
377  SStream_concat(O, "%u", Value);
378 
379  if (MI->csh->detail) {
380  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
381  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
382  MI->flat_insn->detail->ppc.op_count++;
383  }
384 }
385 
386 static void printU4ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
387 {
388  unsigned int Value = (int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
389  //assert(Value <= 15 && "Invalid u4imm argument!");
390 
391  if (Value > HEX_THRESHOLD)
392  SStream_concat(O, "0x%x", Value);
393  else
394  SStream_concat(O, "%u", Value);
395 
396  if (MI->csh->detail) {
397  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
398  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
399  MI->flat_insn->detail->ppc.op_count++;
400  }
401 }
402 
403 static void printS5ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
404 {
405  int Value = (int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
406  Value = SignExtend32(Value, 5);
407 
408  printInt32(O, Value);
409 
410  if (MI->csh->detail) {
411  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
412  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
413  MI->flat_insn->detail->ppc.op_count++;
414  }
415 }
416 
417 static void printU5ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
418 {
419  unsigned int Value = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
420  //assert(Value <= 31 && "Invalid u5imm argument!");
421  printUInt32(O, Value);
422 
423  if (MI->csh->detail) {
424  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
425  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
426  MI->flat_insn->detail->ppc.op_count++;
427  }
428 }
429 
430 static void printU6ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
431 {
432  unsigned int Value = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
433  //assert(Value <= 63 && "Invalid u6imm argument!");
434  printUInt32(O, Value);
435 
436  if (MI->csh->detail) {
437  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
438  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
439  MI->flat_insn->detail->ppc.op_count++;
440  }
441 }
442 
443 static void printU12ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
444 {
445  unsigned short Value = (unsigned short)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
446 
447  // assert(Value <= 4095 && "Invalid u12imm argument!");
448 
449  if (Value > HEX_THRESHOLD)
450  SStream_concat(O, "0x%x", Value);
451  else
452  SStream_concat(O, "%u", Value);
453 
454  if (MI->csh->detail) {
455  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
456  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Value;
457  MI->flat_insn->detail->ppc.op_count++;
458  }
459 }
460 
461 static void printS16ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
462 {
463  if (MCOperand_isImm(MCInst_getOperand(MI, OpNo))) {
464  unsigned short Imm = (unsigned short)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
465  if (Imm > HEX_THRESHOLD)
466  SStream_concat(O, "0x%x", Imm);
467  else
468  SStream_concat(O, "%u", Imm);
469 
470  if (MI->csh->detail) {
471  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
472  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Imm;
473  MI->flat_insn->detail->ppc.op_count++;
474  }
475  } else
476  printOperand(MI, OpNo, O);
477 }
478 
479 static void printS16ImmOperand_Mem(MCInst *MI, unsigned OpNo, SStream *O)
480 {
481  if (MCOperand_isImm(MCInst_getOperand(MI, OpNo))) {
482  short Imm = (short)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
483 
484  if (Imm >= 0) {
485  if (Imm > HEX_THRESHOLD)
486  SStream_concat(O, "0x%x", Imm);
487  else
488  SStream_concat(O, "%u", Imm);
489  } else {
490  if (Imm < -HEX_THRESHOLD)
491  SStream_concat(O, "-0x%x", -Imm);
492  else
493  SStream_concat(O, "-%u", -Imm);
494  }
495 
496  if (MI->csh->detail) {
497  if (MI->csh->doing_mem) {
498  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].mem.disp = Imm;
499  } else {
500  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
501  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Imm;
502  MI->flat_insn->detail->ppc.op_count++;
503  }
504  }
505  } else
506  printOperand(MI, OpNo, O);
507 }
508 
509 static void printU16ImmOperand(MCInst *MI, unsigned OpNo, SStream *O)
510 {
511  if (MCOperand_isImm(MCInst_getOperand(MI, OpNo))) {
512  unsigned short Imm = (unsigned short)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
513  if (Imm > HEX_THRESHOLD)
514  SStream_concat(O, "0x%x", Imm);
515  else
516  SStream_concat(O, "%u", Imm);
517 
518  if (MI->csh->detail) {
519  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
520  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = Imm;
521  MI->flat_insn->detail->ppc.op_count++;
522  }
523  } else
524  printOperand(MI, OpNo, O);
525 }
526 
527 static void printBranchOperand(MCInst *MI, unsigned OpNo, SStream *O)
528 {
529  if (!MCOperand_isImm(MCInst_getOperand(MI, OpNo))) {
530  printOperand(MI, OpNo, O);
531  return;
532  }
533 
534  // Branches can take an immediate operand. This is used by the branch
535  // selection pass to print .+8, an eight byte displacement from the PC.
536  printAbsBranchOperand(MI, OpNo, O);
537 }
538 
539 static void printAbsBranchOperand(MCInst *MI, unsigned OpNo, SStream *O)
540 {
541  int64_t imm;
542 
543  if (!MCOperand_isImm(MCInst_getOperand(MI, OpNo))) {
544  printOperand(MI, OpNo, O);
545  return;
546  }
547 
548  imm = MCOperand_getImm(MCInst_getOperand(MI, OpNo)) * 4;
549 
550  if (!PPC_abs_branch(MI->csh, MCInst_getOpcode(MI))) {
551  imm = MI->address + imm;
552  }
553 
554  SStream_concat(O, "0x%"PRIx64, imm);
555 
556  if (MI->csh->detail) {
557  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
558  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = imm;
559  MI->flat_insn->detail->ppc.op_count++;
560  }
561 }
562 
563 
564 #define GET_REGINFO_ENUM
565 #include "PPCGenRegisterInfo.inc"
566 
567 static void printcrbitm(MCInst *MI, unsigned OpNo, SStream *O)
568 {
569  unsigned RegNo, tmp;
570  unsigned CCReg = MCOperand_getReg(MCInst_getOperand(MI, OpNo));
571 
572  switch (CCReg) {
573  default: // llvm_unreachable("Unknown CR register");
574  case PPC_CR0: RegNo = 0; break;
575  case PPC_CR1: RegNo = 1; break;
576  case PPC_CR2: RegNo = 2; break;
577  case PPC_CR3: RegNo = 3; break;
578  case PPC_CR4: RegNo = 4; break;
579  case PPC_CR5: RegNo = 5; break;
580  case PPC_CR6: RegNo = 6; break;
581  case PPC_CR7: RegNo = 7; break;
582  }
583 
584  tmp = 0x80 >> RegNo;
585  if (tmp > HEX_THRESHOLD)
586  SStream_concat(O, "0x%x", tmp);
587  else
588  SStream_concat(O, "%u", tmp);
589 }
590 
591 static void printMemRegImm(MCInst *MI, unsigned OpNo, SStream *O)
592 {
593  set_mem_access(MI, true);
594 
595  printS16ImmOperand_Mem(MI, OpNo, O);
596 
597  SStream_concat0(O, "(");
598 
599  if (MCOperand_getReg(MCInst_getOperand(MI, OpNo + 1)) == PPC_R0)
600  SStream_concat0(O, "0");
601  else
602  printOperand(MI, OpNo + 1, O);
603 
604  SStream_concat0(O, ")");
605  set_mem_access(MI, false);
606 }
607 
608 static void printMemRegReg(MCInst *MI, unsigned OpNo, SStream *O)
609 {
610  // When used as the base register, r0 reads constant zero rather than
611  // the value contained in the register. For this reason, the darwin
612  // assembler requires that we print r0 as 0 (no r) when used as the base.
613  if (MCOperand_getReg(MCInst_getOperand(MI, OpNo)) == PPC_R0)
614  SStream_concat0(O, "0");
615  else
616  printOperand(MI, OpNo, O);
617  SStream_concat0(O, ", ");
618 
619  printOperand(MI, OpNo + 1, O);
620 }
621 
622 static void printTLSCall(MCInst *MI, unsigned OpNo, SStream *O)
623 {
624  set_mem_access(MI, true);
625  //printBranchOperand(MI, OpNo, O);
626 
627  // On PPC64, VariantKind is VK_None, but on PPC32, it's VK_PLT, and it must
628  // come at the _end_ of the expression.
629 
630  SStream_concat0(O, "(");
631  printOperand(MI, OpNo + 1, O);
632  SStream_concat0(O, ")");
633  set_mem_access(MI, false);
634 }
635 
636 #ifndef CAPSTONE_DIET
639 static const char *stripRegisterPrefix(const char *RegName)
640 {
641  switch (RegName[0]) {
642  case 'r':
643  case 'f':
644  case 'q': // for QPX
645  case 'v':
646  if (RegName[1] == 's')
647  return RegName + 2;
648  return RegName + 1;
649  case 'c':
650  if (RegName[1] == 'r')
651  return RegName + 2;
652  }
653 
654  return RegName;
655 }
656 #endif
657 
658 static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
659 {
660  MCOperand *Op = MCInst_getOperand(MI, OpNo);
661  if (MCOperand_isReg(Op)) {
662  unsigned reg = MCOperand_getReg(Op);
663 #ifndef CAPSTONE_DIET
664  const char *RegName = getRegisterName(reg);
665 #endif
666  // map to public register
668 #ifndef CAPSTONE_DIET
669  // The linux and AIX assembler does not take register prefixes.
670  if (MI->csh->syntax == CS_OPT_SYNTAX_NOREGNAME)
671  RegName = stripRegisterPrefix(RegName);
672 
673  SStream_concat0(O, RegName);
674 #endif
675 
676  if (MI->csh->detail) {
677  if (MI->csh->doing_mem) {
678  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].mem.base = reg;
679  } else {
680  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_REG;
681  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].reg = reg;
682  MI->flat_insn->detail->ppc.op_count++;
683  }
684  }
685 
686  return;
687  }
688 
689  if (MCOperand_isImm(Op)) {
691  printInt32(O, imm);
692 
693  if (MI->csh->detail) {
694  if (MI->csh->doing_mem) {
695  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].mem.disp = (int32_t)imm;
696  } else {
697  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
698  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = imm;
699  MI->flat_insn->detail->ppc.op_count++;
700  }
701  }
702  }
703 }
704 
705 static void op_addImm(MCInst *MI, int v)
706 {
707  if (MI->csh->detail) {
708  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_IMM;
709  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].imm = v;
710  MI->flat_insn->detail->ppc.op_count++;
711  }
712 }
713 
714 static void op_addReg(MCInst *MI, unsigned int reg)
715 {
716  if (MI->csh->detail) {
717  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_REG;
718  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].reg = reg;
719  MI->flat_insn->detail->ppc.op_count++;
720  }
721 }
722 
723 static void op_addBC(MCInst *MI, unsigned int bc)
724 {
725  if (MI->csh->detail) {
726  MI->flat_insn->detail->ppc.bc = (ppc_bc)bc;
727  }
728 }
729 
730 #define CREQ (0)
731 #define CRGT (1)
732 #define CRLT (2)
733 #define CRUN (3)
734 
735 static int getBICRCond(int bi)
736 {
737  return (bi-PPC_CR0EQ) >> 3;
738 }
739 
740 static int getBICR(int bi)
741 {
742  return ((bi - PPC_CR0EQ) & 7) + PPC_CR0;
743 }
744 
745 static char *printAliasInstrEx(MCInst *MI, SStream *OS, void *info)
746 {
747 #define GETREGCLASS_CONTAIN(_class, _reg) MCRegisterClass_contains(MCRegisterInfo_getRegClass(MRI, _class), MCOperand_getReg(MCInst_getOperand(MI, _reg)))
748  SStream ss;
749  const char *opCode;
750  char *tmp, *AsmMnem, *AsmOps, *c;
751  int OpIdx, PrintMethodIdx;
752  int decCtr = false, needComma = false;
754 
755  SStream_Init(&ss);
756  switch (MCInst_getOpcode(MI)) {
757  default: return NULL;
758  case PPC_gBC:
759  opCode = "b%s";
760  break;
761  case PPC_gBCA:
762  opCode = "b%sa";
763  break;
764  case PPC_gBCCTR:
765  opCode = "b%sctr";
766  break;
767  case PPC_gBCCTRL:
768  opCode = "b%sctrl";
769  break;
770  case PPC_gBCL:
771  opCode = "b%sl";
772  break;
773  case PPC_gBCLA:
774  opCode = "b%sla";
775  break;
776  case PPC_gBCLR:
777  opCode = "b%slr";
778  break;
779  case PPC_gBCLRL:
780  opCode = "b%slrl";
781  break;
782  }
783 
784  if (MCInst_getNumOperands(MI) == 3 &&
786  (MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 0) &&
787  (MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 1)) {
788  SStream_concat(&ss, opCode, "dnzf");
789  decCtr = true;
790  }
791 
792  if (MCInst_getNumOperands(MI) == 3 &&
794  (MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 2) &&
795  (MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 3)) {
796  SStream_concat(&ss, opCode, "dzf");
797  decCtr = true;
798  }
799 
800  if (MCInst_getNumOperands(MI) == 3 &&
802  (MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 4) &&
803  (MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 7) &&
805  GETREGCLASS_CONTAIN(PPC_CRBITRCRegClassID, 1)) {
806  int cr = getBICRCond(MCOperand_getReg(MCInst_getOperand(MI, 1)));
807  switch(cr) {
808  case CREQ:
809  SStream_concat(&ss, opCode, "ne");
810  break;
811  case CRGT:
812  SStream_concat(&ss, opCode, "le");
813  break;
814  case CRLT:
815  SStream_concat(&ss, opCode, "ge");
816  break;
817  case CRUN:
818  SStream_concat(&ss, opCode, "ns");
819  break;
820  }
821 
822  if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 6)
823  SStream_concat0(&ss, "-");
824 
825  if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 7)
826  SStream_concat0(&ss, "+");
827 
828  decCtr = false;
829  }
830 
831  if (MCInst_getNumOperands(MI) == 3 &&
833  (MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 8) &&
834  (MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 9)) {
835  SStream_concat(&ss, opCode, "dnzt");
836  decCtr = true;
837  }
838 
839  if (MCInst_getNumOperands(MI) == 3 &&
841  (MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 10) &&
842  (MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 11)) {
843  SStream_concat(&ss, opCode, "dzt");
844  decCtr = true;
845  }
846 
847  if (MCInst_getNumOperands(MI) == 3 &&
849  (MCOperand_getImm(MCInst_getOperand(MI, 0)) >= 12) &&
850  (MCOperand_getImm(MCInst_getOperand(MI, 0)) <= 15) &&
852  GETREGCLASS_CONTAIN(PPC_CRBITRCRegClassID, 1)) {
853  int cr = getBICRCond(MCOperand_getReg(MCInst_getOperand(MI, 1)));
854  switch(cr) {
855  case CREQ:
856  SStream_concat(&ss, opCode, "eq");
857  break;
858  case CRGT:
859  SStream_concat(&ss, opCode, "gt");
860  break;
861  case CRLT:
862  SStream_concat(&ss, opCode, "lt");
863  break;
864  case CRUN:
865  SStream_concat(&ss, opCode, "so");
866  break;
867  }
868 
869  if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 14)
870  SStream_concat0(&ss, "-");
871 
872  if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 15)
873  SStream_concat0(&ss, "+");
874 
875  decCtr = false;
876  }
877 
878  if (MCInst_getNumOperands(MI) == 3 &&
880  ((MCOperand_getImm(MCInst_getOperand(MI, 0)) & 0x12)== 16)) {
881  SStream_concat(&ss, opCode, "dnz");
882 
883  if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 24)
884  SStream_concat0(&ss, "-");
885 
886  if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 25)
887  SStream_concat0(&ss, "+");
888 
889  needComma = false;
890  }
891 
892  if (MCInst_getNumOperands(MI) == 3 &&
894  ((MCOperand_getImm(MCInst_getOperand(MI, 0)) & 0x12)== 18)) {
895  SStream_concat(&ss, opCode, "dz");
896 
897  if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 26)
898  SStream_concat0(&ss, "-");
899 
900  if (MCOperand_getImm(MCInst_getOperand(MI, 0)) == 27)
901  SStream_concat0(&ss, "+");
902 
903  needComma = false;
904  }
905 
906  if (MCOperand_isReg(MCInst_getOperand(MI, 1)) &&
907  GETREGCLASS_CONTAIN(PPC_CRBITRCRegClassID, 1) &&
909  (MCOperand_getImm(MCInst_getOperand(MI, 0)) < 16)) {
910  int cr = getBICR(MCOperand_getReg(MCInst_getOperand(MI, 1)));
911 
912  if (decCtr) {
913  needComma = true;
914  SStream_concat0(&ss, " ");
915 
916  if (cr > PPC_CR0) {
917  SStream_concat(&ss, "4*cr%d+", cr - PPC_CR0);
918  }
919 
920  cr = getBICRCond(MCOperand_getReg(MCInst_getOperand(MI, 1)));
921  switch(cr) {
922  case CREQ:
923  SStream_concat0(&ss, "eq");
924  op_addBC(MI, PPC_BC_EQ);
925  break;
926  case CRGT:
927  SStream_concat0(&ss, "gt");
928  op_addBC(MI, PPC_BC_GT);
929  break;
930  case CRLT:
931  SStream_concat0(&ss, "lt");
932  op_addBC(MI, PPC_BC_LT);
933  break;
934  case CRUN:
935  SStream_concat0(&ss, "so");
936  op_addBC(MI, PPC_BC_SO);
937  break;
938  }
939 
940  cr = getBICR(MCOperand_getReg(MCInst_getOperand(MI, 1)));
941  if (cr > PPC_CR0) {
942  if (MI->csh->detail) {
943  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].type = PPC_OP_CRX;
944  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].crx.scale = 4;
945  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].crx.reg = PPC_REG_CR0 + cr - PPC_CR0;
946  MI->flat_insn->detail->ppc.operands[MI->flat_insn->detail->ppc.op_count].crx.cond = MI->flat_insn->detail->ppc.bc;
947  MI->flat_insn->detail->ppc.op_count++;
948  }
949  }
950  } else {
951  if (cr > PPC_CR0) {
952  needComma = true;
953  SStream_concat(&ss, " cr%d", cr - PPC_CR0);
954  op_addReg(MI, PPC_REG_CR0 + cr - PPC_CR0);
955  }
956  }
957  }
958 
959  if (MCOperand_isImm(MCInst_getOperand(MI, 2)) &&
960  MCOperand_getImm(MCInst_getOperand(MI, 2)) != 0) {
961  if (needComma)
962  SStream_concat0(&ss, ",");
963 
964  SStream_concat0(&ss, " $\xFF\x03\x01");
965  }
966 
967  tmp = cs_strdup(ss.buffer);
968  AsmMnem = tmp;
969  for(AsmOps = tmp; *AsmOps; AsmOps++) {
970  if (*AsmOps == ' ' || *AsmOps == '\t') {
971  *AsmOps = '\0';
972  AsmOps++;
973  break;
974  }
975  }
976 
977  SStream_concat0(OS, AsmMnem);
978  if (*AsmOps) {
979  SStream_concat0(OS, "\t");
980  for (c = AsmOps; *c; c++) {
981  if (*c == '$') {
982  c += 1;
983  if (*c == (char)0xff) {
984  c += 1;
985  OpIdx = *c - 1;
986  c += 1;
987  PrintMethodIdx = *c - 1;
988  printCustomAliasOperand(MI, OpIdx, PrintMethodIdx, OS);
989  } else
990  printOperand(MI, *c - 1, OS);
991  } else {
992  SStream_concat(OS, "%c", *c);
993  }
994  }
995  }
996 
997  return tmp;
998 }
999 
1000 #define PRINT_ALIAS_INSTR
1001 #include "PPCGenAsmWriter.inc"
1002 
1003 #endif
#define mnem(n, mn)
unsigned MCInst_getOpcode(const MCInst *inst)
Definition: MCInst.c:68
unsigned MCInst_getNumOperands(const MCInst *inst)
Definition: MCInst.c:83
MCOperand * MCInst_getOperand(MCInst *inst, unsigned i)
Definition: MCInst.c:78
void MCOperand_setImm(MCOperand *op, int64_t Val)
Definition: MCInst.c:133
bool MCOperand_isReg(const MCOperand *op)
Definition: MCInst.c:101
void MCInst_setOpcodePub(MCInst *inst, unsigned Op)
Definition: MCInst.c:63
int64_t MCOperand_getImm(MCOperand *op)
Definition: MCInst.c:128
unsigned MCOperand_getReg(const MCOperand *op)
getReg - Returns the register number.
Definition: MCInst.c:117
bool MCOperand_isImm(const MCOperand *op)
Definition: MCInst.c:106
static int64_t SignExtend64(uint64_t X, unsigned B)
Sign extend number in the bottom B bits of X to a 64-bit int. Requires 0 < B <= 64.
Definition: MathExtras.h:413
static int32_t SignExtend32(uint32_t X, unsigned B)
Sign extend number in the bottom B bits of X to a 32-bit int. Requires 0 < B <= 32.
Definition: MathExtras.h:407
void PPC_printInst(MCInst *MI, SStream *O, void *Info)
void PPC_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
ppc_reg PPC_map_register(unsigned int r)
bool PPC_alias_insn(const char *name, struct ppc_alias *alias)
bool PPC_abs_branch(cs_struct *h, unsigned int id)
ppc_insn PPC_map_insn(const char *name)
ppc_predicate
Definition: PPCPredicates.h:23
@ PPC_PRED_BIT_SET
Definition: PPCPredicates.h:51
@ PPC_PRED_UN
Definition: PPCPredicates.h:30
@ PPC_PRED_GE_MINUS
Definition: PPCPredicates.h:35
@ PPC_PRED_LT_PLUS
Definition: PPCPredicates.h:40
@ PPC_PRED_EQ_MINUS
Definition: PPCPredicates.h:34
@ PPC_PRED_NU
Definition: PPCPredicates.h:31
@ PPC_PRED_GE_PLUS
Definition: PPCPredicates.h:43
@ PPC_PRED_UN_MINUS
Definition: PPCPredicates.h:38
@ PPC_PRED_NE_MINUS
Definition: PPCPredicates.h:37
@ PPC_PRED_NU_PLUS
Definition: PPCPredicates.h:47
@ PPC_PRED_EQ
Definition: PPCPredicates.h:26
@ PPC_PRED_GT
Definition: PPCPredicates.h:28
@ PPC_PRED_LT
Definition: PPCPredicates.h:24
@ PPC_PRED_LT_MINUS
Definition: PPCPredicates.h:32
@ PPC_PRED_LE_MINUS
Definition: PPCPredicates.h:33
@ PPC_PRED_NE_PLUS
Definition: PPCPredicates.h:45
@ PPC_PRED_BIT_UNSET
Definition: PPCPredicates.h:52
@ PPC_PRED_LE
Definition: PPCPredicates.h:25
@ PPC_PRED_GT_PLUS
Definition: PPCPredicates.h:44
@ PPC_PRED_GT_MINUS
Definition: PPCPredicates.h:36
@ PPC_PRED_UN_PLUS
Definition: PPCPredicates.h:46
@ PPC_PRED_GE
Definition: PPCPredicates.h:27
@ PPC_PRED_NE
Definition: PPCPredicates.h:29
@ PPC_PRED_LE_PLUS
Definition: PPCPredicates.h:41
@ PPC_PRED_NU_MINUS
Definition: PPCPredicates.h:39
@ PPC_PRED_EQ_PLUS
Definition: PPCPredicates.h:42
void SStream_Init(SStream *ss)
Definition: SStream.c:25
void SStream_concat(SStream *ss, const char *fmt,...)
Definition: SStream.c:45
void SStream_concat0(SStream *ss, const char *s)
Definition: SStream.c:31
void printUInt32(SStream *O, uint32_t val)
Definition: SStream.c:164
void printInt32(SStream *O, int32_t val)
Definition: SStream.c:137
void op_addImm(MCInst *MI, int v)
void op_addReg(MCInst *MI, int reg)
#define imm
RzBinInfo * info(RzBinFile *bf)
Definition: bin_ne.c:86
size_t csh
Definition: capstone.h:71
@ CS_OPT_SYNTAX_NOREGNAME
Prints register name with only number (CS_OPT_SYNTAX)
Definition: capstone.h:187
@ CS_OPT_ON
Turn ON an option (CS_OPT_DETAIL, CS_OPT_SKIPDATA).
Definition: capstone.h:183
#define NULL
Definition: cris-opc.c:27
cs_free_t cs_mem_free
Definition: cs.c:351
#define Code
Definition: deflate.h:80
const char * v
Definition: dsignal.c:12
@ OS
Definition: inflate.h:24
#define reg(n)
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
#define O
Definition: rcond.c:14
#define SH
Definition: rsp_idec.c:406
static int
Definition: sfsocketcall.h:114
long int64_t
Definition: sftypes.h:32
int int32_t
Definition: sftypes.h:33
#define c(i)
Definition: sha256.c:43
Definition: MCInst.h:88
cs_insn * flat_insn
Definition: MCInst.h:95
cs_struct * csh
Definition: MCInst.h:97
uint64_t address
Definition: MCInst.h:96
Definition: SStream.h:9
char buffer[512]
Definition: SStream.h:10
Instruction structure.
Definition: ppc.h:294
bool doing_mem
Definition: cs_priv.h:70
int syntax
Definition: cs_priv.h:69
cs_opt_value detail
Definition: cs_priv.h:68
@ PPC_BH_PLUS
PLUS hint.
Definition: ppc.h:37
@ PPC_BH_MINUS
MINUS hint.
Definition: ppc.h:38
@ PPC_OP_REG
= CS_OP_REG (Register operand).
Definition: ppc.h:44
@ PPC_OP_IMM
= CS_OP_IMM (Immediate operand).
Definition: ppc.h:45
@ PPC_OP_MEM
= CS_OP_MEM (Memory operand).
Definition: ppc.h:46
@ PPC_OP_CRX
Condition Register field.
Definition: ppc.h:47
ppc_bc
PPC branch codes for some branch instructions.
Definition: ppc.h:18
@ PPC_BC_LE
Definition: ppc.h:21
@ PPC_BC_EQ
Definition: ppc.h:22
@ PPC_BC_SO
summary overflow
Definition: ppc.h:30
@ PPC_BC_UN
Definition: ppc.h:26
@ PPC_BC_NE
Definition: ppc.h:25
@ PPC_BC_GT
Definition: ppc.h:24
@ PPC_BC_NU
Definition: ppc.h:27
@ PPC_BC_LT
Definition: ppc.h:20
@ PPC_BC_GE
Definition: ppc.h:23
@ PPC_INS_MR
Definition: ppc.h:1324
@ PPC_INS_SRWI
Definition: ppc.h:1249
@ PPC_INS_SLWI
Definition: ppc.h:1248
@ PPC_INS_SLDI
Definition: ppc.h:1250
@ PPC_REG_INVALID
Definition: ppc.h:52
@ PPC_REG_CR0
Definition: ppc.h:55
char * cs_strdup(const char *str)
Definition: utils.c:92
#define HEX_THRESHOLD
Definition: utils.h:16
#define PRIx64
Definition: sysdefs.h:94
Definition: dis.c:32
#define MB
Definition: unum.c:92