| 1 | //! Special function register and bit addresses of the standard 8051. |
| 2 | |
| 3 | pub const P0: u8 = 0x80; |
| 4 | pub const SP: u8 = 0x81; |
| 5 | pub const DPL: u8 = 0x82; |
| 6 | pub const DPH: u8 = 0x83; |
| 7 | pub const PCON: u8 = 0x87; |
| 8 | pub const TCON: u8 = 0x88; |
| 9 | pub const TMOD: u8 = 0x89; |
| 10 | pub const TL0: u8 = 0x8A; |
| 11 | pub const TL1: u8 = 0x8B; |
| 12 | pub const TH0: u8 = 0x8C; |
| 13 | pub const TH1: u8 = 0x8D; |
| 14 | pub const P1: u8 = 0x90; |
| 15 | pub const SCON: u8 = 0x98; |
| 16 | pub const SBUF: u8 = 0x99; |
| 17 | pub const P2: u8 = 0xA0; |
| 18 | pub const IE: u8 = 0xA8; |
| 19 | pub const P3: u8 = 0xB0; |
| 20 | pub const IP: u8 = 0xB8; |
| 21 | pub const PSW: u8 = 0xD0; |
| 22 | pub const ACC: u8 = 0xE0; |
| 23 | pub const B: u8 = 0xF0; |
| 24 | |
| 25 | pub const SFRS: &[(&str, u8)] = &[ |
| 26 | ("P0", P0), |
| 27 | ("SP", SP), |
| 28 | ("DPL", DPL), |
| 29 | ("DPH", DPH), |
| 30 | ("PCON", PCON), |
| 31 | ("TCON", TCON), |
| 32 | ("TMOD", TMOD), |
| 33 | ("TL0", TL0), |
| 34 | ("TL1", TL1), |
| 35 | ("TH0", TH0), |
| 36 | ("TH1", TH1), |
| 37 | ("P1", P1), |
| 38 | ("SCON", SCON), |
| 39 | ("SBUF", SBUF), |
| 40 | ("P2", P2), |
| 41 | ("IE", IE), |
| 42 | ("P3", P3), |
| 43 | ("IP", IP), |
| 44 | ("PSW", PSW), |
| 45 | ("ACC", ACC), |
| 46 | ("B", B), |
| 47 | ]; |
| 48 | |
| 49 | pub const BITS: &[(&str, u8)] = &[ |
| 50 | ("IT0", 0x88), |
| 51 | ("IE0", 0x89), |
| 52 | ("IT1", 0x8A), |
| 53 | ("IE1", 0x8B), |
| 54 | ("TR0", 0x8C), |
| 55 | ("TF0", 0x8D), |
| 56 | ("TR1", 0x8E), |
| 57 | ("TF1", 0x8F), |
| 58 | ("RI", 0x98), |
| 59 | ("TI", 0x99), |
| 60 | ("RB8", 0x9A), |
| 61 | ("TB8", 0x9B), |
| 62 | ("REN", 0x9C), |
| 63 | ("SM2", 0x9D), |
| 64 | ("SM1", 0x9E), |
| 65 | ("SM0", 0x9F), |
| 66 | ("EX0", 0xA8), |
| 67 | ("ET0", 0xA9), |
| 68 | ("EX1", 0xAA), |
| 69 | ("ET1", 0xAB), |
| 70 | ("ES", 0xAC), |
| 71 | ("EA", 0xAF), |
| 72 | ("RXD", 0xB0), |
| 73 | ("TXD", 0xB1), |
| 74 | ("INT0", 0xB2), |
| 75 | ("INT1", 0xB3), |
| 76 | ("T0", 0xB4), |
| 77 | ("T1", 0xB5), |
| 78 | ("WR", 0xB6), |
| 79 | ("RD", 0xB7), |
| 80 | ("PX0", 0xB8), |
| 81 | ("PT0", 0xB9), |
| 82 | ("PX1", 0xBA), |
| 83 | ("PT1", 0xBB), |
| 84 | ("PS", 0xBC), |
| 85 | ("P", 0xD0), |
| 86 | ("OV", 0xD2), |
| 87 | ("RS0", 0xD3), |
| 88 | ("RS1", 0xD4), |
| 89 | ("F0", 0xD5), |
| 90 | ("AC", 0xD6), |
| 91 | ("CY", 0xD7), |
| 92 | ]; |
| 93 | |
| 94 | pub fn sfr_name(addr: u8) -> Option<&'static str> { |
| 95 | SFRS.iter().find(|&&(_, a)| a == addr).map(|&(n, _)| n) |
| 96 | } |
| 97 | |
| 98 | pub fn bit_name(addr: u8) -> Option<&'static str> { |
| 99 | BITS.iter().find(|&&(_, a)| a == addr).map(|&(n, _)| n) |
| 100 | } |
| 101 | |
| 102 | /// Byte address and bit index of a bit address. |
| 103 | pub fn bit_location(bit: u8) -> (u8, u8) { |
| 104 | if bit < 0x80 { |
| 105 | (0x20 + bit / 8, bit % 8) |
| 106 | } else { |
| 107 | (bit & 0xF8, bit & 7) |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | /// Human-readable bit operand, e.g. `TR0`, `P1.3` or `20h.5`. |
| 112 | pub fn format_bit(bit: u8) -> String { |
| 113 | if let Some(n) = bit_name(bit) { |
| 114 | return n.to_string(); |
| 115 | } |
| 116 | let (byte, idx) = bit_location(bit); |
| 117 | match sfr_name(byte) { |
| 118 | Some(n) => format!("{n}.{idx}"), |
| 119 | None => format!("{}.{idx}", hex8(byte)), |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | /// Human-readable direct address: SFR name or hex. |
| 124 | pub fn format_direct(addr: u8) -> String { |
| 125 | match sfr_name(addr) { |
| 126 | Some(n) => n.to_string(), |
| 127 | None => hex8(addr), |
| 128 | } |
| 129 | } |
| 130 | |
| 131 | /// Assembler-style hex literal, with a leading zero when needed (`0A0h`). |
| 132 | pub fn hex8(v: u8) -> String { |
| 133 | if v >= 0xA0 { |
| 134 | format!("0{v:02X}h") |
| 135 | } else { |
| 136 | format!("{v:02X}h") |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | pub fn hex16(v: u16) -> String { |
| 141 | if v >= 0xA000 { |
| 142 | format!("0{v:04X}h") |
| 143 | } else { |
| 144 | format!("{v:04X}h") |
| 145 | } |
| 146 | } |