mirror of
https://github.com/radareorg/radare2.git
synced 2024-11-26 06:30:33 +00:00
Initial SH4 support
This commit is contained in:
parent
08ee3226ec
commit
7c04f11226
@ -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
505
libr/anal/p/anal_sh.c
Normal 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
9
libr/anal/p/sh.mk
Normal 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}
|
387
libr/asm/arch/sh/gnu/sh-dis.c
Normal file
387
libr/asm/arch/sh/gnu/sh-dis.c
Normal 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;
|
||||
}
|
11
libr/asm/arch/sh/gnu/sh-dis.d
Normal file
11
libr/asm/arch/sh/gnu/sh-dis.d
Normal 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
|
573
libr/asm/arch/sh/gnu/sh-opc.h
Normal file
573
libr/asm/arch/sh/gnu/sh-opc.h
Normal 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
|
@ -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
92
libr/asm/p/asm_sh.c
Normal 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
10
libr/asm/p/sh.mk
Normal 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}
|
@ -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");
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 }}
|
||||
};
|
||||
|
@ -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 ?
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user