|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * AutoConfig devices
5: *
6: * (c) 1995 Bernd Schmidt
7: * (c) 1996 Ed Hanway
8: */
9:
10: #include "sysconfig.h"
11: #include "sysdeps.h"
12:
13: #include "config.h"
14: #include "options.h"
15: #include "memory.h"
16: #include "custom.h"
17: #include "newcpu.h"
18: #include "disk.h"
19: #include "xwin.h"
20: #include "autoconf.h"
21:
22: static struct {
23: CPTR libbase;
24: TrapFunction functions[300]; /* I don't think any library has more than 300 functions */
25: } libpatches[20];
26: static int n_libpatches = 0;
27:
28: ULONG Call68k_retaddr(CPTR address, int saveregs, CPTR retaddr)
29: {
30: ULONG retval;
31: CPTR oldpc = m68k_getpc();
32:
33: struct regstruct backup_regs;
34: if (saveregs)
35: backup_regs = regs;
36: regs.a[7] -= 4;
37: put_long (regs.a[7], retaddr);
38: m68k_setpc(address);
39: m68k_go(0);
40: retval = regs.d[0];
41: if (saveregs)
42: regs = backup_regs;
43: m68k_setpc(oldpc);
44: return retval;
45: }
46:
47: ULONG Call68k(CPTR address, int saveregs)
48: {
49: return Call68k_retaddr(address, saveregs, 0xF0FFF0);
50: }
51:
52: ULONG CallLib(CPTR base, WORD offset)
53: {
54: int i;
55: CPTR olda6 = regs.a[6];
56: ULONG retval;
57:
58: for (i = 0; i < n_libpatches; i++) {
59: if (libpatches[i].libbase == base && libpatches[i].functions[-offset/6] != NULL)
60: return (*libpatches[i].functions[-offset/6])();
61: }
62:
63: regs.a[6] = base;
64: retval = Call68k(base + offset, 1);
65: regs.a[6] = olda6;
66: return retval;
67: }
68:
69: /* @$%&� compiler bugs */
70: static volatile int four = 4;
71:
72: CPTR libemu_InstallFunctionFlags(TrapFunction f, CPTR libbase, int offset,
73: int flags)
74: {
75: int i;
76: CPTR retval;
77: CPTR execbase = get_long(four);
78: ULONG addr = here();
79: calltrap2(deftrap2(f, flags));
80: dw(RTS);
81:
82: regs.a[1] = libbase;
83: regs.a[0] = offset;
84: regs.d[0] = addr;
85: retval = CallLib(execbase, -420);
86: for (i = 0; i < n_libpatches; i++) {
87: if (libpatches[i].libbase == libbase)
88: break;
89: }
90: if (i == n_libpatches) {
91: int j;
92: libpatches[i].libbase = libbase;
93: for (j = 0; j < 300; j++)
94: libpatches[i].functions[j] = NULL;
95: n_libpatches++;
96: }
97: libpatches[i].functions[-offset/6] = f;
98: return retval;
99: }
100:
101: CPTR libemu_InstallFunction(TrapFunction f, CPTR libbase, int offset)
102: {
103: return libemu_InstallFunctionFlags(f, libbase, offset, 0);
104: }
105:
106: /* Commonly used autoconfig strings */
107:
108: CPTR EXPANSION_explibname, EXPANSION_doslibname, EXPANSION_uaeversion;
109: CPTR EXPANSION_uaedevname, EXPANSION_explibbase = 0, EXPANSION_haveV36;
110: CPTR EXPANSION_bootcode;
111:
112: static int current_deviceno = 0;
113:
114: int get_new_device(char **devname, CPTR *devname_amiga)
115: {
116: char buffer[80];
117:
118: sprintf(buffer,"UAE%d", current_deviceno);
119:
120: *devname_amiga = ds(*devname = strdup(buffer));
121: return current_deviceno++;
122: }
123:
124: /* ROM tag area memory access */
125:
126: static UBYTE rtarea[65536];
127:
128: static ULONG rtarea_lget(CPTR) REGPARAM;
129: static UWORD rtarea_wget(CPTR) REGPARAM;
130: static UBYTE rtarea_bget(CPTR) REGPARAM;
131: static void rtarea_lput(CPTR, ULONG) REGPARAM;
132: static void rtarea_wput(CPTR, UWORD) REGPARAM;
133: static void rtarea_bput(CPTR, UBYTE) REGPARAM;
134: static UBYTE *rtarea_xlate(CPTR) REGPARAM;
135:
136: addrbank rtarea_bank = {
137: rtarea_lget, rtarea_wget,
138: rtarea_lget, rtarea_wget, rtarea_bget,
139: rtarea_lput, rtarea_wput, rtarea_bput,
140: rtarea_xlate, default_check
141: };
142:
143: UBYTE *rtarea_xlate(CPTR addr)
144: {
145: addr &= 0xFFFF;
146: return rtarea + addr;
147: }
148:
149: ULONG rtarea_lget(CPTR addr)
150: {
151: addr &= 0xFFFF;
152: return (ULONG)(rtarea_wget(addr) << 16) + rtarea_wget(addr+2);
153: }
154:
155: UWORD rtarea_wget(CPTR addr)
156: {
157: addr &= 0xFFFF;
158: return (rtarea[addr]<<8) + rtarea[addr+1];
159: }
160:
161: UBYTE rtarea_bget(CPTR addr)
162: {
163: UWORD data;
164: addr &= 0xFFFF;
165: return rtarea[addr];
166: }
167:
168: void rtarea_lput(CPTR addr, ULONG value) { }
169: void rtarea_bput(CPTR addr, UBYTE value) { }
170:
171: /* Don't start at 0 -- can get bogus writes there. */
172: static ULONG trap_base_addr = 0x00F00180;
173:
174: /* We'll need a lot of these. */
175: TrapFunction traps[16384];
176: char trapmode[16384];
177:
178: static int max_trap = 0;
179:
180: int lasttrap;
181:
182: void do_emultrap(int tr)
183: {
184: struct regstruct backup_regs;
185: ULONG retval;
186:
187: if ((trapmode[tr] & 1) == 0)
188: backup_regs = regs;
189: retval = (*traps[tr])();
190: if ((trapmode[tr] & 1) == 0)
191: regs = backup_regs;
192: if ((trapmode[tr] & 2) == 0)
193: regs.d[0] = retval;
194: }
195:
196: void rtarea_wput(CPTR addr, UWORD value)
197: {
198: /* Save all registers */
199: struct regstruct backup_regs;
200: ULONG retval = 0;
201: ULONG func = ((addr - trap_base_addr) & 0xFFFF) >> 1;
202:
203: if (func == 0) {
204: lasttrap = get_long(regs.a[7]);
205: regs.a[7] += 4;
206: regs.spcflags |= SPCFLAG_EMULTRAP;
207: return;
208: }
209:
210: backup_regs = regs;
211: if(func < max_trap) {
212: retval = (*traps[func])();
213: } else {
214: fprintf(stderr, "illegal emulator trap\n");
215: }
216: regs = backup_regs;
217: regs.d[0] = retval;
218: }
219:
220: /* some quick & dirty code to fill in the rt area and save me a lot of
221: * scratch paper
222: */
223:
224: static int rt_addr = 0;
225: static int rt_straddr = 0xFF00 - 2;
226:
227: ULONG addr(int ptr)
228: {
229: return (ULONG)ptr + 0x00F00000;
230: }
231:
232: void dw(UWORD data)
233: {
234: rtarea[rt_addr++] = data >> 8;
235: rtarea[rt_addr++] = data;
236: }
237:
238: void dl(ULONG data)
239: {
240: rtarea[rt_addr++] = data >> 24;
241: rtarea[rt_addr++] = data >> 16;
242: rtarea[rt_addr++] = data >> 8;
243: rtarea[rt_addr++] = data;
244: }
245:
246: /* store strings starting at the end of the rt area and working
247: * backward. store pointer at current address
248: */
249:
250: ULONG ds(char *str)
251: {
252: int len = strlen(str) + 1;
253:
254: rt_straddr -= len;
255: strcpy(rtarea + rt_straddr, str);
256:
257: return addr(rt_straddr);
258: }
259:
260: void calltrap2(ULONG n)
261: {
262: dw(0x4878); /* PEA.L n.w */
263: dw(n);
264: /* Call trap #0 is reserved for this */
265: dw(0x33C0); /* MOVE.W D0,abs32 */
266: dl(trap_base_addr);
267: }
268:
269: void calltrap(ULONG n)
270: {
271: #if 1
272: dw(0x33C0); /* MOVE.W D0,abs32 */
273: dl(n*2 + trap_base_addr);
274: #else
275: calltrap2(n);
276: #endif
277: }
278:
279: void org(ULONG a)
280: {
281: rt_addr = a - 0x00F00000;
282: }
283:
284: ULONG here(void)
285: {
286: return addr(rt_addr);
287: }
288:
289: int deftrap(TrapFunction func)
290: {
291: int num = max_trap++;
292: traps[num] = func;
293: trapmode[num] = 0;
294: return num;
295: }
296:
297: int deftrap2(TrapFunction func, int mode)
298: {
299: int num = max_trap++;
300: traps[num] = func;
301: trapmode[num] = mode;
302: return num;
303: }
304:
305: void align(int b)
306: {
307: rt_addr = (rt_addr + (b-1)) & ~(b-1);
308: }
309:
310: static ULONG bootcode(void)
311: {
312: regs.a[1] = EXPANSION_doslibname;
313: regs.d[0] = CallLib (regs.a[6], -96); /* FindResident() */
314: regs.a[0] = get_long(regs.d[0]+22); /* get dos.library rt_init */
315: return regs.a[0];
316: }
317:
318: void rtarea_init()
319: {
320: ULONG a;
321: char uaever[100];
322: sprintf(uaever, "uae-%d.%d.%d", (version / 100) % 10, (version / 10) % 10, (version / 1) % 10);
323:
324: EXPANSION_uaeversion = ds(uaever);
325: EXPANSION_explibname = ds("expansion.library");
326: EXPANSION_doslibname = ds("dos.library");
327: EXPANSION_uaedevname = ds("uae.device");
328:
329: deftrap(NULL); /* Generic emulator trap */
330: lasttrap = 0;
331:
332: align(4);
333: EXPANSION_bootcode = here();
334: calltrap2(deftrap2(bootcode, 1));
335: dw(0x2040); /* move.l d0,a0 */
336: dw(0x4e90); /* jsr (a0) */
337: dw(RTS);
338:
339: a = here();
340:
341: /* Idle task */
342: org(0xF0FFF0 - 4);
343: dw(0x4E72); dw (0x2000); /* STOP 0x2000 */
344:
345: /* Standard "return from 68k mode" trap */
346: /*org(0xF0FFF0); */
347: calltrap2(0);
348: dw(RTS);
349: org(a);
350: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.