|
|
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"
1.1.1.2 root 18: #include "readcpu.h"
1.1 root 19: #include "newcpu.h"
1.1.1.3 root 20: #include "compiler.h"
1.1 root 21: #include "autoconf.h"
1.1.1.3 root 22: #include "osdep/exectasks.h"
1.1 root 23:
1.1.1.2 root 24: /* We'll need a lot of these. */
25: #define MAX_TRAPS 4096
26: static TrapFunction traps[MAX_TRAPS];
1.1.1.3 root 27: static int trapmode[MAX_TRAPS];
1.1.1.2 root 28: static const char *trapstr[MAX_TRAPS];
1.1.1.3 root 29: static uaecptr trapoldfunc[MAX_TRAPS];
1.1.1.2 root 30:
31: static int max_trap = 0;
32: int lasttrap;
33:
1.1.1.3 root 34: /* Stack management */
35:
36: /* The mechanism for doing m68k calls from native code is as follows:
37: *
38: * m68k code executes, stack is main
39: * calltrap to execute_fn_on_extra_stack. new stack is allocated
40: * do_stack_magic is called for the first time
41: * current context is saved with setjmp [0]
42: * transfer_control is done
43: * native code executes on new stack
44: * native code calls call_m68k
45: * setjmp saves current context [1]
46: * longjmp back to execute_fn_on_extra_stack [0]
47: * pointer to new stack is saved on m68k stack. m68k return address set
48: * to 0xF0FF00. m68k PC set to called function
49: * m68k function executes, stack is main
50: * m68k function returns to 0xF0FF00
51: * calltrap to m68k_mode_return
52: * do_stack_magic is called again
53: * current context is saved again with setjmp [0]
54: * this time, transfer_control is _not_ done, instead a longjmp[1]
55: * to the previously saved context
56: * native code executes again on temp stack
57: * native function returns to stack_stub
58: * longjmp[0] back to old context
59: * back again!
60: *
61: * A bearded man enters the room, carrying a bowl of spaghetti.
62: */
63:
64: /* This _shouldn't_ crash with a stack size of 4096, but it does...
65: * might be a bug */
66: #ifndef EXTRA_STACK_SIZE
67: #define EXTRA_STACK_SIZE 65536
68: #endif
69:
70: static void *extra_stack_list = NULL;
71:
1.1.1.4 root 72: static void *get_extra_stack (void)
1.1.1.3 root 73: {
74: void *s = extra_stack_list;
75: if (s)
76: extra_stack_list = *(void **)s;
77: if (!s)
78: s = xmalloc (EXTRA_STACK_SIZE);
79: return s;
1.1 root 80: }
81:
1.1.1.3 root 82: static void free_extra_stack (void *s)
1.1 root 83: {
1.1.1.3 root 84: *(void **)s = extra_stack_list;
85: extra_stack_list = s;
1.1 root 86: }
87:
1.1.1.3 root 88: static void stack_stub (void *s, TrapFunction f, uae_u32 *retval)
1.1 root 89: {
1.1.1.3 root 90: #ifdef CAN_DO_STACK_MAGIC
91: /*printf("in stack_stub: %p %p %p %x\n", s, f, retval, (int)*retval);*/
1.1.1.4 root 92: *retval = f ();
1.1.1.3 root 93: /*write_log ("returning from stack_stub\n");*/
1.1.1.4 root 94: longjmp (((jmp_buf *)s)[0], 1);
1.1.1.3 root 95: #endif
96: }
1.1 root 97:
1.1.1.3 root 98: static void *current_extra_stack = NULL;
99: static uaecptr m68k_calladdr;
100:
1.1.1.4 root 101: static void do_stack_magic (TrapFunction f, void *s, int has_retval)
1.1.1.3 root 102: {
103: #ifdef CAN_DO_STACK_MAGIC
104: uaecptr a7;
105: jmp_buf *j = (jmp_buf *)s;
1.1.1.4 root 106: switch (setjmp (j[0])) {
1.1.1.3 root 107: case 0:
108: /* Returning directly */
109: current_extra_stack = s;
110: if (has_retval == -1) {
111: /*write_log ("finishing m68k mode return\n");*/
1.1.1.4 root 112: longjmp (j[1], 1);
1.1.1.3 root 113: }
114: /*write_log ("calling native function\n");*/
115: transfer_control (s, EXTRA_STACK_SIZE, stack_stub, f, has_retval);
116: /* not reached */
1.1.1.4 root 117: abort ();
1.1.1.3 root 118:
119: case 1:
120: /*write_log ("native function complete\n");*/
121: /* Returning normally. */
122: if (stack_has_retval (s, EXTRA_STACK_SIZE))
123: m68k_dreg (regs, 0) = get_retval_from_stack (s, EXTRA_STACK_SIZE);
124: free_extra_stack (s);
125: break;
126:
127: case 2:
128: /* Returning to do a m68k call. We're now back on the main stack. */
129: a7 = m68k_areg(regs, 7) -= (sizeof (void *) + 7) & ~3;
130: /* Save stack to restore */
131: *((void **)get_real_address (a7 + 4)) = s;
132: /* Save special return address: this address contains a
133: * calltrap that will longjmp to the right stack. */
134: put_long (m68k_areg (regs, 7), 0xF0FF00);
135: m68k_setpc (m68k_calladdr);
136: fill_prefetch_0 ();
137: /*write_log ("native function calls m68k\n");*/
138: break;
1.1 root 139: }
1.1.1.3 root 140: current_extra_stack = 0;
141: #endif
1.1 root 142: }
143:
1.1.1.4 root 144: static uae_u32 execute_fn_on_extra_stack (TrapFunction f, int has_retval)
1.1 root 145: {
1.1.1.3 root 146: #ifdef CAN_DO_STACK_MAGIC
1.1.1.4 root 147: void *s = get_extra_stack ();
1.1.1.3 root 148: do_stack_magic (f, s, has_retval);
149: #endif
150: return 0;
151: }
1.1.1.2 root 152:
1.1.1.4 root 153: static uae_u32 m68k_mode_return (void)
1.1.1.3 root 154: {
155: #ifdef CAN_DO_STACK_MAGIC
156: uaecptr a7 = m68k_areg(regs, 7);
157: void *s = *(void **)get_real_address(a7);
158: m68k_areg(regs, 7) += (sizeof (void *) + 3) & ~3;
159: /*write_log ("doing m68k mode return\n");*/
160: do_stack_magic (NULL, s, -1);
161: #endif
162: return 0;
163: }
1.1.1.2 root 164:
1.1.1.4 root 165: static uae_u32 call_m68k (uaecptr addr, int saveregs)
1.1.1.3 root 166: {
167: volatile uae_u32 retval = 0;
168: volatile int do_save = saveregs;
169: if (current_extra_stack == NULL)
170: abort();
171: #ifdef CAN_DO_STACK_MAGIC
172: {
173: volatile struct regstruct saved_regs;
174: jmp_buf *j = (jmp_buf *)current_extra_stack;
175:
176: if (do_save)
177: saved_regs = regs;
178: m68k_calladdr = addr;
179: switch (setjmp(j[1])) {
180: case 0:
181: /*write_log ("doing call\n");*/
182: /* Returning directly: now switch to main stack and do the call */
183: longjmp (j[0], 2);
184: case 1:
185: /*write_log ("returning from call\n");*/
186: retval = m68k_dreg (regs, 0);
187: if (do_save)
188: regs = saved_regs;
189: /* Returning after the call. */
1.1 root 190: break;
1.1.1.3 root 191: }
1.1 root 192: }
1.1.1.3 root 193: #endif
1.1 root 194: return retval;
195: }
196:
1.1.1.4 root 197: uae_u32 CallLib (uaecptr base, uae_s16 offset)
1.1 root 198: {
1.1.1.3 root 199: int i;
200: uaecptr olda6 = m68k_areg(regs, 6);
201: uae_u32 retval;
202: #if 0
203: for (i = 0; i < n_libpatches; i++) {
204: if (libpatches[i].libbase == base && libpatches[i].functions[-offset/6] != NULL)
205: return (*libpatches[i].functions[-offset/6])();
206: }
207: #endif
208: m68k_areg(regs, 6) = base;
209: retval = call_m68k(base + offset, 1);
210: m68k_areg(regs, 6) = olda6;
211: return retval;
1.1 root 212: }
213:
214: /* Commonly used autoconfig strings */
215:
1.1.1.3 root 216: uaecptr EXPANSION_explibname, EXPANSION_doslibname, EXPANSION_uaeversion;
217: uaecptr EXPANSION_uaedevname, EXPANSION_explibbase = 0, EXPANSION_haveV36;
218: uaecptr EXPANSION_bootcode, EXPANSION_nullfunc;
1.1 root 219:
220: static int current_deviceno = 0;
221:
1.1.1.4 root 222: void reset_uaedevices (void)
223: {
224: current_deviceno = 0;
225: }
226:
227: int get_new_device (char **devname, uaecptr *devname_amiga)
1.1 root 228: {
229: char buffer[80];
1.1.1.3 root 230:
1.1.1.5 root 231: sprintf (buffer, "DH%d", current_deviceno);
1.1 root 232:
1.1.1.4 root 233: *devname_amiga = ds (*devname = my_strdup (buffer));
1.1 root 234: return current_deviceno++;
235: }
236:
237: /* ROM tag area memory access */
238:
1.1.1.3 root 239: static uae_u8 rtarea[65536];
1.1 root 240:
1.1.1.4 root 241: static uae_u32 rtarea_lget (uaecptr) REGPARAM;
242: static uae_u32 rtarea_wget (uaecptr) REGPARAM;
243: static uae_u32 rtarea_bget (uaecptr) REGPARAM;
244: static void rtarea_lput (uaecptr, uae_u32) REGPARAM;
245: static void rtarea_wput (uaecptr, uae_u32) REGPARAM;
246: static void rtarea_bput (uaecptr, uae_u32) REGPARAM;
247: static uae_u8 *rtarea_xlate (uaecptr) REGPARAM;
1.1 root 248:
249: addrbank rtarea_bank = {
250: rtarea_lget, rtarea_wget, rtarea_bget,
251: rtarea_lput, rtarea_wput, rtarea_bput,
252: rtarea_xlate, default_check
253: };
254:
1.1.1.4 root 255: uae_u8 REGPARAM2 *rtarea_xlate (uaecptr addr)
1.1 root 256: {
257: addr &= 0xFFFF;
258: return rtarea + addr;
259: }
260:
1.1.1.4 root 261: uae_u32 REGPARAM2 rtarea_lget (uaecptr addr)
1.1 root 262: {
263: addr &= 0xFFFF;
1.1.1.4 root 264: return (uae_u32)(rtarea_wget (addr) << 16) + rtarea_wget (addr+2);
1.1 root 265: }
266:
1.1.1.4 root 267: uae_u32 REGPARAM2 rtarea_wget (uaecptr addr)
1.1 root 268: {
269: addr &= 0xFFFF;
270: return (rtarea[addr]<<8) + rtarea[addr+1];
271: }
272:
1.1.1.4 root 273: uae_u32 REGPARAM2 rtarea_bget (uaecptr addr)
1.1 root 274: {
275: addr &= 0xFFFF;
276: return rtarea[addr];
277: }
278:
1.1.1.4 root 279: void REGPARAM2 rtarea_lput (uaecptr addr, uae_u32 value) { }
280: void REGPARAM2 rtarea_wput (uaecptr addr, uae_u32 value) { }
281: void REGPARAM2 rtarea_bput (uaecptr addr, uae_u32 value) { }
1.1 root 282:
1.1.1.3 root 283: static int trace_traps = 1;
1.1 root 284:
1.1.1.3 root 285: void REGPARAM2 call_calltrap(int func)
1.1 root 286: {
1.1.1.3 root 287: uae_u32 retval = 0;
288: int has_retval = (trapmode[func] & TRAPFLAG_NO_RETVAL) == 0;
289: int implicit_rts = (trapmode[func] & TRAPFLAG_DORET) != 0;
1.1 root 290:
1.1.1.4 root 291: if (*trapstr[func] != 0 && trace_traps)
292: write_log ("TRAP: %s\n", trapstr[func]);
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])();
1.1.1.4 root 307: } else
308: write_log ("illegal emulator trap\n");
309:
1.1.1.3 root 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:
1.1.1.4 root 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;
1.1.1.4 root 326: uaecptr execbase = get_long (four);
1.1.1.3 root 327: int trnum;
328: uaecptr addr = here();
1.1.1.4 root 329: calltrap (trnum = deftrap2 (f, flags, tracename));
330: dw (RTS);
1.1.1.3 root 331:
332: m68k_areg(regs, 1) = libbase;
333: m68k_areg(regs, 0) = offset;
334: m68k_dreg(regs, 0) = addr;
1.1.1.4 root 335: retval = CallLib (execbase, -420);
1.1.1.3 root 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.4 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.4 root 367: void db (uae_u8 data)
1.1.1.3 root 368: {
369: rtarea[rt_addr++] = data;
370: }
371:
1.1.1.4 root 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.4 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.4 root 390: uae_u32 ds (char *str)
1.1 root 391: {
1.1.1.4 root 392: int len = strlen (str) + 1;
1.1 root 393:
394: rt_straddr -= len;
1.1.1.4 root 395: strcpy ((char *)rtarea + rt_straddr, str);
1.1.1.3 root 396:
1.1.1.4 root 397: return addr (rt_straddr);
1.1 root 398: }
399:
1.1.1.4 root 400: void calltrap (uae_u32 n)
1.1 root 401: {
1.1.1.4 root 402: dw (0xA000 + n);
1.1 root 403: }
404:
1.1.1.4 root 405: void org (uae_u32 a)
1.1 root 406: {
407: rt_addr = a - 0x00F00000;
408: }
409:
1.1.1.4 root 410: uae_u32 here (void)
1.1 root 411: {
1.1.1.4 root 412: return addr (rt_addr);
1.1 root 413: }
414:
1.1.1.4 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.4 root 424: int deftrap (TrapFunction func)
1.1 root 425: {
1.1.1.4 root 426: return deftrap2 (func, 0, "");
1.1 root 427: }
428:
1.1.1.4 root 429: void align (int b)
1.1 root 430: {
1.1.1.4 root 431: rt_addr = (rt_addr + b - 1) & ~(b - 1);
1.1 root 432: }
433:
1.1.1.3 root 434: static uae_u32 nullfunc(void)
1.1 root 435: {
1.1.1.4 root 436: fprintf (stderr, "Null function called\n");
1.1.1.3 root 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.4 root 442: return allocated_chipmem;
1.1 root 443: }
444:
1.1.1.4 root 445: void rtarea_init (void)
1.1 root 446: {
1.1.1.3 root 447: uae_u32 a;
1.1 root 448: char uaever[100];
1.1.1.4 root 449: sprintf (uaever, "uae-%d.%d.%d", UAEMAJOR, UAEMINOR, UAESUBREV);
1.1 root 450:
1.1.1.4 root 451: EXPANSION_uaeversion = ds (uaever);
452: EXPANSION_explibname = ds ("expansion.library");
453: EXPANSION_doslibname = ds ("dos.library");
454: EXPANSION_uaedevname = ds ("uae.device");
1.1 root 455:
1.1.1.4 root 456: deftrap (NULL); /* Generic emulator trap */
1.1 root 457: lasttrap = 0;
458:
1.1.1.4 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.4 root 465: org (0xF0FF00);
1.1.1.3 root 466: calltrap (deftrap2 (m68k_mode_return, TRAPFLAG_NO_RETVAL, ""));
467:
468: org (0xF0FF80);
469: calltrap (deftrap2 (getchipmemsize, TRAPFLAG_DORET, ""));
1.1.1.4 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.