Commit e8af50a30e89e5cfdc1b2a2fa8fab3ce463a4790

Authored by bellard
1 parent 525d67bc

full system SPARC emulation (Blue Swirl)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1083 c046a42c-6fe2-441c-8c8c-71466251a162
target-sparc/cpu.h
... ... @@ -9,8 +9,10 @@
9 9  
10 10 /* trap definitions */
11 11 #define TT_ILL_INSN 0x02
  12 +#define TT_PRIV_INSN 0x03
12 13 #define TT_WIN_OVF 0x05
13 14 #define TT_WIN_UNF 0x06
  15 +#define TT_FP_EXCP 0x08
14 16 #define TT_DIV_ZERO 0x2a
15 17 #define TT_TRAP 0x80
16 18  
... ... @@ -18,27 +20,101 @@
18 20 #define PSR_ZERO (1<<22)
19 21 #define PSR_OVF (1<<21)
20 22 #define PSR_CARRY (1<<20)
  23 +#define PSR_ICC (PSR_NEG|PSR_ZERO|PSR_OVF|PSR_CARRY)
  24 +#define PSR_S (1<<7)
  25 +#define PSR_PS (1<<6)
  26 +#define PSR_ET (1<<5)
  27 +#define PSR_CWP 0x1f
  28 +/* Fake impl 0, version 4 */
  29 +#define GET_PSR(env) ((0<<28) | (4<<24) | env->psr | (env->psrs? PSR_S : 0) | (env->psrs? PSR_PS : 0) |(env->psret? PSR_ET : 0) | env->cwp)
  30 +
  31 +/* Trap base register */
  32 +#define TBR_BASE_MASK 0xfffff000
  33 +
  34 +/* Fcc */
  35 +#define FSR_RD1 (1<<31)
  36 +#define FSR_RD0 (1<<30)
  37 +#define FSR_RD_MASK (FSR_RD1 | FSR_RD0)
  38 +#define FSR_RD_NEAREST 0
  39 +#define FSR_RD_ZERO FSR_RD0
  40 +#define FSR_RD_POS FSR_RD1
  41 +#define FSR_RD_NEG (FSR_RD1 | FSR_RD0)
  42 +
  43 +#define FSR_NVM (1<<27)
  44 +#define FSR_OFM (1<<26)
  45 +#define FSR_UFM (1<<25)
  46 +#define FSR_DZM (1<<24)
  47 +#define FSR_NXM (1<<23)
  48 +#define FSR_TEM_MASK (FSR_NVM | FSR_OFM | FSR_UFM | FSR_DZM | FSR_NXM)
  49 +
  50 +#define FSR_NVA (1<<9)
  51 +#define FSR_OFA (1<<8)
  52 +#define FSR_UFA (1<<7)
  53 +#define FSR_DZA (1<<6)
  54 +#define FSR_NXA (1<<5)
  55 +#define FSR_AEXC_MASK (FSR_NVA | FSR_OFA | FSR_UFA | FSR_DZA | FSR_NXA)
  56 +
  57 +#define FSR_NVC (1<<4)
  58 +#define FSR_OFC (1<<3)
  59 +#define FSR_UFC (1<<2)
  60 +#define FSR_DZC (1<<1)
  61 +#define FSR_NXC (1<<0)
  62 +#define FSR_CEXC_MASK (FSR_NVC | FSR_OFC | FSR_UFC | FSR_DZC | FSR_NXC)
  63 +
  64 +#define FSR_FTT2 (1<<16)
  65 +#define FSR_FTT1 (1<<15)
  66 +#define FSR_FTT0 (1<<14)
  67 +#define FSR_FTT_MASK (FSR_FTT2 | FSR_FTT1 | FSR_FTT0)
  68 +
  69 +#define FSR_FCC1 (1<<11)
  70 +#define FSR_FCC0 (1<<10)
  71 +
  72 +/* MMU */
  73 +#define MMU_E (1<<0)
  74 +#define MMU_NF (1<<1)
  75 +
  76 +#define PTE_ENTRYTYPE_MASK 3
  77 +#define PTE_ACCESS_MASK 0x1c
  78 +#define PTE_ACCESS_SHIFT 2
  79 +#define PTE_ADDR_MASK 0xffffff00
  80 +
  81 +#define PG_ACCESSED_BIT 5
  82 +#define PG_MODIFIED_BIT 6
  83 +#define PG_CACHE_BIT 7
  84 +
  85 +#define PG_ACCESSED_MASK (1 << PG_ACCESSED_BIT)
  86 +#define PG_MODIFIED_MASK (1 << PG_MODIFIED_BIT)
  87 +#define PG_CACHE_MASK (1 << PG_CACHE_BIT)
  88 +
  89 +#define ACCESS_DATA 0
  90 +#define ACCESS_CODE 1
  91 +#define ACCESS_MMU 2
21 92  
22 93 #define NWINDOWS 32
23 94  
24 95 typedef struct CPUSPARCState {
25 96 uint32_t gregs[8]; /* general registers */
26 97 uint32_t *regwptr; /* pointer to current register window */
27   - double *regfptr; /* floating point registers */
  98 + float fpr[32]; /* floating point registers */
28 99 uint32_t pc; /* program counter */
29 100 uint32_t npc; /* next program counter */
30   - uint32_t sp; /* stack pointer */
31 101 uint32_t y; /* multiply/divide register */
32 102 uint32_t psr; /* processor state register */
  103 + uint32_t fsr; /* FPU state register */
33 104 uint32_t T2;
34 105 uint32_t cwp; /* index of current register window (extracted
35 106 from PSR) */
36 107 uint32_t wim; /* window invalid mask */
  108 + uint32_t tbr; /* trap base register */
  109 + int psrs; /* supervisor mode (extracted from PSR) */
  110 + int psrps; /* previous supervisor mode */
  111 + int psret; /* enable traps */
37 112 jmp_buf jmp_env;
38 113 int user_mode_only;
39 114 int exception_index;
40 115 int interrupt_index;
41 116 int interrupt_request;
  117 + uint32_t exception_next_pc;
42 118 struct TranslationBlock *current_tb;
43 119 void *opaque;
44 120 /* NOTE: we allow 8 more registers to handle wrapping */
... ... @@ -51,6 +127,22 @@ typedef struct CPUSPARCState {
51 127 written */
52 128 unsigned long mem_write_vaddr; /* target virtual addr at which the
53 129 memory was written */
  130 + /* 0 = kernel, 1 = user (may have 2 = kernel code, 3 = user code ?) */
  131 + CPUTLBEntry tlb_read[2][CPU_TLB_SIZE];
  132 + CPUTLBEntry tlb_write[2][CPU_TLB_SIZE];
  133 + int error_code;
  134 + int access_type;
  135 + /* MMU regs */
  136 + uint32_t mmuregs[16];
  137 + /* temporary float registers */
  138 + float ft0, ft1, ft2;
  139 + double dt0, dt1, dt2;
  140 +
  141 + /* ice debug support */
  142 + uint32_t breakpoints[MAX_BREAKPOINTS];
  143 + int nb_breakpoints;
  144 + int singlestep_enabled; /* XXX: should use CPU single step mode instead */
  145 +
54 146 } CPUSPARCState;
55 147  
56 148 CPUSPARCState *cpu_sparc_init(void);
... ... @@ -61,7 +153,7 @@ struct siginfo;
61 153 int cpu_sparc_signal_handler(int hostsignum, struct siginfo *info, void *puc);
62 154 void cpu_sparc_dump_state(CPUSPARCState *env, FILE *f, int flags);
63 155  
64   -#define TARGET_PAGE_BITS 13
  156 +#define TARGET_PAGE_BITS 12 /* 4k */
65 157 #include "cpu-all.h"
66 158  
67 159 #endif
... ...
target-sparc/exec.h
... ... @@ -6,6 +6,12 @@ register struct CPUSPARCState *env asm(AREG0);
6 6 register uint32_t T0 asm(AREG1);
7 7 register uint32_t T1 asm(AREG2);
8 8 register uint32_t T2 asm(AREG3);
  9 +#define FT0 (env->ft0)
  10 +#define FT1 (env->ft1)
  11 +#define FT2 (env->ft2)
  12 +#define DT0 (env->dt0)
  13 +#define DT1 (env->dt1)
  14 +#define DT2 (env->dt2)
9 15  
10 16 #include "cpu.h"
11 17 #include "exec-all.h"
... ... @@ -14,4 +20,88 @@ void cpu_lock(void);
14 20 void cpu_unlock(void);
15 21 void cpu_loop_exit(void);
16 22 void helper_flush(target_ulong addr);
  23 +void helper_ld_asi(int asi, int size, int sign);
  24 +void helper_st_asi(int asi, int size, int sign);
  25 +void helper_rett(void);
  26 +void helper_stfsr(void);
  27 +void set_cwp(int new_cwp);
  28 +void do_fabss(void);
  29 +void do_fsqrts(void);
  30 +void do_fsqrtd(void);
  31 +void do_fcmps(void);
  32 +void do_fcmpd(void);
  33 +void do_interrupt(int intno, int is_int, int error_code,
  34 + unsigned int next_eip, int is_hw);
  35 +void raise_exception_err(int exception_index, int error_code);
  36 +void raise_exception(int tt);
  37 +void memcpy32(uint32_t *dst, const uint32_t *src);
  38 +
  39 +/* XXX: move that to a generic header */
  40 +#if !defined(CONFIG_USER_ONLY)
  41 +
  42 +#define ldul_user ldl_user
  43 +#define ldul_kernel ldl_kernel
  44 +
  45 +#define ACCESS_TYPE 0
  46 +#define MEMSUFFIX _kernel
  47 +#define DATA_SIZE 1
  48 +#include "softmmu_header.h"
  49 +
  50 +#define DATA_SIZE 2
  51 +#include "softmmu_header.h"
  52 +
  53 +#define DATA_SIZE 4
  54 +#include "softmmu_header.h"
  55 +
  56 +#define DATA_SIZE 8
  57 +#include "softmmu_header.h"
  58 +#undef ACCESS_TYPE
  59 +#undef MEMSUFFIX
  60 +
  61 +#define ACCESS_TYPE 1
  62 +#define MEMSUFFIX _user
  63 +#define DATA_SIZE 1
  64 +#include "softmmu_header.h"
  65 +
  66 +#define DATA_SIZE 2
  67 +#include "softmmu_header.h"
  68 +
  69 +#define DATA_SIZE 4
  70 +#include "softmmu_header.h"
  71 +
  72 +#define DATA_SIZE 8
  73 +#include "softmmu_header.h"
  74 +#undef ACCESS_TYPE
  75 +#undef MEMSUFFIX
  76 +
  77 +/* these access are slower, they must be as rare as possible */
  78 +#define ACCESS_TYPE 2
  79 +#define MEMSUFFIX _data
  80 +#define DATA_SIZE 1
  81 +#include "softmmu_header.h"
  82 +
  83 +#define DATA_SIZE 2
  84 +#include "softmmu_header.h"
  85 +
  86 +#define DATA_SIZE 4
  87 +#include "softmmu_header.h"
  88 +
  89 +#define DATA_SIZE 8
  90 +#include "softmmu_header.h"
  91 +#undef ACCESS_TYPE
  92 +#undef MEMSUFFIX
  93 +
  94 +#define ldub(p) ldub_data(p)
  95 +#define ldsb(p) ldsb_data(p)
  96 +#define lduw(p) lduw_data(p)
  97 +#define ldsw(p) ldsw_data(p)
  98 +#define ldl(p) ldl_data(p)
  99 +#define ldq(p) ldq_data(p)
  100 +
  101 +#define stb(p, v) stb_data(p, v)
  102 +#define stw(p, v) stw_data(p, v)
  103 +#define stl(p, v) stl_data(p, v)
  104 +#define stq(p, v) stq_data(p, v)
  105 +
  106 +#endif /* !defined(CONFIG_USER_ONLY) */
17 107 #endif
... ...
target-sparc/fop_template.h 0 โ†’ 100644
  1 +/*
  2 + * SPARC micro operations (templates for various register related
  3 + * operations)
  4 + *
  5 + * Copyright (c) 2003 Fabrice Bellard
  6 + *
  7 + * This library is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU Lesser General Public
  9 + * License as published by the Free Software Foundation; either
  10 + * version 2 of the License, or (at your option) any later version.
  11 + *
  12 + * This library is distributed in the hope that it will be useful,
  13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15 + * Lesser General Public License for more details.
  16 + *
  17 + * You should have received a copy of the GNU Lesser General Public
  18 + * License along with this library; if not, write to the Free Software
  19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20 + */
  21 +
  22 +/* floating point registers moves */
  23 +void OPPROTO glue(op_load_fpr_FT0_fpr, REGNAME)(void)
  24 +{
  25 + FT0 = REG;
  26 +}
  27 +
  28 +void OPPROTO glue(op_store_FT0_fpr_fpr, REGNAME)(void)
  29 +{
  30 + REG = FT0;
  31 +}
  32 +
  33 +void OPPROTO glue(op_load_fpr_FT1_fpr, REGNAME)(void)
  34 +{
  35 + FT1 = REG;
  36 +}
  37 +
  38 +void OPPROTO glue(op_store_FT1_fpr_fpr, REGNAME)(void)
  39 +{
  40 + REG = FT1;
  41 +}
  42 +
  43 +void OPPROTO glue(op_load_fpr_FT2_fpr, REGNAME)(void)
  44 +{
  45 + FT2 = REG;
  46 +}
  47 +
  48 +void OPPROTO glue(op_store_FT2_fpr_fpr, REGNAME)(void)
  49 +{
  50 + REG = FT2;
  51 +}
  52 +
  53 +/* double floating point registers moves */
  54 +#if 0
  55 +#define CPU_DOUBLE_U_DEF
  56 +typedef union {
  57 + double d;
  58 + struct {
  59 + uint32_t lower;
  60 + uint32_t upper;
  61 + } l;
  62 + uint64_t ll;
  63 +} CPU_DoubleU;
  64 +#endif /* CPU_DOUBLE_U_DEF */
  65 +
  66 +void OPPROTO glue(op_load_fpr_DT0_fpr, REGNAME)(void)
  67 +{
  68 + CPU_DoubleU u;
  69 + uint32_t *p = (uint32_t *)&REG;
  70 + u.l.lower = *(p +1);
  71 + u.l.upper = *p;
  72 + DT0 = u.d;
  73 +}
  74 +
  75 +void OPPROTO glue(op_store_DT0_fpr_fpr, REGNAME)(void)
  76 +{
  77 + CPU_DoubleU u;
  78 + uint32_t *p = (uint32_t *)&REG;
  79 + u.d = DT0;
  80 + *(p +1) = u.l.lower;
  81 + *p = u.l.upper;
  82 +}
  83 +
  84 +void OPPROTO glue(op_load_fpr_DT1_fpr, REGNAME)(void)
  85 +{
  86 + CPU_DoubleU u;
  87 + uint32_t *p = (uint32_t *)&REG;
  88 + u.l.lower = *(p +1);
  89 + u.l.upper = *p;
  90 + DT1 = u.d;
  91 +}
  92 +
  93 +void OPPROTO glue(op_store_DT1_fpr_fpr, REGNAME)(void)
  94 +{
  95 + CPU_DoubleU u;
  96 + uint32_t *p = (uint32_t *)&REG;
  97 + u.d = DT1;
  98 + *(p +1) = u.l.lower;
  99 + *p = u.l.upper;
  100 +}
  101 +
  102 +void OPPROTO glue(op_load_fpr_DT2_fpr, REGNAME)(void)
  103 +{
  104 + CPU_DoubleU u;
  105 + uint32_t *p = (uint32_t *)&REG;
  106 + u.l.lower = *(p +1);
  107 + u.l.upper = *p;
  108 + DT2 = u.d;
  109 +}
  110 +
  111 +void OPPROTO glue(op_store_DT2_fpr_fpr, REGNAME)(void)
  112 +{
  113 + CPU_DoubleU u;
  114 + uint32_t *p = (uint32_t *)&REG;
  115 + u.d = DT2;
  116 + *(p +1) = u.l.lower;
  117 + *p = u.l.upper;
  118 +}
  119 +
  120 +#undef REG
  121 +#undef REGNAME
... ...
target-sparc/helper.c 0 โ†’ 100644
  1 +/*
  2 + * sparc helpers
  3 + *
  4 + * Copyright (c) 2003 Fabrice Bellard
  5 + *
  6 + * This library is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU Lesser General Public
  8 + * License as published by the Free Software Foundation; either
  9 + * version 2 of the License, or (at your option) any later version.
  10 + *
  11 + * This library is distributed in the hope that it will be useful,
  12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14 + * Lesser General Public License for more details.
  15 + *
  16 + * You should have received a copy of the GNU Lesser General Public
  17 + * License along with this library; if not, write to the Free Software
  18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  19 + */
  20 +#include "exec.h"
  21 +
  22 +#define DEBUG_PCALL
  23 +
  24 +#if 0
  25 +#define raise_exception_err(a, b)\
  26 +do {\
  27 + fprintf(logfile, "raise_exception line=%d\n", __LINE__);\
  28 + (raise_exception_err)(a, b);\
  29 +} while (0)
  30 +#endif
  31 +
  32 +/* Sparc MMU emulation */
  33 +int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
  34 + int is_user, int is_softmmu);
  35 +
  36 +
  37 +/* thread support */
  38 +
  39 +spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
  40 +
  41 +void cpu_lock(void)
  42 +{
  43 + spin_lock(&global_cpu_lock);
  44 +}
  45 +
  46 +void cpu_unlock(void)
  47 +{
  48 + spin_unlock(&global_cpu_lock);
  49 +}
  50 +
  51 +#if 0
  52 +void cpu_loop_exit(void)
  53 +{
  54 + /* NOTE: the register at this point must be saved by hand because
  55 + longjmp restore them */
  56 + longjmp(env->jmp_env, 1);
  57 +}
  58 +#endif
  59 +
  60 +#if !defined(CONFIG_USER_ONLY)
  61 +
  62 +#define MMUSUFFIX _mmu
  63 +#define GETPC() (__builtin_return_address(0))
  64 +
  65 +#define SHIFT 0
  66 +#include "softmmu_template.h"
  67 +
  68 +#define SHIFT 1
  69 +#include "softmmu_template.h"
  70 +
  71 +#define SHIFT 2
  72 +#include "softmmu_template.h"
  73 +
  74 +#define SHIFT 3
  75 +#include "softmmu_template.h"
  76 +
  77 +
  78 +/* try to fill the TLB and return an exception if error. If retaddr is
  79 + NULL, it means that the function was called in C code (i.e. not
  80 + from generated code or from helper.c) */
  81 +/* XXX: fix it to restore all registers */
  82 +void tlb_fill(unsigned long addr, int is_write, int is_user, void *retaddr)
  83 +{
  84 + TranslationBlock *tb;
  85 + int ret;
  86 + unsigned long pc;
  87 + CPUState *saved_env;
  88 +
  89 + /* XXX: hack to restore env in all cases, even if not called from
  90 + generated code */
  91 + saved_env = env;
  92 + env = cpu_single_env;
  93 +
  94 + ret = cpu_sparc_handle_mmu_fault(env, addr, is_write, is_user, 1);
  95 + if (ret) {
  96 + if (retaddr) {
  97 + /* now we have a real cpu fault */
  98 + pc = (unsigned long)retaddr;
  99 + tb = tb_find_pc(pc);
  100 + if (tb) {
  101 + /* the PC is inside the translated code. It means that we have
  102 + a virtual CPU fault */
  103 + cpu_restore_state(tb, env, pc, NULL);
  104 + }
  105 + }
  106 + raise_exception_err(ret, env->error_code);
  107 + }
  108 + env = saved_env;
  109 +}
  110 +#endif
  111 +
  112 +static const int access_table[8][8] = {
  113 + { 0, 0, 0, 0, 2, 0, 3, 3 },
  114 + { 0, 0, 0, 0, 2, 0, 0, 0 },
  115 + { 2, 2, 0, 0, 0, 2, 3, 3 },
  116 + { 2, 2, 0, 0, 0, 2, 0, 0 },
  117 + { 2, 0, 2, 0, 2, 2, 3, 3 },
  118 + { 2, 0, 2, 0, 2, 0, 2, 0 },
  119 + { 2, 2, 2, 0, 2, 2, 3, 3 },
  120 + { 2, 2, 2, 0, 2, 2, 2, 0 }
  121 +};
  122 +
  123 +/* 1 = write OK */
  124 +static const int rw_table[2][8] = {
  125 + { 0, 1, 0, 1, 0, 1, 0, 1 },
  126 + { 0, 1, 0, 1, 0, 0, 0, 0 }
  127 +};
  128 +
  129 +
  130 +/* Perform address translation */
  131 +int cpu_sparc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
  132 + int is_user, int is_softmmu)
  133 +{
  134 + int exception = 0;
  135 + int access_type, access_perms = 0, access_index = 0;
  136 + uint8_t *pde_ptr;
  137 + uint32_t pde, virt_addr;
  138 + int error_code = 0, is_dirty, prot, ret = 0;
  139 + unsigned long paddr, vaddr, page_offset;
  140 +
  141 + access_type = env->access_type;
  142 + if (env->user_mode_only) {
  143 + /* user mode only emulation */
  144 + ret = -2;
  145 + goto do_fault;
  146 + }
  147 +
  148 + virt_addr = address & TARGET_PAGE_MASK;
  149 + if ((env->mmuregs[0] & MMU_E) == 0) { /* MMU disabled */
  150 + paddr = address;
  151 + page_offset = address & (TARGET_PAGE_SIZE - 1);
  152 + prot = PAGE_READ | PAGE_WRITE;
  153 + goto do_mapping;
  154 + }
  155 +
  156 + /* SPARC reference MMU table walk: Context table->L1->L2->PTE */
  157 + /* Context base + context number */
  158 + pde_ptr = phys_ram_base + (env->mmuregs[1] << 4) + (env->mmuregs[2] << 4);
  159 + env->access_type = ACCESS_MMU;
  160 + pde = ldl_raw(pde_ptr);
  161 +
  162 + /* Ctx pde */
  163 + switch (pde & PTE_ENTRYTYPE_MASK) {
  164 + case 0: /* Invalid */
  165 + error_code = 1;
  166 + goto do_fault;
  167 + case 2: /* PTE, maybe should not happen? */
  168 + case 3: /* Reserved */
  169 + error_code = 4;
  170 + goto do_fault;
  171 + case 1: /* L1 PDE */
  172 + pde_ptr = phys_ram_base + ((address >> 22) & ~3) + ((pde & ~3) << 4);
  173 + pde = ldl_raw(pde_ptr);
  174 +
  175 + switch (pde & PTE_ENTRYTYPE_MASK) {
  176 + case 0: /* Invalid */
  177 + error_code = 1;
  178 + goto do_fault;
  179 + case 3: /* Reserved */
  180 + error_code = 4;
  181 + goto do_fault;
  182 + case 1: /* L2 PDE */
  183 + pde_ptr = phys_ram_base + ((address & 0xfc0000) >> 16) + ((pde & ~3) << 4);
  184 + pde = ldl_raw(pde_ptr);
  185 +
  186 + switch (pde & PTE_ENTRYTYPE_MASK) {
  187 + case 0: /* Invalid */
  188 + error_code = 1;
  189 + goto do_fault;
  190 + case 3: /* Reserved */
  191 + error_code = 4;
  192 + goto do_fault;
  193 + case 1: /* L3 PDE */
  194 + pde_ptr = phys_ram_base + ((address & 0x3f000) >> 10) + ((pde & ~3) << 4);
  195 + pde = ldl_raw(pde_ptr);
  196 +
  197 + switch (pde & PTE_ENTRYTYPE_MASK) {
  198 + case 0: /* Invalid */
  199 + error_code = 1;
  200 + goto do_fault;
  201 + case 1: /* PDE, should not happen */
  202 + case 3: /* Reserved */
  203 + error_code = 4;
  204 + goto do_fault;
  205 + case 2: /* L3 PTE */
  206 + virt_addr = address & TARGET_PAGE_MASK;
  207 + page_offset = (address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1);
  208 + }
  209 + break;
  210 + case 2: /* L2 PTE */
  211 + virt_addr = address & ~0x3ffff;
  212 + page_offset = address & 0x3ffff;
  213 + }
  214 + break;
  215 + case 2: /* L1 PTE */
  216 + virt_addr = address & ~0xffffff;
  217 + page_offset = address & 0xffffff;
  218 + }
  219 + }
  220 +
  221 + /* update page modified and dirty bits */
  222 + is_dirty = rw && !(pde & PG_MODIFIED_MASK);
  223 + if (!(pde & PG_ACCESSED_MASK) || is_dirty) {
  224 + pde |= PG_ACCESSED_MASK;
  225 + if (is_dirty)
  226 + pde |= PG_MODIFIED_MASK;
  227 + stl_raw(pde_ptr, pde);
  228 + }
  229 +
  230 + /* check access */
  231 + access_index = (rw << 2) | ((access_type == ACCESS_CODE)? 2 : 0) | (is_user? 0 : 1);
  232 + access_perms = (pde & PTE_ACCESS_MASK) >> PTE_ACCESS_SHIFT;
  233 + error_code = access_table[access_index][access_perms];
  234 + if (error_code)
  235 + goto do_fault;
  236 +
  237 + /* the page can be put in the TLB */
  238 + prot = PAGE_READ;
  239 + if (pde & PG_MODIFIED_MASK) {
  240 + /* only set write access if already dirty... otherwise wait
  241 + for dirty access */
  242 + if (rw_table[is_user][access_perms])
  243 + prot |= PAGE_WRITE;
  244 + }
  245 +
  246 + /* Even if large ptes, we map only one 4KB page in the cache to
  247 + avoid filling it too fast */
  248 + virt_addr = address & TARGET_PAGE_MASK;
  249 + paddr = ((pde & PTE_ADDR_MASK) << 4) + page_offset;
  250 +
  251 + do_mapping:
  252 + env->access_type = access_type;
  253 + vaddr = virt_addr + ((address & TARGET_PAGE_MASK) & (TARGET_PAGE_SIZE - 1));
  254 +
  255 + ret = tlb_set_page(env, vaddr, paddr, prot, is_user, is_softmmu);
  256 + return ret;
  257 +
  258 + do_fault:
  259 + env->access_type = access_type;
  260 + if (env->mmuregs[3]) /* Fault status register */
  261 + env->mmuregs[3] = 1; /* overflow (not read before another fault) */
  262 + env->mmuregs[3] |= (access_index << 5) | (error_code << 2) | 2;
  263 + env->mmuregs[4] = address; /* Fault address register */
  264 +
  265 + if (env->mmuregs[0] & MMU_NF) // No fault
  266 + return 0;
  267 +
  268 + env->exception_index = exception;
  269 + env->error_code = error_code;
  270 + return error_code;
  271 +}
  272 +
  273 +void memcpy32(uint32_t *dst, const uint32_t *src)
  274 +{
  275 + dst[0] = src[0];
  276 + dst[1] = src[1];
  277 + dst[2] = src[2];
  278 + dst[3] = src[3];
  279 + dst[4] = src[4];
  280 + dst[5] = src[5];
  281 + dst[6] = src[6];
  282 + dst[7] = src[7];
  283 +}
  284 +
  285 +void set_cwp(int new_cwp)
  286 +{
  287 + /* put the modified wrap registers at their proper location */
  288 + if (env->cwp == (NWINDOWS - 1))
  289 + memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
  290 + env->cwp = new_cwp;
  291 + /* put the wrap registers at their temporary location */
  292 + if (new_cwp == (NWINDOWS - 1))
  293 + memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
  294 + env->regwptr = env->regbase + (new_cwp * 16);
  295 +}
  296 +
  297 +/*
  298 + * Begin execution of an interruption. is_int is TRUE if coming from
  299 + * the int instruction. next_eip is the EIP value AFTER the interrupt
  300 + * instruction. It is only relevant if is_int is TRUE.
  301 + */
  302 +void do_interrupt(int intno, int is_int, int error_code,
  303 + unsigned int next_eip, int is_hw)
  304 +{
  305 + int cwp;
  306 +
  307 +#ifdef DEBUG_PCALL
  308 + if (loglevel & CPU_LOG_INT) {
  309 + static int count;
  310 + fprintf(logfile, "%6d: v=%02x e=%04x i=%d pc=%08x npc=%08x SP=%08x\n",
  311 + count, intno, error_code, is_int,
  312 + env->pc,
  313 + env->npc, env->gregs[7]);
  314 +#if 0
  315 + cpu_sparc_dump_state(env, logfile, 0);
  316 + {
  317 + int i;
  318 + uint8_t *ptr;
  319 + fprintf(logfile, " code=");
  320 + ptr = env->pc;
  321 + for(i = 0; i < 16; i++) {
  322 + fprintf(logfile, " %02x", ldub(ptr + i));
  323 + }
  324 + fprintf(logfile, "\n");
  325 + }
  326 +#endif
  327 + count++;
  328 + }
  329 +#endif
  330 + env->psret = 0;
  331 + cwp = (env->cwp - 1) & (NWINDOWS - 1);
  332 + set_cwp(cwp);
  333 + env->regwptr[9] = env->pc;
  334 + env->regwptr[10] = env->npc;
  335 + env->psrps = env->psrs;
  336 + env->psrs = 1;
  337 + env->tbr = (env->tbr & TBR_BASE_MASK) | (intno << 4);
  338 + env->pc = env->tbr;
  339 + env->npc = env->pc + 4;
  340 + env->exception_index = 0;
  341 +}
  342 +
  343 +void raise_exception_err(int exception_index, int error_code)
  344 +{
  345 + raise_exception(exception_index);
  346 +}
... ...
target-sparc/op.c
... ... @@ -117,9 +117,108 @@
117 117 #define REGNAME o7
118 118 #define REG (env->regwptr[7])
119 119 #include "op_template.h"
  120 +
  121 +#define REGNAME f0
  122 +#define REG (env->fpr[0])
  123 +#include "fop_template.h"
  124 +#define REGNAME f1
  125 +#define REG (env->fpr[1])
  126 +#include "fop_template.h"
  127 +#define REGNAME f2
  128 +#define REG (env->fpr[2])
  129 +#include "fop_template.h"
  130 +#define REGNAME f3
  131 +#define REG (env->fpr[3])
  132 +#include "fop_template.h"
  133 +#define REGNAME f4
  134 +#define REG (env->fpr[4])
  135 +#include "fop_template.h"
  136 +#define REGNAME f5
  137 +#define REG (env->fpr[5])
  138 +#include "fop_template.h"
  139 +#define REGNAME f6
  140 +#define REG (env->fpr[6])
  141 +#include "fop_template.h"
  142 +#define REGNAME f7
  143 +#define REG (env->fpr[7])
  144 +#include "fop_template.h"
  145 +#define REGNAME f8
  146 +#define REG (env->fpr[8])
  147 +#include "fop_template.h"
  148 +#define REGNAME f9
  149 +#define REG (env->fpr[9])
  150 +#include "fop_template.h"
  151 +#define REGNAME f10
  152 +#define REG (env->fpr[10])
  153 +#include "fop_template.h"
  154 +#define REGNAME f11
  155 +#define REG (env->fpr[11])
  156 +#include "fop_template.h"
  157 +#define REGNAME f12
  158 +#define REG (env->fpr[12])
  159 +#include "fop_template.h"
  160 +#define REGNAME f13
  161 +#define REG (env->fpr[13])
  162 +#include "fop_template.h"
  163 +#define REGNAME f14
  164 +#define REG (env->fpr[14])
  165 +#include "fop_template.h"
  166 +#define REGNAME f15
  167 +#define REG (env->fpr[15])
  168 +#include "fop_template.h"
  169 +#define REGNAME f16
  170 +#define REG (env->fpr[16])
  171 +#include "fop_template.h"
  172 +#define REGNAME f17
  173 +#define REG (env->fpr[17])
  174 +#include "fop_template.h"
  175 +#define REGNAME f18
  176 +#define REG (env->fpr[18])
  177 +#include "fop_template.h"
  178 +#define REGNAME f19
  179 +#define REG (env->fpr[19])
  180 +#include "fop_template.h"
  181 +#define REGNAME f20
  182 +#define REG (env->fpr[20])
  183 +#include "fop_template.h"
  184 +#define REGNAME f21
  185 +#define REG (env->fpr[21])
  186 +#include "fop_template.h"
  187 +#define REGNAME f22
  188 +#define REG (env->fpr[22])
  189 +#include "fop_template.h"
  190 +#define REGNAME f23
  191 +#define REG (env->fpr[23])
  192 +#include "fop_template.h"
  193 +#define REGNAME f24
  194 +#define REG (env->fpr[24])
  195 +#include "fop_template.h"
  196 +#define REGNAME f25
  197 +#define REG (env->fpr[25])
  198 +#include "fop_template.h"
  199 +#define REGNAME f26
  200 +#define REG (env->fpr[26])
  201 +#include "fop_template.h"
  202 +#define REGNAME f27
  203 +#define REG (env->fpr[27])
  204 +#include "fop_template.h"
  205 +#define REGNAME f28
  206 +#define REG (env->fpr[28])
  207 +#include "fop_template.h"
  208 +#define REGNAME f29
  209 +#define REG (env->fpr[29])
  210 +#include "fop_template.h"
  211 +#define REGNAME f30
  212 +#define REG (env->fpr[30])
  213 +#include "fop_template.h"
  214 +#define REGNAME f31
  215 +#define REG (env->fpr[31])
  216 +#include "fop_template.h"
  217 +
120 218 #define EIP (env->pc)
121 219  
122 220 #define FLAG_SET(x) (env->psr&x)?1:0
  221 +#define FFLAG_SET(x) ((env->fsr&x)?1:0)
123 222  
124 223 void OPPROTO op_movl_T0_0(void)
125 224 {
... ... @@ -375,6 +474,7 @@ void OPPROTO op_sra(void)
375 474 T0 = ((int32_t) T0) >> T1;
376 475 }
377 476  
  477 +#if 0
378 478 void OPPROTO op_st(void)
379 479 {
380 480 stl((void *) T0, T1);
... ... @@ -440,6 +540,51 @@ void OPPROTO op_ldd(void)
440 540 T0 = ldl((void *) (T0 + 4));
441 541 }
442 542  
  543 +void OPPROTO op_stf(void)
  544 +{
  545 + stfl((void *) T0, FT0);
  546 +}
  547 +
  548 +void OPPROTO op_stdf(void)
  549 +{
  550 + stfq((void *) T0, DT0);
  551 +}
  552 +
  553 +void OPPROTO op_ldf(void)
  554 +{
  555 + FT0 = ldfl((void *) T0);
  556 +}
  557 +
  558 +void OPPROTO op_lddf(void)
  559 +{
  560 + DT0 = ldfq((void *) T0);
  561 +}
  562 +#else
  563 +/* Load and store */
  564 +#define MEMSUFFIX _raw
  565 +#include "op_mem.h"
  566 +#if !defined(CONFIG_USER_ONLY)
  567 +#define MEMSUFFIX _user
  568 +#include "op_mem.h"
  569 +
  570 +#define MEMSUFFIX _kernel
  571 +#include "op_mem.h"
  572 +#endif
  573 +#endif
  574 +
  575 +void OPPROTO op_ldfsr(void)
  576 +{
  577 + env->fsr = *((uint32_t *) &FT0);
  578 + FORCE_RET();
  579 +}
  580 +
  581 +void OPPROTO op_stfsr(void)
  582 +{
  583 + *((uint32_t *) &FT0) = env->fsr;
  584 + helper_stfsr();
  585 + FORCE_RET();
  586 +}
  587 +
443 588 void OPPROTO op_wry(void)
444 589 {
445 590 env->y = T0;
... ... @@ -450,36 +595,56 @@ void OPPROTO op_rdy(void)
450 595 T0 = env->y;
451 596 }
452 597  
453   -void raise_exception(int tt)
  598 +void OPPROTO op_rdwim(void)
454 599 {
455   - env->exception_index = tt;
456   - cpu_loop_exit();
457   -}
  600 + T0 = env->wim;
  601 +}
  602 +
  603 +void OPPROTO op_wrwim(void)
  604 +{
  605 + env->wim = T0;
  606 + FORCE_RET();
  607 +}
  608 +
  609 +void OPPROTO op_rdpsr(void)
  610 +{
  611 + T0 = GET_PSR(env);
  612 + FORCE_RET();
  613 +}
  614 +
  615 +void OPPROTO op_wrpsr(void)
  616 +{
  617 + env->psr = T0 & ~PSR_ICC;
  618 + env->psrs = (T0 & PSR_S)? 1 : 0;
  619 + env->psrps = (T0 & PSR_PS)? 1 : 0;
  620 + env->psret = (T0 & PSR_ET)? 1 : 0;
  621 + env->cwp = (T0 & PSR_CWP);
  622 + FORCE_RET();
  623 +}
  624 +
  625 +void OPPROTO op_rdtbr(void)
  626 +{
  627 + T0 = env->tbr;
  628 +}
458 629  
459   -void memcpy32(uint32_t *dst, const uint32_t *src)
  630 +void OPPROTO op_wrtbr(void)
460 631 {
461   - dst[0] = src[0];
462   - dst[1] = src[1];
463   - dst[2] = src[2];
464   - dst[3] = src[3];
465   - dst[4] = src[4];
466   - dst[5] = src[5];
467   - dst[6] = src[6];
468   - dst[7] = src[7];
  632 + env->tbr = T0;
  633 + FORCE_RET();
469 634 }
470 635  
471   -static inline void set_cwp(int new_cwp)
  636 +void OPPROTO op_rett(void)
472 637 {
473   - /* put the modified wrap registers at their proper location */
474   - if (env->cwp == (NWINDOWS - 1))
475   - memcpy32(env->regbase, env->regbase + NWINDOWS * 16);
476   - env->cwp = new_cwp;
477   - /* put the wrap registers at their temporary location */
478   - if (new_cwp == (NWINDOWS - 1))
479   - memcpy32(env->regbase + NWINDOWS * 16, env->regbase);
480   - env->regwptr = env->regbase + (new_cwp * 16);
  638 + helper_rett();
  639 + FORCE_RET();
481 640 }
482 641  
  642 +void raise_exception(int tt)
  643 +{
  644 + env->exception_index = tt;
  645 + cpu_loop_exit();
  646 +}
  647 +
483 648 /* XXX: use another pointer for %iN registers to avoid slow wrapping
484 649 handling ? */
485 650 void OPPROTO op_save(void)
... ... @@ -525,6 +690,12 @@ void OPPROTO op_trapcc_T0(void)
525 690 FORCE_RET();
526 691 }
527 692  
  693 +void OPPROTO op_debug(void)
  694 +{
  695 + env->exception_index = EXCP_DEBUG;
  696 + cpu_loop_exit();
  697 +}
  698 +
528 699 void OPPROTO op_exit_tb(void)
529 700 {
530 701 EXIT_TB();
... ... @@ -612,6 +783,92 @@ void OPPROTO op_eval_bvc(void)
612 783 T2 = !(env->psr & PSR_OVF);
613 784 }
614 785  
  786 +/* FCC1:FCC0: 0 =, 1 <, 2 >, 3 u */
  787 +
  788 +void OPPROTO op_eval_fbne(void)
  789 +{
  790 +// !0
  791 + T2 = (env->fsr & (FSR_FCC1 | FSR_FCC0)); /* L or G or U */
  792 +}
  793 +
  794 +void OPPROTO op_eval_fblg(void)
  795 +{
  796 +// 1 or 2
  797 + T2 = FFLAG_SET(FSR_FCC0) ^ FFLAG_SET(FSR_FCC1);
  798 +}
  799 +
  800 +void OPPROTO op_eval_fbul(void)
  801 +{
  802 +// 1 or 3
  803 + T2 = FFLAG_SET(FSR_FCC0);
  804 +}
  805 +
  806 +void OPPROTO op_eval_fbl(void)
  807 +{
  808 +// 1
  809 + T2 = FFLAG_SET(FSR_FCC0) & !FFLAG_SET(FSR_FCC1);
  810 +}
  811 +
  812 +void OPPROTO op_eval_fbug(void)
  813 +{
  814 +// 2 or 3
  815 + T2 = FFLAG_SET(FSR_FCC1);
  816 +}
  817 +
  818 +void OPPROTO op_eval_fbg(void)
  819 +{
  820 +// 2
  821 + T2 = !FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1);
  822 +}
  823 +
  824 +void OPPROTO op_eval_fbu(void)
  825 +{
  826 +// 3
  827 + T2 = FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1);
  828 +}
  829 +
  830 +void OPPROTO op_eval_fbe(void)
  831 +{
  832 +// 0
  833 + T2 = !FFLAG_SET(FSR_FCC0) & !FFLAG_SET(FSR_FCC1);
  834 +}
  835 +
  836 +void OPPROTO op_eval_fbue(void)
  837 +{
  838 +// 0 or 3
  839 + T2 = !(FFLAG_SET(FSR_FCC1) ^ FFLAG_SET(FSR_FCC0));
  840 +}
  841 +
  842 +void OPPROTO op_eval_fbge(void)
  843 +{
  844 +// 0 or 2
  845 + T2 = !FFLAG_SET(FSR_FCC0);
  846 +}
  847 +
  848 +void OPPROTO op_eval_fbuge(void)
  849 +{
  850 +// !1
  851 + T2 = !(FFLAG_SET(FSR_FCC0) & !FFLAG_SET(FSR_FCC1));
  852 +}
  853 +
  854 +void OPPROTO op_eval_fble(void)
  855 +{
  856 +// 0 or 1
  857 + T2 = !FFLAG_SET(FSR_FCC1);
  858 +}
  859 +
  860 +void OPPROTO op_eval_fbule(void)
  861 +{
  862 +// !2
  863 + T2 = !(!FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1));
  864 +}
  865 +
  866 +void OPPROTO op_eval_fbo(void)
  867 +{
  868 +// !3
  869 + T2 = !(FFLAG_SET(FSR_FCC0) & FFLAG_SET(FSR_FCC1));
  870 +}
  871 +
615 872 void OPPROTO op_movl_T2_0(void)
616 873 {
617 874 T2 = 0;
... ... @@ -687,3 +944,119 @@ void OPPROTO op_flush_T0(void)
687 944 {
688 945 helper_flush(T0);
689 946 }
  947 +
  948 +void OPPROTO op_fnegs(void)
  949 +{
  950 + FT0 = -FT1;
  951 +}
  952 +
  953 +void OPPROTO op_fabss(void)
  954 +{
  955 + do_fabss();
  956 +}
  957 +
  958 +void OPPROTO op_fsqrts(void)
  959 +{
  960 + do_fsqrts();
  961 +}
  962 +
  963 +void OPPROTO op_fsqrtd(void)
  964 +{
  965 + do_fsqrtd();
  966 +}
  967 +
  968 +void OPPROTO op_fmuls(void)
  969 +{
  970 + FT0 *= FT1;
  971 +}
  972 +
  973 +void OPPROTO op_fmuld(void)
  974 +{
  975 + DT0 *= DT1;
  976 +}
  977 +
  978 +void OPPROTO op_fsmuld(void)
  979 +{
  980 + DT0 = FT0 * FT1;
  981 +}
  982 +
  983 +void OPPROTO op_fadds(void)
  984 +{
  985 + FT0 += FT1;
  986 +}
  987 +
  988 +void OPPROTO op_faddd(void)
  989 +{
  990 + DT0 += DT1;
  991 +}
  992 +
  993 +void OPPROTO op_fsubs(void)
  994 +{
  995 + FT0 -= FT1;
  996 +}
  997 +
  998 +void OPPROTO op_fsubd(void)
  999 +{
  1000 + DT0 -= DT1;
  1001 +}
  1002 +
  1003 +void OPPROTO op_fdivs(void)
  1004 +{
  1005 + FT0 /= FT1;
  1006 +}
  1007 +
  1008 +void OPPROTO op_fdivd(void)
  1009 +{
  1010 + DT0 /= DT1;
  1011 +}
  1012 +
  1013 +void OPPROTO op_fcmps(void)
  1014 +{
  1015 + do_fcmps();
  1016 +}
  1017 +
  1018 +void OPPROTO op_fcmpd(void)
  1019 +{
  1020 + do_fcmpd();
  1021 +}
  1022 +
  1023 +void OPPROTO op_fitos(void)
  1024 +{
  1025 + FT0 = (float) *((int32_t *)&FT1);
  1026 +}
  1027 +
  1028 +void OPPROTO op_fdtos(void)
  1029 +{
  1030 + FT0 = (float) DT1;
  1031 +}
  1032 +
  1033 +void OPPROTO op_fitod(void)
  1034 +{
  1035 + DT0 = (double) *((int32_t *)&FT1);
  1036 +}
  1037 +
  1038 +void OPPROTO op_fstod(void)
  1039 +{
  1040 + DT0 = (double) FT1;
  1041 +}
  1042 +
  1043 +void OPPROTO op_fstoi(void)
  1044 +{
  1045 + *((int32_t *)&FT0) = (int32_t) FT1;
  1046 +}
  1047 +
  1048 +void OPPROTO op_fdtoi(void)
  1049 +{
  1050 + *((int32_t *)&FT0) = (int32_t) DT1;
  1051 +}
  1052 +
  1053 +void OPPROTO op_ld_asi()
  1054 +{
  1055 + helper_ld_asi(PARAM1, PARAM2, PARAM3);
  1056 +}
  1057 +
  1058 +void OPPROTO op_st_asi()
  1059 +{
  1060 + helper_st_asi(PARAM1, PARAM2, PARAM3);
  1061 +}
  1062 +
... ...
target-sparc/op_helper.c 0 โ†’ 100644
  1 +#include <math.h>
  2 +#include <fenv.h>
  3 +#include "exec.h"
  4 +
  5 +void OPPROTO do_fabss(void)
  6 +{
  7 + FT0 = fabsf(FT1);
  8 +}
  9 +
  10 +void OPPROTO do_fsqrts(void)
  11 +{
  12 + FT0 = sqrtf(FT1);
  13 +}
  14 +
  15 +void OPPROTO do_fsqrtd(void)
  16 +{
  17 + DT0 = sqrt(DT1);
  18 +}
  19 +
  20 +void OPPROTO do_fcmps (void)
  21 +{
  22 + if (isnan(FT0) || isnan(FT1)) {
  23 + T0 = FSR_FCC1 | FSR_FCC0;
  24 + } else if (FT0 < FT1) {
  25 + T0 = FSR_FCC0;
  26 + } else if (FT0 > FT1) {
  27 + T0 = FSR_FCC1;
  28 + } else {
  29 + T0 = 0;
  30 + }
  31 + env->fsr = T0;
  32 +}
  33 +
  34 +void OPPROTO do_fcmpd (void)
  35 +{
  36 + if (isnan(DT0) || isnan(DT1)) {
  37 + T0 = FSR_FCC1 | FSR_FCC0;
  38 + } else if (DT0 < DT1) {
  39 + T0 = FSR_FCC0;
  40 + } else if (DT0 > DT1) {
  41 + T0 = FSR_FCC1;
  42 + } else {
  43 + T0 = 0;
  44 + }
  45 + env->fsr = T0;
  46 +}
  47 +
  48 +void OPPROTO helper_ld_asi(int asi, int size, int sign)
  49 +{
  50 + switch(asi) {
  51 + case 3: /* MMU probe */
  52 + T1 = 0;
  53 + return;
  54 + case 4: /* read MMU regs */
  55 + {
  56 + int temp, reg = (T0 >> 8) & 0xf;
  57 +
  58 + temp = env->mmuregs[reg];
  59 + if (reg == 3 || reg == 4) /* Fault status, addr cleared on read*/
  60 + env->mmuregs[reg] = 0;
  61 + T1 = temp;
  62 + }
  63 + return;
  64 + case 0x20 ... 0x2f: /* MMU passthrough */
  65 + {
  66 + int temp;
  67 +
  68 + cpu_physical_memory_read(T0, (void *) &temp, size);
  69 + bswap32s(&temp);
  70 + T1 = temp;
  71 + }
  72 + return;
  73 + default:
  74 + T1 = 0;
  75 + return;
  76 + }
  77 +}
  78 +
  79 +void OPPROTO helper_st_asi(int asi, int size, int sign)
  80 +{
  81 + switch(asi) {
  82 + case 3: /* MMU flush */
  83 + return;
  84 + case 4: /* write MMU regs */
  85 + {
  86 + int reg = (T0 >> 8) & 0xf;
  87 + if (reg == 0) {
  88 + env->mmuregs[reg] &= ~(MMU_E | MMU_NF);
  89 + env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);
  90 + } else
  91 + env->mmuregs[reg] = T1;
  92 + return;
  93 + }
  94 + case 0x20 ... 0x2f: /* MMU passthrough */
  95 + {
  96 + int temp = T1;
  97 +
  98 + bswap32s(&temp);
  99 + cpu_physical_memory_write(T0, (void *) &temp, size);
  100 + }
  101 + return;
  102 + default:
  103 + return;
  104 + }
  105 +}
  106 +
  107 +void OPPROTO helper_rett()
  108 +{
  109 + int cwp;
  110 + env->psret = 1;
  111 + cwp = (env->cwp + 1) & (NWINDOWS - 1);
  112 + if (env->wim & (1 << cwp)) {
  113 + raise_exception(TT_WIN_UNF);
  114 + }
  115 + set_cwp(cwp);
  116 + env->psrs = env->psrps;
  117 +}
  118 +
  119 +void helper_stfsr(void)
  120 +{
  121 + switch (env->fsr & FSR_RD_MASK) {
  122 + case FSR_RD_NEAREST:
  123 + fesetround(FE_TONEAREST);
  124 + break;
  125 + case FSR_RD_ZERO:
  126 + fesetround(FE_TOWARDZERO);
  127 + break;
  128 + case FSR_RD_POS:
  129 + fesetround(FE_UPWARD);
  130 + break;
  131 + case FSR_RD_NEG:
  132 + fesetround(FE_DOWNWARD);
  133 + break;
  134 + }
  135 +}
... ...
target-sparc/op_mem.h 0 โ†’ 100644
  1 +/*** Integer load ***/
  2 +#define SPARC_LD_OP(name, qp) \
  3 +void OPPROTO glue(glue(op_, name), MEMSUFFIX)(void) \
  4 +{ \
  5 + T1 = glue(qp, MEMSUFFIX)((void *)T0); \
  6 +}
  7 +
  8 +#define SPARC_ST_OP(name, op) \
  9 +void OPPROTO glue(glue(op_, name), MEMSUFFIX)(void) \
  10 +{ \
  11 + glue(op, MEMSUFFIX)((void *)T0, T1); \
  12 +}
  13 +
  14 +SPARC_LD_OP(ld, ldl);
  15 +SPARC_LD_OP(ldub, ldub);
  16 +SPARC_LD_OP(lduh, lduw);
  17 +SPARC_LD_OP(ldsb, ldsb);
  18 +SPARC_LD_OP(ldsh, ldsw);
  19 +
  20 +/*** Integer store ***/
  21 +SPARC_ST_OP(st, stl);
  22 +SPARC_ST_OP(stb, stb);
  23 +SPARC_ST_OP(sth, stw);
  24 +
  25 +void OPPROTO glue(op_std, MEMSUFFIX)(void)
  26 +{
  27 + glue(stl, MEMSUFFIX)((void *) T0, T1);
  28 + glue(stl, MEMSUFFIX)((void *) (T0 + 4), T2);
  29 +}
  30 +
  31 +void OPPROTO glue(op_ldstub, MEMSUFFIX)(void)
  32 +{
  33 + T1 = glue(ldub, MEMSUFFIX)((void *) T0);
  34 + glue(stb, MEMSUFFIX)((void *) T0, 0xff); /* XXX: Should be Atomically */
  35 +}
  36 +
  37 +void OPPROTO glue(op_swap, MEMSUFFIX)(void)
  38 +{
  39 + unsigned int tmp = glue(ldl, MEMSUFFIX)((void *) T0);
  40 + glue(stl, MEMSUFFIX)((void *) T0, T1); /* XXX: Should be Atomically */
  41 + T1 = tmp;
  42 +}
  43 +
  44 +void OPPROTO glue(op_ldd, MEMSUFFIX)(void)
  45 +{
  46 + T1 = glue(ldl, MEMSUFFIX)((void *) T0);
  47 + T0 = glue(ldl, MEMSUFFIX)((void *) (T0 + 4));
  48 +}
  49 +
  50 +/*** Floating-point store ***/
  51 +void OPPROTO glue(op_stf, MEMSUFFIX) (void)
  52 +{
  53 + glue(stfl, MEMSUFFIX)((void *) T0, FT0);
  54 +}
  55 +
  56 +void OPPROTO glue(op_stdf, MEMSUFFIX) (void)
  57 +{
  58 + glue(stfq, MEMSUFFIX)((void *) T0, DT0);
  59 +}
  60 +
  61 +/*** Floating-point load ***/
  62 +void OPPROTO glue(op_ldf, MEMSUFFIX) (void)
  63 +{
  64 + FT0 = glue(ldfl, MEMSUFFIX)((void *) T0);
  65 +}
  66 +
  67 +void OPPROTO glue(op_lddf, MEMSUFFIX) (void)
  68 +{
  69 + DT0 = glue(ldfq, MEMSUFFIX)((void *) T0);
  70 +}
  71 +#undef MEMSUFFIX
... ...
target-sparc/translate.c
... ... @@ -51,6 +51,7 @@ typedef struct DisasContext {
51 51 target_ulong npc; /* next PC: integer or DYNAMIC_PC or JUMP_PC */
52 52 target_ulong jump_pc[2]; /* used when JUMP_PC pc value is used */
53 53 int is_br;
  54 + int mem_idx;
54 55 struct TranslationBlock *tb;
55 56 } DisasContext;
56 57  
... ... @@ -257,6 +258,96 @@ static GenOpFunc1 *gen_op_movl_TN_im[3] = {
257 258 gen_op_movl_T2_im
258 259 };
259 260  
  261 +#define GEN32(func, NAME) \
  262 +static GenOpFunc *NAME ## _table [32] = { \
  263 +NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
  264 +NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
  265 +NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
  266 +NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
  267 +NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
  268 +NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
  269 +NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
  270 +NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
  271 +}; \
  272 +static inline void func(int n) \
  273 +{ \
  274 + NAME ## _table[n](); \
  275 +}
  276 +
  277 +/* floating point registers moves */
  278 +GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fprf);
  279 +GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fprf);
  280 +GEN32(gen_op_load_fpr_FT2, gen_op_load_fpr_FT2_fprf);
  281 +GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fprf);
  282 +GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fprf);
  283 +GEN32(gen_op_store_FT2_fpr, gen_op_store_FT2_fpr_fprf);
  284 +
  285 +GEN32(gen_op_load_fpr_DT0, gen_op_load_fpr_DT0_fprf);
  286 +GEN32(gen_op_load_fpr_DT1, gen_op_load_fpr_DT1_fprf);
  287 +GEN32(gen_op_load_fpr_DT2, gen_op_load_fpr_DT2_fprf);
  288 +GEN32(gen_op_store_DT0_fpr, gen_op_store_DT0_fpr_fprf);
  289 +GEN32(gen_op_store_DT1_fpr, gen_op_store_DT1_fpr_fprf);
  290 +GEN32(gen_op_store_DT2_fpr, gen_op_store_DT2_fpr_fprf);
  291 +
  292 +#if defined(CONFIG_USER_ONLY)
  293 +#define gen_op_ldst(name) gen_op_##name##_raw()
  294 +#define OP_LD_TABLE(width)
  295 +#define supervisor(dc) 0
  296 +#else
  297 +#define gen_op_ldst(name) (*gen_op_##name[dc->mem_idx])()
  298 +#define OP_LD_TABLE(width) \
  299 +static GenOpFunc *gen_op_##width[] = { \
  300 + &gen_op_##width##_user, \
  301 + &gen_op_##width##_kernel, \
  302 +}; \
  303 + \
  304 +static void gen_op_##width##a(int insn, int is_ld, int size, int sign) \
  305 +{ \
  306 + int asi; \
  307 + \
  308 + asi = GET_FIELD(insn, 19, 26); \
  309 + switch (asi) { \
  310 + case 10: /* User data access */ \
  311 + gen_op_##width##_user(); \
  312 + break; \
  313 + case 11: /* Supervisor data access */ \
  314 + gen_op_##width##_kernel(); \
  315 + break; \
  316 + case 0x20 ... 0x2f: /* MMU passthrough */ \
  317 + if (is_ld) \
  318 + gen_op_ld_asi(asi, size, sign); \
  319 + else \
  320 + gen_op_st_asi(asi, size, sign); \
  321 + break; \
  322 + default: \
  323 + if (is_ld) \
  324 + gen_op_ld_asi(asi, size, sign); \
  325 + else \
  326 + gen_op_st_asi(asi, size, sign); \
  327 + break; \
  328 + } \
  329 +}
  330 +
  331 +#define supervisor(dc) (dc->mem_idx == 1)
  332 +#endif
  333 +
  334 +OP_LD_TABLE(ld);
  335 +OP_LD_TABLE(st);
  336 +OP_LD_TABLE(ldub);
  337 +OP_LD_TABLE(lduh);
  338 +OP_LD_TABLE(ldsb);
  339 +OP_LD_TABLE(ldsh);
  340 +OP_LD_TABLE(stb);
  341 +OP_LD_TABLE(sth);
  342 +OP_LD_TABLE(std);
  343 +OP_LD_TABLE(ldstub);
  344 +OP_LD_TABLE(swap);
  345 +OP_LD_TABLE(ldd);
  346 +OP_LD_TABLE(stf);
  347 +OP_LD_TABLE(stdf);
  348 +OP_LD_TABLE(ldf);
  349 +OP_LD_TABLE(lddf);
  350 +
260 351 static inline void gen_movl_imm_TN(int reg, int imm)
261 352 {
262 353 gen_op_movl_TN_im[reg] (imm);
... ... @@ -391,6 +482,60 @@ static void gen_cond(int cond)
391 482 }
392 483 }
393 484  
  485 +static void gen_fcond(int cond)
  486 +{
  487 + switch (cond) {
  488 + case 0x0:
  489 + gen_op_movl_T2_0();
  490 + break;
  491 + case 0x1:
  492 + gen_op_eval_fbne();
  493 + break;
  494 + case 0x2:
  495 + gen_op_eval_fblg();
  496 + break;
  497 + case 0x3:
  498 + gen_op_eval_fbul();
  499 + break;
  500 + case 0x4:
  501 + gen_op_eval_fbl();
  502 + break;
  503 + case 0x5:
  504 + gen_op_eval_fbug();
  505 + break;
  506 + case 0x6:
  507 + gen_op_eval_fbg();
  508 + break;
  509 + case 0x7:
  510 + gen_op_eval_fbu();
  511 + break;
  512 + case 0x8:
  513 + gen_op_movl_T2_1();
  514 + break;
  515 + case 0x9:
  516 + gen_op_eval_fbe();
  517 + break;
  518 + case 0xa:
  519 + gen_op_eval_fbue();
  520 + break;
  521 + case 0xb:
  522 + gen_op_eval_fbge();
  523 + break;
  524 + case 0xc:
  525 + gen_op_eval_fbuge();
  526 + break;
  527 + case 0xd:
  528 + gen_op_eval_fble();
  529 + break;
  530 + case 0xe:
  531 + gen_op_eval_fbule();
  532 + break;
  533 + default:
  534 + case 0xf:
  535 + gen_op_eval_fbo();
  536 + break;
  537 + }
  538 +}
394 539  
395 540 static void do_branch(DisasContext * dc, uint32_t target, uint32_t insn)
396 541 {
... ... @@ -429,6 +574,50 @@ static void do_branch(DisasContext * dc, uint32_t target, uint32_t insn)
429 574 }
430 575 }
431 576  
  577 +static void do_fbranch(DisasContext * dc, uint32_t target, uint32_t insn)
  578 +{
  579 + unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29));
  580 + target += (uint32_t) dc->pc;
  581 + if (cond == 0x0) {
  582 + /* unconditional not taken */
  583 + if (a) {
  584 + dc->pc = dc->npc + 4;
  585 + dc->npc = dc->pc + 4;
  586 + } else {
  587 + dc->pc = dc->npc;
  588 + dc->npc = dc->pc + 4;
  589 + }
  590 + } else if (cond == 0x8) {
  591 + /* unconditional taken */
  592 + if (a) {
  593 + dc->pc = target;
  594 + dc->npc = dc->pc + 4;
  595 + } else {
  596 + dc->pc = dc->npc;
  597 + dc->npc = target;
  598 + }
  599 + } else {
  600 + flush_T2(dc);
  601 + gen_fcond(cond);
  602 + if (a) {
  603 + gen_op_branch_a((long)dc->tb, target, dc->npc);
  604 + dc->is_br = 1;
  605 + } else {
  606 + dc->pc = dc->npc;
  607 + dc->jump_pc[0] = target;
  608 + dc->jump_pc[1] = dc->npc + 4;
  609 + dc->npc = JUMP_PC;
  610 + }
  611 + }
  612 +}
  613 +
  614 +static void gen_debug(DisasContext *s, uint32_t pc)
  615 +{
  616 + gen_op_jmp_im(pc);
  617 + gen_op_debug();
  618 + s->is_br = 1;
  619 +}
  620 +
432 621 #define GET_FIELDs(x,a,b) sign_extend (GET_FIELD(x,a,b), (b) - (a) + 1)
433 622  
434 623 static int sign_extend(int x, int len)
... ... @@ -454,6 +643,7 @@ static void disas_sparc_insn(DisasContext * dc)
454 643 switch (xop) {
455 644 case 0x0:
456 645 case 0x1: /* UNIMPL */
  646 + default:
457 647 goto illegal_insn;
458 648 case 0x2: /* BN+x */
459 649 {
... ... @@ -462,8 +652,13 @@ static void disas_sparc_insn(DisasContext * dc)
462 652 do_branch(dc, target, insn);
463 653 goto jmp_insn;
464 654 }
465   - case 0x3: /* FBN+x */
466   - break;
  655 + case 0x6: /* FBN+x */
  656 + {
  657 + target <<= 2;
  658 + target = sign_extend(target, 22);
  659 + do_fbranch(dc, target, insn);
  660 + goto jmp_insn;
  661 + }
467 662 case 0x4: /* SETHI */
468 663 gen_movl_imm_T0(target << 10);
469 664 gen_movl_T0_reg(rd);
... ... @@ -492,12 +687,16 @@ static void disas_sparc_insn(DisasContext * dc)
492 687 rs1 = GET_FIELD(insn, 13, 17);
493 688 gen_movl_reg_T0(rs1);
494 689 if (IS_IMM) {
495   - gen_movl_imm_T1(GET_FIELD(insn, 25, 31));
  690 + rs2 = GET_FIELD(insn, 25, 31);
  691 + if (rs2 != 0) {
  692 + gen_movl_imm_T1(rs2);
  693 + gen_op_add_T1_T0();
  694 + }
496 695 } else {
497 696 rs2 = GET_FIELD(insn, 27, 31);
498 697 gen_movl_reg_T1(rs2);
  698 + gen_op_add_T1_T0();
499 699 }
500   - gen_op_add_T1_T0();
501 700 save_state(dc);
502 701 cond = GET_FIELD(insn, 3, 6);
503 702 if (cond == 0x8) {
... ... @@ -514,11 +713,167 @@ static void disas_sparc_insn(DisasContext * dc)
514 713 gen_op_rdy();
515 714 gen_movl_T0_reg(rd);
516 715 break;
  716 + case 15: /* stbar */
  717 + break; /* no effect? */
517 718 default:
518 719 goto illegal_insn;
519 720 }
  721 +#if !defined(CONFIG_USER_ONLY)
  722 + } else if (xop == 0x29) {
  723 + if (!supervisor(dc))
  724 + goto priv_insn;
  725 + gen_op_rdpsr();
  726 + gen_movl_T0_reg(rd);
  727 + break;
  728 + } else if (xop == 0x2a) {
  729 + if (!supervisor(dc))
  730 + goto priv_insn;
  731 + gen_op_rdwim();
  732 + gen_movl_T0_reg(rd);
  733 + break;
  734 + } else if (xop == 0x2b) {
  735 + if (!supervisor(dc))
  736 + goto priv_insn;
  737 + gen_op_rdtbr();
  738 + gen_movl_T0_reg(rd);
  739 + break;
  740 +#endif
520 741 } else if (xop == 0x34 || xop == 0x35) { /* FPU Operations */
521   - goto illegal_insn;
  742 + rs1 = GET_FIELD(insn, 13, 17);
  743 + rs2 = GET_FIELD(insn, 27, 31);
  744 + xop = GET_FIELD(insn, 18, 26);
  745 + switch (xop) {
  746 + case 0x1: /* fmovs */
  747 + gen_op_load_fpr_FT0(rs2);
  748 + gen_op_store_FT0_fpr(rd);
  749 + break;
  750 + case 0x5: /* fnegs */
  751 + gen_op_load_fpr_FT1(rs2);
  752 + gen_op_fnegs();
  753 + gen_op_store_FT0_fpr(rd);
  754 + break;
  755 + case 0x9: /* fabss */
  756 + gen_op_load_fpr_FT1(rs2);
  757 + gen_op_fabss();
  758 + gen_op_store_FT0_fpr(rd);
  759 + break;
  760 + case 0x29: /* fsqrts */
  761 + gen_op_load_fpr_FT1(rs2);
  762 + gen_op_fsqrts();
  763 + gen_op_store_FT0_fpr(rd);
  764 + break;
  765 + case 0x2a: /* fsqrtd */
  766 + gen_op_load_fpr_DT1(rs2);
  767 + gen_op_fsqrtd();
  768 + gen_op_store_DT0_fpr(rd);
  769 + break;
  770 + case 0x41:
  771 + gen_op_load_fpr_FT0(rs1);
  772 + gen_op_load_fpr_FT1(rs2);
  773 + gen_op_fadds();
  774 + gen_op_store_FT0_fpr(rd);
  775 + break;
  776 + case 0x42:
  777 + gen_op_load_fpr_DT0(rs1);
  778 + gen_op_load_fpr_DT1(rs2);
  779 + gen_op_faddd();
  780 + gen_op_store_DT0_fpr(rd);
  781 + break;
  782 + case 0x45:
  783 + gen_op_load_fpr_FT0(rs1);
  784 + gen_op_load_fpr_FT1(rs2);
  785 + gen_op_fsubs();
  786 + gen_op_store_FT0_fpr(rd);
  787 + break;
  788 + case 0x46:
  789 + gen_op_load_fpr_DT0(rs1);
  790 + gen_op_load_fpr_DT1(rs2);
  791 + gen_op_fsubd();
  792 + gen_op_store_DT0_fpr(rd);
  793 + break;
  794 + case 0x49:
  795 + gen_op_load_fpr_FT0(rs1);
  796 + gen_op_load_fpr_FT1(rs2);
  797 + gen_op_fmuls();
  798 + gen_op_store_FT0_fpr(rd);
  799 + break;
  800 + case 0x4a:
  801 + gen_op_load_fpr_DT0(rs1);
  802 + gen_op_load_fpr_DT1(rs2);
  803 + gen_op_fmuld();
  804 + gen_op_store_DT0_fpr(rd);
  805 + break;
  806 + case 0x4d:
  807 + gen_op_load_fpr_FT0(rs1);
  808 + gen_op_load_fpr_FT1(rs2);
  809 + gen_op_fdivs();
  810 + gen_op_store_FT0_fpr(rd);
  811 + break;
  812 + case 0x4e:
  813 + gen_op_load_fpr_DT0(rs1);
  814 + gen_op_load_fpr_DT1(rs2);
  815 + gen_op_fdivd();
  816 + gen_op_store_DT0_fpr(rd);
  817 + break;
  818 + case 0x51:
  819 + gen_op_load_fpr_FT0(rs1);
  820 + gen_op_load_fpr_FT1(rs2);
  821 + gen_op_fcmps();
  822 + break;
  823 + case 0x52:
  824 + gen_op_load_fpr_DT0(rs1);
  825 + gen_op_load_fpr_DT1(rs2);
  826 + gen_op_fcmpd();
  827 + break;
  828 + case 0x55: /* fcmpes */
  829 + gen_op_load_fpr_FT0(rs1);
  830 + gen_op_load_fpr_FT1(rs2);
  831 + gen_op_fcmps(); /* XXX */
  832 + break;
  833 + case 0x56: /* fcmped */
  834 + gen_op_load_fpr_DT0(rs1);
  835 + gen_op_load_fpr_DT1(rs2);
  836 + gen_op_fcmpd(); /* XXX */
  837 + break;
  838 + case 0x69:
  839 + gen_op_load_fpr_FT0(rs1);
  840 + gen_op_load_fpr_FT1(rs2);
  841 + gen_op_fsmuld();
  842 + gen_op_store_DT0_fpr(rd);
  843 + break;
  844 + case 0xc4:
  845 + gen_op_load_fpr_FT1(rs2);
  846 + gen_op_fitos();
  847 + gen_op_store_FT0_fpr(rd);
  848 + break;
  849 + case 0xc6:
  850 + gen_op_load_fpr_DT1(rs2);
  851 + gen_op_fdtos();
  852 + gen_op_store_FT0_fpr(rd);
  853 + break;
  854 + case 0xc8:
  855 + gen_op_load_fpr_FT1(rs2);
  856 + gen_op_fitod();
  857 + gen_op_store_DT0_fpr(rd);
  858 + break;
  859 + case 0xc9:
  860 + gen_op_load_fpr_FT1(rs2);
  861 + gen_op_fstod();
  862 + gen_op_store_DT0_fpr(rd);
  863 + break;
  864 + case 0xd1:
  865 + gen_op_load_fpr_FT1(rs2);
  866 + gen_op_fstoi();
  867 + gen_op_store_FT0_fpr(rd);
  868 + break;
  869 + case 0xd2:
  870 + gen_op_load_fpr_DT1(rs2);
  871 + gen_op_fdtoi();
  872 + gen_op_store_FT0_fpr(rd);
  873 + break;
  874 + default:
  875 + goto illegal_insn;
  876 + }
522 877 } else {
523 878 rs1 = GET_FIELD(insn, 13, 17);
524 879 gen_movl_reg_T0(rs1);
... ... @@ -637,6 +992,32 @@ static void disas_sparc_insn(DisasContext * dc)
637 992 }
638 993 }
639 994 break;
  995 +#if !defined(CONFIG_USER_ONLY)
  996 + case 0x31:
  997 + {
  998 + if (!supervisor(dc))
  999 + goto priv_insn;
  1000 + gen_op_xor_T1_T0();
  1001 + gen_op_wrpsr();
  1002 + }
  1003 + break;
  1004 + case 0x32:
  1005 + {
  1006 + if (!supervisor(dc))
  1007 + goto priv_insn;
  1008 + gen_op_xor_T1_T0();
  1009 + gen_op_wrwim();
  1010 + }
  1011 + break;
  1012 + case 0x33:
  1013 + {
  1014 + if (!supervisor(dc))
  1015 + goto priv_insn;
  1016 + gen_op_xor_T1_T0();
  1017 + gen_op_wrtbr();
  1018 + }
  1019 + break;
  1020 +#endif
640 1021 case 0x38: /* jmpl */
641 1022 {
642 1023 gen_op_add_T1_T0();
... ... @@ -649,6 +1030,24 @@ static void disas_sparc_insn(DisasContext * dc)
649 1030 dc->npc = DYNAMIC_PC;
650 1031 }
651 1032 goto jmp_insn;
  1033 +#if !defined(CONFIG_USER_ONLY)
  1034 + case 0x39: /* rett */
  1035 + {
  1036 + if (!supervisor(dc))
  1037 + goto priv_insn;
  1038 + gen_op_add_T1_T0();
  1039 + gen_op_movl_npc_T0();
  1040 + gen_op_rett();
  1041 +#if 0
  1042 + dc->pc = dc->npc;
  1043 + dc->npc = DYNAMIC_PC;
  1044 +#endif
  1045 + }
  1046 +#if 0
  1047 + goto jmp_insn;
  1048 +#endif
  1049 + break;
  1050 +#endif
652 1051 case 0x3b: /* flush */
653 1052 gen_op_add_T1_T0();
654 1053 gen_op_flush_T0();
... ... @@ -679,60 +1078,157 @@ static void disas_sparc_insn(DisasContext * dc)
679 1078 gen_movl_reg_T0(rs1);
680 1079 if (IS_IMM) { /* immediate */
681 1080 rs2 = GET_FIELDs(insn, 19, 31);
682   - gen_movl_imm_T1(rs2);
  1081 + if (rs2 != 0) {
  1082 + gen_movl_imm_T1(rs2);
  1083 + gen_op_add_T1_T0();
  1084 + }
683 1085 } else { /* register */
684 1086 rs2 = GET_FIELD(insn, 27, 31);
685 1087 gen_movl_reg_T1(rs2);
  1088 + gen_op_add_T1_T0();
686 1089 }
687   - gen_op_add_T1_T0();
688   - if (xop < 4 || xop > 7) {
  1090 + if (xop < 4 || (xop > 7 && xop < 0x14) || \
  1091 + (xop > 0x17 && xop < 0x20)) {
689 1092 switch (xop) {
690 1093 case 0x0: /* load word */
691   - gen_op_ld();
  1094 + gen_op_ldst(ld);
692 1095 break;
693 1096 case 0x1: /* load unsigned byte */
694   - gen_op_ldub();
  1097 + gen_op_ldst(ldub);
695 1098 break;
696 1099 case 0x2: /* load unsigned halfword */
697   - gen_op_lduh();
  1100 + gen_op_ldst(lduh);
698 1101 break;
699 1102 case 0x3: /* load double word */
700   - gen_op_ldd();
  1103 + gen_op_ldst(ldd);
701 1104 gen_movl_T0_reg(rd + 1);
702 1105 break;
703 1106 case 0x9: /* load signed byte */
704   - gen_op_ldsb();
  1107 + gen_op_ldst(ldsb);
705 1108 break;
706 1109 case 0xa: /* load signed halfword */
707   - gen_op_ldsh();
  1110 + gen_op_ldst(ldsh);
708 1111 break;
709 1112 case 0xd: /* ldstub -- XXX: should be atomically */
710   - gen_op_ldstub();
  1113 + gen_op_ldst(ldstub);
711 1114 break;
712 1115 case 0x0f: /* swap register with memory. Also atomically */
713   - gen_op_swap();
  1116 + gen_op_ldst(swap);
  1117 + break;
  1118 + case 0x10: /* load word alternate */
  1119 + if (!supervisor(dc))
  1120 + goto priv_insn;
  1121 + gen_op_lda(insn, 1, 4, 0);
  1122 + break;
  1123 + case 0x11: /* load unsigned byte alternate */
  1124 + if (!supervisor(dc))
  1125 + goto priv_insn;
  1126 + gen_op_lduba(insn, 1, 1, 0);
  1127 + break;
  1128 + case 0x12: /* load unsigned halfword alternate */
  1129 + if (!supervisor(dc))
  1130 + goto priv_insn;
  1131 + gen_op_lduha(insn, 1, 2, 0);
  1132 + break;
  1133 + case 0x13: /* load double word alternate */
  1134 + if (!supervisor(dc))
  1135 + goto priv_insn;
  1136 + gen_op_ldda(insn, 1, 8, 0);
  1137 + gen_movl_T0_reg(rd + 1);
  1138 + break;
  1139 + case 0x19: /* load signed byte alternate */
  1140 + if (!supervisor(dc))
  1141 + goto priv_insn;
  1142 + gen_op_ldsba(insn, 1, 1, 1);
  1143 + break;
  1144 + case 0x1a: /* load signed halfword alternate */
  1145 + if (!supervisor(dc))
  1146 + goto priv_insn;
  1147 + gen_op_ldsha(insn, 1, 2 ,1);
  1148 + break;
  1149 + case 0x1d: /* ldstuba -- XXX: should be atomically */
  1150 + if (!supervisor(dc))
  1151 + goto priv_insn;
  1152 + gen_op_ldstuba(insn, 1, 1, 0);
  1153 + break;
  1154 + case 0x1f: /* swap reg with alt. memory. Also atomically */
  1155 + if (!supervisor(dc))
  1156 + goto priv_insn;
  1157 + gen_op_swapa(insn, 1, 4, 0);
714 1158 break;
715 1159 }
716 1160 gen_movl_T1_reg(rd);
717   - } else if (xop < 8) {
  1161 + } else if (xop >= 0x20 && xop < 0x24) {
  1162 + switch (xop) {
  1163 + case 0x20: /* load fpreg */
  1164 + gen_op_ldst(ldf);
  1165 + gen_op_store_FT0_fpr(rd);
  1166 + break;
  1167 + case 0x21: /* load fsr */
  1168 + gen_op_ldfsr();
  1169 + break;
  1170 + case 0x23: /* load double fpreg */
  1171 + gen_op_ldst(lddf);
  1172 + gen_op_store_DT0_fpr(rd);
  1173 + break;
  1174 + }
  1175 + } else if (xop < 8 || (xop >= 0x14 && xop < 0x18)) {
718 1176 gen_movl_reg_T1(rd);
719 1177 switch (xop) {
720 1178 case 0x4:
721   - gen_op_st();
  1179 + gen_op_ldst(st);
722 1180 break;
723 1181 case 0x5:
724   - gen_op_stb();
  1182 + gen_op_ldst(stb);
725 1183 break;
726 1184 case 0x6:
727   - gen_op_sth();
  1185 + gen_op_ldst(sth);
728 1186 break;
729 1187 case 0x7:
730 1188 flush_T2(dc);
731 1189 gen_movl_reg_T2(rd + 1);
732   - gen_op_std();
  1190 + gen_op_ldst(std);
  1191 + break;
  1192 + case 0x14:
  1193 + if (!supervisor(dc))
  1194 + goto priv_insn;
  1195 + gen_op_sta(insn, 0, 4, 0);
  1196 + break;
  1197 + case 0x15:
  1198 + if (!supervisor(dc))
  1199 + goto priv_insn;
  1200 + gen_op_stba(insn, 0, 1, 0);
  1201 + break;
  1202 + case 0x16:
  1203 + if (!supervisor(dc))
  1204 + goto priv_insn;
  1205 + gen_op_stha(insn, 0, 2, 0);
  1206 + break;
  1207 + case 0x17:
  1208 + if (!supervisor(dc))
  1209 + goto priv_insn;
  1210 + flush_T2(dc);
  1211 + gen_movl_reg_T2(rd + 1);
  1212 + gen_op_stda(insn, 0, 8, 0);
733 1213 break;
734 1214 }
735   - }
  1215 + } else if (xop > 0x23 && xop < 0x28) {
  1216 + switch (xop) {
  1217 + case 0x24:
  1218 + gen_op_load_fpr_FT0(rd);
  1219 + gen_op_ldst(stf);
  1220 + break;
  1221 + case 0x25:
  1222 + gen_op_stfsr();
  1223 + break;
  1224 + case 0x27:
  1225 + gen_op_load_fpr_DT0(rd);
  1226 + gen_op_ldst(stdf);
  1227 + break;
  1228 + }
  1229 + } else if (xop > 0x33 && xop < 0x38) {
  1230 + /* Co-processor */
  1231 + }
736 1232 }
737 1233 }
738 1234 /* default case for non jump instructions */
... ... @@ -753,30 +1249,59 @@ static void disas_sparc_insn(DisasContext * dc)
753 1249 save_state(dc);
754 1250 gen_op_exception(TT_ILL_INSN);
755 1251 dc->is_br = 1;
  1252 + return;
  1253 + priv_insn:
  1254 + save_state(dc);
  1255 + gen_op_exception(TT_PRIV_INSN);
  1256 + dc->is_br = 1;
756 1257 }
757 1258  
758 1259 static inline int gen_intermediate_code_internal(TranslationBlock * tb,
759   - int spc)
  1260 + int spc, CPUSPARCState *env)
760 1261 {
761 1262 target_ulong pc_start, last_pc;
762 1263 uint16_t *gen_opc_end;
763 1264 DisasContext dc1, *dc = &dc1;
  1265 + int j, lj = -1;
764 1266  
765 1267 memset(dc, 0, sizeof(DisasContext));
766   - if (spc) {
767   - printf("SearchPC not yet supported\n");
768   - exit(0);
769   - }
770 1268 dc->tb = tb;
771 1269 pc_start = tb->pc;
772 1270 dc->pc = pc_start;
773 1271 dc->npc = (target_ulong) tb->cs_base;
774   -
  1272 +#if defined(CONFIG_USER_ONLY)
  1273 + dc->mem_idx = 0;
  1274 +#else
  1275 + dc->mem_idx = ((env->psrs) != 0);
  1276 +#endif
775 1277 gen_opc_ptr = gen_opc_buf;
776 1278 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
777 1279 gen_opparam_ptr = gen_opparam_buf;
778 1280  
  1281 + env->access_type = ACCESS_CODE;
  1282 +
779 1283 do {
  1284 + if (env->nb_breakpoints > 0) {
  1285 + for(j = 0; j < env->nb_breakpoints; j++) {
  1286 + if (env->breakpoints[j] == dc->pc) {
  1287 + gen_debug(dc, dc->pc);
  1288 + break;
  1289 + }
  1290 + }
  1291 + }
  1292 + if (spc) {
  1293 + if (loglevel > 0)
  1294 + fprintf(logfile, "Search PC...\n");
  1295 + j = gen_opc_ptr - gen_opc_buf;
  1296 + if (lj < j) {
  1297 + lj++;
  1298 + while (lj < j)
  1299 + gen_opc_instr_start[lj++] = 0;
  1300 + gen_opc_pc[lj] = dc->pc;
  1301 + gen_opc_npc[lj] = dc->npc;
  1302 + gen_opc_instr_start[lj] = 1;
  1303 + }
  1304 + }
780 1305 last_pc = dc->pc;
781 1306 disas_sparc_insn(dc);
782 1307 if (dc->is_br)
... ... @@ -800,6 +1325,20 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
800 1325 }
801 1326 }
802 1327 *gen_opc_ptr = INDEX_op_end;
  1328 + if (spc) {
  1329 + j = gen_opc_ptr - gen_opc_buf;
  1330 + lj++;
  1331 + while (lj <= j)
  1332 + gen_opc_instr_start[lj++] = 0;
  1333 + tb->size = 0;
  1334 +#if 0
  1335 + if (loglevel > 0) {
  1336 + page_dump(logfile);
  1337 + }
  1338 +#endif
  1339 + } else {
  1340 + tb->size = dc->npc - pc_start;
  1341 + }
803 1342 #ifdef DEBUG_DISAS
804 1343 if (loglevel & CPU_LOG_TB_IN_ASM) {
805 1344 fprintf(logfile, "--------------\n");
... ... @@ -814,17 +1353,18 @@ static inline int gen_intermediate_code_internal(TranslationBlock * tb,
814 1353 }
815 1354 #endif
816 1355  
  1356 + env->access_type = ACCESS_DATA;
817 1357 return 0;
818 1358 }
819 1359  
820 1360 int gen_intermediate_code(CPUSPARCState * env, TranslationBlock * tb)
821 1361 {
822   - return gen_intermediate_code_internal(tb, 0);
  1362 + return gen_intermediate_code_internal(tb, 0, env);
823 1363 }
824 1364  
825 1365 int gen_intermediate_code_pc(CPUSPARCState * env, TranslationBlock * tb)
826 1366 {
827   - return gen_intermediate_code_internal(tb, 1);
  1367 + return gen_intermediate_code_internal(tb, 1, env);
828 1368 }
829 1369  
830 1370 CPUSPARCState *cpu_sparc_init(void)
... ... @@ -839,7 +1379,17 @@ CPUSPARCState *cpu_sparc_init(void)
839 1379 env->cwp = 0;
840 1380 env->wim = 1;
841 1381 env->regwptr = env->regbase + (env->cwp * 16);
  1382 + env->access_type = ACCESS_DATA;
  1383 +#if defined(CONFIG_USER_ONLY)
842 1384 env->user_mode_only = 1;
  1385 +#else
  1386 + /* Emulate Prom */
  1387 + env->psrs = 1;
  1388 + env->pc = 0x4000;
  1389 + env->npc = env->pc + 4;
  1390 + env->mmuregs[0] = (0x10<<24) | MMU_E; /* Impl 1, ver 0, MMU Enabled */
  1391 + env->mmuregs[1] = 0x3000 >> 4; /* MMU Context table */
  1392 +#endif
843 1393 cpu_single_env = env;
844 1394 return (env);
845 1395 }
... ... @@ -870,10 +1420,20 @@ void cpu_sparc_dump_state(CPUSPARCState * env, FILE * f, int flags)
870 1420 env->regwptr[i + x * 8]);
871 1421 fprintf(f, "\n");
872 1422 }
873   - fprintf(f, "psr: 0x%08x -> %c%c%c%c wim: 0x%08x\n", env->psr | env->cwp,
  1423 + fprintf(f, "\nFloating Point Registers:\n");
  1424 + for (i = 0; i < 32; i++) {
  1425 + if ((i & 3) == 0)
  1426 + fprintf(f, "%%f%02d:", i);
  1427 + fprintf(f, " %016lf", env->fpr[i]);
  1428 + if ((i & 3) == 3)
  1429 + fprintf(f, "\n");
  1430 + }
  1431 + fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n", GET_PSR(env),
874 1432 GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
875 1433 GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
876   - env->wim);
  1434 + env->psrs?'S':'-', env->psrps?'P':'-',
  1435 + env->psret?'E':'-', env->wim);
  1436 + fprintf(f, "fsr: 0x%08x\n", env->fsr);
877 1437 }
878 1438  
879 1439 target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
... ...