#include "exec/helper-proto.h"
#include "qemu/host-utils.h"
#include "qemu/log.h"
+#include "qemu/main-loop.h"
#include "sysemu/sysemu.h"
#include "qemu/bitops.h"
#include "internals.h"
return revbit64(x);
}
+void HELPER(msr_i_spsel)(CPUARMState *env, uint32_t imm)
+{
+ update_spsel(env, imm);
+}
+
+static void daif_check(CPUARMState *env, uint32_t op,
+ uint32_t imm, uintptr_t ra)
+{
+ /* DAIF update to PSTATE. This is OK from EL0 only if UMA is set. */
+ if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
+ raise_exception_ra(env, EXCP_UDEF,
+ syn_aa64_sysregtrap(0, extract32(op, 0, 3),
+ extract32(op, 3, 3), 4,
+ imm, 0x1f, 0),
+ exception_target_el(env), ra);
+ }
+}
+
+void HELPER(msr_i_daifset)(CPUARMState *env, uint32_t imm)
+{
+ daif_check(env, 0x1e, imm, GETPC());
+ env->daif |= (imm << 6) & PSTATE_DAIF;
+}
+
+void HELPER(msr_i_daifclear)(CPUARMState *env, uint32_t imm)
+{
+ daif_check(env, 0x1f, imm, GETPC());
+ env->daif &= ~((imm << 6) & PSTATE_DAIF);
+}
+
/* Convert a softfloat float_relation_ (as returned by
* the float*_compare functions) to the correct ARM
* NZCV flag state.
/* ??? Enforce alignment. */
uint64_t *haddr = g2h(addr);
- helper_retaddr = ra;
+ set_helper_retaddr(ra);
o0 = ldq_le_p(haddr + 0);
o1 = ldq_le_p(haddr + 1);
oldv = int128_make128(o0, o1);
stq_le_p(haddr + 0, int128_getlo(newv));
stq_le_p(haddr + 1, int128_gethi(newv));
}
- helper_retaddr = 0;
+ clear_helper_retaddr();
#else
int mem_idx = cpu_mmu_index(env, false);
TCGMemOpIdx oi0 = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
* High and low need to be switched here because this is not actually a
* 128bit store but two doublewords stored consecutively
*/
- Int128 cmpv = int128_make128(env->exclusive_val, env->exclusive_high);
- Int128 newv = int128_make128(new_lo, new_hi);
+ Int128 cmpv = int128_make128(env->exclusive_high, env->exclusive_val);
+ Int128 newv = int128_make128(new_hi, new_lo);
Int128 oldv;
uintptr_t ra = GETPC();
uint64_t o0, o1;
/* ??? Enforce alignment. */
uint64_t *haddr = g2h(addr);
- helper_retaddr = ra;
+ set_helper_retaddr(ra);
o1 = ldq_be_p(haddr + 0);
o0 = ldq_be_p(haddr + 1);
oldv = int128_make128(o0, o1);
stq_be_p(haddr + 0, int128_gethi(newv));
stq_be_p(haddr + 1, int128_getlo(newv));
}
- helper_retaddr = 0;
+ clear_helper_retaddr();
#else
int mem_idx = cpu_mmu_index(env, false);
TCGMemOpIdx oi0 = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
}
}
-void HELPER(exception_return)(CPUARMState *env)
+void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
{
int cur_el = arm_current_el(env);
unsigned int spsr_idx = aarch64_banked_spsr_index(cur_el);
}
qemu_mutex_lock_iothread();
- arm_call_pre_el_change_hook(arm_env_get_cpu(env));
+ arm_call_pre_el_change_hook(env_archcpu(env));
qemu_mutex_unlock_iothread();
if (!return_to_aa64) {
aarch64_sync_64_to_32(env);
if (spsr & CPSR_T) {
- env->regs[15] = env->elr_el[cur_el] & ~0x1;
+ env->regs[15] = new_pc & ~0x1;
} else {
- env->regs[15] = env->elr_el[cur_el] & ~0x3;
+ env->regs[15] = new_pc & ~0x3;
}
qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
"AArch32 EL%d PC 0x%" PRIx32 "\n",
env->pstate &= ~PSTATE_SS;
}
aarch64_restore_sp(env, new_el);
- env->pc = env->elr_el[cur_el];
+ env->pc = new_pc;
qemu_log_mask(CPU_LOG_INT, "Exception return from AArch64 EL%d to "
"AArch64 EL%d PC 0x%" PRIx64 "\n",
cur_el, new_el, env->pc);
aarch64_sve_change_el(env, cur_el, new_el, return_to_aa64);
qemu_mutex_lock_iothread();
- arm_call_el_change_hook(arm_env_get_cpu(env));
+ arm_call_el_change_hook(env_archcpu(env));
qemu_mutex_unlock_iothread();
return;
* no change to exception level, execution state or stack pointer
*/
env->pstate |= PSTATE_IL;
- env->pc = env->elr_el[cur_el];
+ env->pc = new_pc;
spsr &= PSTATE_NZCV | PSTATE_DAIF;
spsr |= pstate_read(env) & ~(PSTATE_NZCV | PSTATE_DAIF);
pstate_write(env, spsr);