Message ID | 20190508145611.107133-5-ysato@users.sourceforge.jp (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Add RX archtecture support | expand |
On 5/8/19 4:56 PM, Yoshinori Sato wrote: > Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com> > --- > include/disas/dis-asm.h | 5 + > target/rx/disas.c | 1480 +++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 1485 insertions(+) > create mode 100644 target/rx/disas.c > > diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h > index 9240ec32c2..de17792e88 100644 > --- a/include/disas/dis-asm.h > +++ b/include/disas/dis-asm.h > @@ -226,6 +226,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 > @@ -433,6 +437,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..3dce2dd864 > --- /dev/null > +++ b/target/rx/disas.c > @@ -0,0 +1,1480 @@ > +/* > + * Renesas RX Disassembler > + * > + * Copyright (c) 2019 Yoshinori Sato <ysato@users.sourceforge.jp> > + * > + * 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 <http://www.gnu.org/licenses/>. > + */ > + > +#include "qemu/osdep.h" > +#include "disas/dis-asm.h" > +#include "qemu/bitops.h" > +#include "cpu.h" > + > +typedef struct DisasContext { > + disassemble_info *dis; > + uint32_t addr; > + uint32_t pc; > +} 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 (int8_t)buf[0]; > + case 2: > + ctx->addr += 2; > + ctx->dis->read_memory_func(addr, buf, 2, ctx->dis); > + return ldsw_le_p(buf); > + case 3: > + ctx->addr += 3; > + ctx->dis->read_memory_func(addr, buf, 3, ctx->dis); > + return (int8_t)buf[2] << 16 | lduw_le_p(buf); > + case 0: > + ctx->addr += 4; > + ctx->dis->read_memory_func(addr, buf, 4, ctx->dis); > + return ldl_le_p(buf); > + default: > + g_assert_not_reached(); > + } > +} > + > +static int bdsp_s(DisasContext *ctx, int d) > +{ > + /* > + * 0 -> 8 > + * 1 -> 9 > + * 2 -> 10 > + * 3 -> 3 > + * : > + * 7 -> 7 > + */ > + if (d < 3) { > + d += 8; > + } > + return d; > +} > + > +/* 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_IM_BYTE 0 > +#define RX_IM_WORD 1 > +#define RX_IM_LONG 2 > +#define RX_IM_UWORD 3 > + > +static const char size[] = {'b', 'w', 'l'}; > +static const char cond[][4] = { > + "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n", > + "ge", "lt", "gt", "le", "o", "no", "ra", "f" > +}; > +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 ((uint8_t)buf[0]) << size; > + case 2: > + ctx->dis->read_memory_func(ctx->addr, buf, 2, ctx->dis); > + ctx->addr += 2; > + return lduw_le_p(buf) << size; > + } > + g_assert_not_reached(); > +} > + > +static void operand(DisasContext *ctx, int ld, int mi, int rs, int rd) > +{ > + int dsp; > + static const char sizes[][4] = {".b", ".w", ".l", ".uw", ".ub"}; > + if (ld < 3) { > + switch (mi) { > + case 4: > + /* dsp[rs].ub */ > + dsp = rx_index_addr(ld, RX_MEMORY_BYTE, ctx); > + break; > + case 3: > + /* dsp[rs].uw */ > + dsp = rx_index_addr(ld, RX_MEMORY_WORD, ctx); > + break; > + default: > + /* dsp[rs].b */ > + /* dsp[rs].w */ > + /* dsp[rs].l */ > + dsp = rx_index_addr(ld, mi, ctx); > + break; > + } > + if (dsp > 0) { > + prt("%d", dsp); > + } > + prt("[r%d]%s", rs, sizes[mi]); > + } else { > + prt("r%d", rs); > + } > + prt(", r%d", rd); > +} > + > +static void prt_ir(DisasContext *ctx, const char *insn, int imm, int rd) > +{ > + if (imm < 0x100) { > + prt("%s\t#%d, r%d", insn, imm, rd); > + } else { > + prt("%s\t#0x%08x, r%d", insn, imm, rd); > + } > +} > + > +/* mov.[bwl] rs,dsp:[rd] */ > +static bool trans_MOV_rm(DisasContext *ctx, arg_MOV_rm *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_mr(DisasContext *ctx, arg_MOV_mr *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 */ > +/* mov.l #imm,rd */ > +static bool trans_MOV_ir(DisasContext *ctx, arg_MOV_ir *a) > +{ > + prt_ir(ctx, "mov.l", a->imm, a->rd); > + return true; > +} > + > +/* mov.[bwl] #uimm8,dsp:[rd] */ > +/* mov #imm, dsp:[rd] */ > +static bool trans_MOV_im(DisasContext *ctx, arg_MOV_im *a) > +{ > + if (a->dsp > 0) { > + prt("mov.%c\t#%d,%d[r%d]", > + size[a->sz], a->imm, a->dsp << a->sz, a->rd); > + } else { > + prt("mov.%c\t#%d,[r%d]", > + size[a->sz], a->imm, a->rd); > + } > + return true; > +} > + > +/* mov.[bwl] [ri,rb],rd */ > +static bool trans_MOV_ar(DisasContext *ctx, arg_MOV_ar *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_ra(DisasContext *ctx, arg_MOV_ra *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_mm(DisasContext *ctx, arg_MOV_mm *a) > +{ > + int dsp; > + > + prt("mov.%c\t", size[a->sz]); > + if (a->lds == 3 && a->ldd == 3) { > + /* mov.[bwl] rs,rd */ > + prt("r%d, r%d", a->rs, a->rd); > + return true; > + } > + if (a->lds == 3) { > + prt("r%d, ", a->rd); > + dsp = rx_index_addr(a->ldd, a->sz, ctx); > + if (dsp > 0) { > + prt("%d", dsp); > + } > + prt("[r%d]", a->rs); > + } else if (a->ldd == 3) { > + dsp = rx_index_addr(a->lds, a->sz, ctx); > + if (dsp > 0) { > + prt("%d", dsp); > + } > + prt("[r%d], r%d", a->rs, a->rd); > + } else { > + dsp = rx_index_addr(a->lds, a->sz, ctx); > + if (dsp > 0) { > + prt("%d", dsp); > + } > + prt("[r%d], ", a->rs); > + dsp = rx_index_addr(a->ldd, a->sz, ctx); > + if (dsp > 0) { > + prt("%d", dsp); > + } > + prt("[r%d]", a->rd); > + } > + return true; > +} > + > +/* mov.[bwl] rs,[rd+] */ > +/* mov.[bwl] rs,[-rd] */ > +static bool trans_MOV_rp(DisasContext *ctx, arg_MOV_rp *a) > +{ > + prt("mov.%c\tr%d, ", size[a->sz], a->rs); > + prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd); > + return true; > +} > + > +/* mov.[bwl] [rd+],rs */ > +/* mov.[bwl] [-rd],rs */ > +static bool trans_MOV_pr(DisasContext *ctx, arg_MOV_pr *a) > +{ > + prt("mov.%c\t", size[a->sz]); > + prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd); > + prt(", r%d", a->rs); > + return true; > +} > + > +/* movu.[bw] dsp5:[rs],rd */ > +static bool trans_MOVU_mr(DisasContext *ctx, arg_MOVU_mr *a) > +{ > + if (a->dsp > 0) { > + prt("movu.%c\t%d[r%d], r%d", size[a->sz], > + a->dsp << a->sz, a->rs, a->rd); > + } else { > + prt("movu.%c\t[r%d], r%d", size[a->sz], a->rs, a->rd); > + } > + return true; > +} > + > +/* movu.[bw] rs,rd */ > +static bool trans_MOVU_rr(DisasContext *ctx, arg_MOVU_rr *a) > +{ > + prt("movu.%c\tr%d, r%d", size[a->sz], a->rs, a->rd); > + return true; > +} > + > +/* movu.[bw] [ri,rb],rd */ > +static bool trans_MOVU_ar(DisasContext *ctx, arg_MOVU_ar *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_pr(DisasContext *ctx, arg_MOVU_pr *a) > +{ > + prt("movu.%c\t", size[a->sz]); > + prt((a->ad == 0) ? "[r%d+]" : "[-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", rx_crname[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", rx_crname[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 */ > +static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr *a) > +{ > + prt("xchg\tr%d, r%d", a->rs, a->rd); > + return true; > +} > +/* xchg dsp[rs].<mi>,rd */ > +static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a) > +{ > + int dsp; > + static const char msize[][4] = { > + "b", "w", "l", "ub", "uw", > + }; > + > + prt("xchg\t"); > + dsp = rx_index_addr(a->ld, a->mi, ctx); > + if (dsp > 0) { > + prt("%d", dsp); > + } > + prt("[r%d].%s, r%d", a->rs, msize[a->mi], a->rd); > + return true; > +} > + > +/* stz #imm,rd */ > +static bool trans_STZ(DisasContext *ctx, arg_STZ *a) > +{ > + prt_ir(ctx, "stz", a->imm, a->rd); > + return true; > +} > + > +/* stnz #imm,rd */ > +static bool trans_STNZ(DisasContext *ctx, arg_STNZ *a) > +{ > + prt_ir(ctx, "stnz", 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 << 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 << 2, a->rd, a->rd2); > + return true; > +} > + > +/* and #uimm:4, rd */ > +/* and #imm, rd */ > +static bool trans_AND_ir(DisasContext *ctx, arg_AND_ir *a) > +{ > + prt_ir(ctx, "and", a->imm, a->rd); > + return true; > +} > + > +/* and dsp[rs], rd */ > +/* and rs,rd */ > +static bool trans_AND_mr(DisasContext *ctx, arg_AND_mr *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 */ > +/* or #imm, rd */ > +static bool trans_OR_ir(DisasContext *ctx, arg_OR_ir *a) > +{ > + prt_ir(ctx, "or", a->imm, a->rd); > + return true; > +} > + > +/* or dsp[rs], rd */ > +/* or rs,rd */ > +static bool trans_OR_mr(DisasContext *ctx, arg_OR_mr *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_ir(DisasContext *ctx, arg_XOR_ir *a) > +{ > + prt_ir(ctx, "xor", a->imm, a->rd); > + return true; > +} > + > +/* xor dsp[rs], rd */ > +/* xor rs,rd */ > +static bool trans_XOR_mr(DisasContext *ctx, arg_XOR_mr *a) > +{ > + prt("xor\t"); > + operand(ctx, a->ld, a->mi, a->rs, a->rd); > + return true; > +} > + > +/* tst #imm, rd */ > +static bool trans_TST_ir(DisasContext *ctx, arg_TST_ir *a) > +{ > + prt_ir(ctx, "tst", a->imm, a->rd); > + return true; > +} > + > +/* tst dsp[rs], rd */ > +/* tst rs, rd */ > +static bool trans_TST_mr(DisasContext *ctx, arg_TST_mr *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 != a->rd) { > + 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 != a->rd) { > + prt("r%d, ", a->rs); > + } > + prt("r%d", a->rd); > + return true; > +} > + > +/* adc #imm, rd */ > +static bool trans_ADC_ir(DisasContext *ctx, arg_ADC_ir *a) > +{ > + prt_ir(ctx, "adc", 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_mr(DisasContext *ctx, arg_ADC_mr *a) > +{ > + int dsp; > + prt("adc\t"); > + dsp = rx_index_addr(a->ld, 2, ctx); > + if (dsp > 0) { > + prt("%d", dsp); > + } > + prt("[r%d], r%d", a->rs, a->rd); > + return true; > +} > + > +/* add #uimm4, rd */ > +/* add #imm, rs, rd */ > +static bool trans_ADD_irr(DisasContext *ctx, arg_ADD_irr *a) > +{ > + if (a->imm < 0x10 && a->rs2 == a->rd) { > + prt("add\t#%d, r%d", a->imm, a->rd); > + } else { > + prt("add\t#0x%08x, r%d, r%d", a->imm, a->rs2, a->rd); > + } > + return true; > +} > + > +/* add rs, rd */ > +/* add dsp[rs], rd */ > +static bool trans_ADD_mr(DisasContext *ctx, arg_ADD_mr *a) > +{ > + prt("add\t"); > + operand(ctx, a->ld, a->mi, a->rs, 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 */ > +/* cmp #imm, rs2 */ > +static bool trans_CMP_ir(DisasContext *ctx, arg_CMP_ir *a) > +{ > + prt_ir(ctx, "cmp", a->imm, a->rs2); > + return true; > +} > + > +/* cmp rs, rs2 */ > +/* cmp dsp[rs], rs2 */ > +static bool trans_CMP_mr(DisasContext *ctx, arg_CMP_mr *a) > +{ > + prt("cmp\t"); > + operand(ctx, a->ld, a->mi, a->rs, a->rd); > + return true; > +} > + > +/* sub #imm4, rd */ > +static bool trans_SUB_ir(DisasContext *ctx, arg_SUB_ir *a) > +{ > + prt("sub\t#%d, r%d", a->imm, a->rd); > + return true; > +} > + > +/* sub rs, rd */ > +/* sub dsp[rs], rd */ > +static bool trans_SUB_mr(DisasContext *ctx, arg_SUB_mr *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, r%d", a->rs, a->rd); > + return true; > +} > + > +/* sbb dsp[rs], rd */ > +static bool trans_SBB_mr(DisasContext *ctx, arg_SBB_mr *a) > +{ > + prt("sbb\t"); > + operand(ctx, a->ld, RX_IM_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 == a->rd) { > + prt("r%d", a->rd); > + } else { > + prt("r%d, r%d", a->rs, a->rd); > + } > + return true; > +} > + > +/* max #imm, rd */ > +static bool trans_MAX_ir(DisasContext *ctx, arg_MAX_ir *a) > +{ > + prt_ir(ctx, "max", a->imm, a->rd); > + return true; > +} > + > +/* max rs, rd */ > +/* max dsp[rs], rd */ > +static bool trans_MAX_mr(DisasContext *ctx, arg_MAX_mr *a) > +{ > + prt("max\t"); > + operand(ctx, a->ld, a->mi, a->rs, a->rd); > + return true; > +} > + > +/* min #imm, rd */ > +static bool trans_MIN_ir(DisasContext *ctx, arg_MIN_ir *a) > +{ > + prt_ir(ctx, "min", a->imm, a->rd); > + return true; > +} > + > +/* min rs, rd */ > +/* min dsp[rs], rd */ > +static bool trans_MIN_mr(DisasContext *ctx, arg_MIN_mr *a) > +{ > + prt("max\t"); > + operand(ctx, a->ld, a->mi, a->rs, a->rd); > + return true; > +} > + > +/* mul #uimm4, rd */ > +/* mul #imm, rd */ > +static bool trans_MUL_ir(DisasContext *ctx, arg_MUL_ir *a) > +{ > + prt_ir(ctx, "mul", a->imm, a->rd); > + return true; > +} > + > +/* mul rs, rd */ > +/* mul dsp[rs], rd */ > +static bool trans_MUL_mr(DisasContext *ctx, arg_MUL_mr *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_ir(DisasContext *ctx, arg_EMUL_ir *a) > +{ > + prt_ir(ctx, "emul", a->imm, a->rd); > + return true; > +} > + > +/* emul rs, rd */ > +/* emul dsp[rs], rd */ > +static bool trans_EMUL_mr(DisasContext *ctx, arg_EMUL_mr *a) > +{ > + prt("emul\t"); > + operand(ctx, a->ld, a->mi, a->rs, a->rd); > + return true; > +} > + > +/* emulu #imm, rd */ > +static bool trans_EMULU_ir(DisasContext *ctx, arg_EMULU_ir *a) > +{ > + prt_ir(ctx, "emulu", a->imm, a->rd); > + return true; > +} > + > +/* emulu rs, rd */ > +/* emulu dsp[rs], rd */ > +static bool trans_EMULU_mr(DisasContext *ctx, arg_EMULU_mr *a) > +{ > + prt("emulu\t"); > + operand(ctx, a->ld, a->mi, a->rs, a->rd); > + return true; > +} > + > +/* div #imm, rd */ > +static bool trans_DIV_ir(DisasContext *ctx, arg_DIV_ir *a) > +{ > + prt_ir(ctx, "div", a->imm, a->rd); > + return true; > +} > + > +/* div rs, rd */ > +/* div dsp[rs], rd */ > +static bool trans_DIV_mr(DisasContext *ctx, arg_DIV_mr *a) > +{ > + prt("div\t"); > + operand(ctx, a->ld, a->mi, a->rs, a->rd); > + return true; > +} > + > +/* divu #imm, rd */ > +static bool trans_DIVU_ir(DisasContext *ctx, arg_DIVU_ir *a) > +{ > + prt_ir(ctx, "divu", a->imm, a->rd); > + return true; > +} > + > +/* divu rs, rd */ > +/* divu dsp[rs], rd */ > +static bool trans_DIVU_mr(DisasContext *ctx, arg_DIVU_mr *a) > +{ > + prt("divu\t"); > + 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_irr(DisasContext *ctx, arg_SHLL_irr *a) > +{ > + prt("shll\t#%d, ", a->imm); > + if (a->rs2 != a->rd) { > + 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_irr(DisasContext *ctx, arg_SHAR_irr *a) > +{ > + prt("shar\t#%d,", a->imm); > + if (a->rs2 != a->rd) { > + 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_irr(DisasContext *ctx, arg_SHLR_irr *a) > +{ > + prt("shlr\t#%d, ", a->imm); > + if (a->rs2 != a->rd) { > + 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_ir(DisasContext *ctx, arg_ROTL_ir *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_ir(DisasContext *ctx, arg_ROTR_ir *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 len, int dst) > +{ > + static const char sz[] = {'s', 'b', 'w', 'a'}; > + prt("b%s.%c\t%08x", cond[cd], sz[len - 1], ctx->pc + dst); > +} > + > +/* beq dsp:3 / bne dsp:3 */ > +/* 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 */ > +/* beq dsp:16 / bne dsp:16 */ > +static bool trans_BCnd(DisasContext *ctx, arg_BCnd *a) > +{ > + rx_bcnd_main(ctx, a->cd, a->sz, a->dsp); > + return true; > +} > + > +/* bra dsp:3 */ > +/* bra dsp:8 */ > +/* bra dsp:16 */ > +/* bra dsp:24 */ > +static bool trans_BRA(DisasContext *ctx, arg_BRA *a) > +{ > + rx_bcnd_main(ctx, 14, a->sz, a->dsp); > + 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 */ > +/* bsr dsp:24 */ > +static bool trans_BSR(DisasContext *ctx, arg_BSR *a) > +{ > + static const char sz[] = {'w', 'a'}; > + prt("bsr.%c\t%08x", sz[a->sz - 3], ctx->pc + 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_ir(DisasContext *ctx, arg_FADD_ir *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_mr(DisasContext *ctx, arg_FADD_mr *a) > +{ > + prt("fadd\t"); > + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); > + return true; > +} > + > +/* fcmp #imm, rd */ > +static bool trans_FCMP_ir(DisasContext *ctx, arg_FCMP_ir *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_mr(DisasContext *ctx, arg_FCMP_mr *a) > +{ > + prt("fcmp\t"); > + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); > + return true; > +} > + > +/* fsub #imm, rd */ > +static bool trans_FSUB_ir(DisasContext *ctx, arg_FSUB_ir *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_mr(DisasContext *ctx, arg_FSUB_mr *a) > +{ > + prt("fsub\t"); > + operand(ctx, a->ld, RX_IM_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_IM_LONG, a->rs, a->rd); > + return true; > +} > + > +/* fmul #imm, rd */ > +static bool trans_FMUL_ir(DisasContext *ctx, arg_FMUL_ir *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_mr(DisasContext *ctx, arg_FMUL_mr *a) > +{ > + prt("fmul\t"); > + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); > + return true; > +} > + > +/* fdiv #imm, rd */ > +static bool trans_FDIV_ir(DisasContext *ctx, arg_FDIV_ir *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_mr(DisasContext *ctx, arg_FDIV_mr *a) > +{ > + prt("fdiv\t"); > + operand(ctx, a->ld, RX_IM_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_IM_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_IM_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) > + > +#define BOP_RM(name) \ > + do { \ > + int dsp; \ > + prt("b%s\tr%d, ", #name, a->rd); \ > + dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx); \ > + if (dsp > 0) { \ > + prt("%d", dsp); \ > + } \ > + prt("[r%d]", a->rs); \ > + return true; \ > + } while (0) > + > +/* bset #imm, dsp[rd] */ > +static bool trans_BSET_im(DisasContext *ctx, arg_BSET_im *a) > +{ > + BOP_IM(bset, a->rs); > +} > + > +/* bset rs, dsp[rd] */ > +static bool trans_BSET_rm(DisasContext *ctx, arg_BSET_rm *a) > +{ > + BOP_RM(set); > +} > + > +/* bset rs, rd */ > +static bool trans_BSET_rr(DisasContext *ctx, arg_BSET_rr *a) > +{ > + prt("bset\tr%d,r%d", a->rs, a->rd); > + return true; > +} > + > +/* bset #imm, rd */ > +static bool trans_BSET_ir(DisasContext *ctx, arg_BSET_ir *a) > +{ > + prt("bset\t#%d, r%d", a->imm, a->rd); > + return true; > +} > + > +/* bclr #imm, dsp[rd] */ > +static bool trans_BCLR_im(DisasContext *ctx, arg_BCLR_im *a) > +{ > + BOP_IM(clr, a->rs); > +} > + > +/* bclr rs, dsp[rd] */ > +static bool trans_BCLR_rm(DisasContext *ctx, arg_BCLR_rm *a) > +{ > + BOP_RM(clr); > +} > + > +/* bclr rs, rd */ > +static bool trans_BCLR_rr(DisasContext *ctx, arg_BCLR_rr *a) > +{ > + prt("bclr\tr%d, r%d", a->rs, a->rd); > + return true; > +} > + > +/* bclr #imm, rd */ > +static bool trans_BCLR_ir(DisasContext *ctx, arg_BCLR_ir *a) > +{ > + prt("bclr\t#%d,r%d", a->imm, a->rd); > + return true; > +} > + > +/* btst #imm, dsp[rd] */ > +static bool trans_BTST_im(DisasContext *ctx, arg_BTST_im *a) > +{ > + BOP_IM(tst, a->rs); > +} > + > +/* btst rs, dsp[rd] */ > +static bool trans_BTST_rm(DisasContext *ctx, arg_BTST_rm *a) > +{ > + BOP_RM(tst); > +} > + > +/* btst rs, rd */ > +static bool trans_BTST_rr(DisasContext *ctx, arg_BTST_rr *a) > +{ > + prt("btst\tr%d, r%d", a->rs, a->rd); > + return true; > +} > + > +/* btst #imm, rd */ > +static bool trans_BTST_ir(DisasContext *ctx, arg_BTST_ir *a) > +{ > + prt("btst\t#%d, r%d", a->imm, a->rd); > + return true; > +} > + > +/* bnot rs, dsp[rd] */ > +static bool trans_BNOT_rm(DisasContext *ctx, arg_BNOT_rm *a) > +{ > + BOP_RM(not); > +} > + > +/* bnot rs, rd */ > +static bool trans_BNOT_rr(DisasContext *ctx, arg_BNOT_rr *a) > +{ > + prt("bnot\tr%d, r%d", a->rs, a->rd); > + return true; > +} > + > +/* bnot #imm, dsp[rd] */ > +static bool trans_BNOT_im(DisasContext *ctx, arg_BNOT_im *a) > +{ > + BOP_IM(not, a->rs); > +} > + > +/* bnot #imm, rd */ > +static bool trans_BNOT_ir(DisasContext *ctx, arg_BNOT_ir *a) > +{ > + prt("bnot\t#%d, r%d", a->imm, a->rd); > + return true; > +} > + > +/* bmcond #imm, dsp[rd] */ > +static bool trans_BMCnd_im(DisasContext *ctx, arg_BMCnd_im *a) > +{ > + 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 */ > +static bool trans_BMCnd_ir(DisasContext *ctx, arg_BMCnd_ir *a) > +{ > + 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, rx_crname[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, rx_crname[a->cr]); > + return true; > +} > + > +/* mvfc rs, rd */ > +static bool trans_MVFC(DisasContext *ctx, arg_MVFC *a) > +{ > + prt("mvfc\t%s, r%d", rx_crname[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.pc = 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; > +} >
On 5/8/19 7:56 AM, Yoshinori Sato wrote: > Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp> > --- > include/disas/dis-asm.h | 5 + > target/rx/disas.c | 1480 +++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 1485 insertions(+) > create mode 100644 target/rx/disas.c Reviewed-by: Richard Henderson <richard.henderson@linaro.org> r~
diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h index 9240ec32c2..de17792e88 100644 --- a/include/disas/dis-asm.h +++ b/include/disas/dis-asm.h @@ -226,6 +226,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 @@ -433,6 +437,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..3dce2dd864 --- /dev/null +++ b/target/rx/disas.c @@ -0,0 +1,1480 @@ +/* + * Renesas RX Disassembler + * + * Copyright (c) 2019 Yoshinori Sato <ysato@users.sourceforge.jp> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "disas/dis-asm.h" +#include "qemu/bitops.h" +#include "cpu.h" + +typedef struct DisasContext { + disassemble_info *dis; + uint32_t addr; + uint32_t pc; +} 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 (int8_t)buf[0]; + case 2: + ctx->addr += 2; + ctx->dis->read_memory_func(addr, buf, 2, ctx->dis); + return ldsw_le_p(buf); + case 3: + ctx->addr += 3; + ctx->dis->read_memory_func(addr, buf, 3, ctx->dis); + return (int8_t)buf[2] << 16 | lduw_le_p(buf); + case 0: + ctx->addr += 4; + ctx->dis->read_memory_func(addr, buf, 4, ctx->dis); + return ldl_le_p(buf); + default: + g_assert_not_reached(); + } +} + +static int bdsp_s(DisasContext *ctx, int d) +{ + /* + * 0 -> 8 + * 1 -> 9 + * 2 -> 10 + * 3 -> 3 + * : + * 7 -> 7 + */ + if (d < 3) { + d += 8; + } + return d; +} + +/* 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_IM_BYTE 0 +#define RX_IM_WORD 1 +#define RX_IM_LONG 2 +#define RX_IM_UWORD 3 + +static const char size[] = {'b', 'w', 'l'}; +static const char cond[][4] = { + "eq", "ne", "c", "nc", "gtu", "leu", "pz", "n", + "ge", "lt", "gt", "le", "o", "no", "ra", "f" +}; +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 ((uint8_t)buf[0]) << size; + case 2: + ctx->dis->read_memory_func(ctx->addr, buf, 2, ctx->dis); + ctx->addr += 2; + return lduw_le_p(buf) << size; + } + g_assert_not_reached(); +} + +static void operand(DisasContext *ctx, int ld, int mi, int rs, int rd) +{ + int dsp; + static const char sizes[][4] = {".b", ".w", ".l", ".uw", ".ub"}; + if (ld < 3) { + switch (mi) { + case 4: + /* dsp[rs].ub */ + dsp = rx_index_addr(ld, RX_MEMORY_BYTE, ctx); + break; + case 3: + /* dsp[rs].uw */ + dsp = rx_index_addr(ld, RX_MEMORY_WORD, ctx); + break; + default: + /* dsp[rs].b */ + /* dsp[rs].w */ + /* dsp[rs].l */ + dsp = rx_index_addr(ld, mi, ctx); + break; + } + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d]%s", rs, sizes[mi]); + } else { + prt("r%d", rs); + } + prt(", r%d", rd); +} + +static void prt_ir(DisasContext *ctx, const char *insn, int imm, int rd) +{ + if (imm < 0x100) { + prt("%s\t#%d, r%d", insn, imm, rd); + } else { + prt("%s\t#0x%08x, r%d", insn, imm, rd); + } +} + +/* mov.[bwl] rs,dsp:[rd] */ +static bool trans_MOV_rm(DisasContext *ctx, arg_MOV_rm *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_mr(DisasContext *ctx, arg_MOV_mr *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 */ +/* mov.l #imm,rd */ +static bool trans_MOV_ir(DisasContext *ctx, arg_MOV_ir *a) +{ + prt_ir(ctx, "mov.l", a->imm, a->rd); + return true; +} + +/* mov.[bwl] #uimm8,dsp:[rd] */ +/* mov #imm, dsp:[rd] */ +static bool trans_MOV_im(DisasContext *ctx, arg_MOV_im *a) +{ + if (a->dsp > 0) { + prt("mov.%c\t#%d,%d[r%d]", + size[a->sz], a->imm, a->dsp << a->sz, a->rd); + } else { + prt("mov.%c\t#%d,[r%d]", + size[a->sz], a->imm, a->rd); + } + return true; +} + +/* mov.[bwl] [ri,rb],rd */ +static bool trans_MOV_ar(DisasContext *ctx, arg_MOV_ar *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_ra(DisasContext *ctx, arg_MOV_ra *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_mm(DisasContext *ctx, arg_MOV_mm *a) +{ + int dsp; + + prt("mov.%c\t", size[a->sz]); + if (a->lds == 3 && a->ldd == 3) { + /* mov.[bwl] rs,rd */ + prt("r%d, r%d", a->rs, a->rd); + return true; + } + if (a->lds == 3) { + prt("r%d, ", a->rd); + dsp = rx_index_addr(a->ldd, a->sz, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d]", a->rs); + } else if (a->ldd == 3) { + dsp = rx_index_addr(a->lds, a->sz, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d], r%d", a->rs, a->rd); + } else { + dsp = rx_index_addr(a->lds, a->sz, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d], ", a->rs); + dsp = rx_index_addr(a->ldd, a->sz, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d]", a->rd); + } + return true; +} + +/* mov.[bwl] rs,[rd+] */ +/* mov.[bwl] rs,[-rd] */ +static bool trans_MOV_rp(DisasContext *ctx, arg_MOV_rp *a) +{ + prt("mov.%c\tr%d, ", size[a->sz], a->rs); + prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd); + return true; +} + +/* mov.[bwl] [rd+],rs */ +/* mov.[bwl] [-rd],rs */ +static bool trans_MOV_pr(DisasContext *ctx, arg_MOV_pr *a) +{ + prt("mov.%c\t", size[a->sz]); + prt((a->ad == 0) ? "[r%d+]" : "[-r%d]", a->rd); + prt(", r%d", a->rs); + return true; +} + +/* movu.[bw] dsp5:[rs],rd */ +static bool trans_MOVU_mr(DisasContext *ctx, arg_MOVU_mr *a) +{ + if (a->dsp > 0) { + prt("movu.%c\t%d[r%d], r%d", size[a->sz], + a->dsp << a->sz, a->rs, a->rd); + } else { + prt("movu.%c\t[r%d], r%d", size[a->sz], a->rs, a->rd); + } + return true; +} + +/* movu.[bw] rs,rd */ +static bool trans_MOVU_rr(DisasContext *ctx, arg_MOVU_rr *a) +{ + prt("movu.%c\tr%d, r%d", size[a->sz], a->rs, a->rd); + return true; +} + +/* movu.[bw] [ri,rb],rd */ +static bool trans_MOVU_ar(DisasContext *ctx, arg_MOVU_ar *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_pr(DisasContext *ctx, arg_MOVU_pr *a) +{ + prt("movu.%c\t", size[a->sz]); + prt((a->ad == 0) ? "[r%d+]" : "[-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", rx_crname[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", rx_crname[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 */ +static bool trans_XCHG_rr(DisasContext *ctx, arg_XCHG_rr *a) +{ + prt("xchg\tr%d, r%d", a->rs, a->rd); + return true; +} +/* xchg dsp[rs].<mi>,rd */ +static bool trans_XCHG_mr(DisasContext *ctx, arg_XCHG_mr *a) +{ + int dsp; + static const char msize[][4] = { + "b", "w", "l", "ub", "uw", + }; + + prt("xchg\t"); + dsp = rx_index_addr(a->ld, a->mi, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d].%s, r%d", a->rs, msize[a->mi], a->rd); + return true; +} + +/* stz #imm,rd */ +static bool trans_STZ(DisasContext *ctx, arg_STZ *a) +{ + prt_ir(ctx, "stz", a->imm, a->rd); + return true; +} + +/* stnz #imm,rd */ +static bool trans_STNZ(DisasContext *ctx, arg_STNZ *a) +{ + prt_ir(ctx, "stnz", 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 << 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 << 2, a->rd, a->rd2); + return true; +} + +/* and #uimm:4, rd */ +/* and #imm, rd */ +static bool trans_AND_ir(DisasContext *ctx, arg_AND_ir *a) +{ + prt_ir(ctx, "and", a->imm, a->rd); + return true; +} + +/* and dsp[rs], rd */ +/* and rs,rd */ +static bool trans_AND_mr(DisasContext *ctx, arg_AND_mr *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 */ +/* or #imm, rd */ +static bool trans_OR_ir(DisasContext *ctx, arg_OR_ir *a) +{ + prt_ir(ctx, "or", a->imm, a->rd); + return true; +} + +/* or dsp[rs], rd */ +/* or rs,rd */ +static bool trans_OR_mr(DisasContext *ctx, arg_OR_mr *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_ir(DisasContext *ctx, arg_XOR_ir *a) +{ + prt_ir(ctx, "xor", a->imm, a->rd); + return true; +} + +/* xor dsp[rs], rd */ +/* xor rs,rd */ +static bool trans_XOR_mr(DisasContext *ctx, arg_XOR_mr *a) +{ + prt("xor\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* tst #imm, rd */ +static bool trans_TST_ir(DisasContext *ctx, arg_TST_ir *a) +{ + prt_ir(ctx, "tst", a->imm, a->rd); + return true; +} + +/* tst dsp[rs], rd */ +/* tst rs, rd */ +static bool trans_TST_mr(DisasContext *ctx, arg_TST_mr *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 != a->rd) { + 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 != a->rd) { + prt("r%d, ", a->rs); + } + prt("r%d", a->rd); + return true; +} + +/* adc #imm, rd */ +static bool trans_ADC_ir(DisasContext *ctx, arg_ADC_ir *a) +{ + prt_ir(ctx, "adc", 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_mr(DisasContext *ctx, arg_ADC_mr *a) +{ + int dsp; + prt("adc\t"); + dsp = rx_index_addr(a->ld, 2, ctx); + if (dsp > 0) { + prt("%d", dsp); + } + prt("[r%d], r%d", a->rs, a->rd); + return true; +} + +/* add #uimm4, rd */ +/* add #imm, rs, rd */ +static bool trans_ADD_irr(DisasContext *ctx, arg_ADD_irr *a) +{ + if (a->imm < 0x10 && a->rs2 == a->rd) { + prt("add\t#%d, r%d", a->imm, a->rd); + } else { + prt("add\t#0x%08x, r%d, r%d", a->imm, a->rs2, a->rd); + } + return true; +} + +/* add rs, rd */ +/* add dsp[rs], rd */ +static bool trans_ADD_mr(DisasContext *ctx, arg_ADD_mr *a) +{ + prt("add\t"); + operand(ctx, a->ld, a->mi, a->rs, 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 */ +/* cmp #imm, rs2 */ +static bool trans_CMP_ir(DisasContext *ctx, arg_CMP_ir *a) +{ + prt_ir(ctx, "cmp", a->imm, a->rs2); + return true; +} + +/* cmp rs, rs2 */ +/* cmp dsp[rs], rs2 */ +static bool trans_CMP_mr(DisasContext *ctx, arg_CMP_mr *a) +{ + prt("cmp\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* sub #imm4, rd */ +static bool trans_SUB_ir(DisasContext *ctx, arg_SUB_ir *a) +{ + prt("sub\t#%d, r%d", a->imm, a->rd); + return true; +} + +/* sub rs, rd */ +/* sub dsp[rs], rd */ +static bool trans_SUB_mr(DisasContext *ctx, arg_SUB_mr *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, r%d", a->rs, a->rd); + return true; +} + +/* sbb dsp[rs], rd */ +static bool trans_SBB_mr(DisasContext *ctx, arg_SBB_mr *a) +{ + prt("sbb\t"); + operand(ctx, a->ld, RX_IM_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 == a->rd) { + prt("r%d", a->rd); + } else { + prt("r%d, r%d", a->rs, a->rd); + } + return true; +} + +/* max #imm, rd */ +static bool trans_MAX_ir(DisasContext *ctx, arg_MAX_ir *a) +{ + prt_ir(ctx, "max", a->imm, a->rd); + return true; +} + +/* max rs, rd */ +/* max dsp[rs], rd */ +static bool trans_MAX_mr(DisasContext *ctx, arg_MAX_mr *a) +{ + prt("max\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* min #imm, rd */ +static bool trans_MIN_ir(DisasContext *ctx, arg_MIN_ir *a) +{ + prt_ir(ctx, "min", a->imm, a->rd); + return true; +} + +/* min rs, rd */ +/* min dsp[rs], rd */ +static bool trans_MIN_mr(DisasContext *ctx, arg_MIN_mr *a) +{ + prt("max\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* mul #uimm4, rd */ +/* mul #imm, rd */ +static bool trans_MUL_ir(DisasContext *ctx, arg_MUL_ir *a) +{ + prt_ir(ctx, "mul", a->imm, a->rd); + return true; +} + +/* mul rs, rd */ +/* mul dsp[rs], rd */ +static bool trans_MUL_mr(DisasContext *ctx, arg_MUL_mr *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_ir(DisasContext *ctx, arg_EMUL_ir *a) +{ + prt_ir(ctx, "emul", a->imm, a->rd); + return true; +} + +/* emul rs, rd */ +/* emul dsp[rs], rd */ +static bool trans_EMUL_mr(DisasContext *ctx, arg_EMUL_mr *a) +{ + prt("emul\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* emulu #imm, rd */ +static bool trans_EMULU_ir(DisasContext *ctx, arg_EMULU_ir *a) +{ + prt_ir(ctx, "emulu", a->imm, a->rd); + return true; +} + +/* emulu rs, rd */ +/* emulu dsp[rs], rd */ +static bool trans_EMULU_mr(DisasContext *ctx, arg_EMULU_mr *a) +{ + prt("emulu\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* div #imm, rd */ +static bool trans_DIV_ir(DisasContext *ctx, arg_DIV_ir *a) +{ + prt_ir(ctx, "div", a->imm, a->rd); + return true; +} + +/* div rs, rd */ +/* div dsp[rs], rd */ +static bool trans_DIV_mr(DisasContext *ctx, arg_DIV_mr *a) +{ + prt("div\t"); + operand(ctx, a->ld, a->mi, a->rs, a->rd); + return true; +} + +/* divu #imm, rd */ +static bool trans_DIVU_ir(DisasContext *ctx, arg_DIVU_ir *a) +{ + prt_ir(ctx, "divu", a->imm, a->rd); + return true; +} + +/* divu rs, rd */ +/* divu dsp[rs], rd */ +static bool trans_DIVU_mr(DisasContext *ctx, arg_DIVU_mr *a) +{ + prt("divu\t"); + 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_irr(DisasContext *ctx, arg_SHLL_irr *a) +{ + prt("shll\t#%d, ", a->imm); + if (a->rs2 != a->rd) { + 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_irr(DisasContext *ctx, arg_SHAR_irr *a) +{ + prt("shar\t#%d,", a->imm); + if (a->rs2 != a->rd) { + 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_irr(DisasContext *ctx, arg_SHLR_irr *a) +{ + prt("shlr\t#%d, ", a->imm); + if (a->rs2 != a->rd) { + 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_ir(DisasContext *ctx, arg_ROTL_ir *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_ir(DisasContext *ctx, arg_ROTR_ir *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 len, int dst) +{ + static const char sz[] = {'s', 'b', 'w', 'a'}; + prt("b%s.%c\t%08x", cond[cd], sz[len - 1], ctx->pc + dst); +} + +/* beq dsp:3 / bne dsp:3 */ +/* 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 */ +/* beq dsp:16 / bne dsp:16 */ +static bool trans_BCnd(DisasContext *ctx, arg_BCnd *a) +{ + rx_bcnd_main(ctx, a->cd, a->sz, a->dsp); + return true; +} + +/* bra dsp:3 */ +/* bra dsp:8 */ +/* bra dsp:16 */ +/* bra dsp:24 */ +static bool trans_BRA(DisasContext *ctx, arg_BRA *a) +{ + rx_bcnd_main(ctx, 14, a->sz, a->dsp); + 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 */ +/* bsr dsp:24 */ +static bool trans_BSR(DisasContext *ctx, arg_BSR *a) +{ + static const char sz[] = {'w', 'a'}; + prt("bsr.%c\t%08x", sz[a->sz - 3], ctx->pc + 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_ir(DisasContext *ctx, arg_FADD_ir *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_mr(DisasContext *ctx, arg_FADD_mr *a) +{ + prt("fadd\t"); + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + return true; +} + +/* fcmp #imm, rd */ +static bool trans_FCMP_ir(DisasContext *ctx, arg_FCMP_ir *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_mr(DisasContext *ctx, arg_FCMP_mr *a) +{ + prt("fcmp\t"); + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + return true; +} + +/* fsub #imm, rd */ +static bool trans_FSUB_ir(DisasContext *ctx, arg_FSUB_ir *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_mr(DisasContext *ctx, arg_FSUB_mr *a) +{ + prt("fsub\t"); + operand(ctx, a->ld, RX_IM_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_IM_LONG, a->rs, a->rd); + return true; +} + +/* fmul #imm, rd */ +static bool trans_FMUL_ir(DisasContext *ctx, arg_FMUL_ir *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_mr(DisasContext *ctx, arg_FMUL_mr *a) +{ + prt("fmul\t"); + operand(ctx, a->ld, RX_IM_LONG, a->rs, a->rd); + return true; +} + +/* fdiv #imm, rd */ +static bool trans_FDIV_ir(DisasContext *ctx, arg_FDIV_ir *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_mr(DisasContext *ctx, arg_FDIV_mr *a) +{ + prt("fdiv\t"); + operand(ctx, a->ld, RX_IM_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_IM_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_IM_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) + +#define BOP_RM(name) \ + do { \ + int dsp; \ + prt("b%s\tr%d, ", #name, a->rd); \ + dsp = rx_index_addr(a->ld, RX_MEMORY_BYTE, ctx); \ + if (dsp > 0) { \ + prt("%d", dsp); \ + } \ + prt("[r%d]", a->rs); \ + return true; \ + } while (0) + +/* bset #imm, dsp[rd] */ +static bool trans_BSET_im(DisasContext *ctx, arg_BSET_im *a) +{ + BOP_IM(bset, a->rs); +} + +/* bset rs, dsp[rd] */ +static bool trans_BSET_rm(DisasContext *ctx, arg_BSET_rm *a) +{ + BOP_RM(set); +} + +/* bset rs, rd */ +static bool trans_BSET_rr(DisasContext *ctx, arg_BSET_rr *a) +{ + prt("bset\tr%d,r%d", a->rs, a->rd); + return true; +} + +/* bset #imm, rd */ +static bool trans_BSET_ir(DisasContext *ctx, arg_BSET_ir *a) +{ + prt("bset\t#%d, r%d", a->imm, a->rd); + return true; +} + +/* bclr #imm, dsp[rd] */ +static bool trans_BCLR_im(DisasContext *ctx, arg_BCLR_im *a) +{ + BOP_IM(clr, a->rs); +} + +/* bclr rs, dsp[rd] */ +static bool trans_BCLR_rm(DisasContext *ctx, arg_BCLR_rm *a) +{ + BOP_RM(clr); +} + +/* bclr rs, rd */ +static bool trans_BCLR_rr(DisasContext *ctx, arg_BCLR_rr *a) +{ + prt("bclr\tr%d, r%d", a->rs, a->rd); + return true; +} + +/* bclr #imm, rd */ +static bool trans_BCLR_ir(DisasContext *ctx, arg_BCLR_ir *a) +{ + prt("bclr\t#%d,r%d", a->imm, a->rd); + return true; +} + +/* btst #imm, dsp[rd] */ +static bool trans_BTST_im(DisasContext *ctx, arg_BTST_im *a) +{ + BOP_IM(tst, a->rs); +} + +/* btst rs, dsp[rd] */ +static bool trans_BTST_rm(DisasContext *ctx, arg_BTST_rm *a) +{ + BOP_RM(tst); +} + +/* btst rs, rd */ +static bool trans_BTST_rr(DisasContext *ctx, arg_BTST_rr *a) +{ + prt("btst\tr%d, r%d", a->rs, a->rd); + return true; +} + +/* btst #imm, rd */ +static bool trans_BTST_ir(DisasContext *ctx, arg_BTST_ir *a) +{ + prt("btst\t#%d, r%d", a->imm, a->rd); + return true; +} + +/* bnot rs, dsp[rd] */ +static bool trans_BNOT_rm(DisasContext *ctx, arg_BNOT_rm *a) +{ + BOP_RM(not); +} + +/* bnot rs, rd */ +static bool trans_BNOT_rr(DisasContext *ctx, arg_BNOT_rr *a) +{ + prt("bnot\tr%d, r%d", a->rs, a->rd); + return true; +} + +/* bnot #imm, dsp[rd] */ +static bool trans_BNOT_im(DisasContext *ctx, arg_BNOT_im *a) +{ + BOP_IM(not, a->rs); +} + +/* bnot #imm, rd */ +static bool trans_BNOT_ir(DisasContext *ctx, arg_BNOT_ir *a) +{ + prt("bnot\t#%d, r%d", a->imm, a->rd); + return true; +} + +/* bmcond #imm, dsp[rd] */ +static bool trans_BMCnd_im(DisasContext *ctx, arg_BMCnd_im *a) +{ + 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 */ +static bool trans_BMCnd_ir(DisasContext *ctx, arg_BMCnd_ir *a) +{ + 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, rx_crname[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, rx_crname[a->cr]); + return true; +} + +/* mvfc rs, rd */ +static bool trans_MVFC(DisasContext *ctx, arg_MVFC *a) +{ + prt("mvfc\t%s, r%d", rx_crname[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.pc = 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; +}
Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp> --- include/disas/dis-asm.h | 5 + target/rx/disas.c | 1480 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1485 insertions(+) create mode 100644 target/rx/disas.c