|
|
1.1.1.2 ! root 1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */ 1.1 root 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: 1.1.1.2 ! root 11: #include "reg68k.h" 1.1 root 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: 1.1.1.2 ! root 32: /*** reg68k_external_step - execute one instruction ***/ 1.1 root 33: 1.1.1.2 ! root 34: unsigned int reg68k_external_step(void) 1.1 root 35: { 36: static t_ipc ipc; 37: static t_iib *piib; 38: jmp_buf jb; 1.1.1.2 ! root 39: static unsigned int clks; ! 40: ! 41: if (!(piib = cpu68k_iibtable[fetchword(regs.pc)])) ! 42: ui_err("Invalid instruction @ %08X\n", regs.pc); 1.1 root 43: 44: /* !!! entering global register usage area !!! */ 45: 46: if (!setjmp(jb)) { 1.1.1.2 ! root 47: /* move PC and register block into global processor register variables */ 1.1 root 48: reg68k_pc = regs.pc; 49: reg68k_regs = regs.regs; 50: reg68k_sr = regs.sr; 51: 1.1.1.2 ! root 52: if (regs.pending && ((reg68k_sr.sr_int >> 8) & 7) < regs.pending) ! 53: reg68k_internal_autovector(regs.pending); ! 54: 1.1 root 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: cpu68k_clocks+= piib->clocks; 1.1.1.2 ! root 60: clks = cpu68k_clocks; 1.1 root 61: /* restore global registers back to permanent storage */ 62: regs.pc = reg68k_pc; 63: regs.sr = reg68k_sr; 64: longjmp(jb, 1); 65: } 1.1.1.2 ! root 66: return clks; /* number of clocks done */ 1.1 root 67: } 68: 1.1.1.2 ! root 69: /*** reg68k_external_execute - execute at least given number of clocks, ! 70: and return number of clocks executed too much (-ve) ***/ 1.1 root 71: 1.1.1.2 ! root 72: unsigned int reg68k_external_execute(unsigned int clocks) 1.1 root 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; 1.1.1.2 ! root 81: static int clks; ! 82: ! 83: clks = clocks; 1.1 root 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: 1.1.1.2 ! root 91: if (regs.pending && ((reg68k_sr.sr_int >> 8) & 7) < regs.pending) ! 92: reg68k_internal_autovector(regs.pending); ! 93: 1.1 root 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: cpu68k_ipc(reg68k_pc, 101: mem68k_memptr[(reg68k_pc>>12) & 102: 0xfff](reg68k_pc & 0xFFFFFF), 103: step_piib, &step_ipc); 104: cpu68k_functable[fetchword(reg68k_pc)*2+1](&step_ipc); 1.1.1.2 ! root 105: clks-= step_piib->clocks; 1.1 root 106: cpu68k_clocks+= step_piib->clocks; 107: } while (!step_piib->flags.endblk); 108: list = NULL; /* stop compiler warning ;( */ 109: } else { 110: index = (pc24>>1) & (LEN_IPCLISTTABLE-1); 111: list = ipclist[index]; 112: while(list && (list->pc != pc24)) { 113: list = list->next; 114: } 115: #ifdef PROCESSOR_ARM 116: if (!list) { 117: list = cpu68k_makeipclist(pc24); 118: list->next = ipclist[index]; 119: ipclist[index] = list; 120: list->compiled = compile_make(list); 121: } 122: list->compiled((t_ipc *)(list+1)); 123: #else 124: if (!list) { 125: /* LOG_USER(("Making IPC list @ %08x", pc24)); */ 126: list = cpu68k_makeipclist(pc24); 127: list->next = ipclist[index]; 128: ipclist[index] = list; 129: } 130: ipc = (t_ipc *)(list+1); 131: do { 132: ipc->function(ipc); 133: ipc++; 134: } while (*(int *)ipc); 135: #endif 1.1.1.2 ! root 136: clks-= list->clocks; 1.1 root 137: cpu68k_clocks+= list->clocks; 138: } 1.1.1.2 ! root 139: } while (clks > 0); 1.1 root 140: /* restore global registers back to permanent storage */ 141: regs.pc = reg68k_pc; 142: regs.sr = reg68k_sr; 143: longjmp(jb, 1); 144: } 1.1.1.2 ! root 145: return -clks; /* i.e. number of clocks done too much */ 1.1 root 146: } 147: 1.1.1.2 ! root 148: /*** reg68k_external_autovector - for external use ***/ ! 149: ! 150: void reg68k_external_autovector(int avno) ! 151: { ! 152: jmp_buf jb; ! 153: ! 154: if (!setjmp(jb)) { ! 155: /* move PC and register block into global processor register variables */ ! 156: reg68k_pc = regs.pc; ! 157: reg68k_regs = regs.regs; ! 158: reg68k_sr = regs.sr; ! 159: ! 160: reg68k_internal_autovector(avno); ! 161: ! 162: /* restore global registers back to permanent storage */ ! 163: regs.pc = reg68k_pc; ! 164: regs.sr = reg68k_sr; ! 165: longjmp(jb, 1); ! 166: } ! 167: } ! 168: ! 169: /*** reg68k_internal_autovector - go to autovector - this call assumes global ! 170: registers are already setup ***/ ! 171: ! 172: void reg68k_internal_autovector(int avno) 1.1 root 173: { 174: int curlevel = (reg68k_sr.sr_int>>8) & 7; 175: uint32 tmpaddr; 176: 1.1.1.2 ! root 177: LOG_DEBUG1(("autovector %d", avno)); 1.1 root 178: if (curlevel < avno || avno == 7) { 1.1.1.2 ! root 179: if (regs.stop) { ! 180: LOG_DEBUG1(("stop finished")); ! 181: /* autovector whilst in a STOP instruction */ ! 182: reg68k_pc+= 4; ! 183: regs.stop = 0; ! 184: } 1.1 root 185: if (!reg68k_sr.sr_struct.s) { 186: regs.regs[15]^= regs.sp; /* swap A7 and SP */ 187: regs.sp^= regs.regs[15]; 188: regs.regs[15]^= regs.sp; 189: reg68k_sr.sr_struct.s = 1; 190: } 191: regs.regs[15]-=4; 192: storelong(regs.regs[15], reg68k_pc); 193: regs.regs[15]-=2; 194: storeword(regs.regs[15], reg68k_sr.sr_int); 195: reg68k_sr.sr_struct.t = 0; 196: reg68k_sr.sr_int&= ~0x0700; 197: reg68k_sr.sr_int|= avno << 8; 198: tmpaddr = reg68k_pc; 199: reg68k_pc = fetchlong((V_AUTO+avno-1)*4); 200: LOG_DEBUG1(("AUTOVECTOR %d: %X -> %X", avno, tmpaddr, reg68k_pc)); 1.1.1.2 ! root 201: regs.pending = 0; ! 202: } else { ! 203: LOG_DEBUG1(("%08X autovector %d pending", reg68k_pc, avno)); ! 204: regs.pending = avno; 1.1 root 205: } 206: } 207: 1.1.1.2 ! root 208: /*** reg68k_internal_vector - go to vector - this call assumes global ! 209: registers are already setup ***/ ! 210: ! 211: void reg68k_internal_vector(int vno, uint32 oldpc) 1.1 root 212: { 213: LOG_DEBUG1(("Vector %d called from %8x!", vno, regs.pc)); 214: if (!reg68k_sr.sr_struct.s) { 215: regs.regs[15]^= regs.sp; /* swap A7 and SP */ 216: regs.sp^= regs.regs[15]; 217: regs.regs[15]^= regs.sp; 218: reg68k_sr.sr_struct.s = 1; 219: } 220: regs.regs[15]-=4; 221: storelong(regs.regs[15], oldpc); 222: regs.regs[15]-=2; 223: storeword(regs.regs[15], reg68k_sr.sr_int); 224: reg68k_pc = fetchlong(vno*4); 225: LOG_DEBUG1(("VECTOR %d: %X -> %X\n", vno, oldpc, reg68k_pc)); 226: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.