Assembla.

wip/its-not-my-fault
ondra05 2023-06-07 15:07:37 +02:00
parent 529006a6f7
commit c40b10d26c
No known key found for this signature in database
GPG Key ID: 0DA6D2BB2285E881
11 changed files with 319 additions and 10 deletions

105
Cargo.lock generated
View File

@ -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"

View File

@ -1,2 +1,2 @@
[workspace]
members = ["hbvm", "compiler"]
members = ["hbasm", "hbbytecode", "hbvm", "compiler"]

13
hbasm/Cargo.toml Normal file
View 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
View 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
View File

@ -0,0 +1,3 @@
fn main() {
// TODO
}

6
hbbytecode/Cargo.toml Normal file
View File

@ -0,0 +1,6 @@
[package]
name = "hbbytecode"
version = "0.1.0"
edition = "2021"
[dependencies]

View File

@ -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);

View File

@ -10,3 +10,4 @@ lto = true
log = "*"
hashbrown = "0.13.2"
static_assertions = "1.0"
hbbytecode = { path = "../hbbytecode" }

View File

@ -1,7 +1,6 @@
#![no_std]
extern crate alloc;
pub mod bytecode;
pub mod validate;
pub mod vm;

View File

@ -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> {

View File

@ -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 };