initial commit
This commit is contained in:
commit
6ab27289a8
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/.idea/
|
||||||
|
|
||||||
|
/target
|
400
Cargo.lock
generated
Normal file
400
Cargo.lock
generated
Normal file
@ -0,0 +1,400 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android-tzdata"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android_system_properties"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c"
|
||||||
|
dependencies = [
|
||||||
|
"shlex",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
|
||||||
|
dependencies = [
|
||||||
|
"android-tzdata",
|
||||||
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
|
"num-traits",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-link",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "core-foundation-sys"
|
||||||
|
version = "0.8.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "customasm"
|
||||||
|
version = "0.13.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "570773ea039d836498dbadc8de4ea40609325b1bdbd159adc82aecc7f790a2dd"
|
||||||
|
dependencies = [
|
||||||
|
"getopts",
|
||||||
|
"num-bigint",
|
||||||
|
"vergen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "footvm"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"customasm",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getopts"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone"
|
||||||
|
version = "0.1.61"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
|
||||||
|
dependencies = [
|
||||||
|
"android_system_properties",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"iana-time-zone-haiku",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone-haiku"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.77"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.170"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.20.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.94"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.39"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||||
|
dependencies = [
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.99"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "vergen"
|
||||||
|
version = "3.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7141e445af09c8919f1d5f8a20dae0b20c3b57a45dee0d5823c6ed5d237f15a"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"chrono",
|
||||||
|
"rustc_version",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"rustversion",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-backend"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"log",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.52.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-link"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6dccfd733ce2b1753b03b6d3c65edf020262ea35e20ccdf3e288043e6dd620e3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_gnullvm",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "footvm"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
byteorder = "1"
|
||||||
|
customasm = "0.13.9"
|
42
src/foot.asm
Normal file
42
src/foot.asm
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#subruledef operand
|
||||||
|
{
|
||||||
|
#{immediate: s5} => 0b000 @ immediate
|
||||||
|
r{register: u5} => 0b001 @ register
|
||||||
|
[r{register: u5}++] => 0b010 @ register
|
||||||
|
[r{register: u5}--] => 0b011 @ register
|
||||||
|
[r{register: u5}] => 0b100 @ register
|
||||||
|
[r{register: u5} + {offset: u2} => 0b1 @ offset @ register
|
||||||
|
}
|
||||||
|
|
||||||
|
#subruledef crflags
|
||||||
|
{
|
||||||
|
. => 0b0000
|
||||||
|
.l => 0b0010
|
||||||
|
.le => 0b0100
|
||||||
|
.e => 0b0110
|
||||||
|
.ge => 0b1000
|
||||||
|
.g => 0b1010
|
||||||
|
.ne => 0b1100
|
||||||
|
.r => 0b0001
|
||||||
|
.rl => 0b0011
|
||||||
|
.rle => 0b0101
|
||||||
|
.re => 0b0111
|
||||||
|
.rge => 0b1001
|
||||||
|
.re => 0b1011
|
||||||
|
.rne => 0b1101
|
||||||
|
}
|
||||||
|
|
||||||
|
#ruledef
|
||||||
|
{
|
||||||
|
CNST{flags: crflags} {dst: operand}, {imm: i16} => imm @ 0b0000 @ flags @ dst
|
||||||
|
}
|
||||||
|
|
||||||
|
#bankdef mem
|
||||||
|
{
|
||||||
|
#bits 16
|
||||||
|
#addr 0
|
||||||
|
#size 0x10000
|
||||||
|
#outp 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#bank mem
|
18
src/main.rs
Normal file
18
src/main.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
mod vm;
|
||||||
|
|
||||||
|
use vm::{FootVM};
|
||||||
|
|
||||||
|
fn main()
|
||||||
|
{
|
||||||
|
let mut vm = FootVM::new();
|
||||||
|
vm[0] = 0xFEED;
|
||||||
|
vm[1] = 0b0000_0000_001_00000;
|
||||||
|
|
||||||
|
let result = vm.load("CNST. r0, 0xBEEF", Some(&mut std::io::stderr()));
|
||||||
|
if result.is_ok()
|
||||||
|
{
|
||||||
|
vm.cycle();
|
||||||
|
|
||||||
|
println!("{}", vm.registers[0]);
|
||||||
|
}
|
||||||
|
}
|
574
src/vm.rs
Normal file
574
src/vm.rs
Normal file
@ -0,0 +1,574 @@
|
|||||||
|
use std::io::{Cursor};
|
||||||
|
use std::ops::{Index, IndexMut};
|
||||||
|
use AddressingMode::*;
|
||||||
|
use ConditionalExecutionFlag::*;
|
||||||
|
use Instruction::*;
|
||||||
|
use byteorder::{BigEndian, ReadBytesExt};
|
||||||
|
|
||||||
|
const ASM_PREFIX: &str = include_str!("foot.asm");
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
enum ConditionalExecutionFlag
|
||||||
|
{
|
||||||
|
Always,
|
||||||
|
LessThan,
|
||||||
|
LessThanOrEqual,
|
||||||
|
Equal,
|
||||||
|
GreaterThanOrEqual,
|
||||||
|
GreaterThan,
|
||||||
|
NotEqual
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u32> for ConditionalExecutionFlag
|
||||||
|
{
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: u32) -> Result<Self, Self::Error>
|
||||||
|
{
|
||||||
|
match value
|
||||||
|
{
|
||||||
|
0 => Ok(Always),
|
||||||
|
1 => Ok(LessThan),
|
||||||
|
2 => Ok(LessThanOrEqual),
|
||||||
|
3 => Ok(Equal),
|
||||||
|
4 => Ok(GreaterThanOrEqual),
|
||||||
|
5 => Ok(GreaterThan),
|
||||||
|
6 => Ok(NotEqual),
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
enum AddressingMode
|
||||||
|
{
|
||||||
|
Immediate,
|
||||||
|
Direct,
|
||||||
|
Indirect(u8),
|
||||||
|
IndirectAutoIncrement,
|
||||||
|
IndirectAutoDecrement
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u32> for AddressingMode
|
||||||
|
{
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: u32) -> Result<Self, Self::Error>
|
||||||
|
{
|
||||||
|
match value
|
||||||
|
{
|
||||||
|
0 => Ok(Immediate),
|
||||||
|
1 => Ok(Direct),
|
||||||
|
2 => Ok(IndirectAutoIncrement),
|
||||||
|
3 => Ok(IndirectAutoDecrement),
|
||||||
|
4..8 => Ok(Indirect((value - 4) as u8)),
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
struct Operand
|
||||||
|
{
|
||||||
|
pub addressing_mode: AddressingMode,
|
||||||
|
pub value: u8
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u32> for Operand
|
||||||
|
{
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: u32) -> Result<Self, Self::Error>
|
||||||
|
{
|
||||||
|
match (value >> 5).try_into()
|
||||||
|
{
|
||||||
|
Ok(addressing_mode) => Ok(
|
||||||
|
Operand
|
||||||
|
{
|
||||||
|
addressing_mode,
|
||||||
|
value: (value as u8) & 0b00011111
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Err(_) => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Instruction
|
||||||
|
{
|
||||||
|
CNST(ConditionalExecutionFlag, bool, Operand, u16),
|
||||||
|
CMPR(ConditionalExecutionFlag, bool, Operand, Operand),
|
||||||
|
BWNG(ConditionalExecutionFlag, bool, Operand, Operand),
|
||||||
|
ARNG(ConditionalExecutionFlag, bool, Operand, Operand),
|
||||||
|
LONG(ConditionalExecutionFlag, bool, Operand, Operand),
|
||||||
|
BWOR(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
|
BAND(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
|
BXOR(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
|
URSH(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
|
SRSH(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
|
ZLSH(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
|
CLSH(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
|
ADDI(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
|
SUBT(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
|
MULT(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
|
DIVI(ConditionalExecutionFlag, bool, Operand, Operand, Operand),
|
||||||
|
MODU(ConditionalExecutionFlag, bool, Operand, Operand, Operand)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<u32> for Instruction
|
||||||
|
{
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: u32) -> Result<Self, Self::Error>
|
||||||
|
{
|
||||||
|
let ceflag: ConditionalExecutionFlag = (value >> 29).try_into()?;
|
||||||
|
let rflag: bool = (value >> 28 & 1) == 1;
|
||||||
|
let dst: Operand = (value >> 16).try_into()?;
|
||||||
|
match value >> 24
|
||||||
|
{
|
||||||
|
0 => Ok(CNST(ceflag, rflag, dst, (value & 0xFFFF) as u16)),
|
||||||
|
1 =>
|
||||||
|
{
|
||||||
|
let a: Operand = (value & 0xFF).try_into()?;
|
||||||
|
match (value >> 8) & 0xFF
|
||||||
|
{
|
||||||
|
0 => Ok(CMPR(ceflag, rflag, dst, a)),
|
||||||
|
1 => Ok(BWNG(ceflag, rflag, dst, a)),
|
||||||
|
2 => Ok(ARNG(ceflag, rflag, dst, a)),
|
||||||
|
3 => Ok(LONG(ceflag, rflag, dst, a)),
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
2..14 =>
|
||||||
|
{
|
||||||
|
let a: Operand = (value & 0xFF).try_into()?;
|
||||||
|
let b: Operand = ((value >> 8) & 0xFF).try_into()?;
|
||||||
|
match value >> 24
|
||||||
|
{
|
||||||
|
2 => Ok(BWOR(ceflag, rflag, dst, b, a)),
|
||||||
|
3 => Ok(BAND(ceflag, rflag, dst, b, a)),
|
||||||
|
4 => Ok(BXOR(ceflag, rflag, dst, b, a)),
|
||||||
|
5 => Ok(URSH(ceflag, rflag, dst, b, a)),
|
||||||
|
6 => Ok(SRSH(ceflag, rflag, dst, b, a)),
|
||||||
|
7 => Ok(ZLSH(ceflag, rflag, dst, b, a)),
|
||||||
|
8 => Ok(CLSH(ceflag, rflag, dst, b, a)),
|
||||||
|
9 => Ok(ADDI(ceflag, rflag, dst, b, a)),
|
||||||
|
10 => Ok(SUBT(ceflag, rflag, dst, b, a)),
|
||||||
|
11 => Ok(MULT(ceflag, rflag, dst, b, a)),
|
||||||
|
12 => Ok(DIVI(ceflag, rflag, dst, b, a)),
|
||||||
|
13 => Ok(MODU(ceflag, rflag, dst, b, a)),
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq)]
|
||||||
|
enum Status
|
||||||
|
{
|
||||||
|
Less,
|
||||||
|
Equal,
|
||||||
|
Greater
|
||||||
|
}
|
||||||
|
|
||||||
|
const MEMORY_SIZE: usize = 1 << 16;
|
||||||
|
|
||||||
|
pub struct FootVM
|
||||||
|
{
|
||||||
|
memory: [u16; MEMORY_SIZE],
|
||||||
|
pub registers: [u16; 32],
|
||||||
|
status: Status
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! run_instruction
|
||||||
|
{
|
||||||
|
($self:ident, $cef:ident, $rep:ident, $name:ident, $d:ident, $a:ident) =>
|
||||||
|
{
|
||||||
|
if $rep
|
||||||
|
{
|
||||||
|
while $self.should_repeat()
|
||||||
|
{
|
||||||
|
if $self.check($cef)
|
||||||
|
{
|
||||||
|
$self.$name($d, $a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if $self.check($cef)
|
||||||
|
{
|
||||||
|
$self.$name($d, $a)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($self:ident, $cef:ident, $rep:ident, $name:ident, $d:ident, $a:ident, $b:ident) =>
|
||||||
|
{
|
||||||
|
if $rep
|
||||||
|
{
|
||||||
|
while $self.should_repeat()
|
||||||
|
{
|
||||||
|
if $self.check($cef)
|
||||||
|
{
|
||||||
|
$self.$name($d, $a, $b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if $self.check($cef)
|
||||||
|
{
|
||||||
|
$self.$name($d, $a, $b)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FootVM
|
||||||
|
{
|
||||||
|
pub fn new() -> FootVM
|
||||||
|
{
|
||||||
|
FootVM
|
||||||
|
{
|
||||||
|
memory: [0; MEMORY_SIZE],
|
||||||
|
registers: [0; 32],
|
||||||
|
status: Status::Equal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load(&mut self, asm_src: &str, write: Option<&mut dyn std::io::Write>) -> Result<(), ()>
|
||||||
|
{
|
||||||
|
let mut asm_src = asm_src.to_owned();
|
||||||
|
asm_src.insert_str(0, ASM_PREFIX);
|
||||||
|
let asm_src = asm_src;
|
||||||
|
|
||||||
|
let virtual_filename = "loaded";
|
||||||
|
let mut report = customasm::diagn::Report::new();
|
||||||
|
let mut fileserver = customasm::util::FileServerMock::new();
|
||||||
|
fileserver.add(virtual_filename, asm_src);
|
||||||
|
|
||||||
|
let opts = customasm::asm::AssemblyOptions::new();
|
||||||
|
|
||||||
|
let assembly = customasm::asm::assemble(
|
||||||
|
&mut report,
|
||||||
|
&opts,
|
||||||
|
&mut fileserver,
|
||||||
|
&[virtual_filename]
|
||||||
|
);
|
||||||
|
|
||||||
|
let binary = assembly.output.map(|o| o.format_binary()).ok_or_else(
|
||||||
|
|| {
|
||||||
|
match write
|
||||||
|
{
|
||||||
|
Some(w) => report.print_all(w, &mut fileserver, true),
|
||||||
|
None => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut cursor = Cursor::new(binary);
|
||||||
|
let mut index = 0;
|
||||||
|
|
||||||
|
loop
|
||||||
|
{
|
||||||
|
match cursor.read_u16::<BigEndian>()
|
||||||
|
{
|
||||||
|
Ok(value) =>
|
||||||
|
{
|
||||||
|
self[index] = value;
|
||||||
|
index += 1;
|
||||||
|
},
|
||||||
|
Err(_) => break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cycle(&mut self)
|
||||||
|
{
|
||||||
|
let first_word = self[self.program_counter()];
|
||||||
|
let second_word = self[self.program_counter() + 1];
|
||||||
|
match ((second_word as u32) << 16 | first_word as u32).try_into()
|
||||||
|
{
|
||||||
|
Ok(CNST(cef, rep, dst, imm)) =>
|
||||||
|
run_instruction!(self, cef, rep, cnst, dst, imm),
|
||||||
|
Ok(CMPR(cef, rep, a, b)) =>
|
||||||
|
run_instruction!(self, cef, rep, cmpr, a, b),
|
||||||
|
Ok(BWNG(cef, rep, dst, src)) =>
|
||||||
|
run_instruction!(self, cef, rep, bwng, dst, src),
|
||||||
|
Ok(ARNG(cef, rep, dst, src)) =>
|
||||||
|
run_instruction!(self, cef, rep, arng, dst, src),
|
||||||
|
Ok(LONG(cef, rep, dst, src)) =>
|
||||||
|
run_instruction!(self, cef, rep, long, dst, src),
|
||||||
|
Ok(BWOR(cef, rep, dst, b, a)) =>
|
||||||
|
run_instruction!(self, cef, rep, bwor, dst, a, b),
|
||||||
|
Ok(BAND(cef, rep, dst, b, a)) =>
|
||||||
|
run_instruction!(self, cef, rep, band, dst, a, b),
|
||||||
|
Ok(BXOR(cef, rep, dst, b, a)) =>
|
||||||
|
run_instruction!(self, cef, rep, bxor, dst, a, b),
|
||||||
|
Ok(URSH(cef, rep, dst, b, a)) =>
|
||||||
|
run_instruction!(self, cef, rep, ursh, dst, a, b),
|
||||||
|
Ok(SRSH(cef, rep, dst, b, a)) =>
|
||||||
|
run_instruction!(self, cef, rep, srsh, dst, a, b),
|
||||||
|
Ok(ZLSH(cef, rep, dst, b, a)) =>
|
||||||
|
run_instruction!(self, cef, rep, zlsh, dst, a, b),
|
||||||
|
Ok(CLSH(cef, rep, dst, b, a)) =>
|
||||||
|
run_instruction!(self, cef, rep, clsh, dst, a, b),
|
||||||
|
Ok(ADDI(cef, rep, dst, b, a)) =>
|
||||||
|
run_instruction!(self, cef, rep, addi, dst, a, b),
|
||||||
|
Ok(SUBT(cef, rep, dst, b, a)) =>
|
||||||
|
run_instruction!(self, cef, rep, subt, dst, a, b),
|
||||||
|
Ok(MULT(cef, rep, dst, b, a)) =>
|
||||||
|
run_instruction!(self, cef, rep, mult, dst, a, b),
|
||||||
|
Ok(DIVI(cef, rep, dst, b, a)) =>
|
||||||
|
run_instruction!(self, cef, rep, divi, dst, a, b),
|
||||||
|
Ok(MODU(cef, rep, dst, b, a)) =>
|
||||||
|
run_instruction!(self, cef, rep, modu, dst, a, b),
|
||||||
|
Err(_) => ()
|
||||||
|
}
|
||||||
|
|
||||||
|
*self.mut_program_counter() += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cnst(&mut self, dst: Operand, imm: u16)
|
||||||
|
{
|
||||||
|
self.store_operand(dst, imm)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cmpr(&mut self, a: Operand, b: Operand)
|
||||||
|
{
|
||||||
|
let a = self.load_operand(a) as i16;
|
||||||
|
let b = self.load_operand(b) as i16;
|
||||||
|
|
||||||
|
self.status = match a - b
|
||||||
|
{
|
||||||
|
..0 => Status::Less,
|
||||||
|
0 => Status::Equal,
|
||||||
|
1.. => Status::Greater
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bwng(&mut self, dst: Operand, src: Operand)
|
||||||
|
{
|
||||||
|
let value = self.load_operand(src);
|
||||||
|
self.store_operand(dst, !value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn arng(&mut self, dst: Operand, src: Operand)
|
||||||
|
{
|
||||||
|
let a = self.load_operand(src);
|
||||||
|
self.store_operand(dst, (-(a as i16)) as u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn long(&mut self, dst: Operand, src: Operand)
|
||||||
|
{
|
||||||
|
let a = self.load_operand(src);
|
||||||
|
match a
|
||||||
|
{
|
||||||
|
0 => self.store_operand(dst, 1),
|
||||||
|
_ => self.store_operand(dst, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bwor(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
|
{
|
||||||
|
let a = self.load_operand(src_a);
|
||||||
|
let b = self.load_operand(src_b);
|
||||||
|
self.store_operand(dst, a | b);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn band(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
|
{
|
||||||
|
let a = self.load_operand(src_a);
|
||||||
|
let b = self.load_operand(src_b);
|
||||||
|
self.store_operand(dst, a & b);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bxor(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
|
{
|
||||||
|
let a = self.load_operand(src_a);
|
||||||
|
let b = self.load_operand(src_b);
|
||||||
|
self.store_operand(dst, a ^ b);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ursh(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
|
{
|
||||||
|
let a = self.load_operand(src_a);
|
||||||
|
let b = self.load_operand(src_b);
|
||||||
|
self.store_operand(dst, a >> b);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn srsh(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
|
{
|
||||||
|
let a = self.load_operand(src_a);
|
||||||
|
let b = self.load_operand(src_b);
|
||||||
|
self.store_operand(dst, ((a as i16) >> (b as i16)) as u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zlsh(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
|
{
|
||||||
|
let a = self.load_operand(src_a);
|
||||||
|
let b = self.load_operand(src_b);
|
||||||
|
self.store_operand(dst, a << b);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clsh(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
|
{
|
||||||
|
let a = self.load_operand(src_a);
|
||||||
|
let b = self.load_operand(src_b);
|
||||||
|
self.store_operand(dst, a.rotate_left(b as u32));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn addi(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
|
{
|
||||||
|
let a = self.load_operand(src_a);
|
||||||
|
let b = self.load_operand(src_b);
|
||||||
|
self.store_operand(dst, ((a as i16) + (b as i16)) as u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn subt(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
|
{
|
||||||
|
let a = self.load_operand(src_a);
|
||||||
|
let b = self.load_operand(src_b);
|
||||||
|
self.store_operand(dst, ((a as i16) - (b as i16)) as u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mult(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
|
{
|
||||||
|
let a = self.load_operand(src_a);
|
||||||
|
let b = self.load_operand(src_b);
|
||||||
|
self.store_operand(dst, ((a as i16) * (b as i16)) as u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn divi(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
|
{
|
||||||
|
let a = self.load_operand(src_a);
|
||||||
|
let b = self.load_operand(src_b);
|
||||||
|
self.store_operand(dst, ((a as i16) / (b as i16)) as u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn modu(&mut self, dst: Operand, src_a: Operand, src_b: Operand)
|
||||||
|
{
|
||||||
|
let a = self.load_operand(src_a);
|
||||||
|
let b = self.load_operand(src_b);
|
||||||
|
self.store_operand(dst, ((a as i16) % (b as i16)) as u16);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn store_operand(&mut self, dst: Operand, value: u16)
|
||||||
|
{
|
||||||
|
match dst.addressing_mode
|
||||||
|
{
|
||||||
|
Immediate => (),
|
||||||
|
Direct => self.registers[dst.value as usize] = value,
|
||||||
|
Indirect(offset) =>
|
||||||
|
{
|
||||||
|
let ptr = self.registers[dst.value as usize] + offset as u16;
|
||||||
|
self[ptr] = value
|
||||||
|
}
|
||||||
|
IndirectAutoIncrement =>
|
||||||
|
{
|
||||||
|
let ptr = self.registers[dst.value as usize];
|
||||||
|
self[ptr] = value;
|
||||||
|
self.registers[dst.value as usize] += 1;
|
||||||
|
},
|
||||||
|
IndirectAutoDecrement =>
|
||||||
|
{
|
||||||
|
let ptr = self.registers[dst.value as usize];
|
||||||
|
self[ptr] = value;
|
||||||
|
self.registers[dst.value as usize] -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_operand(&mut self, src: Operand) -> u16
|
||||||
|
{
|
||||||
|
match src.addressing_mode
|
||||||
|
{
|
||||||
|
Immediate => src.value as u16,
|
||||||
|
Direct => self.registers[src.value as usize],
|
||||||
|
Indirect(offset) => self[self.registers[src.value as usize] + offset as u16],
|
||||||
|
IndirectAutoIncrement =>
|
||||||
|
{
|
||||||
|
let ptr = self.registers[src.value as usize];
|
||||||
|
let retval = self[ptr];
|
||||||
|
self.registers[src.value as usize] += 1;
|
||||||
|
retval
|
||||||
|
},
|
||||||
|
IndirectAutoDecrement =>
|
||||||
|
{
|
||||||
|
let ptr = self.registers[src.value as usize];
|
||||||
|
let retval = self[ptr];
|
||||||
|
self.registers[src.value as usize] -= 1;
|
||||||
|
retval
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn program_counter(&self) -> u16
|
||||||
|
{
|
||||||
|
self.registers[31]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mut_program_counter(&mut self) -> &mut u16
|
||||||
|
{
|
||||||
|
&mut self.registers[31]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stack_pointer(&self) -> u16
|
||||||
|
{
|
||||||
|
self.registers[30]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn loop_count(&self) -> u16
|
||||||
|
{
|
||||||
|
self.registers[29]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mut_loop_count(&mut self) -> &mut u16
|
||||||
|
{
|
||||||
|
&mut self.registers[29]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn should_repeat(&mut self) -> bool
|
||||||
|
{
|
||||||
|
if self.loop_count() > 0
|
||||||
|
{
|
||||||
|
*self.mut_loop_count() -= 1;
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check(&self, cef: ConditionalExecutionFlag) -> bool
|
||||||
|
{
|
||||||
|
match cef
|
||||||
|
{
|
||||||
|
Always => true,
|
||||||
|
LessThan => self.status == Status::Less,
|
||||||
|
LessThanOrEqual => self.status == Status::Less || self.status == Status::Equal,
|
||||||
|
Equal => self.status == Status::Equal,
|
||||||
|
GreaterThanOrEqual => self.status == Status::Greater || self.status == Status::Equal,
|
||||||
|
GreaterThan => self.status == Status::Greater,
|
||||||
|
NotEqual => self.status != Status::Equal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Index<u16> for FootVM
|
||||||
|
{
|
||||||
|
type Output = u16;
|
||||||
|
|
||||||
|
fn index(&self, index: u16) -> &Self::Output
|
||||||
|
{
|
||||||
|
&self.memory[index as usize]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexMut<u16> for FootVM
|
||||||
|
{
|
||||||
|
fn index_mut(&mut self, index: u16) -> &mut Self::Output
|
||||||
|
{
|
||||||
|
&mut self.memory[index as usize]
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user