Last active
July 5, 2017 02:37
-
-
Save notwa/622d29dfdeb07c20af92 to your computer and use it in GitHub Desktop.
r4300i disassembler by spinout182
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
mipsdis.c | |
redistribute and modify at will, my name is spinout, keep it here. | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <assert.h> | |
#include <stdint.h> | |
typedef void (*Handler)( unsigned long int word ); | |
#define getRS(word)\ | |
(unsigned int)(unsigned int)((word >> 21) & 31) | |
#define getRT(word)\ | |
(unsigned int)((word >> 16) & 31) | |
#define getRD(word)\ | |
(unsigned int)((word >> 11) & 31) | |
#define getSA(word)\ | |
(unsigned int)((word >> 6) & 31) | |
/* | |
#define getFT(word)\ | |
(unsigned int)((word >> 16) & 31) | |
#define getFS(word)\ | |
(unsigned int)((word >> 11) & 31) | |
#define getFD(word)\ | |
(unsigned int)((word >> 6) & 31) | |
*/ | |
#define getFT(word)\ | |
(unsigned int)(unsigned int)((word >> 21) & 31) | |
#define getFS(word)\ | |
(unsigned int)((word >> 16) & 31) | |
#define getFD(word)\ | |
(unsigned int)((word >> 11) & 31) | |
#define getBASE(word)\ | |
(unsigned int)((word >> 21) & 31) | |
#define getIMM(word)\ | |
(unsigned short int)(word & 0xFFFF) | |
#define getSIMM(word)\ | |
(signed short int)(word & 0xFFFF) | |
#define getOFFSET(word)\ | |
((signed short)(word & 0xFFFF)) * 4 | |
#define getTARGET(word)\ | |
(unsigned int)((word & 0x3FFFFFF) << 2) | |
#define flip32(word)\ | |
(unsigned int)(((word&0xFF000000)>>24)|((word&0x00FF0000)>>8)|((word&0x0000FF00)<<8)|((word&0x000000FF)<<24)) | |
#define flip16(value)\ | |
(unsigned short) ((value&0xFF00)>>8) | ((value&0xFF)<<8) | |
typedef uint8_t u8; | |
typedef uint16_t u16; | |
typedef uint32_t u32; | |
typedef int8_t s8; | |
typedef int16_t s16; | |
typedef int32_t s32; | |
typedef float f32; | |
typedef struct { | |
unsigned addr; | |
char * name; | |
} function; | |
unsigned int pc = 0x80000000; | |
char *dis_op; | |
int map_branches; | |
int *branches; | |
int noBranches=0; | |
int EndOfFunction=-1; | |
unsigned local_start; | |
unsigned local_end; | |
int jaltaken=0; | |
int target_count = 0; | |
char *mapped_functions; | |
function **functions; | |
unsigned gpr_regs[32]={ | |
0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, | |
}; | |
const char * gpr_rn[32]={ | |
"$zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", | |
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", | |
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", | |
"t8", "t9", "k0", "k1", "gp", "$sp", "s8", "$ra" | |
}; | |
const char * cop_rn[32]={ | |
"Index", "Random", "EntryLo0", "EntryLo1", "Context", "PageMask", "Wired", "Reserved", | |
"BadVAddr", "Count", "EntryHi", "Compare", "Status", "Cause", "Epc", "PRevID", | |
"Config", "LLAddr", "WatchLo", "WatchHi", "XContext", "Reserved", "Reserved", "Reserved", | |
"Reserved", "Reserved", "PErr", "CacheErr", "TagLo", "TagHi", "ErrorEpc", "Reserved" | |
}; | |
const char * fpr_rn[32]={ | |
"$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", | |
"$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", | |
"$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", | |
"$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31" | |
}; | |
void reset_gpr_regs_soft(void) | |
{ | |
gpr_regs[1] = 0; | |
gpr_regs[2] = 0; | |
gpr_regs[3] = 0; | |
gpr_regs[4] = 0; | |
gpr_regs[5] = 0; | |
gpr_regs[6] = 0; | |
gpr_regs[7] = 0; | |
gpr_regs[8] = 0; | |
gpr_regs[9] = 0; | |
gpr_regs[10] = 0; | |
gpr_regs[11] = 0; | |
gpr_regs[12] = 0; | |
gpr_regs[13] = 0; | |
gpr_regs[14] = 0; | |
gpr_regs[15] = 0; | |
gpr_regs[24] = 0; | |
gpr_regs[25] = 0; | |
} | |
int target2label(int addr) | |
{ | |
int i; | |
addr |= 0x80000000; | |
for (i=0; i<target_count; i++) | |
{ | |
if (functions[i]->addr == addr) | |
return i; | |
} | |
return -1; | |
} | |
int add_function(int addr, char * name) | |
{ | |
if(target2label(addr)>=0) /* Function already mapped? */ | |
return 0; | |
char * name_ = (char*)malloc(32); | |
int i; | |
for (i=0; i<32;i++)name_[i]=name[i]; | |
functions[target_count]->name = name_; | |
functions[target_count]->addr = addr|0x80000000; | |
target_count+=1; | |
return target_count-1; | |
} | |
int isTarget(int pc) | |
{ | |
int i; | |
for (i=0; i<=noBranches; i++) | |
{ | |
if (pc==branches[i]) | |
return i; | |
} | |
return -1; | |
} | |
char label[16]; | |
char * branch2label(int addr) | |
{ | |
if (map_branches) | |
{ | |
noBranches++; | |
branches[noBranches]=addr; | |
sprintf(label, "0x%08X", addr); | |
} | |
else | |
{ | |
int lbl_no = isTarget(addr); | |
sprintf(label, "$lbl_%i", lbl_no); | |
} | |
return label; | |
} | |
void COP1_NONE(unsigned long word) | |
{ | |
sprintf(dis_op, "(Invalid COP1: %08X)", (unsigned int)word); | |
} | |
void TLB_NONE(unsigned long word) | |
{ | |
sprintf(dis_op, "(Invalid TLB: %08X)", (unsigned int)word); | |
} | |
void COP0_NONE(unsigned long word) | |
{ | |
sprintf(dis_op, "(Invalid COP0: %08X)", (unsigned int)word); | |
} | |
void NONE(unsigned long word) | |
{ | |
sprintf(dis_op, "(Invalid opcode: %08X)", (unsigned int)word); | |
} | |
/* | |
cop1 | |
MIPS R3400i Co-processor 1 (FPU processor) | |
*/ | |
//COP1.L | |
void CVT_S_L(unsigned long word) | |
{ | |
sprintf(dis_op, "cvt.s.l\t%s, %s", fpr_rn[getFD(word)],fpr_rn[getFS(word)]); | |
} | |
void CVT_D_L(unsigned long word) | |
{ | |
sprintf(dis_op, "cvt.d.l\t%s, %s", fpr_rn[getFD(word)],fpr_rn[getFS(word)]); | |
} | |
//COP1.W | |
void CVT_S_W(unsigned long word) | |
{ | |
sprintf(dis_op, "cvt.s.w\t%s, %s", fpr_rn[getFD(word)],fpr_rn[getFS(word)]); | |
} | |
void CVT_D_W(unsigned long word) | |
{ | |
sprintf(dis_op, "cvt.d.w\t%s, %s", fpr_rn[getFD(word)],fpr_rn[getFS(word)]); | |
} | |
//COP1.S | |
void ADD_S(unsigned long word) | |
{ //00 (00) | |
sprintf(dis_op, "add.s\t%s, %s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)], fpr_rn[getFT(word)]); | |
} | |
void SUB_S(unsigned long word) | |
{ //01 (01) | |
sprintf(dis_op, "sub.s\t%s, %s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)], fpr_rn[getFT(word)]); | |
} | |
void MUL_S(unsigned long word) | |
{ //02 (02) | |
sprintf(dis_op, "mul.s\t%s, %s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)], fpr_rn[getFT(word)]); | |
} | |
void DIV_S(unsigned long word) | |
{ //03 (03) | |
sprintf(dis_op, "div.s\t%s, %s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)], fpr_rn[getFT(word)]); | |
} | |
void SQRT_S(unsigned long word) | |
{ //04 (04) | |
sprintf(dis_op, "sqrt.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void ABS_S(unsigned long word) | |
{ //05 (05) | |
sprintf(dis_op, "abs.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void MOV_S(unsigned long word) | |
{ //06 (06) | |
sprintf(dis_op, "mov.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void NEG_S(unsigned long word) | |
{ //07 (07) | |
sprintf(dis_op, "neg.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void ROUND_L_S(unsigned long word) | |
{ //08 (08) | |
sprintf(dis_op, "round.l.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void TRUNC_L_S(unsigned long word) | |
{ //09 (09) | |
sprintf(dis_op, "trunc.l.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void CEIL_L_S(unsigned long word) | |
{ //10 (0A) | |
sprintf(dis_op, "ceil.l.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void FLOOR_L_S(unsigned long word) | |
{ //11 (0B) | |
sprintf(dis_op, "floor.l.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void ROUND_W_S(unsigned long word) | |
{ //12 (0C) | |
sprintf(dis_op, "round.w.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void TRUNC_W_S(unsigned long word) | |
{ //13 (0D) | |
sprintf(dis_op, "trunc.w.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void CEIL_W_S(unsigned long word) | |
{ //14 (0E) | |
sprintf(dis_op, "ceil.w.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void FLOOR_W_S(unsigned long word) | |
{ //15 (0F) | |
sprintf(dis_op, "floor.w.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void CVT_D_S(unsigned long word) | |
{ //33 (21) | |
sprintf(dis_op, "cvt.d.s\t%s, %s", fpr_rn[getFD(word)],fpr_rn[getFS(word)]); | |
} | |
void CVT_W_S(unsigned long word) | |
{ //36 (24) | |
sprintf(dis_op, "cvt.w.s\t%s, %s", fpr_rn[getFD(word)],fpr_rn[getFS(word)]); | |
} | |
void CVT_L_S(unsigned long word) | |
{ //37 (25) | |
sprintf(dis_op, "cvt.l.s\t%s, %s", fpr_rn[getFD(word)],fpr_rn[getFS(word)]); | |
} | |
void C_F_S(unsigned long word) | |
{ //48 (30) | |
sprintf(dis_op, "c.f.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_UN_S(unsigned long word) | |
{ //49 (31) | |
sprintf(dis_op, "c.un.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_EQ_S(unsigned long word) | |
{ //50 (32) | |
sprintf(dis_op, "c.eq.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_UEQ_S(unsigned long word) | |
{ //51 (33) | |
sprintf(dis_op, "c.ueq.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_OLT_S(unsigned long word) | |
{ //52 (34) | |
sprintf(dis_op, "c.olt.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_ULT_S(unsigned long word) | |
{ //53 (35) | |
sprintf(dis_op, "c.ult.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_OLE_S(unsigned long word) | |
{ //54 (36) | |
sprintf(dis_op, "c.ole.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_ULE_S(unsigned long word) | |
{ //55 (37) | |
sprintf(dis_op, "c.ule.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_SF_S(unsigned long word) | |
{ //56 (38) | |
sprintf(dis_op, "c.sf.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_NGLE_S(unsigned long word) | |
{ //57 (39) | |
sprintf(dis_op, "c.ngle.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_SEQ_S(unsigned long word) | |
{ //58 (3A) | |
sprintf(dis_op, "c.seq.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_NGL_S(unsigned long word) | |
{ //59 (3B) | |
sprintf(dis_op, "c.ngl.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_LT_S(unsigned long word) | |
{ //60 (3C) | |
sprintf(dis_op, "c.lt.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_NGE_S(unsigned long word) | |
{ //61 (3D) | |
sprintf(dis_op, "c.nge.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_LE_S(unsigned long word) | |
{ //62 (3E) | |
sprintf(dis_op, "c.le.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_NGT_S(unsigned long word) | |
{ //63 (3F) | |
sprintf(dis_op, "c.ngt.s\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
Handler S_T[64] = { | |
ADD_S, SUB_S, MUL_S, DIV_S, SQRT_S, ABS_S, MOV_S, NEG_S, | |
ROUND_L_S, TRUNC_L_S, CEIL_L_S, FLOOR_L_S, ROUND_W_S, TRUNC_W_S, CEIL_W_S, FLOOR_W_S, | |
COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, | |
COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, | |
COP1_NONE, CVT_D_S, COP1_NONE, COP1_NONE, CVT_W_S, CVT_L_S, COP1_NONE, COP1_NONE, | |
COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, | |
C_F_S, C_UN_S, C_EQ_S, C_UEQ_S, C_OLT_S, C_ULT_S, C_OLE_S, C_ULE_S, | |
C_SF_S, C_NGLE_S, C_SEQ_S, C_NGL_S, C_LT_S, C_NGE_S, C_LE_S, C_NGT_S | |
}; | |
//COP1.D | |
void ADD_D(unsigned long word) | |
{ //00 (00) | |
sprintf(dis_op, "add.d\t%s, %s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)], fpr_rn[getFT(word)]); | |
} | |
void SUB_D(unsigned long word) | |
{ //01 (01) | |
sprintf(dis_op, "sub.d\t%s, %s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)], fpr_rn[getFT(word)]); | |
} | |
void MUL_D(unsigned long word) | |
{ //02 (02) | |
sprintf(dis_op, "mul.d\t%s, %s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)], fpr_rn[getFT(word)]); | |
} | |
void DIV_D(unsigned long word) | |
{ //03 (03) | |
sprintf(dis_op, "add.d\t%s, %s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)], fpr_rn[getFT(word)]); | |
} | |
void SQRT_D(unsigned long word) | |
{ //04 (04) | |
sprintf(dis_op, "sqrt.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void ABS_D(unsigned long word) | |
{ //05 (05) | |
sprintf(dis_op, "abs.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void MOV_D(unsigned long word) | |
{ //06 (06) | |
sprintf(dis_op, "mov.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void NEG_D(unsigned long word) | |
{ //07 (07) | |
sprintf(dis_op, "neg.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void ROUND_L_D(unsigned long word) | |
{ //08 (08) | |
sprintf(dis_op, "round.l.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void TRUNC_L_D(unsigned long word) | |
{ //09 (09) | |
sprintf(dis_op, "trunc.l.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void CEIL_L_D(unsigned long word) | |
{ //10 (0A) | |
sprintf(dis_op, "ceil.l.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void FLOOR_L_D(unsigned long word) | |
{ //11 (0B) | |
sprintf(dis_op, "floor.l.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void ROUND_W_D(unsigned long word) | |
{ //12 (0C) | |
sprintf(dis_op, "round.w.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void TRUNC_W_D(unsigned long word) | |
{ //13 (0D) | |
sprintf(dis_op, "trunc.w.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void CEIL_W_D(unsigned long word) | |
{ //14 (0E) | |
sprintf(dis_op, "ceil.w.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void FLOOR_W_D(unsigned long word) | |
{ //15 (0F) | |
sprintf(dis_op, "floor.w.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void CVT_S_D(unsigned long word) | |
{ //32 (20) | |
sprintf(dis_op, "cvt.s.d\t%s, %s", fpr_rn[getFD(word)],fpr_rn[getFS(word)]); | |
} | |
void CVT_W_D(unsigned long word) | |
{ //36 (24) | |
sprintf(dis_op, "cvt.w.d\t%s, %s", fpr_rn[getFD(word)],fpr_rn[getFS(word)]); | |
} | |
void CVT_L_D(unsigned long word) | |
{ //37 (25) | |
sprintf(dis_op, "cvt.l.d\t%s, %s", fpr_rn[getFD(word)],fpr_rn[getFS(word)]); | |
} | |
void C_F_D(unsigned long word) | |
{ //48 (30) | |
sprintf(dis_op, "c.f.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_UN_D(unsigned long word) | |
{ //49 (31) | |
sprintf(dis_op, "c.un.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_EQ_D(unsigned long word) | |
{ //50 (32) | |
sprintf(dis_op, "c.eq.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_UEQ_D(unsigned long word) | |
{ //51 (33) | |
sprintf(dis_op, "c.ueq.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_OLT_D(unsigned long word) | |
{ //52 (34) | |
sprintf(dis_op, "c.olt.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_ULT_D(unsigned long word) | |
{ //53 (35) | |
sprintf(dis_op, "c.ult.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_OLE_D(unsigned long word) | |
{ //54 (36) | |
sprintf(dis_op, "c.ole.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_ULE_D(unsigned long word) | |
{ //55 (37) | |
sprintf(dis_op, "c.ule.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_SF_D(unsigned long word) | |
{ //56 (38) | |
sprintf(dis_op, "c.df.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_NGLE_D(unsigned long word) | |
{ //57 (39) | |
sprintf(dis_op, "c.ngle.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_SEQ_D(unsigned long word) | |
{ //58 (3A) | |
sprintf(dis_op, "c.deq.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_NGL_D(unsigned long word) | |
{ //59 (3B) | |
sprintf(dis_op, "c.ngl.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_LT_D(unsigned long word) | |
{ //60 (3C) | |
sprintf(dis_op, "c.lt.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_NGE_D(unsigned long word) | |
{ //61 (3D) | |
sprintf(dis_op, "c.nge.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_LE_D(unsigned long word) | |
{ //62 (3E) | |
sprintf(dis_op, "c.le.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
void C_NGT_D(unsigned long word) | |
{ //63 (3F) | |
sprintf(dis_op, "c.ngt.d\t%s, %s", fpr_rn[getFD(word)], fpr_rn[getFS(word)]); | |
} | |
Handler D_T[64] = { | |
ADD_D, SUB_D, MUL_D, DIV_D, SQRT_D, ABS_D, MOV_D, NEG_D, | |
ROUND_L_D, TRUNC_L_D, CEIL_L_D, FLOOR_L_D, ROUND_W_D, TRUNC_W_D, CEIL_W_D, FLOOR_W_D, | |
COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, | |
COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, | |
CVT_S_D, COP1_NONE, COP1_NONE, COP1_NONE, CVT_W_D, CVT_L_D, COP1_NONE, COP1_NONE, | |
COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, | |
C_F_D, C_UN_D, C_EQ_D, C_UEQ_D, C_OLT_D, C_ULT_D, C_OLE_D, C_ULE_D, | |
C_SF_D, C_NGLE_D, C_SEQ_D, C_NGL_D, C_LT_D, C_NGE_D, C_LE_D, C_NGT_D | |
}; | |
//COP1.BC opcodes | |
void BC1F(unsigned long word) | |
{ | |
sprintf(dis_op, "bc1f\t%s", branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void BC1T(unsigned long word) | |
{ | |
sprintf(dis_op, "bc1t\t%s", branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void BC1FL(unsigned long word) | |
{ | |
sprintf(dis_op, "bc1fl\t%s", branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void BC1TL(unsigned long word) | |
{ | |
sprintf(dis_op, "bc1tl\t%s", branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
Handler BC_T[4] = {BC1F, BC1T, BC1FL, BC1TL}; | |
//COP1 op types | |
void MFC1(unsigned long word) | |
{ //00 (00) | |
sprintf(dis_op, "mfc1\t%s, %s", gpr_rn[getRT(word)], fpr_rn[getFD(word)]); | |
} | |
void DMFC1(unsigned long word) | |
{ //01 (01) | |
sprintf(dis_op, "dmfc1\t%s, %s", gpr_rn[getRT(word)], fpr_rn[getFD(word)]); | |
} | |
void CFC1(unsigned long word) | |
{ //02 (02) | |
sprintf(dis_op, "cfc1\t%s, %s", gpr_rn[getRT(word)], fpr_rn[getFD(word)]); | |
} | |
void MTC1(unsigned long word) | |
{ //04 (04) | |
float * value = (float *) &gpr_regs[getRT(word)]; | |
sprintf(dis_op, "mtc1\t%s, %s\t; %s = %f", gpr_rn[getRT(word)], fpr_rn[getFD(word)], fpr_rn[getFD(word)], *value ); | |
} | |
void DMTC1(unsigned long word) | |
{ //05 (05) | |
sprintf(dis_op, "dmtc1\t%s, %s", gpr_rn[getRT(word)], fpr_rn[getFD(word)]); | |
} | |
void CTC1(unsigned long word) | |
{ //06 (06) | |
sprintf(dis_op, "ctc1\t%s, %s", gpr_rn[getRT(word)], fpr_rn[getFD(word)]); | |
} | |
void BC(unsigned long word) | |
{ //08 (08) | |
BC_T[(word >> 16) & 3](word); | |
} | |
void S(unsigned long word) | |
{ //16 (10) | |
S_T[word & 63](word); | |
} | |
void D(unsigned long word) | |
{ //17 (11) | |
D_T[word & 63](word); | |
} | |
void W(unsigned long word) | |
{ //20 (14) | |
if (!(word & 0x1E)) | |
{ | |
if (word & 1) | |
CVT_D_W(word); | |
else | |
CVT_S_W(word); | |
} | |
else | |
COP1_NONE(word); | |
} | |
void L(unsigned long word) | |
{ //21 (15) | |
if (!(word & 0x1E)) | |
{ | |
if (word & 1) | |
CVT_D_L(word); | |
else | |
CVT_S_L(word); | |
} | |
else | |
COP1_NONE(word); | |
} | |
Handler COP1_T[32] = { | |
MFC1, DMFC1, CFC1, COP1_NONE, MTC1, DMTC1, CTC1, COP1_NONE, | |
BC, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, | |
S, D, COP1_NONE, COP1_NONE, W, L, COP1_NONE, COP1_NONE, | |
COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE, COP1_NONE | |
}; | |
/* | |
cop0 | |
MIPS R3400i Co-processor 0 (Status processor) | |
*/ | |
/* TLB op types */ | |
void TLBR(unsigned long word) | |
{ | |
sprintf(dis_op, "tlbr"); | |
} | |
void TLBWI(unsigned long word) | |
{ | |
sprintf(dis_op, "tlbwi"); | |
} | |
void TLBWR(unsigned long word) | |
{ | |
sprintf(dis_op, "tlbwr"); | |
} | |
void TLBP(unsigned long word) | |
{ | |
sprintf(dis_op, "tlbp"); | |
} | |
void ERET(unsigned long word) | |
{ | |
sprintf(dis_op, "eret"); | |
} | |
Handler TLB_T[64] = { | |
TLB_NONE, TLBR, TLBWI, TLB_NONE, TLB_NONE, TLB_NONE, TLBWR, TLB_NONE, | |
TLBP, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, | |
TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, | |
ERET, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, | |
TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, | |
TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, | |
TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, | |
TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE, TLB_NONE | |
}; | |
/* COP0 op types */ | |
void MFC0(unsigned long word) | |
{ /* 00 */ | |
sprintf(dis_op, "mfc0\t%s, %s", gpr_rn[getRT(word)], cop_rn[getFS(word)]); | |
} | |
void MTC0(unsigned long word) | |
{ /* 04 */ | |
sprintf(dis_op, "mtc0\t%s, %s", gpr_rn[getRT(word)], cop_rn[getFS(word)]); | |
} | |
void TLB(unsigned long word) | |
{ | |
TLB_T[word & 63](word); | |
} | |
Handler COP0_T[32] = { | |
MFC0, COP0_NONE, COP0_NONE, COP0_NONE, MTC0, COP0_NONE, COP0_NONE, COP0_NONE, | |
NONE, COP0_NONE, COP0_NONE, COP0_NONE, COP0_NONE, COP0_NONE, COP0_NONE, COP0_NONE, | |
TLB, COP0_NONE, COP0_NONE, COP0_NONE, COP0_NONE, COP0_NONE, COP0_NONE, COP0_NONE, | |
NONE, COP0_NONE, COP0_NONE, COP0_NONE, COP0_NONE, COP0_NONE, COP0_NONE, COP0_NONE | |
}; | |
/* | |
mips | |
Main Processor | |
*/ | |
// REGIMM op types | |
void BLTZ(unsigned long word) | |
{ | |
sprintf(dis_op, "bltz\t%s, %s", gpr_rn[getRS(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void BGEZ(unsigned long word) | |
{ | |
sprintf(dis_op, "bgez\t%s, %s", gpr_rn[getRS(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void BLTZL(unsigned long word) | |
{ | |
sprintf(dis_op, "bltzl\t%s, %s", gpr_rn[getRS(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void BGEZL(unsigned long word) | |
{ | |
sprintf(dis_op, "bgezl\t%s, %s", gpr_rn[getRS(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void TGEI(unsigned long word) | |
{ | |
sprintf(dis_op, "tgei\t%s, 0x%08X", gpr_rn[getRS(word)], getIMM(word)); | |
} | |
void TGEIU(unsigned long word) | |
{ | |
sprintf(dis_op, "tgeiu\t%s 0x%08X", gpr_rn[getRS(word)], getIMM(word)); | |
} | |
void TLTI(unsigned long word) | |
{ | |
sprintf(dis_op, "tlti\t%s, 0x%08X", gpr_rn[getRS(word)], getIMM(word)); | |
} | |
void TLTIU(unsigned long word) | |
{ | |
sprintf(dis_op, "tltiu\t%s, 0x%08X", gpr_rn[getRS(word)], getIMM(word)); | |
} | |
void TEQI(unsigned long word) | |
{ | |
sprintf(dis_op, "tqei\t%s, 0x%08X", gpr_rn[getRS(word)], getIMM(word)); | |
} | |
void TNEI(unsigned long word) | |
{ | |
sprintf(dis_op, "tnei\t%s, 0x%08X", gpr_rn[getRS(word)], getIMM(word)); | |
} | |
void BLTZAL(unsigned long word) | |
{ | |
sprintf(dis_op, "bltzal\t%s, %s", gpr_rn[getRS(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void BGEZAL(unsigned long word) | |
{ | |
sprintf(dis_op, "bgezal\t%s, %s", gpr_rn[getRS(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void BLTZALL(unsigned long word) | |
{ | |
sprintf(dis_op, "bltzall\t%s, %s", gpr_rn[getRS(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void BGEZALL(unsigned long word) | |
{ | |
sprintf(dis_op, "bgezall\t%s, %s", gpr_rn[getRS(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
Handler REGIMM_T[32] = { | |
BLTZ, BGEZ, BLTZL, BGEZL, NONE, NONE, NONE, NONE, | |
TGEI, TGEIU, TLTI, TLTIU, TEQI, NONE, TNEI, NONE, | |
BLTZAL, BGEZAL, BLTZALL, BGEZALL, NONE, NONE, NONE, NONE, | |
NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE | |
}; | |
//SPECIAL op types | |
void SLL(unsigned long word) | |
{ //00 (00) | |
if (word) | |
sprintf(dis_op, "sll\t%s, %s, %i", gpr_rn[getRD(word)], gpr_rn[getRT(word)], getSA(word) ); | |
else | |
sprintf(dis_op, "nop"); | |
} | |
void SRL(unsigned long word) | |
{ //02 (02) | |
sprintf(dis_op, "srl\t%s, %s, %i", gpr_rn[getRD(word)],gpr_rn[getRT(word)],getSA(word)); | |
} | |
void SRA(unsigned long word) | |
{ //03 (03) | |
sprintf(dis_op, "sra\t%s, %s, %i", gpr_rn[getRD(word)],gpr_rn[getRT(word)],getSA(word)); | |
} | |
void SLLV(unsigned long word) | |
{ //04 (04) | |
sprintf(dis_op, "sllv\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRT(word)],gpr_rn[getRS(word)]); | |
} | |
void SRLV(unsigned long word) | |
{ //06 (06) | |
sprintf(dis_op, "srlv\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRT(word)],gpr_rn[getRS(word)]); | |
} | |
void SRAV(unsigned long word) | |
{ //07 (07) | |
sprintf(dis_op, "srav\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRT(word)],gpr_rn[getRS(word)]); | |
} | |
void JR(unsigned long word) | |
{ //08 (08) | |
sprintf(dis_op, "jr\t%s", gpr_rn[getRS(word)]); | |
if (getRS(word) == 31) | |
EndOfFunction=pc+4; | |
} | |
void JALR(unsigned long word) | |
{ //09 (09) | |
sprintf(dis_op, "jalr\t%s, %s", gpr_rn[getRS(word)],gpr_rn[getRD(word)]); | |
jaltaken=2; | |
} | |
void SYSCALL(unsigned long word) | |
{ //12 (0C) | |
sprintf(dis_op, "syscall\t0x%04X", getIMM(word)); | |
} | |
void BREAK(unsigned long word) | |
{ //13 (0D) | |
sprintf(dis_op, "break\t0x%04X", getIMM(word)); | |
} | |
void SYNC(unsigned long word) | |
{ //15 (0F) | |
sprintf(dis_op, "sync"); | |
} | |
void MFHI(unsigned long word) | |
{ //16 (10) | |
sprintf(dis_op, "mfhi\t%s", gpr_rn[getRD(word)]); | |
} | |
void MTHI(unsigned long word) | |
{ //17 (11) | |
sprintf(dis_op, "mthi\t%s", gpr_rn[getRD(word)]); | |
} | |
void MFLO(unsigned long word) | |
{ //18 (12) | |
sprintf(dis_op, "mflo\t%s", gpr_rn[getRD(word)]); | |
} | |
void MTLO(unsigned long word) | |
{ //19 (13) | |
sprintf(dis_op, "mtlo\t%s", gpr_rn[getRD(word)]); | |
} | |
void DSLLV(unsigned long word) | |
{ //20 (14) | |
sprintf(dis_op, "dsllv\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRT(word)],gpr_rn[getRS(word)]); | |
} | |
void DSRLV(unsigned long word) | |
{ //22 (16) | |
sprintf(dis_op, "dsrlv\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRT(word)],gpr_rn[getRS(word)]); | |
} | |
void DSRAV(unsigned long word) | |
{ //23 (17) | |
sprintf(dis_op, "dsrav\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRT(word)],gpr_rn[getRS(word)]); | |
} | |
void MULT(unsigned long word) | |
{ //24 (18) | |
sprintf(dis_op, "mult\t%s, %s", gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void MULTU(unsigned long word) | |
{ //25 (19) | |
sprintf(dis_op, "multu\t%s, %s", gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void DIV(unsigned long word) | |
{ //26 (1A) | |
sprintf(dis_op, "div\t%s, %s", gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void DIVU(unsigned long word) | |
{ //27 (1B) | |
sprintf(dis_op, "divu\t%s, %s", gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void DMULT(unsigned long word) | |
{ //28 (1C) | |
sprintf(dis_op, "dmult\t%s, %s", gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void DMULTU(unsigned long word) | |
{ //29 (1D) | |
sprintf(dis_op, "dmultu\t%s, %s", gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void DDIV(unsigned long word) | |
{ //30 (1E) | |
sprintf(dis_op, "ddiv\t%s, %s", gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void DDIVU(unsigned long word) | |
{ //31 (1F) | |
sprintf(dis_op, "ddivu\t%s, %s", gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void ADD(unsigned long word) | |
{ //32 (20) | |
sprintf(dis_op, "add\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void ADDU(unsigned long word) | |
{ //33 (21) | |
sprintf(dis_op, "addu\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void SUB(unsigned long word) | |
{ //34 (22) | |
sprintf(dis_op, "sub\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void SUBU(unsigned long word) | |
{ //35 (23) | |
sprintf(dis_op, "subu\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void AND(unsigned long word) | |
{ //36 (24) | |
sprintf(dis_op, "and\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void OR(unsigned long word) | |
{ //37 (25) | |
gpr_regs[getRD(word)]=gpr_regs[getRS(word)] | gpr_regs[getRT(word)]; | |
sprintf(dis_op, "or\t%s, %s, %s\t; %s = %08X", gpr_rn[getRD(word)],gpr_rn[getRS(word)],gpr_rn[getRT(word)], gpr_rn[getRD(word)],gpr_regs[getRD(word)]); | |
} | |
void XOR(unsigned long word) | |
{ //38 (26) | |
sprintf(dis_op, "xor\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void NOR(unsigned long word) | |
{ //39 (27) | |
sprintf(dis_op, "nor\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void SLT(unsigned long word) | |
{ //42 (2A) | |
sprintf(dis_op, "slt\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void SLTU(unsigned long word) | |
{ //43 (2B) | |
sprintf(dis_op, "sltu\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void DADD(unsigned long word) | |
{ //44 (2C) | |
sprintf(dis_op, "dadd\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void DADDU(unsigned long word) | |
{ //45 (2D) | |
sprintf(dis_op, "daddu\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void DSUB(unsigned long word) | |
{ //46 (2E) | |
sprintf(dis_op, "dsub\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void DSUBU(unsigned long word) | |
{ //47 (2F) | |
sprintf(dis_op, "dsubu\t%s, %s, %s", gpr_rn[getRD(word)],gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void TGE(unsigned long word) | |
{ //48 (30) | |
sprintf(dis_op, "tge\t%s, %s", gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void TGEU(unsigned long word) | |
{ //49 (31) | |
sprintf(dis_op, "tgeu\t%s, %s", gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void TLT(unsigned long word) | |
{ //50 (32) | |
sprintf(dis_op, "tlt\t%s, %s", gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void TLTU(unsigned long word) | |
{ //51 (33) | |
sprintf(dis_op, "tltu\t%s, %s", gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void TEQ(unsigned long word) | |
{ //52 (34) | |
sprintf(dis_op, "teq\t%s, %s", gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void TNE(unsigned long word) | |
{ //54 (36) | |
sprintf(dis_op, "tne\t%s, %s", gpr_rn[getRS(word)],gpr_rn[getRT(word)]); | |
} | |
void DSLL(unsigned long word) | |
{ //56 (38) | |
sprintf(dis_op, "dsll\t%s, %s, %i", gpr_rn[getRD(word)],gpr_rn[getRT(word)],getSA(word)); | |
} | |
void DSRL(unsigned long word) | |
{ //58 (3A) | |
sprintf(dis_op, "dsrl\t%s, %s, %i", gpr_rn[getRD(word)],gpr_rn[getRT(word)],getSA(word)); | |
} | |
void DSRA(unsigned long word) | |
{ //59 (3B) | |
sprintf(dis_op, "dsra\t%s, %s, %i", gpr_rn[getRD(word)],gpr_rn[getRT(word)],getSA(word)); | |
} | |
void DSLL32(unsigned long word) | |
{ //60 (3C) | |
sprintf(dis_op, "dsll32\t%s, %s, %i", gpr_rn[getRD(word)],gpr_rn[getRT(word)],getSA(word)); | |
} | |
void DSRL32(unsigned long word) | |
{ //62 (3E) | |
sprintf(dis_op, "dsrl32\t%s, %s, %i", gpr_rn[getRD(word)],gpr_rn[getRT(word)],getSA(word)); | |
} | |
void DSRA32(unsigned long word) | |
{ //63 (3F) | |
sprintf(dis_op, "dsra32\t%s, %s, %i", gpr_rn[getRD(word)],gpr_rn[getRT(word)],getSA(word)); | |
}; | |
Handler SPECIAL_T[64] = { | |
SLL, NONE, SRL, SRA, SLLV, NONE, SRLV, SRAV, | |
JR, JALR, NONE, NONE, SYSCALL, BREAK, NONE, SYNC, | |
MFHI, MTHI, MFLO, MTLO, DSLLV, NONE, DSRLV, DSRAV, | |
MULT, MULTU, DIV, DIVU, DMULT, DMULTU, DDIV, DDIVU, | |
ADD, ADDU, SUB, SUBU, AND, OR, XOR, NOR, | |
NONE, NONE, SLT, SLTU, DADD, DADDU, DSUB, DSUBU, | |
TGE, TGEU, TLT, TLTU, TEQ, NONE, TNE, NONE, | |
DSLL, NONE, DSRL, DSRA, DSLL32, NONE, DSRL32, DSRA32 | |
}; | |
//Main op types | |
void SPECIAL(unsigned long word) | |
{ //00(00) | |
SPECIAL_T[word & 63](word); | |
} | |
void REGIMM(unsigned long word) | |
{ //01(01) | |
REGIMM_T[getRT(word)](word); | |
} | |
void J(unsigned long word) | |
{ //02(02) | |
sprintf(dis_op, "j\t0x0%08X", 0x80000000 | getTARGET(word)); | |
} | |
void JAL(unsigned long word) | |
{ //03(03) | |
int target = getTARGET(word); | |
int functionno = target2label(target); | |
if(functionno >= 0) | |
{ | |
sprintf(dis_op, "jal\t%s\t; %08X", functions[functionno]->name, target); | |
} | |
else | |
sprintf(dis_op, "jal\t0x%08X", target|0x80000000); | |
jaltaken=2; | |
} | |
void BEQ(unsigned long word) | |
{ //04(04) | |
sprintf(dis_op, "beq\t%s, %s, %s", gpr_rn[getRS(word)], gpr_rn[getRT(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4) ); | |
} | |
void BNE(unsigned long word) | |
{ //05(05) | |
sprintf(dis_op, "bne\t%s, %s, %s", gpr_rn[getRS(word)], gpr_rn[getRT(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4) ); | |
} | |
void BLEZ(unsigned long word) | |
{ //06(06) | |
sprintf(dis_op, "blez\t%s, %s", gpr_rn[getRS(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void BGTZ(unsigned long word) | |
{ //07(07) | |
sprintf(dis_op, "bgtz\t%s, %s", gpr_rn[getRS(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void ADDI(unsigned long word) | |
{ //08(08) | |
gpr_regs[getRT(word)] = gpr_regs[getRS(word)] + getSIMM(word); | |
sprintf(dis_op, "addi\t%s, %s, 0x%04X\t; %s = %08X", gpr_rn[getRT(word)], gpr_rn[getRS(word)], getIMM(word), gpr_rn[getRT(word)], gpr_regs[getRT(word)]); | |
} | |
void ADDIU(unsigned long word) | |
{ //09(09) | |
gpr_regs[getRT(word)] = gpr_regs[getRS(word)] + getSIMM(word); | |
sprintf(dis_op, "addiu\t%s, %s, 0x%04X\t; %s = %08X", gpr_rn[getRT(word)], gpr_rn[getRS(word)], getIMM(word), gpr_rn[getRT(word)], gpr_regs[getRT(word)]); | |
} | |
void SLTI(unsigned long word) | |
{ //10(0A) | |
sprintf(dis_op, "slti\t%s, %s, 0x%04X", gpr_rn[getRT(word)], gpr_rn[getRS(word)], getIMM(word)); | |
} | |
void SLTIU(unsigned long word) | |
{ //11(0B) | |
sprintf(dis_op, "sltiu\t%s, %s, 0x%04X", gpr_rn[getRT(word)], gpr_rn[getRS(word)], getIMM(word)); | |
} | |
void ANDI(unsigned long word) | |
{ //12(0C) | |
gpr_regs[getRT(word)] = gpr_regs[getRS(word)] & getIMM(word); | |
sprintf(dis_op, "andi\t%s, %s, 0x%04X\t; %s = %08X", gpr_rn[getRT(word)], gpr_rn[getRS(word)], getIMM(word), gpr_rn[getRT(word)], gpr_regs[getRT(word)]); | |
} | |
void ORI(unsigned long word) | |
{ //13(0D) | |
gpr_regs[getRT(word)] = gpr_regs[getRS(word)] | getIMM(word); | |
sprintf(dis_op, "ori\t%s, %s, 0x%04X\t; %s = %08X", gpr_rn[getRT(word)], gpr_rn[getRS(word)], getIMM(word), gpr_rn[getRT(word)], gpr_regs[getRT(word)]); | |
} | |
void XORI(unsigned long word) | |
{ //14(0E) | |
gpr_regs[getRT(word)] = gpr_regs[getRS(word)] ^ getIMM(word); | |
sprintf(dis_op, "xori\t%s, %s, 0x%04X\t; %s = %08X", gpr_rn[getRT(word)], gpr_rn[getRS(word)], getIMM(word), gpr_rn[getRT(word)], gpr_regs[getRT(word)]); | |
} | |
void LUI(unsigned long word) | |
{ //15(0F) | |
gpr_regs[getRT(word)] = getIMM(word)<<16; | |
sprintf(dis_op, "lui\t%s, 0x%04X\t; %s = %08X", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getRT(word)], gpr_regs[getRT(word)]); | |
} | |
void COP0(unsigned long word) | |
{ //16(10) | |
COP0_T[getRS(word)](word); | |
} | |
void COP1(unsigned long word) | |
{ //17(11) | |
COP1_T[getRS(word)](word); | |
} | |
void BEQL(unsigned long word) | |
{ //20(14) | |
sprintf(dis_op, "beql\t%s, %s, %s", gpr_rn[getRS(word)], gpr_rn[getRT(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void BNEL(unsigned long word) | |
{ //21(15) | |
sprintf(dis_op, "bnel\t%s, %s, %s", gpr_rn[getRS(word)], gpr_rn[getRT(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void BLEZL(unsigned long word) | |
{ //22(16) | |
sprintf(dis_op, "blezl\t%s, %s", gpr_rn[getRS(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void BGTZL(unsigned long word) | |
{ //23(17) | |
sprintf(dis_op, "bgtzl\t%s, %s", gpr_rn[getRS(word)], branch2label(getOFFSET(word) + (pc | 0x80000000) + 4)); | |
} | |
void DADDI(unsigned long word) | |
{ //24(18) | |
sprintf(dis_op, "daddi\t%s, %s, 0x%04X", gpr_rn[getRT(word)], gpr_rn[getRS(word)], getIMM(word)); | |
} | |
void DADDIU(unsigned long word) | |
{ //25(19) | |
sprintf(dis_op, "daddiu\t%s, %s, 0x%04X", gpr_rn[getRT(word)], gpr_rn[getRS(word)], getIMM(word)); | |
} | |
void LDL(unsigned long word) | |
{ //26(1A) | |
sprintf(dis_op, "ldl\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void LDR(unsigned long word) | |
{ //27(1B) | |
sprintf(dis_op, "ldr\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void LB(unsigned long word) | |
{ //32(20) | |
//gpr_regs[getRT(word)] = memory.sbyte[getIMM(word)+gpr_regs[getBASE(word)]]; | |
sprintf(dis_op, "lb\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void LH(unsigned long word) | |
{ //33(21) | |
//gpr_regs[getRT(word)] = memory.shalf[(getIMM(word)+gpr_regs[getBASE(word)])>>1]; | |
sprintf(dis_op, "lh\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void LWL(unsigned long word) | |
{ //34(22) | |
sprintf(dis_op, "lwl\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void LW(unsigned long word) | |
{ //35(23) | |
//gpr_regs[getRT(word)] = memory.sword[(getIMM(word)+gpr_regs[getBASE(word)])>>2]; | |
sprintf(dis_op, "lw\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void LBU(unsigned long word) | |
{ //36(24) | |
//gpr_regs[getRT(word)] = memory.ubyte[getIMM(word)+gpr_regs[getBASE(word)]]; | |
sprintf(dis_op, "lbu\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void LHU(unsigned long word) | |
{ //37(25) | |
//gpr_regs[getRT(word)] = memory.uhalf[(getIMM(word)+gpr_regs[getBASE(word)])>>1]; | |
sprintf(dis_op, "lhu\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void LWR(unsigned long word) | |
{ //38(26) | |
sprintf(dis_op, "lwr\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void LWU(unsigned long word) | |
{ //39(27) | |
//gpr_regs[getRT(word)] = memory.uword[(getIMM(word)+gpr_regs[getBASE(word)])>>2]; | |
sprintf(dis_op, "lwu\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void SB(unsigned long word) | |
{ //40(28) | |
//memory.sbyte[getIMM(word)+gpr_regs[getBASE(word)]] = gpr_regs[getRT(word)]; | |
sprintf(dis_op, "sb\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void SH(unsigned long word) | |
{ //41(29) | |
//memory.shalf[(getIMM(word)+gpr_regs[getBASE(word)])>>2] = gpr_regs[getRT(word)]; | |
sprintf(dis_op, "sh\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void SWL(unsigned long word) | |
{ //42(2A) | |
sprintf(dis_op, "swl\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void SW(unsigned long word) | |
{ //43(2B) | |
sprintf(dis_op, "sw\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void SDL(unsigned long word) | |
{ //44(2C) | |
sprintf(dis_op, "sdl\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void SDR(unsigned long word) | |
{ //45(2D) | |
sprintf(dis_op, "sdr\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void SWR(unsigned long word) | |
{ //46(2E) | |
sprintf(dis_op, "swr\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void CACHE(unsigned long word) | |
{ //47(2F) | |
sprintf(dis_op, "cache\t0x%02X, 0x%04X(%s)", getRT(word), getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void LL(unsigned long word) | |
{ //48(30) | |
sprintf(dis_op, "ll\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void LWC1(unsigned long word) | |
{ //49(31) | |
sprintf(dis_op, "lwc1\t%s, 0x%04X(%s)", fpr_rn[getFS(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void LLD(unsigned long word) | |
{ //52(34) | |
sprintf(dis_op, "lld\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void LDC1(unsigned long word) | |
{ //53(35) | |
sprintf(dis_op, "ldc1\t%s, 0x%04X(%s)", gpr_rn[getFT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void LDC2(unsigned long word) | |
{ //54(36) | |
sprintf(dis_op, "ldc2\t%s, 0x%04X(%s)", gpr_rn[getFT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void LD(unsigned long word) | |
{ //55(37) | |
sprintf(dis_op, "ld\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void SC(unsigned long word) | |
{ //56(38) | |
sprintf(dis_op, "sc\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void SWC1(unsigned long word) | |
{ //57(39) | |
sprintf(dis_op, "swc1\t%s, 0x%04X(%s)", gpr_rn[getFT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void SCD(unsigned long word) | |
{ //60(3C) | |
sprintf(dis_op, "sdc\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void SDC1(unsigned long word) | |
{ //61(3D) | |
sprintf(dis_op, "sdc1\t%s, 0x%04X(%s)", gpr_rn[getFT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void SDC2(unsigned long word) | |
{ //62(3E) | |
sprintf(dis_op, "sdc2\t%s, 0x%04X(%s)", gpr_rn[getFT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
void SD(unsigned long word) | |
{ //63(3F) | |
sprintf(dis_op, "sd\t%s, 0x%04X(%s)", gpr_rn[getRT(word)], getIMM(word), gpr_rn[getBASE(word)]); | |
} | |
Handler MAIN_T[64] = { | |
SPECIAL, REGIMM, J, JAL, BEQ, BNE, BLEZ, BGTZ, | |
ADDI, ADDIU, SLTI, SLTIU, ANDI, ORI, XORI, LUI, | |
COP0, COP1, NONE, NONE, BEQL, BNEL, BLEZL, BGTZL, | |
DADDI, DADDIU, LDL, LDR, NONE, NONE, NONE, NONE, | |
LB, LH, LWL, LW, LBU, LHU, LWR, LWU, | |
SB, SH, SWL, SW, SDL, SDR, SWR, CACHE, | |
LL, LWC1, NONE, NONE, LLD, LDC1, LDC2, LD, | |
SC, SWC1, NONE, NONE, SCD, SDC1, SDC2, SD | |
}; | |
char * getOP(unsigned long int word) | |
{ | |
//printf("%08X\n", (unsigned int) word); | |
MAIN_T[ word >> 26 ](word); | |
return dis_op; | |
} | |
int main(int argc, char * argv[]) | |
{ | |
int i; | |
char * buff; | |
FILE * ROM; | |
int targetnum; | |
#define XBOX_HUGE (1024*1024*8) | |
char *tmp = calloc(1, XBOX_HUGE); | |
dis_op = calloc(1, XBOX_HUGE); | |
branches = calloc(1, XBOX_HUGE); | |
mapped_functions = calloc(1, XBOX_HUGE); | |
#define FUNCTIONS (XBOX_HUGE / sizeof(function)) | |
functions = calloc(FUNCTIONS, sizeof(function)); | |
function *functions_data = calloc(FUNCTIONS, sizeof(function)); | |
for (i = 0; i < FUNCTIONS; i++) { | |
functions[i] = functions_data; | |
functions_data += sizeof(function); | |
} | |
/* Well gee scooby I hope they gave enough arguments */ | |
if(argc != 2) | |
{ | |
printf("usage: %s {code file} \n", argv[0]); | |
return EXIT_FAILURE; | |
} | |
FILE *outputf=stdout; | |
ROM = fopen(argv[1],"rb"); | |
if (!ROM) | |
{ | |
printf("Error opening file `%s`\n",argv[1]); | |
return EXIT_FAILURE; | |
} | |
fseek(ROM, 0, SEEK_END); | |
int fend = ftell(ROM); | |
rewind(ROM); | |
buff=(char*)malloc(fend); | |
fread(buff, 1, fend, ROM); | |
fclose(ROM); | |
//#define RAM_CODE 0x8001CE60 // TODO: don't hardcode | |
#define RAM_CODE 0x800110A0 // TODO: don't hardcode | |
pc=RAM_CODE; | |
// int text_size = 0xF5260; // TODO: don't hardcode | |
int text_size = 0xD206C; // TODO: don't hardcode | |
//int data_size = fend - text_size; | |
//int rodata_size = 0; // TODO? | |
unsigned long (*words)[] = (void*)buff; | |
map_branches = 1; | |
int function_count=0; | |
sprintf(tmp, "code_Func_0"); | |
add_function(pc, tmp); | |
function_count++; | |
/* First scan - just to map out branches/jumps */ | |
for (i=0; i<(text_size >> 2); i++) | |
{ | |
if (pc == EndOfFunction+4) | |
{ | |
getOP( flip32((*words)[i]) ); | |
if((*words)[i]) | |
{ | |
sprintf(tmp, "code_Func_%i", function_count); | |
//puts(tmp); | |
if(add_function(pc, tmp))function_count++; | |
reset_gpr_regs_soft(); | |
} | |
else | |
EndOfFunction+=4; | |
} | |
getOP(flip32((*words)[i])); | |
pc+=4; | |
} | |
pc=RAM_CODE; | |
map_branches = 0; | |
reset_gpr_regs_soft(); | |
/* | |
fprintf(outputf, "/\*\n"); | |
for (i=0; i<target_count; i++) | |
{ | |
fprintf(outputf, "%s = 0x%08X;\n", functions[i]->name, functions[i]->addr); | |
} | |
fprintf(outputf, "*\/\n\n\t.text\n\t\n\t\n"); | |
*/ | |
char currFuncName[256]; | |
sprintf(currFuncName, "code_Func_0"); | |
//fprintf(outputf, "\t.set\tnoreorder\n\t.set\tnoat\n\t.global\t%s\n\t.ent\t%s\n\n", currFuncName, currFuncName); | |
fprintf(outputf, "\n%s:\t\t\t; %08X (%08X)\n", currFuncName, pc, pc - RAM_CODE); | |
function_count=1; | |
/* Second scan - fprintf()s */ | |
for (i=0; i<(text_size >> 2); i++) | |
{ | |
map_branches = 0; | |
if (pc == EndOfFunction+4) | |
{ | |
if((*words)[i]) | |
{ | |
int functionno = target2label(pc); | |
if(functionno >= 0) | |
sprintf(currFuncName, "%s", functions[functionno]->name); | |
else | |
sprintf(currFuncName, "function_%08X", pc|0x80000000); | |
//fprintf(outputf, "\t.set\tnoreorder\n\t.set\tnoat\n\t.global\t%s\n\t.ent\t%s\n\n",currFuncName, currFuncName); | |
fprintf(outputf, "\n%s:\t\t\t; %08X (%08X)\n", currFuncName, pc, pc - RAM_CODE); | |
function_count++; | |
EndOfFunction = -1; | |
} | |
else | |
EndOfFunction+=4; | |
} | |
fprintf(outputf, " \t%s\n", getOP( flip32((*words)[i]) )); | |
gpr_regs[0] = 0; /* Just in case anything tries to change $zero */ | |
if (pc == EndOfFunction && !(mapped_functions[function_count])) | |
{ | |
mapped_functions[function_count] = 1; | |
//fprintf(outputf, "\n\t.end\t%s\n\t.set\tat\n\t.set\tnoreorder\n\n",currFuncName); | |
//fprintf(outputf, "\n/* ~~~~~~~~~~ */\n"); | |
} | |
if (jaltaken) | |
{ | |
jaltaken--; | |
if (!jaltaken) | |
reset_gpr_regs_soft(); | |
} | |
pc+=4; | |
targetnum=isTarget(pc+4); | |
if (targetnum>0) | |
fprintf(outputf, "$lbl_%i:\t\t\t; %08X\n", targetnum, pc); | |
} | |
// fprintf(outputf, "\n\n\n\t.data\n\n\t/*\n\tAddr: %08X\n\t\n\t",text_size); | |
// int j; | |
// for (i=text_size; i<text_size+data_size; i+=16) | |
// { | |
// /* | |
// for (j=i;j<i+16;j+=4) | |
// fprintf(outputf, "%08X ", flip32((*words)[j>>2])); | |
// fprintf(outputf, "\n\t"); | |
// */ | |
// } | |
// if (rodata_size > 0) | |
// fprintf(outputf, "\n\t*/\n\n\t.rodata\n\n\t/*\n\tAddr: %08X\n\t\n\t",text_size+rodata_size); | |
// | |
// for (; i<text_size+data_size+rodata_size; i+=16) | |
// { | |
// for (j=i;j<i+16;j+=4) | |
// fprintf(outputf, "%08X ", flip32((*words)[j>>2])); | |
// fprintf(outputf, "\n\t"); | |
// } | |
// fprintf(outputf, "\n\t*/\n"); | |
fclose(outputf); | |
free(buff); | |
return EXIT_SUCCESS; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#CFLAGS = -ggdb -Wall | |
CFLAGS = -Ofast -Wall | |
install: all | |
cp zadis /usr/bin/zadis | |
all: | |
$(CC) $(CFLAGS) -o zadis adis.c | |
clean: | |
rm -vf adis |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment