forked from AbleOS/holey-bytes
Added assembler
- its a bit cursed, prolly broken, but at least something
This commit is contained in:
parent
83563fff84
commit
8182abca98
312
Cargo.lock
generated
312
Cargo.lock
generated
|
@ -17,6 +17,15 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "argh"
|
||||
version = "0.1.12"
|
||||
|
@ -48,6 +57,12 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.69"
|
||||
|
@ -69,6 +84,16 @@ 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"
|
||||
|
@ -111,6 +136,22 @@ dependencies = [
|
|||
"tracing-error",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "eyre"
|
||||
version = "0.6.8"
|
||||
|
@ -127,6 +168,15 @@ version = "0.28.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
|
||||
|
||||
[[package]]
|
||||
name = "hbasm"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"mlua",
|
||||
"paste",
|
||||
"with_builtin_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hbbytecode"
|
||||
version = "0.1.0"
|
||||
|
@ -149,12 +199,30 @@ dependencies = [
|
|||
"nix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "home"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indenter"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
|
@ -167,6 +235,31 @@ 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"
|
||||
|
@ -182,6 +275,48 @@ 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"
|
||||
|
@ -193,6 +328,15 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.32.1"
|
||||
|
@ -214,12 +358,48 @@ version = "3.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
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"
|
||||
|
@ -238,12 +418,60 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[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"
|
||||
|
@ -358,6 +586,90 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "which"
|
||||
version = "4.4.2"
|
||||
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"
|
||||
|
||||
[[package]]
|
||||
name = "with_builtin_macros"
|
||||
version = "0.0.3"
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["hbbytecode", "hbvm", "hbxrt", "xtask"]
|
||||
members = ["hbasm", "hbbytecode", "hbvm", "hbxrt", "xtask"]
|
||||
|
|
12
hbasm/Cargo.toml
Normal file
12
hbasm/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "hbasm"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
paste = "1.0"
|
||||
with_builtin_macros = "0.0.3"
|
||||
|
||||
[dependencies.mlua]
|
||||
version = "0.9"
|
||||
features = ["luajit52", "macros", "vendored"]
|
3
hbasm/assets/exit.lua
Normal file
3
hbasm/assets/exit.lua
Normal file
|
@ -0,0 +1,3 @@
|
|||
li8(r1, 60)
|
||||
li8(r2, 69)
|
||||
eca()
|
8
hbasm/assets/label.lua
Normal file
8
hbasm/assets/label.lua
Normal file
|
@ -0,0 +1,8 @@
|
|||
label "label" -- set named label
|
||||
local a = label {} -- unassigned label
|
||||
|
||||
jmp16("label")
|
||||
a:here() -- assign label
|
||||
jmp16(a)
|
||||
|
||||
addi8(r3, r4, 5)
|
53
hbasm/src/arraylist.rs
Normal file
53
hbasm/src/arraylist.rs
Normal file
|
@ -0,0 +1,53 @@
|
|||
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),
|
||||
});
|
||||
}
|
||||
}
|
194
hbasm/src/ins.rs
Normal file
194
hbasm/src/ins.rs
Normal file
|
@ -0,0 +1,194 @@
|
|||
use {
|
||||
crate::arraylist::ArrayList,
|
||||
mlua::{prelude::*, Result, Scope},
|
||||
};
|
||||
|
||||
mod opsty {
|
||||
pub type R = i8;
|
||||
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());
|
||||
};
|
||||
)*
|
||||
|
||||
($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,
|
||||
};
|
||||
}
|
||||
|
||||
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})"
|
||||
)));
|
||||
}
|
||||
}
|
||||
.is_err()
|
||||
{
|
||||
return Err(mlua::Error::runtime("Failed to cast offset"));
|
||||
}
|
||||
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(())
|
||||
}
|
91
hbasm/src/label.rs
Normal file
91
hbasm/src/label.rs
Normal file
|
@ -0,0 +1,91 @@
|
|||
use {
|
||||
crate::{arraylist::ArrayList, Labels},
|
||||
mlua::{Result, prelude::*},
|
||||
};
|
||||
|
||||
#[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));
|
||||
}
|
||||
|
||||
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(),
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
None => Err(mlua::Error::runtime("Invalid label")),
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[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)",
|
||||
)),
|
||||
}),
|
||||
}
|
||||
}
|
44
hbasm/src/linker.rs
Normal file
44
hbasm/src/linker.rs
Normal file
|
@ -0,0 +1,44 @@
|
|||
use mlua::prelude::*;
|
||||
|
||||
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"))?;
|
||||
|
||||
let loc = loc - 1;
|
||||
let dest = dest - 1;
|
||||
|
||||
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")),
|
||||
}
|
||||
}
|
||||
|
||||
dbg!(&code);
|
||||
out.write_all(code)?;
|
||||
Ok(())
|
||||
}
|
54
hbasm/src/main.rs
Normal file
54
hbasm/src/main.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
mod arraylist;
|
||||
mod ins;
|
||||
mod label;
|
||||
mod linker;
|
||||
|
||||
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(),
|
||||
)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -39,6 +39,7 @@ define_items! {
|
|||
OpsRW (OpR, OpW ),
|
||||
OpsRD (OpR, OpD ),
|
||||
OpsRRD (OpR, OpR, OpD ),
|
||||
OpsRRA (OpR, OpR, OpA ),
|
||||
OpsRRAH (OpR, OpR, OpA, OpH),
|
||||
OpsRROH (OpR, OpR, OpO, OpH),
|
||||
OpsRRPH (OpR, OpR, OpP, OpH),
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//!
|
||||
//! Have fun
|
||||
|
||||
use hbbytecode::RoundingMode;
|
||||
use hbbytecode::{OpsRRA, RoundingMode};
|
||||
|
||||
use crate::mem::addr::AddressOp;
|
||||
|
||||
|
@ -271,23 +271,29 @@ where
|
|||
usize::from(count),
|
||||
);
|
||||
}),
|
||||
JMP => handler!(self, |OpsO(off)| self.pc = self.pc.wrapping_add(off)),
|
||||
JAL => handler!(self, |OpsRRO(save, reg, offset)| {
|
||||
JMP => {
|
||||
let OpsO(off) = self.decode();
|
||||
self.pc = self.pc.wrapping_add(off);
|
||||
}
|
||||
JAL => {
|
||||
// Jump and link. Save PC after this instruction to
|
||||
// specified register and jump to reg + relative offset.
|
||||
let OpsRRO(save, reg, offset) = self.decode();
|
||||
|
||||
self.write_reg(save, self.pc.get());
|
||||
self.pc = self
|
||||
.pcrel(offset, 3)
|
||||
.wrapping_add(self.read_reg(reg).cast::<i64>());
|
||||
}),
|
||||
JALA => handler!(self, |OpsRRW(save, reg, offset)| {
|
||||
}
|
||||
JALA => {
|
||||
// Jump and link. Save PC after this instruction to
|
||||
// specified register and jump to reg
|
||||
let OpsRRA(save, reg, offset) = self.decode();
|
||||
|
||||
self.write_reg(save, self.pc.get());
|
||||
self.pc = Address::new(
|
||||
self.read_reg(reg).cast::<u64>().wrapping_add(offset.into()),
|
||||
);
|
||||
}),
|
||||
self.pc =
|
||||
Address::new(self.read_reg(reg).cast::<u64>().wrapping_add(offset));
|
||||
}
|
||||
// Conditional jumps, jump only to immediates
|
||||
JEQ => self.cond_jmp::<u64>(Ordering::Equal),
|
||||
JNE => handler!(self, |OpsRRP(a0, a1, ja)| {
|
||||
|
@ -385,7 +391,10 @@ where
|
|||
STR16 => handler!(self, |OpsRRPH(dst, base, off, count)| {
|
||||
self.store(dst, base, self.pcrel(off, 3).get(), count)?;
|
||||
}),
|
||||
JMP16 => handler!(self, |OpsP(off)| self.pc = self.pcrel(off, 1)),
|
||||
JMP16 => {
|
||||
let OpsP(off) = self.decode();
|
||||
self.pc = self.pcrel(off, 1);
|
||||
}
|
||||
op => return Err(VmRunError::InvalidOpcode(op)),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue