aarch64_esr_decoder/
lib.rs1mod esr;
18mod midr;
19mod smccc;
20
21use bit_field::BitField;
22pub use esr::decode;
23pub use midr::decode_midr;
24pub use smccc::decode_smccc;
25use std::fmt::{self, Debug, Display, Formatter};
26use std::num::ParseIntError;
27use thiserror::Error;
28
29#[derive(Clone, Debug, Eq, PartialEq)]
31pub struct FieldInfo {
32 pub name: &'static str,
34 pub long_name: Option<&'static str>,
36 pub start: usize,
38 pub width: usize,
40 pub value: u64,
42 pub description: Option<String>,
44 pub subfields: Vec<FieldInfo>,
46}
47
48impl FieldInfo {
49 fn get(
50 register: u64,
51 name: &'static str,
52 long_name: Option<&'static str>,
53 start: usize,
54 end: usize,
55 ) -> Self {
56 let value = register.get_bits(start..end);
57 Self {
58 name,
59 long_name,
60 start,
61 width: end - start,
62 value,
63 description: None,
64 subfields: vec![],
65 }
66 }
67
68 fn get_bit(
69 register: u64,
70 name: &'static str,
71 long_name: Option<&'static str>,
72 bit: usize,
73 ) -> Self {
74 Self::get(register, name, long_name, bit, bit + 1)
75 }
76
77 fn with_description(self, description: String) -> Self {
78 Self {
79 description: Some(description),
80 ..self
81 }
82 }
83
84 fn as_bit(&self) -> bool {
85 assert!(self.width == 1);
86 self.value == 1
87 }
88
89 fn describe_bit<F>(self, describer: F) -> Self
93 where
94 F: FnOnce(bool) -> &'static str,
95 {
96 let bit = self.as_bit();
97 let description = describer(bit).to_string();
98 self.with_description(description)
99 }
100
101 fn describe<F>(self, describer: F) -> Result<Self, DecodeError>
102 where
103 F: FnOnce(u64) -> Result<&'static str, DecodeError>,
104 {
105 let description = describer(self.value)?.to_string();
106 Ok(self.with_description(description))
107 }
108
109 fn check_res0(self) -> Result<Self, DecodeError> {
110 if self.value != 0 {
111 Err(DecodeError::InvalidRes0 { res0: self.value })
112 } else {
113 Ok(self)
114 }
115 }
116
117 pub fn value_string(&self) -> String {
119 if self.width == 1 {
120 if self.value == 1 { "true" } else { "false" }.to_string()
121 } else {
122 format!("{:#01$x}", self.value, self.width.div_ceil(4) + 2,)
123 }
124 }
125
126 pub fn value_binary_string(&self) -> String {
128 format!("{:#01$b}", self.value, self.width + 2)
129 }
130}
131
132impl Display for FieldInfo {
133 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
134 if self.width == 1 {
135 write!(
136 f,
137 "{}: {}",
138 self.name,
139 if self.value == 1 { "true" } else { "false" }
140 )
141 } else {
142 write!(
143 f,
144 "{}: {} {}",
145 self.name,
146 self.value_string(),
147 self.value_binary_string(),
148 )
149 }
150 }
151}
152
153#[derive(Debug, Error)]
155pub enum DecodeError {
156 #[error("Invalid ESR, res0 is {res0:#x}")]
158 InvalidRes0 { res0: u64 },
159 #[error("Invalid EC {ec:#x}")]
161 InvalidEc { ec: u64 },
162 #[error("Invalid DFSC or IFSC {fsc:#x}")]
164 InvalidFsc { fsc: u64 },
165 #[error("Invalid SET {set:#x}")]
167 InvalidSet { set: u64 },
168 #[error("Invalid AET {aet:#x}")]
170 InvalidAet { aet: u64 },
171 #[error("Invalid AM {am:#x}")]
173 InvalidAm { am: u64 },
174 #[error("Invalid ISS {iss:#x} for trapped LD64B or ST64B*")]
176 InvalidLd64bIss { iss: u64 },
177}
178
179pub fn parse_number(s: &str) -> Result<u64, ParseIntError> {
184 if let Some(hex) = s.strip_prefix("0x") {
185 u64::from_str_radix(hex, 16)
186 } else {
187 s.parse()
188 }
189}
190
191#[cfg(test)]
192mod tests {
193 use super::*;
194
195 #[test]
196 fn parse_decimal() {
197 assert_eq!(parse_number("12345"), Ok(12345));
198 }
199
200 #[test]
201 fn parse_hex() {
202 assert_eq!(parse_number("0x123abc"), Ok(0x123abc));
203 }
204
205 #[test]
206 fn parse_invalid() {
207 assert!(parse_number("123abc").is_err());
208 }
209}