Rizin
unix-like reverse engineering framework and cli tools
propeller_disas.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2014 Fedor Sakharov <fedor.sakharov@gmail.com>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_types.h>
5 #include <rz_util.h>
6 
7 #include "propeller_disas.h"
8 
9 static const char *instrs[] = {
10  [PROP_ABS] = "abs",
11  [PROP_ABSNEG] = "absneg",
12  [PROP_ADD] = "add",
13  [PROP_ADDABS] = "addabs",
14  [PROP_ADDS] = "adds",
15  [PROP_ADDSX] = "addsx",
16  [PROP_ADDX] = "addx",
17  [PROP_AND] = "and", // or TEST
18  [PROP_ANDN] = "andn", // or TESTN
19  [PROP_CALL] = "call", // or JMP JMPRET RET
20  [PROP_CMP] = "cmp",
21  [PROP_CMPS] = "cmps",
22  [PROP_CMPSUB] = "cmpsub",
23  [PROP_CMPSX] = "cmpsx",
24  [PROP_CMPX] = "cmpx",
25  [PROP_DJNZ] = "djnz",
26  [PROP_HUBOP] = "hubop",
27  [PROP_MOV] = "mov",
28  [PROP_MAX] = "max",
29  [PROP_MAXS] = "maxs",
30  [PROP_MIN] = "min",
31  [PROP_MINS] = "mins",
32  [PROP_MOVD] = "movd",
33  [PROP_MOVI] = "movi",
34  [PROP_MOVS] = "movs",
35  [PROP_MUXC] = "muxc",
36  [PROP_MUXNC] = "muxnc",
37  [PROP_MUXNZ] = "muxnz",
38  [PROP_MUXZ] = "muxz",
39  [PROP_NEG] = "neg",
40  [PROP_NEGC] = "negc",
41  [PROP_NEGNC] = "negnc",
42  [PROP_NEGNZ] = "negnz",
43  [PROP_NEGZ] = "negz",
44  [PROP_OR] = "or",
45  [PROP_RCL] = "rcl",
46  [PROP_RCR] = "rcr",
47  [PROP_RDBYTE] = "rdbyte",
48  [PROP_RDLONG] = "rdlong",
49  [PROP_RDWORD] = "rdword",
50  [PROP_REV] = "rev",
51  [PROP_ROL] = "rol",
52  [PROP_ROR] = "ror",
53  [PROP_SAR] = "sar",
54  [PROP_SHL] = "shl",
55  [PROP_SHR] = "shr",
56  [PROP_SUBABS] = "subabs",
57  [PROP_SUBS] = "subs",
58  [PROP_SUBSX] = "subsx",
59  [PROP_SUMC] = "sumc",
60  [PROP_SUMNC] = "sumnc",
61  [PROP_SUMNZ] = "sumnz",
62  [PROP_SUMZ] = "sumz",
63  [PROP_TJZ] = "tjz",
64  [PROP_WAITCNT] = "waitcnt",
65  [PROP_WAITVID] = "waitvid",
66  [PROP_XOR] = "xor",
67 };
68 
69 static const char *ext_instrs[] = {
70  [PROP_CLKSET] = "clkset",
71  [PROP_COGID] = "cogid",
72  [PROP_COGINIT] = "coginit",
73  [PROP_COGSTOP] = "cogstop",
74  [PROP_LOCKCLR] = "lockclr",
75  [PROP_LOCKNEW] = "locknew",
76  [PROP_LOCKRET] = "lockret",
77  [PROP_LOCKSET] = "lockset",
78 };
79 
80 static const char *conditions[] = {
81  [PROP_IF_ALWAYS] = "",
82  [PROP_IF_NEVER] = "",
83  [PROP_IF_E] = "if_e",
84  [PROP_IF_NE] = "if_ne",
85  [PROP_IF_A] = "if_a",
86  [PROP_IF_B] = "if_b",
87  [PROP_IF_AE] = "if_ae",
88  [PROP_IF_BE] = "if_be",
89  [PROP_IF_C_EQ_Z] = "if_c_eq_z",
90  [PROP_IF_C_NE_Z] = "if_c_ne_z",
91  [PROP_IF_C_AND_Z] = "if_c_and_z",
92  [PROP_IF_C_AND_NZ] = "if_c_and_nz",
93  [PROP_IF_NC_AND_Z] = "if_nc_and_z",
94  [PROP_IF_NZ_OR_NC] = "if_nc_or_nz",
95  [PROP_IF_NZ_OR_C] = "if_nz_or_c",
96  [PROP_IF_Z_OR_NC] = "if_z_or_c",
97 };
98 
99 static ut16 get_opcode(ut32 instr) {
100  return instr >> 26;
101 }
102 
103 static ut16 get_opcode_ext(ut32 instr) {
104  return (instr & 0x7) | (instr >> 23);
105 }
106 
107 static ut16 get_src(ut32 instr) {
108  return instr & 0x1FF;
109 }
110 
111 static ut16 get_dst(ut32 instr) {
112  return ((instr >> 9) & 0x1FF) << 2;
113 }
114 
115 static int is_immediate(ut32 instr) {
116  return instr & 0x00400000;
117 }
118 
119 static int decode_ext_cmd(struct propeller_cmd *cmd, ut32 instr) {
120  ut16 opcode;
121 
122  opcode = get_opcode_ext(instr);
123 
124  switch (opcode) {
125  case PROP_CLKSET:
126  case PROP_COGID:
127  case PROP_COGINIT:
128  case PROP_COGSTOP:
129  case PROP_LOCKCLR:
130  case PROP_LOCKNEW:
131  case PROP_LOCKRET:
132  case PROP_LOCKSET:
133  snprintf(cmd->instr, PROP_INSTR_MAXLEN - 1,
134  "%s", ext_instrs[PROP_CLKSET]);
135  snprintf(cmd->operands, PROP_INSTR_MAXLEN - 1,
136  "%d", get_dst(instr));
137  return 4;
138  break;
139  }
140 
141  return -1;
142 }
143 
144 static ut8 get_zcri(ut32 instr) {
145  return (instr >> 22) & 0xf;
146 }
147 
148 static ut8 get_con(ut32 instr) {
149  return (instr >> 18) & 0xf;
150 }
151 
152 static void decode_prefix(struct propeller_cmd *cmd, ut32 instr) {
153  ut8 prefix = (instr >> 18) & 0xF;
154 
155  snprintf(cmd->prefix, 15, "%s", conditions[prefix]);
156  cmd->prefix[15] = '\0';
157 }
158 
159 static int decode_jmp(struct propeller_cmd *cmd, ut32 instr) {
160  ut16 opcode;
161  ut8 zcri;
162  int ret = 1;
163  opcode = get_opcode(instr);
164  switch (opcode) {
165  case PROP_JMP:
166  zcri = get_zcri(instr);
167  if (zcri & 0x2) {
168  snprintf(cmd->instr, PROP_INSTR_MAXLEN - 1,
169  "%s", "jmpret");
170  if (zcri & 1) {
171  cmd->dst = get_dst(instr) << 2;
172  cmd->src = get_src(instr) << 2;
173 
174  snprintf(cmd->operands, PROP_INSTR_MAXLEN - 1,
175  "0x%x, #0x%x", get_dst(instr), get_src(instr) << 2);
176  } else {
177  cmd->src = get_src(instr) << 2;
178  cmd->dst = get_dst(instr) << 2;
179  snprintf(cmd->operands, PROP_INSTR_MAXLEN - 1,
180  "0x%x, 0x%x", get_dst(instr), get_src(instr) << 2);
181  }
182  } else {
183  snprintf(cmd->instr, PROP_INSTR_MAXLEN - 1,
184  "%s", "jmp");
185  if (zcri & 1) {
186  cmd->src = get_src(instr) << 2;
187  cmd->immed = 1;
188  snprintf(cmd->operands, PROP_INSTR_MAXLEN - 1,
189  "#0x%x", get_src(instr) << 2);
190  } else {
191  cmd->immed = 0;
192  cmd->src = get_src(instr) << 2;
193  snprintf(cmd->operands, PROP_INSTR_MAXLEN - 1,
194  "0x%x", get_src(instr) << 2);
195  }
196  }
197 
198  ret = 4;
199  break;
200  }
201 
202  return ret;
203 }
204 
205 int propeller_decode_command(const ut8 *instr, struct propeller_cmd *cmd) {
206  int ret = -1;
207  ut32 in;
208  ut16 opcode;
209 
210  in = rz_read_be32(instr);
211 
212  opcode = get_opcode(in);
213 
214  if (!get_con(in)) {
215  snprintf(cmd->instr, PROP_INSTR_MAXLEN, "nop");
216  cmd->operands[0] = '\0';
217  return 4;
218  }
219 
220  switch (opcode) {
221  case PROP_ABS:
222  case PROP_ABSNEG:
223  case PROP_ADD:
224  case PROP_ADDABS:
225  case PROP_ADDS:
226  case PROP_ADDSX:
227  case PROP_ADDX:
228  case PROP_AND:
229  case PROP_ANDN:
230  case PROP_CMP:
231  case PROP_CMPS:
232  case PROP_CMPSUB:
233  case PROP_CMPSX:
234  case PROP_CMPX:
235  case PROP_DJNZ:
236  case PROP_MAX:
237  case PROP_MAXS:
238  case PROP_MIN:
239  case PROP_MINS:
240  case PROP_MOV:
241  case PROP_MOVD:
242  case PROP_MOVI:
243  case PROP_MOVS:
244  case PROP_MUXC:
245  case PROP_MUXNC:
246  case PROP_MUXNZ:
247  case PROP_MUXZ:
248  case PROP_NEG:
249  case PROP_NEGC:
250  case PROP_NEGNC:
251  case PROP_NEGNZ:
252  case PROP_NEGZ:
253  case PROP_OR:
254  case PROP_RCL:
255  case PROP_RCR:
256  case PROP_RDBYTE:
257  case PROP_RDLONG:
258  case PROP_RDWORD:
259  // case PROP_RET:
260  case PROP_REV:
261  case PROP_ROL:
262  case PROP_ROR:
263  case PROP_SAR:
264  case PROP_SHL:
265  case PROP_SHR:
266  case PROP_SUBABS:
267  case PROP_SUBS:
268  case PROP_SUBSX:
269  // case PROP_SUBX:
270  case PROP_SUMC:
271  case PROP_SUMNC:
272  case PROP_SUMNZ:
273  case PROP_SUMZ:
274  // case PROP_TEST:
275  case PROP_TJZ:
276  case PROP_WAITCNT:
277  case PROP_WAITPEQ:
278  case PROP_WAITPNE:
279  case PROP_WAITVID:
280  case PROP_XOR:
281  snprintf(cmd->instr, sizeof cmd->instr, "%s", instrs[opcode]);
282 
283  if ((opcode == PROP_RDBYTE || opcode == PROP_RDLONG ||
284  opcode == PROP_RDWORD) &&
285  (!(get_zcri(in) & 0x2))) {
286  cmd->instr[0] = 'w';
287  cmd->instr[1] = 'r';
288  }
289 
290  if (opcode == PROP_SUB && in & 0x08000000) {
291  snprintf(cmd->instr, PROP_INSTR_MAXLEN - 1, "sub");
292  } else if (opcode == PROP_SUBX && in & 0x08000000) {
293  snprintf(cmd->instr, PROP_INSTR_MAXLEN - 1, "subx");
294  }
295 
296  if (is_immediate(in)) {
297  cmd->src = get_src(in);
298  cmd->dst = get_dst(in);
299  snprintf(cmd->operands, PROP_INSTR_MAXLEN - 1, "0x%x, #%d",
300  get_dst(in), get_src(in));
301  } else {
302  cmd->src = get_src(in) << 2;
303  cmd->dst = get_dst(in);
304  snprintf(cmd->operands, PROP_INSTR_MAXLEN - 1, "0x%x, 0x%x",
305  get_dst(in), get_src(in) << 2);
306  }
307 
308  ret = 4;
309  break;
310  case PROP_HUBOP:
311  ret = decode_ext_cmd(cmd, in);
312  if (ret == -1) {
313  snprintf(cmd->instr, PROP_INSTR_MAXLEN - 1, "%s",
314  instrs[opcode]);
315 
316  if (is_immediate(in)) {
317  cmd->src = get_src(in);
318  cmd->dst = get_dst(in);
319 
320  snprintf(cmd->operands, PROP_INSTR_MAXLEN - 1, "0x%x, #%d",
321  get_dst(in) << 2, get_src(in));
322  } else {
323  cmd->src = get_src(in);
324  cmd->dst = get_dst(in);
325 
326  snprintf(cmd->operands, PROP_INSTR_MAXLEN - 1, "0x%x, 0x%x",
327  get_dst(in), get_src(in));
328  }
329 
330  ret = 4;
331  }
332  break;
333  case PROP_JMP:
334  ret = decode_jmp(cmd, in);
335  break;
336  }
337 
338  cmd->opcode = opcode;
339 
340  if (ret > 0) {
341  decode_prefix(cmd, in);
342  }
343 
344  return ret;
345 }
const lzma_allocator const uint8_t * in
Definition: block.h:527
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags cmd
Definition: sflib.h:79
uint16_t ut16
uint32_t ut32
unsigned short prefix[65536]
Definition: gun.c:163
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
static ut16 get_opcode_ext(ut32 instr)
static const char * instrs[]
static const char * ext_instrs[]
static ut8 get_zcri(ut32 instr)
static const char * conditions[]
static ut16 get_src(ut32 instr)
static int decode_jmp(struct propeller_cmd *cmd, ut32 instr)
static int decode_ext_cmd(struct propeller_cmd *cmd, ut32 instr)
static ut8 get_con(ut32 instr)
static ut16 get_opcode(ut32 instr)
int propeller_decode_command(const ut8 *instr, struct propeller_cmd *cmd)
static void decode_prefix(struct propeller_cmd *cmd, ut32 instr)
static int is_immediate(ut32 instr)
static ut16 get_dst(ut32 instr)
@ PROP_WAITPEQ
@ PROP_MOVS
@ PROP_MOVD
@ PROP_SUMNZ
@ PROP_MIN
@ PROP_CALL
@ PROP_RDWORD
@ PROP_CMPSUB
@ PROP_ANDN
@ PROP_RCR
@ PROP_ADDX
@ PROP_SUMNC
@ PROP_REV
@ PROP_SUBX
@ PROP_XOR
@ PROP_NEG
@ PROP_MOVI
@ PROP_NEGZ
@ PROP_CMPX
@ PROP_SHL
@ PROP_RDBYTE
@ PROP_ADDSX
@ PROP_ABSNEG
@ PROP_TJZ
@ PROP_SHR
@ PROP_RCL
@ PROP_NEGC
@ PROP_NEGNC
@ PROP_MUXC
@ PROP_NEGNZ
@ PROP_SUBABS
@ PROP_SAR
@ PROP_CMP
@ PROP_MUXZ
@ PROP_ROR
@ PROP_MAXS
@ PROP_AND
@ PROP_MINS
@ PROP_WAITPNE
@ PROP_RDLONG
@ PROP_ADDABS
@ PROP_ADDS
@ PROP_MOV
@ PROP_WAITCNT
@ PROP_MUXNZ
@ PROP_MUXNC
@ PROP_SUMZ
@ PROP_WAITVID
@ PROP_HUBOP
@ PROP_ADD
@ PROP_SUMC
@ PROP_SUBS
@ PROP_ROL
@ PROP_OR
@ PROP_MAX
@ PROP_JMP
@ PROP_DJNZ
@ PROP_CMPS
@ PROP_SUB
@ PROP_SUBSX
@ PROP_CMPSX
@ PROP_ABS
@ PROP_IF_BE
@ PROP_IF_B
@ PROP_IF_C_NE_Z
@ PROP_IF_NZ_OR_C
@ PROP_IF_ALWAYS
@ PROP_IF_E
@ PROP_IF_AE
@ PROP_IF_C_AND_Z
@ PROP_IF_C_AND_NZ
@ PROP_IF_Z_OR_NC
@ PROP_IF_NC_AND_Z
@ PROP_IF_C_EQ_Z
@ PROP_IF_NEVER
@ PROP_IF_NE
@ PROP_IF_NZ_OR_NC
@ PROP_IF_A
#define PROP_INSTR_MAXLEN
@ PROP_LOCKNEW
@ PROP_CLKSET
@ PROP_COGSTOP
@ PROP_LOCKRET
@ PROP_LOCKSET
@ PROP_COGINIT
@ PROP_LOCKCLR
@ PROP_COGID
static ut32 rz_read_be32(const void *src)
Definition: rz_endian.h:87