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