target/arm: Add FPMR_EL to TBFLAGS
Prepare to perform access checks for direct and indirect uses of FPMR. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260522220306.235200-13-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Richard Henderson committed
May 22, 2026 at 15:02 UTC
cc04352a1f100c64d0a467bc678cae16713da4b8
4 files changed
+46
target/arm/cpu.h
+1
@@ -2567,6 +2567,7 @@ FIELD(TBFLAG_A64, ZT0EXC_EL, 39, 2)
2567
FIELD(TBFLAG_A64, GCS_EN, 41, 1)
2568
FIELD(TBFLAG_A64, GCS_RVCEN, 42, 1)
2569
FIELD(TBFLAG_A64, GCSSTR_EL, 43, 2)
2570
+FIELD(TBFLAG_A64, FPMR_EL, 45, 2)
2571
2572
/*
2573
* Helpers for using the above. Note that only the A64 accessors use
target/arm/tcg/hflags.c
+42
@@ -237,6 +237,44 @@ static int zt0_exception_el(CPUARMState *env, int el)
237
return 0;
238
}
239
240
+/*
241
+ * Return the exception level to which exceptions should be taken for FPMR.
242
+ * Compare the EnFPM bits in the "Accessing FPMR" pseudocode. Note that
243
+ * the floating-point enabled check will be handled separately.
244
+ */
245
+static int fpmr_exception_el(CPUARMState *env, int el)
246
+{
247
+ switch (el) {
248
+ case 0:
249
+ if (el_is_in_host(env, 0)) {
250
+ if (!(env->cp15.sctlr_el[2] & SCTLR_EnFPM)) {
251
+ return 2;
252
+ }
253
+ break;
254
+ }
255
+ if (!(env->cp15.sctlr_el[1] & SCTLR_EnFPM)) {
256
+ return 1;
257
+ }
258
+ /* fall through */
259
+ case 1:
260
+ if (!(arm_hcrx_el2_eff(env) & HCRX_ENFPM)) {
261
+ return 2;
262
+ }
263
+ break;
264
+ case 2:
265
+ break;
266
+ case 3:
267
+ return 0;
268
+ default:
269
+ g_assert_not_reached();
270
+ }
271
+ if (arm_feature(env, ARM_FEATURE_EL3)
272
+ && !(env->cp15.scr_el3 & SCR_ENFPM)) {
273
+ return 3;
274
+ }
275
+ return 0;
276
+}
277
+
278
static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
279
ARMMMUIdx mmu_idx)
280
{
@@ -500,6 +538,10 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
538
}
539
}
540
541
+ if (cpu_isar_feature(aa64_fpmr, env_archcpu(env))) {
542
+ DP_TBFLAG_A64(flags, FPMR_EL, fpmr_exception_el(env, el));
543
+ }
544
+
545
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
546
}
547
target/arm/tcg/translate-a64.c
+1
@@ -10723,6 +10723,7 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
10723
dc->gcs_en = EX_TBFLAG_A64(tb_flags, GCS_EN);
10724
dc->gcs_rvcen = EX_TBFLAG_A64(tb_flags, GCS_RVCEN);
10725
dc->gcsstr_el = EX_TBFLAG_A64(tb_flags, GCSSTR_EL);
10726
+ dc->fpmr_el = EX_TBFLAG_A64(tb_flags, FPMR_EL);
10727
dc->vec_len = 0;
10728
dc->vec_stride = 0;
10729
dc->cp_regs = arm_cpu->cp_regs;
target/arm/tcg/translate.h
+2
@@ -199,6 +199,8 @@ typedef struct DisasContext {
199
uint8_t gm_blocksize;
200
/* True if the current insn_start has been updated. */
201
bool insn_start_updated;
202
+ /* FPMR access exception EL or 0 if enabled. */
203
+ uint8_t fpmr_el;
204
/* Offset from VNCR_EL2 when FEAT_NV2 redirects this reg to memory */
205
uint32_t nv2_redirect_offset;
206
} DisasContext;