Commit 99029be1 authored by Yongbok Kim's avatar Yongbok Kim Committed by Aleksandar Markovic
Browse files

target/mips: Add implementation of GINVT instruction



Implement emulation of GINVT instruction. As QEMU doesn't support
caches and virtualization, this implementation covers only one
instruction (GINVT - Global Invalidate TLB) among all TLB-related
MIPS instructions.

Reviewed-by: default avatarAleksandar Rikalo <aleksandar.rikalo@rt-rk.com>
Signed-off-by: default avatarYongbok Kim <yongbok.kim@mips.com>
Signed-off-by: default avatarAleksandar Markovic <amarkovic@wavecomp.com>
Message-Id: <1579883929-1517-5-git-send-email-aleksandar.markovic@rt-rk.com>
parent feafe82c
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -1409,6 +1409,16 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"dvp",        "t",     0x41600024, 0xffe0ffff, TRAP|WR_t,            0, I32R6},
{"evp",        "",      0x41600004, 0xffffffff, TRAP,                 0, I32R6},
{"evp",        "t",     0x41600004, 0xffe0ffff, TRAP|WR_t,            0, I32R6},
{"ginvi",      "v",     0x7c00003d, 0xfc1ffcff, TRAP | INSN_TLB,      0, I32R6},
{"ginvt",      "v",     0x7c0000bd, 0xfc1ffcff, TRAP | INSN_TLB,      0, I32R6},
{"crc32b",     "t,v,t", 0x7c00000f, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I32R6},
{"crc32h",     "t,v,t", 0x7c00004f, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I32R6},
{"crc32w",     "t,v,t", 0x7c00008f, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I32R6},
{"crc32d",     "t,v,t", 0x7c0000cf, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I64R6},
{"crc32cb",    "t,v,t", 0x7c00010f, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I32R6},
{"crc32ch",    "t,v,t", 0x7c00014f, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I32R6},
{"crc32cw",    "t,v,t", 0x7c00018f, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I32R6},
{"crc32cd",    "t,v,t", 0x7c0001cf, 0xfc00ff3f, WR_d | RD_s | RD_t,   0, I64R6},

/* MSA */
{"sll.b",   "+d,+e,+f", 0x7800000d, 0xffe0003f, WR_VD|RD_VS|RD_VT,  0, MSA},
+1 −1
Original line number Diff line number Diff line
@@ -309,7 +309,7 @@ typedef struct mips_def_t mips_def_t;
#define CP0_REG04__USERLOCAL       2
#define CP0_REG04__XCONTEXTCONFIG  3
#define CP0_REG04__DBGCONTEXTID    4
#define CP0_REG00__MMID            5
#define CP0_REG04__MMID            5
/* CP0 Register 05 */
#define CP0_REG05__PAGEMASK        0
#define CP0_REG05__PAGEGRAIN       1
+16 −4
Original line number Diff line number Diff line
@@ -72,8 +72,13 @@ int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
                    target_ulong address, int rw, int access_type)
{
    uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
    uint32_t MMID = env->CP0_MemoryMapID;
    bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
    uint32_t tlb_mmid;
    int i;

    MMID = mi ? MMID : (uint32_t) ASID;

    for (i = 0; i < env->tlb->tlb_in_use; i++) {
        r4k_tlb_t *tlb = &env->tlb->mmu.r4k.tlb[i];
        /* 1k pages are not supported. */
@@ -84,8 +89,9 @@ int r4k_map_address(CPUMIPSState *env, hwaddr *physical, int *prot,
        tag &= env->SEGMask;
#endif

        /* Check ASID, virtual page number & size */
        if ((tlb->G == 1 || tlb->ASID == ASID) && VPN == tag && !tlb->EHINV) {
        /* Check ASID/MMID, virtual page number & size */
        tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
        if ((tlb->G == 1 || tlb_mmid == MMID) && VPN == tag && !tlb->EHINV) {
            /* TLB match */
            int n = !!(address & mask & ~(mask >> 1));
            /* Check access rights */
@@ -1418,14 +1424,20 @@ void r4k_invalidate_tlb(CPUMIPSState *env, int idx, int use_extra)
    target_ulong addr;
    target_ulong end;
    uint16_t ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
    uint32_t MMID = env->CP0_MemoryMapID;
    bool mi = !!((env->CP0_Config5 >> CP0C5_MI) & 1);
    uint32_t tlb_mmid;
    target_ulong mask;

    MMID = mi ? MMID : (uint32_t) ASID;

    tlb = &env->tlb->mmu.r4k.tlb[idx];
    /*
     * The qemu TLB is flushed when the ASID changes, so no need to
     * The qemu TLB is flushed when the ASID/MMID changes, so no need to
     * flush these entries again.
     */
    if (tlb->G == 0 && tlb->ASID != ASID) {
    tlb_mmid = mi ? tlb->MMID : (uint32_t) tlb->ASID;
    if (tlb->G == 0 && tlb_mmid != MMID) {
        return;
    }

+2 −0
Original line number Diff line number Diff line
@@ -120,6 +120,7 @@ DEF_HELPER_2(mtc0_tcschefback, void, env, tl)
DEF_HELPER_2(mttc0_tcschefback, void, env, tl)
DEF_HELPER_2(mtc0_entrylo1, void, env, tl)
DEF_HELPER_2(mtc0_context, void, env, tl)
DEF_HELPER_2(mtc0_memorymapid, void, env, tl)
DEF_HELPER_2(mtc0_pagemask, void, env, tl)
DEF_HELPER_2(mtc0_pagegrain, void, env, tl)
DEF_HELPER_2(mtc0_segctl0, void, env, tl)
@@ -376,6 +377,7 @@ DEF_HELPER_1(ei, tl, env)
DEF_HELPER_1(eret, void, env)
DEF_HELPER_1(eretnc, void, env)
DEF_HELPER_1(deret, void, env)
DEF_HELPER_3(ginvt, void, env, tl, i32)
#endif /* !CONFIG_USER_ONLY */
DEF_HELPER_1(rdhwr_cpunum, tl, env)
DEF_HELPER_1(rdhwr_synci_step, tl, env)
+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ struct r4k_tlb_t {
    target_ulong VPN;
    uint32_t PageMask;
    uint16_t ASID;
    uint32_t MMID;
    unsigned int G:1;
    unsigned int C0:3;
    unsigned int C1:3;
Loading