c6000_disassembler/instruction/
parser.rs1use std::{
2 collections::HashMap,
3 io::{Error, ErrorKind, Result},
4};
5
6use crate::instruction::{
7 ConditionalOperation, Unit,
8 register::{ControlRegister, Register},
9};
10
11pub fn parse(
12 opcode: u32,
13 format: &[ParsingInstruction],
14) -> Result<HashMap<String, ParsedVariable>> {
15 let mut resulting_map = HashMap::<String, ParsedVariable>::new();
16 let mut temp_opcode = opcode;
17
18 for instruction in format {
19 match instruction {
20 ParsingInstruction::Match { size, value } => {
21 let masked_value = read_u32(&mut temp_opcode, *size);
22 if masked_value != *value {
23 return Err(Error::new(
24 ErrorKind::InvalidInput,
25 format!(
26 "Opcode does not match instruction format (got {masked_value:b} instead of {value:b})"
27 ),
28 ));
29 }
30 }
31 ParsingInstruction::MatchMultiple { size, values } => {
32 let masked_value = read_u32(&mut temp_opcode, *size);
33 for value in values {
34 if masked_value == *value {
35 continue;
36 }
37 }
38 return Err(Error::new(
39 ErrorKind::InvalidInput,
40 format!("Opcode does not match instruction format (got {masked_value:b})"),
41 ));
42 }
43 ParsingInstruction::Bit { name } => {
44 resulting_map.insert(
45 name.clone(),
46 ParsedVariable::Bool(read_bool(&mut temp_opcode)),
47 );
48 }
49 ParsingInstruction::BitMatch { name, value } => {
50 let read_value = read_bool(&mut temp_opcode);
51 if read_value != *value {
52 return Err(Error::new(
53 ErrorKind::InvalidInput,
54 format!(
55 "Opcode does not match instruction format ({name} is {read_value} instead of {value})"
56 ),
57 ));
58 }
59 resulting_map.insert(name.clone(), ParsedVariable::Bool(read_value));
60 }
61 ParsingInstruction::BitArray { size, name } => {
62 let mut value = Vec::<bool>::new();
63 for _ in 0..*size {
64 value.push(read_bool(&mut temp_opcode));
65 }
66 resulting_map.insert(name.clone(), ParsedVariable::BoolVec(value));
67 }
68 ParsingInstruction::Unsigned { size, name } => {
69 let value = read_u32(&mut temp_opcode, *size);
70 let parsed_variable = {
71 if *size > 8 {
72 ParsedVariable::U32(value)
73 } else {
74 ParsedVariable::U8(value as u8)
75 }
76 };
77 resulting_map.insert(name.clone(), parsed_variable);
78 }
79 ParsingInstruction::Signed { size, name } => {
80 let value = read_i32(&mut temp_opcode, *size);
81 resulting_map.insert(name.clone(), ParsedVariable::I32(value));
82 }
83 ParsingInstruction::Register { size, name }
84 | ParsingInstruction::RegisterCrosspath { size, name }
85 | ParsingInstruction::RegisterPair { size, name } => {
86 let u32_value = read_u32(&mut temp_opcode, *size);
87 let side = {
88 let mut s = ParsedVariable::try_get(&resulting_map, "s")?.get_bool()?;
89 if let ParsingInstruction::RegisterCrosspath { size: _, name: _ } = instruction
90 {
91 let crosspath = ParsedVariable::try_get(&resulting_map, "x")?.get_bool()?;
92 s ^= crosspath;
93 }
94 s
95 };
96 let value = {
97 if let ParsingInstruction::RegisterPair { size: _, name: _ } = instruction {
98 Register::from_pair(u32_value as u8, side)
99 } else {
100 Register::from(u32_value as u8, side)
101 }
102 };
103 resulting_map.insert(name.clone(), ParsedVariable::Register(value));
104 }
105 ParsingInstruction::ControlRegister { size, name } => {
106 let low_bits = read_u32(&mut temp_opcode, *size) as u8;
107 let high_bits = {
108 if let Ok(variable) = ParsedVariable::try_get(&resulting_map, "crhi") {
109 variable.get_u8()?
110 } else {
111 0
112 }
113 };
114 let Some(value) = ControlRegister::from(low_bits, high_bits) else {
115 return Err(Error::other(format!(
116 "Invalid Control Register values (got crhi crlo {high_bits:b} {low_bits:b})"
117 )));
118 };
119 resulting_map.insert(name.clone(), ParsedVariable::ControlRegister(value));
120 }
121 ParsingInstruction::LSDUnit { name } => {
122 let unit = match read_u32(&mut temp_opcode, 2) {
123 0 => Unit::L,
124 1 => Unit::S,
125 2 => Unit::D,
126 num => return Err(Error::other(format!("Invalid LSDUnit (got {num})"))),
127 };
128 resulting_map.insert(name.clone(), ParsedVariable::Unit(unit));
129 }
130 ParsingInstruction::ConditionalOperation { name } => {
131 let z = read_bool(&mut temp_opcode);
132 let creg = read_u32(&mut temp_opcode, 3) as u8;
133 resulting_map.insert(
134 name.clone(),
135 ParsedVariable::ConditionalOperation(ConditionalOperation::from(creg, z)),
136 );
137 }
138 }
139 }
140
141 Ok(resulting_map)
142}
143
144#[derive(Debug)]
145pub enum ParsingInstruction {
146 Match {
147 size: usize,
148 value: u32,
149 },
150 MatchMultiple {
151 size: usize,
152 values: Vec<u32>,
153 },
154 Bit {
155 name: String,
156 },
157 BitMatch {
158 name: String,
159 value: bool,
160 },
161 BitArray {
162 size: usize,
163 name: String,
164 },
165 Unsigned {
166 size: usize,
167 name: String,
168 },
169 Signed {
170 size: usize,
171 name: String,
172 },
173 Register {
174 size: usize,
175 name: String,
176 },
177 RegisterPair {
178 size: usize,
179 name: String,
180 },
181 RegisterCrosspath {
182 size: usize,
183 name: String,
184 },
185 ControlRegister {
186 size: usize,
187 name: String,
188 },
189 LSDUnit {
191 name: String,
192 },
193 ConditionalOperation {
194 name: String,
195 },
196}
197
198#[derive(Clone)]
199pub enum ParsedVariable {
200 Bool(bool),
201 BoolVec(Vec<bool>),
202 U32(u32),
203 U8(u8),
204 I32(i32),
205 Register(Register),
206 ControlRegister(ControlRegister),
207 Unit(Unit),
208 ConditionalOperation(Option<ConditionalOperation>),
209}
210
211impl ParsedVariable {
212 pub fn get_bool(&self) -> Result<bool> {
213 if let ParsedVariable::Bool(value) = self {
214 Ok(*value)
215 } else {
216 Err(Error::other("Not a Bool variable"))
217 }
218 }
219
220 pub fn get_bool_vec(&self) -> Result<Vec<bool>> {
221 if let ParsedVariable::BoolVec(value) = self {
222 Ok(value.clone())
223 } else {
224 Err(Error::other("Not a BoolVec variable"))
225 }
226 }
227
228 pub fn get_u32(&self) -> Result<u32> {
229 if let ParsedVariable::U32(value) = self {
230 Ok(*value)
231 } else if let ParsedVariable::U8(value) = self {
232 Ok(*value as u32)
233 } else {
234 Err(Error::other("Not a U32 variable"))
235 }
236 }
237
238 pub fn get_i32(&self) -> Result<i32> {
239 if let ParsedVariable::I32(value) = self {
240 Ok(*value)
241 } else if let ParsedVariable::U32(value) = self {
242 Ok(u32::cast_signed(*value))
243 } else if let ParsedVariable::U8(value) = self {
244 Ok(u8::cast_signed(*value) as i32)
245 } else {
246 Err(Error::other("Not a U32 variable"))
247 }
248 }
249
250 pub fn get_u8(&self) -> Result<u8> {
251 if let ParsedVariable::U8(value) = self {
252 Ok(*value)
253 } else if let ParsedVariable::U32(value) = self {
254 Ok(*value as u8)
255 } else {
256 Err(Error::other("Not a U8 variable"))
257 }
258 }
259
260 pub fn get_register(&self) -> Result<Register> {
261 if let ParsedVariable::Register(value) = self {
262 Ok(*value)
263 } else {
264 Err(Error::other("Not a Register variable"))
265 }
266 }
267
268 pub fn get_control_register(&self) -> Result<ControlRegister> {
269 if let ParsedVariable::ControlRegister(value) = self {
270 Ok(*value)
271 } else {
272 Err(Error::other("Not a Control Register variable"))
273 }
274 }
275
276 pub fn get_unit(&self) -> Result<Unit> {
277 if let ParsedVariable::Unit(value) = self {
278 Ok(*value)
279 } else {
280 Err(Error::other("Not a Unit variable"))
281 }
282 }
283
284 pub fn get_conditional_operation(&self) -> Result<Option<ConditionalOperation>> {
285 if let ParsedVariable::ConditionalOperation(value) = self {
286 Ok(*value)
287 } else {
288 Err(Error::other("Not a Conditional Operation variable"))
289 }
290 }
291
292 pub fn try_get<'a>(hashmap: &'a HashMap<String, Self>, name: &str) -> Result<&'a Self> {
293 let Some(value) = hashmap.get(name) else {
294 return Err(Error::other("Parsing error"));
295 };
296 Ok(value)
297 }
298}
299
300fn read_bool(opcode: &mut u32) -> bool {
301 let value = if *opcode & 1 == 1 { true } else { false };
302 *opcode >>= 1;
303 value
304}
305
306fn read_i32(opcode: &mut u32, size: usize) -> i32 {
307 let mask = create_mask(size);
308 let mut value_u32 = *opcode & mask;
309 *opcode >>= size;
310 let sign_bit_mask = 1 << (size - 1);
311 let value = {
312 if value_u32 & sign_bit_mask == sign_bit_mask {
313 value_u32 ^= mask;
314 value_u32 += 1;
315 -(value_u32 as i32)
316 } else {
317 value_u32 as i32
318 }
319 };
320 value
321}
322
323fn read_u32(opcode: &mut u32, size: usize) -> u32 {
324 let mask = create_mask(size);
325 let value = *opcode & mask;
326 *opcode >>= size;
327 value
328}
329
330fn create_mask(size: usize) -> u32 {
331 let mut mask = 0u32;
332 for _ in 0..size {
333 mask <<= 1;
334 mask += 1;
335 }
336 mask
337}