Skip to main content

instruction_decoder/
lib.rs

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}