|
|
1.1 root 1: /*
2: Hatari - hatari-glue.c
3:
1.1.1.4 ! 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 file contains some code to glue the UAE CPU core to the rest of the
8: emulator and Hatari's "illegal" opcodes.
9: */
10: const char HatariGlue_fileid[] = "Hatari hatari-glue.c : " __DATE__ " " __TIME__;
11:
12:
13: #include <stdio.h>
14:
15: #include "main.h"
16: #include "configuration.h"
17: #include "cycInt.h"
18: #include "tos.h"
19: #include "gemdos.h"
1.1.1.4 ! root 20: #include "natfeats.h"
1.1 root 21: #include "cart.h"
22: #include "vdi.h"
23: #include "stMemory.h"
24: #include "ikbd.h"
25: #include "screen.h"
26: #include "video.h"
1.1.1.2 root 27: #include "psg.h"
1.1.1.4 ! root 28: #include "mfp.h"
! 29: #include "fdc.h"
1.1 root 30:
31: #include "sysdeps.h"
32: #include "maccess.h"
33: #include "memory.h"
1.1.1.4 ! root 34: #include "m68000.h"
1.1 root 35: #include "newcpu.h"
1.1.1.3 root 36: #include "cpu_prefetch.h"
1.1 root 37: #include "hatari-glue.h"
38:
39:
40: struct uae_prefs currprefs, changed_prefs;
41:
42: int pendingInterrupts = 0;
43:
44:
45: /**
46: * Reset custom chips
1.1.1.4 ! root 47: * In case the RESET instruction is called, we must reset all the peripherals
! 48: * connected to the CPU's reset pin.
1.1 root 49: */
50: void customreset(void)
51: {
52: pendingInterrupts = 0;
53:
1.1.1.4 ! root 54: /* Reset the IKBD */
! 55: IKBD_Reset ( false );
1.1 root 56:
57: /* Reseting the GLUE video chip should also set freq/res register to 0 */
58: Video_Reset_Glue ();
1.1.1.2 root 59:
60: /* Reset the YM2149 (stop any sound) */
61: PSG_Reset ();
1.1.1.4 ! root 62:
! 63: /* Reset the MFP */
! 64: MFP_Reset ();
! 65:
! 66: /* Reset the FDC */
! 67: FDC_Reset ();
1.1 root 68: }
69:
70:
71: /**
72: * Return interrupt number (1 - 7), -1 means no interrupt.
73: * Note that the interrupt stays pending if it can't be executed yet
74: * due to the interrupt level field in the SR.
75: */
76: int intlev(void)
77: {
78: /* There are only VBL and HBL autovector interrupts in the ST... */
79: assert((pendingInterrupts & ~((1<<4)|(1<<2))) == 0);
80:
1.1.1.4 ! root 81: #if 0
1.1 root 82: if (pendingInterrupts & (1 << 4)) /* VBL interrupt? */
83: {
84: if (regs.intmask < 4)
85: pendingInterrupts &= ~(1 << 4);
86: return 4;
87: }
88: else if (pendingInterrupts & (1 << 2)) /* HBL interrupt? */
89: {
90: if (regs.intmask < 2)
91: pendingInterrupts &= ~(1 << 2);
92: return 2;
93: }
1.1.1.4 ! root 94: #else
! 95: if ( pendingInterrupts & (1 << 4) ) /* VBL interrupt ? */
! 96: return 4;
! 97: else if ( pendingInterrupts & (1 << 2) ) /* HBL interrupt ? */
! 98: return 2;
! 99: #endif
1.1 root 100:
101: return -1;
102: }
103:
104: /**
105: * Initialize 680x0 emulation
106: */
107: int Init680x0(void)
108: {
109: currprefs.cpu_level = changed_prefs.cpu_level = ConfigureParams.System.nCpuLevel;
110:
111: switch (currprefs.cpu_level) {
112: case 0 : currprefs.cpu_model = 68000; break;
113: case 1 : currprefs.cpu_model = 68010; break;
114: case 2 : currprefs.cpu_model = 68020; break;
115: case 3 : currprefs.cpu_model = 68030; break;
116: case 4 : currprefs.cpu_model = 68040; break;
117: case 5 : currprefs.cpu_model = 68060; break;
118: default: fprintf (stderr, "Init680x0() : Error, cpu_level unknown\n");
119: }
120:
121: currprefs.cpu_compatible = changed_prefs.cpu_compatible = ConfigureParams.System.bCompatibleCpu;
122: currprefs.address_space_24 = changed_prefs.address_space_24 = ConfigureParams.System.bAddressSpace24;
123: currprefs.cpu_cycle_exact = changed_prefs.cpu_cycle_exact = ConfigureParams.System.bCycleExactCpu;
124: currprefs.fpu_model = changed_prefs.fpu_model = ConfigureParams.System.n_FPUType;
125: currprefs.fpu_strict = changed_prefs.fpu_strict = ConfigureParams.System.bCompatibleFPU;
126: currprefs.mmu_model = changed_prefs.mmu_model = ConfigureParams.System.bMMU;
127:
128: init_m68k();
129:
130: return true;
131: }
132:
133:
134: /**
135: * Deinitialize 680x0 emulation
136: */
137: void Exit680x0(void)
138: {
139: memory_uninit();
140:
141: free(table68k);
142: table68k = NULL;
143: }
144:
145: /**
146: * This function will be called at system init by the cartridge routine
147: * (after gemdos init, before booting floppies).
148: * The GEMDOS vector (#$84) is setup and we also initialize the connected
149: * drive mask and Line-A variables (for an extended VDI resolution) from here.
150: */
151: unsigned long OpCode_SysInit(uae_u32 opcode)
152: {
153: /* Add any drives mapped by TOS in the interim */
154: ConnectedDriveMask |= STMemory_ReadLong(0x4c2);
155: /* Initialize the connected drive mask */
156: STMemory_WriteLong(0x4c2, ConnectedDriveMask);
157:
158: if (!bInitGemDOS)
159: {
160: /* Init on boot - see cart.c */
161: GemDOS_Boot();
162:
163: /* Update LineA for extended VDI res
164: * D0: LineA base, A1: Font base
165: */
166: VDI_LineA(regs.regs[0], regs.regs[9]);
167: }
168:
169: m68k_incpc(2);
1.1.1.3 root 170: regs.ir = regs.irc;
171: get_word_prefetch(2);
172:
173: return 4 * CYCLE_UNIT / 2;
1.1 root 174: }
175:
176:
177: /**
178: * Intercept GEMDOS calls.
179: * Used for GEMDOS HD emulation (see gemdos.c).
180: */
181: unsigned long OpCode_GemDos(uae_u32 opcode)
182: {
183: GemDOS_OpCode(); /* handler code in gemdos.c */
184:
185: m68k_incpc(2);
1.1.1.3 root 186: regs.ir = regs.irc;
187: get_word_prefetch(2);
188:
189: return 4 * CYCLE_UNIT / 2;
1.1 root 190: }
191:
192:
193: /**
194: * This is called after completion of each VDI call
195: */
196: unsigned long OpCode_VDI(uae_u32 opcode)
197: {
1.1.1.4 ! root 198: Uint32 pc = M68000_GetPC();
1.1 root 199:
1.1.1.4 ! root 200: /* this is valid only after VDI trap, called from cartridge code */
! 201: if (VDI_OldPC && pc >= 0xfa0000 && pc < 0xfc0000)
! 202: {
! 203: VDI_Complete();
! 204:
! 205: /* Set PC back to where originated from to continue instruction decoding */
! 206: m68k_setpc(VDI_OldPC);
! 207: VDI_OldPC = 0;
! 208: }
! 209: else
! 210: {
! 211: /* illegal instruction */
! 212: op_illg(opcode);
! 213: }
1.1 root 214:
1.1.1.3 root 215: get_word_prefetch (0);
216: regs.ir = regs.irc;
217: get_word_prefetch(2);
218:
219: return 4 * CYCLE_UNIT / 2;
1.1 root 220: }
1.1.1.4 ! root 221:
! 222:
! 223: /**
! 224: * Emulator Native Features ID opcode interception.
! 225: */
! 226: unsigned long OpCode_NatFeat_ID(uae_u32 opcode)
! 227: {
! 228: Uint32 stack = Regs[REG_A7] + SIZE_LONG; /* skip return address */
! 229: Uint16 SR = M68000_GetSR();
! 230:
! 231: if (NatFeat_ID(stack, &(Regs[REG_D0]))) {
! 232: M68000_SetSR(SR);
! 233: m68k_incpc(2);
! 234: regs.ir = regs.irc;
! 235: get_word_prefetch(2);
! 236: }
! 237: return 4 * CYCLE_UNIT / 2;
! 238: }
! 239:
! 240: /**
! 241: * Emulator Native Features call opcode interception.
! 242: */
! 243: unsigned long OpCode_NatFeat_Call(uae_u32 opcode)
! 244: {
! 245: Uint32 stack = Regs[REG_A7] + SIZE_LONG; /* skip return address */
! 246: Uint16 SR = M68000_GetSR();
! 247: bool super;
! 248:
! 249: super = ((SR & SR_SUPERMODE) == SR_SUPERMODE);
! 250: if (NatFeat_Call(stack, super, &(Regs[REG_D0]))) {
! 251: M68000_SetSR(SR);
! 252: m68k_incpc(2);
! 253: regs.ir = regs.irc;
! 254: get_word_prefetch(2);
! 255: }
! 256: return 4 * CYCLE_UNIT / 2;
! 257: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.