|
|
1.1 root 1: /*
2: Hatari - ioMem.c
3:
1.1.1.10 root 4: This file is distributed under the GNU General Public License, version 2
5: or at your option any later version. Read the file gpl.txt for details.
1.1 root 6:
7: This is where we intercept read/writes to/from the hardware. The ST's memory
8: is nicely split into four main parts - the bottom area of RAM is for user
9: programs. This is followed by a large area which causes a Bus Error. After
10: this is the ROM addresses for TOS and finally an area for hardware mapping.
11: To gain speed any address in the user area can simply read/write, but anything
12: above this range needs to be checked for validity and sent to the various
13: handlers.
14: A big problem for ST emulation is the use of the hardware registers. These
15: often consist of an 'odd' byte in memory and is usually addressed as a single
16: byte. A number of applications, however, write to the address using a word or
17: even long word. So we have a list of handlers that take care of each address
18: that has to be intercepted. Eg, a long write to a PSG register (which access
19: two registers) will write the long into IO memory space and then call the two
20: handlers which read off the bytes for each register.
21: This means that any access to any hardware register in such a way will work
22: correctly - it certainly fixes a lot of bugs and means writing just one
23: routine for each hardware register we mean to intercept! Phew!
24: You have also to take into consideration that some hardware registers are
25: bigger than 1 byte (there are also word and longword registers) and that
26: a lot of addresses in between can cause a bus error - so it's not so easy
27: to cope with all type of handlers in a straight forward way.
28: Also note the 'mirror' (or shadow) registers of the PSG - this is used by most
29: games.
30: */
1.1.1.6 root 31: const char IoMem_fileid[] = "Hatari ioMem.c : " __DATE__ " " __TIME__;
1.1 root 32:
33: #include "main.h"
34: #include "configuration.h"
35: #include "ioMem.h"
36: #include "ioMemTables.h"
1.1.1.8 root 37: #include "memorySnapShot.h"
1.1 root 38: #include "m68000.h"
1.1.1.3 root 39: #include "sysdeps.h"
1.1 root 40:
41:
42: static void (*pInterceptReadTable[0x8000])(void); /* Table with read access handlers */
43: static void (*pInterceptWriteTable[0x8000])(void); /* Table with write access handlers */
44:
45: int nIoMemAccessSize; /* Set to 1, 2 or 4 according to byte, word or long word access */
46: Uint32 IoAccessBaseAddress; /* Stores the base address of the IO mem access */
1.1.1.3 root 47: Uint32 IoAccessCurrentAddress; /* Current byte address while handling WORD and LONG accesses */
1.1 root 48: static int nBusErrorAccesses; /* Needed to count bus error accesses */
49:
1.1.1.8 root 50: /* Falcon bus mode (Falcon STe compatible bus or Falcon only bus) */
51: static enum {
52: STE_BUS_COMPATIBLE,
53: FALCON_ONLY_BUS
54: } falconBusMode;
55:
56: /*-----------------------------------------------------------------------*/
57: /**
58: * Save/Restore snapshot of local variables ('MemorySnapShot_Store' handles type)
59: */
60: void IoMem_MemorySnapShot_Capture(bool bSave)
61: {
62: /* Save/Restore details */
63: MemorySnapShot_Store(&falconBusMode, sizeof(falconBusMode));
64: }
1.1 root 65:
66: /*-----------------------------------------------------------------------*/
1.1.1.3 root 67: /**
68: * Fill a region with bus error handlers.
69: */
1.1 root 70: static void IoMem_SetBusErrorRegion(Uint32 startaddr, Uint32 endaddr)
71: {
72: Uint32 a;
73:
74: for (a = startaddr; a <= endaddr; a++)
75: {
76: if (a & 1)
77: {
78: pInterceptReadTable[a - 0xff8000] = IoMem_BusErrorOddReadAccess; /* For 'read' */
79: pInterceptWriteTable[a - 0xff8000] = IoMem_BusErrorOddWriteAccess; /* and 'write' */
80: }
81: else
82: {
83: pInterceptReadTable[a - 0xff8000] = IoMem_BusErrorEvenReadAccess; /* For 'read' */
84: pInterceptWriteTable[a - 0xff8000] = IoMem_BusErrorEvenWriteAccess; /* and 'write' */
85: }
86: }
87: }
88:
89:
90: /*-----------------------------------------------------------------------*/
1.1.1.3 root 91: /**
92: * Create 'intercept' tables for hardware address access. Each 'intercept
93: * table is a list of 0x8000 pointers to a list of functions to call when
94: * that location in the ST's memory is accessed.
95: */
1.1 root 96: void IoMem_Init(void)
97: {
98: Uint32 addr;
99: int i;
1.1.1.2 root 100: const INTERCEPT_ACCESS_FUNC *pInterceptAccessFuncs = NULL;
1.1 root 101:
102: /* Set default IO access handler (-> bus error) */
103: IoMem_SetBusErrorRegion(0xff8000, 0xffffff);
104:
1.1.1.8 root 105:
106: /* Initialize STe bus specific registers for Falcon in FALCON STe compatible bus mode */
107: if ((ConfigureParams.System.nMachineType == MACHINE_FALCON) && (falconBusMode == STE_BUS_COMPATIBLE)) {
108: for (addr = 0xff8000; addr < 0xffd426; addr++)
109: {
110: if ( ((addr >= 0xff8002) && (addr < 0xff8006)) ||
111: ((addr >= 0xff8008) && (addr < 0xff800c)) ||
112: ((addr >= 0xff800e) && (addr < 0xff8060)) ||
113: ((addr >= 0xff8064) && (addr < 0xff8200)) ||
114: ((addr >= 0xff82c4) && (addr < 0xff8400)) ||
115: (addr == 0xff8560) ||
116: (addr == 0xff8564) ||
117: ((addr >= 0xff8804) && (addr < 0xff8900)) ||
118: ((addr >= 0xff8964) && (addr < 0xff8970)) ||
119: ((addr >= 0xff8c00) && (addr < 0xff8c80)) ||
120: ((addr >= 0xff8c88) && (addr < 0xff8d00)) ||
121: ((addr >= 0xff9000) && (addr < 0xff9200)) ||
122: ((addr >= 0xff9204) && (addr < 0xff9206)) ||
123: ((addr >= 0xff9207) && (addr < 0xff9210)) ||
124: ((addr >= 0xff9218) && (addr < 0xff9220)) ||
125: ((addr >= 0xff9224) && (addr < 0xff9800)) ||
126: ((addr >= 0xff9c00) && (addr < 0xffa000)) ||
127: ((addr >= 0xffa200) && (addr < 0xffa208)) ||
128: (addr == 0xffc020) ||
129: (addr == 0xffc021) ||
130: (addr == 0xffd020) ||
131: (addr == 0xffd021) ||
132: (addr == 0xffd420) ||
133: (addr == 0xffd421) ||
134: (addr == 0xffd425)
135: ) {
136: pInterceptReadTable[addr - 0xff8000] = IoMem_VoidRead; /* For 'read' */
137: pInterceptWriteTable[addr - 0xff8000] = IoMem_VoidWrite; /* and 'write' */
138: }
139: }
140: }
141:
1.1 root 142: switch (ConfigureParams.System.nMachineType)
143: {
144: case MACHINE_ST: pInterceptAccessFuncs = IoMemTable_ST; break;
145: case MACHINE_STE: pInterceptAccessFuncs = IoMemTable_STE; break;
1.1.1.2 root 146: case MACHINE_TT: pInterceptAccessFuncs = IoMemTable_TT; break;
1.1.1.3 root 147: case MACHINE_FALCON: pInterceptAccessFuncs = IoMemTable_Falcon; break;
1.1.1.8 root 148: default: abort(); /* bug */
1.1 root 149: }
150:
151: /* Now set the correct handlers */
152: for (addr=0xff8000; addr <= 0xffffff; addr++)
153: {
154: /* Does this hardware location/span appear in our list of possible intercepted functions? */
155: for (i=0; pInterceptAccessFuncs[i].Address != 0; i++)
156: {
157: if (addr >= pInterceptAccessFuncs[i].Address
158: && addr < pInterceptAccessFuncs[i].Address+pInterceptAccessFuncs[i].SpanInBytes)
159: {
160: /* Security checks... */
161: if (pInterceptReadTable[addr-0xff8000] != IoMem_BusErrorEvenReadAccess && pInterceptReadTable[addr-0xff8000] != IoMem_BusErrorOddReadAccess)
162: fprintf(stderr, "IoMem_Init: Warning: $%x (R) already defined\n", addr);
163: if (pInterceptWriteTable[addr-0xff8000] != IoMem_BusErrorEvenWriteAccess && pInterceptWriteTable[addr-0xff8000] != IoMem_BusErrorOddWriteAccess)
164: fprintf(stderr, "IoMem_Init: Warning: $%x (W) already defined\n", addr);
165:
166: /* This location needs to be intercepted, so add entry to list */
167: pInterceptReadTable[addr-0xff8000] = pInterceptAccessFuncs[i].ReadFunc;
168: pInterceptWriteTable[addr-0xff8000] = pInterceptAccessFuncs[i].WriteFunc;
169: }
170: }
171: }
172:
1.1.1.4 root 173: /* Set registers for Falcon DSP emulation */
1.1.1.3 root 174: if (ConfigureParams.System.nMachineType == MACHINE_FALCON)
175: {
1.1.1.4 root 176: switch (ConfigureParams.System.nDSPType)
177: {
1.1.1.3 root 178: #if ENABLE_DSP_EMU
179: case DSP_TYPE_EMU:
180: IoMemTabFalcon_DSPemulation(pInterceptReadTable,
181: pInterceptWriteTable);
182: break;
183: #endif
184: case DSP_TYPE_DUMMY:
185: IoMemTabFalcon_DSPdummy(pInterceptReadTable,
186: pInterceptWriteTable);
187: break;
188: default:
189: /* none */
190: IoMemTabFalcon_DSPnone(pInterceptReadTable,
191: pInterceptWriteTable);
192: }
193: }
194:
1.1 root 195: /* Disable blitter? */
1.1.1.3 root 196: if (!ConfigureParams.System.bBlitter && ConfigureParams.System.nMachineType == MACHINE_ST)
1.1 root 197: {
198: IoMem_SetBusErrorRegion(0xff8a00, 0xff8a3f);
199: }
200:
201: /* Disable real time clock? */
202: if (!ConfigureParams.System.bRealTimeClock)
203: {
1.1.1.4 root 204: for (addr = 0xfffc21; addr <= 0xfffc3f; addr++)
1.1 root 205: {
206: pInterceptReadTable[addr - 0xff8000] = IoMem_VoidRead; /* For 'read' */
207: pInterceptWriteTable[addr - 0xff8000] = IoMem_VoidWrite; /* and 'write' */
208: }
1.1.1.4 root 209: }
210:
1.1.1.8 root 211: /* Initialize PSG shadow registers for ST, STe, TT machines */
1.1.1.4 root 212: if (ConfigureParams.System.nMachineType != MACHINE_FALCON)
213: {
214: for (addr = 0xff8804; addr < 0xff8900; addr++)
215: {
216: pInterceptReadTable[addr - 0xff8000] = pInterceptReadTable[(addr & 0xfff803) - 0xff8000];
217: pInterceptWriteTable[addr - 0xff8000] = pInterceptWriteTable[(addr & 0xfff803) - 0xff8000];
218: }
1.1.1.8 root 219: }
220: else {
221: /* Initialize PSG shadow registers for Falcon machine when in STe bus compatibility mode */
222: if (falconBusMode == STE_BUS_COMPATIBLE) {
223: for (addr = 0xff8804; addr < 0xff8900; addr++)
224: {
225: pInterceptReadTable[addr - 0xff8000] = IoMem_VoidRead; /* For 'read' */
226: pInterceptWriteTable[addr - 0xff8000] = IoMem_VoidWrite; /* and 'write' */
227: }
228:
229: }
1.1 root 230: }
231: }
232:
1.1.1.8 root 233: /*-----------------------------------------------------------------------*/
234: /**
235: * This function is called to fix falconBusMode (0 = Falcon STe bus compatibility, other value = Falcon only bus compatibility)
236: * This value comes from register $ff8007.b (Bit 5) and is called by ioMemTabFalcon
237: */
238: void IoMem_Init_FalconInSTeBuscompatibilityMode(Uint8 value)
239: {
240: if (value == 0)
241: falconBusMode = STE_BUS_COMPATIBLE;
242: else
243: falconBusMode = FALCON_ONLY_BUS;
244:
245: IoMem_Init();
246: }
1.1 root 247:
248: /*-----------------------------------------------------------------------*/
1.1.1.3 root 249: /**
250: * Uninitialize the IoMem code (currently unused).
251: */
1.1 root 252: void IoMem_UnInit(void)
253: {
254: }
255:
256:
257: /*-----------------------------------------------------------------------*/
1.1.1.3 root 258: /**
259: * Handle byte read access from IO memory.
260: */
1.1 root 261: uae_u32 IoMem_bget(uaecptr addr)
262: {
1.1.1.6 root 263: Uint8 val;
1.1 root 264:
265: addr &= 0x00ffffff; /* Use a 24 bit address */
266:
1.1.1.9 root 267: if (addr < 0xff8000 || !regs.s)
1.1 root 268: {
269: /* invalid memory addressing --> bus error */
1.1.1.12! root 270: M68000_BusError(addr, BUS_ERROR_READ, BUS_ERROR_SIZE_BYTE, BUS_ERROR_ACCESS_DATA);
1.1 root 271: return -1;
272: }
273:
274: IoAccessBaseAddress = addr; /* Store access location */
275: nIoMemAccessSize = SIZE_BYTE;
276: nBusErrorAccesses = 0;
277:
278: IoAccessCurrentAddress = addr;
279: pInterceptReadTable[addr-0xff8000](); /* Call handler */
280:
281: /* Check if we read from a bus-error region */
282: if (nBusErrorAccesses == 1)
283: {
1.1.1.12! root 284: M68000_BusError(addr, BUS_ERROR_READ, BUS_ERROR_SIZE_BYTE, BUS_ERROR_ACCESS_DATA);
1.1 root 285: return -1;
286: }
287:
1.1.1.6 root 288: val = IoMem[addr];
289:
1.1.1.11 root 290: LOG_TRACE(TRACE_IOMEM_RD, "IO read.b $%06x = $%02x pc=%x\n", addr, val, M68000_GetPC());
1.1.1.6 root 291:
292: return val;
1.1 root 293: }
294:
295:
296: /*-----------------------------------------------------------------------*/
1.1.1.3 root 297: /**
298: * Handle word read access from IO memory.
299: */
1.1 root 300: uae_u32 IoMem_wget(uaecptr addr)
301: {
302: Uint32 idx;
1.1.1.6 root 303: Uint16 val;
1.1 root 304:
305: addr &= 0x00ffffff; /* Use a 24 bit address */
306:
1.1.1.9 root 307: if (addr < 0xff8000 || !regs.s)
1.1 root 308: {
309: /* invalid memory addressing --> bus error */
1.1.1.12! root 310: M68000_BusError(addr, BUS_ERROR_READ, BUS_ERROR_SIZE_WORD, BUS_ERROR_ACCESS_DATA);
1.1 root 311: return -1;
312: }
313: if (addr > 0xfffffe)
314: {
315: fprintf(stderr, "Illegal IO memory access: IoMem_wget($%x)\n", addr);
316: return -1;
317: }
318:
319: IoAccessBaseAddress = addr; /* Store for exception frame */
320: nIoMemAccessSize = SIZE_WORD;
321: nBusErrorAccesses = 0;
322: idx = addr - 0xff8000;
323:
324: IoAccessCurrentAddress = addr;
325: pInterceptReadTable[idx](); /* Call 1st handler */
326:
327: if (pInterceptReadTable[idx+1] != pInterceptReadTable[idx])
328: {
329: IoAccessCurrentAddress = addr + 1;
330: pInterceptReadTable[idx+1](); /* Call 2nd handler */
331: }
332:
333: /* Check if we completely read from a bus-error region */
334: if (nBusErrorAccesses == 2)
335: {
1.1.1.12! root 336: M68000_BusError(addr, BUS_ERROR_READ, BUS_ERROR_SIZE_WORD, BUS_ERROR_ACCESS_DATA);
1.1 root 337: return -1;
338: }
339:
1.1.1.6 root 340: val = IoMem_ReadWord(addr);
341:
1.1.1.11 root 342: LOG_TRACE(TRACE_IOMEM_RD, "IO read.w $%06x = $%04x pc=%x\n", addr, val, M68000_GetPC());
1.1.1.6 root 343:
344: return val;
1.1 root 345: }
346:
347:
348: /*-----------------------------------------------------------------------*/
1.1.1.3 root 349: /**
350: * Handle long-word read access from IO memory.
351: */
1.1 root 352: uae_u32 IoMem_lget(uaecptr addr)
353: {
354: Uint32 idx;
1.1.1.6 root 355: Uint32 val;
1.1.1.12! root 356: int n;
1.1 root 357:
358: addr &= 0x00ffffff; /* Use a 24 bit address */
359:
1.1.1.9 root 360: if (addr < 0xff8000 || !regs.s)
1.1 root 361: {
362: /* invalid memory addressing --> bus error */
1.1.1.12! root 363: M68000_BusError(addr, BUS_ERROR_READ, BUS_ERROR_SIZE_LONG, BUS_ERROR_ACCESS_DATA);
1.1 root 364: return -1;
365: }
366: if (addr > 0xfffffc)
367: {
368: fprintf(stderr, "Illegal IO memory access: IoMem_lget($%x)\n", addr);
369: return -1;
370: }
371:
372: IoAccessBaseAddress = addr; /* Store for exception frame */
373: nIoMemAccessSize = SIZE_LONG;
374: nBusErrorAccesses = 0;
375: idx = addr - 0xff8000;
376:
377: IoAccessCurrentAddress = addr;
378: pInterceptReadTable[idx](); /* Call 1st handler */
379:
1.1.1.12! root 380: for (n = 1; n < nIoMemAccessSize; n++)
1.1 root 381: {
1.1.1.12! root 382: if (pInterceptReadTable[idx+n] != pInterceptReadTable[idx+n-1])
! 383: {
! 384: IoAccessCurrentAddress = addr + n;
! 385: pInterceptReadTable[idx+n](); /* Call n-th handler */
! 386: }
1.1 root 387: }
388:
389: /* Check if we completely read from a bus-error region */
390: if (nBusErrorAccesses == 4)
391: {
1.1.1.12! root 392: M68000_BusError(addr, BUS_ERROR_READ, BUS_ERROR_SIZE_LONG, BUS_ERROR_ACCESS_DATA);
1.1 root 393: return -1;
394: }
395:
1.1.1.6 root 396: val = IoMem_ReadLong(addr);
397:
1.1.1.11 root 398: LOG_TRACE(TRACE_IOMEM_RD, "IO read.l $%06x = $%08x pc=%x\n", addr, val, M68000_GetPC());
1.1.1.6 root 399:
400: return val;
1.1 root 401: }
402:
403:
404: /*-----------------------------------------------------------------------*/
1.1.1.3 root 405: /**
406: * Handle byte write access to IO memory.
407: */
1.1 root 408: void IoMem_bput(uaecptr addr, uae_u32 val)
409: {
410: addr &= 0x00ffffff; /* Use a 24 bit address */
411:
1.1.1.11 root 412: LOG_TRACE(TRACE_IOMEM_WR, "IO write.b $%06x = $%02x pc=%x\n", addr, val&0x0ff, M68000_GetPC());
1.1.1.6 root 413:
1.1.1.5 root 414: if (addr < 0xff8000 || !regs.s)
1.1 root 415: {
416: /* invalid memory addressing --> bus error */
1.1.1.12! root 417: M68000_BusError(addr, BUS_ERROR_WRITE, BUS_ERROR_SIZE_BYTE, BUS_ERROR_ACCESS_DATA);
1.1 root 418: return;
419: }
420:
421: IoAccessBaseAddress = addr; /* Store for exception frame, just in case */
422: nIoMemAccessSize = SIZE_BYTE;
423: nBusErrorAccesses = 0;
424:
425: IoMem[addr] = val;
426:
427: IoAccessCurrentAddress = addr;
428: pInterceptWriteTable[addr-0xff8000](); /* Call handler */
429:
430: /* Check if we wrote to a bus-error region */
431: if (nBusErrorAccesses == 1)
432: {
1.1.1.12! root 433: M68000_BusError(addr, BUS_ERROR_WRITE, BUS_ERROR_SIZE_BYTE, BUS_ERROR_ACCESS_DATA);
1.1 root 434: }
435: }
436:
437:
438: /*-----------------------------------------------------------------------*/
1.1.1.3 root 439: /**
440: * Handle word write access to IO memory.
441: */
1.1 root 442: void IoMem_wput(uaecptr addr, uae_u32 val)
443: {
444: Uint32 idx;
445:
446: addr &= 0x00ffffff; /* Use a 24 bit address */
447:
1.1.1.11 root 448: LOG_TRACE(TRACE_IOMEM_WR, "IO write.w $%06x = $%04x pc=%x\n", addr, val&0x0ffff, M68000_GetPC());
1.1.1.6 root 449:
1.1.1.5 root 450: if (addr < 0x00ff8000 || !regs.s)
1.1 root 451: {
452: /* invalid memory addressing --> bus error */
1.1.1.12! root 453: M68000_BusError(addr, BUS_ERROR_WRITE, BUS_ERROR_SIZE_WORD, BUS_ERROR_ACCESS_DATA);
1.1 root 454: return;
455: }
456: if (addr > 0xfffffe)
457: {
458: fprintf(stderr, "Illegal IO memory access: IoMem_wput($%x)\n", addr);
459: return;
460: }
461:
462: IoAccessBaseAddress = addr; /* Store for exception frame, just in case */
463: nIoMemAccessSize = SIZE_WORD;
464: nBusErrorAccesses = 0;
465:
466: IoMem_WriteWord(addr, val);
467: idx = addr - 0xff8000;
468:
469: IoAccessCurrentAddress = addr;
470: pInterceptWriteTable[idx](); /* Call 1st handler */
471:
472: if (pInterceptWriteTable[idx+1] != pInterceptWriteTable[idx])
473: {
474: IoAccessCurrentAddress = addr + 1;
475: pInterceptWriteTable[idx+1](); /* Call 2nd handler */
476: }
477:
478: /* Check if we wrote to a bus-error region */
479: if (nBusErrorAccesses == 2)
480: {
1.1.1.12! root 481: M68000_BusError(addr, BUS_ERROR_WRITE, BUS_ERROR_SIZE_WORD, BUS_ERROR_ACCESS_DATA);
1.1 root 482: }
483: }
484:
485:
486: /*-----------------------------------------------------------------------*/
1.1.1.3 root 487: /**
488: * Handle long-word write access to IO memory.
489: */
1.1 root 490: void IoMem_lput(uaecptr addr, uae_u32 val)
491: {
492: Uint32 idx;
1.1.1.12! root 493: int n;
1.1 root 494:
495: addr &= 0x00ffffff; /* Use a 24 bit address */
496:
1.1.1.11 root 497: LOG_TRACE(TRACE_IOMEM_WR, "IO write.l $%06x = $%08x pc=%x\n", addr, val, M68000_GetPC());
1.1.1.6 root 498:
1.1.1.5 root 499: if (addr < 0xff8000 || !regs.s)
1.1 root 500: {
501: /* invalid memory addressing --> bus error */
1.1.1.12! root 502: M68000_BusError(addr, BUS_ERROR_WRITE, BUS_ERROR_SIZE_LONG, BUS_ERROR_ACCESS_DATA);
1.1 root 503: return;
504: }
505: if (addr > 0xfffffc)
506: {
507: fprintf(stderr, "Illegal IO memory access: IoMem_lput($%x)\n", addr);
508: return;
509: }
510:
511: IoAccessBaseAddress = addr; /* Store for exception frame, just in case */
512: nIoMemAccessSize = SIZE_LONG;
513: nBusErrorAccesses = 0;
514:
515: IoMem_WriteLong(addr, val);
516: idx = addr - 0xff8000;
517:
518: IoAccessCurrentAddress = addr;
1.1.1.12! root 519: pInterceptWriteTable[idx](); /* Call first handler */
1.1 root 520:
1.1.1.12! root 521: for (n = 1; n < nIoMemAccessSize; n++)
1.1 root 522: {
1.1.1.12! root 523: if (pInterceptWriteTable[idx+n] != pInterceptWriteTable[idx+n-1])
! 524: {
! 525: IoAccessCurrentAddress = addr + n;
! 526: pInterceptWriteTable[idx+n](); /* Call n-th handler */
! 527: }
1.1 root 528: }
529:
530: /* Check if we wrote to a bus-error region */
531: if (nBusErrorAccesses == 4)
532: {
1.1.1.12! root 533: M68000_BusError(addr, BUS_ERROR_WRITE, BUS_ERROR_SIZE_LONG, BUS_ERROR_ACCESS_DATA);
1.1 root 534: }
535: }
536:
537:
538: /*-------------------------------------------------------------------------*/
1.1.1.3 root 539: /**
540: * This handler will be called if a ST program tries to read from an address
541: * that causes a bus error on a real ST. However, we can't call M68000_BusError()
542: * directly: For example, a "move.b $ff8204,d0" triggers a bus error on a real ST,
543: * while a "move.w $ff8204,d0" works! So we have to count the accesses to bus error
544: * addresses and we only trigger a bus error later if the count matches the complete
545: * access size (e.g. nBusErrorAccesses==4 for a long word access).
546: */
1.1 root 547: void IoMem_BusErrorEvenReadAccess(void)
548: {
549: nBusErrorAccesses += 1;
550: IoMem[IoAccessCurrentAddress] = 0xff;
551: }
552:
1.1.1.3 root 553: /**
554: * We need two handler so that the IoMem_*get functions can distinguish
555: * consecutive addresses.
556: */
1.1 root 557: void IoMem_BusErrorOddReadAccess(void)
558: {
559: nBusErrorAccesses += 1;
560: IoMem[IoAccessCurrentAddress] = 0xff;
561: }
562:
563: /*-------------------------------------------------------------------------*/
1.1.1.3 root 564: /**
565: * Same as IoMem_BusErrorReadAccess() but for write access this time.
566: */
1.1 root 567: void IoMem_BusErrorEvenWriteAccess(void)
568: {
569: nBusErrorAccesses += 1;
570: }
571:
1.1.1.3 root 572: /**
573: * We need two handler so that the IoMem_*put functions can distinguish
574: * consecutive addresses.
575: */
1.1 root 576: void IoMem_BusErrorOddWriteAccess(void)
577: {
578: nBusErrorAccesses += 1;
579: }
580:
581:
582: /*-------------------------------------------------------------------------*/
1.1.1.3 root 583: /**
584: * This is the read handler for the IO memory locations without an assigned
585: * IO register and which also do not generate a bus error. Reading from such
586: * a register will return the result 0xff.
587: */
1.1 root 588: void IoMem_VoidRead(void)
589: {
590: Uint32 a;
591:
592: /* handler is probably called only once, so we have to take care of the neighbour "void IO registers" */
593: for (a = IoAccessBaseAddress; a < IoAccessBaseAddress + nIoMemAccessSize; a++)
594: {
595: if (pInterceptReadTable[a - 0xff8000] == IoMem_VoidRead)
596: {
597: IoMem[a] = 0xff;
598: }
599: }
600: }
601:
602: /*-------------------------------------------------------------------------*/
1.1.1.3 root 603: /**
1.1.1.8 root 604: * This is the same function as IoMem_VoidRead, but for IO registers that
605: * return 0x00 instead of 0xff when read (this is the case for some video
606: * registers on STE, Falcon, ...)
607: */
608: void IoMem_VoidRead_00(void)
609: {
610: Uint32 a;
611:
612: /* handler is probably called only once, so we have to take care of the neighbour "void IO registers" */
613: for (a = IoAccessBaseAddress; a < IoAccessBaseAddress + nIoMemAccessSize; a++)
614: {
615: if (pInterceptReadTable[a - 0xff8000] == IoMem_VoidRead_00)
616: {
617: IoMem[a] = 0x00;
618: }
619: }
620: }
621:
622: /*-------------------------------------------------------------------------*/
623: /**
1.1.1.3 root 624: * This is the write handler for the IO memory locations without an assigned
625: * IO register and which also do not generate a bus error. We simply ignore
626: * a write access to these registers.
627: */
1.1 root 628: void IoMem_VoidWrite(void)
629: {
630: /* Nothing... */
631: }
632:
633:
634: /*-------------------------------------------------------------------------*/
1.1.1.3 root 635: /**
636: * A dummy function that does nothing at all - for memory regions that don't
637: * need a special handler for read access.
638: */
1.1 root 639: void IoMem_ReadWithoutInterception(void)
640: {
641: /* Nothing... */
642: }
643:
644: /*-------------------------------------------------------------------------*/
1.1.1.3 root 645: /**
646: * A dummy function that does nothing at all - for memory regions that don't
647: * need a special handler for write access.
648: */
1.1 root 649: void IoMem_WriteWithoutInterception(void)
650: {
651: /* Nothing... */
652: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.