def __init__(self, cpu_type=M68K_CPU_TYPE_68000, ram_size_kib=1024, use_labels=True, raise_on_main_run=True): # setup musashi components self.cpu_type = cpu_type self.cpu = emu.CPU(cpu_type) self.mem = emu.Memory(ram_size_kib) self.traps = emu.Traps() self.raise_on_main_run = raise_on_main_run # internal state if use_labels: self.label_mgr = LabelManager() else: self.label_mgr = None self.ram_total = ram_size_kib * 1024 self.ram_bytes = self.ram_total - self.ram_begin self.error_reporter = ErrorReporter(self) self.run_states = [] self.mem0 = 0 self.mem4 = 0 self.shutdown_func = None self.instr_hook = None self.cycles_per_run = 1000 self.bail_out = False # call init self._alloc_trap() self._init_base_mem() self._setup_handler()
def __init__(self, cpu_type=M68K_CPU_TYPE_68000, ram_size_kib=1024, use_labels=True, raise_on_main_run=True, cycles_per_run=1000, max_cycles=0, cpu_name=None): if cpu_name is None: cpu_name = self._get_cpu_name(cpu_type) # setup musashi components self.cpu_type = cpu_type self.cpu_name = cpu_name self.cpu = emu.CPU(cpu_type) self.mem = emu.Memory(ram_size_kib) self.traps = emu.Traps() # internal state if use_labels: self.label_mgr = LabelManager() else: self.label_mgr = None self.raise_on_main_run = raise_on_main_run self.ram_total = ram_size_kib * 1024 self.ram_bytes = self.ram_total - self.ram_begin self.error_reporter = ErrorReporter(self) self.run_states = [] self.instr_hook = None self.cycles_per_run = cycles_per_run self.max_cycles = max_cycles self.bail_out = False # call init self._setup_handler() self._setup_quick_traps() self._init_cpu() self._init_base_mem()
def musashi_traps_trigger_test(): traps = emu.Traps() a = [] def my_func(opcode, pc): a.append(opcode) a.append(pc) tid = traps.setup(my_func) assert tid >= 0 traps.trigger(tid, 23) assert a == [tid, 23] traps.free(tid)
def musashi_traps_raise_test(): traps = emu.Traps() a = [] b = [] def exc_func(opcode, pc): a.append(opcode) a.append(pc) b.append(sys.exc_info()) traps.set_exc_func(exc_func) def my_func(opcode, pc): raise ValueError("bla") tid = traps.setup(my_func) assert tid >= 0 traps.trigger(tid, 23) assert a == [tid, 23] assert b[0][0] == ValueError traps.free(tid)
def main(): # retrieve vamos home and data dir home_dir = os.path.dirname(amitools.__file__) data_dir = os.path.join(home_dir, "data") # --- args -- parser = argparse.ArgumentParser() parser.add_argument('bin', help="AmigaOS binary to run") parser.add_argument('args', nargs='*', help="AmigaOS binary arguments") # config options parser.add_argument('-c', '--config-file', action='store', default=None, help="vamos config file") parser.add_argument('-S', '--skip-default-configs', action='store_true', default=False, help="do not read ~/.vamosrc or ./vamosrc") # logging config parser.add_argument('-l', '--logging', action='store', default=None, help="logging settings: <chan>:<level>,*:<level>,...") parser.add_argument('-v', '--verbose', action='store_true', default=None, help="be more verbos") parser.add_argument('-q', '--quiet', action='store_true', default=None, help="do not output any logging") parser.add_argument('-b', '--benchmark', action='store_true', default=None, help="enable benchmarking") parser.add_argument('-L', '--log-file', action='store', default=None, help="write all log messages to a file") parser.add_argument('--no-ts', action='store_true', default=False, help="do not log with timestamp") # low-level tracing parser.add_argument('-I', '--instr-trace', action='store_true', default=None, help="enable instruction trace") parser.add_argument('-t', '--memory-trace', action='store_true', default=None, help="enable memory tracing (slower)") parser.add_argument('-T', '--internal-memory-trace', action='store_true', default=None, help="enable internal memory tracing (slow)") parser.add_argument('-r', '--reg-dump', action='store_true', default=None, help="add register dump to instruction trace") # cpu emu parser.add_argument('-C', '--cpu', action='store', default=None, help="Set type of CPU to emulate (68000 or 68020)") parser.add_argument('-y', '--max-cycles', action='store', type=int, default=None, help="maximum number of cycles to execute") parser.add_argument('-B', '--cycles-per-block', action='store', type=int, default=None, help="cycles per block") # system parser.add_argument('-m', '--ram-size', action='store', default=None, type=int, help="set RAM size in KiB") parser.add_argument('-s', '--stack-size', action='store', default=None, help="set stack size in KiB") parser.add_argument('-H', '--hw-access', action='store', default=None, help="What to do on direct HW access? (emu,ignore,abort,disable)") parser.add_argument('-x', '--shell',action='store_true', default=None, help="run an AmigaOs shell instead of a binary") # dirs parser.add_argument('-D', '--data-dir', action='store', default=None, help="set vamos data directory (default: %s)" % data_dir) # lib config parser.add_argument('-O', '--lib-options', action='append', default=None, help="set lib options: <lib>+<key>=<value>,...") # path config parser.add_argument('-a', '--assign', action='append', default=None, help="add AmigaOS assign: name:[+]/sys/path[,/more/path]") parser.add_argument('-V', '--volume', action='append', default=None, help="define AmigaOS volume: name:/abs/sys/path") parser.add_argument('-A', '--auto-assign', action='store', default=None, help="define auto assign ami path, e.g. vol:/ami/path") parser.add_argument('-p', '--path', action='append', default=None, help="define command search ami path, e.g. c:") parser.add_argument('-d', '--cwd', action='store', default=None, help="set current working directory") # arg handling parser.add_argument('-P', '--pure-ami-paths', action='store_true', default=None, help="do not allow sys paths for binary") parser.add_argument('-R', '--raw-arg', action='store_true', default=None, help="pass a single unmodified argument string") args = parser.parse_args() # --- init config --- cfg = VamosConfig(extra_file=args.config_file, skip_defaults=args.skip_default_configs, args=args, def_data_dir=data_dir) # --- init logging --- if not log_setup(cfg.logging, cfg.verbose, cfg.quiet, cfg.log_file, args.no_ts): log_help() sys.exit(1) cfg.log() # ----- vamos! --------------------------------------------------------------- # setup CPU if cfg.cpu in ('68000', '000', '00'): cpu_type = m68k.M68K_CPU_TYPE_68000 cfg.cpu = '68000' elif cfg.cpu in ('68020', '020', '20'): cpu_type = m68k.M68K_CPU_TYPE_68020 cfg.cpu = '68020' elif cfg.cpu in ('68030', '030', '30'): # fake 030 CPU only to set AttnFlags accordingly cpu_type = m68k.M68K_CPU_TYPE_68020 cfg.cpu = '68030' log_main.info("fake 68030 CPU selected") else: log_main.error("Invalid CPU type: %s" % cfg.cpu) sys.exit(1) log_main.info("setting up CPU: %s = %d" % (cfg.cpu, cpu_type)) cpu = emu.CPU(cpu_type) # setup memory if cfg.hw_access != "disable": max_mem = 0xbf0000 / 1024 if cfg.ram_size >= max_mem: log_main.error("too much RAM requested. max allowed KiB: %d", max_mem) sys.exit(1) mem = emu.Memory(cfg.ram_size) log_main.info("setting up main memory with %s KiB RAM: top=%06x" % (cfg.ram_size, cfg.ram_size * 1024)) # setup traps traps = emu.Traps() # setup current working dir cwd = cfg.cwd if cwd is None: cwd = 'root:' + os.getcwd() # --- binary and arg_str --- # a single Amiga-like raw arg was passed if args.raw_arg: # check args if len(args.args) > 0: log_main.error("raw arg only allows a single argument!") sys.exit(1) # parse raw arg cl = CommandLine() res = cl.parse_line(args.bin) if res != cl.LINE_OK: log_main.error("raw arg is invalid! (error %d)", res) sys.exit(1) binary = cl.get_cmd() arg_str = cl.get_arg_str() else: # setup binary binary = args.bin if not cfg.pure_ami_paths: # if path exists on host system then make a root path if os.path.exists(binary): binary = "root:" + os.path.abspath(binary) # combine remaining args to arg_str arg_str = sys_args_to_ami_arg_str(args.args) # where does the process return? exit_addr = VamosRun.exit_addr # summary log_main.info("bin='%s', arg_str='%s', cwd='%s', shell='%s', stack=%d, exit_addr=%08x", binary, arg_str[:-1], cwd, args.shell, cfg.stack_size, exit_addr) stack_size=cfg.stack_size * 1024 # combine to vamos instance vamos = Vamos(mem, cpu, traps, cfg) vamos.init(binary, arg_str, stack_size, args.shell, cwd, exit_addr) # ------ main loop ------ # init cpu and initial registers run = VamosRun(vamos, args.benchmark, args.shell) run.init() # main loop exit_code = run.run(cfg.cycles_per_block, cfg.max_cycles) # shutdown vamos vamos.cleanup() # exit log_main.info("vamos is exiting") return exit_code
def main(): # retrieve vamos home and data dir home_dir = os.path.dirname(amitools.__file__) data_dir = os.path.join(home_dir, "data") # --- args -- parser = argparse.ArgumentParser() parser.add_argument('bin', help="AmigaOS binary to run") parser.add_argument('args', nargs='*', help="AmigaOS binary arguments") # config options parser.add_argument('-c', '--config-file', action='store', default=None, help="vamos config file") parser.add_argument('-S', '--skip-default-configs', action='store_true', default=False, help="do not read ~/.vamosrc or ./vamosrc") # logging config parser.add_argument('-l', '--logging', action='store', default=None, help="logging settings: <chan>:<level>,*:<level>,...") parser.add_argument('-v', '--verbose', action='store_true', default=None, help="be more verbos") parser.add_argument('-q', '--quiet', action='store_true', default=None, help="do not output any logging") parser.add_argument('-b', '--benchmark', action='store_true', default=None, help="enable benchmarking") parser.add_argument('-L', '--log-file', action='store', default=None, help="write all log messages to a file") # low-level tracing parser.add_argument('-I', '--instr-trace', action='store_true', default=None, help="enable instruction trace") parser.add_argument('-t', '--memory-trace', action='store_true', default=None, help="enable memory tracing (slower)") parser.add_argument('-T', '--internal-memory-trace', action='store_true', default=None, help="enable internal memory tracing (slow)") parser.add_argument('-r', '--reg-dump', action='store_true', default=None, help="add register dump to instruction trace") # cpu emu parser.add_argument('-C', '--cpu', action='store', default=None, help="Set type of CPU to emulate (68000 or 68020)") parser.add_argument('-y', '--max-cycles', action='store', type=int, default=None, help="maximum number of cycles to execute") parser.add_argument('-B', '--cycles-per-block', action='store', type=int, default=None, help="cycles per block") # system parser.add_argument('-m', '--ram-size', action='store', default=None, type=int, help="set RAM size in KiB") parser.add_argument('-s', '--stack-size', action='store', default=None, help="set stack size in KiB") parser.add_argument( '-H', '--hw-access', action='store', default=None, help="What to do on direct HW access? (emu,ignore,abort,disable)") parser.add_argument('-x', '--shell', action='store_true', default=None, help="run an AmigaOs shell instead of a binary") # dirs parser.add_argument('-D', '--data-dir', action='store', default=None, help="set vamos data directory (default: %s)" % data_dir) # lib config parser.add_argument('-O', '--lib-options', action='append', default=None, help="set lib options: <lib>:<key>=<value>,...") # path config parser.add_argument( '-a', '--assign', action='append', default=None, help="add AmigaOS assign: name:[+]/sys/path[,/more/path]") parser.add_argument('-V', '--volume', action='append', default=None, help="define AmigaOS volume: name:/abs/sys/path") parser.add_argument('-A', '--auto-assign', action='store', default=None, help="define auto assign ami path, e.g. vol:/ami/path") parser.add_argument('-p', '--path', action='append', default=None, help="define command search ami path, e.g. c:") parser.add_argument('-d', '--cwd', action='store', default=None, help="set current working directory") args = parser.parse_args() # --- init config --- cfg = VamosConfig(extra_file=args.config_file, skip_defaults=args.skip_default_configs, args=args, def_data_dir=data_dir) # --- init logging --- if not log_setup(cfg.logging, cfg.verbose, cfg.quiet, cfg.log_file): log_help() sys.exit(1) cfg.log() # ----- vamos! --------------------------------------------------------------- # setup CPU if cfg.cpu in ('68000', '000', '00'): cpu_type = m68k.M68K_CPU_TYPE_68000 elif cfg.cpu in ('68020', '020', '20'): cpu_type = m68k.M68K_CPU_TYPE_68020 else: log_main.error("Invalid CPU type: %s" % cfg.cpu) sys.exit(1) log_main.info("setting up CPU: %s = %d" % (cfg.cpu, cpu_type)) cpu = emu.CPU(cpu_type) # setup memory if cfg.hw_access != "disable": max_mem = 0xbf0000 / 1024 if cfg.ram_size >= max_mem: log_main.error("too much RAM requested. max allowed KiB: %d", max_mem) sys.exit(1) mem = emu.Memory(cfg.ram_size) log_main.info("setting up main memory with %s KiB RAM: top=%06x" % (cfg.ram_size, cfg.ram_size * 1024)) # setup traps traps = emu.Traps() # combine to vamos instance vamos = Vamos(mem, cpu, traps, cfg) vamos.init() # --- create main process --- # setup current working dir cwd = args.cwd if cwd is None: cwd = 'root:' + os.getcwd() proc = Process(vamos, args.bin, args.args, stack_size=cfg.stack_size * 1024, shell=args.shell, cwd=cwd) if not proc.ok: sys.exit(1) vamos.set_main_process(proc) # ------ main loop ------ # init cpu and initial registers run = VamosRun(vamos, args.benchmark, args.shell) run.init() # main loop exit_code = run.run(cfg.cycles_per_block, cfg.max_cycles) # free process proc.free() # shutdown vamos vamos.cleanup() # exit log_main.info("vamos is exiting") return exit_code