1use std::collections::HashMap;
7use std::fmt::Write;
8
9use crate::tree::DecodeNode;
10use crate::types::*;
11
12fn needs_variable_length_decode(def: &ValidatedDef) -> bool {
14 def.instructions.iter().any(|i| i.unit_count() > 1)
15}
16
17pub fn generate_code(
24 def: &ValidatedDef,
25 tree: &DecodeNode,
26 type_maps: &HashMap<String, String>,
27 dispatch_overrides: &HashMap<String, crate::Dispatch>,
28) -> String {
29 let mut out = String::new();
30
31 writeln!(
32 out,
33 "// Auto-generated by https://github.com/ioncodes/chipi"
34 )
35 .unwrap();
36 writeln!(out, "// Do not edit.").unwrap();
37 writeln!(out).unwrap();
38 writeln!(out, "use std::fmt;").unwrap();
39 writeln!(out, "use std::marker::PhantomData;").unwrap();
40 writeln!(out).unwrap();
41
42 let mut import_paths: Vec<&str> = type_maps.values().map(|v| v.as_str()).collect();
44 import_paths.sort();
45 import_paths.dedup();
46 for path in &import_paths {
47 if path.contains("::") {
49 writeln!(out, "use {};", path).unwrap();
50 }
51 }
52 if !import_paths.is_empty() {
53 writeln!(out).unwrap();
54 }
55
56 let word_type = word_type_for_width(def.config.width);
57 let unit_bytes = def.config.width / 8;
58 let variable_length = needs_variable_length_decode(def);
59 let enum_name = format!("{}Instruction", def.config.name);
60 let trait_name = format!("{}Format", def.config.name);
61 let default_struct = format!("Default{}Format", def.config.name);
62 let display_with = "DisplayWith";
63 let endian_suffix = match def.config.endian {
64 ByteEndian::Big => "be",
65 ByteEndian::Little => "le",
66 };
67
68 generate_display_helpers(&mut out, def);
70
71 generate_map_functions(&mut out, def);
73
74 for sd in &def.sub_decoders {
76 let dispatch = dispatch_overrides
77 .get(&sd.name)
78 .copied()
79 .unwrap_or(crate::Dispatch::FnPtrLut);
80 generate_subdecoder(&mut out, sd, dispatch);
81 }
82
83 writeln!(out, "#[derive(Debug, Clone, Copy, PartialEq, Eq)]").unwrap();
85 writeln!(out, "pub enum {} {{", enum_name).unwrap();
86
87 for instr in &def.instructions {
88 let variant_name = to_pascal_case(&instr.name);
89 if instr.resolved_fields.is_empty() {
90 writeln!(out, " {},", variant_name).unwrap();
91 } else {
92 let fields: Vec<String> = instr
93 .resolved_fields
94 .iter()
95 .map(|f| {
96 let rust_type = field_rust_type_with_maps(f, &type_maps);
97 format!("{}: {}", f.name, rust_type)
98 })
99 .collect();
100 writeln!(out, " {} {{ {} }},", variant_name, fields.join(", ")).unwrap();
101 }
102 }
103
104 writeln!(out, "}}").unwrap();
105 writeln!(out).unwrap();
106
107 generate_format_trait(&mut out, def, &trait_name, type_maps);
109
110 writeln!(out, "impl {} {{", enum_name).unwrap();
112 writeln!(out, " #[inline]").unwrap();
113
114 writeln!(
116 out,
117 " pub fn decode(data: &[u8]) -> Option<(Self, usize)> {{"
118 )
119 .unwrap();
120 writeln!(
121 out,
122 " if data.len() < {} {{ return None; }}",
123 unit_bytes
124 )
125 .unwrap();
126 writeln!(
127 out,
128 " let opcode = {}::from_{}_bytes(data[0..{}].try_into().unwrap());",
129 word_type, endian_suffix, unit_bytes
130 )
131 .unwrap();
132
133 emit_tree(
134 &mut out,
135 tree,
136 def,
137 &enum_name,
138 2,
139 variable_length,
140 &word_type,
141 type_maps,
142 );
143
144 writeln!(out, " }}").unwrap();
145 writeln!(out).unwrap();
146
147 generate_write_asm(&mut out, def, &enum_name, &trait_name);
149
150 writeln!(out).unwrap();
152 writeln!(out, " #[allow(dead_code)]").unwrap();
153 writeln!(
154 out,
155 " pub fn display<F: {}>(&self) -> {}<'_, F> {{",
156 trait_name, display_with
157 )
158 .unwrap();
159 writeln!(
160 out,
161 " {} {{ insn: self, _phantom: PhantomData }}",
162 display_with
163 )
164 .unwrap();
165 writeln!(out, " }}").unwrap();
166
167 writeln!(out, "}}").unwrap();
168 writeln!(out).unwrap();
169
170 writeln!(out, "#[allow(dead_code)]").unwrap();
172 writeln!(out, "pub struct {}<'a, F: {}> {{", display_with, trait_name).unwrap();
173 writeln!(out, " insn: &'a {},", enum_name).unwrap();
174 writeln!(out, " _phantom: PhantomData<F>,").unwrap();
175 writeln!(out, "}}").unwrap();
176 writeln!(out).unwrap();
177
178 writeln!(
179 out,
180 "impl<F: {}> fmt::Display for {}<'_, F> {{",
181 trait_name, display_with
182 )
183 .unwrap();
184 writeln!(
185 out,
186 " fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {{"
187 )
188 .unwrap();
189 writeln!(out, " self.insn.write_asm::<F>(f)").unwrap();
190 writeln!(out, " }}").unwrap();
191 writeln!(out, "}}").unwrap();
192 writeln!(out).unwrap();
193
194 writeln!(out, "pub struct {};", default_struct).unwrap();
196 writeln!(out, "impl {} for {} {{}}", trait_name, default_struct).unwrap();
197 writeln!(out).unwrap();
198
199 writeln!(out, "impl fmt::Display for {} {{", enum_name).unwrap();
201 writeln!(
202 out,
203 " fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {{"
204 )
205 .unwrap();
206 writeln!(out, " self.write_asm::<{}>(f)", default_struct).unwrap();
207 writeln!(out, " }}").unwrap();
208 writeln!(out, "}}").unwrap();
209
210 out
211}
212
213fn emit_tree(
215 out: &mut String,
216 node: &DecodeNode,
217 def: &ValidatedDef,
218 enum_name: &str,
219 indent: usize,
220 variable_length: bool,
221 word_type: &str,
222 type_maps: &HashMap<String, String>,
223) {
224 let unit_bytes = def.config.width / 8;
225 let endian_suffix = match def.config.endian {
226 ByteEndian::Big => "be",
227 ByteEndian::Little => "le",
228 };
229 let pad = " ".repeat(indent);
230 match node {
231 DecodeNode::Leaf { instruction_index } => {
232 let instr = &def.instructions[*instruction_index];
233 if let Some(guard) = leaf_guard(instr, word_type, unit_bytes, endian_suffix) {
234 writeln!(out, "{}if {} {{", pad, guard).unwrap();
235 emit_some(
236 out,
237 instr,
238 enum_name,
239 &format!("{} ", pad),
240 variable_length,
241 word_type,
242 unit_bytes,
243 endian_suffix,
244 &type_maps,
245 );
246 writeln!(out, "{}}} else {{", pad).unwrap();
247 writeln!(out, "{} None", pad).unwrap();
248 writeln!(out, "{}}}", pad).unwrap();
249 } else {
250 emit_some(
251 out,
252 instr,
253 enum_name,
254 &pad,
255 variable_length,
256 word_type,
257 unit_bytes,
258 endian_suffix,
259 &type_maps,
260 );
261 }
262 }
263 DecodeNode::PriorityLeaves { candidates } => {
264 for (i, &idx) in candidates.iter().enumerate() {
266 let instr = &def.instructions[idx];
267 let guard = leaf_guard(instr, word_type, unit_bytes, endian_suffix);
268
269 if i == 0 {
270 if let Some(guard_expr) = guard {
272 writeln!(out, "{}if {} {{", pad, guard_expr).unwrap();
273 emit_some(
274 out,
275 instr,
276 enum_name,
277 &format!("{} ", pad),
278 variable_length,
279 word_type,
280 unit_bytes,
281 endian_suffix,
282 &type_maps,
283 );
284 } else {
285 emit_some(
287 out,
288 instr,
289 enum_name,
290 &pad,
291 variable_length,
292 word_type,
293 unit_bytes,
294 endian_suffix,
295 &type_maps,
296 );
297 break; }
299 } else if i == candidates.len() - 1 {
300 writeln!(out, "{}}} else {{", pad).unwrap();
302 if let Some(guard_expr) = guard {
303 writeln!(out, "{} if {} {{", pad, guard_expr).unwrap();
304 emit_some(
305 out,
306 instr,
307 enum_name,
308 &format!("{} ", pad),
309 variable_length,
310 word_type,
311 unit_bytes,
312 endian_suffix,
313 &type_maps,
314 );
315 writeln!(out, "{} }} else {{", pad).unwrap();
316 writeln!(out, "{} None", pad).unwrap();
317 writeln!(out, "{} }}", pad).unwrap();
318 } else {
319 emit_some(
320 out,
321 instr,
322 enum_name,
323 &format!("{} ", pad),
324 variable_length,
325 word_type,
326 unit_bytes,
327 endian_suffix,
328 &type_maps,
329 );
330 }
331 writeln!(out, "{}}}", pad).unwrap();
332 } else {
333 writeln!(
335 out,
336 "{}}} else if {} {{",
337 pad,
338 guard.unwrap_or_else(|| "true".to_string())
339 )
340 .unwrap();
341 emit_some(
342 out,
343 instr,
344 enum_name,
345 &format!("{} ", pad),
346 variable_length,
347 word_type,
348 unit_bytes,
349 endian_suffix,
350 &type_maps,
351 );
352 }
353 }
354 }
355 DecodeNode::Fail => {
356 writeln!(out, "{}None", pad).unwrap();
357 }
358 DecodeNode::Branch {
359 range,
360 arms,
361 default,
362 } => {
363 let extract_expr =
364 extract_expression("opcode", &[*range], word_type, unit_bytes, endian_suffix);
365 writeln!(out, "{}match {} {{", pad, extract_expr).unwrap();
366
367 for (value, child) in arms {
368 emit_arm(
369 out,
370 child,
371 def,
372 enum_name,
373 indent + 1,
374 &format!("{:#x}", value),
375 variable_length,
376 word_type,
377 type_maps,
378 );
379 }
380
381 emit_arm(
382 out,
383 default,
384 def,
385 enum_name,
386 indent + 1,
387 "_",
388 variable_length,
389 word_type,
390 type_maps,
391 );
392
393 writeln!(out, "{}}}", pad).unwrap();
394 }
395 }
396}
397
398fn emit_arm(
400 out: &mut String,
401 node: &DecodeNode,
402 def: &ValidatedDef,
403 enum_name: &str,
404 indent: usize,
405 pattern: &str,
406 variable_length: bool,
407 word_type: &str,
408 type_maps: &HashMap<String, String>,
409) {
410 let unit_bytes = def.config.width / 8;
411 let endian_suffix = match def.config.endian {
412 ByteEndian::Big => "be",
413 ByteEndian::Little => "le",
414 };
415 let pad = " ".repeat(indent);
416 match node {
417 DecodeNode::Fail => {
418 writeln!(out, "{}{} => None,", pad, pattern).unwrap();
419 }
420 DecodeNode::Leaf { instruction_index } => {
421 let instr = &def.instructions[*instruction_index];
422 if let Some(guard) = leaf_guard(instr, word_type, unit_bytes, endian_suffix) {
423 if pattern == "_" {
424 write!(out, "{}{} if {} => ", pad, pattern, guard).unwrap();
426 emit_some_inline(
427 out,
428 instr,
429 enum_name,
430 variable_length,
431 word_type,
432 unit_bytes,
433 endian_suffix,
434 &type_maps,
435 );
436 writeln!(out, "{}{} => None,", pad, pattern).unwrap();
437 } else {
438 write!(out, "{}{} if {} => ", pad, pattern, guard).unwrap();
439 emit_some_inline(
440 out,
441 instr,
442 enum_name,
443 variable_length,
444 word_type,
445 unit_bytes,
446 endian_suffix,
447 &type_maps,
448 );
449 }
450 } else {
451 write!(out, "{}{} => ", pad, pattern).unwrap();
452 emit_some_inline(
453 out,
454 instr,
455 enum_name,
456 variable_length,
457 word_type,
458 unit_bytes,
459 endian_suffix,
460 &type_maps,
461 );
462 }
463 }
464 DecodeNode::PriorityLeaves { candidates } => {
465 writeln!(out, "{}{} => {{", pad, pattern).unwrap();
467 let inner_pad = " ".repeat(indent + 1);
468
469 for (i, &idx) in candidates.iter().enumerate() {
470 let instr = &def.instructions[idx];
471 let guard = leaf_guard(instr, word_type, unit_bytes, endian_suffix);
472
473 if i == 0 {
474 if let Some(guard_expr) = guard {
476 writeln!(out, "{}if {} {{", inner_pad, guard_expr).unwrap();
477 emit_some(
478 out,
479 instr,
480 enum_name,
481 &format!("{} ", inner_pad),
482 variable_length,
483 word_type,
484 unit_bytes,
485 endian_suffix,
486 &type_maps,
487 );
488 } else {
489 emit_some(
491 out,
492 instr,
493 enum_name,
494 &inner_pad,
495 variable_length,
496 word_type,
497 unit_bytes,
498 endian_suffix,
499 &type_maps,
500 );
501 writeln!(out, "{}}}", pad).unwrap();
502 return;
503 }
504 } else if i == candidates.len() - 1 {
505 writeln!(out, "{}}} else {{", inner_pad).unwrap();
507 if let Some(guard_expr) = guard {
508 writeln!(out, "{} if {} {{", inner_pad, guard_expr).unwrap();
509 emit_some(
510 out,
511 instr,
512 enum_name,
513 &format!("{} ", inner_pad),
514 variable_length,
515 word_type,
516 unit_bytes,
517 endian_suffix,
518 &type_maps,
519 );
520 writeln!(out, "{} }} else {{", inner_pad).unwrap();
521 writeln!(out, "{} None", inner_pad).unwrap();
522 writeln!(out, "{} }}", inner_pad).unwrap();
523 } else {
524 emit_some(
525 out,
526 instr,
527 enum_name,
528 &format!("{} ", inner_pad),
529 variable_length,
530 word_type,
531 unit_bytes,
532 endian_suffix,
533 &type_maps,
534 );
535 }
536 writeln!(out, "{}}}", inner_pad).unwrap();
537 writeln!(out, "{}}}", pad).unwrap();
538 } else {
539 writeln!(
541 out,
542 "{}}} else if {} {{",
543 inner_pad,
544 guard.unwrap_or_else(|| "true".to_string())
545 )
546 .unwrap();
547 emit_some(
548 out,
549 instr,
550 enum_name,
551 &format!("{} ", inner_pad),
552 variable_length,
553 word_type,
554 unit_bytes,
555 endian_suffix,
556 &type_maps,
557 );
558 }
559 }
560 }
561 DecodeNode::Branch {
562 range,
563 arms,
564 default,
565 } => {
566 writeln!(out, "{}{} => {{", pad, pattern).unwrap();
567 let extract_expr =
568 extract_expression("opcode", &[*range], word_type, unit_bytes, endian_suffix);
569 let inner_pad = " ".repeat(indent + 1);
570 writeln!(out, "{}match {} {{", inner_pad, extract_expr).unwrap();
571
572 for (value, child) in arms {
573 emit_arm(
574 out,
575 child,
576 def,
577 enum_name,
578 indent + 2,
579 &format!("{:#x}", value),
580 variable_length,
581 word_type,
582 type_maps,
583 );
584 }
585
586 emit_arm(
587 out,
588 default,
589 def,
590 enum_name,
591 indent + 2,
592 "_",
593 variable_length,
594 word_type,
595 type_maps,
596 );
597
598 writeln!(out, "{}}}", inner_pad).unwrap();
599 writeln!(out, "{}}}", pad).unwrap();
600 }
601 }
602}
603
604fn leaf_guard(
608 instr: &ValidatedInstruction,
609 word_type: &str,
610 unit_bytes: u32,
611 endian_suffix: &str,
612) -> Option<String> {
613 let fixed_bits = instr.fixed_bits();
614 if fixed_bits.is_empty() {
615 return None;
616 }
617
618 let mut units_map: std::collections::HashMap<u32, Vec<(u32, Bit)>> =
620 std::collections::HashMap::new();
621 for (unit, hw_bit, bit) in fixed_bits {
622 units_map.entry(unit).or_default().push((hw_bit, bit));
623 }
624
625 let mut conditions = Vec::new();
626
627 for (unit, bits) in units_map {
628 let (mask, value) = compute_mask_value(&bits);
629 if mask != 0 {
630 let source = unit_read_expr(unit, word_type, unit_bytes, endian_suffix);
631 conditions.push(format!("{} & {:#x} == {:#x}", source, mask, value));
632 }
633 }
634
635 if conditions.is_empty() {
636 None
637 } else {
638 Some(conditions.join(" && "))
639 }
640}
641
642fn emit_some_inline(
644 out: &mut String,
645 instr: &ValidatedInstruction,
646 enum_name: &str,
647 variable_length: bool,
648 word_type: &str,
649 unit_bytes: u32,
650 endian_suffix: &str,
651 type_maps: &HashMap<String, String>,
652) {
653 let variant_name = to_pascal_case(&instr.name);
654 let unit_count = instr.unit_count();
655 let bytes_consumed = unit_count * unit_bytes;
656
657 if variable_length && unit_count > 1 {
658 let cond = format!("data.len() >= {}", bytes_consumed);
660 write!(out, "if {} {{ ", cond).unwrap();
661 }
662
663 if instr.resolved_fields.is_empty() {
664 write!(
665 out,
666 "Some(({}::{}, {}))",
667 enum_name, variant_name, bytes_consumed
668 )
669 .unwrap();
670 } else {
671 let fields: Vec<String> = instr
672 .resolved_fields
673 .iter()
674 .map(|f| {
675 let extract =
676 extract_expression("opcode", &f.ranges, word_type, unit_bytes, endian_suffix);
677 let expr = apply_transforms_with_maps(&extract, &f.resolved_type, type_maps);
678 format!("{}: {}", f.name, expr)
679 })
680 .collect();
681 write!(
682 out,
683 "Some(({}::{} {{ {} }}, {}))",
684 enum_name,
685 variant_name,
686 fields.join(", "),
687 bytes_consumed
688 )
689 .unwrap();
690 }
691
692 if variable_length && unit_count > 1 {
693 write!(out, " }} else {{ None }}").unwrap();
694 }
695 writeln!(out, ",").unwrap();
696}
697
698fn emit_some(
700 out: &mut String,
701 instr: &ValidatedInstruction,
702 enum_name: &str,
703 pad: &str,
704 variable_length: bool,
705 word_type: &str,
706 unit_bytes: u32,
707 endian_suffix: &str,
708 type_maps: &HashMap<String, String>,
709) {
710 let unit_count = instr.unit_count();
711 let bytes_consumed = unit_count * unit_bytes;
712
713 if variable_length && unit_count > 1 {
714 writeln!(out, "{}if data.len() >= {} {{", pad, bytes_consumed).unwrap();
715 let inner_pad = format!("{} ", pad);
716 emit_some_inner(
717 out,
718 instr,
719 enum_name,
720 &inner_pad,
721 word_type,
722 unit_bytes,
723 endian_suffix,
724 bytes_consumed,
725 type_maps,
726 );
727 writeln!(out, "{}}} else {{", pad).unwrap();
728 writeln!(out, "{} None", pad).unwrap();
729 writeln!(out, "{}}}", pad).unwrap();
730 } else {
731 emit_some_inner(
732 out,
733 instr,
734 enum_name,
735 pad,
736 word_type,
737 unit_bytes,
738 endian_suffix,
739 bytes_consumed,
740 type_maps,
741 );
742 }
743}
744
745fn emit_some_inner(
747 out: &mut String,
748 instr: &ValidatedInstruction,
749 enum_name: &str,
750 pad: &str,
751 word_type: &str,
752 unit_bytes: u32,
753 endian_suffix: &str,
754 bytes_consumed: u32,
755 type_maps: &HashMap<String, String>,
756) {
757 let variant_name = to_pascal_case(&instr.name);
758 if instr.resolved_fields.is_empty() {
759 writeln!(
760 out,
761 "{}Some(({}::{}, {}))",
762 pad, enum_name, variant_name, bytes_consumed
763 )
764 .unwrap();
765 } else {
766 writeln!(out, "{}Some(({}::{} {{", pad, enum_name, variant_name).unwrap();
767 for field in &instr.resolved_fields {
768 let extract = extract_expression(
769 "opcode",
770 &field.ranges,
771 word_type,
772 unit_bytes,
773 endian_suffix,
774 );
775 let expr = apply_transforms_with_maps(&extract, &field.resolved_type, type_maps);
776 writeln!(out, "{} {}: {},", pad, field.name, expr).unwrap();
777 }
778 writeln!(out, "{}}}, {}))", pad, bytes_consumed).unwrap();
779 }
780}
781
782fn compute_mask_value(fixed_bits: &[(u32, Bit)]) -> (u64, u64) {
785 let mut mask: u64 = 0;
786 let mut value: u64 = 0;
787 for &(bit_pos, bit_val) in fixed_bits {
788 if bit_val == Bit::Wildcard {
790 continue;
791 }
792 mask |= 1u64 << bit_pos;
793 if bit_val == Bit::One {
794 value |= 1u64 << bit_pos;
795 }
796 }
797 (mask, value)
798}
799
800fn unit_read_expr(unit: u32, word_type: &str, unit_bytes: u32, endian_suffix: &str) -> String {
804 if unit == 0 {
805 "opcode".to_string()
806 } else {
807 let start = unit * unit_bytes;
808 let end = start + unit_bytes;
809 format!(
810 "{}::from_{}_bytes(data[{}..{}].try_into().unwrap())",
811 word_type, endian_suffix, start, end
812 )
813 }
814}
815
816fn extract_expression(
818 var: &str,
819 ranges: &[BitRange],
820 word_type: &str,
821 unit_bytes: u32,
822 endian_suffix: &str,
823) -> String {
824 if ranges.is_empty() {
825 return "0".to_string();
826 }
827
828 if ranges.len() == 1 {
829 let range = ranges[0];
831 let source = if range.unit == 0 {
832 var.to_string()
833 } else {
834 unit_read_expr(range.unit, word_type, unit_bytes, endian_suffix)
835 };
836
837 let width = range.width();
838 let shift = range.end;
839 let mask = (1u64 << width) - 1;
840
841 if shift == 0 {
842 format!("{} & {:#x}", source, mask)
843 } else {
844 format!("({} >> {}) & {:#x}", source, shift, mask)
845 }
846 } else {
847 let mut parts = Vec::new();
849 let mut accumulated_width = 0u32;
850
851 for range in ranges {
853 let source = if range.unit == 0 {
854 var.to_string()
855 } else {
856 unit_read_expr(range.unit, word_type, unit_bytes, endian_suffix)
857 };
858
859 let width = range.width();
860 let shift = range.end;
861 let mask = (1u64 << width) - 1;
862
863 let extracted = if shift == 0 {
864 format!("({} & {:#x})", source, mask)
865 } else {
866 format!("(({} >> {}) & {:#x})", source, shift, mask)
867 };
868
869 if accumulated_width > 0 {
871 parts.push(format!("({} << {})", extracted, accumulated_width));
872 } else {
873 parts.push(extracted);
874 }
875
876 accumulated_width += width;
877 }
878
879 parts.join(" | ")
880 }
881}
882
883fn apply_transforms(extract_expr: &str, resolved: &ResolvedFieldType) -> String {
885 apply_transforms_with_maps(extract_expr, resolved, &HashMap::new())
886}
887
888fn apply_transforms_with_maps(
890 extract_expr: &str,
891 resolved: &ResolvedFieldType,
892 type_maps: &HashMap<String, String>,
893) -> String {
894 let mut expr = extract_expr.to_string();
895
896 for transform in &resolved.transforms {
897 match transform {
898 Transform::SignExtend(n) => {
899 let signed_type = signed_type_for(&resolved.base_type);
900 let bits = type_bits(&resolved.base_type);
901 expr = format!(
902 "(((({}) as {}) << ({} - {})) >> ({} - {}))",
903 expr, signed_type, bits, n, bits, n
904 );
905 }
906 Transform::ZeroExtend(_) => {
907 }
909 Transform::ShiftLeft(n) => {
910 expr = format!("(({}) << {})", expr, n);
911 }
912 }
913 }
914
915 if let Some(ref sd_name) = resolved.sub_decoder {
917 let decode_fn = format!("decode_{}", to_snake_case(sd_name));
918 return format!(
920 "{}(({}) as {}).unwrap()",
921 decode_fn, expr, resolved.base_type
922 );
923 }
924
925 let wrapper_type = resolved.alias_name.as_ref().and_then(|a| type_maps.get(a));
927
928 if let Some(wrapper) = wrapper_type {
929 let short_name = wrapper.rsplit("::").next().unwrap_or(wrapper);
930 expr = format!("{}::from(({}) as {})", short_name, expr, resolved.base_type);
931 } else if resolved.base_type == "bool" {
932 expr = format!("({}) != 0", expr);
933 } else {
934 expr = format!("({}) as {}", expr, resolved.base_type);
935 }
936
937 expr
938}
939
940fn generate_display_helpers(out: &mut String, def: &ValidatedDef) {
942 let mut need_signed_hex = false;
943 let mut need_hex = false;
944
945 for instr in &def.instructions {
946 for field in &instr.resolved_fields {
947 match field.resolved_type.display_format {
948 Some(DisplayFormat::SignedHex) => need_signed_hex = true,
949 Some(DisplayFormat::Hex) => need_hex = true,
950 None => {}
951 }
952 }
953 }
954
955 if need_signed_hex {
956 writeln!(out, "struct SignedHex<T>(T);").unwrap();
957 writeln!(out).unwrap();
958
959 for ty in &["i8", "i16", "i32"] {
960 writeln!(out, "impl fmt::Display for SignedHex<{}> {{", ty).unwrap();
961 writeln!(
962 out,
963 " fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {{"
964 )
965 .unwrap();
966 writeln!(out, " if self.0 == 0 {{ write!(f, \"0\") }}").unwrap();
967 writeln!(
968 out,
969 " else if self.0 > 0 {{ write!(f, \"0x{{:X}}\", self.0) }}"
970 )
971 .unwrap();
972 writeln!(
973 out,
974 " else {{ write!(f, \"-0x{{:X}}\", (self.0 as i64).wrapping_neg()) }}"
975 )
976 .unwrap();
977 writeln!(out, " }}").unwrap();
978 writeln!(out, "}}").unwrap();
979 writeln!(out).unwrap();
980 }
981 }
982
983 if need_hex {
984 if !need_signed_hex {
985 writeln!(out, "struct SignedHex<T>(T);").unwrap();
986 writeln!(out).unwrap();
987 }
988
989 for ty in &["u8", "u16", "u32"] {
990 writeln!(out, "impl fmt::Display for SignedHex<{}> {{", ty).unwrap();
991 writeln!(
992 out,
993 " fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {{"
994 )
995 .unwrap();
996 writeln!(out, " if self.0 == 0 {{ write!(f, \"0\") }}").unwrap();
997 writeln!(out, " else {{ write!(f, \"0x{{:X}}\", self.0) }}").unwrap();
998 writeln!(out, " }}").unwrap();
999 writeln!(out, "}}").unwrap();
1000 writeln!(out).unwrap();
1001 }
1002 }
1003}
1004
1005fn generate_map_functions(out: &mut String, def: &ValidatedDef) {
1007 if def.maps.is_empty() {
1008 return;
1009 }
1010
1011 let map_param_types = infer_map_param_types(def);
1013
1014 for map in &def.maps {
1015 let has_interpolation = map.entries.iter().any(|entry| {
1016 entry
1017 .output
1018 .iter()
1019 .any(|p| matches!(p, FormatPiece::FieldRef { .. }))
1020 });
1021
1022 let param_types: Vec<String> = map
1023 .params
1024 .iter()
1025 .enumerate()
1026 .map(|(i, _)| {
1027 map_param_types
1028 .get(&map.name)
1029 .and_then(|types| types.get(i))
1030 .cloned()
1031 .unwrap_or_else(|| "i64".to_string())
1032 })
1033 .collect();
1034
1035 let return_type = if has_interpolation {
1036 "String"
1037 } else {
1038 "&'static str"
1039 };
1040
1041 let params: Vec<String> = map
1042 .params
1043 .iter()
1044 .zip(param_types.iter())
1045 .map(|(name, ty)| format!("{}: {}", name, ty))
1046 .collect();
1047
1048 writeln!(out, "#[allow(dead_code)]").unwrap();
1049 writeln!(
1050 out,
1051 "fn {}({}) -> {} {{",
1052 map.name,
1053 params.join(", "),
1054 return_type
1055 )
1056 .unwrap();
1057
1058 if map.params.len() == 1 {
1059 writeln!(out, " match {} {{", map.params[0]).unwrap();
1060 } else {
1061 let tuple: Vec<&str> = map.params.iter().map(|s| s.as_str()).collect();
1062 writeln!(out, " match ({}) {{", tuple.join(", ")).unwrap();
1063 }
1064
1065 let mut default_entry = None;
1067
1068 for entry in &map.entries {
1069 let is_all_wildcard = entry.keys.iter().all(|k| matches!(k, MapKey::Wildcard));
1070 if is_all_wildcard {
1071 default_entry = Some(entry);
1072 continue;
1073 }
1074
1075 let pattern = if map.params.len() == 1 {
1076 format_map_key(&entry.keys[0])
1077 } else {
1078 let keys: Vec<String> = entry.keys.iter().map(|k| format_map_key(k)).collect();
1079 format!("({})", keys.join(", "))
1080 };
1081
1082 let output = format_map_output(&entry.output, has_interpolation);
1083 writeln!(out, " {} => {},", pattern, output).unwrap();
1084 }
1085
1086 if let Some(entry) = default_entry {
1088 let output = format_map_output(&entry.output, has_interpolation);
1089 writeln!(out, " _ => {},", output).unwrap();
1090 } else {
1091 if has_interpolation {
1092 writeln!(out, " _ => String::from(\"???\"),").unwrap();
1093 } else {
1094 writeln!(out, " _ => \"???\",").unwrap();
1095 }
1096 }
1097
1098 writeln!(out, " }}").unwrap();
1099 writeln!(out, "}}").unwrap();
1100 writeln!(out).unwrap();
1101 }
1102}
1103
1104fn format_map_key(key: &MapKey) -> String {
1105 match key {
1106 MapKey::Value(v) => format!("{}", v),
1107 MapKey::Wildcard => "_".to_string(),
1108 }
1109}
1110
1111fn format_map_output(pieces: &[FormatPiece], has_interpolation: bool) -> String {
1112 if !has_interpolation {
1113 let mut s = String::new();
1115 for piece in pieces {
1116 if let FormatPiece::Literal(lit) = piece {
1117 s.push_str(lit);
1118 }
1119 }
1120 return format!("\"{}\"", s);
1121 }
1122
1123 let mut fmt_str = String::new();
1125 let mut args = Vec::new();
1126
1127 for piece in pieces {
1128 match piece {
1129 FormatPiece::Literal(lit) => {
1130 for ch in lit.chars() {
1132 match ch {
1133 '{' => fmt_str.push_str("{{"),
1134 '}' => fmt_str.push_str("}}"),
1135 _ => fmt_str.push(ch),
1136 }
1137 }
1138 }
1139 FormatPiece::FieldRef { expr, spec } => {
1140 if let Some(spec) = spec {
1141 fmt_str.push_str(&format!("{{:{}}}", spec));
1142 } else {
1143 fmt_str.push_str("{}");
1144 }
1145 args.push(expr_to_rust(expr, &[]));
1146 }
1147 }
1148 }
1149
1150 if args.is_empty() {
1151 format!("String::from(\"{}\")", fmt_str)
1152 } else {
1153 format!("format!(\"{}\", {})", fmt_str, args.join(", "))
1154 }
1155}
1156
1157fn infer_map_param_types(def: &ValidatedDef) -> HashMap<String, Vec<String>> {
1159 let mut result: HashMap<String, Vec<String>> = HashMap::new();
1160
1161 for instr in &def.instructions {
1163 let field_types: HashMap<&str, &ResolvedFieldType> = instr
1164 .resolved_fields
1165 .iter()
1166 .map(|f| (f.name.as_str(), &f.resolved_type))
1167 .collect();
1168
1169 for fl in &instr.format_lines {
1170 for piece in &fl.pieces {
1171 if let FormatPiece::FieldRef { expr, .. } = piece {
1172 collect_map_call_types(expr, &field_types, &mut result);
1173 }
1174 }
1175 }
1176 }
1177
1178 result
1179}
1180
1181fn infer_expr_type(
1183 expr: &FormatExpr,
1184 field_types: &HashMap<&str, &ResolvedFieldType>,
1185) -> Option<String> {
1186 match expr {
1187 FormatExpr::Field(name) => field_types
1188 .get(name.as_str())
1189 .map(|ft| ft.base_type.clone()),
1190 FormatExpr::Arithmetic { left, .. } => infer_expr_type(left, field_types),
1191 FormatExpr::IntLiteral(_) => Some("i64".to_string()),
1192 _ => None,
1193 }
1194}
1195
1196fn collect_map_call_types(
1197 expr: &FormatExpr,
1198 field_types: &HashMap<&str, &ResolvedFieldType>,
1199 result: &mut HashMap<String, Vec<String>>,
1200) {
1201 match expr {
1202 FormatExpr::MapCall { map_name, args } => {
1203 let entry = result
1204 .entry(map_name.clone())
1205 .or_insert_with(|| vec!["i64".to_string(); args.len()]);
1206
1207 for (i, arg) in args.iter().enumerate() {
1208 if i < entry.len() {
1209 if let Some(rust_type) = infer_expr_type(arg, field_types) {
1210 entry[i] = rust_type;
1211 }
1212 }
1213 }
1214
1215 for arg in args {
1217 collect_map_call_types(arg, field_types, result);
1218 }
1219 }
1220 FormatExpr::Arithmetic { left, right, .. } => {
1221 collect_map_call_types(left, field_types, result);
1222 collect_map_call_types(right, field_types, result);
1223 }
1224 FormatExpr::BuiltinCall { args, .. } => {
1225 for arg in args {
1226 collect_map_call_types(arg, field_types, result);
1227 }
1228 }
1229 FormatExpr::SubDecoderAccess { .. }
1230 | FormatExpr::Field(_)
1231 | FormatExpr::Ternary { .. }
1232 | FormatExpr::IntLiteral(_) => {}
1233 }
1234}
1235
1236fn generate_format_trait(
1238 out: &mut String,
1239 def: &ValidatedDef,
1240 trait_name: &str,
1241 type_maps: &HashMap<String, String>,
1242) {
1243 writeln!(out, "pub trait {} {{", trait_name).unwrap();
1244
1245 for instr in &def.instructions {
1246 let method_name = format!("fmt_{}", instr.name);
1247 let params = trait_method_params(&instr.resolved_fields, &type_maps);
1248
1249 if params.is_empty() {
1250 writeln!(
1251 out,
1252 " fn {}(f: &mut fmt::Formatter) -> fmt::Result {{",
1253 method_name
1254 )
1255 .unwrap();
1256 } else {
1257 writeln!(
1258 out,
1259 " fn {}({}, f: &mut fmt::Formatter) -> fmt::Result {{",
1260 method_name, params
1261 )
1262 .unwrap();
1263 }
1264
1265 generate_format_body(out, instr, 2, &type_maps);
1266
1267 writeln!(out, " }}").unwrap();
1268 }
1269
1270 writeln!(out, "}}").unwrap();
1271 writeln!(out).unwrap();
1272}
1273
1274fn trait_method_params(fields: &[ResolvedField], type_maps: &HashMap<String, String>) -> String {
1276 let mut params = Vec::new();
1277 for field in fields {
1278 let rust_type = field_rust_type_with_maps(field, type_maps);
1279 params.push(format!("{}: {}", field.name, rust_type));
1280 }
1281 params.join(", ")
1282}
1283
1284fn generate_format_body(
1286 out: &mut String,
1287 instr: &ValidatedInstruction,
1288 indent: usize,
1289 type_maps: &HashMap<String, String>,
1290) {
1291 let pad = " ".repeat(indent);
1292
1293 if instr.format_lines.is_empty() {
1294 if instr.resolved_fields.is_empty() {
1296 writeln!(out, "{}write!(f, \"{}\")", pad, instr.name).unwrap();
1297 } else {
1298 let field_names: Vec<&str> = instr
1299 .resolved_fields
1300 .iter()
1301 .map(|f| f.name.as_str())
1302 .collect();
1303 let placeholders: Vec<&str> = field_names.iter().map(|_| "{}").collect();
1304 let fmt_str = format!("{} {}", instr.name, placeholders.join(", "));
1305 let args: Vec<String> = instr
1306 .resolved_fields
1307 .iter()
1308 .map(|f| f.name.clone())
1309 .collect();
1310 writeln!(
1311 out,
1312 "{}write!(f, \"{}\", {})",
1313 pad,
1314 fmt_str,
1315 args.join(", ")
1316 )
1317 .unwrap();
1318 }
1319 return;
1320 }
1321
1322 if instr.format_lines.len() == 1 && instr.format_lines[0].guard.is_none() {
1323 emit_write_call(
1325 out,
1326 &instr.format_lines[0].pieces,
1327 &instr.resolved_fields,
1328 &pad,
1329 );
1330 return;
1331 }
1332
1333 for (i, fl) in instr.format_lines.iter().enumerate() {
1335 if let Some(guard) = &fl.guard {
1336 let guard_code = generate_guard_code(guard, &instr.resolved_fields, type_maps);
1337 if i == 0 {
1338 writeln!(out, "{}if {} {{", pad, guard_code).unwrap();
1339 } else {
1340 writeln!(out, "{}}} else if {} {{", pad, guard_code).unwrap();
1341 }
1342 emit_write_call(
1343 out,
1344 &fl.pieces,
1345 &instr.resolved_fields,
1346 &format!("{} ", pad),
1347 );
1348 } else {
1349 if i > 0 {
1351 writeln!(out, "{}}} else {{", pad).unwrap();
1352 }
1353 emit_write_call(
1354 out,
1355 &fl.pieces,
1356 &instr.resolved_fields,
1357 &format!("{} ", pad),
1358 );
1359 }
1360 }
1361
1362 if instr.format_lines.len() > 1
1363 || instr
1364 .format_lines
1365 .first()
1366 .map_or(false, |fl| fl.guard.is_some())
1367 {
1368 writeln!(out, "{}}}", pad).unwrap();
1369 }
1370}
1371
1372fn emit_write_call(out: &mut String, pieces: &[FormatPiece], fields: &[ResolvedField], pad: &str) {
1374 let mut fmt_str = String::new();
1375 let mut args = Vec::new();
1376
1377 for piece in pieces {
1378 match piece {
1379 FormatPiece::Literal(lit) => {
1380 for ch in lit.chars() {
1381 match ch {
1382 '{' => fmt_str.push_str("{{"),
1383 '}' => fmt_str.push_str("}}"),
1384 _ => fmt_str.push(ch),
1385 }
1386 }
1387 }
1388 FormatPiece::FieldRef { expr, spec } => {
1389 if let Some(spec) = spec {
1390 fmt_str.push_str(&format!("{{:{}}}", spec));
1391 args.push(expr_to_rust(expr, fields));
1392 } else if let Some(display_fmt) = resolve_display_format(expr, fields) {
1393 fmt_str.push_str("{}");
1394 let rust_expr = expr_to_rust(expr, fields);
1395 match display_fmt {
1396 DisplayFormat::SignedHex | DisplayFormat::Hex => {
1397 args.push(format!("SignedHex({})", rust_expr));
1398 }
1399 }
1400 } else {
1401 fmt_str.push_str("{}");
1402 args.push(expr_to_rust(expr, fields));
1403 }
1404 }
1405 }
1406 }
1407
1408 if args.is_empty() {
1409 writeln!(out, "{}write!(f, \"{}\")", pad, fmt_str).unwrap();
1410 } else {
1411 writeln!(
1412 out,
1413 "{}write!(f, \"{}\", {})",
1414 pad,
1415 fmt_str,
1416 args.join(", ")
1417 )
1418 .unwrap();
1419 }
1420}
1421
1422fn resolve_display_format(expr: &FormatExpr, fields: &[ResolvedField]) -> Option<DisplayFormat> {
1424 if let FormatExpr::Field(name) = expr {
1425 fields
1426 .iter()
1427 .find(|f| f.name == *name)
1428 .and_then(|f| f.resolved_type.display_format)
1429 } else {
1430 None
1431 }
1432}
1433
1434fn expr_to_rust(expr: &FormatExpr, fields: &[ResolvedField]) -> String {
1436 match expr {
1437 FormatExpr::Field(name) => {
1438 let field = fields.iter().find(|f| f.name == *name);
1439 if let Some(f) = field {
1440 if f.resolved_type.base_type == "bool" {
1441 format!("{} as u8", name)
1442 } else {
1443 name.clone()
1444 }
1445 } else {
1446 name.clone()
1447 }
1448 }
1449 FormatExpr::Ternary {
1450 field,
1451 if_nonzero,
1452 if_zero,
1453 } => {
1454 let f = fields.iter().find(|f| f.name == *field);
1455 let cond = if let Some(f) = f {
1456 if f.resolved_type.base_type == "bool" {
1457 field.clone()
1458 } else {
1459 format!("{} != 0", field)
1460 }
1461 } else {
1462 format!("{} != 0", field)
1463 };
1464
1465 let else_val = if_zero
1466 .as_deref()
1467 .map(|s| format!("\"{}\"", s))
1468 .unwrap_or_else(|| "\"\"".to_string());
1469
1470 format!(
1471 "if {} {{ \"{}\" }} else {{ {} }}",
1472 cond, if_nonzero, else_val
1473 )
1474 }
1475 FormatExpr::Arithmetic { left, op, right } => {
1476 let l = expr_to_rust(left, fields);
1477 let r = expr_to_rust(right, fields);
1478 let op_str = match op {
1479 ArithOp::Add => "+",
1480 ArithOp::Sub => "-",
1481 ArithOp::Mul => "*",
1482 ArithOp::Div => "/",
1483 ArithOp::Mod => "%",
1484 };
1485 format!("{} {} {}", l, op_str, r)
1486 }
1487 FormatExpr::IntLiteral(val) => format!("{}", val),
1488 FormatExpr::MapCall { map_name, args } => {
1489 let arg_strs: Vec<String> = args.iter().map(|a| expr_to_rust(a, fields)).collect();
1490 format!("{}({})", map_name, arg_strs.join(", "))
1491 }
1492 FormatExpr::BuiltinCall { func, args } => {
1493 let arg_strs: Vec<String> = args.iter().map(|a| expr_to_rust(a, fields)).collect();
1494 match func {
1495 BuiltinFunc::RotateRight => {
1496 format!(
1497 "({} as u32).rotate_right({} as u32)",
1498 arg_strs.get(0).map(|s| s.as_str()).unwrap_or("0"),
1499 arg_strs.get(1).map(|s| s.as_str()).unwrap_or("0")
1500 )
1501 }
1502 BuiltinFunc::RotateLeft => {
1503 format!(
1504 "({} as u32).rotate_left({} as u32)",
1505 arg_strs.get(0).map(|s| s.as_str()).unwrap_or("0"),
1506 arg_strs.get(1).map(|s| s.as_str()).unwrap_or("0")
1507 )
1508 }
1509 }
1510 }
1511 FormatExpr::SubDecoderAccess { field, fragment } => {
1512 format!("{}.{}", field, fragment)
1513 }
1514 }
1515}
1516
1517fn generate_guard_code(
1519 guard: &Guard,
1520 fields: &[ResolvedField],
1521 type_maps: &HashMap<String, String>,
1522) -> String {
1523 let conditions: Vec<String> = guard
1524 .conditions
1525 .iter()
1526 .map(|cond| {
1527 let left = guard_operand_to_rust(&cond.left, fields);
1528 let right = guard_operand_to_rust(&cond.right, fields);
1529 let op = match cond.op {
1530 CompareOp::Eq => "==",
1531 CompareOp::Ne => "!=",
1532 CompareOp::Lt => "<",
1533 CompareOp::Le => "<=",
1534 CompareOp::Gt => ">",
1535 CompareOp::Ge => ">=",
1536 };
1537
1538 let left_field = match &cond.left {
1539 GuardOperand::Field(name) => fields.iter().find(|f| f.name == *name),
1540 _ => None,
1541 };
1542
1543 if let Some(f) = left_field {
1544 let wrapper = f
1546 .resolved_type
1547 .alias_name
1548 .as_ref()
1549 .and_then(|a| type_maps.get(a));
1550 if let Some(wrapper_path) = wrapper {
1551 let short_name = wrapper_path.rsplit("::").next().unwrap_or(wrapper_path);
1552 if let GuardOperand::Literal(val) = &cond.right {
1553 return format!(
1554 "{} {} {}::from({}{})",
1555 left, op, short_name, val, f.resolved_type.base_type
1556 );
1557 }
1558 } else if f.resolved_type.base_type == "bool" {
1559 if let GuardOperand::Literal(val) = &cond.right {
1561 match (cond.op, *val) {
1562 (CompareOp::Eq, 0) => return format!("!{}", left),
1563 (CompareOp::Eq, _) => return left.clone(),
1564 (CompareOp::Ne, 0) => return left.clone(),
1565 (CompareOp::Ne, _) => return format!("!{}", left),
1566 _ => {}
1567 }
1568 }
1569 }
1570 }
1571
1572 format!("{} {} {}", left, op, right)
1573 })
1574 .collect();
1575
1576 conditions.join(" && ")
1577}
1578
1579fn guard_operand_to_rust(operand: &GuardOperand, fields: &[ResolvedField]) -> String {
1580 match operand {
1581 GuardOperand::Field(name) => name.clone(),
1582 GuardOperand::Literal(val) => format!("{}", val),
1583 GuardOperand::Expr { left, op, right } => {
1584 let l = guard_operand_to_rust(left, fields);
1585 let r = guard_operand_to_rust(right, fields);
1586 let op_str = match op {
1587 ArithOp::Add => "+",
1588 ArithOp::Sub => "-",
1589 ArithOp::Mul => "*",
1590 ArithOp::Div => "/",
1591 ArithOp::Mod => "%",
1592 };
1593 format!("({} {} {})", l, op_str, r)
1594 }
1595 }
1596}
1597
1598fn generate_write_asm(out: &mut String, def: &ValidatedDef, enum_name: &str, trait_name: &str) {
1600 writeln!(
1601 out,
1602 " pub fn write_asm<F: {}>(&self, f: &mut fmt::Formatter) -> fmt::Result {{",
1603 trait_name
1604 )
1605 .unwrap();
1606 writeln!(out, " match self {{").unwrap();
1607
1608 for instr in &def.instructions {
1609 let variant_name = to_pascal_case(&instr.name);
1610 let method_name = format!("fmt_{}", instr.name);
1611
1612 if instr.resolved_fields.is_empty() {
1613 writeln!(
1614 out,
1615 " {}::{} => F::{}(f),",
1616 enum_name, variant_name, method_name
1617 )
1618 .unwrap();
1619 } else {
1620 let field_names: Vec<String> = instr
1621 .resolved_fields
1622 .iter()
1623 .map(|f| f.name.clone())
1624 .collect();
1625 let destructure = format!(
1626 "{}::{} {{ {} }}",
1627 enum_name,
1628 variant_name,
1629 field_names.join(", ")
1630 );
1631
1632 let args: Vec<String> = instr
1633 .resolved_fields
1634 .iter()
1635 .map(|f| format!("*{}", f.name))
1636 .collect();
1637
1638 writeln!(
1639 out,
1640 " {} => F::{}({}, f),",
1641 destructure,
1642 method_name,
1643 args.join(", ")
1644 )
1645 .unwrap();
1646 }
1647 }
1648
1649 writeln!(out, " }}").unwrap();
1650 writeln!(out, " }}").unwrap();
1651}
1652
1653fn word_type_for_width(width: u32) -> &'static str {
1654 match width {
1655 8 => "u8",
1656 16 => "u16",
1657 32 => "u32",
1658 _ => "u32",
1659 }
1660}
1661
1662pub(crate) fn signed_type_for(base: &str) -> &'static str {
1663 match base {
1664 "u8" | "i8" => "i8",
1665 "u16" | "i16" => "i16",
1666 "u32" | "i32" => "i32",
1667 _ => "i32",
1668 }
1669}
1670
1671pub(crate) fn type_bits(base: &str) -> u32 {
1672 match base {
1673 "u8" | "i8" => 8,
1674 "u16" | "i16" => 16,
1675 "u32" | "i32" => 32,
1676 _ => 32,
1677 }
1678}
1679
1680fn field_rust_type_with_maps(field: &ResolvedField, type_maps: &HashMap<String, String>) -> String {
1681 if field.resolved_type.sub_decoder.is_some() {
1682 let sd_name = field.resolved_type.sub_decoder.as_ref().unwrap();
1683 format!("{}Insn", sd_name)
1684 } else if let Some(ref alias) = field.resolved_type.alias_name {
1685 if let Some(rust_type) = type_maps.get(alias) {
1686 rust_type
1688 .rsplit("::")
1689 .next()
1690 .unwrap_or(rust_type)
1691 .to_string()
1692 } else {
1693 field.resolved_type.base_type.clone()
1694 }
1695 } else {
1696 field.resolved_type.base_type.clone()
1697 }
1698}
1699
1700pub fn to_pascal_case(name: &str) -> String {
1705 let mut result = String::new();
1706 let mut capitalize_next = true;
1707
1708 for ch in name.chars() {
1709 if ch == '_' {
1710 capitalize_next = true;
1711 } else if capitalize_next {
1712 result.push(ch.to_ascii_uppercase());
1713 capitalize_next = false;
1714 } else {
1715 result.push(ch.to_ascii_lowercase());
1716 }
1717 }
1718
1719 result
1720}
1721
1722fn generate_subdecoder(out: &mut String, sd: &ValidatedSubDecoder, dispatch: crate::Dispatch) {
1724 let opcode_enum = format!("{}Opcode", sd.name);
1725 let insn_struct = format!("{}Insn", sd.name);
1726 let decode_fn = format!("decode_{}", to_snake_case(&sd.name));
1727 let word_type = word_type_for_width(sd.width);
1728 let lut_size = 1usize << sd.width;
1729 let use_inline = dispatch == crate::Dispatch::JumpTable;
1730
1731 if !sd.maps.is_empty() {
1733 for map in &sd.maps {
1734 let has_interpolation = map.entries.iter().any(|entry| {
1735 entry
1736 .output
1737 .iter()
1738 .any(|p| matches!(p, FormatPiece::FieldRef { .. }))
1739 });
1740 let return_type = if has_interpolation {
1741 "String"
1742 } else {
1743 "&'static str"
1744 };
1745 let params: Vec<String> = map
1746 .params
1747 .iter()
1748 .map(|name| format!("{}: {}", name, word_type))
1749 .collect();
1750 writeln!(out, "#[allow(dead_code)]").unwrap();
1751 writeln!(
1752 out,
1753 "fn {}({}) -> {} {{",
1754 map.name,
1755 params.join(", "),
1756 return_type
1757 )
1758 .unwrap();
1759 if map.params.len() == 1 {
1760 writeln!(out, " match {} {{", map.params[0]).unwrap();
1761 } else {
1762 let tuple: Vec<&str> = map.params.iter().map(|s| s.as_str()).collect();
1763 writeln!(out, " match ({}) {{", tuple.join(", ")).unwrap();
1764 }
1765 let mut default_entry = None;
1766 for entry in &map.entries {
1767 let is_all_wildcard = entry.keys.iter().all(|k| matches!(k, MapKey::Wildcard));
1768 if is_all_wildcard {
1769 default_entry = Some(entry);
1770 continue;
1771 }
1772 let pattern = if map.params.len() == 1 {
1773 format_map_key(&entry.keys[0])
1774 } else {
1775 let keys: Vec<String> = entry.keys.iter().map(|k| format_map_key(k)).collect();
1776 format!("({})", keys.join(", "))
1777 };
1778 let output = format_map_output(&entry.output, has_interpolation);
1779 writeln!(out, " {} => {},", pattern, output).unwrap();
1780 }
1781 if let Some(entry) = default_entry {
1782 let output = format_map_output(&entry.output, has_interpolation);
1783 writeln!(out, " _ => {},", output).unwrap();
1784 } else if has_interpolation {
1785 writeln!(out, " _ => String::from(\"???\"),").unwrap();
1786 } else {
1787 writeln!(out, " _ => \"???\",").unwrap();
1788 }
1789 writeln!(out, " }}").unwrap();
1790 writeln!(out, "}}").unwrap();
1791 writeln!(out).unwrap();
1792 }
1793 }
1794
1795 writeln!(out, "#[derive(Debug, Clone, Copy, PartialEq, Eq)]").unwrap();
1797 writeln!(out, "pub enum {} {{", opcode_enum).unwrap();
1798 for instr in &sd.instructions {
1799 writeln!(out, " {},", to_pascal_case(&instr.name)).unwrap();
1800 }
1801 writeln!(out, "}}").unwrap();
1802 writeln!(out).unwrap();
1803
1804 writeln!(out, "#[derive(Debug, Clone, Copy, PartialEq, Eq)]").unwrap();
1806 writeln!(out, "pub struct {} {{", insn_struct).unwrap();
1807 writeln!(out, " pub opcode: {},", opcode_enum).unwrap();
1808 for frag_name in &sd.fragment_names {
1809 writeln!(out, " pub {}: &'static str,", frag_name).unwrap();
1810 }
1811 writeln!(out, "}}").unwrap();
1812 writeln!(out).unwrap();
1813
1814 for instr in &sd.instructions {
1816 let handler_name = format!("_sd_{}", instr.name);
1817
1818 let has_fields = !instr.resolved_fields.is_empty();
1821
1822 if has_fields {
1823 for frag in &instr.fragments {
1825 let has_field_refs = frag
1826 .pieces
1827 .iter()
1828 .any(|p| matches!(p, FormatPiece::FieldRef { .. }));
1829 if has_field_refs {
1830 generate_prebaked_fragment_array(out, sd, instr, frag);
1832 }
1833 }
1834 }
1835
1836 if use_inline {
1838 writeln!(out, "#[inline(always)]").unwrap();
1839 }
1840 let param_name = if has_fields { "val" } else { "_val" };
1841 writeln!(
1842 out,
1843 "fn {}({}: {}) -> {} {{",
1844 handler_name, param_name, word_type, insn_struct
1845 )
1846 .unwrap();
1847
1848 for field in &instr.resolved_fields {
1850 let extract = extract_expression("val", &field.ranges, word_type, sd.width / 8, "be");
1851 let expr = apply_transforms(&extract, &field.resolved_type);
1852 writeln!(out, " let {} = {};", field.name, expr).unwrap();
1853 }
1854
1855 writeln!(out, " {} {{", insn_struct).unwrap();
1857 writeln!(
1858 out,
1859 " opcode: {}::{},",
1860 opcode_enum,
1861 to_pascal_case(&instr.name)
1862 )
1863 .unwrap();
1864
1865 for frag in &instr.fragments {
1866 let has_field_refs = frag
1867 .pieces
1868 .iter()
1869 .any(|p| matches!(p, FormatPiece::FieldRef { .. }));
1870 if has_field_refs {
1871 let array_name = prebaked_array_name(&instr.name, &frag.name);
1873 let index_expr = prebaked_index_expr(instr);
1874 writeln!(
1875 out,
1876 " {}: {}[{} as usize],",
1877 frag.name, array_name, index_expr
1878 )
1879 .unwrap();
1880 } else {
1881 let literal = pieces_to_static_str(&frag.pieces);
1883 writeln!(out, " {}: \"{}\",", frag.name, literal).unwrap();
1884 }
1885 }
1886
1887 writeln!(out, " }}").unwrap();
1888 writeln!(out, "}}").unwrap();
1889 writeln!(out).unwrap();
1890 }
1891
1892 let mut dispatch_table: Vec<Option<usize>> = vec![None; lut_size];
1895
1896 for (instr_idx, instr) in sd.instructions.iter().enumerate() {
1897 for val in 0..lut_size {
1899 let matches = instr.segments.iter().all(|seg| {
1900 if let Segment::Fixed {
1901 ranges, pattern, ..
1902 } = seg
1903 {
1904 let mut bit_idx = 0;
1905 for range in ranges {
1906 for i in 0..range.width() as usize {
1907 if bit_idx < pattern.len() {
1908 let hw_bit = range.start - i as u32;
1909 let bit_val = (val >> hw_bit) & 1;
1910 match pattern[bit_idx] {
1911 Bit::Zero if bit_val != 0 => return false,
1912 Bit::One if bit_val != 1 => return false,
1913 _ => {}
1914 }
1915 bit_idx += 1;
1916 }
1917 }
1918 }
1919 true
1920 } else {
1921 true
1922 }
1923 });
1924 if matches && dispatch_table[val].is_none() {
1925 dispatch_table[val] = Some(instr_idx);
1926 }
1927 }
1928 }
1929
1930 match dispatch {
1931 crate::Dispatch::JumpTable => {
1932 writeln!(out, "#[inline(always)]").unwrap();
1934 writeln!(
1935 out,
1936 "pub fn {}(val: {}) -> Option<{}> {{",
1937 decode_fn, word_type, insn_struct
1938 )
1939 .unwrap();
1940 writeln!(out, " match val {{").unwrap();
1941
1942 let mut i = 0;
1943 while i < lut_size {
1944 let current = dispatch_table[i];
1945 let start = i;
1946 while i < lut_size && dispatch_table[i] == current {
1947 i += 1;
1948 }
1949 let end = i - 1;
1950
1951 let handler_name = current.map(|idx| format!("_sd_{}", sd.instructions[idx].name));
1952
1953 let pattern = if start == end {
1954 format!("{:#x}", start)
1955 } else {
1956 format!("{:#x}..={:#x}", start, end)
1957 };
1958
1959 match handler_name {
1960 Some(h) => writeln!(out, " {} => Some({}(val)),", pattern, h).unwrap(),
1961 None => writeln!(out, " {} => None,", pattern).unwrap(),
1962 }
1963 }
1964
1965 writeln!(out, " }}").unwrap();
1966 writeln!(out, "}}").unwrap();
1967 writeln!(out).unwrap();
1968 }
1969 crate::Dispatch::FnPtrLut => {
1970 let handler_type = format!("fn({}) -> {}", word_type, insn_struct);
1972 let table_name = format!("_SD_{}_LUT", sd.name.to_uppercase());
1973
1974 writeln!(
1975 out,
1976 "static {}: [Option<{}>; {}] = [",
1977 table_name, handler_type, lut_size
1978 )
1979 .unwrap();
1980 for val in 0..lut_size {
1981 match dispatch_table[val] {
1982 Some(idx) => {
1983 writeln!(out, " Some(_sd_{}),", sd.instructions[idx].name).unwrap()
1984 }
1985 None => writeln!(out, " None,").unwrap(),
1986 }
1987 }
1988 writeln!(out, "];").unwrap();
1989 writeln!(out).unwrap();
1990
1991 writeln!(
1992 out,
1993 "pub fn {}(val: {}) -> Option<{}> {{",
1994 decode_fn, word_type, insn_struct
1995 )
1996 .unwrap();
1997 writeln!(out, " {}[val as usize].map(|f| f(val))", table_name).unwrap();
1998 writeln!(out, "}}").unwrap();
1999 writeln!(out).unwrap();
2000 }
2001 }
2002}
2003
2004fn generate_prebaked_fragment_array(
2006 out: &mut String,
2007 sd: &ValidatedSubDecoder,
2008 instr: &ValidatedSubInstruction,
2009 frag: &FragmentLine,
2010) {
2011 let array_name = prebaked_array_name(&instr.name, &frag.name);
2012 let total = prebaked_total_entries(instr);
2014
2015 writeln!(out, "static {}: [&str; {}] = [", array_name, total).unwrap();
2016
2017 for combo_idx in 0..total {
2018 let field_values = prebaked_field_values(instr, combo_idx);
2020 let s = evaluate_fragment_pieces(&frag.pieces, &field_values, &sd.maps);
2021 writeln!(out, " \"{}\",", s).unwrap();
2022 }
2023
2024 writeln!(out, "];").unwrap();
2025 writeln!(out).unwrap();
2026}
2027
2028fn evaluate_fragment_pieces(
2030 pieces: &[FormatPiece],
2031 field_values: &HashMap<String, i64>,
2032 maps: &[MapDef],
2033) -> String {
2034 evaluate_fragment_pieces_str(pieces, field_values, maps)
2035}
2036
2037fn evaluate_format_expr(
2039 expr: &FormatExpr,
2040 field_values: &HashMap<String, i64>,
2041 maps: &[MapDef],
2042) -> i64 {
2043 match expr {
2044 FormatExpr::Field(name) => *field_values.get(name).unwrap_or(&0),
2045 FormatExpr::IntLiteral(v) => *v,
2046 FormatExpr::Arithmetic { left, op, right } => {
2047 let l = evaluate_format_expr(left, field_values, maps);
2048 let r = evaluate_format_expr(right, field_values, maps);
2049 match op {
2050 ArithOp::Add => l + r,
2051 ArithOp::Sub => l - r,
2052 ArithOp::Mul => l * r,
2053 ArithOp::Div => {
2054 if r != 0 {
2055 l / r
2056 } else {
2057 0
2058 }
2059 }
2060 ArithOp::Mod => {
2061 if r != 0 {
2062 l % r
2063 } else {
2064 0
2065 }
2066 }
2067 }
2068 }
2069 _ => 0,
2070 }
2071}
2072
2073fn evaluate_fragment_pieces_str(
2075 pieces: &[FormatPiece],
2076 field_values: &HashMap<String, i64>,
2077 maps: &[MapDef],
2078) -> String {
2079 let mut result = String::new();
2080 for piece in pieces {
2081 match piece {
2082 FormatPiece::Literal(s) => result.push_str(s),
2083 FormatPiece::FieldRef { expr, spec } => {
2084 match expr {
2085 FormatExpr::MapCall { map_name, args } => {
2086 if let Some(map) = maps.iter().find(|m| m.name == *map_name) {
2088 let arg_vals: Vec<i64> = args
2089 .iter()
2090 .map(|a| evaluate_format_expr(a, field_values, maps))
2091 .collect();
2092 let map_result = evaluate_map(map, &arg_vals);
2093 result.push_str(&map_result);
2094 }
2095 }
2096 FormatExpr::Field(name) => {
2097 let val = *field_values.get(name).unwrap_or(&0);
2098 match spec {
2099 Some(s) if s.contains('x') || s.contains('X') => {
2100 result.push_str(&format!("{:x}", val));
2101 }
2102 _ => result.push_str(&val.to_string()),
2103 }
2104 }
2105 _ => {
2106 let val = evaluate_format_expr(expr, field_values, maps);
2107 result.push_str(&val.to_string());
2108 }
2109 }
2110 }
2111 }
2112 }
2113 result
2114}
2115
2116fn evaluate_map(map: &MapDef, keys: &[i64]) -> String {
2118 for entry in &map.entries {
2119 let matches = entry.keys.iter().zip(keys.iter()).all(|(k, v)| match k {
2120 MapKey::Value(expected) => *expected == *v,
2121 MapKey::Wildcard => true,
2122 });
2123 if matches {
2124 let mut s = String::new();
2126 for piece in &entry.output {
2127 if let FormatPiece::Literal(lit) = piece {
2128 s.push_str(lit);
2129 }
2130 }
2131 return s;
2132 }
2133 }
2134 "???".to_string()
2135}
2136
2137fn prebaked_total_entries(instr: &ValidatedSubInstruction) -> usize {
2139 let mut total = 1usize;
2140 for field in &instr.resolved_fields {
2141 let field_bits: u32 = field.ranges.iter().map(|r| r.width()).sum();
2142 total *= 1 << field_bits;
2143 }
2144 total
2145}
2146
2147fn prebaked_field_values(
2149 instr: &ValidatedSubInstruction,
2150 combo_idx: usize,
2151) -> HashMap<String, i64> {
2152 let mut values = HashMap::new();
2153 let mut remaining = combo_idx;
2154
2155 for field in instr.resolved_fields.iter().rev() {
2156 let field_bits: u32 = field.ranges.iter().map(|r| r.width()).sum();
2157 let field_range = 1 << field_bits;
2158 let val = remaining % field_range;
2159 remaining /= field_range;
2160 values.insert(field.name.clone(), val as i64);
2161 }
2162
2163 values
2164}
2165
2166fn prebaked_index_expr(instr: &ValidatedSubInstruction) -> String {
2168 if instr.resolved_fields.len() == 1 {
2169 return instr.resolved_fields[0].name.clone();
2170 }
2171
2172 let mut parts = Vec::new();
2174 let mut accumulated_bits = 0u32;
2175
2176 for field in instr.resolved_fields.iter().rev() {
2177 let field_bits: u32 = field.ranges.iter().map(|r| r.width()).sum();
2178 if accumulated_bits > 0 {
2179 parts.push(format!(
2180 "(({} as usize) << {})",
2181 field.name, accumulated_bits
2182 ));
2183 } else {
2184 parts.push(format!("({} as usize)", field.name));
2185 }
2186 accumulated_bits += field_bits;
2187 }
2188
2189 parts.reverse();
2190 parts.join(" | ")
2191}
2192
2193fn prebaked_array_name(instr_name: &str, frag_name: &str) -> String {
2195 format!(
2196 "_SD_{}_{}",
2197 instr_name.to_uppercase(),
2198 frag_name.to_uppercase()
2199 )
2200}
2201
2202fn pieces_to_static_str(pieces: &[FormatPiece]) -> String {
2204 let mut s = String::new();
2205 for piece in pieces {
2206 if let FormatPiece::Literal(lit) = piece {
2207 s.push_str(lit);
2208 }
2209 }
2210 s
2211}
2212
2213fn to_snake_case(name: &str) -> String {
2215 let mut result = String::new();
2216 for (i, ch) in name.chars().enumerate() {
2217 if ch.is_ascii_uppercase() && i > 0 {
2218 result.push('_');
2219 }
2220 result.push(ch.to_ascii_lowercase());
2221 }
2222 result
2223}
2224
2225#[cfg(test)]
2226mod tests {
2227 use super::*;
2228
2229 #[test]
2230 fn test_to_pascal_case() {
2231 assert_eq!(to_pascal_case("addi"), "Addi");
2232 assert_eq!(to_pascal_case("ld_b_c"), "LdBC");
2233 assert_eq!(to_pascal_case("ADD"), "Add");
2234 assert_eq!(to_pascal_case("nop"), "Nop");
2235 }
2236
2237 #[test]
2238 fn test_extract_expression() {
2239 let range = BitRange::new(5, 0);
2241 assert_eq!(
2242 extract_expression("opcode", &[range], "u32", 4, "be"),
2243 "opcode & 0x3f"
2244 );
2245
2246 let range = BitRange::new(31, 26);
2248 assert_eq!(
2249 extract_expression("opcode", &[range], "u32", 4, "be"),
2250 "(opcode >> 26) & 0x3f"
2251 );
2252
2253 let range = BitRange::new_in_unit(1, 15, 0);
2255 assert_eq!(
2256 extract_expression("opcode", &[range], "u16", 2, "be"),
2257 "u16::from_be_bytes(data[2..4].try_into().unwrap()) & 0xffff"
2258 );
2259
2260 let range0 = BitRange::new_in_unit(0, 7, 0); let range1 = BitRange::new_in_unit(1, 15, 8); let result = extract_expression("opcode", &[range0, range1], "u16", 2, "be");
2265 assert!(result.contains("opcode & 0xff"));
2266 assert!(result.contains("u16::from_be_bytes(data[2..4].try_into().unwrap())"));
2267 }
2268}