aboutsummaryrefslogtreecommitdiff
path: root/target/arm/tcg/helper-a64.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/arm/tcg/helper-a64.c')
-rw-r--r--target/arm/tcg/helper-a64.c57
1 files changed, 27 insertions, 30 deletions
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
index 4f618ae..ba1d775 100644
--- a/target/arm/tcg/helper-a64.c
+++ b/target/arm/tcg/helper-a64.c
@@ -402,6 +402,8 @@ AH_MINMAX_HELPER(vfp_ah_mind, float64, float64, min)
AH_MINMAX_HELPER(vfp_ah_maxh, dh_ctype_f16, float16, max)
AH_MINMAX_HELPER(vfp_ah_maxs, float32, float32, max)
AH_MINMAX_HELPER(vfp_ah_maxd, float64, float64, max)
+AH_MINMAX_HELPER(sme2_ah_fmax_b16, bfloat16, bfloat16, max)
+AH_MINMAX_HELPER(sme2_ah_fmin_b16, bfloat16, bfloat16, min)
/* 64-bit versions of the CRC helpers. Note that although the operation
* (and the prototypes of crc32c() and crc32() mean that only the bottom
@@ -574,6 +576,7 @@ uint32_t HELPER(advsimd_rinth)(uint32_t x, float_status *fp_status)
return ret;
}
+#ifndef CONFIG_USER_ONLY
static int el_from_spsr(uint32_t spsr)
{
/* Return the exception level that this SPSR is requesting a return to,
@@ -612,32 +615,12 @@ static int el_from_spsr(uint32_t spsr)
}
}
-static void cpsr_write_from_spsr_elx(CPUARMState *env,
- uint32_t val)
-{
- uint32_t mask;
-
- /* Save SPSR_ELx.SS into PSTATE. */
- env->pstate = (env->pstate & ~PSTATE_SS) | (val & PSTATE_SS);
- val &= ~PSTATE_SS;
-
- /* Move DIT to the correct location for CPSR */
- if (val & PSTATE_DIT) {
- val &= ~PSTATE_DIT;
- val |= CPSR_DIT;
- }
-
- mask = aarch32_cpsr_valid_mask(env->features, \
- &env_archcpu(env)->isar);
- cpsr_write(env, val, mask, CPSRWriteRaw);
-}
-
void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
{
ARMCPU *cpu = env_archcpu(env);
int cur_el = arm_current_el(env);
unsigned int spsr_idx = aarch64_banked_spsr_index(cur_el);
- uint32_t spsr = env->banked_spsr[spsr_idx];
+ uint64_t spsr = env->banked_spsr[spsr_idx];
int new_el;
bool return_to_aa64 = (spsr & PSTATE_nRW) == 0;
@@ -656,15 +639,6 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
spsr &= ~PSTATE_SS;
}
- /*
- * FEAT_RME forbids return from EL3 with an invalid security state.
- * We don't need an explicit check for FEAT_RME here because we enforce
- * in scr_write() that you can't set the NSE bit without it.
- */
- if (cur_el == 3 && (env->cp15.scr_el3 & (SCR_NS | SCR_NSE)) == SCR_NSE) {
- goto illegal_return;
- }
-
new_el = el_from_spsr(spsr);
if (new_el == -1) {
goto illegal_return;
@@ -676,6 +650,17 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
goto illegal_return;
}
+ /*
+ * FEAT_RME forbids return from EL3 to a lower exception level
+ * with an invalid security state.
+ * We don't need an explicit check for FEAT_RME here because we enforce
+ * in scr_write() that you can't set the NSE bit without it.
+ */
+ if (cur_el == 3 && new_el < 3 &&
+ (env->cp15.scr_el3 & (SCR_NS | SCR_NSE)) == SCR_NSE) {
+ goto illegal_return;
+ }
+
if (new_el != 0 && arm_el_is_aa64(env, new_el) != return_to_aa64) {
/* Return to an EL which is configured for a different register width */
goto illegal_return;
@@ -690,6 +675,17 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
goto illegal_return;
}
+ /*
+ * If GetCurrentEXLOCKEN, the exception return path must use GCSPOPCX,
+ * which will set PSTATE.EXLOCK. We need not explicitly check FEAT_GCS,
+ * because GCSCR_ELx cannot be set without it.
+ */
+ if (new_el == cur_el &&
+ (env->cp15.gcscr_el[cur_el] & GCSCR_EXLOCKEN) &&
+ !(env->pstate & PSTATE_EXLOCK)) {
+ goto illegal_return;
+ }
+
bql_lock();
arm_call_pre_el_change_hook(cpu);
bql_unlock();
@@ -783,6 +779,7 @@ illegal_return:
qemu_log_mask(LOG_GUEST_ERROR, "Illegal exception return at EL%d: "
"resuming execution at 0x%" PRIx64 "\n", cur_el, env->pc);
}
+#endif /* !CONFIG_USER_ONLY */
void HELPER(dc_zva)(CPUARMState *env, uint64_t vaddr_in)
{