aboutsummaryrefslogtreecommitdiff
path: root/target-sparc/op_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-sparc/op_helper.c')
-rw-r--r--target-sparc/op_helper.c88
1 files changed, 55 insertions, 33 deletions
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 15af27ba1..8962e3821 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -79,9 +79,14 @@
#define CACHE_CTRL_FD (1 << 22) /* Flush Data cache (Write only) */
#define CACHE_CTRL_DS (1 << 23) /* Data cache snoop enable */
-#if defined(CONFIG_USER_ONLY) && defined(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);
+#else
+#ifdef TARGET_SPARC64
static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
- int is_asi, int size);
+ int is_asi, int size);
+#endif
#endif
#if defined(TARGET_SPARC64) && !defined(CONFIG_USER_ONLY)
@@ -287,7 +292,8 @@ static inline int is_translating_asi(int asi)
*/
switch (asi) {
case 0x04 ... 0x11:
- case 0x18 ... 0x19:
+ case 0x16 ... 0x19:
+ case 0x1E ... 0x1F:
case 0x24 ... 0x2C:
case 0x70 ... 0x73:
case 0x78 ... 0x79:
@@ -525,6 +531,7 @@ typedef union {
uint16_t w[4];
int16_t sw[4];
uint32_t l[2];
+ uint64_t ll;
float64 d;
} vis64;
@@ -789,32 +796,34 @@ VIS_HELPER(helper_fpadd, FADD)
VIS_HELPER(helper_fpsub, FSUB)
#define VIS_CMPHELPER(name, F) \
- void name##16(void) \
+ uint64_t name##16(void) \
{ \
vis64 s, d; \
\
s.d = DT0; \
d.d = DT1; \
\
- d.VIS_W64(0) = F(d.VIS_W64(0), s.VIS_W64(0))? 1: 0; \
- d.VIS_W64(0) |= F(d.VIS_W64(1), s.VIS_W64(1))? 2: 0; \
- d.VIS_W64(0) |= F(d.VIS_W64(2), s.VIS_W64(2))? 4: 0; \
- d.VIS_W64(0) |= F(d.VIS_W64(3), s.VIS_W64(3))? 8: 0; \
+ d.VIS_W64(0) = F(s.VIS_W64(0), d.VIS_W64(0)) ? 1 : 0; \
+ d.VIS_W64(0) |= F(s.VIS_W64(1), d.VIS_W64(1)) ? 2 : 0; \
+ d.VIS_W64(0) |= F(s.VIS_W64(2), d.VIS_W64(2)) ? 4 : 0; \
+ d.VIS_W64(0) |= F(s.VIS_W64(3), d.VIS_W64(3)) ? 8 : 0; \
+ d.VIS_W64(1) = d.VIS_W64(2) = d.VIS_W64(3) = 0; \
\
- DT0 = d.d; \
+ return d.ll; \
} \
\
- void name##32(void) \
+ uint64_t name##32(void) \
{ \
vis64 s, d; \
\
s.d = DT0; \
d.d = DT1; \
\
- d.VIS_L64(0) = F(d.VIS_L64(0), s.VIS_L64(0))? 1: 0; \
- d.VIS_L64(0) |= F(d.VIS_L64(1), s.VIS_L64(1))? 2: 0; \
+ d.VIS_L64(0) = F(s.VIS_L64(0), d.VIS_L64(0)) ? 1 : 0; \
+ d.VIS_L64(0) |= F(s.VIS_L64(1), d.VIS_L64(1)) ? 2 : 0; \
+ d.VIS_L64(1) = 0; \
\
- DT0 = d.d; \
+ return d.ll; \
}
#define FCMPGT(a, b) ((a) > (b))
@@ -2558,24 +2567,30 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
helper_check_align(addr, size - 1);
addr = asi_address_mask(env, asi, addr);
- switch (asi) {
- case 0x82: // Primary no-fault
- case 0x8a: // Primary no-fault LE
- case 0x83: // Secondary no-fault
- case 0x8b: // Secondary no-fault LE
- {
- /* secondary space access has lowest asi bit equal to 1 */
- int access_mmu_idx = ( asi & 1 ) ? MMU_KERNEL_IDX
- : MMU_KERNEL_SECONDARY_IDX;
+ /* process nonfaulting loads first */
+ if ((asi & 0xf6) == 0x82) {
+ int mmu_idx;
+
+ /* secondary space access has lowest asi bit equal to 1 */
+ if (env->pstate & PS_PRIV) {
+ mmu_idx = (asi & 1) ? MMU_KERNEL_SECONDARY_IDX : MMU_KERNEL_IDX;
+ } else {
+ mmu_idx = (asi & 1) ? MMU_USER_SECONDARY_IDX : MMU_USER_IDX;
+ }
- if (cpu_get_phys_page_nofault(env, addr, access_mmu_idx) == -1ULL) {
+ if (cpu_get_phys_page_nofault(env, addr, mmu_idx) == -1ULL) {
#ifdef DEBUG_ASI
- dump_asi("read ", last_addr, asi, size, ret);
+ dump_asi("read ", last_addr, asi, size, ret);
#endif
- return 0;
- }
+ /* env->exception_index is set in get_physical_address_data(). */
+ raise_exception(env->exception_index);
}
- // Fall through
+
+ /* convert nonfaulting load ASIs to normal load ASIs */
+ asi &= ~0x02;
+ }
+
+ switch (asi) {
case 0x10: // As if user primary
case 0x11: // As if user secondary
case 0x18: // As if user primary LE
@@ -2853,8 +2868,6 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
case 0x1d: // Bypass, non-cacheable LE
case 0x88: // Primary LE
case 0x89: // Secondary LE
- case 0x8a: // Primary no-fault LE
- case 0x8b: // Secondary no-fault LE
switch(size) {
case 2:
ret = bswap16(ret);
@@ -4231,8 +4244,8 @@ void tlb_fill(target_ulong addr, int is_write, int mmu_idx, void *retaddr)
#ifndef TARGET_SPARC64
#if !defined(CONFIG_USER_ONLY)
-void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
- int is_asi, int size)
+static void do_unassigned_access(target_phys_addr_t addr, int is_write,
+ int is_exec, int is_asi, int size)
{
CPUState *saved_env;
int fault_type;
@@ -4297,8 +4310,8 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
static void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
int is_asi, int size)
#else
-void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
- int is_asi, int size)
+static void do_unassigned_access(target_phys_addr_t addr, int is_write,
+ int is_exec, int is_asi, int size)
#endif
{
CPUState *saved_env;
@@ -4347,3 +4360,12 @@ void helper_tick_set_limit(void *opaque, uint64_t limit)
#endif
}
#endif
+
+#if !defined(CONFIG_USER_ONLY)
+void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr,
+ int is_write, int is_exec, int is_asi, int size)
+{
+ env = env1;
+ do_unassigned_access(addr, is_write, is_exec, is_asi, size);
+}
+#endif