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