|
|
1.1.1.3 ! root 1: /* 1.1 root 2: * UAE - The Un*x Amiga Emulator 1.1.1.3 ! root 3: * 1.1 root 4: * AutoConfig devices 5: * 1.1.1.2 root 6: * Copyright 1995, 1996 Bernd Schmidt 7: * Copyright 1996 Ed Hanway 1.1 root 8: */ 9: 10: #include "sysconfig.h" 11: #include "sysdeps.h" 12: 13: #include "config.h" 14: #include "options.h" 1.1.1.2 root 15: #include "machdep/m68k.h" 1.1.1.3 ! root 16: #include "uae.h" 1.1 root 17: #include "memory.h" 18: #include "custom.h" 1.1.1.2 root 19: #include "readcpu.h" 1.1 root 20: #include "newcpu.h" 1.1.1.3 ! root 21: #include "compiler.h" 1.1 root 22: #include "autoconf.h" 1.1.1.3 ! root 23: #include "osdep/exectasks.h" 1.1 root 24: 1.1.1.2 root 25: /* We'll need a lot of these. */ 26: #define MAX_TRAPS 4096 27: static TrapFunction traps[MAX_TRAPS]; 1.1.1.3 ! root 28: static int trapmode[MAX_TRAPS]; 1.1.1.2 root 29: static const char *trapstr[MAX_TRAPS]; 1.1.1.3 ! root 30: static uaecptr trapoldfunc[MAX_TRAPS]; 1.1.1.2 root 31: 32: static int max_trap = 0; 33: int lasttrap; 34: 1.1.1.3 ! root 35: /* Stack management */ ! 36: ! 37: /* The mechanism for doing m68k calls from native code is as follows: ! 38: * ! 39: * m68k code executes, stack is main ! 40: * calltrap to execute_fn_on_extra_stack. new stack is allocated ! 41: * do_stack_magic is called for the first time ! 42: * current context is saved with setjmp [0] ! 43: * transfer_control is done ! 44: * native code executes on new stack ! 45: * native code calls call_m68k ! 46: * setjmp saves current context [1] ! 47: * longjmp back to execute_fn_on_extra_stack [0] ! 48: * pointer to new stack is saved on m68k stack. m68k return address set ! 49: * to 0xF0FF00. m68k PC set to called function ! 50: * m68k function executes, stack is main ! 51: * m68k function returns to 0xF0FF00 ! 52: * calltrap to m68k_mode_return ! 53: * do_stack_magic is called again ! 54: * current context is saved again with setjmp [0] ! 55: * this time, transfer_control is _not_ done, instead a longjmp[1] ! 56: * to the previously saved context ! 57: * native code executes again on temp stack ! 58: * native function returns to stack_stub ! 59: * longjmp[0] back to old context ! 60: * back again! ! 61: * ! 62: * A bearded man enters the room, carrying a bowl of spaghetti. ! 63: */ ! 64: ! 65: /* This _shouldn't_ crash with a stack size of 4096, but it does... ! 66: * might be a bug */ ! 67: #ifndef EXTRA_STACK_SIZE ! 68: #define EXTRA_STACK_SIZE 65536 ! 69: #endif ! 70: ! 71: static void *extra_stack_list = NULL; ! 72: ! 73: static void *get_extra_stack(void) ! 74: { ! 75: void *s = extra_stack_list; ! 76: if (s) ! 77: extra_stack_list = *(void **)s; ! 78: if (!s) ! 79: s = xmalloc (EXTRA_STACK_SIZE); ! 80: return s; 1.1 root 81: } 82: 1.1.1.3 ! root 83: static void free_extra_stack (void *s) 1.1 root 84: { 1.1.1.3 ! root 85: *(void **)s = extra_stack_list; ! 86: extra_stack_list = s; 1.1 root 87: } 88: 1.1.1.3 ! root 89: static void stack_stub (void *s, TrapFunction f, uae_u32 *retval) 1.1 root 90: { 1.1.1.3 ! root 91: #ifdef CAN_DO_STACK_MAGIC ! 92: /*printf("in stack_stub: %p %p %p %x\n", s, f, retval, (int)*retval);*/ ! 93: *retval = f(); ! 94: /*write_log ("returning from stack_stub\n");*/ ! 95: longjmp(((jmp_buf *)s)[0], 1); ! 96: #endif ! 97: } 1.1 root 98: 1.1.1.3 ! root 99: static void *current_extra_stack = NULL; ! 100: static uaecptr m68k_calladdr; ! 101: ! 102: static void do_stack_magic(TrapFunction f, void *s, int has_retval) ! 103: { ! 104: #ifdef CAN_DO_STACK_MAGIC ! 105: uaecptr a7; ! 106: jmp_buf *j = (jmp_buf *)s; ! 107: switch (setjmp(j[0])) { ! 108: case 0: ! 109: /* Returning directly */ ! 110: current_extra_stack = s; ! 111: if (has_retval == -1) { ! 112: /*write_log ("finishing m68k mode return\n");*/ ! 113: longjmp(j[1], 1); ! 114: } ! 115: /*write_log ("calling native function\n");*/ ! 116: transfer_control (s, EXTRA_STACK_SIZE, stack_stub, f, has_retval); ! 117: /* not reached */ ! 118: abort(); ! 119: ! 120: case 1: ! 121: /*write_log ("native function complete\n");*/ ! 122: /* Returning normally. */ ! 123: if (stack_has_retval (s, EXTRA_STACK_SIZE)) ! 124: m68k_dreg (regs, 0) = get_retval_from_stack (s, EXTRA_STACK_SIZE); ! 125: free_extra_stack (s); ! 126: break; ! 127: ! 128: case 2: ! 129: /* Returning to do a m68k call. We're now back on the main stack. */ ! 130: a7 = m68k_areg(regs, 7) -= (sizeof (void *) + 7) & ~3; ! 131: /* Save stack to restore */ ! 132: *((void **)get_real_address (a7 + 4)) = s; ! 133: /* Save special return address: this address contains a ! 134: * calltrap that will longjmp to the right stack. */ ! 135: put_long (m68k_areg (regs, 7), 0xF0FF00); ! 136: m68k_setpc (m68k_calladdr); ! 137: fill_prefetch_0 (); ! 138: /*write_log ("native function calls m68k\n");*/ ! 139: break; 1.1 root 140: } 1.1.1.3 ! root 141: current_extra_stack = 0; ! 142: #endif 1.1 root 143: } 144: 1.1.1.3 ! root 145: static uae_u32 execute_fn_on_extra_stack(TrapFunction f, int has_retval) 1.1 root 146: { 1.1.1.3 ! root 147: uae_u32 retval = 0; ! 148: #ifdef CAN_DO_STACK_MAGIC ! 149: void *s = get_extra_stack(); ! 150: do_stack_magic (f, s, has_retval); ! 151: #endif ! 152: return 0; ! 153: } 1.1.1.2 root 154: 1.1.1.3 ! root 155: static uae_u32 m68k_mode_return(void) ! 156: { ! 157: #ifdef CAN_DO_STACK_MAGIC ! 158: uaecptr a7 = m68k_areg(regs, 7); ! 159: void *s = *(void **)get_real_address(a7); ! 160: m68k_areg(regs, 7) += (sizeof (void *) + 3) & ~3; ! 161: /*write_log ("doing m68k mode return\n");*/ ! 162: do_stack_magic (NULL, s, -1); ! 163: #endif ! 164: return 0; ! 165: } 1.1.1.2 root 166: 1.1.1.3 ! root 167: static uae_u32 call_m68k(uaecptr addr, int saveregs) ! 168: { ! 169: volatile uae_u32 retval = 0; ! 170: volatile int do_save = saveregs; ! 171: if (current_extra_stack == NULL) ! 172: abort(); ! 173: #ifdef CAN_DO_STACK_MAGIC ! 174: { ! 175: volatile struct regstruct saved_regs; ! 176: jmp_buf *j = (jmp_buf *)current_extra_stack; ! 177: ! 178: if (do_save) ! 179: saved_regs = regs; ! 180: m68k_calladdr = addr; ! 181: switch (setjmp(j[1])) { ! 182: case 0: ! 183: /*write_log ("doing call\n");*/ ! 184: /* Returning directly: now switch to main stack and do the call */ ! 185: longjmp (j[0], 2); ! 186: case 1: ! 187: /*write_log ("returning from call\n");*/ ! 188: retval = m68k_dreg (regs, 0); ! 189: if (do_save) ! 190: regs = saved_regs; ! 191: /* Returning after the call. */ 1.1 root 192: break; 1.1.1.3 ! root 193: } 1.1 root 194: } 1.1.1.3 ! root 195: #endif 1.1 root 196: return retval; 197: } 198: 1.1.1.3 ! root 199: uae_u32 CallLib(uaecptr base, uae_s16 offset) 1.1 root 200: { 1.1.1.3 ! root 201: int i; ! 202: uaecptr olda6 = m68k_areg(regs, 6); ! 203: uae_u32 retval; ! 204: #if 0 ! 205: for (i = 0; i < n_libpatches; i++) { ! 206: if (libpatches[i].libbase == base && libpatches[i].functions[-offset/6] != NULL) ! 207: return (*libpatches[i].functions[-offset/6])(); ! 208: } ! 209: #endif ! 210: m68k_areg(regs, 6) = base; ! 211: retval = call_m68k(base + offset, 1); ! 212: m68k_areg(regs, 6) = olda6; ! 213: return retval; 1.1 root 214: } 215: 216: /* Commonly used autoconfig strings */ 217: 1.1.1.3 ! root 218: uaecptr EXPANSION_explibname, EXPANSION_doslibname, EXPANSION_uaeversion; ! 219: uaecptr EXPANSION_uaedevname, EXPANSION_explibbase = 0, EXPANSION_haveV36; ! 220: uaecptr EXPANSION_bootcode, EXPANSION_nullfunc; 1.1 root 221: 222: static int current_deviceno = 0; 223: 1.1.1.3 ! root 224: int get_new_device(char **devname, uaecptr *devname_amiga) 1.1 root 225: { 226: char buffer[80]; 1.1.1.3 ! root 227: 1.1 root 228: sprintf(buffer,"UAE%d", current_deviceno); 229: 1.1.1.2 root 230: *devname_amiga = ds(*devname = my_strdup(buffer)); 1.1 root 231: return current_deviceno++; 232: } 233: 234: /* ROM tag area memory access */ 235: 1.1.1.3 ! root 236: static uae_u8 rtarea[65536]; 1.1 root 237: 1.1.1.3 ! root 238: static uae_u32 rtarea_lget(uaecptr) REGPARAM; ! 239: static uae_u32 rtarea_wget(uaecptr) REGPARAM; ! 240: static uae_u32 rtarea_bget(uaecptr) REGPARAM; ! 241: static void rtarea_lput(uaecptr, uae_u32) REGPARAM; ! 242: static void rtarea_wput(uaecptr, uae_u32) REGPARAM; ! 243: static void rtarea_bput(uaecptr, uae_u32) REGPARAM; ! 244: static uae_u8 *rtarea_xlate(uaecptr) REGPARAM; 1.1 root 245: 246: addrbank rtarea_bank = { 247: rtarea_lget, rtarea_wget, rtarea_bget, 248: rtarea_lput, rtarea_wput, rtarea_bput, 249: rtarea_xlate, default_check 250: }; 251: 1.1.1.3 ! root 252: uae_u8 REGPARAM2 *rtarea_xlate(uaecptr addr) 1.1 root 253: { 254: addr &= 0xFFFF; 255: return rtarea + addr; 256: } 257: 1.1.1.3 ! root 258: uae_u32 REGPARAM2 rtarea_lget(uaecptr addr) 1.1 root 259: { 260: addr &= 0xFFFF; 1.1.1.3 ! root 261: return (uae_u32)(rtarea_wget(addr) << 16) + rtarea_wget(addr+2); 1.1 root 262: } 263: 1.1.1.3 ! root 264: uae_u32 REGPARAM2 rtarea_wget(uaecptr addr) 1.1 root 265: { 266: addr &= 0xFFFF; 267: return (rtarea[addr]<<8) + rtarea[addr+1]; 268: } 269: 1.1.1.3 ! root 270: uae_u32 REGPARAM2 rtarea_bget(uaecptr addr) 1.1 root 271: { 1.1.1.3 ! root 272: uae_u16 data; 1.1 root 273: addr &= 0xFFFF; 274: return rtarea[addr]; 275: } 276: 1.1.1.3 ! root 277: void REGPARAM2 rtarea_lput(uaecptr addr, uae_u32 value) { } ! 278: void REGPARAM2 rtarea_wput(uaecptr addr, uae_u32 value) { } ! 279: void REGPARAM2 rtarea_bput(uaecptr addr, uae_u32 value) { } 1.1 root 280: 1.1.1.3 ! root 281: static int trace_traps = 1; 1.1 root 282: 1.1.1.3 ! root 283: void REGPARAM2 call_calltrap(int func) 1.1 root 284: { 1.1.1.3 ! root 285: uae_u32 retval = 0; ! 286: int has_retval = (trapmode[func] & TRAPFLAG_NO_RETVAL) == 0; ! 287: int implicit_rts = (trapmode[func] & TRAPFLAG_DORET) != 0; 1.1 root 288: 1.1.1.3 ! root 289: if (*trapstr[func] != 0 && trace_traps) { ! 290: sprintf (warning_buffer, "TRAP: %s\n", trapstr[func]); ! 291: write_log (warning_buffer); ! 292: } 1.1.1.2 root 293: 294: /* For monitoring only? */ 1.1.1.3 ! root 295: if (traps[func] == NULL) { ! 296: m68k_setpc(trapoldfunc[func]); ! 297: fill_prefetch_0 (); 1.1.1.2 root 298: return; 299: } 1.1.1.3 ! root 300: ! 301: if (func < max_trap) { ! 302: if (trapmode[func] & TRAPFLAG_EXTRA_STACK) { ! 303: execute_fn_on_extra_stack(traps[func], has_retval); ! 304: return; ! 305: } ! 306: retval = (*traps[func])(); ! 307: } else { ! 308: fprintf(stderr, "illegal emulator trap\n"); ! 309: } ! 310: if (has_retval) 1.1.1.2 root 311: m68k_dreg(regs, 0) = retval; 1.1.1.3 ! root 312: if (implicit_rts) { ! 313: m68k_do_rts (); ! 314: fill_prefetch_0 (); 1.1.1.2 root 315: } 1.1 root 316: } 317: 1.1.1.3 ! root 318: /* @$%&� compiler bugs */ ! 319: static volatile int four = 4; ! 320: ! 321: uaecptr libemu_InstallFunctionFlags(TrapFunction f, uaecptr libbase, int offset, ! 322: int flags, const char *tracename) 1.1 root 323: { 1.1.1.3 ! root 324: int i; ! 325: uaecptr retval; ! 326: uaecptr execbase = get_long(four); ! 327: int trnum; ! 328: uaecptr addr = here(); ! 329: calltrap(trnum = deftrap2(f, flags, tracename)); ! 330: dw(RTS); ! 331: ! 332: m68k_areg(regs, 1) = libbase; ! 333: m68k_areg(regs, 0) = offset; ! 334: m68k_dreg(regs, 0) = addr; ! 335: retval = CallLib(execbase, -420); ! 336: ! 337: trapoldfunc[trnum] = retval; ! 338: #if 0 ! 339: for (i = 0; i < n_libpatches; i++) { ! 340: if (libpatches[i].libbase == libbase) ! 341: break; 1.1 root 342: } 1.1.1.3 ! root 343: if (i == n_libpatches) { ! 344: int j; ! 345: libpatches[i].libbase = libbase; ! 346: for (j = 0; j < 300; j++) ! 347: libpatches[i].functions[j] = NULL; ! 348: n_libpatches++; 1.1 root 349: } 1.1.1.3 ! root 350: libpatches[i].functions[-offset/6] = f; ! 351: #endif ! 352: return retval; 1.1 root 353: } 354: 355: /* some quick & dirty code to fill in the rt area and save me a lot of 356: * scratch paper 357: */ 358: 359: static int rt_addr = 0; 360: static int rt_straddr = 0xFF00 - 2; 361: 1.1.1.3 ! root 362: uae_u32 addr(int ptr) 1.1 root 363: { 1.1.1.3 ! root 364: return (uae_u32)ptr + 0x00F00000; 1.1 root 365: } 366: 1.1.1.3 ! root 367: void db(uae_u8 data) ! 368: { ! 369: rtarea[rt_addr++] = data; ! 370: } ! 371: ! 372: void dw(uae_u16 data) 1.1 root 373: { 374: rtarea[rt_addr++] = data >> 8; 375: rtarea[rt_addr++] = data; 376: } 377: 1.1.1.3 ! root 378: void dl(uae_u32 data) 1.1 root 379: { 380: rtarea[rt_addr++] = data >> 24; 381: rtarea[rt_addr++] = data >> 16; 382: rtarea[rt_addr++] = data >> 8; 383: rtarea[rt_addr++] = data; 384: } 385: 386: /* store strings starting at the end of the rt area and working 387: * backward. store pointer at current address 388: */ 389: 1.1.1.3 ! root 390: uae_u32 ds(char *str) 1.1 root 391: { 392: int len = strlen(str) + 1; 393: 394: rt_straddr -= len; 1.1.1.2 root 395: strcpy((char *)rtarea + rt_straddr, str); 1.1.1.3 ! root 396: 1.1 root 397: return addr(rt_straddr); 398: } 399: 1.1.1.3 ! root 400: void calltrap(uae_u32 n) 1.1 root 401: { 1.1.1.3 ! root 402: dw(0xA000 + n); 1.1 root 403: } 404: 1.1.1.3 ! root 405: void org(uae_u32 a) 1.1 root 406: { 407: rt_addr = a - 0x00F00000; 408: } 409: 1.1.1.3 ! root 410: uae_u32 here(void) 1.1 root 411: { 412: return addr(rt_addr); 413: } 414: 1.1.1.3 ! root 415: int deftrap2(TrapFunction func, int mode, const char *str) 1.1 root 416: { 417: int num = max_trap++; 418: traps[num] = func; 1.1.1.3 ! root 419: trapstr[num] = str; ! 420: trapmode[num] = mode; 1.1 root 421: return num; 422: } 423: 1.1.1.3 ! root 424: int deftrap(TrapFunction func) 1.1 root 425: { 1.1.1.3 ! root 426: return deftrap2(func, 0, ""); 1.1 root 427: } 428: 429: void align(int b) 430: { 431: rt_addr = (rt_addr + (b-1)) & ~(b-1); 432: } 433: 1.1.1.3 ! root 434: static uae_u32 nullfunc(void) 1.1 root 435: { 1.1.1.3 ! root 436: fprintf(stderr, "Null function called\n"); ! 437: return 0; 1.1.1.2 root 438: } 439: 1.1.1.3 ! root 440: static uae_u32 getchipmemsize (void) 1.1.1.2 root 441: { 1.1.1.3 ! root 442: return chipmem_size; 1.1 root 443: } 444: 445: void rtarea_init() 446: { 1.1.1.3 ! root 447: uae_u32 a; 1.1 root 448: char uaever[100]; 449: sprintf(uaever, "uae-%d.%d.%d", (version / 100) % 10, (version / 10) % 10, (version / 1) % 10); 450: 451: EXPANSION_uaeversion = ds(uaever); 452: EXPANSION_explibname = ds("expansion.library"); 453: EXPANSION_doslibname = ds("dos.library"); 454: EXPANSION_uaedevname = ds("uae.device"); 455: 456: deftrap(NULL); /* Generic emulator trap */ 457: lasttrap = 0; 458: 1.1.1.2 root 459: EXPANSION_nullfunc = here(); 460: calltrap(deftrap(nullfunc)); 461: dw(RTS); 1.1.1.3 ! root 462: 1.1.1.2 root 463: a = here(); 1.1 root 464: /* Standard "return from 68k mode" trap */ 1.1.1.3 ! root 465: org(0xF0FF00); ! 466: calltrap (deftrap2 (m68k_mode_return, TRAPFLAG_NO_RETVAL, "")); ! 467: ! 468: org (0xF0FF80); ! 469: calltrap (deftrap2 (getchipmemsize, TRAPFLAG_DORET, "")); 1.1 root 470: org(a); 1.1.1.2 root 471: 1.1.1.3 ! root 472: filesys_install_code (); ! 473: } 1.1.1.2 root 474: 1.1.1.3 ! root 475: volatile int uae_int_requested = 0; 1.1.1.2 root 476: 1.1.1.3 ! root 477: void set_uae_int_flag (void) ! 478: { ! 479: rtarea[0xFFFB] = uae_int_requested; 1.1.1.2 root 480: } 481: 482: void rtarea_setup(void) 483: { 484: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.