|
|
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:
1.1.1.4 ! root 73: static void *get_extra_stack (void)
1.1.1.3 root 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);*/
1.1.1.4 ! root 93: *retval = f ();
1.1.1.3 root 94: /*write_log ("returning from stack_stub\n");*/
1.1.1.4 ! root 95: longjmp (((jmp_buf *)s)[0], 1);
1.1.1.3 root 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:
1.1.1.4 ! root 102: static void do_stack_magic (TrapFunction f, void *s, int has_retval)
1.1.1.3 root 103: {
104: #ifdef CAN_DO_STACK_MAGIC
105: uaecptr a7;
106: jmp_buf *j = (jmp_buf *)s;
1.1.1.4 ! root 107: switch (setjmp (j[0])) {
1.1.1.3 root 108: case 0:
109: /* Returning directly */
110: current_extra_stack = s;
111: if (has_retval == -1) {
112: /*write_log ("finishing m68k mode return\n");*/
1.1.1.4 ! root 113: longjmp (j[1], 1);
1.1.1.3 root 114: }
115: /*write_log ("calling native function\n");*/
116: transfer_control (s, EXTRA_STACK_SIZE, stack_stub, f, has_retval);
117: /* not reached */
1.1.1.4 ! root 118: abort ();
1.1.1.3 root 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.4 ! 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: #ifdef CAN_DO_STACK_MAGIC
1.1.1.4 ! root 148: void *s = get_extra_stack ();
1.1.1.3 root 149: do_stack_magic (f, s, has_retval);
150: #endif
151: return 0;
152: }
1.1.1.2 root 153:
1.1.1.4 ! root 154: static uae_u32 m68k_mode_return (void)
1.1.1.3 root 155: {
156: #ifdef CAN_DO_STACK_MAGIC
157: uaecptr a7 = m68k_areg(regs, 7);
158: void *s = *(void **)get_real_address(a7);
159: m68k_areg(regs, 7) += (sizeof (void *) + 3) & ~3;
160: /*write_log ("doing m68k mode return\n");*/
161: do_stack_magic (NULL, s, -1);
162: #endif
163: return 0;
164: }
1.1.1.2 root 165:
1.1.1.4 ! root 166: static uae_u32 call_m68k (uaecptr addr, int saveregs)
1.1.1.3 root 167: {
168: volatile uae_u32 retval = 0;
169: volatile int do_save = saveregs;
170: if (current_extra_stack == NULL)
171: abort();
172: #ifdef CAN_DO_STACK_MAGIC
173: {
174: volatile struct regstruct saved_regs;
175: jmp_buf *j = (jmp_buf *)current_extra_stack;
176:
177: if (do_save)
178: saved_regs = regs;
179: m68k_calladdr = addr;
180: switch (setjmp(j[1])) {
181: case 0:
182: /*write_log ("doing call\n");*/
183: /* Returning directly: now switch to main stack and do the call */
184: longjmp (j[0], 2);
185: case 1:
186: /*write_log ("returning from call\n");*/
187: retval = m68k_dreg (regs, 0);
188: if (do_save)
189: regs = saved_regs;
190: /* Returning after the call. */
1.1 root 191: break;
1.1.1.3 root 192: }
1.1 root 193: }
1.1.1.3 root 194: #endif
1.1 root 195: return retval;
196: }
197:
1.1.1.4 ! root 198: uae_u32 CallLib (uaecptr base, uae_s16 offset)
1.1 root 199: {
1.1.1.3 root 200: int i;
201: uaecptr olda6 = m68k_areg(regs, 6);
202: uae_u32 retval;
203: #if 0
204: for (i = 0; i < n_libpatches; i++) {
205: if (libpatches[i].libbase == base && libpatches[i].functions[-offset/6] != NULL)
206: return (*libpatches[i].functions[-offset/6])();
207: }
208: #endif
209: m68k_areg(regs, 6) = base;
210: retval = call_m68k(base + offset, 1);
211: m68k_areg(regs, 6) = olda6;
212: return retval;
1.1 root 213: }
214:
215: /* Commonly used autoconfig strings */
216:
1.1.1.3 root 217: uaecptr EXPANSION_explibname, EXPANSION_doslibname, EXPANSION_uaeversion;
218: uaecptr EXPANSION_uaedevname, EXPANSION_explibbase = 0, EXPANSION_haveV36;
219: uaecptr EXPANSION_bootcode, EXPANSION_nullfunc;
1.1 root 220:
221: static int current_deviceno = 0;
222:
1.1.1.4 ! root 223: void reset_uaedevices (void)
! 224: {
! 225: current_deviceno = 0;
! 226: }
! 227:
! 228: int get_new_device (char **devname, uaecptr *devname_amiga)
1.1 root 229: {
230: char buffer[80];
1.1.1.3 root 231:
1.1.1.4 ! root 232: sprintf (buffer, "UAE%d", current_deviceno);
1.1 root 233:
1.1.1.4 ! root 234: *devname_amiga = ds (*devname = my_strdup (buffer));
1.1 root 235: return current_deviceno++;
236: }
237:
238: /* ROM tag area memory access */
239:
1.1.1.3 root 240: static uae_u8 rtarea[65536];
1.1 root 241:
1.1.1.4 ! root 242: static uae_u32 rtarea_lget (uaecptr) REGPARAM;
! 243: static uae_u32 rtarea_wget (uaecptr) REGPARAM;
! 244: static uae_u32 rtarea_bget (uaecptr) REGPARAM;
! 245: static void rtarea_lput (uaecptr, uae_u32) REGPARAM;
! 246: static void rtarea_wput (uaecptr, uae_u32) REGPARAM;
! 247: static void rtarea_bput (uaecptr, uae_u32) REGPARAM;
! 248: static uae_u8 *rtarea_xlate (uaecptr) REGPARAM;
1.1 root 249:
250: addrbank rtarea_bank = {
251: rtarea_lget, rtarea_wget, rtarea_bget,
252: rtarea_lput, rtarea_wput, rtarea_bput,
253: rtarea_xlate, default_check
254: };
255:
1.1.1.4 ! root 256: uae_u8 REGPARAM2 *rtarea_xlate (uaecptr addr)
1.1 root 257: {
258: addr &= 0xFFFF;
259: return rtarea + addr;
260: }
261:
1.1.1.4 ! root 262: uae_u32 REGPARAM2 rtarea_lget (uaecptr addr)
1.1 root 263: {
264: addr &= 0xFFFF;
1.1.1.4 ! root 265: return (uae_u32)(rtarea_wget (addr) << 16) + rtarea_wget (addr+2);
1.1 root 266: }
267:
1.1.1.4 ! root 268: uae_u32 REGPARAM2 rtarea_wget (uaecptr addr)
1.1 root 269: {
270: addr &= 0xFFFF;
271: return (rtarea[addr]<<8) + rtarea[addr+1];
272: }
273:
1.1.1.4 ! root 274: uae_u32 REGPARAM2 rtarea_bget (uaecptr addr)
1.1 root 275: {
276: addr &= 0xFFFF;
277: return rtarea[addr];
278: }
279:
1.1.1.4 ! root 280: void REGPARAM2 rtarea_lput (uaecptr addr, uae_u32 value) { }
! 281: void REGPARAM2 rtarea_wput (uaecptr addr, uae_u32 value) { }
! 282: void REGPARAM2 rtarea_bput (uaecptr addr, uae_u32 value) { }
1.1 root 283:
1.1.1.3 root 284: static int trace_traps = 1;
1.1 root 285:
1.1.1.3 root 286: void REGPARAM2 call_calltrap(int func)
1.1 root 287: {
1.1.1.3 root 288: uae_u32 retval = 0;
289: int has_retval = (trapmode[func] & TRAPFLAG_NO_RETVAL) == 0;
290: int implicit_rts = (trapmode[func] & TRAPFLAG_DORET) != 0;
1.1 root 291:
1.1.1.4 ! root 292: if (*trapstr[func] != 0 && trace_traps)
! 293: write_log ("TRAP: %s\n", trapstr[func]);
1.1.1.2 root 294:
295: /* For monitoring only? */
1.1.1.3 root 296: if (traps[func] == NULL) {
297: m68k_setpc(trapoldfunc[func]);
298: fill_prefetch_0 ();
1.1.1.2 root 299: return;
300: }
1.1.1.3 root 301:
302: if (func < max_trap) {
303: if (trapmode[func] & TRAPFLAG_EXTRA_STACK) {
304: execute_fn_on_extra_stack(traps[func], has_retval);
305: return;
306: }
307: retval = (*traps[func])();
1.1.1.4 ! root 308: } else
! 309: write_log ("illegal emulator trap\n");
! 310:
1.1.1.3 root 311: if (has_retval)
1.1.1.2 root 312: m68k_dreg(regs, 0) = retval;
1.1.1.3 root 313: if (implicit_rts) {
314: m68k_do_rts ();
315: fill_prefetch_0 ();
1.1.1.2 root 316: }
1.1 root 317: }
318:
1.1.1.3 root 319: /* @$%&� compiler bugs */
320: static volatile int four = 4;
321:
1.1.1.4 ! root 322: uaecptr libemu_InstallFunctionFlags (TrapFunction f, uaecptr libbase, int offset,
! 323: int flags, const char *tracename)
1.1 root 324: {
1.1.1.3 root 325: int i;
326: uaecptr retval;
1.1.1.4 ! root 327: uaecptr execbase = get_long (four);
1.1.1.3 root 328: int trnum;
329: uaecptr addr = here();
1.1.1.4 ! root 330: calltrap (trnum = deftrap2 (f, flags, tracename));
! 331: dw (RTS);
1.1.1.3 root 332:
333: m68k_areg(regs, 1) = libbase;
334: m68k_areg(regs, 0) = offset;
335: m68k_dreg(regs, 0) = addr;
1.1.1.4 ! root 336: retval = CallLib (execbase, -420);
1.1.1.3 root 337:
338: trapoldfunc[trnum] = retval;
339: #if 0
340: for (i = 0; i < n_libpatches; i++) {
341: if (libpatches[i].libbase == libbase)
342: break;
1.1 root 343: }
1.1.1.3 root 344: if (i == n_libpatches) {
345: int j;
346: libpatches[i].libbase = libbase;
347: for (j = 0; j < 300; j++)
348: libpatches[i].functions[j] = NULL;
349: n_libpatches++;
1.1 root 350: }
1.1.1.3 root 351: libpatches[i].functions[-offset/6] = f;
352: #endif
353: return retval;
1.1 root 354: }
355:
356: /* some quick & dirty code to fill in the rt area and save me a lot of
357: * scratch paper
358: */
359:
360: static int rt_addr = 0;
361: static int rt_straddr = 0xFF00 - 2;
362:
1.1.1.4 ! root 363: uae_u32 addr (int ptr)
1.1 root 364: {
1.1.1.3 root 365: return (uae_u32)ptr + 0x00F00000;
1.1 root 366: }
367:
1.1.1.4 ! root 368: void db (uae_u8 data)
1.1.1.3 root 369: {
370: rtarea[rt_addr++] = data;
371: }
372:
1.1.1.4 ! root 373: void dw (uae_u16 data)
1.1 root 374: {
375: rtarea[rt_addr++] = data >> 8;
376: rtarea[rt_addr++] = data;
377: }
378:
1.1.1.4 ! root 379: void dl (uae_u32 data)
1.1 root 380: {
381: rtarea[rt_addr++] = data >> 24;
382: rtarea[rt_addr++] = data >> 16;
383: rtarea[rt_addr++] = data >> 8;
384: rtarea[rt_addr++] = data;
385: }
386:
387: /* store strings starting at the end of the rt area and working
388: * backward. store pointer at current address
389: */
390:
1.1.1.4 ! root 391: uae_u32 ds (char *str)
1.1 root 392: {
1.1.1.4 ! root 393: int len = strlen (str) + 1;
1.1 root 394:
395: rt_straddr -= len;
1.1.1.4 ! root 396: strcpy ((char *)rtarea + rt_straddr, str);
1.1.1.3 root 397:
1.1.1.4 ! root 398: return addr (rt_straddr);
1.1 root 399: }
400:
1.1.1.4 ! root 401: void calltrap (uae_u32 n)
1.1 root 402: {
1.1.1.4 ! root 403: dw (0xA000 + n);
1.1 root 404: }
405:
1.1.1.4 ! root 406: void org (uae_u32 a)
1.1 root 407: {
408: rt_addr = a - 0x00F00000;
409: }
410:
1.1.1.4 ! root 411: uae_u32 here (void)
1.1 root 412: {
1.1.1.4 ! root 413: return addr (rt_addr);
1.1 root 414: }
415:
1.1.1.4 ! root 416: int deftrap2 (TrapFunction func, int mode, const char *str)
1.1 root 417: {
418: int num = max_trap++;
419: traps[num] = func;
1.1.1.3 root 420: trapstr[num] = str;
421: trapmode[num] = mode;
1.1 root 422: return num;
423: }
424:
1.1.1.4 ! root 425: int deftrap (TrapFunction func)
1.1 root 426: {
1.1.1.4 ! root 427: return deftrap2 (func, 0, "");
1.1 root 428: }
429:
1.1.1.4 ! root 430: void align (int b)
1.1 root 431: {
1.1.1.4 ! root 432: rt_addr = (rt_addr + b - 1) & ~(b - 1);
1.1 root 433: }
434:
1.1.1.3 root 435: static uae_u32 nullfunc(void)
1.1 root 436: {
1.1.1.4 ! root 437: fprintf (stderr, "Null function called\n");
1.1.1.3 root 438: return 0;
1.1.1.2 root 439: }
440:
1.1.1.3 root 441: static uae_u32 getchipmemsize (void)
1.1.1.2 root 442: {
1.1.1.4 ! root 443: return allocated_chipmem;
1.1 root 444: }
445:
1.1.1.4 ! root 446: void rtarea_init (void)
1.1 root 447: {
1.1.1.3 root 448: uae_u32 a;
1.1 root 449: char uaever[100];
1.1.1.4 ! root 450: sprintf (uaever, "uae-%d.%d.%d", UAEMAJOR, UAEMINOR, UAESUBREV);
1.1 root 451:
1.1.1.4 ! root 452: EXPANSION_uaeversion = ds (uaever);
! 453: EXPANSION_explibname = ds ("expansion.library");
! 454: EXPANSION_doslibname = ds ("dos.library");
! 455: EXPANSION_uaedevname = ds ("uae.device");
1.1 root 456:
1.1.1.4 ! root 457: deftrap (NULL); /* Generic emulator trap */
1.1 root 458: lasttrap = 0;
459:
1.1.1.4 ! root 460: EXPANSION_nullfunc = here ();
! 461: calltrap (deftrap (nullfunc));
! 462: dw (RTS);
1.1.1.3 root 463:
1.1.1.2 root 464: a = here();
1.1 root 465: /* Standard "return from 68k mode" trap */
1.1.1.4 ! root 466: org (0xF0FF00);
1.1.1.3 root 467: calltrap (deftrap2 (m68k_mode_return, TRAPFLAG_NO_RETVAL, ""));
468:
469: org (0xF0FF80);
470: calltrap (deftrap2 (getchipmemsize, TRAPFLAG_DORET, ""));
1.1.1.4 ! root 471: org (a);
1.1.1.2 root 472:
1.1.1.3 root 473: filesys_install_code ();
474: }
1.1.1.2 root 475:
1.1.1.3 root 476: volatile int uae_int_requested = 0;
1.1.1.2 root 477:
1.1.1.3 root 478: void set_uae_int_flag (void)
479: {
480: rtarea[0xFFFB] = uae_int_requested;
1.1.1.2 root 481: }
482:
483: void rtarea_setup(void)
484: {
485: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.