diff options
-rw-r--r-- | hw/sun4m.c | 2 | ||||
-rw-r--r-- | hw/sun4u.c | 2 | ||||
-rw-r--r-- | linux-user/main.c | 2 | ||||
-rw-r--r-- | target-sparc/cpu.h | 5 | ||||
-rw-r--r-- | target-sparc/op_helper.c | 167 | ||||
-rw-r--r-- | target-sparc/translate.c | 3 |
6 files changed, 160 insertions, 21 deletions
@@ -327,7 +327,7 @@ static void *sun4m_hw_init(const struct hwdef *hwdef, int RAM_size, for(i = 0; i < smp_cpus; i++) { env = cpu_init(); - cpu_sparc_register(env, def); + cpu_sparc_register(env, def, i); envs[i] = env; if (i == 0) { qemu_register_reset(main_cpu_reset, env); @@ -358,7 +358,7 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device, exit(1); } env = cpu_init(); - cpu_sparc_register(env, def); + cpu_sparc_register(env, def, 0); bh = qemu_bh_new(tick_irq, env); env->tick = ptimer_init(bh); ptimer_set_period(env->tick, 1ULL); diff --git a/linux-user/main.c b/linux-user/main.c index ac5a63b..1388d48 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2142,7 +2142,7 @@ int main(int argc, char **argv) fprintf(stderr, "Unable to find Sparc CPU definition\n"); exit(1); } - cpu_sparc_register(env, def); + cpu_sparc_register(env, def, 0); env->pc = regs->pc; env->npc = regs->npc; env->y = regs->y; diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h index 30e1d82..e9699cf 100644 --- a/target-sparc/cpu.h +++ b/target-sparc/cpu.h @@ -212,6 +212,8 @@ typedef struct CPUSPARCState { uint64_t dtlb_tte[64]; #else uint32_t mmuregs[16]; + uint64_t mxccdata[4]; + uint64_t mxccregs[8]; #endif /* temporary float registers */ float32 ft0, ft1; @@ -268,7 +270,8 @@ int cpu_sparc_close(CPUSPARCState *s); int sparc_find_by_name (const unsigned char *name, const sparc_def_t **def); void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)); -int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def); +int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def, + unsigned int cpu); #define GET_PSR(env) (env->version | (env->psr & PSR_ICC) | \ (env->psref? PSR_EF : 0) | \ diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c index 6d08e1c..ac88b55 100644 --- a/target-sparc/op_helper.c +++ b/target-sparc/op_helper.c @@ -2,9 +2,24 @@ //#define DEBUG_PCALL //#define DEBUG_MMU +//#define DEBUG_MXCC //#define DEBUG_UNALIGNED //#define DEBUG_UNASSIGNED +#ifdef DEBUG_MMU +#define DPRINTF_MMU(fmt, args...) \ +do { printf("MMU: " fmt , ##args); } while (0) +#else +#define DPRINTF_MMU(fmt, args...) +#endif + +#ifdef DEBUG_MXCC +#define DPRINTF_MXCC(fmt, args...) \ +do { printf("MXCC: " fmt , ##args); } while (0) +#else +#define DPRINTF_MXCC(fmt, args...) +#endif + void raise_exception(int tt) { env->exception_index = tt; @@ -139,12 +154,58 @@ GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1); #ifndef TARGET_SPARC64 #ifndef CONFIG_USER_ONLY + +#ifdef DEBUG_MXCC +static void dump_mxcc(CPUState *env) +{ + printf("mxccdata: %016llx %016llx %016llx %016llx\n", + env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]); + printf("mxccregs: %016llx %016llx %016llx %016llx\n" + " %016llx %016llx %016llx %016llx\n", + env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3], + env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]); +} +#endif + void helper_ld_asi(int asi, int size, int sign) { uint32_t ret = 0; +#ifdef DEBUG_MXCC + uint32_t last_T0 = T0; +#endif switch (asi) { case 2: /* SuperSparc MXCC registers */ + switch (T0) { + case 0x01c00a00: /* MXCC control register */ + if (size == 8) { + ret = env->mxccregs[3]; + T0 = env->mxccregs[3] >> 32; + } else + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + break; + case 0x01c00a04: /* MXCC control register */ + if (size == 4) + ret = env->mxccregs[3]; + else + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + break; + case 0x01c00f00: /* MBus port address register */ + if (size == 8) { + ret = env->mxccregs[7]; + T0 = env->mxccregs[7] >> 32; + } else + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + break; + default: + DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size); + break; + } + DPRINTF_MXCC("asi = %d, size = %d, sign = %d, T0 = %08x -> ret = %08x," + "T0 = %08x\n", asi, size, sign, last_T0, ret, T0); +#ifdef DEBUG_MXCC + dump_mxcc(env); +#endif break; case 3: /* MMU probe */ { @@ -157,9 +218,7 @@ void helper_ld_asi(int asi, int size, int sign) ret = mmu_probe(env, T0, mmulev); //bswap32s(&ret); } -#ifdef DEBUG_MMU - printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret); -#endif + DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret); } break; case 4: /* read MMU regs */ @@ -169,9 +228,7 @@ void helper_ld_asi(int asi, int size, int sign) ret = env->mmuregs[reg]; if (reg == 3) /* Fault status cleared on read */ env->mmuregs[reg] = 0; -#ifdef DEBUG_MMU - printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret); -#endif + DPRINTF_MMU("mmu_read: reg[%d] = 0x%08x\n", reg, ret); } break; case 9: /* Supervisor code access */ @@ -302,15 +359,93 @@ void helper_st_asi(int asi, int size) { switch(asi) { case 2: /* SuperSparc MXCC registers */ + switch (T0) { + case 0x01c00000: /* MXCC stream data register 0 */ + if (size == 8) + env->mxccdata[0] = ((uint64_t)T1 << 32) | T2; + else + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + break; + case 0x01c00008: /* MXCC stream data register 1 */ + if (size == 8) + env->mxccdata[1] = ((uint64_t)T1 << 32) | T2; + else + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + break; + case 0x01c00010: /* MXCC stream data register 2 */ + if (size == 8) + env->mxccdata[2] = ((uint64_t)T1 << 32) | T2; + else + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + break; + case 0x01c00018: /* MXCC stream data register 3 */ + if (size == 8) + env->mxccdata[3] = ((uint64_t)T1 << 32) | T2; + else + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + break; + case 0x01c00100: /* MXCC stream source */ + if (size == 8) + env->mxccregs[0] = ((uint64_t)T1 << 32) | T2; + else + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 0); + env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 8); + env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16); + env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 24); + break; + case 0x01c00200: /* MXCC stream destination */ + if (size == 8) + env->mxccregs[1] = ((uint64_t)T1 << 32) | T2; + else + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0, env->mxccdata[0]); + stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8, env->mxccdata[1]); + stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]); + stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, env->mxccdata[3]); + break; + case 0x01c00a00: /* MXCC control register */ + if (size == 8) + env->mxccregs[3] = ((uint64_t)T1 << 32) | T2; + else + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + break; + case 0x01c00a04: /* MXCC control register */ + if (size == 4) + env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000) | T1; + else + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + break; + case 0x01c00e00: /* MXCC error register */ + if (size == 8) + env->mxccregs[6] = ((uint64_t)T1 << 32) | T2; + else + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + if (env->mxccregs[6] == 0xffffffffffffffffULL) { + // this is probably a reset + } + break; + case 0x01c00f00: /* MBus port address register */ + if (size == 8) + env->mxccregs[7] = ((uint64_t)T1 << 32) | T2; + else + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); + break; + default: + DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size); + break; + } + DPRINTF_MXCC("asi = %d, size = %d, T0 = %08x, T1 = %08x\n", asi, size, T0, T1); +#ifdef DEBUG_MXCC + dump_mxcc(env); +#endif break; case 3: /* MMU flush */ { int mmulev; mmulev = (T0 >> 8) & 15; -#ifdef DEBUG_MMU - printf("mmu flush level %d\n", mmulev); -#endif + DPRINTF_MMU("mmu flush level %d\n", mmulev); switch (mmulev) { case 0: // flush page tlb_flush_page(env, T0 & 0xfffff000); @@ -359,10 +494,10 @@ void helper_st_asi(int asi, int size) env->mmuregs[reg] = T1; break; } -#ifdef DEBUG_MMU if (oldreg != env->mmuregs[reg]) { - printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]); + DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]); } +#ifdef DEBUG_MMU dump_mmu(env); #endif return; @@ -962,8 +1097,8 @@ void helper_st_asi(int asi, int size) // Mappings generated during D/I MMU disabled mode are // invalid in normal mode if (oldreg != env->lsu) { + DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu); #ifdef DEBUG_MMU - printf("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu); dump_mmu(env); #endif tlb_flush(env, 1); @@ -995,10 +1130,10 @@ void helper_st_asi(int asi, int size) break; } env->immuregs[reg] = T1; -#ifdef DEBUG_MMU if (oldreg != env->immuregs[reg]) { - printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]); + DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]); } +#ifdef DEBUG_MMU dump_mmu(env); #endif return; @@ -1064,10 +1199,10 @@ void helper_st_asi(int asi, int size) break; } env->dmmuregs[reg] = T1; -#ifdef DEBUG_MMU if (oldreg != env->dmmuregs[reg]) { - printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]); + DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]); } +#ifdef DEBUG_MMU dump_mmu(env); #endif return; diff --git a/target-sparc/translate.c b/target-sparc/translate.c index 3027bb8..046dc0b 100644 --- a/target-sparc/translate.c +++ b/target-sparc/translate.c @@ -3618,12 +3618,13 @@ void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) } } -int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def) +int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def, unsigned int cpu) { env->version = def->iu_version; env->fsr = def->fpu_version; #if !defined(TARGET_SPARC64) env->mmuregs[0] |= def->mmu_version; + env->mxccregs[7] = ((cpu + 8) & 0xf) << 24; #endif return 0; } |