Krolyxon
Commit 6efefdd

Branches

Tags

Refs →

bench51cratesbench51-coresrcfiles.rs

95 lines · 2.9 KB · Rust

1//! Loading programs: assembly sources as they are, Intel HEX images as
2//! disassembled source.
3
4use std::path::Path;
5
6use crate::asm::hex;
7use crate::sfr::{hex8, hex16};
8use crate::sim::disasm;
9
10pub enum Loaded {
11 Source(String),
12 /// A HEX image turned into source that reassembles to the same bytes.
13 Hex {
14 source: String,
15 bytes: usize,
16 },
17}
18
19pub fn is_hex_path(path: &Path) -> bool {
20 path.extension()
21 .is_some_and(|e| e.eq_ignore_ascii_case("hex") || e.eq_ignore_ascii_case("ihx"))
22}
23
24/// Reads `path`. Errors are ready to show to the user.
25pub fn load(path: &Path) -> Result<Loaded, String> {
26 let text = std::fs::read_to_string(path)
27 .map_err(|e| format!("cannot open {}: {e}", path.display()))?;
28 if !is_hex_path(path) {
29 return Ok(Loaded::Source(text));
30 }
31 let bytes = hex::read(&text).map_err(|e| format!("invalid HEX file: {e}"))?;
32 Ok(Loaded::Hex {
33 source: disassemble_image(&bytes, path),
34 bytes: bytes.len(),
35 })
36}
37
38/// Builds an assembler source from a HEX image by disassembling each
39/// contiguous run of bytes. Reassembling it reproduces the image exactly.
40pub fn disassemble_image(bytes: &[(u16, u8)], path: &Path) -> String {
41 let mut code = Box::new([0u8; 0x10000]);
42 let mut used = vec![false; 0x10000];
43 for &(a, b) in bytes {
44 code[a as usize] = b;
45 used[a as usize] = true;
46 }
47 let mut src = format!("; disassembled from {}\n", path.display());
48 let mut addr = 0usize;
49 while addr < 0x10000 {
50 if !used[addr] {
51 addr += 1;
52 continue;
53 }
54 src.push_str(&format!("\n ORG {}\n", hex16(addr as u16)));
55 while addr < 0x10000 && used[addr] {
56 let d = disasm::disassemble(&code, addr as u16);
57 let size = d.size as usize;
58 if (addr..addr + size).all(|a| a < 0x10000 && used[a]) {
59 src.push_str(&format!(" {:<24}; {:04X}\n", d.text, addr));
60 addr += size;
61 } else {
62 src.push_str(&format!(
63 " DB {:<21}; {:04X}\n",
64 hex8(code[addr]),
65 addr
66 ));
67 addr += 1;
68 }
69 }
70 }
71 src.push_str(" END\n");
72 src
73}
74
75#[cfg(test)]
76mod tests {
77 use std::path::Path;
78
79 use crate::asm::{assemble, hex};
80
81 #[test]
82 fn hex_disassembly_reassembles_to_the_same_image() {
83 let out = assemble(include_str!("../../../examples/serial_hello.asm"));
84 assert!(out.ok());
85 let image = hex::read(&out.intel_hex()).unwrap();
86 let src = super::disassemble_image(&image, Path::new("x.hex"));
87 let again = assemble(&src);
88 assert!(again.ok(), "{:?}", again.diagnostics);
89 let mut a: Vec<_> = out.bytes().collect();
90 let mut b: Vec<_> = again.bytes().collect();
91 a.sort();
92 b.sort();
93 assert_eq!(a, b);
94 }
95}