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 | } | ... | ... |