www.pudn.com > raine.rar > make6502.c
/* Multi-6502 32 Bit emulator */ /* Copyright 1996, 1997, 1998, Neil Bradley, All rights reserved * * License agreement: * * (M6502 Refers to both the assembly code emitted by make6502.c and make6502.c * itself) * * M6502 May be distributed in unmodified form to any medium. * * M6502 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 M6502 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 * M6502 in source or object form, but if you make modifications to M6502 * then it should be noted in the top as a comment in make6502.c. * * M6502 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 M6502. It is purely "as-is". * * If you use M6502 in a freeware application, credit in the following text: * * "Multi-6502 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 M6502, 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 M6502 * users. If you find performance improvements or problems with M6502, please * email the author with your changes/suggestions and they will be rolled in * with subsequent releases of M6502. * * The whole idea of this emulator is to have the fastest available 32 bit * Multi-6502 emulator for the PC, giving maximum performance. */ #include#include #include #include #define VERSION "1.6" #define TRUE 0xff #define FALSE 0x0 #define INVALID 0xff #define UINT32 unsigned long int #define UINT16 unsigned short int #define UINT8 unsigned char FILE *fp = NULL; char string[150]; char cpubasename[150]; UINT32 dwPageLabel = 0; UINT32 dwGlobalLabel = 0; UINT32 dwAnotherLabel = 0; UINT8 bPlain = FALSE; // Do we use plain global names? UINT8 bUseStack = FALSE; // Use stack calling conventions UINT8 bZeroDirect = FALSE; // Zero page direct UINT8 bSingleStep = FALSE; // Here if we want to single step the CPU UINT8 bBankswitch = FALSE; // Here if we want bankswitching UINT8 bInvalidAsNop = FALSE; // Treat invalid instructions as NOP UINT8 bNoDecimal = FALSE; // Set if we don't want decimal mode UINT8 b6510Instructions = FALSE; // TRUE If we include 6510 instructions UINT32 dwBankSize = 12; // 4K Default static UINT8 bUsed[256]; void BrkHandler(UINT16 dwOpcode); void LdxHandler(UINT16 dwOpcode); void LdyHandler(UINT16 dwOpcode); void LdaHandler(UINT16 dwOpcode); void TxsHandler(UINT16 dwOpcode); void TsxHandler(UINT16 dwOpcode); void TaxHandler(UINT16 dwOpcode); void TxaHandler(UINT16 dwOpcode); void TayHandler(UINT16 dwOpcode); void TyaHandler(UINT16 dwOpcode); void DecxyHandler(UINT16 dwOpcode); void IncxyHandler(UINT16 dwOpcode); void StaHandler(UINT16 dwOpcode); void StxHandler(UINT16 dwOpcode); void StyHandler(UINT16 dwOpcode); void BranchHandler(UINT16 dwOpcode); void AndHandler(UINT16 dwOpcode); void AslHandler(UINT16 dwOpcode); void LsrHandler(UINT16 dwOpcode); void OraHandler(UINT16 dwOpcode); void EorHandler(UINT16 dwOpcode); void JmpHandler(UINT16 dwOpcode); void JsrHandler(UINT16 dwOpcode); void RtsHandler(UINT16 dwOpcode); void IncHandler(UINT16 dwOpcode); void DecHandler(UINT16 dwOpcode); void CmpHandler(UINT16 dwOpcode); void CpyHandler(UINT16 dwOpcode); void CpxHandler(UINT16 dwOpcode); void ClcCldCliClvHandler(UINT16 dwOpcode); void AdcHandler(UINT16 dwOpcode); void SbcHandler(UINT16 dwOpcode); void RolHandler(UINT16 dwOpcode); void RorHandler(UINT16 dwOpcode); void BitHandler(UINT16 dwOpcode); void PhaPhpHandler(UINT16 dwOpcode); void PlaPlpHandler(UINT16 dwOpcode); void RtiHandler(UINT16 dwOpcode); void NopHandler(UINT16 dwOpcode); void DeaInaHandler(UINT16 dwOpcode); void StzHandler(UINT16 dwOpcode); void TrbHandler(UINT16 dwOpcode); void TsbHandler(UINT16 dwOpcode); void BraHandler(UINT16 dwOpcode); struct sOp { UINT16 bOpCode; void (*Emitter)(UINT16); UINT8 b6510Instruction; }; struct sOp StandardOps[] = { {0x00, BrkHandler, FALSE}, // Bank mod * {0x81, StaHandler, FALSE}, {0x85, StaHandler, FALSE}, {0x8d, StaHandler, FALSE}, {0x91, StaHandler, FALSE}, {0x95, StaHandler, FALSE}, {0x99, StaHandler, FALSE}, {0x9d, StaHandler, FALSE}, {0x8e, StxHandler, FALSE}, {0x86, StxHandler, FALSE}, {0x96, StxHandler, FALSE}, {0x8c, StyHandler, FALSE}, {0x84, StyHandler, FALSE}, {0x94, StyHandler, FALSE}, {0xa9, LdaHandler, FALSE}, {0xad, LdaHandler, FALSE}, {0xa5, LdaHandler, FALSE}, {0xbd, LdaHandler, FALSE}, {0xb9, LdaHandler, FALSE}, {0xa1, LdaHandler, FALSE}, {0xb1, LdaHandler, FALSE}, {0xb5, LdaHandler, FALSE}, {0xae, LdxHandler, FALSE}, {0xa6, LdxHandler, FALSE}, {0xa2, LdxHandler, FALSE}, {0xbe, LdxHandler, FALSE}, {0xb6, LdxHandler, FALSE}, {0xac, LdyHandler, FALSE}, {0xa4, LdyHandler, FALSE}, {0xa0, LdyHandler, FALSE}, {0xbc, LdyHandler, FALSE}, {0xb4, LdyHandler, FALSE}, {0x88, DecxyHandler, FALSE}, {0xca, DecxyHandler, FALSE}, {0xe8, IncxyHandler, FALSE}, {0xc8, IncxyHandler, FALSE}, {0x8a, TxaHandler, FALSE}, {0x98, TyaHandler, FALSE}, {0x9a, TxsHandler, FALSE}, {0xa8, TayHandler, FALSE}, {0xaa, TaxHandler, FALSE}, {0xba, TsxHandler, FALSE}, {0x10, BranchHandler, FALSE}, // Bank mod * {0x30, BranchHandler, FALSE}, // Bank mod * {0x50, BranchHandler, FALSE}, // Bank mod * {0x70, BranchHandler, FALSE}, // Bank mod * {0x90, BranchHandler, FALSE}, // Bank mod * {0xb0, BranchHandler, FALSE}, // Bank mod * {0xd0, BranchHandler, FALSE}, // Bank mod * {0xf0, BranchHandler, FALSE}, // Bank mod * {0x2d, AndHandler, FALSE}, {0x25, AndHandler, FALSE}, {0x29, AndHandler, FALSE}, {0x3d, AndHandler, FALSE}, {0x39, AndHandler, FALSE}, {0x21, AndHandler, FALSE}, {0x31, AndHandler, FALSE}, {0x35, AndHandler, FALSE}, {0x0a, AslHandler, FALSE}, {0x0e, AslHandler, FALSE}, {0x06, AslHandler, FALSE}, {0x1e, AslHandler, FALSE}, {0x16, AslHandler, FALSE}, {0x4a, LsrHandler, FALSE}, {0x4e, LsrHandler, FALSE}, {0x46, LsrHandler, FALSE}, {0x5e, LsrHandler, FALSE}, {0x56, LsrHandler, FALSE}, {0x0d, OraHandler, FALSE}, {0x05, OraHandler, FALSE}, {0x09, OraHandler, FALSE}, {0x1d, OraHandler, FALSE}, {0x19, OraHandler, FALSE}, {0x01, OraHandler, FALSE}, {0x11, OraHandler, FALSE}, {0x15, OraHandler, FALSE}, {0x4d, EorHandler, FALSE}, {0x45, EorHandler, FALSE}, {0x49, EorHandler, FALSE}, {0x5d, EorHandler, FALSE}, {0x59, EorHandler, FALSE}, {0x41, EorHandler, FALSE}, {0x51, EorHandler, FALSE}, {0x55, EorHandler, FALSE}, {0xee, IncHandler, FALSE}, {0xe6, IncHandler, FALSE}, {0xfe, IncHandler, FALSE}, {0xf6, IncHandler, FALSE}, {0xce, DecHandler, FALSE}, {0xc6, DecHandler, FALSE}, {0xde, DecHandler, FALSE}, {0xd6, DecHandler, FALSE}, {0xcd, CmpHandler, FALSE}, {0xc5, CmpHandler, FALSE}, {0xc9, CmpHandler, FALSE}, {0xdd, CmpHandler, FALSE}, {0xd9, CmpHandler, FALSE}, {0xc1, CmpHandler, FALSE}, {0xd1, CmpHandler, FALSE}, {0xd5, CmpHandler, FALSE}, {0xcc, CpyHandler, FALSE}, {0xc4, CpyHandler, FALSE}, {0xc0, CpyHandler, FALSE}, {0xec, CpxHandler, FALSE}, {0xe4, CpxHandler, FALSE}, {0xe0, CpxHandler, FALSE}, {0x4c, JmpHandler, FALSE}, // Bank mod * {0x6c, JmpHandler, FALSE}, // Bank mod * {0x20, JsrHandler, FALSE}, // Bank mod * {0x60, RtsHandler, FALSE}, // Bank mod * {0x18, ClcCldCliClvHandler, FALSE}, {0x58, ClcCldCliClvHandler, FALSE}, {0xb8, ClcCldCliClvHandler, FALSE}, {0xd8, ClcCldCliClvHandler, FALSE}, {0x38, ClcCldCliClvHandler, FALSE}, {0x78, ClcCldCliClvHandler, FALSE}, {0xf8, ClcCldCliClvHandler, FALSE}, {0x6d, AdcHandler, FALSE}, {0x65, AdcHandler, FALSE}, {0x69, AdcHandler, FALSE}, {0x7d, AdcHandler, FALSE}, {0x79, AdcHandler, FALSE}, {0x61, AdcHandler, FALSE}, {0x71, AdcHandler, FALSE}, {0x75, AdcHandler, FALSE}, {0xed, SbcHandler, FALSE}, {0xe5, SbcHandler, FALSE}, {0xe9, SbcHandler, FALSE}, {0xfd, SbcHandler, FALSE}, {0xf9, SbcHandler, FALSE}, {0xe1, SbcHandler, FALSE}, {0xf1, SbcHandler, FALSE}, {0xf5, SbcHandler, FALSE}, {0x2a, RolHandler, FALSE}, {0x2e, RolHandler, FALSE}, {0x26, RolHandler, FALSE}, {0x3e, RolHandler, FALSE}, {0x36, RolHandler, FALSE}, {0x6a, RorHandler, FALSE}, {0x6e, RorHandler, FALSE}, {0x66, RorHandler, FALSE}, {0x7e, RorHandler, FALSE}, {0x76, RorHandler, FALSE}, {0x2c, BitHandler, FALSE}, {0x24, BitHandler, FALSE}, {0x48, PhaPhpHandler, FALSE}, {0x08, PhaPhpHandler, FALSE}, {0x68, PlaPlpHandler, FALSE}, {0x28, PlaPlpHandler, FALSE}, {0x40, RtiHandler, FALSE}, // Bank mod * {0xea, NopHandler, FALSE}, // The remaining instructions are part of the 6510 - not the basic 6502 {0x3a, DeaInaHandler, TRUE}, {0x1a, DeaInaHandler, TRUE}, {0xda, PhaPhpHandler, TRUE}, {0x5a, PhaPhpHandler, TRUE}, {0xfa, PlaPlpHandler, TRUE}, {0x7a, PlaPlpHandler, TRUE}, {0x64, StzHandler, TRUE}, {0x74, StzHandler, TRUE}, {0x9c, StzHandler, TRUE}, {0x9e, StzHandler, TRUE}, {0x80, BraHandler, TRUE}, // Bank mod {0x04, TsbHandler, TRUE}, {0x0c, TsbHandler, TRUE}, {0x14, TrbHandler, TRUE}, {0x1c, TrbHandler, TRUE}, // Terminator {0xffff, NULL} }; UINT8 bTimingTable[256] = { 0x07, 0x06, 0x02, 0x02, 0x03, 0x03, 0x05, 0x02, 0x03, 0x02, 0x02, 0x02, 0x04, 0x04, 0x06, 0x02, 0x03, 0x05, 0x03, 0x02, 0x03, 0x04, 0x06, 0x02, 0x02, 0x04, 0x02, 0x02, 0x04, 0x04, 0x07, 0x02, 0x06, 0x06, 0x02, 0x02, 0x03, 0x03, 0x05, 0x02, 0x04, 0x02, 0x02, 0x02, 0x04, 0x04, 0x06, 0x02, 0x03, 0x05, 0x03, 0x02, 0x04, 0x04, 0x06, 0x02, 0x02, 0x04, 0x02, 0x02, 0x04, 0x04, 0x07, 0x02, 0x06, 0x06, 0x02, 0x02, 0x02, 0x03, 0x05, 0x02, 0x03, 0x02, 0x02, 0x02, 0x03, 0x04, 0x06, 0x02, 0x03, 0x05, 0x03, 0x02, 0x02, 0x04, 0x06, 0x02, 0x02, 0x04, 0x03, 0x02, 0x02, 0x04, 0x07, 0x02, 0x06, 0x06, 0x02, 0x02, 0x03, 0x03, 0x05, 0x02, 0x04, 0x02, 0x02, 0x02, 0x05, 0x04, 0x06, 0x02, 0x03, 0x05, 0x03, 0x02, 0x04, 0x04, 0x06, 0x02, 0x02, 0x04, 0x04, 0x02, 0x06, 0x04, 0x07, 0x02, 0x02, 0x06, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x02, 0x03, 0x06, 0x03, 0x02, 0x04, 0x04, 0x04, 0x02, 0x02, 0x05, 0x02, 0x02, 0x04, 0x05, 0x05, 0x02, 0x02, 0x06, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x02, 0x03, 0x05, 0x03, 0x02, 0x04, 0x04, 0x04, 0x02, 0x02, 0x04, 0x02, 0x02, 0x04, 0x04, 0x04, 0x02, 0x02, 0x06, 0x02, 0x02, 0x03, 0x03, 0x05, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x06, 0x02, 0x03, 0x05, 0x03, 0x02, 0x02, 0x04, 0x06, 0x02, 0x02, 0x04, 0x03, 0x02, 0x02, 0x04, 0x07, 0x02, 0x02, 0x06, 0x02, 0x02, 0x03, 0x03, 0x05, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x04, 0x06, 0x02, 0x03, 0x05, 0x03, 0x02, 0x02, 0x04, 0x06, 0x02, 0x02, 0x04, 0x04, 0x02, 0x02, 0x04, 0x07, 0x02 }; UINT8 bBit6502tox86[8] = {0, 6, 1, 0xff, 0xff, 0xff, 4, 7}; UINT8 bBitx86to6502[8] = {0, 0xff, 0xff, 0xff, 6, 0xff, 1, 7}; Flags6502toX86() { fprintf(fp, " xor edx, edx\n"); fprintf(fp, " mov dl, ah\n"); fprintf(fp, " mov [_altFlags], dl\n"); fprintf(fp, " and [_altFlags], byte 3ch;\n"); fprintf(fp, " mov ah, [bit6502tox86+edx]\n"); } FlagsX86to6502() { fprintf(fp, " xor edx, edx\n"); fprintf(fp, " mov dl, ah\n"); fprintf(fp, " mov ah, [bitx86to6502+edx]\n"); fprintf(fp, " or ah, [_altFlags]\n"); } SetZeroSign(UINT8 *pszRegister) { fprintf(fp, " mov dl, ah ; Save flags\n"); fprintf(fp, " or %s, %s ; OR Our new value\n", pszRegister, pszRegister); fprintf(fp, " lahf ; Restore flags\n"); fprintf(fp, " and dl, 03fh ; Original value\n"); fprintf(fp, " and ah, 0c0h ; Only zero and sign\n"); fprintf(fp, " or ah, dl ; New flags with the old!\n"); } SetZero(UINT8 *pszRegister) { fprintf(fp, " mov dl, ah ; Save flags\n"); fprintf(fp, " or %s, %s ; OR Our new value\n", pszRegister, pszRegister); fprintf(fp, " lahf ; Restore flags\n"); fprintf(fp, " and dl, 0bfh ; Original value\n"); fprintf(fp, " and ah, 040h ; Only zero\n"); fprintf(fp, " or ah, dl ; New flags with the old!\n"); } DecSetZeroSign(UINT8 *pszRegister) { fprintf(fp, " mov dl, ah ; Save flags\n"); fprintf(fp, " dec %s ; Decrement\n", pszRegister); fprintf(fp, " lahf ; Restore flags\n"); fprintf(fp, " and dl, 03fh ; Original value\n"); fprintf(fp, " and ah, 0c0h ; Only zero and sign\n"); fprintf(fp, " or ah, dl ; New flags with the old!\n"); } IncSetZeroSign(UINT8 *pszRegister) { fprintf(fp, " mov dl, ah ; Save flags\n"); fprintf(fp, " inc %s ; Increment\n", pszRegister); fprintf(fp, " lahf ; Restore flags\n"); fprintf(fp, " and dl, 03fh ; Original value\n"); fprintf(fp, " and ah, 0c0h ; Only zero and sign\n"); fprintf(fp, " or ah, dl ; New flags with the old!\n"); } void PCToPage() { fprintf(fp, " mov edi, esi ; Here, too\n"); fprintf(fp, " and edi, 0%.4xh ; Knock off the unimportant stuff\n", (1 << dwBankSize) - 1); fprintf(fp, " and esi, 0%.4xh ; Knock out the detailed stuff\n", ~((1 << dwBankSize) - 1)); fprintf(fp, " mov [_%sBasePage], esi ; Store our base page\n", cpubasename); fprintf(fp, " shr esi, %ld ; Get rid of the data we don't need\n", dwBankSize); fprintf(fp, " mov esi, [_%spbBankSwitch+esi*4] ; Get our base address\n", cpubasename); fprintf(fp, " mov [_%sBaseAddr], esi ; Save our base pointer (possibly)\n", cpubasename); fprintf(fp, " add esi, edi ; Add our offset - depaged\n"); fprintf(fp, ";\n; Warning! edi is trashed at this point!\n;\n"); ++dwPageLabel; } void PageToPC() { fprintf(fp, " sub esi, [_%sBaseAddr] ; Normalize it!\n", cpubasename); fprintf(fp, " add esi, [_%sBasePage] ; And our base page!\n", cpubasename); } StandardHeader() { fprintf(fp,"; For assembly by NASM only\n"); fprintf(fp,"bits 32\n"); fprintf(fp, ";\n; %s - V%s - Copyright 1998, Neil Bradley (neil@synthcom.com)\n;\n;\n\n", cpubasename, VERSION); if (bUseStack) fprintf(fp, "; Using stack calling conventions\n"); else fprintf(fp, "; Using register calling conventions\n"); if (bBankswitch) fprintf(fp, "; Bank switch version - %ld byte banks\n", (1 << dwBankSize)); if (bZeroDirect) fprintf(fp, "; Zero page version (all zero page accesses are direct)\n"); else fprintf(fp, "; Non-zero page version (all zero page accesses through handlers)\n"); if (bSingleStep) fprintf(fp, "; Single step version (debug)\n"); fprintf(fp, "\n\n"); } Alignment() { fprintf(fp, "\ntimes ($$-$) & 3 nop ; pad with NOPs to 4-byte boundary\n\n"); } ProcBegin(char *procname, UINT32 dwOpcode) { Alignment(); fprintf(fp, "%s:\n", procname); if (0xffffffff != dwOpcode) { if (FALSE == bSingleStep) { fprintf(fp, " sub dword [cyclesRemaining], byte %ld\n", bTimingTable[dwOpcode]); fprintf(fp, " jc near noMoreExec ; Can't execute anymore!\n"); } else { fprintf(fp, " dec dword [cyclesRemaining] ; Single stepping (debugger)\n"); fprintf(fp, " jz near noMoreExec ; No more code!\n", procname); } fprintf(fp, " add dword [dwElapsedTicks], byte %ld\n", bTimingTable[dwOpcode]); } } ProcEnd(char *procname) { } FetchInstructionByte() { fprintf(fp, " mov dl, [esi] ; Get the next instruction\n"); fprintf(fp, " inc esi ; Advance PC!\n"); } FetchAndExec(UINT32 dwClock) { fprintf(fp, " xor edx, edx\n"); fprintf(fp, " mov dl, [esi]\n"); fprintf(fp, " inc esi\n"); fprintf(fp, " jmp dword [%sregular+edx*4]\n\n", cpubasename); } ReadMemoryByte(UINT8 *pszTargetReg, UINT8 *pszAddress) { fprintf(fp, " mov edi, [_%sMemRead] ; Point to the read array\n\n", cpubasename); fprintf(fp, "checkLoop%ld:\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of the list?\n"); fprintf(fp, " je short memoryRead%ld\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi] ; Are we smaller?\n", pszAddress); fprintf(fp, " jb short nextAddr%ld ; Yes, go to the next address\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi+4] ; Are we bigger?\n", pszAddress); fprintf(fp, " jbe short callRoutine%ld\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%ld:\n", dwGlobalLabel); fprintf(fp, " add edi, 10h ; Next structure!\n"); fprintf(fp, " jmp short checkLoop%ld\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%ld:\n", dwGlobalLabel); assert(strcmp(pszAddress, "dx") == 0); fprintf(fp, " call ReadMemoryByte ; Standard read routine\n"); if (strcmp(pszTargetReg, "bl") != 0) fprintf(fp, " mov bl, [_%sx] ; Get X back\n", cpubasename); if (strcmp(pszTargetReg, "cl") != 0) fprintf(fp, " mov cl, [_%sy] ; Get Y back\n", cpubasename); if (strcmp(pszTargetReg, "al") != 0) { fprintf(fp, " mov %s, al ; Get our value\n", pszTargetReg); fprintf(fp, " mov ax, [_%saf] ; Get our flags & stuff back\n", cpubasename); } else fprintf(fp, " mov ah, [_%saf + 1] ; Get our flags back\n", cpubasename); fprintf(fp, " jmp short readExit%ld\n\n", dwGlobalLabel); fprintf(fp, "memoryRead%ld:\n", dwGlobalLabel); if (bBankswitch) { fprintf(fp, " mov ebp, e%s ; Save our original address in EBP\n", pszAddress); fprintf(fp, " and ebp, 0ffffh ; Mask off the upper bits\n"); fprintf(fp, " mov edi, ebp ; Get our address\n"); fprintf(fp, " shr edi, %ld ; Find which bank we belong to\n", dwBankSize); fprintf(fp, " mov edi, [_%spbBankSwitch+edi*4] ; Get our base address for this bank\n", cpubasename); fprintf(fp, " or edi, edi ; NULL?\n"); fprintf(fp, " jz regularRead%ld ; If so, we're not banking!\n", dwGlobalLabel); // This is the code that fetches the data from the proper address fprintf(fp, " and ebp, 0%.4xh ; Mask out the unimportant stuff\n", (1 << dwBankSize) - 1); fprintf(fp, " mov %s, [ebp+edi] ; Get our banked data\n", pszTargetReg); fprintf(fp, " mov ebp, [_%sBase] ; Get our base pointer back\n", cpubasename); fprintf(fp, " jmp short readExit%ld\n", dwGlobalLabel); fprintf(fp, "regularRead%ld:\n", dwGlobalLabel); fprintf(fp, " mov ebp, [_%sBase] ; Get our base pointer back\n", cpubasename); } fprintf(fp, " mov %s, [ebp + e%s] ; Get our data\n\n", pszTargetReg, pszAddress); fprintf(fp, "readExit%ld:\n", dwGlobalLabel); dwGlobalLabel++; } ReadMemoryWord() { fprintf(fp, " push edx ; Save address\n"); fprintf(fp, " mov [_%saf], ax ; Store AF\n", cpubasename); ReadMemoryByte("al", "dx"); fprintf(fp, " pop edx ; Restore address\n"); fprintf(fp, " inc dx ; Next address\n"); fprintf(fp, " push eax ; Save it for later\n"); fprintf(fp, " mov ax, [_%saf] ; Restore AF because it gets used later\n", cpubasename); ReadMemoryByte("dh", "dx"); fprintf(fp, " pop eax ; Restore it!\n"); fprintf(fp, " mov dl, al ; Restore our word into DX\n"); fprintf(fp, " mov ax, [_%saf] ; Restore AF\n", cpubasename); } WriteMemoryByte(UINT8 *pszSourceReg, UINT8 *pszAddress) { fprintf(fp, " mov edi, [_%sMemWrite] ; Point to the write array\n\n", cpubasename); fprintf(fp, "checkLoop%ld:\n", dwGlobalLabel); fprintf(fp, " cmp [edi], word 0ffffh ; End of our list?\n"); fprintf(fp, " je near memoryWrite%ld ; Yes - go write it!\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi] ; Are we smaller?\n", pszAddress); fprintf(fp, " jb nextAddr%ld ; Yes... go to the next addr\n", dwGlobalLabel); fprintf(fp, " cmp %s, [edi+4] ; Are we bigger?\n", pszAddress); fprintf(fp, " jbe callRoutine%ld ; If not, go call it!\n\n", dwGlobalLabel); fprintf(fp, "nextAddr%ld:\n", dwGlobalLabel); fprintf(fp, " add edi, 10h ; Next structure, please\n"); fprintf(fp, " jmp short checkLoop%ld\n\n", dwGlobalLabel); fprintf(fp, "callRoutine%ld:\n", dwGlobalLabel); // Save off our registers! fprintf(fp, " mov [_%sx], bl ; Save X\n", cpubasename); fprintf(fp, " mov [_%sy], cl ; Save Y\n", cpubasename); fprintf(fp, " mov [_%saf], ax ; Save Accumulator & flags\n", cpubasename); if (bBankswitch) PageToPC(); else fprintf(fp, " sub esi, ebp ; Our program counter\n", cpubasename); fprintf(fp, " mov [_%spc], si ; Save our program counter\n", cpubasename); if (bUseStack) { fprintf(fp, " push edi ; Pointer to MemoryWriteByte structure\n"); if (strcmp(pszSourceReg, "bl") == 0) fprintf(fp, " push ebx ; The byte value\n"); if (strcmp(pszSourceReg, "bh") == 0) { fprintf(fp, " mov bl, bh ; Put a copy here\n"); fprintf(fp, " push ebx ; The byte value\n"); } if (strcmp(pszSourceReg, "cl") == 0) fprintf(fp, " push ecx ; The byte value\n"); if (strcmp(pszSourceReg, "al") == 0) fprintf(fp, " push eax ; The byte value\n"); fprintf(fp, " and e%s, 0ffffh ; Only lower 16 bits\n", pszAddress); fprintf(fp, " push e%s ; The address\n", pszAddress); } else // Register calling convention { if ((strcmp(pszSourceReg, "al") == 0) && (strcmp(pszAddress, "dx") == 0)) fprintf(fp, " xchg eax, edx ; Swap 'em\n"); else { if (strcmp(pszAddress, "bx") == 0) fprintf(fp, " mov eax, ebx ; Address\n"); if (strcmp(pszAddress, "cx") == 0) fprintf(fp, " mov eax, ebx ; Address\n"); if (strcmp(pszAddress, "dx") == 0) fprintf(fp, " mov eax, edx ; Address\n"); if (strcmp(pszSourceReg, "bh") == 0) { fprintf(fp, " mov bl, bh ; Put a copy here\n"); fprintf(fp, " mov edx, ebx ; The byte value\n"); } if (strcmp(pszSourceReg, "bl") == 0) fprintf(fp, " mov edx, ebx ; The byte value\n"); if (strcmp(pszSourceReg, "cl") == 0) fprintf(fp, " mov edx, ecx ; The byte value\n"); if (strcmp(pszSourceReg, "al") == 0) fprintf(fp, " mov edx, eax ; The byte value\n"); } fprintf(fp, " mov ebx, edi ; MemoryWriteByte structure\n"); } fprintf(fp, " call dword [edi + 8] ; Go call our handler\n"); if (bUseStack) fprintf(fp, " add esp, 12 ; Get rid of our stack\n"); fprintf(fp, " xor ebx, ebx ; Zero this\n"); fprintf(fp, " xor ecx, ecx ; This too!\n"); fprintf(fp, " mov bl, [_%sx] ; Get X back\n", cpubasename); fprintf(fp, " mov cl, [_%sy] ; Get Y back\n", cpubasename); fprintf(fp, " xor esi, esi ; Zero it!\n"); fprintf(fp, " mov si, [_%spc] ; Get our program counter back\n", cpubasename); fprintf(fp, " mov ebp, [_%sBase] ; Base pointer comes back\n", cpubasename); if (bBankswitch) PCToPage(); else fprintf(fp, " add esi, ebp ; Rebase it properly\n"); fprintf(fp, " mov ax, [_%saf] ; Get our flags & stuff back\n", cpubasename); fprintf(fp, " jmp short writeMacroExit%ld\n\n", dwGlobalLabel); fprintf(fp, "memoryWrite%ld:\n", dwGlobalLabel); fprintf(fp, " mov [ebp + e%s], %s ; Store the byte\n\n", pszAddress, pszSourceReg); fprintf(fp, "writeMacroExit%ld:\n", dwGlobalLabel); ++dwGlobalLabel; } void ReadMemoryByteHandler() { 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, "ReadMemoryByte:\n"); fprintf(fp, " mov [_%sx], bl ; Save X\n", cpubasename); fprintf(fp, " mov [_%sy], cl ; Save Y\n", cpubasename); fprintf(fp, " mov [_%saf], ax ; Save Accumulator & flags\n", cpubasename); if (bBankswitch) PageToPC(); else fprintf(fp, " sub esi, ebp ; Our program counter\n", cpubasename); fprintf(fp, " mov [_%spc], si ; Save our program counter\n", cpubasename); if (bUseStack) { fprintf(fp, " push edi ; Save our structure address\n"); fprintf(fp, " and edx, 0ffffh ; Only the lower 16 bits\n"); fprintf(fp, " push edx ; And our desired address\n"); } else { 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"); if (bUseStack) fprintf(fp, " add esp, 8 ; Get the junk off the stack\n"); fprintf(fp, " xor ebx, ebx ; Zero X\n"); fprintf(fp, " xor ecx, ecx ; Zero Y\n"); fprintf(fp, " xor esi, esi ; Zero it!\n"); fprintf(fp, " mov si, [_%spc] ; Get our program counter back\n", cpubasename); fprintf(fp, " mov ebp, [_%sBase] ; Base pointer comes back\n", cpubasename); if (bBankswitch) PCToPage(); else fprintf(fp, " add esi, ebp ; Rebase it properly\n"); fprintf(fp, " ret\n\n"); ++dwGlobalLabel; } FetchInstructionWord() { fprintf(fp, " mov dx, [esi] ; Get our address\n"); fprintf(fp, " add esi, 2 ; Increment past instruction\n"); } Absolute() { FetchInstructionWord(); } ZeroPage() { FetchInstructionByte(); } ZeroPageX() { FetchInstructionByte(); fprintf(fp, " add dl, bl ; Add X\n"); } ZeroPageY() { FetchInstructionByte(); fprintf(fp, " add dl, cl ; Add Y\n"); } AbsoluteX() { FetchInstructionWord(); fprintf(fp, " add dx, bx ; Add X\n"); } AbsoluteY() { FetchInstructionWord(); fprintf(fp, " add dx, cx ; Add Y\n"); } IndirectX() { FetchInstructionByte(); fprintf(fp, " add dl, bl ; Add in X\n"); if (bZeroDirect) fprintf(fp, " mov dx, [ebp+edx] ; Get our 16 bit address\n"); else ReadMemoryWord(); } IndirectY() { FetchInstructionByte(); if (bZeroDirect) fprintf(fp, " mov dx, [ebp+edx] ; Get our 16 bit address\n"); else ReadMemoryWord(); fprintf(fp, " add dx, cx ; Add in Y\n"); } DataSegment() { UINT32 dwLoop = 0; UINT32 dwBit = 0; UINT8 bValue = 0; fprintf(fp, " section .data\n"); Alignment(); if (bPlain) fprintf(fp, " global %spc\n\n",cpubasename); else fprintf(fp, " global _%spc\n\n",cpubasename); fprintf(fp, " global %spbBankSwitch_, _%spbBankSwitch\n\n", cpubasename, cpubasename); fprintf(fp, "_%scontextBegin:\n", cpubasename); fprintf(fp, "\n"); fprintf(fp, "; DO NOT CHANGE THE ORDER OF THE FOLLOWING REGISTERS!\n"); fprintf(fp, "\n"); fprintf(fp, "_%sBase dd 0 ; Base address for 6502 stuff\n", cpubasename); fprintf(fp, "_%sMemRead dd 0 ; Offset of memory read structure array\n", cpubasename); fprintf(fp, "_%sMemWrite dd 0 ; Offset of memory write structure array\n", cpubasename); if (bBankswitch) { fprintf(fp, "_%spbBankSwitch:\n", cpubasename); for (dwLoop = 0; dwLoop < 32; dwLoop++) { if (dwLoop * (1 << dwBankSize) < 65536) fprintf(fp, " dd 0 ; Addr=$%.4x\n", dwLoop * (1 << dwBankSize)); else fprintf(fp, " dd 0 ; Filler\n"); } } fprintf(fp, "_%saf dw 0 ; A register and flags\n", cpubasename); fprintf(fp, "_%spc:\n", cpubasename); fprintf(fp, "%spc dw 0 ; 6502 Program counter\n", cpubasename); fprintf(fp, "_%sx db 0 ; X\n", cpubasename); fprintf(fp, "_%sy db 0 ; Y\n", cpubasename); fprintf(fp, "_%ss db 0 ; s\n", cpubasename); fprintf(fp, "_irqPending db 0 ; Non-zero if an IRQ is pending\n"); fprintf(fp, "\n"); fprintf(fp, "_%scontextEnd:\n", cpubasename); if (bBankswitch) { fprintf(fp, "_%sBaseAddr dd 0 ; Temporary base address\n", cpubasename); fprintf(fp, "_%sBasePage dd 0 ; What page are we on? (ready for use)\n", cpubasename); } fprintf(fp, "\n"); Alignment(); fprintf(fp, "_tempAddr dd 0 ; Temporary address storage\n"); fprintf(fp, "dwElapsedTicks dd 0 ; Elapsed ticks!\n"); fprintf(fp, "cyclesRemaining dd 0 ; # Of cycles remaining\n"); fprintf(fp, "_altFlags db 0 ; Storage for I, D, and B\n"); // Now we write out our tables Alignment(); for (dwLoop = 0; dwLoop < 256; dwLoop++) bUsed[dwLoop] = 0; // Create flag translation tables fprintf(fp, "bit6502tox86:\n"); for (dwLoop = 0; dwLoop < 256; dwLoop++) { bValue = 0; for (dwBit = 0; dwBit < 8; dwBit++) { if (bBit6502tox86[dwBit] != 0xff) { if ((1 << dwBit) & dwLoop) bValue |= (1 << bBit6502tox86[dwBit]); } } if ((dwLoop & 0x0f) == 0) fprintf(fp, " db "); if (bValue < 0xa0) fprintf(fp, "%.2xh", bValue); else fprintf(fp, "0%.2xh", bValue); if ((dwLoop & 0x0f) != 0xf) fprintf(fp, ", "); else fprintf(fp, "\n"); } // Create flag translation tables fprintf(fp, "\nbitx86to6502:\n"); for (dwLoop = 0; dwLoop < 256; dwLoop++) { bValue = 0; for (dwBit = 0; dwBit < 8; dwBit++) { if (bBitx86to6502[dwBit] != 0xff) { if ((1 << dwBit) & dwLoop) bValue |= (1 << bBitx86to6502[dwBit]); } } if ((dwLoop & 0x0f) == 0) fprintf(fp, " db "); if (bValue < 0xa0) fprintf(fp, "%.2xh", bValue); else fprintf(fp, "0%.2xh", bValue); if ((dwLoop & 0x0f) != 0xf) fprintf(fp, ", "); else fprintf(fp, "\n"); } fprintf(fp, "\n"); // 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", StandardOps[dwLoop].bOpCode); exit(1); } if (b6510Instructions) bUsed[StandardOps[dwLoop].bOpCode] = 1; else { if (StandardOps[dwLoop].b6510Instruction == FALSE) bUsed[StandardOps[dwLoop].bOpCode] = 1; } dwLoop++; } fprintf(stderr, "%ld Unique opcodes\n", dwLoop); // Now that that's taken care of, emit the table fprintf(fp, "%sregular:\n", cpubasename); dwLoop = 0; while (dwLoop < 0x100) { fprintf(fp, " dd "); if (bUsed[dwLoop]) fprintf(fp, "RegInst%.2x", dwLoop); else { if (bInvalidAsNop) fprintf(fp, "RegInstea"); else fprintf(fp, "invalidInsByte"); } fprintf(fp, "\n"); dwLoop++; } fprintf(fp, "\n"); } CodeSegmentBegin() { fprintf(fp, " section .text\n"); } CodeSegmentEnd() { } ProgramEnd() { fprintf(fp, " end\n"); } EmitRegularInstructions() { UINT32 dwLoop = 0; UINT32 dwLoop2 = 0; while (dwLoop < 0x100) { dwLoop2 = 0; while (StandardOps[dwLoop2].bOpCode != dwLoop && StandardOps[dwLoop2].bOpCode != 0xffff) dwLoop2++; assert(dwLoop2 < 0x100); if (StandardOps[dwLoop2].Emitter && StandardOps[dwLoop2].bOpCode != 0xffff && bUsed[dwLoop]) StandardOps[dwLoop2].Emitter((UINT16) dwLoop); dwLoop++; } } void Immediate(UINT8 *pszRegister) { fprintf(fp, " mov %s, [esi] ; Get our next byte\n", pszRegister); fprintf(fp, " inc esi ; Increment to our next byte\n"); } // LDX Handler void LdxHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; LDX\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0xa2 == dwOpcode) Immediate("bl"); else if (0xae == dwOpcode) Absolute(); else if (0xa6 == dwOpcode) ZeroPage(); else if (0xbe == dwOpcode) AbsoluteY(); else if (0xb6 == dwOpcode) ZeroPageY(); else assert(0); if (0xa2 != dwOpcode) { if ((0xa6 != dwOpcode && 0xb6 != dwOpcode) || (FALSE == bZeroDirect)) ReadMemoryByte("bl", "dx"); else fprintf(fp, " mov bl, [ebp + edx] ; Zero page!\n"); } SetZeroSign("bl"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // LDY Handler void LdyHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; LDY\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0xa0 == dwOpcode) Immediate("cl"); else if (0xac == dwOpcode) Absolute(); else if (0xa4 == dwOpcode) ZeroPage(); else if (0xbc == dwOpcode) AbsoluteX(); else if (0xb4 == dwOpcode) ZeroPageX(); else assert(0); if (0xa0 != dwOpcode) { if ((0xa4 != dwOpcode && 0xb4 != dwOpcode) || (FALSE == bZeroDirect)) ReadMemoryByte("cl", "dx"); else fprintf(fp, " mov cl, [ebp + edx] ; Zero page!\n"); } SetZeroSign("cl"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // DEC Handler void DecxyHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); if (0x88 == dwOpcode) fprintf(fp, "; DEY\n"); else fprintf(fp, "; DEX\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x88 == dwOpcode) DecSetZeroSign("cl"); // Decrement & do Y else if (0xca == dwOpcode) DecSetZeroSign("bl"); // Decrement & do X else assert(0); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // DeaIna Handler void DeaInaHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); if (0x3a == dwOpcode) fprintf(fp, "; DEA\n"); else fprintf(fp, "; INA\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x3a == dwOpcode) DecSetZeroSign("al"); // Decrement else if (0x1a == dwOpcode) DecSetZeroSign("al"); // Decrement else assert(0); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // INC Handler void IncxyHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); if (0xc8 == dwOpcode) fprintf(fp, "; INY\n"); else fprintf(fp, "; INX\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0xc8 == dwOpcode) IncSetZeroSign("cl"); // Increment & do Y else if (0xe8 == dwOpcode) IncSetZeroSign("bl"); // Increment & do X else assert(0); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // INC Handler void IncHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; INC\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0xee == dwOpcode || 0xfe == dwOpcode) { if (0xee == dwOpcode) Absolute(); else AbsoluteX(); fprintf(fp, " push edx ; Save this for later\n"); ReadMemoryByte("dl", "dx"); fprintf(fp, " mov bh, dl ; Save the data we just got\n"); } else if (0xe6 == dwOpcode || 0xf6 == dwOpcode) { if (0xe6 == dwOpcode) ZeroPage(); else ZeroPageX(); if (FALSE == bZeroDirect) { fprintf(fp, " push edx ; Save this for later\n"); ReadMemoryByte("dl", "dx"); fprintf(fp, " mov bh, dl ; Save the data we just got\n"); } } else assert(0); // Handle the increment fprintf(fp, " mov ch, ah ; Save flags\n"); fprintf(fp, " and ch, 03fh ; No sign or zero flags\n"); if (((0xe6 == dwOpcode) || (0xf6 == dwOpcode)) && (bZeroDirect)) fprintf(fp, " inc byte [edx+ebp] ; Increment our zero page stuff\n"); else fprintf(fp, " inc bh ; Increment!\n"); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0c0h ; Only sign & zero flags\n"); fprintf(fp, " or ah, ch ; Merge the two flags together\n"); if ( (0xee == dwOpcode || 0xfe == dwOpcode) || (((0xe6 == dwOpcode) || (0xf6 == dwOpcode)) && (FALSE == bZeroDirect)) ) { fprintf(fp, " pop edx ; Restore our address\n"); WriteMemoryByte("bh", "dx"); } fprintf(fp, " xor bh, bh ; Zero this so we don't totally screw things up\n"); fprintf(fp, " xor ch, ch ; Zero this as well\n"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // DEC Handler void DecHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; DEC\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0xce == dwOpcode || 0xde == dwOpcode) { if (0xce == dwOpcode) Absolute(); else AbsoluteX(); fprintf(fp, " push edx ; Save this for later\n"); ReadMemoryByte("dl", "dx"); fprintf(fp, " mov bh, dl ; Save the data we just got\n"); } else if (0xc6 == dwOpcode || 0xd6 == dwOpcode) { if (0xc6 == dwOpcode) ZeroPage(); else ZeroPageX(); if (FALSE == bZeroDirect) { fprintf(fp, " push edx ; Save this for later\n"); ReadMemoryByte("dl", "dx"); fprintf(fp, " mov bh, dl ; Save the data we just got\n"); } } else assert(0); // Handle the increment fprintf(fp, " mov ch, ah ; Save flags\n"); fprintf(fp, " and ch, 03fh ; No sign or zero flags\n"); if (((0xc6 == dwOpcode) || (0xd6 == dwOpcode)) && (bZeroDirect)) fprintf(fp, " dec byte [edx+ebp] ; Increment our zero page stuff\n"); else fprintf(fp, " dec bh ; Decrement!\n"); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0c0h ; Only sign & zero flags\n"); fprintf(fp, " or ah, ch ; Merge the two flags together\n"); if ( (0xce == dwOpcode || 0xde == dwOpcode) || (((0xc6 == dwOpcode) || (0xd6 == dwOpcode)) && (FALSE == bZeroDirect)) ) { fprintf(fp, " pop edx ; Restore our address\n"); WriteMemoryByte("bh", "dx"); } fprintf(fp, " xor bh, bh ; Zero this so we don't totally screw things up\n"); fprintf(fp, " xor ch, ch ; Zero this as well\n"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // AND Handler void AndHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; AND\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x2d == dwOpcode) Absolute(); else if (0x25 == dwOpcode) ZeroPage(); else if (0x29 == dwOpcode) Immediate("dl"); else if (0x3d == dwOpcode) AbsoluteX(); else if (0x39 == dwOpcode) AbsoluteY(); else if (0x21 == dwOpcode) IndirectX(); else if (0x31 == dwOpcode) IndirectY(); else if (0x35 == dwOpcode) ZeroPageX(); else assert(0); if ((bZeroDirect) && ((0x25 == dwOpcode) || (0x35 == dwOpcode))) fprintf(fp, " and al, [ebp+edx] ; And it!\n"); else { if (0x29 != dwOpcode) ReadMemoryByte("dl", "dx"); fprintf(fp, " and al, dl ; And it\n"); } fprintf(fp, " mov bh, ah ; Save flags for later\n"); fprintf(fp, " lahf ; Get the flags\n"); fprintf(fp, " and ah, 0c0h ; Only sign and zero flag\n"); fprintf(fp, " and bh, 03fh ; Kill sign and zero flag\n"); fprintf(fp, " or ah, bh ; Get our original (other) flags back\n"); fprintf(fp, " xor bh, bh ; Kill it so we don't screw X up for later\n"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // ASL Handler void AslHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; Asl\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x0a == dwOpcode) { fprintf(fp, " sahf ; Restore flags\n"); fprintf(fp, " mov dl, ah ; Store our original flags\n"); fprintf(fp, " shl al, 1 ; Shift left by 1\n"); fprintf(fp, " lahf ; Load the flags back in\n"); fprintf(fp, " and dl, 03eh ; No carry, zero, or sign\n"); fprintf(fp, " and ah, 0c1h ; Only carry, zero and sign\n"); fprintf(fp, " or ah, dl ; Or it into our flags\n"); } else if (0x0e == dwOpcode) // Absolute Absolute(); else if (0x06 == dwOpcode) // Zero page ZeroPage(); else if (0x1e == dwOpcode) // Absolute X AbsoluteX(); else if (0x16 == dwOpcode) // Zero page X ZeroPageX(); else assert(0); // We have the address. Now fetch the info! if (0x0a != dwOpcode) { // Read the data if (((0x16 == dwOpcode) || (0x06 == dwOpcode)) && bZeroDirect) fprintf(fp, " mov bh, [ebp+edx] ; Get our zero page stuff\n"); else { fprintf(fp, " push edx ; Save our address\n"); ReadMemoryByte("bh", "dx"); fprintf(fp, " pop edx ; Restore our address\n"); } // Process the data fprintf(fp, " sahf ; Restore flags\n"); fprintf(fp, " mov ch, ah ; Store our original flags\n"); fprintf(fp, " shl bh, 1 ; Shift left by 1\n"); fprintf(fp, " lahf ; Load the flags back in\n"); fprintf(fp, " and ch, 03eh ; No carry, zero, or sign\n"); fprintf(fp, " and ah, 0c1h ; Only carry, zero and sign\n"); fprintf(fp, " or ah, ch ; Or it into our flags\n"); fprintf(fp, " xor ch, ch ; Clear it!\n"); // Write the data back if (((0x16 == dwOpcode) || (0x06 == dwOpcode)) && bZeroDirect) fprintf(fp, " mov [ebp+edx], bh ; Set our zero page byte\n"); else WriteMemoryByte("bh", "dx"); fprintf(fp, " xor bh, bh ; Prevent us from being hosed later\n"); } FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // LSR Handler void LsrHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; Lsr\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x4a == dwOpcode) { fprintf(fp, " sahf ; Restore flags\n"); fprintf(fp, " mov dl, ah ; Store our original flags\n"); fprintf(fp, " shr al, 1 ; Shift right by 1\n"); fprintf(fp, " lahf ; Load the flags back in\n"); fprintf(fp, " and dl, 03eh ; No carry, zero, or sign\n"); fprintf(fp, " and ah, 0c1h ; Only carry, zero and sign\n"); fprintf(fp, " or ah, dl ; Or it into our flags\n"); } else if (0x4e == dwOpcode) // Absolute Absolute(); else if (0x46 == dwOpcode) // Zero page ZeroPage(); else if (0x5e == dwOpcode) // Absolute X AbsoluteX(); else if (0x56 == dwOpcode) // Zero page X ZeroPageX(); else assert(0); // We have the address. Now fetch the info! if (0x4a != dwOpcode) { // Read the data fprintf(fp, " push edx ; Save our address away\n"); if (((0x56 == dwOpcode) || (0x46 == dwOpcode)) && bZeroDirect) fprintf(fp, " mov bh, [ebp+edx] ; Get our zero page stuff\n"); else ReadMemoryByte("bh", "dx"); // Process the data fprintf(fp, " sahf ; Restore flags\n"); fprintf(fp, " mov ch, ah ; Store our original flags\n"); fprintf(fp, " shr bh, 1 ; Shift right by 1\n"); fprintf(fp, " lahf ; Load the flags back in\n"); fprintf(fp, " and ch, 03eh ; No carry, zero, or sign\n"); fprintf(fp, " and ah, 0c1h ; Only carry, zero and sign\n"); fprintf(fp, " or ah, ch ; Or it into our flags\n"); fprintf(fp, " xor ch, ch ; Clear it!\n"); // Write the data back fprintf(fp, " pop edx ; Restore our address\n"); if (((0x56 == dwOpcode) || (0x46 == dwOpcode)) && bZeroDirect) fprintf(fp, " mov [ebp+edx], bh ; Set our zero page byte\n"); else WriteMemoryByte("bh", "dx"); fprintf(fp, " xor bh, bh ; Zero the upper part so we don't host X!\n"); } FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // ORA Handler void OraHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; Ora\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x0d == dwOpcode) Absolute(); else if (0x05 == dwOpcode) ZeroPage(); else if (0x09 == dwOpcode) Immediate("dl"); else if (0x1d == dwOpcode) AbsoluteX(); else if (0x19 == dwOpcode) AbsoluteY(); else if (0x01 == dwOpcode) IndirectX(); else if (0x11 == dwOpcode) IndirectY(); else if (0x15 == dwOpcode) ZeroPageX(); else assert(0); // Address is now in DX to read if (0x09 != dwOpcode) { if ((0x05 == dwOpcode || 0x15 == dwOpcode) && (bZeroDirect)) fprintf(fp, " mov dl, [ebp+edx] ; Get our zero page data\n"); else ReadMemoryByte("dl", "dx"); } // Let's do the OR with A, shall we? fprintf(fp, " mov dh, ah ; Get the flags\n"); fprintf(fp, " or al, dl ; OR In our value\n"); fprintf(fp, " lahf ; Get the flag settings\n"); fprintf(fp, " and ah, 0c0h ; Only sign and zero flag\n"); fprintf(fp, " and dh, 03fh ; Clear sign & zero flags\n"); fprintf(fp, " or ah, dh ; Merge the affected flags together\n"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // EOR Handler void EorHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; Eor\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x4d == dwOpcode) Absolute(); else if (0x45 == dwOpcode) ZeroPage(); else if (0x49 == dwOpcode) Immediate("dl"); else if (0x5d == dwOpcode) AbsoluteX(); else if (0x59 == dwOpcode) AbsoluteY(); else if (0x41 == dwOpcode) IndirectX(); else if (0x51 == dwOpcode) IndirectY(); else if (0x55 == dwOpcode) ZeroPageX(); else assert(0); // Address is now in DX to read if (0x49 != dwOpcode) { if ((0x45 == dwOpcode || 0x55 == dwOpcode) && (bZeroDirect)) fprintf(fp, " mov dl, [ebp+edx] ; Get our zero page data\n"); else ReadMemoryByte("dl", "dx"); } // Let's do the XOR with A, shall we? fprintf(fp, " mov dh, ah ; Get the flags\n"); fprintf(fp, " xor al, dl ; XOR In our value\n"); fprintf(fp, " lahf ; Get the flag settings\n"); fprintf(fp, " and ah, 0c0h ; Only sign and zero flag\n"); fprintf(fp, " and dh, 03fh ; Clear sign & zero flags\n"); fprintf(fp, " or ah, dh ; Merge the affected flags together\n"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // STA Handler void StaHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; STA\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x9d == dwOpcode) AbsoluteX(); else if (0x99 == dwOpcode) AbsoluteY(); else if (0x8d == dwOpcode) Absolute(); else if (0x85 == dwOpcode) ZeroPage(); else if (0x81 == dwOpcode) IndirectX(); else if (0x91 == dwOpcode) IndirectY(); else if (0x95 == dwOpcode) ZeroPageX(); else assert(0); if ((0x85 == dwOpcode || 0x95 == dwOpcode) && bZeroDirect) fprintf(fp, " mov [ebp+edx], al ; Store A\n"); else WriteMemoryByte("al", "dx"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // STX Handler void StxHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; STX\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x8e == dwOpcode) Absolute(); else if (0x86 == dwOpcode) ZeroPage(); else if (0x96 == dwOpcode) ZeroPageY(); else assert(0); if ((0x86 == dwOpcode || 0x96 == dwOpcode) && bZeroDirect) fprintf(fp, " mov [ebp+edx], bl ; Store X\n"); else WriteMemoryByte("bl", "dx"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // STY Handler void StyHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; STY\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x8c == dwOpcode) Absolute(); else if (0x84 == dwOpcode) ZeroPage(); else if (0x94 == dwOpcode) ZeroPageX(); else assert(0); if ((0x86 == dwOpcode || 0x96 == dwOpcode) && bZeroDirect) fprintf(fp, " mov [ebp+edx], cl ; Store Y\n"); else WriteMemoryByte("cl", "dx"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // LDA Handler void LdaHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; LDA\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0xa9 == dwOpcode) Immediate("al"); else if (0xad == dwOpcode) Absolute(); else if (0xa5 == dwOpcode) ZeroPage(); else if (0xbd == dwOpcode) AbsoluteX(); else if (0xb9 == dwOpcode) AbsoluteY(); else if (0xa1 == dwOpcode) IndirectX(); else if (0xb1 == dwOpcode) IndirectY(); else if (0xb5 == dwOpcode) ZeroPageX(); else assert(0); if (0xa9 != dwOpcode) { if (bZeroDirect && (0xb5 == dwOpcode || 0xa5 == dwOpcode)) fprintf(fp, " mov al, [ebp+edx] ; Get our zero page byte\n"); else ReadMemoryByte("al", "dx"); } SetZeroSign("al"); // Set flags according to A FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // TXS void TxsHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; TXS\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); fprintf(fp, " mov [_%ss], bl ; X -> S\n", cpubasename); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // TSX void TsxHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; TSX\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); fprintf(fp, " mov bl, [_%ss] ; S -> X\n", cpubasename); SetZeroSign("bl"); // Set flags according to X FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // TAX void TaxHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; TAX\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); fprintf(fp, " mov bl, al ; X = A\n"); SetZeroSign("bl"); // Set flags according to X FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // TXA void TxaHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; TXA\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); fprintf(fp, " mov al, bl ; A = X\n"); SetZeroSign("al"); // Set flags according to A FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // TAY void TayHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; TAY\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); fprintf(fp, " mov cl, al ; Y = A\n"); SetZeroSign("cl"); // Set flags according to Y FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // TYA void TyaHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; TYA\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); fprintf(fp, " mov al, cl ; A = Y\n"); SetZeroSign("al"); // Set flags according to A FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // Branch handler void BranchHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; Branch\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); // Put test case here if (0xd0 == dwOpcode) // BNE { fprintf(fp, " test ah, 40h ; Are we non-zero?\n"); fprintf(fp, " jz short takeJump%.2x ; Do it!\n", dwOpcode); } else if (0x30 == dwOpcode) // BMI { fprintf(fp, " test ah, 80h ; Are we minus?\n"); fprintf(fp, " jnz short takeJump%.2x ; Do it!\n", dwOpcode); } else if (0xb0 == dwOpcode) // BCS { fprintf(fp, " test ah, 1h ; Is carry set?\n"); fprintf(fp, " jnz short takeJump%.2x ; Do it!\n", dwOpcode); } else if (0x10 == dwOpcode) // BPL { fprintf(fp, " test ah, 80h ; Are we plus?\n"); fprintf(fp, " jz short takeJump%.2x ; Do it!\n", dwOpcode); } else if (0x70 == dwOpcode) // BVS { fprintf(fp, " test ah, 10h ; Overflow set?\n"); fprintf(fp, " jnz short takeJump%.2x ; Do it!\n", dwOpcode); } else if (0x50 == dwOpcode) // BVC { fprintf(fp, " test ah, 10h ; Overflow not set?\n"); fprintf(fp, " jz short takeJump%.2x ; Do it!\n", dwOpcode); } else if (0xf0 == dwOpcode) // BEQ { fprintf(fp, " test ah, 40h ; Non-zero set?\n"); fprintf(fp, " jnz short takeJump%.2x ; Do it!\n", dwOpcode); } else if (0x90 == dwOpcode) // BCC { fprintf(fp, " test ah, 1h ; Carry not set?\n"); fprintf(fp, " jz short takeJump%.2x ; Do it!\n", dwOpcode); } else assert(0); fprintf(fp, " inc esi ; Skip past the offset\n"); FetchAndExec(bTimingTable[dwOpcode] - 1); fprintf(fp, "takeJump%.2x:\n", dwOpcode); FetchInstructionByte(); // Go get our offset just in case fprintf(fp, " movsx dx, dl\n"); if (bBankswitch) { PageToPC(); fprintf(fp, " add si, dx\n"); fprintf(fp, " mov [_%spc], si\n", cpubasename); PCToPage(); } else { fprintf(fp, " sub esi, ebp\n"); fprintf(fp, " add si, dx\n"); fprintf(fp, " add esi, ebp\n"); } ++dwGlobalLabel; FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // JMP void JmpHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; JMP\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); FetchInstructionWord(); if (0x6c == dwOpcode) ReadMemoryWord(); if (bBankswitch) { fprintf(fp, " xor esi, esi\n"); fprintf(fp, " mov si, dx\n"); fprintf(fp, " mov [_%spc], si\n", cpubasename); PCToPage(); } else { fprintf(fp, " add edx, ebp ; Add in our base\n"); fprintf(fp, " mov esi, edx ; Put it here for execution\n"); } ++dwGlobalLabel; FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // Brk void BrkHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; BRK\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (bBankswitch) PageToPC(); else fprintf(fp, " sub esi, ebp ; Get our real program counter\n"); fprintf(fp, " inc si ; Move to the next position\n"); fprintf(fp, " or [_altFlags], byte 14h ; Indicate a break happened\n"); FlagsX86to6502(); fprintf(fp, " mov dl, [_%ss] ; Get our stack pointer\n", cpubasename); fprintf(fp, " add dx, 0ffh ; Stack area is 100-1ffh\n"); fprintf(fp, " mov [edx+ebp], si ; Store our PC\n"); fprintf(fp, " dec dx ; Back up for flag storage\n"); fprintf(fp, " mov [edx+ebp], ah ; Store our flags\n"); fprintf(fp, " dec dx ; Back up for flag storage\n"); fprintf(fp, " mov [_%ss], dl ; Store our new stack area\n", cpubasename); fprintf(fp, " xor esi, esi ; Zero our program counter\n"); fprintf(fp, " mov si, [ebp+0fffeh] ; Get our break handler\n"); if (bBankswitch) { fprintf(fp, " mov [_%spc], si\n", cpubasename); PCToPage(); } else fprintf(fp, " add esi, ebp ; Add our base pointer back in\n"); ++dwGlobalLabel; Flags6502toX86(); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // JSR void JsrHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; JSR\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); FetchInstructionWord(); if (bBankswitch) PageToPC(); else { fprintf(fp, " sub esi, ebp ; Get our real program counter\n"); } fprintf(fp, " dec si ; Our offset to return to\n"); fprintf(fp, " sub [_%ss], byte 2 ; Back up 2 byte for stack push\n", cpubasename); fprintf(fp, " mov di, word [_%ss] ; Our stack area\n", cpubasename); fprintf(fp, " and edi, 0ffh ; Only the lower byte matters\n"); fprintf(fp, " add edi, 101h ; Make sure it's on the stack page\n"); fprintf(fp, " mov [edi+ebp], si ; Store our return address\n"); if (bBankswitch) { fprintf(fp, " xor esi, esi\n"); fprintf(fp, " mov si, dx ; Get our address\n"); fprintf(fp, " mov [_%spc], si ; Store our new PC\n", cpubasename); PCToPage(); } else { fprintf(fp, " add edx, ebp ; Our new address\n"); fprintf(fp, " mov esi, edx ; Put it in here for the fetch\n"); } dwGlobalLabel++; FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // RTS void RtsHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; RTS\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); fprintf(fp, " xor esi, esi ; Zero ESI for later\n"); fprintf(fp, " mov dl, [_%ss] ; Get our stack\n", cpubasename); fprintf(fp, " add [_%ss], byte 2 ; Pop off a word\n", cpubasename); fprintf(fp, " inc dl ; Increment our stack page\n"); fprintf(fp, " inc dh ; Our stack page\n"); fprintf(fp, " mov si, [ebp+edx] ; Get our stack area\n"); fprintf(fp, " inc si ; Increment!\n"); if (bBankswitch) { fprintf(fp, " mov [_%spc], si\n", cpubasename); PCToPage(); } else fprintf(fp, " add esi, ebp ; Add in our base address\n"); ++dwGlobalLabel; FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // CMP Handler void CmpHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; CMP\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0xcd == dwOpcode) Absolute(); else if (0xc5 == dwOpcode) ZeroPage(); else if (0xc9 == dwOpcode) Immediate("dl"); else if (0xdd == dwOpcode) AbsoluteX(); else if (0xd9 == dwOpcode) AbsoluteY(); else if (0xc1 == dwOpcode) IndirectX(); else if (0xd1 == dwOpcode) IndirectY(); else if (0xd5 == dwOpcode) ZeroPageX(); else assert(0); // Now that we have the address of what we want in DX, let's go fetch the // data if (0xc9 != dwOpcode) // Make sure it's not immediate { if (((0xc5 == dwOpcode) || (0xd5 == dwOpcode)) && bZeroDirect) fprintf(fp, " mov dl, [ebp+edx] ; Get our zero page data\n"); else ReadMemoryByte("dl", "dx"); } // We have our value in DL. Now do the work! fprintf(fp, " mov dh, ah ; Get our flags\n"); fprintf(fp, " cmp al, dl ; Compare!\n"); fprintf(fp, " cmc ; Compliment carry flag\n"); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0c1h ; Sign, zero, and carry\n"); fprintf(fp, " and dh, 03eh ; Everything but sign, zero and carry\n"); fprintf(fp, " or ah, dh ; OR In our new flags\n"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // CPY Handler void CpyHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; CPY\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0xcc == dwOpcode) Absolute(); else if (0xc4 == dwOpcode) ZeroPage(); else if (0xc0 == dwOpcode) Immediate("dl"); else assert(0); // Now that we have the address of what we want in DX, let's go fetch the // data if (0xc0 != dwOpcode) // Make sure it's not immediate { if (0xc4 == dwOpcode && bZeroDirect) fprintf(fp, " mov dl, [ebp+edx] ; Get our zero page data\n"); else ReadMemoryByte("dl", "dx"); } // We have our value in DL. Now do the work! fprintf(fp, " mov dh, ah ; Get our flags\n"); fprintf(fp, " cmp cl, dl ; Compare with Y!\n"); fprintf(fp, " cmc ; Compliment carry flag\n"); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0c1h ; Sign, zero, and carry\n"); fprintf(fp, " and dh, 03eh ; Everything but sign, zero and carry\n"); fprintf(fp, " or ah, dh ; OR In our new flags\n"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } // CPX Handler void CpxHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; CPX\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0xec == dwOpcode) Absolute(); else if (0xe4 == dwOpcode) ZeroPage(); else if (0xe0 == dwOpcode) Immediate("dl"); else assert(0); // Now that we have the address of what we want in DX, let's go fetch the // data if (0xe0 != dwOpcode) // Make sure it's not immediate { if (0xe4 == dwOpcode && bZeroDirect) fprintf(fp, " mov dl, [ebp+edx] ; Get our zero page data\n"); else ReadMemoryByte("dl", "dx"); } // We have our value in DL. Now do the work! fprintf(fp, " mov dh, ah ; Get our flags\n"); fprintf(fp, " cmp bl, dl ; Compare with X!\n"); fprintf(fp, " cmc ; Compliment carry flag\n"); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0c1h ; Sign, zero, and carry\n"); fprintf(fp, " and dh, 03eh ; Everything but sign, zero and carry\n"); fprintf(fp, " or ah, dh ; OR In our new flags\n"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } void ClcCldCliClvHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); if (0x58 == dwOpcode) fprintf(fp, "; CLI\n"); else if (0xd8 == dwOpcode) fprintf(fp, "; CLD\n"); else if (0xb8 == dwOpcode) fprintf(fp, "; CLV\n"); else if (0x18 == dwOpcode) fprintf(fp, "; CLC\n"); else if (0x38 == dwOpcode) fprintf(fp, "; SEC\n"); else if (0xf8 == dwOpcode) fprintf(fp, "; SED\n"); else if (0x78 == dwOpcode) fprintf(fp, "; SEI\n"); else assert(0); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x58 == dwOpcode) { fprintf(fp, " and [_altFlags], byte 0fbh ; No interrupts!\n"); fprintf(fp, " cmp [_irqPending], byte 0 ; IRQ pending?\n"); fprintf(fp, " je near notEnabledCli\n"); if (bBankswitch) PageToPC(); else fprintf(fp, " sub esi, ebp ; Get our real program counter\n"); fprintf(fp, " mov [_%spc], si\n", cpubasename); FlagsX86to6502(); fprintf(fp, " mov [_%saf], ax ; Save this\n", cpubasename); fprintf(fp, " push eax ; Save this - we need it\n"); fprintf(fp, " call _%sint ; Go do an interrupt\n", cpubasename); fprintf(fp, " pop eax ; Restore this - we need it!\n"); fprintf(fp, " mov si, [_%spc] ; Get our program counter\n", cpubasename); fprintf(fp, " and esi, 0ffffh ; Only the lower 16 bits\n"); if (bBankswitch) { fprintf(fp, " mov [_%spc], si\n", cpubasename); PCToPage(); } else fprintf(fp, " add esi, ebp ; So it properly points to the code\n"); fprintf(fp, " mov ax, [_%saf] ; Restore this\n", cpubasename); Flags6502toX86(); fprintf(fp, "notEnabledCli:\n"); } else if (0xd8 == dwOpcode) fprintf(fp, " and [_altFlags], byte 0f7h ; Binary mode\n"); else if (0xb8 == dwOpcode) fprintf(fp, " and ah, 0efh ; Clear out overflow\n"); else if (0x18 == dwOpcode) fprintf(fp, " and ah, 0feh ; No carry\n"); else if (0x38 == dwOpcode) fprintf(fp, " or ah, 01h ; Carry!\n"); else if (0xf8 == dwOpcode) fprintf(fp, " or [_altFlags], byte 08h ; Decimal mode\n"); else if (0x78 == dwOpcode) fprintf(fp, " or [_altFlags], byte 04h ; Interrupts!\n"); else assert(0); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } void AdcHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; ADC\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x6d == dwOpcode) Absolute(); else if (0x65 == dwOpcode) ZeroPage(); else if (0x69 == dwOpcode) Immediate("dl"); else if (0x7d == dwOpcode) AbsoluteX(); else if (0x79 == dwOpcode) AbsoluteY(); else if (0x61 == dwOpcode) IndirectX(); else if (0x71 == dwOpcode) IndirectY(); else if (0x75 == dwOpcode) ZeroPageX(); else assert(0); // We've got our address (or byte if immediate) in DL now if (0x69 != dwOpcode) // Make sure it's not immediate { if (((0x65 == dwOpcode) || (0x75 == dwOpcode)) && bZeroDirect) fprintf(fp, " mov dl, [ebp+edx] ; Get our zero page data\n"); else ReadMemoryByte("dl", "dx"); } if (FALSE == bNoDecimal) { fprintf(fp, " test [_altFlags], byte 08h ; Are we in decimal mode?\n"); fprintf(fp, " je binaryMode%ld ; It's binary mode\n", dwAnotherLabel); fprintf(fp, " jmp decimalMode%ld ; Yup - go handle dec mode\n", dwAnotherLabel); fprintf(fp, "binaryMode%ld:\n", dwAnotherLabel); } // Now let's ADC, man! fprintf(fp, " sahf ; Restore our flags for the adc\n"); fprintf(fp, " adc al, dl ; Add in our value\n"); fprintf(fp, " o16 pushf ; Push our flags (and overflow)\n"); fprintf(fp, " and ah, 02eh ; No carry, overflow, zero or sign\n"); fprintf(fp, " pop dx ; Restore our flags into DX\n"); fprintf(fp, " shl dh, 1 ; Shift overflow into position\n"); fprintf(fp, " and dh, 10h ; Only the overflow\n"); fprintf(fp, " and dl, 0c1h ; Only carry, sign, and zero\n"); fprintf(fp, " or ah, dl ; OR In our new flags\n"); fprintf(fp, " or ah, dh ; OR In overflow\n"); FetchAndExec(bTimingTable[dwOpcode]); if (FALSE == bNoDecimal) { fprintf(fp, "decimalMode%ld:\n", dwAnotherLabel); // On the way in: // AH=x86 Flags (0x01 = Carry) // AL=Accumulator value // DL=Value to add to fprintf(fp, " xor di, di ; Zero DI for later\n"); fprintf(fp, " sahf\n"); fprintf(fp, " adc di, 0 ; Increment if carry is set\n"); fprintf(fp, " and ah, 03ch ; Knock out carry, zero, sign, and overflow\n"); fprintf(fp, " mov [_%sx], bl ; Save X\n", cpubasename); fprintf(fp, " mov [_%sy], cl ; Save Y\n", cpubasename); fprintf(fp, " mov bl, al ; Get Accumulator\n"); fprintf(fp, " mov bh, dl ; Original value\n"); fprintf(fp, " mov cx, bx ; Put it here for later\n"); fprintf(fp, " and bx, 0f0fh ; Only the nibbles\n"); fprintf(fp, " add bl, bh ; Add it to the lower value\n"); fprintf(fp, " add bx, di ; Add in our carry\n"); fprintf(fp, " shr cx, 4 ; Upper nibbles only\n"); fprintf(fp, " and cx, 0f0fh ; Only the lower nibbles now\n"); fprintf(fp, " add cl, ch ; Add in the original value\n"); fprintf(fp, " mov bh, cl ; Put our upper nibble in BH\n"); fprintf(fp, " xor cx, cx ; Zero the upper part\n"); fprintf(fp, " cmp bl, 9 ; Digit overflow?\n"); fprintf(fp, " jbe notOverflowed%ld\n", dwAnotherLabel); fprintf(fp, " inc bh ; Increment - we've overflowed\n"); fprintf(fp, " add bl, 6 ; Fix the lower nibble\n"); fprintf(fp, "notOverflowed%ld:\n", dwAnotherLabel); fprintf(fp, " mov cl, al ; Get the accumulator\n"); fprintf(fp, " xor cl, dl ; XOR It with the original value\n"); fprintf(fp, " not cl ; Invert & add 1\n"); fprintf(fp, " mov ch, bh ; Get our high BCD\n"); fprintf(fp, " shl ch, 4 ; Move into position\n"); fprintf(fp, " and ch, cl ; And 'em together\n"); fprintf(fp, " or ch, ch ; See if we've overflowed\n"); fprintf(fp, " jns noOv%ld\n", dwAnotherLabel); fprintf(fp, " or ah, 040h ; Set overflow\n"); fprintf(fp, "noOv%ld:\n", dwAnotherLabel); fprintf(fp, " cmp bh, 9 ; Greater than 9?\n"); fprintf(fp, " jbe noOvTwo%ld\n", dwAnotherLabel); fprintf(fp, " add bh, 6 ; Digit fixup\n"); fprintf(fp, "noOvTwo%ld:\n", dwAnotherLabel); fprintf(fp, " mov al, bh ; Get most significant nibble\n"); fprintf(fp, " shl al, 4 ; Put it into position\n"); fprintf(fp, " and bl, 0fh ; Only the lower nibble matters now\n"); fprintf(fp, " or al, bl ; Put it in the accumulator\n"); fprintf(fp, " test bh, 0f0h ; Carry?\n"); fprintf(fp, " jz noCarry%ld\n", dwAnotherLabel); fprintf(fp, " or ah, 01h ; Set carry\n"); fprintf(fp, "noCarry%ld:\n", dwAnotherLabel); SetZeroSign("al"); fprintf(fp, " xor bx, bx ; Zero\n"); fprintf(fp, " xor cx, cx\n"); fprintf(fp, " mov bl, [_%sx] ; X!\n", cpubasename); fprintf(fp, " mov cl, [_%sy] ; Y!\n", cpubasename); FetchAndExec(bTimingTable[dwOpcode]); } dwAnotherLabel++; ProcEnd(string); } void SbcHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; SBC\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0xed == dwOpcode) Absolute(); else if (0xe5 == dwOpcode) ZeroPage(); else if (0xe9 == dwOpcode) Immediate("dl"); else if (0xfd == dwOpcode) AbsoluteX(); else if (0xf9 == dwOpcode) AbsoluteY(); else if (0xe1 == dwOpcode) IndirectX(); else if (0xf1 == dwOpcode) IndirectY(); else if (0xf5 == dwOpcode) ZeroPageX(); else assert(0); // We've got our address (or byte if immediate) in DL now if (0xe9 != dwOpcode) // Make sure it's not immediate { if (((0xe5 == dwOpcode) || (0xf5 == dwOpcode)) && bZeroDirect) fprintf(fp, " mov dl, [ebp+edx] ; Get our zero page data\n"); else ReadMemoryByte("dl", "dx"); } if (FALSE == bNoDecimal) { fprintf(fp, " test [_altFlags], byte 08h ; Are we in decimal mode?\n"); fprintf(fp, " jz binaryMode%ld ; It's binary mode\n", dwAnotherLabel); fprintf(fp, " jmp decimalMode%ld ; Yup - go handle dec mode\n", dwAnotherLabel); fprintf(fp, "binaryMode%ld:\n", dwAnotherLabel); } // Now let's SBC, man! fprintf(fp, " sahf ; Restore our flags for the adc\n"); fprintf(fp, " cmc\n"); fprintf(fp, " sbb al, dl ; Subtract our value\n"); fprintf(fp, " cmc\n"); fprintf(fp, " o16 pushf ; Push our flags (and overflow)\n"); fprintf(fp, " and ah, 02eh ; No carry, overflow, zero or sign\n"); fprintf(fp, " pop dx ; Restore our flags into DX\n"); fprintf(fp, " shl dh, 1 ; Shift overflow into position\n"); fprintf(fp, " and dh, 10h ; Only the overflow\n"); fprintf(fp, " and dl, 0c1h ; Only carry, sign, and zero\n"); fprintf(fp, " or ah, dl ; OR In our new flags\n"); fprintf(fp, " or ah, dh ; OR In overflow\n"); FetchAndExec(bTimingTable[dwOpcode]); if (FALSE == bNoDecimal) { fprintf(fp, "decimalMode%ld:\n", dwAnotherLabel); fprintf(fp, " xor di, di ; Zero our carry flag surrogate\n"); fprintf(fp, " xor ah, 01h ; Toggle carry - intentional\n"); fprintf(fp, " sahf\n"); fprintf(fp, " adc di, 0 ; Make 1 if carry is set\n"); fprintf(fp, " xor ah, ah ; Clear our flag register\n"); fprintf(fp, " mov [_%sx], bl ; Save X\n", cpubasename); fprintf(fp, " mov [_%sy], cl ; Save Y\n", cpubasename); fprintf(fp, " xor dh, dh ; Just in case we want to add with it later\n"); fprintf(fp, " mov cx, ax ; This is our sum\n"); fprintf(fp, " sub cx, dx ; Subtract our value\n"); fprintf(fp, " sub cx, di ; And our carry status\n"); fprintf(fp, " mov bl, al ; Get accumulator\n"); fprintf(fp, " xor bl, dl ; XOR With our value\n"); fprintf(fp, " mov bh, al ; Get accumulator\n"); fprintf(fp, " xor bh, cl ; XOR With our sum\n"); fprintf(fp, " and bl, bh ; See if we overflow\n"); fprintf(fp, " and bl, 80h ; Only the top bit\n"); fprintf(fp, " jns noOverflow%ld ; No overflow\n", dwAnotherLabel); fprintf(fp, " or ah, 40h ; Indicate an overflow\n"); fprintf(fp, "noOverflow%ld:\n", dwAnotherLabel); fprintf(fp, " mov bl, al ; Get our low value\n"); fprintf(fp, " mov bh, dl ; Original value\n"); fprintf(fp, " and bx, 0f0fh ; Only the lower nibbles\n"); fprintf(fp, " sub bl, bh ; Subtract\n"); fprintf(fp, " xor bh, bh ; Zero this\n"); fprintf(fp, " sub bx, di ; Subtract our !Carry flag\n"); fprintf(fp, " test bl, 0f0h ; Did we underflow?\n"); fprintf(fp, " jz noUnderFlow%ld\n", dwAnotherLabel); fprintf(fp, " sub bl, 6 ; BCD Fixup\n"); fprintf(fp, "noUnderFlow%ld:\n", dwAnotherLabel); fprintf(fp, " shr al, 4 ; Upper BCD\n"); fprintf(fp, " shr dl, 4 ; Upper BCD for the value\n"); fprintf(fp, " mov bh, al ; A\n"); fprintf(fp, " sub bh, dl ; Subtract our bigger BCD\n"); fprintf(fp, " or bl, bl ; Set flags\n"); fprintf(fp, " jns noHighNeg%ld\n", dwAnotherLabel); fprintf(fp, " dec bh ; Borrow\n"); fprintf(fp, "noHighNeg%ld:\n", dwAnotherLabel); fprintf(fp, " test bh, 0f0h ; Upper nibble? Underflow?\n"); fprintf(fp, " jz noUpperUnderflow%ld\n", dwAnotherLabel); fprintf(fp, " sub bh, 6 ; BCD Fixup\n"); fprintf(fp, "noUpperUnderflow%ld:\n", dwAnotherLabel); fprintf(fp, " or ch, ch ; Did we underflow on our sum?\n"); fprintf(fp, " jnz noUnderflow%ld ; Nope!\n", dwAnotherLabel); fprintf(fp, " or ah, 01h ; Set carry\n"); fprintf(fp, "noUnderflow%ld:\n", dwAnotherLabel); fprintf(fp, " and bl, 0fh ; Only the lower nibble\n"); fprintf(fp, " mov al, bl ; Low part\n"); fprintf(fp, " shl bh, 4 ; Move to upper BCD\n"); fprintf(fp, " or al, bh ; OR It in!\n"); SetZeroSign("al"); fprintf(fp, " xor bx, bx ; Zero\n"); fprintf(fp, " xor cx, cx\n"); fprintf(fp, " mov bl, [_%sx] ; X!\n", cpubasename); fprintf(fp, " mov cl, [_%sy] ; Y!\n", cpubasename); FetchAndExec(bTimingTable[dwOpcode]); } dwAnotherLabel++; ProcEnd(string); } void RolHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; ROL\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x2e == dwOpcode) Absolute(); else if (0x26 == dwOpcode) ZeroPage(); else if (0x3e == dwOpcode) AbsoluteX(); else if (0x36 == dwOpcode) ZeroPageX(); // Now that we've got the address (or whatever) let's fetch it! if (0x2a != dwOpcode) // Make sure it's not the accumulator { fprintf(fp, " push edx ; Save our address\n"); if (((0x36 == dwOpcode) || (0x26 == dwOpcode) && bZeroDirect)) fprintf(fp, " mov dl, [ebp+edx] ; Get our zero page byte\n"); else ReadMemoryByte("dl", "dx"); } // We've got the data in DL (or in AL if accumulator shift) fprintf(fp, " mov dh, ah ; Save off our original flags\n"); fprintf(fp, " and dh, 3eh ; No carry, zero, or sign\n"); fprintf(fp, " sahf ; Restore flags\n"); if (0x2a == dwOpcode) fprintf(fp, " rcl al, 1 ; Through carry rotate\n"); else fprintf(fp, " rcl dl, 1 ; Through carry rotate\n"); // Do the flag fixup here fprintf(fp, " lahf ; Get the current flags back\n"); fprintf(fp, " mov bh, ah ; Store it here for later\n"); // DH Contains our original flags, BH Contains the live carry flag fprintf(fp, " and bh, 1 ; Only the carry matters\n"); if (0x2a == dwOpcode) fprintf(fp, " or al, al ; Set sign/zero\n"); else fprintf(fp, " or dl, dl ; Set sign/zero\n"); fprintf(fp, " lahf ; Get the flags\n"); fprintf(fp, " and ah, 0c0h ; Only sign and zero\n"); fprintf(fp, " or ah, bh ; Or In our carry\n"); fprintf(fp, " or ah, dh ; Or in our original flags\n"); if (0x2a != dwOpcode) // Make sure it's not the accumulator { fprintf(fp, " mov bh, dl ; Get our byte to write\n"); fprintf(fp, " pop edx ; Restore the address\n"); if (((0x36 == dwOpcode) || (0x26 == dwOpcode) && (bZeroDirect))) fprintf(fp, " mov [ebp+edx], bh ; Set our zero page byte\n"); else WriteMemoryByte("bh", "dx"); } fprintf(fp, " xor bh, bh ; Zero this so we don't screw up things\n"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } void RorHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; ROR\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x6e == dwOpcode) Absolute(); else if (0x66 == dwOpcode) ZeroPage(); else if (0x7e == dwOpcode) AbsoluteX(); else if (0x76 == dwOpcode) ZeroPageX(); // Now that we've got the address (or whatever) let's fetch it! if (0x6a != dwOpcode) // Make sure it's not the accumulator { fprintf(fp, " push edx ; Save our address\n"); if (((0x76 == dwOpcode) || (0x66 == dwOpcode) && bZeroDirect)) fprintf(fp, " mov dl, [ebp+edx] ; Get our zero page byte\n"); else ReadMemoryByte("dl", "dx"); } // We've got the data in DL (or in AL if accumulator shift) fprintf(fp, " mov dh, ah ; Save off our original flags\n"); fprintf(fp, " and dh, 3eh ; No carry, zero, or sign\n"); fprintf(fp, " sahf ; Restore flags\n"); if (0x6a == dwOpcode) fprintf(fp, " rcr al, 1 ; Through carry rotate\n"); else fprintf(fp, " rcr dl, 1 ; Through carry rotate\n"); // Do the flag fixup here fprintf(fp, " lahf ; Get the current flags back\n"); fprintf(fp, " mov bh, ah ; Store it here for later\n"); // DH Contains our original flags, BH Contains the live carry flag fprintf(fp, " and bh, 1 ; Only the carry matters\n"); if (0x6a == dwOpcode) fprintf(fp, " or al, al ; Set sign/zero\n"); else fprintf(fp, " or dl, dl ; Set sign/zero\n"); fprintf(fp, " lahf ; Get the flags\n"); fprintf(fp, " and ah, 0c0h ; Only sign and zero\n"); fprintf(fp, " or ah, bh ; Or In our carry\n"); fprintf(fp, " or ah, dh ; Or in our original flags\n"); if (0x6a != dwOpcode) // Make sure it's not the accumulator { fprintf(fp, " mov bh, dl ; Get our byte to write\n"); fprintf(fp, " pop edx ; Restore the address\n"); if (((0x76 == dwOpcode) || (0x66 == dwOpcode) && (bZeroDirect))) fprintf(fp, " mov [ebp+edx], bh ; Set our zero page byte\n"); else WriteMemoryByte("bh", "dx"); } fprintf(fp, " xor bh, bh ; Zero this so we don't screw up things\n"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } void BitHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; BIT\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x2c == dwOpcode) Absolute(); else if (0x24 == dwOpcode) ZeroPage(); else assert(0); if ((0x2c == dwOpcode) || ((0x24 == dwOpcode) && (FALSE == bZeroDirect))) ReadMemoryByte("dl", "dx"); else fprintf(fp, " mov dl, [ebp+edx] ; Get our zero page byte\n"); fprintf(fp, " mov dh, dl ; Save this, too\n"); fprintf(fp, " and ah, 2fh ; Kill sign, zero, and overflow\n"); fprintf(fp, " mov bh, ah ; Put it here for later\n"); fprintf(fp, " and dl, al ; And this value with the accumulator\n"); fprintf(fp, " lahf ; Get our flags\n"); fprintf(fp, " and ah, 040h ; Only the zero matters\n"); fprintf(fp, " or ah, bh ; Get our other original flags back\n"); fprintf(fp, " mov dl, dh ; Get our value back\n"); fprintf(fp, " and dl, 80h ; Only the negative flag\n"); fprintf(fp, " or ah, dl ; OR It in with the original\n"); fprintf(fp, " and dh, 40h ; What we do with the 6th bit\n"); fprintf(fp, " shr dh, 2 ; Save this for later\n"); fprintf(fp, " or ah, dh ; OR In our \"overflow\"\n"); fprintf(fp, " xor bh, bh ; Zero this!\n"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } void PhaPhpHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); if (0x48 == dwOpcode) fprintf(fp, "; PHA\n"); else if (0x08 == dwOpcode) fprintf(fp, "; PHP\n"); else if (0xda == dwOpcode) fprintf(fp, "; PHX\n"); else if (0x5a == dwOpcode) fprintf(fp, "; PHY\n"); else assert(0); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x08 == dwOpcode) FlagsX86to6502(); fprintf(fp, " inc dh ; Stack page\n"); fprintf(fp, " mov dl, [_%ss] ; Stack pointer\n", cpubasename); if (0x08 == dwOpcode) fprintf(fp, " mov [ebp+edx], ah\n"); else if (0x48 == dwOpcode) fprintf(fp, " mov [ebp+edx], al\n"); else if (0xda == dwOpcode) fprintf(fp, " mov [ebp+edx], bl\n"); // X else if (0x5a == dwOpcode) fprintf(fp, " mov [ebp+edx], cl\n"); // Y fprintf(fp, " dec byte [_%ss] ; Decrement our stack pointer\n", cpubasename); if (0x08 == dwOpcode) Flags6502toX86(); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } void PlaPlpHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); if (0x28 == dwOpcode) fprintf(fp, "; PLP\n"); else if (0x68 == dwOpcode) fprintf(fp, "; PLA\n"); else if (0x7a == dwOpcode) fprintf(fp, "; PLY\n"); else if (0xfa == dwOpcode) fprintf(fp, "; PLX\n"); else assert(0); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); fprintf(fp, " inc dh ; Stack page\n"); fprintf(fp, " inc byte [_%ss] ; Increment our stack pointer\n", cpubasename); fprintf(fp, " mov dl, [_%ss] ; Stack pointer\n", cpubasename); if (0x28 == dwOpcode) // PLP { fprintf(fp, " mov ah, [ebp+edx]\n"); Flags6502toX86(); } else { if (0x68 == dwOpcode) fprintf(fp, " mov al, [ebp+edx]\n"); else if (0x7a == dwOpcode) // PLY fprintf(fp, " mov cl, [ebp+edx]\n"); else if (0xfa == dwOpcode) // PLX fprintf(fp, " mov bl, [ebp+edx]\n"); else assert(0); fprintf(fp, " mov dl, ah\n"); fprintf(fp, " and dl, 03fh\n"); if (0x68 == dwOpcode) fprintf(fp, " or al, al\n"); else if (0x7a == dwOpcode) fprintf(fp, " or cl, cl\n"); // PLY else if (0xfa == dwOpcode) fprintf(fp, " or bl, bl\n"); // PLX else assert(0); fprintf(fp, " lahf\n"); fprintf(fp, " and ah, 0c0h\n"); fprintf(fp, " or ah, dl\n"); } FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } void RtiHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; RTI\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); fprintf(fp, " mov dl, [_%ss] ; Get our stack pointer\n", cpubasename); fprintf(fp, " add [_%ss], byte 3 ; Restore our stack\n", cpubasename); fprintf(fp, " inc dh ; Increment to the stack page\n"); fprintf(fp, " inc dl ; And our pointer to the flags\n"); fprintf(fp, " mov ah, [ebp+edx] ; Get our flags\n"); fprintf(fp, " inc dl ; Next address\n"); fprintf(fp, " mov si, [ebp+edx] ; Get our new address\n"); fprintf(fp, " mov [_%spc], si ; Store our program counter\n", cpubasename); fprintf(fp, " or ah, 20h ; This bit is always 1\n"); fprintf(fp, " mov [_%saf + 1], ah ; Store our flags\n", cpubasename); fprintf(fp, " test ah, 04h ; Interrupts reenabled?\n"); fprintf(fp, " jnz notEnabled\n"); fprintf(fp, " cmp [_irqPending], byte 0 ; IRQ pending?\n"); fprintf(fp, " je notEnabled\n"); fprintf(fp, " push eax ; Save this - we need it\n"); fprintf(fp, " call _%sint ; Go do an interrupt\n", cpubasename); fprintf(fp, " pop eax ; Restore this - we need it!\n"); fprintf(fp, "notEnabled:\n"); fprintf(fp, " xor esi, esi\n"); fprintf(fp, " mov si, [_%spc] ; Get our program counter\n", cpubasename); if (bBankswitch) PCToPage(); else fprintf(fp, " add esi, ebp ; So it properly points to the code\n"); Flags6502toX86(); ++dwGlobalLabel; FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } void NopHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; NOP\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } void StzHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; STZ\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); // 64 - Zero page // 74 - Zero page X // 9c - Absolute // 9e - Absolute X // First fetch the info if (0x64 == dwOpcode) { ZeroPage(); if (FALSE != bZeroDirect) fprintf(fp, " mov [ebp+edx], byte 0 ; Zero it!\n"); } else if (0x74 == dwOpcode) ZeroPageX(); else if (0x9c == dwOpcode) Absolute(); else if (0x9e == dwOpcode) AbsoluteX(); // Now we have the address in DX - let's see what we do with it if ((0x64 != dwOpcode) || (FALSE == bZeroDirect)) WriteMemoryByte("bh", "dx"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } void BraHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; BRA\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); FetchInstructionByte(); // Go get our offset just in case fprintf(fp, " movsx dx, dl\n"); if (bBankswitch) PageToPC(); else fprintf(fp, " sub esi, ebp ; Get our real program counter\n"); fprintf(fp, " add si, dx\n"); if (bBankswitch) { fprintf(fp, " mov [_%spc], si\n", cpubasename); PCToPage(); } else fprintf(fp, " add esi, ebp\n"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } void TsbHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; TSB\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x04 == dwOpcode) // Zero page ZeroPage(); else if (0x0c == dwOpcode) // Absolute Absolute(); else assert(0); // Address is now in EDX if ((FALSE != bZeroDirect) && (0x04 == dwOpcode)) // If it's zero page, just do the work! { fprintf(fp, " or [ebp+edx], al ; OR In accumulator\n"); fprintf(fp, " mov dh, [ebp+edx] ; Get the data\n"); } else // We go through our handlers { fprintf(fp, " mov [_tempAddr], edx ; Store our address for later\n"); ReadMemoryByte("dh", "dx"); fprintf(fp, " or dh, al ; OR In our value\n"); fprintf(fp, " mov bh, dh ; Our value\n"); fprintf(fp, " push edx ; Save this for later\n"); WriteMemoryByte("bh", "dx"); fprintf(fp, " pop edx ; Restore our data (in DL)\n"); fprintf(fp, " xor bh, bh ; Zero this\n"); } // Now we have our value in DH - set the zero flag accordingly SetZero("dh"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } void TrbHandler(UINT16 dwOpcode) { fprintf(fp, ";\n"); fprintf(fp, "; TRB\n"); fprintf(fp, ";\n"); sprintf(string, "RegInst%.2x", dwOpcode); ProcBegin(string, dwOpcode); if (0x14 == dwOpcode) // Zero page ZeroPage(); else if (0x1c == dwOpcode) // Absolute Absolute(); else assert(0); // Address is now in EDX fprintf(fp, " mov bh, al\n"); fprintf(fp, " xor bh, 0ffh\n"); if ((FALSE != bZeroDirect) && (0x04 == dwOpcode)) // If it's zero page, just do the work! { fprintf(fp, " and [ebp+edx], bh ; AND In the appropriate value\n"); fprintf(fp, " mov dh, [ebp+edx] ; Get the data\n"); } else // We go through our handlers { fprintf(fp, " mov [_tempAddr], edx ; Store our address for later\n"); ReadMemoryByte("dh", "dx"); fprintf(fp, " and dh, bh ; AND In our value\n"); fprintf(fp, " mov bh, dh ; Our value\n"); fprintf(fp, " push edx ; Save this for later\n"); WriteMemoryByte("bh", "dx"); fprintf(fp, " pop edx ; Restore our data (in DL)\n"); fprintf(fp, " xor bh, bh ; Zero this\n"); } // Now we have our value in DH - set the zero flag accordingly SetZero("dh"); FetchAndExec(bTimingTable[dwOpcode]); ProcEnd(string); } /* These are the meta routines */ ExecCode() { fprintf(fp, " global _%sexec\n", cpubasename); fprintf(fp, " global %sexec_\n", cpubasename); if (bPlain) fprintf(fp, " global %sexec\n", cpubasename); if (bPlain) sprintf(string, "%sexec", cpubasename); else sprintf(string, "%sexec_", cpubasename); ProcBegin(string, 0xffffffff); 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"); if (bSingleStep) fprintf(fp, " mov eax, 2 ; No longer cycles - now instructions!\n"); fprintf(fp, " mov dword [cyclesRemaining], eax ; Store # of instructions to\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 esi, esi ; Zero our source address\n"); fprintf(fp, "\n"); fprintf(fp, " mov bl, [_%sx] ; Get X\n", cpubasename); fprintf(fp, " mov cl, [_%sy] ; Get Y\n", cpubasename); fprintf(fp, " mov ax, [_%saf] ; Get our flags and accumulator\n", cpubasename); fprintf(fp, " mov si, [_%spc] ; Get our program counter\n", cpubasename); fprintf(fp, " mov ebp, [_%sBase] ; Get our base address register\n", cpubasename); if (bBankswitch) PCToPage(); else fprintf(fp, " add esi, ebp ; Add in our base address\n"); fprintf(fp, " xor edx, edx ; And EDX\n"); fprintf(fp, " xor edi, edi ; Zero EDI as well\n"); Flags6502toX86(); FetchAndExec(0); 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, " dec esi ; Back up one instruction...\n"); if (FALSE == bBankswitch) { fprintf(fp, " mov edx, esi ; Get our address in EAX\n"); fprintf(fp, " sub edx, ebp ; And subtract our base for\n"); } else { PageToPC(); fprintf(fp, " mov edx, esi\n"); } fprintf(fp, " ; an invalid instruction\n"); fprintf(fp, " jmp short emulateEnd\n"); fprintf(fp, "\n"); fprintf(fp, "noMoreExec:\n"); fprintf(fp, " dec esi\n"); if (bBankswitch) PageToPC(); // Put any register storing here fprintf(fp, " mov edx, 80000000h ; Indicate successful exec\n"); // Store all the registers here fprintf(fp, "emulateEnd:\n"); fprintf(fp, " push edx ; Save this for the return\n"); FlagsX86to6502(); fprintf(fp, " mov [_%sx], bl ; Store X\n", cpubasename); fprintf(fp, " mov [_%sy], cl ; Store Y\n", cpubasename); fprintf(fp, " mov [_%saf], ax ; Store A & flags\n", cpubasename); if (FALSE == bBankswitch) fprintf(fp, " sub esi, ebp ; Get our PC back\n"); fprintf(fp, " mov [_%spc], si ; Store PC\n", cpubasename); fprintf(fp, " pop edx ; Restore EDX for later\n"); fprintf(fp, "\n"); fprintf(fp, "popReg:\n"); fprintf(fp, " mov eax, edx ; Get our result code\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"); ProcEnd(string); } CpuInit() { fprintf(fp, " global _%sinit\n", cpubasename); fprintf(fp, " global %sinit_\n", cpubasename); if (bPlain) sprintf(string, "%sinit", cpubasename); else sprintf(string, "%sinit_", cpubasename); ProcBegin(string, 0xffffffff); fprintf(fp, "_%sinit:\n", cpubasename); fprintf(fp, " ret\n"); ProcEnd(string); } NmiCode() { fprintf(fp, " global _%snmi\n", cpubasename); fprintf(fp, " global %snmi_\n", cpubasename); if (bPlain) sprintf(string, "%snmi", cpubasename); else sprintf(string, "%snmi_", cpubasename); ProcBegin(string, 0xffffffff); fprintf(fp, "_%snmi:\n", cpubasename); fprintf(fp, " push edi\n", cpubasename); fprintf(fp, " push ebx\n", cpubasename); fprintf(fp, "\n", cpubasename); fprintf(fp, " mov ebx, 0100h ; Point to stack page\n", cpubasename); fprintf(fp, "\n", cpubasename); fprintf(fp, " mov edi, [_%sBase] ; Get pointer to game image\n", cpubasename); fprintf(fp, " mov bl, [_%ss] ; Get our S reg pointer\n", cpubasename); fprintf(fp, " mov ax, [_%spc] ; Get our PC\n", cpubasename); fprintf(fp, "\n", cpubasename); fprintf(fp, " mov [edi + ebx], ah ; Store it!\n", cpubasename); fprintf(fp, " dec bl\n", cpubasename); fprintf(fp, " mov [edi + ebx], al ; Store it!\n", cpubasename); fprintf(fp, " dec bl\n", cpubasename); fprintf(fp, "\n", cpubasename); fprintf(fp, " mov al, byte [_%saf+1] ; Get our flags\n", cpubasename); fprintf(fp, "\n", cpubasename); fprintf(fp, "\n", cpubasename); fprintf(fp, " mov [edi + ebx], al ; Store flags\n", cpubasename); fprintf(fp, " dec bl\n", cpubasename); fprintf(fp, " mov ax, [edi+0fffah] ; Get our start vector!\n", cpubasename); fprintf(fp, "\n", cpubasename); fprintf(fp, " mov [_%ss], bl ; Store S reg pointer\n", cpubasename); fprintf(fp, " and [_%saf + 1], byte 0efh ; Knock out source of interrupt bit\n", cpubasename); fprintf(fp, " or [_%saf + 1], byte 24h ; Turn on something\n", cpubasename); fprintf(fp, " mov [_%spc], ax ; Store our new PC\n", cpubasename); fprintf(fp, "\n", cpubasename); fprintf(fp, " pop ebx\n", cpubasename); fprintf(fp, " pop edi\n", cpubasename); fprintf(fp, "\n", cpubasename); fprintf(fp, " xor eax, eax ; Indicate that we took the NMI\n", cpubasename); fprintf(fp, " ret\n", cpubasename); ProcEnd(string); } IntCode() { fprintf(fp, " global _%sint\n", cpubasename); fprintf(fp, " global %sint_\n", cpubasename); if (bPlain) sprintf(string, "%sint", cpubasename); else sprintf(string, "%sint_", cpubasename); ProcBegin(string, 0xffffffff); fprintf(fp, "_%sint:\n", cpubasename); fprintf(fp, " test [_%saf + 1], byte 04h ; Are interrupts disabled?\n", cpubasename); fprintf(fp, " jnz intNotTaken ; Nope! Make it pending!\n"); fprintf(fp, " mov [_irqPending], byte 00h ; No longer pending\n"); fprintf(fp, " push edi\n"); fprintf(fp, " push ebx\n"); fprintf(fp, " push ax\n"); fprintf(fp, " mov ebx, 0100h ; Point to stack page\n"); fprintf(fp, " mov edi, [_%sBase] ; Get pointer to game image\n", cpubasename); fprintf(fp, " mov bl, [_%ss] ; Get our S reg pointer\n", cpubasename); fprintf(fp, " mov ax, [_%spc] ; Get our PC\n", cpubasename); fprintf(fp, " mov [edi + ebx], ah ; Store it!\n"); fprintf(fp, " dec bl\n"); fprintf(fp, " mov [edi + ebx], al ; Store it!\n"); fprintf(fp, " dec bl\n"); fprintf(fp, " mov al, byte [_%saf+1] ; Get our flags\n", cpubasename); fprintf(fp, " mov [edi + ebx], al ; Store flags\n"); fprintf(fp, " dec bl\n"); fprintf(fp, " mov ax, [edi+0fffeh] ; Get our start vector!\n"); fprintf(fp, " mov [_%ss], bl ; Store S reg pointer\n", cpubasename); fprintf(fp, " and [_%saf + 1], byte 0efh ; Knock out source of interrupt bit\n", cpubasename); fprintf(fp, " or [_%saf + 1], byte 24h ; Turn on something\n", cpubasename); fprintf(fp, " mov [_%spc], ax ; Store our new PC\n", cpubasename); fprintf(fp, " pop ax ; Restore used registers\n"); fprintf(fp, " pop ebx\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " xor eax, eax ; Indicate we've taken the interrupt\n"); fprintf(fp, " mov [_irqPending], al ; No more IRQ pending!\n"); fprintf(fp, " ret\n"); fprintf(fp, "intNotTaken:\n"); fprintf(fp, " mov eax, 1 ; Indicate we didn't take it\n"); fprintf(fp, " mov [_irqPending], al ; Indicate we have a pending IRQ\n"); fprintf(fp, " ret\n"); ProcEnd(string); } GetTicksCode() { fprintf(fp, " global _%sGetElapsedTicks\n", cpubasename); fprintf(fp, " global %sGetElapsedTicks_\n", cpubasename); if (bPlain) sprintf(string, "%sGetElapsedTicks", cpubasename); else sprintf(string, "%sGetElapsedTicks_", cpubasename); ProcBegin(string, 0xffffffff); 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"); ProcEnd(string); } ReleaseTimesliceCode() { fprintf(fp, " global _%sReleaseTimeslice\n", cpubasename); fprintf(fp, " global %sReleaseTimeslice_\n", cpubasename); if (bPlain) sprintf(string, "%sReleaseTimeslice", cpubasename); else sprintf(string, "%sReleaseTimeslice_", cpubasename); ProcBegin(string, 0xffffffff); fprintf(fp, "_%sReleaseTimeslice:\n", cpubasename); fprintf(fp, " mov [cyclesRemaining], dword 1\n"); fprintf(fp, " ret\n"); ProcEnd(string); } ResetCode() { fprintf(fp, " global _%sreset\n", cpubasename); fprintf(fp, " global %sreset_\n", cpubasename); fprintf(fp, " global %sreset\n", cpubasename); if (bPlain) sprintf(string, "%sreset", cpubasename); else sprintf(string, "%sreset_", cpubasename); ProcBegin(string, 0xffffffff); fprintf(fp, "_%sreset:\n", cpubasename); fprintf(fp, " push ebp ; Save our important register\n"); fprintf(fp, " xor eax, eax\n"); fprintf(fp, " mov ebp, [_%sBase]\n", cpubasename); fprintf(fp, " mov [_%sx], al\n", cpubasename); fprintf(fp, " mov [_%sy], al\n", cpubasename); fprintf(fp, " mov [_irqPending], al\n"); fprintf(fp, " mov [_%ss], byte 0ffh\n", cpubasename); fprintf(fp, " mov [_%saf], word 2200h\n", cpubasename); fprintf(fp, " mov ax, [ebp + 0fffch] ; Get reset address\n"); fprintf(fp, " mov [_%spc], ax\n", cpubasename); fprintf(fp, " pop ebp\n"); fprintf(fp, " ret\n"); fprintf(fp, "\n"); ProcEnd(string); } SetContextCode() { fprintf(fp, " global _%sSetContext\n", cpubasename); fprintf(fp, " global %sSetContext_\n", cpubasename); fprintf(fp, " global %sSetContext\n", cpubasename); if (bPlain) sprintf(string, "%sSetContext", cpubasename); else sprintf(string, "%sSetContext_", cpubasename); ProcBegin(string, 0xffffffff); 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, " mov ecx, _%scontextEnd - _%scontextBegin\n", cpubasename, cpubasename); fprintf(fp, " mov edi, _%scontextBegin\n", cpubasename); fprintf(fp, " mov esi, eax ; Source address in ESI\n"); fprintf(fp, " rep movsb ; Move it as fast as we can!\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " ret ; No return code\n"); ProcEnd(string); } GetContextCode() { fprintf(fp, " global _%sGetContext\n", cpubasename); fprintf(fp, " global %sGetContext_\n", cpubasename); fprintf(fp, " global %sGetContext\n", cpubasename); if (bPlain) sprintf(string, "%sGetContext", cpubasename); else sprintf(string, "%sGetContext_", cpubasename); ProcBegin(string, 0xffffffff); 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, " mov ecx, _%scontextEnd - _%scontextBegin\n", cpubasename, cpubasename); fprintf(fp, " mov esi, _%scontextBegin\n", cpubasename); fprintf(fp, " mov edi, eax ; Source address in ESI\n"); fprintf(fp, " rep movsb ; Move it as fast as we can!\n"); fprintf(fp, " pop ecx\n"); fprintf(fp, " pop edi\n"); fprintf(fp, " pop esi\n"); fprintf(fp, " ret ; No return code\n"); ProcEnd(string); } GetContextSizeCode() { fprintf(fp, " global _%sGetContextSize\n", cpubasename); fprintf(fp, " global %sGetContextSize_\n", cpubasename); fprintf(fp, " global %sGetContextSize\n", cpubasename); if (bPlain) sprintf(string, "%sGetContextSize", cpubasename); else sprintf(string, "%sGetContextSize_", cpubasename); ProcBegin(string, 0xffffffff); fprintf(fp, "_%sGetContextSize:\n", cpubasename); fprintf(fp, " mov eax, _%scontextEnd - _%scontextBegin\n", cpubasename, cpubasename); fprintf(fp, " ret\n"); ProcEnd(string); } EmitCode() { CodeSegmentBegin(); ReadMemoryByteHandler(); EmitRegularInstructions(); GetContextCode(); SetContextCode(); GetContextSizeCode(); CpuInit(); GetTicksCode(); ReleaseTimesliceCode(); ResetCode(); IntCode(); NmiCode(); ExecCode(); CodeSegmentEnd(); } main(int argc, char **argv) { UINT32 dwLoop = 0; printf("Make6502 - V%s - Copyright 1998, Neil Bradley (neil@synthcom.com)\n", VERSION); if (argc < 2) { printf("Usage: %s outfile [option1] [option2] ....\n", argv[0]); printf("\n -ss - Create m6502(zp) to execute one instruction per m6502exec()\n"); printf(" -s - Stack calling conventions (DJGPP, MSVC, Borland)\n"); printf(" -z - Create zero page version of m6502 (see documentation)\n"); printf(" -bs - Create boundary bank switched version (8K page default)\n"); printf(" -l - Create 'plain' function names with no leading or trailing _'s\n"); printf(" -# - -2=2K bank switch, -4=4K Banks, -8=8K Banks, -16=16K Banks\n"); printf(" -i - Treat invalid instructions as NOPs\n"); printf(" -d - No decimal mode\n"); printf(" -6510 - Include 6510 instructions\n"); exit(1); } dwLoop = 1; while (dwLoop < (UINT32)argc) { if (strcmp("-l", argv[dwLoop]) == 0) bPlain = TRUE; if (strcmp("-2", argv[dwLoop]) == 0) dwBankSize = 11; if (strcmp("-4", argv[dwLoop]) == 0) dwBankSize = 12; if (strcmp("-8", argv[dwLoop]) == 0) dwBankSize = 13; if (strcmp("-16", argv[dwLoop]) == 0) dwBankSize = 14; if (strcmp("-bs", argv[dwLoop]) == 0 || strcmp("-BS", argv[dwLoop]) == 0) bBankswitch = 1; if (strcmp("-ss", argv[dwLoop]) == 0 || strcmp("-S", argv[dwLoop]) == 0) bSingleStep = 1; if (strcmp("-s", argv[dwLoop]) == 0 || strcmp("-S", argv[dwLoop]) == 0) bUseStack = 1; if (strcmp("-z", argv[dwLoop]) == 0 || strcmp("-Z", argv[dwLoop]) == 0) bZeroDirect = (UINT8) TRUE; if (strcmp("-i", argv[dwLoop]) == 0 || strcmp("-I", argv[dwLoop]) == 0) bInvalidAsNop = (UINT8) TRUE; if (strcmp("-d", argv[dwLoop]) == 0 || strcmp("-D", argv[dwLoop]) == 0) bNoDecimal = (UINT8) TRUE; if (strcmp("-6510", argv[dwLoop]) == 0) b6510Instructions = (UINT8) TRUE; dwLoop++; } if (bBankswitch) strcpy(cpubasename, "m6502bs"); else if (bZeroDirect) strcpy(cpubasename, "m6502zp"); else strcpy(cpubasename, "m6502"); for (dwLoop = 1; dwLoop < (UINT32)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]); } StandardHeader(); DataSegment(); EmitCode(); ProgramEnd(); fclose(fp); }