Annotation of generator/main/reg68k.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.