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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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;
|