Annotation of generator/extra/cpuz80.c.dual, revision 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.