1use std::{
2 collections::{BTreeMap, HashMap},
3 str::FromStr,
4};
5
6use toml::{map::Map, Table, Value};
7
8#[cfg(test)]
9mod tests;
10
11#[cfg(feature = "specs")]
12pub mod specs;
13
14pub struct Decoder {
15 instruction_sets: Vec<InstructionSet>,
16}
17
18struct InstructionSet {
19 bit_width: usize,
20 formats: BTreeMap<String, InstructionFormat>,
21 parts: HashMap<String, PartDecoder>,
22 mappings: HashMap<String, Mapping>,
23}
24
25fn parse_usize(s: &str) -> usize {
26 if let Some(s) = s.strip_prefix("0x") {
27 usize::from_str_radix(s, 16)
28 } else if let Some(s) = s.strip_prefix("0o") {
29 usize::from_str_radix(s, 8)
30 } else if let Some(s) = s.strip_prefix("0b") {
31 usize::from_str_radix(s, 2)
32 } else {
33 s.parse::<usize>()
34 }
35 .unwrap()
36}
37
38fn parse_u128(s: &str) -> u128 {
39 if let Some(s) = s.strip_prefix("0x") {
40 u128::from_str_radix(s, 16)
41 } else if let Some(s) = s.strip_prefix("0o") {
42 u128::from_str_radix(s, 8)
43 } else if let Some(s) = s.strip_prefix("0b") {
44 u128::from_str_radix(s, 2)
45 } else {
46 s.parse::<u128>()
47 }
48 .unwrap()
49}
50
51fn handle_err_get(
52 table: &Table,
53 error_stack: &mut Vec<String>,
54 key: &str,
55 prefix: &str,
56 sample: Value,
57) -> Value {
58 let display_key = if !prefix.is_empty() {
59 format!("{prefix}.{key}")
60 } else {
61 key.to_string()
62 };
63 let val = table.get(key);
64 if let Some(v) = val {
65 if v.same_type(&sample) {
66 v.clone()
67 } else {
68 error_stack.push(format!(
69 "key '{}' is of type '{}' instead of type '{}'",
70 display_key,
71 v.type_str(),
72 sample.type_str()
73 ));
74 sample
75 }
76 } else {
77 error_stack.push(format!("key '{display_key}' not found in toml"));
78 sample
79 }
80}
81
82fn handle_err_get_multitype(
83 table: &Table,
84 error_stack: &mut Vec<String>,
85 key: &str,
86 prefix: &str,
87 samples: &Vec<Value>,
88) -> Value {
89 let display_key = if !prefix.is_empty() {
90 format!("{prefix}.{key}")
91 } else {
92 key.to_string()
93 };
94 let val = table.get(key);
95 let mut result_value = samples[0].clone();
96 if let Some(v) = val {
97 let mut found = false;
98 for sample in samples {
99 if v.same_type(sample) {
100 result_value = v.clone();
101 found = true;
102 }
103 }
104 if !found {
105 error_stack.push(format!(
106 "key '{}' is of type '{}' which is not in the list ['{}']",
107 display_key,
108 v.type_str(),
109 samples
110 .iter()
111 .map(|x| x.type_str().to_string())
112 .collect::<Vec<String>>()
113 .join(", ")
114 ));
115 }
116 result_value
117 } else {
118 error_stack.push(format!("key '{display_key}' not found in toml"));
119 result_value
120 }
121}
122
123impl InstructionSet {
124 pub fn new(table: &Table, error_stack: &mut Vec<String>) -> Self {
125 let bit_width = handle_err_get(table, error_stack, "width", "", Value::Integer(0))
126 .as_integer()
127 .unwrap() as usize;
128
129 let mappings_table_value = handle_err_get(
130 table,
131 error_stack,
132 "mappings",
133 "",
134 Value::Table(Table::new()),
135 );
136 let mappings_table = mappings_table_value.as_table().unwrap();
137
138 let mapping_names_value = handle_err_get(
139 mappings_table,
140 error_stack,
141 "names",
142 "mappings",
143 Value::Array(vec![]),
144 );
145 let mapping_names = mapping_names_value.as_array().unwrap();
146 let mut mapping_map = HashMap::new();
147 for value in mapping_names {
148 if let Some(mapping_name) = value.as_str() {
149 let mappings_val = handle_err_get_multitype(
150 mappings_table,
151 error_stack,
152 mapping_name,
153 "mappings",
154 &vec![Value::Array(vec![]), Value::Table(Table::new())],
155 );
156 let (map_map, strict) = match mappings_val {
157 Value::Array(val) => Some((
158 val.iter()
159 .enumerate()
160 .map(|(k, v)| (k, v.clone()))
161 .collect::<HashMap<usize, Value>>(),
162 true,
163 )),
164 Value::Table(val) => Some((
165 val.iter()
166 .map(|(k, v)| (parse_usize(k), v.clone()))
167 .collect::<HashMap<usize, Value>>(),
168 false,
169 )),
170 _ => None,
171 }
172 .unwrap();
173
174 let mappings: Mapping = Mapping::new(&map_map, strict, error_stack, mapping_name);
175 mapping_map.insert(mapping_name.to_string(), mappings);
176 } else {
177 error_stack.push(format!(
178 "value of array entry in 'mappings.names' is of type '{}' instead of type 'string'",
179 value.type_str()
180 ));
181 }
182 }
183
184 let formats_table_value = handle_err_get(
185 table,
186 error_stack,
187 "formats",
188 "",
189 Value::Table(Table::new()),
190 );
191 let formats_table = formats_table_value.as_table().unwrap();
192
193 let parts: HashMap<String, PartDecoder> = handle_err_get(
194 formats_table,
195 error_stack,
196 "parts",
197 "formats",
198 Value::Array(vec![]),
199 )
200 .as_array()
201 .unwrap_or(&vec![])
202 .iter()
203 .filter_map(|x| {
204 let parr = x.as_array().unwrap();
205 if parr.len() < 3 || parr.len() > 4 {
206 error_stack.push(format!("expected length of part {parr:?} to be 3 or 4, in the form of [name: string, bitwidth: integer, type: string, (format: string = \"decimal\")]"));
207 None
208 } else {
209 let name = parr[0].as_str().unwrap_or("").to_string();
210 Some((name, PartDecoder::new(parr, error_stack, &mapping_map)))
211 }
212 })
213 .collect();
214
215 let types_table_value =
216 handle_err_get(table, error_stack, "types", "", Value::Table(Table::new()));
217 let types_table = types_table_value.as_table().unwrap();
218 let types: HashMap<String, InstructionType> = handle_err_get(
219 types_table,
220 error_stack,
221 "names",
222 "types",
223 Value::Array(vec![]),
224 )
225 .as_array()
226 .unwrap()
227 .iter()
228 .enumerate()
229 .filter_map(|(i, x)| {
230 if x.is_str() {
231 Some((
232 x.as_str().unwrap().to_string(),
233 InstructionType::new(
234 handle_err_get(
235 types_table,
236 error_stack,
237 x.as_str().unwrap(),
238 "types",
239 Value::Array(vec![]),
240 )
241 .as_array()
242 .unwrap(),
243 &parts,
244 error_stack,
245 format!("types.{}", x.as_str().unwrap()).as_str(),
246 x.as_str().unwrap(),
247 bit_width,
248 ),
249 ))
250 } else {
251 error_stack.push(format!(
252 "value of entry 'types.names[{}]' is of type '{}' instead of type 'string'",
253 i,
254 x.type_str()
255 ));
256 None
257 }
258 })
259 .collect();
260
261 let formats_table_value = handle_err_get(
262 table,
263 error_stack,
264 "formats",
265 "",
266 Value::Table(Table::new()),
267 );
268 let formats_table = formats_table_value.as_table().unwrap();
269
270 let formats: BTreeMap<String, InstructionFormat> = handle_err_get(
271 formats_table,
272 error_stack,
273 "names",
274 "formats",
275 Value::Array(vec![]),
276 )
277 .as_array()
278 .unwrap()
279 .iter()
280 .enumerate()
281 .filter_map(|(i, x)| {
282 if x.is_str() {
283 Some((
284 x.as_str().unwrap().to_string(),
285 InstructionFormat::new(
286 table,
287 &x.as_str().unwrap().to_string(),
288 &types,
289 error_stack,
290 "",
291 ),
292 ))
293 } else {
294 error_stack.push(format!(
295 "value of entry 'formats.names[{}]' is of type '{}' instead of type 'string'",
296 i,
297 x.type_str()
298 ));
299 None
300 }
301 })
302 .collect();
303
304 for (fmt_name, fmt) in &formats {
305 for (repr_name, repr) in &fmt.repr {
306 let mut idx = 0;
307 while idx < repr.len() && repr[idx..].contains('%') {
308 let begin = repr[idx..].find('%').unwrap() + 1 + idx;
309 if !repr[begin..].contains('%') {
310 error_stack.push(format!(
311 "no closing % found in format {fmt_name}.{repr_name}: '{repr}'"
312 ));
313 break;
314 } else {
315 let end = repr[begin..].find('%').unwrap() + begin;
316 let var_name = &repr[begin..end];
317
318 let nmatches = fmt
319 .instruction_type
320 .slices
321 .iter()
322 .filter(|x| x.name == var_name)
323 .count();
324
325 if nmatches == 0 {
326 error_stack.push(format!(
327 "format of {fmt_name}.{repr_name} is trying to reference nonexistant slice {var_name}"
328 ));
329 }
330 idx = end + 1;
331 }
332 }
333 }
334 }
335
336 InstructionSet {
337 bit_width,
338 formats,
339 parts,
340 mappings: mapping_map,
341 }
342 }
343}
344
345#[derive(Clone)]
346enum PartType {
347 Boolean,
348 Char,
349 I8,
350 I16,
351 I32,
352 I64,
353 U8,
354 U16,
355 U32,
356 U64,
357 ISize,
358 USize,
359 F32,
360 F64,
361 Mapping(String),
362 VInt,
363 None,
364}
365
366enum PartTypeValue {
367 Boolean(bool),
368 Char(char),
369 I8(i8),
370 I16(i16),
371 I32(i32),
372 I64(i64),
373 U8(u8),
374 U16(u16),
375 U32(u32),
376 U64(u64),
377 ISize(isize),
378 USize(usize),
379 F32(f32),
380 F64(f64),
381 Mapping(String),
382 VInt(i128),
383 None,
384}
385
386#[derive(Clone)]
387enum NumberRadix {
388 Decimal,
389 Hexadecimal,
390 Octal,
391 Binary,
392}
393
394impl FromStr for NumberRadix {
395 type Err = String;
396
397 fn from_str(s: &str) -> Result<Self, Self::Err> {
398 match s {
399 "" => Ok(NumberRadix::Decimal),
400 "decimal" => Ok(NumberRadix::Decimal),
401 "dec" => Ok(NumberRadix::Decimal),
402 "d" => Ok(NumberRadix::Decimal),
403 "10" => Ok(NumberRadix::Decimal),
404 "hexadecimal" => Ok(NumberRadix::Hexadecimal),
405 "hex" => Ok(NumberRadix::Hexadecimal),
406 "h" => Ok(NumberRadix::Hexadecimal),
407 "x" => Ok(NumberRadix::Hexadecimal),
408 "0x" => Ok(NumberRadix::Hexadecimal),
409 "16" => Ok(NumberRadix::Hexadecimal),
410 "octal" => Ok(NumberRadix::Octal),
411 "oct" => Ok(NumberRadix::Octal),
412 "o" => Ok(NumberRadix::Octal),
413 "0o" => Ok(NumberRadix::Octal),
414 "8" => Ok(NumberRadix::Octal),
415 "binary" => Ok(NumberRadix::Binary),
416 "bin" => Ok(NumberRadix::Binary),
417 "b" => Ok(NumberRadix::Binary),
418 "0b" => Ok(NumberRadix::Binary),
419 "2" => Ok(NumberRadix::Binary),
420 _ => Err("not a valid desctriptor for base 2, 8, 10 or 16".to_string()),
421 }
422 }
423}
424
425impl NumberRadix {
426 fn format_unsigned(&self, value: u128) -> String {
427 match self {
428 NumberRadix::Decimal => format!("{value}"),
429 NumberRadix::Hexadecimal => format!("{value:#x}"),
430 NumberRadix::Octal => format!("{value:#o}"),
431 NumberRadix::Binary => format!("{value:#b}"),
432 }
433 }
434
435 fn format_signed(&self, value: i128) -> String {
436 match self {
437 NumberRadix::Decimal => format!("{value}"),
438 NumberRadix::Hexadecimal => {
439 if value < 0 {
440 format!("-{:#x}", -value)
441 } else {
442 format!("{value:#x}")
443 }
444 }
445 NumberRadix::Octal => {
446 if value < 0 {
447 format!("-{:#o}", -value)
448 } else {
449 format!("{value:#o}")
450 }
451 }
452 NumberRadix::Binary => {
453 if value < 0 {
454 format!("-{:#b}", -value)
455 } else {
456 format!("{value:#b}")
457 }
458 }
459 }
460 }
461
462 fn format_part_type_val(&self, value_type: PartTypeValue) -> String {
463 match value_type {
464 PartTypeValue::Boolean(a) => format!("{a}"),
465 PartTypeValue::Char(a) => format!("{a}"),
466 PartTypeValue::I8(a) => self.format_signed(a as i128),
467 PartTypeValue::I16(a) => self.format_signed(a as i128),
468 PartTypeValue::I32(a) => self.format_signed(a as i128),
469 PartTypeValue::I64(a) => self.format_signed(a as i128),
470 PartTypeValue::U8(a) => self.format_unsigned(a as u128),
471 PartTypeValue::U16(a) => self.format_unsigned(a as u128),
472 PartTypeValue::U32(a) => self.format_unsigned(a as u128),
473 PartTypeValue::U64(a) => self.format_unsigned(a as u128),
474 PartTypeValue::ISize(a) => self.format_signed(a as i128),
475 PartTypeValue::USize(a) => self.format_unsigned(a as u128),
476 PartTypeValue::F32(a) => format!("{a}"),
477 PartTypeValue::F64(a) => format!("{a}"),
478 PartTypeValue::Mapping(a) => a.to_string(),
479 PartTypeValue::VInt(a) => self.format_signed(a),
480 PartTypeValue::None => "".to_string(),
481 }
482 }
483}
484
485impl PartialEq for PartTypeValue {
486 fn eq(&self, other: &Self) -> bool {
487 match (self, other) {
488 (Self::Boolean(l0), Self::Boolean(r0)) => l0 == r0,
489 (Self::Char(l0), Self::Char(r0)) => l0 == r0,
490 (Self::I8(l0), Self::I8(r0)) => l0 == r0,
491 (Self::I16(l0), Self::I16(r0)) => l0 == r0,
492 (Self::I32(l0), Self::I32(r0)) => l0 == r0,
493 (Self::I64(l0), Self::I64(r0)) => l0 == r0,
494 (Self::U8(l0), Self::U8(r0)) => l0 == r0,
495 (Self::U16(l0), Self::U16(r0)) => l0 == r0,
496 (Self::U32(l0), Self::U32(r0)) => l0 == r0,
497 (Self::U64(l0), Self::U64(r0)) => l0 == r0,
498 (Self::ISize(l0), Self::ISize(r0)) => l0 == r0,
499 (Self::USize(l0), Self::USize(r0)) => l0 == r0,
500 (Self::F32(l0), Self::F32(r0)) => l0 == r0,
501 (Self::F64(l0), Self::F64(r0)) => l0 == r0,
502 (Self::Mapping(l0), Self::Mapping(r0)) => l0 == r0,
503 (Self::VInt(l0), Self::VInt(r0)) => l0 == r0,
504 _ => false,
505 }
506 }
507}
508
509impl FromStr for PartType {
510 type Err = ();
511
512 fn from_str(s: &str) -> Result<Self, Self::Err> {
513 match s {
514 "boolean" => Ok(PartType::Boolean),
515 "char" => Ok(PartType::Char),
516 "i8" => Ok(PartType::I8),
517 "i16" => Ok(PartType::I16),
518 "i32" => Ok(PartType::I32),
519 "i64" => Ok(PartType::I64),
520 "u8" => Ok(PartType::U8),
521 "u16" => Ok(PartType::U16),
522 "u32" => Ok(PartType::U32),
523 "u64" => Ok(PartType::U64),
524 "isize" => Ok(PartType::ISize),
525 "usize" => Ok(PartType::USize),
526 "f32" => Ok(PartType::F32),
527 "f64" => Ok(PartType::F64),
528 "VInt" => Ok(PartType::VInt),
529 "" => Ok(PartType::None),
530 _ => Ok(PartType::Mapping(s.to_string())),
531 }
532 }
533}
534
535impl PartType {
536 fn get_unsigned(&self, unsigned_imm: bool) -> bool {
537 match self {
538 PartType::Boolean => true,
539 PartType::Char => true,
540 PartType::I8 => false,
541 PartType::I16 => false,
542 PartType::I32 => false,
543 PartType::I64 => false,
544 PartType::U8 => true,
545 PartType::U16 => true,
546 PartType::U32 => true,
547 PartType::U64 => true,
548 PartType::ISize => false,
549 PartType::USize => true,
550 PartType::F32 => true,
551 PartType::F64 => true,
552 PartType::Mapping(_) => true,
553 PartType::VInt => unsigned_imm,
554 PartType::None => true,
555 }
556 }
557
558 fn is_mapping(&self) -> bool {
559 matches!(self, PartType::Mapping(_))
560 }
561}
562
563#[derive(Clone)]
564struct PartDecoder {
565 part_type: PartType,
566 number_radix: NumberRadix,
567}
568
569impl PartDecoder {
570 pub fn new(
571 part_array: &[Value],
572 error_stack: &mut Vec<String>,
573 mapping_map: &HashMap<String, Mapping>,
574 ) -> Self {
575 let number_radix = if part_array.len() == 4 {
576 NumberRadix::from_str(part_array[3].as_str().unwrap_or("")).unwrap()
577 } else {
578 NumberRadix::Decimal
579 };
580 let part_type_name = part_array[2].as_str().unwrap_or("");
581 let part_type = PartType::from_str(part_type_name).unwrap_or(PartType::None);
582 if part_type.is_mapping() && !mapping_map.contains_key(part_type_name) {
583 error_stack.push(format!(
584 "mapping {} referenced in type of part {} does not exist",
585 part_type_name,
586 part_array[0].as_str().unwrap_or(""),
587 ));
588 }
589 PartDecoder {
590 part_type,
591 number_radix,
592 }
593 }
594
595 fn decode(&self, value: u128, mappings: &HashMap<String, Mapping>) -> PartTypeValue {
596 match &self.part_type {
597 PartType::Boolean => PartTypeValue::Boolean(value != 0),
598 PartType::Char => PartTypeValue::Char(char::from_u32(value as u32).unwrap()),
599 PartType::I8 => PartTypeValue::I8(value as i8),
600 PartType::I16 => PartTypeValue::I16(value as i16),
601 PartType::I32 => PartTypeValue::I32(value as i32),
602 PartType::I64 => PartTypeValue::I64(value as i64),
603 PartType::U8 => PartTypeValue::U8(value as u8),
604 PartType::U16 => PartTypeValue::U16(value as u16),
605 PartType::U32 => PartTypeValue::U32(value as u32),
606 PartType::U64 => PartTypeValue::U64(value as u64),
607 PartType::ISize => PartTypeValue::ISize(value as isize),
608 PartType::USize => PartTypeValue::USize(value as usize),
609 PartType::F32 => PartTypeValue::F32(f32::from_bits(value as u32)),
610 PartType::F64 => PartTypeValue::F64(f64::from_bits(value as u64)),
611 PartType::Mapping(mapping_set_name) => PartTypeValue::Mapping(
612 mappings[mapping_set_name]
613 .names
614 .get(&(value as usize))
615 .unwrap_or(&if mappings[mapping_set_name].strict {
616 format!("ERROR({:#b})", value as usize)
617 } else {
618 format!("{:#x}", value as usize)
619 })
620 .clone(),
621 ),
622 PartType::VInt => PartTypeValue::VInt(value as i128),
623 PartType::None => PartTypeValue::None,
624 }
625 }
626}
627
628struct Mapping {
629 names: HashMap<usize, String>,
630 strict: bool,
631}
632
633impl Mapping {
634 pub fn new(
635 list: &HashMap<usize, Value>,
636 strict: bool,
637 error_stack: &mut Vec<String>,
638 table_prefix: &str,
639 ) -> Self {
640 let names = list
641 .iter()
642 .map(|(k, v)| {
643 if !v.is_str() {
644 error_stack.push(format!(
645 "mapping value at {table_prefix}[{k}] is not type 'string'"
646 ));
647 }
648 (*k, v.as_str().unwrap_or("").to_string())
649 })
650 .collect();
651 Mapping { names, strict }
652 }
653}
654
655struct InstructionFormat {
656 repr: HashMap<String, String>,
657 instruction_type: InstructionType,
658 instructions: Vec<Instruction>,
659}
660
661impl InstructionFormat {
662 pub fn new(
663 table: &Table,
664 name: &String,
665 types: &HashMap<String, InstructionType>,
666 error_stack: &mut Vec<String>,
667 table_prefix: &str,
668 ) -> Self {
669 let format_table_value = handle_err_get(
670 table,
671 error_stack,
672 name,
673 table_prefix,
674 Value::Table(Table::new()),
675 );
676 let format_table = format_table_value.as_table().unwrap();
677 let repr_value = handle_err_get(
678 format_table,
679 error_stack,
680 "repr",
681 name,
682 Value::Table(Table::new()),
683 );
684 let repr = repr_value
685 .as_table()
686 .unwrap()
687 .iter()
688 .filter_map(|(k, v)| {
689 if v.is_str() {
690 Some((k.clone(), v.as_str().unwrap().to_string()))
691 } else {
692 error_stack.push(format!("value of {name}.repr.{k} is not type 'string'"));
693 None
694 }
695 })
696 .collect();
697 let instruction_type = &types[table[name]["type"].as_str().unwrap_or("")];
698 let instructions = table[name]["instructions"]
699 .as_table()
700 .unwrap()
701 .iter()
702 .enumerate()
703 .map(|(i, (x, y))| {
704 Instruction::new(
705 x,
706 y.as_table().unwrap(),
707 error_stack,
708 format!("{name}.instructions[{i}]").as_str(),
709 )
710 })
711 .collect();
712 InstructionFormat {
713 repr,
714 instruction_type: instruction_type.clone(),
715 instructions,
716 }
717 }
718
719 fn parse(
720 &self,
721 instruction: u128,
722 bit_width: usize,
723 part_decoders: &HashMap<String, PartDecoder>,
724 unsigned_imm: bool,
725 ) -> HashMap<String, SliceValue> {
726 self.instruction_type
727 .parse(instruction, bit_width, unsigned_imm, part_decoders)
728 }
729}
730
731#[derive(Clone)]
732struct SliceValue {
733 name: String,
734 value: u128,
735}
736
737impl SliceValue {
738 pub fn new(
739 name: &str,
740 value: u128,
741 idx: usize,
742 bit_width: usize,
743 slice_extend: usize,
744 unsigned_imm: bool,
745 part_type: PartType,
746 ) -> Self {
747 let mut tmp = value << idx;
748 let unsigned = part_type.get_unsigned(unsigned_imm);
749 if slice_extend > 0 && ((tmp >> (bit_width - 1)) != 0) {
750 tmp |= (1 << (slice_extend + bit_width)) - (1 << bit_width);
751 }
752 if !unsigned && ((tmp >> (bit_width - 1)) != 0) {
753 tmp |= u128::MAX - (1 << bit_width) + 1;
754 }
755 SliceValue {
756 name: name.to_owned(),
757 value: tmp,
758 }
759 }
760
761 fn join(&mut self, other_value: &SliceValue) {
762 self.value |= other_value.value;
763 }
764
765 fn get_value(
766 &self,
767 part_decoder: &PartDecoder,
768 mappigns: &HashMap<String, Mapping>,
769 ) -> PartTypeValue {
770 part_decoder.decode(self.value, mappigns)
771 }
772
773 fn get_string_value(
774 &self,
775 part_decoder: &PartDecoder,
776 mappings: &HashMap<String, Mapping>,
777 ) -> String {
778 let tmp = self.get_value(part_decoder, mappings);
779 part_decoder.number_radix.format_part_type_val(tmp)
780 }
781}
782
783#[derive(Clone)]
784struct Instruction {
785 name: String,
786 mask_u128: u128,
787 match_u128: u128,
788 unsigned_imm: bool,
789}
790
791impl Instruction {
792 pub fn new(
793 name: &str,
794 table: &Map<String, Value>,
795 error_stack: &mut Vec<String>,
796 table_prefix: &str,
797 ) -> Self {
798 let unsigned_imm = if table.contains_key("unsigned") {
799 handle_err_get(
800 table,
801 error_stack,
802 "unsigned",
803 table_prefix,
804 Value::Boolean(false),
805 )
806 .as_bool()
807 .unwrap()
808 } else {
809 false
810 };
811 let mask_u128 = handle_err_get(table, error_stack, "mask", table_prefix, Value::Integer(0))
812 .as_integer()
813 .unwrap() as u128;
814 let match_u128 =
815 handle_err_get(table, error_stack, "match", table_prefix, Value::Integer(0))
816 .as_integer()
817 .unwrap() as u128;
818 Instruction {
819 name: name.to_owned(),
820 mask_u128,
821 match_u128,
822 unsigned_imm,
823 }
824 }
825
826 fn matches(&self, instruction_u128: u128) -> bool {
827 (instruction_u128 & self.mask_u128) == self.match_u128
828 }
829
830 fn display(
831 &self,
832 values: &HashMap<String, SliceValue>,
833 instruction_format: &InstructionFormat,
834 part_decoders: &HashMap<String, PartDecoder>,
835 mappings: &HashMap<String, Mapping>,
836 ) -> String {
837 let mut fmt = if instruction_format.repr.contains_key(&self.name) {
838 instruction_format.repr.get(&self.name)
839 } else {
840 instruction_format.repr.get("default")
841 }
842 .unwrap()
843 .clone();
844
845 fmt = fmt.replace("$name$", &self.name);
846 while fmt.contains('%') {
847 let begin = fmt.find('%').unwrap() + 1;
848 let end = fmt[begin..].find('%').unwrap() + begin;
849 let var_name = &fmt[begin..end];
850
851 fmt = fmt.replace(
852 &fmt[begin - 1..end + 1],
853 values[var_name]
854 .get_string_value(&part_decoders[var_name], mappings)
855 .as_str(),
856 );
857 }
858 fmt
859 }
860}
861
862#[derive(Clone)]
863struct InstructionType {
864 slices: Vec<InstructionSlice>,
865}
866
867impl InstructionType {
868 pub fn new(
869 names: &[Value],
870 parts: &HashMap<String, PartDecoder>,
871 error_stack: &mut Vec<String>,
872 table_prefix: &str,
873 type_name: &str,
874 bit_width: usize,
875 ) -> Self {
876 let mut position = 0;
877 let slices = names
878 .iter()
879 .enumerate()
880 .filter_map(|(i, x)| {
881 if x.is_table() {
882 let slice = InstructionSlice::new(
883 x.as_table().unwrap(),
884 parts,
885 &position,
886 error_stack,
887 format!("{table_prefix}[{i}]").as_str(),
888 type_name,
889 bit_width,
890 );
891 position += slice.slice_top - slice.slice_bottom;
892 Some(slice)
893 } else {
894 error_stack.push(format!(
895 "Instruction Type of {table_prefix}[{i}] is not a table"
896 ));
897 None
898 }
899 })
900 .collect();
901 InstructionType { slices }
902 }
903
904 fn parse(
905 &self,
906 instruction: u128,
907 bit_width: usize,
908 unsigned_imm: bool,
909 part_decoders: &HashMap<String, PartDecoder>,
910 ) -> HashMap<String, SliceValue> {
911 self.slices
912 .iter()
913 .map(|x| {
914 let top = bit_width - x.pos;
915 let bot = bit_width + x.slice_bottom - x.pos - x.slice_top;
916 let tmp = (instruction >> bot) & ((1 << (top - bot)) - 1);
917 let slice_bit_width = self
918 .slices
919 .iter()
920 .filter(|y| y.name == x.name)
921 .max_by(|a, b| a.slice_top.cmp(&b.slice_top))
922 .unwrap()
923 .slice_top;
924 SliceValue::new(
925 &x.name,
926 tmp,
927 x.slice_bottom,
928 slice_bit_width,
929 x.slice_extend,
930 unsigned_imm,
931 part_decoders[&x.name].part_type.clone(),
932 )
933 })
934 .fold(HashMap::new(), |mut acc, x| {
935 if let Some(tmp) = acc.get_mut(&x.name) {
936 tmp.join(&x);
937 } else {
938 acc.insert(x.name.clone(), x.clone());
939 }
940 acc
941 })
942 }
943}
944
945#[derive(Clone)]
946struct InstructionSlice {
947 name: String,
948 pos: usize,
949 slice_top: usize,
950 slice_bottom: usize,
951 slice_extend: usize,
952}
953
954impl InstructionSlice {
955 pub fn new(
956 table: &Map<String, Value>,
957 parts: &HashMap<String, PartDecoder>,
958 position: &usize,
959 error_stack: &mut Vec<String>,
960 table_prefix: &str,
961 type_name: &str,
962 bit_width: usize,
963 ) -> Self {
964 let name = handle_err_get(
965 table,
966 error_stack,
967 "name",
968 "",
969 Value::String("".to_string()),
970 )
971 .as_str()
972 .unwrap()
973 .to_string();
974 if !parts.contains_key(&name) {
975 error_stack.push(format!("instruction slice with name \"{name}\" referenced in types.{type_name} not defined in formats.parts"));
976 }
977 let slice_top =
978 1 + handle_err_get(table, error_stack, "top", table_prefix, Value::Integer(0))
979 .as_integer()
980 .unwrap() as usize;
981 let slice_bottom =
982 handle_err_get(table, error_stack, "bot", table_prefix, Value::Integer(0))
983 .as_integer()
984 .unwrap() as usize;
985 let slice_extend_value = table.get("extend_top").unwrap_or(&Value::Integer(0));
986 let slice_extend = if slice_extend_value.is_integer() {
987 slice_extend_value.as_integer().unwrap() as usize
988 } else {
989 error_stack.push(format!(
990 "optional field {table_prefix}.extend_top is not of type 'integer'"
991 ));
992 0
993 };
994
995 if slice_top > bit_width || slice_bottom > bit_width {
996 error_stack.push(format!("instruction slice \"{}\" of type \"{}\" at position {} downto {} is out of range for bit width {}", name, type_name, slice_top-1, slice_bottom, bit_width));
997 };
998
999 InstructionSlice {
1000 name,
1001 pos: *position,
1002 slice_top,
1003 slice_bottom,
1004 slice_extend,
1005 }
1006 }
1007}
1008
1009impl Decoder {
1010 pub fn new(instruction_set_tomls: &[String]) -> Result<Self, Vec<Vec<String>>> {
1011 let mut error_stacks = Vec::new();
1012
1013 let decoder = Decoder {
1014 instruction_sets: instruction_set_tomls
1015 .iter()
1016 .filter_map(|x| {
1017 let mut error_stack = Vec::new();
1018
1019 let instruction_set =
1020 InstructionSet::new(&x.parse::<Table>().unwrap(), &mut error_stack);
1021 error_stacks.push(error_stack);
1022 if error_stacks.last()?.is_empty() {
1023 Some(instruction_set)
1024 } else {
1025 None
1026 }
1027 })
1028 .collect(),
1029 };
1030
1031 let mut failed = false;
1032 for error_stack in &error_stacks {
1033 if !error_stack.is_empty() {
1034 failed = true;
1035 break;
1036 }
1037 }
1038 if failed {
1039 Err(error_stacks)
1040 } else {
1041 Ok(decoder)
1042 }
1043 }
1044
1045 pub fn new_from_table(instruction_sets: Vec<Table>) -> Result<Self, Vec<Vec<String>>> {
1046 let mut error_stacks = Vec::new();
1047 let decoder = Decoder {
1048 instruction_sets: instruction_sets
1049 .iter()
1050 .filter_map(|x| {
1051 let mut error_stack = Vec::new();
1052 let instruction_set = InstructionSet::new(x, &mut error_stack);
1053 error_stacks.push(error_stack);
1054 if error_stacks.last()?.is_empty() {
1055 Some(instruction_set)
1056 } else {
1057 None
1058 }
1059 })
1060 .collect(),
1061 };
1062
1063 let mut failed = false;
1064 for error_stack in &error_stacks {
1065 if !error_stack.is_empty() {
1066 failed = true;
1067 break;
1068 }
1069 }
1070 if failed {
1071 Err(error_stacks)
1072 } else {
1073 Ok(decoder)
1074 }
1075 }
1076
1077 pub fn decode_from_string(
1078 &self,
1079 instruction: &str,
1080 bit_width: usize,
1081 ) -> Result<String, String> {
1082 self.decode(parse_u128(instruction), bit_width)
1083 }
1084
1085 pub fn decode(&self, instruction: u128, bit_width: usize) -> Result<String, String> {
1086 let finds = self.decode_all(instruction, bit_width);
1087 if finds.is_empty() {
1088 Err("Unknown Instruction".to_string())
1089 } else {
1090 Ok(finds[finds.len() - 1].clone())
1091 }
1092 }
1093
1094 pub fn decode_all(&self, instruction: u128, bit_width: usize) -> Vec<String> {
1095 let mut finds: Vec<String> = vec![];
1096
1097 for instruction_set in &self.instruction_sets {
1098 if bit_width == instruction_set.bit_width {
1099 for inst_format in instruction_set.formats.values() {
1100 for inst in &inst_format.instructions {
1101 if inst.matches(instruction) {
1102 let values = inst_format.parse(
1103 instruction,
1104 bit_width,
1105 &instruction_set.parts,
1106 inst.unsigned_imm,
1107 );
1108 finds.push(inst.display(
1109 &values,
1110 inst_format,
1111 &instruction_set.parts,
1112 &instruction_set.mappings,
1113 ));
1114 }
1115 }
1116 }
1117 }
1118 }
1119 finds
1120 }
1121
1122 pub fn decode_from_u32(&self, instruction: u32, bit_width: usize) -> Result<String, String> {
1123 self.decode(instruction as u128, bit_width)
1124 }
1125
1126 pub fn decode_all_from_u32(&self, instruction: u32, bit_width: usize) -> Vec<String> {
1127 self.decode_all(instruction as u128, bit_width)
1128 }
1129
1130 pub fn decode_from_i64(&self, instruction: i64, bit_width: usize) -> Result<String, String> {
1131 self.decode(instruction as u128, bit_width)
1132 }
1133
1134 pub fn decode_all_from_i64(&self, instruction: i64, bit_width: usize) -> Vec<String> {
1135 self.decode_all(instruction as u128, bit_width)
1136 }
1137
1138 pub fn decode_from_bytes(
1139 &self,
1140 instruction: Vec<u8>,
1141 bit_width: usize,
1142 ) -> Result<String, String> {
1143 let mut tmp = 0;
1144 for ib in instruction {
1145 tmp <<= 8;
1146 tmp |= ib as u128;
1147 }
1148 self.decode(tmp, bit_width)
1149 }
1150
1151 pub fn decode_all_from_bytes(&self, instruction: Vec<u8>, bit_width: usize) -> Vec<String> {
1152 let mut tmp = 0;
1153 for ib in instruction {
1154 tmp <<= 8;
1155 tmp |= ib as u128;
1156 }
1157 self.decode_all(tmp, bit_width)
1158 }
1159}