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