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