📄 dis16.c
字号:
/************************************************************* * File: dis16.c * Purpose: disassembler for mips16 * Author: Phil Bunce (pjb@carmel.com) * Revision History: * 970505 Created * 980107 Corrected typedef for dis16fmt * 980715 Fixed for -EL mips16 * 990107 Fixed prob with extended instrs * 990303 Fixed disassembly of lbu */#include <mon.h>#include <stdio.h>#define RXN(i) (((i)>>8)&7)#define RYN(i) (((i)>>5)&7)#define RZN(i) (((i)>>2)&7)#define R32AN(i) (((i)>>0)&0x1f)#define R32BN(i) (((i)&0x18)|((i)>>5)&7)#define RX(i) gp16regs[RXN(i)]#define RY(i) gp16regs[RYN(i)]#define RZ(i) gp16regs[RZN(i)]#define SA(i) ((((i)>>2)&7)?(((i)>>2)&7):8)#define R32A(i) gp32regs[R32AN(i)]#define R32B(i) gp32regs[R32BN(i)]typedef enum { RA_O_SP, RX_O_SP, RY_O_RX1, RY_O_RX2, RX_O_PC, RX_I8, RX_UI8, RX_PC_I8, RX_SP_I8, RY_RX_I4, SP_I8, RZ_RX_RY, R32B_RZ, RY_R32A, RX_RY_SA, JAL_TARG, RX_RY, OFFSET8_ONLY, RY_I5, RY_PC_I5, RY_SP_I5, RY_O_SP3, RY_O_RX3, RY_O_PC, RY_O_RX0, RX_ONLY, RA_ONLY, RA_RX, OFFSET11_ONLY, RX_OFFSET, IMM6_ONLY, RY_RX, RY_SA, NO_OPS, JALX_TARG, JR_RX } dis16fmt;enum { SIMM4, SIMM5, UIMM5, UIMM8, SIMM8, SIMM11, SIMM15, UIMM16, SIMM16, SIMM16S};typedef struct Dis16Rec { char *name; Ulong mask; Ulong val; int fmt; } Dis16Rec;Dis16Rec dis16tbl[] = { {"jal", 0xfc00,0x1800,JAL_TARG}, {"jalx", 0xfc00,0x1c00,JALX_TARG}, {"nop", 0xffff,0x6500,NO_OPS}, {"addiu", 0xf800,0x0000,RX_SP_I8}, /* rx, sp, imm8 */ {"addiu", 0xf800,0x0800,RX_PC_I8}, /* rx, pc, imm8 */ {"addiu", 0xf800,0x4800,RX_I8}, /* rx, imm8 */ {"addiu", 0xf810,0x4000,RY_RX_I4}, /* ry, rx, imm4 */ {"addiu", 0xff00,0x6300,SP_I8}, /* sp, imm8 */ {"addu", 0xf803,0xe001,RZ_RX_RY}, /* rz,rx,ry */ {"and", 0xf81f,0xe80c,RX_RY}, {"b", 0xf800,0x1000,OFFSET11_ONLY}, {"beqz", 0xf800,0x2000,RX_OFFSET}, {"bnez", 0xf800,0x2800,RX_OFFSET}, {"break", 0xf81f,0xe805,IMM6_ONLY}, {"bteqz", 0xff00,0x6000,OFFSET8_ONLY}, {"btnez", 0xff00,0x6100,OFFSET8_ONLY}, {"cmp", 0xf800,0x7000,RX_I8}, {"cmp", 0xf81f,0xe80a,RX_RY},#if 0 /* 64-bit */ {"daddiu",0xf810,0x4010,RY_RX_I4}, {"daddiu",0xff00,0xfb00,SP_I8}, {"daddiu",0xff00,0xfd00,RY_I5}, {"daddiu",0xff00,0xfe00,RY_PC_I5}, {"daddiu",0xff00,0xff00,RY_SP_I5}, {"daddu", 0xf803,0xe000,RZ_RX_RY}, {"ddiv", 0xf81f,0xe81e,RX_RY}, {"ddivu", 0xf81f,0xe81f,RX_RY}, {"dmult", 0xf81f,0xe81c,RX_RY}, {"dmultu",0xf81f,0xe81d,RX_RY}, {"dsll", 0xf803,0x3001,RX_RY_SA}, {"dsll", 0xf81f,0xe814,RY_RX}, {"dsra", 0xf81f,0xe813,RY_SA}, {"dsra", 0xf81f,0xe817,RY_RX}, {"dsrl", 0xf81f,0xe808,RY_SA}, {"dsrl", 0xf81f,0xe816,RY_RX}, {"dsubu", 0xf803,0xe002,RZ_RX_RY}, {"lwu", 0xf800,0xb800,RY_O_RX2}, /* ry,off(rx) */ {"ld", 0xf800,0x3800,RY_O_RX3}, {"ld", 0xff00,0xf800,RY_O_SP3}, {"ld", 0xff00,0xfc00,RY_O_PC}, {"sd", 0xff00,0xfa00,RA_O_SP}, {"sd", 0xf800,0x7800,RY_O_RX3}, {"sd", 0xff00,0xf900,RY_O_SP3},#endif {"div", 0xf81f,0xe81a,RX_RY}, {"divu", 0xf81f,0xe81b,RX_RY}, {"jalr", 0xf8ff,0xe840,RA_RX}, {"jr", 0xf8ff,0xe800,JR_RX}, {"jr", 0xffff,0xe820,RA_ONLY}, {"lb", 0xf800,0x8000,RY_O_RX0}, {"lh", 0xf800,0x8800,RY_O_RX1}, /* ry,off(rx) */ {"lbu", 0xf800,0xa000,RY_O_RX0}, {"lhu", 0xf800,0xa800,RY_O_RX1}, /* ry,off(rx) */ {"li", 0xf800,0x6800,RX_UI8}, {"lw", 0xf800,0x9000,RX_O_SP}, /* rx,off(sp) */ {"lw", 0xf800,0x9800,RY_O_RX2}, /* ry,off(rx) */ {"lw", 0xf800,0xb000,RX_O_PC}, /* rx,off(pc) */ {"mfhi", 0xf8ff,0xe810,RX_ONLY}, {"mflo", 0xf8ff,0xe812,RX_ONLY}, {"mult", 0xf81f,0xe818,RX_RY}, {"multu", 0xf81f,0xe819,RX_RY}, {"move", 0xff00,0x6500,R32B_RZ}, {"move", 0xff00,0x6700,RY_R32A}, {"neg", 0xf81f,0xe80b,RX_RY}, {"not", 0xf81f,0xe80f,RX_RY}, {"or", 0xf81f,0xe80d,RX_RY}, {"sb", 0xf800,0xc000,RY_O_RX0}, /* ry,off(rx) */ {"sh", 0xf800,0xc800,RY_O_RX1}, /* ry,off(rx) */ {"sll", 0xf803,0x3000,RX_RY_SA}, {"sllv", 0xf81f,0xe804,RY_RX}, {"slt", 0xf81f,0xe802,RX_RY}, {"slti", 0xf800,0x5000,RX_I8}, {"sltiu", 0xf800,0x5800,RX_I8}, {"sltu", 0xf81f,0xe803,RX_RY}, {"sra", 0xf803,0x3003,RX_RY_SA}, {"srav", 0xf81f,0xe807,RY_RX}, {"srl", 0xf803,0x3002,RX_RY_SA}, {"srlv", 0xf81f,0xe806,RY_RX}, {"subu", 0xf803,0xe803,RZ_RX_RY}, {"sw", 0xff00,0x6200,RA_O_SP}, /* ra,off(sp) */ {"sw", 0xf800,0xd000,RX_O_SP}, /* rx,off(sp) */ {"sw", 0xf800,0xd800,RY_O_RX2}, /* ry,off(rx) */ {"xor", 0xf81f,0xe80e,RX_RY}, {0}};char *gp16regs[] = {"s0","s1","v0","v1","a0","a1","a2","a3"};char gp16regNum[] = {16,17,2,3,4,5,6,7};char *gp32regs[] = {"zero","AT","v0","v1","a0","a1","a2","a3","t0,","t1","t2","t3","t4","t5","t6","t7","s0","s1","s2","s3","s4","s5","s5","s6","s7","t8","t9","k0","k1","gp","sp", "s8","ra"};static Ulong imm();static Ulong sgnext();#define swap_halves(v) ((((Ulong)(v))>>16)&0xffff) | \ ((((Ulong)(v))<<16)&0xffff0000);/* hw0 and hw1 are for accessing half-word zero and half-word on.* Half-word zero is always the first read from memory (ie the occupying* the lowest numbered address).*/#ifdef MIPSEB#define hw0(v) (((Ulong)(v))>>16)#define hw1(v) (((Ulong)(v))&0xffff)#else#define hw0(v) (((Ulong)(v))&0xffff)#define hw1(v) (((Ulong)(v))>>16)#endifstatic Ulong getInst(Ulong instr);static int mips16_32bit_instr(Ulong instr);static Dis16Rec *getDis16Rec(Ulong instr);static Ulong get16Gpr(int n);/**************************************************************/Ulong dis16(prnbuf,addr,wd)char *prnbuf;Ulong addr,wd;{int n,sz,extended;char tmp[200];Ulong im,vaddr,instr;Dis16Rec *t;vaddr = addr&~1;instr = getInst(wd);extended = 0;if (mips16_32bit_instr(wd)) { addr += 2; sprintf(tmp," %04x%04x ",hw0(wd),hw1(wd)); extended = 1; }else sprintf(tmp," %04x ",instr);strcat(prnbuf,tmp);if ((t=getDis16Rec(wd))==0) { sprintf(tmp,".half %04x",instr); strcat(prnbuf,tmp); return(addr+2); }n = strlen(t->name);strcat(prnbuf,t->name);while(n++ < 8) strcat(prnbuf," ");switch (t->fmt) { case NO_OPS : *tmp=0; break; case RY_I5: im = imm(instr,(!extended)?SIMM5:SIMM16,wd,0); sprintf(tmp,"%s,%d",RY(instr),im); strcat(prnbuf,tmp); *tmp = 0; mkcomment(prnbuf,"# 0x%08lx",im); break; case RY_PC_I5: im = imm(instr,(!extended)?UIMM5:UIMM16,wd,2); sprintf(tmp,"%s,pc,%d",RY(instr),im); strcat(prnbuf,tmp); *tmp = 0; mkcomment(prnbuf,"# 0x%08lx",vaddr+im); break; case RY_SP_I5: im = imm(instr,(!extended)?UIMM5:UIMM16,wd,2); sprintf(tmp,"%s,sp,%d",RY(instr),im); strcat(prnbuf,tmp); *tmp = 0; mkcomment(prnbuf,"# 0x%08lx",im); break; case IMM6_ONLY: im = (instr>>5)&0x3f; sprintf(tmp,"%d",im); break; case RX_RY: sprintf(tmp,"%s,%s",RX(instr),RY(instr)); break; case RA_RX: sprintf(tmp,"ra,%s",RX(instr)); break; case RA_ONLY: sprintf(tmp,"ra"); break; case RX_ONLY: case JR_RX : sprintf(tmp,"%s",RX(instr)); break; case JAL_TARG: im = ((hw0(wd)&0x1f)<<21)| ((hw0(wd)&0x3e0)<<(16-5))| hw1(wd); im = (vaddr&0xf0000000)|(im<<2); if (!adr2symoff(tmp,im+1,0)) sprintf(tmp,"%x",im); strcat(prnbuf,tmp); *tmp = 0; mkcomment(prnbuf,"# 0x%08lx",im); break; case JALX_TARG: im = ((hw0(wd)&0x1f)<<21)| ((hw0(wd)&0x3e0)<<(16-5))| hw1(wd); im = (vaddr&0xf0000000)|(im<<2); if (!adr2symoff(tmp,im,0)) sprintf(tmp,"%x",im); strcat(prnbuf,tmp); *tmp = 0; mkcomment(prnbuf,"# 0x%08lx",im); break; case RX_RY_SA: sprintf(tmp,"%s,%s,%d",RX(instr),RY(instr),SA(instr)); break; case RY_SA: sprintf(tmp,"%s,%d",RY(instr),SA(instr)); break; /* ry,im,rx */ case RY_O_RX0: im = imm(instr,(!extended)?UIMM5:SIMM16,wd,0); sprintf(tmp,"%s,%d(%s)",RY(instr),im,RX(instr)); break; case RY_O_RX1: im = imm(instr,(!extended)?UIMM5:SIMM16,wd,1); sprintf(tmp,"%s,%d(%s)",RY(instr),im,RX(instr)); break; case RY_O_RX2: im = imm(instr,(!extended)?UIMM5:SIMM16,wd,2); sprintf(tmp,"%s,%d(%s)",RY(instr),im,RX(instr)); break; case RY_O_RX3: im = imm(instr,(!extended)?UIMM5:SIMM16,wd,3); sprintf(tmp,"%s,%d(%s)",RY(instr),im,RX(instr)); break; /* rx,im,im */ case RX_OFFSET: /* RX_IM_IM, SIMM8, SIMM16S, 1, $addr+2 */ sz = instr_size(addr,instr); im = vaddr+sz+imm(instr,(!extended)?SIMM8:SIMM16S,wd,1); sprintf(tmp,"%s,",RX(instr)); strcat(prnbuf,tmp); if (!adr2symoff(tmp,im+1,0)) sprintf(tmp,"%x",im); strcat(prnbuf,tmp); *tmp = 0; mkcomment(prnbuf,"# 0x%08lx",im); break; case RY_O_SP3: im = imm(instr,(!extended)?UIMM8:SIMM16,wd,3); sprintf(tmp,"%s,%d(sp)",RY(instr),im); break; case RX_O_SP: im = imm(instr,(!extended)?UIMM8:SIMM16,wd,2); sprintf(tmp,"%s,%d(sp)",RX(instr),im); break; case RX_I8: im = imm(instr,(!extended)?SIMM8:UIMM16,wd,0); sprintf(tmp,"%s,%d",RX(instr),im); strcat(prnbuf,tmp); *tmp = 0; mkcomment(prnbuf,"# 0x%08lx",im); break; case RX_UI8: im = imm(instr,(!extended)?UIMM8:UIMM16,wd,0); sprintf(tmp,"%s,%d",RX(instr),im); strcat(prnbuf,tmp); *tmp = 0; mkcomment(prnbuf,"# 0x%08lx",im); break; case RX_SP_I8: im = imm(instr,(!extended)?UIMM8:UIMM16,wd,2); sprintf(tmp,"%s,sp,%d",RX(instr),im); strcat(prnbuf,tmp); *tmp = 0; mkcomment(prnbuf,"# 0x%08lx",im); break; /* ry,rx,im */ case RY_RX_I4: im = imm(instr,(!extended)?SIMM4:SIMM15,wd,0); sprintf(tmp,"%s,%s,%d",RY(instr),RX(instr),im); break; /* rx,im,addr+im */ case RY_O_PC: im = imm(instr,(!extended)?UIMM8:SIMM16,wd,2); sprintf(tmp,"%s,%d(pc)",RY(instr),im); strcat(prnbuf,tmp); *tmp = 0; mkcomment(prnbuf,"# 0x%08lx",vaddr+im); break; case RX_O_PC: im = imm(instr,(!extended)?UIMM8:SIMM16,wd,2); sprintf(tmp,"%s,%d(pc)",RX(instr),im); strcat(prnbuf,tmp); *tmp = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -