--- uae/src/execlib.c 2018/04/24 16:38:39 1.1.1.1 +++ uae/src/execlib.c 2018/04/24 16:38:55 1.1.1.2 @@ -6,27 +6,29 @@ * Copyright 1996 Bernd Schmidt */ -#undef USE_EXECLIB - #include "sysconfig.h" #include "sysdeps.h" #include #include -#ifdef USE_EXECLIB -#include -#endif +#include #include "config.h" #include "options.h" +#include "machdep/exectasks.h" +#include "machdep/m68k.h" #include "memory.h" #include "custom.h" +#include "readcpu.h" #include "newcpu.h" #include "xwin.h" #include "autoconf.h" #include "osemu.h" +#include "execlib.h" -static CPTR sysbase; +#ifdef USE_EXECLIB + +CPTR EXEC_sysbase; /* * Exec list management @@ -96,20 +98,17 @@ void EXEC_AddTail(CPTR list, CPTR node) CPTR EXEC_FindName(CPTR start, char *name) { - CPTR node = start; + CPTR node, next; + if (name == NULL) return 0; - for (;;) { + for (node = get_long(start);(next = get_long(node)) != 0; node = next) { CPTR nnp; char *nn; - node = get_long(start); - - if (node == 0) - break; nnp = get_long(node + 10); - if (nnp != 0 && (nn = get_real_address(nnp)) != NULL) + if (nnp != 0 && (nn = raddr(nnp)) != NULL) if (strcmp(nn, name) == 0) return node; start = node; @@ -117,14 +116,14 @@ CPTR EXEC_FindName(CPTR start, char *nam return 0; } -static ULONG execl_Enqueue(void) { EXEC_Enqueue(regs.a[0], regs.a[1]); return 0; } -static ULONG execl_Insert(void) { EXEC_Insert(regs.a[0], regs.a[1], regs.a[2]); return 0; } -static ULONG execl_AddHead(void) { EXEC_Insert(regs.a[0], regs.a[1], 0); return 0; } -static ULONG execl_AddTail(void) { EXEC_Insert(regs.a[0], regs.a[1], get_long(regs.a[0] + 8)); return 0; } -static ULONG execl_Remove(void) { EXEC_Remove(regs.a[1]); return 0; } -static ULONG execl_RemHead(void) { return EXEC_RemHead(regs.a[0]); } -static ULONG execl_RemTail(void) { return EXEC_RemTail(regs.a[0]); } -static ULONG execl_FindName(void) { CPTR n = EXEC_FindName(regs.a[0], get_real_address(regs.a[1])); ZFLG = n == 0; return n; } +static ULONG execl_Enqueue(void) { EXEC_Enqueue(m68k_areg(regs, 0), m68k_areg(regs, 1)); return 0; } +static ULONG execl_Insert(void) { EXEC_Insert(m68k_areg(regs, 0), m68k_areg(regs, 1), m68k_areg(regs, 2)); return 0; } +static ULONG execl_AddHead(void) { EXEC_Insert(m68k_areg(regs, 0), m68k_areg(regs, 1), 0); return 0; } +static ULONG execl_AddTail(void) { EXEC_Insert(m68k_areg(regs, 0), m68k_areg(regs, 1), get_long(m68k_areg(regs, 0) + 8)); return 0; } +static ULONG execl_Remove(void) { EXEC_Remove(m68k_areg(regs, 1)); return 0; } +static ULONG execl_RemHead(void) { return EXEC_RemHead(m68k_areg(regs, 0)); } +static ULONG execl_RemTail(void) { return EXEC_RemTail(m68k_areg(regs, 0)); } +static ULONG execl_FindName(void) { CPTR n = EXEC_FindName(m68k_areg(regs, 0), raddr(m68k_areg(regs, 1))); ZFLG = n == 0; return n; } /* * Miscellaneous @@ -133,7 +132,7 @@ static ULONG execl_FindName(void) { CPTR void EXEC_InitStruct(CPTR inittable, CPTR memory, unsigned long size) { CPTR dptr = memory; - UBYTE *mem = get_real_address(memory); + UBYTE *mem = (UBYTE *)raddr(memory); if (memory == 0 || mem == NULL || !valid_address(memory, size)) { fprintf(stderr, "Foo\n"); return; @@ -193,7 +192,14 @@ void EXEC_InitStruct(CPTR inittable, CPT } } /* The size parameter sometimes seems to contain garbage in the top 16 bit */ -static ULONG execl_InitStruct(void) { EXEC_InitStruct(regs.a[1], regs.a[2], regs.d[0] & 0xFFFF); return 0; } +static ULONG execl_InitStruct(void) { EXEC_InitStruct(m68k_areg(regs, 1), m68k_areg(regs, 2), m68k_dreg(regs, 0) & 0xFFFF); return 0; } + +static ULONG execl_GetCC(void) +{ + MakeSR(); + m68k_dreg(regs, 0) = regs.sr & 0xFF; + return 0; /* ignored */ +} /* * Interrupts @@ -210,22 +216,22 @@ static ULONG execl_InitStruct(void) { EX CPTR EXEC_SetIntVector(int number, CPTR interrupt) { - CPTR oldvec = get_long(sysbase + 84 + 12*number + 8); + CPTR oldvec = get_long(EXEC_sysbase + 84 + 12*number + 8); if (interrupt == 0) { - put_long(sysbase + 84 + 12*number, 0); - put_long(sysbase + 84 + 12*number + 4, 0); - put_long(sysbase + 84 + 12*number + 8, 0); + put_long(EXEC_sysbase + 84 + 12*number, 0); + put_long(EXEC_sysbase + 84 + 12*number + 4, 0); + put_long(EXEC_sysbase + 84 + 12*number + 8, 0); } else { - put_long(sysbase + 84 + 12*number, get_long(interrupt + 14)); - put_long(sysbase + 84 + 12*number + 4, get_long(interrupt + 18)); - put_long(sysbase + 84 + 12*number + 8, interrupt); + put_long(EXEC_sysbase + 84 + 12*number, get_long(interrupt + 14)); + put_long(EXEC_sysbase + 84 + 12*number + 4, get_long(interrupt + 18)); + put_long(EXEC_sysbase + 84 + 12*number + 8, interrupt); } return oldvec; } void EXEC_RemIntServer(ULONG nr, CPTR interrupt) { - CPTR list = get_long(sysbase + 84 + nr*12); + CPTR list = get_long(EXEC_sysbase + 84 + nr*12); EXEC_Remove(interrupt); /* Disable interrupt if necessary */ @@ -235,7 +241,7 @@ void EXEC_RemIntServer(ULONG nr, CPTR in void EXEC_AddIntServer(ULONG nr, CPTR interrupt) { - CPTR list = get_long(sysbase + 84 + nr*12); + CPTR list = get_long(EXEC_sysbase + 84 + nr*12); int was_empty; /* Disable interrupt if necessary */ @@ -247,9 +253,9 @@ void EXEC_AddIntServer(ULONG nr, CPTR in } -static ULONG execl_SetIntVector(void) { return EXEC_SetIntVector(regs.d[0], regs.a[1]); } -static ULONG execl_AddIntServer(void) { EXEC_AddIntServer(regs.d[0] & 15, regs.a[1]); return 0; } -static ULONG execl_RemIntServer(void) { EXEC_RemIntServer(regs.d[0] & 15, regs.a[1]); return 0; } +static ULONG execl_SetIntVector(void) { return EXEC_SetIntVector(m68k_dreg(regs, 0), m68k_areg(regs, 1)); } +static ULONG execl_AddIntServer(void) { EXEC_AddIntServer(m68k_dreg(regs, 0) & 15, m68k_areg(regs, 1)); return 0; } +static ULONG execl_RemIntServer(void) { EXEC_RemIntServer(m68k_dreg(regs, 0) & 15, m68k_areg(regs, 1)); return 0; } /* * Memory functions @@ -329,7 +335,7 @@ void EXEC_Deallocate(CPTR memheader, CPT CPTR EXEC_AllocMem(unsigned long size, ULONG requirements) { - CPTR nextmh, memheader = get_long(sysbase + 322); + CPTR nextmh, memheader = get_long(EXEC_sysbase + 322); ULONG attrs = requirements & (MEMF_PUBLIC | MEMF_CHIP | MEMF_FAST); CPTR result = 0; @@ -344,7 +350,7 @@ CPTR EXEC_AllocMem(unsigned long size, U } if (result) { if (requirements & MEMF_CLEAR) - memset(get_real_address(result), 0, size); + memset(raddr(result), 0, size); } return result; } @@ -370,11 +376,15 @@ CPTR EXEC_AllocEntry(CPTR ml) void EXEC_FreeMem(CPTR addr, unsigned long size) { - CPTR nextmh, memheader = get_long(sysbase + 322); + CPTR nextmh, memheader = get_long(EXEC_sysbase + 322); size = (size + 7) & ~7; if (addr == 0) return; + if (size == 0) { + fprintf(stderr, "warning: Freemem(..., 0)\n"); + return; + } for (;(nextmh = get_long(memheader)) != 0; memheader = nextmh) { if (get_long(memheader + 20) <= addr @@ -388,7 +398,7 @@ void EXEC_FreeMem(CPTR addr, unsigned lo unsigned long EXEC_AvailMem(ULONG requirements) { ULONG attrs = requirements & (MEMF_PUBLIC | MEMF_CHIP | MEMF_FAST); - CPTR nextmh, memheader = get_long(sysbase + 322); + CPTR nextmh, memheader = get_long(EXEC_sysbase + 322); CPTR result = 0; for (;(nextmh = get_long(memheader)) != 0; memheader = nextmh) { @@ -411,6 +421,11 @@ unsigned long EXEC_AvailMem(ULONG requir void EXEC_AddMemList(unsigned long size, ULONG attrs, int pri, CPTR base, CPTR name) { + if (size == 0xFFFFFFFF) { + fprintf(stderr, "Weird AddMemList call\n"); + return; + } + put_byte(base + 8, 0); put_byte(base + 9, pri); put_long(base + 10, name); @@ -420,35 +435,40 @@ void EXEC_AddMemList(unsigned long size, put_long(base + 36, size - 32); put_long(base + 28, size - 32); put_long(base + 24, base + size); - EXEC_Enqueue(sysbase + 322, base); + EXEC_Enqueue(EXEC_sysbase + 322, base); } static ULONG execl_AddMemList(void) { - EXEC_AddMemList(regs.d[0], regs.d[1], (LONG)regs.d[2], regs.a[0], regs.a[1]); + EXEC_AddMemList(m68k_dreg(regs, 0), m68k_dreg(regs, 1), (LONG)m68k_dreg(regs, 2), m68k_areg(regs, 0), m68k_areg(regs, 1)); return 0; } static ULONG execl_CopyMem(void) { - UBYTE *src = get_real_address(regs.a[0]); - UBYTE *dst = get_real_address(regs.a[1]); + UBYTE *src = (UBYTE *)raddr(m68k_areg(regs, 0)); + UBYTE *dst = (UBYTE *)raddr(m68k_areg(regs, 1)); if (src != NULL && dst != NULL - && valid_address(regs.a[0], regs.d[0]) - && valid_address(regs.a[1], regs.d[0])) - memcpy(dst, src, regs.d[0]); - else - fprintf(stderr, "CopyMem with bogus parameters\n"); + && valid_address(m68k_areg(regs, 0), m68k_dreg(regs, 0)) + && valid_address(m68k_areg(regs, 1), m68k_dreg(regs, 0))) + memcpy(dst, src, m68k_dreg(regs, 0)); + else { + /* Ho hum. This happens when copying expansion card data. We + * better do something sensible in this case */ + unsigned long int i; + for(i = 0; i < m68k_dreg(regs, 0); i++) + put_byte(m68k_areg(regs, 1) + i, get_byte(m68k_areg(regs, 0) + i)); + } return 0; } -static ULONG execl_AllocMem(void) { return EXEC_AllocMem(regs.d[0], regs.d[1]); } -static ULONG execl_AllocEntry(void) { return EXEC_AllocEntry(regs.a[0]); } -static ULONG execl_Allocate(void) { return EXEC_Allocate(regs.a[0], regs.d[0]); } -static ULONG execl_FreeMem(void) { EXEC_FreeMem(regs.a[1], regs.d[0]); return 0; } -static ULONG execl_AvailMem(void) { return EXEC_AvailMem(regs.d[1]); } -static ULONG execl_Deallocate(void) { EXEC_Deallocate(regs.a[0], regs.a[1], regs.d[0]); return 0; } +static ULONG execl_AllocMem(void) { return EXEC_AllocMem(m68k_dreg(regs, 0), m68k_dreg(regs, 1)); } +static ULONG execl_AllocEntry(void) { return EXEC_AllocEntry(m68k_areg(regs, 0)); } +static ULONG execl_Allocate(void) { return EXEC_Allocate(m68k_areg(regs, 0), m68k_dreg(regs, 0)); } +static ULONG execl_FreeMem(void) { EXEC_FreeMem(m68k_areg(regs, 1), m68k_dreg(regs, 0)); return 0; } +static ULONG execl_AvailMem(void) { return EXEC_AvailMem(m68k_dreg(regs, 1)); } +static ULONG execl_Deallocate(void) { EXEC_Deallocate(m68k_areg(regs, 0), m68k_areg(regs, 1), m68k_dreg(regs, 0)); return 0; } /* * Scheduling @@ -458,20 +478,20 @@ static ULONG execl_Deallocate(void) { EX #define TS_READY 3 #define TS_WAIT 4 #define TS_EXCEPT 5 +#define TS_REMOVED 6 struct NewTask { struct NewTask *next, *prev; CPTR exectask; -#ifdef USE_EXECLIB - jmp_buf j; -#endif + struct switch_struct sws; void *stack; struct regstruct regs; struct flag_struct flags; }; static struct NewTask idle_task; -static int intr_count, need_resched; +static int intr_count, need_resched, quantum_elapsed; +static struct NewTask *task_to_kill; static struct NewTask *find_newtask(CPTR task) { @@ -483,44 +503,58 @@ static struct NewTask *find_newtask(CPTR t = t->next; } while (t != &idle_task); fprintf(stderr, "Uh oh. Task list corrupt\n"); + return 0; } +void EXEC_QuantumElapsed(void) +{ + need_resched = 1; + quantum_elapsed = 1; +} + +static int trace_schedules = 0; + static void schedule(void) { -#ifdef USE_EXECLIB - CPTR readylist = sysbase + 406; + CPTR readylist = EXEC_sysbase + 406; CPTR readytask = get_long(readylist); - CPTR runtask = get_long(sysbase + 276); + CPTR runtask = get_long(EXEC_sysbase + 276); struct NewTask *runtask_nt, *readytask_nt; unsigned long oldflags; - + UBYTE oldstate; int idis; + TIMER_block(); + need_resched = 0; /* Any ready tasks? */ if (get_long(readytask) == 0) - return; + goto dont_schedule; - /* If the running task is going to sleep, don't check priorities*/ - if (get_byte(runtask + 15) != TS_WAIT) { + /* If the running task is going to sleep, don't check priorities */ + oldstate = get_byte(runtask + 15); + if (oldstate != TS_WAIT && oldstate != TS_REMOVED) { /* Has the running task a higher priority than any ready tasks? */ if ((BYTE)get_byte(runtask + 9) > (BYTE)get_byte(readytask + 9)) - return; - /* We should only preempt a task of the same priority if the quantum - * has expired. Hmmm... */ - } - if (get_byte(runtask + 15) == TS_RUN) - put_byte(runtask + 15, TS_READY); - if (get_byte(runtask + 15) == TS_WAIT) - EXEC_Enqueue(sysbase + 420, runtask); - else + goto dont_schedule; + if ((BYTE)get_byte(runtask + 9) == (BYTE)get_byte(readytask + 9) + && !quantum_elapsed) + goto dont_schedule; + quantum_elapsed = 0; + } + if (oldstate == TS_RUN) + put_byte(runtask + 15, oldstate = TS_READY); + if (oldstate == TS_WAIT) + EXEC_Enqueue(EXEC_sysbase + 420, runtask); + else + /* Removed tasks end up here also, so we can safely Remove() them + * always. */ EXEC_Enqueue(readylist, runtask); put_byte(readytask + 15, TS_RUN); EXEC_Remove(readytask); readytask_nt = find_newtask(readytask); runtask_nt = find_newtask(runtask); - oldflags = regs.spcflags; runtask_nt->regs = regs; @@ -528,30 +562,49 @@ static void schedule(void) regs = readytask_nt->regs; regflags = readytask_nt->flags; regs.spcflags = (regs.spcflags & ~PRESERVED_FLAGS) | (oldflags & PRESERVED_FLAGS); - - put_byte(runtask + 16, get_byte(sysbase + 294)); - put_byte(runtask + 17, get_byte(sysbase + 295)); - put_byte(sysbase + 294, idis = get_byte(readytask + 16)); - put_byte(sysbase + 295, get_byte(readytask + 17)); - put_long(sysbase + 276, readytask); + regs.isp = runtask_nt->regs.isp; + regs.msp = runtask_nt->regs.msp; + put_byte(runtask + 16, get_byte(EXEC_sysbase + 294)); + put_byte(runtask + 17, get_byte(EXEC_sysbase + 295)); + put_byte(EXEC_sysbase + 294, idis = get_byte(readytask + 16)); + put_byte(EXEC_sysbase + 295, get_byte(readytask + 17)); + put_long(EXEC_sysbase + 276, readytask); /* Set INTENA according to new interrupt enable status */ if (idis == 0xFF) put_word(0xDFF09A, 0xC000); else put_word(0xDFF09A, 0x4000); - /* Whee... */ - fprintf(stderr, "Task switch: new task %s\n", get_real_address(get_long(readytask + 10))); - if (setjmp(runtask_nt->j) == 0) - longjmp(readytask_nt->j, 1); + + if (trace_schedules) + fprintf(stderr, "Task switch: new task %s\n", raddr(get_long(readytask + 10))); + + EXEC_SWITCH_TASKS(runtask_nt, readytask_nt); + regs.spcflags &= ~SPCFLAG_BRK; -#endif + + dont_schedule: + + TIMER_unblock(); + + /* Now we know we are running in a live task, so we can safely remove + * a corpse if necessary */ + if (task_to_kill != NULL) { + struct NewTask *nt = task_to_kill; + task_to_kill = NULL; + EXEC_Remove(nt->exectask); + EXEC_FreeMem(nt->exectask, 92); + free(nt->stack); + nt->prev->next = nt->next; + nt->next->prev = nt->prev; + free(nt); + } } static __inline__ void maybe_schedule(void) { /* @@@ Should we avoid a schedule when supervisor bit is set? * Definitely not if the running task is the idle task */ - if (intr_count == 0 && get_byte(sysbase + 294) == 0xFF && get_byte(sysbase + 295) == 0xFF && need_resched) + if (intr_count == 0 && get_byte(EXEC_sysbase + 294) == 0xFF && get_byte(EXEC_sysbase + 295) == 0xFF && need_resched) schedule(); } @@ -561,7 +614,7 @@ static __inline__ void maybe_schedule(vo int EXEC_AllocSignal(int signum) { - CPTR thistask = get_long(sysbase + 276); + CPTR thistask = get_long(EXEC_sysbase + 276); ULONG sigalloc = get_long(thistask + 18); if (signum == -1) for (signum = 0; signum < 32; signum++) @@ -578,7 +631,7 @@ int EXEC_AllocSignal(int signum) void EXEC_FreeSignal(int signum) { - CPTR thistask = get_long(sysbase + 276); + CPTR thistask = get_long(EXEC_sysbase + 276); if (signum != -1) return; put_long(thistask + 18, get_long(thistask + 18) & ~(1 << signum)); @@ -586,7 +639,7 @@ void EXEC_FreeSignal(int signum) ULONG EXEC_SetSignal(ULONG newsig, ULONG exec_sigmask) { - CPTR task = get_long(sysbase + 276); + CPTR task = get_long(EXEC_sysbase + 276); ULONG signals = get_long(task + 26); /* @@@ check SigExcept here */ put_long(task + 26, (signals & ~exec_sigmask) | (newsig & exec_sigmask)); @@ -597,10 +650,16 @@ void EXEC_Signal(CPTR task, ULONG exec_s { ULONG exec_sigs = get_long(task + 26); ULONG sigwait = get_long(task + 22); + + if (task == 0) { +/* fprintf(stderr, "Signalling NULL task. Bad\n");*/ + return; + } put_long(task + 26, exec_sigs | exec_sigmask); if (get_byte(task + 15) == TS_WAIT && (sigwait & exec_sigmask) != 0) { EXEC_Remove(task); - EXEC_Enqueue(sysbase + 406, task); + put_byte(task + 15, TS_READY); + EXEC_Enqueue(EXEC_sysbase + 406, task); need_resched = 1; maybe_schedule(); } @@ -608,13 +667,13 @@ void EXEC_Signal(CPTR task, ULONG exec_s ULONG EXEC_Wait(ULONG exec_sigmask) { - CPTR task = get_long(sysbase + 276); + CPTR task = get_long(EXEC_sysbase + 276); ULONG exec_sigs = get_long(task + 26); if ((exec_sigs & exec_sigmask) != 0) { put_long(task + 26, exec_sigs & ~exec_sigmask); return exec_sigs & exec_sigmask; } - if (get_byte(sysbase + 294) != 0xFF || get_byte(sysbase + 295) != 0xFF) + if (get_byte(EXEC_sysbase + 294) != 0xFF || get_byte(EXEC_sysbase + 295) != 0xFF) { fprintf(stderr, "Arrgh, task Wait()ing when it shouldn't\n"); } @@ -634,11 +693,11 @@ ULONG EXEC_Wait(ULONG exec_sigmask) return 0; } -static ULONG execl_SetSignal(void) { return EXEC_SetSignal(regs.d[0], regs.d[1]); } -static ULONG execl_Signal(void) { EXEC_Signal(regs.a[1], regs.d[0]); return 0; } -static ULONG execl_Wait(void) { return EXEC_Wait(regs.d[0]); } -static ULONG execl_AllocSignal(void) { return EXEC_AllocSignal((BYTE)regs.d[0]); } -static ULONG execl_FreeSignal(void) { EXEC_FreeSignal((BYTE)regs.d[0]); return 0; } +static ULONG execl_SetSignal(void) { return EXEC_SetSignal(m68k_dreg(regs, 0), m68k_dreg(regs, 1)); } +static ULONG execl_Signal(void) { EXEC_Signal(m68k_areg(regs, 1), m68k_dreg(regs, 0)); return 0; } +static ULONG execl_Wait(void) { return EXEC_Wait(m68k_dreg(regs, 0)); } +static ULONG execl_AllocSignal(void) { return EXEC_AllocSignal((BYTE)m68k_dreg(regs, 0)); } +static ULONG execl_FreeSignal(void) { EXEC_FreeSignal((BYTE)m68k_dreg(regs, 0)); return 0; } /* * Semaphores @@ -653,7 +712,7 @@ void EXEC_InitSemaphore(CPTR exec_sigsem ULONG EXEC_AttemptSemaphore(CPTR exec_sigsem) { - CPTR task = get_long(sysbase + 276); + CPTR task = get_long(EXEC_sysbase + 276); UWORD count = get_word(exec_sigsem + 44); if (count == 0xFFFF) { /* Semaphore free -> lock it */ @@ -672,8 +731,10 @@ ULONG EXEC_AttemptSemaphore(CPTR exec_si void EXEC_ObtainSemaphore(CPTR exec_sigsem) { - CPTR task = get_long(sysbase + 276); + CPTR task = get_long(EXEC_sysbase + 276); UWORD count = get_word(exec_sigsem + 44); + CPTR n; + if (count == 0xFFFF) { /* Semaphore free -> lock it */ put_word(exec_sigsem + 44, 0); @@ -690,10 +751,12 @@ void EXEC_ObtainSemaphore(CPTR exec_sigs /* @@@ None of the predefined signals in exec/tasks.h seem to be used * for this. We use 0x8000, which appears not to be used otherwise */ put_word(exec_sigsem + 44, count + 1); - EXEC_AddTail(exec_sigsem + 16, task); + n = EXEC_AllocMem(12, 0); /* Ugh... is there a cleaner way? */ + put_long(n + 8, task); + EXEC_AddTail(exec_sigsem + 16, n); if (EXEC_Wait(0x8000) != 0x8000) fprintf(stderr, "BUG\n"); - + EXEC_FreeMem(n, 12); /* Now it's mine, all mine! */ put_long(exec_sigsem + 40, task); put_word(exec_sigsem + 14, 1); @@ -706,7 +769,7 @@ void EXEC_ReleaseSemaphore(CPTR exec_sig if (nest == 1) { /* We're losing it. Signal the first task on the wait queue * (that one will in turn wake the next, etc.) */ - CPTR task = EXEC_RemHead(exec_sigsem + 16); + CPTR task = get_long(EXEC_RemHead(exec_sigsem + 16) + 8); UWORD count = get_word(exec_sigsem + 44); put_word(exec_sigsem + 44, count - 1); if (task) { @@ -715,12 +778,68 @@ void EXEC_ReleaseSemaphore(CPTR exec_sig } } -static ULONG execl_ObtainSemaphore(void) { EXEC_ObtainSemaphore(regs.a[0]); return 0; } -static ULONG execl_ReleaseSemaphore(void) { EXEC_ReleaseSemaphore(regs.a[0]); return 0; } -static ULONG execl_FindSemaphore(void) { return EXEC_FindName(sysbase + 532, get_real_address(regs.a[1])); } -static ULONG execl_InitSemaphore(void) { EXEC_InitSemaphore(regs.a[0]); return 0; } -static ULONG execl_AttemptSemaphore(void) { return EXEC_AttemptSemaphore(regs.a[0]); } -static ULONG execl_AddSemaphore(void) { put_byte(regs.a[1] + 8, 15); EXEC_Enqueue(sysbase + 532, regs.a[1]); return 0; } +/* Assumption: Semaphores on the list are only handled through these two + * functions. I don't see how it could work reliably otherwise. But I don't + * see either why these functions ought to be used: You might as well have + * one semaphore instead of a list of them. + * For safety, these functions try hard to function even in cases where they + * might otherwise deadlock or break. + * @@@ what should happen if the task already owns semaphores on the list? + */ + +void EXEC_ObtainSemaphoreList(CPTR l) +{ + CPTR task = get_long(EXEC_sysbase + 276); + CPTR n; + + int retry; + EXEC_Forbid(); + do { + retry = 0; + /* See if any semaphores on the list are locked. If so, go to + * sleep */ + n = get_long(l); + while(get_long(n) != 0) { + if (get_word(n + 44) != 0xFFFF && get_long(n + 40) != task) { + /* Semaphore is locked. Obtain it the normal way */ + EXEC_Permit(); + EXEC_ObtainSemaphore(n); + EXEC_ReleaseSemaphore(n); + EXEC_Forbid(); + retry = 1; + break; + } + n = get_long(n); + } + } while (retry); + /* All semaphores on the list are unlocked. */ + for (n = get_long(l); get_long(n) != 0; n = get_long(n)) { + put_word(n + 44, get_word(n + 44) + 1); + put_long(n + 40, task); + put_word(n + 14, get_word(n + 14) + 1); + } + EXEC_Permit(); +} + +void EXEC_ReleaseSemaphoreList(CPTR l) +{ + CPTR n; + + EXEC_Forbid(); + for (n = get_long(l); get_long(n) != 0; n = get_long(n)) { + EXEC_ReleaseSemaphore(n); + } + EXEC_Permit(); +} + +static ULONG execl_ObtainSemaphore(void) { EXEC_ObtainSemaphore(m68k_areg(regs, 0)); return 0; } +static ULONG execl_ReleaseSemaphore(void) { EXEC_ReleaseSemaphore(m68k_areg(regs, 0)); return 0; } +static ULONG execl_ObtainSemaphoreList(void) { EXEC_ObtainSemaphoreList(m68k_areg(regs, 0)); return 0; } +static ULONG execl_ReleaseSemaphoreList(void) { EXEC_ReleaseSemaphoreList(m68k_areg(regs, 0)); return 0; } +static ULONG execl_FindSemaphore(void) { return EXEC_FindName(EXEC_sysbase + 532, raddr(m68k_areg(regs, 1))); } +static ULONG execl_InitSemaphore(void) { EXEC_InitSemaphore(m68k_areg(regs, 0)); return 0; } +static ULONG execl_AttemptSemaphore(void) { return EXEC_AttemptSemaphore(m68k_areg(regs, 0)); } +static ULONG execl_AddSemaphore(void) { put_byte(m68k_areg(regs, 1) + 8, NT_SIGNALSEM); EXEC_Enqueue(EXEC_sysbase + 532, m68k_areg(regs, 1)); return 0; } /* * Messages and ports @@ -745,14 +864,19 @@ static void EXEC_doputmsg(CPTR port, CPT void EXEC_PutMsg(CPTR port, CPTR msg) { - put_byte(msg + 8, 5); + put_byte(msg + 8, NT_MESSAGE); EXEC_doputmsg(port, msg); } void EXEC_ReplyMsg(CPTR msg) -{ - put_byte(msg + 8, 7); - EXEC_doputmsg(get_long(msg + 14), msg); +{ + CPTR p = get_long(msg + 14); + if (p == 0) { + put_byte(msg + 8, NT_FREEMSG); + } else { + put_byte(msg + 8, NT_REPLYMSG); + EXEC_doputmsg(p, msg); + } } CPTR EXEC_WaitPort(CPTR port) @@ -767,12 +891,26 @@ CPTR EXEC_WaitPort(CPTR port) } } -static ULONG execl_GetMsg(void) { return EXEC_GetMsg(regs.a[0]); } -static ULONG execl_PutMsg(void) { EXEC_PutMsg(regs.a[0], regs.a[1]); return 0; } -static ULONG execl_ReplyMsg(void) { EXEC_ReplyMsg(regs.a[1]); return 0; } -static ULONG execl_WaitPort(void) { return EXEC_WaitPort(regs.a[0]); } -static ULONG execl_FindPort(void) { return EXEC_FindName(sysbase + 392, get_real_address(regs.a[1])); } -static ULONG execl_AddPort(void) { put_byte(regs.a[1] + 8, 4); EXEC_Enqueue(sysbase + 392, regs.a[1]); return 0; } +void EXEC_AddPort(CPTR port) +{ + put_byte(port + 8, NT_MSGPORT); + EXEC_Enqueue(EXEC_sysbase + 392, port); + EXEC_NewList(port + 20); + /* should we put the task into the appropriate place? */ +} + +void EXEC_RemPort(CPTR port) +{ + EXEC_Remove(port); +} + +static ULONG execl_GetMsg(void) { return EXEC_GetMsg(m68k_areg(regs, 0)); } +static ULONG execl_PutMsg(void) { EXEC_PutMsg(m68k_areg(regs, 0), m68k_areg(regs, 1)); return 0; } +static ULONG execl_ReplyMsg(void) { EXEC_ReplyMsg(m68k_areg(regs, 1)); return 0; } +static ULONG execl_WaitPort(void) { return EXEC_WaitPort(m68k_areg(regs, 0)); } +static ULONG execl_FindPort(void) { return EXEC_FindName(EXEC_sysbase + 392, raddr(m68k_areg(regs, 1))); } +static ULONG execl_AddPort(void) { EXEC_AddPort(m68k_areg(regs, 1)); return 0; } +static ULONG execl_RemPort(void) { EXEC_RemPort(m68k_areg(regs, 1)); return 0; } /* * I/O @@ -786,7 +924,7 @@ LONG EXEC_WaitIO(CPTR ioreq) return (LONG)(BYTE)get_byte(ioreq + 31); for (;;) { - if (get_byte(ioreq + 8) == 7) /* NT_REPLYMSG? */ + if (get_byte(ioreq + 8) == NT_REPLYMSG) break; /* We'll just hope that this a) has a ReplyPort and b) that port * is of type PA_SIGNAL @@ -802,18 +940,19 @@ LONG EXEC_WaitIO(CPTR ioreq) static void EXEC_BeginIO(CPTR ioreq) { CPTR dev = get_long(ioreq + 20); - regs.a[6] = dev; - regs.a[1] = ioreq; + m68k_areg(regs, 6) = dev; + m68k_areg(regs, 1) = ioreq; Call68k(dev - 30, 1); + m68k_areg(regs, 6) = EXEC_sysbase; } -void EXEC_DoIO(CPTR ioreq) +LONG EXEC_DoIO(CPTR ioreq) { put_byte(ioreq + 30, 1); EXEC_BeginIO(ioreq); - EXEC_WaitIO(ioreq); + return EXEC_WaitIO(ioreq); } - + void EXEC_SendIO(CPTR ioreq) { put_byte(ioreq + 30, 0); @@ -824,15 +963,26 @@ CPTR EXEC_CheckIO(CPTR ioreq) { if ((get_byte(ioreq + 30) & 1) == 1) return ioreq; - if (get_byte(ioreq + 8) == 7) + if (get_byte(ioreq + 8) == NT_REPLYMSG) return ioreq; return 0; } -static ULONG execl_WaitIO(void) { return EXEC_WaitIO(regs.a[1]); } -static ULONG execl_DoIO(void) { EXEC_DoIO(regs.a[1]); return 0; } -static ULONG execl_SendIO(void) { EXEC_SendIO(regs.a[1]); return 0; } -static ULONG execl_CheckIO(void) { return EXEC_CheckIO(regs.a[1]); } +void EXEC_AbortIO(CPTR ioRequest) +{ + CPTR dev = get_long(ioRequest + 20); + m68k_areg(regs, 6) = dev; + m68k_areg(regs, 1) = ioRequest; + /* The example code returns a value here. What should we do with it? */ + Call68k(dev - 36, 1); + m68k_areg(regs, 6) = EXEC_sysbase; +} + +static ULONG execl_WaitIO(void) { return EXEC_WaitIO(m68k_areg(regs, 1)); } +static ULONG execl_DoIO(void) { return EXEC_DoIO(m68k_areg(regs, 1)); } +static ULONG execl_SendIO(void) { EXEC_SendIO(m68k_areg(regs, 1)); return 0; } +static ULONG execl_CheckIO(void) { return EXEC_CheckIO(m68k_areg(regs, 1)); } +static ULONG execl_AbortIO(void) { EXEC_AbortIO(m68k_areg(regs, 1)); return 0; } /* * Libraries @@ -865,25 +1015,35 @@ CPTR EXEC_SetFunction(CPTR lib, int func void EXEC_AddLibrary(CPTR lib) { - EXEC_Enqueue(sysbase + 378, lib); + EXEC_Enqueue(EXEC_sysbase + 378, lib); put_word(lib + 14, 2); /* mark as changed */ EXEC_SumLibrary(lib); } CPTR EXEC_OpenLibrary(char *name, int version) { - CPTR lib = EXEC_FindName(sysbase + 378, name); + CPTR lib = EXEC_FindName(EXEC_sysbase + 378, name); + + if (lib != 0 && get_word(lib + 20) < version) + return 0; + if (lib != 0) { - regs.a[6] = lib; - regs.d[0] = version; - lib = Call68k(lib - 6, 1); + CPTR lib2; + m68k_areg(regs, 6) = lib; + m68k_dreg(regs, 0) = version; + lib2 = Call68k(lib - 6, 1); + if (lib2 == 0) + lib = 0; + else if (lib2 != lib) + fprintf(stderr, "OpenLibrary: weirdness\n"); + m68k_areg(regs, 6) = EXEC_sysbase; } return lib; } CPTR EXEC_OpenDevice(char *name, ULONG unit, CPTR ioRequest, ULONG flags) { - CPTR dev = EXEC_FindName(sysbase + 350, name); + CPTR dev = EXEC_FindName(EXEC_sysbase + 350, name); CPTR replyport = get_long(ioRequest + 14); put_long(ioRequest + 20, dev); put_byte(ioRequest + 31, 0); @@ -892,35 +1052,73 @@ CPTR EXEC_OpenDevice(char *name, ULONG u fprintf(stderr, "ioRequest has no ReplyPort\n"); else { CPTR rtask = get_long(replyport + 16); - if (rtask == 0) + if (rtask == 0) { fprintf(stderr, "replyTask == 0\n"); - else if (rtask != get_long(sysbase + 276)) + put_long(replyport + 16, get_long(EXEC_sysbase + 276)); + } + else if (rtask != get_long(EXEC_sysbase + 276)) fprintf(stderr, "replyTask != current\n"); -/* put_long(replyport + 16, get_long(sysbase + 276));*/ +/* put_long(replyport + 16, get_long(EXEC_sysbase + 276));*/ } if (dev != 0) { - regs.a[6] = dev; - regs.a[1] = ioRequest; - regs.d[0] = unit; - regs.d[1] = flags; + m68k_areg(regs, 6) = dev; + m68k_areg(regs, 1) = ioRequest; + m68k_dreg(regs, 0) = unit; + m68k_dreg(regs, 1) = flags; + EXEC_Forbid(); dev = Call68k(dev - 6, 1); + EXEC_Permit(); + m68k_areg(regs, 6) = EXEC_sysbase; } return (LONG)(BYTE)get_byte(ioRequest + 31); } +/* + * There seems to be some magic involved here. These functions are documented + * as returning void. However, if we leave D0 unmodified by giving + * TRAPFLAG_NORETVAL, there are bogus FreeMem calls; these go away if we + * return 0 in D0 as the old code did. I guess these are really supposed to + * return the value that was given to them by the library's Close routine + * (for the DOS CloseDevice()/CloseLibrary() calls, probably) + */ + +ULONG EXEC_CloseDevice(CPTR ioRequest) +{ + CPTR dev = get_long(ioRequest + 20); + ULONG retval; + + m68k_areg(regs, 6) = dev; + m68k_areg(regs, 1) = ioRequest; + EXEC_Forbid(); + retval = Call68k(dev - 12, 1); + EXEC_Permit(); + return retval; +} + +ULONG EXEC_CloseLibrary(CPTR lib) +{ + ULONG retval; + + m68k_areg(regs, 6) = lib; + EXEC_Forbid(); + retval = Call68k(lib - 12, 1); + EXEC_Permit(); + return retval; +} + void EXEC_AddDevice(CPTR lib) { - EXEC_Enqueue(sysbase + 350, lib); + EXEC_Enqueue(EXEC_sysbase + 350, lib); } void EXEC_AddResource(CPTR lib) { - EXEC_Enqueue(sysbase + 336, lib); + EXEC_Enqueue(EXEC_sysbase + 336, lib); } CPTR EXEC_OpenResource(char *name) { - CPTR lib = EXEC_FindName(sysbase + 336, name); + CPTR lib = EXEC_FindName(EXEC_sysbase + 336, name); return lib; } @@ -949,7 +1147,6 @@ void EXEC_MakeFunctions(CPTR target, CPT } } -/* This doesn't work yet */ CPTR EXEC_MakeLibrary(CPTR vectors, CPTR structure, CPTR init, unsigned long dsize, ULONG seglist_b) { @@ -959,7 +1156,6 @@ CPTR EXEC_MakeLibrary(CPTR vectors, CPTR CPTR base, fdispb = 0, funcarray = vectors; ULONG retval = 0; - fprintf(stderr, "MakeLibrary\n"); if (get_word (vectors) == (UWORD)-1) { int offs = 2; fdispb = vectors; @@ -970,7 +1166,7 @@ CPTR EXEC_MakeLibrary(CPTR vectors, CPTR } } else { int offs = 0; - while (get_long (vectors+offs) != (LONG)-1) { + while (get_long (vectors+offs) != (ULONG)-1) { offs += 4; vec_cnt++; } @@ -990,41 +1186,78 @@ CPTR EXEC_MakeLibrary(CPTR vectors, CPTR EXEC_InitStruct(structure, base, 0); } if (init != 0) { - regs.a[6] = sysbase; - regs.a[0] = seglist_b; /* BCPL seglist here? */ - regs.d[0] = base; + m68k_areg(regs, 6) = EXEC_sysbase; + m68k_areg(regs, 0) = seglist; /* BCPL seglist here? */ + m68k_dreg(regs, 0) = base; /* call it */ retval = Call68k(init, 0); } else retval = base; + fprintf(stderr, "MakeLibrary: %s\n", raddr(get_long(base+10))); return retval; } CPTR EXEC_InitResident(CPTR resident, ULONG segList) { UBYTE flags = get_byte(resident + 10); - + if (flags & 0x80) { CPTR autoinit = get_long(resident + 22); - return EXEC_MakeLibrary(get_long(autoinit + 4), get_long(autoinit + 8), - get_long(autoinit + 12), get_long(autoinit), segList >> 4); + CPTR lib; + lib = EXEC_MakeLibrary(get_long(autoinit + 4), get_long(autoinit + 8), + get_long(autoinit + 12), get_long(autoinit), + segList >> 2); + + /* Is this right? Some libraries never get added if we don't do + * this. */ + if (get_byte(resident + 12) == NT_LIBRARY) + EXEC_AddLibrary(lib); + else if (get_byte(resident + 12) == NT_DEVICE) + EXEC_AddDevice(lib); + else if (get_byte(resident + 12) == NT_RESOURCE) + EXEC_AddResource(lib); + return lib; + } - - regs.d[0] = 0; regs.a[0] = segList; regs.a[6] = sysbase; + + m68k_dreg(regs, 0) = 0; + m68k_areg(regs, 0) = segList; + m68k_areg(regs, 6) = EXEC_sysbase; return Call68k(get_long(resident + 22), 0); } -static ULONG execl_MakeFunctions(void) { EXEC_MakeFunctions(regs.a[0], regs.a[1], regs.a[2]); return 0; } -static ULONG execl_SumLibrary(void) { EXEC_SumLibrary(regs.a[1]); return 0; } -static ULONG execl_SetFunction(void) { return EXEC_SetFunction(regs.a[1], (WORD)regs.a[0], regs.d[0]); } -static ULONG execl_AddLibrary(void) { EXEC_AddLibrary(regs.a[1]); return 0; } -static ULONG execl_AddDevice(void) { EXEC_AddDevice(regs.a[1]); return 0; } -static ULONG execl_AddResource(void) { EXEC_AddResource(regs.a[1]); return 0; } -static ULONG execl_OpenLibrary(void) { return EXEC_OpenLibrary(get_real_address(regs.a[1]), regs.d[0]); } -static ULONG execl_OpenDevice(void) { return EXEC_OpenDevice(get_real_address(regs.a[0]), regs.d[0], regs.a[1], regs.d[1]); } -static ULONG execl_OpenResource(void) { return EXEC_OpenResource(get_real_address(regs.a[1])); } -static ULONG execl_MakeLibrary(void) { return EXEC_MakeLibrary(regs.a[0], regs.a[1], regs.a[2], regs.d[0], regs.d[1]); } +CPTR EXEC_FindResident(char *name) +{ + CPTR rmods = get_long(EXEC_sysbase + 300); + CPTR tmp2; + + if (name == NULL) + return 0; + + for (; (tmp2 = get_long(rmods)) != 0; rmods += 4) { + char *name2 = raddr(get_long(tmp2 + 14)); + if (strcmp(name, name2) == 0) + return tmp2; + } + return 0; +} + +static ULONG execl_MakeFunctions(void) { EXEC_MakeFunctions(m68k_areg(regs, 0), m68k_areg(regs, 1), m68k_areg(regs, 2)); return 0; } +static ULONG execl_SumLibrary(void) { EXEC_SumLibrary(m68k_areg(regs, 1)); return 0; } +static ULONG execl_SetFunction(void) { return EXEC_SetFunction(m68k_areg(regs, 1), (WORD)m68k_areg(regs, 0), m68k_dreg(regs, 0)); } +static ULONG execl_AddLibrary(void) { EXEC_AddLibrary(m68k_areg(regs, 1)); return 0; } +static ULONG execl_AddDevice(void) { EXEC_AddDevice(m68k_areg(regs, 1)); return 0; } +static ULONG execl_AddResource(void) { EXEC_AddResource(m68k_areg(regs, 1)); return 0; } +static ULONG execl_OpenLibrary(void) { return EXEC_OpenLibrary(raddr(m68k_areg(regs, 1)), m68k_dreg(regs, 0)); } +static ULONG execl_OldOpenLibrary(void) { return EXEC_OpenLibrary(raddr(m68k_areg(regs, 1)), 0); } +static ULONG execl_CloseLibrary(void) { return EXEC_CloseLibrary(m68k_areg(regs, 1)); } +static ULONG execl_OpenDevice(void) { return EXEC_OpenDevice(raddr(m68k_areg(regs, 0)), m68k_dreg(regs, 0), m68k_areg(regs, 1), m68k_dreg(regs, 1)); } +static ULONG execl_CloseDevice(void) { return EXEC_CloseDevice(m68k_areg(regs, 1)); } +static ULONG execl_OpenResource(void) { return EXEC_OpenResource(raddr(m68k_areg(regs, 1))); } +static ULONG execl_MakeLibrary(void) { return EXEC_MakeLibrary(m68k_areg(regs, 0), m68k_areg(regs, 1), m68k_areg(regs, 2), m68k_dreg(regs, 0), m68k_dreg(regs, 1)); } +static ULONG execl_FindResident(void) { return EXEC_FindResident(raddr(m68k_areg(regs, 1))); } +static ULONG execl_InitResident(void) { return EXEC_InitResident(m68k_areg(regs, 1), m68k_dreg(regs, 1)); } /* * Tasks @@ -1033,14 +1266,25 @@ static ULONG execl_MakeLibrary(void) { r static void task_startup(void) { m68k_setpc(regs.pc); - Call68k_retaddr(regs.pc, 0, get_long(regs.a[7] - 4)); + Call68k_retaddr(regs.pc, 0, get_long(m68k_areg(regs, 7) - 4)); fprintf(stderr, "Task fell through at the end\n"); } +void EXEC_RemTask(CPTR task) +{ + if (task == 0) + task = get_long(EXEC_sysbase + 276); + /* We can't easily delete it here while we use it's stack. Let schedule() + * do it. */ + put_byte(task + 15, TS_REMOVED); + task_to_kill = find_newtask(task); + schedule(); +} + CPTR EXEC_AddTask(CPTR task, CPTR initPC, CPTR finalPC) { -#ifdef USE_EXECLIB struct NewTask *nt = (struct NewTask *)malloc(sizeof (struct NewTask)); + nt->exectask = task; nt->prev = &idle_task; nt->next = idle_task.next; @@ -1048,25 +1292,46 @@ CPTR EXEC_AddTask(CPTR task, CPTR initPC idle_task.next = nt; memset(&nt->regs, 0, sizeof (nt->regs)); nt->regs.pc = initPC; - nt->regs.a[7] = get_long(task + 54); + m68k_areg(nt->regs, 7) = get_long(task + 54); if (finalPC == 0) finalPC = 0xF0FFF0; /* standard "return from 68k mode" calltrap */ put_byte(task + 16, 0xFF); put_byte(task + 17, 0xFF); - put_long(nt->regs.a[7] - 4, finalPC); + put_long(m68k_areg(nt->regs, 7) - 4, finalPC); nt->stack = malloc(65536); /* @@@ make this smaller after checking that * no parts of the emulator need much stack - * space */ - nt->j[0].__sp = nt->stack + 65536; - nt->j[0].__pc = &task_startup; + * space */ + EXEC_SETUP_SWS(nt); + put_byte(task + 15, TS_READY); put_long(task + 18,0x0000FFFF); /* all tasks have the lower 16 signals allocated */ - EXEC_Enqueue(sysbase + 406, task); + EXEC_Enqueue(EXEC_sysbase + 406, task); need_resched = 1; + fprintf(stderr, "AddTask: %s\n", raddr(get_long(task + 10))); maybe_schedule(); return task; -#endif +} + +int EXEC_SetTaskPri(CPTR task, int pri) +{ + int oldpri = get_byte(task + 9); + + if (task == get_long(EXEC_sysbase + 276)) { + put_byte(task + 9, pri); + return oldpri; + } + if (get_byte(task + 15) == TS_WAIT) { + EXEC_Remove(task); + put_byte(task + 9, pri); + EXEC_Enqueue(EXEC_sysbase + 420, task); + return oldpri; + } + EXEC_Remove(task); + put_byte(task + 9, pri); + EXEC_Enqueue(EXEC_sysbase + 406, task); + schedule(); + return oldpri; } CPTR EXEC_FindTask(char *name) @@ -1074,156 +1339,319 @@ CPTR EXEC_FindTask(char *name) char *n; CPTR v; - if (name == NULL || ((n = get_real_address(get_long(get_long(sysbase + 276) + 10))) != NULL + if (name == NULL || ((n = raddr(get_long(get_long(EXEC_sysbase + 276) + 10))) != NULL && strcmp(n, name) == 0)) - return get_long(sysbase + 276); + return get_long(EXEC_sysbase + 276); - v = EXEC_FindName(sysbase + 406, name); /* ready tasks */ + v = EXEC_FindName(EXEC_sysbase + 406, name); /* ready tasks */ if (v != 0) return v; - return EXEC_FindName(sysbase + 420, name); /* waiting tasks */ + return EXEC_FindName(EXEC_sysbase + 420, name); /* waiting tasks */ } -static ULONG execl_FindTask(void) { return EXEC_FindTask(regs.a[1] == 0 ? NULL : get_real_address(regs.a[1])); } -static ULONG execl_AddTask(void) { return EXEC_AddTask(regs.a[1], regs.a[2], regs.a[3]); } +static ULONG execl_FindTask(void) { return EXEC_FindTask(raddr(m68k_areg(regs, 1))); } +static ULONG execl_AddTask(void) { return EXEC_AddTask(m68k_areg(regs, 1), m68k_areg(regs, 2), m68k_areg(regs, 3)); } +static ULONG execl_RemTask(void) { EXEC_RemTask(m68k_areg(regs, 1)); return 0; } +static ULONG execl_SetTaskPri(void) { return EXEC_SetTaskPri(m68k_areg(regs, 1), (BYTE)m68k_dreg(regs, 0)); } ULONG EXEC_Forbid(void) { - int count = (BYTE)get_byte(sysbase + 295); + int count = (BYTE)get_byte(EXEC_sysbase + 295); count++; - put_byte(sysbase + 295, count); + put_byte(EXEC_sysbase + 295, count); return 0; } ULONG EXEC_Permit(void) { - int count = (BYTE)get_byte(sysbase + 295); + int count = (BYTE)get_byte(EXEC_sysbase + 295); if (count == -1) fprintf(stderr, "Too many Permit() calls\n"); else count--; - put_byte(sysbase + 295, count); + put_byte(EXEC_sysbase + 295, count); maybe_schedule(); return 0; } ULONG EXEC_Disable(void) { - int count = (BYTE)get_byte(sysbase + 294); + int count = (BYTE)get_byte(EXEC_sysbase + 294); count++; - put_byte(sysbase + 294, count); + put_byte(EXEC_sysbase + 294, count); put_word(0xDFF09A, 0x4000); return 0; } ULONG EXEC_Enable(void) { - int count = (BYTE)get_byte(sysbase + 294); + int count = (BYTE)get_byte(EXEC_sysbase + 294); if (count == -1) fprintf(stderr, "Too many Enable() calls\n"); else count--; if (count == -1) put_word(0xDFF09A, 0xC000); - put_byte(sysbase + 294, count); + put_byte(EXEC_sysbase + 294, count); maybe_schedule(); return 0; } + +/* + * Annoyances... + */ + +enum rdf_state { rdf_flags, rdf_width, rdf_limit, rdf_type }; + +CPTR EXEC_RawDoFormat(UBYTE *fstr, CPTR data, CPTR pcp, ULONG pcd) +{ + if (fstr == NULL) + return data; + for (;;) { + UBYTE c = *fstr++; + + if (c == 0) + break; + + if (c == '%') { + enum rdf_state rdfs = rdf_flags; + int ljust = 0, fill0 = 0, islong = 0; + int w = 0, lim = 0, havelim = 0; + + for (;;) { + c = *fstr++; + + if (c == 0) + break; + + if (rdfs == rdf_flags) { + rdfs = rdf_width; + if (c == '-') { + ljust = 1; + continue; + } + } + if (rdfs == rdf_width && c == '.') { + rdfs = rdf_limit; + continue; + } else if (rdfs == rdf_width && isdigit(c)) { + w = w*10 + c - '0'; + if (w == 0) + fill0 = 1; + continue; + } else if (rdfs == rdf_limit && isdigit(c)) { + lim = lim*10 + c - '0'; + havelim = 1; + continue; + } else if ((rdfs == rdf_limit || rdfs == rdf_width) && c == 'l') { + islong = 1; + rdfs = rdf_type; + continue; + } + switch (c) { + CPTR tmp; + ULONG tmp1; + unsigned int tmpl; + char tmps1[20], tmps2[20], *tmpsp; + + case 'b': + tmp = get_long(data); + data += 4; + tmpl = get_byte(tmp++); + for(; tmpl > 0; tmpl--) { + m68k_dreg(regs, 0) = get_byte(tmp++); + m68k_areg(regs, 3) = pcd; + Call68k(pcp, 0); + } + break; + + case 'd': + case 'u': + case 'x': + if (islong) { + tmp1 = get_long(data); data += 4; + } else { + tmp1 = get_word(data); data += 2; + if (c == 'd') + tmp1 = (LONG)(WORD)tmp1; + } + tmpsp = tmps1; + *tmpsp++ = '%'; + if (fill0) + *tmpsp++ = '0'; + if (w != 0) + sprintf(tmpsp, "%d", w); + tmpsp += strlen(tmpsp); + *tmpsp++ = c; + *tmpsp++ = 0; + sprintf(tmps2, tmps1, tmp1); + for (tmpsp = tmps2; ;) { + m68k_dreg(regs, 0) = *tmpsp++; + if (m68k_dreg(regs, 0) == 0) + break; + m68k_areg(regs, 3) = pcd; + Call68k(pcp, 0); + } + break; + + case 's': + tmp = get_long(data); + data += 4; + for(;!havelim || lim-- > 0;) { + m68k_dreg(regs, 0) = get_byte(tmp++); + if (m68k_dreg(regs, 0) == 0) + break; + m68k_areg(regs, 3) = pcd; + Call68k(pcp, 0); + } + break; + + case 'c': + if (islong) { + m68k_dreg(regs, 0) = get_long(data); data += 4; + } else { + m68k_dreg(regs, 0) = get_word(data); data += 2; + } + m68k_areg(regs, 3) = pcd; + Call68k(pcp, 0); + } + break; + } + + } else { + m68k_dreg(regs, 0) = c; + m68k_areg(regs, 3) = pcd; + Call68k(pcp, 0); + } + } + return data; +} + +static ULONG execl_RawDoFormat(void) +{ + return EXEC_RawDoFormat((UBYTE *)raddr(m68k_areg(regs, 0)), m68k_areg(regs, 1), m68k_areg(regs, 2), m68k_areg(regs, 3)); +} + /* * Initialization */ static ULONG execlib_init(void) { - sysbase = get_long(4); - + EXEC_sysbase = get_long(4); +#if 1 /* CopyMem and CopyMemQuick */ - libemu_InstallFunction(execl_CopyMem, sysbase, -630); - libemu_InstallFunction(execl_CopyMem, sysbase, -624); - libemu_InstallFunction(execl_Allocate, sysbase, -186); - libemu_InstallFunction(execl_AllocMem, sysbase, -198); - libemu_InstallFunction(execl_Deallocate, sysbase, -192); - libemu_InstallFunction(execl_FreeMem, sysbase, -210); - libemu_InstallFunction(execl_AvailMem, sysbase, -216); + libemu_InstallFunctionFlags(execl_CopyMem, EXEC_sysbase, -630, 0, "CopyMem"); + libemu_InstallFunctionFlags(execl_CopyMem, EXEC_sysbase, -624, 0, "CopyMem"); + libemu_InstallFunctionFlags(execl_Allocate, EXEC_sysbase, -186, 0, "Allocate"); + libemu_InstallFunctionFlags(execl_AllocMem, EXEC_sysbase, -198, 0, "AllocMem"); + libemu_InstallFunctionFlags(execl_Deallocate, EXEC_sysbase, -192, 0, "Deallocate"); + libemu_InstallFunctionFlags(execl_FreeMem, EXEC_sysbase, -210, 0, "FreeMem"); + libemu_InstallFunctionFlags(execl_AvailMem, EXEC_sysbase, -216, 0, "AvailMem"); /* List management */ - libemu_InstallFunction(execl_Insert, sysbase, -234); - libemu_InstallFunction(execl_AddHead, sysbase, -240); - libemu_InstallFunction(execl_AddTail, sysbase, -246); - libemu_InstallFunction(execl_Enqueue, sysbase, -270); - libemu_InstallFunction(execl_RemHead, sysbase, -258); - libemu_InstallFunction(execl_RemTail, sysbase, -264); - libemu_InstallFunction(execl_Remove, sysbase, -252); - libemu_InstallFunction(execl_FindName, sysbase, -276); + libemu_InstallFunctionFlags(execl_Insert, EXEC_sysbase, -234, TRAPFLAG_NORETVAL, "Insert"); + libemu_InstallFunctionFlags(execl_AddHead, EXEC_sysbase, -240, TRAPFLAG_NORETVAL, "AddHead"); + libemu_InstallFunctionFlags(execl_AddTail, EXEC_sysbase, -246, TRAPFLAG_NORETVAL, "AddTail"); + libemu_InstallFunctionFlags(execl_Enqueue, EXEC_sysbase, -270, TRAPFLAG_NORETVAL, "Enqueue"); + libemu_InstallFunctionFlags(execl_RemHead, EXEC_sysbase, -258, 0, "RemHead"); + libemu_InstallFunctionFlags(execl_RemTail, EXEC_sysbase, -264, 0, "RemTail"); + libemu_InstallFunctionFlags(execl_Remove, EXEC_sysbase, -252, TRAPFLAG_NORETVAL, "Remove"); + libemu_InstallFunctionFlags(execl_FindName, EXEC_sysbase, -276, 0, "FindName"); /* Signals */ - libemu_InstallFunction(execl_AllocSignal, sysbase, -330); - libemu_InstallFunction(execl_FreeSignal, sysbase, -336); + libemu_InstallFunctionFlags(execl_AllocSignal, EXEC_sysbase, -330, 0, "AllocSignal"); + libemu_InstallFunctionFlags(execl_FreeSignal, EXEC_sysbase, -336, 0, "FreeSignal"); /* Semaphores */ - libemu_InstallFunction(execl_FindSemaphore, sysbase, -594); - libemu_InstallFunction(execl_InitSemaphore, sysbase, -558); - libemu_InstallFunction(execl_AddSemaphore, sysbase, -600); + libemu_InstallFunctionFlags(execl_FindSemaphore, EXEC_sysbase, -594, 0, "FindSemaphore"); + libemu_InstallFunctionFlags(execl_InitSemaphore, EXEC_sysbase, -558, 0, "InitSemaphore"); + libemu_InstallFunctionFlags(execl_AddSemaphore, EXEC_sysbase, -600, TRAPFLAG_NORETVAL, "AddSemaphore"); /* Messages/Ports */ - libemu_InstallFunction(execl_FindPort, sysbase, -390); - libemu_InstallFunction(execl_GetMsg, sysbase, -372); + libemu_InstallFunctionFlags(execl_FindPort, EXEC_sysbase, -390, 0, "FindPort"); + libemu_InstallFunctionFlags(execl_GetMsg, EXEC_sysbase, -372, 0, "GetMsg"); /* Libraries */ - libemu_InstallFunction(execl_MakeFunctions, sysbase, -90); - libemu_InstallFunction(execl_SumLibrary, sysbase, -426); - libemu_InstallFunction(execl_SetFunction, sysbase, -420); + libemu_InstallFunctionFlags(execl_MakeFunctions, EXEC_sysbase, -90, 0, "MakeFunctions"); + libemu_InstallFunctionFlags(execl_SumLibrary, EXEC_sysbase, -426, TRAPFLAG_NORETVAL, "SumLibrary"); + libemu_InstallFunctionFlags(execl_SetFunction, EXEC_sysbase, -420, 0, "SetFunction"); /* Tasks */ - libemu_InstallFunction(execl_FindTask, sysbase, -294); + libemu_InstallFunctionFlags(execl_FindTask, EXEC_sysbase, -294, 0, "FindTask"); /* Interrupts */ - libemu_InstallFunction(execl_SetIntVector, sysbase, -162); - libemu_InstallFunction(execl_AddIntServer, sysbase, -168); - libemu_InstallFunction(execl_RemIntServer, sysbase, -174); + libemu_InstallFunctionFlags(execl_SetIntVector, EXEC_sysbase, -162, 0, "SetIntVector"); + libemu_InstallFunctionFlags(execl_AddIntServer, EXEC_sysbase, -168, TRAPFLAG_NORETVAL, "AddIntServer"); + libemu_InstallFunctionFlags(execl_RemIntServer, EXEC_sysbase, -174, 0, "RemIntServer"); /* Miscellaneous */ - libemu_InstallFunction(execl_InitStruct, sysbase, -78); - + libemu_InstallFunctionFlags(execl_InitStruct, EXEC_sysbase, -78, 0, "InitStruct"); + libemu_InstallFunctionFlags(execl_GetCC, EXEC_sysbase, -528, TRAPFLAG_NORETVAL|TRAPFLAG_NOREGSAVE, "InitStruct"); +#elif 0 + libemu_InstallFunctionFlags(NULL, EXEC_sysbase, -564, TRAPFLAG_NORETVAL, "ObtainSemaphore"); + libemu_InstallFunctionFlags(NULL, EXEC_sysbase, -570, TRAPFLAG_NORETVAL, "ReleaseSemaphore"); + libemu_InstallFunctionFlags(NULL, EXEC_sysbase, -576, 0, "AttemptSemaphore"); + libemu_InstallFunctionFlags(NULL, EXEC_sysbase, -582, TRAPFLAG_NORETVAL, "ObtainSemaphoreList"); + libemu_InstallFunctionFlags(NULL, EXEC_sysbase, -588, TRAPFLAG_NORETVAL, "ReleaseSemaphoreList"); +#endif return 0; } +static ULONG execl_Open(void) { return EXEC_sysbase; } + static ULONG execlib_init2(void) { - sysbase = get_long(4); - - libemu_InstallFunction(execl_AllocEntry, sysbase, -222); + EXEC_sysbase = get_long(4); - libemu_InstallFunction(execl_AddLibrary, sysbase, -396); - libemu_InstallFunction(execl_AddDevice, sysbase, -432); - libemu_InstallFunction(execl_AddResource, sysbase, -486); - libemu_InstallFunction(execl_OpenLibrary, sysbase, -552); - libemu_InstallFunction(execl_OpenDevice, sysbase, -444); - libemu_InstallFunction(execl_OpenResource, sysbase, -498); - libemu_InstallFunction(execl_MakeLibrary, sysbase, -84); - - libemu_InstallFunctionFlags(EXEC_Disable, sysbase, -120, TRAPFLAG_NORETVAL); - libemu_InstallFunctionFlags(EXEC_Enable, sysbase, -126, TRAPFLAG_NORETVAL); - libemu_InstallFunctionFlags(EXEC_Permit, sysbase, -138, TRAPFLAG_NORETVAL); - libemu_InstallFunctionFlags(EXEC_Forbid, sysbase, -132, TRAPFLAG_NORETVAL); - - libemu_InstallFunction(execl_AddTask, sysbase, -282); - - libemu_InstallFunction(execl_SetSignal, sysbase, -306); - libemu_InstallFunction(execl_Signal, sysbase, -324); - libemu_InstallFunction(execl_Wait, sysbase, -318); - - libemu_InstallFunction(execl_PutMsg, sysbase, -366); - libemu_InstallFunction(execl_ReplyMsg, sysbase, -378); - libemu_InstallFunction(execl_WaitPort, sysbase, -384); - - libemu_InstallFunction(execl_WaitIO, sysbase, -474); - libemu_InstallFunction(execl_DoIO, sysbase, -456); - libemu_InstallFunction(execl_SendIO, sysbase, -462); - libemu_InstallFunction(execl_CheckIO, sysbase, -468); - - libemu_InstallFunctionFlags(execl_ObtainSemaphore, sysbase, -564, TRAPFLAG_NORETVAL); - libemu_InstallFunctionFlags(execl_ReleaseSemaphore, sysbase, -570, TRAPFLAG_NORETVAL); - libemu_InstallFunction(execl_AttemptSemaphore, sysbase, -576); + libemu_InstallFunctionFlags(execl_Open, EXEC_sysbase, -6, 0, "Open"); + libemu_InstallFunctionFlags(execl_AllocEntry, EXEC_sysbase, -222, 0, "AllocEntry"); + libemu_InstallFunctionFlags(execl_AddMemList, EXEC_sysbase, -618, 0, "AddMemList"); + + libemu_InstallFunctionFlags(execl_AddLibrary, EXEC_sysbase, -396, TRAPFLAG_NORETVAL, "AddLibrary"); + libemu_InstallFunctionFlags(execl_AddDevice, EXEC_sysbase, -432, TRAPFLAG_NORETVAL, "AddDevice"); + libemu_InstallFunctionFlags(execl_AddResource, EXEC_sysbase, -486, TRAPFLAG_NORETVAL, "AddResource"); + libemu_InstallFunctionFlags(execl_OpenLibrary, EXEC_sysbase, -552, 0, "OpenLibrary"); + libemu_InstallFunctionFlags(execl_OldOpenLibrary, EXEC_sysbase, -408, 0, "OldOpenLibrary"); + libemu_InstallFunctionFlags(execl_OpenDevice, EXEC_sysbase, -444, 0, "OpenDevice"); + libemu_InstallFunctionFlags(execl_CloseDevice, EXEC_sysbase, -450, 0, "CloseDevice"); + libemu_InstallFunctionFlags(execl_OpenResource, EXEC_sysbase, -498, 0, "OpenResource"); + libemu_InstallFunctionFlags(execl_MakeLibrary, EXEC_sysbase, -84, 0, "MakeLibrary"); + libemu_InstallFunctionFlags(execl_CloseLibrary, EXEC_sysbase, -414, 0, "CloseLibrary"); + + libemu_InstallFunctionFlags(execl_RawDoFormat, EXEC_sysbase, -522, 0, "RawDoFmt"); + libemu_InstallFunctionFlags(execl_InitResident, EXEC_sysbase, -102, 0, "InitResident"); + + libemu_InstallFunctionFlags(EXEC_Disable, EXEC_sysbase, -120, TRAPFLAG_NORETVAL, ""); + libemu_InstallFunctionFlags(EXEC_Enable, EXEC_sysbase, -126, TRAPFLAG_NORETVAL, ""); + libemu_InstallFunctionFlags(EXEC_Permit, EXEC_sysbase, -138, TRAPFLAG_NORETVAL, "Permit"); + libemu_InstallFunctionFlags(EXEC_Forbid, EXEC_sysbase, -132, TRAPFLAG_NORETVAL, "Forbid"); + + libemu_InstallFunctionFlags(execl_AddTask, EXEC_sysbase, -282, 0, "AddTask"); + libemu_InstallFunctionFlags(execl_RemTask, EXEC_sysbase, -288, TRAPFLAG_NORETVAL, "RemTask"); + libemu_InstallFunctionFlags(execl_SetTaskPri, EXEC_sysbase, -300, 0, "SetTaskPri"); + + libemu_InstallFunctionFlags(execl_SetSignal, EXEC_sysbase, -306, 0, "SetSignal"); + libemu_InstallFunctionFlags(execl_Signal, EXEC_sysbase, -324, TRAPFLAG_NORETVAL, "Signal"); + libemu_InstallFunctionFlags(execl_Wait, EXEC_sysbase, -318, 0, "Wait"); + + libemu_InstallFunctionFlags(execl_PutMsg, EXEC_sysbase, -366, 0, "PutMsg"); + libemu_InstallFunctionFlags(execl_ReplyMsg, EXEC_sysbase, -378, 0, "ReplyMsg"); + libemu_InstallFunctionFlags(execl_WaitPort, EXEC_sysbase, -384, 0, "WaitPort"); + libemu_InstallFunctionFlags(execl_AddPort, EXEC_sysbase, -354, TRAPFLAG_NORETVAL, "AddPort"); + libemu_InstallFunctionFlags(execl_RemPort, EXEC_sysbase, -360, TRAPFLAG_NORETVAL, "RemPort"); + + libemu_InstallFunctionFlags(execl_WaitIO, EXEC_sysbase, -474, 0, "WaitIO"); + libemu_InstallFunctionFlags(execl_DoIO, EXEC_sysbase, -456, 0, "DoIO"); + libemu_InstallFunctionFlags(execl_SendIO, EXEC_sysbase, -462, TRAPFLAG_NORETVAL, "SendIO"); + libemu_InstallFunctionFlags(execl_CheckIO, EXEC_sysbase, -468, 0, "CheckIO"); + libemu_InstallFunctionFlags(execl_AbortIO, EXEC_sysbase, -468, 0, "AbortIO"); + + libemu_InstallFunctionFlags(execl_ObtainSemaphore, EXEC_sysbase, -564, TRAPFLAG_NORETVAL, "ObtainSemaphore"); + libemu_InstallFunctionFlags(execl_ReleaseSemaphore, EXEC_sysbase, -570, TRAPFLAG_NORETVAL, "ReleaseSemaphore"); + libemu_InstallFunctionFlags(execl_AttemptSemaphore, EXEC_sysbase, -576, 0, "AttemptSemaphore"); + libemu_InstallFunctionFlags(execl_ObtainSemaphoreList, EXEC_sysbase, -582, TRAPFLAG_NORETVAL, "ObtainSemaphoreList"); + libemu_InstallFunctionFlags(execl_ReleaseSemaphoreList, EXEC_sysbase, -588, TRAPFLAG_NORETVAL, "ReleaseSemaphoreList"); + libemu_InstallFunctionFlags(execl_FindResident, EXEC_sysbase, -96, 0, "FindResident"); return 0; } @@ -1241,43 +1669,68 @@ static ULONG EXEC_ENOSYS(void) static ULONG EXEC_StandardIntVec(void) { - int num = regs.a[1]; + int num = m68k_areg(regs, 1); /* Call the IntHandlers */ return 0; } +static int trace_ints = 0; + static ULONG EXEC_IntTrap(void) { + struct regstruct rtmp = regs; + struct flag_struct ftmp = regflags; + UWORD intsreq = get_word(0xDFF01E) & get_word(0xDFF01C); - int i; + int i, do_timer = 0; intr_count++; + + if ((intena & 0x4000) == 0) + fprintf(stderr, "Interrupt came in with interrupts off (%x, %x)!\n", get_byte(EXEC_sysbase + 294), get_byte(EXEC_sysbase + 295)); + + TIMER_block(); + + if (regs.spcflags & SPCFLAG_TIMER) { + regs.spcflags &= ~SPCFLAG_TIMER; + do_timer = 1; + } + + TIMER_unblock(); + + if (do_timer) + TIMER_Interrupt(); for (i = 13; i >= 0; i--) { if ((intsreq & (1 << i)) != 0) { - /* Is this a server chain? */ + if (trace_ints) + fprintf(stderr, "INT: %d\n", i); + /* Is this a server chain? */ if (i == 3 || i == 4 || i == 5 || i == 13 || i == 15) { - CPTR slist = get_long(sysbase + 84 + 12*i); + CPTR slist = get_long(EXEC_sysbase + 84 + 12*i); CPTR snode = get_long(slist); for (;;) { if (get_long(snode) == 0) break; - regs.a[0] = 0xDFF000; - regs.a[5] = get_long(snode + 18); - regs.a[1] = get_long(snode + 14); - Call68k(regs.a[5], 0); + m68k_areg(regs, 0) = 0xDFF000; + m68k_areg(regs, 5) = get_long(snode + 18); + m68k_areg(regs, 1) = get_long(snode + 14); + Call68k(m68k_areg(regs, 5), 0); if (ZFLG == 0) break; snode = get_long(snode); } put_word(0xDFF09C, 1 << i); } else { - CPTR intnode = get_long(sysbase + 84 + 12*i + 8); - regs.d[1] = intsreq; - regs.a[1] = get_long(intnode + 14); - regs.a[0] = 0xDFF000; - regs.a[5] = get_long(intnode + 18); - regs.a[6] = sysbase; - Call68k(regs.a[5], 0); + CPTR intnode = get_long(EXEC_sysbase + 84 + 12*i + 8); + /* Blitter interrupts happen before vector is set up :-/ */ + if (intnode != 0) { + m68k_dreg(regs, 1) = intsreq; + m68k_areg(regs, 1) = get_long(intnode + 14); + m68k_areg(regs, 0) = 0xDFF000; + m68k_areg(regs, 5) = get_long(intnode + 18); + m68k_areg(regs, 6) = EXEC_sysbase; + Call68k(m68k_areg(regs, 5), 0); + } } break; } @@ -1285,7 +1738,24 @@ static ULONG EXEC_IntTrap(void) if (i < 0) fprintf(stderr, "So what interrupt am I supposed to serve?\n"); intr_count--; + + /* This usually is a great indicator that the ExecBase pointer at + * address 4 has been messed with... */ + if ((intena & 0x4000) == 0) + fprintf(stderr, "Interrupt left interrupts off (%x, %x)!\n", get_byte(EXEC_sysbase + 294), get_byte(EXEC_sysbase + 295)); + regflags = ftmp; + regs = rtmp; + /* Perform a RTE */ + { + CPTR sra = m68k_areg(regs, 7); + regs.sr = get_word(sra); + m68k_setpc_rte(get_long(sra+2)); + m68k_areg(regs, 7) = sra + 6; + MakeFromSR(); + } + maybe_schedule(); + return 0; /* ignored */ } void execlib_sysinit(void) @@ -1293,7 +1763,7 @@ void execlib_sysinit(void) CPTR tmp, tmp2; CPTR enosys = deftrap(EXEC_ENOSYS); CPTR intvec = deftrap(EXEC_StandardIntVec); - CPTR inttrap = deftrap2(EXEC_IntTrap, TRAPFLAG_NORETVAL); + CPTR inttrap = deftrap2(EXEC_IntTrap, TRAPFLAG_NORETVAL|TRAPFLAG_NOREGSAVE, ""); CPTR sysstack; int i; @@ -1301,36 +1771,55 @@ void execlib_sysinit(void) calltrap2(enosys); dw(RTS); /* why 0x400? */ - sysbase = 0x400 + NR_EXEC_FUNCTIONS*6; - memset(get_real_address(sysbase), 0, 558); - put_long(4, sysbase); + EXEC_sysbase = 0x400 + NR_EXEC_FUNCTIONS*6; + memset(raddr(EXEC_sysbase), 0, 558); + put_long(4, EXEC_sysbase); /* Build vectors. We initialize SetFunction so we can call execlib_Init() */ tmp2 = here(); calltrap(deftrap(execl_SetFunction)); dw(RTS); for (i = 0; i < NR_EXEC_FUNCTIONS; i++) { - put_word(sysbase - 6*(i+1), 0x4EF9); - put_long(sysbase - 6*(i+1) + 2, i == 69 ? tmp2 : tmp); + put_word(EXEC_sysbase - 6*(i+1), 0x4EF9); + put_long(EXEC_sysbase - 6*(i+1) + 2, i == 69 ? tmp2 : tmp); } /* Build syslists */ - EXEC_NewList(sysbase + 322); /* MemList */ - EXEC_NewList(sysbase + 336); /* ResourceList */ - EXEC_NewList(sysbase + 350); /* ResourceList */ - EXEC_NewList(sysbase + 364); /* List */ - EXEC_NewList(sysbase + 378); /* LibList */ - EXEC_NewList(sysbase + 392); /* PortList */ - EXEC_NewList(sysbase + 406); /* TaskReady */ - EXEC_NewList(sysbase + 420); /* TaskWait */ - EXEC_NewList(sysbase + 434); /* SoftInts[5] */ - EXEC_NewList(sysbase + 450); - EXEC_NewList(sysbase + 466); - EXEC_NewList(sysbase + 482); - EXEC_NewList(sysbase + 498); - EXEC_NewList(sysbase + 532); /* SemaphoreList */ - - tmp = sysbase + 558; /* sizeof struct V34 execbase */ + EXEC_NewList(EXEC_sysbase + 322); /* MemList */ + EXEC_NewList(EXEC_sysbase + 336); /* ResourceList */ + EXEC_NewList(EXEC_sysbase + 350); /* ResourceList */ + EXEC_NewList(EXEC_sysbase + 364); /* List */ + EXEC_NewList(EXEC_sysbase + 378); /* LibList */ + EXEC_NewList(EXEC_sysbase + 392); /* PortList */ + EXEC_NewList(EXEC_sysbase + 406); /* TaskReady */ + EXEC_NewList(EXEC_sysbase + 420); /* TaskWait */ + EXEC_NewList(EXEC_sysbase + 434); /* SoftInts[5] */ + EXEC_NewList(EXEC_sysbase + 450); + EXEC_NewList(EXEC_sysbase + 466); + EXEC_NewList(EXEC_sysbase + 482); + EXEC_NewList(EXEC_sysbase + 498); + EXEC_NewList(EXEC_sysbase + 532); /* SemaphoreList */ + + put_long(EXEC_sysbase + 10, ds("exec.library")); + put_word(EXEC_sysbase + 20, 34); put_word(EXEC_sysbase + 22, 0); + put_byte(EXEC_sysbase + 8, NT_LIBRARY); + put_byte(EXEC_sysbase + 9, 0); + + put_long(EXEC_sysbase + 42, 0); + put_long(EXEC_sysbase + 46, 0); + put_long(EXEC_sysbase + 50, 0); + put_long(EXEC_sysbase + 62, chipmem_size); + put_long(EXEC_sysbase + 514, 0xFFFFFFFF); + put_long(EXEC_sysbase + 518, 0); /* seems to contain random values */ + put_long(EXEC_sysbase + 522, 0); + put_long(EXEC_sysbase + 526, 0); + put_word(EXEC_sysbase + 530, 0x3232); + put_long(EXEC_sysbase + 546, 0); + put_long(EXEC_sysbase + 550, 0); + put_long(EXEC_sysbase + 554, 0); + EXEC_Enqueue(EXEC_sysbase + 378, EXEC_sysbase); + + tmp = EXEC_sysbase + 558; /* sizeof struct V34 execbase */ /* We put the supervisor stack at the end, the user stack for our new * task at the end - 0x800, and build the ResModules array at the bottom * of the stack */ @@ -1343,7 +1832,7 @@ void execlib_sysinit(void) /* Set up the CPU */ regs.usp = chipmem_size - 0x800; regs.isp = chipmem_size; /* What about MSP? */ - regs.a[7] = regs.usp; + m68k_areg(regs, 7) = regs.usp; regs.s = 0; regs.m = 0; regs.vbr = 0; regs.t0 = regs.t1 = 0; @@ -1352,15 +1841,15 @@ void execlib_sysinit(void) put_word(0xDFF096, 0x7FFF); put_word(0xDFF09C, 0x7FFF); put_word(0xDFF09A, 0xC000); - put_word(0xDFF096, 0xE100); + put_word(0xDFF096, 0x8200); /* Initialize our supported functions */ execlib_init(); execlib_init2(); /* Initialize interrupts */ intr_count = 0; - put_byte(sysbase + 294, 0xFF); - put_byte(sysbase + 295, 0xFF); + put_byte(EXEC_sysbase + 294, 0xFF); + put_byte(EXEC_sysbase + 295, 0xFF); tmp = here(); calltrap2(inttrap); @@ -1375,15 +1864,17 @@ void execlib_sysinit(void) /* Is this a server chain? */ if (i == 3 || i == 4 || i == 5 || i == 13 || i == 15) EXEC_NewList(tmp2 = EXEC_AllocMem(14, MEMF_PUBLIC)); - put_long(sysbase + 84 + i*12, tmp2); - put_long(sysbase + 84 + i*12 + 4, tmp); - put_long(sysbase + 84 + i*12 + 8, 0); + put_long(EXEC_sysbase + 84 + i*12, tmp2); + put_long(EXEC_sysbase + 84 + i*12 + 4, tmp); + put_long(EXEC_sysbase + 84 + i*12 + 8, 0); } put_word(0xDFF09A, 0xAFC3); /* Enable everything but the server chains */ + + task_to_kill = NULL; /* Set up the init task. We don't really set it up properly. */ tmp = EXEC_AllocMem(92, MEMF_CLEAR); - put_long(sysbase + 276, tmp); - put_byte(tmp + 8, 1); + put_long(EXEC_sysbase + 276, tmp); + put_byte(tmp + 8, NT_TASK); put_byte(tmp + 9, -127); put_long(tmp + 10, ds("init")); put_byte(tmp + 16, 0xFF); @@ -1400,32 +1891,34 @@ void execlib_sysinit(void) /* Set up an idle task */ tmp2 = here(); - dw (0x4E72); dw(0x2000); dw (0x4eF9); dl (tmp2); + dw (0xFF0D); dw (0x4eF9); dl (tmp2); tmp = EXEC_AllocMem(92, MEMF_CLEAR); - put_byte(tmp + 8, 1); + put_byte(tmp + 8, NT_TASK); put_byte(tmp + 9, -128); put_long(tmp + 10, ds("idle")); + put_byte(tmp + 16, 0xFF); + put_byte(tmp + 17, 0xFF); put_long(tmp + 58, chipmem_size - 0x2000); put_long(tmp + 62, chipmem_size - 0x1800); put_long(tmp + 54, chipmem_size - 0x1804); EXEC_NewList(tmp + 74); EXEC_AddTask(tmp, tmp2, 0); /* This won't start executing yet */ - find_newtask(tmp)->regs.s = 1; +/* find_newtask(tmp)->regs.s = 1;*/ /* Grep Kickstart for resident modules */ - regs.a[7] -= 4; - put_long(regs.a[7], 0); - tmp2 = regs.a[7]; + m68k_areg(regs, 7) -= 4; + put_long(m68k_areg(regs, 7), 0); + tmp2 = m68k_areg(regs, 7); for (tmp = 0xF80000; tmp < 0xFFFFFF; tmp += 2) { if (get_word(tmp) == 0x4AFC && get_long(tmp + 2) == tmp) { - regs.a[7] -= 4; put_long(regs.a[7], tmp); + m68k_areg(regs, 7) -= 4; put_long(m68k_areg(regs, 7), tmp); } } - put_long(sysbase + 300, regs.a[7]); + put_long(EXEC_sysbase + 300, m68k_areg(regs, 7)); /* Bubble me do */ - for (tmp = regs.a[7]; tmp < tmp2; tmp += 4) { + for (tmp = m68k_areg(regs, 7); tmp < tmp2; tmp += 4) { CPTR tmp3; for (tmp3 = tmp2 - 4; tmp3 > tmp; tmp3 -= 4) { if ((BYTE)get_byte(get_long(tmp3) + 13) > (BYTE)get_byte(get_long(tmp3 - 4) + 13)) { @@ -1436,15 +1929,21 @@ void execlib_sysinit(void) } } + need_resched = quantum_elapsed = 0; + /* Initialize them and watch everything blow up. */ - for (tmp = regs.a[7]; (tmp2 = get_long(tmp)) != 0; tmp += 4) { + for (tmp = m68k_areg(regs, 7); (tmp2 = get_long(tmp)) != 0; tmp += 4) { UBYTE flags = get_byte(tmp2 + 10); if (!(flags & 1)) /* RTF_COLDSTART? */ continue; - if (strncmp("alert", get_real_address(get_long(tmp2 + 18)), 5) == 0) - /*continue*/; - fprintf(stderr, "Initializing %s\n", get_real_address(get_long(tmp2 + 18))); + fprintf(stderr, "Initializing %s\n", raddr(get_long(tmp2 + 18))); +/* if (strcmp("timer.device", raddr(get_long(tmp2 + 14))) == 0) { + timerdev_init(); + continue; + }*/ + m68k_areg(regs, 6) = EXEC_sysbase; EXEC_InitResident(tmp2, /* ? */ 0); + } /* Idle task */ for(;;) { @@ -1488,3 +1987,10 @@ void execlib_install(void) intr_count = 1; /* So we don't try to schedule if we don't emulate * all of Exec */ } +#else +ULONG EXEC_Forbid(void) { return 0; } +ULONG EXEC_Permit(void) { return 0; } +ULONG EXEC_Enable(void) { return 0; } +ULONG EXEC_Disable(void) { return 0; } +void execlib_install (void) { abort (); } +#endif