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