I'm trying to add SuperSparc II MXCC support and need some feedback.
Is there a better way to read and write physical memory in 64bit chunks? I'm not sure what I'm doing is portable between 32/64 and big/little endian.
Index: hw/sun4m.c =================================================================== RCS file: /sources/qemu/qemu/hw/sun4m.c,v retrieving revision 1.55 diff -p -u -r1.55 sun4m.c --- hw/sun4m.c 6 Oct 2007 11:28:21 -0000 1.55 +++ hw/sun4m.c 13 Oct 2007 20:35:48 -0000 @@ -327,7 +327,7 @@ static void *sun4m_hw_init(const struct 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); Index: linux-user/main.c =================================================================== RCS file: /sources/qemu/qemu/linux-user/main.c,v retrieving revision 1.132 diff -p -u -r1.132 main.c --- linux-user/main.c 12 Oct 2007 06:47:46 -0000 1.132 +++ linux-user/main.c 13 Oct 2007 20:35:49 -0000 @@ -2139,7 +2139,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; Index: target-sparc/cpu.h =================================================================== RCS file: /sources/qemu/qemu/target-sparc/cpu.h,v retrieving revision 1.53 diff -p -u -r1.53 cpu.h --- target-sparc/cpu.h 12 Oct 2007 06:47:46 -0000 1.53 +++ target-sparc/cpu.h 13 Oct 2007 20:35:49 -0000 @@ -210,6 +210,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; @@ -266,7 +268,7 @@ 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, int cpu); #define GET_PSR(env) (env->version | (env->psr & PSR_ICC) | \ (env->psref? PSR_EF : 0) | \ Index: target-sparc/op_helper.c =================================================================== RCS file: /sources/qemu/qemu/target-sparc/op_helper.c,v retrieving revision 1.41 diff -p -u -r1.41 op_helper.c --- target-sparc/op_helper.c 1 Oct 2007 17:07:58 -0000 1.41 +++ target-sparc/op_helper.c 13 Oct 2007 20:35:51 -0000 @@ -2,6 +2,7 @@ //#define DEBUG_PCALL //#define DEBUG_MMU +#define DEBUG_MXCC //#define DEBUG_UNALIGNED //#define DEBUG_UNASSIGNED @@ -139,12 +140,68 @@ GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, #ifndef TARGET_SPARC64 #ifndef CONFIG_USER_ONLY + +#ifdef DEBUG_MXCC +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; + } +#ifdef DEBUG_MXCC + else + printf("ERROR: helper_ld_asi(asi = %d, size = %d, sign = %d) T0 = %08x: unsupported size\n", asi, size, sign, T0); +#endif + break; + case 0x01c00a04: /* MXCC control register */ + if (size == 4) + ret = env->mxccregs[3]; +#ifdef DEBUG_MXCC + else + printf("ERROR: helper_ld_asi(asi = %d, size = %d, sign = %d) T0 = %08x: unsupported size\n", asi, size, sign, T0); +#endif + break; + case 0x01c00f00: /* MBus port address register */ + if (size == 8) { + ret = env->mxccregs[7]; + T0 = env->mxccregs[7] >> 32; + } +#ifdef DEBUG_MXCC + else + printf("ERROR: helper_ld_asi(asi = %d, size = %d, sign = %d) T0 = %08x: unsupported size\n", asi, size, sign, T0); +#endif + break; + default: +#ifdef DEBUG_MXCC + printf("ERROR: helper_ld_asi(asi = %d, size = %d, sign = %d) T0 = %08x: unsupported address\n", asi, size, sign, T0); +#endif + ret = 0; + break; + } +#ifdef DEBUG_MXCC + printf("helper_ld_asi(asi = %d, size = %d, sign = %d) T0 = %08x: ret = %08x, T0 = %08x\n", asi, size, sign, last_T0, ret, T0); + dump_mxcc(env); +#endif break; case 3: /* MMU probe */ { @@ -302,6 +359,116 @@ 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; +#ifdef DEBUG_MXCC + else + printf("ERROR: helper_st_asi(asi = %d, size = %d) T0 = %08x, T1 = %08x: unsupported size\n", asi, size, T0, T1); +#endif + break; + case 0x01c00008: /* MXCC stream data register 1 */ + if (size == 8) + env->mxccdata[1] = ((uint64_t)T1 << 32) | T2; +#ifdef DEBUG_MXCC + else + printf("ERROR: helper_st_asi(asi = %d, size = %d) T0 = %08x, T1 = %08x: unsupported size\n", asi, size, T0, T1); +#endif + break; + case 0x01c00010: /* MXCC stream data register 2 */ + if (size == 8) + env->mxccdata[2] = ((uint64_t)T1 << 32) | T2; +#ifdef DEBUG_MXCC + else + printf("ERROR: helper_st_asi(asi = %d, size = %d) T0 = %08x, T1 = %08x: unsupported size\n", asi, size, T0, T1); +#endif + break; + case 0x01c00018: /* MXCC stream data register 3 */ + if (size == 8) + env->mxccdata[3] = ((uint64_t)T1 << 32) | T2; +#ifdef DEBUG_MXCC + else + printf("ERROR: helper_st_asi(asi = %d, size = %d) T0 = %08x, T1 = %08x: unsupported size\n", asi, size, T0, T1); +#endif + break; + case 0x01c00100: /* MXCC stream source */ + if (size == 8) + env->mxccregs[0] = ((uint64_t)T1 << 32) | T2; +#ifdef DEBUG_MXCC + else + printf("ERROR: helper_st_asi(asi = %d, size = %d) T0 = %08x, T1 = %08x: unsupported size\n", asi, size, T0, T1); +#endif + env->mxccdata[0] = (uint64_t)ldl_phys((target_phys_addr_t)((env->mxccregs[0] + 4) & 0xffffffffULL)) + + ((uint64_t)(ldl_phys((target_phys_addr_t)((env->mxccregs[0] + 0) & 0xffffffffULL))) << 32); + env->mxccdata[1] = (uint64_t)ldl_phys((target_phys_addr_t)((env->mxccregs[0] + 12) & 0xffffffffULL)) + + ((uint64_t)(ldl_phys((target_phys_addr_t)((env->mxccregs[0] + 8) & 0xffffffffULL))) << 32); + env->mxccdata[2] = (uint64_t)ldl_phys((target_phys_addr_t)((env->mxccregs[0] + 20) & 0xffffffffULL)) + + ((uint64_t)(ldl_phys((target_phys_addr_t)((env->mxccregs[0] + 16) & 0xffffffffULL))) << 32); + env->mxccdata[3] = (uint64_t)ldl_phys((target_phys_addr_t)((env->mxccregs[0] + 28) & 0xffffffffULL)) + + ((uint64_t)(ldl_phys((target_phys_addr_t)((env->mxccregs[0] + 24) & 0xffffffffULL))) << 32); + break; + case 0x01c00200: /* MXCC stream destination */ + if (size == 8) + env->mxccregs[1] = ((uint64_t)T1 << 32) | T2; +#ifdef DEBUG_MXCC + else + printf("ERROR: helper_st_asi(asi = %d, size = %d) T0 = %08x, T1 = %08x: unsupported size\n", asi, size, T0, T1); +#endif + stl_phys((target_phys_addr_t)((env->mxccregs[1] + 0) & 0xffffffffULL), env->mxccdata[0] >> 32); + stl_phys((target_phys_addr_t)((env->mxccregs[1] + 4) & 0xffffffffULL), env->mxccdata[0]); + stl_phys((target_phys_addr_t)((env->mxccregs[1] + 8) & 0xffffffffULL), env->mxccdata[1] >> 32); + stl_phys((target_phys_addr_t)((env->mxccregs[1] + 12) & 0xffffffffULL), env->mxccdata[1]); + stl_phys((target_phys_addr_t)((env->mxccregs[1] + 16) & 0xffffffffULL), env->mxccdata[2] >> 32); + stl_phys((target_phys_addr_t)((env->mxccregs[1] + 20) & 0xffffffffULL), env->mxccdata[2]); + stl_phys((target_phys_addr_t)((env->mxccregs[1] + 24) & 0xffffffffULL), env->mxccdata[3] >> 32); + stl_phys((target_phys_addr_t)((env->mxccregs[1] + 28) & 0xffffffffULL), env->mxccdata[3]); + break; + case 0x01c00a00: /* MXCC control register */ + if (size == 8) + env->mxccregs[3] = ((uint64_t)T1 << 32) | T2; +#ifdef DEBUG_MXCC + else + printf("ERROR: helper_st_asi(asi = %d, size = %d) T0 = %08x, T1 = %08x: unsupported size\n", asi, size, T0, T1); +#endif + break; + case 0x01c00a04: /* MXCC control register */ + if (size == 4) + env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000) | T1; +#ifdef DEBUG_MXCC + else + printf("ERROR: helper_st_asi(asi = %d, size = %d) T0 = %08x, T1 = %08x: unsupported size\n", asi, size, T0, T1); +#endif + break; + case 0x01c00e00: /* MXCC error register */ + if (size == 8) + env->mxccregs[6] = ((uint64_t)T1 << 32) | T2; +#ifdef DEBUG_MXCC + else + printf("ERROR: helper_st_asi(asi = %d, size = %d) T0 = %08x, T1 = %08x: unsupported size\n", asi, size, T0, T1); +#endif + 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; +#ifdef DEBUG_MXCC + else + printf("ERROR: helper_st_asi(asi = %d, size = %d) T0 = %08x, T1 = %08x: unsupported size\n", asi, size, T0, T1); +#endif + break; + default: +#ifdef DEBUG_MXCC + printf("ERROR: helper_st_asi(asi = %d, size = %d) T0 = %08x, T1 = %08x: unsupported address\n", asi, size, T0, T1); +#endif + break; + } +#ifdef DEBUG_MXCC + printf("helper_st_asi(asi = %d, size = %d) T0 = %08x, T1 = %08x\n", asi, size, T0, T1); + dump_mxcc(env); +#endif break; case 3: /* MMU flush */ { Index: target-sparc/translate.c =================================================================== RCS file: /sources/qemu/qemu/target-sparc/translate.c,v retrieving revision 1.74 diff -p -u -r1.74 translate.c --- target-sparc/translate.c 10 Oct 2007 19:11:54 -0000 1.74 +++ target-sparc/translate.c 13 Oct 2007 20:35:53 -0000 @@ -3618,12 +3618,13 @@ void sparc_cpu_list (FILE *f, int (*cpu_ } } -int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def) +int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def, 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; }