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