Ejemplo n.º 1
0
target_ulong helper_csrrc(CPURISCVState *env, target_ulong src,
        target_ulong csr, target_ulong new_pc) {
    validate_csr(env, csr, 1, new_pc);
    uint64_t csr_backup = csr_read_helper(env, csr);
    csr_write_helper(env, (~src) & csr_backup, csr);
    return csr_backup;
}
Ejemplo n.º 2
0
target_ulong helper_mrts(CPURISCVState *env, target_ulong curr_pc)
{
    target_ulong mstatus = env->csr[NEW_CSR_MSTATUS];
    if(!(get_field(mstatus, MSTATUS_PRV) >= PRV_M)) {
        // TODO: real illegal instruction trap
        printf("ILLEGAL INST");
        exit(1);
    }

    csr_write_helper(env, set_field(mstatus, MSTATUS_PRV, PRV_S),
            NEW_CSR_MSTATUS);
    env->csr[NEW_CSR_SBADADDR] = env->csr[NEW_CSR_MBADADDR];
    env->csr[NEW_CSR_SCAUSE] = env->csr[NEW_CSR_MCAUSE];
    env->csr[NEW_CSR_SEPC] = env->csr[NEW_CSR_MEPC];

    if (env->csr[NEW_CSR_STVEC] & 0x3) {
        helper_raise_exception_mbadaddr(env, NEW_RISCV_EXCP_INST_ADDR_MIS,
                curr_pc);
        return curr_pc;
    }
    return env->csr[NEW_CSR_STVEC];
}
Ejemplo n.º 3
0
target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb)
{
    target_ulong mstatus = env->csr[NEW_CSR_MSTATUS];
    if(!(get_field(mstatus, MSTATUS_PRV) >= PRV_S)) {
        // TODO: real illegal instruction trap
        printf("ILLEGAL INST");
        exit(1);
    }

    target_ulong retpc = 0;
    switch(get_field(mstatus, MSTATUS_PRV)) {
        case PRV_S:
            // set PC val to sepc
            retpc = env->csr[NEW_CSR_SEPC];
            break;
        case PRV_M:
            // set PC val to mepc
            retpc = env->csr[NEW_CSR_MEPC];
            break;
        default:
            // TODO: illegal inst
            printf("ILLEGAL INST");
            exit(1);
            break;
    }
    if (retpc & 0x3) {
        // check for misaligned fetch
        helper_raise_exception_mbadaddr(env, NEW_RISCV_EXCP_INST_ADDR_MIS,
                cpu_pc_deb);
        return cpu_pc_deb;
    }

    target_ulong next_mstatus = pop_priv_stack(env->csr[NEW_CSR_MSTATUS]);
    csr_write_helper(env, next_mstatus, NEW_CSR_MSTATUS);
    return retpc;
}
Ejemplo n.º 4
0
target_ulong helper_csrrc(CPURISCVState *env, target_ulong src, target_ulong csr) {
    uint64_t csr_backup = csr_read_helper(env, csr);
    csr_write_helper(env, (~src) & csr_backup, csr);
    return csr_backup;
}
Ejemplo n.º 5
0
/*
 * Handle writes to CSRs and any resulting special behavior
 *
 * Note: mtohost and mfromhost are not handled here
 */
inline void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
        target_ulong csrno)
{
    #ifdef RISCV_DEBUG_PRINT
    fprintf(stderr, "Write CSR reg: 0x" TARGET_FMT_lx "\n", csrno);
    fprintf(stderr, "Write CSR val: 0x" TARGET_FMT_lx "\n", val_to_write);
    #endif

    switch (csrno)
    {
    case NEW_CSR_FFLAGS:
        env->csr[NEW_CSR_MSTATUS] |= MSTATUS_FS | MSTATUS64_SD;
        env->csr[NEW_CSR_FFLAGS] = val_to_write & (FSR_AEXC >> FSR_AEXC_SHIFT);
        break;
    case NEW_CSR_FRM:
        env->csr[NEW_CSR_MSTATUS] |= MSTATUS_FS | MSTATUS64_SD;
        env->csr[NEW_CSR_FRM] = val_to_write & (FSR_RD >> FSR_RD_SHIFT);
        break;
    case NEW_CSR_FCSR:
        env->csr[NEW_CSR_MSTATUS] |= MSTATUS_FS | MSTATUS64_SD;
        env->csr[NEW_CSR_FFLAGS] = (val_to_write & FSR_AEXC) >> FSR_AEXC_SHIFT;
        env->csr[NEW_CSR_FRM] = (val_to_write & FSR_RD) >> FSR_RD_SHIFT;
        break;
    case NEW_CSR_MTIME:
    case NEW_CSR_STIMEW:
        // this implementation ignores writes to MTIME
        break;
    case NEW_CSR_MTIMEH:
    case NEW_CSR_STIMEHW:
        // this implementation ignores writes to MTIME
        break;
    case NEW_CSR_TIMEW:
        cpu_riscv_store_timew(env, val_to_write);
        break;
    case NEW_CSR_TIMEHW:
        fprintf(stderr, "CSR_TIMEHW unsupported on RV64I\n");
        exit(1);
        break;
    case NEW_CSR_CYCLEW:
    case NEW_CSR_INSTRETW:
        cpu_riscv_store_instretw(env, val_to_write);
        break;
    case NEW_CSR_CYCLEHW:
    case NEW_CSR_INSTRETHW:
        fprintf(stderr, "CSR_CYCLEHW/INSTRETHW unsupported on RV64I\n");
        exit(1);
        break;
    case NEW_CSR_MSTATUS: {
        target_ulong mstatus = env->csr[NEW_CSR_MSTATUS];
        #ifdef RISCV_DEBUG_PRINT
        target_ulong debug_mstatus = mstatus;
        #endif
        if ((val_to_write ^ mstatus) &
                (MSTATUS_VM | MSTATUS_PRV | MSTATUS_PRV1 | MSTATUS_MPRV)) {
            #ifdef RISCV_DEBUG_PRINT
            fprintf(stderr, "flushing TLB\n");
            #endif
            helper_tlb_flush(env);
        }

        // no extension support
        target_ulong mask = MSTATUS_IE | MSTATUS_IE1 | MSTATUS_IE2
            | MSTATUS_MPRV | MSTATUS_FS;

        if (validate_vm(get_field(val_to_write, MSTATUS_VM))) {
            mask |= MSTATUS_VM;
        }
        if (validate_priv(get_field(val_to_write, MSTATUS_PRV))) {
            mask |= MSTATUS_PRV;
        }
        if (validate_priv(get_field(val_to_write, MSTATUS_PRV1))) {
            mask |= MSTATUS_PRV1;
        }
        if (validate_priv(get_field(val_to_write, MSTATUS_PRV2))) {
            mask |= MSTATUS_PRV2;
        }

        mstatus = (mstatus & ~mask) | (val_to_write & mask);

        int dirty = (mstatus & MSTATUS_FS) == MSTATUS_FS;
        dirty |= (mstatus & MSTATUS_XS) == MSTATUS_XS;
        mstatus = set_field(mstatus, MSTATUS64_SD, dirty);
        env->csr[NEW_CSR_MSTATUS] = mstatus;
        break;
    }
    case NEW_CSR_MIP: {
        target_ulong mask = MIP_SSIP | MIP_MSIP | MIP_STIP;
        env->csr[NEW_CSR_MIP] = (env->csr[NEW_CSR_MIP] & ~mask) |
            (val_to_write & mask);
        CPUState *cs = CPU(riscv_env_get_cpu(env));
        if (env->csr[NEW_CSR_MIP] & MIP_SSIP) {
            stw_phys(cs->as, 0xFFFFFFFFF0000020, 0x1);
        } else {
            stw_phys(cs->as, 0xFFFFFFFFF0000020, 0x0);
        }
        if (env->csr[NEW_CSR_MIP] & MIP_STIP) {
            stw_phys(cs->as, 0xFFFFFFFFF0000040, 0x1);
        } else {
            stw_phys(cs->as, 0xFFFFFFFFF0000040, 0x0);
        }
        if (env->csr[NEW_CSR_MIP] & MIP_MSIP) {
            stw_phys(cs->as, 0xFFFFFFFFF0000060, 0x1);
        } else {
            stw_phys(cs->as, 0xFFFFFFFFF0000060, 0x0);
        }
        break;
    }
    case NEW_CSR_MIPI: {
        CPUState *cs = CPU(riscv_env_get_cpu(env));
        env->csr[NEW_CSR_MIP] = set_field(env->csr[NEW_CSR_MIP], MIP_MSIP, val_to_write & 1);
        if (env->csr[NEW_CSR_MIP] & MIP_MSIP) {
            stw_phys(cs->as, 0xFFFFFFFFF0000060, 0x1);
        } else {
            stw_phys(cs->as, 0xFFFFFFFFF0000060, 0x0);
        }
        break;
    }
    case NEW_CSR_MIE: {
        target_ulong mask = MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP;
        env->csr[NEW_CSR_MIE] = (env->csr[NEW_CSR_MIE] & ~mask) |
            (val_to_write & mask);
        break;
    }
    case NEW_CSR_SSTATUS: {
        target_ulong ms = env->csr[NEW_CSR_MSTATUS];
        ms = set_field(ms, MSTATUS_IE, get_field(val_to_write, SSTATUS_IE));
        ms = set_field(ms, MSTATUS_IE1, get_field(val_to_write, SSTATUS_PIE));
        ms = set_field(ms, MSTATUS_PRV1, get_field(val_to_write, SSTATUS_PS));
        ms = set_field(ms, MSTATUS_FS, get_field(val_to_write, SSTATUS_FS));
        ms = set_field(ms, MSTATUS_XS, get_field(val_to_write, SSTATUS_XS));
        ms = set_field(ms, MSTATUS_MPRV, get_field(val_to_write, SSTATUS_MPRV));
        csr_write_helper(env, ms, NEW_CSR_MSTATUS);
        break;
    }
    case NEW_CSR_SIP: {
        target_ulong mask = MIP_SSIP;
        env->csr[NEW_CSR_MIP] = (env->csr[NEW_CSR_MIP] & ~mask) |
            (val_to_write & mask);
        CPUState *cs = CPU(riscv_env_get_cpu(env));
        if (env->csr[NEW_CSR_MIP] & MIP_SSIP) {
            stw_phys(cs->as, 0xFFFFFFFFF0000020, 0x1);
        } else {
            stw_phys(cs->as, 0xFFFFFFFFF0000020, 0x0);
        }
        break;
    }
    case NEW_CSR_SIE: {
        target_ulong mask = MIP_SSIP | MIP_STIP | MIP_SXIP;
        env->csr[NEW_CSR_MIE] = (env->csr[NEW_CSR_MIE] & ~mask) |
            (val_to_write & mask);
        break;
    }
    case NEW_CSR_SEPC:
        env->csr[NEW_CSR_SEPC] = val_to_write;
        break;
    case NEW_CSR_STVEC:
        env->csr[NEW_CSR_STVEC] = val_to_write >> 2 << 2;
        break;
    case NEW_CSR_SPTBR:
        env->csr[NEW_CSR_SPTBR] = val_to_write & -(1L << PGSHIFT);
        break;
    case NEW_CSR_SSCRATCH:
        env->csr[NEW_CSR_SSCRATCH] = val_to_write;
        break;
    case NEW_CSR_MEPC:
        env->csr[NEW_CSR_MEPC] = val_to_write;
        break;
    case NEW_CSR_MSCRATCH:
        env->csr[NEW_CSR_MSCRATCH] = val_to_write;
        break;
    case NEW_CSR_MCAUSE:
        env->csr[NEW_CSR_MCAUSE] = val_to_write;
        break;
    case NEW_CSR_MBADADDR:
        env->csr[NEW_CSR_MBADADDR] = val_to_write;
        break;
    case NEW_CSR_MTIMECMP:
        // NOTE: clearing bit in MIP handled in cpu_riscv_store_compare
        cpu_riscv_store_compare(env, val_to_write);
        break;
    case NEW_CSR_MTOHOST:
        fprintf(stderr, "Write to mtohost should not be handled here\n");
        exit(1);
        break;
    case NEW_CSR_MFROMHOST:
        fprintf(stderr, "Write to mfromhost should not be handled here\n");
        exit(1);
        break;
    }
}