def _run_exit_handler(self, opcode, pc): """regular end of a machine run""" sp = self.cpu.r_reg(REG_A7) callee_pc = self.mem.r32(sp) log_machine.debug("run exit: opcode=%04x, pc=%06x, sp=%06x, callee=%06x", opcode, pc, sp, callee_pc) run_state = self.get_cur_run_state() run_state.done = True self.cpu.end()
def _trap_exc_handler(self, op, pc): """triggerd if Python code in a trap raised a Python exception""" log_machine.debug("trap exception handler: op=%04x pc=%06x", op, pc) # get pending exception exc_info = sys.exc_info() if exc_info: error = exc_info[1] else: error = RuntimeError("No exception?!") self._terminate_run(error)
def _trap_exc_handler(self, op, pc): """triggerd if Python code in a trap raised a Python exception""" log_machine.debug("trap exception handler: op=%04x pc=%06x", op, pc) # get pending exception exc_info = sys.exc_info() if exc_info: error = exc_info[1] else: error = RuntimeError("No exception?!") self._terminate_run(error)
def _trap_exc_handler(self, op, pc): log_machine.debug("trap exception handler: op=%04x pc=%06x", op, pc) run_state = self.get_cur_run_state() # get pending exception exc_info = sys.exc_info() if exc_info: run_state.error = exc_info[1] run_state.done = True # end time slice of cpu self.cpu.end() # report error self.error_reporter.report_error(run_state.error)
def _hw_exc_handler(self, opcode, pc): """an m68k Hardware Exception was triggered""" # get current pc sp = self.cpu.r_reg(REG_A7) callee_pc = self.mem.r32(sp) log_machine.debug("hw exception: pc=%06x sp=%06x callee=%06x", pc, sp, callee_pc) # m68k Exception Triggered sr = self.mem.r16(sp) pc = self.mem.r32(sp + 2) txt = "m68k Exception: sr=%04x" % sr error = InvalidCPUStateError(pc, txt) self._terminate_run(error)
def _invalid_mem_access(self, mode, width, addr): log_machine.debug("invalid memory access: mode=%s width=%d addr=%06x", mode, width, addr) run_state = self.get_cur_run_state() # already a pending error? if run_state.error: return run_state.error = InvalidMemoryAccessError(mode, width, addr) run_state.done = True # end time slice of cpu self.cpu.end() # report error self.error_reporter.report_error(run_state.error)
def _hw_exc_handler(self, opcode, pc): """an m68k Hardware Exception was triggered""" # get current pc sp = self.cpu.r_reg(REG_A7) callee_pc = self.mem.r32(sp) log_machine.debug("hw exception: pc=%06x sp=%06x callee=%06x", pc, sp, callee_pc) # m68k Exception Triggered sr = self.mem.r16(sp) pc = self.mem.r32(sp + 2) txt = "m68k Exception: sr=%04x" % sr error = InvalidCPUStateError(pc, txt) self._terminate_run(error)
def _run_exit_handler(self, opcode, pc): """regular end of a machine run""" sp = self.cpu.r_reg(REG_A7) callee_pc = self.mem.r32(sp) log_machine.debug( "run exit: opcode=%04x, pc=%06x, sp=%06x, callee=%06x", opcode, pc, sp, callee_pc, ) run_state = self.get_cur_run_state() run_state.done = True self.cpu.end()
def run(self, pc, sp=None, set_regs=None, get_regs=None, max_cycles=0, cycles_per_run=0, name=None): mem = self.mem cpu = self.cpu if name is None: name = "default" # current run nesting level nesting = len(self.run_states) # return address of a run is always run_end_addr ret_addr = self.run_exit_addr # get cpu context if nesting > 0: cpu_ctx = cpu.get_cpu_context() else: cpu_ctx = None # share stack with last run if not specified if sp is None: if nesting == 0: raise ValueError("stack must be specified!") else: sp = cpu.r_reg(REG_A7) sp -= 4 log_machine.info("run#%d(%s): begin pc=%06x, sp=%06x, ret_addr=%06x", nesting, name, pc, sp, ret_addr) # store return address on stack mem.w32(sp, ret_addr) # setup pc, sp cpu.w_pc(pc) cpu.w_reg(REG_A7, sp) # create run state for this run and push it run_state = RunState(name, pc, sp, ret_addr) self.run_states.append(run_state) # setup regs if set_regs: set_regs_txt = self._print_regs(set_regs) log_machine.info("run#%d: set_regs=%s", nesting, set_regs_txt) for reg in set_regs: val = set_regs[reg] cpu.w_reg(reg, val) # get cycle params either from this call or from default if not cycles_per_run: cycles_per_run = self.cycles_per_run if not max_cycles: max_cycles = self.max_cycles # main execution loop of run total_cycles = 0 start_time = time.clock() try: while not run_state.done: log_machine.debug("+ cpu.execute") total_cycles += cpu.execute(cycles_per_run) log_machine.debug("- cpu.execute") # end after enough cycles if max_cycles > 0 and total_cycles >= max_cycles: break except Exception as e: self.error_reporter.report_error(e) end_time = time.clock() # retrieve regs if get_regs: regs = {} for reg in get_regs: val = cpu.r_reg(reg) regs[reg] = val regs_text = self._print_regs(regs) log_machine.info("run #%d: get_regs=%s", nesting, regs_text) run_state.regs = regs # restore cpu context if cpu_ctx: cpu.set_cpu_context(cpu_ctx) # update run state run_state.time_delta = end_time - start_time run_state.cycles = total_cycles # pop self.run_states.pop() log_machine.info("run #%d(%s): end. state=%s", nesting, name, run_state) # if run_state has error and we are not a top-level raise an error # so the running trap code gets aborted and propagates the abort if run_state.error: if nesting > 0 or self.raise_on_main_run: pc = cpu.r_pc() raise NestedCPURunError(pc, run_state.error) return run_state
def _invalid_mem_access(self, mode, width, addr): """triggered by invalid memory access""" log_machine.debug("invalid memory access: mode=%s width=%d addr=%06x", mode, width, addr) error = InvalidMemoryAccessError(mode, width, addr) self._terminate_run(error)
def _shutdown_trap(self, op, pc): log_machine.debug("trigger shutdown func") self.shutdown_func()
def run(self, pc, sp=None, set_regs=None, get_regs=None, max_cycles=0, cycles_per_run=0, name=None): mem = self.mem cpu = self.cpu if name is None: name = "default" # current run nesting level nesting = len(self.run_states) # return address of a run is always run_end_addr ret_addr = self.run_exit_addr # get cpu context if nesting > 0: cpu_ctx = cpu.get_cpu_context() else: cpu_ctx = None # share stack with last run if not specified if sp is None: if nesting == 0: raise ValueError("stack must be specified!") else: sp = cpu.r_reg(REG_A7) sp -= 4 log_machine.info("run#%d(%s): begin pc=%06x, sp=%06x, ret_addr=%06x", nesting, name, pc, sp, ret_addr) # store return address on stack mem.w32(sp, ret_addr) # setup pc, sp cpu.w_pc(pc) cpu.w_reg(REG_A7, sp) # create run state for this run and push it run_state = RunState(name, pc, sp, ret_addr) self.run_states.append(run_state) # setup regs if set_regs: set_regs_txt = self._print_regs(set_regs) log_machine.info("run#%d: set_regs=%s", nesting, set_regs_txt) for reg in set_regs: val = set_regs[reg] cpu.w_reg(reg, val) # get cycle params either from this call or from default if not cycles_per_run: cycles_per_run = self.cycles_per_run if not max_cycles: max_cycles = self.max_cycles # main execution loop of run total_cycles = 0 start_time = time.clock() try: while not run_state.done: log_machine.debug("+ cpu.execute") total_cycles += cpu.execute(cycles_per_run) log_machine.debug("- cpu.execute") # end after enough cycles if max_cycles > 0 and total_cycles >= max_cycles: break except Exception as e: self.error_reporter.report_error(e) end_time = time.clock() # retrieve regs if get_regs: regs = {} for reg in get_regs: val = cpu.r_reg(reg) regs[reg] = val regs_text = self._print_regs(regs) log_machine.info("run #%d: get_regs=%s", nesting, regs_text) run_state.regs = regs # restore cpu context if cpu_ctx: cpu.set_cpu_context(cpu_ctx) # update run state run_state.time_delta = end_time - start_time run_state.cycles = total_cycles # pop self.run_states.pop() log_machine.info("run #%d(%s): end. state=%s", nesting, name, run_state) # if run_state has error and we are not a top-level raise an error # so the running trap code gets aborted and propagates the abort if run_state.error: if nesting > 0 or self.raise_on_main_run: pc = cpu.r_pc() raise NestedCPURunError(pc, run_state.error) return run_state
def _invalid_mem_access(self, mode, width, addr): """triggered by invalid memory access""" log_machine.debug("invalid memory access: mode=%s width=%d addr=%06x", mode, width, addr) error = InvalidMemoryAccessError(mode, width, addr) self._terminate_run(error)