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