op_helper.c

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

C
2,373
字号
        default:        case 4:            ret = ldl_user(addr & ~3);            break;        case 8:            ret = ldq_user(addr & ~7);            break;        }        break;    case 0xb: /* Supervisor data access */        switch(size) {        case 1:            ret = ldub_kernel(addr);            break;        case 2:            ret = lduw_kernel(addr & ~1);            break;        default:        case 4:            ret = ldl_kernel(addr & ~3);            break;        case 8:            ret = ldq_kernel(addr & ~7);            break;        }        break;    case 0xc: /* I-cache tag */    case 0xd: /* I-cache data */    case 0xe: /* D-cache tag */    case 0xf: /* D-cache data */        break;    case 0x20: /* MMU passthrough */        switch(size) {        case 1:            ret = ldub_phys(addr);            break;        case 2:            ret = lduw_phys(addr & ~1);            break;        default:        case 4:            ret = ldl_phys(addr & ~3);            break;        case 8:            ret = ldq_phys(addr & ~7);            break;        }        break;    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */        switch(size) {        case 1:            ret = ldub_phys((target_phys_addr_t)addr                            | ((target_phys_addr_t)(asi & 0xf) << 32));            break;        case 2:            ret = lduw_phys((target_phys_addr_t)(addr & ~1)                            | ((target_phys_addr_t)(asi & 0xf) << 32));            break;        default:        case 4:            ret = ldl_phys((target_phys_addr_t)(addr & ~3)                           | ((target_phys_addr_t)(asi & 0xf) << 32));            break;        case 8:            ret = ldq_phys((target_phys_addr_t)(addr & ~7)                           | ((target_phys_addr_t)(asi & 0xf) << 32));            break;        }        break;    case 0x30: // Turbosparc secondary cache diagnostic    case 0x31: // Turbosparc RAM snoop    case 0x32: // Turbosparc page table descriptor diagnostic    case 0x39: /* data cache diagnostic register */        ret = 0;        break;    case 8: /* User code access, XXX */    default:        do_unassigned_access(addr, 0, 0, asi);        ret = 0;        break;    }    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, uint64_t val, int asi, int size){    helper_check_align(addr, size - 1);    switch(asi) {    case 2: /* SuperSparc MXCC registers */        switch (addr) {        case 0x01c00000: /* MXCC stream data register 0 */            if (size == 8)                env->mxccdata[0] = val;            else                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,                             size);            break;        case 0x01c00008: /* MXCC stream data register 1 */            if (size == 8)                env->mxccdata[1] = val;            else                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,                             size);            break;        case 0x01c00010: /* MXCC stream data register 2 */            if (size == 8)                env->mxccdata[2] = val;            else                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,                             size);            break;        case 0x01c00018: /* MXCC stream data register 3 */            if (size == 8)                env->mxccdata[3] = val;            else                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,                             size);            break;        case 0x01c00100: /* MXCC stream source */            if (size == 8)                env->mxccregs[0] = val;            else                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,                             size);            env->mxccdata[0] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +                                        0);            env->mxccdata[1] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +                                        8);            env->mxccdata[2] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +                                        16);            env->mxccdata[3] = ldq_phys((env->mxccregs[0] & 0xffffffffULL) +                                        24);            break;        case 0x01c00200: /* MXCC stream destination */            if (size == 8)                env->mxccregs[1] = val;            else                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,                             size);            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  0,                     env->mxccdata[0]);            stq_phys((env->mxccregs[1] & 0xffffffffULL) +  8,                     env->mxccdata[1]);            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 16,                     env->mxccdata[2]);            stq_phys((env->mxccregs[1] & 0xffffffffULL) + 24,                     env->mxccdata[3]);            break;        case 0x01c00a00: /* MXCC control register */            if (size == 8)                env->mxccregs[3] = val;            else                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,                             size);            break;        case 0x01c00a04: /* MXCC control register */            if (size == 4)                env->mxccregs[3] = (env->mxccregs[0xa] & 0xffffffff00000000ULL)                    | val;            else                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,                             size);            break;        case 0x01c00e00: /* MXCC error register  */            // writing a 1 bit clears the error            if (size == 8)                env->mxccregs[6] &= ~val;            else                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,                             size);            break;        case 0x01c00f00: /* MBus port address register */            if (size == 8)                env->mxccregs[7] = val;            else                DPRINTF_MXCC("%08x: unimplemented access size: %d\n", addr,                             size);            break;        default:            DPRINTF_MXCC("%08x: unimplemented address, size: %d\n", addr,                         size);            break;        }        DPRINTF_MXCC("asi = %d, size = %d, addr = %08x, val = %08x\n", asi,                     size, addr, val);#ifdef DEBUG_MXCC        dump_mxcc(env);#endif        break;    case 3: /* MMU flush */        {            int mmulev;            mmulev = (addr >> 8) & 15;            DPRINTF_MMU("mmu flush level %d\n", mmulev);            switch (mmulev) {            case 0: // flush page                tlb_flush_page(env, addr & 0xfffff000);                break;            case 1: // flush segment (256k)            case 2: // flush region (16M)            case 3: // flush context (4G)            case 4: // flush entire                tlb_flush(env, 1);                break;            default:                break;            }#ifdef DEBUG_MMU            dump_mmu(env);#endif        }        break;    case 4: /* write MMU regs */        {            int reg = (addr >> 8) & 0x1f;            uint32_t oldreg;            oldreg = env->mmuregs[reg];            switch(reg) {            case 0: // Control Register                env->mmuregs[reg] = (env->mmuregs[reg] & 0xff000000) |                                    (val & 0x00ffffff);                // Mappings generated during no-fault mode or MMU                // disabled mode are invalid in normal mode                if ((oldreg & (MMU_E | MMU_NF | env->mmu_bm)) !=                    (env->mmuregs[reg] & (MMU_E | MMU_NF | env->mmu_bm)))                    tlb_flush(env, 1);                break;            case 1: // Context Table Pointer Register                env->mmuregs[reg] = val & env->mmu_ctpr_mask;                break;            case 2: // Context Register                env->mmuregs[reg] = val & env->mmu_cxr_mask;                if (oldreg != env->mmuregs[reg]) {                    /* we flush when the MMU context changes because                       QEMU has no MMU context support */                    tlb_flush(env, 1);                }                break;            case 3: // Synchronous Fault Status Register with Clear            case 4: // Synchronous Fault Address Register                break;            case 0x10: // TLB Replacement Control Register                env->mmuregs[reg] = val & env->mmu_trcr_mask;                break;            case 0x13: // Synchronous Fault Status Register with Read and Clear                env->mmuregs[3] = val & env->mmu_sfsr_mask;                break;            case 0x14: // Synchronous Fault Address Register                env->mmuregs[4] = val;                break;            default:                env->mmuregs[reg] = val;                break;            }            if (oldreg != env->mmuregs[reg]) {                DPRINTF_MMU("mmu change reg[%d]: 0x%08x -> 0x%08x\n",                            reg, oldreg, env->mmuregs[reg]);            }#ifdef DEBUG_MMU            dump_mmu(env);#endif        }        break;    case 5: // Turbosparc ITLB Diagnostic    case 6: // Turbosparc DTLB Diagnostic    case 7: // Turbosparc IOTLB Diagnostic        break;    case 0xa: /* User data access */        switch(size) {        case 1:            stb_user(addr, val);            break;        case 2:            stw_user(addr & ~1, val);            break;        default:        case 4:            stl_user(addr & ~3, val);            break;        case 8:            stq_user(addr & ~7, val);            break;        }        break;    case 0xb: /* Supervisor data access */        switch(size) {        case 1:            stb_kernel(addr, val);            break;        case 2:            stw_kernel(addr & ~1, val);            break;        default:        case 4:            stl_kernel(addr & ~3, val);            break;        case 8:            stq_kernel(addr & ~7, val);            break;        }        break;    case 0xc: /* I-cache tag */    case 0xd: /* I-cache data */    case 0xe: /* D-cache tag */    case 0xf: /* D-cache data */    case 0x10: /* I/D-cache flush page */    case 0x11: /* I/D-cache flush segment */    case 0x12: /* I/D-cache flush region */    case 0x13: /* I/D-cache flush context */    case 0x14: /* I/D-cache flush user */        break;    case 0x17: /* Block copy, sta access */        {            // val = src            // addr = dst            // copy 32 bytes            unsigned int i;            uint32_t src = val & ~3, dst = addr & ~3, temp;            for (i = 0; i < 32; i += 4, src += 4, dst += 4) {                temp = ldl_kernel(src);                stl_kernel(dst, temp);            }        }        break;    case 0x1f: /* Block fill, stda access */        {            // addr = dst            // fill 32 bytes with val            unsigned int i;            uint32_t dst = addr & 7;            for (i = 0; i < 32; i += 8, dst += 8)                stq_kernel(dst, val);        }        break;    case 0x20: /* MMU passthrough */        {            switch(size) {            case 1:                stb_phys(addr, val);                break;            case 2:                stw_phys(addr & ~1, val);                break;            case 4:            default:                stl_phys(addr & ~3, val);                break;            case 8:                stq_phys(addr & ~7, val);                break;            }        }        break;    case 0x21 ... 0x2f: /* MMU passthrough, 0x100000000 to 0xfffffffff */        {            switch(size) {            case 1:                stb_phys((target_phys_addr_t)addr                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);                break;            case 2:                stw_phys((target_phys_addr_t)(addr & ~1)                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);                break;            case 4:            default:                stl_phys((target_phys_addr_t)(addr & ~3)                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);                break;            case 8:                stq_phys((target_phys_addr_t)(addr & ~7)                         | ((target_phys_addr_t)(asi & 0xf) << 32), val);                break;            }        }        break;    case 0x30: // store buffer tags or Turbosparc secondary cache diagnostic    case 0x31: // store buffer data, Ross RT620 I-cache flush or               // Turbosparc snoop RAM    case 0x32: // store buffer control or Turbosparc page table               // descriptor diagnostic    case 0x36: /* I-cache flash clear */    case 0x37: /* D-cache flash clear */    case 0x38: /* breakpoint diagnostics */    case 0x4c: /* breakpoint action */        break;    case 8: /* User code access, XXX */    case 9: /* Supervisor code access, XXX */    default:        do_unassigned_access(addr, 1, 0, asi);        break;    }#ifdef DEBUG_ASI    dump_asi("write", addr, asi, size, val);#endif}#endif /* CONFIG_USER_ONLY */#else /* TARGET_SPARC64 */#ifdef CONFIG_USER_ONLYuint64_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)        raise_exception(TT_PRIV_ACT);    helper_check_align(addr, size - 1);    ABI32_MASK(addr);    switch (asi) {    case 0x80: // Primary    case 0x82: // Primary no-fault    case 0x88: // Primary LE    case 0x8a: // Primary no-fault LE        {            switch(size) {            case 1:                ret = ldub_raw(addr);                break;            case 2:                ret = lduw_raw(addr & ~1);                break;            case 4:                ret = ldl_raw(addr & ~3);                break;            default:            case 8:                ret = ldq_raw(addr & ~7);                break;            }        }        break;    case 0x81: // Secondary    case 0x83: // Secondary no-fault    case 0x89: // Secondary LE    case 0x8b: // Secondary no-fault LE        // XXX        break;    default:        break;    }    /* Convert from little endian */    switch (asi) {    case 0x88: // Primary LE    case 0x89: // Secondary LE    case 0x8a: // Primary no-fault LE    case 0x8b: // Secondary no-fault LE

⌨️ 快捷键说明

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