Commit 952a328ff50c323b28fb07658ccbc6604cf26a45
1 parent
992f48a0
SuperSparc MXCC support (Robert Reif)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3397 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
160 additions
and
21 deletions
hw/sun4m.c
| ... | ... | @@ -327,7 +327,7 @@ static void *sun4m_hw_init(const struct hwdef *hwdef, int RAM_size, |
| 327 | 327 | |
| 328 | 328 | for(i = 0; i < smp_cpus; i++) { |
| 329 | 329 | env = cpu_init(); |
| 330 | - cpu_sparc_register(env, def); | |
| 330 | + cpu_sparc_register(env, def, i); | |
| 331 | 331 | envs[i] = env; |
| 332 | 332 | if (i == 0) { |
| 333 | 333 | qemu_register_reset(main_cpu_reset, env); | ... | ... |
hw/sun4u.c
| ... | ... | @@ -358,7 +358,7 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device, |
| 358 | 358 | exit(1); |
| 359 | 359 | } |
| 360 | 360 | env = cpu_init(); |
| 361 | - cpu_sparc_register(env, def); | |
| 361 | + cpu_sparc_register(env, def, 0); | |
| 362 | 362 | bh = qemu_bh_new(tick_irq, env); |
| 363 | 363 | env->tick = ptimer_init(bh); |
| 364 | 364 | ptimer_set_period(env->tick, 1ULL); | ... | ... |
linux-user/main.c
| ... | ... | @@ -2142,7 +2142,7 @@ int main(int argc, char **argv) |
| 2142 | 2142 | fprintf(stderr, "Unable to find Sparc CPU definition\n"); |
| 2143 | 2143 | exit(1); |
| 2144 | 2144 | } |
| 2145 | - cpu_sparc_register(env, def); | |
| 2145 | + cpu_sparc_register(env, def, 0); | |
| 2146 | 2146 | env->pc = regs->pc; |
| 2147 | 2147 | env->npc = regs->npc; |
| 2148 | 2148 | env->y = regs->y; | ... | ... |
target-sparc/cpu.h
| ... | ... | @@ -212,6 +212,8 @@ typedef struct CPUSPARCState { |
| 212 | 212 | uint64_t dtlb_tte[64]; |
| 213 | 213 | #else |
| 214 | 214 | uint32_t mmuregs[16]; |
| 215 | + uint64_t mxccdata[4]; | |
| 216 | + uint64_t mxccregs[8]; | |
| 215 | 217 | #endif |
| 216 | 218 | /* temporary float registers */ |
| 217 | 219 | float32 ft0, ft1; |
| ... | ... | @@ -268,7 +270,8 @@ int cpu_sparc_close(CPUSPARCState *s); |
| 268 | 270 | int sparc_find_by_name (const unsigned char *name, const sparc_def_t **def); |
| 269 | 271 | void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, |
| 270 | 272 | ...)); |
| 271 | -int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def); | |
| 273 | +int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def, | |
| 274 | + unsigned int cpu); | |
| 272 | 275 | |
| 273 | 276 | #define GET_PSR(env) (env->version | (env->psr & PSR_ICC) | \ |
| 274 | 277 | (env->psref? PSR_EF : 0) | \ | ... | ... |
target-sparc/op_helper.c
| ... | ... | @@ -2,9 +2,24 @@ |
| 2 | 2 | |
| 3 | 3 | //#define DEBUG_PCALL |
| 4 | 4 | //#define DEBUG_MMU |
| 5 | +//#define DEBUG_MXCC | |
| 5 | 6 | //#define DEBUG_UNALIGNED |
| 6 | 7 | //#define DEBUG_UNASSIGNED |
| 7 | 8 | |
| 9 | +#ifdef DEBUG_MMU | |
| 10 | +#define DPRINTF_MMU(fmt, args...) \ | |
| 11 | +do { printf("MMU: " fmt , ##args); } while (0) | |
| 12 | +#else | |
| 13 | +#define DPRINTF_MMU(fmt, args...) | |
| 14 | +#endif | |
| 15 | + | |
| 16 | +#ifdef DEBUG_MXCC | |
| 17 | +#define DPRINTF_MXCC(fmt, args...) \ | |
| 18 | +do { printf("MXCC: " fmt , ##args); } while (0) | |
| 19 | +#else | |
| 20 | +#define DPRINTF_MXCC(fmt, args...) | |
| 21 | +#endif | |
| 22 | + | |
| 8 | 23 | void raise_exception(int tt) |
| 9 | 24 | { |
| 10 | 25 | env->exception_index = tt; |
| ... | ... | @@ -139,12 +154,58 @@ GEN_FCMP(fcmped_fcc3, float64, DT0, DT1, 26, 1); |
| 139 | 154 | |
| 140 | 155 | #ifndef TARGET_SPARC64 |
| 141 | 156 | #ifndef CONFIG_USER_ONLY |
| 157 | + | |
| 158 | +#ifdef DEBUG_MXCC | |
| 159 | +static void dump_mxcc(CPUState *env) | |
| 160 | +{ | |
| 161 | + printf("mxccdata: %016llx %016llx %016llx %016llx\n", | |
| 162 | + env->mxccdata[0], env->mxccdata[1], env->mxccdata[2], env->mxccdata[3]); | |
| 163 | + printf("mxccregs: %016llx %016llx %016llx %016llx\n" | |
| 164 | + " %016llx %016llx %016llx %016llx\n", | |
| 165 | + env->mxccregs[0], env->mxccregs[1], env->mxccregs[2], env->mxccregs[3], | |
| 166 | + env->mxccregs[4], env->mxccregs[5], env->mxccregs[6], env->mxccregs[7]); | |
| 167 | +} | |
| 168 | +#endif | |
| 169 | + | |
| 142 | 170 | void helper_ld_asi(int asi, int size, int sign) |
| 143 | 171 | { |
| 144 | 172 | uint32_t ret = 0; |
| 173 | +#ifdef DEBUG_MXCC | |
| 174 | + uint32_t last_T0 = T0; | |
| 175 | +#endif | |
| 145 | 176 | |
| 146 | 177 | switch (asi) { |
| 147 | 178 | case 2: /* SuperSparc MXCC registers */ |
| 179 | + switch (T0) { | |
| 180 | + case 0x01c00a00: /* MXCC control register */ | |
| 181 | + if (size == 8) { | |
| 182 | + ret = env->mxccregs[3]; | |
| 183 | + T0 = env->mxccregs[3] >> 32; | |
| 184 | + } else | |
| 185 | + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); | |
| 186 | + break; | |
| 187 | + case 0x01c00a04: /* MXCC control register */ | |
| 188 | + if (size == 4) | |
| 189 | + ret = env->mxccregs[3]; | |
| 190 | + else | |
| 191 | + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); | |
| 192 | + break; | |
| 193 | + case 0x01c00f00: /* MBus port address register */ | |
| 194 | + if (size == 8) { | |
| 195 | + ret = env->mxccregs[7]; | |
| 196 | + T0 = env->mxccregs[7] >> 32; | |
| 197 | + } else | |
| 198 | + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); | |
| 199 | + break; | |
| 200 | + default: | |
| 201 | + DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size); | |
| 202 | + break; | |
| 203 | + } | |
| 204 | + DPRINTF_MXCC("asi = %d, size = %d, sign = %d, T0 = %08x -> ret = %08x," | |
| 205 | + "T0 = %08x\n", asi, size, sign, last_T0, ret, T0); | |
| 206 | +#ifdef DEBUG_MXCC | |
| 207 | + dump_mxcc(env); | |
| 208 | +#endif | |
| 148 | 209 | break; |
| 149 | 210 | case 3: /* MMU probe */ |
| 150 | 211 | { |
| ... | ... | @@ -157,9 +218,7 @@ void helper_ld_asi(int asi, int size, int sign) |
| 157 | 218 | ret = mmu_probe(env, T0, mmulev); |
| 158 | 219 | //bswap32s(&ret); |
| 159 | 220 | } |
| 160 | -#ifdef DEBUG_MMU | |
| 161 | - printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret); | |
| 162 | -#endif | |
| 221 | + DPRINTF_MMU("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret); | |
| 163 | 222 | } |
| 164 | 223 | break; |
| 165 | 224 | case 4: /* read MMU regs */ |
| ... | ... | @@ -169,9 +228,7 @@ void helper_ld_asi(int asi, int size, int sign) |
| 169 | 228 | ret = env->mmuregs[reg]; |
| 170 | 229 | if (reg == 3) /* Fault status cleared on read */ |
| 171 | 230 | env->mmuregs[reg] = 0; |
| 172 | -#ifdef DEBUG_MMU | |
| 173 | - printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret); | |
| 174 | -#endif | |
| 231 | + DPRINTF_MMU("mmu_read: reg[%d] = 0x%08x\n", reg, ret); | |
| 175 | 232 | } |
| 176 | 233 | break; |
| 177 | 234 | case 9: /* Supervisor code access */ |
| ... | ... | @@ -302,15 +359,93 @@ void helper_st_asi(int asi, int size) |
| 302 | 359 | { |
| 303 | 360 | switch(asi) { |
| 304 | 361 | case 2: /* SuperSparc MXCC registers */ |
| 362 | + switch (T0) { | |
| 363 | + case 0x01c00000: /* MXCC stream data register 0 */ | |
| 364 | + if (size == 8) | |
| 365 | + env->mxccdata[0] = ((uint64_t)T1 << 32) | T2; | |
| 366 | + else | |
| 367 | + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); | |
| 368 | + break; | |
| 369 | + case 0x01c00008: /* MXCC stream data register 1 */ | |
| 370 | + if (size == 8) | |
| 371 | + env->mxccdata[1] = ((uint64_t)T1 << 32) | T2; | |
| 372 | + else | |
| 373 | + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); | |
| 374 | + break; | |
| 375 | + case 0x01c00010: /* MXCC stream data register 2 */ | |
| 376 | + if (size == 8) | |
| 377 | + env->mxccdata[2] = ((uint64_t)T1 << 32) | T2; | |
| 378 | + else | |
| 379 | + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); | |
| 380 | + break; | |
| 381 | + case 0x01c00018: /* MXCC stream data register 3 */ | |
| 382 | + if (size == 8) | |
| 383 | + env->mxccdata[3] = ((uint64_t)T1 << 32) | T2; | |
| 384 | + else | |
| 385 | + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); | |
| 386 | + break; | |
| 387 | + case 0x01c00100: /* MXCC stream source */ | |
| 388 | + if (size == 8) | |
| 389 | + env->mxccregs[0] = ((uint64_t)T1 << 32) | T2; | |
| 390 | + else | |
| 391 | + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); | |
| 392 | + env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 0); | |
| 393 | + env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 8); | |
| 394 | + env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 16); | |
| 395 | + env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) + 24); | |
| 396 | + break; | |
| 397 | + case 0x01c00200: /* MXCC stream destination */ | |
| 398 | + if (size == 8) | |
| 399 | + env->mxccregs[1] = ((uint64_t)T1 << 32) | T2; | |
| 400 | + else | |
| 401 | + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); | |
| 402 | + stq_phys((env->mxccregs[1] & 0xffffffffULL) + 0, env->mxccdata[0]); | |
| 403 | + stq_phys((env->mxccregs[1] & 0xffffffffULL) + 8, env->mxccdata[1]); | |
| 404 | + stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16, env->mxccdata[2]); | |
| 405 | + stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24, env->mxccdata[3]); | |
| 406 | + break; | |
| 407 | + case 0x01c00a00: /* MXCC control register */ | |
| 408 | + if (size == 8) | |
| 409 | + env->mxccregs[3] = ((uint64_t)T1 << 32) | T2; | |
| 410 | + else | |
| 411 | + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); | |
| 412 | + break; | |
| 413 | + case 0x01c00a04: /* MXCC control register */ | |
| 414 | + if (size == 4) | |
| 415 | + env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000) | T1; | |
| 416 | + else | |
| 417 | + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); | |
| 418 | + break; | |
| 419 | + case 0x01c00e00: /* MXCC error register */ | |
| 420 | + if (size == 8) | |
| 421 | + env->mxccregs[6] = ((uint64_t)T1 << 32) | T2; | |
| 422 | + else | |
| 423 | + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); | |
| 424 | + if (env->mxccregs[6] == 0xffffffffffffffffULL) { | |
| 425 | + // this is probably a reset | |
| 426 | + } | |
| 427 | + break; | |
| 428 | + case 0x01c00f00: /* MBus port address register */ | |
| 429 | + if (size == 8) | |
| 430 | + env->mxccregs[7] = ((uint64_t)T1 << 32) | T2; | |
| 431 | + else | |
| 432 | + DPRINTF_MXCC("%08x: unimplemented access size: %d\n", T0, size); | |
| 433 | + break; | |
| 434 | + default: | |
| 435 | + DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", T0, size); | |
| 436 | + break; | |
| 437 | + } | |
| 438 | + DPRINTF_MXCC("asi = %d, size = %d, T0 = %08x, T1 = %08x\n", asi, size, T0, T1); | |
| 439 | +#ifdef DEBUG_MXCC | |
| 440 | + dump_mxcc(env); | |
| 441 | +#endif | |
| 305 | 442 | break; |
| 306 | 443 | case 3: /* MMU flush */ |
| 307 | 444 | { |
| 308 | 445 | int mmulev; |
| 309 | 446 | |
| 310 | 447 | mmulev = (T0 >> 8) & 15; |
| 311 | -#ifdef DEBUG_MMU | |
| 312 | - printf("mmu flush level %d\n", mmulev); | |
| 313 | -#endif | |
| 448 | + DPRINTF_MMU("mmu flush level %d\n", mmulev); | |
| 314 | 449 | switch (mmulev) { |
| 315 | 450 | case 0: // flush page |
| 316 | 451 | tlb_flush_page(env, T0 & 0xfffff000); |
| ... | ... | @@ -359,10 +494,10 @@ void helper_st_asi(int asi, int size) |
| 359 | 494 | env->mmuregs[reg] = T1; |
| 360 | 495 | break; |
| 361 | 496 | } |
| 362 | -#ifdef DEBUG_MMU | |
| 363 | 497 | if (oldreg != env->mmuregs[reg]) { |
| 364 | - printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]); | |
| 498 | + DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]); | |
| 365 | 499 | } |
| 500 | +#ifdef DEBUG_MMU | |
| 366 | 501 | dump_mmu(env); |
| 367 | 502 | #endif |
| 368 | 503 | return; |
| ... | ... | @@ -962,8 +1097,8 @@ void helper_st_asi(int asi, int size) |
| 962 | 1097 | // Mappings generated during D/I MMU disabled mode are |
| 963 | 1098 | // invalid in normal mode |
| 964 | 1099 | if (oldreg != env->lsu) { |
| 1100 | + DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu); | |
| 965 | 1101 | #ifdef DEBUG_MMU |
| 966 | - printf("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu); | |
| 967 | 1102 | dump_mmu(env); |
| 968 | 1103 | #endif |
| 969 | 1104 | tlb_flush(env, 1); |
| ... | ... | @@ -995,10 +1130,10 @@ void helper_st_asi(int asi, int size) |
| 995 | 1130 | break; |
| 996 | 1131 | } |
| 997 | 1132 | env->immuregs[reg] = T1; |
| 998 | -#ifdef DEBUG_MMU | |
| 999 | 1133 | if (oldreg != env->immuregs[reg]) { |
| 1000 | - printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]); | |
| 1134 | + DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->immuregs[reg]); | |
| 1001 | 1135 | } |
| 1136 | +#ifdef DEBUG_MMU | |
| 1002 | 1137 | dump_mmu(env); |
| 1003 | 1138 | #endif |
| 1004 | 1139 | return; |
| ... | ... | @@ -1064,10 +1199,10 @@ void helper_st_asi(int asi, int size) |
| 1064 | 1199 | break; |
| 1065 | 1200 | } |
| 1066 | 1201 | env->dmmuregs[reg] = T1; |
| 1067 | -#ifdef DEBUG_MMU | |
| 1068 | 1202 | if (oldreg != env->dmmuregs[reg]) { |
| 1069 | - printf("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]); | |
| 1203 | + DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08" PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]); | |
| 1070 | 1204 | } |
| 1205 | +#ifdef DEBUG_MMU | |
| 1071 | 1206 | dump_mmu(env); |
| 1072 | 1207 | #endif |
| 1073 | 1208 | return; | ... | ... |
target-sparc/translate.c
| ... | ... | @@ -3618,12 +3618,13 @@ void sparc_cpu_list (FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...)) |
| 3618 | 3618 | } |
| 3619 | 3619 | } |
| 3620 | 3620 | |
| 3621 | -int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def) | |
| 3621 | +int cpu_sparc_register (CPUSPARCState *env, const sparc_def_t *def, unsigned int cpu) | |
| 3622 | 3622 | { |
| 3623 | 3623 | env->version = def->iu_version; |
| 3624 | 3624 | env->fsr = def->fpu_version; |
| 3625 | 3625 | #if !defined(TARGET_SPARC64) |
| 3626 | 3626 | env->mmuregs[0] |= def->mmu_version; |
| 3627 | + env->mxccregs[7] = ((cpu + 8) & 0xf) << 24; | |
| 3627 | 3628 | #endif |
| 3628 | 3629 | return 0; |
| 3629 | 3630 | } | ... | ... |