提交 bf99fd39 编写于 作者: P Peter Maydell

Merge remote-tracking branch 'remotes/rth/tags/pull-sparc-20161031-2' into staging

target-sparc updates for atomics and alignment

# gpg: Signature made Mon 31 Oct 2016 20:47:57 GMT
# gpg:                using RSA key 0xAD1270CC4DD0279B
# gpg: Good signature from "Richard Henderson <rth7680@gmail.com>"
# gpg:                 aka "Richard Henderson <rth@redhat.com>"
# gpg:                 aka "Richard Henderson <rth@twiddle.net>"
# Primary key fingerprint: 9CB1 8DDA F8E8 49AD 2AFC  16A4 AD12 70CC 4DD0 279B

* remotes/rth/tags/pull-sparc-20161031-2:
  target-sparc: Use tcg_gen_atomic_cmpxchg_tl
  target-sparc: Use tcg_gen_atomic_xchg_tl
  target-sparc: Remove MMU_MODE*_SUFFIX
  target-sparc: Allow 4-byte alignment on fp mem ops
  target-sparc: Implement ldqf and stqf inline
  target-sparc: Remove asi helper code handled inline
  target-sparc: Implement BCOPY/BFILL inline
  target-sparc: Implement cas_asi/casx_asi inline
  target-sparc: Implement ldstub_asi inline
  target-sparc: Implement swap_asi inline
  target-sparc: Handle more twinx asis
  target-sparc: Use MMU_PHYS_IDX for bypass asis
  target-sparc: Add MMU_PHYS_IDX
  target-sparc: Introduce cpu_raise_exception_ra
  target-sparc: Use overalignment flags for twinx and block asis
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
......@@ -225,9 +225,9 @@ enum {
#define MAX_NWINDOWS 32
#if !defined(TARGET_SPARC64)
#define NB_MMU_MODES 2
#define NB_MMU_MODES 3
#else
#define NB_MMU_MODES 6
#define NB_MMU_MODES 7
typedef struct trap_state {
uint64_t tpc;
uint64_t tnpc;
......@@ -549,6 +549,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 */
......@@ -637,22 +638,16 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
/* MMU modes definitions */
#if defined (TARGET_SPARC64)
#define MMU_USER_IDX 0
#define MMU_MODE0_SUFFIX _user
#define MMU_USER_SECONDARY_IDX 1
#define MMU_MODE1_SUFFIX _user_secondary
#define MMU_KERNEL_IDX 2
#define MMU_MODE2_SUFFIX _kernel
#define MMU_KERNEL_SECONDARY_IDX 3
#define MMU_MODE3_SUFFIX _kernel_secondary
#define MMU_NUCLEUS_IDX 4
#define MMU_MODE4_SUFFIX _nucleus
#define MMU_HYPV_IDX 5
#define MMU_MODE5_SUFFIX _hypv
#define MMU_PHYS_IDX 6
#else
#define MMU_USER_IDX 0
#define MMU_MODE0_SUFFIX _user
#define MMU_KERNEL_IDX 1
#define MMU_MODE1_SUFFIX _kernel
#define MMU_PHYS_IDX 2
#endif
#if defined (TARGET_SPARC64)
......@@ -672,18 +667,27 @@ static inline int cpu_supervisor_mode(CPUSPARCState *env1)
}
#endif
static inline int cpu_mmu_index(CPUSPARCState *env1, bool ifetch)
static inline int cpu_mmu_index(CPUSPARCState *env, bool ifetch)
{
#if defined(CONFIG_USER_ONLY)
return MMU_USER_IDX;
#elif !defined(TARGET_SPARC64)
return env1->psrs;
if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
return MMU_PHYS_IDX;
} else {
return env->psrs;
}
#else
if (env1->tl > 0) {
/* IMMU or DMMU disabled. */
if (ifetch
? (env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0
: (env->lsu & DMMU_E) == 0) {
return MMU_PHYS_IDX;
} else if (env->tl > 0) {
return MMU_NUCLEUS_IDX;
} else if (cpu_hypervisor_mode(env1)) {
} else if (cpu_hypervisor_mode(env)) {
return MMU_HYPV_IDX;
} else if (cpu_supervisor_mode(env1)) {
} else if (cpu_supervisor_mode(env)) {
return MMU_KERNEL_IDX;
} else {
return MMU_USER_IDX;
......
......@@ -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));
......@@ -59,7 +67,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);
......@@ -76,10 +84,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;
......@@ -88,8 +95,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;
......@@ -108,18 +114,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;
......@@ -128,8 +133,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;
......@@ -151,12 +155,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
......@@ -164,10 +168,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;
......@@ -180,10 +181,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;
}
......@@ -192,7 +190,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. */
......@@ -215,14 +212,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. */
......@@ -245,8 +240,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
......
......@@ -17,8 +17,6 @@ DEF_HELPER_1(rdcwp, tl, env)
DEF_HELPER_2(wrcwp, void, env, tl)
DEF_HELPER_FLAGS_2(array8, TCG_CALL_NO_RWG_SE, tl, tl, tl)
DEF_HELPER_FLAGS_1(popc, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_3(ldda_asi, TCG_CALL_NO_WG, void, env, tl, int)
DEF_HELPER_FLAGS_5(casx_asi, TCG_CALL_NO_WG, tl, env, tl, tl, tl, i32)
DEF_HELPER_FLAGS_2(set_softint, TCG_CALL_NO_RWG, void, env, i64)
DEF_HELPER_FLAGS_2(clear_softint, TCG_CALL_NO_RWG, void, env, i64)
DEF_HELPER_FLAGS_2(write_softint, TCG_CALL_NO_RWG, void, env, i64)
......@@ -26,9 +24,6 @@ DEF_HELPER_FLAGS_2(tick_set_count, TCG_CALL_NO_RWG, void, ptr, i64)
DEF_HELPER_FLAGS_3(tick_get_count, TCG_CALL_NO_WG, i64, env, ptr, int)
DEF_HELPER_FLAGS_2(tick_set_limit, TCG_CALL_NO_RWG, void, ptr, i64)
#endif
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
DEF_HELPER_FLAGS_5(cas_asi, TCG_CALL_NO_WG, tl, env, tl, tl, tl, i32)
#endif
DEF_HELPER_FLAGS_3(check_align, TCG_CALL_NO_WG, void, env, tl, i32)
DEF_HELPER_1(debug, void, env)
DEF_HELPER_1(save, void, env)
......@@ -43,8 +38,6 @@ DEF_HELPER_3(tsubcctv, tl, env, tl, tl)
DEF_HELPER_FLAGS_3(sdivx, TCG_CALL_NO_WG, s64, env, s64, s64)
DEF_HELPER_FLAGS_3(udivx, TCG_CALL_NO_WG, i64, env, i64, i64)
#endif
DEF_HELPER_FLAGS_3(ldqf, TCG_CALL_NO_WG, void, env, tl, int)
DEF_HELPER_FLAGS_3(stqf, TCG_CALL_NO_WG, void, env, tl, int)
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
DEF_HELPER_FLAGS_4(ld_asi, TCG_CALL_NO_WG, i64, env, tl, int, i32)
DEF_HELPER_FLAGS_5(st_asi, TCG_CALL_NO_WG, void, env, tl, i64, int, i32)
......
此差异已折叠。
......@@ -92,7 +92,7 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
is_user = mmu_idx == MMU_USER_IDX;
if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
if (mmu_idx == MMU_PHYS_IDX) {
*page_size = TARGET_PAGE_SIZE;
/* Boot mode: instruction fetches are taken from PROM */
if (rw == 2 && (env->mmuregs[0] & env->def->mmu_bm)) {
......@@ -494,23 +494,21 @@ static int get_physical_address_data(CPUSPARCState *env,
unsigned int i;
uint64_t context;
uint64_t sfsr = 0;
int is_user = (mmu_idx == MMU_USER_IDX ||
mmu_idx == MMU_USER_SECONDARY_IDX);
if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */
*physical = ultrasparc_truncate_physical(address);
*prot = PAGE_READ | PAGE_WRITE;
return 0;
}
bool is_user = false;
switch (mmu_idx) {
case MMU_PHYS_IDX:
g_assert_not_reached();
case MMU_USER_IDX:
is_user = true;
/* fallthru */
case MMU_KERNEL_IDX:
context = env->dmmu.mmu_primary_context & 0x1fff;
sfsr |= SFSR_CT_PRIMARY;
break;
case MMU_USER_SECONDARY_IDX:
is_user = true;
/* fallthru */
case MMU_KERNEL_SECONDARY_IDX:
context = env->dmmu.mmu_secondary_context & 0x1fff;
sfsr |= SFSR_CT_SECONDARY;
......@@ -613,15 +611,22 @@ static int get_physical_address_code(CPUSPARCState *env,
CPUState *cs = CPU(sparc_env_get_cpu(env));
unsigned int i;
uint64_t context;
bool is_user = false;
int is_user = (mmu_idx == MMU_USER_IDX ||
mmu_idx == MMU_USER_SECONDARY_IDX);
if ((env->lsu & IMMU_E) == 0 || (env->pstate & PS_RED) != 0) {
/* IMMU disabled */
*physical = ultrasparc_truncate_physical(address);
*prot = PAGE_EXEC;
return 0;
switch (mmu_idx) {
case MMU_PHYS_IDX:
case MMU_USER_SECONDARY_IDX:
case MMU_KERNEL_SECONDARY_IDX:
g_assert_not_reached();
case MMU_USER_IDX:
is_user = true;
/* fallthru */
case MMU_KERNEL_IDX:
context = env->dmmu.mmu_primary_context & 0x1fff;
break;
default:
context = 0;
break;
}
if (env->tl == 0) {
......@@ -700,6 +705,12 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
}
}
if (mmu_idx == MMU_PHYS_IDX) {
*physical = ultrasparc_truncate_physical(address);
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
return 0;
}
if (rw == 2) {
return get_physical_address_code(env, physical, prot, address,
mmu_idx);
......
此差异已折叠。
......@@ -19,6 +19,7 @@
#include "qemu/osdep.h"
#include "cpu.h"
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
#include "trace.h"
......@@ -111,13 +112,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;
......@@ -131,7 +132,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);
}
......@@ -142,7 +143,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);
}
......@@ -150,7 +151,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);
}
......@@ -170,14 +171,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++;
......@@ -192,10 +193,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--;
......@@ -206,10 +207,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());
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册