Revision 3b1c8be4 target-mips/helper.c

b/target-mips/helper.c
41 41
static int map_address (CPUState *env, target_ulong *physical, int *prot,
42 42
                        target_ulong address, int rw, int access_type)
43 43
{
44
    target_ulong tag = address & (TARGET_PAGE_MASK << 1);
45
    uint8_t ASID = env->CP0_EntryHi & 0xFF;
46
    tlb_t *tlb;
47
    int i, n;
44
    int i;
48 45

  
49 46
    for (i = 0; i < env->tlb_in_use; i++) {
50
        tlb = &env->tlb[i];
47
        tlb_t *tlb = &env->tlb[i];
48
        /* 1k pages are not supported. */
49
        uint8_t ASID = env->CP0_EntryHi & 0xFF;
50
        target_ulong mask = tlb->PageMask | 0x1FFF;
51
        target_ulong tag = address & ~mask;
52
        int n;
53

  
51 54
        /* Check ASID, virtual page number & size */
52 55
        if ((tlb->G == 1 || tlb->ASID == ASID) &&
53 56
            tlb->VPN == tag) {
54 57
            /* TLB match */
55
            n = (address >> TARGET_PAGE_BITS) & 1;
58
            n = !!(address & mask & ~(mask >> 1));
56 59
            /* Check access rights */
57 60
           if (!(n ? tlb->V1 : tlb->V0))
58 61
                return TLBRET_INVALID;
59 62
           if (rw == 0 || (n ? tlb->D1 : tlb->D0)) {
60
                *physical = tlb->PFN[n] | (address & ~TARGET_PAGE_MASK);
63
                *physical = tlb->PFN[n] | (address & (mask >> 1));
61 64
                *prot = PAGE_READ;
62 65
                if (n ? tlb->D1 : tlb->D0)
63 66
                    *prot |= PAGE_WRITE;
......
420 423
void invalidate_tlb (CPUState *env, int idx, int use_extra)
421 424
{
422 425
    tlb_t *tlb;
423
    uint8_t ASID;
424

  
425
    ASID = env->CP0_EntryHi & 0xFF;
426
    target_ulong addr;
427
    target_ulong end;
428
    uint8_t ASID = env->CP0_EntryHi & 0xFF;
429
    target_ulong mask;
426 430

  
427 431
    tlb = &env->tlb[idx];
428 432
    /* The qemu TLB is flushed then the ASID changes, so no need to
......
440 444
        return;
441 445
    }
442 446

  
443
    if (tlb->V0)
444
            tlb_flush_page (env, tlb->VPN);
445
    if (tlb->V1)
446
            tlb_flush_page (env, tlb->VPN + TARGET_PAGE_SIZE);
447
    /* 1k pages are not supported. */
448
    mask = tlb->PageMask | 0x1FFF;
449
    if (tlb->V0) {
450
        addr = tlb->VPN;
451
        end = addr | (mask >> 1);
452
        while (addr < end) {
453
            tlb_flush_page (env, addr);
454
            addr += TARGET_PAGE_SIZE;
455
        }
456
    }
457
    if (tlb->V1) {
458
        addr = tlb->VPN | ((mask >> 1) + 1);
459
        addr = tlb->VPN + TARGET_PAGE_SIZE;
460
        end = addr | mask;
461
        while (addr < end) {
462
            tlb_flush_page (env, addr);
463
            addr += TARGET_PAGE_SIZE;
464
        }
465
    }
447 466
}

Also available in: Unified diff