//---------------------------------------------------------------------- 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); } }
//---------------------------------------------------------------------- static void process_imm(op_t &x) { doImmd(cmd.ea); if ( isDefArg(uFlag,x.n) ) return; // if already defined by user switch (cmd.itype) { case TMS320C54_cmpm: case TMS320C54_bitf: case TMS320C54_andm: case TMS320C54_orm: case TMS320C54_xorm: case TMS320C54_addm: case TMS320C54_st: case TMS320C54_stm: case TMS320C54_rpt: case TMS320C54_ld3: case TMS320C54_mpy2: case TMS320C54_rptz: case TMS320C54_add3: case TMS320C54_sub3: case TMS320C54_and3: case TMS320C54_or3: case TMS320C54_xor3: case TMS320C54_mac2: op_num(cmd.ea, x.n); } }
//------------------------------------------------------------------------ static void doImmdValue(void) { doImmd(cmd.ea); switch ( cmd.itype ) { case TMS_and: case TMS_bit: case TMS_bitt: case TMS_bsar: case TMS_cmpr: case TMS_in: case TMS_intr: case TMS_apl2: case TMS_opl2: case TMS_xpl2: case TMS_or: case TMS_rpt: case TMS_xc: case TMS_xor: case TMS_rptz: case TMS2_bit: case TMS2_in: case TMS2_out: case TMS2_andk: case TMS2_ork: case TMS2_xork: case TMS2_rptk: op_num(cmd.ea,0); } }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; /* switch ( cmd.itype ) { op_dec(cmd.ea, n); break; }*/ }
static void handle_imm(op_t &op) { doImmd(cmd.ea); bool in_hex = false; switch (cmd.itype) { case m740_and: case m740_ora: in_hex = true; break; } if (in_hex) op_hex(cmd.ea, op.n); }
//------------------------------------------------------------------------ static void doImmdValue(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { case AVR_andi: case AVR_ori: op_num(cmd.ea, n); } }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { // case DSP56_asl: // case DSP56_asr: case DSP56_bchg: case DSP56_bclr: case DSP56_brclr: case DSP56_brset: case DSP56_bsclr: case DSP56_bset: case DSP56_bsset: case DSP56_btst: case DSP56_jclr: case DSP56_jset: case DSP56_jsclr: case DSP56_jsset: // case DSP56_lsl: // case DSP56_lsr: op_dec(cmd.ea, n); break; case DSP56_add: case DSP56_and: case DSP56_andi: case DSP56_cmp: case DSP56_eor: case DSP56_extract: case DSP56_extractu: case DSP56_insert: case DSP56_mac: case DSP56_maci: case DSP56_macr: case DSP56_macri: case DSP56_mpy: case DSP56_mpyi: case DSP56_mpyr: case DSP56_mpyri: case DSP56_or: case DSP56_ori: case DSP56_sub: case DSP56_do: case DSP56_dor: case DSP56_rep: op_num(cmd.ea, n); break; } }
static void doImmdValue(void) { doImmd(cmd.ea); switch ( cmd.itype ) { case I51_anl: case I51_orl: case I51_xrl: op_num(cmd.ea,1); break; } }
//------------------------------------------------------------------------ static void doImmdValue(void) { doImmd(cmd.ea); switch ( cmd.itype ) { case I860_and: case I860_andh: case I860_andnot: case I860_andnoth: case I860_xor: case I860_xorh: op_num(cmd.ea,1); break; } }
//------------------------------------------------------------------------ static void doImmdValue(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { case TMS6_and: // Rd = Op1 & Op2 case TMS6_xor: // Rd = Op1 ^ Op2 case TMS6_or: // Rd = Op2 | Op1 case TMS6_set: // Rd = Op1 & ~Op2 case TMS6_clr: // Rd = Op1 & ~Op2 case TMS6_ext: // Rd = Op1 & ~Op2 case TMS6_extu: // Rd = Op1 & ~Op2 op_num(cmd.ea,n); } }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { case PIC_iorlw: case PIC_andlw: case PIC_xorlw: op_num(cmd.ea, n); break; case PIC_lfsr2: // FSRs are used to address the data memory if ( dataseg != BADADDR ) op_offset(cmd.ea, n, REF_OFF16, BADADDR, dataseg); break; } }
//------------------------------------------------------------------------ static void doImmdValue(int n) { doImmd(cmd.ea); if ( !isDefArg(uFlag, n) ) { switch ( cmd.itype ) { case I5_ani: case I5_xri: case I5_ori: case I5_in: case I5_out: case I5_rst: case HD_in0: case HD_out0: case HD_tstio: op_num(cmd.ea,-1); break; } } }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { case H8500_add_q: case H8500_bclr: case H8500_bnot: case H8500_bset: case H8500_btst: op_dec(cmd.ea, n); break; case H8500_and: case H8500_or: case H8500_xor: case H8500_andc: case H8500_orc: case H8500_xorc: op_num(cmd.ea, n); break; } }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { case H8_shal: case H8_shar: case H8_shll: case H8_shlr: case H8_rotl: case H8_rotr: case H8_rotxl: case H8_rotxr: op_dec(cmd.ea, n); break; case H8_and: case H8_or: case H8_xor: op_num(cmd.ea, n); break; } }
static void op_imm(int n) { doImmd(cmd.ea); if (isDefArg(uFlag, n)) return; switch (cmd.itype) { case M8B_ADD: case M8B_ADC: case M8B_SUB: case M8B_SBB: op_dec(cmd.ea, n); break; case M8B_CMP: case M8B_MOV: case M8B_AND: case M8B_OR: case M8B_XOR: op_num(cmd.ea, n); break; } }
//---------------------------------------------------------------------- static void process_imm(op_t &x) { doImmd(cmd.ea); if ( isDefArg(uFlag,x.n) ) return; // if already defined by user op_num(cmd.ea, x.n); }
bool handle_operand(const op_t &op, enum opRefType ref_type) { ea_t ea; sel_t data_selector; bool flow = true; switch ( op.type ) { case o_reg: // // Register operand. // // // Nothing needs to be calculated or examined for this // operand. // break; case o_imm: // // Immediate operand. // // Make sure that this operand reference isn't a write reference. // (Writing to an immediate value is not allowed and is a sure // sign of a badly decoded instruction). // if ( ref_type == hop_WRITE ) { // // Attempt to write to an immediate value. // Error. // warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), op.n, op.type); break; } // // SPECIAL INSTRUCTION CASE: // // The LDPK instruction is decoded by ana() to have an immediate // value as an operand. However, this immediate value is to be // the new data page pointer, which we must track for proper // memory referencing. // if ( cmd.itype == I_LDPK ) { // // This is an LDPK instruction. Let the kernel know that // we are changing the current data page pointer. We track // this bit as though it were a virtual segment register named // I_VDS, although it is not a true register in the CPU. // // Determine into which data page the instruction is attempting // to point. // if ( op.value == 0 ) { // // Data page 0 is being loaded. // data_selector = tms320c1x_dpage0; } else { // // Data page 1 is being loaded. // data_selector = tms320c1x_dpage1; } // // Notify the IDA kernel of the change. // split_srarea( cmd.ea, // The current instruction's address IREG_VDS, // The segment register being modified data_selector, // The new selector value being loaded SR_auto // How the new value was determined ); } // // Let the kernel know that the instruction's address should // be marked with a 'has immediate value' flag. // (Useful during search?) // doImmd(cmd.ea); break; case o_phrase: // // Processor-specific phrase. // // These operands have no currently trackable side effect. // break; case o_mem: // // Direct memory reference. // // // Ask the IDA kernel for the current data page pointer selector. // data_selector = get_segreg(cmd.ea, IREG_VDS); // // Is it known? // if ( data_selector == BADSEL ) { // // The current data page pointer is unknown. // There is nothing to do. // } else { // // The current data page pointer is known. // Calculate the full effective address being referenced // by this operand. // ea = sel2ea(data_selector) + op.addr; // // Generate a data cross reference from this instruction // to the target address. // ua_add_dref(op.offb, ea, ref_type == hop_READ ? dr_R : dr_W); } // // TODO: DMOV, ... // These instructions read from the address in their operands // and write to the address ADJACENT to it. // break; case o_near: // // Code reference in current segment. // // // Determine the effective address of the reference. // ea = toEA(cmd.cs, op.addr); // // Is this a 'CALL' type reference, or a branch type reference? // if ( InstrIsSet(cmd.itype, CF_CALL) ) { // // This is a CALL type reference. Make a cross reference // that notes it. // ua_add_cref(op.offb, ea, fl_CN); if ( !func_does_return(ea) ) flow = false; } else { // // This is a branch type reference. Make a cross reference // that notes it. // ua_add_cref(op.offb, ea, fl_JN); } break; default: // // Unhandled operand type. // Error. // warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), op.n, op.type); break; } return flow; }
//---------------------------------------------------------------------- static void process_operand(op_t &x, int use) { switch ( x.type ) { case o_bit: case o_reg: case o_cond8: case o_cond2: return; case o_near: case o_far: { if (cmd.itype != TMS320C54_rptb && cmd.itype != TMS320C54_rptbd) { cref_t ftype = fl_JN; ea_t ea = calc_code_mem(x.addr, x.type == o_near); if ( InstrIsSet(cmd.itype, CF_CALL) ) { if ( !func_does_return(ea) ) flow = false; ftype = fl_CN; } #ifndef TMS320C54_NO_NAME_NO_REF if ( x.dtyp == dt_byte ) ua_add_dref(x.offb, ea, dr_R); else ua_add_cref(x.offb, ea, ftype); #endif } #ifndef TMS320C54_NO_NAME_NO_REF else // evaluate RPTB[D] loops as dref ua_add_dref(x.offb, calc_code_mem(x.addr), dr_I); #endif } break; case o_imm: if ( !use ) error("interr: emu"); process_imm(x); #ifndef TMS320C54_NO_NAME_NO_REF if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, x.Signed ? OOF_SIGNED : 0); #endif break; case o_mem: case o_farmem: case o_mmr: { ea_t ea = calc_data_mem(x.addr, x.type == o_mem); if (ea != BADADDR) { #ifndef TMS320C54_NO_NAME_NO_REF ua_add_dref(x.offb, ea, use ? dr_R : dr_W); #endif ua_dodata2(x.offb, ea, x.dtyp); if ( !use ) doVar(ea); } } break; case o_local: // local variables if ( may_create_stkvars() && (get_func(cmd.ea) != NULL) && ua_stkvar2(x, x.addr, STKVAR_VALID_SIZE) ) { op_stkvar(cmd.ea, x.n); } break; case o_displ: doImmd(cmd.ea); break; default: warning("interr: emu2 address:%a operand:%d type:%d", cmd.ea, x.n, x.type); } }
// Emulate an operand. static void handle_operand(op_t &op, bool write) { switch ( op.type ) { // Code address case o_near: { cref_t mode; ea_t ea = toEA(cmd.cs, op.addr); // call or jump ? if ( cmd.itype == st9_call || cmd.itype == st9_calls ) { if ( !func_does_return(ea) ) flow = false; mode = fl_CN; } else { mode = fl_JN; } ua_add_cref(op.offb, ea, mode); } break; // Memory address case o_mem: { enum dref_t mode; mode = write ? dr_W: dr_R; ua_add_dref(op.offb, toEA(cmd.cs, op.addr), mode); ua_dodata2(op.offb, op.addr, op.dtyp); } break; // Immediate value case o_imm: doImmd(cmd.ea); // create a comment if this immediate is represented in the .cfg file { const ioport_t * port = find_sym(op.value); if ( port != NULL && !has_cmt(uFlag) ) { set_cmt(cmd.ea, port->cmt, false); } } // if the value was converted to an offset, then create a data xref: if ( isOff(uFlag, op.n) ) ua_add_off_drefs2(op, dr_O, 0); break; // Displacement case o_displ: doImmd(cmd.ea); if ( isOff(uFlag, op.n) ) { ua_add_off_drefs2(op, dr_O, OOF_ADDR); ua_dodata2(op.offb, op.addr, op.dtyp); } // create stack variables if required if ( may_create_stkvars() && !isDefArg(uFlag, op.n) ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && pfn->flags & FUNC_FRAME ) { if ( ua_stkvar2(op, op.addr, STKVAR_VALID_SIZE) ) { op_stkvar(cmd.ea, op.n); if ( cmd.Op2.type == o_reg ) { regvar_t *r = find_regvar(pfn, cmd.ea, ph.regNames[cmd.Op2.reg]); if ( r != NULL ) { struc_t *s = get_frame(pfn); member_t *m = get_stkvar(op, op.addr, NULL); char b[20]; qsnprintf(b, sizeof b, "%scopy", r->user); set_member_name(s, m->soff, b); } } } } } break; // Register - Phrase - Void: do nothing case o_reg: case o_phrase: case o_void: break; default: IDA_ERROR("Invalid op.type in handle_operand()"); } }
//---------------------------------------------------------------------- static void TouchArg(op_t &x,int isAlt,int isload) { switch ( x.type ) { case o_phrase: //Добавляем в список ошибок(выводим сообщение) //ошибку и адресс где это случилось //QueueMark(Q_jumps, cmd.ea); case o_void: case o_reg: break; case o_sr: case o_displ: //Установить для данного байта признак immedia doImmd(cmd.ea); //Получить флаг для указанного линейного адресса if ( !isAlt ) { uint32 offb; ushort addr = ushort(x.addr); if ( x.type == o_displ ) { addr += (ushort)cmd.ip; addr += cmd.size; //Получить линейный адресс offb = (uint32)toEA(codeSeg(addr,x.n), 0); DataSet(x, offb+addr, isload); } else if ( isOff(uFlag, x.n) ) { reref: ua_add_off_drefs2(x, dr_O, x.type == o_displ ? OOF_ADDR : 0); if ( x.type == o_displ ) //Преобразовать данные по указанному линейному адрессу в указанный тип ua_dodata2(x.offb, calc_target(cmd.ea+x.offb, cmd.ea, x.n, x.addr), x.dtyp); } else if ( x.type == o_displ && !x.reg && !isDefArg(uFlag, x.n ) && set_offset(cmd.ea, x.n, toEA(cmd.cs,0))) goto reref; } break; case o_stk: case o_imm: { //Установить для данного байта признак immedia doImmd(cmd.ea); if ( isOff(get_flags_novalue(cmd.ea), x.n) ) ua_add_off_drefs2(x, dr_O, 0); } break; case o_ab: { if ( x.TypeOper == TAB_INDIRECTED_ABS_X ) { ea_t ea = toEA(cmd.cs, x.addr); ua_dodata2(x.offb, ea, dt_word); //добавить крос референсы для текущей инструкции ua_add_dref(x.offb, ea, isload ? dr_R : dr_W); //получить данные uint32 Addr; Addr = get_word(ea); Addr = uint32( Addr | (getPG<<16)); //добавить крос референсы для текущей инструкции ua_add_cref(2, Addr, fl_JF); } else DataSet(x, toEA(codeSeg(x.addr,x.n), x.addr), isload); } break; case o_mem: { // Конвертирование в данные(указан адресс) по указанному типу, //добавить крос референсы для текущей инструкции switch ( x.TypeOper ) { case TDIR_DIR_Y: case TDIR_DIR_X: case TDIR_DIR: case TDIR_INDIRECT_DIR: case TDIR_INDIRECT_DIR_X: case TDIR_INDIRECT_DIR_Y: case TDIR_L_INDIRECT_DIR: case TDIR_L_INDIRECT_DIR_Y: { if ( getDPReg == 1 ) { uint32 d = x.addr & 0xC; x.addr &= 0xFF3F; DataSet(x, toEA(codeSeg(x.addr,x.n), x.addr), isload); x.addr |=d; } else DataSet(x, toEA(codeSeg(x.addr,x.n), x.addr), isload); } break; default: DataSet(x, toEA(codeSeg(x.addr,x.n), x.addr), isload); }//end switch } break; case o_near: { //Получить линейный адресс ea_t ea = toEA(cmd.cs, x.addr); switch ( cmd.itype ) { case m7900_jsr: { //добавить крос референсы для текущей инструкции ua_add_cref(x.offb, ea, fl_CN ); if ( !func_does_return(ea) ) flow = false; } break; case m7900_jsrl: //добавить крос референсы для текущей инструкции ua_add_cref(x.offb, ea, fl_CF); if ( !func_does_return(ea) ) flow = false; break; case m7900_jmpl: //добавить крос референсы для текущей инструкции ua_add_cref(x.offb, ea, fl_JF); break; default: ua_add_cref(x.offb, ea, fl_JN); break; } } break; default: // warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type); break; } }
//------------------------------------------------------------------------ static void process_immediate_number(int n) { doImmd(cmd.ea); if ( isDefArg(uFlag,n) ) return; switch ( cmd.itype ) { case OAK_Dsp_shfi: case OAK_Dsp_movsi: op_dec(cmd.ea, n); uFlag = getFlags(cmd.ea); break; case OAK_Dsp_lpg: case OAK_Dsp_mpyi: case OAK_Dsp_mov: case OAK_Dsp_rets: case OAK_Dsp_rep: case OAK_Dsp_load: case OAK_Dsp_push: case OAK_Dsp_bkrep: case OAK_Dsp_msu: case OAK_Dsp_tstb: case OAK_Dsp_or: case OAK_Dsp_and: case OAK_Dsp_xor: case OAK_Dsp_add: case OAK_Dsp_alm_tst0: case OAK_Dsp_alm_tst1: case OAK_Dsp_cmp: case OAK_Dsp_sub: case OAK_Dsp_alm_msu: case OAK_Dsp_addh: case OAK_Dsp_addl: case OAK_Dsp_subh: case OAK_Dsp_subl: case OAK_Dsp_sqr: case OAK_Dsp_sqra: case OAK_Dsp_cmpu: case OAK_Dsp_set: case OAK_Dsp_rst: case OAK_Dsp_chng: case OAK_Dsp_addv: case OAK_Dsp_alb_tst0: case OAK_Dsp_alb_tst1: case OAK_Dsp_cmpv: case OAK_Dsp_subv: case OAK_Dsp_mpy: case OAK_Dsp_mpysu: case OAK_Dsp_mac: case OAK_Dsp_macus: case OAK_Dsp_maa: case OAK_Dsp_macuu: case OAK_Dsp_macsu: case OAK_Dsp_maasu: op_num(cmd.ea, n); uFlag = getFlags(cmd.ea); break; } }
//------------------------------------------------------------------------ inline void doImmdValue(void) { doImmd(cmd.ea); }
// Emulate an operand. static void handle_operand(op_t &op) { bool offset = false; switch ( op.type ) { case o_near: ua_add_cref(op.offb, toEA(cmd.cs, op.addr), (cmd.itype == fr_call) ? fl_CN : fl_JN); break; case o_mem: { enum dref_t mode = dr_U; if ( op.specflag1 & OP_ADDR_R ) mode = dr_R; else if ( op.specflag1 & OP_ADDR_W ) mode = dr_W; ea_t ea = toEA(cmd.cs, op.addr); ua_add_dref(op.offb, ea, mode); ua_dodata2(op.offb, ea, op.dtyp); } break; case o_imm: // if current insn is ldi:32 #imm, r1 // and next insn is call @r1, // replace the immediate value with an offset. if (cmd.itype == fr_ldi_32 && cmd.Op1.type == o_imm && cmd.Op2.type == o_reg) { const int callreg = cmd.Op2.reg; insn_t cmd_backup = cmd; if ( next_insn(cmd.ea + cmd.size ) > 0 && cmd.itype == fr_call && cmd.Op1.type == o_phrase && cmd.Op1.specflag2 == fIGR && cmd.Op1.reg == callreg) { offset = true; } const ea_t from = cmd.ea; cmd = cmd_backup; if ( !isDefArg(uFlag, 0) && offset && set_offset(cmd.ea, 0, 0) ) add_cref(from, toEA(cmd.cs, cmd.Op1.value), fl_CN); } doImmd(cmd.ea); if ( !offset ) // if the value was converted to an offset, then create a data xref: if ( isOff(uFlag, op.n) ) ua_add_off_drefs2(op, dr_O, 0); // create stack variables if necessary { bool ok = false; // ldi8 #our_value, R1 // extsb R1 // addn R14, R1 if (cmd.itype == fr_ldi_8 && cmd.Op2.type == o_reg && cmd.Op2.reg == rR1) { insn_t current_insn = cmd; next_insn(cmd.ea + cmd.size); if (cmd.itype == fr_extsb && cmd.Op1.type == o_reg && cmd.Op1.reg == rR1) { ok = true; } if ( ok ) { ok = false; next_insn(cmd.ea + cmd.size); if (cmd.itype == fr_addn && cmd.Op1.type == o_reg && cmd.Op1.reg == rR14 && cmd.Op2.type == o_reg && cmd.Op2.reg == rR1) { ok = true; } } cmd = current_insn; } // ldi32 #our_value, Ri // addn R14, Ri // // (where Ri is either R1 or R2) else if (cmd.itype == fr_ldi_32 && cmd.Op2.type == o_reg && (cmd.Op2.reg == rR1 || cmd.Op2.reg == rR2)) { ushort the_reg = cmd.Op2.reg; insn_t current_insn = cmd; next_insn(cmd.ea + cmd.size); if (cmd.itype == fr_addn && cmd.Op1.type == o_reg && cmd.Op1.reg == rR14 && cmd.Op2.type == o_reg && cmd.Op2.reg == the_reg) { ok = true; } cmd = current_insn; } if ( ok && may_create_stkvars() && !isDefArg(uFlag, op.n) ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && pfn->flags & FUNC_FRAME ) { if ( ua_stkvar2(op, op.value, 0) ) { op_stkvar(cmd.ea, op.n); } } } } break; case o_displ: case o_phrase: // XXX case o_reglist: case o_void: case o_reg: break; default: INTERR(10017); } }
// handle immediate values static void handle_imm(void) { doImmd(cmd.ea); }
//---------------------------------------------------------------------- static void TouchArg(op_t &x,int isAlt,int isload) { switch (x.type) { case o_phrase: //Добавляем в список ошибок(выводим сообщение) //ошибку и адресс где это случилось //QueueMark(Q_jumps, cmd.ea); case o_void: case o_reg: break; case o_imm: { //Установить для данного байта признак immedia doImmd(cmd.ea); //Получить флаг для указанного линейного адресса if(!isAlt) { uint32 offb; ushort addr = ushort(x.addr); if(x.type == o_displ ) { addr += (ushort)cmd.ip; addr += cmd.size; //Получить линейный адресс offb = (uint32)toEA(codeSeg(addr,x.n), 0); DataSet(x, offb+addr, isload); } else if ( isOff(uFlag, x.n) ) { reref: ua_add_off_drefs(x, dr_O); if ( x.type == o_displ ) //Преобразовать данные по указанному линейному адрессу в указанный тип ua_dodata2(x.offb, calc_target(cmd.ea+x.offb, cmd.ea, x.n, x.addr), x.dtyp); } else if(x.type == o_displ && !x.reg && !isDefArg(uFlag, x.n) && set_offset(cmd.ea, x.n, toEA(cmd.cs,0))) goto reref; } } break; case o_bit: case o_mem: // Конвертирование в данные(указан адресс) по указанному типу, //добавить крос референсы для текущей инструкции DataSet(x, toEA(codeSeg(x.addr,x.n), x.addr), isload); 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 ( iscall ) flow = func_does_return(ea); } break; default: warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type); break; } }
//---------------------------------------------------------------------- // поставим использование/изменение операндов static void near TouchArg(op_t &x,int isAlt,int isload) { ea_t ea = toEA(codeSeg(x.addr,x.n), x.addr); switch ( x.type ) { // эта часть не используется ! case o_void: break; // тут тоже нечего делать case o_reg: break; // непосредственный операнд case o_imm: // непосредственный не может меняться if ( ! isload ) goto badTouch; // поставим флажок непосредственного операнда doImmd(cmd.ea); // если не форсирован и помечен смещением if ( !isAlt && isOff(uFlag,x.n) ) // это смещение ! ua_add_dref(x.offb,ea,dr_O); break; // переход или вызов case o_near: // это вызов ? (или переход) if(InstrIsSet(cmd.itype,CF_CALL)){ // поставим ссылку на код ua_add_cref(x.offb,ea,fl_CN); // это функция без возврата ? #if IDP_INTERFACE_VERSION > 37 flow = func_does_return(ea); #else // получим описатель функции func_t *pfn = get_func(ea); // если функция описана и не имеет возврата - остановим if(pfn != NULL && (pfn->flags & FUNC_NORET) ) flow = false; #endif } else ua_add_cref(x.offb,ea,fl_JN); break; // ссылка на ячейку памяти case o_mem: // сделаем данные по указанному адресу ua_dodata2(x.offb, ea, x.dtyp); // если изменяется - поставим переменную if ( ! isload ) doVar(ea); // добавим ссылку на память ua_add_dref(x.offb,ea,isload ? dr_R : dr_W); break; // прочее - сообщим ошибку default: badTouch: #if IDP_INTERFACE_VERSION > 37 warning("%a %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), #else warning("%08lX %s,%d: bad optype (%x)", cmd.ea,(char far *)Instructions[cmd.itype].name, #endif x.n, x.type); break; } }
//---------------------------------------------------------------------- static void process_operand(op_t &x, int use) { switch ( x.type ) { case o_reg: return; case o_near: { if (cmd.itype != TMS320C3X_RPTB ) { cref_t ftype = fl_JN; ea_t ea = calc_code_mem(x); if ( InstrIsSet(cmd.itype, CF_CALL) ) { if ( !func_does_return(ea) ) flow = false; ftype = fl_CN; } ua_add_cref(x.offb, ea, ftype); } else // evaluate RPTB loops as dref ua_add_dref(x.offb, calc_code_mem(x), dr_I); } break; case o_imm: if ( !use ) error("interr: emu"); process_imm(x); if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, 0); break; case o_mem: { ea_t ea = calc_data_mem(x); if (ea != BADADDR) { ua_add_dref(x.offb, ea, use ? dr_R : dr_W); ua_dodata2(x.offb, ea, x.dtyp); if ( !use ) doVar(ea); } } break; case o_phrase: break; case o_displ: doImmd(cmd.ea); break; default: if ( x.type == o_void ) { if ( cmd.itype == TMS320C3X_ABSF ) break; if ( cmd.itype == TMS320C3X_ABSI ) break; } warning("interr: emu2 address:%a operand:%d type:%d", cmd.ea, x.n, x.type); } }