diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-07-23 14:27:54 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-07-23 14:27:54 +0000 |
commit | 8346901560d96edf94b803fd3f94db940ad370b3 (patch) | |
tree | 4f7736383fd41291f63d97c92767409330a7acb9 /target-sparc | |
parent | b7c7b18129e137bd24240800d7fac02eee3b1edf (diff) |
sparc64 fixes (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1514 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-sparc')
-rw-r--r-- | target-sparc/cpu.h | 21 | ||||
-rw-r--r-- | target-sparc/exec.h | 3 | ||||
-rw-r--r-- | target-sparc/helper.c | 226 | ||||
-rw-r--r-- | target-sparc/op.c | 82 | ||||
-rw-r--r-- | target-sparc/op_helper.c | 174 | ||||
-rw-r--r-- | target-sparc/op_mem.h | 16 | ||||
-rw-r--r-- | target-sparc/translate.c | 249 |
7 files changed, 576 insertions, 195 deletions
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 2eb900dfe4..999d5d7e68 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -6,9 +6,11 @@ #if !defined(TARGET_SPARC64) #define TARGET_LONG_BITS 32 #define TARGET_FPREGS 32 +#define TARGET_PAGE_BITS 12 /* 4k */ #else #define TARGET_LONG_BITS 64 #define TARGET_FPREGS 64 +#define TARGET_PAGE_BITS 12 /* XXX */ #endif #define TARGET_FPREG_T float @@ -35,6 +37,7 @@ #define TT_TRAP 0x80 #else #define TT_TFAULT 0x08 +#define TT_TMISS 0x09 #define TT_ILL_INSN 0x10 #define TT_PRIV_INSN 0x11 #define TT_NFPU_INSN 0x20 @@ -42,6 +45,9 @@ #define TT_CLRWIN 0x24 #define TT_DIV_ZERO 0x28 #define TT_DFAULT 0x30 +#define TT_DMISS 0x31 +#define TT_DPROT 0x32 +#define TT_PRIV_ACT 0x37 #define TT_EXTINT 0x40 #define TT_SPILL 0x80 #define TT_FILL 0xc0 @@ -65,10 +71,14 @@ #define TBR_BASE_MASK 0xfffff000 #if defined(TARGET_SPARC64) +#define PS_IG (1<<11) +#define PS_MG (1<<10) +#define PS_RED (1<<5) #define PS_PEF (1<<4) #define PS_AM (1<<3) #define PS_PRIV (1<<2) #define PS_IE (1<<1) +#define PS_AG (1<<0) #endif /* Fcc */ @@ -166,7 +176,7 @@ typedef struct CPUSPARCState { context) */ unsigned long mem_write_pc; /* host pc at which the memory was written */ - unsigned long mem_write_vaddr; /* target virtual addr at which the + target_ulong mem_write_vaddr; /* target virtual addr at which the memory was written */ /* 0 = kernel, 1 = user (may have 2 = kernel code, 3 = user code ?) */ CPUTLBEntry tlb_read[2][CPU_TLB_SIZE]; @@ -201,11 +211,13 @@ typedef struct CPUSPARCState { uint32_t pstate; uint32_t tl; uint32_t cansave, canrestore, otherwin, wstate, cleanwin; - target_ulong agregs[8]; /* alternate general registers */ - target_ulong igregs[8]; /* interrupt general registers */ - target_ulong mgregs[8]; /* mmu general registers */ + uint64_t agregs[8]; /* alternate general registers */ + uint64_t bgregs[8]; /* backup for normal global registers */ + uint64_t igregs[8]; /* interrupt general registers */ + uint64_t mgregs[8]; /* mmu general registers */ uint64_t version; uint64_t fprs; + uint64_t tick_cmpr, stick_cmpr; #endif #if !defined(TARGET_SPARC64) && !defined(reg_T2) target_ulong t2; @@ -275,7 +287,6 @@ void cpu_set_cwp(CPUSPARCState *env1, int new_cwp); struct siginfo; int cpu_sparc_signal_handler(int hostsignum, struct siginfo *info, void *puc); -#define TARGET_PAGE_BITS 12 /* 4k */ #include "cpu-all.h" #endif diff --git a/target-sparc/exec.h b/target-sparc/exec.h index c5b73fee8f..942b811897 100644 --- a/target-sparc/exec.h +++ b/target-sparc/exec.h @@ -65,6 +65,9 @@ void do_fcmpd_fcc2(void); void do_fcmps_fcc3(void); void do_fcmpd_fcc3(void); void do_popc(); +void do_wrpstate(); +void do_done(); +void do_retry(); #endif void do_ldd_kernel(target_ulong addr); void do_ldd_user(target_ulong addr); diff --git a/target-sparc/helper.c b/target-sparc/helper.c index be3d6b9857..78a033bc53 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -1,7 +1,7 @@ /* * sparc helpers * - * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2003-2005 Fabrice Bellard * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,7 +28,6 @@ #include "cpu.h" #include "exec-all.h" -//#define DEBUG_PCALL //#define DEBUG_MMU /* Sparc MMU emulation */ @@ -62,6 +61,9 @@ int cpu_sparc_handle_mmu_fault(CPUState *env, target_ulong address, int rw, #else #ifndef TARGET_SPARC64 +/* + * Sparc V8 Reference MMU (SRMMU) + */ static const int access_table[8][8] = { { 0, 0, 0, 0, 2, 0, 3, 3 }, { 0, 0, 0, 0, 2, 0, 0, 0 }, @@ -229,6 +231,9 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, } } #else +/* + * UltraSparc IIi I/DMMUs + */ static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical, int *prot, int *access_index, target_ulong address, int rw, int is_user) @@ -237,46 +242,55 @@ static int get_physical_address_data(CPUState *env, target_phys_addr_t *physical unsigned int i; if ((env->lsu & DMMU_E) == 0) { /* DMMU disabled */ - *physical = address & 0xffffffff; + *physical = address; *prot = PAGE_READ | PAGE_WRITE; return 0; } for (i = 0; i < 64; i++) { - if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) { - switch (env->dtlb_tte[i] >> 60) { - default: - case 0x4: // 8k - mask = 0xffffffffffffe000ULL; - break; - case 0x5: // 64k - mask = 0xffffffffffff0000ULL; - break; - case 0x6: // 512k - mask = 0xfffffffffff80000ULL; - break; - case 0x7: // 4M - mask = 0xffffffffffc00000ULL; - break; - } - // ctx match, vaddr match? - if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) && - (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) { - // access ok? - if (((env->dtlb_tte[i] & 0x4) && !(env->pstate & PS_PRIV)) || - (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) { - env->exception_index = TT_DFAULT; - return 1; - } - *physical = env->dtlb_tte[i] & 0xffffe000; - *prot = PAGE_READ; - if (env->dtlb_tte[i] & 0x2) - *prot |= PAGE_WRITE; - return 0; + switch ((env->dtlb_tte[i] >> 61) & 3) { + default: + case 0x0: // 8k + mask = 0xffffffffffffe000ULL; + break; + case 0x1: // 64k + mask = 0xffffffffffff0000ULL; + break; + case 0x2: // 512k + mask = 0xfffffffffff80000ULL; + break; + case 0x3: // 4M + mask = 0xffffffffffc00000ULL; + break; + } + // ctx match, vaddr match? + if (env->dmmuregs[1] == (env->dtlb_tag[i] & 0x1fff) && + (address & mask) == (env->dtlb_tag[i] & ~0x1fffULL)) { + // valid, access ok? + if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0 || + ((env->dtlb_tte[i] & 0x4) && is_user) || + (!(env->dtlb_tte[i] & 0x2) && (rw == 1))) { + if (env->dmmuregs[3]) /* Fault status register */ + env->dmmuregs[3] = 2; /* overflow (not read before another fault) */ + env->dmmuregs[3] |= (is_user << 3) | ((rw == 1) << 2) | 1; + env->dmmuregs[4] = address; /* Fault address register */ + env->exception_index = TT_DFAULT; +#ifdef DEBUG_MMU + printf("DFAULT at 0x%llx\n", address); +#endif + return 1; } + *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL); + *prot = PAGE_READ; + if (env->dtlb_tte[i] & 0x2) + *prot |= PAGE_WRITE; + return 0; } } - env->exception_index = TT_DFAULT; +#ifdef DEBUG_MMU + printf("DMISS at 0x%llx\n", address); +#endif + env->exception_index = TT_DMISS; return 1; } @@ -288,42 +302,51 @@ static int get_physical_address_code(CPUState *env, target_phys_addr_t *physical unsigned int i; if ((env->lsu & IMMU_E) == 0) { /* IMMU disabled */ - *physical = address & 0xffffffff; + *physical = address; *prot = PAGE_READ; return 0; } + for (i = 0; i < 64; i++) { - if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) { - switch (env->itlb_tte[i] >> 60) { - default: - case 0x4: // 8k - mask = 0xffffffffffffe000ULL; - break; - case 0x5: // 64k - mask = 0xffffffffffff0000ULL; - break; - case 0x6: // 512k - mask = 0xfffffffffff80000ULL; - break; - case 0x7: // 4M - mask = 0xffffffffffc00000ULL; + switch ((env->itlb_tte[i] >> 61) & 3) { + default: + case 0x0: // 8k + mask = 0xffffffffffffe000ULL; + break; + case 0x1: // 64k + mask = 0xffffffffffff0000ULL; + break; + case 0x2: // 512k + mask = 0xfffffffffff80000ULL; + break; + case 0x3: // 4M + mask = 0xffffffffffc00000ULL; break; + } + // ctx match, vaddr match? + if (env->dmmuregs[1] == (env->itlb_tag[i] & 0x1fff) && + (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) { + // valid, access ok? + if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0 || + ((env->itlb_tte[i] & 0x4) && is_user)) { + if (env->immuregs[3]) /* Fault status register */ + env->immuregs[3] = 2; /* overflow (not read before another fault) */ + env->immuregs[3] |= (is_user << 3) | 1; + env->exception_index = TT_TFAULT; +#ifdef DEBUG_MMU + printf("TFAULT at 0x%llx\n", address); +#endif + return 1; } - // ctx match, vaddr match? - if (env->immuregs[1] == (env->itlb_tag[i] & 0x1fff) && - (address & mask) == (env->itlb_tag[i] & ~0x1fffULL)) { - // access ok? - if ((env->itlb_tte[i] & 0x4) && !(env->pstate & PS_PRIV)) { - env->exception_index = TT_TFAULT; - return 1; - } - *physical = env->itlb_tte[i] & 0xffffe000; - *prot = PAGE_READ; - return 0; - } + *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) + (address & ~mask & 0x1fffffff000ULL); + *prot = PAGE_READ; + return 0; } } - env->exception_index = TT_TFAULT; +#ifdef DEBUG_MMU + printf("TMISS at 0x%llx\n", address); +#endif + env->exception_index = TT_TMISS; return 1; } @@ -341,15 +364,17 @@ int get_physical_address(CPUState *env, target_phys_addr_t *physical, int *prot, int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, int is_user, int is_softmmu) { - target_ulong virt_addr; + target_ulong virt_addr, vaddr; target_phys_addr_t paddr; - unsigned long vaddr; int error_code = 0, prot, ret = 0, access_index; error_code = get_physical_address(env, &paddr, &prot, &access_index, address, rw, is_user); if (error_code == 0) { virt_addr = address & TARGET_PAGE_MASK; vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1)); +#ifdef DEBUG_MMU + printf("Translate at 0x%llx -> 0x%llx, vaddr 0x%llx\n", address, paddr, vaddr); +#endif ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu); return ret; } @@ -471,4 +496,77 @@ void dump_mmu(CPUState *env) printf("MMU dump ends\n"); } #endif +#else +#ifdef DEBUG_MMU +void dump_mmu(CPUState *env) +{ + unsigned int i; + const char *mask; + + printf("MMU contexts: Primary: %lld, Secondary: %lld\n", env->dmmuregs[1], env->dmmuregs[2]); + if ((env->lsu & DMMU_E) == 0) { + printf("DMMU disabled\n"); + } else { + printf("DMMU dump:\n"); + for (i = 0; i < 64; i++) { + switch ((env->dtlb_tte[i] >> 61) & 3) { + default: + case 0x0: + mask = " 8k"; + break; + case 0x1: + mask = " 64k"; + break; + case 0x2: + mask = "512k"; + break; + case 0x3: + mask = " 4M"; + break; + } + if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0) { + printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, %s, ctx %lld\n", + env->dtlb_tag[i] & ~0x1fffULL, + env->dtlb_tte[i] & 0x1ffffffe000ULL, + mask, + env->dtlb_tte[i] & 0x4? "priv": "user", + env->dtlb_tte[i] & 0x2? "RW": "RO", + env->dtlb_tte[i] & 0x40? "locked": "unlocked", + env->dtlb_tag[i] & 0x1fffULL); + } + } + } + if ((env->lsu & IMMU_E) == 0) { + printf("IMMU disabled\n"); + } else { + printf("IMMU dump:\n"); + for (i = 0; i < 64; i++) { + switch ((env->itlb_tte[i] >> 61) & 3) { + default: + case 0x0: + mask = " 8k"; + break; + case 0x1: + mask = " 64k"; + break; + case 0x2: + mask = "512k"; + break; + case 0x3: + mask = " 4M"; + break; + } + if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0) { + printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx ", %s, %s, %s, ctx %lld\n", + env->itlb_tag[i] & ~0x1fffULL, + env->itlb_tte[i] & 0x1ffffffe000ULL, + mask, + env->itlb_tte[i] & 0x4? "priv": "user", + env->itlb_tte[i] & 0x40? "locked": "unlocked", + env->itlb_tag[i] & 0x1fffULL); + } + } + } +} +#endif #endif diff --git a/target-sparc/op.c b/target-sparc/op.c index 86c45c7093..f8b491a7fa 100644 --- a/target-sparc/op.c +++ b/target-sparc/op.c @@ -267,15 +267,6 @@ #endif #ifdef TARGET_SPARC64 -#undef JUMP_TB -#define JUMP_TB(opname, tbparam, n, eip) \ - do { \ - GOTO_TB(opname, tbparam, n); \ - T0 = (long)(tbparam) + (n); \ - env->pc = (eip) & 0xffffffff; \ - EXIT_TB(); \ - } while (0) - #ifdef WORDS_BIGENDIAN typedef union UREG64 { struct { uint16_t v3, v2, v1, v0; } w; @@ -388,7 +379,7 @@ void OPPROTO op_add_T1_T0_cc(void) env->psr |= PSR_ZERO; if ((int32_t) T0 < 0) env->psr |= PSR_NEG; - if ((T0 & 0xffffffff) < (src1 & 0xffffffff)) + if ((src1 & 0xffffffff) < (T1 & 0xffffffff)) env->psr |= PSR_CARRY; if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) & ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) @@ -433,7 +424,7 @@ void OPPROTO op_addx_T1_T0_cc(void) env->psr |= PSR_ZERO; if ((int32_t) T0 < 0) env->psr |= PSR_NEG; - if ((T0 & 0xffffffff) < (src1 & 0xffffffff)) + if ((src1 & 0xffffffff) < (T1 & 0xffffffff)) env->psr |= PSR_CARRY; if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff) ^ -1) & ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) @@ -478,7 +469,7 @@ void OPPROTO op_sub_T1_T0_cc(void) env->psr |= PSR_ZERO; if ((int32_t) T0 < 0) env->psr |= PSR_NEG; - if ((T0 & 0xffffffff) < (src1 & 0xffffffff)) + if ((src1 & 0xffffffff) < (T1 & 0xffffffff)) env->psr |= PSR_CARRY; if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) & ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) @@ -523,7 +514,7 @@ void OPPROTO op_subx_T1_T0_cc(void) env->psr |= PSR_ZERO; if ((int32_t) T0 < 0) env->psr |= PSR_NEG; - if ((T0 & 0xffffffff) < (src1 & 0xffffffff)) + if ((src1 & 0xffffffff) < (T1 & 0xffffffff)) env->psr |= PSR_CARRY; if ((((src1 & 0xffffffff) ^ (T1 & 0xffffffff)) & ((src1 & 0xffffffff) ^ (T0 & 0xffffffff))) & (1 << 31)) @@ -585,7 +576,11 @@ void OPPROTO op_umul_T1_T0(void) { uint64_t res; res = (uint64_t) T0 * (uint64_t) T1; +#ifdef TARGET_SPARC64 + T0 = res; +#else T0 = res & 0xffffffff; +#endif env->y = res >> 32; } @@ -593,7 +588,11 @@ void OPPROTO op_smul_T1_T0(void) { uint64_t res; res = (int64_t) ((int32_t) T0) * (int64_t) ((int32_t) T1); +#ifdef TARGET_SPARC64 + T0 = res; +#else T0 = res & 0xffffffff; +#endif env->y = res >> 32; } @@ -902,7 +901,7 @@ void OPPROTO op_rdpstate(void) void OPPROTO op_wrpstate(void) { - env->pstate = T0 & 0x1f; + do_wrpstate(); } // CWP handling is reversed in V9, but we still use the V8 register @@ -1201,12 +1200,12 @@ void OPPROTO op_eval_xbvc(void) #ifdef TARGET_SPARC64 void OPPROTO op_eval_brz(void) { - T2 = T0; + T2 = (T0 == 0); } void OPPROTO op_eval_brnz(void) { - T2 = !T0; + T2 = (T0 != 0); } void OPPROTO op_eval_brlz(void) @@ -1266,43 +1265,32 @@ void OPPROTO op_next_insn(void) env->npc = env->npc + 4; } -void OPPROTO op_branch(void) +void OPPROTO op_goto_tb0(void) { - env->npc = (uint32_t)PARAM3; /* XXX: optimize */ - JUMP_TB(op_branch, PARAM1, 0, PARAM2); + GOTO_TB(op_goto_tb0, PARAM1, 0); } -void OPPROTO op_branch2(void) +void OPPROTO op_goto_tb1(void) { - if (T2) { - env->npc = (uint32_t)PARAM2 + 4; - JUMP_TB(op_branch2, PARAM1, 0, PARAM2); - } else { - env->npc = (uint32_t)PARAM3 + 4; - JUMP_TB(op_branch2, PARAM1, 1, PARAM3); - } - FORCE_RET(); + GOTO_TB(op_goto_tb1, PARAM1, 1); } -void OPPROTO op_branch_a(void) +void OPPROTO op_jmp_label(void) { - if (T2) { - env->npc = (uint32_t)PARAM2; /* XXX: optimize */ - JUMP_TB(op_branch_a, PARAM1, 0, PARAM3); - } else { - env->npc = (uint32_t)PARAM3 + 8; /* XXX: optimize */ - JUMP_TB(op_branch_a, PARAM1, 1, PARAM3 + 4); - } + GOTO_LABEL_PARAM(1); +} + +void OPPROTO op_jnz_T2_label(void) +{ + if (T2) + GOTO_LABEL_PARAM(1); FORCE_RET(); } -void OPPROTO op_generic_branch(void) +void OPPROTO op_jz_T2_label(void) { - if (T2) { - env->npc = (uint32_t)PARAM1; - } else { - env->npc = (uint32_t)PARAM2; - } + if (!T2) + GOTO_LABEL_PARAM(1); FORCE_RET(); } @@ -1547,18 +1535,12 @@ void OPPROTO op_popc(void) void OPPROTO op_done(void) { - env->pc = env->tnpc[env->tl]; - env->npc = env->tnpc[env->tl] + 4; - env->pstate = env->tstate[env->tl]; - env->tl--; + do_done(); } void OPPROTO op_retry(void) { - env->pc = env->tpc[env->tl]; - env->npc = env->tnpc[env->tl]; - env->pstate = env->tstate[env->tl]; - env->tl--; + do_retry(); } void OPPROTO op_sir(void) diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index 15ce853373..468bbb6b43 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -1,5 +1,6 @@ #include "exec.h" +//#define DEBUG_PCALL //#define DEBUG_MMU void raise_exception(int tt) @@ -223,7 +224,7 @@ void do_fcmpd_fcc3 (void) #ifndef TARGET_SPARC64 void helper_ld_asi(int asi, int size, int sign) { - uint32_t ret; + uint32_t ret = 0; switch (asi) { case 3: /* MMU probe */ @@ -299,7 +300,8 @@ void helper_st_asi(int asi, int size, int sign) } case 4: /* write MMU regs */ { - int reg = (T0 >> 8) & 0xf, oldreg; + int reg = (T0 >> 8) & 0xf; + uint32_t oldreg; oldreg = env->mmuregs[reg]; switch(reg) { @@ -339,7 +341,7 @@ void helper_st_asi(int asi, int size, int sign) // value (T1) = src // address (T0) = dst // copy 32 bytes - int src = T1, dst = T0; + uint32_t src = T1, dst = T0; uint8_t temp[32]; tswap32s(&src); @@ -353,7 +355,8 @@ void helper_st_asi(int asi, int size, int sign) // value (T1, T2) // address (T0) = dst // fill 32 bytes - int i, dst = T0; + int i; + uint32_t dst = T0; uint64_t val; val = (((uint64_t)T1) << 32) | T2; @@ -366,7 +369,7 @@ void helper_st_asi(int asi, int size, int sign) return; case 0x20 ... 0x2f: /* MMU passthrough */ { - int temp = T1; + uint32_t temp = T1; if (size == 4) tswap32s(&temp); else if (size == 2) @@ -383,10 +386,10 @@ void helper_st_asi(int asi, int size, int sign) void helper_ld_asi(int asi, int size, int sign) { - uint64_t ret; + uint64_t ret = 0; if (asi < 0x80 && (env->pstate & PS_PRIV) == 0) - raise_exception(TT_PRIV_INSN); + raise_exception(TT_PRIV_ACT); switch (asi) { case 0x14: // Bypass @@ -401,8 +404,23 @@ void helper_ld_asi(int asi, int size, int sign) tswap16s((uint16_t *)&ret); break; } + case 0x04: // Nucleus + case 0x0c: // Nucleus Little Endian (LE) + case 0x10: // As if user primary + case 0x11: // As if user secondary + case 0x18: // As if user primary LE + case 0x19: // As if user secondary LE case 0x1c: // Bypass LE case 0x1d: // Bypass, non-cacheable LE + case 0x24: // Nucleus quad LDD 128 bit atomic + case 0x2c: // Nucleus quad LDD 128 bit atomic + case 0x4a: // UPA config + case 0x82: // Primary no-fault + case 0x83: // Secondary no-fault + case 0x88: // Primary LE + case 0x89: // Secondary LE + case 0x8a: // Primary no-fault LE + case 0x8b: // Secondary no-fault LE // XXX break; case 0x45: // LSU @@ -418,8 +436,22 @@ void helper_ld_asi(int asi, int size, int sign) case 0x51: // I-MMU 8k TSB pointer case 0x52: // I-MMU 64k TSB pointer case 0x55: // I-MMU data access - case 0x56: // I-MMU tag read + // XXX break; + case 0x56: // I-MMU tag read + { + unsigned int i; + + for (i = 0; i < 64; i++) { + // Valid, ctx match, vaddr match + if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 && + env->itlb_tag[i] == T0) { + ret = env->itlb_tag[i]; + break; + } + } + break; + } case 0x58: // D-MMU regs { int reg = (T0 >> 3) & 0xf; @@ -427,16 +459,34 @@ void helper_ld_asi(int asi, int size, int sign) ret = env->dmmuregs[reg]; break; } + case 0x5e: // D-MMU tag read + { + unsigned int i; + + for (i = 0; i < 64; i++) { + // Valid, ctx match, vaddr match + if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 && + env->dtlb_tag[i] == T0) { + ret = env->dtlb_tag[i]; + break; + } + } + break; + } case 0x59: // D-MMU 8k TSB pointer case 0x5a: // D-MMU 64k TSB pointer case 0x5b: // D-MMU data pointer case 0x5d: // D-MMU data access - case 0x5e: // D-MMU tag read + 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: ret = 0; break; @@ -447,7 +497,7 @@ void helper_ld_asi(int asi, int size, int sign) void helper_st_asi(int asi, int size, int sign) { if (asi < 0x80 && (env->pstate & PS_PRIV) == 0) - raise_exception(TT_PRIV_INSN); + raise_exception(TT_PRIV_ACT); switch(asi) { case 0x14: // Bypass @@ -463,8 +513,19 @@ void helper_st_asi(int asi, int size, int sign) cpu_physical_memory_write(T0, (void *) &temp, size); } return; + case 0x04: // Nucleus + case 0x0c: // Nucleus Little Endian (LE) + case 0x10: // As if user primary + case 0x11: // As if user secondary + case 0x18: // As if user primary LE + case 0x19: // As if user secondary LE case 0x1c: // Bypass LE case 0x1d: // Bypass, non-cacheable LE + case 0x24: // Nucleus quad LDD 128 bit atomic + case 0x2c: // Nucleus quad LDD 128 bit atomic + case 0x4a: // UPA config + case 0x88: // Primary LE + case 0x89: // Secondary LE // XXX return; case 0x45: // LSU @@ -475,8 +536,13 @@ void helper_st_asi(int asi, int size, int sign) env->lsu = T1 & (DMMU_E | IMMU_E); // Mappings generated during D/I MMU disabled mode are // invalid in normal mode - if (oldreg != env->lsu) + if (oldreg != env->lsu) { +#ifdef DEBUG_MMU + printf("LSU change: 0x%llx -> 0x%llx\n", oldreg, env->lsu); + dump_mmu(env); +#endif tlb_flush(env, 1); + } return; } case 0x50: // I-MMU regs @@ -506,7 +572,7 @@ void helper_st_asi(int asi, int size, int sign) env->immuregs[reg] = T1; #ifdef DEBUG_MMU if (oldreg != env->immuregs[reg]) { - printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->immuregs[reg]); + printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->immuregs[reg]); } dump_mmu(env); #endif @@ -544,6 +610,7 @@ void helper_st_asi(int asi, int size, int sign) return; } case 0x57: // I-MMU demap + // XXX return; case 0x58: // D-MMU regs { @@ -574,7 +641,7 @@ void helper_st_asi(int asi, int size, int sign) env->dmmuregs[reg] = T1; #ifdef DEBUG_MMU if (oldreg != env->dmmuregs[reg]) { - printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->dmmuregs[reg]); + printf("mmu change reg[%d]: 0x%08llx -> 0x%08llx\n", reg, oldreg, env->dmmuregs[reg]); } dump_mmu(env); #endif @@ -612,6 +679,8 @@ void helper_st_asi(int asi, int size, int sign) return; } case 0x5f: // D-MMU demap + case 0x49: // Interrupt data receive + // XXX return; case 0x51: // I-MMU 8k TSB pointer, RO case 0x52: // I-MMU 64k TSB pointer, RO @@ -620,6 +689,12 @@ void helper_st_asi(int asi, int size, int sign) case 0x5a: // D-MMU 64k TSB pointer, RO case 0x5b: // D-MMU data pointer, RO case 0x5e: // D-MMU tag read, RO + case 0x48: // Interrupt dispatch, RO + case 0x7f: // Incoming interrupt vector, RO + case 0x82: // Primary no-fault, RO + case 0x83: // Secondary no-fault, RO + case 0x8a: // Primary no-fault LE, RO + case 0x8b: // Secondary no-fault LE, RO default: return; } @@ -704,6 +779,61 @@ void do_popc() T0 = (T0 & 0x0000ffff0000ffffULL) + ((T0 >> 16) & 0x0000ffff0000ffffULL); T0 = (T0 & 0x00000000ffffffffULL) + ((T0 >> 32) & 0x00000000ffffffffULL); } + +static inline uint64_t *get_gregset(uint64_t pstate) +{ + switch (pstate) { + default: + case 0: + return env->bgregs; + case PS_AG: + return env->agregs; + case PS_MG: + return env->mgregs; + case PS_IG: + return env->igregs; + } +} + +void do_wrpstate() +{ + uint64_t new_pstate, pstate_regs, new_pstate_regs; + uint64_t *src, *dst; + + new_pstate = T0 & 0xf3f; + pstate_regs = env->pstate & 0xc01; + new_pstate_regs = new_pstate & 0xc01; + if (new_pstate_regs != pstate_regs) { + // Switch global register bank + src = get_gregset(new_pstate_regs); + dst = get_gregset(pstate_regs); + memcpy32(dst, env->gregs); + memcpy32(env->gregs, src); + } + env->pstate = new_pstate; +} + +void do_done(void) +{ + env->tl--; + env->pc = env->tnpc[env->tl]; + env->npc = env->tnpc[env->tl] + 4; + PUT_CCR(env, env->tstate[env->tl] >> 32); + env->asi = (env->tstate[env->tl] >> 24) & 0xff; + env->pstate = (env->tstate[env->tl] >> 8) & 0xfff; + set_cwp(env->tstate[env->tl] & 0xff); +} + +void do_retry(void) +{ + env->tl--; + env->pc = env->tpc[env->tl]; + env->npc = env->tnpc[env->tl]; + PUT_CCR(env, env->tstate[env->tl] >> 32); + env->asi = (env->tstate[env->tl] >> 24) & 0xff; + env->pstate = (env->tstate[env->tl] >> 8) & 0xfff; + set_cwp(env->tstate[env->tl] & 0xff); +} #endif void set_cwp(int new_cwp) @@ -744,7 +874,7 @@ void do_interrupt(int intno) #ifdef DEBUG_PCALL if (loglevel & CPU_LOG_INT) { static int count; - fprintf(logfile, "%6d: v=%02x pc=%08x npc=%08x SP=%08x\n", + fprintf(logfile, "%6d: v=%04x pc=%016llx npc=%016llx SP=%016llx\n", count, intno, env->pc, env->npc, env->regwptr[6]); @@ -766,8 +896,8 @@ void do_interrupt(int intno) } #endif #if !defined(CONFIG_USER_ONLY) - if (env->pstate & PS_IE) { - cpu_abort(cpu_single_env, "Trap 0x%02x while interrupts disabled, Error state", env->exception_index); + if (env->tl == MAXTL) { + cpu_abort(cpu_single_env, "Trap 0x%04x while trap level is MAXTL, Error state", env->exception_index); return; } #endif @@ -776,8 +906,16 @@ void do_interrupt(int intno) env->tpc[env->tl] = env->pc; env->tnpc[env->tl] = env->npc; env->tt[env->tl] = intno; - env->tbr = env->tbr | (env->tl > 1) ? 1 << 14 : 0 | (intno << 4); - env->tl++; + env->pstate = PS_PEF | PS_PRIV | PS_AG; + env->tbr &= ~0x7fffULL; + env->tbr |= ((env->tl > 1) ? 1 << 14 : 0) | (intno << 5); + if (env->tl < MAXTL - 1) { + env->tl++; + } else { + env->pstate |= PS_RED; + if (env->tl != MAXTL) + env->tl++; + } env->pc = env->tbr; env->npc = env->pc + 4; env->exception_index = 0; diff --git a/target-sparc/op_mem.h b/target-sparc/op_mem.h index 2407c15d8b..f5dbd2605f 100644 --- a/target-sparc/op_mem.h +++ b/target-sparc/op_mem.h @@ -105,20 +105,10 @@ void OPPROTO glue(op_casx, MEMSUFFIX)(void) void OPPROTO glue(op_ldsw, MEMSUFFIX)(void) { - T1 = (int64_t)glue(ldl, MEMSUFFIX)(T0); + T1 = (int64_t)(glue(ldl, MEMSUFFIX)(T0) & 0xffffffff); } -void OPPROTO glue(op_ldx, MEMSUFFIX)(void) -{ - // XXX - T1 = (uint64_t)glue(ldl, MEMSUFFIX)(T0) << 32; - T1 |= glue(ldl, MEMSUFFIX)(T0); -} - -void OPPROTO glue(op_stx, MEMSUFFIX)(void) -{ - glue(stl, MEMSUFFIX)(T0, T1 >> 32); - glue(stl, MEMSUFFIX)(T0, T1 & 0xffffffff); -} +SPARC_LD_OP(ldx, ldq); +SPARC_ST_OP(stx, stq); #endif #undef MEMSUFFIX diff --git a/target-sparc/translate.c b/target-sparc/translate.c index e1c02725fe..c2ba2e35cd 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -86,6 +86,12 @@ enum { #define DFPREG(r) (r) #endif +#ifdef USE_DIRECT_JUMP +#define TBPARAM(x) +#else +#define TBPARAM(x) (long)(x) +#endif + static int sign_extend(int x, int len) { len = 32 - len; @@ -462,7 +468,7 @@ OP_LD_TABLE(casx); static inline void gen_movl_imm_TN(int reg, uint32_t imm) { - gen_op_movl_TN_im[reg] (imm); + gen_op_movl_TN_im[reg](imm); } static inline void gen_movl_imm_T1(uint32_t val) @@ -529,15 +535,6 @@ static inline void gen_movl_T1_reg(int reg) gen_movl_TN_reg(reg, 1); } -/* call this function before using T2 as it may have been set for a jump */ -static inline void flush_T2(DisasContext * dc) -{ - if (dc->npc == JUMP_PC) { - gen_op_generic_branch(dc->jump_pc[0], dc->jump_pc[1]); - dc->npc = DYNAMIC_PC; - } -} - static inline void gen_jmp_im(target_ulong pc) { #ifdef TARGET_SPARC64 @@ -564,10 +561,88 @@ static inline void gen_movl_npc_im(target_ulong npc) #endif } +static inline void gen_branch2(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2) +{ + int l1; + + l1 = gen_new_label(); + + gen_op_jz_T2_label(l1); + + gen_op_goto_tb0(TBPARAM(tb)); + gen_jmp_im(pc1); + gen_movl_npc_im(pc1 + 4); + gen_op_movl_T0_im((long)tb + 0); + gen_op_exit_tb(); + + gen_set_label(l1); + gen_op_goto_tb1(TBPARAM(tb)); + gen_jmp_im(pc2); + gen_movl_npc_im(pc2 + 4); + gen_op_movl_T0_im((long)tb + 1); + gen_op_exit_tb(); +} + +static inline void gen_branch_a(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2) +{ + int l1; + + l1 = gen_new_label(); + + gen_op_jz_T2_label(l1); + + gen_op_goto_tb0(TBPARAM(tb)); + gen_jmp_im(pc2); + gen_movl_npc_im(pc1); + gen_op_movl_T0_im((long)tb + 0); + gen_op_exit_tb(); + + gen_set_label(l1); + gen_op_goto_tb1(TBPARAM(tb)); + gen_jmp_im(pc2 + 4); + gen_movl_npc_im(pc2 + 8); + gen_op_movl_T0_im((long)tb + 1); + gen_op_exit_tb(); +} + +static inline void gen_branch(DisasContext *dc, long tb, target_ulong pc, target_ulong npc) +{ + gen_op_goto_tb0(TBPARAM(tb)); + gen_jmp_im(pc); + gen_movl_npc_im(npc); + gen_op_movl_T0_im((long)tb + 0); + gen_op_exit_tb(); +} + +static inline void gen_generic_branch(DisasContext *dc, target_ulong npc1, target_ulong npc2) +{ + int l1, l2; + + l1 = gen_new_label(); + l2 = gen_new_label(); + gen_op_jz_T2_label(l1); + + gen_movl_npc_im(npc1); + gen_op_jmp_label(l2); + + gen_set_label(l1); + gen_movl_npc_im(npc2); + gen_set_label(l2); +} + +/* call this function before using T2 as it may have been set for a jump */ +static inline void flush_T2(DisasContext * dc) +{ + if (dc->npc == JUMP_PC) { + gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]); + dc->npc = DYNAMIC_PC; + } +} + static inline void save_npc(DisasContext * dc) { if (dc->npc == JUMP_PC) { - gen_op_generic_branch(dc->jump_pc[0], dc->jump_pc[1]); + gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]); dc->npc = DYNAMIC_PC; } else if (dc->npc != DYNAMIC_PC) { gen_movl_npc_im(dc->npc); @@ -583,7 +658,7 @@ static inline void save_state(DisasContext * dc) static inline void gen_mov_pc_npc(DisasContext * dc) { if (dc->npc == JUMP_PC) { - gen_op_generic_branch(dc->jump_pc[0], dc->jump_pc[1]); + gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]); gen_op_mov_pc_npc(); dc->pc = DYNAMIC_PC; } else if (dc->npc == DYNAMIC_PC) { @@ -769,7 +844,7 @@ static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn, int cc) flush_T2(dc); gen_cond[cc][cond](); if (a) { - gen_op_branch_a((long)dc->tb, target, dc->npc); + gen_branch_a(dc, (long)dc->tb, target, dc->npc); dc->is_br = 1; } else { dc->pc = dc->npc; @@ -808,7 +883,7 @@ static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn, int cc) flush_T2(dc); gen_fcond[cc][cond](); if (a) { - gen_op_branch_a((long)dc->tb, target, dc->npc); + gen_branch_a(dc, (long)dc->tb, target, dc->npc); dc->is_br = 1; } else { dc->pc = dc->npc; @@ -829,7 +904,7 @@ static void do_branch_reg(DisasContext * dc, int32_t offset, uint32_t insn) flush_T2(dc); gen_cond_reg(cond); if (a) { - gen_op_branch_a((long)dc->tb, target, dc->npc); + gen_branch_a(dc, (long)dc->tb, target, dc->npc); dc->is_br = 1; } else { dc->pc = dc->npc; @@ -893,7 +968,7 @@ static void disas_sparc_insn(DisasContext * dc) target <<= 2; target = sign_extend(target, 16); rs1 = GET_FIELD(insn, 13, 17); - gen_movl_T0_reg(rs1); + gen_movl_reg_T0(rs1); do_branch_reg(dc, target, insn); goto jmp_insn; } @@ -952,7 +1027,15 @@ static void disas_sparc_insn(DisasContext * dc) /*CALL*/ { target_long target = GET_FIELDs(insn, 2, 31) << 2; +#ifdef TARGET_SPARC64 + if (dc->pc == (uint32_t)dc->pc) { + gen_op_movl_T0_im(dc->pc); + } else { + gen_op_movq_T0_im64(dc->pc >> 32, dc->pc); + } +#else gen_op_movl_T0_im(dc->pc); +#endif gen_movl_T0_reg(15); target += dc->pc; gen_mov_pc_npc(dc); @@ -1039,6 +1122,25 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_movl_T0_env(offsetof(CPUSPARCState, fprs)); gen_movl_T0_reg(rd); break; + case 0x17: /* Tick compare */ + gen_op_movtl_T0_env(offsetof(CPUSPARCState, tick_cmpr)); + gen_movl_T0_reg(rd); + break; + case 0x18: /* System tick */ + gen_op_rdtick(); // XXX + gen_movl_T0_reg(rd); + break; + case 0x19: /* System tick compare */ + gen_op_movtl_T0_env(offsetof(CPUSPARCState, stick_cmpr)); + gen_movl_T0_reg(rd); + break; + case 0x10: /* Performance Control */ + case 0x11: /* Performance Instrumentation Counter */ + case 0x12: /* Dispatch Control */ + case 0x13: /* Graphics Status */ + case 0x14: /* Softint set, WO */ + case 0x15: /* Softint clear, WO */ + case 0x16: /* Softint write */ #endif default: goto illegal_insn; @@ -1549,6 +1651,50 @@ static void disas_sparc_insn(DisasContext * dc) gen_movl_T0_reg(rd); } #endif +#ifdef TARGET_SPARC64 + } else if (xop == 0x25) { /* sll, V9 sllx ( == sll) */ + rs1 = GET_FIELD(insn, 13, 17); + gen_movl_reg_T0(rs1); + if (IS_IMM) { /* immediate */ + rs2 = GET_FIELDs(insn, 20, 31); + gen_movl_simm_T1(rs2); + } else { /* register */ + rs2 = GET_FIELD(insn, 27, 31); + gen_movl_reg_T1(rs2); + } + gen_op_sll(); + gen_movl_T0_reg(rd); + } else if (xop == 0x26) { /* srl, V9 srlx */ + rs1 = GET_FIELD(insn, 13, 17); + gen_movl_reg_T0(rs1); + if (IS_IMM) { /* immediate */ + rs2 = GET_FIELDs(insn, 20, 31); + gen_movl_simm_T1(rs2); + } else { /* register */ + rs2 = GET_FIELD(insn, 27, 31); + gen_movl_reg_T1(rs2); + } + if (insn & (1 << 12)) + gen_op_srlx(); + else + gen_op_srl(); + gen_movl_T0_reg(rd); + } else if (xop == 0x27) { /* sra, V9 srax */ + rs1 = GET_FIELD(insn, 13, 17); + gen_movl_reg_T0(rs1); + if (IS_IMM) { /* immediate */ + rs2 = GET_FIELDs(insn, 20, 31); + gen_movl_simm_T1(rs2); + } else { /* register */ + rs2 = GET_FIELD(insn, 27, 31); + gen_movl_reg_T1(rs2); + } + if (insn & (1 << 12)) + gen_op_srax(); + else + gen_op_sra(); + gen_movl_T0_reg(rd); +#endif } else if (xop < 0x38) { rs1 = GET_FIELD(insn, 13, 17); gen_movl_reg_T0(rs1); @@ -1660,32 +1806,20 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_mulscc_T1_T0(); gen_movl_T0_reg(rd); break; - case 0x25: /* sll, V9 sllx ( == sll) */ +#ifndef TARGET_SPARC64 + case 0x25: /* sll */ gen_op_sll(); gen_movl_T0_reg(rd); break; - case 0x26: /* srl, V9 srlx */ -#ifdef TARGET_SPARC64 - if (insn & (1 << 12)) - gen_op_srlx(); - else - gen_op_srl(); -#else + case 0x26: /* srl */ gen_op_srl(); -#endif gen_movl_T0_reg(rd); break; - case 0x27: /* sra, V9 srax */ -#ifdef TARGET_SPARC64 - if (insn & (1 << 12)) - gen_op_srax(); - else - gen_op_sra(); -#else + case 0x27: /* sra */ gen_op_sra(); -#endif gen_movl_T0_reg(rd); break; +#endif case 0x30: { switch(rd) { @@ -1709,7 +1843,28 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_sir(); #endif break; + case 0x17: /* Tick compare */ +#if !defined(CONFIG_USER_ONLY) + if (!supervisor(dc)) + goto illegal_insn; +#endif + gen_op_movtl_env_T0(offsetof(CPUSPARCState, tick_cmpr)); + break; + case 0x18: /* System tick */ +#if !defined(CONFIG_USER_ONLY) + if (!supervisor(dc)) + goto illegal_insn; +#endif + gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr)); + break; + case 0x19: /* System tick compare */ +#if !defined(CONFIG_USER_ONLY) + if (!supervisor(dc)) + goto illegal_insn; #endif + gen_op_movtl_env_T0(offsetof(CPUSPARCState, stick_cmpr)); + break; + case 0x10: /* Performance Control */ case 0x11: /* Performance Instrumentation Counter */ case 0x12: /* Dispatch Control */ @@ -1717,9 +1872,7 @@ static void disas_sparc_insn(DisasContext * dc) case 0x14: /* Softint set */ case 0x15: /* Softint clear */ case 0x16: /* Softint write */ - case 0x17: /* Tick compare */ - case 0x18: /* System tick */ - case 0x19: /* System tick compare */ +#endif default: goto illegal_insn; } @@ -1770,7 +1923,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_wrtick(); break; case 5: // tba - gen_op_movl_env_T0(offsetof(CPUSPARCState, tbr)); + gen_op_movtl_env_T0(offsetof(CPUSPARCState, tbr)); break; case 6: // pstate gen_op_wrpstate(); @@ -1896,7 +2049,6 @@ static void disas_sparc_insn(DisasContext * dc) } #ifdef TARGET_SPARC64 } else if (xop == 0x39) { /* V9 return */ - gen_op_restore(); rs1 = GET_FIELD(insn, 13, 17); gen_movl_reg_T0(rs1); if (IS_IMM) { /* immediate */ @@ -1920,6 +2072,7 @@ static void disas_sparc_insn(DisasContext * dc) } #endif } + gen_op_restore(); gen_mov_pc_npc(dc); gen_op_movl_npc_T0(); dc->npc = DYNAMIC_PC; @@ -1993,13 +2146,17 @@ static void disas_sparc_insn(DisasContext * dc) case 0: if (!supervisor(dc)) goto priv_insn; + dc->npc = DYNAMIC_PC; + dc->pc = DYNAMIC_PC; gen_op_done(); - break; + goto jmp_insn; case 1: if (!supervisor(dc)) goto priv_insn; + dc->npc = DYNAMIC_PC; + dc->pc = DYNAMIC_PC; gen_op_retry(); - break; + goto jmp_insn; default: goto illegal_insn; } @@ -2317,7 +2474,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_next_insn(); } else if (dc->npc == JUMP_PC) { /* we can do a static jump */ - gen_op_branch2((long)dc->tb, dc->jump_pc[0], dc->jump_pc[1]); + gen_branch2(dc, (long)dc->tb, dc->jump_pc[0], dc->jump_pc[1]); dc->is_br = 1; } else { dc->pc = dc->npc; @@ -2365,6 +2522,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, gen_opc_ptr = gen_opc_buf; gen_opc_end = gen_opc_buf + OPC_MAX_SIZE; gen_opparam_ptr = gen_opparam_buf; + nb_gen_labels = 0; do { if (env->nb_breakpoints > 0) { @@ -2421,7 +2579,7 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb, if (dc->pc != DYNAMIC_PC && (dc->npc != DYNAMIC_PC && dc->npc != JUMP_PC)) { /* static PC and NPC: we can use direct chaining */ - gen_op_branch((long)tb, dc->pc, dc->npc); + gen_branch(dc, (long)tb, dc->pc, dc->npc); } else { if (dc->pc != DYNAMIC_PC) gen_jmp_im(dc->pc); @@ -2487,15 +2645,16 @@ void cpu_reset(CPUSPARCState *env) #else env->psrs = 1; env->psrps = 1; - env->pc = 0xffd00000; env->gregs[1] = ram_size; - env->npc = env->pc + 4; #ifdef TARGET_SPARC64 - env->pstate = PS_AM | PS_PRIV; // XXX: Force AM + env->pstate = PS_PRIV; env->version = GET_VER(env); + env->pc = 0x1fff0000000ULL; #else env->mmuregs[0] = (0x04 << 24); /* Impl 0, ver 4, MMU disabled */ + env->pc = 0xffd00000; #endif + env->npc = env->pc + 4; #endif } |