Compare commits

...

4 Commits

  1. 590
      Cargo.lock
  2. 1
      Cargo.toml
  3. 6
      crsn/src/asm/data/mod.rs
  4. 5
      crsn/src/asm/data/rd.rs
  5. 4
      crsn/src/asm/data/reg.rs
  6. 4
      crsn/src/asm/data/wr.rs
  7. 2
      crsn/src/asm/error.rs
  8. 6
      crsn/src/asm/instr/cond.rs
  9. 16
      crsn/src/asm/instr/flatten.rs
  10. 2
      crsn/src/asm/instr/op.rs
  11. 4
      crsn/src/asm/mod.rs
  12. 2
      crsn/src/asm/parse/arg_parser.rs
  13. 4
      crsn/src/asm/parse/mod.rs
  14. 6
      crsn/src/asm/parse/parse_cond.rs
  15. 12
      crsn/src/asm/parse/parse_data.rs
  16. 4
      crsn/src/asm/parse/parse_instr.rs
  17. 6
      crsn/src/asm/parse/parse_op.rs
  18. 4
      crsn/src/asm/parse/parse_routines.rs
  19. 20
      crsn/src/asm/parse/sexp_expect.rs
  20. 2
      crsn/src/builtin/defs.rs
  21. 6
      crsn/src/builtin/exec.rs
  22. 5
      crsn/src/builtin/parse.rs
  23. 29
      crsn/src/module/mod.rs
  24. 4
      crsn/src/runtime/fault.rs
  25. 6
      crsn/src/runtime/program.rs
  26. 27
      crsn/src/runtime/run_thread.rs
  27. 9
      crsn/src/runtime/run_thread/info.rs
  28. 2
      crsn/src/runtime/run_thread/state.rs
  29. 23
      crsn_arith/src/lib.rs
  30. 738
      crsn_arith/src/parse.rs
  31. 13
      crsn_screen/Cargo.toml
  32. 14
      crsn_screen/src/defs.rs
  33. 99
      crsn_screen/src/exec.rs
  34. 30
      crsn_screen/src/lib.rs
  35. 30
      crsn_screen/src/parse.rs
  36. 2
      crsn_stacks/src/defs.rs
  37. 7
      crsn_stacks/src/exec.rs
  38. 30
      crsn_stacks/src/lib.rs
  39. 72
      crsn_stacks/src/parse.rs
  40. 1
      launcher/Cargo.toml
  41. 58
      launcher/src/main.rs

590
Cargo.lock generated

@ -17,12 +17,30 @@ dependencies = [
"winapi",
]
[[package]]
name = "autocfg"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "cc"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c"
[[package]]
name = "cfg-if"
version = "0.1.10"
@ -40,6 +58,24 @@ dependencies = [
"time",
]
[[package]]
name = "cloudabi"
version = "0.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
dependencies = [
"bitflags",
]
[[package]]
name = "cloudabi"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467"
dependencies = [
"bitflags",
]
[[package]]
name = "colored"
version = "1.9.3"
@ -71,6 +107,16 @@ dependencies = [
"num-traits",
]
[[package]]
name = "crsn_screen"
version = "0.1.0"
dependencies = [
"crsn",
"log",
"minifb",
"parking_lot",
]
[[package]]
name = "crsn_stacks"
version = "0.1.0"
@ -78,6 +124,12 @@ dependencies = [
"crsn",
]
[[package]]
name = "downcast-rs"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]]
name = "dyn-clonable"
version = "0.9.0"
@ -105,6 +157,23 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c53dc3a653e0f64081026e4bf048d48fec9fce90c66e8326ca7292df0ff2d82"
[[package]]
name = "fuchsia-cprng"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
[[package]]
name = "getrandom"
version = "0.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6"
dependencies = [
"cfg-if",
"libc",
"wasi 0.9.0+wasi-snapshot-preview1",
]
[[package]]
name = "hermit-abi"
version = "0.1.16"
@ -114,6 +183,15 @@ dependencies = [
"libc",
]
[[package]]
name = "instant"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63312a18f7ea8760cdd0a7c5aac1a619752a246b833545e3e36d1f81f7cd9e66"
dependencies = [
"cfg-if",
]
[[package]]
name = "launcher"
version = "0.1.0"
@ -121,6 +199,7 @@ dependencies = [
"anyhow",
"crsn",
"crsn_arith",
"crsn_screen",
"crsn_stacks",
"log",
"simple_logger",
@ -139,6 +218,15 @@ version = "0.2.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
[[package]]
name = "lock_api"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28247cc5a5be2f05fbcd76dd0cf2c7d3b5400cb978a28042abcd4fa0b3f8261c"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.11"
@ -148,13 +236,89 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
[[package]]
name = "memchr"
version = "2.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
[[package]]
name = "minifb"
version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eb411a297b8f714800f085846cbda55fbd2ae17ecd381f1b4652af0e5bebe63"
dependencies = [
"cc",
"orbclient",
"raw-window-handle",
"tempfile",
"wayland-client",
"wayland-cursor",
"wayland-protocols",
"winapi",
"x11-dl",
"xkb",
"xkbcommon-sys",
]
[[package]]
name = "nix"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
dependencies = [
"bitflags",
"cc",
"cfg-if",
"libc",
"void",
]
[[package]]
name = "nom"
version = "5.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
dependencies = [
"memchr",
"version_check",
]
[[package]]
name = "num"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e"
dependencies = [
"num-integer",
"num-iter",
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
dependencies = [
"autocfg",
"autocfg 1.0.1",
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f"
dependencies = [
"autocfg 1.0.1",
"num-integer",
"num-traits",
]
@ -164,9 +328,63 @@ version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
dependencies = [
"autocfg",
"autocfg 1.0.1",
]
[[package]]
name = "once_cell"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
[[package]]
name = "orbclient"
version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8b18f57ab94fbd058e30aa57f712ec423c0bb7403f8493a6c58eef0c36d9402"
dependencies = [
"redox_syscall",
"sdl2",
]
[[package]]
name = "parking_lot"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733"
dependencies = [
"instant",
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
dependencies = [
"cfg-if",
"cloudabi 0.1.0",
"instant",
"libc",
"redox_syscall",
"smallvec",
"winapi",
]
[[package]]
name = "pkg-config"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d36492546b6af1463394d46f0c834346f31548646f6ba10849802c9c9a27ac33"
[[package]]
name = "ppv-lite86"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20"
[[package]]
name = "proc-macro2"
version = "1.0.21"
@ -185,6 +403,216 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
dependencies = [
"autocfg 0.1.7",
"libc",
"rand_chacha 0.1.1",
"rand_core 0.4.2",
"rand_hc 0.1.0",
"rand_isaac",
"rand_jitter",
"rand_os",
"rand_pcg",
"rand_xorshift",
"winapi",
]
[[package]]
name = "rand"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [
"getrandom",
"libc",
"rand_chacha 0.2.2",
"rand_core 0.5.1",
"rand_hc 0.2.0",
]
[[package]]
name = "rand_chacha"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
dependencies = [
"autocfg 0.1.7",
"rand_core 0.3.1",
]
[[package]]
name = "rand_chacha"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [
"ppv-lite86",
"rand_core 0.5.1",
]
[[package]]
name = "rand_core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
dependencies = [
"rand_core 0.4.2",
]
[[package]]
name = "rand_core"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
[[package]]
name = "rand_core"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
dependencies = [
"getrandom",
]
[[package]]
name = "rand_hc"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [
"rand_core 0.5.1",
]
[[package]]
name = "rand_isaac"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "rand_jitter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
dependencies = [
"libc",
"rand_core 0.4.2",
"winapi",
]
[[package]]
name = "rand_os"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
dependencies = [
"cloudabi 0.0.3",
"fuchsia-cprng",
"libc",
"rand_core 0.4.2",
"rdrand",
"winapi",
]
[[package]]
name = "rand_pcg"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
dependencies = [
"autocfg 0.1.7",
"rand_core 0.4.2",
]
[[package]]
name = "rand_xorshift"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "raw-window-handle"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a441a7a6c80ad6473bd4b74ec1c9a4c951794285bf941c2126f607c72e48211"
dependencies = [
"libc",
]
[[package]]
name = "rdrand"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
dependencies = [
"rand_core 0.3.1",
]
[[package]]
name = "redox_syscall"
version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "sdl2"
version = "0.32.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d051a07231e303f5f719da78cb6f7394f6d5b54f733aef5b0b447804a83edd7b"
dependencies = [
"bitflags",
"lazy_static",
"libc",
"num",
"rand 0.6.5",
"sdl2-sys",
]
[[package]]
name = "sdl2-sys"
version = "0.32.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34e71125077d297d57e4c1acfe8981b5bdfbf5a20e7b589abfdcb33bf1127f86"
dependencies = [
"cfg-if",
"libc",
]
[[package]]
name = "sexp"
version = "1.1.4"
@ -204,6 +632,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "smallvec"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252"
[[package]]
name = "syn"
version = "1.0.41"
@ -215,6 +649,20 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "tempfile"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
dependencies = [
"cfg-if",
"libc",
"rand 0.7.3",
"redox_syscall",
"remove_dir_all",
"winapi",
]
[[package]]
name = "thiserror"
version = "1.0.20"
@ -242,7 +690,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc",
"wasi",
"wasi 0.10.0+wasi-snapshot-preview1",
"winapi",
]
@ -252,12 +700,100 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "version_check"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "wayland-client"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab702fefbcd6d6f67fb5816e3a89a3b5a42a94290abbc015311c9a30d1068ae4"
dependencies = [
"bitflags",
"downcast-rs",
"libc",
"nix",
"wayland-commons",
"wayland-scanner",
"wayland-sys",
]
[[package]]
name = "wayland-commons"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e972e9336ad5a9dd861b4e21ff35ad71d3e5c6b4803d65c39913612f851b95f1"
dependencies = [
"nix",
"once_cell",
"smallvec",
"wayland-sys",
]
[[package]]
name = "wayland-cursor"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "539f346e1a3f706f38c8ccbe1196001e2fb1c9b3e6b605c27d665db2f5b60d41"
dependencies = [
"nix",
"wayland-client",
"xcursor",
]
[[package]]
name = "wayland-protocols"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3d6fc54b17b98b5083bc21ae3a30e6d75cb4b01647360e4c3a04648bcf8781d"
dependencies = [
"bitflags",
"wayland-client",
"wayland-commons",
"wayland-scanner",
]
[[package]]
name = "wayland-scanner"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "030f56009d932bd9400bb472764fea8109be1b0fc482d9cd75496c943ac30328"
dependencies = [
"proc-macro2",
"quote",
"xml-rs",
]
[[package]]
name = "wayland-sys"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bdeffbbb474477dfa2acb45ac7479e5fe8f741c64ab032c5d11b94d07edc269"
dependencies = [
"pkg-config",
]
[[package]]
name = "winapi"
version = "0.3.9"
@ -279,3 +815,51 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "x11-dl"
version = "2.18.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bf981e3a5b3301209754218f962052d4d9ee97e478f4d26d4a6eced34c1fef8"
dependencies = [
"lazy_static",
"libc",
"maybe-uninit",
"pkg-config",
]
[[package]]
name = "xcursor"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3a481cfdefd35e1c50073ae33a8000d695c98039544659f5dc5dd71311b0d01"
dependencies = [
"nom",
]
[[package]]
name = "xkb"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aec02bc5de902aa579f3d2f2c522edaf40fa42963cbaffe645b058ddcc68fdb2"
dependencies = [
"bitflags",
"libc",
"xkbcommon-sys",
]
[[package]]
name = "xkbcommon-sys"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa434980dca02ebf28795d71e570dbb78316d095a228707efd6117bf8246d78b"
dependencies = [
"libc",
"pkg-config",
]
[[package]]
name = "xml-rs"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a"

@ -4,4 +4,5 @@ members = [
"crsn",
"crsn_arith",
"crsn_stacks",
"crsn_screen",
]

@ -3,7 +3,10 @@ use std::fmt::{Debug, Display, Formatter};
use std::fmt;
pub use mask::Mask;
pub use rd::Rd;
pub use rd::RdObj;
pub use reg::Register;
pub use wr::Wr;
use crate::asm::data::literal::{as_signed, Value};
@ -14,11 +17,8 @@ pub mod reg;
pub mod mask;
mod rd;
pub use rd::Rd;
pub use rd::RdObj;
mod wr;
pub use wr::Wr;
/// Data source disposition
#[derive(Debug, Clone, Copy, Eq, PartialEq)]

@ -1,8 +1,9 @@
use crate::asm::data::{RdData, Mask, DataDisp, Register};
use crate::asm::data::literal::Value;
use std::fmt::{Debug, Formatter};
use std::fmt;
use crate::asm::data::{DataDisp, Mask, RdData, Register};
use crate::asm::data::literal::Value;
/// Data source argument (read-only)
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct Rd(pub RdData, pub Mask);

@ -1,6 +1,6 @@
use std::fmt::{self, Display, Formatter};
use crate::asm::error::Error;
use crate::asm::error::CrsnError;
/// Register name
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
@ -34,6 +34,6 @@ pub fn parse_reg(name: &str) -> anyhow::Result<Register> {
let val: u8 = rn.parse()?;
Ok(Register::Gen(val))
} else {
Err(Error::Parse(format!("Bad reg name: {}", name).into()))?
Err(CrsnError::Parse(format!("Bad reg name: {}", name).into()))?
}
}

@ -1,8 +1,8 @@
use crate::asm::data::{RdData, Mask, DataDisp, WrData, Rd};
use crate::asm::data::literal::Value;
use std::fmt::{Debug, Formatter};
use std::fmt;
use crate::asm::data::{DataDisp, Mask, Rd, WrData};
/// Data destination argument (read-write)
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct Wr(WrData, Mask);

@ -8,7 +8,7 @@ use crate::asm::instr::Cond;
/// csn_asm unified error type
#[derive(Error, Debug)]
pub enum Error {
pub enum CrsnError {
#[error("S-expression syntax error: {0:?}")]
PreParse(#[from] Box<sexp::Error>),
#[error("Parse error: {0:?}")]

@ -1,7 +1,7 @@
use std::fmt::{self, Display, Formatter};
use std::ops::Not;
use crate::asm::error::Error;
use crate::asm::error::CrsnError;
/// Condition flag
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
@ -45,7 +45,7 @@ pub enum Cond {
NotCarry,
}
pub fn parse_cond(text: &str) -> Result<Cond, Error> {
pub fn parse_cond(text: &str) -> Result<Cond, CrsnError> {
Ok(match text.trim_end_matches('?') {
"eq" | "=" | "==" => Cond::Equal,
"ne" | "<>" | "!=" | "≠" => Cond::NotEqual,
@ -66,7 +66,7 @@ pub fn parse_cond(text: &str) -> Result<Cond, Error> {
"ov" | "^" => Cond::Overflow,
"nov" | "!ov" | "!^" => Cond::NotOverflow,
_ => {
return Err(Error::Parse(format!("Unknown cond: {}", text).into()));
return Err(CrsnError::Parse(format!("Unknown cond: {}", text).into()));
}
})
}

@ -3,17 +3,17 @@ use std::sync::atomic::AtomicU32;
use crate::asm::data::{Rd, RdData};
use crate::asm::data::literal::{Label, Value};
use crate::asm::error::{AsmError, Error};
use crate::asm::error::{AsmError, CrsnError};
use crate::asm::instr::{Cond, Instr, Op, Routine};
use crate::builtin::defs::BuiltinOp;
/// A trait for something that can turn into multiple instructions
pub trait Flatten {
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, Error>;
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError>;
}
impl Flatten for Instr {
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, Error> {
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError> {
let mut ops = vec![self.op];
if let Some(branches) = self.branches {
@ -22,7 +22,7 @@ impl Flatten for Instr {
let end_lbl = Label::unique(label_num);
for (cnt, (cond, branch)) in branches.into_iter().enumerate() {
if labels.contains_key(&cond) {
return Err(Error::Asm(AsmError::ConditionalAlreadyUsed(cond)));
return Err(CrsnError::Asm(AsmError::ConditionalAlreadyUsed(cond)));
}
let next_lbl = if cnt == branch_count - 1 {
@ -49,7 +49,7 @@ impl Flatten for Instr {
}
impl Flatten for Routine {
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, Error> {
fn flatten(self, label_num: &AtomicU32) -> Result<Vec<Op>, CrsnError> {
let mut ops = vec![
BuiltinOp::Routine(self.name.clone()).into(),
];
@ -65,7 +65,7 @@ impl Flatten for Routine {
}
/// Convert jumps to relative skips
fn numbered_labels_to_skips(ops: Vec<Op>) -> Result<Vec<Op>, Error> {
fn numbered_labels_to_skips(ops: Vec<Op>) -> Result<Vec<Op>, CrsnError> {
let mut label_positions = HashMap::<Label, usize>::new();
for (n, op) in ops.iter().enumerate() {
if let Op::BuiltIn(BuiltinOp::Label(name @ Label::Numbered(_))) = op {
@ -85,7 +85,7 @@ fn numbered_labels_to_skips(ops: Vec<Op>) -> Result<Vec<Op>, Error> {
let skip = *dest as isize - n as isize + skipped;
cleaned.push(Op::BuiltIn(BuiltinOp::Skip(Rd::new(RdData::Immediate(skip as Value)))));
} else {
return Err(Error::Asm(AsmError::LabelNotDefined(target)));
return Err(CrsnError::Asm(AsmError::LabelNotDefined(target)));
}
}
Op::BuiltIn(BuiltinOp::JumpIf(cond, target @ Label::Numbered(_))) => {
@ -93,7 +93,7 @@ fn numbered_labels_to_skips(ops: Vec<Op>) -> Result<Vec<Op>, Error> {
let skip = *dest as isize - n as isize + skipped;
cleaned.push(Op::BuiltIn(BuiltinOp::SkipIf(cond, Rd::new(RdData::Immediate(skip as Value)))));
} else {
return Err(Error::Asm(AsmError::LabelNotDefined(target)));
return Err(CrsnError::Asm(AsmError::LabelNotDefined(target)));
}
}
other => {

@ -3,7 +3,7 @@ use std::fmt::Debug;
use crate::builtin::defs::BuiltinOp;
use crate::module::{EvalRes, OpTrait};
use crate::runtime::fault::Fault;
use crate::runtime::run_thread::{state::RunState, info::ThreadInfo};
use crate::runtime::run_thread::{info::ThreadInfo, state::RunState};
/// A higher level simple opration
#[derive(Debug)]

@ -10,8 +10,8 @@ pub mod parse;
pub mod patches;
/// Parse a program from string and assemble a low level instruction sequence from it.
pub fn assemble(source: &str, parsers: &'static [Box<dyn CrsnExtension>]) -> Result<Arc<Program>, error::Error> {
let ops = parse::parse(source, parsers)?;
pub fn assemble(source: &str, parsers: Arc<Vec<Box<dyn CrsnExtension>>>) -> Result<Arc<Program>, error::CrsnError> {
let ops = parse::parse(source, &parsers)?;
trace!("--- Compiled program ---");
for (n, op) in ops.iter().enumerate() {

@ -1,6 +1,6 @@
use sexp::Sexp;
use crate::asm::data::{Rd, Wr, RdObj, RdData, Mask};
use crate::asm::data::{Mask, Rd, RdData, RdObj, Wr};
use crate::asm::parse::parse_data::{parse_rd, parse_wr};
use crate::asm::parse::sexp_expect::expect_string_atom;

@ -3,7 +3,7 @@ use std::sync::atomic::AtomicU32;
pub use parse_instr::parse_instructions;
use parse_routines::parse_routines;
use crate::asm::error::Error;
use crate::asm::error::CrsnError;
use crate::asm::instr::{Flatten, Op, Routine};
use crate::asm::parse::sexp_expect::expect_list;
use crate::module::CrsnExtension;
@ -17,7 +17,7 @@ mod parse_op;
pub mod arg_parser;
pub fn parse(source: &str, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Op>, Error> {
pub fn parse(source: &str, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Op>, CrsnError> {
let root = sexp::parse(source)?;
let subs: Vec<Routine> = parse_routines(expect_list(Some(root), true)?, parsers)?;

@ -1,18 +1,18 @@
use sexp::Sexp;
use crate::asm::error::Error;
use crate::asm::error::CrsnError;
use crate::asm::instr::{Cond, cond, Instr};
use crate::asm::parse::parse_instr::parse_instructions;
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
use crate::asm::patches::TryRemove;
use crate::module::CrsnExtension;
pub fn parse_cond_branch(tok: Sexp, parsers: &[Box<dyn CrsnExtension>]) -> Result<(Cond, Vec<Instr>), Error> {
pub fn parse_cond_branch(tok: Sexp, parsers: &[Box<dyn CrsnExtension>]) -> Result<(Cond, Vec<Instr>), CrsnError> {
let mut list = expect_list(Some(tok), false)?;
let kw = expect_string_atom(list.try_remove(0))?;
if !kw.ends_with('?') {
return Err(Error::Parse(format!("Condition must end with '?': {}", kw).into()));
return Err(CrsnError::Parse(format!("Condition must end with '?': {}", kw).into()));
}
Ok((cond::parse_cond(&kw)?, parse_instructions(list, parsers)?))

@ -2,23 +2,23 @@ use std::convert::TryFrom;
use sexp::{Atom, Sexp};
use crate::asm::data::{DataDisp, WrData, Rd, reg, RdData, Wr};
use crate::asm::data::{DataDisp, Rd, RdData, reg, Wr, WrData};
use crate::asm::data::literal::Label;
use crate::asm::error::Error;
use crate::asm::error::CrsnError;
use crate::asm::parse::sexp_expect::expect_string_atom;
/// Parse a label
pub fn parse_label(name: Option<Sexp>) -> Result<Label, Error> {
pub fn parse_label(name: Option<Sexp>) -> Result<Label, CrsnError> {
let name = expect_string_atom(name)?;
Ok(Label::Named(name.trim_start_matches(':').into()))
}
/// Parse data disposition (address/value, without the read/write restriction)
pub fn parse_data_disp(tok: Option<Sexp>) -> Result<DataDisp, Error> {
pub fn parse_data_disp(tok: Option<Sexp>) -> Result<DataDisp, CrsnError> {
let tok = if let Some(tok) = tok {
tok
} else {
return Err(Error::Parse("Expected data disposition token".into()));
return Err(CrsnError::Parse("Expected data disposition token".into()));
};
// TODO implement masks
@ -41,7 +41,7 @@ pub fn parse_data_disp(tok: Option<Sexp>) -> Result<DataDisp, Error> {
}
}
_ => {
Err(Error::Parse(format!("bad data disp: {:?}", tok).into()))
Err(CrsnError::Parse(format!("bad data disp: {:?}", tok).into()))
}
}
}

@ -1,6 +1,6 @@
use sexp::Sexp;
use crate::asm::error::Error;
use crate::asm::error::CrsnError;
use crate::asm::instr::Instr;
use crate::asm::parse::arg_parser::ArgParser;
use crate::asm::parse::parse_cond::parse_cond_branch;
@ -10,7 +10,7 @@ use crate::module::CrsnExtension;
use super::parse_op::parse_op;
pub fn parse_instructions(instrs: Vec<Sexp>, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Instr>, Error> {
pub fn parse_instructions(instrs: Vec<Sexp>, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Instr>, CrsnError> {
let mut parsed = vec![];
for expr in instrs {
let tokens = expect_list(Some(expr), false)?;

@ -1,10 +1,10 @@
use crate::asm::error::Error;
use crate::asm::error::CrsnError;
use crate::asm::instr::Op;
use crate::asm::parse::arg_parser::ArgParser;
use crate::builtin::parse::BuiltinOps;
use crate::module::{CrsnExtension, ParseOpRes};
pub fn parse_op(keyword: &str, mut arg_tokens: ArgParser, parsers: &[Box<dyn CrsnExtension>]) -> Result<Op, Error> {
pub fn parse_op(keyword: &str, mut arg_tokens: ArgParser, parsers: &[Box<dyn CrsnExtension>]) -> Result<Op, CrsnError> {
// Include built-in instructions
let builtins = [BuiltinOps::new()];
@ -23,5 +23,5 @@ pub fn parse_op(keyword: &str, mut arg_tokens: ArgParser, parsers: &[Box<dyn Crs
}
}
return Err(Error::Parse(format!("Unknown instruction: {}", keyword).into()));
return Err(CrsnError::Parse(format!("Unknown instruction: {}", keyword).into()));
}

@ -1,14 +1,14 @@
use sexp::Sexp;
use crate::asm::data::literal::RoutineName;
use crate::asm::error::Error;
use crate::asm::error::CrsnError;
use crate::asm::instr::Routine;
use crate::asm::parse::parse_instr::parse_instructions;
use crate::asm::parse::sexp_expect::{expect_list, expect_string_atom};
use crate::asm::patches::TryRemove;
use crate::module::CrsnExtension;
pub fn parse_routines(routines: Vec<Sexp>, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Routine>, Error> {
pub fn parse_routines(routines: Vec<Sexp>, parsers: &[Box<dyn CrsnExtension>]) -> Result<Vec<Routine>, CrsnError> {
let mut parsed = vec![];
for rt in routines {
let mut def = expect_list(Some(rt), false)?;

@ -1,16 +1,16 @@
use sexp::{Atom, Sexp};
use crate::asm::error::Error;
use crate::asm::error::CrsnError;
pub fn expect_list(expr: Option<Sexp>, allow_empty: bool) -> Result<Vec<Sexp>, Error> {
pub fn expect_list(expr: Option<Sexp>, allow_empty: bool) -> Result<Vec<Sexp>, CrsnError> {
if let Some(expr) = expr {
match &expr {
Sexp::Atom(_) => {
return Err(Error::ParseIn("Expected a list".into(), expr));
return Err(CrsnError::ParseIn("Expected a list".into(), expr));
}
Sexp::List(list) => {
if !allow_empty && list.is_empty() {
return Err(Error::ParseIn("Routine: Empty list".into(), expr));
return Err(CrsnError::ParseIn("Routine: Empty list".into(), expr));
}
if let Sexp::List(list) = expr {
@ -22,10 +22,10 @@ pub fn expect_list(expr: Option<Sexp>, allow_empty: bool) -> Result<Vec<Sexp>, E
}
}
Err(Error::Parse("Expected a list, got nothing".into()))
Err(CrsnError::Parse("Expected a list, got nothing".into()))
}
pub fn expect_atom(expr: Option<Sexp>) -> Result<Atom, Error> {
pub fn expect_atom(expr: Option<Sexp>) -> Result<Atom, CrsnError> {
if let Some(expr) = expr {
match &expr {
Sexp::Atom(_atom) => {
@ -36,18 +36,18 @@ pub fn expect_atom(expr: Option<Sexp>) -> Result<Atom, Error> {
}
}
Sexp::List(_) => {
return Err(Error::ParseIn("Expected atom got list".into(), expr));
return Err(CrsnError::ParseIn("Expected atom got list".into(), expr));
}
}
}
Err(Error::Parse("Expected atom, got nothing".into()))
Err(CrsnError::Parse("Expected atom, got nothing".into()))
}
pub fn expect_string_atom(expr: Option<Sexp>) -> Result<String, Error> {
pub fn expect_string_atom(expr: Option<Sexp>) -> Result<String, CrsnError> {
match expect_atom(expr) {
Ok(Atom::S(s)) => Ok(s),
Ok(atom) => Err(Error::ParseIn("Expected string atom".into(), Sexp::Atom(atom))),
Ok(atom) => Err(CrsnError::ParseIn("Expected string atom".into(), Sexp::Atom(atom))),
Err(e) => Err(e),
}
}

@ -1,4 +1,4 @@
use crate::asm::data::{Rd, Wr, RdObj};
use crate::asm::data::{Rd, RdObj, Wr};
use crate::asm::data::literal::{DebugMsg, Label, RoutineName};
use crate::asm::instr::{Cond, Op};

@ -1,11 +1,11 @@
use crate::asm::data::{Rd, RdData};
use crate::asm::data::literal::Addr;
use crate::asm::instr::Cond;
use crate::builtin::defs::BuiltinOp;
use crate::module::{EvalRes, OpTrait};
use crate::runtime::fault::Fault;
use crate::runtime::frame::StackFrame;
use crate::runtime::run_thread::{state::RunState, ThreadInfo};
use crate::asm::data::{Rd, RdData};
use crate::asm::instr::Cond;
impl OpTrait for BuiltinOp {
fn execute(&self, info: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {
@ -142,7 +142,7 @@ impl OpTrait for BuiltinOp {
trace!("Drop object: {:#x}", x);
let mut dropped = false;
for ex in info.program.extensions {
for ex in info.program.extensions.iter() {
if ex.drop_obj(info, state, x)?.is_some() {
dropped = true;
}

@ -1,7 +1,7 @@
use sexp::{Atom, Sexp};
use crate::asm::data::literal::{Label, RoutineName};
use crate::asm::error::Error;
use crate::asm::error::CrsnError;
use crate::asm::instr::cond::parse_cond;
use crate::asm::instr::Op;
use crate::asm::parse::arg_parser::ArgParser;
@ -9,7 +9,6 @@ use crate::asm::parse::parse_data::{parse_label, parse_rd};
use crate::asm::parse::sexp_expect::expect_string_atom;
use crate::builtin::defs::BuiltinOp;
use crate::module::{CrsnExtension, ParseOpRes};
use crate::asm::data::RdObj;
#[derive(Debug, Clone)]
pub struct BuiltinOps {
@ -29,7 +28,7 @@ impl CrsnExtension for BuiltinOps {
"builtin"
}
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpRes, Error> {
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
Ok(ParseOpRes::Parsed(Op::BuiltIn(match keyword {
"nop" => {
BuiltinOp::Nop

@ -2,25 +2,32 @@ use std::fmt::Debug;
pub use eval_res::EvalRes;
use crate::asm::error::Error;
use crate::asm::data::literal::Value;
use crate::asm::data::Mask;
use crate::asm::error::CrsnError;
use crate::asm::instr::Op;
use crate::asm::parse::arg_parser::ArgParser;
use crate::runtime::fault::Fault;
use crate::runtime::run_thread::state::RunState;
use crate::runtime::run_thread::ThreadInfo;
use crate::asm::data::literal::Value;
use crate::asm::data::Mask;
mod eval_res;
/// Result type returned from the op parser. This is the Ok variant of a Result.
pub enum ParseOpRes {
pub enum ParseOpRes<T> {
/// Parsing successful.
Parsed(Op),
Parsed(T),
/// Instruction not recognized, but there was no error.
Unknown(ArgParser),
}
impl ParseOpRes<Op> {
/// Helper to construct an extension op
pub fn ext(op : impl OpTrait) -> Self {
Self::Parsed(Op::Ext(Box::new(op)))
}
}
pub trait OpTrait: Debug + Send + Sync + 'static {
fn execute(&self, ti: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault>;
}
@ -34,13 +41,13 @@ pub trait CrsnExtension: Debug + Send + Sync + 'static {
/// the argument list and either return Ok or Err.
///
/// If the instruction keyword is not recognized, return Unknown with the unchanged argument list.
fn parse_op(&self, keyword: &str, arg_tokens: ArgParser) -> Result<ParseOpRes, Error>;
fn parse_op(&self, keyword: &str, arg_tokens: ArgParser) -> Result<ParseOpRes<Op>, CrsnError>;
/// Drop an object referenced by a handle
fn drop_obj(&self,
#[allow(unused)] ti: &ThreadInfo,
#[allow(unused)] state: &mut RunState,
#[allow(unused)] handle : Value) -> Result<Option<()>, Fault>
#[allow(unused)] handle: Value) -> Result<Option<()>, Fault>
{
// Default impl - we do not support dropping this object
Ok(None)
@ -50,8 +57,8 @@ pub trait CrsnExtension: Debug + Send + Sync + 'static {
fn read_obj(&self,
#[allow(unused)] ti: &ThreadInfo,
#[allow(unused)] state: &mut RunState,
#[allow(unused)] handle : Value,
#[allow(unused)] mask : Mask
#[allow(unused)] handle: Value,
#[allow(unused)] mask: Mask,
) -> Result<Option<Value>, Fault> {
// Default impl - we do not support reading this object
Ok(None)
@ -61,8 +68,8 @@ pub trait CrsnExtension: Debug + Send + Sync + 'static {
fn write_obj(&self,
#[allow(unused)] ti: &ThreadInfo,
#[allow(unused)] state: &mut RunState,
#[allow(unused)] handle : Value,
#[allow(unused)] mask : Mask
#[allow(unused)] handle: Value,
#[allow(unused)] mask: Mask,
) -> Result<Option<()>, Fault> {
// Default impl - we do not support writing this object
Ok(None)

@ -2,6 +2,7 @@ use thiserror::Error;
use crate::asm::data::literal::{DebugMsg, Label, RoutineName, Value};
use crate::asm::data::Register;
use std::borrow::Cow;
#[derive(Error, Debug)]
pub enum Fault {
@ -24,6 +25,9 @@ pub enum Fault {
#[error("Program ended.")]
Halt,
#[error("Operation not allowed: {0}")]
NotAllowed(Cow<'static, str>),
#[error("Object does not exist: {0:#x}")]
ObjectNotExist(Value),

@ -4,20 +4,20 @@ use std::sync::Arc;
use crate::asm::data::literal::{Addr, Label, RoutineName};
use crate::asm::instr::Op;
use crate::builtin::defs::BuiltinOp;
use crate::runtime::fault::Fault;
use crate::module::CrsnExtension;
use crate::runtime::fault::Fault;
#[derive(Debug)]
pub struct Program {
pub ops: Vec<Op>,
pub extensions: &'static [Box<dyn CrsnExtension>],
pub extensions: Arc<Vec<Box<dyn CrsnExtension>>>,
routines: HashMap<RoutineName, Addr>,
far_labels: HashMap<Label, Addr>,
barriers: Vec<Addr>,
}
impl Program {
pub fn new(ops: Vec<Op>, extensions: &'static [Box<dyn CrsnExtension>]) -> Arc<Self> {
pub fn new(ops: Vec<Op>, extensions: Arc<Vec<Box<dyn CrsnExtension>>>) -> Arc<Self> {
let mut p = Self {
ops,
extensions,

@ -1,14 +1,17 @@
use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::atomic::AtomicU64;
use std::thread::JoinHandle;
use std::time::Duration;
use crate::asm::data::literal::{Addr, Value};
pub use info::ThreadInfo;
pub use state::RunState;
use crate::asm::data::literal::Addr;
use crate::module::EvalRes;
use crate::runtime::fault::Fault;
use crate::runtime::frame::StackFrame;
use crate::runtime::program::Program;
use crate::runtime::run_thread::info::{UNIQ_BASE};
use std::pin::Pin;
#[derive(Clone, Copy, Eq, PartialEq, Debug, Ord, PartialOrd)]
pub struct ThreadToken(pub u32);
@ -20,27 +23,17 @@ pub struct RunThread {
pub mod info;
pub mod state;
pub use info::ThreadInfo;
pub use state::RunState;
pub fn new_uniq() -> &'static AtomicU64 {
let uniq = AtomicU64::new(info::UNIQ_BASE);
Box::leak(Box::new(uniq))
pub fn new_uniq() -> Arc<AtomicU64> {
Arc::new(AtomicU64::new(info::UNIQ_BASE))
}
impl RunThread {
pub fn new(id: ThreadToken, uniq: Option<&'static AtomicU64>, program: Arc<Program>, pc: Addr, args: &[u64]) -> Self {
let uniq = if let Some(u) = uniq {
u
} else {
let u = AtomicU64::new(UNIQ_BASE);
Box::leak(Box::new(u)) as &AtomicU64
};
pub fn new(id: ThreadToken, uniq: Option<Arc<AtomicU64>>, program: Arc<Program>, pc: Addr, args: &[u64]) -> Self {
Self {
info: ThreadInfo {
id,
uniq,
uniq: uniq.unwrap_or_else(new_uniq),
program,
cycle_time: Duration::default(),
},

@ -1,15 +1,16 @@
use crate::runtime::run_thread::ThreadToken;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use crate::runtime::program::Program;
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::Duration;
use crate::asm::data::literal::Value;
use crate::runtime::program::Program;
use crate::runtime::run_thread::ThreadToken;
pub struct ThreadInfo {
/// Thread ID
pub id: ThreadToken,
/// Thread ID
pub(crate) uniq: &'static AtomicU64,
pub(crate) uniq: Arc<AtomicU64>,
/// Program to run
pub program: Arc<Program>,
/// Program to run

@ -1,7 +1,7 @@
use std::any::{Any, TypeId};
use std::collections::HashMap;
use crate::asm::data::{WrData, Rd, Register, RdData, Wr, RdObj};
use crate::asm::data::{Rd, RdData, RdObj, Register, Wr, WrData};
use crate::asm::data::literal::{Addr, Value};
use crate::asm::instr::Cond;
use crate::runtime::fault::Fault;

@ -1,6 +1,27 @@
pub use parse::ArithOps;
use crsn::module::{CrsnExtension, ParseOpRes};
use crsn::asm::parse::arg_parser::ArgParser;
use crsn::asm::error::CrsnError;
use crsn::asm::instr::Op;
mod defs;
mod parse;
mod exec;
#[derive(Debug, Clone)]
pub struct ArithOps;
impl ArithOps {
pub fn new() -> Box<dyn CrsnExtension> {
Box::new(Self)
}
}
impl CrsnExtension for ArithOps {
fn name(&self) -> &'static str {
"arith"
}
fn parse_op(&self, keyword: &str, args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
parse::parse(keyword, args)
}
}

@ -1,455 +1,437 @@
use crsn::asm::data::{Rd, Wr};
use crsn::asm::error::Error;
use crsn::asm::error::CrsnError;
use crsn::asm::instr::Op;
use crsn::asm::parse::arg_parser::ArgParser;
use crsn::module::{CrsnExtension, ParseOpRes};
use crsn::module::{ParseOpRes};
use crate::defs::ArithOp;
#[derive(Debug, Clone)]
pub struct ArithOps {
_internal: ()
}
impl ArithOps {
pub fn new() -> Box<dyn CrsnExtension> {
Box::new(Self {
_internal: ()
})
}
}
pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
Ok(ParseOpRes::ext(match keyword {
"cmp" => {
ArithOp::Compare {
a: args.next_rd()?,
b: args.next_rd()?,
}
}
impl CrsnExtension for ArithOps {
fn name(&self) -> &'static str {
"arith"
}
"tst" => {
let arg = args.next_rd()?;
ArithOp::Test { a: arg }
}
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpRes, Error> {
Ok(ParseOpRes::Parsed(Op::Ext(Box::new(match keyword {
"cmp" => {
ArithOp::Compare {
a: args.next_rd()?,
b: args.next_rd()?,
}
"inc" => {
let dst = args.next_wr()?;
ArithOp::Add {
dst,
a: dst.as_rd(),
b: Rd::immediate(1),
}
}
"tst" => {
let arg = args.next_rd()?;
ArithOp::Test { a: arg }
"dec" => {
let dst = args.next_wr()?;
ArithOp::Sub {
dst,
a: dst.as_rd(),
b: Rd::immediate(1),
}
}
"inc" => {
let dst = args.next_wr()?;
ArithOp::Add {
dst,
a: dst.as_rd(),
b: Rd::immediate(1),
"add" => {
match args.len() {
3 => {
ArithOp::Add {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
}
"dec" => {
let dst = args.next_wr()?;
ArithOp::Sub {
dst,
a: dst.as_rd(),
b: Rd::immediate(1),
2 => {
let dst = args.next_wr()?;
ArithOp::Add {
dst,
a: dst.as_rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Add requires 2 or 3 arguments".into()));
}
}
}
"add" => {
match args.len() {
3 => {
ArithOp::Add {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Add {
dst,
a: dst.as_rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(Error::Parse("Add requires 2 or 3 arguments".into()));
"sub" => {
match args.len() {
3 => {
ArithOp::Sub {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Sub {
dst,
a: dst.as_rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Sub requires 2 or 3 arguments".into()));
}
}
}
"sub" => {
match args.len() {
3 => {
ArithOp::Sub {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Sub {
dst,
a: dst.as_rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(Error::Parse("Sub requires 2 or 3 arguments".into()));
"mul" => {
match args.len() {
3 => {
ArithOp::Mul {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Mul {
dst,
a: dst.as_rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Mul requires 2 or 3 arguments".into()));
}
}
}
"mul" => {
match args.len() {
3 => {
ArithOp::Mul {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Mul {
dst,
a: dst.as_rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(Error::Parse("Mul requires 2 or 3 arguments".into()));
"divr" => {
match args.len() {
3 => {
let dst = args.next_wr()?;
let rem = args.next_wr()?;
let div = args.next_rd()?;
ArithOp::Div {
dst,
rem,
a: dst.as_rd(),
div,
}
}
4 => {
ArithOp::Div {
dst: args.next_wr()?,
rem: args.next_wr()?,
a: args.next_rd()?,
div: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("DivR requires 3 or 4 arguments".into()));
}
}
}
"divr" => {
match args.len() {
3 => {
let dst = args.next_wr()?;
let rem = args.next_wr()?;
let div = args.next_rd()?;
ArithOp::Div {
dst,
rem,
a: dst.as_rd(),
div,
}
}
4 => {
ArithOp::Div {
dst: args.next_wr()?,
rem: args.next_wr()?,
a: args.next_rd()?,
div: args.next_rd()?,
}
}
_ => {
return Err(Error::Parse("DivR requires 3 or 4 arguments".into()));
"div" => {
match args.len() {
3 => {
ArithOp::Div {
dst: args.next_wr()?,
rem: Wr::discard(),
a: args.next_rd()?,
div: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
let div = args.next_rd()?;
ArithOp::Div {
dst,
rem: Wr::discard(),
a: dst.as_rd(),
div,
}
}
_ => {
return Err(CrsnError::Parse("Div requires 2 or 3 arguments".into()));
}
}
}
"div" => {
match args.len() {
3 => {
ArithOp::Div {
dst: args.next_wr()?,
rem: Wr::discard(),
a: args.next_rd()?,
div: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
let div = args.next_rd()?;
ArithOp::Div {
dst,
rem: Wr::discard(),
a: dst.as_rd(),
div,
}
}
_ => {
return Err(Error::Parse("Div requires 2 or 3 arguments".into()));
"mod" => {
match args.len() {
3 => {
ArithOp::Mod {
dst: args.next_wr()?,
a: args.next_rd()?,
div: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
let div = args.next_rd()?;
ArithOp::Mod {
dst,
a: dst.as_rd(),
div,
}
}
_ => {
return Err(CrsnError::Parse("Mod requires 2 or 3 arguments".into()));
}
}
}
"mod" => {
match args.len() {
3 => {
ArithOp::Mod {
dst: args.next_wr()?,
a: args.next_rd()?,
div: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
let div = args.next_rd()?;
ArithOp::Mod {
dst,
a: dst.as_rd(),
div,
}
}
_ => {
return Err(Error::Parse("Mod requires 2 or 3 arguments".into()));
"and" => {
match args.len() {
3 => {
ArithOp::And {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::And {
dst,
a: dst.as_rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("And requires 2 or 3 arguments".into()));
}
}
}
"and" => {
match args.len() {
3 => {
ArithOp::And {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::And {
dst,
a: dst.as_rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(Error::Parse("And requires 2 or 3 arguments".into()));
"or" => {
match args.len() {
3 => {
ArithOp::Or {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Or {
dst,
a: dst.as_rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Or requires 2 or 3 arguments".into()));
}
}
}
"or" => {
match args.len() {
3 => {
ArithOp::Or {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Or {
dst,
a: dst.as_rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(Error::Parse("Or requires 2 or 3 arguments".into()));
"xor" => {
match args.len() {
3 => {
ArithOp::Xor {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Xor {
dst,
a: dst.as_rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(CrsnError::Parse("Xor requires 2 or 3 arguments".into()));
}
}
}
"xor" => {
match args.len() {
3 => {
ArithOp::Xor {
dst: args.next_wr()?,
a: args.next_rd()?,
b: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Xor {
dst,
a: dst.as_rd(),
b: args.next_rd()?,
}
}
_ => {
return Err(Error::Parse("Xor requires 2 or 3 arguments".into()));
"cpl" => {
match args.len() {
2 => {
ArithOp::Cpl {
dst: args.next_wr()?,
a: args.next_rd()?,
}
}
1 => {
let dst = args.next_wr()?;
ArithOp::Cpl {
dst,
a: dst.as_rd(),
}
}
_ => {
return Err(CrsnError::Parse("Cpl requires 1 or 2 arguments".into()));
}
}
}
"cpl" => {
match args.len() {
2 => {
ArithOp::Cpl {
dst: args.next_wr()?,
a: args.next_rd()?,
}
"rol" => {
match args.len() {
3 => {
ArithOp::Rol {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
1 => {
let dst = args.next_wr()?;
ArithOp::Cpl {
dst,
a: dst.as_rd(),
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Rol {
dst,
a: dst.as_rd(),
n: args.next_rd()?,
}
_ => {
return Err(Error::Parse("Cpl requires 1 or 2 arguments".into()));
}
1 => {
let dst = args.next_wr()?;
ArithOp::Rol {
dst,
a: dst.as_rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Rol requires 1, 2 or 3 arguments".into()));
}
}
}
"rol" => {
match args.len() {
3 => {
ArithOp::Rol {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Rol {
dst,
a: dst.as_rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_wr()?;
ArithOp::Rol {
dst,
a: dst.as_rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(Error::Parse("Rol requires 1, 2 or 3 arguments".into()));
"ror" => {
match args.len() {
3 => {
ArithOp::Ror {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
}
"ror" => {
match args.len() {
3 => {
ArithOp::Ror {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Ror {
dst,
a: dst.as_rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_wr()?;
ArithOp::Ror {
dst,
a: dst.as_rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(Error::Parse("Ror requires 1, 2 or 3 arguments".into()));
2 => {
let dst = args.next_wr()?;
ArithOp::Ror {
dst,
a: dst.as_rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_wr()?;
ArithOp::Ror {
dst,
a: dst.as_rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Ror requires 1, 2 or 3 arguments".into()));
}
}
}
"lsl" | "asl" => {
match args.len() {
3 => {
ArithOp::Lsl {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Lsl {
dst,
a: dst.as_rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_wr()?;
ArithOp::Lsl {
dst,
a: dst.as_rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(Error::Parse("Lsl requires 1, 2 or 3 arguments".into()));
"lsl" | "asl" => {
match args.len() {
3 => {
ArithOp::Lsl {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Lsl {
dst,
a: dst.as_rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_wr()?;
ArithOp::Lsl {
dst,
a: dst.as_rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Lsl requires 1, 2 or 3 arguments".into()));
}
}
}
"lsr" => {
match args.len() {
3 => {
ArithOp::Lsr {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Lsr {
dst,
a: dst.as_rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_wr()?;
ArithOp::Lsr {
dst,
a: dst.as_rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(Error::Parse("Lsr requires 1, 2 or 3 arguments".into()));
"lsr" => {
match args.len() {
3 => {
ArithOp::Lsr {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Lsr {
dst,
a: dst.as_rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_wr()?;
ArithOp::Lsr {
dst,
a: dst.as_rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Lsr requires 1, 2 or 3 arguments".into()));
}
}
}
"asr" => {
match args.len() {
3 => {
ArithOp::Asr {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Asr {
dst,
a: dst.as_rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_wr()?;
ArithOp::Asr {
dst,
a: dst.as_rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(Error::Parse("Asr requires 1, 2 or 3 arguments".into()));
"asr" => {
match args.len() {
3 => {
ArithOp::Asr {
dst: args.next_wr()?,
a: args.next_rd()?,
n: args.next_rd()?,
}
}
2 => {
let dst = args.next_wr()?;
ArithOp::Asr {
dst,
a: dst.as_rd(),
n: args.next_rd()?,
}
}
1 => {
let dst = args.next_wr()?;
ArithOp::Asr {
dst,
a: dst.as_rd(),
n: Rd::immediate(1),
}
}
_ => {
return Err(CrsnError::Parse("Asr requires 1, 2 or 3 arguments".into()));
}
}
}
_other => {
return Ok(ParseOpRes::Unknown(args));
}
}))))
}
_other => {
return Ok(ParseOpRes::Unknown(args));
}
}))
}

@ -0,0 +1,13 @@
[package]
name = "crsn_screen"
version = "0.1.0"
authors = ["Ondřej Hruška <ondra@ondrovo.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
crsn = { path = "../crsn" }
minifb = "0.19.1"
parking_lot = "0.11.0"
log = "0.4.11"

@ -0,0 +1,14 @@
use crsn::asm::data::{Rd, RdObj, Wr};
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum ScreenOp {
ScreenInit {
width: Rd,
height: Rd,
},
SetPixel {
x: Rd,
y: Rd,
color: Rd,
}
}

@ -0,0 +1,99 @@
use std::collections::{HashMap, VecDeque};
use crsn::asm::data::literal::Value;
use crsn::asm::instr::Cond;
use crsn::module::{CrsnExtension, EvalRes, OpTrait};
use crsn::runtime::fault::Fault;
use crsn::runtime::run_thread::{state::RunState, ThreadInfo};
use crate::defs::ScreenOp;
use minifb::{Window, WindowOptions, ScaleMode};
use parking_lot::Mutex;
use std::sync::Arc;
#[derive(Debug, Default)]
struct Backend {
width: usize,
height: usize,
buffer: Vec<u32>,
window: Option<Window>,
}
// Hack for Window
unsafe impl std::marker::Send for Backend { }
impl OpTrait for ScreenOp {
fn execute(&self, info: &ThreadInfo, state: &mut RunState) -> Result<EvalRes, Fault> {
let eres = EvalRes::default();
match self {
ScreenOp::ScreenInit { width, height } => {
let w = state.read(*width)?;
let h = state.read(*height)?;
init(state, w, h)?;
}
ScreenOp::SetPixel { x, y, color } => {
let x = state.read(*x)?;
let y = state.read(*y)?;
let color = state.read(*color)?;
let backend : &mut Backend = state.ext_mut();
match &mut backend.window {
Some(w) => {
let index = y * backend.width as u64 + x;
if index as usize > backend.buffer.len() {
warn!("Screen set pixel out of bounds");
state.set_flag(Cond::Invalid, true);
} else {
backend.buffer[index as usize] = color as u32;
w
.update_with_buffer(&backend.buffer, backend.width, backend.height)
.expect("Update screen"); // TODO fault
}
}
None => {
state.set_flag(Cond::Invalid, true);
}
}
}
}
Ok(eres)
}
//
}
fn init(state: &mut RunState, width: Value, height: Value) -> Result<(), Fault> {
let mut window = Window::new(
"Croissant",
width as usize,
height as usize,
WindowOptions {
resize: true,
scale_mode: ScaleMode::AspectRatioStretch,
..WindowOptions::default()
},
).expect("Unable to create window"); // TODO fault
let backend : &mut Backend = state.ext_mut();
if backend.window.is_some() {
return Err(Fault::NotAllowed("Screen already initialized".into()));
}
backend.width = width as usize;
backend.height = height as usize;
backend.buffer = vec![0; (width * height) as usize];
// window.limit_update_rate(Some(std::time::Duration::from_micros(16600)));
window.limit_update_rate(None);
window
.update_with_buffer(&backend.buffer, backend.width, backend.height)
.expect("Update screen"); // TODO fault
backend.window = Some(window);
Ok(())
}

@ -0,0 +1,30 @@
#[macro_use]
extern crate log;
use crsn::module::{CrsnExtension, ParseOpRes};
use crsn::asm::parse::arg_parser::ArgParser;
use crsn::asm::instr::Op;
use crsn::asm::error::CrsnError;
mod defs;
mod parse;
mod exec;
#[derive(Debug, Clone)]
pub struct ScreenOps;
impl ScreenOps {
pub fn new() -> Box<dyn CrsnExtension> {
Box::new(Self)
}
}
impl CrsnExtension for ScreenOps {
fn name(&self) -> &'static str {
"screen"
}
fn parse_op(&self, keyword: &str, args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
parse::parse(keyword, args)
}
}

@ -0,0 +1,30 @@
use crsn::asm::error::CrsnError;
use crsn::asm::instr::Op;
use crsn::asm::parse::arg_parser::ArgParser;
use crsn::module::{ParseOpRes};
use crate::defs::ScreenOp;
pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
Ok(ParseOpRes::ext(match keyword {
"sc-init" => {
ScreenOp::ScreenInit {
width: args.next_rd()?,
height: args.next_rd()?,
}
}
"sc-px" => {
ScreenOp::SetPixel {
x: args.next_rd()?,
y: args.next_rd()?,
color: args.next_rd()?,
}
}
_other => {
return Ok(ParseOpRes::Unknown(args));
}
}))
}

@ -1,4 +1,4 @@
use crsn::asm::data::{Rd, Wr, RdObj};
use crsn::asm::data::{Rd, RdObj, Wr};
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum StackOp {

@ -1,13 +1,12 @@
use std::collections::{VecDeque, HashMap};
use std::collections::{HashMap, VecDeque};
use crsn::asm::data::literal::Value;
use crsn::asm::instr::Cond;
use crsn::module::{EvalRes, OpTrait, CrsnExtension};
use crsn::module::{CrsnExtension, EvalRes, OpTrait};
use crsn::runtime::fault::Fault;
use crsn::runtime::run_thread::{state::RunState, ThreadInfo};
use crate::defs::StackOp;
use crate::StackOps;
#[derive(Debug, Default)]
struct Stacks {
@ -68,7 +67,7 @@ impl OpTrait for StackOp {
//
}
pub(crate) fn drop_stack(state: &mut RunState, handle : Value) -> Result<Option<()>, Fault> {
pub(crate) fn drop_obj(state: &mut RunState, handle: Value) -> Result<Option<()>, Fault> {
let stacks: &mut Stacks = state.ext_mut();
Ok(stacks.store.remove(&handle).map(|_| ()))
}

@ -1,6 +1,34 @@
pub use parse::StackOps;
use crsn::module::{CrsnExtension, ParseOpRes};
use crsn::asm::parse::arg_parser::ArgParser;
use crsn::asm::instr::Op;
use crsn::asm::error::CrsnError;
use crsn::runtime::run_thread::{ThreadInfo, RunState};
use crsn::asm::data::literal::Value;
use crsn::runtime::fault::Fault;
mod defs;
mod parse;
mod exec;
#[derive(Debug, Clone)]
pub struct StackOps;
impl StackOps {
pub fn new() -> Box<dyn CrsnExtension> {
Box::new(Self)
}
}
impl CrsnExtension for StackOps {
fn name(&self) -> &'static str {
"stacks"
}
fn parse_op(&self, keyword: &str, args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
parse::parse(keyword, args)
}
fn drop_obj(&self, ti: &ThreadInfo, state: &mut RunState, handle: Value) -> Result<Option<()>, Fault> {
exec::drop_obj(state, handle)
}
}

@ -1,61 +1,37 @@
use crsn::asm::error::Error;
use crsn::asm::error::CrsnError;
use crsn::asm::instr::Op;
use crsn::asm::parse::arg_parser::ArgParser;
use crsn::module::{CrsnExtension, ParseOpRes};
use crsn::module::{ParseOpRes};
use crate::defs::StackOp;
use crsn::runtime::run_thread::{ThreadInfo, RunState};
use crsn::asm::data::literal::Value;
use crsn::runtime::fault::Fault;
#[derive(Debug, Clone)]
pub struct StackOps {
_internal: ()
}
impl StackOps {
pub fn new() -> Box<dyn CrsnExtension> {
Box::new(Self {
_internal: ()
})
}
}
impl CrsnExtension for StackOps {
fn name(&self) -> &'static str {
"stacks"
}
fn parse_op(&self, keyword: &str, mut args: ArgParser) -> Result<ParseOpRes, Error> {
Ok(ParseOpRes::Parsed(Op::Ext(Box::new(match keyword {
"stack" => {
StackOp::NewStack {
dst: args.next_wr()?,
}
}
use crate::defs::StackOp;
"push" => {
StackOp::Push {
obj: args.next_rdobj()?,
src: args.next_rd()?,
}
pub(crate) fn parse(keyword: &str, mut args: ArgParser) -> Result<ParseOpRes<Op>, CrsnError> {
Ok(ParseOpRes::ext(match keyword {
"stack" => {
StackOp::NewStack {
dst: args.next_wr()?,
}
}
"pop" => {
StackOp::Pop {
dst: args.next_wr()?,
obj: args.next_rdobj()?,
}
"push" => {
StackOp::Push {
obj: args.next_rdobj()?,
src: args.next_rd()?,
}
}
_other => {
return Ok(ParseOpRes::Unknown(args));
"pop" => {
StackOp::Pop {
dst: args.next_wr()?,
obj: args.next_rdobj()?,
}
}))))
}
}
fn drop_obj(&self, _ti: &ThreadInfo, state: &mut RunState, handle : Value) -> Result<Option<()>, Fault>
{
crate::exec::drop_stack(state, handle)
}
_other => {
return Ok(ParseOpRes::Unknown(args));
}
}))
}

@ -10,6 +10,7 @@ edition = "2018"
crsn = { path = "../crsn" }
crsn_arith = { path = "../crsn_arith" }
crsn_stacks = { path = "../crsn_stacks" }
crsn_screen = { path = "../crsn_screen" }
simple_logger = "1.9.0"
log = "0.4.11"

@ -1,19 +1,24 @@
#[macro_use]
extern crate log;
use std::time::Duration;
use std::sync::Arc;
use simple_logger::SimpleLogger;
use crsn::asm::data::literal::Addr;
use crsn::runtime::run_thread::{RunThread, ThreadToken};
use crsn::runtime::run_thread;
use crsn_arith::ArithOps;
use crsn_stacks::StackOps;
use std::sync::atomic::AtomicU64;
use crsn::runtime::run_thread;
use crsn_screen::ScreenOps;
use std::time::Duration;
use log::LevelFilter;
fn main() {
SimpleLogger::new().init().unwrap();
SimpleLogger::new()
.with_level(LevelFilter::Warn)
.init().unwrap();
// ;(dec r0 (z? (ret)))
/*let program = "
@ -72,35 +77,42 @@ fn main() {
let program = "
(
(main
(stack r7)
(push @r7 10)
(push @r7 20)
(call emptystack r7)
(push @r7 30)
(pop r0 @r7)
(pop r0 @r7)
(drop @r7)
(pop r0 @r7) ; this fails
(halt)
)
(emptystack
(:again)
(pop _ @arg0 (nz? (j :again)))
(ret)
(sc-init 640 480)
(ld r0 39) ; x
(ld r1 0) ; y
(ld r2 1) ; dx
(ld r3 1) ; dy
(ld r5 0xffffff)
(:loop)
(add r5 0x123456)
(and r5 0xffffff)
(sc-px r0 r1 r5)
(add r0 r2)
(add r1 r3)
(cmp r0 639 (eq? (ld r2 -1)))
(cmp r0 0 (eq? (ld r2 1)))
(cmp r1 479 (eq? (ld r3 -1)))
(cmp r1 0 (eq? (ld r3 1)))
(j :loop)
)
)
";
let parsers = Box::leak(Box::new(vec![
let parsers = Arc::new(vec![
ArithOps::new(),
StackOps::new(),
]));
ScreenOps::new(),
]);
let parsed = crsn::asm::assemble(program, parsers.as_slice()).unwrap();
let parsed = crsn::asm::assemble(program, parsers).unwrap();
let uniq = run_thread::new_uniq();
let mut thread1 = RunThread::new(ThreadToken(0), Some(uniq), parsed.clone(), Addr(0), &[]);
let mut thread1 = RunThread::new(ThreadToken(0), Some(uniq.clone()), parsed.clone(), Addr(0), &[]);
//thread1.set_speed(Duration::from_millis(250));
let _thread2 = RunThread::new(ThreadToken(1), Some(uniq), parsed.clone(), Addr(0), &[]);

Loading…
Cancel
Save