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