aboutsummaryrefslogtreecommitdiff
path: root/target-sparc/ldst_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-sparc/ldst_helper.c')
-rw-r--r--target-sparc/ldst_helper.c433
1 files changed, 242 insertions, 191 deletions
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