From 5ee12bdbc0ec43c569a75573a3b64171fc8a78b0 Mon Sep 17 00:00:00 2001 From: Matthias Endler Date: Sun, 4 Nov 2018 20:26:51 +0100 Subject: [PATCH] Add no_std support --- .gitignore | 3 +- Cargo.lock | 383 ++++++++++++++++++ Cargo.toml | 21 +- README.md | 108 ++++++ build.rs | 5 + src/address.rs | 5 +- src/bin/{main.rs => mos6502.rs} | 8 +- src/cpu.rs | 663 ++++++++++++++++---------------- src/instruction.rs | 18 +- src/lib.rs | 6 +- src/registers.rs | 38 +- tests/skeptic.rs | 1 + 12 files changed, 876 insertions(+), 383 deletions(-) create mode 100644 Cargo.lock create mode 100644 build.rs rename src/bin/{main.rs => mos6502.rs} (94%) create mode 100644 tests/skeptic.rs diff --git a/.gitignore b/.gitignore index 59e08d1..0fe8ab9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ -Cargo.lock *.a *.aux *.bc @@ -65,4 +64,4 @@ TAGS.vi \#* \#*\# src/.DS_Store -tmp.*.rs \ No newline at end of file +tmp.*.rs diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..0664e70 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,383 @@ +[[package]] +name = "backtrace" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "bitflags" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitflags" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bytecount" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cargo_metadata" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cc" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "error-chain" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "itoa" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libc" +version = "0.2.43" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "log" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mos6502" +version = "0.1.0" +dependencies = [ + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "skeptic 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-complex" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-integer" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-iter" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-rational" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "proc-macro2" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pulldown-cmark" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ryu" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "same-file" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "serde_derive" +version = "1.0.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "serde_json" +version = "1.0.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "skeptic" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tempdir" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "walkdir" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" +"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" +"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f861d9ce359f56dbcb6e0c2a1cb84e52ad732cadb57b806adeb3c7668caccbd8" +"checksum cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1efca0b863ca03ed4c109fb1c55e0bc4bbeb221d3e103d86251046b06a526bd0" +"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" +"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" +"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" +"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" +"checksum num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "107b9be86cd2481930688277b675b0114578227f034674726605b8a482d8baf8" +"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" +"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" +"checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10" +"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" +"checksum proc-macro2 0.4.20 (registry+https://github.com/rust-lang/crates.io-index)" = "3d7b7eaaa90b4a90a932a9ea6666c95a389e424eff347f0f793979289429feee" +"checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" +"checksum quote 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "63b5829244f52738cfee93b3a165c1911388675be000c888d2fae620dee8fa5b" +"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" +"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" +"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" +"checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" +"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef" +"checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c" +"checksum serde_json 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "43344e7ce05d0d8280c5940cabb4964bea626aa58b1ec0e8c73fa2a8512a38ce" +"checksum skeptic 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c4474d6da9593171bcb086890fc344a3a12783cb24e5b141f8a5d0e43561f4b6" +"checksum syn 0.15.18 (registry+https://github.com/rust-lang/crates.io-index)" = "90c39a061e2f412a9f869540471ab679e85e50c6b05604daf28bc3060f75c430" +"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum walkdir 2.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0ffb549f212c31e19f3667c55a7f515b983a84aef10fd0a4d1f9c125425115f3" +"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 19be059..8ec4aeb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,18 +30,25 @@ name = "mos6502" description = "A MOS 6502 Emulator" license = "BSD-3-Clause" -version = "0.0.1" +version = "0.1.0" authors = ["The 6502-rs Developers"] +build = "build.rs" [lib] # This will look in src/lib.rs name = "mos6502" -[[bin]] -# This will look in src/bin/mos6502.rs -name = "mos6502" - [dependencies] bitflags = "0.9.1" -log = "0.3.8" -num = "0.1" +log = "0.4.6" + +[dependencies.num] +version = "0.2" +# no_std support +default-features = false + +[build-dependencies] +skeptic = "0.13" + +[dev-dependencies] +skeptic = "0.13" diff --git a/README.md b/README.md index 88b84b4..83aed56 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,111 @@ This started off as a fork of [6502-rs](https://github.com/amw-zero/6502-rs), which seems to be unmaintained at this point. It builds with the latest stable Rust. + +## Usage example + +```rust +extern crate mos6502; + +use mos6502::cpu; +use mos6502::address::Address; + +fn main() { + let mut cpu = cpu::CPU::new(); + + let zero_page_data = [ + // ZeroPage data start + 0x00, + 0x02, // ADC ZeroPage target + 0x00, + 0x04, // ADC ZeroPageX target + 0x00, + 0x00, + 0x00, + 0x00, + 0x10, // ADC IndexedIndirectX address + 0x80, // ADC IndexedIndirectX address + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x08, // ADC IndirectIndexedY address + 0x80, // ADC IndirectIndexedY address + ]; + + let program = [ + // Code start + 0xA9, // LDA Immediate + 0x01, // Immediate operand + 0x69, // ADC Immediate + 0x07, // Immediate operand + 0x65, // ADC ZeroPage + 0x01, // ZeroPage operand + 0xA2, // LDX Immediate + 0x01, // Immediate operand + 0x75, // ADC ZeroPageX + 0x02, // ZeroPageX operand + 0x6D, // ADC Absolute + 0x01, // Absolute operand + 0x80, // Absolute operand + 0xA2, // LDX immediate + 0x08, // Immediate operand + 0x7D, // ADC AbsoluteX + 0x00, // AbsoluteX operand + 0x80, // AbsoluteX operand + 0xA0, // LDY immediate + 0x04, // Immediate operand + 0x79, // ADC AbsoluteY + 0x00, // AbsoluteY operand + 0x80, // AbsoluteY operand + 0xA2, // LDX immediate + 0x05, // Immediate operand + 0x61, // ADC IndexedIndirectX + 0x03, // IndexedIndirectX operand + 0xA0, // LDY immediate + 0x10, // Immediate operand + 0x71, // ADC IndirectIndexedY + 0x0F, // IndirectIndexedY operand + 0xEA, // NOP :) + 0xFF, // Something invalid -- the end! + ]; + + let data: [u8; 25] = [ + 0x00, + 0x09, // ADC Absolute target + 0x00, + 0x00, + 0x40, // ADC AbsoluteY target + 0x00, + 0x00, + 0x00, + 0x11, // ADC AbsoluteX target + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x12, // ADC IndexedIndirectX target + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x06, // ADC IndirectIndexedY target + ]; + + // "Load" a program + cpu.memory.set_bytes(Address(0x0000), &zero_page_data); + cpu.memory.set_bytes(Address(0x4000), &program); + cpu.memory.set_bytes(Address(0x8000), &data); + + cpu.registers.program_counter = Address(0x4000); + + cpu.run(); +} +``` diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..a780b3d --- /dev/null +++ b/build.rs @@ -0,0 +1,5 @@ +extern crate skeptic; + +fn main() { + skeptic::generate_doc_tests(&["README.md"]); +} diff --git a/src/address.rs b/src/address.rs index 0479a96..b3a00f4 100644 --- a/src/address.rs +++ b/src/address.rs @@ -25,7 +25,7 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -use std::ops::Add; +use core::ops::Add; // The idea here is that it doesn't make sense to add two addresses, but it // does make sense to add an address and an "address-difference". (If this @@ -42,8 +42,7 @@ impl Add for Address { fn add(self, AddressDiff(rhs): AddressDiff) -> Address { let Address(lhs) = self; - // TODO akeeton: Do a checked cast. - Address(((lhs as i32) + rhs) as u16) + Address(((i32::from(lhs)) + rhs) as u16) } } diff --git a/src/bin/main.rs b/src/bin/mos6502.rs similarity index 94% rename from src/bin/main.rs rename to src/bin/mos6502.rs index 22e0586..f8c4612 100644 --- a/src/bin/main.rs +++ b/src/bin/mos6502.rs @@ -39,10 +39,8 @@ fn main() { // "Load" a program - // JAM: FIXME: What's the syntax for specifying the array element type, - // but not the length? (For a fixed-size array) - let zero_page_data: [u8; 17] = [ + let zero_page_data = [ // ZeroPage data start 0x00, 0x02, // ADC ZeroPage target @@ -63,7 +61,7 @@ fn main() { 0x80, // ADC IndirectIndexedY address ]; - let program: [u8; 33] = [ + let program = [ // Code start 0xA9, // LDA Immediate 0x01, // Immediate operand @@ -100,7 +98,7 @@ fn main() { 0xFF, // Something invalid -- the end! ]; - let data: [u8; 25] = [ + let data = [ 0x00, 0x09, // ADC Absolute target 0x00, diff --git a/src/cpu.rs b/src/cpu.rs index 2bdca43..972b4de 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -25,15 +25,14 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -use std; - use address::{Address, AddressDiff}; use instruction; use instruction::{DecodedInstr, Instruction, OpInput}; use memory::Memory; use registers::{Registers, StackPointer, Status, StatusArgs}; -use registers::{PS_CARRY, PS_DECIMAL_MODE, PS_DISABLE_INTERRUPTS, PS_NEGATIVE, PS_OVERFLOW, - PS_ZERO}; +use registers::{ + PS_CARRY, PS_DECIMAL_MODE, PS_DISABLE_INTERRUPTS, PS_NEGATIVE, PS_OVERFLOW, PS_ZERO, +}; #[derive(Clone)] pub struct CPU { @@ -410,12 +409,8 @@ impl CPU { } pub fn run(&mut self) { - loop { - if let Some(decoded_instr) = self.fetch_next_and_decode() { - self.execute_instruction(decoded_instr); - } else { - break; - } + while let Some(decoded_instr) = self.fetch_next_and_decode() { + self.execute_instruction(decoded_instr); } } @@ -758,8 +753,8 @@ impl CPU { } } -impl std::fmt::Debug for CPU { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +impl core::fmt::Debug for CPU { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!( f, "CPU Dump:\n\nAccumulator: {}", @@ -776,385 +771,385 @@ mod tests { #[test] fn add_with_carry_test() { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); - CPU.add_with_carry(1); - assert_eq!(CPU.registers.accumulator, 1); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.add_with_carry(1); + assert_eq!(cpu.registers.accumulator, 1); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - CPU.add_with_carry(-1); - assert_eq!(CPU.registers.accumulator, 0); - assert_eq!(CPU.registers.status.contains(PS_CARRY), true); - assert_eq!(CPU.registers.status.contains(PS_ZERO), true); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.add_with_carry(-1); + assert_eq!(cpu.registers.accumulator, 0); + assert_eq!(cpu.registers.status.contains(PS_CARRY), true); + assert_eq!(cpu.registers.status.contains(PS_ZERO), true); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - CPU.add_with_carry(1); - assert_eq!(CPU.registers.accumulator, 2); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.add_with_carry(1); + assert_eq!(cpu.registers.accumulator, 2); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); - CPU.add_with_carry(127); - assert_eq!(CPU.registers.accumulator, 127); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.add_with_carry(127); + assert_eq!(cpu.registers.accumulator, 127); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - CPU.add_with_carry(-127); - assert_eq!(CPU.registers.accumulator, 0); - assert_eq!(CPU.registers.status.contains(PS_CARRY), true); - assert_eq!(CPU.registers.status.contains(PS_ZERO), true); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.add_with_carry(-127); + assert_eq!(cpu.registers.accumulator, 0); + assert_eq!(cpu.registers.status.contains(PS_CARRY), true); + assert_eq!(cpu.registers.status.contains(PS_ZERO), true); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - CPU.registers.status.remove(PS_CARRY); - CPU.add_with_carry(-128); - assert_eq!(CPU.registers.accumulator, -128); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.registers.status.remove(PS_CARRY); + cpu.add_with_carry(-128); + assert_eq!(cpu.registers.accumulator, -128); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - CPU.add_with_carry(127); - assert_eq!(CPU.registers.accumulator, -1); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.add_with_carry(127); + assert_eq!(cpu.registers.accumulator, -1); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); - CPU.add_with_carry(127); - assert_eq!(CPU.registers.accumulator, 127); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.add_with_carry(127); + assert_eq!(cpu.registers.accumulator, 127); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - CPU.add_with_carry(1); - assert_eq!(CPU.registers.accumulator, -128); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), true); + cpu.add_with_carry(1); + assert_eq!(cpu.registers.accumulator, -128); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), true); } #[test] fn and_test() { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); - CPU.registers.accumulator = 0; - CPU.and(-1); - assert_eq!(CPU.registers.accumulator, 0); - assert_eq!(CPU.registers.status.contains(PS_ZERO), true); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + cpu.registers.accumulator = 0; + cpu.and(-1); + assert_eq!(cpu.registers.accumulator, 0); + assert_eq!(cpu.registers.status.contains(PS_ZERO), true); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); - CPU.registers.accumulator = -1; - CPU.and(0); - assert_eq!(CPU.registers.accumulator, 0); - assert_eq!(CPU.registers.status.contains(PS_ZERO), true); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + cpu.registers.accumulator = -1; + cpu.and(0); + assert_eq!(cpu.registers.accumulator, 0); + assert_eq!(cpu.registers.status.contains(PS_ZERO), true); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); - CPU.registers.accumulator = -1; - CPU.and(0x0f); - assert_eq!(CPU.registers.accumulator, 0x0f); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + cpu.registers.accumulator = -1; + cpu.and(0x0f); + assert_eq!(cpu.registers.accumulator, 0x0f); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); - CPU.registers.accumulator = -1; - CPU.and(-128); - assert_eq!(CPU.registers.accumulator, -128); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); + cpu.registers.accumulator = -1; + cpu.and(-128); + assert_eq!(cpu.registers.accumulator, -128); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), true); } #[test] fn subtract_with_carry_test() { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); - CPU.execute_instruction((Instruction::SEC, OpInput::UseImplied)); - CPU.registers.accumulator = 0; + cpu.execute_instruction((Instruction::SEC, OpInput::UseImplied)); + cpu.registers.accumulator = 0; - CPU.subtract_with_carry(1); - assert_eq!(CPU.registers.accumulator, -1); - assert_eq!(CPU.registers.status.contains(PS_CARRY), true); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.subtract_with_carry(1); + assert_eq!(cpu.registers.accumulator, -1); + assert_eq!(cpu.registers.status.contains(PS_CARRY), true); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - CPU.execute_instruction((Instruction::SEC, OpInput::UseImplied)); - CPU.registers.accumulator = -128; - CPU.subtract_with_carry(1); - assert_eq!(CPU.registers.accumulator, 127); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), true); + cpu.execute_instruction((Instruction::SEC, OpInput::UseImplied)); + cpu.registers.accumulator = -128; + cpu.subtract_with_carry(1); + assert_eq!(cpu.registers.accumulator, 127); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), true); - CPU.execute_instruction((Instruction::SEC, OpInput::UseImplied)); - CPU.registers.accumulator = 127; - CPU.subtract_with_carry(-1); - assert_eq!(CPU.registers.accumulator, -128); - assert_eq!(CPU.registers.status.contains(PS_CARRY), true); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), true); + cpu.execute_instruction((Instruction::SEC, OpInput::UseImplied)); + cpu.registers.accumulator = 127; + cpu.subtract_with_carry(-1); + assert_eq!(cpu.registers.accumulator, -128); + assert_eq!(cpu.registers.status.contains(PS_CARRY), true); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), true); - CPU.execute_instruction((Instruction::CLC, OpInput::UseImplied)); - CPU.registers.accumulator = -64; - CPU.subtract_with_carry(64); - assert_eq!(CPU.registers.accumulator, 127); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), true); + cpu.execute_instruction((Instruction::CLC, OpInput::UseImplied)); + cpu.registers.accumulator = -64; + cpu.subtract_with_carry(64); + assert_eq!(cpu.registers.accumulator, 127); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), true); - CPU.execute_instruction((Instruction::SEC, OpInput::UseImplied)); - CPU.registers.accumulator = 0; - CPU.subtract_with_carry(-128); - assert_eq!(CPU.registers.accumulator, -128); - assert_eq!(CPU.registers.status.contains(PS_CARRY), true); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), true); + cpu.execute_instruction((Instruction::SEC, OpInput::UseImplied)); + cpu.registers.accumulator = 0; + cpu.subtract_with_carry(-128); + assert_eq!(cpu.registers.accumulator, -128); + assert_eq!(cpu.registers.status.contains(PS_CARRY), true); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), true); - CPU.execute_instruction((Instruction::CLC, OpInput::UseImplied)); - CPU.registers.accumulator = 0; - CPU.subtract_with_carry(127); - assert_eq!(CPU.registers.accumulator, -128); - assert_eq!(CPU.registers.status.contains(PS_CARRY), true); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.execute_instruction((Instruction::CLC, OpInput::UseImplied)); + cpu.registers.accumulator = 0; + cpu.subtract_with_carry(127); + assert_eq!(cpu.registers.accumulator, -128); + assert_eq!(cpu.registers.status.contains(PS_CARRY), true); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); } #[test] fn decrement_memory_test() { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); let addr = Address(0xA1B2); - CPU.memory.set_byte(addr, 5); + cpu.memory.set_byte(addr, 5); - CPU.decrement_memory(addr); - assert_eq!(CPU.memory.get_byte(addr), 4); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + cpu.decrement_memory(addr); + assert_eq!(cpu.memory.get_byte(addr), 4); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); - CPU.decrement_memory(addr); - assert_eq!(CPU.memory.get_byte(addr), 3); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + cpu.decrement_memory(addr); + assert_eq!(cpu.memory.get_byte(addr), 3); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); - CPU.decrement_memory(addr); - CPU.decrement_memory(addr); - CPU.decrement_memory(addr); - assert_eq!(CPU.memory.get_byte(addr), 0); - assert_eq!(CPU.registers.status.contains(PS_ZERO), true); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); + cpu.decrement_memory(addr); + cpu.decrement_memory(addr); + cpu.decrement_memory(addr); + assert_eq!(cpu.memory.get_byte(addr), 0); + assert_eq!(cpu.registers.status.contains(PS_ZERO), true); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); - CPU.decrement_memory(addr); - assert_eq!(CPU.memory.get_byte(addr) as i8, -1); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); + cpu.decrement_memory(addr); + assert_eq!(cpu.memory.get_byte(addr) as i8, -1); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), true); } #[test] fn logical_shift_right_test() { // Testing UseImplied version (which targets the accumulator) only, for now - let mut CPU = CPU::new(); - CPU.execute_instruction((Instruction::LDA, OpInput::UseImmediate(0))); - CPU.execute_instruction((Instruction::LSR, OpInput::UseImplied)); - assert_eq!(CPU.registers.accumulator, 0); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), true); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + let mut cpu = CPU::new(); + cpu.execute_instruction((Instruction::LDA, OpInput::UseImmediate(0))); + cpu.execute_instruction((Instruction::LSR, OpInput::UseImplied)); + assert_eq!(cpu.registers.accumulator, 0); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), true); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - CPU.execute_instruction((Instruction::LDA, OpInput::UseImmediate(1))); - CPU.execute_instruction((Instruction::LSR, OpInput::UseImplied)); - assert_eq!(CPU.registers.accumulator, 0); - assert_eq!(CPU.registers.status.contains(PS_CARRY), true); - assert_eq!(CPU.registers.status.contains(PS_ZERO), true); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.execute_instruction((Instruction::LDA, OpInput::UseImmediate(1))); + cpu.execute_instruction((Instruction::LSR, OpInput::UseImplied)); + assert_eq!(cpu.registers.accumulator, 0); + assert_eq!(cpu.registers.status.contains(PS_CARRY), true); + assert_eq!(cpu.registers.status.contains(PS_ZERO), true); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - CPU.execute_instruction((Instruction::LDA, OpInput::UseImmediate(255))); - CPU.execute_instruction((Instruction::LSR, OpInput::UseImplied)); - assert_eq!(CPU.registers.accumulator, 0x7F); - assert_eq!(CPU.registers.status.contains(PS_CARRY), true); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.execute_instruction((Instruction::LDA, OpInput::UseImmediate(255))); + cpu.execute_instruction((Instruction::LSR, OpInput::UseImplied)); + assert_eq!(cpu.registers.accumulator, 0x7F); + assert_eq!(cpu.registers.status.contains(PS_CARRY), true); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - CPU.execute_instruction((Instruction::LDA, OpInput::UseImmediate(254))); - CPU.execute_instruction((Instruction::LSR, OpInput::UseImplied)); - assert_eq!(CPU.registers.accumulator, 0x7F); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.execute_instruction((Instruction::LDA, OpInput::UseImmediate(254))); + cpu.execute_instruction((Instruction::LSR, OpInput::UseImplied)); + assert_eq!(cpu.registers.accumulator, 0x7F); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); } #[test] fn dec_x_test() { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); - CPU.dec_x(); - assert_eq!(CPU.registers.index_x, -1); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.dec_x(); + assert_eq!(cpu.registers.index_x, -1); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - CPU.dec_x(); - assert_eq!(CPU.registers.index_x, -2); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.dec_x(); + assert_eq!(cpu.registers.index_x, -2); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - CPU.load_x_register(5); - CPU.dec_x(); - assert_eq!(CPU.registers.index_x, 4); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.load_x_register(5); + cpu.dec_x(); + assert_eq!(cpu.registers.index_x, 4); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - CPU.dec_x(); - CPU.dec_x(); - CPU.dec_x(); - CPU.dec_x(); + cpu.dec_x(); + cpu.dec_x(); + cpu.dec_x(); + cpu.dec_x(); - assert_eq!(CPU.registers.index_x, 0); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), true); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), false); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + assert_eq!(cpu.registers.index_x, 0); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), true); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), false); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); - CPU.dec_x(); - assert_eq!(CPU.registers.index_x, -1); - assert_eq!(CPU.registers.status.contains(PS_CARRY), false); - assert_eq!(CPU.registers.status.contains(PS_ZERO), false); - assert_eq!(CPU.registers.status.contains(PS_NEGATIVE), true); - assert_eq!(CPU.registers.status.contains(PS_OVERFLOW), false); + cpu.dec_x(); + assert_eq!(cpu.registers.index_x, -1); + assert_eq!(cpu.registers.status.contains(PS_CARRY), false); + assert_eq!(cpu.registers.status.contains(PS_ZERO), false); + assert_eq!(cpu.registers.status.contains(PS_NEGATIVE), true); + assert_eq!(cpu.registers.status.contains(PS_OVERFLOW), false); } #[test] fn jump_test() { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); let addr = Address(0xA1B1); - CPU.jump(addr); - assert_eq!(CPU.registers.program_counter, addr); + cpu.jump(addr); + assert_eq!(cpu.registers.program_counter, addr); } #[test] fn branch_if_carry_clear_test() { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); - CPU.execute_instruction((Instruction::SEC, OpInput::UseImplied)); - CPU.branch_if_carry_clear(Address(0xABCD)); - assert_eq!(CPU.registers.program_counter, Address(0)); + cpu.execute_instruction((Instruction::SEC, OpInput::UseImplied)); + cpu.branch_if_carry_clear(Address(0xABCD)); + assert_eq!(cpu.registers.program_counter, Address(0)); - CPU.execute_instruction((Instruction::CLC, OpInput::UseImplied)); - CPU.branch_if_carry_clear(Address(0xABCD)); - assert_eq!(CPU.registers.program_counter, Address(0xABCD)); + cpu.execute_instruction((Instruction::CLC, OpInput::UseImplied)); + cpu.branch_if_carry_clear(Address(0xABCD)); + assert_eq!(cpu.registers.program_counter, Address(0xABCD)); } #[test] fn branch_if_carry_set_test() { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); - CPU.execute_instruction((Instruction::CLC, OpInput::UseImplied)); - CPU.branch_if_carry_set(Address(0xABCD)); - assert_eq!(CPU.registers.program_counter, Address(0)); + cpu.execute_instruction((Instruction::CLC, OpInput::UseImplied)); + cpu.branch_if_carry_set(Address(0xABCD)); + assert_eq!(cpu.registers.program_counter, Address(0)); - CPU.execute_instruction((Instruction::SEC, OpInput::UseImplied)); - CPU.branch_if_carry_set(Address(0xABCD)); - assert_eq!(CPU.registers.program_counter, Address(0xABCD)); + cpu.execute_instruction((Instruction::SEC, OpInput::UseImplied)); + cpu.branch_if_carry_set(Address(0xABCD)); + assert_eq!(cpu.registers.program_counter, Address(0xABCD)); } #[test] fn branch_if_equal_test() { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); - CPU.branch_if_equal(Address(0xABCD)); - assert_eq!(CPU.registers.program_counter, Address(0)); + cpu.branch_if_equal(Address(0xABCD)); + assert_eq!(cpu.registers.program_counter, Address(0)); - CPU.registers.status.or(PS_ZERO); - CPU.branch_if_equal(Address(0xABCD)); - assert_eq!(CPU.registers.program_counter, Address(0xABCD)); + cpu.registers.status.or(PS_ZERO); + cpu.branch_if_equal(Address(0xABCD)); + assert_eq!(cpu.registers.program_counter, Address(0xABCD)); } #[test] fn branch_if_minus_test() { { - let mut CPU = CPU::new(); - let registers_before = CPU.registers; + let mut cpu = CPU::new(); + let registers_before = cpu.registers; - CPU.branch_if_minus(Address(0xABCD)); - assert_eq!(CPU.registers, registers_before); - assert_eq!(CPU.registers.program_counter, Address(0)); + cpu.branch_if_minus(Address(0xABCD)); + assert_eq!(cpu.registers, registers_before); + assert_eq!(cpu.registers.program_counter, Address(0)); } { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); - CPU.registers.status.or(PS_NEGATIVE); - let registers_before = CPU.registers; + cpu.registers.status.or(PS_NEGATIVE); + let registers_before = cpu.registers; - CPU.branch_if_minus(Address(0xABCD)); - assert_eq!(CPU.registers.status, registers_before.status); - assert_eq!(CPU.registers.program_counter, Address(0xABCD)); + cpu.branch_if_minus(Address(0xABCD)); + assert_eq!(cpu.registers.status, registers_before.status); + assert_eq!(cpu.registers.program_counter, Address(0xABCD)); } } #[test] fn branch_if_positive_test() { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); - CPU.registers.status.insert(PS_NEGATIVE); - CPU.branch_if_positive(Address(0xABCD)); - assert_eq!(CPU.registers.program_counter, Address(0)); + cpu.registers.status.insert(PS_NEGATIVE); + cpu.branch_if_positive(Address(0xABCD)); + assert_eq!(cpu.registers.program_counter, Address(0)); - CPU.registers.status.remove(PS_NEGATIVE); - CPU.branch_if_positive(Address(0xABCD)); - assert_eq!(CPU.registers.program_counter, Address(0xABCD)); + cpu.registers.status.remove(PS_NEGATIVE); + cpu.branch_if_positive(Address(0xABCD)); + assert_eq!(cpu.registers.program_counter, Address(0xABCD)); } #[test] fn branch_if_overflow_clear_test() { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); - CPU.registers.status.insert(PS_OVERFLOW); - CPU.branch_if_overflow_clear(Address(0xABCD)); - assert_eq!(CPU.registers.program_counter, Address(0)); + cpu.registers.status.insert(PS_OVERFLOW); + cpu.branch_if_overflow_clear(Address(0xABCD)); + assert_eq!(cpu.registers.program_counter, Address(0)); - CPU.registers.status.remove(PS_OVERFLOW); - CPU.branch_if_overflow_clear(Address(0xABCD)); - assert_eq!(CPU.registers.program_counter, Address(0xABCD)); + cpu.registers.status.remove(PS_OVERFLOW); + cpu.branch_if_overflow_clear(Address(0xABCD)); + assert_eq!(cpu.registers.program_counter, Address(0xABCD)); } #[test] fn branch_if_overflow_set_test() { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); - CPU.branch_if_overflow_set(Address(0xABCD)); - assert_eq!(CPU.registers.program_counter, Address(0)); + cpu.branch_if_overflow_set(Address(0xABCD)); + assert_eq!(cpu.registers.program_counter, Address(0)); - CPU.registers.status.insert(PS_OVERFLOW); - CPU.branch_if_overflow_set(Address(0xABCD)); - assert_eq!(CPU.registers.program_counter, Address(0xABCD)); + cpu.registers.status.insert(PS_OVERFLOW); + cpu.branch_if_overflow_set(Address(0xABCD)); + assert_eq!(cpu.registers.program_counter, Address(0xABCD)); } #[cfg(test)] @@ -1162,61 +1157,56 @@ mod tests { where F: FnMut(&mut CPU, u8), { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); - CPU.execute_instruction((load_instruction, OpInput::UseImmediate(127))); + cpu.execute_instruction((load_instruction, OpInput::UseImmediate(127))); - compare(&mut CPU, 127); - assert!(CPU.registers.status.contains(PS_ZERO)); - assert!(CPU.registers.status.contains(PS_CARRY)); - assert!(!CPU.registers.status.contains(PS_NEGATIVE)); + compare(&mut cpu, 127); + assert!(cpu.registers.status.contains(PS_ZERO)); + assert!(cpu.registers.status.contains(PS_CARRY)); + assert!(!cpu.registers.status.contains(PS_NEGATIVE)); + cpu.execute_instruction((load_instruction, OpInput::UseImmediate(127))); - CPU.execute_instruction((load_instruction, OpInput::UseImmediate(127))); + compare(&mut cpu, 1); + assert!(!cpu.registers.status.contains(PS_ZERO)); + assert!(cpu.registers.status.contains(PS_CARRY)); + assert!(!cpu.registers.status.contains(PS_NEGATIVE)); - compare(&mut CPU, 1); - assert!(!CPU.registers.status.contains(PS_ZERO)); - assert!(CPU.registers.status.contains(PS_CARRY)); - assert!(!CPU.registers.status.contains(PS_NEGATIVE)); + cpu.execute_instruction((load_instruction, OpInput::UseImmediate(1))); + compare(&mut cpu, 2); + assert!(!cpu.registers.status.contains(PS_ZERO)); + assert!(!cpu.registers.status.contains(PS_CARRY)); + assert!(cpu.registers.status.contains(PS_NEGATIVE)); - CPU.execute_instruction((load_instruction, OpInput::UseImmediate(1))); + cpu.execute_instruction((load_instruction, OpInput::UseImmediate(20))); - compare(&mut CPU, 2); - assert!(!CPU.registers.status.contains(PS_ZERO)); - assert!(!CPU.registers.status.contains(PS_CARRY)); - assert!(CPU.registers.status.contains(PS_NEGATIVE)); + compare(&mut cpu, -50i8 as u8); + assert!(!cpu.registers.status.contains(PS_ZERO)); + assert!(!cpu.registers.status.contains(PS_CARRY)); + assert!(!cpu.registers.status.contains(PS_NEGATIVE)); + cpu.execute_instruction((load_instruction, OpInput::UseImmediate(1))); - CPU.execute_instruction((load_instruction, OpInput::UseImmediate(20))); + compare(&mut cpu, -1i8 as u8); + assert!(!cpu.registers.status.contains(PS_ZERO)); + assert!(!cpu.registers.status.contains(PS_CARRY)); + assert!(!cpu.registers.status.contains(PS_NEGATIVE)); - compare(&mut CPU, -50i8 as u8); - assert!(!CPU.registers.status.contains(PS_ZERO)); - assert!(!CPU.registers.status.contains(PS_CARRY)); - assert!(!CPU.registers.status.contains(PS_NEGATIVE)); + cpu.execute_instruction((load_instruction, OpInput::UseImmediate(127))); - - CPU.execute_instruction((load_instruction, OpInput::UseImmediate(1))); - - compare(&mut CPU, -1i8 as u8); - assert!(!CPU.registers.status.contains(PS_ZERO)); - assert!(!CPU.registers.status.contains(PS_CARRY)); - assert!(!CPU.registers.status.contains(PS_NEGATIVE)); - - - CPU.execute_instruction((load_instruction, OpInput::UseImmediate(127))); - - compare(&mut CPU, -128i8 as u8); - assert!(!CPU.registers.status.contains(PS_ZERO)); - assert!(!CPU.registers.status.contains(PS_CARRY)); - assert!(CPU.registers.status.contains(PS_NEGATIVE)); + compare(&mut cpu, -128i8 as u8); + assert!(!cpu.registers.status.contains(PS_ZERO)); + assert!(!cpu.registers.status.contains(PS_CARRY)); + assert!(cpu.registers.status.contains(PS_NEGATIVE)); } #[test] fn compare_with_a_register_test() { compare_test_helper( - &mut |CPU: &mut CPU, val: u8| { - CPU.compare_with_a_register(val); + &mut |cpu: &mut CPU, val: u8| { + cpu.compare_with_a_register(val); }, Instruction::LDA, ); @@ -1225,8 +1215,8 @@ mod tests { #[test] fn compare_with_x_register_test() { compare_test_helper( - &mut |CPU: &mut CPU, val: u8| { - CPU.compare_with_x_register(val); + &mut |cpu: &mut CPU, val: u8| { + cpu.compare_with_x_register(val); }, Instruction::LDX, ); @@ -1235,8 +1225,8 @@ mod tests { #[test] fn compare_with_y_register_test() { compare_test_helper( - &mut |CPU: &mut CPU, val: u8| { - CPU.compare_with_y_register(val); + &mut |cpu: &mut CPU, val: u8| { + cpu.compare_with_y_register(val); }, Instruction::LDY, ); @@ -1244,27 +1234,27 @@ mod tests { #[test] fn exclusive_or_test() { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); for a_before in range_inclusive(0u8, 255u8) { for val in range_inclusive(0u8, 255u8) { - CPU.execute_instruction((Instruction::LDA, OpInput::UseImmediate(a_before))); + cpu.execute_instruction((Instruction::LDA, OpInput::UseImmediate(a_before))); - CPU.exclusive_or(val); + cpu.exclusive_or(val); let a_after = a_before ^ val; - assert_eq!(CPU.registers.accumulator, a_after as i8); + assert_eq!(cpu.registers.accumulator, a_after as i8); if a_after == 0 { - assert!(CPU.registers.status.contains(PS_ZERO)); + assert!(cpu.registers.status.contains(PS_ZERO)); } else { - assert!(!CPU.registers.status.contains(PS_ZERO)); + assert!(!cpu.registers.status.contains(PS_ZERO)); } if (a_after as i8) < 0 { - assert!(CPU.registers.status.contains(PS_NEGATIVE)); + assert!(cpu.registers.status.contains(PS_NEGATIVE)); } else { - assert!(!CPU.registers.status.contains(PS_NEGATIVE)); + assert!(!cpu.registers.status.contains(PS_NEGATIVE)); } } } @@ -1272,29 +1262,30 @@ mod tests { #[test] fn inclusive_or_test() { - let mut CPU = CPU::new(); + let mut cpu = CPU::new(); for a_before in range_inclusive(0u8, 255u8) { for val in range_inclusive(0u8, 255u8) { - CPU.execute_instruction((Instruction::LDA, OpInput::UseImmediate(a_before))); + cpu.execute_instruction((Instruction::LDA, OpInput::UseImmediate(a_before))); - CPU.inclusive_or(val); + cpu.inclusive_or(val); let a_after = a_before | val; - assert_eq!(CPU.registers.accumulator, a_after as i8); + assert_eq!(cpu.registers.accumulator, a_after as i8); if a_after == 0 { - assert!(CPU.registers.status.contains(PS_ZERO)); + assert!(cpu.registers.status.contains(PS_ZERO)); } else { - assert!(!CPU.registers.status.contains(PS_ZERO)); + assert!(!cpu.registers.status.contains(PS_ZERO)); } if (a_after as i8) < 0 { - assert!(CPU.registers.status.contains(PS_NEGATIVE)); + assert!(cpu.registers.status.contains(PS_NEGATIVE)); } else { - assert!(!CPU.registers.status.contains(PS_NEGATIVE)); + assert!(!cpu.registers.status.contains(PS_NEGATIVE)); } } } } } + diff --git a/src/instruction.rs b/src/instruction.rs index cf77feb..ac053f2 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -139,7 +139,7 @@ pub enum AddressingMode { fn arr_to_addr(arr: &[u8]) -> Address { debug_assert!(arr.len() == 2); - let x = (arr[0] as u16) + ((arr[1] as u16) << 8usize); + let x = u16::from(arr[0]) + (u16::from(arr[1]) << 8usize); Address(x) } @@ -187,19 +187,19 @@ impl AddressingMode { // Use [u8, ..1] from instruction // Interpret as zero page address // (Output: an 8-bit zero-page address) - OpInput::UseAddress(Address(arr[0] as u16)) + OpInput::UseAddress(Address(u16::from(arr[0]))) } AddressingMode::ZeroPageX => { // Use [u8, ..1] from instruction // Add to X register (as u8 -- the final address is in 0-page) // (Output: an 8-bit zero-page address) - OpInput::UseAddress(Address((arr[0] + x) as u16)) + OpInput::UseAddress(Address(u16::from(arr[0] + x))) } AddressingMode::ZeroPageY => { // Use [u8, ..1] from instruction // Add to Y register (as u8 -- the final address is in 0-page) // (Output: an 8-bit zero-page address) - OpInput::UseAddress(Address((arr[0] + y) as u16)) + OpInput::UseAddress(Address(u16::from(arr[0] + y))) } AddressingMode::Relative => { // Use [u8, ..1] from instruction @@ -214,12 +214,12 @@ impl AddressingMode { AddressingMode::AbsoluteX => { // Use [u8, ..2] from instruction as address, add X // (Output: a 16-bit address) - OpInput::UseAddress(arr_to_addr(arr) + AddressDiff(x as i32)) + OpInput::UseAddress(arr_to_addr(arr) + AddressDiff(i32::from(x))) } AddressingMode::AbsoluteY => { // Use [u8, ..2] from instruction as address, add Y // (Output: a 16-bit address) - OpInput::UseAddress(arr_to_addr(arr) + AddressDiff(y as i32)) + OpInput::UseAddress(arr_to_addr(arr) + AddressDiff(i32::from(y))) } AddressingMode::Indirect => { // Use [u8, ..2] from instruction as an address. Interpret the @@ -234,7 +234,7 @@ impl AddressingMode { // This is where the absolute (16-bit) target address is stored. // (Output: a 16-bit address) let start = arr[0] + x; - let slice = memory.get_slice(Address(start as u16), AddressDiff(2)); + let slice = memory.get_slice(Address(u16::from(start)), AddressDiff(2)); OpInput::UseAddress(arr_to_addr(slice)) } AddressingMode::IndirectIndexedY => { @@ -243,8 +243,8 @@ impl AddressingMode { // Add Y register to this address to get the final address // (Output: a 16-bit address) let start = arr[0]; - let slice = memory.get_slice(Address(start as u16), AddressDiff(2)); - OpInput::UseAddress(arr_to_addr(slice) + AddressDiff(y as i32)) + let slice = memory.get_slice(Address(u16::from(start)), AddressDiff(2)); + OpInput::UseAddress(arr_to_addr(slice) + AddressDiff(i32::from(y))) } } } diff --git a/src/lib.rs b/src/lib.rs index fd23caf..64e8035 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,7 +25,8 @@ // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. -// Needed for debug! / log! macros +#![no_std] + #[macro_use] extern crate log; @@ -35,7 +36,8 @@ extern crate num; extern crate bitflags; pub mod address; -pub mod instruction; pub mod cpu; +pub mod instruction; pub mod memory; pub mod registers; + diff --git a/src/registers.rs b/src/registers.rs index 77ea196..485e923 100644 --- a/src/registers.rs +++ b/src/registers.rs @@ -58,17 +58,17 @@ impl StatusArgs { bitflags! { pub struct Status: u8 { - const PS_NEGATIVE = 0b10000000; - const PS_OVERFLOW = 0b01000000; - const PS_UNUSED = 0b00100000; // JAM: Should this exist? + const PS_NEGATIVE = 0b1000_0000; + const PS_OVERFLOW = 0b0100_0000; + const PS_UNUSED = 0b0010_0000; // JAM: Should this exist? // (note that it affects the // behavior of things like // from_bits_truncate) - const PS_BRK = 0b00010000; - const PS_DECIMAL_MODE = 0b00001000; - const PS_DISABLE_INTERRUPTS = 0b00000100; - const PS_ZERO = 0b00000010; - const PS_CARRY = 0b00000001; + const PS_BRK = 0b0001_0000; + const PS_DECIMAL_MODE = 0b0000_1000; + const PS_DISABLE_INTERRUPTS = 0b0000_0100; + const PS_ZERO = 0b0000_0010; + const PS_CARRY = 0b0000_0001; } } @@ -100,39 +100,39 @@ impl Status { let mut out = Status::empty(); if negative { - out = out | PS_NEGATIVE + out |= PS_NEGATIVE } if overflow { - out = out | PS_OVERFLOW + out |= PS_OVERFLOW } if unused { - out = out | PS_UNUSED + out |= PS_UNUSED } if brk { - out = out | PS_BRK + out |= PS_BRK } if decimal_mode { - out = out | PS_DECIMAL_MODE + out |= PS_DECIMAL_MODE } if disable_interrupts { - out = out | PS_DISABLE_INTERRUPTS + out |= PS_DISABLE_INTERRUPTS } if zero { - out = out | PS_ZERO + out |= PS_ZERO } if carry { - out = out | PS_CARRY + out |= PS_CARRY } out } pub fn and(&mut self, rhs: Status) { - *self = *self & rhs; + *self &= rhs; } pub fn or(&mut self, rhs: Status) { - *self = *self | rhs; + *self |= rhs; } pub fn set_with_mask(&mut self, mask: Status, rhs: Status) { @@ -146,7 +146,7 @@ pub struct StackPointer(pub u8); impl StackPointer { pub fn to_address(&self) -> Address { let StackPointer(sp) = *self; - STACK_ADDRESS_LO + AddressDiff(sp as i32) + STACK_ADDRESS_LO + AddressDiff(i32::from(sp)) } // JAM: FIXME: Should we prevent overflow here? What would a 6502 do? diff --git a/tests/skeptic.rs b/tests/skeptic.rs new file mode 100644 index 0000000..ff46c9c --- /dev/null +++ b/tests/skeptic.rs @@ -0,0 +1 @@ +include!(concat!(env!("OUT_DIR"), "/skeptic-tests.rs"));