osiris_process/operation/
scheme.rs1use std::fmt::{Display, Formatter};
2use std::hash::{Hash, Hasher};
3
4use osiris_data::data::identification::Identifier;
5
6use crate::register::{RegisterId, RegisterRange};
7use crate::operation::error::{OperationError, OperationResult};
8
9#[derive(Copy, Clone, Debug, Eq, PartialEq)]
11pub struct OperationId(u16);
12
13impl OperationId {
14 pub const fn new(raw: u16) -> Self { Self(raw) }
15 pub const fn to_u16(&self) -> u16 { self.0 }
16}
17
18impl Hash for OperationId {
19 fn hash<H: Hasher>(&self, state: &mut H) {
20 state.write_usize(self.to_usize());
21 }
22}
23
24impl Identifier for OperationId {
25 fn to_usize(&self) -> usize { self.0 as usize }
26}
27
28#[derive(Copy, Clone, Debug, Eq, PartialEq)]
29pub enum ArgumentType {
30 NoArgument,
31 Range,
32 OneU32,
33 TwoU16,
34 FourU8,
35}
36
37impl ArgumentType {
38 pub fn to_asm_template(&self) -> String {
39 match self {
40 ArgumentType::NoArgument => String::new(),
41 ArgumentType::Range => "[{start}, {end}]".to_string(),
42 ArgumentType::OneU32 => "{argument}".to_string(),
43 ArgumentType::TwoU16 => "{first}, {second}".to_string(),
44 ArgumentType::FourU8 => "{first}, {second}, {third}, {fourth}".to_string(),
45 }
46 }
47}
48
49#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
50pub enum ArgumentValue {
51 OneU32(u32),
52 TwoU16(u16, u16),
53 FourU8(u8, u8, u8, u8),
54}
55
56impl ArgumentValue {
57 pub fn to_u32(&self) -> u32 {
58 match self {
59 ArgumentValue::OneU32(v) => *v,
60 ArgumentValue::TwoU16(t, b) => (*t as u32) << 8 | *b as u32,
61 ArgumentValue::FourU8(a, b, c, d) => (*a as u32) << 24 | (*b as u32) << 16 | (*c as u32) << 8 | *d as u32,
62 }
63 }
64}
65
66impl Display for ArgumentValue {
67 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
68 write!(f, "{}", match self {
69 ArgumentValue::OneU32(a) => format!("{:08x}", a),
70 ArgumentValue::TwoU16(a, b) => format!("{:04x}:{:04x}", a, b),
71 ArgumentValue::FourU8(a, b, c, d) => format!("{:02x}:{:02x}:{:02x}:{:02x}", a, b, c, d),
72 })
73 }
74}
75
76#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
77pub enum ArgumentScheme {
78 NoArgument,
79 Range(RegisterRange),
80 Value(ArgumentValue),
81}
82
83impl ArgumentScheme {
84 pub fn from_type(arg_type: ArgumentType, data: u32) -> ArgumentScheme {
85 match arg_type {
86 ArgumentType::NoArgument => ArgumentScheme::NoArgument,
87 ArgumentType::Range => ArgumentScheme::Range(RegisterRange::from_u32(data)),
88 ArgumentType::OneU32 => ArgumentScheme::Value(ArgumentValue::OneU32(data)),
89 ArgumentType::TwoU16 => ArgumentScheme::Value(ArgumentValue::TwoU16((data >> 16) as u16, data as u16)),
90 ArgumentType::FourU8 => ArgumentScheme::Value(ArgumentValue::FourU8((data >> 24) as u8, (data >> 16) as u8, (data >> 8) as u8, data as u8)),
91 }
92 }
93
94 pub fn get_type(&self) -> ArgumentType {
95 match self {
96 ArgumentScheme::NoArgument => ArgumentType::NoArgument,
97 ArgumentScheme::Value(a) => match a {
98 ArgumentValue::OneU32(_) => ArgumentType::OneU32,
99 ArgumentValue::TwoU16(_, _) => ArgumentType::TwoU16,
100 ArgumentValue::FourU8(_, _, _, _) => ArgumentType::FourU8,
101 },
102 ArgumentScheme::Range(_) => ArgumentType::Range,
103 }
104 }
105
106 pub fn to_u32(&self) -> u32 {
107 match self {
108 ArgumentScheme::NoArgument => 0,
109 ArgumentScheme::Value(a) => a.to_u32(),
110 ArgumentScheme::Range(range) => {
111 let start = range.start.to_u16() as u32;
112 let end = range.end.to_u16() as u32;
113 (start << 16) | end
114 }
115 }
116 }
117
118 pub fn to_asm(&self) -> String {
119 match self {
120 ArgumentScheme::NoArgument => String::new(),
121 ArgumentScheme::Value(value) => value.to_string(),
122 ArgumentScheme::Range(range) => range.to_string(),
123 }
124 }
125
126 pub fn get_no_argument(&self) -> OperationResult<()> {
128 match self {
129 ArgumentScheme::NoArgument => { Ok(()) }
130 ArgumentScheme::Value(_) => { Err(OperationError::InvalidArgumentType { expected: ArgumentType::NoArgument, provided: self.get_type() }) }
131 ArgumentScheme::Range(_) => { Err(OperationError::InvalidArgumentType { expected: ArgumentType::NoArgument, provided: ArgumentType::Range }) }
132 }
133 }
134
135 pub fn get_value(&self) -> OperationResult<u32> {
137 match self {
138 ArgumentScheme::NoArgument => { Err(OperationError::InvalidArgumentType { expected: ArgumentType::OneU32, provided: ArgumentType::NoArgument }) }
139 ArgumentScheme::Value(v) => { Ok(v.to_u32()) }
140 ArgumentScheme::Range(_) => { Err(OperationError::InvalidArgumentType { expected: ArgumentType::OneU32, provided: ArgumentType::Range }) }
141 }
142 }
143
144 pub fn get_range(&self) -> OperationResult<RegisterRange> {
146 match self {
147 ArgumentScheme::NoArgument => { Err(OperationError::InvalidArgumentType { expected: ArgumentType::Range, provided: ArgumentType::NoArgument }) }
148 ArgumentScheme::Value(_) => { Err(OperationError::InvalidArgumentType { expected: ArgumentType::Range, provided: ArgumentType::OneU32 }) }
149 ArgumentScheme::Range(r) => { Ok(*r) }
150 }
151 }
152
153 pub fn get_one_u32(&self) -> OperationResult<u32> {
155 match self {
156 ArgumentScheme::NoArgument => { Err(OperationError::InvalidArgumentType { expected: ArgumentType::OneU32, provided: ArgumentType::NoArgument }) }
157 ArgumentScheme::Value(v) => {
158 match v {
159 ArgumentValue::OneU32(v) => Ok(*v),
160 ArgumentValue::TwoU16(_, _) => Err(OperationError::InvalidArgumentType { expected: ArgumentType::OneU32, provided: ArgumentType::TwoU16 }),
161 ArgumentValue::FourU8(_, _, _, _) => Err(OperationError::InvalidArgumentType { expected: ArgumentType::OneU32, provided: ArgumentType::FourU8 }),
162 }
163 }
164 ArgumentScheme::Range(_) => { Err(OperationError::InvalidArgumentType { expected: ArgumentType::OneU32, provided: ArgumentType::Range }) }
165 }
166 }
167
168 pub fn get_two_u16(&self) -> OperationResult<(u16, u16)> {
170 match self {
171 ArgumentScheme::NoArgument => { Err(OperationError::InvalidArgumentType { expected: ArgumentType::TwoU16, provided: ArgumentType::NoArgument }) }
172 ArgumentScheme::Value(v) => {
173 match v {
174 ArgumentValue::OneU32(_) => Err(OperationError::InvalidArgumentType { expected: ArgumentType::TwoU16, provided: ArgumentType::OneU32 }),
175 ArgumentValue::TwoU16(a, b) => Ok((*a, *b)),
176 ArgumentValue::FourU8(_, _, _, _) => Err(OperationError::InvalidArgumentType { expected: ArgumentType::TwoU16, provided: ArgumentType::FourU8 }),
177 }
178 }
179 ArgumentScheme::Range(_) => { Err(OperationError::InvalidArgumentType { expected: ArgumentType::TwoU16, provided: ArgumentType::Range }) }
180 }
181 }
182
183 pub fn get_four_u8(&self) -> OperationResult<(u8, u8, u8, u8)> {
185 match self {
186 ArgumentScheme::NoArgument => { Err(OperationError::InvalidArgumentType { expected: ArgumentType::FourU8, provided: ArgumentType::NoArgument }) }
187 ArgumentScheme::Value(v) => {
188 match v {
189 ArgumentValue::OneU32(_) => Err(OperationError::InvalidArgumentType { expected: ArgumentType::FourU8, provided: ArgumentType::OneU32 }),
190 ArgumentValue::TwoU16(_, _) => Err(OperationError::InvalidArgumentType { expected: ArgumentType::FourU8, provided: ArgumentType::TwoU16 }),
191 ArgumentValue::FourU8(a, b, c, d) => Ok((*a, *b, *c, *d)),
192 }
193 }
194 ArgumentScheme::Range(_) => { Err(OperationError::InvalidArgumentType { expected: ArgumentType::FourU8, provided: ArgumentType::Range }) }
195 }
196 }
197}
198
199#[derive(Copy, Clone, Debug, Eq, PartialEq)]
200pub struct InstructionScheme {
201 pub identifier: OperationId,
202 pub target: RegisterId,
203 pub argument: ArgumentScheme,
204}
205
206impl InstructionScheme {
207 pub fn to_u64(&self) -> u64 {
208 (self.identifier.to_u16() as u64) << 48
209 | (self.target.to_u16() as u64) << 32
210 | self.argument.to_u32() as u64
211 }
212}