--- uae/src/autoconf.c 2018/04/24 16:38:59 1.1.1.2 +++ uae/src/autoconf.c 2018/04/24 17:10:41 1.1.1.11 @@ -1,6 +1,6 @@ - /* + /* * UAE - The Un*x Amiga Emulator - * + * * AutoConfig devices * * Copyright 1995, 1996 Bernd Schmidt @@ -12,239 +12,340 @@ #include "config.h" #include "options.h" -#include "machdep/m68k.h" +#include "uae.h" #include "memory.h" #include "custom.h" -#include "readcpu.h" #include "newcpu.h" -#include "disk.h" -#include "xwin.h" #include "autoconf.h" +#include "osdep/exectasks.h" /* We'll need a lot of these. */ #define MAX_TRAPS 4096 static TrapFunction traps[MAX_TRAPS]; -static char trapmode[MAX_TRAPS]; +static int trapmode[MAX_TRAPS]; static const char *trapstr[MAX_TRAPS]; -static CPTR trapoldfunc[MAX_TRAPS]; +static uaecptr trapoldfunc[MAX_TRAPS]; static int max_trap = 0; -static int trace_traps = 0; int lasttrap; -static struct { - CPTR libbase; - TrapFunction functions[300]; /* I don't think any library has more than 300 functions */ -} libpatches[20]; -static int n_libpatches = 0; - -ULONG Call68k_retaddr(CPTR address, int saveregs, CPTR retaddr) -{ - ULONG retval; - CPTR oldpc = m68k_getpc(); - - struct regstruct backup_regs; - struct flag_struct backup_flags; - - if (saveregs) { - backup_regs = regs; - backup_flags = regflags; - } - m68k_areg(regs, 7) -= 4; - put_long (m68k_areg(regs, 7), retaddr); - m68k_setpc(address); - m68k_go(0); - retval = m68k_dreg(regs, 0); - if (saveregs) { - regs = backup_regs; - regflags = backup_flags; - } - m68k_setpc(oldpc); - return retval; +/* Stack management */ + +/* The mechanism for doing m68k calls from native code is as follows: + * + * m68k code executes, stack is main + * calltrap to execute_fn_on_extra_stack. new stack is allocated + * do_stack_magic is called for the first time + * current context is saved with setjmp [0] + * transfer_control is done + * native code executes on new stack + * native code calls call_m68k + * setjmp saves current context [1] + * longjmp back to execute_fn_on_extra_stack [0] + * pointer to new stack is saved on m68k stack. m68k return address set + * to RTAREA_BASE + 0xFF00. m68k PC set to called function + * m68k function executes, stack is main + * m68k function returns to RTAREA_BASE + 0xFF00 + * calltrap to m68k_mode_return + * do_stack_magic is called again + * current context is saved again with setjmp [0] + * this time, transfer_control is _not_ done, instead a longjmp[1] + * to the previously saved context + * native code executes again on temp stack + * native function returns to stack_stub + * longjmp[0] back to old context + * back again! + * + * A bearded man enters the room, carrying a bowl of spaghetti. + */ + +/* This _shouldn't_ crash with a stack size of 4096, but it does... + * might be a bug */ +#ifndef EXTRA_STACK_SIZE +#define EXTRA_STACK_SIZE 65536 +#endif + +static void *extra_stack_list = NULL; + +static void *get_extra_stack (void) +{ + void *s = extra_stack_list; + if (s) + extra_stack_list = *(void **)s; + if (!s) + s = xmalloc (EXTRA_STACK_SIZE); + return s; } -ULONG Call68k(CPTR address, int saveregs) +static void free_extra_stack (void *s) { - return Call68k_retaddr(address, saveregs, 0xF0FFF0); + *(void **)s = extra_stack_list; + extra_stack_list = s; } -ULONG CallLib(CPTR base, WORD offset) +static void stack_stub (void *s, TrapFunction f, uae_u32 *retval) { - int i; - CPTR olda6 = m68k_areg(regs, 6); - ULONG retval; +#ifdef CAN_DO_STACK_MAGIC + /*printf("in stack_stub: %p %p %p %x\n", s, f, retval, (int)*retval);*/ + *retval = f (); + /*write_log ("returning from stack_stub\n");*/ + longjmp (((jmp_buf *)s)[0], 1); +#endif +} - for (i = 0; i < n_libpatches; i++) { - if (libpatches[i].libbase == base && libpatches[i].functions[-offset/6] != NULL) - return (*libpatches[i].functions[-offset/6])(); +static void *current_extra_stack = NULL; +static uaecptr m68k_calladdr; + +static void do_stack_magic (TrapFunction f, void *s, int has_retval) +{ +#ifdef CAN_DO_STACK_MAGIC + uaecptr a7; + jmp_buf *j = (jmp_buf *)s; + switch (setjmp (j[0])) { + case 0: + /* Returning directly */ + current_extra_stack = s; + if (has_retval == -1) { + /*write_log ("finishing m68k mode return\n");*/ + longjmp (j[1], 1); + } + /*write_log ("calling native function\n");*/ + transfer_control (s, EXTRA_STACK_SIZE, stack_stub, f, has_retval); + /* not reached */ + abort (); + + case 1: + /*write_log ("native function complete\n");*/ + /* Returning normally. */ + if (stack_has_retval (s, EXTRA_STACK_SIZE)) + m68k_dreg (regs, 0) = get_retval_from_stack (s, EXTRA_STACK_SIZE); + free_extra_stack (s); + break; + + case 2: + /* Returning to do a m68k call. We're now back on the main stack. */ + a7 = m68k_areg(regs, 7) -= (sizeof (void *) + 7) & ~3; + /* Save stack to restore */ + *((void **)get_real_address (a7 + 4)) = s; + /* Save special return address: this address contains a + * calltrap that will longjmp to the right stack. */ + put_long (m68k_areg (regs, 7), RTAREA_BASE + 0xFF00); + m68k_setpc (m68k_calladdr); + fill_prefetch_slow (); + /*write_log ("native function calls m68k\n");*/ + break; } - - m68k_areg(regs, 6) = base; - retval = Call68k(base + offset, 1); - m68k_areg(regs, 6) = olda6; - return retval; + current_extra_stack = 0; +#endif } -/* @$%&§ compiler bugs */ -static volatile int four = 4; - -CPTR libemu_InstallFunctionFlags(TrapFunction f, CPTR libbase, int offset, - int flags, const char *tracename) +static uae_u32 execute_fn_on_extra_stack (TrapFunction f, int has_retval) { - int i; - CPTR retval; - CPTR execbase = get_long(four); - int trnum; - ULONG addr = here(); - calltrap2(trnum = deftrap2(f, flags, tracename)); - dw(RTS); - - m68k_areg(regs, 1) = libbase; - m68k_areg(regs, 0) = offset; - m68k_dreg(regs, 0) = addr; - retval = CallLib(execbase, -420); +#ifdef CAN_DO_STACK_MAGIC + void *s = get_extra_stack (); + do_stack_magic (f, s, has_retval); +#endif + return 0; +} - trapoldfunc[trnum] = retval; +static uae_u32 m68k_mode_return (void) +{ +#ifdef CAN_DO_STACK_MAGIC + uaecptr a7 = m68k_areg(regs, 7); + void *s = *(void **)get_real_address(a7); + m68k_areg(regs, 7) += (sizeof (void *) + 3) & ~3; + /*write_log ("doing m68k mode return\n");*/ + do_stack_magic (NULL, s, -1); +#endif + return 0; +} - for (i = 0; i < n_libpatches; i++) { - if (libpatches[i].libbase == libbase) +static uae_u32 call_m68k (uaecptr addr, int saveregs) +{ + volatile uae_u32 retval = 0; + volatile int do_save = saveregs; + if (current_extra_stack == NULL) + abort(); +#ifdef CAN_DO_STACK_MAGIC + { + volatile struct regstruct saved_regs; + jmp_buf *j = (jmp_buf *)current_extra_stack; + + if (do_save) + saved_regs = regs; + m68k_calladdr = addr; + switch (setjmp(j[1])) { + case 0: + /*write_log ("doing call\n");*/ + /* Returning directly: now switch to main stack and do the call */ + longjmp (j[0], 2); + case 1: + /*write_log ("returning from call\n");*/ + retval = m68k_dreg (regs, 0); + if (do_save) + regs = saved_regs; + /* Returning after the call. */ break; + } } - if (i == n_libpatches) { - int j; - libpatches[i].libbase = libbase; - for (j = 0; j < 300; j++) - libpatches[i].functions[j] = NULL; - n_libpatches++; - } - libpatches[i].functions[-offset/6] = f; +#endif return retval; } -CPTR libemu_InstallFunction(TrapFunction f, CPTR libbase, int offset, - const char *tracename) +uae_u32 CallLib (uaecptr base, uae_s16 offset) { - return libemu_InstallFunctionFlags(f, libbase, offset, 0, tracename); + int i; + uaecptr olda6 = m68k_areg(regs, 6); + uae_u32 retval; +#if 0 + for (i = 0; i < n_libpatches; i++) { + if (libpatches[i].libbase == base && libpatches[i].functions[-offset/6] != NULL) + return (*libpatches[i].functions[-offset/6])(); + } +#endif + m68k_areg(regs, 6) = base; + retval = call_m68k(base + offset, 1); + m68k_areg(regs, 6) = olda6; + return retval; } /* Commonly used autoconfig strings */ -CPTR EXPANSION_explibname, EXPANSION_doslibname, EXPANSION_uaeversion; -CPTR EXPANSION_uaedevname, EXPANSION_explibbase = 0, EXPANSION_haveV36; -CPTR EXPANSION_bootcode, EXPANSION_nullfunc; - -static int current_deviceno = 0; - -int get_new_device(char **devname, CPTR *devname_amiga) -{ - char buffer[80]; - - sprintf(buffer,"UAE%d", current_deviceno); - - *devname_amiga = ds(*devname = my_strdup(buffer)); - return current_deviceno++; -} +uaecptr EXPANSION_explibname, EXPANSION_doslibname, EXPANSION_uaeversion; +uaecptr EXPANSION_uaedevname, EXPANSION_explibbase = 0, EXPANSION_haveV36; +uaecptr EXPANSION_bootcode, EXPANSION_nullfunc; +uaecptr EXPANSION_cddevice; /* ROM tag area memory access */ -static UBYTE rtarea[65536]; +static uae_u8 *rtarea; -static ULONG rtarea_lget(CPTR) REGPARAM; -static ULONG rtarea_wget(CPTR) REGPARAM; -static ULONG rtarea_bget(CPTR) REGPARAM; -static void rtarea_lput(CPTR, ULONG) REGPARAM; -static void rtarea_wput(CPTR, ULONG) REGPARAM; -static void rtarea_bput(CPTR, ULONG) REGPARAM; -static UBYTE *rtarea_xlate(CPTR) REGPARAM; +static uae_u32 rtarea_lget (uaecptr) REGPARAM; +static uae_u32 rtarea_wget (uaecptr) REGPARAM; +static uae_u32 rtarea_bget (uaecptr) REGPARAM; +static void rtarea_lput (uaecptr, uae_u32) REGPARAM; +static void rtarea_wput (uaecptr, uae_u32) REGPARAM; +static void rtarea_bput (uaecptr, uae_u32) REGPARAM; +static uae_u8 *rtarea_xlate (uaecptr) REGPARAM; addrbank rtarea_bank = { - rtarea_lget, rtarea_wget, rtarea_lget, rtarea_wget, rtarea_bget, rtarea_lput, rtarea_wput, rtarea_bput, - rtarea_xlate, default_check + rtarea_xlate, default_check, NULL }; -UBYTE REGPARAM2 *rtarea_xlate(CPTR addr) +uae_u8 REGPARAM2 *rtarea_xlate (uaecptr addr) { addr &= 0xFFFF; return rtarea + addr; } -ULONG REGPARAM2 rtarea_lget(CPTR addr) +uae_u32 REGPARAM2 rtarea_lget (uaecptr addr) { + special_mem |= S_READ; addr &= 0xFFFF; - return (ULONG)(rtarea_wget(addr) << 16) + rtarea_wget(addr+2); + return (uae_u32)(rtarea_wget (addr) << 16) + rtarea_wget (addr+2); } -ULONG REGPARAM2 rtarea_wget(CPTR addr) +uae_u32 REGPARAM2 rtarea_wget (uaecptr addr) { + special_mem |= S_READ; addr &= 0xFFFF; return (rtarea[addr]<<8) + rtarea[addr+1]; } -ULONG REGPARAM2 rtarea_bget(CPTR addr) +uae_u32 REGPARAM2 rtarea_bget (uaecptr addr) { - UWORD data; + special_mem |= S_READ; addr &= 0xFFFF; return rtarea[addr]; } -void REGPARAM2 rtarea_lput(CPTR addr, ULONG value) { } -void REGPARAM2 rtarea_bput(CPTR addr, ULONG value) { } +void REGPARAM2 rtarea_lput (uaecptr addr, uae_u32 value) +{ + special_mem |= S_WRITE; +} -/* Don't start at 0 -- can get bogus writes there. */ -static ULONG trap_base_addr = 0x00F00180; +void REGPARAM2 rtarea_wput (uaecptr addr, uae_u32 value) +{ + special_mem |= S_WRITE; +} -void do_emultrap(int tr) +void REGPARAM2 rtarea_bput (uaecptr addr, uae_u32 value) { - struct regstruct backup_regs; - ULONG retval; + special_mem |= S_WRITE; +} - if (*trapstr[tr] != 0 && trace_traps) - fprintf(stderr, "TRAP: %s\n", trapstr[tr]); +static int trace_traps = 1; + +void REGPARAM2 call_calltrap(int func) +{ + uae_u32 retval = 0; + int has_retval = (trapmode[func] & TRAPFLAG_NO_RETVAL) == 0; + int implicit_rts = (trapmode[func] & TRAPFLAG_DORET) != 0; + + if (*trapstr[func] != 0 && trace_traps) + write_log ("TRAP: %s\n", trapstr[func]); /* For monitoring only? */ - if (traps[tr] == NULL) { - Call68k(trapoldfunc[tr], 0); - if (*trapstr[tr] != 0 && trace_traps) - fprintf(stderr, "RET : %s\n", trapstr[tr]); + if (traps[func] == NULL) { + m68k_setpc(trapoldfunc[func]); + fill_prefetch_slow (); return; } - - if ((trapmode[tr] & TRAPFLAG_NOREGSAVE) == 0) - backup_regs = regs; - - retval = (*traps[tr])(); - - if ((trapmode[tr] & TRAPFLAG_NOREGSAVE) == 0) - regs = backup_regs; - if ((trapmode[tr] & TRAPFLAG_NORETVAL) == 0) { + + if (func < max_trap) { + if (trapmode[func] & TRAPFLAG_EXTRA_STACK) { + execute_fn_on_extra_stack(traps[func], has_retval); + return; + } + retval = (*traps[func])(); + } else + write_log ("illegal emulator trap\n"); + + if (has_retval) m68k_dreg(regs, 0) = retval; + if (implicit_rts) { + m68k_do_rts (); + fill_prefetch_slow (); } } -void REGPARAM2 rtarea_wput(CPTR addr, ULONG value) +/* @$%&§ compiler bugs */ +static volatile int four = 4; + +uaecptr libemu_InstallFunctionFlags (TrapFunction f, uaecptr libbase, int offset, + int flags, const char *tracename) { - /* Save all registers */ - struct regstruct backup_regs; - ULONG retval = 0; - ULONG func = ((addr - trap_base_addr) & 0xFFFF) >> 1; - - if (func == 0) { - lasttrap = get_long(m68k_areg(regs, 7)); - m68k_areg(regs, 7) += 4; - regs.spcflags |= SPCFLAG_EMULTRAP; - return; + int i; + uaecptr retval; + uaecptr execbase = get_long (four); + int trnum; + uaecptr addr = here(); + calltrap (trnum = deftrap2 (f, flags, tracename)); + dw (RTS); + + m68k_areg(regs, 1) = libbase; + m68k_areg(regs, 0) = offset; + m68k_dreg(regs, 0) = addr; + retval = CallLib (execbase, -420); + + trapoldfunc[trnum] = retval; +#if 0 + for (i = 0; i < n_libpatches; i++) { + if (libpatches[i].libbase == libbase) + break; } - - backup_regs = regs; - if(func < max_trap) { - retval = (*traps[func])(); - } else { - fprintf(stderr, "illegal emulator trap\n"); + if (i == n_libpatches) { + int j; + libpatches[i].libbase = libbase; + for (j = 0; j < 300; j++) + libpatches[i].functions[j] = NULL; + n_libpatches++; } - regs = backup_regs; - m68k_dreg(regs, 0) = retval; + libpatches[i].functions[-offset/6] = f; +#endif + return retval; } /* some quick & dirty code to fill in the rt area and save me a lot of @@ -254,18 +355,23 @@ void REGPARAM2 rtarea_wput(CPTR addr, UL static int rt_addr = 0; static int rt_straddr = 0xFF00 - 2; -ULONG addr(int ptr) +uae_u32 addr (int ptr) { - return (ULONG)ptr + 0x00F00000; + return (uae_u32)ptr + RTAREA_BASE; } -void dw(UWORD data) +void db (uae_u8 data) +{ + rtarea[rt_addr++] = data; +} + +void dw (uae_u16 data) { rtarea[rt_addr++] = data >> 8; rtarea[rt_addr++] = data; } -void dl(ULONG data) +void dl (uae_u32 data) { rtarea[rt_addr++] = data >> 24; rtarea[rt_addr++] = data >> 16; @@ -277,174 +383,122 @@ void dl(ULONG data) * backward. store pointer at current address */ -ULONG ds(char *str) +uae_u32 ds (char *str) { - int len = strlen(str) + 1; + int len = strlen (str) + 1; rt_straddr -= len; - strcpy((char *)rtarea + rt_straddr, str); - - return addr(rt_straddr); -} + strcpy ((char *)rtarea + rt_straddr, str); -void calltrap2(ULONG n) -{ - dw(0x4878); /* PEA.L n.w */ - dw(n); - /* Call trap #0 is reserved for this */ - dw(0x33C0); /* MOVE.W D0,abs32 */ - dl(trap_base_addr); + return addr (rt_straddr); } -void calltrap(ULONG n) +void calltrap (uae_u32 n) { -#if 1 - dw(0x33C0); /* MOVE.W D0,abs32 */ - dl(n*2 + trap_base_addr); -#else - calltrap2(n); -#endif + dw (0xA000 + n); } -void org(ULONG a) +void org (uae_u32 a) { - rt_addr = a - 0x00F00000; + rt_addr = a - RTAREA_BASE; } -ULONG here(void) +uae_u32 here (void) { - return addr(rt_addr); + return addr (rt_addr); } -int deftrap(TrapFunction func) +int deftrap2 (TrapFunction func, int mode, const char *str) { int num = max_trap++; traps[num] = func; - trapmode[num] = 0; - trapstr[num] = ""; + trapstr[num] = str; + trapmode[num] = mode; return num; } -int deftrap2(TrapFunction func, int mode, const char *str) +int deftrap (TrapFunction func) { - int num = max_trap++; - traps[num] = func; - trapmode[num] = mode; - trapstr[num] = str; - return num; + return deftrap2 (func, 0, ""); +} + +void align (int b) +{ + rt_addr = (rt_addr + b - 1) & ~(b - 1); } -void align(int b) +static uae_u32 nullfunc(void) { - rt_addr = (rt_addr + (b-1)) & ~(b-1); + write_log ("Null function called\n"); + return 0; } -static ULONG bootcode(void) +static uae_u32 getchipmemsize (void) { - m68k_areg(regs, 1) = EXPANSION_doslibname; - m68k_dreg(regs, 0) = CallLib (m68k_areg(regs, 6), -96); /* FindResident() */ - m68k_areg(regs, 0) = get_long(m68k_dreg(regs, 0) + 22); /* get dos.library rt_init */ - return m68k_areg(regs, 0); + return allocated_chipmem; } -static ULONG nullfunc(void) +static uae_u32 uae_puts (void) { - fprintf(stderr, "Null function called\n"); + puts (get_real_address (m68k_areg (regs, 0))); return 0; } -void rtarea_init() +static void rtarea_init_mem (void) { - ULONG a; + rtarea = mapped_malloc (0x10000, "rtarea"); + if (!rtarea) { + write_log ("virtual memory exhausted (rtarea)!\n"); + abort (); + } + rtarea_bank.baseaddr = rtarea; +} + +void rtarea_init (void) +{ + uae_u32 a; char uaever[100]; - sprintf(uaever, "uae-%d.%d.%d", (version / 100) % 10, (version / 10) % 10, (version / 1) % 10); - EXPANSION_uaeversion = ds(uaever); - EXPANSION_explibname = ds("expansion.library"); - EXPANSION_doslibname = ds("dos.library"); - EXPANSION_uaedevname = ds("uae.device"); + rtarea_init_mem (); + + sprintf (uaever, "uae-%d.%d.%d", UAEMAJOR, UAEMINOR, UAESUBREV); + + EXPANSION_uaeversion = ds (uaever); + EXPANSION_explibname = ds ("expansion.library"); + EXPANSION_doslibname = ds ("dos.library"); + EXPANSION_uaedevname = ds ("uae.device"); - deftrap(NULL); /* Generic emulator trap */ + deftrap (NULL); /* Generic emulator trap */ lasttrap = 0; - align(4); - EXPANSION_bootcode = here(); - calltrap2(deftrap2(bootcode, 1, "")); - dw(0x2040); /* move.l d0,a0 */ - dw(0x4e90); /* jsr (a0) */ - dw(RTS); - - EXPANSION_nullfunc = here(); - calltrap(deftrap(nullfunc)); - dw(RTS); - + EXPANSION_nullfunc = here (); + calltrap (deftrap (nullfunc)); + dw (RTS); + a = here(); /* Standard "return from 68k mode" trap */ - org(0xF0FFF0); - calltrap2(0); - dw(RTS); - org(a); -} - -static ULONG hyperchip_init(void) -{ -#if 0 /* This doesn't work either. Arrrgh!! */ - CPTR execbase = get_long(4); - CPTR memlist = execbase + 322; - CPTR memh; - - for (;;) { - memh = get_long(memlist); - if (get_long(memh) == 0) { - fprintf(stderr, "No chip memory !?!??\n"); - return 0; - } + org (RTAREA_BASE + 0xFF00); + calltrap (deftrap2 (m68k_mode_return, TRAPFLAG_NO_RETVAL, "")); - if (get_word(memh + 14) == 3) - break; + org (RTAREA_BASE + 0xFF80); + calltrap (deftrap2 (getchipmemsize, TRAPFLAG_DORET, "")); - memlist = memh; - } - put_long(memh + 24, get_long(memh + 24) + chipmem_size - 0x200000); - put_long(memh + 28, get_long(memh + 28) + chipmem_size - 0x200000); - memlist = memh + 16; - for (;;) { - memh = get_long(memlist); - if (memh == 0) - break; - memlist = memh; - } - put_long(memlist, 0x200000); - put_long(0x200000, 0); - put_long(0x200004, chipmem_size - 0x200000); -#endif - return 0; + org (RTAREA_BASE + 0xFF10); + calltrap (deftrap2 (uae_puts, TRAPFLAG_NO_RETVAL, "")); + dw (RTS); + + org (a); + + filesys_install_code (); +} + +volatile int uae_int_requested = 0; + +void set_uae_int_flag (void) +{ + rtarea[0xFFFB] = uae_int_requested; } void rtarea_setup(void) { -#if 0 - if (chipmem_size > 0x200000) { - CPTR a = here(); - /* Build a struct Resident for the 8MB chipmem support */ - dw(0x4AFC); - dl(a); - dl(a + 0x1A); /* Continue scan here */ - dw(0x0101); /* RTF_COLDSTART; Version 1 */ - dw(0x0305); /* NT_DEVICE; pri 05 */ - a = ds("UAE HyperChip (tm)"); - dl(a); dl(a); /* Identification */ - dl(here() + 4); /* Init code */ - - calltrap(deftrap(hyperchip_init)); -#if 0 /* This doesn't work for some reason */ - dw(0x2c78); dw(4); /* move.l $4,a6 */ - dw(0x203c); dl(chipmem_size - 0x200000); - dw(0x7203); dw(0x74f6); - dw(0x207c); dl(0x200000); - dw(0x227c); dl(ds("Chip RAM")); - dw(0x4eee); dw(0xfd96); /* jmp AddMemList(a6) */ -#endif - } -#endif }