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
43pub 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}