Rizin
unix-like reverse engineering framework and cli tools
libps.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2017 deroad <wargio@libero.it>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 #include "libps.h"
4 #include "libps_internal.h"
5 
7  { 0, 0 }, // No Operand
8  { 5, 16 }, // FA
9  { 5, 11 }, // FB
10  { 5, 6 }, // FC
11  { 5, 21 }, // FD/FS
12  { 3, 23 }, // crfD,
13  { 1, 16 }, // WB,
14  { 3, 12 }, // IB,
15  { 1, 10 }, // WC,
16  { 3, 7 }, // IC,
17  { 5, 16 }, // RA
18  { 5, 11 }, // RB
19  { 5, 16 }, // DRA,
20  { 5, 11 }, // DRB,
21 };
22 
24  { psq_lx, "psq_lx", OPM(4, 6), OPM_MASK, { OP_FD, OP_RA, OP_RB, OP_WC, OP_IC }, "Paired Single Quantized Load Indexed" },
25  { psq_stx, "psq_stx", OPM(4, 7), OPM_MASK, { OP_FS, OP_RA, OP_RB, OP_WC, OP_IC }, "Paired Single Quantized Store Indexed" },
26  { psq_lux, "psq_lux", OPM(4, 38), OPM_MASK, { OP_FD, OP_RA, OP_RB, OP_WC, OP_IC }, "Paired Single Quantized Load with update Indexed" },
27  { psq_stux, "psq_stux", OPM(4, 39), OPM_MASK, { OP_FS, OP_RA, OP_RB, OP_WC, OP_IC }, "Paired Single Quantized Store with update Indexed" },
28 
29  { psq_l, "psq_l", OP(56), OP_MASK, { OP_FD, OP_DRA, OP_WB, OP_IB }, "Paired Single Quantized Load" },
30  { psq_lu, "psq_lu", OP(57), OP_MASK, { OP_FD, OP_DRA, OP_WB, OP_IB }, "Paired Single Quantized Load with Update" },
31  { psq_st, "psq_st", OP(60), OP_MASK, { OP_FS, OP_DRA, OP_WB, OP_IB }, "Paired Single Quantized Store" },
32  { psq_stu, "psq_stu", OP(61), OP_MASK, { OP_FS, OP_DRA, OP_WB, OP_IB }, "Paired Single Quantized Store with update" },
33 
34  { ps_div, "ps_div", OPSC(4, 18, 0), OPS_MASK, { OP_FD, OP_FA, OP_FB }, "Paired Single Divide" },
35  { ps_div_dot, "ps_div.", OPSC(4, 18, 1), OPS_MASK_DOT, { OP_FD, OP_FA, OP_FB }, "Paired Single Divide" },
36  { ps_sub, "ps_sub", OPSC(4, 20, 0), OPS_MASK, { OP_FD, OP_FA, OP_FB }, "Paired Single Subtract" },
37  { ps_sub_dot, "ps_sub.", OPSC(4, 20, 1), OPS_MASK_DOT, { OP_FD, OP_FA, OP_FB }, "Paired Single Subtract" },
38  { ps_add, "ps_add", OPSC(4, 21, 0), OPS_MASK, { OP_FD, OP_FA, OP_FB }, "Paired Single Add" },
39  { ps_add_dot, "ps_add.", OPSC(4, 21, 1), OPS_MASK_DOT, { OP_FD, OP_FA, OP_FB }, "Paired Single Add" },
40  { ps_sel, "ps_sel", OPSC(4, 23, 0), OPS_MASK, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single Select" },
41  { ps_sel_dot, "ps_sel.", OPSC(4, 23, 1), OPS_MASK_DOT, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single Select" },
42  { ps_res, "ps_res", OPSC(4, 24, 0), OPS_MASK, { OP_FD, OP_FB }, "Paired Single Reciprocal Estimate" },
43  { ps_res_dot, "ps_res.", OPSC(4, 24, 1), OPS_MASK_DOT, { OP_FD, OP_FB }, "Paired Single Reciprocal Estimate" },
44  { ps_mul, "ps_mul", OPSC(4, 25, 0), OPS_MASK, { OP_FD, OP_FA, OP_FC }, "Paired Single Multiply" },
45  { ps_mul_dot, "ps_mul.", OPSC(4, 25, 1), OPS_MASK_DOT, { OP_FD, OP_FA, OP_FC }, "Paired Single Multiply" },
46  { ps_rsqrte, "ps_rsqrte", OPSC(4, 26, 0), OPS_MASK, { OP_FD, OP_FB }, "Paired Single Reciprocal Square Root Estimate" },
47  { ps_rsqrte_dot, "ps_rsqrte.", OPSC(4, 26, 1), OPS_MASK_DOT, { OP_FD, OP_FB }, "Paired Single Reciprocal Square Root Estimate" },
48  { ps_msub, "ps_msub", OPSC(4, 28, 0), OPS_MASK, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single Multiply-Subtract" },
49  { ps_msub_dot, "ps_msub.", OPSC(4, 28, 1), OPS_MASK_DOT, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single Multiply-Subtract" },
50  { ps_madd, "ps_madd", OPSC(4, 29, 0), OPS_MASK, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single Multiply-Add" },
51  { ps_madd_dot, "ps_madd.", OPSC(4, 29, 1), OPS_MASK_DOT, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single Multiply-Add" },
52  { ps_nmsub, "ps_nmsub", OPSC(4, 30, 0), OPS_MASK, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single Negative Multiply-Subtract" },
53  { ps_nmsub_dot, "ps_nmsub.", OPSC(4, 30, 1), OPS_MASK_DOT, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single Negative Multiply-Subtract" },
54  { ps_nmadd, "ps_nmadd", OPSC(4, 31, 0), OPS_MASK, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single Negative Multiply-Add" },
55  { ps_nmadd_dot, "ps_nmadd.", OPSC(4, 31, 1), OPS_MASK_DOT, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single Negative Multiply-Add" },
56 
57  { ps_neg, "ps_neg", OPLC(4, 40, 0), OPL_MASK, { OP_FD, OP_FB }, "Paired Single Negate" },
58  { ps_neg_dot, "ps_neg.", OPLC(4, 40, 1), OPL_MASK_DOT, { OP_FD, OP_FB }, "Paired Single Negate" },
59  { ps_mr, "ps_mr", OPLC(4, 72, 0), OPL_MASK, { OP_FD, OP_FB }, "Paired Single Move Register" },
60  { ps_mr_dot, "ps_mr.", OPLC(4, 72, 1), OPL_MASK_DOT, { OP_FD, OP_FB }, "Paired Single Move Register" },
61  { ps_nabs, "ps_nabs", OPLC(4, 136, 0), OPL_MASK, { OP_FD, OP_FB }, "Paired Single Negative Absolute Value" },
62  { ps_nabs_dot, "ps_nabs.", OPLC(4, 136, 1), OPL_MASK_DOT, { OP_FD, OP_FB }, "Paired Single Negative Absolute Value" },
63  { ps_abs, "ps_abs", OPLC(4, 264, 0), OPL_MASK, { OP_FD, OP_FB }, "Paired Single Absolute Value" },
64  { ps_abs_dot, "ps_abs.", OPLC(4, 264, 1), OPL_MASK_DOT, { OP_FD, OP_FB }, "Paired Single Absolute Value" },
65 
66  { ps_sum0, "ps_sum0", OPSC(4, 10, 0), OPS_MASK, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single vector SUM high" },
67  { ps_sum0_dot, "ps_sum0.", OPSC(4, 10, 1), OPS_MASK_DOT, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single vector SUM high" },
68  { ps_sum1, "ps_sum1", OPSC(4, 11, 0), OPS_MASK, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single vector SUM low" },
69  { ps_sum1_dot, "ps_sum1.", OPSC(4, 11, 1), OPS_MASK_DOT, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single vector SUM low" },
70  { ps_muls0, "ps_muls0", OPSC(4, 12, 0), OPS_MASK, { OP_FD, OP_FA, OP_FC }, "Paired Single Multiply Scalar high" },
71  { ps_muls0_dot, "ps_muls0.", OPSC(4, 12, 1), OPS_MASK_DOT, { OP_FD, OP_FA, OP_FC }, "Paired Single Multiply Scalar high" },
72  { ps_muls1, "ps_muls1", OPSC(4, 13, 0), OPS_MASK, { OP_FD, OP_FA, OP_FC }, "Paired Single Multiply Scalar low" },
73  { ps_muls1_dot, "ps_muls1.", OPSC(4, 13, 1), OPS_MASK_DOT, { OP_FD, OP_FA, OP_FC }, "Paired Single Multiply Scalar low" },
74  { ps_madds0, "ps_madds0", OPSC(4, 14, 0), OPS_MASK, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single Multiply-Add Scalar high" },
75  { ps_madds0_dot, "ps_madds0.", OPSC(4, 14, 1), OPS_MASK_DOT, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single Multiply-Add Scalar high" },
76  { ps_madds1, "ps_madds1", OPSC(4, 15, 0), OPS_MASK, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single Multiply-Add Scalar low" },
77  { ps_madds1_dot, "ps_madds1.", OPSC(4, 15, 1), OPS_MASK_DOT, { OP_FD, OP_FA, OP_FC, OP_FB }, "Paired Single Multiply-Add Scalar low" },
78 
79  { ps_cmpu0, "ps_cmpu0", OPL(4, 0), OPL_MASK, { OP_crfD, OP_FA, OP_FB }, "Paired Singles Compare Unordered High" },
80  { ps_cmpo0, "ps_cmpo0", OPL(4, 32), OPL_MASK, { OP_crfD, OP_FA, OP_FB }, "Paired Singles Compare Ordered High" },
81  { ps_cmpu1, "ps_cmpu1", OPL(4, 64), OPL_MASK, { OP_crfD, OP_FA, OP_FB }, "Paired Singles Compare Unordered Low" },
82  { ps_cmpo1, "ps_cmpo1", OPL(4, 96), OPL_MASK, { OP_crfD, OP_FA, OP_FB }, "Paired Singles Compare Ordered Low" },
83 
84  { ps_merge00, "ps_merge00", OPLC(4, 528, 0), OPL_MASK, { OP_FD, OP_FA, OP_FB }, "Paired Single MERGE high" },
85  { ps_merge00_dot, "ps_merge00.", OPLC(4, 528, 1), OPL_MASK_DOT, { OP_FD, OP_FA, OP_FB }, "Paired Single MERGE high" },
86  { ps_merge01, "ps_merge01", OPLC(4, 560, 0), OPL_MASK, { OP_FD, OP_FA, OP_FB }, "Paired Single MERGE direct" },
87  { ps_merge01_dot, "ps_merge01.", OPLC(4, 560, 1), OPL_MASK_DOT, { OP_FD, OP_FA, OP_FB }, "Paired Single MERGE direct" },
88  { ps_merge10, "ps_merge10", OPLC(4, 592, 0), OPL_MASK, { OP_FD, OP_FA, OP_FB }, "Paired Single MERGE swapped" },
89  { ps_merge10_dot, "ps_merge10.", OPLC(4, 592, 1), OPL_MASK_DOT, { OP_FD, OP_FA, OP_FB }, "Paired Single MERGE swapped" },
90  { ps_merge11, "ps_merge11", OPLC(4, 624, 0), OPL_MASK, { OP_FD, OP_FA, OP_FB }, "Paired Single MERGE low" },
91  { ps_merge11_dot, "ps_merge11.", OPLC(4, 624, 1), OPL_MASK_DOT, { OP_FD, OP_FA, OP_FB }, "Paired Single MERGE low" },
92 
93  { ps_dcbz_l, "dcbz_l", OPL(4, 1014), OPL_MASK, { OP_RA, OP_RB }, "Data Cache Block Set to Zero Locked" },
94 
95 };
96 
97 bool libps_decode(ut32 data, ppcps_t *ps) {
98  ut32 op = (data & OP_MASK);
99 
100  if ((op == OP(4)) || (op == OP(56)) ||
101  (op == OP(57)) || (op == OP(60)) ||
102  (op == OP(61))) {
103  ut32 size = sizeof(ps_opcodes_array) / sizeof(ps_opcode_t);
105 
106  ut32 l, j;
107  for (l = 0; l < size; l++) {
108  if ((data & instruction->mask) == instruction->opcode) {
109  j = 0;
110  for (; j < 6 && instruction->operands[j] != 0; j++) {
111  ppcps_field_t *field = &ps->operands[j];
112  ps_operand_t *ps_operand = &ps_operands_array[instruction->operands[j]];
113 
114  int bits = (data >> ps_operand->shift) & ((1 << ps_operand->bits) - 1);
115  // int ext_bits = (bits << (32 - ps_operand->bits)) >> (32 - ps_operand->bits);
116 
117  switch (instruction->operands[j]) {
118  case OP_FA:
119  case OP_FB:
120  case OP_FC:
121  case OP_FD: {
122  field->type = TYPE_REG;
123  field->value = bits;
124  break;
125  }
126 
127  case OP_RA:
128  case OP_RB: {
129  field->type = TYPE_REG;
130  field->value = bits;
131  break;
132  }
133 
134  case OP_crfD: {
135  field->type = TYPE_CR;
136  field->value = bits;
137  break;
138  }
139  case OP_WB:
140  case OP_IB:
141  case OP_WC:
142  case OP_IC: {
143  field->type = TYPE_IMM;
144  field->value = bits;
145  break;
146  }
147 
148  case OP_DRA: {
149  ut16 imm = (ut16)(data & 0x7FF);
150  ut16 sign = (ut16)(data & 0x800);
151  st16 displacement = 0;
152  if (sign == 0) {
153  displacement = imm;
154  } else {
155  displacement = -1 * imm;
156  }
157  field->type = TYPE_MEM;
158  field->value = bits + displacement;
159  break;
160  }
161 
162  default:
163  break;
164  }
165  }
166  ps->n = j;
167  ps->name = instruction->name;
168  ps->op = instruction->insn;
169  return true;
170  }
171  instruction++;
172  }
173  }
174  return false;
175 }
176 
177 void libps_snprint(char *str, int size, ut64 addr, ppcps_t *instr) {
178  ut32 i;
179  int bufsize = size, add = 0;
180  add = snprintf(str, bufsize, "%s", instr->name);
181  for (i = 0; add > 0 && i < instr->n && add < bufsize; i++) {
182  if (instr->operands[i].type == TYPE_REG) {
183  add += snprintf(str + add, bufsize - add, " fr%u", instr->operands[i].value);
184  } else if (instr->operands[i].type == TYPE_IMM) {
185  add += snprintf(str + add, bufsize - add, " 0x%x", instr->operands[i].value);
186  } else if (instr->operands[i].type == TYPE_MEM) {
187  add += snprintf(str + add, bufsize - add, " 0x%x(r%d)", instr->operands[i].value, instr->operands[i + 1].value);
188  i++;
189  } else if (instr->operands[i].type == TYPE_CR) {
190  add += snprintf(str + add, bufsize - add, " cr%u", instr->operands[i].value);
191  }
192  }
193 }
#define imm
lzma_index ** i
Definition: index.h:629
@ TYPE_IMM
Definition: armass.c:35
@ TYPE_MEM
Definition: armass.c:36
int bits(struct state *s, int need)
Definition: blast.c:72
uint16_t ut16
uint32_t ut32
#define OP(v, w, x, y, z)
voidpf void uLong size
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
void libps_snprint(char *str, int size, ut64 addr, ppcps_t *instr)
Definition: libps.c:177
bool libps_decode(ut32 data, ppcps_t *ps)
Definition: libps.c:97
ps_opcode_t ps_opcodes_array[]
Definition: libps.c:23
ps_operand_t ps_operands_array[]
Definition: libps.c:6
#define OPM_MASK
#define OPSC(op, xop, rc)
@ ps_nmsub
@ ps_nmadd_dot
@ ps_sum1_dot
@ ps_rsqrte
@ ps_madds1
@ ps_sum1
@ ps_nmsub_dot
@ ps_madd
@ ps_rsqrte_dot
@ ps_res_dot
@ ps_mul
@ ps_div
@ ps_madds1_dot
@ ps_merge10_dot
@ ps_merge11
@ psq_st
@ psq_stx
@ ps_nabs_dot
@ ps_neg_dot
@ ps_mr
@ psq_lu
@ ps_madds0_dot
@ ps_abs
@ ps_merge01_dot
@ ps_add
@ ps_cmpo0
@ ps_neg
@ ps_muls0
@ ps_div_dot
@ ps_sub
@ ps_dcbz_l
@ psq_stux
@ ps_res
@ ps_cmpu1
@ ps_merge00
@ ps_sum0_dot
@ ps_muls1_dot
@ ps_nmadd
@ ps_sel_dot
@ ps_merge10
@ ps_merge11_dot
@ ps_madd_dot
@ ps_add_dot
@ ps_abs_dot
@ ps_sel
@ ps_muls0_dot
@ psq_lx
@ psq_lux
@ ps_madds0
@ psq_stu
@ ps_msub
@ ps_merge00_dot
@ ps_sum0
@ ps_msub_dot
@ ps_sub_dot
@ ps_muls1
@ ps_cmpo1
@ ps_mul_dot
@ ps_cmpu0
@ ps_mr_dot
@ ps_merge01
@ psq_l
@ ps_nabs
#define OPL_MASK
#define OPL_MASK_DOT
#define OPS_MASK
#define OPS_MASK_DOT
#define OPLC(op, xop, rc)
@ OP_FC
@ OP_RB
@ OP_WB
@ OP_RA
@ OP_IB
@ OP_FD
@ OP_FB
@ OP_FA
@ OP_DRA
@ OP_WC
@ OP_IC
@ OP_crfD
@ OP_FS
#define OPL(op, xop)
#define TYPE_CR
#define OPM(op, xop)
#define TYPE_REG
Definition: mcore.h:22
#define OP_MASK
Definition: nios2.h:467
#define st16
Definition: rz_types_base.h:14
ut32 value
Definition: libps.h:9
ut16 type
Definition: libps.h:10
Definition: libps.h:13
ppcps_field_t operands[6]
Definition: libps.h:15
const char * name
Definition: libps.h:14
int op
Definition: libps.h:17
int n
Definition: libps.h:16
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58
static int add(char *argv[])
Definition: ziptool.c:84