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