Revision 29929e34 target-mips/op_helper.c
b/target-mips/op_helper.c | ||
---|---|---|
298 | 298 |
cpu_abort(env, "mtc0 status irqraise debug\n"); |
299 | 299 |
} |
300 | 300 |
|
301 |
void do_tlbwi (void) |
|
302 |
{ |
|
303 |
cpu_abort(env, "tlbwi\n"); |
|
304 |
} |
|
305 |
|
|
306 |
void do_tlbwr (void) |
|
307 |
{ |
|
308 |
cpu_abort(env, "tlbwr\n"); |
|
309 |
} |
|
310 |
|
|
311 |
void do_tlbp (void) |
|
312 |
{ |
|
313 |
cpu_abort(env, "tlbp\n"); |
|
314 |
} |
|
315 |
|
|
316 |
void do_tlbr (void) |
|
317 |
{ |
|
318 |
cpu_abort(env, "tlbr\n"); |
|
319 |
} |
|
320 |
|
|
321 | 301 |
void cpu_mips_tlb_flush (CPUState *env, int flush_global) |
322 | 302 |
{ |
323 | 303 |
cpu_abort(env, "mips_tlb_flush\n"); |
... | ... | |
389 | 369 |
} |
390 | 370 |
|
391 | 371 |
/* TLB management */ |
392 |
#if defined(MIPS_USES_R4K_TLB) |
|
393 | 372 |
void cpu_mips_tlb_flush (CPUState *env, int flush_global) |
394 | 373 |
{ |
395 | 374 |
/* Flush qemu's TLB and discard all shadowed entries. */ |
... | ... | |
397 | 376 |
env->tlb_in_use = env->nb_tlb; |
398 | 377 |
} |
399 | 378 |
|
400 |
static void mips_tlb_flush_extra (CPUState *env, int first) |
|
379 |
static void r4k_mips_tlb_flush_extra (CPUState *env, int first)
|
|
401 | 380 |
{ |
402 | 381 |
/* Discard entries from env->tlb[first] onwards. */ |
403 | 382 |
while (env->tlb_in_use > first) { |
404 |
invalidate_tlb(env, --env->tlb_in_use, 0); |
|
383 |
r4k_invalidate_tlb(env, --env->tlb_in_use, 0);
|
|
405 | 384 |
} |
406 | 385 |
} |
407 | 386 |
|
408 |
static void fill_tlb (int idx) |
|
387 |
static void r4k_fill_tlb (int idx)
|
|
409 | 388 |
{ |
410 |
tlb_t *tlb; |
|
389 |
r4k_tlb_t *tlb;
|
|
411 | 390 |
|
412 | 391 |
/* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */ |
413 |
tlb = &env->tlb[idx]; |
|
392 |
tlb = &env->mmu.r4k.tlb[idx];
|
|
414 | 393 |
tlb->VPN = env->CP0_EntryHi & ~(target_ulong)0x1FFF; |
415 | 394 |
tlb->ASID = env->CP0_EntryHi & 0xFF; |
416 | 395 |
tlb->PageMask = env->CP0_PageMask; |
... | ... | |
425 | 404 |
tlb->PFN[1] = (env->CP0_EntryLo1 >> 6) << 12; |
426 | 405 |
} |
427 | 406 |
|
428 |
void do_tlbwi (void) |
|
407 |
void r4k_do_tlbwi (void)
|
|
429 | 408 |
{ |
430 | 409 |
/* Discard cached TLB entries. We could avoid doing this if the |
431 | 410 |
tlbwi is just upgrading access permissions on the current entry; |
432 | 411 |
that might be a further win. */ |
433 |
mips_tlb_flush_extra (env, env->nb_tlb); |
|
412 |
r4k_mips_tlb_flush_extra (env, env->nb_tlb);
|
|
434 | 413 |
|
435 |
invalidate_tlb(env, env->CP0_Index % env->nb_tlb, 0); |
|
436 |
fill_tlb(env->CP0_Index % env->nb_tlb); |
|
414 |
r4k_invalidate_tlb(env, env->CP0_Index % env->nb_tlb, 0);
|
|
415 |
r4k_fill_tlb(env->CP0_Index % env->nb_tlb);
|
|
437 | 416 |
} |
438 | 417 |
|
439 |
void do_tlbwr (void) |
|
418 |
void r4k_do_tlbwr (void)
|
|
440 | 419 |
{ |
441 | 420 |
int r = cpu_mips_get_random(env); |
442 | 421 |
|
443 |
invalidate_tlb(env, r, 1); |
|
444 |
fill_tlb(r); |
|
422 |
r4k_invalidate_tlb(env, r, 1);
|
|
423 |
r4k_fill_tlb(r);
|
|
445 | 424 |
} |
446 | 425 |
|
447 |
void do_tlbp (void) |
|
426 |
void r4k_do_tlbp (void)
|
|
448 | 427 |
{ |
449 |
tlb_t *tlb; |
|
428 |
r4k_tlb_t *tlb;
|
|
450 | 429 |
target_ulong tag; |
451 | 430 |
uint8_t ASID; |
452 | 431 |
int i; |
... | ... | |
454 | 433 |
tag = env->CP0_EntryHi & (int32_t)0xFFFFE000; |
455 | 434 |
ASID = env->CP0_EntryHi & 0xFF; |
456 | 435 |
for (i = 0; i < env->nb_tlb; i++) { |
457 |
tlb = &env->tlb[i]; |
|
436 |
tlb = &env->mmu.r4k.tlb[i];
|
|
458 | 437 |
/* Check ASID, virtual page number & size */ |
459 | 438 |
if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) { |
460 | 439 |
/* TLB match */ |
... | ... | |
465 | 444 |
if (i == env->nb_tlb) { |
466 | 445 |
/* No match. Discard any shadow entries, if any of them match. */ |
467 | 446 |
for (i = env->nb_tlb; i < env->tlb_in_use; i++) { |
468 |
tlb = &env->tlb[i]; |
|
447 |
tlb = &env->mmu.r4k.tlb[i];
|
|
469 | 448 |
|
470 | 449 |
/* Check ASID, virtual page number & size */ |
471 | 450 |
if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) { |
472 |
mips_tlb_flush_extra (env, i); |
|
451 |
r4k_mips_tlb_flush_extra (env, i);
|
|
473 | 452 |
break; |
474 | 453 |
} |
475 | 454 |
} |
... | ... | |
478 | 457 |
} |
479 | 458 |
} |
480 | 459 |
|
481 |
void do_tlbr (void) |
|
460 |
void r4k_do_tlbr (void)
|
|
482 | 461 |
{ |
483 |
tlb_t *tlb; |
|
462 |
r4k_tlb_t *tlb;
|
|
484 | 463 |
uint8_t ASID; |
485 | 464 |
|
486 | 465 |
ASID = env->CP0_EntryHi & 0xFF; |
487 |
tlb = &env->tlb[env->CP0_Index % env->nb_tlb]; |
|
466 |
tlb = &env->mmu.r4k.tlb[env->CP0_Index % env->nb_tlb];
|
|
488 | 467 |
|
489 | 468 |
/* If this will change the current ASID, flush qemu's TLB. */ |
490 | 469 |
if (ASID != tlb->ASID) |
491 | 470 |
cpu_mips_tlb_flush (env, 1); |
492 | 471 |
|
493 |
mips_tlb_flush_extra(env, env->nb_tlb); |
|
472 |
r4k_mips_tlb_flush_extra(env, env->nb_tlb);
|
|
494 | 473 |
|
495 | 474 |
env->CP0_EntryHi = tlb->VPN | tlb->ASID; |
496 | 475 |
env->CP0_PageMask = tlb->PageMask; |
... | ... | |
499 | 478 |
env->CP0_EntryLo1 = tlb->G | (tlb->V1 << 1) | (tlb->D1 << 2) | |
500 | 479 |
(tlb->C1 << 3) | (tlb->PFN[1] >> 6); |
501 | 480 |
} |
502 |
#endif |
|
503 | 481 |
|
504 | 482 |
#endif /* !CONFIG_USER_ONLY */ |
505 | 483 |
|
Also available in: Unified diff