//---------------------------------------------------------------------- static void process_operand(op_t &x,int isAlt,int isload) { switch ( x.type ) { case o_reg: break; default: // interr("emu"); break; case o_imm: // if ( !isload ) interr("emu2"); process_immediate_number(x.n); if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, x.amode & amode_signed ? OOF_SIGNED : 0); break; case o_phrase: if ( !isAlt && 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_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; case o_near: add_near_ref(x, calc_mem(x)); break; case o_textphrase: break; case o_local: // local variables if ( may_create_stkvars() ) { func_t *pfn = get_func(cmd.ea); if ( (pfn != NULL) && (pfn->flags & FUNC_FRAME) && ua_stkvar2(x, x.addr, STKVAR_VALID_SIZE) ) op_stkvar(cmd.ea, x.n); } break; } }
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,int isAlt,int isload) { switch ( x.type ) { case o_reg: break; default: // interr("emu"); break; case o_imm: process_immediate_number(x.n); if ( op_adds_xrefs(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, OOFS_IFSIGN); break; case o_phrase: if ( !isAlt && op_adds_xrefs(uFlag, x.n) ) { ea_t ea = ua_add_off_drefs2(x, isload ? dr_R : dr_W, OOF_ADDR); if ( ea != BADADDR ) { ua_dodata2(x.offb, ea, x.dtyp); if ( !isload ) doVar(ea); } } 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); if ( x.amode & amode_l ) { ea = ymem + x.addr; ua_add_dref(x.offb, ea, isload ? dr_R : dr_W); ua_dodata2(x.offb, ea, x.dtyp); } } break; case o_near: add_near_ref(x, calc_mem(x)); break; } }
//---------------------------------------------------------------------- static void TouchArg(op_t &x, int isload) { switch ( x.type ) { case o_displ: case o_imm: if ( op_adds_xrefs(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: case o_reg: case o_ind_reg: { ea_t dea; if ( x.type == o_mem || x.type == o_ind_mem ) { dea = map_addr(x.addr, x.n, true); } else { if ( x.reg >= rRR0 ) dea = map_addr(x.reg - rRR0, x.n, true); else dea = map_addr(x.reg - rR0, x.n, true); } ua_dodata2(x.offb, dea, x.dtyp); if ( !isload ) doVar(dea); ua_add_dref(x.offb, dea, isload ? dr_R : dr_W); if ( !has_user_name(get_flags_novalue(dea)) && dea > intmem) { char buf[10]; int num = dea - intmem; if ( num < 0x100 ) { qsnprintf(buf, sizeof(buf), "R%d", num); } else if ( num < 0x1000 ) { qsnprintf(buf, sizeof(buf), "ERF_%X_%d", num >> 8, num & 0xFF); } else { int reg_no = ((num >> 4) & 0xF0) + (num & 0xF); int subbank_no = ((num >> 4) & 0xF) + 1; qsnprintf(buf, sizeof(buf), "R%d_%X", reg_no, subbank_no); } set_name(dea, buf, SN_NOWARN); }
//---------------------------------------------------------------------- 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 SaveArg(op_t &x) { switch ( x.type ) { case o_reg: { // if ( x.reg == R_sp ) return; // AbstractRegister *out = &i5_getreg(x.reg); // if ( ! isDef(r) ) { // out->undef(); // } else { // out->doInt(r.value()); // } return; } case o_mem: { ea_t ea = toEA(dataSeg_op(x.n),x.addr); ua_dodata2(x.offb, ea, x.dtyp); doVar(ea); ua_add_dref(x.offb,ea,dr_W); } break; case o_displ: doImmdValue(x.n); if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dr_W, OOF_ADDR); case o_phrase: break; default: switch ( cmd.itype ) { case Z80_in0: case Z80_outaw: break; default: // warning("%a: %s,%d: bad save optype %d", cmd.ea, cmd.get_canon_mnem(), x.n, x.type); break; } break; } }
//---------------------------------------------------------------------- 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 void process_operand(op_t &x,int isAlt,int isload) { switch ( x.type ) { case o_reg: case o_phrase: case o_reglist: return; case o_imm: QASSERT(10094, isload); process_immediate_number(x.n); if ( op_adds_xrefs(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, OOFS_IFSIGN|OOFW_IMM); break; 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, get_displ_outf(x)); if ( ea != BADADDR ) { ua_dodata2(x.offb, ea, x.dtyp); if ( !isload ) doVar(ea); } } // create stack variables if required if ( 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: add_code_xref(x, calc_mem(x.addr)); break; case o_mem: case o_memind: { ea_t ea = calc_mem(x.addr); if ( !isEnabled(ea) && find_sym(ea) ) break; // address not here ua_add_dref(x.offb, ea, isload ? dr_R : dr_W); ua_dodata2(x.offb, ea, x.dtyp); if ( x.type == o_memind ) { ssize_t size = get_dtyp_size(x.dtyp); flags_t F = getFlags(ea); if ( (isWord(F) || isDwrd(F)) && (!isDefArg0(F) || isOff0(F)) ) { ea_t target = calc_mem(size == 2 ? get_word(ea) : (get_long(ea) & 0xFFFFFFL)); if ( isEnabled(target) ) add_code_xref(x, target); if ( !isOff0(F) ) set_offset(ea, 0, calc_mem(0)); } break; } if ( !isload ) doVar(ea); } break; default: INTERR(10095); } }
//---------------------------------------------------------------------- int idaapi emu(void) { uint32 Feature = cmd.get_canon_feature(); flow = ((Feature & CF_STOP) == 0); if ( Feature & CF_USE1 ) handle_operand(cmd.Op1, 1); if ( Feature & CF_USE2 ) handle_operand(cmd.Op2, 1); if ( Feature & CF_CHG1 ) handle_operand(cmd.Op1, 0); if ( Feature & CF_CHG2 ) handle_operand(cmd.Op2, 0); if ( Feature & CF_JUMP ) QueueSet(Q_jumps, cmd.ea); if ( flow ) ua_add_cref(0,cmd.ea+cmd.size,fl_F); uint8 code = get_byte(cmd.ea); const struct opcode_info_t &opinfo = get_opcode_info(code); if ( opinfo.itype == M65816_jmp || opinfo.itype == M65816_jsr ) { if ( opinfo.addr == ABS_INDIR || opinfo.addr == ABS_INDIR_LONG || opinfo.addr == ABS_IX_INDIR ) { QueueSet(Q_jumps,cmd.ea); } } #if 0 switch ( opinfo.addr ) { case ABS_LONG_IX: { ea_t orig_ea = cmd.Op1.addr; ea_t ea = xlat(orig_ea); bool read_access; if ( cmd.itype == M65816_sta ) read_access = false; else read_access = true; if ( !read_access ) doVar(ea); ua_add_dref(cmd.Op1.offb, ea, read_access ? dr_R : dr_W); break; } case DP: { bool read_access; if ( cmd.itype == M65816_tsb || cmd.itype == M65816_asl || cmd.itype == M65816_trb || cmd.itype == M65816_rol || cmd.itype == M65816_lsr || cmd.itype == M65816_ror || cmd.itype == M65816_dec || cmd.itype == M65816_inc ) read_access = false; else read_access = true; int32 val = backtrack_value(cmd.ea, 2, BT_DP); if ( val != -1 ) { ea_t orig_ea = val + cmd.Op1.addr; ea_t ea = xlat(orig_ea); ua_dodata2(cmd.Op1.offb, ea, cmd.Op1.dtyp); if ( !read_access ) doVar(ea); ua_add_dref(cmd.Op1.offb, ea, read_access ? dr_R : dr_W); } } break; } #endif switch ( cmd.itype ) { case M65816_sep: case M65816_rep: { // Switching 8 -> 16 bits modes. uint8 flag_data = get_byte(cmd.ea + 1); uint8 m_flag = flag_data & 0x20; uint8 x_flag = flag_data & 0x10; uint8 val = (cmd.itype == M65816_rep) ? 0 : 1; if ( m_flag ) split_srarea(cmd.ea + 2, rFm, val, SR_auto); if ( x_flag ) split_srarea(cmd.ea + 2, rFx, val, SR_auto); } break; case M65816_xce: { // Switching to native mode? uint8 prev = get_byte(cmd.ea - 1); const struct opcode_info_t &opinf = get_opcode_info(prev); if ( opinf.itype == M65816_clc ) split_srarea(cmd.ea + 1, rFe, 0, SR_auto); else if ( opinf.itype == M65816_sec ) split_srarea(cmd.ea + 1, rFe, 1, SR_auto); } break; case M65816_jmp: case M65816_jml: case M65816_jsl: case M65816_jsr: { if ( cmd.Op1.full_target_ea ) { ea_t ftea = cmd.Op1.full_target_ea; if ( cmd.itype != M65816_jsl && cmd.itype != M65816_jml ) ftea = toEA(codeSeg(ftea, 0), ftea); else ftea = xlat(ftea); split_srarea(ftea, rFm, get_segreg(cmd.ea, rFm), SR_auto); split_srarea(ftea, rFx, get_segreg(cmd.ea, rFx), SR_auto); split_srarea(ftea, rFe, get_segreg(cmd.ea, rFe), SR_auto); split_srarea(ftea, rPB, ftea >> 16, SR_auto); split_srarea(ftea, rB, get_segreg(cmd.ea, rB), SR_auto); split_srarea(ftea, rDs, get_segreg(cmd.ea, rDs), SR_auto); split_srarea(ftea, rD, get_segreg(cmd.ea, rD), SR_auto); } } break; case M65816_plb: { int32 val = backtrack_value(cmd.ea, 1, BT_STACK); if ( val != -1 ) { split_srarea(cmd.ea + cmd.size, rB, val, SR_auto); split_srarea(cmd.ea + cmd.size, rDs, val << 12, SR_auto); } } break; case M65816_pld: { int32 val = backtrack_value(cmd.ea, 2, BT_STACK); if ( val != -1 ) split_srarea(cmd.ea + cmd.size, rD, val, SR_auto); } break; case M65816_plp: { // Ideally, should pass another parameter, specifying when to stop // backtracking. // For example, in order to avoid this: // PHP // PLP <-- this one is causing interference // (dunno if that even happens, though) // PLP ea_t ea = backtrack_prev_ins(cmd.ea, M65816_php); if ( ea != BADADDR ) { uint16 p = get_cpu_status(ea); split_srarea(cmd.ea + cmd.size, rFm, (p >> 5) & 0x1, SR_auto); split_srarea(cmd.ea + cmd.size, rFx, (p >> 4) & 0x1, SR_auto); } }
//---------------------------------------------------------------------- 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); }
//---------------------------------------------------------------------- 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); } }
//---------------------------------------------------------------------- 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); } }