/* Multi-Z80 32 Bit emulator */ /* Copyright 1996, 1997, 1998, 1999, 2000 Neil Bradley, All rights reserved * * License agreement: * * (MZ80 Refers to both the assembly and C code emitted by makeZ80.c and * makeZ80.c itself) * * MZ80 May be distributed in unmodified form to any medium. * * MZ80 May not be sold, or sold as a part of a commercial package without * the express written permission of Neil Bradley (neil@synthcom.com). This * includes shareware. * * Modified versions of MZ80 may not be publicly redistributed without author * approval (neil@synthcom.com). This includes distributing via a publicly * accessible LAN. You may make your own source modifications and distribute * MZ80 in source or object form, but if you make modifications to MZ80 * then it should be noted in the top as a comment in makeZ80.c. * * MZ80 Licensing for commercial applications is available. Please email * neil@synthcom.com for details. * * Synthcom Systems, Inc, and Neil Bradley will not be held responsible for * any damage done by the use of MZ80. It is purely "as-is". * * If you use MZ80 in a freeware application, credit in the following text: * * "Multi-Z80 CPU emulator by Neil Bradley (neil@synthcom.com)" * * must accompany the freeware application within the application itself or * in the documentation. * * Legal stuff aside: * * If you find problems with MZ80, please email the author so they can get * resolved. If you find a bug and fix it, please also email the author so * that those bug fixes can be propogated to the installed base of MZ80 * users. If you find performance improvements or problems with MZ80, please * email the author with your changes/suggestions and they will be rolled in * with subsequent releases of MZ80. * * The whole idea of this emulator is to have the fastest available 32 bit * Multi-Z80 emulator for the PC, giving maximum performance. * */ /* DGen/SDL modifications for compilation issues and bugfixes: 2011-08-28 - Rename VERSION to MZ80_VERSION. - Some fprintf() calls had too many arguments. - Use C99 uint*_t/int*_t for portability. 2011-09-11 - Replace assert(0) occurences with abort() as these checks shouldn't go away when defining NDEBUG. - Add default case to switch statement in IRHandler(). - Append -dgen to version number. 2011-10-08 - Fix segfault on reset in the C version. 2014-06-22 - Remove malloc() calls from mz80init() as they cannot be checked nor freed. */ #include #include #include #include #include #include #define MZ80_VERSION "3.4-dgen" #define TRUE 0xff #define FALSE 0x0 #define INVALID 0xff #define UINT32 uint32_t #define UINT8 uint8_t #define INT8 char #define TIMING_REGULAR 0x00 #define TIMING_XXCB 0x01 #define TIMING_CB 0xcb #define TIMING_DDFD 0xdd #define TIMING_ED 0xed #define TIMING_EXCEPT 0x02 FILE *fp = NULL; char string[150]; char cpubasename[150]; static char mz80Index[50]; static char mz80IndexHalfHigh[50]; static char mz80IndexHalfLow[50]; char majorOp[50]; char procname[150]; UINT32 dwGlobalLabel = 0; enum { MZ80_ASSEMBLY_X86, MZ80_C, MZ80_UNKNOWN }; UINT8 bPlain = FALSE; UINT8 bNoTiming = FALSE; UINT8 bUseStack = 0; UINT8 bCurrentMode = TIMING_REGULAR; // Current timing mode UINT8 b16BitIo = FALSE; UINT8 bThroughCallHandler = FALSE; UINT8 bOS2 = FALSE; UINT8 bWhat = MZ80_UNKNOWN; void ProcBegin(UINT32 dwOpcode); INT8 *pbLocalReg[8] = { "ch", "cl", "dh", "dl", "bh", "bl", "dl", "al" }; INT8 *pbLocalRegC[8] = { "cpu.z80B", "cpu.z80C", "cpu.z80D", "cpu.z80E", "cpu.z80H", "cpu.z80L", "barf", "cpu.z80A" }; INT8 *pbPushReg[8] = { "cl", "ch", "byte [_z80de]", "byte [_z80de + 1]", "bl", "bh", "ah", "al" }; INT8 *pbFlags[8] = { "nz", "z", "nc", "c", "po", "pe", "ns", "s" }; INT8 *pbRegPairC[] = { "cpu.z80BC", "cpu.z80DE", "cpu.z80HL", "cpu.z80sp" }; INT8 *pbFlagsC[8] = { "(!(cpu.z80F & Z80_FLAG_ZERO))", "(cpu.z80F & Z80_FLAG_ZERO)", "(!(cpu.z80F & Z80_FLAG_CARRY))", "(cpu.z80F & Z80_FLAG_CARRY)", "(!(cpu.z80F & Z80_FLAG_OVERFLOW_PARITY))", "(cpu.z80F & Z80_FLAG_OVERFLOW_PARITY)", "(!(cpu.z80F & Z80_FLAG_SIGN))", "(cpu.z80F & Z80_FLAG_SIGN)" }; INT8 *pbMathReg[8] = { "ch", "cl", "byte [_z80de + 1]", "byte [_z80de]", "bh", "bl", "INVALID", "al" }; INT8 *pbMathRegC[8] = { "cpu.z80B", "cpu.z80C", "cpu.z80D", "cpu.z80E", "cpu.z80H", "cpu.z80L", "bTemp", "cpu.z80A" }; INT8 *pbRegPairs[4] = { "cx", // BC "word [_z80de]", // DE "bx", // HL "word [_z80sp]" // SP }; INT8 *pbRegPairsC[4] = { "cpu.z80BC", // BC "cpu.z80DE", // DE "cpu.z80HL", // HL "cpu.z80sp" // SP }; INT8 *pbPopRegPairs[4] = { "cx", // BC "word [_z80de]", // DE "bx", // HL "ax" // SP }; INT8 *pbPopRegPairC[4] = { "cpu.z80BC", "cpu.z80DE", "cpu.z80HL", "cpu.z80AF" }; INT8 *pbIndexedRegPairs[4] = { "cx", // BC "word [_z80de]", // DE "di", // IX/IY "word [_z80sp]" // SP }; // Timing tables UINT8 bTimingRegular[0x100] = { 0x04, 0x0a, 0x07, 0x06, 0x04, 0x04, 0x07, 0x04, 0x04, 0x0b, 0x07, 0x06, 0x04, 0x04, 0x07, 0x04, 0x08, 0x0a, 0x07, 0x06, 0x04, 0x04, 0x07, 0x04, 0x0c, 0x0b, 0x07, 0x06, 0x04, 0x04, 0x07, 0x04, 0x07, 0x0a, 0x10, 0x06, 0x04, 0x04, 0x07, 0x04, 0x07, 0x0b, 0x10, 0x06, 0x04, 0x04, 0x07, 0x04, 0x07, 0x0a, 0x0d, 0x06, 0x0b, 0x0b, 0x0a, 0x04, 0x07, 0x0b, 0x0d, 0x06, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x05, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x07, 0x0b, 0x05, 0x0a, 0x0a, 0x00, 0x0a, 0x11, 0x07, 0x0b, 0x05, 0x0a, 0x0a, 0x0b, 0x0a, 0x0b, 0x07, 0x0b, 0x05, 0x04, 0x0a, 0x0b, 0x0a, 0x00, 0x07, 0x0b, 0x05, 0x0a, 0x0a, 0x13, 0x0a, 0x0b, 0x07, 0x0b, 0x05, 0x04, 0x0a, 0x04, 0x0a, 0x00, 0x07, 0x0b, 0x05, 0x0a, 0x0a, 0x04, 0x0a, 0x0b, 0x07, 0x0b, 0x05, 0x06, 0x0a, 0x04, 0x0a, 0x00, 0x07, 0x0b }; UINT8 bTimingCB[0x100] = { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0f, 0x08 }; UINT8 bTimingXXCB[0x100] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00 }; UINT8 bTimingDDFD[0x100] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x14, 0x0a, 0x09, 0x09, 0x09, 0x00, 0x00, 0x0f, 0x14, 0x0a, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x17, 0x13, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x13, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x13, 0x09, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x17, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; UINT8 bTimingED[0x100] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x0e, 0x08, 0x09, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x0e, 0x08, 0x09, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x08, 0x08, 0x09, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x08, 0x08, 0x09, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x08, 0x08, 0x12, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x08, 0x08, 0x12, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x08, 0x08, 0x00, 0x0c, 0x0c, 0x0f, 0x14, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; void EDHandler(UINT32 dwOpcode); void DDHandler(UINT32 dwOpcode); void FDHandler(UINT32 dwOpcode); void CBHandler(UINT32 dwOpcode); void PushPopOperations(UINT32 dwOpcode); void AddRegpairOperations(UINT32 dwOpcode); void CallHandler(UINT32 dwOpcode); void MiscHandler(UINT32 dwOpcode); void IMHandler(UINT32 dwOpcode); void IRHandler(UINT32 dwOpcode); void LdRegPairImmediate(UINT32 dwOpcode); void LoadImmediate(UINT32 dwOpcode); void LdRegpairPtrByte(UINT32 dwOpcode); void MathOperation(UINT32 dwOpcode); void RegIntoMemory(UINT32 dwOpcode); void JpHandler(UINT32 dwOpcode); void LdRegImmediate(UINT32 dwOpcode); void IncRegister(UINT32 dwOpcode); void DecRegister(UINT32 dwOpcode); void IncDecRegpair(UINT32 dwOpcode); void LdRegReg(UINT32 dwOpcode); void MathOperationDirect(UINT32 dwOpcode); void JrHandler(UINT32 dwOpcode); void RetHandler(UINT32 dwOpcode); void RestartHandler(UINT32 dwOpcode); void ToRegFromHl(UINT32); void RraRlaHandler(UINT32); void LdByteRegpair(UINT32); void IncDecHLPtr(UINT32 dwOpcode); void InOutHandler(UINT32 dwOpcode); void RLCRRCRLRRSLASRASRLHandler(UINT32 dwOpcode); void BITHandler(UINT32 dwOpcode); void RESSETHandler(UINT32 dwOpcode); void PushPopOperationsIndexed(UINT32 dwOpcode); void LDILDRLDIRLDDRHandler(UINT32); void LdRegpair(UINT32 dwOpcode); void ExtendedRegIntoMemory(UINT32 dwOpcode); void NegHandler(UINT32 dwOpcode); void ExtendedInHandler(UINT32 dwOpcode); void ExtendedOutHandler(UINT32 dwOpcode); void RetIRetNHandler(UINT32 dwOcode); void AdcSbcRegpair(UINT32 dwOpcode); void CPICPDCPIRCPDRHandler(UINT32 dwOpcode); void RRDRLDHandler(UINT32 dwOpcode); void UndocRegToIndex(UINT32 dwOpcode); void UndocIndexToReg(UINT32 dwOpcode); void MathOperationIndexed(UINT32 dwOpcode); void IncDecIndexed(UINT32 dwOpcode); void DDFDCBHandler(UINT32 dwOpcode); void JPIXIYHandler(UINT32 dwOpcode); void AddIndexHandler(UINT32 dwOpcode); void SPToIndex(UINT32 dwOpcode); void LdByteToIndex(UINT32 dwOpcode); void LdRegIndexOffset(UINT32 dwOpcode); void IncDecIndexReg(UINT32 dwOpcode); void ExIndexed(UINT32 dwOpcode); void UndocIncDecIndexReg(UINT32 dwOpcode); void UndocLoadHalfIndexReg(UINT32 dwOpcode); void UndocMathIndex(UINT32 dwOpcode); void ddcbBitWise(UINT32 dwOpcode); void LdIndexPtrReg(UINT32 dwOpcode); void StoreIndexReg(UINT32 dwOpcode); void LoadIndexReg(UINT32 dwOpcode); void OTIROTDROUTIOUTDHandler(UINT32 dwOpcode); void INIRINDRINIINDHandler(UINT32 dwOpcode); struct sOp { UINT32 bOpCode; void (*Emitter)(UINT32); }; struct sOp StandardOps[] = { {0xd3, InOutHandler}, // V {0xdb, InOutHandler}, // V {0x0a, LdByteRegpair}, // V {0x1a, LdByteRegpair}, // V {0x17, RraRlaHandler}, // V {0x1f, RraRlaHandler}, // V {0x05, DecRegister}, // V {0x0d, DecRegister}, // V {0x15, DecRegister}, // V {0x1d, DecRegister}, // V {0x25, DecRegister}, // V {0x2d, DecRegister}, // V {0x3d, DecRegister}, // V {0x04, IncRegister}, // V {0x0c, IncRegister}, // V {0x14, IncRegister}, // V {0x1c, IncRegister}, // V {0x24, IncRegister}, // V {0x2c, IncRegister}, // V {0x3c, IncRegister}, // V {0x32, RegIntoMemory}, // V {0x22, RegIntoMemory}, // V {0xc3, JpHandler}, // V {0xc2, JpHandler}, // V {0xca, JpHandler}, // V {0xd2, JpHandler}, // V {0xda, JpHandler}, // V {0xe2, JpHandler}, // V {0xea, JpHandler}, // V {0xf2, JpHandler}, // V {0xfa, JpHandler}, // V {0x06, LdRegImmediate}, // V {0x0e, LdRegImmediate}, // V {0x16, LdRegImmediate}, // V {0x1e, LdRegImmediate}, // V {0x26, LdRegImmediate}, // V {0x2e, LdRegImmediate}, // V {0x3e, LdRegImmediate}, // V {0x0b, IncDecRegpair}, // V {0x1b, IncDecRegpair}, // V {0x2b, IncDecRegpair}, // V {0x3b, IncDecRegpair}, // V {0x03, IncDecRegpair}, // V {0x13, IncDecRegpair}, // V {0x23, IncDecRegpair}, // V {0x33, IncDecRegpair}, // V {0x34, IncDecHLPtr}, // V {0x35, IncDecHLPtr}, // V {0xcb, CBHandler}, {0xdd, DDHandler}, {0xed, EDHandler}, {0xfd, FDHandler}, {0x01, LdRegPairImmediate}, // V {0x11, LdRegPairImmediate}, // V {0x21, LdRegPairImmediate}, // V {0x31, LdRegPairImmediate}, // V {0xe3, MiscHandler}, // V {0x2a, MiscHandler}, // V {0xfb, MiscHandler}, // V {0xf9, MiscHandler}, // V {0xd9, MiscHandler}, // V {0x76, MiscHandler}, // V {0x3f, MiscHandler}, // V {0x37, MiscHandler}, // V {0x27, MiscHandler}, // V {0x07, MiscHandler}, // V {0x08, MiscHandler}, // V {0x00, MiscHandler}, // V {0xe9, MiscHandler}, // V {0xeb, MiscHandler}, // V {0xf3, MiscHandler}, // V {0x3a, MiscHandler}, // V {0x10, MiscHandler}, // V {0x2f, MiscHandler}, // V {0x0f, MiscHandler}, // V {0x02, LdRegpairPtrByte}, // V {0x12, LdRegpairPtrByte}, // V {0x70, LdRegpairPtrByte}, // V {0x71, LdRegpairPtrByte}, // V {0x72, LdRegpairPtrByte}, // V {0x73, LdRegpairPtrByte}, // V {0x74, LdRegpairPtrByte}, // V {0x75, LdRegpairPtrByte}, // V {0x77, LdRegpairPtrByte}, // V {0x36, LdRegpairPtrByte}, // V {0x80, MathOperation}, // V {0x81, MathOperation}, // V {0x82, MathOperation}, // V {0x83, MathOperation}, // V {0x84, MathOperation}, // V {0x85, MathOperation}, // V {0x86, MathOperation}, // V {0x87, MathOperation}, // V {0x88, MathOperation}, // V {0x89, MathOperation}, // V {0x8a, MathOperation}, // V {0x8b, MathOperation}, // V {0x8c, MathOperation}, // V {0x8d, MathOperation}, // V {0x8e, MathOperation}, // V {0x8f, MathOperation}, // V {0x90, MathOperation}, // V {0x91, MathOperation}, // V {0x92, MathOperation}, // V {0x93, MathOperation}, // V {0x94, MathOperation}, // V {0x95, MathOperation}, // V {0x96, MathOperation}, // V {0x97, MathOperation}, // V {0x98, MathOperation}, // V {0x99, MathOperation}, // V {0x9a, MathOperation}, // V {0x9b, MathOperation}, // V {0x9c, MathOperation}, // V {0x9d, MathOperation}, // V {0x9e, MathOperation}, // V {0x9f, MathOperation}, // V {0xa0, MathOperation}, // V {0xa1, MathOperation}, // V {0xa2, MathOperation}, // V {0xa3, MathOperation}, // V {0xa4, MathOperation}, // V {0xa5, MathOperation}, // V {0xa6, MathOperation}, // V {0xa7, MathOperation}, // V {0xa8, MathOperation}, // V {0xa9, MathOperation}, // V {0xaa, MathOperation}, // V {0xab, MathOperation}, // V {0xac, MathOperation}, // V {0xad, MathOperation}, // V {0xae, MathOperation}, // V {0xaf, MathOperation}, // V {0xb0, MathOperation}, // V {0xb1, MathOperation}, // V {0xb2, MathOperation}, // V {0xb3, MathOperation}, // V {0xb4, MathOperation}, // V {0xb5, MathOperation}, // V {0xb6, MathOperation}, // V {0xb7, MathOperation}, // V {0xb8, MathOperation}, // V {0xb9, MathOperation}, // V {0xba, MathOperation}, // V {0xbb, MathOperation}, // V {0xbc, MathOperation}, // V {0xbd, MathOperation}, // V {0xbe, MathOperation}, // V {0xbf, MathOperation}, // V {0x40, LdRegReg}, // V {0x41, LdRegReg}, // V {0x42, LdRegReg}, // V {0x43, LdRegReg}, // V {0x44, LdRegReg}, // V {0x45, LdRegReg}, // V {0x47, LdRegReg}, // V {0x48, LdRegReg}, // V {0x49, LdRegReg}, // V {0x4a, LdRegReg}, // V {0x4b, LdRegReg}, // V {0x4c, LdRegReg}, // V {0x4d, LdRegReg}, // V {0x4f, LdRegReg}, // V {0x50, LdRegReg}, // V {0x51, LdRegReg}, // V {0x52, LdRegReg}, // V {0x53, LdRegReg}, // V {0x54, LdRegReg}, // V {0x55, LdRegReg}, // V {0x57, LdRegReg}, // V {0x58, LdRegReg}, // V {0x59, LdRegReg}, // V {0x5a, LdRegReg}, // V {0x5b, LdRegReg}, // V {0x5c, LdRegReg}, // V {0x5d, LdRegReg}, // V {0x5f, LdRegReg}, // V {0x60, LdRegReg}, // V {0x61, LdRegReg}, // V {0x62, LdRegReg}, // V {0x63, LdRegReg}, // V {0x64, LdRegReg}, // V {0x65, LdRegReg}, // V {0x67, LdRegReg}, // V {0x68, LdRegReg}, // V {0x69, LdRegReg}, // V {0x6a, LdRegReg}, // V {0x6b, LdRegReg}, // V {0x6c, LdRegReg}, // V {0x6d, LdRegReg}, // V {0x6f, LdRegReg}, // V {0x78, LdRegReg}, // V {0x79, LdRegReg}, // V {0x7a, LdRegReg}, // V {0x7b, LdRegReg}, // V {0x7c, LdRegReg}, // V {0x7d, LdRegReg}, // V {0x7f, LdRegReg}, // V {0xc6, MathOperationDirect}, // V {0xce, MathOperationDirect}, // V {0xd6, MathOperationDirect}, // V {0xde, MathOperationDirect}, // V {0xe6, MathOperationDirect}, // V {0xee, MathOperationDirect}, // V {0xf6, MathOperationDirect}, // V {0xfe, MathOperationDirect}, // V {0x18, JrHandler}, // V {0x20, JrHandler}, // V {0x28, JrHandler}, // V {0x30, JrHandler}, // V {0x38, JrHandler}, {0xc4, CallHandler}, // V {0xcc, CallHandler}, // V {0xcd, CallHandler}, // V {0xd4, CallHandler}, // V {0xdc, CallHandler}, // V {0xe4, CallHandler}, // V {0xec, CallHandler}, // V {0xf4, CallHandler}, // V {0xfc, CallHandler}, // V {0xc9, RetHandler}, // V {0xc0, RetHandler}, // V {0xc8, RetHandler}, // V {0xd0, RetHandler}, // V {0xd8, RetHandler}, // V {0xe0, RetHandler}, // V {0xe8, RetHandler}, // V {0xf0, RetHandler}, // V {0xf8, RetHandler}, // V {0xc7, RestartHandler}, // V {0xcf, RestartHandler}, // V {0xd7, RestartHandler}, // V {0xdf, RestartHandler}, // V {0xe7, RestartHandler}, // V {0xef, RestartHandler}, // V {0xf7, RestartHandler}, // V {0xff, RestartHandler}, // V {0x46, ToRegFromHl}, // V {0x4e, ToRegFromHl}, // V {0x56, ToRegFromHl}, // V {0x5e, ToRegFromHl}, // V {0x66, ToRegFromHl}, // V {0x6e, ToRegFromHl}, // V {0x7e, ToRegFromHl}, {0x09, AddRegpairOperations}, // V {0x19, AddRegpairOperations}, // V {0x29, AddRegpairOperations}, // V {0x39, AddRegpairOperations}, // V {0xc5, PushPopOperations}, // V {0xd5, PushPopOperations}, // V {0xe5, PushPopOperations}, // V {0xf5, PushPopOperations}, // V {0xc1, PushPopOperations}, // V {0xd1, PushPopOperations}, // V {0xe1, PushPopOperations}, // V {0xf1, PushPopOperations}, // V // Terminator {0xffffffff, NULL} }; struct sOp CBOps[] = { {0x00, RLCRRCRLRRSLASRASRLHandler}, {0x01, RLCRRCRLRRSLASRASRLHandler}, {0x02, RLCRRCRLRRSLASRASRLHandler}, {0x03, RLCRRCRLRRSLASRASRLHandler}, {0x04, RLCRRCRLRRSLASRASRLHandler}, {0x05, RLCRRCRLRRSLASRASRLHandler}, {0x06, RLCRRCRLRRSLASRASRLHandler}, {0x07, RLCRRCRLRRSLASRASRLHandler}, {0x08, RLCRRCRLRRSLASRASRLHandler}, {0x09, RLCRRCRLRRSLASRASRLHandler}, {0x0a, RLCRRCRLRRSLASRASRLHandler}, {0x0b, RLCRRCRLRRSLASRASRLHandler}, {0x0c, RLCRRCRLRRSLASRASRLHandler}, {0x0d, RLCRRCRLRRSLASRASRLHandler}, {0x0e, RLCRRCRLRRSLASRASRLHandler}, {0x0f, RLCRRCRLRRSLASRASRLHandler}, {0x10, RLCRRCRLRRSLASRASRLHandler}, {0x11, RLCRRCRLRRSLASRASRLHandler}, {0x12, RLCRRCRLRRSLASRASRLHandler}, {0x13, RLCRRCRLRRSLASRASRLHandler}, {0x14, RLCRRCRLRRSLASRASRLHandler}, {0x15, RLCRRCRLRRSLASRASRLHandler}, {0x16, RLCRRCRLRRSLASRASRLHandler}, {0x17, RLCRRCRLRRSLASRASRLHandler}, {0x18, RLCRRCRLRRSLASRASRLHandler}, {0x19, RLCRRCRLRRSLASRASRLHandler}, {0x1a, RLCRRCRLRRSLASRASRLHandler}, {0x1b, RLCRRCRLRRSLASRASRLHandler}, {0x1c, RLCRRCRLRRSLASRASRLHandler}, {0x1d, RLCRRCRLRRSLASRASRLHandler}, {0x1e, RLCRRCRLRRSLASRASRLHandler}, {0x1f, RLCRRCRLRRSLASRASRLHandler}, {0x20, RLCRRCRLRRSLASRASRLHandler}, {0x21, RLCRRCRLRRSLASRASRLHandler}, {0x22, RLCRRCRLRRSLASRASRLHandler}, {0x23, RLCRRCRLRRSLASRASRLHandler}, {0x24, RLCRRCRLRRSLASRASRLHandler}, {0x25, RLCRRCRLRRSLASRASRLHandler}, {0x26, RLCRRCRLRRSLASRASRLHandler}, {0x27, RLCRRCRLRRSLASRASRLHandler}, {0x28, RLCRRCRLRRSLASRASRLHandler}, {0x29, RLCRRCRLRRSLASRASRLHandler}, {0x2a, RLCRRCRLRRSLASRASRLHandler}, {0x2b, RLCRRCRLRRSLASRASRLHandler}, {0x2c, RLCRRCRLRRSLASRASRLHandler}, {0x2d, RLCRRCRLRRSLASRASRLHandler}, {0x2e, RLCRRCRLRRSLASRASRLHandler}, {0x2f, RLCRRCRLRRSLASRASRLHandler}, {0x30, RLCRRCRLRRSLASRASRLHandler}, {0x31, RLCRRCRLRRSLASRASRLHandler}, {0x32, RLCRRCRLRRSLASRASRLHandler}, {0x33, RLCRRCRLRRSLASRASRLHandler}, {0x34, RLCRRCRLRRSLASRASRLHandler}, {0x35, RLCRRCRLRRSLASRASRLHandler}, {0x36, RLCRRCRLRRSLASRASRLHandler}, {0x37, RLCRRCRLRRSLASRASRLHandler}, {0x38, RLCRRCRLRRSLASRASRLHandler}, {0x39, RLCRRCRLRRSLASRASRLHandler}, {0x3a, RLCRRCRLRRSLASRASRLHandler}, {0x3b, RLCRRCRLRRSLASRASRLHandler}, {0x3c, RLCRRCRLRRSLASRASRLHandler}, {0x3d, RLCRRCRLRRSLASRASRLHandler}, {0x3e, RLCRRCRLRRSLASRASRLHandler}, {0x3f, RLCRRCRLRRSLASRASRLHandler}, {0x40, BITHandler}, {0x41, BITHandler}, {0x42, BITHandler}, {0x43, BITHandler}, {0x44, BITHandler}, {0x45, BITHandler}, {0x46, BITHandler}, {0x47, BITHandler}, {0x48, BITHandler}, {0x49, BITHandler}, {0x4a, BITHandler}, {0x4b, BITHandler}, {0x4c, BITHandler}, {0x4d, BITHandler}, {0x4e, BITHandler}, {0x4f, BITHandler}, {0x50, BITHandler}, {0x51, BITHandler}, {0x52, BITHandler}, {0x53, BITHandler}, {0x54, BITHandler}, {0x55, BITHandler}, {0x56, BITHandler}, {0x57, BITHandler}, {0x58, BITHandler}, {0x59, BITHandler}, {0x5a, BITHandler}, {0x5b, BITHandler}, {0x5c, BITHandler}, {0x5d, BITHandler}, {0x5e, BITHandler}, {0x5f, BITHandler}, {0x60, BITHandler}, {0x61, BITHandler}, {0x62, BITHandler}, {0x63, BITHandler}, {0x64, BITHandler}, {0x65, BITHandler}, {0x66, BITHandler}, {0x67, BITHandler}, {0x68, BITHandler}, {0x69, BITHandler}, {0x6a, BITHandler}, {0x6b, BITHandler}, {0x6c, BITHandler}, {0x6d, BITHandler}, {0x6e, BITHandler}, {0x6f, BITHandler}, {0x70, BITHandler}, {0x71, BITHandler}, {0x72, BITHandler}, {0x73, BITHandler}, {0x74, BITHandler}, {0x75, BITHandler}, {0x76, BITHandler}, {0x77, BITHandler}, {0x78, BITHandler}, {0x79, BITHandler}, {0x7a, BITHandler}, {0x7b, BITHandler}, {0x7c, BITHandler}, {0x7d, BITHandler}, {0x7e, BITHandler}, {0x7f, BITHandler}, // RES {0x80, RESSETHandler}, {0x81, RESSETHandler}, {0x82, RESSETHandler}, {0x83, RESSETHandler}, {0x84, RESSETHandler}, {0x85, RESSETHandler}, {0x86, RESSETHandler}, {0x87, RESSETHandler}, {0x88, RESSETHandler}, {0x89, RESSETHandler}, {0x8a, RESSETHandler}, {0x8b, RESSETHandler}, {0x8c, RESSETHandler}, {0x8d, RESSETHandler}, {0x8e, RESSETHandler}, {0x8f, RESSETHandler}, {0x90, RESSETHandler}, {0x91, RESSETHandler}, {0x92, RESSETHandler}, {0x93, RESSETHandler}, {0x94, RESSETHandler}, {0x95, RESSETHandler}, {0x96, RESSETHandler}, {0x97, RESSETHandler}, {0x98, RESSETHandler}, {0x99, RESSETHandler}, {0x9a, RESSETHandler}, {0x9b, RESSETHandler}, {0x9c, RESSETHandler}, {0x9d, RESSETHandler}, {0x9e, RESSETHandler}, {0x9f, RESSETHandler}, {0xa0, RESSETHandler}, {0xa1, RESSETHandler}, {0xa2, RESSETHandler}, {0xa3, RESSETHandler}, {0xa4, RESSETHandler}, {0xa5, RESSETHandler}, {0xa6, RESSETHandler}, {0xa7, RESSETHandler}, {0xa8, RESSETHandler}, {0xa9, RESSETHandler}, {0xaa, RESSETHandler}, {0xab, RESSETHandler}, {0xac, RESSETHandler}, {0xad, RESSETHandler}, {0xae, RESSETHandler}, {0xaf, RESSETHandler}, {0xb0, RESSETHandler}, {0xb1, RESSETHandler}, {0xb2, RESSETHandler}, {0xb3, RESSETHandler}, {0xb4, RESSETHandler}, {0xb5, RESSETHandler}, {0xb6, RESSETHandler}, {0xb7, RESSETHandler}, {0xb8, RESSETHandler}, {0xb9, RESSETHandler}, {0xba, RESSETHandler}, {0xbb, RESSETHandler}, {0xbc, RESSETHandler}, {0xbd, RESSETHandler}, {0xbe, RESSETHandler}, {0xbf, RESSETHandler}, // SET {0xc0, RESSETHandler}, {0xc1, RESSETHandler}, {0xc2, RESSETHandler}, {0xc3, RESSETHandler}, {0xc4, RESSETHandler}, {0xc5, RESSETHandler}, {0xc6, RESSETHandler}, {0xc7, RESSETHandler}, {0xc8, RESSETHandler}, {0xc9, RESSETHandler}, {0xca, RESSETHandler}, {0xcb, RESSETHandler}, {0xcc, RESSETHandler}, {0xcd, RESSETHandler}, {0xce, RESSETHandler}, {0xcf, RESSETHandler}, {0xd0, RESSETHandler}, {0xd1, RESSETHandler}, {0xd2, RESSETHandler}, {0xd3, RESSETHandler}, {0xd4, RESSETHandler}, {0xd5, RESSETHandler}, {0xd6, RESSETHandler}, {0xd7, RESSETHandler}, {0xd8, RESSETHandler}, {0xd9, RESSETHandler}, {0xda, RESSETHandler}, {0xdb, RESSETHandler}, {0xdc, RESSETHandler}, {0xdd, RESSETHandler}, {0xde, RESSETHandler}, {0xdf, RESSETHandler}, {0xe0, RESSETHandler}, {0xe1, RESSETHandler}, {0xe2, RESSETHandler}, {0xe3, RESSETHandler}, {0xe4, RESSETHandler}, {0xe5, RESSETHandler}, {0xe6, RESSETHandler}, {0xe7, RESSETHandler}, {0xe8, RESSETHandler}, {0xe9, RESSETHandler}, {0xea, RESSETHandler}, {0xeb, RESSETHandler}, {0xec, RESSETHandler}, {0xed, RESSETHandler}, {0xee, RESSETHandler}, {0xef, RESSETHandler}, {0xf0, RESSETHandler}, {0xf1, RESSETHandler}, {0xf2, RESSETHandler}, {0xf3, RESSETHandler}, {0xf4, RESSETHandler}, {0xf5, RESSETHandler}, {0xf6, RESSETHandler}, {0xf7, RESSETHandler}, {0xf8, RESSETHandler}, {0xf9, RESSETHandler}, {0xfa, RESSETHandler}, {0xfb, RESSETHandler}, {0xfc, RESSETHandler}, {0xfd, RESSETHandler}, {0xfe, RESSETHandler}, {0xff, RESSETHandler}, // Terminator {0xffffffff, NULL} }; struct sOp EDOps[] = { {0x67, RRDRLDHandler}, {0x6f, RRDRLDHandler}, {0x42, AdcSbcRegpair}, {0x4a, AdcSbcRegpair}, {0x52, AdcSbcRegpair}, {0x5a, AdcSbcRegpair}, {0x62, AdcSbcRegpair}, {0x6a, AdcSbcRegpair}, {0x72, AdcSbcRegpair}, {0x7a, AdcSbcRegpair}, {0x45, RetIRetNHandler}, {0x4d, RetIRetNHandler}, {0x44, NegHandler}, {0xa0, LDILDRLDIRLDDRHandler}, {0xa8, LDILDRLDIRLDDRHandler}, {0xb0, LDILDRLDIRLDDRHandler}, {0xb8, LDILDRLDIRLDDRHandler}, {0x57, IRHandler}, {0x5F, IRHandler}, {0x47, IRHandler}, {0x4F, IRHandler}, {0x46, IMHandler}, {0x56, IMHandler}, {0x5e, IMHandler}, {0x4b, LdRegpair}, {0x5b, LdRegpair}, {0x7b, LdRegpair}, {0x43, ExtendedRegIntoMemory}, {0x53, ExtendedRegIntoMemory}, {0x63, ExtendedRegIntoMemory}, {0x73, ExtendedRegIntoMemory}, {0x40, ExtendedInHandler}, {0x48, ExtendedInHandler}, {0x50, ExtendedInHandler}, {0x58, ExtendedInHandler}, {0x60, ExtendedInHandler}, {0x68, ExtendedInHandler}, {0x78, ExtendedInHandler}, {0x41, ExtendedOutHandler}, {0x49, ExtendedOutHandler}, {0x51, ExtendedOutHandler}, {0x59, ExtendedOutHandler}, {0x61, ExtendedOutHandler}, {0x69, ExtendedOutHandler}, {0x79, ExtendedOutHandler}, {0xa1, CPICPDCPIRCPDRHandler}, {0xa9, CPICPDCPIRCPDRHandler}, {0xb1, CPICPDCPIRCPDRHandler}, {0xb9, CPICPDCPIRCPDRHandler}, {0xbb, OTIROTDROUTIOUTDHandler}, // OTDR {0xb3, OTIROTDROUTIOUTDHandler}, // OTIR {0xab, OTIROTDROUTIOUTDHandler}, // OUTD {0xa3, OTIROTDROUTIOUTDHandler}, // OUTI {0xb2, INIRINDRINIINDHandler}, // INIR {0xba, INIRINDRINIINDHandler}, // INDR {0xa2, INIRINDRINIINDHandler}, // INI {0xaa, INIRINDRINIINDHandler}, // IND // Terminator {0xffffffff, NULL} }; struct sOp DDFDOps[] = { {0x35, IncDecIndexed}, {0x34, IncDecIndexed}, {0xcb, DDFDCBHandler}, {0x86, MathOperationIndexed}, {0x8e, MathOperationIndexed}, {0x96, MathOperationIndexed}, {0x9e, MathOperationIndexed}, {0xa6, MathOperationIndexed}, {0xae, MathOperationIndexed}, {0xb6, MathOperationIndexed}, {0xbe, MathOperationIndexed}, {0xe1, PushPopOperationsIndexed}, {0xe5, PushPopOperationsIndexed}, {0x21, LoadImmediate}, {0xe9, JPIXIYHandler}, {0x09, AddIndexHandler}, {0x19, AddIndexHandler}, {0x29, AddIndexHandler}, {0x39, AddIndexHandler}, {0xf9, SPToIndex}, {0x36, LdByteToIndex}, {0x46, LdRegIndexOffset}, {0x4e, LdRegIndexOffset}, {0x56, LdRegIndexOffset}, {0x5e, LdRegIndexOffset}, {0x66, LdRegIndexOffset}, {0x6e, LdRegIndexOffset}, {0x7e, LdRegIndexOffset}, {0x70, LdIndexPtrReg}, {0x71, LdIndexPtrReg}, {0x72, LdIndexPtrReg}, {0x73, LdIndexPtrReg}, {0x74, LdIndexPtrReg}, {0x75, LdIndexPtrReg}, {0x77, LdIndexPtrReg}, {0x23, IncDecIndexReg}, {0x2b, IncDecIndexReg}, {0x22, StoreIndexReg}, {0x2a, LoadIndexReg}, {0xe3, ExIndexed}, {0x44, UndocRegToIndex}, {0x45, UndocRegToIndex}, {0x4c, UndocRegToIndex}, {0x4d, UndocRegToIndex}, {0x54, UndocRegToIndex}, {0x55, UndocRegToIndex}, {0x5c, UndocRegToIndex}, {0x5d, UndocRegToIndex}, {0x7c, UndocRegToIndex}, {0x7d, UndocRegToIndex}, {0x60, UndocIndexToReg}, {0x61, UndocIndexToReg}, {0x62, UndocIndexToReg}, {0x63, UndocIndexToReg}, {0x64, UndocIndexToReg}, {0x65, UndocIndexToReg}, {0x67, UndocIndexToReg}, {0x68, UndocIndexToReg}, {0x69, UndocIndexToReg}, {0x6a, UndocIndexToReg}, {0x6b, UndocIndexToReg}, {0x6c, UndocIndexToReg}, {0x6d, UndocIndexToReg}, {0x6f, UndocIndexToReg}, {0x24, UndocIncDecIndexReg}, {0x25, UndocIncDecIndexReg}, {0x2c, UndocIncDecIndexReg}, {0x2d, UndocIncDecIndexReg}, {0x26, UndocLoadHalfIndexReg}, {0x2e, UndocLoadHalfIndexReg}, {0x84, UndocMathIndex}, {0x85, UndocMathIndex}, {0x8c, UndocMathIndex}, {0x8d, UndocMathIndex}, {0x94, UndocMathIndex}, {0x95, UndocMathIndex}, {0x9c, UndocMathIndex}, {0x9d, UndocMathIndex}, {0xa4, UndocMathIndex}, {0xa5, UndocMathIndex}, {0xac, UndocMathIndex}, {0xad, UndocMathIndex}, {0xb4, UndocMathIndex}, {0xb5, UndocMathIndex}, {0xbc, UndocMathIndex}, {0xbd, UndocMathIndex}, // Terminator {0xffffffff, NULL} }; struct sOp DDFDCBOps[] = { {0x06, ddcbBitWise}, {0x0e, ddcbBitWise}, {0x16, ddcbBitWise}, {0x1e, ddcbBitWise}, {0x26, ddcbBitWise}, {0x2e, ddcbBitWise}, {0x3e, ddcbBitWise}, {0x46, ddcbBitWise}, {0x4e, ddcbBitWise}, {0x56, ddcbBitWise}, {0x5e, ddcbBitWise}, {0x66, ddcbBitWise}, {0x6e, ddcbBitWise}, {0x76, ddcbBitWise}, {0x7e, ddcbBitWise}, {0x86, ddcbBitWise}, {0x8e, ddcbBitWise}, {0x96, ddcbBitWise}, {0x9e, ddcbBitWise}, {0xa6, ddcbBitWise}, {0xae, ddcbBitWise}, {0xb6, ddcbBitWise}, {0xbe, ddcbBitWise}, {0xc6, ddcbBitWise}, {0xce, ddcbBitWise}, {0xd6, ddcbBitWise}, {0xde, ddcbBitWise}, {0xe6, ddcbBitWise}, {0xee, ddcbBitWise}, {0xf6, ddcbBitWise}, {0xfe, ddcbBitWise}, // Terminator {0xffffffff, NULL} }; void InvalidInstructionC(UINT32 dwCount) { fprintf(fp, " InvalidInstruction(%" PRIu32 ");\n", dwCount); } UINT32 Timing(UINT8 bWho, UINT32 dwOpcode) { UINT32 dwTiming = 0; assert(dwOpcode < 0x100); if (TIMING_REGULAR == bWho) // Regular? dwTiming = bTimingRegular[dwOpcode]; else if (TIMING_CB == bWho) dwTiming = bTimingCB[dwOpcode]; else if (TIMING_DDFD == bWho) dwTiming = bTimingDDFD[dwOpcode]; else if (TIMING_ED == bWho) dwTiming = bTimingED[dwOpcode]; else if (TIMING_XXCB == bWho) dwTiming = bTimingXXCB[dwOpcode]; else if (TIMING_EXCEPT == bWho) dwTiming = dwOpcode; else abort(); if (0 == dwTiming) { fprintf(stderr, "Opcode: %.2x:%.2x - Not zero!\n", bWho, dwOpcode); fclose(fp); exit(1); } return(dwTiming); } void IndexedOffset(INT8 *Localmz80Index) { fprintf(fp, " mov dl, [esi] ; Fetch our offset\n"); fprintf(fp, " inc esi ; Move past the offset\n"); fprintf(fp, " or dl, dl ; Is this bad boy signed?\n"); fprintf(fp, " jns notSigned%" PRIu32 " ; Nope!\n", dwGlobalLabel); fprintf(fp, " dec dh ; Make it FFable\n"); fprintf(fp, "notSigned%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " add dx, [_z80%s] ; Our offset!\n", Localmz80Index); ++dwGlobalLabel; } void CBHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, ";\n"); fprintf(fp, "; Handler for all CBxx instructions\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(0xffffffff); fprintf(fp, " mov dl, [esi]\n"); fprintf(fp, " inc esi\n"); fprintf(fp, " jmp dword [z80PrefixCB+edx*4]\n\n"); fprintf(fp, "\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, " CBHandler();\n"); } else { abort(); } } void EDHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, ";\n"); fprintf(fp, "; Handler for all EDxx instructions\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(0xffffffff); fprintf(fp, " mov dl, [esi]\n"); fprintf(fp, " inc esi\n"); fprintf(fp, " jmp dword [z80PrefixED+edx*4]\n\n"); fprintf(fp, "\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, " EDHandler();\n"); } else { abort(); } } void DDHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, ";\n"); fprintf(fp, "; Handler for all DDxx instructions\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(0xffffffff); fprintf(fp, " mov dl, [esi]\n"); fprintf(fp, " inc esi\n"); fprintf(fp, " jmp dword [z80PrefixDD+edx*4]\n\n"); fprintf(fp, "\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, " DDHandler();\n"); } else { abort(); } } void FDHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, ";\n"); fprintf(fp, "; Handler for all FDxx instructions\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(0xffffffff); fprintf(fp, " mov dl, [esi]\n"); fprintf(fp, " inc esi\n"); fprintf(fp, " jmp dword [z80PrefixFD+edx*4]\n\n"); fprintf(fp, "\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, " FDHandler();\n"); } else { abort(); } } void StandardHeader(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp,"; For assembly by NASM only\n"); fprintf(fp,"bits 32\n\n"); fprintf(fp,"; Theory of operation\n\n"); fprintf(fp,"; EDI=General purpose\n"); fprintf(fp,"; ESI=Program counter + base address\n"); fprintf(fp,"; EBP=z80Base\n"); fprintf(fp,"; AX=AF\n"); fprintf(fp,"; BX=HL\n"); fprintf(fp,"; CX=BC\n"); fprintf(fp,"; DX=General purpose\n\n"); if (bUseStack) fprintf(fp, "; Using stack calling conventions\n"); else fprintf(fp, "; Using register calling conventions\n"); if (b16BitIo) fprintf(fp, "; Extended input/output instructions treat (BC) as I/O address\n"); else fprintf(fp, "; Extended input/output instructions treat (C) as I/O address\n\n"); fprintf(fp, "IFF1 equ 01h\n"); fprintf(fp, "IFF2 equ 02h\n"); fprintf(fp, "CPUREG_PC equ 00h\n"); fprintf(fp, "CPUREG_SP equ 01h\n"); fprintf(fp, "CPUREG_AF equ 02h\n"); fprintf(fp, "CPUREG_BC equ 03h\n"); fprintf(fp, "CPUREG_DE equ 04h\n"); fprintf(fp, "CPUREG_HL equ 05h\n"); fprintf(fp, "CPUREG_AFPRIME equ 06h\n"); fprintf(fp, "CPUREG_BCPRIME equ 07h\n"); fprintf(fp, "CPUREG_DEPRIME equ 08h\n"); fprintf(fp, "CPUREG_HLPRIME equ 09h\n"); fprintf(fp, "CPUREG_IX equ 0ah\n"); fprintf(fp, "CPUREG_IY equ 0bh\n"); fprintf(fp, "CPUREG_I equ 0ch\n"); fprintf(fp, "CPUREG_A equ 0dh\n"); fprintf(fp, "CPUREG_F equ 0eh\n"); fprintf(fp, "CPUREG_B equ 0fh\n"); fprintf(fp, "CPUREG_C equ 10h\n"); fprintf(fp, "CPUREG_D equ 11h\n"); fprintf(fp, "CPUREG_E equ 12h\n"); fprintf(fp, "CPUREG_H equ 13h\n"); fprintf(fp, "CPUREG_L equ 14h\n"); fprintf(fp, "CPUREG_IFF1 equ 15h\n"); fprintf(fp, "CPUREG_IFF2 equ 16h\n"); fprintf(fp, "CPUREG_CARRY equ 17h\n"); fprintf(fp, "CPUREG_NEGATIVE equ 18h\n"); fprintf(fp, "CPUREG_PARITY equ 19h\n"); fprintf(fp, "CPUREG_OVERFLOW equ 1ah\n"); fprintf(fp, "CPUREG_HALFCARRY equ 1bh\n"); fprintf(fp, "CPUREG_ZERO equ 1ch\n"); fprintf(fp, "CPUREG_SIGN equ 1dh\n"); fprintf(fp, "CPUREG_MAXINDEX equ 1eh\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Multi-Z80 32 Bit emulator */\n"); fprintf(fp, "\n"); fprintf(fp, "/* Copyright 1996-2000 Neil Bradley, All rights reserved\n"); fprintf(fp, " *\n"); fprintf(fp, " * License agreement:\n"); fprintf(fp, " *\n"); fprintf(fp, " * (MZ80 Refers to both the assembly code emitted by makeZ80.c and makeZ80.c\n"); fprintf(fp, " * itself)\n"); fprintf(fp, " *\n"); fprintf(fp, " * MZ80 May be distributed in unmodified form to any medium.\n"); fprintf(fp, " *\n"); fprintf(fp, " * MZ80 May not be sold, or sold as a part of a commercial package without\n"); fprintf(fp, " * the express written permission of Neil Bradley (neil@synthcom.com). This\n"); fprintf(fp, " * includes shareware.\n"); fprintf(fp, " *\n"); fprintf(fp, " * Modified versions of MZ80 may not be publicly redistributed without author\n"); fprintf(fp, " * approval (neil@synthcom.com). This includes distributing via a publicly\n"); fprintf(fp, " * accessible LAN. You may make your own source modifications and distribute\n"); fprintf(fp, " * MZ80 in source or object form, but if you make modifications to MZ80\n"); fprintf(fp, " * then it should be noted in the top as a comment in makeZ80.c.\n"); fprintf(fp, " *\n"); fprintf(fp, " * MZ80 Licensing for commercial applications is available. Please email\n"); fprintf(fp, " * neil@synthcom.com for details.\n"); fprintf(fp, " *\n"); fprintf(fp, " * Synthcom Systems, Inc, and Neil Bradley will not be held responsible for\n"); fprintf(fp, " * any damage done by the use of MZ80. It is purely \"as-is\".\n"); fprintf(fp, " *\n"); fprintf(fp, " * If you use MZ80 in a freeware application, credit in the following text:\n"); fprintf(fp, " *\n"); fprintf(fp, " * \"Multi-Z80 CPU emulator by Neil Bradley (neil@synthcom.com)\"\n"); fprintf(fp, " *\n"); fprintf(fp, " * must accompany the freeware application within the application itself or\n"); fprintf(fp, " * in the documentation.\n"); fprintf(fp, " *\n"); fprintf(fp, " * Legal stuff aside:\n"); fprintf(fp, " *\n"); fprintf(fp, " * If you find problems with MZ80, please email the author so they can get\n"); fprintf(fp, " * resolved. If you find a bug and fix it, please also email the author so\n"); fprintf(fp, " * that those bug fixes can be propogated to the installed base of MZ80\n"); fprintf(fp, " * users. If you find performance improvements or problems with MZ80, please\n"); fprintf(fp, " * email the author with your changes/suggestions and they will be rolled in\n"); fprintf(fp, " * with subsequent releases of MZ80.\n"); fprintf(fp, " *\n"); fprintf(fp, " * The whole idea of this emulator is to have the fastest available 32 bit\n"); fprintf(fp, " * Multi-Z80 emulator for the PC, giving maximum performance. \n"); fprintf(fp, " */\n\n"); fprintf(fp, "#include \n"); fprintf(fp, "#include \n"); fprintf(fp, "#include \n"); fprintf(fp, "#ifdef HAVE_MEMCPY_H\n" "#include \"memcpy.h\"\n" "#endif\n"); fprintf(fp, "#include \"mz80.h\"\n"); // HACK HACK fprintf(fp, "UINT32 z80intAddr;\n"); fprintf(fp, "UINT32 z80pc;\n"); } else { // Whoops. Unknown emission type. abort(); } fprintf(fp, "\n\n"); } void Alignment(void) { fprintf(fp, "\ntimes ($$-$) & 3 nop ; pad with NOPs to 4-byte boundary\n\n"); } void ProcBegin(UINT32 dwOpcode) { (void)dwOpcode; Alignment(); fprintf(fp, "%s:\n", procname); } void SetSubFlagsSZHVC(INT8 *pszLeft, INT8 *pszRight) { fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | \n"); fprintf(fp, " Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) |\n"); fprintf(fp, " pbSubSbcTable[((UINT32) %s << 8) | %s];\n", pszLeft, pszRight); } void SetSbcFlagsSZHVC(INT8 *pszLeft, INT8 *pszRight) { fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | \n"); fprintf(fp, " Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) |\n"); fprintf(fp, " pbSubSbcTable[((UINT32) %s << 8) | %s | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)];\n", pszLeft, pszRight); } void SetAddFlagsSZHVC(INT8 *pszLeft, INT8 *pszRight) { fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | \n"); fprintf(fp, " Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) |\n"); fprintf(fp, " pbAddAdcTable[((UINT32) %s << 8) | %s];\n", pszLeft, pszRight); } void SetAdcFlagsSZHVC(INT8 *pszLeft, INT8 *pszRight) { fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | \n"); fprintf(fp, " Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN)) |\n"); fprintf(fp, " pbAddAdcTable[((UINT32) %s << 8) | %s | (((UINT32) cpu.z80F & Z80_FLAG_CARRY) << 16)];\n", pszLeft, pszRight); } UINT32 dwOverflowCount = 0; void SetOverflow(void) { fprintf(fp, " seto dl\n"); fprintf(fp, " and ah, 0fbh ; Knock out parity/overflow\n"); fprintf(fp, " shl dl, 2\n"); fprintf(fp, " or ah, dl\n"); } void FetchNextInstruction(UINT32 dwOpcode) { if (0xffffffff != dwOpcode) { fprintf(fp, " sub edi, byte %" PRIu32 "\n", Timing(bCurrentMode, dwOpcode)); if (bCurrentMode == TIMING_REGULAR) fprintf(fp, " js near noMoreExec\n"); else fprintf(fp, " js near noMoreExec\n"); } fprintf(fp, " mov dl, byte [esi] ; Get our next instruction\n"); fprintf(fp, " inc esi ; Increment PC\n"); fprintf(fp, " jmp dword [z80regular+edx*4]\n\n"); } void WriteValueToMemory(INT8 *pszAddress, INT8 *pszValue) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov [_z80af], ax ; Store AF\n"); // First off, load our byte to write into al after we've saved AF if (strcmp(pszValue, "al") != 0) fprintf(fp, " mov al, %s ; And our data to write\n", pszValue); if (strcmp(pszValue, "[esi]") == 0) // Immediate value? fprintf(fp, " inc esi ; Increment our program counter\n"); // Now get the address in DX - regardless of what it is if (strcmp(pszAddress, "[_z80de]") == 0 || strcmp(pszAddress, "[_orgval]") == 0 || strcmp(pszAddress, "[_z80ix]") == 0 || strcmp(pszAddress, "[_z80iy]") == 0) fprintf(fp, " mov dx, %s\n", pszAddress); fprintf(fp, " mov edi, [_z80MemWrite] ; Point to the write array\n\n"); fprintf(fp, "checkLoop%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of our list?\n"); fprintf(fp, " je memoryWrite%" PRIu32 " ; Yes - go write it!\n", dwGlobalLabel); if (strcmp(pszAddress, "[_z80de]") == 0 || strcmp(pszAddress, "[_orgval]") == 0 || strcmp(pszAddress, "[_z80ix]") == 0 || strcmp(pszAddress, "[_z80iy]") == 0) fprintf(fp, " cmp dx, [edi] ; Are we smaller?\n"); else fprintf(fp, " cmp %s, [edi] ; Are we smaller?\n", pszAddress); fprintf(fp, " jb nextAddr%" PRIu32 " ; Yes... go to the next addr\n", dwGlobalLabel); if (strcmp(pszAddress, "[_z80de]") == 0 || strcmp(pszAddress, "[_orgval]") == 0 || strcmp(pszAddress, "[_z80ix]") == 0 || strcmp(pszAddress, "[_z80iy]") == 0) fprintf(fp, " cmp dx, [edi+4] ; Are we smaller?\n"); else fprintf(fp, " cmp %s, [edi+4] ; Are we smaller?\n", pszAddress); fprintf(fp, " jbe callRoutine%" PRIu32 " ; If not, go call it!\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " add edi, 10h ; Next structure, please\n"); fprintf(fp, " jmp short checkLoop%" PRIu32 "\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%" PRIu32 ":\n", dwGlobalLabel); // Save off our registers! if ((strcmp(pszAddress, "dx") != 0) && (strcmp(pszAddress, "[_z80de]") != 0) && (strcmp(pszAddress, "[_z80ix]") != 0) && (strcmp(pszAddress, "[_orgval]") != 0) && (strcmp(pszAddress, "[_z80iy]") != 0)) fprintf(fp, " mov dx, %s ; Get our address to target\n", pszAddress); fprintf(fp, " call WriteMemoryByte ; Go write the data!\n"); fprintf(fp, " jmp short WriteMacroExit%" PRIu32 "\n", dwGlobalLabel); fprintf(fp, "memoryWrite%" PRIu32 ":\n", dwGlobalLabel); if (strcmp(pszValue, "[esi]") == 0) fprintf(fp, " mov [ebp + e%s], al ; Store our direct value\n", pszAddress); else { if (pszValue[0] == 'b' && pszValue[1] == 'y' && pszValue[2] == 't') { fprintf(fp, " mov edi, edx\n"); assert(strcmp(pszValue, "dl") != 0); fprintf(fp, " mov dl, %s\n", pszValue); if (strcmp(pszAddress, "dx") == 0) fprintf(fp, " mov [ebp + edi], dl\n"); else fprintf(fp, " mov [ebp + e%s], dl\n", pszAddress); fprintf(fp, " mov edx, edi\n"); } else { if (strcmp(pszAddress, "[_z80de]") != 0 && strcmp(pszAddress, "[_orgval]") != 0 && strcmp(pszAddress, "[_z80ix]") != 0 && strcmp(pszAddress, "[_z80iy]") != 0) fprintf(fp, " mov [ebp + e%s], %s\n", pszAddress, pszValue); else fprintf(fp, " mov [ebp + edx], al\n"); } } fprintf(fp, " mov ax, [_z80af] ; Get our accumulator and flags\n"); fprintf(fp, "WriteMacroExit%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " mov edi, [cyclesRemaining]\n"); ++dwGlobalLabel; } else if (MZ80_C == bWhat) { fprintf(fp, " psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */\n"); fprintf(fp, " while (psMemWrite->lowAddr != 0xffffffff)\n"); fprintf(fp, " {\n"); fprintf(fp, " if ((%s >= psMemWrite->lowAddr) && (%s <= psMemWrite->highAddr))\n", pszAddress, pszAddress); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = (UINTPTR) pbPC - (UINTPTR) cpu.z80Base;\n"); fprintf(fp, " if (psMemWrite->memoryCall)\n"); fprintf(fp, " {\n"); fprintf(fp, " psMemWrite->memoryCall(%s, %s, psMemWrite);\n", pszAddress, pszValue); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " *((UINT8 *) psMemWrite->pUserArea + (%s - psMemWrite->lowAddr)) = %s;\n", pszAddress, pszValue); fprintf(fp, " }\n"); fprintf(fp, " psMemWrite = NULL;\n"); fprintf(fp, " break;\n"); fprintf(fp, " }\n"); fprintf(fp, " ++psMemWrite;\n"); fprintf(fp, " }\n\n"); fprintf(fp, " if (psMemWrite)\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80Base[%s] = (UINT8) %s;\n", pszAddress, pszValue); fprintf(fp, " }\n\n"); } } void WriteWordToMemory(INT8 *pszAddress, INT8 *pszTarget) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov edi, [_z80MemWrite] ; Point to the write array\n\n"); fprintf(fp, "checkLoop%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of the list?\n"); fprintf(fp, " je memoryWrite%" PRIu32 "\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi] ; Are we smaller?\n", pszAddress); fprintf(fp, " jb nextAddr%" PRIu32 " ; Yes, go to the next address\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi+4] ; Are we bigger?\n", pszAddress); fprintf(fp, " jbe callRoutine%" PRIu32 "\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " add edi, 10h ; Next structure!\n"); fprintf(fp, " jmp short checkLoop%" PRIu32 "\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " push ax ; Save this for later\n"); // Write the LSB fprintf(fp, " push dx\n"); if (strcmp(pszTarget, "ax") != 0) { fprintf(fp, " mov ax, %s\n", pszTarget); } else { fprintf(fp, " xchg ah, al\n"); } fprintf(fp, " call WriteMemoryByte\n"); fprintf(fp, " pop dx\n"); fprintf(fp, " pop ax\n"); fprintf(fp, " inc dx\n\n"); fprintf(fp, " push ax\n"); fprintf(fp, " push dx\n"); if (strcmp(pszTarget, "ax") != 0) { fprintf(fp, " mov ax, %s\n", pszTarget); fprintf(fp, " xchg ah, al\n"); } fprintf(fp, " call WriteMemoryByte\n"); fprintf(fp, " pop dx\n"); fprintf(fp, " pop ax ; Restore us!\n"); fprintf(fp, " jmp writeExit%" PRIu32 "\n\n", dwGlobalLabel); fprintf(fp, "memoryWrite%" PRIu32 ":\n", dwGlobalLabel); if (strlen(pszTarget) != 2) { fprintf(fp, " mov di, %s\n", pszTarget); fprintf(fp, " mov [ebp + e%s], di ; Store our word\n", pszAddress); } else { if (strcmp(pszTarget, "ax") != 0) { fprintf(fp, " mov [ebp + e%s], %s ; Store our word\n", pszAddress, pszTarget); } else { fprintf(fp, " xchg ah, al ; Swap for later\n"); fprintf(fp, " mov [ebp + e%s], %s ; Store our word\n", pszAddress, pszTarget); fprintf(fp, " xchg ah, al ; Restore\n"); } } fprintf(fp, "writeExit%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " mov edi, [cyclesRemaining]\n"); dwGlobalLabel++; } else if (MZ80_C == bWhat) { fprintf(fp, " psMemWrite = cpu.z80MemWrite; /* Beginning of our handler */\n"); fprintf(fp, " while (psMemWrite->lowAddr != 0xffffffff)\n"); fprintf(fp, " {\n"); fprintf(fp, " if ((%s >= psMemWrite->lowAddr) && (%s <= psMemWrite->highAddr))\n", pszAddress, pszAddress); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = (UINTPTR) pbPC - (UINTPTR) cpu.z80Base;\n"); fprintf(fp, " if (psMemWrite->memoryCall)\n"); fprintf(fp, " {\n"); fprintf(fp, " psMemWrite->memoryCall(%s, (%s & 0xff), psMemWrite);\n", pszAddress, pszTarget); fprintf(fp, " psMemWrite->memoryCall(%s + 1, (%s >> 8), psMemWrite);\n", pszAddress, pszTarget); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " *((UINT8 *) psMemWrite->pUserArea + (%s - psMemWrite->lowAddr)) = %s;\n", pszAddress, pszTarget); fprintf(fp, " *((UINT8 *) psMemWrite->pUserArea + (%s - psMemWrite->lowAddr) + 1) = %s >> 8;\n", pszAddress, pszTarget); fprintf(fp, " }\n"); fprintf(fp, " psMemWrite = NULL;\n"); fprintf(fp, " break;\n"); fprintf(fp, " }\n"); fprintf(fp, " ++psMemWrite;\n"); fprintf(fp, " }\n\n"); fprintf(fp, " if (psMemWrite)\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80Base[%s] = (UINT8) %s;\n", pszAddress, pszTarget); fprintf(fp, " cpu.z80Base[%s + 1] = (UINT8) ((UINT32) %s >> 8);\n", pszAddress, pszTarget); fprintf(fp, " }\n\n"); } else { abort(); } } void WriteValueToIo(INT8 *pszIoAddress, INT8 *pszValue) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov [_z80af], ax ; Store AF\n"); if (strcmp(pszValue, "al") != 0) fprintf(fp, " mov al, %s ; And our data to write\n", pszValue); if (strcmp(pszValue, "[esi]") == 0) // Immediate value? fprintf(fp, " inc esi ; Increment our program counter\n"); fprintf(fp, " mov edi, [_z80IoWrite] ; Point to the I/O write array\n\n"); fprintf(fp, "checkLoop%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of our list?\n"); fprintf(fp, " je WriteMacroExit%" PRIu32 " ; Yes - ignore it!\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi] ; Are we smaller?\n", pszIoAddress); fprintf(fp, " jb nextAddr%" PRIu32 " ; Yes... go to the next addr\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi+2] ; Are we bigger?\n", pszIoAddress); fprintf(fp, " jbe callRoutine%" PRIu32 " ; If not, go call it!\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " add edi, 0ch ; Next structure, please\n"); fprintf(fp, " jmp short checkLoop%" PRIu32 "\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%" PRIu32 ":\n", dwGlobalLabel); // Save off our registers! if (strcmp(pszIoAddress, "dx") != 0) fprintf(fp, " mov dx, %s ; Get our address to target\n", pszIoAddress); fprintf(fp, " call WriteIOByte ; Go write the data!\n"); fprintf(fp, "WriteMacroExit%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " mov edi, [cyclesRemaining]\n"); } else if (MZ80_C == bWhat) { fprintf(fp, " psIoWrite = cpu.z80IoWrite; /* Beginning of our handler */\n"); fprintf(fp, " while (psIoWrite->lowIoAddr != 0xffff)\n"); fprintf(fp, " {\n"); fprintf(fp, " if ((%s >= psIoWrite->lowIoAddr) && (%s <= psIoWrite->highIoAddr))\n", pszIoAddress, pszIoAddress); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = (UINTPTR) pbPC - (UINTPTR) cpu.z80Base;\n"); fprintf(fp, " psIoWrite->IOCall(%s, %s, psIoWrite);\n", pszIoAddress, pszValue); fprintf(fp, " psIoWrite = NULL;\n"); fprintf(fp, " break;\n"); fprintf(fp, " }\n"); fprintf(fp, " ++psIoWrite;\n"); fprintf(fp, " }\n\n"); } else { abort(); } ++dwGlobalLabel; } void ReadValueFromMemory(INT8 *pszAddress, INT8 *pszTarget) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov edi, [_z80MemRead] ; Point to the read array\n\n"); fprintf(fp, "checkLoop%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of the list?\n"); fprintf(fp, " je memoryRead%" PRIu32 "\n", dwGlobalLabel); fprintf(fp, " cmp e%s, [edi] ; Are we smaller?\n", pszAddress); fprintf(fp, " jb nextAddr%" PRIu32 " ; Yes, go to the next address\n", dwGlobalLabel); fprintf(fp, " cmp e%s, [edi+4] ; Are we bigger?\n", pszAddress); fprintf(fp, " jbe callRoutine%" PRIu32 "\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " add edi, 10h ; Next structure!\n"); fprintf(fp, " jmp short checkLoop%" PRIu32 "\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%" PRIu32 ":\n", dwGlobalLabel); if (strcmp(pszAddress, "dx") != 0) fprintf(fp, " mov dx, %s ; Get our address\n", pszAddress); fprintf(fp, " call ReadMemoryByte ; Standard read routine\n"); // Yes, these are intentionally reversed! if (strcmp(pszTarget, "al") == 0) fprintf(fp, " mov [_z80af], al ; Save our new accumulator\n"); else if (strcmp(pszTarget, "ah") == 0) fprintf(fp, " mov [_z80af + 1], al ; Save our new flags\n"); else fprintf(fp, " mov %s, al ; Put our returned value here\n", pszTarget); // And are properly restored HERE: fprintf(fp, " mov ax, [_z80af] ; Get our AF back\n"); // Restore registers here... fprintf(fp, " jmp short readExit%" PRIu32 "\n\n", dwGlobalLabel); fprintf(fp, "memoryRead%" PRIu32 ":\n", dwGlobalLabel); if (pszTarget[0] == 'b' && pszTarget[1] == 'y' && pszTarget[2] == 't') { fprintf(fp, " mov di, dx\n"); fprintf(fp, " mov dl, [ebp + e%s]\n", pszAddress); fprintf(fp, " mov %s, dl\n", pszTarget); fprintf(fp, " mov dx, di\n"); } else fprintf(fp, " mov %s, [ebp + e%s] ; Get our data\n\n", pszTarget, pszAddress); fprintf(fp, "readExit%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " mov edi, [cyclesRemaining]\n"); dwGlobalLabel++; } else if (MZ80_C == bWhat) { fprintf(fp, " psMemRead = cpu.z80MemRead; /* Beginning of our handler */\n"); fprintf(fp, " while (psMemRead->lowAddr != 0xffffffff)\n"); fprintf(fp, " {\n"); fprintf(fp, " if ((%s >= psMemRead->lowAddr) && (%s <= psMemRead->highAddr))\n", pszAddress, pszAddress); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = (UINTPTR) pbPC - (UINTPTR) cpu.z80Base;\n"); fprintf(fp, " if (psMemRead->memoryCall)\n"); fprintf(fp, " {\n"); fprintf(fp, " %s = psMemRead->memoryCall(%s, psMemRead);\n", pszTarget, pszAddress); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " %s = *((UINT8 *) psMemRead->pUserArea + (%s - psMemRead->lowAddr));\n", pszTarget, pszAddress); fprintf(fp, " }\n"); fprintf(fp, " psMemRead = NULL;\n"); fprintf(fp, " break;\n"); fprintf(fp, " }\n"); fprintf(fp, " ++psMemRead;\n"); fprintf(fp, " }\n\n"); fprintf(fp, " if (psMemRead)\n"); fprintf(fp, " {\n"); fprintf(fp, " %s = cpu.z80Base[%s];\n", pszTarget, pszAddress); fprintf(fp, " }\n\n"); } else { abort(); } } void ReadWordFromMemory(INT8 *pszAddress, INT8 *pszTarget) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov edi, [_z80MemRead] ; Point to the read array\n\n"); fprintf(fp, "checkLoop%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of the list?\n"); fprintf(fp, " je memoryRead%" PRIu32 "\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi] ; Are we smaller?\n", pszAddress); fprintf(fp, " jb nextAddr%" PRIu32 " ; Yes, go to the next address\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi+4] ; Are we bigger?\n", pszAddress); fprintf(fp, " jbe callRoutine%" PRIu32 "\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " add edi, 10h ; Next structure!\n"); fprintf(fp, " jmp short checkLoop%" PRIu32 "\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%" PRIu32 ":\n", dwGlobalLabel); if (strcmp(pszAddress, "dx") != 0) fprintf(fp, " mov dx, %s ; Get our address\n", pszAddress); if (strcmp(pszTarget, "ax") != 0) fprintf(fp, " push ax ; Save this for later\n"); fprintf(fp, " push dx ; Save address\n"); fprintf(fp, " call ReadMemoryByte ; Standard read routine\n"); fprintf(fp, " pop dx ; Restore our address\n"); fprintf(fp, " inc dx ; Next byte, please\n"); fprintf(fp, " push ax ; Save returned byte\n"); fprintf(fp, " call ReadMemoryByte ; Standard read routine\n"); fprintf(fp, " xchg ah, al ; Swap for endian's sake\n"); fprintf(fp, " pop dx ; Restore LSB\n"); fprintf(fp, " mov dh, ah ; Our word is now in DX\n"); // DX Now has our data and our address is toast if (strcmp(pszTarget, "ax") != 0) { fprintf(fp, " pop ax ; Restore this\n"); if (strcmp(pszTarget, "dx") != 0) { fprintf(fp, " mov %s, dx ; Store our word\n", pszTarget); } } else fprintf(fp, " mov ax, dx\n"); if (strcmp(pszTarget, "ax") == 0) { fprintf(fp, " xchg ah, al\n"); } fprintf(fp, " jmp readExit%" PRIu32 "\n\n", dwGlobalLabel); fprintf(fp, "memoryRead%" PRIu32 ":\n", dwGlobalLabel); if (strlen(pszTarget) == 2) { fprintf(fp, " mov %s, [ebp + e%s]\n", pszTarget, pszAddress); if (strcmp(pszTarget, "ax") == 0) { fprintf(fp, " xchg ah, al\n"); } } else { fprintf(fp, " mov dx, [ebp + e%s]\n", pszAddress); fprintf(fp, " mov %s, dx\n", pszTarget); } fprintf(fp, "readExit%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " mov edi, [cyclesRemaining]\n"); } else if (MZ80_C == bWhat) { fprintf(fp, " psMemRead = cpu.z80MemRead; /* Beginning of our handler */\n"); fprintf(fp, " while (psMemRead->lowAddr != 0xffffffff)\n"); fprintf(fp, " {\n"); fprintf(fp, " if ((%s >= psMemRead->lowAddr) && (%s <= psMemRead->highAddr))\n", pszAddress, pszAddress); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = (UINTPTR) pbPC - (UINTPTR) cpu.z80Base;\n"); fprintf(fp, " if (psMemRead->memoryCall)\n"); fprintf(fp, " {\n"); fprintf(fp, " %s = psMemRead->memoryCall(%s, psMemRead);\n", pszTarget, pszAddress); fprintf(fp, " %s |= (UINT32) ((UINT32) psMemRead->memoryCall(%s + 1, psMemRead) << 8);\n", pszTarget, pszAddress); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " %s = *((UINT8 *) psMemRead->pUserArea + (%s - psMemRead->lowAddr));\n", pszTarget, pszAddress); fprintf(fp, " %s |= (UINT32) ((UINT32) *((UINT8 *) psMemRead->pUserArea + (%s - psMemRead->lowAddr + 1)) << 8);\n", pszTarget, pszAddress); fprintf(fp, " }\n"); fprintf(fp, " psMemRead = NULL;\n"); fprintf(fp, " break;\n"); fprintf(fp, " }\n"); fprintf(fp, " ++psMemRead;\n"); fprintf(fp, " }\n\n"); fprintf(fp, " if (psMemRead)\n"); fprintf(fp, " {\n"); fprintf(fp, " %s = cpu.z80Base[%s];\n", pszTarget, pszAddress); fprintf(fp, " %s |= (UINT32) ((UINT32) cpu.z80Base[%s + 1] << 8);\n", pszTarget, pszAddress); fprintf(fp, " }\n\n"); } else { abort(); } dwGlobalLabel++; } void ReadValueFromIo(INT8 *pszIoAddress, INT8 *pszTarget) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov edi, [_z80IoRead] ; Point to the read array\n\n"); fprintf(fp, "checkLoop%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of the list?\n"); fprintf(fp, " je ioRead%" PRIu32 "\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi] ; Are we smaller?\n", pszIoAddress); fprintf(fp, " jb nextAddr%" PRIu32 " ; Yes, go to the next address\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi+2] ; Are we bigger?\n", pszIoAddress); fprintf(fp, " jbe callRoutine%" PRIu32 "\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " add edi, 0ch ; Next structure!\n"); fprintf(fp, " jmp short checkLoop%" PRIu32 "\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%" PRIu32 ":\n", dwGlobalLabel); if (strcmp(pszIoAddress, "dx") != 0) fprintf(fp, " mov dx, %s ; Get our address\n", pszIoAddress); fprintf(fp, " call ReadIOByte ; Standard read routine\n"); // Yes, these are intentionally reversed! if (strcmp(pszTarget, "al") == 0) fprintf(fp, " mov [_z80af], al ; Save our new accumulator\n"); else if (strcmp(pszTarget, "ah") == 0) fprintf(fp, " mov [_z80af + 1], ah ; Save our new flags\n"); else if (strcmp(pszTarget, "dl") == 0) fprintf(fp, " mov [_z80de], al ; Put it in E\n"); else if (strcmp(pszTarget, "dh") == 0) fprintf(fp, " mov [_z80de + 1], al ; Put it in D\n"); else if (strcmp(pszTarget, "*dl") == 0) fprintf(fp, " mov dl, al ; Put it in DL for later consumption\n"); else fprintf(fp, " mov %s, al ; Put our returned value here\n", pszTarget); // And are properly restored HERE: fprintf(fp, " mov ax, [_z80af] ; Get our AF back\n"); // Restore registers here... fprintf(fp, " jmp short readExit%" PRIu32 "\n\n", dwGlobalLabel); fprintf(fp, "ioRead%" PRIu32 ":\n", dwGlobalLabel); if (strcmp(pszTarget, "*dl") == 0) fprintf(fp, " mov dl, 0ffh ; An unreferenced read\n"); else fprintf(fp, " mov %s, 0ffh ; An unreferenced read\n", pszTarget); fprintf(fp, "readExit%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " mov edi, [cyclesRemaining]\n"); } else if (MZ80_C == bWhat) { fprintf(fp, " psIoRead = cpu.z80IoRead; /* Beginning of our handler */\n"); fprintf(fp, " while (psIoRead->lowIoAddr != 0xffff)\n"); fprintf(fp, " {\n"); fprintf(fp, " if ((%s >= psIoRead->lowIoAddr) && (%s <= psIoRead->highIoAddr))\n", pszIoAddress, pszIoAddress); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = (UINTPTR) pbPC - (UINTPTR) cpu.z80Base;\n"); fprintf(fp, " %s = psIoRead->IOCall(%s, psIoRead);\n", pszTarget, pszIoAddress); fprintf(fp, " psIoRead = NULL;\n"); fprintf(fp, " break;\n"); fprintf(fp, " }\n"); fprintf(fp, " ++psIoRead;\n"); fprintf(fp, " }\n\n"); fprintf(fp, " if (psIoRead)\n"); fprintf(fp, " {\n"); fprintf(fp, " %s = 0xff; /* Unclaimed I/O read */\n", pszTarget); fprintf(fp, " }\n\n"); } else { abort(); } dwGlobalLabel++; } // Basic instruction set area void MiscHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode == 0xe3) { if (bThroughCallHandler) { fprintf(fp, " call PopWord\n"); fprintf(fp, " xchg bx, [_wordval]\n"); fprintf(fp, " call PushWord\n"); } else { fprintf(fp, " mov dx, word [_z80sp]\n"); fprintf(fp, " xchg bx, [ebp+edx]\n"); fprintf(fp, " xor edx, edx\n"); } } if (dwOpcode == 0x2a) { fprintf(fp, " mov dx, [esi] ; Get address to load\n"); fprintf(fp, " add esi, 2 ; Skip over it so we don't execute it\n"); ReadWordFromMemory("dx", "bx"); fprintf(fp, " xor edx, edx\n"); } if (dwOpcode == 0xfb) { fprintf(fp, " or dword [_z80iff], IFF1 ; Indicate interrupts are enabled now\n"); fprintf(fp, " sub edi, 4 ; Takes 4 cycles!\n"); fprintf(fp, " mov [dwEITiming], edi ; Snapshot our current timing\n"); fprintf(fp, " mov [bEIExit], byte 1 ; Indicate we're exiting because of an EI\n"); fprintf(fp, " xor edi, edi ; Force next instruction to exit\n"); fprintf(fp, " mov dl, byte [esi] ; Get our next instruction\n"); fprintf(fp, " inc esi ; Next PC\n"); fprintf(fp, " jmp dword [z80regular+edx*4]\n\n"); } if (dwOpcode == 0xf9) fprintf(fp, " mov word [_z80sp], bx\n"); if (dwOpcode == 0xd9) { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov di, [_z80de]\n"); fprintf(fp, " xchg cx, [_z80bcprime]\n"); fprintf(fp, " xchg di, [_z80deprime]\n"); fprintf(fp, " xchg bx, [_z80hlprime]\n"); fprintf(fp, " mov [_z80de], di\n"); fprintf(fp, " mov edi, [cyclesRemaining]\n"); } if (dwOpcode == 0x76) { fprintf(fp, " mov dword [_z80halted], 1 ; We've halted the chip!\n"); if (FALSE == bNoTiming) { fprintf(fp, " xor edi, edi\n"); fprintf(fp, " mov [cyclesRemaining], edi\n"); } fprintf(fp, " jmp noMoreExec\n"); return; } if (dwOpcode == 0x3f) { fprintf(fp, " mov dl, ah\n"); fprintf(fp, " and dl, 01h\n"); fprintf(fp, " shl dl, 4\n"); fprintf(fp, " xor ah, 01h\n"); fprintf(fp, " and ah, 0edh\n"); fprintf(fp, " or ah, dl\n"); } if (dwOpcode == 0x37) { fprintf(fp, " or ah, 1\n"); fprintf(fp, " and ah,0edh\n"); } if (dwOpcode == 0x27) { fprintf(fp, " mov dh, ah\n"); fprintf(fp, " and dh, 02ah\n"); fprintf(fp, " test ah, 02h ; Were we doing a subtraction?\n"); fprintf(fp, " jnz handleNeg ; Nope!\n"); fprintf(fp, " sahf\n"); fprintf(fp, " daa\n"); fprintf(fp, " lahf\n"); fprintf(fp, " jmp short endDaa\n"); fprintf(fp, "handleNeg:\n"); fprintf(fp, " sahf\n"); fprintf(fp, " das\n"); fprintf(fp, " lahf\n"); fprintf(fp, "endDaa:\n"); fprintf(fp, " and ah, 0d5h\n"); fprintf(fp, " or ah, dh\n"); fprintf(fp, " xor edx, edx\n"); } if (dwOpcode == 0x08) { fprintf(fp, " xchg ah, al\n"); fprintf(fp, " xchg ax, [_z80afprime]\n"); fprintf(fp, " xchg ah, al\n"); } if (dwOpcode == 0x07) { fprintf(fp, " sahf\n"); fprintf(fp, " rol al, 1\n"); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0edh\n"); } if (dwOpcode == 0x0f) { fprintf(fp, " sahf\n"); fprintf(fp, " ror al, 1\n"); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0edh\n"); } if (dwOpcode == 0xe9) { fprintf(fp, " mov si, bx\n"); fprintf(fp, " and esi, 0ffffh\n"); fprintf(fp, " add esi, ebp\n"); } if (dwOpcode == 0xeb) fprintf(fp, " xchg [_z80de], bx ; Exchange DE & HL\n"); if (dwOpcode == 0x2f) { fprintf(fp, " not al\n"); fprintf(fp, " or ah, 012h ; N And H are now on!\n"); } if (dwOpcode == 0x10) // DJNZ { fprintf(fp, " mov dl, [esi] ; Get our relative offset\n"); fprintf(fp, " inc esi ; Next instruction, please!\n"); fprintf(fp, " dec ch ; Decrement B\n"); fprintf(fp, " jz noJump ; Don't take the jump if it's done!\n"); fprintf(fp, "; Otherwise, take the jump\n"); fprintf(fp, " sub edi, 5\n"); fprintf(fp, " xchg eax, edx\n"); fprintf(fp, " cbw\n"); fprintf(fp, " xchg eax, edx\n"); fprintf(fp, " sub esi, ebp\n"); fprintf(fp, " add si, dx\n"); fprintf(fp, " add esi, ebp\n"); fprintf(fp, "noJump:\n"); fprintf(fp, " xor edx, edx\n"); } if (dwOpcode == 0x3a) // LD A,(xxxx) { fprintf(fp, " mov dx, [esi] ; Get our address\n"); fprintf(fp, " add esi, 2 ; Skip past the address\n"); ReadValueFromMemory("dx", "al"); fprintf(fp, " xor edx, edx ; Make sure we don't hose things\n"); } if (dwOpcode == 0xf3) // DI { fprintf(fp, " and dword [_z80iff], (~IFF1) ; Not in an interrupt\n"); } FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode == 0x76) // HALT! { fprintf(fp, " cpu.z80halted = 1;\n"); fprintf(fp, " dwElapsedTicks += sdwCyclesRemaining;\n"); fprintf(fp, " sdwCyclesRemaining = 0;\n"); } else if (dwOpcode == 0x2f) // CPL { fprintf(fp, " cpu.z80A ^= 0xff;\n"); fprintf(fp, " cpu.z80F |= (Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY);\n"); } else if (dwOpcode == 0xd9) // EXX { fprintf(fp, " dwTemp = cpu.z80DE;\n"); fprintf(fp, " cpu.z80DE = cpu.z80deprime;\n"); fprintf(fp, " cpu.z80deprime = dwTemp;\n"); fprintf(fp, " dwTemp = cpu.z80BC;\n"); fprintf(fp, " cpu.z80BC = cpu.z80bcprime;\n"); fprintf(fp, " cpu.z80bcprime = dwTemp;\n"); fprintf(fp, " dwTemp = cpu.z80HL;\n"); fprintf(fp, " cpu.z80HL = cpu.z80hlprime;\n"); fprintf(fp, " cpu.z80hlprime = dwTemp;\n"); } else if (dwOpcode == 0xf9) // LD SP, HL { fprintf(fp, " cpu.z80sp = cpu.z80HL;\n"); } else if (dwOpcode == 0x27) // DAA { fprintf(fp, " dwAddr = (((cpu.z80F & Z80_FLAG_CARRY) | \n"); fprintf(fp, " ((cpu.z80F & Z80_FLAG_HALF_CARRY) >> 3) | \n"); fprintf(fp, " ((cpu.z80F & Z80_FLAG_NEGATIVE) << 1)) << 8) | cpu.z80A;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= (wDAATable[dwAddr] >> 8);\n"); fprintf(fp, " cpu.z80A = wDAATable[dwAddr] & 0xff;\n"); } else if (dwOpcode == 0x2a) { fprintf(fp, " dwAddr = *pbPC++;\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbPC++ << 8);\n"); ReadWordFromMemory("dwAddr", "cpu.z80HL"); } else if (dwOpcode == 0xe3) // EX (SP), HL { ReadWordFromMemory("cpu.z80sp", "dwAddr"); WriteWordToMemory("cpu.z80sp", "cpu.z80HL"); fprintf(fp, " cpu.z80HL = dwAddr;\n"); } else if (dwOpcode == 0xe9) // JP (HL) { fprintf(fp, " pbPC = cpu.z80Base + cpu.z80HL;\n"); } else if (0x08 == dwOpcode) // EX AF, AF' { fprintf(fp, " dwAddr = (UINT32) cpu.z80AF;\n"); fprintf(fp, " cpu.z80AF = cpu.z80afprime;\n"); fprintf(fp, " cpu.z80afprime = dwAddr;\n"); } else if (0xeb == dwOpcode) // EX DE, HL { fprintf(fp, " dwAddr = cpu.z80DE;\n"); fprintf(fp, " cpu.z80DE = cpu.z80HL;\n"); fprintf(fp, " cpu.z80HL = dwAddr;\n"); } else if (0x10 == dwOpcode) // DJNZ { fprintf(fp, " sdwAddr = (INT8) *pbPC++; /* Get LSB first */\n"); fprintf(fp, " if (--cpu.z80B)\n"); fprintf(fp, " {\n"); fprintf(fp, " dwElapsedTicks += 5; /* 5 More for jump taken */\n"); fprintf(fp, " cpu.z80pc = (UINTPTR) pbPC - (UINTPTR) cpu.z80Base;\n"); fprintf(fp, " sdwAddr = (sdwAddr + (INT32) cpu.z80pc) & 0xffff;\n"); fprintf(fp, " pbPC = cpu.z80Base + sdwAddr; /* Normalize the address */\n"); fprintf(fp, " }\n"); } else if (0x37 == dwOpcode) // SCF { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_CARRY;\n"); } else if (0x3f == dwOpcode) // CCF { fprintf(fp, " bTemp = (cpu.z80F & Z80_FLAG_CARRY) << 4;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F ^= Z80_FLAG_CARRY;\n"); } else if (0x07 == dwOpcode) // RLCA { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY);\n"); fprintf(fp, " cpu.z80F |= (cpu.z80A >> 7);\n"); fprintf(fp, " cpu.z80A = (cpu.z80A << 1) | (cpu.z80A >> 7);\n"); } else if (0x0f == dwOpcode) // RRCA { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY);\n"); fprintf(fp, " cpu.z80F |= (cpu.z80A & Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80A = (cpu.z80A >> 1) | (cpu.z80A << 7);\n"); } else if (0x3a == dwOpcode) // LD A, (xxxxh) { fprintf(fp, " dwTemp = *pbPC++;\n"); fprintf(fp, " dwTemp |= (((UINT32) *pbPC++) << 8);\n"); ReadValueFromMemory("dwTemp", "cpu.z80A"); } else if (0xf3 == dwOpcode) // DI { fprintf(fp, " cpu.z80iff &= (~IFF1);\n"); } else if (0xfb == dwOpcode) // EI { fprintf(fp, " cpu.z80iff |= IFF1;\n"); } else if (0x00 == dwOpcode) // NOP { fprintf(fp, " /* Intentionally not doing anything - NOP! */\n"); } else { InvalidInstructionC(1); } } else { abort(); } } void LdRegPairImmediate(UINT32 dwOpcode) { UINT8 bOp = 0; bOp = (dwOpcode >> 4) & 0x3; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (bOp == 0) fprintf(fp, " mov cx, [esi] ; Get our immediate value of BC\n"); else if (bOp == 2) fprintf(fp, " mov bx, [esi] ; Get our immediate value of HL\n"); else if (bOp == 1) { fprintf(fp, " mov dx, [esi] ; Get our immediate value of DE\n"); fprintf(fp, " mov word [_z80de], dx ; Store DE\n"); fprintf(fp, " xor edx, edx\n"); } else if (bOp == 3) { fprintf(fp, " mov dx, [esi] ; Get our immediate value of SP\n"); fprintf(fp, " mov word [_z80sp], dx ; Store it!\n"); fprintf(fp, " xor edx, edx\n"); } fprintf(fp, " add esi, 2\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " %s = *pbPC++; /* LSB First */\n", pbRegPairC[bOp]); fprintf(fp, " %s |= (((UINT32) *pbPC++ << 8)); /* Now the MSB */\n", pbRegPairC[bOp]); } else { abort(); } } void LdRegpairPtrByte(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode == 0x36) // Immediate into (HL) WriteValueToMemory("bx", "[esi]"); if (dwOpcode == 0x12) WriteValueToMemory("[_z80de]", "al"); // (DE), A if (dwOpcode == 0x2) // (BC), A WriteValueToMemory("cx", "al"); if (dwOpcode >= 0x70 && dwOpcode < 0x78) WriteValueToMemory("bx", pbMathReg[dwOpcode & 0x07]); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode == 0x36) WriteValueToMemory("cpu.z80HL", "*pbPC++"); if (dwOpcode == 0x12) WriteValueToMemory("cpu.z80DE", "cpu.z80A"); if (dwOpcode == 0x02) WriteValueToMemory("cpu.z80BC", "cpu.z80A"); if (dwOpcode >= 0x70 && dwOpcode < 0x78) WriteValueToMemory("cpu.z80HL", pbMathRegC[dwOpcode & 0x07]); } else { abort(); } } void MathOperation(UINT32 dwOrgOpcode) { UINT8 bRegister; UINT32 dwOpcode; INT8 tempstr[150]; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOrgOpcode); dwOpcode = dwOrgOpcode; bRegister = dwOpcode & 0x07; dwOpcode &= 0xf8; if (dwOpcode == 0x80) strcpy(tempstr, "add"); if (dwOpcode == 0x88) strcpy(tempstr, "adc"); if (dwOpcode == 0x90) strcpy(tempstr, "sub"); if (dwOpcode == 0x98) strcpy(tempstr, "sbb"); if (dwOpcode == 0xa0) strcpy(tempstr, "and"); if (dwOpcode == 0xa8) strcpy(tempstr, "xor"); if (dwOpcode == 0xb0) strcpy(tempstr, "or"); if (dwOpcode == 0xb8) strcpy(tempstr, "cmp"); // Let's see if we have to deal with (HL) or #xxh if (bRegister == 0x6) { // We have to deal with (HL) ReadValueFromMemory("bx", "dl"); } if (bRegister != 0x06 && bRegister < 0xff) { fprintf(fp, " sahf\n"); fprintf(fp, " %s al, %s\n", tempstr, pbMathReg[bRegister]); fprintf(fp, " lahf\n"); } else // If it's (HL).... { fprintf(fp, " sahf\n"); fprintf(fp, " %s al, dl\n", tempstr); fprintf(fp, " lahf\n"); } if (dwOpcode != 0xa8 && dwOpcode != 0xa0 && dwOpcode != 0xb0) SetOverflow(); if (dwOpcode == 0xa8) fprintf(fp, " and ah, 0ech ; Only these flags matter!\n"); if (dwOpcode == 0xa0) { fprintf(fp, " and ah, 0ech ; Only these flags matter!\n"); fprintf(fp, " or ah, 010h ; Half carry gets set\n"); } if (dwOpcode == 0xb0) fprintf(fp, " and ah, 0ech ; No H, N, or C\n"); if (dwOpcode == 0xb8) fprintf(fp, " or ah, 02h ; Set N for compare!\n"); if (dwOpcode == 0x80 || dwOpcode == 0x88) fprintf(fp, " and ah, 0fdh ; No N!\n"); if (dwOpcode == 0x90 || dwOpcode == 0x98) fprintf(fp, " or ah, 02h ; N Gets set!\n"); if (bRegister == 0x6) fprintf(fp, " xor edx, edx ; Zero this...\n"); FetchNextInstruction(dwOrgOpcode); } else if (MZ80_C == bWhat) { dwOpcode = dwOrgOpcode; bRegister = dwOpcode & 0x07; dwOpcode &= 0xf8; if (6 == bRegister) // Deal with (HL) { ReadValueFromMemory("cpu.z80HL", "bTemp"); } if (dwOpcode == 0xa0) { fprintf(fp, " cpu.z80A &= %s;\n", pbMathRegC[bRegister]); } else if (dwOpcode == 0xa8) { fprintf(fp, " cpu.z80A ^= %s;\n", pbMathRegC[bRegister]); } else if (dwOpcode == 0xb0) { fprintf(fp, " cpu.z80A |= %s;\n", pbMathRegC[bRegister]); } else if (dwOpcode == 0xb8) { // Don't do anything. We just do flags! } else if (dwOpcode == 0x88) // ADC { fprintf(fp, " bTemp2 = cpu.z80A + %s + (cpu.z80F & Z80_FLAG_CARRY);\n", pbMathRegC[bRegister]); } else if (dwOpcode == 0x90) // SUB { fprintf(fp, " bTemp2 = cpu.z80A - %s;\n", pbMathRegC[bRegister]); } else if (dwOpcode == 0x80) // ADD { fprintf(fp, " bTemp2 = cpu.z80A + %s;\n", pbMathRegC[bRegister]); } else if (dwOpcode == 0x98) // SBC { fprintf(fp, " bTemp2 = cpu.z80A - %s - (cpu.z80F & Z80_FLAG_CARRY);\n", pbMathRegC[bRegister]); } else { InvalidInstructionC(1); } // Now do flag fixup if (0xb0 == dwOpcode || 0xa8 == dwOpcode) { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } if (0xa0 == dwOpcode) { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostANDFlags[cpu.z80A];\n\n"); } if (0xb8 == dwOpcode || 0x90 == dwOpcode) { SetSubFlagsSZHVC("cpu.z80A", pbMathRegC[bRegister]); if (0x90 == dwOpcode) { fprintf(fp, " cpu.z80A = bTemp2;\n"); } } if (0x80 == dwOpcode) // Add fixup { SetAddFlagsSZHVC("cpu.z80A", pbMathRegC[bRegister]); fprintf(fp, " cpu.z80A = bTemp2;\n"); } if (0x88 == dwOpcode) // Adc fixup { SetAdcFlagsSZHVC("cpu.z80A", pbMathRegC[bRegister]); fprintf(fp, " cpu.z80A = bTemp2;\n"); } if (0x98 == dwOpcode) // Sbc fixup { SetSbcFlagsSZHVC("cpu.z80A", pbMathRegC[bRegister]); fprintf(fp, " cpu.z80A = bTemp2;\n"); } } else { abort(); } } void RegIntoMemory(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [esi] ; Get our address to write to\n"); fprintf(fp, " add esi, 2 ; Next address, please...\n"); if (0x32 == dwOpcode) // LD (xxxx), A WriteValueToMemory("dx", "al"); if (0x22 == dwOpcode) // LD (xxxx), HL { WriteWordToMemory("dx", "bx"); } fprintf(fp, " xor edx, edx ; Zero our upper byte\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " dwTemp = *pbPC++;\n"); fprintf(fp, " dwTemp |= ((UINT32) *pbPC++ << 8);\n"); if (0x32 == dwOpcode) WriteValueToMemory("dwTemp", "cpu.z80A"); if (0x22 == dwOpcode) WriteWordToMemory("dwTemp", "cpu.z80HL"); return; } else { abort(); } } void JpHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (0xc3 == dwOpcode) // If it's a straight jump... { fprintf(fp, " mov si, [esi] ; Get our new address\n"); fprintf(fp, " and esi, 0ffffh ; Only the lower 16 bits\n"); fprintf(fp, " add esi, ebp ; Our new address!\n"); } else // It's a conditional handler... { fprintf(fp, " sahf ; Restore our flags\n"); fprintf(fp, " j%s takeJump%" PRIu32 " ; We're going to take a jump\n", pbFlags[(dwOpcode >> 3) & 0x07], dwGlobalLabel); fprintf(fp, " add esi, 2 ; Skip past the address\n"); fprintf(fp, " jmp short nextInst%" PRIu32 " ; Go execute the next instruction\n", dwGlobalLabel); fprintf(fp, "takeJump%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " mov si, [esi] ; Get our new offset\n"); fprintf(fp, " and esi, 0ffffh ; Only the lower WORD is valid\n"); fprintf(fp, " add esi, ebp ; Our new address!\n"); fprintf(fp, "nextInst%" PRIu32 ":\n", dwGlobalLabel); ++dwGlobalLabel; } FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " dwAddr = *pbPC++; /* Get LSB first */\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */\n"); if (0xc3 != dwOpcode) { fprintf(fp, " if %s\n", pbFlagsC[(dwOpcode >> 3) & 0x07]); fprintf(fp, " {\n"); fprintf(fp, " pbPC = cpu.z80Base + dwAddr; /* Normalize the address */\n"); fprintf(fp, " }\n"); } else // Regular jump here { fprintf(fp, " pbPC = cpu.z80Base + dwAddr; /* Normalize the address */\n"); } } else { abort(); } } void LdRegImmediate(UINT32 dwOpcode) { UINT8 bOp; bOp = (dwOpcode >> 3) & 0x7; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (bOp != 2 && bOp != 3) fprintf(fp, " mov %s, [esi] ; Get our immediate value\n", pbMathReg[bOp]); else { fprintf(fp, " mov dl, [esi] ; Get our immediate value\n"); fprintf(fp, " mov %s, dl ; Store our new value\n", pbMathReg[bOp]); } fprintf(fp, " inc esi\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " %s = *pbPC++; /* Get immediate byte into register */\n", pbMathRegC[bOp]); } else { abort(); } } void IncRegister(UINT32 dwOpcode) { UINT32 dwOpcode1 = 0; dwOpcode1 = (dwOpcode >> 3) & 0x07; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " sahf\n"); fprintf(fp, " inc %s\n", pbMathReg[dwOpcode1]); fprintf(fp, " lahf\n"); SetOverflow(); fprintf(fp, " and ah, 0fdh ; Knock out N!\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp ," cpu.z80F |= bPostIncFlags[%s++];\n", pbMathRegC[dwOpcode1]); } else { abort(); } } void DecRegister(UINT32 dwOpcode) { UINT32 dwOpcode1 = 0; dwOpcode1 = (dwOpcode >> 3) & 0x07; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " sahf\n"); fprintf(fp, " dec %s\n", pbMathReg[dwOpcode1]); fprintf(fp, " lahf\n"); SetOverflow(); fprintf(fp, " or ah, 02h ; Set negative!\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY);\n"); fprintf(fp ," cpu.z80F |= bPostDecFlags[%s--];\n", pbMathRegC[dwOpcode1]); } else { abort(); } } void IncDecRegpair(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if ((dwOpcode & 0x0f) == 3) // Increment? fprintf(fp, " inc %s\n", pbRegPairs[(dwOpcode >> 4) & 0x03]); else fprintf(fp, " dec %s\n", pbRegPairs[(dwOpcode >> 4) & 0x03]); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if ((dwOpcode & 0x0f) == 3) // Increment fprintf(fp, " %s++;\n", pbRegPairC[(dwOpcode >> 4) & 0x03]); else fprintf(fp, " %s--;\n", pbRegPairC[(dwOpcode >> 4) & 0x03]); fprintf(fp, " %s &= 0xffff;\n", pbRegPairC[(dwOpcode >> 4) & 0x03]); } else { abort(); } } void LdRegReg(UINT32 dwOpcode) { UINT8 bDestination; UINT8 bSource; bDestination = (dwOpcode >> 3) & 0x07; bSource = (dwOpcode) & 0x07; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (bSource != bDestination) { if (bSource == 2 && bDestination == 3) { fprintf(fp, " mov dl, byte [_z80de + 1]\n"); fprintf(fp, " mov [_z80de], dl\n"); } else if (bSource == 3 && bDestination == 2) { fprintf(fp, " mov dl, byte [_z80de]\n"); fprintf(fp, " mov [_z80de + 1], dl\n"); } else fprintf(fp, " mov %s, %s\n", pbMathReg[bDestination], pbMathReg[bSource]); } FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (bDestination != bSource) { fprintf(fp, " %s = %s;\n", pbMathRegC[bDestination], pbMathRegC[bSource]); } } else { abort(); } } void MathOperationDirect(UINT32 dwOpcode) { INT8 tempstr[4]; if (MZ80_ASSEMBLY_X86 == bWhat) { if (dwOpcode == 0xc6) strcpy(tempstr, "add"); if (dwOpcode == 0xce) strcpy(tempstr, "adc"); if (dwOpcode == 0xd6) strcpy(tempstr, "sub"); if (dwOpcode == 0xde) strcpy(tempstr, "sbb"); if (dwOpcode == 0xe6) strcpy(tempstr, "and"); if (dwOpcode == 0xee) strcpy(tempstr, "xor"); if (dwOpcode == 0xf6) strcpy(tempstr, "or"); if (dwOpcode == 0xfe) strcpy(tempstr, "cmp"); ProcBegin(dwOpcode); // Let's see if we have to deal with (HL) or #xxh fprintf(fp, " sahf\n"); fprintf(fp, " %s al, [esi]\n", tempstr); fprintf(fp, " lahf\n"); if (dwOpcode != 0xee && dwOpcode != 0xe6 && dwOpcode != 0xf6) { SetOverflow(); } if (dwOpcode == 0xe6) { fprintf(fp, " and ah, 0ech ; Only parity, half carry, sign, zero\n"); fprintf(fp, " or ah, 10h ; Half carry\n"); } if (dwOpcode == 0xc6 || dwOpcode == 0xce) fprintf(fp, " and ah, 0fdh ; Knock out N!\n"); if (dwOpcode == 0xd6 || dwOpcode == 0xde || dwOpcode == 0xfe) fprintf(fp, " or ah, 02h ; Set negative!\n"); if (dwOpcode == 0xf6 || dwOpcode == 0xee) fprintf(fp, " and ah, 0ech ; No H, N, or C\n"); fprintf(fp, " inc esi\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0xfe == dwOpcode) // Cp { SetSubFlagsSZHVC("cpu.z80A", "*pbPC++"); } else if (0xe6 == dwOpcode) // And { fprintf(fp, " cpu.z80A &= *pbPC++;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostANDFlags[cpu.z80A];\n\n"); } else if (0xf6 == dwOpcode) // Or { fprintf(fp, " cpu.z80A |= *pbPC++;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } else if (0xc6 == dwOpcode) // Add { fprintf(fp, " bTemp = *pbPC++;\n"); SetAddFlagsSZHVC("cpu.z80A", "bTemp"); fprintf(fp, " cpu.z80A += bTemp;\n"); } else if (0xce == dwOpcode) // Adc { fprintf(fp, " bTemp = *pbPC++ + (cpu.z80F & Z80_FLAG_CARRY);\n"); SetAdcFlagsSZHVC("cpu.z80A", "bTemp"); fprintf(fp, " cpu.z80A += bTemp;\n"); } else if (0xd6 == dwOpcode) // Sub { fprintf(fp, " bTemp = *pbPC++;\n"); SetSubFlagsSZHVC("cpu.z80A", "bTemp"); fprintf(fp, " cpu.z80A -= bTemp;\n"); } else if (0xde == dwOpcode) // Sbc { fprintf(fp, " bTemp = *pbPC++ + (cpu.z80F & Z80_FLAG_CARRY);\n"); SetSbcFlagsSZHVC("cpu.z80A", "bTemp"); fprintf(fp, " cpu.z80A = cpu.z80A - bTemp;\n"); } else if (0xee == dwOpcode) // Xor { fprintf(fp, " cpu.z80A ^= *pbPC++;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } else InvalidInstructionC(1); } else { abort(); } } // JR cc, addr void JrHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " sub esi, ebp\n"); fprintf(fp, " and esi, 0ffffh\n"); fprintf(fp, " add esi, ebp\n"); fprintf(fp, " mov dl, [esi] ; Get our relative offset\n"); fprintf(fp, " inc esi ; Next instruction, please!\n"); if (dwOpcode != 0x18) { fprintf(fp, " sahf\n"); fprintf(fp, " j%s takeJump%" PRIu32 "\n", pbFlags[(dwOpcode >> 3) & 0x3], dwGlobalLabel); fprintf(fp, " jmp short noJumpMan%" PRIu32 "\n", dwGlobalLabel); fprintf(fp, "takeJump%" PRIu32 ":\n", dwGlobalLabel); if (FALSE == bNoTiming) { fprintf(fp, " sub edi, 5\n"); } } else // It's a JR { fprintf(fp, " cmp dl, 0feh ; Jump to self?\n"); fprintf(fp, " je yesJrMan ; Yup! Bail out!\n"); } fprintf(fp, " xchg eax, edx\n"); fprintf(fp, " cbw\n"); fprintf(fp, " xchg eax, edx\n"); fprintf(fp, " sub esi, ebp\n"); fprintf(fp, " add si, dx\n"); fprintf(fp, " and esi, 0ffffh ; Only the lower 16 bits\n"); fprintf(fp, " add esi, ebp\n"); fprintf(fp, " xor dh, dh\n"); fprintf(fp, "noJumpMan%" PRIu32 ":\n", dwGlobalLabel++); FetchNextInstruction(dwOpcode); if (0x18 == dwOpcode) { fprintf(fp,"yesJrMan:\n"); fprintf(fp, " xor edx, edx ; Zero me for later\n"); fprintf(fp, " mov edi, edx\n"); fprintf(fp, " mov [cyclesRemaining], edx\n"); fprintf(fp, " sub esi, 2 ; Back to the instruction again\n"); fprintf(fp, " jmp noMoreExec\n\n"); } } else if (MZ80_C == bWhat) { fprintf(fp, " sdwAddr = (INT8) *pbPC++; /* Get LSB first */\n"); fprintf(fp, " cpu.z80pc = (UINTPTR) pbPC - (UINTPTR) cpu.z80Base;\n"); fprintf(fp, " sdwAddr = (sdwAddr + (INT32) cpu.z80pc) & 0xffff;\n"); if (0x18 != dwOpcode) { fprintf(fp, " if %s\n", pbFlagsC[(dwOpcode >> 3) & 0x03]); } fprintf(fp, " {\n"); fprintf(fp, " sdwCyclesRemaining -= 5;\n"); fprintf(fp, " pbPC = cpu.z80Base + sdwAddr; /* Normalize the address */\n"); fprintf(fp, " }\n"); } else { abort(); } } void CallHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode != 0xcd) { fprintf(fp, " sahf ; Restore our flags\n"); fprintf(fp, " j%s takeJump%" PRIu32 " ; We're going call in this case\n", pbFlags[(dwOpcode >> 3) & 0x07], dwGlobalLabel); fprintf(fp, " add esi, 2 ; Skip past the address\n"); fprintf(fp, " jmp short noCallTaken%" PRIu32 " ; Go execute the next instruction\n", dwGlobalLabel); fprintf(fp, "takeJump%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " sub edi, 7\n"); } if (bThroughCallHandler) { fprintf(fp, " mov dx, [esi] ; Get our call to address\n"); fprintf(fp, " mov [_z80pc], dx ; Store our new program counter\n"); fprintf(fp, " add esi, 2 ; Skip to our new address to be pushed\n"); fprintf(fp, " sub esi, ebp ; Value to push onto the \"stack\"\n"); fprintf(fp, " mov [_wordval], si ; Store our return address on the stack\n"); fprintf(fp, " mov si, dx ; Our new address\n"); fprintf(fp, " add esi, ebp ; And our base address\n"); fprintf(fp, " call PushWord ; Go push our orgval to the stack\n"); } else { fprintf(fp, " mov dx, [esi] ; Get our call to address\n"); fprintf(fp, " mov [_z80pc], dx ; Store our new program counter\n"); fprintf(fp, " add esi, 2 ; Skip to our new address to be pushed\n"); fprintf(fp, " sub esi, ebp ; Value to push onto the \"stack\"\n"); fprintf(fp, " mov dx, word [_z80sp] ; Get the current stack pointer\n"); fprintf(fp, " sub dx, 2 ; Back up two bytes\n"); fprintf(fp, " mov [ebp+edx], si ; PUSH It!\n"); fprintf(fp, " mov word [_z80sp], dx ; Store our new stack pointer\n"); fprintf(fp, " mov si, [_z80pc] ; Get our new program counter\n"); fprintf(fp, " add esi, ebp ; Naturalize it!\n"); } if (dwOpcode != 0xcd) fprintf(fp, "noCallTaken%" PRIu32 ":\n", dwGlobalLabel++); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " dwAddr = *pbPC++; /* Get LSB first */\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbPC++ << 8); /* Get MSB last */\n"); if (0xcd != dwOpcode) { fprintf(fp, " if %s\n", pbFlagsC[(dwOpcode >> 3) & 0x07]); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = (UINTPTR) pbPC - (UINTPTR) cpu.z80Base;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */\n"); fprintf(fp, " *pbSP-- = cpu.z80pc >> 8; /* MSB */\n"); fprintf(fp, " *pbSP = (UINT8) cpu.z80pc; /* LSB */\n"); fprintf(fp, " cpu.z80sp -= 2; /* Back our stack up */\n"); fprintf(fp, " pbPC = cpu.z80Base + dwAddr; /* Normalize the address */\n"); fprintf(fp, " }\n"); } else // Just a regular call { fprintf(fp, " cpu.z80pc = (UINTPTR) pbPC - (UINTPTR) cpu.z80Base;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */\n"); fprintf(fp, " *pbSP-- = cpu.z80pc >> 8; /* LSB */\n"); fprintf(fp, " *pbSP = (UINT8) cpu.z80pc; /* MSB */\n"); fprintf(fp, " cpu.z80sp -= 2; /* Back our stack up */\n"); fprintf(fp, " pbPC = cpu.z80Base + dwAddr; /* Normalize the address */\n"); } } else { abort(); } } void RetHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode != 0xc9) { fprintf(fp, " sahf\n"); fprintf(fp, " j%s takeReturn%" PRIu32 "\n", pbFlags[(dwOpcode >> 3) & 0x07], dwGlobalLabel); fprintf(fp, " jmp short retNotTaken%" PRIu32 "\n", dwGlobalLabel); fprintf(fp, "takeReturn%" PRIu32 ":\n", dwGlobalLabel); if (FALSE == bNoTiming) { fprintf(fp, " sub edi, byte 6\n"); } } if (bThroughCallHandler) { fprintf(fp, " call PopWord\n"); fprintf(fp, " xor esi, esi\n"); fprintf(fp, " mov si, dx\n"); fprintf(fp, " add esi, ebp\n"); fprintf(fp, " xor edx, edx\n"); } else { fprintf(fp, " mov dx, word [_z80sp] ; Get our current stack pointer\n"); fprintf(fp, " mov si, [edx+ebp] ; Get our return address\n"); fprintf(fp, " and esi, 0ffffh ; Only within 64K!\n"); fprintf(fp, " add esi, ebp ; Add in our base address\n"); fprintf(fp, " add word [_z80sp], 02h ; Remove our two bytes from the stack\n"); fprintf(fp, " xor edx, edx\n"); } if (dwOpcode != 0xc9) fprintf(fp, "retNotTaken%" PRIu32 ":\n", dwGlobalLabel++); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode != 0xc9) { fprintf(fp, " if %s\n", pbFlagsC[(dwOpcode >> 3) & 0x07]); fprintf(fp, " {\n"); fprintf(fp, " dwElapsedTicks += 6;\n"); } fprintf(fp, " pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */\n"); fprintf(fp, " dwAddr = *pbSP++; /* Pop LSB */\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */\n"); fprintf(fp, " cpu.z80sp += 2; /* Pop the word off */\n"); fprintf(fp, " pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */\n"); if (dwOpcode != 0xc9) { fprintf(fp, " }\n"); } } else { abort(); } } void RestartHandler(UINT32 dwOpcode) { UINT32 dwOpcode1 = 0; dwOpcode1 = dwOpcode & 0x38; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (bThroughCallHandler) { fprintf(fp, " sub esi, ebp\n"); fprintf(fp, " mov [_wordval], si ; Store our return address\n"); fprintf(fp, " call PushWord\n"); fprintf(fp, " xor esi, esi\n"); fprintf(fp, " mov si, %.4" PRIx32 "h\n", dwOpcode1); fprintf(fp, " add esi, ebp\n"); } else { fprintf(fp, " mov dx, word [_z80sp] ; Get our stack pointer\n"); fprintf(fp, " sub dx, 2 ; Make room for the new value!\n"); fprintf(fp, " mov word [_z80sp], dx ; Store our new stack pointer\n"); fprintf(fp, " sub esi, ebp ; Get our real PC\n"); fprintf(fp, " mov [ebp+edx], si ; Our return address\n"); fprintf(fp, " mov si, 0%.2xh ; Our new call address\n", dwOpcode1); fprintf(fp, " add esi, ebp ; Back to the base!\n"); } fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " cpu.z80pc = (UINTPTR) pbPC - (UINTPTR) cpu.z80Base;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */\n"); fprintf(fp, " *pbSP-- = cpu.z80pc >> 8; /* LSB */\n"); fprintf(fp, " *pbSP = (UINT8) cpu.z80pc; /* MSB */\n"); fprintf(fp, " cpu.z80sp -= 2; /* Back our stack up */\n"); fprintf(fp, " pbPC = cpu.z80Base + 0x%.2x; /* Normalize the address */\n", dwOpcode1); } else { abort(); } } void ToRegFromHl(UINT32 dwOpcode) { UINT8 bReg; bReg = (dwOpcode >> 3) & 0x07; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (bReg != 2 && bReg != 3) ReadValueFromMemory("bx", pbMathReg[bReg]); else { ReadValueFromMemory("bx", pbLocalReg[bReg]); fprintf(fp, " mov %s, %s\n", pbMathReg[bReg], pbLocalReg[bReg]); } fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { ReadValueFromMemory("cpu.z80HL", pbLocalRegC[bReg]); } else { abort(); } } void AddRegpairOperations(UINT32 dwOpcode) { UINT8 bRegpair; bRegpair = (dwOpcode >> 4) & 0x3; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dh, ah ; Get our flags\n"); fprintf(fp, " and dh, 0ech ; Preserve the top three and bits 2 & 3\n"); fprintf(fp, " mov [_orgval], bx ; Store our original value\n"); fprintf(fp, " add bx, %s\n", pbRegPairs[bRegpair]); fprintf(fp, " lahf\n"); fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov di, [_orgval] ; Get original\n"); fprintf(fp, " xor di, bx ; XOR It with our computed value\n"); fprintf(fp, " xor di, %s\n", pbRegPairs[bRegpair]); fprintf(fp, " and di, 1000h ; Just our half carry\n"); fprintf(fp, " or dx, di ; Or in our flags\n"); fprintf(fp, " and ah, 01h ; Just carry\n"); fprintf(fp, " or ah, dh\n"); fprintf(fp, " mov edi, [cyclesRemaining]\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY);\n"); fprintf(fp, " dwTemp = cpu.z80HL + %s;\n", pbRegPairsC[bRegpair]); fprintf(fp, " cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((cpu.z80HL ^ dwTemp ^ %s) >> 8) & Z80_FLAG_HALF_CARRY);\n", pbRegPairsC[bRegpair]); fprintf(fp, " cpu.z80HL = dwTemp & 0xffff;\n"); return; } else { abort(); } } void PushPopOperations(UINT32 dwOpcode) { UINT8 bRegPair; bRegPair = ((dwOpcode >> 4) & 0x3) << 1; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if ((dwOpcode & 0xcf) == 0xc5) // Push { fprintf(fp, " sub word [_z80sp], 2\n"); fprintf(fp, " mov dx, [_z80sp]\n"); WriteWordToMemory("dx", pbPopRegPairs[bRegPair >> 1]); } else // Pop { fprintf(fp, " mov dx, [_z80sp]\n"); ReadWordFromMemory("dx", pbPopRegPairs[bRegPair >> 1]); fprintf(fp, " add word [_z80sp], 2\n"); } fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if ((dwOpcode & 0xcf) == 0xc5) // Push? { fprintf(fp, " cpu.z80sp -= 2;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */\n"); WriteWordToMemory("cpu.z80sp", pbPopRegPairC[bRegPair >> 1]); return; } else { ReadWordFromMemory("cpu.z80sp", pbPopRegPairC[bRegPair >> 1]); fprintf(fp, " cpu.z80sp += 2;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */\n"); return; } InvalidInstructionC(1); } else { abort(); } } void RraRlaHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " sahf\n"); if (dwOpcode == 0x1f) fprintf(fp, " rcr al, 1\n"); else fprintf(fp, " rcl al, 1\n"); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0edh\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0x1f == dwOpcode) // RRA { fprintf(fp, " bTemp = (cpu.z80F & Z80_FLAG_CARRY) << 7;\n"); fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY)) | (cpu.z80A & Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80A = ((cpu.z80A >> 1) | bTemp);\n"); } else // RLA { fprintf(fp, " bTemp = cpu.z80A >> 7;\n"); fprintf(fp, " cpu.z80A = (cpu.z80A << 1) | (cpu.z80F & Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY)) | bTemp;\n"); } } else { abort(); } } void LdByteRegpair(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode == 0x0a) ReadValueFromMemory("cx", "al"); if (dwOpcode == 0x1a) { fprintf(fp, " mov dx, [_z80de]\n"); ReadValueFromMemory("dx", "al"); } fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode == 0x0a) ReadValueFromMemory("cpu.z80BC", "cpu.z80A"); if (dwOpcode == 0x1a) ReadValueFromMemory("cpu.z80DE", "cpu.z80A"); } else { abort(); } } void IncDecHLPtr(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); ReadValueFromMemory("bx", "dl"); fprintf(fp, " sahf\n"); if (dwOpcode == 0x34) fprintf(fp, " inc dl\n"); else fprintf(fp, " dec dl\n"); fprintf(fp, " lahf\n"); fprintf(fp, " o16 pushf\n"); fprintf(fp, " shl edx, 16\n"); fprintf(fp, " and ah, 0fbh ; Knock out parity/overflow\n"); fprintf(fp, " pop dx\n"); fprintf(fp, " and dh, 08h ; Just the overflow\n"); fprintf(fp, " shr dh, 1 ; Shift it into position\n"); fprintf(fp, " or ah, dh ; OR It in with the real flags\n"); fprintf(fp, " shr edx, 16\n"); if (dwOpcode == 0x34) fprintf(fp, " and ah, 0fdh ; Knock out N!\n"); else fprintf(fp, " or ah, 02h ; Make it N!\n"); WriteValueToMemory("bx", "dl"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { ReadValueFromMemory("cpu.z80HL", "bTemp"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); if (0x34 == dwOpcode) fprintf(fp ," cpu.z80F |= bPostIncFlags[bTemp];\n"); else fprintf(fp ," cpu.z80F |= bPostDecFlags[bTemp];\n"); if (0x34 == dwOpcode) fprintf(fp, " bTemp++;\n"); else fprintf(fp, " bTemp--;\n"); WriteValueToMemory("cpu.z80HL", "bTemp"); return; } else { abort(); } } void InOutHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dl, [esi] ; Get our address to 'out' to\n"); fprintf(fp, " inc esi ; Next address\n"); if (b16BitIo) { fprintf(fp, " mov dh, al ; Upper 8 bits are the A register for 16 bit addressing\n"); } if (0xd3 == dwOpcode) WriteValueToIo("dx", "al"); else ReadValueFromIo("dx", "al"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp ," dwTemp = *pbPC++;\n"); if (0xd3 == dwOpcode) WriteValueToIo("dwTemp", "cpu.z80A"); else ReadValueFromIo("dwTemp", "cpu.z80A"); // Not supposed to set flags for immediate instruction! return; } else { abort(); } } // CB Area void RESSETHandler(UINT32 dwOpcode) { UINT8 op = 0; op = dwOpcode & 0x07; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if ((2 == op) || (3 == op)) fprintf(fp, " mov dx, [_z80de] ; Move DE into something half usable\n"); if ((dwOpcode & 0x07) == 6) // (HL)? ReadValueFromMemory("bx", "dl"); if ((dwOpcode & 0xc0) == 0x80) fprintf(fp, " and %s, 0%.2xh ; Reset a bit\n", pbLocalReg[op], 0xff - (1 << ((dwOpcode >> 3) & 0x7))); if ((dwOpcode & 0xc0) == 0xc0) fprintf(fp, " or %s, 0%.2xh ; Set a bit\n", pbLocalReg[op], (1 << ((dwOpcode >> 3) & 0x7))); if ((2 == op) || (3 == op)) { fprintf(fp, " mov [_z80de], dx ; Once modified, put it back\n"); fprintf(fp, " xor edx, edx\n"); } if ((dwOpcode & 0x07) == 6) // (HL)? { WriteValueToMemory("bx", "dl"); fprintf(fp, " xor edx, edx\n"); } FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (6 == op) // (HL)? ReadValueFromMemory("cpu.z80HL", "bTemp"); if ((dwOpcode & 0xc0) == 0x80) // RES fprintf(fp, " %s &= 0x%.2x;\n", pbMathRegC[op], (UINT8) ~((UINT8) 1 << ((dwOpcode >> 3) & 0x07))); else // SET fprintf(fp, " %s |= 0x%.2x;\n", pbMathRegC[op], 1 << ((dwOpcode >> 3) & 0x07)); if (6 == op) // (HL)? WriteValueToMemory("cpu.z80HL", "bTemp"); } else abort(); } void BITHandler(UINT32 dwOpcode) { UINT8 op = 0; UINT8 bBitVal = 0; op = dwOpcode & 0x07; bBitVal = 1 << ((dwOpcode >> 3) & 0x07); if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if ((dwOpcode & 0x07) == 6) // (HL)? ReadValueFromMemory("bx", "dl"); fprintf(fp, " mov byte [_z80af], ah ; Store F\n"); fprintf(fp, " sahf\n"); if ((dwOpcode & 0x07) == 6) fprintf(fp, " test dl, 0%.2xh ; Do a bitwise check\n", 1 << ((dwOpcode >> 3) & 0x7)); else fprintf(fp, " test %s, 0%.2xh ; Do a bitwise check\n", pbMathReg[op], 1 << ((dwOpcode >> 3) & 0x7)); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0c0h ; Only care about Z and S\n"); fprintf(fp, " or ah, 10h ; Set half carry to 1\n"); fprintf(fp, " and byte [_z80af], 029h ; Only zero/non-zero!\n"); fprintf(fp, " or ah, byte [_z80af] ; Put it in with the real flags\n"); if (6 == (dwOpcode & 0x07)) // (HL)? fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (6 == op) // (HL)? ReadValueFromMemory("cpu.z80HL", "bTemp"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO);\n"); fprintf(fp, " cpu.z80F |= (Z80_FLAG_HALF_CARRY);\n"); fprintf(fp, " if (!(%s & 0x%.2" PRIx32 "))\n", pbMathRegC[op], bBitVal); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_ZERO;\n"); fprintf(fp, " }\n"); } else abort(); } void RLCRRCRLRRSLASRASRLHandler(UINT32 dwOpcode) { UINT8 op = 0; op = dwOpcode & 0x07; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if ((2 == op) || (3 == op)) fprintf(fp, " mov dx, [_z80de] ; Move DE into something half usable\n"); if ((dwOpcode & 0x07) == 6) // (HL)? ReadValueFromMemory("bx", "dl"); fprintf(fp, " sahf\n"); if ((dwOpcode & 0xf8) == 0) fprintf(fp, " rol %s, 1\n", pbLocalReg[op]); else if ((dwOpcode & 0xf8) == 0x08) fprintf(fp, " ror %s, 1\n", pbLocalReg[op]); else if ((dwOpcode & 0xf8) == 0x10) fprintf(fp, " rcl %s, 1\n", pbLocalReg[op]); else if ((dwOpcode & 0xf8) == 0x18) fprintf(fp, " rcr %s, 1\n", pbLocalReg[op]); else if ((dwOpcode & 0xf8) == 0x20 || (dwOpcode & 0xf8) == 0x30) fprintf(fp, " shl %s, 1\n", pbLocalReg[op]); else if ((dwOpcode & 0xf8) == 0x28) fprintf(fp, " sar %s, 1\n", pbLocalReg[op]); else if ((dwOpcode & 0xf8) == 0x38) fprintf(fp, " shr %s, 1\n", pbLocalReg[op]); else abort(); fprintf(fp, " lahf\n"); if ((dwOpcode & 0xf8) >= 0x20) { if ((dwOpcode & 0xf8) == 0x30) fprintf(fp, " or %s, 1 ; Slide in a 1 bit (SLIA)\n", pbLocalReg[op]); fprintf(fp, " and ah, 0edh ; Clear H and N\n"); } else { fprintf(fp, " and ah, 029h ; Clear H and N\n"); fprintf(fp, " mov byte [_z80af], ah\n"); fprintf(fp, " or %s, %s\n", pbLocalReg[op], pbLocalReg[op]); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0c4h ; Sign, zero, and parity\n"); fprintf(fp, " or ah, byte [_z80af]\n"); } if ((2 == op) || (3 == op)) { fprintf(fp, " mov [_z80de], dx ; Once modified, put it back\n"); fprintf(fp, " xor edx, edx\n"); } if ((dwOpcode & 0x07) == 6) // (HL)? { WriteValueToMemory("bx", "dl"); fprintf(fp, " xor edx, edx\n"); } FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (6 == op) // (HL)? ReadValueFromMemory("cpu.z80HL", "bTemp"); dwOpcode &= 0xf8; // Just the instruction if (0 == dwOpcode) // RLC { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " bTemp2 = (%s >> 7);\n", pbMathRegC[op]); fprintf(fp, " %s = (%s << 1) | bTemp2;\n", pbMathRegC[op], pbMathRegC[op]); fprintf(fp, " cpu.z80F |= bTemp2 | bPostORFlags[%s];\n", pbMathRegC[op]); } else if (0x08 == dwOpcode) // RRC { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (%s & Z80_FLAG_CARRY);\n", pbMathRegC[op]); fprintf(fp, " %s = (%s >> 1) | (%s << 7);\n", pbMathRegC[op], pbMathRegC[op], pbMathRegC[op]); fprintf(fp, " cpu.z80F |= bPostORFlags[%s];\n", pbMathRegC[op]); } else if (0x10 == dwOpcode) // RL { fprintf(fp, " bTemp2 = cpu.z80F & Z80_FLAG_CARRY;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (%s >> 7);\n", pbMathRegC[op]); fprintf(fp, " %s = (%s << 1) | bTemp2;\n", pbMathRegC[op], pbMathRegC[op]); fprintf(fp, " cpu.z80F |= bPostORFlags[%s];\n", pbMathRegC[op]); } else if (0x18 == dwOpcode) // RR { fprintf(fp, " bTemp2 = (cpu.z80F & Z80_FLAG_CARRY) << 7;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (%s & Z80_FLAG_CARRY);\n", pbMathRegC[op]); fprintf(fp, " %s = (%s >> 1) | bTemp2;\n", pbMathRegC[op], pbMathRegC[op]); fprintf(fp, " cpu.z80F |= bPostORFlags[%s];\n", pbMathRegC[op]); } else if ((0x20 == dwOpcode) || (0x30 == dwOpcode)) // SLA/SRL { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (%s >> 7);\n", pbMathRegC[op]); fprintf(fp, " %s = (%s << 1);\n", pbMathRegC[op], pbMathRegC[op]); fprintf(fp, " cpu.z80F |= bPostORFlags[%s];\n", pbMathRegC[op]); } else if (0x28 == dwOpcode) // SRA { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (%s & Z80_FLAG_CARRY);\n", pbMathRegC[op]); fprintf(fp, " %s = (%s >> 1) | (%s & 0x80);\n", pbMathRegC[op], pbMathRegC[op], pbMathRegC[op]); fprintf(fp, " cpu.z80F |= bPostORFlags[%s];\n", pbMathRegC[op]); } else if (0x38 == dwOpcode) // SRL { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (%s & Z80_FLAG_CARRY);\n", pbMathRegC[op]); fprintf(fp, " %s = (%s >> 1);\n", pbMathRegC[op], pbMathRegC[op]); fprintf(fp, " cpu.z80F |= bPostORFlags[%s];\n", pbMathRegC[op]); } else { InvalidInstructionC(2); } if (6 == op) // (HL)? WriteValueToMemory("cpu.z80HL", "bTemp"); } else abort(); } // ED Area void RRDRLDHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); ReadValueFromMemory("bx", "dl"); // Get (HL) fprintf(fp, " mov dh, dl ; Put a copy in DH\n"); if (0x6f == dwOpcode) // RLD { fprintf(fp, " shr dh, 4 ; Get our upper nibble in position\n"); fprintf(fp, " shl dl, 4 ; Get our lower nibble into the higher position\n"); fprintf(fp, " shl ecx, 16 ; Save this for later\n"); fprintf(fp, " mov cl, al\n"); fprintf(fp, " and cl, 0fh\n ; Only the lower nibble\n"); fprintf(fp, " or dl, cl ; OR In A->(HL) transfer\n"); fprintf(fp, " and al, 0f0h ; Only the upper 4 bits remain\n"); fprintf(fp, " or al, dh ; OR It in to our accumulator\n"); fprintf(fp, " shr ecx, 16 ; Restore this\n"); } else // RRD if (0x67 == dwOpcode) { fprintf(fp, " shr dl, 4 ; Upper nibble to lower nibble\n"); fprintf(fp, " shl ecx, 16 ; Save this\n"); fprintf(fp, " mov cl, al\n"); fprintf(fp, " shl cl, 4\n"); fprintf(fp, " or dl, cl ; OR In what was in A\n"); fprintf(fp, " and al, 0f0h ; Knock out lower part\n"); fprintf(fp, " and dh, 0fh ; Only the lower nibble\n"); fprintf(fp, " or al, dh ; OR In our nibble\n"); fprintf(fp, " shr ecx, 16 ; Restore this\n"); } else // Whoops! abort(); // This routine assumes that the new value to be placed at (HL) is in DL fprintf(fp, " and ah, 29h ; Retain carry & two undefined bits\n"); fprintf(fp, " mov dh, ah ; Store our flags away for later\n"); fprintf(fp, " or al, al ; Get our flags\n"); fprintf(fp, " lahf\n"); fprintf(fp, " and ah,0c4h ; Only partiy, zero, and sign\n"); fprintf(fp, " or ah, dh ; OR In our old flags\n"); // Now go write the value back WriteValueToMemory("bx", "dl"); fprintf(fp, " xor edx, edx ; Zero out this for later\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0x67 == dwOpcode) // RRD { ReadValueFromMemory("cpu.z80HL", "bTemp"); fprintf(fp, " bTemp2 = (cpu.z80A & 0x0f) << 4;\n"); fprintf(fp, " cpu.z80A = (cpu.z80A & 0xf0) | (bTemp & 0x0f);\n"); fprintf(fp, " bTemp = (bTemp >> 4) | bTemp2;\n"); WriteValueToMemory("cpu.z80HL", "bTemp"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n"); } else if (0x6f == dwOpcode) // RLD { ReadValueFromMemory("cpu.z80HL", "bTemp"); fprintf(fp, " bTemp2 = (cpu.z80A & 0x0f);\n"); fprintf(fp, " cpu.z80A = (cpu.z80A & 0xf0) | (bTemp >> 4);\n"); fprintf(fp, " bTemp = (bTemp << 4) | bTemp2;\n"); WriteValueToMemory("cpu.z80HL", "bTemp"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n"); } else InvalidInstructionC(2); } else abort(); } void CPICPDCPIRCPDRHandler(UINT32 dwOpcode) { UINT32 dwRepeatOb = 0; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode == 0xb1 || dwOpcode == 0xb9) { fprintf(fp, "cpRepeat%" PRIu32 ":\n", dwGlobalLabel); dwRepeatOb = dwGlobalLabel; ++dwGlobalLabel; } // Now go get the data from the source ReadValueFromMemory("bx", "dl"); // Target data is in DL fprintf(fp, " mov byte [_z80af], ah\n"); fprintf(fp, " sahf\n"); fprintf(fp, " cmp al, dl ; Do our comparison\n"); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0fah ; No P/V or carry!\n"); fprintf(fp, " dec cx ; Dec BC\n"); fprintf(fp, " jz notBcZero%" PRIu32 "\n", dwGlobalLabel); fprintf(fp, " or ah, 04h ; P/V set when BC not zero\n"); fprintf(fp, "notBcZero%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " or ah, 02h ; N Gets set when we do compares\n"); fprintf(fp, " mov dl, byte [_z80af]\n"); fprintf(fp, " and dl, 01h\n"); fprintf(fp, " or ah, dl ; Preserve carry!\n"); if (dwOpcode == 0xa1 || dwOpcode == 0xb1) fprintf(fp, " inc bx ; Increment!\n"); if (dwOpcode == 0xa9 || dwOpcode == 0xb9) fprintf(fp, " dec bx ; Decrement!\n"); // Let's see if we repeat... if (dwOpcode == 0xb1 || dwOpcode == 0xb9) { fprintf(fp, " sahf\n"); fprintf(fp, " jz BCDone%" PRIu32 "\n", dwRepeatOb); fprintf(fp, " jnp BCDone%" PRIu32 "\n", dwRepeatOb); if (FALSE == bNoTiming) { fprintf(fp, " sub edi, dword 21\n"); fprintf(fp, " js BCDoneExit%" PRIu32 "\n", dwRepeatOb); } fprintf(fp, " jmp cpRepeat%" PRIu32 "\n", dwRepeatOb); fprintf(fp, "BCDoneExit%" PRIu32 ":\n", dwRepeatOb); fprintf(fp, " sub esi, 2 ; Back up to the instruction again\n"); fprintf(fp, " jmp noMoreExec\n\n"); fprintf(fp, "BCDone%" PRIu32 ":\n", dwRepeatOb); } fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0xb1 == dwOpcode || 0xb9 == dwOpcode) // Repeat instruction? { fprintf(fp, " while ((sdwCyclesRemaining >= 0) && (cpu.z80BC))\n"); } fprintf(fp, " {\n"); ReadValueFromMemory("cpu.z80HL", "bTemp"); if (0xb1 == dwOpcode || 0xa1 == dwOpcode) { fprintf(fp, " cpu.z80HL++;\n"); fprintf(fp, " cpu.z80HL &= 0xffff;\n"); } else { fprintf(fp, " cpu.z80HL--;\n"); fprintf(fp, " cpu.z80HL &= 0xffff;\n"); } fprintf(fp, " cpu.z80BC--;\n"); fprintf(fp, " cpu.z80BC &= 0xffff;\n"); if (0xb1 == dwOpcode || 0xb9 == dwOpcode) // Repeat? { fprintf(fp, " sdwCyclesRemaining -= 16;\n"); fprintf(fp, " if (cpu.z80A == bTemp)\n"); fprintf(fp, " {\n"); fprintf(fp, " break;\n"); fprintf(fp, " }\n"); } fprintf(fp, " }\n"); // Now figure out what's going on fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= (pbSubSbcTable[((UINT32) cpu.z80A << 8) | bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO));\n"); fprintf(fp, " if (cpu.z80BC)\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY;\n"); fprintf(fp, " }\n"); } else abort(); } void INIRINDRINIINDHandler(UINT32 dwOpcode) { UINT32 dwTempLabel = 0; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); dwTempLabel = dwGlobalLabel; dwGlobalLabel++; if (0xba == dwOpcode || 0xb2 == dwOpcode) fprintf(fp, "loopIt%" PRIu32 ":\n", dwTempLabel); // Fetch what's at (C) and put it in (HL) fprintf(fp, " push cx ; Save BC\n"); if (b16BitIo == FALSE) fprintf(fp, " xor ch, ch ; We want 8 bit ports\n"); ReadValueFromIo("cx", "*dl"); // Put our value in DL fprintf(fp, " pop cx ; Restore BC\n"); WriteValueToMemory("bx", "dl"); if (0xa2 == dwOpcode || 0xb2 == dwOpcode) fprintf(fp, " inc bx ; Increment HL\n"); else if (0xaa == dwOpcode || 0xba == dwOpcode) fprintf(fp, " dec bx ; Decrement HL\n"); // Now we decrement B fprintf(fp, " dec ch ; Decrement B (of C)\n"); // Emit this instruction if we repeat if (0xba == dwOpcode || 0xb2 == dwOpcode) { fprintf(fp, " jz near finalExit%" PRIu32 "\n", dwTempLabel); // Otherwise, we need to loop again if (FALSE == bNoTiming) { fprintf(fp, " sub edi, dword 21\n"); fprintf(fp, " js loopExit%" PRIu32 "\n", dwTempLabel); } fprintf(fp, " jmp loopIt%" PRIu32 "\n\n", dwTempLabel); fprintf(fp, "loopExit%" PRIu32 ":\n", dwTempLabel); fprintf(fp, " sub esi, 2\n"); fprintf(fp, " jmp noMoreExec\n\n"); } // Now let's fix up the flags fprintf(fp, "finalExit%" PRIu32 ":\n", dwTempLabel); fprintf(fp, " jnz clearFlag%" PRIu32 "\n", dwTempLabel); fprintf(fp, " or ah, 040h ; Set the Zero flag!\n"); fprintf(fp, " jmp short continue%" PRIu32 "\n", dwTempLabel); fprintf(fp, "clearFlag%" PRIu32 ":\n", dwTempLabel); fprintf(fp, " and ah, 0bfh ; Clear the zero flag\n"); fprintf(fp, "continue%" PRIu32 ":\n", dwTempLabel); fprintf(fp, " or ah, 02h ; Set negative!\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0xb2 == dwOpcode || 0xba == dwOpcode) // Repeat instruction? { fprintf(fp, " while ((sdwCyclesRemaining > 0) && (cpu.z80B))\n"); } fprintf(fp, " {\n"); ReadValueFromIo("cpu.z80B", "bTemp"); WriteValueToMemory("cpu.z80HL", "bTemp"); if (0xb2 == dwOpcode || 0xa2 == dwOpcode) { fprintf(fp, " cpu.z80HL++;\n"); fprintf(fp, " cpu.z80HL &= 0xffff;\n"); } else { fprintf(fp, " cpu.z80HL--;\n"); fprintf(fp, " cpu.z80HL &= 0xffff;\n"); } fprintf(fp, " sdwCyclesRemaining -= 16;\n"); fprintf(fp, " cpu.z80B--;\n"); fprintf(fp, " }\n"); // Now figure out what's going on fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= (bPostORFlags[bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY));\n"); fprintf(fp, " if (cpu.z80B)\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY;\n"); fprintf(fp, " pbPC -= 2;\n"); fprintf(fp, " }\n"); } else abort(); } void OTIROTDROUTIOUTDHandler(UINT32 dwOpcode) { UINT32 dwTempLabel = 0; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); dwTempLabel = dwGlobalLabel; dwGlobalLabel++; if (0xbb == dwOpcode || 0xb3 == dwOpcode) fprintf(fp, "loopIt%" PRIu32 ":\n", dwTempLabel); // Fetch what's at (HL) and put it in DL ReadValueFromMemory("bx", "dl"); fprintf(fp, " push cx ; Save BC\n"); if (b16BitIo == FALSE) fprintf(fp, " xor ch, ch ; No 16 bit for this instruction!\n"); WriteValueToIo("cx", "dl"); fprintf(fp, " pop cx ; Restore BC now that it has been \"OUT\"ed\n"); if (0xa3 == dwOpcode || 0xb3 == dwOpcode) fprintf(fp, " inc bx ; Increment HL\n"); else if (0xab == dwOpcode || 0xbb == dwOpcode) fprintf(fp, " dec bx ; Decrement HL\n"); // Now we decrement B fprintf(fp, " dec ch ; Decrement B (of C)\n"); // Emit this instruction if we repeat if (0xbb == dwOpcode || 0xb3 == dwOpcode) { fprintf(fp, " jz near finalExit%" PRIu32 "\n", dwTempLabel); // Otherwise, we need to loop again if (FALSE == bNoTiming) { fprintf(fp, " sub edi, dword 21\n"); fprintf(fp, " js loopExit%" PRIu32 "\n", dwTempLabel); } fprintf(fp, " jmp loopIt%" PRIu32 "\n\n", dwTempLabel); fprintf(fp, "loopExit%" PRIu32 ":\n", dwTempLabel); fprintf(fp, " sub esi, 2\n"); fprintf(fp, " jmp noMoreExec\n\n"); } // Now let's fix up the flags fprintf(fp, "finalExit%" PRIu32 ":\n", dwTempLabel); fprintf(fp, " jnz clearFlag%" PRIu32 "\n", dwTempLabel); fprintf(fp, " or ah, 040h ; Set the Zero flag!\n"); fprintf(fp, " jmp short continue%" PRIu32 "\n", dwTempLabel); fprintf(fp, "clearFlag%" PRIu32 ":\n", dwTempLabel); fprintf(fp, " and ah, 0bfh ; Clear the zero flag\n"); fprintf(fp, "continue%" PRIu32 ":\n", dwTempLabel); fprintf(fp, " or ah, 02h ; Set negative!\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0xb3 == dwOpcode || 0xbb == dwOpcode) // Repeat instruction? { fprintf(fp, " while ((sdwCyclesRemaining > 0) && (cpu.z80B))\n"); } fprintf(fp, " {\n"); ReadValueFromMemory("cpu.z80HL", "bTemp"); WriteValueToIo("cpu.z80BC", "bTemp"); if (0xb3 == dwOpcode || 0xa3 == dwOpcode) { fprintf(fp, " cpu.z80HL++;\n"); fprintf(fp, " cpu.z80HL &= 0xffff;\n"); } else { fprintf(fp, " cpu.z80HL--;\n"); fprintf(fp, " cpu.z80HL &= 0xffff;\n"); } fprintf(fp, " sdwCyclesRemaining -= 16;\n"); fprintf(fp, " cpu.z80B--;\n"); fprintf(fp, " }\n"); // Now figure out what's going on fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= (bPostORFlags[bTemp] & (Z80_FLAG_SIGN | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY));\n"); fprintf(fp, " if (cpu.z80B)\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY;\n"); fprintf(fp, " }\n"); } else abort(); } void AdcSbcRegpair(UINT32 dwOpcode) { UINT8 bOp = 0; bOp = (dwOpcode >> 4) & 0x03; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, %s ; Get our original register\n", pbRegPairs[bOp]); fprintf(fp, " mov [_orgval], dx ; Store this for later half carry computation\n"); fprintf(fp, " mov [_orgval2], bx ; Store this, too\n"); fprintf(fp, " sahf ; Restore our flags\n"); if ((dwOpcode & 0xcf) == 0x4a) fprintf(fp, " adc bx, dx ; Do the operation!\n"); else fprintf(fp, " sbb bx, dx ; Do the operation!\n"); fprintf(fp, " lahf ; Get our new flags\n"); if ((dwOpcode & 0xcf) != 0x4a) { SetOverflow(); fprintf(fp, " and ah, 0edh ; Knock out negative & half carry flags\n"); fprintf(fp, " or ah, 02h ; Negative!\n"); fprintf(fp, " mov [_z80hl], bx\n"); fprintf(fp, " xor bx, [_orgval]\n"); fprintf(fp, " xor bx, [_orgval2]\n"); fprintf(fp, " and bh, 10h ; Half carry?\n"); fprintf(fp, " or ah, bh ; OR It in if so\n"); fprintf(fp, " mov bx, [_z80hl]\n"); } else { SetOverflow(); fprintf(fp, " and ah, 0edh ; Knock out negative & half carry flags\n"); fprintf(fp, " mov [_z80hl], bx\n"); fprintf(fp, " xor bx, [_orgval]\n"); fprintf(fp, " xor bx, [_orgval2]\n"); fprintf(fp, " and bh, 10h ; Half carry?\n"); fprintf(fp, " or ah, bh ; OR It in if so\n"); fprintf(fp, " mov bx, [_z80hl]\n"); } fprintf(fp, " xor edx, edx ; Make sure we don't hose things\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if ((dwOpcode & 0xcf) == 0x4a) // ADC { fprintf(fp, " dwTemp = cpu.z80HL + %s + (cpu.z80F & Z80_FLAG_CARRY);\n", pbRegPairsC[bOp]); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= ((dwTemp >> 8) & Z80_FLAG_SIGN);\n"); fprintf(fp, " if (0 == (dwTemp & 0xffff))\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_ZERO;\n"); fprintf(fp, " }\n"); fprintf(fp, " cpu.z80F |= (((cpu.z80HL ^ dwTemp ^ %s) >> 8) & Z80_FLAG_HALF_CARRY);\n", pbRegPairsC[bOp]); fprintf(fp, " cpu.z80F |= ((((%s ^ cpu.z80HL ^ 0x8000) & (%s ^ dwTemp)) >> 13) & Z80_FLAG_OVERFLOW_PARITY);\n", pbRegPairsC[bOp], pbRegPairsC[bOp]); fprintf(fp, " cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80HL = dwTemp & 0xffff;\n"); return; } else // SBC { fprintf(fp, " dwTemp = cpu.z80HL - %s - (cpu.z80F & Z80_FLAG_CARRY);\n", pbRegPairsC[bOp]); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= ((dwTemp >> 8) & Z80_FLAG_SIGN);\n"); fprintf(fp, " if (0 == (dwTemp & 0xffff))\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_ZERO;\n"); fprintf(fp, " }\n"); fprintf(fp, " cpu.z80F |= (((cpu.z80HL ^ dwTemp ^ %s) >> 8) & Z80_FLAG_HALF_CARRY);\n", pbRegPairsC[bOp]); fprintf(fp, " cpu.z80F |= ((((%s ^ cpu.z80HL) & (%s ^ dwTemp)) >> 13) & Z80_FLAG_OVERFLOW_PARITY);\n", pbRegPairsC[bOp], pbRegPairsC[bOp]); fprintf(fp, " cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80HL = dwTemp & 0xffff;\n"); return; } } else abort(); } void RetIRetNHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (bThroughCallHandler) { fprintf(fp, " call PopWord\n"); fprintf(fp, " xor esi, esi\n"); fprintf(fp, " mov si, dx\n"); fprintf(fp, " add esi, ebp\n"); } else { fprintf(fp, " mov dx, word [_z80sp] ; Get our current stack pointer\n"); fprintf(fp, " mov si, [edx+ebp] ; Get our return address\n"); fprintf(fp, " and esi, 0ffffh ; Only within 64K!\n"); fprintf(fp, " add esi, ebp ; Add in our base address\n"); fprintf(fp, " add word [_z80sp], 02h ; Remove our two bytes from the stack\n"); } if (dwOpcode == 0x45) { fprintf(fp, " xor edx, edx\n"); fprintf(fp, " mov dl, [_z80iff] ; Get interrupt flags\n"); fprintf(fp, " shr dl, 1 ; Move IFF2->IFF1\n"); fprintf(fp, " and [_z80iff], dword (~IFF1) ; Get rid of IFF 1\n"); fprintf(fp, " and dl, IFF1 ; Just want the IFF 1 value now\n"); fprintf(fp, " or dword [_z80iff], edx\n"); } fprintf(fp, " xor edx, edx ; Make sure we don't hose things\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0x4d == dwOpcode) // RETI { fprintf(fp, " pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */\n"); fprintf(fp, " dwAddr = *pbSP++; /* Pop LSB */\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */\n"); fprintf(fp, " cpu.z80sp += 2; /* Pop the word off */\n"); fprintf(fp, " pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */\n"); } else if (0x45 == dwOpcode) // RETN { fprintf(fp, " pbSP = cpu.z80Base + cpu.z80sp; /* Normalize our stack PTR */\n"); fprintf(fp, " dwAddr = *pbSP++; /* Pop LSB */\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbSP << 8); /* Pop MSB */\n"); fprintf(fp, " cpu.z80sp += 2; /* Pop the word off */\n"); fprintf(fp, " pbPC = (cpu.z80Base + dwAddr); /* Point PC to our return address */\n"); fprintf(fp, " cpu.z80iff &= ~(IFF1); /* Keep IFF2 around */\n"); fprintf(fp, " cpu.z80iff |= ((cpu.z80iff >> 1) & IFF1); /* IFF2->IFF1 */\n"); } else { InvalidInstructionC(2); } } else abort(); } void ExtendedOutHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (b16BitIo == FALSE) fprintf(fp, " mov dl, cl ; Address in DX... (C)\n"); else fprintf(fp, " mov dx, cx ; Address in DX... (BC)\n"); WriteValueToIo("dx", pbMathReg[(dwOpcode >> 3) & 0x07]); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (b16BitIo == FALSE) fprintf(fp, " dwAddr = cpu.z80C;\n"); else fprintf(fp, " dwAddr = cpu.z80BC;\n"); WriteValueToIo("dwAddr", pbMathRegC[(dwOpcode >> 3) & 0x07]); } else abort(); } void ExtendedInHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (b16BitIo == FALSE) fprintf(fp, " mov dl, cl ; Address in DX... (C)\n"); else fprintf(fp, " mov dx, cx ; Address in DX... (BC)\n"); ReadValueFromIo("dx", pbMathReg[(dwOpcode >> 3) & 0x07]); fprintf(fp, ";\n; Remember, this variant of the IN instruction modifies the flags\n;\n\n"); fprintf(fp, " sahf ; Restore our flags\n"); fprintf(fp, " mov dh, ah ; Save flags for later\n"); if (0x50 == dwOpcode || 0x58 == dwOpcode) { fprintf(fp, " mov dl, %s\n", pbMathReg[(dwOpcode >> 3) & 0x07]); fprintf(fp, " or dl, dl\n"); } else fprintf(fp, " or %s, %s;\n", pbMathReg[(dwOpcode >> 3) & 0x07], pbMathReg[(dwOpcode >> 3) & 0x07]); fprintf(fp, " lahf\n"); fprintf(fp, " and dh, 029h ; Only keep carry and two unused flags\n"); fprintf(fp, " and ah, 0d4h\n"); fprintf(fp, " or ah, dh\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (b16BitIo == FALSE) fprintf(fp, " dwAddr = cpu.z80C;\n"); else fprintf(fp, " dwAddr = cpu.z80BC;\n"); ReadValueFromIo("dwAddr", pbMathRegC[(dwOpcode >> 3) & 0x07]); // Set flags! fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[%s];\n", pbMathRegC[(dwOpcode >> 3) & 0x07]); } else abort(); } void NegHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " sahf\n"); fprintf(fp, " sub dh, al\n"); fprintf(fp, " lahf\n"); fprintf(fp, " mov al, dh\n"); SetOverflow(); fprintf(fp, " or ah, 02h\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { SetSubFlagsSZHVC("0", "cpu.z80A"); fprintf(fp, " cpu.z80A = 0 - cpu.z80A;\n"); } else abort(); } void ExtendedRegIntoMemory(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [esi] ; Get our address to write to\n"); fprintf(fp, " add esi, 2 ; Next address, please...\n"); if (dwOpcode == 0x43) WriteValueToMemory("dx", "cl"); if (dwOpcode == 0x53) WriteValueToMemory("dx", "byte [_z80de]"); if (dwOpcode == 0x63) WriteValueToMemory("dx", "bl"); if (dwOpcode == 0x73) WriteValueToMemory("dx", "byte [_z80sp]"); fprintf(fp, " inc dx\n"); if (dwOpcode == 0x43) WriteValueToMemory("dx", "ch"); if (dwOpcode == 0x53) WriteValueToMemory("dx", "byte [_z80de + 1]"); if (dwOpcode == 0x63) WriteValueToMemory("dx", "bh"); if (dwOpcode == 0x73) WriteValueToMemory("dx", "byte [_z80sp + 1]"); fprintf(fp, " xor edx, edx ; Zero our upper word\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " dwTemp = *pbPC++;\n"); fprintf(fp, " dwTemp |= ((UINT32) *pbPC++ << 8);\n"); if (0x43 == dwOpcode) // LD (xxxxh), BC WriteWordToMemory("dwTemp", "cpu.z80BC"); if (0x53 == dwOpcode) // LD (xxxxh), DE WriteWordToMemory("dwTemp", "cpu.z80DE"); if (0x63 == dwOpcode) // LD (xxxxh), HL WriteWordToMemory("dwTemp", "cpu.z80HL"); if (0x73 == dwOpcode) // LD (xxxxh), SP WriteWordToMemory("dwTemp", "cpu.z80sp"); } else abort(); } void LdRegpair(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [esi] ; Get address to load\n"); fprintf(fp, " add esi, 2 ; Skip over it so we don't execute it\n"); if (dwOpcode == 0x4b) ReadValueFromMemory("dx", "cl"); if (dwOpcode == 0x5b) ReadValueFromMemory("dx", "byte [_z80de]"); if (dwOpcode == 0x7b) ReadValueFromMemory("dx", "byte [_z80sp]"); fprintf(fp, " inc dx\n"); if (dwOpcode == 0x4b) ReadValueFromMemory("dx", "ch"); if (dwOpcode == 0x5b) ReadValueFromMemory("dx", "byte [_z80de + 1]"); if (dwOpcode == 0x7b) ReadValueFromMemory("dx", "byte [_z80sp + 1]"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " dwTemp = *pbPC++;\n"); fprintf(fp, " dwTemp |= ((UINT32) *pbPC++ << 8);\n"); if (0x4b == dwOpcode) ReadWordFromMemory("dwTemp", "cpu.z80BC"); if (0x5b == dwOpcode) ReadWordFromMemory("dwTemp", "cpu.z80DE"); if (0x7b == dwOpcode) ReadWordFromMemory("dwTemp", "cpu.z80sp"); } else abort(); } void LDILDRLDIRLDDRHandler(UINT32 dwOpcode) { UINT32 dwOrgGlobal = 0; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode == 0xb0 || dwOpcode == 0xb8) { dwOrgGlobal = dwGlobalLabel; fprintf(fp, "ldRepeat%" PRIu32 ":\n", dwGlobalLabel); } ReadValueFromMemory("bx", "dl"); // Here we write the byte back to the target WriteValueToMemory("[_z80de]", "dl"); // Now we decide what to do if ((dwOpcode & 0x0f) == 0) { fprintf(fp, " inc bx ; Increment HL\n"); fprintf(fp, " inc word [_z80de] ; Increment DE\n"); } else { fprintf(fp, " dec bx ; Decrement HL\n"); fprintf(fp, " dec word [_z80de] ; Decrement DE\n"); } fprintf(fp, " dec cx ; Decrement BC\n"); if (dwOpcode == 0xb0 || dwOpcode == 0xb8) { if (FALSE == bNoTiming) { fprintf(fp, " jz noMore%" PRIu32 "\n", dwGlobalLabel); fprintf(fp, " sub edi, dword 16 ; 16 T-States per iteration\n"); fprintf(fp, " js noMore%" PRIu32 "\n", dwGlobalLabel); } else { fprintf(fp, " jz noMore%" PRIu32 "\n", dwGlobalLabel); } fprintf(fp, " jmp ldRepeat%" PRIu32 " ; Loop until we're done!\n", dwOrgGlobal); fprintf(fp, "noMore%" PRIu32 ":\n", dwGlobalLabel); } fprintf(fp, " and ah, 0e9h ; Knock out H & N and P/V\n"); fprintf(fp, " or cx, cx ; Flag BC\n"); fprintf(fp, " jz atZero%" PRIu32 " ; We're done!\n", dwGlobalLabel); if (dwOpcode == 0xb0 || dwOpcode == 0xb8) { // It's a repeat, so let's readjust ESI, shall we? fprintf(fp, " or ah, 04h ; Non-zero - we're still going!\n"); fprintf(fp, " sub esi, 2 ; Adjust back to the beginning of the instruction\n"); fprintf(fp, " jmp noMoreExec\n\n"); } else if (dwOpcode == 0xa0 || dwOpcode == 0xa8) { fprintf(fp, " or ah, 04h ; Non-zero - we're still going!\n"); } fprintf(fp, "atZero%" PRIu32 ":\n", dwGlobalLabel); ++dwGlobalLabel; fprintf(fp, " xor edx, edx ; Make sure we don't hose things\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { // This is the actual move if (0xb0 == dwOpcode || 0xb8 == dwOpcode) // Repeat instruction? { fprintf(fp, " while ((sdwCyclesRemaining > 0) && (cpu.z80BC))\n"); fprintf(fp, " {\n"); } ReadValueFromMemory("cpu.z80HL", "bTemp"); WriteValueToMemory("cpu.z80DE", "bTemp"); if ((dwOpcode & 0x0f) == 0) { fprintf(fp, " ++cpu.z80HL;\n"); fprintf(fp, " ++cpu.z80DE;\n"); } else { fprintf(fp, " --cpu.z80HL;\n"); fprintf(fp, " --cpu.z80DE;\n"); } fprintf(fp, " --cpu.z80BC;\n"); fprintf(fp, " cpu.z80HL &= 0xffff;\n"); fprintf(fp, " cpu.z80DE &= 0xffff;\n"); fprintf(fp, " cpu.z80BC &= 0xffff;\n"); if (0xb0 == dwOpcode || 0xb8 == dwOpcode) // Repeat instruction? { fprintf(fp, " sdwCyclesRemaining -= 21;\n"); fprintf(fp, " }\n"); } // Time for a flag fixup! fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY);\n"); fprintf(fp, " if (cpu.z80BC)\n"); fprintf(fp, " {\n"); if (0xb0 == dwOpcode || 0xb8 == dwOpcode) { fprintf(fp, " pbPC -= 2; /* Back up so we hit this instruction again */\n"); } fprintf(fp, " cpu.z80F |= Z80_FLAG_OVERFLOW_PARITY;\n"); fprintf(fp, " }\n"); if (0xb0 == dwOpcode || 0xb8 == dwOpcode) // Repeat instruction? { fprintf(fp, " sdwCyclesRemaining -= 16;\n"); } } else abort(); } void IMHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode == 0x46) fprintf(fp, " mov dword [_z80interruptMode], 0 ; IM 0\n"); if (dwOpcode == 0x56) { fprintf(fp, " mov dword [_z80interruptMode], 1 ; Interrupt mode 1\n"); fprintf(fp, " mov word [_z80intAddr], 038h ; Interrupt mode 1 cmd!\n"); } if (dwOpcode == 0x5e) fprintf(fp, " mov dword [_z80interruptMode], 2 ; IM 2\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0x46 == dwOpcode) // IM 0 fprintf(fp, " cpu.z80interruptMode = 0;\n"); if (0x56 == dwOpcode) // IM 1 { fprintf(fp, " cpu.z80interruptMode = 1;\n"); fprintf(fp, " cpu.z80intAddr = 0x38;\n"); } if (0x5e == dwOpcode) // IM 2 fprintf(fp, " cpu.z80interruptMode = 2;\n"); } else abort(); } void IRHandler(UINT32 dwOpcode) { char *src, *dst; if (MZ80_ASSEMBLY_X86 == bWhat) { switch(dwOpcode) { case 0x57: dst = "al"; src="[_z80i]"; break; case 0x5F: dst = "al"; src="[_z80r]"; break; case 0x47: dst = "[_z80i]"; src="al"; break; case 0x4F: dst = "[_z80r]"; src="al"; break; default: abort(); } ProcBegin(dwOpcode); fprintf(fp, " mov %s, %s\n",dst,src); if (dwOpcode == 0x5f) { fprintf(fp, " and ah, 029h ; No N, H, Z, or S!\n"); fprintf(fp, " or al,al ; Get appropriate flags\n"); fprintf(fp, " o16 pushf\n"); fprintf(fp, " pop dx\n"); fprintf(fp, " and dl, 0c0h\n"); fprintf(fp, " or ah, dl ; OR In our S & Z flags\n"); fprintf(fp, " mov dl, [_z80iff]\n"); fprintf(fp, " and dl, IFF2\n"); fprintf(fp, " shl dl, 1\n"); fprintf(fp, " or ah, dl\n"); // Randomize R fprintf(fp, " mov edx, [dwLastRSample]\n"); fprintf(fp, " sub edx, edi\n"); fprintf(fp, " add edx, [_z80rCounter]\n"); fprintf(fp, " shr edx, 2\n"); fprintf(fp, " and edx, 07fh\n"); fprintf(fp, " and byte [_z80r], 80h\n"); fprintf(fp, " or byte [_z80r], dl\n"); fprintf(fp, " xor edx, edx\n"); fprintf(fp, " mov [dwLastRSample], edi\n"); } FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0x5f == dwOpcode) // LD A, R { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80r];\n"); fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_OVERFLOW_PARITY)) | ((cpu.z80iff & IFF2) << 1);\n"); fprintf(fp, " cpu.z80A = cpu.z80r;\n"); // Now randomize a little fprintf(fp, " bTemp = (cpu.z80r + (cpu.z80B + sdwCyclesRemaining + 1 + cpu.z80H)) ^ cpu.z80A;\n"); fprintf(fp, " cpu.z80r = (cpu.z80r & 0x80) | (bTemp & 0x7f);\n"); } else if (0x47 == dwOpcode) // LD I, A { fprintf(fp, " cpu.z80i = cpu.z80A;\n"); } else if (0x57 == dwOpcode) // LD A, I { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= ((cpu.z80iff & IFF2) << 1);\n"); fprintf(fp, " cpu.z80A = cpu.z80i;\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n"); } else if (0x4f == dwOpcode) // LD R, A { fprintf(fp, " cpu.z80r = cpu.z80A;\n"); } else { InvalidInstructionC(2); } } else abort(); } // DD/FD Area void DDFDCBHandler(UINT32 dwOpcode) { UINT32 dwData = 0; if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, "%sInst%.2x:\n", majorOp, dwOpcode); fprintf(fp, " mov dx, [esi] ; Get our instruction (and offset)\n"); fprintf(fp, " add esi, 2 ; Increment our PC\n"); fprintf(fp, " mov byte [_orgval], dl ; Store our value\n"); fprintf(fp, " or dl, dl\n"); fprintf(fp, " js notNeg%" PRIu32 "\n", dwGlobalLabel); fprintf(fp, " mov byte [_orgval + 1], 00h;\n"); fprintf(fp, " jmp short jumpHandler%" PRIu32 "\n", dwGlobalLabel); fprintf(fp, "notNeg%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " mov byte [_orgval + 1], 0ffh; It's negative\n"); fprintf(fp, "jumpHandler%" PRIu32 ":\n", dwGlobalLabel++); fprintf(fp, " shl ebx, 16 ; Save BX away\n"); fprintf(fp, " mov bx, [_z80%s]\n", mz80Index); fprintf(fp, " add [_orgval], bx\n"); fprintf(fp, " shr ebx, 16 ; Restore BX\n"); fprintf(fp, " mov dl, dh ; Get our instruction\n"); fprintf(fp, " xor dh, dh ; Zero this\n"); fprintf(fp, " jmp dword [z80ddfdcbInstructions+edx*4]\n\n"); } else if (MZ80_C == bWhat) { if (strcmp("cpu.z80IX", mz80Index) == 0) dwData = 0; else dwData = 1; fprintf(fp, " DDFDCBHandler(%d);\n", dwData); } else abort(); } void LoadIndexReg(UINT32 dwOpcode) { INT8 string[150]; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); sprintf(string, "[_z80%s]", mz80Index); fprintf(fp, " mov dx, [esi] ; Get our address to store\n"); fprintf(fp, " add esi, 2\n"); ReadWordFromMemory("dx", string); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " dwAddr = *pbPC++;\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbPC++ << 8);\n"); ReadWordFromMemory("dwAddr", mz80Index); } else abort(); } void StoreIndexReg(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [esi] ; Get our address to store\n"); fprintf(fp, " add esi, 2\n"); fprintf(fp, " mov [_orgval], dx\n"); fprintf(fp, " mov dl, [_z80%s]\n", mz80Index); WriteValueToMemory("[_orgval]", "dl"); fprintf(fp, " inc word [_orgval]\n"); fprintf(fp, " mov dl, [_z80%s + 1]\n", mz80Index); WriteValueToMemory("[_orgval]", "dl"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " dwAddr = *pbPC++;\n"); fprintf(fp, " dwAddr |= ((UINT32) *pbPC++ << 8);\n"); WriteWordToMemory("dwAddr", mz80Index); } else abort(); } void LdIndexPtrReg(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); IndexedOffset(mz80Index); // DX Contains the address WriteValueToMemory("dx", pbMathReg[dwOpcode & 0x07]); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " sdwAddr = (INT8) *pbPC++; // Get the offset\n"); fprintf(fp, " sdwAddr = ((INT32) %s + sdwAddr) & 0xffff;\n", mz80Index); WriteValueToMemory("sdwAddr", pbMathRegC[dwOpcode & 0x07]); } else abort(); } void UndocMathIndex(UINT32 dwOpcode) { UINT32 dwOpcode1 = 0; INT8 *pbIndexReg = NULL; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode & 1) fprintf(fp, " mov dl, byte [_z80%s]\n", mz80Index); else fprintf(fp, " mov dl, byte [_z80%s + 1]\n", mz80Index); // Info is in DL - let's do the math operation fprintf(fp, " sahf ; Store our flags in x86 flag reg\n"); dwOpcode1 = (dwOpcode & 0xf8); // Only the operation if (dwOpcode1 == 0x80) fprintf(fp, " add al, dl\n"); else if (dwOpcode1 == 0x88) fprintf(fp, " adc al, dl\n"); else if (dwOpcode1 == 0x90) fprintf(fp, " sub al, dl\n"); else if (dwOpcode1 == 0x98) fprintf(fp, " sbb al, dl\n"); else if (dwOpcode1 == 0xa0) fprintf(fp, " and al, dl\n"); else if (dwOpcode1 == 0xa8) fprintf(fp, " xor al, dl\n"); else if (dwOpcode1 == 0xb0) fprintf(fp, " or al, dl\n"); else if (dwOpcode1 == 0xb8) fprintf(fp, " cmp al, dl\n"); else abort(); fprintf(fp, " lahf ; Get flags back into AH\n"); if (dwOpcode1 != 0xa8 && dwOpcode1 != 0xa0 && dwOpcode1 != 0xb0) { SetOverflow(); } if (dwOpcode1 == 0xa8) fprintf(fp, " and ah, 0ech ; Only these flags matter!\n"); if (dwOpcode1 == 0xa0) { fprintf(fp, " and ah, 0ech ; Only these flags matter!\n"); fprintf(fp, " or ah, 010h ; Half carry gets set\n"); } if (dwOpcode1 == 0xb0) fprintf(fp, " and ah, 0ech ; No H, N, or C\n"); if (dwOpcode1 == 0xb8) fprintf(fp, " or ah, 02h ; Negative gets set on a compare\n"); if (dwOpcode1 == 0x80 || dwOpcode1 == 0x88) fprintf(fp, " and ah, 0fdh ; No N!\n"); if (dwOpcode1 == 0x90 || dwOpcode1 == 0x98) fprintf(fp, " or ah, 02h ; N Gets set!\n"); if (dwOpcode1 == 0xb0) fprintf(fp, " and ah, 0ech ; No H, N, or C\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode & 1) pbIndexReg = mz80IndexHalfLow; else pbIndexReg = mz80IndexHalfHigh; dwOpcode1 = (dwOpcode & 0xf8); // Only the operation if (0x80 == dwOpcode1) // ADD { fprintf(fp, " bTemp2 = cpu.z80A + %s;\n", pbIndexReg); SetAddFlagsSZHVC("cpu.z80A", pbIndexReg); } else if (0x88 == dwOpcode1) // ADC { fprintf(fp, " bTemp2 = cpu.z80A + %s + (cpu.z80F & Z80_FLAG_CARRY);\n", pbIndexReg); SetAdcFlagsSZHVC("cpu.z80A", pbIndexReg); } else if (0x90 == dwOpcode1) // SUB { fprintf(fp, " bTemp2 = cpu.z80A - %s;\n", pbIndexReg); SetSubFlagsSZHVC("cpu.z80A", pbIndexReg); } else if (0x98 == dwOpcode1) // SBC { fprintf(fp, " bTemp2 = cpu.z80A - %s - (cpu.z80F & Z80_FLAG_CARRY);\n", pbIndexReg); SetSbcFlagsSZHVC("cpu.z80A", pbIndexReg); } else if (0xa0 == dwOpcode1) // AND { fprintf(fp, " cpu.z80A &= %s;\n", pbIndexReg); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostANDFlags[cpu.z80A];\n\n"); } else if (0xa8 == dwOpcode1) // XOR { fprintf(fp, " cpu.z80A ^= %s;\n", pbIndexReg); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } else if (0xb0 == dwOpcode1) // OR { fprintf(fp, " cpu.z80A |= %s;\n", pbIndexReg); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } else if (0xb8 == dwOpcode1) // CP - Don't do anything! Just flags! { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } else { abort(); } InvalidInstructionC(2); } else abort(); } void UndocLoadHalfIndexReg(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dl, [esi] ; Get immediate byte to load\n"); fprintf(fp, " inc esi ; Next byte\n"); if (dwOpcode == 0x26) fprintf(fp, " mov byte [_z80%s + 1], dl\n", mz80Index); if (dwOpcode == 0x2e) fprintf(fp, " mov byte [_z80%s], dl\n", mz80Index); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode & 0x08) fprintf(fp, " %s = *pbPC++;\n", mz80IndexHalfLow); else fprintf(fp, " %s = *pbPC++;\n", mz80IndexHalfHigh); } else abort(); } void UndocIncDecIndexReg(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " sahf\n"); if (dwOpcode == 0x24) fprintf(fp, " inc byte [_z80%s + 1]\n", mz80Index); if (dwOpcode == 0x25) fprintf(fp, " dec byte [_z80%s + 1]\n", mz80Index); if (dwOpcode == 0x2c) fprintf(fp, " inc byte [_z80%s]\n", mz80Index); if (dwOpcode == 0x2d) fprintf(fp, " dec byte [_z80%s]\n", mz80Index); fprintf(fp, " lahf\n"); SetOverflow(); if ((0x24 == dwOpcode) || (0x2c == dwOpcode)) fprintf(fp, " and ah, 0fdh ; Knock out N!\n"); else fprintf(fp, " or ah, 02h ; Set negative!\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); if (0x24 == dwOpcode || 0x2c == dwOpcode) { if (dwOpcode & 0x08) fprintf(fp, " cpu.z80F |= bPostIncFlags[%s++];\n", mz80IndexHalfLow); else fprintf(fp, " cpu.z80F |= bPostIncFlags[%s++];\n", mz80IndexHalfHigh); } else { if (dwOpcode & 0x08) fprintf(fp, " cpu.z80F |= bPostDecFlags[%s--];\n", mz80IndexHalfLow); else fprintf(fp, " cpu.z80F |= bPostDecFlags[%s--];\n", mz80IndexHalfHigh); } } else abort(); } void ExIndexed(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if( bThroughCallHandler ) { fprintf(fp, " mov dx, word [_z80%s]\n", mz80Index); fprintf(fp, " push dx\n"); fprintf(fp, " call PopWord\n"); fprintf(fp, " mov [_z80%s], dx\n", mz80Index); fprintf(fp, " pop dx\n"); fprintf(fp, " mov [_wordval], dx\n" ); fprintf(fp, " call PushWord\n" ); } else { fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov dx, word [_z80sp]\n"); fprintf(fp, " xor edi, edi\n"); fprintf(fp, " mov di, [_z80%s]\n", mz80Index); fprintf(fp, " xchg di, [ebp+edx]\n"); fprintf(fp, " mov [_z80%s], di\n", mz80Index); fprintf(fp, " xor edx, edx\n"); fprintf(fp, " mov edi, [cyclesRemaining]\n"); } FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { ReadWordFromMemory("cpu.z80sp", "dwAddr"); WriteWordToMemory("cpu.z80sp", mz80Index); fprintf(fp, " %s = dwAddr;\n", mz80Index); } else abort(); } void IncDecIndexReg(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if (dwOpcode == 0x23) fprintf(fp, " inc word [_z80%s] ; Increment our mz80Index register\n", mz80Index); else fprintf(fp, " dec word [_z80%s] ; Increment our mz80Index register\n", mz80Index); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0x23 == dwOpcode) { fprintf(fp, " %s++;\n", mz80Index); } else { fprintf(fp, " %s--;\n", mz80Index); } fprintf(fp, " %s &= 0xffff;\n", mz80Index); } else abort(); } void LdRegIndexOffset(UINT32 dwOpcode) { UINT32 dwOpcode1 = 0; dwOpcode1 = (dwOpcode & 0x38) >> 3; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); IndexedOffset(mz80Index); ReadValueFromMemory("dx", pbMathReg[dwOpcode1]); fprintf(fp, " xor edx, edx ; Make sure we don't hose things\n"); dwGlobalLabel++; FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " sdwAddr = (INT8) *pbPC++; // Get the offset\n"); fprintf(fp, " sdwAddr = ((INT32) %s + sdwAddr) & 0xffff;\n", mz80Index); ReadValueFromMemory("sdwAddr", pbMathRegC[dwOpcode1]); } else abort(); } void LdByteToIndex(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [esi] ; Get our address\n"); fprintf(fp, " add esi, 2 ; Skip over our storage bytes\n"); fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov di, dx ; Store it here for later\n"); fprintf(fp, " xor dh, dh\n"); fprintf(fp, " or dl, dl\n"); fprintf(fp, " jns noNegate%" PRIu32 "\n", dwGlobalLabel); fprintf(fp, " dec dh\n"); fprintf(fp, "noNegate%" PRIu32 ":\n", dwGlobalLabel); fprintf(fp, " add dx, [_z80%s] ; Add in our index\n", mz80Index); fprintf(fp, " mov [_orgval], dx ; Store our address to write to\n"); fprintf(fp, " mov dx, di\n"); fprintf(fp, " xchg dh, dl\n"); fprintf(fp, " mov edi, [cyclesRemaining]\n"); WriteValueToMemory("[_orgval]", "dl"); fprintf(fp, " xor edx, edx\n"); ++dwGlobalLabel; FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " sdwAddr = (INT8) *pbPC++; // Get the offset\n"); fprintf(fp, " sdwAddr = ((INT32) %s + sdwAddr) & 0xffff;\n", mz80Index); WriteValueToMemory("sdwAddr", "*pbPC++"); } else abort(); } void SPToIndex(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [_z80%s] ; Get our source register\n", mz80Index); fprintf(fp, " mov word [_z80sp], dx ; Store our new SP\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " cpu.z80sp = %s;\n", mz80Index); } else abort(); } void AddIndexHandler(UINT32 dwOpcode) { UINT8 bRegPair; bRegPair = dwOpcode >> 4; if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dh, ah ; Get our flags\n"); fprintf(fp, " and dh, 0ech ; Preserve the top three and bits 2 & 3\n"); fprintf(fp, " mov [cyclesRemaining], edi\n"); fprintf(fp, " mov di, [_z80%s] ; Get our value\n", mz80Index); fprintf(fp, " mov [_orgval], di ; Store our original value\n"); fprintf(fp, " add di, %s\n", pbIndexedRegPairs[(dwOpcode & 0x30) >> 4]); fprintf(fp, " lahf\n"); fprintf(fp, " mov [_z80%s], di ; Store our register back\n", mz80Index); fprintf(fp, " mov di, [_orgval] ; Get original\n"); fprintf(fp, " xor di, word [_z80%s] ; XOR It with our computed value\n", mz80Index); fprintf(fp, " xor di, %s\n", pbIndexedRegPairs[(dwOpcode & 0x30) >> 4]); fprintf(fp, " and di, 1000h ; Just our half carry\n"); fprintf(fp, " or dx, di ; Or in our flags\n"); fprintf(fp, " and ah, 01h ; Just carry\n"); fprintf(fp, " or ah, dh\n"); fprintf(fp, " mov edi, [cyclesRemaining]\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (bRegPair != 2) { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY);\n"); fprintf(fp, " dwTemp = %s + %s;\n", mz80Index, pbRegPairsC[bRegPair]); fprintf(fp, " cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((%s ^ dwTemp ^ %s) >> 8) & Z80_FLAG_HALF_CARRY);\n", mz80Index, pbRegPairsC[bRegPair]); fprintf(fp, " %s = dwTemp & 0xffff;\n", mz80Index); } else { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_HALF_CARRY);\n"); fprintf(fp, " dwTemp = %s + %s;\n", mz80Index, mz80Index); fprintf(fp, " cpu.z80F |= ((dwTemp >> 16) & Z80_FLAG_CARRY) | (((%s ^ dwTemp ^ %s) >> 8) & Z80_FLAG_HALF_CARRY);\n", mz80Index, pbRegPairsC[bRegPair]); fprintf(fp, " %s = dwTemp & 0xffff;\n", mz80Index); } } else abort(); } void JPIXIYHandler(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [_z80%s] ; Get our value\n", mz80Index); fprintf(fp, " mov esi, edx ; New PC!\n"); fprintf(fp, " add esi, ebp ; Add in our base\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " pbPC = cpu.z80Base + %s;\n", mz80Index); } else abort(); } void IncDecIndexed(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); IndexedOffset(mz80Index); fprintf(fp, " mov [_orgval], dx\n"); ReadValueFromMemory("dx", "dl"); fprintf(fp, " sahf\n"); if (dwOpcode == 0x34) fprintf(fp, " inc dl\n"); else fprintf(fp, " dec dl\n"); fprintf(fp, " lahf\n"); fprintf(fp, " o16 pushf\n"); fprintf(fp, " shl edx, 16\n"); fprintf(fp, " and ah, 0fbh ; Knock out parity/overflow\n"); fprintf(fp, " pop dx\n"); fprintf(fp, " and dh, 08h ; Just the overflow\n"); fprintf(fp, " shr dh, 1 ; Shift it into position\n"); fprintf(fp, " or ah, dh ; OR It in with the real flags\n"); fprintf(fp, " shr edx, 16\n"); if (dwOpcode == 0x34) fprintf(fp, " and ah, 0fdh ; Knock out N!\n"); else fprintf(fp, " or ah, 02h ; Make it N!\n"); WriteValueToMemory("[_orgval]", "dl"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " sdwAddr = (INT8) *pbPC++; /* Get LSB first */\n"); fprintf(fp, " dwAddr = (sdwAddr + (INT32) %s) & 0xffff;\n", mz80Index); ReadValueFromMemory("dwAddr", "bTemp"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_SIGN | Z80_FLAG_ZERO | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE);\n"); if (0x34 == dwOpcode) { fprintf(fp ," cpu.z80F |= bPostIncFlags[bTemp++];\n"); } else { fprintf(fp ," cpu.z80F |= bPostDecFlags[bTemp--];\n"); } WriteValueToMemory("dwAddr", "bTemp"); } else abort(); } void MathOperationIndexed(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); IndexedOffset(mz80Index); ReadValueFromMemory("dx", "dl"); fprintf(fp, " sahf\n"); if (dwOpcode == 0x86) // Add fprintf(fp, " add al, dl\n"); if (dwOpcode == 0x8e) // Adc fprintf(fp, " adc al, dl\n"); if (dwOpcode == 0x96) // Sub fprintf(fp, " sub al, dl\n"); if (dwOpcode == 0x9e) // Sbc fprintf(fp, " sbb al, dl\n"); if (dwOpcode == 0xa6) // And fprintf(fp, " and al, dl\n"); if (dwOpcode == 0xae) // Xor fprintf(fp, " xor al, dl\n"); if (dwOpcode == 0xb6) // Or fprintf(fp, " or al, dl\n"); if (dwOpcode == 0xbe) // Cp fprintf(fp, " cmp al, dl\n"); fprintf(fp, " lahf\n"); if (dwOpcode == 0x86 || dwOpcode == 0x8e) { SetOverflow(); fprintf(fp, " and ah, 0fdh ; Knock out negative\n"); } if (dwOpcode == 0x96 || dwOpcode == 0x9e || dwOpcode == 0xbe) { SetOverflow(); fprintf(fp, " or ah, 02h ; Set negative\n"); } if (dwOpcode == 0xae || dwOpcode == 0xb6) fprintf(fp, " and ah, 0ech ; Knock out H, N, and C\n"); if (dwOpcode == 0xa6) { fprintf(fp, " and ah,0fch ; Knock out N & C\n"); fprintf(fp, " or ah, 10h ; Set half carry\n"); } fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " sdwAddr = (INT8) *pbPC++; /* Get LSB first */\n"); fprintf(fp, " dwAddr = (sdwAddr + (INT32) %s) & 0xffff;\n", mz80Index); ReadValueFromMemory("dwAddr", "bTemp"); if (0x86 == dwOpcode) // ADD A, (IX/IY+nn) { SetAddFlagsSZHVC("cpu.z80A", "bTemp"); fprintf(fp, " cpu.z80A += bTemp;\n"); } else if (0x8e == dwOpcode) // ADC A, (IX/IY+nn) { fprintf(fp, " bTemp2 = (cpu.z80F & Z80_FLAG_CARRY);\n"); SetAdcFlagsSZHVC("cpu.z80A", "bTemp"); fprintf(fp, " cpu.z80A += bTemp + bTemp2;\n"); } else if (0x96 == dwOpcode) // SUB A, (IX/IY+nn) { SetSubFlagsSZHVC("cpu.z80A", "bTemp"); fprintf(fp, " cpu.z80A -= bTemp;\n"); } else if (0x9e == dwOpcode) // SBC A, (IX/IY+nn) { fprintf(fp, " bTemp2 = cpu.z80A;\n"); fprintf(fp, " cpu.z80A = cpu.z80A - bTemp - (cpu.z80F & Z80_FLAG_CARRY);\n"); SetSbcFlagsSZHVC("bTemp2", "bTemp"); } else if (0xa6 == dwOpcode) // AND A, (IX/IY+nn) { fprintf(fp, " cpu.z80A &= bTemp;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostANDFlags[cpu.z80A];\n\n"); } else if (0xae == dwOpcode) // XOR A, (IX/IY+nn) { fprintf(fp, " cpu.z80A ^= bTemp;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } else if (0xb6 == dwOpcode) // OR A, (IX/IY+nn) { fprintf(fp, " cpu.z80A |= bTemp;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_CARRY | Z80_FLAG_NEGATIVE | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_HALF_CARRY | Z80_FLAG_ZERO | Z80_FLAG_SIGN);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[cpu.z80A];\n\n"); } else if (0xbe == dwOpcode) // CP A, (IX/IY+nn) { SetSubFlagsSZHVC("cpu.z80A", "bTemp"); } else InvalidInstructionC(2); } else abort(); } void UndocIndexToReg(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if ((dwOpcode & 0x07) == 2 || (dwOpcode & 0x07) == 3) fprintf(fp, " mov dx, [_z80de] ; Get DE\n"); if ((dwOpcode & 0x07) == 4) fprintf(fp, " mov dh, byte [_z80%s + 1]\n", mz80Index); if ((dwOpcode & 0x07) == 5) fprintf(fp, " mov dl, byte [_z80%s]\n", mz80Index); fprintf(fp, " mov byte [_z80%s + %" PRIu32 "], %s\n", mz80Index, 1 - ((dwOpcode & 0x08) >> 3), pbLocalReg[dwOpcode & 0x07]); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode != 0x64 && dwOpcode != 0x65 && dwOpcode != 0x6c && dwOpcode != 0x6d) { if (dwOpcode & 0x08) fprintf(fp, " %s = %s;\n", mz80IndexHalfLow, pbLocalRegC[dwOpcode & 0x07]); else fprintf(fp, " %s = %s;\n", mz80IndexHalfHigh, pbLocalRegC[dwOpcode & 0x07]); } else // IX/IY High/low weirdness afoot... { // We don't generate any code for ld indexH, indexH and ld indexL, indexL if (0x65 == dwOpcode) // LD indexH, indexL { fprintf(fp, " %s = %s;\n", mz80IndexHalfHigh, mz80IndexHalfLow); } else if (0x6c == dwOpcode) // LD indexH, indexL { fprintf(fp, " %s = %s;\n", mz80IndexHalfLow, mz80IndexHalfHigh); } } } else abort(); } void UndocRegToIndex(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); if ((dwOpcode & 0x38) == 0x10 || (dwOpcode & 0x38) == 0x18) fprintf(fp, " mov dx, [_z80de] ; Get a usable copy of DE here\n"); fprintf(fp, " mov %s, byte [_z80%s + %" PRIu32 "]\n", pbLocalReg[(dwOpcode >> 3) & 0x07], mz80Index, 1 - (dwOpcode & 1)); if ((dwOpcode & 0x38) == 0x10 || (dwOpcode & 0x38) == 0x18) fprintf(fp, " mov [_z80de], dx ; Put it back!\n"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (dwOpcode & 1) fprintf(fp, " %s = %s;\n", pbLocalRegC[(dwOpcode >> 3) & 0x07], mz80IndexHalfLow); else fprintf(fp, " %s = %s;\n", pbLocalRegC[(dwOpcode >> 3) & 0x07], mz80IndexHalfHigh); } else abort(); } void LoadImmediate(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); fprintf(fp, " mov dx, [esi] ; Get our word to load\n"); fprintf(fp, " add esi, 2 ; Advance past the word\n"); fprintf(fp, " mov [_z80%s], dx ; Store our new value\n", mz80Index); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { fprintf(fp, " %s = *pbPC++;\n", mz80Index); fprintf(fp, " %s |= ((UINT32) *pbPC++ << 8);\n", mz80Index); } else abort(); } void PushPopOperationsIndexed(UINT32 dwOpcode) { INT8 bRegBaseLsb[25]; INT8 bRegBaseMsb[25]; INT8 string[150]; if (MZ80_ASSEMBLY_X86 == bWhat) { sprintf(bRegBaseLsb, "byte [_z80%s]", mz80Index); sprintf(bRegBaseMsb, "byte [_z80%s + 1]", mz80Index); sprintf(string, "[_z80%s]", mz80Index); ProcBegin(dwOpcode); if (dwOpcode == 0xe5) // Push IX/IY { fprintf(fp, " sub word [_z80sp], 2\n"); fprintf(fp, " mov dx, [_z80sp]\n"); WriteWordToMemory("dx", string); } else // Pop { fprintf(fp, " mov dx, [_z80sp]\n"); ReadWordFromMemory("dx", string); fprintf(fp, " add word [_z80sp], 2\n"); } fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0xe5 == dwOpcode) // Push IX/IY { fprintf(fp, " cpu.z80sp -= 2;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */\n"); WriteWordToMemory("cpu.z80sp", mz80Index); } else if (0xe1 == dwOpcode) // Pop IX/IY { ReadWordFromMemory("cpu.z80sp", mz80Index); fprintf(fp, " cpu.z80sp += 2;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp); /* Normalize the stack pointer */\n"); return; } } else abort(); } // DDFD XXCB Instructions void ddcbBitWise(UINT32 dwOpcode) { if (MZ80_ASSEMBLY_X86 == bWhat) { ProcBegin(dwOpcode); // NOTE: _orgval contains the address to get from. It includes the offset // already computed plus the mz80Index register. // Read our byte fprintf(fp, " mov dx, [_orgval] ; Get our target address\n"); ReadValueFromMemory("dx", "dl"); // Do the operation if (dwOpcode != 0x06 && dwOpcode != 0x0e && dwOpcode != 0x16 && dwOpcode != 0x1e && dwOpcode != 0x26 && dwOpcode != 0x2e && dwOpcode != 0x3e && (dwOpcode & 0xc7) != 0x86 && (dwOpcode & 0xc7) != 0xc6) { fprintf(fp, " mov dh, ah ; Store our original flags\n"); fprintf(fp, " and dh, 29h ; Keep our old flags\n"); } if ((dwOpcode & 0xc7) != 0x86 && (dwOpcode & 0xc7) != 0xc6) fprintf(fp, " sahf ; Restore our flags\n"); if (dwOpcode == 0x06) fprintf(fp, " rol dl, 1\n"); if (dwOpcode == 0x0e) fprintf(fp, " ror dl, 1\n"); if (dwOpcode == 0x16) fprintf(fp, " rcl dl, 1\n"); if (dwOpcode == 0x1e) fprintf(fp, " rcr dl, 1\n"); if (dwOpcode == 0x26) fprintf(fp, " shl dl, 1\n"); if (dwOpcode == 0x2e) fprintf(fp, " sar dl, 1\n"); if (dwOpcode == 0x3e) fprintf(fp, " shr dl, 1\n"); // BIT, AND, and OR if ((dwOpcode & 0xc7) == 0x46) fprintf(fp, " test dl, 0%.2xh ; Is it set?\n", (1 << ((dwOpcode >> 3) & 0x07))); else if ((dwOpcode & 0xc7) == 0x86) fprintf(fp, " and dl, 0%.2xh ; Reset the bit\n", 0xff - (1 << ((dwOpcode >> 3) & 0x07))); else if ((dwOpcode & 0xc7) == 0xc6) fprintf(fp, " or dl, 0%.2xh ; Set the bit\n", (1 << ((dwOpcode >> 3) & 0x07))); if ((dwOpcode & 0xc7) != 0x86 && (dwOpcode & 0xc7) != 0xc6) fprintf(fp, " lahf ; Get our flags back\n"); // Do the flag fixup (if any) if (dwOpcode == 0x26 || dwOpcode == 0x2e || ((dwOpcode & 0xc7) == 0x46)) fprintf(fp, " and ah, 0edh ; No Half carry or negative!\n"); if (dwOpcode == 0x06 || dwOpcode == 0x0e || dwOpcode == 0x16 || dwOpcode == 0x1e || dwOpcode == 0x3e) fprintf(fp, " and ah, 0edh ; Knock out H & N\n"); // BIT! if ((dwOpcode & 0xc7) == 0x46) { fprintf(fp, " or ah, 10h ; OR In our half carry\n"); fprintf(fp, " and ah, 0d0h ; New flags\n"); fprintf(fp, " or ah, dh ; OR In our old flags\n"); } // Now write our data back if it's not a BIT instruction if ((dwOpcode & 0xc7) != 0x46) // If it's not a BIT, write it back WriteValueToMemory("[_orgval]", "dl"); fprintf(fp, " xor edx, edx\n"); FetchNextInstruction(dwOpcode); } else if (MZ80_C == bWhat) { if (0x06 == dwOpcode) // RLC { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " bTemp2 = (bTemp >> 7);\n"); fprintf(fp, " bTemp = (bTemp << 1) | bTemp2;\n"); fprintf(fp, " cpu.z80F |= bTemp2 | bPostORFlags[bTemp];\n"); WriteValueToMemory("dwAddr", "bTemp"); } else if (0x0e == dwOpcode) // RRC { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (bTemp & Z80_FLAG_CARRY);\n"); fprintf(fp, " bTemp = (bTemp >> 1) | (bTemp << 7);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[bTemp];\n"); WriteValueToMemory("dwAddr", "bTemp"); } else if (0x16 == dwOpcode) // RL { fprintf(fp, " bTemp2 = cpu.z80F & Z80_FLAG_CARRY;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (bTemp >> 7);\n"); fprintf(fp, " bTemp = (bTemp << 1) | bTemp2;\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[bTemp];\n"); WriteValueToMemory("dwAddr", "bTemp"); } else if (0x1e == dwOpcode) // RR { fprintf(fp, " bTemp2 = (cpu.z80F & Z80_FLAG_CARRY) << 7;\n"); fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (bTemp & Z80_FLAG_CARRY);\n"); fprintf(fp, " bTemp = (bTemp >> 1) | bTemp2;\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[bTemp];\n"); WriteValueToMemory("dwAddr", "bTemp"); } else if (0x26 == dwOpcode) // SLA { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (bTemp >> 7);\n"); fprintf(fp, " bTemp = (bTemp << 1);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[bTemp];\n"); WriteValueToMemory("dwAddr", "bTemp"); } else if (0x2e == dwOpcode) // SRA { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (bTemp & Z80_FLAG_CARRY);\n"); fprintf(fp, " bTemp = (bTemp >> 1) | (bTemp & 0x80);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[bTemp];\n"); WriteValueToMemory("dwAddr", "bTemp"); } else if (0x3e == dwOpcode) // SRL { fprintf(fp, " cpu.z80F &= ~(Z80_FLAG_ZERO | Z80_FLAG_SIGN | Z80_FLAG_HALF_CARRY | Z80_FLAG_OVERFLOW_PARITY | Z80_FLAG_NEGATIVE | Z80_FLAG_CARRY);\n"); fprintf(fp, " cpu.z80F |= (bTemp & Z80_FLAG_CARRY);\n"); fprintf(fp, " bTemp = (bTemp >> 1);\n"); fprintf(fp, " cpu.z80F |= bPostORFlags[bTemp];\n"); WriteValueToMemory("dwAddr", "bTemp"); } else if ((dwOpcode & 0xc0) == 0x40) // BIT { fprintf(fp, " cpu.z80F = (cpu.z80F & ~(Z80_FLAG_ZERO | Z80_FLAG_NEGATIVE)) | Z80_FLAG_HALF_CARRY;\n"); fprintf(fp, " if (!(bTemp & 0x%.2x))\n", 1 << ((dwOpcode >> 3) & 0x07)); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80F |= Z80_FLAG_ZERO;\n"); fprintf(fp, " }\n"); } else if ((dwOpcode & 0xc0) == 0x80) // RES { fprintf(fp, " bTemp &= 0x%.2x;\n", ~(1 << ((dwOpcode >> 3) & 0x07)) & 0xff); WriteValueToMemory("dwAddr", "bTemp"); } else if ((dwOpcode & 0xc0) == 0xC0) // SET { fprintf(fp, " bTemp |= 0x%.2x;\n", 1 << ((dwOpcode >> 3) & 0x07)); WriteValueToMemory("dwAddr", "bTemp"); } else InvalidInstructionC(4); } else abort(); } void GetTicksCode(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sGetElapsedTicks\n", cpubasename); fprintf(fp, " global %sGetElapsedTicks_\n", cpubasename); fprintf(fp, " global %sGetElapsedTicks\n", cpubasename); Alignment(); sprintf(procname, "%sGetElapsedTicks_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sGetElapsedTicks:\n", cpubasename); fprintf(fp, "%sGetElapsedTicks:\n", cpubasename); if (bUseStack) fprintf(fp, " mov eax, [esp+4] ; Get our context address\n"); fprintf(fp, " or eax, eax ; Should we clear it?\n"); fprintf(fp, " jz getTicks\n"); fprintf(fp, " xor eax, eax\n"); fprintf(fp, " xchg eax, [dwElapsedTicks]\n"); fprintf(fp, " ret\n"); fprintf(fp, "getTicks:\n"); fprintf(fp, " mov eax, [dwElapsedTicks]\n"); fprintf(fp, " ret\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* This will return the elapsed ticks */\n\n"); fprintf(fp, "UINT32 %sGetElapsedTicks(UINT32 dwClear)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " UINT32 dwTemp = dwElapsedTicks;\n\n"); fprintf(fp, " if (dwClear)\n"); fprintf(fp, " {\n"); fprintf(fp, " dwElapsedTicks = 0;\n"); fprintf(fp, " }\n\n"); fprintf(fp, " return(dwTemp);\n"); fprintf(fp, "}\n\n"); } else { abort(); } } void ReleaseTimesliceCode(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sReleaseTimeslice\n", cpubasename); fprintf(fp, " global %sReleaseTimeslice_\n", cpubasename); fprintf(fp, " global %sReleaseTimeslice\n", cpubasename); Alignment(); sprintf(procname, "%sReleaseTimeslice_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sReleaseTimeslice:\n", cpubasename); fprintf(fp, "%sReleaseTimeslice:\n", cpubasename); fprintf(fp, " mov eax, [cyclesRemaining]\n"); fprintf(fp, " sub [dwOriginalExec], eax\n"); fprintf(fp, " mov [cyclesRemaining], dword 0\n"); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Releases mz80 from its current timeslice */\n\n"); fprintf(fp, "void %sReleaseTimeslice(void)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " dwOriginalCycles -= sdwCyclesRemaining;\n"); fprintf(fp, " sdwCyclesRemaining = 0;\n"); fprintf(fp, "}\n\n"); } else { abort(); } } void DataSegment(void) { UINT32 dwLoop = 0; UINT8 bUsed[256]; if (MZ80_ASSEMBLY_X86 == bWhat) { if (bOS2) fprintf(fp, " section .DATA32 use32 flat class=data\n"); else fprintf(fp, " section .data use32 flat class=data\n"); Alignment(); fprintf(fp, " global _%scontextBegin\n", cpubasename); fprintf(fp, "_%scontextBegin:\n", cpubasename); fprintf(fp, " global _z80pc\n"); fprintf(fp, " global z80pc_\n"); if (bPlain) fprintf(fp, " global z80pc\n"); fprintf(fp, " global _z80nmiAddr\n"); fprintf(fp, " global _z80intAddr\n"); fprintf(fp, " global z80intAddr\n"); fprintf(fp, "\n"); fprintf(fp, "; DO NOT CHANGE THE ORDER OF AF, BC, DE, HL and THE PRIME REGISTERS!\n"); fprintf(fp, "\n"); fprintf(fp, "_z80Base dd 0 ; Base address for Z80 stuff\n"); fprintf(fp, "_z80MemRead dd 0 ; Offset of memory read structure array\n"); fprintf(fp, "_z80MemWrite dd 0 ; Offset of memory write structure array\n"); fprintf(fp, "_z80IoRead dd 0 ; Base address for I/O reads list\n"); fprintf(fp, "_z80IoWrite dd 0 ; Base address for I/O write list\n"); fprintf(fp, "_z80clockticks dd 0 ; # Of clock tips that have elapsed\n"); fprintf(fp, "_z80iff dd 0 ; Non-zero if we're in an interrupt\n"); fprintf(fp, "_z80interruptMode dd 0 ; Interrupt mode\n"); fprintf(fp, "_z80halted dd 0 ; 0=Not halted, 1=Halted\n"); #ifdef MZ80_TRAP fprintf(fp, "_z80trapList dd 0 ; pointer to trap list\n"); fprintf(fp, "_z80trapAddr dw 0 ; PC where trap occurred\n"); #endif fprintf(fp, "_z80af dd 0 ; A Flag & Flags\n"); fprintf(fp, "_z80bc dd 0 ; BC\n"); fprintf(fp, "_z80de dd 0 ; DE\n"); fprintf(fp, "_z80hl dd 0 ; HL\n"); fprintf(fp, "_z80afprime dd 0 ; A Flag & Flags prime\n"); fprintf(fp, "_z80bcprime dd 0 ; BC prime\n"); fprintf(fp, "_z80deprime dd 0 ; DE prime\n"); fprintf(fp, "_z80hlprime dd 0 ; HL prime\n"); fprintf(fp, "\n"); fprintf(fp, "; The order of the following registers can be changed without adverse\n"); fprintf(fp, "; effect. Keep the WORD and DWORDs on boundaries of two for faster access\n"); fprintf(fp, "\n"); fprintf(fp, "_z80ix dd 0 ; IX\n"); fprintf(fp, "_z80iy dd 0 ; IY\n"); fprintf(fp, "_z80sp dd 0 ; Stack pointer\n"); if (bPlain) fprintf(fp,"z80pc:\n"); fprintf(fp, "z80pc_:\n"); fprintf(fp, "_z80pc dd 0 ; PC\n"); fprintf(fp, "_z80nmiAddr dd 0 ; Address to jump to for NMI\n"); fprintf(fp, "z80intAddr:\n"); fprintf(fp, "_z80intAddr dd 0 ; Address to jump to for INT\n"); fprintf(fp, "_z80rCounter dd 0 ; R Register counter\n"); fprintf(fp, "_z80i db 0 ; I register\n"); fprintf(fp, "_z80r db 0 ; R register\n"); fprintf(fp, "_z80intPending db 0 ; Non-zero if an interrupt is pending\n"); fprintf(fp, "\n"); fprintf(fp, "_%scontextEnd:\n", cpubasename); Alignment(); fprintf(fp, "dwElapsedTicks dd 0 ; # Of ticks elapsed\n"); fprintf(fp, "cyclesRemaining dd 0 ; # Of cycles remaining\n"); fprintf(fp, "dwOriginalExec dd 0 ; # Of cycles originally executing\n"); fprintf(fp, "dwLastRSample dd 0 ; Last sample for R computation\n"); fprintf(fp, "dwEITiming dd 0 ; Used when we cause an interrupt\n"); fprintf(fp, "_orgval dw 0 ; Scratch area\n"); fprintf(fp, "_orgval2 dw 0 ; Scratch area\n"); fprintf(fp, "_wordval dw 0 ; Scratch area\n"); fprintf(fp, "_intData db 0 ; Interrupt data when an interrupt is pending\n"); fprintf(fp, "bEIExit db 0 ; Are we exiting because of an EI instruction?\n"); fprintf(fp, "\n"); // Debugger junk fprintf(fp, "RegTextPC db 'PC',0\n"); fprintf(fp, "RegTextAF db 'AF',0\n"); fprintf(fp, "RegTextBC db 'BC',0\n"); fprintf(fp, "RegTextDE db 'DE',0\n"); fprintf(fp, "RegTextHL db 'HL',0\n"); fprintf(fp, "RegTextAFP db 'AF',27h,0\n"); fprintf(fp, "RegTextBCP db 'BC',27h,0\n"); fprintf(fp, "RegTextDEP db 'DE',27h,0\n"); fprintf(fp, "RegTextHLP db 'HL',27h,0\n"); fprintf(fp, "RegTextIX db 'IX',0\n"); fprintf(fp, "RegTextIY db 'IY',0\n"); fprintf(fp, "RegTextSP db 'SP',0\n"); fprintf(fp, "RegTextI db 'I',0\n"); fprintf(fp, "RegTextR db 'R',0\n"); // 8 Byte textual info fprintf(fp, "RegTextA db 'A',0\n"); fprintf(fp, "RegTextB db 'B',0\n"); fprintf(fp, "RegTextC db 'C',0\n"); fprintf(fp, "RegTextD db 'D',0\n"); fprintf(fp, "RegTextE db 'E',0\n"); fprintf(fp, "RegTextH db 'H',0\n"); fprintf(fp, "RegTextL db 'L',0\n"); fprintf(fp, "RegTextF db 'F',0\n"); // Individual flags fprintf(fp, "RegTextCarry db 'Carry',0\n"); fprintf(fp, "RegTextNegative db 'Negative',0\n"); fprintf(fp, "RegTextParity db 'Parity',0\n"); fprintf(fp, "RegTextOverflow db 'Overflow',0\n"); fprintf(fp, "RegTextHalfCarry db 'HalfCarry',0\n"); fprintf(fp, "RegTextZero db 'Zero',0\n"); fprintf(fp, "RegTextSign db 'Sign',0\n"); fprintf(fp, "RegTextIFF1 db 'IFF1',0\n"); fprintf(fp, "RegTextIFF2 db 'IFF2',0\n\n"); // Timing for interrupt modes fprintf(fp, "intModeTStates:\n"); fprintf(fp, " db 13 ; IM 0 - 13 T-States\n"); fprintf(fp, " db 11 ; IM 1 - 11 T-States\n"); fprintf(fp, " db 11 ; IM 2 - 11 T-States\n\n"); // Now the master reg/flag table fprintf(fp, "\n;\n"); fprintf(fp, "; Info is in: pointer to text, address, shift value, mask value, size of data chunk\n"); fprintf(fp, ";\n\n"); fprintf(fp, "RegTable:\n"); // Pointer to text, address, shift value, mask, size fprintf(fp, " dd RegTextPC, _z80pc - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextSP, _z80sp - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextAF, _z80af - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextBC, _z80bc - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextDE, _z80de - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextHL, _z80hl - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextAFP, _z80af - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextBCP, _z80bc - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextDEP, _z80de - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextHLP, _z80hl - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextIX, _z80ix - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextIY, _z80iy - _%scontextBegin, 0, 0ffffh\n", cpubasename); fprintf(fp, " dd RegTextI, _z80i - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextR, _z80r - _%scontextBegin, 0, 0ffh\n", cpubasename); // Individual regs fprintf(fp, " dd RegTextA, (_z80af + 1) - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextF, _z80af - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextB, (_z80bc + 1) - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextC, _z80bc - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextD, (_z80de + 1) - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextE, _z80de - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextH, (_z80hl + 1) - _%scontextBegin, 0, 0ffh\n", cpubasename); fprintf(fp, " dd RegTextL, _z80hl - _%scontextBegin, 0, 0ffh\n", cpubasename); // IFF register fprintf(fp, " dd RegTextIFF1, _z80iff - _%scontextBegin, 0, 01h\n", cpubasename); fprintf(fp, " dd RegTextIFF2, _z80iff - _%scontextBegin, 1, 01h\n", cpubasename); // Individual flags fprintf(fp, " dd RegTextCarry, _z80af - _%scontextBegin, 0, 01h\n", cpubasename); fprintf(fp, " dd RegTextNegative, _z80af - _%scontextBegin, 1, 01h\n", cpubasename); fprintf(fp, " dd RegTextParity, _z80af - _%scontextBegin, 2, 01h\n", cpubasename); fprintf(fp, " dd RegTextOverflow, _z80af - _%scontextBegin, 2, 01h\n", cpubasename); fprintf(fp, " dd RegTextHalfCarry, _z80af - _%scontextBegin, 4, 01h\n", cpubasename); fprintf(fp, " dd RegTextZero, _z80af - _%scontextBegin, 6, 01h\n", cpubasename); fprintf(fp, " dd RegTextSign, _z80af - _%scontextBegin, 7, 01h\n", cpubasename); // Now we write out our tables Alignment(); for (dwLoop = 0; dwLoop < 256; dwLoop++) bUsed[dwLoop] = 0; // Now rip through and find out what is and isn't used dwLoop = 0; while (StandardOps[dwLoop].Emitter) { assert(StandardOps[dwLoop].bOpCode < 0x100); if (bUsed[StandardOps[dwLoop].bOpCode]) { fprintf(stderr, "Oops! %.2x\n", dwLoop); fclose(fp); exit(1); } bUsed[StandardOps[dwLoop].bOpCode] = 1; dwLoop++; } // Now that that's taken care of, emit the table fprintf(fp, "z80regular:\n"); dwLoop = 0; while (dwLoop < 0x100) { fprintf(fp, " dd "); if (bUsed[dwLoop]) fprintf(fp, "RegInst%.2x", dwLoop); else fprintf(fp, "invalidInsByte"); fprintf(fp, "\n"); dwLoop++; } fprintf(fp, "\n"); // Now rip through and find out what is and isn't used (CB Ops) for (dwLoop = 0; dwLoop < 0x100; dwLoop++) bUsed[dwLoop] = 0; dwLoop = 0; while (CBOps[dwLoop].Emitter) { assert(CBOps[dwLoop].bOpCode < 0x100); if (bUsed[CBOps[dwLoop].bOpCode]) { fprintf(stderr, "Oops CB! %.2x\n", dwLoop); fclose(fp); exit(1); } bUsed[CBOps[dwLoop].bOpCode] = 1; dwLoop++; } dwLoop = 0; // Let's emit the CB prefixes fprintf(fp, "z80PrefixCB:\n"); while (dwLoop < 0x100) { fprintf(fp, " dd "); if (bUsed[dwLoop]) fprintf(fp, "CBInst%.2x", dwLoop); else fprintf(fp, "invalidInsWord"); fprintf(fp, "\n"); dwLoop++; } fprintf(fp, "\n"); // Now rip through and find out what is and isn't used (ED Ops) for (dwLoop = 0; dwLoop < 0x100; dwLoop++) bUsed[dwLoop] = 0; dwLoop = 0; while (EDOps[dwLoop].Emitter) { assert(EDOps[dwLoop].bOpCode < 0x100); if (bUsed[EDOps[dwLoop].bOpCode]) { fprintf(stderr, "Oops ED! %.2x\n", dwLoop); fclose(fp); exit(1); } bUsed[EDOps[dwLoop].bOpCode] = 1; dwLoop++; } dwLoop = 0; // Let's emit the ED prefixes fprintf(fp, "z80PrefixED:\n"); while (dwLoop < 0x100) { fprintf(fp, " dd "); if (bUsed[dwLoop]) fprintf(fp, "EDInst%.2x", dwLoop); else fprintf(fp, "invalidInsWord"); fprintf(fp, "\n"); dwLoop++; } fprintf(fp, "\n"); // Now rip through and find out what is and isn't used (DD Ops) for (dwLoop = 0; dwLoop < 0x100; dwLoop++) bUsed[dwLoop] = 0; dwLoop = 0; while (DDFDOps[dwLoop].Emitter) { assert(DDFDOps[dwLoop].bOpCode < 0x100); if (bUsed[DDFDOps[dwLoop].bOpCode]) { fprintf(stderr, "Oops DD! %.2x\n", bUsed[DDFDOps[dwLoop].bOpCode]); fclose(fp); exit(1); } bUsed[DDFDOps[dwLoop].bOpCode] = 1; dwLoop++; } dwLoop = 0; // Let's emit the DD prefixes fprintf(fp, "z80PrefixDD:\n"); while (dwLoop < 0x100) { fprintf(fp, " dd "); if (bUsed[dwLoop]) fprintf(fp, "DDInst%.2x", dwLoop); else fprintf(fp, "invalidInsWord"); fprintf(fp, "\n"); dwLoop++; } fprintf(fp, "\n"); // Now rip through and find out what is and isn't used (FD Ops) for (dwLoop = 0; dwLoop < 0x100; dwLoop++) bUsed[dwLoop] = 0; dwLoop = 0; while (DDFDOps[dwLoop].Emitter) { assert(DDFDOps[dwLoop].bOpCode < 0x100); if (bUsed[DDFDOps[dwLoop].bOpCode]) { fprintf(stderr, "Oops FD! %.2x\n", dwLoop); fclose(fp); exit(1); } bUsed[DDFDOps[dwLoop].bOpCode] = 1; dwLoop++; } for (dwLoop = 0; dwLoop < 0x100; dwLoop++) bUsed[dwLoop] = 0; // Let's emit the DDFD prefixes for (dwLoop = 0; dwLoop < 0x100; dwLoop++) bUsed[dwLoop] = 0; dwLoop = 0; while (DDFDOps[dwLoop].Emitter) { assert(DDFDOps[dwLoop].bOpCode < 0x100); if (bUsed[DDFDOps[dwLoop].bOpCode]) { fprintf(stderr, "Oops FD! %.2x\n", dwLoop); exit(1); } bUsed[DDFDOps[dwLoop].bOpCode] = 1; dwLoop++; } dwLoop = 0; // Let's emit the DDFD prefixes fprintf(fp, "z80PrefixFD:\n"); while (dwLoop < 0x100) { fprintf(fp, " dd "); if (bUsed[dwLoop]) fprintf(fp, "FDInst%.2x", dwLoop); else fprintf(fp, "invalidInsWord"); fprintf(fp, "\n"); dwLoop++; } for (dwLoop = 0; dwLoop < 0x100; dwLoop++) bUsed[dwLoop] = 0; dwLoop = 0; while (DDFDCBOps[dwLoop].Emitter) { assert(DDFDCBOps[dwLoop].bOpCode < 0x100); if (bUsed[DDFDCBOps[dwLoop].bOpCode]) { fprintf(stderr, "Oops CBFDDD! %.2x\n", bUsed[DDFDCBOps[dwLoop].bOpCode]); fclose(fp); exit(1); } bUsed[DDFDCBOps[dwLoop].bOpCode] = 1; dwLoop++; } // Let's emit the DDFD prefixes dwLoop = 0; fprintf(fp, "z80ddfdcbInstructions:\n"); while (dwLoop < 0x100) { fprintf(fp, " dd "); if (bUsed[dwLoop]) fprintf(fp, "DDFDCBInst%.2x", dwLoop); else fprintf(fp, "invalidInsWord"); fprintf(fp, "\n"); dwLoop++; } fprintf(fp, "\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Modular global variables go here*/\n\n"); fprintf(fp, "static CONTEXTMZ80 cpu; /* CPU Context */\n"); fprintf(fp, "static UINT8 *pbPC; /* Program counter normalized */\n"); fprintf(fp, "static UINT8 *pbSP; /* Stack pointer normalized */\n"); fprintf(fp, "static struct MemoryReadByte *psMemRead; /* Read memory structure */\n"); fprintf(fp, "static struct MemoryWriteByte *psMemWrite; /* Write memory structure */\n"); fprintf(fp, "static struct z80PortRead *psIoRead; /* Read I/O structure */\n"); fprintf(fp, "static struct z80PortWrite *psIoWrite; /* Write memory structure */\n"); fprintf(fp, "static INT32 sdwCyclesRemaining; /* Used as a countdown */\n"); fprintf(fp, "static UINT32 dwReturnCode; /* Return code from exec() */\n"); fprintf(fp, "static UINT32 dwOriginalCycles; /* How many cycles did we start with? */\n"); fprintf(fp, "static UINT32 dwElapsedTicks; /* How many ticks did we elapse? */\n"); fprintf(fp, "static UINT32 sdwAddr; /* Temporary address storage */\n"); fprintf(fp, "static UINT32 dwAddr; /* Temporary stack address */\n"); fprintf(fp, "static UINT8 *pbAddAdcTable; /* Pointer to add/adc flag table */\n"); fprintf(fp, "static UINT8 *pbSubSbcTable; /* Pointer to sub/sbc flag table */\n"); fprintf(fp, "static UINT32 dwTemp; /* Temporary value */\n\n"); fprintf(fp, "static UINT8 bTemp; /* Temporary value */\n\n"); fprintf(fp, "static UINT8 bTemp2; /* Temporary value */\n\n"); fprintf(fp, "/* Precomputed flag tables */\n\n"); fprintf(fp, "static UINT8 bPostIncFlags[0x100] = \n"); fprintf(fp, "{\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,\n"); fprintf(fp, " 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x90,\n"); fprintf(fp, " 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x50\n"); fprintf(fp, "};\n\n"); fprintf(fp, "static UINT8 bPostDecFlags[0x100] = \n"); fprintf(fp, "{\n"); fprintf(fp, " 0x92,0x42,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x12,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,\n"); fprintf(fp, " 0x16,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,\n"); fprintf(fp, " 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,\n"); fprintf(fp, " 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,\n"); fprintf(fp, " 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,\n"); fprintf(fp, " 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,\n"); fprintf(fp, " 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,\n"); fprintf(fp, " 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,\n"); fprintf(fp, " 0x92,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82\n"); fprintf(fp, "};\n\n"); fprintf(fp, "static UINT8 bPostORFlags[0x100] = \n"); fprintf(fp, "{\n"); fprintf(fp, " 0x44,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,\n"); fprintf(fp, " 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,\n"); fprintf(fp, " 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,\n"); fprintf(fp, " 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,\n"); fprintf(fp, " 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,\n"); fprintf(fp, " 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,\n"); fprintf(fp, " 0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,\n"); fprintf(fp, " 0x00,0x04,0x04,0x00,0x04,0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x00,0x04,0x04,0x00,\n"); fprintf(fp, " 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,\n"); fprintf(fp, " 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,\n"); fprintf(fp, " 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,\n"); fprintf(fp, " 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,\n"); fprintf(fp, " 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,\n"); fprintf(fp, " 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,\n"); fprintf(fp, " 0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84,0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,\n"); fprintf(fp, " 0x84,0x80,0x80,0x84,0x80,0x84,0x84,0x80,0x80,0x84,0x84,0x80,0x84,0x80,0x80,0x84\n"); fprintf(fp, "};\n\n"); fprintf(fp, "static UINT8 bPostANDFlags[0x100] = \n"); fprintf(fp, "{\n"); fprintf(fp, " 0x54,0x10,0x10,0x14,0x10,0x14,0x14,0x10,0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,\n"); fprintf(fp, " 0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,\n"); fprintf(fp, " 0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,\n"); fprintf(fp, " 0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,\n"); fprintf(fp, " 0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,\n"); fprintf(fp, " 0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,\n"); fprintf(fp, " 0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,\n"); fprintf(fp, " 0x10,0x14,0x14,0x10,0x14,0x10,0x10,0x14,0x14,0x10,0x10,0x14,0x10,0x14,0x14,0x10,\n"); fprintf(fp, " 0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,\n"); fprintf(fp, " 0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,\n"); fprintf(fp, " 0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,\n"); fprintf(fp, " 0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,\n"); fprintf(fp, " 0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,\n"); fprintf(fp, " 0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,\n"); fprintf(fp, " 0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94,0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,\n"); fprintf(fp, " 0x94,0x90,0x90,0x94,0x90,0x94,0x94,0x90,0x90,0x94,0x94,0x90,0x94,0x90,0x90,0x94\n"); fprintf(fp, "};\n\n"); fprintf(fp, "static UINT16 wDAATable[0x800] = \n"); fprintf(fp, "{\n"); fprintf(fp, " 0x5400,0x1001,0x1002,0x1403,0x1004,0x1405,0x1406,0x1007,\n"); fprintf(fp, " 0x1008,0x1409,0x1010,0x1411,0x1412,0x1013,0x1414,0x1015,\n"); fprintf(fp, " 0x1010,0x1411,0x1412,0x1013,0x1414,0x1015,0x1016,0x1417,\n"); fprintf(fp, " 0x1418,0x1019,0x1020,0x1421,0x1422,0x1023,0x1424,0x1025,\n"); fprintf(fp, " 0x1020,0x1421,0x1422,0x1023,0x1424,0x1025,0x1026,0x1427,\n"); fprintf(fp, " 0x1428,0x1029,0x1430,0x1031,0x1032,0x1433,0x1034,0x1435,\n"); fprintf(fp, " 0x1430,0x1031,0x1032,0x1433,0x1034,0x1435,0x1436,0x1037,\n"); fprintf(fp, " 0x1038,0x1439,0x1040,0x1441,0x1442,0x1043,0x1444,0x1045,\n"); fprintf(fp, " 0x1040,0x1441,0x1442,0x1043,0x1444,0x1045,0x1046,0x1447,\n"); fprintf(fp, " 0x1448,0x1049,0x1450,0x1051,0x1052,0x1453,0x1054,0x1455,\n"); fprintf(fp, " 0x1450,0x1051,0x1052,0x1453,0x1054,0x1455,0x1456,0x1057,\n"); fprintf(fp, " 0x1058,0x1459,0x1460,0x1061,0x1062,0x1463,0x1064,0x1465,\n"); fprintf(fp, " 0x1460,0x1061,0x1062,0x1463,0x1064,0x1465,0x1466,0x1067,\n"); fprintf(fp, " 0x1068,0x1469,0x1070,0x1471,0x1472,0x1073,0x1474,0x1075,\n"); fprintf(fp, " 0x1070,0x1471,0x1472,0x1073,0x1474,0x1075,0x1076,0x1477,\n"); fprintf(fp, " 0x1478,0x1079,0x9080,0x9481,0x9482,0x9083,0x9484,0x9085,\n"); fprintf(fp, " 0x9080,0x9481,0x9482,0x9083,0x9484,0x9085,0x9086,0x9487,\n"); fprintf(fp, " 0x9488,0x9089,0x9490,0x9091,0x9092,0x9493,0x9094,0x9495,\n"); fprintf(fp, " 0x9490,0x9091,0x9092,0x9493,0x9094,0x9495,0x9496,0x9097,\n"); fprintf(fp, " 0x9098,0x9499,0x5500,0x1101,0x1102,0x1503,0x1104,0x1505,\n"); fprintf(fp, " 0x5500,0x1101,0x1102,0x1503,0x1104,0x1505,0x1506,0x1107,\n"); fprintf(fp, " 0x1108,0x1509,0x1110,0x1511,0x1512,0x1113,0x1514,0x1115,\n"); fprintf(fp, " 0x1110,0x1511,0x1512,0x1113,0x1514,0x1115,0x1116,0x1517,\n"); fprintf(fp, " 0x1518,0x1119,0x1120,0x1521,0x1522,0x1123,0x1524,0x1125,\n"); fprintf(fp, " 0x1120,0x1521,0x1522,0x1123,0x1524,0x1125,0x1126,0x1527,\n"); fprintf(fp, " 0x1528,0x1129,0x1530,0x1131,0x1132,0x1533,0x1134,0x1535,\n"); fprintf(fp, " 0x1530,0x1131,0x1132,0x1533,0x1134,0x1535,0x1536,0x1137,\n"); fprintf(fp, " 0x1138,0x1539,0x1140,0x1541,0x1542,0x1143,0x1544,0x1145,\n"); fprintf(fp, " 0x1140,0x1541,0x1542,0x1143,0x1544,0x1145,0x1146,0x1547,\n"); fprintf(fp, " 0x1548,0x1149,0x1550,0x1151,0x1152,0x1553,0x1154,0x1555,\n"); fprintf(fp, " 0x1550,0x1151,0x1152,0x1553,0x1154,0x1555,0x1556,0x1157,\n"); fprintf(fp, " 0x1158,0x1559,0x1560,0x1161,0x1162,0x1563,0x1164,0x1565,\n"); fprintf(fp, " 0x1560,0x1161,0x1162,0x1563,0x1164,0x1565,0x1566,0x1167,\n"); fprintf(fp, " 0x1168,0x1569,0x1170,0x1571,0x1572,0x1173,0x1574,0x1175,\n"); fprintf(fp, " 0x1170,0x1571,0x1572,0x1173,0x1574,0x1175,0x1176,0x1577,\n"); fprintf(fp, " 0x1578,0x1179,0x9180,0x9581,0x9582,0x9183,0x9584,0x9185,\n"); fprintf(fp, " 0x9180,0x9581,0x9582,0x9183,0x9584,0x9185,0x9186,0x9587,\n"); fprintf(fp, " 0x9588,0x9189,0x9590,0x9191,0x9192,0x9593,0x9194,0x9595,\n"); fprintf(fp, " 0x9590,0x9191,0x9192,0x9593,0x9194,0x9595,0x9596,0x9197,\n"); fprintf(fp, " 0x9198,0x9599,0x95a0,0x91a1,0x91a2,0x95a3,0x91a4,0x95a5,\n"); fprintf(fp, " 0x95a0,0x91a1,0x91a2,0x95a3,0x91a4,0x95a5,0x95a6,0x91a7,\n"); fprintf(fp, " 0x91a8,0x95a9,0x91b0,0x95b1,0x95b2,0x91b3,0x95b4,0x91b5,\n"); fprintf(fp, " 0x91b0,0x95b1,0x95b2,0x91b3,0x95b4,0x91b5,0x91b6,0x95b7,\n"); fprintf(fp, " 0x95b8,0x91b9,0x95c0,0x91c1,0x91c2,0x95c3,0x91c4,0x95c5,\n"); fprintf(fp, " 0x95c0,0x91c1,0x91c2,0x95c3,0x91c4,0x95c5,0x95c6,0x91c7,\n"); fprintf(fp, " 0x91c8,0x95c9,0x91d0,0x95d1,0x95d2,0x91d3,0x95d4,0x91d5,\n"); fprintf(fp, " 0x91d0,0x95d1,0x95d2,0x91d3,0x95d4,0x91d5,0x91d6,0x95d7,\n"); fprintf(fp, " 0x95d8,0x91d9,0x91e0,0x95e1,0x95e2,0x91e3,0x95e4,0x91e5,\n"); fprintf(fp, " 0x91e0,0x95e1,0x95e2,0x91e3,0x95e4,0x91e5,0x91e6,0x95e7,\n"); fprintf(fp, " 0x95e8,0x91e9,0x95f0,0x91f1,0x91f2,0x95f3,0x91f4,0x95f5,\n"); fprintf(fp, " 0x95f0,0x91f1,0x91f2,0x95f3,0x91f4,0x95f5,0x95f6,0x91f7,\n"); fprintf(fp, " 0x91f8,0x95f9,0x5500,0x1101,0x1102,0x1503,0x1104,0x1505,\n"); fprintf(fp, " 0x5500,0x1101,0x1102,0x1503,0x1104,0x1505,0x1506,0x1107,\n"); fprintf(fp, " 0x1108,0x1509,0x1110,0x1511,0x1512,0x1113,0x1514,0x1115,\n"); fprintf(fp, " 0x1110,0x1511,0x1512,0x1113,0x1514,0x1115,0x1116,0x1517,\n"); fprintf(fp, " 0x1518,0x1119,0x1120,0x1521,0x1522,0x1123,0x1524,0x1125,\n"); fprintf(fp, " 0x1120,0x1521,0x1522,0x1123,0x1524,0x1125,0x1126,0x1527,\n"); fprintf(fp, " 0x1528,0x1129,0x1530,0x1131,0x1132,0x1533,0x1134,0x1535,\n"); fprintf(fp, " 0x1530,0x1131,0x1132,0x1533,0x1134,0x1535,0x1536,0x1137,\n"); fprintf(fp, " 0x1138,0x1539,0x1140,0x1541,0x1542,0x1143,0x1544,0x1145,\n"); fprintf(fp, " 0x1140,0x1541,0x1542,0x1143,0x1544,0x1145,0x1146,0x1547,\n"); fprintf(fp, " 0x1548,0x1149,0x1550,0x1151,0x1152,0x1553,0x1154,0x1555,\n"); fprintf(fp, " 0x1550,0x1151,0x1152,0x1553,0x1154,0x1555,0x1556,0x1157,\n"); fprintf(fp, " 0x1158,0x1559,0x1560,0x1161,0x1162,0x1563,0x1164,0x1565,\n"); fprintf(fp, " 0x1406,0x1007,0x1008,0x1409,0x140a,0x100b,0x140c,0x100d,\n"); fprintf(fp, " 0x100e,0x140f,0x1010,0x1411,0x1412,0x1013,0x1414,0x1015,\n"); fprintf(fp, " 0x1016,0x1417,0x1418,0x1019,0x101a,0x141b,0x101c,0x141d,\n"); fprintf(fp, " 0x141e,0x101f,0x1020,0x1421,0x1422,0x1023,0x1424,0x1025,\n"); fprintf(fp, " 0x1026,0x1427,0x1428,0x1029,0x102a,0x142b,0x102c,0x142d,\n"); fprintf(fp, " 0x142e,0x102f,0x1430,0x1031,0x1032,0x1433,0x1034,0x1435,\n"); fprintf(fp, " 0x1436,0x1037,0x1038,0x1439,0x143a,0x103b,0x143c,0x103d,\n"); fprintf(fp, " 0x103e,0x143f,0x1040,0x1441,0x1442,0x1043,0x1444,0x1045,\n"); fprintf(fp, " 0x1046,0x1447,0x1448,0x1049,0x104a,0x144b,0x104c,0x144d,\n"); fprintf(fp, " 0x144e,0x104f,0x1450,0x1051,0x1052,0x1453,0x1054,0x1455,\n"); fprintf(fp, " 0x1456,0x1057,0x1058,0x1459,0x145a,0x105b,0x145c,0x105d,\n"); fprintf(fp, " 0x105e,0x145f,0x1460,0x1061,0x1062,0x1463,0x1064,0x1465,\n"); fprintf(fp, " 0x1466,0x1067,0x1068,0x1469,0x146a,0x106b,0x146c,0x106d,\n"); fprintf(fp, " 0x106e,0x146f,0x1070,0x1471,0x1472,0x1073,0x1474,0x1075,\n"); fprintf(fp, " 0x1076,0x1477,0x1478,0x1079,0x107a,0x147b,0x107c,0x147d,\n"); fprintf(fp, " 0x147e,0x107f,0x9080,0x9481,0x9482,0x9083,0x9484,0x9085,\n"); fprintf(fp, " 0x9086,0x9487,0x9488,0x9089,0x908a,0x948b,0x908c,0x948d,\n"); fprintf(fp, " 0x948e,0x908f,0x9490,0x9091,0x9092,0x9493,0x9094,0x9495,\n"); fprintf(fp, " 0x9496,0x9097,0x9098,0x9499,0x949a,0x909b,0x949c,0x909d,\n"); fprintf(fp, " 0x909e,0x949f,0x5500,0x1101,0x1102,0x1503,0x1104,0x1505,\n"); fprintf(fp, " 0x1506,0x1107,0x1108,0x1509,0x150a,0x110b,0x150c,0x110d,\n"); fprintf(fp, " 0x110e,0x150f,0x1110,0x1511,0x1512,0x1113,0x1514,0x1115,\n"); fprintf(fp, " 0x1116,0x1517,0x1518,0x1119,0x111a,0x151b,0x111c,0x151d,\n"); fprintf(fp, " 0x151e,0x111f,0x1120,0x1521,0x1522,0x1123,0x1524,0x1125,\n"); fprintf(fp, " 0x1126,0x1527,0x1528,0x1129,0x112a,0x152b,0x112c,0x152d,\n"); fprintf(fp, " 0x152e,0x112f,0x1530,0x1131,0x1132,0x1533,0x1134,0x1535,\n"); fprintf(fp, " 0x1536,0x1137,0x1138,0x1539,0x153a,0x113b,0x153c,0x113d,\n"); fprintf(fp, " 0x113e,0x153f,0x1140,0x1541,0x1542,0x1143,0x1544,0x1145,\n"); fprintf(fp, " 0x1146,0x1547,0x1548,0x1149,0x114a,0x154b,0x114c,0x154d,\n"); fprintf(fp, " 0x154e,0x114f,0x1550,0x1151,0x1152,0x1553,0x1154,0x1555,\n"); fprintf(fp, " 0x1556,0x1157,0x1158,0x1559,0x155a,0x115b,0x155c,0x115d,\n"); fprintf(fp, " 0x115e,0x155f,0x1560,0x1161,0x1162,0x1563,0x1164,0x1565,\n"); fprintf(fp, " 0x1566,0x1167,0x1168,0x1569,0x156a,0x116b,0x156c,0x116d,\n"); fprintf(fp, " 0x116e,0x156f,0x1170,0x1571,0x1572,0x1173,0x1574,0x1175,\n"); fprintf(fp, " 0x1176,0x1577,0x1578,0x1179,0x117a,0x157b,0x117c,0x157d,\n"); fprintf(fp, " 0x157e,0x117f,0x9180,0x9581,0x9582,0x9183,0x9584,0x9185,\n"); fprintf(fp, " 0x9186,0x9587,0x9588,0x9189,0x918a,0x958b,0x918c,0x958d,\n"); fprintf(fp, " 0x958e,0x918f,0x9590,0x9191,0x9192,0x9593,0x9194,0x9595,\n"); fprintf(fp, " 0x9596,0x9197,0x9198,0x9599,0x959a,0x919b,0x959c,0x919d,\n"); fprintf(fp, " 0x919e,0x959f,0x95a0,0x91a1,0x91a2,0x95a3,0x91a4,0x95a5,\n"); fprintf(fp, " 0x95a6,0x91a7,0x91a8,0x95a9,0x95aa,0x91ab,0x95ac,0x91ad,\n"); fprintf(fp, " 0x91ae,0x95af,0x91b0,0x95b1,0x95b2,0x91b3,0x95b4,0x91b5,\n"); fprintf(fp, " 0x91b6,0x95b7,0x95b8,0x91b9,0x91ba,0x95bb,0x91bc,0x95bd,\n"); fprintf(fp, " 0x95be,0x91bf,0x95c0,0x91c1,0x91c2,0x95c3,0x91c4,0x95c5,\n"); fprintf(fp, " 0x95c6,0x91c7,0x91c8,0x95c9,0x95ca,0x91cb,0x95cc,0x91cd,\n"); fprintf(fp, " 0x91ce,0x95cf,0x91d0,0x95d1,0x95d2,0x91d3,0x95d4,0x91d5,\n"); fprintf(fp, " 0x91d6,0x95d7,0x95d8,0x91d9,0x91da,0x95db,0x91dc,0x95dd,\n"); fprintf(fp, " 0x95de,0x91df,0x91e0,0x95e1,0x95e2,0x91e3,0x95e4,0x91e5,\n"); fprintf(fp, " 0x91e6,0x95e7,0x95e8,0x91e9,0x91ea,0x95eb,0x91ec,0x95ed,\n"); fprintf(fp, " 0x95ee,0x91ef,0x95f0,0x91f1,0x91f2,0x95f3,0x91f4,0x95f5,\n"); fprintf(fp, " 0x95f6,0x91f7,0x91f8,0x95f9,0x95fa,0x91fb,0x95fc,0x91fd,\n"); fprintf(fp, " 0x91fe,0x95ff,0x5500,0x1101,0x1102,0x1503,0x1104,0x1505,\n"); fprintf(fp, " 0x1506,0x1107,0x1108,0x1509,0x150a,0x110b,0x150c,0x110d,\n"); fprintf(fp, " 0x110e,0x150f,0x1110,0x1511,0x1512,0x1113,0x1514,0x1115,\n"); fprintf(fp, " 0x1116,0x1517,0x1518,0x1119,0x111a,0x151b,0x111c,0x151d,\n"); fprintf(fp, " 0x151e,0x111f,0x1120,0x1521,0x1522,0x1123,0x1524,0x1125,\n"); fprintf(fp, " 0x1126,0x1527,0x1528,0x1129,0x112a,0x152b,0x112c,0x152d,\n"); fprintf(fp, " 0x152e,0x112f,0x1530,0x1131,0x1132,0x1533,0x1134,0x1535,\n"); fprintf(fp, " 0x1536,0x1137,0x1138,0x1539,0x153a,0x113b,0x153c,0x113d,\n"); fprintf(fp, " 0x113e,0x153f,0x1140,0x1541,0x1542,0x1143,0x1544,0x1145,\n"); fprintf(fp, " 0x1146,0x1547,0x1548,0x1149,0x114a,0x154b,0x114c,0x154d,\n"); fprintf(fp, " 0x154e,0x114f,0x1550,0x1151,0x1152,0x1553,0x1154,0x1555,\n"); fprintf(fp, " 0x1556,0x1157,0x1158,0x1559,0x155a,0x115b,0x155c,0x115d,\n"); fprintf(fp, " 0x115e,0x155f,0x1560,0x1161,0x1162,0x1563,0x1164,0x1565,\n"); fprintf(fp, " 0x5600,0x1201,0x1202,0x1603,0x1204,0x1605,0x1606,0x1207,\n"); fprintf(fp, " 0x1208,0x1609,0x1204,0x1605,0x1606,0x1207,0x1208,0x1609,\n"); fprintf(fp, " 0x1210,0x1611,0x1612,0x1213,0x1614,0x1215,0x1216,0x1617,\n"); fprintf(fp, " 0x1618,0x1219,0x1614,0x1215,0x1216,0x1617,0x1618,0x1219,\n"); fprintf(fp, " 0x1220,0x1621,0x1622,0x1223,0x1624,0x1225,0x1226,0x1627,\n"); fprintf(fp, " 0x1628,0x1229,0x1624,0x1225,0x1226,0x1627,0x1628,0x1229,\n"); fprintf(fp, " 0x1630,0x1231,0x1232,0x1633,0x1234,0x1635,0x1636,0x1237,\n"); fprintf(fp, " 0x1238,0x1639,0x1234,0x1635,0x1636,0x1237,0x1238,0x1639,\n"); fprintf(fp, " 0x1240,0x1641,0x1642,0x1243,0x1644,0x1245,0x1246,0x1647,\n"); fprintf(fp, " 0x1648,0x1249,0x1644,0x1245,0x1246,0x1647,0x1648,0x1249,\n"); fprintf(fp, " 0x1650,0x1251,0x1252,0x1653,0x1254,0x1655,0x1656,0x1257,\n"); fprintf(fp, " 0x1258,0x1659,0x1254,0x1655,0x1656,0x1257,0x1258,0x1659,\n"); fprintf(fp, " 0x1660,0x1261,0x1262,0x1663,0x1264,0x1665,0x1666,0x1267,\n"); fprintf(fp, " 0x1268,0x1669,0x1264,0x1665,0x1666,0x1267,0x1268,0x1669,\n"); fprintf(fp, " 0x1270,0x1671,0x1672,0x1273,0x1674,0x1275,0x1276,0x1677,\n"); fprintf(fp, " 0x1678,0x1279,0x1674,0x1275,0x1276,0x1677,0x1678,0x1279,\n"); fprintf(fp, " 0x9280,0x9681,0x9682,0x9283,0x9684,0x9285,0x9286,0x9687,\n"); fprintf(fp, " 0x9688,0x9289,0x9684,0x9285,0x9286,0x9687,0x9688,0x9289,\n"); fprintf(fp, " 0x9690,0x9291,0x9292,0x9693,0x9294,0x9695,0x9696,0x9297,\n"); fprintf(fp, " 0x9298,0x9699,0x1334,0x1735,0x1736,0x1337,0x1338,0x1739,\n"); fprintf(fp, " 0x1340,0x1741,0x1742,0x1343,0x1744,0x1345,0x1346,0x1747,\n"); fprintf(fp, " 0x1748,0x1349,0x1744,0x1345,0x1346,0x1747,0x1748,0x1349,\n"); fprintf(fp, " 0x1750,0x1351,0x1352,0x1753,0x1354,0x1755,0x1756,0x1357,\n"); fprintf(fp, " 0x1358,0x1759,0x1354,0x1755,0x1756,0x1357,0x1358,0x1759,\n"); fprintf(fp, " 0x1760,0x1361,0x1362,0x1763,0x1364,0x1765,0x1766,0x1367,\n"); fprintf(fp, " 0x1368,0x1769,0x1364,0x1765,0x1766,0x1367,0x1368,0x1769,\n"); fprintf(fp, " 0x1370,0x1771,0x1772,0x1373,0x1774,0x1375,0x1376,0x1777,\n"); fprintf(fp, " 0x1778,0x1379,0x1774,0x1375,0x1376,0x1777,0x1778,0x1379,\n"); fprintf(fp, " 0x9380,0x9781,0x9782,0x9383,0x9784,0x9385,0x9386,0x9787,\n"); fprintf(fp, " 0x9788,0x9389,0x9784,0x9385,0x9386,0x9787,0x9788,0x9389,\n"); fprintf(fp, " 0x9790,0x9391,0x9392,0x9793,0x9394,0x9795,0x9796,0x9397,\n"); fprintf(fp, " 0x9398,0x9799,0x9394,0x9795,0x9796,0x9397,0x9398,0x9799,\n"); fprintf(fp, " 0x97a0,0x93a1,0x93a2,0x97a3,0x93a4,0x97a5,0x97a6,0x93a7,\n"); fprintf(fp, " 0x93a8,0x97a9,0x93a4,0x97a5,0x97a6,0x93a7,0x93a8,0x97a9,\n"); fprintf(fp, " 0x93b0,0x97b1,0x97b2,0x93b3,0x97b4,0x93b5,0x93b6,0x97b7,\n"); fprintf(fp, " 0x97b8,0x93b9,0x97b4,0x93b5,0x93b6,0x97b7,0x97b8,0x93b9,\n"); fprintf(fp, " 0x97c0,0x93c1,0x93c2,0x97c3,0x93c4,0x97c5,0x97c6,0x93c7,\n"); fprintf(fp, " 0x93c8,0x97c9,0x93c4,0x97c5,0x97c6,0x93c7,0x93c8,0x97c9,\n"); fprintf(fp, " 0x93d0,0x97d1,0x97d2,0x93d3,0x97d4,0x93d5,0x93d6,0x97d7,\n"); fprintf(fp, " 0x97d8,0x93d9,0x97d4,0x93d5,0x93d6,0x97d7,0x97d8,0x93d9,\n"); fprintf(fp, " 0x93e0,0x97e1,0x97e2,0x93e3,0x97e4,0x93e5,0x93e6,0x97e7,\n"); fprintf(fp, " 0x97e8,0x93e9,0x97e4,0x93e5,0x93e6,0x97e7,0x97e8,0x93e9,\n"); fprintf(fp, " 0x97f0,0x93f1,0x93f2,0x97f3,0x93f4,0x97f5,0x97f6,0x93f7,\n"); fprintf(fp, " 0x93f8,0x97f9,0x93f4,0x97f5,0x97f6,0x93f7,0x93f8,0x97f9,\n"); fprintf(fp, " 0x5700,0x1301,0x1302,0x1703,0x1304,0x1705,0x1706,0x1307,\n"); fprintf(fp, " 0x1308,0x1709,0x1304,0x1705,0x1706,0x1307,0x1308,0x1709,\n"); fprintf(fp, " 0x1310,0x1711,0x1712,0x1313,0x1714,0x1315,0x1316,0x1717,\n"); fprintf(fp, " 0x1718,0x1319,0x1714,0x1315,0x1316,0x1717,0x1718,0x1319,\n"); fprintf(fp, " 0x1320,0x1721,0x1722,0x1323,0x1724,0x1325,0x1326,0x1727,\n"); fprintf(fp, " 0x1728,0x1329,0x1724,0x1325,0x1326,0x1727,0x1728,0x1329,\n"); fprintf(fp, " 0x1730,0x1331,0x1332,0x1733,0x1334,0x1735,0x1736,0x1337,\n"); fprintf(fp, " 0x1338,0x1739,0x1334,0x1735,0x1736,0x1337,0x1338,0x1739,\n"); fprintf(fp, " 0x1340,0x1741,0x1742,0x1343,0x1744,0x1345,0x1346,0x1747,\n"); fprintf(fp, " 0x1748,0x1349,0x1744,0x1345,0x1346,0x1747,0x1748,0x1349,\n"); fprintf(fp, " 0x1750,0x1351,0x1352,0x1753,0x1354,0x1755,0x1756,0x1357,\n"); fprintf(fp, " 0x1358,0x1759,0x1354,0x1755,0x1756,0x1357,0x1358,0x1759,\n"); fprintf(fp, " 0x1760,0x1361,0x1362,0x1763,0x1364,0x1765,0x1766,0x1367,\n"); fprintf(fp, " 0x1368,0x1769,0x1364,0x1765,0x1766,0x1367,0x1368,0x1769,\n"); fprintf(fp, " 0x1370,0x1771,0x1772,0x1373,0x1774,0x1375,0x1376,0x1777,\n"); fprintf(fp, " 0x1778,0x1379,0x1774,0x1375,0x1376,0x1777,0x1778,0x1379,\n"); fprintf(fp, " 0x9380,0x9781,0x9782,0x9383,0x9784,0x9385,0x9386,0x9787,\n"); fprintf(fp, " 0x9788,0x9389,0x9784,0x9385,0x9386,0x9787,0x9788,0x9389,\n"); fprintf(fp, " 0x9790,0x9391,0x9392,0x9793,0x9394,0x9795,0x9796,0x9397,\n"); fprintf(fp, " 0x9398,0x9799,0x9394,0x9795,0x9796,0x9397,0x9398,0x9799,\n"); fprintf(fp, " 0x97fa,0x93fb,0x97fc,0x93fd,0x93fe,0x97ff,0x5600,0x1201,\n"); fprintf(fp, " 0x1202,0x1603,0x1204,0x1605,0x1606,0x1207,0x1208,0x1609,\n"); fprintf(fp, " 0x160a,0x120b,0x160c,0x120d,0x120e,0x160f,0x1210,0x1611,\n"); fprintf(fp, " 0x1612,0x1213,0x1614,0x1215,0x1216,0x1617,0x1618,0x1219,\n"); fprintf(fp, " 0x121a,0x161b,0x121c,0x161d,0x161e,0x121f,0x1220,0x1621,\n"); fprintf(fp, " 0x1622,0x1223,0x1624,0x1225,0x1226,0x1627,0x1628,0x1229,\n"); fprintf(fp, " 0x122a,0x162b,0x122c,0x162d,0x162e,0x122f,0x1630,0x1231,\n"); fprintf(fp, " 0x1232,0x1633,0x1234,0x1635,0x1636,0x1237,0x1238,0x1639,\n"); fprintf(fp, " 0x163a,0x123b,0x163c,0x123d,0x123e,0x163f,0x1240,0x1641,\n"); fprintf(fp, " 0x1642,0x1243,0x1644,0x1245,0x1246,0x1647,0x1648,0x1249,\n"); fprintf(fp, " 0x124a,0x164b,0x124c,0x164d,0x164e,0x124f,0x1650,0x1251,\n"); fprintf(fp, " 0x1252,0x1653,0x1254,0x1655,0x1656,0x1257,0x1258,0x1659,\n"); fprintf(fp, " 0x165a,0x125b,0x165c,0x125d,0x125e,0x165f,0x1660,0x1261,\n"); fprintf(fp, " 0x1262,0x1663,0x1264,0x1665,0x1666,0x1267,0x1268,0x1669,\n"); fprintf(fp, " 0x166a,0x126b,0x166c,0x126d,0x126e,0x166f,0x1270,0x1671,\n"); fprintf(fp, " 0x1672,0x1273,0x1674,0x1275,0x1276,0x1677,0x1678,0x1279,\n"); fprintf(fp, " 0x127a,0x167b,0x127c,0x167d,0x167e,0x127f,0x9280,0x9681,\n"); fprintf(fp, " 0x9682,0x9283,0x9684,0x9285,0x9286,0x9687,0x9688,0x9289,\n"); fprintf(fp, " 0x928a,0x968b,0x928c,0x968d,0x968e,0x928f,0x9690,0x9291,\n"); fprintf(fp, " 0x9292,0x9693,0x1334,0x1735,0x1736,0x1337,0x1338,0x1739,\n"); fprintf(fp, " 0x173a,0x133b,0x173c,0x133d,0x133e,0x173f,0x1340,0x1741,\n"); fprintf(fp, " 0x1742,0x1343,0x1744,0x1345,0x1346,0x1747,0x1748,0x1349,\n"); fprintf(fp, " 0x134a,0x174b,0x134c,0x174d,0x174e,0x134f,0x1750,0x1351,\n"); fprintf(fp, " 0x1352,0x1753,0x1354,0x1755,0x1756,0x1357,0x1358,0x1759,\n"); fprintf(fp, " 0x175a,0x135b,0x175c,0x135d,0x135e,0x175f,0x1760,0x1361,\n"); fprintf(fp, " 0x1362,0x1763,0x1364,0x1765,0x1766,0x1367,0x1368,0x1769,\n"); fprintf(fp, " 0x176a,0x136b,0x176c,0x136d,0x136e,0x176f,0x1370,0x1771,\n"); fprintf(fp, " 0x1772,0x1373,0x1774,0x1375,0x1376,0x1777,0x1778,0x1379,\n"); fprintf(fp, " 0x137a,0x177b,0x137c,0x177d,0x177e,0x137f,0x9380,0x9781,\n"); fprintf(fp, " 0x9782,0x9383,0x9784,0x9385,0x9386,0x9787,0x9788,0x9389,\n"); fprintf(fp, " 0x938a,0x978b,0x938c,0x978d,0x978e,0x938f,0x9790,0x9391,\n"); fprintf(fp, " 0x9392,0x9793,0x9394,0x9795,0x9796,0x9397,0x9398,0x9799,\n"); fprintf(fp, " 0x979a,0x939b,0x979c,0x939d,0x939e,0x979f,0x97a0,0x93a1,\n"); fprintf(fp, " 0x93a2,0x97a3,0x93a4,0x97a5,0x97a6,0x93a7,0x93a8,0x97a9,\n"); fprintf(fp, " 0x97aa,0x93ab,0x97ac,0x93ad,0x93ae,0x97af,0x93b0,0x97b1,\n"); fprintf(fp, " 0x97b2,0x93b3,0x97b4,0x93b5,0x93b6,0x97b7,0x97b8,0x93b9,\n"); fprintf(fp, " 0x93ba,0x97bb,0x93bc,0x97bd,0x97be,0x93bf,0x97c0,0x93c1,\n"); fprintf(fp, " 0x93c2,0x97c3,0x93c4,0x97c5,0x97c6,0x93c7,0x93c8,0x97c9,\n"); fprintf(fp, " 0x97ca,0x93cb,0x97cc,0x93cd,0x93ce,0x97cf,0x93d0,0x97d1,\n"); fprintf(fp, " 0x97d2,0x93d3,0x97d4,0x93d5,0x93d6,0x97d7,0x97d8,0x93d9,\n"); fprintf(fp, " 0x93da,0x97db,0x93dc,0x97dd,0x97de,0x93df,0x93e0,0x97e1,\n"); fprintf(fp, " 0x97e2,0x93e3,0x97e4,0x93e5,0x93e6,0x97e7,0x97e8,0x93e9,\n"); fprintf(fp, " 0x93ea,0x97eb,0x93ec,0x97ed,0x97ee,0x93ef,0x97f0,0x93f1,\n"); fprintf(fp, " 0x93f2,0x97f3,0x93f4,0x97f5,0x97f6,0x93f7,0x93f8,0x97f9,\n"); fprintf(fp, " 0x97fa,0x93fb,0x97fc,0x93fd,0x93fe,0x97ff,0x5700,0x1301,\n"); fprintf(fp, " 0x1302,0x1703,0x1304,0x1705,0x1706,0x1307,0x1308,0x1709,\n"); fprintf(fp, " 0x170a,0x130b,0x170c,0x130d,0x130e,0x170f,0x1310,0x1711,\n"); fprintf(fp, " 0x1712,0x1313,0x1714,0x1315,0x1316,0x1717,0x1718,0x1319,\n"); fprintf(fp, " 0x131a,0x171b,0x131c,0x171d,0x171e,0x131f,0x1320,0x1721,\n"); fprintf(fp, " 0x1722,0x1323,0x1724,0x1325,0x1326,0x1727,0x1728,0x1329,\n"); fprintf(fp, " 0x132a,0x172b,0x132c,0x172d,0x172e,0x132f,0x1730,0x1331,\n"); fprintf(fp, " 0x1332,0x1733,0x1334,0x1735,0x1736,0x1337,0x1338,0x1739,\n"); fprintf(fp, " 0x173a,0x133b,0x173c,0x133d,0x133e,0x173f,0x1340,0x1741,\n"); fprintf(fp, " 0x1742,0x1343,0x1744,0x1345,0x1346,0x1747,0x1748,0x1349,\n"); fprintf(fp, " 0x134a,0x174b,0x134c,0x174d,0x174e,0x134f,0x1750,0x1351,\n"); fprintf(fp, " 0x1352,0x1753,0x1354,0x1755,0x1756,0x1357,0x1358,0x1759,\n"); fprintf(fp, " 0x175a,0x135b,0x175c,0x135d,0x135e,0x175f,0x1760,0x1361,\n"); fprintf(fp, " 0x1362,0x1763,0x1364,0x1765,0x1766,0x1367,0x1368,0x1769,\n"); fprintf(fp, " 0x176a,0x136b,0x176c,0x136d,0x136e,0x176f,0x1370,0x1771,\n"); fprintf(fp, " 0x1772,0x1373,0x1774,0x1375,0x1376,0x1777,0x1778,0x1379,\n"); fprintf(fp, " 0x137a,0x177b,0x137c,0x177d,0x177e,0x137f,0x9380,0x9781,\n"); fprintf(fp, " 0x9782,0x9383,0x9784,0x9385,0x9386,0x9787,0x9788,0x9389,\n"); fprintf(fp, " 0x938a,0x978b,0x938c,0x978d,0x978e,0x938f,0x9790,0x9391,\n"); fprintf(fp, " 0x9392,0x9793,0x9394,0x9795,0x9796,0x9397,0x9398,0x9799 \n"); fprintf(fp, "};\n\n"); fprintf(fp, "void DDFDCBHandler(UINT32 dwWhich);\n\n"); fprintf(fp, "\n"); } else { abort(); } } void CodeSegmentBegin(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " section .text use32 flat class=code\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "static void InvalidInstruction(UINT32 dwCount)\n"); fprintf(fp, "{\n"); fprintf(fp, " pbPC -= dwCount; /* Invalid instruction - back up */\n"); fprintf(fp, " dwReturnCode = (UINTPTR) pbPC - (UINTPTR) cpu.z80Base;\n"); fprintf(fp, " dwOriginalCycles -= sdwCyclesRemaining;\n"); fprintf(fp, " sdwCyclesRemaining = 0;\n"); fprintf(fp, "}\n\n"); } else { abort(); } } void CodeSegmentEnd(void) { } void ProgramEnd(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, "\n"); fprintf(fp, "%%ifdef NASM_STACK_NOEXEC\n"); fprintf(fp, "section .note.GNU-stack noalloc noexec nowrite progbits\n"); fprintf(fp, "%%endif\n"); } else if (MZ80_C == bWhat) { } else { abort(); } } void EmitRegularInstructions(void) { UINT32 dwLoop = 0; UINT32 dwLoop2 = 0; bCurrentMode = TIMING_REGULAR; if (MZ80_ASSEMBLY_X86 == bWhat) { while (dwLoop < 0x100) { dwLoop2 = 0; sprintf(procname, "RegInst%.2x", dwLoop); while (StandardOps[dwLoop2].bOpCode != dwLoop && StandardOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; assert(dwLoop2 < 0x100); if (StandardOps[dwLoop2].Emitter && StandardOps[dwLoop2].bOpCode != 0xffffffff) StandardOps[dwLoop2].Emitter((UINT32) dwLoop); dwLoop++; } } else if (MZ80_C == bWhat) { fprintf(fp, "/* Main execution entry point */\n\n"); fprintf(fp, "UINT32 %sexec(UINT32 dwCycles)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " UINT8 bOpcode;\n\n"); fprintf(fp, " dwReturnCode = 0x80000000; /* Assume it'll work */\n"); fprintf(fp, " sdwCyclesRemaining = dwCycles;\n"); fprintf(fp, " dwOriginalCycles = dwCycles;\n"); fprintf(fp, " if (cpu.z80halted)\n"); fprintf(fp, " {\n"); fprintf(fp, " dwElapsedTicks += dwCycles;\n"); fprintf(fp, " return(0x80000000);\n"); fprintf(fp, " }\n\n"); fprintf(fp, " pbPC = cpu.z80Base + cpu.z80pc;\n\n"); fprintf(fp, " while (sdwCyclesRemaining > 0)\n"); fprintf(fp, " {\n"); fprintf(fp, " bOpcode = *pbPC++;\n"); fprintf(fp, " switch (bOpcode)\n"); fprintf(fp, " {\n"); while (dwLoop < 0x100) { dwLoop2 = 0; fprintf(fp, " case 0x%.2x:\n", dwLoop); fprintf(fp, " {\n"); while (StandardOps[dwLoop2].bOpCode != dwLoop && StandardOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; if (bTimingRegular[dwLoop]) { fprintf(fp, " sdwCyclesRemaining -= %" PRIu32 ";\n", bTimingRegular[dwLoop]); } if (StandardOps[dwLoop2].Emitter) { StandardOps[dwLoop2].Emitter(dwLoop); } fprintf(fp, " break;\n"); fprintf(fp, " }\n"); ++dwLoop; } fprintf(fp, " }\n"); fprintf(fp, " }\n\n"); fprintf(fp, " dwElapsedTicks += (dwOriginalCycles - sdwCyclesRemaining);\n\n"); fprintf(fp, " cpu.z80pc = (UINTPTR) pbPC - (UINTPTR) cpu.z80Base;\n"); fprintf(fp, " return(dwReturnCode); /* Indicate success */\n"); fprintf(fp, "}\n\n"); } else { abort(); } } void EmitCBInstructions(void) { UINT32 dwLoop = 0; UINT32 dwLoop2 = 0; bCurrentMode = TIMING_CB; if (MZ80_ASSEMBLY_X86 == bWhat) { while (dwLoop < 0x100) { sprintf(procname, "CBInst%.2x", dwLoop); dwLoop2 = 0; while (CBOps[dwLoop2].bOpCode != dwLoop && CBOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; assert(dwLoop2 < 0x100); if (CBOps[dwLoop2].Emitter && CBOps[dwLoop2].bOpCode != 0xffffffff) CBOps[dwLoop2].Emitter((UINT32) dwLoop); dwLoop++; } } else if (MZ80_C == bWhat) { fprintf(fp, "void CBHandler(void)\n"); fprintf(fp, "{\n"); fprintf(fp, " switch (*pbPC++)\n"); fprintf(fp, " {\n"); while (dwLoop < 0x100) { dwLoop2 = 0; fprintf(fp, " case 0x%.2x:\n", dwLoop); fprintf(fp, " {\n"); while (CBOps[dwLoop2].bOpCode != dwLoop && CBOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; if (bTimingCB[dwLoop]) { fprintf(fp, " sdwCyclesRemaining -= %" PRIu32 ";\n", bTimingCB[dwLoop]); } if (CBOps[dwLoop2].Emitter) { CBOps[dwLoop2].Emitter(dwLoop); } else { InvalidInstructionC(2); } fprintf(fp, " break;\n"); fprintf(fp, " }\n"); ++dwLoop; } fprintf(fp, " }\n"); fprintf(fp, "}\n"); } else { abort(); } } void EmitEDInstructions(void) { UINT32 dwLoop = 0; UINT32 dwLoop2 = 0; bCurrentMode = TIMING_ED; if (MZ80_ASSEMBLY_X86 == bWhat) { while (dwLoop < 0x100) { sprintf(procname, "EDInst%.2x", dwLoop); dwLoop2 = 0; while (EDOps[dwLoop2].bOpCode != dwLoop && EDOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; assert(dwLoop2 < 0x100); if (EDOps[dwLoop2].Emitter && EDOps[dwLoop2].bOpCode != 0xffffffff) EDOps[dwLoop2].Emitter((UINT32) dwLoop); dwLoop++; } } else if (MZ80_C == bWhat) { fprintf(fp, "void EDHandler(void)\n"); fprintf(fp, "{\n"); fprintf(fp, " switch (*pbPC++)\n"); fprintf(fp, " {\n"); while (dwLoop < 0x100) { dwLoop2 = 0; fprintf(fp, " case 0x%.2x:\n", dwLoop); fprintf(fp, " {\n"); while (EDOps[dwLoop2].bOpCode != dwLoop && EDOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; if (bTimingED[dwLoop]) { fprintf(fp, " sdwCyclesRemaining -= %" PRIu32 ";\n", bTimingED[dwLoop]); } if (EDOps[dwLoop2].Emitter) { EDOps[dwLoop2].Emitter(dwLoop); } else { InvalidInstructionC(2); } fprintf(fp, " break;\n"); fprintf(fp, " }\n"); ++dwLoop; } fprintf(fp, " }\n"); fprintf(fp, "}\n"); } else { abort(); } fprintf(fp, "\n"); } void EmitDDInstructions(void) { UINT32 dwLoop = 0; UINT32 dwLoop2 = 0; bCurrentMode = TIMING_DDFD; if (MZ80_ASSEMBLY_X86 == bWhat) { while (dwLoop < 0x100) { sprintf(procname, "DDInst%.2x", dwLoop); dwLoop2 = 0; while (DDFDOps[dwLoop2].bOpCode != dwLoop && DDFDOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; assert(dwLoop2 < 0x100); if (DDFDOps[dwLoop2].Emitter && DDFDOps[dwLoop2].bOpCode != 0xffffffff) DDFDOps[dwLoop2].Emitter((UINT32) dwLoop); dwLoop++; } bCurrentMode = TIMING_XXCB; dwLoop = 0; while (dwLoop < 0x100) { sprintf(procname, "DDFDCBInst%.2x", dwLoop); dwLoop2 = 0; while (DDFDCBOps[dwLoop2].bOpCode != dwLoop && DDFDCBOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; assert(dwLoop2 < 0x100); if (DDFDCBOps[dwLoop2].Emitter && DDFDCBOps[dwLoop2].bOpCode != 0xffffffff) DDFDCBOps[dwLoop2].Emitter((UINT32) dwLoop); dwLoop++; } } else if (MZ80_C == bWhat) { fprintf(fp, "void DDHandler(void)\n"); fprintf(fp, "{\n"); fprintf(fp, " switch (*pbPC++)\n"); fprintf(fp, " {\n"); while (dwLoop < 0x100) { dwLoop2 = 0; fprintf(fp, " case 0x%.2x:\n", dwLoop); fprintf(fp, " {\n"); while (DDFDOps[dwLoop2].bOpCode != dwLoop && DDFDOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; if (bTimingDDFD[dwLoop]) { fprintf(fp, " sdwCyclesRemaining -= %" PRIu32 ";\n", bTimingDDFD[dwLoop]); } if (DDFDOps[dwLoop2].Emitter) { DDFDOps[dwLoop2].Emitter(dwLoop); } else { InvalidInstructionC(2); } fprintf(fp, " break;\n"); fprintf(fp, " }\n"); ++dwLoop; } fprintf(fp, " }\n"); fprintf(fp, "}\n"); // DDFD Handler bCurrentMode = TIMING_XXCB; dwLoop = 0; fprintf(fp, "void DDFDCBHandler(UINT32 dwWhich)\n"); fprintf(fp, "{\n"); fprintf(fp, " if (dwWhich)\n"); fprintf(fp, " {\n"); fprintf(fp, " dwAddr = (UINT32) ((INT32) cpu.z80IY + ((INT32) *pbPC++)) & 0xffff;\n"); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " dwAddr = (UINT32) ((INT32) cpu.z80IX + ((INT32) *pbPC++)) & 0xffff;\n"); fprintf(fp, " }\n\n"); ReadValueFromMemory("dwAddr", "bTemp"); fprintf(fp, " switch (*pbPC++)\n"); fprintf(fp, " {\n"); while (dwLoop < 0x100) { dwLoop2 = 0; fprintf(fp, " case 0x%.2x:\n", dwLoop); fprintf(fp, " {\n"); while (DDFDCBOps[dwLoop2].bOpCode != dwLoop && DDFDCBOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; if (bTimingXXCB[dwLoop]) { fprintf(fp, " sdwCyclesRemaining -= %" PRIu32 ";\n", bTimingXXCB[dwLoop]); } if (DDFDCBOps[dwLoop2].Emitter) { DDFDCBOps[dwLoop2].Emitter(dwLoop); } else { InvalidInstructionC(4); } fprintf(fp, " break;\n"); fprintf(fp, " }\n"); ++dwLoop; } fprintf(fp, " }\n"); fprintf(fp, "}\n"); } else { abort(); } } void EmitFDInstructions(void) { UINT32 dwLoop = 0; UINT32 dwLoop2 = 0; bCurrentMode = TIMING_DDFD; if (MZ80_ASSEMBLY_X86 == bWhat) { while (dwLoop < 0x100) { sprintf(procname, "FDInst%.2x", dwLoop); dwLoop2 = 0; while (DDFDOps[dwLoop2].bOpCode != dwLoop && DDFDOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; assert(dwLoop2 < 0x100); if (DDFDOps[dwLoop2].Emitter && DDFDOps[dwLoop2].bOpCode != 0xffffffff) DDFDOps[dwLoop2].Emitter((UINT32) dwLoop); dwLoop++; } } else if (MZ80_C == bWhat) { fprintf(fp, "void FDHandler(void)\n"); fprintf(fp, "{\n"); fprintf(fp, " switch (*pbPC++)\n"); fprintf(fp, " {\n"); while (dwLoop < 0x100) { dwLoop2 = 0; fprintf(fp, " case 0x%.2x:\n", dwLoop); fprintf(fp, " {\n"); while (DDFDOps[dwLoop2].bOpCode != dwLoop && DDFDOps[dwLoop2].bOpCode != 0xffffffff) dwLoop2++; if (bTimingDDFD[dwLoop]) { fprintf(fp, " sdwCyclesRemaining -= %" PRIu32 ";\n", bTimingDDFD[dwLoop]); } if (DDFDOps[dwLoop2].Emitter) { DDFDOps[dwLoop2].Emitter(dwLoop); } else { InvalidInstructionC(2); } fprintf(fp, " break;\n"); fprintf(fp, " }\n"); ++dwLoop; } fprintf(fp, " }\n"); fprintf(fp, "}\n"); } else { abort(); } } /* These are the meta routines */ void ReadMemoryByteHandler() { if (MZ80_ASSEMBLY_X86 == bWhat) { Alignment(); fprintf(fp, "; This is a generic read memory byte handler when a foreign\n"); fprintf(fp, "; handler is to be called\n\n"); fprintf(fp, "; EDI=Handler address, EDX=Address\n"); fprintf(fp, "; On return, EDX & EDI are undisturbed and AL=Byte read\n\n"); fprintf(fp, "ReadMemoryByte:\n"); fprintf(fp, " mov [_z80af], ax ; Save AF\n"); fprintf(fp, " cmp [edi+8], dword 0 ; Null handler?\n"); fprintf(fp, " je directReadHandler ; Yep! It's a direct read!\n\n"); fprintf(fp, " mov [_z80hl], bx ; Save HL\n"); fprintf(fp, " mov [_z80bc], cx ; Save BC\n"); fprintf(fp, " sub esi, ebp ; Our program counter\n"); fprintf(fp, " mov [_z80pc], si ; Save our program counter\n"); // Now adjust the proper timing fprintf(fp, " mov esi, [dwOriginalExec] \n"); fprintf(fp, " sub esi, [cyclesRemaining]\n"); fprintf(fp, " add [dwElapsedTicks], esi\n"); fprintf(fp, " add [_z80rCounter], esi\n"); fprintf(fp, " sub [dwOriginalExec], esi\n"); fprintf(fp, " push edi ; Save our structure address\n"); fprintf(fp, " push edx ; And our desired address\n"); if (FALSE == bUseStack) { fprintf(fp, " mov eax, edx ; Get our desired address reg\n"); fprintf(fp, " mov edx, edi ; Pointer to the structure\n"); } fprintf(fp, " call dword [edi + 8] ; Go call our handler\n"); fprintf(fp, " pop edx ; Restore our address\n"); fprintf(fp, " pop edi ; Restore our handler's address\n"); fprintf(fp, " xor ebx, ebx ; Zero our future HL\n"); fprintf(fp, " xor esi, esi ; Zero it!\n"); fprintf(fp, " mov ebp, [_z80Base] ; Base pointer comes back\n"); fprintf(fp, " mov si, [_z80pc] ; Get our program counter back\n"); fprintf(fp, " xor ecx, ecx ; Zero our future BC\n"); fprintf(fp, " add esi, ebp ; Rebase it properly\n"); fprintf(fp, " mov bx, [_z80hl] ; Get HL back\n"); fprintf(fp, " mov cx, [_z80bc] ; Get BC back\n"); // Note: the callee must restore AF! fprintf(fp, " ret\n\n"); fprintf(fp, "directReadHandler:\n"); fprintf(fp, " mov eax, [edi+12] ; Get our base address\n"); fprintf(fp, " sub edx, [edi] ; Subtract our base (low) address\n"); fprintf(fp, " mov al, [edx+eax] ; Get our data byte\n"); fprintf(fp, " and eax, 0ffh ; Only the lower byte matters!\n"); fprintf(fp, " add edx, [edi] ; Add our base back\n"); fprintf(fp, " ret ; Return to caller!\n\n"); } else if (MZ80_C == bWhat) { } else { abort(); } } void WriteMemoryByteHandler() { if (MZ80_ASSEMBLY_X86 == bWhat) { Alignment(); fprintf(fp, "; This is a generic read memory byte handler when a foreign\n"); fprintf(fp, "; handler is to be called.\n"); fprintf(fp, "; EDI=Handler address, AL=Byte to write, EDX=Address\n"); fprintf(fp, "; EDI and EDX Are undisturbed on exit\n\n"); fprintf(fp, "WriteMemoryByte:\n"); fprintf(fp, " cmp [edi+8], dword 0 ; Null handler?\n"); fprintf(fp, " je directWriteHandler\n\n"); fprintf(fp, " mov [_z80hl], bx ; Save HL\n"); fprintf(fp, " mov [_z80bc], cx ; Save BX\n"); fprintf(fp, " sub esi, ebp ; Our program counter\n"); fprintf(fp, " mov [_z80pc], si ; Save our program counter\n"); // Now adjust the proper timing fprintf(fp, " mov esi, [dwOriginalExec] \n"); fprintf(fp, " sub esi, [cyclesRemaining]\n"); fprintf(fp, " add [dwElapsedTicks], esi\n"); fprintf(fp, " add [_z80rCounter], esi\n"); fprintf(fp, " sub [dwOriginalExec], esi\n"); fprintf(fp, " push edi ; Save our structure address\n"); if (bUseStack) fprintf(fp, " push eax ; Data to write\n"); fprintf(fp, " push edx ; And our desired address\n"); if (FALSE == bUseStack) { fprintf(fp, " xchg eax, edx ; Swap address/data around\n"); fprintf(fp, " mov ebx, edi ; Our MemoryWriteByte structure address\n"); } fprintf(fp, " call dword [edi + 8] ; Go call our handler\n"); fprintf(fp, " pop edx ; Restore our address\n"); if (bUseStack) fprintf(fp, " pop eax ; Restore our data written\n"); fprintf(fp, " pop edi ; Save our structure address\n"); fprintf(fp, " xor ebx, ebx ; Zero our future HL\n"); fprintf(fp, " xor ecx, ecx ; Zero our future BC\n"); fprintf(fp, " mov bx, [_z80hl] ; Get HL back\n"); fprintf(fp, " mov cx, [_z80bc] ; Get BC back\n"); fprintf(fp, " mov ax, [_z80af] ; Get AF back\n"); fprintf(fp, " xor esi, esi ; Zero it!\n"); fprintf(fp, " mov si, [_z80pc] ; Get our program counter back\n"); fprintf(fp, " mov ebp, [_z80Base] ; Base pointer comes back\n"); fprintf(fp, " add esi, ebp ; Rebase it properly\n"); fprintf(fp, " ret\n\n"); fprintf(fp, "directWriteHandler:\n"); fprintf(fp, " sub edx, [edi] ; Subtract our offset\n"); fprintf(fp, " add edx, [edi+12] ; Add in the base address\n"); fprintf(fp, " mov [edx], al ; Store our byte\n"); fprintf(fp, " sub edx, [edi+12] ; Restore our base address\n"); fprintf(fp, " add edx, [edi] ; And put our offset back\n"); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { } else { abort(); } } void PushWordHandler() { if (MZ80_ASSEMBLY_X86 == bWhat) { Alignment(); fprintf(fp, ";\n"); fprintf(fp, "; DX=Top of SP, [_wordval]=word value to push\n"); fprintf(fp, ";\n\n"); fprintf(fp, "PushWord:\n"); fprintf(fp, " mov dx, [_z80sp]\n"); fprintf(fp, " dec dx\n"); WriteValueToMemory("dx", "byte [_wordval+1]"); fprintf(fp, " dec dx\n"); WriteValueToMemory("dx", "byte [_wordval]"); fprintf(fp, " sub [_z80sp], word 2\n"); fprintf(fp, " xor edx, edx\n"); fprintf(fp, " ret\n\n"); } } void PopWordHandler() { if (MZ80_ASSEMBLY_X86 == bWhat) { Alignment(); fprintf(fp, ";\n"); fprintf(fp, "; [_z80sp]=Top of SP, DX=Word value read\n"); fprintf(fp, ";\n\n"); fprintf(fp, "PopWord:\n"); fprintf(fp, " mov dx, [_z80sp]\n"); ReadWordFromMemory("dx", "dx"); fprintf(fp, " ret\n\n"); } } void ReadIoHandler() { if (MZ80_ASSEMBLY_X86 == bWhat) { Alignment(); fprintf(fp, "; This is a generic I/O read byte handler for when a foreign\n"); fprintf(fp, "; handler is to be called\n"); fprintf(fp, "; EDI=Handler address, EDX=I/O Address\n"); fprintf(fp, "; On return, EDX & EDI are undisturbed and AL=Byte read\n\n"); fprintf(fp, "ReadIOByte:\n"); fprintf(fp, " mov [_z80af], ax ; Save AF\n"); fprintf(fp, " mov [_z80hl], bx ; Save HL\n"); fprintf(fp, " mov [_z80bc], cx ; Save BC\n"); fprintf(fp, " sub esi, ebp ; Our program counter\n"); fprintf(fp, " mov [_z80pc], si ; Save our program counter\n"); // Now adjust the proper timing fprintf(fp, " mov esi, [dwOriginalExec] \n"); fprintf(fp, " sub esi, [cyclesRemaining]\n"); fprintf(fp, " add [dwElapsedTicks], esi\n"); fprintf(fp, " add [_z80rCounter], esi\n"); fprintf(fp, " sub [dwOriginalExec], esi\n"); fprintf(fp, " push edi ; Save our structure address\n"); fprintf(fp, " push edx ; And our desired I/O port\n"); if (FALSE == bUseStack) { fprintf(fp, " mov eax, edx ; Get our desired address reg\n"); fprintf(fp, " mov edx, edi ; Pointer to the structure\n"); } fprintf(fp, " call dword [edi + 4] ; Go call our handler\n"); fprintf(fp, " pop edx ; Restore our address\n"); fprintf(fp, " pop edi ; Restore our handler's address\n"); fprintf(fp, " xor ebx, ebx ; Zero our future HL\n"); fprintf(fp, " xor ecx, ecx ; Zero our future BC\n"); fprintf(fp, " xor esi, esi ; Zero it!\n"); fprintf(fp, " mov si, [_z80pc] ; Get our program counter back\n"); fprintf(fp, " mov ebp, [_z80Base] ; Base pointer comes back\n"); fprintf(fp, " add esi, ebp ; Rebase it properly\n"); fprintf(fp, " mov bx, [_z80hl] ; Get HL back\n"); fprintf(fp, " mov cx, [_z80bc] ; Get BC back\n"); // Note: the callee must restore AF! fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { } else { abort(); } } void WriteIoHandler() { if (MZ80_ASSEMBLY_X86 == bWhat) { Alignment(); fprintf(fp, "; This is a generic write I/O byte handler when a foreign handler is to\n"); fprintf(fp, "; be called\n"); fprintf(fp, "; EDI=Handler address, AL=Byte to write, EDX=I/O Address\n"); fprintf(fp, "; EDI and EDX Are undisturbed on exit\n\n"); fprintf(fp, "WriteIOByte:\n"); fprintf(fp, " mov [_z80hl], bx ; Save HL\n"); fprintf(fp, " mov [_z80bc], cx ; Save BX\n"); fprintf(fp, " sub esi, ebp ; Our program counter\n"); fprintf(fp, " mov [_z80pc], si ; Save our program counter\n"); // Now adjust the proper timing fprintf(fp, " mov esi, [dwOriginalExec] \n"); fprintf(fp, " sub esi, [cyclesRemaining]\n"); fprintf(fp, " add [dwElapsedTicks], esi\n"); fprintf(fp, " add [_z80rCounter], esi\n"); fprintf(fp, " sub [dwOriginalExec], esi\n"); fprintf(fp, " push edi ; Save our structure address\n"); if (bUseStack) fprintf(fp, " push eax ; Data to write\n"); fprintf(fp, " push edx ; And our desired I/O address\n"); if (FALSE == bUseStack) { fprintf(fp, " xchg eax, edx ; Swap address/data around\n"); fprintf(fp, " mov ebx, edi ; Our z80IoWrite structure address\n"); } fprintf(fp, " call dword [edi + 4] ; Go call our handler\n"); fprintf(fp, " pop edx ; Restore our address\n"); if (bUseStack) fprintf(fp, " pop eax ; Restore our data written\n"); fprintf(fp, " pop edi ; Save our structure address\n"); fprintf(fp, " xor ebx, ebx ; Zero our future HL\n"); fprintf(fp, " xor ecx, ecx ; Zero our future BC\n"); fprintf(fp, " mov bx, [_z80hl] ; Get HL back\n"); fprintf(fp, " mov cx, [_z80bc] ; Get BC back\n"); fprintf(fp, " mov ax, [_z80af] ; Get AF back\n"); fprintf(fp, " xor esi, esi ; Zero it!\n"); fprintf(fp, " mov si, [_z80pc] ; Get our program counter back\n"); fprintf(fp, " mov ebp, [_z80Base] ; Base pointer comes back\n"); fprintf(fp, " add esi, ebp ; Rebase it properly\n"); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { } else { abort(); } } void ExecCode(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sexec\n", cpubasename); fprintf(fp, " global %sexec_\n", cpubasename); if (bPlain) fprintf(fp, " global %sexec\n", cpubasename); sprintf(procname, "%sexec_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sexec:\n", cpubasename); if (bPlain) fprintf(fp, "%sexec:\n", cpubasename); if (bUseStack) fprintf(fp, " mov eax, [esp+4] ; Get our execution cycle count\n"); fprintf(fp, " push ebx ; Save all registers we use\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push edx\n"); fprintf(fp, " push ebp\n"); fprintf(fp, " push esi\n"); fprintf(fp, " push edi\n"); fprintf(fp, "\n"); fprintf(fp, " mov edi, eax\n"); fprintf(fp, " mov dword [cyclesRemaining], eax ; Store # of instructions to\n"); fprintf(fp, " mov [dwLastRSample], eax\n"); fprintf(fp, " mov [dwOriginalExec], eax ; Store this!\n"); fprintf(fp, " cmp dword [_z80halted], 0\n"); fprintf(fp, " je goCpu\n"); fprintf(fp, " add [_z80rCounter], eax\n"); if (FALSE == bNoTiming) { fprintf(fp, " add dword [dwElapsedTicks], eax\n"); } fprintf(fp, " mov dword [cyclesRemaining], 0 ; Nothing left!\n"); fprintf(fp, " mov eax, 80000000h ; Successful exection\n"); fprintf(fp, " jmp popReg\n"); fprintf(fp, "goCpu:\n"); fprintf(fp, " cld ; Go forward!\n"); fprintf(fp, "\n"); fprintf(fp, " xor eax, eax ; Zero EAX 'cause we use it!\n"); fprintf(fp, " xor ebx, ebx ; Zero EBX, too\n"); fprintf(fp, " xor ecx, ecx ; Zero ECX\n"); fprintf(fp, " xor edx, edx ; And EDX\n"); fprintf(fp, " xor esi, esi ; Zero our source address\n"); fprintf(fp, "\n"); fprintf(fp, " mov ax, [_z80af] ; Accumulator & flags\n"); fprintf(fp, " xchg ah, al ; Swap these for later\n"); fprintf(fp, " mov bx, [_z80hl] ; Get our HL value\n"); fprintf(fp, " mov cx, [_z80bc] ; And our BC value\n"); fprintf(fp, " mov ebp, [_z80Base] ; Get the base address\n"); fprintf(fp, " mov si, [_z80pc] ; Get our program counter\n"); fprintf(fp, " add esi, ebp ; Add in our base address\n"); fprintf(fp, " cmp [_z80intPending], byte 0 ; Interrupt pending?\n"); fprintf(fp, " jz masterExecTarget\n\n"); fprintf(fp, " call causeInternalInterrupt\n\n"); fprintf(fp, "masterExecTarget:\n"); fprintf(fp, " mov dl, [esi]\n"); fprintf(fp, " inc esi\n"); fprintf(fp, " jmp dword [z80regular+edx*4]\n\n"); fprintf(fp, "; We get to invalidInsWord if it's a double byte invalid opcode\n"); fprintf(fp, "\n"); fprintf(fp, "invalidInsWord:\n"); fprintf(fp, " dec esi\n"); fprintf(fp, "\n"); fprintf(fp, "; We get to invalidInsByte if it's a single byte invalid opcode\n"); fprintf(fp, "\n"); fprintf(fp, "invalidInsByte:\n"); fprintf(fp, " xchg ah, al ; Swap them back so they look good\n"); fprintf(fp, " mov [_z80af], ax ; Store A & flags\n"); fprintf(fp, " dec esi ; Back up one instruction...\n"); fprintf(fp, " mov edx, esi ; Get our address in EAX\n"); fprintf(fp, " sub edx, ebp ; And subtract our base for\n"); fprintf(fp, " ; an invalid instruction\n"); fprintf(fp, " jmp short emulateEnd\n"); fprintf(fp, "\n"); fprintf(fp, "noMoreExec:\n"); fprintf(fp, " cmp [bEIExit], byte 0 ; Are we exiting because of an EI?\n"); fprintf(fp, " jne checkEI\n"); fprintf(fp, "noMoreExecNoEI:\n"); fprintf(fp, " xchg ah, al ; Swap these for later\n"); fprintf(fp, " mov [_z80af], ax ; Store A & flags\n"); fprintf(fp, " mov edx, [dwOriginalExec] ; Original exec time\n"); fprintf(fp, " sub edx, edi ; Subtract # of cycles remaining\n"); fprintf(fp, " add [_z80rCounter], edx\n"); fprintf(fp, " add [dwElapsedTicks], edx ; Add our executed time\n"); fprintf(fp, " mov edx, 80000000h ; Indicate successful exec\n"); fprintf(fp, " jmp short emulateEnd ; All finished!\n"); fprintf(fp, "\n"); fprintf(fp, "; Now let's tuck away the virtual registers for next time\n"); fprintf(fp, "\n"); fprintf(fp, "storeFlags:\n"); fprintf(fp, " xchg ah, al ; Swap these for later\n"); fprintf(fp, " mov [_z80af], ax ; Store A & flags\n"); fprintf(fp, "emulateEnd:\n"); fprintf(fp, " mov [_z80hl], bx ; Store HL\n"); fprintf(fp, " mov [_z80bc], cx ; Store BC\n"); fprintf(fp, " sub esi, [_z80Base] ; Knock off physical address\n"); fprintf(fp, " mov [_z80pc], si ; And store virtual address\n"); fprintf(fp, " mov eax, edx ; Result code return\n"); fprintf(fp, "\n"); fprintf(fp, "popReg:\n"); fprintf(fp, " pop edi ; Restore registers\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " pop ebp\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop ebx\n"); fprintf(fp, "\n"); fprintf(fp, " ret\n"); fprintf(fp, "\n"); Alignment(); fprintf(fp, "checkEI:\n"); fprintf(fp, " xor edx, edx\n"); fprintf(fp, " mov [bEIExit], byte 0\n"); fprintf(fp, " sub edx, edi ; Find out how much time has passed\n"); fprintf(fp, " mov edi, [dwEITiming]\n"); fprintf(fp, " sub edi, edx\n"); fprintf(fp, " js noMoreExecNoEI\n"); fprintf(fp, " xor edx, edx\n"); fprintf(fp, " cmp [_z80intPending], byte 0\n"); fprintf(fp, " je near masterExecTarget\n"); fprintf(fp, " call causeInternalInterrupt\n"); fprintf(fp, " jmp masterExecTarget\n\n"); Alignment(); fprintf(fp, "causeInternalInterrupt:\n"); fprintf(fp, " mov dword [_z80halted], 0 ; We're not halted anymore!\n"); fprintf(fp, " test [_z80iff], byte IFF1 ; Interrupt enabled yet?\n"); fprintf(fp, " jz near internalInterruptsDisabled\n"); fprintf(fp, "\n; Interrupts enabled. Clear IFF1 and IFF2\n\n"); fprintf(fp, " mov [_z80intPending], byte 0\n"); fprintf(fp, "\n; Save off our active register sets\n\n"); fprintf(fp, " xchg ah, al ; Swap these for later\n"); fprintf(fp, " mov [_z80af], ax ; Store A & flags\n"); fprintf(fp, " mov [_z80hl], bx ; Store HL\n"); fprintf(fp, " mov [_z80bc], cx ; Store BC\n"); fprintf(fp, " sub esi, ebp ; Knock off physical address\n"); fprintf(fp, " mov [_z80pc], si ; And store virtual address\n"); fprintf(fp, " xor eax, eax\n"); fprintf(fp, " mov al, [_intData]\n\n"); fprintf(fp, "\n"); fprintf(fp, " push edi\n"); fprintf(fp, "\n"); if (bThroughCallHandler) { fprintf(fp, " pushad\n" ); fprintf(fp, " xor edx, edx\n" ); fprintf(fp, " mov ax, [_z80pc]\n"); fprintf(fp, " mov [_wordval], ax\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push ebx\n"); fprintf(fp, " push esi\n"); fprintf(fp, " mov ax, [_z80af]\n"); // Get AF fprintf(fp, " mov bx, [_z80hl]\n"); // Get HL fprintf(fp, " mov cx, [_z80bc]\n"); // Get BC fprintf(fp, " call PushWord\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " pop ebx\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " popad\n" ); } else { fprintf(fp, " mov dx, [_z80pc]\n"); fprintf(fp, " xor edi, edi\n"); fprintf(fp, " mov di, word [_z80sp]\n"); fprintf(fp, " sub di, 2\n"); fprintf(fp, " mov word [_z80sp], di\n"); fprintf(fp, " mov [ebp+edi], dx\n"); } fprintf(fp, " cmp dword [_z80interruptMode], 2 ; Are we lower than mode 2?\n"); fprintf(fp, " jb internalJustModeTwo\n"); fprintf(fp, " mov ah, [_z80i] ; Get our high address here\n"); fprintf(fp, " and eax, 0ffffh ; Only the lower part\n"); fprintf(fp, " mov ax, [eax+ebp] ; Get our vector\n"); fprintf(fp, " jmp short internalSetNewVector ; Go set it!\n"); fprintf(fp, "internalJustModeTwo:\n"); fprintf(fp, " mov ax, word [_z80intAddr]\n"); fprintf(fp, "internalSetNewVector:\n"); fprintf(fp, " mov [_z80pc], ax\n"); fprintf(fp, "\n"); fprintf(fp, " pop edi\n"); fprintf(fp, "\n"); fprintf(fp, " xor eax, eax ; Zero this so we can use it as an index\n"); fprintf(fp, " mov al, [_z80interruptMode]\n"); fprintf(fp, " mov al, [intModeTStates+eax]\n"); fprintf(fp, " sub edi, eax\n"); fprintf(fp, " add [_z80rCounter], eax\n"); fprintf(fp, "\n; Restore all the registers and whatnot\n\n"); fprintf(fp, " mov ax, [_z80af] ; Accumulator & flags\n"); fprintf(fp, " xchg ah, al ; Swap these for later\n"); fprintf(fp, " mov bx, [_z80hl] ; Get our HL value\n"); fprintf(fp, " mov cx, [_z80bc] ; And our BC value\n"); fprintf(fp, " mov ebp, [_z80Base] ; Get the base address\n"); fprintf(fp, " mov si, [_z80pc] ; Get our program counter\n"); fprintf(fp, " add esi, ebp ; Add in our base address\n"); fprintf(fp, "internalInterruptsDisabled:\n"); fprintf(fp, " xor edx, edx\n"); fprintf(fp, " ret\n"); } else if (MZ80_C == bWhat) { } else { abort(); } } void NmiCode(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%snmi\n", cpubasename); fprintf(fp, " global %snmi_\n", cpubasename); if (bPlain) fprintf(fp, " global %snmi\n", cpubasename); sprintf(procname, "%snmi_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%snmi:\n", cpubasename); if (bPlain) fprintf(fp, "%snmi:\n", cpubasename); fprintf(fp, " mov dword [_z80halted], 0 ; We're not halted anymore!\n"); fprintf(fp, " mov al, [_z80iff] ; Get our IFF setting\n"); fprintf(fp, " and al, IFF1 ; Just IFF 1\n"); fprintf(fp, " shl al, 1 ; Makes IFF1->IFF2 and zeros IFF1\n"); fprintf(fp, " mov [_z80iff], al ; Store it back to the interrupt state!\n"); fprintf(fp, "\n"); fprintf(fp, " push ebp\n"); fprintf(fp, " push edi\n"); fprintf(fp, " mov ebp, [_z80Base]\n"); fprintf(fp, "\n"); fprintf(fp, " xor eax, eax\n"); fprintf(fp, " mov ax, [_z80pc]\n"); if (bThroughCallHandler) { fprintf(fp, " push esi\n"); fprintf(fp, " push ebx\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " mov [_wordval], ax\n"); fprintf(fp, " mov esi, ebp\n"); fprintf(fp, " add esi, eax\n"); fprintf(fp, " mov ax, [_z80af]\n"); // Get AF fprintf(fp, " mov bx, [_z80hl]\n"); // Get HL fprintf(fp, " mov cx, [_z80bc]\n"); // Get BC fprintf(fp, " push ebx\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push edx\n"); fprintf(fp, " push esi\n"); fprintf(fp, " push eax\n"); fprintf(fp, " call PushWord\n"); fprintf(fp, " pop eax\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop ebx\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop ebx\n"); fprintf(fp, " pop esi\n"); } else { fprintf(fp, " xor edi, edi\n"); fprintf(fp, " mov di, word [_z80sp]\n"); fprintf(fp, " sub di, 2\n"); fprintf(fp, " mov word [_z80sp], di\n"); fprintf(fp, " mov [ebp+edi], ax\n"); } fprintf(fp, " mov ax, [_z80nmiAddr]\n"); fprintf(fp, " mov [_z80pc], ax\n"); fprintf(fp, "\n"); fprintf(fp, " add [dwElapsedTicks], dword 11 ; 11 T-States for NMI\n"); fprintf(fp, " add [_z80rCounter], dword 11\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " pop ebp\n"); fprintf(fp, "\n"); fprintf(fp, " xor eax, eax ; Indicate we took the interrupt\n"); fprintf(fp, " ret\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* NMI Handler */\n\n"); fprintf(fp, "UINT32 %snmi(void)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " cpu.z80halted = 0;\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */\n"); fprintf(fp, " *pbSP-- = cpu.z80pc >> 8; /* LSB */\n"); fprintf(fp, " *pbSP = (UINT8) cpu.z80pc; /* MSB */\n"); fprintf(fp, " cpu.z80sp -= 2; /* Back our stack up */\n"); fprintf(fp, " cpu.z80pc = cpu.z80nmiAddr; /* Our NMI */\n"); fprintf(fp, " return(0);\n"); fprintf(fp, "}\n\n"); } else { abort(); } } void IntCode(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sint\n", cpubasename); fprintf(fp, " global %sint_\n", cpubasename); if (bPlain) fprintf(fp, " global %sint\n", cpubasename); sprintf(procname, "%sint_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sint:\n", cpubasename); if (bPlain) fprintf(fp, "%sint:\n", cpubasename); if (bUseStack) fprintf(fp, " mov eax, [esp+4] ; Get our (potential) lower interrupt address\n"); fprintf(fp, " mov dword [_z80halted], 0 ; We're not halted anymore!\n"); fprintf(fp, " mov ah, IFF1 ; Is IFF1 enabled?\n"); fprintf(fp, " and ah, [_z80iff] ; Well, is it?\n"); fprintf(fp, " jz near interruptsDisabled\n"); fprintf(fp, "\n; Interrupts enabled. Clear IFF1 and IFF2\n\n"); fprintf(fp, " and dword [_z80iff], ~(IFF1 | IFF2);\n\n"); fprintf(fp, " mov [_z80intPending], byte 0\n"); fprintf(fp, "\n"); fprintf(fp, " push ebp\n"); fprintf(fp, " push edi\n"); fprintf(fp, " push edx\n"); fprintf(fp, " mov ebp, [_z80Base]\n"); fprintf(fp, "\n"); if (bThroughCallHandler) { fprintf(fp, " pushad\n" ); fprintf(fp, " xor edx, edx\n" ); fprintf(fp, " mov ax, [_z80pc]\n"); fprintf(fp, " mov [_wordval], ax\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push ebx\n"); fprintf(fp, " push esi\n"); fprintf(fp, " mov ax, [_z80af]\n"); // Get AF fprintf(fp, " mov bx, [_z80hl]\n"); // Get HL fprintf(fp, " mov cx, [_z80bc]\n"); // Get BC fprintf(fp, " call PushWord\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " pop ebx\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " popad\n" ); } else { fprintf(fp, " mov dx, [_z80pc]\n"); fprintf(fp, " xor edi, edi\n"); fprintf(fp, " mov di, word [_z80sp]\n"); fprintf(fp, " sub di, 2\n"); fprintf(fp, " mov word [_z80sp], di\n"); fprintf(fp, " mov [ebp+edi], dx\n"); } fprintf(fp, " cmp dword [_z80interruptMode], 2 ; Are we lower than mode 2?\n"); fprintf(fp, " jb justModeTwo\n"); fprintf(fp, " mov ah, [_z80i] ; Get our high address here\n"); fprintf(fp, " and eax, 0ffffh ; Only the lower part\n"); fprintf(fp, " mov ax, [eax+ebp] ; Get our vector\n"); fprintf(fp, " jmp short setNewVector ; Go set it!\n"); fprintf(fp, "justModeTwo:\n"); fprintf(fp, " mov ax, word [_z80intAddr]\n"); fprintf(fp, "setNewVector:\n"); fprintf(fp, " mov [_z80pc], ax\n"); fprintf(fp, "\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " pop ebp\n"); fprintf(fp, "\n"); fprintf(fp, " xor eax, eax ; Zero this so we can use it as an index\n"); fprintf(fp, " mov al, [_z80interruptMode]\n"); fprintf(fp, " mov al, [intModeTStates+eax]\n"); fprintf(fp, " add [dwElapsedTicks], eax\n"); fprintf(fp, " add [_z80rCounter], eax\n"); fprintf(fp, " xor eax, eax ; Indicate we took the interrupt\n"); fprintf(fp, " jmp short z80intExit\n"); fprintf(fp, "\n"); fprintf(fp, "interruptsDisabled:\n"); fprintf(fp, " mov [_z80intPending], byte 1\n"); fprintf(fp, " mov [_intData], al ; Save this info for later\n"); fprintf(fp, " mov eax, 0ffffffffh ; Indicate we didn't take it\n"); fprintf(fp, "\n"); fprintf(fp, "z80intExit:\n"); fprintf(fp, " ret\n\n"); fprintf(fp, " global _%sClearPendingInterrupt\n", cpubasename); fprintf(fp, " global %sClearPendingInterrupt_\n", cpubasename); if (bPlain) fprintf(fp, " global %sClearPendingInterrupt\n", cpubasename); sprintf(procname, "%sClearPendingInterrupt_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sClearPendingInterrupt:\n", cpubasename); if (bPlain) fprintf(fp, "%sClearPendingInterrupt:\n", cpubasename); fprintf(fp, " mov [_z80intPending], byte 0\n"); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Interrupt handler */\n\n"); fprintf(fp, "UINT32 %sint(UINT32 dwLowAddr)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " cpu.z80halted = 0;\n"); fprintf(fp, " if (0 == (cpu.z80iff & IFF1))\n"); fprintf(fp, " return(0xffffffff);\n"); fprintf(fp, " cpu.z80iff &= ~(IFF1 | IFF2);\n"); fprintf(fp, " pbSP = (cpu.z80Base + cpu.z80sp - 1); /* Normalize the stack pointer */\n"); fprintf(fp, " *pbSP-- = cpu.z80pc >> 8; /* LSB */\n"); fprintf(fp, " *pbSP = (UINT8) cpu.z80pc; /* MSB */\n"); fprintf(fp, " cpu.z80sp -= 2; /* Back our stack up */\n"); fprintf(fp, " if (2 == cpu.z80interruptMode)\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = ((UINT16) cpu.z80i << 8) | (dwLowAddr & 0xff);\n"); fprintf(fp, " cpu.z80pc = ((UINT16) cpu.z80Base[cpu.z80pc + 1] << 8) | (cpu.z80Base[cpu.z80pc]);\n"); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " cpu.z80pc = cpu.z80intAddr;\n"); fprintf(fp, " }\n"); fprintf(fp, " pbPC = cpu.z80Base + cpu.z80pc; /* Normalize the address */\n"); fprintf(fp, " return(0);\n"); fprintf(fp, "}\n\n"); fprintf(fp, "void %sClearPendingInterrupt(void)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " cpu.z80intPending = 0;\n"); fprintf(fp, "}\n\n"); } else { abort(); } } void ResetCode(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sreset\n", cpubasename); fprintf(fp, " global %sreset_\n", cpubasename); if (bPlain) fprintf(fp, " global %sreset\n", cpubasename); sprintf(procname, "%sreset_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sreset:\n", cpubasename); if (bPlain) fprintf(fp, "%sreset:\n", cpubasename); fprintf(fp, " xor eax, eax ; Zero AX\n"); fprintf(fp, "\n"); fprintf(fp, " mov dword [_z80halted], eax ; We're not halted anymore!\n"); fprintf(fp, " mov word [_z80af], 0040h ; Zero A & flags - zero flag set\n"); fprintf(fp, " mov word [_z80bc], ax ; Zero BC\n"); fprintf(fp, " mov word [_z80de], ax ; Zero DE\n"); fprintf(fp, " mov word [_z80hl], ax ; Zero HL\n"); fprintf(fp, " mov word [_z80afprime], ax ; Zero AF Prime\n"); fprintf(fp, " mov word [_z80bcprime], ax ; Zero BC prime\n"); fprintf(fp, " mov word [_z80deprime], ax ; Zero DE prime\n"); fprintf(fp, " mov word [_z80hlprime], ax ; Zero HL prime\n"); fprintf(fp, " mov byte [_z80i], al ; Zero Interrupt register\n"); fprintf(fp, " mov byte [_z80r], al ; Zero refresh register\n"); fprintf(fp, " mov word [_z80ix], 0ffffh ; Default mz80Index register\n"); fprintf(fp, " mov word [_z80iy], 0ffffh ; Default mz80Index register\n"); fprintf(fp, " mov word [_z80pc], ax ; Zero program counter\n"); fprintf(fp, " mov word [_z80sp], ax ; And the stack pointer\n"); fprintf(fp, " mov dword [_z80iff], eax ; IFF1/IFF2 disabled!\n"); fprintf(fp, " mov dword [_z80interruptMode], eax ; Clear our interrupt mode (0)\n"); fprintf(fp, " mov word [_z80intAddr], 38h ; Set default interrupt address\n"); fprintf(fp, " mov word [_z80nmiAddr], 66h ; Set default nmi addr\n"); fprintf(fp, "\n"); fprintf(fp, " ret\n"); fprintf(fp, "\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* This routine is mz80's reset handler */\n\n"); fprintf(fp, "void %sreset(void)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " cpu.z80halted = 0;\n"); fprintf(fp, " cpu.z80AF = 0;\n"); fprintf(fp, " cpu.z80F = Z80_FLAG_ZERO;\n"); fprintf(fp, " cpu.z80BC = 0;\n"); fprintf(fp, " cpu.z80DE = 0;\n"); fprintf(fp, " cpu.z80HL = 0;\n"); fprintf(fp, " cpu.z80afprime = 0;\n"); fprintf(fp, " cpu.z80bcprime = 0;\n"); fprintf(fp, " cpu.z80deprime = 0;\n"); fprintf(fp, " cpu.z80hlprime = 0;\n"); fprintf(fp, " cpu.z80i = 0;\n"); fprintf(fp, " cpu.z80r = 0;\n"); fprintf(fp, " cpu.z80IX = 0xffff; /* Yes, this is intentional */\n"); fprintf(fp, " cpu.z80IY = 0xffff; /* Yes, this is intentional */\n"); fprintf(fp, " cpu.z80pc = 0;\n"); fprintf(fp, " cpu.z80sp = 0xffff; /* Prevent segfault on reset */\n"); fprintf(fp, " cpu.z80interruptMode = 0;\n"); fprintf(fp, " cpu.z80intAddr = 0x38;\n"); fprintf(fp, " cpu.z80nmiAddr = 0x66;\n"); fprintf(fp, "}\n\n"); } else { abort(); } } void SetContextCode(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sSetContext\n", cpubasename); fprintf(fp, " global %sSetContext_\n", cpubasename); if (bPlain) fprintf(fp, " global %sSetContext\n", cpubasename); sprintf(procname, "%sSetContext_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sSetContext:\n", cpubasename); if (bPlain) fprintf(fp, "%sSetContext:\n", cpubasename); if (bUseStack) fprintf(fp, " mov eax, [esp+4] ; Get our context address\n"); fprintf(fp, " push esi ; Save registers we use\n"); fprintf(fp, " push edi\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push es\n"); fprintf(fp, " mov di, ds\n"); fprintf(fp, " mov es, di\n"); fprintf(fp, " mov edi, _%scontextBegin\n", cpubasename); fprintf(fp, " mov esi, eax ; Source address in ESI\n"); fprintf(fp, " mov ecx, (_%scontextEnd - _%scontextBegin) >> 2\n", cpubasename, cpubasename); fprintf(fp, " rep movsd\n"); fprintf(fp, " mov ecx, (_%scontextEnd - _%scontextBegin) & 0x03\n", cpubasename, cpubasename); fprintf(fp, " rep movsb\n"); fprintf(fp, " pop es\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " ret ; No return code\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Set mz80's context */\n\n"); fprintf(fp, "void %sSetContext(void *pData)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " memcpy(&cpu, pData, sizeof(CONTEXTMZ80));\n"); fprintf(fp, "}\n\n"); } else { abort(); } } void GetContextCode(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sGetContext\n", cpubasename); fprintf(fp, " global %sGetContext_\n", cpubasename); if (bPlain) fprintf(fp, " global %sGetContext\n", cpubasename); sprintf(procname, "%sGetContext_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sGetContext:\n", cpubasename); if (bPlain) fprintf(fp, "%sGetContext:\n", cpubasename); if (bUseStack) fprintf(fp, " mov eax, [esp+4] ; Get our context address\n"); fprintf(fp, " push esi ; Save registers we use\n"); fprintf(fp, " push edi\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push es\n"); fprintf(fp, " mov di, ds\n"); fprintf(fp, " mov es, di\n"); fprintf(fp, " mov esi, _%scontextBegin\n", cpubasename); fprintf(fp, " mov edi, eax ; Source address in ESI\n"); fprintf(fp, " mov ecx, (_%scontextEnd - _%scontextBegin) >> 2\n", cpubasename, cpubasename); fprintf(fp, " rep movsd\n"); fprintf(fp, " mov ecx, (_%scontextEnd - _%scontextBegin) & 0x03\n", cpubasename, cpubasename); fprintf(fp, " rep movsb\n"); fprintf(fp, " pop es\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " ret ; No return code\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Get mz80's context */\n\n"); fprintf(fp, "void %sGetContext(void *pData)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " memcpy(pData, &cpu, sizeof(CONTEXTMZ80));\n"); fprintf(fp, "}\n\n"); } else { abort(); } } void GetContextSizeCode(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sGetContextSize\n", cpubasename); fprintf(fp, " global %sGetContextSize_\n", cpubasename); if (bPlain) fprintf(fp, " global %sGetContextSize\n", cpubasename); sprintf(procname, "%sGetContextSize_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sGetContextSize:\n", cpubasename); if (bPlain) fprintf(fp, "%sGetContextSize:\n", cpubasename); fprintf(fp, " mov eax, _%scontextEnd - _%scontextBegin\n", cpubasename, cpubasename); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Get mz80's context size */\n\n"); fprintf(fp, "UINT32 %sGetContextSize(void)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " return(sizeof(CONTEXTMZ80));\n"); fprintf(fp, "}\n\n"); } else { abort(); } } void InitCode(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sinit\n", cpubasename); fprintf(fp, " global %sinit_\n", cpubasename); if (bPlain) fprintf(fp, " global %sinit\n", cpubasename); sprintf(procname, "%sinit_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sinit:\n", cpubasename); if (bPlain) fprintf(fp, "%sinit:\n", cpubasename); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Initialize MZ80 for action */\n\n"); fprintf(fp, "void %sinit(void)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, " UINT32 dwLoop;\n"); fprintf(fp, " UINT8 *pbTempPtr;\n"); fprintf(fp, " UINT8 *pbTempPtr2;\n"); fprintf(fp, " UINT8 bNewAdd;\n"); fprintf(fp, " UINT8 bNewSub;\n"); fprintf(fp, " UINT8 bFlag;\n"); fprintf(fp, " UINT8 bLow;\n"); fprintf(fp, " UINT8 bHigh;\n"); fprintf(fp, " UINT8 bCarry;\n"); fprintf(fp, "\n"); fprintf(fp, " if (NULL == pbAddAdcTable)\n"); fprintf(fp, " {\n"); fprintf(fp, " static UINT8 paat[256 * 256 * 2];"); fprintf(fp, " static UINT8 psst[256 * 256 * 2];"); fprintf(fp, "\n"); fprintf(fp, " pbAddAdcTable = paat;\n"); fprintf(fp, "\n"); fprintf(fp, " pbTempPtr = pbAddAdcTable;\n\n"); fprintf(fp, " pbSubSbcTable = psst;\n"); fprintf(fp, "\n"); fprintf(fp, " pbTempPtr2 = pbSubSbcTable;\n"); fprintf(fp, "\n"); fprintf(fp, " for (dwLoop = 0; dwLoop < (256*256*2); dwLoop++)\n"); fprintf(fp, " {\n"); fprintf(fp, " bLow = dwLoop & 0xff;\n"); fprintf(fp, " bHigh = (dwLoop >> 8) & 0xff;\n"); fprintf(fp, " bCarry = (dwLoop >> 16);\n"); fprintf(fp, "\n"); fprintf(fp, " bFlag = 0;\n"); fprintf(fp, " bNewAdd = bHigh + bLow + bCarry;\n"); fprintf(fp, "\n"); fprintf(fp, " if (0 == bNewAdd)\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_ZERO;\n"); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag = bNewAdd & 0x80; /* Sign flag */\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " if (((UINT32) bLow + (UINT32) bHigh + (UINT32) bCarry) >= 0x100)\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_CARRY;\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " if ( ((bLow ^ bHigh ^ 0x80) & (bLow ^ (bNewAdd & 0x80))) & 0x80)\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_OVERFLOW_PARITY;\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " if (((bLow & 0x0f) + (bHigh & 0x0f) + bCarry) >= 0x10)\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_HALF_CARRY;\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " *pbTempPtr++ = bFlag; /* Store our new flag */\n\n"); fprintf(fp, " // Now do subtract - Zero\n"); fprintf(fp, "\n"); fprintf(fp, " bFlag = Z80_FLAG_NEGATIVE;\n"); fprintf(fp, " bNewSub = bHigh - bLow - bCarry;\n"); fprintf(fp, "\n"); fprintf(fp, " if (0 == bNewSub)\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_ZERO;\n"); fprintf(fp, " }\n"); fprintf(fp, " else\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= bNewSub & 0x80; /* Sign flag */\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " if ( ((INT32) bHigh - (INT32) bLow - (INT32) bCarry) < 0)\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_CARRY;\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " if ( ((INT32) (bHigh & 0xf) - (INT32) (bLow & 0x0f) - (INT32) bCarry) < 0)\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_HALF_CARRY;\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " if ( ((bLow ^ bHigh) & (bHigh ^ bNewSub) & 0x80) )\n"); fprintf(fp, " {\n"); fprintf(fp, " bFlag |= Z80_FLAG_OVERFLOW_PARITY;\n"); fprintf(fp, " }\n"); fprintf(fp, "\n"); fprintf(fp, " *pbTempPtr2++ = bFlag; /* Store our sub flag */\n"); fprintf(fp, "\n"); fprintf(fp, " }\n"); fprintf(fp, " }\n"); fprintf(fp, "}\n"); } else { abort(); } } void ShutdownCode(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { fprintf(fp, " global _%sshutdown\n", cpubasename); fprintf(fp, " global %sshutdown_\n", cpubasename); if (bPlain) fprintf(fp, " global %sshutdown\n", cpubasename); sprintf(procname, "%sshutdown_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sshutdown:\n", cpubasename); if (bPlain) fprintf(fp, "%sshutdown:\n", cpubasename); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { fprintf(fp, "/* Shut down MZ80 */\n\n"); fprintf(fp, "void %sshutdown(void)\n", cpubasename); fprintf(fp, "{\n"); fprintf(fp, "}\n\n"); } else { abort(); } } void DebuggerCode(void) { if (MZ80_ASSEMBLY_X86 == bWhat) { Alignment(); fprintf(fp, ";\n"); fprintf(fp, "; In : EAX=Reg #, ESI=Context address\n"); fprintf(fp, "; Out: EAX=Value of register\n"); fprintf(fp, ";\n"); fprintf(fp, "getRegValueInternal:\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push edx\n\n"); fprintf(fp, " cmp eax, CPUREG_MAXINDEX\n"); fprintf(fp, " jae badIndex2\n\n"); fprintf(fp, " shl eax, 4 ; Times 16 for table entry size\n"); fprintf(fp, " add eax, RegTable ; Now it's the memory location\n"); fprintf(fp, " mov edx, [eax+4] ; Get the offset of the register\n"); fprintf(fp, " mov edx, [edx + esi] ; Get our value\n"); fprintf(fp, " mov ecx, [eax+8] ; Get our shift value\n"); fprintf(fp, " shr edx, cl ; Shift it right by a value\n"); fprintf(fp, " and edx, [eax+12] ; Mask off any unneeded bits\n"); fprintf(fp, " mov eax, edx ; Put our value in EAX\n"); fprintf(fp, " jmp short indexExit ; Index's exit!\n"); fprintf(fp, "badIndex2:\n"); fprintf(fp, " mov eax, 0ffffffffh\n\n"); fprintf(fp, "indexExit:\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " ret\n\n"); Alignment(); fprintf(fp, ";\n"); fprintf(fp, "; In : EAX=Value, EDX=Reg #, ESI=Context address\n"); fprintf(fp, "; Out: EAX=Value of register\n"); fprintf(fp, ";\n"); fprintf(fp, "convertValueToText:\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push edx\n\n"); fprintf(fp, " cmp edx, CPUREG_MAXINDEX\n"); fprintf(fp, " jae badIndex3\n\n"); fprintf(fp, " shl edx, 4 ; Times 16 for table entry size\n"); fprintf(fp, " add edx, RegTable ; Now it's the memory location\n"); fprintf(fp, " mov edx, [edx + 12] ; Shift mask\n"); fprintf(fp, " xor ecx, ecx ; Zero our shift\n"); fprintf(fp, "shiftLoop:\n"); fprintf(fp, " test edx, 0f0000000h ; High nibble nonzero yet?\n"); fprintf(fp, " jnz convertLoop ; Yup!\n"); fprintf(fp, " shl edx, 4 ; Move over, bacon\n"); fprintf(fp, " shl eax, 4 ; Move the value over, too\n"); fprintf(fp, " jmp short shiftLoop ; Keep shiftin'\n\n"); fprintf(fp, "convertLoop:\n"); fprintf(fp, " mov ecx, eax ; Get our value\n"); fprintf(fp, " shr ecx, 28 ; Only the top nibble\n"); fprintf(fp, " add cl, '0' ; Convert to ASCII\n"); fprintf(fp, " cmp cl, '9' ; Greater than 9?\n"); fprintf(fp, " jbe noAdd ; Nope! Don't add it\n"); fprintf(fp, " add cl, 32+7 ; Convert from lowercase a-f\n"); fprintf(fp, "noAdd:\n"); fprintf(fp, " mov [edi], cl ; New value storage\n"); fprintf(fp, " inc edi ; Next byte, please\n"); fprintf(fp, " shl eax, 4 ; Move the mask over\n"); fprintf(fp, " shl edx, 4 ; Move the mask over\n"); fprintf(fp, " jnz convertLoop ; Keep convertin'\n\n"); fprintf(fp, "badIndex3:\n"); fprintf(fp, " mov [edi], byte 0 ; Null terminate the sucker!\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " ret\n\n"); fprintf(fp, " global _%sSetRegisterValue\n", cpubasename); fprintf(fp, " global %sSetRegisterValue_\n", cpubasename); if (bPlain) fprintf(fp, " global %sSetRegisterValue\n", cpubasename); sprintf(procname, "%sSetRegisterValue_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sSetRegisterValue:\n", cpubasename); if (bPlain) fprintf(fp, "%sSetRegisterValue:\n", cpubasename); fprintf(fp, " push esi\n"); fprintf(fp, " push edi\n"); fprintf(fp, " push edx\n"); fprintf(fp, " push ecx\n"); if (bUseStack) { fprintf(fp, " mov eax, [esp+20] ; Get our register #\n"); fprintf(fp, " mov esi, [esp+24] ; Get our context address\n"); fprintf(fp, " mov edi, [esp+28] ; Value to assign\n"); } else { fprintf(fp, " mov esi, eax ; Get context\n"); fprintf(fp, " mov eax, edx ; Get register # in EAX\n"); fprintf(fp, " mov edi, ebx ; Get value to assign\n"); } fprintf(fp, " or esi, esi ; Are we NULL?\n"); fprintf(fp, " jnz userDefined\n"); fprintf(fp, " mov esi, _%scontextBegin\n", cpubasename); fprintf(fp, "userDefined:\n\n"); fprintf(fp, " shl eax, 4 ; Times 16 for reg entry size\n"); fprintf(fp, " add eax, RegTable\n"); fprintf(fp, " mov edx, [eax+12] ; Our mask\n"); fprintf(fp, " not edx ; Invert EDX!\n"); fprintf(fp, " test edi, edx ; Did we set any invalid bits?\n"); fprintf(fp, " jnz rangeViolation\n\n"); fprintf(fp, " not edx ; Toggle it back to normal\n"); fprintf(fp, " mov ecx, [eax+8] ; Get our shift value\n"); fprintf(fp, " shl edx, cl ; Shift our mask\n"); fprintf(fp, " shl eax, cl ; And our value to OR in\n"); fprintf(fp, " not edx ; Make it the inverse of what we want\n"); fprintf(fp, " mov eax, [eax+4] ; Get our offset into the context\n"); fprintf(fp, " and [esi+eax], edx ; Mask off the bits we're changin\n"); fprintf(fp, " or [esi+eax], edi ; Or in our new value\n\n"); fprintf(fp, " xor eax, eax\n"); fprintf(fp, " jmp short setExit\n\n"); fprintf(fp, "rangeViolation:\n"); fprintf(fp, " mov eax, 0ffffffffh\n\n"); fprintf(fp, "setExit:\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " pop esi\n\n"); fprintf(fp, " ret\n\n"); Alignment(); fprintf(fp, " global _%sGetRegisterValue\n", cpubasename); fprintf(fp, " global %sGetRegisterValue_\n", cpubasename); if (bPlain) fprintf(fp, " global %sGetRegisterValue\n", cpubasename); sprintf(procname, "%sGetRegisterValue_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sGetRegisterValue:\n", cpubasename); if (bPlain) fprintf(fp, "%sGetRegisterValue:\n", cpubasename); fprintf(fp, " push esi\n"); if (bUseStack) { fprintf(fp, " mov eax, [esp+8] ; Get our register #\n"); fprintf(fp, " mov esi, [esp+12] ; Get our context address\n"); } else { fprintf(fp, " mov esi, eax ; Get context\n"); fprintf(fp, " mov eax, edx ; Get register # in EAX\n"); } fprintf(fp, " or esi, esi ; Is context NULL?\n"); fprintf(fp, " jnz getVal ; Nope - use it!\n"); fprintf(fp, " mov esi, _%scontextBegin\n\n", cpubasename); fprintf(fp, "getVal:\n"); fprintf(fp, " call getRegValueInternal\n\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " ret\n\n"); Alignment(); fprintf(fp, " global _%sGetRegisterName\n", cpubasename); fprintf(fp, " global %sGetRegisterName_\n", cpubasename); if (bPlain) fprintf(fp, " global %sGetRegisterName\n", cpubasename); sprintf(procname, "%sGetRegisterName_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sGetRegisterName:\n", cpubasename); if (bPlain) fprintf(fp, "%sGetRegisterName:\n", cpubasename); if (bUseStack) { fprintf(fp, " mov eax, [esp+4] ; Get our register #\n"); } fprintf(fp, " cmp eax, CPUREG_MAXINDEX\n"); fprintf(fp, " jae badIndex\n"); fprintf(fp, " shl eax, 4 ; Times 16 bytes for each entry\n"); fprintf(fp, " mov eax, [eax+RegTable]\n"); fprintf(fp, " jmp nameExit\n\n"); fprintf(fp, "badIndex:\n"); fprintf(fp, " xor eax, eax\n\n"); fprintf(fp, "nameExit:\n"); fprintf(fp, " ret\n\n"); Alignment(); fprintf(fp, " global _%sGetRegisterTextValue\n", cpubasename); fprintf(fp, " global %sGetRegisterTextValue_\n", cpubasename); if (bPlain) fprintf(fp, " global %sGetRegisterTextValue\n", cpubasename); sprintf(procname, "%sGetRegisterTextValue_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sGetRegisterTextValue:\n", cpubasename); if (bPlain) fprintf(fp, "%sGetRegisterTextValue:\n", cpubasename); fprintf(fp, " push esi\n"); fprintf(fp, " push edi\n"); fprintf(fp, " push edx\n"); if (bUseStack) { fprintf(fp, " mov eax, [esp+16] ; Get our register #\n"); fprintf(fp, " mov esi, [esp+20] ; Get our context address\n"); fprintf(fp, " mov edi, [esp+24] ; Address to place text\n"); } else { fprintf(fp, " mov esi, eax ; Get context\n"); fprintf(fp, " mov eax, edx ; Get register # in EAX\n"); fprintf(fp, " mov edi, ebx ; Address to place text\n"); } fprintf(fp, " or esi, esi ; Is context NULL?\n"); fprintf(fp, " jnz getVal2 ; Nope - use it!\n"); fprintf(fp, " mov esi, _%scontextBegin\n\n", cpubasename); fprintf(fp, "getVal2:\n"); fprintf(fp, " mov edx, eax ; Save off our index for later\n"); fprintf(fp, " call getRegValueInternal\n\n"); fprintf(fp, "; EAX Holds the value, EDX=Register #, and EDI=Destination!\n\n"); fprintf(fp, " call convertValueToText\n\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " ret\n\n"); Alignment(); fprintf(fp, " global _%sWriteValue\n", cpubasename); fprintf(fp, " global %sWriteValue_\n", cpubasename); if (bPlain) fprintf(fp, " global %sWriteValue\n", cpubasename); sprintf(procname, "%sWriteValue_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sWriteValue:\n", cpubasename); if (bPlain) fprintf(fp, "%sWriteValue:\n", cpubasename); fprintf(fp, " push esi\n"); fprintf(fp, " push edi\n"); fprintf(fp, " push edx\n"); fprintf(fp, " push ebx\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push ebp\n"); if (bUseStack) { fprintf(fp, " mov eax, [esp+28] ; What kind of write is this?\n"); fprintf(fp, " mov ebx, [esp+32] ; Address\n"); fprintf(fp, " mov edx, [esp+36] ; Value\n"); } else { fprintf(fp, " xchg edx, ebx ; Addr=EBX, value=EDX\n"); } fprintf(fp, " cmp eax, 1 ; Is it a word write?\n"); fprintf(fp, " je near invalidWrite ; Yep - it's not valid\n"); fprintf(fp, " cmp eax, 2 ; Is it a dword write?\n"); fprintf(fp, " je near invalidWrite ; Yep - it's not valid\n\n"); fprintf(fp, " or eax, eax ; Is it a byte write?\n"); fprintf(fp, " jnz itsIoDummy ; Nope... it's an I/O write\n\n"); // Here we do a write memory byte fprintf(fp, " mov ebp, [_z80Base] ; Base pointer comes back\n"); fprintf(fp, " mov edi, [_z80MemWrite] ; Point to the write array\n"); fprintf(fp, "checkLoop:\n"); fprintf(fp, " cmp [edi], word 0ffffh ; End of our list?\n"); fprintf(fp, " je memoryWrite ; Yes - go write it!\n"); fprintf(fp, " cmp bx, [edi] ; Are we smaller?\n"); fprintf(fp, " jb nextAddr ; Yes... go to the next addr\n"); fprintf(fp, " cmp bx, [edi+4] ; Are we smaller?\n"); fprintf(fp, " jbe callRoutine ; If not, go call it!\n"); fprintf(fp, "nextAddr:\n"); fprintf(fp, " add edi, 10h ; Next structure, please\n"); fprintf(fp, " jmp short checkLoop\n"); fprintf(fp, "callRoutine:\n"); fprintf(fp, "\n;\n; EBX=Address to target, DL=Byte to write \n;\n\n"); fprintf(fp, " cmp [edi+8], dword 0 ; Null handler?\n"); fprintf(fp, " je directWriteHandler2\n\n"); if (FALSE == bUseStack) { fprintf(fp, " mov eax, ebx ; Address\n"); fprintf(fp, " mov ebx, edi ; Pointer to struct (EDX Already has the byte to write)\n"); } else { fprintf(fp, " push edi ; Handler\n"); fprintf(fp, " push edx ; Byte\n"); fprintf(fp, " push ebx ; Address\n"); } fprintf(fp, " call dword [edi + 8] ; Go call our handler\n"); if (bUseStack) { fprintf(fp, " add esp, 12\n"); } fprintf(fp, " jmp short itsGood\n"); fprintf(fp, "directWriteHandler2:\n"); fprintf(fp, " sub ebx, [edi] ; Subtract our offset\n"); fprintf(fp, " add ebx, [edi+12] ; Add in the base address\n"); fprintf(fp, " mov [ebx], dl ; Store our byte\n"); fprintf(fp, " jmp short itsGood\n"); fprintf(fp, "memoryWrite:\n"); fprintf(fp, " mov [ebp + ebx], dl\n\n"); fprintf(fp, " jmp short itsGood\n"); // Here we do an "out" fprintf(fp, "itsIoDummy:\n"); fprintf(fp, " mov edi, [_z80IoWrite] ; Point to the I/O write array\n"); fprintf(fp, "IOCheck:\n"); fprintf(fp, " cmp [edi], word 0ffffh ; End of our list?\n"); fprintf(fp, " je itsGood ; Yes - ignore it!\n"); fprintf(fp, " cmp bx, [edi] ; Are we smaller?\n"); fprintf(fp, " jb nextIOAddr ; Yes... go to the next addr\n"); fprintf(fp, " cmp bx, [edi+2] ; Are we bigger?\n"); fprintf(fp, " jbe callIOHandler ; If not, go call it!\n"); fprintf(fp, "nextIOAddr:\n"); fprintf(fp, " add edi, 0ch ; Next structure, please\n"); fprintf(fp, " jmp short IOCheck\n"); fprintf(fp, "callIOHandler:\n"); if (FALSE == bUseStack) { fprintf(fp, " mov eax, ebx ; Address\n"); fprintf(fp, " mov ebx, edi ; Pointer to struct (EDX Already has the byte to write)\n"); } else { fprintf(fp, " push edi ; Handler\n"); fprintf(fp, " push edx ; Byte\n"); fprintf(fp, " push ebx ; Address\n"); } fprintf(fp, " call dword [edi+4] ; Call the handler!\n"); if (bUseStack) fprintf(fp, " add esp, 12\n"); fprintf(fp, " jmp short itsGood\n\n"); // Errors and whatnot fprintf(fp, "invalidWrite:\n"); fprintf(fp, " mov eax, 0ffffffffh\n"); fprintf(fp, " jmp short writeValueExit\n\n"); fprintf(fp, "itsGood:\n"); fprintf(fp, " xor eax, eax\n\n"); fprintf(fp, "writeValueExit:\n"); fprintf(fp, " pop ebp\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop ebx\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " ret\n\n"); Alignment(); fprintf(fp, " global _%sReadValue\n", cpubasename); fprintf(fp, " global %sReadValue_\n", cpubasename); if (bPlain) fprintf(fp, " global %sReadValue\n", cpubasename); sprintf(procname, "%sReadValue_", cpubasename); ProcBegin(0xffffffff); fprintf(fp, "_%sReadValue:\n", cpubasename); if (bPlain) fprintf(fp, "%sReadValue:\n", cpubasename); fprintf(fp, " push esi\n"); fprintf(fp, " push edi\n"); fprintf(fp, " push edx\n"); fprintf(fp, " push ebx\n"); fprintf(fp, " push ecx\n"); fprintf(fp, " push ebp\n"); if (bUseStack) { fprintf(fp, " mov eax, [esp+28] ; What kind of read is this?\n"); fprintf(fp, " mov ebx, [esp+32] ; Address\n"); } else { fprintf(fp, " xchg edx, ebx ; Addr=EBX\n"); } fprintf(fp, " cmp eax, 1 ; Is it a word read?\n"); fprintf(fp, " je near invalidRead ; Yep - it's not valid\n"); fprintf(fp, " cmp eax, 2 ; Is it a dword read?\n"); fprintf(fp, " je near invalidRead ; Yep - it's not valid\n\n"); fprintf(fp, " or eax, eax ; Is it a byte read?\n"); fprintf(fp, " jnz itsIoDummyRead ; Nope... it's an I/O read\n\n"); // Here we do a read memory byte fprintf(fp, " mov ebp, [_z80Base] ; Base pointer comes back\n"); fprintf(fp, " mov edi, [_z80MemRead] ; Point to the read array\n"); fprintf(fp, "checkLoopRead:\n"); fprintf(fp, " cmp [edi], word 0ffffh ; End of our list?\n"); fprintf(fp, " je memoryRead ; Yes - go read it!\n"); fprintf(fp, " cmp bx, [edi] ; Are we smaller?\n"); fprintf(fp, " jb nextAddrRead ; Yes... go to the next addr\n"); fprintf(fp, " cmp bx, [edi+4] ; Are we smaller?\n"); fprintf(fp, " jbe callRoutineRead ; If not, go call it!\n"); fprintf(fp, "nextAddrRead:\n"); fprintf(fp, " add edi, 10h ; Next structure, please\n"); fprintf(fp, " jmp short checkLoopRead\n"); fprintf(fp, "callRoutineRead:\n"); fprintf(fp, "\n;\n; EBX=Address to target\n;\n\n"); fprintf(fp, " cmp [edi+8], dword 0 ; NULL HAndler?\n"); fprintf(fp, " je handleSharedRead\n\n"); if (FALSE == bUseStack) { fprintf(fp, " mov eax, ebx ; Address\n"); fprintf(fp, " mov edx, edi ; Pointer to struct\n"); } else { fprintf(fp, " push edi ; Handler\n"); fprintf(fp, " push ebx ; Address\n"); } fprintf(fp, " call dword [edi + 8] ; Go call our handler\n"); fprintf(fp, " mov dl, al ; Get our byte read\n"); if (bUseStack) { fprintf(fp, " add esp, 8\n"); } fprintf(fp, " jmp short itsGoodRead\n\n"); fprintf(fp, "memoryRead:\n"); fprintf(fp, " mov dl, [ebp+ebx]\n\n"); fprintf(fp, " jmp short itsGoodRead\n\n"); fprintf(fp, "handleSharedRead:\n"); fprintf(fp, " sub ebx, [edi]\n"); fprintf(fp, " add ebx, [edi+12]\n"); fprintf(fp, " mov dl, [ebx]\n"); fprintf(fp, " jmp short itsGoodRead\n\n"); // Here we do an "out" fprintf(fp, "itsIoDummyRead:\n"); fprintf(fp, " mov edi, [_z80IoRead] ; Point to the I/O read array\n"); fprintf(fp, " mov dl, 0ffh ; Assume no handler\n"); fprintf(fp, "IOCheckRead:\n"); fprintf(fp, " cmp [edi], word 0ffffh ; End of our list?\n"); fprintf(fp, " je itsGoodRead ; Yes - ignore it!\n"); fprintf(fp, " cmp bx, [edi] ; Are we smaller?\n"); fprintf(fp, " jb nextIOAddrRead ; Yes... go to the next addr\n"); fprintf(fp, " cmp bx, [edi+2] ; Are we bigger?\n"); fprintf(fp, " jbe callIOHandlerRead ; If not, go call it!\n"); fprintf(fp, "nextIOAddrRead:\n"); fprintf(fp, " add edi, 0ch ; Next structure, please\n"); fprintf(fp, " jmp short IOCheckRead\n"); fprintf(fp, "callIOHandlerRead:\n"); if (FALSE == bUseStack) { fprintf(fp, " mov eax, ebx ; Address\n"); fprintf(fp, " mov edx, edi ; Pointer to struct (EDX Already has the byte to write)\n"); } else { fprintf(fp, " push edi ; Handler\n"); fprintf(fp, " push ebx ; Address\n"); } fprintf(fp, " call dword [edi+4] ; Call the handler!\n"); fprintf(fp, " mov dl, al ; Get our byte read\n"); if (bUseStack) fprintf(fp, " add esp, 8\n"); fprintf(fp, " jmp short itsGoodRead\n\n"); // Errors and whatnot fprintf(fp, "invalidRead:\n"); fprintf(fp, " mov eax, 0ffffffffh\n"); fprintf(fp, " jmp short ReadValueExit\n\n"); fprintf(fp, "itsGoodRead:\n"); fprintf(fp, " xor eax, eax\n"); fprintf(fp, " mov al, dl\n\n"); fprintf(fp, "ReadValueExit:\n"); fprintf(fp, " pop ebp\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop ebx\n"); fprintf(fp, " pop edx\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " ret\n\n"); } else if (MZ80_C == bWhat) { } } void EmitCode(void) { CodeSegmentBegin(); EmitCBInstructions(); EmitEDInstructions(); if (MZ80_ASSEMBLY_X86 == bWhat) strcpy(mz80Index, "ix"); else { strcpy(mz80Index, "cpu.z80IX"); strcpy(mz80IndexHalfHigh, "cpu.z80XH"); strcpy(mz80IndexHalfLow, "cpu.z80XL"); } strcpy(majorOp, "DD"); EmitDDInstructions(); if (MZ80_ASSEMBLY_X86 == bWhat) strcpy(mz80Index, "iy"); else { strcpy(mz80Index, "cpu.z80IY"); strcpy(mz80IndexHalfHigh, "cpu.z80YH"); strcpy(mz80IndexHalfLow, "cpu.z80YL"); } strcpy(majorOp, "FD"); EmitFDInstructions(); majorOp[0] = '\0'; EmitRegularInstructions(); ReadMemoryByteHandler(); WriteMemoryByteHandler(); if (bThroughCallHandler) { PushWordHandler(); PopWordHandler(); } ReadIoHandler(); WriteIoHandler(); GetContextCode(); SetContextCode(); GetContextSizeCode(); GetTicksCode(); ReleaseTimesliceCode(); ResetCode(); IntCode(); NmiCode(); ExecCode(); InitCode(); ShutdownCode(); DebuggerCode(); CodeSegmentEnd(); } int main(int argc, char **argv) { int dwLoop = 0; printf("MakeZ80 - V%s - Copyright 1996-2000 Neil Bradley (neil@synthcom.com)\n", MZ80_VERSION); if (argc < 2) { printf("Usage: %s outfile [option1] [option2] ....\n", argv[0]); printf("\n -s - Stack calling conventions (DJGPP, MSVC, Borland)\n"); printf(" -x86 - Emit an assembly version of mz80\n"); printf(" -c - Emit a C version of mz80\n"); printf(" -cs - All stack operations go through handlers\n"); printf(" -16 - Treat all I/O input and output as 16 bit (BC) instead of (C)\n"); printf(" -l - Create 'plain' labels - ones without leading or trailing _'s\n"); printf(" -nt - No timing additions occur\n"); printf(" -os2 - Emit OS/2 compatible segmentation pragmas\n"); exit(1); } dwLoop = 1; while (dwLoop < argc) { if (strcmp("-x86", argv[dwLoop]) == 0 || strcmp("-X86", argv[dwLoop]) == 0) bWhat = MZ80_ASSEMBLY_X86; if (strcmp("-c", argv[dwLoop]) == 0 || strcmp("-C", argv[dwLoop]) == 0) bWhat = MZ80_C; if (strcmp("-cs", argv[dwLoop]) == 0 || strcmp("-cs", argv[dwLoop]) == 0) bThroughCallHandler = TRUE; if (strcmp("-s", argv[dwLoop]) == 0 || strcmp("-S", argv[dwLoop]) == 0) bUseStack = 1; if (strcmp("-l", argv[dwLoop]) == 0 || strcmp("-L", argv[dwLoop]) == 0) bPlain = TRUE; if (strcmp("-16", argv[dwLoop]) == 0) b16BitIo = TRUE; if (strcmp("-os2", argv[dwLoop]) == 0 || strcmp("-OS2", argv[dwLoop]) == 0) bOS2 = TRUE; if (strcmp("-nt", argv[dwLoop]) == 0) { bNoTiming = TRUE; } dwLoop++; } if (bWhat == MZ80_UNKNOWN) { fprintf(stderr, "Need emitted type qualifier\n"); exit(1); } for (dwLoop = 1; dwLoop < argc; dwLoop++) if (argv[dwLoop][0] != '-') { fp = fopen(argv[dwLoop], "w"); break; } if (NULL == fp) { fprintf(stderr, "Can't open %s for writing\n", argv[1]); exit(1); } strcpy(cpubasename, "mz80"); StandardHeader(); DataSegment(); EmitCode(); ProgramEnd(); fclose(fp); }