diff options
Diffstat (limited to 'target-sparc/op_helper.c')
-rw-r--r-- | target-sparc/op_helper.c | 88 |
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 |