|
|
1.1 ! root 1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */ ! 2: ! 3: #include "generator.h" ! 4: #include "registers.h" ! 5: ! 6: #include <stdio.h> ! 7: #include <string.h> ! 8: #include <stdlib.h> ! 9: #include <setjmp.h> ! 10: ! 11: #include "reg68k.h" ! 12: #include "mem68k.h" ! 13: #include "cpu68k.h" ! 14: #include "cpuz80.h" ! 15: #include "vdp.h" ! 16: #include "ui.h" ! 17: #include "compile.h" ! 18: #include "gensound.h" ! 19: ! 20: /*** externed variables ***/ ! 21: ! 22: #if (!(defined(PROCESSOR_ARM) || defined(PROCESSOR_SPARC) \ ! 23: || defined(PROCESSOR_INTEL))) ! 24: uint32 reg68k_pc; ! 25: uint32 *reg68k_regs; ! 26: t_sr reg68k_sr; ! 27: #endif ! 28: ! 29: /*** forward references ***/ ! 30: ! 31: ! 32: /*** reg68k_external_step - execute one instruction ***/ ! 33: ! 34: unsigned int reg68k_external_step(void) ! 35: { ! 36: static t_ipc ipc; ! 37: static t_iib *piib; ! 38: jmp_buf jb; ! 39: static unsigned int clks; ! 40: ! 41: /* !!! entering global register usage area !!! */ ! 42: ! 43: if (!setjmp(jb)) { ! 44: /* move PC and register block into global processor register variables */ ! 45: reg68k_pc = regs.pc; ! 46: reg68k_regs = regs.regs; ! 47: reg68k_sr = regs.sr; ! 48: ! 49: if (regs.pending && ((reg68k_sr.sr_int >> 8) & 7) < regs.pending) ! 50: reg68k_internal_autovector(regs.pending); ! 51: ! 52: if (!(piib = cpu68k_iibtable[fetchword(reg68k_pc)])) ! 53: ui_err("Invalid instruction @ %08X\n", reg68k_pc); ! 54: ! 55: cpu68k_ipc(reg68k_pc, ! 56: mem68k_memptr[(reg68k_pc>>12) & 0xfff](reg68k_pc & 0xFFFFFF), ! 57: piib, &ipc); ! 58: cpu68k_functable[fetchword(reg68k_pc)*2+1](&ipc); ! 59: clks = piib->clocks; ! 60: /* restore global registers back to permanent storage */ ! 61: regs.pc = reg68k_pc; ! 62: regs.sr = reg68k_sr; ! 63: longjmp(jb, 1); ! 64: } ! 65: cpu68k_clocks+= clks; ! 66: return clks; /* number of clocks done */ ! 67: } ! 68: ! 69: /*** reg68k_external_execute - execute at least given number of clocks, ! 70: and return number of clocks executed too much ***/ ! 71: ! 72: unsigned int reg68k_external_execute(unsigned int clocks) ! 73: { ! 74: unsigned int index, i; ! 75: t_ipclist *list; ! 76: t_ipc *ipc; ! 77: uint32 pc24; ! 78: jmp_buf jb; ! 79: static t_ipc step_ipc; ! 80: static t_iib *step_piib; ! 81: static int clks; ! 82: ! 83: clks = clocks; ! 84: ! 85: if (!setjmp(jb)) { ! 86: /* move PC and register block into global variables */ ! 87: reg68k_pc = regs.pc; ! 88: reg68k_regs = regs.regs; ! 89: reg68k_sr = regs.sr; ! 90: ! 91: if (regs.pending && ((reg68k_sr.sr_int >> 8) & 7) < regs.pending) ! 92: reg68k_internal_autovector(regs.pending); ! 93: ! 94: do { ! 95: pc24 = reg68k_pc & 0xffffff; ! 96: if ((pc24 & 0xff0000) == 0xff0000) { ! 97: /* executing code from RAM, do not use compiled information */ ! 98: do { ! 99: step_piib = cpu68k_iibtable[fetchword(reg68k_pc)]; ! 100: if (!step_piib) ! 101: ui_err("Invalid instruction (iib assert) @ %08X\n", reg68k_pc); ! 102: cpu68k_ipc(reg68k_pc, ! 103: mem68k_memptr[(reg68k_pc>>12) & ! 104: 0xfff](reg68k_pc & 0xFFFFFF), ! 105: step_piib, &step_ipc); ! 106: cpu68k_functable[fetchword(reg68k_pc)*2+1](&step_ipc); ! 107: clks-= step_piib->clocks; ! 108: cpu68k_clocks+= step_piib->clocks; ! 109: } while (!step_piib->flags.endblk); ! 110: list = NULL; /* stop compiler warning ;( */ ! 111: } else { ! 112: index = (pc24>>1) & (LEN_IPCLISTTABLE-1); ! 113: list = ipclist[index]; ! 114: while(list && (list->pc != pc24)) { ! 115: list = list->next; ! 116: } ! 117: #ifdef PROCESSOR_ARM ! 118: if (!list) { ! 119: list = cpu68k_makeipclist(pc24); ! 120: list->next = ipclist[index]; ! 121: ipclist[index] = list; ! 122: list->compiled = compile_make(list); ! 123: } ! 124: list->compiled((t_ipc *)(list+1)); ! 125: #else ! 126: if (!list) { ! 127: /* LOG_USER(("Making IPC list @ %08x", pc24)); */ ! 128: list = cpu68k_makeipclist(pc24); ! 129: list->next = ipclist[index]; ! 130: ipclist[index] = list; ! 131: } ! 132: ipc = (t_ipc *)(list+1); ! 133: do { ! 134: ipc->function(ipc); ! 135: ipc++; ! 136: } while (*(int *)ipc); ! 137: #endif ! 138: clks-= list->clocks; ! 139: cpu68k_clocks+= list->clocks; ! 140: } ! 141: } while (clks > 0); ! 142: /* restore global registers back to permanent storage */ ! 143: regs.pc = reg68k_pc; ! 144: regs.sr = reg68k_sr; ! 145: longjmp(jb, 1); ! 146: } ! 147: return -clks; /* i.e. number of clocks done too much */ ! 148: } ! 149: ! 150: /*** reg68k_external_autovector - for external use ***/ ! 151: ! 152: void reg68k_external_autovector(int avno) ! 153: { ! 154: jmp_buf jb; ! 155: ! 156: if (!setjmp(jb)) { ! 157: /* move PC and register block into global processor register variables */ ! 158: reg68k_pc = regs.pc; ! 159: reg68k_regs = regs.regs; ! 160: reg68k_sr = regs.sr; ! 161: ! 162: reg68k_internal_autovector(avno); ! 163: ! 164: /* restore global registers back to permanent storage */ ! 165: regs.pc = reg68k_pc; ! 166: regs.sr = reg68k_sr; ! 167: longjmp(jb, 1); ! 168: } ! 169: } ! 170: ! 171: /*** reg68k_internal_autovector - go to autovector - this call assumes global ! 172: registers are already setup ***/ ! 173: ! 174: /* interrupts must not occur during cpu68k_frozen, as this flag indicates ! 175: that we are catching up events due to a dma transfer. Since the dma ! 176: transfer is triggered by a memory write at which stage the current value ! 177: of the PC is not written anywhere (due to being in the middle of a 68k ! 178: block and it's in a local register), we MUST NOT use regs.pc - this ! 179: routine uses reg68k_pc but this is loaded by reg68k_external_autovector, ! 180: which is called by event_nextevent() and therefore will be a *WRONG* ! 181: reg68k_pc! */ ! 182: ! 183: void reg68k_internal_autovector(int avno) ! 184: { ! 185: int curlevel = (reg68k_sr.sr_int>>8) & 7; ! 186: uint32 tmpaddr; ! 187: ! 188: if ((curlevel < avno || avno == 7) && !cpu68k_frozen) { ! 189: if (regs.stop) { ! 190: LOG_DEBUG1(("stop finished")); ! 191: /* autovector whilst in a STOP instruction */ ! 192: reg68k_pc+= 4; ! 193: regs.stop = 0; ! 194: } ! 195: if (!reg68k_sr.sr_struct.s) { ! 196: regs.regs[15]^= regs.sp; /* swap A7 and SP */ ! 197: regs.sp^= regs.regs[15]; ! 198: regs.regs[15]^= regs.sp; ! 199: reg68k_sr.sr_struct.s = 1; ! 200: } ! 201: regs.regs[15]-=4; ! 202: storelong(regs.regs[15], reg68k_pc); ! 203: regs.regs[15]-=2; ! 204: storeword(regs.regs[15], reg68k_sr.sr_int); ! 205: reg68k_sr.sr_struct.t = 0; ! 206: reg68k_sr.sr_int&= ~0x0700; ! 207: reg68k_sr.sr_int|= avno << 8; ! 208: tmpaddr = reg68k_pc; ! 209: reg68k_pc = fetchlong((V_AUTO+avno-1)*4); ! 210: /* LOG_USER(("AUTOVECTOR %d: %X -> %X", avno, tmpaddr, reg68k_pc)); */ ! 211: regs.pending = 0; ! 212: } else { ! 213: /* LOG_USER(("%08X autovector %d pending", reg68k_pc, avno)); */ ! 214: regs.pending = avno; ! 215: } ! 216: } ! 217: ! 218: /*** reg68k_internal_vector - go to vector - this call assumes global ! 219: registers are already setup ***/ ! 220: ! 221: void reg68k_internal_vector(int vno, uint32 oldpc) ! 222: { ! 223: if (!reg68k_sr.sr_struct.s) { ! 224: reg68k_regs[15]^= regs.sp; /* swap A7 and SP */ ! 225: regs.sp^= reg68k_regs[15]; ! 226: reg68k_regs[15]^= regs.sp; ! 227: reg68k_sr.sr_struct.s = 1; ! 228: } ! 229: reg68k_regs[15]-=4; ! 230: storelong(reg68k_regs[15], oldpc); ! 231: reg68k_regs[15]-=2; ! 232: storeword(reg68k_regs[15], reg68k_sr.sr_int); ! 233: reg68k_pc = fetchlong(vno*4); ! 234: /* LOG_USER(("VECTOR %d: %X -> %X\n", vno, oldpc, reg68k_pc)); */ ! 235: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.