Initial SH4 support

This commit is contained in:
Eloi Sanfelix 2011-03-29 14:55:41 +02:00
parent 08ee3226ec
commit 7c04f11226
16 changed files with 1617 additions and 2 deletions

View File

@ -8,7 +8,7 @@ foo: all
ALL_TARGETS=
# TODO: rename to enabled plugins
ARCHS=x86.mk x86_simple.mk ppc.mk arm.mk avr.mk csr.mk dalvik.mk
ARCHS=x86.mk x86_simple.mk ppc.mk arm.mk avr.mk csr.mk dalvik.mk sh.mk
include $(ARCHS)
all: ${ALL_TARGETS}

505
libr/anal/p/anal_sh.c Normal file
View File

@ -0,0 +1,505 @@
/* radare - GPL3 - Copyright 2010-2011 eloi<limited-entropy.com> */
#include <string.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_asm.h>
#include <r_anal.h>
#define API static
#define LONG_SIZE 4
#define WORD_SIZE 2
#define BYTE_SIZE 1
//Macros for different instruction types
#define IS_RTE(x) ((x) == 0x002b)
#define IS_RTS(x) ((x) == 0x000b)
#define IS_BSRF(x) (((x) & 0xf0ff) == 0x0003)
#define IS_BRAF(x) (((x) & 0xf0ff) == 0x0023)
#define IS_MOVB_REG_TO_R0REL(x) (((x) & 0xF00F) == 0x0004)
#define IS_MOVW_REG_TO_R0REL(x) (((x) & 0xF00F) == 0x0005)
#define IS_MOVL_REG_TO_R0REL(x) (((x) & 0xF00F) == 0x0006)
#define IS_MOVB_R0REL_TO_REG(x) (((x) & 0xF00F) == 0x000C)
#define IS_MOVW_R0REL_TO_REG(x) (((x) & 0xF00F) == 0x000D)
#define IS_MOVL_R0REL_TO_REG(x) (((x) & 0xF00F) == 0x000E)
#define IS_MOVB_REG_TO_REGREF(x) (((x) & 0xF00F) == 0x2000)
#define IS_MOVW_REG_TO_REGREF(x) (((x) & 0xF00F) == 0x2001)
#define IS_MOVL_REG_TO_REGREF(x) (((x) & 0xF00F) == 0x2002)
#define IS_PUSHB(x) (((x) & 0xF00F) == 0x2004)
#define IS_PUSHW(x) (((x) & 0xF00F) == 0x2005)
#define IS_PUSHL(x) (((x) & 0xF00F) == 0x2006)
#define IS_AND_REGS(x) (((x) & 0xF00F) == 0x2009)
#define IS_XOR_REGS(x) (((x) & 0xF00F) == 0x200A)
#define IS_OR_REGS(x) (((x) & 0xF00F) == 0x200B)
#define IS_ADD(x) (((x) & 0xF00F) == 0x300C)
#define IS_ADDC(x) (((x) & 0xF00F) == 0x300E)
#define IS_ADDV(x) (((x) & 0xF00F) == 0x300F)
#define IS_SUB(x) (((x) & 0xF00F) == 0x3008)
#define IS_SUBC(x) (((x) & 0xF00F) == 0x300A)
#define IS_SUBV(x) (((x) & 0xF00F) == 0x300B)
#define IS_JSR(x) (((x) & 0xf0ff) == 0x400b)
#define IS_JMP(x) (((x) & 0xf0ff) == 0x402b)
#define IS_MOV_REGS(x) (((x) & 0xf00f) == 0x6003)
#define IS_MOVB_REGREF_TO_REG(x) (((x) & 0xF00F) == 0x6000)
#define IS_MOVW_REGREF_TO_REG(x) (((x) & 0xF00F) == 0x6001)
#define IS_MOVL_REGREF_TO_REG(x) (((x) & 0xF00F) == 0x6002)
#define IS_BF(x) (((x) & 0xff00) == 0x8B00)
#define IS_BFS(x) (((x) & 0xff00) == 0x8F00)
#define IS_BT(x) (((x) & 0xff00) == 0x8900)
#define IS_BTS(x) (((x) & 0xff00) == 0x8D00)
#define IS_BT_OR_BF(x) IS_BT(x)||IS_BTS(x)||IS_BF(x)||IS_BFS(x)
#define IS_MOVB_REGDISP_R0(x) (((x) & 0xFF00) == 0x8400)
#define IS_MOVW_REGDISP_R0(x) (((x) & 0xFF00) == 0x8500)
#define IS_TRAP(x) (((x) & 0xFF00) == 0xC300)
#define IS_MOVA_PCREL_R0(x) (((x) & 0xFF00) == 0xC700)
#define IS_AND_IMM_R0(x) (((x) & 0xFF00) == 0xC900)
#define IS_XOR_IMM_R0(x) (((x) & 0xFF00) == 0xCA00)
#define IS_OR_IMM_R0(x) (((x) & 0xFF00) == 0xCB00)
/* Compute PC-relative displacement for branch instructions */
#define GET_BRA_OFFSET(x) ((x) & 0x0fff)
#define GET_BTF_OFFSET(x) ((x) & 0x00ff)
/* Compute reg nr for BRAF,BSR,BSRF,JMP,JSR */
#define GET_TARGET_REG(x) ((x >> 8) & 0x0f)
#define GET_SOURCE_REG(x) ((x >> 4) & 0x0f)
#define PC_IDX 16
static RAnalValue *anal_fill_12bit_offset (RAnalOp *op, unsigned int insoff) {
unsigned int add = insoff;
RAnalValue *ret = r_anal_value_new();
/* sign extend if higher bit is 1 (0x0800) */
if ((add & 0x0800) == 0x0800)
add |= 0xFFFFF000;
ret->base = (add<<1) + op->addr + 4;
return ret;
}
static unsigned int disarm_8bit_offset (unsigned int pc, unsigned int insoff) {
unsigned int add = insoff;
/* sign extend if higher bit is 1 (0x08) */
if ((add & 0x80) == 0x80)
add |= 0xFFFFFF00;
return (add<<1) + pc + 4; //2*sign_extend(displacement) + 4
}
static char *regs[]={"r0","r1","r2","r3","r4","r5","r6","r7","r8","r9","r10","r11","r12","r13","r14","r15","pc"};
static RAnalValue *anal_fill_ai_rg(RAnal *anal, int idx) {
RAnalValue *ret = r_anal_value_new ();
ret->reg = r_reg_get (anal->reg,regs[idx],R_REG_TYPE_GPR);
return ret;
}
static RAnalValue *anal_fill_im(RAnal *anal, st32 v) {
RAnalValue *ret = r_anal_value_new ();
ret->imm = v;
return ret;
}
/* Implements @(disp,Rn) , size=1 for .b, 2 for .w, 4 for .l */
static RAnalValue *anal_fill_reg_disp_mem(RAnal *anal, int reg, st64 delta, st64 size) {
RAnalValue *ret = anal_fill_ai_rg(anal,reg);
ret->memref = size;
ret->delta = delta*size;
return ret;
}
static RAnalValue *anal_fill_reg_ref(RAnal *anal, int reg, st64 size){
RAnalValue *ret = anal_fill_ai_rg(anal,reg);
ret->memref = size;
return ret;
}
/* @(R0,Rx) references for all sizes */
static RAnalValue *anal_fill_r0_reg_ref(RAnal *anal, int reg,st64 size){
RAnalValue *ret = anal_fill_ai_rg(anal,0);
ret->regdelta = r_reg_get(anal->reg,regs[reg],R_REG_TYPE_GPR);
ret->memref = size;
return ret;
}
static st32 sign_extend_12b(st32 v){
if( v & 0x800 ){
v |= 0xFFFFF000;
}
return v;
}
static RAnalValue *anal_pcrel_disp_mov(RAnal* anal,RAnalOp* op,st8 disp){
RAnalValue *ret = r_anal_value_new ();
ret->base = op->addr;
ret->delta = (op->addr & 0x02)?WORD_SIZE:LONG_SIZE;
ret->delta = ret->delta + disp*LONG_SIZE;
return ret;
}
static RAnalValue *anal_regrel_jump(RAnal* anal,RAnalOp* op, ut8 reg){
RAnalValue *ret = r_anal_value_new ();
ret->reg = r_reg_get(anal->reg,regs[reg],R_REG_TYPE_GPR);
ret->delta = op->addr+4;
return ret;
}
/* 16 decoder routines, based on 1st nibble value */
int first_nibble_is_0(RAnal* anal, RAnalOp* op, ut16 code){
if(IS_BSRF(code)){
/* Call 'far' subroutine Rn+PC+4 */
op->type = R_ANAL_OP_TYPE_UCALL;
op->delay = 1;
op->dst = anal_regrel_jump(anal,op,GET_TARGET_REG(code));
} else if (IS_BRAF(code)){
/* Unconditional branch to Rn+PC+4, no delay slot */
op->type = R_ANAL_OP_TYPE_UJMP;
op->dst = anal_regrel_jump(anal,op,GET_TARGET_REG(code));
op->eob = R_TRUE;
} else if( IS_RTS(code) ){
/* Ret from subroutine. Returns to pr */
//TODO Convert into jump pr?
op->type = R_ANAL_OP_TYPE_RET;
op->delay = 1;
op->eob = R_TRUE;
} else if (IS_RTE(code)){
//TODO Convert into jmp spc? Indicate ssr->sr as well?
op->type = R_ANAL_OP_TYPE_RET;
op->delay = 1;
op->eob = R_TRUE;
} else if (IS_MOVB_REG_TO_R0REL(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_fill_ai_rg(anal,GET_SOURCE_REG(code));
op->dst = anal_fill_r0_reg_ref(anal,GET_TARGET_REG(code),BYTE_SIZE);
} else if (IS_MOVW_REG_TO_R0REL(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_fill_ai_rg(anal,GET_SOURCE_REG(code));
op->dst = anal_fill_r0_reg_ref(anal,GET_TARGET_REG(code),WORD_SIZE);
} else if (IS_MOVL_REG_TO_R0REL(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_fill_ai_rg(anal,GET_SOURCE_REG(code));
op->dst = anal_fill_r0_reg_ref(anal,GET_TARGET_REG(code),LONG_SIZE);
} else if (IS_MOVB_R0REL_TO_REG(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_fill_r0_reg_ref(anal,GET_SOURCE_REG(code),BYTE_SIZE);
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
} else if (IS_MOVW_R0REL_TO_REG(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_fill_r0_reg_ref(anal,GET_SOURCE_REG(code),WORD_SIZE);
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
} else if (IS_MOVL_R0REL_TO_REG(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_fill_r0_reg_ref(anal,GET_SOURCE_REG(code),LONG_SIZE);
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
}
//TODO Check missing insns, specially STC might be interesting
return op->length;
}
int movl_reg_rdisp(RAnal* anal, RAnalOp* op, ut16 code){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_fill_ai_rg(anal,GET_SOURCE_REG(code));
op->dst = anal_fill_reg_disp_mem(anal,GET_TARGET_REG(code),code&0x0F,LONG_SIZE);
return op->length;
}
int first_nibble_is_2(RAnal* anal, RAnalOp* op, ut16 code){
//TODO handle mov.x Rm, @Rn, (X)OR/AND regs,
if (IS_MOVB_REG_TO_REGREF(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_fill_ai_rg(anal,GET_SOURCE_REG(code));
op->dst = anal_fill_reg_ref(anal,GET_TARGET_REG(code),BYTE_SIZE);
} else if (IS_MOVW_REG_TO_REGREF(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_fill_ai_rg(anal,GET_SOURCE_REG(code));
op->dst = anal_fill_reg_ref(anal,GET_TARGET_REG(code),WORD_SIZE);
} else if (IS_MOVL_REG_TO_REGREF(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_fill_ai_rg(anal,GET_SOURCE_REG(code));
op->dst = anal_fill_reg_ref(anal,GET_TARGET_REG(code),LONG_SIZE);
} else if (IS_AND_REGS(code)){
op->type = R_ANAL_OP_TYPE_AND;
op->src[0] = anal_fill_ai_rg(anal,GET_SOURCE_REG(code));
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
} else if (IS_XOR_REGS(code)){
op->type = R_ANAL_OP_TYPE_XOR;
op->src[0] = anal_fill_ai_rg(anal,GET_SOURCE_REG(code));
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
} else if (IS_OR_REGS(code)){
op->type = R_ANAL_OP_TYPE_OR;
op->src[0] = anal_fill_ai_rg(anal,GET_SOURCE_REG(code));
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
}
//TODO Handle 'pushes' (mov Rm,@-Rn)
//TODO Handle CMP/STR ??
return op->length;
}
int first_nibble_is_3(RAnal* anal, RAnalOp* op, ut16 code){
//TODO Handle carry/overflow , CMP/xx?
if( IS_ADD(code) || IS_ADDC(code) || IS_ADDV(code) ){
op->type = R_ANAL_OP_TYPE_ADD;
op->src[0] = anal_fill_ai_rg(anal,GET_SOURCE_REG(code));
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
} else if ( IS_SUB(code) || IS_SUBC(code) || IS_SUBV(code)){
op->type = R_ANAL_OP_TYPE_SUB;
op->src[0] = anal_fill_ai_rg(anal,GET_SOURCE_REG(code));
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
}
return op->length;
}
int first_nibble_is_4(RAnal* anal, RAnalOp* op, ut16 code){
if(IS_JSR(code)){
op->type = R_ANAL_OP_TYPE_UCALL; //call to reg
op->delay = 1;
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
} else if ( IS_JMP(code) ){
op->type = R_ANAL_OP_TYPE_UJMP; //jmp to reg
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
op->delay = 1;
op->eob = R_TRUE;
}
//TODO shifts + many system insns + CMP/P[L|Z]??
return op->length;
}
int movl_rdisp_reg(RAnal* anal, RAnalOp* op, ut16 code){
op->type = R_ANAL_OP_TYPE_MOV;
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
op->src[0] = anal_fill_reg_disp_mem(anal,GET_SOURCE_REG(code),code&0x0F,LONG_SIZE);
return op->length;
}
int first_nibble_is_6(RAnal* anal, RAnalOp* op, ut16 code){
if(IS_MOV_REGS(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_fill_ai_rg(anal,GET_SOURCE_REG(code));
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
} else if (IS_MOVB_REGREF_TO_REG(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_fill_reg_ref(anal,GET_SOURCE_REG(code),BYTE_SIZE);
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
} else if (IS_MOVW_REGREF_TO_REG(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_fill_reg_ref(anal,GET_SOURCE_REG(code),WORD_SIZE);
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
} else if (IS_MOVL_REGREF_TO_REG(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_fill_reg_ref(anal,GET_SOURCE_REG(code),LONG_SIZE);
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
}
//TODO neg(c) + MOV.L @Rm+,Rn
return op->length;
}
int add_imm(RAnal* anal, RAnalOp* op, ut16 code){
op->type = R_ANAL_OP_TYPE_ADD;
op->src[0] = anal_fill_im(anal, (st8)(code&0xFF)); //Casting to (st8) forces sign-extension.
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
return op->length;
}
int first_nibble_is_8(RAnal* anal, RAnalOp* op, ut16 code){
if (IS_BT_OR_BF(code)){
op->type = R_ANAL_OP_TYPE_CJMP; //Jump if true or jump if false insns
op->jump = disarm_8bit_offset(op->addr,GET_BTF_OFFSET(code));
op->fail = op->addr + 2 ;
op->eob = R_TRUE;
if (IS_BTS(code) || IS_BFS(code))
op->delay = 1; //Only /S versions have a delay slot
} else if (IS_MOVB_REGDISP_R0(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
op->src[0] = anal_fill_reg_disp_mem(anal,GET_SOURCE_REG(code),code&0x0F,BYTE_SIZE);
} else if (IS_MOVW_REGDISP_R0(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
op->src[0] = anal_fill_reg_disp_mem(anal,GET_SOURCE_REG(code),code&0x0F,WORD_SIZE);
}
//TODO some movs + CMP/EQ??
return op->length;
}
int movw_pcdisp_reg(RAnal* anal, RAnalOp* op, ut16 code){
op->type = R_ANAL_OP_TYPE_MOV;
op->dst = anal_fill_ai_rg(anal, GET_TARGET_REG(code));
op->src[0] = anal_fill_reg_disp_mem(anal,PC_IDX,code&0xFF,WORD_SIZE);
return op->length;
}
int bra(RAnal* anal, RAnalOp* op, ut16 code){
/* Unconditional branch, relative to PC */
op->type = R_ANAL_OP_TYPE_JMP;
op->delay = 1;
op->dst = anal_fill_12bit_offset(op,GET_BRA_OFFSET(code));
op->eob = R_TRUE;
return op->length;
}
int bsr(RAnal* anal, RAnalOp* op, ut16 code){
/* Subroutine call, relative to PC */
op->type = R_ANAL_OP_TYPE_CALL;
op->dst = anal_fill_12bit_offset(op,GET_BRA_OFFSET(code));
op->delay = 1;
return op->length;
}
int first_nibble_is_c(RAnal* anal, RAnalOp* op, ut16 code){
if (IS_TRAP(code)){
op->type = R_ANAL_OP_TYPE_SWI;
op->value = (ut8)(code&0xFF);
} else if (IS_MOVA_PCREL_R0(code)){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_pcrel_disp_mov(anal,op,code&0xFF);
op->dst = anal_fill_ai_rg(anal,0); //Always R0
} else if (IS_AND_IMM_R0(code)){
op->type = R_ANAL_OP_TYPE_AND;
op->src[0] = anal_fill_im(anal,code&0xFF);
op->dst = anal_fill_ai_rg(anal,0); //Always R0
} else if (IS_OR_IMM_R0(code)){
op->type = R_ANAL_OP_TYPE_OR;
op->src[0] = anal_fill_im(anal,code&0xFF);
op->dst = anal_fill_ai_rg(anal,0); //Always R0
} else if (IS_XOR_IMM_R0(code)){
op->type = R_ANAL_OP_TYPE_XOR;
op->src[0] = anal_fill_im(anal,code&0xFF);
op->dst = anal_fill_ai_rg(anal,0); //Always R0
}
//TODO Logic insns referencing GBR
return op->length;
}
int movl_pcdisp_reg(RAnal* anal, RAnalOp* op, ut16 code){
op->type = R_ANAL_OP_TYPE_MOV;
op->src[0] = anal_pcrel_disp_mov(anal,op,code&0x0F);
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
return op->length;
}
int mov_imm_reg(RAnal* anal, RAnalOp* op, ut16 code){
op->type = R_ANAL_OP_TYPE_MOV;
op->dst = anal_fill_ai_rg(anal,GET_TARGET_REG(code));
op->src[0] = anal_fill_im(anal,(st8)(code & 0xFF));
return op->length;
}
int fpu_insn(RAnal* anal, RAnalOp* op, ut16 code){
//Not interested on FPU stuff for now
op->family = R_ANAL_OP_FAMILY_FPU;
return op->length;
}
/* Table of routines for further analysis based on 1st nibble */
int (*first_nibble_decode[])(RAnal*,RAnalOp*,ut16) = {
first_nibble_is_0,
movl_reg_rdisp,
first_nibble_is_2,
first_nibble_is_3,
first_nibble_is_4,
movl_rdisp_reg,
first_nibble_is_6,
add_imm,
first_nibble_is_8,
movw_pcdisp_reg,
bra,
bsr,
first_nibble_is_c,
movl_pcdisp_reg,
mov_imm_reg,
fpu_insn
};
/* This is the basic operation analysis. Just initialize and jump to
* routines defined in first_nibble_decode table
*/
static int sh_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) {
//TODO Check if we must do big or little endian. Also fix in RAsm
ut16 code = *((ut16 *)data);
ut8 b = data[1]; //First byte, little endian
int ret;
if (data == NULL)
return 0;
memset (op, '\0', sizeof (RAnalOp));
op->addr = addr;
op->type = R_ANAL_OP_TYPE_UNK;
op->jump = op->fail = -1;
op->ref = op->value = -1;
op->length = 2;
ret = first_nibble_decode[(b>>4) & 0x0F](anal,op,code);
return ret;
}
/* Set the profile register */
static int sh_set_reg_profile(RAnal* anal){
//TODO Add system ( ssr, spc ) + fpu regs
int ret = r_reg_set_profile_string(anal->reg,
"=pc pc\n"
"=sp r15\n"
"=bp r14\n"
"gpr r0 .32 0 0\n"
"gpr r1 .32 4 0\n"
"gpr r2 .32 8 0\n"
"gpr r3 .32 12 0\n"
"gpr r4 .32 16 0\n"
"gpr r5 .32 20 0\n"
"gpr r6 .32 24 0\n"
"gpr r7 .32 28 0\n"
"gpr r8 .32 32 0\n"
"gpr r9 .32 36 0\n"
"gpr r10 .32 36 0\n"
"gpr r11 .32 40 0\n"
"gpr r12 .32 44 0\n"
"gpr r13 .32 48 0\n"
"gpr r14 .32 52 0\n"
"gpr r15 .32 56 0\n"
"gpr pc .32 60 0\n"
"gpr pr .32 64 0\n"
"gpr sr .32 68 0\n"
"gpr gbr .32 72 0\n"
"gpr mach .32 76 0\n"
"gpr macl .32 80 0\n"
);
return ret;
}
struct r_anal_plugin_t r_anal_plugin_sh = {
.name = "sh",
.desc = "SH-4 code analysis plugin",
.init = NULL,
.fini = NULL,
.op = &sh_op,
.set_reg_profile = &sh_set_reg_profile,
.fingerprint_bb = NULL,
.fingerprint_fcn = NULL,
.diff_bb = NULL,
.diff_fcn = NULL,
.diff_eval = NULL
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ANAL,
.data = &r_anal_plugin_sh
};
#endif

9
libr/anal/p/sh.mk Normal file
View File

@ -0,0 +1,9 @@
OBJ_SH=anal_sh.o
STATIC_OBJ+=${OBJ_SH}
TARGET_SH=anal_sh.${EXT_SO}
ALL_TARGETS+=${TARGET_SH}
${TARGET_SH}: ${OBJ_SH}
${CC} ${LDFLAGS} ${CFLAGS} -o anal_sh.${EXT_SO} ${OBJ_SH}

View File

@ -0,0 +1,387 @@
/* Disassemble SH instructions.
Copyright (C) 1993, 94, 95, 96, 97, 1998 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <stdio.h>
#define STATIC_TABLE
#define DEFINE_TABLE
#include "sh-opc.h"
#include "dis-asm.h"
#define LITTLE_BIT 2
static int
print_insn_shx (memaddr, info)
bfd_vma memaddr;
struct disassemble_info *info;
{
fprintf_ftype fprintf_fn = info->fprintf_func;
void *stream = info->stream;
unsigned char insn[2];
unsigned char nibs[4];
int status;
bfd_vma relmask = ~ (bfd_vma) 0;
sh_opcode_info *op;
status = info->read_memory_func (memaddr, insn, 2, info);
if (status != 0)
{
info->memory_error_func (status, memaddr, info);
return -1;
}
if (info->flags & LITTLE_BIT)
{
nibs[0] = (insn[1] >> 4) & 0xf;
nibs[1] = insn[1] & 0xf;
nibs[2] = (insn[0] >> 4) & 0xf;
nibs[3] = insn[0] & 0xf;
}
else
{
nibs[0] = (insn[0] >> 4) & 0xf;
nibs[1] = insn[0] & 0xf;
nibs[2] = (insn[1] >> 4) & 0xf;
nibs[3] = insn[1] & 0xf;
}
for (op = sh_table; op->name; op++)
{
int n;
int imm = 0;
int rn = 0;
int rm = 0;
int rb = 0;
int disp_pc;
bfd_vma disp_pc_addr = 0;
for (n = 0; n < 4; n++)
{
int i = op->nibbles[n];
if (i < 16)
{
if (nibs[n] == i)
continue;
goto fail;
}
switch (i)
{
case BRANCH_8:
imm = (nibs[2] << 4) | (nibs[3]);
if (imm & 0x80)
imm |= ~0xff;
imm = ((char)imm) * 2 + 4 ;
goto ok;
case BRANCH_12:
imm = ((nibs[1]) << 8) | (nibs[2] << 4) | (nibs[3]);
if (imm & 0x800)
imm |= ~0xfff;
imm = imm * 2 + 4;
goto ok;
case IMM_4:
imm = nibs[3];
goto ok;
case IMM_4BY2:
imm = nibs[3] <<1;
goto ok;
case IMM_4BY4:
imm = nibs[3] <<2;
goto ok;
case IMM_8:
imm = (nibs[2] << 4) | nibs[3];
goto ok;
case PCRELIMM_8BY2:
imm = ((nibs[2] << 4) | nibs[3]) <<1;
relmask = ~ (bfd_vma) 1;
goto ok;
case PCRELIMM_8BY4:
imm = ((nibs[2] << 4) | nibs[3]) <<2;
relmask = ~ (bfd_vma) 3;
goto ok;
case IMM_8BY2:
imm = ((nibs[2] << 4) | nibs[3]) <<1;
goto ok;
case IMM_8BY4:
imm = ((nibs[2] << 4) | nibs[3]) <<2;
goto ok;
case DISP_8:
imm = (nibs[2] << 4) | (nibs[3]);
goto ok;
case DISP_4:
imm = nibs[3];
goto ok;
case REG_N:
rn = nibs[n];
break;
case REG_M:
rm = nibs[n];
break;
case REG_NM:
rn = (nibs[n] & 0xc) >> 2;
rm = (nibs[n] & 0x3);
break;
case REG_B:
rb = nibs[n] & 0x07;
break;
default:
abort();
}
}
ok:
fprintf_fn (stream,"%s\t", op->name);
disp_pc = 0;
for (n = 0; n < 3 && op->arg[n] != A_END; n++)
{
if (n && op->arg[1] != A_END)
fprintf_fn (stream, ",");
switch (op->arg[n])
{
case A_IMM:
fprintf_fn (stream, "#%d", (char)(imm));
break;
case A_R0:
fprintf_fn (stream, "r0");
break;
case A_REG_N:
fprintf_fn (stream, "r%d", rn);
break;
case A_INC_N:
fprintf_fn (stream, "@r%d+", rn);
break;
case A_DEC_N:
fprintf_fn (stream, "@-r%d", rn);
break;
case A_IND_N:
fprintf_fn (stream, "@r%d", rn);
break;
case A_DISP_REG_N:
fprintf_fn (stream, "@(%d,r%d)", imm, rn);
break;
case A_REG_M:
fprintf_fn (stream, "r%d", rm);
break;
case A_INC_M:
fprintf_fn (stream, "@r%d+", rm);
break;
case A_DEC_M:
fprintf_fn (stream, "@-r%d", rm);
break;
case A_IND_M:
fprintf_fn (stream, "@r%d", rm);
break;
case A_DISP_REG_M:
fprintf_fn (stream, "@(%d,r%d)", imm, rm);
break;
case A_REG_B:
fprintf_fn (stream, "r%d_bank", rb);
break;
case A_DISP_PC:
disp_pc = 1;
disp_pc_addr = imm + 4 + (memaddr & relmask);
(*info->print_address_func) (disp_pc_addr, info);
break;
case A_IND_R0_REG_N:
fprintf_fn (stream, "@(r0,r%d)", rn);
break;
case A_IND_R0_REG_M:
fprintf_fn (stream, "@(r0,r%d)", rm);
break;
case A_DISP_GBR:
fprintf_fn (stream, "@(%d,gbr)",imm);
break;
case A_R0_GBR:
fprintf_fn (stream, "@(r0,gbr)");
break;
case A_BDISP12:
case A_BDISP8:
(*info->print_address_func) (imm + memaddr, info);
break;
case A_SR:
fprintf_fn (stream, "sr");
break;
case A_GBR:
fprintf_fn (stream, "gbr");
break;
case A_VBR:
fprintf_fn (stream, "vbr");
break;
case A_SSR:
fprintf_fn (stream, "ssr");
break;
case A_SPC:
fprintf_fn (stream, "spc");
break;
case A_MACH:
fprintf_fn (stream, "mach");
break;
case A_MACL:
fprintf_fn (stream ,"macl");
break;
case A_PR:
fprintf_fn (stream, "pr");
break;
case A_SGR:
fprintf_fn (stream, "sgr");
break;
case A_DBR:
fprintf_fn (stream, "dbr");
break;
case FD_REG_N:
if (0)
goto d_reg_n;
case F_REG_N:
fprintf_fn (stream, "fr%d", rn);
break;
case F_REG_M:
fprintf_fn (stream, "fr%d", rm);
break;
case DX_REG_N:
if (rn & 1)
{
fprintf_fn (stream, "xd%d", rn & ~1);
break;
}
d_reg_n:
case D_REG_N:
fprintf_fn (stream, "dr%d", rn);
break;
case DX_REG_M:
if (rm & 1)
{
fprintf_fn (stream, "xd%d", rm & ~1);
break;
}
case D_REG_M:
fprintf_fn (stream, "dr%d", rm);
break;
case FPSCR_M:
case FPSCR_N:
fprintf_fn (stream, "fpscr");
break;
case FPUL_M:
case FPUL_N:
fprintf_fn (stream, "fpul");
break;
case F_FR0:
fprintf_fn (stream, "fr0");
break;
case V_REG_N:
fprintf_fn (stream, "fv%d", rn*4);
break;
case V_REG_M:
fprintf_fn (stream, "fv%d", rm*4);
break;
case XMTRX_M4:
fprintf_fn (stream, "xmtrx");
break;
default:
abort();
}
}
#if 0
/* This code prints instructions in delay slots on the same line
as the instruction which needs the delay slots. This can be
confusing, since other disassembler don't work this way, and
it means that the instructions are not all in a line. So I
disabled it. Ian. */
if (!(info->flags & 1)
&& (op->name[0] == 'j'
|| (op->name[0] == 'b'
&& (op->name[1] == 'r'
|| op->name[1] == 's'))
|| (op->name[0] == 'r' && op->name[1] == 't')
|| (op->name[0] == 'b' && op->name[2] == '.')))
{
info->flags |= 1;
fprintf_fn (stream, "\t(slot ");
print_insn_shx (memaddr + 2, info);
info->flags &= ~1;
fprintf_fn (stream, ")");
return 4;
}
#endif
if (disp_pc && strcmp (op->name, "mova") != 0)
{
int size;
bfd_byte bytes[4];
if (relmask == ~ (bfd_vma) 1)
size = 2;
else
size = 4;
status = info->read_memory_func (disp_pc_addr, bytes, size, info);
if (status == 0)
{
unsigned int val;
if (size == 2)
{
if ((info->flags & LITTLE_BIT) != 0)
val = bfd_getl16 (bytes);
else
val = bfd_getb16 (bytes);
}
else
{
if ((info->flags & LITTLE_BIT) != 0)
val = bfd_getl32 (bytes);
else
val = bfd_getb32 (bytes);
}
fprintf_fn (stream, "\t! 0x%x", val);
}
}
return 2;
fail:
;
}
fprintf_fn (stream, ".word 0x%x%x%x%x", nibs[0], nibs[1], nibs[2], nibs[3]);
return 2;
}
int
print_insn_shl (memaddr, info)
bfd_vma memaddr;
struct disassemble_info *info;
{
int r;
info->flags = LITTLE_BIT;
r = print_insn_shx (memaddr, info);
return r;
}
int
print_insn_sh (memaddr, info)
bfd_vma memaddr;
struct disassemble_info *info;
{
int r;
info->flags = 0;
r = print_insn_shx (memaddr, info);
return r;
}

View File

@ -0,0 +1,11 @@
p/../arch/sh/gnu/sh-dis.o: p/../arch/sh/gnu/sh-dis.c /usr/include/stdio.h \
/usr/include/features.h /usr/include/bits/predefs.h \
/usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
/usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
/usr/lib/gcc/i486-linux-gnu/4.4.3/include/stddef.h \
/usr/include/bits/types.h /usr/include/bits/typesizes.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/i486-linux-gnu/4.4.3/include/stdarg.h \
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
p/../arch/sh/gnu/sh-opc.h arch/include/dis-asm.h arch/include/mybfd.h \
arch/include/ansidecl.h arch/include/symcat.h

View File

@ -0,0 +1,573 @@
/* Definitions for SH opcodes.
Copyright (C) 1993, 94, 95, 96, 1997 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that 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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
typedef enum {
HEX_0,
HEX_1,
HEX_2,
HEX_3,
HEX_4,
HEX_5,
HEX_6,
HEX_7,
HEX_8,
HEX_9,
HEX_A,
HEX_B,
HEX_C,
HEX_D,
HEX_E,
HEX_F,
REG_N,
REG_M,
REG_NM,
REG_B,
BRANCH_12,
BRANCH_8,
DISP_8,
DISP_4,
IMM_4,
IMM_4BY2,
IMM_4BY4,
PCRELIMM_8BY2,
PCRELIMM_8BY4,
IMM_8,
IMM_8BY2,
IMM_8BY4
} sh_nibble_type;
typedef enum {
A_END,
A_BDISP12,
A_BDISP8,
A_DEC_M,
A_DEC_N,
A_DISP_GBR,
A_DISP_PC,
A_DISP_REG_M,
A_DISP_REG_N,
A_GBR,
A_IMM,
A_INC_M,
A_INC_N,
A_IND_M,
A_IND_N,
A_IND_R0_REG_M,
A_IND_R0_REG_N,
A_MACH,
A_MACL,
A_PR,
A_R0,
A_R0_GBR,
A_REG_M,
A_REG_N,
A_REG_B,
A_SR,
A_VBR,
A_SSR,
A_SPC,
A_SGR,
A_DBR,
F_REG_N,
F_REG_M,
D_REG_N,
D_REG_M,
X_REG_N, /* Only used for argument parsing */
X_REG_M, /* Only used for argument parsing */
DX_REG_N,
DX_REG_M,
V_REG_N,
V_REG_M,
FD_REG_N,
XMTRX_M4,
F_FR0,
FPUL_N,
FPUL_M,
FPSCR_N,
FPSCR_M
} sh_arg_type;
typedef struct {
char *name;
sh_arg_type arg[4];
sh_nibble_type nibbles[4];
} sh_opcode_info;
#ifdef DEFINE_TABLE
sh_opcode_info sh_table[] = {
/* 0111nnnni8*1.... add #<imm>,<REG_N> */{"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM_8}},
/* 0011nnnnmmmm1100 add <REG_M>,<REG_N> */{"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}},
/* 0011nnnnmmmm1110 addc <REG_M>,<REG_N>*/{"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}},
/* 0011nnnnmmmm1111 addv <REG_M>,<REG_N>*/{"addv",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_F}},
/* 11001001i8*1.... and #<imm>,R0 */{"and",{A_IMM,A_R0},{HEX_C,HEX_9,IMM_8}},
/* 0010nnnnmmmm1001 and <REG_M>,<REG_N> */{"and",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_9}},
/* 11001101i8*1.... and.b #<imm>,@(R0,GBR)*/{"and.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_D,IMM_8}},
/* 1010i12......... bra <bdisp12> */{"bra",{A_BDISP12},{HEX_A,BRANCH_12}},
/* 1011i12......... bsr <bdisp12> */{"bsr",{A_BDISP12},{HEX_B,BRANCH_12}},
/* 10001001i8p1.... bt <bdisp8> */{"bt",{A_BDISP8},{HEX_8,HEX_9,BRANCH_8}},
/* 10001011i8p1.... bf <bdisp8> */{"bf",{A_BDISP8},{HEX_8,HEX_B,BRANCH_8}},
/* 10001101i8p1.... bt.s <bdisp8> */{"bt.s",{A_BDISP8},{HEX_8,HEX_D,BRANCH_8}},
/* 10001101i8p1.... bt/s <bdisp8> */{"bt/s",{A_BDISP8},{HEX_8,HEX_D,BRANCH_8}},
/* 10001111i8p1.... bf.s <bdisp8> */{"bf.s",{A_BDISP8},{HEX_8,HEX_F,BRANCH_8}},
/* 10001111i8p1.... bf/s <bdisp8> */{"bf/s",{A_BDISP8},{HEX_8,HEX_F,BRANCH_8}},
/* 0000000000101000 clrmac */{"clrmac",{0},{HEX_0,HEX_0,HEX_2,HEX_8}},
/* 0000000001001000 clrs */{"clrs",{0},{HEX_0,HEX_0,HEX_4,HEX_8}},
/* 0000000000001000 clrt */{"clrt",{0},{HEX_0,HEX_0,HEX_0,HEX_8}},
/* 10001000i8*1.... cmp/eq #<imm>,R0 */{"cmp/eq",{A_IMM,A_R0},{HEX_8,HEX_8,IMM_8}},
/* 0011nnnnmmmm0000 cmp/eq <REG_M>,<REG_N>*/{"cmp/eq",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_0}},
/* 0011nnnnmmmm0011 cmp/ge <REG_M>,<REG_N>*/{"cmp/ge",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_3}},
/* 0011nnnnmmmm0111 cmp/gt <REG_M>,<REG_N>*/{"cmp/gt",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_7}},
/* 0011nnnnmmmm0110 cmp/hi <REG_M>,<REG_N>*/{"cmp/hi",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_6}},
/* 0011nnnnmmmm0010 cmp/hs <REG_M>,<REG_N>*/{"cmp/hs",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_2}},
/* 0100nnnn00010101 cmp/pl <REG_N> */{"cmp/pl",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_5}},
/* 0100nnnn00010001 cmp/pz <REG_N> */{"cmp/pz",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_1}},
/* 0010nnnnmmmm1100 cmp/str <REG_M>,<REG_N>*/{"cmp/str",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_C}},
/* 0010nnnnmmmm0111 div0s <REG_M>,<REG_N>*/{"div0s",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_7}},
/* 0000000000011001 div0u */{"div0u",{0},{HEX_0,HEX_0,HEX_1,HEX_9}},
/* 0011nnnnmmmm0100 div1 <REG_M>,<REG_N>*/{"div1",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_4}},
/* 0110nnnnmmmm1110 exts.b <REG_M>,<REG_N>*/{"exts.b",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_E}},
/* 0110nnnnmmmm1111 exts.w <REG_M>,<REG_N>*/{"exts.w",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_F}},
/* 0110nnnnmmmm1100 extu.b <REG_M>,<REG_N>*/{"extu.b",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_C}},
/* 0110nnnnmmmm1101 extu.w <REG_M>,<REG_N>*/{"extu.w",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_D}},
/* 0100nnnn00101011 jmp @<REG_N> */{"jmp",{A_IND_N},{HEX_4,REG_N,HEX_2,HEX_B}},
/* 0100nnnn00001011 jsr @<REG_N> */{"jsr",{A_IND_N},{HEX_4,REG_N,HEX_0,HEX_B}},
/* 0100nnnn00001110 ldc <REG_N>,SR */{"ldc",{A_REG_N,A_SR},{HEX_4,REG_N,HEX_0,HEX_E}},
/* 0100nnnn00011110 ldc <REG_N>,GBR */{"ldc",{A_REG_N,A_GBR},{HEX_4,REG_N,HEX_1,HEX_E}},
/* 0100nnnn00101110 ldc <REG_N>,VBR */{"ldc",{A_REG_N,A_VBR},{HEX_4,REG_N,HEX_2,HEX_E}},
/* 0100nnnn00111110 ldc <REG_N>,SSR */{"ldc",{A_REG_N,A_SSR},{HEX_4,REG_N,HEX_3,HEX_E}},
/* 0100nnnn01001110 ldc <REG_N>,SPC */{"ldc",{A_REG_N,A_SPC},{HEX_4,REG_N,HEX_4,HEX_E}},
/* 0100nnnn01111110 ldc <REG_N>,DBR */{"ldc",{A_REG_N,A_DBR},{HEX_4,REG_N,HEX_7,HEX_E}},
/* 0100nnnn1xxx1110 ldc <REG_N>,Rn_BANK */{"ldc",{A_REG_N,A_REG_B},{HEX_4,REG_N,REG_B,HEX_E}},
/* 0100nnnn00000111 ldc.l @<REG_N>+,SR */{"ldc.l",{A_INC_N,A_SR},{HEX_4,REG_N,HEX_0,HEX_7}},
/* 0100nnnn00010111 ldc.l @<REG_N>+,GBR */{"ldc.l",{A_INC_N,A_GBR},{HEX_4,REG_N,HEX_1,HEX_7}},
/* 0100nnnn00100111 ldc.l @<REG_N>+,VBR */{"ldc.l",{A_INC_N,A_VBR},{HEX_4,REG_N,HEX_2,HEX_7}},
/* 0100nnnn00110111 ldc.l @<REG_N>+,SSR */{"ldc.l",{A_INC_N,A_SSR},{HEX_4,REG_N,HEX_3,HEX_7}},
/* 0100nnnn01000111 ldc.l @<REG_N>+,SPC */{"ldc.l",{A_INC_N,A_SPC},{HEX_4,REG_N,HEX_4,HEX_7}},
/* 0100nnnn01110111 ldc.l @<REG_N>+,DBR */{"ldc.l",{A_INC_N,A_DBR},{HEX_4,REG_N,HEX_7,HEX_7}},
/* 0100nnnn1xxx0111 ldc.l <REG_N>,Rn_BANK */{"ldc.l",{A_INC_N,A_REG_B},{HEX_4,REG_N,REG_B,HEX_7}},
/* 0100nnnn00001010 lds <REG_N>,MACH */{"lds",{A_REG_N,A_MACH},{HEX_4,REG_N,HEX_0,HEX_A}},
/* 0100nnnn00011010 lds <REG_N>,MACL */{"lds",{A_REG_N,A_MACL},{HEX_4,REG_N,HEX_1,HEX_A}},
/* 0100nnnn00101010 lds <REG_N>,PR */{"lds",{A_REG_N,A_PR},{HEX_4,REG_N,HEX_2,HEX_A}},
/* 0100nnnn01011010 lds <REG_N>,FPUL */{"lds",{A_REG_M,FPUL_N},{HEX_4,REG_M,HEX_5,HEX_A}},
/* 0100nnnn01101010 lds <REG_M>,FPSCR */{"lds",{A_REG_M,FPSCR_N},{HEX_4,REG_M,HEX_6,HEX_A}},
/* 0100nnnn00000110 lds.l @<REG_N>+,MACH*/{"lds.l",{A_INC_N,A_MACH},{HEX_4,REG_N,HEX_0,HEX_6}},
/* 0100nnnn00010110 lds.l @<REG_N>+,MACL*/{"lds.l",{A_INC_N,A_MACL},{HEX_4,REG_N,HEX_1,HEX_6}},
/* 0100nnnn00100110 lds.l @<REG_N>+,PR */{"lds.l",{A_INC_N,A_PR},{HEX_4,REG_N,HEX_2,HEX_6}},
/* 0100nnnn01010110 lds.l @<REG_M>+,FPUL*/{"lds.l",{A_INC_M,FPUL_N},{HEX_4,REG_M,HEX_5,HEX_6}},
/* 0100nnnn01100110 lds.l @<REG_M>+,FPSCR*/{"lds.l",{A_INC_M,FPSCR_N},{HEX_4,REG_M,HEX_6,HEX_6}},
/* 0000000000111000 ldtlb */{"ldtlb",{0},{HEX_0,HEX_0,HEX_3,HEX_8}},
/* 0100nnnnmmmm1111 mac.w @<REG_M>+,@<REG_N>+*/{"mac.w",{A_INC_M,A_INC_N},{HEX_4,REG_N,REG_M,HEX_F}},
/* 1110nnnni8*1.... mov #<imm>,<REG_N> */{"mov",{A_IMM,A_REG_N},{HEX_E,REG_N,IMM_8}},
/* 0110nnnnmmmm0011 mov <REG_M>,<REG_N> */{"mov",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_3}},
/* 0000nnnnmmmm0100 mov.b <REG_M>,@(R0,<REG_N>)*/{"mov.b",{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_4}},
/* 0010nnnnmmmm0100 mov.b <REG_M>,@-<REG_N>*/{"mov.b",{ A_REG_M,A_DEC_N},{HEX_2,REG_N,REG_M,HEX_4}},
/* 0010nnnnmmmm0000 mov.b <REG_M>,@<REG_N>*/{"mov.b",{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_0}},
/* 10000100mmmmi4*1 mov.b @(<disp>,<REG_M>),R0*/{"mov.b",{A_DISP_REG_M,A_R0},{HEX_8,HEX_4,REG_M,IMM_4}},
/* 11000100i8*1.... mov.b @(<disp>,GBR),R0*/{"mov.b",{A_DISP_GBR,A_R0},{HEX_C,HEX_4,IMM_8}},
/* 0000nnnnmmmm1100 mov.b @(R0,<REG_M>),<REG_N>*/{"mov.b",{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_C}},
/* 0110nnnnmmmm0100 mov.b @<REG_M>+,<REG_N>*/{"mov.b",{A_INC_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_4}},
/* 0110nnnnmmmm0000 mov.b @<REG_M>,<REG_N>*/{"mov.b",{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_0}},
/* 10000000mmmmi4*1 mov.b R0,@(<disp>,<REG_M>)*/{"mov.b",{A_R0,A_DISP_REG_M},{HEX_8,HEX_0,REG_M,IMM_4}},
/* 11000000i8*1.... mov.b R0,@(<disp>,GBR)*/{"mov.b",{A_R0,A_DISP_GBR},{HEX_C,HEX_0,IMM_8}},
/* 0001nnnnmmmmi4*4 mov.l <REG_M>,@(<disp>,<REG_N>)*/{"mov.l",{ A_REG_M,A_DISP_REG_N},{HEX_1,REG_N,REG_M,IMM_4BY4}},
/* 0000nnnnmmmm0110 mov.l <REG_M>,@(R0,<REG_N>)*/{"mov.l",{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_6}},
/* 0010nnnnmmmm0110 mov.l <REG_M>,@-<REG_N>*/{"mov.l",{ A_REG_M,A_DEC_N},{HEX_2,REG_N,REG_M,HEX_6}},
/* 0010nnnnmmmm0010 mov.l <REG_M>,@<REG_N>*/{"mov.l",{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_2}},
/* 0101nnnnmmmmi4*4 mov.l @(<disp>,<REG_M>),<REG_N>*/{"mov.l",{A_DISP_REG_M,A_REG_N},{HEX_5,REG_N,REG_M,IMM_4BY4}},
/* 11000110i8*4.... mov.l @(<disp>,GBR),R0*/{"mov.l",{A_DISP_GBR,A_R0},{HEX_C,HEX_6,IMM_8BY4}},
/* 1101nnnni8p4.... mov.l @(<disp>,PC),<REG_N>*/{"mov.l",{A_DISP_PC,A_REG_N},{HEX_D,REG_N,PCRELIMM_8BY4}},
/* 0000nnnnmmmm1110 mov.l @(R0,<REG_M>),<REG_N>*/{"mov.l",{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_E}},
/* 0110nnnnmmmm0110 mov.l @<REG_M>+,<REG_N>*/{"mov.l",{A_INC_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_6}},
/* 0110nnnnmmmm0010 mov.l @<REG_M>,<REG_N>*/{"mov.l",{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_2}},
/* 11000010i8*4.... mov.l R0,@(<disp>,GBR)*/{"mov.l",{A_R0,A_DISP_GBR},{HEX_C,HEX_2,IMM_8BY4}},
/* 0000nnnnmmmm0101 mov.w <REG_M>,@(R0,<REG_N>)*/{"mov.w",{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_5}},
/* 0010nnnnmmmm0101 mov.w <REG_M>,@-<REG_N>*/{"mov.w",{ A_REG_M,A_DEC_N},{HEX_2,REG_N,REG_M,HEX_5}},
/* 0010nnnnmmmm0001 mov.w <REG_M>,@<REG_N>*/{"mov.w",{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_1}},
/* 10000101mmmmi4*2 mov.w @(<disp>,<REG_M>),R0*/{"mov.w",{A_DISP_REG_M,A_R0},{HEX_8,HEX_5,REG_M,IMM_4BY2}},
/* 11000101i8*2.... mov.w @(<disp>,GBR),R0*/{"mov.w",{A_DISP_GBR,A_R0},{HEX_C,HEX_5,IMM_8BY2}},
/* 1001nnnni8p2.... mov.w @(<disp>,PC),<REG_N>*/{"mov.w",{A_DISP_PC,A_REG_N},{HEX_9,REG_N,PCRELIMM_8BY2}},
/* 0000nnnnmmmm1101 mov.w @(R0,<REG_M>),<REG_N>*/{"mov.w",{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_D}},
/* 0110nnnnmmmm0101 mov.w @<REG_M>+,<REG_N>*/{"mov.w",{A_INC_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_5}},
/* 0110nnnnmmmm0001 mov.w @<REG_M>,<REG_N>*/{"mov.w",{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_1}},
/* 10000001mmmmi4*2 mov.w R0,@(<disp>,<REG_M>)*/{"mov.w",{A_R0,A_DISP_REG_M},{HEX_8,HEX_1,REG_M,IMM_4BY2}},
/* 11000001i8*2.... mov.w R0,@(<disp>,GBR)*/{"mov.w",{A_R0,A_DISP_GBR},{HEX_C,HEX_1,IMM_8BY2}},
/* 11000111i8p4.... mova @(<disp>,PC),R0*/{"mova",{A_DISP_PC,A_R0},{HEX_C,HEX_7,PCRELIMM_8BY4}},
/* 0000nnnn11000011 movca.l R0,@<REG_N> */{"movca.l",{A_R0,A_IND_N},{HEX_0,REG_N,HEX_C,HEX_3}},
/* 0000nnnn00101001 movt <REG_N> */{"movt",{A_REG_N},{HEX_0,REG_N,HEX_2,HEX_9}},
/* 0010nnnnmmmm1111 muls <REG_M>,<REG_N>*/{"muls",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_F}},
/* 0000nnnnmmmm0111 mul.l <REG_M>,<REG_N>*/{"mul.l",{ A_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_7}},
/* 0010nnnnmmmm1110 mulu <REG_M>,<REG_N>*/{"mulu",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_E}},
/* 0110nnnnmmmm1011 neg <REG_M>,<REG_N> */{"neg",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_B}},
/* 0110nnnnmmmm1010 negc <REG_M>,<REG_N>*/{"negc",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_A}},
/* 0000000000001001 nop */{"nop",{0},{HEX_0,HEX_0,HEX_0,HEX_9}},
/* 0110nnnnmmmm0111 not <REG_M>,<REG_N> */{"not",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_7}},
/* 0000nnnn10010011 ocbi @<REG_N> */{"ocbi",{A_IND_N},{HEX_0,REG_N,HEX_9,HEX_3}},
/* 0000nnnn10100011 ocbp @<REG_N> */{"ocbp",{A_IND_N},{HEX_0,REG_N,HEX_A,HEX_3}},
/* 0000nnnn10110011 ocbwb @<REG_N> */{"ocbwb",{A_IND_N},{HEX_0,REG_N,HEX_B,HEX_3}},
/* 11001011i8*1.... or #<imm>,R0 */{"or",{A_IMM,A_R0},{HEX_C,HEX_B,IMM_8}},
/* 0010nnnnmmmm1011 or <REG_M>,<REG_N> */{"or",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_B}},
/* 11001111i8*1.... or.b #<imm>,@(R0,GBR)*/{"or.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_F,IMM_8}},
/* 0000nnnn10000011 pref @<REG_N> */{"pref",{A_IND_N},{HEX_0,REG_N,HEX_8,HEX_3}},
/* 0100nnnn00100100 rotcl <REG_N> */{"rotcl",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_4}},
/* 0100nnnn00100101 rotcr <REG_N> */{"rotcr",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_5}},
/* 0100nnnn00000100 rotl <REG_N> */{"rotl",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_4}},
/* 0100nnnn00000101 rotr <REG_N> */{"rotr",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_5}},
/* 0000000000101011 rte */{"rte",{0},{HEX_0,HEX_0,HEX_2,HEX_B}},
/* 0000000000001011 rts */{"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}},
/* 0000000001011000 sets */{"sets",{0},{HEX_0,HEX_0,HEX_5,HEX_8}},
/* 0000000000011000 sett */{"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}},
/* 0100nnnnmmmm1100 shad <REG_M>,<REG_N>*/{"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}},
/* 0100nnnnmmmm1101 shld <REG_M>,<REG_N>*/{"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}},
/* 0100nnnn00100000 shal <REG_N> */{"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}},
/* 0100nnnn00100001 shar <REG_N> */{"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}},
/* 0100nnnn00000000 shll <REG_N> */{"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}},
/* 0100nnnn00101000 shll16 <REG_N> */{"shll16",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_8}},
/* 0100nnnn00001000 shll2 <REG_N> */{"shll2",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_8}},
/* 0100nnnn00011000 shll8 <REG_N> */{"shll8",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_8}},
/* 0100nnnn00000001 shlr <REG_N> */{"shlr",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_1}},
/* 0100nnnn00101001 shlr16 <REG_N> */{"shlr16",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_9}},
/* 0100nnnn00001001 shlr2 <REG_N> */{"shlr2",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_9}},
/* 0100nnnn00011001 shlr8 <REG_N> */{"shlr8",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_9}},
/* 0000000000011011 sleep */{"sleep",{0},{HEX_0,HEX_0,HEX_1,HEX_B}},
/* 0000nnnn00000010 stc SR,<REG_N> */{"stc",{A_SR,A_REG_N},{HEX_0,REG_N,HEX_0,HEX_2}},
/* 0000nnnn00010010 stc GBR,<REG_N> */{"stc",{A_GBR,A_REG_N},{HEX_0,REG_N,HEX_1,HEX_2}},
/* 0000nnnn00100010 stc VBR,<REG_N> */{"stc",{A_VBR,A_REG_N},{HEX_0,REG_N,HEX_2,HEX_2}},
/* 0000nnnn00110010 stc SSR,<REG_N> */{"stc",{A_SSR,A_REG_N},{HEX_0,REG_N,HEX_3,HEX_2}},
/* 0000nnnn01000010 stc SPC,<REG_N> */{"stc",{A_SPC,A_REG_N},{HEX_0,REG_N,HEX_4,HEX_2}},
/* 0000nnnn01100010 stc SGR,<REG_N> */{"stc",{A_SGR,A_REG_N},{HEX_0,REG_N,HEX_6,HEX_2}},
/* 0000nnnn01110010 stc DBR,<REG_N> */{"stc",{A_DBR,A_REG_N},{HEX_0,REG_N,HEX_7,HEX_2}},
/* 0000nnnn1xxx0012 stc Rn_BANK,<REG_N> */{"stc",{A_REG_B,A_REG_N},{HEX_0,REG_N,REG_B,HEX_2}},
/* 0100nnnn00000011 stc.l SR,@-<REG_N> */{"stc.l",{A_SR,A_DEC_N},{HEX_4,REG_N,HEX_0,HEX_3}},
/* 0100nnnn00010011 stc.l GBR,@-<REG_N> */{"stc.l",{A_GBR,A_DEC_N},{HEX_4,REG_N,HEX_1,HEX_3}},
/* 0100nnnn00100011 stc.l VBR,@-<REG_N> */{"stc.l",{A_VBR,A_DEC_N},{HEX_4,REG_N,HEX_2,HEX_3}},
/* 0100nnnn00110011 stc.l SSR,@-<REG_N> */{"stc.l",{A_SSR,A_DEC_N},{HEX_4,REG_N,HEX_3,HEX_3}},
/* 0100nnnn01000011 stc.l SPC,@-<REG_N> */{"stc.l",{A_SPC,A_DEC_N},{HEX_4,REG_N,HEX_4,HEX_3}},
/* 0100nnnn01100011 stc.l SGR,@-<REG_N> */{"stc.l",{A_SGR,A_DEC_N},{HEX_4,REG_N,HEX_6,HEX_3}},
/* 0100nnnn01110011 stc.l DBR,@-<REG_N> */{"stc.l",{A_DBR,A_DEC_N},{HEX_4,REG_N,HEX_7,HEX_3}},
/* 0100nnnn1xxx0012 stc.l Rn_BANK,@-<REG_N> */{"stc.l",{A_REG_B,A_DEC_N},{HEX_4,REG_N,REG_B,HEX_3}},
/* 0000nnnn00001010 sts MACH,<REG_N> */{"sts",{A_MACH,A_REG_N},{HEX_0,REG_N,HEX_0,HEX_A}},
/* 0000nnnn00011010 sts MACL,<REG_N> */{"sts",{A_MACL,A_REG_N},{HEX_0,REG_N,HEX_1,HEX_A}},
/* 0000nnnn00101010 sts PR,<REG_N> */{"sts",{A_PR,A_REG_N},{HEX_0,REG_N,HEX_2,HEX_A}},
/* 0000nnnn01011010 sts FPUL,<REG_N> */{"sts",{FPUL_M,A_REG_N},{HEX_0,REG_N,HEX_5,HEX_A}},
/* 0000nnnn01101010 sts FPSCR,<REG_N> */{"sts",{FPSCR_M,A_REG_N},{HEX_0,REG_N,HEX_6,HEX_A}},
/* 0100nnnn00000010 sts.l MACH,@-<REG_N>*/{"sts.l",{A_MACH,A_DEC_N},{HEX_4,REG_N,HEX_0,HEX_2}},
/* 0100nnnn00010010 sts.l MACL,@-<REG_N>*/{"sts.l",{A_MACL,A_DEC_N},{HEX_4,REG_N,HEX_1,HEX_2}},
/* 0100nnnn00100010 sts.l PR,@-<REG_N> */{"sts.l",{A_PR,A_DEC_N},{HEX_4,REG_N,HEX_2,HEX_2}},
/* 0100nnnn01010010 sts.l FPUL,@-<REG_N>*/{"sts.l",{FPUL_M,A_DEC_N},{HEX_4,REG_N,HEX_5,HEX_2}},
/* 0100nnnn01100010 sts.l FPSCR,@-<REG_N>*/{"sts.l",{FPSCR_M,A_DEC_N},{HEX_4,REG_N,HEX_6,HEX_2}},
/* 0011nnnnmmmm1000 sub <REG_M>,<REG_N> */{"sub",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_8}},
/* 0011nnnnmmmm1010 subc <REG_M>,<REG_N>*/{"subc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_A}},
/* 0011nnnnmmmm1011 subv <REG_M>,<REG_N>*/{"subv",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_B}},
/* 0110nnnnmmmm1000 swap.b <REG_M>,<REG_N>*/{"swap.b",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_8}},
/* 0110nnnnmmmm1001 swap.w <REG_M>,<REG_N>*/{"swap.w",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_9}},
/* 0100nnnn00011011 tas.b @<REG_N> */{"tas.b",{A_IND_N},{HEX_4,REG_N,HEX_1,HEX_B}},
/* 11000011i8*1.... trapa #<imm> */{"trapa",{A_IMM},{HEX_C,HEX_3,IMM_8}},
/* 11001000i8*1.... tst #<imm>,R0 */{"tst",{A_IMM,A_R0},{HEX_C,HEX_8,IMM_8}},
/* 0010nnnnmmmm1000 tst <REG_M>,<REG_N> */{"tst",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_8}},
/* 11001100i8*1.... tst.b #<imm>,@(R0,GBR)*/{"tst.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_C,IMM_8}},
/* 11001010i8*1.... xor #<imm>,R0 */{"xor",{A_IMM,A_R0},{HEX_C,HEX_A,IMM_8}},
/* 0010nnnnmmmm1010 xor <REG_M>,<REG_N> */{"xor",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_A}},
/* 11001110i8*1.... xor.b #<imm>,@(R0,GBR)*/{"xor.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_E,IMM_8}},
/* 0010nnnnmmmm1101 xtrct <REG_M>,<REG_N>*/{"xtrct",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_D}},
/* 0000nnnnmmmm0111 mul.l <REG_M>,<REG_N>*/{"mul.l",{ A_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_7}},
/* 0100nnnn00010000 dt <REG_N> */{"dt",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_0}},
/* 0011nnnnmmmm1101 dmuls.l <REG_M>,<REG_N>*/{"dmuls.l",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_D}},
/* 0011nnnnmmmm0101 dmulu.l <REG_M>,<REG_N>*/{"dmulu.l",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_5}},
/* 0000nnnnmmmm1111 mac.l @<REG_M>+,@<REG_N>+*/{"mac.l",{A_INC_M,A_INC_N},{HEX_0,REG_N,REG_M,HEX_F}},
/* 0000nnnn00100011 braf <REG_N> */{"braf",{A_REG_N},{HEX_0,REG_N,HEX_2,HEX_3}},
/* 0000nnnn00000011 bsrf <REG_N> */{"bsrf",{A_REG_N},{HEX_0,REG_N,HEX_0,HEX_3}},
/* 1111nnnn01011101 fabs <F_REG_N> */{"fabs",{FD_REG_N},{HEX_F,REG_N,HEX_5,HEX_D}},
/* 1111nnnnmmmm0000 fadd <F_REG_M>,<F_REG_N>*/{"fadd",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_0}},
/* 1111nnn0mmm00000 fadd <D_REG_M>,<D_REG_N>*/{"fadd",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_0}},
/* 1111nnnnmmmm0100 fcmp/eq <F_REG_M>,<F_REG_N>*/{"fcmp/eq",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_4}},
/* 1111nnn0mmm00100 fcmp/eq <D_REG_M>,<D_REG_N>*/{"fcmp/eq",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_4}},
/* 1111nnnnmmmm0101 fcmp/gt <F_REG_M>,<F_REG_N>*/{"fcmp/gt",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_5}},
/* 1111nnn0mmm00101 fcmp/gt <D_REG_M>,<D_REG_N>*/{"fcmp/gt",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_5}},
/* 1111nnn010111101 fcnvds <D_REG_N>,FPUL*/{"fcnvds",{D_REG_N,FPUL_M},{HEX_F,REG_N,HEX_B,HEX_D}},
/* 1111nnn010101101 fcnvsd FPUL,<D_REG_N>*/{"fcnvsd",{FPUL_M,D_REG_N},{HEX_F,REG_N,HEX_A,HEX_D}},
/* 1111nnnnmmmm0011 fdiv <F_REG_M>,<F_REG_N>*/{"fdiv",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_3}},
/* 1111nnn0mmm00011 fdiv <D_REG_M>,<D_REG_N>*/{"fdiv",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_3}},
/* 1111nnmm11101101 fipr <V_REG_M>,<V_REG_N>*/{"fipr",{V_REG_M,V_REG_N},{HEX_F,REG_NM,HEX_E,HEX_D}},
/* 1111nnnn10001101 fldi0 <F_REG_N> */{"fldi0",{F_REG_N},{HEX_F,REG_N,HEX_8,HEX_D}},
/* 1111nnnn10011101 fldi1 <F_REG_N> */{"fldi1",{F_REG_N},{HEX_F,REG_N,HEX_9,HEX_D}},
/* 1111nnnn00011101 flds <F_REG_N>,FPUL*/{"flds",{F_REG_N,FPUL_M},{HEX_F,REG_N,HEX_1,HEX_D}},
/* 1111nnnn00101101 float FPUL,<FD_REG_N>*/{"float",{FPUL_M,FD_REG_N},{HEX_F,REG_N,HEX_2,HEX_D}},
/* 1111nnnnmmmm1110 fmac FR0,<F_REG_M>,<F_REG_N>*/{"fmac",{F_FR0,F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_E}},
/* 1111nnnnmmmm1100 fmov <F_REG_M>,<F_REG_N>*/{"fmov",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_C}},
/* 1111nnnnmmmm1100 fmov <DX_REG_M>,<DX_REG_N>*/{"fmov",{DX_REG_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_C}},
/* 1111nnnnmmmm1000 fmov @<REG_M>,<F_REG_N>*/{"fmov",{A_IND_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_8}},
/* 1111nnnnmmmm1000 fmov @<REG_M>,<DX_REG_N>*/{"fmov",{A_IND_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_8}},
/* 1111nnnnmmmm1010 fmov <F_REG_M>,@<REG_N>*/{"fmov",{F_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}},
/* 1111nnnnmmmm1010 fmov <DX_REG_M>,@<REG_N>*/{"fmov",{DX_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}},
/* 1111nnnnmmmm1001 fmov @<REG_M>+,<F_REG_N>*/{"fmov",{A_INC_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_9}},
/* 1111nnnnmmmm1001 fmov @<REG_M>+,<DX_REG_N>*/{"fmov",{A_INC_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_9}},
/* 1111nnnnmmmm1011 fmov <F_REG_M>,@-<REG_N>*/{"fmov",{F_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}},
/* 1111nnnnmmmm1011 fmov <DX_REG_M>,@-<REG_N>*/{"fmov",{DX_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}},
/* 1111nnnnmmmm0110 fmov @(R0,<REG_M>),<F_REG_N>*/{"fmov",{A_IND_R0_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_6}},
/* 1111nnnnmmmm0110 fmov @(R0,<REG_M>),<DX_REG_N>*/{"fmov",{A_IND_R0_REG_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_6}},
/* 1111nnnnmmmm0111 fmov <F_REG_M>,@(R0,<REG_N>)*/{"fmov",{F_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}},
/* 1111nnnnmmmm0111 fmov <DX_REG_M>,@(R0,<REG_N>)*/{"fmov",{DX_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}},
/* 1111nnnnmmmm1000 fmov.d @<REG_M>,<DX_REG_N>*/{"fmov.d",{A_IND_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_8}},
/* 1111nnnnmmmm1010 fmov.d <DX_REG_M>,@<REG_N>*/{"fmov.d",{DX_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}},
/* 1111nnnnmmmm1001 fmov.d @<REG_M>+,<DX_REG_N>*/{"fmov.d",{A_INC_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_9}},
/* 1111nnnnmmmm1011 fmov.d <DX_REG_M>,@-<REG_N>*/{"fmov.d",{DX_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}},
/* 1111nnnnmmmm0110 fmov.d @(R0,<REG_M>),<DX_REG_N>*/{"fmov.d",{A_IND_R0_REG_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_6}},
/* 1111nnnnmmmm0111 fmov.d <DX_REG_M>,@(R0,<REG_N>)*/{"fmov.d",{DX_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}},
/* 1111nnnnmmmm1000 fmov.s @<REG_M>,<F_REG_N>*/{"fmov.s",{A_IND_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_8}},
/* 1111nnnnmmmm1010 fmov.s <F_REG_M>,@<REG_N>*/{"fmov.s",{F_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}},
/* 1111nnnnmmmm1001 fmov.s @<REG_M>+,<F_REG_N>*/{"fmov.s",{A_INC_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_9}},
/* 1111nnnnmmmm1011 fmov.s <F_REG_M>,@-<REG_N>*/{"fmov.s",{F_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}},
/* 1111nnnnmmmm0110 fmov.s @(R0,<REG_M>),<F_REG_N>*/{"fmov.s",{A_IND_R0_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_6}},
/* 1111nnnnmmmm0111 fmov.s <F_REG_M>,@(R0,<REG_N>)*/{"fmov.s",{F_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}},
/* 1111nnnnmmmm0010 fmul <F_REG_M>,<F_REG_N>*/{"fmul",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_2}},
/* 1111nnn0mmm00010 fmul <D_REG_M>,<D_REG_N>*/{"fmul",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_2}},
/* 1111nnnn01001101 fneg <FD_REG_N> */{"fneg",{FD_REG_N},{HEX_F,REG_N,HEX_4,HEX_D}},
/* 1111101111111101 frchg */{"frchg",{0},{HEX_F,HEX_B,HEX_F,HEX_D}},
/* 1111001111111101 fschg */{"fschg",{0},{HEX_F,HEX_3,HEX_F,HEX_D}},
/* 1111nnnn01101101 fsqrt <FD_REG_N> */{"fsqrt",{FD_REG_N},{HEX_F,REG_N,HEX_6,HEX_D}},
/* 1111nnnn00001101 fsts FPUL,<F_REG_N>*/{"fsts",{FPUL_M,F_REG_N},{HEX_F,REG_N,HEX_0,HEX_D}},
/* 1111nnnnmmmm0001 fsub <F_REG_M>,<F_REG_N>*/{"fsub",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_1}},
/* 1111nnn0mmm00001 fsub <D_REG_M>,<D_REG_N>*/{"fsub",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_1}},
/* 1111nnnn00111101 ftrc <FD_REG_N>,FPUL*/{"ftrc",{FD_REG_N,FPUL_M},{HEX_F,REG_N,HEX_3,HEX_D}},
/* 1111nn0111111101 ftrv XMTRX_M4,<V_REG_n>*/{"ftrv",{XMTRX_M4,V_REG_N},{HEX_F,REG_NM,HEX_F,HEX_D}},
{ 0 }
};
#endif

View File

@ -12,7 +12,7 @@ ALL_TARGETS=
# TODO: rename to enabled plugins
ARCHS=mips.mk sparc.mk java.mk bf.mk arm.mk dalvik.mk
ARCHS+=ppc.mk x86_olly.mk x86.mk csr.mk x86_nasm.mk psosvm.mk avr.mk
ARCHS+=msil.mk
ARCHS+=msil.mk sh.mk
include $(ARCHS)
all: ${ALL_TARGETS}

92
libr/asm/p/asm_sh.c Normal file
View File

@ -0,0 +1,92 @@
/* radare - GPL3 - Copyright 2010-2011 eloi<limited-entropy.com> */
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <r_types.h>
#include <r_lib.h>
#include <r_util.h>
#include <r_asm.h>
#include "dis-asm.h"
static unsigned long Offset = 0;
static char *buf_global = NULL;
static unsigned char bytes[2];
static int sh_buffer_read_memory (bfd_vma memaddr, bfd_byte *myaddr, unsigned int length, struct disassemble_info *info) {
memcpy (myaddr, bytes, length);
return 0;
}
static int symbol_at_address(bfd_vma addr, struct disassemble_info * info) {
return 0;
}
static void memory_error_func(int status, bfd_vma memaddr, struct disassemble_info *info) {
//--
}
static void print_address(bfd_vma address, struct disassemble_info *info) {
char tmp[32];
if (buf_global == NULL)
return;
sprintf (tmp, "0x%08"PFMT64x"", (ut64)address);
strcat (buf_global, tmp);
}
static int buf_fprintf(void *stream, const char *format, ...) {
va_list ap;
char *tmp;
if (buf_global == NULL)
return 0;
va_start (ap, format);
tmp = alloca (strlen (format)+strlen (buf_global)+2);
sprintf (tmp, "%s%s", buf_global, format);
vsprintf (buf_global, tmp, ap);
va_end (ap);
return 0;
}
static int disassemble(RAsm *a, struct r_asm_op_t *op, ut8 *buf, ut64 len) {
static struct disassemble_info disasm_obj;
if (len<2) return -1;
buf_global = op->buf_asm;
Offset = a->pc;
memcpy (bytes, buf, 2); // TODO handle thumb
/* prepare disassembler */
memset (&disasm_obj,'\0', sizeof (struct disassemble_info));
disasm_obj.buffer = bytes;
disasm_obj.read_memory_func = &sh_buffer_read_memory;
disasm_obj.symbol_at_address_func = &symbol_at_address;
disasm_obj.memory_error_func = &memory_error_func;
disasm_obj.print_address_func = &print_address;
disasm_obj.endian = !a->big_endian;
disasm_obj.fprintf_func = &buf_fprintf;
disasm_obj.stream = stdout;
op->buf_asm[0]='\0';
op->inst_len = print_insn_shl ((bfd_vma)Offset, &disasm_obj);
if (op->inst_len == -1)
strncpy (op->buf_asm, " (data)", R_ASM_BUFSIZE);
return op->inst_len;
}
RAsmPlugin r_asm_plugin_sh = {
.name = "sh",
.arch = "sh",
.bits = (int[]){ 32, 0 },
.desc = "SH-4 disassembly plugin",
.init = NULL,
.fini = NULL,
.disassemble = &disassemble,
.assemble = NULL
};
#ifndef CORELIB
struct r_lib_struct_t radare_plugin = {
.type = R_LIB_TYPE_ASM,
.data = &r_asm_plugin_sh
};
#endif

10
libr/asm/p/sh.mk Normal file
View File

@ -0,0 +1,10 @@
OBJ_SH=asm_sh.o
OBJ_SH+=../arch/sh/gnu/sh-dis.o
STATIC_OBJ+=${OBJ_SH}
TARGET_SH=asm_sh.${EXT_SO}
ALL_TARGETS+=${TARGET_SH}
${TARGET_SH}: ${OBJ_SH}
${CC} ${LDFLAGS} ${CFLAGS} -o ${TARGET_SH} ${OBJ_SH}

View File

@ -301,6 +301,8 @@ char* Elf_(r_bin_elf_get_arch)(struct Elf_(r_bin_elf_obj_t) *bin) {
case EM_PPC:
case EM_PPC64:
return strdup ("ppc");
case EM_SH:
return strdup ("sh");
default:
return strdup ("x86");
}

View File

@ -527,6 +527,7 @@ extern RAnalPlugin r_anal_plugin_ppc;
extern RAnalPlugin r_anal_plugin_java;
extern RAnalPlugin r_anal_plugin_mips;
extern RAnalPlugin r_anal_plugin_dalvik;
extern RAnalPlugin r_anal_plugin_sh;
#endif
#endif

View File

@ -135,6 +135,7 @@ extern RAsmPlugin r_asm_plugin_psosvm;
extern RAsmPlugin r_asm_plugin_avr;
extern RAsmPlugin r_asm_plugin_dalvik;
extern RAsmPlugin r_asm_plugin_msil;
extern RAsmPlugin r_asm_plugin_sh;
#endif
#endif

View File

@ -27,3 +27,13 @@ static struct r_syscall_regs_t fastcall_x86 [R_SYSCALL_ARGS] = {
{{ "eax", "ebx", "ecx", "edx", NULL }},
{{ NULL }}
};
static struct r_syscall_regs_t fastcall_sh [R_SYSCALL_ARGS] = {
{{ "r4", NULL }},
{{ "r4", "r5", NULL }},
{{ "r4", "r5", "r6", NULL }},
{{ "r4", "r5", "r6", "r7", NULL }},
{{ NULL }}
};

View File

@ -44,6 +44,7 @@ RSyscallItem syscalls_linux_x86[] = {
{ NULL, 0, 0, 0 }
};
RSyscallItem syscalls_linux_sh[] = {{NULL,0,0,0} };
// http://lxr.oss.org.cn/source/include/asm-arm/unistd.h
/* syscall-linux */
// XXX: same as in linux-x86 ?

View File

@ -7,6 +7,7 @@
#include <string.h>
#include "fastcall.h"
extern RSyscallItem syscalls_linux_sh[];
extern RSyscallItem syscalls_netbsd_x86[];
extern RSyscallItem syscalls_linux_x86[];
extern RSyscallItem syscalls_linux_mips[];
@ -90,6 +91,16 @@ R_API int r_syscall_setup(RSyscall *ctx, const char *arch, const char *os) {
eprintf ("r_syscall_setup: Unknown os '%s'\n", os);
return R_FALSE;
}
} else
if (!strcmp (arch,"sh")){
ctx->regs = fastcall_sh;
if (!strcmp (os, "linux"))
ctx->sysptr = syscalls_linux_sh;
else {
eprintf ("r_syscall_setup: Unknown os '%s'\n",os);
return R_FALSE;
}
} else {
eprintf ("r_syscall_setup: Unknown os/arch '%s'/'%s'\n", os, arch);
return R_FALSE;

View File

@ -6,6 +6,7 @@
STATIC="asm.java
asm.arm
asm.armthumb
asm.sh
asm.csr
asm.avr
asm.dalvik
@ -15,6 +16,7 @@ asm.x86
asm.x86_nasm
asm.x86_olly
asm.msil
anal.sh
anal.x86
anal.x86_simple
anal.arm