cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

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
     24typedef 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
     33static 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
     51static 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
     86static 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
    105static 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
    130static const char size[] = {'b', 'w', 'l'};
    131static const char cond[][4] = {
    132    "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n",
    133    "ge", "lt", "gt", "le", "o", "no", "ra", "f"
    134};
    135static const char psw[] = {
    136    'c', 'z', 's', 'o', 0, 0, 0, 0,
    137    'i', 'u', 0, 0, 0, 0, 0, 0,
    138};
    139
    140static 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
    172static 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
    186static 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] */
    196static 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 */
    209static 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 */
    224static 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] */
    232static 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 */
    245static 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] */
    252static 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 */
    263static 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] */
    286static 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 */
    298static 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 */
    309static 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 */
    321static 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 */
    328static 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 */
    336static 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 */
    347static bool trans_POP(DisasContext *ctx, arg_POP *a)
    348{
    349    prt("pop\tr%d", a->rd);
    350    return true;
    351}
    352
    353/* popc rx */
    354static 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 */
    361static 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 */
    368static 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] */
    375static 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 */
    385static 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*/
    392static 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 */
    399static 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 */
    405static 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 */
    412static 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 */
    419static 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 */
    426static 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 */
    433static 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 */
    441static 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 */
    449static 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 */
    456static 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 */
    464static 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 */
    472static 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 */
    479static 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 */
    486static 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 */
    494static 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 */
    501static 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 */
    509static 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 */
    517static 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 */
    529static 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 */
    540static 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 */
    547static 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 */
    554static 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 */
    565static 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 */
    577static 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 */
    584static 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 */
    593static 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 */
    601static 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 */
    608static 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 */
    616static 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 */
    623static 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 */
    630static 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 */
    637static 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 */
    645static 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 */
    656static 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 */
    664static 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 */
    671static 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 */
    679static 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 */
    687static 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 */
    695static 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 */
    702static 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 */
    709static 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 */
    717static 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 */
    724static 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 */
    732static 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 */
    739static 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 */
    747static 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 */
    754static 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 */
    762static 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 */
    771static 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 */
    782static 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 */
    790static 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 */
    801static 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 */
    809static 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 */
    820static 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 */
    827static bool trans_ROLC(DisasContext *ctx, arg_ROLC *a)
    828{
    829    prt("rorc\tr%d", a->rd);
    830    return true;
    831}
    832
    833/* rorc rd */
    834static 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 */
    841static 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 */
    848static 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 */
    855static 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 */
    862static 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 */
    869static 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 */
    876static 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 */
    883static 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 */
    898static 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 */
    908static 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 */
    915static 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 */
    922static bool trans_JMP(DisasContext *ctx, arg_JMP *a)
    923{
    924    prt("jmp\tr%d", a->rs);
    925    return true;
    926}
    927
    928/* jsr rs */
    929static 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 */
    937static 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 */
    945static 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 */
    952static bool trans_RTS(DisasContext *ctx, arg_RTS *a)
    953{
    954    prt("rts");
    955    return true;
    956}
    957
    958/* nop */
    959static bool trans_NOP(DisasContext *ctx, arg_NOP *a)
    960{
    961    prt("nop");
    962    return true;
    963}
    964
    965/* scmpu */
    966static bool trans_SCMPU(DisasContext *ctx, arg_SCMPU *a)
    967{
    968    prt("scmpu");
    969    return true;
    970}
    971
    972/* smovu */
    973static bool trans_SMOVU(DisasContext *ctx, arg_SMOVU *a)
    974{
    975    prt("smovu");
    976    return true;
    977}
    978
    979/* smovf */
    980static bool trans_SMOVF(DisasContext *ctx, arg_SMOVF *a)
    981{
    982    prt("smovf");
    983    return true;
    984}
    985
    986/* smovb */
    987static bool trans_SMOVB(DisasContext *ctx, arg_SMOVB *a)
    988{
    989    prt("smovb");
    990    return true;
    991}
    992
    993/* suntile */
    994static bool trans_SUNTIL(DisasContext *ctx, arg_SUNTIL *a)
    995{
    996    prt("suntil.%c", size[a->sz]);
    997    return true;
    998}
    999
   1000/* swhile */
   1001static bool trans_SWHILE(DisasContext *ctx, arg_SWHILE *a)
   1002{
   1003    prt("swhile.%c", size[a->sz]);
   1004    return true;
   1005}
   1006/* sstr */
   1007static bool trans_SSTR(DisasContext *ctx, arg_SSTR *a)
   1008{
   1009    prt("sstr.%c", size[a->sz]);
   1010    return true;
   1011}
   1012
   1013/* rmpa */
   1014static 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 */
   1021static 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 */
   1028static 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 */
   1035static 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 */
   1042static 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 */
   1049static bool trans_MVFACHI(DisasContext *ctx, arg_MVFACHI *a)
   1050{
   1051    prt("mvfachi\tr%d", a->rd);
   1052    return true;
   1053}
   1054
   1055/* mvfacmi rd */
   1056static bool trans_MVFACMI(DisasContext *ctx, arg_MVFACMI *a)
   1057{
   1058    prt("mvfacmi\tr%d", a->rd);
   1059    return true;
   1060}
   1061
   1062/* mvtachi rs */
   1063static bool trans_MVTACHI(DisasContext *ctx, arg_MVTACHI *a)
   1064{
   1065    prt("mvtachi\tr%d", a->rs);
   1066    return true;
   1067}
   1068
   1069/* mvtaclo rs */
   1070static bool trans_MVTACLO(DisasContext *ctx, arg_MVTACLO *a)
   1071{
   1072    prt("mvtaclo\tr%d", a->rs);
   1073    return true;
   1074}
   1075
   1076/* racw #imm */
   1077static 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 */
   1084static bool trans_SAT(DisasContext *ctx, arg_SAT *a)
   1085{
   1086    prt("sat\tr%d", a->rd);
   1087    return true;
   1088}
   1089
   1090/* satr */
   1091static bool trans_SATR(DisasContext *ctx, arg_SATR *a)
   1092{
   1093    prt("satr");
   1094    return true;
   1095}
   1096
   1097/* fadd #imm, rd */
   1098static 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 */
   1106static 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 */
   1113static 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 */
   1121static 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 */
   1128static 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 */
   1136static 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 */
   1144static 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 */
   1151static 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 */
   1159static 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 */
   1166static 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 */
   1174static 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 */
   1182static 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 */
   1190static 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] */
   1213static bool trans_BSET_im(DisasContext *ctx, arg_BSET_im *a)
   1214{
   1215    BOP_IM(bset, a->rs);
   1216}
   1217
   1218/* bset rs, dsp[rd] */
   1219static bool trans_BSET_rm(DisasContext *ctx, arg_BSET_rm *a)
   1220{
   1221    BOP_RM(set);
   1222}
   1223
   1224/* bset rs, rd */
   1225static 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 */
   1232static 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] */
   1239static bool trans_BCLR_im(DisasContext *ctx, arg_BCLR_im *a)
   1240{
   1241    BOP_IM(clr, a->rs);
   1242}
   1243
   1244/* bclr rs, dsp[rd] */
   1245static bool trans_BCLR_rm(DisasContext *ctx, arg_BCLR_rm *a)
   1246{
   1247    BOP_RM(clr);
   1248}
   1249
   1250/* bclr rs, rd */
   1251static 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 */
   1258static 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] */
   1265static bool trans_BTST_im(DisasContext *ctx, arg_BTST_im *a)
   1266{
   1267    BOP_IM(tst, a->rs);
   1268}
   1269
   1270/* btst rs, dsp[rd] */
   1271static bool trans_BTST_rm(DisasContext *ctx, arg_BTST_rm *a)
   1272{
   1273    BOP_RM(tst);
   1274}
   1275
   1276/* btst rs, rd */
   1277static 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 */
   1284static 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] */
   1291static bool trans_BNOT_rm(DisasContext *ctx, arg_BNOT_rm *a)
   1292{
   1293    BOP_RM(not);
   1294}
   1295
   1296/* bnot rs, rd */
   1297static 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] */
   1304static bool trans_BNOT_im(DisasContext *ctx, arg_BNOT_im *a)
   1305{
   1306    BOP_IM(not, a->rs);
   1307}
   1308
   1309/* bnot #imm, rd */
   1310static 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] */
   1317static 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 */
   1327static 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 */
   1334static 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 */
   1341static 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 */
   1348static 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 */
   1355static 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 */
   1362static 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 */
   1369static 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 */
   1376static bool trans_RTFI(DisasContext *ctx, arg_RTFI *a)
   1377{
   1378    prt("rtfi");
   1379    return true;
   1380}
   1381
   1382/* rte */
   1383static bool trans_RTE(DisasContext *ctx, arg_RTE *a)
   1384{
   1385    prt("rte");
   1386    return true;
   1387}
   1388
   1389/* brk */
   1390static bool trans_BRK(DisasContext *ctx, arg_BRK *a)
   1391{
   1392    prt("brk");
   1393    return true;
   1394}
   1395
   1396/* int #imm */
   1397static bool trans_INT(DisasContext *ctx, arg_INT *a)
   1398{
   1399    prt("int\t#%d", a->imm);
   1400    return true;
   1401}
   1402
   1403/* wait */
   1404static 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] */
   1412static 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
   1424int 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}