op_helper.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 2,373 行 · 第 1/5 页

C
2,373
字号
                tlb_flush(env, 1);            }            return;        }    case 0x50: // I-MMU regs        {            int reg = (addr >> 3) & 0xf;            uint64_t oldreg;            oldreg = env->immuregs[reg];            switch(reg) {            case 0: // RO            case 4:                return;            case 1: // Not in I-MMU            case 2:            case 7:            case 8:                return;            case 3: // SFSR                if ((val & 1) == 0)                    val = 0; // Clear SFSR                break;            case 5: // TSB access            case 6: // Tag access            default:                break;            }            env->immuregs[reg] = val;            if (oldreg != env->immuregs[reg]) {                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"                            PRIx64 "\n", reg, oldreg, env->immuregs[reg]);            }#ifdef DEBUG_MMU            dump_mmu(env);#endif            return;        }    case 0x54: // I-MMU data in        {            unsigned int i;            // Try finding an invalid entry            for (i = 0; i < 64; i++) {                if ((env->itlb_tte[i] & 0x8000000000000000ULL) == 0) {                    env->itlb_tag[i] = env->immuregs[6];                    env->itlb_tte[i] = val;                    return;                }            }            // Try finding an unlocked entry            for (i = 0; i < 64; i++) {                if ((env->itlb_tte[i] & 0x40) == 0) {                    env->itlb_tag[i] = env->immuregs[6];                    env->itlb_tte[i] = val;                    return;                }            }            // error state?            return;        }    case 0x55: // I-MMU data access        {            unsigned int i = (addr >> 3) & 0x3f;            env->itlb_tag[i] = env->immuregs[6];            env->itlb_tte[i] = val;            return;        }    case 0x57: // I-MMU demap        // XXX        return;    case 0x58: // D-MMU regs        {            int reg = (addr >> 3) & 0xf;            uint64_t oldreg;            oldreg = env->dmmuregs[reg];            switch(reg) {            case 0: // RO            case 4:                return;            case 3: // SFSR                if ((val & 1) == 0) {                    val = 0; // Clear SFSR, Fault address                    env->dmmuregs[4] = 0;                }                env->dmmuregs[reg] = val;                break;            case 1: // Primary context            case 2: // Secondary context            case 5: // TSB access            case 6: // Tag access            case 7: // Virtual Watchpoint            case 8: // Physical Watchpoint            default:                break;            }            env->dmmuregs[reg] = val;            if (oldreg != env->dmmuregs[reg]) {                DPRINTF_MMU("mmu change reg[%d]: 0x%08" PRIx64 " -> 0x%08"                            PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);            }#ifdef DEBUG_MMU            dump_mmu(env);#endif            return;        }    case 0x5c: // D-MMU data in        {            unsigned int i;            // Try finding an invalid entry            for (i = 0; i < 64; i++) {                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) == 0) {                    env->dtlb_tag[i] = env->dmmuregs[6];                    env->dtlb_tte[i] = val;                    return;                }            }            // Try finding an unlocked entry            for (i = 0; i < 64; i++) {                if ((env->dtlb_tte[i] & 0x40) == 0) {                    env->dtlb_tag[i] = env->dmmuregs[6];                    env->dtlb_tte[i] = val;                    return;                }            }            // error state?            return;        }    case 0x5d: // D-MMU data access        {            unsigned int i = (addr >> 3) & 0x3f;            env->dtlb_tag[i] = env->dmmuregs[6];            env->dtlb_tte[i] = val;            return;        }    case 0x5f: // D-MMU demap    case 0x49: // Interrupt data receive        // XXX        return;    case 0x51: // I-MMU 8k TSB pointer, RO    case 0x52: // I-MMU 64k TSB pointer, RO    case 0x56: // I-MMU tag read, RO    case 0x59: // D-MMU 8k TSB pointer, RO    case 0x5a: // D-MMU 64k TSB pointer, RO    case 0x5b: // D-MMU data pointer, RO    case 0x5e: // D-MMU tag read, RO    case 0x48: // Interrupt dispatch, RO    case 0x7f: // Incoming interrupt vector, RO    case 0x82: // Primary no-fault, RO    case 0x83: // Secondary no-fault, RO    case 0x8a: // Primary no-fault LE, RO    case 0x8b: // Secondary no-fault LE, RO    default:        do_unassigned_access(addr, 1, 0, 1);        return;    }}#endif /* CONFIG_USER_ONLY */void helper_ldf_asi(target_ulong addr, int asi, int size, int rd){    unsigned int i;    target_ulong val;    helper_check_align(addr, 3);    switch (asi) {    case 0xf0: // Block load primary    case 0xf1: // Block load secondary    case 0xf8: // Block load primary LE    case 0xf9: // Block load secondary LE        if (rd & 7) {            raise_exception(TT_ILL_INSN);            return;        }        helper_check_align(addr, 0x3f);        for (i = 0; i < 16; i++) {            *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x8f, 4,                                                         0);            addr += 4;        }        return;    default:        break;    }    val = helper_ld_asi(addr, asi, size, 0);    switch(size) {    default:    case 4:        *((uint32_t *)&FT0) = val;        break;    case 8:        *((int64_t *)&DT0) = val;        break;    case 16:        // XXX        break;    }}void helper_stf_asi(target_ulong addr, int asi, int size, int rd){    unsigned int i;    target_ulong val = 0;    helper_check_align(addr, 3);    switch (asi) {    case 0xf0: // Block store primary    case 0xf1: // Block store secondary    case 0xf8: // Block store primary LE    case 0xf9: // Block store secondary LE        if (rd & 7) {            raise_exception(TT_ILL_INSN);            return;        }        helper_check_align(addr, 0x3f);        for (i = 0; i < 16; i++) {            val = *(uint32_t *)&env->fpr[rd++];            helper_st_asi(addr, val, asi & 0x8f, 4);            addr += 4;        }        return;    default:        break;    }    switch(size) {    default:    case 4:        val = *((uint32_t *)&FT0);        break;    case 8:        val = *((int64_t *)&DT0);        break;    case 16:        // XXX        break;    }    helper_st_asi(addr, val, asi, size);}target_ulong helper_cas_asi(target_ulong addr, target_ulong val1,                            target_ulong val2, uint32_t asi){    target_ulong ret;    val1 &= 0xffffffffUL;    ret = helper_ld_asi(addr, asi, 4, 0);    ret &= 0xffffffffUL;    if (val1 == ret)        helper_st_asi(addr, val2 & 0xffffffffUL, asi, 4);    return ret;}target_ulong helper_casx_asi(target_ulong addr, target_ulong val1,                             target_ulong val2, uint32_t asi){    target_ulong ret;    ret = helper_ld_asi(addr, asi, 8, 0);    if (val1 == ret)        helper_st_asi(addr, val2, asi, 8);    return ret;}#endif /* TARGET_SPARC64 */#ifndef TARGET_SPARC64void helper_rett(void){    unsigned int cwp;    if (env->psret == 1)        raise_exception(TT_ILL_INSN);    env->psret = 1;    cwp = (env->cwp + 1) & (NWINDOWS - 1);    if (env->wim & (1 << cwp)) {        raise_exception(TT_WIN_UNF);    }    set_cwp(cwp);    env->psrs = env->psrps;}#endiftarget_ulong helper_udiv(target_ulong a, target_ulong b){    uint64_t x0;    uint32_t x1;    x0 = a | ((uint64_t) (env->y) << 32);    x1 = b;    if (x1 == 0) {        raise_exception(TT_DIV_ZERO);    }    x0 = x0 / x1;    if (x0 > 0xffffffff) {        env->cc_src2 = 1;        return 0xffffffff;    } else {        env->cc_src2 = 0;        return x0;    }}target_ulong helper_sdiv(target_ulong a, target_ulong b){    int64_t x0;    int32_t x1;    x0 = a | ((int64_t) (env->y) << 32);    x1 = b;    if (x1 == 0) {        raise_exception(TT_DIV_ZERO);    }    x0 = x0 / x1;    if ((int32_t) x0 != x0) {        env->cc_src2 = 1;        return x0 < 0? 0x80000000: 0x7fffffff;    } else {        env->cc_src2 = 0;        return x0;    }}uint64_t helper_pack64(target_ulong high, target_ulong low){    return ((uint64_t)high << 32) | (uint64_t)(low & 0xffffffff);}void helper_stdf(target_ulong addr, int mem_idx){    helper_check_align(addr, 7);#if !defined(CONFIG_USER_ONLY)    switch (mem_idx) {    case 0:        stfq_user(addr, DT0);        break;    case 1:        stfq_kernel(addr, DT0);        break;#ifdef TARGET_SPARC64    case 2:        stfq_hypv(addr, DT0);        break;#endif    default:        break;    }#else    ABI32_MASK(addr);    stfq_raw(addr, DT0);#endif}void helper_lddf(target_ulong addr, int mem_idx){    helper_check_align(addr, 7);#if !defined(CONFIG_USER_ONLY)    switch (mem_idx) {    case 0:        DT0 = ldfq_user(addr);        break;    case 1:        DT0 = ldfq_kernel(addr);        break;#ifdef TARGET_SPARC64    case 2:        DT0 = ldfq_hypv(addr);        break;#endif    default:        break;    }#else    ABI32_MASK(addr);    DT0 = ldfq_raw(addr);#endif}void helper_ldqf(target_ulong addr, int mem_idx){    // XXX add 128 bit load    CPU_QuadU u;    helper_check_align(addr, 7);#if !defined(CONFIG_USER_ONLY)    switch (mem_idx) {    case 0:        u.ll.upper = ldq_user(addr);        u.ll.lower = ldq_user(addr + 8);        QT0 = u.q;        break;    case 1:        u.ll.upper = ldq_kernel(addr);        u.ll.lower = ldq_kernel(addr + 8);        QT0 = u.q;        break;#ifdef TARGET_SPARC64    case 2:        u.ll.upper = ldq_hypv(addr);        u.ll.lower = ldq_hypv(addr + 8);        QT0 = u.q;        break;#endif    default:        break;    }#else    ABI32_MASK(addr);    u.ll.upper = ldq_raw(addr);    u.ll.lower = ldq_raw((addr + 8) & 0xffffffffULL);    QT0 = u.q;#endif}void helper_stqf(target_ulong addr, int mem_idx){    // XXX add 128 bit store    CPU_QuadU u;    helper_check_align(addr, 7);#if !defined(CONFIG_USER_ONLY)    switch (mem_idx) {    case 0:        u.q = QT0;        stq_user(addr, u.ll.upper);        stq_user(addr + 8, u.ll.lower);        break;    case 1:        u.q = QT0;        stq_kernel(addr, u.ll.upper);        stq_kernel(addr + 8, u.ll.lower);        break;#ifdef TARGET_SPARC64    case 2:        u.q = QT0;        stq_hypv(addr, u.ll.upper);        stq_hypv(addr + 8, u.ll.lower);        break;#endif    default:        break;    }#else    u.q = QT0;    ABI32_MASK(addr);    stq_raw(addr, u.ll.upper);    stq_raw((addr + 8) & 0xffffffffULL, u.ll.lower);#endif}void helper_ldfsr(void){    int rnd_mode;    PUT_FSR32(env, *((uint32_t *) &FT0));    switch (env->fsr & FSR_RD_MASK) {    case FSR_RD_NEAREST:        rnd_mode = float_round_nearest_even;        break;    default:    case FSR_RD_ZERO:        rnd_

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?