summaryrefslogtreecommitdiff
path: root/target-sparc
diff options
context:
space:
mode:
authorChanho Park <chanho61.park@samsung.com>2014-06-26 20:28:10 +0900
committerChanho Park <chanho61.park@samsung.com>2014-07-07 16:25:44 +0900
commita15119db2ff5c2fdfdeb913b297bf8aa3399132e (patch)
tree7d6f779408bb772b11c029ab88000fc01856b599 /target-sparc
parent340f06c9eaee097e626c251bf7a013350649c091 (diff)
downloadqemu-a15119db2ff5c2fdfdeb913b297bf8aa3399132e.tar.gz
qemu-a15119db2ff5c2fdfdeb913b297bf8aa3399132e.tar.bz2
qemu-a15119db2ff5c2fdfdeb913b297bf8aa3399132e.zip
Imported Upstream version 2.0.0upstream/2.0.0
Change-Id: I081766c4314e7893f54fec80b920b1638d15021f
Diffstat (limited to 'target-sparc')
-rw-r--r--target-sparc/cpu.c118
-rw-r--r--target-sparc/cpu.h19
-rw-r--r--target-sparc/helper.c53
-rw-r--r--target-sparc/helper.h22
-rw-r--r--target-sparc/int32_helper.c10
-rw-r--r--target-sparc/int64_helper.c8
-rw-r--r--target-sparc/ldst_helper.c145
-rw-r--r--target-sparc/machine.c3
-rw-r--r--target-sparc/mmu_helper.c60
-rw-r--r--target-sparc/translate.c61
10 files changed, 288 insertions, 211 deletions
diff --git a/target-sparc/cpu.c b/target-sparc/cpu.c
index 47ce60de4..d9f37e9b6 100644
--- a/target-sparc/cpu.c
+++ b/target-sparc/cpu.c
@@ -18,6 +18,7 @@
*/
#include "cpu.h"
+#include "qemu/error-report.h"
//#define DEBUG_FEATURES
@@ -32,8 +33,8 @@ static void sparc_cpu_reset(CPUState *s)
scc->parent_reset(s);
- memset(env, 0, offsetof(CPUSPARCState, breakpoints));
- tlb_flush(env, 1);
+ memset(env, 0, offsetof(CPUSPARCState, version));
+ tlb_flush(s, 1);
env->cwp = 0;
#ifndef TARGET_SPARC64
env->wim = 1;
@@ -69,22 +70,32 @@ static void sparc_cpu_reset(CPUState *s)
env->cache_control = 0;
}
-static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
+static int cpu_sparc_register(SPARCCPU *cpu, const char *cpu_model)
{
+ CPUClass *cc = CPU_GET_CLASS(cpu);
+ CPUSPARCState *env = &cpu->env;
+ char *s = g_strdup(cpu_model);
+ char *featurestr, *name = strtok(s, ",");
sparc_def_t def1, *def = &def1;
+ Error *err = NULL;
- if (cpu_sparc_find_by_name(def, cpu_model) < 0) {
+ if (cpu_sparc_find_by_name(def, name) < 0) {
+ g_free(s);
return -1;
}
env->def = g_new0(sparc_def_t, 1);
memcpy(env->def, def, sizeof(*def));
-#if defined(CONFIG_USER_ONLY)
- if ((env->def->features & CPU_FEATURE_FLOAT)) {
- env->def->features |= CPU_FEATURE_FLOAT128;
+
+ featurestr = strtok(NULL, ",");
+ cc->parse_features(CPU(cpu), featurestr, &err);
+ g_free(s);
+ if (err) {
+ error_report("%s", error_get_pretty(err));
+ error_free(err);
+ return -1;
}
-#endif
- env->cpu_model_str = cpu_model;
+
env->version = def->iu_version;
env->fsr = def->fpu_version;
env->nwindows = def->nwindows;
@@ -104,12 +115,10 @@ static int cpu_sparc_register(CPUSPARCState *env, const char *cpu_model)
SPARCCPU *cpu_sparc_init(const char *cpu_model)
{
SPARCCPU *cpu;
- CPUSPARCState *env;
cpu = SPARC_CPU(object_new(TYPE_SPARC_CPU));
- env = &cpu->env;
- if (cpu_sparc_register(env, cpu_model) < 0) {
+ if (cpu_sparc_register(cpu, cpu_model) < 0) {
object_unref(OBJECT(cpu));
return NULL;
}
@@ -459,7 +468,8 @@ static const sparc_def_t sparc_defs[] = {
.mmu_trcr_mask = 0xffffffff,
.nwindows = 8,
.features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
- CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN,
+ CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL | CPU_FEATURE_POWERDOWN |
+ CPU_FEATURE_CASA,
},
#endif
};
@@ -506,19 +516,13 @@ static void add_flagname_to_bitmaps(const char *flagname, uint32_t *features)
return;
}
}
- fprintf(stderr, "CPU feature %s not found\n", flagname);
+ error_report("CPU feature %s not found", flagname);
}
-static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
+static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *name)
{
unsigned int i;
const sparc_def_t *def = NULL;
- char *s = g_strdup(cpu_model);
- char *featurestr, *name = strtok(s, ",");
- uint32_t plus_features = 0;
- uint32_t minus_features = 0;
- uint64_t iu_version;
- uint32_t fpu_version, mmu_version, nwindows;
for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
if (strcasecmp(name, sparc_defs[i].name) == 0) {
@@ -526,11 +530,24 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
}
}
if (!def) {
- goto error;
+ return -1;
}
memcpy(cpu_def, def, sizeof(*def));
+ return 0;
+}
- featurestr = strtok(NULL, ",");
+static void sparc_cpu_parse_features(CPUState *cs, char *features,
+ Error **errp)
+{
+ SPARCCPU *cpu = SPARC_CPU(cs);
+ sparc_def_t *cpu_def = cpu->env.def;
+ char *featurestr;
+ uint32_t plus_features = 0;
+ uint32_t minus_features = 0;
+ uint64_t iu_version;
+ uint32_t fpu_version, mmu_version, nwindows;
+
+ featurestr = features ? strtok(features, ",") : NULL;
while (featurestr) {
char *val;
@@ -545,8 +562,8 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
iu_version = strtoll(val, &err, 0);
if (!*val || *err) {
- fprintf(stderr, "bad numerical value %s\n", val);
- goto error;
+ error_setg(errp, "bad numerical value %s", val);
+ return;
}
cpu_def->iu_version = iu_version;
#ifdef DEBUG_FEATURES
@@ -557,8 +574,8 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
fpu_version = strtol(val, &err, 0);
if (!*val || *err) {
- fprintf(stderr, "bad numerical value %s\n", val);
- goto error;
+ error_setg(errp, "bad numerical value %s", val);
+ return;
}
cpu_def->fpu_version = fpu_version;
#ifdef DEBUG_FEATURES
@@ -569,8 +586,8 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
mmu_version = strtol(val, &err, 0);
if (!*val || *err) {
- fprintf(stderr, "bad numerical value %s\n", val);
- goto error;
+ error_setg(errp, "bad numerical value %s", val);
+ return;
}
cpu_def->mmu_version = mmu_version;
#ifdef DEBUG_FEATURES
@@ -582,21 +599,21 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
nwindows = strtol(val, &err, 0);
if (!*val || *err || nwindows > MAX_NWINDOWS ||
nwindows < MIN_NWINDOWS) {
- fprintf(stderr, "bad numerical value %s\n", val);
- goto error;
+ error_setg(errp, "bad numerical value %s", val);
+ return;
}
cpu_def->nwindows = nwindows;
#ifdef DEBUG_FEATURES
fprintf(stderr, "nwindows %d\n", nwindows);
#endif
} else {
- fprintf(stderr, "unrecognized feature %s\n", featurestr);
- goto error;
+ error_setg(errp, "unrecognized feature %s", featurestr);
+ return;
}
} else {
- fprintf(stderr, "feature string `%s' not in format "
- "(+feature|-feature|feature=xyz)\n", featurestr);
- goto error;
+ error_setg(errp, "feature string `%s' not in format "
+ "(+feature|-feature|feature=xyz)", featurestr);
+ return;
}
featurestr = strtok(NULL, ",");
}
@@ -605,12 +622,6 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
#ifdef DEBUG_FEATURES
print_features(stderr, fprintf, cpu_def->features, NULL);
#endif
- g_free(s);
- return 0;
-
- error:
- g_free(s);
- return -1;
}
void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf)
@@ -739,9 +750,26 @@ static void sparc_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb)
cpu->env.npc = tb->cs_base;
}
+static bool sparc_cpu_has_work(CPUState *cs)
+{
+ SPARCCPU *cpu = SPARC_CPU(cs);
+ CPUSPARCState *env = &cpu->env;
+
+ return (cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+ cpu_interrupts_enabled(env);
+}
+
static void sparc_cpu_realizefn(DeviceState *dev, Error **errp)
{
SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(dev);
+#if defined(CONFIG_USER_ONLY)
+ SPARCCPU *cpu = SPARC_CPU(dev);
+ CPUSPARCState *env = &cpu->env;
+
+ if ((env->def->features & CPU_FEATURE_FLOAT)) {
+ env->def->features |= CPU_FEATURE_FLOAT128;
+ }
+#endif
qemu_init_vcpu(CPU(dev));
@@ -782,6 +810,8 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
scc->parent_reset = cc->reset;
cc->reset = sparc_cpu_reset;
+ cc->parse_features = sparc_cpu_parse_features;
+ cc->has_work = sparc_cpu_has_work;
cc->do_interrupt = sparc_cpu_do_interrupt;
cc->dump_state = sparc_cpu_dump_state;
#if !defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
@@ -791,7 +821,9 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data)
cc->synchronize_from_tb = sparc_cpu_synchronize_from_tb;
cc->gdb_read_register = sparc_cpu_gdb_read_register;
cc->gdb_write_register = sparc_cpu_gdb_write_register;
-#ifndef CONFIG_USER_ONLY
+#ifdef CONFIG_USER_ONLY
+ cc->handle_mmu_fault = sparc_cpu_handle_mmu_fault;
+#else
cc->do_unassigned_access = sparc_cpu_unassigned_access;
cc->get_phys_page_debug = sparc_cpu_get_phys_page_debug;
#endif
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 41194ec06..f72451d53 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -271,6 +271,7 @@ typedef struct sparc_def_t {
#define CPU_FEATURE_ASR17 (1 << 15)
#define CPU_FEATURE_CACHE_CTRL (1 << 16)
#define CPU_FEATURE_POWERDOWN (1 << 17)
+#define CPU_FEATURE_CASA (1 << 18)
#ifndef TARGET_SPARC64
#define CPU_DEFAULT_FEATURES (CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | \
@@ -282,7 +283,8 @@ typedef struct sparc_def_t {
CPU_FEATURE_MUL | CPU_FEATURE_DIV | \
CPU_FEATURE_FLUSH | CPU_FEATURE_FSQRT | \
CPU_FEATURE_FMUL | CPU_FEATURE_VIS1 | \
- CPU_FEATURE_VIS2 | CPU_FEATURE_FSMULD)
+ CPU_FEATURE_VIS2 | CPU_FEATURE_FSMULD | \
+ CPU_FEATURE_CASA)
enum {
mmu_us_12, // Ultrasparc < III (64 entry TLB)
mmu_us_3, // Ultrasparc III (512 entry TLB)
@@ -370,7 +372,7 @@ struct CPUTimer
uint32_t disabled;
uint64_t disabled_mask;
int64_t clock_offset;
- struct QEMUTimer *qtimer;
+ QEMUTimer *qtimer;
};
typedef struct CPUTimer CPUTimer;
@@ -421,6 +423,7 @@ struct CPUSPARCState {
CPU_COMMON
+ /* Fields from here on are preserved across CPU reset. */
target_ulong version;
uint32_t nwindows;
@@ -519,9 +522,8 @@ SPARCCPU *cpu_sparc_init(const char *cpu_model);
void cpu_sparc_set_id(CPUSPARCState *env, unsigned int cpu);
void sparc_cpu_list(FILE *f, fprintf_function cpu_fprintf);
/* mmu_helper.c */
-int cpu_sparc_handle_mmu_fault(CPUSPARCState *env1, target_ulong address, int rw,
+int sparc_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int rw,
int mmu_idx);
-#define cpu_handle_mmu_fault cpu_sparc_handle_mmu_fault
target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev);
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUSPARCState *env);
@@ -747,15 +749,6 @@ static inline bool tb_am_enabled(int tb_flags)
#endif
}
-static inline bool cpu_has_work(CPUState *cpu)
-{
- SPARCCPU *sparc_cpu = SPARC_CPU(cpu);
- CPUSPARCState *env1 = &sparc_cpu->env;
-
- return (cpu->interrupt_request & CPU_INTERRUPT_HARD) &&
- cpu_interrupts_enabled(env1);
-}
-
#include "exec/exec-all.h"
#endif
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 57c20af47..ae7740bca 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -24,14 +24,18 @@
void helper_raise_exception(CPUSPARCState *env, int tt)
{
- env->exception_index = tt;
- cpu_loop_exit(env);
+ CPUState *cs = CPU(sparc_env_get_cpu(env));
+
+ cs->exception_index = tt;
+ cpu_loop_exit(cs);
}
void helper_debug(CPUSPARCState *env)
{
- env->exception_index = EXCP_DEBUG;
- cpu_loop_exit(env);
+ CPUState *cs = CPU(sparc_env_get_cpu(env));
+
+ cs->exception_index = EXCP_DEBUG;
+ cpu_loop_exit(cs);
}
#ifdef TARGET_SPARC64
@@ -67,6 +71,7 @@ void helper_tick_set_limit(void *opaque, uint64_t limit)
static target_ulong helper_udiv_common(CPUSPARCState *env, target_ulong a,
target_ulong b, int cc)
{
+ SPARCCPU *cpu = sparc_env_get_cpu(env);
int overflow = 0;
uint64_t x0;
uint32_t x1;
@@ -75,13 +80,13 @@ static target_ulong helper_udiv_common(CPUSPARCState *env, target_ulong a,
x1 = (b & 0xffffffff);
if (x1 == 0) {
- cpu_restore_state(env, GETPC());
+ cpu_restore_state(CPU(cpu), GETPC());
helper_raise_exception(env, TT_DIV_ZERO);
}
x0 = x0 / x1;
- if (x0 > 0xffffffff) {
- x0 = 0xffffffff;
+ if (x0 > UINT32_MAX) {
+ x0 = UINT32_MAX;
overflow = 1;
}
@@ -106,6 +111,7 @@ target_ulong helper_udiv_cc(CPUSPARCState *env, target_ulong a, target_ulong b)
static target_ulong helper_sdiv_common(CPUSPARCState *env, target_ulong a,
target_ulong b, int cc)
{
+ SPARCCPU *cpu = sparc_env_get_cpu(env);
int overflow = 0;
int64_t x0;
int32_t x1;
@@ -114,14 +120,17 @@ static target_ulong helper_sdiv_common(CPUSPARCState *env, target_ulong a,
x1 = (b & 0xffffffff);
if (x1 == 0) {
- cpu_restore_state(env, GETPC());
+ cpu_restore_state(CPU(cpu), GETPC());
helper_raise_exception(env, TT_DIV_ZERO);
- }
-
- x0 = x0 / x1;
- if ((int32_t) x0 != x0) {
- x0 = x0 < 0 ? 0x80000000 : 0x7fffffff;
+ } else if (x1 == -1 && x0 == INT64_MIN) {
+ x0 = INT32_MAX;
overflow = 1;
+ } else {
+ x0 = x0 / x1;
+ if ((int32_t) x0 != x0) {
+ x0 = x0 < 0 ? INT32_MIN : INT32_MAX;
+ overflow = 1;
+ }
}
if (cc) {
@@ -147,7 +156,9 @@ int64_t helper_sdivx(CPUSPARCState *env, int64_t a, int64_t b)
{
if (b == 0) {
/* Raise divide by zero trap. */
- cpu_restore_state(env, GETPC());
+ SPARCCPU *cpu = sparc_env_get_cpu(env);
+
+ cpu_restore_state(CPU(cpu), GETPC());
helper_raise_exception(env, TT_DIV_ZERO);
} else if (b == -1) {
/* Avoid overflow trap with i386 divide insn. */
@@ -161,7 +172,9 @@ uint64_t helper_udivx(CPUSPARCState *env, uint64_t a, uint64_t b)
{
if (b == 0) {
/* Raise divide by zero trap. */
- cpu_restore_state(env, GETPC());
+ SPARCCPU *cpu = sparc_env_get_cpu(env);
+
+ cpu_restore_state(CPU(cpu), GETPC());
helper_raise_exception(env, TT_DIV_ZERO);
}
return a / b;
@@ -171,6 +184,7 @@ 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. */
@@ -193,13 +207,14 @@ target_ulong helper_taddcctv(CPUSPARCState *env, target_ulong src1,
return dst;
tag_overflow:
- cpu_restore_state(env, GETPC());
+ cpu_restore_state(CPU(cpu), GETPC());
helper_raise_exception(env, TT_TOVF);
}
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. */
@@ -222,7 +237,7 @@ target_ulong helper_tsubcctv(CPUSPARCState *env, target_ulong src1,
return dst;
tag_overflow:
- cpu_restore_state(env, GETPC());
+ cpu_restore_state(CPU(cpu), GETPC());
helper_raise_exception(env, TT_TOVF);
}
@@ -232,9 +247,9 @@ void helper_power_down(CPUSPARCState *env)
CPUState *cs = CPU(sparc_env_get_cpu(env));
cs->halted = 1;
- env->exception_index = EXCP_HLT;
+ cs->exception_index = EXCP_HLT;
env->pc = env->npc;
env->npc = env->pc + 4;
- cpu_loop_exit(env);
+ cpu_loop_exit(cs);
}
#endif
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 15f73283f..cd8d3fa9f 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -22,7 +22,6 @@ DEF_HELPER_1(popc, tl, tl)
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)
@@ -31,6 +30,9 @@ 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
+#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
+DEF_HELPER_5(cas_asi, tl, env, tl, tl, tl, i32)
+#endif
DEF_HELPER_3(check_align, void, env, tl, i32)
DEF_HELPER_1(debug, void, env)
DEF_HELPER_1(save, void, env)
@@ -103,7 +105,7 @@ DEF_HELPER_3(fmuls, f32, env, f32, f32)
DEF_HELPER_3(fdivs, f32, env, f32, f32)
DEF_HELPER_3(fsmuld, f64, env, f32, f32)
-DEF_HELPER_3(fdmulq, void, env, f64, f64);
+DEF_HELPER_3(fdmulq, void, env, f64, f64)
DEF_HELPER_FLAGS_1(fnegs, TCG_CALL_NO_RWG_SE, f32, f32)
DEF_HELPER_2(fitod, f64, env, s32)
@@ -156,22 +158,22 @@ DEF_HELPER_FLAGS_3(bshuffle, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
DEF_HELPER_FLAGS_2(f ## name ## 32s, TCG_CALL_NO_RWG_SE, \
i32, i32, i32)
-VIS_HELPER(padd);
-VIS_HELPER(psub);
+VIS_HELPER(padd)
+VIS_HELPER(psub)
#define VIS_CMPHELPER(name) \
DEF_HELPER_FLAGS_2(f##name##16, TCG_CALL_NO_RWG_SE, \
i64, i64, i64) \
DEF_HELPER_FLAGS_2(f##name##32, TCG_CALL_NO_RWG_SE, \
i64, i64, i64)
-VIS_CMPHELPER(cmpgt);
-VIS_CMPHELPER(cmpeq);
-VIS_CMPHELPER(cmple);
-VIS_CMPHELPER(cmpne);
+VIS_CMPHELPER(cmpgt)
+VIS_CMPHELPER(cmpeq)
+VIS_CMPHELPER(cmple)
+VIS_CMPHELPER(cmpne)
#endif
#undef F_HELPER_0_1
#undef VIS_HELPER
#undef VIS_CMPHELPER
-DEF_HELPER_1(compute_psr, void, env);
-DEF_HELPER_1(compute_C_icc, i32, env);
+DEF_HELPER_1(compute_psr, void, env)
+DEF_HELPER_1(compute_C_icc, i32, env)
#include "exec/def-helper.h"
diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c
index d5322380c..7c380ba2a 100644
--- a/target-sparc/int32_helper.c
+++ b/target-sparc/int32_helper.c
@@ -62,7 +62,7 @@ void sparc_cpu_do_interrupt(CPUState *cs)
{
SPARCCPU *cpu = SPARC_CPU(cs);
CPUSPARCState *env = &cpu->env;
- int cwp, intno = env->exception_index;
+ int cwp, intno = cs->exception_index;
/* Compute PSR before exposing state. */
if (env->cc_op != CC_OP_FLAGS) {
@@ -105,12 +105,12 @@ void sparc_cpu_do_interrupt(CPUState *cs)
#endif
#if !defined(CONFIG_USER_ONLY)
if (env->psret == 0) {
- if (env->exception_index == 0x80 &&
+ if (cs->exception_index == 0x80 &&
env->def->features & CPU_FEATURE_TA0_SHUTDOWN) {
qemu_system_shutdown_request();
} else {
- cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
- env->exception_index);
+ cpu_abort(cs, "Trap 0x%02x while interrupts disabled, Error state",
+ cs->exception_index);
}
return;
}
@@ -125,7 +125,7 @@ void sparc_cpu_do_interrupt(CPUState *cs)
env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
env->pc = env->tbr;
env->npc = env->pc + 4;
- env->exception_index = -1;
+ cs->exception_index = -1;
#if !defined(CONFIG_USER_ONLY)
/* IRQ acknowledgment */
diff --git a/target-sparc/int64_helper.c b/target-sparc/int64_helper.c
index bf7dd86ab..bf242323a 100644
--- a/target-sparc/int64_helper.c
+++ b/target-sparc/int64_helper.c
@@ -63,7 +63,7 @@ void sparc_cpu_do_interrupt(CPUState *cs)
{
SPARCCPU *cpu = SPARC_CPU(cs);
CPUSPARCState *env = &cpu->env;
- int intno = env->exception_index;
+ int intno = cs->exception_index;
trap_state *tsptr;
/* Compute PSR before exposing state. */
@@ -111,8 +111,8 @@ void sparc_cpu_do_interrupt(CPUState *cs)
#endif
#if !defined(CONFIG_USER_ONLY)
if (env->tl >= env->maxtl) {
- cpu_abort(env, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
- " Error state", env->exception_index, env->tl, env->maxtl);
+ cpu_abort(cs, "Trap 0x%04x while trap level (%d) >= MAXTL (%d),"
+ " Error state", cs->exception_index, env->tl, env->maxtl);
return;
}
#endif
@@ -160,7 +160,7 @@ void sparc_cpu_do_interrupt(CPUState *cs)
env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5);
env->pc = env->tbr;
env->npc = env->pc + 4;
- env->exception_index = -1;
+ cs->exception_index = -1;
}
trap_state *cpu_tsptr(CPUSPARCState* env)
diff --git a/target-sparc/ldst_helper.c b/target-sparc/ldst_helper.c
index 2936b58b3..ec1480257 100644
--- a/target-sparc/ldst_helper.c
+++ b/target-sparc/ldst_helper.c
@@ -141,6 +141,7 @@ static void replace_tlb_entry(SparcTLBEntry *tlb,
/* flush page range if translation is valid */
if (TTE_IS_VALID(tlb->tte)) {
+ CPUState *cs = CPU(sparc_env_get_cpu(env1));
mask = 0xffffffffffffe000ULL;
mask <<= 3 * ((tlb->tte >> 61) & 3);
@@ -149,7 +150,7 @@ static void replace_tlb_entry(SparcTLBEntry *tlb,
va = tlb->tag & mask;
for (offset = 0; offset < size; offset += TARGET_PAGE_SIZE) {
- tlb_flush_page(env1, va + offset);
+ tlb_flush_page(cs, va + offset);
}
}
@@ -447,6 +448,7 @@ static uint64_t leon3_cache_control_ld(CPUSPARCState *env, target_ulong addr,
uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
int sign)
{
+ CPUState *cs = CPU(sparc_env_get_cpu(env));
uint64_t ret = 0;
#if defined(DEBUG_MXCC) || defined(DEBUG_ASI)
uint32_t last_addr = addr;
@@ -583,6 +585,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
}
break;
case 0xb: /* Supervisor data access */
+ case 0x80:
switch (size) {
case 1:
ret = cpu_ldub_kernel(env, addr);
@@ -608,37 +611,37 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
case 0x1c: /* LEON MMU passthrough */
switch (size) {
case 1:
- ret = ldub_phys(addr);
+ ret = ldub_phys(cs->as, addr);
break;
case 2:
- ret = lduw_phys(addr);
+ ret = lduw_phys(cs->as, addr);
break;
default:
case 4:
- ret = ldl_phys(addr);
+ ret = ldl_phys(cs->as, addr);
break;
case 8:
- ret = ldq_phys(addr);
+ ret = ldq_phys(cs->as, addr);
break;
}
break;
case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */
switch (size) {
case 1:
- ret = ldub_phys((hwaddr)addr
+ ret = ldub_phys(cs->as, (hwaddr)addr
| ((hwaddr)(asi & 0xf) << 32));
break;
case 2:
- ret = lduw_phys((hwaddr)addr
+ ret = lduw_phys(cs->as, (hwaddr)addr
| ((hwaddr)(asi & 0xf) << 32));
break;
default:
case 4:
- ret = ldl_phys((hwaddr)addr
+ ret = ldl_phys(cs->as, (hwaddr)addr
| ((hwaddr)(asi & 0xf) << 32));
break;
case 8:
- ret = ldq_phys((hwaddr)addr
+ ret = ldq_phys(cs->as, (hwaddr)addr
| ((hwaddr)(asi & 0xf) << 32));
break;
}
@@ -686,8 +689,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
break;
case 8: /* User code access, XXX */
default:
- cpu_unassigned_access(CPU(sparc_env_get_cpu(env)),
- addr, false, false, asi, size);
+ cpu_unassigned_access(cs, addr, false, false, asi, size);
ret = 0;
break;
}
@@ -715,6 +717,9 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
int size)
{
+ SPARCCPU *cpu = sparc_env_get_cpu(env);
+ CPUState *cs = CPU(cpu);
+
helper_check_align(env, addr, size - 1);
switch (asi) {
case 2: /* SuperSparc MXCC registers and Leon3 cache control */
@@ -771,13 +776,17 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
"%08x: unimplemented access size: %d\n", addr,
size);
}
- env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
+ env->mxccdata[0] = ldq_phys(cs->as,
+ (env->mxccregs[0] & 0xffffffffULL) +
0);
- env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
+ env->mxccdata[1] = ldq_phys(cs->as,
+ (env->mxccregs[0] & 0xffffffffULL) +
8);
- env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
+ env->mxccdata[2] = ldq_phys(cs->as,
+ (env->mxccregs[0] & 0xffffffffULL) +
16);
- env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +
+ env->mxccdata[3] = ldq_phys(cs->as,
+ (env->mxccregs[0] & 0xffffffffULL) +
24);
break;
case 0x01c00200: /* MXCC stream destination */
@@ -788,13 +797,13 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
"%08x: unimplemented access size: %d\n", addr,
size);
}
- stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0,
+ stq_phys(cs->as, (env->mxccregs[1] & 0xffffffffULL) + 0,
env->mxccdata[0]);
- stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8,
+ stq_phys(cs->as, (env->mxccregs[1] & 0xffffffffULL) + 8,
env->mxccdata[1]);
- stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,
+ stq_phys(cs->as, (env->mxccregs[1] & 0xffffffffULL) + 16,
env->mxccdata[2]);
- stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,
+ stq_phys(cs->as, (env->mxccregs[1] & 0xffffffffULL) + 24,
env->mxccdata[3]);
break;
case 0x01c00a00: /* MXCC control register */
@@ -856,13 +865,13 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
DPRINTF_MMU("mmu flush level %d\n", mmulev);
switch (mmulev) {
case 0: /* flush page */
- tlb_flush_page(env, addr & 0xfffff000);
+ tlb_flush_page(CPU(cpu), addr & 0xfffff000);
break;
case 1: /* flush segment (256k) */
case 2: /* flush region (16M) */
case 3: /* flush context (4G) */
case 4: /* flush entire */
- tlb_flush(env, 1);
+ tlb_flush(CPU(cpu), 1);
break;
default:
break;
@@ -887,7 +896,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
disabled mode are invalid in normal mode */
if ((oldreg & (MMU_E | MMU_NF | env->def->mmu_bm)) !=
(env->mmuregs[reg] & (MMU_E | MMU_NF | env->def->mmu_bm))) {
- tlb_flush(env, 1);
+ tlb_flush(CPU(cpu), 1);
}
break;
case 1: /* Context Table Pointer Register */
@@ -898,7 +907,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
if (oldreg != env->mmuregs[reg]) {
/* we flush when the MMU context changes because
QEMU has no MMU context support */
- tlb_flush(env, 1);
+ tlb_flush(CPU(cpu), 1);
}
break;
case 3: /* Synchronous Fault Status Register with Clear */
@@ -949,6 +958,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
}
break;
case 0xb: /* Supervisor data access */
+ case 0x80:
switch (size) {
case 1:
cpu_stb_kernel(env, addr, val);
@@ -1006,17 +1016,17 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
{
switch (size) {
case 1:
- stb_phys(addr, val);
+ stb_phys(cs->as, addr, val);
break;
case 2:
- stw_phys(addr, val);
+ stw_phys(cs->as, addr, val);
break;
case 4:
default:
- stl_phys(addr, val);
+ stl_phys(cs->as, addr, val);
break;
case 8:
- stq_phys(addr, val);
+ stq_phys(cs->as, addr, val);
break;
}
}
@@ -1025,20 +1035,20 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, uint64_t val, int asi,
{
switch (size) {
case 1:
- stb_phys((hwaddr)addr
+ stb_phys(cs->as, (hwaddr)addr
| ((hwaddr)(asi & 0xf) << 32), val);
break;
case 2:
- stw_phys((hwaddr)addr
+ stw_phys(cs->as, (hwaddr)addr
| ((hwaddr)(asi & 0xf) << 32), val);
break;
case 4:
default:
- stl_phys((hwaddr)addr
+ stl_phys(cs->as, (hwaddr)addr
| ((hwaddr)(asi & 0xf) << 32), val);
break;
case 8:
- stq_phys((hwaddr)addr
+ stq_phys(cs->as, (hwaddr)addr
| ((hwaddr)(asi & 0xf) << 32), val);
break;
}
@@ -1284,6 +1294,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
int sign)
{
+ CPUState *cs = CPU(sparc_env_get_cpu(env));
uint64_t ret = 0;
#if defined(DEBUG_ASI)
target_ulong last_addr = addr;
@@ -1317,7 +1328,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
dump_asi("read ", last_addr, asi, size, ret);
#endif
/* env->exception_index is set in get_physical_address_data(). */
- helper_raise_exception(env, env->exception_index);
+ helper_raise_exception(env, cs->exception_index);
}
/* convert nonfaulting load ASIs to normal load ASIs */
@@ -1432,17 +1443,17 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
{
switch (size) {
case 1:
- ret = ldub_phys(addr);
+ ret = ldub_phys(cs->as, addr);
break;
case 2:
- ret = lduw_phys(addr);
+ ret = lduw_phys(cs->as, addr);
break;
case 4:
- ret = ldl_phys(addr);
+ ret = ldl_phys(cs->as, addr);
break;
default:
case 8:
- ret = ldq_phys(addr);
+ ret = ldq_phys(cs->as, addr);
break;
}
break;
@@ -1596,8 +1607,7 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
case 0x5f: /* D-MMU demap, WO */
case 0x77: /* Interrupt vector, WO */
default:
- cpu_unassigned_access(CPU(sparc_env_get_cpu(env)),
- addr, false, false, 1, size);
+ cpu_unassigned_access(cs, addr, false, false, 1, size);
ret = 0;
break;
}
@@ -1653,6 +1663,9 @@ uint64_t helper_ld_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
int asi, int size)
{
+ SPARCCPU *cpu = sparc_env_get_cpu(env);
+ CPUState *cs = CPU(cpu);
+
#ifdef DEBUG_ASI
dump_asi("write", addr, asi, size, val);
#endif
@@ -1803,17 +1816,17 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
{
switch (size) {
case 1:
- stb_phys(addr, val);
+ stb_phys(cs->as, addr, val);
break;
case 2:
- stw_phys(addr, val);
+ stw_phys(cs->as, addr, val);
break;
case 4:
- stl_phys(addr, val);
+ stl_phys(cs->as, addr, val);
break;
case 8:
default:
- stq_phys(addr, val);
+ stq_phys(cs->as, addr, val);
break;
}
}
@@ -1861,7 +1874,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
#ifdef DEBUG_MMU
dump_mmu(stdout, fprintf, env);
#endif
- tlb_flush(env, 1);
+ tlb_flush(CPU(cpu), 1);
}
return;
}
@@ -1950,13 +1963,13 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
env->dmmu.mmu_primary_context = val;
/* can be optimized to only flush MMU_USER_IDX
and MMU_KERNEL_IDX entries */
- tlb_flush(env, 1);
+ tlb_flush(CPU(cpu), 1);
break;
case 2: /* Secondary context */
env->dmmu.mmu_secondary_context = val;
/* can be optimized to only flush MMU_USER_SECONDARY_IDX
and MMU_KERNEL_SECONDARY_IDX entries */
- tlb_flush(env, 1);
+ tlb_flush(CPU(cpu), 1);
break;
case 5: /* TSB access */
DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64 " -> 0x%016"
@@ -2030,8 +2043,7 @@ void helper_st_asi(CPUSPARCState *env, target_ulong addr, target_ulong val,
case 0x8a: /* Primary no-fault LE, RO */
case 0x8b: /* Secondary no-fault LE, RO */
default:
- cpu_unassigned_access(CPU(sparc_env_get_cpu(env)),
- addr, true, false, 1, size);
+ cpu_unassigned_access(cs, addr, true, false, 1, size);
return;
}
}
@@ -2224,33 +2236,35 @@ void helper_stf_asi(CPUSPARCState *env, target_ulong addr, int asi, int size,
}
}
-target_ulong helper_cas_asi(CPUSPARCState *env, 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;
- val2 &= 0xffffffffUL;
- ret = helper_ld_asi(env, addr, asi, 4, 0);
- ret &= 0xffffffffUL;
+ ret = helper_ld_asi(env, addr, asi, 8, 0);
if (val2 == ret) {
- helper_st_asi(env, addr, val1 & 0xffffffffUL, asi, 4);
+ helper_st_asi(env, addr, val1, asi, 8);
}
return ret;
}
+#endif /* TARGET_SPARC64 */
-target_ulong helper_casx_asi(CPUSPARCState *env, target_ulong addr,
- target_ulong val1, target_ulong val2,
- uint32_t asi)
+#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
+target_ulong helper_cas_asi(CPUSPARCState *env, target_ulong addr,
+ target_ulong val1, target_ulong val2, uint32_t asi)
{
target_ulong ret;
- ret = helper_ld_asi(env, addr, asi, 8, 0);
+ val2 &= 0xffffffffUL;
+ ret = helper_ld_asi(env, addr, asi, 4, 0);
+ ret &= 0xffffffffUL;
if (val2 == ret) {
- helper_st_asi(env, addr, val1, asi, 8);
+ helper_st_asi(env, addr, val1 & 0xffffffffUL, asi, 4);
}
return ret;
}
-#endif /* TARGET_SPARC64 */
+#endif /* !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64) */
void helper_ldqf(CPUSPARCState *env, target_ulong addr, int mem_idx)
{
@@ -2385,7 +2399,7 @@ void sparc_cpu_unassigned_access(CPUState *cs, hwaddr addr,
/* flush neverland mappings created during no-fault mode,
so the sequential MMU faults report proper fault types */
if (env->mmuregs[0] & MMU_NF) {
- tlb_flush(env, 1);
+ tlb_flush(cs, 1);
}
}
#else
@@ -2415,12 +2429,13 @@ static void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env,
target_ulong addr, int is_write,
int is_user, uintptr_t retaddr)
{
+ SPARCCPU *cpu = sparc_env_get_cpu(env);
#ifdef DEBUG_UNALIGNED
printf("Unaligned access to 0x" TARGET_FMT_lx " from 0x" TARGET_FMT_lx
"\n", addr, env->pc);
#endif
if (retaddr) {
- cpu_restore_state(env, retaddr);
+ cpu_restore_state(CPU(cpu), retaddr);
}
helper_raise_exception(env, TT_UNALIGNED);
}
@@ -2429,17 +2444,17 @@ static void QEMU_NORETURN do_unaligned_access(CPUSPARCState *env,
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 tlb_fill(CPUState *cs, target_ulong addr, int is_write, int mmu_idx,
uintptr_t retaddr)
{
int ret;
- ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, mmu_idx);
+ ret = sparc_cpu_handle_mmu_fault(cs, addr, is_write, mmu_idx);
if (ret) {
if (retaddr) {
- cpu_restore_state(env, retaddr);
+ cpu_restore_state(cs, retaddr);
}
- cpu_loop_exit(env);
+ cpu_loop_exit(cs);
}
}
#endif
diff --git a/target-sparc/machine.c b/target-sparc/machine.c
index a353dabdd..3f3de4c65 100644
--- a/target-sparc/machine.c
+++ b/target-sparc/machine.c
@@ -112,6 +112,7 @@ void cpu_save(QEMUFile *f, void *opaque)
int cpu_load(QEMUFile *f, void *opaque, int version_id)
{
CPUSPARCState *env = opaque;
+ SPARCCPU *cpu = sparc_env_get_cpu(env);
int i;
uint32_t tmp;
@@ -212,6 +213,6 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_be64s(f, &env->ssr);
cpu_get_timer(f, env->hstick);
#endif
- tlb_flush(env, 1);
+ tlb_flush(CPU(cpu), 1);
return 0;
}
diff --git a/target-sparc/mmu_helper.c b/target-sparc/mmu_helper.c
index ef12a0a8d..61afbcf04 100644
--- a/target-sparc/mmu_helper.c
+++ b/target-sparc/mmu_helper.c
@@ -25,13 +25,13 @@
#if defined(CONFIG_USER_ONLY)
-int cpu_sparc_handle_mmu_fault(CPUSPARCState *env1, target_ulong address, int rw,
+int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
int mmu_idx)
{
if (rw & 2) {
- env1->exception_index = TT_TFAULT;
+ cs->exception_index = TT_TFAULT;
} else {
- env1->exception_index = TT_DFAULT;
+ cs->exception_index = TT_DFAULT;
}
return 1;
}
@@ -86,6 +86,7 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
uint32_t pde;
int error_code = 0, is_dirty, is_user;
unsigned long page_offset;
+ CPUState *cs = CPU(sparc_env_get_cpu(env));
is_user = mmu_idx == MMU_USER_IDX;
@@ -108,7 +109,7 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
/* SPARC reference MMU table walk: Context table->L1->L2->PTE */
/* Context base + context number */
pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
- pde = ldl_phys(pde_ptr);
+ pde = ldl_phys(cs->as, pde_ptr);
/* Ctx pde */
switch (pde & PTE_ENTRYTYPE_MASK) {
@@ -120,7 +121,7 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
return 4 << 2;
case 1: /* L0 PDE */
pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
- pde = ldl_phys(pde_ptr);
+ pde = ldl_phys(cs->as, pde_ptr);
switch (pde & PTE_ENTRYTYPE_MASK) {
default:
@@ -130,7 +131,7 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
return (1 << 8) | (4 << 2);
case 1: /* L1 PDE */
pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
- pde = ldl_phys(pde_ptr);
+ pde = ldl_phys(cs->as, pde_ptr);
switch (pde & PTE_ENTRYTYPE_MASK) {
default:
@@ -140,7 +141,7 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
return (2 << 8) | (4 << 2);
case 1: /* L2 PDE */
pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
- pde = ldl_phys(pde_ptr);
+ pde = ldl_phys(cs->as, pde_ptr);
switch (pde & PTE_ENTRYTYPE_MASK) {
default:
@@ -179,7 +180,7 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
if (is_dirty) {
pde |= PG_MODIFIED_MASK;
}
- stl_phys_notdirty(pde_ptr, pde);
+ stl_phys_notdirty(cs->as, pde_ptr, pde);
}
/* the page can be put in the TLB */
@@ -197,9 +198,11 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
}
/* Perform address translation */
-int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw,
+int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
int mmu_idx)
{
+ SPARCCPU *cpu = SPARC_CPU(cs);
+ CPUSPARCState *env = &cpu->env;
hwaddr paddr;
target_ulong vaddr;
target_ulong page_size;
@@ -211,10 +214,10 @@ int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw,
vaddr = address;
if (error_code == 0) {
#ifdef DEBUG_MMU
- printf("Translate at " TARGET_FMT_lx " -> " TARGET_FMT_plx ", vaddr "
+ printf("Translate at %" VADDR_PRIx " -> " TARGET_FMT_plx ", vaddr "
TARGET_FMT_lx "\n", address, paddr, vaddr);
#endif
- tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
+ tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, page_size);
return 0;
}
@@ -230,13 +233,13 @@ int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw,
neverland. Fake/overridden mappings will be flushed when
switching to normal mode. */
prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- tlb_set_page(env, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
+ tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, TARGET_PAGE_SIZE);
return 0;
} else {
if (rw & 2) {
- env->exception_index = TT_TFAULT;
+ cs->exception_index = TT_TFAULT;
} else {
- env->exception_index = TT_DFAULT;
+ cs->exception_index = TT_DFAULT;
}
return 1;
}
@@ -244,13 +247,14 @@ int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw,
target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev)
{
+ CPUState *cs = CPU(sparc_env_get_cpu(env));
hwaddr pde_ptr;
uint32_t pde;
/* Context base + context number */
pde_ptr = (hwaddr)(env->mmuregs[1] << 4) +
(env->mmuregs[2] << 2);
- pde = ldl_phys(pde_ptr);
+ pde = ldl_phys(cs->as, pde_ptr);
switch (pde & PTE_ENTRYTYPE_MASK) {
default:
@@ -263,7 +267,7 @@ target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev)
return pde;
}
pde_ptr = ((address >> 22) & ~3) + ((pde & ~3) << 4);
- pde = ldl_phys(pde_ptr);
+ pde = ldl_phys(cs->as, pde_ptr);
switch (pde & PTE_ENTRYTYPE_MASK) {
default:
@@ -277,7 +281,7 @@ target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev)
return pde;
}
pde_ptr = ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
- pde = ldl_phys(pde_ptr);
+ pde = ldl_phys(cs->as, pde_ptr);
switch (pde & PTE_ENTRYTYPE_MASK) {
default:
@@ -291,7 +295,7 @@ target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev)
return pde;
}
pde_ptr = ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
- pde = ldl_phys(pde_ptr);
+ pde = ldl_phys(cs->as, pde_ptr);
switch (pde & PTE_ENTRYTYPE_MASK) {
default:
@@ -317,7 +321,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUSPARCState *env)
uint32_t pde;
pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
- pde = ldl_phys(pde_ptr);
+ pde = ldl_phys(cs->as, pde_ptr);
(*cpu_fprintf)(f, "Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
(hwaddr)env->mmuregs[1] << 4, env->mmuregs[2]);
for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
@@ -485,6 +489,7 @@ static int get_physical_address_data(CPUSPARCState *env,
hwaddr *physical, int *prot,
target_ulong address, int rw, int mmu_idx)
{
+ CPUState *cs = CPU(sparc_env_get_cpu(env));
unsigned int i;
uint64_t context;
uint64_t sfsr = 0;
@@ -549,10 +554,10 @@ static int get_physical_address_data(CPUSPARCState *env,
if (do_fault) {
/* faults above are reported with TT_DFAULT. */
- env->exception_index = TT_DFAULT;
+ cs->exception_index = TT_DFAULT;
} else if (!TTE_IS_W_OK(env->dtlb[i].tte) && (rw == 1)) {
do_fault = 1;
- env->exception_index = TT_DPROT;
+ cs->exception_index = TT_DPROT;
trace_mmu_helper_dprot(address, context, mmu_idx, env->tl);
}
@@ -596,7 +601,7 @@ static int get_physical_address_data(CPUSPARCState *env,
* - JPS1: SFAR updated and some fields of SFSR updated
*/
env->dmmu.tag_access = (address & ~0x1fffULL) | context;
- env->exception_index = TT_DMISS;
+ cs->exception_index = TT_DMISS;
return 1;
}
@@ -604,6 +609,7 @@ static int get_physical_address_code(CPUSPARCState *env,
hwaddr *physical, int *prot,
target_ulong address, int mmu_idx)
{
+ CPUState *cs = CPU(sparc_env_get_cpu(env));
unsigned int i;
uint64_t context;
@@ -647,7 +653,7 @@ static int get_physical_address_code(CPUSPARCState *env,
/* FIXME: ASI field in SFSR must be set */
env->immu.sfsr |= SFSR_FT_PRIV_BIT | SFSR_VALID_BIT;
- env->exception_index = TT_TFAULT;
+ cs->exception_index = TT_TFAULT;
env->immu.tag_access = (address & ~0x1fffULL) | context;
@@ -665,7 +671,7 @@ static int get_physical_address_code(CPUSPARCState *env,
/* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
env->immu.tag_access = (address & ~0x1fffULL) | context;
- env->exception_index = TT_TMISS;
+ cs->exception_index = TT_TMISS;
return 1;
}
@@ -703,9 +709,11 @@ static int get_physical_address(CPUSPARCState *env, hwaddr *physical,
}
/* Perform address translation */
-int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw,
+int sparc_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
int mmu_idx)
{
+ SPARCCPU *cpu = SPARC_CPU(cs);
+ CPUSPARCState *env = &cpu->env;
target_ulong vaddr;
hwaddr paddr;
target_ulong page_size;
@@ -721,7 +729,7 @@ int cpu_sparc_handle_mmu_fault(CPUSPARCState *env, target_ulong address, int rw,
env->dmmu.mmu_primary_context,
env->dmmu.mmu_secondary_context);
- tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
+ tlb_set_page(cs, vaddr, paddr, prot, mmu_idx, page_size);
return 0;
}
/* XXX */
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 093e0e2c7..2de1c4a58 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -322,7 +322,7 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num,
tcg_gen_goto_tb(tb_num);
tcg_gen_movi_tl(cpu_pc, pc);
tcg_gen_movi_tl(cpu_npc, npc);
- tcg_gen_exit_tb((tcg_target_long)tb + tb_num);
+ tcg_gen_exit_tb((uintptr_t)tb + tb_num);
} else {
/* jump to another page: currently not optimized */
tcg_gen_movi_tl(cpu_pc, pc);
@@ -2107,18 +2107,6 @@ static inline void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
tcg_temp_free_i64(t64);
}
-static inline void gen_cas_asi(DisasContext *dc, TCGv addr,
- TCGv val2, int insn, int rd)
-{
- TCGv val1 = gen_load_gpr(dc, rd);
- TCGv dst = gen_dest_gpr(dc, rd);
- TCGv_i32 r_asi = gen_get_asi(insn, addr);
-
- gen_helper_cas_asi(dst, cpu_env, addr, val1, val2, r_asi);
- tcg_temp_free_i32(r_asi);
- gen_store_gpr(dc, rd, dst);
-}
-
static inline void gen_casx_asi(DisasContext *dc, TCGv addr,
TCGv val2, int insn, int rd)
{
@@ -2229,6 +2217,22 @@ static inline void gen_stda_asi(DisasContext *dc, TCGv hi, TCGv addr,
#endif
#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
+static inline void gen_cas_asi(DisasContext *dc, TCGv addr,
+ TCGv val2, int insn, int rd)
+{
+ TCGv val1 = gen_load_gpr(dc, rd);
+ TCGv dst = gen_dest_gpr(dc, rd);
+#ifdef TARGET_SPARC64
+ TCGv_i32 r_asi = gen_get_asi(insn, addr);
+#else
+ TCGv_i32 r_asi = tcg_const_i32(GET_FIELD(insn, 19, 26));
+#endif
+
+ gen_helper_cas_asi(dst, cpu_env, addr, val1, val2, r_asi);
+ tcg_temp_free_i32(r_asi);
+ gen_store_gpr(dc, rd, dst);
+}
+
static inline void gen_ldstub_asi(TCGv dst, TCGv addr, int insn)
{
TCGv_i64 r_val;
@@ -3626,6 +3630,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
if ((rd == 0x13) && (dc->def->features &
CPU_FEATURE_POWERDOWN)) {
/* LEON3 power-down */
+ save_state(dc);
gen_helper_power_down(cpu_env);
}
break;
@@ -5102,11 +5107,6 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
}
gen_stf_asi(cpu_addr, insn, 8, DFPREG(rd));
break;
- case 0x3c: /* V9 casa */
- rs2 = GET_FIELD(insn, 27, 31);
- cpu_src2 = gen_load_gpr(dc, rs2);
- gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd);
- break;
case 0x3e: /* V9 casxa */
rs2 = GET_FIELD(insn, 27, 31);
cpu_src2 = gen_load_gpr(dc, rs2);
@@ -5119,6 +5119,22 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn)
case 0x37: /* stdc */
goto ncp_insn;
#endif
+#if !defined(CONFIG_USER_ONLY) || defined(TARGET_SPARC64)
+ case 0x3c: /* V9 or LEON3 casa */
+#ifndef TARGET_SPARC64
+ CHECK_IU_FEATURE(dc, CASA);
+ if (IS_IMM) {
+ goto illegal_insn;
+ }
+ if (!supervisor(dc)) {
+ goto priv_insn;
+ }
+#endif
+ rs2 = GET_FIELD(insn, 27, 31);
+ cpu_src2 = gen_load_gpr(dc, rs2);
+ gen_cas_asi(dc, cpu_addr, cpu_src2, insn, rd);
+ break;
+#endif
default:
goto illegal_insn;
}
@@ -5254,8 +5270,8 @@ static inline void gen_intermediate_code_internal(SPARCCPU *cpu,
max_insns = CF_COUNT_MASK;
gen_tb_start();
do {
- if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
- QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
+ if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
+ QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
if (bp->pc == dc->pc) {
if (dc->pc != pc_start)
save_state(dc);
@@ -5456,11 +5472,6 @@ void gen_intermediate_code_init(CPUSPARCState *env)
offsetof(CPUSPARCState, fpr[i]),
fregnames[i]);
}
-
- /* register helpers */
-
-#define GEN_HELPER 2
-#include "helper.h"
}
}