op_helper.c

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

C
2,373
字号
        switch(size) {        case 2:            ret = bswap16(ret);            break;        case 4:            ret = bswap32(ret);            break;        case 8:            ret = bswap64(ret);            break;        default:            break;        }    default:        break;    }    /* Convert to signed number */    if (sign) {        switch(size) {        case 1:            ret = (int8_t) ret;            break;        case 2:            ret = (int16_t) ret;            break;        case 4:            ret = (int32_t) ret;            break;        default:            break;        }    }#ifdef DEBUG_ASI    dump_asi("read ", last_addr, asi, size, ret);#endif    return ret;}void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size){#ifdef DEBUG_ASI    dump_asi("write", addr, asi, size, val);#endif    if (asi < 0x80)        raise_exception(TT_PRIV_ACT);    helper_check_align(addr, size - 1);    ABI32_MASK(addr);    /* Convert to little endian */    switch (asi) {    case 0x88: // Primary LE    case 0x89: // Secondary LE        switch(size) {        case 2:            addr = bswap16(addr);            break;        case 4:            addr = bswap32(addr);            break;        case 8:            addr = bswap64(addr);            break;        default:            break;        }    default:        break;    }    switch(asi) {    case 0x80: // Primary    case 0x88: // Primary LE        {            switch(size) {            case 1:                stb_raw(addr, val);                break;            case 2:                stw_raw(addr & ~1, val);                break;            case 4:                stl_raw(addr & ~3, val);                break;            case 8:            default:                stq_raw(addr & ~7, val);                break;            }        }        break;    case 0x81: // Secondary    case 0x89: // Secondary LE        // XXX        return;    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;    }}#else /* CONFIG_USER_ONLY */uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign){    uint64_t ret = 0;#if defined(DEBUG_ASI)    target_ulong last_addr = addr;#endif    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))        raise_exception(TT_PRIV_ACT);    helper_check_align(addr, size - 1);    switch (asi) {    case 0x10: // As if user primary    case 0x18: // As if user primary LE    case 0x80: // Primary    case 0x82: // Primary no-fault    case 0x88: // Primary LE    case 0x8a: // Primary no-fault LE        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {            if (env->hpstate & HS_PRIV) {                switch(size) {                case 1:                    ret = ldub_hypv(addr);                    break;                case 2:                    ret = lduw_hypv(addr & ~1);                    break;                case 4:                    ret = ldl_hypv(addr & ~3);                    break;                default:                case 8:                    ret = ldq_hypv(addr & ~7);                    break;                }            } else {                switch(size) {                case 1:                    ret = ldub_kernel(addr);                    break;                case 2:                    ret = lduw_kernel(addr & ~1);                    break;                case 4:                    ret = ldl_kernel(addr & ~3);                    break;                default:                case 8:                    ret = ldq_kernel(addr & ~7);                    break;                }            }        } else {            switch(size) {            case 1:                ret = ldub_user(addr);                break;            case 2:                ret = lduw_user(addr & ~1);                break;            case 4:                ret = ldl_user(addr & ~3);                break;            default:            case 8:                ret = ldq_user(addr & ~7);                break;            }        }        break;    case 0x14: // Bypass    case 0x15: // Bypass, non-cacheable    case 0x1c: // Bypass LE    case 0x1d: // Bypass, non-cacheable LE        {            switch(size) {            case 1:                ret = ldub_phys(addr);                break;            case 2:                ret = lduw_phys(addr & ~1);                break;            case 4:                ret = ldl_phys(addr & ~3);                break;            default:            case 8:                ret = ldq_phys(addr & ~7);                break;            }            break;        }    case 0x04: // Nucleus    case 0x0c: // Nucleus Little Endian (LE)    case 0x11: // As if user secondary    case 0x19: // As if user secondary LE    case 0x24: // Nucleus quad LDD 128 bit atomic    case 0x2c: // Nucleus quad LDD 128 bit atomic    case 0x4a: // UPA config    case 0x81: // Secondary    case 0x83: // Secondary no-fault    case 0x89: // Secondary LE    case 0x8b: // Secondary no-fault LE        // XXX        break;    case 0x45: // LSU        ret = env->lsu;        break;    case 0x50: // I-MMU regs        {            int reg = (addr >> 3) & 0xf;            ret = env->immuregs[reg];            break;        }    case 0x51: // I-MMU 8k TSB pointer    case 0x52: // I-MMU 64k TSB pointer    case 0x55: // I-MMU data access        // XXX        break;    case 0x56: // I-MMU tag read        {            unsigned int i;            for (i = 0; i < 64; i++) {                // Valid, ctx match, vaddr match                if ((env->itlb_tte[i] & 0x8000000000000000ULL) != 0 &&                    env->itlb_tag[i] == addr) {                    ret = env->itlb_tag[i];                    break;                }            }            break;        }    case 0x58: // D-MMU regs        {            int reg = (addr >> 3) & 0xf;            ret = env->dmmuregs[reg];            break;        }    case 0x5e: // D-MMU tag read        {            unsigned int i;            for (i = 0; i < 64; i++) {                // Valid, ctx match, vaddr match                if ((env->dtlb_tte[i] & 0x8000000000000000ULL) != 0 &&                    env->dtlb_tag[i] == addr) {                    ret = env->dtlb_tag[i];                    break;                }            }            break;        }    case 0x59: // D-MMU 8k TSB pointer    case 0x5a: // D-MMU 64k TSB pointer    case 0x5b: // D-MMU data pointer    case 0x5d: // D-MMU data access    case 0x48: // Interrupt dispatch, RO    case 0x49: // Interrupt data receive    case 0x7f: // Incoming interrupt vector, RO        // XXX        break;    case 0x54: // I-MMU data in, WO    case 0x57: // I-MMU demap, WO    case 0x5c: // D-MMU data in, WO    case 0x5f: // D-MMU demap, WO    case 0x77: // Interrupt vector, WO    default:        do_unassigned_access(addr, 0, 0, 1);        ret = 0;        break;    }    /* Convert from little endian */    switch (asi) {    case 0x0c: // Nucleus Little Endian (LE)    case 0x18: // As if user primary LE    case 0x19: // As if user secondary LE    case 0x1c: // Bypass LE    case 0x1d: // Bypass, non-cacheable LE    case 0x88: // Primary LE    case 0x89: // Secondary LE    case 0x8a: // Primary no-fault LE    case 0x8b: // Secondary no-fault LE        switch(size) {        case 2:            ret = bswap16(ret);            break;        case 4:            ret = bswap32(ret);            break;        case 8:            ret = bswap64(ret);            break;        default:            break;        }    default:        break;    }    /* Convert to signed number */    if (sign) {        switch(size) {        case 1:            ret = (int8_t) ret;            break;        case 2:            ret = (int16_t) ret;            break;        case 4:            ret = (int32_t) ret;            break;        default:            break;        }    }#ifdef DEBUG_ASI    dump_asi("read ", last_addr, asi, size, ret);#endif    return ret;}void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size){#ifdef DEBUG_ASI    dump_asi("write", addr, asi, size, val);#endif    if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)        || (asi >= 0x30 && asi < 0x80 && !(env->hpstate & HS_PRIV)))        raise_exception(TT_PRIV_ACT);    helper_check_align(addr, size - 1);    /* Convert to little endian */    switch (asi) {    case 0x0c: // Nucleus Little Endian (LE)    case 0x18: // As if user primary LE    case 0x19: // As if user secondary LE    case 0x1c: // Bypass LE    case 0x1d: // Bypass, non-cacheable LE    case 0x88: // Primary LE    case 0x89: // Secondary LE        switch(size) {        case 2:            addr = bswap16(addr);            break;        case 4:            addr = bswap32(addr);            break;        case 8:            addr = bswap64(addr);            break;        default:            break;        }    default:        break;    }    switch(asi) {    case 0x10: // As if user primary    case 0x18: // As if user primary LE    case 0x80: // Primary    case 0x88: // Primary LE        if ((asi & 0x80) && (env->pstate & PS_PRIV)) {            if (env->hpstate & HS_PRIV) {                switch(size) {                case 1:                    stb_hypv(addr, val);                    break;                case 2:                    stw_hypv(addr & ~1, val);                    break;                case 4:                    stl_hypv(addr & ~3, val);                    break;                case 8:                default:                    stq_hypv(addr & ~7, val);                    break;                }            } else {                switch(size) {                case 1:                    stb_kernel(addr, val);                    break;                case 2:                    stw_kernel(addr & ~1, val);                    break;                case 4:                    stl_kernel(addr & ~3, val);                    break;                case 8:                default:                    stq_kernel(addr & ~7, val);                    break;                }            }        } else {            switch(size) {            case 1:                stb_user(addr, val);                break;            case 2:                stw_user(addr & ~1, val);                break;            case 4:                stl_user(addr & ~3, val);                break;            case 8:            default:                stq_user(addr & ~7, val);                break;            }        }        break;    case 0x14: // Bypass    case 0x15: // Bypass, non-cacheable    case 0x1c: // Bypass LE    case 0x1d: // Bypass, non-cacheable LE        {            switch(size) {            case 1:                stb_phys(addr, val);                break;            case 2:                stw_phys(addr & ~1, val);                break;            case 4:                stl_phys(addr & ~3, val);                break;            case 8:            default:                stq_phys(addr & ~7, val);                break;            }        }        return;    case 0x04: // Nucleus    case 0x0c: // Nucleus Little Endian (LE)    case 0x11: // As if user secondary    case 0x19: // As if user secondary LE    case 0x24: // Nucleus quad LDD 128 bit atomic    case 0x2c: // Nucleus quad LDD 128 bit atomic    case 0x4a: // UPA config    case 0x81: // Secondary    case 0x89: // Secondary LE        // XXX        return;    case 0x45: // LSU        {            uint64_t oldreg;            oldreg = env->lsu;            env->lsu = val & (DMMU_E | IMMU_E);            // Mappings generated during D/I MMU disabled mode are            // invalid in normal mode            if (oldreg != env->lsu) {                DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",                            oldreg, env->lsu);#ifdef DEBUG_MMU                dump_mmu(env);#endif

⌨️ 快捷键说明

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