static void TouchArg( op_t &x, int isload ) { switch( x.type ) { case o_imm: case o_displ: if ( isOff(uFlag, x.n) ) ua_add_off_drefs(x, dr_O); break; case o_mem: case o_ind_mem: { ulong dea = intmem + x.addr; ua_dodata( dea, x.dtyp ); if( !isload ) doVar( dea ); ua_add_dref( x.offb, dea, isload ? dr_R : dr_W ); } break; case o_near: ulong 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 ) { if ( !func_does_return(ea) ) flow = false; } } }
static void TouchArg( op_t &x, int isload ) { switch( x.type ) { case o_displ: case o_imm: if ( isOff(uFlag, x.n) ) { int outf = x.type != o_imm ? OOF_ADDR : 0; ua_add_off_drefs2(x, dr_O, outf|OOF_SIGNED); } break; case o_mem: case o_ind_mem: { ea_t dea = intmem + x.addr; ua_dodata2(x.offb, dea, x.dtyp); if( !isload ) doVar( dea ); ua_add_dref( x.offb, dea, isload ? dr_R : dr_W ); } 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 ) { if ( !func_does_return(ea) ) flow = false; } } }
//---------------------------------------------------------------------- static void process_operand(op_t &x, bool isload) { ea_t ea; dref_t dref; if ( is_forced_operand(cmd.ea, x.n) ) return; switch ( x.type ) { case o_reg: case o_phrase: break; case o_imm: if ( !isload ) interr("emu1"); process_immediate_number(x.n); if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, OOFS_IFSIGN|OOFW_IMM); break; case o_mem: ea = calc_mem(x.addr); ua_dodata2(x.offb, ea, x.dtyp); dref = cmd.itype == I960_lda ? dr_O : isload ? dr_R : dr_W; ua_add_dref(x.offb, ea, dref); break; case o_near: { cref_t ftype = fl_JN; ea = calc_mem(x.addr); if ( InstrIsSet(cmd.itype, CF_CALL) ) { flow = func_does_return(ea); ftype = fl_CN; } ua_add_cref(x.offb, ea, ftype); } break; case o_displ: dref = cmd.itype == I960_lda ? dr_O : isload ? dr_R : dr_W; process_immediate_number(x.n); if ( x.reg == IP ) { ea_t ea = cmd.ea + 8 + x.addr; ua_add_dref(x.offb, ea, dref); } else { if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dref, OOFS_IFSIGN|OOF_SIGNED|OOF_ADDR|OOFW_32); } break; default: interr("emu"); } }
//---------------------------------------------------------------------- static void add_code_xref(op_t &x, ea_t ea) { cref_t ftype = fl_JN; if ( InstrIsSet(cmd.itype, CF_CALL) ) { if ( !func_does_return(ea) ) flow = false; ftype = fl_CN; } ua_add_cref(x.offb, ea, ftype); }
//---------------------------------------------------------------------- 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 TouchArg(op_t &x,int isAlt,int isload) { switch ( x.type ) { case o_reg: case o_phrase: case o_port: break; case o_imm: if ( !isload ) goto badTouch; doImmdValue(x.n); if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, OOF_SIGNED); break; case o_displ: doImmdValue(x.n); if ( isAlt ) break; if ( isOff(uFlag, x.n) ) { ua_add_off_drefs2(x, isload ? dr_R : dr_W, OOF_ADDR); ea_t ea = calc_target(cmd.ea+x.offb, cmd.ea, x.n, x.addr); ua_dodata2(x.offb, ea, x.dtyp); if ( !isload ) doVar(ea); } break; case o_near: { cref_t ftype = fl_JN; ea_t ea = toEA(cmd.cs, x.addr); if ( InstrIsSet(cmd.itype, CF_CALL) ) { if ( !func_does_return(ea) ) flow = false; ftype = fl_CN; } ua_add_cref(x.offb, ea, ftype); } break; case o_mem: { ea_t ea = toEA(dataSeg(), x.addr); ua_add_dref(x.offb, ea, isload ? dr_R : dr_W); } break; default: badTouch: if ( cmd.itype != AVR_lpm && cmd.itype != AVR_elpm ) warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type); break; } }
//---------------------------------------------------------------------- static bool TouchArg(op_t &x,int isload) { dref_t xreftype; uchar outf; switch ( x.type ) { case o_phrase: // 2 registers case o_reg: break; case o_imm: if ( !isload ) goto badTouch; xreftype = dr_O; outf = OOF_SIGNED; goto makeImm; case o_displ: xreftype = isload ? dr_R : dr_W; outf = OOF_SIGNED|OOF_ADDR; makeImm: doImmdValue(); if ( op_adds_xrefs(uFlag, x.n) ) ua_add_off_drefs2(x, xreftype, outf); break; case o_mem: ua_dodata2(x.offb, x.addr, x.dtyp); if ( !isload ) doVar(x.addr); ua_add_dref(x.offb,x.addr,isload ? dr_R : dr_W); break; case o_near: { int iscall = InstrIsSet(cmd.itype,CF_CALL); ua_add_cref(x.offb,x.addr,iscall ? fl_CN : fl_JN); if ( iscall && !func_does_return(x.addr) ) return false; } break; default: badTouch: warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type); break; } return true; }
//---------------------------------------------------------------------- static void process_operand(op_t &x,int isAlt,int isload) { switch ( x.type ) { case o_reg: case o_reglist: return; case o_imm: QASSERT(10090, isload); process_immediate_number(x.n); if ( op_adds_xrefs(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, calc_opimm_flags()); break; case o_phrase: case o_displ: process_immediate_number(x.n); if ( isAlt ) break; if ( op_adds_xrefs(uFlag, x.n) ) { ea_t ea = ua_add_off_drefs2(x, isload ? dr_R : dr_W, calc_opdispl_flags()); if ( ea != BADADDR ) { ua_dodata2(x.offb, ea, x.dtyp); if ( !isload ) doVar(ea); } } // create stack variables if required if ( x.type == o_displ && may_create_stkvars() && !isDefArg(uFlag, x.n) ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && (issp(x.phrase) || isbp(x.phrase) && (pfn->flags & FUNC_FRAME) != 0) ) { if ( ua_stkvar2(x, x.addr, STKVAR_VALID_SIZE) ) op_stkvar(cmd.ea, x.n); } } break; case o_near: case o_far: { cref_t ftype = x.type == o_near ? fl_JN : fl_JF; ea_t ea = calc_mem(x); if ( InstrIsSet(cmd.itype, CF_CALL) ) { if ( !func_does_return(ea) ) flow = false; ftype = x.type == o_near ? fl_CN : fl_CF; } ua_add_cref(x.offb, ea, ftype); } break; case o_mem: { ea_t ea = calc_mem(x); ua_add_dref(x.offb, ea, isload ? dr_R : dr_W); ua_dodata2(x.offb, ea, x.dtyp); if ( !isload ) doVar(ea); } break; default: INTERR(10091); } }
//---------------------------------------------------------------------- static int LoadArg(op_t &x) { dref_t xreftype; switch ( x.type ) { case o_reg: { if ( x.reg == R_sp ) goto Undefined; // AbstractRegister *in = &i5_getreg(x.reg); // if ( ! in->isDef() ) goto Undefined; // r.doInt(in->value()); return 1; } case o_imm: // r.doInt(unsigned(x.value)); xreftype = dr_O; MakeImm: doImmdValue(x.n); if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, xreftype, 0); return 1; case o_displ: // r.undef(); xreftype = dr_R; goto MakeImm; case o_mem: { ea_t ea = toEA(dataSeg_op(x.n),x.addr); ua_add_dref(x.offb,ea,dr_R); ua_dodata2(x.offb, ea, x.dtyp); if ( !isVar(get_flags_novalue(ea)) && isLoaded(ea) ) { // r.doInt( x.dtyp != dt_byte ? get_word(ea) : char(get_byte(ea)) ); return 1; } } case o_phrase: Undefined: // r.undef(); break; case o_near: { ea_t segbase = codeSeg(x.addr,x.n); ea_t ea = toEA(segbase,x.addr); ea_t thisseg = cmd.cs; int iscall = InstrIsSet(cmd.itype,CF_CALL); ua_add_cref(x.offb, ea, iscall ? ((segbase == thisseg) ? fl_CN : fl_CF) : ((segbase == thisseg) ? fl_JN : fl_JF)); if ( iscall && !func_does_return(ea) ) flow = false; // r.doInt(unsigned(x.addr)); } return 1; default: // warning("%a: %s,%d: bad load optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type); break; } return 0; }
//---------------------------------------------------------------------- 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 handle_operand(op_t &x, bool read_access) { ea_t ea; dref_t dreftype; switch ( x.type ) { case o_void: case o_reg: break; case o_imm: QASSERT(557, read_access); dreftype = dr_O; MAKE_IMMD: doImmdValue(); if ( isOff(uFlag, x.n) ) ua_add_off_drefs(x, dreftype); break; case o_displ: dreftype = read_access ? dr_R : dr_W; switch ( x.phrase ) { case rD: // "dp" case rDX: // "dp, X" case rDY: // "dp, Y" case riDX: // "(dp, X)" case rDi: // "(dp,n)" case rDiL: // "long(dp,n)" case rDiY: // "(dp,n), Y" case rDiLY: // "long(dp,n), Y" { sel_t dp = get_segreg(cmd.ea, rD); if ( dp != BADSEL ) { ea_t orig_ea = dp + x.addr; ea = xlat(orig_ea); goto MAKE_DREF; } else { goto MAKE_IMMD; } } case rAbsi: // "(abs)" case rAbsX: // "abs, X" case rAbsY: // "abs, Y" case rAbsiL: // "long(abs)" ea = toEA(dataSeg_op(x.n), x.addr); goto MAKE_DREF; case rAbsXi: // "(abs,X)" ea = toEA(codeSeg(cmd.ea, x.n), x.addr); // jmp, jsr goto MAKE_DREF; case rAbsLX: // "long abs, X" ea = x.addr; goto MAKE_DREF; default: goto MAKE_IMMD; } case o_mem: case o_mem_far: ea = calc_addr(x); MAKE_DREF: ua_dodata2(x.offb, ea, x.dtyp); if ( !read_access ) doVar(ea); ua_add_dref(x.offb, ea, read_access ? dr_R : dr_W); break; case o_near: case o_far: { ea_t orig_ea; ea = calc_addr(x, &orig_ea); if ( cmd.itype == M65816_per ) { ua_add_dref(x.offb, ea, dr_O); } else { bool iscall = InstrIsSet(cmd.itype, CF_CALL); cref_t creftype = x.type == o_near ? iscall ? fl_CN : fl_JN : iscall ? fl_CF : fl_JF; ua_add_cref(x.offb, ea, creftype); if ( flow && iscall ) flow = func_does_return(ea); } } break; default: INTERR(558); } }
static void op_emu(op_t& x, int fIsLoad) { char szLabel[128]; cref_t ftype; ea_t ea; switch (x.type) { case o_reg: case o_phrase: return; case o_imm: if (!fIsLoad) break; op_imm(cmd.ea); return; case o_displ: case o_mem: switch (cmd.itype) { case M8B_IORD: case M8B_IOWR: case M8B_IOWX: case M8B_IPRET: ea = toIOP(x.addr); if (ea != BADADDR) { ua_dodata2(x.offb, ea, x.dtyp); if (!fIsLoad) doVar(ea); ua_add_dref(x.offb, ea, cmd.itype == M8B_IORD ? dr_R : dr_W); } break; default: ea = toRAM(x.addr); if (ea != BADADDR) { if (!has_any_name(get_flags_novalue(ea))) { qsnprintf(szLabel, sizeof(szLabel), "ram_%0.2X", x.addr); set_name(ea, szLabel, SN_NOWARN); } ua_dodata2(x.offb, ea, x.dtyp); if (!fIsLoad) doVar(ea); ua_add_dref(x.offb, ea, cmd.itype == M8B_IORD ? dr_R : dr_W); } } return; case o_near: ea = toROM(x.addr); if (ea != BADADDR) { switch (cmd.itype) { case M8B_INDEX: if (!has_any_name(get_flags_novalue(ea))) { qsnprintf(szLabel, sizeof(szLabel), "tbl_%0.4X", x.addr); set_name(ea, szLabel, SN_NOWARN); } ua_add_dref(x.offb, ea, dr_R); break; default: ftype = fl_JN; if (InstrIsSet(cmd.itype, CF_CALL)) { if (!func_does_return(ea)) fFlow = false; ftype = fl_CN; } ua_add_cref(x.offb, ea, ftype); } } return; } warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type); }
//---------------------------------------------------------------------- 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; }
//---------------------------------------------------------------------- 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); } }
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_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); } }
//---------------------------------------------------------------------- static void TouchArg(op_t &x,int isload) { ea_t ea; switch ( x.type ) { case o_phrase: // 2 registers or indirect addressing if ( cmd.itype != TMS_mar && cmd.itype != TMS2_mar && find_ar(&ea) ) goto set_dref; case o_reg: case o_bit: case o_cond: break; case o_imm: if ( ! isload ) goto badTouch; doImmdValue(); if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, is_mpy() ? OOF_SIGNED : 0); break; case o_mem: ea = toEA(dataSeg_op(x.n),x.addr); set_dref: ua_dodata2(x.offb, ea, x.dtyp); if ( ! isload ) doVar(ea); ua_add_dref(x.offb,ea,isload ? dr_R : dr_W); if ( x.type == o_mem ) if ( cmd.itype == TMS_dmov || cmd.itype == TMS_ltd || cmd.itype == TMS_macd || cmd.itype == TMS_madd || cmd.itype == TMS2_dmov || cmd.itype == TMS2_macd ) ua_add_dref(x.offb,ea+1,dr_W); break; case o_near: { ea_t segbase = codeSeg(x.addr, x.n); ea = toEA(segbase, x.addr); if ( cmd.itype == TMS_blpd || cmd.itype == TMS_mac || cmd.itype == TMS_macd || cmd.itype == TMS2_blkp || cmd.itype == TMS2_mac || cmd.itype == TMS2_macd ) goto set_dref; uval_t thisseg = cmd.cs; int iscall = InstrIsSet(cmd.itype,CF_CALL); if ( cmd.itype == TMS_rptb && isTail(get_flags_novalue(ea)) ) { // small hack to display end_loop-1 instead of before_end_loop+1 ea++; } ua_add_cref(x.offb, ea, iscall ? ((segbase == thisseg) ? fl_CN : fl_CF) : ((segbase == thisseg) ? fl_JN : fl_JF)); if ( iscall ) { if ( !func_does_return(ea) ) flow = false; } } break; default: badTouch: warning("%a: %s,%d: bad optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type); break; } }
static void handle_operand(op_t &x,int loading) { switch ( x.type ) { case o_phrase: // no special hanlding for these types case o_reg: break; case o_imm: // an immediate number as an operand if ( !loading ) goto BAD_LOGIC; // this can't happen! doImmdValue(); // handle immediate number // if the value was converted to an offset, then create a data xref: if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, OOFS_IFSIGN); break; case o_displ: doImmdValue(); // handle immediate number // if the value was converted to an offset, then create a data xref: if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, loading?dr_R:dr_W, OOFS_IFSIGN|OOF_ADDR); break; case o_bit: // 8051 specific operand types - bits case o_bitnot: x.addr = (x.reg & 0xF8); if( (x.addr & 0x80) == 0 ) x.addr = x.addr/8 + 0x20; attach_bit_comment(x.addr, x.reg & 7); // attach a comment if necessary goto MEM_XREF; case o_bit251: attach_bit_comment(x.addr, x.b251_bit); /* no break */ case o_mem: // an ordinary memory data reference MEM_XREF: { ea_t dea = map_addr(x.addr, x.n, true); ua_dodata2(x.offb, dea, x.dtyp); if ( !loading ) doVar(dea); // write access ua_add_dref(x.offb, dea, loading ? dr_R : dr_W); } break; case o_near: // a code reference { ea_t ea = map_addr(x.addr, x.n, false); 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); } break; default: BAD_LOGIC: 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 ,int isload) { if ( cmd.Op2.type == o_reg && cmd.Op2.reg == F || cmd.itype == PIC_swapf ) isload = 0; switch ( x.type ) { case o_reg: return; case o_imm: if ( !isload ) error("interr: emu"); process_immediate_number(x.n); if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, calc_outf(x)); break; case o_near: { cref_t ftype = fl_JN; ea_t ea = calc_code_mem(x.addr); if ( InstrIsSet(cmd.itype, CF_CALL) ) { if ( !func_does_return(ea) ) flow = false; ftype = fl_CN; } ua_add_cref(x.offb, ea, ftype); } break; case o_mem: { ea_t ea = calc_data_mem(x.addr); destroy_if_unnamed_array(ea); ua_add_dref(x.offb, ea, isload ? dr_R : dr_W); ua_dodata2(x.offb, ea, x.dtyp); if ( !isload ) doVar(ea); if ( may_create_stkvars()) { if ( x.addr == PIC16_INDF2 ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && (pfn->flags & FUNC_FRAME) != 0 ) { ua_stkvar2(cmd.Op1, 0, STKVAR_VALID_SIZE); } } else if ( x.addr == PIC16_PLUSW2 ) { insn_t saved = cmd; if ( decode_prev_insn(cmd.ea) != BADADDR && cmd.itype == PIC_movlw ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && (pfn->flags & FUNC_FRAME) != 0 ) { if ( ua_stkvar2(cmd.Op1, cmd.Op1.value, STKVAR_VALID_SIZE) ) op_stkvar(cmd.ea, cmd.Op1.n); } } cmd = saved; } } } break; default: warning("interr: emu2 %a", cmd.ea); } }