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