static void raise_mmu_exception(CPUMIPSState *env, target_ulong address,

                                int rw, int tlb_error)

{

    CPUState *cs = CPU(mips_env_get_cpu(env));

    int exception = 0, error_code = 0;



    switch (tlb_error) {

    default:

    case TLBRET_BADADDR:

        /* Reference to kernel address from user mode or supervisor mode */

        /* Reference to supervisor address from user mode */

        if (rw == MMU_DATA_STORE) {

            exception = EXCP_AdES;

        } else {

            exception = EXCP_AdEL;

        }

        break;

    case TLBRET_NOMATCH:

        /* No TLB match for a mapped address */

        if (rw == MMU_DATA_STORE) {

            exception = EXCP_TLBS;

        } else {

            exception = EXCP_TLBL;

        }

        error_code = 1;

        break;

    case TLBRET_INVALID:

        /* TLB match with no valid bit */

        if (rw == MMU_DATA_STORE) {

            exception = EXCP_TLBS;

        } else {

            exception = EXCP_TLBL;

        }

        break;

    case TLBRET_DIRTY:

        /* TLB match but 'D' bit is cleared */

        exception = EXCP_LTLBL;

        break;

    case TLBRET_XI:

        /* Execute-Inhibit Exception */

        if (env->CP0_PageGrain & (1 << CP0PG_IEC)) {

            exception = EXCP_TLBXI;

        } else {

            exception = EXCP_TLBL;

        }

        break;

    case TLBRET_RI:

        /* Read-Inhibit Exception */

        if (env->CP0_PageGrain & (1 << CP0PG_IEC)) {

            exception = EXCP_TLBRI;

        } else {

            exception = EXCP_TLBL;

        }

        break;

    }

    /* Raise exception */

    env->CP0_BadVAddr = address;

    env->CP0_Context = (env->CP0_Context & ~0x007fffff) |

                       ((address >> 9) & 0x007ffff0);

    env->CP0_EntryHi =

        (env->CP0_EntryHi & 0xFF) | (address & (TARGET_PAGE_MASK << 1));

#if defined(TARGET_MIPS64)

    env->CP0_EntryHi &= env->SEGMask;

    env->CP0_XContext = (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) |

                        ((address & 0xC00000000000ULL) >> (55 - env->SEGBITS)) |

                        ((address & ((1ULL << env->SEGBITS) - 1) & 0xFFFFFFFFFFFFE000ULL) >> 9);

#endif

    cs->exception_index = exception;

    env->error_code = error_code;

}
