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

📄 helper.c

📁 QEMU 0.91 source code, supports ARM processor including S3C24xx series
💻 C
📖 第 1 页 / 共 2 页
字号:
#if !defined(CONFIG_USER_ONLY)static const char * const excp_names[EXCP_LAST + 1] = {    [EXCP_RESET] = "reset",    [EXCP_SRESET] = "soft reset",    [EXCP_DSS] = "debug single step",    [EXCP_DINT] = "debug interrupt",    [EXCP_NMI] = "non-maskable interrupt",    [EXCP_MCHECK] = "machine check",    [EXCP_EXT_INTERRUPT] = "interrupt",    [EXCP_DFWATCH] = "deferred watchpoint",    [EXCP_DIB] = "debug instruction breakpoint",    [EXCP_IWATCH] = "instruction fetch watchpoint",    [EXCP_AdEL] = "address error load",    [EXCP_AdES] = "address error store",    [EXCP_TLBF] = "TLB refill",    [EXCP_IBE] = "instruction bus error",    [EXCP_DBp] = "debug breakpoint",    [EXCP_SYSCALL] = "syscall",    [EXCP_BREAK] = "break",    [EXCP_CpU] = "coprocessor unusable",    [EXCP_RI] = "reserved instruction",    [EXCP_OVERFLOW] = "arithmetic overflow",    [EXCP_TRAP] = "trap",    [EXCP_FPE] = "floating point",    [EXCP_DDBS] = "debug data break store",    [EXCP_DWATCH] = "data watchpoint",    [EXCP_LTLBL] = "TLB modify",    [EXCP_TLBL] = "TLB load",    [EXCP_TLBS] = "TLB store",    [EXCP_DBE] = "data bus error",    [EXCP_DDBL] = "debug data break load",    [EXCP_THREAD] = "thread",    [EXCP_MDMX] = "MDMX",    [EXCP_C2E] = "precise coprocessor 2",    [EXCP_CACHE] = "cache error",};#endifvoid do_interrupt (CPUState *env){#if !defined(CONFIG_USER_ONLY)    target_ulong offset;    int cause = -1;    const char *name;    if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {        if (env->exception_index < 0 || env->exception_index > EXCP_LAST)            name = "unknown";        else            name = excp_names[env->exception_index];        fprintf(logfile, "%s enter: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " %s exception\n",                __func__, env->PC[env->current_tc], env->CP0_EPC, name);    }    if (env->exception_index == EXCP_EXT_INTERRUPT &&        (env->hflags & MIPS_HFLAG_DM))        env->exception_index = EXCP_DINT;    offset = 0x180;    switch (env->exception_index) {    case EXCP_DSS:        env->CP0_Debug |= 1 << CP0DB_DSS;        /* Debug single step cannot be raised inside a delay slot and         * resume will always occur on the next instruction         * (but we assume the pc has always been updated during         *  code translation).         */        env->CP0_DEPC = env->PC[env->current_tc];        goto enter_debug_mode;    case EXCP_DINT:        env->CP0_Debug |= 1 << CP0DB_DINT;        goto set_DEPC;    case EXCP_DIB:        env->CP0_Debug |= 1 << CP0DB_DIB;        goto set_DEPC;    case EXCP_DBp:        env->CP0_Debug |= 1 << CP0DB_DBp;        goto set_DEPC;    case EXCP_DDBS:        env->CP0_Debug |= 1 << CP0DB_DDBS;        goto set_DEPC;    case EXCP_DDBL:        env->CP0_Debug |= 1 << CP0DB_DDBL;    set_DEPC:        if (env->hflags & MIPS_HFLAG_BMASK) {            /* If the exception was raised from a delay slot,               come back to the jump.  */            env->CP0_DEPC = env->PC[env->current_tc] - 4;            env->hflags &= ~MIPS_HFLAG_BMASK;        } else {            env->CP0_DEPC = env->PC[env->current_tc];        }    enter_debug_mode:        env->hflags |= MIPS_HFLAG_DM | MIPS_HFLAG_64 | MIPS_HFLAG_CP0;        env->hflags &= ~(MIPS_HFLAG_KSU);        /* EJTAG probe trap enable is not implemented... */        if (!(env->CP0_Status & (1 << CP0St_EXL)))            env->CP0_Cause &= ~(1 << CP0Ca_BD);        env->PC[env->current_tc] = (int32_t)0xBFC00480;        break;    case EXCP_RESET:        cpu_reset(env);        break;    case EXCP_SRESET:        env->CP0_Status |= (1 << CP0St_SR);        memset(env->CP0_WatchLo, 0, sizeof(*env->CP0_WatchLo));        goto set_error_EPC;    case EXCP_NMI:        env->CP0_Status |= (1 << CP0St_NMI);    set_error_EPC:        if (env->hflags & MIPS_HFLAG_BMASK) {            /* If the exception was raised from a delay slot,               come back to the jump.  */            env->CP0_ErrorEPC = env->PC[env->current_tc] - 4;            env->hflags &= ~MIPS_HFLAG_BMASK;        } else {            env->CP0_ErrorEPC = env->PC[env->current_tc];        }        env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);        env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;        env->hflags &= ~(MIPS_HFLAG_KSU);        if (!(env->CP0_Status & (1 << CP0St_EXL)))            env->CP0_Cause &= ~(1 << CP0Ca_BD);        env->PC[env->current_tc] = (int32_t)0xBFC00000;        break;    case EXCP_EXT_INTERRUPT:        cause = 0;        if (env->CP0_Cause & (1 << CP0Ca_IV))            offset = 0x200;        goto set_EPC;    case EXCP_LTLBL:        cause = 1;        goto set_EPC;    case EXCP_TLBL:        cause = 2;        if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {#if defined(TARGET_MIPS64)            int R = env->CP0_BadVAddr >> 62;            int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;            int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;            int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;            if ((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX))                offset = 0x080;            else#endif                offset = 0x000;        }        goto set_EPC;    case EXCP_TLBS:        cause = 3;        if (env->error_code == 1 && !(env->CP0_Status & (1 << CP0St_EXL))) {#if defined(TARGET_MIPS64)            int R = env->CP0_BadVAddr >> 62;            int UX = (env->CP0_Status & (1 << CP0St_UX)) != 0;            int SX = (env->CP0_Status & (1 << CP0St_SX)) != 0;            int KX = (env->CP0_Status & (1 << CP0St_KX)) != 0;            if ((R == 0 && UX) || (R == 1 && SX) || (R == 3 && KX))                offset = 0x080;            else#endif                offset = 0x000;        }        goto set_EPC;    case EXCP_AdEL:        cause = 4;        goto set_EPC;    case EXCP_AdES:        cause = 5;        goto set_EPC;    case EXCP_IBE:        cause = 6;        goto set_EPC;    case EXCP_DBE:        cause = 7;        goto set_EPC;    case EXCP_SYSCALL:        cause = 8;        goto set_EPC;    case EXCP_BREAK:        cause = 9;        goto set_EPC;    case EXCP_RI:        cause = 10;        goto set_EPC;    case EXCP_CpU:        cause = 11;        env->CP0_Cause = (env->CP0_Cause & ~(0x3 << CP0Ca_CE)) |                         (env->error_code << CP0Ca_CE);        goto set_EPC;    case EXCP_OVERFLOW:        cause = 12;        goto set_EPC;    case EXCP_TRAP:        cause = 13;        goto set_EPC;    case EXCP_FPE:        cause = 15;        goto set_EPC;    case EXCP_C2E:        cause = 18;        goto set_EPC;    case EXCP_MDMX:        cause = 22;        goto set_EPC;    case EXCP_DWATCH:        cause = 23;        /* XXX: TODO: manage defered watch exceptions */        goto set_EPC;    case EXCP_MCHECK:        cause = 24;        goto set_EPC;    case EXCP_THREAD:        cause = 25;        goto set_EPC;    case EXCP_CACHE:        cause = 30;        if (env->CP0_Status & (1 << CP0St_BEV)) {            offset = 0x100;        } else {            offset = 0x20000100;        }    set_EPC:        if (!(env->CP0_Status & (1 << CP0St_EXL))) {            if (env->hflags & MIPS_HFLAG_BMASK) {                /* If the exception was raised from a delay slot,                   come back to the jump.  */                env->CP0_EPC = env->PC[env->current_tc] - 4;                env->CP0_Cause |= (1 << CP0Ca_BD);            } else {                env->CP0_EPC = env->PC[env->current_tc];                env->CP0_Cause &= ~(1 << CP0Ca_BD);            }            env->CP0_Status |= (1 << CP0St_EXL);            env->hflags |= MIPS_HFLAG_64 | MIPS_HFLAG_CP0;            env->hflags &= ~(MIPS_HFLAG_KSU);        }        env->hflags &= ~MIPS_HFLAG_BMASK;        if (env->CP0_Status & (1 << CP0St_BEV)) {            env->PC[env->current_tc] = (int32_t)0xBFC00200;        } else {            env->PC[env->current_tc] = (int32_t)(env->CP0_EBase & ~0x3ff);        }        env->PC[env->current_tc] += offset;        env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC);        break;    default:        if (logfile) {            fprintf(logfile, "Invalid MIPS exception %d. Exiting\n",                    env->exception_index);        }        printf("Invalid MIPS exception %d. Exiting\n", env->exception_index);        exit(1);    }    if (logfile && env->exception_index != EXCP_EXT_INTERRUPT) {        fprintf(logfile, "%s: PC " TARGET_FMT_lx " EPC " TARGET_FMT_lx " cause %d\n"                "    S %08x C %08x A " TARGET_FMT_lx " D " TARGET_FMT_lx "\n",                __func__, env->PC[env->current_tc], env->CP0_EPC, cause,                env->CP0_Status, env->CP0_Cause, env->CP0_BadVAddr,                env->CP0_DEPC);    }#endif /* !defined(CONFIG_USER_ONLY) */    env->exception_index = EXCP_NONE;}void r4k_invalidate_tlb (CPUState *env, int idx, int use_extra){    r4k_tlb_t *tlb;    target_ulong addr;    target_ulong end;    uint8_t ASID = env->CP0_EntryHi & 0xFF;    target_ulong mask;    tlb = &env->tlb->mmu.r4k.tlb[idx];    /* The qemu TLB is flushed when the ASID changes, so no need to       flush these entries again.  */    if (tlb->G == 0 && tlb->ASID != ASID) {        return;    }    if (use_extra && env->tlb->tlb_in_use < MIPS_TLB_MAX) {        /* For tlbwr, we can shadow the discarded entry into	   a new (fake) TLB entry, as long as the guest can not	   tell that it's there.  */        env->tlb->mmu.r4k.tlb[env->tlb->tlb_in_use] = *tlb;        env->tlb->tlb_in_use++;        return;    }    /* 1k pages are not supported. */    mask = tlb->PageMask | ~(TARGET_PAGE_MASK << 1);    if (tlb->V0) {        addr = tlb->VPN & ~mask;#if defined(TARGET_MIPS64)        if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {            addr |= 0x3FFFFF0000000000ULL;        }#endif        end = addr | (mask >> 1);        while (addr < end) {            tlb_flush_page (env, addr);            addr += TARGET_PAGE_SIZE;        }    }    if (tlb->V1) {        addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1);#if defined(TARGET_MIPS64)        if (addr >= (0xFFFFFFFF80000000ULL & env->SEGMask)) {            addr |= 0x3FFFFF0000000000ULL;        }#endif        end = addr | mask;        while (addr < end) {            tlb_flush_page (env, addr);            addr += TARGET_PAGE_SIZE;        }    }}

⌨️ 快捷键说明

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