Compare commits
2 Commits
1237cc4163
...
7d1fd088ef
Author | SHA1 | Date | |
---|---|---|---|
7d1fd088ef | |||
923c0373b3 |
267
Cargo.lock
generated
267
Cargo.lock
generated
@ -4,9 +4,9 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.19"
|
||||
version = "0.7.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
|
||||
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@ -22,9 +22,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.66"
|
||||
version = "1.0.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
|
||||
checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
@ -38,7 +38,7 @@ version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"hermit-abi 0.1.19",
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
@ -69,15 +69,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.11.1"
|
||||
version = "3.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
|
||||
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
|
||||
|
||||
[[package]]
|
||||
name = "card_macro"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.76"
|
||||
version = "1.0.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f"
|
||||
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
@ -109,7 +118,7 @@ dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
"clap_derive",
|
||||
"clap_lex",
|
||||
"clap_lex 0.2.4",
|
||||
"indexmap",
|
||||
"once_cell",
|
||||
"strsim",
|
||||
@ -117,6 +126,19 @@ dependencies = [
|
||||
"textwrap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"clap_lex 0.3.1",
|
||||
"is-terminal",
|
||||
"strsim",
|
||||
"termcolor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.2.18"
|
||||
@ -139,6 +161,15 @@ dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade"
|
||||
dependencies = [
|
||||
"os_str_bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "codespan-reporting"
|
||||
version = "0.11.1"
|
||||
@ -157,9 +188,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
|
||||
|
||||
[[package]]
|
||||
name = "crossterm"
|
||||
version = "0.23.2"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2102ea4f781910f8a5b98dd061f4c2023f479ce7bb1236330099ceb5a93cf17"
|
||||
checksum = "ab9f7409c70a38a56216480fba371ee460207dd8926ccf5b4160591759559170"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crossterm_winapi",
|
||||
@ -172,6 +203,22 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossterm"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crossterm_winapi",
|
||||
"libc",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossterm_winapi"
|
||||
version = "0.9.0"
|
||||
@ -193,9 +240,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxx"
|
||||
version = "1.0.82"
|
||||
version = "1.0.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453"
|
||||
checksum = "322296e2f2e5af4270b54df9e85a02ff037e271af20ba3e7fe1575515dc840b8"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cxxbridge-flags",
|
||||
@ -205,9 +252,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxx-build"
|
||||
version = "1.0.82"
|
||||
version = "1.0.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0"
|
||||
checksum = "017a1385b05d631e7875b1f151c9f012d37b53491e2a87f65bff5c262b2111d8"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"codespan-reporting",
|
||||
@ -220,15 +267,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-flags"
|
||||
version = "1.0.82"
|
||||
version = "1.0.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71"
|
||||
checksum = "c26bbb078acf09bc1ecda02d4223f03bdd28bd4874edcb0379138efc499ce971"
|
||||
|
||||
[[package]]
|
||||
name = "cxxbridge-macro"
|
||||
version = "1.0.82"
|
||||
version = "1.0.88"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470"
|
||||
checksum = "357f40d1f06a24b60ae1fe122542c1fb05d28d32acb2aed064e84bc2ad1e252e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -248,15 +295,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.8.0"
|
||||
version = "1.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
|
||||
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
|
||||
|
||||
[[package]]
|
||||
name = "elf"
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6de42b0529467fc9a2692fd91585c84dd255fb15b0df0f80299724a9456986c6"
|
||||
checksum = "2ace2c81c1832d02208b8317b90b2de5b3b4f55024b86d3f2ae800353e348fd7"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
@ -281,9 +328,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "fd-lock"
|
||||
version = "3.0.8"
|
||||
version = "3.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb21c69b9fea5e15dbc1049e4b77145dd0ba1c84019c488102de0dc4ea4b0a27"
|
||||
checksum = "28c0190ff0bd3b28bfdd4d0cf9f92faa12880fb0b8ae2054723dd6c76a4efd42"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"rustix",
|
||||
@ -298,9 +345,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||
|
||||
[[package]]
|
||||
name = "ghost"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb19fe8de3ea0920d282f7b77dd4227aea6b8b999b42cdf0ca41b2472b14443a"
|
||||
checksum = "41973d4c45f7a35af8753ba3457cc99d406d863941fd7f52663cff54a5ab99b3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -328,6 +375,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "human-repr"
|
||||
version = "1.0.1"
|
||||
@ -370,9 +426,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "inventory"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e21e0a36a4dc4b469422ee17f715e8313f4a637675656d6a13637954278c6f55"
|
||||
checksum = "16fe3b35d64bd1f72917f06425e7573a2f63f74f42c8f56e53ea6826dde3a2b5"
|
||||
dependencies = [
|
||||
"ctor",
|
||||
"ghost",
|
||||
@ -380,14 +436,26 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "io-lifetimes"
|
||||
version = "1.0.1"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7d367024b3f3414d8e01f437f704f41a9f64ab36f9067fa73e526ad4c763c87"
|
||||
checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-terminal"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
|
||||
dependencies = [
|
||||
"hermit-abi 0.2.6",
|
||||
"io-lifetimes",
|
||||
"rustix",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.5"
|
||||
@ -408,24 +476,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.137"
|
||||
version = "0.2.139"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
|
||||
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
|
||||
|
||||
[[package]]
|
||||
name = "link-cplusplus"
|
||||
version = "1.0.7"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369"
|
||||
checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.1.2"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb68f22743a3fb35785f1e7f844ca5a3de2dde5bd0c0ef5b372065814699b121"
|
||||
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
@ -453,7 +521,8 @@ dependencies = [
|
||||
"anyhow",
|
||||
"bitflags",
|
||||
"bitvec",
|
||||
"clap",
|
||||
"card_macro",
|
||||
"clap 3.2.23",
|
||||
"derive-try-from-primitive",
|
||||
"elf",
|
||||
"human-repr",
|
||||
@ -496,9 +565,9 @@ checksum = "a785740271256c230f57462d3b83e52f998433a7062fc18f96d5999474a9f915"
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.45.1"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7bca0d33a384280d1563b97f49cb95303df9fa22588739a04b7d8015c1ccd50"
|
||||
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||
dependencies = [
|
||||
"overload",
|
||||
"winapi",
|
||||
@ -531,15 +600,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.16.0"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "6.4.0"
|
||||
version = "6.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b5bf27447411e9ee3ff51186bf7a08e16c341efdde93f4d823e8844429bed7e"
|
||||
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
@ -559,9 +628,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.4"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
|
||||
checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
@ -605,18 +674,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.47"
|
||||
version = "1.0.50"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
|
||||
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.21"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@ -638,30 +707,32 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "reedline"
|
||||
version = "0.6.0"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "422f144c06f679da4ab4f082a6d1d43e28bfabb68d009100e6e5520728f99fec"
|
||||
checksum = "555a4285d183a94d140d749712a6600b10e70d7cd6aef91e3cfb65ba09b1d75e"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"crossterm",
|
||||
"crossterm 0.24.0",
|
||||
"fd-lock",
|
||||
"itertools",
|
||||
"nu-ansi-term",
|
||||
"serde",
|
||||
"strip-ansi-escapes",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"thiserror",
|
||||
"unicode-segmentation",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "reedline-repl-rs"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a82ee3209046ff272bd79fe1311ed82823102f741f3130be9dc82ef77d492b3"
|
||||
checksum = "9431c30dcf1210814a728e1ceedf8070a6589cd15d80717f313f92c4d2f73469"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"crossterm",
|
||||
"clap 4.1.4",
|
||||
"crossterm 0.25.0",
|
||||
"nu-ansi-term",
|
||||
"reedline",
|
||||
"regex",
|
||||
@ -671,9 +742,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.7.0"
|
||||
version = "1.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
|
||||
checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@ -688,9 +759,9 @@ checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.36.1"
|
||||
version = "0.36.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "812a2ec2043c4d6bc6482f5be2ab8244613cac2493d128d36c0759e52a626ab3"
|
||||
checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
@ -702,9 +773,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.9"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
|
||||
checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
@ -714,24 +785,24 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "scratch"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898"
|
||||
checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.147"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
|
||||
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.147"
|
||||
version = "1.0.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
|
||||
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -810,9 +881,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.103"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
|
||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -827,9 +898,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.3"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
|
||||
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
|
||||
dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
@ -842,18 +913,18 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.37"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
|
||||
checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.37"
|
||||
version = "1.0.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
|
||||
checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -862,9 +933,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.44"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
|
||||
checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"wasi 0.10.0+wasi-snapshot-preview1",
|
||||
@ -873,18 +944,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.9"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
|
||||
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.5"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
@ -1045,45 +1116,45 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.42.0"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
|
||||
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.42.0"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
|
||||
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.42.0"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
|
||||
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.42.0"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
|
||||
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.42.0"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
|
||||
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.42.0"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
|
||||
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.42.0"
|
||||
version = "0.42.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
|
||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
||||
|
||||
[[package]]
|
||||
name = "wyz"
|
||||
|
@ -9,6 +9,7 @@ edition = "2021"
|
||||
anyhow = "1.0.66"
|
||||
bitflags = "1.3.2"
|
||||
bitvec = "1.0.0"
|
||||
card_macro = { version = "0.1.0", path = "card_macro" }
|
||||
clap = { version = "3.2.23", features = ["clap_derive", "derive"] }
|
||||
derive-try-from-primitive = "1.0.0"
|
||||
elf = "0.7.0"
|
||||
|
749
src/main.rs
749
src/main.rs
@ -97,402 +97,401 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
return Ok(());
|
||||
}
|
||||
Repl::<_, anyhow::Error>::new(state)
|
||||
.with_name("68KEmu")
|
||||
.with_version("0.1.0")
|
||||
.with_banner("68K Backplane Computer Emulator")
|
||||
.with_description("68K Backplane Computer Emulator")
|
||||
.with_command(
|
||||
Command::new("card")
|
||||
.trailing_var_arg(true)
|
||||
.with_name("68KEmu")
|
||||
.with_version("0.1.0")
|
||||
.with_banner("68K Backplane Computer Emulator")
|
||||
.with_description("68K Backplane Computer Emulator")
|
||||
.with_command(
|
||||
Command::new("card")
|
||||
.arg(
|
||||
Arg::new("num")
|
||||
.required(true)
|
||||
.help("The card number to send the command to"),
|
||||
.required(true)
|
||||
.help("The card number to send the command to"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("cmd")
|
||||
.required(true)
|
||||
.multiple_values(true)
|
||||
.takes_value(true)
|
||||
.help("The command to send"),
|
||||
.trailing_var_arg(true)
|
||||
.num_args(1..)
|
||||
.required(true)
|
||||
.help("The command to send"),
|
||||
)
|
||||
.about("Send a command to a card"),
|
||||
|args, state| {
|
||||
let num = args.get_one::<String>("num").unwrap().parse::<u8>()?;
|
||||
state.cpu.bus_mut().card_cmd(
|
||||
num,
|
||||
&args
|
||||
|args, state| {
|
||||
let num = args.get_one::<String>("num").unwrap().parse::<u8>()?;
|
||||
state.cpu.bus_mut().card_cmd(
|
||||
num,
|
||||
&args
|
||||
.get_many::<String>("cmd")
|
||||
.unwrap()
|
||||
.map(String::as_str)
|
||||
.collect_vec(),
|
||||
)?;
|
||||
Ok(None)
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("ls").about("List the cards in the system"),
|
||||
|_, state| Ok(Some(state.cpu.bus_mut().to_string())),
|
||||
)
|
||||
.with_command(
|
||||
Command::new("regs").about("Show CPU registers"),
|
||||
|_, state| Ok(Some(format!("{}", state.cpu))),
|
||||
)
|
||||
.with_command(
|
||||
Command::new("step")
|
||||
.arg(
|
||||
Arg::new("count")
|
||||
.takes_value(true)
|
||||
.help("Count of instructions to step by. Defaults to 1"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("print_ins")
|
||||
.long("print_ins")
|
||||
.short('i')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("Print instructions"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("print_regs")
|
||||
.long("print_regs")
|
||||
.short('r')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("Print ending registers"),
|
||||
)
|
||||
.about("Step the CPU"),
|
||||
|args, state| {
|
||||
let count = parse::<u32>(args.get_one::<String>("count").map_or("1", String::as_str))?;
|
||||
let mut out = String::new();
|
||||
for _ in 0..count {
|
||||
if state.cpu.stopped {
|
||||
out += &format!("CPU stopped at PC {:#x}\n", state.cpu.pc());
|
||||
break;
|
||||
}
|
||||
if args.get_flag("print_ins") {
|
||||
let pc = state.cpu.pc();
|
||||
out += &disas_fmt(&mut state.cpu, pc, &state.symbol_tables).0;
|
||||
}
|
||||
state.cpu.step();
|
||||
}
|
||||
if args.get_flag("print_regs") {
|
||||
out += &format!("{}\n", state.cpu);
|
||||
}
|
||||
if out.is_empty() {
|
||||
)?;
|
||||
Ok(None)
|
||||
} else {
|
||||
out.pop(); // Remove trailing newline
|
||||
Ok(Some(out))
|
||||
}
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("run")
|
||||
.arg(Arg::new("stop_addr").takes_value(true).help(
|
||||
"Optional address to stop execution at. Works as a breakpoint only for this run",
|
||||
))
|
||||
.arg(
|
||||
Arg::new("print_ins")
|
||||
.long("print_ins")
|
||||
.short('p')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("Print all executed instructions"),
|
||||
},
|
||||
)
|
||||
.about("Run the CPU"),
|
||||
|args, state| {
|
||||
let mut out = String::new();
|
||||
while !state.cpu.stopped {
|
||||
let stop_addr = args
|
||||
.get_one::<String>("stop_addr")
|
||||
.map(|s| state.symbol_tables.parse_location_address(s))
|
||||
.transpose()?;
|
||||
if stop_addr.map_or(false, |a| state.cpu.pc() == a)
|
||||
|| state.symbol_tables.breakpoint_set_at(state.cpu.pc())
|
||||
|| state.address_breakpoints.contains(&state.cpu.pc())
|
||||
{
|
||||
break;
|
||||
}
|
||||
if args.get_flag("print_ins") {
|
||||
let pc = state.cpu.pc();
|
||||
out += &disas_fmt(&mut state.cpu, pc, &state.symbol_tables).0;
|
||||
}
|
||||
state.cpu.step();
|
||||
}
|
||||
out += &format!("{}\n", state.cpu);
|
||||
let pc = state.cpu.pc();
|
||||
out += &disas_fmt(&mut state.cpu, pc, &state.symbol_tables).0;
|
||||
out.pop(); // Remove trailing newline
|
||||
Ok(Some(out))
|
||||
},
|
||||
.with_command(
|
||||
Command::new("ls").about("List the cards in the system"),
|
||||
|_, state| Ok(Some(state.cpu.bus_mut().to_string())),
|
||||
)
|
||||
.with_command(
|
||||
Command::new("regs").about("Show CPU registers"),
|
||||
|_, state| Ok(Some(format!("{}", state.cpu))),
|
||||
)
|
||||
.with_command(
|
||||
Command::new("step")
|
||||
.arg(
|
||||
Arg::new("count")
|
||||
|
||||
.help("Count of instructions to step by. Defaults to 1"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("print_ins")
|
||||
.long("print_ins")
|
||||
.short('i')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("Print instructions"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("print_regs")
|
||||
.long("print_regs")
|
||||
.short('r')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("Print ending registers"),
|
||||
)
|
||||
.about("Step the CPU"),
|
||||
|args, state| {
|
||||
let count = parse::<u32>(args.get_one::<String>("count").map_or("1", String::as_str))?;
|
||||
let mut out = String::new();
|
||||
for _ in 0..count {
|
||||
if state.cpu.stopped {
|
||||
out += &format!("CPU stopped at PC {:#x}\n", state.cpu.pc());
|
||||
break;
|
||||
}
|
||||
if args.get_flag("print_ins") {
|
||||
let pc = state.cpu.pc();
|
||||
out += &disas_fmt(&mut state.cpu, pc, &state.symbol_tables).0;
|
||||
}
|
||||
state.cpu.step();
|
||||
}
|
||||
if args.get_flag("print_regs") {
|
||||
out += &format!("{}\n", state.cpu);
|
||||
}
|
||||
if out.is_empty() {
|
||||
Ok(None)
|
||||
} else {
|
||||
out.pop(); // Remove trailing newline
|
||||
Ok(Some(out))
|
||||
}
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("run")
|
||||
.arg(Arg::new("stop_addr").help(
|
||||
"Optional address to stop execution at. Works as a breakpoint only for this run",
|
||||
))
|
||||
.arg(
|
||||
Arg::new("print_ins")
|
||||
.long("print_ins")
|
||||
.short('p')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("Print all executed instructions"),
|
||||
)
|
||||
.about("Run the CPU"),
|
||||
|args, state| {
|
||||
let mut out = String::new();
|
||||
while !state.cpu.stopped {
|
||||
let stop_addr = args
|
||||
.get_one::<String>("stop_addr")
|
||||
.map(|s| state.symbol_tables.parse_location_address(s))
|
||||
.transpose()?;
|
||||
if stop_addr.map_or(false, |a| state.cpu.pc() == a)
|
||||
|| state.symbol_tables.breakpoint_set_at(state.cpu.pc())
|
||||
|| state.address_breakpoints.contains(&state.cpu.pc())
|
||||
{
|
||||
break;
|
||||
}
|
||||
if args.get_flag("print_ins") {
|
||||
let pc = state.cpu.pc();
|
||||
out += &disas_fmt(&mut state.cpu, pc, &state.symbol_tables).0;
|
||||
}
|
||||
state.cpu.step();
|
||||
}
|
||||
out += &format!("{}\n", state.cpu);
|
||||
let pc = state.cpu.pc();
|
||||
out += &disas_fmt(&mut state.cpu, pc, &state.symbol_tables).0;
|
||||
out.pop(); // Remove trailing newline
|
||||
Ok(Some(out))
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("reset").about("Reset the cards and CPU, in that order"),
|
||||
|_, state| {
|
||||
state.cpu.bus_mut().reset();
|
||||
state.cpu.reset();
|
||||
Ok(None)
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("peek")
|
||||
.arg(
|
||||
Arg::new("count")
|
||||
.short('c')
|
||||
|
||||
.help("The count of values to print"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("fmt")
|
||||
.short('f')
|
||||
|
||||
.help("The format to print the values in (<fmt><size>)"),
|
||||
)
|
||||
.arg(Arg::new("addr").required(true))
|
||||
.about("Peek a memory address"),
|
||||
|args, state| {
|
||||
let (fmt, size) = if let Some(fmt_str) = args.get_one::<String>("fmt") {
|
||||
if fmt_str.len() != 2 {
|
||||
return Err(anyhow!("Peek format length must be 2"));
|
||||
}
|
||||
let fmt = peek::Format::try_from(fmt_str.chars().next().unwrap())?;
|
||||
let size = peek::Size::try_from(fmt_str.chars().nth(1).unwrap())?;
|
||||
state.last_peek_format = (fmt, size);
|
||||
(fmt, size)
|
||||
} else {
|
||||
state.last_peek_format
|
||||
};
|
||||
let count = parse::<u32>(args.get_one::<String>("count").map_or("1", String::as_str))?;
|
||||
let addr = state
|
||||
.symbol_tables
|
||||
.parse_location_address(args.get_one::<String>("addr").unwrap())?;
|
||||
if (size != peek::Size::Byte) & ((addr & 0x1) != 0) {
|
||||
return Err(anyhow!("Cannot peek words from a non-aligned address"));
|
||||
}
|
||||
let mut data = Vec::new();
|
||||
let bus = state.cpu.bus_mut();
|
||||
for i in 0..count {
|
||||
match size {
|
||||
peek::Size::Byte => data.push(bus.read_byte(addr + i)? as u32),
|
||||
peek::Size::Word => data.push(bus.read_word(addr + (i * 2))? as u32),
|
||||
peek::Size::LongWord => data.push(
|
||||
(bus.read_word(addr + (i * 4))? as u32) << 16
|
||||
| (bus.read_word(addr + (i * 4) + 2)? as u32),
|
||||
),
|
||||
}
|
||||
}
|
||||
Ok(Some(
|
||||
data.chunks(size.chunk_size())
|
||||
.enumerate()
|
||||
.map(|(i, c)| {
|
||||
format!(
|
||||
"0x{:x}: ",
|
||||
addr + (size.chunk_size() * size.byte_count() * i) as u32
|
||||
) + &c.iter().map(|d| fmt.format(*d, size)).join(" ")
|
||||
})
|
||||
.join("\n"),
|
||||
))
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("poke")
|
||||
.arg(Arg::new("address").help("The address to write to").required(true))
|
||||
.arg(Arg::new("data").help("The data to write").required(true))
|
||||
.arg(
|
||||
Arg::new("word")
|
||||
.long("word")
|
||||
.short('w')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("Write a word instead of a byte"),
|
||||
)
|
||||
.about("Write to a memory address"),
|
||||
|args, state| {
|
||||
let address = parse::<u32>(args.get_one::<String>("address").unwrap())?;
|
||||
if args.get_flag("word") {
|
||||
if (address & 0x1) != 0 {
|
||||
return Err(anyhow!("Cannot poke a word to a non-aligned address"));
|
||||
}
|
||||
let data = parse::<u16>(args.get_one::<String>("data").unwrap())?;
|
||||
state.cpu.bus_mut().write_word(address, data)?;
|
||||
} else {
|
||||
let data = parse::<u8>(args.get_one::<String>("data").unwrap())?;
|
||||
state.cpu.bus_mut().write_byte(address, data as u8)?;
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
)
|
||||
.with_command(
|
||||
Command::new("reset").about("Reset the cards and CPU, in that order"),
|
||||
|_, state| {
|
||||
state.cpu.bus_mut().reset();
|
||||
state.cpu.reset();
|
||||
Ok(None)
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("peek")
|
||||
.arg(
|
||||
Arg::new("count")
|
||||
.short('c')
|
||||
.takes_value(true)
|
||||
.help("The count of values to print"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("fmt")
|
||||
.short('f')
|
||||
.takes_value(true)
|
||||
.help("The format to print the values in (<fmt><size>)"),
|
||||
)
|
||||
.arg(Arg::new("addr").required(true))
|
||||
.about("Peek a memory address"),
|
||||
|args, state| {
|
||||
let (fmt, size) = if let Some(fmt_str) = args.get_one::<String>("fmt") {
|
||||
if fmt_str.len() != 2 {
|
||||
return Err(anyhow!("Peek format length must be 2"));
|
||||
}
|
||||
let fmt = peek::Format::try_from(fmt_str.chars().next().unwrap())?;
|
||||
let size = peek::Size::try_from(fmt_str.chars().nth(1).unwrap())?;
|
||||
state.last_peek_format = (fmt, size);
|
||||
(fmt, size)
|
||||
} else {
|
||||
state.last_peek_format
|
||||
};
|
||||
let count = parse::<u32>(args.get_one::<String>("count").map_or("1", String::as_str))?;
|
||||
let addr = state
|
||||
.symbol_tables
|
||||
.parse_location_address(args.get_one::<String>("addr").unwrap())?;
|
||||
if (size != peek::Size::Byte) & ((addr & 0x1) != 0) {
|
||||
return Err(anyhow!("Cannot peek words from a non-aligned address"));
|
||||
}
|
||||
let mut data = Vec::new();
|
||||
let bus = state.cpu.bus_mut();
|
||||
for i in 0..count {
|
||||
match size {
|
||||
peek::Size::Byte => data.push(bus.read_byte(addr + i)? as u32),
|
||||
peek::Size::Word => data.push(bus.read_word(addr + (i * 2))? as u32),
|
||||
peek::Size::LongWord => data.push(
|
||||
(bus.read_word(addr + (i * 4))? as u32) << 16
|
||||
| (bus.read_word(addr + (i * 4) + 2)? as u32),
|
||||
),
|
||||
}
|
||||
}
|
||||
Ok(Some(
|
||||
data.chunks(size.chunk_size())
|
||||
.enumerate()
|
||||
.map(|(i, c)| {
|
||||
format!(
|
||||
"0x{:x}: ",
|
||||
addr + (size.chunk_size() * size.byte_count() * i) as u32
|
||||
) + &c.iter().map(|d| fmt.format(*d, size)).join(" ")
|
||||
})
|
||||
.join("\n"),
|
||||
))
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("poke")
|
||||
.arg(Arg::new("address").help("The address to write to").required(true))
|
||||
.arg(Arg::new("data").help("The data to write").required(true))
|
||||
.arg(
|
||||
Arg::new("word")
|
||||
.long("word")
|
||||
.short('w')
|
||||
.action(ArgAction::SetTrue)
|
||||
.help("Write a word instead of a byte"),
|
||||
)
|
||||
.about("Write to a memory address"),
|
||||
|args, state| {
|
||||
let address = parse::<u32>(args.get_one::<String>("address").unwrap())?;
|
||||
if args.get_flag("word") {
|
||||
if (address & 0x1) != 0 {
|
||||
return Err(anyhow!("Cannot poke a word to a non-aligned address"));
|
||||
}
|
||||
let data = parse::<u16>(args.get_one::<String>("data").unwrap())?;
|
||||
state.cpu.bus_mut().write_word(address, data)?;
|
||||
} else {
|
||||
let data = parse::<u8>(args.get_one::<String>("data").unwrap())?;
|
||||
state.cpu.bus_mut().write_byte(address, data as u8)?;
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
)
|
||||
.with_command(
|
||||
Command::new("disas")
|
||||
.with_command(
|
||||
Command::new("disas")
|
||||
.arg(Arg::new("addr").help("Address to start disassembly at. Defaults to current PC"))
|
||||
.arg(
|
||||
Arg::new("count")
|
||||
.short('c')
|
||||
.takes_value(true)
|
||||
.help("Count of instructions to disassemble. Defaults to 1"),
|
||||
.short('c')
|
||||
|
||||
.help("Count of instructions to disassemble. Defaults to 1"),
|
||||
)
|
||||
.about("Disassemble a region of memory"),
|
||||
|args, state| {
|
||||
let mut addr = args
|
||||
.get_one::<String>("addr")
|
||||
.map_or(Ok(state.cpu.pc()), |s| {
|
||||
state.symbol_tables.parse_location_address(s)
|
||||
})?;
|
||||
let count = parse::<u32>(args.get_one::<String>("count").map_or("1", String::as_str))?;
|
||||
let mut out = String::new();
|
||||
for _ in 0..count {
|
||||
let (fmt, res) = disas_fmt(&mut state.cpu, addr, &state.symbol_tables);
|
||||
out += &fmt;
|
||||
match res {
|
||||
Ok(new_addr) => {
|
||||
addr = new_addr;
|
||||
}
|
||||
Err(_) => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
out.pop(); // Remove trailing newline
|
||||
Ok(Some(out))
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("sym")
|
||||
.arg(Arg::new("file").help("The ELF file to load symbols from"))
|
||||
.arg(
|
||||
Arg::new("append")
|
||||
.long("append")
|
||||
.short('a')
|
||||
.action(ArgAction::SetTrue)
|
||||
.requires("file")
|
||||
.conflicts_with_all(&["delete", "set-active"])
|
||||
.help("Append the file's symbols to the loaded list of symbols"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("delete")
|
||||
.long("delete")
|
||||
.short('d')
|
||||
.action(ArgAction::SetTrue)
|
||||
.requires("file")
|
||||
.conflicts_with_all(&["append", "set-active"])
|
||||
.help("Delete the symbol table instead of loading it"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("set-active")
|
||||
.long("set-active")
|
||||
.short('c')
|
||||
.takes_value(true)
|
||||
.value_parser(BoolishValueParser::new())
|
||||
.requires("file")
|
||||
.conflicts_with_all(&["append", "delete"])
|
||||
.help("Set whether the symbol table is active or not"),
|
||||
)
|
||||
.about("Load symbols from an ELF file, or list symbols if no file provided"),
|
||||
|args, state| {
|
||||
if let Some(file_path) = args.get_one::<String>("file") {
|
||||
let table_name = Path::new(&file_path).file_name().unwrap().to_str().unwrap();
|
||||
if args.get_flag("delete") {
|
||||
state.symbol_tables.delete(table_name)?;
|
||||
} else if let Some(&active) = args.get_one::<bool>("set-active") {
|
||||
state.symbol_tables.set_active(table_name, active)?;
|
||||
} else {
|
||||
state
|
||||
.symbol_tables
|
||||
.load_table(file_path, args.get_flag("append"))?;
|
||||
}
|
||||
Ok(None)
|
||||
} else if state.symbol_tables.is_empty() {
|
||||
Ok(Some("No symbols".to_string()))
|
||||
} else {
|
||||
Ok(Some(format!("{}", state.symbol_tables.symbol_displayer())))
|
||||
}
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("resolve")
|
||||
.arg(
|
||||
Arg::new("location")
|
||||
.help("The location to resolve")
|
||||
.required(true),
|
||||
)
|
||||
.about("Resolve a location to an address"),
|
||||
|args, state| {
|
||||
let location = args.get_one::<String>("location").unwrap();
|
||||
Ok(Some(format!(
|
||||
"{}",
|
||||
state
|
||||
.symbol_tables
|
||||
.parse_location(location)?
|
||||
.displayer(&state.symbol_tables)
|
||||
)))
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("bp")
|
||||
.arg(Arg::new("location").help("The location to set a breakpoint at"))
|
||||
.arg(
|
||||
Arg::new("delete")
|
||||
.long("delete")
|
||||
.short('d')
|
||||
.action(ArgAction::SetTrue)
|
||||
.requires("location")
|
||||
.help("Delete the breakpoint instead of setting it"),
|
||||
)
|
||||
.about("Set a breakpoint or list current breakpoints"),
|
||||
|args, state| {
|
||||
if let Some(location) = args.get_one::<String>("location") {
|
||||
let location = state.symbol_tables.parse_location(location)?;
|
||||
if args.get_flag("delete") {
|
||||
let deleted = match location {
|
||||
Location::Symbol((table, symbol)) => {
|
||||
state.symbol_tables.delete_breakpoint(&table, &symbol)?
|
||||
}
|
||||
Location::Address(address) => {
|
||||
state.address_breakpoints.shift_remove(&address)
|
||||
}
|
||||
};
|
||||
if deleted {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some("No such breakpoint".to_string()))
|
||||
}
|
||||
} else {
|
||||
match location {
|
||||
Location::Symbol((table, symbol)) => {
|
||||
state.symbol_tables.set_breakpoint(&table, symbol)?;
|
||||
}
|
||||
Location::Address(address) => {
|
||||
state.address_breakpoints.insert(address);
|
||||
}
|
||||
};
|
||||
Ok(None)
|
||||
}
|
||||
} else {
|
||||
|args, state| {
|
||||
let mut addr = args
|
||||
.get_one::<String>("addr")
|
||||
.map_or(Ok(state.cpu.pc()), |s| {
|
||||
state.symbol_tables.parse_location_address(s)
|
||||
})?;
|
||||
let count = parse::<u32>(args.get_one::<String>("count").map_or("1", String::as_str))?;
|
||||
let mut out = String::new();
|
||||
out += &format!("{}", state.symbol_tables.breakpoint_displayer());
|
||||
if !state.address_breakpoints.is_empty() {
|
||||
if !out.is_empty() {
|
||||
out += "\n";
|
||||
}
|
||||
out += "Address breakpoints:\n";
|
||||
out += &format!("{}", state.address_breakpoints.iter().format("\n"));
|
||||
for _ in 0..count {
|
||||
let (fmt, res) = disas_fmt(&mut state.cpu, addr, &state.symbol_tables);
|
||||
out += &fmt;
|
||||
match res {
|
||||
Ok(new_addr) => {
|
||||
addr = new_addr;
|
||||
}
|
||||
Err(_) => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if out.is_empty() {
|
||||
Ok(Some("No breakpoints".to_string()))
|
||||
} else {
|
||||
Ok(Some(out))
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("quit")
|
||||
.visible_alias("q")
|
||||
.visible_alias("exit")
|
||||
.about("Quit"),
|
||||
|_, _| process::exit(0),
|
||||
)
|
||||
// Visible aliases don't actually work, so fake it with hidden subcommands
|
||||
.with_command(Command::new("q").hide(true), |_, _| process::exit(0))
|
||||
.with_command(Command::new("exit").hide(true), |_, _| process::exit(0))
|
||||
.run()?;
|
||||
out.pop(); // Remove trailing newline
|
||||
Ok(Some(out))
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("sym")
|
||||
.arg(Arg::new("file").help("The ELF file to load symbols from"))
|
||||
.arg(
|
||||
Arg::new("append")
|
||||
.long("append")
|
||||
.short('a')
|
||||
.action(ArgAction::SetTrue)
|
||||
.requires("file")
|
||||
.conflicts_with_all(&["delete", "set-active"])
|
||||
.help("Append the file's symbols to the loaded list of symbols"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("delete")
|
||||
.long("delete")
|
||||
.short('d')
|
||||
.action(ArgAction::SetTrue)
|
||||
.requires("file")
|
||||
.conflicts_with_all(&["append", "set-active"])
|
||||
.help("Delete the symbol table instead of loading it"),
|
||||
)
|
||||
.arg(
|
||||
Arg::new("set-active")
|
||||
.long("set-active")
|
||||
.short('c')
|
||||
|
||||
.value_parser(BoolishValueParser::new())
|
||||
.requires("file")
|
||||
.conflicts_with_all(&["append", "delete"])
|
||||
.help("Set whether the symbol table is active or not"),
|
||||
)
|
||||
.about("Load symbols from an ELF file, or list symbols if no file provided"),
|
||||
|args, state| {
|
||||
if let Some(file_path) = args.get_one::<String>("file") {
|
||||
let table_name = Path::new(&file_path).file_name().unwrap().to_str().unwrap();
|
||||
if args.get_flag("delete") {
|
||||
state.symbol_tables.delete(table_name)?;
|
||||
} else if let Some(&active) = args.get_one::<bool>("set-active") {
|
||||
state.symbol_tables.set_active(table_name, active)?;
|
||||
} else {
|
||||
state
|
||||
.symbol_tables
|
||||
.load_table(file_path, args.get_flag("append"))?;
|
||||
}
|
||||
Ok(None)
|
||||
} else if state.symbol_tables.is_empty() {
|
||||
Ok(Some("No symbols".to_string()))
|
||||
} else {
|
||||
Ok(Some(format!("{}", state.symbol_tables.symbol_displayer())))
|
||||
}
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("resolve")
|
||||
.arg(
|
||||
Arg::new("location")
|
||||
.help("The location to resolve")
|
||||
.required(true),
|
||||
)
|
||||
.about("Resolve a location to an address"),
|
||||
|args, state| {
|
||||
let location = args.get_one::<String>("location").unwrap();
|
||||
Ok(Some(format!(
|
||||
"{}",
|
||||
state
|
||||
.symbol_tables
|
||||
.parse_location(location)?
|
||||
.displayer(&state.symbol_tables)
|
||||
)))
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("bp")
|
||||
.arg(Arg::new("location").help("The location to set a breakpoint at"))
|
||||
.arg(
|
||||
Arg::new("delete")
|
||||
.long("delete")
|
||||
.short('d')
|
||||
.action(ArgAction::SetTrue)
|
||||
.requires("location")
|
||||
.help("Delete the breakpoint instead of setting it"),
|
||||
)
|
||||
.about("Set a breakpoint or list current breakpoints"),
|
||||
|args, state| {
|
||||
if let Some(location) = args.get_one::<String>("location") {
|
||||
let location = state.symbol_tables.parse_location(location)?;
|
||||
if args.get_flag("delete") {
|
||||
let deleted = match location {
|
||||
Location::Symbol((table, symbol)) => {
|
||||
state.symbol_tables.delete_breakpoint(&table, &symbol)?
|
||||
}
|
||||
Location::Address(address) => {
|
||||
state.address_breakpoints.shift_remove(&address)
|
||||
}
|
||||
};
|
||||
if deleted {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some("No such breakpoint".to_string()))
|
||||
}
|
||||
} else {
|
||||
match location {
|
||||
Location::Symbol((table, symbol)) => {
|
||||
state.symbol_tables.set_breakpoint(&table, symbol)?;
|
||||
}
|
||||
Location::Address(address) => {
|
||||
state.address_breakpoints.insert(address);
|
||||
}
|
||||
};
|
||||
Ok(None)
|
||||
}
|
||||
} else {
|
||||
let mut out = String::new();
|
||||
out += &format!("{}", state.symbol_tables.breakpoint_displayer());
|
||||
if !state.address_breakpoints.is_empty() {
|
||||
if !out.is_empty() {
|
||||
out += "\n";
|
||||
}
|
||||
out += "Address breakpoints:\n";
|
||||
out += &format!("{}", state.address_breakpoints.iter().format("\n"));
|
||||
}
|
||||
if out.is_empty() {
|
||||
Ok(Some("No breakpoints".to_string()))
|
||||
} else {
|
||||
Ok(Some(out))
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
.with_command(
|
||||
Command::new("quit")
|
||||
.visible_alias("q")
|
||||
.visible_alias("exit")
|
||||
.about("Quit"),
|
||||
|_, _| process::exit(0),
|
||||
)
|
||||
// Visible aliases don't actually work, so fake it with hidden subcommands
|
||||
.with_command(Command::new("q").hide(true), |_, _| process::exit(0))
|
||||
.with_command(Command::new("exit").hide(true), |_, _| process::exit(0))
|
||||
.run()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
147
src/mmu.rs
147
src/mmu.rs
@ -4,7 +4,7 @@ use nullable_result::NullableResult;
|
||||
|
||||
use crate::{
|
||||
backplane::{Backplane, CardAccessorBuilder, DMAHandler, MMUHandler},
|
||||
card::{u16_get_be_byte, Card},
|
||||
card::{u16_get_be_byte, u32_get_be_byte, u32_set_be_byte, Card},
|
||||
m68k::BusError,
|
||||
register,
|
||||
};
|
||||
@ -35,7 +35,10 @@ impl From<u32> for PagingEntry {
|
||||
pub struct MmuCard {
|
||||
enabled: bool,
|
||||
cache: [Option<PagingEntry>; 4096],
|
||||
map_frames: [Option<u32>; 4],
|
||||
map_frames: [u32; 4],
|
||||
map_frames_enabled: [bool; 4],
|
||||
tlb_clear_entry: u16,
|
||||
print_debug: bool,
|
||||
}
|
||||
|
||||
impl Card for MmuCard {
|
||||
@ -44,7 +47,10 @@ impl Card for MmuCard {
|
||||
Self {
|
||||
enabled: false,
|
||||
cache: [None; 4096],
|
||||
map_frames: [None; 4],
|
||||
map_frames: [0; 4],
|
||||
map_frames_enabled: [false; 4],
|
||||
tlb_clear_entry: 0,
|
||||
print_debug: false,
|
||||
},
|
||||
None,
|
||||
))
|
||||
@ -56,14 +62,78 @@ impl Card for MmuCard {
|
||||
|
||||
fn read_byte_io(&mut self, address: u8) -> NullableResult<u8, BusError> {
|
||||
match address {
|
||||
(0x0..=0xF) => {
|
||||
let map_no = (address / 4) as usize;
|
||||
let offset = address % 4;
|
||||
match offset {
|
||||
(0..=2) => NullableResult::Ok(u32_get_be_byte(self.map_frames[map_no], offset)),
|
||||
3 => NullableResult::Ok(self.map_frames_enabled[map_no] as u8),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
(0xFE..=0xFF) => NullableResult::Ok(u16_get_be_byte(ID, address - 0xFE)),
|
||||
_ => NullableResult::Null,
|
||||
}
|
||||
}
|
||||
|
||||
fn write_byte_io(&mut self, address: u8, data: u8) -> NullableResult<(), BusError> {
|
||||
match address {
|
||||
(0x0..=0xF) => {
|
||||
let map_no = (address / 4) as usize;
|
||||
let offset = address % 4;
|
||||
match offset {
|
||||
(0..=1) => {
|
||||
self.map_frames[map_no] =
|
||||
u32_set_be_byte(self.map_frames[map_no], offset, data);
|
||||
}
|
||||
2 => {
|
||||
self.map_frames[map_no] =
|
||||
u32_set_be_byte(self.map_frames[map_no], offset, data & 0xf0);
|
||||
}
|
||||
3 => {
|
||||
self.map_frames_enabled[map_no] = (data & 0x1) > 0;
|
||||
for i in map_no * 1024..(map_no + 1) * 1024 {
|
||||
self.cache[i] = None;
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
}
|
||||
(0x10..=0x13) => {
|
||||
let offset = (address - 0x10) % 4;
|
||||
match offset {
|
||||
0 => (),
|
||||
1 => {
|
||||
self.tlb_clear_entry = (self.tlb_clear_entry & 0xF) | ((data as u16) << 4);
|
||||
}
|
||||
2 => {
|
||||
self.tlb_clear_entry =
|
||||
(self.tlb_clear_entry & 0xFF0) | (((data as u16) & 0xF0) >> 4);
|
||||
}
|
||||
3 => {
|
||||
if self.print_debug {
|
||||
println!(
|
||||
"Clearing TLB entry {:#x} ( page start {:#x} )",
|
||||
self.tlb_clear_entry,
|
||||
(self.tlb_clear_entry as u32) << 12
|
||||
);
|
||||
}
|
||||
self.cache[self.tlb_clear_entry as usize] = None;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
0x15 => {
|
||||
self.enabled = (data & 0x1) > 0;
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
NullableResult::Ok(())
|
||||
}
|
||||
|
||||
fn cmd(&mut self, cmd: &[&str]) -> anyhow::Result<()> {
|
||||
if cmd[0] == "enable" && cmd.len() >= 2 {
|
||||
self.enabled = cmd[1].parse()?;
|
||||
if cmd[0] == "debug" && cmd.len() >= 2 {
|
||||
self.print_debug = cmd[1].parse()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -75,9 +145,33 @@ impl Card for MmuCard {
|
||||
|
||||
impl Display for MmuCard {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let q1 = if self.map_frames_enabled[0] {
|
||||
Some(self.map_frames[0])
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let q2 = if self.map_frames_enabled[1] {
|
||||
Some(self.map_frames[1])
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let q3 = if self.map_frames_enabled[2] {
|
||||
Some(self.map_frames[2])
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let q4 = if self.map_frames_enabled[3] {
|
||||
Some(self.map_frames[3])
|
||||
} else {
|
||||
None
|
||||
};
|
||||
f.write_fmt(format_args!(
|
||||
"MMU card, {}",
|
||||
"MMU card, {} (Q1: {:?}, Q2: {:?}, Q3: {:?}, Q4: {:?})",
|
||||
if self.enabled { "enabled" } else { "disabled" },
|
||||
q1,
|
||||
q2,
|
||||
q3,
|
||||
q4
|
||||
))
|
||||
}
|
||||
}
|
||||
@ -94,26 +188,59 @@ impl MMUHandler for Mmu {
|
||||
write: bool,
|
||||
) -> NullableResult<u32, BusError> {
|
||||
let card_accessor = card_accessor.build::<MmuCard>();
|
||||
if card_accessor.get().enabled {
|
||||
let card = card_accessor.get();
|
||||
let print_debug = card.print_debug;
|
||||
if card.enabled {
|
||||
let page = address >> 12;
|
||||
let offset = address & 0xFFF;
|
||||
let entry = if let Some(entry) = card_accessor.get().cache[page as usize] {
|
||||
let entry = if let Some(entry) = card.cache[page as usize] {
|
||||
if print_debug {
|
||||
println!("TLB hit");
|
||||
}
|
||||
entry
|
||||
} else {
|
||||
let map_frame = card_accessor.get().map_frames[(page >> 10) as usize]?;
|
||||
let entry_address = (map_frame << 12) | ((page & 0x3FF) << 2);
|
||||
if print_debug {
|
||||
println!("TLB miss, fetching entry");
|
||||
}
|
||||
if card.map_frames_enabled[(page >> 10) as usize] == false {
|
||||
if print_debug {
|
||||
println!("No mapping frame for this quarter");
|
||||
}
|
||||
return NullableResult::Null;
|
||||
}
|
||||
let map_frame = card.map_frames[(page >> 10) as usize];
|
||||
let entry_address = (map_frame) | ((page & 0x3FF) << 2);
|
||||
if print_debug {
|
||||
println!("Entry is at {:#x}", entry_address);
|
||||
}
|
||||
drop(card);
|
||||
let entry_hi = backplane.read_word_phys(entry_address)?;
|
||||
let entry_lo = backplane.read_word_phys(entry_address + 2)?;
|
||||
let entry = PagingEntry::from((entry_hi as u32) << 16 | entry_lo as u32);
|
||||
card_accessor.get().cache[page as usize] = Some(entry);
|
||||
if print_debug {
|
||||
println!("Fetched entry {:#?}", entry);
|
||||
}
|
||||
entry
|
||||
};
|
||||
if entry.present {
|
||||
if write && !entry.writable {
|
||||
if print_debug {
|
||||
println!("Entry not writable");
|
||||
}
|
||||
return NullableResult::Err(BusError);
|
||||
}
|
||||
if print_debug {
|
||||
println!(
|
||||
"Translation success, translated to {:#x}",
|
||||
(entry.frame << 12) | offset
|
||||
);
|
||||
}
|
||||
NullableResult::Ok((entry.frame << 12) | offset)
|
||||
} else {
|
||||
if print_debug {
|
||||
println!("Entry not present");
|
||||
}
|
||||
NullableResult::Null
|
||||
}
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user