]>
Commit | Line | Data |
---|---|---|
4aea3d0c YS |
1 | /* |
2 | * Renesas RX Disassembler | |
3 | * | |
4 | * Copyright (c) 2019 Yoshinori Sato <[email protected]> | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms and conditions of the GNU General Public License, | |
8 | * version 2 or later, as published by the Free Software Foundation. | |
9 | * | |
10 | * This program is distributed in the hope it will be useful, but WITHOUT | |
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
13 | * more details. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License along with | |
16 | * this program. If not, see <http://www.gnu.org/licenses/>. | |
17 | */ | |
18 | ||
19 | #include "qemu/osdep.h" | |
20 | #include "disas/dis-asm.h" | |
21 | #include "qemu/bitops.h" | |
22 | #include "cpu.h" | |
23 | ||
24 | typedef struct DisasContext { | |
25 | disassemble_info *dis; | |
26 | uint32_t addr; | |
27 | uint32_t pc; | |
05a8599f RH |
28 | uint8_t len; |
29 | uint8_t bytes[8]; | |
4aea3d0c YS |
30 | } DisasContext; |
31 | ||
32 | ||
33 | static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn, | |
05a8599f | 34 | int i, int n) |
4aea3d0c | 35 | { |
05a8599f RH |
36 | uint32_t addr = ctx->addr; |
37 | ||
38 | g_assert(ctx->len == i); | |
39 | g_assert(n <= ARRAY_SIZE(ctx->bytes)); | |
40 | ||
4aea3d0c | 41 | while (++i <= n) { |
05a8599f RH |
42 | ctx->dis->read_memory_func(addr++, &ctx->bytes[i - 1], 1, ctx->dis); |
43 | insn |= ctx->bytes[i - 1] << (32 - i * 8); | |
4aea3d0c | 44 | } |
05a8599f RH |
45 | ctx->addr = addr; |
46 | ctx->len = n; | |
47 | ||
4aea3d0c YS |
48 | return insn; |
49 | } | |
50 | ||
51 | static int32_t li(DisasContext *ctx, int sz) | |
52 | { | |
05a8599f RH |
53 | uint32_t addr = ctx->addr; |
54 | uintptr_t len = ctx->len; | |
4aea3d0c YS |
55 | |
56 | switch (sz) { | |
57 | case 1: | |
05a8599f | 58 | g_assert(len + 1 <= ARRAY_SIZE(ctx->bytes)); |
4aea3d0c | 59 | ctx->addr += 1; |
05a8599f RH |
60 | ctx->len += 1; |
61 | ctx->dis->read_memory_func(addr, ctx->bytes + len, 1, ctx->dis); | |
62 | return (int8_t)ctx->bytes[len]; | |
4aea3d0c | 63 | case 2: |
05a8599f | 64 | g_assert(len + 2 <= ARRAY_SIZE(ctx->bytes)); |
4aea3d0c | 65 | ctx->addr += 2; |
05a8599f RH |
66 | ctx->len += 2; |
67 | ctx->dis->read_memory_func(addr, ctx->bytes + len, 2, ctx->dis); | |
68 | return ldsw_le_p(ctx->bytes + len); | |
4aea3d0c | 69 | case 3: |
05a8599f | 70 | g_assert(len + 3 <= ARRAY_SIZE(ctx->bytes)); |
4aea3d0c | 71 | ctx->addr += 3; |
05a8599f RH |
72 | ctx->len += 3; |
73 | ctx->dis->read_memory_func(addr, ctx->bytes + len, 3, ctx->dis); | |
74 | return (int8_t)ctx->bytes[len + 2] << 16 | lduw_le_p(ctx->bytes + len); | |
4aea3d0c | 75 | case 0: |
05a8599f | 76 | g_assert(len + 4 <= ARRAY_SIZE(ctx->bytes)); |
4aea3d0c | 77 | ctx->addr += 4; |
05a8599f RH |
78 | ctx->len += 4; |
79 | ctx->dis->read_memory_func(addr, ctx->bytes + len, 4, ctx->dis); | |
80 | return ldl_le_p(ctx->bytes + len); | |
4aea3d0c YS |
81 | default: |
82 | g_assert_not_reached(); | |
83 | } | |
84 | } | |
85 | ||
86 | static int bdsp_s(DisasContext *ctx, int d) | |
87 | { | |
88 | /* | |
89 | * 0 -> 8 | |
90 | * 1 -> 9 | |
91 | * 2 -> 10 | |
92 | * 3 -> 3 | |
93 | * : | |
94 | * 7 -> 7 | |
95 | */ | |
96 | if (d < 3) { | |
97 | d += 8; | |
98 | } | |
99 | return d; | |
100 | } | |
101 | ||
102 | /* Include the auto-generated decoder. */ | |
103 | #include "decode.inc.c" | |
104 | ||
e43917cc RH |
105 | static void dump_bytes(DisasContext *ctx) |
106 | { | |
107 | int i, len = ctx->len; | |
108 | ||
109 | for (i = 0; i < len; ++i) { | |
110 | ctx->dis->fprintf_func(ctx->dis->stream, "%02x ", ctx->bytes[i]); | |
111 | } | |
112 | ctx->dis->fprintf_func(ctx->dis->stream, "%*c", (8 - i) * 3, '\t'); | |
113 | } | |
114 | ||
115 | #define prt(...) \ | |
116 | do { \ | |
117 | dump_bytes(ctx); \ | |
118 | ctx->dis->fprintf_func(ctx->dis->stream, __VA_ARGS__); \ | |
119 | } while (0) | |
4aea3d0c YS |
120 | |
121 | #define RX_MEMORY_BYTE 0 | |
122 | #define RX_MEMORY_WORD 1 | |
123 | #define RX_MEMORY_LONG 2 | |
124 | ||
125 | #define RX_IM_BYTE 0 | |
126 | #define RX_IM_WORD 1 | |
127 | #define RX_IM_LONG 2 | |
128 | #define RX_IM_UWORD 3 | |
129 | ||
130 | static const char size[] = {'b', 'w', 'l'}; | |
131 | static const char cond[][4] = { | |
132 | "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n", | |
133 | "ge", "lt", "gt", "le", "o", "no", "ra", "f" | |
134 | }; | |
135 | static const char psw[] = { | |
136 | 'c', 'z', 's', 'o', 0, 0, 0, 0, | |
137 | 'i', 'u', 0, 0, 0, 0, 0, 0, | |
138 | }; | |
139 | ||
fa6289e2 | 140 | static void rx_index_addr(DisasContext *ctx, char out[8], int ld, int mi) |
4aea3d0c | 141 | { |
fa6289e2 | 142 | uint32_t addr = ctx->addr; |
05a8599f | 143 | uintptr_t len = ctx->len; |
fa6289e2 RH |
144 | uint16_t dsp; |
145 | ||
4aea3d0c YS |
146 | switch (ld) { |
147 | case 0: | |
fa6289e2 RH |
148 | /* No index; return empty string. */ |
149 | out[0] = '\0'; | |
150 | return; | |
4aea3d0c | 151 | case 1: |
05a8599f | 152 | g_assert(len + 1 <= ARRAY_SIZE(ctx->bytes)); |
4aea3d0c | 153 | ctx->addr += 1; |
05a8599f RH |
154 | ctx->len += 1; |
155 | ctx->dis->read_memory_func(addr, ctx->bytes + len, 1, ctx->dis); | |
156 | dsp = ctx->bytes[len]; | |
fa6289e2 | 157 | break; |
4aea3d0c | 158 | case 2: |
05a8599f | 159 | g_assert(len + 2 <= ARRAY_SIZE(ctx->bytes)); |
4aea3d0c | 160 | ctx->addr += 2; |
05a8599f RH |
161 | ctx->len += 2; |
162 | ctx->dis->read_memory_func(addr, ctx->bytes + len, 2, ctx->dis); | |
163 | dsp = lduw_le_p(ctx->bytes + len); | |
fa6289e2 RH |
164 | break; |
165 | default: | |
166 | g_assert_not_reached(); | |
4aea3d0c | 167 | } |
fa6289e2 RH |
168 | |
169 | sprintf(out, "%u", dsp << (mi < 3 ? mi : 4 - mi)); | |
4aea3d0c YS |
170 | } |
171 | ||
e283adea RH |
172 | static void prt_ldmi(DisasContext *ctx, const char *insn, |
173 | int ld, int mi, int rs, int rd) | |
4aea3d0c | 174 | { |
4aea3d0c | 175 | static const char sizes[][4] = {".b", ".w", ".l", ".uw", ".ub"}; |
fa6289e2 RH |
176 | char dsp[8]; |
177 | ||
4aea3d0c | 178 | if (ld < 3) { |
fa6289e2 | 179 | rx_index_addr(ctx, dsp, ld, mi); |
e283adea | 180 | prt("%s\t%s[r%d]%s, r%d", insn, dsp, rs, sizes[mi], rd); |
4aea3d0c | 181 | } else { |
e283adea | 182 | prt("%s\tr%d, r%d", insn, rs, rd); |
4aea3d0c | 183 | } |
4aea3d0c YS |
184 | } |
185 | ||
186 | static void prt_ir(DisasContext *ctx, const char *insn, int imm, int rd) | |
187 | { | |
188 | if (imm < 0x100) { | |
189 | prt("%s\t#%d, r%d", insn, imm, rd); | |
190 | } else { | |
191 | prt("%s\t#0x%08x, r%d", insn, imm, rd); | |
192 | } | |
193 | } | |
194 | ||
195 | /* mov.[bwl] rs,dsp:[rd] */ | |
196 | static bool trans_MOV_rm(DisasContext *ctx, arg_MOV_rm *a) | |
197 | { | |
198 | if (a->dsp > 0) { | |
199 | prt("mov.%c\tr%d,%d[r%d]", | |
200 | size[a->sz], a->rs, a->dsp << a->sz, a->rd); | |
201 | } else { | |
202 | prt("mov.%c\tr%d,[r%d]", | |
203 | size[a->sz], a->rs, a->rd); | |
204 | } | |
205 | return true; | |
206 | } | |
207 | ||
208 | /* mov.[bwl] dsp:[rs],rd */ | |
209 | static bool trans_MOV_mr(DisasContext *ctx, arg_MOV_mr *a) | |
210 | { | |
211 | if (a->dsp > 0) { | |
212 | prt("mov.%c\t%d[r%d], r%d", | |
213 | size[a->sz], a->dsp << a->sz, a->rs, a->rd); | |
214 | } else { | |
215 | prt("mov.%c\t[r%d], r%d", | |
216 | size[a->sz], a->rs, a->rd); | |
217 | } | |
218 | return true; | |
219 | } | |
220 | ||
221 | /* mov.l #uimm4,rd */ | |
222 | /* mov.l #uimm8,rd */ | |
223 | /* mov.l #imm,rd */ | |
224 | static bool trans_MOV_ir(DisasContext *ctx, arg_MOV_ir *a) | |
225 | { | |
226 | prt_ir(ctx, "mov.l", a->imm, a->rd); | |
227 | return true; | |
228 | } | |
229 | ||
230 | /* mov.[bwl] #uimm8,dsp:[rd] */ | |
231 | /* mov #imm, dsp:[rd] */ | |
232 | static bool trans_MOV_im(DisasContext *ctx, arg_MOV_im *a) | |
233 | { | |
234 | if (a->dsp > 0) { | |
235 | prt("mov.%c\t#%d,%d[r%d]", | |
236 | size[a->sz], a->imm, a->dsp << a->sz, a->rd); | |
237 | } else { | |
238 | prt("mov.%c\t#%d,[r%d]", | |
239 | size[a->sz], a->imm, a->rd); | |
240 | } | |
241 | return true; | |
242 | } | |
243 | ||
244 | /* mov.[bwl] [ri,rb],rd */ | |
245 | static bool trans_MOV_ar(DisasContext *ctx, arg_MOV_ar *a) | |
246 | { | |
247 | prt("mov.%c\t[r%d,r%d], r%d", size[a->sz], a->ri, a->rb, a->rd); | |
248 | return true; | |
249 | } | |
250 | ||
251 | /* mov.[bwl] rd,[ri,rb] */ | |
252 | static bool trans_MOV_ra(DisasContext *ctx, arg_MOV_ra *a) | |
253 | { | |
254 | prt("mov.%c\tr%d, [r%d, r%d]", size[a->sz], a->rs, a->ri, a->rb); | |
255 | return true; | |
256 | } | |
257 | ||
258 | ||
259 | /* mov.[bwl] dsp:[rs],dsp:[rd] */ | |
260 | /* mov.[bwl] rs,dsp:[rd] */ | |
261 | /* mov.[bwl] dsp:[rs],rd */ | |
262 | /* mov.[bwl] rs,rd */ | |
263 | static bool trans_MOV_mm(DisasContext *ctx, arg_MOV_mm *a) | |
264 | { | |
67eb12d8 | 265 | char dspd[8], dsps[8], szc = size[a->sz]; |
4aea3d0c | 266 | |
4aea3d0c YS |
267 | if (a->lds == 3 && a->ldd == 3) { |
268 | /* mov.[bwl] rs,rd */ | |
67eb12d8 RH |
269 | prt("mov.%c\tr%d, r%d", szc, a->rs, a->rd); |
270 | } else if (a->lds == 3) { | |
fa6289e2 | 271 | rx_index_addr(ctx, dspd, a->ldd, a->sz); |
67eb12d8 | 272 | prt("mov.%c\tr%d, %s[r%d]", szc, a->rs, dspd, a->rd); |
4aea3d0c | 273 | } else if (a->ldd == 3) { |
fa6289e2 | 274 | rx_index_addr(ctx, dsps, a->lds, a->sz); |
67eb12d8 | 275 | prt("mov.%c\t%s[r%d], r%d", szc, dsps, a->rs, a->rd); |
4aea3d0c | 276 | } else { |
fa6289e2 RH |
277 | rx_index_addr(ctx, dsps, a->lds, a->sz); |
278 | rx_index_addr(ctx, dspd, a->ldd, a->sz); | |
67eb12d8 | 279 | prt("mov.%c\t%s[r%d], %s[r%d]", szc, dsps, a->rs, dspd, a->rd); |
4aea3d0c YS |
280 | } |
281 | return true; | |
282 | } | |
283 | ||
284 | /* mov.[bwl] rs,[rd+] */ | |
285 | /* mov.[bwl] rs,[-rd] */ | |
286 | static bool trans_MOV_rp(DisasContext *ctx, arg_MOV_rp *a) | |
287 | { | |
67eb12d8 RH |
288 | if (a->ad) { |
289 | prt("mov.%c\tr%d, [-r%d]", size[a->sz], a->rs, a->rd); | |
290 | } else { | |
291 | prt("mov.%c\tr%d, [r%d+]", size[a->sz], a->rs, a->rd); | |
292 | } | |
4aea3d0c YS |
293 | return true; |
294 | } | |
295 | ||
296 | /* mov.[bwl] [rd+],rs */ | |
297 | /* mov.[bwl] [-rd],rs */ | |
298 | static bool trans_MOV_pr(DisasContext *ctx, arg_MOV_pr *a) | |
299 | { | |
67eb12d8 RH |
300 | if (a->ad) { |
301 | prt("mov.%c\t[-r%d], r%d", size[a->sz], a->rd, a->rs); | |
302 | } else { | |
303 | prt("mov.%c\t[r%d+], r%d", size[a->sz], a->rd, a->rs); | |
304 | } | |
4aea3d0c YS |
305 | return true; |
306 | } | |
307 | ||
308 | /* movu.[bw] dsp5:[rs],rd */ | |
309 | static bool trans_MOVU_mr(DisasContext *ctx, arg_MOVU_mr *a) | |
310 | { | |
311 | if (a->dsp > 0) { | |
312 | prt("movu.%c\t%d[r%d], r%d", size[a->sz], | |
313 | a->dsp << a->sz, a->rs, a->rd); | |
314 | } else { | |
315 | prt("movu.%c\t[r%d], r%d", size[a->sz], a->rs, a->rd); | |
316 | } | |
317 | return true; | |
318 | } | |
319 | ||
320 | /* movu.[bw] rs,rd */ | |
321 | static bool trans_MOVU_rr(DisasContext *ctx, arg_MOVU_rr *a) | |
322 | { | |
323 | prt("movu.%c\tr%d, r%d", size[a->sz], a->rs, a->rd); | |
324 | return true; | |
325 | } | |
326 | ||
327 | /* movu.[bw] [ri,rb],rd */ | |
328 | static bool trans_MOVU_ar(DisasContext *ctx, arg_MOVU_ar *a) | |
329 | { | |
330 | prt("mov.%c\t[r%d,r%d], r%d", size[a->sz], a->ri, a->rb, a->rd); | |
331 | return true; | |
332 | } | |
333 | ||
334 | /* movu.[bw] [rs+],rd */ | |
335 | /* movu.[bw] [-rs],rd */ | |
336 | static bool trans_MOVU_pr(DisasContext *ctx, arg_MOVU_pr *a) | |
337 | { | |
67eb12d8 RH |
338 | if (a->ad) { |
339 | prt("movu.%c\t[-r%d], r%d", size[a->sz], a->rd, a->rs); | |
340 | } else { | |
341 | prt("movu.%c\t[r%d+], r%d", size[a->sz], a->rd, a->rs); | |
342 | } | |
4aea3d0c YS |
343 | return true; |
344 | } | |
345 | ||
346 | /* pop rd */ | |
347 | static bool trans_POP(DisasContext *ctx, arg_POP *a) | |
348 | { | |
349 | prt("pop\tr%d", a->rd); | |
350 | return true; | |
351 | } | |
352 | ||
353 | /* popc rx */ | |
354 | static bool trans_POPC(DisasContext *ctx, arg_POPC *a) | |
355 | { | |
356 | prt("pop\tr%s", rx_crname(a->cr)); | |
357 | return true; | |
358 | } | |
359 | ||
360 | /* popm rd-rd2 */ | |
361 | static bool trans_POPM(DisasContext *ctx, arg_POPM *a) | |
362 | { | |
363 | prt("popm\tr%d-r%d", a->rd, a->rd2); | |
364 | return true; | |
365 | } | |
366 | ||
367 | /* push rs */ | |
368 | static bool trans_PUSH_r(DisasContext *ctx, arg_PUSH_r *a) | |
369 | { | |
370 | prt("push\tr%d", a->rs); | |
371 | return true; | |
372 | } | |
373 | ||
374 | /* push dsp[rs] */ | |
375 | static bool trans_PUSH_m(DisasContext *ctx, arg_PUSH_m *a) | |
376 | { | |
fa6289e2 RH |
377 | char dsp[8]; |
378 | ||
379 | rx_index_addr(ctx, dsp, a->ld, a->sz); | |
380 | prt("push\t%s[r%d]", dsp, a->rs); | |
4aea3d0c YS |
381 | return true; |
382 | } | |
383 | ||
384 | /* pushc rx */ | |
385 | static bool trans_PUSHC(DisasContext *ctx, arg_PUSHC *a) | |
386 | { | |
387 | prt("push\t%s", rx_crname(a->cr)); | |
388 | return true; | |
389 | } | |
390 | ||
391 | /* pushm rs-rs2*/ | |
392 | static bool trans_PUSHM(DisasContext *ctx, arg_PUSHM *a) | |
393 | { | |
394 | prt("pushm\tr%d-r%d", a->rs, a->rs2); | |
395 | return true; | |
396 | } | |
397 | ||
398 | /* xchg rs,rd */ | |
399 | static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr *a) | |
400 | { | |
401 | prt("xchg\tr%d, r%d", a->rs, a->rd); | |
402 | return true; | |
403 | } | |
404 | /* xchg dsp[rs].<mi>,rd */ | |
405 | static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a) | |
406 | { | |
5cf7c960 | 407 | prt_ldmi(ctx, "xchg", a->ld, a->mi, a->rs, a->rd); |
4aea3d0c YS |
408 | return true; |
409 | } | |
410 | ||
411 | /* stz #imm,rd */ | |
412 | static bool trans_STZ(DisasContext *ctx, arg_STZ *a) | |
413 | { | |
414 | prt_ir(ctx, "stz", a->imm, a->rd); | |
415 | return true; | |
416 | } | |
417 | ||
418 | /* stnz #imm,rd */ | |
419 | static bool trans_STNZ(DisasContext *ctx, arg_STNZ *a) | |
420 | { | |
421 | prt_ir(ctx, "stnz", a->imm, a->rd); | |
422 | return true; | |
423 | } | |
424 | ||
425 | /* rtsd #imm */ | |
426 | static bool trans_RTSD_i(DisasContext *ctx, arg_RTSD_i *a) | |
427 | { | |
428 | prt("rtsd\t#%d", a->imm << 2); | |
429 | return true; | |
430 | } | |
431 | ||
432 | /* rtsd #imm, rd-rd2 */ | |
433 | static bool trans_RTSD_irr(DisasContext *ctx, arg_RTSD_irr *a) | |
434 | { | |
435 | prt("rtsd\t#%d, r%d - r%d", a->imm << 2, a->rd, a->rd2); | |
436 | return true; | |
437 | } | |
438 | ||
439 | /* and #uimm:4, rd */ | |
440 | /* and #imm, rd */ | |
441 | static bool trans_AND_ir(DisasContext *ctx, arg_AND_ir *a) | |
442 | { | |
443 | prt_ir(ctx, "and", a->imm, a->rd); | |
444 | return true; | |
445 | } | |
446 | ||
447 | /* and dsp[rs], rd */ | |
448 | /* and rs,rd */ | |
449 | static bool trans_AND_mr(DisasContext *ctx, arg_AND_mr *a) | |
450 | { | |
e283adea | 451 | prt_ldmi(ctx, "and", a->ld, a->mi, a->rs, a->rd); |
4aea3d0c YS |
452 | return true; |
453 | } | |
454 | ||
455 | /* and rs,rs2,rd */ | |
456 | static bool trans_AND_rrr(DisasContext *ctx, arg_AND_rrr *a) | |
457 | { | |
458 | prt("and\tr%d,r%d, r%d", a->rs, a->rs2, a->rd); | |
459 | return true; | |
460 | } | |
461 | ||
462 | /* or #uimm:4, rd */ | |
463 | /* or #imm, rd */ | |
464 | static bool trans_OR_ir(DisasContext *ctx, arg_OR_ir *a) | |
465 | { | |
466 | prt_ir(ctx, "or", a->imm, a->rd); | |
467 | return true; | |
468 | } | |
469 | ||
470 | /* or dsp[rs], rd */ | |
471 | /* or rs,rd */ | |
472 | static bool trans_OR_mr(DisasContext *ctx, arg_OR_mr *a) | |
473 | { | |
e283adea | 474 | prt_ldmi(ctx, "or", a->ld, a->mi, a->rs, a->rd); |
4aea3d0c YS |
475 | return true; |
476 | } | |
477 | ||
478 | /* or rs,rs2,rd */ | |
479 | static bool trans_OR_rrr(DisasContext *ctx, arg_OR_rrr *a) | |
480 | { | |
481 | prt("or\tr%d, r%d, r%d", a->rs, a->rs2, a->rd); | |
482 | return true; | |
483 | } | |
484 | ||
485 | /* xor #imm, rd */ | |
486 | static bool trans_XOR_ir(DisasContext *ctx, arg_XOR_ir *a) | |
487 | { | |
488 | prt_ir(ctx, "xor", a->imm, a->rd); | |
489 | return true; | |
490 | } | |
491 | ||
492 | /* xor dsp[rs], rd */ | |
493 | /* xor rs,rd */ | |
494 | static bool trans_XOR_mr(DisasContext *ctx, arg_XOR_mr *a) | |
495 | { | |
e283adea | 496 | prt_ldmi(ctx, "xor", a->ld, a->mi, a->rs, a->rd); |
4aea3d0c YS |
497 | return true; |
498 | } | |
499 | ||
500 | /* tst #imm, rd */ | |
501 | static bool trans_TST_ir(DisasContext *ctx, arg_TST_ir *a) | |
502 | { | |
503 | prt_ir(ctx, "tst", a->imm, a->rd); | |
504 | return true; | |
505 | } | |
506 | ||
507 | /* tst dsp[rs], rd */ | |
508 | /* tst rs, rd */ | |
509 | static bool trans_TST_mr(DisasContext *ctx, arg_TST_mr *a) | |
510 | { | |
e283adea | 511 | prt_ldmi(ctx, "tst", a->ld, a->mi, a->rs, a->rd); |
4aea3d0c YS |
512 | return true; |
513 | } | |
514 | ||
515 | /* not rd */ | |
516 | /* not rs, rd */ | |
517 | static bool trans_NOT_rr(DisasContext *ctx, arg_NOT_rr *a) | |
518 | { | |
4aea3d0c | 519 | if (a->rs != a->rd) { |
67eb12d8 RH |
520 | prt("not\tr%d, r%d", a->rs, a->rd); |
521 | } else { | |
522 | prt("not\tr%d", a->rs); | |
4aea3d0c | 523 | } |
4aea3d0c YS |
524 | return true; |
525 | } | |
526 | ||
527 | /* neg rd */ | |
528 | /* neg rs, rd */ | |
529 | static bool trans_NEG_rr(DisasContext *ctx, arg_NEG_rr *a) | |
530 | { | |
4aea3d0c | 531 | if (a->rs != a->rd) { |
67eb12d8 RH |
532 | prt("neg\tr%d, r%d", a->rs, a->rd); |
533 | } else { | |
534 | prt("neg\tr%d", a->rs); | |
4aea3d0c | 535 | } |
4aea3d0c YS |
536 | return true; |
537 | } | |
538 | ||
539 | /* adc #imm, rd */ | |
540 | static bool trans_ADC_ir(DisasContext *ctx, arg_ADC_ir *a) | |
541 | { | |
542 | prt_ir(ctx, "adc", a->imm, a->rd); | |
543 | return true; | |
544 | } | |
545 | ||
546 | /* adc rs, rd */ | |
547 | static bool trans_ADC_rr(DisasContext *ctx, arg_ADC_rr *a) | |
548 | { | |
549 | prt("adc\tr%d, r%d", a->rs, a->rd); | |
550 | return true; | |
551 | } | |
552 | ||
553 | /* adc dsp[rs], rd */ | |
554 | static bool trans_ADC_mr(DisasContext *ctx, arg_ADC_mr *a) | |
555 | { | |
fa6289e2 RH |
556 | char dsp[8]; |
557 | ||
558 | rx_index_addr(ctx, dsp, a->ld, 2); | |
559 | prt("adc\t%s[r%d], r%d", dsp, a->rs, a->rd); | |
4aea3d0c YS |
560 | return true; |
561 | } | |
562 | ||
563 | /* add #uimm4, rd */ | |
564 | /* add #imm, rs, rd */ | |
565 | static bool trans_ADD_irr(DisasContext *ctx, arg_ADD_irr *a) | |
566 | { | |
567 | if (a->imm < 0x10 && a->rs2 == a->rd) { | |
568 | prt("add\t#%d, r%d", a->imm, a->rd); | |
569 | } else { | |
570 | prt("add\t#0x%08x, r%d, r%d", a->imm, a->rs2, a->rd); | |
571 | } | |
572 | return true; | |
573 | } | |
574 | ||
575 | /* add rs, rd */ | |
576 | /* add dsp[rs], rd */ | |
577 | static bool trans_ADD_mr(DisasContext *ctx, arg_ADD_mr *a) | |
578 | { | |
e283adea | 579 | prt_ldmi(ctx, "add", a->ld, a->mi, a->rs, a->rd); |
4aea3d0c YS |
580 | return true; |
581 | } | |
582 | ||
583 | /* add rs, rs2, rd */ | |
584 | static bool trans_ADD_rrr(DisasContext *ctx, arg_ADD_rrr *a) | |
585 | { | |
586 | prt("add\tr%d, r%d, r%d", a->rs, a->rs2, a->rd); | |
587 | return true; | |
588 | } | |
589 | ||
590 | /* cmp #imm4, rd */ | |
591 | /* cmp #imm8, rd */ | |
592 | /* cmp #imm, rs2 */ | |
593 | static bool trans_CMP_ir(DisasContext *ctx, arg_CMP_ir *a) | |
594 | { | |
595 | prt_ir(ctx, "cmp", a->imm, a->rs2); | |
596 | return true; | |
597 | } | |
598 | ||
599 | /* cmp rs, rs2 */ | |
600 | /* cmp dsp[rs], rs2 */ | |
601 | static bool trans_CMP_mr(DisasContext *ctx, arg_CMP_mr *a) | |
602 | { | |
e283adea | 603 | prt_ldmi(ctx, "cmp", a->ld, a->mi, a->rs, a->rd); |
4aea3d0c YS |
604 | return true; |
605 | } | |
606 | ||
607 | /* sub #imm4, rd */ | |
608 | static bool trans_SUB_ir(DisasContext *ctx, arg_SUB_ir *a) | |
609 | { | |
610 | prt("sub\t#%d, r%d", a->imm, a->rd); | |
611 | return true; | |
612 | } | |
613 | ||
614 | /* sub rs, rd */ | |
615 | /* sub dsp[rs], rd */ | |
616 | static bool trans_SUB_mr(DisasContext *ctx, arg_SUB_mr *a) | |
617 | { | |
e283adea | 618 | prt_ldmi(ctx, "sub", a->ld, a->mi, a->rs, a->rd); |
4aea3d0c YS |
619 | return true; |
620 | } | |
621 | ||
622 | /* sub rs, rs2, rd */ | |
623 | static bool trans_SUB_rrr(DisasContext *ctx, arg_SUB_rrr *a) | |
624 | { | |
625 | prt("sub\tr%d, r%d, r%d", a->rs, a->rs2, a->rd); | |
626 | return true; | |
627 | } | |
628 | ||
629 | /* sbb rs, rd */ | |
630 | static bool trans_SBB_rr(DisasContext *ctx, arg_SBB_rr *a) | |
631 | { | |
632 | prt("sbb\tr%d, r%d", a->rs, a->rd); | |
633 | return true; | |
634 | } | |
635 | ||
636 | /* sbb dsp[rs], rd */ | |
637 | static bool trans_SBB_mr(DisasContext *ctx, arg_SBB_mr *a) | |
638 | { | |
e283adea | 639 | prt_ldmi(ctx, "sbb", a->ld, RX_IM_LONG, a->rs, a->rd); |
4aea3d0c YS |
640 | return true; |
641 | } | |
642 | ||
643 | /* abs rd */ | |
644 | /* abs rs, rd */ | |
645 | static bool trans_ABS_rr(DisasContext *ctx, arg_ABS_rr *a) | |
646 | { | |
67eb12d8 RH |
647 | if (a->rs != a->rd) { |
648 | prt("abs\tr%d, r%d", a->rs, a->rd); | |
4aea3d0c | 649 | } else { |
67eb12d8 | 650 | prt("abs\tr%d", a->rs); |
4aea3d0c YS |
651 | } |
652 | return true; | |
653 | } | |
654 | ||
655 | /* max #imm, rd */ | |
656 | static bool trans_MAX_ir(DisasContext *ctx, arg_MAX_ir *a) | |
657 | { | |
658 | prt_ir(ctx, "max", a->imm, a->rd); | |
659 | return true; | |
660 | } | |
661 | ||
662 | /* max rs, rd */ | |
663 | /* max dsp[rs], rd */ | |
664 | static bool trans_MAX_mr(DisasContext *ctx, arg_MAX_mr *a) | |
665 | { | |
e283adea | 666 | prt_ldmi(ctx, "max", a->ld, a->mi, a->rs, a->rd); |
4aea3d0c YS |
667 | return true; |
668 | } | |
669 | ||
670 | /* min #imm, rd */ | |
671 | static bool trans_MIN_ir(DisasContext *ctx, arg_MIN_ir *a) | |
672 | { | |
673 | prt_ir(ctx, "min", a->imm, a->rd); | |
674 | return true; | |
675 | } | |
676 | ||
677 | /* min rs, rd */ | |
678 | /* min dsp[rs], rd */ | |
679 | static bool trans_MIN_mr(DisasContext *ctx, arg_MIN_mr *a) | |
680 | { | |
e283adea | 681 | prt_ldmi(ctx, "min", a->ld, a->mi, a->rs, a->rd); |
4aea3d0c YS |
682 | return true; |
683 | } | |
684 | ||
685 | /* mul #uimm4, rd */ | |
686 | /* mul #imm, rd */ | |
687 | static bool trans_MUL_ir(DisasContext *ctx, arg_MUL_ir *a) | |
688 | { | |
689 | prt_ir(ctx, "mul", a->imm, a->rd); | |
690 | return true; | |
691 | } | |
692 | ||
693 | /* mul rs, rd */ | |
694 | /* mul dsp[rs], rd */ | |
695 | static bool trans_MUL_mr(DisasContext *ctx, arg_MUL_mr *a) | |
696 | { | |
e283adea | 697 | prt_ldmi(ctx, "mul", a->ld, a->mi, a->rs, a->rd); |
4aea3d0c YS |
698 | return true; |
699 | } | |
700 | ||
701 | /* mul rs, rs2, rd */ | |
702 | static bool trans_MUL_rrr(DisasContext *ctx, arg_MUL_rrr *a) | |
703 | { | |
704 | prt("mul\tr%d,r%d,r%d", a->rs, a->rs2, a->rd); | |
705 | return true; | |
706 | } | |
707 | ||
708 | /* emul #imm, rd */ | |
709 | static bool trans_EMUL_ir(DisasContext *ctx, arg_EMUL_ir *a) | |
710 | { | |
711 | prt_ir(ctx, "emul", a->imm, a->rd); | |
712 | return true; | |
713 | } | |
714 | ||
715 | /* emul rs, rd */ | |
716 | /* emul dsp[rs], rd */ | |
717 | static bool trans_EMUL_mr(DisasContext *ctx, arg_EMUL_mr *a) | |
718 | { | |
e283adea | 719 | prt_ldmi(ctx, "emul", a->ld, a->mi, a->rs, a->rd); |
4aea3d0c YS |
720 | return true; |
721 | } | |
722 | ||
723 | /* emulu #imm, rd */ | |
724 | static bool trans_EMULU_ir(DisasContext *ctx, arg_EMULU_ir *a) | |
725 | { | |
726 | prt_ir(ctx, "emulu", a->imm, a->rd); | |
727 | return true; | |
728 | } | |
729 | ||
730 | /* emulu rs, rd */ | |
731 | /* emulu dsp[rs], rd */ | |
732 | static bool trans_EMULU_mr(DisasContext *ctx, arg_EMULU_mr *a) | |
733 | { | |
e283adea | 734 | prt_ldmi(ctx, "emulu", a->ld, a->mi, a->rs, a->rd); |
4aea3d0c YS |
735 | return true; |
736 | } | |
737 | ||
738 | /* div #imm, rd */ | |
739 | static bool trans_DIV_ir(DisasContext *ctx, arg_DIV_ir *a) | |
740 | { | |
741 | prt_ir(ctx, "div", a->imm, a->rd); | |
742 | return true; | |
743 | } | |
744 | ||
745 | /* div rs, rd */ | |
746 | /* div dsp[rs], rd */ | |
747 | static bool trans_DIV_mr(DisasContext *ctx, arg_DIV_mr *a) | |
748 | { | |
e283adea | 749 | prt_ldmi(ctx, "div", a->ld, a->mi, a->rs, a->rd); |
4aea3d0c YS |
750 | return true; |
751 | } | |
752 | ||
753 | /* divu #imm, rd */ | |
754 | static bool trans_DIVU_ir(DisasContext *ctx, arg_DIVU_ir *a) | |
755 | { | |
756 | prt_ir(ctx, "divu", a->imm, a->rd); | |
757 | return true; | |
758 | } | |
759 | ||
760 | /* divu rs, rd */ | |
761 | /* divu dsp[rs], rd */ | |
762 | static bool trans_DIVU_mr(DisasContext *ctx, arg_DIVU_mr *a) | |
763 | { | |
e283adea | 764 | prt_ldmi(ctx, "divu", a->ld, a->mi, a->rs, a->rd); |
4aea3d0c YS |
765 | return true; |
766 | } | |
767 | ||
768 | ||
769 | /* shll #imm:5, rd */ | |
770 | /* shll #imm:5, rs, rd */ | |
771 | static bool trans_SHLL_irr(DisasContext *ctx, arg_SHLL_irr *a) | |
772 | { | |
4aea3d0c | 773 | if (a->rs2 != a->rd) { |
67eb12d8 RH |
774 | prt("shll\t#%d, r%d, r%d", a->imm, a->rs2, a->rd); |
775 | } else { | |
776 | prt("shll\t#%d, r%d", a->imm, a->rd); | |
4aea3d0c | 777 | } |
4aea3d0c YS |
778 | return true; |
779 | } | |
780 | ||
781 | /* shll rs, rd */ | |
782 | static bool trans_SHLL_rr(DisasContext *ctx, arg_SHLL_rr *a) | |
783 | { | |
784 | prt("shll\tr%d, r%d", a->rs, a->rd); | |
785 | return true; | |
786 | } | |
787 | ||
788 | /* shar #imm:5, rd */ | |
789 | /* shar #imm:5, rs, rd */ | |
790 | static bool trans_SHAR_irr(DisasContext *ctx, arg_SHAR_irr *a) | |
791 | { | |
4aea3d0c | 792 | if (a->rs2 != a->rd) { |
67eb12d8 RH |
793 | prt("shar\t#%d, r%d, r%d", a->imm, a->rs2, a->rd); |
794 | } else { | |
795 | prt("shar\t#%d, r%d", a->imm, a->rd); | |
4aea3d0c | 796 | } |
4aea3d0c YS |
797 | return true; |
798 | } | |
799 | ||
800 | /* shar rs, rd */ | |
801 | static bool trans_SHAR_rr(DisasContext *ctx, arg_SHAR_rr *a) | |
802 | { | |
803 | prt("shar\tr%d, r%d", a->rs, a->rd); | |
804 | return true; | |
805 | } | |
806 | ||
807 | /* shlr #imm:5, rd */ | |
808 | /* shlr #imm:5, rs, rd */ | |
809 | static bool trans_SHLR_irr(DisasContext *ctx, arg_SHLR_irr *a) | |
810 | { | |
4aea3d0c | 811 | if (a->rs2 != a->rd) { |
67eb12d8 RH |
812 | prt("shlr\t#%d, r%d, r%d", a->imm, a->rs2, a->rd); |
813 | } else { | |
814 | prt("shlr\t#%d, r%d", a->imm, a->rd); | |
4aea3d0c | 815 | } |
4aea3d0c YS |
816 | return true; |
817 | } | |
818 | ||
819 | /* shlr rs, rd */ | |
820 | static bool trans_SHLR_rr(DisasContext *ctx, arg_SHLR_rr *a) | |
821 | { | |
822 | prt("shlr\tr%d, r%d", a->rs, a->rd); | |
823 | return true; | |
824 | } | |
825 | ||
826 | /* rolc rd */ | |
827 | static bool trans_ROLC(DisasContext *ctx, arg_ROLC *a) | |
828 | { | |
829 | prt("rorc\tr%d", a->rd); | |
830 | return true; | |
831 | } | |
832 | ||
833 | /* rorc rd */ | |
834 | static bool trans_RORC(DisasContext *ctx, arg_RORC *a) | |
835 | { | |
836 | prt("rorc\tr%d", a->rd); | |
837 | return true; | |
838 | } | |
839 | ||
840 | /* rotl #imm, rd */ | |
841 | static bool trans_ROTL_ir(DisasContext *ctx, arg_ROTL_ir *a) | |
842 | { | |
843 | prt("rotl\t#%d, r%d", a->imm, a->rd); | |
844 | return true; | |
845 | } | |
846 | ||
847 | /* rotl rs, rd */ | |
848 | static bool trans_ROTL_rr(DisasContext *ctx, arg_ROTL_rr *a) | |
849 | { | |
850 | prt("rotl\tr%d, r%d", a->rs, a->rd); | |
851 | return true; | |
852 | } | |
853 | ||
854 | /* rotr #imm, rd */ | |
855 | static bool trans_ROTR_ir(DisasContext *ctx, arg_ROTR_ir *a) | |
856 | { | |
857 | prt("rotr\t#%d, r%d", a->imm, a->rd); | |
858 | return true; | |
859 | } | |
860 | ||
861 | /* rotr rs, rd */ | |
862 | static bool trans_ROTR_rr(DisasContext *ctx, arg_ROTR_rr *a) | |
863 | { | |
864 | prt("rotr\tr%d, r%d", a->rs, a->rd); | |
865 | return true; | |
866 | } | |
867 | ||
868 | /* revl rs, rd */ | |
869 | static bool trans_REVL(DisasContext *ctx, arg_REVL *a) | |
870 | { | |
871 | prt("revl\tr%d, r%d", a->rs, a->rd); | |
872 | return true; | |
873 | } | |
874 | ||
875 | /* revw rs, rd */ | |
876 | static bool trans_REVW(DisasContext *ctx, arg_REVW *a) | |
877 | { | |
878 | prt("revw\tr%d, r%d", a->rs, a->rd); | |
879 | return true; | |
880 | } | |
881 | ||
882 | /* conditional branch helper */ | |
883 | static void rx_bcnd_main(DisasContext *ctx, int cd, int len, int dst) | |
884 | { | |
885 | static const char sz[] = {'s', 'b', 'w', 'a'}; | |
886 | prt("b%s.%c\t%08x", cond[cd], sz[len - 1], ctx->pc + dst); | |
887 | } | |
888 | ||
889 | /* beq dsp:3 / bne dsp:3 */ | |
890 | /* beq dsp:8 / bne dsp:8 */ | |
891 | /* bc dsp:8 / bnc dsp:8 */ | |
892 | /* bgtu dsp:8 / bleu dsp:8 */ | |
893 | /* bpz dsp:8 / bn dsp:8 */ | |
894 | /* bge dsp:8 / blt dsp:8 */ | |
895 | /* bgt dsp:8 / ble dsp:8 */ | |
896 | /* bo dsp:8 / bno dsp:8 */ | |
897 | /* beq dsp:16 / bne dsp:16 */ | |
898 | static bool trans_BCnd(DisasContext *ctx, arg_BCnd *a) | |
899 | { | |
900 | rx_bcnd_main(ctx, a->cd, a->sz, a->dsp); | |
901 | return true; | |
902 | } | |
903 | ||
904 | /* bra dsp:3 */ | |
905 | /* bra dsp:8 */ | |
906 | /* bra dsp:16 */ | |
907 | /* bra dsp:24 */ | |
908 | static bool trans_BRA(DisasContext *ctx, arg_BRA *a) | |
909 | { | |
910 | rx_bcnd_main(ctx, 14, a->sz, a->dsp); | |
911 | return true; | |
912 | } | |
913 | ||
914 | /* bra rs */ | |
915 | static bool trans_BRA_l(DisasContext *ctx, arg_BRA_l *a) | |
916 | { | |
917 | prt("bra.l\tr%d", a->rd); | |
918 | return true; | |
919 | } | |
920 | ||
921 | /* jmp rs */ | |
922 | static bool trans_JMP(DisasContext *ctx, arg_JMP *a) | |
923 | { | |
924 | prt("jmp\tr%d", a->rs); | |
925 | return true; | |
926 | } | |
927 | ||
928 | /* jsr rs */ | |
929 | static bool trans_JSR(DisasContext *ctx, arg_JSR *a) | |
930 | { | |
931 | prt("jsr\tr%d", a->rs); | |
932 | return true; | |
933 | } | |
934 | ||
935 | /* bsr dsp:16 */ | |
936 | /* bsr dsp:24 */ | |
937 | static bool trans_BSR(DisasContext *ctx, arg_BSR *a) | |
938 | { | |
939 | static const char sz[] = {'w', 'a'}; | |
940 | prt("bsr.%c\t%08x", sz[a->sz - 3], ctx->pc + a->dsp); | |
941 | return true; | |
942 | } | |
943 | ||
944 | /* bsr rs */ | |
945 | static bool trans_BSR_l(DisasContext *ctx, arg_BSR_l *a) | |
946 | { | |
947 | prt("bsr.l\tr%d", a->rd); | |
948 | return true; | |
949 | } | |
950 | ||
951 | /* rts */ | |
952 | static bool trans_RTS(DisasContext *ctx, arg_RTS *a) | |
953 | { | |
954 | prt("rts"); | |
955 | return true; | |
956 | } | |
957 | ||
958 | /* nop */ | |
959 | static bool trans_NOP(DisasContext *ctx, arg_NOP *a) | |
960 | { | |
961 | prt("nop"); | |
962 | return true; | |
963 | } | |
964 | ||
965 | /* scmpu */ | |
966 | static bool trans_SCMPU(DisasContext *ctx, arg_SCMPU *a) | |
967 | { | |
968 | prt("scmpu"); | |
969 | return true; | |
970 | } | |
971 | ||
972 | /* smovu */ | |
973 | static bool trans_SMOVU(DisasContext *ctx, arg_SMOVU *a) | |
974 | { | |
975 | prt("smovu"); | |
976 | return true; | |
977 | } | |
978 | ||
979 | /* smovf */ | |
980 | static bool trans_SMOVF(DisasContext *ctx, arg_SMOVF *a) | |
981 | { | |
982 | prt("smovf"); | |
983 | return true; | |
984 | } | |
985 | ||
986 | /* smovb */ | |
987 | static bool trans_SMOVB(DisasContext *ctx, arg_SMOVB *a) | |
988 | { | |
989 | prt("smovb"); | |
990 | return true; | |
991 | } | |
992 | ||
993 | /* suntile */ | |
994 | static bool trans_SUNTIL(DisasContext *ctx, arg_SUNTIL *a) | |
995 | { | |
996 | prt("suntil.%c", size[a->sz]); | |
997 | return true; | |
998 | } | |
999 | ||
1000 | /* swhile */ | |
1001 | static bool trans_SWHILE(DisasContext *ctx, arg_SWHILE *a) | |
1002 | { | |
1003 | prt("swhile.%c", size[a->sz]); | |
1004 | return true; | |
1005 | } | |
1006 | /* sstr */ | |
1007 | static bool trans_SSTR(DisasContext *ctx, arg_SSTR *a) | |
1008 | { | |
1009 | prt("sstr.%c", size[a->sz]); | |
1010 | return true; | |
1011 | } | |
1012 | ||
1013 | /* rmpa */ | |
1014 | static bool trans_RMPA(DisasContext *ctx, arg_RMPA *a) | |
1015 | { | |
1016 | prt("rmpa.%c", size[a->sz]); | |
1017 | return true; | |
1018 | } | |
1019 | ||
1020 | /* mulhi rs,rs2 */ | |
1021 | static bool trans_MULHI(DisasContext *ctx, arg_MULHI *a) | |
1022 | { | |
1023 | prt("mulhi\tr%d,r%d", a->rs, a->rs2); | |
1024 | return true; | |
1025 | } | |
1026 | ||
1027 | /* mullo rs,rs2 */ | |
1028 | static bool trans_MULLO(DisasContext *ctx, arg_MULLO *a) | |
1029 | { | |
1030 | prt("mullo\tr%d, r%d", a->rs, a->rs2); | |
1031 | return true; | |
1032 | } | |
1033 | ||
1034 | /* machi rs,rs2 */ | |
1035 | static bool trans_MACHI(DisasContext *ctx, arg_MACHI *a) | |
1036 | { | |
1037 | prt("machi\tr%d, r%d", a->rs, a->rs2); | |
1038 | return true; | |
1039 | } | |
1040 | ||
1041 | /* maclo rs,rs2 */ | |
1042 | static bool trans_MACLO(DisasContext *ctx, arg_MACLO *a) | |
1043 | { | |
1044 | prt("maclo\tr%d, r%d", a->rs, a->rs2); | |
1045 | return true; | |
1046 | } | |
1047 | ||
1048 | /* mvfachi rd */ | |
1049 | static bool trans_MVFACHI(DisasContext *ctx, arg_MVFACHI *a) | |
1050 | { | |
1051 | prt("mvfachi\tr%d", a->rd); | |
1052 | return true; | |
1053 | } | |
1054 | ||
1055 | /* mvfacmi rd */ | |
1056 | static bool trans_MVFACMI(DisasContext *ctx, arg_MVFACMI *a) | |
1057 | { | |
1058 | prt("mvfacmi\tr%d", a->rd); | |
1059 | return true; | |
1060 | } | |
1061 | ||
1062 | /* mvtachi rs */ | |
1063 | static bool trans_MVTACHI(DisasContext *ctx, arg_MVTACHI *a) | |
1064 | { | |
1065 | prt("mvtachi\tr%d", a->rs); | |
1066 | return true; | |
1067 | } | |
1068 | ||
1069 | /* mvtaclo rs */ | |
1070 | static bool trans_MVTACLO(DisasContext *ctx, arg_MVTACLO *a) | |
1071 | { | |
1072 | prt("mvtaclo\tr%d", a->rs); | |
1073 | return true; | |
1074 | } | |
1075 | ||
1076 | /* racw #imm */ | |
1077 | static bool trans_RACW(DisasContext *ctx, arg_RACW *a) | |
1078 | { | |
1079 | prt("racw\t#%d", a->imm + 1); | |
1080 | return true; | |
1081 | } | |
1082 | ||
1083 | /* sat rd */ | |
1084 | static bool trans_SAT(DisasContext *ctx, arg_SAT *a) | |
1085 | { | |
1086 | prt("sat\tr%d", a->rd); | |
1087 | return true; | |
1088 | } | |
1089 | ||
1090 | /* satr */ | |
1091 | static bool trans_SATR(DisasContext *ctx, arg_SATR *a) | |
1092 | { | |
1093 | prt("satr"); | |
1094 | return true; | |
1095 | } | |
1096 | ||
1097 | /* fadd #imm, rd */ | |
1098 | static bool trans_FADD_ir(DisasContext *ctx, arg_FADD_ir *a) | |
1099 | { | |
1100 | prt("fadd\t#%d,r%d", li(ctx, 0), a->rd); | |
1101 | return true; | |
1102 | } | |
1103 | ||
1104 | /* fadd dsp[rs], rd */ | |
1105 | /* fadd rs, rd */ | |
1106 | static bool trans_FADD_mr(DisasContext *ctx, arg_FADD_mr *a) | |
1107 | { | |
e283adea | 1108 | prt_ldmi(ctx, "fadd", a->ld, RX_IM_LONG, a->rs, a->rd); |
4aea3d0c YS |
1109 | return true; |
1110 | } | |
1111 | ||
1112 | /* fcmp #imm, rd */ | |
1113 | static bool trans_FCMP_ir(DisasContext *ctx, arg_FCMP_ir *a) | |
1114 | { | |
1115 | prt("fadd\t#%d,r%d", li(ctx, 0), a->rd); | |
1116 | return true; | |
1117 | } | |
1118 | ||
1119 | /* fcmp dsp[rs], rd */ | |
1120 | /* fcmp rs, rd */ | |
1121 | static bool trans_FCMP_mr(DisasContext *ctx, arg_FCMP_mr *a) | |
1122 | { | |
e283adea | 1123 | prt_ldmi(ctx, "fcmp", a->ld, RX_IM_LONG, a->rs, a->rd); |
4aea3d0c YS |
1124 | return true; |
1125 | } | |
1126 | ||
1127 | /* fsub #imm, rd */ | |
1128 | static bool trans_FSUB_ir(DisasContext *ctx, arg_FSUB_ir *a) | |
1129 | { | |
1130 | prt("fsub\t#%d,r%d", li(ctx, 0), a->rd); | |
1131 | return true; | |
1132 | } | |
1133 | ||
1134 | /* fsub dsp[rs], rd */ | |
1135 | /* fsub rs, rd */ | |
1136 | static bool trans_FSUB_mr(DisasContext *ctx, arg_FSUB_mr *a) | |
1137 | { | |
e283adea | 1138 | prt_ldmi(ctx, "fsub", a->ld, RX_IM_LONG, a->rs, a->rd); |
4aea3d0c YS |
1139 | return true; |
1140 | } | |
1141 | ||
1142 | /* ftoi dsp[rs], rd */ | |
1143 | /* ftoi rs, rd */ | |
1144 | static bool trans_FTOI(DisasContext *ctx, arg_FTOI *a) | |
1145 | { | |
e283adea | 1146 | prt_ldmi(ctx, "ftoi", a->ld, RX_IM_LONG, a->rs, a->rd); |
4aea3d0c YS |
1147 | return true; |
1148 | } | |
1149 | ||
1150 | /* fmul #imm, rd */ | |
1151 | static bool trans_FMUL_ir(DisasContext *ctx, arg_FMUL_ir *a) | |
1152 | { | |
1153 | prt("fmul\t#%d,r%d", li(ctx, 0), a->rd); | |
1154 | return true; | |
1155 | } | |
1156 | ||
1157 | /* fmul dsp[rs], rd */ | |
1158 | /* fmul rs, rd */ | |
1159 | static bool trans_FMUL_mr(DisasContext *ctx, arg_FMUL_mr *a) | |
1160 | { | |
e283adea | 1161 | prt_ldmi(ctx, "fmul", a->ld, RX_IM_LONG, a->rs, a->rd); |
4aea3d0c YS |
1162 | return true; |
1163 | } | |
1164 | ||
1165 | /* fdiv #imm, rd */ | |
1166 | static bool trans_FDIV_ir(DisasContext *ctx, arg_FDIV_ir *a) | |
1167 | { | |
1168 | prt("fdiv\t#%d,r%d", li(ctx, 0), a->rd); | |
1169 | return true; | |
1170 | } | |
1171 | ||
1172 | /* fdiv dsp[rs], rd */ | |
1173 | /* fdiv rs, rd */ | |
1174 | static bool trans_FDIV_mr(DisasContext *ctx, arg_FDIV_mr *a) | |
1175 | { | |
e283adea | 1176 | prt_ldmi(ctx, "fdiv", a->ld, RX_IM_LONG, a->rs, a->rd); |
4aea3d0c YS |
1177 | return true; |
1178 | } | |
1179 | ||
1180 | /* round dsp[rs], rd */ | |
1181 | /* round rs, rd */ | |
1182 | static bool trans_ROUND(DisasContext *ctx, arg_ROUND *a) | |
1183 | { | |
e283adea | 1184 | prt_ldmi(ctx, "round", a->ld, RX_IM_LONG, a->rs, a->rd); |
4aea3d0c YS |
1185 | return true; |
1186 | } | |
1187 | ||
1188 | /* itof rs, rd */ | |
1189 | /* itof dsp[rs], rd */ | |
1190 | static bool trans_ITOF(DisasContext *ctx, arg_ITOF *a) | |
1191 | { | |
e283adea | 1192 | prt_ldmi(ctx, "itof", a->ld, RX_IM_LONG, a->rs, a->rd); |
4aea3d0c YS |
1193 | return true; |
1194 | } | |
1195 | ||
1196 | #define BOP_IM(name, reg) \ | |
1197 | do { \ | |
fa6289e2 RH |
1198 | char dsp[8]; \ |
1199 | rx_index_addr(ctx, dsp, a->ld, RX_MEMORY_BYTE); \ | |
1200 | prt("b%s\t#%d, %s[r%d]", #name, a->imm, dsp, reg); \ | |
4aea3d0c YS |
1201 | return true; \ |
1202 | } while (0) | |
1203 | ||
1204 | #define BOP_RM(name) \ | |
1205 | do { \ | |
fa6289e2 RH |
1206 | char dsp[8]; \ |
1207 | rx_index_addr(ctx, dsp, a->ld, RX_MEMORY_BYTE); \ | |
1208 | prt("b%s\tr%d, %s[r%d]", #name, a->rd, dsp, a->rs); \ | |
4aea3d0c YS |
1209 | return true; \ |
1210 | } while (0) | |
1211 | ||
1212 | /* bset #imm, dsp[rd] */ | |
1213 | static bool trans_BSET_im(DisasContext *ctx, arg_BSET_im *a) | |
1214 | { | |
1215 | BOP_IM(bset, a->rs); | |
1216 | } | |
1217 | ||
1218 | /* bset rs, dsp[rd] */ | |
1219 | static bool trans_BSET_rm(DisasContext *ctx, arg_BSET_rm *a) | |
1220 | { | |
1221 | BOP_RM(set); | |
1222 | } | |
1223 | ||
1224 | /* bset rs, rd */ | |
1225 | static bool trans_BSET_rr(DisasContext *ctx, arg_BSET_rr *a) | |
1226 | { | |
1227 | prt("bset\tr%d,r%d", a->rs, a->rd); | |
1228 | return true; | |
1229 | } | |
1230 | ||
1231 | /* bset #imm, rd */ | |
1232 | static bool trans_BSET_ir(DisasContext *ctx, arg_BSET_ir *a) | |
1233 | { | |
1234 | prt("bset\t#%d, r%d", a->imm, a->rd); | |
1235 | return true; | |
1236 | } | |
1237 | ||
1238 | /* bclr #imm, dsp[rd] */ | |
1239 | static bool trans_BCLR_im(DisasContext *ctx, arg_BCLR_im *a) | |
1240 | { | |
1241 | BOP_IM(clr, a->rs); | |
1242 | } | |
1243 | ||
1244 | /* bclr rs, dsp[rd] */ | |
1245 | static bool trans_BCLR_rm(DisasContext *ctx, arg_BCLR_rm *a) | |
1246 | { | |
1247 | BOP_RM(clr); | |
1248 | } | |
1249 | ||
1250 | /* bclr rs, rd */ | |
1251 | static bool trans_BCLR_rr(DisasContext *ctx, arg_BCLR_rr *a) | |
1252 | { | |
1253 | prt("bclr\tr%d, r%d", a->rs, a->rd); | |
1254 | return true; | |
1255 | } | |
1256 | ||
1257 | /* bclr #imm, rd */ | |
1258 | static bool trans_BCLR_ir(DisasContext *ctx, arg_BCLR_ir *a) | |
1259 | { | |
1260 | prt("bclr\t#%d,r%d", a->imm, a->rd); | |
1261 | return true; | |
1262 | } | |
1263 | ||
1264 | /* btst #imm, dsp[rd] */ | |
1265 | static bool trans_BTST_im(DisasContext *ctx, arg_BTST_im *a) | |
1266 | { | |
1267 | BOP_IM(tst, a->rs); | |
1268 | } | |
1269 | ||
1270 | /* btst rs, dsp[rd] */ | |
1271 | static bool trans_BTST_rm(DisasContext *ctx, arg_BTST_rm *a) | |
1272 | { | |
1273 | BOP_RM(tst); | |
1274 | } | |
1275 | ||
1276 | /* btst rs, rd */ | |
1277 | static bool trans_BTST_rr(DisasContext *ctx, arg_BTST_rr *a) | |
1278 | { | |
1279 | prt("btst\tr%d, r%d", a->rs, a->rd); | |
1280 | return true; | |
1281 | } | |
1282 | ||
1283 | /* btst #imm, rd */ | |
1284 | static bool trans_BTST_ir(DisasContext *ctx, arg_BTST_ir *a) | |
1285 | { | |
1286 | prt("btst\t#%d, r%d", a->imm, a->rd); | |
1287 | return true; | |
1288 | } | |
1289 | ||
1290 | /* bnot rs, dsp[rd] */ | |
1291 | static bool trans_BNOT_rm(DisasContext *ctx, arg_BNOT_rm *a) | |
1292 | { | |
1293 | BOP_RM(not); | |
1294 | } | |
1295 | ||
1296 | /* bnot rs, rd */ | |
1297 | static bool trans_BNOT_rr(DisasContext *ctx, arg_BNOT_rr *a) | |
1298 | { | |
1299 | prt("bnot\tr%d, r%d", a->rs, a->rd); | |
1300 | return true; | |
1301 | } | |
1302 | ||
1303 | /* bnot #imm, dsp[rd] */ | |
1304 | static bool trans_BNOT_im(DisasContext *ctx, arg_BNOT_im *a) | |
1305 | { | |
1306 | BOP_IM(not, a->rs); | |
1307 | } | |
1308 | ||
1309 | /* bnot #imm, rd */ | |
1310 | static bool trans_BNOT_ir(DisasContext *ctx, arg_BNOT_ir *a) | |
1311 | { | |
1312 | prt("bnot\t#%d, r%d", a->imm, a->rd); | |
1313 | return true; | |
1314 | } | |
1315 | ||
1316 | /* bmcond #imm, dsp[rd] */ | |
1317 | static bool trans_BMCnd_im(DisasContext *ctx, arg_BMCnd_im *a) | |
1318 | { | |
fa6289e2 RH |
1319 | char dsp[8]; |
1320 | ||
1321 | rx_index_addr(ctx, dsp, a->ld, RX_MEMORY_BYTE); | |
1322 | prt("bm%s\t#%d, %s[r%d]", cond[a->cd], a->imm, dsp, a->rd); | |
4aea3d0c YS |
1323 | return true; |
1324 | } | |
1325 | ||
1326 | /* bmcond #imm, rd */ | |
1327 | static bool trans_BMCnd_ir(DisasContext *ctx, arg_BMCnd_ir *a) | |
1328 | { | |
1329 | prt("bm%s\t#%d, r%d", cond[a->cd], a->imm, a->rd); | |
1330 | return true; | |
1331 | } | |
1332 | ||
1333 | /* clrpsw psw */ | |
1334 | static bool trans_CLRPSW(DisasContext *ctx, arg_CLRPSW *a) | |
1335 | { | |
1336 | prt("clrpsw\t%c", psw[a->cb]); | |
1337 | return true; | |
1338 | } | |
1339 | ||
1340 | /* setpsw psw */ | |
1341 | static bool trans_SETPSW(DisasContext *ctx, arg_SETPSW *a) | |
1342 | { | |
1343 | prt("setpsw\t%c", psw[a->cb]); | |
1344 | return true; | |
1345 | } | |
1346 | ||
1347 | /* mvtipl #imm */ | |
1348 | static bool trans_MVTIPL(DisasContext *ctx, arg_MVTIPL *a) | |
1349 | { | |
1350 | prt("movtipl\t#%d", a->imm); | |
1351 | return true; | |
1352 | } | |
1353 | ||
1354 | /* mvtc #imm, rd */ | |
1355 | static bool trans_MVTC_i(DisasContext *ctx, arg_MVTC_i *a) | |
1356 | { | |
1357 | prt("mvtc\t#0x%08x, %s", a->imm, rx_crname(a->cr)); | |
1358 | return true; | |
1359 | } | |
1360 | ||
1361 | /* mvtc rs, rd */ | |
1362 | static bool trans_MVTC_r(DisasContext *ctx, arg_MVTC_r *a) | |
1363 | { | |
1364 | prt("mvtc\tr%d, %s", a->rs, rx_crname(a->cr)); | |
1365 | return true; | |
1366 | } | |
1367 | ||
1368 | /* mvfc rs, rd */ | |
1369 | static bool trans_MVFC(DisasContext *ctx, arg_MVFC *a) | |
1370 | { | |
1371 | prt("mvfc\t%s, r%d", rx_crname(a->cr), a->rd); | |
1372 | return true; | |
1373 | } | |
1374 | ||
1375 | /* rtfi */ | |
1376 | static bool trans_RTFI(DisasContext *ctx, arg_RTFI *a) | |
1377 | { | |
1378 | prt("rtfi"); | |
1379 | return true; | |
1380 | } | |
1381 | ||
1382 | /* rte */ | |
1383 | static bool trans_RTE(DisasContext *ctx, arg_RTE *a) | |
1384 | { | |
1385 | prt("rte"); | |
1386 | return true; | |
1387 | } | |
1388 | ||
1389 | /* brk */ | |
1390 | static bool trans_BRK(DisasContext *ctx, arg_BRK *a) | |
1391 | { | |
1392 | prt("brk"); | |
1393 | return true; | |
1394 | } | |
1395 | ||
1396 | /* int #imm */ | |
1397 | static bool trans_INT(DisasContext *ctx, arg_INT *a) | |
1398 | { | |
1399 | prt("int\t#%d", a->imm); | |
1400 | return true; | |
1401 | } | |
1402 | ||
1403 | /* wait */ | |
1404 | static bool trans_WAIT(DisasContext *ctx, arg_WAIT *a) | |
1405 | { | |
1406 | prt("wait"); | |
1407 | return true; | |
1408 | } | |
1409 | ||
1410 | /* sccnd.[bwl] rd */ | |
1411 | /* sccnd.[bwl] dsp:[rd] */ | |
1412 | static bool trans_SCCnd(DisasContext *ctx, arg_SCCnd *a) | |
1413 | { | |
4aea3d0c | 1414 | if (a->ld < 3) { |
fa6289e2 RH |
1415 | char dsp[8]; |
1416 | rx_index_addr(ctx, dsp, a->sz, a->ld); | |
1417 | prt("sc%s.%c\t%s[r%d]", cond[a->cd], size[a->sz], dsp, a->rd); | |
4aea3d0c | 1418 | } else { |
fa6289e2 | 1419 | prt("sc%s.%c\tr%d", cond[a->cd], size[a->sz], a->rd); |
4aea3d0c YS |
1420 | } |
1421 | return true; | |
1422 | } | |
1423 | ||
1424 | int print_insn_rx(bfd_vma addr, disassemble_info *dis) | |
1425 | { | |
1426 | DisasContext ctx; | |
1427 | uint32_t insn; | |
1428 | int i; | |
05a8599f | 1429 | |
4aea3d0c YS |
1430 | ctx.dis = dis; |
1431 | ctx.pc = ctx.addr = addr; | |
05a8599f | 1432 | ctx.len = 0; |
4aea3d0c YS |
1433 | |
1434 | insn = decode_load(&ctx); | |
1435 | if (!decode(&ctx, insn)) { | |
1436 | ctx.dis->fprintf_func(ctx.dis->stream, ".byte\t"); | |
1437 | for (i = 0; i < ctx.addr - addr; i++) { | |
1438 | if (i > 0) { | |
1439 | ctx.dis->fprintf_func(ctx.dis->stream, ","); | |
1440 | } | |
1441 | ctx.dis->fprintf_func(ctx.dis->stream, "0x%02x", insn >> 24); | |
1442 | insn <<= 8; | |
1443 | } | |
1444 | } | |
1445 | return ctx.addr - addr; | |
1446 | } |