int idaapi emu( void ) { uint32 Feature = cmd.get_canon_feature(); flow = ((Feature & CF_STOP) == 0); if( Feature & CF_USE1 ) TouchArg( cmd.Op1, 1 ); if( Feature & CF_USE2 ) TouchArg( cmd.Op2, 1 ); if( Feature & CF_USE3 ) TouchArg( cmd.Op3, 1 ); if( Feature & CF_JUMP ) QueueMark( Q_jumps, cmd.ea ); if( Feature & CF_CHG1 ) TouchArg( cmd.Op1, 0 ); if( Feature & CF_CHG2 ) TouchArg( cmd.Op2, 0 ); if( Feature & CF_CHG3 ) TouchArg( cmd.Op3, 0 ); switch ( cmd.itype ) { case I196_popa: splitSRarea1(cmd.ea, WSR, BADSEL, SR_auto); splitSRarea1(cmd.ea, WSR1, BADSEL, SR_auto); break; } if( flow ) ua_add_cref( 0, cmd.ea+cmd.size, fl_F ); return 1; }
//---------------------------------------------------------------------- int emu(void) { uint32 Feature = cmd.get_canon_feature(); flow = ((Feature & CF_STOP) == 0); if ( Feature & CF_USE1 ) TouchArg(cmd.Op1,1); if ( Feature & CF_USE2 ) TouchArg(cmd.Op2,1); if ( Feature & CF_JUMP ) QueueMark(Q_jumps,cmd.ea); if ( Feature & CF_CHG1 ) TouchArg(cmd.Op1,0); if ( Feature & CF_CHG2 ) TouchArg(cmd.Op2,0); if ( flow && canFlow() ) ua_add_cref(0,cmd.ea+cmd.size,fl_F); switch ( cmd.itype ) { case TMS_ldp: // change DP register case TMS2_ldp: // change DP register case TMS2_ldpk: // change DP register { uint v = (cmd.Op1.type == o_imm) ? uint(cmd.Op1.value) : -1u; splitSRarea1(get_item_end(cmd.ea),rDP,v,SR_auto); } break; } return 1; }
void LDD(insn_t &cmd) { int DPR[]={ rDPR0, rDPR1, rDPR2, rDPR3 }; if ( cmd.Op1.value==0x1 && cmd.Op1.value==0x2 && cmd.Op1.value==0x4 && cmd.Op1.value==0x8 ) { switch ( cmd.Op1.value ) { case 0x1: splitSRarea1(cmd.ea+cmd.size, rDPR0, cmd.Operands[1+0].value, SR_auto); break; case 0x2: splitSRarea1(cmd.ea+cmd.size, rDPR1, cmd.Operands[1+1].value, SR_auto); break; case 0x4: splitSRarea1(cmd.ea+cmd.size, rDPR2, cmd.Operands[1+2].value, SR_auto); break; case 0x8: splitSRarea1(cmd.ea+cmd.size, rDPR3, cmd.Operands[1+3].value, SR_auto); break; } } else { for(int i=0; i<4; i++) { if( GETBIT(cmd.Op1.value, i) == 1 ) { splitSRarea1(cmd.ea+cmd.size, DPR[i], cmd.Operands[1+i].value, SR_auto); } // if } //for }//else }
//---------------------------------------------------------------------- static void TouchArg( op_t &x, int isload ) { switch( x.type ) { case o_imm: doImmd(cmd.ea); if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, OOF_SIGNED); break; case o_indexed: // addr[value] doImmd(cmd.ea); if ( x.value == 0 && !isDefArg(uFlag, x.n) ) set_offset(cmd.ea, x.n, toEA(cmd.cs, 0)); if ( isOff(uFlag, x.n) ) // xref to addr { uval_t saved = x.value; x.value = x.addr; ua_add_off_drefs2(x, saved ? dr_O : isload ? dr_R : dr_W, OOF_SIGNED|OOF_ADDR); x.value = saved; } if ( x.value != 0 ) // xref to value { // no references to ZERO_REG ea_t ea = toEA(cmd.cs, x.value); ua_add_dref(x.offb, ea, isload ? dr_R : dr_W ); ua_dodata2(x.offb, ea, x.dtyp); } break; case o_indirect: case o_indirect_inc: case o_mem: { ea_t dea = toEA( cmd.cs, x.addr ); ua_dodata2(x.offb, dea, x.dtyp); if( !isload ) doVar(dea); ua_add_dref( x.offb, dea, isload ? dr_R : dr_W ); if ( !isload && (x.addr == 0x14 || x.addr == 0x15) ) { sel_t wsrval = BADSEL; if ( cmd.Op2.type == o_imm ) wsrval = sel_t(cmd.Op2.value); splitSRarea1(cmd.ea, x.addr == 0x14 ? WSR : WSR1, wsrval, SR_auto); } } break; case o_near: ea_t ea = toEA( cmd.cs, x.addr ); int iscall = InstrIsSet( cmd.itype, CF_CALL ); ua_add_cref( x.offb, ea, iscall ? fl_CN : fl_JN ); if ( flow && iscall ) flow = func_does_return(ea); } }
//---------------------------------------------------------------------- int emu(void) { uint32 feature = cmd.get_canon_feature(); flow = (feature & CF_STOP) == 0; if ( feature & CF_USE1 ) process_operand(cmd.Op1, 1); if ( feature & CF_USE2 ) process_operand(cmd.Op2, 1); if ( feature & CF_USE3 ) process_operand(cmd.Op3, 1); if ( feature & CF_CHG1 ) process_operand(cmd.Op1, 0); if ( feature & CF_CHG2 ) process_operand(cmd.Op2, 0); if ( feature & CF_CHG3 ) process_operand(cmd.Op3, 0); // check for CPL changes if ((cmd.itype == TMS320C54_rsbx1 || cmd.itype == TMS320C54_ssbx1) && cmd.Op1.type == o_reg && cmd.Op1.reg == CPL) splitSRarea1(get_item_end(cmd.ea), CPL, cmd.itype == TMS320C54_rsbx1 ? 0 : 1, SR_auto); // check for DP changes if (cmd.itype == TMS320C54_ld2 && cmd.Op1.type == o_imm && cmd.Op1.dtyp == dt_byte && cmd.Op2.type == o_reg && cmd.Op2.reg == DP) splitSRarea1(get_item_end(cmd.ea), DP, cmd.Op1.value & 0x1FF, SR_auto); // determine if the next instruction should be executed if ( segtype(cmd.ea) == SEG_XTRN ) flow = 0; if ( flow && delayed_stop() ) flow = 0; if ( flow ) ua_add_cref(0,cmd.ea+cmd.size,fl_F); if ( may_trace_sp() ) { if ( !flow ) recalc_spd(cmd.ea); // recalculate SP register for the next insn else trace_sp(); } return 1; }
//---------------------------------------------------------------------- int emu(void) { uint32 feature = cmd.get_canon_feature(); flow = (feature & CF_STOP) == 0; if ((cmd.auxpref & DBrFlag) == 0) // У отложенных переходов не надо обрабатывать операнды, т.к. // регистры и так не обрабатываются, а адр. перехода будет обработан через 3 команды { if ( feature & CF_USE1 ) process_operand(cmd.Op1, 1); if ( feature & CF_USE2 ) process_operand(cmd.Op2, 1); if ( feature & CF_USE3 ) process_operand(cmd.Op3, 1); if ( feature & CF_CHG1 ) process_operand(cmd.Op1, 0); if ( feature & CF_CHG2 ) process_operand(cmd.Op2, 0); if ( feature & CF_CHG3 ) process_operand(cmd.Op3, 0); } if (GetDelayedBranchAdr() != BADADDR) // добавить ссылку по отложенному переходу ua_add_cref(0, toEA(cmd.cs, GetDelayedBranchAdr()), fl_JN); if (cmd.itype == TMS320C3X_RETScond) // добавить ссылку по условному выходу ua_add_cref(0, cmd.ea, fl_JN); // check for DP changes if ( ((cmd.itype == TMS320C3X_LDIcond) || (cmd.itype == TMS320C3X_LDI)) && (cmd.Op1.type == o_imm) && (cmd.Op2.type == o_reg) && (cmd.Op2.reg == dp)) splitSRarea1(get_item_end(cmd.ea), dp, cmd.Op1.value & 0xFF, SR_auto); // determine if the next instruction should be executed if ( segtype(cmd.ea) == SEG_XTRN ) flow = 0; if ( flow && delayed_stop() ) flow = 0; if ( flow ) ua_add_cref(0,cmd.ea+cmd.size,fl_F); if ( may_trace_sp() ) { if ( !flow ) recalc_spd(cmd.ea); // recalculate SP register for the next insn else trace_sp(); } return 1; }
//---------------------------------------------------------------------- // change value of virtual register "BANK" and switch to another bank static void split(int reg, sel_t v) { if ( reg == -1 ) { flow = 0; if ( v != BADSEL ) { sel_t pclath = getSR(cmd.ea, PCLATH) & 0x1F; ea_t ea = calc_code_mem(uchar(v) | (pclath<<8)); ua_add_cref(0, ea, fl_JN); } } else { if ( v == BADSEL ) v = 0; // assume bank0 if bank is unknown if ( reg == BANK ) { if ( ptype != PIC16 ) v &= 3; else v &= 0xF; } splitSRarea1(get_item_end(cmd.ea), reg, v, SR_auto); } }
// Emulate an instruction. int emu(void) { uint32 feature = cmd.get_canon_feature(); flow = ((feature & CF_STOP) == 0); if ( cmd.Op1.type != o_void) handle_operand(cmd.Op1, (feature & CF_CHG1) != 0 ); if ( cmd.Op2.type != o_void) handle_operand(cmd.Op2, (feature & CF_CHG2) != 0 ); if ( cmd.Op3.type != o_void) handle_operand(cmd.Op3, (feature & CF_CHG3) != 0 ); if ( flow ) ua_add_cref(0, cmd.ea + cmd.size, fl_F); // Following code will update the current value of the two virtual // segment registers: RW (register window) and RP (register page). bool rw_has_changed = false; bool rp_has_changed = false; switch ( cmd.itype ) { case st9_srp: { sel_t val = cmd.Op1.value; if ( val % 2 ) val--; // even reduced splitSRarea1(cmd.ea, rRW, val | (val << 8), SR_auto); } rw_has_changed = true; break; case st9_srp0: { sel_t RW = getSR(cmd.ea, rRW); splitSRarea1(cmd.ea, rRW, cmd.Op1.value | (RW & 0xFF00), SR_auto); } rw_has_changed = true; break; case st9_srp1: { sel_t RW = getSR(cmd.ea, rRW); splitSRarea1(cmd.ea, rRW, (cmd.Op1.value << 8) | (RW & 0x00FF), SR_auto); } rw_has_changed = true; break; case st9_spp: splitSRarea1(cmd.ea, rRP, cmd.Op1.value, SR_auto); rp_has_changed = true; break; } // If RW / RP registers have changed, print a comment which explains the new mapping of // the general registers. if ( rw_has_changed && !has_cmt(uFlag) ) { char buf[MAXSTR]; sel_t RW = getSR(cmd.ea, rRW); int low = RW & 0x00FF; int high = (RW & 0xFF00) >> 8; low *= 8; high *= 8; const char *fmt = "r0 -> R%d, r1 -> R%d, r2 -> R%d, r3 -> R%d, r4 -> R%d, r5 -> R%d, r6 -> R%d, r7 -> R%d,\n" "r8 -> R%d, r9 -> R%d, r10 -> R%d, r11 -> R%d, r12 -> R%d, r13 -> R%d, r14 -> R%d, r15 -> R%d"; qsnprintf(buf, sizeof buf, fmt, 0 + low, 1 + low, 2 + low, 3 + low, 4 + low, 5 + low, 6 + low, 7 + low, 8 + high, 9 + high, 10 + high, 11 + high, 12 + high, 13 + high, 14 + high, 15 + high ); set_cmt(cmd.ea, buf, false); }
//---------------------------------------------------------------------- int idaapi emu(void) { uint32 Feature = cmd.get_canon_feature(); int flag1 = is_forced_operand(cmd.ea, 0); int flag2 = is_forced_operand(cmd.ea, 1); int flag3 = is_forced_operand(cmd.ea, 2); flow = ((Feature & CF_STOP) == 0); if ( Feature & CF_USE1 ) process_operand(cmd.Op1, flag1, 1); if ( Feature & CF_USE2 ) process_operand(cmd.Op2, flag2, 1); if ( Feature & CF_USE3 ) process_operand(cmd.Op3, flag3, 1); if ( Feature & CF_CHG1 ) process_operand(cmd.Op1, flag1, 0); if ( Feature & CF_CHG2 ) process_operand(cmd.Op2, flag2, 0); if ( Feature & CF_CHG3 ) process_operand(cmd.Op3, flag3, 0); // // Determine if the next instruction should be executed // if ( segtype(cmd.ea) == SEG_XTRN ) flow = false; // // Handle loads to segment registers // sel_t v = BADSEL; switch ( cmd.itype ) { case H8500_andc: if ( cmd.Op1.value == 0 ) v = 0; goto SPLIT; case H8500_orc: if ( cmd.Op1.value == 0xFF ) v = 0xFF; goto SPLIT; case H8500_ldc: if ( cmd.Op1.type == o_imm ) v = cmd.Op1.value; case H8500_xorc: SPLIT: if ( cmd.Op2.reg >= BR && cmd.Op2.reg <= TP ) splitSRarea1(cmd.ea+cmd.size, cmd.Op2.reg, v, SR_auto); break; } if ( (Feature & CF_CALL) != 0 ) { ea_t callee = find_callee(); if ( !handle_function_call(callee) ) flow = false; } // // Handle SP modifications // if ( may_trace_sp() ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL ) { if ( (pfn->flags & FUNC_USERFAR) == 0 && (pfn->flags & FUNC_FAR) == 0 && is_far_ending() ) { pfn->flags |= FUNC_FAR; update_func(pfn); reanalyze_callers(pfn->startEA, 0); } if ( !flow ) recalc_spd(cmd.ea); // recalculate SP register for the next insn else trace_sp(); } } if ( flow ) ua_add_cref(0, cmd.ea+cmd.size, fl_F); return 1; }
//---------------------------------------------------------------------- int emu(void) { if ( segtype(cmd.ea) == SEG_XTRN ) return 1; //uint32 Feature = cmd.get_canon_feature(); int flag1 = is_forced_operand(cmd.ea, 0); int flag2 = is_forced_operand(cmd.ea, 1); int flag3 = is_forced_operand(cmd.ea, 2); // Determine if the next instruction should be executed flow = (InstrIsSet(cmd.itype, CF_STOP) != true); if ( InstrIsSet(cmd.itype,CF_USE1) ) process_operand(cmd.Op1, flag1, 1); if ( InstrIsSet(cmd.itype,CF_USE2) ) process_operand(cmd.Op2, flag2, 1); if ( InstrIsSet(cmd.itype,CF_USE3) ) process_operand(cmd.Op3, flag3, 1); if ( InstrIsSet(cmd.itype,CF_CHG1) ) process_operand(cmd.Op1, flag1, 0); if ( InstrIsSet(cmd.itype,CF_CHG2) ) process_operand(cmd.Op2, flag2, 0); if ( InstrIsSet(cmd.itype,CF_CHG3) ) process_operand(cmd.Op3, flag3, 0); // check for DP changes if ( cmd.itype == OAK_Dsp_lpg ) splitSRarea1(get_item_end(cmd.ea), PAGE, cmd.Op1.value & 0xFF, SR_auto); if ( ( cmd.itype == OAK_Dsp_mov ) && (cmd.Op1.type == o_imm) && (cmd.Op2.type == o_reg) && (cmd.Op2.reg == ST1) ) splitSRarea1(get_item_end(cmd.ea), PAGE, cmd.Op1.value & 0xFF, SR_auto); //Delayed Return insn_t saved = cmd; cycles = cmd.cmd_cycles; delayed = false; if ( decode_prev_insn(cmd.ea) != BADADDR ) { if ( (cmd.itype == OAK_Dsp_retd) || (cmd.itype == OAK_Dsp_retid) ) delayed = true; else cycles += cmd.cmd_cycles; if (!delayed) if ( decode_prev_insn(cmd.ea) != BADADDR ) if ( (cmd.itype == OAK_Dsp_retd) || (cmd.itype == OAK_Dsp_retid) ) delayed = true; } if (delayed && (cycles > 1) ) flow = 0; cmd = saved; //mov #imm, pc if ( ( cmd.itype == OAK_Dsp_mov ) && (cmd.Op2.type == o_reg) && (cmd.Op2.reg == PC) ) flow = 0; if ( flow ) ua_add_cref(0,cmd.ea+cmd.size,fl_F); if ( may_trace_sp() ) { if ( !flow ) recalc_spd(cmd.ea); // recalculate SP register for the next insn else trace_sp(); } return 1; }