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
10
11 #include "reg68k.h"
12 #include "cpu68k.h"
13 #include "mem68k.h"
14 #include "compile.h"
15
16
17 /*** global variables ***/
18 /*
19 #if (!(defined(PROCESSOR_ARM) || defined(PROCESSOR_SPARC) \
20 || defined(PROCESSOR_INTEL)))
21 #endif
22 */
23
24 //#endif
25
26
27 //extern uint8 current_cpu_bank;
28 extern uint32 bankaddress;
29
30 /*** forward references ***/
31
reg68k_printstat(void)32 void reg68k_printstat(void) {
33 unsigned int i;
34 t_ipclist *list;
35 for (i=0;i<LEN_IPCLISTTABLE;i++) {
36 list = ipclist[i];
37 while (list) {
38 printf("%08x %d\n", list->pc, (unsigned)list->pass);
39 list = list->next;
40 }
41 }
42 }
43
44
45
46 /*** reg68k_external_step - execute one instruction ***/
47
48
reg68k_external_step(void)49 unsigned int reg68k_external_step(void)
50 {
51 static t_ipc ipc;
52 static t_iib *piib;
53 static unsigned int clks;
54
55 /* !!! entering global register usage area !!! */
56
57 if (regs.pending && ((regs.sr.sr_int >> 8) & 7) < regs.pending)
58 reg68k_internal_autovector(regs.pending);
59
60 if (!(piib = cpu68k_iibtable[fetchword(regs.pc)]))
61 printf("Invalid instruction @ %08X [%04X]\n", (unsigned)regs.pc,
62 fetchword(regs.pc));
63
64 cpu68k_ipc(regs.pc,
65 mem68k_memptr[(regs.pc >> 12) & 0xfff] (regs.pc &
66 0xFFFFFF), piib,
67 &ipc);
68 cpu68k_functable[fetchword(regs.pc) * 2 + 1] (&ipc);
69 clks = piib->clocks;
70
71 cpu68k_clocks += clks;
72 return clks; /* number of clocks done */
73 }
74
75 /*** reg68k_external_execute - execute at least given number of clocks,
76 and return number of clocks executed too much ***/
77
reg68k_external_execute(unsigned int clocks)78 unsigned int reg68k_external_execute(unsigned int clocks)
79 {
80 unsigned int index;
81 t_ipclist *list;
82 t_ipc *ipc;
83 uint32 pc24;
84
85 uint32 bank;
86 static t_ipc step_ipc;
87 static t_iib *step_piib;
88 static int clks;
89
90
91 clks = clocks;
92
93 if (regs.pending && ((regs.sr.sr_int >> 8) & 7) < regs.pending)
94 reg68k_internal_autovector(regs.pending);
95
96 do {
97 pc24 = regs.pc & 0xffffff;
98 // if ((pc24 & 0xff0000) == 0xff0000) {
99 if ((pc24&0xF00000)==0x200000)
100 bank=bankaddress;
101 else
102 bank=0;
103 if ((pc24>>16) == 0x10) { /* Modif : neogeo RAM is 0x100000 - 0x10FFFF */
104
105 /* executing code from RAM, do not use compiled information */
106 do {
107 step_piib = cpu68k_iibtable[fetchword(regs.pc)];
108 if (!step_piib)
109 printf("Invalid instruction (iib assert) @ %08X\n",
110 (unsigned)regs.pc);
111 cpu68k_ipc(regs.pc,
112 mem68k_memptr[(regs.pc >> 12) &
113 0xfff] (regs.pc & 0xFFFFFF),
114 step_piib, &step_ipc);
115 cpu68k_functable[fetchword(regs.pc) * 2 + 1] (&step_ipc);
116 clks -= step_piib->clocks;
117 cpu68k_clocks += step_piib->clocks;
118 }
119 while (!step_piib->flags.endblk);
120 list = NULL; /* stop compiler warning ;( */
121 } else {
122 index = (pc24 >> 1) & (LEN_IPCLISTTABLE - 1);
123 list = ipclist[index];
124 while (list && (list->pc != pc24 || list->bank!=bank)) {
125 //while (list && (list->pc != pc24)) {
126 list = list->next;
127 }
128 //printf("TOOT\n");
129 //#ifdef GENERATOR_JIT
130 #if ((defined PROCESSOR_SPARC) && (defined GENERATOR_JIT))
131 if (!list) {
132 list = cpu68k_makeipclist(pc24);
133 list->pass=0;
134 list->next = ipclist[index];
135 ipclist[index] = list;
136 list->compiled = compile_make(list);
137 }
138 list->pass++;
139 //printf("first ipc=%p\n",(t_ipc *) (list + 1));
140 list->compiled((t_ipc *) (list + 1));
141 //printf("PC=%x\n",regs.pc);
142 #else
143 if (!list) {
144 /* LOG_USER(("Making IPC list @ %08x", pc24)); */
145 //printf("Making IPC list @ %08x\n", pc24);
146 list = cpu68k_makeipclist(pc24);
147 list->next = ipclist[index];
148 ipclist[index] = list;
149 }
150 ipc = (t_ipc *) (list + 1);
151 //printf("Exe IPC list @ %08x\n", pc24);
152 do {
153 ipc->function(ipc);
154 ipc++;
155 }
156 while (*(int *)ipc);
157 #endif
158 //do {
159 clks -= list->clocks;
160 cpu68k_clocks += list->clocks;
161 //} while (list->norepeat && clks > 0);
162 }
163 }
164 while (clks > 0);
165
166 return -clks; /* i.e. number of clocks done too much */
167 }
168
169 /*** reg68k_external_autovector - for external use ***/
170
reg68k_external_autovector(int avno)171 void reg68k_external_autovector(int avno)
172 {
173
174 reg68k_internal_autovector(avno);
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
reg68k_internal_autovector(int avno)190 void reg68k_internal_autovector(int avno)
191 {
192 int curlevel = (regs.sr.sr_int >> 8) & 7;
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 */
199 regs.pc += 4;
200 regs.stop = 0;
201 }
202 if (!regs.sr.sr_struct.s) {
203 regs.regs[15] ^= regs.sp; /* swap A7 and SP */
204 regs.sp ^= regs.regs[15];
205 regs.regs[15] ^= regs.sp;
206 regs.sr.sr_struct.s = 1;
207 }
208 regs.regs[15] -= 4;
209 storelong(regs.regs[15], regs.pc);
210 regs.regs[15] -= 2;
211 storeword(regs.regs[15], regs.sr.sr_int);
212 regs.sr.sr_struct.t = 0;
213 regs.sr.sr_int &= ~0x0700;
214 regs.sr.sr_int |= avno << 8;
215 tmpaddr = regs.pc;
216 regs.pc = fetchlong((V_AUTO + avno - 1) * 4);
217 LOG_USER(("AUTOVECTOR %d: %X -> %X", avno, tmpaddr, regs.pc));
218 regs.pending = 0;
219 } else {
220 LOG_USER(("%08X autovector %d pending", regs.pc, avno));
221 // if (!regs.pending || regs.pending < avno) - not sure about this
222 regs.pending = avno;
223 }
224 }
225
226 /*** reg68k_internal_vector - go to vector - this call assumes global
227 registers are already setup ***/
228
reg68k_internal_vector(int vno,uint32 oldpc)229 void reg68k_internal_vector(int vno, uint32 oldpc)
230 {
231 if (!regs.sr.sr_struct.s) {
232 regs.regs[15] ^= regs.sp; /* swap A7 and SP */
233 regs.sp ^= regs.regs[15];
234 regs.regs[15] ^= regs.sp;
235 regs.sr.sr_struct.s = 1;
236 }
237 regs.regs[15] -= 4;
238 storelong(regs.regs[15], oldpc);
239 regs.regs[15] -= 2;
240 storeword(regs.regs[15], regs.sr.sr_int);
241 regs.pc = fetchlong(vno * 4);
242
243 }
244
245