|
|
1.1 root 1: /*****************************************************************************/
2: /* Generator - Sega Genesis emulation - (c) James Ponder 1997-1998 */
3: /*****************************************************************************/
4: /* */
5: /* cpu68k.c */
6: /* */
7: /*****************************************************************************/
8:
9: #include <stdio.h>
10: #include <string.h>
11: #include <stdlib.h>
12:
13: #include "generator.h"
14: #include "mem68k.h"
15: #include "cpu68k.h"
16: #include "vdp.h"
17: #include "ui.h"
18: #include "out/def68k-iibs.h"
19: #include "out/def68k-proto.h"
20: #include "out/def68k-funcs.h"
21:
22: /*** externed variables ***/
23:
24: uint8 *cpu68k_rom = NULL;
25: unsigned int cpu68k_romlen = 0;
26: uint8 *cpu68k_ram = NULL;
27: t_iib *cpu68k_iibtable[65536];
28: void (*cpu68k_functable[65536*2])(t_ipc *ipc);
29: int cpu68k_totalinstr;
30: int cpu68k_totalfuncs;
31: unsigned int cpu68k_clocks;
32: unsigned int cpu68k_frames;
33: t_regs regs;
34: uint8 movem_bit[256];
35: t_ipclist *ipclist[LEN_IPCLISTTABLE];
36:
37: /*** global variables ***/
38:
39: /*** forward references ***/
40:
41: void cpu68k_reset(void);
42:
43: int cpu68k_init(void)
44: {
45: t_iib *iib;
46: uint16 bitmap;
47: int i, j, sbit, dbit, sbits, dbits;
48:
49: memset(cpu68k_iibtable, 0, sizeof(cpu68k_iibtable));
50: memset(cpu68k_functable, 0, sizeof(cpu68k_functable));
51: memset(®s, 0, sizeof(regs));
52:
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:
181: return 0;
182: }
183:
184: /* fill in ipc */
185:
186: void cpu68k_ipc(uint32 addr68k, uint8 *addr, t_iib *iib, t_ipc *ipc)
187: {
188: t_type type;
189: uint32 *p;
190:
191: ipc->opcode = LOCENDIAN16(*(uint16 *)addr);
192: ipc->wordlen = 1;
193: if (!iib) {
194: /* illegal instruction, no further details (wordlen must be set to 1) */
195: return;
196: }
197:
198: ipc->used = iib->flags.used;
199: ipc->set = iib->flags.set;
200:
201: if ((iib->mnemonic == i_Bcc) || (iib->mnemonic == i_BSR)) {
202: /* special case - we can calculate the offset now */
203: /* low 8 bits of current instruction are addr+1 */
204: ipc->src = (sint32)(*(sint8 *)(addr+1));
205: if (ipc->src == 0) {
206: ipc->src = (sint32)(sint16)LOCENDIAN16(*(uint16 *)(addr+2));
207: ipc->wordlen++;
208: }
209: ipc->src+= addr68k+2; /* add PC of next instruction */
210: return;
211: }
212: if (iib->mnemonic == i_DBcc || iib->mnemonic == i_DBRA) {
213: /* special case - we can calculate the offset now */
214: ipc->src = (sint32)(sint16)LOCENDIAN16(*(uint16 *)(addr+2));
215: ipc->src+= addr68k+2; /* add PC of next instruction */
216: ipc->wordlen++;
217: return;
218: }
219:
220: addr+= 2;
221: addr68k+= 2;
222:
223: for (type = 0; type < 2; type++) {
224:
225: if (type == tp_src)
226: p = &(ipc->src);
227: else
228: p = &(ipc->dst);
229:
230: switch(type == tp_src ? iib->stype : iib->dtype) {
231: case dt_Adis:
232: *p = (sint32)(sint16)LOCENDIAN16(*(uint16 *)addr);
233: ipc->wordlen++;
234: addr+= 2;
235: addr68k+= 2;
236: break;
237: case dt_Aidx:
238: *p = (sint32)(sint8)addr[1];
239: *p = (*p & 0xFFFFFF) | (*addr)<<24;
240: ipc->wordlen++;
241: addr+= 2;
242: addr68k+= 2;
243: break;
244: case dt_AbsW:
245: *p = (sint32)(sint16)LOCENDIAN16(*(uint16 *)addr);
246: ipc->wordlen++;
247: addr+= 2;
248: addr68k+= 2;
249: break;
250: case dt_AbsL:
251: *p = (uint32)( (LOCENDIAN16(*(uint16 *)addr)<<16) +
252: LOCENDIAN16(*(uint16 *)(addr+2)) );
253: ipc->wordlen+= 2;
254: addr+= 4;
255: addr68k+= 4;
256: break;
257: case dt_Pdis:
258: *p = (sint32)(sint16)LOCENDIAN16(*(uint16 *)addr);
259: *p+= addr68k; /* add PC of extension word (this word) */
260: ipc->wordlen++;
261: addr+= 2;
262: addr68k+= 2;
263: break;
264: case dt_Pidx:
265: *p = ((sint32)(sint8)addr[1]) + addr68k;
266: *p = (*p & 0xFFFFFF) | (*addr)<<24;
267: ipc->wordlen++;
268: addr+= 2;
269: addr68k+= 2;
270: break;
271: case dt_ImmB:
272: /* low 8 bits of next 16 bit word is addr+1 */
273: *p = (uint32)(*(uint8 *)(addr+1));
274: ipc->wordlen++;
275: addr+= 2;
276: addr68k+= 2;
277: break;
278: case dt_ImmW:
279: *p = (uint32)LOCENDIAN16(*(uint16 *)addr);
280: ipc->wordlen++;
281: addr+= 2;
282: addr68k+= 2;
283: break;
284: case dt_ImmL:
285: *p = (uint32)( (LOCENDIAN16(*(uint16 *)addr)<<16) +
286: LOCENDIAN16(*(uint16 *)(addr+2)) );
287: ipc->wordlen+= 2;
288: addr+= 4;
289: addr68k+= 4;
290: break;
291: case dt_Imm3:
292: if (type == tp_src)
293: *p = (ipc->opcode >> iib->sbitpos) & 7;
294: else
295: *p = (ipc->opcode >> iib->dbitpos) & 7;
296: break;
297: case dt_Imm4:
298: if (type == tp_src)
299: *p = (ipc->opcode >> iib->sbitpos) & 15;
300: else
301: *p = (ipc->opcode >> iib->dbitpos) & 15;
302: break;
303: case dt_Imm8:
304: if (type == tp_src)
305: *p = (ipc->opcode >> iib->sbitpos) & 255;
306: else
307: *p = (ipc->opcode >> iib->dbitpos) & 255;
308: break;
309: case dt_Imm8s:
310: if (type == tp_src)
311: *p = (sint32)(sint8)((ipc->opcode >> iib->sbitpos) & 255);
312: else
313: *p = (sint32)(sint8)((ipc->opcode >> iib->dbitpos) & 255);
314: break;
315: default:
316: break;
317: }
318: }
319: }
320:
321: t_ipclist *cpu68k_makeipclist(uint32 pc)
322: {
323: int size = 16;
324: t_ipclist *list = malloc(sizeof(t_ipclist) + 16*sizeof(t_ipc) + 8);
325: t_ipc *ipc = (t_ipc *)(list+1);
326: t_iib *iib;
327: int instrs = 0;
328: uint16 required;
329: int i;
330:
331: if (list == NULL)
332: ui_err("Out of memory");
333:
334: pc&= 0xffffff;
335: list->pc = pc;
336: list->clocks = 0;
337: list->norepeat = 0;
338: do {
339: instrs++;
340: if (instrs > size) {
341: size+= 16;
342: list = realloc(list, sizeof(t_ipclist) + size*sizeof(t_ipc) + 8);
343: ipc = ((t_ipc *)(list+1))+instrs-1;
344: }
345: if (!(iib = cpu68k_iibtable[fetchword(pc)])) {
346: ui_err("Invalid instruction @ %08X", pc);
347: }
348: cpu68k_ipc(pc, mem68k_memptr[pc>>12](pc), iib, ipc);
349: list->clocks+= iib->clocks;
350: pc+= (iib->wordlen)<<1;
351: ipc++;
352: } while (!iib->flags.endblk);
353: *(int *)ipc = 0;
354:
355: if (instrs == 2) {
356: ipc--;
357: if (iib->mnemonic == i_Bcc && ipc->src == list->pc) {
358: /* we have a 2-instruction block ending in a branch to start */
359: ipc = (t_ipc *)(list+1);
360: iib = cpu68k_iibtable[ipc->opcode];
361: if (iib->mnemonic == i_TST || iib->mnemonic == i_CMP) {
362: /* it's a tst/cmp and then a Bcc */
363: if (!(iib->stype == dt_Ainc || iib->stype == dt_Adec)) {
364: /* no change could happen during the block */
365: list->norepeat = 1;
366: }
367: }
368: }
369: }
370:
371: ipc = ((t_ipc *)(list+1))+instrs-1;
372: required = 0x1F; /* all 5 flags need to be correct at end */
373: for (i = 0; i < instrs; i++) {
374: ipc->set&= required;
375: required&= ~ipc->set;
376: required|= ipc->used;
377: if (ipc->set) {
378: ipc->function = cpu68k_functable[(ipc->opcode<<1)+1];
379: } else {
380: ipc->function = cpu68k_functable[ipc->opcode<<1];
381: }
382: ipc--;
383: }
384: /* fprintf("Cached %08X to %08X\n", list->pc, pc-((iib->wordlen)<<1)); */
385: return list;
386: }
387:
388: void cpu68k_reset(void)
389: {
390: int i;
391:
392: if (!cpu68k_ram) {
393: if ((cpu68k_ram = malloc(0x10000)) == NULL)
394: ui_err("Out of memory");
395: }
396: memset(cpu68k_ram, 0, 0x10000);
397:
398: regs.pc = fetchlong(4);
399: regs.regs[15] = fetchlong(0);
400: regs.sr.sr_int = 0;
401: regs.sr.sr_struct.s = 1; /* Supervisor mode*/
402: regs.stop = 0;
403: cpu68k_clocks = 0;
404: cpu68k_frames = 0; /* Number of frames */
405:
406: for (i = 0; i < LEN_IPCLISTTABLE; i++) {
407: if (ipclist[i]) {
408: free(ipclist[i]);
409: ipclist[i] = NULL;
410: }
411: }
412: }
413:
414: void cpu68k_endfield(void)
415: {
416: cpu68k_clocks = 0;
417: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.