|
|
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.