//---------------------------------------------------------------------- static void trace_sp(void) { // trace SP changes switch (cmd.itype) { case TMS320C54_fret: case TMS320C54_fretd: case TMS320C54_frete: case TMS320C54_freted: add_stkpnt(2); break; case TMS320C54_ret: case TMS320C54_retd: case TMS320C54_rete: case TMS320C54_reted: case TMS320C54_retf: case TMS320C54_retfd: add_stkpnt(1); break; case TMS320C54_frame: add_stkpnt(cmd.Op1.value); break; case TMS320C54_popd: case TMS320C54_popm: add_stkpnt(1); break; case TMS320C54_pshd: case TMS320C54_pshm: add_stkpnt(-1); break; } }
//---------------------------------------------------------------------- static void trace_sp(void) { // @sp++ if ( is_sp_inc(cmd.Op1) ) { int size = 2; if ( cmd.Op2.type == o_reglist ) size *= calc_reglist_count(cmd.Op2.reg); add_stkpnt(size); return; } // @--sp if ( is_sp_dec(cmd.Op2) ) { int size = 2; if ( cmd.Op1.type == o_reglist ) size *= calc_reglist_count(cmd.Op1.reg); add_stkpnt(-size); return; } // xxx @--sp if ( is_sp_dec(cmd.Op1) ) { add_stkpnt(-2); return; } int v; switch ( cmd.itype ) { case H8500_add_g: case H8500_add_q: case H8500_adds: if ( issp(cmd.Op2.reg) && get_op_value(cmd.Op1, &v) ) add_stkpnt(v); break; case H8500_sub: case H8500_subs: if ( issp(cmd.Op2.reg) && get_op_value(cmd.Op1, &v) ) add_stkpnt(-v); break; } }
int emu(void) { uint32 Feature = cmd.get_canon_feature(); flow = ((Feature & CF_STOP) == 0); // you may emulate selected instructions with a greater care: switch ( cmd.itype ) { case I51_mov: if ( cmd.Op1.type == o_mem && cmd.Op1.addr == 0x81 ) // mov SP, #num { if ( cmd.Op2.type == o_imm && !isDefArg(uFlag,1) ) set_offset(cmd.ea,1,intmem); // convert it to an offset } break; case I51_trap: ua_add_cref(0, 0x7B, fl_CN); break; case I51_pop: add_stkpnt(1); break; case I51_push: add_stkpnt(-1); break; } if ( Feature & CF_USE1 ) handle_operand(cmd.Op1, 1); if ( Feature & CF_USE2 ) handle_operand(cmd.Op2, 1); if ( Feature & CF_USE3 ) handle_operand(cmd.Op3, 1); if ( Feature & CF_JUMP ) QueueMark(Q_jumps,cmd.ea); if ( Feature & CF_CHG1 ) handle_operand(cmd.Op1, 0); if ( Feature & CF_CHG2 ) handle_operand(cmd.Op2, 0); if ( Feature & CF_CHG3 ) handle_operand(cmd.Op3, 0); // if the execution flow is not stopped here, then create // a xref to the next instruction. // Thus we plan to analyze the next instruction. if ( flow ) ua_add_cref(0,cmd.ea+cmd.size,fl_F); return 1; // actually the return value is unimportant, but let's it be so }
//---------------------------------------------------------------------- static void trace_sp(void) { switch (cmd.itype) { case TMS320C3X_RETIcond: add_stkpnt(-2); break; case TMS320C3X_RETScond: add_stkpnt(-1); break; case TMS320C3X_POP: case TMS320C3X_POPF: add_stkpnt(-1); break; case TMS320C3X_PUSH: case TMS320C3X_PUSHF: add_stkpnt(1); break; } }
//---------------------------------------------------------------------- static void trace_sp(void) { int16 frame; // trace SP changes switch (cmd.itype) { case OAK_Dsp_reti_u: case OAK_Dsp_retid: case OAK_Dsp_reti: add_stkpnt(1); break; case OAK_Dsp_ret_u: case OAK_Dsp_retd: case OAK_Dsp_ret: add_stkpnt(1); break; case OAK_Dsp_rets: add_stkpnt(1 + cmd.Op1.value); break; case OAK_Dsp_pop: add_stkpnt(1); break; case OAK_Dsp_push: add_stkpnt(-1); break; case OAK_Dsp_addv: if ( (cmd.Op1.type == o_imm) && (cmd.Op2.type == o_reg) && (cmd.Op2.reg == SP) ) { frame = (uint16)cmd.Op1.value; add_stkpnt(frame); } break; case OAK_Dsp_subv: if ( (cmd.Op1.type == o_imm) && (cmd.Op2.type == o_reg) && (cmd.Op2.reg == SP) ) { frame = (uint16)cmd.Op1.value; add_stkpnt(-frame); } break; } }
//---------------------------------------------------------------------- // trace a function call. // adjuct the stack, determine the execution flow // returns: // true - the called function returns to the caller // false - the called function doesn't return to the caller static bool handle_function_call(ea_t callee) { bool funcflow = true; if ( !func_does_return(callee) ) funcflow = false; if ( should_trace_sp() ) { func_t *caller = get_func(cmd.ea); if ( func_contains(caller, cmd.ea+cmd.size) ) { sval_t delta = calc_func_call_delta(callee); if ( delta != 0 ) add_stkpnt(delta); } } return funcflow; }
//---------------------------------------------------------------------- static void trace_sp(void) { // @sp++ if ( cmd.Op1.type == o_phrase && issp(cmd.Op1.reg) && cmd.Op1.phtype == ph_post ) { ssize_t size = get_dtyp_size(cmd.Op2.dtyp); if ( cmd.Op2.type == o_reglist ) size *= cmd.Op2.nregs; add_stkpnt(size); return; } // @--sp if ( cmd.Op2.type == o_phrase && issp(cmd.Op2.reg) && cmd.Op2.phtype == ph_pre ) { ssize_t size = get_dtyp_size(cmd.Op1.dtyp); if ( cmd.Op1.type == o_reglist ) size *= cmd.Op1.nregs; add_stkpnt(-size); return; } int v; switch ( cmd.itype ) { case H8_add: case H8_adds: if ( !issp(cmd.Op2.reg) ) break; if ( get_op_value(cmd.Op1, &v) ) add_stkpnt(v); break; case H8_sub: case H8_subs: if ( !issp(cmd.Op2.reg) ) break; if ( get_op_value(cmd.Op1, &v) ) add_stkpnt(-v); break; case H8_push: add_stkpnt(-get_dtyp_size(cmd.Op1.dtyp)); break; case H8_pop: add_stkpnt( get_dtyp_size(cmd.Op1.dtyp)); break; } }