sh: superh support backend.

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
This commit is contained in:
Yoshinori Sato 2022-10-12 20:08:29 +09:00
parent 5b6846c2c8
commit b681153238
8 changed files with 3211 additions and 0 deletions

2231
arch/SH/SHDisassembler.c Normal file

File diff suppressed because it is too large Load Diff

19
arch/SH/SHDisassembler.h Normal file
View File

@ -0,0 +1,19 @@
/* Capstone Disassembly Engine */
/* By Nguyen Anh Quynh, 2018 */
#ifndef CS_SHDISASSEMBLER_H
#define CS_SHDISASSEMBLER_H
#include "../../MCInst.h"
typedef struct sh_info {
cs_sh op;
} sh_info;
bool SH_getInstruction(csh ud, const uint8_t *code, size_t code_len,
MCInst *instr, uint16_t *size, uint64_t address, void *info);
void SH_reg_access(const cs_insn *insn,
cs_regs regs_read, uint8_t *regs_read_count,
cs_regs regs_write, uint8_t *regs_write_count);
#endif

66
arch/SH/SHInsnTable.inc Normal file
View File

@ -0,0 +1,66 @@
bool (*decode[])(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, sh_info *info, cs_detail *detail) = {
/// 00000000
NULL, NULL, opSTC, op0xx3, opMOV_B, opMOV_W, opMOV_L, opMUL_L,
/// 00001000
op0xx8, op0xx9, op0xxa, op0xxb, opMOV_B, opMOV_W, opMOV_L, opMAC_L,
/// 00010000
opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp,
/// 00011000
opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp,
/// 00100000
opMOV_rind, opMOV_rind, opMOV_rind, NULL, opMOV_rpd, opMOV_rpd, opMOV_rpd, opDIV0S,
/// 00101000
opTST, opAND, opXOR, opOR, opCMP_STR, opXTRCT, opMULU_W, opMULS_W,
/// 00110000
opCMP_EQ, NULL, opCMP_HS, opCMP_GE, opDIV1, opDMULU_L, opCMP_HI, opCMP_GT,
/// 00111000
opSUB, NULL, opSUBC, opSUBV, opADD_r, opDMULS_L, opADDC, opADDV,
/// 01000000
op4xx0, op4xx1, op4xx2, opSTC_L, op4xx4, op4xx5, op4xx6, opLDC_L,
/// 01001000
op4xx8, op4xx9, op4xxa, op4xxb, opSHAD, opSHLD, opLDC, opMAC_W,
/// 01010000
opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp,
/// 01011000
opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp, opMOV_L_dsp,
/// 01100000
opMOV_rind, opMOV_rind, opMOV_rind, opMOV, opMOV_rpi, opMOV_rpi, opMOV_rpi, opNOT,
/// 01101000
opSWAP_B, opSWAP_W, opNEGC, opNEG, opEXTU_B, opEXTU_W, opEXTS_B, opEXTS_W,
/// 01110000
opADD_i, opADD_i, opADD_i, opADD_i, opADD_i, opADD_i, opADD_i, opADD_i,
/// 01111000
opADD_i, opADD_i, opADD_i, opADD_i, opADD_i, opADD_i, opADD_i, opADD_i,
/// 10000000
opMOV_BW_dsp, opMOV_BW_dsp, opSETRC, opJSR_N, opMOV_BW_dsp, opMOV_BW_dsp, op86xx, op87xx,
/// 10001000
opCMP_EQi, opBT, opLDRC, opBF, opLDRS, opBT_S, opLDRE, opBF_S,
/// 10010000
opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc,
/// 10011000
opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc,
/// 10100000
opBRA, opBRA, opBRA, opBRA, opBRA, opBRA, opBRA, opBRA,
/// 10101000
opBRA, opBRA, opBRA, opBRA, opBRA, opBRA, opBRA, opBRA,
/// 10110000
opBSR, opBSR, opBSR, opBSR, opBSR, opBSR, opBSR, opBSR,
/// 10111000
opBSR, opBSR, opBSR, opBSR, opBSR, opBSR, opBSR, opBSR,
/// 11000000
opMOV_gbr, opMOV_gbr, opMOV_gbr, opTRAPA, opMOV_gbr, opMOV_gbr, opMOV_gbr, opMOVA,
/// 11001000
opTST_i, opAND_i, opXOR_i, opOR_i, opTST_B, opAND_B, opXOR_B, opOR_B,
/// 11010000
opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc,
/// 11011000
opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc, opMOV_pc,
/// 11100000
opMOV_i, opMOV_i, opMOV_i, opMOV_i, opMOV_i, opMOV_i, opMOV_i, opMOV_i,
/// 11101000
opMOV_i, opMOV_i, opMOV_i, opMOV_i, opMOV_i, opMOV_i, opMOV_i, opMOV_i,
/// 11110000
opFADD, opFSUB, opFMUL, opFDIV, opFCMP_EQ, opFCMP_GT, opfxx6, opfxx7,
/// 11111000
opfxx8, opfxx9, opfxxa, opfxxb, opFMOV, opfxxd, opFMAC, NULL,
};

431
arch/SH/SHInstPrinter.c Normal file
View File

@ -0,0 +1,431 @@
/* Capstone Disassembly Engine */
/* By Yoshinori Sato, 2022 */
#include <string.h>
#include "SHInstPrinter.h"
#ifndef CAPSTONE_DIET
static const char* const s_reg_names[] = {
"invalid",
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
"r0_bank", "r1_bank", "r2_bank", "r3_bank",
"r4_bank", "r5_bank", "r6_bank", "r7_bank",
"fr0", "fr1", "fr2", "fr3", "fr4", "fr5", "fr6", "fr7",
"fr8", "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
"dr0", "dr2", "dr4", "dr6", "dr8", "dr10", "dr12", "dr14",
"xd0", "xd2", "xd4", "xd6", "xd8", "xd10", "xd12", "xd14",
"xf0", "xf1", "xf2", "xf3", "xf4", "xf5", "xf6", "xf7",
"xf8", "xf9", "xf10", "xf11", "xf12", "xf13", "xf14", "xf15",
"fv0", "fv4", "fv8", "fv12",
"xmtrx",
"pc", "pr", "mach", "macl",
"sr", "gbr", "ssr", "spc", "sgr", "dbr", "vbr", "tbr",
"rs", "re", "mod",
"fpul", "fpscr",
"x0", "x1", "y0", "y1", "a0", "a1", "a0g", "a1g", "m0", "m1",
"dsr",
"0x0", "0x1", "0x2", "0x3", "0x4", "0x5", "0x6", "0x7",
"0x8", "0x9", "0xa", "0xb", "0xc", "0xd", "0xe", "0xf",
};
#endif
const char* SH_reg_name(csh handle, unsigned int reg)
{
#ifdef CAPSTONE_DIET
return NULL;
#else
if (reg >= ARR_SIZE(s_reg_names)) {
return NULL;
}
return s_reg_names[(int)reg];
#endif
}
void SH_get_insn_id(cs_struct* h, cs_insn* insn, unsigned int id)
{
insn->id = id; // These id's matches for sh
}
#ifndef CAPSTONE_DIET
static const char* const s_insn_names[] = {
"unknwon",
"add", "add", "addc", "addv", "and",
"band", "bandnot", "bclr",
"bf", "bf/s", "bld", "bldnot", "bor", "bornot", "bra", "braf",
"bset", "bsr", "bsrf", "bst", "bt", "bt/s", "bxor",
"clips", "clipu",
"clrdmxy",
"clrmac", "clrs", "clrt",
"cmp/eq", "cmp/ge", "cmp/gt", "cmp/hi", "cmp/hs", "cmp/pl",
"cmp/pz", "cmp/str",
"div0s", "div0u", "div1",
"divs", "divu",
"dmuls.l", "dmulu.l",
"dt",
"exts", "exts", "extu", "extu",
"fabs", "fadd", "fcmp/eq", "fcmp/gt",
"fcnvds", "fcnvsd", "fdiv",
"fipr", "fldi0", "fldi1", "flds", "float",
"fmac", "fmov", "fmul", "fneg", "fpchg",
"frchg", "fsca", "fschg", "fsqrt", "fsrra",
"fsts", "fsub", "ftrc", "ftrv",
"icbi",
"jmp", "jsr", "jsr/n",
"ldbank",
"ldc", "ldrc", "ldre", "ldrs", "lds",
"ldtlb",
"mac.l", "mac.w",
"mov", "mova", "movca", "movco", "movi20", "movi20s",
"movli", "movml", "movmu", "movrt", "movt", "movu", "movua",
"mul.l", "mulr", "muls", "mulu",
"neg", "negc",
"nop",
"not", "nott",
"ocbi", "ocbp", "ocbwb",
"or",
"pref", "prefi",
"resbank",
"rotcl", "rotcr", "rotl", "rotr",
"rte", "rts", "rts/n", "rtv/n",
"setdmx", "setdmy", "setrc",
"sets", "sett",
"shad", "shal", "shar", "shld", "shll",
"shll16", "shll2", "shll8",
"shlr", "shlr16", "shlr2", "shlr8",
"sleep",
"stbank",
"stc", "sts",
"sub", "subc", "subv",
"swap", "swap",
"synco",
"tas",
"trapa",
"tst",
"xor",
"xtrct",
};
#endif
const char* SH_insn_name(csh handle, unsigned int id)
{
#ifdef CAPSTONE_DIET
return NULL;
#else
if (id >= ARR_SIZE(s_insn_names)) {
return NULL;
}
return s_insn_names[id];
#endif
}
#ifndef CAPSTONE_DIET
#endif
#ifndef CAPSTONE_DIET
static void print_dsp_double(SStream *O, sh_info *info, int xy)
{
char suffix_xy = 'x' + xy;
int i;
if (info->op.operands[xy].dsp.insn == SH_INS_DSP_NOP) {
if ((info->op.operands[0].dsp.insn == SH_INS_DSP_NOP) &&
(info->op.operands[1].dsp.insn == SH_INS_DSP_NOP)) {
SStream_concat(O, "nop%c", suffix_xy);
}
} else {
SStream_concat(O, "mov%c", suffix_xy);
switch(info->op.operands[xy].dsp.size) {
case 16:
SStream_concat0(O, ".w ");
break;
case 32:
SStream_concat0(O, ".l ");
break;
}
for (i = 0; i < 2; i++) {
switch(info->op.operands[xy].dsp.operand[i]) {
case SH_OP_DSP_REG_IND:
SStream_concat(O, "@%s", s_reg_names[info->op.operands[xy].dsp.r[i]]);
break;
case SH_OP_DSP_REG_POST:
SStream_concat(O, "@%s+", s_reg_names[info->op.operands[xy].dsp.r[i]]);
break;
case SH_OP_DSP_REG_INDEX:
SStream_concat(O, "@%s+%s", s_reg_names[info->op.operands[xy].dsp.r[i]], s_reg_names[SH_REG_R8 + xy]);
break;
case SH_OP_DSP_REG:
SStream_concat(O, "%s", s_reg_names[info->op.operands[xy].dsp.r[i]]);
break;
}
if (i == 0)
SStream_concat0(O, ",");
}
}
if (xy == 0)
SStream_concat0(O, " ");
}
static const char *s_dsp_insns[] = {
"invalid",
"nop",
"mov",
"pshl",
"psha",
"pmuls",
"pclr_pmuls",
"psub_pmuls",
"padd_pmuls",
"psubc",
"paddc",
"pcmp",
"pabs",
"prnd",
"psub",
"psub",
"padd",
"pand",
"pxor",
"por",
"pdec",
"pinc",
"pclr",
"pdmsb",
"pneg",
"pcopy",
"psts",
"plds",
"pswap",
"pwad",
"pwsb",
};
static void print_dsp(SStream *O, sh_info *info)
{
int i;
switch(info->op.op_count) {
case 1:
// single transfer
SStream_concat0(O, "movs");
switch(info->op.operands[0].dsp.size) {
case 16:
SStream_concat0(O, ".w ");
break;
case 32:
SStream_concat0(O, ".l ");
break;
}
for (i = 0; i < 2; i++) {
switch(info->op.operands[0].dsp.operand[i]) {
case SH_OP_DSP_REG_PRE:
SStream_concat(O, "@-%s", s_reg_names[info->op.operands[0].dsp.r[i]]);
break;
case SH_OP_DSP_REG_IND:
SStream_concat(O, "@%s", s_reg_names[info->op.operands[0].dsp.r[i]]);
break;
case SH_OP_DSP_REG_POST:
SStream_concat(O, "@%s+", s_reg_names[info->op.operands[0].dsp.r[i]]);
break;
case SH_OP_DSP_REG_INDEX:
SStream_concat(O, "@%s+%s", s_reg_names[info->op.operands[0].dsp.r[i]],s_reg_names[SH_REG_R8]);
break;
case SH_OP_DSP_REG:
SStream_concat(O, "%s", s_reg_names[info->op.operands[0].dsp.r[i]]);
}
if (i == 0)
SStream_concat0(O, ",");
}
break;
case 2: // Double transfer
print_dsp_double(O, info, 0);
print_dsp_double(O, info, 1);
break;
case 3: // Parallel
switch(info->op.operands[2].dsp.cc) {
case SH_DSP_CC_DCT:
SStream_concat0(O,"dct ");
break;
case SH_DSP_CC_DCF:
SStream_concat0(O,"dcf ");
break;
}
switch(info->op.operands[2].dsp.insn) {
case SH_INS_DSP_PSUB_PMULS:
case SH_INS_DSP_PADD_PMULS:
switch(info->op.operands[2].dsp.insn) {
case SH_INS_DSP_PSUB_PMULS:
SStream_concat0(O, "psub ");
break;
case SH_INS_DSP_PADD_PMULS:
SStream_concat0(O, "padd ");
break;
}
for (i = 0; i < 6; i++) {
SStream_concat(O, "%s", s_reg_names[info->op.operands[2].dsp.r[i]]);
if ((i % 3) < 2)
SStream_concat0(O, ",");
if (i == 2)
SStream_concat(O, " %s ", s_dsp_insns[SH_INS_DSP_PMULS]);
}
break;
case SH_INS_DSP_PCLR_PMULS:
SStream_concat0(O, s_dsp_insns[SH_INS_DSP_PCLR]);
SStream_concat(O, " %s ", s_reg_names[info->op.operands[2].dsp.r[3]]);
SStream_concat(O, "%s ", s_dsp_insns[SH_INS_DSP_PMULS]);
for (i = 0; i < 3; i++) {
SStream_concat(O, "%s", s_reg_names[info->op.operands[2].dsp.r[i]]);
if (i < 2)
SStream_concat0(O, ",");
}
break;
default:
SStream_concat0(O, s_dsp_insns[info->op.operands[2].dsp.insn]);
SStream_concat0(O, " ");
for (i = 0; i < 3; i++) {
if (info->op.operands[2].dsp.r[i] == SH_REG_INVALID) {
if (i == 0) {
SStream_concat(O, "#%d", info->op.operands[2].dsp.imm);
}
} else
SStream_concat(O, "%s", s_reg_names[info->op.operands[2].dsp.r[i]]);
if (i < 2 && info->op.operands[2].dsp.r[i + 1] != SH_REG_INVALID)
SStream_concat0(O, ",");
}
}
if (info->op.operands[0].dsp.insn != SH_INS_DSP_NOP) {
SStream_concat0(O, " ");
print_dsp_double(O, info, 0);
}
if (info->op.operands[1].dsp.insn != SH_INS_DSP_NOP) {
SStream_concat0(O, " ");
print_dsp_double(O, info, 1);
}
break;
}
}
static void PrintMemop(SStream *O, sh_op_mem *op) {
switch(op->address) {
case SH_OP_MEM_INVALID:
break;
case SH_OP_MEM_REG_IND:
SStream_concat(O, "@%s", s_reg_names[op->reg]);
break;
case SH_OP_MEM_REG_POST:
SStream_concat(O, "@%s+", s_reg_names[op->reg]);
break;
case SH_OP_MEM_REG_PRE:
SStream_concat(O, "@-%s", s_reg_names[op->reg]);
break;
case SH_OP_MEM_REG_DISP:
SStream_concat(O, "@(%d,%s)", op->disp, s_reg_names[op->reg]);
break;
case SH_OP_MEM_REG_R0: /// <= R0 indexed
SStream_concat(O, "@(%s,%s)",
s_reg_names[SH_REG_R0], s_reg_names[op->reg]);
break;
case SH_OP_MEM_GBR_DISP: /// <= GBR based displaysment
SStream_concat(O, "@(%d,%s)",
op->disp, s_reg_names[SH_REG_GBR]);
break;
case SH_OP_MEM_GBR_R0: /// <= GBR based R0 indexed
SStream_concat(O, "@(%s,%s)",
s_reg_names[SH_REG_R0], s_reg_names[SH_REG_GBR]);
break;
case SH_OP_MEM_PCR: /// <= PC relative
SStream_concat(O, "0x%x", op->disp);
break;
case SH_OP_MEM_TBR_DISP: /// <= GBR based displaysment
SStream_concat(O, "@@(%d,%s)",
op->disp, s_reg_names[SH_REG_TBR]);
break;
}
}
#endif
void SH_printInst(MCInst* MI, SStream* O, void* PrinterInfo)
{
#ifndef CAPSTONE_DIET
sh_info *info = (sh_info *)PrinterInfo;
cs_detail *detail = MI->flat_insn->detail;
int i;
int imm;
if (MI->Opcode == SH_INS_DSP) {
print_dsp(O, info);
return;
}
SStream_concat0(O, (char*)s_insn_names[MI->Opcode]);
switch(info->op.size) {
case 8:
SStream_concat0(O, ".b");
break;
case 16:
SStream_concat0(O, ".w");
break;
case 32:
SStream_concat0(O, ".l");
break;
case 64:
SStream_concat0(O, ".d");
break;
}
SStream_concat0(O, " ");
for (i = 0; i < info->op.op_count; i++) {
switch(info->op.operands[i].type) {
case SH_OP_INVALID:
break;
case SH_OP_REG:
SStream_concat0(O, s_reg_names[info->op.operands[i].reg]);
break;
case SH_OP_IMM:
imm = info->op.operands[i].imm;
SStream_concat(O, "#%d", imm);
break;
case SH_OP_MEM:
PrintMemop(O, &info->op.operands[i].mem);
break;
}
if (i < (info->op.op_count - 1)) {
SStream_concat0(O, ",");
}
}
#endif
}
#ifndef CAPSTONE_DIET
static const name_map group_name_maps[] = {
{ SH_GRP_INVALID , NULL },
{ SH_GRP_JUMP, "jump" },
{ SH_GRP_CALL, "call" },
{ SH_GRP_INT, "int" },
{ SH_GRP_RET , "ret" },
{ SH_GRP_IRET, "iret" },
{ SH_GRP_PRIVILEGE, "privilege" },
{ SH_GRP_BRANCH_RELATIVE, "branch_relative" },
{ SH_GRP_SH2, "SH2" },
{ SH_GRP_SH2E, "SH2E" },
{ SH_GRP_SH2DSP, "SH2-DSP" },
{ SH_GRP_SH2A, "SH2A" },
{ SH_GRP_SH2AFPU, "SH2A-FPU" },
{ SH_GRP_SH3, "SH3" },
{ SH_GRP_SH3DSP, "SH3-DSP" },
{ SH_GRP_SH4, "SH4" },
{ SH_GRP_SH4A, "SH4A" },
};
#endif
const char *SH_group_name(csh handle, unsigned int id)
{
#ifndef CAPSTONE_DIET
return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
#else
return NULL;
#endif
}

23
arch/SH/SHInstPrinter.h Normal file
View File

@ -0,0 +1,23 @@
/* Capstone Disassembly Engine */
/* By Yoshinori Sato, 2022 */
#ifndef CS_SHINSTPRINTER_H
#define CS_SHINSTPRINTER_H
#include "capstone/capstone.h"
#include "../../capstone/utils.h"
#include "../../MCInst.h"
#include "../../SStream.h"
#include "../../cs_priv.h"
#include "SHDisassembler.h"
struct SStream;
void SH_printInst(MCInst *MI, struct SStream *O, void *Info);
const char* SH_reg_name(csh handle, unsigned int reg);
void SH_get_insn_id(cs_struct* h, cs_insn* insn, unsigned int id);
const char* SH_insn_name(csh handle, unsigned int id);
const char *SH_group_name(csh handle, unsigned int id);
#endif

39
arch/SH/SHModule.c Normal file
View File

@ -0,0 +1,39 @@
/* Capstone Disassembly Engine */
/* By Yoshinori Sato 2022 */
#ifdef CAPSTONE_HAS_SH
#include "../../cs_priv.h"
#include "SHDisassembler.h"
#include "SHInstPrinter.h"
#include "SHModule.h"
cs_err SH_global_init(cs_struct *ud)
{
sh_info *info;
info = cs_mem_malloc(sizeof(sh_info));
if (!info) {
return CS_ERR_MEM;
}
ud->printer = SH_printInst;
ud->printer_info = info;
ud->reg_name = SH_reg_name;
ud->insn_id = SH_get_insn_id;
ud->insn_name = SH_insn_name;
ud->group_name = SH_group_name;
ud->disasm = SH_getInstruction;
#ifndef CAPSTONE_DIET
ud->reg_access = SH_reg_access;
#endif
return CS_ERR_OK;
}
cs_err SH_option(cs_struct *handle, cs_opt_type type, size_t value)
{
return CS_ERR_OK;
}
#endif

12
arch/SH/SHModule.h Normal file
View File

@ -0,0 +1,12 @@
/* Capstone Disassembly Engine */
/* By Yoshinori Sato, 2022 */
#ifndef CS_SH_MODULE_H
#define CS_SH_MODULE_H
#include "../../utils.h"
cs_err SH_global_init(cs_struct *ud);
cs_err SH_option(cs_struct *handle, cs_opt_type type, size_t value);
#endif

390
arch/SH/mktable.rb Normal file
View File

@ -0,0 +1,390 @@
#!/usr/bin/env ruby
out = Array.new(256, "NULL");
code_list = <<EOF
MOV_i #imm,Rn 1110nnnniiiiiiii
MOV.W @(disp*,PC),Rn 1001nnnndddddddd
MOV.L @(disp*,PC),Rn 1101nnnndddddddd
MOV Rm,Rn 0110nnnnmmmm0011
MOV.B Rm,@Rn 0010nnnnmmmm0000
MOV.W Rm,@Rn 0010nnnnmmmm0001
MOV.L Rm,@Rn 0010nnnnmmmm0010
MOV.B @Rm,Rn 0110nnnnmmmm0000
MOV.W @Rm,Rn 0110nnnnmmmm0001
MOV.L @Rm,Rn 0110nnnnmmmm0010
MOV.B Rm,@-Rn 0010nnnnmmmm0100
MOV.W Rm,@-Rn 0010nnnnmmmm0101
MOV.L Rm,@-Rn 0010nnnnmmmm0110
MOV.B @Rm+,Rn 0110nnnnmmmm0100
MOV.W @Rm+,Rn 0110nnnnmmmm0101
MOV.L @Rm+,Rn 0110nnnnmmmm0110
MOV.B R0,@(disp*,Rn) 10000000nnnndddd
MOV.W R0,@(disp*,Rn) 10000001nnnndddd
MOV.L Rm,@(disp*,Rn) 0001nnnnmmmmdddd
MOV.B @(disp*,Rm),R0 10000100mmmmdddd
MOV.W @(disp*,Rm),R0 10000101mmmmdddd
MOV.L @(disp*,Rm),Rn 0101nnnnmmmmdddd
MOV.B Rm,@(R0,Rn) 0000nnnnmmmm0100
MOV.W Rm,@(R0,Rn) 0000nnnnmmmm0101
MOV.L Rm,@(R0,Rn) 0000nnnnmmmm0110
MOV.B @(R0,Rm),Rn 0000nnnnmmmm1100
MOV.W @(R0,Rm),Rn 0000nnnnmmmm1101
MOV.L @(R0,Rm),Rn 0000nnnnmmmm1110
MOV.B R0,@(disp*,GBR) 11000000dddddddd
MOV.W R0,@(disp*,GBR) 11000001dddddddd
MOV.L R0,@(disp*,GBR) 11000010dddddddd
MOV.B @(disp*,GBR),R0 11000100dddddddd
MOV.W @(disp*,GBR),R0 11000101dddddddd
MOV.L @(disp*,GBR),R0 11000110dddddddd
MOVA @(disp*,PC),R0 11000111dddddddd
MOVCO.L R0,@Rn 0000nnnn01110011
MOVLI.L @Rm,R0 0000mmmm01100011
MOVUA.L @Rm,R0 0100mmmm10101001
MOVUA.L @Rm+,R0 0100mmmm11101001
MOVT Rn 0000nnnn00101001
SWAP.B Rm,Rn 0110nnnnmmmm1000
SWAP.W Rm,Rn 0110nnnnmmmm1001
XTRCT Rm,Rn 0010nnnnmmmm1101
ADD_r Rm,Rn 0011nnnnmmmm1100
ADD_i #imm,Rn 0111nnnniiiiiiii
ADDC Rm,Rn 0011nnnnmmmm1110
ADDV Rm,Rn 0011nnnnmmmm1111
CMP/EQ #imm,R0 10001000iiiiiiii
CMP/EQ Rm,Rn 0011nnnnmmmm0000
CMP/HS Rm,Rn 0011nnnnmmmm0010
CMP/GE Rm,Rn 0011nnnnmmmm0011
CMP/HI Rm,Rn 0011nnnnmmmm0110
CMP/GT Rm,Rn 0011nnnnmmmm0111
CMP/PZ Rn 0100nnnn00010001
CMP/PL Rn 0100nnnn00010101
CMP/STR Rm,Rn 0010nnnnmmmm1100
DIV1 Rm,Rn 0011nnnnmmmm0100
DIV0S Rm,Rn 0010nnnnmmmm0111
DIV0U 0000000000011001
DMULS.L Rm,Rn 0011nnnnmmmm1101
DMULU.L Rm,Rn 0011nnnnmmmm0101
DT Rn 0100nnnn00010000
EXTS.B Rm,Rn 0110nnnnmmmm1110
EXTS.W Rm,Rn 0110nnnnmmmm1111
EXTU.B Rm,Rn 0110nnnnmmmm1100
EXTU.W Rm,Rn 0110nnnnmmmm1101
MAC.L @Rm+,@Rn+ 0000nnnnmmmm1111
MAC.W @Rm+,@Rn+ 0100nnnnmmmm1111
MUL.L Rm,Rn 0000nnnnmmmm0111
MULS.W Rm,Rn 0010nnnnmmmm1111
MULU.W Rm,Rn 0010nnnnmmmm1110
NEG Rm,Rn 0110nnnnmmmm1011
NEGC Rm,Rn 0110nnnnmmmm1010
SUB Rm,Rn 0011nnnnmmmm1000
SUBC Rm,Rn 0011nnnnmmmm1010
SUBV Rm,Rn 0011nnnnmmmm1011
AND Rm,Rn 0010nnnnmmmm1001
AND_i #imm,R0 11001001iiiiiiii
AND.B #imm,@(R0,GBR) 11001101iiiiiiii
NOT Rm,Rn 0110nnnnmmmm0111
OR Rm,Rn 0010nnnnmmmm1011
OR_i #imm,R0 11001011iiiiiiii
OR.B #imm,@(R0,GBR) 11001111iiiiiiii
TAS.B @Rn 0100nnnn00011011
TST Rm,Rn 0010nnnnmmmm1000
TST_i #imm,R0 11001000iiiiiiii
TST.B #imm,@(R0,GBR) 11001100iiiiiiii
XOR Rm,Rn 0010nnnnmmmm1010
XOR_i #imm,R0 11001010iiiiiiii
XOR.B #imm,@(R0,GBR) 11001110iiiiiiii
ROTL Rn 0100nnnn00000100
ROTR Rn 0100nnnn00000101
ROTCL Rn 0100nnnn00100100
ROTCR Rn 0100nnnn00100101
SHAD Rm,Rn 0100nnnnmmmm1100
SHAL Rn 0100nnnn00100000
SHAR Rn 0100nnnn00100001
SHLD Rm,Rn 0100nnnnmmmm1101
SHLL Rn 0100nnnn00000000
SHLR Rn 0100nnnn00000001
SHLL2 Rn 0100nnnn00001000
SHLR2 Rn 0100nnnn00001001
SHLL8 Rn 0100nnnn00011000
SHLR8 Rn 0100nnnn00011001
SHLL16 Rn 0100nnnn00101000
SHLR16 Rn 0100nnnn00101001
BF label 10001011dddddddd
BF/S label 10001111dddddddd
BT label 10001001dddddddd
BT/S label 10001101dddddddd
BRA label 1010dddddddddddd
BRAF Rn 0000nnnn00100011
BSR label 1011dddddddddddd
BSRF Rn 0000nnnn00000011
JMP @Rn 0100nnnn00101011
JSR @Rn 0100nnnn00001011
RTS 0000000000001011
CLRMAC 0000000000101000
CLRS 0000000001001000
CLRT 0000000000001000
ICBI @Rn 0000nnnn11100011
LDC Rm,SR 0100mmmm00001110
LDC Rm,GBR 0100mmmm00011110
LDC Rm,VBR 0100mmmm00101110
LDC Rm,SGR 0100mmmm00111010
LDC Rm,SSR 0100mmmm00111110
LDC Rm,SPC 0100mmmm01001110
LDC Rm,DBR 0100mmmm11111010
LDC Rm,Rn_BANK 0100mmmm1nnn1110
LDC.L @Rm+,SR 0100mmmm00000111
LDC.L @Rm+,GBR 0100mmmm00010111
LDC.L @Rm+,VBR 0100mmmm00100111
LDC.L @Rm+,SGR 0100mmmm00110110
LDC.L @Rm+,SSR 0100mmmm00110111
LDC.L @Rm+,SPC 0100mmmm01000111
LDC.L @Rm+,DBR 0100mmmm11110110
LDC.L @Rm+,Rn_BANK 0100mmmm1nnn0111
LDS Rm,MACH 0100mmmm00001010
LDS Rm,MACL 0100mmmm00011010
LDS Rm,PR 0100mmmm00101010
LDS.L @Rm+,MACH 0100mmmm00000110
LDS.L @Rm+,MACL 0100mmmm00010110
LDS.L @Rm+,PR 0100mmmm00100110
LDTLB 0000000000111000
MOVCA.L R0,@Rn 0000nnnn11000011
NOP 0000000000001001
OCBI @Rn 0000nnnn10010011
OCBP @Rn 0000nnnn10100011
OCBWB @Rn 0000nnnn10110011
PREF @Rn 0000nnnn10000011
PREFI @Rn 0000nnnn11010011
RTE 0000000000101011
SETS 0000000001011000
SETT 0000000000011000
SLEEP 0000000000011011
STC SR,Rn 0000nnnn00000010
STC GBR,Rn 0000nnnn00010010
STC VBR,Rn 0000nnnn00100010
STC SSR,Rn 0000nnnn00110010
STC SPC,Rn 0000nnnn01000010
STC SGR,Rn 0000nnnn00111010
STC DBR,Rn 0000nnnn11111010
STC Rm_BANK,Rn 0000nnnn1mmm0010
STC.L SR,@-Rn 0100nnnn00000011
STC.L GBR,@-Rn 0100nnnn00010011
STC.L VBR,@-Rn 0100nnnn00100011
STC.L SSR,@-Rn 0100nnnn00110011
STC.L SPC,@-Rn 0100nnnn01000011
STC.L SGR,@-Rn 0100nnnn00110010
STC.L DBR,@-Rn 0100nnnn11110010
STC.L Rm_BANK,@-Rn 0100nnnn1mmm0011
STS MACH,Rn 0000nnnn00001010
STS MACL,Rn 0000nnnn00011010
STS PR,Rn 0000nnnn00101010
STS.L MACH,@-Rn 0100nnnn00000010
STS.L MACL,@-Rn 0100nnnn00010010
STS.L PR,@-Rn 0100nnnn00100010
SYNCO 0000000010101011
TRAPA #imm 11000011iiiiiiii
FLDI0 FRn 1111nnnn10001101
FLDI1 FRn 1111nnnn10011101
FMOV FRm,FRn 1111nnnnmmmm1100
FMOV.S @Rm,FRn 1111nnnnmmmm1000
FMOV.S @(R0,Rm),FRn 1111nnnnmmmm0110
FMOV.S @Rm+,FRn 1111nnnnmmmm1001
FMOV.S FRm,@Rn 1111nnnnmmmm1010
FMOV.S FRm,@-Rn 1111nnnnmmmm1011
FMOV.S FRm,@(R0,Rn) 1111nnnnmmmm0111
FMOV DRm,DRn 1111nnn0mmm01100
FMOV @Rm,DRn 1111nnn0mmmm1000
FMOV @(R0,Rm),DRn 1111nnn0mmmm0110
FMOV @Rm+,DRn 1111nnn0mmmm1001
FMOV DRm,@Rn 1111nnnnmmm01010
FMOV DRm,@-Rn 1111nnnnmmm01011
FMOV DRm,@(R0,Rn) 1111nnnnmmm00111
FLDS FRm,FPUL 1111mmmm00011101
FSTS FPUL,FRn 1111nnnn00001101
FABS FRn 1111nnnn01011101
FADD FRm,FRn 1111nnnnmmmm0000
FCMP/EQ FRm,FRn 1111nnnnmmmm0100
FCMP/GT FRm,FRn 1111nnnnmmmm0101
FDIV FRm,FRn 1111nnnnmmmm0011
FLOAT FPUL,FRn 1111nnnn00101101
FMAC FR0,FRm,FRn 1111nnnnmmmm1110
FMUL FRm,FRn 1111nnnnmmmm0010
FNEG FRn 1111nnnn01001101
FSQRT FRn 1111nnnn01101101
FSUB FRm,FRn 1111nnnnmmmm0001
FTRC FRm,FPUL 1111mmmm00111101
FABS DRn 1111nnn001011101
FADD DRm,DRn 1111nnn0mmm00000
FCMP/EQ DRm,DRn 1111nnn0mmm00100
FCMP/GT DRm,DRn 1111nnn0mmm00101
FDIV DRm,DRn 1111nnn0mmm00011
FCNVDS DRm,FPUL 1111mmm010111101
FCNVSD FPUL,DRn 1111nnn010101101
FLOAT FPUL,DRn 1111nnn000101101
FMUL DRm,DRn 1111nnn0mmm00010
FNEG DRn 1111nnn001001101
FSQRT DRn 1111nnn001101101
FSUB DRm,DRn 1111nnn0mmm00001
FTRC DRm,FPUL 1111mmm000111101
LDS Rm,FPSCR 0100mmmm01101010
LDS Rm,FPUL 0100mmmm01011010
LDS.L @Rm+,FPSCR 0100mmmm01100110
LDS.L @Rm+,FPUL 0100mmmm01010110
STS FPSCR,Rn 0000nnnn01101010
STS FPUL,Rn 0000nnnn01011010
STS.L FPSCR,@-Rn 0100nnnn01100010
STS.L FPUL,@-Rn 0100nnnn01010010
FMOV DRm,XDn 1111nnn1mmm01100
FMOV XDm,DRn 1111nnn0mmm11100
FMOV XDm,XDn 1111nnn1mmm11100
FMOV @Rm,XDn 1111nnn1mmmm1000
FMOV @Rm+,XDn 1111nnn1mmmm1001
FMOV @(R0,Rm),XDn 1111nnn1mmmm0110
FMOV XDm,@Rn 1111nnnnmmm11010
FMOV XDm,@-Rn 1111nnnnmmm11011
FMOV XDm,@(R0,Rn) 1111nnnnmmm10111
FIPR FVm,FVn 1111nnmm11101101
FTRV XMTRX,FVn 1111nn0111111101
FRCHG 1111101111111101
FSCHG 1111001111111101
FPCHG 1111011111111101
FSRRA FRn 1111nnnn01111101
FSCA FPUL,DRn 1111nnn011111101
MOV.B R0,@Rn+ 0100nnnn10001011
MOV.W R0,@Rn+ 0100nnnn10011011
MOV.L R0,@Rn+ 0100nnnn10101011
MOV.B @-Rm,R0 0100mmmm11001011
MOV.W @-Rm,R0 0100mmmm11011011
MOV.L @-Rm,R0 0100mmmm11101011
MOV.B Rm,@(disp12,Rn) 0011nnnnmmmm00010000dddddddddddd
MOV.W Rm,@(disp12,Rn) 0011nnnnmmmm00010001dddddddddddd
MOV.L Rm,@(disp12,Rn) 0011nnnnmmmm00010010dddddddddddd
MOV.B @(disp12,Rm),Rn 0011nnnnmmmm00010100dddddddddddd
MOV.W @(disp12,Rm),Rn 0011nnnnmmmm00010101dddddddddddd
MOV.L @(disp12,Rm),Rn 0011nnnnmmmm00010110dddddddddddd
MOVI20 #imm20,Rn 0000nnnniiii0000iiiiiiiiiiiiiiii
MOVI20S #imm20,Rn 0000nnnniiii0001iiiiiiiiiiiiiiii
MOVML.L Rm,@-R15 0100mmmm11110001
MOVML.L @R15+,Rn 0100nnnn11110101
MOVMU.L Rm,@-R15 0100mmmm11110000
MOVMU.L @R15+,Rn 0100nnnn11110100
MOVRT Rn 0000nnnn00111001
MOVU.B @(disp12,Rm),Rn 0011nnnnmmmm00011000dddddddddddd
MOVU.W @(disp12,Rm),Rn 0011nnnnmmmm00011001dddddddddddd
NOTT 0000000001101000
CLIPS.B Rn 0100nnnn10010001
CLIPS.W Rn 0100nnnn10010101
CLIPU.B Rn 0100nnnn10000001
CLIPU.W Rn 0100nnnn10000101
DIVS R0,Rn 0100nnnn10010100
DIVU R0,Rn 0100nnnn10000100
MULR R0,Rn 0100nnnn10000000
JSR/N @Rm 0100mmmm01001011
JSR/N @@(disp8,TBR) 10000011dddddddd
RTS/N 0000000001101011
RTV/N Rm 0000mmmm01111011
LDBANK @Rm,R0 0100mmmm11100101
LDC Rm,TBR 0100mmmm01001010
RESBANK 0000000001011011
STBANK R0,@Rn 0100nnnn11100001
STC TBR,Rn 0000nnnn01001010
FMOV.S @(disp12,Rm),FRn 0011nnnnmmmm00010111dddddddddddd
FMOV.D @(disp12,Rm),DRn 0011nnn0mmmm00010111dddddddddddd
FMOV.S FRm,@(disp12,Rn) 0011nnnnmmmm00010011dddddddddddd
FMOV.D DRm,@(disp12,Rn) 0011nnnnmmm000010011dddddddddddd
FMOV.S FRm,@(disp12,Rn) 0011nnnnmmmm00010011dddddddddddd
FMOV.D DRm,@(disp12,Rn) 0011nnnnmmm000010011dddddddddddd
BAND.B #imm3,@(disp12,Rn) 0011nnnn0iii10010100dddddddddddd
BANDNOT.B #imm3,@(disp12,Rn) 0011nnnn0iii10011100dddddddddddd
BCLR.B #imm3,@(disp12,Rn) 0011nnnn0iii10010000dddddddddddd
BCLR #imm3,Rn 10000110nnnn0iii
BLD.B #imm3,@(disp12,Rn) 0011nnnn0iii10010011dddddddddddd
BLD #imm3,Rn 10000111nnnn1iii
BLDNOT.B #imm3,@(disp12,Rn) 0011nnnn0iii10011011dddddddddddd
BOR.B #imm3,@(disp12,Rn) 0011nnnn0iii10010101dddddddddddd
BORNOT.B #imm3,@(disp12,Rn) 0011nnnn0iii10011101dddddddddddd
BSET.B #imm3,@(disp12,Rn) 0011nnnn0iii10010001dddddddddddd
BSET #imm3,Rn 10000110nnnn1iii
BST.B #imm3,@(disp12,Rn) 0011nnnn0iii10010010dddddddddddd
BST #imm3,Rn 10000111nnnn0iii
BXOR.B #imm3,@(disp12,Rn) 0011nnnn0iii10010110dddddddddddd
LDRE @(disp,PC) 10001110dddddddd
LDRS @(disp,PC) 10001100dddddddd
SETRC Rm 0100mmmm00010100
SETRC #imm 10000010iiiiiiii
LDRC #imm 10001010iiiiiiii
EOF
code_list.each_line { |line|
l = line.split
l[2] = l[1] if (l.length < 3)
if l[2].length > 16 then
l[2] = l[2][0..15]
end
if l[2][0..3].to_i(2) < 8 || l[2][0..3].to_i(2) == 15 then
b = l[2][0..3] + l[2][12..15]
else
b = l[2][0..7]
end
if b =~ /^\d+$/ then
no = b.to_i(2)
if no == 0x00 || no == 0x01 || no == 0x31 || no == 0x39 then
# SH2A 32bit instructions prefix
next
end
next if out[no] == "op" + l[0]
if (no >= 0x20 && no <= 0x22) || (no >= 0x60 && no <= 0x62)then
l[0] = "MOV_rind"
end
if no >= 0x24 && no <= 0x26 then
l[0] = "MOV_rpd"
end
if no >= 0x64 && no <= 0x66 then
l[0] = "MOV_rpi"
end
if no == 0x80 || no == 0x81 || no == 0x84 || no == 0x85 then
l[0] = "MOV_BW_dsp"
end
if no == 0x88 then
l[0] = "CMP_EQi"
end
if no == 0xc0 || no == 0xc1 || no == 0xc2 || no == 0xc4 || no == 0xc5 || no == 0xc6 then
l[0] = "MOV_gbr"
end
if out[no] == "NULL" then
out[no] = "op" + l[0]
else
hi = b.to_i(2) / 16
lo = b.to_i(2) % 16
if (hi < 0x8) || (hi >= 0x0f) then
out[no] = "op" + hi.to_s(16) + "xx" + lo.to_s(16)
else
out[no] = "op" + hi.to_s(16) + lo.to_s(16) + "xx"
end
end
else
n = (l[2][0..3].to_i(2)) * 16
if n != 0x80 && n != 0xc0 then
if n == 0x10 || n == 0x50 then
l[0] = "MOV_L_dsp"
end
if n == 0x90 || n == 0xd0 then
l[0] = "MOV_pc"
end
16.times { |i|
out[n + i] = "op" + l[0]
}
end
end
}
code = 0
print "bool (*decode[])(uint16_t code, uint64_t address, MCInst *MI, cs_mode mode, sh_info *info, cs_detail *detail) = {\n"
(256 / 8).times { |i|
bit = "0000000" + code.to_s(2)
print "\t/// ", bit[-8,8], "\n\t"
8.times { |j|
o = out[i * 8 + j].gsub(/[\.\/]/, '_')
print o, ", "
code = code.succ
}
print "\n"
}
print "};\n"