juicebox_asm/
imm.rs

1// SPDX-License-Identifier: MIT
2//
3// Copyright (c) 2023, Johannes Stoelp <dev@memzero.de>
4
5//! Definition of different immediate types which are used as input operands for various
6//! instructions.
7
8/// Trait to interact with immediate operands.
9pub(crate) trait Imm {
10    /// Get immediate operand as slice of bytes.
11    fn bytes(&self) -> &[u8];
12}
13
14macro_rules! impl_imm {
15    (#[$doc:meta] $name:ident, $size:expr, from: { $( $from:ty ),* $(,)? }) => {
16        #[$doc]
17        pub struct $name([u8; $size]);
18
19        impl Imm for $name {
20            /// Get immediate operand as slice of bytes.
21            fn bytes(&self) -> &[u8] {
22                &self.0
23            }
24        }
25
26        $(
27        impl From<$from> for $name {
28            fn from(imm: $from) -> Self {
29                let mut buf = [0u8; $size];
30                let imm = imm.to_ne_bytes();
31                buf[0..imm.len()].copy_from_slice(&imm);
32                $name(buf)
33            }
34        }
35        )*
36    }
37}
38
39impl_imm!(
40    /// Type representing an 8 bit immediate.
41    Imm8, 1, from: { u8, i8 }
42);
43impl_imm!(
44    /// Type representing a 16 bit immediate.
45    Imm16, 2, from: { u16, i16, u8, i8 }
46);
47impl_imm!(
48    /// Type representing a 32 bit immediate.
49    Imm32, 4, from: { u32, i32, u16, i16, u8, i8 }
50);
51impl_imm!(
52    /// Type representing a 64 bit immediate.
53    Imm64, 8, from: { u64, i64, u32, i32, u16, i16, u8, i8, usize, isize }
54);
55
56#[cfg(test)]
57mod test {
58    use super::*;
59    use std::mem::size_of;
60
61    #[test]
62    fn test_usize_isize() {
63        // Imm64 should not implementd from usize/isize if this fails.
64        assert_eq!(size_of::<usize>(), size_of::<Imm64>());
65        assert_eq!(size_of::<isize>(), size_of::<Imm64>());
66    }
67}