xref: /qemu/target/arm/cpu-features.h (revision 7698afc42b5af9e55f12ab2236618e38e5a1c23f)
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  */
isar_feature_aa32_thumb_div(const ARMISARegisters * id)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 
isar_feature_aa32_arm_div(const ARMISARegisters * id)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 
isar_feature_aa32_lob(const ARMISARegisters * id)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 
isar_feature_aa32_jazelle(const ARMISARegisters * id)63 static inline bool isar_feature_aa32_jazelle(const ARMISARegisters *id)
64 {
65     return FIELD_EX32_IDREG(id, ID_ISAR1, JAZELLE) != 0;
66 }
67 
isar_feature_aa32_aes(const ARMISARegisters * id)68 static inline bool isar_feature_aa32_aes(const ARMISARegisters *id)
69 {
70     return FIELD_EX32_IDREG(id, ID_ISAR5, AES) != 0;
71 }
72 
isar_feature_aa32_pmull(const ARMISARegisters * id)73 static inline bool isar_feature_aa32_pmull(const ARMISARegisters *id)
74 {
75     return FIELD_EX32_IDREG(id, ID_ISAR5, AES) > 1;
76 }
77 
isar_feature_aa32_sha1(const ARMISARegisters * id)78 static inline bool isar_feature_aa32_sha1(const ARMISARegisters *id)
79 {
80     return FIELD_EX32_IDREG(id, ID_ISAR5, SHA1) != 0;
81 }
82 
isar_feature_aa32_sha2(const ARMISARegisters * id)83 static inline bool isar_feature_aa32_sha2(const ARMISARegisters *id)
84 {
85     return FIELD_EX32_IDREG(id, ID_ISAR5, SHA2) != 0;
86 }
87 
isar_feature_aa32_crc32(const ARMISARegisters * id)88 static inline bool isar_feature_aa32_crc32(const ARMISARegisters *id)
89 {
90     return FIELD_EX32_IDREG(id, ID_ISAR5, CRC32) != 0;
91 }
92 
isar_feature_aa32_rdm(const ARMISARegisters * id)93 static inline bool isar_feature_aa32_rdm(const ARMISARegisters *id)
94 {
95     return FIELD_EX32_IDREG(id, ID_ISAR5, RDM) != 0;
96 }
97 
isar_feature_aa32_vcma(const ARMISARegisters * id)98 static inline bool isar_feature_aa32_vcma(const ARMISARegisters *id)
99 {
100     return FIELD_EX32_IDREG(id, ID_ISAR5, VCMA) != 0;
101 }
102 
isar_feature_aa32_jscvt(const ARMISARegisters * id)103 static inline bool isar_feature_aa32_jscvt(const ARMISARegisters *id)
104 {
105     return FIELD_EX32_IDREG(id, ID_ISAR6, JSCVT) != 0;
106 }
107 
isar_feature_aa32_dp(const ARMISARegisters * id)108 static inline bool isar_feature_aa32_dp(const ARMISARegisters *id)
109 {
110     return FIELD_EX32_IDREG(id, ID_ISAR6, DP) != 0;
111 }
112 
isar_feature_aa32_fhm(const ARMISARegisters * id)113 static inline bool isar_feature_aa32_fhm(const ARMISARegisters *id)
114 {
115     return FIELD_EX32_IDREG(id, ID_ISAR6, FHM) != 0;
116 }
117 
isar_feature_aa32_sb(const ARMISARegisters * id)118 static inline bool isar_feature_aa32_sb(const ARMISARegisters *id)
119 {
120     return FIELD_EX32_IDREG(id, ID_ISAR6, SB) != 0;
121 }
122 
isar_feature_aa32_predinv(const ARMISARegisters * id)123 static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
124 {
125     return FIELD_EX32_IDREG(id, ID_ISAR6, SPECRES) != 0;
126 }
127 
isar_feature_aa32_bf16(const ARMISARegisters * id)128 static inline bool isar_feature_aa32_bf16(const ARMISARegisters *id)
129 {
130     return FIELD_EX32_IDREG(id, ID_ISAR6, BF16) != 0;
131 }
132 
isar_feature_aa32_i8mm(const ARMISARegisters * id)133 static inline bool isar_feature_aa32_i8mm(const ARMISARegisters *id)
134 {
135     return FIELD_EX32_IDREG(id, ID_ISAR6, I8MM) != 0;
136 }
137 
isar_feature_aa32_ras(const ARMISARegisters * id)138 static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
139 {
140     return FIELD_EX32_IDREG(id, ID_PFR0, RAS) != 0;
141 }
142 
isar_feature_aa32_mprofile(const ARMISARegisters * id)143 static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
144 {
145     return FIELD_EX32_IDREG(id, ID_PFR1, MPROGMOD) != 0;
146 }
147 
isar_feature_aa32_m_sec_state(const ARMISARegisters * id)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 
isar_feature_aa32_fp16_arith(const ARMISARegisters * id)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 
isar_feature_aa32_mve(const ARMISARegisters * id)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 
isar_feature_aa32_mve_fp(const ARMISARegisters * id)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 
isar_feature_aa32_vfp_simd(const ARMISARegisters * id)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 
isar_feature_aa32_simd_r32(const ARMISARegisters * id)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 
isar_feature_aa32_fpshvec(const ARMISARegisters * id)204 static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id)
205 {
206     return FIELD_EX32(id->mvfr0, MVFR0, FPSHVEC) > 0;
207 }
208 
isar_feature_aa32_fpsp_v2(const ARMISARegisters * id)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 
isar_feature_aa32_fpsp_v3(const ARMISARegisters * id)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 
isar_feature_aa32_fpdp_v2(const ARMISARegisters * id)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 
isar_feature_aa32_fpdp_v3(const ARMISARegisters * id)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 
isar_feature_aa32_vfp(const ARMISARegisters * id)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  */
isar_feature_aa32_fp16_spconv(const ARMISARegisters * id)243 static inline bool isar_feature_aa32_fp16_spconv(const ARMISARegisters *id)
244 {
245     return FIELD_EX32(id->mvfr1, MVFR1, FPHP) > 0;
246 }
247 
isar_feature_aa32_fp16_dpconv(const ARMISARegisters * id)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  */
isar_feature_aa32_simdfmac(const ARMISARegisters * id)260 static inline bool isar_feature_aa32_simdfmac(const ARMISARegisters *id)
261 {
262     return FIELD_EX32(id->mvfr1, MVFR1, SIMDFMAC) != 0;
263 }
264 
isar_feature_aa32_vsel(const ARMISARegisters * id)265 static inline bool isar_feature_aa32_vsel(const ARMISARegisters *id)
266 {
267     return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 1;
268 }
269 
isar_feature_aa32_vcvt_dr(const ARMISARegisters * id)270 static inline bool isar_feature_aa32_vcvt_dr(const ARMISARegisters *id)
271 {
272     return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 2;
273 }
274 
isar_feature_aa32_vrint(const ARMISARegisters * id)275 static inline bool isar_feature_aa32_vrint(const ARMISARegisters *id)
276 {
277     return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 3;
278 }
279 
isar_feature_aa32_vminmaxnm(const ARMISARegisters * id)280 static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
281 {
282     return FIELD_EX32(id->mvfr2, MVFR2, FPMISC) >= 4;
283 }
284 
isar_feature_aa32_pxn(const ARMISARegisters * id)285 static inline bool isar_feature_aa32_pxn(const ARMISARegisters *id)
286 {
287     return FIELD_EX32_IDREG(id, ID_MMFR0, VMSA) >= 4;
288 }
289 
isar_feature_aa32_pan(const ARMISARegisters * id)290 static inline bool isar_feature_aa32_pan(const ARMISARegisters *id)
291 {
292     return FIELD_EX32_IDREG(id, ID_MMFR3, PAN) != 0;
293 }
294 
isar_feature_aa32_ats1e1(const ARMISARegisters * id)295 static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id)
296 {
297     return FIELD_EX32_IDREG(id, ID_MMFR3, PAN) >= 2;
298 }
299 
isar_feature_aa32_pmuv3p1(const ARMISARegisters * id)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 
isar_feature_aa32_pmuv3p4(const ARMISARegisters * id)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 
isar_feature_aa32_pmuv3p5(const ARMISARegisters * id)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 
isar_feature_aa32_hpd(const ARMISARegisters * id)321 static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id)
322 {
323     return FIELD_EX32_IDREG(id, ID_MMFR4, HPDS) != 0;
324 }
325 
isar_feature_aa32_ac2(const ARMISARegisters * id)326 static inline bool isar_feature_aa32_ac2(const ARMISARegisters *id)
327 {
328     return FIELD_EX32_IDREG(id, ID_MMFR4, AC2) != 0;
329 }
330 
isar_feature_aa32_ccidx(const ARMISARegisters * id)331 static inline bool isar_feature_aa32_ccidx(const ARMISARegisters *id)
332 {
333     return FIELD_EX32_IDREG(id, ID_MMFR4, CCIDX) != 0;
334 }
335 
isar_feature_aa32_tts2uxn(const ARMISARegisters * id)336 static inline bool isar_feature_aa32_tts2uxn(const ARMISARegisters *id)
337 {
338     return FIELD_EX32_IDREG(id, ID_MMFR4, XNX) != 0;
339 }
340 
isar_feature_aa32_half_evt(const ARMISARegisters * id)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 
isar_feature_aa32_evt(const ARMISARegisters * id)346 static inline bool isar_feature_aa32_evt(const ARMISARegisters *id)
347 {
348     return FIELD_EX32_IDREG(id, ID_MMFR4, EVT) >= 2;
349 }
350 
isar_feature_aa32_dit(const ARMISARegisters * id)351 static inline bool isar_feature_aa32_dit(const ARMISARegisters *id)
352 {
353     return FIELD_EX32_IDREG(id, ID_PFR0, DIT) != 0;
354 }
355 
isar_feature_aa32_ssbs(const ARMISARegisters * id)356 static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
357 {
358     return FIELD_EX32_IDREG(id, ID_PFR2, SSBS) != 0;
359 }
360 
isar_feature_aa32_debugv7p1(const ARMISARegisters * id)361 static inline bool isar_feature_aa32_debugv7p1(const ARMISARegisters *id)
362 {
363     return FIELD_EX32_IDREG(id, ID_DFR0, COPDBG) >= 5;
364 }
365 
isar_feature_aa32_debugv8p2(const ARMISARegisters * id)366 static inline bool isar_feature_aa32_debugv8p2(const ARMISARegisters *id)
367 {
368     return FIELD_EX32_IDREG(id, ID_DFR0, COPDBG) >= 8;
369 }
370 
isar_feature_aa32_doublelock(const ARMISARegisters * id)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  */
isar_feature_aa64_aes(const ARMISARegisters * id)379 static inline bool isar_feature_aa64_aes(const ARMISARegisters *id)
380 {
381     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, AES) != 0;
382 }
383 
isar_feature_aa64_pmull(const ARMISARegisters * id)384 static inline bool isar_feature_aa64_pmull(const ARMISARegisters *id)
385 {
386     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, AES) > 1;
387 }
388 
isar_feature_aa64_sha1(const ARMISARegisters * id)389 static inline bool isar_feature_aa64_sha1(const ARMISARegisters *id)
390 {
391     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA1) != 0;
392 }
393 
isar_feature_aa64_sha256(const ARMISARegisters * id)394 static inline bool isar_feature_aa64_sha256(const ARMISARegisters *id)
395 {
396     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA2) != 0;
397 }
398 
isar_feature_aa64_sha512(const ARMISARegisters * id)399 static inline bool isar_feature_aa64_sha512(const ARMISARegisters *id)
400 {
401     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA2) > 1;
402 }
403 
isar_feature_aa64_crc32(const ARMISARegisters * id)404 static inline bool isar_feature_aa64_crc32(const ARMISARegisters *id)
405 {
406     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, CRC32) != 0;
407 }
408 
isar_feature_aa64_atomics(const ARMISARegisters * id)409 static inline bool isar_feature_aa64_atomics(const ARMISARegisters *id)
410 {
411     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, ATOMIC) != 0;
412 }
413 
isar_feature_aa64_rdm(const ARMISARegisters * id)414 static inline bool isar_feature_aa64_rdm(const ARMISARegisters *id)
415 {
416     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, RDM) != 0;
417 }
418 
isar_feature_aa64_sha3(const ARMISARegisters * id)419 static inline bool isar_feature_aa64_sha3(const ARMISARegisters *id)
420 {
421     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SHA3) != 0;
422 }
423 
isar_feature_aa64_sm3(const ARMISARegisters * id)424 static inline bool isar_feature_aa64_sm3(const ARMISARegisters *id)
425 {
426     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SM3) != 0;
427 }
428 
isar_feature_aa64_sm4(const ARMISARegisters * id)429 static inline bool isar_feature_aa64_sm4(const ARMISARegisters *id)
430 {
431     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, SM4) != 0;
432 }
433 
isar_feature_aa64_dp(const ARMISARegisters * id)434 static inline bool isar_feature_aa64_dp(const ARMISARegisters *id)
435 {
436     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, DP) != 0;
437 }
438 
isar_feature_aa64_fhm(const ARMISARegisters * id)439 static inline bool isar_feature_aa64_fhm(const ARMISARegisters *id)
440 {
441     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, FHM) != 0;
442 }
443 
isar_feature_aa64_condm_4(const ARMISARegisters * id)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 
isar_feature_aa64_condm_5(const ARMISARegisters * id)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 
isar_feature_aa64_rndr(const ARMISARegisters * id)454 static inline bool isar_feature_aa64_rndr(const ARMISARegisters *id)
455 {
456     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, RNDR) != 0;
457 }
458 
isar_feature_aa64_tlbirange(const ARMISARegisters * id)459 static inline bool isar_feature_aa64_tlbirange(const ARMISARegisters *id)
460 {
461     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, TLB) == 2;
462 }
463 
isar_feature_aa64_tlbios(const ARMISARegisters * id)464 static inline bool isar_feature_aa64_tlbios(const ARMISARegisters *id)
465 {
466     return FIELD_EX64_IDREG(id, ID_AA64ISAR0, TLB) != 0;
467 }
468 
isar_feature_aa64_jscvt(const ARMISARegisters * id)469 static inline bool isar_feature_aa64_jscvt(const ARMISARegisters *id)
470 {
471     return FIELD_EX64_IDREG(id, ID_AA64ISAR1, JSCVT) != 0;
472 }
473 
isar_feature_aa64_fcma(const ARMISARegisters * id)474 static inline bool isar_feature_aa64_fcma(const ARMISARegisters *id)
475 {
476     return FIELD_EX64_IDREG(id, ID_AA64ISAR1, FCMA) != 0;
477 }
478 
isar_feature_aa64_xs(const ARMISARegisters * id)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
isar_feature_pauth_feature(const ARMISARegisters * id)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 
isar_feature_aa64_pauth(const ARMISARegisters * id)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 
isar_feature_aa64_pauth_qarma5(const ARMISARegisters * id)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 
isar_feature_aa64_pauth_qarma3(const ARMISARegisters * id)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 
isar_feature_aa64_sb(const ARMISARegisters * id)537 static inline bool isar_feature_aa64_sb(const ARMISARegisters *id)
538 {
539     return FIELD_EX64_IDREG(id, ID_AA64ISAR1, SB) != 0;
540 }
541 
isar_feature_aa64_predinv(const ARMISARegisters * id)542 static inline bool isar_feature_aa64_predinv(const ARMISARegisters *id)
543 {
544     return FIELD_EX64_IDREG(id, ID_AA64ISAR1, SPECRES) != 0;
545 }
546 
isar_feature_aa64_frint(const ARMISARegisters * id)547 static inline bool isar_feature_aa64_frint(const ARMISARegisters *id)
548 {
549     return FIELD_EX64_IDREG(id, ID_AA64ISAR1, FRINTTS) != 0;
550 }
551 
isar_feature_aa64_dcpop(const ARMISARegisters * id)552 static inline bool isar_feature_aa64_dcpop(const ARMISARegisters *id)
553 {
554     return FIELD_EX64_IDREG(id, ID_AA64ISAR1, DPB) != 0;
555 }
556 
isar_feature_aa64_dcpodp(const ARMISARegisters * id)557 static inline bool isar_feature_aa64_dcpodp(const ARMISARegisters *id)
558 {
559     return FIELD_EX64_IDREG(id, ID_AA64ISAR1, DPB) >= 2;
560 }
561 
isar_feature_aa64_bf16(const ARMISARegisters * id)562 static inline bool isar_feature_aa64_bf16(const ARMISARegisters *id)
563 {
564     return FIELD_EX64_IDREG(id, ID_AA64ISAR1, BF16) != 0;
565 }
566 
isar_feature_aa64_ebf16(const ARMISARegisters * id)567 static inline bool isar_feature_aa64_ebf16(const ARMISARegisters *id)
568 {
569     return FIELD_EX64_IDREG(id, ID_AA64ISAR1, BF16) > 1;
570 }
571 
isar_feature_aa64_rcpc_8_3(const ARMISARegisters * id)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 
isar_feature_aa64_rcpc_8_4(const ARMISARegisters * id)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 
isar_feature_aa64_i8mm(const ARMISARegisters * id)582 static inline bool isar_feature_aa64_i8mm(const ARMISARegisters *id)
583 {
584     return FIELD_EX64_IDREG(id, ID_AA64ISAR1, I8MM) != 0;
585 }
586 
isar_feature_aa64_wfxt(const ARMISARegisters * id)587 static inline bool isar_feature_aa64_wfxt(const ARMISARegisters *id)
588 {
589     return FIELD_EX64_IDREG(id, ID_AA64ISAR2, WFXT) >= 2;
590 }
591 
isar_feature_aa64_hbc(const ARMISARegisters * id)592 static inline bool isar_feature_aa64_hbc(const ARMISARegisters *id)
593 {
594     return FIELD_EX64_IDREG(id, ID_AA64ISAR2, BC) != 0;
595 }
596 
isar_feature_aa64_mops(const ARMISARegisters * id)597 static inline bool isar_feature_aa64_mops(const ARMISARegisters *id)
598 {
599     return FIELD_EX64_IDREG(id, ID_AA64ISAR2, MOPS);
600 }
601 
isar_feature_aa64_rpres(const ARMISARegisters * id)602 static inline bool isar_feature_aa64_rpres(const ARMISARegisters *id)
603 {
604     return FIELD_EX64_IDREG(id, ID_AA64ISAR2, RPRES);
605 }
606 
isar_feature_aa64_fp_simd(const ARMISARegisters * id)607 static inline bool isar_feature_aa64_fp_simd(const ARMISARegisters *id)
608 {
609     /* We always set the AdvSIMD and FP fields identically.  */
610     return FIELD_EX64_IDREG(id, ID_AA64PFR0, FP) != 0xf;
611 }
612 
isar_feature_aa64_fp16(const ARMISARegisters * id)613 static inline bool isar_feature_aa64_fp16(const ARMISARegisters *id)
614 {
615     /* We always set the AdvSIMD and FP fields identically wrt FP16.  */
616     return FIELD_EX64_IDREG(id, ID_AA64PFR0, FP) == 1;
617 }
618 
isar_feature_aa64_aa32(const ARMISARegisters * id)619 static inline bool isar_feature_aa64_aa32(const ARMISARegisters *id)
620 {
621     return FIELD_EX64_IDREG(id, ID_AA64PFR0, EL0) >= 2;
622 }
623 
isar_feature_aa64_aa32_el1(const ARMISARegisters * id)624 static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id)
625 {
626     return FIELD_EX64_IDREG(id, ID_AA64PFR0, EL1) >= 2;
627 }
628 
isar_feature_aa64_aa32_el2(const ARMISARegisters * id)629 static inline bool isar_feature_aa64_aa32_el2(const ARMISARegisters *id)
630 {
631     return FIELD_EX64_IDREG(id, ID_AA64PFR0, EL2) >= 2;
632 }
633 
isar_feature_aa64_ras(const ARMISARegisters * id)634 static inline bool isar_feature_aa64_ras(const ARMISARegisters *id)
635 {
636     return FIELD_EX64_IDREG(id, ID_AA64PFR0, RAS) != 0;
637 }
638 
isar_feature_aa64_doublefault(const ARMISARegisters * id)639 static inline bool isar_feature_aa64_doublefault(const ARMISARegisters *id)
640 {
641     return FIELD_EX64_IDREG(id, ID_AA64PFR0, RAS) >= 2;
642 }
643 
isar_feature_aa64_sve(const ARMISARegisters * id)644 static inline bool isar_feature_aa64_sve(const ARMISARegisters *id)
645 {
646     return FIELD_EX64_IDREG(id, ID_AA64PFR0, SVE) != 0;
647 }
648 
isar_feature_aa64_sel2(const ARMISARegisters * id)649 static inline bool isar_feature_aa64_sel2(const ARMISARegisters *id)
650 {
651     return FIELD_EX64_IDREG(id, ID_AA64PFR0, SEL2) != 0;
652 }
653 
isar_feature_aa64_rme(const ARMISARegisters * id)654 static inline bool isar_feature_aa64_rme(const ARMISARegisters *id)
655 {
656     return FIELD_EX64_IDREG(id, ID_AA64PFR0, RME) != 0;
657 }
658 
isar_feature_aa64_dit(const ARMISARegisters * id)659 static inline bool isar_feature_aa64_dit(const ARMISARegisters *id)
660 {
661     return FIELD_EX64_IDREG(id, ID_AA64PFR0, DIT) != 0;
662 }
663 
isar_feature_aa64_scxtnum(const ARMISARegisters * id)664 static inline bool isar_feature_aa64_scxtnum(const ARMISARegisters *id)
665 {
666     int key = FIELD_EX64_IDREG(id, ID_AA64PFR0, CSV2);
667     if (key >= 2) {
668         return true;      /* FEAT_CSV2_2 */
669     }
670     if (key == 1) {
671         key = FIELD_EX64_IDREG(id, ID_AA64PFR1, CSV2_FRAC);
672         return key >= 2;  /* FEAT_CSV2_1p2 */
673     }
674     return false;
675 }
676 
isar_feature_aa64_ssbs(const ARMISARegisters * id)677 static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
678 {
679     return FIELD_EX64_IDREG(id, ID_AA64PFR1, SSBS) != 0;
680 }
681 
isar_feature_aa64_bti(const ARMISARegisters * id)682 static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
683 {
684     return FIELD_EX64_IDREG(id, ID_AA64PFR1, BT) != 0;
685 }
686 
isar_feature_aa64_mte_insn_reg(const ARMISARegisters * id)687 static inline bool isar_feature_aa64_mte_insn_reg(const ARMISARegisters *id)
688 {
689     return FIELD_EX64_IDREG(id, ID_AA64PFR1, MTE) != 0;
690 }
691 
isar_feature_aa64_mte(const ARMISARegisters * id)692 static inline bool isar_feature_aa64_mte(const ARMISARegisters *id)
693 {
694     return FIELD_EX64_IDREG(id, ID_AA64PFR1, MTE) >= 2;
695 }
696 
isar_feature_aa64_mte3(const ARMISARegisters * id)697 static inline bool isar_feature_aa64_mte3(const ARMISARegisters *id)
698 {
699     return FIELD_EX64_IDREG(id, ID_AA64PFR1, MTE) >= 3;
700 }
701 
isar_feature_aa64_sme(const ARMISARegisters * id)702 static inline bool isar_feature_aa64_sme(const ARMISARegisters *id)
703 {
704     return FIELD_EX64_IDREG(id, ID_AA64PFR1, SME) != 0;
705 }
706 
isar_feature_aa64_nmi(const ARMISARegisters * id)707 static inline bool isar_feature_aa64_nmi(const ARMISARegisters *id)
708 {
709     return FIELD_EX64_IDREG(id, ID_AA64PFR1, NMI) != 0;
710 }
711 
isar_feature_aa64_tgran4_lpa2(const ARMISARegisters * id)712 static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id)
713 {
714     return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN4) >= 1;
715 }
716 
isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters * id)717 static inline bool isar_feature_aa64_tgran4_2_lpa2(const ARMISARegisters *id)
718 {
719     unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN4_2);
720     return t >= 3 || (t == 0 && isar_feature_aa64_tgran4_lpa2(id));
721 }
722 
isar_feature_aa64_tgran16_lpa2(const ARMISARegisters * id)723 static inline bool isar_feature_aa64_tgran16_lpa2(const ARMISARegisters *id)
724 {
725     return FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16) >= 2;
726 }
727 
isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters * id)728 static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id)
729 {
730     unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16_2);
731     return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id));
732 }
733 
isar_feature_aa64_tgran4(const ARMISARegisters * id)734 static inline bool isar_feature_aa64_tgran4(const ARMISARegisters *id)
735 {
736     return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN4) >= 0;
737 }
738 
isar_feature_aa64_tgran16(const ARMISARegisters * id)739 static inline bool isar_feature_aa64_tgran16(const ARMISARegisters *id)
740 {
741     return FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16) >= 1;
742 }
743 
isar_feature_aa64_tgran64(const ARMISARegisters * id)744 static inline bool isar_feature_aa64_tgran64(const ARMISARegisters *id)
745 {
746     return FIELD_SEX64_IDREG(id, ID_AA64MMFR0, TGRAN64) >= 0;
747 }
748 
isar_feature_aa64_tgran4_2(const ARMISARegisters * id)749 static inline bool isar_feature_aa64_tgran4_2(const ARMISARegisters *id)
750 {
751     unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN4_2);
752     return t >= 2 || (t == 0 && isar_feature_aa64_tgran4(id));
753 }
754 
isar_feature_aa64_tgran16_2(const ARMISARegisters * id)755 static inline bool isar_feature_aa64_tgran16_2(const ARMISARegisters *id)
756 {
757     unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN16_2);
758     return t >= 2 || (t == 0 && isar_feature_aa64_tgran16(id));
759 }
760 
isar_feature_aa64_tgran64_2(const ARMISARegisters * id)761 static inline bool isar_feature_aa64_tgran64_2(const ARMISARegisters *id)
762 {
763     unsigned t = FIELD_EX64_IDREG(id, ID_AA64MMFR0, TGRAN64_2);
764     return t >= 2 || (t == 0 && isar_feature_aa64_tgran64(id));
765 }
766 
isar_feature_aa64_fgt(const ARMISARegisters * id)767 static inline bool isar_feature_aa64_fgt(const ARMISARegisters *id)
768 {
769     return FIELD_EX64_IDREG(id, ID_AA64MMFR0, FGT) != 0;
770 }
771 
isar_feature_aa64_ecv_traps(const ARMISARegisters * id)772 static inline bool isar_feature_aa64_ecv_traps(const ARMISARegisters *id)
773 {
774     return FIELD_EX64_IDREG(id, ID_AA64MMFR0, ECV) > 0;
775 }
776 
isar_feature_aa64_ecv(const ARMISARegisters * id)777 static inline bool isar_feature_aa64_ecv(const ARMISARegisters *id)
778 {
779     return FIELD_EX64_IDREG(id, ID_AA64MMFR0, ECV) > 1;
780 }
781 
isar_feature_aa64_vh(const ARMISARegisters * id)782 static inline bool isar_feature_aa64_vh(const ARMISARegisters *id)
783 {
784     return FIELD_EX64_IDREG(id, ID_AA64MMFR1, VH) != 0;
785 }
786 
isar_feature_aa64_lor(const ARMISARegisters * id)787 static inline bool isar_feature_aa64_lor(const ARMISARegisters *id)
788 {
789     return FIELD_EX64_IDREG(id, ID_AA64MMFR1, LO) != 0;
790 }
791 
isar_feature_aa64_pan(const ARMISARegisters * id)792 static inline bool isar_feature_aa64_pan(const ARMISARegisters *id)
793 {
794     return FIELD_EX64_IDREG(id, ID_AA64MMFR1, PAN) != 0;
795 }
796 
isar_feature_aa64_ats1e1(const ARMISARegisters * id)797 static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id)
798 {
799     return FIELD_EX64_IDREG(id, ID_AA64MMFR1, PAN) >= 2;
800 }
801 
isar_feature_aa64_pan3(const ARMISARegisters * id)802 static inline bool isar_feature_aa64_pan3(const ARMISARegisters *id)
803 {
804     return FIELD_EX64_IDREG(id, ID_AA64MMFR1, PAN) >= 3;
805 }
806 
isar_feature_aa64_hcx(const ARMISARegisters * id)807 static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id)
808 {
809     return FIELD_EX64_IDREG(id, ID_AA64MMFR1, HCX) != 0;
810 }
811 
isar_feature_aa64_afp(const ARMISARegisters * id)812 static inline bool isar_feature_aa64_afp(const ARMISARegisters *id)
813 {
814     return FIELD_EX64_IDREG(id, ID_AA64MMFR1, AFP) != 0;
815 }
816 
isar_feature_aa64_tidcp1(const ARMISARegisters * id)817 static inline bool isar_feature_aa64_tidcp1(const ARMISARegisters *id)
818 {
819     return FIELD_EX64_IDREG(id, ID_AA64MMFR1, TIDCP1) != 0;
820 }
821 
isar_feature_aa64_cmow(const ARMISARegisters * id)822 static inline bool isar_feature_aa64_cmow(const ARMISARegisters *id)
823 {
824     return FIELD_EX64_IDREG(id, ID_AA64MMFR1, CMOW) != 0;
825 }
826 
isar_feature_aa64_hafs(const ARMISARegisters * id)827 static inline bool isar_feature_aa64_hafs(const ARMISARegisters *id)
828 {
829     return FIELD_EX64_IDREG(id, ID_AA64MMFR1, HAFDBS) != 0;
830 }
831 
isar_feature_aa64_hdbs(const ARMISARegisters * id)832 static inline bool isar_feature_aa64_hdbs(const ARMISARegisters *id)
833 {
834     return FIELD_EX64_IDREG(id, ID_AA64MMFR1, HAFDBS) >= 2;
835 }
836 
isar_feature_aa64_tts2uxn(const ARMISARegisters * id)837 static inline bool isar_feature_aa64_tts2uxn(const ARMISARegisters *id)
838 {
839     return FIELD_EX64_IDREG(id, ID_AA64MMFR1, XNX) != 0;
840 }
841 
isar_feature_aa64_uao(const ARMISARegisters * id)842 static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
843 {
844     return FIELD_EX64_IDREG(id, ID_AA64MMFR2, UAO) != 0;
845 }
846 
isar_feature_aa64_st(const ARMISARegisters * id)847 static inline bool isar_feature_aa64_st(const ARMISARegisters *id)
848 {
849     return FIELD_EX64_IDREG(id, ID_AA64MMFR2, ST) != 0;
850 }
851 
isar_feature_aa64_lse2(const ARMISARegisters * id)852 static inline bool isar_feature_aa64_lse2(const ARMISARegisters *id)
853 {
854     return FIELD_EX64_IDREG(id, ID_AA64MMFR2, AT) != 0;
855 }
856 
isar_feature_aa64_fwb(const ARMISARegisters * id)857 static inline bool isar_feature_aa64_fwb(const ARMISARegisters *id)
858 {
859     return FIELD_EX64_IDREG(id, ID_AA64MMFR2, FWB) != 0;
860 }
861 
isar_feature_aa64_ids(const ARMISARegisters * id)862 static inline bool isar_feature_aa64_ids(const ARMISARegisters *id)
863 {
864     return FIELD_EX64_IDREG(id, ID_AA64MMFR2, IDS) != 0;
865 }
866 
isar_feature_aa64_half_evt(const ARMISARegisters * id)867 static inline bool isar_feature_aa64_half_evt(const ARMISARegisters *id)
868 {
869     return FIELD_EX64_IDREG(id, ID_AA64MMFR2, EVT) >= 1;
870 }
871 
isar_feature_aa64_evt(const ARMISARegisters * id)872 static inline bool isar_feature_aa64_evt(const ARMISARegisters *id)
873 {
874     return FIELD_EX64_IDREG(id, ID_AA64MMFR2, EVT) >= 2;
875 }
876 
isar_feature_aa64_ccidx(const ARMISARegisters * id)877 static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id)
878 {
879     return FIELD_EX64_IDREG(id, ID_AA64MMFR2, CCIDX) != 0;
880 }
881 
isar_feature_aa64_lva(const ARMISARegisters * id)882 static inline bool isar_feature_aa64_lva(const ARMISARegisters *id)
883 {
884     return FIELD_EX64_IDREG(id, ID_AA64MMFR2, VARANGE) != 0;
885 }
886 
isar_feature_aa64_e0pd(const ARMISARegisters * id)887 static inline bool isar_feature_aa64_e0pd(const ARMISARegisters *id)
888 {
889     return FIELD_EX64_IDREG(id, ID_AA64MMFR2, E0PD) != 0;
890 }
891 
isar_feature_aa64_nv(const ARMISARegisters * id)892 static inline bool isar_feature_aa64_nv(const ARMISARegisters *id)
893 {
894     return FIELD_EX64_IDREG(id, ID_AA64MMFR2, NV) != 0;
895 }
896 
isar_feature_aa64_nv2(const ARMISARegisters * id)897 static inline bool isar_feature_aa64_nv2(const ARMISARegisters *id)
898 {
899     return FIELD_EX64_IDREG(id, ID_AA64MMFR2, NV) >= 2;
900 }
901 
isar_feature_aa64_pmuv3p1(const ARMISARegisters * id)902 static inline bool isar_feature_aa64_pmuv3p1(const ARMISARegisters *id)
903 {
904     return FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) >= 4 &&
905         FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) != 0xf;
906 }
907 
isar_feature_aa64_pmuv3p4(const ARMISARegisters * id)908 static inline bool isar_feature_aa64_pmuv3p4(const ARMISARegisters *id)
909 {
910     return FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) >= 5 &&
911         FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) != 0xf;
912 }
913 
isar_feature_aa64_pmuv3p5(const ARMISARegisters * id)914 static inline bool isar_feature_aa64_pmuv3p5(const ARMISARegisters *id)
915 {
916     return FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) >= 6 &&
917         FIELD_EX64_IDREG(id, ID_AA64DFR0, PMUVER) != 0xf;
918 }
919 
isar_feature_aa64_debugv8p2(const ARMISARegisters * id)920 static inline bool isar_feature_aa64_debugv8p2(const ARMISARegisters *id)
921 {
922     return FIELD_EX64_IDREG(id, ID_AA64DFR0, DEBUGVER) >= 8;
923 }
924 
isar_feature_aa64_doublelock(const ARMISARegisters * id)925 static inline bool isar_feature_aa64_doublelock(const ARMISARegisters *id)
926 {
927     return FIELD_SEX64_IDREG(id, ID_AA64DFR0, DOUBLELOCK) >= 0;
928 }
929 
isar_feature_aa64_sve2(const ARMISARegisters * id)930 static inline bool isar_feature_aa64_sve2(const ARMISARegisters *id)
931 {
932     return FIELD_EX64_IDREG(id, ID_AA64ZFR0, SVEVER) != 0;
933 }
934 
isar_feature_aa64_sve2_aes(const ARMISARegisters * id)935 static inline bool isar_feature_aa64_sve2_aes(const ARMISARegisters *id)
936 {
937     return FIELD_EX64_IDREG(id, ID_AA64ZFR0, AES) != 0;
938 }
939 
isar_feature_aa64_sve2_pmull128(const ARMISARegisters * id)940 static inline bool isar_feature_aa64_sve2_pmull128(const ARMISARegisters *id)
941 {
942     return FIELD_EX64_IDREG(id, ID_AA64ZFR0, AES) >= 2;
943 }
944 
isar_feature_aa64_sve2_bitperm(const ARMISARegisters * id)945 static inline bool isar_feature_aa64_sve2_bitperm(const ARMISARegisters *id)
946 {
947     return FIELD_EX64_IDREG(id, ID_AA64ZFR0, BITPERM) != 0;
948 }
949 
isar_feature_aa64_sve_bf16(const ARMISARegisters * id)950 static inline bool isar_feature_aa64_sve_bf16(const ARMISARegisters *id)
951 {
952     return FIELD_EX64_IDREG(id, ID_AA64ZFR0, BFLOAT16) != 0;
953 }
954 
isar_feature_aa64_sve2_sha3(const ARMISARegisters * id)955 static inline bool isar_feature_aa64_sve2_sha3(const ARMISARegisters *id)
956 {
957     return FIELD_EX64_IDREG(id, ID_AA64ZFR0, SHA3) != 0;
958 }
959 
isar_feature_aa64_sve2_sm4(const ARMISARegisters * id)960 static inline bool isar_feature_aa64_sve2_sm4(const ARMISARegisters *id)
961 {
962     return FIELD_EX64_IDREG(id, ID_AA64ZFR0, SM4) != 0;
963 }
964 
isar_feature_aa64_sve_i8mm(const ARMISARegisters * id)965 static inline bool isar_feature_aa64_sve_i8mm(const ARMISARegisters *id)
966 {
967     return FIELD_EX64_IDREG(id, ID_AA64ZFR0, I8MM) != 0;
968 }
969 
isar_feature_aa64_sve_f32mm(const ARMISARegisters * id)970 static inline bool isar_feature_aa64_sve_f32mm(const ARMISARegisters *id)
971 {
972     return FIELD_EX64_IDREG(id, ID_AA64ZFR0, F32MM) != 0;
973 }
974 
isar_feature_aa64_sve_f64mm(const ARMISARegisters * id)975 static inline bool isar_feature_aa64_sve_f64mm(const ARMISARegisters *id)
976 {
977     return FIELD_EX64_IDREG(id, ID_AA64ZFR0, F64MM) != 0;
978 }
979 
isar_feature_aa64_sme_f64f64(const ARMISARegisters * id)980 static inline bool isar_feature_aa64_sme_f64f64(const ARMISARegisters *id)
981 {
982     return FIELD_EX64_IDREG(id, ID_AA64SMFR0, F64F64);
983 }
984 
isar_feature_aa64_sme_i16i64(const ARMISARegisters * id)985 static inline bool isar_feature_aa64_sme_i16i64(const ARMISARegisters *id)
986 {
987     return FIELD_EX64_IDREG(id, ID_AA64SMFR0, I16I64) == 0xf;
988 }
989 
isar_feature_aa64_sme_fa64(const ARMISARegisters * id)990 static inline bool isar_feature_aa64_sme_fa64(const ARMISARegisters *id)
991 {
992     return FIELD_EX64_IDREG(id, ID_AA64SMFR0, FA64);
993 }
994 
995 /*
996  * Feature tests for "does this exist in either 32-bit or 64-bit?"
997  */
isar_feature_any_fp16(const ARMISARegisters * id)998 static inline bool isar_feature_any_fp16(const ARMISARegisters *id)
999 {
1000     return isar_feature_aa64_fp16(id) || isar_feature_aa32_fp16_arith(id);
1001 }
1002 
isar_feature_any_predinv(const ARMISARegisters * id)1003 static inline bool isar_feature_any_predinv(const ARMISARegisters *id)
1004 {
1005     return isar_feature_aa64_predinv(id) || isar_feature_aa32_predinv(id);
1006 }
1007 
isar_feature_any_pmuv3p1(const ARMISARegisters * id)1008 static inline bool isar_feature_any_pmuv3p1(const ARMISARegisters *id)
1009 {
1010     return isar_feature_aa64_pmuv3p1(id) || isar_feature_aa32_pmuv3p1(id);
1011 }
1012 
isar_feature_any_pmuv3p4(const ARMISARegisters * id)1013 static inline bool isar_feature_any_pmuv3p4(const ARMISARegisters *id)
1014 {
1015     return isar_feature_aa64_pmuv3p4(id) || isar_feature_aa32_pmuv3p4(id);
1016 }
1017 
isar_feature_any_pmuv3p5(const ARMISARegisters * id)1018 static inline bool isar_feature_any_pmuv3p5(const ARMISARegisters *id)
1019 {
1020     return isar_feature_aa64_pmuv3p5(id) || isar_feature_aa32_pmuv3p5(id);
1021 }
1022 
isar_feature_any_ccidx(const ARMISARegisters * id)1023 static inline bool isar_feature_any_ccidx(const ARMISARegisters *id)
1024 {
1025     return isar_feature_aa64_ccidx(id) || isar_feature_aa32_ccidx(id);
1026 }
1027 
isar_feature_any_tts2uxn(const ARMISARegisters * id)1028 static inline bool isar_feature_any_tts2uxn(const ARMISARegisters *id)
1029 {
1030     return isar_feature_aa64_tts2uxn(id) || isar_feature_aa32_tts2uxn(id);
1031 }
1032 
isar_feature_any_debugv8p2(const ARMISARegisters * id)1033 static inline bool isar_feature_any_debugv8p2(const ARMISARegisters *id)
1034 {
1035     return isar_feature_aa64_debugv8p2(id) || isar_feature_aa32_debugv8p2(id);
1036 }
1037 
isar_feature_any_ras(const ARMISARegisters * id)1038 static inline bool isar_feature_any_ras(const ARMISARegisters *id)
1039 {
1040     return isar_feature_aa64_ras(id) || isar_feature_aa32_ras(id);
1041 }
1042 
isar_feature_any_half_evt(const ARMISARegisters * id)1043 static inline bool isar_feature_any_half_evt(const ARMISARegisters *id)
1044 {
1045     return isar_feature_aa64_half_evt(id) || isar_feature_aa32_half_evt(id);
1046 }
1047 
isar_feature_any_evt(const ARMISARegisters * id)1048 static inline bool isar_feature_any_evt(const ARMISARegisters *id)
1049 {
1050     return isar_feature_aa64_evt(id) || isar_feature_aa32_evt(id);
1051 }
1052 
1053 typedef enum {
1054     CCSIDR_FORMAT_LEGACY,
1055     CCSIDR_FORMAT_CCIDX,
1056 } CCSIDRFormat;
1057 
make_ccsidr(CCSIDRFormat format,unsigned assoc,unsigned linesize,unsigned cachesize,uint8_t flags)1058 static inline uint64_t make_ccsidr(CCSIDRFormat format, unsigned assoc,
1059                                    unsigned linesize, unsigned cachesize,
1060                                    uint8_t flags)
1061 {
1062     unsigned lg_linesize = ctz32(linesize);
1063     unsigned sets;
1064     uint64_t ccsidr = 0;
1065 
1066     assert(assoc != 0);
1067     assert(is_power_of_2(linesize));
1068     assert(lg_linesize >= 4 && lg_linesize <= 7 + 4);
1069 
1070     /* sets * associativity * linesize == cachesize. */
1071     sets = cachesize / (assoc * linesize);
1072     assert(cachesize % (assoc * linesize) == 0);
1073 
1074     if (format == CCSIDR_FORMAT_LEGACY) {
1075         /*
1076          * The 32-bit CCSIDR format is:
1077          *   [27:13] number of sets - 1
1078          *   [12:3]  associativity - 1
1079          *   [2:0]   log2(linesize) - 4
1080          *           so 0 == 16 bytes, 1 == 32 bytes, 2 == 64 bytes, etc
1081          */
1082         ccsidr = deposit32(ccsidr, 28,  4, flags);
1083         ccsidr = deposit32(ccsidr, 13, 15, sets - 1);
1084         ccsidr = deposit32(ccsidr,  3, 10, assoc - 1);
1085         ccsidr = deposit32(ccsidr,  0,  3, lg_linesize - 4);
1086     } else {
1087         /*
1088          * The 64-bit CCSIDR_EL1 format is:
1089          *   [55:32] number of sets - 1
1090          *   [23:3]  associativity - 1
1091          *   [2:0]   log2(linesize) - 4
1092          *           so 0 == 16 bytes, 1 == 32 bytes, 2 == 64 bytes, etc
1093          */
1094         ccsidr = deposit64(ccsidr, 32, 24, sets - 1);
1095         ccsidr = deposit64(ccsidr,  3, 21, assoc - 1);
1096         ccsidr = deposit64(ccsidr,  0,  3, lg_linesize - 4);
1097     }
1098 
1099     return ccsidr;
1100 }
1101 
1102 /*
1103  * Forward to the above feature tests given an ARMCPU pointer.
1104  */
1105 #define cpu_isar_feature(name, cpu) \
1106     ({ ARMCPU *cpu_ = (cpu); isar_feature_##name(&cpu_->isar); })
1107 
1108 #endif
1109