summaryrefslogtreecommitdiffstats
path: root/target-sparc
diff options
context:
space:
mode:
Diffstat (limited to 'target-sparc')
-rw-r--r--target-sparc/cpu-qom.h75
-rw-r--r--target-sparc/cpu.c (renamed from target-sparc/cpu_init.c)69
-rw-r--r--target-sparc/cpu.h13
-rw-r--r--target-sparc/helper.h22
-rw-r--r--target-sparc/ldst_helper.c433
-rw-r--r--target-sparc/mmu_helper.c19
-rw-r--r--target-sparc/op_helper.c74
-rw-r--r--target-sparc/translate.c62
8 files changed, 439 insertions, 328 deletions
diff --git a/target-sparc/cpu-qom.h b/target-sparc/cpu-qom.h
new file mode 100644
index 0000000000..3d3ac0fcef
--- /dev/null
+++ b/target-sparc/cpu-qom.h
@@ -0,0 +1,75 @@
+/*
+ * QEMU SPARC CPU
+ *
+ * Copyright (c) 2012 SUSE LINUX Products GmbH
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/lgpl-2.1.html>
+ */
+#ifndef QEMU_SPARC_CPU_QOM_H
+#define QEMU_SPARC_CPU_QOM_H
+
+#include "qemu/cpu.h"
+#include "cpu.h"
+
+#ifdef TARGET_SPARC64
+#define TYPE_SPARC_CPU "sparc64-cpu"
+#else
+#define TYPE_SPARC_CPU "sparc-cpu"
+#endif
+
+#define SPARC_CPU_CLASS(klass) \
+ OBJECT_CLASS_CHECK(SPARCCPUClass, (klass), TYPE_SPARC_CPU)
+#define SPARC_CPU(obj) \
+ OBJECT_CHECK(SPARCCPU, (obj), TYPE_SPARC_CPU)
+#define SPARC_CPU_GET_CLASS(obj) \
+ OBJECT_GET_CLASS(SPARCCPUClass, (obj), TYPE_SPARC_CPU)
+
+/**
+ * SPARCCPUClass:
+ * @parent_reset: The parent class' reset handler.
+ *
+ * A SPARC CPU model.
+ */
+typedef struct SPARCCPUClass {
+ /*< private >*/
+ CPUClass parent_class;
+ /*< public >*/
+
+ void (*parent_reset)(CPUState *cpu);
+} SPARCCPUClass;
+
+/**
+ * SPARCCPU:
+ * @env: #CPUSPARCState
+ *
+ * A SPARC CPU.
+ */
+typedef struct SPARCCPU {
+ /*< private >*/
+ CPUState parent_obj;
+ /*< public >*/
+
+ CPUSPARCState env;
+} SPARCCPU;
+
+static inline SPARCCPU *sparc_env_get_cpu(CPUSPARCState *env)
+{
+ return SPARC_CPU(container_of(env, SPARCCPU, env));
+}
+
+#define ENV_GET_CPU(e) CPU(sparc_env_get_cpu(e))
+
+
+#endif
diff --git a/target-sparc/cpu_init.c b/target-sparc/cpu.c
index 29132fb995..24f90f1ded 100644
--- a/target-sparc/cpu_init.c
+++ b/target-sparc/cpu.c
@@ -25,11 +25,24 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
void cpu_state_reset(CPUSPARCState *env)
{
+ cpu_reset(ENV_GET_CPU(env));
+}
+
+/* CPUClass::reset() */
+static void sparc_cpu_reset(CPUState *s)
+{
+ SPARCCPU *cpu = SPARC_CPU(s);
+ SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(cpu);
+ CPUSPARCState *env = &cpu->env;
+
if (qemu_loglevel_mask(CPU_LOG_RESET)) {
qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
log_cpu_state(env, 0);
}
+ scc->parent_reset(s);
+
+ memset(env, 0, offsetof(CPUSPARCState, breakpoints));
tlb_flush(env, 1);
env->cwp = 0;
#ifndef TARGET_SPARC64
@@ -98,23 +111,18 @@ static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
return 0;
}
-static void cpu_sparc_close(CPUSPARCState *env)
-{
- g_free(env->def);
- g_free(env);
-}
-
CPUSPARCState *cpu_sparc_init(const char *cpu_model)
{
+ SPARCCPU *cpu;
CPUSPARCState *env;
- env = g_new0(CPUSPARCState, 1);
- cpu_exec_init(env);
+ cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));
+ env = &cpu->env;
gen_intermediate_code_init(env);
if (cpu_sparc_register(env, cpu_model) < 0) {
- cpu_sparc_close(env);
+ object_delete(OBJECT(cpu));
return NULL;
}
qemu_init_vcpu(env);
@@ -846,3 +854,46 @@ void cpu_dump_state(CPUSPARCState *env, FILE *f, fprintf_function cpu_fprintf,
env->fsr, env->y);
#endif
}
+
+static void sparc_cpu_initfn(Object *obj)
+{
+ SPARCCPU *cpu = SPARC_CPU(obj);
+ CPUSPARCState *env = &cpu->env;
+
+ cpu_exec_init(env);
+}
+
+static void sparc_cpu_uninitfn(Object *obj)
+{
+ SPARCCPU *cpu = SPARC_CPU(obj);
+ CPUSPARCState *env = &cpu->env;
+
+ g_free(env->def);
+}
+
+static void sparc_cpu_class_init(ObjectClass *oc, void *data)
+{
+ SPARCCPUClass *scc = SPARC_CPU_CLASS(oc);
+ CPUClass *cc = CPU_CLASS(oc);
+
+ scc->parent_reset = cc->reset;
+ cc->reset = sparc_cpu_reset;
+}
+
+static const TypeInfo sparc_cpu_type_info = {
+ .name = TYPE_SPARC_CPU,
+ .parent = TYPE_CPU,
+ .instance_size = sizeof(SPARCCPU),
+ .instance_init = sparc_cpu_initfn,
+ .instance_finalize = sparc_cpu_uninitfn,
+ .abstract = false,
+ .class_size = sizeof(SPARCCPUClass),
+ .class_init = sparc_cpu_class_init,
+};
+
+static void sparc_cpu_register_types(void)
+{
+ type_register_static(&sparc_cpu_type_info);
+}
+
+type_init(sparc_cpu_register_types)
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 86f9de6cfe..865288cc94 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -415,14 +415,15 @@ struct CPUSPARCState {
#if !defined(TARGET_SPARC64)
int psref; /* enable fpu */
#endif
- target_ulong version;
int interrupt_index;
- uint32_t nwindows;
/* NOTE: we allow 8 more registers to handle wrapping */
target_ulong regbase[MAX_NWINDOWS * 16 + 8];
CPU_COMMON
+ target_ulong version;
+ uint32_t nwindows;
+
/* MMU regs */
#if defined(TARGET_SPARC64)
uint64_t lsu;
@@ -492,6 +493,9 @@ struct CPUSPARCState {
/* UA 2005 hyperprivileged registers */
uint64_t hpstate, htstate[MAXTL_MAX], hintp, htba, hver, hstick_cmpr, ssr;
CPUTimer *hstick; // UA 2005
+ /* Interrupt vector registers */
+ uint64_t ivec_status;
+ uint64_t ivec_data[3];
uint32_t softint;
#define SOFTINT_TIMER 1
#define SOFTINT_STIMER (1 << 16)
@@ -582,7 +586,6 @@ void cpu_unassigned_access(CPUSPARCState *env1, target_phys_addr_t addr,
#if defined(TARGET_SPARC64)
target_phys_addr_t cpu_get_phys_page_nofault(CPUSPARCState *env, target_ulong addr,
int mmu_idx);
-
#endif
#endif
int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
@@ -688,6 +691,7 @@ static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp)
#endif
#include "cpu-all.h"
+#include "cpu-qom.h"
#ifdef TARGET_SPARC64
/* sun4u.c */
@@ -696,6 +700,9 @@ uint64_t cpu_tick_get_count(CPUTimer *timer);
void cpu_tick_set_limit(CPUTimer *timer, uint64_t limit);
trap_state* cpu_tsptr(CPUSPARCState* env);
#endif
+void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env, target_ulong addr,
+ int is_write, int is_user,
+ void *retaddr);
#define TB_FLAG_FPU_ENABLED (1 << 4)
#define TB_FLAG_AM_ENABLED (1 << 5)
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 1f67b08065..e3c7fddbe8 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -18,11 +18,11 @@ DEF_HELPER_1(rdcwp, tl, env)
DEF_HELPER_2(wrcwp, void, env, tl)
DEF_HELPER_FLAGS_2(array8, TCG_CALL_CONST | TCG_CALL_PURE, tl, tl, tl)
DEF_HELPER_1(popc, tl, tl)
-DEF_HELPER_3(ldda_asi, void, tl, int, int)
-DEF_HELPER_4(ldf_asi, void, tl, int, int, int)
-DEF_HELPER_4(stf_asi, void, tl, int, int, int)
-DEF_HELPER_4(cas_asi, tl, tl, tl, tl, i32)
-DEF_HELPER_4(casx_asi, tl, tl, tl, tl, i32)
+DEF_HELPER_4(ldda_asi, void, env, tl, int, int)
+DEF_HELPER_5(ldf_asi, void, env, tl, int, int, int)
+DEF_HELPER_5(stf_asi, void, env, tl, int, int, int)
+DEF_HELPER_5(cas_asi, tl, env, tl, tl, tl, i32)
+DEF_HELPER_5(casx_asi, tl, env, tl, tl, tl, i32)
DEF_HELPER_2(set_softint, void, env, i64)
DEF_HELPER_2(clear_softint, void, env, i64)
DEF_HELPER_2(write_softint, void, env, i64)
@@ -30,7 +30,7 @@ DEF_HELPER_2(tick_set_count, void, ptr, i64)
DEF_HELPER_1(tick_get_count, i64, ptr)
DEF_HELPER_2(tick_set_limit, void, ptr, i64)
#endif
-DEF_HELPER_2(check_align, void, tl, i32)
+DEF_HELPER_3(check_align, void, env, tl, i32)
DEF_HELPER_1(debug, void, env)
DEF_HELPER_1(save, void, env)
DEF_HELPER_1(restore, void, env)
@@ -38,11 +38,11 @@ DEF_HELPER_3(udiv, tl, env, tl, tl)
DEF_HELPER_3(udiv_cc, tl, env, tl, tl)
DEF_HELPER_3(sdiv, tl, env, tl, tl)
DEF_HELPER_3(sdiv_cc, tl, env, tl, tl)
-DEF_HELPER_2(ldqf, void, tl, int)
-DEF_HELPER_2(stqf, void, tl, int)
+DEF_HELPER_3(ldqf, void, env, tl, int)
+DEF_HELPER_3(stqf, void, env, tl, int)
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
-DEF_HELPER_4(ld_asi, i64, tl, int, int, int)
-DEF_HELPER_4(st_asi, void, tl, i64, int, int)
+DEF_HELPER_5(ld_asi, i64, env, tl, int, int, int)
+DEF_HELPER_5(st_asi, void, env, tl, i64, int, int)
#endif
DEF_HELPER_2(ldfsr, void, env, i32)
DEF_HELPER_FLAGS_1(fabss, TCG_CALL_CONST | TCG_CALL_PURE, f32, f32)
@@ -78,7 +78,7 @@ DEF_HELPER_1(fcmpeq_fcc1, void, env)
DEF_HELPER_1(fcmpeq_fcc2, void, env)
DEF_HELPER_1(fcmpeq_fcc3, void, env)
#endif
-DEF_HELPER_2(raise_exception, void, env, int)
+DEF_HELPER_2(raise_exception, noreturn, env, int)
#define F_HELPER_0_1(name) DEF_HELPER_1(f ## name, void, env)
DEF_HELPER_3(faddd, f64, env, f64, f64)
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 48d433c571..1418205f99 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -18,13 +18,8 @@
*/
#include "cpu.h"
-#include "dyngen-exec.h"
#include "helper.h"
-#if !defined(CONFIG_USER_ONLY)
-#include "softmmu_exec.h"
-#endif
-
//#define DEBUG_MMU
//#define DEBUG_MXCC
//#define DEBUG_UNALIGNED
@@ -70,13 +65,21 @@
#define QT1 (env->qt1)
#if !defined(CONFIG_USER_ONLY)
-static void do_unassigned_access(target_phys_addr_t addr, int is_write,
- int is_exec, int is_asi, int size);
-#else
-#ifdef TARGET_SPARC64
-static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
- int is_asi, int size);
-#endif
+#include "softmmu_exec.h"
+#define MMUSUFFIX _mmu
+#define ALIGNED_ONLY
+
+#define SHIFT 0
+#include "softmmu_template.h"
+
+#define SHIFT 1
+#include "softmmu_template.h"
+
+#define SHIFT 2
+#include "softmmu_template.h"
+
+#define SHIFT 3
+#include "softmmu_template.h"
#endif
#if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
@@ -300,7 +303,7 @@ static inline int is_translating_asi(int asi)
#endif
}
-static inline target_ulong asi_address_mask(CPUSPARCState *env1,
+static inline target_ulong asi_address_mask(CPUSPARCState *env,
int asi, target_ulong addr)
{
if (is_translating_asi(asi)) {
@@ -310,7 +313,7 @@ static inline target_ulong asi_address_mask(CPUSPARCState *env1,
}
}
-void helper_check_align(target_ulong addr, uint32_t align)
+void helper_check_align(CPUSPARCState *env, target_ulong addr, uint32_t align)
{
if (addr & align) {
#ifdef DEBUG_UNALIGNED
@@ -372,7 +375,8 @@ static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
/* Leon3 cache control */
-static void leon3_cache_control_st(target_ulong addr, uint64_t val, int size)
+static void leon3_cache_control_st(CPUSPARCState *env, target_ulong addr,
+ uint64_t val, int size)
{
DPRINTF_CACHE_CONTROL("st addr:%08x, val:%" PRIx64 ", size:%d\n",
addr, val, size);
@@ -404,7 +408,8 @@ static void leon3_cache_control_st(target_ulong addr, uint64_t val, int size)
};
}
-static uint64_t leon3_cache_control_ld(target_ulong addr, int size)
+static uint64_t leon3_cache_control_ld(CPUSPARCState *env, target_ulong addr,
+ int size)
{
uint64_t ret = 0;
@@ -436,14 +441,15 @@ static uint64_t leon3_cache_control_ld(target_ulong addr, int size)
return ret;
}
-uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
+uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
+ int sign)
{
uint64_t ret = 0;
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
uint32_t last_addr = addr;
#endif
- helper_check_align(addr, size - 1);
+ helper_check_align(env, addr, size - 1);
switch (asi) {
case 2: /* SuperSparc MXCC registers and Leon3 cache control */
switch (addr) {
@@ -451,7 +457,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
case 0x08: /* Leon3 Instruction Cache config */
case 0x0C: /* Leon3 Date Cache config */
if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
- ret = leon3_cache_control_ld(addr, size);
+ ret = leon3_cache_control_ld(env, addr, size);
}
break;
case 0x01c00a00: /* MXCC control register */
@@ -535,51 +541,51 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
case 9: /* Supervisor code access */
switch (size) {
case 1:
- ret = ldub_code(addr);
+ ret = cpu_ldub_code(env, addr);
break;
case 2:
- ret = lduw_code(addr);
+ ret = cpu_lduw_code(env, addr);
break;
default:
case 4:
- ret = ldl_code(addr);
+ ret = cpu_ldl_code(env, addr);
break;
case 8:
- ret = ldq_code(addr);
+ ret = cpu_ldq_code(env, addr);
break;
}
break;
case 0xa: /* User data access */
switch (size) {
case 1:
- ret = ldub_user(addr);
+ ret = cpu_ldub_user(env, addr);
break;
case 2:
- ret = lduw_user(addr);
+ ret = cpu_lduw_user(env, addr);
break;
default:
case 4:
- ret = ldl_user(addr);
+ ret = cpu_ldl_user(env, addr);
break;
case 8:
- ret = ldq_user(addr);
+ ret = cpu_ldq_user(env, addr);
break;
}
break;
case 0xb: /* Supervisor data access */
switch (size) {
case 1:
- ret = ldub_kernel(addr);
+ ret = cpu_ldub_kernel(env, addr);
break;
case 2:
- ret = lduw_kernel(addr);
+ ret = cpu_lduw_kernel(env, addr);
break;
default:
case 4:
- ret = ldl_kernel(addr);
+ ret = cpu_ldl_kernel(env, addr);
break;
case 8:
- ret = ldq_kernel(addr);
+ ret = cpu_ldq_kernel(env, addr);
break;
}
break;
@@ -669,7 +675,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
break;
case 8: /* User code access, XXX */
default:
- do_unassigned_access(addr, 0, 0, asi, size);
+ cpu_unassigned_access(env, addr, 0, 0, asi, size);
ret = 0;
break;
}
@@ -694,9 +700,10 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
return ret;
}
-void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
+void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
+ int size)
{
- helper_check_align(addr, size - 1);
+ helper_check_align(env, addr, size - 1);
switch (asi) {
case 2: /* SuperSparc MXCC registers and Leon3 cache control */
switch (addr) {
@@ -704,7 +711,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
case 0x08: /* Leon3 Instruction Cache config */
case 0x0C: /* Leon3 Date Cache config */
if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
- leon3_cache_control_st(addr, val, size);
+ leon3_cache_control_st(env, addr, val, size);
}
break;
@@ -902,34 +909,34 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
case 0xa: /* User data access */
switch (size) {
case 1:
- stb_user(addr, val);
+ cpu_stb_user(env, addr, val);
break;
case 2:
- stw_user(addr, val);
+ cpu_stw_user(env, addr, val);
break;
default:
case 4:
- stl_user(addr, val);
+ cpu_stl_user(env, addr, val);
break;
case 8:
- stq_user(addr, val);
+ cpu_stq_user(env, addr, val);
break;
}
break;
case 0xb: /* Supervisor data access */
switch (size) {
case 1:
- stb_kernel(addr, val);
+ cpu_stb_kernel(env, addr, val);
break;
case 2:
- stw_kernel(addr, val);
+ cpu_stw_kernel(env, addr, val);
break;
default:
case 4:
- stl_kernel(addr, val);
+ cpu_stl_kernel(env, addr, val);
break;
case 8:
- stq_kernel(addr, val);
+ cpu_stq_kernel(env, addr, val);
break;
}
break;
@@ -952,8 +959,8 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
uint32_t src = val & ~3, dst = addr & ~3, temp;
for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
- temp = ldl_kernel(src);
- stl_kernel(dst, temp);
+ temp = cpu_ldl_kernel(env, src);
+ cpu_stl_kernel(env, dst, temp);
}
}
break;
@@ -965,7 +972,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
uint32_t dst = addr & 7;
for (i = 0; i < 32; i += 8, dst += 8) {
- stq_kernel(dst, val);
+ cpu_stq_kernel(env, dst, val);
}
}
break;
@@ -1056,7 +1063,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
case 8: /* User code access, XXX */
case 9: /* Supervisor code access, XXX */
default:
- do_unassigned_access(addr, 1, 0, asi, size);
+ cpu_unassigned_access(env, addr, 1, 0, asi, size);
break;
}
#ifdef DEBUG_ASI
@@ -1068,7 +1075,8 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
#else /* TARGET_SPARC64 */
#ifdef CONFIG_USER_ONLY
-uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
+uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
+ int sign)
{
uint64_t ret = 0;
#if defined(DEBUG_ASI)
@@ -1079,7 +1087,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
helper_raise_exception(env, TT_PRIV_ACT);
}
- helper_check_align(addr, size - 1);
+ helper_check_align(env, addr, size - 1);
addr = asi_address_mask(env, asi, addr);
switch (asi) {
@@ -1174,7 +1182,8 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
return ret;
}
-void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
+void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
+ int asi, int size)
{
#ifdef DEBUG_ASI
dump_asi("write", addr, asi, size, val);
@@ -1183,7 +1192,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
helper_raise_exception(env, TT_PRIV_ACT);
}
- helper_check_align(addr, size - 1);
+ helper_check_align(env, addr, size - 1);
addr = asi_address_mask(env, asi, addr);
/* Convert to little endian */
@@ -1238,14 +1247,15 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
case 0x8a: /* Primary no-fault LE, RO */
case 0x8b: /* Secondary no-fault LE, RO */
default:
- do_unassigned_access(addr, 1, 0, 1, size);
+ helper_raise_exception(env, TT_DATA_ACCESS);
return;
}
}
#else /* CONFIG_USER_ONLY */
-uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
+uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
+ int sign)
{
uint64_t ret = 0;
#if defined(DEBUG_ASI)
@@ -1261,7 +1271,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
helper_raise_exception(env, TT_PRIV_ACT);
}
- helper_check_align(addr, size - 1);
+ helper_check_align(env, addr, size - 1);
addr = asi_address_mask(env, asi, addr);
/* process nonfaulting loads first */
@@ -1302,17 +1312,17 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
if (cpu_hypervisor_mode(env)) {
switch (size) {
case 1:
- ret = ldub_hypv(addr);
+ ret = cpu_ldub_hypv(env, addr);
break;
case 2:
- ret = lduw_hypv(addr);
+ ret = cpu_lduw_hypv(env, addr);
break;
case 4:
- ret = ldl_hypv(addr);
+ ret = cpu_ldl_hypv(env, addr);
break;
default:
case 8:
- ret = ldq_hypv(addr);
+ ret = cpu_ldq_hypv(env, addr);
break;
}
} else {
@@ -1320,33 +1330,33 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
if (asi & 1) {
switch (size) {
case 1:
- ret = ldub_kernel_secondary(addr);
+ ret = cpu_ldub_kernel_secondary(env, addr);
break;
case 2:
- ret = lduw_kernel_secondary(addr);
+ ret = cpu_lduw_kernel_secondary(env, addr);
break;
case 4:
- ret = ldl_kernel_secondary(addr);
+ ret = cpu_ldl_kernel_secondary(env, addr);
break;
default:
case 8:
- ret = ldq_kernel_secondary(addr);
+ ret = cpu_ldq_kernel_secondary(env, addr);
break;
}
} else {
switch (size) {
case 1:
- ret = ldub_kernel(addr);
+ ret = cpu_ldub_kernel(env, addr);
break;
case 2:
- ret = lduw_kernel(addr);
+ ret = cpu_lduw_kernel(env, addr);
break;
case 4:
- ret = ldl_kernel(addr);
+ ret = cpu_ldl_kernel(env, addr);
break;
default:
case 8:
- ret = ldq_kernel(addr);
+ ret = cpu_ldq_kernel(env, addr);
break;
}
}
@@ -1356,33 +1366,33 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
if (asi & 1) {
switch (size) {
case 1:
- ret = ldub_user_secondary(addr);
+ ret = cpu_ldub_user_secondary(env, addr);
break;
case 2:
- ret = lduw_user_secondary(addr);
+ ret = cpu_lduw_user_secondary(env, addr);
break;
case 4:
- ret = ldl_user_secondary(addr);
+ ret = cpu_ldl_user_secondary(env, addr);
break;
default:
case 8:
- ret = ldq_user_secondary(addr);
+ ret = cpu_ldq_user_secondary(env, addr);
break;
}
} else {
switch (size) {
case 1:
- ret = ldub_user(addr);
+ ret = cpu_ldub_user(env, addr);
break;
case 2:
- ret = lduw_user(addr);
+ ret = cpu_lduw_user(env, addr);
break;
case 4:
- ret = ldl_user(addr);
+ ret = cpu_ldl_user(env, addr);
break;
default:
case 8:
- ret = ldq_user(addr);
+ ret = cpu_ldq_user(env, addr);
break;
}
}
@@ -1420,17 +1430,17 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
{
switch (size) {
case 1:
- ret = ldub_nucleus(addr);
+ ret = cpu_ldub_nucleus(env, addr);
break;
case 2:
- ret = lduw_nucleus(addr);
+ ret = cpu_lduw_nucleus(env, addr);
break;
case 4:
- ret = ldl_nucleus(addr);
+ ret = cpu_ldl_nucleus(env, addr);
break;
default:
case 8:
- ret = ldq_nucleus(addr);
+ ret = cpu_ldq_nucleus(env, addr);
break;
}
break;
@@ -1526,6 +1536,19 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
ret = env->dtlb[reg].tag;
break;
}
+ case 0x48: /* Interrupt dispatch, RO */
+ break;
+ case 0x49: /* Interrupt data receive */
+ ret = env->ivec_status;
+ break;
+ case 0x7f: /* Incoming interrupt vector, RO */
+ {
+ int reg = (addr >> 4) & 0x3;
+ if (reg < 3) {
+ ret = env->ivec_data[reg];
+ }
+ break;
+ }
case 0x46: /* D-cache data */
case 0x47: /* D-cache tag access */
case 0x4b: /* E-cache error enable */
@@ -1540,18 +1563,13 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
case 0x7e: /* E-cache tag */
break;
case 0x5b: /* D-MMU data pointer */
- case 0x48: /* Interrupt dispatch, RO */
- case 0x49: /* Interrupt data receive */
- case 0x7f: /* Incoming interrupt vector, RO */
- /* XXX */
- break;
case 0x54: /* I-MMU data in, WO */
case 0x57: /* I-MMU demap, WO */
case 0x5c: /* D-MMU data in, WO */
case 0x5f: /* D-MMU demap, WO */
case 0x77: /* Interrupt vector, WO */
default:
- do_unassigned_access(addr, 0, 0, 1, size);
+ cpu_unassigned_access(env, addr, 0, 0, 1, size);
ret = 0;
break;
}
@@ -1604,7 +1622,8 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
return ret;
}
-void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
+void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
+ int asi, int size)
{
#ifdef DEBUG_ASI
dump_asi("write", addr, asi, size, val);
@@ -1619,7 +1638,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
helper_raise_exception(env, TT_PRIV_ACT);
}
- helper_check_align(addr, size - 1);
+ helper_check_align(env, addr, size - 1);
addr = asi_address_mask(env, asi, addr);
/* Convert to little endian */
@@ -1663,17 +1682,17 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
if (cpu_hypervisor_mode(env)) {
switch (size) {
case 1:
- stb_hypv(addr, val);
+ cpu_stb_hypv(env, addr, val);
break;
case 2:
- stw_hypv(addr, val);
+ cpu_stw_hypv(env, addr, val);
break;
case 4:
- stl_hypv(addr, val);
+ cpu_stl_hypv(env, addr, val);
break;
case 8:
default:
- stq_hypv(addr, val);
+ cpu_stq_hypv(env, addr, val);
break;
}
} else {
@@ -1681,33 +1700,33 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
if (asi & 1) {
switch (size) {
case 1:
- stb_kernel_secondary(addr, val);
+ cpu_stb_kernel_secondary(env, addr, val);
break;
case 2:
- stw_kernel_secondary(addr, val);
+ cpu_stw_kernel_secondary(env, addr, val);
break;
case 4:
- stl_kernel_secondary(addr, val);
+ cpu_stl_kernel_secondary(env, addr, val);
break;
case 8:
default:
- stq_kernel_secondary(addr, val);
+ cpu_stq_kernel_secondary(env, addr, val);
break;
}
} else {
switch (size) {
case 1:
- stb_kernel(addr, val);
+ cpu_stb_kernel(env, addr, val);
break;
case 2:
- stw_kernel(addr, val);
+ cpu_stw_kernel(env, addr, val);
break;
case 4:
- stl_kernel(addr, val);
+ cpu_stl_kernel(env, addr, val);
break;
case 8:
default:
- stq_kernel(addr, val);
+ cpu_stq_kernel(env, addr, val);
break;
}
}
@@ -1717,33 +1736,33 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
if (asi & 1) {
switch (size) {
case 1:
- stb_user_secondary(addr, val);
+ cpu_stb_user_secondary(env, addr, val);
break;
case 2:
- stw_user_secondary(addr, val);
+ cpu_stw_user_secondary(env, addr, val);
break;
case 4:
- stl_user_secondary(addr, val);
+ cpu_stl_user_secondary(env, addr, val);
break;
case 8:
default:
- stq_user_secondary(addr, val);
+ cpu_stq_user_secondary(env, addr, val);
break;
}
} else {
switch (size) {
case 1:
- stb_user(addr, val);
+ cpu_stb_user(env, addr, val);
break;
case 2:
- stw_user(addr, val);
+ cpu_stw_user(env, addr, val);
break;
case 4:
- stl_user(addr, val);
+ cpu_stl_user(env, addr, val);
break;
case 8:
default:
- stq_user(addr, val);
+ cpu_stq_user(env, addr, val);
break;
}
}
@@ -1781,17 +1800,17 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
{
switch (size) {
case 1:
- stb_nucleus(addr, val);
+ cpu_stb_nucleus(env, addr, val);
break;
case 2:
- stw_nucleus(addr, val);
+ cpu_stw_nucleus(env, addr, val);
break;
case 4:
- stl_nucleus(addr, val);
+ cpu_stl_nucleus(env, addr, val);
break;
default:
case 8:
- stq_nucleus(addr, val);
+ cpu_stq_nucleus(env, addr, val);
break;
}
break;
@@ -1954,7 +1973,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
demap_tlb(env->dtlb, addr, "dmmu", env);
return;
case 0x49: /* Interrupt data receive */
- /* XXX */
+ env->ivec_status = val & 0x20;
return;
case 0x46: /* D-cache data */
case 0x47: /* D-cache tag access */
@@ -1983,13 +2002,13 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
case 0x8a: /* Primary no-fault LE, RO */
case 0x8b: /* Secondary no-fault LE, RO */
default:
- do_unassigned_access(addr, 1, 0, 1, size);
+ cpu_unassigned_access(env, addr, 1, 0, 1, size);
return;
}
}
#endif /* CONFIG_USER_ONLY */
-void helper_ldda_asi(target_ulong addr, int asi, int rd)
+void helper_ldda_asi(CPUSPARCState *env, target_ulong addr, int asi, int rd)
{
if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
|| (cpu_has_hypervisor(env)
@@ -2004,22 +2023,22 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
#if !defined(CONFIG_USER_ONLY)
case 0x24: /* Nucleus quad LDD 128 bit atomic */
case 0x2c: /* Nucleus quad LDD 128 bit atomic LE */
- helper_check_align(addr, 0xf);
+ helper_check_align(env, addr, 0xf);
if (rd == 0) {
- env->gregs[1] = ldq_nucleus(addr + 8);
+ env->gregs[1] = cpu_ldq_nucleus(env, addr + 8);
if (asi == 0x2c) {
bswap64s(&env->gregs[1]);
}
} else if (rd < 8) {
- env->gregs[rd] = ldq_nucleus(addr);
- env->gregs[rd + 1] = ldq_nucleus(addr + 8);
+ env->gregs[rd] = cpu_ldq_nucleus(env, addr);
+ env->gregs[rd + 1] = cpu_ldq_nucleus(env, addr + 8);
if (asi == 0x2c) {
bswap64s(&env->gregs[rd]);
bswap64s(&env->gregs[rd + 1]);
}
} else {
- env->regwptr[rd] = ldq_nucleus(addr);
- env->regwptr[rd + 1] = ldq_nucleus(addr + 8);
+ env->regwptr[rd] = cpu_ldq_nucleus(env, addr);
+ env->regwptr[rd + 1] = cpu_ldq_nucleus(env, addr + 8);
if (asi == 0x2c) {
bswap64s(&env->regwptr[rd]);
bswap64s(&env->regwptr[rd + 1]);
@@ -2028,26 +2047,27 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
break;
#endif
default:
- helper_check_align(addr, 0x3);
+ helper_check_align(env, addr, 0x3);
if (rd == 0) {
- env->gregs[1] = helper_ld_asi(addr + 4, asi, 4, 0);
+ env->gregs[1] = helper_ld_asi(env, addr + 4, asi, 4, 0);
} else if (rd < 8) {
- env->gregs[rd] = helper_ld_asi(addr, asi, 4, 0);
- env->gregs[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
+ env->gregs[rd] = helper_ld_asi(env, addr, asi, 4, 0);
+ env->gregs[rd + 1] = helper_ld_asi(env, addr + 4, asi, 4, 0);
} else {
- env->regwptr[rd] = helper_ld_asi(addr, asi, 4, 0);
- env->regwptr[rd + 1] = helper_ld_asi(addr + 4, asi, 4, 0);
+ env->regwptr[rd] = helper_ld_asi(env, addr, asi, 4, 0);
+ env->regwptr[rd + 1] = helper_ld_asi(env, addr + 4, asi, 4, 0);
}
break;
}
}
-void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
+void helper_ldf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
+ int rd)
{
unsigned int i;
target_ulong val;
- helper_check_align(addr, 3);
+ helper_check_align(env, addr, 3);
addr = asi_address_mask(env, asi, addr);
switch (asi) {
@@ -2059,9 +2079,9 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
helper_raise_exception(env, TT_ILL_INSN);
return;
}
- helper_check_align(addr, 0x3f);
+ helper_check_align(env, addr, 0x3f);
for (i = 0; i < 8; i++, rd += 2, addr += 8) {
- env->fpr[rd/2].ll = helper_ld_asi(addr, asi & 0x8f, 8, 0);
+ env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi & 0x8f, 8, 0);
}
return;
@@ -2077,9 +2097,9 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
helper_raise_exception(env, TT_ILL_INSN);
return;
}
- helper_check_align(addr, 0x3f);
+ helper_check_align(env, addr, 0x3f);
for (i = 0; i < 8; i++, rd += 2, addr += 4) {
- env->fpr[rd/2].ll = helper_ld_asi(addr, asi & 0x19, 8, 0);
+ env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi & 0x19, 8, 0);
}
return;
@@ -2090,29 +2110,30 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
switch (size) {
default:
case 4:
- val = helper_ld_asi(addr, asi, size, 0);
+ val = helper_ld_asi(env, addr, asi, size, 0);
if (rd & 1) {
- env->fpr[rd/2].l.lower = val;
+ env->fpr[rd / 2].l.lower = val;
} else {
- env->fpr[rd/2].l.upper = val;
+ env->fpr[rd / 2].l.upper = val;
}
break;
case 8:
- env->fpr[rd/2].ll = helper_ld_asi(addr, asi, size, 0);
+ env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi, size, 0);
break;
case 16:
- env->fpr[rd/2].ll = helper_ld_asi(addr, asi, 8, 0);
- env->fpr[rd/2 + 1].ll = helper_ld_asi(addr + 8, asi, 8, 0);
+ env->fpr[rd / 2].ll = helper_ld_asi(env, addr, asi, 8, 0);
+ env->fpr[rd / 2 + 1].ll = helper_ld_asi(env, addr + 8, asi, 8, 0);
break;
}
}
-void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
+void helper_stf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
+ int rd)
{
unsigned int i;
target_ulong val;
- helper_check_align(addr, 3);
+ helper_check_align(env, addr, 3);
addr = asi_address_mask(env, asi, addr);
switch (asi) {
@@ -2126,9 +2147,9 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
helper_raise_exception(env, TT_ILL_INSN);
return;
}
- helper_check_align(addr, 0x3f);
+ helper_check_align(env, addr, 0x3f);
for (i = 0; i < 8; i++, rd += 2, addr += 8) {
- helper_st_asi(addr, env->fpr[rd/2].ll, asi & 0x8f, 8);
+ helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi & 0x8f, 8);
}
return;
@@ -2144,9 +2165,9 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
helper_raise_exception(env, TT_ILL_INSN);
return;
}
- helper_check_align(addr, 0x3f);
+ helper_check_align(env, addr, 0x3f);
for (i = 0; i < 8; i++, rd += 2, addr += 8) {
- helper_st_asi(addr, env->fpr[rd/2].ll, asi & 0x19, 8);
+ helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi & 0x19, 8);
}
return;
@@ -2158,71 +2179,72 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
default:
case 4:
if (rd & 1) {
- val = env->fpr[rd/2].l.lower;
+ val = env->fpr[rd / 2].l.lower;
} else {
- val = env->fpr[rd/2].l.upper;
+ val = env->fpr[rd / 2].l.upper;
}
- helper_st_asi(addr, val, asi, size);
+ helper_st_asi(env, addr, val, asi, size);
break;
case 8:
- helper_st_asi(addr, env->fpr[rd/2].ll, asi, size);
+ helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi, size);
break;
case 16:
- helper_st_asi(addr, env->fpr[rd/2].ll, asi, 8);
- helper_st_asi(addr + 8, env->fpr[rd/2 + 1].ll, asi, 8);
+ helper_st_asi(env, addr, env->fpr[rd / 2].ll, asi, 8);
+ helper_st_asi(env, addr + 8, env->fpr[rd / 2 + 1].ll, asi, 8);
break;
}
}
-target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,
- target_ulong val2, uint32_t asi)
+target_ulong helper_cas_asi(CPUSPARCState *env, target_ulong addr,
+ target_ulong val1, target_ulong val2, uint32_t asi)
{
target_ulong ret;
val2 &= 0xffffffffUL;
- ret = helper_ld_asi(addr, asi, 4, 0);
+ ret = helper_ld_asi(env, addr, asi, 4, 0);
ret &= 0xffffffffUL;
if (val2 == ret) {
- helper_st_asi(addr, val1 & 0xffffffffUL, asi, 4);
+ helper_st_asi(env, addr, val1 & 0xffffffffUL, asi, 4);
}
return ret;
}
-target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,
- target_ulong val2, uint32_t asi)
+target_ulong helper_casx_asi(CPUSPARCState *env, target_ulong addr,
+ target_ulong val1, target_ulong val2,
+ uint32_t asi)
{
target_ulong ret;
- ret = helper_ld_asi(addr, asi, 8, 0);
+ ret = helper_ld_asi(env, addr, asi, 8, 0);
if (val2 == ret) {
- helper_st_asi(addr, val1, asi, 8);
+ helper_st_asi(env, addr, val1, asi, 8);
}
return ret;
}
#endif /* TARGET_SPARC64 */
-void helper_ldqf(target_ulong addr, int mem_idx)
+void helper_ldqf(CPUSPARCState *env, target_ulong addr, int mem_idx)
{
/* XXX add 128 bit load */
CPU_QuadU u;
- helper_check_align(addr, 7);
+ helper_check_align(env, addr, 7);
#if !defined(CONFIG_USER_ONLY)
switch (mem_idx) {
case MMU_USER_IDX:
- u.ll.upper = ldq_user(addr);
- u.ll.lower = ldq_user(addr + 8);
+ u.ll.upper = cpu_ldq_user(env, addr);
+ u.ll.lower = cpu_ldq_user(env, addr + 8);
QT0 = u.q;
break;
case MMU_KERNEL_IDX:
- u.ll.upper = ldq_kernel(addr);
- u.ll.lower = ldq_kernel(addr + 8);
+ u.ll.upper = cpu_ldq_kernel(env, addr);
+ u.ll.lower = cpu_ldq_kernel(env, addr + 8);
QT0 = u.q;
break;
#ifdef TARGET_SPARC64
case MMU_HYPV_IDX:
- u.ll.upper = ldq_hypv(addr);
- u.ll.lower = ldq_hypv(addr + 8);
+ u.ll.upper = cpu_ldq_hypv(env, addr);
+ u.ll.lower = cpu_ldq_hypv(env, addr + 8);
QT0 = u.q;
break;
#endif
@@ -2237,29 +2259,29 @@ void helper_ldqf(target_ulong addr, int mem_idx)
#endif
}
-void helper_stqf(target_ulong addr, int mem_idx)
+void helper_stqf(CPUSPARCState *env, target_ulong addr, int mem_idx)
{
/* XXX add 128 bit store */
CPU_QuadU u;
- helper_check_align(addr, 7);
+ helper_check_align(env, addr, 7);
#if !defined(CONFIG_USER_ONLY)
switch (mem_idx) {
case MMU_USER_IDX:
u.q = QT0;
- stq_user(addr, u.ll.upper);
- stq_user(addr + 8, u.ll.lower);
+ cpu_stq_user(env, addr, u.ll.upper);
+ cpu_stq_user(env, addr + 8, u.ll.lower);
break;
case MMU_KERNEL_IDX:
u.q = QT0;
- stq_kernel(addr, u.ll.upper);
- stq_kernel(addr + 8, u.ll.lower);
+ cpu_stq_kernel(env, addr, u.ll.upper);
+ cpu_stq_kernel(env, addr + 8, u.ll.lower);
break;
#ifdef TARGET_SPARC64
case MMU_HYPV_IDX:
u.q = QT0;
- stq_hypv(addr, u.ll.upper);
- stq_hypv(addr + 8, u.ll.lower);
+ cpu_stq_hypv(env, addr, u.ll.upper);
+ cpu_stq_hypv(env, addr + 8, u.ll.lower);
break;
#endif
default:
@@ -2273,10 +2295,10 @@ void helper_stqf(target_ulong addr, int mem_idx)
#endif
}
-#ifndef TARGET_SPARC64
#if !defined(CONFIG_USER_ONLY)
-static void do_unassigned_access(target_phys_addr_t addr, int is_write,
- int is_exec, int is_asi, int size)
+#ifndef TARGET_SPARC64
+void cpu_unassigned_access(CPUSPARCState *env, target_phys_addr_t addr,
+ int is_write, int is_exec, int is_asi, int size)
{
int fault_type;
@@ -2334,15 +2356,9 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
tlb_flush(env, 1);
}
}
-#endif
-#else
-#if defined(CONFIG_USER_ONLY)
-static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
- int is_asi, int size)
#else
-static void do_unassigned_access(target_phys_addr_t addr, int is_write,
- int is_exec, int is_asi, int size)
-#endif
+void cpu_unassigned_access(CPUSPARCState *env, target_phys_addr_t addr,
+ int is_write, int is_exec, int is_asi, int size)
{
#ifdef DEBUG_UNASSIGNED
printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx
@@ -2356,16 +2372,51 @@ static void do_unassigned_access(target_phys_addr_t addr, int is_write,
}
}
#endif
+#endif
#if !defined(CONFIG_USER_ONLY)
-void cpu_unassigned_access(CPUSPARCState *env1, target_phys_addr_t addr,
- int is_write, int is_exec, int is_asi, int size)
+/* XXX: make it generic ? */
+static void cpu_restore_state2(CPUSPARCState *env, void *retaddr)
{
- CPUSPARCState *saved_env;
+ TranslationBlock *tb;
+ unsigned long pc;
+
+ if (retaddr) {
+ /* now we have a real cpu fault */
+ pc = (unsigned long)retaddr;
+ tb = tb_find_pc(pc);
+ if (tb) {
+ /* the PC is inside the translated code. It means that we have
+ a virtual CPU fault */
+ cpu_restore_state(tb, env, pc);
+ }
+ }
+}
+
+void do_unaligned_access(CPUSPARCState *env, target_ulong addr, int is_write,
+ int is_user, void *retaddr)
+{
+#ifdef DEBUG_UNALIGNED
+ printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
+ "\n", addr, env->pc);
+#endif
+ cpu_restore_state2(env, retaddr);
+ helper_raise_exception(env, TT_UNALIGNED);
+}
- saved_env = env;
- env = env1;
- do_unassigned_access(addr, is_write, is_exec, is_asi, size);
- env = saved_env;
+/* try to fill the TLB and return an exception if error. If retaddr is
+ NULL, it means that the function was called in C code (i.e. not
+ from generated code or from helper.c) */
+/* XXX: fix it to restore all registers */
+void tlb_fill(CPUSPARCState *env, target_ulong addr, int is_write, int mmu_idx,
+ void *retaddr)
+{
+ int ret;
+
+ ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx);
+ if (ret) {
+ cpu_restore_state2(env, retaddr);
+ cpu_loop_exit(env);
+ }
}
#endif
diff --git a/target-sparc/mmu_helper.c b/target-sparc/mmu_helper.c
index 11fb9f5de6..cb73c449f0 100644
--- a/target-sparc/mmu_helper.c
+++ b/target-sparc/mmu_helper.c
@@ -150,18 +150,17 @@ static int get_physical_address(CPUSPARCState *env, target_phys_addr_t *physical
case 3: /* Reserved */
return (3 << 8) | (4 << 2);
case 2: /* L3 PTE */
- page_offset = (address & TARGET_PAGE_MASK) &
- (TARGET_PAGE_SIZE - 1);
+ page_offset = 0;
}
*page_size = TARGET_PAGE_SIZE;
break;
case 2: /* L2 PTE */
- page_offset = address & 0x3ffff;
+ page_offset = address & 0x3f000;
*page_size = 0x40000;
}
break;
case 2: /* L1 PTE */
- page_offset = address & 0xffffff;
+ page_offset = address & 0xfff000;
*page_size = 0x1000000;
}
}
@@ -206,11 +205,11 @@ int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw,
target_ulong page_size;
int error_code = 0, prot, access_index;
+ address &= TARGET_PAGE_MASK;
error_code = get_physical_address(env, &paddr, &prot, &access_index,
address, rw, mmu_idx, &page_size);
+ vaddr = address;
if (error_code == 0) {
- vaddr = address & TARGET_PAGE_MASK;
- paddr &= TARGET_PAGE_MASK;
#ifdef DEBUG_MMU
printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
TARGET_FMT_lx "\n", address, paddr, vaddr);
@@ -230,7 +229,6 @@ int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw,
permissions. If no mapping is available, redirect accesses to
neverland. Fake/overridden mappings will be flushed when
switching to normal mode. */
- vaddr = address & TARGET_PAGE_MASK;
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
tlb_set_page(env, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
return 0;
@@ -704,17 +702,16 @@ static int get_physical_address(CPUSPARCState *env, target_phys_addr_t *physical
int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw,
int mmu_idx)
{
- target_ulong virt_addr, vaddr;
+ target_ulong vaddr;
target_phys_addr_t paddr;
target_ulong page_size;
int error_code = 0, prot, access_index;
+ address &= TARGET_PAGE_MASK;
error_code = get_physical_address(env, &paddr, &prot, &access_index,
address, rw, mmu_idx, &page_size);
if (error_code == 0) {
- virt_addr = address & TARGET_PAGE_MASK;
- vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
- (TARGET_PAGE_SIZE - 1));
+ vaddr = address;
trace_mmu_helper_mmu_fault(address, paddr, mmu_idx, env->tl,
env->dmmu.mmu_primary_context,
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
deleted file mode 100644
index 1aff12516e..0000000000
--- a/target-sparc/op_helper.c
+++ /dev/null
@@ -1,74 +0,0 @@
-#include "cpu.h"
-#include "dyngen-exec.h"
-#include "helper.h"
-
-#if !defined(CONFIG_USER_ONLY)
-static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
- void *retaddr);
-
-#define MMUSUFFIX _mmu
-#define ALIGNED_ONLY
-
-#define SHIFT 0
-#include "softmmu_template.h"
-
-#define SHIFT 1
-#include "softmmu_template.h"
-
-#define SHIFT 2
-#include "softmmu_template.h"
-
-#define SHIFT 3
-#include "softmmu_template.h"
-
-/* XXX: make it generic ? */
-static void cpu_restore_state2(void *retaddr)
-{
- TranslationBlock *tb;
- unsigned long pc;
-
- if (retaddr) {
- /* now we have a real cpu fault */
- pc = (unsigned long)retaddr;
- tb = tb_find_pc(pc);
- if (tb) {
- /* the PC is inside the translated code. It means that we have
- a virtual CPU fault */
- cpu_restore_state(tb, env, pc);
- }
- }
-}
-
-static void do_unaligned_access(target_ulong addr, int is_write, int is_user,
- void *retaddr)
-{
-#ifdef DEBUG_UNALIGNED
- printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
- "\n", addr, env->pc);
-#endif
- cpu_restore_state2(retaddr);
- helper_raise_exception(env, TT_UNALIGNED);
-}
-
-/* try to fill the TLB and return an exception if error. If retaddr is
- NULL, it means that the function was called in C code (i.e. not
- from generated code or from helper.c) */
-/* XXX: fix it to restore all registers */
-void tlb_fill(CPUSPARCState *env1, target_ulong addr, int is_write, int mmu_idx,
- void *retaddr)
-{
- int ret;
- CPUSPARCState *saved_env;
-
- saved_env = env;
- env = env1;
-
- ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx);
- if (ret) {
- cpu_restore_state2(retaddr);
- cpu_loop_exit(env);
- }
- env = saved_env;
-}
-
-#endif /* !CONFIG_USER_ONLY */
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index ef176e94b3..4967152e88 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -1955,7 +1955,7 @@ static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
r_asi = gen_get_asi(insn, addr);
r_size = tcg_const_i32(size);
r_sign = tcg_const_i32(sign);
- gen_helper_ld_asi(dst, addr, r_asi, r_size, r_sign);
+ gen_helper_ld_asi(dst, cpu_env, addr, r_asi, r_size, r_sign);
tcg_temp_free_i32(r_sign);
tcg_temp_free_i32(r_size);
tcg_temp_free_i32(r_asi);
@@ -1967,7 +1967,7 @@ static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
r_asi = gen_get_asi(insn, addr);
r_size = tcg_const_i32(size);
- gen_helper_st_asi(addr, src, r_asi, r_size);
+ gen_helper_st_asi(cpu_env, addr, src, r_asi, r_size);
tcg_temp_free_i32(r_size);
tcg_temp_free_i32(r_asi);
}
@@ -1979,7 +1979,7 @@ static inline void gen_ldf_asi(TCGv addr, int insn, int size, int rd)
r_asi = gen_get_asi(insn, addr);
r_size = tcg_const_i32(size);
r_rd = tcg_const_i32(rd);
- gen_helper_ldf_asi(addr, r_asi, r_size, r_rd);
+ gen_helper_ldf_asi(cpu_env, addr, r_asi, r_size, r_rd);
tcg_temp_free_i32(r_rd);
tcg_temp_free_i32(r_size);
tcg_temp_free_i32(r_asi);
@@ -1992,7 +1992,7 @@ static inline void gen_stf_asi(TCGv addr, int insn, int size, int rd)
r_asi = gen_get_asi(insn, addr);
r_size = tcg_const_i32(size);
r_rd = tcg_const_i32(rd);
- gen_helper_stf_asi(addr, r_asi, r_size, r_rd);
+ gen_helper_stf_asi(cpu_env, addr, r_asi, r_size, r_rd);
tcg_temp_free_i32(r_rd);
tcg_temp_free_i32(r_size);
tcg_temp_free_i32(r_asi);
@@ -2005,9 +2005,9 @@ static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn)
r_asi = gen_get_asi(insn, addr);
r_size = tcg_const_i32(4);
r_sign = tcg_const_i32(0);
- gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
+ gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
tcg_temp_free_i32(r_sign);
- gen_helper_st_asi(addr, dst, r_asi, r_size);
+ gen_helper_st_asi(cpu_env, addr, dst, r_asi, r_size);
tcg_temp_free_i32(r_size);
tcg_temp_free_i32(r_asi);
tcg_gen_trunc_i64_tl(dst, cpu_tmp64);
@@ -2019,7 +2019,7 @@ static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd)
r_asi = gen_get_asi(insn, addr);
r_rd = tcg_const_i32(rd);
- gen_helper_ldda_asi(addr, r_asi, r_rd);
+ gen_helper_ldda_asi(cpu_env, addr, r_asi, r_rd);
tcg_temp_free_i32(r_rd);
tcg_temp_free_i32(r_asi);
}
@@ -2032,7 +2032,7 @@ static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd)
tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, hi);
r_asi = gen_get_asi(insn, addr);
r_size = tcg_const_i32(8);
- gen_helper_st_asi(addr, cpu_tmp64, r_asi, r_size);
+ gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size);
tcg_temp_free_i32(r_size);
tcg_temp_free_i32(r_asi);
}
@@ -2046,7 +2046,7 @@ static inline void gen_cas_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
r_val1 = tcg_temp_new();
gen_movl_reg_TN(rd, r_val1);
r_asi = gen_get_asi(insn, addr);
- gen_helper_cas_asi(dst, addr, r_val1, val2, r_asi);
+ gen_helper_cas_asi(dst, cpu_env, addr, r_val1, val2, r_asi);
tcg_temp_free_i32(r_asi);
tcg_temp_free(r_val1);
}
@@ -2058,7 +2058,7 @@ static inline void gen_casx_asi(TCGv dst, TCGv addr, TCGv val2, int insn,
gen_movl_reg_TN(rd, cpu_tmp64);
r_asi = gen_get_asi(insn, addr);
- gen_helper_casx_asi(dst, addr, cpu_tmp64, val2, r_asi);
+ gen_helper_casx_asi(dst, cpu_env, addr, cpu_tmp64, val2, r_asi);
tcg_temp_free_i32(r_asi);
}
@@ -2072,7 +2072,7 @@ static inline void gen_ld_asi(TCGv dst, TCGv addr, int insn, int size,
r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
r_size = tcg_const_i32(size);
r_sign = tcg_const_i32(sign);
- gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
+ gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
tcg_temp_free(r_sign);
tcg_temp_free(r_size);
tcg_temp_free(r_asi);
@@ -2086,7 +2086,7 @@ static inline void gen_st_asi(TCGv src, TCGv addr, int insn, int size)
tcg_gen_extu_tl_i64(cpu_tmp64, src);
r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
r_size = tcg_const_i32(size);
- gen_helper_st_asi(addr, cpu_tmp64, r_asi, r_size);
+ gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size);
tcg_temp_free(r_size);
tcg_temp_free(r_asi);
}
@@ -2099,11 +2099,11 @@ static inline void gen_swap_asi(TCGv dst, TCGv addr, int insn)
r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
r_size = tcg_const_i32(4);
r_sign = tcg_const_i32(0);
- gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
+ gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
tcg_temp_free(r_sign);
r_val = tcg_temp_new_i64();
tcg_gen_extu_tl_i64(r_val, dst);
- gen_helper_st_asi(addr, r_val, r_asi, r_size);
+ gen_helper_st_asi(cpu_env, addr, r_val, r_asi, r_size);
tcg_temp_free_i64(r_val);
tcg_temp_free(r_size);
tcg_temp_free(r_asi);
@@ -2117,7 +2117,7 @@ static inline void gen_ldda_asi(TCGv hi, TCGv addr, int insn, int rd)
r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
r_size = tcg_const_i32(8);
r_sign = tcg_const_i32(0);
- gen_helper_ld_asi(cpu_tmp64, addr, r_asi, r_size, r_sign);
+ gen_helper_ld_asi(cpu_tmp64, cpu_env, addr, r_asi, r_size, r_sign);
tcg_temp_free(r_sign);
tcg_temp_free(r_size);
tcg_temp_free(r_asi);
@@ -2136,7 +2136,7 @@ static inline void gen_stda_asi(TCGv hi, TCGv addr, int insn, int rd)
tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, hi);
r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
r_size = tcg_const_i32(8);
- gen_helper_st_asi(addr, cpu_tmp64, r_asi, r_size);
+ gen_helper_st_asi(cpu_env, addr, cpu_tmp64, r_asi, r_size);
tcg_temp_free(r_size);
tcg_temp_free(r_asi);
}
@@ -2153,7 +2153,7 @@ static inline void gen_ldstub_asi(TCGv dst, TCGv addr, int insn)
r_val = tcg_const_i64(0xffULL);
r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
r_size = tcg_const_i32(1);
- gen_helper_st_asi(addr, r_val, r_asi, r_size);
+ gen_helper_st_asi(cpu_env, addr, r_val, r_asi, r_size);
tcg_temp_free_i32(r_size);
tcg_temp_free_i32(r_asi);
tcg_temp_free_i64(r_val);
@@ -2373,9 +2373,9 @@ static void gen_faligndata(TCGv dst, TCGv gsr, TCGv s1, TCGv s2)
goto nfpu_insn;
/* before an instruction, dc->pc must be static */
-static void disas_sparc_insn(DisasContext * dc)
+static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
{
- unsigned int insn, opc, rs1, rs2, rd;
+ unsigned int opc, rs1, rs2, rd;
TCGv cpu_src1, cpu_src2, cpu_tmp1, cpu_tmp2;
TCGv_i32 cpu_src1_32, cpu_src2_32, cpu_dst_32;
TCGv_i64 cpu_src1_64, cpu_src2_64, cpu_dst_64;
@@ -2383,7 +2383,7 @@ static void disas_sparc_insn(DisasContext * dc)
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
tcg_gen_debug_insn_start(dc->pc);
- insn = ldl_code(dc->pc);
+
opc = GET_FIELD(insn, 0, 1);
rd = GET_FIELD(insn, 2, 6);
@@ -4547,7 +4547,7 @@ static void disas_sparc_insn(DisasContext * dc)
gen_helper_restore(cpu_env);
gen_mov_pc_npc(dc, cpu_cond);
r_const = tcg_const_i32(3);
- gen_helper_check_align(cpu_dst, r_const);
+ gen_helper_check_align(cpu_env, cpu_dst, r_const);
tcg_temp_free_i32(r_const);
tcg_gen_mov_tl(cpu_npc, cpu_dst);
dc->npc = DYNAMIC_PC;
@@ -4577,7 +4577,7 @@ static void disas_sparc_insn(DisasContext * dc)
tcg_temp_free(r_pc);
gen_mov_pc_npc(dc, cpu_cond);
r_const = tcg_const_i32(3);
- gen_helper_check_align(cpu_dst, r_const);
+ gen_helper_check_align(cpu_env, cpu_dst, r_const);
tcg_temp_free_i32(r_const);
tcg_gen_mov_tl(cpu_npc, cpu_dst);
dc->npc = DYNAMIC_PC;
@@ -4592,7 +4592,7 @@ static void disas_sparc_insn(DisasContext * dc)
goto priv_insn;
gen_mov_pc_npc(dc, cpu_cond);
r_const = tcg_const_i32(3);
- gen_helper_check_align(cpu_dst, r_const);
+ gen_helper_check_align(cpu_env, cpu_dst, r_const);
tcg_temp_free_i32(r_const);
tcg_gen_mov_tl(cpu_npc, cpu_dst);
dc->npc = DYNAMIC_PC;
@@ -4696,7 +4696,8 @@ static void disas_sparc_insn(DisasContext * dc)
save_state(dc, cpu_cond);
r_const = tcg_const_i32(7);
- gen_helper_check_align(cpu_addr, r_const); // XXX remove
+ /* XXX remove alignment check */
+ gen_helper_check_align(cpu_env, cpu_addr, r_const);
tcg_temp_free_i32(r_const);
gen_address_mask(dc, cpu_addr);
tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
@@ -4921,7 +4922,7 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, FLOAT128);
r_const = tcg_const_i32(dc->mem_idx);
gen_address_mask(dc, cpu_addr);
- gen_helper_ldqf(cpu_addr, r_const);
+ gen_helper_ldqf(cpu_env, cpu_addr, r_const);
tcg_temp_free_i32(r_const);
gen_op_store_QT0_fpr(QFPREG(rd));
gen_update_fprs_dirty(QFPREG(rd));
@@ -4961,7 +4962,8 @@ static void disas_sparc_insn(DisasContext * dc)
save_state(dc, cpu_cond);
gen_address_mask(dc, cpu_addr);
r_const = tcg_const_i32(7);
- gen_helper_check_align(cpu_addr, r_const); // XXX remove
+ /* XXX remove alignment check */
+ gen_helper_check_align(cpu_env, cpu_addr, r_const);
tcg_temp_free_i32(r_const);
gen_movl_reg_TN(rd + 1, cpu_tmp0);
tcg_gen_concat_tl_i64(cpu_tmp64, cpu_tmp0, cpu_val);
@@ -5065,7 +5067,7 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_load_fpr_QT0(QFPREG(rd));
r_const = tcg_const_i32(dc->mem_idx);
gen_address_mask(dc, cpu_addr);
- gen_helper_stqf(cpu_addr, r_const);
+ gen_helper_stqf(cpu_env, cpu_addr, r_const);
tcg_temp_free_i32(r_const);
}
break;
@@ -5108,7 +5110,7 @@ static void disas_sparc_insn(DisasContext * dc)
goto jmp_insn;
}
r_const = tcg_const_i32(7);
- gen_helper_check_align(cpu_addr, r_const);
+ gen_helper_check_align(cpu_env, cpu_addr, r_const);
tcg_temp_free_i32(r_const);
gen_stf_asi(cpu_addr, insn, 16, QFPREG(rd));
}
@@ -5238,6 +5240,7 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
int j, lj = -1;
int num_insns;
int max_insns;
+ unsigned int insn;
memset(dc, 0, sizeof(DisasContext));
dc->tb = tb;
@@ -5297,7 +5300,8 @@ static inline void gen_intermediate_code_internal(TranslationBlock * tb,
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
last_pc = dc->pc;
- disas_sparc_insn(dc);
+ insn = cpu_ldl_code(env, dc->pc);
+ disas_sparc_insn(dc, insn);
num_insns++;
if (dc->is_br)