def close_lib(self, addr, ctx): # get lib object if addr not in self.open_libs_addr: self.lib_log("close_lib","No library found at address %06x" % (addr)) return None lib = self.open_libs_addr[addr] # native lib handling if lib.is_native: tr = Trampoline(ctx,"close_lib[%s]" % lib.name) self._close_native_lib(lib, ctx, tr) if lib.ref_cnt == 0: self._free_native_lib(lib, ctx, tr) elif lib.ref_cnt < 0: raise VamosInternalError("CloseLib: invalid ref count?!") tr.final_rts() tr.done() # own lib handling else: # decrement usage lib.dec_usage() # not used any more if lib.ref_cnt == 0: # finally close lib self._unregister_open_lib(lib) self._free_vamos_lib(lib, ctx) elif lib.ref_cnt < 0: raise VamosInternalError("CloseLib: invalid ref count?!") return lib
def __init__(self, width, height): Level.__init__(self, width, height) ##initialize blocks## boxtop = Terrain(20, -19, 40, 2, 0, 0, 100, self, 0.5) boxleft = Terrain(-1, -5, 2, 30, 0, 0, 100, self, 0.5) boxbottom = Terrain(20, 9, 40, 2, 0, 0, 100, self, 0.5) boxright = Terrain(41, -5, 2, 30, 0, 0, 100, self, 0.5) barrbottom = Terrain(15, -6, 6, 1, 0, 0, 100, self, .5) barrright = Terrain(18.5, -11, 1, 10, 0, 0, 100, self, .5) goal = Goal(38, -15.5, 1, 5, 0, 0, 100, self, 0.5) tramp1 = Trampoline(7, 7, 6, 1, 0, 0, 100, self, .5) tramp2 = Trampoline(36, 7, 6, 1, 0, 0, 100, self, .5) tramp3 = Trampoline(32, -8, 6, 1, 0, 0, 100, self, .5) tramp4 = Trampoline(36, -23, 6, 1, 0, 0, 100, self, .5) p = Player(2, 5, 1, 2, 0, 0, 1, self, 0.5) g = GoalBlock(16.5, -7, 2, 2, 0, 0, 2, self, 0.5) self.add_elem(p) self.add_elem(barrbottom) self.add_elem(barrright) self.add_elem(tramp1) self.add_elem(tramp2) self.add_elem(tramp3) self.add_elem(tramp4) self.add_elem(g) self.add_elem(boxtop) self.add_elem(boxright) self.add_elem(boxbottom) self.add_elem(boxleft) self.add_elem(goal)
def __init__(self, width, height): Level.__init__(self, width, height) ##initialize blocks## boxtop = Terrain(20, -19, 40, 2, 0, 0,100, self, 0.5) boxleft= Terrain(-1,-5,2,30,0,0,100,self,0.5) boxbottom= Terrain(27.0,9.0,54.0,2.0,0.0,0.0,100,self,0.5) boxright= Terrain(55,-5,2,30,0,0,100,self,0.5) goal= Goal(53,5,1,5,0,0,100,self,0.5) b = Block(2, 2, 4, 1, 0, 0, 1, self, 0.5) c = Player(7, 5, 1, 2, 0, 0, 1, self, 0.5) d = Block(4, 2, 4, 1, 0, 5, 2, self, 0.5) a = GoalBlock(4, 5, 2, 2, 0, 5, 2, self, 0.5) m = Trampoline(30, -4, 2, 1, 0, 0, 1, self, 0.5) e = Spike(30.0, 7.5, 41.0, 1.0, 0.0, 0.0, 100, self, 0.1) f = Spike(29.0, 6.5, 1.0, 1.0, 0.0, 0.0, 100, self, 0.1) self.add_elem(c) self.add_elem(m) self.add_elem(b) self.add_elem(a) self.add_elem(d) self.add_elem(e) self.add_elem(f) self.add_elem(boxtop) self.add_elem(boxright) self.add_elem(boxbottom) self.add_elem(boxleft) self.add_elem(goal)
def close_lib(self, addr, ctx): # get lib object if addr not in self.open_libs_addr: self.lib_log("close_lib","No library found at address %06x" % (addr)) return None lib = self.open_libs_addr[addr] lib.open_base_addr = addr self.lib_log("close_lib","Closing %s at address %06x" % (lib.name,addr)) # native lib handling if lib.is_native: tr = Trampoline(ctx,"close_lib[%s]" % lib.name) self._close_native_lib(lib, addr, ctx, tr) if lib.ref_cnt == 0: pass # THOR: Do not release the library memory. Problem is that # the SAS/C go leaves references to strings to its library # segment pending in the QUAD: file, which then become # invalid if the library is removed. In reality, we should # only flush libs if we are low on memory. # self._free_native_lib(lib, ctx, tr) elif lib.ref_cnt < 0: raise VamosInternalError("CloseLib: invalid ref count?!") tr.final_rts() tr.done() # own lib handling else: # decrement usage lib.dec_usage() # not used any more if lib.ref_cnt == 0: # finally close lib pass #self._unregister_open_lib(lib,None) #self._free_vamos_lib(lib, ctx) elif lib.ref_cnt < 0: raise VamosInternalError("CloseLib: invalid ref count?!") return lib
def _close_native_lib(self, lib, lib_base, ctx): self.lib_log("close_lib","closing native lib: '%s' ref_cnt: %d" % (lib.name, lib.ref_cnt)) tr = Trampoline(ctx,"close_lib[%s]" % lib.name) self._close_native_lib_int(lib, lib_base, ctx, tr) if lib.ref_cnt == 0: # lib has no users and can be expunged/removed expunge_mode = lib.config.expunge if expunge_mode == 'last_close': self.lib_log("close_lib","expunging native lib: '%s'" % lib.name) # do it now self._free_native_lib(lib, ctx, tr) elif lib.ref_cnt < 0: raise VamosInternalError("CloseLib: invalid ref count?!") tr.final_rts() tr.done()
def _load_and_open_native_lib(self, name, sane_name, lib_cfg, ctx): """try to load and open native lib return new lib instance or None if lib was not found""" # create empty lib lib = AmigaLibrary(sane_name, LibraryStruct, lib_cfg) # determine file name from open_name, i.e. prepend LIBS: if no path is found load_name = self._get_load_lib_name(name) self.lib_log("load_lib", "trying to load amiga lib: '%s'" % load_name, level=logging.INFO) # pick current dir lock if available # this allows to resolve relative paths given in load_name cur_dir_lock = None proc = ctx.process if proc is not None: cur_dir_lock = proc.cwd_lock # map ami path of lib to sys_path sys_path = ctx.path_mgr.ami_to_sys_path(cur_dir_lock, load_name, searchMulti=True) # is native lib available in file system? if sys_path and os.path.exists(sys_path): self.lib_log("load_lib", "found amiga lib: '%s'" % load_name) # setup trampoline tr = Trampoline(ctx, "create_lib[%s]" % sane_name) self._create_native_lib(lib, sys_path, ctx, tr) self._open_native_lib_int(lib, ctx, tr) tr.final_rts() tr.done() # do we have an optional fd file for this lib? lib.fd = self._load_fd(sane_name) self._register_lib_name(lib) return lib else: return None
def close_lib(self, addr, ctx): # get lib object if addr not in self.open_libs_addr: self.lib_log("close_lib", "No library found at address %06x" % (addr)) return None lib = self.open_libs_addr[addr] lib.open_base_addr = addr self.lib_log("close_lib", "Closing %s at address %06x" % (lib.name, addr)) # native lib handling if lib.is_native: tr = Trampoline(ctx, "close_lib[%s]" % lib.name) self._close_native_lib(lib, addr, ctx, tr) if lib.ref_cnt == 0: pass # THOR: Do not release the library memory. Problem is that # the SAS/C go leaves references to strings to its library # segment pending in the QUAD: file, which then become # invalid if the library is removed. In reality, we should # only flush libs if we are low on memory. # self._free_native_lib(lib, ctx, tr) elif lib.ref_cnt < 0: raise VamosInternalError("CloseLib: invalid ref count?!") tr.final_rts() tr.done() # own lib handling else: # decrement usage lib.dec_usage() # not used any more if lib.ref_cnt == 0: # finally close lib self._unregister_open_lib(lib, None) self._free_vamos_lib(lib, ctx) elif lib.ref_cnt < 0: raise VamosInternalError("CloseLib: invalid ref count?!") return lib
def open_lib(self, name, ver, ctx): """open a new library in memory return new AmigaLibrary instance that is setup or None if lib was not found Note: may prepare a trampoline to finish operation! """ # sanitize lib name sane_name = self._get_sane_lib_name(name) # is lib already opened? if sane_name in self.open_libs_name: self.lib_log("open_lib","opening already open lib: %s" % sane_name) lib = self.open_libs_name[sane_name] if lib.is_native: # call Open() tr = Trampoline(ctx,"open_lib[%s]" % sane_name) self._open_native_lib(lib, ctx, tr) tr.final_rts() tr.done() else: # handle usage count lib.inc_usage() # lib has to be openend else: # first check if its an internal vamos library if sane_name in self.vamos_libs: self.lib_log("open_lib","opening vamos lib: %s" % sane_name) lib = self.vamos_libs[sane_name] is_vamos_lib = True # otherwise create a new and empty AmigaLibrary else: self.lib_log("open_lib","create default lib: %s" % sane_name) lib_cfg = self.cfg.get_lib_config(sane_name) lib = AmigaLibrary(sane_name, LibraryDef, lib_cfg) is_vamos_lib = False # dump config of lib self._dump_lib_cfg(lib.config) # is lib mode = 'off' then reject open mode = lib.config.mode if mode == 'off': self.lib_log("open_lib","reject open: mode='off': %s" % sane_name, level=logging.WARN) return None # try to load an fd file for this lib lib.fd = self._load_fd(sane_name) # is native loading allowed? native_loaded = False native_allowed = mode in ('auto','amiga') if native_allowed: # now check if the library has a native counterpart # if yes then create memory layout with it load_name = self._get_load_lib_name(name) if ctx.seg_loader.can_load_seg(None,load_name,local_path=True): # setup trampoline tr = Trampoline(ctx,"create_lib[%s]" % sane_name) self._create_native_lib(lib, load_name, ctx, tr) self._open_native_lib(lib, ctx, tr) tr.final_rts() tr.done() native_loaded = True # no native lib available... # either its a vamos lib or we auto create one from an FD file if not native_loaded: # we need to have an FD file otherwise we can't create lib if lib.fd == None: self.lib_log("create_lib","can't create auto lib without FD file: %s" % sane_name, level=logging.ERROR) return None # if not 'auto' or 'vamos' then fail now if mode == 'amiga': self.lib_log("open_lib","can't open amiga lib: %s" % sane_name, level=logging.WARN) return None # create a (opt. fake/empty) vamos library self._create_vamos_lib(lib, ctx) self._register_open_lib(lib,None) lib.inc_usage() self.lib_log("open_lib","leaving open_lib(): %s -> %06x" % (lib,lib.addr_base_open), level=logging.DEBUG) return lib
def run_command(self,start_pc,argsptr,arglen,stacksize): newstack = self.alloc.alloc_memory("shell command stack",stacksize) newstackbase = newstack.addr newstacktop = newstackbase + stacksize oldstackbase = self.process.this_task.access.r_s("pr_Task.tc_SPLower"); oldstacktop = self.process.this_task.access.r_s("pr_Task.tc_SPUpper"); old_stackptr = self.cpu.r_reg(REG_A7) # addr of sys call return # put stack size on top of stack self.mem.w32(newstacktop - 4,stacksize) # activate new stack new_stackptr = newstacktop - 8 self.process.this_task.access.w_s("pr_Task.tc_SPLower",newstackbase) self.process.this_task.access.w_s("pr_Task.tc_SPUpper",newstacktop) # NOTE: the Manx fexec and BPCL mess is not (yet) setup here. # setup trampoline to enter sub process tr = Trampoline(self, "RunCommand") # reserve a long for old stack old_stack_off = tr.dc_l(0) # code starts tr.save_all_but_d0() # new proc registers: d0=arg_len a0=arg_cptr tr.set_dx_l(0, arglen) tr.set_ax_l(0, argsptr) # d2=stack_size. this value is also in 4(sp) (see Process.init_stack), but # various C programs rely on it being present (1.3-3.1 at least have it). tr.set_dx_l(2, stacksize) # to track old dos values odg = self.mem_map.get_old_dos_guard_base() tr.set_ax_l(2, odg) tr.set_ax_l(5, odg) tr.set_ax_l(6, odg) # save old stack and set new stack tr.write_ax_l(7, old_stack_off, True) # write to data offset (dc.l above) tr.set_ax_l(7, new_stackptr) # call code! (jmp - return value is on stack) tr.jmp(start_pc) # restore stack (set a label to return from new stack - see below) return_off = tr.get_code_offset() tr.read_ax_l(7, old_stack_off, True) # read from data offset (dc.l above) # restore regs tr.restore_all_but_d0() # keep the old input file handle input_fh = self.process.get_input() # trap to clean up sub process resources def trap_stop_run_command(): ret_code = self.cpu.r_reg(REG_D0) log_proc.info("return from RunCommand: ret_code=%d", ret_code) self.cpu.w_reg(REG_A7,old_stackptr) self.process.this_task.access.w_s("pr_Task.tc_SPLower",oldstackbase) self.process.this_task.access.w_s("pr_Task.tc_SPUpper",oldstacktop) self.alloc.free_memory(newstack) input_fh.setbuf("") # The return code remains in d0 as is tr.final_rts(trap_stop_run_command) # realize trampoline in memory (data+code) tr.done() # get label addr -> set as return value of new stack return_addr = tr.get_code_addr(return_off) log_proc.debug("new_stack=%06x return_addr=%06x", new_stackptr, return_addr) # place return address for new process self.mem.w32(new_stackptr, return_addr)
def start_sub_process(self, proc): log_proc.info("start sub process: %s", proc) self.proc_list.append(proc) self._set_this_task(proc) # setup trampoline to enter sub process tr = Trampoline(self, "SubProcJump") # reserve a long for old stack old_stack_off = tr.dc_l(0) # code starts tr.save_all_but_d0() # new proc registers: d0=arg_len a0=arg_cptr tr.set_dx_l(0, proc.arg_len) tr.set_ax_l(0, proc.arg_base) # d2=stack_size. this value is also in 4(sp) (see Process.init_stack), but # various C programs rely on it being present (1.3-3.1 at least have it). tr.set_dx_l(2, proc.stack_size) # to track old dos values odg = self.mem_map.get_old_dos_guard_base() tr.set_ax_l(2, odg) tr.set_ax_l(5, odg) tr.set_ax_l(6, odg) # save old stack and set new stack tr.write_ax_l(7, old_stack_off, True) # write to data offset (dc.l above) new_stack = proc.stack_initial tr.set_ax_l(7, new_stack) # call code! (jmp - return value is on stack) tr.jmp(proc.prog_start) # restore stack (set a label to return from new stack - see below) return_off = tr.get_code_offset() tr.read_ax_l(7, old_stack_off, True) # read from data offset (dc.l above) # restore regs tr.restore_all_but_d0() # trap to clean up sub process resources def trap_stop_sub_process(): self.stop_sub_process() tr.final_rts(trap_stop_sub_process) # realize trampoline in memory (data+code) tr.done() # get label addr -> set as return value of new stack return_addr = tr.get_code_addr(return_off) log_proc.debug("new_stack=%06x return_addr=%06x", new_stack, return_addr) # place return address for new process self.mem.w32(new_stack, return_addr)
def run_shell(self, start_pc, packet, stacksize, trap_stop_handler): newstack = self.alloc.alloc_memory("shell command stack", stacksize) newstackbase = newstack.addr newstacktop = newstackbase + stacksize oldstackbase = self.process.this_task.access.r_s("pr_Task.tc_SPLower") oldstacktop = self.process.this_task.access.r_s("pr_Task.tc_SPUpper") old_stackptr = self.cpu.r_reg(REG_A7) # addr of sys call return # put stack size on top of stack self.mem.access.w32(newstacktop - 4, stacksize) # activate new stack new_stackptr = newstacktop - 4 self.process.this_task.access.w_s("pr_Task.tc_SPLower", newstackbase) self.process.this_task.access.w_s("pr_Task.tc_SPUpper", newstacktop) # NOTE: the Manx fexec and BPCL mess is not (yet) setup here. # setup trampoline to enter sub process tr = Trampoline(self, "RunCommand") # reserve a long for old stack old_stack_off = tr.dc_l(0) # code starts tr.save_all_but_d0() # new proc registers: d1=packet tr.set_dx_l(1, packet >> 2) # d2=stack_size. this value is also in 4(sp) (see Process.init_stack), but # various C programs rely on it being present (1.3-3.1 at least have it). tr.set_dx_l(2, stacksize) # to track old dos values tr.set_ax_l(2, self.dos_guard_base) tr.set_ax_l(5, self.dos_guard_base) tr.set_ax_l(6, self.dos_guard_base) # save old stack and set new stack tr.write_ax_l(7, old_stack_off, True) # write to data offset (dc.l above) tr.set_ax_l(7, new_stackptr) # call code! (jmp - return value is on stack) tr.jmp(start_pc) # restore stack (set a label to return from new stack - see below) return_off = tr.get_code_offset() tr.read_ax_l(7, old_stack_off, True) # read from data offset (dc.l above) # restore regs tr.restore_all_but_d0() def trap_stop_function(): ret_code = self.cpu.r_reg(REG_D0) log_proc.info("return from SystemTagList: ret_code=%d", ret_code) self.cpu.w_reg(REG_A7, old_stackptr) self.process.this_task.access.w_s("pr_Task.tc_SPLower", oldstackbase) self.process.this_task.access.w_s("pr_Task.tc_SPUpper", oldstacktop) self.alloc.free_memory(newstack) trap_stop_handler(ret_code) tr.final_rts(trap_stop_function) # realize trampoline in memory (data+code) tr.done() # get label addr -> set as return value of new stack return_addr = tr.get_code_addr(return_off) log_proc.debug("new_stack=%06x return_addr=%06x", new_stackptr, return_addr) # place return address for new process self.mem.access.w32(new_stackptr, return_addr)
def start_sub_process(self, proc): log_proc.info("start sub process: %s", proc) self.proc_list.append(proc) self._set_this_task(proc) # setup trampoline to enter sub process tr = Trampoline(self, "SubProcJump") # reserve a long for old stack old_stack_off = tr.dc_l(0) # code starts tr.save_all_but_d0() # new proc registers: d0=arg_len a0=arg_cptr tr.set_dx_l(0, proc.arg_len) tr.set_ax_l(0, proc.arg_base) # d2=stack_size. this value is also in 4(sp) (see Process.init_stack), but # various C programs rely on it being present (1.3-3.1 at least have it). tr.set_dx_l(2, proc.stack_size) # to track old dos values tr.set_ax_l(2, self.dos_guard_base) tr.set_ax_l(5, self.dos_guard_base) tr.set_ax_l(6, self.dos_guard_base) # save old stack and set new stack tr.write_ax_l(7, old_stack_off, True) # write to data offset (dc.l above) new_stack = proc.stack_initial tr.set_ax_l(7, new_stack) # call code! (jmp - return value is on stack) tr.jmp(proc.prog_start) # restore stack (set a label to return from new stack - see below) return_off = tr.get_code_offset() tr.read_ax_l(7, old_stack_off, True) # read from data offset (dc.l above) # restore regs tr.restore_all_but_d0() # trap to clean up sub process resources def trap_stop_sub_process(): self.stop_sub_process() tr.final_rts(trap_stop_sub_process) # realize trampoline in memory (data+code) tr.done() # get label addr -> set as return value of new stack return_addr = tr.get_code_addr(return_off) log_proc.debug("new_stack=%06x return_addr=%06x", new_stack, return_addr) # place return address for new process self.mem.access.w32(new_stack, return_addr)
def open_lib(self, name, ver, ctx): """open a new library in memory return new AmigaLibrary instance that is setup or None if lib was not found Note: may prepare a trampoline to finish operation! """ # sanitize lib name sane_name = self._get_sane_lib_name(name) # is lib already opened? if sane_name in self.open_libs_name: self.lib_log("open_lib","opening already open lib: %s" % sane_name) lib = self.open_libs_name[sane_name] if lib.is_native: # call Open() tr = Trampoline(ctx,"open_lib[%s]" % sane_name) self._open_native_lib(lib, ctx, tr) tr.final_rts() tr.done() else: # handle usage count lib.inc_usage() # lib has to be openend else: # first check if its an internal vamos library if sane_name in self.vamos_libs: self.lib_log("open_lib","opening vamos lib: %s" % sane_name) lib = self.vamos_libs[sane_name] is_vamos_lib = True # otherwise create a new and empty AmigaLibrary else: self.lib_log("open_lib","create default lib: %s" % sane_name) lib_cfg = self.cfg.get_lib_config(sane_name) lib = AmigaLibrary(sane_name, LibraryDef, lib_cfg) is_vamos_lib = False # dump config of lib self._dump_lib_cfg(lib.config) # is lib mode = 'off' then reject open mode = lib.config.mode if mode == 'off': self.lib_log("open_lib","reject open: mode='off': %s" % sane_name, level=logging.WARN) return None # try to load an fd file for this lib lib.fd = self._load_fd(sane_name) # is native loading allowed? native_loaded = False native_allowed = mode in ('auto','amiga') if native_allowed: # now check if the library has a native counterpart # if yes then create memory layout with it load_name = self._get_load_lib_name(name) if ctx.seg_loader.can_load_seg(None,load_name): # setup trampoline tr = Trampoline(ctx,"create_lib[%s]" % sane_name) self._create_native_lib(lib, load_name, ctx, tr) self._open_native_lib(lib, ctx, tr) tr.final_rts() tr.done() native_loaded = True # no native lib available... # either its a vamos lib or we auto create one from an FD file if not native_loaded: # we need to have an FD file otherwise we can't create lib if lib.fd == None: self.lib_log("create_lib","can't create auto lib without FD file: %s" % sane_name, level=logging.ERROR) return None # if not 'auto' or 'vamos' then fail now if mode == 'amiga': self.lib_log("open_lib","can't open amiga lib: %s" % sane_name, level=logging.WARN) return None # create a (opt. fake/empty) vamos library self._create_vamos_lib(lib, ctx) self._register_open_lib(lib) lib.inc_usage() self.lib_log("open_lib","leaving open_lib(): %s" % lib, level=logging.DEBUG) return lib
def _open_native_lib(self, lib, ctx): # call Open() tr = Trampoline(ctx,"open_lib[%s]" % sane_name) self._open_native_lib_int(lib, ctx, tr) tr.final_rts() tr.done()
def init_trampoline(self): self.tr_mem_size = 256 self.tr_mem = self.alloc.alloc_memory("Trampoline", self.tr_mem_size) self.tr = Trampoline(self, self.tr_mem)
def _expunge_native_lib(self, lib, ctx): self.lib_log("expunge", "expunging native lib: '%s'" % lib.name) tr = Trampoline(ctx,"expunge_lib[%s]" % lib.name) self._free_native_lib(lib, ctx, tr) tr.final_rts() tr.done()
def start_sub_process(self, proc): log_proc.info("start sub process: %s", proc) self.proc_list.append(proc) self._set_this_task(proc) # setup trampoline to enter sub process tr_mem_size = 128 tr_mem = self.alloc.alloc_memory("SubProcJump", tr_mem_size) tr = Trampoline(self, tr_mem) tr.init() tr.save_all_but_d0() # new proc registers: d0=arg_len a0=arg_cptr tr.set_dx_l(0, proc.arg_len) tr.set_ax_l(0, proc.arg_base) # to track old dos values tr.set_ax_l(2, self.dos_guard_base) tr.set_ax_l(5, self.dos_guard_base) tr.set_ax_l(6, self.dos_guard_base) # setup new stack stack_save_addr = tr_mem.addr + tr_mem_size - 4 tr.write_ax_l(7, stack_save_addr) new_stack = proc.stack_initial tr.set_ax_l(7, new_stack) # call code! (jmp - return value is on stack) tr.jmp(proc.prog_start) # restore stack (set a label to return from new stack - see below) lab = tr.set_label() tr.read_ax_l(7, stack_save_addr) # restore regs tr.restore_all_but_d0() # trap to clean up sub process resources tr.trap(lambda x : self.stop_sub_process()) tr.rts() tr.done() # get label addr -> set as return value of new stack lab_addr = tr.get_label(lab) log_proc.debug("new_stack=%06x trampoline_return=%06x", new_stack, lab_addr) self.mem.access.w32(new_stack, lab_addr) # push trampoline self.tr_list.append(tr)
def run_shell(self,start_pc,packet,stacksize,trap_stop_handler): newstack = self.alloc.alloc_memory("shell command stack",stacksize) newstackbase = newstack.addr newstacktop = newstackbase + stacksize oldstackbase = self.process.this_task.access.r_s("pr_Task.tc_SPLower"); oldstacktop = self.process.this_task.access.r_s("pr_Task.tc_SPUpper"); old_stackptr = self.cpu.r_reg(REG_A7) # addr of sys call return # put stack size on top of stack self.mem.access.w32(newstacktop - 4,stacksize) # activate new stack new_stackptr = newstacktop - 8 self.process.this_task.access.w_s("pr_Task.tc_SPLower",newstackbase) self.process.this_task.access.w_s("pr_Task.tc_SPUpper",newstacktop) # NOTE: the Manx fexec and BPCL mess is not (yet) setup here. # setup trampoline to enter sub process tr = Trampoline(self, "RunCommand") # reserve a long for old stack old_stack_off = tr.dc_l(0) # code starts tr.save_all_but_d0() # new proc registers: d1=packet tr.set_dx_l(1, packet >> 2) # d2=stack_size. this value is also in 4(sp) (see Process.init_stack), but # various C programs rely on it being present (1.3-3.1 at least have it). tr.set_dx_l(2, stacksize) # to track old dos values tr.set_ax_l(2, self.dos_guard_base) tr.set_ax_l(5, self.dos_guard_base) tr.set_ax_l(6, self.dos_guard_base) # save old stack and set new stack tr.write_ax_l(7, old_stack_off, True) # write to data offset (dc.l above) tr.set_ax_l(7, new_stackptr) # call code! (jmp - return value is on stack) tr.jmp(start_pc) # restore stack (set a label to return from new stack - see below) return_off = tr.get_code_offset() tr.read_ax_l(7, old_stack_off, True) # read from data offset (dc.l above) # restore regs tr.restore_all_but_d0() def trap_stop_function(): ret_code = self.cpu.r_reg(REG_D0) log_proc.info("return from SystemTagList: ret_code=%d", ret_code) self.cpu.w_reg(REG_A7,old_stackptr) self.process.this_task.access.w_s("pr_Task.tc_SPLower",oldstackbase) self.process.this_task.access.w_s("pr_Task.tc_SPUpper",oldstacktop) self.alloc.free_memory(newstack) trap_stop_handler(ret_code) tr.final_rts(trap_stop_function) # realize trampoline in memory (data+code) tr.done() # get label addr -> set as return value of new stack return_addr = tr.get_code_addr(return_off) log_proc.debug("new_stack=%06x return_addr=%06x", new_stackptr, return_addr) # place return address for new process self.mem.access.w32(new_stackptr, return_addr)