summaryrefslogtreecommitdiff
path: root/plugins/sid/sidplay-libs/libsidplay/src/mos6510
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/sid/sidplay-libs/libsidplay/src/mos6510')
-rw-r--r--plugins/sid/sidplay-libs/libsidplay/src/mos6510/Makefile.am9
-rw-r--r--plugins/sid/sidplay-libs/libsidplay/src/mos6510/Makefile.in426
-rw-r--r--plugins/sid/sidplay-libs/libsidplay/src/mos6510/conf6510.h45
-rw-r--r--plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/mos6510c.h311
-rw-r--r--plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/mos6510c.i2562
-rw-r--r--plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/sid6510c.h118
-rw-r--r--plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/sid6510c.i409
-rw-r--r--plugins/sid/sidplay-libs/libsidplay/src/mos6510/mos6510.cpp534
-rw-r--r--plugins/sid/sidplay-libs/libsidplay/src/mos6510/mos6510.h75
-rw-r--r--plugins/sid/sidplay-libs/libsidplay/src/mos6510/opcodes.h331
10 files changed, 4820 insertions, 0 deletions
diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/Makefile.am b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/Makefile.am
new file mode 100644
index 00000000..27acc569
--- /dev/null
+++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/Makefile.am
@@ -0,0 +1,9 @@
+
+EXTRA_DIST = cycle_based
+
+noinst_LTLIBRARIES = libmos6510.la
+
+libmos6510_la_SOURCES = mos6510.cpp mos6510.h conf6510.h opcodes.h
+
+# Remove bad default includes
+DEFAULT_INCLUDES=
diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/Makefile.in b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/Makefile.in
new file mode 100644
index 00000000..9af93a74
--- /dev/null
+++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/Makefile.in
@@ -0,0 +1,426 @@
+# Makefile.in generated by automake 1.7.1 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_triplet = @host@
+ACLOCAL = @ACLOCAL@
+ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBVERSION = @LIBVERSION@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SID_HAVE_BOOL = @SID_HAVE_BOOL@
+SID_HAVE_STDBOOL_H = @SID_HAVE_STDBOOL_H@
+SID_SIZEOF_CHAR = @SID_SIZEOF_CHAR@
+SID_SIZEOF_INT = @SID_SIZEOF_INT@
+SID_SIZEOF_LONG_INT = @SID_SIZEOF_LONG_INT@
+SID_SIZEOF_SHORT_INT = @SID_SIZEOF_SHORT_INT@
+SID_WORDS_ENDIANESS = @SID_WORDS_ENDIANESS@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builders = @builders@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+
+EXTRA_DIST = cycle_based
+
+noinst_LTLIBRARIES = libmos6510.la
+
+libmos6510_la_SOURCES = mos6510.cpp mos6510.h conf6510.h opcodes.h
+
+# Remove bad default includes
+DEFAULT_INCLUDES =
+subdir = src/mos6510
+mkinstalldirs = $(SHELL) $(top_srcdir)/unix/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/unix/config.h
+CONFIG_CLEAN_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+
+libmos6510_la_LDFLAGS =
+libmos6510_la_LIBADD =
+am_libmos6510_la_OBJECTS = mos6510.lo
+libmos6510_la_OBJECTS = $(am_libmos6510_la_OBJECTS)
+depcomp = $(SHELL) $(top_srcdir)/unix/depcomp
+am__depfiles_maybe = depfiles
+@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/mos6510.Plo
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
+ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+DIST_SOURCES = $(libmos6510_la_SOURCES)
+DIST_COMMON = Makefile.am Makefile.in
+SOURCES = $(libmos6510_la_SOURCES)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .lo .o .obj
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/mos6510/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" = "$$p" && dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libmos6510.la: $(libmos6510_la_OBJECTS) $(libmos6510_la_DEPENDENCIES)
+ $(CXXLINK) $(libmos6510_la_LDFLAGS) $(libmos6510_la_OBJECTS) $(libmos6510_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mos6510.Plo@am__quote@
+
+distclean-depend:
+ -rm -rf ./$(DEPDIR)
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
+@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
+@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
+@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@am__fastdepCXX_TRUE@ fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ if $(CXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
+@am__fastdepCXX_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`; \
+@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
+@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@am__fastdepCXX_TRUE@ fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ if $(LTCXXCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
+@am__fastdepCXX_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
+@am__fastdepCXX_TRUE@ then mv "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; \
+@am__fastdepCXX_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@am__fastdepCXX_TRUE@ fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+
+ETAGS = etags
+ETAGSFLAGS =
+
+CTAGS = ctags
+CTAGSFLAGS =
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$tags$$unique" \
+ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique
+
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkinstalldirs) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES)
+
+installdirs:
+
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f Makefile $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+
+distclean-am: clean-am distclean-compile distclean-depend \
+ distclean-generic distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-depend distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am info \
+ info-am install install-am install-data install-data-am \
+ install-exec install-exec-am install-info install-info-am \
+ install-man install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+ uninstall-am uninstall-info-am
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/conf6510.h b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/conf6510.h
new file mode 100644
index 00000000..6a1ea0bd
--- /dev/null
+++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/conf6510.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ config.h - description
+ -------------------
+ begin : Thu May 11 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: conf6510.h,v $
+ * Revision 1.3 2001/03/19 23:41:51 s_a_white
+ * Better support for global debug.
+ *
+ * Revision 1.2 2000/12/11 19:03:16 s_a_white
+ * AC99 Update.
+ *
+ ***************************************************************************/
+
+#ifndef _conf6510_h_
+#define _conf6510_h_
+
+#include "sidconfig.h"
+
+#define MOS6510_CYCLE_BASED
+#define MOS6510_ACCURATE_CYCLES
+#define MOS6510_SIDPLAY
+//#define MOS6510_STATE_6510
+//#define MOS6510_DEBUG 1
+
+// Support global debug option
+#ifdef DEBUG
+# ifndef MOS6510_DEBUG
+# define MOS6510_DEBUG DEBUG
+# endif
+#endif
+
+#endif // _conf6510_h_
diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/mos6510c.h b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/mos6510c.h
new file mode 100644
index 00000000..9a046d2e
--- /dev/null
+++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/mos6510c.h
@@ -0,0 +1,311 @@
+/***************************************************************************
+ mos6510c.h - Cycle Accurate 6510 Emulation
+ -------------------
+ begin : Thu May 11 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.h,v $
+ * Revision 1.15 2002/11/28 20:35:06 s_a_white
+ * Reduced number of thrown exceptions when dma occurs.
+ *
+ * Revision 1.14 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.13 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.12 2002/11/19 22:57:33 s_a_white
+ * Initial support for external DMA to steal cycles away from the CPU.
+ *
+ * Revision 1.11 2002/11/01 17:35:27 s_a_white
+ * Frame based support for old sidplay1 modes.
+ *
+ * Revision 1.10 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.9 2001/07/14 16:48:03 s_a_white
+ * cycleCount and related must roject.Syn
+ *
+ * Revision 1.8 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.7 2001/03/28 21:17:34 s_a_white
+ * Added support for proper RMW instructions.
+ *
+ * Revision 1.6 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.5 2001/03/19 23:48:21 s_a_white
+ * Interrupts made virtual to allow for redefintion for Sidplay1 compatible
+ * interrupts.
+ *
+ * Revision 1.4 2001/03/09 22:28:03 s_a_white
+ * Speed optimisation update.
+ *
+ * Revision 1.3 2001/02/13 21:03:33 s_a_white
+ * Changed inlines to non-inlines due to function bodies not being in header.
+ *
+ * Revision 1.2 2000/12/11 19:04:32 s_a_white
+ * AC99 Update.
+ *
+ ***************************************************************************/
+
+#ifndef _mos6510c_h_
+#define _mos6510c_h_
+
+#include "sidtypes.h"
+#include "sidendian.h"
+
+
+class MOS6510: public C64Environment, public Event
+{
+private:
+ // External signals
+ bool aec; /* Address Controller, blocks all */
+ bool rdy; /* Bus Access, blocks reads */
+ bool m_blocked;
+
+protected:
+ bool dodump;
+ EventContext &eventContext;
+
+ // Declare processor operations
+ struct ProcessorOperations
+ {
+ void (MOS6510::**cycle)(void);
+ uint cycles;
+ uint_least8_t opcode;
+ };
+
+ void (MOS6510::*fetchCycle[1]) (void);
+ struct ProcessorOperations instrTable[0x100];
+ struct ProcessorOperations interruptTable[3];
+ struct ProcessorOperations *instrCurrent;
+
+ uint_least16_t instrStartPC;
+ uint_least8_t instrOpcode;
+ void (MOS6510::**procCycle) (void);
+ int_least8_t lastAddrCycle;
+ int_least8_t cycleCount;
+
+ // Pointers to the current instruction cycle
+ uint_least16_t Cycle_EffectiveAddress;
+ uint8_t Cycle_Data;
+ uint_least16_t Cycle_Pointer;
+
+ uint8_t Register_Accumulator;
+ uint8_t Register_X;
+ uint8_t Register_Y;
+ uint_least32_t Register_ProgramCounter;
+ uint8_t Register_Status;
+ uint_least8_t Register_c_Flag;
+ uint_least8_t Register_n_Flag;
+ uint_least8_t Register_v_Flag;
+ uint_least8_t Register_z_Flag;
+ uint_least16_t Register_StackPointer;
+ uint_least16_t Instr_Operand;
+
+ // Interrupts
+ struct
+ {
+ uint_least8_t pending;
+ uint_least8_t irqs;
+ event_clock_t nmiClock;
+ event_clock_t irqClock;
+ event_clock_t delay;
+ bool irqRequest;
+ bool irqLatch;
+ } interrupts;
+
+ uint8_t Debug_Data;
+ uint_least16_t Debug_EffectiveAddress;
+ uint_least8_t Debug_Opcode;
+ uint_least16_t Debug_Operand;
+ uint_least16_t Debug_ProgramCounter;
+
+protected:
+ void clock (void);
+ void event (void);
+ void Initialise (void);
+ // Declare Interrupt Routines
+ inline void RSTRequest (void);
+ inline void RST1Request (void);
+ inline void NMIRequest (void);
+ inline void NMI1Request (void);
+ inline void IRQRequest (void);
+ inline void IRQ1Request (void);
+ inline void IRQ2Request (void);
+ bool interruptPending (void);
+
+ // Declare Instruction Routines
+ virtual void FetchOpcode (void);
+ void NextInstr (void);
+ inline void FetchDataByte (void);
+ inline void FetchLowAddr (void);
+ inline void FetchLowAddrX (void);
+ inline void FetchLowAddrY (void);
+ inline void FetchHighAddr (void);
+ inline void FetchHighAddrX (void);
+ inline void FetchHighAddrX2 (void);
+ inline void FetchHighAddrY (void);
+ inline void FetchHighAddrY2 (void);
+ inline void FetchLowEffAddr (void);
+ inline void FetchHighEffAddr (void);
+ inline void FetchHighEffAddrY (void);
+ inline void FetchHighEffAddrY2 (void);
+ inline void FetchLowPointer (void);
+ inline void FetchLowPointerX (void);
+ inline void FetchHighPointer (void);
+ inline void FetchEffAddrDataByte (void);
+ inline void PutEffAddrDataByte (void);
+ inline void FetchPutEffAddrDataByte (void);
+ inline void PushLowPC (void);
+ inline void PushHighPC (void);
+ inline void PushSR (bool b_flag);
+ inline void PushSR (void);
+ inline void PopLowPC (void);
+ inline void PopHighPC (void);
+ inline void PopSR (void);
+ inline void WasteCycle (void);
+ inline void DebugCycle (void);
+
+ // Delcare Instruction Operation Routines
+ inline void adc_instr (void);
+ inline void alr_instr (void);
+ inline void anc_instr (void);
+ inline void and_instr (void);
+ inline void ane_instr (void);
+ inline void arr_instr (void);
+ inline void asl_instr (void);
+ inline void asla_instr (void);
+ inline void aso_instr (void);
+ inline void axa_instr (void);
+ inline void axs_instr (void);
+ inline void bcc_instr (void);
+ inline void bcs_instr (void);
+ inline void beq_instr (void);
+ inline void bit_instr (void);
+ inline void bmi_instr (void);
+ inline void bne_instr (void);
+ inline void branch_instr (bool condition);
+ inline void bpl_instr (void);
+ inline void brk_instr (void);
+ inline void bvc_instr (void);
+ inline void bvs_instr (void);
+ inline void clc_instr (void);
+ inline void cld_instr (void);
+ inline void cli_instr (void);
+ inline void clv_instr (void);
+ inline void cmp_instr (void);
+ inline void cpx_instr (void);
+ inline void cpy_instr (void);
+ inline void dcm_instr (void);
+ inline void dec_instr (void);
+ inline void dex_instr (void);
+ inline void dey_instr (void);
+ inline void eor_instr (void);
+ inline void inc_instr (void);
+ inline void ins_instr (void);
+ inline void inx_instr (void);
+ inline void iny_instr (void);
+ inline void jmp_instr (void);
+ inline void jsr_instr (void);
+ inline void las_instr (void);
+ inline void lax_instr (void);
+ inline void lda_instr (void);
+ inline void ldx_instr (void);
+ inline void ldy_instr (void);
+ inline void lse_instr (void);
+ inline void lsr_instr (void);
+ inline void lsra_instr (void);
+ inline void oal_instr (void);
+ inline void ora_instr (void);
+ inline void pha_instr (void);
+ inline void pla_instr (void);
+ inline void rla_instr (void);
+ inline void rol_instr (void);
+ inline void rola_instr (void);
+ inline void ror_instr (void);
+ inline void rora_instr (void);
+ inline void rra_instr (void);
+ inline void rti_instr (void);
+ inline void rts_instr (void);
+ inline void sbx_instr (void);
+ inline void say_instr (void);
+ inline void sbc_instr (void);
+ inline void sec_instr (void);
+ inline void sed_instr (void);
+ inline void sei_instr (void);
+ inline void shs_instr (void);
+ inline void sta_instr (void);
+ inline void stx_instr (void);
+ inline void sty_instr (void);
+ inline void tas_instr (void);
+ inline void tax_instr (void);
+ inline void tay_instr (void);
+ inline void tsx_instr (void);
+ inline void txa_instr (void);
+ inline void txs_instr (void);
+ inline void tya_instr (void);
+ inline void xas_instr (void);
+ void illegal_instr (void);
+
+ // Declare Arithmatic Operations
+ inline void Perform_ADC (void);
+ inline void Perform_SBC (void);
+
+public:
+ MOS6510 (EventContext *context);
+ virtual ~MOS6510 ();
+ virtual void reset (void);
+ virtual void credits (char *str);
+ virtual void DumpState (void);
+ void debug (bool enable) {dodump = enable;}
+ void aecSignal (bool state);
+ void rdySignal (bool state);
+
+ // Non-standard functions
+ virtual void triggerRST (void);
+ virtual void triggerNMI (void);
+ virtual void triggerIRQ (void);
+ void clearIRQ (void);
+};
+
+
+//-------------------------------------------------------------------------//
+// Emulate One Complete Cycle //
+inline void MOS6510::clock (void)
+{
+ int_least8_t i = cycleCount++;
+ try {
+ (this->*procCycle[i]) ();
+ } catch (int_least8_t delta) {
+ cycleCount += delta;
+ m_blocked = true;
+ eventContext.cancel (this);
+ }
+}
+
+inline void MOS6510::event (void)
+{
+ eventContext.schedule (this, 1);
+ clock ();
+}
+
+#endif // _mos6510c_h_
diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/mos6510c.i b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/mos6510c.i
new file mode 100644
index 00000000..78d57ba6
--- /dev/null
+++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/mos6510c.i
@@ -0,0 +1,2562 @@
+/***************************************************************************
+ 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);
+}
diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/sid6510c.h b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/sid6510c.h
new file mode 100644
index 00000000..49d96dd6
--- /dev/null
+++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/sid6510c.h
@@ -0,0 +1,118 @@
+/***************************************************************************
+ sid6510c.h - Special MOS6510 to be fully
+ compatible with sidplay
+ -------------------
+ begin : Thu May 11 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: sid6510c.h,v $
+ * Revision 1.16 2002/11/25 21:07:32 s_a_white
+ * Allow setting of program counter on reset.
+ *
+ * Revision 1.15 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.14 2002/11/19 22:56:25 s_a_white
+ * Sidplay1 modes modified to make them nolonger require the psid driver.
+ *
+ * Revision 1.13 2002/11/01 17:35:27 s_a_white
+ * Frame based support for old sidplay1 modes.
+ *
+ * Revision 1.12 2002/03/12 18:47:13 s_a_white
+ * Made IRQ in sidplay1 compatibility modes behaves like JSR. This fixes tunes
+ * that have kernel switched out.
+ *
+ * Revision 1.11 2002/02/07 18:02:10 s_a_white
+ * Real C64 compatibility fixes. Debug of BRK works again. Fixed illegal
+ * instructions to work like sidplay1.
+ *
+ * Revision 1.10 2002/02/04 23:53:23 s_a_white
+ * Improved compatibilty of older sidplay1 modes. Fixed BRK to work like sidplay1
+ * only when stack is 0xff in real mode for better compatibility with C64.
+ *
+ * Revision 1.9 2001/09/01 11:08:06 s_a_white
+ * Fixes for sidplay1 environment modes.
+ *
+ * Revision 1.8 2001/07/14 13:18:15 s_a_white
+ * Stack & PC invalid tests now only performed on a BRK.
+ *
+ * Revision 1.7 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.6 2001/03/22 22:40:07 s_a_white
+ * Replaced tabs characters.
+ *
+ * Revision 1.5 2001/03/21 22:26:13 s_a_white
+ * Fake interrupts now been moved into here from player.cpp. At anytime it's
+ * now possible to ditch this compatibility class and use the real thing.
+ *
+ * Revision 1.4 2001/03/09 22:28:03 s_a_white
+ * Speed optimisation update.
+ *
+ * Revision 1.3 2001/02/13 21:02:25 s_a_white
+ * Small tidy up and possibly a small performace increase.
+ *
+ * Revision 1.2 2000/12/11 19:04:32 s_a_white
+ * AC99 Update.
+ *
+ ***************************************************************************/
+
+#ifndef _sid6510c_h_
+#define _sid6510c_h_
+
+#include "mos6510c.h"
+#include "sid2types.h"
+
+class SID6510: public MOS6510
+{
+private:
+ // Sidplay Specials
+ bool m_sleeping;
+ sid2_env_t m_mode;
+ event_clock_t m_delayClk, m_delayCycles;
+ bool m_framelock;
+
+public:
+ SID6510 (EventContext *context);
+
+ // Standard Functions
+ void reset (void);
+ void reset (uint_least16_t pc, uint8_t a, uint8_t x, uint8_t y);
+ void clock (void);
+
+ void environment (sid2_env_t mode) { m_mode = mode; }
+ void triggerRST (void);
+ void triggerNMI (void);
+ void triggerIRQ (void);
+ void sleep (void);
+
+protected:
+ void FetchOpcode (void);
+
+private:
+ void (MOS6510::*delayCycle[1]) (void);
+
+ inline void sid_illegal (void);
+ inline void sid_delay (void);
+ inline void sid_brk (void);
+ inline void sid_jmp (void);
+ inline void sid_rts (void);
+ inline void sid_cli (void);
+ inline void sid_rti (void);
+ inline void sid_irq (void);
+};
+
+#endif // _sid6510c_h_
diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/sid6510c.i b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/sid6510c.i
new file mode 100644
index 00000000..bc573d3b
--- /dev/null
+++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/cycle_based/sid6510c.i
@@ -0,0 +1,409 @@
+/***************************************************************************
+ sid6510c.i - Sidplay Specific 6510 emulation
+ -------------------
+ begin : Thu May 11 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: sid6510c.i,v $
+ * Revision 1.28 2002/12/03 23:24:52 s_a_white
+ * Let environment know when cpu sleeps in real c64 mode.
+ *
+ * Revision 1.27 2002/12/02 22:19:43 s_a_white
+ * sid_brk fix to prevent it running some of the real brk cycles in old emulation
+ * modes.
+ *
+ * Revision 1.26 2002/11/25 21:07:34 s_a_white
+ * Allow setting of program counter on reset.
+ *
+ * Revision 1.25 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.24 2002/11/19 22:56:25 s_a_white
+ * Sidplay1 modes modified to make them nolonger require the psid driver.
+ *
+ * Revision 1.23 2002/11/01 17:35:27 s_a_white
+ * Frame based support for old sidplay1 modes.
+ *
+ * Revision 1.22 2002/10/15 23:52:14 s_a_white
+ * Fix sidplay2 cpu sleep optimisation and NMIs.
+ *
+ * Revision 1.21 2002/09/23 22:50:55 s_a_white
+ * Reverted update 1.20 as was incorrect. Only need to
+ * change MOS6510 to SID6510 for compliancy.
+ *
+ * Revision 1.20 2002/09/23 19:42:14 s_a_white
+ * Newer compilers don't allow pointers to be taken directly
+ * from base class member functions.
+ *
+ * Revision 1.19 2002/03/12 18:47:13 s_a_white
+ * Made IRQ in sidplay1 compatibility modes behaves like JSR. This fixes tunes
+ * that have kernel switched out.
+ *
+ * Revision 1.18 2002/02/07 18:02:10 s_a_white
+ * Real C64 compatibility fixes. Debug of BRK works again. Fixed illegal
+ * instructions to work like sidplay1.
+ *
+ * Revision 1.17 2002/02/06 17:49:12 s_a_white
+ * Fixed sign comparison warning.
+ *
+ * Revision 1.16 2002/02/04 23:53:23 s_a_white
+ * Improved compatibilty of older sidplay1 modes. Fixed BRK to work like sidplay1
+ * only when stack is 0xff in real mode for better compatibility with C64.
+ *
+ * Revision 1.15 2002/01/28 19:32:16 s_a_white
+ * PSID sample improvements.
+ *
+ * Revision 1.14 2001/10/02 18:00:37 s_a_white
+ * Removed un-necessary cli.
+ *
+ * Revision 1.13 2001/09/18 07:51:39 jpaana
+ * Small fix to rti-processing.
+ *
+ * Revision 1.12 2001/09/03 22:23:06 s_a_white
+ * Fixed faked IRQ trigger on BRK for sidplay1 environment modes.
+ *
+ * Revision 1.11 2001/09/01 11:08:06 s_a_white
+ * Fixes for sidplay1 environment modes.
+ *
+ * Revision 1.10 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.9 2001/07/14 13:17:40 s_a_white
+ * Sidplay1 optimisations moved to here. Stack & PC invalid tests now only
+ * performed on a BRK.
+ *
+ * Revision 1.8 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.7 2001/03/22 22:40:07 s_a_white
+ * Replaced tabs characters.
+ *
+ * Revision 1.6 2001/03/21 22:26:24 s_a_white
+ * Fake interrupts now been moved into here from player.cpp. At anytime it's
+ * now possible to ditch this compatibility class and use the real thing.
+ *
+ * Revision 1.5 2001/03/09 22:28:03 s_a_white
+ * Speed optimisation update.
+ *
+ * Revision 1.4 2001/02/13 21:02:16 s_a_white
+ * Small tidy up and possibly a small performace increase.
+ *
+ * Revision 1.3 2000/12/11 19:04:32 s_a_white
+ * AC99 Update.
+ *
+ ***************************************************************************/
+
+#include "sid6510c.h"
+
+
+SID6510::SID6510 (EventContext *context)
+:MOS6510(context),
+ m_mode(sid2_envR),
+ m_framelock(false)
+{ // Ok start all the hacks for sidplay. This prevents
+ // execution of code in roms. For real c64 emulation
+ // create object from base class! Also stops code
+ // rom execution when bad code switches roms in over
+ // itself.
+ for (uint i = 0; i < OPCODE_MAX; i++)
+ {
+ procCycle = instrTable[i].cycle;
+ if (procCycle == NULL) continue;
+
+ for (uint n = 0; n < instrTable[i].cycles; n++)
+ {
+ if (procCycle[n] == &SID6510::illegal_instr)
+ { // Rev 1.2 (saw) - Changed nasty union to reinterpret_cast
+ procCycle[n] = reinterpret_cast <void (MOS6510::*)()>
+ (&SID6510::sid_illegal);
+ }
+ else if (procCycle[n] == &SID6510::jmp_instr)
+ { // Stop jumps into rom code
+ procCycle[n] = reinterpret_cast <void (MOS6510::*)()>
+ (&SID6510::sid_jmp);
+ }
+ else if (procCycle[n] == &SID6510::cli_instr)
+ { // No overlapping IRQs allowed
+ procCycle[n] = reinterpret_cast <void (MOS6510::*)()>
+ (&SID6510::sid_cli);
+ }
+ }
+ }
+
+ { // Since no real IRQs, all RTIs mapped to RTS
+ // Required for fix bad tunes in old modes
+ uint n;
+ procCycle = instrTable[RTIn].cycle;
+ for (n = 0; n < instrTable[RTIn].cycles; n++)
+ {
+ if (procCycle[n] == &SID6510::PopSR)
+ {
+ procCycle[n] = reinterpret_cast <void (MOS6510::*)()>
+ (&SID6510::sid_rti);
+ break;
+ }
+ }
+
+ procCycle = interruptTable[oIRQ].cycle;
+ for (n = 0; n < interruptTable[oIRQ].cycles; n++)
+ {
+ if (procCycle[n] == &SID6510::IRQRequest)
+ {
+ procCycle[n] = reinterpret_cast <void (MOS6510::*)()>
+ (&SID6510::sid_irq);
+ break;
+ }
+ }
+ }
+
+ { // Support of sidplays BRK functionality
+ procCycle = instrTable[BRKn].cycle;
+ for (uint n = 0; n < instrTable[BRKn].cycles; n++)
+ {
+ if (procCycle[n] == &SID6510::PushHighPC)
+ {
+ procCycle[n] = reinterpret_cast <void (MOS6510::*)()>
+ (&SID6510::sid_brk);
+ break;
+ }
+ }
+ }
+
+ // Used to insert busy delays into the CPU emulation
+ delayCycle[0] = reinterpret_cast <void (MOS6510::*)()>
+ (&SID6510::sid_delay);
+}
+
+void SID6510::reset (uint_least16_t pc, uint8_t a, uint8_t x, uint8_t y)
+{ // Reset the processor
+ reset ();
+
+ // Registers not touched by a reset
+ Register_Accumulator = a;
+ Register_X = x;
+ Register_Y = y;
+ Register_ProgramCounter = pc;
+}
+
+void SID6510::reset ()
+{
+ m_sleeping = false;
+ // Call inherited reset
+ MOS6510::reset ();
+}
+
+// Send CPU is about to sleep. Only a reset or
+// interrupt will wake up the processor
+void SID6510::sleep ()
+{ // Simulate a delay for JMPw
+ m_delayClk = eventContext.getTime ();
+ m_sleeping = true;
+ procCycle = delayCycle;
+ cycleCount = 0;
+ eventContext.cancel (this);
+ envSleep ();
+
+ // Check for outstanding interrupts
+ if (interrupts.irqs)
+ {
+ interrupts.irqs--;
+ triggerIRQ ();
+ }
+ else if (interrupts.pending)
+ {
+ m_sleeping = false;
+ eventContext.schedule (this, 1);
+ }
+}
+
+void SID6510::FetchOpcode (void)
+{
+ if (m_mode == sid2_envR)
+ {
+ MOS6510::FetchOpcode ();
+ return;
+ }
+
+ // Sid tunes end by wrapping the stack. For compatibilty it
+ // has to be handled.
+ m_sleeping |= (endian_16hi8 (Register_StackPointer) != SP_PAGE);
+ m_sleeping |= (endian_32hi16 (Register_ProgramCounter) != 0);
+ if (!m_sleeping)
+ MOS6510::FetchOpcode ();
+
+ if (m_framelock == false)
+ {
+ m_framelock = true;
+ // Simulate sidplay1 frame based execution
+ while (!m_sleeping)
+ MOS6510::clock ();
+ sleep ();
+ m_framelock = false;
+ }
+}
+
+
+//**************************************************************************************
+// For sidplay compatibility implement those instructions which don't behave properly.
+//**************************************************************************************
+void SID6510::sid_brk (void)
+{
+ if (m_mode == sid2_envR)
+ {
+ MOS6510::PushHighPC ();
+ return;
+ }
+
+ sei_instr ();
+#if !defined(NO_RTS_UPON_BRK)
+ sid_rts ();
+#endif
+ FetchOpcode ();
+}
+
+void SID6510::sid_jmp (void)
+{ // For sidplay compatibility, inherited from environment
+ if (m_mode == sid2_envR)
+ { // If a busy loop then just sleep
+ if (Cycle_EffectiveAddress != instrStartPC)
+ jmp_instr ();
+ else
+ {
+ Register_ProgramCounter = Cycle_EffectiveAddress;
+ sleep ();
+ }
+ return;
+ }
+
+ if (envCheckBankJump (Cycle_EffectiveAddress))
+ jmp_instr ();
+ else
+ sid_rts ();
+}
+
+// Will do a full rts in 1 cycle, to
+// destroy current function and quit
+void SID6510::sid_rts (void)
+{
+ PopLowPC();
+ PopHighPC();
+ rts_instr();
+}
+
+void SID6510::sid_cli (void)
+{
+ if (m_mode == sid2_envR)
+ cli_instr ();
+}
+
+void SID6510::sid_rti (void)
+{
+ if (m_mode == sid2_envR)
+ {
+ PopSR ();
+ return;
+ }
+
+ // Fake RTS
+ sid_rts ();
+ FetchOpcode ();
+}
+
+void SID6510::sid_irq (void)
+{
+ MOS6510::IRQRequest ();
+ if (m_mode != sid2_envR)
+ { // RTI behaves like RTI in sidplay1 modes
+ Register_StackPointer++;
+ }
+}
+
+// Sidplay Suppresses Illegal Instructions
+void SID6510::sid_illegal (void)
+{
+ if (m_mode == sid2_envR)
+ {
+ MOS6510::illegal_instr ();
+ return;
+ }
+#ifdef MOS6510_DEBUG
+ DumpState ();
+#endif
+}
+
+void SID6510::sid_delay (void)
+{
+ cycleCount = 0;
+ if (++m_delayCycles >= 3)
+ {
+ (void) interruptPending ();
+ m_delayCycles = 0;
+ }
+}
+
+
+//**************************************************************************************
+// Sidplay compatibility interrupts. Basically wakes CPU if it is m_sleeping
+//**************************************************************************************
+void SID6510::triggerRST (void)
+{ // All modes
+ MOS6510::triggerRST ();
+ if (m_sleeping)
+ {
+ m_sleeping = false;
+ eventContext.schedule (this, 1);
+ }
+}
+
+void SID6510::triggerNMI (void)
+{ // Only in Real C64 mode
+ if (m_mode == sid2_envR)
+ {
+ MOS6510::triggerNMI ();
+ if (m_sleeping)
+ {
+ m_delayCycles = eventContext.getTime (m_delayClk) % 3;
+ m_sleeping = false;
+ eventContext.schedule (this, 1);
+ }
+ }
+}
+
+void SID6510::triggerIRQ (void)
+{
+ switch (m_mode)
+ {
+ default:
+#ifdef MOS6510_DEBUG
+ if (dodump)
+ {
+ printf ("****************************************************\n");
+ printf (" Fake IRQ Routine\n");
+ printf ("****************************************************\n");
+ }
+#endif
+ return;
+ case sid2_envR:
+ MOS6510::triggerIRQ ();
+ if (m_sleeping)
+ { // Simulate busy loop
+ m_delayCycles = eventContext.getTime (m_delayClk) % 3;
+ m_sleeping = false;
+ eventContext.schedule (this, 1);
+ }
+ }
+}
diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/mos6510.cpp b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/mos6510.cpp
new file mode 100644
index 00000000..74b09c95
--- /dev/null
+++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/mos6510.cpp
@@ -0,0 +1,534 @@
+/***************************************************************************
+ main.cpp - description
+ -------------------
+ 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: mos6510.cpp,v $
+ * Revision 1.8 2001/08/05 15:46:38 s_a_white
+ * No longer need to check on which cycle to print debug information.
+ *
+ * Revision 1.7 2001/07/14 13:04:34 s_a_white
+ * Accumulator is now unsigned, which improves code readability.
+ *
+ * Revision 1.6 2001/03/09 22:27:46 s_a_white
+ * Speed optimisation update.
+ *
+ * Revision 1.5 2001/02/13 23:01:10 s_a_white
+ * envReadMemDataByte now used for debugging.
+ *
+ * Revision 1.4 2000/12/11 19:03:16 s_a_white
+ * AC99 Update.
+ *
+ ***************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "sidtypes.h"
+#include "sidendian.h"
+#include "sidenv.h"
+#include "conf6510.h"
+#include "opcodes.h"
+
+#ifdef HAVE_EXCEPTIONS
+# include <new>
+#endif
+
+#ifdef MOS6510_STATE_6510
+# include "state6510.h"
+# include "state6510.cpp"
+#else
+
+#include "mos6510.h"
+
+// Check to see what type of emulation is required
+#ifdef MOS6510_CYCLE_BASED
+# include "cycle_based/mos6510c.i"
+
+# ifdef MOS6510_SIDPLAY
+ // Compile in sidplay code
+# include "cycle_based/sid6510c.i"
+# endif // MOS6510_SIDPLAY
+#else
+ // Line based emulation code has not been provided
+#endif // MOS6510_CYCLE_BASED
+
+void MOS6510::DumpState (void)
+{
+ uint8_t opcode, data;
+ uint_least16_t operand, address;
+
+ printf(" PC I A X Y SP DR PR NV-BDIZC Instruction\n");
+ printf("%04x ", instrStartPC);
+ printf("%u ", interrupts.irqs);
+ printf("%02x ", Register_Accumulator);
+ printf("%02x ", Register_X);
+ printf("%02x ", Register_Y);
+ printf("01%02x ", endian_16lo8 (Register_StackPointer));
+ printf("%02x ", envReadMemDataByte (0));
+ printf("%02x ", envReadMemDataByte (1));
+
+ if (getFlagN()) printf ("1"); else printf ("0");
+ if (getFlagV()) printf ("1"); else printf ("0");
+ if (Register_Status & (1 << SR_NOTUSED)) printf ("1"); else printf ("0");
+ if (Register_Status & (1 << SR_BREAK)) printf ("1"); else printf ("0");
+ if (getFlagD()) printf ("1"); else printf ("0");
+ if (getFlagI()) printf ("1"); else printf ("0");
+ if (getFlagZ()) printf ("1"); else printf ("0");
+ if (getFlagC()) printf ("1"); else printf ("0");
+
+ opcode = instrOpcode;
+ operand = Instr_Operand;
+ data = Cycle_Data;
+
+ switch (opcode)
+ {
+ case BCCr: case BCSr: case BEQr: case BMIr: case BNEr: case BPLr:
+ case BVCr: case BVSr:
+ address = (uint_least16_t) (Register_ProgramCounter + (int8_t) operand);
+ break;
+
+ default:
+ address = Cycle_EffectiveAddress;
+ break;
+ }
+
+ printf(" %02x ", opcode);
+
+ switch(opcode)
+ {
+ //Accumulator or Implied addressing
+ case ASLn: case LSRn: case ROLn: case RORn:
+ printf(" ");
+ break;
+ //Zero Page Addressing Mode Handler
+ case ADCz: case ANDz: case ASLz: case BITz: case CMPz: case CPXz:
+ case CPYz: case DCPz: case DECz: case EORz: case INCz: case ISBz:
+ case LAXz: case LDAz: case LDXz: case LDYz: case LSRz: case NOPz_:
+ case ORAz: case ROLz: case RORz: case SAXz: case SBCz: case SREz:
+ case STAz: case STXz: case STYz: case SLOz: case RLAz: case RRAz:
+ //ASOz AXSz DCMz INSz LSEz - Optional Opcode Names
+ printf("%02x ", (uint8_t) operand);
+ break;
+ //Zero Page with X Offset Addressing Mode Handler
+ case ADCzx: case ANDzx: case ASLzx: case CMPzx: case DCPzx: case DECzx:
+ case EORzx: case INCzx: case ISBzx: case LDAzx: case LDYzx: case LSRzx:
+ case NOPzx_: case ORAzx: case RLAzx: case ROLzx: case RORzx: case RRAzx:
+ case SBCzx: case SLOzx: case SREzx: case STAzx: case STYzx:
+ //ASOzx DCMzx INSzx LSEzx - Optional Opcode Names
+ printf("%02x ", (uint8_t) operand);
+ break;
+ //Zero Page with Y Offset Addressing Mode Handler
+ case LDXzy: case STXzy: case SAXzy: case LAXzy:
+ //AXSzx - Optional Opcode Names
+ printf("%02x ", endian_16lo8 (operand));
+ break;
+ //Absolute Addressing Mode Handler
+ case ADCa: case ANDa: case ASLa: case BITa: case CMPa: case CPXa:
+ case CPYa: case DCPa: case DECa: case EORa: case INCa: case ISBa:
+ case JMPw: case JSRw: case LAXa: case LDAa: case LDXa: case LDYa:
+ case LSRa: case NOPa: case ORAa: case ROLa: case RORa: case SAXa:
+ case SBCa: case SLOa: case SREa: case STAa: case STXa: case STYa:
+ case RLAa: case RRAa:
+ //ASOa AXSa DCMa INSa LSEa - Optional Opcode Names
+ printf("%02x %02x ", endian_16lo8 (operand), endian_16hi8 (operand));
+ break;
+ //Absolute With X Offset Addresing Mode Handler
+ case ADCax: case ANDax: case ASLax: case CMPax: case DCPax: case DECax:
+ case EORax: case INCax: case ISBax: case LDAax: case LDYax: case LSRax:
+ case NOPax_: case ORAax: case RLAax: case ROLax: case RORax: case RRAax:
+ case SBCax: case SHYax: case SLOax: case SREax: case STAax:
+ //ASOax DCMax INSax LSEax SAYax - Optional Opcode Names
+ printf("%02x %02x ", endian_16lo8 (operand), endian_16hi8 (operand));
+ break;
+ //Absolute With Y Offset Addresing Mode Handler
+ case ADCay: case ANDay: case CMPay: case DCPay: case EORay: case ISBay:
+ case LASay: case LAXay: case LDAay: case LDXay: case ORAay: case RLAay:
+ case RRAay: case SBCay: case SHAay: case SHSay: case SHXay: case SLOay:
+ case SREay: case STAay:
+ //ASOay AXAay DCMay INSax LSEay TASay XASay - Optional Opcode Names
+ printf("%02x %02x ", endian_16lo8 (operand), endian_16hi8 (operand));
+ break;
+ //Immediate and Relative Addressing Mode Handler
+ case ADCb: case ANDb: case ANCb_: case ANEb: case ASRb: case ARRb:
+
+ case CMPb: case CPXb: case CPYb: case EORb: case LDAb: case LDXb:
+ case LDYb: case LXAb: case NOPb_: case ORAb: case SBCb_: case SBXb:
+ //OALb ALRb XAAb - Optional Opcode Names
+ printf("%02x ", endian_16lo8 (operand));
+ break;
+ case BCCr: case BCSr: case BEQr: case BMIr: case BNEr: case BPLr:
+ case BVCr: case BVSr:
+ printf("%02x ", endian_16lo8 (operand));
+ break;
+ //Indirect Addressing Mode Handler
+ case JMPi:
+ printf("%02x %02x ", endian_16lo8 (operand), endian_16hi8 (operand));
+ break;
+ //Indexed with X Preinc Addressing Mode Handler
+ case ADCix: case ANDix: case CMPix: case DCPix: case EORix: case ISBix:
+ case LAXix: case LDAix: case ORAix: case SAXix: case SBCix: case SLOix:
+ case SREix: case STAix: case RLAix: case RRAix:
+ //ASOix AXSix DCMix INSix LSEix - Optional Opcode Names
+ printf("%02x ", endian_16lo8 (operand));
+ break;
+ //Indexed with Y Postinc Addressing Mode Handler
+ case ADCiy: case ANDiy: case CMPiy: case DCPiy: case EORiy: case ISBiy:
+ case LAXiy: case LDAiy: case ORAiy: case RLAiy: case RRAiy: case SBCiy:
+ case SHAiy: case SLOiy: case SREiy: case STAiy:
+ //AXAiy ASOiy LSEiy DCMiy INSiy - Optional Opcode Names
+ printf("%02x ", endian_16lo8 (operand));
+ break;
+ default:
+ printf(" ");
+ break;
+ }
+
+ switch(opcode)
+ {
+ case ADCb: case ADCz: case ADCzx: case ADCa: case ADCax: case ADCay:
+ case ADCix: case ADCiy:
+ printf(" ADC"); break;
+ case ANCb_:
+ printf("*ANC"); break;
+ case ANDb: case ANDz: case ANDzx: case ANDa: case ANDax: case ANDay:
+ case ANDix: case ANDiy:
+ printf(" AND"); break;
+ case ANEb: //Also known as XAA
+ printf("*ANE"); break;
+ case ARRb:
+ printf("*ARR"); break;
+ case ASLn: case ASLz: case ASLzx: case ASLa: case ASLax:
+ printf(" ASL"); break;
+ case ASRb: //Also known as ALR
+ printf("*ASR"); break;
+ case BCCr:
+ printf(" BCC"); break;
+ case BCSr:
+ printf(" BCS"); break;
+ case BEQr:
+ printf(" BEQ"); break;
+ case BITz: case BITa:
+ printf(" BIT"); break;
+ case BMIr:
+ printf(" BMI"); break;
+ case BNEr:
+ printf(" BNE"); break;
+ case BPLr:
+ printf(" BPL"); break;
+ case BRKn:
+ printf(" BRK"); break;
+ case BVCr:
+ printf(" BVC"); break;
+ case BVSr:
+ printf(" BVS"); break;
+ case CLCn:
+ printf(" CLC"); break;
+ case CLDn:
+ printf(" CLD"); break;
+ case CLIn:
+ printf(" CLI"); break;
+ case CLVn:
+ printf(" CLV"); break;
+ case CMPb: case CMPz: case CMPzx: case CMPa: case CMPax: case CMPay:
+ case CMPix: case CMPiy:
+ printf(" CMP"); break;
+ case CPXb: case CPXz: case CPXa:
+ printf(" CPX"); break;
+ case CPYb: case CPYz: case CPYa:
+ printf(" CPY"); break;
+ case DCPz: case DCPzx: case DCPa: case DCPax: case DCPay: case DCPix:
+ case DCPiy: //Also known as DCM
+ printf("*DCP"); break;
+ case DECz: case DECzx: case DECa: case DECax:
+ printf(" DEC"); break;
+ case DEXn:
+ printf(" DEX"); break;
+ case DEYn:
+ printf(" DEY"); break;
+ case EORb: case EORz: case EORzx: case EORa: case EORax: case EORay:
+ case EORix: case EORiy:
+ printf(" EOR"); break;
+ case INCz: case INCzx: case INCa: case INCax:
+ printf(" INC"); break;
+ case INXn:
+ printf(" INX"); break;
+ case INYn:
+ printf(" INY"); break;
+ case ISBz: case ISBzx: case ISBa: case ISBax: case ISBay: case ISBix:
+ case ISBiy: //Also known as INS
+ printf("*ISB"); break;
+ case JMPw: case JMPi:
+ printf(" JMP"); break;
+ case JSRw:
+ printf(" JSR"); break;
+ case LASay:
+ printf("*LAS"); break;
+ case LAXz: case LAXzy: case LAXa: case LAXay: case LAXix: case LAXiy:
+ printf("*LAX"); break;
+ case LDAb: case LDAz: case LDAzx: case LDAa: case LDAax: case LDAay:
+ case LDAix: case LDAiy:
+ printf(" LDA"); break;
+ case LDXb: case LDXz: case LDXzy: case LDXa: case LDXay:
+ printf(" LDX"); break;
+ case LDYb: case LDYz: case LDYzx: case LDYa: case LDYax:
+ printf(" LDY"); break;
+ case LSRz: case LSRzx: case LSRa: case LSRax: case LSRn:
+ printf(" LSR"); break;
+ case NOPn_: case NOPb_: case NOPz_: case NOPzx_: case NOPa: case NOPax_:
+ if(opcode != NOPn) printf("*");
+ else printf(" ");
+ printf("NOP"); break;
+ case LXAb: //Also known as OAL
+ printf("*LXA"); break;
+ case ORAb: case ORAz: case ORAzx: case ORAa: case ORAax: case ORAay:
+ case ORAix: case ORAiy:
+ printf(" ORA"); break;
+ case PHAn:
+ printf(" PHA"); break;
+ case PHPn:
+ printf(" PHP"); break;
+ case PLAn:
+ printf(" PLA"); break;
+ case PLPn:
+ printf(" PLP"); break;
+ case RLAz: case RLAzx: case RLAix: case RLAa: case RLAax: case RLAay:
+ case RLAiy:
+ printf("*RLA"); break;
+ case ROLz: case ROLzx: case ROLa: case ROLax: case ROLn:
+ printf(" ROL"); break;
+ case RORz: case RORzx: case RORa: case RORax: case RORn:
+ printf(" ROR"); break;
+ case RRAa: case RRAax: case RRAay: case RRAz: case RRAzx: case RRAix:
+ case RRAiy:
+ printf("*RRA"); break;
+ case RTIn:
+ printf(" RTI"); break;
+ case RTSn:
+ printf(" RTS"); break;
+ case SAXz: case SAXzy: case SAXa: case SAXix: //Also known as AXS
+ printf("*SAX"); break;
+ case SBCb_:
+ if(opcode != SBCb) printf("*");
+ else printf(" ");
+ printf ("SBC"); break;
+ case SBCz: case SBCzx: case SBCa: case SBCax: case SBCay: case SBCix:
+ case SBCiy:
+ printf(" SBC"); break;
+ case SBXb:
+ printf("*SBX"); break;
+ case SECn:
+ printf(" SEC"); break;
+ case SEDn:
+ printf(" SED"); break;
+ case SEIn:
+ printf(" SEI"); break;
+ case SHAay: case SHAiy: //Also known as AXA
+ printf("*SHA"); break;
+ case SHSay: //Also known as TAS
+ printf("*SHS"); break;
+ case SHXay: //Also known as XAS
+ printf("*SHX"); break;
+ case SHYax: //Also known as SAY
+ printf("*SHY"); break;
+ case SLOz: case SLOzx: case SLOa: case SLOax: case SLOay: case SLOix:
+ case SLOiy: //Also known as ASO
+ printf("*SLO"); break;
+ case SREz: case SREzx: case SREa: case SREax: case SREay: case SREix:
+ case SREiy: //Also known as LSE
+ printf("*SRE"); break;
+ case STAz: case STAzx: case STAa: case STAax: case STAay: case STAix:
+ case STAiy:
+ printf(" STA"); break;
+ case STXz: case STXzy: case STXa:
+ printf(" STX"); break;
+ case STYz: case STYzx: case STYa:
+ printf(" STY"); break;
+ case TAXn:
+ printf(" TAX"); break;
+ case TAYn:
+ printf(" TAY"); break;
+ case TSXn:
+ printf(" TSX"); break;
+ case TXAn:
+ printf(" TXA"); break;
+ case TXSn:
+ printf(" TXS"); break;
+ case TYAn:
+ printf(" TYA"); break;
+ default:
+ printf("*HLT"); break;
+ }
+
+ switch(opcode)
+ {
+ //Accumulator or Implied addressing
+ case ASLn: case LSRn: case ROLn: case RORn:
+ printf("n A");
+ break;
+
+ //Zero Page Addressing Mode Handler
+ case ADCz: case ANDz: case ASLz: case BITz: case CMPz: case CPXz:
+ case CPYz: case DCPz: case DECz: case EORz: case INCz: case ISBz:
+ case LAXz: case LDAz: case LDXz: case LDYz: case LSRz: case ORAz:
+
+ case ROLz: case RORz: case SBCz: case SREz: case SLOz: case RLAz:
+ case RRAz:
+ //ASOz AXSz DCMz INSz LSEz - Optional Opcode Names
+ printf("z %02x {%02x}", (uint8_t) operand, data);
+ break;
+ case SAXz: case STAz: case STXz: case STYz:
+#ifdef MOS6510_DEBUG
+ case NOPz_:
+#endif
+ printf("z %02x", endian_16lo8 (operand));
+ break;
+
+ //Zero Page with X Offset Addressing Mode Handler
+ case ADCzx: case ANDzx: case ASLzx: case CMPzx: case DCPzx: case DECzx:
+ case EORzx: case INCzx: case ISBzx: case LDAzx: case LDYzx: case LSRzx:
+ case ORAzx: case RLAzx: case ROLzx: case RORzx: case RRAzx: case SBCzx:
+ case SLOzx: case SREzx:
+ //ASOzx DCMzx INSzx LSEzx - Optional Opcode Names
+ printf("zx %02x,X", endian_16lo8 (operand));
+ printf(" [%04x]{%02x}", address, data);
+ break;
+ case STAzx: case STYzx:
+#ifdef MOS6510_DEBUG
+ case NOPzx_:
+#endif
+ printf("zx %02x,X", endian_16lo8 (operand));
+ printf(" [%04x]", address);
+ break;
+
+ //Zero Page with Y Offset Addressing Mode Handler
+ case LAXzy: case LDXzy:
+ //AXSzx - Optional Opcode Names
+ printf("zy %02x,Y", endian_16lo8 (operand));
+ printf(" [%04x]{%02x}", address, data);
+ break;
+ case STXzy: case SAXzy:
+ printf("zy %02x,Y", endian_16lo8 (operand));
+ printf(" [%04x]", address);
+ break;
+
+ //Absolute Addressing Mode Handler
+ case ADCa: case ANDa: case ASLa: case BITa: case CMPa: case CPXa:
+ case CPYa: case DCPa: case DECa: case EORa: case INCa: case ISBa:
+ case LAXa: case LDAa: case LDXa: case LDYa: case LSRa: case ORAa:
+ case ROLa: case RORa: case SBCa: case SLOa: case SREa: case RLAa:
+ case RRAa:
+ //ASOa AXSa DCMa INSa LSEa - Optional Opcode Names
+ printf("a %04x {%02x}", operand, data);
+ break;
+ case SAXa: case STAa: case STXa: case STYa:
+#ifdef MOS6510_DEBUG
+ case NOPa:
+#endif
+ printf("a %04x", operand);
+ break;
+ case JMPw: case JSRw:
+ printf("w %04x", operand);
+ break;
+
+ //Absolute With X Offset Addresing Mode Handler
+ case ADCax: case ANDax: case ASLax: case CMPax: case DCPax: case DECax:
+ case EORax: case INCax: case ISBax: case LDAax: case LDYax: case LSRax:
+ case ORAax: case RLAax: case ROLax: case RORax: case RRAax: case SBCax:
+ case SLOax: case SREax:
+ //ASOax DCMax INSax LSEax SAYax - Optional Opcode Names
+ printf("ax %04x,X", operand);
+ printf(" [%04x]{%02x}", address, data);
+ break;
+ case SHYax: case STAax:
+#ifdef MOS6510_DEBUG
+ case NOPax_:
+#endif
+ printf("ax %04x,X", operand);
+ printf(" [%04x]", address);
+ break;
+
+ //Absolute With Y Offset Addresing Mode Handler
+ case ADCay: case ANDay: case CMPay: case DCPay: case EORay: case ISBay:
+ case LASay: case LAXay: case LDAay: case LDXay: case ORAay: case RLAay:
+ case RRAay: case SBCay: case SHSay: case SLOay: case SREay:
+ //ASOay AXAay DCMay INSax LSEay TASay XASay - Optional Opcode Names
+ printf("ay %04x,Y", operand);
+ printf(" [%04x]{%02x}", address, data);
+ break;
+ case SHAay: case SHXay: case STAay:
+ printf("ay %04x,Y", operand);
+ printf(" [%04x]", address);
+ break;
+
+ //Immediate Addressing Mode Handler
+ case ADCb: case ANDb: case ANCb_: case ANEb: case ASRb: case ARRb:
+ case CMPb: case CPXb: case CPYb: case EORb: case LDAb: case LDXb:
+ case LDYb: case LXAb: case ORAb: case SBCb_: case SBXb:
+ //OALb ALRb XAAb - Optional Opcode Names
+#ifdef MOS6510_DEBUG
+ case NOPb_:
+#endif
+ printf("b #%02x", endian_16lo8 (operand));
+ break;
+
+ //Relative Addressing Mode Handler
+ case BCCr: case BCSr: case BEQr: case BMIr: case BNEr: case BPLr:
+ case BVCr: case BVSr:
+ printf("r #%02x", endian_16lo8 (operand));
+ printf(" [%04x]", address);
+ break;
+
+ //Indirect Addressing Mode Handler
+ case JMPi:
+ printf("i (%04x)", operand);
+ printf(" [%04x]", address);
+ break;
+
+ //Indexed with X Preinc Addressing Mode Handler
+ case ADCix: case ANDix: case CMPix: case DCPix: case EORix: case ISBix:
+ case LAXix: case LDAix: case ORAix: case SBCix: case SLOix: case SREix:
+ case RLAix: case RRAix:
+ //ASOix AXSix DCMix INSix LSEix - Optional Opcode Names
+ printf("ix (%02x,X)", endian_16lo8 (operand));
+ printf(" [%04x]{%02x}", address, data);
+ break;
+ case SAXix: case STAix:
+ printf("ix (%02x,X)", endian_16lo8 (operand));
+ printf(" [%04x]", address);
+ break;
+
+ //Indexed with Y Postinc Addressing Mode Handler
+ case ADCiy: case ANDiy: case CMPiy: case DCPiy: case EORiy: case ISBiy:
+ case LAXiy: case LDAiy: case ORAiy: case RLAiy: case RRAiy: case SBCiy:
+ case SLOiy: case SREiy:
+ //AXAiy ASOiy LSEiy DCMiy INSiy - Optional Opcode Names
+ printf("iy (%02x),Y", endian_16lo8 (operand));
+ printf(" [%04x]{%02x}", address, data);
+ break;
+ case SHAiy: case STAiy:
+ printf("iy (%02x),Y", endian_16lo8 (operand));
+ printf(" [%04x]", address);
+ break;
+
+ default:
+ break;
+ }
+
+ printf ("\n\n");
+ fflush (stdout);
+}
+
+#endif // MOS6510_STATE_6510
+
diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/mos6510.h b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/mos6510.h
new file mode 100644
index 00000000..e7ad1a3f
--- /dev/null
+++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/mos6510.h
@@ -0,0 +1,75 @@
+/***************************************************************************
+ mos6510.h - description
+ -------------------
+ begin : Thu May 11 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: mos6510.h,v $
+ * Revision 1.5 2001/07/14 16:47:21 s_a_white
+ * Sync with sidbuilder class project.
+ *
+ * Revision 1.4 2001/07/14 13:04:34 s_a_white
+ * Accumulator is now unsigned, which improves code readability.
+ *
+ * Revision 1.3 2000/12/11 19:03:16 s_a_white
+ * AC99 Update.
+ *
+ ***************************************************************************/
+
+#ifndef _mos6510_h_
+#define _mos6510_h_
+
+#include "config.h"
+#include "component.h"
+#include "sidenv.h"
+#include "event.h"
+
+#undef MOS6510_VERSION
+#undef MOS6510_DATE
+#undef MOS6510_AUTHOR
+#undef MOS6510_EMAIL
+#define MOS6510_VERSION "1.08"
+#define MOS6510_DATE "23th May 2000"
+#define MOS6510_AUTHOR "Simon White"
+#define MOS6510_EMAIL "s_a_white@email.com"
+#define MOS6510_INTERRUPT_DELAY 2
+
+#include "opcodes.h"
+#include "conf6510.h"
+
+// Status Register flag definistions
+#define SR_NEGATIVE 7
+#define SR_OVERFLOW 6
+#define SR_NOTUSED 5
+#define SR_BREAK 4
+#define SR_DECIMAL 3
+#define SR_INTERRUPT 2
+#define SR_ZERO 1
+#define SR_CARRY 0
+
+#define SP_PAGE 0x01
+
+// Check to see what type of emulation is required
+#ifdef MOS6510_CYCLE_BASED
+# ifdef MOS6510_SIDPLAY
+# include "cycle_based/sid6510c.h"
+# else
+# include "cycle_based/mos6510c.h"
+# endif // MOS6510_SIDPLAY
+#else
+ // Line based emulation code has not been provided
+#endif // MOS6510_CYCLE_BASED
+
+#endif // _mos6510_h_
+
diff --git a/plugins/sid/sidplay-libs/libsidplay/src/mos6510/opcodes.h b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/opcodes.h
new file mode 100644
index 00000000..e4d44acd
--- /dev/null
+++ b/plugins/sid/sidplay-libs/libsidplay/src/mos6510/opcodes.h
@@ -0,0 +1,331 @@
+/***************************************************************************
+ opcodes.h - description
+ -------------------
+ begin : Thu May 11 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. *
+ * *
+ ***************************************************************************/
+#ifndef _opcodes_h_
+#define _opcodes_h_
+
+#define OPCODE_MAX 0x100
+
+/* HLT
+ 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:
+*/
+
+#define BRKn 0x00
+#define JSRw 0x20
+#define RTIn 0x40
+#define RTSn 0x60
+#define NOPb 0x80
+#define NOPb_ NOPb: case 0x82: case 0xC2: case 0xE2: case 0x89
+#define LDYb 0xA0
+#define CPYb 0xC0
+#define CPXb 0xE0
+
+#define ORAix 0x01
+#define ANDix 0x21
+#define EORix 0x41
+#define ADCix 0x61
+#define STAix 0x81
+#define LDAix 0xA1
+#define CMPix 0xC1
+#define SBCix 0xE1
+
+#define LDXb 0xA2
+
+#define SLOix 0x03
+#define RLAix 0x23
+#define SREix 0x43
+#define RRAix 0x63
+#define SAXix 0x83
+#define LAXix 0xA3
+#define DCPix 0xC3
+#define ISBix 0xE3
+
+#define NOPz 0x04
+#define NOPz_ NOPz: case 0x44: case 0x64
+#define BITz 0x24
+#define STYz 0x84
+#define LDYz 0xA4
+#define CPYz 0xC4
+#define CPXz 0xE4
+
+#define ORAz 0x05
+#define ANDz 0x25
+#define EORz 0x45
+#define ADCz 0x65
+#define STAz 0x85
+#define LDAz 0xA5
+#define CMPz 0xC5
+#define SBCz 0xE5
+
+#define ASLz 0x06
+#define ROLz 0x26
+#define LSRz 0x46
+#define RORz 0x66
+#define STXz 0x86
+#define LDXz 0xA6
+#define DECz 0xC6
+#define INCz 0xE6
+
+#define SLOz 0x07
+#define RLAz 0x27
+#define SREz 0x47
+#define RRAz 0x67
+#define SAXz 0x87
+#define LAXz 0xA7
+#define DCPz 0xC7
+#define ISBz 0xE7
+
+#define PHPn 0x08
+#define PLPn 0x28
+#define PHAn 0x48
+#define PLAn 0x68
+#define DEYn 0x88
+#define TAYn 0xA8
+#define INYn 0xC8
+#define INXn 0xE8
+
+#define ORAb 0x09
+#define ANDb 0x29
+#define EORb 0x49
+#define ADCb 0x69
+#define LDAb 0xA9
+#define CMPb 0xC9
+#define SBCb 0xE9
+#define SBCb_ SBCb: case 0XEB
+
+#define ASLn 0x0A
+#define ROLn 0x2A
+#define LSRn 0x4A
+#define RORn 0x6A
+#define TXAn 0x8A
+#define TAXn 0xAA
+#define DEXn 0xCA
+#define NOPn 0xEA
+#define NOPn_ NOPn: case 0x1A: case 0x3A: case 0x5A: case 0x7A: case 0xDA: case 0xFA
+
+#define ANCb 0x0B
+#define ANCb_ ANCb: case 0x2B
+#define ASRb 0x4B
+#define ARRb 0x6B
+#define ANEb 0x8B
+#define XAAb 0x8B
+#define LXAb 0xAB
+#define SBXb 0xCB
+
+#define NOPa 0x0C
+#define BITa 0x2C
+#define JMPw 0x4C
+#define JMPi 0x6C
+#define STYa 0x8C
+#define LDYa 0xAC
+#define CPYa 0xCC
+#define CPXa 0xEC
+
+#define ORAa 0x0D
+#define ANDa 0x2D
+#define EORa 0x4D
+#define ADCa 0x6D
+#define STAa 0x8D
+#define LDAa 0xAD
+#define CMPa 0xCD
+#define SBCa 0xED
+
+#define ASLa 0x0E
+#define ROLa 0x2E
+#define LSRa 0x4E
+#define RORa 0x6E
+#define STXa 0x8E
+#define LDXa 0xAE
+#define DECa 0xCE
+#define INCa 0xEE
+
+#define SLOa 0x0F
+#define RLAa 0x2F
+#define SREa 0x4F
+#define RRAa 0x6F
+#define SAXa 0x8F
+#define LAXa 0xAF
+#define DCPa 0xCF
+#define ISBa 0xEF
+
+#define BPLr 0x10
+#define BMIr 0x30
+#define BVCr 0x50
+#define BVSr 0x70
+#define BCCr 0x90
+#define BCSr 0xB0
+#define BNEr 0xD0
+#define BEQr 0xF0
+
+#define ORAiy 0x11
+#define ANDiy 0x31
+#define EORiy 0x51
+#define ADCiy 0x71
+#define STAiy 0x91
+#define LDAiy 0xB1
+#define CMPiy 0xD1
+#define SBCiy 0xF1
+
+#define SLOiy 0x13
+#define RLAiy 0x33
+#define SREiy 0x53
+#define RRAiy 0x73
+#define SHAiy 0x93
+#define LAXiy 0xB3
+#define DCPiy 0xD3
+#define ISBiy 0xF3
+
+#define NOPzx 0x14
+#define NOPzx_ NOPzx: case 0x34: case 0x54: case 0x74: case 0xD4: case 0xF4
+#define STYzx 0x94
+#define LDYzx 0xB4
+
+#define ORAzx 0x15
+#define ANDzx 0x35
+#define EORzx 0x55
+#define ADCzx 0x75
+#define STAzx 0x95
+#define LDAzx 0xB5
+#define CMPzx 0xD5
+#define SBCzx 0xF5
+
+#define ASLzx 0x16
+#define ROLzx 0x36
+#define LSRzx 0x56
+#define RORzx 0x76
+#define STXzy 0x96
+#define LDXzy 0xB6
+#define DECzx 0xD6
+#define INCzx 0xF6
+
+#define SLOzx 0x17
+#define RLAzx 0x37
+#define SREzx 0x57
+#define RRAzx 0x77
+#define SAXzy 0x97
+#define LAXzy 0xB7
+#define DCPzx 0xD7
+#define ISBzx 0xF7
+
+#define CLCn 0x18
+#define SECn 0x38
+#define CLIn 0x58
+#define SEIn 0x78
+#define TYAn 0x98
+#define CLVn 0xB8
+#define CLDn 0xD8
+#define SEDn 0xF8
+
+#define ORAay 0x19
+#define ANDay 0x39
+#define EORay 0x59
+#define ADCay 0x79
+#define STAay 0x99
+#define LDAay 0xB9
+#define CMPay 0xD9
+#define SBCay 0xF9
+
+#define TXSn 0x9A
+#define TSXn 0xBA
+
+#define SLOay 0x1B
+#define RLAay 0x3B
+#define SREay 0x5B
+#define RRAay 0x7B
+#define SHSay 0x9B
+#define TASay 0x9B
+#define LASay 0xBB
+#define DCPay 0xDB
+#define ISBay 0xFB
+
+#define NOPax 0x1C
+#define NOPax_ NOPax: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC
+#define SHYax 0x9C
+#define LDYax 0xBC
+
+#define ORAax 0x1D
+#define ANDax 0x3D
+#define EORax 0x5D
+#define ADCax 0x7D
+#define STAax 0x9D
+#define LDAax 0xBD
+#define CMPax 0xDD
+#define SBCax 0xFD
+
+#define ASLax 0x1E
+#define ROLax 0x3E
+#define LSRax 0x5E
+#define RORax 0x7E
+#define SHXay 0x9E
+#define LDXay 0xBE
+#define DECax 0xDE
+#define INCax 0xFE
+
+#define SLOax 0x1F
+#define RLAax 0x3F
+#define SREax 0x5F
+#define RRAax 0x7F
+#define SHAay 0x9F
+#define LAXay 0xBF
+#define DCPax 0xDF
+#define ISBax 0xFF
+
+// Instruction Aliases
+#define ASOix SLOix
+#define LSEix SREix
+#define AXSix SAXix
+#define DCMix DCPix
+#define INSix ISBix
+#define ASOz SLOz
+#define LSEz SREz
+#define AXSz SAXz
+#define DCMz DCPz
+#define INSz ISBz
+#define ALRb ASRb
+#define OALb LXAb
+#define ASOa SLOa
+#define LSEa SREa
+#define AXSa SAXa
+#define DCMa DCPa
+#define INSa ISBa
+#define ASOiy SLOiy
+#define LSEiy SREiy
+#define AXAiy SHAiy
+#define DCMiy DCPiy
+#define INSiy ISBiy
+#define ASOzx SLOzx
+#define LSEzx SREzx
+#define AXSzy SAXzy
+#define DCMzx DCPzx
+#define INSzx ISBzx
+#define ASOay SLOay
+#define LSEay SREay
+#define DCMay DCPay
+#define INSay ISBay
+#define SAYax SHYax
+#define XASay SHXay
+#define ASOax SLOax
+#define LSEax SREax
+#define AXAay SHAay
+#define DCMax DCPax
+#define INSax ISBax
+#define SKBn NOPb
+#define SKWn NOPa
+
+#endif // _opcodes_h_