1 /*
2 * QEMU Arm CPU -- feature test functions
3 *
4 * Copyright (c) 2023 Linaro Ltd
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #ifndef TARGET_ARM_FEATURES_H
21 #define TARGET_ARM_FEATURES_H
22
23 /*
24 * Naming convention for isar_feature functions:
25 * Functions which test 32-bit ID registers should have _aa32_ in
26 * their name. Functions which test 64-bit ID registers should have
27 * _aa64_ in their name. These must only be used in code where we
28 * know for certain that the CPU has AArch32 or AArch64 respectively
29 * or where the correct answer for a CPU which doesn't implement that
30 * CPU state is "false" (eg when generating A32 or A64 code, if adding
31 * system registers that are specific to that CPU state, for "should
32 * we let this system register bit be set" tests where the 32-bit
33 * flavour of the register doesn't have the bit, and so on).
34 * Functions which simply ask "does this feature exist at all" have
35 * _any_ in their name, and always return the logical OR of the _aa64_
36 * and the _aa32_ function.
37 */
38
39 /*
40 * 32-bit feature tests via id registers.
41 */
isar_feature_aa32_thumb_div(const ARMISARegisters * id)42 static inline bool isar_feature_aa32_thumb_div(const ARMISARegisters *id)
43 {
44 return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) != 0;
45 }
46
isar_feature_aa32_arm_div(const ARMISARegisters * id)47 static inline bool isar_feature_aa32_arm_div(const ARMISARegisters *id)
48 {
49 return FIELD_EX32(id->id_isar0, ID_ISAR0, DIVIDE) > 1;
50 }
51
isar_feature_aa32_lob(const ARMISARegisters * id)52 static inline bool isar_feature_aa32_lob(const ARMISARegisters *id)
53 {
54 /* (M-profile) low-overhead loops and branch future */
55 return FIELD_EX32(id->id_isar0, ID_ISAR0, CMPBRANCH) >= 3;
56 }
57
isar_feature_aa32_jazelle(const ARMISARegisters * id)58 static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id)
59 {
60 return FIELD_EX32(id->id_isar1, ID_ISAR1, JAZELLE) != 0;
61 }
62
isar_feature_aa32_aes(const ARMISARegisters * id)63 static inline bool isar_feature_aa32_aes(const ARMISARegisters *id)
64 {
65 return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) != 0;
66 }
67
isar_feature_aa32_pmull(const ARMISARegisters * id)68 static inline bool isar_feature_aa32_pmull(const ARMISARegisters *id)
69 {
70 return FIELD_EX32(id->id_isar5, ID_ISAR5, AES) > 1;
71 }
72
isar_feature_aa32_sha1(const ARMISARegisters * id)73 static inline bool isar_feature_aa32_sha1(const ARMISARegisters *id)
74 {
75 return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA1) != 0;
76 }
77
isar_feature_aa32_sha2(const ARMISARegisters * id)78 static inline bool isar_feature_aa32_sha2(const ARMISARegisters *id)
79 {
80 return FIELD_EX32(id->id_isar5, ID_ISAR5, SHA2) != 0;
81 }
82
isar_feature_aa32_crc32(const ARMISARegisters * id)83 static inline bool isar_feature_aa32_crc32(const ARMISARegisters *id)
84 {
85 return FIELD_EX32(id->id_isar5, ID_ISAR5, CRC32) != 0;
86 }
87
isar_feature_aa32_rdm(const ARMISARegisters * id)88 static inline bool isar_feature_aa32_rdm(const ARMISARegisters *id)
89 {
90 return FIELD_EX32(id->id_isar5, ID_ISAR5, RDM) != 0;
91 }
92
isar_feature_aa32_vcma(const ARMISARegisters * id)93 static inline bool isar_feature_aa32_vcma(const ARMISARegisters *id)
94 {
95 return FIELD_EX32(id->id_isar5, ID_ISAR5, VCMA) != 0;
96 }
97
isar_feature_aa32_jscvt(const ARMISARegisters * id)98 static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id)
99 {
100 return FIELD_EX32(id->id_isar6, ID_ISAR6, JSCVT) != 0;
101 }
102
isar_feature_aa32_dp(const ARMISARegisters * id)103 static inline bool isar_feature_aa32_dp(const ARMISARegisters *id)
104 {
105 return FIELD_EX32(id->id_isar6, ID_ISAR6, DP) != 0;
106 }
107
isar_feature_aa32_fhm(const ARMISARegisters * id)108 static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id)
109 {
110 return FIELD_EX32(id->id_isar6, ID_ISAR6, FHM) != 0;
111 }
112
isar_feature_aa32_sb(const ARMISARegisters * id)113 static inline bool isar_feature_aa32_sb(const ARMISARegisters *id)
114 {
115 return FIELD_EX32(id->id_isar6, ID_ISAR6, SB) != 0;
116 }
117
isar_feature_aa32_predinv(const ARMISARegisters * id)118 static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
119 {
120 return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 0;
121 }
122
isar_feature_aa32_bf16(const ARMISARegisters * id)123 static inline bool isar_feature_aa32_bf16(const ARMISARegisters *id)
124 {
125 return FIELD_EX32(id->id_isar6, ID_ISAR6, BF16) != 0;
126 }
127
isar_feature_aa32_i8mm(const ARMISARegisters * id)128 static inline bool isar_feature_aa32_i8mm(const ARMISARegisters *id)
129 {
130 return FIELD_EX32(id->id_isar6, ID_ISAR6, I8MM) != 0;
131 }
132
isar_feature_aa32_ras(const ARMISARegisters * id)133 static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
134 {
135 return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0;
136 }
137
isar_feature_aa32_mprofile(const ARMISARegisters * id)138 static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
139 {
140 return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
141 }
142
isar_feature_aa32_m_sec_state(const ARMISARegisters * id)143 static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
144 {
145 /*
146 * Return true if M-profile state handling insns
147 * (VSCCLRM, CLRM, FPCTX access insns) are implemented
148 */
149 return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3;
150 }
151
isar_feature_aa32_fp16_arith(const ARMISARegisters * id)152 static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
153 {
154 /* Sadly this is encoded differently for A-profile and M-profile */
155 if (isar_feature_aa32_mprofile(id)) {
156 return FIELD_EX32(id->mvfr1, MVFR1, FP16) > 0;
157 } else {
158 return FIELD_EX32(id->mvfr1, MVFR1, FPHP) >= 3;
159 }
160 }
161
isar_feature_aa32_mve(const ARMISARegisters * id)162 static inline bool isar_feature_aa32_mve(const ARMISARegisters *id)
163 {
164 /*
165 * Return true if MVE is supported (either integer or floating point).
166 * We must check for M-profile as the MVFR1 field means something
167 * else for A-profile.
168 */
169 return isar_feature_aa32_mprofile(id) &&
170 FIELD_EX32(id->mvfr1, MVFR1, MVE) > 0;
171 }
172
isar_feature_aa32_mve_fp(const ARMISARegisters * id)173 static inline bool isar_feature_aa32_mve_fp(const ARMISARegisters *id)
174 {
175 /*
176 * Return true if MVE is supported (either integer or floating point).
177 * We must check for M-profile as the MVFR1 field means something
178 * else for A-profile.
179 */
180 return isar_feature_aa32_mprofile(id) &&
181 FIELD_EX32(id->mvfr1, MVFR1, MVE) >= 2;
182 }
183
isar_feature_aa32_vfp_simd(const ARMISARegisters * id)184 static inline bool isar_feature_aa32_vfp_simd(const ARMISARegisters *id)
185 {
186 /*
187 * Return true if either VFP or SIMD is implemented.
188 * In this case, a minimum of VFP w/ D0-D15.
189 */
190 return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) > 0;
191 }
192
isar_feature_aa32_simd_r32(const ARMISARegisters * id)193 static inline bool isar_feature_aa32_simd_r32(const ARMISARegisters *id)
194 {
195 /* Return true if D16-D31 are implemented */
196 return FIELD_EX32(id->mvfr0, MVFR0, SIMDREG) >= 2;
197 }
198
isar_feature_aa32_fpshvec(const ARMISARegisters * id)199 static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id)
200 {
201 return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0;
202 }
203
isar_feature_aa32_fpsp_v2(const ARMISARegisters * id)204 static inline bool isar_feature_aa32_fpsp_v2(const ARMISARegisters *id)
205 {
206 /* Return true if CPU supports single precision floating point, VFPv2 */
207 return FIELD_EX32(id->mvfr0, MVFR0, FPSP) > 0;
208 }
209
isar_feature_aa32_fpsp_v3(const ARMISARegisters * id)210 static inline bool isar_feature_aa32_fpsp_v3(const ARMISARegisters *id)
211 {
212 /* Return true if CPU supports single precision floating point, VFPv3 */
213 return FIELD_EX32(id->mvfr0, MVFR0, FPSP) >= 2;
214 }
215
isar_feature_aa32_fpdp_v2(const ARMISARegisters * id)216 static inline bool isar_feature_aa32_fpdp_v2(const ARMISARegisters *id)
217 {
218 /* Return true if CPU supports double precision floating point, VFPv2 */
219 return FIELD_EX32(id->mvfr0, MVFR0, FPDP) > 0;
220 }
221
isar_feature_aa32_fpdp_v3(const ARMISARegisters * id)222 static inline bool isar_feature_aa32_fpdp_v3(const ARMISARegisters *id)
223 {
224 /* Return true if CPU supports double precision floating point, VFPv3 */
225 return FIELD_EX32(id->mvfr0, MVFR0, FPDP) >= 2;
226 }
227
isar_feature_aa32_vfp(const ARMISARegisters * id)228 static inline bool isar_feature_aa32_vfp(const ARMISARegisters *id)
229 {
230 return isar_feature_aa32_fpsp_v2(id) || isar_feature_aa32_fpdp_v2(id);
231 }
232
233 /*
234 * We always set the FP and SIMD FP16 fields to indicate identical
235 * levels of support (assuming SIMD is implemented at all), so
236 * we only need one set of accessors.
237 */
isar_feature_aa32_fp16_spconv(const ARMISARegisters * id)238 static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id)
239 {
240 return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 0;
241 }
242
isar_feature_aa32_fp16_dpconv(const ARMISARegisters * id)243 static inline bool isar_feature_aa32_fp16_dpconv(const ARMISARegisters *id)
244 {
245 return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 1;
246 }
247
248 /*
249 * Note that this ID register field covers both VFP and Neon FMAC,
250 * so should usually be tested in combination with some other
251 * check that confirms the presence of whichever of VFP or Neon is
252 * relevant, to avoid accidentally enabling a Neon feature on
253 * a VFP-no-Neon core or vice-versa.
254 */
isar_feature_aa32_simdfmac(const ARMISARegisters * id)255 static inline bool isar_feature_aa32_simdfmac(const ARMISARegisters *id)
256 {
257 return FIELD_EX32(id->mvfr1, MVFR1, SIMDFMAC) != 0;
258 }
259
isar_feature_aa32_vsel(const ARMISARegisters * id)260 static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id)
261 {
262 return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 1;
263 }
264
isar_feature_aa32_vcvt_dr(const ARMISARegisters * id)265 static inline bool isar_feature_aa32_vcvt_dr(const ARMISARegisters *id)
266 {
267 return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 2;
268 }
269
isar_feature_aa32_vrint(const ARMISARegisters * id)270 static inline bool isar_feature_aa32_vrint(const ARMISARegisters *id)
271 {
272 return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 3;
273 }
274
isar_feature_aa32_vminmaxnm(const ARMISARegisters * id)275 static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
276 {
277 return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 4;
278 }
279
isar_feature_aa32_pxn(const ARMISARegisters * id)280 static inline bool isar_feature_aa32_pxn(const ARMISARegisters *id)
281 {
282 return FIELD_EX32(id->id_mmfr0, ID_MMFR0, VMSA) >= 4;
283 }
284
isar_feature_aa32_pan(const ARMISARegisters * id)285 static inline bool isar_feature_aa32_pan(const ARMISARegisters *id)
286 {
287 return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) != 0;
288 }
289
isar_feature_aa32_ats1e1(const ARMISARegisters * id)290 static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id)
291 {
292 return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) >= 2;
293 }
294
isar_feature_aa32_pmuv3p1(const ARMISARegisters * id)295 static inline bool isar_feature_aa32_pmuv3p1(const ARMISARegisters *id)
296 {
297 /* 0xf means "non-standard IMPDEF PMU" */
298 return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 4 &&
299 FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf;
300 }
301
isar_feature_aa32_pmuv3p4(const ARMISARegisters * id)302 static inline bool isar_feature_aa32_pmuv3p4(const ARMISARegisters *id)
303 {
304 /* 0xf means "non-standard IMPDEF PMU" */
305 return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 5 &&
306 FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf;
307 }
308
isar_feature_aa32_pmuv3p5(const ARMISARegisters * id)309 static inline bool isar_feature_aa32_pmuv3p5(const ARMISARegisters *id)
310 {
311 /* 0xf means "non-standard IMPDEF PMU" */
312 return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 6 &&
313 FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf;
314 }
315
isar_feature_aa32_hpd(const ARMISARegisters * id)316 static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id)
317 {
318 return FIELD_EX32(id->id_mmfr4, ID_MMFR4, HPDS) != 0;
319 }
320
isar_feature_aa32_ac2(const ARMISARegisters * id)321 static inline bool isar_feature_aa32_ac2(const ARMISARegisters *id)
322 {
323 return FIELD_EX32(id->id_mmfr4, ID_MMFR4, AC2) != 0;
324 }
325
isar_feature_aa32_ccidx(const ARMISARegisters * id)326 static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id)
327 {
328 return FIELD_EX32(id->id_mmfr4, ID_MMFR4, CCIDX) != 0;
329 }
330
isar_feature_aa32_tts2uxn(const ARMISARegisters * id)331 static inline bool isar_feature_aa32_tts2uxn(const ARMISARegisters *id)
332 {
333 return FIELD_EX32(id->id_mmfr4, ID_MMFR4, XNX) != 0;
334 }
335
isar_feature_aa32_half_evt(const ARMISARegisters * id)336 static inline bool isar_feature_aa32_half_evt(const ARMISARegisters *id)
337 {
338 return FIELD_EX32(id->id_mmfr4, ID_MMFR4, EVT) >= 1;
339 }
340
isar_feature_aa32_evt(const ARMISARegisters * id)341 static inline bool isar_feature_aa32_evt(const ARMISARegisters *id)
342 {
343 return FIELD_EX32(id->id_mmfr4, ID_MMFR4, EVT) >= 2;
344 }
345
isar_feature_aa32_dit(const ARMISARegisters * id)346 static inline bool isar_feature_aa32_dit(const ARMISARegisters *id)
347 {
348 return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0;
349 }
350
isar_feature_aa32_ssbs(const ARMISARegisters * id)351 static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
352 {
353 return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0;
354 }
355
isar_feature_aa32_debugv7p1(const ARMISARegisters * id)356 static inline bool isar_feature_aa32_debugv7p1(const ARMISARegisters *id)
357 {
358 return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 5;
359 }
360
isar_feature_aa32_debugv8p2(const ARMISARegisters * id)361 static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id)
362 {
363 return FIELD_EX32(id->id_dfr0, ID_DFR0, COPDBG) >= 8;
364 }
365
isar_feature_aa32_doublelock(const ARMISARegisters * id)366 static inline bool isar_feature_aa32_doublelock(const ARMISARegisters *id)
367 {
368 return FIELD_EX32(id->dbgdevid, DBGDEVID, DOUBLELOCK) > 0;
369 }
370
371 /*
372 * 64-bit feature tests via id registers.
373 */
isar_feature_aa64_aes(const ARMISARegisters * id)374 static inline bool isar_feature_aa64_aes(const ARMISARegisters *id)
375 {
376 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, AES) != 0;
377 }
378
isar_feature_aa64_pmull(const ARMISARegisters * id)379 static inline bool isar_feature_aa64_pmull(const ARMISARegisters *id)
380 {
381 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, AES) > 1;
382 }
383
isar_feature_aa64_sha1(const ARMISARegisters * id)384 static inline bool isar_feature_aa64_sha1(const ARMISARegisters *id)
385 {
386 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA1) != 0;
387 }
388
isar_feature_aa64_sha256(const ARMISARegisters * id)389 static inline bool isar_feature_aa64_sha256(const ARMISARegisters *id)
390 {
391 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA2) != 0;
392 }
393
isar_feature_aa64_sha512(const ARMISARegisters * id)394 static inline bool isar_feature_aa64_sha512(const ARMISARegisters *id)
395 {
396 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA2) > 1;
397 }
398
isar_feature_aa64_crc32(const ARMISARegisters * id)399 static inline bool isar_feature_aa64_crc32(const ARMISARegisters *id)
400 {
401 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, CRC32) != 0;
402 }
403
isar_feature_aa64_atomics(const ARMISARegisters * id)404 static inline bool isar_feature_aa64_atomics(const ARMISARegisters *id)
405 {
406 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, ATOMIC) != 0;
407 }
408
isar_feature_aa64_rdm(const ARMISARegisters * id)409 static inline bool isar_feature_aa64_rdm(const ARMISARegisters *id)
410 {
411 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RDM) != 0;
412 }
413
isar_feature_aa64_sha3(const ARMISARegisters * id)414 static inline bool isar_feature_aa64_sha3(const ARMISARegisters *id)
415 {
416 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SHA3) != 0;
417 }
418
isar_feature_aa64_sm3(const ARMISARegisters * id)419 static inline bool isar_feature_aa64_sm3(const ARMISARegisters *id)
420 {
421 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SM3) != 0;
422 }
423
isar_feature_aa64_sm4(const ARMISARegisters * id)424 static inline bool isar_feature_aa64_sm4(const ARMISARegisters *id)
425 {
426 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, SM4) != 0;
427 }
428
isar_feature_aa64_dp(const ARMISARegisters * id)429 static inline bool isar_feature_aa64_dp(const ARMISARegisters *id)
430 {
431 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, DP) != 0;
432 }
433
isar_feature_aa64_fhm(const ARMISARegisters * id)434 static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id)
435 {
436 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, FHM) != 0;
437 }
438
isar_feature_aa64_condm_4(const ARMISARegisters * id)439 static inline bool isar_feature_aa64_condm_4(const ARMISARegisters *id)
440 {
441 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) != 0;
442 }
443
isar_feature_aa64_condm_5(const ARMISARegisters * id)444 static inline bool isar_feature_aa64_condm_5(const ARMISARegisters *id)
445 {
446 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TS) >= 2;
447 }
448
isar_feature_aa64_rndr(const ARMISARegisters * id)449 static inline bool isar_feature_aa64_rndr(const ARMISARegisters *id)
450 {
451 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, RNDR) != 0;
452 }
453
isar_feature_aa64_tlbirange(const ARMISARegisters * id)454 static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id)
455 {
456 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) == 2;
457 }
458
isar_feature_aa64_tlbios(const ARMISARegisters * id)459 static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id)
460 {
461 return FIELD_EX64(id->id_aa64isar0, ID_AA64ISAR0, TLB) != 0;
462 }
463
isar_feature_aa64_jscvt(const ARMISARegisters * id)464 static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
465 {
466 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, JSCVT) != 0;
467 }
468
isar_feature_aa64_fcma(const ARMISARegisters * id)469 static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id)
470 {
471 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FCMA) != 0;
472 }
473
474 /*
475 * These are the values from APA/API/APA3.
476 * In general these must be compared '>=', per the normal Arm ARM
477 * treatment of fields in ID registers.
478 */
479 typedef enum {
480 PauthFeat_None = 0,
481 PauthFeat_1 = 1,
482 PauthFeat_EPAC = 2,
483 PauthFeat_2 = 3,
484 PauthFeat_FPAC = 4,
485 PauthFeat_FPACCOMBINED = 5,
486 } ARMPauthFeature;
487
488 static inline ARMPauthFeature
isar_feature_pauth_feature(const ARMISARegisters * id)489 isar_feature_pauth_feature(const ARMISARegisters *id)
490 {
491 /*
492 * Architecturally, only one of {APA,API,APA3} may be active (non-zero)
493 * and the other two must be zero. Thus we may avoid conditionals.
494 */
495 return (FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) |
496 FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, API) |
497 FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3));
498 }
499
isar_feature_aa64_pauth(const ARMISARegisters * id)500 static inline bool isar_feature_aa64_pauth(const ARMISARegisters *id)
501 {
502 /*
503 * Return true if any form of pauth is enabled, as this
504 * predicate controls migration of the 128-bit keys.
505 */
506 return isar_feature_pauth_feature(id) != PauthFeat_None;
507 }
508
isar_feature_aa64_pauth_qarma5(const ARMISARegisters * id)509 static inline bool isar_feature_aa64_pauth_qarma5(const ARMISARegisters *id)
510 {
511 /*
512 * Return true if pauth is enabled with the architected QARMA5 algorithm.
513 * QEMU will always enable or disable both APA and GPA.
514 */
515 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, APA) != 0;
516 }
517
isar_feature_aa64_pauth_qarma3(const ARMISARegisters * id)518 static inline bool isar_feature_aa64_pauth_qarma3(const ARMISARegisters *id)
519 {
520 /*
521 * Return true if pauth is enabled with the architected QARMA3 algorithm.
522 * QEMU will always enable or disable both APA3 and GPA3.
523 */
524 return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, APA3) != 0;
525 }
526
isar_feature_aa64_sb(const ARMISARegisters * id)527 static inline bool isar_feature_aa64_sb(const ARMISARegisters *id)
528 {
529 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SB) != 0;
530 }
531
isar_feature_aa64_predinv(const ARMISARegisters * id)532 static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id)
533 {
534 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, SPECRES) != 0;
535 }
536
isar_feature_aa64_frint(const ARMISARegisters * id)537 static inline bool isar_feature_aa64_frint(const ARMISARegisters *id)
538 {
539 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, FRINTTS) != 0;
540 }
541
isar_feature_aa64_dcpop(const ARMISARegisters * id)542 static inline bool isar_feature_aa64_dcpop(const ARMISARegisters *id)
543 {
544 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) != 0;
545 }
546
isar_feature_aa64_dcpodp(const ARMISARegisters * id)547 static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id)
548 {
549 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, DPB) >= 2;
550 }
551
isar_feature_aa64_bf16(const ARMISARegisters * id)552 static inline bool isar_feature_aa64_bf16(const ARMISARegisters *id)
553 {
554 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, BF16) != 0;
555 }
556
isar_feature_aa64_rcpc_8_3(const ARMISARegisters * id)557 static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id)
558 {
559 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0;
560 }
561
isar_feature_aa64_rcpc_8_4(const ARMISARegisters * id)562 static inline bool isar_feature_aa64_rcpc_8_4(const ARMISARegisters *id)
563 {
564 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) >= 2;
565 }
566
isar_feature_aa64_i8mm(const ARMISARegisters * id)567 static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id)
568 {
569 return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, I8MM) != 0;
570 }
571
isar_feature_aa64_hbc(const ARMISARegisters * id)572 static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id)
573 {
574 return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, BC) != 0;
575 }
576
isar_feature_aa64_mops(const ARMISARegisters * id)577 static inline bool isar_feature_aa64_mops(const ARMISARegisters *id)
578 {
579 return FIELD_EX64(id->id_aa64isar2, ID_AA64ISAR2, MOPS);
580 }
581
isar_feature_aa64_fp_simd(const ARMISARegisters * id)582 static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id)
583 {
584 /* We always set the AdvSIMD and FP fields identically. */
585 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) != 0xf;
586 }
587
isar_feature_aa64_fp16(const ARMISARegisters * id)588 static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
589 {
590 /* We always set the AdvSIMD and FP fields identically wrt FP16. */
591 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
592 }
593
isar_feature_aa64_aa32(const ARMISARegisters * id)594 static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id)
595 {
596 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL0) >= 2;
597 }
598
isar_feature_aa64_aa32_el1(const ARMISARegisters * id)599 static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id)
600 {
601 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2;
602 }
603
isar_feature_aa64_aa32_el2(const ARMISARegisters * id)604 static inline bool isar_feature_aa64_aa32_el2(const ARMISARegisters *id)
605 {
606 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL2) >= 2;
607 }
608
isar_feature_aa64_ras(const ARMISARegisters * id)609 static inline bool isar_feature_aa64_ras(const ARMISARegisters *id)
610 {
611 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0;
612 }
613
isar_feature_aa64_doublefault(const ARMISARegisters * id)614 static inline bool isar_feature_aa64_doublefault(const ARMISARegisters *id)
615 {
616 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) >= 2;
617 }
618
isar_feature_aa64_sve(const ARMISARegisters * id)619 static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
620 {
621 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SVE) != 0;
622 }
623
isar_feature_aa64_sel2(const ARMISARegisters * id)624 static inline bool isar_feature_aa64_sel2(const ARMISARegisters *id)
625 {
626 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, SEL2) != 0;
627 }
628
isar_feature_aa64_rme(const ARMISARegisters * id)629 static inline bool isar_feature_aa64_rme(const ARMISARegisters *id)
630 {
631 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RME) != 0;
632 }
633
isar_feature_aa64_dit(const ARMISARegisters * id)634 static inline bool isar_feature_aa64_dit(const ARMISARegisters *id)
635 {
636 return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0;
637 }
638
isar_feature_aa64_scxtnum(const ARMISARegisters * id)639 static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id)
640 {
641 int key = FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, CSV2);
642 if (key >= 2) {
643 return true; /* FEAT_CSV2_2 */
644 }
645 if (key == 1) {
646 key = FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, CSV2_FRAC);
647 return key >= 2; /* FEAT_CSV2_1p2 */
648 }
649 return false;
650 }
651
isar_feature_aa64_ssbs(const ARMISARegisters * id)652 static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
653 {
654 return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
655 }
656
isar_feature_aa64_bti(const ARMISARegisters * id)657 static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
658 {
659 return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
660 }
661
isar_feature_aa64_mte_insn_reg(const ARMISARegisters * id)662 static inline bool isar_feature_aa64_mte_insn_reg(const ARMISARegisters *id)
663 {
664 return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) != 0;
665 }
666
isar_feature_aa64_mte(const ARMISARegisters * id)667 static inline bool isar_feature_aa64_mte(const ARMISARegisters *id)
668 {
669 return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 2;
670 }
671
isar_feature_aa64_mte3(const ARMISARegisters * id)672 static inline bool isar_feature_aa64_mte3(const ARMISARegisters *id)
673 {
674 return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, MTE) >= 3;
675 }
676
isar_feature_aa64_sme(const ARMISARegisters * id)677 static inline bool isar_feature_aa64_sme(const ARMISARegisters *id)
678 {
679 return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SME) != 0;
680 }
681
isar_feature_aa64_tgran4_lpa2(const ARMISARegisters * id)682 static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id)
683 {
684 return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1;
685 }
686
isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters * id)687 static inline bool isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters *id)
688 {
689 unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2);
690 return t >= 3 || (t == 0 && isar_feature_aa64_tgran4_lpa2(id));
691 }
692
isar_feature_aa64_tgran16_lpa2(const ARMISARegisters * id)693 static inline bool isar_feature_aa64_tgran16_lpa2(const ARMISARegisters *id)
694 {
695 return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 2;
696 }
697
isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters * id)698 static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id)
699 {
700 unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2);
701 return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id));
702 }
703
isar_feature_aa64_tgran4(const ARMISARegisters * id)704 static inline bool isar_feature_aa64_tgran4(const ARMISARegisters *id)
705 {
706 return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 0;
707 }
708
isar_feature_aa64_tgran16(const ARMISARegisters * id)709 static inline bool isar_feature_aa64_tgran16(const ARMISARegisters *id)
710 {
711 return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 1;
712 }
713
isar_feature_aa64_tgran64(const ARMISARegisters * id)714 static inline bool isar_feature_aa64_tgran64(const ARMISARegisters *id)
715 {
716 return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64) >= 0;
717 }
718
isar_feature_aa64_tgran4_2(const ARMISARegisters * id)719 static inline bool isar_feature_aa64_tgran4_2(const ARMISARegisters *id)
720 {
721 unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2);
722 return t >= 2 || (t == 0 && isar_feature_aa64_tgran4(id));
723 }
724
isar_feature_aa64_tgran16_2(const ARMISARegisters * id)725 static inline bool isar_feature_aa64_tgran16_2(const ARMISARegisters *id)
726 {
727 unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2);
728 return t >= 2 || (t == 0 && isar_feature_aa64_tgran16(id));
729 }
730
isar_feature_aa64_tgran64_2(const ARMISARegisters * id)731 static inline bool isar_feature_aa64_tgran64_2(const ARMISARegisters *id)
732 {
733 unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64_2);
734 return t >= 2 || (t == 0 && isar_feature_aa64_tgran64(id));
735 }
736
isar_feature_aa64_fgt(const ARMISARegisters * id)737 static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id)
738 {
739 return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, FGT) != 0;
740 }
741
isar_feature_aa64_vh(const ARMISARegisters * id)742 static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
743 {
744 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, VH) != 0;
745 }
746
isar_feature_aa64_lor(const ARMISARegisters * id)747 static inline bool isar_feature_aa64_lor(const ARMISARegisters *id)
748 {
749 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0;
750 }
751
isar_feature_aa64_pan(const ARMISARegisters * id)752 static inline bool isar_feature_aa64_pan(const ARMISARegisters *id)
753 {
754 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) != 0;
755 }
756
isar_feature_aa64_ats1e1(const ARMISARegisters * id)757 static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id)
758 {
759 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2;
760 }
761
isar_feature_aa64_pan3(const ARMISARegisters * id)762 static inline bool isar_feature_aa64_pan3(const ARMISARegisters *id)
763 {
764 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 3;
765 }
766
isar_feature_aa64_hcx(const ARMISARegisters * id)767 static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id)
768 {
769 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HCX) != 0;
770 }
771
isar_feature_aa64_tidcp1(const ARMISARegisters * id)772 static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id)
773 {
774 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, TIDCP1) != 0;
775 }
776
isar_feature_aa64_hafs(const ARMISARegisters * id)777 static inline bool isar_feature_aa64_hafs(const ARMISARegisters *id)
778 {
779 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) != 0;
780 }
781
isar_feature_aa64_hdbs(const ARMISARegisters * id)782 static inline bool isar_feature_aa64_hdbs(const ARMISARegisters *id)
783 {
784 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HAFDBS) >= 2;
785 }
786
isar_feature_aa64_tts2uxn(const ARMISARegisters * id)787 static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id)
788 {
789 return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, XNX) != 0;
790 }
791
isar_feature_aa64_uao(const ARMISARegisters * id)792 static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
793 {
794 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
795 }
796
isar_feature_aa64_st(const ARMISARegisters * id)797 static inline bool isar_feature_aa64_st(const ARMISARegisters *id)
798 {
799 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, ST) != 0;
800 }
801
isar_feature_aa64_lse2(const ARMISARegisters * id)802 static inline bool isar_feature_aa64_lse2(const ARMISARegisters *id)
803 {
804 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, AT) != 0;
805 }
806
isar_feature_aa64_fwb(const ARMISARegisters * id)807 static inline bool isar_feature_aa64_fwb(const ARMISARegisters *id)
808 {
809 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, FWB) != 0;
810 }
811
isar_feature_aa64_ids(const ARMISARegisters * id)812 static inline bool isar_feature_aa64_ids(const ARMISARegisters *id)
813 {
814 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, IDS) != 0;
815 }
816
isar_feature_aa64_half_evt(const ARMISARegisters * id)817 static inline bool isar_feature_aa64_half_evt(const ARMISARegisters *id)
818 {
819 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, EVT) >= 1;
820 }
821
isar_feature_aa64_evt(const ARMISARegisters * id)822 static inline bool isar_feature_aa64_evt(const ARMISARegisters *id)
823 {
824 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, EVT) >= 2;
825 }
826
isar_feature_aa64_ccidx(const ARMISARegisters * id)827 static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id)
828 {
829 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0;
830 }
831
isar_feature_aa64_lva(const ARMISARegisters * id)832 static inline bool isar_feature_aa64_lva(const ARMISARegisters *id)
833 {
834 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, VARANGE) != 0;
835 }
836
isar_feature_aa64_e0pd(const ARMISARegisters * id)837 static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id)
838 {
839 return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, E0PD) != 0;
840 }
841
isar_feature_aa64_pmuv3p1(const ARMISARegisters * id)842 static inline bool isar_feature_aa64_pmuv3p1(const ARMISARegisters *id)
843 {
844 return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 &&
845 FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
846 }
847
isar_feature_aa64_pmuv3p4(const ARMISARegisters * id)848 static inline bool isar_feature_aa64_pmuv3p4(const ARMISARegisters *id)
849 {
850 return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 &&
851 FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
852 }
853
isar_feature_aa64_pmuv3p5(const ARMISARegisters * id)854 static inline bool isar_feature_aa64_pmuv3p5(const ARMISARegisters *id)
855 {
856 return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 6 &&
857 FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf;
858 }
859
isar_feature_aa64_debugv8p2(const ARMISARegisters * id)860 static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id)
861 {
862 return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, DEBUGVER) >= 8;
863 }
864
isar_feature_aa64_doublelock(const ARMISARegisters * id)865 static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id)
866 {
867 return FIELD_SEX64(id->id_aa64dfr0, ID_AA64DFR0, DOUBLELOCK) >= 0;
868 }
869
isar_feature_aa64_sve2(const ARMISARegisters * id)870 static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id)
871 {
872 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SVEVER) != 0;
873 }
874
isar_feature_aa64_sve2_aes(const ARMISARegisters * id)875 static inline bool isar_feature_aa64_sve2_aes(const ARMISARegisters *id)
876 {
877 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) != 0;
878 }
879
isar_feature_aa64_sve2_pmull128(const ARMISARegisters * id)880 static inline bool isar_feature_aa64_sve2_pmull128(const ARMISARegisters *id)
881 {
882 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, AES) >= 2;
883 }
884
isar_feature_aa64_sve2_bitperm(const ARMISARegisters * id)885 static inline bool isar_feature_aa64_sve2_bitperm(const ARMISARegisters *id)
886 {
887 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BITPERM) != 0;
888 }
889
isar_feature_aa64_sve_bf16(const ARMISARegisters * id)890 static inline bool isar_feature_aa64_sve_bf16(const ARMISARegisters *id)
891 {
892 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, BFLOAT16) != 0;
893 }
894
isar_feature_aa64_sve2_sha3(const ARMISARegisters * id)895 static inline bool isar_feature_aa64_sve2_sha3(const ARMISARegisters *id)
896 {
897 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SHA3) != 0;
898 }
899
isar_feature_aa64_sve2_sm4(const ARMISARegisters * id)900 static inline bool isar_feature_aa64_sve2_sm4(const ARMISARegisters *id)
901 {
902 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, SM4) != 0;
903 }
904
isar_feature_aa64_sve_i8mm(const ARMISARegisters * id)905 static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id)
906 {
907 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, I8MM) != 0;
908 }
909
isar_feature_aa64_sve_f32mm(const ARMISARegisters * id)910 static inline bool isar_feature_aa64_sve_f32mm(const ARMISARegisters *id)
911 {
912 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F32MM) != 0;
913 }
914
isar_feature_aa64_sve_f64mm(const ARMISARegisters * id)915 static inline bool isar_feature_aa64_sve_f64mm(const ARMISARegisters *id)
916 {
917 return FIELD_EX64(id->id_aa64zfr0, ID_AA64ZFR0, F64MM) != 0;
918 }
919
isar_feature_aa64_sme_f64f64(const ARMISARegisters * id)920 static inline bool isar_feature_aa64_sme_f64f64(const ARMISARegisters *id)
921 {
922 return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, F64F64);
923 }
924
isar_feature_aa64_sme_i16i64(const ARMISARegisters * id)925 static inline bool isar_feature_aa64_sme_i16i64(const ARMISARegisters *id)
926 {
927 return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, I16I64) == 0xf;
928 }
929
isar_feature_aa64_sme_fa64(const ARMISARegisters * id)930 static inline bool isar_feature_aa64_sme_fa64(const ARMISARegisters *id)
931 {
932 return FIELD_EX64(id->id_aa64smfr0, ID_AA64SMFR0, FA64);
933 }
934
935 /*
936 * Feature tests for "does this exist in either 32-bit or 64-bit?"
937 */
isar_feature_any_fp16(const ARMISARegisters * id)938 static inline bool isar_feature_any_fp16(const ARMISARegisters *id)
939 {
940 return isar_feature_aa64_fp16(id) || isar_feature_aa32_fp16_arith(id);
941 }
942
isar_feature_any_predinv(const ARMISARegisters * id)943 static inline bool isar_feature_any_predinv(const ARMISARegisters *id)
944 {
945 return isar_feature_aa64_predinv(id) || isar_feature_aa32_predinv(id);
946 }
947
isar_feature_any_pmuv3p1(const ARMISARegisters * id)948 static inline bool isar_feature_any_pmuv3p1(const ARMISARegisters *id)
949 {
950 return isar_feature_aa64_pmuv3p1(id) || isar_feature_aa32_pmuv3p1(id);
951 }
952
isar_feature_any_pmuv3p4(const ARMISARegisters * id)953 static inline bool isar_feature_any_pmuv3p4(const ARMISARegisters *id)
954 {
955 return isar_feature_aa64_pmuv3p4(id) || isar_feature_aa32_pmuv3p4(id);
956 }
957
isar_feature_any_pmuv3p5(const ARMISARegisters * id)958 static inline bool isar_feature_any_pmuv3p5(const ARMISARegisters *id)
959 {
960 return isar_feature_aa64_pmuv3p5(id) || isar_feature_aa32_pmuv3p5(id);
961 }
962
isar_feature_any_ccidx(const ARMISARegisters * id)963 static inline bool isar_feature_any_ccidx(const ARMISARegisters *id)
964 {
965 return isar_feature_aa64_ccidx(id) || isar_feature_aa32_ccidx(id);
966 }
967
isar_feature_any_tts2uxn(const ARMISARegisters * id)968 static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id)
969 {
970 return isar_feature_aa64_tts2uxn(id) || isar_feature_aa32_tts2uxn(id);
971 }
972
isar_feature_any_debugv8p2(const ARMISARegisters * id)973 static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id)
974 {
975 return isar_feature_aa64_debugv8p2(id) || isar_feature_aa32_debugv8p2(id);
976 }
977
isar_feature_any_ras(const ARMISARegisters * id)978 static inline bool isar_feature_any_ras(const ARMISARegisters *id)
979 {
980 return isar_feature_aa64_ras(id) || isar_feature_aa32_ras(id);
981 }
982
isar_feature_any_half_evt(const ARMISARegisters * id)983 static inline bool isar_feature_any_half_evt(const ARMISARegisters *id)
984 {
985 return isar_feature_aa64_half_evt(id) || isar_feature_aa32_half_evt(id);
986 }
987
isar_feature_any_evt(const ARMISARegisters * id)988 static inline bool isar_feature_any_evt(const ARMISARegisters *id)
989 {
990 return isar_feature_aa64_evt(id) || isar_feature_aa32_evt(id);
991 }
992
993 /*
994 * Forward to the above feature tests given an ARMCPU pointer.
995 */
996 #define cpu_isar_feature(name, cpu) \
997 ({ ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); })
998
999 #endif
1000