holey-bytes/hbbytecode/src/lib.rs

177 lines
5 KiB
Rust
Raw Normal View History

#![no_std]
use core::convert::TryFrom;
2023-10-01 09:02:06 -05:00
type OpR = u8;
2023-10-01 09:02:06 -05:00
type OpA = u64;
2023-10-22 07:46:45 -05:00
type OpO = i32;
type OpP = i16;
2023-09-26 16:36:27 -05:00
2023-10-01 09:02:06 -05:00
type OpB = u8;
type OpH = u16;
type OpW = u32;
type OpD = u64;
2023-09-26 16:36:27 -05:00
/// # Safety
/// Has to be valid to be decoded from bytecode.
pub unsafe trait BytecodeItem {}
macro_rules! define_items {
($($name:ident ($($item:ident),* $(,)?)),* $(,)?) => {
$(
#[derive(Clone, Copy, Debug)]
2023-09-26 16:36:27 -05:00
#[repr(packed)]
pub struct $name($(pub $item),*);
unsafe impl BytecodeItem for $name {}
2024-01-31 13:11:57 -06:00
impl Encodable for $name {
fn encode(self, buffer: &mut impl Buffer) {
let array = unsafe {
core::mem::transmute::<Self, [u8; core::mem::size_of::<Self>()]>(self)
};
for byte in array {
unsafe { buffer.write(byte) };
}
}
fn encode_len(self) -> usize {
core::mem::size_of::<Self>()
}
}
2023-09-26 16:36:27 -05:00
)*
};
}
2023-09-26 16:36:27 -05:00
define_items! {
OpsRR (OpR, OpR ),
OpsRRR (OpR, OpR, OpR ),
OpsRRRR (OpR, OpR, OpR, OpR),
OpsRRB (OpR, OpR, OpB ),
OpsRRH (OpR, OpR, OpH ),
OpsRRW (OpR, OpR, OpW ),
2023-10-27 20:29:02 -05:00
OpsRRD (OpR, OpR, OpD ),
OpsRB (OpR, OpB ),
OpsRH (OpR, OpH ),
OpsRW (OpR, OpW ),
2023-09-26 16:36:27 -05:00
OpsRD (OpR, OpD ),
OpsRRA (OpR, OpR, OpA ),
2023-09-26 16:36:27 -05:00
OpsRRAH (OpR, OpR, OpA, OpH),
OpsRROH (OpR, OpR, OpO, OpH),
OpsRRPH (OpR, OpR, OpP, OpH),
2023-09-26 16:36:27 -05:00
OpsRRO (OpR, OpR, OpO ),
OpsRRP (OpR, OpR, OpP ),
2023-10-01 09:02:06 -05:00
OpsO (OpO, ),
OpsP (OpP, ),
OpsN ( ),
2023-09-26 16:36:27 -05:00
}
2023-08-08 18:24:13 -05:00
2023-10-01 09:02:06 -05:00
unsafe impl BytecodeItem for u8 {}
2023-08-08 18:24:13 -05:00
2023-09-26 16:36:27 -05:00
::with_builtin_macros::with_builtin! {
let $spec = include_from_root!("instructions.in") in {
/// Invoke macro with bytecode definition
///
/// # Format
/// ```text
/// Opcode, Mnemonic, Type, Docstring;
/// ```
///
/// # Type
/// ```text
/// Types consist of letters meaning a single field
/// | Type | Size (B) | Meaning |
/// |:-----|:---------|:------------------------|
/// | N | 0 | Empty |
/// | R | 1 | Register |
/// | A | 8 | Absolute address |
/// | O | 4 | Relative address offset |
/// | P | 2 | Relative address offset |
/// | B | 1 | Immediate |
/// | H | 2 | Immediate |
/// | W | 4 | Immediate |
/// | D | 8 | Immediate |
/// ```
#[macro_export]
2024-01-06 17:34:28 -06:00
macro_rules! invoke_with_def {
($($macro:tt)*) => {
$($macro)*! { $spec }
};
}
2023-09-26 16:36:27 -05:00
}
}
2024-01-31 13:11:57 -06:00
pub trait Buffer {
fn reserve(&mut self, bytes: usize);
/// # Safety
/// Reserve needs to be called before this function, and only reserved amount can be written.
unsafe fn write(&mut self, byte: u8);
}
pub trait Encodable {
fn encode(self, buffer: &mut impl Buffer);
fn encode_len(self) -> usize;
}
2023-09-26 16:36:27 -05:00
macro_rules! gen_opcodes {
2024-01-31 13:11:57 -06:00
($($opcode:expr, $mnemonic:ident, $ty:ident, $doc:literal;)*) => {
2023-09-26 16:36:27 -05:00
pub mod opcode {
$(
#[doc = $doc]
pub const $mnemonic: u8 = $opcode;
)*
2024-01-31 13:11:57 -06:00
paste::paste! {
#[derive(Clone, Copy, Debug)]
pub enum Op { $(
[< $mnemonic:lower:camel >](super::[<Ops $ty>]),
)* }
impl crate::Encodable for Op {
fn encode(self, buffer: &mut impl crate::Buffer) {
match self {
$(
Self::[< $mnemonic:lower:camel >](op) => {
unsafe { buffer.write($opcode) };
op.encode(buffer);
}
)*
}
}
fn encode_len(self) -> usize {
match self {
$(
Self::[< $mnemonic:lower:camel >](op) => {
1 + crate::Encodable::encode_len(op)
}
)*
}
}
}
}
2023-09-26 16:36:27 -05:00
}
};
}
/// Rounding mode
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u8)]
pub enum RoundingMode {
NearestEven = 0,
Truncate = 1,
Up = 2,
Down = 3,
}
impl TryFrom<u8> for RoundingMode {
type Error = ();
fn try_from(value: u8) -> Result<Self, Self::Error> {
2023-11-03 03:43:08 -05:00
(value <= 3)
.then(|| unsafe { core::mem::transmute(value) })
.ok_or(())
}
}
2023-09-26 16:36:27 -05:00
invoke_with_def!(gen_opcodes);