Annotation of generator/extra/cpuz80.c.dual, revision 1.1.1.1

1.1       root        1: /*****************************************************************************/
                      2: /*     Generator - Sega Genesis emulation - (c) James Ponder 1997-1998       */
                      3: /*****************************************************************************/
                      4: /*                                                                           */
                      5: /* z80.c                                                                     */
                      6: /*                                                                           */
                      7: /*****************************************************************************/
                      8: 
                      9: #include <stdlib.h>
                     10: #include <stdio.h>
                     11: #include <string.h>
                     12: 
                     13: #include "generator.h"
                     14: #include "cpuz80.h"
                     15: #include "cpu68k.h"
                     16: #include "memz80.h"
                     17: #include "ui.h"
                     18: 
                     19: #define BIG_ENDIAN
                     20: 
                     21: #include "z80/mz80.h"
                     22: #include "z80/cmz80.h"
                     23: 
                     24: UINT8 cpuz80_read_actual(UINT32 addr, struct MemoryReadByte *me);
                     25: void cpuz80_write_actual(UINT32 addr, UINT8 data, struct MemoryWriteByte *me);
                     26: UINT16 cpuz80_ioread_actual(UINT16 addr, struct z80PortRead *me);
                     27: void cpuz80_iowrite_actual(UINT16 addr, UINT8 data, struct z80PortWrite *me);
                     28: 
                     29: UINT8 cpuz80c_read_actual(UINT32 addr, struct MemoryReadByte *me);
                     30: void cpuz80c_write_actual(UINT32 addr, UINT8 data, struct MemoryWriteByte *me);
                     31: UINT16 cpuz80c_ioread_actual(UINT16 addr, struct z80PortRead *me);
                     32: void cpuz80c_iowrite_actual(UINT16 addr, UINT8 data, struct z80PortWrite *me);
                     33: 
                     34: /*** variables externed ***/
                     35: 
                     36: uint8 *cpuz80_ram = NULL;
                     37: uint32 cpuz80_bank = 0;
                     38: unsigned int cpuz80_active = 0;
                     39: 
                     40: /*** global variables ***/
                     41: 
                     42: static unsigned int cpuz80_lastsync = 0;
                     43: static unsigned int cpuz80_resetting = 0;
                     44: static CONTEXTMZ80 cpuz80_z80;
                     45: static CONTEXTCMZ80 cpuz80c_z80;
                     46: 
                     47: struct {
                     48:   uint32 addr;
                     49:   uint8 data;
                     50: } reads[256];
                     51: 
                     52: uint32 readpointer_head = 0;
                     53: uint32 readpointer_tail = 0;
                     54: 
                     55: struct {
                     56:   uint32 addr;
                     57:   uint8 data;
                     58: } writes[256];
                     59: 
                     60: uint32 writepointer_head = 0;
                     61: uint32 writepointer_tail = 0;
                     62: 
                     63: static struct MemoryReadByte cpuz80_read[] = {
                     64:   { 0x0000, 0xFFFF, cpuz80_read_actual, NULL },
                     65:   { -1, -1, NULL, NULL }
                     66: };
                     67: 
                     68: static struct MemoryWriteByte cpuz80_write[] = {
                     69:   { 0x0000, 0xFFFF, cpuz80_write_actual, NULL },
                     70:   { -1, -1, NULL, NULL }
                     71: };
                     72: 
                     73: static struct z80PortRead cpuz80_ioread[] = {
                     74:   { 0x0000, 0x00FF, cpuz80_ioread_actual, NULL },
                     75:   { -1, -1, NULL, NULL }
                     76: };
                     77: 
                     78: static struct z80PortWrite cpuz80_iowrite[] = {
                     79:   { 0x0000, 0x00FF, cpuz80_iowrite_actual, NULL },
                     80:   { -1, -1, NULL, NULL }
                     81: };
                     82: 
                     83: 
                     84: 
                     85: static struct MemoryReadByte cpuz80c_read[] = {
                     86:   { 0x0000, 0xFFFF, cpuz80c_read_actual, NULL },
                     87:   { -1, -1, NULL, NULL }
                     88: };
                     89: 
                     90: static struct MemoryWriteByte cpuz80c_write[] = {
                     91:   { 0x0000, 0xFFFF, cpuz80c_write_actual, NULL },
                     92:   { -1, -1, NULL, NULL }
                     93: };
                     94: 
                     95: static struct z80PortRead cpuz80c_ioread[] = {
                     96:   { 0x0000, 0x00FF, cpuz80c_ioread_actual, NULL },
                     97:   { -1, -1, NULL, NULL }
                     98: };
                     99: 
                    100: static struct z80PortWrite cpuz80c_iowrite[] = {
                    101:   { 0x0000, 0x00FF, cpuz80c_iowrite_actual, NULL },
                    102:   { -1, -1, NULL, NULL }
                    103: };
                    104: 
                    105: 
                    106: UINT8 cpuz80_read_actual(UINT32 addr, struct MemoryReadByte *me)
                    107: {
                    108:   uint8 data;
                    109:   (void)me;
                    110:   if (((readpointer_head+1)%256) == readpointer_tail)
                    111:     ui_err("read overrun during REAL read to %08X (p=%d)",
                    112:           addr, readpointer_head);
                    113:   data = memz80_fetchbyte((uint32)addr);
                    114:   LOG_CRITICAL(("REAL read to %08X = %02X (p=%d)", addr, data,
                    115:                readpointer_head));
                    116:   reads[readpointer_head].addr = addr;
                    117:   reads[readpointer_head].data = data;
                    118:   if (++readpointer_head >= 256)
                    119:     readpointer_head = 0;
                    120:   return data;
                    121: }
                    122: 
                    123: void cpuz80_write_actual(UINT32 addr, UINT8 data, struct MemoryWriteByte *me)
                    124: {
                    125:   (void)me;
                    126:   LOG_CRITICAL(("REAL write to %08X of %02X (p=%d)", addr, data,
                    127:                writepointer_head));
                    128:   if (((writepointer_head+1)%256) == writepointer_tail)
                    129:     ui_err("write overrun");
                    130:   writes[writepointer_head].addr = addr;
                    131:   writes[writepointer_head].data = data;
                    132:   if (++writepointer_head >= 256)
                    133:     writepointer_head = 0;
                    134:   memz80_storebyte((uint32)addr, (uint8)data);
                    135: }
                    136: 
                    137: UINT16 cpuz80_ioread_actual(UINT16 addr, struct z80PortRead *me)
                    138: {
                    139:   (void)me;
                    140:   return cpuz80_portread((uint16)addr);
                    141: }
                    142: 
                    143: void cpuz80_iowrite_actual(UINT16 addr, UINT8 data, struct z80PortWrite *me)
                    144: {
                    145:   (void)me;
                    146:   cpuz80_portwrite((uint16)addr, (uint8)data);
                    147: }
                    148: 
                    149: 
                    150: 
                    151: 
                    152: UINT8 cpuz80c_read_actual(UINT32 addr, struct MemoryReadByte *me)
                    153: {
                    154:   uint8 data;
                    155:   (void)me;
                    156:   if (readpointer_tail == readpointer_head)
                    157:     ui_err("read underrun");
                    158:   if (reads[readpointer_tail].addr != addr)
                    159:     ui_err("read address mismatch");
                    160:   data = reads[readpointer_tail].data;
                    161:   LOG_CRITICAL(("FAKE read to %08X = %02X", addr, data));
                    162:   readpointer_tail = (readpointer_tail+1) % 256;
                    163:   return data;
                    164: }
                    165: 
                    166: void cpuz80c_write_actual(UINT32 addr, UINT8 data, struct MemoryWriteByte *me)
                    167: {
                    168:   (void)me;
                    169:   LOG_CRITICAL(("FAKE write to %08X of %02X (p=%d)", addr, data,
                    170:                writepointer_tail));
                    171:   if (writepointer_tail == writepointer_head) {
                    172:     LOG_CRITICAL(("write underrun"));
                    173:     return;
                    174:   }
                    175:   if (writes[writepointer_tail].addr != addr &&
                    176:       writes[writepointer_tail].data != data)
                    177:     ui_err("write address AND data mismatch");
                    178:   if (writes[writepointer_tail].addr != addr)
                    179:     ui_err("write address mismatch");
                    180:   if (writes[writepointer_tail].data != data)
                    181:     ui_err("write data mismatch");
                    182:   writepointer_tail = (writepointer_tail+1) % 256;
                    183: }
                    184: 
                    185: UINT16 cpuz80c_ioread_actual(UINT16 addr, struct z80PortRead *me)
                    186: {
                    187:   (void)me;
                    188:   ui_err("ioread");
                    189:   return 0;
                    190: }
                    191: 
                    192: void cpuz80c_iowrite_actual(UINT16 addr, UINT8 data, struct z80PortWrite *me)
                    193: {
                    194:   (void)me;
                    195:   ui_err("iowrite");
                    196: }
                    197: 
                    198: 
                    199: 
                    200: /*** cpuz80_init - initialise this sub-unit ***/
                    201: 
                    202: int cpuz80_init(void)
                    203: {
                    204:   cmz80init();
                    205:   cpuz80_reset();
                    206:   return 0;
                    207: }
                    208: 
                    209: /*** cpuz80_reset - reset z80 sub-unit ***/
                    210: 
                    211: void cpuz80_reset(void)
                    212: {
                    213:   if (!cpuz80_ram) {
                    214:     if ((cpuz80_ram = malloc(LEN_SRAM)) == NULL) {
                    215:       fprintf(stderr, "Out of memory\n");
                    216:       exit(1);
                    217:     }
                    218:   }
                    219:   memset(cpuz80_ram, 0, LEN_SRAM);
                    220:   cpuz80_resetcpu();
                    221:   cpuz80_bank = 0;
                    222:   cpuz80_active = 0;
                    223:   cpuz80_lastsync = 0;
                    224:   cpuz80_resetting = 0;
                    225:   /* mz80GetContext(&cpuz80_z80); */
                    226:   memset(&cpuz80_z80, 0, sizeof(cpuz80_z80));
                    227:   cpuz80_z80.z80Base = cpuz80_ram;
                    228:   cpuz80_z80.z80MemRead = cpuz80_read;
                    229:   cpuz80_z80.z80MemWrite = cpuz80_write;
                    230:   cpuz80_z80.z80IoRead = cpuz80_ioread;
                    231:   cpuz80_z80.z80IoWrite = cpuz80_iowrite;
                    232:   mz80SetContext(&cpuz80_z80);
                    233:   mz80reset();
                    234:   ;
                    235:   memset(&cpuz80c_z80, 0, sizeof(cpuz80c_z80));
                    236:   cpuz80c_z80.z80Base = cpuz80_ram;
                    237:   cpuz80c_z80.z80MemRead = cpuz80c_read;
                    238:   cpuz80c_z80.z80MemWrite = cpuz80c_write;
                    239:   cpuz80c_z80.z80IoRead = cpuz80c_ioread;
                    240:   cpuz80c_z80.z80IoWrite = cpuz80c_iowrite;
                    241:   cmz80SetContext(&cpuz80c_z80);
                    242:   cmz80reset();
                    243: }
                    244: 
                    245: /*** cpuz80_resetcpu - reset z80 cpu ***/
                    246: 
                    247: void cpuz80_resetcpu(void)
                    248: {
                    249:   mz80reset();
                    250:   cmz80reset();
                    251:   cpuz80_resetting = 1; /* suspends execution */
                    252: }
                    253: 
                    254: /*** cpuz80_unresetcpu - unreset z80 cpu ***/
                    255: 
                    256: void cpuz80_unresetcpu(void)
                    257: {
                    258:   cpuz80_resetting = 0; /* un-suspends execution */
                    259: }
                    260: 
                    261: /*** cpuz80_bankwrite - data is being written to latch ***/
                    262: 
                    263: void cpuz80_bankwrite(uint8 data)
                    264: {
                    265:   cpuz80_bank  = (((cpuz80_bank >> 1) | ((data & 1) <<23)) & 0xff8000);
                    266:   /*
                    267:   if (gen_debug)
                    268:     printf("BANK WRITE: %d --> %08X\n", data, cpuz80_bank);
                    269:   */
                    270: }
                    271: 
                    272: /*** cpuz80_stop - stop the processor ***/
                    273: 
                    274: void cpuz80_stop(void)
                    275: {
                    276:   cpuz80_sync();
                    277:   cpuz80_active = 0;
                    278: }
                    279: 
                    280: /*** cpuz80_start - start the processor ***/
                    281: 
                    282: void cpuz80_start(void)
                    283: {
                    284:   cpuz80_sync();
                    285:   cpuz80_active = 1;
                    286: }
                    287: 
                    288: /*** cpuz80_endfield - reset counters ***/
                    289: 
                    290: void cpuz80_endfield(void)
                    291: {
                    292:   cpuz80_lastsync = 0;
                    293: }
                    294: 
                    295: /*** cpuz80_sync - synchronise ***/
                    296: 
                    297: void cpuz80_sync(void)
                    298: {
                    299:   int cpu68k_wanted = cpu68k_clocks - cpuz80_lastsync;
                    300:   int wanted = (cpu68k_wanted<0?0:cpu68k_wanted)*7/16;
                    301:   int achieved, achieved_c;
                    302:   uint32 oldpc;
                    303: 
                    304:   if (cpuz80_active && !cpuz80_resetting) {
                    305:     /* ui_log(LOG_USER, "executing %d z80 clocks @ %X", wanted,
                    306:        cpuz80_z80.z80pc); */
                    307:     printf("context: s=%08X c=%08X\n", &cpuz80_z80, &cpuz80c_z80);
                    308:     printf("pc invalid: %08X %08X\n", &cpuz80_z80.z80pc, &cpuz80c_z80.z80pc);
                    309:     mz80GetContext(&cpuz80_z80);
                    310:     cmz80GetContext(&cpuz80c_z80);
                    311:     printf("pc start: %08X %08X\n", cpuz80_z80.z80pc, cpuz80c_z80.z80pc);
                    312:     printf("opcodes: %02x(%02x) %02x(%02x)\n", cpuz80_ram[cpuz80_z80.z80pc],
                    313:           cpuz80_ram[cpuz80_z80.z80pc+1],
                    314:           cpuz80_ram[cpuz80c_z80.z80pc],
                    315:           cpuz80_ram[cpuz80c_z80.z80pc+1]);
                    316:     if (cpuz80_z80.z80pc != cpuz80c_z80.z80pc) {
                    317:       ui_err("sPC = %08X / cPC = %08X mismatch on entry",
                    318:             cpuz80_z80.z80pc, cpuz80c_z80.z80pc);
                    319:     }
                    320:     printf("Pending ints: s = %X c = %X\n",
                    321:           cpuz80_z80.z80intPending, cpuz80c_z80.z80intPending);
                    322:     printf("DE on entry: s=%X c=%X\n", cpuz80_z80.z80de.de,
                    323:             cpuz80c_z80.z80de.de);
                    324:     oldpc = cpuz80_z80.z80pc;
                    325:     printf("Attempting to execute %d clocks...\n", wanted);
                    326:     mz80exec(wanted); /* wanted */
                    327:     cmz80exec(wanted);
                    328:     achieved = mz80GetElapsedTicks(1);
                    329:     achieved_c = cmz80GetElapsedTicks(1);
                    330:     mz80GetContext(&cpuz80_z80);
                    331:     cmz80GetContext(&cpuz80c_z80);
                    332:     LOG_CRITICAL(("achieved s=%d c=%d", achieved, achieved_c));
                    333:     printf("pc end: %08X %08X\n", cpuz80_z80.z80pc, cpuz80c_z80.z80pc);
                    334:     printf("Exit pending ints: s = %X c = %X\n",
                    335:           cpuz80_z80.z80intPending, cpuz80c_z80.z80intPending);
                    336:     if (cpuz80_z80.z80af.af != cpuz80c_z80.z80af.af)
                    337:       ui_err("AF differs: s=%X c=%X", cpuz80_z80.z80af.af,
                    338:             cpuz80c_z80.z80af.af);
                    339:     if (cpuz80_z80.z80bc.bc != cpuz80c_z80.z80bc.bc)
                    340:       ui_err("BC differs: s=%X c=%X", cpuz80_z80.z80bc.bc,
                    341:             cpuz80c_z80.z80bc.bc);
                    342:     if (cpuz80_z80.z80de.de != cpuz80c_z80.z80de.de)
                    343:       ui_err("DE differs: s=%X c=%X", cpuz80_z80.z80de.de,
                    344:             cpuz80c_z80.z80de.de);
                    345:     if (cpuz80_z80.z80hl.hl != cpuz80c_z80.z80hl.hl)
                    346:       ui_err("HL differs: s=%X c=%X", cpuz80_z80.z80hl.hl,
                    347:             cpuz80c_z80.z80hl.hl);
                    348:     if (cpuz80_z80.z80ix.ix != cpuz80c_z80.z80ix.ix)
                    349:       ui_err("IX differs: s=%X c=%X", cpuz80_z80.z80ix.ix,
                    350:             cpuz80c_z80.z80ix.ix);
                    351:     if (cpuz80_z80.z80iy.iy != cpuz80c_z80.z80iy.iy)
                    352:       ui_err("IY differs: s=%X c=%X", cpuz80_z80.z80iy.iy,
                    353:             cpuz80c_z80.z80iy.iy);
                    354:     if (cpuz80_z80.z80pc != cpuz80c_z80.z80pc) {
                    355:       ui_err("sPC = %08X / cPC = %08X mismatch on exit",
                    356:             cpuz80_z80.z80pc, cpuz80c_z80.z80pc);
                    357:     }
                    358:     if (cpuz80_z80.z80intPending != cpuz80c_z80.z80intPending) {
                    359:       /*
                    360:       ui_err("sIntPending = %X / cIntPending = %X\n",
                    361:             cpuz80_z80.z80intPending, cpuz80c_z80.z80intPending);
                    362:       */
                    363:     }
                    364:     if (achieved != achieved_c) {
                    365:       LOG_CRITICAL(("oldpc=%08X newpc=%08X", oldpc, cpuz80_z80.z80pc));
                    366:       ui_err("achieved clocks mismatch: s=%d c=%d", achieved, achieved_c);
                    367:     }
                    368:     /* this if/else statement below, I'm not entirely sure this is a good
                    369:        idea, perhaps just doing cpuz80_lastsync = cpu68k_clocks; always is
                    370:        better? hmm. */
                    371:     if (achieved > wanted) {
                    372:       cpuz80_lastsync = cpu68k_clocks;
                    373:     } else {
                    374:       cpuz80_lastsync = cpuz80_lastsync + achieved*16/7;
                    375:     }
                    376:   } else {
                    377:     cpuz80_lastsync = cpu68k_clocks;
                    378:   }
                    379: }
                    380: 
                    381: /*** cpuz80_interrupt - cause an interrupt on the z80 */
                    382: 
                    383: void cpuz80_interrupt(void)
                    384: {
                    385:   if (!cpuz80_resetting) {
                    386:     LOG_CRITICAL(("interrupt!!!!!!!!!!!!!"));
                    387:     mz80int(0);
                    388:     cmz80int(0);
                    389:   }
                    390: }
                    391: 
                    392: /*** cpuz80_portread - port read from z80 */
                    393: 
                    394: uint8 cpuz80_portread(uint8 port)
                    395: {
                    396:   LOG_VERBOSE(("[Z80] Port read to %X", port));
                    397:   return 0;
                    398: }
                    399: 
                    400: /*** cpuz80_portwrite - z80 write to port */
                    401: 
                    402: void cpuz80_portwrite(uint8 port, uint8 value)
                    403: {
                    404:   LOG_VERBOSE(("[Z80] Port write to %X of %X", port, value));
                    405: }

unix.superglobalmegacorp.com

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