*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA
*/
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <signal.h>
-#include <assert.h>
#include "cpu.h"
#include "exec-all.h"
//#define DEBUG_MMU
//#define DEBUG_FEATURES
-//#define DEBUG_PCALL
static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
/* thread support */
-spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t global_cpu_lock = SPIN_LOCK_UNLOCKED;
void cpu_lock(void)
{
mask = 0xffffffffffc00000ULL;
break;
}
- // ctx match, vaddr match?
+ // ctx match, vaddr match, valid?
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) ||
+ (address & mask) == (env->dtlb_tag[i] & mask) &&
+ (env->dtlb_tte[i] & 0x8000000000000000ULL)) {
+ // access ok?
+ if (((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
#endif
return 1;
}
- *physical = (env->dtlb_tte[i] & mask & 0x1fffffff000ULL) +
- (address & ~mask & 0x1fffffff000ULL);
+ *physical = ((env->dtlb_tte[i] & mask) | (address & ~mask)) &
+ 0x1ffffffe000ULL;
*prot = PAGE_READ;
if (env->dtlb_tte[i] & 0x2)
*prot |= PAGE_WRITE;
mask = 0xffffffffffc00000ULL;
break;
}
- // ctx match, vaddr match?
+ // ctx match, vaddr match, valid?
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)) {
+ (address & mask) == (env->itlb_tag[i] & mask) &&
+ (env->itlb_tte[i] & 0x8000000000000000ULL)) {
+ // access ok?
+ if ((env->itlb_tte[i] & 0x4) && is_user) {
if (env->immuregs[3]) /* Fault status register */
env->immuregs[3] = 2; /* overflow (not read before
another fault) */
#endif
return 1;
}
- *physical = (env->itlb_tte[i] & mask & 0x1fffffff000ULL) +
- (address & ~mask & 0x1fffffff000ULL);
+ *physical = ((env->itlb_tte[i] & mask) | (address & ~mask)) &
+ 0x1ffffffe000ULL;
*prot = PAGE_EXEC;
return 0;
}
#ifdef DEBUG_MMU
printf("TMISS at 0x%" PRIx64 "\n", address);
#endif
+ /* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
env->immuregs[6] = (address & ~0x1fffULL) | (env->dmmuregs[1] & 0x1fff);
env->exception_index = TT_TMISS;
return 1;
void cpu_reset(CPUSPARCState *env)
{
+ if (qemu_loglevel_mask(CPU_LOG_RESET)) {
+ qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
+ log_cpu_state(env, 0);
+ }
+
tlb_flush(env, 1);
env->cwp = 0;
env->wim = 1;
env->regwptr = env->regbase + (env->cwp * 16);
#if defined(CONFIG_USER_ONLY)
- env->user_mode_only = 1;
#ifdef TARGET_SPARC64
env->cleanwin = env->nwindows - 2;
env->cansave = env->nwindows - 2;
env->psret = 0;
env->psrs = 1;
env->psrps = 1;
+ CC_OP = CC_OP_FLAGS;
#ifdef TARGET_SPARC64
env->pstate = PS_PRIV;
env->hpstate = HS_PRIV;
- env->pc = 0x1fff0000020ULL; // XXX should be different for system_reset
env->tsptr = &env->ts[env->tl & MAXTL_MASK];
+ env->lsu = 0;
#else
- env->pc = 0;
env->mmuregs[0] &= ~(MMU_E | MMU_NF);
env->mmuregs[0] |= env->def->mmu_bm;
#endif
+ env->pc = 0;
env->npc = env->pc + 4;
#endif
}
#if !defined(TARGET_SPARC64)
env->mmuregs[0] |= def->mmu_version;
cpu_sparc_set_id(env, 0);
+ env->mxccregs[7] |= def->mxcc_version;
#else
env->mmu_version = def->mmu_version;
env->maxtl = def->maxtl;
CPUSPARCState *env;
env = qemu_mallocz(sizeof(CPUSPARCState));
- if (!env)
- return NULL;
cpu_exec_init(env);
gen_intermediate_code_init(env);
return NULL;
}
cpu_reset(env);
+ qemu_init_vcpu(env);
return env;
}
CPU_FEATURE_FSMULD,
},
{
- .name = "TI SuperSparc II",
- .iu_version = 0x40000000,
- .fpu_version = 0 << 17,
- .mmu_version = 0x04000000,
- .mmu_bm = 0x00002000,
- .mmu_ctpr_mask = 0xffffffc0,
- .mmu_cxr_mask = 0x0000ffff,
- .mmu_sfsr_mask = 0xffffffff,
- .mmu_trcr_mask = 0xffffffff,
- .nwindows = 8,
- .features = CPU_DEFAULT_FEATURES,
- },
- {
.name = "TI MicroSparc I",
.iu_version = 0x41000000,
.fpu_version = 4 << 17,
},
{
.name = "TI SuperSparc 40", // STP1020NPGA
- .iu_version = 0x41000000,
+ .iu_version = 0x41000000, // SuperSPARC 2.x
.fpu_version = 0 << 17,
- .mmu_version = 0x00000000,
+ .mmu_version = 0x00000800, // SuperSPARC 2.x, no MXCC
.mmu_bm = 0x00002000,
.mmu_ctpr_mask = 0xffffffc0,
.mmu_cxr_mask = 0x0000ffff,
},
{
.name = "TI SuperSparc 50", // STP1020PGA
- .iu_version = 0x40000000,
+ .iu_version = 0x40000000, // SuperSPARC 3.x
.fpu_version = 0 << 17,
- .mmu_version = 0x04000000,
+ .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
.mmu_bm = 0x00002000,
.mmu_ctpr_mask = 0xffffffc0,
.mmu_cxr_mask = 0x0000ffff,
},
{
.name = "TI SuperSparc 51",
- .iu_version = 0x43000000,
+ .iu_version = 0x40000000, // SuperSPARC 3.x
.fpu_version = 0 << 17,
- .mmu_version = 0x04000000,
+ .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
.mmu_bm = 0x00002000,
.mmu_ctpr_mask = 0xffffffc0,
.mmu_cxr_mask = 0x0000ffff,
.mmu_sfsr_mask = 0xffffffff,
.mmu_trcr_mask = 0xffffffff,
+ .mxcc_version = 0x00000104,
.nwindows = 8,
.features = CPU_DEFAULT_FEATURES,
},
{
.name = "TI SuperSparc 60", // STP1020APGA
- .iu_version = 0x40000000,
+ .iu_version = 0x40000000, // SuperSPARC 3.x
.fpu_version = 0 << 17,
- .mmu_version = 0x03000000,
+ .mmu_version = 0x01000800, // SuperSPARC 3.x, no MXCC
.mmu_bm = 0x00002000,
.mmu_ctpr_mask = 0xffffffc0,
.mmu_cxr_mask = 0x0000ffff,
},
{
.name = "TI SuperSparc 61",
- .iu_version = 0x44000000,
+ .iu_version = 0x44000000, // SuperSPARC 3.x
.fpu_version = 0 << 17,
- .mmu_version = 0x04000000,
+ .mmu_version = 0x01000000, // SuperSPARC 3.x, MXCC
+ .mmu_bm = 0x00002000,
+ .mmu_ctpr_mask = 0xffffffc0,
+ .mmu_cxr_mask = 0x0000ffff,
+ .mmu_sfsr_mask = 0xffffffff,
+ .mmu_trcr_mask = 0xffffffff,
+ .mxcc_version = 0x00000104,
+ .nwindows = 8,
+ .features = CPU_DEFAULT_FEATURES,
+ },
+ {
+ .name = "TI SuperSparc II",
+ .iu_version = 0x40000000, // SuperSPARC II 1.x
+ .fpu_version = 0 << 17,
+ .mmu_version = 0x08000000, // SuperSPARC II 1.x, MXCC
.mmu_bm = 0x00002000,
.mmu_ctpr_mask = 0xffffffc0,
.mmu_cxr_mask = 0x0000ffff,
.mmu_sfsr_mask = 0xffffffff,
.mmu_trcr_mask = 0xffffffff,
+ .mxcc_version = 0x00000104,
.nwindows = 8,
.features = CPU_DEFAULT_FEATURES,
},
long long iu_version;
uint32_t fpu_version, mmu_version, nwindows;
- for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
+ for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
if (strcasecmp(name, sparc_defs[i].name) == 0) {
def = &sparc_defs[i];
}
{
unsigned int i;
- for (i = 0; i < sizeof(sparc_defs) / sizeof(sparc_def_t); i++) {
+ for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
(*cpu_fprintf)(f, "Sparc %16s IU " TARGET_FMT_lx " FPU %08x MMU %08x NWINS %d ",
sparc_defs[i].name,
sparc_defs[i].iu_version,
"fpu_version mmu_version nwindows\n");
}
-#define GET_FLAG(a,b) ((env->psr & a)?b:'-')
-
void cpu_dump_state(CPUState *env, FILE *f,
int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
int flags)
env->cansave, env->canrestore, env->otherwin, env->wstate,
env->cleanwin, env->nwindows - 1 - env->cwp);
#else
+
+#define GET_FLAG(a,b) ((env->psr & a)?b:'-')
+
cpu_fprintf(f, "psr: 0x%08x -> %c%c%c%c %c%c%c wim: 0x%08x\n",
GET_PSR(env), GET_FLAG(PSR_ZERO, 'Z'), GET_FLAG(PSR_OVF, 'V'),
GET_FLAG(PSR_NEG, 'N'), GET_FLAG(PSR_CARRY, 'C'),
env->psrs?'S':'-', env->psrps?'P':'-',
env->psret?'E':'-', env->wim);
#endif
- cpu_fprintf(f, "fsr: 0x%08x\n", GET_FSR32(env));
-}
-
-#ifdef TARGET_SPARC64
-#if !defined(CONFIG_USER_ONLY)
-#include "qemu-common.h"
-#include "hw/irq.h"
-#include "qemu-timer.h"
-#endif
-
-void helper_tick_set_count(void *opaque, uint64_t count)
-{
-#if !defined(CONFIG_USER_ONLY)
- ptimer_set_count(opaque, -count);
-#endif
-}
-
-uint64_t helper_tick_get_count(void *opaque)
-{
-#if !defined(CONFIG_USER_ONLY)
- return -ptimer_get_count(opaque);
-#else
- return 0;
-#endif
+ cpu_fprintf(f, "fsr: 0x%08x\n", env->fsr);
}
-
-void helper_tick_set_limit(void *opaque, uint64_t limit)
-{
-#if !defined(CONFIG_USER_ONLY)
- ptimer_set_limit(opaque, -limit, 0);
-#endif
-}
-#endif