qemu/target/rx/disas.c
<<
>>
Prefs
   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}
1447