qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

disas.c (32065B)


      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-insns.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 }