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

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

unix.superglobalmegacorp.com

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