From: uz Date: Thu, 5 Apr 2012 13:30:21 +0000 (+0000) Subject: Intermediate state - doesn't run as is. X-Git-Tag: V2.14~424 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=10d58204b5957df297838c5ac783ab8ebac52e37;p=cc65 Intermediate state - doesn't run as is. git-svn-id: svn://svn.cc65.org/cc65/trunk@5643 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- diff --git a/src/sim65/addrspace.c b/src/sim65/addrspace.c index 1eda9f76a..78c069437 100644 --- a/src/sim65/addrspace.c +++ b/src/sim65/addrspace.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2002-2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ diff --git a/src/sim65/addrspace.h b/src/sim65/addrspace.h index b353068e4..8d50156b4 100644 --- a/src/sim65/addrspace.h +++ b/src/sim65/addrspace.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2003-2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ diff --git a/src/sim65/cfgdata.c b/src/sim65/cfgdata.c index 5c33ea2a7..e1cbf98e9 100644 --- a/src/sim65/cfgdata.c +++ b/src/sim65/cfgdata.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2002-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2002-2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -57,17 +57,14 @@ CfgData* NewCfgData (void) * uses the current output of the config scanner. */ { - /* Get the length of the identifier */ - unsigned AttrLen = strlen (CfgSVal); - /* Allocate memory */ - CfgData* D = xmalloc (sizeof (CfgData) + AttrLen); + CfgData* D = xmalloc (sizeof (CfgData) + SB_GetLen (&CfgSVal)); /* Initialize the fields */ D->Type = CfgDataInvalid; D->Line = CfgErrorLine; D->Col = CfgErrorCol; - memcpy (D->Attr, CfgSVal, AttrLen+1); + memcpy (D->Attr, SB_GetConstBuf (&CfgSVal), SB_GetLen (&CfgSVal) + 1); /* Return the new struct */ return D; @@ -78,7 +75,7 @@ CfgData* NewCfgData (void) void FreeCfgData (CfgData* D) /* Free a config data structure */ { - if (D->Type == CfgDataString) { + if (D->Type == CfgDataId || D->Type == CfgDataString) { /* Free the string value */ xfree (D->V.SVal); } diff --git a/src/sim65/cfgdata.h b/src/sim65/cfgdata.h index c86522f72..f1a278f92 100644 --- a/src/sim65/cfgdata.h +++ b/src/sim65/cfgdata.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2002-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2002-2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -58,7 +58,7 @@ struct CfgData { CfgDataString } Type; /* Type of the value */ union { - char* SVal; /* String or id value */ + char* SVal; /* String or id value */ long IVal; /* Integer value */ } V; unsigned Line; /* Line where the attribute was defined */ diff --git a/src/sim65/chip.c b/src/sim65/chip.c index 50d248c4e..7d1504bf9 100644 --- a/src/sim65/chip.c +++ b/src/sim65/chip.c @@ -105,6 +105,8 @@ static const SimData Sim65Data = { GetCfgId, GetCfgStr, GetCfgNum, + 0, + 0, Break, IRQRequest, NMIRequest, @@ -156,7 +158,7 @@ static int GetCfgNum (void* CfgInfo, const char* Name, long* Val) static int CmpChips (void* Data attribute ((unused)), - const void* lhs, const void* rhs) + const void* lhs, const void* rhs) /* Compare function for CollSort */ { /* Cast the object pointers */ @@ -404,7 +406,7 @@ void LoadChipLibrary (const char* LibName) /* Output chip name and version to keep the user happy */ Print (stdout, 1, " Found %s `%s', version %u.%u in library `%s'\n", - (D->Type == CHIPDATA_TYPE_CHIP)? "chip" : "cpu", + (D->Type == CHIPDATA_TYPE_CHIP)? "chip" : "cpu", D->ChipName, D->MajorVersion, D->MinorVersion, diff --git a/src/sim65/chips/console.c b/src/sim65/chips/console.c index c257fa787..528925b14 100644 --- a/src/sim65/chips/console.c +++ b/src/sim65/chips/console.c @@ -6,7 +6,7 @@ /* */ /* */ /* */ -/* (C) 2003-2009, Ullrich von Bassewitz */ +/* (C) 2003-2012, Ullrich von Bassewitz */ /* Roemerstrasse 52 */ /* D-70794 Filderstadt */ /* EMail: uz@cc65.org */ diff --git a/src/sim65/chips/make/gcc.mak b/src/sim65/chips/make/gcc.mak index 82a5e152e..506b1670a 100644 --- a/src/sim65/chips/make/gcc.mak +++ b/src/sim65/chips/make/gcc.mak @@ -6,7 +6,7 @@ COMMON = ../../common SIM65 = .. -CFLAGS = -g -O2 -Wall -W -std=c89 +CFLAGS = -g -Wall -W -std=c89 override CFLAGS += -I$(COMMON) -I$(SIM65) -fpic CC = gcc EBIND = emxbind diff --git a/src/sim65/chips/stdio.c b/src/sim65/chips/stdio.c index bce203f84..1e66feb97 100644 --- a/src/sim65/chips/stdio.c +++ b/src/sim65/chips/stdio.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2002-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2002-2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -60,9 +60,15 @@ static void* CreateInstance (unsigned Addr, unsigned Range, void* CfgInfo); static void DestroyInstance (void* Data); /* Destroy a chip instance */ +static void WriteCtrl (void* Data, unsigned Offs, unsigned char Val); +/* Write control data */ + static void Write (void* Data, unsigned Offs, unsigned char Val); /* Write user data */ +static unsigned char ReadCtrl (void* Data, unsigned Offs); +/* Read control data */ + static unsigned char Read (void* Data, unsigned Offs); /* Read user data */ @@ -74,6 +80,9 @@ static unsigned char Read (void* Data, unsigned Offs); +/* The SimData pointer we get when InitChip is called */ +static const SimData* Sim; + /* Control data passed to the main program */ static const struct ChipData CData[1] = { { @@ -86,15 +95,33 @@ static const struct ChipData CData[1] = { InitChip, CreateInstance, DestroyInstance, + WriteCtrl, Write, - Write, - Read, + ReadCtrl, Read } }; -/* The SimData pointer we get when InitChip is called */ -static const SimData* Sim; +/* Screen instance data */ +typedef struct InstanceData InstanceData; +struct InstanceData { + /* The memory area used for data */ + unsigned char* Mem[32]; +}; + +/* Function opcodes */ +enum { + F_open, + F_close, + F_write, + F_read, + F_lseek, + F_unlink, + F_chdir, + F_getcwd, + F_mkdir, + F_rmdir, +}; @@ -137,8 +164,14 @@ static int InitChip (const struct SimData* Data) static void* CreateInstance (unsigned Addr, unsigned Range, void* CfgInfo) /* Initialize a new chip instance */ { - /* We don't need any instance data */ - return 0; + /* Allocate the instance data */ + InstanceData* D = Sim->Malloc (sizeof (InstanceData)); + + /* Initialize the instance data */ + memset (D->Mem, 0x00, sizeof (D->Mem)); + + /* Return the instance data */ + return D; } @@ -146,28 +179,111 @@ static void* CreateInstance (unsigned Addr, unsigned Range, void* CfgInfo) static void DestroyInstance (void* Data) /* Destroy a chip instance */ { + /* Cast the instance data pointer */ + InstanceData* D = Data; + + /* Free the instance data */ + Sim->Free (D); +} + + + +static void WriteCtrl (void* Data attribute, unsigned Offs, unsigned char Val) +/* Write user data */ +{ + /* Cast the instance data pointer */ + InstanceData* D = Data; + + /* Write to the memory */ + D->Mem[Offs] = Val; } -static void Write (void* Data attribute ((unused)), - unsigned Offs attribute ((unused)), - unsigned char Val) +static void Write (void* Data, unsigned Offs, unsigned char Val) /* Write user data */ { - putchar (Val); + /* Cast the instance data pointer */ + InstanceData* D = Data; + + /* Write to the memory */ + D->Mem[Offs] = Val; + + /* Now check the offset. Zero is special because it will trigger the + * action + */ + if (Offs == 0) { + + /* The action is determined by the value that is written */ + switch (Val) { + + case F_open: + Sim->Break ("Unsupported function $%02X", Val); + break; + + case F_close: + Sim->Break ("Unsupported function $%02X", Val); + break; + + case F_write: + Sim->Break ("Unsupported function $%02X", Val); + break; + + case F_read: + Sim->Break ("Unsupported function $%02X", Val); + break; + + case F_lseek: + Sim->Break ("Unsupported function $%02X", Val); + break; + + case F_unlink: + Sim->Break ("Unsupported function $%02X", Val); + break; + + case F_chdir: + Sim->Break ("Unsupported function $%02X", Val); + break; + + case F_getcwd: + Sim->Break ("Unsupported function $%02X", Val); + break; + + case F_mkdir: + Sim->Break ("Unsupported function $%02X", Val); + break; + + case F_rmdir: + Sim->Break ("Unsupported function $%02X", Val); + break; + + } + } } -static unsigned char Read (void* Data attribute ((unused)), - unsigned Offs attribute ((unused))) +static unsigned char ReadCtrl (void* Data, unsigned Offs) /* Read user data */ { - /* Read a character and return the value */ - return getchar (); + /* Cast the instance data pointer */ + InstanceData* D = Data; + + /* Read the cell and return the value */ + return D->Mem[Offs]; } +static unsigned char Read (void* Data, unsigned Offs) +/* Read user data */ +{ + /* Cast the instance data pointer */ + InstanceData* D = Data; + + /* Read the cell and return the value */ + return D->Mem[Offs]; +} + + diff --git a/src/sim65/config.c b/src/sim65/config.c index 3a2a14cdc..7c828026c 100644 --- a/src/sim65/config.c +++ b/src/sim65/config.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 1998-2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -46,11 +46,11 @@ #include "xmalloc.h" /* sim65 */ +#include "addrspace.h" #include "cfgdata.h" #include "chip.h" #include "error.h" #include "global.h" -#include "memory.h" #include "location.h" #include "scanner.h" #include "config.h" @@ -143,18 +143,26 @@ static void ParseCPU (void) AttrCheck (Attr, atType, "TYPE"); AttrCheck (Attr, atAddrSpace, "ADDRSPACE"); + /* Create the CPU */ + CPUInstance = NewCPU ("6502", Size); + /* Skip the semicolon */ CfgConsumeSemi (); } -static void ParseMemory (void) -/* Parse a MEMORY section */ +static void ParseAddrSpace (void) +/* Parse a ADDRSPACE section */ { unsigned I; + /* CPU must be defined before the address space */ + if (CPUInstance == 0) { + CfgError ("CPU must be defined before address space definitions"); + } + /* Parse addresses */ while (CfgTok == CFGTOK_INTCON) { Location* L; @@ -263,8 +271,8 @@ static void ParseMemory (void) /* Delete the "name" attribute */ FreeCfgData (D); - /* Assign the chip instance to memory */ - MemAssignChip (CI, L->Start, Range); + /* Assign the chip instance to address space */ + ASAssignChip (CPUInstance->AS, CI, L->Start, Range); } /* Create the mirrors */ @@ -295,7 +303,7 @@ static void ParseMemory (void) /* For simplicity, get the chip instance we're mirroring from the * memory, instead of searching for the range in the list. */ - CI = MemGetChip (MirrorAddr); + CI = ASGetChip (MirrorAddr); if (CI == 0) { /* We are mirroring an unassigned address */ Error ("%s(%u): Mirroring an unassigned address", @@ -316,8 +324,8 @@ static void ParseMemory (void) /* Clone the chip instance for the new location */ MCI = MirrorChipInstance (CI, L->Start - Offs); - /* Assign the chip instance to memory */ - MemAssignChip (MCI, L->Start, Range); + /* Assign the chip instance to address space */ + ASAssignChip (CPUInstance->AS, MCI, L->Start, Range); } } @@ -327,8 +335,8 @@ static void ParseConfig (void) /* Parse the config file */ { static const IdentTok BlockNames [] = { - { "CPU", CFGTOK_CPU }, - { "MEMORY", CFGTOK_MEMORY }, + { "ADDRSPACE", CFGTOK_ADDRSPACE }, + { "CPU", CFGTOK_CPU }, }; cfgtok_t BlockTok; @@ -345,12 +353,12 @@ static void ParseConfig (void) /* Read the block */ switch (BlockTok) { - case CFGTOK_CPU: - ParseCPU (); + case CFGTOK_ADDRSPACE: + ParseAddrSpace (); break; - case CFGTOK_MEMORY: - ParseMemory (); + case CFGTOK_CPU: + ParseCPU (); break; default: diff --git a/src/sim65/cpu-6502.c b/src/sim65/cpu-6502.c new file mode 100644 index 000000000..39929634d --- /dev/null +++ b/src/sim65/cpu-6502.c @@ -0,0 +1,2592 @@ +/*****************************************************************************/ +/* */ +/* cpucore.c */ +/* */ +/* CPU core for the 6502 simulator */ +/* */ +/* */ +/* */ +/* (C) 2003-2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#include +#include +#include + +/* common */ +#include "abend.h" +#include "attrib.h" +#include "print.h" +#include "strbuf.h" + +/* sim65 */ +#include "cpuregs.h" +#include "cputype.h" +#include "error.h" +#include "global.h" +#include "memory.h" +#include "cpucore.h" + + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* Registers */ +CPURegs Regs; + +/* Count the total number of cylcles */ +unsigned Cycles; /* Cycles per insn */ +unsigned long TotalCycles; /* Total cycles */ + +/* Allow the stack page to be changed */ +static unsigned StackPage = 0x100; + +/* CPU flags */ +int HaveNMIRequest = 0; +int HaveIRQRequest = 0; +int CPUHalted = 0; + +/* Break message */ +static StrBuf BreakMsg = STATIC_STRBUF_INITIALIZER; + + + +/*****************************************************************************/ +/* Helper functions and macros */ +/*****************************************************************************/ + + + +/* Return the flags as a boolean value (0/1) */ +#define GET_CF() ((Regs.SR & CF) != 0) +#define GET_ZF() ((Regs.SR & ZF) != 0) +#define GET_IF() ((Regs.SR & IF) != 0) +#define GET_DF() ((Regs.SR & DF) != 0) +#define GET_BF() ((Regs.SR & BF) != 0) +#define GET_OF() ((Regs.SR & OF) != 0) +#define GET_SF() ((Regs.SR & SF) != 0) + +/* Set the flags. The parameter is a boolean flag that says if the flag should be + * set or reset. + */ +#define SET_CF(f) do { if (f) { Regs.SR |= CF; } else { Regs.SR &= ~CF; } } while (0) +#define SET_ZF(f) do { if (f) { Regs.SR |= ZF; } else { Regs.SR &= ~ZF; } } while (0) +#define SET_IF(f) do { if (f) { Regs.SR |= IF; } else { Regs.SR &= ~IF; } } while (0) +#define SET_DF(f) do { if (f) { Regs.SR |= DF; } else { Regs.SR &= ~DF; } } while (0) +#define SET_BF(f) do { if (f) { Regs.SR |= BF; } else { Regs.SR &= ~BF; } } while (0) +#define SET_OF(f) do { if (f) { Regs.SR |= OF; } else { Regs.SR &= ~OF; } } while (0) +#define SET_SF(f) do { if (f) { Regs.SR |= SF; } else { Regs.SR &= ~SF; } } while (0) + +/* Special test and set macros. The meaning of the parameter depends on the + * actual flag that should be set or reset. + */ +#define TEST_ZF(v) SET_ZF (((v) & 0xFF) == 0) +#define TEST_SF(v) SET_SF (((v) & 0x80) != 0) +#define TEST_CF(v) SET_CF (((v) & 0xFF00) != 0) + +/* Program counter halves */ +#define PCL (Regs.PC & 0xFF) +#define PCH ((Regs.PC >> 8) & 0xFF) + +/* Stack operations */ +#define PUSH(Val) MemWriteByte (StackPage + Regs.SP--, Val) +#define POP() MemReadByte (StackPage + ++Regs.SP) + +/* Test for page cross */ +#define PAGE_CROSS(addr,offs) ((((addr) & 0xFF) + offs) >= 0x100) + +/* #imm */ +#define AC_OP_IMM(op) \ + Cycles = 2; \ + Regs.AC = Regs.AC op MemReadByte (Regs.PC+1); \ + TEST_ZF (Regs.AC); \ + TEST_SF (Regs.AC); \ + Regs.PC += 2 + +/* zp */ +#define AC_OP_ZP(op) \ + Cycles = 3; \ + Regs.AC = Regs.AC op MemReadByte (MemReadByte (Regs.PC+1)); \ + TEST_ZF (Regs.AC); \ + TEST_SF (Regs.AC); \ + Regs.PC += 2 + +/* zp,x */ +#define AC_OP_ZPX(op) \ + unsigned char ZPAddr; \ + Cycles = 4; \ + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \ + Regs.AC = Regs.AC op MemReadByte (ZPAddr); \ + TEST_ZF (Regs.AC); \ + TEST_SF (Regs.AC); \ + Regs.PC += 2 + +/* zp,y */ +#define AC_OP_ZPY(op) \ + unsigned char ZPAddr; \ + Cycles = 4; \ + ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR; \ + Regs.AC = Regs.AC op MemReadByte (ZPAddr); \ + TEST_ZF (Regs.AC); \ + TEST_SF (Regs.AC); \ + Regs.PC += 2 + +/* abs */ +#define AC_OP_ABS(op) \ + unsigned Addr; \ + Cycles = 4; \ + Addr = MemReadWord (Regs.PC+1); \ + Regs.AC = Regs.AC op MemReadByte (Addr); \ + TEST_ZF (Regs.AC); \ + TEST_SF (Regs.AC); \ + Regs.PC += 3 + +/* abs,x */ +#define AC_OP_ABSX(op) \ + unsigned Addr; \ + Cycles = 4; \ + Addr = MemReadWord (Regs.PC+1); \ + if (PAGE_CROSS (Addr, Regs.XR)) { \ + ++Cycles; \ + } \ + Regs.AC = Regs.AC op MemReadByte (Addr + Regs.XR); \ + TEST_ZF (Regs.AC); \ + TEST_SF (Regs.AC); \ + Regs.PC += 3 + +/* abs,y */ +#define AC_OP_ABSY(op) \ + unsigned Addr; \ + Cycles = 4; \ + Addr = MemReadWord (Regs.PC+1); \ + if (PAGE_CROSS (Addr, Regs.YR)) { \ + ++Cycles; \ + } \ + Regs.AC = Regs.AC op MemReadByte (Addr + Regs.YR); \ + TEST_ZF (Regs.AC); \ + TEST_SF (Regs.AC); \ + Regs.PC += 3 + +/* (zp,x) */ +#define AC_OP_ZPXIND(op) \ + unsigned char ZPAddr; \ + unsigned Addr; \ + Cycles = 6; \ + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \ + Addr = MemReadZPWord (ZPAddr); \ + Regs.AC = Regs.AC op MemReadByte (Addr); \ + TEST_ZF (Regs.AC); \ + TEST_SF (Regs.AC); \ + Regs.PC += 2 + +/* (zp),y */ +#define AC_OP_ZPINDY(op) \ + unsigned char ZPAddr; \ + unsigned Addr; \ + Cycles = 5; \ + ZPAddr = MemReadByte (Regs.PC+1); \ + Addr = MemReadZPWord (ZPAddr) + Regs.YR; \ + Regs.AC = Regs.AC op MemReadByte (Addr); \ + TEST_ZF (Regs.AC); \ + TEST_SF (Regs.AC); \ + Regs.PC += 2 + +/* ADC */ +#define ADC(v) \ + do { \ + unsigned old = Regs.AC; \ + unsigned rhs = (v & 0xFF); \ + if (GET_DF ()) { \ + unsigned lo; \ + int res; \ + lo = (old & 0x0F) + (rhs & 0x0F) + GET_CF (); \ + if (lo >= 0x0A) { \ + lo = ((lo + 0x06) & 0x0F) + 0x10; \ + } \ + Regs.AC = (old & 0xF0) + (rhs & 0xF0) + lo; \ + res = (signed char)(old & 0xF0) + \ + (signed char)(rhs & 0xF0) + \ + (signed char)lo; \ + TEST_ZF (old + rhs + GET_CF ()); \ + TEST_SF (Regs.AC); \ + if (Regs.AC >= 0xA0) { \ + Regs.AC += 0x60; \ + } \ + TEST_CF (Regs.AC); \ + SET_OF ((res < -128) || (res > 127)); \ + } else { \ + Regs.AC += rhs + GET_CF (); \ + TEST_ZF (Regs.AC); \ + TEST_SF (Regs.AC); \ + TEST_CF (Regs.AC); \ + SET_OF (!((old ^ rhs) & 0x80) && \ + ((old ^ Regs.AC) & 0x80)); \ + Regs.AC &= 0xFF; \ + } \ + } while (0) + +/* branches */ +#define BRANCH(cond) \ + Cycles = 2; \ + if (cond) { \ + signed char Offs; \ + unsigned char OldPCH; \ + ++Cycles; \ + Offs = (signed char) MemReadByte (Regs.PC+1); \ + OldPCH = PCH; \ + Regs.PC += 2 + (int) Offs; \ + if (PCH != OldPCH) { \ + ++Cycles; \ + } \ + } else { \ + Regs.PC += 2; \ + } + +/* compares */ +#define CMP(v1,v2) \ + do { \ + unsigned Result = v1 - v2; \ + TEST_ZF (Result & 0xFF); \ + TEST_SF (Result); \ + SET_CF (Result <= 0xFF); \ + } while (0) + + +/* ROL */ +#define ROL(Val) \ + Val <<= 1; \ + if (GET_CF ()) { \ + Val |= 0x01; \ + } \ + TEST_ZF (Val); \ + TEST_SF (Val); \ + TEST_CF (Val) + +/* ROR */ +#define ROR(Val) \ + if (GET_CF ()) { \ + Val |= 0x100; \ + } \ + SET_CF (Val & 0x01); \ + Val >>= 1; \ + TEST_ZF (Val); \ + TEST_SF (Val) + +/* SBC */ +#define SBC(v) \ + do { \ + unsigned old = Regs.AC; \ + unsigned rhs = (v & 0xFF); \ + if (GET_DF ()) { \ + unsigned lo; \ + int res; \ + lo = (old & 0x0F) - (rhs & 0x0F) + GET_CF () - 1; \ + if (lo & 0x80) { \ + lo = ((lo - 0x06) & 0x0F) - 0x10; \ + } \ + Regs.AC = (old & 0xF0) - (rhs & 0xF0) + lo; \ + if (Regs.AC & 0x80) { \ + Regs.AC -= 0x60; \ + } \ + res = Regs.AC - rhs + (!GET_CF ()); \ + TEST_ZF (res); \ + TEST_SF (res); \ + SET_CF (res <= 0xFF); \ + SET_OF (((old^rhs) & (old^res) & 0x80)); \ + } else { \ + Regs.AC -= rhs - (!GET_CF ()); \ + TEST_ZF (Regs.AC); \ + TEST_SF (Regs.AC); \ + SET_CF (Regs.AC <= 0xFF); \ + SET_OF (((old^rhs) & (old^Regs.AC) & 0x80)); \ + Regs.AC &= 0xFF; \ + } \ + } while (0) + + +/*****************************************************************************/ +/* Helper functions */ +/*****************************************************************************/ + + + +static void OPC_Illegal (void) +{ + Warning ("Illegal opcode $%02X at address $%04X\n", MemReadByte (Regs.PC), Regs.PC); +} + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +static void OPC_6502_00 (void) +/* Opcode $00: BRK */ +{ + Cycles = 7; + Regs.PC += 2; + SET_BF (1); + PUSH (PCH); + PUSH (PCL); + PUSH (Regs.SR); + SET_IF (1); + Regs.PC = MemReadWord (0xFFFE); + CPUHalted = 1; +} + + + +static void OPC_6502_01 (void) +/* Opcode $01: ORA (ind,x) */ +{ + AC_OP_ZPXIND (|); +} + + + +static void OPC_6502_05 (void) +/* Opcode $05: ORA zp */ +{ + AC_OP_ZP (|); +} + + + +static void OPC_6502_06 (void) +/* Opcode $06: ASL zp */ +{ + unsigned char ZPAddr; + unsigned Val; + Cycles = 5; + ZPAddr = MemReadByte (Regs.PC+1); + Val = MemReadByte (ZPAddr) << 1; + MemWriteByte (ZPAddr, (unsigned char) Val); + TEST_ZF (Val & 0xFF); + TEST_SF (Val); + SET_CF (Val & 0x100); + Regs.PC += 2; +} + + + +static void OPC_6502_08 (void) +/* Opcode $08: PHP */ +{ + Cycles = 3; + PUSH (Regs.SR & ~BF); + Regs.PC += 1; +} + + + +static void OPC_6502_09 (void) +/* Opcode $09: ORA #imm */ +{ + AC_OP_IMM (|); +} + + + +static void OPC_6502_0A (void) +/* Opcode $0A: ASL a */ +{ + Cycles = 2; + Regs.AC <<= 1; + TEST_ZF (Regs.AC & 0xFF); + TEST_SF (Regs.AC); + SET_CF (Regs.AC & 0x100); + Regs.AC &= 0xFF; + Regs.PC += 1; +} + + + +static void OPC_6502_0D (void) +/* Opcode $0D: ORA abs */ +{ + AC_OP_ABS (|); +} + + + +static void OPC_6502_0E (void) +/* Opcode $0E: ALS abs */ +{ + unsigned Addr; + unsigned Val; + Cycles = 6; + Addr = MemReadWord (Regs.PC+1); + Val = MemReadByte (Addr) << 1; + MemWriteByte (Addr, (unsigned char) Val); + TEST_ZF (Val & 0xFF); + TEST_SF (Val); + SET_CF (Val & 0x100); + Regs.PC += 3; +} + + + +static void OPC_6502_10 (void) +/* Opcode $10: BPL */ +{ + BRANCH (!GET_SF ()); +} + + + +static void OPC_6502_11 (void) +/* Opcode $11: ORA (zp),y */ +{ + AC_OP_ZPINDY (|); +} + + + +static void OPC_6502_15 (void) +/* Opcode $15: ORA zp,x */ +{ + AC_OP_ZPX (|); +} + + + +static void OPC_6502_16 (void) +/* Opcode $16: ASL zp,x */ +{ + unsigned char ZPAddr; + unsigned Val; + Cycles = 6; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + Val = MemReadByte (ZPAddr) << 1; + MemWriteByte (ZPAddr, (unsigned char) Val); + TEST_ZF (Val & 0xFF); + TEST_SF (Val); + SET_CF (Val & 0x100); + Regs.PC += 2; +} + + + +static void OPC_6502_18 (void) +/* Opcode $18: CLC */ +{ + Cycles = 2; + SET_CF (0); + Regs.PC += 1; +} + + + +static void OPC_6502_19 (void) +/* Opcode $19: ORA abs,y */ +{ + AC_OP_ABSY (|); +} + + + +static void OPC_6502_1D (void) +/* Opcode $1D: ORA abs,x */ +{ + AC_OP_ABSX (|); +} + + + +static void OPC_6502_1E (void) +/* Opcode $1E: ASL abs,x */ +{ + unsigned Addr; + unsigned Val; + Cycles = 7; + Addr = MemReadWord (Regs.PC+1) + Regs.XR; + Val = MemReadByte (Addr) << 1; + MemWriteByte (Addr, (unsigned char) Val); + TEST_ZF (Val & 0xFF); + TEST_SF (Val); + SET_CF (Val & 0x100); + Regs.PC += 3; +} + + + +static void OPC_6502_20 (void) +/* Opcode $20: JSR */ +{ + unsigned Addr; + Cycles = 6; + Addr = MemReadWord (Regs.PC+1); + Regs.PC += 2; + PUSH (PCH); + PUSH (PCL); + Regs.PC = Addr; +} + + + +static void OPC_6502_21 (void) +/* Opcode $21: AND (zp,x) */ +{ + AC_OP_ZPXIND (&); +} + + + +static void OPC_6502_24 (void) +/* Opcode $24: BIT zp */ +{ + unsigned char ZPAddr; + unsigned char Val; + Cycles = 3; + ZPAddr = MemReadByte (Regs.PC+1); + Val = MemReadByte (ZPAddr); + SET_SF (Val & 0x80); + SET_OF (Val & 0x40); + SET_ZF ((Val & Regs.AC) == 0); + Regs.PC += 2; +} + + + +static void OPC_6502_25 (void) +/* Opcode $25: AND zp */ +{ + AC_OP_ZP (&); +} + + + +static void OPC_6502_26 (void) +/* Opcode $26: ROL zp */ +{ + unsigned char ZPAddr; + unsigned Val; + Cycles = 5; + ZPAddr = MemReadByte (Regs.PC+1); + Val = MemReadByte (ZPAddr); + ROL (Val); + MemWriteByte (ZPAddr, Val); + Regs.PC += 2; +} + + + +static void OPC_6502_28 (void) +/* Opcode $28: PLP */ +{ + Cycles = 4; + Regs.SR = (POP () & ~BF); + Regs.PC += 1; +} + + + +static void OPC_6502_29 (void) +/* Opcode $29: AND #imm */ +{ + AC_OP_IMM (&); +} + + + +static void OPC_6502_2A (void) +/* Opcode $2A: ROL a */ +{ + Cycles = 2; + ROL (Regs.AC); + Regs.AC &= 0xFF; + Regs.PC += 1; +} + + + +static void OPC_6502_2C (void) +/* Opcode $2C: BIT abs */ +{ + unsigned Addr; + unsigned char Val; + Cycles = 4; + Addr = MemReadByte (Regs.PC+1); + Val = MemReadByte (Addr); + SET_SF (Val & 0x80); + SET_OF (Val & 0x40); + SET_ZF ((Val & Regs.AC) == 0); + Regs.PC += 3; +} + + + +static void OPC_6502_2D (void) +/* Opcode $2D: AND abs */ +{ + AC_OP_ABS (&); +} + + + +static void OPC_6502_2E (void) +/* Opcode $2E: ROL abs */ +{ + unsigned Addr; + unsigned Val; + Cycles = 6; + Addr = MemReadWord (Regs.PC+1); + Val = MemReadByte (Addr); + ROL (Val); + MemWriteByte (Addr, Val); + Regs.PC += 3; +} + + + +static void OPC_6502_30 (void) +/* Opcode $30: BMI */ +{ + BRANCH (GET_SF ()); +} + + + +static void OPC_6502_31 (void) +/* Opcode $31: AND (zp),y */ +{ + AC_OP_ZPINDY (&); +} + + + +static void OPC_6502_35 (void) +/* Opcode $35: AND zp,x */ +{ + AC_OP_ZPX (&); +} + + + +static void OPC_6502_36 (void) +/* Opcode $36: ROL zp,x */ +{ + unsigned char ZPAddr; + unsigned Val; + Cycles = 6; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + Val = MemReadByte (ZPAddr); + ROL (Val); + MemWriteByte (ZPAddr, Val); + Regs.PC += 2; +} + + + +static void OPC_6502_38 (void) +/* Opcode $38: SEC */ +{ + Cycles = 2; + SET_CF (1); + Regs.PC += 1; +} + + + +static void OPC_6502_39 (void) +/* Opcode $39: AND abs,y */ +{ + AC_OP_ABSY (&); +} + + + +static void OPC_6502_3D (void) +/* Opcode $3D: AND abs,x */ +{ + AC_OP_ABSX (&); +} + + + +static void OPC_6502_3E (void) +/* Opcode $3E: ROL abs,x */ +{ + unsigned Addr; + unsigned Val; + Cycles = 7; + Addr = MemReadWord (Regs.PC+1) + Regs.XR; + Val = MemReadByte (Addr); + ROL (Val); + MemWriteByte (Addr, Val); + Regs.PC += 2; +} + + + +static void OPC_6502_40 (void) +/* Opcode $40: RTI */ +{ + Cycles = 6; + Regs.SR = POP (); + Regs.PC = POP (); /* PCL */ + Regs.PC |= (POP () << 8); /* PCH */ +} + + + +static void OPC_6502_41 (void) +/* Opcode $41: EOR (zp,x) */ +{ + AC_OP_ZPXIND (^); +} + + + +static void OPC_6502_45 (void) +/* Opcode $45: EOR zp */ +{ + AC_OP_ZP (^); +} + + + +static void OPC_6502_46 (void) +/* Opcode $46: LSR zp */ +{ + unsigned char ZPAddr; + unsigned char Val; + Cycles = 5; + ZPAddr = MemReadByte (Regs.PC+1); + Val = MemReadByte (ZPAddr); + SET_CF (Val & 0x01); + Val >>= 1; + MemWriteByte (ZPAddr, Val); + TEST_ZF (Val); + TEST_SF (Val); + Regs.PC += 2; +} + + + +static void OPC_6502_48 (void) +/* Opcode $48: PHA */ +{ + Cycles = 3; + PUSH (Regs.AC); + Regs.PC += 1; +} + + + +static void OPC_6502_49 (void) +/* Opcode $49: EOR #imm */ +{ + AC_OP_IMM (^); +} + + + +static void OPC_6502_4A (void) +/* Opcode $4A: LSR a */ +{ + Cycles = 2; + SET_CF (Regs.AC & 0x01); + Regs.AC >>= 1; + TEST_ZF (Regs.AC); + TEST_SF (Regs.AC); + Regs.PC += 1; +} + + + +static void OPC_6502_4C (void) +/* Opcode $4C: JMP abs */ +{ + Cycles = 3; + Regs.PC = MemReadWord (Regs.PC+1); +} + + + +static void OPC_6502_4D (void) +/* Opcode $4D: EOR abs */ +{ + AC_OP_ABS (^); +} + + + +static void OPC_6502_4E (void) +/* Opcode $4E: LSR abs */ +{ + unsigned Addr; + unsigned char Val; + Cycles = 6; + Addr = MemReadWord (Regs.PC+1); + Val = MemReadByte (Addr); + SET_CF (Val & 0x01); + Val >>= 1; + MemWriteByte (Addr, Val); + TEST_ZF (Val); + TEST_SF (Val); + Regs.PC += 3; +} + + + +static void OPC_6502_50 (void) +/* Opcode $50: BVC */ +{ + BRANCH (!GET_OF ()); +} + + + +static void OPC_6502_51 (void) +/* Opcode $51: EOR (zp),y */ +{ + AC_OP_ZPINDY (^); +} + + + +static void OPC_6502_55 (void) +/* Opcode $55: EOR zp,x */ +{ + AC_OP_ZPX (^); +} + + + +static void OPC_6502_56 (void) +/* Opcode $56: LSR zp,x */ +{ + unsigned char ZPAddr; + unsigned char Val; + Cycles = 6; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + Val = MemReadByte (ZPAddr); + SET_CF (Val & 0x01); + Val >>= 1; + MemWriteByte (ZPAddr, Val); + TEST_ZF (Val); + TEST_SF (Val); + Regs.PC += 2; +} + + + +static void OPC_6502_58 (void) +/* Opcode $58: CLI */ +{ + Cycles = 2; + SET_IF (0); + Regs.PC += 1; +} + + + +static void OPC_6502_59 (void) +/* Opcode $59: EOR abs,y */ +{ + AC_OP_ABSY (^); +} + + + +static void OPC_6502_5D (void) +/* Opcode $5D: EOR abs,x */ +{ + AC_OP_ABSX (^); +} + + + +static void OPC_6502_5E (void) +/* Opcode $5E: LSR abs,x */ +{ + unsigned Addr; + unsigned char Val; + Cycles = 7; + Addr = MemReadWord (Regs.PC+1) + Regs.XR; + Val = MemReadByte (Addr); + SET_CF (Val & 0x01); + Val >>= 1; + MemWriteByte (Addr, Val); + TEST_ZF (Val); + TEST_SF (Val); + Regs.PC += 3; +} + + + +static void OPC_6502_60 (void) +/* Opcode $60: RTS */ +{ + Cycles = 6; + Regs.PC = POP (); /* PCL */ + Regs.PC |= (POP () << 8); /* PCH */ + Regs.PC += 1; +} + + + +static void OPC_6502_61 (void) +/* Opcode $61: ADC (zp,x) */ +{ + unsigned char ZPAddr; + unsigned Addr; + Cycles = 6; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + Addr = MemReadZPWord (ZPAddr); + ADC (MemReadByte (Addr)); + Regs.PC += 2; +} + + + +static void OPC_6502_65 (void) +/* Opcode $65: ADC zp */ +{ + unsigned char ZPAddr; + Cycles = 3; + ZPAddr = MemReadByte (Regs.PC+1); + ADC (MemReadByte (ZPAddr)); + Regs.PC += 2; +} + + + +static void OPC_6502_66 (void) +/* Opcode $66: ROR zp */ +{ + unsigned char ZPAddr; + unsigned Val; + Cycles = 5; + ZPAddr = MemReadByte (Regs.PC+1); + Val = MemReadByte (ZPAddr); + ROR (Val); + MemWriteByte (ZPAddr, Val); + Regs.PC += 2; +} + + + +static void OPC_6502_68 (void) +/* Opcode $68: PLA */ +{ + Cycles = 4; + Regs.AC = POP (); + TEST_ZF (Regs.AC); + TEST_SF (Regs.AC); + Regs.PC += 1; +} + + + +static void OPC_6502_69 (void) +/* Opcode $69: ADC #imm */ +{ + Cycles = 2; + ADC (MemReadByte (Regs.PC+1)); + Regs.PC += 2; +} + + + +static void OPC_6502_6A (void) +/* Opcode $6A: ROR a */ +{ + Cycles = 2; + ROR (Regs.AC); + Regs.PC += 1; +} + + + +static void OPC_6502_6C (void) +/* Opcode $6C: JMP (ind) */ +{ + unsigned Addr; + Cycles = 5; + Addr = MemReadWord (Regs.PC+1); + if (CPU == CPU_6502) { + /* Emulate the 6502 bug */ + Regs.PC = MemReadByte (Addr); + Addr = (Addr & 0xFF00) | ((Addr + 1) & 0xFF); + Regs.PC |= (MemReadByte (Addr) << 8); + } else { + /* 65C02 and above have this bug fixed */ + Regs.PC = MemReadWord (Addr); + } +} + + + +static void OPC_6502_6D (void) +/* Opcode $6D: ADC abs */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + ADC (MemReadByte (Addr)); + Regs.PC += 3; +} + + + +static void OPC_6502_6E (void) +/* Opcode $6E: ROR abs */ +{ + unsigned Addr; + unsigned Val; + Cycles = 6; + Addr = MemReadWord (Regs.PC+1); + Val = MemReadByte (Addr); + ROR (Val); + MemWriteByte (Addr, Val); + Regs.PC += 3; +} + + + +static void OPC_6502_70 (void) +/* Opcode $70: BVS */ +{ + BRANCH (GET_OF ()); +} + + + +static void OPC_6502_71 (void) +/* Opcode $71: ADC (zp),y */ +{ + unsigned char ZPAddr; + unsigned Addr; + Cycles = 5; + ZPAddr = MemReadByte (Regs.PC+1); + Addr = MemReadZPWord (ZPAddr); + if (PAGE_CROSS (Addr, Regs.YR)) { + ++Cycles; + } + ADC (MemReadByte (Addr + Regs.YR)); + Regs.PC += 2; +} + + + +static void OPC_6502_75 (void) +/* Opcode $75: ADC zp,x */ +{ + unsigned char ZPAddr; + Cycles = 4; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + ADC (MemReadByte (ZPAddr)); + Regs.PC += 2; +} + + + +static void OPC_6502_76 (void) +/* Opcode $76: ROR zp,x */ +{ + unsigned char ZPAddr; + unsigned Val; + Cycles = 6; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + Val = MemReadByte (ZPAddr); + ROR (Val); + MemWriteByte (ZPAddr, Val); + Regs.PC += 2; +} + + + +static void OPC_6502_78 (void) +/* Opcode $78: SEI */ +{ + Cycles = 2; + SET_IF (1); + Regs.PC += 1; +} + + + +static void OPC_6502_79 (void) +/* Opcode $79: ADC abs,y */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + if (PAGE_CROSS (Addr, Regs.YR)) { + ++Cycles; + } + ADC (MemReadByte (Addr + Regs.YR)); + Regs.PC += 3; +} + + + +static void OPC_6502_7D (void) +/* Opcode $7D: ADC abs,x */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + if (PAGE_CROSS (Addr, Regs.XR)) { + ++Cycles; + } + ADC (MemReadByte (Addr + Regs.XR)); + Regs.PC += 3; +} + + + +static void OPC_6502_7E (void) +/* Opcode $7E: ROR abs,x */ +{ + unsigned Addr; + unsigned Val; + Cycles = 7; + Addr = MemReadByte (Regs.PC+1) + Regs.XR; + Val = MemReadByte (Addr); + ROR (Val); + MemWriteByte (Addr, Val); + Regs.PC += 3; +} + + + +static void OPC_6502_81 (void) +/* Opcode $81: STA (zp,x) */ +{ + unsigned char ZPAddr; + unsigned Addr; + Cycles = 6; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + Addr = MemReadZPWord (ZPAddr); + MemWriteByte (Addr, Regs.AC); + Regs.PC += 2; +} + + + +static void OPC_6502_84 (void) +/* Opcode $84: STY zp */ +{ + unsigned char ZPAddr; + Cycles = 3; + ZPAddr = MemReadByte (Regs.PC+1); + MemWriteByte (ZPAddr, Regs.YR); + Regs.PC += 2; +} + + + +static void OPC_6502_85 (void) +/* Opcode $85: STA zp */ +{ + unsigned char ZPAddr; + Cycles = 3; + ZPAddr = MemReadByte (Regs.PC+1); + MemWriteByte (ZPAddr, Regs.AC); + Regs.PC += 2; +} + + + +static void OPC_6502_86 (void) +/* Opcode $86: STX zp */ +{ + unsigned char ZPAddr; + Cycles = 3; + ZPAddr = MemReadByte (Regs.PC+1); + MemWriteByte (ZPAddr, Regs.XR); + Regs.PC += 2; +} + + + +static void OPC_6502_88 (void) +/* Opcode $88: DEY */ +{ + Cycles = 2; + Regs.YR = (Regs.YR - 1) & 0xFF; + TEST_ZF (Regs.YR); + TEST_SF (Regs.YR); + Regs.PC += 1; +} + + + +static void OPC_6502_8A (void) +/* Opcode $8A: TXA */ +{ + Cycles = 2; + Regs.AC = Regs.XR; + TEST_ZF (Regs.AC); + TEST_SF (Regs.AC); + Regs.PC += 1; +} + + + +static void OPC_6502_8C (void) +/* Opcode $8C: STY abs */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + MemWriteByte (Addr, Regs.YR); + Regs.PC += 3; +} + + + +static void OPC_6502_8D (void) +/* Opcode $8D: STA abs */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + MemWriteByte (Addr, Regs.AC); + Regs.PC += 3; +} + + + +static void OPC_6502_8E (void) +/* Opcode $8E: STX abs */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + MemWriteByte (Addr, Regs.XR); + Regs.PC += 3; +} + + + +static void OPC_6502_90 (void) +/* Opcode $90: BCC */ +{ + BRANCH (!GET_CF ()); +} + + + +static void OPC_6502_91 (void) +/* Opcode $91: sta (zp),y */ +{ + unsigned char ZPAddr; + unsigned Addr; + Cycles = 6; + ZPAddr = MemReadByte (Regs.PC+1); + Addr = MemReadZPWord (ZPAddr) + Regs.YR; + MemWriteByte (Addr, Regs.AC); + Regs.PC += 2; +} + + + +static void OPC_6502_94 (void) +/* Opcode $94: STY zp,x */ +{ + unsigned char ZPAddr; + Cycles = 4; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + MemWriteByte (ZPAddr, Regs.YR); + Regs.PC += 2; +} + + + +static void OPC_6502_95 (void) +/* Opcode $95: STA zp,x */ +{ + unsigned char ZPAddr; + Cycles = 4; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + MemWriteByte (ZPAddr, Regs.AC); + Regs.PC += 2; +} + + + +static void OPC_6502_96 (void) +/* Opcode $96: stx zp,y */ +{ + unsigned char ZPAddr; + Cycles = 4; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR; + MemWriteByte (ZPAddr, Regs.XR); + Regs.PC += 2; +} + + + +static void OPC_6502_98 (void) +/* Opcode $98: TYA */ +{ + Cycles = 2; + Regs.AC = Regs.YR; + TEST_ZF (Regs.AC); + TEST_SF (Regs.AC); + Regs.PC += 1; +} + + + +static void OPC_6502_99 (void) +/* Opcode $99: STA abs,y */ +{ + unsigned Addr; + Cycles = 5; + Addr = MemReadWord (Regs.PC+1) + Regs.YR; + MemWriteByte (Addr, Regs.AC); + Regs.PC += 3; +} + + + +static void OPC_6502_9A (void) +/* Opcode $9A: TXS */ +{ + Cycles = 2; + Regs.SP = Regs.XR; + Regs.PC += 1; +} + + + +static void OPC_6502_9D (void) +/* Opcode $9D: STA abs,x */ +{ + unsigned Addr; + Cycles = 5; + Addr = MemReadWord (Regs.PC+1) + Regs.XR; + MemWriteByte (Addr, Regs.AC); + Regs.PC += 3; +} + + + +static void OPC_6502_A0 (void) +/* Opcode $A0: LDY #imm */ +{ + Cycles = 2; + Regs.YR = MemReadByte (Regs.PC+1); + TEST_ZF (Regs.YR); + TEST_SF (Regs.YR); + Regs.PC += 2; +} + + + +static void OPC_6502_A1 (void) +/* Opcode $A1: LDA (zp,x) */ +{ + unsigned char ZPAddr; + unsigned Addr; + Cycles = 6; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + Addr = MemReadZPWord (ZPAddr); + Regs.AC = MemReadByte (Addr); + TEST_ZF (Regs.AC); + TEST_SF (Regs.AC); + Regs.PC += 2; +} + + + +static void OPC_6502_A2 (void) +/* Opcode $A2: LDX #imm */ +{ + Cycles = 2; + Regs.XR = MemReadByte (Regs.PC+1); + TEST_ZF (Regs.XR); + TEST_SF (Regs.XR); + Regs.PC += 2; +} + + + +static void OPC_6502_A4 (void) +/* Opcode $A4: LDY zp */ +{ + unsigned char ZPAddr; + Cycles = 3; + ZPAddr = MemReadByte (Regs.PC+1); + Regs.YR = MemReadByte (ZPAddr); + TEST_ZF (Regs.YR); + TEST_SF (Regs.YR); + Regs.PC += 2; +} + + + +static void OPC_6502_A5 (void) +/* Opcode $A5: LDA zp */ +{ + unsigned char ZPAddr; + Cycles = 3; + ZPAddr = MemReadByte (Regs.PC+1); + Regs.AC = MemReadByte (ZPAddr); + TEST_ZF (Regs.AC); + TEST_SF (Regs.AC); + Regs.PC += 2; +} + + + +static void OPC_6502_A6 (void) +/* Opcode $A6: LDX zp */ +{ + unsigned char ZPAddr; + Cycles = 3; + ZPAddr = MemReadByte (Regs.PC+1); + Regs.XR = MemReadByte (ZPAddr); + TEST_ZF (Regs.XR); + TEST_SF (Regs.XR); + Regs.PC += 2; +} + + + +static void OPC_6502_A8 (void) +/* Opcode $A8: TAY */ +{ + Cycles = 2; + Regs.YR = Regs.AC; + TEST_ZF (Regs.YR); + TEST_SF (Regs.YR); + Regs.PC += 1; +} + + + +static void OPC_6502_A9 (void) +/* Opcode $A9: LDA #imm */ +{ + Cycles = 2; + Regs.AC = MemReadByte (Regs.PC+1); + TEST_ZF (Regs.AC); + TEST_SF (Regs.AC); + Regs.PC += 2; +} + + + +static void OPC_6502_AA (void) +/* Opcode $AA: TAX */ +{ + Cycles = 2; + Regs.XR = Regs.AC; + TEST_ZF (Regs.XR); + TEST_SF (Regs.XR); + Regs.PC += 1; +} + + + +static void OPC_6502_AC (void) +/* Opcode $Regs.AC: LDY abs */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + Regs.YR = MemReadByte (Addr); + TEST_ZF (Regs.YR); + TEST_SF (Regs.YR); + Regs.PC += 3; +} + + + +static void OPC_6502_AD (void) +/* Opcode $AD: LDA abs */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + Regs.AC = MemReadByte (Addr); + TEST_ZF (Regs.AC); + TEST_SF (Regs.AC); + Regs.PC += 3; +} + + + +static void OPC_6502_AE (void) +/* Opcode $AE: LDX abs */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + Regs.XR = MemReadByte (Addr); + TEST_ZF (Regs.XR); + TEST_SF (Regs.XR); + Regs.PC += 3; +} + + + +static void OPC_6502_B0 (void) +/* Opcode $B0: BCS */ +{ + BRANCH (GET_CF ()); +} + + + +static void OPC_6502_B1 (void) +/* Opcode $B1: LDA (zp),y */ +{ + unsigned char ZPAddr; + unsigned Addr; + Cycles = 5; + ZPAddr = MemReadByte (Regs.PC+1); + Addr = MemReadZPWord (ZPAddr); + if (PAGE_CROSS (Addr, Regs.YR)) { + ++Cycles; + } + Regs.AC = MemReadByte (Addr + Regs.YR); + TEST_ZF (Regs.AC); + TEST_SF (Regs.AC); + Regs.PC += 2; +} + + + +static void OPC_6502_B4 (void) +/* Opcode $B4: LDY zp,x */ +{ + unsigned char ZPAddr; + Cycles = 4; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + Regs.YR = MemReadByte (ZPAddr); + TEST_ZF (Regs.YR); + TEST_SF (Regs.YR); + Regs.PC += 2; +} + + + +static void OPC_6502_B5 (void) +/* Opcode $B5: LDA zp,x */ +{ + unsigned char ZPAddr; + Cycles = 4; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + Regs.AC = MemReadByte (ZPAddr); + TEST_ZF (Regs.AC); + TEST_SF (Regs.AC); + Regs.PC += 2; +} + + + +static void OPC_6502_B6 (void) +/* Opcode $B6: LDX zp,y */ +{ + unsigned char ZPAddr; + Cycles = 4; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR; + Regs.XR = MemReadByte (ZPAddr); + TEST_ZF (Regs.XR); + TEST_SF (Regs.XR); + Regs.PC += 2; +} + + + +static void OPC_6502_B8 (void) +/* Opcode $B8: CLV */ +{ + Cycles = 2; + SET_OF (0); + Regs.PC += 1; +} + + + +static void OPC_6502_B9 (void) +/* Opcode $B9: LDA abs,y */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + if (PAGE_CROSS (Addr, Regs.YR)) { + ++Cycles; + } + Regs.AC = MemReadByte (Addr + Regs.YR); + TEST_ZF (Regs.AC); + TEST_SF (Regs.AC); + Regs.PC += 3; +} + + + +static void OPC_6502_BA (void) +/* Opcode $BA: TSX */ +{ + Cycles = 2; + Regs.XR = Regs.SP; + TEST_ZF (Regs.XR); + TEST_SF (Regs.XR); + Regs.PC += 1; +} + + + +static void OPC_6502_BC (void) +/* Opcode $BC: LDY abs,x */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + if (PAGE_CROSS (Addr, Regs.XR)) { + ++Cycles; + } + Regs.YR = MemReadByte (Addr + Regs.XR); + TEST_ZF (Regs.YR); + TEST_SF (Regs.YR); + Regs.PC += 3; +} + + + +static void OPC_6502_BD (void) +/* Opcode $BD: LDA abs,x */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + if (PAGE_CROSS (Addr, Regs.XR)) { + ++Cycles; + } + Regs.AC = MemReadByte (Addr + Regs.XR); + TEST_ZF (Regs.AC); + TEST_SF (Regs.AC); + Regs.PC += 3; +} + + + +static void OPC_6502_BE (void) +/* Opcode $BE: LDX abs,y */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + if (PAGE_CROSS (Addr, Regs.YR)) { + ++Cycles; + } + Regs.XR = MemReadByte (Addr + Regs.YR); + TEST_ZF (Regs.XR); + TEST_SF (Regs.XR); + Regs.PC += 3; +} + + + +static void OPC_6502_C0 (void) +/* Opcode $C0: CPY #imm */ +{ + Cycles = 2; + CMP (Regs.YR, MemReadByte (Regs.PC+1)); + Regs.PC += 2; +} + + + +static void OPC_6502_C1 (void) +/* Opcode $C1: CMP (zp,x) */ +{ + unsigned char ZPAddr; + unsigned Addr; + Cycles = 6; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + Addr = MemReadZPWord (ZPAddr); + CMP (Regs.AC, MemReadByte (Addr)); + Regs.PC += 2; +} + + + +static void OPC_6502_C4 (void) +/* Opcode $C4: CPY zp */ +{ + unsigned char ZPAddr; + Cycles = 3; + ZPAddr = MemReadByte (Regs.PC+1); + CMP (Regs.YR, MemReadByte (ZPAddr)); + Regs.PC += 2; +} + + + +static void OPC_6502_C5 (void) +/* Opcode $C5: CMP zp */ +{ + unsigned char ZPAddr; + Cycles = 3; + ZPAddr = MemReadByte (Regs.PC+1); + CMP (Regs.AC, MemReadByte (ZPAddr)); + Regs.PC += 2; +} + + + +static void OPC_6502_C6 (void) +/* Opcode $C6: DEC zp */ +{ + unsigned char ZPAddr; + unsigned char Val; + Cycles = 5; + ZPAddr = MemReadByte (Regs.PC+1); + Val = MemReadByte (ZPAddr) - 1; + MemWriteByte (ZPAddr, Val); + TEST_ZF (Val); + TEST_SF (Val); + Regs.PC += 2; +} + + + +static void OPC_6502_C8 (void) +/* Opcode $C8: INY */ +{ + Cycles = 2; + Regs.YR = (Regs.YR + 1) & 0xFF; + TEST_ZF (Regs.YR); + TEST_SF (Regs.YR); + Regs.PC += 1; +} + + + +static void OPC_6502_C9 (void) +/* Opcode $C9: CMP #imm */ +{ + Cycles = 2; + CMP (Regs.AC, MemReadByte (Regs.PC+1)); + Regs.PC += 2; +} + + + +static void OPC_6502_CA (void) +/* Opcode $CA: DEX */ +{ + Cycles = 2; + Regs.XR = (Regs.XR - 1) & 0xFF; + TEST_ZF (Regs.XR); + TEST_SF (Regs.XR); + Regs.PC += 1; +} + + + +static void OPC_6502_CC (void) +/* Opcode $CC: CPY abs */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + CMP (Regs.YR, MemReadByte (Addr)); + Regs.PC += 3; +} + + + +static void OPC_6502_CD (void) +/* Opcode $CD: CMP abs */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + CMP (Regs.AC, MemReadByte (Addr)); + Regs.PC += 3; +} + + + +static void OPC_6502_CE (void) +/* Opcode $CE: DEC abs */ +{ + unsigned Addr; + unsigned char Val; + Cycles = 6; + Addr = MemReadWord (Regs.PC+1); + Val = MemReadByte (Addr) - 1; + MemWriteByte (Addr, Val); + TEST_ZF (Val); + TEST_SF (Val); + Regs.PC += 3; +} + + + +static void OPC_6502_D0 (void) +/* Opcode $D0: BNE */ +{ + BRANCH (!GET_ZF ()); +} + + + +static void OPC_6502_D1 (void) +/* Opcode $D1: CMP (zp),y */ +{ + unsigned ZPAddr; + unsigned Addr; + Cycles = 5; + ZPAddr = MemReadByte (Regs.PC+1); + Addr = MemReadWord (ZPAddr); + if (PAGE_CROSS (Addr, Regs.YR)) { + ++Cycles; + } + CMP (Regs.AC, MemReadByte (Addr + Regs.YR)); + Regs.PC += 2; +} + + + +static void OPC_6502_D5 (void) +/* Opcode $D5: CMP zp,x */ +{ + unsigned char ZPAddr; + Cycles = 4; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + CMP (Regs.AC, MemReadByte (ZPAddr)); + Regs.PC += 2; +} + + + +static void OPC_6502_D6 (void) +/* Opcode $D6: DEC zp,x */ +{ + unsigned char ZPAddr; + unsigned char Val; + Cycles = 6; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + Val = MemReadByte (ZPAddr) - 1; + MemWriteByte (ZPAddr, Val); + TEST_ZF (Val); + TEST_SF (Val); + Regs.PC += 2; +} + + + +static void OPC_6502_D8 (void) +/* Opcode $D8: CLD */ +{ + Cycles = 2; + SET_DF (0); + Regs.PC += 1; +} + + + +static void OPC_6502_D9 (void) +/* Opcode $D9: CMP abs,y */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + if (PAGE_CROSS (Addr, Regs.YR)) { + ++Cycles; + } + CMP (Regs.AC, MemReadByte (Addr + Regs.YR)); + Regs.PC += 3; +} + + + +static void OPC_6502_DD (void) +/* Opcode $DD: CMP abs,x */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + if (PAGE_CROSS (Addr, Regs.XR)) { + ++Cycles; + } + CMP (Regs.AC, MemReadByte (Addr + Regs.XR)); + Regs.PC += 3; +} + + + +static void OPC_6502_DE (void) +/* Opcode $DE: DEC abs,x */ +{ + unsigned Addr; + unsigned char Val; + Cycles = 7; + Addr = MemReadWord (Regs.PC+1) + Regs.XR; + Val = MemReadByte (Addr) - 1; + MemWriteByte (Addr, Val); + TEST_ZF (Val); + TEST_SF (Val); + Regs.PC += 3; +} + + + +static void OPC_6502_E0 (void) +/* Opcode $E0: CPX #imm */ +{ + Cycles = 2; + CMP (Regs.XR, MemReadByte (Regs.PC+1)); + Regs.PC += 2; +} + + + +static void OPC_6502_E1 (void) +/* Opcode $E1: SBC (zp,x) */ +{ + unsigned char ZPAddr; + unsigned Addr; + Cycles = 6; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + Addr = MemReadZPWord (ZPAddr); + SBC (MemReadByte (Addr)); + Regs.PC += 2; +} + + + +static void OPC_6502_E4 (void) +/* Opcode $E4: CPX zp */ +{ + unsigned char ZPAddr; + Cycles = 3; + ZPAddr = MemReadByte (Regs.PC+1); + CMP (Regs.XR, MemReadByte (ZPAddr)); + Regs.PC += 2; +} + + + +static void OPC_6502_E5 (void) +/* Opcode $E5: SBC zp */ +{ + unsigned char ZPAddr; + Cycles = 3; + ZPAddr = MemReadByte (Regs.PC+1); + SBC (MemReadByte (ZPAddr)); + Regs.PC += 2; +} + + + +static void OPC_6502_E6 (void) +/* Opcode $E6: INC zp */ +{ + unsigned char ZPAddr; + unsigned char Val; + Cycles = 5; + ZPAddr = MemReadByte (Regs.PC+1); + Val = MemReadByte (ZPAddr) + 1; + MemWriteByte (ZPAddr, Val); + TEST_ZF (Val); + TEST_SF (Val); + Regs.PC += 2; +} + + + +static void OPC_6502_E8 (void) +/* Opcode $E8: INX */ +{ + Cycles = 2; + Regs.XR = (Regs.XR + 1) & 0xFF; + TEST_ZF (Regs.XR); + TEST_SF (Regs.XR); + Regs.PC += 1; +} + + + +static void OPC_6502_E9 (void) +/* Opcode $E9: SBC #imm */ +{ + Cycles = 2; + SBC (MemReadByte (Regs.PC+1)); + Regs.PC += 2; +} + + + +static void OPC_6502_EA (void) +/* Opcode $EA: NOP */ +{ + /* This one is easy... */ + Cycles = 2; + Regs.PC += 1; +} + + + +static void OPC_6502_EC (void) +/* Opcode $EC: CPX abs */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + CMP (Regs.XR, MemReadByte (Addr)); + Regs.PC += 3; +} + + + +static void OPC_6502_ED (void) +/* Opcode $ED: SBC abs */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + SBC (MemReadByte (Addr)); + Regs.PC += 3; +} + + + +static void OPC_6502_EE (void) +/* Opcode $EE: INC abs */ +{ + unsigned Addr; + unsigned char Val; + Cycles = 6; + Addr = MemReadWord (Regs.PC+1); + Val = MemReadByte (Addr) + 1; + MemWriteByte (Addr, Val); + TEST_ZF (Val); + TEST_SF (Val); + Regs.PC += 3; +} + + + +static void OPC_6502_F0 (void) +/* Opcode $F0: BEQ */ +{ + BRANCH (GET_ZF ()); +} + + + +static void OPC_6502_F1 (void) +/* Opcode $F1: SBC (zp),y */ +{ + unsigned char ZPAddr; + unsigned Addr; + Cycles = 5; + ZPAddr = MemReadByte (Regs.PC+1); + Addr = MemReadZPWord (ZPAddr); + if (PAGE_CROSS (Addr, Regs.YR)) { + ++Cycles; + } + SBC (MemReadByte (Addr + Regs.YR)); + Regs.PC += 2; +} + + + +static void OPC_6502_F5 (void) +/* Opcode $F5: SBC zp,x */ +{ + unsigned char ZPAddr; + Cycles = 4; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + SBC (MemReadByte (ZPAddr)); + Regs.PC += 2; +} + + + +static void OPC_6502_F6 (void) +/* Opcode $F6: INC zp,x */ +{ + unsigned char ZPAddr; + unsigned char Val; + Cycles = 6; + ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; + Val = MemReadByte (ZPAddr) + 1; + MemWriteByte (ZPAddr, Val); + TEST_ZF (Val); + TEST_SF (Val); + Regs.PC += 2; +} + + + +static void OPC_6502_F8 (void) +/* Opcode $F8: SED */ +{ + SET_DF (1); +} + + + +static void OPC_6502_F9 (void) +/* Opcode $F9: SBC abs,y */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + if (PAGE_CROSS (Addr, Regs.YR)) { + ++Cycles; + } + SBC (MemReadByte (Addr + Regs.YR)); + Regs.PC += 3; +} + + + +static void OPC_6502_FD (void) +/* Opcode $FD: SBC abs,x */ +{ + unsigned Addr; + Cycles = 4; + Addr = MemReadWord (Regs.PC+1); + if (PAGE_CROSS (Addr, Regs.XR)) { + ++Cycles; + } + SBC (MemReadByte (Addr + Regs.XR)); + Regs.PC += 3; +} + + + +static void OPC_6502_FE (void) +/* Opcode $FE: INC abs,x */ +{ + unsigned Addr; + unsigned char Val; + Cycles = 7; + Addr = MemReadWord (Regs.PC+1) + Regs.XR; + Val = MemReadByte (Addr) + 1; + MemWriteByte (Addr, Val); + TEST_ZF (Val); + TEST_SF (Val); + Regs.PC += 3; +} + + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* Opcode handler table */ +typedef void (*OPCFunc) (void); +static OPCFunc OPCTable[256] = { + OPC_6502_00, + OPC_6502_01, + OPC_Illegal, + OPC_Illegal, + OPC_Illegal, + OPC_6502_05, + OPC_6502_06, + OPC_Illegal, + OPC_6502_08, + OPC_6502_09, + OPC_6502_0A, + OPC_Illegal, + OPC_Illegal, + OPC_6502_0D, + OPC_6502_0E, + OPC_Illegal, + OPC_6502_10, + OPC_6502_11, + OPC_Illegal, + OPC_Illegal, + OPC_Illegal, + OPC_6502_15, + OPC_6502_16, + OPC_Illegal, + OPC_6502_18, + OPC_6502_19, + OPC_Illegal, + OPC_Illegal, + OPC_Illegal, + OPC_6502_1D, + OPC_6502_1E, + OPC_Illegal, + OPC_6502_20, + OPC_6502_21, + OPC_Illegal, + OPC_Illegal, + OPC_6502_24, + OPC_6502_25, + OPC_6502_26, + OPC_Illegal, + OPC_6502_28, + OPC_6502_29, + OPC_6502_2A, + OPC_Illegal, + OPC_6502_2C, + OPC_6502_2D, + OPC_6502_2E, + OPC_Illegal, + OPC_6502_30, + OPC_6502_31, + OPC_Illegal, + OPC_Illegal, + OPC_Illegal, + OPC_6502_35, + OPC_6502_36, + OPC_Illegal, + OPC_6502_38, + OPC_6502_39, + OPC_Illegal, + OPC_Illegal, + OPC_Illegal, + OPC_6502_3D, + OPC_6502_3E, + OPC_Illegal, + OPC_6502_40, + OPC_6502_41, + OPC_Illegal, + OPC_Illegal, + OPC_Illegal, + OPC_6502_45, + OPC_6502_46, + OPC_Illegal, + OPC_6502_48, + OPC_6502_49, + OPC_6502_4A, + OPC_Illegal, + OPC_6502_4C, + OPC_6502_4D, + OPC_6502_4E, + OPC_Illegal, + OPC_6502_50, + OPC_6502_51, + OPC_Illegal, + OPC_Illegal, + OPC_Illegal, + OPC_6502_55, + OPC_6502_56, + OPC_Illegal, + OPC_6502_58, + OPC_6502_59, + OPC_Illegal, + OPC_Illegal, + OPC_Illegal, + OPC_6502_5D, + OPC_6502_5E, + OPC_Illegal, + OPC_6502_60, + OPC_6502_61, + OPC_Illegal, + OPC_Illegal, + OPC_Illegal, + OPC_6502_65, + OPC_6502_66, + OPC_Illegal, + OPC_6502_68, + OPC_6502_69, + OPC_6502_6A, + OPC_Illegal, + OPC_6502_6C, + OPC_6502_6D, + OPC_6502_6E, + OPC_Illegal, + OPC_6502_70, + OPC_6502_71, + OPC_Illegal, + OPC_Illegal, + OPC_Illegal, + OPC_6502_75, + OPC_6502_76, + OPC_Illegal, + OPC_6502_78, + OPC_6502_79, + OPC_Illegal, + OPC_Illegal, + OPC_Illegal, + OPC_6502_7D, + OPC_6502_7E, + OPC_Illegal, + OPC_Illegal, + OPC_6502_81, + OPC_Illegal, + OPC_Illegal, + OPC_6502_84, + OPC_6502_85, + OPC_6502_86, + OPC_Illegal, + OPC_6502_88, + OPC_Illegal, + OPC_6502_8A, + OPC_Illegal, + OPC_6502_8C, + OPC_6502_8D, + OPC_6502_8E, + OPC_Illegal, + OPC_6502_90, + OPC_6502_91, + OPC_Illegal, + OPC_Illegal, + OPC_6502_94, + OPC_6502_95, + OPC_6502_96, + OPC_Illegal, + OPC_6502_98, + OPC_6502_99, + OPC_6502_9A, + OPC_Illegal, + OPC_Illegal, + OPC_6502_9D, + OPC_Illegal, + OPC_Illegal, + OPC_6502_A0, + OPC_6502_A1, + OPC_6502_A2, + OPC_Illegal, + OPC_6502_A4, + OPC_6502_A5, + OPC_6502_A6, + OPC_Illegal, + OPC_6502_A8, + OPC_6502_A9, + OPC_6502_AA, + OPC_Illegal, + OPC_6502_AC, + OPC_6502_AD, + OPC_6502_AE, + OPC_Illegal, + OPC_6502_B0, + OPC_6502_B1, + OPC_Illegal, + OPC_Illegal, + OPC_6502_B4, + OPC_6502_B5, + OPC_6502_B6, + OPC_Illegal, + OPC_6502_B8, + OPC_6502_B9, + OPC_6502_BA, + OPC_Illegal, + OPC_6502_BC, + OPC_6502_BD, + OPC_6502_BE, + OPC_Illegal, + OPC_6502_C0, + OPC_6502_C1, + OPC_Illegal, + OPC_Illegal, + OPC_6502_C4, + OPC_6502_C5, + OPC_6502_C6, + OPC_Illegal, + OPC_6502_C8, + OPC_6502_C9, + OPC_6502_CA, + OPC_Illegal, + OPC_6502_CC, + OPC_6502_CD, + OPC_6502_CE, + OPC_Illegal, + OPC_6502_D0, + OPC_6502_D1, + OPC_Illegal, + OPC_Illegal, + OPC_Illegal, + OPC_6502_D5, + OPC_6502_D6, + OPC_Illegal, + OPC_6502_D8, + OPC_6502_D9, + OPC_Illegal, + OPC_Illegal, + OPC_Illegal, + OPC_6502_DD, + OPC_6502_DE, + OPC_Illegal, + OPC_6502_E0, + OPC_6502_E1, + OPC_Illegal, + OPC_Illegal, + OPC_6502_E4, + OPC_6502_E5, + OPC_6502_E6, + OPC_Illegal, + OPC_6502_E8, + OPC_6502_E9, + OPC_6502_EA, + OPC_Illegal, + OPC_6502_EC, + OPC_6502_ED, + OPC_6502_EE, + OPC_Illegal, + OPC_6502_F0, + OPC_6502_F1, + OPC_Illegal, + OPC_Illegal, + OPC_Illegal, + OPC_6502_F5, + OPC_6502_F6, + OPC_Illegal, + OPC_6502_F8, + OPC_6502_F9, + OPC_Illegal, + OPC_Illegal, + OPC_Illegal, + OPC_6502_FD, + OPC_6502_FE, + OPC_Illegal, +}; + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +void CPUInit (void) +/* Initialize the CPU */ +{ + RESET (); +} + + + +void IRQRequest (void) +/* Generate an IRQ */ +{ + HaveIRQRequest = 1; +} + + + +void NMIRequest (void) +/* Generate an NMI */ +{ + HaveNMIRequest = 1; +} + + + +void RESET (void) +/* Generate a CPU RESET */ +{ + CPUHalted = HaveIRQRequest = HaveNMIRequest = 0; + Regs.PC = MemReadWord (0xFFFC); +} + + + +void Break (const char* Format, ...) +/* Stop running and display the given message */ +{ + va_list ap; + va_start (ap, Format); + SB_VPrintf (&BreakMsg, Format, ap); + va_end (ap); +} + + + +void CPURun (void) +/* Run one CPU instruction */ +{ + /* If the CPU is halted, do nothing */ + if (CPUHalted) { + return; + } + + /* If we have an NMI request, handle it */ + if (HaveNMIRequest) { + + HaveNMIRequest = 0; + PUSH (PCH); + PUSH (PCL); + PUSH (Regs.SR); + SET_IF (1); + Regs.PC = MemReadWord (0xFFFA); + Cycles = 7; + + } else if (HaveIRQRequest && GET_IF () == 0) { + + HaveIRQRequest = 0; + PUSH (PCH); + PUSH (PCL); + PUSH (Regs.SR); + SET_IF (1); + Regs.PC = MemReadWord (0xFFFE); + Cycles = 7; + + } else { + + /* Normal instruction - read the next opcode */ + unsigned char OPC = MemReadByte (Regs.PC); + + /* Execute it */ + OPCTable[OPC] (); + + } + + /* Count cycles */ + TotalCycles += Cycles; + + if (SB_GetLen (&BreakMsg) > 0) { + printf ("%.*s\n", SB_GetLen (&BreakMsg), SB_GetConstBuf (&BreakMsg)); + SB_Clear (&BreakMsg); + } +} + + + +#if 0 + if ((++I & 0xFF) == 0) + printf ("%9lu %06X %02X A=%02X X=%02X Y=%02X %c%c%c%c%c%c%c\n", + TotalCycles, Regs.PC, OPC, Regs.AC, Regs.XR, Regs.YR, + GET_SF()? 'S' : '-', + GET_ZF()? 'Z' : '-', + GET_CF()? 'C' : '-', + GET_IF()? 'I' : '-', + GET_BF()? 'B' : '-', + GET_DF()? 'D' : '-', + GET_OF()? 'V' : '-'); +#endif + + diff --git a/src/sim65/cpu-6502.h b/src/sim65/cpu-6502.h new file mode 100644 index 000000000..b88617143 --- /dev/null +++ b/src/sim65/cpu-6502.h @@ -0,0 +1,88 @@ +/*****************************************************************************/ +/* */ +/* cpucore.h */ +/* */ +/* CPU core for the 6502 simulator */ +/* */ +/* */ +/* */ +/* (C) 2002-2003 Ullrich von Bassewitz */ +/* Römerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#ifndef CPUCORE_H +#define CPUCORE_H + + + +/* sim65 */ +#include "cpuregs.h" + + + +/*****************************************************************************/ +/* Data */ +/*****************************************************************************/ + + + +/* Registers */ +extern CPURegs Regs; + + + +/*****************************************************************************/ +/* Code */ +/*****************************************************************************/ + + + +void CPUInit (void); +/* Initialize the CPU */ + +void RESET (void); +/* Generate a CPU RESET */ + +void IRQRequest (void); +/* Generate an IRQ */ + +void NMIRequest (void); +/* Generate an NMI */ + +void Break (const char* Format, ...); +/* Stop running and display the given message */ + +void CPURun (void); +/* Run one CPU instruction */ + + + +/* End of cpucore.h */ + +#endif + + + diff --git a/src/sim65/cpucore.c b/src/sim65/cpucore.c index 39929634d..e4e189f6d 100644 --- a/src/sim65/cpucore.c +++ b/src/sim65/cpucore.c @@ -1,8 +1,8 @@ /*****************************************************************************/ /* */ -/* cpucore.c */ +/* cpucore.c */ /* */ -/* CPU core for the 6502 simulator */ +/* CPU definition for the simulator */ /* */ /* */ /* */ @@ -33,2560 +33,54 @@ -#include -#include -#include +#include /* common */ -#include "abend.h" -#include "attrib.h" -#include "print.h" -#include "strbuf.h" +#include "xmalloc.h" /* sim65 */ -#include "cpuregs.h" -#include "cputype.h" -#include "error.h" -#include "global.h" -#include "memory.h" -#include "cpucore.h" - - - -/*****************************************************************************/ -/* Data */ -/*****************************************************************************/ - - - -/* Registers */ -CPURegs Regs; - -/* Count the total number of cylcles */ -unsigned Cycles; /* Cycles per insn */ -unsigned long TotalCycles; /* Total cycles */ - -/* Allow the stack page to be changed */ -static unsigned StackPage = 0x100; - -/* CPU flags */ -int HaveNMIRequest = 0; -int HaveIRQRequest = 0; -int CPUHalted = 0; - -/* Break message */ -static StrBuf BreakMsg = STATIC_STRBUF_INITIALIZER; - - - -/*****************************************************************************/ -/* Helper functions and macros */ -/*****************************************************************************/ - - - -/* Return the flags as a boolean value (0/1) */ -#define GET_CF() ((Regs.SR & CF) != 0) -#define GET_ZF() ((Regs.SR & ZF) != 0) -#define GET_IF() ((Regs.SR & IF) != 0) -#define GET_DF() ((Regs.SR & DF) != 0) -#define GET_BF() ((Regs.SR & BF) != 0) -#define GET_OF() ((Regs.SR & OF) != 0) -#define GET_SF() ((Regs.SR & SF) != 0) - -/* Set the flags. The parameter is a boolean flag that says if the flag should be - * set or reset. - */ -#define SET_CF(f) do { if (f) { Regs.SR |= CF; } else { Regs.SR &= ~CF; } } while (0) -#define SET_ZF(f) do { if (f) { Regs.SR |= ZF; } else { Regs.SR &= ~ZF; } } while (0) -#define SET_IF(f) do { if (f) { Regs.SR |= IF; } else { Regs.SR &= ~IF; } } while (0) -#define SET_DF(f) do { if (f) { Regs.SR |= DF; } else { Regs.SR &= ~DF; } } while (0) -#define SET_BF(f) do { if (f) { Regs.SR |= BF; } else { Regs.SR &= ~BF; } } while (0) -#define SET_OF(f) do { if (f) { Regs.SR |= OF; } else { Regs.SR &= ~OF; } } while (0) -#define SET_SF(f) do { if (f) { Regs.SR |= SF; } else { Regs.SR &= ~SF; } } while (0) - -/* Special test and set macros. The meaning of the parameter depends on the - * actual flag that should be set or reset. - */ -#define TEST_ZF(v) SET_ZF (((v) & 0xFF) == 0) -#define TEST_SF(v) SET_SF (((v) & 0x80) != 0) -#define TEST_CF(v) SET_CF (((v) & 0xFF00) != 0) - -/* Program counter halves */ -#define PCL (Regs.PC & 0xFF) -#define PCH ((Regs.PC >> 8) & 0xFF) - -/* Stack operations */ -#define PUSH(Val) MemWriteByte (StackPage + Regs.SP--, Val) -#define POP() MemReadByte (StackPage + ++Regs.SP) - -/* Test for page cross */ -#define PAGE_CROSS(addr,offs) ((((addr) & 0xFF) + offs) >= 0x100) - -/* #imm */ -#define AC_OP_IMM(op) \ - Cycles = 2; \ - Regs.AC = Regs.AC op MemReadByte (Regs.PC+1); \ - TEST_ZF (Regs.AC); \ - TEST_SF (Regs.AC); \ - Regs.PC += 2 - -/* zp */ -#define AC_OP_ZP(op) \ - Cycles = 3; \ - Regs.AC = Regs.AC op MemReadByte (MemReadByte (Regs.PC+1)); \ - TEST_ZF (Regs.AC); \ - TEST_SF (Regs.AC); \ - Regs.PC += 2 - -/* zp,x */ -#define AC_OP_ZPX(op) \ - unsigned char ZPAddr; \ - Cycles = 4; \ - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \ - Regs.AC = Regs.AC op MemReadByte (ZPAddr); \ - TEST_ZF (Regs.AC); \ - TEST_SF (Regs.AC); \ - Regs.PC += 2 - -/* zp,y */ -#define AC_OP_ZPY(op) \ - unsigned char ZPAddr; \ - Cycles = 4; \ - ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR; \ - Regs.AC = Regs.AC op MemReadByte (ZPAddr); \ - TEST_ZF (Regs.AC); \ - TEST_SF (Regs.AC); \ - Regs.PC += 2 - -/* abs */ -#define AC_OP_ABS(op) \ - unsigned Addr; \ - Cycles = 4; \ - Addr = MemReadWord (Regs.PC+1); \ - Regs.AC = Regs.AC op MemReadByte (Addr); \ - TEST_ZF (Regs.AC); \ - TEST_SF (Regs.AC); \ - Regs.PC += 3 - -/* abs,x */ -#define AC_OP_ABSX(op) \ - unsigned Addr; \ - Cycles = 4; \ - Addr = MemReadWord (Regs.PC+1); \ - if (PAGE_CROSS (Addr, Regs.XR)) { \ - ++Cycles; \ - } \ - Regs.AC = Regs.AC op MemReadByte (Addr + Regs.XR); \ - TEST_ZF (Regs.AC); \ - TEST_SF (Regs.AC); \ - Regs.PC += 3 - -/* abs,y */ -#define AC_OP_ABSY(op) \ - unsigned Addr; \ - Cycles = 4; \ - Addr = MemReadWord (Regs.PC+1); \ - if (PAGE_CROSS (Addr, Regs.YR)) { \ - ++Cycles; \ - } \ - Regs.AC = Regs.AC op MemReadByte (Addr + Regs.YR); \ - TEST_ZF (Regs.AC); \ - TEST_SF (Regs.AC); \ - Regs.PC += 3 - -/* (zp,x) */ -#define AC_OP_ZPXIND(op) \ - unsigned char ZPAddr; \ - unsigned Addr; \ - Cycles = 6; \ - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; \ - Addr = MemReadZPWord (ZPAddr); \ - Regs.AC = Regs.AC op MemReadByte (Addr); \ - TEST_ZF (Regs.AC); \ - TEST_SF (Regs.AC); \ - Regs.PC += 2 - -/* (zp),y */ -#define AC_OP_ZPINDY(op) \ - unsigned char ZPAddr; \ - unsigned Addr; \ - Cycles = 5; \ - ZPAddr = MemReadByte (Regs.PC+1); \ - Addr = MemReadZPWord (ZPAddr) + Regs.YR; \ - Regs.AC = Regs.AC op MemReadByte (Addr); \ - TEST_ZF (Regs.AC); \ - TEST_SF (Regs.AC); \ - Regs.PC += 2 - -/* ADC */ -#define ADC(v) \ - do { \ - unsigned old = Regs.AC; \ - unsigned rhs = (v & 0xFF); \ - if (GET_DF ()) { \ - unsigned lo; \ - int res; \ - lo = (old & 0x0F) + (rhs & 0x0F) + GET_CF (); \ - if (lo >= 0x0A) { \ - lo = ((lo + 0x06) & 0x0F) + 0x10; \ - } \ - Regs.AC = (old & 0xF0) + (rhs & 0xF0) + lo; \ - res = (signed char)(old & 0xF0) + \ - (signed char)(rhs & 0xF0) + \ - (signed char)lo; \ - TEST_ZF (old + rhs + GET_CF ()); \ - TEST_SF (Regs.AC); \ - if (Regs.AC >= 0xA0) { \ - Regs.AC += 0x60; \ - } \ - TEST_CF (Regs.AC); \ - SET_OF ((res < -128) || (res > 127)); \ - } else { \ - Regs.AC += rhs + GET_CF (); \ - TEST_ZF (Regs.AC); \ - TEST_SF (Regs.AC); \ - TEST_CF (Regs.AC); \ - SET_OF (!((old ^ rhs) & 0x80) && \ - ((old ^ Regs.AC) & 0x80)); \ - Regs.AC &= 0xFF; \ - } \ - } while (0) - -/* branches */ -#define BRANCH(cond) \ - Cycles = 2; \ - if (cond) { \ - signed char Offs; \ - unsigned char OldPCH; \ - ++Cycles; \ - Offs = (signed char) MemReadByte (Regs.PC+1); \ - OldPCH = PCH; \ - Regs.PC += 2 + (int) Offs; \ - if (PCH != OldPCH) { \ - ++Cycles; \ - } \ - } else { \ - Regs.PC += 2; \ - } - -/* compares */ -#define CMP(v1,v2) \ - do { \ - unsigned Result = v1 - v2; \ - TEST_ZF (Result & 0xFF); \ - TEST_SF (Result); \ - SET_CF (Result <= 0xFF); \ - } while (0) - - -/* ROL */ -#define ROL(Val) \ - Val <<= 1; \ - if (GET_CF ()) { \ - Val |= 0x01; \ - } \ - TEST_ZF (Val); \ - TEST_SF (Val); \ - TEST_CF (Val) - -/* ROR */ -#define ROR(Val) \ - if (GET_CF ()) { \ - Val |= 0x100; \ - } \ - SET_CF (Val & 0x01); \ - Val >>= 1; \ - TEST_ZF (Val); \ - TEST_SF (Val) - -/* SBC */ -#define SBC(v) \ - do { \ - unsigned old = Regs.AC; \ - unsigned rhs = (v & 0xFF); \ - if (GET_DF ()) { \ - unsigned lo; \ - int res; \ - lo = (old & 0x0F) - (rhs & 0x0F) + GET_CF () - 1; \ - if (lo & 0x80) { \ - lo = ((lo - 0x06) & 0x0F) - 0x10; \ - } \ - Regs.AC = (old & 0xF0) - (rhs & 0xF0) + lo; \ - if (Regs.AC & 0x80) { \ - Regs.AC -= 0x60; \ - } \ - res = Regs.AC - rhs + (!GET_CF ()); \ - TEST_ZF (res); \ - TEST_SF (res); \ - SET_CF (res <= 0xFF); \ - SET_OF (((old^rhs) & (old^res) & 0x80)); \ - } else { \ - Regs.AC -= rhs - (!GET_CF ()); \ - TEST_ZF (Regs.AC); \ - TEST_SF (Regs.AC); \ - SET_CF (Regs.AC <= 0xFF); \ - SET_OF (((old^rhs) & (old^Regs.AC) & 0x80)); \ - Regs.AC &= 0xFF; \ - } \ - } while (0) - - -/*****************************************************************************/ -/* Helper functions */ -/*****************************************************************************/ - - - -static void OPC_Illegal (void) -{ - Warning ("Illegal opcode $%02X at address $%04X\n", MemReadByte (Regs.PC), Regs.PC); -} - - - -/*****************************************************************************/ -/* Code */ -/*****************************************************************************/ - - - -static void OPC_6502_00 (void) -/* Opcode $00: BRK */ -{ - Cycles = 7; - Regs.PC += 2; - SET_BF (1); - PUSH (PCH); - PUSH (PCL); - PUSH (Regs.SR); - SET_IF (1); - Regs.PC = MemReadWord (0xFFFE); - CPUHalted = 1; -} - - - -static void OPC_6502_01 (void) -/* Opcode $01: ORA (ind,x) */ -{ - AC_OP_ZPXIND (|); -} - - - -static void OPC_6502_05 (void) -/* Opcode $05: ORA zp */ -{ - AC_OP_ZP (|); -} - - - -static void OPC_6502_06 (void) -/* Opcode $06: ASL zp */ -{ - unsigned char ZPAddr; - unsigned Val; - Cycles = 5; - ZPAddr = MemReadByte (Regs.PC+1); - Val = MemReadByte (ZPAddr) << 1; - MemWriteByte (ZPAddr, (unsigned char) Val); - TEST_ZF (Val & 0xFF); - TEST_SF (Val); - SET_CF (Val & 0x100); - Regs.PC += 2; -} - - - -static void OPC_6502_08 (void) -/* Opcode $08: PHP */ -{ - Cycles = 3; - PUSH (Regs.SR & ~BF); - Regs.PC += 1; -} - - - -static void OPC_6502_09 (void) -/* Opcode $09: ORA #imm */ -{ - AC_OP_IMM (|); -} - - - -static void OPC_6502_0A (void) -/* Opcode $0A: ASL a */ -{ - Cycles = 2; - Regs.AC <<= 1; - TEST_ZF (Regs.AC & 0xFF); - TEST_SF (Regs.AC); - SET_CF (Regs.AC & 0x100); - Regs.AC &= 0xFF; - Regs.PC += 1; -} - - - -static void OPC_6502_0D (void) -/* Opcode $0D: ORA abs */ -{ - AC_OP_ABS (|); -} - - - -static void OPC_6502_0E (void) -/* Opcode $0E: ALS abs */ -{ - unsigned Addr; - unsigned Val; - Cycles = 6; - Addr = MemReadWord (Regs.PC+1); - Val = MemReadByte (Addr) << 1; - MemWriteByte (Addr, (unsigned char) Val); - TEST_ZF (Val & 0xFF); - TEST_SF (Val); - SET_CF (Val & 0x100); - Regs.PC += 3; -} - - - -static void OPC_6502_10 (void) -/* Opcode $10: BPL */ -{ - BRANCH (!GET_SF ()); -} - - - -static void OPC_6502_11 (void) -/* Opcode $11: ORA (zp),y */ -{ - AC_OP_ZPINDY (|); -} - - - -static void OPC_6502_15 (void) -/* Opcode $15: ORA zp,x */ -{ - AC_OP_ZPX (|); -} - - - -static void OPC_6502_16 (void) -/* Opcode $16: ASL zp,x */ -{ - unsigned char ZPAddr; - unsigned Val; - Cycles = 6; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - Val = MemReadByte (ZPAddr) << 1; - MemWriteByte (ZPAddr, (unsigned char) Val); - TEST_ZF (Val & 0xFF); - TEST_SF (Val); - SET_CF (Val & 0x100); - Regs.PC += 2; -} - - - -static void OPC_6502_18 (void) -/* Opcode $18: CLC */ -{ - Cycles = 2; - SET_CF (0); - Regs.PC += 1; -} - - - -static void OPC_6502_19 (void) -/* Opcode $19: ORA abs,y */ -{ - AC_OP_ABSY (|); -} - - - -static void OPC_6502_1D (void) -/* Opcode $1D: ORA abs,x */ -{ - AC_OP_ABSX (|); -} - - - -static void OPC_6502_1E (void) -/* Opcode $1E: ASL abs,x */ -{ - unsigned Addr; - unsigned Val; - Cycles = 7; - Addr = MemReadWord (Regs.PC+1) + Regs.XR; - Val = MemReadByte (Addr) << 1; - MemWriteByte (Addr, (unsigned char) Val); - TEST_ZF (Val & 0xFF); - TEST_SF (Val); - SET_CF (Val & 0x100); - Regs.PC += 3; -} - - - -static void OPC_6502_20 (void) -/* Opcode $20: JSR */ -{ - unsigned Addr; - Cycles = 6; - Addr = MemReadWord (Regs.PC+1); - Regs.PC += 2; - PUSH (PCH); - PUSH (PCL); - Regs.PC = Addr; -} - - - -static void OPC_6502_21 (void) -/* Opcode $21: AND (zp,x) */ -{ - AC_OP_ZPXIND (&); -} - - - -static void OPC_6502_24 (void) -/* Opcode $24: BIT zp */ -{ - unsigned char ZPAddr; - unsigned char Val; - Cycles = 3; - ZPAddr = MemReadByte (Regs.PC+1); - Val = MemReadByte (ZPAddr); - SET_SF (Val & 0x80); - SET_OF (Val & 0x40); - SET_ZF ((Val & Regs.AC) == 0); - Regs.PC += 2; -} - - - -static void OPC_6502_25 (void) -/* Opcode $25: AND zp */ -{ - AC_OP_ZP (&); -} - - - -static void OPC_6502_26 (void) -/* Opcode $26: ROL zp */ -{ - unsigned char ZPAddr; - unsigned Val; - Cycles = 5; - ZPAddr = MemReadByte (Regs.PC+1); - Val = MemReadByte (ZPAddr); - ROL (Val); - MemWriteByte (ZPAddr, Val); - Regs.PC += 2; -} - - - -static void OPC_6502_28 (void) -/* Opcode $28: PLP */ -{ - Cycles = 4; - Regs.SR = (POP () & ~BF); - Regs.PC += 1; -} - - - -static void OPC_6502_29 (void) -/* Opcode $29: AND #imm */ -{ - AC_OP_IMM (&); -} - - - -static void OPC_6502_2A (void) -/* Opcode $2A: ROL a */ -{ - Cycles = 2; - ROL (Regs.AC); - Regs.AC &= 0xFF; - Regs.PC += 1; -} - - - -static void OPC_6502_2C (void) -/* Opcode $2C: BIT abs */ -{ - unsigned Addr; - unsigned char Val; - Cycles = 4; - Addr = MemReadByte (Regs.PC+1); - Val = MemReadByte (Addr); - SET_SF (Val & 0x80); - SET_OF (Val & 0x40); - SET_ZF ((Val & Regs.AC) == 0); - Regs.PC += 3; -} - - - -static void OPC_6502_2D (void) -/* Opcode $2D: AND abs */ -{ - AC_OP_ABS (&); -} - - - -static void OPC_6502_2E (void) -/* Opcode $2E: ROL abs */ -{ - unsigned Addr; - unsigned Val; - Cycles = 6; - Addr = MemReadWord (Regs.PC+1); - Val = MemReadByte (Addr); - ROL (Val); - MemWriteByte (Addr, Val); - Regs.PC += 3; -} - - - -static void OPC_6502_30 (void) -/* Opcode $30: BMI */ -{ - BRANCH (GET_SF ()); -} - - - -static void OPC_6502_31 (void) -/* Opcode $31: AND (zp),y */ -{ - AC_OP_ZPINDY (&); -} - - - -static void OPC_6502_35 (void) -/* Opcode $35: AND zp,x */ -{ - AC_OP_ZPX (&); -} - - - -static void OPC_6502_36 (void) -/* Opcode $36: ROL zp,x */ -{ - unsigned char ZPAddr; - unsigned Val; - Cycles = 6; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - Val = MemReadByte (ZPAddr); - ROL (Val); - MemWriteByte (ZPAddr, Val); - Regs.PC += 2; -} - - - -static void OPC_6502_38 (void) -/* Opcode $38: SEC */ -{ - Cycles = 2; - SET_CF (1); - Regs.PC += 1; -} - - - -static void OPC_6502_39 (void) -/* Opcode $39: AND abs,y */ -{ - AC_OP_ABSY (&); -} - - - -static void OPC_6502_3D (void) -/* Opcode $3D: AND abs,x */ -{ - AC_OP_ABSX (&); -} - - - -static void OPC_6502_3E (void) -/* Opcode $3E: ROL abs,x */ -{ - unsigned Addr; - unsigned Val; - Cycles = 7; - Addr = MemReadWord (Regs.PC+1) + Regs.XR; - Val = MemReadByte (Addr); - ROL (Val); - MemWriteByte (Addr, Val); - Regs.PC += 2; -} - - - -static void OPC_6502_40 (void) -/* Opcode $40: RTI */ -{ - Cycles = 6; - Regs.SR = POP (); - Regs.PC = POP (); /* PCL */ - Regs.PC |= (POP () << 8); /* PCH */ -} - - - -static void OPC_6502_41 (void) -/* Opcode $41: EOR (zp,x) */ -{ - AC_OP_ZPXIND (^); -} - - - -static void OPC_6502_45 (void) -/* Opcode $45: EOR zp */ -{ - AC_OP_ZP (^); -} - - - -static void OPC_6502_46 (void) -/* Opcode $46: LSR zp */ -{ - unsigned char ZPAddr; - unsigned char Val; - Cycles = 5; - ZPAddr = MemReadByte (Regs.PC+1); - Val = MemReadByte (ZPAddr); - SET_CF (Val & 0x01); - Val >>= 1; - MemWriteByte (ZPAddr, Val); - TEST_ZF (Val); - TEST_SF (Val); - Regs.PC += 2; -} - - - -static void OPC_6502_48 (void) -/* Opcode $48: PHA */ -{ - Cycles = 3; - PUSH (Regs.AC); - Regs.PC += 1; -} - - - -static void OPC_6502_49 (void) -/* Opcode $49: EOR #imm */ -{ - AC_OP_IMM (^); -} - - - -static void OPC_6502_4A (void) -/* Opcode $4A: LSR a */ -{ - Cycles = 2; - SET_CF (Regs.AC & 0x01); - Regs.AC >>= 1; - TEST_ZF (Regs.AC); - TEST_SF (Regs.AC); - Regs.PC += 1; -} - - - -static void OPC_6502_4C (void) -/* Opcode $4C: JMP abs */ -{ - Cycles = 3; - Regs.PC = MemReadWord (Regs.PC+1); -} - - - -static void OPC_6502_4D (void) -/* Opcode $4D: EOR abs */ -{ - AC_OP_ABS (^); -} - - - -static void OPC_6502_4E (void) -/* Opcode $4E: LSR abs */ -{ - unsigned Addr; - unsigned char Val; - Cycles = 6; - Addr = MemReadWord (Regs.PC+1); - Val = MemReadByte (Addr); - SET_CF (Val & 0x01); - Val >>= 1; - MemWriteByte (Addr, Val); - TEST_ZF (Val); - TEST_SF (Val); - Regs.PC += 3; -} - - - -static void OPC_6502_50 (void) -/* Opcode $50: BVC */ -{ - BRANCH (!GET_OF ()); -} - - - -static void OPC_6502_51 (void) -/* Opcode $51: EOR (zp),y */ -{ - AC_OP_ZPINDY (^); -} - - - -static void OPC_6502_55 (void) -/* Opcode $55: EOR zp,x */ -{ - AC_OP_ZPX (^); -} - - - -static void OPC_6502_56 (void) -/* Opcode $56: LSR zp,x */ -{ - unsigned char ZPAddr; - unsigned char Val; - Cycles = 6; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - Val = MemReadByte (ZPAddr); - SET_CF (Val & 0x01); - Val >>= 1; - MemWriteByte (ZPAddr, Val); - TEST_ZF (Val); - TEST_SF (Val); - Regs.PC += 2; -} - - - -static void OPC_6502_58 (void) -/* Opcode $58: CLI */ -{ - Cycles = 2; - SET_IF (0); - Regs.PC += 1; -} - - - -static void OPC_6502_59 (void) -/* Opcode $59: EOR abs,y */ -{ - AC_OP_ABSY (^); -} - - - -static void OPC_6502_5D (void) -/* Opcode $5D: EOR abs,x */ -{ - AC_OP_ABSX (^); -} - - - -static void OPC_6502_5E (void) -/* Opcode $5E: LSR abs,x */ -{ - unsigned Addr; - unsigned char Val; - Cycles = 7; - Addr = MemReadWord (Regs.PC+1) + Regs.XR; - Val = MemReadByte (Addr); - SET_CF (Val & 0x01); - Val >>= 1; - MemWriteByte (Addr, Val); - TEST_ZF (Val); - TEST_SF (Val); - Regs.PC += 3; -} - - - -static void OPC_6502_60 (void) -/* Opcode $60: RTS */ -{ - Cycles = 6; - Regs.PC = POP (); /* PCL */ - Regs.PC |= (POP () << 8); /* PCH */ - Regs.PC += 1; -} - - - -static void OPC_6502_61 (void) -/* Opcode $61: ADC (zp,x) */ -{ - unsigned char ZPAddr; - unsigned Addr; - Cycles = 6; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - Addr = MemReadZPWord (ZPAddr); - ADC (MemReadByte (Addr)); - Regs.PC += 2; -} - - - -static void OPC_6502_65 (void) -/* Opcode $65: ADC zp */ -{ - unsigned char ZPAddr; - Cycles = 3; - ZPAddr = MemReadByte (Regs.PC+1); - ADC (MemReadByte (ZPAddr)); - Regs.PC += 2; -} - - - -static void OPC_6502_66 (void) -/* Opcode $66: ROR zp */ -{ - unsigned char ZPAddr; - unsigned Val; - Cycles = 5; - ZPAddr = MemReadByte (Regs.PC+1); - Val = MemReadByte (ZPAddr); - ROR (Val); - MemWriteByte (ZPAddr, Val); - Regs.PC += 2; -} - - - -static void OPC_6502_68 (void) -/* Opcode $68: PLA */ -{ - Cycles = 4; - Regs.AC = POP (); - TEST_ZF (Regs.AC); - TEST_SF (Regs.AC); - Regs.PC += 1; -} - - - -static void OPC_6502_69 (void) -/* Opcode $69: ADC #imm */ -{ - Cycles = 2; - ADC (MemReadByte (Regs.PC+1)); - Regs.PC += 2; -} - - - -static void OPC_6502_6A (void) -/* Opcode $6A: ROR a */ -{ - Cycles = 2; - ROR (Regs.AC); - Regs.PC += 1; -} - - - -static void OPC_6502_6C (void) -/* Opcode $6C: JMP (ind) */ -{ - unsigned Addr; - Cycles = 5; - Addr = MemReadWord (Regs.PC+1); - if (CPU == CPU_6502) { - /* Emulate the 6502 bug */ - Regs.PC = MemReadByte (Addr); - Addr = (Addr & 0xFF00) | ((Addr + 1) & 0xFF); - Regs.PC |= (MemReadByte (Addr) << 8); - } else { - /* 65C02 and above have this bug fixed */ - Regs.PC = MemReadWord (Addr); - } -} - - - -static void OPC_6502_6D (void) -/* Opcode $6D: ADC abs */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - ADC (MemReadByte (Addr)); - Regs.PC += 3; -} - - - -static void OPC_6502_6E (void) -/* Opcode $6E: ROR abs */ -{ - unsigned Addr; - unsigned Val; - Cycles = 6; - Addr = MemReadWord (Regs.PC+1); - Val = MemReadByte (Addr); - ROR (Val); - MemWriteByte (Addr, Val); - Regs.PC += 3; -} - - - -static void OPC_6502_70 (void) -/* Opcode $70: BVS */ -{ - BRANCH (GET_OF ()); -} - - - -static void OPC_6502_71 (void) -/* Opcode $71: ADC (zp),y */ -{ - unsigned char ZPAddr; - unsigned Addr; - Cycles = 5; - ZPAddr = MemReadByte (Regs.PC+1); - Addr = MemReadZPWord (ZPAddr); - if (PAGE_CROSS (Addr, Regs.YR)) { - ++Cycles; - } - ADC (MemReadByte (Addr + Regs.YR)); - Regs.PC += 2; -} - - - -static void OPC_6502_75 (void) -/* Opcode $75: ADC zp,x */ -{ - unsigned char ZPAddr; - Cycles = 4; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - ADC (MemReadByte (ZPAddr)); - Regs.PC += 2; -} - - - -static void OPC_6502_76 (void) -/* Opcode $76: ROR zp,x */ -{ - unsigned char ZPAddr; - unsigned Val; - Cycles = 6; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - Val = MemReadByte (ZPAddr); - ROR (Val); - MemWriteByte (ZPAddr, Val); - Regs.PC += 2; -} - - - -static void OPC_6502_78 (void) -/* Opcode $78: SEI */ -{ - Cycles = 2; - SET_IF (1); - Regs.PC += 1; -} - - - -static void OPC_6502_79 (void) -/* Opcode $79: ADC abs,y */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - if (PAGE_CROSS (Addr, Regs.YR)) { - ++Cycles; - } - ADC (MemReadByte (Addr + Regs.YR)); - Regs.PC += 3; -} - - - -static void OPC_6502_7D (void) -/* Opcode $7D: ADC abs,x */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - if (PAGE_CROSS (Addr, Regs.XR)) { - ++Cycles; - } - ADC (MemReadByte (Addr + Regs.XR)); - Regs.PC += 3; -} - - - -static void OPC_6502_7E (void) -/* Opcode $7E: ROR abs,x */ -{ - unsigned Addr; - unsigned Val; - Cycles = 7; - Addr = MemReadByte (Regs.PC+1) + Regs.XR; - Val = MemReadByte (Addr); - ROR (Val); - MemWriteByte (Addr, Val); - Regs.PC += 3; -} - - - -static void OPC_6502_81 (void) -/* Opcode $81: STA (zp,x) */ -{ - unsigned char ZPAddr; - unsigned Addr; - Cycles = 6; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - Addr = MemReadZPWord (ZPAddr); - MemWriteByte (Addr, Regs.AC); - Regs.PC += 2; -} - - - -static void OPC_6502_84 (void) -/* Opcode $84: STY zp */ -{ - unsigned char ZPAddr; - Cycles = 3; - ZPAddr = MemReadByte (Regs.PC+1); - MemWriteByte (ZPAddr, Regs.YR); - Regs.PC += 2; -} - - - -static void OPC_6502_85 (void) -/* Opcode $85: STA zp */ -{ - unsigned char ZPAddr; - Cycles = 3; - ZPAddr = MemReadByte (Regs.PC+1); - MemWriteByte (ZPAddr, Regs.AC); - Regs.PC += 2; -} - - - -static void OPC_6502_86 (void) -/* Opcode $86: STX zp */ -{ - unsigned char ZPAddr; - Cycles = 3; - ZPAddr = MemReadByte (Regs.PC+1); - MemWriteByte (ZPAddr, Regs.XR); - Regs.PC += 2; -} - - - -static void OPC_6502_88 (void) -/* Opcode $88: DEY */ -{ - Cycles = 2; - Regs.YR = (Regs.YR - 1) & 0xFF; - TEST_ZF (Regs.YR); - TEST_SF (Regs.YR); - Regs.PC += 1; -} - - - -static void OPC_6502_8A (void) -/* Opcode $8A: TXA */ -{ - Cycles = 2; - Regs.AC = Regs.XR; - TEST_ZF (Regs.AC); - TEST_SF (Regs.AC); - Regs.PC += 1; -} - - - -static void OPC_6502_8C (void) -/* Opcode $8C: STY abs */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - MemWriteByte (Addr, Regs.YR); - Regs.PC += 3; -} - - - -static void OPC_6502_8D (void) -/* Opcode $8D: STA abs */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - MemWriteByte (Addr, Regs.AC); - Regs.PC += 3; -} - - - -static void OPC_6502_8E (void) -/* Opcode $8E: STX abs */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - MemWriteByte (Addr, Regs.XR); - Regs.PC += 3; -} - - - -static void OPC_6502_90 (void) -/* Opcode $90: BCC */ -{ - BRANCH (!GET_CF ()); -} - - - -static void OPC_6502_91 (void) -/* Opcode $91: sta (zp),y */ -{ - unsigned char ZPAddr; - unsigned Addr; - Cycles = 6; - ZPAddr = MemReadByte (Regs.PC+1); - Addr = MemReadZPWord (ZPAddr) + Regs.YR; - MemWriteByte (Addr, Regs.AC); - Regs.PC += 2; -} - - - -static void OPC_6502_94 (void) -/* Opcode $94: STY zp,x */ -{ - unsigned char ZPAddr; - Cycles = 4; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - MemWriteByte (ZPAddr, Regs.YR); - Regs.PC += 2; -} - - - -static void OPC_6502_95 (void) -/* Opcode $95: STA zp,x */ -{ - unsigned char ZPAddr; - Cycles = 4; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - MemWriteByte (ZPAddr, Regs.AC); - Regs.PC += 2; -} - - - -static void OPC_6502_96 (void) -/* Opcode $96: stx zp,y */ -{ - unsigned char ZPAddr; - Cycles = 4; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR; - MemWriteByte (ZPAddr, Regs.XR); - Regs.PC += 2; -} - - - -static void OPC_6502_98 (void) -/* Opcode $98: TYA */ -{ - Cycles = 2; - Regs.AC = Regs.YR; - TEST_ZF (Regs.AC); - TEST_SF (Regs.AC); - Regs.PC += 1; -} - - - -static void OPC_6502_99 (void) -/* Opcode $99: STA abs,y */ -{ - unsigned Addr; - Cycles = 5; - Addr = MemReadWord (Regs.PC+1) + Regs.YR; - MemWriteByte (Addr, Regs.AC); - Regs.PC += 3; -} - - - -static void OPC_6502_9A (void) -/* Opcode $9A: TXS */ -{ - Cycles = 2; - Regs.SP = Regs.XR; - Regs.PC += 1; -} - - - -static void OPC_6502_9D (void) -/* Opcode $9D: STA abs,x */ -{ - unsigned Addr; - Cycles = 5; - Addr = MemReadWord (Regs.PC+1) + Regs.XR; - MemWriteByte (Addr, Regs.AC); - Regs.PC += 3; -} - - - -static void OPC_6502_A0 (void) -/* Opcode $A0: LDY #imm */ -{ - Cycles = 2; - Regs.YR = MemReadByte (Regs.PC+1); - TEST_ZF (Regs.YR); - TEST_SF (Regs.YR); - Regs.PC += 2; -} - - - -static void OPC_6502_A1 (void) -/* Opcode $A1: LDA (zp,x) */ -{ - unsigned char ZPAddr; - unsigned Addr; - Cycles = 6; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - Addr = MemReadZPWord (ZPAddr); - Regs.AC = MemReadByte (Addr); - TEST_ZF (Regs.AC); - TEST_SF (Regs.AC); - Regs.PC += 2; -} - - - -static void OPC_6502_A2 (void) -/* Opcode $A2: LDX #imm */ -{ - Cycles = 2; - Regs.XR = MemReadByte (Regs.PC+1); - TEST_ZF (Regs.XR); - TEST_SF (Regs.XR); - Regs.PC += 2; -} - - - -static void OPC_6502_A4 (void) -/* Opcode $A4: LDY zp */ -{ - unsigned char ZPAddr; - Cycles = 3; - ZPAddr = MemReadByte (Regs.PC+1); - Regs.YR = MemReadByte (ZPAddr); - TEST_ZF (Regs.YR); - TEST_SF (Regs.YR); - Regs.PC += 2; -} - - - -static void OPC_6502_A5 (void) -/* Opcode $A5: LDA zp */ -{ - unsigned char ZPAddr; - Cycles = 3; - ZPAddr = MemReadByte (Regs.PC+1); - Regs.AC = MemReadByte (ZPAddr); - TEST_ZF (Regs.AC); - TEST_SF (Regs.AC); - Regs.PC += 2; -} - - - -static void OPC_6502_A6 (void) -/* Opcode $A6: LDX zp */ -{ - unsigned char ZPAddr; - Cycles = 3; - ZPAddr = MemReadByte (Regs.PC+1); - Regs.XR = MemReadByte (ZPAddr); - TEST_ZF (Regs.XR); - TEST_SF (Regs.XR); - Regs.PC += 2; -} - - - -static void OPC_6502_A8 (void) -/* Opcode $A8: TAY */ -{ - Cycles = 2; - Regs.YR = Regs.AC; - TEST_ZF (Regs.YR); - TEST_SF (Regs.YR); - Regs.PC += 1; -} - - - -static void OPC_6502_A9 (void) -/* Opcode $A9: LDA #imm */ -{ - Cycles = 2; - Regs.AC = MemReadByte (Regs.PC+1); - TEST_ZF (Regs.AC); - TEST_SF (Regs.AC); - Regs.PC += 2; -} - - - -static void OPC_6502_AA (void) -/* Opcode $AA: TAX */ -{ - Cycles = 2; - Regs.XR = Regs.AC; - TEST_ZF (Regs.XR); - TEST_SF (Regs.XR); - Regs.PC += 1; -} - - - -static void OPC_6502_AC (void) -/* Opcode $Regs.AC: LDY abs */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - Regs.YR = MemReadByte (Addr); - TEST_ZF (Regs.YR); - TEST_SF (Regs.YR); - Regs.PC += 3; -} - - - -static void OPC_6502_AD (void) -/* Opcode $AD: LDA abs */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - Regs.AC = MemReadByte (Addr); - TEST_ZF (Regs.AC); - TEST_SF (Regs.AC); - Regs.PC += 3; -} - - - -static void OPC_6502_AE (void) -/* Opcode $AE: LDX abs */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - Regs.XR = MemReadByte (Addr); - TEST_ZF (Regs.XR); - TEST_SF (Regs.XR); - Regs.PC += 3; -} - - - -static void OPC_6502_B0 (void) -/* Opcode $B0: BCS */ -{ - BRANCH (GET_CF ()); -} - - - -static void OPC_6502_B1 (void) -/* Opcode $B1: LDA (zp),y */ -{ - unsigned char ZPAddr; - unsigned Addr; - Cycles = 5; - ZPAddr = MemReadByte (Regs.PC+1); - Addr = MemReadZPWord (ZPAddr); - if (PAGE_CROSS (Addr, Regs.YR)) { - ++Cycles; - } - Regs.AC = MemReadByte (Addr + Regs.YR); - TEST_ZF (Regs.AC); - TEST_SF (Regs.AC); - Regs.PC += 2; -} - - - -static void OPC_6502_B4 (void) -/* Opcode $B4: LDY zp,x */ -{ - unsigned char ZPAddr; - Cycles = 4; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - Regs.YR = MemReadByte (ZPAddr); - TEST_ZF (Regs.YR); - TEST_SF (Regs.YR); - Regs.PC += 2; -} - - - -static void OPC_6502_B5 (void) -/* Opcode $B5: LDA zp,x */ -{ - unsigned char ZPAddr; - Cycles = 4; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - Regs.AC = MemReadByte (ZPAddr); - TEST_ZF (Regs.AC); - TEST_SF (Regs.AC); - Regs.PC += 2; -} - - - -static void OPC_6502_B6 (void) -/* Opcode $B6: LDX zp,y */ -{ - unsigned char ZPAddr; - Cycles = 4; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR; - Regs.XR = MemReadByte (ZPAddr); - TEST_ZF (Regs.XR); - TEST_SF (Regs.XR); - Regs.PC += 2; -} - - - -static void OPC_6502_B8 (void) -/* Opcode $B8: CLV */ -{ - Cycles = 2; - SET_OF (0); - Regs.PC += 1; -} - - - -static void OPC_6502_B9 (void) -/* Opcode $B9: LDA abs,y */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - if (PAGE_CROSS (Addr, Regs.YR)) { - ++Cycles; - } - Regs.AC = MemReadByte (Addr + Regs.YR); - TEST_ZF (Regs.AC); - TEST_SF (Regs.AC); - Regs.PC += 3; -} - - - -static void OPC_6502_BA (void) -/* Opcode $BA: TSX */ -{ - Cycles = 2; - Regs.XR = Regs.SP; - TEST_ZF (Regs.XR); - TEST_SF (Regs.XR); - Regs.PC += 1; -} - - - -static void OPC_6502_BC (void) -/* Opcode $BC: LDY abs,x */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - if (PAGE_CROSS (Addr, Regs.XR)) { - ++Cycles; - } - Regs.YR = MemReadByte (Addr + Regs.XR); - TEST_ZF (Regs.YR); - TEST_SF (Regs.YR); - Regs.PC += 3; -} - - - -static void OPC_6502_BD (void) -/* Opcode $BD: LDA abs,x */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - if (PAGE_CROSS (Addr, Regs.XR)) { - ++Cycles; - } - Regs.AC = MemReadByte (Addr + Regs.XR); - TEST_ZF (Regs.AC); - TEST_SF (Regs.AC); - Regs.PC += 3; -} - - - -static void OPC_6502_BE (void) -/* Opcode $BE: LDX abs,y */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - if (PAGE_CROSS (Addr, Regs.YR)) { - ++Cycles; - } - Regs.XR = MemReadByte (Addr + Regs.YR); - TEST_ZF (Regs.XR); - TEST_SF (Regs.XR); - Regs.PC += 3; -} - - - -static void OPC_6502_C0 (void) -/* Opcode $C0: CPY #imm */ -{ - Cycles = 2; - CMP (Regs.YR, MemReadByte (Regs.PC+1)); - Regs.PC += 2; -} - - - -static void OPC_6502_C1 (void) -/* Opcode $C1: CMP (zp,x) */ -{ - unsigned char ZPAddr; - unsigned Addr; - Cycles = 6; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - Addr = MemReadZPWord (ZPAddr); - CMP (Regs.AC, MemReadByte (Addr)); - Regs.PC += 2; -} - - - -static void OPC_6502_C4 (void) -/* Opcode $C4: CPY zp */ -{ - unsigned char ZPAddr; - Cycles = 3; - ZPAddr = MemReadByte (Regs.PC+1); - CMP (Regs.YR, MemReadByte (ZPAddr)); - Regs.PC += 2; -} - - - -static void OPC_6502_C5 (void) -/* Opcode $C5: CMP zp */ -{ - unsigned char ZPAddr; - Cycles = 3; - ZPAddr = MemReadByte (Regs.PC+1); - CMP (Regs.AC, MemReadByte (ZPAddr)); - Regs.PC += 2; -} - - - -static void OPC_6502_C6 (void) -/* Opcode $C6: DEC zp */ -{ - unsigned char ZPAddr; - unsigned char Val; - Cycles = 5; - ZPAddr = MemReadByte (Regs.PC+1); - Val = MemReadByte (ZPAddr) - 1; - MemWriteByte (ZPAddr, Val); - TEST_ZF (Val); - TEST_SF (Val); - Regs.PC += 2; -} - - - -static void OPC_6502_C8 (void) -/* Opcode $C8: INY */ -{ - Cycles = 2; - Regs.YR = (Regs.YR + 1) & 0xFF; - TEST_ZF (Regs.YR); - TEST_SF (Regs.YR); - Regs.PC += 1; -} - - - -static void OPC_6502_C9 (void) -/* Opcode $C9: CMP #imm */ -{ - Cycles = 2; - CMP (Regs.AC, MemReadByte (Regs.PC+1)); - Regs.PC += 2; -} - - - -static void OPC_6502_CA (void) -/* Opcode $CA: DEX */ -{ - Cycles = 2; - Regs.XR = (Regs.XR - 1) & 0xFF; - TEST_ZF (Regs.XR); - TEST_SF (Regs.XR); - Regs.PC += 1; -} - - - -static void OPC_6502_CC (void) -/* Opcode $CC: CPY abs */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - CMP (Regs.YR, MemReadByte (Addr)); - Regs.PC += 3; -} - - - -static void OPC_6502_CD (void) -/* Opcode $CD: CMP abs */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - CMP (Regs.AC, MemReadByte (Addr)); - Regs.PC += 3; -} - - - -static void OPC_6502_CE (void) -/* Opcode $CE: DEC abs */ -{ - unsigned Addr; - unsigned char Val; - Cycles = 6; - Addr = MemReadWord (Regs.PC+1); - Val = MemReadByte (Addr) - 1; - MemWriteByte (Addr, Val); - TEST_ZF (Val); - TEST_SF (Val); - Regs.PC += 3; -} - - - -static void OPC_6502_D0 (void) -/* Opcode $D0: BNE */ -{ - BRANCH (!GET_ZF ()); -} - - - -static void OPC_6502_D1 (void) -/* Opcode $D1: CMP (zp),y */ -{ - unsigned ZPAddr; - unsigned Addr; - Cycles = 5; - ZPAddr = MemReadByte (Regs.PC+1); - Addr = MemReadWord (ZPAddr); - if (PAGE_CROSS (Addr, Regs.YR)) { - ++Cycles; - } - CMP (Regs.AC, MemReadByte (Addr + Regs.YR)); - Regs.PC += 2; -} - - - -static void OPC_6502_D5 (void) -/* Opcode $D5: CMP zp,x */ -{ - unsigned char ZPAddr; - Cycles = 4; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - CMP (Regs.AC, MemReadByte (ZPAddr)); - Regs.PC += 2; -} - - - -static void OPC_6502_D6 (void) -/* Opcode $D6: DEC zp,x */ -{ - unsigned char ZPAddr; - unsigned char Val; - Cycles = 6; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - Val = MemReadByte (ZPAddr) - 1; - MemWriteByte (ZPAddr, Val); - TEST_ZF (Val); - TEST_SF (Val); - Regs.PC += 2; -} - - - -static void OPC_6502_D8 (void) -/* Opcode $D8: CLD */ -{ - Cycles = 2; - SET_DF (0); - Regs.PC += 1; -} - - - -static void OPC_6502_D9 (void) -/* Opcode $D9: CMP abs,y */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - if (PAGE_CROSS (Addr, Regs.YR)) { - ++Cycles; - } - CMP (Regs.AC, MemReadByte (Addr + Regs.YR)); - Regs.PC += 3; -} - - - -static void OPC_6502_DD (void) -/* Opcode $DD: CMP abs,x */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - if (PAGE_CROSS (Addr, Regs.XR)) { - ++Cycles; - } - CMP (Regs.AC, MemReadByte (Addr + Regs.XR)); - Regs.PC += 3; -} - - - -static void OPC_6502_DE (void) -/* Opcode $DE: DEC abs,x */ -{ - unsigned Addr; - unsigned char Val; - Cycles = 7; - Addr = MemReadWord (Regs.PC+1) + Regs.XR; - Val = MemReadByte (Addr) - 1; - MemWriteByte (Addr, Val); - TEST_ZF (Val); - TEST_SF (Val); - Regs.PC += 3; -} - - - -static void OPC_6502_E0 (void) -/* Opcode $E0: CPX #imm */ -{ - Cycles = 2; - CMP (Regs.XR, MemReadByte (Regs.PC+1)); - Regs.PC += 2; -} - - - -static void OPC_6502_E1 (void) -/* Opcode $E1: SBC (zp,x) */ -{ - unsigned char ZPAddr; - unsigned Addr; - Cycles = 6; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - Addr = MemReadZPWord (ZPAddr); - SBC (MemReadByte (Addr)); - Regs.PC += 2; -} - - - -static void OPC_6502_E4 (void) -/* Opcode $E4: CPX zp */ -{ - unsigned char ZPAddr; - Cycles = 3; - ZPAddr = MemReadByte (Regs.PC+1); - CMP (Regs.XR, MemReadByte (ZPAddr)); - Regs.PC += 2; -} - - - -static void OPC_6502_E5 (void) -/* Opcode $E5: SBC zp */ -{ - unsigned char ZPAddr; - Cycles = 3; - ZPAddr = MemReadByte (Regs.PC+1); - SBC (MemReadByte (ZPAddr)); - Regs.PC += 2; -} - - - -static void OPC_6502_E6 (void) -/* Opcode $E6: INC zp */ -{ - unsigned char ZPAddr; - unsigned char Val; - Cycles = 5; - ZPAddr = MemReadByte (Regs.PC+1); - Val = MemReadByte (ZPAddr) + 1; - MemWriteByte (ZPAddr, Val); - TEST_ZF (Val); - TEST_SF (Val); - Regs.PC += 2; -} - - - -static void OPC_6502_E8 (void) -/* Opcode $E8: INX */ -{ - Cycles = 2; - Regs.XR = (Regs.XR + 1) & 0xFF; - TEST_ZF (Regs.XR); - TEST_SF (Regs.XR); - Regs.PC += 1; -} - - - -static void OPC_6502_E9 (void) -/* Opcode $E9: SBC #imm */ -{ - Cycles = 2; - SBC (MemReadByte (Regs.PC+1)); - Regs.PC += 2; -} - - - -static void OPC_6502_EA (void) -/* Opcode $EA: NOP */ -{ - /* This one is easy... */ - Cycles = 2; - Regs.PC += 1; -} - - - -static void OPC_6502_EC (void) -/* Opcode $EC: CPX abs */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - CMP (Regs.XR, MemReadByte (Addr)); - Regs.PC += 3; -} - - - -static void OPC_6502_ED (void) -/* Opcode $ED: SBC abs */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - SBC (MemReadByte (Addr)); - Regs.PC += 3; -} - - - -static void OPC_6502_EE (void) -/* Opcode $EE: INC abs */ -{ - unsigned Addr; - unsigned char Val; - Cycles = 6; - Addr = MemReadWord (Regs.PC+1); - Val = MemReadByte (Addr) + 1; - MemWriteByte (Addr, Val); - TEST_ZF (Val); - TEST_SF (Val); - Regs.PC += 3; -} - - - -static void OPC_6502_F0 (void) -/* Opcode $F0: BEQ */ -{ - BRANCH (GET_ZF ()); -} - - - -static void OPC_6502_F1 (void) -/* Opcode $F1: SBC (zp),y */ -{ - unsigned char ZPAddr; - unsigned Addr; - Cycles = 5; - ZPAddr = MemReadByte (Regs.PC+1); - Addr = MemReadZPWord (ZPAddr); - if (PAGE_CROSS (Addr, Regs.YR)) { - ++Cycles; - } - SBC (MemReadByte (Addr + Regs.YR)); - Regs.PC += 2; -} - - - -static void OPC_6502_F5 (void) -/* Opcode $F5: SBC zp,x */ -{ - unsigned char ZPAddr; - Cycles = 4; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - SBC (MemReadByte (ZPAddr)); - Regs.PC += 2; -} - - - -static void OPC_6502_F6 (void) -/* Opcode $F6: INC zp,x */ -{ - unsigned char ZPAddr; - unsigned char Val; - Cycles = 6; - ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR; - Val = MemReadByte (ZPAddr) + 1; - MemWriteByte (ZPAddr, Val); - TEST_ZF (Val); - TEST_SF (Val); - Regs.PC += 2; -} - - - -static void OPC_6502_F8 (void) -/* Opcode $F8: SED */ -{ - SET_DF (1); -} - - - -static void OPC_6502_F9 (void) -/* Opcode $F9: SBC abs,y */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - if (PAGE_CROSS (Addr, Regs.YR)) { - ++Cycles; - } - SBC (MemReadByte (Addr + Regs.YR)); - Regs.PC += 3; -} - - - -static void OPC_6502_FD (void) -/* Opcode $FD: SBC abs,x */ -{ - unsigned Addr; - Cycles = 4; - Addr = MemReadWord (Regs.PC+1); - if (PAGE_CROSS (Addr, Regs.XR)) { - ++Cycles; - } - SBC (MemReadByte (Addr + Regs.XR)); - Regs.PC += 3; -} - - - -static void OPC_6502_FE (void) -/* Opcode $FE: INC abs,x */ -{ - unsigned Addr; - unsigned char Val; - Cycles = 7; - Addr = MemReadWord (Regs.PC+1) + Regs.XR; - Val = MemReadByte (Addr) + 1; - MemWriteByte (Addr, Val); - TEST_ZF (Val); - TEST_SF (Val); - Regs.PC += 3; -} +#include "cpucore.h" +#include "error.h" /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ -/* Opcode handler table */ -typedef void (*OPCFunc) (void); -static OPCFunc OPCTable[256] = { - OPC_6502_00, - OPC_6502_01, - OPC_Illegal, - OPC_Illegal, - OPC_Illegal, - OPC_6502_05, - OPC_6502_06, - OPC_Illegal, - OPC_6502_08, - OPC_6502_09, - OPC_6502_0A, - OPC_Illegal, - OPC_Illegal, - OPC_6502_0D, - OPC_6502_0E, - OPC_Illegal, - OPC_6502_10, - OPC_6502_11, - OPC_Illegal, - OPC_Illegal, - OPC_Illegal, - OPC_6502_15, - OPC_6502_16, - OPC_Illegal, - OPC_6502_18, - OPC_6502_19, - OPC_Illegal, - OPC_Illegal, - OPC_Illegal, - OPC_6502_1D, - OPC_6502_1E, - OPC_Illegal, - OPC_6502_20, - OPC_6502_21, - OPC_Illegal, - OPC_Illegal, - OPC_6502_24, - OPC_6502_25, - OPC_6502_26, - OPC_Illegal, - OPC_6502_28, - OPC_6502_29, - OPC_6502_2A, - OPC_Illegal, - OPC_6502_2C, - OPC_6502_2D, - OPC_6502_2E, - OPC_Illegal, - OPC_6502_30, - OPC_6502_31, - OPC_Illegal, - OPC_Illegal, - OPC_Illegal, - OPC_6502_35, - OPC_6502_36, - OPC_Illegal, - OPC_6502_38, - OPC_6502_39, - OPC_Illegal, - OPC_Illegal, - OPC_Illegal, - OPC_6502_3D, - OPC_6502_3E, - OPC_Illegal, - OPC_6502_40, - OPC_6502_41, - OPC_Illegal, - OPC_Illegal, - OPC_Illegal, - OPC_6502_45, - OPC_6502_46, - OPC_Illegal, - OPC_6502_48, - OPC_6502_49, - OPC_6502_4A, - OPC_Illegal, - OPC_6502_4C, - OPC_6502_4D, - OPC_6502_4E, - OPC_Illegal, - OPC_6502_50, - OPC_6502_51, - OPC_Illegal, - OPC_Illegal, - OPC_Illegal, - OPC_6502_55, - OPC_6502_56, - OPC_Illegal, - OPC_6502_58, - OPC_6502_59, - OPC_Illegal, - OPC_Illegal, - OPC_Illegal, - OPC_6502_5D, - OPC_6502_5E, - OPC_Illegal, - OPC_6502_60, - OPC_6502_61, - OPC_Illegal, - OPC_Illegal, - OPC_Illegal, - OPC_6502_65, - OPC_6502_66, - OPC_Illegal, - OPC_6502_68, - OPC_6502_69, - OPC_6502_6A, - OPC_Illegal, - OPC_6502_6C, - OPC_6502_6D, - OPC_6502_6E, - OPC_Illegal, - OPC_6502_70, - OPC_6502_71, - OPC_Illegal, - OPC_Illegal, - OPC_Illegal, - OPC_6502_75, - OPC_6502_76, - OPC_Illegal, - OPC_6502_78, - OPC_6502_79, - OPC_Illegal, - OPC_Illegal, - OPC_Illegal, - OPC_6502_7D, - OPC_6502_7E, - OPC_Illegal, - OPC_Illegal, - OPC_6502_81, - OPC_Illegal, - OPC_Illegal, - OPC_6502_84, - OPC_6502_85, - OPC_6502_86, - OPC_Illegal, - OPC_6502_88, - OPC_Illegal, - OPC_6502_8A, - OPC_Illegal, - OPC_6502_8C, - OPC_6502_8D, - OPC_6502_8E, - OPC_Illegal, - OPC_6502_90, - OPC_6502_91, - OPC_Illegal, - OPC_Illegal, - OPC_6502_94, - OPC_6502_95, - OPC_6502_96, - OPC_Illegal, - OPC_6502_98, - OPC_6502_99, - OPC_6502_9A, - OPC_Illegal, - OPC_Illegal, - OPC_6502_9D, - OPC_Illegal, - OPC_Illegal, - OPC_6502_A0, - OPC_6502_A1, - OPC_6502_A2, - OPC_Illegal, - OPC_6502_A4, - OPC_6502_A5, - OPC_6502_A6, - OPC_Illegal, - OPC_6502_A8, - OPC_6502_A9, - OPC_6502_AA, - OPC_Illegal, - OPC_6502_AC, - OPC_6502_AD, - OPC_6502_AE, - OPC_Illegal, - OPC_6502_B0, - OPC_6502_B1, - OPC_Illegal, - OPC_Illegal, - OPC_6502_B4, - OPC_6502_B5, - OPC_6502_B6, - OPC_Illegal, - OPC_6502_B8, - OPC_6502_B9, - OPC_6502_BA, - OPC_Illegal, - OPC_6502_BC, - OPC_6502_BD, - OPC_6502_BE, - OPC_Illegal, - OPC_6502_C0, - OPC_6502_C1, - OPC_Illegal, - OPC_Illegal, - OPC_6502_C4, - OPC_6502_C5, - OPC_6502_C6, - OPC_Illegal, - OPC_6502_C8, - OPC_6502_C9, - OPC_6502_CA, - OPC_Illegal, - OPC_6502_CC, - OPC_6502_CD, - OPC_6502_CE, - OPC_Illegal, - OPC_6502_D0, - OPC_6502_D1, - OPC_Illegal, - OPC_Illegal, - OPC_Illegal, - OPC_6502_D5, - OPC_6502_D6, - OPC_Illegal, - OPC_6502_D8, - OPC_6502_D9, - OPC_Illegal, - OPC_Illegal, - OPC_Illegal, - OPC_6502_DD, - OPC_6502_DE, - OPC_Illegal, - OPC_6502_E0, - OPC_6502_E1, - OPC_Illegal, - OPC_Illegal, - OPC_6502_E4, - OPC_6502_E5, - OPC_6502_E6, - OPC_Illegal, - OPC_6502_E8, - OPC_6502_E9, - OPC_6502_EA, - OPC_Illegal, - OPC_6502_EC, - OPC_6502_ED, - OPC_6502_EE, - OPC_Illegal, - OPC_6502_F0, - OPC_6502_F1, - OPC_Illegal, - OPC_Illegal, - OPC_Illegal, - OPC_6502_F5, - OPC_6502_F6, - OPC_Illegal, - OPC_6502_F8, - OPC_6502_F9, - OPC_Illegal, - OPC_Illegal, - OPC_Illegal, - OPC_6502_FD, - OPC_6502_FE, - OPC_Illegal, -}; +/* The actual CPU instance */ +CPUCore* CPU = 0; /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ -void CPUInit (void) -/* Initialize the CPU */ -{ - RESET (); -} - - - -void IRQRequest (void) -/* Generate an IRQ */ -{ - HaveIRQRequest = 1; -} - - - -void NMIRequest (void) -/* Generate an NMI */ -{ - HaveNMIRequest = 1; -} - - - -void RESET (void) -/* Generate a CPU RESET */ -{ - CPUHalted = HaveIRQRequest = HaveNMIRequest = 0; - Regs.PC = MemReadWord (0xFFFC); -} - - - -void Break (const char* Format, ...) -/* Stop running and display the given message */ +CPUCore* NewCPUCore (const char* Name, unsigned AddrSpaceSize) +/* Create and return a new CPU including it's address space */ { - va_list ap; - va_start (ap, Format); - SB_VPrintf (&BreakMsg, Format, ap); - va_end (ap); -} - - + CPUCore* C; -void CPURun (void) -/* Run one CPU instruction */ -{ - /* If the CPU is halted, do nothing */ - if (CPUHalted) { - return; + /* Make sure this is a 6502 CPU for now */ + if (strcmp (Name, "6502") != 0) { + Error ("Unknown CPU type `%s'", Name); } - /* If we have an NMI request, handle it */ - if (HaveNMIRequest) { - - HaveNMIRequest = 0; - PUSH (PCH); - PUSH (PCL); - PUSH (Regs.SR); - SET_IF (1); - Regs.PC = MemReadWord (0xFFFA); - Cycles = 7; - - } else if (HaveIRQRequest && GET_IF () == 0) { - - HaveIRQRequest = 0; - PUSH (PCH); - PUSH (PCL); - PUSH (Regs.SR); - SET_IF (1); - Regs.PC = MemReadWord (0xFFFE); - Cycles = 7; + /* Allocate memory */ + C = xmalloc (sizeof (*C)); - } else { + /* Initialize the data */ + C->Handle = 0; /* ### */ + C->AS = NewAddressSpace (AddrSpaceSize); - /* Normal instruction - read the next opcode */ - unsigned char OPC = MemReadByte (Regs.PC); - - /* Execute it */ - OPCTable[OPC] (); - - } - - /* Count cycles */ - TotalCycles += Cycles; - - if (SB_GetLen (&BreakMsg) > 0) { - printf ("%.*s\n", SB_GetLen (&BreakMsg), SB_GetConstBuf (&BreakMsg)); - SB_Clear (&BreakMsg); - } + /* Return the new CPU core */ + return C; } -#if 0 - if ((++I & 0xFF) == 0) - printf ("%9lu %06X %02X A=%02X X=%02X Y=%02X %c%c%c%c%c%c%c\n", - TotalCycles, Regs.PC, OPC, Regs.AC, Regs.XR, Regs.YR, - GET_SF()? 'S' : '-', - GET_ZF()? 'Z' : '-', - GET_CF()? 'C' : '-', - GET_IF()? 'I' : '-', - GET_BF()? 'B' : '-', - GET_DF()? 'D' : '-', - GET_OF()? 'V' : '-'); -#endif - - diff --git a/src/sim65/cpucore.h b/src/sim65/cpucore.h index b88617143..28b9351ff 100644 --- a/src/sim65/cpucore.h +++ b/src/sim65/cpucore.h @@ -1,15 +1,15 @@ /*****************************************************************************/ /* */ -/* cpucore.h */ +/* cpucore.h */ /* */ -/* CPU core for the 6502 simulator */ +/* CPU definition for the simulator */ /* */ /* */ /* */ -/* (C) 2002-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2003-2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -39,44 +39,36 @@ /* sim65 */ -#include "cpuregs.h" +#include "addrspace.h" /*****************************************************************************/ -/* Data */ +/* Data */ /*****************************************************************************/ -/* Registers */ -extern CPURegs Regs; +/* CPU core structure */ +typedef struct CPUCore CPUCore; +struct CPUCore { + void* Handle; /* Pointer to shared lib handle */ + AddressSpace* AS; /* Address space */ +}; + +/* The actual CPU instance */ +extern CPUCore* CPU; /*****************************************************************************/ -/* Code */ +/* Code */ /*****************************************************************************/ -void CPUInit (void); -/* Initialize the CPU */ - -void RESET (void); -/* Generate a CPU RESET */ - -void IRQRequest (void); -/* Generate an IRQ */ - -void NMIRequest (void); -/* Generate an NMI */ - -void Break (const char* Format, ...); -/* Stop running and display the given message */ - -void CPURun (void); -/* Run one CPU instruction */ +CPUCore* NewCPUCore (const char* Name, unsigned AddrSpaceSize); +/* Create and return a new CPU including it's address space */ @@ -86,3 +78,4 @@ void CPURun (void); + diff --git a/src/sim65/make/gcc.mak b/src/sim65/make/gcc.mak index bbde6f84d..fe70538be 100644 --- a/src/sim65/make/gcc.mak +++ b/src/sim65/make/gcc.mak @@ -12,7 +12,7 @@ COMMON = ../common # CC = gcc -CFLAGS = -g -O2 -Wall -W -std=c89 +CFLAGS = -g -Wall -W -std=c89 override CFLAGS += -I$(COMMON) EBIND = emxbind LDFLAGS = -ldl @@ -27,13 +27,13 @@ OBJS = addrspace.o \ chip.o \ chippath.o \ config.o \ + cpu-6502.o \ cpucore.o \ cputype.o \ error.o \ global.o \ location.o \ main.o \ - memory.o \ scanner.o \ system.o diff --git a/src/sim65/memory.c b/src/sim65/memory.c index dac80a450..90edf46e6 100644 --- a/src/sim65/memory.c +++ b/src/sim65/memory.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2002-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2002-2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ diff --git a/src/sim65/memory.h b/src/sim65/memory.h index 6874e6411..cafca0052 100644 --- a/src/sim65/memory.h +++ b/src/sim65/memory.h @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2002-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 2002-2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ diff --git a/src/sim65/scanner.c b/src/sim65/scanner.c index 3e6ab739f..86c88fb6f 100644 --- a/src/sim65/scanner.c +++ b/src/sim65/scanner.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 1998-2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -57,7 +57,7 @@ /* Current token and attributes */ cfgtok_t CfgTok; -char CfgSVal [CFG_MAX_IDENT_LEN+1]; +StrBuf CfgSVal = STATIC_STRBUF_INITIALIZER; unsigned long CfgIVal; /* Error location */ @@ -266,7 +266,7 @@ Again: I = 0; while (C != '\"') { if (C == EOF || C == '\n') { - Error ("%s(%u): Unterminated string", CfgName, InputLine); + Error ("%s(%u): Unterminated string", CfgName, InputLine); } if (I < CFG_MAX_IDENT_LEN) { CfgSVal [I++] = C; diff --git a/src/sim65/scanner.h b/src/sim65/scanner.h index 3066e15df..5cb2342b2 100644 --- a/src/sim65/scanner.h +++ b/src/sim65/scanner.h @@ -1,15 +1,15 @@ /*****************************************************************************/ /* */ -/* scanner.h */ +/* scanner.h */ /* */ /* Configuration file scanner for the sim65 6502 simulator */ /* */ /* */ /* */ -/* (C) 1998-2003 Ullrich von Bassewitz */ -/* Römerstrasse 52 */ -/* D-70794 Filderstadt */ -/* EMail: uz@cc65.org */ +/* (C) 1998-2012, Ullrich von Bassewitz */ +/* Roemerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -40,6 +40,7 @@ /* common */ #include "attrib.h" +#include "strbuf.h" @@ -67,11 +68,10 @@ typedef enum { /* Primary blocks */ CFGTOK_CPU, - CFGTOK_MEMORY, + CFGTOK_ADDRSPACE, - /* CPU block */ + /* Secondary stuff */ CFGTOK_TYPE, - CFGTOK_ADDRSPACE, /* Special identifiers */ CFGTOK_TRUE, @@ -92,9 +92,8 @@ struct IdentTok { /* Current token and attributes */ -#define CFG_MAX_IDENT_LEN 255 extern cfgtok_t CfgTok; -extern char CfgSVal [CFG_MAX_IDENT_LEN+1]; +extern StrBuf CfgSVal; extern unsigned long CfgIVal; /* Error location */ diff --git a/src/sim65/simdata.h b/src/sim65/simdata.h index fd97c1223..7eadc6e63 100644 --- a/src/sim65/simdata.h +++ b/src/sim65/simdata.h @@ -89,6 +89,12 @@ struct SimData { * true. If not found, return false. */ + unsigned char (*ReadCtrl) (unsigned Addr); + /* Read from the given address without triggering any additional action */ + + void (*WriteCtrl) (unsigned Addr, unsigned char Val); + /* Write to the given address without triggering additional action */ + void (*Break) (const char* Format, ...); /* Stop the CPU and display the given message */ @@ -98,7 +104,7 @@ struct SimData { void (*NMI) (void); /* Issue an nmi request */ - + };