aarch64_esr_decoder/esr/
mod.rs

1mod abort;
2mod breakpoint;
3mod bti;
4mod common;
5mod fp;
6mod hvc;
7mod ld64b;
8mod ldc;
9mod mcr;
10mod msr;
11mod pauth;
12mod serror;
13mod sve;
14#[cfg(test)]
15mod tests;
16mod wf;
17
18use super::{DecodeError, FieldInfo};
19use abort::{decode_iss_data_abort, decode_iss_instruction_abort};
20use breakpoint::{
21    decode_iss_breakpoint, decode_iss_breakpoint_vector_catch, decode_iss_software_step,
22    decode_iss_watchpoint,
23};
24use bti::decode_iss_bti;
25use fp::decode_iss_fp;
26use hvc::decode_iss_hvc;
27use ld64b::decode_iss_ld64b;
28use ldc::decode_iss_ldc;
29use mcr::{decode_iss_mcr, decode_iss_mcrr};
30use msr::decode_iss_msr;
31use pauth::decode_iss_pauth;
32use serror::decode_iss_serror;
33use sve::decode_iss_sve;
34use wf::decode_iss_wf;
35
36fn decode_iss_res0(iss: u64) -> Result<Vec<FieldInfo>, DecodeError> {
37    let res0 = FieldInfo::get(iss, "RES0", Some("Reserved"), 0, 25)
38        .check_res0()?
39        .with_description("ISS is RES0".to_string());
40    Ok(vec![res0])
41}
42
43/// Decodes the given Exception Syndrome Register value, or returns an error if it is not valid.
44pub fn decode(esr: u64) -> Result<Vec<FieldInfo>, DecodeError> {
45    let res0 = FieldInfo::get(esr, "RES0", Some("Reserved"), 37, 64).check_res0()?;
46    let iss2 = FieldInfo::get(esr, "ISS2", None, 32, 37);
47    let ec = FieldInfo::get(esr, "EC", Some("Exception Class"), 26, 32);
48    let il =
49        FieldInfo::get_bit(esr, "IL", Some("Instruction Length"), 25).describe_bit(describe_il);
50    let iss = FieldInfo::get(esr, "ISS", Some("Instruction Specific Syndrome"), 0, 25);
51    let (class, iss_subfields, iss_description) = match ec.value {
52        0b000000 => ("Unknown reason", decode_iss_res0(iss.value)?, None),
53        0b000001 => (
54            "Wrapped WF* instruction execution",
55            decode_iss_wf(iss.value)?,
56            None,
57        ),
58        0b000011 => (
59            "Trapped MCR or MRC access with coproc=0b1111",
60            decode_iss_mcr(iss.value)?,
61            None,
62        ),
63        0b000100 => (
64            "Trapped MCRR or MRRC access with coproc=0b1111",
65            decode_iss_mcrr(iss.value)?,
66            None,
67        ),
68        0b000101 => (
69            "Trapped MCR or MRC access with coproc=0b1110",
70            decode_iss_mcr(iss.value)?,
71            None,
72        ),
73        0b000110 => (
74            "Trapped LDC or STC access",
75            decode_iss_ldc(iss.value)?,
76            None,
77        ),
78        0b000111 => (
79            "Trapped access to SVE, Advanced SIMD or floating point",
80            decode_iss_sve(iss.value)?,
81            None,
82        ),
83        0b001010 => (
84            "Trapped execution of an LD64B, ST64B, ST64BV, or ST64BV0 instruction",
85            decode_iss_ld64b(iss.value)?,
86            None,
87        ),
88        0b001100 => (
89            "Trapped MRRC access with (coproc==0b1110)",
90            decode_iss_mcrr(iss.value)?,
91            None,
92        ),
93        0b001101 => ("Branch Target Exception", decode_iss_bti(iss.value)?, None),
94        0b001110 => ("Illegal Execution state", decode_iss_res0(iss.value)?, None),
95        0b010001 => (
96            "SVC instruction execution in AArch32 state",
97            decode_iss_hvc(iss.value)?,
98            None,
99        ),
100        0b010101 => (
101            "SVC instruction execution in AArch64 state",
102            decode_iss_hvc(iss.value)?,
103            None,
104        ),
105        0b010110 => (
106            "HVC instruction execution in AArch64 state",
107            decode_iss_hvc(iss.value)?,
108            None,
109        ),
110        0b010111 => (
111            "SMC instruction execution in AArch64 state",
112            decode_iss_hvc(iss.value)?,
113            None,
114        ),
115        0b011000 => {
116            let (subfields, description) = decode_iss_msr(iss.value)?;
117            (
118                "Trapped MSR, MRS or System instruction execution in AArch64 state",
119                subfields,
120                description,
121            )
122        }
123        0b011001 => (
124            "Access to SVE functionality trapped as a result of CPACR_EL1.ZEN, CPTR_EL2.ZEN, \
125                 CPTR_EL2.TZ, or CPTR_EL3.EZ",
126            decode_iss_res0(iss.value)?,
127            None,
128        ),
129        0b011100 => (
130            "Exception from a Pointer Authentication instruction authentication failure",
131            decode_iss_pauth(iss.value)?,
132            None,
133        ),
134        0b100000 => (
135            "Instruction Abort from a lower Exception level",
136            decode_iss_instruction_abort(iss.value)?,
137            None,
138        ),
139        0b100001 => (
140            "Instruction Abort taken without a change in Exception level",
141            decode_iss_instruction_abort(iss.value)?,
142            None,
143        ),
144        0b100010 => (
145            "PC alignment fault exception",
146            decode_iss_res0(iss.value)?,
147            None,
148        ),
149        0b100100 => (
150            "Data Abort from a lower Exception level",
151            decode_iss_data_abort(iss.value)?,
152            None,
153        ),
154        0b100101 => (
155            "Data Abort taken without a change in Exception level",
156            decode_iss_data_abort(iss.value)?,
157            None,
158        ),
159        0b100110 => (
160            "SP alignment fault exception",
161            decode_iss_res0(iss.value)?,
162            None,
163        ),
164        0b101000 => (
165            "Trapped floating-point exception taken from AArch32 state",
166            decode_iss_fp(iss.value)?,
167            None,
168        ),
169        0b101100 => (
170            "Trapped floating-point exception taken from AArch64 state",
171            decode_iss_fp(iss.value)?,
172            None,
173        ),
174        0b101111 => ("SError interrupt", decode_iss_serror(iss.value)?, None),
175        0b110000 => (
176            "Breakpoint exception from a lower Exception level",
177            decode_iss_breakpoint_vector_catch(iss.value)?,
178            None,
179        ),
180        0b110001 => (
181            "Breakpoint exception taken without a change in Exception level",
182            decode_iss_breakpoint_vector_catch(iss.value)?,
183            None,
184        ),
185        0b110010 => (
186            "Software Step exception from a lower Exception level",
187            decode_iss_software_step(iss.value)?,
188            None,
189        ),
190        0b110011 => (
191            "Software Step exception taken without a change in Exception level",
192            decode_iss_software_step(iss.value)?,
193            None,
194        ),
195        0b110100 => (
196            "Watchpoint exception from a lower Exception level",
197            decode_iss_watchpoint(iss.value)?,
198            None,
199        ),
200        0b110101 => (
201            "Watchpoint exception taken without a change in Exception level",
202            decode_iss_watchpoint(iss.value)?,
203            None,
204        ),
205        0b111000 => (
206            "BKPT instruction execution in AArch32 state",
207            decode_iss_breakpoint(iss.value)?,
208            None,
209        ),
210        0b111100 => (
211            "BRK instruction execution in AArch64 state",
212            decode_iss_breakpoint(iss.value)?,
213            None,
214        ),
215        _ => return Err(DecodeError::InvalidEc { ec: ec.value }),
216    };
217    let iss = FieldInfo {
218        description: iss_description,
219        subfields: iss_subfields,
220        ..iss
221    };
222    let ec = ec.with_description(class.to_string());
223    Ok(vec![res0, iss2, ec, il, iss])
224}
225
226fn describe_il(il: bool) -> &'static str {
227    if il {
228        "32-bit instruction trapped"
229    } else {
230        "16-bit instruction trapped"
231    }
232}