📄 disass.c
字号:
o = Dis_OutC(fp_widthname(instr), o); /* Field with only for FLT */ if (op == 0 || op == 1) o = Dis_OutS(fp_rounding(instr), o); /* Rounding mode for FLT/FIX */ o = Dis_spacetocol9(start, o); if (op == 0) /* FLT */ { o = FP_Reg(bits(16,18), ',', o); } o = Dis_ArmReg(bits(12,15), 0, o); if (op == 1) /* FIX */ { o = Dis_OutC(',', o); o = fp_mfield(instr, o); } } return o;}static char *fp_cpdt(unsigned32 instr, unsigned32 address, char *o, char *notes) { if (!bit(24) && !bit(21)) Dis_AddNote(notes, "Postindexed, no WB"); o = Dis_ArmOpCode(instr, (bit(20) ? "LDF" : "STF"), fp_dt_widthname(instr), o); o = FP_Reg(bits(12,14), ',', o); return Dis_ArmOutAddress(instr, address, 4*bits(0,7), 0, o);}static char *fm_cpdt(unsigned32 instr, unsigned32 address, char *o, char *notes) { if (!bit(24) && !bit(21)) Dis_AddNote(notes, "Postindexed, no WB"); o = Dis_ArmOpCode(instr, (bit(20) ? "LFM" : "SFM"), 0, o); o = FP_Reg(bits(12,14), ',', o); { int count = (int)(bit(15) + 2*bit(22)); o = Dis_OutF(o, "%d,", count==0 ? 4: count); } o = Dis_ArmOutAddress(instr, address, 4*bits(0,7), 0, o); return o;}static char *HandleFP( int cpno, Disass_CPOpType type, unsigned32 instr, unsigned32 address, char *o, char *notes) { switch (type) { case CP_DP: if (cpno == 1) return fp_cpdo(instr, o, notes); break; case CP_RT: if (cpno == 1) return fp_cprt(instr, o, notes); break; case CP_DT: if (cpno == 1) return fp_cpdt(instr, address, o, notes); else if (cpno == 2) return fm_cpdt(instr, address, o, notes); break; } return NULL;}void disass_setregnames(char const **rn, char const **fn) { regnames = rn; fregnames = fn;}void disass_sethexprefix(char const *p) { hexprefix = p;}unsigned32 disass_16(unsigned32 instr, unsigned32 instr2, unsigned32 address, char *o, void *cba, dis_cb *cbp){ int32 Rd, Rm, Rn, Ro; int32 imm5, imm8, imm11; int32 L, B; Rd = bits(0, 2); Rm = bits(3, 5); Rn = bits(6, 8); Ro = bits(8, 10);#define imm3 Rn imm11 = bits(0, 10); imm8 = bits(0, 7); imm5 = bits(6, 10); L = bit(11);#define SP (L)#define H (L) B = bit(10);#define S B#define I B switch (bits(11, 15)) { case 3: if (bit(9) == 0 && I && imm3 == 0) { o = t_opcode("MOV", o); o = Dis_ArmReg(Rd, ',', o); o = Dis_ArmReg(Rm, 0, o); break; } o = t_opcode(bit(9) ? "SUB" : "ADD", o); o = Dis_ArmReg(Rd, ',', o); if (Rd != Rm) o = Dis_ArmReg(Rm, ',', o); o = I ? outh(imm3, 1, o) : Dis_ArmReg(Rn, 0 , o); break; case 10: case 11: o = t_opcode("STR\0*STRH\0STRB\0LDSB\0LDR\0*LDRH\0LDRB\0LDSH" + bits(9, 11) * 5, o); o = Dis_ArmReg(Rd, ',', o); o = Dis_OutC('[', o); o = Dis_ArmReg(Rm, ',', o); o = Dis_ArmReg(Rn, ']', o); break; case 12: case 13: imm5 <<= 1; case 16: case 17: imm5 <<= 1; case 14: case 15: o = t_opcode("STR\0*LDR\0*STRB\0LDRB\0STRH\0LDRH\0" + (bits(11, 15) - 12) * 5, o); o = Dis_ArmReg(Rd, ',', o); o = Dis_OutC('[', o); o = Dis_ArmReg(Rm, ',', o); o = outh(imm5, 1, o); o = Dis_OutC(']', o); break; case 0: case 1: case 2: o = t_opcode("LSL\0LSR\0ASR" + bits(11, 12) * 4, o); o = Dis_ArmReg(Rd, ',', o); if (Rd != Rm) o = Dis_ArmReg(Rm, ',', o); if (bits(11, 12) > 0 && imm5 == 0) imm5 = 32; /* LSR/ASR 0 -> LSR/ASR 32 */ o = Dis_OutF(o, "#%ld", imm5); break; case 8: { int32 op; op = bits(6, 10); if (op < 16) { o = t_opcode("AND\0EOR\0LSL\0LSR\0ASR\0ADC\0SBC\0ROR\0TST\0NEG\0CMP\0CMN\0ORR\0MUL\0BIC\0MVN" + op * 4, o); } else { if (op & 2) Rd += 8; if (op & 1) Rm += 8; switch(op) { case 17: case 18: case 19: o = t_opcode("ADD", o); break; case 21: case 22: case 23: o = t_opcode("CMP", o); break; case 25: case 26: case 27: o = t_opcode("MOV", o); break; case 16: case 20: case 24: o = t_opcode("Undefined", o); o = Dis_OutC(0, o); return 2; case 28: case 29: o = t_opcode("BX", o); o = Dis_ArmReg(Rm, 0, o); o = Dis_OutC(0, o); return 2; case 30: case 31: o = t_opcode("BLX", o); o = Dis_ArmReg(Rm, 0, o); o = Dis_OutC(0, o); return 2; } } o = Dis_ArmReg(Rd, ',', o); o = Dis_ArmReg(Rm, 0, o); break; } case 4: case 5: case 6: case 7: o = t_opcode("MOV\0CMP\0ADD\0SUB" + bits(11, 12) * 4, o); o = Dis_ArmReg(Ro, ',', o); o = outh(imm8, 1, o); break; case 18: case 19: { char *oldo; o = t_opcode("STR\0LDR" + L * 4, o); o = Dis_ArmReg(Ro, ',', o); imm8 <<= 2; oldo = o; if (cbp) o = cbp(L ? D_LOAD : D_STORE, imm8, 13, 4, cba, o); if (o == oldo) { o = Dis_OutC('[', o); o = Dis_ArmReg(13, ',', o); o = outh(imm8, 1, o); o = Dis_OutC(']', o); } break; } case 28: { char *oldo; o = t_opcode("B", o); imm11 = (imm11 << 21) / (1 << 20); oldo = o; if (cbp) o = cbp(D_BORBL, imm11, address + imm11 + 4, 0, cba, o); if (o == oldo) o = Dis_OutX(address + imm11 + 4, o); break; } case 22: case 23: if (!bit(10)) { if (bits(8, 11) != 0) { o = t_opcode("Undefined", o); } else { imm8 = (imm8 & 0x7f) << 2; o = t_opcode(bit(7) ? "SUB" : "ADD", o); o = Dis_ArmReg(13, ',', o); o = outh(imm8, 1, o); } } else { if (bit(9)) { o = t_opcode("Undefined", o); } else { instr &= 0x1ff; if (instr & 0x100) { instr &= ~0x100; if (L) instr |= 0x8000; else instr |= 0x4000; } o = t_opcode("PUSH\0POP" + L * 5, o); o = outregset(instr, o); } } break; case 9: { char *oldo; o = t_opcode("LDR", o); o = Dis_ArmReg(Ro, ',', o); imm8 <<= 2; oldo = o; address = (address + 4) & ~3; if (cbp) o = cbp(D_LOADPCREL, imm8, address + imm8, 0, cba, o); if (o == oldo) o = Dis_OutX(address + imm8, o); break; } case 24: case 25: instr &= 0xff; o = t_opcode("STMIA\0LDMIA" + L * 6, o); o = Dis_ArmReg(Ro, '!', o); o = Dis_OutC(',', o); o = outregset(instr, o); break; case 20: case 21: { char *oldo; o = t_opcode("ADR\0ADD" + SP * 4, o); o = Dis_ArmReg(Ro, ',', o); imm8 <<= 2; if (!SP) { oldo = o; address = (address + 4) & ~3; if (cbp) o = cbp(D_ADDPCREL, imm8, address + imm8, 0, cba, o); if (o == oldo) o = Dis_OutX(address + imm8, o); } else { o = Dis_ArmReg(13, ',', o); o = outh(imm8, 1, o); } break; } case 26: case 27: { char *oldo; int32 op; op = bits(8, 11); if (op == 15) { o = t_opcode("SWI", o); oldo = o; if (cbp) cbp(D_SWI, imm8, 0, 0, cba, o); if (o == oldo) o = Dis_OutX(imm8, o); } else { o = Dis_ArmOpCode(op << 28, "B", 0, o); imm8 = (imm8 << 24) / (1 << 23); oldo = o; if (cbp) o = cbp(D_BORBL, imm8, address + imm8 + 4, 0, cba, o); if (o == oldo) o = Dis_OutX(address + imm8 + 4, o); } break; } case 30: { int32 offset; char *oldo; if ((instr2 & 0xe800) == 0xe800) { if (instr2 & 0x1000) o = t_opcode("BL", o); else o = t_opcode("BLX", o); offset = instr2 & 0x7ff; offset = (((imm11 << 11) | offset) << 10) / (1 << 9); oldo = o; if (cbp) o = cbp(D_BORBL, offset, address + offset + 4, 0, cba, o); if (o == oldo) o = Dis_OutX(address + offset + 4, o); o = Dis_OutC(0, o); return 4; } else { o = t_opcode("???", o); } break; } case 29: case 31: o = t_opcode("???", o); break; default: o = t_opcode("Undefined", o); break; } o = Dis_OutC(0, o); return 2;}#undef imm3#undef SP#undef S#undef H#undef H1#undef H2unsigned32 disass(unsigned32 instr, unsigned32 address, char *o, void *cba, dis_cb *cbp){ disass_32or26(instr, address, o, cba, cbp, 0); return 4;}typedef struct CoProRec CoProRec;struct CoProRec { CoProRec *next; Disass_CoProProc *f;};#define NextCoProRec NULL#ifdef PICCOLO#include "picdis.h"static CoProRec PicCoProRec = { NextCoProRec, piccolo_DisassCP };#undef NextCoProRec#define NextCoProRec (&PicCoProRec)#endifstatic CoProRec FPCoProRec = { NextCoProRec, HandleFP };static CoProRec *copros = &FPCoProRec;static char *HandleCoPro( Disass_CPOpType type, unsigned32 instr, unsigned32 address, char *o, char *notes) { CoProRec *p = copros; int cpno = bits(8, 11); for (; p != NULL; p = p->next) { char *res = p->f(cpno, type, instr, address, o, notes); if (res != NULL) return res; } return HandleGenericCoPro(cpno, type, instr, address, o, notes);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -