예제 #1
0
class ExecLibrary(LibImpl):
    def get_struct_def(self):
        return ExecLibraryStruct

    def is_base_lib(self):
        return True

    def setup_lib(self, ctx, base_addr):
        log_exec.info("setup exec.library")
        self.lib_mgr = ctx.lib_mgr
        self.alloc = ctx.alloc
        self._pools = {}
        self._poolid = 0x1000
        self.exec_lib = ExecLibraryType(ctx.mem, base_addr)
        # init lib list
        self.exec_lib.lib_list.new_list(NodeType.NT_LIBRARY)
        self.exec_lib.device_list.new_list(NodeType.NT_DEVICE)
        # set some system contants
        if ctx.cpu_name == '68030(fake)':
            self.exec_lib.attn_flags = 7
        elif ctx.cpu_name == '68020':
            self.exec_lib.attn_flags = 3
        else:
            self.exec_lib.attn_flags = 0
        self.exec_lib.max_loc_mem = ctx.ram_size
        # create the port manager
        self.port_mgr = PortManager(ctx.alloc)
        self.semaphore_mgr = SemaphoreManager(ctx.alloc, ctx.mem)
        self.mem = ctx.mem

    def set_this_task(self, process):
        self.exec_lib.this_task = process.this_task.addr
        self.stk_lower = process.get_stack().get_lower()
        self.stk_upper = process.get_stack().get_upper()

    # helper

    def get_callee_pc(self, ctx):
        """a call stub log helper to extract the callee's pc"""
        sp = ctx.cpu.r_reg(REG_A7)
        return ctx.mem.r32(sp)

    # ----- System -----

    def Disable(self, ctx):
        log_exec.info("Disable")

    def Enable(self, ctx):
        log_exec.info("Enable")

    def Forbid(self, ctx):
        log_exec.info("Forbid")

    def Permit(self, ctx):
        log_exec.info("Permit")

    def FindTask(self, ctx):
        task_ptr = ctx.cpu.r_reg(REG_A1)
        if task_ptr == 0:
            addr = self.exec_lib.this_task.get_addr()
            log_exec.info("FindTask: me=%06x" % addr)
            return addr
        else:
            task_name = ctx.mem.r_cstr(task_ptr)
            log_exec.info("Find Task: %s" % task_name)
            raise UnsupportedFeatureError("FindTask: other task!")

    def SetSignal(self, ctx):
        new_signals = ctx.cpu.r_reg(REG_D0)
        signal_mask = ctx.cpu.r_reg(REG_D1)
        old_signals = 0
        log_exec.info(
            "SetSignals: new_signals=%08x signal_mask=%08x old_signals=%08x" %
            (new_signals, signal_mask, old_signals))
        return old_signals

    def StackSwap(self, ctx):
        stsw_ptr = ctx.cpu.r_reg(REG_A0)
        stsw = AccessStruct(ctx.mem, StackSwapStruct, struct_addr=stsw_ptr)
        # get new stack values
        new_lower = stsw.r_s('stk_Lower')
        new_upper = stsw.r_s('stk_Upper')
        new_pointer = stsw.r_s('stk_Pointer')
        # retrieve current (old) stack
        old_lower = self.stk_lower
        old_upper = self.stk_upper
        old_pointer = ctx.cpu.r_reg(REG_A7)  # addr of sys call return
        # get adress of callee
        callee = ctx.mem.r32(old_pointer)
        # is a label attached to new addr
        if ctx.label_mgr:
            label = ctx.label_mgr.get_label(new_lower)
            if label is not None:
                label.name = label.name + "=Stack"
        # we report the old stack befor callee
        old_pointer += 4
        log_exec.info(
            "StackSwap: old(lower=%06x,upper=%06x,ptr=%06x) new(lower=%06x,upper=%06x,ptr=%06x)"
            % (old_lower, old_upper, old_pointer, new_lower, new_upper,
               new_pointer))
        stsw.w_s('stk_Lower', old_lower)
        stsw.w_s('stk_Upper', old_upper)
        stsw.w_s('stk_Pointer', old_pointer)
        self.stk_lower = new_lower
        self.stk_upper = new_upper
        # put callee's address on new stack
        new_pointer -= 4
        ctx.mem.w32(new_pointer, callee)
        # activate new stack
        ctx.cpu.w_reg(REG_A7, new_pointer)

    # ----- Libraries -----

    def MakeFunctions(self, ctx):
        target = ctx.cpu.r_reg(REG_A0)
        func_array = ctx.cpu.r_reg(REG_A1)
        func_disp = ctx.cpu.r_reg(REG_A2)
        log_exec.info(
            "MakeFunctions: target=%06x, func_array=%06x, func_disp=%06x",
            target, func_array, func_disp)
        mf = MakeFuncs(ctx.mem)
        return mf.make_functions(target, func_array, func_disp)

    def InitStruct(self, ctx):
        init_tab = ctx.cpu.r_reg(REG_A1)
        memory = ctx.cpu.r_reg(REG_A2)
        size = ctx.cpu.r_reg(REG_D0)
        log_exec.info("InitStruct: init_tab=%06x, memory=%06x, size=%06x",
                      init_tab, memory, size)
        i = InitStruct(ctx.mem)
        i.init_struct(init_tab, memory, size)

    def MakeLibrary(self, ctx):
        vectors = ctx.cpu.r_reg(REG_A0)
        struct = ctx.cpu.r_reg(REG_A1)
        init = ctx.cpu.r_reg(REG_A2)
        dsize = ctx.cpu.r_reg(REG_D0)
        seglist = ctx.cpu.r_reg(REG_D1)
        ml = MakeLib(ctx.machine, ctx.alloc)
        lib_base, mobj = ml.make_library(vectors, struct, init, dsize, seglist)
        log_exec.info("MakeLibrary: vectors=%06x, struct=%06x, init=%06x, " \
                      "dsize=%06x seglist=%06x -> lib_base=%06x, mobj=%s",
                      vectors, struct, init, dsize, seglist, lib_base, mobj)
        return lib_base

    def InitResident(self, ctx):
        resident = ctx.cpu.r_reg(REG_A1)
        seglist = ctx.cpu.r_reg(REG_D1)
        ir = InitRes(ctx.machine, ctx.alloc)
        base, mobj = ir.init_resident(resident, seglist)
        log_exec.info(
            "InitResident: res=%06x, seglist=%06x -> base=%06x, mobj=%s",
            resident, seglist, base, mobj)
        return base

    def AddLibrary(self, ctx):
        lib_addr = ctx.cpu.r_reg(REG_A1)
        log_exec.info("AddLibrary: lib=%06x", lib_addr)
        lf = LibFuncs(ctx.machine, ctx.alloc)
        lf.add_library(lib_addr, exec_lib=self.exec_lib)

    def SumLibrary(self, ctx):
        lib_addr = ctx.cpu.r_reg(REG_A1)
        lf = LibFuncs(ctx.machine, ctx.alloc)
        lib_sum = lf.sum_library(lib_addr)
        log_exec.info("SumLibrary: lib=%06x -> sum=%08x", lib_addr, lib_sum)

    def SetFunction(self, ctx):
        lib_addr = ctx.cpu.r_reg(REG_A1)
        lvo = ctx.cpu.rs_reg(REG_A0)
        new_func = ctx.cpu.r_reg(REG_D0)
        lf = LibFuncs(ctx.machine, ctx.alloc)
        old_func = lf.set_function(lib_addr, lvo, new_func)
        log_exec.info(
            "SetFunction: lib=%06x, lvo=%d, new_func=%06x -> old_func=%06x",
            lib_addr, lvo, new_func, old_func)
        return old_func

    def RemLibrary(self, ctx):
        lib_addr = ctx.cpu.r_reg(REG_A1)
        lf = LibFuncs(ctx.machine, ctx.alloc)
        seglist = lf.rem_library(lib_addr, ctx.seg_loader)
        log_exec.info("RemLibrary: lib=%06x -> seglist=%06x", lib_addr,
                      seglist)

    def OpenLibrary(self, ctx):
        ver = ctx.cpu.r_reg(REG_D0)
        name_ptr = ctx.cpu.r_reg(REG_A1)
        name = ctx.mem.r_cstr(name_ptr)
        proc = ctx.process
        if proc:
            cwd = proc.get_current_dir_lock()
            pd = proc.get_home_dir_lock()
        else:
            cwd, pd = None, None
        addr = self.lib_mgr.open_lib(name, ver, cwd_lock=cwd, progdir_lock=pd)
        log_exec.info("OpenLibrary: '%s' V%d -> %06x", name, ver, addr)
        return addr

    def TaggedOpenLibrary(self, ctx):
        tag = ctx.cpu.r_reg(REG_D0)
        tags = [
            "graphics.library", "layers.library", "intuition.library",
            "dos.library", "icon.library", "expansion.library",
            "utility.library", "keymap.library", "gadtools.library",
            "workbench.library"
        ]
        if tag > 0 and tag <= len(tags):
            name = tags[tag - 1]
            addr = self.lib_mgr.open_lib(name, 0)
            log_exec.info("TaggedOpenLibrary: %d('%s') -> %06x", tag, name,
                          addr)
            return addr
        else:
            log_exec.warn("TaggedOpenLibrary: %d invalid tag -> NULL" % tag)
            return 0

    def OldOpenLibrary(self, ctx):
        name_ptr = ctx.cpu.r_reg(REG_A1)
        name = ctx.mem.r_cstr(name_ptr)
        proc = ctx.process
        if proc:
            cwd = proc.get_current_dir_lock()
            pd = proc.get_home_dir_lock()
        else:
            cwd, pd = None, None
        addr = self.lib_mgr.open_lib(name, 0, cwd_lock=cwd, progdir_lock=pd)
        log_exec.info("OldOpenLibrary: '%s' -> %06x", name, addr)
        return addr

    def CloseLibrary(self, ctx):
        lib_addr = ctx.cpu.r_reg(REG_A1)
        if lib_addr != 0:
            log_exec.info("CloseLibrary: %06x", lib_addr)
            self.lib_mgr.close_lib(lib_addr)

    def FindResident(self, ctx):
        name_ptr = ctx.cpu.r_reg(REG_A1)
        name = ctx.mem.r_cstr(name_ptr)
        log_exec.info("FindResident: '%s'" % (name))
        return 0

    def CreatePool(self, ctx):
        # need some sort of uniq id.
        # HACK: this is a hack to produce private uniq ids
        poolid = self._poolid
        self._poolid += 4
        flags = ctx.cpu.r_reg(REG_D0)
        size = (ctx.cpu.r_reg(REG_D1) + 7) & -8
        thresh = ctx.cpu.r_reg(REG_D2)
        pool = Pool(self.mem, self.alloc, flags, size, thresh, poolid)
        self._pools[poolid] = pool
        log_exec.info("CreatePool: pool 0x%x" % poolid)
        return poolid

    def AllocPooled(self, ctx):
        poolid = ctx.cpu.r_reg(REG_A0)
        size = (ctx.cpu.r_reg(REG_D0) + 7) & -8
        pc = self.get_callee_pc(ctx)
        name = "AllocPooled(%06x)" % pc
        if poolid in self._pools:
            pool = self._pools[poolid]
            mem = pool.AllocPooled(ctx.label_mgr, name, size)
            log_exec.info("AllocPooled: from pool 0x%x size %d -> 0x%06x" %
                          (poolid, size, mem.addr))
            return mem.addr
        else:
            raise VamosInternalError(
                "AllocPooled: invalid memory pool: ptr=%06x" % poolid)

    def FreePooled(self, ctx):
        poolid = ctx.cpu.r_reg(REG_A0)
        size = (ctx.cpu.r_reg(REG_D0) + 7) & -8
        mem_ptr = ctx.cpu.r_reg(REG_A1)
        if poolid in self._pools:
            pool = self._pools[poolid]
            pool.FreePooled(mem_ptr, size)
            log_exec.info("FreePooled: to pool 0x%x mem 0x%06x size %d" %
                          (poolid, mem_ptr, size))
        else:
            raise VamosInternalError(
                "FreePooled: invalid memory pool: ptr=%06x" % poolid)

    def DeletePool(self, ctx):
        log_exec.info("DeletePool")
        poolid = ctx.cpu.r_reg(REG_A0)
        if poolid in self._pools:
            pool = self._pools[poolid]
            del self._pools[poolid]
            pool.__del__()
            log_exec.info("DeletePooled: pool 0x%x" % poolid)
        else:
            raise VamosInternalError(
                "DeletePooled: invalid memory pool: ptr=%06x" % poolid)

    # ----- Memory Handling -----

    def AllocMem(self, ctx):
        size = ctx.cpu.r_reg(REG_D0)
        flags = ctx.cpu.r_reg(REG_D1)
        # label alloc
        pc = self.get_callee_pc(ctx)
        name = "AllocMem(%06x)" % pc
        mb = self.alloc.alloc_memory(name, size)
        log_exec.info("AllocMem: %s -> 0x%06x %d bytes" % (mb, mb.addr, size))
        return mb.addr

    def FreeMem(self, ctx):
        size = ctx.cpu.r_reg(REG_D0)
        addr = ctx.cpu.r_reg(REG_A1)
        if addr == 0 or size == 0:
            log_exec.info("FreeMem: freeing NULL")
            return
        mb = self.alloc.get_memory(addr)
        if mb != None:
            log_exec.info("FreeMem: 0x%06x %d bytes -> %s" % (addr, size, mb))
            self.alloc.free_memory(mb)
        else:
            raise VamosInternalError(
                "FreeMem: Unknown memory to free: ptr=%06x size=%06x" %
                (addr, size))

    def AllocVec(self, ctx):
        size = ctx.cpu.r_reg(REG_D0)
        flags = ctx.cpu.r_reg(REG_D1)
        mb = self.alloc.alloc_memory(
            "AllocVec(@%06x)" % self.get_callee_pc(ctx), size)
        log_exec.info("AllocVec: %s" % mb)
        return mb.addr

    def FreeVec(self, ctx):
        addr = ctx.cpu.r_reg(REG_A1)
        if addr == 0:
            log_exec.info("FreeVec: freeing NULL")
            return
        mb = self.alloc.get_memory(addr)
        if mb != None:
            log_exec.info("FreeVec: %s" % mb)
            self.alloc.free_memory(mb)
        else:
            raise VamosInternalError(
                "FreeVec: Unknown memory to free: ptr=%06x" % (addr))

    def AvailMem(self, ctx):
        reqments = ctx.cpu.r_reg(REG_D1)
        if reqments & 2:
            return 0  # no chip memory
        if reqments & (1 << 17):
            return self.alloc.largest_chunk()
        elif reqments & (1 << 19):
            return self.alloc.total()
        else:
            return self.alloc.available()

    # ----- Message Passing -----

    def PutMsg(self, ctx):
        port_addr = ctx.cpu.r_reg(REG_A0)
        msg_addr = ctx.cpu.r_reg(REG_A1)
        log_exec.info("PutMsg: port=%06x msg=%06x" % (port_addr, msg_addr))
        has_port = self.port_mgr.has_port(port_addr)
        if not has_port:
            raise VamosInternalError("PutMsg: on invalid Port (%06x) called!" %
                                     port_addr)
        self.port_mgr.put_msg(port_addr, msg_addr)

    def GetMsg(self, ctx):
        port_addr = ctx.cpu.r_reg(REG_A0)
        log_exec.info("GetMsg: port=%06x" % (port_addr))
        has_port = self.port_mgr.has_port(port_addr)
        if not has_port:
            raise VamosInternalError("GetMsg: on invalid Port (%06x) called!" %
                                     port_addr)
        msg_addr = self.port_mgr.get_msg(port_addr)
        if msg_addr != None:
            log_exec.info("GetMsg: got message %06x" % (msg_addr))
            return msg_addr
        else:
            log_exec.info("GetMsg: no message available!")
            return 0

    def CreateMsgPort(self, ctx):
        port = self.port_mgr.create_port("exec_port", None)
        log_exec.info("CreateMsgPort: -> port=%06x" % (port))
        return port

    def DeleteMsgPort(self, ctx):
        port = ctx.cpu.r_reg(REG_A0)
        log_exec.info("DeleteMsgPort(%06x)" % port)
        self.port_mgr.free_port(port)
        return 0

    def CreateIORequest(self, ctx):
        port = ctx.cpu.r_reg(REG_A0)
        size = ctx.cpu.r_reg(REG_D0)
        # label alloc
        pc = self.get_callee_pc(ctx)
        name = "CreateIORequest(%06x)" % pc
        mb = self.alloc.alloc_memory(name, size)
        log_exec.info("CreateIORequest: (%s,%s,%s) -> 0x%06x %d bytes" %
                      (mb, port, size, mb.addr, size))
        return mb.addr

    def DeleteIORequest(self, ctx):
        req = ctx.cpu.r_reg(REG_A0)
        mb = self.alloc.get_memory(req)
        if mb != None:
            log_exec.info("DeleteIOREquest: 0x%06x -> %s" % (req, mb))
            self.alloc.free_memory(mb)
        else:
            raise VamosInternalError(
                "DeleteIORequest: Unknown IORequest to delete: ptr=%06x" %
                addr)

    def OpenDevice(self, ctx):
        name_ptr = ctx.cpu.r_reg(REG_A0)
        unit = ctx.cpu.r_reg(REG_D0)
        io_addr = ctx.cpu.r_reg(REG_A1)
        io = AccessStruct(ctx.mem, IORequestStruct, io_addr)
        flags = ctx.cpu.r_reg(REG_D1)
        name = ctx.mem.r_cstr(name_ptr)
        addr = self.lib_mgr.open_lib(name)
        io.w_s("io_Device", addr)
        if addr == 0:
            log_exec.info("OpenDevice: '%s' unit %d flags %d -> NULL", name,
                          unit, flags)
            return -1
        else:
            log_exec.info("OpenDevice: '%s' unit %d flags %d -> %06x", name,
                          unit, flags, addr)
            return 0

    def CloseDevice(self, ctx):
        io_addr = ctx.cpu.r_reg(REG_A1)
        if io_addr != 0:
            io = AccessStruct(ctx.mem, IORequestStruct, io_addr)
            dev_addr = io.r_s("io_Device")
            if dev_addr != 0:
                log_exec.info("CloseDevice: %06x", dev_addr)
                self.lib_mgr.close_lib(dev_addr)
                io.w_s("io_Device", 0)

    def WaitPort(self, ctx):
        port_addr = ctx.cpu.r_reg(REG_A0)
        log_exec.info("WaitPort: port=%06x" % (port_addr))
        has_port = self.port_mgr.has_port(port_addr)
        if not has_port:
            raise VamosInternalError(
                "WaitPort: on invalid Port (%06x) called!" % port_addr)
        has_msg = self.port_mgr.has_msg(port_addr)
        if not has_msg:
            raise UnsupportedFeatureError(
                "WaitPort on empty message queue called: Port (%06x)" %
                port_addr)
        msg_addr = self.port_mgr.get_msg(port_addr)
        log_exec.info("WaitPort: got message %06x" % (msg_addr))
        return msg_addr

    def AddTail(self, ctx):
        list_addr = ctx.cpu.r_reg(REG_A0)
        node_addr = ctx.cpu.r_reg(REG_A1)
        log_exec.info("AddTail(%06x, %06x)" % (list_addr, node_addr))
        l = AccessStruct(ctx.mem, ListStruct, list_addr)
        n = AccessStruct(ctx.mem, NodeStruct, node_addr)
        n.w_s("ln_Succ", l.s_get_addr("lh_Tail"))
        tp = l.r_s("lh_TailPred")
        n.w_s("ln_Pred", tp)
        AccessStruct(ctx.mem, NodeStruct, tp).w_s("ln_Succ", node_addr)
        l.w_s("lh_TailPred", node_addr)

    def AddHead(self, ctx):
        list_addr = ctx.cpu.r_reg(REG_A0)
        node_addr = ctx.cpu.r_reg(REG_A1)
        log_exec.info("AddHead(%06x, %06x)" % (list_addr, node_addr))
        l = AccessStruct(ctx.mem, ListStruct, list_addr)
        n = AccessStruct(ctx.mem, NodeStruct, node_addr)
        n.w_s("ln_Pred", l.s_get_addr("lh_Head"))
        h = l.r_s("lh_Head")
        n.w_s("ln_Succ", h)
        AccessStruct(ctx.mem, NodeStruct, h).w_s("ln_Pred", node_addr)
        l.w_s("lh_Head", node_addr)

    def Remove(self, ctx):
        node_addr = ctx.cpu.r_reg(REG_A1)
        n = AccessStruct(ctx.mem, NodeStruct, node_addr)
        succ = n.r_s("ln_Succ")
        pred = n.r_s("ln_Pred")
        log_exec.info("Remove(%06x): ln_Pred=%06x ln_Succ=%06x" %
                      (node_addr, pred, succ))
        AccessStruct(ctx.mem, NodeStruct, pred).w_s("ln_Succ", succ)
        AccessStruct(ctx.mem, NodeStruct, succ).w_s("ln_Pred", pred)
        return node_addr

    def RemHead(self, ctx):
        list_addr = ctx.cpu.r_reg(REG_A0)
        l = AccessStruct(ctx.mem, ListStruct, list_addr)
        node_addr = l.r_s("lh_Head")
        n = AccessStruct(ctx.mem, NodeStruct, node_addr)
        succ = n.r_s("ln_Succ")
        pred = n.r_s("ln_Pred")
        if succ == 0:
            log_exec.info("RemHead(%06x): null" % list_addr)
            return 0
        AccessStruct(ctx.mem, NodeStruct, pred).w_s("ln_Succ", succ)
        AccessStruct(ctx.mem, NodeStruct, succ).w_s("ln_Pred", pred)
        log_exec.info("RemHead(%06x): %06x" % (list_addr, node_addr))
        return node_addr

    def RemTail(self, ctx):
        list_addr = ctx.cpu.r_reg(REG_A0)
        l = AccessStruct(ctx.mem, ListStruct, list_addr)
        node_addr = l.r_s("lh_TailPred")
        n = AccessStruct(ctx.mem, NodeStruct, node_addr)
        succ = n.r_s("ln_Succ")
        pred = n.r_s("ln_Pred")
        if pred == 0:
            log_exec.info("RemTail(%06x): null" % list_addr)
            return 0
        AccessStruct(ctx.mem, NodeStruct, pred).w_s("ln_Succ", succ)
        AccessStruct(ctx.mem, NodeStruct, succ).w_s("ln_Pred", pred)
        log_exec.info("RemTail(%06x): %06x" % (list_addr, node_addr))
        return node_addr

    def FindName(self, ctx):
        list_addr = ctx.cpu.r_reg(REG_A0)
        name_ptr = ctx.cpu.r_reg(REG_A1)
        name = ctx.mem.r_cstr(name_ptr)
        list_t = List(ctx.mem, list_addr)
        match = list_t.find_name(name)
        log_exec.info("FindName: start=%s, name='%s' -> match=%s", list_t,
                      name, match)
        if match:
            return match.get_addr()
        else:
            return 0

    def CopyMem(self, ctx):
        source = ctx.cpu.r_reg(REG_A0)
        dest = ctx.cpu.r_reg(REG_A1)
        length = ctx.cpu.r_reg(REG_D0)
        log_exec.info("CopyMem: source=%06x dest=%06x len=%06x" %
                      (source, dest, length))
        ctx.mem.copy_block(source, dest, length)

    def CopyMemQuick(self, ctx):
        source = ctx.cpu.r_reg(REG_A0)
        dest = ctx.cpu.r_reg(REG_A1)
        length = ctx.cpu.r_reg(REG_D0)
        log_exec.info("CopyMemQuick: source=%06x dest=%06x len=%06x" %
                      (source, dest, length))
        ctx.mem.copy_block(source, dest, length)

    def TypeOfMem(self, ctx):
        addr = ctx.cpu.r_reg(REG_A1)
        log_exec.info("TypeOfMem: source=%06x -> %s" %
                      (addr, self.alloc.is_valid_address(addr)))
        if self.alloc.is_valid_address(addr):
            return 1  #MEMF_PUBLIC
        return 0

    def CacheClearU(self, ctx):
        return 0

    def RawDoFmt(self, ctx):
        fmtString = ctx.cpu.r_reg(REG_A0)
        dataStream = ctx.cpu.r_reg(REG_A1)
        putProc = ctx.cpu.r_reg(REG_A2)
        putData = ctx.cpu.r_reg(REG_A3)
        dataStream, fmt, resultstr, known = raw_do_fmt(ctx, fmtString,
                                                       dataStream, putProc,
                                                       putData)
        log_exec.info("RawDoFmt: fmtString=%s -> %s (known=%s, dataStream=%06x)" % \
            (fmt, resultstr, known, dataStream))
        return dataStream

    # ----- Semaphore Handling -----

    def InitSemaphore(self, ctx):
        addr = ctx.cpu.r_reg(REG_A0)
        self.semaphore_mgr.InitSemaphore(addr)
        log_exec.info("InitSemaphore(%06x)" % addr)

    def AddSemaphore(self, ctx):
        addr = ctx.cpu.r_reg(REG_A1)
        sstruct = AccessStruct(ctx.mem, SignalSemaphoreStruct, addr)
        name_ptr = sstruct.r_s("ss_Link.ln_Name")
        name = ctx.mem.r_cstr(name_ptr)
        self.semaphore_mgr.AddSemaphore(addr, name)
        log_exec.info("AddSemaphore(%06x,%s)" % (addr, name))

    def RemSemaphore(self, ctx):
        addr = ctx.cpu.r_reg(REG_A1)
        self.semaphore_mgr.RemSemaphore(addr)
        log_exec.info("RemSemaphore(%06x)" % addr)

    def FindSemaphore(self, ctx):
        name_ptr = ctx.cpu.r_reg(REG_A1)
        name = ctx.mem.r_cstr(name_ptr)
        semaphore = self.semaphore_mgr.FindSemaphore(name)
        log_exec.info("FindSemaphore(%s) -> %s" % (name, semaphore))
        if semaphore != None:
            return semaphore.addr
        else:
            return 0

    def ObtainSemaphore(self, ctx):
        addr = ctx.cpu.r_reg(REG_A0)
        # nop for now
        log_exec.info("ObtainSemaphore(%06x) ignored" % addr)

    def ObtainSemaphoreShared(self, ctx):
        addr = ctx.cpu.r_reg(REG_A0)
        # nop for now
        log_exec.info("ObtainSemaphoreShared(%06x) ignored" % addr)

    def AttemptSemaphore(self, ctx):
        addr = ctx.cpu.r_reg(REG_A0)
        # nop for now
        log_exec.info("AttemptSemaphore(%06x) ignored" % addr)
        return 1

    def ReleaseSemaphore(self, ctx):
        addr = ctx.cpu.r_reg(REG_A0)
        # nop for now
        log_exec.info("ReleaseSemaphore(%06x) ignored" % addr)

    # ----- Resources -----

    def OpenResource(self, ctx):
        name_ptr = ctx.cpu.r_reg(REG_A1)
        name = ctx.mem.r_cstr(name_ptr)
        log_exec.info("OpenResource(%s) ignored" % name)
        return 0

    # ----- Allocate/Deallocate -----

    def Allocate(self, ctx):
        mh_addr = ctx.cpu.r_reg(REG_A0)
        num_bytes = ctx.cpu.r_reg(REG_D0)
        blk_addr = lexec.Alloc.allocate(ctx, mh_addr, num_bytes)
        log_exec.info("Allocate(%06x, %06x) -> %06x" %
                      (mh_addr, num_bytes, blk_addr))
        return blk_addr

    def Deallocate(self, ctx):
        mh_addr = ctx.cpu.r_reg(REG_A0)
        blk_addr = ctx.cpu.r_reg(REG_A1)
        num_bytes = ctx.cpu.r_reg(REG_D0)
        lexec.Alloc.deallocate(ctx, mh_addr, blk_addr, num_bytes)
        log_exec.info("Deallocate(%06x, %06x, %06x)" %
                      (mh_addr, blk_addr, num_bytes))
예제 #2
0
class ExecLibrary(LibImpl):

  def get_struct_def(self):
    return ExecLibraryStruct

  def setup_lib(self, ctx, base_addr):
    log_exec.info("setup exec.library")
    self.lib_mgr = ctx.lib_mgr
    self.alloc = ctx.alloc
    self._pools = {}
    self._poolid = 0x1000
    self.exec_lib = ExecLibraryType(ctx.mem, base_addr)
    # init lib list
    self.exec_lib.lib_list.new_list(NodeType.NT_LIBRARY)
    self.exec_lib.device_list.new_list(NodeType.NT_DEVICE)
    # set some system contants
    if ctx.cpu_name == '68030(fake)':
      self.exec_lib.attn_flags = 7
    elif ctx.cpu_name == '68020':
      self.exec_lib.attn_flags = 3
    else:
      self.exec_lib.attn_flags = 0
    self.exec_lib.max_loc_mem = ctx.ram_size
    # create the port manager
    self.port_mgr = PortManager(ctx.alloc)
    self.semaphore_mgr = SemaphoreManager(ctx.alloc,ctx.mem)
    self.mem      = ctx.mem

  def set_this_task(self, process):
    self.exec_lib.this_task = process.this_task.addr
    self.stk_lower = process.get_stack().get_lower()
    self.stk_upper = process.get_stack().get_upper()

  # helper

  def get_callee_pc(self,ctx):
    """a call stub log helper to extract the callee's pc"""
    sp = ctx.cpu.r_reg(REG_A7)
    return ctx.mem.r32(sp)

  # ----- System -----

  def Disable(self, ctx):
    log_exec.info("Disable")
  def Enable(self, ctx):
    log_exec.info("Enable")
  def Forbid(self, ctx):
    log_exec.info("Forbid")
  def Permit(self, ctx):
    log_exec.info("Permit")

  def FindTask(self, ctx):
    task_ptr = ctx.cpu.r_reg(REG_A1)
    if task_ptr == 0:
      addr = self.exec_lib.this_task.get_addr()
      log_exec.info("FindTask: me=%06x" % addr)
      return addr
    else:
      task_name = ctx.mem.r_cstr(task_ptr)
      log_exec.info("Find Task: %s" % task_name)
      raise UnsupportedFeatureError("FindTask: other task!");

  def SetSignal(self, ctx):
    new_signals = ctx.cpu.r_reg(REG_D0)
    signal_mask = ctx.cpu.r_reg(REG_D1)
    old_signals = 0
    log_exec.info("SetSignals: new_signals=%08x signal_mask=%08x old_signals=%08x" % (new_signals, signal_mask, old_signals))
    return old_signals

  def StackSwap(self, ctx):
    stsw_ptr = ctx.cpu.r_reg(REG_A0)
    stsw = AccessStruct(ctx.mem,StackSwapStruct,struct_addr=stsw_ptr)
    # get new stack values
    new_lower = stsw.r_s('stk_Lower')
    new_upper = stsw.r_s('stk_Upper')
    new_pointer = stsw.r_s('stk_Pointer')
    # retrieve current (old) stack
    old_lower = self.stk_lower
    old_upper = self.stk_upper
    old_pointer = ctx.cpu.r_reg(REG_A7) # addr of sys call return
    # get adress of callee
    callee = ctx.mem.r32(old_pointer)
    # is a label attached to new addr
    if ctx.label_mgr:
      label = ctx.label_mgr.get_label(new_lower)
      if label is not None:
        label.name = label.name + "=Stack"
    # we report the old stack befor callee
    old_pointer += 4
    log_exec.info("StackSwap: old(lower=%06x,upper=%06x,ptr=%06x) new(lower=%06x,upper=%06x,ptr=%06x)" % (old_lower,old_upper,old_pointer,new_lower,new_upper,new_pointer))
    stsw.w_s('stk_Lower', old_lower)
    stsw.w_s('stk_Upper', old_upper)
    stsw.w_s('stk_Pointer', old_pointer)
    self.stk_lower = new_lower
    self.stk_upper = new_upper
    # put callee's address on new stack
    new_pointer -= 4
    ctx.mem.w32(new_pointer,callee)
    # activate new stack
    ctx.cpu.w_reg(REG_A7, new_pointer)

  # ----- Libraries -----

  def MakeFunctions(self, ctx):
    target = ctx.cpu.r_reg(REG_A0)
    func_array = ctx.cpu.r_reg(REG_A1)
    func_disp = ctx.cpu.r_reg(REG_A2)
    log_exec.info("MakeFunctions: target=%06x, func_array=%06x, func_disp=%06x",
                  target, func_array, func_disp)
    mf = MakeFuncs(ctx.mem)
    return mf.make_functions(target, func_array, func_disp)

  def InitStruct(self, ctx):
    init_tab = ctx.cpu.r_reg(REG_A1)
    memory = ctx.cpu.r_reg(REG_A2)
    size = ctx.cpu.r_reg(REG_D0)
    log_exec.info("InitStruct: init_tab=%06x, memory=%06x, size=%06x",
                  init_tab, memory, size)
    i = InitStruct(ctx.mem)
    i.init_struct(init_tab, memory, size)

  def MakeLibrary(self, ctx):
    vectors = ctx.cpu.r_reg(REG_A0)
    struct = ctx.cpu.r_reg(REG_A1)
    init = ctx.cpu.r_reg(REG_A2)
    dsize = ctx.cpu.r_reg(REG_D0)
    seglist = ctx.cpu.r_reg(REG_D1)
    ml = MakeLib(ctx.machine, ctx.alloc)
    lib_base, mobj = ml.make_library(vectors, struct, init, dsize, seglist)
    log_exec.info("MakeLibrary: vectors=%06x, struct=%06x, init=%06x, " \
                  "dsize=%06x seglist=%06x -> lib_base=%06x, mobj=%s",
                  vectors, struct, init, dsize, seglist, lib_base, mobj)
    return lib_base

  def InitResident(self, ctx):
    resident = ctx.cpu.r_reg(REG_A1)
    seglist = ctx.cpu.r_reg(REG_D1)
    ir = InitRes(ctx.machine, ctx.alloc)
    base, mobj = ir.init_resident(resident, seglist)
    log_exec.info("InitResident: res=%06x, seglist=%06x -> base=%06x, mobj=%s",
                  resident, seglist, base, mobj)
    return base

  def AddLibrary(self, ctx):
    lib_addr = ctx.cpu.r_reg(REG_A1)
    log_exec.info("AddLibrary: lib=%06x", lib_addr)
    lf = LibFuncs(ctx.machine, ctx.alloc)
    lf.add_library(lib_addr, exec_lib=self.exec_lib)

  def SumLibrary(self, ctx):
    lib_addr = ctx.cpu.r_reg(REG_A1)
    lf = LibFuncs(ctx.machine, ctx.alloc)
    lib_sum = lf.sum_library(lib_addr)
    log_exec.info("SumLibrary: lib=%06x -> sum=%08x", lib_addr, lib_sum)

  def SetFunction(self, ctx):
    lib_addr = ctx.cpu.r_reg(REG_A1)
    lvo = ctx.cpu.rs_reg(REG_A0)
    new_func = ctx.cpu.r_reg(REG_D0)
    lf = LibFuncs(ctx.machine, ctx.alloc)
    old_func = lf.set_function(lib_addr, lvo, new_func)
    log_exec.info("SetFunction: lib=%06x, lvo=%d, new_func=%06x -> old_func=%06x",
                  lib_addr, lvo, new_func, old_func)
    return old_func

  def RemLibrary(self, ctx):
    lib_addr = ctx.cpu.r_reg(REG_A1)
    lf = LibFuncs(ctx.machine, ctx.alloc)
    seglist = lf.rem_library(lib_addr, ctx.seg_loader)
    log_exec.info("RemLibrary: lib=%06x -> seglist=%06x", lib_addr, seglist)

  def OpenLibrary(self, ctx):
    ver = ctx.cpu.r_reg(REG_D0)
    name_ptr = ctx.cpu.r_reg(REG_A1)
    name = ctx.mem.r_cstr(name_ptr)
    proc = ctx.process
    if proc:
      cwd = proc.get_current_dir_lock()
      pd = proc.get_home_dir_lock()
    else:
      cwd, pd = None, None
    addr = self.lib_mgr.open_lib(name, ver, cwd_lock=cwd, progdir_lock=pd)
    log_exec.info("OpenLibrary: '%s' V%d -> %06x", name, ver, addr)
    return addr

  def TaggedOpenLibrary(self, ctx):
    tag = ctx.cpu.r_reg(REG_D0)
    tags = ["graphics.library","layers.library","intuition.library","dos.library","icon.library","expansion.library",
            "utility.library","keymap.library","gadtools.library","workbench.library"]
    if tag > 0 and tag <= len(tags):
      name = tags[tag - 1]
      addr = self.lib_mgr.open_lib(name, 0)
      log_exec.info("TaggedOpenLibrary: %d('%s') -> %06x", tag, name, addr)
      return addr
    else:
      log_exec.warn("TaggedOpenLibrary: %d invalid tag -> NULL" % tag)
      return 0

  def OldOpenLibrary(self, ctx):
    name_ptr = ctx.cpu.r_reg(REG_A1)
    name = ctx.mem.r_cstr(name_ptr)
    proc = ctx.process
    if proc:
      cwd = proc.get_current_dir_lock()
      pd = proc.get_home_dir_lock()
    else:
      cwd, pd = None, None
    addr = self.lib_mgr.open_lib(name, 0, cwd_lock=cwd, progdir_lock=pd)
    log_exec.info("OldOpenLibrary: '%s' -> %06x", name, addr)
    return addr

  def CloseLibrary(self, ctx):
    lib_addr = ctx.cpu.r_reg(REG_A1)
    if lib_addr != 0:
      log_exec.info("CloseLibrary: %06x", lib_addr)
      self.lib_mgr.close_lib(lib_addr)

  def FindResident(self, ctx):
    name_ptr = ctx.cpu.r_reg(REG_A1)
    name = ctx.mem.r_cstr(name_ptr)
    log_exec.info("FindResident: '%s'" % (name))
    return 0

  def CreatePool(self, ctx):
    # need some sort of uniq id.
    # HACK: this is a hack to produce private uniq ids
    poolid = self._poolid
    self._poolid += 4;
    flags  = ctx.cpu.r_reg(REG_D0);
    size   = (ctx.cpu.r_reg(REG_D1) + 7) & -8;
    thresh = ctx.cpu.r_reg(REG_D2)
    pool   = Pool(self.mem, self.alloc, flags, size, thresh, poolid)
    self._pools[poolid] = pool
    log_exec.info("CreatePool: pool 0x%x" % poolid)
    return poolid

  def AllocPooled(self, ctx):
    poolid = ctx.cpu.r_reg(REG_A0)
    size   = (ctx.cpu.r_reg(REG_D0) + 7) & -8
    pc     = self.get_callee_pc(ctx)
    name   = "AllocPooled(%06x)" % pc
    if poolid in self._pools:
      pool = self._pools[poolid]
      mem = pool.AllocPooled(ctx.label_mgr ,name, size)
      log_exec.info("AllocPooled: from pool 0x%x size %d -> 0x%06x" % (poolid,size,mem.addr))
      return mem.addr
    else:
      raise VamosInternalError("AllocPooled: invalid memory pool: ptr=%06x" % poolid)

  def FreePooled(self, ctx):
    poolid = ctx.cpu.r_reg(REG_A0)
    size   = (ctx.cpu.r_reg(REG_D0) + 7) & -8
    mem_ptr= ctx.cpu.r_reg(REG_A1)
    if poolid in self._pools:
      pool   = self._pools[poolid]
      pool.FreePooled(mem_ptr,size)
      log_exec.info("FreePooled: to pool 0x%x mem 0x%06x size %d" % (poolid,mem_ptr,size))
    else:
      raise VamosInternalError("FreePooled: invalid memory pool: ptr=%06x" % poolid)

  def DeletePool(self, ctx):
    log_exec.info("DeletePool")
    poolid = ctx.cpu.r_reg(REG_A0)
    if poolid in self._pools:
      pool = self._pools[poolid]
      del self._pools[poolid]
      pool.__del__()
      log_exec.info("DeletePooled: pool 0x%x" % poolid)
    else:
      raise VamosInternalError("DeletePooled: invalid memory pool: ptr=%06x" % poolid)


  # ----- Memory Handling -----

  def AllocMem(self, ctx):
    size = ctx.cpu.r_reg(REG_D0)
    flags = ctx.cpu.r_reg(REG_D1)
    # label alloc
    pc = self.get_callee_pc(ctx)
    name = "AllocMem(%06x)" % pc
    mb = self.alloc.alloc_memory(name,size)
    log_exec.info("AllocMem: %s -> 0x%06x %d bytes" % (mb,mb.addr,size))
    return mb.addr

  def FreeMem(self, ctx):
    size = ctx.cpu.r_reg(REG_D0)
    addr = ctx.cpu.r_reg(REG_A1)
    if addr == 0 or size == 0:
      log_exec.info("FreeMem: freeing NULL")
      return
    mb = self.alloc.get_memory(addr)
    if mb != None:
      log_exec.info("FreeMem: 0x%06x %d bytes -> %s" % (addr,size,mb))
      self.alloc.free_memory(mb)
    else:
      raise VamosInternalError("FreeMem: Unknown memory to free: ptr=%06x size=%06x" % (addr, size))

  def AllocVec(self, ctx):
    size = ctx.cpu.r_reg(REG_D0)
    flags = ctx.cpu.r_reg(REG_D1)
    mb = self.alloc.alloc_memory("AllocVec(@%06x)" % self.get_callee_pc(ctx),size)
    log_exec.info("AllocVec: %s" % mb)
    return mb.addr

  def FreeVec(self, ctx):
    addr = ctx.cpu.r_reg(REG_A1)
    if addr == 0:
      log_exec.info("FreeVec: freeing NULL")
      return
    mb = self.alloc.get_memory(addr)
    if mb != None:
      log_exec.info("FreeVec: %s" % mb)
      self.alloc.free_memory(mb)
    else:
      raise VamosInternalError("FreeVec: Unknown memory to free: ptr=%06x" % (addr))

  def AvailMem(self, ctx):
    reqments = ctx.cpu.r_reg(REG_D1)
    if reqments & 2:
      return 0 # no chip memory
    if reqments & (1<<17):
      return self.alloc.largest_chunk()
    elif reqments & (1<<19):
      return self.alloc.total()
    else:
      return self.alloc.available()


  # ----- Message Passing -----

  def PutMsg(self, ctx):
    port_addr = ctx.cpu.r_reg(REG_A0)
    msg_addr = ctx.cpu.r_reg(REG_A1)
    log_exec.info("PutMsg: port=%06x msg=%06x" % (port_addr, msg_addr))
    has_port = self.port_mgr.has_port(port_addr)
    if not has_port:
      raise VamosInternalError("PutMsg: on invalid Port (%06x) called!" % port_addr)
    self.port_mgr.put_msg(port_addr, msg_addr)

  def GetMsg(self, ctx):
    port_addr = ctx.cpu.r_reg(REG_A0)
    log_exec.info("GetMsg: port=%06x" % (port_addr))
    has_port = self.port_mgr.has_port(port_addr)
    if not has_port:
      raise VamosInternalError("GetMsg: on invalid Port (%06x) called!" % port_addr)
    msg_addr = self.port_mgr.get_msg(port_addr)
    if msg_addr != None:
      log_exec.info("GetMsg: got message %06x" % (msg_addr))
      return msg_addr
    else:
      log_exec.info("GetMsg: no message available!")
      return 0

  def CreateMsgPort(self, ctx):
    port = self.port_mgr.create_port("exec_port",None)
    log_exec.info("CreateMsgPort: -> port=%06x" % (port))
    return port

  def DeleteMsgPort(self, ctx):
    port = ctx.cpu.r_reg(REG_A0)
    log_exec.info("DeleteMsgPort(%06x)" % port)
    self.port_mgr.free_port(port)
    return 0

  def CreateIORequest(self,ctx):
    port = ctx.cpu.r_reg(REG_A0)
    size = ctx.cpu.r_reg(REG_D0)
    # label alloc
    pc   = self.get_callee_pc(ctx)
    name = "CreateIORequest(%06x)" % pc
    mb   = self.alloc.alloc_memory(name,size)
    log_exec.info("CreateIORequest: (%s,%s,%s) -> 0x%06x %d bytes" % (mb,port,size,mb.addr,size))
    return mb.addr

  def DeleteIORequest(self,ctx):
    req = ctx.cpu.r_reg(REG_A0)
    mb  = self.alloc.get_memory(req)
    if mb != None:
      log_exec.info("DeleteIOREquest: 0x%06x -> %s" % (req,mb))
      self.alloc.free_memory(mb)
    else:
      raise VamosInternalError("DeleteIORequest: Unknown IORequest to delete: ptr=%06x" % addr)

  def OpenDevice(self,ctx):
    name_ptr = ctx.cpu.r_reg(REG_A0)
    unit     = ctx.cpu.r_reg(REG_D0)
    io_addr  = ctx.cpu.r_reg(REG_A1)
    io       = AccessStruct(ctx.mem, IORequestStruct, io_addr)
    flags    = ctx.cpu.r_reg(REG_D1)
    name     = ctx.mem.r_cstr(name_ptr)
    addr     = self.lib_mgr.open_lib(name)
    io.w_s("io_Device", addr)
    if addr == 0:
      log_exec.info("OpenDevice: '%s' unit %d flags %d -> NULL", name, unit, flags)
      return -1
    else:
      log_exec.info("OpenDevice: '%s' unit %d flags %d -> %06x", name, unit, flags, addr)
      return 0

  def CloseDevice(self,ctx):
    io_addr  = ctx.cpu.r_reg(REG_A1)
    if io_addr != 0:
      io       = AccessStruct(ctx.mem, IORequestStruct, io_addr)
      dev_addr = io.r_s("io_Device")
      if dev_addr != 0:
        log_exec.info("CloseDevice: %06x", dev_addr)
        self.lib_mgr.close_lib(dev_addr)
        io.w_s("io_Device", 0)

  def WaitPort(self, ctx):
    port_addr = ctx.cpu.r_reg(REG_A0)
    log_exec.info("WaitPort: port=%06x" % (port_addr))
    has_port = self.port_mgr.has_port(port_addr)
    if not has_port:
      raise VamosInternalError("WaitPort: on invalid Port (%06x) called!" % port_addr)
    has_msg = self.port_mgr.has_msg(port_addr)
    if not has_msg:
      raise UnsupportedFeatureError("WaitPort on empty message queue called: Port (%06x)" % port_addr)
    msg_addr = self.port_mgr.get_msg(port_addr)
    log_exec.info("WaitPort: got message %06x" % (msg_addr))
    return msg_addr

  def AddTail(self, ctx):
    list_addr = ctx.cpu.r_reg(REG_A0)
    node_addr = ctx.cpu.r_reg(REG_A1)
    log_exec.info("AddTail(%06x, %06x)" % (list_addr, node_addr))
    l = AccessStruct(ctx.mem, ListStruct, list_addr)
    n = AccessStruct(ctx.mem, NodeStruct, node_addr)
    n.w_s("ln_Succ", l.s_get_addr("lh_Tail"))
    tp = l.r_s("lh_TailPred")
    n.w_s("ln_Pred", tp)
    AccessStruct(ctx.mem, NodeStruct, tp).w_s("ln_Succ", node_addr)
    l.w_s("lh_TailPred", node_addr)

  def AddHead(self, ctx):
    list_addr = ctx.cpu.r_reg(REG_A0)
    node_addr = ctx.cpu.r_reg(REG_A1)
    log_exec.info("AddHead(%06x, %06x)" % (list_addr, node_addr))
    l = AccessStruct(ctx.mem, ListStruct, list_addr)
    n = AccessStruct(ctx.mem, NodeStruct, node_addr)
    n.w_s("ln_Pred", l.s_get_addr("lh_Head"))
    h = l.r_s("lh_Head")
    n.w_s("ln_Succ", h)
    AccessStruct(ctx.mem, NodeStruct, h).w_s("ln_Pred", node_addr)
    l.w_s("lh_Head", node_addr)

  def Remove(self, ctx):
    node_addr = ctx.cpu.r_reg(REG_A1)
    n = AccessStruct(ctx.mem, NodeStruct, node_addr)
    succ = n.r_s("ln_Succ")
    pred = n.r_s("ln_Pred")
    log_exec.info("Remove(%06x): ln_Pred=%06x ln_Succ=%06x" % (node_addr, pred, succ))
    AccessStruct(ctx.mem, NodeStruct, pred).w_s("ln_Succ", succ)
    AccessStruct(ctx.mem, NodeStruct, succ).w_s("ln_Pred", pred)
    return node_addr

  def RemHead(self, ctx):
    list_addr = ctx.cpu.r_reg(REG_A0)
    l = AccessStruct(ctx.mem, ListStruct, list_addr)
    node_addr = l.r_s("lh_Head")
    n = AccessStruct(ctx.mem, NodeStruct, node_addr)
    succ = n.r_s("ln_Succ")
    pred = n.r_s("ln_Pred")
    if succ == 0:
      log_exec.info("RemHead(%06x): null" % list_addr)
      return 0
    AccessStruct(ctx.mem, NodeStruct, pred).w_s("ln_Succ", succ)
    AccessStruct(ctx.mem, NodeStruct, succ).w_s("ln_Pred", pred)
    log_exec.info("RemHead(%06x): %06x" % (list_addr, node_addr))
    return node_addr

  def RemTail(self, ctx):
    list_addr = ctx.cpu.r_reg(REG_A0)
    l = AccessStruct(ctx.mem, ListStruct, list_addr)
    node_addr = l.r_s("lh_TailPred")
    n = AccessStruct(ctx.mem, NodeStruct, node_addr)
    succ = n.r_s("ln_Succ")
    pred = n.r_s("ln_Pred")
    if pred == 0:
      log_exec.info("RemTail(%06x): null" % list_addr)
      return 0
    AccessStruct(ctx.mem, NodeStruct, pred).w_s("ln_Succ", succ)
    AccessStruct(ctx.mem, NodeStruct, succ).w_s("ln_Pred", pred)
    log_exec.info("RemTail(%06x): %06x" % (list_addr, node_addr))
    return node_addr

  def FindName(self, ctx):
    list_addr = ctx.cpu.r_reg(REG_A0)
    name_ptr = ctx.cpu.r_reg(REG_A1)
    name = ctx.mem.r_cstr(name_ptr)
    list_t = List(ctx.mem, list_addr)
    match = list_t.find_name(name)
    log_exec.info("FindName: start=%s, name='%s' -> match=%s",
                  list_t, name, match)
    if match:
      return match.get_addr()
    else:
      return 0

  def CopyMem(self, ctx):
    source = ctx.cpu.r_reg(REG_A0)
    dest   = ctx.cpu.r_reg(REG_A1)
    length = ctx.cpu.r_reg(REG_D0)
    log_exec.info("CopyMem: source=%06x dest=%06x len=%06x" % (source,dest,length))
    ctx.mem.copy_block(source, dest, length)

  def CopyMemQuick(self, ctx):
    source = ctx.cpu.r_reg(REG_A0)
    dest   = ctx.cpu.r_reg(REG_A1)
    length = ctx.cpu.r_reg(REG_D0)
    log_exec.info("CopyMemQuick: source=%06x dest=%06x len=%06x" % (source,dest,length))
    ctx.mem.copy_block(source, dest, length)

  def TypeOfMem(self, ctx):
    addr = ctx.cpu.r_reg(REG_A1)
    log_exec.info("TypeOfMem: source=%06x -> %s" % (addr,self.alloc.is_valid_address(addr)))
    if self.alloc.is_valid_address(addr):
      return 1 #MEMF_PUBLIC
    return 0

  def CacheClearU(self, ctx):
    return 0

  def RawDoFmt(self, ctx):
    fmtString  = ctx.cpu.r_reg(REG_A0)
    dataStream = ctx.cpu.r_reg(REG_A1)
    putProc    = ctx.cpu.r_reg(REG_A2)
    putData    = ctx.cpu.r_reg(REG_A3)
    dataStream, fmt, resultstr, known = raw_do_fmt(ctx, fmtString, dataStream,
                                                   putProc, putData)
    log_exec.info("RawDoFmt: fmtString=%s -> %s (known=%s, dataStream=%06x)" % \
        (fmt, resultstr, known, dataStream))
    return dataStream

  # ----- Semaphore Handling -----

  def InitSemaphore(self,ctx):
    addr = ctx.cpu.r_reg(REG_A0)
    self.semaphore_mgr.InitSemaphore(addr)
    log_exec.info("InitSemaphore(%06x)" % addr)

  def AddSemaphore(self,ctx):
    addr     = ctx.cpu.r_reg(REG_A1)
    sstruct  = AccessStruct(ctx.mem,SignalSemaphoreStruct,addr)
    name_ptr = sstruct.r_s("ss_Link.ln_Name")
    name     = ctx.mem.r_cstr(name_ptr)
    self.semaphore_mgr.AddSemaphore(addr,name)
    log_exec.info("AddSemaphore(%06x,%s)" % (addr,name))

  def RemSemaphore(self,ctx):
    addr = ctx.cpu.r_reg(REG_A1)
    self.semaphore_mgr.RemSemaphore(addr)
    log_exec.info("RemSemaphore(%06x)" % addr)

  def FindSemaphore(self,ctx):
    name_ptr = ctx.cpu.r_reg(REG_A1)
    name     = ctx.mem.r_cstr(name_ptr)
    semaphore = self.semaphore_mgr.FindSemaphore(name)
    log_exec.info("FindSemaphore(%s) -> %s" % (name,semaphore))
    if semaphore != None:
      return semaphore.addr
    else:
      return 0

  def ObtainSemaphore(self,ctx):
    addr = ctx.cpu.r_reg(REG_A0)
    # nop for now
    log_exec.info("ObtainSemaphore(%06x) ignored" % addr)

  def ObtainSemaphoreShared(self,ctx):
    addr = ctx.cpu.r_reg(REG_A0)
    # nop for now
    log_exec.info("ObtainSemaphoreShared(%06x) ignored" % addr)

  def AttemptSemaphore(self,ctx):
    addr = ctx.cpu.r_reg(REG_A0)
    # nop for now
    log_exec.info("AttemptSemaphore(%06x) ignored" % addr)
    return 1

  def ReleaseSemaphore(self,ctx):
    addr = ctx.cpu.r_reg(REG_A0)
    # nop for now
    log_exec.info("ReleaseSemaphore(%06x) ignored" % addr)


  # ----- Resources -----

  def OpenResource(self,ctx):
    name_ptr = ctx.cpu.r_reg(REG_A1)
    name     = ctx.mem.r_cstr(name_ptr)
    log_exec.info("OpenResource(%s) ignored" % name)
    return 0


  # ----- Allocate/Deallocate -----

  def Allocate(self,ctx):
    mh_addr = ctx.cpu.r_reg(REG_A0)
    num_bytes = ctx.cpu.r_reg(REG_D0)
    blk_addr = lexec.Alloc.allocate(ctx, mh_addr, num_bytes)
    log_exec.info("Allocate(%06x, %06x) -> %06x" % (mh_addr, num_bytes, blk_addr))
    return blk_addr

  def Deallocate(self,ctx):
    mh_addr = ctx.cpu.r_reg(REG_A0)
    blk_addr = ctx.cpu.r_reg(REG_A1)
    num_bytes = ctx.cpu.r_reg(REG_D0)
    lexec.Alloc.deallocate(ctx, mh_addr, blk_addr, num_bytes)
    log_exec.info("Deallocate(%06x, %06x, %06x)" % (mh_addr, blk_addr, num_bytes))
예제 #3
0
class ExecLibrary(LibImpl):

  def get_struct_def(self):
    return ExecLibraryStruct

  def is_base_lib(self):
    return True

  def setup_lib(self, ctx, base_addr):
    log_exec.info("setup exec.library")
    self.lib_mgr = ctx.lib_mgr
    self.alloc = ctx.alloc
    self._pools = {}
    self._poolid = 0x1000
    self.access = AccessStruct(ctx.mem, self.get_struct_def(), base_addr)
    # set some system contants
    if ctx.cpu_type == '68030':
      self.access.w_s("AttnFlags",7)
    elif ctx.cpu_type == '68020':
      self.access.w_s("AttnFlags",3)
    else:
      self.access.w_s("AttnFlags",0)
    self.access.w_s("MaxLocMem", ctx.ram_size)
    # create the port manager
    self.port_mgr = PortManager(ctx.alloc)
    self.semaphore_mgr = SemaphoreManager(ctx.alloc,ctx.mem)
    self.mem      = ctx.mem

  def set_this_task(self, process):
    self.access.w_s("ThisTask",process.this_task.addr)
    self.stk_lower = process.stack_base
    self.stk_upper = process.stack_end

  # helper

  def get_callee_pc(self,ctx):
    """a call stub log helper to extract the callee's pc"""
    sp = ctx.cpu.r_reg(REG_A7)
    return ctx.mem.r32(sp)

  # ----- System -----

  def Disable(self, ctx):
    log_exec.info("Disable")
  def Enable(self, ctx):
    log_exec.info("Enable")
  def Forbid(self, ctx):
    log_exec.info("Forbid")
  def Permit(self, ctx):
    log_exec.info("Permit")

  def FindTask(self, ctx):
    task_ptr = ctx.cpu.r_reg(REG_A1)
    if task_ptr == 0:
      addr = self.access.r_s("ThisTask")
      log_exec.info("FindTask: me=%06x" % addr)
      return addr
    else:
      task_name = ctx.mem.r_cstr(task_ptr)
      log_exec.info("Find Task: %s" % task_name)
      raise UnsupportedFeatureError("FindTask: other task!");

  def SetSignal(self, ctx):
    new_signals = ctx.cpu.r_reg(REG_D0)
    signal_mask = ctx.cpu.r_reg(REG_D1)
    old_signals = 0
    log_exec.info("SetSignals: new_signals=%08x signal_mask=%08x old_signals=%08x" % (new_signals, signal_mask, old_signals))
    return old_signals

  def StackSwap(self, ctx):
    stsw_ptr = ctx.cpu.r_reg(REG_A0)
    stsw = AccessStruct(ctx.mem,StackSwapStruct,struct_addr=stsw_ptr)
    # get new stack values
    new_lower = stsw.r_s('stk_Lower')
    new_upper = stsw.r_s('stk_Upper')
    new_pointer = stsw.r_s('stk_Pointer')
    # retrieve current (old) stack
    old_lower = self.stk_lower
    old_upper = self.stk_upper
    old_pointer = ctx.cpu.r_reg(REG_A7) # addr of sys call return
    # get adress of callee
    callee = ctx.mem.r32(old_pointer)
    # is a label attached to new addr
    label = ctx.label_mgr.get_label(new_lower)
    if label is not None:
      label.name = label.name + "=Stack"
    # we report the old stack befor callee
    old_pointer += 4
    log_exec.info("StackSwap: old(lower=%06x,upper=%06x,ptr=%06x) new(lower=%06x,upper=%06x,ptr=%06x)" % (old_lower,old_upper,old_pointer,new_lower,new_upper,new_pointer))
    stsw.w_s('stk_Lower', old_lower)
    stsw.w_s('stk_Upper', old_upper)
    stsw.w_s('stk_Pointer', old_pointer)
    self.stk_lower = new_lower
    self.stk_upper = new_upper
    # put callee's address on new stack
    new_pointer -= 4
    ctx.mem.w32(new_pointer,callee)
    # activate new stack
    ctx.cpu.w_reg(REG_A7, new_pointer)

  # ----- Libraries -----

  def OpenLibrary(self, ctx):
    ver = ctx.cpu.r_reg(REG_D0)
    name_ptr = ctx.cpu.r_reg(REG_A1)
    name = ctx.mem.r_cstr(name_ptr)
    addr = self.lib_mgr.open_lib(name, ver)
    log_exec.info("OpenLibrary: '%s' V%d -> %06x", name, ver, addr)
    return addr

  def TaggedOpenLibrary(self, ctx):
    tag = ctx.cpu.r_reg(REG_D0)
    tags = ["graphics.library","layers.library","intuition.library","dos.library","icon.library","expansion.library",
            "utility.library","keymap.library","gadtools.library","workbench.library"]
    if tag > 0 and tag <= len(tags):
      name = tags[tag - 1]
      addr = self.lib_mgr.open_lib(name, 0)
      log_exec.info("TaggedOpenLibrary: %d('%s') -> %06x", tag, name, addr)
      return addr
    else:
      log_exec.warn("TaggedOpenLibrary: %d invalid tag -> NULL" % tag)
      return 0

  def OldOpenLibrary(self, ctx):
    name_ptr = ctx.cpu.r_reg(REG_A1)
    name = ctx.mem.r_cstr(name_ptr)
    addr = self.lib_mgr.open_lib(name, 0)
    log_exec.info("OldOpenLibrary: '%s' -> %06x", name, addr)
    return addr

  def CloseLibrary(self, ctx):
    lib_addr = ctx.cpu.r_reg(REG_A1)
    if lib_addr != 0:
      log_exec.info("CloseLibrary: %06x", lib_addr)
      self.lib_mgr.close_lib(lib_addr)

  def FindResident(self, ctx):
    name_ptr = ctx.cpu.r_reg(REG_A1)
    name = ctx.mem.r_cstr(name_ptr)
    log_exec.info("FindResident: '%s'" % (name))
    return 0

  def CreatePool(self, ctx):
    # need some sort of uniq id.
    # HACK: this is a hack to produce private uniq ids
    poolid = self._poolid
    self._poolid += 4;
    flags  = ctx.cpu.r_reg(REG_D0);
    size   = (ctx.cpu.r_reg(REG_D1) + 7) & -8;
    thresh = ctx.cpu.r_reg(REG_D2)
    pool   = Pool(self.mem, self.alloc, flags, size, thresh, poolid)
    self._pools[poolid] = pool
    log_exec.info("CreatePool: pool 0x%x" % poolid)
    return poolid

  def AllocPooled(self, ctx):
    poolid = ctx.cpu.r_reg(REG_A0)
    size   = (ctx.cpu.r_reg(REG_D0) + 7) & -8
    pc     = self.get_callee_pc(ctx)
    name   = "AllocPooled(%06x)" % pc
    if poolid in self._pools:
      pool = self._pools[poolid]
      mem = pool.AllocPooled(ctx.label_mgr ,name, size)
      log_exec.info("AllocPooled: from pool 0x%x size %d -> 0x%06x" % (poolid,size,mem.addr))
      return mem.addr
    else:
      raise VamosInternalError("AllocPooled: invalid memory pool: ptr=%06x" % poolid)

  def FreePooled(self, ctx):
    poolid = ctx.cpu.r_reg(REG_A0)
    size   = (ctx.cpu.r_reg(REG_D0) + 7) & -8
    mem_ptr= ctx.cpu.r_reg(REG_A1)
    if poolid in self._pools:
      pool   = self._pools[poolid]
      pool.FreePooled(mem_ptr,size)
      log_exec.info("FreePooled: to pool 0x%x mem 0x%06x size %d" % (poolid,mem_ptr,size))
    else:
      raise VamosInternalError("FreePooled: invalid memory pool: ptr=%06x" % poolid)

  def DeletePool(self, ctx):
    log_exec.info("DeletePool")
    poolid = ctx.cpu.r_reg(REG_A0)
    if poolid in self._pools:
      pool = self._pools[poolid]
      del self._pools[poolid]
      pool.__del__()
      log_exec.info("DeletePooled: pool 0x%x" % poolid)
    else:
      raise VamosInternalError("DeletePooled: invalid memory pool: ptr=%06x" % poolid)


  # ----- Memory Handling -----

  def AllocMem(self, ctx):
    size = ctx.cpu.r_reg(REG_D0)
    flags = ctx.cpu.r_reg(REG_D1)
    # label alloc
    pc = self.get_callee_pc(ctx)
    name = "AllocMem(%06x)" % pc
    mb = self.alloc.alloc_memory(name,size)
    log_exec.info("AllocMem: %s -> 0x%06x %d bytes" % (mb,mb.addr,size))
    return mb.addr

  def FreeMem(self, ctx):
    size = ctx.cpu.r_reg(REG_D0)
    addr = ctx.cpu.r_reg(REG_A1)
    if addr == 0 or size == 0:
      log_exec.info("FreeMem: freeing NULL")
      return
    mb = self.alloc.get_memory(addr)
    if mb != None:
      log_exec.info("FreeMem: 0x%06x %d bytes -> %s" % (addr,size,mb))
      self.alloc.free_memory(mb)
    else:
      raise VamosInternalError("FreeMem: Unknown memory to free: ptr=%06x size=%06x" % (addr, size))

  def AllocVec(self, ctx):
    size = ctx.cpu.r_reg(REG_D0)
    flags = ctx.cpu.r_reg(REG_D1)
    mb = self.alloc.alloc_memory("AllocVec(@%06x)" % self.get_callee_pc(ctx),size)
    log_exec.info("AllocVec: %s" % mb)
    return mb.addr

  def FreeVec(self, ctx):
    addr = ctx.cpu.r_reg(REG_A1)
    if addr == 0:
      log_exec.info("FreeVec: freeing NULL")
      return
    mb = self.alloc.get_memory(addr)
    if mb != None:
      log_exec.info("FreeVec: %s" % mb)
      self.alloc.free_memory(mb)
    else:
      raise VamosInternalError("FreeVec: Unknown memory to free: ptr=%06x" % (addr))

  def AvailMem(self, ctx):
    reqments = ctx.cpu.r_reg(REG_D1)
    if reqments & 2:
      return 0 # no chip memory
    if reqments & (1<<17):
      return self.alloc.largest_chunk()
    elif reqments & (1<<19):
      return self.alloc.total()
    else:
      return self.alloc.available()


  # ----- Message Passing -----

  def PutMsg(self, ctx):
    port_addr = ctx.cpu.r_reg(REG_A0)
    msg_addr = ctx.cpu.r_reg(REG_A1)
    log_exec.info("PutMsg: port=%06x msg=%06x" % (port_addr, msg_addr))
    has_port = self.port_mgr.has_port(port_addr)
    if not has_port:
      raise VamosInternalError("PutMsg: on invalid Port (%06x) called!" % port_addr)
    self.port_mgr.put_msg(port_addr, msg_addr)

  def GetMsg(self, ctx):
    port_addr = ctx.cpu.r_reg(REG_A0)
    log_exec.info("GetMsg: port=%06x" % (port_addr))
    has_port = self.port_mgr.has_port(port_addr)
    if not has_port:
      raise VamosInternalError("GetMsg: on invalid Port (%06x) called!" % port_addr)
    msg_addr = self.port_mgr.get_msg(port_addr)
    if msg_addr != None:
      log_exec.info("GetMsg: got message %06x" % (msg_addr))
      return msg_addr
    else:
      log_exec.info("GetMsg: no message available!")
      return 0

  def CreateMsgPort(self, ctx):
    port = self.port_mgr.create_port("exec_port",None)
    log_exec.info("CreateMsgPort: -> port=%06x" % (port))
    return port

  def DeleteMsgPort(self, ctx):
    port = ctx.cpu.r_reg(REG_A0)
    log_exec.info("DeleteMsgPort(%06x)" % port)
    self.port_mgr.free_port(port)
    return 0

  def CreateIORequest(self,ctx):
    port = ctx.cpu.r_reg(REG_A0)
    size = ctx.cpu.r_reg(REG_D0)
    # label alloc
    pc   = self.get_callee_pc(ctx)
    name = "CreateIORequest(%06x)" % pc
    mb   = self.alloc.alloc_memory(name,size)
    log_exec.info("CreateIORequest: (%s,%s,%s) -> 0x%06x %d bytes" % (mb,port,size,mb.addr,size))
    return mb.addr

  def DeleteIORequest(self,ctx):
    req = ctx.cpu.r_reg(REG_A0)
    mb  = self.alloc.get_memory(req)
    if mb != None:
      log_exec.info("DeleteIOREquest: 0x%06x -> %s" % (req,mb))
      self.alloc.free_memory(mb)
    else:
      raise VamosInternalError("DeleteIORequest: Unknown IORequest to delete: ptr=%06x" % addr)

  def OpenDevice(self,ctx):
    name_ptr = ctx.cpu.r_reg(REG_A0)
    unit     = ctx.cpu.r_reg(REG_D0)
    io_addr  = ctx.cpu.r_reg(REG_A1)
    io       = AccessStruct(ctx.mem, IORequestStruct, io_addr)
    flags    = ctx.cpu.r_reg(REG_D1)
    name     = ctx.mem.r_cstr(name_ptr)
    addr     = self.lib_mgr.open_dev(name, unit, flags, io)
    if addr == 0:
      log_exec.info("OpenDevice: '%s' unit %d flags %d -> NULL", name, unit, flags)
      return -1
    else:
      log_exec.info("OpenDevice: '%s' unit %d flags %d -> %06x", name, unit, flags, addr)
      return 0

  def CloseDevice(self,ctx):
    io_addr  = ctx.cpu.r_reg(REG_A1)
    if io_addr != 0:
      io       = AccessStruct(ctx.mem, IORequestStruct, io_addr)
      dev_addr = io.r_s("io_Device")
      if dev_addr != 0:
        log_exec.info("CloseDevice: %06x", dev_addr)
        self.lib_mgr.close_dev(dev_addr)
        io.w_s("io_Device", 0)

  def WaitPort(self, ctx):
    port_addr = ctx.cpu.r_reg(REG_A0)
    log_exec.info("WaitPort: port=%06x" % (port_addr))
    has_port = self.port_mgr.has_port(port_addr)
    if not has_port:
      raise VamosInternalError("WaitPort: on invalid Port (%06x) called!" % port_addr)
    has_msg = self.port_mgr.has_msg(port_addr)
    if not has_msg:
      raise UnsupportedFeatureError("WaitPort on empty message queue called: Port (%06x)" % port_addr)
    msg_addr = self.port_mgr.get_msg(port_addr)
    log_exec.info("WaitPort: got message %06x" % (msg_addr))
    return msg_addr

  def AddTail(self, ctx):
    list_addr = ctx.cpu.r_reg(REG_A0)
    node_addr = ctx.cpu.r_reg(REG_A1)
    log_exec.info("AddTail(%06x, %06x)" % (list_addr, node_addr))
    l = AccessStruct(ctx.mem, ListStruct, list_addr)
    n = AccessStruct(ctx.mem, NodeStruct, node_addr)
    n.w_s("ln_Succ", l.s_get_addr("lh_Tail"))
    tp = l.r_s("lh_TailPred")
    n.w_s("ln_Pred", tp)
    AccessStruct(ctx.mem, NodeStruct, tp).w_s("ln_Succ", node_addr)
    l.w_s("lh_TailPred", node_addr)

  def AddHead(self, ctx):
    list_addr = ctx.cpu.r_reg(REG_A0)
    node_addr = ctx.cpu.r_reg(REG_A1)
    log_exec.info("AddHead(%06x, %06x)" % (list_addr, node_addr))
    l = AccessStruct(ctx.mem, ListStruct, list_addr)
    n = AccessStruct(ctx.mem, NodeStruct, node_addr)
    n.w_s("ln_Pred", l.s_get_addr("lh_Head"))
    h = l.r_s("lh_Head")
    n.w_s("ln_Succ", h)
    AccessStruct(ctx.mem, NodeStruct, h).w_s("ln_Pred", node_addr)
    l.w_s("lh_Head", node_addr)

  def Remove(self, ctx):
    node_addr = ctx.cpu.r_reg(REG_A1)
    n = AccessStruct(ctx.mem, NodeStruct, node_addr)
    succ = n.r_s("ln_Succ")
    pred = n.r_s("ln_Pred")
    log_exec.info("Remove(%06x): ln_Pred=%06x ln_Succ=%06x" % (node_addr, pred, succ))
    AccessStruct(ctx.mem, NodeStruct, pred).w_s("ln_Succ", succ)
    AccessStruct(ctx.mem, NodeStruct, succ).w_s("ln_Pred", pred)
    return node_addr

  def RemHead(self, ctx):
    list_addr = ctx.cpu.r_reg(REG_A0)
    l = AccessStruct(ctx.mem, ListStruct, list_addr)
    node_addr = l.r_s("lh_Head")
    n = AccessStruct(ctx.mem, NodeStruct, node_addr)
    succ = n.r_s("ln_Succ")
    pred = n.r_s("ln_Pred")
    if succ == 0:
      log_exec.info("RemHead(%06x): null" % list_addr)
      return 0
    AccessStruct(ctx.mem, NodeStruct, pred).w_s("ln_Succ", succ)
    AccessStruct(ctx.mem, NodeStruct, succ).w_s("ln_Pred", pred)
    log_exec.info("RemHead(%06x): %06x" % (list_addr, node_addr))
    return node_addr

  def RemTail(self, ctx):
    list_addr = ctx.cpu.r_reg(REG_A0)
    l = AccessStruct(ctx.mem, ListStruct, list_addr)
    node_addr = l.r_s("lh_TailPred")
    n = AccessStruct(ctx.mem, NodeStruct, node_addr)
    succ = n.r_s("ln_Succ")
    pred = n.r_s("ln_Pred")
    if pred == 0:
      log_exec.info("RemTail(%06x): null" % list_addr)
      return 0
    AccessStruct(ctx.mem, NodeStruct, pred).w_s("ln_Succ", succ)
    AccessStruct(ctx.mem, NodeStruct, succ).w_s("ln_Pred", pred)
    log_exec.info("RemTail(%06x): %06x" % (list_addr, node_addr))
    return node_addr

  def CopyMem(self, ctx):
    source = ctx.cpu.r_reg(REG_A0)
    dest   = ctx.cpu.r_reg(REG_A1)
    length = ctx.cpu.r_reg(REG_D0)
    log_exec.info("CopyMem: source=%06x dest=%06x len=%06x" % (source,dest,length))
    ctx.mem.copy_block(source, dest, length)

  def CopyMemQuick(self, ctx):
    source = ctx.cpu.r_reg(REG_A0)
    dest   = ctx.cpu.r_reg(REG_A1)
    length = ctx.cpu.r_reg(REG_D0)
    log_exec.info("CopyMemQuick: source=%06x dest=%06x len=%06x" % (source,dest,length))
    ctx.mem.copy_block(source, dest, length)

  def TypeOfMem(self, ctx):
    addr = ctx.cpu.r_reg(REG_A1)
    log_exec.info("TypeOfMem: source=%06x -> %s" % (addr,self.alloc.is_valid_address(addr)))
    if self.alloc.is_valid_address(addr):
      return 1 #MEMF_PUBLIC
    return 0

  def CacheClearU(self, ctx):
    return 0

  def RawDoFmt(self, ctx):
    fmtString  = ctx.cpu.r_reg(REG_A0)
    dataStream = ctx.cpu.r_reg(REG_A1)
    putProc    = ctx.cpu.r_reg(REG_A2)
    putData    = ctx.cpu.r_reg(REG_A3)
    fmt        = ctx.mem.r_cstr(fmtString)
    ps         = dos.Printf.printf_parse_string(fmt)
    dataStream = dos.Printf.printf_read_data(ps, ctx.mem, dataStream)
    resultstr  = dos.Printf.printf_generate_output(ps)
    fmtstr     = resultstr+"\0"
    # Try to use a shortcut to avoid an unnecessary slow-down
    known      = False
    putcode    = ctx.mem.r32(putProc)
    if putcode == 0x16c04e75:
      known    = True
    elif putcode == 0x4e55fffc: #link #-4,a5
      putcode2 = ctx.mem.r32(putProc+4)
      putcode3 = ctx.mem.r32(putProc+8)
      putcode4 = ctx.mem.r16(putProc+12)
      if putcode2 == 0x2b40fffc and putcode3 == 0x16c04e5d and putcode4 == 0x4e75:
        known = True
    if known:
      ctx.mem.w_cstr(putData,fmtstr)
    else:
      # This is a recursive trampoline that writes the formatted data through
      # the put-proc. Unfortunately, this is pretty convoluted.
      def _make_trampoline(fmtstr,olda3,newa3,ctx):
        if len(fmtstr) > 0:
          tr = Trampoline(ctx,"RawDoFmt")
          tr.set_dx_l(0,ord(fmtstr[0:1]))
          tr.set_ax_l(2,putProc)
          tr.set_ax_l(3,newa3)
          tr.jsr(putProc)
          def _done_func():
            a3 = ctx.cpu.r_reg(REG_A3)
            _make_trampoline(fmtstr[1:],olda3,a3,ctx)
          tr.final_rts(_done_func)
          tr.done()
        else:
          ctx.cpu.w_reg(REG_A3,olda3)
      _make_trampoline(fmtstr,putData,putData,ctx)
    log_exec.info("RawDoFmt: fmtString=%s -> %s" % (fmt,resultstr))
    return dataStream

  # ----- Semaphore Handling -----

  def InitSemaphore(self,ctx):
    addr = ctx.cpu.r_reg(REG_A0)
    self.semaphore_mgr.InitSemaphore(addr)
    log_exec.info("InitSemaphore(%06x)" % addr)

  def AddSemaphore(self,ctx):
    addr     = ctx.cpu.r_reg(REG_A1)
    sstruct  = AccessStruct(ctx.mem,SignalSemaphoreStruct,addr)
    name_ptr = sstruct.r_s("ss_Link.ln_Name")
    name     = ctx.mem.r_cstr(name_ptr)
    self.semaphore_mgr.AddSemaphore(addr,name)
    log_exec.info("AddSemaphore(%06x,%s)" % (addr,name))

  def RemSemaphore(self,ctx):
    addr = ctx.cpu.r_reg(REG_A1)
    self.semaphore_mgr.RemSemaphore(addr)
    log_exec.info("RemSemaphore(%06x)" % addr)

  def FindSemaphore(self,ctx):
    name_ptr = ctx.cpu.r_reg(REG_A1)
    name     = ctx.mem.r_cstr(name_ptr)
    semaphore = self.semaphore_mgr.FindSemaphore(name)
    log_exec.info("FindSemaphore(%s) -> %s" % (name,semaphore))
    if semaphore != None:
      return semaphore.addr
    else:
      return 0

  def ObtainSemaphore(self,ctx):
    addr = ctx.cpu.r_reg(REG_A0)
    # nop for now
    log_exec.info("ObtainSemaphore(%06x) ignored" % addr)

  def ReleaseSemaphore(self,ctx):
    addr = ctx.cpu.r_reg(REG_A0)
    # nop for now
    log_exec.info("ReleaseSemaphore(%06x) ignored" % addr)


  # ----- Resources -----

  def OpenResource(self,ctx):
    name_ptr = ctx.cpu.r_reg(REG_A1)
    name     = ctx.mem.r_cstr(name_ptr)
    log_exec.info("OpenResource(%s) ignored" % name)
    return 0


  # ----- Allocate/Deallocate -----

  def Allocate(self,ctx):
    mh_addr = ctx.cpu.r_reg(REG_A0)
    num_bytes = ctx.cpu.r_reg(REG_D0)
    blk_addr = lexec.Alloc.allocate(ctx, mh_addr, num_bytes)
    log_exec.info("Allocate(%06x, %06x) -> %06x" % (mh_addr, num_bytes, blk_addr))
    return blk_addr

  def Deallocate(self,ctx):
    mh_addr = ctx.cpu.r_reg(REG_A0)
    blk_addr = ctx.cpu.r_reg(REG_A1)
    num_bytes = ctx.cpu.r_reg(REG_D0)
    lexec.Alloc.deallocate(ctx, mh_addr, blk_addr, num_bytes)
    log_exec.info("Deallocate(%06x, %06x, %06x)" % (mh_addr, blk_addr, num_bytes))
예제 #4
0
class ExecLibrary(AmigaLibrary):
  name = "exec.library"
  _pools = {}
  _poolid = 0x1000

  def __init__(self, lib_mgr, alloc, config):
    AmigaLibrary.__init__(self, self.name, ExecLibraryDef, config)
    log_exec.info("open exec.library V%d", self.version)
    self.lib_mgr = lib_mgr
    self.alloc = alloc
    self._pools = {}
    self._poolid = 0x1000

  def setup_lib(self, ctx):
    AmigaLibrary.setup_lib(self, ctx)
    # set some system contants
    if ctx.cpu_type == '68020':
      self.access.w_s("AttnFlags",2)
    else:
      self.access.w_s("AttnFlags",0)
    self.access.w_s("MaxLocMem", ctx.ram_size)
    # create the port manager
    self.port_mgr = PortManager(ctx.alloc)
    self.semaphore_mgr = SemaphoreManager(ctx.alloc,ctx.mem)
    self.mem      = ctx.mem

  def finish_lib(self, ctx):
    pass

  def set_this_task(self, process):
    self.access.w_s("ThisTask",process.this_task.addr)
    self.stk_lower = process.stack_base
    self.stk_upper = process.stack_end

  # ----- System -----

  def Disable(self, ctx):
    log_exec.info("Disable")
  def Enable(self, ctx):
    log_exec.info("Enable")
  def Forbid(self, ctx):
    log_exec.info("Forbid")
  def Permit(self, ctx):
    log_exec.info("Permit")

  def FindTask(self, ctx):
    task_ptr = ctx.cpu.r_reg(REG_A1)
    if task_ptr == 0:
      addr = self.access.r_s("ThisTask")
      log_exec.info("FindTask: me=%06x" % addr)
      return addr
    else:
      task_name = ctx.mem.access.r_cstr(task_ptr)
      log_exec.info("Find Task: %s" % task_name)
      raise UnsupportedFeatureError("FindTask: other task!");

  def SetSignal(self, ctx):
    new_signals = ctx.cpu.r_reg(REG_D0)
    signal_mask = ctx.cpu.r_reg(REG_D1)
    old_signals = 0
    log_exec.info("SetSignals: new_signals=%08x signal_mask=%08x old_signals=%08x" % (new_signals, signal_mask, old_signals))
    return old_signals

  def StackSwap(self, ctx):
    stsw_ptr = ctx.cpu.r_reg(REG_A0)
    stsw = AccessStruct(ctx.mem,StackSwapDef,struct_addr=stsw_ptr)
    # get new stack values
    new_lower = stsw.r_s('stk_Lower')
    new_upper = stsw.r_s('stk_Upper')
    new_pointer = stsw.r_s('stk_Pointer')
    # retrieve current (old) stack
    old_lower = self.stk_lower
    old_upper = self.stk_upper
    old_pointer = ctx.cpu.r_reg(REG_A7) # addr of sys call return
    # get adress of callee
    callee = ctx.mem.access.r32(old_pointer)
    # is a label attached to new addr
    label = ctx.label_mgr.get_label(new_lower)
    if label is not None:
      label.name = label.name + "=Stack"
    # we report the old stack befor callee
    old_pointer += 4
    log_exec.info("StackSwap: old(lower=%06x,upper=%06x,ptr=%06x) new(lower=%06x,upper=%06x,ptr=%06x)" % (old_lower,old_upper,old_pointer,new_lower,new_upper,new_pointer))
    stsw.w_s('stk_Lower', old_lower)
    stsw.w_s('stk_Upper', old_upper)
    stsw.w_s('stk_Pointer', old_pointer)
    self.stk_lower = new_lower
    self.stk_upper = new_upper
    # put callee's address on new stack
    new_pointer -= 4
    ctx.mem.access.w32(new_pointer,callee)
    # activate new stack
    ctx.cpu.w_reg(REG_A7, new_pointer)

  # ----- Libraries -----

  def OpenLibrary(self, ctx):
    ver = ctx.cpu.r_reg(REG_D0)
    name_ptr = ctx.cpu.r_reg(REG_A1)
    name = ctx.mem.access.r_cstr(name_ptr)
    lib = self.lib_mgr.open_lib(name, ver, ctx)
    if lib == None:
      log_exec.info("OpenLibrary: '%s' V%d -> NULL" % (name, ver))
      return 0
    else:
      log_exec.info("OpenLibrary: '%s' V%d -> %s@0x%06x" % (name, ver, lib, lib.addr_base_open))
      return lib.addr_base_open

  def TaggedOpenLibrary(self, ctx):
    tag = ctx.cpu.r_reg(REG_D0)
    tags = ["graphics.library","layers.library","intuition.library","dos.library","icon.library","expansion.library",
            "utility.library","keymap.library","gadtools.library","workbench.library"]
    if tag > 0 and tag <= len(tags):
      name = tags[tag - 1]
      lib  = self.lib_mgr.open_lib(name, 0, ctx)
      if lib == None:
        log_exec.info("TaggedOpenLibrary: %d('%s') -> NULL" % (tag, name))
        return 0
      else:
        log_exec.info("TaggedOpenLibrary: %d('%s') -> %s@0x%06x" % (tag, name, lib, lib.addr_base_open))
        return lib.addr_base_open
    else:
      log_exec.warn("TaggedOpenLibrary: %d invalid tag -> NULL" % tag)
      return 0

  def OldOpenLibrary(self, ctx):
    name_ptr = ctx.cpu.r_reg(REG_A1)
    name = ctx.mem.access.r_cstr(name_ptr)
    lib = self.lib_mgr.open_lib(name, 0, ctx)
    log_exec.info("OldOpenLibrary: '%s' -> %s" % (name, lib))
    return lib.addr_base_open

  def CloseLibrary(self, ctx):
    lib_addr = ctx.cpu.r_reg(REG_A1)
    if lib_addr != 0:
      lib = self.lib_mgr.close_lib(lib_addr,ctx)
      if lib != None:
        log_exec.info("CloseLibrary: '%s' -> %06x" % (lib, lib.addr_base))
      else:
        raise VamosInternalError("CloseLibrary: Unknown library to close: ptr=%06x" % lib_addr)

  def FindResident(self, ctx):
    name_ptr = ctx.cpu.r_reg(REG_A1)
    name = ctx.mem.access.r_cstr(name_ptr)
    log_exec.info("FindResident: '%s'" % (name))
    return 0

  def CreatePool(self, ctx):
    # need some sort of uniq id.
    # HACK: this is a hack to produce private uniq ids
    poolid = self._poolid
    self._poolid += 4;
    flags  = ctx.cpu.r_reg(REG_D0);
    size   = (ctx.cpu.r_reg(REG_D1) + 7) & -8;
    thresh = ctx.cpu.r_reg(REG_D2)
    pool   = Pool(self.mem, self.alloc, flags, size, thresh, poolid)
    self._pools[poolid] = pool
    log_exec.info("CreatePool: pool 0x%x" % poolid)
    return poolid

  def AllocPooled(self, ctx):
    poolid = ctx.cpu.r_reg(REG_A0)
    size   = (ctx.cpu.r_reg(REG_D0) + 7) & -8
    pc     = self.get_callee_pc(ctx)
    tag    = ctx.label_mgr.get_mem_str(pc)
    name   = "AllocPooled(%06x = %s)" % (pc,tag)
    if poolid in self._pools:
      pool = self._pools[poolid]
      mem = pool.AllocPooled(ctx.label_mgr ,name, size)
      log_exec.info("AllocPooled: from pool 0x%x size %d -> 0x%06x" % (poolid,size,mem.addr))
      return mem.addr
    else:
      raise VamosInternalError("AllocPooled: invalid memory pool: ptr=%06x" % poolid)

  def FreePooled(self, ctx):
    poolid = ctx.cpu.r_reg(REG_A0)
    size   = (ctx.cpu.r_reg(REG_D0) + 7) & -8
    mem_ptr= ctx.cpu.r_reg(REG_A1)
    if poolid in self._pools:
      pool   = self._pools[poolid]
      pool.FreePooled(mem_ptr,size)
      log_exec.info("FreePooled: to pool 0x%x mem 0x%06x size %d" % (poolid,mem_ptr,size))
    else:
      raise VamosInternalError("FreePooled: invalid memory pool: ptr=%06x" % poolid)

  def DeletePool(self, ctx):
    log_exec.info("DeletePool")
    poolid = ctx.cpu.r_reg(REG_A0)
    if poolid in self._pools:
      pool = self._pools[poolid]
      del self._pools[poolid]
      pool.__del__()
      log_exec.info("DeletePooled: pool 0x%x" % poolid)
    else:
      raise VamosInternalError("DeletePooled: invalid memory pool: ptr=%06x" % poolid)


  # ----- Memory Handling -----

  def AllocMem(self, ctx):
    size = ctx.cpu.r_reg(REG_D0)
    flags = ctx.cpu.r_reg(REG_D1)
    # label alloc
    pc = self.get_callee_pc(ctx)
    tag = ctx.label_mgr.get_mem_str(pc)
    name = "AllocMem(%06x = %s)" % (pc,tag)
    mb = self.alloc.alloc_memory(name,size)
    log_exec.info("AllocMem: %s -> 0x%06x %d bytes" % (mb,mb.addr,size))
    return mb.addr

  def FreeMem(self, ctx):
    size = ctx.cpu.r_reg(REG_D0)
    addr = ctx.cpu.r_reg(REG_A1)
    if addr == 0 or size == 0:
      log_exec.info("FreeMem: freeing NULL")
      return
    mb = self.alloc.get_memory(addr)
    if mb != None:
      log_exec.info("FreeMem: 0x%06x %d bytes -> %s" % (addr,size,mb))
      self.alloc.free_memory(mb)
    else:
      raise VamosInternalError("FreeMem: Unknown memory to free: ptr=%06x size=%06x" % (addr, size))

  def AllocVec(self, ctx):
    size = ctx.cpu.r_reg(REG_D0)
    flags = ctx.cpu.r_reg(REG_D1)
    mb = self.alloc.alloc_memory("AllocVec(@%06x)" % self.get_callee_pc(ctx),size)
    log_exec.info("AllocVec: %s" % mb)
    return mb.addr

  def FreeVec(self, ctx):
    addr = ctx.cpu.r_reg(REG_A1)
    if addr == 0:
      log_exec.info("FreeVec: freeing NULL")
      return
    mb = self.alloc.get_memory(addr)
    if mb != None:
      log_exec.info("FreeVec: %s" % mb)
      self.alloc.free_memory(mb)
    else:
      raise VamosInternalError("FreeVec: Unknown memory to free: ptr=%06x" % (addr))

  def AvailMem(self, ctx):
    reqments = ctx.cpu.r_reg(REG_D1)
    if reqments & 2:
      return 0 # no chip memory
    if reqments & (1<<17):
      return self.alloc.largest_chunk()
    elif reqments & (1<<19):
      return self.alloc.total()
    else:
      return self.alloc.available()
      

  # ----- Message Passing -----

  def PutMsg(self, ctx):
    port_addr = ctx.cpu.r_reg(REG_A0)
    msg_addr = ctx.cpu.r_reg(REG_A1)
    log_exec.info("PutMsg: port=%06x msg=%06x" % (port_addr, msg_addr))
    has_port = self.port_mgr.has_port(port_addr)
    if not has_port:
      raise VamosInternalError("PutMsg: on invalid Port (%06x) called!" % port_addr)
    self.port_mgr.put_msg(port_addr, msg_addr)

  def GetMsg(self, ctx):
    port_addr = ctx.cpu.r_reg(REG_A0)
    log_exec.info("GetMsg: port=%06x" % (port_addr))
    has_port = self.port_mgr.has_port(port_addr)
    if not has_port:
      raise VamosInternalError("GetMsg: on invalid Port (%06x) called!" % port_addr)
    msg_addr = self.port_mgr.get_msg(port_addr)
    if msg_addr != None:
      log_exec.info("GetMsg: got message %06x" % (msg_addr))
      return msg_addr
    else:
      log_exec.info("GetMsg: no message available!")
      return 0

  def CreateMsgPort(self, ctx):
    port = self.port_mgr.create_port("exec_port",None)
    log_exec.info("CreateMsgPort: -> port=%06x" % (port))
    return port

  def DeleteMsgPort(self, ctx):
    port = ctx.cpu.r_reg(REG_A0)
    log_exec.info("DeleteMsgPort(%06x)" % port)
    self.port_mgr.free_port(port)
    return 0

  def CreateIORequest(self,ctx):
    port = ctx.cpu.r_reg(REG_A0)
    size = ctx.cpu.r_reg(REG_D0)
    # label alloc
    pc   = self.get_callee_pc(ctx)
    tag  = ctx.label_mgr.get_mem_str(pc)
    name = "CreateIORequest(%06x = %s)" % (pc,tag)
    mb   = self.alloc.alloc_memory(name,size)
    log_exec.info("CreateIORequest: (%s,%s,%s) -> 0x%06x %d bytes" % (mb,port,size,mb.addr,size))
    return mb.addr

  def DeleteIORequest(self,ctx):
    req = ctx.cpu.r_reg(REG_A0)
    mb  = self.alloc.get_memory(req)
    if mb != None:
      log_exec.info("DeleteIOREquest: 0x%06x -> %s" % (req,mb))
      self.alloc.free_memory(mb)
    else:
      raise VamosInternalError("DeleteIORequest: Unknown IORequest to delete: ptr=%06x" % addr)

  def OpenDevice(self,ctx):
    name_ptr = ctx.cpu.r_reg(REG_A0)
    unit     = ctx.cpu.r_reg(REG_D0)
    io_addr  = ctx.cpu.r_reg(REG_A1)
    io       = AccessStruct(ctx.mem, IORequestDef, io_addr)
    flags    = ctx.cpu.r_reg(REG_D1)
    name     = ctx.mem.access.r_cstr(name_ptr)
    lib      = self.lib_mgr.open_dev(name, unit, flags, io, ctx)
    if lib == None:
      log_exec.info("OpenDevice: '%s' unit %d flags %d -> NULL" % (name, unit, flags))
      return -1
    else:
      log_exec.info("OpenDevice: '%s' unit %d flags %d -> %s@0x%06x" % (name, unit, flags, lib, lib.addr_base_open))
      return 0

  def CloseDevice(self,ctx):
    io_addr  = ctx.cpu.r_reg(REG_A1)
    if io_addr != 0:
      io       = AccessStruct(ctx.mem, IORequestDef, io_addr)
      dev_addr = io.r_s("io_Device")
      if dev_addr != 0:
        dev = self.lib_mgr.close_dev(dev_addr,ctx)
        io.w_s("io_Device",0)
        if dev != None:
          log_exec.info("CloseDevice: '%s' -> %06x" % (dev, dev.addr_base))
        else:
          raise VamosInternalError("CloseDevice: Unknown library to close: ptr=%06x" % dev_addr)

  def WaitPort(self, ctx):
    port_addr = ctx.cpu.r_reg(REG_A0)
    log_exec.info("WaitPort: port=%06x" % (port_addr))
    has_port = self.port_mgr.has_port(port_addr)
    if not has_port:
      raise VamosInternalError("WaitPort: on invalid Port (%06x) called!" % port_addr)
    has_msg = self.port_mgr.has_msg(port_addr)
    if not has_msg:
      raise UnsupportedFeatureError("WaitPort on empty message queue called: Port (%06x)" % port_addr)
    msg_addr = self.port_mgr.get_msg(port_addr)
    log_exec.info("WaitPort: got message %06x" % (msg_addr))
    return msg_addr

  def AddTail(self, ctx):
    list_addr = ctx.cpu.r_reg(REG_A0)
    node_addr = ctx.cpu.r_reg(REG_A1)
    log_exec.info("AddTail(%06x, %06x)" % (list_addr, node_addr))
    l = AccessStruct(ctx.mem, ListDef, list_addr)
    n = AccessStruct(ctx.mem, NodeDef, node_addr)
    n.w_s("ln_Succ", l.s_get_addr("lh_Tail"))
    tp = l.r_s("lh_TailPred")
    n.w_s("ln_Pred", tp)
    AccessStruct(ctx.mem, NodeDef, tp).w_s("ln_Succ", node_addr)
    l.w_s("lh_TailPred", node_addr)

  def AddHead(self, ctx):
    list_addr = ctx.cpu.r_reg(REG_A0)
    node_addr = ctx.cpu.r_reg(REG_A1)
    log_exec.info("AddHead(%06x, %06x)" % (list_addr, node_addr))
    l = AccessStruct(ctx.mem, ListDef, list_addr)
    n = AccessStruct(ctx.mem, NodeDef, node_addr)
    n.w_s("ln_Pred", l.s_get_addr("lh_Head"))
    h = l.r_s("lh_Head")
    n.w_s("ln_Succ", h)
    AccessStruct(ctx.mem, NodeDef, h).w_s("ln_Pred", node_addr)
    l.w_s("lh_Head", node_addr)

  def Remove(self, ctx):
    node_addr = ctx.cpu.r_reg(REG_A1)
    n = AccessStruct(ctx.mem, NodeDef, node_addr)
    succ = n.r_s("ln_Succ")
    pred = n.r_s("ln_Pred")
    log_exec.info("Remove(%06x): ln_Pred=%06x ln_Succ=%06x" % (node_addr, pred, succ))
    AccessStruct(ctx.mem, NodeDef, pred).w_s("ln_Succ", succ)
    AccessStruct(ctx.mem, NodeDef, succ).w_s("ln_Pred", pred)
    return node_addr

  def RemHead(self, ctx):
    list_addr = ctx.cpu.r_reg(REG_A0)
    l = AccessStruct(ctx.mem, ListDef, list_addr)
    node_addr = l.r_s("lh_Head")
    n = AccessStruct(ctx.mem, NodeDef, node_addr)
    succ = n.r_s("ln_Succ")
    pred = n.r_s("ln_Pred")
    if succ == 0:
      log_exec.info("RemHead(%06x): null" % list_addr)
      return 0
    AccessStruct(ctx.mem, NodeDef, pred).w_s("ln_Succ", succ)
    AccessStruct(ctx.mem, NodeDef, succ).w_s("ln_Pred", pred)
    log_exec.info("RemHead(%06x): %06x" % (list_addr, node_addr))
    return node_addr
  
  def RemTail(self, ctx):
    list_addr = ctx.cpu.r_reg(REG_A0)
    l = AccessStruct(ctx.mem, ListDef, list_addr)
    node_addr = l.r_s("lh_TailPred")
    n = AccessStruct(ctx.mem, NodeDef, node_addr)
    succ = n.r_s("ln_Succ")
    pred = n.r_s("ln_Pred")
    if pred == 0:
      log_exec.info("RemTail(%06x): null" % list_addr)
      return 0
    AccessStruct(ctx.mem, NodeDef, pred).w_s("ln_Succ", succ)
    AccessStruct(ctx.mem, NodeDef, succ).w_s("ln_Pred", pred)
    log_exec.info("RemTail(%06x): %06x" % (list_addr, node_addr))
    return node_addr

  def CopyMem(self, ctx):
    source = ctx.cpu.r_reg(REG_A0)
    dest   = ctx.cpu.r_reg(REG_A1)
    length = ctx.cpu.r_reg(REG_D0)
    log_exec.info("CopyMem: source=%06x dest=%06x len=%06x" % (source,dest,length))
    ctx.mem.raw_mem.copy_block(source, dest, length)

  def CopyMemQuick(self, ctx):
    source = ctx.cpu.r_reg(REG_A0)
    dest   = ctx.cpu.r_reg(REG_A1)
    length = ctx.cpu.r_reg(REG_D0)
    log_exec.info("CopyMemQuick: source=%06x dest=%06x len=%06x" % (source,dest,length))
    ctx.mem.raw_mem.copy_block(source, dest, length)

  def TypeOfMem(self, ctx):
    addr = ctx.cpu.r_reg(REG_A1)
    log_exec.info("TypeOfMem: source=%06x -> %s" % (addr,self.alloc.is_valid_address(addr)))
    if self.alloc.is_valid_address(addr):
      return 1 #MEMF_PUBLIC
    return 0

  def CacheClearU(self, ctx):
    return 0

  def RawDoFmt(self, ctx):
    fmtString  = ctx.cpu.r_reg(REG_A0)
    dataStream = ctx.cpu.r_reg(REG_A1)
    putProc    = ctx.cpu.r_reg(REG_A2)
    putData    = ctx.cpu.r_reg(REG_A3)
    fmt        = ctx.mem.access.r_cstr(fmtString)
    ps         = dos.Printf.printf_parse_string(fmt)
    dataStream = dos.Printf.printf_read_data(ps, ctx.mem.access, dataStream)
    resultstr  = dos.Printf.printf_generate_output(ps)
    fmtstr     = resultstr+"\0"
    # Try to use a shortcut to avoid an unnecessary slow-down
    known      = False
    putcode    = ctx.mem.access.r32(putProc)
    if putcode == 0x16c04e75:
      known    = True
    elif putcode == 0x4e55fffc: #link #-4,a5
      putcode2 = ctx.mem.access.r32(putProc+4)
      putcode3 = ctx.mem.access.r32(putProc+8)
      putcode4 = ctx.mem.access.r16(putProc+12)
      if putcode2 == 0x2b40fffc and putcode3 == 0x16c04e5d and putcode4 == 0x4e75:
        known = True
    if known:
      ctx.mem.access.w_cstr(putData,fmtstr)
    else:
      # This is a recursive trampoline that writes the formatted data through
      # the put-proc. Unfortunately, this is pretty convoluted.
      def _make_trampoline(fmtstr,olda3,newa3,ctx):
        if len(fmtstr) > 0:
          tr = Trampoline(ctx,"RawDoFmt")
          tr.set_dx_l(0,ord(fmtstr[0:1]))
          tr.set_ax_l(2,putProc)
          tr.set_ax_l(3,newa3)
          tr.jsr(putProc)
          def _done_func():
            a3 = ctx.cpu.r_reg(REG_A3)
            _make_trampoline(fmtstr[1:],olda3,a3,ctx)
          tr.final_rts(_done_func)
          tr.done()
        else:
          ctx.cpu.w_reg(REG_A3,olda3)
      _make_trampoline(fmtstr,putData,putData,ctx)
    log_exec.info("RawDoFmt: fmtString=%s -> %s" % (fmt,resultstr))
    return dataStream

  # ----- Semaphore Handling -----

  def InitSemaphore(self,ctx):
    addr = ctx.cpu.r_reg(REG_A0)
    self.semaphore_mgr.InitSemaphore(addr)
    log_exec.info("InitSemaphore(%06x)" % addr)
     
  def AddSemaphore(self,ctx):
    addr     = ctx.cpu.r_reg(REG_A1)
    sstruct  = AccessStruct(ctx.mem,SignalSemaphoreDef,addr)
    name_ptr = sstruct.r_s("ss_Link.ln_Name")
    name     = ctx.mem.access.r_cstr(name_ptr)
    self.semaphore_mgr.AddSemaphore(addr,name)
    log_exec.info("AddSemaphore(%06x,%s)" % (addr,name))
     
  def RemSemaphore(self,ctx):
    addr = ctx.cpu.r_reg(REG_A1)
    self.semaphore_mgr.RemSemaphore(addr)
    log_exec.info("RemSemaphore(%06x)" % addr)

  def FindSemaphore(self,ctx):
    name_ptr = ctx.cpu.r_reg(REG_A1)
    name     = ctx.mem.access.r_cstr(name_ptr)
    semaphore = self.semaphore_mgr.FindSemaphore(name)
    log_exec.info("FindSemaphore(%s) -> %s" % (name,semaphore))
    if semaphore != None:
      return semaphore.addr
    else:
      return 0