void make_stack_var(op_t &x) { if (may_create_stkvars()) { adiff_t sp_off = x.value; if ( ua_stkvar2(x, sp_off, 0) ) op_stkvar(cmd.ea, x.n); } }
//---------------------------------------------------------------------- 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; } }
// 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 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); } }
// 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 process_operand(op_t &x, int use) { switch ( x.type ) { case o_bit: case o_reg: case o_cond8: case o_cond2: return; case o_near: case o_far: { if (cmd.itype != TMS320C54_rptb && cmd.itype != TMS320C54_rptbd) { cref_t ftype = fl_JN; ea_t ea = calc_code_mem(x.addr, x.type == o_near); if ( InstrIsSet(cmd.itype, CF_CALL) ) { if ( !func_does_return(ea) ) flow = false; ftype = fl_CN; } #ifndef TMS320C54_NO_NAME_NO_REF if ( x.dtyp == dt_byte ) ua_add_dref(x.offb, ea, dr_R); else ua_add_cref(x.offb, ea, ftype); #endif } #ifndef TMS320C54_NO_NAME_NO_REF else // evaluate RPTB[D] loops as dref ua_add_dref(x.offb, calc_code_mem(x.addr), dr_I); #endif } break; case o_imm: if ( !use ) error("interr: emu"); process_imm(x); #ifndef TMS320C54_NO_NAME_NO_REF if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, x.Signed ? OOF_SIGNED : 0); #endif break; case o_mem: case o_farmem: case o_mmr: { ea_t ea = calc_data_mem(x.addr, x.type == o_mem); if (ea != BADADDR) { #ifndef TMS320C54_NO_NAME_NO_REF ua_add_dref(x.offb, ea, use ? dr_R : dr_W); #endif ua_dodata2(x.offb, ea, x.dtyp); if ( !use ) doVar(ea); } } break; case o_local: // local variables if ( may_create_stkvars() && (get_func(cmd.ea) != NULL) && ua_stkvar2(x, x.addr, STKVAR_VALID_SIZE) ) { op_stkvar(cmd.ea, x.n); } break; case o_displ: doImmd(cmd.ea); break; default: warning("interr: emu2 address:%a operand:%d type:%d", cmd.ea, x.n, x.type); } }
// emulate operand static void handle_operand(op_t &op, bool loading) { switch ( op.type ) { // Address case o_near: // branch label - create code reference (call or jump // according to the instruction) { ea_t ea = toEA(cmd.cs, op.addr); cref_t ftype = fl_JN; if ( cmd.itype == m32r_bl ) { if ( !func_does_return(ea) ) flow = false; ftype = fl_CN; } ua_add_cref(op.offb, ea, ftype); } break; // Immediate case o_imm: if ( !loading ) { interr1("handle_operand(): o_imm with CF_CHG"); } handle_imm(); // if the value was converted to an offset, then create a data xref: if ( op_adds_xrefs(uFlag, op.n) ) ua_add_off_drefs2(op, dr_O, OOFW_IMM|OOF_SIGNED); // 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); } break; // Displ case o_displ: handle_imm(); // if the value was converted to an offset, then create a data xref: if ( op_adds_xrefs(uFlag, op.n) ) ua_add_off_drefs2(op, loading ? dr_R : dr_W, OOF_SIGNED|OOF_ADDR|OOFW_32); // create stack variables if required if ( may_create_stkvars() && !isDefArg(uFlag, op.n) ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && (op.reg == rFP || op.reg == rSP) && pfn->flags & FUNC_FRAME ) { if ( ua_stkvar2(op, op.addr, STKVAR_VALID_SIZE) ) { op_stkvar(cmd.ea, op.n); } } } break; case o_phrase: /* create stack variables if required */ if ( op.specflag1 == fRI && may_create_stkvars() && !isDefArg(uFlag, op.n) ) { func_t *pfn = get_func(cmd.ea); if ( pfn != NULL && (op.reg == rFP || op.reg == rSP) && pfn->flags & FUNC_FRAME ) { if ( ua_stkvar2(op, 0, STKVAR_VALID_SIZE) ) { op_stkvar(cmd.ea, op.n); } } } break; // Phrase - register - void : do nothing case o_reg: case o_void: break; // Others types should never be called default: interr2("handle_operand(): unknown type %d", op.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); } }