From patchwork Sat Mar 2 06:21:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yoshinori Sato X-Patchwork-Id: 10836479 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 61525139A for ; Sat, 2 Mar 2019 06:25:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 44FE32D22A for ; Sat, 2 Mar 2019 06:25:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 349032D23E; Sat, 2 Mar 2019 06:25:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id EDCCD2D22A for ; Sat, 2 Mar 2019 06:25:19 +0000 (UTC) Received: from localhost ([127.0.0.1]:49120 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gzy5G-0003o2-AH for patchwork-qemu-devel@patchwork.kernel.org; Sat, 02 Mar 2019 01:25:18 -0500 Received: from eggs.gnu.org ([209.51.188.92]:49488) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gzy3x-0002vM-As for qemu-devel@nongnu.org; Sat, 02 Mar 2019 01:24:00 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gzy2C-00032q-7O for qemu-devel@nongnu.org; Sat, 02 Mar 2019 01:22:12 -0500 Received: from mail01.asahi-net.or.jp ([202.224.55.13]:48764) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gzy2B-0002sx-5H for qemu-devel@nongnu.org; Sat, 02 Mar 2019 01:22:07 -0500 Received: from h61-195-96-97.vps.ablenet.jp (h61-195-96-97.vps.ablenet.jp [61.195.96.97]) (Authenticated sender: PQ4Y-STU) by mail01.asahi-net.or.jp (Postfix) with ESMTPA id E1C1010C3AF; Sat, 2 Mar 2019 15:21:49 +0900 (JST) Received: from ysato.dip.jp (ZM005235.ppp.dion.ne.jp [222.8.5.235]) by h61-195-96-97.vps.ablenet.jp (Postfix) with ESMTPSA id 9778A240089; Sat, 2 Mar 2019 15:21:49 +0900 (JST) From: Yoshinori Sato To: qemu-devel@nongnu.org Date: Sat, 2 Mar 2019 15:21:31 +0900 Message-Id: <20190302062138.10713-5-ysato@users.sourceforge.jp> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190302062138.10713-1-ysato@users.sourceforge.jp> References: <20190122121413.31437-1-ysato@users.sourceforge.jp> <20190302062138.10713-1-ysato@users.sourceforge.jp> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 202.224.55.13 Subject: [Qemu-devel] [PATCH RFC v3 04/11] target/rx: RX disassembler X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, richard.henderson@linaro.org, Yoshinori Sato Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Signed-off-by: Yoshinori Sato --- include/disas/bfd.h | 5 + target/rx/disas.c | 1570 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1575 insertions(+) create mode 100644 target/rx/disas.c diff --git a/include/disas/bfd.h b/include/disas/bfd.h index 41b61c85f9..b2c34274dd 100644 --- a/include/disas/bfd.h +++ b/include/disas/bfd.h @@ -228,6 +228,10 @@ enum bfd_architecture #define bfd_mach_nios2r2 2 bfd_arch_lm32, /* Lattice Mico32 */ #define bfd_mach_lm32 1 + bfd_arch_rx, /* Renesas RX */ +#define bfd_mach_rx 0x75 +#define bfd_mach_rx_v2 0x76 +#define bfd_mach_rx_v3 0x77 bfd_arch_last }; #define bfd_mach_s390_31 31 @@ -432,6 +436,7 @@ int print_insn_little_nios2 (bfd_vma, disassemble_info*); int print_insn_xtensa (bfd_vma, disassemble_info*); int print_insn_riscv32 (bfd_vma, disassemble_info*); int print_insn_riscv64 (bfd_vma, disassemble_info*); +int print_insn_rx(bfd_vma, disassemble_info *); #if 0 /* Fetch the disassembler for a given BFD, if that support is available. */ diff --git a/target/rx/disas.c b/target/rx/disas.c new file mode 100644 index 0000000000..737fd425b6 --- /dev/null +++ b/target/rx/disas.c @@ -0,0 +1,1570 @@ +/* + * Renesas RX Disassembler + * + * Copyright (c) 2019 Yoshinori Sato + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "disas/bfd.h" +#include "qemu/bitops.h" +#include "cpu.h" + +typedef struct DisasContext { + disassemble_info *dis; + uint32_t addr; +} DisasContext; + + +static uint32_t decode_load_bytes(DisasContext *ctx, uint32_t insn, + int i, int n) +{ + bfd_byte buf; + while (++i <= n) { + ctx->dis->read_memory_func(ctx->addr++, &buf, 1, ctx->dis); + insn |= buf << (32 - i * 8); + } + return insn; +} + +static int32_t li(DisasContext *ctx, int sz) +{ + int32_t addr; + bfd_byte buf[4]; + addr = ctx->addr; + + switch (sz) { + case 1: + ctx->addr += 1; + ctx->dis->read_memory_func(addr, buf, 1, ctx->dis); + return buf[0]; + case 2: + ctx->addr += 2; + ctx->dis->read_memory_func(addr, buf, 2, ctx->dis); + return buf[1] << 8 | buf[0]; + case 3: + ctx->addr += 3; + ctx->dis->read_memory_func(addr, buf, 3, ctx->dis); + return buf[2] << 16 | buf[1] << 8 | buf[0]; + case 0: + ctx->addr += 4; + ctx->dis->read_memory_func(addr, buf, 4, ctx->dis); + return buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]; + default: + g_assert_not_reached(); + } +} + +/* Include the auto-generated decoder. */ +#include "decode.inc.c" + +#define prt(...) (ctx->dis->fprintf_func)((ctx->dis->stream), __VA_ARGS__) + +#define RX_MEMORY_BYTE 0 +#define RX_MEMORY_WORD 1 +#define RX_MEMORY_LONG 2 + +#define RX_MI_BYTE 0 +#define RX_MI_WORD 1 +#define RX_MI_LONG 2 +#define RX_MI_UWORD 3 + +static const char size[] = {'b', 'w', 'l'}; +static const char *cond[] = { + "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n", + "ge", "lt", "gt", "le", "o", "no", "ra", "f" +}; +static const char *cr[] = { + "psw", "", "usp", "fpsw", "", "", "", "", + "bpsw", "bpc", "isp", "fintv", "intb", "", "", "", +}; +static const char *msize[] = { + "b", "w", "l", "ub", "uw", +}; + +static const char psw[] = { + 'c', 'z', 's', 'o', 0, 0, 0, 0, + 'i', 'u', 0, 0, 0, 0, 0, 0, +}; + +static uint32_t rx_index_addr(int ld, int size, DisasContext *ctx) +{ + bfd_byte buf[2]; + switch (ld) { + case 0: + return 0; + case 1: + ctx->dis->read_memory_func(ctx->addr, buf, 1, ctx->dis); + ctx->addr += 1; + return buf[0]; + case 2: + ctx->dis->read_memory_func(ctx->addr, buf, 2, ctx->dis); + ctx->addr += 2; + return buf[1] << 8 | buf[0]; + } + g_assert_not_reached(); +} + +static void operand(DisasContext *ctx, int ld, int mi, int rs, int rd) +{ + int dsp; + const char *mis; + static const char *sizes[] = {".b", ".w", ".l"}; + if (ld < 3) { + switch (mi) { + case 4: + /* dsp[rs].ub */ + dsp = rx_index_addr(ld, RX_MEMORY_BYTE, ctx); + mis = ".ub"; + break; + case 3: + /* dsp[rs].uw */ + dsp = rx_index_addr(ld, RX_MEMORY_BYTE, ctx); + mis = ".uw"; + break; + default: + dsp = rx_index_addr(ld, mi, ctx); + mis = sizes[mi]; + break; + } + if (dsp > 0) { + dsp <<= ld; + prt("%d", dsp); + } + prt("[r%d]%s", rs, mis); + } else { + prt("r%d", rs); + } + prt(",r%d", rd); +} + +/* mov.[bwl] rs,dsp:[rd] */ +static bool trans_MOV_mr(DisasContext *ctx, arg_MOV_mr *a) +{ + if (a->dsp > 0) { + prt("mov.%c\tr%d,%d[r%d]", + size[a->sz], a->rs, a->dsp << a->sz, a->rd); + } else { + prt("mov.%c\tr%d,[r%d]", + size[a->sz], a->rs, a->rd); + } + return true; +} + +/* mov.[bwl] dsp:[rd],rs */ +static bool trans_MOV_rm(DisasContext *ctx, arg_MOV_rm *a) +{ + if (a->dsp > 0) { + prt("mov.%c\t%d[r%d],r%d", + size[a->sz], a->dsp << a->sz, a->rd, a->rs); + } else { + prt("mov.%c\t[r%d],r%d", + size[a->sz], a->rd, a->rs); + } + return true; +} + +/* mov.l #uimm4,rd */ +/* mov.l #uimm8,rd */ +static bool trans_MOV_ri(DisasContext *ctx, arg_MOV_ri *a) +{ + prt("mov.l\t#%d,r%d", a->imm & 0xff, a->rd); + return true; +} + +/* mov.[bwl] #uimm8,dsp:[rd] */ +static bool trans_MOV_mi(DisasContext *ctx, arg_MOV_mi *a) +{ + if (a->dsp > 0) { + prt("mov.%c\t#%d,%d[r%d]", + size[a->sz], a->imm & 0xff, a->dsp << a->sz, a->rd); + } else { + prt("mov.%c\t#%d,[r%d]", + size[a->sz], a->imm & 0xff, a->rd); + } + return true; +} + +/* mov.l #imm,rd */ +static bool trans_MOV_rli(DisasContext *ctx, arg_MOV_rli *a) +{ + prt("mov.l\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + + +/* mov #imm, dsp:[rd] */ +static bool trans_MOV_mli(DisasContext *ctx, arg_MOV_mli *a) +{ + if (a->ld == 2) { + a->dsp = bswap_16(a->dsp); + } + if (a->dsp > 0) { + prt("mov.%c\t#0x%08x,%d[r%d]", + size[a->sz], a->imm, a->dsp << a->sz, a->rd); + } else { + prt("mov.%c\t#0x%08x,[r%d]", + size[a->sz], a->imm, a->rd); + } + return true; +} + + +/* mov.[bwl] [ri,rb],rd */ +static bool trans_MOV_ra(DisasContext *ctx, arg_MOV_ra *a) +{ + prt("mov.%c\t[r%d,r%d],r%d", size[a->sz], a->ri, a->rb, a->rd); + return true; +} + +/* mov.[bwl] rd,[ri,rb] */ +static bool trans_MOV_ar(DisasContext *ctx, arg_MOV_ar *a) +{ + prt("mov.%c\tr%d,[r%d,r%d]", size[a->sz], a->rs, a->ri, a->rb); + return true; +} + + +/* mov.[bwl] dsp:[rs],dsp:[rd] */ +/* mov.[bwl] rs,dsp:[rd] */ +/* mov.[bwl] dsp:[rs],rd */ +/* mov.[bwl] rs,rd */ +static bool trans_MOV_ll(DisasContext *ctx, arg_MOV_ll *a) +{ + int rs, rd, dsp; + + if (a->lds == 3 && a->ldd < 3) { + rs = a->rd; + rd = a->rs; + } else { + rs = a->rs; + rd = a->rd; + } + prt("mov.%c\t", size[a->sz]); + if (a->lds < 3) { + dsp = rx_index_addr(a->lds, a->sz, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d],", rs); + } else { + prt("r%d,", rs); + } + if (a->ldd < 3) { + dsp = rx_index_addr(a->ldd, a->sz, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d]", rd); + } else { + prt("r%d", rd); + } + return true; +} + +/* mov.[bwl] rs,[rd+] */ +/* mov.[bwl] rs,[-rd] */ +static bool trans_MOV_pr(DisasContext *ctx, arg_MOV_pr *a) +{ + prt("mov.%c\tr%d,", size[a->sz], a->rs); + if (a->ad == 0) { + prt("[r%d+]", a->rd); + } else { + prt("[-r%d]", a->rd); + } + return true; +} + +/* mov.[bwl] [rd+],rs */ +/* mov.[bwl] [-rd],rs */ +static bool trans_MOV_rp(DisasContext *ctx, arg_MOV_rp *a) +{ + prt("mov.%c\t", size[a->sz]); + if (a->ad == 1) { + prt("[-r%d]", a->rd); + } else { + prt("[r%d+]", a->rd); + } + prt(",r%d", a->rs); + return true; +} + +/* movu.[bw] dsp5:[rs],rd */ +static bool trans_MOVU_rm(DisasContext *ctx, arg_MOVU_rm *a) +{ + if (a->dsp > 0) { + prt("movu.%c%d[r%d],r%d", size[a->sz], a->dsp << a->sz, a->rs, a->rd); + } else { + prt("movu.%c[r%d],r%d", size[a->sz], a->rs, a->rd); + } + return true; +} + +/* movu.[bw] rs,rd */ +/* movu.[bw] dsp:[rs],rd */ +static bool trans_MOVU_rl(DisasContext *ctx, arg_MOVU_rl *a) +{ + int dsp; + prt("movu.%c\t", size[a->sz]); + if (a->ld < 3) { + /* from memory */ + dsp = rx_index_addr(a->ld, a->sz, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d]", a->rs); + } else { + prt("r%d", a->rs); + } + prt(",r%d", a->rd); + return true; +} + +/* movu.[bw] [ri,rb],rd */ +static bool trans_MOVU_ra(DisasContext *ctx, arg_MOVU_ra *a) +{ + prt("mov.%c\t[r%d,r%d],r%d", size[a->sz], a->ri, a->rb, a->rd); + return true; +} + +/* movu.[bw] [rs+],rd */ +/* movu.[bw] [-rs],rd */ +static bool trans_MOVU_rp(DisasContext *ctx, arg_MOVU_rp *a) +{ + prt("movu.%c\t", size[a->sz]); + if (a->ad == 1) { + prt("[-r%d]", a->rd); + } else { + prt("[r%d+]", a->rd); + } + prt(",r%d", a->rs); + return true; +} + +/* pop rd */ +static bool trans_POP(DisasContext *ctx, arg_POP *a) +{ + prt("pop\tr%d", a->rd); + return true; +} + +/* popc rx */ +static bool trans_POPC(DisasContext *ctx, arg_POPC *a) +{ + prt("pop\tr%s", cr[a->cr]); + return true; +} + +/* popm rd-rd2 */ +static bool trans_POPM(DisasContext *ctx, arg_POPM *a) +{ + prt("popm\tr%d-r%d", a->rd, a->rd2); + return true; +} + +/* push rs */ +static bool trans_PUSH_r(DisasContext *ctx, arg_PUSH_r *a) +{ + prt("push\tr%d", a->rs); + return true; +} + +/* push dsp[rs] */ +static bool trans_PUSH_m(DisasContext *ctx, arg_PUSH_m *a) +{ + prt("push\t"); + int dsp = rx_index_addr(a->ld, a->sz, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d]", a->rs); + return true; +} + +/* pushc rx */ +static bool trans_PUSHC(DisasContext *ctx, arg_PUSHC *a) +{ + prt("push\t%s", cr[a->cr]); + return true; +} + +/* pushm rs-rs2*/ +static bool trans_PUSHM(DisasContext *ctx, arg_PUSHM *a) +{ + prt("pushm\tr%d-r%d", a->rs, a->rs2); + return true; +} + +/* xchg rs,rd */ +/* xchg dsp[rs].,rd */ +static bool trans_XCHG_rl(DisasContext *ctx, arg_XCHG_rl *a) +{ + int dsp; + + prt("xchg\t"); + if (a->ld == 3) { + /* xchg rs,rd */ + prt("r%d", a->rs); + } else { + dsp = rx_index_addr(a->ld, a->mi, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d].%s", a->rs, msize[a->mi]); + } + prt(",r%d", a->rd); + return true; +} + +/* stz #imm,rd */ +static bool trans_STZ(DisasContext *ctx, arg_STZ *a) +{ + prt("stz\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + +/* stnz #imm,rd */ +static bool trans_STNZ(DisasContext *ctx, arg_STNZ *a) +{ + prt("stnz\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + +/* rtsd #imm */ +static bool trans_RTSD_i(DisasContext *ctx, arg_RTSD_i *a) +{ + prt("rtsd\t#%d", (a->imm & 0xff) << 2); + return true; +} + +/* rtsd #imm, rd-rd2 */ +static bool trans_RTSD_irr(DisasContext *ctx, arg_RTSD_irr *a) +{ + prt("rtsd\t#%d,r%d-r%d", (a->imm & 0xff) << 2, a->rd, a->rd2); + return true; +} + +/* and #uimm:4, rd */ +static bool trans_AND_ri(DisasContext *ctx, arg_AND_ri *a) +{ + prt("and\t#%d,r%d", a->imm, a->rd); + return true; +} + +/* and #imm, rd */ +static bool trans_AND_rli(DisasContext *ctx, arg_AND_rli *a) +{ + prt("and\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + +/* and dsp[rs], rd */ +/* and rs,rd */ +static bool trans_AND_rl(DisasContext *ctx, arg_AND_rl *a) +{ + prt("and\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* and rs,rs2,rd */ +static bool trans_AND_rrr(DisasContext *ctx, arg_AND_rrr *a) +{ + prt("and\tr%d,r%d,r%d", a->rs, a->rs2, a->rd); + return true; +} + +/* or #uimm:4, rd */ +static bool trans_OR_ri(DisasContext *ctx, arg_OR_ri *a) +{ + prt("or\t#%d,r%d", a->imm, a->rd); + return true; +} + +/* or #imm, rd */ +static bool trans_OR_rli(DisasContext *ctx, arg_OR_rli *a) +{ + prt("or\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + +/* or dsp[rs], rd */ +/* or rs,rd */ +static bool trans_OR_rl(DisasContext *ctx, arg_OR_rl *a) +{ + prt("or\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* or rs,rs2,rd */ +static bool trans_OR_rrr(DisasContext *ctx, arg_OR_rrr *a) +{ + prt("or\tr%d,r%d,r%d", a->rs, a->rs2, a->rd); + return true; +} + +/* xor #imm, rd */ +static bool trans_XOR_rli(DisasContext *ctx, arg_XOR_rli *a) +{ + prt("xor\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + +/* xor dsp[rs], rd */ +/* xor rs,rd */ +static bool trans_XOR_rl(DisasContext *ctx, arg_XOR_rl *a) +{ + prt("xor\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* tst #imm, rd */ +static bool trans_TST_rli(DisasContext *ctx, arg_TST_rli *a) +{ + prt("tst\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + +/* tst dsp[rs], rd */ +/* tst rs, rd */ +static bool trans_TST_rl(DisasContext *ctx, arg_TST_rl *a) +{ + prt("tst\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* not rd */ +/* not rs, rd */ +static bool trans_NOT_rr(DisasContext *ctx, arg_NOT_rr *a) +{ + prt("not\t"); + if (a->rs < 16) { + prt("r%d", a->rs); + } + prt("r%d", a->rd); + return true; +} + +/* neg rd */ +/* neg rs, rd */ +static bool trans_NEG_rr(DisasContext *ctx, arg_NEG_rr *a) +{ + prt("neg\t"); + if (a->rs < 16) { + prt("r%d", a->rs); + } + prt("r%d", a->rd); + return true; +} + +/* adc #imm, rd */ +static bool trans_ADC_rli(DisasContext *ctx, arg_ADC_rli *a) +{ + prt("adc\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + +/* adc rs, rd */ +static bool trans_ADC_rr(DisasContext *ctx, arg_ADC_rr *a) +{ + prt("adc\tr%d,r%d", a->rs, a->rd); + return true; +} + +/* adc dsp[rs], rd */ +static bool trans_ADC_rl(DisasContext *ctx, arg_ADC_rl *a) +{ + int dsp; + prt("adc\t"); + dsp = rx_index_addr(a->ld, RX_LONG, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d],r%d", a->rs, a->rd); + return true; +} + +/* add #uimm4, rd */ +static bool trans_ADD_rri(DisasContext *ctx, arg_ADD_rri *a) +{ + prt("add\t#%d,r%d", a->imm, a->rd); + return true; +} + +/* add rs, rd */ +/* add dsp[rs], rd */ +static bool trans_ADD_rl(DisasContext *ctx, arg_ADD_rl *a) +{ + prt("add\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* add #imm, rs, rd */ +static bool trans_ADD_rrli(DisasContext *ctx, arg_ADD_rrli *a) +{ + prt("add\t#0x%08x,r%d,r%d", a->imm, a->rs2, a->rd); + return true; +} + +/* add rs, rs2, rd */ +static bool trans_ADD_rrr(DisasContext *ctx, arg_ADD_rrr *a) +{ + prt("add\tr%d,r%d,r%d", a->rs, a->rs2, a->rd); + return true; +} + +/* cmp #imm4, rd */ +/* cmp #imm8, rd */ +static bool trans_CMP_ri(DisasContext *ctx, arg_CMP_ri *a) +{ + int rs; + rs = (a->rs2 < 16) ? a->rs2 : a->rd; + prt("cmp\t#%d,r%d", a->imm & 0xff, rs); + return true; +} + +/* cmp #imm, rs2 */ +static bool trans_CMP_rli(DisasContext *ctx, arg_CMP_rli *a) +{ + prt("cmp\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + +/* cmp rs, rs2 */ +/* cmp dsp[rs], rs2 */ +static bool trans_CMP_rl(DisasContext *ctx, arg_CMP_rl *a) +{ + prt("cmp\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* sub #imm4, rd */ +static bool trans_SUB_ri(DisasContext *ctx, arg_SUB_ri *a) +{ + prt("sub\t#%d,r%d", a->imm, a->rd); + return true; +} + +/* sub rs, rd */ +/* sub dsp[rs], rd */ +static bool trans_SUB_rl(DisasContext *ctx, arg_SUB_rl *a) +{ + prt("sub\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* sub rs, rs2, rd */ +static bool trans_SUB_rrr(DisasContext *ctx, arg_SUB_rrr *a) +{ + prt("sub\tr%d,r%d,r%d", a->rs, a->rs2, a->rd); + return true; +} + +/* sbb rs, rd */ +static bool trans_SBB_rr(DisasContext *ctx, arg_SBB_rr *a) +{ + prt("sbb\tr%d,%d", a->rs, a->rd); + return true; +} + +/* sbb dsp[rs], rd */ +static bool trans_SBB_rl(DisasContext *ctx, arg_SBB_rl *a) +{ + prt("sbb\t"); + operand(ctx, a->ld, RX_MI_LONG, a->rs, a->rd); + return true; +} + +/* abs rd */ +/* abs rs, rd */ +static bool trans_ABS_rr(DisasContext *ctx, arg_ABS_rr *a) +{ + prt("abs\t"); + if (a->rs < 16) { + prt("r%d,r%d", a->rs, a->rd); + } else { + prt("r%d", a->rd); + } + return true; +} + +/* max #imm, rd */ +static bool trans_MAX_ri(DisasContext *ctx, arg_MAX_ri *a) +{ + prt("max\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + +/* max rs, rd */ +/* max dsp[rs], rd */ +static bool trans_MAX_rl(DisasContext *ctx, arg_MAX_rl *a) +{ + prt("max\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* min #imm, rd */ +static bool trans_MIN_ri(DisasContext *ctx, arg_MIN_ri *a) +{ + prt("min\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + +/* min rs, rd */ +/* min dsp[rs], rd */ +static bool trans_MIN_rl(DisasContext *ctx, arg_MIN_rl *a) +{ + prt("max\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* mul #uimm4, rd */ +static bool trans_MUL_ri(DisasContext *ctx, arg_MUL_ri *a) +{ + prt("mul\t#%d,r%d", a->imm, a->rd); + return true; +} + +/* mul #imm, rd */ +static bool trans_MUL_rli(DisasContext *ctx, arg_MUL_rli *a) +{ + prt("mul\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + +/* mul rs, rd */ +/* mul dsp[rs], rd */ +static bool trans_MUL_rl(DisasContext *ctx, arg_MUL_rl *a) +{ + prt("mul\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* mul rs, rs2, rd */ +static bool trans_MUL_rrr(DisasContext *ctx, arg_MUL_rrr *a) +{ + prt("mul\tr%d,r%d,r%d", a->rs, a->rs2, a->rd); + return true; +} + +/* emul #imm, rd */ +static bool trans_EMUL_ri(DisasContext *ctx, arg_EMUL_ri *a) +{ + prt("emul\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + +/* emul rs, rd */ +/* emul dsp[rs], rd */ +static bool trans_EMUL_rl(DisasContext *ctx, arg_EMUL_rl *a) +{ + prt("emul\n"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* emulu #imm, rd */ +static bool trans_EMULU_ri(DisasContext *ctx, arg_EMULU_ri *a) +{ + prt("emulu\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + +/* emulu rs, rd */ +/* emulu dsp[rs], rd */ +static bool trans_EMULU_rl(DisasContext *ctx, arg_EMULU_rl *a) +{ + prt("emulu\n"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* div #imm, rd */ +static bool trans_DIV_ri(DisasContext *ctx, arg_DIV_ri *a) +{ + prt("div\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + +/* div rs, rd */ +/* div dsp[rs], rd */ +static bool trans_DIV_rl(DisasContext *ctx, arg_DIV_rl *a) +{ + prt("div\n"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* divu #imm, rd */ +static bool trans_DIVU_ri(DisasContext *ctx, arg_DIVU_ri *a) +{ + prt("divu\t#0x%08x,r%d", a->imm, a->rd); + return true; +} + +/* divu rs, rd */ +/* divu dsp[rs], rd */ +static bool trans_DIVU_rl(DisasContext *ctx, arg_DIVU_rl *a) +{ + prt("divu\n"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + + +/* shll #imm:5, rd */ +/* shll #imm:5, rs, rd */ +static bool trans_SHLL_rri(DisasContext *ctx, arg_SHLL_rri *a) +{ + prt("shll\t#%d,", a->imm); + if (a->rs2 < 16) { + prt("r%d,", a->rs2); + } + prt("r%d", a->rd); + return true; +} + +/* shll rs, rd */ +static bool trans_SHLL_rr(DisasContext *ctx, arg_SHLL_rr *a) +{ + prt("shll\tr%d,r%d", a->rs, a->rd); + return true; +} + +/* shar #imm:5, rd */ +/* shar #imm:5, rs, rd */ +static bool trans_SHAR_rri(DisasContext *ctx, arg_SHAR_rri *a) +{ + prt("shar\t#%d,", a->imm); + if (a->rs2 < 16) { + prt("r%d,", a->rs2); + } + prt("r%d", a->rd); + return true; +} + +/* shar rs, rd */ +static bool trans_SHAR_rr(DisasContext *ctx, arg_SHAR_rr *a) +{ + prt("shar\tr%d,r%d", a->rs, a->rd); + return true; +} + +/* shlr #imm:5, rd */ +/* shlr #imm:5, rs, rd */ +static bool trans_SHLR_rri(DisasContext *ctx, arg_SHLR_rri *a) +{ + prt("shlr\t#%d,", a->imm); + if (a->rs2 < 16) { + prt("r%d,", a->rs2); + } + prt("r%d", a->rd); + return true; +} + +/* shlr rs, rd */ +static bool trans_SHLR_rr(DisasContext *ctx, arg_SHLR_rr *a) +{ + prt("shlr\tr%d,r%d", a->rs, a->rd); + return true; +} + +/* rolc rd */ +static bool trans_ROLC(DisasContext *ctx, arg_ROLC *a) +{ + prt("rorc\tr%d", a->rd); + return true; +} + +/* rorc rd */ +static bool trans_RORC(DisasContext *ctx, arg_RORC *a) +{ + prt("rorc\tr%d", a->rd); + return true; +} + +/* rotl #imm, rd */ +static bool trans_ROTL_ri(DisasContext *ctx, arg_ROTL_ri *a) +{ + prt("rotl\t#%d,r%d", a->imm, a->rd); + return true; +} + +/* rotl rs, rd */ +static bool trans_ROTL_rr(DisasContext *ctx, arg_ROTL_rr *a) +{ + prt("rotl\tr%d,r%d", a->rs, a->rd); + return true; +} + +/* rotr #imm, rd */ +static bool trans_ROTR_ri(DisasContext *ctx, arg_ROTR_ri *a) +{ + prt("rotr\t#%d,r%d", a->imm, a->rd); + return true; +} + +/* rotr rs, rd */ +static bool trans_ROTR_rr(DisasContext *ctx, arg_ROTR_rr *a) +{ + prt("rotr\tr%d,r%d", a->rs, a->rd); + return true; +} + +/* revl rs, rd */ +static bool trans_REVL(DisasContext *ctx, arg_REVL *a) +{ + prt("revl\tr%d,r%d", a->rs, a->rd); + return true; +} + +/* revw rs, rd */ +static bool trans_REVW(DisasContext *ctx, arg_REVW *a) +{ + prt("revw\tr%d,r%d", a->rs, a->rd); + return true; +} + +/* conditional branch helper */ +static void rx_bcnd_main(DisasContext *ctx, int cd, int dst, int len) +{ + static const char sz[] = {'s', 'b', 'w', 'a'}; + prt("b%s.%c\t%08x", cond[cd], sz[len - 1], ctx->addr - len + dst); +} + +static int16_t rev16(uint16_t dsp) +{ + return ((dsp << 8) & 0xff00) | ((dsp >> 8) & 0x00ff); +} + +static int32_t rev24(uint32_t dsp) +{ + dsp = ((dsp << 16) & 0xff0000) | + (dsp & 0x00ff00) | + ((dsp >> 16) & 0x0000ff); + dsp |= (dsp & 0x00800000) ? 0xff000000 : 0x00000000; + return dsp; +} + +/* beq dsp:3 */ +/* bne dsp:3 */ +static bool trans_BCnd_s(DisasContext *ctx, arg_BCnd_s *a) +{ + if (a->dsp < 3) { + a->dsp += 8; + } + rx_bcnd_main(ctx, a->cd, a->dsp, 1); + return true; +} + +/* beq dsp:8 */ +/* bne dsp:8 */ +/* bc dsp:8 */ +/* bnc dsp:8 */ +/* bgtu dsp:8 */ +/* bleu dsp:8 */ +/* bpz dsp:8 */ +/* bn dsp:8 */ +/* bge dsp:8 */ +/* blt dsp:8 */ +/* bgt dsp:8 */ +/* ble dsp:8 */ +/* bo dsp:8 */ +/* bno dsp:8 */ +/* bra dsp:8 */ +static bool trans_BCnd_b(DisasContext *ctx, arg_BCnd_b *a) +{ + rx_bcnd_main(ctx, a->cd, (int8_t)a->dsp, 2); + return true; +} + +/* beq dsp:16 */ +/* bne dsp:16 */ +static bool trans_BCnd_w(DisasContext *ctx, arg_BCnd_w *a) +{ + rx_bcnd_main(ctx, a->cd, rev16(a->dsp), 3); + return true; +} + +/* bra dsp:3 */ +static bool trans_BRA_s(DisasContext *ctx, arg_BRA_s *a) +{ + if (a->dsp < 3) { + a->dsp += 8; + } + rx_bcnd_main(ctx, 14, a->dsp, 1); + return true; +} + +/* bra dsp:16 */ +static bool trans_BRA_w(DisasContext *ctx, arg_BRA_w *a) +{ + rx_bcnd_main(ctx, 14, rev16(a->dsp), 3); + return true; +} + +/* bra dsp:24 */ +static bool trans_BRA_a(DisasContext *ctx, arg_BRA_a *a) +{ + rx_bcnd_main(ctx, 14, rev24(a->dsp), 4); + return true; +} + +/* bra rs */ +static bool trans_BRA_l(DisasContext *ctx, arg_BRA_l *a) +{ + prt("bra.l\tr%d", a->rd); + return true; +} + +/* jmp rs */ +static bool trans_JMP(DisasContext *ctx, arg_JMP *a) +{ + prt("jmp\tr%d", a->rs); + return true; +} + +/* jsr rs */ +static bool trans_JSR(DisasContext *ctx, arg_JSR *a) +{ + prt("jsr\tr%d", a->rs); + return true; +} + +/* bsr dsp:16 */ +static bool trans_BSR_w(DisasContext *ctx, arg_BSR_w *a) +{ + prt("bsr.w\t%08x", ctx->addr - 3 + rev16(a->dsp)); + return true; +} + +/* bsr dsp:24 */ +static bool trans_BSR_a(DisasContext *ctx, arg_BSR_a *a) +{ + prt("bsr.a\t%08x", ctx->addr - 4 + rev24(a->dsp)); + return true; +} + +/* bsr rs */ +static bool trans_BSR_l(DisasContext *ctx, arg_BSR_l *a) +{ + prt("bsr.l\tr%d", a->rd); + return true; +} + +/* rts */ +static bool trans_RTS(DisasContext *ctx, arg_RTS *a) +{ + prt("rts"); + return true; +} + +/* nop */ +static bool trans_NOP(DisasContext *ctx, arg_NOP *a) +{ + prt("nop"); + return true; +} + +/* scmpu */ +static bool trans_SCMPU(DisasContext *ctx, arg_SCMPU *a) +{ + prt("scmpu"); + return true; +} + +/* smovu */ +static bool trans_SMOVU(DisasContext *ctx, arg_SMOVU *a) +{ + prt("smovu"); + return true; +} + +/* smovf */ +static bool trans_SMOVF(DisasContext *ctx, arg_SMOVF *a) +{ + prt("smovf"); + return true; +} + +/* smovb */ +static bool trans_SMOVB(DisasContext *ctx, arg_SMOVB *a) +{ + prt("smovb"); + return true; +} + +/* suntile */ +static bool trans_SUNTIL(DisasContext *ctx, arg_SUNTIL *a) +{ + prt("suntil.%c", size[a->sz]); + return true; +} + +/* swhile */ +static bool trans_SWHILE(DisasContext *ctx, arg_SWHILE *a) +{ + prt("swhile.%c", size[a->sz]); + return true; +} +/* sstr */ +static bool trans_SSTR(DisasContext *ctx, arg_SSTR *a) +{ + prt("sstr.%c", size[a->sz]); + return true; +} + +/* rmpa */ +static bool trans_RMPA(DisasContext *ctx, arg_RMPA *a) +{ + prt("rmpa.%c", size[a->sz]); + return true; +} + +/* mulhi rs,rs2 */ +static bool trans_MULHI(DisasContext *ctx, arg_MULHI *a) +{ + prt("mulhi\tr%d,r%d", a->rs, a->rs2); + return true; +} + +/* mullo rs,rs2 */ +static bool trans_MULLO(DisasContext *ctx, arg_MULLO *a) +{ + prt("mullo\tr%d,r%d", a->rs, a->rs2); + return true; +} + +/* machi rs,rs2 */ +static bool trans_MACHI(DisasContext *ctx, arg_MACHI *a) +{ + prt("machi\tr%d,r%d", a->rs, a->rs2); + return true; +} + +/* maclo rs,rs2 */ +static bool trans_MACLO(DisasContext *ctx, arg_MACLO *a) +{ + prt("maclo\tr%d,r%d", a->rs, a->rs2); + return true; +} + +/* mvfachi rd */ +static bool trans_MVFACHI(DisasContext *ctx, arg_MVFACHI *a) +{ + prt("mvfachi\tr%d", a->rd); + return true; +} + +/* mvfacmi rd */ +static bool trans_MVFACMI(DisasContext *ctx, arg_MVFACMI *a) +{ + prt("mvfacmi\tr%d", a->rd); + return true; +} + +/* mvtachi rs */ +static bool trans_MVTACHI(DisasContext *ctx, arg_MVTACHI *a) +{ + prt("mvtachi\tr%d", a->rs); + return true; +} + +/* mvtaclo rs */ +static bool trans_MVTACLO(DisasContext *ctx, arg_MVTACLO *a) +{ + prt("mvtaclo\tr%d", a->rs); + return true; +} + +/* racw #imm */ +static bool trans_RACW(DisasContext *ctx, arg_RACW *a) +{ + prt("racw\t#%d", a->imm + 1); + return true; +} + +/* sat rd */ +static bool trans_SAT(DisasContext *ctx, arg_SAT *a) +{ + prt("sat\tr%d", a->rd); + return true; +} + +/* satr */ +static bool trans_SATR(DisasContext *ctx, arg_SATR *a) +{ + prt("satr"); + return true; +} + +/* fadd #imm, rd */ +static bool trans_FADD_ri(DisasContext *ctx, arg_FADD_ri *a) +{ + prt("fadd\t#%d,r%d", li(ctx, 0), a->rd); + return true; +} + +/* fadd dsp[rs], rd */ +/* fadd rs, rd */ +static bool trans_FADD_rl(DisasContext *ctx, arg_FADD_rl *a) +{ + prt("fadd\t"); + operand(ctx, a->ld, RX_MI_LONG, a->rs, a->rd); + return true; +} + +/* fcmp #imm, rd */ +static bool trans_FCMP_ri(DisasContext *ctx, arg_FCMP_ri *a) +{ + prt("fadd\t#%d,r%d", li(ctx, 0), a->rd); + return true; +} + +/* fcmp dsp[rs], rd */ +/* fcmp rs, rd */ +static bool trans_FCMP_rl(DisasContext *ctx, arg_FCMP_rl *a) +{ + prt("fcmp\t"); + operand(ctx, a->ld, RX_MI_LONG, a->rs, a->rd); + return true; +} + +/* fsub #imm, rd */ +static bool trans_FSUB_ri(DisasContext *ctx, arg_FSUB_ri *a) +{ + prt("fsub\t#%d,r%d", li(ctx, 0), a->rd); + return true; +} + +/* fsub dsp[rs], rd */ +/* fsub rs, rd */ +static bool trans_FSUB_rl(DisasContext *ctx, arg_FSUB_rl *a) +{ + prt("fsub\t"); + operand(ctx, a->ld, RX_MI_LONG, a->rs, a->rd); + return true; +} + +/* ftoi dsp[rs], rd */ +/* ftoi rs, rd */ +static bool trans_FTOI(DisasContext *ctx, arg_FTOI *a) +{ + prt("ftoi\t"); + operand(ctx, a->ld, RX_MI_LONG, a->rs, a->rd); + return true; +} + +/* fmul #imm, rd */ +static bool trans_FMUL_ri(DisasContext *ctx, arg_FMUL_ri *a) +{ + prt("fmul\t#%d,r%d", li(ctx, 0), a->rd); + return true; +} + +/* fmul dsp[rs], rd */ +/* fmul rs, rd */ +static bool trans_FMUL_rl(DisasContext *ctx, arg_FMUL_rl *a) +{ + prt("fmul\t"); + operand(ctx, a->ld, RX_MI_LONG, a->rs, a->rd); + return true; +} + +/* fdiv #imm, rd */ +static bool trans_FDIV_ri(DisasContext *ctx, arg_FDIV_ri *a) +{ + prt("fdiv\t#%d,r%d", li(ctx, 0), a->rd); + return true; +} + +/* fdiv dsp[rs], rd */ +/* fdiv rs, rd */ +static bool trans_FDIV_rl(DisasContext *ctx, arg_FDIV_rl *a) +{ + prt("fdiv\t"); + operand(ctx, a->ld, RX_MI_LONG, a->rs, a->rd); + return true; +} + +/* round dsp[rs], rd */ +/* round rs, rd */ +static bool trans_ROUND(DisasContext *ctx, arg_ROUND *a) +{ + prt("round\t"); + operand(ctx, a->ld, RX_MI_LONG, a->rs, a->rd); + return true; +} + +/* itof rs, rd */ +/* itof dsp[rs], rd */ +static bool trans_ITOF(DisasContext *ctx, arg_ITOF *a) +{ + prt("itof\t"); + operand(ctx, a->ld, RX_MI_LONG, a->rs, a->rd); + return true; +} + +#define BOP_IM(name, reg) \ + do { \ + int dsp; \ + prt("b%s\t#%d,", #name, a->imm); \ + dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx); \ + if (dsp > 0) { \ + prt("%d", dsp); \ + } \ + prt("[r%d]", reg); \ + return true; \ + } while (0) + +/* bset #imm, dsp[rd] */ +static bool trans_BSET_li(DisasContext *ctx, arg_BSET_li *a) +{ + BOP_IM(bset, a->rs); +} + +#define BOP_RM(name) \ + do { \ + int dsp; \ + prt("b%s\tr%d,", #name, a->rs2); \ + switch (a->ld) { \ + case 0 ... 2: \ + dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx); \ + if (dsp > 0) { \ + prt("%d", dsp); \ + } \ + prt("[r%d]", a->rs); \ + break; \ + case 3: \ + prt("r%d", a->rs); \ + break; \ + } \ + return true; \ + } while (0) + +/* bset rs, dsp[rd] */ +/* bset rs, rd */ +static bool trans_BSET_lr(DisasContext *ctx, arg_BSET_lr *a) +{ + BOP_RM(set); +} + +/* bset #imm, rd */ +static bool trans_BSET_ri(DisasContext *ctx, arg_BSET_ri *a) +{ + prt("bset\t#%d,r%d", a->imm, a->rd); + return true; +} + +/* bclr #imm, dsp[rd] */ +static bool trans_BCLR_li(DisasContext *ctx, arg_BCLR_li *a) +{ +BOP_IM(clr, a->rs); +} + +/* bclr rs, dsp[rd] */ +/* bclr rs, rd */ +static bool trans_BCLR_lr(DisasContext *ctx, arg_BCLR_lr *a) +{ + BOP_RM(clr); +} + +/* bclr #imm, rd */ +static bool trans_BCLR_ri(DisasContext *ctx, arg_BCLR_ri *a) +{ + prt("bclr\t#%d,r%d", a->imm, a->rd); + return true; +} + +/* btst #imm, dsp[rd] */ +static bool trans_BTST_li(DisasContext *ctx, arg_BTST_li *a) +{ + BOP_IM(tst, a->rs); +} + +/* btst rs, dsp[rd] */ +/* btst rs, rd */ +static bool trans_BTST_lr(DisasContext *ctx, arg_BTST_lr *a) +{ + BOP_RM(tst); +} + +/* btst #imm, rd */ +static bool trans_BTST_ri(DisasContext *ctx, arg_BTST_ri *a) +{ + prt("btst\t#%d,r%d", a->imm, a->rd); + return true; +} + +/* bnot rs, dsp[rd] */ +/* bnot rs, rd */ +static bool trans_BNOT_lr(DisasContext *ctx, arg_BNOT_lr *a) +{ + BOP_RM(not); +} + +/* bmcond #imm, dsp[rd] */ +/* bnot #imm, dsp[rd] */ +static bool trans_BMCnd_BNOT_mi(DisasContext *ctx, arg_BMCnd_BNOT_mi *a) +{ + if (a->cd == 15) { + BOP_IM(not, a->rd); + } else { + int dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx); + prt("bm%s\t#%d,", cond[a->cd], a->imm); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[%d]", a->rd); + } + return true; +} + +/* bmcond #imm, rd */ +/* bnot #imm, rd */ +static bool trans_BMCnd_BNOT_ri(DisasContext *ctx, arg_BMCnd_BNOT_ri *a) +{ + if (a->cd == 15) { + prt("bnot\t#%d,r%d", a->imm, a->rd); + } else { + prt("bm%s\t#%d,r%d", cond[a->cd], a->imm, a->rd); + } + return true; +} + +/* clrpsw psw */ +static bool trans_CLRPSW(DisasContext *ctx, arg_CLRPSW *a) +{ + prt("clrpsw\t%c", psw[a->cb]); + return true; +} + +/* setpsw psw */ +static bool trans_SETPSW(DisasContext *ctx, arg_SETPSW *a) +{ + prt("setpsw\t%c", psw[a->cb]); + return true; +} + +/* mvtipl #imm */ +static bool trans_MVTIPL(DisasContext *ctx, arg_MVTIPL *a) +{ + prt("movtipl\t#%d", a->imm); + return true; +} + +/* mvtc #imm, rd */ +static bool trans_MVTC_i(DisasContext *ctx, arg_MVTC_i *a) +{ + prt("mvtc/t#0x%08x,%s", a->imm, cr[a->cr]); + return true; +} + +/* mvtc rs, rd */ +static bool trans_MVTC_r(DisasContext *ctx, arg_MVTC_r *a) +{ + prt("mvtc/tr%d,%s", a->rs, cr[a->cr]); + return true; +} + +/* mvfc rs, rd */ +static bool trans_MVFC(DisasContext *ctx, arg_MVFC *a) +{ + prt("mvfc/t%s,r%d", cr[a->cr], a->rd); + return true; +} + +/* rtfi */ +static bool trans_RTFI(DisasContext *ctx, arg_RTFI *a) +{ + prt("rtfi"); + return true; +} + +/* rte */ +static bool trans_RTE(DisasContext *ctx, arg_RTE *a) +{ + prt("rte"); + return true; +} + +/* brk */ +static bool trans_BRK(DisasContext *ctx, arg_BRK *a) +{ + prt("brk"); + return true; +} + +/* int #imm */ +static bool trans_INT(DisasContext *ctx, arg_INT *a) +{ + prt("int\t#%d", a->imm); + return true; +} + +/* wait */ +static bool trans_WAIT(DisasContext *ctx, arg_WAIT *a) +{ + prt("wait"); + return true; +} + +/* sccnd.[bwl] rd */ +/* sccnd.[bwl] dsp:[rd] */ +static bool trans_SCCnd(DisasContext *ctx, arg_SCCnd *a) +{ + int dsp; + prt("sc%s.%c\t", cond[a->cd], size[a->sz]); + if (a->ld < 3) { + dsp = rx_index_addr(a->sz, a->ld, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d]", a->rd); + } else { + prt("r%d", a->rd); + } + return true; +} + +int print_insn_rx(bfd_vma addr, disassemble_info *dis) +{ + DisasContext ctx; + uint32_t insn; + int i; + ctx.dis = dis; + ctx.addr = addr; + + insn = decode_load(&ctx); + if (!decode(&ctx, insn)) { + ctx.dis->fprintf_func(ctx.dis->stream, ".byte\t"); + for (i = 0; i < ctx.addr - addr; i++) { + if (i > 0) { + ctx.dis->fprintf_func(ctx.dis->stream, ","); + } + ctx.dis->fprintf_func(ctx.dis->stream, "0x%02x", insn >> 24); + insn <<= 8; + } + } + return ctx.addr - addr; +}