//---------------------------------------------------------------------- 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 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 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 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 fixup(uint32 ea, uint32 delta, int extdef) { fixup_data_t fd; fd.type = FIXUP_OFF32; if ( extdef ) fd.type |= FIXUP_EXTDEF; segment_t *s = getseg(delta); fd.displacement = get_long(ea); if ( s == NULL ) { fd.sel = 0; fd.off = delta; } else { fd.sel = (ushort)s->sel; fd.off = delta - get_segm_base(s); } set_fixup(ea, &fd); uint32 target = get_long(ea) + delta; put_long(ea, target); set_offset(ea, 0, 0); cmd.ea = ea; ua_add_dref(0, target, dr_O); cmd.ea = BADADDR; if ( target != toc_ea && !has_name(get_flags_novalue(ea)) && has_name(get_flags_novalue(target)) ) { char buf[MAXSTR]; if ( get_true_name(BADADDR, target, &buf[3], sizeof(buf)-3) != NULL ) { buf[0] = 'T'; buf[1] = 'C'; buf[2] = '_'; do_name_anyway(ea, buf); make_name_auto(ea); } } // toc.charset(ea,XMC_TC+1,1); }
//------------------------------------------------------------------------ // Конвертирование в данные(указан адресс) по указанному типу, // добавить крос референсы для текущей инструкции void DataSet(op_t &x, ea_t EA, int isload) { // Конвертирование в данные(указан адресс) по указанному типу ua_dodata2(x.offb, EA, x.dtyp); //добавить крос референсы для текущей инструкции ua_add_dref(x.offb, EA, isload ? dr_R : dr_W); }
//---------------------------------------------------------------------- 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 handle_operand(op_t &op) { switch (op.type) { // code address case o_near: { ea_t ea = toEA(cmd.cs, op.addr); cref_t mode = fl_JN; if (cmd.itype == m740_jsr) { if ( !func_does_return(ea) ) flow = false; mode = fl_CN; } ua_add_cref(op.offb, ea, mode); } break; // data address case o_mem: { enum dref_t mode = dr_U; if (is_addr_ind(op)) mode = dr_R; /* NOT dr_O */ else if (is_addr_read(op)) mode = dr_R; else if (is_addr_write(op)) mode = dr_W; ua_add_dref(op.offb, toEA(cmd.cs, op.addr), mode); ua_dodata2(op.offb, op.addr, op.dtyp); } break; // immediate case o_imm: handle_imm(op); // 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; // displ case o_displ: if (isOff(uFlag, op.n)) { ua_add_off_drefs2(op, dr_O, OOF_ADDR); ua_dodata2(op.offb, op.addr, op.dtyp); } break; // reg - do nothing case o_reg: case o_void: break; default: IDA_ERROR("Invalid op.type in handle_operand()"); } }
//---------------------------------------------------------------------- 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 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 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 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 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 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 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; } }
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 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); } }
// 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 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 idaapi emu() { char szLabel[MAXSTR]; insn_t saved; segment_t* pSegment; ea_t ea, length, offset; flags_t flags; uint32 dwFeature, i; dwFeature = cmd.get_canon_feature(); fFlow = !(dwFeature & CF_STOP); if (dwFeature & CF_USE1) op_emu(cmd.Op1, 1); if (dwFeature & CF_USE2) op_emu(cmd.Op2, 1); if (dwFeature & CF_CHG1) op_emu(cmd.Op1, 0); if (dwFeature & CF_CHG2) op_emu(cmd.Op2, 0); saved = cmd; switch (cmd.itype) { case M8B_MOV: if (!cmd.Op1.is_reg(rPSP)) break; case M8B_SWAP: if (cmd.itype == M8B_SWAP && !cmd.Op2.is_reg(rDSP)) break; for (i = 0; i < 5; ++i) { ea = decode_prev_insn(cmd.ea); if (ea == BADADDR) break; if (cmd.itype == M8B_MOV && cmd.Op1.is_reg(rA) && cmd.Op2.type == o_imm) { ea = toRAM(cmd.Op2.value); if (ea != BADADDR) { qsnprintf(szLabel, sizeof(szLabel), "%s_%0.2X", cmd.itype == M8B_MOV ? "psp" : "dsp", cmd.Op2.value); ua_add_dref(cmd.Op2.offb, ea, dr_O); set_name(ea, szLabel, SN_NOWARN); } break; } } break; case M8B_JACC: pSegment = getseg(cmd.ea); if (!pSegment) break; length = pSegment->endEA - cmd.ea; if (length > 256) length = 256; for (offset = 2; offset < length; offset += 2) { ea = toROM(saved.Op1.addr + offset); if (ea == BADADDR) break; flags = getFlags(ea); if (!hasValue(flags) || (has_any_name(flags) || hasRef(flags)) || !create_insn(ea)) break; switch (cmd.itype) { case M8B_JMP: case M8B_RET: case M8B_RETI: case M8B_IPRET: add_cref(saved.ea, ea, fl_JN); break; default: offset = length; } } break; case M8B_IORD: case M8B_IOWR: case M8B_IOWX: for (i = 0; i < 5; ++i) { ea = (saved.itype == M8B_IORD) ? decode_insn(cmd.ea + cmd.size) : decode_prev_insn(cmd.ea); if (ea == BADADDR) break; if (cmd.Op1.is_reg(rA) && cmd.Op2.type == o_imm) { qsnprintf(szLabel, sizeof(szLabel), "[A=%0.2Xh] ", cmd.Op2.value); if (get_portbits_sym(szLabel + qstrlen(szLabel), saved.Op1.addr, cmd.Op2.value)) set_cmt(saved.ea, szLabel, false); break; } } } cmd = saved; if ((cmd.ea & 0xFF) == 0xFF) { switch (cmd.itype) { case M8B_RET: case M8B_RETI: case M8B_XPAGE: break; default: QueueMark(Q_noValid, cmd.ea); } } if (fFlow) ua_add_cref(0, cmd.ea + cmd.size, fl_F); return 1; }
//---------------------------------------------------------------------- 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); } }
//------------------------------------------------------------------------ static void TouchArg(op_t &x,int isAlt,int isload) { ea_t jmpa; switch ( x.type ) { case o_near: // Jcc/ [jmp/call 37/67] case o_mem: // 37/67/77 case o_far: jmpa = toEA(x.type == o_far ? x.segval : codeSeg(x.addr16,x.n), x.addr16); if ( x.phrase == 0) { ua_add_cref(x.offb,jmpa,fl_JN ); break; } //Jcc extxref: if ( (x.phrase & 070) == 070 ) goto xrefset; if ( cmd.itype == pdp_jmp) ua_add_cref(x.offb,jmpa,fl_JF ); else if ( cmd.itype == pdp_jsr || cmd.itype == pdp_call ) { ua_add_cref(x.offb,jmpa,fl_CF); if ( !func_does_return(jmpa) ) flow = false; } else { xrefset: ua_dodata2(x.offb, jmpa, x.dtyp); ua_add_dref(x.offb, jmpa, isload ? dr_R : dr_W); } break; case o_displ: // 6x/7x (!67/!77) doImmdValue(); if ( !isload && x.phrase == (060 + rR0) && x.addr16 <= 1 ) loadR0data(&x, x.addr16); if ( !isAlt && isOff(emuFlg,x.n ) && (jmpa = get_offbase(cmd.ea, x.n)) != BADADDR) { jmpa += x.addr16; goto extxref; } break; case o_imm: // 27 if ( !x.ill_imm ) { doImmdValue(); if ( op_adds_xrefs(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, OOF_SIGNED); } break; case o_number: // EMT/TRAP/MARK/SPL if ( cmd.itype == pdp_emt && get_cmt(cmd.ea, false, NULL, 0) <= 0 ) { if ( x.value >= 0374 && x.value <= 0375 ) { cmd.Op2.value = (x.value == 0375) ? emuR0data.b[1] : (emuR0 >> 8); cmd.Op2.type = o_imm; } char buf[MAXSTR]; if ( get_predef_insn_cmt(cmd, buf, sizeof(buf)) > 0 ) set_cmt(cmd.ea, buf, false); cmd.Op2.type = o_void; } break; case o_reg: // 0 if ( x.reg == rR0 ) { if ( cmd.Op2.type == o_void ) { // one operand cmd if ( cmd.itype != pdp_clr ) { goto undefall; } else { if ( cmd.bytecmd ) emuR0 &= 0xFF00; else emuR0 = 0; goto undefdata; } } if ( &x == &cmd.Op2 ) { if ( cmd.itype != pdp_mov ) { if ( cmd.bytecmd ) { emuR0 |= 0xFF; goto undefdata; } else goto undefall; } if ( cmd.bytecmd ) goto undefall; if ( cmd.Op1.type == o_imm ) { if ( (emuR0 = (ushort)cmd.Op1.value) & 1 ) goto undefdata; emuR0data.w = get_word(toEA(cmd.cs, emuR0)); } else { undefall: emuR0 = 0xFFFF; undefdata: emuR0data.w = 0xFFFF; } } } break; case o_phrase: // 1x/2x/3x/4x/5x (!27/!37) if ( (x.phrase & 7) == rR0 ) { if ( !isload && x.phrase == (010 + rR0)) loadR0data(&x, 0 ); else if ( cmd.Op2.type == o_void || &x == &cmd.Op2 ) goto undefall; } case o_fpreg: // FPP break; default: warning("%" FMT_EA "o (%s): bad optype %d", cmd.ip, cmd.get_canon_mnem(), x.type); break; }
// 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); } }
//---------------------------------------------------------------------- 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 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 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; }
//---------------------------------------------------------------------- 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 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 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; } }