summaryrefslogtreecommitdiff
path: root/libsidplay2/sidplay-libs-2.1.0/libsidplay/src/mos6510/cycle_based/mos6510c.i
diff options
context:
space:
mode:
Diffstat (limited to 'libsidplay2/sidplay-libs-2.1.0/libsidplay/src/mos6510/cycle_based/mos6510c.i')
-rw-r--r--libsidplay2/sidplay-libs-2.1.0/libsidplay/src/mos6510/cycle_based/mos6510c.i2562
1 files changed, 0 insertions, 2562 deletions
diff --git a/libsidplay2/sidplay-libs-2.1.0/libsidplay/src/mos6510/cycle_based/mos6510c.i b/libsidplay2/sidplay-libs-2.1.0/libsidplay/src/mos6510/cycle_based/mos6510c.i
deleted file mode 100644
index 78d57ba6..00000000
--- a/libsidplay2/sidplay-libs-2.1.0/libsidplay/src/mos6510/cycle_based/mos6510c.i
+++ /dev/null
@@ -1,2562 +0,0 @@
-/***************************************************************************
- mos6510.i - Cycle Accurate 6510 emulation
- -------------------
- begin : Thu May 11 06:22:40 BST 2000
- copyright : (C) 2000 by Simon White
- email : s_a_white@email.com
- ***************************************************************************/
-
-/***************************************************************************
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- ***************************************************************************/
-/***************************************************************************
- * $Log: mos6510c.i,v $
- * Revision 1.30 2002/12/16 08:42:58 s_a_white
- * Fixed use of nothrow to be namespaced with std::.
- *
- * Revision 1.29 2002/11/28 20:35:06 s_a_white
- * Reduced number of thrown exceptions when dma occurs.
- *
- * Revision 1.28 2002/11/25 20:10:55 s_a_white
- * A bus access failure should stop the CPU dead like the cycle never started.
- * This is currently simulated using throw (execption handling) for now.
- *
- * Revision 1.27 2002/11/21 19:52:48 s_a_white
- * CPU upgraded to be like other components. Theres nolonger a clock call,
- * instead events are registered to occur at a specific time.
- *
- * Revision 1.26 2002/11/19 22:57:33 s_a_white
- * Initial support for external DMA to steal cycles away from the CPU.
- *
- * Revision 1.25 2002/11/01 19:22:36 s_a_white
- * Removed debug printf.
- *
- * Revision 1.24 2002/11/01 17:35:27 s_a_white
- * Frame based support for old sidplay1 modes.
- *
- * Revision 1.23 2002/03/12 18:48:03 s_a_white
- * Tidied illegal instruction debug print out.
- *
- * Revision 1.22 2001/12/11 19:24:15 s_a_white
- * More GCC3 Fixes.
- *
- * Revision 1.21 2001/11/16 19:21:03 s_a_white
- * Sign fixes.
- *
- * Revision 1.20 2001/10/28 21:31:26 s_a_white
- * Removed kernel debuging code.
- *
- * Revision 1.19 2001/09/03 22:21:52 s_a_white
- * When initialising the status register and therefore unmasking the irqs,
- * check the irq line to see if any are pending.
- *
- * Revision 1.18 2001/08/10 20:05:50 s_a_white
- * Fixed RMW instructions which broke due to the optimisation.
- *
- * Revision 1.17 2001/08/05 15:46:02 s_a_white
- * No longer need to check on which cycle an instruction ends or when to print
- * debug information.
- *
- * Revision 1.16 2001/07/14 13:15:30 s_a_white
- * Accumulator is now unsigned, which improves code readability. Emulation
- * tested with testsuite 2.15. Various instructions required modification.
- *
- * Revision 1.15 2001/04/20 22:23:11 s_a_white
- * Handling of page boundary crossing now correct for branch instructions.
- *
- * Revision 1.14 2001/03/28 22:59:59 s_a_white
- * Converted some bad envReadMemByte's to
- * envReadMemDataByte
- *
- * Revision 1.13 2001/03/28 21:17:34 s_a_white
- * Added support for proper RMW instructions.
- *
- * Revision 1.12 2001/03/24 18:09:17 s_a_white
- * On entry to interrupt routine the first instruction in the handler is now always
- * executed before pending interrupts are re-checked.
- *
- * Revision 1.11 2001/03/22 22:40:43 s_a_white
- * Added new header for definition of nothrow.
- *
- * Revision 1.10 2001/03/21 22:27:18 s_a_white
- * Change to IRQ error message.
- *
- * Revision 1.9 2001/03/19 23:46:35 s_a_white
- * NMI no longer sets I flag. RTI and store instructions are no longer
- * overlapped.
- *
- * Revision 1.8 2001/03/09 22:28:51 s_a_white
- * Speed optimisation update and fix for interrupt flag in PushSR call.
- *
- * Revision 1.7 2001/02/22 08:28:57 s_a_white
- * Interrupt masking fixed.
- *
- * Revision 1.6 2001/02/13 23:01:44 s_a_white
- * envReadMemDataByte now used for some memory accesses.
- *
- * Revision 1.5 2000/12/24 00:45:38 s_a_white
- * HAVE_EXCEPTIONS update
- *
- * Revision 1.4 2000/12/14 23:55:07 s_a_white
- * PushSR optimisation and PopSR code cleanup.
- *
- ***************************************************************************/
-/*
-const char _sidtune_CHRtab[256] = // CHR$ conversion table (0x01 = no output)
-{
- 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0xd, 0x1, 0x1,
- 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
- 0x20,0x21, 0x1,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
- 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,
- 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,
- 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x24,0x5d,0x20,0x20,
- // alternative: CHR$(92=0x5c) => ISO Latin-1(0xa3)
- 0x2d,0x23,0x7c,0x2d,0x2d,0x2d,0x2d,0x7c,0x7c,0x5c,0x5c,0x2f,0x5c,0x5c,0x2f,0x2f,
- 0x5c,0x23,0x5f,0x23,0x7c,0x2f,0x58,0x4f,0x23,0x7c,0x23,0x2b,0x7c,0x7c,0x26,0x5c,
- // 0x80-0xFF
- 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
- 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
- 0x20,0x7c,0x23,0x2d,0x2d,0x7c,0x23,0x7c,0x23,0x2f,0x7c,0x7c,0x2f,0x5c,0x5c,0x2d,
- 0x2f,0x2d,0x2d,0x7c,0x7c,0x7c,0x7c,0x2d,0x2d,0x2d,0x2f,0x5c,0x5c,0x2f,0x2f,0x23,
- 0x2d,0x23,0x7c,0x2d,0x2d,0x2d,0x2d,0x7c,0x7c,0x5c,0x5c,0x2f,0x5c,0x5c,0x2f,0x2f,
- 0x5c,0x23,0x5f,0x23,0x7c,0x2f,0x58,0x4f,0x23,0x7c,0x23,0x2b,0x7c,0x7c,0x26,0x5c,
- 0x20,0x7c,0x23,0x2d,0x2d,0x7c,0x23,0x7c,0x23,0x2f,0x7c,0x7c,0x2f,0x5c,0x5c,0x2d,
- 0x2f,0x2d,0x2d,0x7c,0x7c,0x7c,0x7c,0x2d,0x2d,0x2d,0x2f,0x5c,0x5c,0x2f,0x2f,0x23
-};
-*/
-
-#include "config.h"
-
-#ifdef HAVE_EXCEPTIONS
-# include <new>
-#endif
-
-// Microsoft Visual C++ Version Number to work around compiler bug
-// Currently both Visual C++ Versions 5, 6 are broken.
-#define _MSC_VER_BAD_NEW 1200 /* Defines VC6 and below */
-//char filetmp[0x100];
-//int filepos = 0;
-
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-// Status Register Routines //
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-// Use macros to access flags. Allows compatiblity with other versions
-// of this emulation
-// Set N and Z flags according to byte
-#define setFlagsNZ(x) (Register_z_Flag = (Register_n_Flag = (uint_least8_t) (x)))
-#define setFlagN(x) (Register_n_Flag = (uint_least8_t) (x))
-#define setFlagV(x) (Register_v_Flag = (uint_least8_t) (x))
-#define setFlagD(x) (Register_Status = (Register_Status & ~(1 << SR_DECIMAL)) \
- | (((x) != 0) << SR_DECIMAL))
-#define setFlagI(x) (Register_Status = (Register_Status & ~(1 << SR_INTERRUPT)) \
- | (((x) != 0) << SR_INTERRUPT))
-#define setFlagZ(x) (Register_z_Flag = (uint_least8_t) (x))
-#define setFlagC(x) (Register_c_Flag = (uint_least8_t) (x))
-
-
-#define getFlagN() ((Register_n_Flag & (1 << SR_NEGATIVE)) != 0)
-#define getFlagV() (Register_v_Flag != 0)
-#define getFlagD() ((Register_Status & (1 << SR_DECIMAL)) != 0)
-#define getFlagI() ((Register_Status & (1 << SR_INTERRUPT)) != 0)
-#define getFlagZ() (Register_z_Flag == 0)
-#define getFlagC() (Register_c_Flag != 0)
-
-#define stealCycle() \
- interrupts.delay++; \
- throw((int_least8_t) -1);
-
-
-// Handle bus access signals
-void MOS6510::aecSignal (bool state)
-{ // If the cpu blocked waiting for the bus
- // the schedule a retry.
- aec = state;
- if (state && m_blocked)
- {
- m_blocked = false;
- eventContext.schedule (this, 1);
- }
-}
-
-void MOS6510::rdySignal (bool state)
-{ // If the cpu blocked waiting for the bus
- // the schedule a retry.
- rdy = state;
- if (state && m_blocked)
- {
- m_blocked = false;
- eventContext.schedule (this, 1);
- }
-}
-
-// Push P on stack, decrement S
-void MOS6510::PushSR (bool b_flag)
-{
- if (aec)
- {
- uint_least16_t addr = Register_StackPointer;
- endian_16hi8 (addr, SP_PAGE);
- /* Rev 1.04 - Corrected flag mask */
- Register_Status &= ((1 << SR_NOTUSED) | (1 << SR_INTERRUPT) |
- (1 << SR_DECIMAL) | (1 << SR_BREAK));
- Register_Status |= (getFlagN () << SR_NEGATIVE);
- Register_Status |= (getFlagV () << SR_OVERFLOW);
- Register_Status |= (getFlagZ () << SR_ZERO);
- Register_Status |= (getFlagC () << SR_CARRY);
- envWriteMemByte (addr, Register_Status & ~((!b_flag) << SR_BREAK));
- Register_StackPointer--;
- }
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-void MOS6510::PushSR (void)
-{
- PushSR (true);
-}
-
-// increment S, Pop P off stack
-void MOS6510::PopSR (void)
-{
- if (rdy && aec)
- {
- bool newFlagI, oldFlagI;
- oldFlagI = getFlagI ();
-
- // Get status register off stack
- Register_StackPointer++;
- {
- uint_least16_t addr = Register_StackPointer;
- endian_16hi8 (addr, SP_PAGE);
- Register_Status = envReadMemByte (addr);
- }
- Register_Status |= ((1 << SR_NOTUSED) | (1 << SR_BREAK));
- setFlagN (Register_Status);
- setFlagV (Register_Status & (1 << SR_OVERFLOW));
- setFlagZ (!(Register_Status & (1 << SR_ZERO)));
- setFlagC (Register_Status & (1 << SR_CARRY));
-
- // I flag change is delayed by 1 instruction
- newFlagI = getFlagI ();
- interrupts.irqLatch = oldFlagI ^ newFlagI;
- // Check to see if interrupts got re-enabled
- if (!newFlagI && interrupts.irqs)
- interrupts.irqRequest = true;
- }
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-// Interrupt Routines //
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-#define iIRQSMAX 3
-enum
-{
- oNONE = -1,
- oRST,
- oNMI,
- oIRQ
-};
-
-enum
-{
- iNONE = 0,
- iRST = 1 << oRST,
- iNMI = 1 << oNMI,
- iIRQ = 1 << oIRQ
-};
-
-void MOS6510::triggerRST (void)
-{
- interrupts.pending |= iRST;
-}
-
-void MOS6510::triggerNMI (void)
-{
- interrupts.pending |= iNMI;
- interrupts.nmiClock = eventContext.getTime ();
-}
-
-// Level triggered interrupt
-void MOS6510::triggerIRQ (void)
-{ // IRQ Suppressed
- if (!getFlagI ())
- interrupts.irqRequest = true;
- if (!interrupts.irqs++)
- interrupts.irqClock = eventContext.getTime ();
-
- if (interrupts.irqs > iIRQSMAX)
- {
- printf ("\nMOS6510 ERROR: An external component is not clearing down it's IRQs.\n\n");
- exit (-1);
- }
-}
-
-void MOS6510::clearIRQ (void)
-{
- if (interrupts.irqs > 0)
- {
- if (!(--interrupts.irqs))
- { // Clear off the interrupts
- interrupts.irqRequest = false;
- }
- }
-}
-
-bool MOS6510::interruptPending (void)
-{
- int_least8_t offset, pending;
- static const int_least8_t offTable[] = {oNONE, oRST, oNMI, oRST,
- oIRQ, oRST, oNMI, oRST};
- // Update IRQ pending
- if (!interrupts.irqLatch)
- {
- interrupts.pending &= ~iIRQ;
- if (interrupts.irqRequest)
- interrupts.pending |= iIRQ;
- }
-
- pending = interrupts.pending;
-MOS6510_interruptPending_check:
- // Service the highest priority interrupt
- offset = offTable[pending];
- switch (offset)
- {
- case oNONE:
- return false;
-
- case oNMI:
- {
- // Try to determine if we should be processing the NMI yet
- event_clock_t cycles = eventContext.getTime (interrupts.nmiClock);
- if (cycles >= interrupts.delay)
- {
- interrupts.pending &= ~iNMI;
- break;
- }
-
- // NMI delayed so check for other interrupts
- pending &= ~iNMI;
- goto MOS6510_interruptPending_check;
- }
-
- case oIRQ:
- {
- // Try to determine if we should be processing the IRQ yet
- event_clock_t cycles = eventContext.getTime (interrupts.irqClock);
- if (cycles >= interrupts.delay)
- break;
-
- // NMI delayed so check for other interrupts
- pending &= ~iIRQ;
- goto MOS6510_interruptPending_check;
- }
-
- case oRST:
- break;
- }
-
-#ifdef MOS6510_DEBUG
- if (dodump)
- {
- printf ("****************************************************\n");
- switch (offset)
- {
- case oIRQ:
- printf (" IRQ Routine\n");
- break;
- case oNMI:
- printf (" NMI Routine\n");
- break;
- case oRST:
- printf (" RST Routine\n");
- break;
- }
- printf ("****************************************************\n");
- }
-#endif
-
- // Start the interrupt
- instrCurrent = &interruptTable[offset];
- procCycle = instrCurrent->cycle;
- cycleCount = 0;
- return true;
-}
-
-void MOS6510::RSTRequest (void)
-{
- envReset ();
-}
-
-void MOS6510::NMIRequest (void)
-{
- if (rdy && aec)
- endian_16lo8 (Cycle_EffectiveAddress, envReadMemDataByte (0xFFFA));
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-void MOS6510::NMI1Request (void)
-{
- if (rdy && aec)
- {
- endian_16hi8 (Cycle_EffectiveAddress, envReadMemDataByte (0xFFFB));
- endian_32lo16 (Register_ProgramCounter, Cycle_EffectiveAddress);
- }
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-void MOS6510::IRQRequest (void)
-{
- PushSR (false);
- setFlagI (true);
- interrupts.irqRequest = false;
-}
-
-void MOS6510::IRQ1Request (void)
-{
- if (rdy && aec)
- endian_16lo8 (Cycle_EffectiveAddress, envReadMemDataByte (0xFFFE));
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-void MOS6510::IRQ2Request (void)
-{
- if (rdy && aec)
- {
- endian_16hi8 (Cycle_EffectiveAddress, envReadMemDataByte (0xFFFF));
- endian_32lo16 (Register_ProgramCounter, Cycle_EffectiveAddress);
- }
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-void MOS6510::NextInstr (void)
-{
- if (!interruptPending ())
- FetchOpcode ();
-}
-
-
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-// Common Instruction Addressing Routines //
-// Addressing operations as described in 64doc by John West and //
-// Marko Makela //
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-
-// Fetch opcode, increment PC
-// Addressing Modes: All
-void MOS6510::FetchOpcode (void)
-{
- if (rdy && aec)
- { // On new instruction all interrupt delays are reset
- interrupts.delay = MOS6510_INTERRUPT_DELAY;
- interrupts.irqLatch = false;
-
- instrStartPC = endian_32lo16 (Register_ProgramCounter++);
- instrOpcode = envReadMemByte (instrStartPC);
- // Convert opcode to pointer in instruction table
- instrCurrent = &instrTable[instrOpcode];
- Instr_Operand = 0;
- procCycle = instrCurrent->cycle;
- cycleCount = 0;
- clock ();
- }
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-// Fetch value, increment PC
-/* Addressing Modes: Immediate
- Relative
-*/
-void MOS6510::FetchDataByte (void)
-{ // Get data byte from memory
- Cycle_Data = envReadMemByte (endian_32lo16 (Register_ProgramCounter));
- Register_ProgramCounter++;
-
- // Nextline used for Debug
- Instr_Operand = (uint_least16_t) Cycle_Data;
-}
-
-// Fetch low address byte, increment PC
-/* Addressing Modes: Stack Manipulation
- Absolute
- Zero Page
- Zerp Page Indexed
- Absolute Indexed
- Absolute Indirect
-*/
-void MOS6510::FetchLowAddr (void)
-{
- if (rdy && aec)
- {
- Cycle_EffectiveAddress = envReadMemByte (endian_32lo16 (Register_ProgramCounter));
- Register_ProgramCounter++;
-
- // Nextline used for Debug
- Instr_Operand = Cycle_EffectiveAddress;
- }
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-// Read from address, add index register X to it
-// Addressing Modes: Zero Page Indexed
-void MOS6510::FetchLowAddrX (void)
-{
- FetchLowAddr ();
- Cycle_EffectiveAddress = (Cycle_EffectiveAddress + Register_X) & 0xFF;
-}
-
-// Read from address, add index register Y to it
-// Addressing Modes: Zero Page Indexed
-void MOS6510::FetchLowAddrY (void)
-{
- FetchLowAddr ();
- Cycle_EffectiveAddress = (Cycle_EffectiveAddress + Register_Y) & 0xFF;
-}
-
-// Fetch high address byte, increment PC (Absoulte Addressing)
-// Low byte must have been obtained first!
-// Addressing Modes: Absolute
-void MOS6510::FetchHighAddr (void)
-{
- if (rdy && aec)
- { // Get the high byte of an address from memory
- endian_16hi8 (Cycle_EffectiveAddress, envReadMemByte (endian_32lo16 (Register_ProgramCounter)));
- Register_ProgramCounter++;
-
- // Nextline used for Debug
- endian_16hi8 (Instr_Operand, endian_16hi8 (Cycle_EffectiveAddress));
- }
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-// Fetch high byte of address, add index register X to low address byte,
-// increment PC
-// Addressing Modes: Absolute Indexed
-void MOS6510::FetchHighAddrX (void)
-{
- uint8_t page;
- // Rev 1.05 (saw) - Call base Function
- FetchHighAddr ();
- page = endian_16hi8 (Cycle_EffectiveAddress);
- Cycle_EffectiveAddress += Register_X;
-
-#ifdef MOS6510_ACCURATE_CYCLES
- // Handle page boundary crossing
- if (endian_16hi8 (Cycle_EffectiveAddress) == page)
- cycleCount++;
-#endif
-}
-
-// Same as above except dosen't worry about page crossing
-void MOS6510::FetchHighAddrX2 (void)
-{
- FetchHighAddr ();
- Cycle_EffectiveAddress += Register_X;
-}
-
-// Fetch high byte of address, add index register Y to low address byte,
-// increment PC
-// Addressing Modes: Absolute Indexed
-void MOS6510::FetchHighAddrY (void)
-{
- uint8_t page;
- // Rev 1.05 (saw) - Call base Function
- FetchHighAddr ();
- page = endian_16hi8 (Cycle_EffectiveAddress);
- Cycle_EffectiveAddress += Register_Y;
-
-#ifdef MOS6510_ACCURATE_CYCLES
- // Handle page boundary crossing
- if (endian_16hi8 (Cycle_EffectiveAddress) == page)
- cycleCount++;
-#endif
-}
-
-// Same as above except dosen't worry about page crossing
-void MOS6510::FetchHighAddrY2 (void)
-{
- FetchHighAddr ();
- Cycle_EffectiveAddress += Register_Y;
-}
-
-// Fetch pointer address low, increment PC
-/* Addressing Modes: Absolute Indirect
- Indirect indexed (post Y)
-*/
-void MOS6510::FetchLowPointer (void)
-{
- if (rdy && aec)
- {
- Cycle_Pointer = envReadMemByte (endian_32lo16 (Register_ProgramCounter));
- Register_ProgramCounter++;
- // Nextline used for Debug
- Instr_Operand = Cycle_Pointer;
- }
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-// Read pointer from the address and add X to it
-// Addressing Modes: Indexed Indirect (pre X)
-void MOS6510::FetchLowPointerX (void)
-{
- if (rdy && aec)
- {
- endian_16hi8 (Cycle_Pointer, envReadMemDataByte (Cycle_Pointer));
- // Page boundary crossing is not handled
- Cycle_Pointer = (Cycle_Pointer + Register_X) & 0xFF;
- }
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-// Fetch pointer address high, increment PC
-// Addressing Modes: Absolute Indirect
-void MOS6510::FetchHighPointer (void)
-{
- if (rdy && aec)
- {
- endian_16hi8 (Cycle_Pointer, envReadMemByte (endian_32lo16 (Register_ProgramCounter)));
- Register_ProgramCounter++;
-
- // Nextline used for Debug
- endian_16hi8 (Instr_Operand, endian_16hi8 (Cycle_Pointer));
- }
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-// Fetch effective address low
-/* Addressing Modes: Indirect
- Indexed Indirect (pre X)
- Indirect indexed (post Y)
-*/
-void MOS6510::FetchLowEffAddr (void)
-{
- if (rdy && aec)
- Cycle_EffectiveAddress = envReadMemDataByte (Cycle_Pointer);
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-// Fetch effective address high
-/* Addressing Modes: Indirect
- Indexed Indirect (pre X)
-*/
-void MOS6510::FetchHighEffAddr (void)
-{
- if (rdy && aec)
- { // Rev 1.03 (Mike) - Extra +1 removed
- endian_16lo8 (Cycle_Pointer, (Cycle_Pointer + 1) & 0xff);
- endian_16hi8 (Cycle_EffectiveAddress, envReadMemDataByte (Cycle_Pointer));
- }
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-// Fetch effective address high, add Y to low byte of effective address
-// Addressing Modes: Indirect indexed (post Y)
-void MOS6510::FetchHighEffAddrY (void)
-{
- uint8_t page;
- // Rev 1.05 (saw) - Call base Function
- FetchHighEffAddr ();
- page = endian_16hi8 (Cycle_EffectiveAddress);
- Cycle_EffectiveAddress += Register_Y;
-
-#ifdef MOS6510_ACCURATE_CYCLES
- // Handle page boundary crossing
- if (endian_16hi8 (Cycle_EffectiveAddress) == page)
- cycleCount++;
-#endif
-}
-
-// Same as above except dosen't worry about page crossing
-void MOS6510::FetchHighEffAddrY2 (void)
-{
- FetchHighEffAddr ();
- Cycle_EffectiveAddress += Register_Y;
-}
-
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-// Common Data Accessing Routines //
-// Data Accessing operations as described in 64doc by John West and //
-// Marko Makela //
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-
-void MOS6510::FetchEffAddrDataByte (void)
-{
- if (rdy && aec)
- Cycle_Data = envReadMemDataByte (Cycle_EffectiveAddress);
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-void MOS6510::PutEffAddrDataByte (void)
-{
- if (aec)
- envWriteMemByte (Cycle_EffectiveAddress, Cycle_Data);
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-// Used for Read Modify Write (RMW) instructions
-void MOS6510::FetchPutEffAddrDataByte (void)
-{
- FetchEffAddrDataByte ();
- PutEffAddrDataByte ();
-}
-
-// Push Program Counter Low Byte on stack, decrement S
-void MOS6510::PushLowPC (void)
-{
- if (aec)
- {
- uint_least16_t addr;
- addr = Register_StackPointer;
- endian_16hi8 (addr, SP_PAGE);
- envWriteMemByte (addr, endian_32lo8 (Register_ProgramCounter));
- Register_StackPointer--;
- }
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-// Push Program Counter High Byte on stack, decrement S
-void MOS6510::PushHighPC (void)
-{
- if (aec)
- {
- uint_least16_t addr;
- addr = Register_StackPointer;
- endian_16hi8 (addr, SP_PAGE);
- envWriteMemByte (addr, endian_32hi8 (Register_ProgramCounter));
- Register_StackPointer--;
- }
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-// Increment stack and pull program counter low byte from stack,
-void MOS6510::PopLowPC (void)
-{
- if (rdy && aec)
- {
- uint_least16_t addr;
- Register_StackPointer++;
- addr = Register_StackPointer;
- endian_16hi8 (addr, SP_PAGE);
- endian_16lo8 (Cycle_EffectiveAddress, envReadMemDataByte (addr));
- }
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-// Increment stack and pull program counter high byte from stack,
-void MOS6510::PopHighPC (void)
-{
- if (rdy && aec)
- {
- uint_least16_t addr;
- Register_StackPointer++;
- addr = Register_StackPointer;
- endian_16hi8 (addr, SP_PAGE);
- endian_16hi8 (Cycle_EffectiveAddress, envReadMemDataByte (addr));
- }
- else
- { // Address bus not ready
- stealCycle();
- }
-}
-
-void MOS6510::WasteCycle (void)
-{
-}
-
-void MOS6510::DebugCycle (void)
-{
- if (dodump)
- DumpState ();
- clock ();
-}
-
-
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-// Common Instruction Opcodes //
-// See and 6510 Assembly Book for more information on these instructions //
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-
-void MOS6510::brk_instr (void)
-{
- PushSR ();
- setFlagI (true);
- interrupts.irqRequest = false;
-
- // Check for an NMI, and switch over if pending
- if (interrupts.pending & iNMI)
- {
- event_clock_t cycles = eventContext.getTime (interrupts.nmiClock);
- if (cycles >= interrupts.delay)
- {
- interrupts.pending &= ~iNMI;
- instrCurrent = &interruptTable[oNMI];
- procCycle = &instrCurrent->cycle[cycleCount];
- }
- }
-}
-
-void MOS6510::cld_instr (void)
-{
- setFlagD (false);
-}
-
-void MOS6510::cli_instr (void)
-{
- bool oldFlagI = getFlagI ();
- setFlagI (false);
- // I flag change is delayed by 1 instruction
- interrupts.irqLatch = oldFlagI ^ getFlagI ();
- // Check to see if interrupts got re-enabled
- if (interrupts.irqs)
- interrupts.irqRequest = true;
-}
-
-void MOS6510::jmp_instr (void)
-{
- endian_32lo16 (Register_ProgramCounter, Cycle_EffectiveAddress);
-}
-
-void MOS6510::jsr_instr (void)
-{ // JSR uses absolute addressing in this emulation,
- // hence the -1. The real SID does not use this addressing
- // mode.
- Register_ProgramCounter--;
- PushHighPC ();
-}
-
-void MOS6510::pha_instr (void)
-{
- if (aec)
- {
- uint_least16_t addr;
- addr = Register_StackPointer;
- endian_16hi8 (addr, SP_PAGE);
- envWriteMemByte (addr, Register_Accumulator);
- Register_StackPointer--;
- }
- else
- { // Address bus not ready
- cycleCount--;
- return;
- }
-}
-
-/* RTI does not delay the IRQ I flag change as it is set 3 cycles before
- * the end of the opcode, and thus the 6510 has enough time to call the
- * interrupt routine as soon as the opcode ends, if necessary. */
-void MOS6510::rti_instr (void)
-{
-#ifdef MOS6510_DEBUG
- if (dodump)
- printf ("****************************************************\n\n");
-#endif
-
- endian_32lo16 (Register_ProgramCounter, Cycle_EffectiveAddress);
- interrupts.irqLatch = false;
-}
-
-void MOS6510::rts_instr (void)
-{
-/*
- // Hack - Output character to screen
- if (Register_ProgramCounter == 0xffd3)
- {
- char ch = _sidtune_CHRtab[Register_Accumulator];
- switch (ch)
- {
- case 0:
- break;
- case 1:
- printf (" ");
- fprintf (stderr, " ");
- case 0xd:
- printf ("\n");
- fprintf (stderr, "\n");
- filepos = 0;
- break;
- default:
- filetmp[filepos++] = ch;
- printf ("%c", ch);
- fprintf (stderr, "%c", ch);
- }
- }
-
- if (Register_ProgramCounter == 0xe170)
- {
- filetmp[filepos] = '\0';
- envLoadFile (filetmp);
- }
-*/
- endian_32lo16 (Register_ProgramCounter, Cycle_EffectiveAddress);
- Register_ProgramCounter++;
-}
-
-void MOS6510::sed_instr (void)
-{
- setFlagD (true);
-}
-
-void MOS6510::sei_instr (void)
-{
- bool oldFlagI = getFlagI ();
- setFlagI (true);
- // I flag change is delayed by 1 instruction
- interrupts.irqLatch = oldFlagI ^ getFlagI ();
- interrupts.irqRequest = false;
-}
-
-void MOS6510::sta_instr (void)
-{
- Cycle_Data = Register_Accumulator;
- PutEffAddrDataByte ();
-}
-
-void MOS6510::stx_instr (void)
-{
- Cycle_Data = Register_X;
- PutEffAddrDataByte ();
-}
-
-void MOS6510::sty_instr (void)
-{
- Cycle_Data = Register_Y;
- PutEffAddrDataByte ();
-}
-
-
-
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-// Common Instruction Undocumented Opcodes //
-// See documented 6502-nmo.opc by Adam Vardy for more details //
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-
-// Undocumented - This opcode stores the result of A AND X AND the high
-// byte of the target address of the operand +1 in memory.
-void MOS6510::axa_instr (void)
-{
- Cycle_Data = Register_X & Register_Accumulator & (endian_16hi8 (Cycle_EffectiveAddress) + 1);
- PutEffAddrDataByte ();
-}
-
-// Undocumented - AXS ANDs the contents of the A and X registers (without changing the
-// contents of either register) and stores the result in memory.
-// AXS does not affect any flags in the processor status register.
-void MOS6510::axs_instr (void)
-{
- Cycle_Data = Register_Accumulator & Register_X;
-}
-
-/* Not required - Operation performed By another method
-// Undocumented - HLT crashes the microprocessor. When this opcode is executed, program
-// execution ceases. No hardware interrupts will execute either. The author
-// has characterized this instruction as a halt instruction since this is the
-// most straightforward explanation for this opcode's behaviour. Only a reset
-// will restart execution. This opcode leaves no trace of any operation
-// performed! No registers affected.
-void MOS6510::hlt_instr (void)
-{
-}
-*/
-
-/* Not required - Operation performed By another method
-void MOS6510::nop_instr (void)
-{
-}
-*/
-
-/* Not required - Operation performed By another method
-void MOS6510::php_instr (void)
-{
-}
-*/
-
-// Undocumented - This opcode ANDs the contents of the Y register with <ab+1> and stores the
-// result in memory.
-void MOS6510::say_instr (void)
-{
- Cycle_Data = Register_Y & (endian_16hi8 (Cycle_EffectiveAddress) + 1);
-}
-
-/* Not required - Operation performed By another method
-// Undocumented - skip next byte.
-void MOS6510::skb_instr (void)
-{
- Register_ProgramCounter++;
-}
-*/
-
-/* Not required - Operation performed By another method
-// Undocumented - skip next word.
-void MOS6510::skw_instr (void)
-{
- Register_ProgramCounter += 2;
-}
-*/
-
-// Undocumented - This opcode ANDs the contents of the X register with <ab+1> and stores the
-// result in memory.
-void MOS6510::xas_instr (void)
-{
- Cycle_Data = Register_X & (endian_16hi8 (Cycle_EffectiveAddress) + 1);
-}
-
-
-#ifdef X86
-#include "MOS6510\CYCLE_~1\X86.CPP"
-//#include "MOS6510\CYCLE_BASED\X86.CPP"
-#else
-
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-// Generic Binary Coded Decimal Correction //
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-
-void MOS6510::Perform_ADC (void)
-{
- uint C = getFlagC ();
- uint A = Register_Accumulator;
- uint s = Cycle_Data;
- uint regAC2 = A + s + C;
-
- if (getFlagD ())
- { // BCD mode
- uint lo = (A & 0x0f) + (s & 0x0f) + C;
- uint hi = (A & 0xf0) + (s & 0xf0);
- if (lo > 0x09) lo += 0x06;
- if (lo > 0x0f) hi += 0x10;
-
- setFlagZ (regAC2);
- setFlagN (hi);
- setFlagV (((hi ^ A) & 0x80) && !((A ^ s) & 0x80));
- if (hi > 0x90) hi += 0x60;
-
- setFlagC (hi > 0xff);
- Register_Accumulator = (hi | (lo & 0x0f));
- }
- else
- { // Binary mode
- setFlagC (regAC2 > 0xff);
- setFlagV (((regAC2 ^ A) & 0x80) && !((A ^ s) & 0x80));
- setFlagsNZ (Register_Accumulator = regAC2 & 0xff);
- }
-}
-
-void MOS6510::Perform_SBC (void)
-{
- uint C = !getFlagC ();
- uint A = Register_Accumulator;
- uint s = Cycle_Data;
- uint regAC2 = A - s - C;
-
- setFlagC (regAC2 < 0x100);
- setFlagV (((regAC2 ^ A) & 0x80) && ((A ^ s) & 0x80));
- setFlagsNZ (regAC2);
-
- if (getFlagD ())
- { // BCD mode
- uint lo = (A & 0x0f) - (s & 0x0f) - C;
- uint hi = (A & 0xf0) - (s & 0xf0);
- if (lo & 0x10)
- {
- lo -= 0x06;
- hi -= 0x10;
- }
- if (hi & 0x100) hi -= 0x60;
- Register_Accumulator = (hi | (lo & 0x0f));
- }
- else
- { // Binary mode
- Register_Accumulator = regAC2 & 0xff;
- }
-}
-
-
-
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-// Generic Instruction Addressing Routines //
-//-------------------------------------------------------------------------/
-
-
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-// Generic Instruction Opcodes //
-// See and 6510 Assembly Book for more information on these instructions //
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-
-void MOS6510::adc_instr (void)
-{
- Perform_ADC ();
-}
-
-void MOS6510::and_instr (void)
-{
- setFlagsNZ (Register_Accumulator &= Cycle_Data);
-}
-
-void MOS6510::ane_instr (void)
-{
- setFlagsNZ (Register_Accumulator = (Register_Accumulator | 0xee) & Register_X & Cycle_Data);
-}
-
-void MOS6510::asl_instr (void)
-{
- setFlagC (Cycle_Data & 0x80);
- setFlagsNZ (Cycle_Data <<= 1);
-}
-
-void MOS6510::asla_instr (void)
-{
- setFlagC (Register_Accumulator & 0x80);
- setFlagsNZ (Register_Accumulator <<= 1);
-}
-
-void MOS6510::branch_instr (bool condition)
-{
- if (condition)
-#ifdef MOS6510_ACCURATE_CYCLES
- {
- uint8_t page;
- page = endian_32hi8 (Register_ProgramCounter);
- Register_ProgramCounter += (int8_t) Cycle_Data;
-
- // Handle page boundary crossing
- if (endian_32hi8 (Register_ProgramCounter) == page)
- {
- cycleCount++;
- interrupts.delay++;
- }
- }
- else
- {
- cycleCount += 2;
- }
-#else
- Register_ProgramCounter += (int8_t) Cycle_Data;
-#endif
-}
-
-void MOS6510::bcc_instr (void)
-{
- branch_instr (!getFlagC ());
-}
-
-void MOS6510::bcs_instr (void)
-{
- branch_instr (getFlagC ());
-}
-
-void MOS6510::beq_instr (void)
-{
- branch_instr (getFlagZ ());
-}
-
-void MOS6510::bit_instr (void)
-{
- setFlagZ (Register_Accumulator & Cycle_Data);
- setFlagN (Cycle_Data);
- setFlagV (Cycle_Data & 0x40);
-}
-
-void MOS6510::bmi_instr (void)
-{
- branch_instr (getFlagN ());
-}
-
-void MOS6510::bne_instr (void)
-{
- branch_instr (!getFlagZ ());
-}
-
-void MOS6510::bpl_instr(void)
-{
- branch_instr (!getFlagN ());
-}
-
-void MOS6510::bvc_instr (void)
-{
- branch_instr (!getFlagV ());
-}
-
-void MOS6510::bvs_instr (void)
-{
- branch_instr (getFlagV ());
-}
-
-void MOS6510::clc_instr (void)
-{
- setFlagC (false);
-}
-
-void MOS6510::clv_instr (void)
-{
- setFlagV (false);
-}
-
-void MOS6510::cmp_instr (void)
-{
- uint_least16_t tmp = (uint_least16_t) Register_Accumulator - Cycle_Data;
- setFlagsNZ (tmp);
- setFlagC (tmp < 0x100);
-}
-
-void MOS6510::cpx_instr (void)
-{
- uint_least16_t tmp = (uint_least16_t) Register_X - Cycle_Data;
- setFlagsNZ (tmp);
- setFlagC (tmp < 0x100);
-}
-
-void MOS6510::cpy_instr (void)
-{
- uint_least16_t tmp = (uint_least16_t) Register_Y - Cycle_Data;
- setFlagsNZ (tmp);
- setFlagC (tmp < 0x100);
-}
-
-void MOS6510::dec_instr (void)
-{
- setFlagsNZ (--Cycle_Data);
-}
-
-void MOS6510::dex_instr (void)
-{
- setFlagsNZ (--Register_X);
-}
-
-void MOS6510::dey_instr (void)
-{
- setFlagsNZ (--Register_Y);
-}
-
-void MOS6510::eor_instr (void)
-{
- setFlagsNZ (Register_Accumulator^= Cycle_Data);
-}
-
-void MOS6510::inc_instr (void)
-{
- setFlagsNZ (++Cycle_Data);
-}
-
-void MOS6510::inx_instr (void)
-{
- setFlagsNZ (++Register_X);
-}
-
-void MOS6510::iny_instr (void)
-{
- setFlagsNZ (++Register_Y);
-}
-
-void MOS6510::lda_instr (void)
-{
- setFlagsNZ (Register_Accumulator = Cycle_Data);
-}
-
-void MOS6510::ldx_instr (void)
-{
- setFlagsNZ (Register_X = Cycle_Data);
-}
-
-void MOS6510::ldy_instr (void)
-{
- setFlagsNZ (Register_Y = Cycle_Data);
-}
-
-void MOS6510::lsr_instr (void)
-{
- setFlagC (Cycle_Data & 0x01);
- setFlagsNZ (Cycle_Data >>= 1);
-}
-
-void MOS6510::lsra_instr (void)
-{
- setFlagC (Register_Accumulator & 0x01);
- setFlagsNZ (Register_Accumulator >>= 1);
-}
-
-void MOS6510::ora_instr (void)
-{
- setFlagsNZ (Register_Accumulator |= Cycle_Data);
-}
-
-void MOS6510::pla_instr (void)
-{
- if (rdy && aec)
- {
- uint_least16_t addr;
- Register_StackPointer++;
- addr = Register_StackPointer;
- endian_16hi8 (addr, SP_PAGE);
- setFlagsNZ (Register_Accumulator = envReadMemByte (addr));
- }
- else
- { // Address bus not ready
- cycleCount--;
- return;
- }
-}
-
-void MOS6510::rol_instr (void)
-{
- uint8_t tmp = Cycle_Data & 0x80;
- Cycle_Data <<= 1;
- if (getFlagC ()) Cycle_Data |= 0x01;
- setFlagsNZ (Cycle_Data);
- setFlagC (tmp);
-}
-
-void MOS6510::rola_instr (void)
-{
- uint8_t tmp = Register_Accumulator & 0x80;
- Register_Accumulator <<= 1;
- if (getFlagC ()) Register_Accumulator |= 0x01;
- setFlagsNZ (Register_Accumulator);
- setFlagC (tmp);
-}
-
-void MOS6510::ror_instr (void)
-{
- uint8_t tmp = Cycle_Data & 0x01;
- Cycle_Data >>= 1;
- if (getFlagC ()) Cycle_Data |= 0x80;
- setFlagsNZ (Cycle_Data);
- setFlagC (tmp);
-}
-
-void MOS6510::rora_instr (void)
-{
- uint8_t tmp = Register_Accumulator & 0x01;
- Register_Accumulator >>= 1;
- if (getFlagC ()) Register_Accumulator |= 0x80;
- setFlagsNZ (Register_Accumulator);
- setFlagC (tmp);
-}
-
-void MOS6510::sbx_instr (void)
-{
- uint tmp = (Register_X & Register_Accumulator) - Cycle_Data;
- setFlagsNZ (Register_X = tmp & 0xff);
- setFlagC (tmp < 0x100);
-}
-
-void MOS6510::sbc_instr (void)
-{
- Perform_SBC ();
-}
-
-void MOS6510::sec_instr (void)
-{
- setFlagC (true);
-}
-
-void MOS6510::shs_instr (void)
-{
- endian_16lo8 (Register_StackPointer, (Register_Accumulator & Register_X));
- Cycle_Data = (endian_16hi8 (Cycle_EffectiveAddress) + 1) & Register_StackPointer;
-}
-
-void MOS6510::tax_instr (void)
-{
- setFlagsNZ (Register_X = Register_Accumulator);
-}
-
-void MOS6510::tay_instr (void)
-{
- setFlagsNZ (Register_Y = Register_Accumulator);
-}
-
-void MOS6510::tsx_instr (void)
-{ // Rev 1.03 (saw) - Got these tsx and txs reversed
- setFlagsNZ (Register_X = endian_16lo8 (Register_StackPointer));
-}
-
-void MOS6510::txa_instr (void)
-{
- setFlagsNZ (Register_Accumulator = Register_X);
-}
-
-void MOS6510::txs_instr (void)
-{ // Rev 1.03 (saw) - Got these tsx and txs reversed
- endian_16lo8 (Register_StackPointer, Register_X);
-}
-
-void MOS6510::tya_instr (void)
-{
- setFlagsNZ (Register_Accumulator = Register_Y);
-}
-
-void MOS6510::illegal_instr (void)
-{
- printf ("\n\nILLEGAL INSTRUCTION, resetting emulation. **************\n");
- DumpState ();
- printf ("********************************************************\n");
- // Perform Environment Reset
- envReset ();
-}
-
-
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-// Generic Instruction Undocuemented Opcodes //
-// See documented 6502-nmo.opc by Adam Vardy for more details //
-//-------------------------------------------------------------------------//
-//-------------------------------------------------------------------------//
-
-// Undocumented - This opcode ANDs the contents of the A register with an immediate value and
-// then LSRs the result.
-void MOS6510::alr_instr (void)
-{
- Register_Accumulator &= Cycle_Data;
- setFlagC (Register_Accumulator & 0x01);
- setFlagsNZ (Register_Accumulator >>= 1);
-}
-
-// Undcouemented - ANC ANDs the contents of the A register with an immediate value and then
-// moves bit 7 of A into the Carry flag. This opcode works basically
-// identically to AND #immed. except that the Carry flag is set to the same
-// state that the Negative flag is set to.
-void MOS6510::anc_instr (void)
-{
- setFlagsNZ (Register_Accumulator &= Cycle_Data);
- setFlagC (getFlagN ());
-}
-
-// Undocumented - This opcode ANDs the contents of the A register with an immediate value and
-// then RORs the result (Implementation based on that of Frodo C64 Emulator)
-void MOS6510::arr_instr (void)
-{
- uint8_t data = Cycle_Data & Register_Accumulator;
- Register_Accumulator = data >> 1;
- if (getFlagC ()) Register_Accumulator |= 0x80;
-
- if (getFlagD ())
- {
- setFlagN (0);
- if (getFlagC ()) setFlagN (1 << SR_NEGATIVE);
- setFlagZ (Register_Accumulator);
- setFlagV ((data ^ Register_Accumulator) & 0x40);
-
- if ((data & 0x0f) + (data & 0x01) > 5)
- Register_Accumulator = Register_Accumulator & 0xf0 | (Register_Accumulator + 6) & 0x0f;
- setFlagC (((data + (data & 0x10)) & 0x1f0) > 0x50);
- if (getFlagC ())
- Register_Accumulator += 0x60;
- }
- else
- {
- setFlagsNZ (Register_Accumulator);
- setFlagC (Register_Accumulator & 0x40);
- setFlagV ((Register_Accumulator & 0x40) ^ ((Register_Accumulator & 0x20) << 1));
- }
-}
-
-// Undocumented - This opcode ASLs the contents of a memory location and then ORs the result
-// with the accumulator.
-void MOS6510::aso_instr (void)
-{
- setFlagC (Cycle_Data & 0x80);
- Cycle_Data <<= 1;
- setFlagsNZ (Register_Accumulator |= Cycle_Data);
-}
-
-// Undocumented - This opcode DECs the contents of a memory location and then CMPs the result
-// with the A register.
-void MOS6510::dcm_instr (void)
-{
- uint_least16_t tmp;
- Cycle_Data--;
- tmp = (uint_least16_t) Register_Accumulator - Cycle_Data;
- setFlagsNZ (tmp);
- setFlagC (tmp < 0x100);
-}
-
-// Undocumented - This opcode INCs the contents of a memory location and then SBCs the result
-// from the A register.
-void MOS6510::ins_instr (void)
-{
- Cycle_Data++;
- Perform_SBC ();
-}
-
-// Undocumented - This opcode ANDs the contents of a memory location with the contents of the
-// stack pointer register and stores the result in the accumulator, the X
-// register, and the stack pointer. Affected flags: N Z.
-void MOS6510::las_instr (void)
-{
- setFlagsNZ (Cycle_Data &= endian_16lo8 (Register_StackPointer));
- Register_Accumulator = Cycle_Data;
- Register_X = Cycle_Data;
- Register_StackPointer = Cycle_Data;
-}
-
-// Undocumented - This opcode loads both the accumulator and the X register with the contents
-// of a memory location.
-void MOS6510::lax_instr (void)
-{
- setFlagsNZ (Register_Accumulator = Register_X = Cycle_Data);
-}
-
-// Undocumented - LSE LSRs the contents of a memory location and then EORs the result with
-// the accumulator.
-void MOS6510::lse_instr (void)
-{
- setFlagC (Cycle_Data & 0x01);
- Cycle_Data >>= 1;
- setFlagsNZ (Register_Accumulator ^= Cycle_Data);
-}
-
-// Undocumented - This opcode ORs the A register with #xx, ANDs the result with an immediate
-// value, and then stores the result in both A and X.
-// xx may be EE,EF,FE, OR FF, but most emulators seem to use EE
-void MOS6510::oal_instr (void)
-{
- setFlagsNZ (Register_X = (Register_Accumulator = (Cycle_Data & (Register_Accumulator | 0xee))));
-}
-
-// Undocumented - RLA ROLs the contents of a memory location and then ANDs the result with
-// the accumulator.
-void MOS6510::rla_instr (void)
-{
- uint8_t tmp = Cycle_Data & 0x80;
- Cycle_Data = Cycle_Data << 1;
- if (getFlagC ()) Cycle_Data |= 0x01;
- setFlagC (tmp);
- setFlagsNZ (Register_Accumulator &= Cycle_Data);
-}
-
-// Undocumented - RRA RORs the contents of a memory location and then ADCs the result with
-// the accumulator.
-void MOS6510::rra_instr (void)
-{
- uint8_t tmp = Cycle_Data & 0x01;
- Cycle_Data >>= 1;
- if (getFlagC ()) Cycle_Data |= 0x80;
- setFlagC (tmp);
- Perform_ADC ();
-}
-
-// Undocumented - This opcode ANDs the contents of the A and X registers (without changing
-// the contents of either register) and transfers the result to the stack
-// pointer. It then ANDs that result with the contents of the high byte of
-// the target address of the operand +1 and stores that final result in
-// memory.
-void MOS6510::tas_instr (void)
-{
- endian_16lo8 (Register_StackPointer, Register_Accumulator & Register_X);
- uint_least16_t tmp = Register_StackPointer & (Cycle_EffectiveAddress + 1);
- Cycle_Data = (signed) endian_16lo8 (tmp);
-}
-
-#endif // X86
-
-
-//-------------------------------------------------------------------------//
-// Initialise and create CPU Chip //
-
-//MOS6510::MOS6510 (model_t _model, const char *id)
-MOS6510::MOS6510 (EventContext *context)
-:eventContext(*context),
- Event("CPU")
-{
- struct ProcessorOperations *instr;
- uint8_t legalMode = true;
- uint8_t legalInstr = true;
- uint i, pass;
-
- //----------------------------------------------------------------------
- // Build up the processor instruction table
- for (i = 0; i < 0x100; i++)
- {
-#if MOS6510_DEBUG > 1
- printf ("Building Command %d[%02x]..", i, i);
-#endif
-
- // Pass 1 allocates the memory, Pass 2 builds the instruction
- instr = &instrTable[i];
- instr->cycle = NULL;
-
- for (pass = 0; pass < 2; pass++)
- {
- enum {WRITE = 0, RMW = 1, READ = 2};
- int access = WRITE;
- cycleCount = -1;
- legalMode = true;
- legalInstr = true;
- if (pass) procCycle = instr->cycle;
-
- switch (i)
- {
- // Accumulator or Implied addressing
- case ASLn: case CLCn: case CLDn: case CLIn: case CLVn: case DEXn:
- case DEYn: case INXn: case INYn: case LSRn: case NOPn_: case PHAn:
- case PHPn: case PLAn: case PLPn: case ROLn: case RORn: case RTIn:
- case RTSn: case SECn: case SEDn: case SEIn: case TAXn: case TAYn:
- case TSXn: case TXAn: case TXSn: case TYAn:
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- break;
-
- // Immediate and Relative Addressing Mode Handler
- case ADCb: case ANDb: case ANCb_: case ANEb: case ASRb: case ARRb:
- case BCCr: case BCSr: case BEQr: case BMIr: case BNEr: case BPLr:
- case BRKn: case BVCr: case BVSr: case CMPb: case CPXb: case CPYb:
- case EORb: case LDAb: case LDXb: case LDYb: case LXAb: case NOPb_:
- case ORAb: case SBCb_: case SBXb:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchDataByte;
- break;
-
- // Zero Page Addressing Mode Handler - Read & RMW
- case ADCz: case ANDz: case BITz: case CMPz: case CPXz: case CPYz:
- case EORz: case LAXz: case LDAz: case LDXz: case LDYz: case ORAz:
- case NOPz_: case SBCz:
- access++;
- case ASLz: case DCPz: case DECz: case INCz: case ISBz: case LSRz:
- case ROLz: case RORz: case SREz: case SLOz: case RLAz: case RRAz:
- access++;
- case SAXz: case STAz: case STXz: case STYz:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddr;
- if (access == READ) {
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte;
- } else if (access == RMW) {
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchPutEffAddrDataByte;
- }
- break;
-
- // Zero Page with X Offset Addressing Mode Handler
- case ADCzx: case ANDzx: case CMPzx: case EORzx: case LDAzx: case LDYzx:
- case NOPzx_: case ORAzx: case SBCzx:
- access++;
- case ASLzx: case DCPzx: case DECzx: case INCzx: case ISBzx: case LSRzx:
- case RLAzx: case ROLzx: case RORzx: case RRAzx: case SLOzx: case SREzx:
- access++;
- case STAzx: case STYzx:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddrX;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- if (access == READ) {
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte;
- } else if (access == RMW) {
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchPutEffAddrDataByte;
- }
- break;
-
- // Zero Page with Y Offset Addressing Mode Handler
- case LDXzy: case LAXzy:
- access = READ;
- case STXzy: case SAXzy:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddrY;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- if (access == READ) {
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte;
- }
- break;
-
- // Absolute Addressing Mode Handler
- case ADCa: case ANDa: case BITa: case CMPa: case CPXa: case CPYa:
- case EORa: case LAXa: case LDAa: case LDXa: case LDYa: case NOPa:
- case ORAa: case SBCa:
- access++;
- case ASLa: case DCPa: case DECa: case INCa: case ISBa: case LSRa:
- case ROLa: case RORa: case SLOa: case SREa: case RLAa: case RRAa:
- access++;
- case JMPw: case JSRw: case SAXa: case STAa: case STXa: case STYa:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighAddr;
- if (access == READ) {
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte;
- } else if (access == RMW) {
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchPutEffAddrDataByte;
- }
- break;
-
- // Absolute With X Offset Addressing Mode Handler (Read)
- case ADCax: case ANDax: case CMPax: case EORax: case LDAax:
- case LDYax: case NOPax_: case ORAax: case SBCax:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighAddrX;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte;
- break;
-
- // Absolute X (No page crossing handled)
- case ASLax: case DCPax: case DECax: case INCax: case ISBax:
- case LSRax: case RLAax: case ROLax: case RORax: case RRAax:
- case SLOax: case SREax:
- access = RMW;
- case SHYax: case STAax:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighAddrX2;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- if (access == RMW) {
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchPutEffAddrDataByte;
- }
- break;
-
- // Absolute With Y Offset Addresing Mode Handler (Read)
- case ADCay: case ANDay: case CMPay: case EORay: case LASay:
- case LAXay: case LDAay: case LDXay: case ORAay: case SBCay:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighAddrY;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte;
- break;
-
- // Absolute Y (No page crossing handled)
- case DCPay: case ISBay: case RLAay: case RRAay: case SLOay:
- case SREay:
- access = RMW;
- case SHAay: case SHSay: case SHXay: case STAay:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowAddr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighAddrY2;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- if (access == RMW) {
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchPutEffAddrDataByte;
- }
- break;
-
- // Absolute Indirect Addressing Mode Handler
- case JMPi:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowPointer;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighPointer;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowEffAddr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighEffAddr;
- break;
-
- // Indexed with X Preinc Addressing Mode Handler
- case ADCix: case ANDix: case CMPix: case EORix: case LAXix: case LDAix:
- case ORAix: case SBCix:
- access++;
- case DCPix: case ISBix: case SLOix: case SREix: case RLAix: case RRAix:
- access++;
- case SAXix: case STAix:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowPointer;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowPointerX;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowEffAddr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighEffAddr;
- if (access == READ) {
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte;
- } else if (access == RMW) {
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchPutEffAddrDataByte;
- }
- break;
-
- // Indexed with Y Postinc Addressing Mode Handler (Read)
- case ADCiy: case ANDiy: case CMPiy: case EORiy: case LAXiy:
- case LDAiy: case ORAiy: case SBCiy:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowPointer;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowEffAddr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighEffAddrY;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchEffAddrDataByte;
- break;
-
- // Indexed Y (No page crossing handled)
- case DCPiy: case ISBiy: case RLAiy: case RRAiy: case SLOiy:
- case SREiy:
- access = RMW;
- case SHAiy: case STAiy:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowPointer;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchLowEffAddr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchHighEffAddrY2;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- if (access == RMW) {
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchPutEffAddrDataByte;
- }
- break;
-
- default:
- legalMode = false;
- break;
- }
-
-#ifdef MOS6510_DEBUG
- if (legalMode)
- {
- cycleCount++;
- if (pass) procCycle[cycleCount] = &MOS6510::DebugCycle;
- }
-#endif // MOS6510_DEBUG
-
- //---------------------------------------------------------------------------------------
- // Addressing Modes Finished, other cycles are instruction dependent
- switch(i)
- {
- case ADCz: case ADCzx: case ADCa: case ADCax: case ADCay: case ADCix:
- case ADCiy: case ADCb:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::adc_instr;
- break;
-
- case ANCb_:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::anc_instr;
- break;
-
- case ANDz: case ANDzx: case ANDa: case ANDax: case ANDay: case ANDix:
- case ANDiy: case ANDb:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::and_instr;
- break;
-
- case ANEb: // Also known as XAA
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::ane_instr;
- break;
-
- case ARRb:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::arr_instr;
- break;
-
- case ASLn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::asla_instr;
- break;
-
- case ASLz: case ASLzx: case ASLa: case ASLax:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::asl_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case ASRb: // Also known as ALR
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::alr_instr;
- break;
-
- case BCCr:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bcc_instr;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- break;
-
- case BCSr:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bcs_instr;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- break;
-
- case BEQr:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::beq_instr;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- break;
-
- case BITz: case BITa:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bit_instr;
- break;
-
- case BMIr:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bmi_instr;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- break;
-
- case BNEr:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bne_instr;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- break;
-
- case BPLr:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bpl_instr;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- break;
-
- case BRKn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushHighPC;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushLowPC;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::brk_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::IRQ1Request;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::IRQ2Request;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchOpcode;
- break;
-
- case BVCr:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bvc_instr;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- break;
-
- case BVSr:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::bvs_instr;
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- break;
-
- case CLCn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::clc_instr;
- break;
-
- case CLDn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::cld_instr;
- break;
-
- case CLIn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::cli_instr;
- break;
-
- case CLVn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::clv_instr;
- break;
-
- case CMPz: case CMPzx: case CMPa: case CMPax: case CMPay: case CMPix:
- case CMPiy: case CMPb:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::cmp_instr;
- break;
-
- case CPXz: case CPXa: case CPXb:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::cpx_instr;
- break;
-
- case CPYz: case CPYa: case CPYb:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::cpy_instr;
- break;
-
- case DCPz: case DCPzx: case DCPa: case DCPax: case DCPay: case DCPix:
- case DCPiy: // Also known as DCM
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::dcm_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case DECz: case DECzx: case DECa: case DECax:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::dec_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case DEXn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::dex_instr;
- break;
-
- case DEYn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::dey_instr;
- break;
-
- case EORz: case EORzx: case EORa: case EORax: case EORay: case EORix:
- case EORiy: case EORb:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::eor_instr;
- break;
-
-/* HLT // Also known as JAM
- case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52:
- case 0x62: case 0x72: case 0x92: case 0xb2: case 0xd2: case 0xf2:
- case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52:
- case 0x62: case 0x72: case 0x92: case 0xb2: case 0xd2: case 0xf2:
- cycleCount++; if (pass) procCycle[cycleCount] = hlt_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-*/
-
- case INCz: case INCzx: case INCa: case INCax:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::inc_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case INXn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::inx_instr;
- break;
-
- case INYn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::iny_instr;
- break;
-
- case ISBz: case ISBzx: case ISBa: case ISBax: case ISBay: case ISBix:
- case ISBiy: // Also known as INS
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::ins_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case JMPw: case JMPi:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::jmp_instr;
- break;
-
- case JSRw:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::jsr_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushLowPC;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::jmp_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case LASay:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::las_instr;
- break;
-
- case LAXz: case LAXzy: case LAXa: case LAXay: case LAXix: case LAXiy:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::lax_instr;
- break;
-
- case LDAz: case LDAzx: case LDAa: case LDAax: case LDAay: case LDAix:
- case LDAiy: case LDAb:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::lda_instr;
- break;
-
- case LDXz: case LDXzy: case LDXa: case LDXay: case LDXb:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::ldx_instr;
- break;
-
- case LDYz: case LDYzx: case LDYa: case LDYax: case LDYb:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::ldy_instr;
- break;
-
- case LSRn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::lsra_instr;
- break;
-
- case LSRz: case LSRzx: case LSRa: case LSRax:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::lsr_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case NOPn_: case NOPb_:
- // Should not be required!
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case NOPz_: case NOPzx_: case NOPa: case NOPax_:
- // NOPb NOPz NOPzx - Also known as SKBn
- // NOPa NOPax - Also known as SKWn
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case LXAb: // Also known as OAL
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::oal_instr;
- break;
-
- case ORAz: case ORAzx: case ORAa: case ORAax: case ORAay: case ORAix:
- case ORAiy: case ORAb:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::ora_instr;
- break;
-
- case PHAn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::pha_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case PHPn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushSR;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case PLAn:
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::pla_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case PLPn:
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PopSR;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case RLAz: case RLAzx: case RLAix: case RLAa: case RLAax: case RLAay:
- case RLAiy:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::rla_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case ROLn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::rola_instr;
- break;
-
- case ROLz: case ROLzx: case ROLa: case ROLax:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::rol_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case RORn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::rora_instr;
- break;
-
- case RORz: case RORzx: case RORa: case RORax:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::ror_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case RRAa: case RRAax: case RRAay: case RRAz: case RRAzx: case RRAix:
- case RRAiy:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::rra_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case RTIn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PopSR;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PopLowPC;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PopHighPC;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::rti_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case RTSn:
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PopLowPC;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PopHighPC;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::rts_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case SAXz: case SAXzy: case SAXa: case SAXix: // Also known as AXS
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::axs_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- break;
-
- case SBCz: case SBCzx: case SBCa: case SBCax: case SBCay: case SBCix:
- case SBCiy: case SBCb_:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::sbc_instr;
- break;
-
- case SBXb:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::sbx_instr;
- break;
-
- case SECn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::sec_instr;
- break;
-
- case SEDn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::sed_instr;
- break;
-
- case SEIn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::sei_instr;
- break;
-
- case SHAay: case SHAiy: // Also known as AXA
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::axa_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case SHSay: // Also known as TAS
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::shs_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- break;
-
- case SHXay: // Also known as XAS
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::xas_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- break;
-
- case SHYax: // Also known as SAY
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::say_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- break;
-
- case SLOz: case SLOzx: case SLOa: case SLOax: case SLOay: case SLOix:
- case SLOiy: // Also known as ASO
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::aso_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case SREz: case SREzx: case SREa: case SREax: case SREay: case SREix:
- case SREiy: // Also known as LSE
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::lse_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PutEffAddrDataByte;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case STAz: case STAzx: case STAa: case STAax: case STAay: case STAix:
- case STAiy:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::sta_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case STXz: case STXzy: case STXa:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::stx_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case STYz: case STYzx: case STYa:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::sty_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- break;
-
- case TAXn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::tax_instr;
- break;
-
- case TAYn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::tay_instr;
- break;
-
- case TSXn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::tsx_instr;
- break;
-
- case TXAn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::txa_instr;
- break;
-
- case TXSn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::txs_instr;
- break;
-
- case TYAn:
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::tya_instr;
- break;
-
- default:
- legalInstr = false;
- break;
- }
-
- if (!(legalMode || legalInstr))
- {
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::illegal_instr;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- }
- else if (!(legalMode && legalInstr))
- {
- printf ("\nInstruction 0x%x: Not built correctly.\n\n", i);
- exit(1);
- }
-
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::NextInstr;
- cycleCount++;
- if (!pass)
- { // Pass 1 - Allocate Memory
- if (cycleCount)
- {
-#if defined(_MSC_VER) && (_MSC_VER <= _MSC_VER_BAD_NEW)
- typedef void (MOS6510::*ptr2cycle) (void);
- instr->cycle = (ptr2cycle*) new char[sizeof (ptr2cycle) *cycleCount];
-#else
-# ifdef HAVE_EXCEPTIONS
- instr->cycle = new(std::nothrow) (void (MOS6510::*[cycleCount]) (void));
-# else
- instr->cycle = new (void (MOS6510::*[cycleCount]) (void));
-# endif
-#endif // _MSC_VER
- if (!instr->cycle)
- goto MOS6510_MemAllocFailed;
- }
- }
- else
- instr->opcode = i;
-
-#if MOS6510_DEBUG > 1
- printf (".");
-#endif
- }
-
- instr->cycles = cycleCount;
-#if MOS6510_DEBUG > 1
- printf ("Done [%d Cycles]\n", cycleCount);
-#endif
- }
-
- //----------------------------------------------------------------------
- // Build interrupts
- for (i = 0; i < 3; i++)
- {
-#if MOS6510_DEBUG > 1
- printf ("Building Interrupt %d[%02x]..", i, i);
-#endif
-
- // Pass 1 allocates the memory, Pass 2 builds the interrupt
- instr = &interruptTable[i];
- instr->cycle = NULL;
- instr->opcode = 0;
-
- for (int pass = 0; pass < 2; pass++)
- {
- cycleCount = -1;
- if (pass) procCycle = instr->cycle;
-
- switch (i)
- {
- case oRST:
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::RSTRequest;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchOpcode;
- break;
-
- case oNMI:
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushHighPC;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushLowPC;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::IRQRequest;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::NMIRequest;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::NMI1Request;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchOpcode;
- break;
-
- case oIRQ:
-#ifdef MOS6510_ACCURATE_CYCLES
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::WasteCycle;
-#endif
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushHighPC;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::PushLowPC;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::IRQRequest;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::IRQ1Request;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::IRQ2Request;
- cycleCount++; if (pass) procCycle[cycleCount] = &MOS6510::FetchOpcode;
- break;
- }
-
- cycleCount++;
- if (!pass)
- { // Pass 1 - Allocate Memory
- if (cycleCount)
- {
-#if defined(_MSC_VER) && (_MSC_VER <= _MSC_VER_BAD_NEW)
- typedef void (MOS6510::*ptr2cycle) (void);
- instr->cycle = (ptr2cycle*) new char[sizeof (ptr2cycle) *cycleCount];
-#else
-# ifdef HAVE_EXCEPTIONS
- instr->cycle = new(std::nothrow) (void (MOS6510::*[cycleCount]) (void));
-# else
- instr->cycle = new (void (MOS6510::*[cycleCount]) (void));
-# endif
-#endif // _MSC_VER
- if (!instr->cycle)
- goto MOS6510_MemAllocFailed;
- }
- }
-
-#if MOS6510_DEBUG > 1
- printf (".");
-#endif
- }
-
- instr->cycles = cycleCount;
-#if MOS6510_DEBUG > 1
- printf ("Done [%d Cycles]\n", cycleCount);
-#endif
- }
-
- // Intialise Processor Registers
- Register_Accumulator = 0;
- Register_X = 0;
- Register_Y = 0;
-
- Cycle_EffectiveAddress = 0;
- Cycle_Data = 0;
- fetchCycle[0] = &MOS6510::NextInstr;
-
- dodump = false;
- Initialise ();
-return;
-
-MOS6510_MemAllocFailed:
- printf ("Unable to allocate enough memory.\n\n");
-exit (-1);
-}
-
-MOS6510::~MOS6510 ()
-{
- struct ProcessorOperations *instr;
- uint i;
-
- // Remove Opcodes
- for (i = 0; i < 0x100; i++)
- {
- instr = &instrTable[i];
- if (instr->cycle != NULL) delete [] instr->cycle;
- }
-
- // Remove Interrupts
- for (i = 0; i < 3; i++)
- {
- instr = &interruptTable[i];
- if (instr->cycle != NULL) delete [] instr->cycle;
- }
-}
-
-
-//-------------------------------------------------------------------------//
-// Initialise CPU Emulation (Registers) //
-void MOS6510::Initialise (void)
-{
- // Reset stack
- Register_StackPointer = endian_16 (SP_PAGE, 0xFF);
-
- // Reset Cycle Count
- cycleCount = 0;
- procCycle = fetchCycle;
-
- // Reset Status Register
- Register_Status = (1 << SR_NOTUSED) | (1 << SR_BREAK);
- // FLAGS are set from data directly and do not require
- // being calculated first before setting. E.g. if you used
- // SetFlags (0), N flag would = 0, and Z flag would = 1.
- setFlagsNZ (1);
- setFlagC (false);
- setFlagV (false);
-
- // Set PC to some value
- Register_ProgramCounter = 0;
- // IRQs pending check
- interrupts.irqLatch = false;
- interrupts.irqRequest = false;
- if (interrupts.irqs)
- interrupts.irqRequest = true;
-
- // Signals
- aec = true;
- rdy = true;
-
- m_blocked = false;
- eventContext.schedule (this, 1);
-}
-
-//-------------------------------------------------------------------------//
-// Reset CPU Emulation //
-void MOS6510::reset (void)
-{
- // Reset Interrupts
- interrupts.pending = false;
- interrupts.irqs = 0;
- interrupts.delay = MOS6510_INTERRUPT_DELAY;
-
- // Internal Stuff
- Initialise ();
-
- // Requires External Bits
- // Read from reset vector for program entry point
- endian_16lo8 (Cycle_EffectiveAddress, envReadMemDataByte (0xFFFC));
- endian_16hi8 (Cycle_EffectiveAddress, envReadMemDataByte (0xFFFD));
- Register_ProgramCounter = Cycle_EffectiveAddress;
-// filepos = 0;
-}
-
-//-------------------------------------------------------------------------//
-// Module Credits //
-void MOS6510::credits (char *sbuffer)
-{ // Copy credits to buffer
- sprintf (sbuffer, "%sModule : MOS6510 Cycle Exact Emulation\n", sbuffer);
- sprintf (sbuffer, "%sWritten By : %s\n", sbuffer, MOS6510_AUTHOR);
- sprintf (sbuffer, "%sVersion : %s\n", sbuffer, MOS6510_VERSION);
- sprintf (sbuffer, "%sReleased : %s\n", sbuffer, MOS6510_DATE);
- sprintf (sbuffer, "%sEmail : %s\n", sbuffer, MOS6510_EMAIL);
-}