mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-02 01:21:02 +00:00
target-sparc: Introduce cpu_raise_exception_ra
Several helpers call helper_raise_exception directly, which requires in turn that their callers have performed save_state. The new function allows a TCG return address to be passed in so that we can restore PC + NPC + flags data from that. This fixes a bug in the usage of helper_check_align, whose callers had not been calling save_state. It fixes another bug in which the divide helpers used GETPC at a level other than the direct callee from TCG. This allows the translator to avoid save_state prior to SAVE, RESTORE, and FLUSHW instructions. Backports commit 2f9d35fc4006122bad33f9ae3e2e51d2263e98ee from qemu
This commit is contained in:
parent
62ae2a5102
commit
9e60a8e432
|
@ -4366,6 +4366,7 @@ sparc_symbols = (
|
|||
'cpu_get_psr',
|
||||
'cpu_put_psr',
|
||||
'cpu_put_psr_raw',
|
||||
'cpu_raise_exception_ra',
|
||||
'cpu_set_cwp',
|
||||
'cpu_sparc_exec',
|
||||
'cpu_sparc_init',
|
||||
|
|
|
@ -3352,6 +3352,7 @@
|
|||
#define cpu_get_psr cpu_get_psr_sparc
|
||||
#define cpu_put_psr cpu_put_psr_sparc
|
||||
#define cpu_put_psr_raw cpu_put_psr_raw_sparc
|
||||
#define cpu_raise_exception_ra cpu_raise_exception_ra_sparc
|
||||
#define cpu_set_cwp cpu_set_cwp_sparc
|
||||
#define cpu_sparc_exec cpu_sparc_exec_sparc
|
||||
#define cpu_sparc_init cpu_sparc_init_sparc
|
||||
|
|
|
@ -3352,6 +3352,7 @@
|
|||
#define cpu_get_psr cpu_get_psr_sparc64
|
||||
#define cpu_put_psr cpu_put_psr_sparc64
|
||||
#define cpu_put_psr_raw cpu_put_psr_raw_sparc64
|
||||
#define cpu_raise_exception_ra cpu_raise_exception_ra_sparc64
|
||||
#define cpu_set_cwp cpu_set_cwp_sparc64
|
||||
#define cpu_sparc_exec cpu_sparc_exec_sparc64
|
||||
#define cpu_sparc_init cpu_sparc_init_sparc64
|
||||
|
|
|
@ -540,6 +540,7 @@ void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cpu, vaddr addr,
|
|||
MMUAccessType access_type,
|
||||
int mmu_idx,
|
||||
uintptr_t retaddr);
|
||||
void cpu_raise_exception_ra(CPUSPARCState *, int, uintptr_t) QEMU_NORETURN;
|
||||
|
||||
#ifndef NO_CPU_IO_DEFS
|
||||
/* cpu_init.c */
|
||||
|
|
|
@ -24,6 +24,14 @@
|
|||
#include "exec/helper-proto.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
void cpu_raise_exception_ra(CPUSPARCState *env, int tt, uintptr_t ra)
|
||||
{
|
||||
CPUState *cs = CPU(sparc_env_get_cpu(env));
|
||||
|
||||
cs->exception_index = tt;
|
||||
cpu_loop_exit_restore(cs, ra);
|
||||
}
|
||||
|
||||
void helper_raise_exception(CPUSPARCState *env, int tt)
|
||||
{
|
||||
CPUState *cs = CPU(sparc_env_get_cpu(env));
|
||||
|
@ -61,7 +69,7 @@ uint64_t helper_tick_get_count(CPUSPARCState *env, void *opaque, int mem_idx)
|
|||
CPUTimer *timer = opaque;
|
||||
|
||||
if (timer->npt && mem_idx < MMU_KERNEL_IDX) {
|
||||
helper_raise_exception(env, TT_PRIV_INSN);
|
||||
cpu_raise_exception_ra(env, TT_PRIV_INSN, GETPC());
|
||||
}
|
||||
|
||||
return cpu_tick_get_count(timer);*/
|
||||
|
@ -79,10 +87,9 @@ void helper_tick_set_limit(void *opaque, uint64_t limit)
|
|||
}
|
||||
#endif
|
||||
|
||||
static target_ulong helper_udiv_common(CPUSPARCState *env, target_ulong a,
|
||||
target_ulong b, int cc)
|
||||
static target_ulong do_udiv(CPUSPARCState *env, target_ulong a,
|
||||
target_ulong b, int cc, uintptr_t ra)
|
||||
{
|
||||
SPARCCPU *cpu = sparc_env_get_cpu(env);
|
||||
int overflow = 0;
|
||||
uint64_t x0;
|
||||
uint32_t x1;
|
||||
|
@ -91,8 +98,7 @@ static target_ulong helper_udiv_common(CPUSPARCState *env, target_ulong a,
|
|||
x1 = (b & 0xffffffff);
|
||||
|
||||
if (x1 == 0) {
|
||||
cpu_restore_state(CPU(cpu), GETPC());
|
||||
helper_raise_exception(env, TT_DIV_ZERO);
|
||||
cpu_raise_exception_ra(env, TT_DIV_ZERO, ra);
|
||||
}
|
||||
|
||||
x0 = x0 / x1;
|
||||
|
@ -111,18 +117,17 @@ static target_ulong helper_udiv_common(CPUSPARCState *env, target_ulong a,
|
|||
|
||||
target_ulong helper_udiv(CPUSPARCState *env, target_ulong a, target_ulong b)
|
||||
{
|
||||
return helper_udiv_common(env, a, b, 0);
|
||||
return do_udiv(env, a, b, 0, GETPC());
|
||||
}
|
||||
|
||||
target_ulong helper_udiv_cc(CPUSPARCState *env, target_ulong a, target_ulong b)
|
||||
{
|
||||
return helper_udiv_common(env, a, b, 1);
|
||||
return do_udiv(env, a, b, 1, GETPC());
|
||||
}
|
||||
|
||||
static target_ulong helper_sdiv_common(CPUSPARCState *env, target_ulong a,
|
||||
target_ulong b, int cc)
|
||||
static target_ulong do_sdiv(CPUSPARCState *env, target_ulong a,
|
||||
target_ulong b, int cc, uintptr_t ra)
|
||||
{
|
||||
SPARCCPU *cpu = sparc_env_get_cpu(env);
|
||||
int overflow = 0;
|
||||
int64_t x0;
|
||||
int32_t x1;
|
||||
|
@ -131,8 +136,7 @@ static target_ulong helper_sdiv_common(CPUSPARCState *env, target_ulong a,
|
|||
x1 = (b & 0xffffffff);
|
||||
|
||||
if (x1 == 0) {
|
||||
cpu_restore_state(CPU(cpu), GETPC());
|
||||
helper_raise_exception(env, TT_DIV_ZERO);
|
||||
cpu_raise_exception_ra(env, TT_DIV_ZERO, ra);
|
||||
} else if (x1 == -1 && x0 == INT64_MIN) {
|
||||
x0 = INT32_MAX;
|
||||
overflow = 1;
|
||||
|
@ -154,12 +158,12 @@ static target_ulong helper_sdiv_common(CPUSPARCState *env, target_ulong a,
|
|||
|
||||
target_ulong helper_sdiv(CPUSPARCState *env, target_ulong a, target_ulong b)
|
||||
{
|
||||
return helper_sdiv_common(env, a, b, 0);
|
||||
return do_sdiv(env, a, b, 0, GETPC());
|
||||
}
|
||||
|
||||
target_ulong helper_sdiv_cc(CPUSPARCState *env, target_ulong a, target_ulong b)
|
||||
{
|
||||
return helper_sdiv_common(env, a, b, 1);
|
||||
return do_sdiv(env, a, b, 1, GETPC());
|
||||
}
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
|
@ -167,10 +171,7 @@ int64_t helper_sdivx(CPUSPARCState *env, int64_t a, int64_t b)
|
|||
{
|
||||
if (b == 0) {
|
||||
/* Raise divide by zero trap. */
|
||||
SPARCCPU *cpu = sparc_env_get_cpu(env);
|
||||
|
||||
cpu_restore_state(CPU(cpu), GETPC());
|
||||
helper_raise_exception(env, TT_DIV_ZERO);
|
||||
cpu_raise_exception_ra(env, TT_DIV_ZERO, GETPC());
|
||||
} else if (b == -1) {
|
||||
/* Avoid overflow trap with i386 divide insn. */
|
||||
return -a;
|
||||
|
@ -183,10 +184,7 @@ uint64_t helper_udivx(CPUSPARCState *env, uint64_t a, uint64_t b)
|
|||
{
|
||||
if (b == 0) {
|
||||
/* Raise divide by zero trap. */
|
||||
SPARCCPU *cpu = sparc_env_get_cpu(env);
|
||||
|
||||
cpu_restore_state(CPU(cpu), GETPC());
|
||||
helper_raise_exception(env, TT_DIV_ZERO);
|
||||
cpu_raise_exception_ra(env, TT_DIV_ZERO, GETPC());
|
||||
}
|
||||
return a / b;
|
||||
}
|
||||
|
@ -195,7 +193,6 @@ uint64_t helper_udivx(CPUSPARCState *env, uint64_t a, uint64_t b)
|
|||
target_ulong helper_taddcctv(CPUSPARCState *env, target_ulong src1,
|
||||
target_ulong src2)
|
||||
{
|
||||
SPARCCPU *cpu = sparc_env_get_cpu(env);
|
||||
target_ulong dst;
|
||||
|
||||
/* Tag overflow occurs if either input has bits 0 or 1 set. */
|
||||
|
@ -218,14 +215,12 @@ target_ulong helper_taddcctv(CPUSPARCState *env, target_ulong src1,
|
|||
return dst;
|
||||
|
||||
tag_overflow:
|
||||
cpu_restore_state(CPU(cpu), GETPC());
|
||||
helper_raise_exception(env, TT_TOVF);
|
||||
cpu_raise_exception_ra(env, TT_TOVF, GETPC());
|
||||
}
|
||||
|
||||
target_ulong helper_tsubcctv(CPUSPARCState *env, target_ulong src1,
|
||||
target_ulong src2)
|
||||
{
|
||||
SPARCCPU *cpu = sparc_env_get_cpu(env);
|
||||
target_ulong dst;
|
||||
|
||||
/* Tag overflow occurs if either input has bits 0 or 1 set. */
|
||||
|
@ -248,8 +243,7 @@ target_ulong helper_tsubcctv(CPUSPARCState *env, target_ulong src1,
|
|||
return dst;
|
||||
|
||||
tag_overflow:
|
||||
cpu_restore_state(CPU(cpu), GETPC());
|
||||
helper_raise_exception(env, TT_TOVF);
|
||||
cpu_raise_exception_ra(env, TT_TOVF, GETPC());
|
||||
}
|
||||
|
||||
//#ifndef TARGET_SPARC64
|
||||
|
|
|
@ -254,17 +254,23 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
|
|||
|
||||
#endif
|
||||
|
||||
void helper_check_align(CPUSPARCState *env, target_ulong addr, uint32_t align)
|
||||
static void do_check_align(CPUSPARCState *env, target_ulong addr,
|
||||
uint32_t align, uintptr_t ra)
|
||||
{
|
||||
if (addr & align) {
|
||||
#ifdef DEBUG_UNALIGNED
|
||||
printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
|
||||
"\n", addr, env->pc);
|
||||
#endif
|
||||
helper_raise_exception(env, TT_UNALIGNED);
|
||||
cpu_raise_exception_ra(env, TT_UNALIGNED, ra);
|
||||
}
|
||||
}
|
||||
|
||||
void helper_check_align(CPUSPARCState *env, target_ulong addr, uint32_t align)
|
||||
{
|
||||
do_check_align(env, addr, align, GETPC());
|
||||
}
|
||||
|
||||
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY) && \
|
||||
defined(DEBUG_MXCC)
|
||||
static void dump_mxcc(CPUSPARCState *env)
|
||||
|
@ -393,7 +399,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr,
|
|||
uint32_t last_addr = addr;
|
||||
#endif
|
||||
|
||||
helper_check_align(env, addr, size - 1);
|
||||
do_check_align(env, addr, size - 1, GETPC());
|
||||
switch (asi) {
|
||||
case ASI_M_MXCC: /* SuperSparc MXCC registers, or... */
|
||||
/* case ASI_LEON_CACHEREGS: Leon3 cache control */
|
||||
|
@ -663,7 +669,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val,
|
|||
SPARCCPU *cpu = sparc_env_get_cpu(env);
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
helper_check_align(env, addr, size - 1);
|
||||
do_check_align(env, addr, size - 1, GETPC());
|
||||
switch (asi) {
|
||||
case ASI_M_MXCC: /* SuperSparc MXCC registers, or... */
|
||||
/* case ASI_LEON_CACHEREGS: Leon3 cache control */
|
||||
|
@ -1117,10 +1123,10 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr,
|
|||
#endif
|
||||
|
||||
if (asi < 0x80) {
|
||||
helper_raise_exception(env, TT_PRIV_ACT);
|
||||
cpu_raise_exception_ra(env, TT_PRIV_ACT, GETPC());
|
||||
}
|
||||
|
||||
helper_check_align(env, addr, size - 1);
|
||||
do_check_align(env, addr, size - 1, GETPC());
|
||||
addr = asi_address_mask(env, asi, addr);
|
||||
|
||||
switch (asi) {
|
||||
|
@ -1223,10 +1229,9 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
|
|||
dump_asi("write", addr, asi, size, val);
|
||||
#endif
|
||||
if (asi < 0x80) {
|
||||
helper_raise_exception(env, TT_PRIV_ACT);
|
||||
cpu_raise_exception_ra(env, TT_PRIV_ACT, GETPC());
|
||||
}
|
||||
|
||||
helper_check_align(env, addr, size - 1);
|
||||
do_check_align(env, addr, size - 1, GETPC());
|
||||
addr = asi_address_mask(env, asi, addr);
|
||||
|
||||
/* Convert to little endian */
|
||||
|
@ -1281,7 +1286,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
|
|||
case ASI_PNFL: /* Primary no-fault LE, RO */
|
||||
case ASI_SNFL: /* Secondary no-fault LE, RO */
|
||||
default:
|
||||
helper_raise_exception(env, TT_DATA_ACCESS);
|
||||
cpu_raise_exception_ra(env, TT_DATA_ACCESS, GETPC());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1305,10 +1310,10 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr,
|
|||
|| (cpu_has_hypervisor(env)
|
||||
&& asi >= 0x30 && asi < 0x80
|
||||
&& !(env->hpstate & HS_PRIV))) {
|
||||
helper_raise_exception(env, TT_PRIV_ACT);
|
||||
cpu_raise_exception_ra(env, TT_PRIV_ACT, GETPC());
|
||||
}
|
||||
|
||||
helper_check_align(env, addr, size - 1);
|
||||
do_check_align(env, addr, size - 1, GETPC());
|
||||
addr = asi_address_mask(env, asi, addr);
|
||||
|
||||
/* process nonfaulting loads first */
|
||||
|
@ -1327,7 +1332,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr,
|
|||
dump_asi("read ", last_addr, asi, size, ret);
|
||||
#endif
|
||||
/* env->exception_index is set in get_physical_address_data(). */
|
||||
helper_raise_exception(env, cs->exception_index);
|
||||
cpu_raise_exception_ra(env, cs->exception_index, GETPC());
|
||||
}
|
||||
|
||||
/* convert nonfaulting load ASIs to normal load ASIs */
|
||||
|
@ -1619,7 +1624,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr,
|
|||
case ASI_TWINX_S: /* Secondary, twinx */
|
||||
case ASI_TWINX_SL: /* Secondary, twinx, LE */
|
||||
/* These are all 128-bit atomic; only ldda (now ldtxa) allowed */
|
||||
helper_raise_exception(env, TT_ILL_INSN);
|
||||
cpu_raise_exception_ra(env, TT_ILL_INSN, GETPC());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1688,10 +1693,10 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
|
|||
|| (cpu_has_hypervisor(env)
|
||||
&& asi >= 0x30 && asi < 0x80
|
||||
&& !(env->hpstate & HS_PRIV))) {
|
||||
helper_raise_exception(env, TT_PRIV_ACT);
|
||||
cpu_raise_exception_ra(env, TT_PRIV_ACT, GETPC());
|
||||
}
|
||||
|
||||
helper_check_align(env, addr, size - 1);
|
||||
do_check_align(env, addr, size - 1, GETPC());
|
||||
addr = asi_address_mask(env, asi, addr);
|
||||
|
||||
/* Convert to little endian */
|
||||
|
@ -2037,7 +2042,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
|
|||
case ASI_TWINX_S: /* Secondary, twinx */
|
||||
case ASI_TWINX_SL: /* Secondary, twinx, LE */
|
||||
/* Only stda allowed */
|
||||
helper_raise_exception(env, TT_ILL_INSN);
|
||||
cpu_raise_exception_ra(env, TT_ILL_INSN, GETPC());
|
||||
return;
|
||||
case ASI_DCACHE_DATA: /* D-cache data */
|
||||
case ASI_DCACHE_TAG: /* D-cache tag access */
|
||||
|
@ -2081,7 +2086,7 @@ void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi)
|
|||
|| (cpu_has_hypervisor(env)
|
||||
&& asi >= 0x30 && asi < 0x80
|
||||
&& !(env->hpstate & HS_PRIV))) {
|
||||
helper_raise_exception(env, TT_PRIV_ACT);
|
||||
cpu_raise_exception_ra(env, TT_PRIV_ACT, GETPC());
|
||||
}
|
||||
|
||||
addr = asi_address_mask(env, asi, addr);
|
||||
|
@ -2090,19 +2095,19 @@ void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi)
|
|||
#if !defined(CONFIG_USER_ONLY)
|
||||
case ASI_TWINX_AIUP: /* As if user primary, twinx */
|
||||
case ASI_TWINX_AIUP_L: /* As if user primary, twinx, LE */
|
||||
helper_check_align(env, addr, 0xf);
|
||||
do_check_align(env, addr, 0xf, GETPC());
|
||||
h = cpu_ldq_user(env, addr);
|
||||
l = cpu_ldq_user(env, addr + 8);
|
||||
break;
|
||||
case ASI_TWINX_AIUS: /* As if user secondary, twinx */
|
||||
case ASI_TWINX_AIUS_L: /* As if user secondary, twinx, LE */
|
||||
helper_check_align(env, addr, 0xf);
|
||||
do_check_align(env, addr, 0xf, GETPC());
|
||||
h = cpu_ldq_user_secondary(env, addr);
|
||||
l = cpu_ldq_user_secondary(env, addr + 8);
|
||||
break;
|
||||
case ASI_TWINX_REAL: /* Real address, twinx */
|
||||
case ASI_TWINX_REAL_L: /* Real address, twinx, LE */
|
||||
helper_check_align(env, addr, 0xf);
|
||||
do_check_align(env, addr, 0xf, GETPC());
|
||||
{
|
||||
CPUState *cs = CPU(sparc_env_get_cpu(env));
|
||||
h = ldq_phys(cs->as, addr);
|
||||
|
@ -2113,14 +2118,14 @@ void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi)
|
|||
case ASI_NUCLEUS_QUAD_LDD_L:
|
||||
case ASI_TWINX_N: /* Nucleus, twinx */
|
||||
case ASI_TWINX_NL: /* Nucleus, twinx, LE */
|
||||
helper_check_align(env, addr, 0xf);
|
||||
do_check_align(env, addr, 0xf, GETPC());
|
||||
h = cpu_ldq_nucleus(env, addr);
|
||||
l = cpu_ldq_nucleus(env, addr + 8);
|
||||
break;
|
||||
case ASI_TWINX_S: /* Secondary, twinx */
|
||||
case ASI_TWINX_SL: /* Secondary, twinx, LE */
|
||||
if (!cpu_hypervisor_mode(env)) {
|
||||
helper_check_align(env, addr, 0xf);
|
||||
do_check_align(env, addr, 0xf, GETPC());
|
||||
if (env->pstate & PS_PRIV) {
|
||||
h = cpu_ldq_kernel_secondary(env, addr);
|
||||
l = cpu_ldq_kernel_secondary(env, addr + 8);
|
||||
|
@ -2133,7 +2138,7 @@ void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi)
|
|||
/* fallthru */
|
||||
case ASI_TWINX_P: /* Primary, twinx */
|
||||
case ASI_TWINX_PL: /* Primary, twinx, LE */
|
||||
helper_check_align(env, addr, 0xf);
|
||||
do_check_align(env, addr, 0xf, GETPC());
|
||||
h = cpu_ldq_data(env, addr);
|
||||
l = cpu_ldq_data(env, addr + 8);
|
||||
break;
|
||||
|
@ -2144,7 +2149,7 @@ void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi)
|
|||
case ASI_TWINX_SL: /* Primary, twinx, LE */
|
||||
/* ??? Should be available, but we need to implement
|
||||
an atomic 128-bit load. */
|
||||
helper_raise_exception(env, TT_PRIV_ACT);
|
||||
cpu_raise_exception_ra(env, TT_PRIV_ACT, GETPC());
|
||||
#endif
|
||||
default:
|
||||
/* Non-twinx asi, so this is the legacy ldda insn, which
|
||||
|
@ -2152,7 +2157,7 @@ void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi)
|
|||
/* ??? The UA2011 manual recommends emulating this with
|
||||
a single 64-bit load. However, LE asis *are* treated
|
||||
as two 32-bit loads individually byte swapped. */
|
||||
helper_check_align(env, addr, 0x7);
|
||||
do_check_align(env, addr, 7, GETPC());
|
||||
QT0.high = (uint32_t)helper_ld_asi(env, addr, asi, MO_UL);
|
||||
QT0.low = (uint32_t)helper_ld_asi(env, addr + 4, asi, MO_UL);
|
||||
return;
|
||||
|
@ -2202,7 +2207,7 @@ void helper_ldqf(CPUSPARCState *env, target_ulong addr, int mem_idx)
|
|||
/* XXX add 128 bit load */
|
||||
CPU_QuadU u;
|
||||
|
||||
helper_check_align(env, addr, 7);
|
||||
do_check_align(env, addr, 7, GETPC());
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
switch (mem_idx) {
|
||||
case MMU_USER_IDX:
|
||||
|
@ -2238,7 +2243,7 @@ void helper_stqf(CPUSPARCState *env, target_ulong addr, int mem_idx)
|
|||
/* XXX add 128 bit store */
|
||||
CPU_QuadU u;
|
||||
|
||||
helper_check_align(env, addr, 7);
|
||||
do_check_align(env, addr, 7, GETPC());
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
switch (mem_idx) {
|
||||
case MMU_USER_IDX:
|
||||
|
@ -2320,11 +2325,8 @@ void sparc_cpu_unassigned_access(CPUState *cs, hwaddr addr,
|
|||
}
|
||||
|
||||
if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
|
||||
if (is_exec) {
|
||||
helper_raise_exception(env, TT_CODE_ACCESS);
|
||||
} else {
|
||||
helper_raise_exception(env, TT_DATA_ACCESS);
|
||||
}
|
||||
int tt = is_exec ? TT_CODE_ACCESS : TT_DATA_ACCESS;
|
||||
cpu_raise_exception_ra(env, tt, GETPC());
|
||||
}
|
||||
|
||||
/* flush neverland mappings created during no-fault mode,
|
||||
|
@ -2340,17 +2342,14 @@ void sparc_cpu_unassigned_access(CPUState *cs, hwaddr addr,
|
|||
{
|
||||
SPARCCPU *cpu = SPARC_CPU(cs->uc, cs);
|
||||
CPUSPARCState *env = &cpu->env;
|
||||
int tt = is_exec ? TT_CODE_ACCESS : TT_DATA_ACCESS;
|
||||
|
||||
#ifdef DEBUG_UNASSIGNED
|
||||
printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
|
||||
"\n", addr, env->pc);
|
||||
#endif
|
||||
|
||||
if (is_exec) {
|
||||
helper_raise_exception(env, TT_CODE_ACCESS);
|
||||
} else {
|
||||
helper_raise_exception(env, TT_DATA_ACCESS);
|
||||
}
|
||||
cpu_raise_exception_ra(env, tt, GETPC());
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -2368,10 +2367,7 @@ void QEMU_NORETURN sparc_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
|
|||
printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
|
||||
"\n", addr, env->pc);
|
||||
#endif
|
||||
if (retaddr) {
|
||||
cpu_restore_state(CPU(cpu), retaddr);
|
||||
}
|
||||
helper_raise_exception(env, TT_UNALIGNED);
|
||||
cpu_raise_exception_ra(env, TT_UNALIGNED, retaddr);
|
||||
}
|
||||
|
||||
/* try to fill the TLB and return an exception if error. If retaddr is
|
||||
|
@ -2385,10 +2381,7 @@ void tlb_fill(CPUState *cs, target_ulong addr, MMUAccessType access_type,
|
|||
|
||||
ret = sparc_cpu_handle_mmu_fault(cs, addr, access_type, mmu_idx);
|
||||
if (ret) {
|
||||
if (retaddr) {
|
||||
cpu_restore_state(cs, retaddr);
|
||||
}
|
||||
cpu_loop_exit(cs);
|
||||
cpu_loop_exit_restore(cs, retaddr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -3637,7 +3637,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins
|
|||
break;
|
||||
} else if (xop == 0x2b) { /* rdtbr / V9 flushw */
|
||||
#ifdef TARGET_SPARC64
|
||||
save_state(dc);
|
||||
gen_helper_flushw(tcg_ctx, tcg_ctx->cpu_env);
|
||||
#else
|
||||
if (!supervisor(dc))
|
||||
|
@ -5241,12 +5240,10 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins
|
|||
/* nop */
|
||||
break;
|
||||
case 0x3c: /* save */
|
||||
save_state(dc);
|
||||
gen_helper_save(tcg_ctx, tcg_ctx->cpu_env);
|
||||
gen_store_gpr(dc, rd, cpu_tmp0);
|
||||
break;
|
||||
case 0x3d: /* restore */
|
||||
save_state(dc);
|
||||
gen_helper_restore(tcg_ctx, tcg_ctx->cpu_env);
|
||||
gen_store_gpr(dc, rd, cpu_tmp0);
|
||||
break;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "qemu/osdep.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
static inline void memcpy32(target_ulong *dst, const target_ulong *src)
|
||||
|
@ -112,13 +113,13 @@ void helper_rett(CPUSPARCState *env)
|
|||
unsigned int cwp;
|
||||
|
||||
if (env->psret == 1) {
|
||||
helper_raise_exception(env, TT_ILL_INSN);
|
||||
cpu_raise_exception_ra(env, TT_ILL_INSN, GETPC());
|
||||
}
|
||||
|
||||
env->psret = 1;
|
||||
cwp = cpu_cwp_inc(env, env->cwp + 1) ;
|
||||
if (env->wim & (1 << cwp)) {
|
||||
helper_raise_exception(env, TT_WIN_UNF);
|
||||
cpu_raise_exception_ra(env, TT_WIN_UNF, GETPC());
|
||||
}
|
||||
cpu_set_cwp(env, cwp);
|
||||
env->psrs = env->psrps;
|
||||
|
@ -132,7 +133,7 @@ void helper_save(CPUSPARCState *env)
|
|||
|
||||
cwp = cpu_cwp_dec(env, env->cwp - 1);
|
||||
if (env->wim & (1 << cwp)) {
|
||||
helper_raise_exception(env, TT_WIN_OVF);
|
||||
cpu_raise_exception_ra(env, TT_WIN_OVF, GETPC());
|
||||
}
|
||||
cpu_set_cwp(env, cwp);
|
||||
}
|
||||
|
@ -143,7 +144,7 @@ void helper_restore(CPUSPARCState *env)
|
|||
|
||||
cwp = cpu_cwp_inc(env, env->cwp + 1);
|
||||
if (env->wim & (1 << cwp)) {
|
||||
helper_raise_exception(env, TT_WIN_UNF);
|
||||
cpu_raise_exception_ra(env, TT_WIN_UNF, GETPC());
|
||||
}
|
||||
cpu_set_cwp(env, cwp);
|
||||
}
|
||||
|
@ -151,7 +152,7 @@ void helper_restore(CPUSPARCState *env)
|
|||
void helper_wrpsr(CPUSPARCState *env, target_ulong new_psr)
|
||||
{
|
||||
if ((new_psr & PSR_CWP) >= env->nwindows) {
|
||||
helper_raise_exception(env, TT_ILL_INSN);
|
||||
cpu_raise_exception_ra(env, TT_ILL_INSN, GETPC());
|
||||
} else {
|
||||
cpu_put_psr(env, new_psr);
|
||||
}
|
||||
|
@ -171,14 +172,14 @@ void helper_save(CPUSPARCState *env)
|
|||
|
||||
cwp = cpu_cwp_dec(env, env->cwp - 1);
|
||||
if (env->cansave == 0) {
|
||||
helper_raise_exception(env, TT_SPILL | (env->otherwin != 0 ?
|
||||
(TT_WOTHER |
|
||||
((env->wstate & 0x38) >> 1)) :
|
||||
((env->wstate & 0x7) << 2)));
|
||||
int tt = TT_SPILL | (env->otherwin != 0
|
||||
? (TT_WOTHER | ((env->wstate & 0x38) >> 1))
|
||||
: ((env->wstate & 0x7) << 2));
|
||||
cpu_raise_exception_ra(env, tt, GETPC());
|
||||
} else {
|
||||
if (env->cleanwin - env->canrestore == 0) {
|
||||
/* XXX Clean windows without trap */
|
||||
helper_raise_exception(env, TT_CLRWIN);
|
||||
cpu_raise_exception_ra(env, TT_CLRWIN, GETPC());
|
||||
} else {
|
||||
env->cansave--;
|
||||
env->canrestore++;
|
||||
|
@ -193,10 +194,10 @@ void helper_restore(CPUSPARCState *env)
|
|||
|
||||
cwp = cpu_cwp_inc(env, env->cwp + 1);
|
||||
if (env->canrestore == 0) {
|
||||
helper_raise_exception(env, TT_FILL | (env->otherwin != 0 ?
|
||||
(TT_WOTHER |
|
||||
((env->wstate & 0x38) >> 1)) :
|
||||
((env->wstate & 0x7) << 2)));
|
||||
int tt = TT_FILL | (env->otherwin != 0
|
||||
? (TT_WOTHER | ((env->wstate & 0x38) >> 1))
|
||||
: ((env->wstate & 0x7) << 2));
|
||||
cpu_raise_exception_ra(env, tt, GETPC());
|
||||
} else {
|
||||
env->cansave++;
|
||||
env->canrestore--;
|
||||
|
@ -207,10 +208,10 @@ void helper_restore(CPUSPARCState *env)
|
|||
void helper_flushw(CPUSPARCState *env)
|
||||
{
|
||||
if (env->cansave != env->nwindows - 2) {
|
||||
helper_raise_exception(env, TT_SPILL | (env->otherwin != 0 ?
|
||||
(TT_WOTHER |
|
||||
((env->wstate & 0x38) >> 1)) :
|
||||
((env->wstate & 0x7) << 2)));
|
||||
int tt = TT_SPILL | (env->otherwin != 0
|
||||
? (TT_WOTHER | ((env->wstate & 0x38) >> 1))
|
||||
: ((env->wstate & 0x7) << 2));
|
||||
cpu_raise_exception_ra(env, tt, GETPC());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue