state.rs (3475B)
1 #[derive(Clone, Copy, PartialEq, Eq)] 2 pub(crate) enum RunState { 3 Idle, 4 FreeRun, 5 RunToPc(u32), 6 } 7 8 impl std::fmt::Display for RunState { 9 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 10 match self { 11 RunState::Idle => write!(f, "Idle"), 12 RunState::FreeRun => write!(f, "Running"), 13 RunState::RunToPc(pc) => write!(f, "Run to 0x{pc:08x}"), 14 } 15 } 16 } 17 18 #[derive(Clone, Copy, PartialEq, Eq)] 19 pub(crate) enum ViewMode { 20 Word, 21 Byte, 22 } 23 24 /// Which pane receives keyboard editing. 25 #[derive(Clone, Copy, PartialEq, Eq)] 26 pub(crate) enum Focus { 27 Registers, 28 Memory, 29 } 30 31 pub(crate) fn register_alias(index: usize) -> &'static str { 32 match index { 33 0 => "zero", 34 1 => "ra", 35 2 => "sp", 36 3 => "gp", 37 4 => "tp", 38 5 => "t0", 39 6 => "t1", 40 7 => "t2", 41 8 => "s0/fp", 42 9 => "s1", 43 10 => "a0", 44 11 => "a1", 45 12 => "a2", 46 13 => "a3", 47 14 => "a4", 48 15 => "a5", 49 16 => "a6", 50 17 => "a7", 51 18 => "s2", 52 19 => "s3", 53 20 => "s4", 54 21 => "s5", 55 22 => "s6", 56 23 => "s7", 57 24 => "s8", 58 25 => "s9", 59 26 => "s10", 60 27 => "s11", 61 28 => "t3", 62 29 => "t4", 63 30 => "t5", 64 31 => "t6", 65 _ => "??", 66 } 67 } 68 69 pub(crate) fn printable(byte: u8) -> char { 70 if (b' '..=b'~').contains(&byte) { 71 byte as char 72 } else { 73 '.' 74 } 75 } 76 77 pub(crate) fn hex_char(nibble: u8) -> char { 78 std::char::from_digit(nibble as u32, 16).unwrap_or('?') 79 } 80 81 /// Screen order of the 64 hex digits in one memory row, as 82 /// `(byte offset within the row, nibble index)` where nibble 0 is the high 83 /// nibble of the byte and 1 is the low nibble. 84 /// 85 /// Word view prints each 32-bit word big-endian, so the bytes within a word 86 /// appear in descending address order. Byte view prints bytes in ascending 87 /// memory order. 88 pub(crate) fn row_digits(view: ViewMode) -> [(u32, u8); 64] { 89 let mut out = [(0u32, 0u8); 64]; 90 let mut i = 0; 91 match view { 92 ViewMode::Word => { 93 for word in 0..8u32 { 94 for byte in (0..4u32).rev() { 95 out[i] = (word * 4 + byte, 0); 96 i += 1; 97 out[i] = (word * 4 + byte, 1); 98 i += 1; 99 } 100 } 101 } 102 ViewMode::Byte => { 103 for byte in 0..32u32 { 104 out[i] = (byte, 0); 105 i += 1; 106 out[i] = (byte, 1); 107 i += 1; 108 } 109 } 110 } 111 out 112 } 113 114 #[cfg(test)] 115 mod tests { 116 use super::*; 117 118 #[test] 119 fn aliases_cover_register_file() { 120 assert_eq!(register_alias(0), "zero"); 121 assert_eq!(register_alias(8), "s0/fp"); 122 assert_eq!(register_alias(17), "a7"); 123 assert_eq!(register_alias(31), "t6"); 124 } 125 126 #[test] 127 fn printable_only_decodes_ascii() { 128 assert_eq!(printable(b'A'), 'A'); 129 assert_eq!(printable(b' '), ' '); 130 assert_eq!(printable(0), '.'); 131 assert_eq!(printable(0x7f), '.'); 132 } 133 134 #[test] 135 fn row_digit_order() { 136 let word = row_digits(ViewMode::Word); 137 assert_eq!(word[0], (3, 0)); 138 assert_eq!(word[7], (0, 1)); 139 let byte = row_digits(ViewMode::Byte); 140 assert_eq!(byte[0], (0, 0)); 141 assert_eq!(byte[63], (31, 1)); 142 } 143 }