|
|
1.1 root 1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */
2:
3: #include "generator.h"
4: #include "registers.h"
5:
6: #include <stdio.h>
7: #include <string.h>
8: #include <stdlib.h>
9: #include <setjmp.h>
10:
11: #include "reg68k.h"
12: #include "cpu68k.h"
1.1.1.2 root 13: #include "mem68k.h"
1.1.1.4 ! root 14: #include "diss68k.h"
1.1 root 15: #include "cpuz80.h"
16: #include "vdp.h"
17: #include "ui.h"
18: #include "compile.h"
19: #include "gensound.h"
20:
1.1.1.2 root 21: /*** global variables ***/
1.1 root 22:
23: #if (!(defined(PROCESSOR_ARM) || defined(PROCESSOR_SPARC) \
24: || defined(PROCESSOR_INTEL)))
1.1.1.2 root 25: uint32 reg68k_pc;
26: uint32 *reg68k_regs;
27: t_sr reg68k_sr;
1.1 root 28: #endif
29:
30: /*** forward references ***/
31:
32: /*** reg68k_external_step - execute one instruction ***/
33:
34: unsigned int reg68k_external_step(void)
35: {
36: static t_ipc ipc;
37: static t_iib *piib;
38: jmp_buf jb;
39: static unsigned int clks;
40:
41: /* !!! entering global register usage area !!! */
42:
43: if (!setjmp(jb)) {
44: /* move PC and register block into global processor register variables */
45: reg68k_pc = regs.pc;
46: reg68k_regs = regs.regs;
47: reg68k_sr = regs.sr;
48:
49: if (regs.pending && ((reg68k_sr.sr_int >> 8) & 7) < regs.pending)
50: reg68k_internal_autovector(regs.pending);
51:
52: if (!(piib = cpu68k_iibtable[fetchword(reg68k_pc)]))
1.1.1.4 ! root 53: ui_err("Invalid instruction @ %08X [%04X]\n", reg68k_pc,
! 54: fetchword(reg68k_pc));
1.1 root 55:
56: cpu68k_ipc(reg68k_pc,
1.1.1.2 root 57: mem68k_memptr[(reg68k_pc >> 12) & 0xfff] (reg68k_pc &
58: 0xFFFFFF), piib,
59: &ipc);
60: cpu68k_functable[fetchword(reg68k_pc) * 2 + 1] (&ipc);
61: clks = piib->clocks;
1.1 root 62: /* restore global registers back to permanent storage */
63: regs.pc = reg68k_pc;
64: regs.sr = reg68k_sr;
65: longjmp(jb, 1);
66: }
1.1.1.2 root 67: cpu68k_clocks += clks;
68: return clks; /* number of clocks done */
1.1 root 69: }
70:
71: /*** reg68k_external_execute - execute at least given number of clocks,
72: and return number of clocks executed too much ***/
73:
74: unsigned int reg68k_external_execute(unsigned int clocks)
75: {
1.1.1.3 root 76: unsigned int index;
1.1 root 77: t_ipclist *list;
78: t_ipc *ipc;
79: uint32 pc24;
80: jmp_buf jb;
81: static t_ipc step_ipc;
82: static t_iib *step_piib;
83: static int clks;
84:
85: clks = clocks;
86:
87: if (!setjmp(jb)) {
88: /* move PC and register block into global variables */
89: reg68k_pc = regs.pc;
90: reg68k_regs = regs.regs;
91: reg68k_sr = regs.sr;
92:
93: if (regs.pending && ((reg68k_sr.sr_int >> 8) & 7) < regs.pending)
94: reg68k_internal_autovector(regs.pending);
95:
96: do {
97: pc24 = reg68k_pc & 0xffffff;
98: if ((pc24 & 0xff0000) == 0xff0000) {
1.1.1.2 root 99: /* executing code from RAM, do not use compiled information */
100: do {
101: step_piib = cpu68k_iibtable[fetchword(reg68k_pc)];
1.1 root 102: if (!step_piib)
103: ui_err("Invalid instruction (iib assert) @ %08X\n", reg68k_pc);
1.1.1.2 root 104: cpu68k_ipc(reg68k_pc,
105: mem68k_memptr[(reg68k_pc >> 12) &
106: 0xfff] (reg68k_pc & 0xFFFFFF),
107: step_piib, &step_ipc);
108: cpu68k_functable[fetchword(reg68k_pc) * 2 + 1] (&step_ipc);
109: clks -= step_piib->clocks;
110: cpu68k_clocks += step_piib->clocks;
111: }
112: while (!step_piib->flags.endblk);
113: list = NULL; /* stop compiler warning ;( */
1.1 root 114: } else {
1.1.1.2 root 115: index = (pc24 >> 1) & (LEN_IPCLISTTABLE - 1);
116: list = ipclist[index];
117: while (list && (list->pc != pc24)) {
118: list = list->next;
119: }
1.1 root 120: #ifdef PROCESSOR_ARM
1.1.1.2 root 121: if (!list) {
122: list = cpu68k_makeipclist(pc24);
123: list->next = ipclist[index];
124: ipclist[index] = list;
125: list->compiled = compile_make(list);
126: }
127: list->compiled((t_ipc *) (list + 1));
1.1 root 128: #else
1.1.1.2 root 129: if (!list) {
130: /* LOG_USER(("Making IPC list @ %08x", pc24)); */
131: list = cpu68k_makeipclist(pc24);
132: list->next = ipclist[index];
133: ipclist[index] = list;
134: }
135: ipc = (t_ipc *) (list + 1);
136: do {
137: ipc->function(ipc);
138: ipc++;
139: }
140: while (*(int *)ipc);
1.1 root 141: #endif
1.1.1.4 ! root 142: do {
! 143: clks -= list->clocks;
! 144: cpu68k_clocks += list->clocks;
! 145: } while (list->norepeat && clks > 0);
1.1 root 146: }
1.1.1.2 root 147: }
148: while (clks > 0);
1.1 root 149: /* restore global registers back to permanent storage */
150: regs.pc = reg68k_pc;
151: regs.sr = reg68k_sr;
152: longjmp(jb, 1);
153: }
1.1.1.2 root 154: return -clks; /* i.e. number of clocks done too much */
1.1 root 155: }
156:
157: /*** reg68k_external_autovector - for external use ***/
158:
159: void reg68k_external_autovector(int avno)
160: {
161: jmp_buf jb;
162:
163: if (!setjmp(jb)) {
164: /* move PC and register block into global processor register variables */
165: reg68k_pc = regs.pc;
166: reg68k_regs = regs.regs;
167: reg68k_sr = regs.sr;
168:
169: reg68k_internal_autovector(avno);
170:
171: /* restore global registers back to permanent storage */
172: regs.pc = reg68k_pc;
173: regs.sr = reg68k_sr;
174: longjmp(jb, 1);
175: }
176: }
177:
178: /*** reg68k_internal_autovector - go to autovector - this call assumes global
179: registers are already setup ***/
180:
181: /* interrupts must not occur during cpu68k_frozen, as this flag indicates
182: that we are catching up events due to a dma transfer. Since the dma
183: transfer is triggered by a memory write at which stage the current value
184: of the PC is not written anywhere (due to being in the middle of a 68k
185: block and it's in a local register), we MUST NOT use regs.pc - this
186: routine uses reg68k_pc but this is loaded by reg68k_external_autovector,
187: which is called by event_nextevent() and therefore will be a *WRONG*
188: reg68k_pc! */
189:
190: void reg68k_internal_autovector(int avno)
191: {
1.1.1.2 root 192: int curlevel = (reg68k_sr.sr_int >> 8) & 7;
1.1 root 193: uint32 tmpaddr;
194:
195: if ((curlevel < avno || avno == 7) && !cpu68k_frozen) {
196: if (regs.stop) {
197: LOG_DEBUG1(("stop finished"));
198: /* autovector whilst in a STOP instruction */
1.1.1.2 root 199: reg68k_pc += 4;
1.1 root 200: regs.stop = 0;
201: }
202: if (!reg68k_sr.sr_struct.s) {
1.1.1.2 root 203: reg68k_regs[15] ^= regs.sp; /* swap A7 and SP */
204: regs.sp ^= reg68k_regs[15];
205: reg68k_regs[15] ^= regs.sp;
1.1 root 206: reg68k_sr.sr_struct.s = 1;
207: }
1.1.1.2 root 208: reg68k_regs[15] -= 4;
209: storelong(reg68k_regs[15], reg68k_pc);
210: reg68k_regs[15] -= 2;
211: storeword(reg68k_regs[15], reg68k_sr.sr_int);
1.1 root 212: reg68k_sr.sr_struct.t = 0;
1.1.1.2 root 213: reg68k_sr.sr_int &= ~0x0700;
214: reg68k_sr.sr_int |= avno << 8;
1.1 root 215: tmpaddr = reg68k_pc;
1.1.1.2 root 216: reg68k_pc = fetchlong((V_AUTO + avno - 1) * 4);
217: LOG_USER(("AUTOVECTOR %d: %X -> %X", avno, tmpaddr, reg68k_pc));
1.1 root 218: regs.pending = 0;
219: } else {
1.1.1.2 root 220: LOG_USER(("%08X autovector %d pending", reg68k_pc, avno));
221: // if (!regs.pending || regs.pending < avno) - not sure about this
1.1 root 222: regs.pending = avno;
223: }
224: }
225:
226: /*** reg68k_internal_vector - go to vector - this call assumes global
227: registers are already setup ***/
228:
229: void reg68k_internal_vector(int vno, uint32 oldpc)
230: {
231: if (!reg68k_sr.sr_struct.s) {
1.1.1.2 root 232: reg68k_regs[15] ^= regs.sp; /* swap A7 and SP */
233: regs.sp ^= reg68k_regs[15];
234: reg68k_regs[15] ^= regs.sp;
1.1 root 235: reg68k_sr.sr_struct.s = 1;
236: }
1.1.1.2 root 237: reg68k_regs[15] -= 4;
1.1 root 238: storelong(reg68k_regs[15], oldpc);
1.1.1.2 root 239: reg68k_regs[15] -= 2;
1.1 root 240: storeword(reg68k_regs[15], reg68k_sr.sr_int);
1.1.1.2 root 241: reg68k_pc = fetchlong(vno * 4);
1.1 root 242: /* LOG_USER(("VECTOR %d: %X -> %X\n", vno, oldpc, reg68k_pc)); */
1.1.1.2 root 243: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.