holey-bytes/hbbytecode/src/lib.rs

120 lines
3.1 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 {}
)*
};
}
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]
macro_rules! invoke_with_def {
($macro:path) => {
$macro! { $spec }
};
}
}
}
2023-09-26 16:36:27 -05:00
macro_rules! gen_opcodes {
($($opcode:expr, $mnemonic:ident, $_ty:ident, $doc:literal;)*) => {
pub mod opcode {
$(
#[doc = $doc]
pub const $mnemonic: u8 = $opcode;
)*
}
};
}
/// 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);