diff options
Diffstat (limited to 'target-sparc')
| -rw-r--r-- | target-sparc/cpu.h | 39 | ||||
| -rw-r--r-- | target-sparc/exec.h | 15 | ||||
| -rw-r--r-- | target-sparc/helper.c | 153 | ||||
| -rw-r--r-- | target-sparc/helper.h | 4 | ||||
| -rw-r--r-- | target-sparc/op_helper.c | 118 | ||||
| -rw-r--r-- | target-sparc/translate.c | 163 |
6 files changed, 360 insertions, 132 deletions
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 22ee2743d7..a51863cf07 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -290,18 +290,51 @@ enum { #endif #define TTE_VALID_BIT (1ULL << 63) +#define TTE_NFO_BIT (1ULL << 60) #define TTE_USED_BIT (1ULL << 41) #define TTE_LOCKED_BIT (1ULL << 6) +#define TTE_SIDEEFFECT_BIT (1ULL << 3) +#define TTE_PRIV_BIT (1ULL << 2) +#define TTE_W_OK_BIT (1ULL << 1) #define TTE_GLOBAL_BIT (1ULL << 0) #define TTE_IS_VALID(tte) ((tte) & TTE_VALID_BIT) +#define TTE_IS_NFO(tte) ((tte) & TTE_NFO_BIT) #define TTE_IS_USED(tte) ((tte) & TTE_USED_BIT) #define TTE_IS_LOCKED(tte) ((tte) & TTE_LOCKED_BIT) +#define TTE_IS_SIDEEFFECT(tte) ((tte) & TTE_SIDEEFFECT_BIT) +#define TTE_IS_PRIV(tte) ((tte) & TTE_PRIV_BIT) +#define TTE_IS_W_OK(tte) ((tte) & TTE_W_OK_BIT) #define TTE_IS_GLOBAL(tte) ((tte) & TTE_GLOBAL_BIT) #define TTE_SET_USED(tte) ((tte) |= TTE_USED_BIT) #define TTE_SET_UNUSED(tte) ((tte) &= ~TTE_USED_BIT) +#define TTE_PGSIZE(tte) (((tte) >> 61) & 3ULL) +#define TTE_PA(tte) ((tte) & 0x1ffffffe000ULL) + +#define SFSR_NF_BIT (1ULL << 24) /* JPS1 NoFault */ +#define SFSR_TM_BIT (1ULL << 15) /* JPS1 TLB Miss */ +#define SFSR_FT_VA_IMMU_BIT (1ULL << 13) /* USIIi VA out of range (IMMU) */ +#define SFSR_FT_VA_DMMU_BIT (1ULL << 12) /* USIIi VA out of range (DMMU) */ +#define SFSR_FT_NFO_BIT (1ULL << 11) /* NFO page access */ +#define SFSR_FT_ILL_BIT (1ULL << 10) /* illegal LDA/STA ASI */ +#define SFSR_FT_ATOMIC_BIT (1ULL << 9) /* atomic op on noncacheable area */ +#define SFSR_FT_NF_E_BIT (1ULL << 8) /* NF access on side effect area */ +#define SFSR_FT_PRIV_BIT (1ULL << 7) /* privilege violation */ +#define SFSR_PR_BIT (1ULL << 3) /* privilege mode */ +#define SFSR_WRITE_BIT (1ULL << 2) /* write access mode */ +#define SFSR_OW_BIT (1ULL << 1) /* status overwritten */ +#define SFSR_VALID_BIT (1ULL << 0) /* status valid */ + +#define SFSR_ASI_SHIFT 16 /* 23:16 ASI value */ +#define SFSR_ASI_MASK (0xffULL << SFSR_ASI_SHIFT) +#define SFSR_CT_PRIMARY (0ULL << 4) /* 5:4 context type */ +#define SFSR_CT_SECONDARY (1ULL << 4) +#define SFSR_CT_NUCLEUS (2ULL << 4) +#define SFSR_CT_NOTRANS (3ULL << 4) +#define SFSR_CT_MASK (3ULL << 4) + typedef struct SparcTLBEntry { uint64_t tag; uint64_t tte; @@ -510,12 +543,14 @@ static inline int tlb_compare_context(const SparcTLBEntry *tlb, /* cpu-exec.c */ #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); +void cpu_unassigned_access(CPUState *env1, target_phys_addr_t addr, + int is_write, int is_exec, int is_asi, int size); +#if defined(TARGET_SPARC64) target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr, int mmu_idx); #endif +#endif int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc); #define cpu_init cpu_sparc_init diff --git a/target-sparc/exec.h b/target-sparc/exec.h deleted file mode 100644 index 2395b0092f..0000000000 --- a/target-sparc/exec.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef EXEC_SPARC_H -#define EXEC_SPARC_H 1 -#include "config.h" -#include "dyngen-exec.h" - -register struct CPUSPARCState *env asm(AREG0); - -#include "cpu.h" -#include "exec-all.h" - -#if !defined(CONFIG_USER_ONLY) -#include "softmmu_exec.h" -#endif /* !defined(CONFIG_USER_ONLY) */ - -#endif diff --git a/target-sparc/helper.c b/target-sparc/helper.c index 7eea1acbd5..efab885b83 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -378,7 +378,7 @@ static inline int ultrasparc_tag_match(SparcTLBEntry *tlb, { uint64_t mask; - switch ((tlb->tte >> 61) & 3) { + switch (TTE_PGSIZE(tlb->tte)) { default: case 0x0: // 8k mask = 0xffffffffffffe000ULL; @@ -413,6 +413,7 @@ static int get_physical_address_data(CPUState *env, { unsigned int i; uint64_t context; + uint64_t sfsr = 0; int is_user = (mmu_idx == MMU_USER_IDX || mmu_idx == MMU_USER_SECONDARY_IDX); @@ -427,54 +428,88 @@ static int get_physical_address_data(CPUState *env, case MMU_USER_IDX: case MMU_KERNEL_IDX: context = env->dmmu.mmu_primary_context & 0x1fff; + sfsr |= SFSR_CT_PRIMARY; break; case MMU_USER_SECONDARY_IDX: case MMU_KERNEL_SECONDARY_IDX: context = env->dmmu.mmu_secondary_context & 0x1fff; + sfsr |= SFSR_CT_SECONDARY; break; case MMU_NUCLEUS_IDX: + sfsr |= SFSR_CT_NUCLEUS; + /* FALLTHRU */ default: context = 0; break; } + if (rw == 1) { + sfsr |= SFSR_WRITE_BIT; + } else if (rw == 4) { + sfsr |= SFSR_NF_BIT; + } + for (i = 0; i < 64; i++) { // ctx match, vaddr match, valid? if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) { - - uint8_t fault_type = 0; + int do_fault = 0; // access ok? - if ((env->dtlb[i].tte & 0x4) && is_user) { - fault_type |= 1; /* privilege violation */ - env->exception_index = TT_DFAULT; + /* multiple bits in SFSR.FT may be set on TT_DFAULT */ + if (TTE_IS_PRIV(env->dtlb[i].tte) && is_user) { + do_fault = 1; + sfsr |= SFSR_FT_PRIV_BIT; /* privilege violation */ DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64 " mmu_idx=%d tl=%d\n", address, context, mmu_idx, env->tl); - } else if (!(env->dtlb[i].tte & 0x2) && (rw == 1)) { + } + if (rw == 4) { + if (TTE_IS_SIDEEFFECT(env->dtlb[i].tte)) { + do_fault = 1; + sfsr |= SFSR_FT_NF_E_BIT; + } + } else { + if (TTE_IS_NFO(env->dtlb[i].tte)) { + do_fault = 1; + sfsr |= SFSR_FT_NFO_BIT; + } + } + + if (do_fault) { + /* faults above are reported with TT_DFAULT. */ + env->exception_index = TT_DFAULT; + } else if (!TTE_IS_W_OK(env->dtlb[i].tte) && (rw == 1)) { + do_fault = 1; env->exception_index = TT_DPROT; DPRINTF_MMU("DPROT at %" PRIx64 " context %" PRIx64 " mmu_idx=%d tl=%d\n", address, context, mmu_idx, env->tl); - } else { + } + + if (!do_fault) { *prot = PAGE_READ; - if (env->dtlb[i].tte & 0x2) + if (TTE_IS_W_OK(env->dtlb[i].tte)) { *prot |= PAGE_WRITE; + } TTE_SET_USED(env->dtlb[i].tte); return 0; } - if (env->dmmu.sfsr & 1) /* Fault status register */ - env->dmmu.sfsr = 2; /* overflow (not read before - another fault) */ + if (env->dmmu.sfsr & SFSR_VALID_BIT) { /* Fault status register */ + sfsr |= SFSR_OW_BIT; /* overflow (not read before + another fault) */ + } - env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1; + if (env->pstate & PS_PRIV) { + sfsr |= SFSR_PR_BIT; + } - env->dmmu.sfsr |= (fault_type << 7); + /* FIXME: ASI field in SFSR must be set */ + env->dmmu.sfsr = sfsr | SFSR_VALID_BIT; env->dmmu.sfar = address; /* Fault address register */ @@ -487,6 +522,11 @@ static int get_physical_address_data(CPUState *env, DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n", address, context); + /* + * On MMU misses: + * - UltraSPARC IIi: SFSR and SFAR unmodified + * - JPS1: SFAR updated and some fields of SFSR updated + */ env->dmmu.tag_access = (address & ~0x1fffULL) | context; env->exception_index = TT_DMISS; return 1; @@ -522,11 +562,23 @@ static int get_physical_address_code(CPUState *env, if (ultrasparc_tag_match(&env->itlb[i], address, context, physical)) { // access ok? - if ((env->itlb[i].tte & 0x4) && is_user) { - if (env->immu.sfsr) /* Fault status register */ - env->immu.sfsr = 2; /* overflow (not read before - another fault) */ - env->immu.sfsr |= (is_user << 3) | 1; + if (TTE_IS_PRIV(env->itlb[i].tte) && is_user) { + /* Fault status register */ + if (env->immu.sfsr & SFSR_VALID_BIT) { + env->immu.sfsr = SFSR_OW_BIT; /* overflow (not read before + another fault) */ + } else { + env->immu.sfsr = 0; + } + if (env->pstate & PS_PRIV) { + env->immu.sfsr |= SFSR_PR_BIT; + } + if (env->tl > 0) { + env->immu.sfsr |= SFSR_CT_NUCLEUS; + } + + /* FIXME: ASI field in SFSR must be set */ + env->immu.sfsr |= SFSR_FT_PRIV_BIT | SFSR_VALID_BIT; env->exception_index = TT_TFAULT; env->immu.tag_access = (address & ~0x1fffULL) | context; @@ -632,7 +684,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env) } else { (*cpu_fprintf)(f, "DMMU dump\n"); for (i = 0; i < 64; i++) { - switch ((env->dtlb[i].tte >> 61) & 3) { + switch (TTE_PGSIZE(env->dtlb[i].tte)) { default: case 0x0: mask = " 8k"; @@ -647,16 +699,17 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env) mask = " 4M"; break; } - if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) { - (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64 + if (TTE_IS_VALID(env->dtlb[i].tte)) { + (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %llx" ", %s, %s, %s, %s, ctx %" PRId64 " %s\n", i, env->dtlb[i].tag & (uint64_t)~0x1fffULL, - env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL, + TTE_PA(env->dtlb[i].tte), mask, - env->dtlb[i].tte & 0x4? "priv": "user", - env->dtlb[i].tte & 0x2? "RW": "RO", - env->dtlb[i].tte & 0x40? "locked": "unlocked", + TTE_IS_PRIV(env->dtlb[i].tte) ? "priv" : "user", + TTE_IS_W_OK(env->dtlb[i].tte) ? "RW" : "RO", + TTE_IS_LOCKED(env->dtlb[i].tte) ? + "locked" : "unlocked", env->dtlb[i].tag & (uint64_t)0x1fffULL, TTE_IS_GLOBAL(env->dtlb[i].tte)? "global" : "local"); @@ -668,7 +721,7 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env) } else { (*cpu_fprintf)(f, "IMMU dump\n"); for (i = 0; i < 64; i++) { - switch ((env->itlb[i].tte >> 61) & 3) { + switch (TTE_PGSIZE(env->itlb[i].tte)) { default: case 0x0: mask = " 8k"; @@ -683,15 +736,16 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env) mask = " 4M"; break; } - if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) { - (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64 + if (TTE_IS_VALID(env->itlb[i].tte)) { + (*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %llx" ", %s, %s, %s, ctx %" PRId64 " %s\n", i, env->itlb[i].tag & (uint64_t)~0x1fffULL, - env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL, + TTE_PA(env->itlb[i].tte), mask, - env->itlb[i].tte & 0x4? "priv": "user", - env->itlb[i].tte & 0x40? "locked": "unlocked", + TTE_IS_PRIV(env->itlb[i].tte) ? "priv" : "user", + TTE_IS_LOCKED(env->itlb[i].tte) ? + "locked" : "unlocked", env->itlb[i].tag & (uint64_t)0x1fffULL, TTE_IS_GLOBAL(env->itlb[i].tte)? "global" : "local"); @@ -705,26 +759,43 @@ void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env) #if !defined(CONFIG_USER_ONLY) +static int cpu_sparc_get_phys_page(CPUState *env, target_phys_addr_t *phys, + target_ulong addr, int rw, int mmu_idx) +{ + target_ulong page_size; + int prot, access_index; + + return get_physical_address(env, phys, &prot, &access_index, addr, rw, + mmu_idx, &page_size); +} + +#if defined(TARGET_SPARC64) target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr, int mmu_idx) { target_phys_addr_t phys_addr; - target_ulong page_size; - int prot, access_index; - if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, - mmu_idx, &page_size) != 0) - if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, - 0, mmu_idx, &page_size) != 0) - return -1; - if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED) + if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 4, mmu_idx) != 0) { return -1; + } return phys_addr; } +#endif target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) { - return cpu_get_phys_page_nofault(env, addr, cpu_mmu_index(env)); + target_phys_addr_t phys_addr; + int mmu_idx = cpu_mmu_index(env); + + if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 2, mmu_idx) != 0) { + if (cpu_sparc_get_phys_page(env, &phys_addr, addr, 0, mmu_idx) != 0) { + return -1; + } + } + if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED) { + return -1; + } + return phys_addr; } #endif diff --git a/target-sparc/helper.h b/target-sparc/helper.h index 023f4d6023..2d36af3a31 100644 --- a/target-sparc/helper.h +++ b/target-sparc/helper.h @@ -148,8 +148,8 @@ F_HELPER_0_0(expand); VIS_HELPER(padd); VIS_HELPER(psub); #define VIS_CMPHELPER(name) \ - F_HELPER_0_0(name##16); \ - F_HELPER_0_0(name##32) + DEF_HELPER_0(f##name##16, i64); \ + DEF_HELPER_0(f##name##32, i64) VIS_CMPHELPER(cmpgt); VIS_CMPHELPER(cmpeq); VIS_CMPHELPER(cmple); diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index 15af27ba1f..5aeca2b06d 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -1,8 +1,13 @@ -#include "exec.h" +#include "cpu.h" +#include "dyngen-exec.h" #include "host-utils.h" #include "helper.h" #include "sysemu.h" +#if !defined(CONFIG_USER_ONLY) +#include "softmmu_exec.h" +#endif + //#define DEBUG_MMU //#define DEBUG_MXCC //#define DEBUG_UNALIGNED @@ -79,9 +84,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 +297,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 +536,7 @@ typedef union { uint16_t w[4]; int16_t sw[4]; uint32_t l[2]; + uint64_t ll; float64 d; } vis64; @@ -789,32 +801,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 +2572,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; - if (cpu_get_phys_page_nofault(env, addr, access_mmu_idx) == -1ULL) { + /* 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, 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 +2873,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,16 +4249,11 @@ 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; - /* XXX: hack to restore env in all cases, even if not called from - generated code */ - saved_env = env; - env = cpu_single_env; #ifdef DEBUG_UNASSIGNED if (is_asi) printf("Unassigned mem %s access of %d byte%s to " TARGET_FMT_plx @@ -4288,8 +4301,6 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, if (env->mmuregs[0] & MMU_NF) { tlb_flush(env, 1); } - - env = saved_env; } #endif #else @@ -4297,17 +4308,10 @@ 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; - - /* XXX: hack to restore env in all cases, even if not called from - generated code */ - saved_env = env; - env = cpu_single_env; - #ifdef DEBUG_UNASSIGNED printf("Unassigned mem access to " TARGET_FMT_plx " from " TARGET_FMT_lx "\n", addr, env->pc); @@ -4317,8 +4321,6 @@ void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec, raise_exception(TT_CODE_ACCESS); else raise_exception(TT_DATA_ACCESS); - - env = saved_env; } #endif @@ -4347,3 +4349,19 @@ 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) +{ + CPUState *saved_env; + + saved_env = env; + env = env1; + /* Ignore unassigned accesses outside of CPU context */ + if (env1) { + do_unassigned_access(addr, is_write, is_exec, is_asi, size); + } + env = saved_env; +} +#endif diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 27c2cf98e8..958fbc5a9d 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -1558,6 +1558,13 @@ static int gen_trap_ifnofpu(DisasContext *dc, TCGv r_cond) return 0; } +static inline void gen_update_fprs_dirty(int rd) +{ +#if defined(TARGET_SPARC64) + tcg_gen_ori_i32(cpu_fprs, cpu_fprs, (rd < 32) ? 1 : 2); +#endif +} + static inline void gen_op_clear_ieee_excp_and_FTT(void) { tcg_gen_andi_tl(cpu_fsr, cpu_fsr, FSR_FTT_CEXC_NMASK); @@ -2351,12 +2358,15 @@ static void disas_sparc_insn(DisasContext * dc) switch (xop) { case 0x1: /* fmovs */ tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x5: /* fnegs */ gen_helper_fnegs(cpu_fpr[rd], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x9: /* fabss */ gen_helper_fabss(cpu_fpr[rd], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x29: /* fsqrts */ CHECK_FPU_FEATURE(dc, FSQRT); @@ -2364,6 +2374,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fsqrts(cpu_tmp32, cpu_fpr[rs2]); gen_helper_check_ieee_exceptions(); tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32); + gen_update_fprs_dirty(rd); break; case 0x2a: /* fsqrtd */ CHECK_FPU_FEATURE(dc, FSQRT); @@ -2372,6 +2383,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fsqrtd(); gen_helper_check_ieee_exceptions(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x2b: /* fsqrtq */ CHECK_FPU_FEATURE(dc, FLOAT128); @@ -2380,12 +2392,14 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fsqrtq(); gen_helper_check_ieee_exceptions(); gen_op_store_QT0_fpr(QFPREG(rd)); + gen_update_fprs_dirty(QFPREG(rd)); break; case 0x41: /* fadds */ gen_clear_float_exceptions(); gen_helper_fadds(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]); gen_helper_check_ieee_exceptions(); tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32); + gen_update_fprs_dirty(rd); break; case 0x42: /* faddd */ gen_op_load_fpr_DT0(DFPREG(rs1)); @@ -2394,6 +2408,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_faddd(); gen_helper_check_ieee_exceptions(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x43: /* faddq */ CHECK_FPU_FEATURE(dc, FLOAT128); @@ -2403,12 +2418,14 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_faddq(); gen_helper_check_ieee_exceptions(); gen_op_store_QT0_fpr(QFPREG(rd)); + gen_update_fprs_dirty(QFPREG(rd)); break; case 0x45: /* fsubs */ gen_clear_float_exceptions(); gen_helper_fsubs(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]); gen_helper_check_ieee_exceptions(); tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32); + gen_update_fprs_dirty(rd); break; case 0x46: /* fsubd */ gen_op_load_fpr_DT0(DFPREG(rs1)); @@ -2417,6 +2434,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fsubd(); gen_helper_check_ieee_exceptions(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x47: /* fsubq */ CHECK_FPU_FEATURE(dc, FLOAT128); @@ -2426,6 +2444,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fsubq(); gen_helper_check_ieee_exceptions(); gen_op_store_QT0_fpr(QFPREG(rd)); + gen_update_fprs_dirty(QFPREG(rd)); break; case 0x49: /* fmuls */ CHECK_FPU_FEATURE(dc, FMUL); @@ -2433,6 +2452,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fmuls(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]); gen_helper_check_ieee_exceptions(); tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32); + gen_update_fprs_dirty(rd); break; case 0x4a: /* fmuld */ CHECK_FPU_FEATURE(dc, FMUL); @@ -2442,6 +2462,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fmuld(); gen_helper_check_ieee_exceptions(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x4b: /* fmulq */ CHECK_FPU_FEATURE(dc, FLOAT128); @@ -2452,12 +2473,14 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fmulq(); gen_helper_check_ieee_exceptions(); gen_op_store_QT0_fpr(QFPREG(rd)); + gen_update_fprs_dirty(QFPREG(rd)); break; case 0x4d: /* fdivs */ gen_clear_float_exceptions(); gen_helper_fdivs(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]); gen_helper_check_ieee_exceptions(); tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32); + gen_update_fprs_dirty(rd); break; case 0x4e: /* fdivd */ gen_op_load_fpr_DT0(DFPREG(rs1)); @@ -2466,6 +2489,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fdivd(); gen_helper_check_ieee_exceptions(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x4f: /* fdivq */ CHECK_FPU_FEATURE(dc, FLOAT128); @@ -2475,6 +2499,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fdivq(); gen_helper_check_ieee_exceptions(); gen_op_store_QT0_fpr(QFPREG(rd)); + gen_update_fprs_dirty(QFPREG(rd)); break; case 0x69: /* fsmuld */ CHECK_FPU_FEATURE(dc, FSMULD); @@ -2482,6 +2507,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fsmuld(cpu_fpr[rs1], cpu_fpr[rs2]); gen_helper_check_ieee_exceptions(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x6e: /* fdmulq */ CHECK_FPU_FEATURE(dc, FLOAT128); @@ -2491,12 +2517,14 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fdmulq(); gen_helper_check_ieee_exceptions(); gen_op_store_QT0_fpr(QFPREG(rd)); + gen_update_fprs_dirty(QFPREG(rd)); break; case 0xc4: /* fitos */ gen_clear_float_exceptions(); gen_helper_fitos(cpu_tmp32, cpu_fpr[rs2]); gen_helper_check_ieee_exceptions(); tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32); + gen_update_fprs_dirty(rd); break; case 0xc6: /* fdtos */ gen_op_load_fpr_DT1(DFPREG(rs2)); @@ -2504,6 +2532,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fdtos(cpu_tmp32); gen_helper_check_ieee_exceptions(); tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32); + gen_update_fprs_dirty(rd); break; case 0xc7: /* fqtos */ CHECK_FPU_FEATURE(dc, FLOAT128); @@ -2512,14 +2541,17 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fqtos(cpu_tmp32); gen_helper_check_ieee_exceptions(); tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32); + gen_update_fprs_dirty(rd); break; case 0xc8: /* fitod */ gen_helper_fitod(cpu_fpr[rs2]); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0xc9: /* fstod */ gen_helper_fstod(cpu_fpr[rs2]); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0xcb: /* fqtod */ CHECK_FPU_FEATURE(dc, FLOAT128); @@ -2528,28 +2560,33 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fqtod(); gen_helper_check_ieee_exceptions(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0xcc: /* fitoq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_helper_fitoq(cpu_fpr[rs2]); gen_op_store_QT0_fpr(QFPREG(rd)); + gen_update_fprs_dirty(QFPREG(rd)); break; case 0xcd: /* fstoq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_helper_fstoq(cpu_fpr[rs2]); gen_op_store_QT0_fpr(QFPREG(rd)); + gen_update_fprs_dirty(QFPREG(rd)); break; case 0xce: /* fdtoq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fdtoq(); gen_op_store_QT0_fpr(QFPREG(rd)); + gen_update_fprs_dirty(QFPREG(rd)); break; case 0xd1: /* fstoi */ gen_clear_float_exceptions(); gen_helper_fstoi(cpu_tmp32, cpu_fpr[rs2]); gen_helper_check_ieee_exceptions(); tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32); + gen_update_fprs_dirty(rd); break; case 0xd2: /* fdtoi */ gen_op_load_fpr_DT1(DFPREG(rs2)); @@ -2557,6 +2594,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fdtoi(cpu_tmp32); gen_helper_check_ieee_exceptions(); tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32); + gen_update_fprs_dirty(rd); break; case 0xd3: /* fqtoi */ CHECK_FPU_FEATURE(dc, FLOAT128); @@ -2565,12 +2603,14 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fqtoi(cpu_tmp32); gen_helper_check_ieee_exceptions(); tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32); + gen_update_fprs_dirty(rd); break; #ifdef TARGET_SPARC64 case 0x2: /* V9 fmovd */ tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)]); tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs2) + 1]); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x3: /* V9 fmovq */ CHECK_FPU_FEATURE(dc, FLOAT128); @@ -2581,34 +2621,40 @@ static void disas_sparc_insn(DisasContext * dc) cpu_fpr[QFPREG(rs2) + 2]); tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3], cpu_fpr[QFPREG(rs2) + 3]); + gen_update_fprs_dirty(QFPREG(rd)); break; case 0x6: /* V9 fnegd */ gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fnegd(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x7: /* V9 fnegq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT1(QFPREG(rs2)); gen_helper_fnegq(); gen_op_store_QT0_fpr(QFPREG(rd)); + gen_update_fprs_dirty(QFPREG(rd)); break; case 0xa: /* V9 fabsd */ gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fabsd(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0xb: /* V9 fabsq */ CHECK_FPU_FEATURE(dc, FLOAT128); gen_op_load_fpr_QT1(QFPREG(rs2)); gen_helper_fabsq(); gen_op_store_QT0_fpr(QFPREG(rd)); + gen_update_fprs_dirty(QFPREG(rd)); break; case 0x81: /* V9 fstox */ gen_clear_float_exceptions(); gen_helper_fstox(cpu_fpr[rs2]); gen_helper_check_ieee_exceptions(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x82: /* V9 fdtox */ gen_op_load_fpr_DT1(DFPREG(rs2)); @@ -2616,6 +2662,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fdtox(); gen_helper_check_ieee_exceptions(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x83: /* V9 fqtox */ CHECK_FPU_FEATURE(dc, FLOAT128); @@ -2624,6 +2671,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fqtox(); gen_helper_check_ieee_exceptions(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x84: /* V9 fxtos */ gen_op_load_fpr_DT1(DFPREG(rs2)); @@ -2631,6 +2679,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fxtos(cpu_tmp32); gen_helper_check_ieee_exceptions(); tcg_gen_mov_i32(cpu_fpr[rd], cpu_tmp32); + gen_update_fprs_dirty(rd); break; case 0x88: /* V9 fxtod */ gen_op_load_fpr_DT1(DFPREG(rs2)); @@ -2638,6 +2687,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fxtod(); gen_helper_check_ieee_exceptions(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x8c: /* V9 fxtoq */ CHECK_FPU_FEATURE(dc, FLOAT128); @@ -2646,6 +2696,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_fxtoq(); gen_helper_check_ieee_exceptions(); gen_op_store_QT0_fpr(QFPREG(rd)); + gen_update_fprs_dirty(QFPREG(rd)); break; #endif default: @@ -2672,6 +2723,7 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_brcondi_tl(gen_tcg_cond_reg[cond], cpu_src1, 0, l1); tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); gen_set_label(l1); break; } else if ((xop & 0x11f) == 0x006) { // V9 fmovdr @@ -2684,6 +2736,7 @@ static void disas_sparc_insn(DisasContext * dc) 0, l1); tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)]); tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs2) + 1]); + gen_update_fprs_dirty(DFPREG(rd)); gen_set_label(l1); break; } else if ((xop & 0x11f) == 0x007) { // V9 fmovqr @@ -2699,6 +2752,7 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 1], cpu_fpr[QFPREG(rs2) + 1]); tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 2], cpu_fpr[QFPREG(rs2) + 2]); tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3], cpu_fpr[QFPREG(rs2) + 3]); + gen_update_fprs_dirty(QFPREG(rd)); gen_set_label(l1); break; } @@ -2717,6 +2771,7 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \ 0, l1); \ tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]); \ + gen_update_fprs_dirty(rd); \ gen_set_label(l1); \ tcg_temp_free(r_cond); \ } @@ -2735,6 +2790,7 @@ static void disas_sparc_insn(DisasContext * dc) cpu_fpr[DFPREG(rs2)]); \ tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1], \ cpu_fpr[DFPREG(rs2) + 1]); \ + gen_update_fprs_dirty(DFPREG(rd)); \ gen_set_label(l1); \ tcg_temp_free(r_cond); \ } @@ -2757,6 +2813,7 @@ static void disas_sparc_insn(DisasContext * dc) cpu_fpr[QFPREG(rs2) + 2]); \ tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3], \ cpu_fpr[QFPREG(rs2) + 3]); \ + gen_update_fprs_dirty(QFPREG(rd)); \ gen_set_label(l1); \ tcg_temp_free(r_cond); \ } @@ -2815,6 +2872,7 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_brcondi_tl(TCG_COND_EQ, r_cond, \ 0, l1); \ tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]); \ + gen_update_fprs_dirty(rd); \ gen_set_label(l1); \ tcg_temp_free(r_cond); \ } @@ -2833,6 +2891,7 @@ static void disas_sparc_insn(DisasContext * dc) cpu_fpr[DFPREG(rs2)]); \ tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1], \ cpu_fpr[DFPREG(rs2) + 1]); \ + gen_update_fprs_dirty(DFPREG(rd)); \ gen_set_label(l1); \ tcg_temp_free(r_cond); \ } @@ -2855,6 +2914,7 @@ static void disas_sparc_insn(DisasContext * dc) cpu_fpr[QFPREG(rs2) + 2]); \ tcg_gen_mov_i32(cpu_fpr[QFPREG(rd) + 3], \ cpu_fpr[QFPREG(rs2) + 3]); \ + gen_update_fprs_dirty(QFPREG(rd)); \ gen_set_label(l1); \ tcg_temp_free(r_cond); \ } @@ -2864,6 +2924,7 @@ static void disas_sparc_insn(DisasContext * dc) break; case 0x102: /* V9 fmovdcc %icc */ FMOVDCC(0); + break; case 0x103: /* V9 fmovqcc %icc */ CHECK_FPU_FEATURE(dc, FLOAT128); FMOVQCC(0); @@ -3789,57 +3850,57 @@ static void disas_sparc_insn(DisasContext * dc) CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); - gen_helper_fcmple16(); - gen_op_store_DT0_fpr(DFPREG(rd)); + gen_helper_fcmple16(cpu_dst); + gen_movl_TN_reg(rd, cpu_dst); break; case 0x022: /* VIS I fcmpne16 */ CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); - gen_helper_fcmpne16(); - gen_op_store_DT0_fpr(DFPREG(rd)); + gen_helper_fcmpne16(cpu_dst); + gen_movl_TN_reg(rd, cpu_dst); break; case 0x024: /* VIS I fcmple32 */ CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); - gen_helper_fcmple32(); - gen_op_store_DT0_fpr(DFPREG(rd)); + gen_helper_fcmple32(cpu_dst); + gen_movl_TN_reg(rd, cpu_dst); break; case 0x026: /* VIS I fcmpne32 */ CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); - gen_helper_fcmpne32(); - gen_op_store_DT0_fpr(DFPREG(rd)); + gen_helper_fcmpne32(cpu_dst); + gen_movl_TN_reg(rd, cpu_dst); break; case 0x028: /* VIS I fcmpgt16 */ CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); - gen_helper_fcmpgt16(); - gen_op_store_DT0_fpr(DFPREG(rd)); + gen_helper_fcmpgt16(cpu_dst); + gen_movl_TN_reg(rd, cpu_dst); break; case 0x02a: /* VIS I fcmpeq16 */ CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); - gen_helper_fcmpeq16(); - gen_op_store_DT0_fpr(DFPREG(rd)); + gen_helper_fcmpeq16(cpu_dst); + gen_movl_TN_reg(rd, cpu_dst); break; case 0x02c: /* VIS I fcmpgt32 */ CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); - gen_helper_fcmpgt32(); - gen_op_store_DT0_fpr(DFPREG(rd)); + gen_helper_fcmpgt32(cpu_dst); + gen_movl_TN_reg(rd, cpu_dst); break; case 0x02e: /* VIS I fcmpeq32 */ CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs1)); gen_op_load_fpr_DT1(DFPREG(rs2)); - gen_helper_fcmpeq32(); - gen_op_store_DT0_fpr(DFPREG(rd)); + gen_helper_fcmpeq32(cpu_dst); + gen_movl_TN_reg(rd, cpu_dst); break; case 0x031: /* VIS I fmul8x16 */ CHECK_FPU_FEATURE(dc, VIS1); @@ -3847,6 +3908,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fmul8x16(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x033: /* VIS I fmul8x16au */ CHECK_FPU_FEATURE(dc, VIS1); @@ -3854,6 +3916,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fmul8x16au(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x035: /* VIS I fmul8x16al */ CHECK_FPU_FEATURE(dc, VIS1); @@ -3861,6 +3924,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fmul8x16al(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x036: /* VIS I fmul8sux16 */ CHECK_FPU_FEATURE(dc, VIS1); @@ -3868,6 +3932,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fmul8sux16(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x037: /* VIS I fmul8ulx16 */ CHECK_FPU_FEATURE(dc, VIS1); @@ -3875,6 +3940,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fmul8ulx16(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x038: /* VIS I fmuld8sux16 */ CHECK_FPU_FEATURE(dc, VIS1); @@ -3882,6 +3948,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fmuld8sux16(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x039: /* VIS I fmuld8ulx16 */ CHECK_FPU_FEATURE(dc, VIS1); @@ -3889,6 +3956,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fmuld8ulx16(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x03a: /* VIS I fpack32 */ case 0x03b: /* VIS I fpack16 */ @@ -3902,6 +3970,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_faligndata(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x04b: /* VIS I fpmerge */ CHECK_FPU_FEATURE(dc, VIS1); @@ -3909,6 +3978,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fpmerge(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x04c: /* VIS II bshuffle */ // XXX @@ -3919,6 +3989,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fexpand(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x050: /* VIS I fpadd16 */ CHECK_FPU_FEATURE(dc, VIS1); @@ -3926,11 +3997,13 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fpadd16(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x051: /* VIS I fpadd16s */ CHECK_FPU_FEATURE(dc, VIS1); gen_helper_fpadd16s(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x052: /* VIS I fpadd32 */ CHECK_FPU_FEATURE(dc, VIS1); @@ -3938,11 +4011,13 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fpadd32(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x053: /* VIS I fpadd32s */ CHECK_FPU_FEATURE(dc, VIS1); gen_helper_fpadd32s(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x054: /* VIS I fpsub16 */ CHECK_FPU_FEATURE(dc, VIS1); @@ -3950,11 +4025,13 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fpsub16(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x055: /* VIS I fpsub16s */ CHECK_FPU_FEATURE(dc, VIS1); gen_helper_fpsub16s(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x056: /* VIS I fpsub32 */ CHECK_FPU_FEATURE(dc, VIS1); @@ -3962,31 +4039,38 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_load_fpr_DT1(DFPREG(rs2)); gen_helper_fpsub32(); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x057: /* VIS I fpsub32s */ CHECK_FPU_FEATURE(dc, VIS1); gen_helper_fpsub32s(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x060: /* VIS I fzero */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_movi_i32(cpu_fpr[DFPREG(rd)], 0); tcg_gen_movi_i32(cpu_fpr[DFPREG(rd) + 1], 0); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x061: /* VIS I fzeros */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_movi_i32(cpu_fpr[rd], 0); + gen_update_fprs_dirty(rd); break; case 0x062: /* VIS I fnor */ CHECK_FPU_FEATURE(dc, VIS1); - tcg_gen_nor_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1)], + tcg_gen_nor_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)], cpu_fpr[DFPREG(rs2)]); - tcg_gen_nor_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1) + 1], + tcg_gen_nor_i32(cpu_fpr[DFPREG(rd) + 1], + cpu_fpr[DFPREG(rs1) + 1], cpu_fpr[DFPREG(rs2) + 1]); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x063: /* VIS I fnors */ CHECK_FPU_FEATURE(dc, VIS1); - tcg_gen_nor_i32(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]); + tcg_gen_nor_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x064: /* VIS I fandnot2 */ CHECK_FPU_FEATURE(dc, VIS1); @@ -3995,20 +4079,24 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_andc_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs1) + 1], cpu_fpr[DFPREG(rs2) + 1]); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x065: /* VIS I fandnot2s */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_andc_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x066: /* VIS I fnot2 */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_not_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs2)]); tcg_gen_not_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs2) + 1]); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x067: /* VIS I fnot2s */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_not_i32(cpu_fpr[rd], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x068: /* VIS I fandnot1 */ CHECK_FPU_FEATURE(dc, VIS1); @@ -4017,20 +4105,24 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_andc_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs2) + 1], cpu_fpr[DFPREG(rs1) + 1]); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x069: /* VIS I fandnot1s */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_andc_i32(cpu_fpr[rd], cpu_fpr[rs2], cpu_fpr[rs1]); + gen_update_fprs_dirty(rd); break; case 0x06a: /* VIS I fnot1 */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_not_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)]); tcg_gen_not_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs1) + 1]); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x06b: /* VIS I fnot1s */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_not_i32(cpu_fpr[rd], cpu_fpr[rs1]); + gen_update_fprs_dirty(rd); break; case 0x06c: /* VIS I fxor */ CHECK_FPU_FEATURE(dc, VIS1); @@ -4039,21 +4131,26 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_xor_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs1) + 1], cpu_fpr[DFPREG(rs2) + 1]); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x06d: /* VIS I fxors */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_xor_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x06e: /* VIS I fnand */ CHECK_FPU_FEATURE(dc, VIS1); - tcg_gen_nand_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1)], + tcg_gen_nand_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)], cpu_fpr[DFPREG(rs2)]); - tcg_gen_nand_i32(cpu_tmp32, cpu_fpr[DFPREG(rs1) + 1], + tcg_gen_nand_i32(cpu_fpr[DFPREG(rd) + 1], + cpu_fpr[DFPREG(rs1) + 1], cpu_fpr[DFPREG(rs2) + 1]); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x06f: /* VIS I fnands */ CHECK_FPU_FEATURE(dc, VIS1); - tcg_gen_nand_i32(cpu_tmp32, cpu_fpr[rs1], cpu_fpr[rs2]); + tcg_gen_nand_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x070: /* VIS I fand */ CHECK_FPU_FEATURE(dc, VIS1); @@ -4062,10 +4159,12 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_and_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs1) + 1], cpu_fpr[DFPREG(rs2) + 1]); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x071: /* VIS I fands */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_and_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x072: /* VIS I fxnor */ CHECK_FPU_FEATURE(dc, VIS1); @@ -4075,21 +4174,25 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_xori_i32(cpu_tmp32, cpu_fpr[DFPREG(rs2) + 1], -1); tcg_gen_xor_i32(cpu_fpr[DFPREG(rd) + 1], cpu_tmp32, cpu_fpr[DFPREG(rs1) + 1]); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x073: /* VIS I fxnors */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_xori_i32(cpu_tmp32, cpu_fpr[rs2], -1); tcg_gen_xor_i32(cpu_fpr[rd], cpu_tmp32, cpu_fpr[rs1]); + gen_update_fprs_dirty(rd); break; case 0x074: /* VIS I fsrc1 */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_mov_i32(cpu_fpr[DFPREG(rd)], cpu_fpr[DFPREG(rs1)]); tcg_gen_mov_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs1) + 1]); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x075: /* VIS I fsrc1s */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs1]); + gen_update_fprs_dirty(rd); break; case 0x076: /* VIS I fornot2 */ CHECK_FPU_FEATURE(dc, VIS1); @@ -4098,19 +4201,23 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_orc_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs1) + 1], cpu_fpr[DFPREG(rs2) + 1]); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x077: /* VIS I fornot2s */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_orc_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x078: /* VIS I fsrc2 */ CHECK_FPU_FEATURE(dc, VIS1); gen_op_load_fpr_DT0(DFPREG(rs2)); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x079: /* VIS I fsrc2s */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_mov_i32(cpu_fpr[rd], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x07a: /* VIS I fornot1 */ CHECK_FPU_FEATURE(dc, VIS1); @@ -4119,10 +4226,12 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_orc_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs2) + 1], cpu_fpr[DFPREG(rs1) + 1]); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x07b: /* VIS I fornot1s */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_orc_i32(cpu_fpr[rd], cpu_fpr[rs2], cpu_fpr[rs1]); + gen_update_fprs_dirty(rd); break; case 0x07c: /* VIS I for */ CHECK_FPU_FEATURE(dc, VIS1); @@ -4131,19 +4240,23 @@ static void disas_sparc_insn(DisasContext * dc) tcg_gen_or_i32(cpu_fpr[DFPREG(rd) + 1], cpu_fpr[DFPREG(rs1) + 1], cpu_fpr[DFPREG(rs2) + 1]); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x07d: /* VIS I fors */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_or_i32(cpu_fpr[rd], cpu_fpr[rs1], cpu_fpr[rs2]); + gen_update_fprs_dirty(rd); break; case 0x07e: /* VIS I fone */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_movi_i32(cpu_fpr[DFPREG(rd)], -1); tcg_gen_movi_i32(cpu_fpr[DFPREG(rd) + 1], -1); + gen_update_fprs_dirty(DFPREG(rd)); break; case 0x07f: /* VIS I fones */ CHECK_FPU_FEATURE(dc, VIS1); tcg_gen_movi_i32(cpu_fpr[rd], -1); + gen_update_fprs_dirty(rd); break; case 0x080: /* VIS I shutdown */ case 0x081: /* VIS II siam */ @@ -4489,6 +4602,7 @@ static void disas_sparc_insn(DisasContext * dc) } save_state(dc, cpu_cond); gen_ldf_asi(cpu_addr, insn, 4, rd); + gen_update_fprs_dirty(rd); goto skip_move; case 0x33: /* V9 lddfa */ if (gen_trap_ifnofpu(dc, cpu_cond)) { @@ -4496,6 +4610,7 @@ static void disas_sparc_insn(DisasContext * dc) } save_state(dc, cpu_cond); gen_ldf_asi(cpu_addr, insn, 8, DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); goto skip_move; case 0x3d: /* V9 prefetcha, no effect */ goto skip_move; @@ -4506,6 +4621,7 @@ static void disas_sparc_insn(DisasContext * dc) } save_state(dc, cpu_cond); gen_ldf_asi(cpu_addr, insn, 16, QFPREG(rd)); + gen_update_fprs_dirty(QFPREG(rd)); goto skip_move; #endif default: @@ -4524,6 +4640,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_address_mask(dc, cpu_addr); tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx); tcg_gen_trunc_tl_i32(cpu_fpr[rd], cpu_tmp0); + gen_update_fprs_dirty(rd); break; case 0x21: /* ldfsr, V9 ldxfsr */ #ifdef TARGET_SPARC64 @@ -4553,6 +4670,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_ldqf(cpu_addr, r_const); tcg_temp_free_i32(r_const); gen_op_store_QT0_fpr(QFPREG(rd)); + gen_update_fprs_dirty(QFPREG(rd)); } break; case 0x23: /* lddf, load double fpreg */ @@ -4564,6 +4682,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_helper_lddf(cpu_addr, r_const); tcg_temp_free_i32(r_const); gen_op_store_DT0_fpr(DFPREG(rd)); + gen_update_fprs_dirty(DFPREG(rd)); } break; default: |