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