📄 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 <stdio.h>#include <stdlib.h>#include <string.h>#include <assert.h>#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 charFILE *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 conventionsUINT8 bZeroDirect = FALSE; // Zero page directUINT8 bSingleStep = FALSE; // Here if we want to single step the CPUUINT8 bBankswitch = FALSE; // Here if we want bankswitchingUINT8 bInvalidAsNop = FALSE; // Treat invalid instructions as NOPUINT8 bNoDecimal = FALSE; // Set if we don't want decimal modeUINT8 b6510Instructions = FALSE; // TRUE If we include 6510 instructionsUINT32 dwBankSize = 12; // 4K Defaultstatic 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");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -