Revision f2e9ebef

b/target-mips/helper.c
73 73
    for (i = 0; i < env->tlb_in_use; i++) {
74 74
        r4k_tlb_t *tlb = &env->mmu.r4k.tlb[i];
75 75
        /* 1k pages are not supported. */
76
        target_ulong mask = tlb->PageMask | 0x1FFF;
76
        target_ulong mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
77 77
        target_ulong tag = address & ~mask;
78
        int n;
78
        target_ulong VPN = tlb->VPN & ~mask;
79 79

  
80 80
        /* Check ASID, virtual page number & size */
81
        if ((tlb->G == 1 || tlb->ASID == ASID) &&
82
            tlb->VPN == tag) {
81
        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
83 82
            /* TLB match */
84
            n = !!(address & mask & ~(mask >> 1));
83
            int n = !!(address & mask & ~(mask >> 1));
85 84
            /* Check access rights */
86
           if (!(n ? tlb->V1 : tlb->V0))
85
            if (!(n ? tlb->V1 : tlb->V0))
87 86
                return TLBRET_INVALID;
88
           if (rw == 0 || (n ? tlb->D1 : tlb->D0)) {
87
            if (rw == 0 || (n ? tlb->D1 : tlb->D0)) {
89 88
                *physical = tlb->PFN[n] | (address & (mask >> 1));
90 89
                *prot = PAGE_READ;
91 90
                if (n ? tlb->D1 : tlb->D0)
......
502 501
    target_ulong mask;
503 502

  
504 503
    tlb = &env->mmu.r4k.tlb[idx];
505
    /* The qemu TLB is flushed then the ASID changes, so no need to
504
    /* The qemu TLB is flushed when the ASID changes, so no need to
506 505
       flush these entries again.  */
507 506
    if (tlb->G == 0 && tlb->ASID != ASID) {
508 507
        return;
......
518 517
    }
519 518

  
520 519
    /* 1k pages are not supported. */
521
    mask = tlb->PageMask | 0x1FFF;
520
    mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
522 521
    if (tlb->V0) {
523
        addr = tlb->VPN;
522
        addr = tlb->VPN & ~mask;
524 523
        end = addr | (mask >> 1);
525 524
        while (addr < end) {
526 525
            tlb_flush_page (env, addr);
......
528 527
        }
529 528
    }
530 529
    if (tlb->V1) {
531
        addr = tlb->VPN | ((mask >> 1) + 1);
532
        addr = tlb->VPN + TARGET_PAGE_SIZE;
530
        addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1);
533 531
        end = addr | mask;
534 532
        while (addr < end) {
535 533
            tlb_flush_page (env, addr);
b/target-mips/op.c
1283 1283
void op_mtc0_pagemask (void)
1284 1284
{
1285 1285
    /* 1k pages not implemented */
1286
    env->CP0_PageMask = T0 & 0x1FFFE000;
1286
    env->CP0_PageMask = T0 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
1287 1287
    RETURN();
1288 1288
}
1289 1289

  
b/target-mips/op_helper.c
390 390

  
391 391
    /* XXX: detect conflicting TLBs and raise a MCHECK exception when needed */
392 392
    tlb = &env->mmu.r4k.tlb[idx];
393
    tlb->VPN = env->CP0_EntryHi & ~(target_ulong)0x1FFF;
393
    tlb->VPN = env->CP0_EntryHi & (TARGET_PAGE_MASK << 1);
394 394
    tlb->ASID = env->CP0_EntryHi & 0xFF;
395 395
    tlb->PageMask = env->CP0_PageMask;
396 396
    tlb->G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
......
426 426
void r4k_do_tlbp (void)
427 427
{
428 428
    r4k_tlb_t *tlb;
429
    target_ulong mask;
429 430
    target_ulong tag;
431
    target_ulong VPN;
430 432
    uint8_t ASID;
431 433
    int i;
432 434

  
433
    tag = env->CP0_EntryHi & (int32_t)0xFFFFE000;
434 435
    ASID = env->CP0_EntryHi & 0xFF;
435 436
    for (i = 0; i < env->nb_tlb; i++) {
436 437
        tlb = &env->mmu.r4k.tlb[i];
438
        /* 1k pages are not supported. */
439
        mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
440
        tag = env->CP0_EntryHi & ~mask;
441
        VPN = tlb->VPN & ~mask;
437 442
        /* Check ASID, virtual page number & size */
438
        if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) {
443
        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
439 444
            /* TLB match */
440 445
            env->CP0_Index = i;
441 446
            break;
......
445 450
        /* No match.  Discard any shadow entries, if any of them match.  */
446 451
        for (i = env->nb_tlb; i < env->tlb_in_use; i++) {
447 452
	    tlb = &env->mmu.r4k.tlb[i];
448

  
453
	    /* 1k pages are not supported. */
454
	    mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);
455
	    tag = env->CP0_EntryHi & ~mask;
456
	    VPN = tlb->VPN & ~mask;
449 457
	    /* Check ASID, virtual page number & size */
450
	    if ((tlb->G == 1 || tlb->ASID == ASID) && tlb->VPN == tag) {
458
	    if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag) {
451 459
                r4k_mips_tlb_flush_extra (env, i);
452 460
	        break;
453 461
	    }

Also available in: Unified diff