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