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",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "beef"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -23,6 +29,12 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
name = "compiler"
|
name = "compiler"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fnv"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.13.2"
|
version = "0.13.2"
|
||||||
|
@ -32,11 +44,25 @@ dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hbasm"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"hbbytecode",
|
||||||
|
"logos",
|
||||||
|
"paste",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hbbytecode"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hbvm"
|
name = "hbvm"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
|
"hbbytecode",
|
||||||
"log",
|
"log",
|
||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
@ -50,18 +76,97 @@ dependencies = [
|
||||||
"cfg-if",
|
"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]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.17.1"
|
version = "1.17.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
|
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]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
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]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
[workspace]
|
[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 {
|
macro_rules! constmod {
|
||||||
($vis:vis $mname:ident($repr:ty) { $($cname:ident = $val:expr),* $(,)? }) => {
|
($vis:vis $mname:ident($repr:ty) { $($cname:ident = $val:expr),* $(,)? }) => {
|
||||||
|
@ -43,10 +43,10 @@ constmod!(pub opcode(u8) {
|
||||||
PAGEUNMAP = 25, // ?; Unmap a page
|
PAGEUNMAP = 25, // ?; Unmap a page
|
||||||
PAGEMP = 26, // ?; Page modify protection flags
|
PAGEMP = 26, // ?; Page modify protection flags
|
||||||
|
|
||||||
JMP = 100, // I; Unconditional jump
|
JMP = 27, // I; Unconditional jump
|
||||||
JMPCOND = 101, // ?; Conditional jump
|
JMPCOND = 28, // ?; Conditional jump
|
||||||
RET = 103, // N; Return
|
RET = 29, // N; Return
|
||||||
ECALL = 255, // N; Issue system call
|
ECALL = 30, // N; Issue system call
|
||||||
});
|
});
|
||||||
|
|
||||||
#[repr(packed)] pub struct ParamRRR(pub u8, pub u8, pub u8);
|
#[repr(packed)] pub struct ParamRRR(pub u8, pub u8, pub u8);
|
|
@ -10,3 +10,4 @@ lto = true
|
||||||
log = "*"
|
log = "*"
|
||||||
hashbrown = "0.13.2"
|
hashbrown = "0.13.2"
|
||||||
static_assertions = "1.0"
|
static_assertions = "1.0"
|
||||||
|
hbbytecode = { path = "../hbbytecode" }
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
pub mod bytecode;
|
|
||||||
pub mod validate;
|
pub mod validate;
|
||||||
pub mod vm;
|
pub mod vm;
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub struct Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn validate(mut program: &[u8]) -> Result<(), Error> {
|
pub fn validate(mut program: &[u8]) -> Result<(), Error> {
|
||||||
use crate::bytecode::opcode::*;
|
use hbbytecode::opcode::*;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn reg(regs: &[u8]) -> Option<usize> {
|
fn reg(regs: &[u8]) -> Option<usize> {
|
||||||
|
|
|
@ -3,8 +3,8 @@ use crate::validate;
|
||||||
mod value;
|
mod value;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::bytecode::{OpParam, ParamRI, ParamRR, ParamRRR},
|
|
||||||
core::ops,
|
core::ops,
|
||||||
|
hbbytecode::{OpParam, ParamRI, ParamRR, ParamRRR},
|
||||||
static_assertions::assert_impl_one,
|
static_assertions::assert_impl_one,
|
||||||
value::Value,
|
value::Value,
|
||||||
};
|
};
|
||||||
|
@ -51,7 +51,7 @@ impl<'a> Vm<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
use crate::bytecode::opcode::*;
|
use hbbytecode::opcode::*;
|
||||||
loop {
|
loop {
|
||||||
let Some(&opcode) = self.program.get(self.pc)
|
let Some(&opcode) = self.program.get(self.pc)
|
||||||
else { return };
|
else { return };
|
||||||
|
|
Loading…
Reference in a new issue