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