📄 disassembler.c
字号:
case sh_op: case sw_op: case sd_op: case swl_op: case swr_op: case lwl_op: case lwr_op: case ll_op: case sc_op: sprintf(bufptr, "%s\t%s,", op_name[i.i_format.opcode], register_name(i.i_format.rt, regmask)); do_loadstore = true; break; case ori_op: case xori_op: if (i.u_format.rs == ZERO) { sprintf(bufptr, "li\t%s,%d", register_name(i.u_format.rt, regmask), i.u_format.uimmediate); break; } /* fall through */ case andi_op: sprintf(bufptr, "%s\t%s,%s,%#x", op_name[i.u_format.opcode], register_name(i.u_format.rt, regmask), register_name(i.u_format.rs, regmask), i.u_format.uimmediate); break; case lui_op: sprintf(bufptr, "%s\t%s,%#x", op_name[i.u_format.opcode], register_name(i.u_format.rt, regmask), i.u_format.uimmediate); break; case addi_op: case addiu_op: if (i.i_format.rs == ZERO) { short sign_extender = i.i_format.simmediate; sprintf(bufptr, "li\t%s,%d", register_name(i.i_format.rt, regmask), sign_extender); break; } /* fall through */ default: { short sign_extender = i.i_format.simmediate; sprintf(bufptr, "%s\t%s,%s,%d", op_name[i.i_format.opcode], register_name(i.i_format.rt, regmask), register_name(i.i_format.rs, regmask), sign_extender); } break; case cop0_op: switch (i.r_format.rs) { case bc_op: sprintf(bufptr, "bc0%s\t", bc_name[i.i_format.rt]); do_b_displacement = true; break; case mtc_op: sprintf(bufptr, "mtc0\t%s,%s", register_name(i.r_format.rt, regmask), c0_register_name(i.r_format.rd)); break; case mfc_op: sprintf(bufptr, "mfc0\t%s,%s", register_name(i.r_format.rt, regmask), c0_register_name(i.r_format.rd)); break; case cfc_op: sprintf(bufptr, "cfc0\t%s,$%d", register_name(i.r_format.rt, regmask), i.r_format.rd); break; case ctc_op: sprintf(bufptr, "ctc0\t%s,$%d", register_name(i.r_format.rt, regmask), i.r_format.rd); break; case cop_op: sprintf(bufptr, "c0\t%s", c0func_name[i.r_format.func]); break; default: sprintf(bufptr, "c0rs%d", i.r_format.rs); break; } break; case cop1_op: switch (i.r_format.rs) { case bc_op: sprintf(bufptr, "bc1%s\t", bc_name[i.i_format.rt]); do_b_displacement = true; break; case mtc_op: sprintf(bufptr, "mtc1\t%s,%s", register_name(i.r_format.rt, regmask), fp_register_name(i.r_format.rd)); break; case mfc_op: sprintf(bufptr, "mfc1\t%s,%s", register_name(i.r_format.rt, regmask), fp_register_name(i.r_format.rd)); break; case cfc_op: sprintf(bufptr, "cfc1\t%s,$%d", register_name(i.r_format.rt, regmask), i.r_format.rd); break; case ctc_op: sprintf(bufptr, "ctc1\t%s,$%d", register_name(i.r_format.rt, regmask), i.r_format.rd); break; case cop_op+s_fmt: case cop_op+d_fmt: case cop_op+e_fmt: case cop_op+w_fmt: sprintf(bufptr, "%s.%s\t", cop1func_name[i.r_format.func], c1fmt_name[i.r_format.rs - cop_op]); bufptr += strlen(bufptr); switch (i.r_format.func) { case fsqrt_op: case fabs_op: case fmov_op: case fcvts_op: case fcvtd_op: case fcvte_op: case fcvtw_op: case ftrunc_op: case fround_op: case ffloor_op: case fceil_op: sprintf(bufptr, "%s,%s", fp_register_name(i.r_format.re), fp_register_name(i.r_format.rd)); break; case fcmp_op+0x0: case fcmp_op+0x1: case fcmp_op+0x2: case fcmp_op+0x3: case fcmp_op+0x4: case fcmp_op+0x5: case fcmp_op+0x6: case fcmp_op+0x7: case fcmp_op+0x8: case fcmp_op+0x9: case fcmp_op+0xa: case fcmp_op+0xb: case fcmp_op+0xc: case fcmp_op+0xd: case fcmp_op+0xe: case fcmp_op+0xf: sprintf(bufptr, "%s,%s", fp_register_name(i.r_format.rd), fp_register_name(i.r_format.rt)); break; default: sprintf(bufptr, "%s,%s,%s", fp_register_name(i.r_format.re), fp_register_name(i.r_format.rd), fp_register_name(i.r_format.rt)); break; } /* switch on func */ } /* switch on rs */ break; /* End of cop1 */ case cop2_op: case cop3_op: { unsigned which_cop = i.j_format.opcode - cop0_op; switch (i.r_format.rs) { case bc_op: sprintf(bufptr, "bc%d%c\t", which_cop, bc_name[i.r_format.rt]); do_b_displacement = true; break; case mtc_op: sprintf(bufptr, "mtc%d\t%s,$%d", which_cop, register_name(i.r_format.rt, regmask), i.r_format.rd); break; case mfc_op: sprintf(bufptr, "mfc%d\t%s,$%d", which_cop, register_name(i.r_format.rt, regmask), i.r_format.rd); break; case cfc_op: sprintf(bufptr, "cfc%d\t%s,$%d", which_cop, register_name(i.r_format.rt, regmask), i.r_format.rd); break; case ctc_op: sprintf(bufptr, "ctc%d\t%s,$%d", which_cop, register_name(i.r_format.rt, regmask), i.r_format.rd); break; default: sprintf(bufptr, "c%d.%d\t%d", which_cop, i.r_format.rs, i.r_format.func); break; } } break; } /* Some instructions require more than just registers */ if (do_loadstore) { short sign_extender = i.i_format.simmediate; *symbol_value = sign_extender; *ls_register = i.i_format.rs; bufptr += strlen(bufptr); sprintf(bufptr, "%d(%s)", sign_extender, register_name(i.i_format.rs, regmask)); return_value = -1; } else if (do_b_displacement) { short sign_extender = i.i_format.simmediate; bufptr += strlen(bufptr); sprintf(bufptr, "%#x", address+4+(sign_extender<<2)); return_value = 2; } return return_value;}/* public - see .h file */voiddis_regs(buffer, regmask, reg_values) char *buffer; unsigned regmask; unsigned reg_values[]; { boolean first = true; unsigned i; buffer += strlen(buffer); for (i = 0; regmask; i++, regmask >>= 1) { if (regmask & 1) { sprintf(buffer, "%s%s=%#x", first ? "\t<" : ",", save.reg_names[i], reg_values[i]); buffer += strlen(buffer); first = false; } } if (!first) strcat(buffer, ">"); }#include <errno.h>extern int errno;/* public - see .h file */intdisassembler(iadr, regstyle, get_symname, get_regvalue, get_bytes, print_header) unsigned iadr; int regstyle; char *(*get_symname)(); int (*get_regvalue)(); long (*get_bytes)(); void (*print_header)(); { unsigned old_iadr = iadr; if (!get_bytes) { errno = EINVAL; return -1; } /* Don't print address, value, or (if we have get_symname) jal targets */ dis_init("", "", regstyle ? HARDWARE_NAMES : COMPILER_NAMES, ! (int) get_symname); for (; ; iadr += 4) { int which; unsigned instr, regmask, symbol_value, ls_register; char buffer[1024], *symname; instr = (unsigned) get_bytes(); if (print_header) print_header(iadr, instr); which = disasm(buffer, iadr, instr, ®mask, &symbol_value, &ls_register); /* For jal, must print the target either via get_symname or numerically */ if ((which == 1) && get_symname) if (symname = get_symname(symbol_value)) strcat(buffer, symname); else sprintf(buffer + strlen(buffer), "%#x", symbol_value); /* For load/store, if we have get_regvalue, must print the effective addr */ else if ((which < 0) && get_regvalue) sprintf(buffer + strlen(buffer), " <0x%x>", get_regvalue(ls_register) + symbol_value); /* If we have get_regvalue, we must print the registers */ if (regmask && get_regvalue) { unsigned reg_values[32], reg_cnt, regtemp; for (reg_cnt = 0, regtemp = regmask; regtemp; reg_cnt++, regtemp >>= 1) if (regtemp & 1) reg_values[reg_cnt] = get_regvalue(reg_cnt); dis_regs(buffer + strlen(buffer), regmask, reg_values); } puts(buffer); /* Quit unless we have a jump/call/branch delay slot */ if (which <= 0) return iadr - old_iadr + 4; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -