📄 disass.c
字号:
}#ifndef NO_MALLOCvoid disass_addcopro(Disass_CoProProc *f) { CoProRec *p = copros; for (; p != NULL; p = p->next) if (p->f == f) return; p = (CoProRec *)malloc(sizeof(CoProRec)); p->next = copros; p->f = f; copros = p;}#endif#ifndef NO_MALLOCvoid disass_deletecopro(Disass_CoProProc *f) { CoProRec **pp = &copros, *p; for (; (p = *pp) != NULL; pp = &p->next) if (p->f == f) { *pp = p->next; free(p); return; }}#endifstatic char *DPOp2(unsigned32 instr, unsigned32 address, char *o) { if (bit(25)) { /* rhs is immediate */ int op = (int)bits(21,24); int shift = 2*(int)bits(8,11); int32 operand = ror(bits(0,7), shift); char *oldo = o; if ((op == 4 || op == 2) && /* ADD or SUB */ bits(16,19) == 15 && /* rn = pc */ cb_proc != NULL) o = cb_proc((op == 4 ? D_ADDPCREL : D_SUBPCREL), operand, address+8, 0, cb_arg, o); if (o == oldo) { o = outh(operand, 1, o); if ((op == 4 || op == 2) && /* ADD or SUB */ bits(16,19) == 15) { /* rn = pc */ o = Dis_OutS(" ; ", o); o = outh(address+8 + ((op == 4) ? operand : -operand), 1, o); } } } else { /* rhs is a register */ o = shiftedreg(instr, o); } return o;}unsigned32 disass_32or26(unsigned32 instr, unsigned32 address, char *o, void *cba, dis_cb *cbp, int mode_32bit) { char notes[64]; notes[0] = 0; cb_proc = cbp; cb_arg = cba; switch (bits(24,27)) { case 0: if (bits(4,7) == 9) { /* Arithmetic extension space */ if (bits(22,23) == 0) { o = Dis_ArmOpCode(instr, (bit(21) ? "MLA" : "MUL"), (bit(20) ? 'S' : 0), o); o = Dis_ArmReg(bits(16,19), ',', o); o = Dis_ArmReg(bits(0,3), ',', o); o = Dis_ArmReg(bits(8,11), 0, o); if (bit(21)) { o = Dis_OutC(',', o); o = Dis_ArmReg(bits(12,15), 0, o); } break; } else if (bit(23)==1) { /* Long Multiply */ o=Dis_ArmOpCode(instr, bit(21) ? (bit(22) ? "SMLAL" : "UMLAL") : (bit(22) ? "SMULL" : "UMULL"), bit(20) ? 'S' : 0, o); o = Dis_ArmReg(bits(12,15), ',', o); o = Dis_ArmReg(bits(16,19), ',', o); o = Dis_ArmReg(bits(0,3), ',', o); o = Dis_ArmReg(bits(8,11), 0, o); break; } else { Dis_AddNote(notes, "Bad arithmetic extension op = %ld", bits(20,23)); /* And fall through to disassemble as data-processing */ } } /* Drop through */ case 1: case 2: case 3: if (bits(26,27) == 0 && bits(23,24) == 2 && !bit(20) && (bit(25) || !bit(7) || !bit(4))) { /* Control extension space */ if (!bit(25) && bits(4,7) == 1 && bits(8,19) == 0xfff && bits(21,22) == 1) { o = Dis_ArmOpCode(instr, "BX", 0, o); o = Dis_ArmReg(bits(0, 3), 0, o); break; } if (!bit(25) && bits(4,7) == 3 && bits(8,19) == 0xfff && bits(21,22) == 1) { o = Dis_ArmOpCode(instr, "BLX", 0, o); o = Dis_ArmReg(bits(0, 3), 0, o); break; } if ((bits(20,27) == 0x16) && bits(4,7) == 1){ o = Dis_ArmOpCode(instr, "CLZ", 0, o); o = Dis_ArmReg(bits(12, 15), ',', o); o = Dis_ArmReg(bits(0, 3), 0, o); break; } if (bits(4,11) == 0x05 && bits(23,27) == 2 && !bit(20)) { /* El Segundo saturated arithmetic */ char *satname = NULL; bool swap_sources = FALSE; unsigned32 src1, src2; switch(bits(21,22)) { case 0: satname = "QADD"; break; case 1: satname = "QSUB"; break; case 2: satname = "QDADD"; swap_sources = TRUE; break; case 3: satname = "QDSUB"; swap_sources = TRUE; break; } o = Dis_ArmOpCode(instr, satname, 0, o); o = Dis_ArmReg(bits(12, 15), ',', o); src1 = bits(16, 19); src2 = bits(0, 3); if (swap_sources) { unsigned32 tmpsrc = src1; src1 = src2; src2 = tmpsrc; } o = Dis_ArmReg(src1, ',', o); o = Dis_ArmReg(src2, 0, o); break; } if (bits(23, 27) == 2 && !bit(20) && !bit(4) && bit(7)) { /* El Segundo narrow multiply instructions */ char *mname = NULL; enum { fourth_reg_none, fourth_reg_is_rn, fourth_reg_is_rdlo } fourth_reg = fourth_reg_none; char mulname[10]; bool select_rm = TRUE; switch(bits(21,22)) { case 0: mname = "SMLA"; fourth_reg = fourth_reg_is_rn; break; case 1: select_rm = FALSE; if (bit(5)) { mname = "SMULW"; } else { mname = "SMLAW"; fourth_reg = fourth_reg_is_rn; } break; case 2: mname = "SMLAL"; fourth_reg = fourth_reg_is_rdlo; break; case 3: mname = "SMUL"; break; } strcpy(mulname, mname); if (select_rm) strcat(mulname, bit(5) ? "T" : "B"); strcat(mulname, bit(6) ? "T" : "B"); o = Dis_ArmOpCode(instr, mulname, 0, o); if (fourth_reg == fourth_reg_is_rdlo) o = Dis_ArmReg(bits(12, 15), ',', o); o = Dis_ArmReg(bits(16, 19), ',', o); o = Dis_ArmReg(bits(0, 3), ',', o); o = Dis_ArmReg(bits(8, 11), ","[fourth_reg != fourth_reg_is_rn], o); if (fourth_reg == fourth_reg_is_rn) o = Dis_ArmReg(bits(12, 15), 0, o); break; } if (!bit(25) && !bit(21)) { o = Dis_ArmOpCode(instr, "MRS", 0, o); o = Dis_ArmReg(bits(12,15), ',', o); o = Dis_OutS(!bit(22) ? "CPSR" : "SPSR", o); Dis_CheckZero(bits(0,11), "0-11", notes); Dis_CheckValue(bits(16,19), 15, "Rn", notes); break; } if (bit(21)) { const char *rname = !bit(22) ? "CPSR" : "SPSR"; int rn = (int)bits(16, 19); char flags[8]; char *f = flags; *f++ = '_'; if (rn & 1) *f++ = 'c'; if (rn & 2) *f++ = 'x'; if (rn & 4) *f++ = 's'; if (rn & 8) *f++ = 'f'; if (rn == 0) Dis_AddNote(notes, "field-mask = 0"); *f++ = ','; *f = '\0'; o = Dis_ArmOpCode(instr, "MSR", 0, o); o = Dis_OutS(rname, o); o = Dis_OutS(flags, o); Dis_CheckValue(bits(12,15), 15, "Rd", notes); if (!bit(25)) Dis_CheckZero(bits(4,11), "4-11", notes); o = DPOp2(instr, address, o); break; } Dis_AddNote(notes, "Bad control extension op"); } if (bits(25,27) == 0 && bit(7) && bit(4) && (bit(24) || bits(5,6))) { /* Load-store extension space */ if (bits(23,24) == 2 && bits(20,21) == 0 && bits(4,11) == 9) { /* Swap */ o = Dis_ArmOpCode(instr, "SWP", (bit(22) ? 'B' : 0), o); o = Dis_ArmReg(bits(12,15), ',', o); o = Dis_ArmReg(bits(0,3), ',', o); o = Dis_OutC('[', o); o = Dis_ArmReg(bits(16,19), ']', o); break; } if (bit(20) ? bits(5,6) != 0 : bits(5,6) == 1) { char *start = o; o = Dis_OutS(bit(20) ? "LDR" : "STR", o); o = Dis_cond(instr, o); if (bit(6)) { o = Dis_OutC('S', o); o = Dis_OutC(bit(5) ? 'H' : 'B', o); } else o = Dis_OutC('H', o); o = Dis_spacetocol9(start, o); o = Dis_ArmReg(bits(12,15), ',', o); o = Dis_OutC('[', o); o = Dis_ArmReg(bits(16,19), 0, o); if (bit(24)) o = Dis_OutC(',', o); else o = Dis_OutC(']', o), o = Dis_OutC(',', o); if (bit(22)) { o = outh(bits(0, 3) + (bits(8,11)<<4), bit(23), o); } else { if (!bit(23)) o = Dis_OutC('-',o); o = Dis_ArmReg(bits(0,3),0,o); } if (bit(24)) { o = Dis_OutC(']', o); if (bit(21)) o = Dis_OutC('!', o); } else if (bit(21)) Dis_AddNote(notes, "Post-indexed, W=1"); break; } Dis_AddNote(notes, "Bad load/store extension op"); } if (instr == 0xe1a00000L) { o = Dis_ArmOpCode(instr, "NOP", 0, o); break; } { /* data processing */ int op = (int)bits(21,24); const char *opnames = "AND\0EOR\0SUB\0RSB\0ADD\0ADC\0SBC\0RSC\0\TST\0TEQ\0CMP\0CMN\0ORR\0MOV\0BIC\0MVN"; unsigned32 rd = bits(12,15); int ch = (!bit(20)) ? 0 : (op>=8 && op<12) ? (rd==15 ? 'P' : 0) : 'S'; o = Dis_ArmOpCode(instr, opnames+4*op, ch, o); if (op >= 8 && op < 12) { /* TST TEQ CMP CMN */ if (rd != 15) Dis_CheckZero(rd, "Rd", notes); } else { /* print the dest reg */ o = Dis_ArmReg(rd, ',', o); } if (op == 13 || op == 15) { /* MOV MVN */ Dis_CheckZero(bits(16,19), "Rn", notes); } else { o = Dis_ArmReg(bits(16,19), ',', o); } o = DPOp2(instr, address, o); } break; case 0xa: case 0xb: if (bits(25,31) == 0x7d) { char *start = o ; o = Dis_OutS("BLX", o); o = Dis_spacetocol9(start, o); } else o = Dis_ArmOpCode(instr, (bit(24) ? "BL" : "B"), 0, o); { int32 offset = (((int32)bits(0,23))<<8)>>6; /* sign extend and * 4 */ char *oldo = o; if (bits(24,31) == 0xfb) offset |= bit(24) >> 23 ; address += offset + 8; if (!mode_32bit) address &= 0x3ffffffL; if (cb_proc != NULL) o = cb_proc(D_BORBL, offset, address, 0, cb_arg, o); if (o == oldo) o = Dis_OutX(address, o); } break; case 6: case 7: /* Cope with the case where register shift register is specified * as this is an undefined instruction rather than an LDR or STR */ if (bit(4)) { o=Dis_OutS("Undefined Instruction",o); break; } /* Drop through to alwasy LDR / STR case */ case 4: case 5: { char *start = o; o = Dis_OutS(bit(20) ? "LDR" : "STR", o); o = Dis_cond(instr, o); if (bit(22)) o = Dis_OutC('B', o); if (!bit(24) && bit(21)) /* post, writeback */ o = Dis_OutC('T', o); o = Dis_spacetocol9(start, o); o = Dis_ArmReg(bits(12,15), ',', o); o = Dis_ArmOutAddress(instr, address, bits(0,11), (bit(22) ? 1 : 4), o); break; } case 8: case 9: { char *start = o; o = Dis_OutS(bit(20) ? "LDM" : "STM", o); o = Dis_cond(instr, o); o = Dis_OutS("DA\0\0IA\0\0DB\0\0IB" + 4*(int)bits(23,24), o); o = Dis_spacetocol9(start, o); o = Dis_ArmReg(bits(16,19), 0, o); if (bit(21)) o = Dis_OutC('!', o); o = Dis_OutC(',', o); o = outregset(instr, o); if (bit(22)) o = Dis_OutC('^', o); break; } case 0xf: o = Dis_ArmOpCode(instr, "SWI", 0, o); { char *oldo = o; int32 swino = bits(0,23); if (cb_proc != NULL) o = cb_proc(D_SWI, swino, 0, 0, cb_arg, o); if (o == oldo) o = Dis_OutX(swino, o); } break; case 0xe: o = HandleCoPro(bit(4)==0 ? CP_DP : CP_RT, instr, address, o, notes); break; case 0xc: case 0xd: o = HandleCoPro(CP_DT, instr, address, o, notes); break; default: o = Dis_OutS("EQUD ", o); o = Dis_OutX(instr, o); } if (notes[0] != 0) o = Dis_OutF(o, " ; ? %s", notes); o = Dis_OutC('\0', o); return 4;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -