Showing preview only (1,044K chars total). Download the full file or copy to clipboard to get everything.
Repository: marioballano/emudore
Branch: master
Commit: 5d98f4447409
Files: 42
Total size: 1013.4 KB
Directory structure:
gitextract_1yla08f4/
├── CMakeLists.txt
├── LICENSE
├── Makefile
├── README.md
├── assets/
│ ├── bas/
│ │ ├── 10print.bas
│ │ ├── bitmap.bas
│ │ ├── bouncing.bas
│ │ └── lowercase.bas
│ ├── prg/
│ │ └── monopole.prg
│ ├── roms/
│ │ └── README.md
│ └── tests/
│ ├── 6502_functional_test.a65
│ ├── 6502_functional_test.lst
│ └── README.md
├── cmake/
│ ├── FindSDL2.cmake
│ ├── FindSDL2_image.cmake
│ ├── FindSDL2_net.cmake
│ ├── FindSDL2_ttf.cmake
│ └── README.md
├── doc/
│ ├── .gitignore
│ └── doxygen.conf
├── res/
│ └── emudore.rc
└── src/
├── c64.cpp
├── c64.h
├── cia1.cpp
├── cia1.h
├── cia2.cpp
├── cia2.h
├── cpu.cpp
├── cpu.h
├── debugger.cpp
├── debugger.h
├── io.cpp
├── io.h
├── loader.cpp
├── loader.h
├── main.cpp
├── memory.cpp
├── memory.h
├── sid.h
├── util.h
├── vic.cpp
└── vic.h
================================================
FILE CONTENTS
================================================
================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required (VERSION 2.8)
project(emudore)
set(SRC_FILES "src/c64.cpp"
"src/cpu.cpp"
"src/memory.cpp"
"src/cia1.cpp"
"src/cia2.cpp"
"src/vic.cpp"
"src/io.cpp"
"src/loader.cpp"
"src/main.cpp")
# GCC and Clang
if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Wall")
# C++11
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
endif()
# r2 debugging support, for now only available on Linux
# and OSX Debug builds, if you want it enabled on release
# mode just remove the second part of the expression
if(CMAKE_BUILD_TYPE MATCHES "Debug" AND
(CMAKE_SYSTEM_NAME MATCHES "Linux" OR CMAKE_SYSTEM_NAME MATCHES "Darwin"))
add_definitions(-DDEBUGGER_SUPPORT)
set(SRC_FILES ${SRC_FILES} "src/debugger.cpp")
endif()
# MSVC, using pre-built binaries downloaded from:
# https://www.libsdl.org/download-2.0.php
if (MSVC)
set(SDL2_PATH "C:\\SDL2")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
add_executable (emudore ${SRC_FILES} res/emudore.rc)
set_target_properties(emudore PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:WINDOWS")
set_target_properties(emudore PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
else()
add_executable (emudore ${SRC_FILES})
endif()
# JavaScript and WebAssembly builds with emscripten
if(CMAKE_SYSTEM_NAME MATCHES "Emscripten")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O2 -s USE_SDL=2 -s DISABLE_EXCEPTION_CATCHING=0 --preload-file assets/roms/")
if(WASM)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s WASM=1")
endif()
endif()
# SDL2
# Cmake 2.8 does not provide scripts to find SDL2, adding
# them to the cmake module path and here for convenience
if(NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
find_package(SDL2 REQUIRED)
include_directories(${SDL2_INCLUDE_DIR})
endif()
# link
target_link_libraries(emudore ${SDL2_LIBRARY})
# copy assets to build directory
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/assets/ ${CMAKE_BINARY_DIR}/assets/)
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: Makefile
================================================
release:
rm -rf build/*
cd build;cmake -DCMAKE_BUILD_TYPE=Release ..
cd build;make
debug:
rm -rf build/*
cd build;cmake -DCMAKE_BUILD_TYPE=Debug ..
cd build;make
js:
rm -rf build/*
cd build;cmake -DCMAKE_TOOLCHAIN_FILE=~/emsdk/emscripten/incoming/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_BUILD_TYPE=Release ..
cd build;make
wasm:
rm -rf build/*
cd build;cmake -DCMAKE_TOOLCHAIN_FILE=~/emsdk/emscripten/incoming/cmake/Modules/Platform/Emscripten.cmake -DWASM=1 -DCMAKE_BUILD_TYPE=Release ..
cd build;make
================================================
FILE: README.md
================================================
# emudore, a Commodore 64 emulator

# What's this?
emudore is a [Commodore 64 emulator](https://en.wikipedia.org/wiki/Commodore_64),
fully written from the scratch and built on the top of the following technologies:
* [C++11](https://en.wikipedia.org/wiki/C%2B%2B11)
* [SDL2](https://www.libsdl.org/download-2.0.php)
emudore builds and runs on Linux, Windows (Visual Studio), OSX and even runs in
your browser thanks to Emscriptem, it should theoretically work on any platform
supported by SDL2 provided a C++11 compiler is available.
# JavaScript and WebAssembly builds
If you wish to play a bit around without having to go through the hassle of
compiling it you can try the web build:
* [emudore (boot into CBM BASIC)](http://marioballano.github.io/emudorejs/)
* [emudore (load Monopole PRG)](http://marioballano.github.io/emudorejs/?load=samples/monopole.prg)
A [WebAssembly](https://en.wikipedia.org/wiki/WebAssembly) build of emudore is also available,
please note that a browser with WebAssembly support is required to run these demos:
* [emudore (boot into CBM BASIC)](http://marioballano.github.io/emudorewa/)
* [emudore (load Monopole PRG)](http://marioballano.github.io/emudorewa/?load=samples/monopole.prg)
# Why am I writing another C64 emulator?
Long story short: to learn a bit more about computer architecture, graphics,
C++, etc.. while having some fun!
The Commodore 64 is regarded as one of the most epic 8-bit computers, it was actually
the first computer I ever laid hands on - thanks to my dad :) - and it seemed like a
sound choice to write an emulator for.
# Does this even work?
Well, yeah, mostly...
The BASIC ROM runs just fine, and most simple programs run without issues, however, many
of the more advanced games written in ML do not yet play well due to unimplemented hardware
features, writing an emulator is a tough task and after all my goal wasn't to write a full
perfect emulator but to learn in the process of making a simple one, here follow some facts
you might be interested in knowing about emudore's implementation:
**emulation is instruction-exact**
That's right, on every emulation cycle a single instruction is fetched and interpreted,
the number of CPU cycles the instruction has taken to execute is used to synchronize the
rest of the chips in a C64 board.
Unfortunately, this is not the best approach, other emulators are able to execute a single
instruction over multiple iterations of their emulation loop and mimic more accurately
the behaviour of the real hardware, however, this is an easier approach to implement
and does not impede the emulation from being relatively accurate.
**illegal opcodes not supported yet**
As many other architectures the MOS 6510 features a number of undocumented opcodes,
most of these are thought to be unintended and usually perform a mix of other opcodes
operations:
[NMOS 6510 Unintended Opcodes - PDF](http://csdb.dk/getinternalfile.php/135165/NoMoreSecrets-NMOS6510UnintendedOpcodes-20142412.pdf)
Nevertheless, some of these unintended opcodes have proven to be useful and are often
used in games and demos, emudore will need to support these in the future if we ever
intend to emulate serious games and demos.
**single-threaded**
emudore has been written as a single-threaded program, everything (including graphics) is
handled within the same thread, again, this approach has possibly some drawbacks, especially
in terms of performance, but it greatly simplifies the architecture: things like
synchronization of the mainboard chips become easier to implement.
**hardware acceleration and vertical refresh sync**
The screen is refreshed once at the end of every frame, when the video raster reaches the
last visible scanline, this way we're not constantly writing to the host video memory.
Also, to speed things up a bit I implemented hardware acceleration, we use an accelerated
renderer and streaming textures, unfortunately, we need to keep the rendered video frame
within emudore's memory and upload the texture to the GPU on every frame, direct pixel-access
is not doable straight on the GPU memory.
I also implemented vertical refresh synchronization, at the end of every frame we check
whether we are ahead of time compared to a real C64 computer, if that's the case we sleep
for a bit and wake up at the point a real C64 would have finished rendering the frame, this
effectively locks the screen refresh down to ~50Hz (PAL).
There are two main benefits of implementing vsync: it helps with performance since GPU
operations are costly and after all we don't want to run at the limit of fps our GPU can
handle; also, and more importantly, by doing this we emulate the speed of the real C64
computer synce the CPU and other chips are synchronized and run within the same thread, if
we are on a fast computer visual effects won't look accelerated and games become playable :)
**VIC-II chip**
The vic-ii is a relatively complex chip, my implementation is not yet complete whatsoever,
and certain features are more than likely still buggy, for now four out of the five official
graphic modes are supported:
* standard character mode
* multicolor character mode
* standard bitmap mode
* multicolor bitmap mode
Smooth scrolling, sprites and raster interrupts have also been implemented and badlines
are also emulated.
Some things that are left to implement include: sprite double height/width mode, sprite
collision interrupts, etc.
A simple approach was taken to emulate the raster beam drawing, pixels drawn to the
screen surface are computed at the end of each scan line, this might result in
certain graphic effects being badly emulated, bear in mind that timing is of the essence
in the c64, well-versed programmers master and exploit it to put together amazing
effects that otherwise wouldn't be feasible.
**beware**
Due to some of the aforementioned facts, expect things to fail, don't even dream
the emulation is going to be pixel-exact, certain effects are likely to get badly
emulated, specially if you're running things like a demo.
# Are you bleedin' serious radare2 is supported?
Indeed, for now it's only suppported on Linux and OSX (debug) builds, you can grab
a fresh copy of radare from [github](https://github.com/radare/radare2)
Then fire the emulator up and connect with radare:
r2 -w -a 6502 rap://localhost:9999//
For now radare can just read and modify memory, further support might be coming
down the line once [this feature](https://github.com/radare/radare2/issues/4173)
gets implemented in radare.
Some pictures of radare in action:


I hope this feature will come in useful to retrodev reverse engineers :)
# So now .. what?
There are many features of the currently emulated chips that I haven't implemented
yet, time permitting my plan is to keep working and learning about other aspects of
the C64 technology, also, at some stage I'd love to get the time to work on:
* Sound support: [SID](https://en.wikipedia.org/wiki/MOS_Technology_SID)
* Floppy drive support: [VIC-1541](https://en.wikipedia.org/wiki/Commodore_1541)
# Alright, enough of your jibba-jabba, how do I run this?
If you are running a Linux Debian-based distro:
sudo apt-get install g++ cmake libsdl2-dev
Then simply compile and run:
make release
cd build
./emudore
# What C64 programs can I load into this?
For the time being emudore can load PRGs, you can test:
./emudore assets/prg/monopole.prg
emudore can also type BASIC listings for you (special keys not supported yet):
./emudore assets/bas/10print.bas
(then type RUN at the emulator window)
# Got some more screenshots?
Sure..
  
  
# References
If you are interested in computer archeology, and particularly in the C64, among
others, the following resources came in handy to develop (and get inspiration) while
developing emudore:
* [The C64 Wiki](http://www.c64-wiki.com/)
* [Programming the Commodore 64: The Definitive Guide](http://www.amazon.co.uk/Programming-Commodore-64-Definitive-Guide/dp/0874550815/)
* [Commodore: A Company on the Edge (book)](http://www.amazon.co.uk/Commodore-Company-Edge-Brian-Bagnall/dp/0973864966/)
* [The Ultimate Commodore 64 Talk](https://www.youtube.com/watch?v=ZsRRCnque2E)
* [Behind the scenes of a C64 demo](https://www.youtube.com/watch?v=So-m4NUzKLw)
* [Dustlayer's blog](http://dustlayer.com/blog/)
* [The MOS 6567/6569 video controller (VIC-II) and its application in the Commodore 64](http://www.zimmers.net/cbmpics/cbm/c64/vic-ii.txt)
# Forks
Some people have forked emudore and experimented with it, some notable forks include:
* [Chris Frantz's C64 and NES emulator](https://github.com/cfrantz/emudore)
* [Scott Hutter's bare metal x86-64 emulator](https://github.com/xlar54/emudore64)
# License
I don't think anybody will ever dare to use this for an actual useful purpose, but just in case,
the project is licensed under the [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0)
================================================
FILE: assets/bas/10print.bas
================================================
REM source: http://10print.org/
10 PRINT CHR$(205.5+RND(1)); : GOTO 10
================================================
FILE: assets/bas/bitmap.bas
================================================
10 POKE 53272,PEEK(53272)OR8:POKE 53265,PEEK(53265)OR32
20 FORI=8192TO16191 STEP 8
30 POKEI,240:POKEI+1,240:POKEI+2,240:POKEI+3,240
40 POKEI+4,15:POKEI+5,15:POKEI+6,15:POKEI+7,15
50 NEXT
60 FORI=1024TO2034:POKEI,251:NEXT
70 GOTO 70
================================================
FILE: assets/bas/bouncing.bas
================================================
REM source: http://www.lemon64.com/manual/
NEW
10 POKE 53281,1: PRINT"*"
20 POKE 53280,7: POKE 53281,6
30 X = 1 : Y = 1
40 DX = 1 : DY = 1
50 POKE 1024 + X + 40 * Y, 81
60 FOR T = 1 TO 10 : NEXT
70 POKE 1024 + X + 40 * Y, 32
80 X = X + DX
90 IF X <= 0 OR X >= 39 THEN DX = -DX
100 Y = Y + DY
110 IF Y <= 0 OR Y >= 24 THEN DY = -DY
120 GOTO 50
================================================
FILE: assets/bas/lowercase.bas
================================================
REM SWITCH TO LOWERCASE MODE
POKE 53272,23
================================================
FILE: assets/roms/README.md
================================================
The following files have been downloaded from:
ftp://www.zimmers.net/pub/cbm/firmware/computers/c64/
Please, bear in mind that these files might be subject to other licenses
than emudore's
# kernal.901227-03.bin
This 8-kilobyte 2364 ROM is the third and essentially last revision of
the Commodore 64 KERNAL. It is the most widely spread version.
# basic.901226-01.bin
Commodore 64 BASIC V2. The first and essentially only revision, located at
$A000-$BFFF. In the 64GS system firmware, the 30 unused bytes at $BF53-$BF70
are filled with $00 instead of $AA. In the Commodore 65 firmware, these bytes
are filled with $FF.
# characters.901225-01.bin
The character generator ROM.
================================================
FILE: assets/tests/6502_functional_test.a65
================================================
;
; 6 5 0 2 F U N C T I O N A L T E S T
;
; Copyright (C) 2012-2015 Klaus Dormann
;
; 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 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
; This program is designed to test all opcodes of a 6502 emulator using all
; addressing modes with focus on propper setting of the processor status
; register bits.
;
; version 21-oct-2015
; contact info at http://2m5.de or email K@2m5.de
;
; assembled with AS65 from http://www.kingswood-consulting.co.uk/assemblers/
; command line switches: -l -m -s2 -w -h0
; | | | | no page headers in listing
; | | | wide listing (133 char/col)
; | | write intel hex file instead of binary
; | expand macros in listing
; generate pass2 listing
;
; No IO - should be run from a monitor with access to registers.
; To run load intel hex image with a load command, than alter PC to 400 hex
; (code_segment) and enter a go command.
; Loop on program counter determines error or successful completion of test.
; Check listing for relevant traps (jump/branch *).
; Please note that in early tests some instructions will have to be used before
; they are actually tested!
;
; RESET, NMI or IRQ should not occur and will be trapped if vectors are enabled.
; Tests documented behavior of the original NMOS 6502 only! No unofficial
; opcodes. Additional opcodes of newer versions of the CPU (65C02, 65816) will
; not be tested. Decimal ops will only be tested with valid BCD operands and
; N V Z flags will be ignored.
;
; Debugging hints:
; Most of the code is written sequentially. if you hit a trap, check the
; immediately preceeding code for the instruction to be tested. Results are
; tested first, flags are checked second by pushing them onto the stack and
; pulling them to the accumulator after the result was checked. The "real"
; flags are no longer valid for the tested instruction at this time!
; If the tested instruction was indexed, the relevant index (X or Y) must
; also be checked. Opposed to the flags, X and Y registers are still valid.
;
; versions:
; 28-jul-2012 1st version distributed for testing
; 29-jul-2012 fixed references to location 0, now #0
; added license - GPLv3
; 30-jul-2012 added configuration options
; 01-aug-2012 added trap macro to allow user to change error handling
; 01-dec-2012 fixed trap in branch field must be a branch
; 02-mar-2013 fixed PLA flags not tested
; 19-jul-2013 allowed ROM vectors to be loaded when load_data_direct = 0
; added test sequence check to detect if tests jump their fence
; 23-jul-2013 added RAM integrity check option
; 16-aug-2013 added error report to standard output option
; 13-dec-2014 added binary/decimal opcode table switch test
; 14-dec-2014 improved relative address test
; 23-aug-2015 added option to disable self modifying tests
; 24-aug-2015 all self modifying immediate opcodes now execute in data RAM
; added small branch offset pretest
; 21-oct-2015 added option to disable decimal mode ADC & SBC tests
; C O N F I G U R A T I O N
;ROM_vectors writable (0=no, 1=yes)
;if ROM vectors can not be used interrupts will not be trapped
;as a consequence BRK can not be tested but will be emulated to test RTI
ROM_vectors = 1
;load_data_direct (0=move from code segment, 1=load directly)
;loading directly is preferred but may not be supported by your platform
;0 produces only consecutive object code, 1 is not suitable for a binary image
load_data_direct = 0
;I_flag behavior (0=force enabled, 1=force disabled, 2=prohibit change, 3=allow
;change) 2 requires extra code and is not recommended. SEI & CLI can only be
;tested if you allow changing the interrupt status (I_flag = 3)
I_flag = 3
;configure memory - try to stay away from memory used by the system
;zero_page memory start address, $50 (80) consecutive Bytes required
; add 2 if I_flag = 2
zero_page = $a
;data_segment memory start address, $6A (106) consecutive Bytes required
data_segment = $200
if (data_segment & $ff) != 0
ERROR ERROR ERROR low byte of data_segment MUST be $00 !!
endif
;code_segment memory start address, 13kB of consecutive space required
; add 2.5 kB if I_flag = 2
code_segment = $400
;self modifying code may be disabled to allow running in ROM
;0=part of the code is self modifying and must reside in RAM
;1=tests disabled: branch range
disable_selfmod = 0
;report errors through I/O channel (0=use standard self trap loops, 1=include
;report.i65 as I/O channel, add 3.5 kB)
report = 0
;RAM integrity test option. Checks for undesired RAM writes.
;set lowest non RAM or RAM mirror address page (-1=disable, 0=64k, $40=16k)
;leave disabled if a monitor, OS or background interrupt is allowed to alter RAM
ram_top = -1
;disable test decimal mode ADC & SBC, 0=enable, 1=disable,
;2=disable including decimal flag in processor status
disable_decimal = 0
noopt ;do not take shortcuts
;macros for error & success traps to allow user modification
;example:
;trap macro
; jsr my_error_handler
; endm
;trap_eq macro
; bne skip\?
; trap ;failed equal (zero)
;skip\?
; endm
;
; my_error_handler should pop the calling address from the stack and report it.
; putting larger portions of code (more than 3 bytes) inside the trap macro
; may lead to branch range problems for some tests.
if report = 0
trap macro
jmp * ;failed anyway
endm
trap_eq macro
beq * ;failed equal (zero)
endm
trap_ne macro
bne * ;failed not equal (non zero)
endm
trap_cs macro
bcs * ;failed carry set
endm
trap_cc macro
bcc * ;failed carry clear
endm
trap_mi macro
bmi * ;failed minus (bit 7 set)
endm
trap_pl macro
bpl * ;failed plus (bit 7 clear)
endm
trap_vs macro
bvs * ;failed overflow set
endm
trap_vc macro
bvc * ;failed overflow clear
endm
; please observe that during the test the stack gets invalidated
; therefore a RTS inside the success macro is not possible
success macro
jmp * ;test passed, no errors
endm
endif
if report = 1
trap macro
jsr report_error
endm
trap_eq macro
bne skip\?
trap ;failed equal (zero)
skip\?
endm
trap_ne macro
beq skip\?
trap ;failed not equal (non zero)
skip\?
endm
trap_cs macro
bcc skip\?
trap ;failed carry set
skip\?
endm
trap_cc macro
bcs skip\?
trap ;failed carry clear
skip\?
endm
trap_mi macro
bpl skip\?
trap ;failed minus (bit 7 set)
skip\?
endm
trap_pl macro
bmi skip\?
trap ;failed plus (bit 7 clear)
skip\?
endm
trap_vs macro
bvc skip\?
trap ;failed overflow set
skip\?
endm
trap_vc macro
bvs skip\?
trap ;failed overflow clear
skip\?
endm
; please observe that during the test the stack gets invalidated
; therefore a RTS inside the success macro is not possible
success macro
jsr report_success
endm
endif
carry equ %00000001 ;flag bits in status
zero equ %00000010
intdis equ %00000100
decmode equ %00001000
break equ %00010000
reserv equ %00100000
overfl equ %01000000
minus equ %10000000
fc equ carry
fz equ zero
fzc equ carry+zero
fv equ overfl
fvz equ overfl+zero
fn equ minus
fnc equ minus+carry
fnz equ minus+zero
fnzc equ minus+zero+carry
fnv equ minus+overfl
fao equ break+reserv ;bits always on after PHP, BRK
fai equ fao+intdis ;+ forced interrupt disable
faod equ fao+decmode ;+ ignore decimal
faid equ fai+decmode ;+ ignore decimal
m8 equ $ff ;8 bit mask
m8i equ $ff&~intdis ;8 bit mask - interrupt disable
;macros to allow masking of status bits.
;masking test of decimal bit
;masking of interrupt enable/disable on load and compare
;masking of always on bits after PHP or BRK (unused & break) on compare
if disable_decimal < 2
if I_flag = 0
load_flag macro
lda #\1&m8i ;force enable interrupts (mask I)
endm
cmp_flag macro
cmp #(\1|fao)&m8i ;I_flag is always enabled + always on bits
endm
eor_flag macro
eor #(\1&m8i|fao) ;mask I, invert expected flags + always on bits
endm
endif
if I_flag = 1
load_flag macro
lda #\1|intdis ;force disable interrupts
endm
cmp_flag macro
cmp #(\1|fai)&m8 ;I_flag is always disabled + always on bits
endm
eor_flag macro
eor #(\1|fai) ;invert expected flags + always on bits + I
endm
endif
if I_flag = 2
load_flag macro
lda #\1
ora flag_I_on ;restore I-flag
and flag_I_off
endm
cmp_flag macro
eor flag_I_on ;I_flag is never changed
cmp #(\1|fao)&m8i ;expected flags + always on bits, mask I
endm
eor_flag macro
eor flag_I_on ;I_flag is never changed
eor #(\1&m8i|fao) ;mask I, invert expected flags + always on bits
endm
endif
if I_flag = 3
load_flag macro
lda #\1 ;allow test to change I-flag (no mask)
endm
cmp_flag macro
cmp #(\1|fao)&m8 ;expected flags + always on bits
endm
eor_flag macro
eor #\1|fao ;invert expected flags + always on bits
endm
endif
else
if I_flag = 0
load_flag macro
lda #\1&m8i ;force enable interrupts (mask I)
endm
cmp_flag macro
ora #decmode ;ignore decimal mode bit
cmp #(\1|faod)&m8i ;I_flag is always enabled + always on bits
endm
eor_flag macro
ora #decmode ;ignore decimal mode bit
eor #(\1&m8i|faod) ;mask I, invert expected flags + always on bits
endm
endif
if I_flag = 1
load_flag macro
lda #\1|intdis ;force disable interrupts
endm
cmp_flag macro
ora #decmode ;ignore decimal mode bit
cmp #(\1|faid)&m8 ;I_flag is always disabled + always on bits
endm
eor_flag macro
ora #decmode ;ignore decimal mode bit
eor #(\1|faid) ;invert expected flags + always on bits + I
endm
endif
if I_flag = 2
load_flag macro
lda #\1
ora flag_I_on ;restore I-flag
and flag_I_off
endm
cmp_flag macro
eor flag_I_on ;I_flag is never changed
ora #decmode ;ignore decimal mode bit
cmp #(\1|faod)&m8i ;expected flags + always on bits, mask I
endm
eor_flag macro
eor flag_I_on ;I_flag is never changed
ora #decmode ;ignore decimal mode bit
eor #(\1&m8i|faod) ;mask I, invert expected flags + always on bits
endm
endif
if I_flag = 3
load_flag macro
lda #\1 ;allow test to change I-flag (no mask)
endm
cmp_flag macro
ora #decmode ;ignore decimal mode bit
cmp #(\1|faod)&m8 ;expected flags + always on bits
endm
eor_flag macro
ora #decmode ;ignore decimal mode bit
eor #\1|faod ;invert expected flags + always on bits
endm
endif
endif
;macros to set (register|memory|zeropage) & status
set_stat macro ;setting flags in the processor status register
load_flag \1
pha ;use stack to load status
plp
endm
set_a macro ;precharging accu & status
load_flag \2
pha ;use stack to load status
lda #\1 ;precharge accu
plp
endm
set_x macro ;precharging index & status
load_flag \2
pha ;use stack to load status
ldx #\1 ;precharge index x
plp
endm
set_y macro ;precharging index & status
load_flag \2
pha ;use stack to load status
ldy #\1 ;precharge index y
plp
endm
set_ax macro ;precharging indexed accu & immediate status
load_flag \2
pha ;use stack to load status
lda \1,x ;precharge accu
plp
endm
set_ay macro ;precharging indexed accu & immediate status
load_flag \2
pha ;use stack to load status
lda \1,y ;precharge accu
plp
endm
set_z macro ;precharging indexed zp & immediate status
load_flag \2
pha ;use stack to load status
lda \1,x ;load to zeropage
sta zpt
plp
endm
set_zx macro ;precharging zp,x & immediate status
load_flag \2
pha ;use stack to load status
lda \1,x ;load to indexed zeropage
sta zpt,x
plp
endm
set_abs macro ;precharging indexed memory & immediate status
load_flag \2
pha ;use stack to load status
lda \1,x ;load to memory
sta abst
plp
endm
set_absx macro ;precharging abs,x & immediate status
load_flag \2
pha ;use stack to load status
lda \1,x ;load to indexed memory
sta abst,x
plp
endm
;macros to test (register|memory|zeropage) & status & (mask)
tst_stat macro ;testing flags in the processor status register
php ;save status
pla ;use stack to retrieve status
pha
cmp_flag \1
trap_ne
plp ;restore status
endm
tst_a macro ;testing result in accu & flags
php ;save flags
cmp #\1 ;test result
trap_ne
pla ;load status
pha
cmp_flag \2
trap_ne
plp ;restore status
endm
tst_x macro ;testing result in x index & flags
php ;save flags
cpx #\1 ;test result
trap_ne
pla ;load status
pha
cmp_flag \2
trap_ne
plp ;restore status
endm
tst_y macro ;testing result in y index & flags
php ;save flags
cpy #\1 ;test result
trap_ne
pla ;load status
pha
cmp_flag \2
trap_ne
plp ;restore status
endm
tst_ax macro ;indexed testing result in accu & flags
php ;save flags
cmp \1,x ;test result
trap_ne
pla ;load status
eor_flag \3
cmp \2,x ;test flags
trap_ne ;
endm
tst_ay macro ;indexed testing result in accu & flags
php ;save flags
cmp \1,y ;test result
trap_ne ;
pla ;load status
eor_flag \3
cmp \2,y ;test flags
trap_ne
endm
tst_z macro ;indexed testing result in zp & flags
php ;save flags
lda zpt
cmp \1,x ;test result
trap_ne
pla ;load status
eor_flag \3
cmp \2,x ;test flags
trap_ne
endm
tst_zx macro ;testing result in zp,x & flags
php ;save flags
lda zpt,x
cmp \1,x ;test result
trap_ne
pla ;load status
eor_flag \3
cmp \2,x ;test flags
trap_ne
endm
tst_abs macro ;indexed testing result in memory & flags
php ;save flags
lda abst
cmp \1,x ;test result
trap_ne
pla ;load status
eor_flag \3
cmp \2,x ;test flags
trap_ne
endm
tst_absx macro ;testing result in abs,x & flags
php ;save flags
lda abst,x
cmp \1,x ;test result
trap_ne
pla ;load status
eor_flag \3
cmp \2,x ;test flags
trap_ne
endm
; RAM integrity test
; verifies that none of the previous tests has altered RAM outside of the
; designated write areas.
; uses zpt word as indirect pointer, zpt+2 word as checksum
if ram_top > -1
check_ram macro
cld
lda #0
sta zpt ;set low byte of indirect pointer
sta zpt+3 ;checksum high byte
if disable_selfmod = 0
sta range_adr ;reset self modifying code
endif
clc
ldx #zp_bss-zero_page ;zeropage - write test area
ccs3\? adc zero_page,x
bcc ccs2\?
inc zpt+3 ;carry to high byte
clc
ccs2\? inx
bne ccs3\?
ldx #hi(abs1) ;set high byte of indirect pointer
stx zpt+1
ldy #lo(abs1) ;data after write & execute test area
ccs5\? adc (zpt),y
bcc ccs4\?
inc zpt+3 ;carry to high byte
clc
ccs4\? iny
bne ccs5\?
inx ;advance RAM high address
stx zpt+1
cpx #ram_top
bne ccs5\?
sta zpt+2 ;checksum low is
cmp ram_chksm ;checksum low expected
trap_ne ;checksum mismatch
lda zpt+3 ;checksum high is
cmp ram_chksm+1 ;checksum high expected
trap_ne ;checksum mismatch
endm
else
check_ram macro
;RAM check disabled - RAM size not set
endm
endif
next_test macro ;make sure, tests don't jump the fence
lda test_case ;previous test
cmp #test_num
trap_ne ;test is out of sequence
test_num = test_num + 1
lda #test_num ;*** next tests' number
sta test_case
;check_ram ;uncomment to find altered RAM after each test
endm
if load_data_direct = 1
data
else
bss ;uninitialized segment, copy of data at end of code!
endif
org zero_page
;break test interrupt save
irq_a ds 1 ;a register
irq_x ds 1 ;x register
if I_flag = 2
;masking for I bit in status
flag_I_on ds 1 ;or mask to load flags
flag_I_off ds 1 ;and mask to load flags
endif
zpt ;5 bytes store/modify test area
;add/subtract operand generation and result/flag prediction
adfc ds 1 ;carry flag before op
ad1 ds 1 ;operand 1 - accumulator
ad2 ds 1 ;operand 2 - memory / immediate
adrl ds 1 ;expected result bits 0-7
adrh ds 1 ;expected result bit 8 (carry)
adrf ds 1 ;expected flags NV0000ZC (only binary mode)
sb2 ds 1 ;operand 2 complemented for subtract
zp_bss
zp1 db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
zp7f db $7f ;test pattern for compare
;logical zeropage operands
zpOR db 0,$1f,$71,$80 ;test pattern for OR
zpAN db $0f,$ff,$7f,$80 ;test pattern for AND
zpEO db $ff,$0f,$8f,$8f ;test pattern for EOR
;indirect addressing pointers
ind1 dw abs1 ;indirect pointer to pattern in absolute memory
dw abs1+1
dw abs1+2
dw abs1+3
dw abs7f
inw1 dw abs1-$f8 ;indirect pointer for wrap-test pattern
indt dw abst ;indirect pointer to store area in absolute memory
dw abst+1
dw abst+2
dw abst+3
inwt dw abst-$f8 ;indirect pointer for wrap-test store
indAN dw absAN ;indirect pointer to AND pattern in absolute memory
dw absAN+1
dw absAN+2
dw absAN+3
indEO dw absEO ;indirect pointer to EOR pattern in absolute memory
dw absEO+1
dw absEO+2
dw absEO+3
indOR dw absOR ;indirect pointer to OR pattern in absolute memory
dw absOR+1
dw absOR+2
dw absOR+3
;add/subtract indirect pointers
adi2 dw ada2 ;indirect pointer to operand 2 in absolute memory
sbi2 dw sba2 ;indirect pointer to complemented operand 2 (SBC)
adiy2 dw ada2-$ff ;with offset for indirect indexed
sbiy2 dw sba2-$ff
zp_bss_end
org data_segment
test_case ds 1 ;current test number
ram_chksm ds 2 ;checksum for RAM integrity test
;add/subtract operand copy - abs tests write area
abst ;5 bytes store/modify test area
ada2 ds 1 ;operand 2
sba2 ds 1 ;operand 2 complemented for subtract
ds 3 ;fill remaining bytes
data_bss
if load_data_direct = 1
ex_andi and #0 ;execute immediate opcodes
rts
ex_eori eor #0 ;execute immediate opcodes
rts
ex_orai ora #0 ;execute immediate opcodes
rts
ex_adci adc #0 ;execute immediate opcodes
rts
ex_sbci sbc #0 ;execute immediate opcodes
rts
else
ex_andi ds 3
ex_eori ds 3
ex_orai ds 3
ex_adci ds 3
ex_sbci ds 3
endif
abs1 db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
abs7f db $7f ;test pattern for compare
;loads
fLDx db fn,fn,0,fz ;expected flags for load
;shifts
rASL ;expected result ASL & ROL -carry
rROL db $86,$04,$82,0 ; "
rROLc db $87,$05,$83,1 ;expected result ROL +carry
rLSR ;expected result LSR & ROR -carry
rROR db $61,$41,$20,0 ; "
rRORc db $e1,$c1,$a0,$80 ;expected result ROR +carry
fASL ;expected flags for shifts
fROL db fnc,fc,fn,fz ;no carry in
fROLc db fnc,fc,fn,0 ;carry in
fLSR
fROR db fc,0,fc,fz ;no carry in
fRORc db fnc,fn,fnc,fn ;carry in
;increments (decrements)
rINC db $7f,$80,$ff,0,1 ;expected result for INC/DEC
fINC db 0,fn,fn,fz,0 ;expected flags for INC/DEC
;logical memory operand
absOR db 0,$1f,$71,$80 ;test pattern for OR
absAN db $0f,$ff,$7f,$80 ;test pattern for AND
absEO db $ff,$0f,$8f,$8f ;test pattern for EOR
;logical accu operand
absORa db 0,$f1,$1f,0 ;test pattern for OR
absANa db $f0,$ff,$ff,$ff ;test pattern for AND
absEOa db $ff,$f0,$f0,$0f ;test pattern for EOR
;logical results
absrlo db 0,$ff,$7f,$80
absflo db fz,fn,0,fn
data_bss_end
code
org code_segment
start cld
ldx #$ff
txs
lda #0 ;*** test 0 = initialize
sta test_case
test_num = 0
;stop interrupts before initializing BSS
if I_flag = 1
sei
endif
;initialize I/O for report channel
if report = 1
jsr report_init
endif
;pretest small branch offset
ldx #5
jmp psb_test
psb_bwok
ldy #5
bne psb_forw
trap ;branch should be taken
dey ;forward landing zone
dey
dey
dey
dey
psb_forw
dey
dey
dey
dey
dey
beq psb_fwok
trap ;forward offset
dex ;backward landing zone
dex
dex
dex
dex
psb_back
dex
dex
dex
dex
dex
beq psb_bwok
trap ;backward offset
psb_test
bne psb_back
trap ;branch should be taken
psb_fwok
;initialize BSS segment
if load_data_direct != 1
ldx #zp_end-zp_init-1
ld_zp lda zp_init,x
sta zp_bss,x
dex
bpl ld_zp
ldx #data_end-data_init-1
ld_data lda data_init,x
sta data_bss,x
dex
bpl ld_data
if ROM_vectors = 1
ldx #5
ld_vect lda vec_init,x
sta vec_bss,x
dex
bpl ld_vect
endif
endif
;retain status of interrupt flag
if I_flag = 2
php
pla
and #4 ;isolate flag
sta flag_I_on ;or mask
eor #lo(~4) ;reverse
sta flag_I_off ;and mask
endif
;generate checksum for RAM integrity test
if ram_top > -1
lda #0
sta zpt ;set low byte of indirect pointer
sta ram_chksm+1 ;checksum high byte
if disable_selfmod = 0
sta range_adr ;reset self modifying code
endif
clc
ldx #zp_bss-zero_page ;zeropage - write test area
gcs3 adc zero_page,x
bcc gcs2
inc ram_chksm+1 ;carry to high byte
clc
gcs2 inx
bne gcs3
ldx #hi(abs1) ;set high byte of indirect pointer
stx zpt+1
ldy #lo(abs1) ;data after write & execute test area
gcs5 adc (zpt),y
bcc gcs4
inc ram_chksm+1 ;carry to high byte
clc
gcs4 iny
bne gcs5
inx ;advance RAM high address
stx zpt+1
cpx #ram_top
bne gcs5
sta ram_chksm ;checksum complete
endif
next_test
if disable_selfmod = 0
;testing relative addressing with BEQ
ldy #$fe ;testing maximum range, not -1/-2 (invalid/self adr)
range_loop
dey ;next relative address
tya
tax ;precharge count to end of loop
bpl range_fw ;calculate relative address
clc ;avoid branch self or to relative address of branch
adc #2
nop ;offset landing zone - tolerate +/-5 offset to branch
nop
nop
nop
nop
range_fw
nop
nop
nop
nop
nop
eor #$7f ;complement except sign
sta range_adr ;load into test target
lda #0 ;should set zero flag in status register
jmp range_op
dex ; offset landing zone - backward branch too far
dex
dex
dex
dex
;relative address target field with branch under test in the middle
dex ;-128 - max backward
dex
dex
dex
dex
dex
dex
dex
dex ;-120
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;-110
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;-100
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;-90
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;-80
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;-70
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;-60
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;-50
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;-40
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;-30
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;-20
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;-10
dex
dex
dex
dex
dex
dex
dex ;-3
range_op ;test target with zero flag=0, z=1 if previous dex
range_adr = *+1 ;modifiable relative address
beq *+64 ;+64 if called without modification
dex ;+0
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;+10
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;+20
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;+30
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;+40
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;+50
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;+60
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;+70
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;+80
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;+90
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;+100
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;+110
dex
dex
dex
dex
dex
dex
dex
dex
dex
dex ;+120
dex
dex
dex
dex
dex
dex
nop ;offset landing zone - forward branch too far
nop
nop
nop
nop
beq range_ok ;+127 - max forward
trap ; bad range
nop ;offset landing zone - tolerate +/-5 offset to branch
nop
nop
nop
nop
range_ok
nop
nop
nop
nop
nop
cpy #0
beq range_end
jmp range_loop
range_end ;range test successful
endif
next_test
;partial test BNE & CMP, CPX, CPY immediate
cpy #1 ;testing BNE true
bne test_bne
trap
test_bne
lda #0
cmp #0 ;test compare immediate
trap_ne
trap_cc
trap_mi
cmp #1
trap_eq
trap_cs
trap_pl
tax
cpx #0 ;test compare x immediate
trap_ne
trap_cc
trap_mi
cpx #1
trap_eq
trap_cs
trap_pl
tay
cpy #0 ;test compare y immediate
trap_ne
trap_cc
trap_mi
cpy #1
trap_eq
trap_cs
trap_pl
next_test
;testing stack operations PHA PHP PLA PLP
ldx #$ff ;initialize stack
txs
lda #$55
pha
lda #$aa
pha
cmp $1fe ;on stack ?
trap_ne
tsx
txa ;overwrite accu
cmp #$fd ;sp decremented?
trap_ne
pla
cmp #$aa ;successful retreived from stack?
trap_ne
pla
cmp #$55
trap_ne
cmp $1ff ;remains on stack?
trap_ne
tsx
cpx #$ff ;sp incremented?
trap_ne
next_test
;testing branch decisions BPL BMI BVC BVS BCC BCS BNE BEQ
set_stat $ff ;all on
bpl nbr1 ;branches should not be taken
bvc nbr2
bcc nbr3
bne nbr4
bmi br1 ;branches should be taken
trap
br1 bvs br2
trap
br2 bcs br3
trap
br3 beq br4
trap
nbr1
trap ;previous bpl taken
nbr2
trap ;previous bvc taken
nbr3
trap ;previous bcc taken
nbr4
trap ;previous bne taken
br4 php
tsx
cpx #$fe ;sp after php?
trap_ne
pla
cmp_flag $ff ;returned all flags on?
trap_ne
tsx
cpx #$ff ;sp after php?
trap_ne
set_stat 0 ;all off
bmi nbr11 ;branches should not be taken
bvs nbr12
bcs nbr13
beq nbr14
bpl br11 ;branches should be taken
trap
br11 bvc br12
trap
br12 bcc br13
trap
br13 bne br14
trap
nbr11
trap ;previous bmi taken
nbr12
trap ;previous bvs taken
nbr13
trap ;previous bcs taken
nbr14
trap ;previous beq taken
br14 php
pla
cmp_flag 0 ;flags off except break (pushed by sw) + reserved?
trap_ne
;crosscheck flags
set_stat zero
bne brzs1
beq brzs2
brzs1
trap ;branch zero/non zero
brzs2 bcs brzs3
bcc brzs4
brzs3
trap ;branch carry/no carry
brzs4 bmi brzs5
bpl brzs6
brzs5
trap ;branch minus/plus
brzs6 bvs brzs7
bvc brzs8
brzs7
trap ;branch overflow/no overflow
brzs8
set_stat carry
beq brcs1
bne brcs2
brcs1
trap ;branch zero/non zero
brcs2 bcc brcs3
bcs brcs4
brcs3
trap ;branch carry/no carry
brcs4 bmi brcs5
bpl brcs6
brcs5
trap ;branch minus/plus
brcs6 bvs brcs7
bvc brcs8
brcs7
trap ;branch overflow/no overflow
brcs8
set_stat minus
beq brmi1
bne brmi2
brmi1
trap ;branch zero/non zero
brmi2 bcs brmi3
bcc brmi4
brmi3
trap ;branch carry/no carry
brmi4 bpl brmi5
bmi brmi6
brmi5
trap ;branch minus/plus
brmi6 bvs brmi7
bvc brmi8
brmi7
trap ;branch overflow/no overflow
brmi8
set_stat overfl
beq brvs1
bne brvs2
brvs1
trap ;branch zero/non zero
brvs2 bcs brvs3
bcc brvs4
brvs3
trap ;branch carry/no carry
brvs4 bmi brvs5
bpl brvs6
brvs5
trap ;branch minus/plus
brvs6 bvc brvs7
bvs brvs8
brvs7
trap ;branch overflow/no overflow
brvs8
set_stat $ff-zero
beq brzc1
bne brzc2
brzc1
trap ;branch zero/non zero
brzc2 bcc brzc3
bcs brzc4
brzc3
trap ;branch carry/no carry
brzc4 bpl brzc5
bmi brzc6
brzc5
trap ;branch minus/plus
brzc6 bvc brzc7
bvs brzc8
brzc7
trap ;branch overflow/no overflow
brzc8
set_stat $ff-carry
bne brcc1
beq brcc2
brcc1
trap ;branch zero/non zero
brcc2 bcs brcc3
bcc brcc4
brcc3
trap ;branch carry/no carry
brcc4 bpl brcc5
bmi brcc6
brcc5
trap ;branch minus/plus
brcc6 bvc brcc7
bvs brcc8
brcc7
trap ;branch overflow/no overflow
brcc8
set_stat $ff-minus
bne brpl1
beq brpl2
brpl1
trap ;branch zero/non zero
brpl2 bcc brpl3
bcs brpl4
brpl3
trap ;branch carry/no carry
brpl4 bmi brpl5
bpl brpl6
brpl5
trap ;branch minus/plus
brpl6 bvc brpl7
bvs brpl8
brpl7
trap ;branch overflow/no overflow
brpl8
set_stat $ff-overfl
bne brvc1
beq brvc2
brvc1
trap ;branch zero/non zero
brvc2 bcc brvc3
bcs brvc4
brvc3
trap ;branch carry/no carry
brvc4 bpl brvc5
bmi brvc6
brvc5
trap ;branch minus/plus
brvc6 bvs brvc7
bvc brvc8
brvc7
trap ;branch overflow/no overflow
brvc8
next_test
; test PHA does not alter flags or accumulator but PLA does
ldx #$55 ;x & y protected
ldy #$aa
set_a 1,$ff ;push
pha
tst_a 1,$ff
set_a 0,0
pha
tst_a 0,0
set_a $ff,$ff
pha
tst_a $ff,$ff
set_a 1,0
pha
tst_a 1,0
set_a 0,$ff
pha
tst_a 0,$ff
set_a $ff,0
pha
tst_a $ff,0
set_a 0,$ff ;pull
pla
tst_a $ff,$ff-zero
set_a $ff,0
pla
tst_a 0,zero
set_a $fe,$ff
pla
tst_a 1,$ff-zero-minus
set_a 0,0
pla
tst_a $ff,minus
set_a $ff,$ff
pla
tst_a 0,$ff-minus
set_a $fe,0
pla
tst_a 1,0
cpx #$55 ;x & y unchanged?
trap_ne
cpy #$aa
trap_ne
next_test
; partial pretest EOR #
set_a $3c,0
eor #$c3
tst_a $ff,fn
set_a $c3,0
eor #$c3
tst_a 0,fz
next_test
; PC modifying instructions except branches (NOP, JMP, JSR, RTS, BRK, RTI)
; testing NOP
ldx #$24
ldy #$42
set_a $18,0
nop
tst_a $18,0
cpx #$24
trap_ne
cpy #$42
trap_ne
ldx #$db
ldy #$bd
set_a $e7,$ff
nop
tst_a $e7,$ff
cpx #$db
trap_ne
cpy #$bd
trap_ne
next_test
; jump absolute
set_stat $0
lda #'F'
ldx #'A'
ldy #'R' ;N=0, V=0, Z=0, C=0
jmp test_far
nop
nop
trap_ne ;runover protection
inx
inx
far_ret
trap_eq ;returned flags OK?
trap_pl
trap_cc
trap_vc
cmp #('F'^$aa) ;returned registers OK?
trap_ne
cpx #('A'+1)
trap_ne
cpy #('R'-3)
trap_ne
dex
iny
iny
iny
eor #$aa ;N=0, V=1, Z=0, C=1
jmp test_near
nop
nop
trap_ne ;runover protection
inx
inx
test_near
trap_eq ;passed flags OK?
trap_mi
trap_cc
trap_vc
cmp #'F' ;passed registers OK?
trap_ne
cpx #'A'
trap_ne
cpy #'R'
trap_ne
next_test
; jump indirect
set_stat 0
lda #'I'
ldx #'N'
ldy #'D' ;N=0, V=0, Z=0, C=0
jmp (ptr_tst_ind)
nop
trap_ne ;runover protection
dey
dey
ind_ret
php ;either SP or Y count will fail, if we do not hit
dey
dey
dey
plp
trap_eq ;returned flags OK?
trap_pl
trap_cc
trap_vc
cmp #('I'^$aa) ;returned registers OK?
trap_ne
cpx #('N'+1)
trap_ne
cpy #('D'-6)
trap_ne
tsx ;SP check
cpx #$ff
trap_ne
next_test
; jump subroutine & return from subroutine
set_stat 0
lda #'J'
ldx #'S'
ldy #'R' ;N=0, V=0, Z=0, C=0
jsr test_jsr
jsr_ret = *-1 ;last address of jsr = return address
php ;either SP or Y count will fail, if we do not hit
dey
dey
dey
plp
trap_eq ;returned flags OK?
trap_pl
trap_cc
trap_vc
cmp #('J'^$aa) ;returned registers OK?
trap_ne
cpx #('S'+1)
trap_ne
cpy #('R'-6)
trap_ne
tsx ;sp?
cpx #$ff
trap_ne
next_test
; break & return from interrupt
if ROM_vectors = 1
set_stat 0
lda #'B'
ldx #'R'
ldy #'K' ;N=0, V=0, Z=0, C=0
brk
else
lda #hi brk_ret ;emulated break
pha
lda #lo brk_ret
pha
lda #fao ;set break & unused on stack
pha
set_stat intdis
lda #'B'
ldx #'R'
ldy #'K' ;N=0, V=0, Z=0, C=0
jmp irq_trap
endif
dey ;should not be executed
brk_ret ;address of break return
php ;either SP or Y count will fail, if we do not hit
dey
dey
dey
cmp #('B'^$aa) ;returned registers OK?
trap_ne
cpx #('R'+1)
trap_ne
cpy #('K'-6)
trap_ne
pla ;returned flags OK (unchanged)?
cmp_flag 0
trap_ne
tsx ;sp?
cpx #$ff
trap_ne
next_test
; test set and clear flags CLC CLI CLD CLV SEC SEI SED
set_stat $ff
clc
tst_stat $ff-carry
sec
tst_stat $ff
if I_flag = 3
cli
tst_stat $ff-intdis
sei
tst_stat $ff
endif
cld
tst_stat $ff-decmode
sed
tst_stat $ff
clv
tst_stat $ff-overfl
set_stat 0
tst_stat 0
sec
tst_stat carry
clc
tst_stat 0
if I_flag = 3
sei
tst_stat intdis
cli
tst_stat 0
endif
sed
tst_stat decmode
cld
tst_stat 0
set_stat overfl
tst_stat overfl
clv
tst_stat 0
next_test
; testing index register increment/decrement and transfer
; INX INY DEX DEY TAX TXA TAY TYA
ldx #$fe
set_stat $ff
inx ;ff
tst_x $ff,$ff-zero
inx ;00
tst_x 0,$ff-minus
inx ;01
tst_x 1,$ff-minus-zero
dex ;00
tst_x 0,$ff-minus
dex ;ff
tst_x $ff,$ff-zero
dex ;fe
set_stat 0
inx ;ff
tst_x $ff,minus
inx ;00
tst_x 0,zero
inx ;01
tst_x 1,0
dex ;00
tst_x 0,zero
dex ;ff
tst_x $ff,minus
ldy #$fe
set_stat $ff
iny ;ff
tst_y $ff,$ff-zero
iny ;00
tst_y 0,$ff-minus
iny ;01
tst_y 1,$ff-minus-zero
dey ;00
tst_y 0,$ff-minus
dey ;ff
tst_y $ff,$ff-zero
dey ;fe
set_stat 0
iny ;ff
tst_y $ff,0+minus
iny ;00
tst_y 0,zero
iny ;01
tst_y 1,0
dey ;00
tst_y 0,zero
dey ;ff
tst_y $ff,minus
ldx #$ff
set_stat $ff
txa
tst_a $ff,$ff-zero
php
inx ;00
plp
txa
tst_a 0,$ff-minus
php
inx ;01
plp
txa
tst_a 1,$ff-minus-zero
set_stat 0
txa
tst_a 1,0
php
dex ;00
plp
txa
tst_a 0,zero
php
dex ;ff
plp
txa
tst_a $ff,minus
ldy #$ff
set_stat $ff
tya
tst_a $ff,$ff-zero
php
iny ;00
plp
tya
tst_a 0,$ff-minus
php
iny ;01
plp
tya
tst_a 1,$ff-minus-zero
set_stat 0
tya
tst_a 1,0
php
dey ;00
plp
tya
tst_a 0,zero
php
dey ;ff
plp
tya
tst_a $ff,minus
load_flag $ff
pha
ldx #$ff ;ff
txa
plp
tay
tst_y $ff,$ff-zero
php
inx ;00
txa
plp
tay
tst_y 0,$ff-minus
php
inx ;01
txa
plp
tay
tst_y 1,$ff-minus-zero
load_flag 0
pha
lda #0
txa
plp
tay
tst_y 1,0
php
dex ;00
txa
plp
tay
tst_y 0,zero
php
dex ;ff
txa
plp
tay
tst_y $ff,minus
load_flag $ff
pha
ldy #$ff ;ff
tya
plp
tax
tst_x $ff,$ff-zero
php
iny ;00
tya
plp
tax
tst_x 0,$ff-minus
php
iny ;01
tya
plp
tax
tst_x 1,$ff-minus-zero
load_flag 0
pha
lda #0 ;preset status
tya
plp
tax
tst_x 1,0
php
dey ;00
tya
plp
tax
tst_x 0,zero
php
dey ;ff
tya
plp
tax
tst_x $ff,minus
next_test
;TSX sets NZ - TXS does not
; This section also tests for proper stack wrap around.
ldx #1 ;01
set_stat $ff
txs
php
lda $101
cmp_flag $ff
trap_ne
set_stat 0
txs
php
lda $101
cmp_flag 0
trap_ne
dex ;00
set_stat $ff
txs
php
lda $100
cmp_flag $ff
trap_ne
set_stat 0
txs
php
lda $100
cmp_flag 0
trap_ne
dex ;ff
set_stat $ff
txs
php
lda $1ff
cmp_flag $ff
trap_ne
set_stat 0
txs
php
lda $1ff
cmp_flag 0
ldx #1
txs ;sp=01
set_stat $ff
tsx ;clears Z, N
php ;sp=00
cpx #1
trap_ne
lda $101
cmp_flag $ff-minus-zero
trap_ne
set_stat $ff
tsx ;clears N, sets Z
php ;sp=ff
cpx #0
trap_ne
lda $100
cmp_flag $ff-minus
trap_ne
set_stat $ff
tsx ;clears N, sets Z
php ;sp=fe
cpx #$ff
trap_ne
lda $1ff
cmp_flag $ff-zero
trap_ne
ldx #1
txs ;sp=01
set_stat 0
tsx ;clears Z, N
php ;sp=00
cpx #1
trap_ne
lda $101
cmp_flag 0
trap_ne
set_stat 0
tsx ;clears N, sets Z
php ;sp=ff
cpx #0
trap_ne
lda $100
cmp_flag zero
trap_ne
set_stat 0
tsx ;clears N, sets Z
php ;sp=fe
cpx #$ff
trap_ne
lda $1ff
cmp_flag minus
trap_ne
pla ;sp=ff
next_test
; testing index register load & store LDY LDX STY STX all addressing modes
; LDX / STX - zp,y / abs,y
ldy #3
tldx
set_stat 0
ldx zp1,y
php ;test stores do not alter flags
txa
eor #$c3
plp
sta abst,y
php ;flags after load/store sequence
eor #$c3
cmp abs1,y ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx,y ;test flags
trap_ne
dey
bpl tldx
ldy #3
tldx1
set_stat $ff
ldx zp1,y
php ;test stores do not alter flags
txa
eor #$c3
plp
sta abst,y
php ;flags after load/store sequence
eor #$c3
cmp abs1,y ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx,y ;test flags
trap_ne
dey
bpl tldx1
ldy #3
tldx2
set_stat 0
ldx abs1,y
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx zpt,y
php ;flags after load/store sequence
eor #$c3
cmp zp1,y ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx,y ;test flags
trap_ne
dey
bpl tldx2
ldy #3
tldx3
set_stat $ff
ldx abs1,y
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx zpt,y
php ;flags after load/store sequence
eor #$c3
cmp zp1,y ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx,y ;test flags
trap_ne
dey
bpl tldx3
ldy #3 ;testing store result
ldx #0
tstx lda zpt,y
eor #$c3
cmp zp1,y
trap_ne ;store to zp data
stx zpt,y ;clear
lda abst,y
eor #$c3
cmp abs1,y
trap_ne ;store to abs data
txa
sta abst,y ;clear
dey
bpl tstx
next_test
; indexed wraparound test (only zp should wrap)
ldy #3+$fa
tldx4 ldx zp1-$fa&$ff,y ;wrap on indexed zp
txa
sta abst-$fa,y ;no STX abs,y!
dey
cpy #$fa
bcs tldx4
ldy #3+$fa
tldx5 ldx abs1-$fa,y ;no wrap on indexed abs
stx zpt-$fa&$ff,y
dey
cpy #$fa
bcs tldx5
ldy #3 ;testing wraparound result
ldx #0
tstx1 lda zpt,y
cmp zp1,y
trap_ne ;store to zp data
stx zpt,y ;clear
lda abst,y
cmp abs1,y
trap_ne ;store to abs data
txa
sta abst,y ;clear
dey
bpl tstx1
next_test
; LDY / STY - zp,x / abs,x
ldx #3
tldy
set_stat 0
ldy zp1,x
php ;test stores do not alter flags
tya
eor #$c3
plp
sta abst,x
php ;flags after load/store sequence
eor #$c3
cmp abs1,x ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx,x ;test flags
trap_ne
dex
bpl tldy
ldx #3
tldy1
set_stat $ff
ldy zp1,x
php ;test stores do not alter flags
tya
eor #$c3
plp
sta abst,x
php ;flags after load/store sequence
eor #$c3
cmp abs1,x ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx,x ;test flags
trap_ne
dex
bpl tldy1
ldx #3
tldy2
set_stat 0
ldy abs1,x
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty zpt,x
php ;flags after load/store sequence
eor #$c3
cmp zp1,x ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx,x ;test flags
trap_ne
dex
bpl tldy2
ldx #3
tldy3
set_stat $ff
ldy abs1,x
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty zpt,x
php ;flags after load/store sequence
eor #$c3
cmp zp1,x ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx,x ;test flags
trap_ne
dex
bpl tldy3
ldx #3 ;testing store result
ldy #0
tsty lda zpt,x
eor #$c3
cmp zp1,x
trap_ne ;store to zp,x data
sty zpt,x ;clear
lda abst,x
eor #$c3
cmp abs1,x
trap_ne ;store to abs,x data
txa
sta abst,x ;clear
dex
bpl tsty
next_test
; indexed wraparound test (only zp should wrap)
ldx #3+$fa
tldy4 ldy zp1-$fa&$ff,x ;wrap on indexed zp
tya
sta abst-$fa,x ;no STX abs,x!
dex
cpx #$fa
bcs tldy4
ldx #3+$fa
tldy5 ldy abs1-$fa,x ;no wrap on indexed abs
sty zpt-$fa&$ff,x
dex
cpx #$fa
bcs tldy5
ldx #3 ;testing wraparound result
ldy #0
tsty1 lda zpt,x
cmp zp1,x
trap_ne ;store to zp,x data
sty zpt,x ;clear
lda abst,x
cmp abs1,x
trap_ne ;store to abs,x data
txa
sta abst,x ;clear
dex
bpl tsty1
next_test
; LDX / STX - zp / abs / #
set_stat 0
ldx zp1
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx abst
php ;flags after load/store sequence
eor #$c3
tax
cpx #$c3 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx ;test flags
trap_ne
set_stat 0
ldx zp1+1
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx abst+1
php ;flags after load/store sequence
eor #$c3
tax
cpx #$82 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+1 ;test flags
trap_ne
set_stat 0
ldx zp1+2
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx abst+2
php ;flags after load/store sequence
eor #$c3
tax
cpx #$41 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+2 ;test flags
trap_ne
set_stat 0
ldx zp1+3
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx abst+3
php ;flags after load/store sequence
eor #$c3
tax
cpx #0 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+3 ;test flags
trap_ne
set_stat $ff
ldx zp1
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx abst
php ;flags after load/store sequence
eor #$c3
tax
cpx #$c3 ;test result
trap_ne ;
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx ;test flags
trap_ne
set_stat $ff
ldx zp1+1
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx abst+1
php ;flags after load/store sequence
eor #$c3
tax
cpx #$82 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+1 ;test flags
trap_ne
set_stat $ff
ldx zp1+2
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx abst+2
php ;flags after load/store sequence
eor #$c3
tax
cpx #$41 ;test result
trap_ne ;
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+2 ;test flags
trap_ne
set_stat $ff
ldx zp1+3
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx abst+3
php ;flags after load/store sequence
eor #$c3
tax
cpx #0 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+3 ;test flags
trap_ne
set_stat 0
ldx abs1
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx zpt
php ;flags after load/store sequence
eor #$c3
cmp zp1 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx ;test flags
trap_ne
set_stat 0
ldx abs1+1
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx zpt+1
php ;flags after load/store sequence
eor #$c3
cmp zp1+1 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+1 ;test flags
trap_ne
set_stat 0
ldx abs1+2
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx zpt+2
php ;flags after load/store sequence
eor #$c3
cmp zp1+2 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+2 ;test flags
trap_ne
set_stat 0
ldx abs1+3
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx zpt+3
php ;flags after load/store sequence
eor #$c3
cmp zp1+3 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+3 ;test flags
trap_ne
set_stat $ff
ldx abs1
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx zpt
php ;flags after load/store sequence
eor #$c3
tax
cpx zp1 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx ;test flags
trap_ne
set_stat $ff
ldx abs1+1
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx zpt+1
php ;flags after load/store sequence
eor #$c3
tax
cpx zp1+1 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+1 ;test flags
trap_ne
set_stat $ff
ldx abs1+2
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx zpt+2
php ;flags after load/store sequence
eor #$c3
tax
cpx zp1+2 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+2 ;test flags
trap_ne
set_stat $ff
ldx abs1+3
php ;test stores do not alter flags
txa
eor #$c3
tax
plp
stx zpt+3
php ;flags after load/store sequence
eor #$c3
tax
cpx zp1+3 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+3 ;test flags
trap_ne
set_stat 0
ldx #$c3
php
cpx abs1 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx ;test flags
trap_ne
set_stat 0
ldx #$82
php
cpx abs1+1 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+1 ;test flags
trap_ne
set_stat 0
ldx #$41
php
cpx abs1+2 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+2 ;test flags
trap_ne
set_stat 0
ldx #0
php
cpx abs1+3 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+3 ;test flags
trap_ne
set_stat $ff
ldx #$c3
php
cpx abs1 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx ;test flags
trap_ne
set_stat $ff
ldx #$82
php
cpx abs1+1 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+1 ;test flags
trap_ne
set_stat $ff
ldx #$41
php
cpx abs1+2 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+2 ;test flags
trap_ne
set_stat $ff
ldx #0
php
cpx abs1+3 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+3 ;test flags
trap_ne
ldx #0
lda zpt
eor #$c3
cmp zp1
trap_ne ;store to zp data
stx zpt ;clear
lda abst
eor #$c3
cmp abs1
trap_ne ;store to abs data
stx abst ;clear
lda zpt+1
eor #$c3
cmp zp1+1
trap_ne ;store to zp data
stx zpt+1 ;clear
lda abst+1
eor #$c3
cmp abs1+1
trap_ne ;store to abs data
stx abst+1 ;clear
lda zpt+2
eor #$c3
cmp zp1+2
trap_ne ;store to zp data
stx zpt+2 ;clear
lda abst+2
eor #$c3
cmp abs1+2
trap_ne ;store to abs data
stx abst+2 ;clear
lda zpt+3
eor #$c3
cmp zp1+3
trap_ne ;store to zp data
stx zpt+3 ;clear
lda abst+3
eor #$c3
cmp abs1+3
trap_ne ;store to abs data
stx abst+3 ;clear
next_test
; LDY / STY - zp / abs / #
set_stat 0
ldy zp1
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty abst
php ;flags after load/store sequence
eor #$c3
tay
cpy #$c3 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx ;test flags
trap_ne
set_stat 0
ldy zp1+1
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty abst+1
php ;flags after load/store sequence
eor #$c3
tay
cpy #$82 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+1 ;test flags
trap_ne
set_stat 0
ldy zp1+2
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty abst+2
php ;flags after load/store sequence
eor #$c3
tay
cpy #$41 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+2 ;test flags
trap_ne
set_stat 0
ldy zp1+3
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty abst+3
php ;flags after load/store sequence
eor #$c3
tay
cpy #0 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+3 ;test flags
trap_ne
set_stat $ff
ldy zp1
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty abst
php ;flags after load/store sequence
eor #$c3
tay
cpy #$c3 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx ;test flags
trap_ne
set_stat $ff
ldy zp1+1
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty abst+1
php ;flags after load/store sequence
eor #$c3
tay
cpy #$82 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+1 ;test flags
trap_ne
set_stat $ff
ldy zp1+2
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty abst+2
php ;flags after load/store sequence
eor #$c3
tay
cpy #$41 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+2 ;test flags
trap_ne
set_stat $ff
ldy zp1+3
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty abst+3
php ;flags after load/store sequence
eor #$c3
tay
cpy #0 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+3 ;test flags
trap_ne
set_stat 0
ldy abs1
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty zpt
php ;flags after load/store sequence
eor #$c3
tay
cpy zp1 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx ;test flags
trap_ne
set_stat 0
ldy abs1+1
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty zpt+1
php ;flags after load/store sequence
eor #$c3
tay
cpy zp1+1 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+1 ;test flags
trap_ne
set_stat 0
ldy abs1+2
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty zpt+2
php ;flags after load/store sequence
eor #$c3
tay
cpy zp1+2 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+2 ;test flags
trap_ne
set_stat 0
ldy abs1+3
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty zpt+3
php ;flags after load/store sequence
eor #$c3
tay
cpy zp1+3 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+3 ;test flags
trap_ne
set_stat $ff
ldy abs1
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty zpt
php ;flags after load/store sequence
eor #$c3
tay
cmp zp1 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx ;test flags
trap_ne
set_stat $ff
ldy abs1+1
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty zpt+1
php ;flags after load/store sequence
eor #$c3
tay
cmp zp1+1 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+1 ;test flags
trap_ne
set_stat $ff
ldy abs1+2
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty zpt+2
php ;flags after load/store sequence
eor #$c3
tay
cmp zp1+2 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+2 ;test flags
trap_ne
set_stat $ff
ldy abs1+3
php ;test stores do not alter flags
tya
eor #$c3
tay
plp
sty zpt+3
php ;flags after load/store sequence
eor #$c3
tay
cmp zp1+3 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+3 ;test flags
trap_ne
set_stat 0
ldy #$c3
php
cpy abs1 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx ;test flags
trap_ne
set_stat 0
ldy #$82
php
cpy abs1+1 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+1 ;test flags
trap_ne
set_stat 0
ldy #$41
php
cpy abs1+2 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+2 ;test flags
trap_ne
set_stat 0
ldy #0
php
cpy abs1+3 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+3 ;test flags
trap_ne
set_stat $ff
ldy #$c3
php
cpy abs1 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx ;test flags
trap_ne
set_stat $ff
ldy #$82
php
cpy abs1+1 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+1 ;test flags
trap_ne
set_stat $ff
ldy #$41
php
cpy abs1+2 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+2 ;test flags
trap_ne
set_stat $ff
ldy #0
php
cpy abs1+3 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+3 ;test flags
trap_ne
ldy #0
lda zpt
eor #$c3
cmp zp1
trap_ne ;store to zp data
sty zpt ;clear
lda abst
eor #$c3
cmp abs1
trap_ne ;store to abs data
sty abst ;clear
lda zpt+1
eor #$c3
cmp zp1+1
trap_ne ;store to zp+1 data
sty zpt+1 ;clear
lda abst+1
eor #$c3
cmp abs1+1
trap_ne ;store to abs+1 data
sty abst+1 ;clear
lda zpt+2
eor #$c3
cmp zp1+2
trap_ne ;store to zp+2 data
sty zpt+2 ;clear
lda abst+2
eor #$c3
cmp abs1+2
trap_ne ;store to abs+2 data
sty abst+2 ;clear
lda zpt+3
eor #$c3
cmp zp1+3
trap_ne ;store to zp+3 data
sty zpt+3 ;clear
lda abst+3
eor #$c3
cmp abs1+3
trap_ne ;store to abs+3 data
sty abst+3 ;clear
next_test
; testing load / store accumulator LDA / STA all addressing modes
; LDA / STA - zp,x / abs,x
ldx #3
tldax
set_stat 0
lda zp1,x
php ;test stores do not alter flags
eor #$c3
plp
sta abst,x
php ;flags after load/store sequence
eor #$c3
cmp abs1,x ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx,x ;test flags
trap_ne
dex
bpl tldax
ldx #3
tldax1
set_stat $ff
lda zp1,x
php ;test stores do not alter flags
eor #$c3
plp
sta abst,x
php ;flags after load/store sequence
eor #$c3
cmp abs1,x ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx,x ;test flags
trap_ne
dex
bpl tldax1
ldx #3
tldax2
set_stat 0
lda abs1,x
php ;test stores do not alter flags
eor #$c3
plp
sta zpt,x
php ;flags after load/store sequence
eor #$c3
cmp zp1,x ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx,x ;test flags
trap_ne
dex
bpl tldax2
ldx #3
tldax3
set_stat $ff
lda abs1,x
php ;test stores do not alter flags
eor #$c3
plp
sta zpt,x
php ;flags after load/store sequence
eor #$c3
cmp zp1,x ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx,x ;test flags
trap_ne
dex
bpl tldax3
ldx #3 ;testing store result
ldy #0
tstax lda zpt,x
eor #$c3
cmp zp1,x
trap_ne ;store to zp,x data
sty zpt,x ;clear
lda abst,x
eor #$c3
cmp abs1,x
trap_ne ;store to abs,x data
txa
sta abst,x ;clear
dex
bpl tstax
next_test
; LDA / STA - (zp),y / abs,y / (zp,x)
ldy #3
tlday
set_stat 0
lda (ind1),y
php ;test stores do not alter flags
eor #$c3
plp
sta abst,y
php ;flags after load/store sequence
eor #$c3
cmp abs1,y ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx,y ;test flags
trap_ne
dey
bpl tlday
ldy #3
tlday1
set_stat $ff
lda (ind1),y
php ;test stores do not alter flags
eor #$c3
plp
sta abst,y
php ;flags after load/store sequence
eor #$c3
cmp abs1,y ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx,y ;test flags
trap_ne
dey
bpl tlday1
ldy #3 ;testing store result
ldx #0
tstay lda abst,y
eor #$c3
cmp abs1,y
trap_ne ;store to abs data
txa
sta abst,y ;clear
dey
bpl tstay
ldy #3
tlday2
set_stat 0
lda abs1,y
php ;test stores do not alter flags
eor #$c3
plp
sta (indt),y
php ;flags after load/store sequence
eor #$c3
cmp (ind1),y ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx,y ;test flags
trap_ne
dey
bpl tlday2
ldy #3
tlday3
set_stat $ff
lda abs1,y
php ;test stores do not alter flags
eor #$c3
plp
sta (indt),y
php ;flags after load/store sequence
eor #$c3
cmp (ind1),y ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx,y ;test flags
trap_ne
dey
bpl tlday3
ldy #3 ;testing store result
ldx #0
tstay1 lda abst,y
eor #$c3
cmp abs1,y
trap_ne ;store to abs data
txa
sta abst,y ;clear
dey
bpl tstay1
ldx #6
ldy #3
tldax4
set_stat 0
lda (ind1,x)
php ;test stores do not alter flags
eor #$c3
plp
sta (indt,x)
php ;flags after load/store sequence
eor #$c3
cmp abs1,y ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx,y ;test flags
trap_ne
dex
dex
dey
bpl tldax4
ldx #6
ldy #3
tldax5
set_stat $ff
lda (ind1,x)
php ;test stores do not alter flags
eor #$c3
plp
sta (indt,x)
php ;flags after load/store sequence
eor #$c3
cmp abs1,y ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx,y ;test flags
trap_ne
dex
dex
dey
bpl tldax5
ldy #3 ;testing store result
ldx #0
tstay2 lda abst,y
eor #$c3
cmp abs1,y
trap_ne ;store to abs data
txa
sta abst,y ;clear
dey
bpl tstay2
next_test
; indexed wraparound test (only zp should wrap)
ldx #3+$fa
tldax6 lda zp1-$fa&$ff,x ;wrap on indexed zp
sta abst-$fa,x ;no STX abs,x!
dex
cpx #$fa
bcs tldax6
ldx #3+$fa
tldax7 lda abs1-$fa,x ;no wrap on indexed abs
sta zpt-$fa&$ff,x
dex
cpx #$fa
bcs tldax7
ldx #3 ;testing wraparound result
ldy #0
tstax1 lda zpt,x
cmp zp1,x
trap_ne ;store to zp,x data
sty zpt,x ;clear
lda abst,x
cmp abs1,x
trap_ne ;store to abs,x data
txa
sta abst,x ;clear
dex
bpl tstax1
ldy #3+$f8
ldx #6+$f8
tlday4 lda (ind1-$f8&$ff,x) ;wrap on indexed zp indirect
sta abst-$f8,y
dex
dex
dey
cpy #$f8
bcs tlday4
ldy #3 ;testing wraparound result
ldx #0
tstay4 lda abst,y
cmp abs1,y
trap_ne ;store to abs data
txa
sta abst,y ;clear
dey
bpl tstay4
ldy #3+$f8
tlday5 lda abs1-$f8,y ;no wrap on indexed abs
sta (inwt),y
dey
cpy #$f8
bcs tlday5
ldy #3 ;testing wraparound result
ldx #0
tstay5 lda abst,y
cmp abs1,y
trap_ne ;store to abs data
txa
sta abst,y ;clear
dey
bpl tstay5
ldy #3+$f8
ldx #6+$f8
tlday6 lda (inw1),y ;no wrap on zp indirect indexed
sta (indt-$f8&$ff,x)
dex
dex
dey
cpy #$f8
bcs tlday6
ldy #3 ;testing wraparound result
ldx #0
tstay6 lda abst,y
cmp abs1,y
trap_ne ;store to abs data
txa
sta abst,y ;clear
dey
bpl tstay6
next_test
; LDA / STA - zp / abs / #
set_stat 0
lda zp1
php ;test stores do not alter flags
eor #$c3
plp
sta abst
php ;flags after load/store sequence
eor #$c3
cmp #$c3 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx ;test flags
trap_ne
set_stat 0
lda zp1+1
php ;test stores do not alter flags
eor #$c3
plp
sta abst+1
php ;flags after load/store sequence
eor #$c3
cmp #$82 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+1 ;test flags
trap_ne
set_stat 0
lda zp1+2
php ;test stores do not alter flags
eor #$c3
plp
sta abst+2
php ;flags after load/store sequence
eor #$c3
cmp #$41 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+2 ;test flags
trap_ne
set_stat 0
lda zp1+3
php ;test stores do not alter flags
eor #$c3
plp
sta abst+3
php ;flags after load/store sequence
eor #$c3
cmp #0 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+3 ;test flags
trap_ne
set_stat $ff
lda zp1
php ;test stores do not alter flags
eor #$c3
plp
sta abst
php ;flags after load/store sequence
eor #$c3
cmp #$c3 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx ;test flags
trap_ne
set_stat $ff
lda zp1+1
php ;test stores do not alter flags
eor #$c3
plp
sta abst+1
php ;flags after load/store sequence
eor #$c3
cmp #$82 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+1 ;test flags
trap_ne
set_stat $ff
lda zp1+2
php ;test stores do not alter flags
eor #$c3
plp
sta abst+2
php ;flags after load/store sequence
eor #$c3
cmp #$41 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+2 ;test flags
trap_ne
set_stat $ff
lda zp1+3
php ;test stores do not alter flags
eor #$c3
plp
sta abst+3
php ;flags after load/store sequence
eor #$c3
cmp #0 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+3 ;test flags
trap_ne
set_stat 0
lda abs1
php ;test stores do not alter flags
eor #$c3
plp
sta zpt
php ;flags after load/store sequence
eor #$c3
cmp zp1 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx ;test flags
trap_ne
set_stat 0
lda abs1+1
php ;test stores do not alter flags
eor #$c3
plp
sta zpt+1
php ;flags after load/store sequence
eor #$c3
cmp zp1+1 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+1 ;test flags
trap_ne
set_stat 0
lda abs1+2
php ;test stores do not alter flags
eor #$c3
plp
sta zpt+2
php ;flags after load/store sequence
eor #$c3
cmp zp1+2 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+2 ;test flags
trap_ne
set_stat 0
lda abs1+3
php ;test stores do not alter flags
eor #$c3
plp
sta zpt+3
php ;flags after load/store sequence
eor #$c3
cmp zp1+3 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+3 ;test flags
trap_ne
set_stat $ff
lda abs1
php ;test stores do not alter flags
eor #$c3
plp
sta zpt
php ;flags after load/store sequence
eor #$c3
cmp zp1 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx ;test flags
trap_ne
set_stat $ff
lda abs1+1
php ;test stores do not alter flags
eor #$c3
plp
sta zpt+1
php ;flags after load/store sequence
eor #$c3
cmp zp1+1 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+1 ;test flags
trap_ne
set_stat $ff
lda abs1+2
php ;test stores do not alter flags
eor #$c3
plp
sta zpt+2
php ;flags after load/store sequence
eor #$c3
cmp zp1+2 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+2 ;test flags
trap_ne
set_stat $ff
lda abs1+3
php ;test stores do not alter flags
eor #$c3
plp
sta zpt+3
php ;flags after load/store sequence
eor #$c3
cmp zp1+3 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+3 ;test flags
trap_ne
set_stat 0
lda #$c3
php
cmp abs1 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx ;test flags
trap_ne
set_stat 0
lda #$82
php
cmp abs1+1 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+1 ;test flags
trap_ne
set_stat 0
lda #$41
php
cmp abs1+2 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+2 ;test flags
trap_ne
set_stat 0
lda #0
php
cmp abs1+3 ;test result
trap_ne
pla ;load status
eor_flag 0
cmp fLDx+3 ;test flags
trap_ne
set_stat $ff
lda #$c3
php
cmp abs1 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx ;test flags
trap_ne
set_stat $ff
lda #$82
php
cmp abs1+1 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+1 ;test flags
trap_ne
set_stat $ff
lda #$41
php
cmp abs1+2 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+2 ;test flags
trap_ne
set_stat $ff
lda #0
php
cmp abs1+3 ;test result
trap_ne
pla ;load status
eor_flag lo~fnz ;mask bits not altered
cmp fLDx+3 ;test flags
trap_ne
ldx #0
lda zpt
eor #$c3
cmp zp1
trap_ne ;store to zp data
stx zpt ;clear
lda abst
eor #$c3
cmp abs1
trap_ne ;store to abs data
stx abst ;clear
lda zpt+1
eor #$c3
cmp zp1+1
trap_ne ;store to zp data
stx zpt+1 ;clear
lda abst+1
eor #$c3
cmp abs1+1
trap_ne ;store to abs data
stx abst+1 ;clear
lda zpt+2
eor #$c3
cmp zp1+2
trap_ne ;store to zp data
stx zpt+2 ;clear
lda abst+2
eor #$c3
cmp abs1+2
trap_ne ;store to abs data
stx abst+2 ;clear
lda zpt+3
eor #$c3
cmp zp1+3
trap_ne ;store to zp data
stx zpt+3 ;clear
lda abst+3
eor #$c3
cmp abs1+3
trap_ne ;store to abs data
stx abst+3 ;clear
next_test
; testing bit test & compares BIT CPX CPY CMP all addressing modes
; BIT - zp / abs
set_a $ff,0
bit zp1+3 ;00 - should set Z / clear NV
tst_a $ff,fz
set_a 1,0
bit zp1+2 ;41 - should set V (M6) / clear NZ
tst_a 1,fv
set_a 1,0
bit zp1+1 ;82 - should set N (M7) & Z / clear V
tst_a 1,fnz
set_a 1,0
bit zp1 ;c3 - should set N (M7) & V (M6) / clear Z
tst_a 1,fnv
set_a $ff,$ff
bit zp1+3 ;00 - should set Z / clear NV
tst_a $ff,~fnv
set_a 1,$ff
bit zp1+2 ;41 - should set V (M6) / clear NZ
tst_a 1,~fnz
set_a 1,$ff
bit zp1+1 ;82 - should set N (M7) & Z / clear V
tst_a 1,~fv
set_a 1,$ff
bit zp1 ;c3 - should set N (M7) & V (M6) / clear Z
tst_a 1,~fz
set_a $ff,0
bit abs1+3 ;00 - should set Z / clear NV
tst_a $ff,fz
set_a 1,0
bit abs1+2 ;41 - should set V (M6) / clear NZ
tst_a 1,fv
set_a 1,0
bit abs1+1 ;82 - should set N (M7) & Z / clear V
tst_a 1,fnz
set_a 1,0
bit abs1 ;c3 - should set N (M7) & V (M6) / clear Z
tst_a 1,fnv
set_a $ff,$ff
bit abs1+3 ;00 - should set Z / clear NV
tst_a $ff,~fnv
set_a 1,$ff
bit abs1+2 ;41 - should set V (M6) / clear NZ
tst_a 1,~fnz
set_a 1,$ff
bit abs1+1 ;82 - should set N (M7) & Z / clear V
tst_a 1,~fv
set_a 1,$ff
bit abs1 ;c3 - should set N (M7) & V (M6) / clear Z
tst_a 1,~fz
next_test
; CPX - zp / abs / #
set_x $80,0
cpx zp7f
tst_stat fc
dex
cpx zp7f
tst_stat fzc
dex
cpx zp7f
tst_x $7e,fn
set_x $80,$ff
cpx zp7f
tst_stat ~fnz
dex
cpx zp7f
tst_stat ~fn
dex
cpx zp7f
tst_x $7e,~fzc
set_x $80,0
cpx abs7f
tst_stat fc
dex
cpx abs7f
tst_stat fzc
dex
cpx abs7f
tst_x $7e,fn
set_x $80,$ff
cpx abs7f
tst_stat ~fnz
dex
cpx abs7f
tst_stat ~fn
dex
cpx abs7f
tst_x $7e,~fzc
set_x $80,0
cpx #$7f
tst_stat fc
dex
cpx #$7f
tst_stat fzc
dex
cpx #$7f
tst_x $7e,fn
set_x $80,$ff
cpx #$7f
tst_stat ~fnz
dex
cpx #$7f
tst_stat ~fn
dex
cpx #$7f
tst_x $7e,~fzc
next_test
; CPY - zp / abs / #
set_y $80,0
cpy zp7f
tst_stat fc
dey
cpy zp7f
tst_stat fzc
dey
cpy zp7f
tst_y $7e,fn
set_y $80,$ff
cpy zp7f
tst_stat ~fnz
dey
cpy zp7f
tst_stat ~fn
dey
cpy zp7f
tst_y $7e,~fzc
set_y $80,0
cpy abs7f
tst_stat fc
dey
cpy abs7f
tst_stat fzc
dey
cpy abs7f
tst_y $7e,fn
set_y $80,$ff
cpy abs7f
tst_stat ~fnz
dey
cpy abs7f
tst_stat ~fn
dey
cpy abs7f
tst_y $7e,~fzc
set_y $80,0
cpy #$7f
tst_stat fc
dey
cpy #$7f
tst_stat fzc
dey
cpy #$7f
tst_y $7e,fn
set_y $80,$ff
cpy #$7f
tst_stat ~fnz
dey
cpy #$7f
tst_stat ~fn
dey
cpy #$7f
tst_y $7e,~fzc
next_test
; CMP - zp / abs / #
set_a $80,0
cmp zp7f
tst_a $80,fc
set_a $7f,0
cmp zp7f
tst_a $7f,fzc
set_a $7e,0
cmp zp7f
tst_a $7e,fn
set_a $80,$ff
cmp zp7f
tst_a $80,~fnz
set_a $7f,$ff
cmp zp7f
tst_a $7f,~fn
set_a $7e,$ff
cmp zp7f
tst_a $7e,~fzc
set_a $80,0
cmp abs7f
tst_a $80,fc
set_a $7f,0
cmp abs7f
tst_a $7f,fzc
set_a $7e,0
cmp abs7f
tst_a $7e,fn
set_a $80,$ff
cmp abs7f
tst_a $80,~fnz
set_a $7f,$ff
cmp abs7f
tst_a $7f,~fn
set_a $7e,$ff
cmp abs7f
tst_a $7e,~fzc
set_a $80,0
cmp #$7f
tst_a $80,fc
set_a $7f,0
cmp #$7f
tst_a $7f,fzc
set_a $7e,0
cmp #$7f
tst_a $7e,fn
set_a $80,$ff
cmp #$7f
tst_a $80,~fnz
set_a $7f,$ff
cmp #$7f
tst_a $7f,~fn
set_a $7e,$ff
cmp #$7f
tst_a $7e,~fzc
ldx #4 ;with indexing by X
set_a $80,0
cmp zp1,x
tst_a $80,fc
set_a $7f,0
cmp zp1,x
tst_a $7f,fzc
set_a $7e,0
cmp zp1,x
tst_a $7e,fn
set_a $80,$ff
cmp zp1,x
tst_a $80,~fnz
set_a $7f,$ff
cmp zp1,x
tst_a $7f,~fn
set_a $7e,$ff
cmp zp1,x
tst_a $7e,~fzc
set_a $80,0
cmp abs1,x
tst_a $80,fc
set_a $7f,0
cmp abs1,x
tst_a $7f,fzc
set_a $7e,0
cmp abs1,x
tst_a $7e,fn
set_a $80,$ff
cmp abs1,x
tst_a $80,~fnz
set_a $7f,$ff
cmp abs1,x
tst_a $7f,~fn
set_a $7e,$ff
cmp abs1,x
tst_a $7e,~fzc
ldy #4 ;with indexing by Y
ldx #8 ;with indexed indirect
set_a $80,0
cmp abs1,y
tst_a $80,fc
set_a $7f,0
cmp abs1,y
tst_a $7f,fzc
set_a $7e,0
cmp abs1,y
tst_a $7e,fn
set_a $80,$ff
cmp abs1,y
tst_a $80,~fnz
set_a $7f,$ff
cmp abs1,y
tst_a $7f,~fn
set_a $7e,$ff
cmp abs1,y
tst_a $7e,~fzc
set_a $80,0
cmp (ind1,x)
tst_a $80,fc
set_a $7f,0
cmp (ind1,x)
tst_a $7f,fzc
set_a $7e,0
cmp (ind1,x)
tst_a $7e,fn
set_a $80,$ff
cmp (ind1,x)
tst_a $80,~fnz
set_a $7f,$ff
cmp (ind1,x)
tst_a $7f,~fn
set_a $7e,$ff
cmp (ind1,x)
tst_a $7e,~fzc
set_a $80,0
cmp (ind1),y
tst_a $80,fc
set_a $7f,0
cmp (ind1),y
tst_a $7f,fzc
set_a $7e,0
cmp (ind1),y
tst_a $7e,fn
set_a $80,$ff
cmp (ind1),y
tst_a $80,~fnz
set_a $7f,$ff
cmp (ind1),y
tst_a $7f,~fn
set_a $7e,$ff
cmp (ind1),y
tst_a $7e,~fzc
next_test
; testing shifts - ASL LSR ROL ROR all addressing modes
; shifts - accumulator
ldx #3
tasl
set_ax zp1,0
asl a
tst_ax rASL,fASL,0
dex
bpl tasl
ldx #3
tasl1
set_ax zp1,$ff
asl a
tst_ax rASL,fASL,$ff-fnzc
dex
bpl tasl1
ldx #3
tlsr
set_ax zp1,0
lsr a
tst_ax rLSR,fLSR,0
dex
bpl tlsr
ldx #3
tlsr1
set_ax zp1,$ff
lsr a
tst_ax rLSR,fLSR,$ff-fnzc
dex
bpl tlsr1
ldx #3
trol
set_ax zp1,0
rol a
tst_ax rROL,fROL,0
dex
bpl trol
ldx #3
trol1
set_ax zp1,$ff-fc
rol a
tst_ax rROL,fROL,$ff-fnzc
dex
bpl trol1
ldx #3
trolc
set_ax zp1,fc
rol a
tst_ax rROLc,fROLc,0
dex
bpl trolc
ldx #3
trolc1
set_ax zp1,$ff
rol a
tst_ax rROLc,fROLc,$ff-fnzc
dex
bpl trolc1
ldx #3
tror
set_ax zp1,0
ror a
tst_ax rROR,fROR,0
dex
bpl tror
ldx #3
tror1
set_ax zp1,$ff-fc
ror a
tst_ax rROR,fROR,$ff-fnzc
dex
bpl tror1
ldx #3
trorc
set_ax zp1,fc
ror a
tst_ax rRORc,fRORc,0
dex
bpl trorc
ldx #3
trorc1
set_ax zp1,$ff
ror a
tst_ax rRORc,fRORc,$ff-fnzc
dex
bpl trorc1
next_test
; shifts - zeropage
ldx #3
tasl2
set_z zp1,0
asl zpt
tst_z rASL,fASL,0
dex
bpl tasl2
ldx #3
tasl3
set_z zp1,$ff
asl zpt
tst_z rASL,fASL,$ff-fnzc
dex
bpl tasl3
ldx #3
tlsr2
set_z zp1,0
lsr zpt
tst_z rLSR,fLSR,0
dex
bpl tlsr2
ldx #3
tlsr3
set_z zp1,$ff
lsr zpt
tst_z rLSR,fLSR,$ff-fnzc
dex
bpl tlsr3
ldx #3
trol2
set_z zp1,0
rol zpt
tst_z rROL,fROL,0
dex
bpl trol2
ldx #3
trol3
set_z zp1,$ff-fc
rol zpt
tst_z rROL,fROL,$ff-fnzc
dex
bpl trol3
ldx #3
trolc2
set_z zp1,fc
rol zpt
tst_z rROLc,fROLc,0
dex
bpl trolc2
ldx #3
trolc3
set_z zp1,$ff
rol zpt
tst_z rROLc,fROLc,$ff-fnzc
dex
bpl trolc3
ldx #3
tror2
set_z zp1,0
ror zpt
tst_z rROR,fROR,0
dex
bpl tror2
ldx #3
tror3
set_z zp1,$ff-fc
ror zpt
tst_z rROR,fROR,$ff-fnzc
dex
bpl tror3
ldx #3
trorc2
set_z zp1,fc
ror zpt
tst_z rRORc,fRORc,0
dex
bpl trorc2
ldx #3
trorc3
set_z zp1,$ff
ror zpt
tst_z rRORc,fRORc,$ff-fnzc
dex
bpl trorc3
next_test
; shifts - absolute
ldx #3
tasl4
set_abs zp1,0
asl abst
tst_abs rASL,fASL,0
dex
bpl tasl4
ldx #3
tasl5
set_abs zp1,$ff
asl abst
tst_abs rASL,fASL,$ff-fnzc
dex
bpl tasl5
ldx #3
tlsr4
set_abs zp1,0
lsr abst
tst_abs rLSR,fLSR,0
dex
bpl tlsr4
ldx #3
tlsr5
set_abs zp1,$ff
lsr abst
tst_abs rLSR,fLSR,$ff-fnzc
dex
bpl tlsr5
ldx #3
trol4
set_abs zp1,0
rol abst
tst_abs rROL,fROL,0
dex
bpl trol4
ldx #3
trol5
set_abs zp1,$ff-fc
rol abst
tst_abs rROL,fROL,$ff-fnzc
dex
bpl trol5
ldx #3
trolc4
set_abs zp1,fc
rol abst
tst_abs rROLc,fROLc,0
dex
bpl trolc4
ldx #3
trolc5
set_abs zp1,$ff
rol abst
tst_abs rROLc,fROLc,$ff-fnzc
dex
bpl trolc5
ldx #3
tror4
set_abs zp1,0
ror abst
tst_abs rROR,fROR,0
dex
bpl tror4
ldx #3
tror5
set_abs zp1,$ff-fc
ror abst
tst_abs rROR,fROR,$ff-fnzc
dex
bpl tror5
ldx #3
trorc4
set_abs zp1,fc
ror abst
tst_abs rRORc,fRORc,0
dex
bpl trorc4
ldx #3
trorc5
set_abs zp1,$ff
ror abst
tst_abs rRORc,fRORc,$ff-fnzc
dex
bpl trorc5
next_test
; shifts - zp indexed
ldx #3
tasl6
set_zx zp1,0
asl zpt,x
tst_zx rASL,fASL,0
dex
bpl tasl6
ldx #3
tasl7
set_zx zp1,$ff
asl zpt,x
tst_zx rASL,fASL,$ff-fnzc
dex
bpl tasl7
ldx #3
tlsr6
set_zx zp1,0
lsr zpt,x
tst_zx rLSR,fLSR,0
dex
bpl tlsr6
ldx #3
tlsr7
set_zx zp1,$ff
lsr zpt,x
tst_zx rLSR,fLSR,$ff-fnzc
dex
bpl tlsr7
ldx #3
trol6
set_zx zp1,0
rol zpt,x
tst_zx rROL,fROL,0
dex
bpl trol6
ldx #3
trol7
set_zx zp1,$ff-fc
rol zpt,x
tst_zx rROL,fROL,$ff-fnzc
dex
bpl trol7
ldx #3
trolc6
set_zx zp1,fc
rol zpt,x
tst_zx rROLc,fROLc,0
dex
bpl trolc6
ldx #3
trolc7
set_zx zp1,$ff
rol zpt,x
tst_zx rROLc,fROLc,$ff-fnzc
dex
bpl trolc7
ldx #3
tror6
set_zx zp1,0
ror zpt,x
tst_zx rROR,fROR,0
dex
bpl tror6
ldx #3
tror7
set_zx zp1,$ff-fc
ror zpt,x
tst_zx rROR,fROR,$ff-fnzc
dex
bpl tror7
ldx #3
trorc6
set_zx zp1,fc
ror zpt,x
tst_zx rRORc,fRORc,0
dex
bpl trorc6
ldx #3
trorc7
set_zx zp1,$ff
ror zpt,x
tst_zx rRORc,fRORc,$ff-fnzc
dex
bpl trorc7
next_test
; shifts - abs indexed
ldx #3
tasl8
set_absx zp1,0
asl abst,x
tst_absx rASL,fASL,0
dex
bpl tasl8
ldx #3
tasl9
set_absx zp1,$ff
asl abst,x
tst_absx rASL,fASL,$ff-fnzc
dex
bpl tasl9
ldx #3
tlsr8
set_absx zp1,0
lsr abst,x
tst_absx rLSR,fLSR,0
dex
bpl tlsr8
ldx #3
tlsr9
set_absx zp1,$ff
lsr abst,x
tst_absx rLSR,fLSR,$ff-fnzc
dex
bpl tlsr9
ldx #3
trol8
set_absx zp1,0
rol abst,x
tst_absx rROL,fROL,0
dex
bpl trol8
ldx #3
trol9
set_absx zp1,$ff-fc
rol abst,x
tst_absx rROL,fROL,$ff-fnzc
dex
bpl trol9
ldx #3
trolc8
set_absx zp1,fc
rol abst,x
tst_absx rROLc,fROLc,0
dex
bpl trolc8
ldx #3
trolc9
set_absx zp1,$ff
rol abst,x
tst_absx rROLc,fROLc,$ff-fnzc
dex
bpl trolc9
ldx #3
tror8
set_absx zp1,0
ror abst,x
tst_absx rROR,fROR,0
dex
bpl tror8
ldx #3
tror9
set_absx zp1,$ff-fc
ror abst,x
tst_absx rROR,fROR,$ff-fnzc
dex
bpl tror9
ldx #3
trorc8
set_absx zp1,fc
ror abst,x
tst_absx rRORc,fRORc,0
dex
bpl trorc8
ldx #3
trorc9
set_absx zp1,$ff
ror abst,x
tst_absx rRORc,fRORc,$ff-fnzc
dex
bpl trorc9
next_test
; testing memory increment/decrement - INC DEC all addressing modes
; zeropage
ldx #0
lda #$7e
sta zpt
tinc
set_stat 0
inc zpt
tst_z rINC,fINC,0
inx
cpx #2
bne tinc1
lda #$fe
sta zpt
tinc1 cpx #5
bne tinc
dex
inc zpt
tdec
set_stat 0
dec zpt
tst_z rINC,fINC,0
dex
bmi tdec1
cpx #1
bne tdec
lda #$81
sta zpt
bne tdec
tdec1
ldx #0
lda #$7e
sta zpt
tinc10
set_stat $ff
inc zpt
tst_z rINC,fINC,$ff-fnz
inx
cpx #2
bne tinc11
lda #$fe
sta zpt
tinc11 cpx #5
bne tinc10
dex
inc zpt
tdec10
set_stat $ff
dec zpt
tst_z rINC,fINC,$ff-fnz
dex
bmi tdec11
cpx #1
bne tdec10
lda #$81
sta zpt
bne tdec10
tdec11
next_test
; absolute memory
ldx #0
lda #$7e
sta abst
tinc2
set_stat 0
inc abst
tst_abs rINC,fINC,0
inx
cpx #2
bne tinc3
lda #$fe
sta abst
tinc3 cpx #5
bne tinc2
dex
inc abst
tdec2
set_stat 0
dec abst
tst_abs rINC,fINC,0
dex
bmi tdec3
cpx #1
bne tdec2
lda #$81
sta abst
bne tdec2
tdec3
ldx #0
lda #$7e
sta abst
tinc12
set_stat $ff
inc abst
tst_abs rINC,fINC,$ff-fnz
inx
cpx #2
bne tinc13
lda #$fe
sta abst
tinc13 cpx #5
bne tinc12
dex
inc abst
tdec12
set_stat $ff
dec abst
tst_abs rINC,fINC,$ff-fnz
dex
bmi tdec13
cpx #1
bne tdec12
lda #$81
sta abst
bne tdec12
tdec13
next_test
; zeropage indexed
ldx #0
lda #$7e
tinc4 sta zpt,x
set_stat 0
inc zpt,x
tst_zx rINC,fINC,0
lda zpt,x
inx
cpx #2
bne tinc5
lda #$fe
tinc5 cpx #5
bne tinc4
dex
lda #2
tdec4 sta zpt,x
set_stat 0
dec zpt,x
tst_zx rINC,fINC,0
lda zpt,x
dex
bmi tdec5
cpx #1
bne tdec4
lda #$81
bne tdec4
tdec5
ldx #0
lda #$7e
tinc14 sta zpt,x
set_stat $ff
inc zpt,x
tst_zx rINC,fINC,$ff-fnz
lda zpt,x
inx
cpx #2
bne tinc15
lda #$fe
tinc15 cpx #5
bne tinc14
dex
lda #2
tdec14 sta zpt,x
set_stat $ff
dec zpt,x
tst_zx rINC,fINC,$ff-fnz
lda zpt,x
dex
bmi tdec15
cpx #1
bne tdec14
lda #$81
bne tdec14
tdec15
next_test
; memory indexed
ldx #0
lda #$7e
tinc6 sta abst,x
set_stat 0
inc abst,x
tst_absx rINC,fINC,0
lda abst,x
inx
cpx #2
bne tinc7
lda #$fe
tinc7 cpx #5
bne tinc6
dex
lda #2
tdec6 sta abst,x
set_stat 0
dec abst,x
tst_absx rINC,fINC,0
lda abst,x
dex
bmi tdec7
cpx #1
bne tdec6
lda #$81
bne tdec6
tdec7
ldx #0
lda #$7e
tinc16 sta abst,x
set_stat $ff
inc abst,x
tst_absx rINC,fINC,$ff-fnz
lda abst,x
inx
cpx #2
bne tinc17
lda #$fe
tinc17 cpx #5
bne tinc16
dex
lda #2
tdec16 sta abst,x
set_stat $ff
dec abst,x
tst_absx rINC,fINC,$ff-fnz
lda abst,x
dex
bmi tdec17
cpx #1
bne tdec16
lda #$81
bne tdec16
tdec17
next_test
; testing logical instructions - AND EOR ORA all addressing modes
; AND
ldx #3 ;immediate
tand lda zpAN,x
sta ex_andi+1 ;set AND # operand
set_ax absANa,0
jsr ex_andi ;execute AND # in RAM
tst_ax absrlo,absflo,0
dex
bpl tand
ldx #3
tand1 lda zpAN,x
sta ex_andi+1 ;set AND # operand
set_ax absANa,$ff
jsr ex_andi ;execute AND # in RAM
tst_ax absrlo,absflo,$ff-fnz
dex
bpl tand1
ldx #3 ;zp
tand2 lda zpAN,x
sta zpt
set_ax absANa,0
and zpt
tst_ax absrlo,absflo,0
dex
bpl tand2
ldx #3
tand3 lda zpAN,x
sta zpt
set_ax absANa,$ff
and zpt
tst_ax absrlo,absflo,$ff-fnz
dex
bpl tand3
ldx #3 ;abs
tand4 lda zpAN,x
sta abst
set_ax absANa,0
and abst
tst_ax absrlo,absflo,0
dex
bpl tand4
ldx #3
tand5 lda zpAN,x
sta abst
set_ax absANa,$ff
and abst
tst_ax absrlo,absflo,$ff-fnz
dex
bpl tand6
ldx #3 ;zp,x
tand6
set_ax absANa,0
and zpAN,x
tst_ax absrlo,absflo,0
dex
bpl tand6
ldx #3
tand7
set_ax absANa,$ff
and zpAN,x
tst_ax absrlo,absflo,$ff-fnz
dex
bpl tand7
ldx #3 ;abs,x
tand8
set_ax absANa,0
and absAN,x
tst_ax absrlo,absflo,0
dex
bpl tand8
ldx #3
tand9
set_ax absANa,$ff
and absAN,x
tst_ax absrlo,absflo,$ff-fnz
dex
bpl tand9
ldy #3 ;abs,y
tand10
set_ay absANa,0
and absAN,y
tst_ay absrlo,absflo,0
dey
bpl tand10
ldy #3
tand11
set_ay absANa,$ff
and absAN,y
tst_ay absrlo,absflo,$ff-fnz
dey
bpl tand11
ldx #6 ;(zp,x)
ldy #3
tand12
set_ay absANa,0
and (indAN,x)
tst_ay absrlo,absflo,0
dex
dex
dey
bpl tand12
ldx #6
ldy #3
tand13
set_ay absANa,$ff
and (indAN,x)
tst_ay absrlo,absflo,$ff-fnz
dex
dex
dey
bpl tand13
ldy #3 ;(zp),y
tand14
set_ay absANa,0
and (indAN),y
tst_ay absrlo,absflo,0
dey
bpl tand14
ldy #3
tand15
set_ay absANa,$ff
and (indAN),y
tst_ay absrlo,absflo,$ff-fnz
dey
bpl tand15
next_test
; EOR
ldx #3 ;immediate - self modifying code
teor lda zpEO,x
sta ex_eori+1 ;set EOR # operand
set_ax absEOa,0
jsr ex_eori ;execute EOR # in RAM
tst_ax absrlo,absflo,0
dex
bpl teor
ldx #3
teor1 lda zpEO,x
sta ex_eori+1 ;set EOR # operand
set_ax absEOa,$ff
jsr ex_eori ;execute EOR # in RAM
tst_ax absrlo,absflo,$ff-fnz
dex
bpl teor1
ldx #3 ;zp
teor2 lda zpEO,x
sta zpt
set_ax absEOa,0
eor zpt
tst_ax absrlo,absflo,0
dex
bpl teor2
ldx #3
teor3 lda zpEO,x
sta zpt
set_ax absEOa,$ff
eor zpt
tst_ax absrlo,absflo,$ff-fnz
dex
bpl teor3
ldx #3 ;abs
teor4 lda zpEO,x
sta abst
set_ax absEOa,0
eor abst
tst_ax absrlo,absflo,0
dex
bpl teor4
ldx #3
teor5 lda zpEO,x
sta abst
set_ax absEOa,$ff
eor abst
tst_ax absrlo,absflo,$ff-fnz
dex
bpl teor6
ldx #3 ;zp,x
teor6
set_ax absEOa,0
eor zpEO,x
tst_ax absrlo,absflo,0
dex
bpl teor6
ldx #3
teor7
set_ax absEOa,$ff
eor zpEO,x
tst_ax absrlo,absflo,$ff-fnz
dex
bpl teor7
ldx #3 ;abs,x
teor8
set_ax absEOa,0
eor absEO,x
tst_ax absrlo,absflo,0
dex
bpl teor8
ldx #3
teor9
set_ax absEOa,$ff
eor absEO,x
tst_ax absrlo,absflo,$ff-fnz
dex
bpl teor9
ldy #3 ;abs,y
teor10
set_ay absEOa,0
eor absEO,y
tst_ay absrlo,absflo,0
dey
bpl teor10
ldy #3
teor11
set_ay absEOa,$ff
eor absEO,y
tst_ay absrlo,absflo,$ff-fnz
dey
bpl teor11
ldx #6 ;(zp,x)
ldy #3
teor12
set_ay absEOa,0
eor (indEO,x)
tst_ay absrlo,absflo,0
dex
dex
dey
bpl teor12
ldx #6
ldy #3
teor13
set_ay absEOa,$ff
eor (indEO,x)
tst_ay absrlo,absflo,$ff-fnz
dex
dex
dey
bpl teor13
ldy #3 ;(zp),y
teor14
set_ay absEOa,0
eor (indEO),y
tst_ay absrlo,absflo,0
dey
bpl teor14
ldy #3
teor15
set_ay absEOa,$ff
eor (indEO),y
tst_ay absrlo,absflo,$ff-fnz
dey
bpl teor15
next_test
; OR
ldx #3 ;immediate - self modifying code
tora lda zpOR,x
sta ex_orai+1 ;set ORA # operand
set_ax absORa,0
jsr ex_orai ;execute ORA # in RAM
tst_ax absrlo,absflo,0
dex
bpl tora
ldx #3
tora1 lda zpOR,x
sta ex_orai+1 ;set ORA # operand
set_ax absORa,$ff
jsr ex_orai ;execute ORA # in RAM
tst_ax absrlo,absflo,$ff-fnz
dex
bpl tora1
ldx #3 ;zp
tora2 lda zpOR,x
sta zpt
set_ax absORa,0
ora zpt
tst_ax absrlo,absflo,0
dex
bpl tora2
ldx #3
tora3 lda zpOR,x
sta zpt
set_ax absORa,$ff
ora zpt
tst_ax absrlo,absflo,$ff-fnz
dex
bpl tora3
ldx #3 ;abs
tora4 lda zpOR,x
sta abst
set_ax absORa,0
ora abst
tst_ax absrlo,absflo,0
dex
bpl tora4
ldx #3
tora5 lda zpOR,x
sta abst
set_ax absORa,$ff
ora abst
tst_ax absrlo,absflo,$ff-fnz
dex
bpl tora6
ldx #3 ;zp,x
tora6
set_ax absORa,0
ora zpOR,x
tst_ax absrlo,absflo,0
dex
bpl tora6
ldx #3
tora7
set_ax absORa,$ff
ora zpOR,x
tst_ax absrlo,absflo,$ff-fnz
dex
bpl tora7
ldx #3 ;abs,x
tora8
set_ax absORa,0
ora absOR,x
tst_ax absrlo,absflo,0
dex
bpl tora8
ldx #3
tora9
set_ax absORa,$ff
ora absOR,x
tst_ax absrlo,absflo,$ff-fnz
dex
bpl tora9
ldy #3 ;abs,y
tora10
set_ay absORa,0
ora absOR,y
tst_ay absrlo,absflo,0
dey
bpl tora10
ldy #3
tora11
set_ay absORa,$ff
ora absOR,y
tst_ay absrlo,absflo,$ff-fnz
dey
bpl tora11
ldx #6 ;(zp,x)
ldy #3
tora12
set_ay absORa,0
ora (indOR,x)
tst_ay absrlo,absflo,0
dex
dex
dey
bpl tora12
ldx #6
ldy #3
tora13
set_ay absORa,$ff
ora (indOR,x)
tst_ay absrlo,absflo,$ff-fnz
dex
dex
dey
bpl tora13
ldy #3 ;(zp),y
tora14
set_ay absORa,0
ora (indOR),y
tst_ay absrlo,absflo,0
dey
bpl tora14
ldy #3
tora15
set_ay absORa,$ff
ora (indOR),y
tst_ay absrlo,absflo,$ff-fnz
dey
bpl tora15
if I_flag = 3
cli
endif
next_test
; full binary add/subtract test
; iterates through all combinations of operands and carry input
; uses increments/decrements to predict result & result flags
cld
ldx #ad2 ;for indexed test
ldy #$ff ;max range
lda #0 ;start with adding zeroes & no carry
sta adfc ;carry in - for diag
sta ad1 ;operand 1 - accumulator
sta ad2 ;operand 2 - memory or immediate
sta ada2 ;non zp
sta adrl ;expected result bits 0-7
sta adrh ;expected result bit 8 (carry out)
lda #$ff ;complemented operand 2 for subtract
sta sb2
sta sba2 ;non zp
lda #2 ;expected Z-flag
sta adrf
tadd clc ;test with carry clear
jsr chkadd
inc adfc ;now with carry
inc adrl ;result +1
php ;save N & Z from low result
php
pla ;accu holds expected flags
and #$82 ;mask N & Z
plp
bne tadd1
inc adrh ;result bit 8 - carry
tadd1 ora adrh ;merge C to expected flags
sta adrf ;save expected flags except overflow
sec ;test with carry set
jsr chkadd
dec adfc ;same for operand +1 but no carry
inc ad1
bne tadd ;iterate op1
lda #0 ;preset result to op2 when op1 = 0
sta adrh
inc ada2
inc ad2
php ;save NZ as operand 2 becomes the new result
pla
and #$82 ;mask N00000Z0
sta adrf ;no need to check carry as we are adding to 0
dec sb2 ;complement subtract operand 2
dec sba2
lda ad2
sta adrl
bne tadd ;iterate op2
if disable_decimal < 1
next_test
; decimal add/subtract test
; *** WARNING - tests documented behavior only! ***
; only valid BCD operands are tested, N V Z flags are ignored
; iterates through all valid combinations of operands and carry input
; uses increments/decrements to predict result & carry flag
sed
ldx #ad2 ;for indexed test
ldy #$ff ;max range
lda #$99 ;start with adding 99 to 99 with carry
sta ad1 ;operand 1 - accumulator
sta ad2 ;operand 2 - memory or immediate
sta ada2 ;non zp
sta adrl ;expected result bits 0-7
lda #1 ;set carry in & out
sta adfc ;carry in - for diag
sta adrh ;expected result bit 8 (carry out)
lda #0 ;complemented operand 2 for subtract
sta sb2
sta sba2 ;non zp
tdad sec ;test with carry set
jsr chkdad
dec adfc ;now with carry clear
lda adrl ;decimal adjust result
bne tdad1 ;skip clear carry & preset result 99 (9A-1)
dec adrh
lda #$99
sta adrl
bne tdad3
tdad1 and #$f ;lower nibble mask
bne tdad2 ;no decimal adjust needed
dec adrl ;decimal adjust (?0-6)
dec adrl
dec adrl
dec adrl
dec adrl
dec adrl
tdad2 dec adrl ;result -1
tdad3 clc ;test with carry clear
jsr chkdad
inc adfc ;same for operand -1 but with carry
lda ad1 ;decimal adjust operand 1
beq tdad5 ;iterate operand 2
and #$f ;lower nibble mask
bne tdad4 ;skip decimal adjust
dec ad1 ;decimal adjust (?0-6)
dec ad1
dec ad1
dec ad1
dec ad1
dec ad1
tdad4 dec ad1 ;operand 1 -1
jmp tdad ;iterate op1
tdad5 lda #$99 ;precharge op1 max
sta ad1
lda ad2 ;decimal adjust operand 2
beq tdad7 ;end of iteration
and #$f ;lower nibble mask
bne tdad6 ;skip decimal adjust
dec ad2 ;decimal adjust (?0-6)
dec ad2
dec ad2
dec ad2
dec ad2
dec ad2
inc sb2 ;complemented decimal adjust for subtract (?9+6)
inc sb2
inc sb2
inc sb2
inc sb2
inc sb2
tdad6 dec ad2 ;operand 2 -1
inc sb2 ;complemented operand for subtract
lda sb2
sta sba2 ;copy as non zp operand
lda ad2
sta ada2 ;copy as non zp operand
sta adrl ;new result since op1+carry=00+carry +op2=op2
inc adrh ;result carry
bne tdad ;iterate op2
tdad7
next_test
; decimal/binary switch test
; tests CLD, SED, PLP, RTI to properly switch between decimal & binary opcode
; tables
clc
cld
php
lda #$55
adc #$55
cmp #$aa
trap_ne ;expected binary result after cld
clc
sed
php
lda #$55
adc #$55
cmp #$10
trap_ne ;expected decimal result after sed
cld
plp
lda #$55
adc #$55
cmp #$10
trap_ne ;expected decimal result after plp D=1
plp
lda #$55
adc #$55
cmp #$aa
trap_ne ;expected binary result after plp D=0
clc
lda #hi bin_rti_ret ;emulated interrupt for rti
pha
lda #lo bin_rti_ret
pha
php
sed
lda #hi dec_rti_ret ;emulated interrupt for rti
pha
lda #lo dec_rti_ret
pha
php
cld
rti
dec_rti_ret
lda #$55
adc #$55
cmp #$10
trap_ne ;expected decimal result after rti D=1
rti
bin_rti_ret
lda #$55
adc #$55
cmp #$aa
trap_ne ;expected binary result after rti D=0
endif
lda test_case
cmp #test_num
trap_ne ;previous test is out of sequence
lda #$f0 ;mark opcode testing complete
sta test_case
; final RAM integrity test
; verifies that none of the previous tests has altered RAM outside of the
; designated write areas.
check_ram
; *** DEBUG INFO ***
; to debug checksum errors uncomment check_ram in the next_test macro to
; narrow down the responsible opcode.
; may give false errors when monitor, OS or other background activity is
; allowed during previous tests.
; S U C C E S S ************************************************
; -------------
success ;if you get here everything went well
; -------------
; S U C C E S S ************************************************
jmp start ;run again
if disable_decimal < 1
; core subroutine of the decimal add/subtract test
; *** WARNING - tests documented behavior only! ***
; only valid BCD operands are tested, N V Z flags are ignored
; iterates through all valid combinations of operands and carry input
; uses increments/decrements to predict result & carry flag
chkdad
; decimal ADC / SBC zp
php ;save carry for subtract
lda ad1
adc ad2 ;perform add
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad carry
plp
php ;save carry for next add
lda ad1
sbc sb2 ;perform subtract
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad flags
plp
; decimal ADC / SBC abs
php ;save carry for subtract
lda ad1
adc ada2 ;perform add
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad carry
plp
php ;save carry for next add
lda ad1
sbc sba2 ;perform subtract
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad carry
plp
; decimal ADC / SBC #
php ;save carry for subtract
lda ad2
sta ex_adci+1 ;set ADC # operand
lda ad1
jsr ex_adci ;execute ADC # in RAM
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad carry
plp
php ;save carry for next add
lda sb2
sta ex_sbci+1 ;set SBC # operand
lda ad1
jsr ex_sbci ;execute SBC # in RAM
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad carry
plp
; decimal ADC / SBC zp,x
php ;save carry for subtract
lda ad1
adc 0,x ;perform add
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad carry
plp
php ;save carry for next add
lda ad1
sbc sb2-ad2,x ;perform subtract
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad carry
plp
; decimal ADC / SBC abs,x
php ;save carry for subtract
lda ad1
adc ada2-ad2,x ;perform add
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad carry
plp
php ;save carry for next add
lda ad1
sbc sba2-ad2,x ;perform subtract
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad carry
plp
; decimal ADC / SBC abs,y
php ;save carry for subtract
lda ad1
adc ada2-$ff,y ;perform add
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad carry
plp
php ;save carry for next add
lda ad1
sbc sba2-$ff,y ;perform subtract
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad carry
plp
; decimal ADC / SBC (zp,x)
php ;save carry for subtract
lda ad1
adc (lo adi2-ad2,x) ;perform add
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad carry
plp
php ;save carry for next add
lda ad1
sbc (lo sbi2-ad2,x) ;perform subtract
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad carry
plp
; decimal ADC / SBC (abs),y
php ;save carry for subtract
lda ad1
adc (adiy2),y ;perform add
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad carry
plp
php ;save carry for next add
lda ad1
sbc (sbiy2),y ;perform subtract
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #1 ;mask carry
cmp adrh
trap_ne ;bad carry
plp
rts
endif
; core subroutine of the full binary add/subtract test
; iterates through all combinations of operands and carry input
; uses increments/decrements to predict result & result flags
chkadd lda adrf ;add V-flag if overflow
and #$83 ;keep N-----ZC / clear V
pha
lda ad1 ;test sign unequal between operands
eor ad2
bmi ckad1 ;no overflow possible - operands have different sign
lda ad1 ;test sign equal between operands and result
eor adrl
bpl ckad1 ;no overflow occured - operand and result have same sign
pla
ora #$40 ;set V
pha
ckad1 pla
sta adrf ;save expected flags
; binary ADC / SBC zp
php ;save carry for subtract
lda ad1
adc ad2 ;perform add
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
php ;save carry for next add
lda ad1
sbc sb2 ;perform subtract
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
; binary ADC / SBC abs
php ;save carry for subtract
lda ad1
adc ada2 ;perform add
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
php ;save carry for next add
lda ad1
sbc sba2 ;perform subtract
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
; binary ADC / SBC #
php ;save carry for subtract
lda ad2
sta ex_adci+1 ;set ADC # operand
lda ad1
jsr ex_adci ;execute ADC # in RAM
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
php ;save carry for next add
lda sb2
sta ex_sbci+1 ;set SBC # operand
lda ad1
jsr ex_sbci ;execute SBC # in RAM
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
; binary ADC / SBC zp,x
php ;save carry for subtract
lda ad1
adc 0,x ;perform add
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
php ;save carry for next add
lda ad1
sbc sb2-ad2,x ;perform subtract
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
; binary ADC / SBC abs,x
php ;save carry for subtract
lda ad1
adc ada2-ad2,x ;perform add
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
php ;save carry for next add
lda ad1
sbc sba2-ad2,x ;perform subtract
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
; binary ADC / SBC abs,y
php ;save carry for subtract
lda ad1
adc ada2-$ff,y ;perform add
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
php ;save carry for next add
lda ad1
sbc sba2-$ff,y ;perform subtract
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
; binary ADC / SBC (zp,x)
php ;save carry for subtract
lda ad1
adc (lo adi2-ad2,x) ;perform add
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
php ;save carry for next add
lda ad1
sbc (lo sbi2-ad2,x) ;perform subtract
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
; binary ADC / SBC (abs),y
php ;save carry for subtract
lda ad1
adc (adiy2),y ;perform add
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
php ;save carry for next add
lda ad1
sbc (sbiy2),y ;perform subtract
php
cmp adrl ;check result
trap_ne ;bad result
pla ;check flags
and #$c3 ;mask NV----ZC
cmp adrf
trap_ne ;bad flags
plp
rts
; target for the jump absolute test
dey
dey
test_far
php ;either SP or Y count will fail, if we do not hit
dey
dey
dey
plp
trap_cs ;flags loaded?
trap_vs
trap_mi
trap_eq
cmp #'F' ;registers loaded?
trap_ne
cpx #'A'
trap_ne
cpy #('R'-3)
trap_ne
pha ;save a,x
txa
pha
tsx
cpx #$fd ;check SP
trap_ne
pla ;restore x
tax
set_stat $ff
pla ;restore a
inx ;return registers with modifications
eor #$aa ;N=1, V=1, Z=0, C=1
jmp far_ret
; target for the jump indirect test
align
ptr_tst_ind dw test_ind
ptr_ind_ret dw ind_ret
trap ;runover protection
dey
dey
test_ind
php ;either SP or Y count will fail, if we do not hit
dey
dey
dey
plp
trap_cs ;flags loaded?
trap_vs
trap_mi
trap_eq
cmp #'I' ;registers loaded?
trap_ne
cpx #'N'
trap_ne
cpy #('D'-3)
trap_ne
pha ;save a,x
txa
pha
tsx
cpx #$fd ;check SP
trap_ne
pla ;restore x
tax
set_stat $ff
pla ;restore a
inx ;return registers with modifications
eor #$aa ;N=1, V=1, Z=0, C=1
jmp (ptr_ind_ret)
trap ;runover protection
; target for the jump subroutine test
dey
dey
test_jsr
php ;either SP or Y count will fail, if we do not hit
dey
dey
dey
plp
trap_cs ;flags loaded?
trap_vs
trap_mi
trap_eq
cmp #'J' ;registers loaded?
trap_ne
cpx #'S'
trap_ne
cpy #('R'-3)
trap_ne
pha ;save a,x
txa
pha
tsx ;sp -4? (return addr,a,x)
cpx #$fb
trap_ne
lda $1ff ;propper return on stack
cmp #hi(jsr_ret)
trap_ne
lda $1fe
cmp #lo(jsr_ret)
trap_ne
set_stat $ff
pla ;pull x,a
tax
pla
inx ;return registers with modifications
eor #$aa ;N=1, V=1, Z=0, C=1
rts
trap ;runover protection
;trap in case of unexpected IRQ, NMI, BRK, RESET - BRK test target
nmi_trap
trap ;check stack for conditions at NMI
res_trap
trap ;unexpected RESET
dey
dey
irq_trap ;BRK test or unextpected BRK or IRQ
php ;either SP or Y count will fail, if we do not hit
dey
dey
dey
;next 4 traps could be caused by unexpected BRK or IRQ
;check stack for BREAK and originating location
;possible jump/branch into weeds (uninitialized space)
cmp #'B' ;registers loaded?
trap_ne
cpx #'R'
trap_ne
cpy #('K'-3)
trap_ne
sta irq_a ;save registers during break test
stx irq_x
tsx ;test break on stack
lda $102,x
cmp_flag 0 ;break test should have B=1
trap_ne ; - no break flag on stack
pla
cmp #fai ;should have added interrupt disable
trap_ne
tsx
cpx #$fc ;sp -3? (return addr, flags)
trap_ne
lda $1ff ;propper return on stack
cmp #hi(brk_ret)
trap_ne
lda $1fe
cmp #lo(brk_ret)
trap_ne
set_stat $ff
ldx irq_x
inx ;return registers with modifications
lda irq_a
eor #$aa ;N=1, V=1, Z=0, C=1 but original flags should be restored
rti
trap ;runover protection
if report = 1
include "report.i65"
endif
;copy of data to initialize BSS segment
if load_data_direct != 1
zp_init
zp1_ db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
zp7f_ db $7f ;test pattern for compare
;logical zeropage operands
zpOR_ db 0,$1f,$71,$80 ;test pattern for OR
zpAN_ db $0f,$ff,$7f,$80 ;test pattern for AND
zpEO_ db $ff,$0f,$8f,$8f ;test pattern for EOR
;indirect addressing pointers
ind1_ dw abs1 ;indirect pointer to pattern in absolute memory
dw abs1+1
dw abs1+2
dw abs1+3
dw abs7f
inw1_ dw abs1-$f8 ;indirect pointer for wrap-test pattern
indt_ dw abst ;indirect pointer to store area in absolute memory
dw abst+1
dw abst+2
dw abst+3
inwt_ dw abst-$f8 ;indirect pointer for wrap-test store
indAN_ dw absAN ;indirect pointer to AND pattern in absolute memory
dw absAN+1
dw absAN+2
dw absAN+3
indEO_ dw absEO ;indirect pointer to EOR pattern in absolute memory
dw absEO+1
dw absEO+2
dw absEO+3
indOR_ dw absOR ;indirect pointer to OR pattern in absolute memory
dw absOR+1
dw absOR+2
dw absOR+3
;add/subtract indirect pointers
adi2_ dw ada2 ;indirect pointer to operand 2 in absolute memory
sbi2_ dw sba2 ;indirect pointer to complemented operand 2 (SBC)
adiy2_ dw ada2-$ff ;with offset for indirect indexed
sbiy2_ dw sba2-$ff
zp_end
if (zp_end - zp_init) != (zp_bss_end - zp_bss)
;force assembler error if size is different
ERROR ERROR ERROR ;mismatch between bss and zeropage data
endif
data_init
ex_and_ and #0 ;execute immediate opcodes
rts
ex_eor_ eor #0 ;execute immediate opcodes
rts
ex_ora_ ora #0 ;execute immediate opcodes
rts
ex_adc_ adc #0 ;execute immediate opcodes
rts
ex_sbc_ sbc #0 ;execute immediate opcodes
rts
abs1_ db $c3,$82,$41,0 ;test patterns for LDx BIT ROL ROR ASL LSR
abs7f_ db $7f ;test pattern for compare
;loads
fLDx_ db fn,fn,0,fz ;expected flags for load
;shifts
rASL_ ;expected result ASL & ROL -carry
rROL_ db $86,$04,$82,0 ; "
rROLc_ db $87,$05,$83,1 ;expected result ROL +carry
rLSR_ ;expected result LSR & ROR -carry
rROR_ db $61,$41,$20,0 ; "
rRORc_ db $e1,$c1,$a0,$80 ;expected result ROR +carry
fASL_ ;expected flags for shifts
fROL_ db fnc,fc,fn,fz ;no carry in
fROLc_ db fnc,fc,fn,0 ;carry in
fLSR_
fROR_ db fc,0,fc,fz ;no carry in
fRORc_ db fnc,fn,fnc,fn ;carry in
;increments (decrements)
rINC_ db $7f,$80,$ff,0,1 ;expected result for INC/DEC
fINC_ db 0,fn,fn,fz,0 ;expected flags for INC/DEC
;logical memory operand
absOR_ db 0,$1f,$71,$80 ;test pattern for OR
absAN_ db $0f,$ff,$7f,$80 ;test pattern for AND
absEO_ db $ff,$0f,$8f,$8f ;test pattern for EOR
;logical accu operand
absORa_ db 0,$f1,$1f,0 ;test pattern for OR
absANa_ db $f0,$ff,$ff,$ff ;test pattern for AND
absEOa_ db $ff,$f0,$f0,$0f ;test pattern for EOR
;logical results
absrlo_ db 0,$ff,$7f,$80
absflo_ db fz,fn,0,fn
data_end
if (data_end - data_init) != (data_bss_end - data_bss)
;force assembler error if size is different
ERROR ERROR ERROR ;mismatch between bss and data
endif
vec_init
dw nmi_trap
dw res_trap
dw irq_trap
vec_bss equ $fffa
endif ;end of RAM init data
if (load_data_direct = 1) & (ROM_vectors = 1)
org $fffa ;vectors
dw nmi_trap
dw res_trap
dw irq_trap
endif
end start
================================================
FILE: assets/tests/6502_functional_test.lst
================================================
AS65 Assembler for R6502 [1.42]. Copyright 1994-2007, Frank A. Kingswood Page 1
---------------------------------------------------- 6502_functional_test.a65 ----------------------------------------------------
6010 lines read, no errors in pass 1.
;
; 6 5 0 2 F U N C T I O N A L T E S T
;
; Copyright (C) 2012-2015 Klaus Dormann
;
; 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 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.
; This program is designed to test all opcodes of a 6502 emulator using all
; addressing modes with focus on propper setting of the processor status
; register bits.
;
; version 21-oct-2015
; contact info at http://2m5.de or email K@2m5.de
;
; assembled with AS65 from http://www.kingswood-consulting.co.uk/assemblers/
; command line switches: -l -m -s2 -w -h0
; | | | | no page headers in listing
; | | | wide listing (133 char/col)
; | | write intel hex file instead of binary
; | expand macros in listing
; generate pass2 listing
;
; No IO - should be run from a monitor with access to registers.
; To run load intel hex image with a load command, than alter PC to 400 hex
; (code_segment) and enter a go command.
; Loop on program counter determines error or successful completion of test.
; Check listing for relevant traps (jump/branch *).
; Please note that in early tests some instructions will have to be used before
; they are actually tested!
;
; RESET, NMI or IRQ should not occur and will be trapped if vectors are enabled.
; Tests documented behavior of the original NMOS 6502 only! No unofficial
; opcodes. Additional opcodes of newer versions of the CPU (65C02, 65816) will
; not be tested. Decimal ops will only be tested with valid BCD operands and
; N V Z flags will be ignored.
;
; Debugging hints:
; Most of the code is written sequentially. if you hit a trap, check the
; immediately preceeding code for the instruction to be tested. Results are
; tested first, flags are checked second by pushing them onto the stack and
; pulling them to the accumulator after the result was checked. The "real"
; flags are no longer valid for the tested instruction at this time!
; If the tested instruction was indexed, the relevant index (X or Y) must
; also be checked. Opposed to the flags, X and Y registers are still valid.
;
; versions:
; 28-jul-2012 1st version distributed for testing
; 29-jul-2012 fixed references to location 0, now #0
; added license - GPLv3
; 30-jul-2012 added configuration options
; 01-aug-2012 added trap macro to allow user to change error handling
; 01-dec-2012 fixed trap in branch field must be a branch
; 02-mar-2013 fixed PLA flags not tested
; 19-jul-2013 allowed ROM vectors to be loaded when load_data_direct = 0
; added test sequence check to detect if tests jump their fence
; 23-jul-2013 added RAM integrity check option
; 16-aug-2013 added error report to standard output option
; 13-dec-2014 added binary/decimal opcode table switch test
; 14-dec-2014 improved relative address test
; 23-aug-2015 added option to disable self modifying tests
; 24-aug-2015 all self modifying immediate opcodes now execute in data RAM
; added small branch offset pretest
; 21-oct-2015 added option to disable decimal mode ADC & SBC tests
; C O N F I G U R A T I O N
;ROM_vectors writable (0=no, 1=yes)
;if ROM vectors can not be used interrupts will not be trapped
;as a consequence BRK can not be tested but will be emulated to test RTI
0001 = ROM_vectors = 1
;load_data_direct (0=move from code segment, 1=load directly)
;loading directly is preferred but may not be supported by your platform
;0 produces only consecutive object code, 1 is not suitable for a binary image
0000 = load_data_direct = 0
;I_flag behavior (0=force enabled, 1=force disabled, 2=prohibit change, 3=allow
;change) 2 requires extra code and is not recommended. SEI & CLI can only be
;tested if you allow changing the interrupt status (I_flag = 3)
0003 = I_flag = 3
;configure memory - try to stay away from memory used by the system
;zero_page memory start address, $50 (80) consecutive Bytes required
; add 2 if I_flag = 2
000a = zero_page = $a
;data_segment memory start address, $6A (106) consecutive Bytes required
0200 = data_segment = $200
if (data_segment & $ff) != 0
ERROR ERROR ERROR low byte of data_segment MUST be $00 !!
endif
;code_segment memory start address, 13kB of consecutive space required
; add 2.5 kB if I_flag = 2
0400 = code_segment = $400
;self modifying code may be disabled to allow running in ROM
;0=part of the code is self modifying and must reside in RAM
;1=tests disabled: branch range
0000 = disable_selfmod = 0
;report errors through I/O channel (0=use standard self trap loops, 1=include
;report.i65 as I/O channel, add 3.5 kB)
0000 = report = 0
;RAM integrity test option. Checks for undesired RAM writes.
;set lowest non RAM or RAM mirror address page (-1=disable, 0=64k, $40=16k)
;leave disabled if a monitor, OS or background interrupt is allowed to alter RAM
ffff = ram_top = -1
;disable test decimal mode ADC & SBC, 0=enable, 1=disable,
;2=disable including decimal flag in processor status
0000 = disable_decimal = 0
noopt ;do not take shortcuts
;macros for error & success traps to allow user modification
;example:
;trap macro
; jsr my_error_handler
; endm
;trap_eq macro
; bne skip\?
; trap ;failed equal (zero)
;skip\?
; endm
;
; my_error_handler should pop the calling address from the stack and report it.
; putting larger portions of code (more than 3 bytes) inside the trap macro
; may lead to branch range problems for some tests.
if report = 0
trap macro
jmp * ;failed anyway
endm
trap_eq macro
beq * ;failed equal (zero)
endm
trap_ne macro
bne * ;failed not equal (non zero)
endm
trap_cs macro
bcs * ;failed carry set
endm
trap_cc macro
bcc * ;failed carry clear
endm
trap_mi macro
bmi * ;failed minus (bit 7 set)
endm
trap_pl macro
bpl * ;failed plus (bit 7 clear)
endm
trap_vs macro
bvs * ;failed overflow set
endm
trap_vc macro
bvc * ;failed overflow clear
endm
; please observe that during the test the stack gets invalidated
; therefore a RTS inside the success macro is not possible
success macro
jmp * ;test passed, no errors
endm
endif
if report = 1
trap macro
jsr report_error
endm
trap_eq macro
bne skip\?
trap ;failed equal (zero)
skip\?
endm
trap_ne macro
beq skip\?
trap ;failed not equal (non zero)
skip\?
endm
trap_cs macro
bcc skip\?
trap ;failed carry set
skip\?
endm
trap_cc macro
bcs skip\?
trap ;failed carry clear
skip\?
endm
trap_mi macro
bpl skip\?
trap ;failed minus (bit 7 set)
skip\?
endm
trap_pl macro
bmi skip\?
trap ;failed plus (bit 7 clear)
skip\?
endm
trap_vs macro
bvc skip\?
trap ;failed overflow set
skip\?
endm
trap_vc macro
bvs skip\?
trap ;failed overflow clear
skip\?
endm
; please observe that during the test the stack gets invalidated
; therefore a RTS inside the success macro is not possible
success macro
jsr report_success
endm
endif
0001 = carry equ %00000001 ;flag bits in status
0002 = zero equ %00000010
0004 = intdis equ %00000100
0008 = decmode equ %00001000
0010 = break equ %00010000
0020 = reserv equ %00100000
0040 = overfl equ %01000000
0080 = minus equ %10000000
0001 = fc equ carry
0002 = fz equ zero
0003 = fzc equ carry+zero
0040 = fv equ overfl
0042 = fvz equ overfl+zero
0080 = fn equ minus
0081 = fnc equ minus+carry
0082 = fnz equ minus+zero
0083 = fnzc equ minus+zero+carry
00c0 = fnv equ minus+overfl
0030 = fao equ break+reserv ;bits always on after PHP, BRK
0034 = fai equ fao+intdis ;+ forced interrupt disable
0038 = faod equ fao+decmode ;+ ignore decimal
003c = faid equ fai+decmode ;+ ignore decimal
00ff = m8 equ $ff ;8 bit mask
00fb = m8i equ $ff&~intdis ;8 bit mask - interrupt disable
;macros to allow masking of status bits.
;masking test of decimal bit
;masking of interrupt enable/disable on load and compare
;masking of always on bits after PHP or BRK (unused & break) on compare
if disable_decimal < 2
if I_flag = 0
load_flag macro
lda #\1&m8i ;force enable interrupts (mask I)
endm
cmp_flag macro
cmp #(\1|fao)&m8i ;I_flag is always enabled + always on bits
endm
eor_flag macro
eor #(\1&m8i|fao) ;mask I, invert expected flags + always on bits
endm
endif
if I_flag = 1
load_flag macro
lda #\1|intdis ;force disable interrupts
endm
cmp_flag macro
cmp #(\1|fai)&m8 ;I_flag is always disabled + always on bits
endm
eor_flag macro
eor #(\1|fai) ;invert expected flags + always on bits + I
endm
endif
if I_flag = 2
load_flag macro
lda #\1
ora flag_I_on ;restore I-flag
and flag_I_off
endm
cmp_flag macro
eor flag_I_on ;I_flag is never changed
cmp #(\1|fao)&m8i ;expected flags + always on bits, mask I
endm
eor_flag macro
eor flag_I_on ;I_flag is never changed
eor #(\1&m8i|fao) ;mask I, invert expected flags + always on bits
endm
endif
if I_flag = 3
load_flag macro
lda #\1 ;allow test to change I-flag (no mask)
endm
cmp_flag macro
cmp #(\1|fao)&m8 ;expected flags + always on bits
endm
eor_flag macro
eor #\1|fao ;invert expected flags + always on bits
endm
endif
else
if I_flag = 0
load_flag macro
lda #\1&m8i ;force enable interrupts (mask I)
endm
cmp_flag macro
ora #decmode ;ignore decimal mode bit
cmp #(\1|faod)&m8i ;I_flag is always enabled + always on bits
endm
eor_flag macro
ora #decmode ;ignore decimal mode bit
eor #(\1&m8i|faod) ;mask I, invert expected flags + always on bits
endm
endif
if I_flag = 1
load_flag macro
lda #\1|intdis ;force disable interrupts
endm
cmp_flag macro
ora #decmode ;ignore decimal mode bit
cmp #(\1|faid)&m8 ;I_flag is always disabled + always on bits
endm
eor_flag macro
ora #decmode ;ignore decimal mode bit
eor #(\1|faid) ;invert expected flags + always on bits + I
endm
endif
if I_flag = 2
load_flag macro
lda #\1
ora flag_I_on ;restore I-flag
and flag_I_off
endm
cmp_flag macro
eor flag_I_on ;I_flag is never changed
ora #decmode ;ignore decimal mode bit
cmp #(\1|faod)&m8i ;expected flags + always on bits, mask I
endm
eor_flag macro
eor flag_I_on ;I_flag is never changed
ora #decmode ;ignore decimal mode bit
eor #(\1&m8i|faod) ;mask I, invert expected flags + always on bits
endm
endif
if I_flag = 3
load_flag macro
lda #\1 ;allow test to change I-flag (no mask)
endm
cmp_flag macro
ora #decmode ;ignore decimal mode bit
cmp #(\1|faod)&m8 ;expected flags + always on bits
endm
eor_flag macro
ora #decmode ;ignore decimal mode bit
eor #\1|faod ;invert expected flags + always on bits
endm
endif
endif
;macros to set (register|memory|zeropage) & status
set_stat macro ;setting flags in the processor status register
load_flag \1
pha ;use stack to load status
plp
endm
set_a macro ;precharging accu & status
load_flag \2
pha ;use stack to load status
lda #\1 ;precharge accu
plp
endm
set_x macro ;precharging index & status
load_flag \2
pha ;use stack to load status
ldx #\1 ;precharge index x
plp
endm
set_y macro ;precharging index & status
load_flag \2
pha ;use stack to load status
ldy #\1 ;precharge index y
plp
endm
set_ax macro ;precharging indexed accu & immediate status
load_flag \2
pha ;use stack to load status
lda \1,x ;precharge accu
plp
endm
set_ay macro ;precharging indexed accu & immediate status
load_flag \2
pha ;use stack to load status
lda \1,y ;precharge accu
plp
endm
set_z macro ;precharging indexed zp & immediate status
load_flag \2
pha ;use stack to load status
lda \1,x ;load to zeropage
sta zpt
plp
endm
set_zx macro ;precharging zp,x & immediate status
load_flag \2
pha ;use stack to load status
lda \1,x ;load to indexed zeropage
sta zpt,x
plp
endm
set_abs macro ;precharging indexed memory & immediate status
load_flag \2
pha ;use stack to load status
lda \1,x ;load to memory
sta abst
plp
endm
set_absx macro ;precharging abs,x & immediate status
load_flag \2
pha ;use stack to load status
lda \1,x ;load to indexed memory
sta abst,x
plp
endm
;macros to test (register|memory|zeropage) & status & (mask)
tst_stat macro ;testing flags in the processor status register
php ;save status
pla ;use stack to retrieve status
pha
cmp_flag \1
trap_ne
plp ;restore status
endm
tst_a macro ;testing result in accu & flags
php ;save flags
cmp #\1 ;test result
trap_ne
pla ;load status
pha
cmp_flag \2
trap_ne
plp ;restore status
endm
tst_x macro ;testing result in x index & flags
php ;save flags
cpx #\1 ;test result
trap_ne
pla ;load status
pha
cmp_flag \2
trap_ne
plp ;restore status
endm
tst_y macro ;testing result in y index & flags
php ;save flags
cpy #\1 ;test result
trap_ne
pla ;load status
pha
cmp_flag \2
trap_ne
plp ;restore status
endm
tst_ax macro ;indexed testing result in accu & flags
php ;save flags
cmp \1,x ;test result
trap_ne
pla ;load status
eor_flag \3
cmp \2,x ;test flags
trap_ne ;
endm
tst_ay macro ;indexed testing result in accu & flags
php ;save flags
cmp \1,y ;test result
gitextract_1yla08f4/
├── CMakeLists.txt
├── LICENSE
├── Makefile
├── README.md
├── assets/
│ ├── bas/
│ │ ├── 10print.bas
│ │ ├── bitmap.bas
│ │ ├── bouncing.bas
│ │ └── lowercase.bas
│ ├── prg/
│ │ └── monopole.prg
│ ├── roms/
│ │ └── README.md
│ └── tests/
│ ├── 6502_functional_test.a65
│ ├── 6502_functional_test.lst
│ └── README.md
├── cmake/
│ ├── FindSDL2.cmake
│ ├── FindSDL2_image.cmake
│ ├── FindSDL2_net.cmake
│ ├── FindSDL2_ttf.cmake
│ └── README.md
├── doc/
│ ├── .gitignore
│ └── doxygen.conf
├── res/
│ └── emudore.rc
└── src/
├── c64.cpp
├── c64.h
├── cia1.cpp
├── cia1.h
├── cia2.cpp
├── cia2.h
├── cpu.cpp
├── cpu.h
├── debugger.cpp
├── debugger.h
├── io.cpp
├── io.h
├── loader.cpp
├── loader.h
├── main.cpp
├── memory.cpp
├── memory.h
├── sid.h
├── util.h
├── vic.cpp
└── vic.h
SYMBOL INDEX (21 symbols across 12 files) FILE: src/c64.h function class (line 41) | class C64 FILE: src/cia1.h function class (line 29) | class Cia1 FILE: src/cia2.h function class (line 29) | class Cia2 FILE: src/cpu.h function class (line 27) | class Cpu FILE: src/debugger.cpp type sockaddr_in (line 38) | struct sockaddr_in type sockaddr (line 58) | struct sockaddr type sockaddr_in (line 156) | struct sockaddr_in type sockaddr (line 159) | struct sockaddr FILE: src/debugger.h function class (line 34) | class Debugger FILE: src/io.h function class (line 40) | class IO function screen_update_pixel (line 89) | inline void IO::screen_update_pixel(int x, int y, int color) FILE: src/loader.h function class (line 27) | class Loader FILE: src/main.cpp function loader_cb (line 32) | bool loader_cb() function emscripten_loader_cb (line 39) | bool emscripten_loader_cb() function load_file (line 46) | void load_file(const char *file) function wget_cb (line 63) | void wget_cb(const char *f) function emscripten_loop (line 69) | void emscripten_loop() function main (line 74) | int main(int argc, char **argv) FILE: src/memory.h function class (line 50) | class Memory FILE: src/sid.h function class (line 26) | class Sid FILE: src/vic.h function class (line 33) | class Vic
Condensed preview — 42 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,067K chars).
[
{
"path": "CMakeLists.txt",
"chars": 2357,
"preview": "cmake_minimum_required (VERSION 2.8)\nproject(emudore)\nset(SRC_FILES \"src/c64.cpp\"\n \"src/cpu.cpp\"\n "
},
{
"path": "LICENSE",
"chars": 11357,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "Makefile",
"chars": 523,
"preview": "release:\n\trm -rf build/*\n\tcd build;cmake -DCMAKE_BUILD_TYPE=Release ..\n\tcd build;make\ndebug:\n\trm -rf build/*\n\tcd build;c"
},
{
"path": "README.md",
"chars": 9404,
"preview": "# emudore, a Commodore 64 emulator\n\n\n\n# What's this?\n\nemudore is a [Commodore 64 emulat"
},
{
"path": "assets/bas/10print.bas",
"chars": 71,
"preview": "REM source: http://10print.org/\n10 PRINT CHR$(205.5+RND(1)); : GOTO 10\n"
},
{
"path": "assets/bas/bitmap.bas",
"chars": 232,
"preview": "10 POKE 53272,PEEK(53272)OR8:POKE 53265,PEEK(53265)OR32\n20 FORI=8192TO16191 STEP 8\n30 POKEI,240:POKEI+1,240:POKEI+2,240:"
},
{
"path": "assets/bas/bouncing.bas",
"chars": 343,
"preview": "REM source: http://www.lemon64.com/manual/\nNEW\n10 POKE 53281,1: PRINT\"*\"\n20 POKE 53280,7: POKE 53281,6\n30 X = 1 : Y = 1\n"
},
{
"path": "assets/bas/lowercase.bas",
"chars": 44,
"preview": "REM SWITCH TO LOWERCASE MODE\nPOKE 53272,23 \n"
},
{
"path": "assets/roms/README.md",
"chars": 702,
"preview": "The following files have been downloaded from: \n\nftp://www.zimmers.net/pub/cbm/firmware/computers/c64/\n\nPlease, bear in "
},
{
"path": "assets/tests/6502_functional_test.a65",
"chars": 144710,
"preview": ";\n; 6 5 0 2 F U N C T I O N A L T E S T\n;\n; Copyright (C) 2012-2015 Klaus Dormann\n;\n; This program is free software"
},
{
"path": "assets/tests/6502_functional_test.lst",
"chars": 721434,
"preview": "AS65 Assembler for R6502 [1.42]. Copyright 1994-2007, Frank A. Kingswood "
},
{
"path": "assets/tests/README.md",
"chars": 359,
"preview": "These are Klaus Dormann 6502 functional tests, also available at:\n\nhttps://github.com/Klaus2m5/6502_65C02_functional_tes"
},
{
"path": "cmake/FindSDL2.cmake",
"chars": 6193,
"preview": "\n# This module defines\n# SDL2_LIBRARY, the name of the library to link against\n# SDL2_FOUND, if false, do not try to lin"
},
{
"path": "cmake/FindSDL2_image.cmake",
"chars": 3864,
"preview": "# Locate SDL_image library\n#\n# This module defines:\n#\n# ::\n#\n# SDL_IMAGE_LIBRARIES, the name of the library to link ag"
},
{
"path": "cmake/FindSDL2_net.cmake",
"chars": 3200,
"preview": "# - Find SDL2_net library and headers\n# \n# Find module for SDL_net 2.0 (http://www.libsdl.org/projects/SDL_net/).\n# It d"
},
{
"path": "cmake/FindSDL2_ttf.cmake",
"chars": 3728,
"preview": "# Locate SDL_image library\n#\n# This module defines:\n#\n# ::\n#\n# SDL_TTF_LIBRARIES, the name of the library to link agai"
},
{
"path": "cmake/README.md",
"chars": 82,
"preview": "These have been downloaded from:\n\nhttps://github.com/tcbrindle/sdl2-cmake-scripts\n"
},
{
"path": "doc/.gitignore",
"chars": 6,
"preview": "html/\n"
},
{
"path": "doc/doxygen.conf",
"chars": 11621,
"preview": "\n#---------------------------------------------------------------------------\n# Project related configuration options\n#-"
},
{
"path": "res/emudore.rc",
"chars": 62,
"preview": "IDI_ICON1 ICON DISCARDABLE \"emudore.ico\"\n"
},
{
"path": "src/c64.cpp",
"chars": 2976,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/c64.h",
"chars": 1538,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/cia1.cpp",
"chars": 6141,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/cia1.h",
"chars": 1888,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/cia2.cpp",
"chars": 6262,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/cia2.h",
"chars": 1902,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/cpu.cpp",
"chars": 23708,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/cpu.h",
"chars": 5444,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/debugger.cpp",
"chars": 6140,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/debugger.h",
"chars": 1689,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/io.cpp",
"chars": 12648,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/io.h",
"chars": 2599,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/loader.cpp",
"chars": 2641,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/loader.h",
"chars": 1480,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/main.cpp",
"chars": 2172,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/memory.cpp",
"chars": 7457,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/memory.h",
"chars": 4480,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/sid.h",
"chars": 857,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/util.h",
"chars": 1465,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/vic.cpp",
"chars": 19167,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
},
{
"path": "src/vic.h",
"chars": 4750,
"preview": "/*\n * emudore, Commodore 64 emulator\n * Copyright (c) 2016, Mario Ballano <mballano@gmail.com>\n *\n * Licensed under the "
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the marioballano/emudore GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 42 files (1013.4 KB), approximately 256.8k tokens, and a symbol index with 21 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.