forked from AbleOS/holey-bytes
Assembla.
This commit is contained in:
parent
8675965ef5
commit
cbb0ac2abe
105
Cargo.lock
generated
105
Cargo.lock
generated
|
@ -13,6 +13,12 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "beef"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
|
@ -23,6 +29,12 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||
name = "compiler"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.13.2"
|
||||
|
@ -32,11 +44,25 @@ dependencies = [
|
|||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hbasm"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hbbytecode",
|
||||
"logos",
|
||||
"paste",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hbbytecode"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "hbvm"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"hashbrown",
|
||||
"hbbytecode",
|
||||
"log",
|
||||
"static_assertions",
|
||||
]
|
||||
|
@ -50,18 +76,97 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "logos"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c000ca4d908ff18ac99b93a062cb8958d331c3220719c52e77cb19cc6ac5d2c1"
|
||||
dependencies = [
|
||||
"logos-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "logos-codegen"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc487311295e0002e452025d6b580b77bb17286de87b57138f3b5db711cded68"
|
||||
dependencies = [
|
||||
"beef",
|
||||
"fnv",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"regex-syntax",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "logos-derive"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbfc0d229f1f42d790440136d941afd806bc9e949e2bcb8faa813b0f00d1267e"
|
||||
dependencies = [
|
||||
"logos-codegen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.59"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
[workspace]
|
||||
members = ["hbvm", "compiler"]
|
||||
members = ["hbasm", "hbbytecode", "hbvm", "compiler"]
|
||||
|
|
13
hbasm/Cargo.toml
Normal file
13
hbasm/Cargo.toml
Normal file
|
@ -0,0 +1,13 @@
|
|||
[package]
|
||||
name = "hbasm"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
hbbytecode = { path = "../hbbytecode" }
|
||||
paste = "1.0"
|
||||
|
||||
[dependencies.logos]
|
||||
version = "0.13"
|
||||
default-features = false
|
||||
features = ["export_derive"]
|
182
hbasm/src/lib.rs
Normal file
182
hbasm/src/lib.rs
Normal file
|
@ -0,0 +1,182 @@
|
|||
use {
|
||||
logos::{Lexer, Logos, Span},
|
||||
std::{ops::Range, str::FromStr},
|
||||
};
|
||||
|
||||
macro_rules! tokendef {
|
||||
($($opcode:literal),* $(,)?) => {
|
||||
paste::paste! {
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Logos)]
|
||||
#[logos(skip r"[ \t\f]+")]
|
||||
pub enum Token {
|
||||
$(#[token($opcode, |_| hbbytecode::opcode::[<$opcode:upper>])])*
|
||||
OpCode(u8),
|
||||
|
||||
#[regex("[0-9]+", |l| l.slice().parse().ok())]
|
||||
#[regex(
|
||||
"-[0-9]+",
|
||||
|lexer| {
|
||||
Some(u64::from_ne_bytes(lexer.slice().parse::<i64>().ok()?.to_ne_bytes()))
|
||||
},
|
||||
)] Integer(u64),
|
||||
|
||||
#[regex(
|
||||
"r[0-9]+",
|
||||
|lexer| match lexer.slice()[1..].parse() {
|
||||
Ok(n) if n <= 59 => Some(n),
|
||||
_ => None
|
||||
},
|
||||
)] Register(u8),
|
||||
|
||||
#[token("\n")]
|
||||
#[token(";")] ISep,
|
||||
|
||||
#[token(",")] PSep,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
tokendef![
|
||||
"nop", "add", "sub", "mul", "rem", "and", "or", "xor", "not",
|
||||
"addf", "subf", "mulf", "divf", "cp", "li", "lb", "ld", "lq",
|
||||
"lo", "sb", "sd", "sq", "so", "pagemap", "pageunmap", "pagemp",
|
||||
"jmp", "jmpcond", "ret", "ecall",
|
||||
];
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum ErrorKind {
|
||||
UnexpectedToken,
|
||||
InvalidToken,
|
||||
UnexpectedEnd,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Error {
|
||||
kind: ErrorKind,
|
||||
span: Span,
|
||||
}
|
||||
|
||||
macro_rules! expect_matches {
|
||||
($self:expr, $($pat:pat),* $(,)?) => {$(
|
||||
let $pat = $self.next()?
|
||||
else { return Err(ErrorKind::UnexpectedToken) };
|
||||
)*}
|
||||
}
|
||||
|
||||
pub fn assembly(code: &str, buf: &mut Vec<u8>) -> Result<(), Error> {
|
||||
struct Assembler<'a> {
|
||||
lexer: Lexer<'a, Token>,
|
||||
buf: &'a mut Vec<u8>,
|
||||
}
|
||||
|
||||
impl<'a> Assembler<'a> {
|
||||
fn next(&mut self) -> Result<Token, ErrorKind> {
|
||||
match self.lexer.next() {
|
||||
Some(Ok(t)) => Ok(t),
|
||||
Some(Err(())) => Err(ErrorKind::InvalidToken),
|
||||
None => Err(ErrorKind::UnexpectedEnd),
|
||||
}
|
||||
}
|
||||
|
||||
fn assemble(&mut self) -> Result<(), ErrorKind> {
|
||||
use hbbytecode::opcode::*;
|
||||
loop {
|
||||
match self.lexer.next() {
|
||||
Some(Ok(Token::OpCode(op))) => {
|
||||
self.buf.push(op);
|
||||
match op {
|
||||
NOP | RET | ECALL => Ok(()),
|
||||
ADD..=XOR | ADDF..=DIVF => self.rrr(),
|
||||
NOT | CP => self.rr(),
|
||||
LI => self.ri(),
|
||||
LB..=SO => self.rri(),
|
||||
JMP => self.i(),
|
||||
_ => unreachable!(),
|
||||
}?;
|
||||
match self.next() {
|
||||
Ok(Token::ISep) => (),
|
||||
Ok(_) => return Err(ErrorKind::UnexpectedToken),
|
||||
Err(ErrorKind::UnexpectedEnd) => return Ok(()),
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
Some(Ok(_)) => return Err(ErrorKind::UnexpectedToken),
|
||||
Some(Err(())) => return Err(ErrorKind::InvalidToken),
|
||||
None => return Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn rrr(&mut self) -> Result<(), ErrorKind> {
|
||||
expect_matches!(
|
||||
self,
|
||||
Token::Register(r0),
|
||||
Token::PSep,
|
||||
Token::Register(r1),
|
||||
Token::PSep,
|
||||
Token::Register(r2)
|
||||
);
|
||||
self.buf.extend([r0, r1, r2]);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn rr(&mut self) -> Result<(), ErrorKind> {
|
||||
expect_matches!(
|
||||
self,
|
||||
Token::Register(r0),
|
||||
Token::PSep,
|
||||
Token::Register(r1),
|
||||
);
|
||||
self.buf.extend([r0, r1]);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ri(&mut self) -> Result<(), ErrorKind> {
|
||||
expect_matches!(
|
||||
self,
|
||||
Token::Register(r0),
|
||||
Token::PSep,
|
||||
Token::Integer(r1),
|
||||
);
|
||||
|
||||
self.buf.push(r0);
|
||||
self.buf.extend(r1.to_le_bytes());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn rri(&mut self) -> Result<(), ErrorKind> {
|
||||
expect_matches!(
|
||||
self,
|
||||
Token::Register(r0),
|
||||
Token::PSep,
|
||||
Token::Register(r1),
|
||||
Token::PSep,
|
||||
Token::Integer(imm),
|
||||
);
|
||||
self.buf.extend([r0, r1]);
|
||||
self.buf.extend(imm.to_le_bytes());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn i(&mut self) -> Result<(), ErrorKind> {
|
||||
expect_matches!(
|
||||
self,
|
||||
Token::Integer(imm),
|
||||
);
|
||||
self.buf.extend(imm.to_le_bytes());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
let mut asm = Assembler {
|
||||
lexer: Token::lexer(code),
|
||||
buf,
|
||||
};
|
||||
|
||||
asm.assemble().map_err(|kind| Error {
|
||||
kind,
|
||||
span: asm.lexer.span()
|
||||
})
|
||||
}
|
3
hbasm/src/main.rs
Normal file
3
hbasm/src/main.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
fn main() {
|
||||
// TODO
|
||||
}
|
6
hbbytecode/Cargo.toml
Normal file
6
hbbytecode/Cargo.toml
Normal file
|
@ -0,0 +1,6 @@
|
|||
[package]
|
||||
name = "hbbytecode"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
|
@ -1,4 +1,4 @@
|
|||
pub const REG_COUNT: usize = 60;
|
||||
#![no_std]
|
||||
|
||||
macro_rules! constmod {
|
||||
($vis:vis $mname:ident($repr:ty) { $($cname:ident = $val:expr),* $(,)? }) => {
|
||||
|
@ -43,10 +43,10 @@ constmod!(pub opcode(u8) {
|
|||
PAGEUNMAP = 25, // ?; Unmap a page
|
||||
PAGEMP = 26, // ?; Page modify protection flags
|
||||
|
||||
JMP = 100, // I; Unconditional jump
|
||||
JMPCOND = 101, // ?; Conditional jump
|
||||
RET = 103, // N; Return
|
||||
ECALL = 255, // N; Issue system call
|
||||
JMP = 27, // I; Unconditional jump
|
||||
JMPCOND = 28, // ?; Conditional jump
|
||||
RET = 29, // N; Return
|
||||
ECALL = 30, // N; Issue system call
|
||||
});
|
||||
|
||||
#[repr(packed)] pub struct ParamRRR(pub u8, pub u8, pub u8);
|
|
@ -10,3 +10,4 @@ lto = true
|
|||
log = "*"
|
||||
hashbrown = "0.13.2"
|
||||
static_assertions = "1.0"
|
||||
hbbytecode = { path = "../hbbytecode" }
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#![no_std]
|
||||
extern crate alloc;
|
||||
|
||||
pub mod bytecode;
|
||||
pub mod validate;
|
||||
pub mod vm;
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ pub struct Error {
|
|||
}
|
||||
|
||||
pub fn validate(mut program: &[u8]) -> Result<(), Error> {
|
||||
use crate::bytecode::opcode::*;
|
||||
use hbbytecode::opcode::*;
|
||||
|
||||
#[inline]
|
||||
fn reg(regs: &[u8]) -> Option<usize> {
|
||||
|
|
|
@ -3,8 +3,8 @@ use crate::validate;
|
|||
mod value;
|
||||
|
||||
use {
|
||||
crate::bytecode::{OpParam, ParamRI, ParamRR, ParamRRR},
|
||||
core::ops,
|
||||
hbbytecode::{OpParam, ParamRI, ParamRR, ParamRRR},
|
||||
static_assertions::assert_impl_one,
|
||||
value::Value,
|
||||
};
|
||||
|
@ -51,7 +51,7 @@ impl<'a> Vm<'a> {
|
|||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
use crate::bytecode::opcode::*;
|
||||
use hbbytecode::opcode::*;
|
||||
loop {
|
||||
let Some(&opcode) = self.program.get(self.pc)
|
||||
else { return };
|
||||
|
|
Loading…
Reference in a new issue