1 /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */
2
3 #include <stdio.h>
4 #include <string.h>
5 #include <stdlib.h>
6
7 #include "generator.h"
8 #include "cpu68k.h"
9 #include "mem68k.h"
10 #include "def68k-iibs.h"
11 #include "def68k-proto.h"
12 #include "def68k-funcs.h"
13
14 int diss68k_gettext(t_ipc * ipc, char *text);
15
16 /*** externed variables ***/
17
18 uint8 *cpu68k_rom = NULL;
19 unsigned int cpu68k_romlen = 0;
20 uint8 *cpu68k_ram = NULL;
21 t_iib *cpu68k_iibtable[65536];
22 void (*cpu68k_functable[65536 * 2]) (t_ipc * ipc);
23 int cpu68k_totalinstr;
24 int cpu68k_totalfuncs;
25
26 unsigned int cpu68k_clocks;
27 unsigned int cpu68k_frames;
28 unsigned int cpu68k_frozen; /* cpu frozen, do not interrupt, make pending */
29 t_regs regs;
30 uint8 movem_bit[256];
31 t_ipclist *ipclist[LEN_IPCLISTTABLE];
32
33 //extern uint8 current_cpu_bank;
34 extern uint32 bankaddress;
35
36 /*** global variables ***/
37
38 /*** forward references ***/
39
40 void cpu68k_reset(void);
41
cpu68k_init(void)42 int cpu68k_init(void)
43 {
44 t_iib *iib;
45 uint16 bitmap;
46 int i, j, sbit, dbit, sbits, dbits;
47
48 memset(cpu68k_iibtable, 0, sizeof(cpu68k_iibtable));
49 memset(cpu68k_functable, 0, sizeof(cpu68k_functable));
50 memset(®s, 0, sizeof(regs));
51
52 cpu68k_frozen = 0;
53 cpu68k_totalinstr = 0;
54
55 for (i = 0; i < iibs_num; i++) {
56 iib = &iibs[i];
57
58 bitmap = iib->mask;
59 sbits = 0;
60 dbits = 0;
61
62 for (j = 0; j < 2; j++) {
63 switch (j ? iib->stype : iib->dtype) {
64 case dt_Dreg:
65 case dt_Areg:
66 case dt_Aind:
67 case dt_Ainc:
68 case dt_Adec:
69 case dt_Adis:
70 case dt_Aidx:
71 if (j) {
72 bitmap ^= 7 << iib->sbitpos;
73 sbits = 3;
74 } else {
75 bitmap ^= 7 << iib->dbitpos;
76 dbits = 3;
77 }
78 break;
79 case dt_AbsW:
80 case dt_AbsL:
81 case dt_Pdis:
82 case dt_Pidx:
83 break;
84 case dt_ImmB:
85 case dt_ImmW:
86 case dt_ImmL:
87 case dt_ImmS:
88 break;
89 case dt_Imm3:
90 if (j) {
91 bitmap ^= 7 << iib->sbitpos;
92 sbits = 3;
93 } else {
94 bitmap ^= 7 << iib->dbitpos;
95 dbits = 3;
96 }
97 break;
98 case dt_Imm4:
99 if (j) {
100 bitmap ^= 15 << iib->sbitpos;
101 sbits = 4;
102 } else {
103 bitmap ^= 15 << iib->dbitpos;
104 dbits = 4;
105 }
106 break;
107 case dt_Imm8:
108 case dt_Imm8s:
109 if (j) {
110 bitmap ^= 255 << iib->sbitpos;
111 sbits = 8;
112 } else {
113 bitmap ^= 255 << iib->dbitpos;
114 dbits = 8;
115 }
116 break;
117 case dt_ImmV:
118 sbits = 12;
119 bitmap ^= 0x0FFF;
120 break;
121 case dt_Ill:
122 /* no src/dst parameter */
123 break;
124 default:
125 LOG_CRITICAL(("CPU definition #%d incorrect", i));
126 return 1;
127 }
128 }
129 if (bitmap != 0xFFFF) {
130 LOG_CRITICAL(("CPU definition #%d incorrect (0x%x)", i, bitmap));
131 return 1;
132 }
133 for (sbit = 0; sbit < (1 << sbits); sbit++) {
134 for (dbit = 0; dbit < (1 << dbits); dbit++) {
135 bitmap = iib->bits | (sbit << iib->sbitpos) | (dbit << iib->dbitpos);
136 if (iib->stype == dt_Imm3 || iib->stype == dt_Imm4
137 || iib->stype == dt_Imm8) {
138 if (sbit == 0 && iib->flags.imm_notzero) {
139 continue;
140 }
141 }
142 if (cpu68k_iibtable[bitmap] != NULL) {
143 LOG_CRITICAL(("CPU definition #%d conflicts (0x%x)", i, bitmap));
144 return 1;
145 }
146 cpu68k_iibtable[bitmap] = iib;
147 /* set both flag and non-flag versions */
148 cpu68k_functable[bitmap * 2] = cpu68k_funcindex[i * 2];
149 cpu68k_functable[bitmap * 2 + 1] = cpu68k_funcindex[i * 2 + 1];
150 cpu68k_totalinstr++;
151 }
152 }
153 }
154
155 j = 0;
156
157 for (i = 0; i < 65536; i++) {
158 if (cpu68k_iibtable[i]) {
159 j++;
160 }
161 }
162 if (j != cpu68k_totalinstr) {
163 LOG_CRITICAL(("Instruction count not verified (%d/%d)\n",
164 cpu68k_totalinstr, i));
165 return 1;
166 }
167
168 cpu68k_totalfuncs = iibs_num;
169
170 for (i = 0; i < 256; i++) {
171 for (j = 0; j < 8; j++) {
172 if (i & (1 << j))
173 break;
174 }
175 movem_bit[i] = j;
176 }
177
178 LOG_VERBOSE(("CPU: %d instructions supported by %d routines",
179 cpu68k_totalinstr, cpu68k_totalfuncs));
180 iib = cpu68k_iibtable[0x2F39];
181 return 0;
182 }
183
cpu68k_printipc(t_ipc * ipc)184 void cpu68k_printipc(t_ipc * ipc)
185 {
186 static char dasmtxt[256];
187 printf("IPC @ 0x%p\n", ipc);
188 diss68k_gettext(ipc,dasmtxt);
189 printf("%s\n",dasmtxt);
190 printf(" opcode: %04X, uses %X set %X\n", ipc->opcode, ipc->used,
191 ipc->set);
192 printf(" src = %08X\n", (unsigned)ipc->src);
193 printf(" dst = %08X\n", (unsigned)ipc->dst);
194 }
195
196 /* fill in ipc */
197
cpu68k_ipc(uint32 addr68k,uint8 * addr,t_iib * iib,t_ipc * ipc)198 void cpu68k_ipc(uint32 addr68k, uint8 *addr, t_iib * iib, t_ipc * ipc)
199 {
200 t_type type;
201 uint32 *p;
202
203 ipc->opcode = LOCENDIAN16(*(uint16 *)addr);
204 ipc->wordlen = 1;
205 if (!iib) {
206 /* illegal instruction, no further details (wordlen must be set to 1) */
207 return;
208 }
209
210 ipc->used = iib->flags.used;
211 ipc->set = iib->flags.set;
212
213 if ((iib->mnemonic == i_Bcc) || (iib->mnemonic == i_BSR)) {
214 /* special case - we can calculate the offset now */
215 /* low 8 bits of current instruction are addr+1 */
216 ipc->src = (sint32)(*(sint8 *)(addr + 1));
217 if (ipc->src == 0) {
218 ipc->src = (sint32)(sint16)LOCENDIAN16(*(uint16 *)(addr + 2));
219 ipc->wordlen++;
220 }
221 ipc->src += addr68k + 2; /* add PC of next instruction */
222 return;
223 }
224 if (iib->mnemonic == i_DBcc || iib->mnemonic == i_DBRA) {
225 /* special case - we can calculate the offset now */
226 ipc->src = (sint32)(sint16)LOCENDIAN16(*(uint16 *)(addr + 2));
227 ipc->src += addr68k + 2; /* add PC of next instruction */
228 ipc->wordlen++;
229 return;
230 }
231
232 addr += 2;
233 addr68k += 2;
234
235 for (type = 0; type < 2; type++) {
236 if (type == tp_src)
237 p = &(ipc->src);
238 else
239 p = &(ipc->dst);
240
241 switch (type == tp_src ? iib->stype : iib->dtype) {
242 case dt_Adis:
243 *p = (sint32)(sint16)LOCENDIAN16(*(uint16 *)addr);
244 ipc->wordlen++;
245 addr += 2;
246 addr68k += 2;
247 break;
248 case dt_Aidx:
249 *p = (sint32)(sint8)addr[1];
250 *p = (*p & 0xFFFFFF) | (*addr) << 24;
251 ipc->wordlen++;
252 addr += 2;
253 addr68k += 2;
254 break;
255 case dt_AbsW:
256 *p = (sint32)(sint16)LOCENDIAN16(*(uint16 *)addr);
257 ipc->wordlen++;
258 addr += 2;
259 addr68k += 2;
260 break;
261 case dt_AbsL:
262 *p = (uint32)((LOCENDIAN16(*(uint16 *)addr) << 16) +
263 LOCENDIAN16(*(uint16 *)(addr + 2)));
264 ipc->wordlen += 2;
265 addr += 4;
266 addr68k += 4;
267 break;
268 case dt_Pdis:
269 *p = (sint32)(sint16)LOCENDIAN16(*(uint16 *)addr);
270 *p += addr68k; /* add PC of extension word (this word) */
271 ipc->wordlen++;
272 addr += 2;
273 addr68k += 2;
274 break;
275 case dt_Pidx:
276 *p = ((sint32)(sint8)addr[1]) + addr68k;
277 *p = (*p & 0xFFFFFF) | (*addr) << 24;
278 ipc->wordlen++;
279 addr += 2;
280 addr68k += 2;
281 break;
282 case dt_ImmB:
283 /* low 8 bits of next 16 bit word is addr+1 */
284 *p = (uint32)(*(uint8 *)(addr + 1));
285 ipc->wordlen++;
286 addr += 2;
287 addr68k += 2;
288 break;
289 case dt_ImmW:
290 *p = (uint32)LOCENDIAN16(*(uint16 *)addr);
291 ipc->wordlen++;
292 addr += 2;
293 addr68k += 2;
294 break;
295 case dt_ImmL:
296 *p = (uint32)((LOCENDIAN16(*(uint16 *)addr) << 16) +
297 LOCENDIAN16(*(uint16 *)(addr + 2)));
298 ipc->wordlen += 2;
299 addr += 4;
300 addr68k += 4;
301 break;
302 case dt_Imm3:
303 if (type == tp_src)
304 *p = (ipc->opcode >> iib->sbitpos) & 7;
305 else
306 *p = (ipc->opcode >> iib->dbitpos) & 7;
307 break;
308 case dt_Imm4:
309 if (type == tp_src)
310 *p = (ipc->opcode >> iib->sbitpos) & 15;
311 else
312 *p = (ipc->opcode >> iib->dbitpos) & 15;
313 break;
314 case dt_Imm8:
315 if (type == tp_src)
316 *p = (ipc->opcode >> iib->sbitpos) & 255;
317 else
318 *p = (ipc->opcode >> iib->dbitpos) & 255;
319 break;
320 case dt_Imm8s:
321 if (type == tp_src)
322 *p = (sint32)(sint8)((ipc->opcode >> iib->sbitpos) & 255);
323 else
324 *p = (sint32)(sint8)((ipc->opcode >> iib->dbitpos) & 255);
325 break;
326 default:
327 break;
328 }
329 }
330 }
331
cpu68k_makeipclist(uint32 pc)332 t_ipclist *cpu68k_makeipclist(uint32 pc)
333 {
334 int size = 16;
335 t_ipclist *list = malloc(sizeof(t_ipclist) + 16 * sizeof(t_ipc) + 8);
336 t_ipc *ipc = (t_ipc *) (list + 1);
337 t_iib *iib;
338 int instrs = 0;
339 uint16 required;
340 int i;
341
342 if (list == NULL) {
343 printf("Out of memory");
344 exit(1);
345 }
346
347 pc &= 0xffffff;
348 list->pc = pc;
349 list->clocks = 0;
350 list->norepeat = 0;
351
352 if ((pc&0xF00000)==0x200000)
353 list->bank = bankaddress;
354 else
355 list->bank = 0;
356
357
358 do {
359 instrs++;
360 if (instrs > size) {
361 if (size > 10000) {
362 printf("Something has gone seriously wrong @ %08X", (unsigned)pc);
363 exit(1);
364 }
365 size += 16;
366 list = realloc(list, sizeof(t_ipclist) + size * sizeof(t_ipc) + 8);
367 if (list == NULL) {
368 printf("Out of memory whilst making ipc list @ %08X",
369 (unsigned)pc);
370 exit(1);
371 }
372 ipc = ((t_ipc *) (list + 1)) + instrs - 1;
373 }
374 if (!(iib = cpu68k_iibtable[fetchword(pc)])) {
375 printf("Invalid instruction @ %08X [%04X]", (unsigned)pc,
376 fetchword(pc));
377 exit(1);
378 }
379 cpu68k_ipc(pc, mem68k_memptr[pc >> 12] (pc), iib, ipc);
380 list->clocks += iib->clocks;
381 pc += (iib->wordlen) << 1;
382 ipc++;
383 }
384 while (!iib->flags.endblk);
385 *(int *)ipc = 0;
386
387 if (instrs == 2) {
388 ipc--;
389 if (iib->mnemonic == i_Bcc && ipc->src == list->pc) {
390 /* we have a 2-instruction block ending in a branch to start */
391 ipc = (t_ipc *) (list + 1);
392 iib = cpu68k_iibtable[ipc->opcode];
393 if (iib->mnemonic == i_TST || iib->mnemonic == i_CMP) {
394 /* it's a tst/cmp and then a Bcc */
395 if (!(iib->stype == dt_Ainc || iib->stype == dt_Adec)) {
396 /* no change could happen during the block */
397 list->norepeat = 1;
398 }
399 }
400 }
401 }
402
403 ipc = ((t_ipc *) (list + 1)) + instrs - 1;
404 required = 0x1F; /* all 5 flags need to be correct at end */
405 for (i = 0; i < instrs; i++) {
406 ipc->set &= required;
407 required &= ~ipc->set;
408 required |= ipc->used;
409 if (ipc->set) {
410 ipc->function = cpu68k_functable[(ipc->opcode << 1) + 1];
411 } else {
412 ipc->function = cpu68k_functable[ipc->opcode << 1];
413 }
414 ipc--;
415 }
416 /* fprintf("Cached %08X to %08X\n", list->pc, pc-((iib->wordlen)<<1)); */
417 return list;
418 }
419
cpu68k_clearcache(void)420 void cpu68k_clearcache(void)
421 {
422 int i;
423 t_ipclist *p, *n;
424
425 for (i = 0; i < LEN_IPCLISTTABLE; i++) {
426 if (ipclist[i]) {
427 p=ipclist[i];
428 while(p){
429 n=p->next;
430 free(p);
431 p=n;
432 }
433 ipclist[i] = NULL;
434 }
435 }
436 }
437
cpu68k_reset(void)438 void cpu68k_reset(void)
439 {
440 int i;
441 t_ipclist *p, *n;
442 #if 0
443 if (!cpu68k_ram) {
444 /* +4 due to bug in DIRECTRAM hdr/mem68k.h code over-run of buffer */
445 if ((cpu68k_ram = malloc(0x10000 + 4)) == NULL)
446 ui_err("Out of memory");
447 }
448 memset(cpu68k_ram, 0, 0x10000);
449 #endif
450
451 regs.pc = fetchlong(4);
452 regs.regs[15] = fetchlong(0);
453 regs.sr.sr_int = 0;
454 regs.sr.sr_struct.s = 1; /* Supervisor mode */
455 regs.stop = 0;
456 cpu68k_clocks = 0;
457 cpu68k_frames = 0; /* Number of frames */
458
459 for (i = 0; i < LEN_IPCLISTTABLE; i++) {
460 if (ipclist[i]) {
461 p=ipclist[i];
462 while(p){
463 n=p->next;
464 free(p);
465 p=n;
466 }
467 ipclist[i] = NULL;
468 }
469 }
470 }
471
cpu68k_endfield(void)472 void cpu68k_endfield(void)
473 {
474 cpu68k_clocks = 0;
475 }
476