xref: /openbmc/qemu/target/rx/disas.c (revision b4b9a0e3)
1 /*
2  * Renesas RX Disassembler
3  *
4  * Copyright (c) 2019 Yoshinori Sato <ysato@users.sourceforge.jp>
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;
28     uint8_t len;
29     uint8_t bytes[8];
30 } DisasContext;
31 
32 
33 static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn,
34                                   int i, int n)
35 {
36     uint32_t addr = ctx->addr;
37 
38     g_assert(ctx->len == i);
39     g_assert(n <= ARRAY_SIZE(ctx->bytes));
40 
41     while (++i <= n) {
42         ctx->dis->read_memory_func(addr++, &ctx->bytes[i - 1], 1, ctx->dis);
43         insn |= ctx->bytes[i - 1] << (32 - i * 8);
44     }
45     ctx->addr = addr;
46     ctx->len = n;
47 
48     return insn;
49 }
50 
51 static int32_t li(DisasContext *ctx, int sz)
52 {
53     uint32_t addr = ctx->addr;
54     uintptr_t len = ctx->len;
55 
56     switch (sz) {
57     case 1:
58         g_assert(len + 1 <= ARRAY_SIZE(ctx->bytes));
59         ctx->addr += 1;
60         ctx->len += 1;
61         ctx->dis->read_memory_func(addr, ctx->bytes + len, 1, ctx->dis);
62         return (int8_t)ctx->bytes[len];
63     case 2:
64         g_assert(len + 2 <= ARRAY_SIZE(ctx->bytes));
65         ctx->addr += 2;
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);
69     case 3:
70         g_assert(len + 3 <= ARRAY_SIZE(ctx->bytes));
71         ctx->addr += 3;
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);
75     case 0:
76         g_assert(len + 4 <= ARRAY_SIZE(ctx->bytes));
77         ctx->addr += 4;
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);
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-insns.c.inc"
104 
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)
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 
140 static void rx_index_addr(DisasContext *ctx, char out[8], int ld, int mi)
141 {
142     uint32_t addr = ctx->addr;
143     uintptr_t len = ctx->len;
144     uint16_t dsp;
145 
146     switch (ld) {
147     case 0:
148         /* No index; return empty string.  */
149         out[0] = '\0';
150         return;
151     case 1:
152         g_assert(len + 1 <= ARRAY_SIZE(ctx->bytes));
153         ctx->addr += 1;
154         ctx->len += 1;
155         ctx->dis->read_memory_func(addr, ctx->bytes + len, 1, ctx->dis);
156         dsp = ctx->bytes[len];
157         break;
158     case 2:
159         g_assert(len + 2 <= ARRAY_SIZE(ctx->bytes));
160         ctx->addr += 2;
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);
164         break;
165     default:
166         g_assert_not_reached();
167     }
168 
169     sprintf(out, "%u", dsp << (mi < 3 ? mi : 4 - mi));
170 }
171 
172 static void prt_ldmi(DisasContext *ctx, const char *insn,
173                      int ld, int mi, int rs, int rd)
174 {
175     static const char sizes[][4] = {".b", ".w", ".l", ".uw", ".ub"};
176     char dsp[8];
177 
178     if (ld < 3) {
179         rx_index_addr(ctx, dsp, ld, mi);
180         prt("%s\t%s[r%d]%s, r%d", insn, dsp, rs, sizes[mi], rd);
181     } else {
182         prt("%s\tr%d, r%d", insn, rs, rd);
183     }
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 {
265     char dspd[8], dsps[8], szc = size[a->sz];
266 
267     if (a->lds == 3 && a->ldd == 3) {
268         /* mov.[bwl] rs,rd */
269         prt("mov.%c\tr%d, r%d", szc, a->rs, a->rd);
270     } else if (a->lds == 3) {
271         rx_index_addr(ctx, dspd, a->ldd, a->sz);
272         prt("mov.%c\tr%d, %s[r%d]", szc, a->rs, dspd, a->rd);
273     } else if (a->ldd == 3) {
274         rx_index_addr(ctx, dsps, a->lds, a->sz);
275         prt("mov.%c\t%s[r%d], r%d", szc, dsps, a->rs, a->rd);
276     } else {
277         rx_index_addr(ctx, dsps, a->lds, a->sz);
278         rx_index_addr(ctx, dspd, a->ldd, a->sz);
279         prt("mov.%c\t%s[r%d], %s[r%d]", szc, dsps, a->rs, dspd, a->rd);
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 {
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     }
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 {
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     }
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 {
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     }
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 {
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);
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 {
407     prt_ldmi(ctx, "xchg", a->ld, a->mi, a->rs, a->rd);
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 {
451     prt_ldmi(ctx, "and", a->ld, a->mi, a->rs, a->rd);
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 {
474     prt_ldmi(ctx, "or", a->ld, a->mi, a->rs, a->rd);
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 {
496     prt_ldmi(ctx, "xor", a->ld, a->mi, a->rs, a->rd);
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 {
511     prt_ldmi(ctx, "tst", a->ld, a->mi, a->rs, a->rd);
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 {
519     if (a->rs != a->rd) {
520         prt("not\tr%d, r%d", a->rs, a->rd);
521     } else {
522         prt("not\tr%d", a->rs);
523     }
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 {
531     if (a->rs != a->rd) {
532         prt("neg\tr%d, r%d", a->rs, a->rd);
533     } else {
534         prt("neg\tr%d", a->rs);
535     }
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 {
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);
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 {
579     prt_ldmi(ctx, "add", a->ld, a->mi, a->rs, a->rd);
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 {
603     prt_ldmi(ctx, "cmp", a->ld, a->mi, a->rs, a->rd);
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 {
618     prt_ldmi(ctx, "sub", a->ld, a->mi, a->rs, a->rd);
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 {
639     prt_ldmi(ctx, "sbb", a->ld, RX_IM_LONG, a->rs, a->rd);
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 {
647     if (a->rs != a->rd) {
648         prt("abs\tr%d, r%d", a->rs, a->rd);
649     } else {
650         prt("abs\tr%d", a->rs);
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 {
666     prt_ldmi(ctx, "max", a->ld, a->mi, a->rs, a->rd);
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 {
681     prt_ldmi(ctx, "min", a->ld, a->mi, a->rs, a->rd);
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 {
697     prt_ldmi(ctx, "mul", a->ld, a->mi, a->rs, a->rd);
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 {
719     prt_ldmi(ctx, "emul", a->ld, a->mi, a->rs, a->rd);
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 {
734     prt_ldmi(ctx, "emulu", a->ld, a->mi, a->rs, a->rd);
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 {
749     prt_ldmi(ctx, "div", a->ld, a->mi, a->rs, a->rd);
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 {
764     prt_ldmi(ctx, "divu", a->ld, a->mi, a->rs, a->rd);
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 {
773     if (a->rs2 != a->rd) {
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);
777     }
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 {
792     if (a->rs2 != a->rd) {
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);
796     }
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 {
811     if (a->rs2 != a->rd) {
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);
815     }
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 {
1108     prt_ldmi(ctx, "fadd", a->ld, RX_IM_LONG, a->rs, a->rd);
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 {
1123     prt_ldmi(ctx, "fcmp", a->ld, RX_IM_LONG, a->rs, a->rd);
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 {
1138     prt_ldmi(ctx, "fsub", a->ld, RX_IM_LONG, a->rs, a->rd);
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 {
1146     prt_ldmi(ctx, "ftoi", a->ld, RX_IM_LONG, a->rs, a->rd);
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 {
1161     prt_ldmi(ctx, "fmul", a->ld, RX_IM_LONG, a->rs, a->rd);
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 {
1176     prt_ldmi(ctx, "fdiv", a->ld, RX_IM_LONG, a->rs, a->rd);
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 {
1184     prt_ldmi(ctx, "round", a->ld, RX_IM_LONG, a->rs, a->rd);
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 {
1192     prt_ldmi(ctx, "itof", a->ld, RX_IM_LONG, a->rs, a->rd);
1193     return true;
1194 }
1195 
1196 #define BOP_IM(name, reg)                                       \
1197     do {                                                        \
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);      \
1201         return true;                                            \
1202     } while (0)
1203 
1204 #define BOP_RM(name)                                            \
1205     do {                                                        \
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);     \
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 {
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);
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 {
1414     if (a->ld < 3) {
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);
1418     } else {
1419         prt("sc%s.%c\tr%d", cond[a->cd], size[a->sz], a->rd);
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;
1429 
1430     ctx.dis = dis;
1431     ctx.pc = ctx.addr = addr;
1432     ctx.len = 0;
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 }
1447