// emulate an instruction int emu(void) { uint32 feature = cmd.get_canon_feature(); flow = ((feature & CF_STOP) == 0); if (cmd.Op1.type != o_void) handle_operand(cmd.Op1); if (cmd.Op2.type != o_void) handle_operand(cmd.Op2); if (cmd.Op3.type != o_void) handle_operand(cmd.Op3); /* we can't use this code if (feature & CF_USE1) handle_operand(cmd.Op1, 1); if (feature & CF_USE2) handle_operand(cmd.Op2, 1); if (feature & CF_USE3) handle_operand(cmd.Op3, 1); */ // we don't use CF_JUMP //if (feature & CF_JUMP) switch (cmd.itype) { case m740_jmp: case m740_jsr: if (cmd.Op1.type != o_void && is_addr_ind(cmd.Op1)) QueueMark(Q_jumps, cmd.ea); break; } /* if (feature & CF_CHG1) handle_operand(cmd.Op1, 0); if (feature & CF_CHG2) handle_operand(cmd.Op2, 0); if (feature & CF_CHG3) handle_operand(cmd.Op3, 0); */ if (flow) { // skip the next byte if the current insn is brk if (cmd.itype == m740_brk) { ua_add_cref(0, cmd.ea + cmd.size + 1, fl_JN); doByte(cmd.ea + cmd.size, 1); } else { ua_add_cref(0, cmd.ea + cmd.size, fl_F); } } return 1; }
// Emulate an instruction. int idaapi emu(void) { bool flow = !is_stop() || (cmd.auxpref & INSN_DELAY_SHOT); if ( flow ) { insn_t cmd_backup = cmd; if ( decode_prev_insn(cmd.ea) != BADADDR ) { flow = !(is_stop() && (cmd.auxpref & INSN_DELAY_SHOT)); } cmd = cmd_backup; } if ( cmd.Op1.type != o_void) handle_operand(cmd.Op1 ); if ( cmd.Op2.type != o_void) handle_operand(cmd.Op2 ); if ( cmd.Op3.type != o_void) handle_operand(cmd.Op3 ); if ( cmd.Op4.type != o_void) handle_operand(cmd.Op4 ); if ( flow ) ua_add_cref(0, cmd.ea + cmd.size, fl_F); return 1; }
int parse_ld_line(ld_line_t line) { int rv = PLC_OK; if(line == (ld_line_t)NULL) return PLC_ERR; int c = LD_AND; //default character = '-' BYTE n_mode = FALSE; while (line->status == STATUS_UNRESOLVED && c != LD_NODE) { //loop c = read_char(line->buf, line->cursor); switch (c) { case LD_NODE://PAUSE break; case ERR_BADCHAR: case (BYTE)PLC_ERR: rv = PLC_ERR; line->status = STATUS_ERROR; break; case OP_END:/*this should happen only if line ends without a valid coil*/ line->status = STATUS_RESOLVED; line->stmt = NULL;//clear_tree(line->stmt); break; case LD_OR: case LD_BLANK://if blank or '|', empty value for the line. line->cursor++; line->stmt = NULL;//clear_tree(line->stmt); break; case LD_NOT: n_mode = TRUE; //normally closed mode case LD_AND: line->cursor++; break; case LD_COIL://see if it is a coil: ()[] case LD_SET: case LD_RESET: case LD_DOWN: rv = handle_coil(c, line); break; default://otherwise operand is expected(i,q,f,r,m,t,c,b) rv = handle_operand(c, n_mode, line); n_mode = FALSE; break; } } if(rv < PLC_OK) line->stmt = clear_tree(line->stmt); return rv; }
int idaapi emu(void) { int features; // // Determine the current instruction's features. // features = cmd.get_canon_feature(); bool flow = (features & CF_STOP) == 0; // // Examine each operand and determine what effect, if any, // it makes on the environment. // // Operands that are read if ( features & CF_USE1 ) flow &= handle_operand(cmd.Op1, hop_READ); if ( features & CF_USE2 ) flow &= handle_operand(cmd.Op2, hop_READ); if ( features & CF_USE3 ) flow &= handle_operand(cmd.Op3, hop_READ); // Operands that are written if ( features & CF_CHG1 ) flow &= handle_operand(cmd.Op1, hop_WRITE); if ( features & CF_CHG2 ) flow &= handle_operand(cmd.Op2, hop_WRITE); if ( features & CF_CHG3 ) flow &= handle_operand(cmd.Op3, hop_WRITE); // // Determine whether the instruction stops the execution flow. // if ( flow ) { // // This instruction doesn't stop execution flow. // Add a cross reference to the next instrction. // ua_add_cref(0,cmd.ea+cmd.size,fl_F); } // // If the instruction makes a branch, let the IDA kernel // know. // if ( features & CF_JUMP ) QueueSet(Q_jumps, cmd.ea); return 1; }
// emulate an instruction 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_USE3) handle_operand(cmd.Op3, 1 ); if ( feature & CF_JUMP) QueueMark(Q_jumps, cmd.ea ); if ( feature & CF_CHG1) handle_operand(cmd.Op1, 0 ); if ( feature & CF_CHG2) handle_operand(cmd.Op2, 0 ); if ( feature & CF_CHG3) handle_operand(cmd.Op3, 0 ); if ( flow) ua_add_cref(0, cmd.ea + cmd.size, fl_F ); return 1; }
int emu(void) { uint32 Feature = cmd.get_canon_feature(); flow = ((Feature & CF_STOP) == 0); // you may emulate selected instructions with a greater care: switch ( cmd.itype ) { case I51_mov: if ( cmd.Op1.type == o_mem && cmd.Op1.addr == 0x81 ) // mov SP, #num { if ( cmd.Op2.type == o_imm && !isDefArg(uFlag,1) ) set_offset(cmd.ea,1,intmem); // convert it to an offset } break; case I51_trap: ua_add_cref(0, 0x7B, fl_CN); break; case I51_pop: add_stkpnt(1); break; case I51_push: add_stkpnt(-1); break; } if ( Feature & CF_USE1 ) handle_operand(cmd.Op1, 1); if ( Feature & CF_USE2 ) handle_operand(cmd.Op2, 1); if ( Feature & CF_USE3 ) handle_operand(cmd.Op3, 1); if ( Feature & CF_JUMP ) QueueMark(Q_jumps,cmd.ea); if ( Feature & CF_CHG1 ) handle_operand(cmd.Op1, 0); if ( Feature & CF_CHG2 ) handle_operand(cmd.Op2, 0); if ( Feature & CF_CHG3 ) handle_operand(cmd.Op3, 0); // if the execution flow is not stopped here, then create // a xref to the next instruction. // Thus we plan to analyze the next instruction. if ( flow ) ua_add_cref(0,cmd.ea+cmd.size,fl_F); return 1; // actually the return value is unimportant, but let's it be so }
// Emulate an instruction. int emu(void) { uint32 feature = cmd.get_canon_feature(); flow = ((feature & CF_STOP) == 0); if ( cmd.Op1.type != o_void) handle_operand(cmd.Op1, (feature & CF_CHG1) != 0 ); if ( cmd.Op2.type != o_void) handle_operand(cmd.Op2, (feature & CF_CHG2) != 0 ); if ( cmd.Op3.type != o_void) handle_operand(cmd.Op3, (feature & CF_CHG3) != 0 ); if ( flow ) ua_add_cref(0, cmd.ea + cmd.size, fl_F); // Following code will update the current value of the two virtual // segment registers: RW (register window) and RP (register page). bool rw_has_changed = false; bool rp_has_changed = false; switch ( cmd.itype ) { case st9_srp: { sel_t val = cmd.Op1.value; if ( val % 2 ) val--; // even reduced splitSRarea1(cmd.ea, rRW, val | (val << 8), SR_auto); } rw_has_changed = true; break; case st9_srp0: { sel_t RW = getSR(cmd.ea, rRW); splitSRarea1(cmd.ea, rRW, cmd.Op1.value | (RW & 0xFF00), SR_auto); } rw_has_changed = true; break; case st9_srp1: { sel_t RW = getSR(cmd.ea, rRW); splitSRarea1(cmd.ea, rRW, (cmd.Op1.value << 8) | (RW & 0x00FF), SR_auto); } rw_has_changed = true; break; case st9_spp: splitSRarea1(cmd.ea, rRP, cmd.Op1.value, SR_auto); rp_has_changed = true; break; } // If RW / RP registers have changed, print a comment which explains the new mapping of // the general registers. if ( rw_has_changed && !has_cmt(uFlag) ) { char buf[MAXSTR]; sel_t RW = getSR(cmd.ea, rRW); int low = RW & 0x00FF; int high = (RW & 0xFF00) >> 8; low *= 8; high *= 8; const char *fmt = "r0 -> R%d, r1 -> R%d, r2 -> R%d, r3 -> R%d, r4 -> R%d, r5 -> R%d, r6 -> R%d, r7 -> R%d,\n" "r8 -> R%d, r9 -> R%d, r10 -> R%d, r11 -> R%d, r12 -> R%d, r13 -> R%d, r14 -> R%d, r15 -> R%d"; qsnprintf(buf, sizeof buf, fmt, 0 + low, 1 + low, 2 + low, 3 + low, 4 + low, 5 + low, 6 + low, 7 + low, 8 + high, 9 + high, 10 + high, 11 + high, 12 + high, 13 + high, 14 + high, 15 + high ); set_cmt(cmd.ea, buf, false); }
//---------------------------------------------------------------------- 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); } }