//---------------------------------------------------------------------- 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(); int flag1 = is_forced_operand(cmd.ea, 0); int flag2 = is_forced_operand(cmd.ea, 1); int flag3 = is_forced_operand(cmd.ea, 2); flow = (Feature & CF_STOP) == 0; if ( Feature & CF_USE1 ) process_operand(cmd.Op1, flag1, 1); if ( Feature & CF_USE2 ) process_operand(cmd.Op2, flag2, 1); if ( Feature & CF_USE3 ) process_operand(cmd.Op3, flag3, 1); if ( Feature & CF_CHG1 ) process_operand(cmd.Op1, flag1, 0); if ( Feature & CF_CHG2 ) process_operand(cmd.Op2, flag2, 0); if ( Feature & CF_CHG3 ) process_operand(cmd.Op3, flag3, 0); // // Check for: // - the register bank changes // - PCLATH changes // - PCL changes // for ( int i=0; i < 3; i++ ) { int reg = 0; switch ( i ) { case 0: reg = BANK; if ( !is_bank() ) continue; break; case 1: reg = PCLATH; if ( !is_pclath() ) continue; break; case 2: reg = -1; if ( !is_pcl() ) continue; break; } sel_t v = (reg == -1) ? cmd.ip : getSR(cmd.ea, reg); if ( cmd.Op2.type == o_reg && cmd.Op2.reg == F ) { // split(reg, v); } else { switch ( cmd.itype ) { case PIC_bcf: case PIC_bcf3: case PIC_bsf: case PIC_bsf3: if ( ((ptype == PIC12) && (cmd.Op2.value == 5) ) // bank selector || ((ptype == PIC14) && ( (reg == BANK && (cmd.Op2.value == 5 || cmd.Op2.value == 6)) || (reg == PCLATH && (cmd.Op2.value == 3 || cmd.Op2.value == 4)))) || ((ptype == PIC16) && (sval_t(cmd.Op2.value) >= 0 && cmd.Op2.value <= 3))) { if ( v == BADSEL ) v = 0; int shift = 0; if ( ptype == PIC14 && reg == BANK ) shift = 5; if ( cmd.itype == PIC_bcf ) v = v & ~(1 << (cmd.Op2.value-shift)); else v = v | (1 << (cmd.Op2.value-shift)); split(reg, v); } break; case PIC_clrf: case PIC_clrf2: split(reg, 0); break; case PIC_swapf: case PIC_swapf3: split(reg, ((v>>4) & 15) | ((v & 15) << 4)); break; case PIC_movwf: case PIC_movwf2: case PIC_addlw: case PIC_andlw: case PIC_iorlw: case PIC_sublw: case PIC_xorlw: { insn_t saved = cmd; if ( decode_prev_insn(cmd.ea) != BADADDR && ( cmd.itype == PIC_movlw ) ) { switch ( saved.itype ) { case PIC_movwf: case PIC_movwf2: v = cmd.Op1.value; break; case PIC_addlw: v += cmd.Op1.value; break; case PIC_andlw: v &= cmd.Op1.value; break; case PIC_iorlw: v |= cmd.Op1.value; break; case PIC_sublw: v -= cmd.Op1.value; break; case PIC_xorlw: v ^= cmd.Op1.value; break; } } else { v = BADSEL; } cmd = saved; } split(reg, v); break; case PIC_movlw: split(reg, cmd.Op2.value); break; } } } // Such as , IDA doesn't seem to convert the following: // tris 6 // into // tris PORTB ( or whatever ) if ( cmd.itype == PIC_tris && !isDefArg0(uFlag) ) set_offset(cmd.ea, 0, dataseg); // movlw value // followed by a // movwf FSR // should convert value into an offset , because FSR is used as a pointer to // the INDF (indirect addressing file) if ( ptype == PIC12 || ptype == PIC14 && cmd.itype == PIC_movwf && cmd.Op1.type == o_mem && (cmd.Op1.addr & 0x7F) == 0x4 ) // FSR { insn_t saved = cmd; if ( decode_prev_insn(cmd.ea) != BADADDR && cmd.itype == PIC_movlw ) { set_offset(cmd.ea, 0, dataseg); } cmd = saved; } // Also - it seems to make sense to me that a // movlw value // followed by a // tris PORTn (or movwf TRISn) // should convert value into a binary , because the bits indicate whether a // port is defined for input or output. if ( is_load_tris_reg() ) { insn_t saved = cmd; if ( decode_prev_insn(cmd.ea) != BADADDR && cmd.itype == PIC_movlw ) { op_bin(cmd.ea, 0); } cmd = saved; } // Move litteral to BSR if ( cmd.itype == PIC_movlb1 ) split(BANK, cmd.Op1.value); // // Determine if the next instruction should be executed // if ( !flow ) flow = conditional_insn(); if ( segtype(cmd.ea) == SEG_XTRN ) flow = 0; if ( flow ) ua_add_cref(0,cmd.ea+cmd.size,fl_F); return 1; }