⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 op_helper.c

📁 qemu性能直逼VMware的仿真器QEMU 的模擬速度約為實機的 25%;約為 Bochs 的 60 倍。Plex86、User-Mode-Linux、VMware 和 Virtual PC 則比
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "exec.h"//#define DEBUG_PCALL//#define DEBUG_MMUvoid raise_exception(int tt){    env->exception_index = tt;    cpu_loop_exit();}   #ifdef USE_INT_TO_FLOAT_HELPERSvoid do_fitos(void){    FT0 = int32_to_float32(*((int32_t *)&FT1), &env->fp_status);}void do_fitod(void){    DT0 = int32_to_float64(*((int32_t *)&FT1), &env->fp_status);}#endifvoid do_fabss(void){    FT0 = float32_abs(FT1);}#ifdef TARGET_SPARC64void do_fabsd(void){    DT0 = float64_abs(DT1);}#endifvoid do_fsqrts(void){    FT0 = float32_sqrt(FT1, &env->fp_status);}void do_fsqrtd(void){    DT0 = float64_sqrt(DT1, &env->fp_status);}#define GEN_FCMP(name, size, reg1, reg2, FS)                            \    void glue(do_, name) (void)                                         \    {                                                                   \        env->fsr &= ~((FSR_FCC1 | FSR_FCC0) << FS);                     \        switch (glue(size, _compare) (reg1, reg2, &env->fp_status)) {   \        case float_relation_unordered:                                  \            T0 = (FSR_FCC1 | FSR_FCC0) << FS;                           \            if (env->fsr & FSR_NVM) {                                   \                env->fsr |= T0;                                         \                raise_exception(TT_FP_EXCP);                            \            } else {                                                    \                env->fsr |= FSR_NVA;                                    \            }                                                           \            break;                                                      \        case float_relation_less:                                       \            T0 = FSR_FCC0 << FS;                                        \            break;                                                      \        case float_relation_greater:                                    \            T0 = FSR_FCC1 << FS;                                        \            break;                                                      \        default:                                                        \            T0 = 0;                                                     \            break;                                                      \        }                                                               \        env->fsr |= T0;                                                 \    }GEN_FCMP(fcmps, float32, FT0, FT1, 0);GEN_FCMP(fcmpd, float64, DT0, DT1, 0);#ifdef TARGET_SPARC64GEN_FCMP(fcmps_fcc1, float32, FT0, FT1, 22);GEN_FCMP(fcmpd_fcc1, float64, DT0, DT1, 22);GEN_FCMP(fcmps_fcc2, float32, FT0, FT1, 24);GEN_FCMP(fcmpd_fcc2, float64, DT0, DT1, 24);GEN_FCMP(fcmps_fcc3, float32, FT0, FT1, 26);GEN_FCMP(fcmpd_fcc3, float64, DT0, DT1, 26);#endif#if defined(CONFIG_USER_ONLY) void helper_ld_asi(int asi, int size, int sign){}void helper_st_asi(int asi, int size, int sign){}#else#ifndef TARGET_SPARC64void helper_ld_asi(int asi, int size, int sign){    uint32_t ret = 0;    switch (asi) {    case 3: /* MMU probe */	{	    int mmulev;	    mmulev = (T0 >> 8) & 15;	    if (mmulev > 4)		ret = 0;	    else {		ret = mmu_probe(env, T0, mmulev);		//bswap32s(&ret);	    }#ifdef DEBUG_MMU	    printf("mmu_probe: 0x%08x (lev %d) -> 0x%08x\n", T0, mmulev, ret);#endif	}	break;    case 4: /* read MMU regs */	{	    int reg = (T0 >> 8) & 0xf;	    	    ret = env->mmuregs[reg];	    if (reg == 3) /* Fault status cleared on read */		env->mmuregs[reg] = 0;#ifdef DEBUG_MMU	    printf("mmu_read: reg[%d] = 0x%08x\n", reg, ret);#endif	}	break;    case 0x20 ... 0x2f: /* MMU passthrough */        switch(size) {        case 1:            ret = ldub_phys(T0);            break;        case 2:            ret = lduw_phys(T0 & ~1);            break;        default:        case 4:            ret = ldl_phys(T0 & ~3);            break;        case 8:	    ret = ldl_phys(T0 & ~3);	    T0 = ldl_phys((T0 + 4) & ~3);	    break;        }	break;    default:	ret = 0;	break;    }    T1 = ret;}void helper_st_asi(int asi, int size, int sign){    switch(asi) {    case 3: /* MMU flush */	{	    int mmulev;	    mmulev = (T0 >> 8) & 15;#ifdef DEBUG_MMU	    printf("mmu flush level %d\n", mmulev);#endif	    switch (mmulev) {	    case 0: // flush page		tlb_flush_page(env, T0 & 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	    return;	}    case 4: /* write MMU regs */	{	    int reg = (T0 >> 8) & 0xf;	    uint32_t oldreg;	    	    oldreg = env->mmuregs[reg];            switch(reg) {            case 0:		env->mmuregs[reg] &= ~(MMU_E | MMU_NF);		env->mmuregs[reg] |= T1 & (MMU_E | MMU_NF);		// Mappings generated during no-fault mode or MMU		// disabled mode are invalid in normal mode                if (oldreg != env->mmuregs[reg])                    tlb_flush(env, 1);                break;            case 2:		env->mmuregs[reg] = T1;                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:            case 4:                break;            default:		env->mmuregs[reg] = T1;                break;            }#ifdef DEBUG_MMU            if (oldreg != env->mmuregs[reg]) {                printf("mmu change reg[%d]: 0x%08x -> 0x%08x\n", reg, oldreg, env->mmuregs[reg]);            }	    dump_mmu(env);#endif	    return;	}    case 0x17: /* Block copy, sta access */	{	    // value (T1) = src	    // address (T0) = dst	    // copy 32 bytes	    uint32_t src = T1, dst = T0;	    uint8_t temp[32];	    	    tswap32s(&src);	    cpu_physical_memory_read(src, (void *) &temp, 32);	    cpu_physical_memory_write(dst, (void *) &temp, 32);	}	return;    case 0x1f: /* Block fill, stda access */	{	    // value (T1, T2)	    // address (T0) = dst	    // fill 32 bytes	    int i;	    uint32_t dst = T0;	    uint64_t val;	    	    val = (((uint64_t)T1) << 32) | T2;	    tswap64s(&val);	    for (i = 0; i < 32; i += 8, dst += 8) {		cpu_physical_memory_write(dst, (void *) &val, 8);	    }	}	return;    case 0x20 ... 0x2f: /* MMU passthrough */	{            switch(size) {            case 1:                stb_phys(T0, T1);                break;            case 2:                stw_phys(T0 & ~1, T1);                break;            case 4:            default:                stl_phys(T0 & ~3, T1);                break;            case 8:                stl_phys(T0 & ~3, T1);                stl_phys((T0 + 4) & ~3, T2);                break;            }	}	return;    default:	return;    }}#elsevoid helper_ld_asi(int asi, int size, int sign){    uint64_t ret = 0;    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)	raise_exception(TT_PRIV_ACT);    switch (asi) {    case 0x14: // Bypass    case 0x15: // Bypass, non-cacheable	{            switch(size) {            case 1:                ret = ldub_phys(T0);                break;            case 2:                ret = lduw_phys(T0 & ~1);                break;            case 4:                ret = ldl_phys(T0 & ~3);                break;            default:            case 8:                ret = ldq_phys(T0 & ~7);                break;            }	    break;	}    case 0x04: // Nucleus    case 0x0c: // Nucleus Little Endian (LE)    case 0x10: // As if user primary    case 0x11: // As if user secondary    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 0x24: // Nucleus quad LDD 128 bit atomic    case 0x2c: // Nucleus quad LDD 128 bit atomic    case 0x4a: // UPA config    case 0x82: // Primary no-fault    case 0x83: // Secondary no-fault    case 0x88: // Primary LE    case 0x89: // Secondary LE    case 0x8a: // Primary no-fault LE    case 0x8b: // Secondary no-fault LE	// XXX	break;    case 0x45: // LSU	ret = env->lsu;	break;    case 0x50: // I-MMU regs	{	    int reg = (T0 >> 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] == T0) {		    ret = env->itlb_tag[i];		    break;		}	    }	    break;	}    case 0x58: // D-MMU regs	{	    int reg = (T0 >> 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] == T0) {		    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:	ret = 0;	break;    }    T1 = ret;}void helper_st_asi(int asi, int size, int sign){    if (asi < 0x80 && (env->pstate & PS_PRIV) == 0)	raise_exception(TT_PRIV_ACT);    switch(asi) {    case 0x14: // Bypass    case 0x15: // Bypass, non-cacheable	{            switch(size) {            case 1:                stb_phys(T0, T1);                break;            case 2:                stw_phys(T0 & ~1, T1);                break;            case 4:                stl_phys(T0 & ~3, T1);                break;            case 8:            default:                stq_phys(T0 & ~7, T1);                break;            }	}	return;    case 0x04: // Nucleus    case 0x0c: // Nucleus Little Endian (LE)    case 0x10: // As if user primary    case 0x11: // As if user secondary    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 0x24: // Nucleus quad LDD 128 bit atomic    case 0x2c: // Nucleus quad LDD 128 bit atomic    case 0x4a: // UPA config    case 0x88: // Primary LE    case 0x89: // Secondary LE	// XXX	return;    case 0x45: // LSU	{	    uint64_t oldreg;	    oldreg = env->lsu;	    env->lsu = T1 & (DMMU_E | IMMU_E);	    // Mappings generated during D/I MMU disabled mode are	    // invalid in normal mode	    if (oldreg != env->lsu) {#ifdef DEBUG_MMU                printf("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", oldreg, env->lsu);		dump_mmu(env);#endif		tlb_flush(env, 1);	    }	    return;	}    case 0x50: // I-MMU regs	{	    int reg = (T0 >> 3) & 0xf;	    uint64_t oldreg;	    

⌨️ 快捷键说明

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