Squashed assembler
This commit is contained in:
parent
3a6d0fdd2d
commit
d6243fa99f
363
Cargo.lock
generated
363
Cargo.lock
generated
|
@ -18,12 +18,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.2"
|
||||
name = "ahash"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||
checksum = "cd7d5a2cecb58716e47d67d5703a249964b14c7be1ec3cad3affc295b2d1c35d"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"cfg-if",
|
||||
"const-random",
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -84,16 +89,6 @@ version = "2.4.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c79ad7fb2dd38f3dabd76b09c6a5a20c038fc0213ef1e9afd30eb777f120f019"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.83"
|
||||
|
@ -137,21 +132,31 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
name = "const-random"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
checksum = "11df32a13d7892ec42d51d3d175faba5211ffe13ed25d4fb348ac9e9ce835593"
|
||||
dependencies = [
|
||||
"const-random-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.5"
|
||||
name = "const-random-macro"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"
|
||||
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"tiny-keccak",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
|
||||
|
||||
[[package]]
|
||||
name = "eyre"
|
||||
version = "0.6.8"
|
||||
|
@ -162,6 +167,17 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.28.0"
|
||||
|
@ -172,8 +188,8 @@ checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
|
|||
name = "hbasm"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"mlua",
|
||||
"paste",
|
||||
"rhai",
|
||||
"with_builtin_macros",
|
||||
]
|
||||
|
||||
|
@ -192,7 +208,7 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "hbxrt"
|
||||
name = "hbvm_aos_on_linux"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hbvm",
|
||||
|
@ -200,12 +216,11 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "home"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
|
||||
name = "hbxrt"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
"hbvm",
|
||||
"nix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -215,12 +230,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.11.0"
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"either",
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -235,31 +250,6 @@ version = "0.2.149"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da2479e8c062e40bf0066ffa0bc823de0a9368974af99c9f6df941d2c231e03f"
|
||||
|
||||
[[package]]
|
||||
name = "lua-src"
|
||||
version = "546.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c26d4af78361e025a3d03a2b964cd1592aff7495f4d4f7947218c084c6fdca8"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "luajit-src"
|
||||
version = "210.4.8+resty107baaf"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e05167e8b2a2185758d83ed23541e5bd8bce37072e4204e0ef2c9b322bc87c4e"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"which",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.6.4"
|
||||
|
@ -275,48 +265,6 @@ dependencies = [
|
|||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mlua"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c3a7a7ff4481ec91b951a733390211a8ace1caba57266ccb5f4d4966704e560"
|
||||
dependencies = [
|
||||
"bstr",
|
||||
"mlua-sys",
|
||||
"mlua_derive",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"rustc-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mlua-sys"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ec8b54eddb76093069cce9eeffb4c7b3a1a0fe66962d7bd44c4867928149ca3"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"lua-src",
|
||||
"luajit-src",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mlua_derive"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f359220f24e6452dd82a3f50d7242d4aab822b5594798048e953d7a9e0314c6"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"once_cell",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex",
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.27.1"
|
||||
|
@ -370,36 +318,6 @@ version = "0.2.13"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.69"
|
||||
|
@ -419,59 +337,38 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.2"
|
||||
name = "rhai"
|
||||
version = "1.16.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||
checksum = "206cee941730eaf90a22c84235b25193df661393688162e15551164f92f09eca"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
"ahash",
|
||||
"bitflags",
|
||||
"instant",
|
||||
"num-traits",
|
||||
"once_cell",
|
||||
"rhai_codegen",
|
||||
"smallvec",
|
||||
"smartstring",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.3"
|
||||
name = "rhai_codegen"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||
checksum = "853977598f084a492323fe2f7896b4100a86284ee8473612de60021ea341310f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.189"
|
||||
|
@ -501,6 +398,29 @@ dependencies = [
|
|||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
|
||||
|
||||
[[package]]
|
||||
name = "smartstring"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"static_assertions",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
|
@ -533,6 +453,15 @@ dependencies = [
|
|||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tiny-keccak"
|
||||
version = "2.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
|
||||
dependencies = [
|
||||
"crunchy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.40"
|
||||
|
@ -593,82 +522,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.4.2"
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
|
||||
dependencies = [
|
||||
"either",
|
||||
"home",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "with_builtin_macros"
|
||||
|
@ -698,3 +555,23 @@ dependencies = [
|
|||
"color-eyre",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ffc046c9f849405a42c87e82e2f2f861d1f0a06b855910c76c2bd1e87be900c"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "246c000cfc5f942bac7ff99fde24a9ebb589d92e024bc758c6c733c15a02a73e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.38",
|
||||
]
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["hbasm", "hbbytecode", "hbvm", "hbxrt", "xtask"]
|
||||
members = ["hbasm", "hbbytecode", "hbvm", "hbvm_aos_on_linux", "hbxrt", "xtask"]
|
||||
|
|
|
@ -5,8 +5,5 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
paste = "1.0"
|
||||
rhai = "1.16"
|
||||
with_builtin_macros = "0.0.3"
|
||||
|
||||
[dependencies.mlua]
|
||||
version = "0.9"
|
||||
features = ["luajit52", "macros", "vendored"]
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
li8(r1, 60)
|
||||
li8(r2, 69)
|
||||
eca()
|
|
@ -1,8 +0,0 @@
|
|||
label "label" -- set named label
|
||||
local a = label {} -- unassigned label
|
||||
|
||||
jmp16("label")
|
||||
a:here() -- assign label
|
||||
jmp16(a)
|
||||
|
||||
addi8(r3, r4, 5)
|
13
hbasm/examples/ableos/main.rhai
Normal file
13
hbasm/examples/ableos/main.rhai
Normal file
|
@ -0,0 +1,13 @@
|
|||
import "hbasm/examples/ableos/std" as std;
|
||||
|
||||
fn main(){
|
||||
std::Error(":+)");
|
||||
std::Warn("Your mom fell in a well!");
|
||||
std::Info("Hello, world!");
|
||||
std::Debug("ABC");
|
||||
std::Trace("Trace Deez");
|
||||
|
||||
tx();
|
||||
}
|
||||
|
||||
main();
|
24
hbasm/examples/ableos/std.rhai
Normal file
24
hbasm/examples/ableos/std.rhai
Normal file
|
@ -0,0 +1,24 @@
|
|||
fn ipc_send(buffer_id, mem_addr, length){
|
||||
// set the ecall
|
||||
li8(r1, 3);
|
||||
// Set the buffer ID to be the BufferID
|
||||
li64(r2, buffer_id);
|
||||
lra(r3, r0, mem_addr);
|
||||
// set the length
|
||||
li64(r4, length);
|
||||
// ecall
|
||||
eca();
|
||||
}
|
||||
|
||||
private fn log(log_level, string){
|
||||
let str = data::str(string);
|
||||
ipc_send(1, str, str.len);
|
||||
}
|
||||
|
||||
fn Error(string) {log(0, string);}
|
||||
fn Warn(string) {log(1, string);}
|
||||
fn Info(string) {log(2, string);}
|
||||
// Due to rhai limitations this cannot be debug
|
||||
// because of this all of the log levels are upper case
|
||||
fn Debug(string) {log(3, string);}
|
||||
fn Trace(string) {log(4, string);}
|
9
hbasm/examples/hello-linux.rhai
Normal file
9
hbasm/examples/hello-linux.rhai
Normal file
|
@ -0,0 +1,9 @@
|
|||
let hello = data::str("Hello, world!");
|
||||
|
||||
li8 (r1, 1); // Write syscall
|
||||
li8 (r2, 1); // Stdout FD
|
||||
lra16 (r3, r0, hello); // String buffer
|
||||
li8 (r4, hello.len); // String length
|
||||
eca (); // System call
|
||||
|
||||
tx (); // End program
|
33
hbasm/examples/macros.rhai
Normal file
33
hbasm/examples/macros.rhai
Normal file
|
@ -0,0 +1,33 @@
|
|||
li8(r1, 69);
|
||||
li8(r2, 0);
|
||||
|
||||
if_eq(r1, r2,
|
||||
|| puts("Equals!"),
|
||||
|| puts("Not equals!"),
|
||||
);
|
||||
|
||||
|
||||
tx(); // END OF MAIN
|
||||
|
||||
/// Inline function – write text to stdout
|
||||
fn puts(string) {
|
||||
let d = data::str(string);
|
||||
li8 (r1, 1); // Write syscall
|
||||
li8 (r2, 1); // Stdout handle
|
||||
lra16 (r3, r0, d);
|
||||
li64 (r4, d.len);
|
||||
eca ();
|
||||
}
|
||||
|
||||
fn if_eq(a, b, thenblk, elseblk) {
|
||||
let elselbl = declabel();
|
||||
let endlbl = declabel();
|
||||
|
||||
jne(a, b, elselbl);
|
||||
thenblk.call();
|
||||
jmp16(endlbl);
|
||||
|
||||
elselbl.here();
|
||||
elseblk.call();
|
||||
endlbl.here();
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
use mlua::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, Default, FromLua)]
|
||||
pub struct ArrayList<T>(pub Vec<T>);
|
||||
impl<T> LuaUserData for ArrayList<T>
|
||||
where
|
||||
T: for<'lua> FromLua<'lua> + for<'lua> IntoLua<'lua> + Clone + std::fmt::Debug,
|
||||
{
|
||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_meta_method(
|
||||
LuaMetaMethod::Index,
|
||||
|lua, this, index: LuaInteger| match this.0.get(
|
||||
(index as usize)
|
||||
.checked_sub(1)
|
||||
.ok_or_else(|| mlua::Error::runtime("Invalid index: 0"))?,
|
||||
) {
|
||||
Some(i) => i.clone().into_lua(lua),
|
||||
None => Ok(LuaValue::Nil),
|
||||
},
|
||||
);
|
||||
|
||||
methods.add_meta_method_mut(
|
||||
LuaMetaMethod::NewIndex,
|
||||
|_, this, (index, val): (LuaInteger, T)| match this.0.get_mut(
|
||||
(index as usize)
|
||||
.checked_sub(1)
|
||||
.ok_or_else(|| mlua::Error::runtime("Invalid index: 0"))?,
|
||||
) {
|
||||
Some(x) => {
|
||||
*x = val;
|
||||
Ok(())
|
||||
}
|
||||
None => Err(mlua::Error::runtime(format!(
|
||||
"Index out of bounds: length = {}, index = {index}",
|
||||
this.0.len()
|
||||
))),
|
||||
},
|
||||
);
|
||||
|
||||
methods.add_meta_method(LuaMetaMethod::Len, |_, this, ()| Ok(this.0.len()));
|
||||
methods.add_meta_method(LuaMetaMethod::ToString, |_, this, ()| {
|
||||
Ok(format!("{this:?}"))
|
||||
});
|
||||
methods.add_method_mut("push", |_, this, val: T| {
|
||||
this.0.push(val);
|
||||
Ok(())
|
||||
});
|
||||
methods.add_method_mut("pop", |lua, this, ()| match this.0.pop() {
|
||||
Some(val) => val.into_lua(lua),
|
||||
None => Ok(LuaValue::Nil),
|
||||
});
|
||||
}
|
||||
}
|
85
hbasm/src/data.rs
Normal file
85
hbasm/src/data.rs
Normal file
|
@ -0,0 +1,85 @@
|
|||
use rhai::{CustomType, Engine, ImmutableString};
|
||||
|
||||
use {
|
||||
crate::{object::SymbolRef, SharedObject},
|
||||
rhai::Module,
|
||||
};
|
||||
|
||||
macro_rules! gen_data_insertions {
|
||||
($module:expr, $obj:expr, [$($ty:ident),* $(,)?] $(,)?) => {{
|
||||
let (module, obj) = ($module, $obj);
|
||||
$({
|
||||
let obj = ::std::rc::Rc::clone(obj);
|
||||
let hash = module.set_native_fn(stringify!($ty), move |arr: ::rhai::Array| {
|
||||
let obj = &mut *obj.borrow_mut();
|
||||
let symbol = obj.symbol($crate::object::Section::Data);
|
||||
|
||||
obj.sections
|
||||
.data
|
||||
.reserve(arr.len() * ::std::mem::size_of::<$ty>());
|
||||
|
||||
for item in arr {
|
||||
obj.sections.data.extend(
|
||||
match item.as_int() {
|
||||
Ok(num) => $ty::try_from(num).map_err(|_| "i64".to_owned()),
|
||||
Err(ty) => Err(ty.to_owned()),
|
||||
}
|
||||
.map_err(|err| {
|
||||
::rhai::EvalAltResult::ErrorMismatchDataType(
|
||||
stringify!($ty).to_owned(),
|
||||
err,
|
||||
::rhai::Position::NONE,
|
||||
)
|
||||
})?
|
||||
.to_le_bytes(),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(DataRef {
|
||||
symbol,
|
||||
len: obj.sections.data.len() - symbol.0,
|
||||
})
|
||||
});
|
||||
|
||||
module.update_fn_namespace(hash, ::rhai::FnNamespace::Global);
|
||||
})*
|
||||
}};
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct DataRef {
|
||||
pub symbol: SymbolRef,
|
||||
pub len: usize,
|
||||
}
|
||||
|
||||
impl CustomType for DataRef {
|
||||
fn build(mut builder: rhai::TypeBuilder<Self>) {
|
||||
builder
|
||||
.with_name("DataRef")
|
||||
.with_get("symbol", |this: &mut Self| this.symbol)
|
||||
.with_get("len", |this: &mut Self| this.len as u64 as i64);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn module(engine: &mut Engine, obj: SharedObject) -> Module {
|
||||
let mut module = Module::new();
|
||||
gen_data_insertions!(&mut module, &obj, [i8, i16, i32, i64]);
|
||||
|
||||
{
|
||||
let hash = module.set_native_fn("str", move |s: ImmutableString| {
|
||||
let obj = &mut *obj.borrow_mut();
|
||||
let symbol = obj.symbol(crate::object::Section::Data);
|
||||
|
||||
obj.sections.data.extend(s.as_bytes());
|
||||
Ok(DataRef {
|
||||
symbol,
|
||||
len: s.len(),
|
||||
})
|
||||
});
|
||||
|
||||
module.update_fn_namespace(hash, rhai::FnNamespace::Global);
|
||||
}
|
||||
|
||||
engine.build_type::<DataRef>();
|
||||
module
|
||||
}
|
386
hbasm/src/ins.rs
386
hbasm/src/ins.rs
|
@ -1,194 +1,226 @@
|
|||
use {
|
||||
crate::arraylist::ArrayList,
|
||||
mlua::{prelude::*, Result, Scope},
|
||||
crate::object::Object,
|
||||
rhai::{FnNamespace, Module},
|
||||
std::{cell::RefCell, rc::Rc},
|
||||
};
|
||||
|
||||
mod opsty {
|
||||
pub type R = i8;
|
||||
mod optypes {
|
||||
use {
|
||||
crate::{
|
||||
label::UnboundLabel,
|
||||
object::{Object, RelocKey, RelocType, SymbolRef},
|
||||
},
|
||||
rhai::{Dynamic, EvalAltResult, ImmutableString, Position},
|
||||
};
|
||||
|
||||
pub type R = u8;
|
||||
pub type B = i8;
|
||||
pub type H = i16;
|
||||
pub type W = i32;
|
||||
pub type D = i64;
|
||||
pub type A = i64;
|
||||
pub type O<'lua> = super::LuaValue<'lua>;
|
||||
pub type P<'lua> = super::LuaValue<'lua>;
|
||||
}
|
||||
|
||||
macro_rules! gen_insert {
|
||||
($($plain:ident),* $(,)?) => {
|
||||
macro_rules! insert {
|
||||
$(
|
||||
($label:expr, $lua:expr, $symrt:expr, $code:expr, $plain) => {
|
||||
$code.0.extend($label.to_le_bytes());
|
||||
};
|
||||
)*
|
||||
pub type A = Dynamic;
|
||||
pub type O = Dynamic;
|
||||
pub type P = Dynamic;
|
||||
|
||||
($label:expr, $lua:expr, $symrt:expr, $code:expr, O) => {
|
||||
insert_label_ref::<4>(
|
||||
$label,
|
||||
$lua,
|
||||
&$symrt,
|
||||
&mut $code.0,
|
||||
)?;
|
||||
};
|
||||
|
||||
($label:expr, $lua:expr, $symrt:expr, $code:expr, P) => {
|
||||
insert_label_ref::<2>(
|
||||
$label,
|
||||
$lua,
|
||||
&$symrt,
|
||||
&mut $code.0,
|
||||
)?;
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
gen_insert!(R, B, H, W, D, A);
|
||||
|
||||
macro_rules! generic_ins {
|
||||
{
|
||||
($lua:expr, $scope:expr);
|
||||
$($name:ident($($param_i:ident : $param_ty:ident),*);)*
|
||||
} => {{
|
||||
let lua = $lua;
|
||||
let scope = $scope;
|
||||
|
||||
let code = $lua.globals()
|
||||
.get::<_, LuaTable>("_CODE")?
|
||||
.get::<_, LuaAnyUserData>("text")?;
|
||||
|
||||
let symrt = $lua.globals()
|
||||
.get::<_, LuaTable>("_SYM_REPLS")?;
|
||||
|
||||
lua.globals().set(
|
||||
"_GENERIC",
|
||||
lua.create_table_from([$((
|
||||
stringify!($name),
|
||||
#[allow(unused)]
|
||||
{
|
||||
let code = code.clone();
|
||||
let symrt = symrt.clone();
|
||||
scope.create_function_mut(move |lua, (opcode, $($param_i),*): (u8, $(opsty::$param_ty),*)| {
|
||||
let mut code = code.borrow_mut::<ArrayList<u8>>()?;
|
||||
code.0.push(opcode);
|
||||
$(insert!($param_i, lua, symrt, code, $param_ty);)*
|
||||
Ok(())
|
||||
})?
|
||||
}
|
||||
)),*])?
|
||||
)?;
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! ins {
|
||||
{
|
||||
$lua:expr;
|
||||
{$($opcode:expr, $mnemonic:ident, $ty:ident, $_doc:literal;)*}
|
||||
} => {{
|
||||
use std::fmt::Write;
|
||||
|
||||
let lua = $lua;
|
||||
let mut code = String::new();
|
||||
|
||||
$({
|
||||
paste::paste! {
|
||||
let name = match stringify!([<$mnemonic:lower>]) {
|
||||
"and" => "and_",
|
||||
"or" => "or_",
|
||||
"not" => "not_",
|
||||
name => name,
|
||||
};
|
||||
pub fn insert_reloc(
|
||||
obj: &mut Object,
|
||||
ty: RelocType,
|
||||
val: &Dynamic,
|
||||
) -> Result<(), EvalAltResult> {
|
||||
match () {
|
||||
_ if val.is::<SymbolRef>() => {
|
||||
obj.relocation(RelocKey::Symbol(val.clone_cast::<SymbolRef>().0), ty)
|
||||
}
|
||||
|
||||
writeln!(
|
||||
code,
|
||||
"function {name}(...) _GENERIC.{ty}({opcode}, ...) end",
|
||||
ty = stringify!($ty).to_lowercase(),
|
||||
opcode = $opcode,
|
||||
).unwrap();
|
||||
|
||||
})*
|
||||
|
||||
lua.load(code).exec()?;
|
||||
}};
|
||||
}
|
||||
|
||||
pub fn setup<'lua, 'scope>(lua: &'lua Lua, scope: &Scope<'lua, 'scope>) -> Result<()>
|
||||
where
|
||||
'lua: 'scope,
|
||||
{
|
||||
generic_ins! {
|
||||
(lua, scope);
|
||||
rr (o0: R, o1: R);
|
||||
rrr (o0: R, o1: R, o2: R);
|
||||
rrrr(o0: R, o1: R, o2: R, o3: R);
|
||||
rrb (o0: R, o1: R, o2: B);
|
||||
rrh (o0: R, o1: R, o2: H);
|
||||
rrw (o0: R, o1: R, o2: W);
|
||||
rrd (o0: R, o1: R, o2: D);
|
||||
rb (o0: R, o1: B);
|
||||
rh (o0: R, o1: H);
|
||||
rw (o0: R, o1: W);
|
||||
rd (o0: R, o1: D);
|
||||
rrah(o0: R, o1: R, o2: A, o3: H);
|
||||
rroh(o0: R, o1: R, o2: O, o3: H);
|
||||
rrph(o0: R, o1: R, o2: P, o3: H);
|
||||
rro (o0: R, o1: R, o2: O);
|
||||
rrp (o0: R, o1: R, r2: P);
|
||||
o (o0: O);
|
||||
p (o0: P);
|
||||
n ();
|
||||
}
|
||||
|
||||
with_builtin_macros::with_builtin! {
|
||||
let $spec = include_from_root!("../hbbytecode/instructions.in") in {
|
||||
ins!(lua; { $spec });
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn insert_label_ref<const SIZE: usize>(
|
||||
label: LuaValue,
|
||||
lua: &Lua,
|
||||
symrt: &LuaTable,
|
||||
code: &mut Vec<u8>,
|
||||
) -> Result<()> {
|
||||
match label {
|
||||
LuaValue::Integer(offset) => {
|
||||
if match SIZE {
|
||||
2 => i16::try_from(offset).map(|o| code.extend(o.to_le_bytes())),
|
||||
4 => i32::try_from(offset).map(|o| code.extend(o.to_le_bytes())),
|
||||
s => {
|
||||
return Err(mlua::Error::runtime(format!(
|
||||
"Invalid offset size (expected 2 or 4 bytes, got {s})"
|
||||
)));
|
||||
_ if val.is::<UnboundLabel>() => {
|
||||
obj.relocation(RelocKey::Symbol(val.clone_cast::<UnboundLabel>().0), ty)
|
||||
}
|
||||
_ if val.is::<DataRef>() => {
|
||||
obj.relocation(RelocKey::Symbol(val.clone_cast::<DataRef>().symbol.0), ty)
|
||||
}
|
||||
_ if val.is_string() => {
|
||||
obj.relocation(RelocKey::Label(val.clone_cast::<ImmutableString>()), ty)
|
||||
}
|
||||
_ if val.is_int() => {
|
||||
let int = val.clone_cast::<i64>();
|
||||
match ty {
|
||||
RelocType::Rel32 => obj.sections.text.extend((int as i32).to_le_bytes()),
|
||||
RelocType::Rel16 => obj.sections.text.extend((int as i16).to_le_bytes()),
|
||||
RelocType::Abs64 => obj.sections.text.extend(int.to_le_bytes()),
|
||||
}
|
||||
}
|
||||
.is_err()
|
||||
{
|
||||
return Err(mlua::Error::runtime("Failed to cast offset"));
|
||||
_ => {
|
||||
return Err(EvalAltResult::ErrorMismatchDataType(
|
||||
"SybolRef, UnboundLabel, String or Int".to_owned(),
|
||||
val.type_name().to_owned(),
|
||||
Position::NONE,
|
||||
))
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
LuaValue::UserData(ud) => {
|
||||
symrt.set(
|
||||
code.len() + 1,
|
||||
lua.create_table_from([("label", ud.get("id")?), ("size", SIZE)])?,
|
||||
)?;
|
||||
code.extend([0; SIZE]);
|
||||
}
|
||||
LuaValue::String(_) => {
|
||||
symrt.set(
|
||||
code.len() + 1,
|
||||
lua.create_table_from([("label", label), ("size", SIZE.into_lua(lua)?)])?,
|
||||
)?;
|
||||
code.extend([0; SIZE]);
|
||||
}
|
||||
_ => return Err(mlua::Error::runtime("Invalid label type")),
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Ok(())
|
||||
macro_rules! gen_insert {
|
||||
(le_bytes: [$($lety:ident),* $(,)?]) => {
|
||||
macro_rules! insert {
|
||||
$(($thing:expr, $obj: expr, $lety) => {
|
||||
$obj.sections.text.extend($thing.to_le_bytes());
|
||||
};)*
|
||||
|
||||
($thing:expr, $obj:expr, A) => {
|
||||
$crate::ins::optypes::insert_reloc(
|
||||
$obj,
|
||||
$crate::object::RelocType::Abs64,
|
||||
$thing
|
||||
)?
|
||||
};
|
||||
($thing:expr, $obj:expr, O) => {
|
||||
$crate::ins::optypes::insert_reloc(
|
||||
$obj,
|
||||
$crate::object::RelocType::Rel32,
|
||||
$thing
|
||||
)?
|
||||
};
|
||||
($thing:expr, $obj:expr, P) => {
|
||||
$crate::ins::optypes::insert_reloc(
|
||||
$obj,
|
||||
$crate::object::RelocType::Rel16,
|
||||
$thing
|
||||
)?
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
gen_insert!(le_bytes: [R, B, H, W, D]);
|
||||
|
||||
#[allow(clippy::single_component_path_imports)]
|
||||
pub(super) use insert;
|
||||
|
||||
use crate::data::DataRef;
|
||||
}
|
||||
|
||||
mod rity {
|
||||
pub use super::optypes::{A, O, P, R};
|
||||
pub type B = i64;
|
||||
pub type H = i64;
|
||||
pub type W = i64;
|
||||
pub type D = i64;
|
||||
}
|
||||
|
||||
mod generic {
|
||||
use {crate::object::Object, rhai::EvalAltResult};
|
||||
|
||||
pub(super) fn convert_op<A, B>(from: A) -> Result<B, EvalAltResult>
|
||||
where
|
||||
B: TryFrom<A>,
|
||||
<B as TryFrom<A>>::Error: std::error::Error + Sync + Send + 'static,
|
||||
{
|
||||
B::try_from(from).map_err(|e| {
|
||||
EvalAltResult::ErrorSystem("Data conversion error".to_owned(), Box::new(e))
|
||||
})
|
||||
}
|
||||
|
||||
macro_rules! gen_ins {
|
||||
($($($name:ident : $ty:ty),*;)*) => {
|
||||
paste::paste! {
|
||||
$(#[inline]
|
||||
pub fn [<$($ty:lower)*>](
|
||||
obj: &mut Object,
|
||||
opcode: u8,
|
||||
$($name: $crate::ins::optypes::$ty),*,
|
||||
) -> Result<(), EvalAltResult> {
|
||||
obj.sections.text.push(opcode);
|
||||
$($crate::ins::optypes::insert!(&$name, obj, $ty);)*
|
||||
Ok(())
|
||||
})*
|
||||
|
||||
macro_rules! gen_ins_fn {
|
||||
$(($obj:expr, $opcode:expr, [<$($ty)*>]) => {
|
||||
move |$($name: $crate::ins::rity::$ty),*| {
|
||||
$crate::ins::generic::[<$($ty:lower)*>](
|
||||
&mut *$obj.borrow_mut(),
|
||||
$opcode,
|
||||
$(
|
||||
$crate::ins::generic::convert_op::<
|
||||
_,
|
||||
$crate::ins::optypes::$ty
|
||||
>($name)?
|
||||
),*
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
};)*
|
||||
|
||||
($obj:expr, $opcode:expr, N) => {
|
||||
move || {
|
||||
$crate::ins::generic::n(&mut *$obj.borrow_mut(), $opcode);
|
||||
Ok(())
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn n(obj: &mut Object, opcode: u8) {
|
||||
obj.sections.text.push(opcode);
|
||||
}
|
||||
|
||||
gen_ins! {
|
||||
o0: R, o1: R;
|
||||
o0: R, o1: R, o2: R;
|
||||
o0: R, o1: R, o2: R, o3: R;
|
||||
o0: R, o1: R, o2: B;
|
||||
o0: R, o1: R, o2: H;
|
||||
o0: R, o1: R, o2: W;
|
||||
o0: R, o1: R, o2: D;
|
||||
o0: R, o1: B;
|
||||
o0: R, o1: H;
|
||||
o0: R, o1: W;
|
||||
o0: R, o1: D;
|
||||
o0: R, o1: R, o2: A;
|
||||
o0: R, o1: R, o2: A, o3: H;
|
||||
o0: R, o1: R, o2: O, o3: H;
|
||||
o0: R, o1: R, o2: P, o3: H;
|
||||
o0: R, o1: R, o2: O;
|
||||
o0: R, o1: R, o2: P;
|
||||
o0: O;
|
||||
o0: P;
|
||||
}
|
||||
|
||||
#[allow(clippy::single_component_path_imports)]
|
||||
pub(super) use gen_ins_fn;
|
||||
}
|
||||
|
||||
macro_rules! instructions {
|
||||
(
|
||||
($module:expr, $obj:expr $(,)?)
|
||||
{ $($opcode:expr, $mnemonic:ident, $ops:ident, $doc:literal;)* }
|
||||
) => {{
|
||||
let (module, obj) = ($module, $obj);
|
||||
$({
|
||||
let obj = Rc::clone(&obj);
|
||||
let hash = module.set_native_fn(
|
||||
paste::paste!(stringify!([<$mnemonic:lower>])),
|
||||
generic::gen_ins_fn!(
|
||||
obj,
|
||||
$opcode,
|
||||
$ops
|
||||
)
|
||||
);
|
||||
|
||||
module.update_fn_namespace(hash, FnNamespace::Global);
|
||||
})*
|
||||
}};
|
||||
}
|
||||
|
||||
pub fn setup(module: &mut Module, obj: Rc<RefCell<Object>>) {
|
||||
with_builtin_macros::with_builtin! {
|
||||
let $spec = include_from_root!("../hbbytecode/instructions.in") in {
|
||||
instructions!((module, obj) { $spec });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,91 +1,76 @@
|
|||
use {
|
||||
crate::{arraylist::ArrayList, Labels},
|
||||
mlua::{Result, prelude::*},
|
||||
crate::SharedObject,
|
||||
rhai::{Engine, ImmutableString, Module},
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, FromLua)]
|
||||
pub struct UnassignedLabel(pub usize);
|
||||
impl LuaUserData for UnassignedLabel {
|
||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("id", |_, this| Ok(this.0));
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct UnboundLabel(pub usize);
|
||||
|
||||
pub fn setup(engine: &mut Engine, module: &mut Module, object: SharedObject) {
|
||||
{
|
||||
let object = SharedObject::clone(&object);
|
||||
let hash = module.set_native_fn("label", move || {
|
||||
let mut obj = object.borrow_mut();
|
||||
let symbol = obj.symbol(crate::object::Section::Text);
|
||||
Ok(symbol)
|
||||
});
|
||||
|
||||
module.update_fn_namespace(hash, rhai::FnNamespace::Global);
|
||||
}
|
||||
|
||||
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
|
||||
methods.add_method("here", |lua, this, ()| {
|
||||
match lua
|
||||
.globals()
|
||||
.get::<_, LuaUserDataRefMut<Labels>>("_LABELS")?
|
||||
.0
|
||||
.get_mut(
|
||||
this.0
|
||||
.checked_sub(1)
|
||||
.ok_or_else(|| mlua::Error::runtime("Invalid label"))?,
|
||||
) {
|
||||
Some(entry) => {
|
||||
*entry = Some(
|
||||
lua.globals()
|
||||
.get::<_, LuaTable>("_CODE")?
|
||||
.get::<_, LuaUserDataRef<ArrayList<u8>>>("text")?
|
||||
.0
|
||||
.len(),
|
||||
);
|
||||
{
|
||||
let object = SharedObject::clone(&object);
|
||||
let hash = module.set_native_fn("label", move |label: ImmutableString| {
|
||||
let mut obj = object.borrow_mut();
|
||||
let symbol = obj.symbol(crate::object::Section::Text);
|
||||
obj.labels.insert(label, symbol.0);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
None => Err(mlua::Error::runtime("Invalid label")),
|
||||
}
|
||||
Ok(symbol)
|
||||
});
|
||||
|
||||
module.update_fn_namespace(hash, rhai::FnNamespace::Global);
|
||||
}
|
||||
|
||||
{
|
||||
let object = SharedObject::clone(&object);
|
||||
let hash = module.set_native_fn("declabel", move || {
|
||||
let mut obj = object.borrow_mut();
|
||||
|
||||
let index = obj.symbols.len();
|
||||
obj.symbols.push(None);
|
||||
|
||||
Ok(UnboundLabel(index))
|
||||
});
|
||||
|
||||
module.update_fn_namespace(hash, rhai::FnNamespace::Global);
|
||||
}
|
||||
|
||||
{
|
||||
let object = SharedObject::clone(&object);
|
||||
let hash = module.set_native_fn("declabel", move |label: ImmutableString| {
|
||||
let mut obj = object.borrow_mut();
|
||||
|
||||
let index = obj.symbols.len();
|
||||
obj.symbols.push(None);
|
||||
obj.labels.insert(label, index);
|
||||
|
||||
Ok(UnboundLabel(index))
|
||||
});
|
||||
|
||||
module.update_fn_namespace(hash, rhai::FnNamespace::Global);
|
||||
}
|
||||
|
||||
{
|
||||
module.set_native_fn("here", move |label: UnboundLabel| {
|
||||
let mut obj = object.borrow_mut();
|
||||
obj.symbols[label.0] = Some(crate::object::SymbolEntry {
|
||||
location: crate::object::Section::Text,
|
||||
offset: obj.sections.text.len(),
|
||||
});
|
||||
|
||||
Ok(())
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, FromLua)]
|
||||
pub struct Label(pub usize);
|
||||
impl LuaUserData for Label {
|
||||
fn add_fields<'lua, F: LuaUserDataFields<'lua, Self>>(fields: &mut F) {
|
||||
fields.add_field_method_get("id", |_, this| Ok(this.0));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn label<'lua>(lua: &'lua Lua, val: LuaValue<'lua>) -> Result<LuaValue<'lua>> {
|
||||
let globals = lua.globals();
|
||||
let mut labels = globals.get::<_, LuaUserDataRefMut<Labels>>("_LABELS")?;
|
||||
|
||||
let code_ix = globals
|
||||
.get::<_, LuaTable>("_CODE")?
|
||||
.get::<_, LuaUserDataRefMut<ArrayList<u8>>>("text")?
|
||||
.0
|
||||
.len();
|
||||
|
||||
match val {
|
||||
LuaValue::Table(_) => {
|
||||
labels.0.push(None);
|
||||
Ok(LuaValue::UserData(
|
||||
lua.create_userdata(UnassignedLabel(labels.0.len()))?,
|
||||
))
|
||||
}
|
||||
LuaValue::String(str) => {
|
||||
labels.0.push(Some(code_ix + 1));
|
||||
globals
|
||||
.get::<_, LuaTable>("_SYM_TABLE")?
|
||||
.set(str, labels.0.len())?;
|
||||
|
||||
Ok(LuaValue::UserData(
|
||||
lua.create_userdata(Label(labels.0.len()))?,
|
||||
))
|
||||
}
|
||||
LuaNil => {
|
||||
labels.0.push(Some(code_ix + 1));
|
||||
Ok(LuaValue::UserData(
|
||||
lua.create_userdata(Label(labels.0.len()))?,
|
||||
))
|
||||
}
|
||||
_ => Err(mlua::Error::BadArgument {
|
||||
to: Some("label".into()),
|
||||
pos: 1,
|
||||
name: None,
|
||||
cause: std::sync::Arc::new(mlua::Error::runtime(
|
||||
"Unsupported type (nil and string are only supported)",
|
||||
)),
|
||||
}),
|
||||
}
|
||||
|
||||
engine.register_type_with_name::<UnboundLabel>("UnboundLabel");
|
||||
}
|
||||
|
|
45
hbasm/src/lib.rs
Normal file
45
hbasm/src/lib.rs
Normal file
|
@ -0,0 +1,45 @@
|
|||
mod data;
|
||||
mod ins;
|
||||
mod label;
|
||||
mod linker;
|
||||
mod object;
|
||||
|
||||
use {
|
||||
object::Object,
|
||||
rhai::{Engine, Module},
|
||||
std::{cell::RefCell, rc::Rc},
|
||||
};
|
||||
|
||||
type SharedObject = Rc<RefCell<Object>>;
|
||||
|
||||
pub fn assembler(
|
||||
linkout: &mut impl std::io::Write,
|
||||
loader: impl FnOnce(&mut Engine) -> Result<(), Box<rhai::EvalAltResult>>,
|
||||
) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let mut engine = Engine::new();
|
||||
let mut module = Module::new();
|
||||
let obj = Rc::new(RefCell::new(Object::default()));
|
||||
ins::setup(&mut module, Rc::clone(&obj));
|
||||
label::setup(&mut engine, &mut module, Rc::clone(&obj));
|
||||
|
||||
// Registers
|
||||
for n in 0_u8..255 {
|
||||
module.set_var(format!("r{n}"), n);
|
||||
}
|
||||
|
||||
module.set_native_fn("reg", |n: i64| {
|
||||
Ok(u8::try_from(n).map_err(|_| {
|
||||
rhai::EvalAltResult::ErrorRuntime("Invalid register value".into(), rhai::Position::NONE)
|
||||
})?)
|
||||
});
|
||||
|
||||
module.set_native_fn("as_i64", |n: u8| Ok(n as i64));
|
||||
|
||||
let datamod = Rc::new(data::module(&mut engine, SharedObject::clone(&obj)));
|
||||
engine.register_global_module(Rc::new(module));
|
||||
engine.register_static_module("data", datamod);
|
||||
engine.register_type_with_name::<object::SymbolRef>("SymbolRef");
|
||||
loader(&mut engine)?;
|
||||
linker::link(obj, linkout)?;
|
||||
Ok(())
|
||||
}
|
|
@ -1,44 +1,35 @@
|
|||
use mlua::prelude::*;
|
||||
use {
|
||||
crate::{
|
||||
object::{RelocKey, RelocType, Section},
|
||||
SharedObject,
|
||||
},
|
||||
std::io::Write,
|
||||
};
|
||||
|
||||
pub fn link(
|
||||
symrt: LuaTable,
|
||||
symtab: LuaTable,
|
||||
labels: &[Option<usize>],
|
||||
code: &mut [u8],
|
||||
out: &mut impl std::io::Write,
|
||||
) -> mlua::Result<()> {
|
||||
for item in symrt.pairs::<usize, LuaTable>() {
|
||||
let (loc, val) = item?;
|
||||
let size: usize = val.get("size")?;
|
||||
let dest = labels
|
||||
.get(
|
||||
match val.get::<_, LuaValue>("label")? {
|
||||
LuaValue::Integer(i) => i,
|
||||
LuaValue::String(s) => symtab.get(s)?,
|
||||
_ => {
|
||||
return Err(mlua::Error::runtime(
|
||||
"Invalid symbol type (int or string expected)",
|
||||
))
|
||||
}
|
||||
} as usize
|
||||
- 1,
|
||||
)
|
||||
.copied()
|
||||
.flatten()
|
||||
.ok_or_else(|| mlua::Error::runtime("Invalid label"))?;
|
||||
pub fn link(object: SharedObject, out: &mut impl Write) -> std::io::Result<()> {
|
||||
let obj = &mut *object.borrow_mut();
|
||||
for (&loc, entry) in &obj.relocs {
|
||||
let value = match &entry.key {
|
||||
RelocKey::Symbol(sym) => obj.symbols[*sym],
|
||||
RelocKey::Label(label) => obj.symbols[obj.labels[label]],
|
||||
}
|
||||
.ok_or_else(|| std::io::Error::other("Invalid symbol"))?;
|
||||
|
||||
let loc = loc - 1;
|
||||
let dest = dest - 1;
|
||||
let offset = match value.location {
|
||||
Section::Text => value.offset,
|
||||
Section::Data => value.offset + obj.sections.text.len(),
|
||||
};
|
||||
|
||||
let offset = dest.wrapping_sub(loc);
|
||||
match size {
|
||||
4 => code[loc..loc + size].copy_from_slice(&(offset as u32).to_le_bytes()),
|
||||
2 => code[loc..loc + size].copy_from_slice(&(offset as u16).to_le_bytes()),
|
||||
_ => return Err(mlua::Error::runtime("Invalid symbol")),
|
||||
match entry.ty {
|
||||
RelocType::Rel32 => obj.sections.text[loc..loc + 4]
|
||||
.copy_from_slice(&((offset as isize - loc as isize) as i32).to_le_bytes()),
|
||||
RelocType::Rel16 => obj.sections.text[loc..loc + 2]
|
||||
.copy_from_slice(&((offset as isize - loc as isize) as i16).to_le_bytes()),
|
||||
RelocType::Abs64 => obj.sections.text[loc..loc + 8]
|
||||
.copy_from_slice(&(offset as isize - loc as isize).to_le_bytes()),
|
||||
}
|
||||
}
|
||||
|
||||
dbg!(&code);
|
||||
out.write_all(code)?;
|
||||
Ok(())
|
||||
out.write_all(&obj.sections.text)?;
|
||||
out.write_all(&obj.sections.data)
|
||||
}
|
||||
|
|
|
@ -1,54 +1,8 @@
|
|||
mod arraylist;
|
||||
mod ins;
|
||||
mod label;
|
||||
mod linker;
|
||||
use std::{io::stdout, path::PathBuf};
|
||||
|
||||
use {arraylist::ArrayList, mlua::{Result, prelude::*}, std::io::Read};
|
||||
|
||||
pub type Labels = ArrayList<Option<usize>>;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
let mut code = vec![];
|
||||
std::io::stdin().read_to_end(&mut code)?;
|
||||
|
||||
let lua = Lua::new();
|
||||
lua.scope(|scope| {
|
||||
// Global values
|
||||
let globals = lua.globals();
|
||||
globals.set(
|
||||
"_CODE",
|
||||
lua.create_table_from([
|
||||
("text", ArrayList::<u8>::default()),
|
||||
("data", ArrayList::<u8>::default()),
|
||||
])?,
|
||||
)?;
|
||||
|
||||
globals.set("_LABELS", Labels::default())?;
|
||||
globals.set("_SYM_TABLE", lua.create_table()?)?;
|
||||
globals.set("_SYM_REPLS", lua.create_table()?)?;
|
||||
|
||||
// Functions
|
||||
globals.set("label", lua.create_function(label::label)?)?;
|
||||
ins::setup(&lua, scope)?;
|
||||
|
||||
// Register symbols
|
||||
for n in 0..255 {
|
||||
globals.set(format!("r{n}"), n)?;
|
||||
}
|
||||
|
||||
lua.load(code).exec()?;
|
||||
|
||||
linker::link(
|
||||
globals.get("_SYM_REPLS")?,
|
||||
globals.get("_SYM_TABLE")?,
|
||||
&globals.get::<_, Labels>("_LABELS")?.0,
|
||||
&mut globals
|
||||
.get::<_, LuaTable>("_CODE")?
|
||||
.get::<_, LuaUserDataRefMut<ArrayList<u8>>>("text")?
|
||||
.0,
|
||||
&mut std::io::stdout(),
|
||||
)
|
||||
})?;
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let path = PathBuf::from(std::env::args().nth(1).ok_or("Missing path")?);
|
||||
hbasm::assembler(&mut stdout(), |engine| engine.run_file(path))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
77
hbasm/src/object.rs
Normal file
77
hbasm/src/object.rs
Normal file
|
@ -0,0 +1,77 @@
|
|||
use {rhai::ImmutableString, std::collections::HashMap};
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum Section {
|
||||
Text,
|
||||
Data,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct SymbolEntry {
|
||||
pub location: Section,
|
||||
pub offset: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum RelocKey {
|
||||
Symbol(usize),
|
||||
Label(ImmutableString),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum RelocType {
|
||||
Rel32,
|
||||
Rel16,
|
||||
Abs64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct RelocEntry {
|
||||
pub key: RelocKey,
|
||||
pub ty: RelocType,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Sections {
|
||||
pub text: Vec<u8>,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Object {
|
||||
pub sections: Sections,
|
||||
pub symbols: Vec<Option<SymbolEntry>>,
|
||||
pub labels: HashMap<ImmutableString, usize>,
|
||||
pub relocs: HashMap<usize, RelocEntry>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct SymbolRef(pub usize);
|
||||
|
||||
impl Object {
|
||||
pub fn symbol(&mut self, section: Section) -> SymbolRef {
|
||||
let section_buf = match section {
|
||||
Section::Text => &mut self.sections.text,
|
||||
Section::Data => &mut self.sections.data,
|
||||
};
|
||||
|
||||
self.symbols.push(Some(SymbolEntry {
|
||||
location: section,
|
||||
offset: section_buf.len(),
|
||||
}));
|
||||
|
||||
SymbolRef(self.symbols.len() - 1)
|
||||
}
|
||||
|
||||
pub fn relocation(&mut self, key: RelocKey, ty: RelocType) {
|
||||
self.relocs
|
||||
.insert(self.sections.text.len(), RelocEntry { key, ty });
|
||||
|
||||
self.sections.text.extend(match ty {
|
||||
RelocType::Rel32 => &[0_u8; 4] as &[u8],
|
||||
RelocType::Rel16 => &[0; 2],
|
||||
RelocType::Abs64 => &[0; 8],
|
||||
});
|
||||
}
|
||||
}
|
|
@ -34,11 +34,11 @@ define_items! {
|
|||
OpsRRB (OpR, OpR, OpB ),
|
||||
OpsRRH (OpR, OpR, OpH ),
|
||||
OpsRRW (OpR, OpR, OpW ),
|
||||
OpsRRD (OpR, OpR, OpD ),
|
||||
OpsRB (OpR, OpB ),
|
||||
OpsRH (OpR, OpH ),
|
||||
OpsRW (OpR, OpW ),
|
||||
OpsRD (OpR, OpD ),
|
||||
OpsRRD (OpR, OpR, OpD ),
|
||||
OpsRRA (OpR, OpR, OpA ),
|
||||
OpsRRAH (OpR, OpR, OpA, OpH),
|
||||
OpsRROH (OpR, OpR, OpO, OpH),
|
||||
|
|
|
@ -273,6 +273,8 @@ where
|
|||
let OpsRRP(a0, a1, ja) = self.decode();
|
||||
if self.read_reg(a0).cast::<u64>() != self.read_reg(a1).cast::<u64>() {
|
||||
self.pc = self.pcrel(ja, 3);
|
||||
} else {
|
||||
self.bump_pc::<OpsRRP, true>();
|
||||
}
|
||||
}
|
||||
JLTS => self.cond_jmp::<u64>(Ordering::Less),
|
||||
|
@ -453,7 +455,7 @@ where
|
|||
let OpsRR(tg, reg) = self.decode();
|
||||
let imm: T = self.decode();
|
||||
self.write_reg(tg, op(self.read_reg(reg).cast::<T>(), imm));
|
||||
self.bump_pc::<OpsRRD, false>();
|
||||
self.bump_pc::<OpsRR, false>();
|
||||
self.bump_pc::<T, true>();
|
||||
}
|
||||
|
||||
|
@ -527,9 +529,9 @@ where
|
|||
== expected
|
||||
{
|
||||
self.pc = self.pcrel(ja, 3);
|
||||
} else {
|
||||
self.bump_pc::<OpsRRP, true>();
|
||||
}
|
||||
|
||||
self.bump_pc::<OpsRRP, true>();
|
||||
}
|
||||
|
||||
/// Read register
|
||||
|
|
9
hbvm_aos_on_linux/Cargo.toml
Normal file
9
hbvm_aos_on_linux/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "hbvm_aos_on_linux"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
default-run = "hbvm_aos_on_linux"
|
||||
|
||||
[dependencies]
|
||||
hbvm.path = "../hbvm"
|
||||
nix = { version = "0.27", features = ["mman", "signal"] }
|
3
hbvm_aos_on_linux/readme.md
Normal file
3
hbvm_aos_on_linux/readme.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
As close to the AbleOS runtime as possible
|
||||
|
||||
useful for me to spec out things on my laptop
|
96
hbvm_aos_on_linux/src/main.rs
Normal file
96
hbvm_aos_on_linux/src/main.rs
Normal file
|
@ -0,0 +1,96 @@
|
|||
//! Holey Bytes Experimental Runtime
|
||||
mod mem;
|
||||
|
||||
use {
|
||||
hbvm::{mem::Address, Vm, VmRunOk},
|
||||
nix::sys::mman::{mmap, MapFlags, ProtFlags},
|
||||
std::{env::args, fs::File, num::NonZeroUsize, process::exit},
|
||||
};
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
eprintln!("== HB×RT (Holey Bytes Linux Runtime) v0.1 ==");
|
||||
eprintln!("[W] Currently supporting only flat images");
|
||||
|
||||
let Some(image_path) = args().nth(1) else {
|
||||
eprintln!("[E] Missing image path");
|
||||
exit(1);
|
||||
};
|
||||
|
||||
// Load program
|
||||
eprintln!("[I] Loading image from \"{image_path}\"");
|
||||
let file = File::open(image_path)?;
|
||||
let ptr = unsafe {
|
||||
mmap(
|
||||
None,
|
||||
NonZeroUsize::new(file.metadata()?.len() as usize).ok_or("File is empty")?,
|
||||
ProtFlags::PROT_READ,
|
||||
MapFlags::MAP_PRIVATE,
|
||||
Some(&file),
|
||||
0,
|
||||
)?
|
||||
};
|
||||
|
||||
eprintln!("[I] Image loaded at {ptr:p}");
|
||||
|
||||
// Execute program
|
||||
let mut vm = unsafe { Vm::<_, 0>::new(mem::HostMemory, Address::new(ptr as u64)) };
|
||||
|
||||
// Memory access fault handling
|
||||
unsafe {
|
||||
use nix::sys::signal;
|
||||
|
||||
extern "C" fn action(
|
||||
_: std::ffi::c_int,
|
||||
info: *mut nix::libc::siginfo_t,
|
||||
_: *mut std::ffi::c_void,
|
||||
) {
|
||||
unsafe {
|
||||
eprintln!("[E] Memory access fault at {:p}", (*info).si_addr());
|
||||
}
|
||||
}
|
||||
|
||||
signal::sigaction(
|
||||
signal::Signal::SIGSEGV,
|
||||
&nix::sys::signal::SigAction::new(
|
||||
signal::SigHandler::SigAction(action),
|
||||
signal::SaFlags::SA_NODEFER,
|
||||
nix::sys::signalfd::SigSet::empty(),
|
||||
),
|
||||
)?;
|
||||
}
|
||||
|
||||
let stat = loop {
|
||||
match vm.run() {
|
||||
Ok(VmRunOk::Breakpoint) => eprintln!(
|
||||
"[I] Hit breakpoint\nIP: {}\n== Registers ==\n{:?}",
|
||||
vm.pc, vm.registers
|
||||
),
|
||||
Ok(VmRunOk::Timer) => (),
|
||||
Ok(VmRunOk::Ecall) => {
|
||||
|
||||
// unsafe {
|
||||
// std::arch::asm!(
|
||||
// "syscall",
|
||||
// inlateout("rax") vm.registers[1].0,
|
||||
// in("rdi") vm.registers[2].0,
|
||||
// in("rsi") vm.registers[3].0,
|
||||
// in("rdx") vm.registers[4].0,
|
||||
// in("r10") vm.registers[5].0,
|
||||
// in("r8") vm.registers[6].0,
|
||||
// in("r9") vm.registers[7].0,
|
||||
// )
|
||||
// }
|
||||
}
|
||||
Ok(VmRunOk::End) => break Ok(()),
|
||||
Err(e) => break Err(e),
|
||||
}
|
||||
};
|
||||
|
||||
eprintln!("\n== Registers ==\n{:?}", vm.registers);
|
||||
if let Err(e) = stat {
|
||||
eprintln!("\n[E] Runtime error: {e:?}");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
31
hbvm_aos_on_linux/src/mem.rs
Normal file
31
hbvm_aos_on_linux/src/mem.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
use hbvm::mem::{Address, LoadError, Memory, StoreError};
|
||||
|
||||
pub struct HostMemory;
|
||||
impl Memory for HostMemory {
|
||||
#[inline]
|
||||
unsafe fn load(
|
||||
&mut self,
|
||||
addr: Address,
|
||||
target: *mut u8,
|
||||
count: usize,
|
||||
) -> Result<(), LoadError> {
|
||||
unsafe { core::ptr::copy(addr.get() as *const u8, target, count) }
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn store(
|
||||
&mut self,
|
||||
addr: Address,
|
||||
source: *const u8,
|
||||
count: usize,
|
||||
) -> Result<(), StoreError> {
|
||||
unsafe { core::ptr::copy(source, addr.get() as *mut u8, count) }
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn prog_read<T: Copy>(&mut self, addr: Address) -> T {
|
||||
core::ptr::read(addr.get() as *const T)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue