librz/arch/sh: add SuperH-3 support via asm.cpu (#6531)

Co-authored-by agent: Claude/Claude-Opus-4.8
Co-authored-by: Anton Kochkov <anton.kochkov@gmail.com>
This commit is contained in:
NOT XVilka 2026-06-19 04:37:30 +08:00 committed by GitHub
parent 5fb6f39091
commit 9217b0a86a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 407 additions and 202 deletions

View file

@ -391,15 +391,16 @@ static bool sh_op_compare(SHOpRaw raw, const char *mnem, SHAddrHelper modes[]) {
}
/**
* \brief Assemble instruction from SuperH-4 ISA
* \brief Assemble instruction from SuperH ISA
* FPU instructions not implemented yet
*
* \param buffer Instruction string buffer
* \param pc Current value of program counter
* \param success Store bool whether the assembler succeeded or not (RZ_NULLABLE)
* \param cpu SuperH CPU model to assemble for (instructions not available on it will fail)
* \return ut16 Opcode for the given instruction
*/
RZ_IPI ut16 sh_assembler(RZ_NONNULL const char *buffer, ut64 pc, RZ_NULLABLE bool *success) {
RZ_IPI ut16 sh_assembler(RZ_NONNULL const char *buffer, ut64 pc, RZ_NULLABLE bool *success, SHCpu cpu) {
rz_return_val_if_fail(buffer, -1);
if (success) {
*success = true;
@ -434,10 +435,15 @@ RZ_IPI ut16 sh_assembler(RZ_NONNULL const char *buffer, ut64 pc, RZ_NULLABLE boo
j++;
}
SHArch want = (cpu == SH_CPU_SH3) ? SH_ARCH_SH3 : SH_ARCH_SH4;
for (ut16 i = 0; i < OPCODE_NUM; i++) {
if (!sh_op_compare(sh_op_lookup[i], mnem, sham)) {
continue;
}
if (!(sh_op_lookup[i].arch & want)) {
// instruction is not available on the selected CPU
continue;
}
SHOpRaw raw = sh_op_lookup[i];
opcode = raw.opcode ^ raw.mask;

View file

@ -7,6 +7,6 @@
#include "common.h"
#include "disassembler.h"
RZ_IPI ut16 sh_assembler(RZ_NONNULL const char *buffer, ut64 pc, RZ_NULLABLE bool *success);
RZ_IPI ut16 sh_assembler(RZ_NONNULL const char *buffer, ut64 pc, RZ_NULLABLE bool *success, SHCpu cpu);
#endif // RZ_SH_ASSEMBLER_H

View file

@ -28,6 +28,7 @@ typedef struct sh_op_raw_t {
ut16 mask; ///< mask for opcode to mask out param bits
SHScaling scaling; ///< scaling for the opcode
SHParamBuilder param_builder[2]; ///< param builders for the params
SHArch arch; ///< set of SuperH CPU models on which this instruction is available
} SHOpRaw;
// xxxx used to denote param fields in the opcode

View file

@ -121,17 +121,44 @@ static SHParam sh_op_get_param_movl(ut16 opcode, bool m) {
}
}
/**
* \brief Resolve the SuperH CPU model from its "asm.cpu" name
*
* \param name CPU name (e.g. "sh3", "sh4"), may be NULL or empty
* \return SHCpu the matching CPU model, defaulting to \ref SH_CPU_SH4
*/
RZ_IPI SHCpu sh_cpu_by_name(RZ_NULLABLE const char *name) {
if (RZ_STR_ISEMPTY(name)) {
return SH_CPU_SH4;
}
if (RZ_STR_EQ(name, "sh3")) {
return SH_CPU_SH3;
}
// SuperH-4 is the default and keeps backward compatibility
return SH_CPU_SH4;
}
/**
* \brief Disassemble \p opcode and return a SHOp
*
* Instructions which do not belong to \p cpu are not decoded (NULL is
* returned), so that e.g. SuperH-4 only instructions are treated as invalid
* when disassembling for SuperH-3.
*
* \param opcode 16 bit wide opcode
* \param cpu SuperH CPU model to disassemble for
* \return SHOp object corresponding to the opcode
*/
RZ_IPI RZ_OWN SHOp *sh_disassembler(ut16 opcode) {
RZ_IPI RZ_OWN SHOp *sh_disassembler(ut16 opcode, SHCpu cpu) {
SHArch want = (cpu == SH_CPU_SH3) ? SH_ARCH_SH3 : SH_ARCH_SH4;
for (ut16 i = 0; i < OPCODE_NUM; i++) {
if ((opcode | sh_op_lookup[i].mask) != sh_op_lookup[i].opcode) {
continue;
}
if (!(sh_op_lookup[i].arch & want)) {
// instruction is not available on the selected CPU
continue;
}
SHOpRaw raw = sh_op_lookup[i];
SHOp *op = RZ_NEW(SHOp);
@ -139,6 +166,7 @@ RZ_IPI RZ_OWN SHOp *sh_disassembler(ut16 opcode) {
op->mnemonic = raw.mnemonic;
op->scaling = raw.scaling;
op->str_mnem = raw.str_mnem;
op->arch = raw.arch;
// check for "weird" mov.l
if (raw.opcode == MOVL) {
op->param[0] = sh_op_get_param_movl(opcode, true);

View file

@ -14,6 +14,33 @@
#define SH_BANKED_REG_COUNT 8
#define SH_REG_COUNT 61
/**
* \brief SuperH CPU model
*
* Selected through the "asm.cpu" option. SuperH-4 is the default since it is a
* superset (at the instruction set level) of all the currently supported
* instructions, so it keeps backward compatibility with the previous behavior.
*/
typedef enum sh_cpu_t {
SH_CPU_SH4 = 0, ///< SuperH-4 (default)
SH_CPU_SH3, ///< SuperH-3
} SHCpu;
/**
* \brief Set of SuperH CPU models on which an instruction is available
*
* Used to tag each entry of the opcode lookup table so that the disassembler
* can reject instructions which do not belong to the selected \ref SHCpu. The
* SuperH instruction set is upward compatible (SH-1 through SH-4 at the
* instruction set level), so the only currently tracked distinction is whether
* an instruction was introduced with SuperH-4 or is shared with SuperH-3.
*/
typedef enum sh_arch_t {
SH_ARCH_SH3 = 1 << 0, ///< available on SuperH-3
SH_ARCH_SH4 = 1 << 1, ///< available on SuperH-4
SH_ARCH_COMMON = SH_ARCH_SH3 | SH_ARCH_SH4, ///< available on both SuperH-3 and SuperH-4
} SHArch;
typedef enum sh_addr_mode_t {
SH_ADDR_INVALID = 0,
SH_REG_DIRECT,
@ -245,9 +272,12 @@ typedef struct sh_opcode_t {
SHOpMnem mnemonic;
SHParam param[2];
SHScaling scaling;
SHArch arch; ///< set of SuperH CPU models on which this instruction is available
} SHOp;
RZ_IPI RZ_OWN SHOp *sh_disassembler(ut16 opcode);
RZ_IPI RZ_OWN SHOp *sh_disassembler(ut16 opcode, SHCpu cpu);
RZ_IPI SHCpu sh_cpu_by_name(RZ_NULLABLE const char *name);
RZ_IPI RZ_OWN char *sh_op_param_to_str(SHParam param, SHScaling scaling, ut64 pc);
RZ_IPI RZ_OWN char *sh_op_to_str(RZ_NONNULL const SHOp *op, ut64 pc);

View file

@ -6,187 +6,187 @@
// Opcode lookup list
const SHOpRaw sh_op_lookup[] = {
/* fixed-point transfer instructions */
{ "mov", SH_OP_MOV, OPCODE(e, N, I, I), 0x0fff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_U), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mov.w", SH_OP_MOV, OPCODE(9, N, D, D), 0x0fff, SH_SCALING_W, { ADDR(NIB0, SH_PC_RELATIVE_DISP), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mov.l", SH_OP_MOV, OPCODE(d, N, D, D), 0x0fff, SH_SCALING_L, { ADDR(NIB0, SH_PC_RELATIVE_DISP), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mov", SH_OP_MOV, OPCODE(6, N, M, 3), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mov.b", SH_OP_MOV, OPCODE(2, N, M, 0), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT) } },
{ "mov.w", SH_OP_MOV, OPCODE(2, N, M, 1), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT) } },
{ "mov.l", SH_OP_MOV, OPCODE(2, N, M, 2), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT) } },
{ "mov.b", SH_OP_MOV, OPCODE(6, N, M, 0), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_INDIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mov.w", SH_OP_MOV, OPCODE(6, N, M, 1), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_INDIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mov.l", SH_OP_MOV, OPCODE(6, N, M, 2), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_INDIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mov.b", SH_OP_MOV, OPCODE(2, N, M, 4), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) } },
{ "mov.w", SH_OP_MOV, OPCODE(2, N, M, 5), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) } },
{ "mov.l", SH_OP_MOV, OPCODE(2, N, M, 6), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) } },
{ "mov.b", SH_OP_MOV, OPCODE(6, N, M, 4), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_INDIRECT_I), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mov.w", SH_OP_MOV, OPCODE(6, N, M, 5), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_INDIRECT_I), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mov.l", SH_OP_MOV, OPCODE(6, N, M, 6), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_INDIRECT_I), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mov.b", SH_OP_MOV, OPCODE(8, 0, N, D), 0x00ff, SH_SCALING_B, { PARAM(R0, SH_REG_DIRECT), ADDR(NIB0, SH_REG_INDIRECT_DISP) } },
{ "mov.w", SH_OP_MOV, OPCODE(8, 1, N, D), 0x00ff, SH_SCALING_W, { PARAM(R0, SH_REG_DIRECT), ADDR(NIB0, SH_REG_INDIRECT_DISP) } },
{ "mov.l", SH_OP_MOV, OPCODE(1, N, M, D), 0x0fff, SH_SCALING_L, { /*dummy values*/ ADDR(NIB0, SH_REG_DIRECT), ADDR(NIB0, SH_REG_INDIRECT_DISP) } },
{ "mov", SH_OP_MOV, OPCODE(e, N, I, I), 0x0fff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_S), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.w", SH_OP_MOV, OPCODE(9, N, D, D), 0x0fff, SH_SCALING_W, { ADDR(NIB0, SH_PC_RELATIVE_DISP), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.l", SH_OP_MOV, OPCODE(d, N, D, D), 0x0fff, SH_SCALING_L, { ADDR(NIB0, SH_PC_RELATIVE_DISP), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov", SH_OP_MOV, OPCODE(6, N, M, 3), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.b", SH_OP_MOV, OPCODE(2, N, M, 0), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT) }, SH_ARCH_COMMON },
{ "mov.w", SH_OP_MOV, OPCODE(2, N, M, 1), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT) }, SH_ARCH_COMMON },
{ "mov.l", SH_OP_MOV, OPCODE(2, N, M, 2), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT) }, SH_ARCH_COMMON },
{ "mov.b", SH_OP_MOV, OPCODE(6, N, M, 0), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_INDIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.w", SH_OP_MOV, OPCODE(6, N, M, 1), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_INDIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.l", SH_OP_MOV, OPCODE(6, N, M, 2), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_INDIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.b", SH_OP_MOV, OPCODE(2, N, M, 4), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) }, SH_ARCH_COMMON },
{ "mov.w", SH_OP_MOV, OPCODE(2, N, M, 5), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) }, SH_ARCH_COMMON },
{ "mov.l", SH_OP_MOV, OPCODE(2, N, M, 6), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) }, SH_ARCH_COMMON },
{ "mov.b", SH_OP_MOV, OPCODE(6, N, M, 4), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_INDIRECT_I), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.w", SH_OP_MOV, OPCODE(6, N, M, 5), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_INDIRECT_I), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.l", SH_OP_MOV, OPCODE(6, N, M, 6), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_INDIRECT_I), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.b", SH_OP_MOV, OPCODE(8, 0, N, D), 0x00ff, SH_SCALING_B, { PARAM(R0, SH_REG_DIRECT), ADDR(NIB0, SH_REG_INDIRECT_DISP) }, SH_ARCH_COMMON },
{ "mov.w", SH_OP_MOV, OPCODE(8, 1, N, D), 0x00ff, SH_SCALING_W, { PARAM(R0, SH_REG_DIRECT), ADDR(NIB0, SH_REG_INDIRECT_DISP) }, SH_ARCH_COMMON },
{ "mov.l", SH_OP_MOV, OPCODE(1, N, M, D), 0x0fff, SH_SCALING_L, { /*dummy values*/ ADDR(NIB0, SH_REG_DIRECT), ADDR(NIB0, SH_REG_INDIRECT_DISP) }, SH_ARCH_COMMON },
// ^ Just this instruction is kinda weird, so needs to be taken care of specially
{ "mov.b", SH_OP_MOV, OPCODE(8, 4, M, D), 0x00ff, SH_SCALING_B, { ADDR(NIB0, SH_REG_INDIRECT_DISP), PARAM(R0, SH_REG_DIRECT) } },
{ "mov.w", SH_OP_MOV, OPCODE(8, 5, M, D), 0x00ff, SH_SCALING_W, { ADDR(NIB0, SH_REG_INDIRECT_DISP), PARAM(R0, SH_REG_DIRECT) } },
{ "mov.l", SH_OP_MOV, OPCODE(5, N, M, D), 0x0fff, SH_SCALING_L, { ADDR(NIB0, SH_REG_INDIRECT_DISP), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mov.b", SH_OP_MOV, OPCODE(0, N, M, 4), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_INDEXED) } },
{ "mov.w", SH_OP_MOV, OPCODE(0, N, M, 5), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_INDEXED) } },
{ "mov.l", SH_OP_MOV, OPCODE(0, N, M, 6), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_INDEXED) } },
{ "mov.b", SH_OP_MOV, OPCODE(0, N, M, c), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_INDIRECT_INDEXED), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mov.w", SH_OP_MOV, OPCODE(0, N, M, d), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_INDIRECT_INDEXED), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mov.l", SH_OP_MOV, OPCODE(0, N, M, e), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_INDIRECT_INDEXED), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mov.b", SH_OP_MOV, OPCODE(c, 0, D, D), 0x00ff, SH_SCALING_B, { PARAM(R0, SH_REG_DIRECT), ADDR(NIB0, SH_GBR_INDIRECT_DISP) } },
{ "mov.w", SH_OP_MOV, OPCODE(c, 1, D, D), 0x00ff, SH_SCALING_W, { PARAM(R0, SH_REG_DIRECT), ADDR(NIB0, SH_GBR_INDIRECT_DISP) } },
{ "mov.l", SH_OP_MOV, OPCODE(c, 2, D, D), 0x00ff, SH_SCALING_L, { PARAM(R0, SH_REG_DIRECT), ADDR(NIB0, SH_GBR_INDIRECT_DISP) } },
{ "mov.b", SH_OP_MOV, OPCODE(c, 4, D, D), 0x00ff, SH_SCALING_B, { ADDR(NIB0, SH_GBR_INDIRECT_DISP), PARAM(R0, SH_REG_DIRECT) } },
{ "mov.w", SH_OP_MOV, OPCODE(c, 5, D, D), 0x00ff, SH_SCALING_W, { ADDR(NIB0, SH_GBR_INDIRECT_DISP), PARAM(R0, SH_REG_DIRECT) } },
{ "mov.l", SH_OP_MOV, OPCODE(c, 6, D, D), 0x00ff, SH_SCALING_L, { ADDR(NIB0, SH_GBR_INDIRECT_DISP), PARAM(R0, SH_REG_DIRECT) } },
{ "mova", SH_OP_MOV, OPCODE(c, 7, D, D), 0x00ff, SH_SCALING_L, { ADDR(NIB0, SH_PC_RELATIVE_DISP), PARAM(R0, SH_REG_DIRECT) } },
{ "movt", SH_OP_MOVT, OPCODE(0, N, 2, 9), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "swap.b", SH_OP_SWAP, OPCODE(6, N, M, 8), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "swap.w", SH_OP_SWAP, OPCODE(6, N, M, 9), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "xtrct", SH_OP_XTRCT, OPCODE(2, N, M, d), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mov.b", SH_OP_MOV, OPCODE(8, 4, M, D), 0x00ff, SH_SCALING_B, { ADDR(NIB0, SH_REG_INDIRECT_DISP), PARAM(R0, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.w", SH_OP_MOV, OPCODE(8, 5, M, D), 0x00ff, SH_SCALING_W, { ADDR(NIB0, SH_REG_INDIRECT_DISP), PARAM(R0, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.l", SH_OP_MOV, OPCODE(5, N, M, D), 0x0fff, SH_SCALING_L, { ADDR(NIB0, SH_REG_INDIRECT_DISP), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.b", SH_OP_MOV, OPCODE(0, N, M, 4), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_INDEXED) }, SH_ARCH_COMMON },
{ "mov.w", SH_OP_MOV, OPCODE(0, N, M, 5), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_INDEXED) }, SH_ARCH_COMMON },
{ "mov.l", SH_OP_MOV, OPCODE(0, N, M, 6), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_INDEXED) }, SH_ARCH_COMMON },
{ "mov.b", SH_OP_MOV, OPCODE(0, N, M, c), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_INDIRECT_INDEXED), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.w", SH_OP_MOV, OPCODE(0, N, M, d), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_INDIRECT_INDEXED), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.l", SH_OP_MOV, OPCODE(0, N, M, e), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_INDIRECT_INDEXED), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.b", SH_OP_MOV, OPCODE(c, 0, D, D), 0x00ff, SH_SCALING_B, { PARAM(R0, SH_REG_DIRECT), ADDR(NIB0, SH_GBR_INDIRECT_DISP) }, SH_ARCH_COMMON },
{ "mov.w", SH_OP_MOV, OPCODE(c, 1, D, D), 0x00ff, SH_SCALING_W, { PARAM(R0, SH_REG_DIRECT), ADDR(NIB0, SH_GBR_INDIRECT_DISP) }, SH_ARCH_COMMON },
{ "mov.l", SH_OP_MOV, OPCODE(c, 2, D, D), 0x00ff, SH_SCALING_L, { PARAM(R0, SH_REG_DIRECT), ADDR(NIB0, SH_GBR_INDIRECT_DISP) }, SH_ARCH_COMMON },
{ "mov.b", SH_OP_MOV, OPCODE(c, 4, D, D), 0x00ff, SH_SCALING_B, { ADDR(NIB0, SH_GBR_INDIRECT_DISP), PARAM(R0, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.w", SH_OP_MOV, OPCODE(c, 5, D, D), 0x00ff, SH_SCALING_W, { ADDR(NIB0, SH_GBR_INDIRECT_DISP), PARAM(R0, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mov.l", SH_OP_MOV, OPCODE(c, 6, D, D), 0x00ff, SH_SCALING_L, { ADDR(NIB0, SH_GBR_INDIRECT_DISP), PARAM(R0, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mova", SH_OP_MOV, OPCODE(c, 7, D, D), 0x00ff, SH_SCALING_L, { ADDR(NIB0, SH_PC_RELATIVE_DISP), PARAM(R0, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "movt", SH_OP_MOVT, OPCODE(0, N, 2, 9), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "swap.b", SH_OP_SWAP, OPCODE(6, N, M, 8), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "swap.w", SH_OP_SWAP, OPCODE(6, N, M, 9), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "xtrct", SH_OP_XTRCT, OPCODE(2, N, M, d), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
/* arithmetic operation instructions */
{ "add", SH_OP_ADD, OPCODE(3, N, M, c), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "add", SH_OP_ADD, OPCODE(7, N, I, I), 0x0fff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_S), ADDR(NIB2, SH_REG_DIRECT) } },
{ "addc", SH_OP_ADDC, OPCODE(3, N, M, e), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "addv", SH_OP_ADDV, OPCODE(3, N, M, f), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "cmp/eq", SH_OP_CMP_EQ, OPCODE(8, 8, I, I), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_S), PARAM(R0, SH_REG_DIRECT) } },
{ "cmp/eq", SH_OP_CMP_EQ, OPCODE(3, N, M, 0), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "cmp/hs", SH_OP_CMP_HS, OPCODE(3, N, M, 2), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "cmp/ge", SH_OP_CMP_GE, OPCODE(3, N, M, 3), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "cmp/hi", SH_OP_CMP_HI, OPCODE(3, N, M, 6), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "cmp/gt", SH_OP_CMP_GT, OPCODE(3, N, M, 7), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "cmp/pz", SH_OP_CMP_PZ, OPCODE(4, N, 1, 1), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "cmp/pl", SH_OP_CMP_PL, OPCODE(4, N, 1, 5), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "cmp/str", SH_OP_CMP_STR, OPCODE(2, N, M, c), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "div1", SH_OP_DIV1, OPCODE(3, N, M, 4), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "div0s", SH_OP_DIV0S, OPCODE(2, N, M, 7), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "div0u", SH_OP_DIV0U, OPCODE(0, 0, 1, 9), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM } },
{ "dmuls.l", SH_OP_DMULS, OPCODE(3, N, M, d), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "dmulu.l", SH_OP_DMULU, OPCODE(3, N, M, 5), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "dt", SH_OP_DT, OPCODE(4, N, 1, 0), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "exts.b", SH_OP_EXTS, OPCODE(6, N, M, e), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "exts.w", SH_OP_EXTS, OPCODE(6, N, M, f), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "extu.b", SH_OP_EXTU, OPCODE(6, N, M, c), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "extu.w", SH_OP_EXTU, OPCODE(6, N, M, d), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mac.l", SH_OP_MAC, OPCODE(0, N, M, f), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_INDIRECT_I), ADDR(NIB2, SH_REG_INDIRECT_I) } },
{ "mac.w", SH_OP_MAC, OPCODE(4, N, M, f), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_INDIRECT_I), ADDR(NIB2, SH_REG_INDIRECT_I) } },
{ "mul.l", SH_OP_MUL, OPCODE(0, N, M, 7), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "muls.w", SH_OP_MULS, OPCODE(2, N, M, f), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "mulu.w", SH_OP_MULU, OPCODE(2, N, M, e), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "neg", SH_OP_NEG, OPCODE(6, N, M, b), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "negc", SH_OP_NEGC, OPCODE(6, N, M, a), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "sub", SH_OP_SUB, OPCODE(3, N, M, 8), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "subc", SH_OP_SUBC, OPCODE(3, N, M, a), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "subv", SH_OP_SUBV, OPCODE(3, N, M, b), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "add", SH_OP_ADD, OPCODE(3, N, M, c), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "add", SH_OP_ADD, OPCODE(7, N, I, I), 0x0fff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_S), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "addc", SH_OP_ADDC, OPCODE(3, N, M, e), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "addv", SH_OP_ADDV, OPCODE(3, N, M, f), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "cmp/eq", SH_OP_CMP_EQ, OPCODE(8, 8, I, I), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_S), PARAM(R0, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "cmp/eq", SH_OP_CMP_EQ, OPCODE(3, N, M, 0), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "cmp/hs", SH_OP_CMP_HS, OPCODE(3, N, M, 2), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "cmp/ge", SH_OP_CMP_GE, OPCODE(3, N, M, 3), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "cmp/hi", SH_OP_CMP_HI, OPCODE(3, N, M, 6), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "cmp/gt", SH_OP_CMP_GT, OPCODE(3, N, M, 7), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "cmp/pz", SH_OP_CMP_PZ, OPCODE(4, N, 1, 1), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "cmp/pl", SH_OP_CMP_PL, OPCODE(4, N, 1, 5), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "cmp/str", SH_OP_CMP_STR, OPCODE(2, N, M, c), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "div1", SH_OP_DIV1, OPCODE(3, N, M, 4), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "div0s", SH_OP_DIV0S, OPCODE(2, N, M, 7), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "div0u", SH_OP_DIV0U, OPCODE(0, 0, 1, 9), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM }, SH_ARCH_COMMON },
{ "dmuls.l", SH_OP_DMULS, OPCODE(3, N, M, d), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "dmulu.l", SH_OP_DMULU, OPCODE(3, N, M, 5), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "dt", SH_OP_DT, OPCODE(4, N, 1, 0), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "exts.b", SH_OP_EXTS, OPCODE(6, N, M, e), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "exts.w", SH_OP_EXTS, OPCODE(6, N, M, f), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "extu.b", SH_OP_EXTU, OPCODE(6, N, M, c), 0x0ff0, SH_SCALING_B, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "extu.w", SH_OP_EXTU, OPCODE(6, N, M, d), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mac.l", SH_OP_MAC, OPCODE(0, N, M, f), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_INDIRECT_I), ADDR(NIB2, SH_REG_INDIRECT_I) }, SH_ARCH_COMMON },
{ "mac.w", SH_OP_MAC, OPCODE(4, N, M, f), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_INDIRECT_I), ADDR(NIB2, SH_REG_INDIRECT_I) }, SH_ARCH_COMMON },
{ "mul.l", SH_OP_MUL, OPCODE(0, N, M, 7), 0x0ff0, SH_SCALING_L, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "muls.w", SH_OP_MULS, OPCODE(2, N, M, f), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "mulu.w", SH_OP_MULU, OPCODE(2, N, M, e), 0x0ff0, SH_SCALING_W, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "neg", SH_OP_NEG, OPCODE(6, N, M, b), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "negc", SH_OP_NEGC, OPCODE(6, N, M, a), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "sub", SH_OP_SUB, OPCODE(3, N, M, 8), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "subc", SH_OP_SUBC, OPCODE(3, N, M, a), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "subv", SH_OP_SUBV, OPCODE(3, N, M, b), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
/* logic operation instructions */
{ "and", SH_OP_AND, OPCODE(2, N, M, 9), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "and", SH_OP_AND, OPCODE(c, 9, I, I), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_REG_DIRECT) } },
{ "and.b", SH_OP_AND, OPCODE(c, d, I, I), 0x00ff, SH_SCALING_B, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_GBR_INDIRECT_INDEXED) } },
{ "not", SH_OP_NOT, OPCODE(6, N, M, 7), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "or", SH_OP_OR, OPCODE(2, N, M, b), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "or", SH_OP_OR, OPCODE(c, b, I, I), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_REG_DIRECT) } },
{ "or.b", SH_OP_OR, OPCODE(c, f, I, I), 0x00ff, SH_SCALING_B, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_GBR_INDIRECT_INDEXED) } },
{ "tas.b", SH_OP_TAS, OPCODE(4, N, 1, b), 0x0f00, SH_SCALING_B, { ADDR(NIB2, SH_REG_INDIRECT), NOPARAM } },
{ "tst", SH_OP_TST, OPCODE(2, N, M, 8), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "tst", SH_OP_TST, OPCODE(c, 8, I, I), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_REG_DIRECT) } },
{ "tst.b", SH_OP_TST, OPCODE(c, c, I, I), 0x00ff, SH_SCALING_B, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_GBR_INDIRECT_INDEXED) } },
{ "xor", SH_OP_XOR, OPCODE(2, N, M, a), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "xor", SH_OP_XOR, OPCODE(c, a, I, I), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_REG_DIRECT) } },
{ "xor.b", SH_OP_XOR, OPCODE(c, e, I, I), 0x00ff, SH_SCALING_B, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_GBR_INDIRECT_INDEXED) } },
{ "and", SH_OP_AND, OPCODE(2, N, M, 9), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "and", SH_OP_AND, OPCODE(c, 9, I, I), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "and.b", SH_OP_AND, OPCODE(c, d, I, I), 0x00ff, SH_SCALING_B, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_GBR_INDIRECT_INDEXED) }, SH_ARCH_COMMON },
{ "not", SH_OP_NOT, OPCODE(6, N, M, 7), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "or", SH_OP_OR, OPCODE(2, N, M, b), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "or", SH_OP_OR, OPCODE(c, b, I, I), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "or.b", SH_OP_OR, OPCODE(c, f, I, I), 0x00ff, SH_SCALING_B, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_GBR_INDIRECT_INDEXED) }, SH_ARCH_COMMON },
{ "tas.b", SH_OP_TAS, OPCODE(4, N, 1, b), 0x0f00, SH_SCALING_B, { ADDR(NIB2, SH_REG_INDIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "tst", SH_OP_TST, OPCODE(2, N, M, 8), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "tst", SH_OP_TST, OPCODE(c, 8, I, I), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "tst.b", SH_OP_TST, OPCODE(c, c, I, I), 0x00ff, SH_SCALING_B, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_GBR_INDIRECT_INDEXED) }, SH_ARCH_COMMON },
{ "xor", SH_OP_XOR, OPCODE(2, N, M, a), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "xor", SH_OP_XOR, OPCODE(c, a, I, I), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "xor.b", SH_OP_XOR, OPCODE(c, e, I, I), 0x00ff, SH_SCALING_B, { ADDR(NIB0, SH_IMM_U), PARAM(R0, SH_GBR_INDIRECT_INDEXED) }, SH_ARCH_COMMON },
/* shift instructions */
{ "rotl", SH_OP_ROTL, OPCODE(4, N, 0, 4), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "rotr", SH_OP_ROTR, OPCODE(4, N, 0, 5), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "rotcl", SH_OP_ROTCL, OPCODE(4, N, 2, 4), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "rotcr", SH_OP_ROTCR, OPCODE(4, N, 2, 5), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "shad", SH_OP_SHAD, OPCODE(4, N, M, c), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "shal", SH_OP_SHAL, OPCODE(4, N, 2, 0), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "shar", SH_OP_SHAR, OPCODE(4, N, 2, 1), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "shld", SH_OP_SHLD, OPCODE(4, N, M, d), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "shll", SH_OP_SHLL, OPCODE(4, N, 0, 0), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "shlr", SH_OP_SHLR, OPCODE(4, N, 0, 1), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "shll2", SH_OP_SHLL2, OPCODE(4, N, 0, 8), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "shlr2", SH_OP_SHLR2, OPCODE(4, N, 0, 9), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "shll8", SH_OP_SHLL8, OPCODE(4, N, 1, 8), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "shlr8", SH_OP_SHLR8, OPCODE(4, N, 1, 9), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "shll16", SH_OP_SHLL16, OPCODE(4, N, 2, 8), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "shlr16", SH_OP_SHLR16, OPCODE(4, N, 2, 9), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM } },
{ "rotl", SH_OP_ROTL, OPCODE(4, N, 0, 4), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "rotr", SH_OP_ROTR, OPCODE(4, N, 0, 5), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "rotcl", SH_OP_ROTCL, OPCODE(4, N, 2, 4), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "rotcr", SH_OP_ROTCR, OPCODE(4, N, 2, 5), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "shad", SH_OP_SHAD, OPCODE(4, N, M, c), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "shal", SH_OP_SHAL, OPCODE(4, N, 2, 0), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "shar", SH_OP_SHAR, OPCODE(4, N, 2, 1), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "shld", SH_OP_SHLD, OPCODE(4, N, M, d), 0x0ff0, SH_SCALING_INVALID, { ADDR(NIB1, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "shll", SH_OP_SHLL, OPCODE(4, N, 0, 0), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "shlr", SH_OP_SHLR, OPCODE(4, N, 0, 1), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "shll2", SH_OP_SHLL2, OPCODE(4, N, 0, 8), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "shlr2", SH_OP_SHLR2, OPCODE(4, N, 0, 9), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "shll8", SH_OP_SHLL8, OPCODE(4, N, 1, 8), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "shlr8", SH_OP_SHLR8, OPCODE(4, N, 1, 9), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "shll16", SH_OP_SHLL16, OPCODE(4, N, 2, 8), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "shlr16", SH_OP_SHLR16, OPCODE(4, N, 2, 9), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), NOPARAM }, SH_ARCH_COMMON },
/* branch instructions */
{ "bf", SH_OP_BF, OPCODE(8, b, D, D), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_PC_RELATIVE8), NOPARAM } },
{ "bf/s", SH_OP_BFS, OPCODE(8, f, D, D), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_PC_RELATIVE8), NOPARAM } },
{ "bt", SH_OP_BT, OPCODE(8, 9, D, D), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_PC_RELATIVE8), NOPARAM } },
{ "bt/s", SH_OP_BTS, OPCODE(8, d, D, D), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_PC_RELATIVE8), NOPARAM } },
{ "bra", SH_OP_BRA, OPCODE(a, D, D, D), 0x0fff, SH_SCALING_INVALID, { ADDR(NIB0, SH_PC_RELATIVE12), NOPARAM } },
{ "braf", SH_OP_BRAF, OPCODE(0, N, 2, 3), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_PC_RELATIVE_REG), NOPARAM } },
{ "bsr", SH_OP_BSR, OPCODE(b, D, D, D), 0x0fff, SH_SCALING_INVALID, { ADDR(NIB0, SH_PC_RELATIVE12), NOPARAM } },
{ "bsrf", SH_OP_BSRF, OPCODE(0, N, 0, 3), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_PC_RELATIVE_REG), NOPARAM } },
{ "jmp", SH_OP_JMP, OPCODE(4, N, 2, b), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_INDIRECT), NOPARAM } },
{ "jsr", SH_OP_JSR, OPCODE(4, N, 0, b), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_INDIRECT), NOPARAM } },
{ "rts", SH_OP_RTS, OPCODE(0, 0, 0, b), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM } },
{ "bf", SH_OP_BF, OPCODE(8, b, D, D), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_PC_RELATIVE8), NOPARAM }, SH_ARCH_COMMON },
{ "bf/s", SH_OP_BFS, OPCODE(8, f, D, D), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_PC_RELATIVE8), NOPARAM }, SH_ARCH_COMMON },
{ "bt", SH_OP_BT, OPCODE(8, 9, D, D), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_PC_RELATIVE8), NOPARAM }, SH_ARCH_COMMON },
{ "bt/s", SH_OP_BTS, OPCODE(8, d, D, D), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_PC_RELATIVE8), NOPARAM }, SH_ARCH_COMMON },
{ "bra", SH_OP_BRA, OPCODE(a, D, D, D), 0x0fff, SH_SCALING_INVALID, { ADDR(NIB0, SH_PC_RELATIVE12), NOPARAM }, SH_ARCH_COMMON },
{ "braf", SH_OP_BRAF, OPCODE(0, N, 2, 3), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_PC_RELATIVE_REG), NOPARAM }, SH_ARCH_COMMON },
{ "bsr", SH_OP_BSR, OPCODE(b, D, D, D), 0x0fff, SH_SCALING_INVALID, { ADDR(NIB0, SH_PC_RELATIVE12), NOPARAM }, SH_ARCH_COMMON },
{ "bsrf", SH_OP_BSRF, OPCODE(0, N, 0, 3), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_PC_RELATIVE_REG), NOPARAM }, SH_ARCH_COMMON },
{ "jmp", SH_OP_JMP, OPCODE(4, N, 2, b), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_INDIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "jsr", SH_OP_JSR, OPCODE(4, N, 0, b), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_INDIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "rts", SH_OP_RTS, OPCODE(0, 0, 0, b), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM }, SH_ARCH_COMMON },
/* system control instructions */
{ "clrmac", SH_OP_CLRMAC, OPCODE(0, 0, 2, 8), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM } },
{ "clrs", SH_OP_CLRS, OPCODE(0, 0, 4, 8), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM } },
{ "clrt", SH_OP_CLRT, OPCODE(0, 0, 0, 8), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM } },
{ "ldc", SH_OP_LDC, OPCODE(4, M, 0, e), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(SR, SH_REG_DIRECT) } },
{ "ldc", SH_OP_LDC, OPCODE(4, M, 1, e), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(GBR, SH_REG_DIRECT) } },
{ "ldc", SH_OP_LDC, OPCODE(4, M, 2, e), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(VBR, SH_REG_DIRECT) } },
{ "ldc", SH_OP_LDC, OPCODE(4, M, 3, e), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(SSR, SH_REG_DIRECT) } },
{ "ldc", SH_OP_LDC, OPCODE(4, M, 4, e), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(SPC, SH_REG_DIRECT) } },
{ "ldc", SH_OP_LDC, OPCODE(4, M, f, a), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(DBR, SH_REG_DIRECT) } },
{ "ldc", SH_OP_LDC, OPCODE(4, M, N, e), 0x0f70, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), ADDRBITS(NIB1, SH_REG_DIRECT, 3) } },
{ "ldc.l", SH_OP_LDC, OPCODE(4, M, 0, 7), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(SR, SH_REG_DIRECT) } },
{ "ldc.l", SH_OP_LDC, OPCODE(4, M, 1, 7), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(GBR, SH_REG_DIRECT) } },
{ "ldc.l", SH_OP_LDC, OPCODE(4, M, 2, 7), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(VBR, SH_REG_DIRECT) } },
{ "ldc.l", SH_OP_LDC, OPCODE(4, M, 3, 7), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(SSR, SH_REG_DIRECT) } },
{ "ldc.l", SH_OP_LDC, OPCODE(4, M, 4, 7), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(SPC, SH_REG_DIRECT) } },
{ "ldc.l", SH_OP_LDC, OPCODE(4, M, f, 6), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(DBR, SH_REG_DIRECT) } },
{ "ldc.l", SH_OP_LDC, OPCODE(4, M, N, 7), 0x0f70, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), ADDRBITS(NIB1, SH_REG_DIRECT, 3) } },
{ "lds", SH_OP_LDS, OPCODE(4, M, 0, a), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(MACH, SH_REG_DIRECT) } },
{ "lds", SH_OP_LDS, OPCODE(4, M, 1, a), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(MACL, SH_REG_DIRECT) } },
{ "lds", SH_OP_LDS, OPCODE(4, M, 2, a), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(PR, SH_REG_DIRECT) } },
{ "lds.l", SH_OP_LDS, OPCODE(4, M, 0, 6), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(MACH, SH_REG_DIRECT) } },
{ "lds.l", SH_OP_LDS, OPCODE(4, M, 1, 6), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(MACL, SH_REG_DIRECT) } },
{ "lds.l", SH_OP_LDS, OPCODE(4, M, 2, 6), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(PR, SH_REG_DIRECT) } },
{ "ldtlb", SH_OP_UNIMPL, OPCODE(0, 0, 3, 8), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM } },
{ "movca.l", SH_OP_MOVCA, OPCODE(0, N, c, 3), 0x0f00, SH_SCALING_L, { PARAM(R0, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT) } },
{ "nop", SH_OP_NOP, OPCODE(0, 0, 0, 9), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM } },
{ "ocbi", SH_OP_UNIMPL, OPCODE(0, N, 9, 3), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_INDIRECT), NOPARAM } },
{ "ocbp", SH_OP_UNIMPL, OPCODE(0, N, a, 3), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_INDIRECT), NOPARAM } },
{ "ocbwb", SH_OP_UNIMPL, OPCODE(0, N, b, 3), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_INDIRECT), NOPARAM } },
{ "pref", SH_OP_UNIMPL, OPCODE(0, N, 8, 3), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_INDIRECT), NOPARAM } },
{ "rte", SH_OP_RTE, OPCODE(0, 0, 2, b), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM } },
{ "sets", SH_OP_SETS, OPCODE(0, 0, 5, 8), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM } },
{ "sett", SH_OP_SETT, OPCODE(0, 0, 1, 8), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM } },
{ "sleep", SH_OP_SLEEP, OPCODE(0, 0, 1, b), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM } },
{ "stc", SH_OP_STC, OPCODE(0, M, 0, 2), 0x0f00, SH_SCALING_INVALID, { PARAM(SR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "stc", SH_OP_STC, OPCODE(0, M, 1, 2), 0x0f00, SH_SCALING_INVALID, { PARAM(GBR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "stc", SH_OP_STC, OPCODE(0, M, 2, 2), 0x0f00, SH_SCALING_INVALID, { PARAM(VBR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "stc", SH_OP_STC, OPCODE(0, M, 3, 2), 0x0f00, SH_SCALING_INVALID, { PARAM(SSR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "stc", SH_OP_STC, OPCODE(0, M, 4, 2), 0x0f00, SH_SCALING_INVALID, { PARAM(SPC, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "stc", SH_OP_STC, OPCODE(0, M, 3, a), 0x0f00, SH_SCALING_INVALID, { PARAM(SGR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "stc", SH_OP_STC, OPCODE(0, M, f, a), 0x0f00, SH_SCALING_INVALID, { PARAM(DBR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "stc", SH_OP_STC, OPCODE(0, N, M, 2), 0x0f70, SH_SCALING_INVALID, { ADDRBITS(NIB1, SH_REG_DIRECT, 3), ADDR(NIB2, SH_REG_DIRECT) } },
{ "stc.l", SH_OP_STC, OPCODE(4, M, 0, 3), 0x0f00, SH_SCALING_L, { PARAM(SR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) } },
{ "stc.l", SH_OP_STC, OPCODE(4, M, 1, 3), 0x0f00, SH_SCALING_L, { PARAM(GBR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) } },
{ "stc.l", SH_OP_STC, OPCODE(4, M, 2, 3), 0x0f00, SH_SCALING_L, { PARAM(VBR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) } },
{ "stc.l", SH_OP_STC, OPCODE(4, M, 3, 3), 0x0f00, SH_SCALING_L, { PARAM(SSR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) } },
{ "stc.l", SH_OP_STC, OPCODE(4, M, 4, 3), 0x0f00, SH_SCALING_L, { PARAM(SPC, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) } },
{ "stc.l", SH_OP_STC, OPCODE(4, M, 3, 2), 0x0f00, SH_SCALING_L, { PARAM(SGR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) } },
{ "stc.l", SH_OP_STC, OPCODE(4, M, f, 2), 0x0f00, SH_SCALING_L, { PARAM(DBR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) } },
{ "stc.l", SH_OP_STC, OPCODE(4, N, M, 3), 0x0f70, SH_SCALING_L, { ADDRBITS(NIB1, SH_REG_DIRECT, 3), ADDR(NIB2, SH_REG_INDIRECT_D) } },
{ "sts", SH_OP_STS, OPCODE(0, N, 0, a), 0x0f00, SH_SCALING_INVALID, { PARAM(MACH, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "sts", SH_OP_STS, OPCODE(0, N, 1, a), 0x0f00, SH_SCALING_INVALID, { PARAM(MACL, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "sts", SH_OP_STS, OPCODE(0, N, 2, a), 0x0f00, SH_SCALING_INVALID, { PARAM(PR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) } },
{ "sts.l", SH_OP_STS, OPCODE(4, N, 0, 2), 0x0f00, SH_SCALING_L, { PARAM(MACH, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) } },
{ "sts.l", SH_OP_STS, OPCODE(4, N, 1, 2), 0x0f00, SH_SCALING_L, { PARAM(MACL, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) } },
{ "sts.l", SH_OP_STS, OPCODE(4, N, 2, 2), 0x0f00, SH_SCALING_L, { PARAM(PR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) } },
{ "trapa", SH_OP_UNIMPL, OPCODE(c, 3, I, I), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_U), NOPARAM } }
{ "clrmac", SH_OP_CLRMAC, OPCODE(0, 0, 2, 8), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM }, SH_ARCH_COMMON },
{ "clrs", SH_OP_CLRS, OPCODE(0, 0, 4, 8), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM }, SH_ARCH_COMMON },
{ "clrt", SH_OP_CLRT, OPCODE(0, 0, 0, 8), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM }, SH_ARCH_COMMON },
{ "ldc", SH_OP_LDC, OPCODE(4, M, 0, e), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(SR, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "ldc", SH_OP_LDC, OPCODE(4, M, 1, e), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(GBR, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "ldc", SH_OP_LDC, OPCODE(4, M, 2, e), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(VBR, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "ldc", SH_OP_LDC, OPCODE(4, M, 3, e), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(SSR, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "ldc", SH_OP_LDC, OPCODE(4, M, 4, e), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(SPC, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "ldc", SH_OP_LDC, OPCODE(4, M, f, a), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(DBR, SH_REG_DIRECT) }, SH_ARCH_SH4 },
{ "ldc", SH_OP_LDC, OPCODE(4, M, N, e), 0x0f70, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), ADDRBITS(NIB1, SH_REG_DIRECT, 3) }, SH_ARCH_COMMON },
{ "ldc.l", SH_OP_LDC, OPCODE(4, M, 0, 7), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(SR, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "ldc.l", SH_OP_LDC, OPCODE(4, M, 1, 7), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(GBR, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "ldc.l", SH_OP_LDC, OPCODE(4, M, 2, 7), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(VBR, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "ldc.l", SH_OP_LDC, OPCODE(4, M, 3, 7), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(SSR, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "ldc.l", SH_OP_LDC, OPCODE(4, M, 4, 7), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(SPC, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "ldc.l", SH_OP_LDC, OPCODE(4, M, f, 6), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(DBR, SH_REG_DIRECT) }, SH_ARCH_SH4 },
{ "ldc.l", SH_OP_LDC, OPCODE(4, M, N, 7), 0x0f70, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), ADDRBITS(NIB1, SH_REG_DIRECT, 3) }, SH_ARCH_COMMON },
{ "lds", SH_OP_LDS, OPCODE(4, M, 0, a), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(MACH, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "lds", SH_OP_LDS, OPCODE(4, M, 1, a), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(MACL, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "lds", SH_OP_LDS, OPCODE(4, M, 2, a), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_DIRECT), PARAM(PR, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "lds.l", SH_OP_LDS, OPCODE(4, M, 0, 6), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(MACH, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "lds.l", SH_OP_LDS, OPCODE(4, M, 1, 6), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(MACL, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "lds.l", SH_OP_LDS, OPCODE(4, M, 2, 6), 0x0f00, SH_SCALING_L, { ADDR(NIB2, SH_REG_INDIRECT_I), PARAM(PR, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "ldtlb", SH_OP_UNIMPL, OPCODE(0, 0, 3, 8), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM }, SH_ARCH_COMMON },
{ "movca.l", SH_OP_MOVCA, OPCODE(0, N, c, 3), 0x0f00, SH_SCALING_L, { PARAM(R0, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT) }, SH_ARCH_SH4 },
{ "nop", SH_OP_NOP, OPCODE(0, 0, 0, 9), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM }, SH_ARCH_COMMON },
{ "ocbi", SH_OP_UNIMPL, OPCODE(0, N, 9, 3), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_INDIRECT), NOPARAM }, SH_ARCH_SH4 },
{ "ocbp", SH_OP_UNIMPL, OPCODE(0, N, a, 3), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_INDIRECT), NOPARAM }, SH_ARCH_SH4 },
{ "ocbwb", SH_OP_UNIMPL, OPCODE(0, N, b, 3), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_INDIRECT), NOPARAM }, SH_ARCH_SH4 },
{ "pref", SH_OP_UNIMPL, OPCODE(0, N, 8, 3), 0x0f00, SH_SCALING_INVALID, { ADDR(NIB2, SH_REG_INDIRECT), NOPARAM }, SH_ARCH_COMMON },
{ "rte", SH_OP_RTE, OPCODE(0, 0, 2, b), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM }, SH_ARCH_COMMON },
{ "sets", SH_OP_SETS, OPCODE(0, 0, 5, 8), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM }, SH_ARCH_COMMON },
{ "sett", SH_OP_SETT, OPCODE(0, 0, 1, 8), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM }, SH_ARCH_COMMON },
{ "sleep", SH_OP_SLEEP, OPCODE(0, 0, 1, b), 0x0000, SH_SCALING_INVALID, { NOPARAM, NOPARAM }, SH_ARCH_COMMON },
{ "stc", SH_OP_STC, OPCODE(0, M, 0, 2), 0x0f00, SH_SCALING_INVALID, { PARAM(SR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "stc", SH_OP_STC, OPCODE(0, M, 1, 2), 0x0f00, SH_SCALING_INVALID, { PARAM(GBR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "stc", SH_OP_STC, OPCODE(0, M, 2, 2), 0x0f00, SH_SCALING_INVALID, { PARAM(VBR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "stc", SH_OP_STC, OPCODE(0, M, 3, 2), 0x0f00, SH_SCALING_INVALID, { PARAM(SSR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "stc", SH_OP_STC, OPCODE(0, M, 4, 2), 0x0f00, SH_SCALING_INVALID, { PARAM(SPC, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "stc", SH_OP_STC, OPCODE(0, M, 3, a), 0x0f00, SH_SCALING_INVALID, { PARAM(SGR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_SH4 },
{ "stc", SH_OP_STC, OPCODE(0, M, f, a), 0x0f00, SH_SCALING_INVALID, { PARAM(DBR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_SH4 },
{ "stc", SH_OP_STC, OPCODE(0, N, M, 2), 0x0f70, SH_SCALING_INVALID, { ADDRBITS(NIB1, SH_REG_DIRECT, 3), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "stc.l", SH_OP_STC, OPCODE(4, M, 0, 3), 0x0f00, SH_SCALING_L, { PARAM(SR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) }, SH_ARCH_COMMON },
{ "stc.l", SH_OP_STC, OPCODE(4, M, 1, 3), 0x0f00, SH_SCALING_L, { PARAM(GBR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) }, SH_ARCH_COMMON },
{ "stc.l", SH_OP_STC, OPCODE(4, M, 2, 3), 0x0f00, SH_SCALING_L, { PARAM(VBR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) }, SH_ARCH_COMMON },
{ "stc.l", SH_OP_STC, OPCODE(4, M, 3, 3), 0x0f00, SH_SCALING_L, { PARAM(SSR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) }, SH_ARCH_COMMON },
{ "stc.l", SH_OP_STC, OPCODE(4, M, 4, 3), 0x0f00, SH_SCALING_L, { PARAM(SPC, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) }, SH_ARCH_COMMON },
{ "stc.l", SH_OP_STC, OPCODE(4, M, 3, 2), 0x0f00, SH_SCALING_L, { PARAM(SGR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) }, SH_ARCH_SH4 },
{ "stc.l", SH_OP_STC, OPCODE(4, M, f, 2), 0x0f00, SH_SCALING_L, { PARAM(DBR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) }, SH_ARCH_SH4 },
{ "stc.l", SH_OP_STC, OPCODE(4, N, M, 3), 0x0f70, SH_SCALING_L, { ADDRBITS(NIB1, SH_REG_DIRECT, 3), ADDR(NIB2, SH_REG_INDIRECT_D) }, SH_ARCH_COMMON },
{ "sts", SH_OP_STS, OPCODE(0, N, 0, a), 0x0f00, SH_SCALING_INVALID, { PARAM(MACH, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "sts", SH_OP_STS, OPCODE(0, N, 1, a), 0x0f00, SH_SCALING_INVALID, { PARAM(MACL, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "sts", SH_OP_STS, OPCODE(0, N, 2, a), 0x0f00, SH_SCALING_INVALID, { PARAM(PR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_DIRECT) }, SH_ARCH_COMMON },
{ "sts.l", SH_OP_STS, OPCODE(4, N, 0, 2), 0x0f00, SH_SCALING_L, { PARAM(MACH, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) }, SH_ARCH_COMMON },
{ "sts.l", SH_OP_STS, OPCODE(4, N, 1, 2), 0x0f00, SH_SCALING_L, { PARAM(MACL, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) }, SH_ARCH_COMMON },
{ "sts.l", SH_OP_STS, OPCODE(4, N, 2, 2), 0x0f00, SH_SCALING_L, { PARAM(PR, SH_REG_DIRECT), ADDR(NIB2, SH_REG_INDIRECT_D) }, SH_ARCH_COMMON },
{ "trapa", SH_OP_UNIMPL, OPCODE(c, 3, I, I), 0x00ff, SH_SCALING_INVALID, { ADDR(NIB0, SH_IMM_U), NOPARAM }, SH_ARCH_COMMON }
/* floating-point single-precision instructions */
// TODO

View file

@ -382,7 +382,9 @@ static SHParamHelper sh_il_get_param_pc_ctx(SHParam param, SHScaling scaling, ut
ret.pure = UN(sh_scaling_size[scaling] * BITS_PER_BYTE, param.param[0]);
break;
case SH_IMM_S:
ret.pure = SN(sh_scaling_size[scaling] * BITS_PER_BYTE, param.param[0]);
// the immediate is an 8 bit field which must be sign-extended to the
// operation width (e.g. `add #imm, Rn` and `mov #imm, Rn`)
ret.pure = SN(sh_scaling_size[scaling] * BITS_PER_BYTE, (st8)param.param[0]);
break;
default:
RZ_LOG_ERROR("RzIL: SuperH: Invalid addressing mode\n");
@ -1353,7 +1355,8 @@ static RzILOpEffect *sh_il_shlr16(const SHOp *op, ut64 pc, RzAnalysis *analysis,
*/
static RzILOpEffect *sh_il_bf(const SHOp *op, ut64 pc, RzAnalysis *analysis, SHILContext *ctx) {
RzILOpPure *new_pc = sh_il_get_effective_addr_param(0);
return BRANCH(VARG(SH_SR_T), JMP(new_pc), NOP());
// BF branches when T = 0, so the jump is the false-branch of the condition
return BRANCH(VARG(SH_SR_T), NOP(), JMP(new_pc));
}
/**
@ -1364,7 +1367,8 @@ static RzILOpEffect *sh_il_bf(const SHOp *op, ut64 pc, RzAnalysis *analysis, SHI
*/
static RzILOpEffect *sh_il_bfs(const SHOp *op, ut64 pc, RzAnalysis *analysis, SHILContext *ctx) {
RzILOpPure *new_pc = sh_il_get_effective_addr_param(0);
return BRANCH(VARG(SH_SR_T), JMP(new_pc), NOP());
// BF/S branches when T = 0, so the jump is the false-branch of the condition
return BRANCH(VARG(SH_SR_T), NOP(), JMP(new_pc));
}
/**

View file

@ -1101,13 +1101,23 @@ static int sh_op(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *d
ret = first_nibble_decode[(op_MSB >> 4) & 0x0F](analysis, op, opcode);
// RzIL uplifting
SHOp *ilop = sh_disassembler(opcode);
SHILContext *ctx = RZ_NEW0(SHILContext);
ctx->use_banked = true;
SHCpu cpu = sh_cpu_by_name(rz_analysis_get_cpu(analysis));
SHOp *ilop = sh_disassembler(opcode, cpu);
if (ilop) {
SHILContext *ctx = RZ_NEW0(SHILContext);
ctx->use_banked = true;
rz_sh_il_opcode(analysis, op, addr, ilop, ctx);
RZ_FREE(ctx);
} else if (cpu != SH_CPU_SH4) {
// The instruction may belong to a more capable CPU (e.g. an
// SuperH-4 only instruction decoded while targeting SuperH-3).
// In that case it is illegal for the selected CPU.
SHOp *sh4op = sh_disassembler(opcode, SH_CPU_SH4);
if (sh4op) {
op->type = RZ_ANALYSIS_OP_TYPE_ILL;
RZ_FREE(sh4op);
}
}
RZ_FREE(ctx);
RZ_FREE(ilop);
return ret;
@ -1193,7 +1203,7 @@ static int sh_archinfo(RzAnalysis *a, RzAnalysisInfoType query) {
RzAnalysisPlugin rz_analysis_plugin_sh = {
.name = "sh",
.desc = "SH-4 code analysis plugin",
.desc = "SH-4/SH-3 code analysis plugin",
.license = "LGPL3",
.arch = "sh",
.archinfo = sh_archinfo,

View file

@ -10,7 +10,8 @@
#include "sh/assembler.h"
static int disassemble(const RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) {
SHOp *dis_op = sh_disassembler(rz_read_ble16(buf, a->big_endian));
SHCpu cpu = sh_cpu_by_name(a->cpu);
SHOp *dis_op = sh_disassembler(rz_read_ble16(buf, a->big_endian), cpu);
op->size = 2;
if (!dis_op) {
rz_strbuf_set(&op->buf_asm, "invalid");
@ -25,7 +26,8 @@ static int disassemble(const RzAsm *a, RzAsmOp *op, const ut8 *buf, int len) {
static int assemble(const RzAsm *a, RzAsmOp *ao, const char *str) {
bool success;
ut16 opcode = sh_assembler(str, a->pc, &success);
SHCpu cpu = sh_cpu_by_name(a->cpu);
ut16 opcode = sh_assembler(str, a->pc, &success, cpu);
if (!success) {
return -1;
}
@ -50,7 +52,8 @@ RzAsmPlugin rz_asm_plugin_sh = {
.license = "LGPL3",
.bits = 32,
.endian = RZ_SYS_ENDIAN_LITTLE | RZ_SYS_ENDIAN_BIG,
.desc = "Hitachi/Renesas SuperH-4 disassembler",
.cpus = "sh4,sh3",
.desc = "Hitachi/Renesas SuperH-4/SuperH-3 disassembler",
.disassemble = &disassemble,
.assemble = &assemble,
.sw_breakpoint = sh_sw_breakpoint,

67
test/db/analysis/sh3 Normal file
View file

@ -0,0 +1,67 @@
NAME=SuperH-3 asm.cpu disassembly and control flow
FILE=malloc://32
CMDS=<<EOF
e asm.arch=sh
e asm.bits=32
e cfg.bigendian=true
e asm.cpu=sh3
wx 8b10
ao~type
wx 402b @ 0
ao~type
wx 000b @ 0
ao~type
wx 01c30009421c402b000b @ 0
pd 5
EOF
EXPECT=<<EOF
type: cjmp
type: ujmp
type: ret
0x00000000 invalid
0x00000002 nop
0x00000004 shad r1, r2
0x00000006 jmp @r0
0x00000008 rts
EOF
RUN
NAME=SuperH-4 only instructions are illegal under SuperH-3
FILE=malloc://32
CMDS=<<EOF
e asm.arch=sh
e asm.bits=32
e cfg.bigendian=true
e asm.cpu=sh3
wx 01c3 @ 0
ao~type
wx 0293 @ 0
ao~type
wx 053a @ 0
ao~type
EOF
EXPECT=<<EOF
type: ill
type: ill
type: ill
EOF
RUN
NAME=SuperH-4 only instructions are valid under SuperH-4
FILE=malloc://32
CMDS=<<EOF
e asm.arch=sh
e asm.bits=32
e cfg.bigendian=true
e asm.cpu=sh4
wx 01c30009421c402b000b
pd 5
EOF
EXPECT=<<EOF
0x00000000 movca.l r0, @r1
0x00000002 nop
0x00000004 shad r1, r2
0x00000006 jmp @r0
0x00000008 rts
EOF
RUN

View file

@ -44,7 +44,7 @@ adE "add r0, r1" 310c 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (set _regv
adE "add 0x42, r9" 7942 0x0 (set r9 (+ (bv 32 0x42) (var r9)))
adE "addc r10, r11" 3bae 0x100 (seq (set sum (+ (+ (var r10) (var r11)) (cast 32 false (ite (var sr_t) (bv 32 0x1) (bv 32 0x0))))) (set sr_t (|| (|| (&& (msb (var r10)) (msb (var r11))) (&& (! (msb (var sum))) (msb (var r11)))) (&& (msb (var r10)) (! (msb (var sum)))))) (set r11 (var sum)))
adE "addv r1, r0" 301f 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (set sum (+ (ite (var _priv) (var r1b) (var r1)) (ite (var _priv) (var r0b) (var r0)))) (set sr_t (|| (&& (&& (! (msb (var sum))) (msb (ite (var _priv) (var r1b) (var r1)))) (msb (ite (var _priv) (var r0b) (var r0)))) (&& (&& (msb (var sum)) (! (msb (ite (var _priv) (var r1b) (var r1))))) (! (msb (ite (var _priv) (var r0b) (var r0))))))) (set _regv (var sum)) (branch (var _priv) (set r0b (var _regv)) (set r0 (var _regv))))
adE "cmp/eq 0x99, r0" 8899 0x10 (seq (set _priv (&& (var sr_d) (var sr_r))) (set sr_t (== (bv 32 0x99) (ite (var _priv) (var r0b) (var r0)))))
adE "cmp/eq 0x99, r0" 8899 0x10 (seq (set _priv (&& (var sr_d) (var sr_r))) (set sr_t (== (bv 32 0xffffff99) (ite (var _priv) (var r0b) (var r0)))))
adE "cmp/eq r9, r14" 3e90 0x0 (set sr_t (== (var r9) (var r14)))
adE "cmp/hs r13, r11" 3bd2 0x10 (set sr_t (|| (! (ule (var r11) (var r13))) (== (var r11) (var r13))))
adE "cmp/ge r1, r10" 3a13 0x44 (seq (set _priv (&& (var sr_d) (var sr_r))) (set sr_t (|| (! (sle (var r10) (ite (var _priv) (var r1b) (var r1)))) (== (var r10) (ite (var _priv) (var r1b) (var r1))))))
@ -108,8 +108,8 @@ adE "shll16 r13" 4d28 0x0 (set r13 (<< (var r13) (bv 32 0x10) false))
adE "shlr16 r13" 4d29 0x0 (set r13 (>> (var r13) (bv 32 0x10) false))
# Branch instructions
adE "bf 0x00000072" 8b27 0x20 (branch (var sr_t) (jmp (+ (+ (bv 32 0x20) (bv 32 0x4)) (<< (bv 32 0x27) (bv 32 0x1) false))) nop)
adE "bf/s 0x00000072" 8f27 0x20 (branch (var sr_t) (jmp (+ (+ (bv 32 0x20) (bv 32 0x4)) (<< (bv 32 0x27) (bv 32 0x1) false))) nop)
adE "bf 0x00000072" 8b27 0x20 (branch (var sr_t) nop (jmp (+ (+ (bv 32 0x20) (bv 32 0x4)) (<< (bv 32 0x27) (bv 32 0x1) false))))
adE "bf/s 0x00000072" 8f27 0x20 (branch (var sr_t) nop (jmp (+ (+ (bv 32 0x20) (bv 32 0x4)) (<< (bv 32 0x27) (bv 32 0x1) false))))
adE "bt 0x00000004" 8900 0x0 (branch (var sr_t) (jmp (+ (+ (bv 32 0x0) (bv 32 0x4)) (<< (bv 32 0x0) (bv 32 0x1) false))) nop)
adE "bt/s 0xd3adb008" 8dfe 0xd3adb008 (branch (var sr_t) (jmp (+ (+ (bv 32 0xd3adb008) (bv 32 0x4)) (<< (bv 32 0xfffffffe) (bv 32 0x1) false))) nop)
adE "bra 0x00000004" a000 0x0 (jmp (+ (+ (bv 32 0x0) (bv 32 0x4)) (<< (bv 32 0x0) (bv 32 0x1) false)))

40
test/db/asm/sh_sh3_32 Normal file
View file

@ -0,0 +1,40 @@
# SuperH-3 (asm.cpu=sh3)
# SuperH-4 only instructions must be rejected when targeting SuperH-3
dE "invalid" 01c3 # movca.l r0, @r1 (SH-4)
dE "invalid" 0293 # ocbi @r2 (SH-4)
dE "invalid" 03a3 # ocbp @r3 (SH-4)
dE "invalid" 04b3 # ocbwb @r4 (SH-4)
dE "invalid" 053a # stc sgr, r5 (SH-4)
dE "invalid" 06fa # stc dbr, r6 (SH-4)
dE "invalid" 47fa # ldc r7, dbr (SH-4)
dE "invalid" 4832 # stc.l sgr, @-r8 (SH-4)
dE "invalid" 49f2 # stc.l dbr, @-r9 (SH-4)
dE "invalid" 4af6 # ldc.l @r10+, dbr (SH-4)
# SuperH-3 specific instructions (shared with SuperH-4)
adE "shad r1, r2" 421c 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (set shift_ (cast 5 false (ite (var _priv) (var r1b) (var r1)))) (branch (|| (! (sle (ite (var _priv) (var r1b) (var r1)) (bv 32 0x0))) (== (ite (var _priv) (var r1b) (var r1)) (bv 32 0x0))) (seq (set _regv (<< (ite (var _priv) (var r2b) (var r2)) (var shift_) false)) (branch (var _priv) (set r2b (var _regv)) (set r2 (var _regv)))) (seq (set _regv (>> (ite (var _priv) (var r2b) (var r2)) (~- (var shift_)) (msb (ite (var _priv) (var r2b) (var r2))))) (branch (var _priv) (set r2b (var _regv)) (set r2 (var _regv))))))
adE "shld r3, r4" 443d 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (set shift_ (cast 5 false (ite (var _priv) (var r3b) (var r3)))) (branch (|| (! (sle (ite (var _priv) (var r3b) (var r3)) (bv 32 0x0))) (== (ite (var _priv) (var r3b) (var r3)) (bv 32 0x0))) (seq (set _regv (<< (ite (var _priv) (var r4b) (var r4)) (var shift_) false)) (branch (var _priv) (set r4b (var _regv)) (set r4 (var _regv)))) (seq (set _regv (>> (ite (var _priv) (var r4b) (var r4)) (~- (var shift_)) false)) (branch (var _priv) (set r4b (var _regv)) (set r4 (var _regv))))))
adE "clrs" 0048 0x0 (set sr_s false)
adE "sets" 0058 0x0 (set sr_s true)
adE "ldc r6, ssr" 463e 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (branch (var _priv) (set ssr (var r6)) empty))
adE "stc ssr, r7" 0732 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (branch (var _priv) (set r7 (var ssr)) empty))
adE "ldc r8, spc" 484e 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (branch (var _priv) (set spc (var r8)) empty))
adE "stc spc, r9" 0942 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (branch (var _priv) (set r9 (var spc)) empty))
adE "ldc r10, r0b" 4a8e 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (branch (var _priv) (set r0b (var r10)) empty))
adE "ldc.l @r10+, r0b" 4a87 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (branch (var _priv) (seq (set r0b (loadw 0 32 (var r10))) (set r10 (+ (var r10) (bv 32 0x4)))) empty))
adE "pref @r5" 0583 0x0
adE "ldtlb" 0038 0x0
# A sample of common instructions must keep working under SuperH-3
adE "nop" 0009 0x0 nop
adE "mov 0x27, r7" e727 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (set _regv (bv 32 0x27)) (branch (var _priv) (set r7b (var _regv)) (set r7 (var _regv))))
adE "add 0x01, r3" 7301 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (set _regv (+ (bv 32 0x1) (ite (var _priv) (var r3b) (var r3)))) (branch (var _priv) (set r3b (var _regv)) (set r3 (var _regv))))
adE "add r0, r0" 300c 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (set _regv (+ (ite (var _priv) (var r0b) (var r0)) (ite (var _priv) (var r0b) (var r0)))) (branch (var _priv) (set r0b (var _regv)) (set r0 (var _regv))))
adE "tst r0, r0" 2008 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (set sr_t (is_zero (& (ite (var _priv) (var r0b) (var r0)) (ite (var _priv) (var r0b) (var r0))))))
adE "bf 0x00000024" 8b10 0x0 (branch (var sr_t) nop (jmp (+ (+ (bv 32 0x0) (bv 32 0x4)) (<< (bv 32 0x10) (bv 32 0x1) false))))
adE "rts" 000b 0x0 (jmp (var pr))
adE "jmp @r0" 402b 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (jmp (ite (var _priv) (var r0b) (var r0))))
# 8 bit immediates of mov/add/cmp-eq are sign-extended in the IL
adE "mov 0xff, r0" e0ff 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (set _regv (bv 32 0xffffffff)) (branch (var _priv) (set r0b (var _regv)) (set r0 (var _regv))))
adE "add 0xc0, r5" 75c0 0x0 (seq (set _priv (&& (var sr_d) (var sr_r))) (set _regv (+ (bv 32 0xffffffc0) (ite (var _priv) (var r5b) (var r5)))) (branch (var _priv) (set r5b (var _regv)) (set r5 (var _regv))))

View file

@ -52,7 +52,7 @@ _dA__ 32 64 riscv BSD RISC-V Capstone-based disassembler
adA__ 32 rl78 LGPL3 Renesas RL78 disassembler (by Bastian Engel)
_dA__ 32 rsp LGPL3 Nintendo N64 Reality Signal Processor disassembler
_dA__ 32 rx LGPL3 Renesas RX Family disassembler (by Heersin)
adAeI 32 sh LGPL3 Hitachi/Renesas SuperH-4 disassembler (by DMaroo)
adAeI 32 sh LGPL3 Hitachi/Renesas SuperH-4/SuperH-3 disassembler (by DMaroo)
_dA__ 8 16 snes LGPL3 SuperNES CPU disassembler
_dA_I 32 64 sparc BSD Sun SPARC Capstone-based disassembler
_dA__ 16 spc700 LGPL3 Sony SPC700 (Nintendo SuperNES sound-chip) disassembler

File diff suppressed because one or more lines are too long

16
test/db/rzil/sh3 Normal file
View file

@ -0,0 +1,16 @@
NAME=Testing the decryption in emulateme (SuperH-3)
FILE=bins/sh/emulateme.sh3
TIMEOUT=30
CMDS=<<EOF
e asm.cpu=sh3
aaa
e io.cache=1
s entry0
aezi
aezsu 0x00400032
ps @ obj.seckrit
EOF
EXPECT=<<EOF
Hello from RzIL!
EOF
RUN