maikor_platform/
op_params.rs

1use crate::op_params::ID::{Dec, Inc};
2use crate::op_params::PP::{Post, Pre};
3use crate::LangError;
4use crate::LangError::InvalidRegisterArgCode;
5
6pub const MASK: u8 = 0xF0;
7
8pub const REGISTER: u8 = 0b00000000;
9//pub const RESERVED: u8 =   0b00010000;
10//pub const RESERVED: u8 =   0b00100000;
11//pub const RESERVED: u8 =   0b00110000;
12pub const POST_INC: u8 = 0b01000000;
13pub const POST_DEC: u8 = 0b01010000;
14pub const PRE_INC: u8 = 0b01100000;
15pub const PRE_DEC: u8 = 0b01110000;
16pub const INDIRECT: u8 = 0b10000000;
17pub const IND_OFFSET_REG: u8 = 0b10010000;
18pub const IND_OFFSET_EXT_REG: u8 = 0b10100000;
19pub const IND_OFFSET_NUM: u8 = 0b10110000;
20pub const IND_POST_INC: u8 = 0b11000000;
21pub const IND_POST_DEC: u8 = 0b11010000;
22pub const IND_PRE_INC: u8 = 0b11100000;
23pub const IND_PRE_DEC: u8 = 0b11110000;
24
25#[derive(Debug, Copy, Clone, Eq, PartialEq)]
26pub enum PP {
27    Pre,
28    Post,
29}
30
31#[derive(Debug, Copy, Clone, Eq, PartialEq)]
32pub enum ID {
33    Inc,
34    Dec,
35}
36
37#[derive(Debug, Clone, PartialEq, Eq, Default)]
38pub struct RegisterPPID {
39    pub is_indirect: bool,
40    pub is_offset_reg: bool,
41    pub is_offset_ext_reg: bool,
42    pub is_offset_num: bool,
43    pub ppid: Option<(PP, ID)>,
44}
45
46impl RegisterPPID {
47    pub fn new(
48        is_indirect: bool,
49        is_offset_reg: bool,
50        is_offset_num: bool,
51        is_offset_ext_reg: bool,
52        ppid: Option<(PP, ID)>,
53    ) -> Self {
54        Self {
55            is_indirect,
56            is_offset_reg,
57            is_offset_num,
58            is_offset_ext_reg,
59            ppid,
60        }
61    }
62}
63
64impl TryFrom<u8> for RegisterPPID {
65    type Error = LangError;
66
67    fn try_from(value: u8) -> Result<Self, LangError> {
68        let ppid = match value & MASK {
69            IND_PRE_DEC => RegisterPPID::new(true, false, false, false, Some((Pre, Dec))),
70            IND_POST_DEC => RegisterPPID::new(true, false, false, false, Some((Post, Dec))),
71            IND_PRE_INC => RegisterPPID::new(true, false, false, false, Some((Pre, Inc))),
72            IND_POST_INC => RegisterPPID::new(true, false, false, false, Some((Post, Inc))),
73            INDIRECT => RegisterPPID::new(true, false, false, false, None),
74            PRE_DEC => RegisterPPID::new(false, false, false, false, Some((Pre, Dec))),
75            POST_DEC => RegisterPPID::new(false, false, false, false, Some((Post, Dec))),
76            PRE_INC => RegisterPPID::new(false, false, false, false, Some((Pre, Inc))),
77            POST_INC => RegisterPPID::new(false, false, false, false, Some((Post, Inc))),
78            REGISTER => RegisterPPID::new(false, false, false, false, None),
79            IND_OFFSET_REG => RegisterPPID::new(true, true, false, false, None),
80            IND_OFFSET_EXT_REG => RegisterPPID::new(true, false, false, true, None),
81            IND_OFFSET_NUM => RegisterPPID::new(true, false, true, false, None),
82            _ => return Err(InvalidRegisterArgCode(value)),
83        };
84        Ok(ppid)
85    }
86}
87
88impl From<RegisterPPID> for u8 {
89    fn from(arg: RegisterPPID) -> Self {
90        let mut byte = 0;
91
92        if arg.is_offset_reg {
93            return IND_OFFSET_REG;
94        } else if arg.is_offset_ext_reg {
95            return IND_OFFSET_EXT_REG;
96        } else if arg.is_offset_num {
97            return IND_OFFSET_NUM;
98        } else if arg.is_indirect {
99            byte |= INDIRECT;
100        }
101        if let Some(ppid) = arg.ppid {
102            match (ppid.0, ppid.1) {
103                (Pre, Inc) => byte |= PRE_INC,
104                (Post, Inc) => byte |= POST_INC,
105                (Pre, Dec) => byte |= PRE_DEC,
106                (Post, Dec) => byte |= POST_DEC,
107            }
108        }
109
110        byte
111    }
112}
113
114#[cfg(test)]
115mod test {
116    use super::*;
117
118    #[test]
119    fn check_alignment() {
120        let values = vec![
121            REGISTER,
122            POST_INC,
123            POST_DEC,
124            PRE_INC,
125            PRE_DEC,
126            INDIRECT,
127            IND_POST_INC,
128            IND_POST_DEC,
129            IND_PRE_INC,
130            IND_PRE_DEC,
131            IND_OFFSET_REG,
132            IND_OFFSET_EXT_REG,
133            IND_OFFSET_NUM,
134        ];
135        for value in values {
136            let ppid: RegisterPPID = value.try_into().unwrap();
137            let byte: u8 = ppid.into();
138            assert_eq!(value, byte, "{}", value);
139        }
140    }
141}