From af7bf89b1f525bb684f48ed0e847ad2d2d11c5e5 Mon Sep 17 00:00:00 2001 From: bellard Date: Sun, 30 Jan 2005 22:39:04 +0000 Subject: [PATCH] initial sparc64 support - sparc fixes (Blue Swirl) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1251 c046a42c-6fe2-441c-8c8c-71466251a162 --- target-sparc/cpu.h | 36 +++++--- target-sparc/exec.h | 18 ++-- target-sparc/helper.c | 41 ++++++---- target-sparc/op.c | 173 ++++++++++++++++++++------------------- target-sparc/op_helper.c | 13 ++- target-sparc/op_mem.h | 2 +- target-sparc/translate.c | 160 +++++++++++++++++++++++------------- 7 files changed, 263 insertions(+), 180 deletions(-) diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 6a077c58e3..7f8b9060a2 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -1,7 +1,17 @@ #ifndef CPU_SPARC_H #define CPU_SPARC_H +#include "config.h" + +#if !defined(TARGET_SPARC64) #define TARGET_LONG_BITS 32 +#define TARGET_FPREGS 32 +#define TARGET_FPREG_T float +#else +#define TARGET_LONG_BITS 64 +#define TARGET_FPREGS 64 +#define TARGET_FPREG_T double +#endif #include "cpu-defs.h" @@ -95,15 +105,14 @@ #define NWINDOWS 32 typedef struct CPUSPARCState { - uint32_t gregs[8]; /* general registers */ - uint32_t *regwptr; /* pointer to current register window */ - float fpr[32]; /* floating point registers */ - uint32_t pc; /* program counter */ - uint32_t npc; /* next program counter */ - uint32_t y; /* multiply/divide register */ + target_ulong gregs[8]; /* general registers */ + target_ulong *regwptr; /* pointer to current register window */ + TARGET_FPREG_T fpr[TARGET_FPREGS]; /* floating point registers */ + target_ulong pc; /* program counter */ + target_ulong npc; /* next program counter */ + target_ulong y; /* multiply/divide register */ uint32_t psr; /* processor state register */ uint32_t fsr; /* FPU state register */ - uint32_t T2; uint32_t cwp; /* index of current register window (extracted from PSR) */ uint32_t wim; /* window invalid mask */ @@ -118,11 +127,11 @@ typedef struct CPUSPARCState { int exception_index; int interrupt_index; int interrupt_request; - uint32_t exception_next_pc; + target_ulong exception_next_pc; struct TranslationBlock *current_tb; void *opaque; /* NOTE: we allow 8 more registers to handle wrapping */ - uint32_t regbase[NWINDOWS * 16 + 8]; + target_ulong regbase[NWINDOWS * 16 + 8]; /* in order to avoid passing too many arguments to the memory write helpers, we store some rarely used information in the CPU @@ -140,9 +149,12 @@ typedef struct CPUSPARCState { /* temporary float registers */ float ft0, ft1, ft2; double dt0, dt1, dt2; +#if defined(TARGET_SPARC64) + target_ulong t0, t1, t2; +#endif /* ice debug support */ - uint32_t breakpoints[MAX_BREAKPOINTS]; + target_ulong breakpoints[MAX_BREAKPOINTS]; int nb_breakpoints; int singlestep_enabled; /* XXX: should use CPU single step mode instead */ @@ -155,7 +167,7 @@ void cpu_get_fp64(uint64_t *pmant, uint16_t *pexp, double f); double cpu_put_fp64(uint64_t mant, uint16_t exp); /* Fake impl 0, version 4 */ -#define GET_PSR(env) ((0 << 28) | (4 << 24) | env->psr | \ +#define GET_PSR(env) ((0 << 28) | (4 << 24) | (env->psr & PSR_ICC) | \ (env->psref? PSR_EF : 0) | \ (env->psrpil << 8) | \ (env->psrs? PSR_S : 0) | \ @@ -167,7 +179,7 @@ void cpu_set_cwp(CPUSPARCState *env1, int new_cwp); #endif #define PUT_PSR(env, val) do { int _tmp = val; \ - env->psr = _tmp & ~PSR_ICC; \ + env->psr = _tmp & PSR_ICC; \ env->psref = (_tmp & PSR_EF)? 1 : 0; \ env->psrpil = (_tmp & PSR_PIL) >> 8; \ env->psrs = (_tmp & PSR_S)? 1 : 0; \ diff --git a/target-sparc/exec.h b/target-sparc/exec.h index f8edc17153..1fa7d87dce 100644 --- a/target-sparc/exec.h +++ b/target-sparc/exec.h @@ -3,9 +3,15 @@ #include "dyngen-exec.h" register struct CPUSPARCState *env asm(AREG0); +#ifdef TARGET_SPARC64 +#define T0 (env->t0) +#define T1 (env->t1) +#define T2 (env->t2) +#else register uint32_t T0 asm(AREG1); register uint32_t T1 asm(AREG2); register uint32_t T2 asm(AREG3); +#endif #define FT0 (env->ft0) #define FT1 (env->ft1) #define FT2 (env->ft2) @@ -32,17 +38,19 @@ void do_fsqrts(void); void do_fsqrtd(void); void do_fcmps(void); void do_fcmpd(void); -void do_ldd_kernel(uint32_t addr); -void do_ldd_user(uint32_t addr); -void do_ldd_raw(uint32_t addr); +void do_ldd_kernel(target_ulong addr); +void do_ldd_user(target_ulong addr); +void do_ldd_raw(target_ulong addr); void do_interrupt(int intno, int is_int, int error_code, unsigned int next_eip, int is_hw); void raise_exception_err(int exception_index, int error_code); void raise_exception(int tt); -void memcpy32(uint32_t *dst, const uint32_t *src); -uint32_t mmu_probe(uint32_t address, int mmulev); +void memcpy32(target_ulong *dst, const target_ulong *src); +target_ulong mmu_probe(target_ulong address, int mmulev); void dump_mmu(void); void helper_debug(); +void do_wrpsr(); +void do_rdpsr(); /* XXX: move that to a generic header */ #if !defined(CONFIG_USER_ONLY) diff --git a/target-sparc/helper.c b/target-sparc/helper.c index f4111b3f6b..60096bf3a3 100644 --- a/target-sparc/helper.c +++ b/target-sparc/helper.c @@ -23,7 +23,7 @@ //#define DEBUG_MMU /* Sparc MMU emulation */ -int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw, +int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, int is_user, int is_softmmu); /* thread support */ @@ -109,13 +109,14 @@ static const int rw_table[2][8] = { { 0, 1, 0, 1, 0, 0, 0, 0 } }; -int get_physical_address (CPUState *env, uint32_t *physical, int *prot, - int *access_index, uint32_t address, int rw, +int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot, + int *access_index, target_ulong address, int rw, int is_user) { int access_perms = 0; target_phys_addr_t pde_ptr; - uint32_t pde, virt_addr; + uint32_t pde; + target_ulong virt_addr; int error_code = 0, is_dirty; unsigned long page_offset; @@ -217,11 +218,12 @@ int get_physical_address (CPUState *env, uint32_t *physical, int *prot, } /* Perform address translation */ -int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw, +int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw, int is_user, int is_softmmu) { int exception = 0; - uint32_t virt_addr, paddr; + target_ulong virt_addr; + target_phys_addr_t paddr; unsigned long vaddr; int error_code = 0, prot, ret = 0, access_index; @@ -252,7 +254,7 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw, return error_code; } -void memcpy32(uint32_t *dst, const uint32_t *src) +void memcpy32(target_ulong *dst, const target_ulong *src) { dst[0] = src[0]; dst[1] = src[1]; @@ -328,8 +330,13 @@ void do_interrupt(int intno, int is_int, int error_code, env->psret = 0; cwp = (env->cwp - 1) & (NWINDOWS - 1); set_cwp(cwp); - env->regwptr[9] = env->pc - 4; // XXX? - env->regwptr[10] = env->pc; + if (intno & 0x80) { + env->regwptr[9] = env->pc; + env->regwptr[10] = env->npc; + } else { + env->regwptr[9] = env->pc - 4; // XXX? + env->regwptr[10] = env->pc; + } env->psrps = env->psrs; env->psrs = 1; env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4); @@ -343,7 +350,7 @@ void raise_exception_err(int exception_index, int error_code) raise_exception(exception_index); } -uint32_t mmu_probe(uint32_t address, int mmulev) +target_ulong mmu_probe(target_ulong address, int mmulev) { target_phys_addr_t pde_ptr; uint32_t pde; @@ -408,30 +415,30 @@ uint32_t mmu_probe(uint32_t address, int mmulev) void dump_mmu(void) { #ifdef DEBUG_MMU - uint32_t pa, va, va1, va2; - int n, m, o; - target_phys_addr_t pde_ptr; + target_ulong va, va1, va2; + unsigned int n, m, o; + target_phys_addr_t pde_ptr, pa; uint32_t pde; printf("MMU dump:\n"); pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4); pde = ldl_phys(pde_ptr); - printf("Root ptr: 0x%08x, ctx: %d\n", env->mmuregs[1] << 4, env->mmuregs[2]); + printf("Root ptr: " TARGET_FMT_lx ", ctx: %d\n", env->mmuregs[1] << 4, env->mmuregs[2]); for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) { pde_ptr = mmu_probe(va, 2); if (pde_ptr) { pa = cpu_get_phys_page_debug(env, va); - printf("VA: 0x%08x, PA: 0x%08x PDE: 0x%08x\n", va, pa, pde_ptr); + printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PDE: " TARGET_FMT_lx "\n", va, pa, pde_ptr); for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) { pde_ptr = mmu_probe(va1, 1); if (pde_ptr) { pa = cpu_get_phys_page_debug(env, va1); - printf(" VA: 0x%08x, PA: 0x%08x PDE: 0x%08x\n", va1, pa, pde_ptr); + printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PDE: " TARGET_FMT_lx "\n", va1, pa, pde_ptr); for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) { pde_ptr = mmu_probe(va2, 0); if (pde_ptr) { pa = cpu_get_phys_page_debug(env, va2); - printf(" VA: 0x%08x, PA: 0x%08x PTE: 0x%08x\n", va2, pa, pde_ptr); + printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_lx " PTE: " TARGET_FMT_lx "\n", va2, pa, pde_ptr); } } } diff --git a/target-sparc/op.c b/target-sparc/op.c index f8cf2f8934..d1d48d2a78 100644 --- a/target-sparc/op.c +++ b/target-sparc/op.c @@ -217,7 +217,7 @@ #define EIP (env->pc) -#define FLAG_SET(x) (env->psr&x)?1:0 +#define FLAG_SET(x) ((env->psr&x)?1:0) #define FFLAG_SET(x) ((env->fsr&x)?1:0) void OPPROTO op_movl_T0_0(void) @@ -225,11 +225,6 @@ void OPPROTO op_movl_T0_0(void) T0 = 0; } -void OPPROTO op_movl_T0_1(void) -{ - T0 = 1; -} - void OPPROTO op_movl_T0_im(void) { T0 = PARAM1; @@ -245,21 +240,6 @@ void OPPROTO op_movl_T2_im(void) T2 = PARAM1; } -void OPPROTO op_addl_T1_im(void) -{ - T1 += PARAM1; -} - -void OPPROTO op_addl_T1_T2(void) -{ - T1 += T2; -} - -void OPPROTO op_subl_T1_T2(void) -{ - T1 -= T2; -} - void OPPROTO op_add_T1_T0(void) { T0 += T1; @@ -267,18 +247,44 @@ void OPPROTO op_add_T1_T0(void) void OPPROTO op_add_T1_T0_cc(void) { - unsigned int src1; + target_ulong src1; + src1 = T0; T0 += T1; env->psr = 0; if (!T0) env->psr |= PSR_ZERO; - if ((int) T0 < 0) + if ((int32_t) T0 < 0) env->psr |= PSR_NEG; if (T0 < src1) env->psr |= PSR_CARRY; if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31)) env->psr |= PSR_OVF; + /* V9 xcc */ + FORCE_RET(); +} + +void OPPROTO op_addx_T1_T0(void) +{ + T0 += T1 + FLAG_SET(PSR_CARRY); +} + +void OPPROTO op_addx_T1_T0_cc(void) +{ + target_ulong src1; + + src1 = T0; + T0 += T1 + FLAG_SET(PSR_CARRY); + env->psr = 0; + if (!T0) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + if (T0 < src1) + env->psr |= PSR_CARRY; + if (((src1 ^ T1 ^ -1) & (src1 ^ T0)) & (1 << 31)) + env->psr |= PSR_OVF; + /* V9 xcc */ FORCE_RET(); } @@ -289,19 +295,44 @@ void OPPROTO op_sub_T1_T0(void) void OPPROTO op_sub_T1_T0_cc(void) { - unsigned int src1; + target_ulong src1; src1 = T0; T0 -= T1; env->psr = 0; if (!T0) env->psr |= PSR_ZERO; - if ((int) T0 < 0) + if ((int32_t) T0 < 0) env->psr |= PSR_NEG; if (src1 < T1) env->psr |= PSR_CARRY; if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31)) env->psr |= PSR_OVF; + /* V9 xcc */ + FORCE_RET(); +} + +void OPPROTO op_subx_T1_T0(void) +{ + T0 -= T1 + FLAG_SET(PSR_CARRY); +} + +void OPPROTO op_subx_T1_T0_cc(void) +{ + target_ulong src1; + + src1 = T0; + T0 -= T1 + FLAG_SET(PSR_CARRY); + env->psr = 0; + if (!T0) + env->psr |= PSR_ZERO; + if ((int32_t) T0 < 0) + env->psr |= PSR_NEG; + if (src1 < T1) + env->psr |= PSR_CARRY; + if (((src1 ^ T1) & (src1 ^ T0)) & (1 << 31)) + env->psr |= PSR_OVF; + /* V9 xcc */ FORCE_RET(); } @@ -335,15 +366,10 @@ void OPPROTO op_xnor_T1_T0(void) T0 ^= ~T1; } -void OPPROTO op_addx_T1_T0(void) -{ - T0 += T1 + ((env->psr & PSR_CARRY) ? 1 : 0); -} - void OPPROTO op_umul_T1_T0(void) { uint64_t res; - res = (uint64_t) T0 *(uint64_t) T1; + res = (uint64_t) T0 * (uint64_t) T1; T0 = res & 0xffffffff; env->y = res >> 32; } @@ -358,7 +384,9 @@ void OPPROTO op_smul_T1_T0(void) void OPPROTO op_mulscc_T1_T0(void) { - unsigned int b1, N, V, b2, src1; + unsigned int b1, N, V, b2; + target_ulong src1; + N = FLAG_SET(PSR_NEG); V = FLAG_SET(PSR_OVF); b1 = N ^ V; @@ -372,7 +400,7 @@ void OPPROTO op_mulscc_T1_T0(void) env->psr = 0; if (!T0) env->psr |= PSR_ZERO; - if ((int) T0 < 0) + if ((int32_t) T0 < 0) env->psr |= PSR_NEG; if (T0 < src1) env->psr |= PSR_CARRY; @@ -405,11 +433,11 @@ void OPPROTO op_sdiv_T1_T0(void) int64_t x0; int32_t x1; - x0 = T0 | ((uint64_t) (env->y) << 32); + x0 = T0 | ((int64_t) (env->y) << 32); x1 = T1; x0 = x0 / x1; if ((int32_t) x0 != x0) { - T0 = x0 >> 63; + T0 = x0 < 0? 0x80000000: 0x7fffffff; T1 = 1; } else { T0 = x0; @@ -423,39 +451,22 @@ void OPPROTO op_div_cc(void) env->psr = 0; if (!T0) env->psr |= PSR_ZERO; - if ((int) T0 < 0) + if ((int32_t) T0 < 0) env->psr |= PSR_NEG; if (T1) env->psr |= PSR_OVF; + /* V9 xcc */ FORCE_RET(); } -void OPPROTO op_subx_T1_T0(void) -{ - T0 -= T1 + ((env->psr & PSR_CARRY) ? 1 : 0); -} - void OPPROTO op_logic_T0_cc(void) { env->psr = 0; if (!T0) env->psr |= PSR_ZERO; - if ((int) T0 < 0) - env->psr |= PSR_NEG; - FORCE_RET(); -} - -void OPPROTO op_set_flags(void) -{ - env->psr = 0; - if (!T0) - env->psr |= PSR_ZERO; - if ((unsigned int) T0 < (unsigned int) T1) - env->psr |= PSR_CARRY; - if ((int) T0 < (int) T1) - env->psr |= PSR_OVF; - if ((int) T0 < 0) + if ((int32_t) T0 < 0) env->psr |= PSR_NEG; + /* V9 xcc */ FORCE_RET(); } @@ -519,12 +530,12 @@ void OPPROTO op_wrwim(void) void OPPROTO op_rdpsr(void) { - T0 = GET_PSR(env); + do_rdpsr(); } void OPPROTO op_wrpsr(void) { - PUT_PSR(env,T0); + do_wrpsr(); FORCE_RET(); } @@ -555,7 +566,7 @@ void raise_exception(int tt) handling ? */ void OPPROTO op_save(void) { - int cwp; + uint32_t cwp; cwp = (env->cwp - 1) & (NWINDOWS - 1); if (env->wim & (1 << cwp)) { raise_exception(TT_WIN_OVF); @@ -566,7 +577,7 @@ void OPPROTO op_save(void) void OPPROTO op_restore(void) { - int cwp; + uint32_t cwp; cwp = (env->cwp + 1) & (NWINDOWS - 1); if (env->wim & (1 << cwp)) { raise_exception(TT_WIN_UNF); @@ -626,84 +637,84 @@ void OPPROTO op_exit_tb(void) void OPPROTO op_eval_be(void) { - T2 = (env->psr & PSR_ZERO); + T2 = FLAG_SET(PSR_ZERO); } void OPPROTO op_eval_ble(void) { - unsigned int Z = FLAG_SET(PSR_ZERO), N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF); + target_ulong Z = FLAG_SET(PSR_ZERO), N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF); T2 = Z | (N ^ V); } void OPPROTO op_eval_bl(void) { - unsigned int N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF); + target_ulong N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF); T2 = N ^ V; } void OPPROTO op_eval_bleu(void) { - unsigned int Z = FLAG_SET(PSR_ZERO), C = FLAG_SET(PSR_CARRY); + target_ulong Z = FLAG_SET(PSR_ZERO), C = FLAG_SET(PSR_CARRY); T2 = C | Z; } void OPPROTO op_eval_bcs(void) { - T2 = (env->psr & PSR_CARRY); + T2 = FLAG_SET(PSR_CARRY); } void OPPROTO op_eval_bvs(void) { - T2 = (env->psr & PSR_OVF); + T2 = FLAG_SET(PSR_OVF); } void OPPROTO op_eval_bneg(void) { - T2 = (env->psr & PSR_NEG); + T2 = FLAG_SET(PSR_NEG); } void OPPROTO op_eval_bne(void) { - T2 = !(env->psr & PSR_ZERO); + T2 = !FLAG_SET(PSR_ZERO); } void OPPROTO op_eval_bg(void) { - unsigned int Z = FLAG_SET(PSR_ZERO), N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF); + target_ulong Z = FLAG_SET(PSR_ZERO), N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF); T2 = !(Z | (N ^ V)); } void OPPROTO op_eval_bge(void) { - unsigned int N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF); + target_ulong N = FLAG_SET(PSR_NEG), V = FLAG_SET(PSR_OVF); T2 = !(N ^ V); } void OPPROTO op_eval_bgu(void) { - unsigned int Z = FLAG_SET(PSR_ZERO), C = FLAG_SET(PSR_CARRY); + target_ulong Z = FLAG_SET(PSR_ZERO), C = FLAG_SET(PSR_CARRY); T2 = !(C | Z); } void OPPROTO op_eval_bcc(void) { - T2 = !(env->psr & PSR_CARRY); + T2 = !FLAG_SET(PSR_CARRY); } void OPPROTO op_eval_bpos(void) { - T2 = !(env->psr & PSR_NEG); + T2 = !FLAG_SET(PSR_NEG); } void OPPROTO op_eval_bvc(void) { - T2 = !(env->psr & PSR_OVF); + T2 = !FLAG_SET(PSR_OVF); } /* FCC1:FCC0: 0 =, 1 <, 2 >, 3 u */ @@ -792,16 +803,6 @@ void OPPROTO op_eval_fbo(void) T2 = !(FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1)); } -void OPPROTO op_movl_T2_0(void) -{ - T2 = 0; -} - -void OPPROTO op_movl_T2_1(void) -{ - T2 = 1; -} - void OPPROTO op_jmp_im(void) { env->pc = PARAM1; @@ -845,10 +846,10 @@ void OPPROTO op_branch_a(void) { if (T2) { env->npc = PARAM2; /* XXX: optimize */ - JUMP_TB(op_generic_branch_a, PARAM1, 0, PARAM3); + JUMP_TB(op_branch_a, PARAM1, 0, PARAM3); } else { env->npc = PARAM3 + 8; /* XXX: optimize */ - JUMP_TB(op_generic_branch_a, PARAM1, 1, PARAM3 + 4); + JUMP_TB(op_branch_a, PARAM1, 1, PARAM3 + 4); } FORCE_RET(); } diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index fecb80dcdd..2529cca720 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -209,7 +209,8 @@ void helper_st_asi(int asi, int size, int sign) void helper_rett() { - int cwp; + unsigned int cwp; + env->psret = 1; cwp = (env->cwp + 1) & (NWINDOWS - 1); if (env->wim & (1 << cwp)) { @@ -255,3 +256,13 @@ void helper_debug() env->exception_index = EXCP_DEBUG; cpu_loop_exit(); } + +void do_wrpsr() +{ + PUT_PSR(env, T0); +} + +void do_rdpsr() +{ + T0 = GET_PSR(env); +} diff --git a/target-sparc/op_mem.h b/target-sparc/op_mem.h index 995eb27d75..9f6ecefd8f 100644 --- a/target-sparc/op_mem.h +++ b/target-sparc/op_mem.h @@ -36,7 +36,7 @@ void OPPROTO glue(op_ldstub, MEMSUFFIX)(void) void OPPROTO glue(op_swap, MEMSUFFIX)(void) { - unsigned int tmp = glue(ldl, MEMSUFFIX)(T0); + target_ulong tmp = glue(ldl, MEMSUFFIX)(T0); glue(stl, MEMSUFFIX)(T0, T1); /* XXX: Should be Atomically */ T1 = tmp; } diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 7673bf2ddd..0baf8036e0 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -423,16 +423,13 @@ static inline void save_npc(DisasContext * dc) static inline void save_state(DisasContext * dc) { - gen_op_jmp_im((uint32_t)dc->pc); + gen_op_jmp_im(dc->pc); save_npc(dc); } static void gen_cond(int cond) { switch (cond) { - case 0x0: - gen_op_movl_T2_0(); - break; case 0x1: gen_op_eval_be(); break; @@ -454,9 +451,6 @@ static void gen_cond(int cond) case 0x7: gen_op_eval_bvs(); break; - case 0x8: - gen_op_movl_T2_1(); - break; case 0x9: gen_op_eval_bne(); break; @@ -485,9 +479,6 @@ static void gen_cond(int cond) static void gen_fcond(int cond) { switch (cond) { - case 0x0: - gen_op_movl_T2_0(); - break; case 0x1: gen_op_eval_fbne(); break; @@ -509,9 +500,6 @@ static void gen_fcond(int cond) case 0x7: gen_op_eval_fbu(); break; - case 0x8: - gen_op_movl_T2_1(); - break; case 0x9: gen_op_eval_fbe(); break; @@ -537,10 +525,11 @@ static void gen_fcond(int cond) } } -static void do_branch(DisasContext * dc, uint32_t target, uint32_t insn) +static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn) { unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29)); - target += (uint32_t) dc->pc; + target_ulong target = dc->pc + offset; + if (cond == 0x0) { /* unconditional not taken */ if (a) { @@ -574,10 +563,11 @@ static void do_branch(DisasContext * dc, uint32_t target, uint32_t insn) } } -static void do_fbranch(DisasContext * dc, uint32_t target, uint32_t insn) +static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn) { unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29)); - target += (uint32_t) dc->pc; + target_ulong target = dc->pc + offset; + if (cond == 0x0) { /* unconditional not taken */ if (a) { @@ -611,15 +601,6 @@ static void do_fbranch(DisasContext * dc, uint32_t target, uint32_t insn) } } -#if 0 -static void gen_debug(DisasContext *s, uint32_t pc) -{ - gen_op_jmp_im(pc); - gen_op_debug(); - s->is_br = 1; -} -#endif - #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1) static int sign_extend(int x, int len) @@ -640,12 +621,13 @@ static void disas_sparc_insn(DisasContext * dc) case 0: /* branches/sethi */ { unsigned int xop = GET_FIELD(insn, 7, 9); - int target; + int32_t target; target = GET_FIELD(insn, 10, 31); switch (xop) { - case 0x0: - case 0x1: /* UNIMPL */ - case 0x5: /*CBN+x */ + case 0x0: /* UNIMPL */ + case 0x1: /* V9 BPcc */ + case 0x3: /* V9 BPr */ + case 0x5: /* V9 FBPcc */ default: goto illegal_insn; case 0x2: /* BN+x */ @@ -679,13 +661,14 @@ static void disas_sparc_insn(DisasContext * dc) } break; } + break; case 1: /*CALL*/ { - unsigned int target = GET_FIELDs(insn, 2, 31) << 2; + target_long target = GET_FIELDs(insn, 2, 31) << 2; - gen_op_movl_T0_im((long) (dc->pc)); + gen_op_movl_T0_im(dc->pc); gen_movl_T0_reg(15); - target = dc->pc + target; + target += dc->pc; dc->pc = dc->npc; dc->npc = target; } @@ -719,12 +702,13 @@ static void disas_sparc_insn(DisasContext * dc) #endif } save_state(dc); + /* V9 icc/xcc */ cond = GET_FIELD(insn, 3, 6); if (cond == 0x8) { gen_op_trap_T0(); dc->is_br = 1; goto jmp_insn; - } else { + } else if (cond != 0) { gen_cond(cond); gen_op_trapcc_T0(); } @@ -735,9 +719,14 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_rdy(); gen_movl_T0_reg(rd); break; - case 15: /* stbar */ + case 15: /* stbar / V9 membar */ break; /* no effect? */ default: + case 0x2: /* V9 rdccr */ + case 0x3: /* V9 rdasi */ + case 0x4: /* V9 rdtick */ + case 0x5: /* V9 rdpc */ + case 0x6: /* V9 rdfprs */ goto illegal_insn; } #if !defined(CONFIG_USER_ONLY) @@ -901,6 +890,19 @@ static void disas_sparc_insn(DisasContext * dc) case 0xd3: /* fqtoi */ goto nfpu_insn; default: + case 0x2: /* V9 fmovd */ + case 0x6: /* V9 fnegd */ + case 0xa: /* V9 fabsd */ + case 0x81: /* V9 fstox */ + case 0x82: /* V9 fdtox */ + case 0x84: /* V9 fxtos */ + case 0x88: /* V9 fxtod */ + + case 0x3: /* V9 fmovq */ + case 0x7: /* V9 fnegq */ + case 0xb: /* V9 fabsq */ + case 0x83: /* V9 fqtox */ + case 0x8c: /* V9 fxtoq */ goto illegal_insn; } } else if (xop == 0x35) { /* FPU Operations */ @@ -910,6 +912,10 @@ static void disas_sparc_insn(DisasContext * dc) rs1 = GET_FIELD(insn, 13, 17); rs2 = GET_FIELD(insn, 27, 31); xop = GET_FIELD(insn, 18, 26); + /* V9 fmovscc: x5, cond = x >> 1 */ + /* V9 fmovdcc: x6, cond = x >> 1 */ + + /* V9 fmovqcc: x7, cond = x >> 1 */ switch (xop) { case 0x51: gen_op_load_fpr_FT0(rs1); @@ -1028,9 +1034,10 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_logic_T0_cc(); break; case 0x8: - gen_op_addx_T1_T0(); if (xop & 0x10) - gen_op_set_flags(); + gen_op_addx_T1_T0_cc(); + else + gen_op_addx_T1_T0(); break; case 0xa: gen_op_umul_T1_T0(); @@ -1043,9 +1050,10 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_logic_T0_cc(); break; case 0xc: - gen_op_subx_T1_T0(); if (xop & 0x10) - gen_op_set_flags(); + gen_op_subx_T1_T0_cc(); + else + gen_op_subx_T1_T0(); break; case 0xe: gen_op_udiv_T1_T0(); @@ -1058,6 +1066,8 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_div_cc(); break; default: + case 0x9: /* V9 mulx */ + case 0xd: /* V9 udivx */ goto illegal_insn; } gen_movl_T0_reg(rd); @@ -1072,15 +1082,15 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_mulscc_T1_T0(); gen_movl_T0_reg(rd); break; - case 0x25: /* SLL */ + case 0x25: /* sll, V9 sllx */ gen_op_sll(); gen_movl_T0_reg(rd); break; - case 0x26: + case 0x26: /* srl, V9 srlx */ gen_op_srl(); gen_movl_T0_reg(rd); break; - case 0x27: + case 0x27: /* sra, V9 srax */ gen_op_sra(); gen_movl_T0_reg(rd); break; @@ -1092,12 +1102,16 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_wry(); break; default: + case 0x2: /* V9 wrccr */ + case 0x3: /* V9 wrasi */ + case 0x6: /* V9 wrfprs */ + case 0xf: /* V9 sir */ goto illegal_insn; } } break; #if !defined(CONFIG_USER_ONLY) - case 0x31: + case 0x31: /* wrpsr, V9 saved, restored */ { if (!supervisor(dc)) goto priv_insn; @@ -1105,7 +1119,7 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_wrpsr(); } break; - case 0x32: + case 0x32: /* wrwim, V9 wrpr */ { if (!supervisor(dc)) goto priv_insn; @@ -1123,6 +1137,12 @@ static void disas_sparc_insn(DisasContext * dc) break; #endif default: + case 0x2a: /* V9 rdpr */ + case 0x2b: /* V9 flushw */ + case 0x2c: /* V9 movcc */ + case 0x2d: /* V9 sdivx */ + case 0x2e: /* V9 popc */ + case 0x2f: /* V9 movr */ goto illegal_insn; } } @@ -1155,7 +1175,7 @@ static void disas_sparc_insn(DisasContext * dc) { gen_op_movl_npc_T0(); if (rd != 0) { - gen_op_movl_T0_im((long) (dc->pc)); + gen_op_movl_T0_im(dc->pc); gen_movl_T0_reg(rd); } dc->pc = dc->npc; @@ -1163,7 +1183,7 @@ static void disas_sparc_insn(DisasContext * dc) } goto jmp_insn; #if !defined(CONFIG_USER_ONLY) - case 0x39: /* rett */ + case 0x39: /* rett, V9 return */ { if (!supervisor(dc)) goto priv_insn; @@ -1186,11 +1206,13 @@ static void disas_sparc_insn(DisasContext * dc) gen_movl_T0_reg(rd); break; default: + case 0x3e: /* V9 done/retry */ goto illegal_insn; } } break; } + break; case 3: /* load/store instructions */ { unsigned int xop = GET_FIELD(insn, 7, 12); @@ -1297,6 +1319,16 @@ static void disas_sparc_insn(DisasContext * dc) (void) &gen_op_lddfa; #endif default: + case 0x08: /* V9 ldsw */ + case 0x0b: /* V9 ldx */ + case 0x18: /* V9 ldswa */ + case 0x1b: /* V9 ldxa */ + case 0x2d: /* V9 prefetch */ + case 0x30: /* V9 ldfa */ + case 0x33: /* V9 lddfa */ + case 0x3d: /* V9 prefetcha */ + + case 0x32: /* V9 ldqfa */ goto illegal_insn; } gen_movl_T1_reg(rd); @@ -1313,6 +1345,8 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_ldfsr(); gen_op_store_FT0_fpr(rd); break; + case 0x22: /* load quad fpreg */ + goto nfpu_insn; case 0x23: /* load double fpreg */ gen_op_ldst(lddf); gen_op_store_DT0_fpr(rd); @@ -1362,6 +1396,8 @@ static void disas_sparc_insn(DisasContext * dc) break; #endif default: + case 0x0e: /* V9 stx */ + case 0x1e: /* V9 stxa */ goto illegal_insn; } } else if (xop > 0x23 && xop < 0x28) { @@ -1373,16 +1409,23 @@ static void disas_sparc_insn(DisasContext * dc) gen_op_load_fpr_FT0(rd); gen_op_ldst(stf); break; - case 0x25: + case 0x25: /* stfsr, V9 stxfsr */ gen_op_load_fpr_FT0(rd); gen_op_stfsr(); break; + case 0x26: /* stdfq */ + goto nfpu_insn; case 0x27: gen_op_load_fpr_DT0(rd); gen_op_ldst(stdf); break; - case 0x26: /* stdfq */ default: + case 0x34: /* V9 stfa */ + case 0x37: /* V9 stdfa */ + case 0x3c: /* V9 casa */ + case 0x3e: /* V9 casxa */ + + case 0x36: /* V9 stqfa */ goto illegal_insn; } } else if (xop > 0x33 && xop < 0x38) { @@ -1392,6 +1435,7 @@ static void disas_sparc_insn(DisasContext * dc) else goto illegal_insn; } + break; } /* default case for non jump instructions */ if (dc->npc == DYNAMIC_PC) { @@ -1589,22 +1633,22 @@ void cpu_dump_state(CPUState *env, FILE *f, { int i, x; - cpu_fprintf(f, "pc: 0x%08x npc: 0x%08x\n", (int) env->pc, (int) env->npc); + cpu_fprintf(f, "pc: " TARGET_FMT_lx " npc: " TARGET_FMT_lx "\n", env->pc, env->npc); cpu_fprintf(f, "General Registers:\n"); for (i = 0; i < 4; i++) - cpu_fprintf(f, "%%g%c: 0x%08x\t", i + '0', env->gregs[i]); + cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]); cpu_fprintf(f, "\n"); for (; i < 8; i++) - cpu_fprintf(f, "%%g%c: 0x%08x\t", i + '0', env->gregs[i]); + cpu_fprintf(f, "%%g%c: " TARGET_FMT_lx "\t", i + '0', env->gregs[i]); cpu_fprintf(f, "\nCurrent Register Window:\n"); for (x = 0; x < 3; x++) { for (i = 0; i < 4; i++) - cpu_fprintf(f, "%%%c%d: 0x%08x\t", + cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t", (x == 0 ? 'o' : (x == 1 ? 'l' : 'i')), i, env->regwptr[i + x * 8]); cpu_fprintf(f, "\n"); for (; i < 8; i++) - cpu_fprintf(f, "%%%c%d: 0x%08x\t", + cpu_fprintf(f, "%%%c%d: " TARGET_FMT_lx "\t", (x == 0 ? 'o' : x == 1 ? 'l' : 'i'), i, env->regwptr[i + x * 8]); cpu_fprintf(f, "\n"); @@ -1626,19 +1670,19 @@ void cpu_dump_state(CPUState *env, FILE *f, } #if defined(CONFIG_USER_ONLY) -target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) +target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) { return addr; } #else -extern int get_physical_address (CPUState *env, uint32_t *physical, int *prot, - int *access_index, uint32_t address, int rw, +extern int get_physical_address (CPUState *env, target_phys_addr_t *physical, int *prot, + int *access_index, target_ulong address, int rw, int is_user); -target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr) +target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) { - uint32_t phys_addr; + target_phys_addr_t phys_addr; int prot, access_index; if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)