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