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

📄 op_helper.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  MIPS emulation helpers for qemu. *  *  Copyright (c) 2004-2005 Jocelyn Mayer * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "exec.h"#define MIPS_DEBUG_DISAS#define GETPC() (__builtin_return_address(0))/*****************************************************************************//* Exceptions processing helpers */void cpu_loop_exit(void){    longjmp(env->jmp_env, 1);}void do_raise_exception_err (uint32_t exception, int error_code){#if 1    if (logfile && exception < 0x100)        fprintf(logfile, "%s: %d %d\n", __func__, exception, error_code);#endif    env->exception_index = exception;    env->error_code = error_code;    T0 = 0;    cpu_loop_exit();}void do_raise_exception (uint32_t exception){    do_raise_exception_err(exception, 0);}void do_restore_state (void *pc_ptr){  TranslationBlock *tb;  unsigned long pc = (unsigned long) pc_ptr;  tb = tb_find_pc (pc);  cpu_restore_state (tb, env, pc, NULL);}void do_raise_exception_direct (uint32_t exception){    do_restore_state (GETPC ());    do_raise_exception_err (exception, 0);}#define MEMSUFFIX _raw#include "op_helper_mem.c"#undef MEMSUFFIX#if !defined(CONFIG_USER_ONLY)#define MEMSUFFIX _user#include "op_helper_mem.c"#undef MEMSUFFIX#define MEMSUFFIX _kernel#include "op_helper_mem.c"#undef MEMSUFFIX#endif/* 64 bits arithmetic for 32 bits hosts */#if (HOST_LONG_BITS == 32)static inline uint64_t get_HILO (void){    return ((uint64_t)env->HI << 32) | (uint64_t)env->LO;}static inline void set_HILO (uint64_t HILO){    env->LO = HILO & 0xFFFFFFFF;    env->HI = HILO >> 32;}void do_mult (void){    set_HILO((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);}void do_multu (void){    set_HILO((uint64_t)T0 * (uint64_t)T1);}void do_madd (void){    int64_t tmp;    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);    set_HILO((int64_t)get_HILO() + tmp);}void do_maddu (void){    uint64_t tmp;    tmp = ((uint64_t)T0 * (uint64_t)T1);    set_HILO(get_HILO() + tmp);}void do_msub (void){    int64_t tmp;    tmp = ((int64_t)(int32_t)T0 * (int64_t)(int32_t)T1);    set_HILO((int64_t)get_HILO() - tmp);}void do_msubu (void){    uint64_t tmp;    tmp = ((uint64_t)T0 * (uint64_t)T1);    set_HILO(get_HILO() - tmp);}#endif#if defined(CONFIG_USER_ONLY) void do_mfc0 (int reg, int sel){    cpu_abort(env, "mfc0 reg=%d sel=%d\n", reg, sel);}void do_mtc0 (int reg, int sel){    cpu_abort(env, "mtc0 reg=%d sel=%d\n", reg, sel);}void do_tlbwi (void){    cpu_abort(env, "tlbwi\n");}void do_tlbwr (void){    cpu_abort(env, "tlbwr\n");}void do_tlbp (void){    cpu_abort(env, "tlbp\n");}void do_tlbr (void){    cpu_abort(env, "tlbr\n");}#else/* CP0 helpers */void do_mfc0 (int reg, int sel){    const unsigned char *rn;    if (sel != 0 && reg != 16 && reg != 28) {        rn = "invalid";        goto print;    }    switch (reg) {    case 0:        T0 = env->CP0_index;        rn = "Index";        break;    case 1:        T0 = cpu_mips_get_random(env);        rn = "Random";        break;    case 2:        T0 = env->CP0_EntryLo0;        rn = "EntryLo0";        break;    case 3:        T0 = env->CP0_EntryLo1;        rn = "EntryLo1";        break;    case 4:        T0 = env->CP0_Context;        rn = "Context";        break;    case 5:        T0 = env->CP0_PageMask;        rn = "PageMask";        break;    case 6:        T0 = env->CP0_Wired;        rn = "Wired";        break;    case 8:        T0 = env->CP0_BadVAddr;        rn = "BadVaddr";        break;    case 9:        T0 = cpu_mips_get_count(env);        rn = "Count";        break;    case 10:        T0 = env->CP0_EntryHi;        rn = "EntryHi";        break;    case 11:        T0 = env->CP0_Compare;        rn = "Compare";        break;    case 12:        T0 = env->CP0_Status;        if (env->hflags & MIPS_HFLAG_UM)            T0 |= (1 << CP0St_UM);        if (env->hflags & MIPS_HFLAG_ERL)            T0 |= (1 << CP0St_ERL);        if (env->hflags & MIPS_HFLAG_EXL)            T0 |= (1 << CP0St_EXL);        rn = "Status";        break;    case 13:        T0 = env->CP0_Cause;        rn = "Cause";        break;    case 14:        T0 = env->CP0_EPC;        rn = "EPC";        break;    case 15:        T0 = env->CP0_PRid;        rn = "PRid";        break;    case 16:        switch (sel) {        case 0:            T0 = env->CP0_Config0;            rn = "Config";            break;        case 1:            T0 = env->CP0_Config1;            rn = "Config1";            break;        default:            rn = "Unknown config register";            break;        }        break;    case 17:        T0 = env->CP0_LLAddr >> 4;        rn = "LLAddr";        break;    case 18:        T0 = env->CP0_WatchLo;        rn = "WatchLo";        break;    case 19:        T0 = env->CP0_WatchHi;        rn = "WatchHi";        break;    case 23:        T0 = env->CP0_Debug;        if (env->hflags & MIPS_HFLAG_DM)            T0 |= 1 << CP0DB_DM;        rn = "Debug";        break;    case 24:        T0 = env->CP0_DEPC;        rn = "DEPC";        break;    case 28:        switch (sel) {        case 0:            T0 = env->CP0_TagLo;            rn = "TagLo";            break;        case 1:            T0 = env->CP0_DataLo;            rn = "DataLo";            break;        default:            rn = "unknown sel";            break;        }        break;    case 30:        T0 = env->CP0_ErrorEPC;        rn = "ErrorEPC";        break;    case 31:        T0 = env->CP0_DESAVE;        rn = "DESAVE";        break;    default:        rn = "unknown";        break;    } print:#if defined MIPS_DEBUG_DISAS    if (loglevel & CPU_LOG_TB_IN_ASM) {        fprintf(logfile, "%08x mfc0 %s => %08x (%d %d)\n",                env->PC, rn, T0, reg, sel);    }#endif    return;}void do_mtc0 (int reg, int sel){    const unsigned char *rn;    uint32_t val, old, mask;    if (sel != 0 && reg != 16 && reg != 28) {        val = -1;        old = -1;        rn = "invalid";        goto print;    }    switch (reg) {    case 0:        val = (env->CP0_index & 0x80000000) | (T0 & 0x0000000F);        old = env->CP0_index;        env->CP0_index = val;        rn = "Index";        break;    case 2:        val = T0 & 0x03FFFFFFF;        old = env->CP0_EntryLo0;        env->CP0_EntryLo0 = val;        rn = "EntryLo0";        break;    case 3:        val = T0 & 0x03FFFFFFF;        old = env->CP0_EntryLo1;        env->CP0_EntryLo1 = val;        rn = "EntryLo1";        break;    case 4:        val = (env->CP0_Context & 0xFF000000) | (T0 & 0x00FFFFF0);        old = env->CP0_Context;        env->CP0_Context = val;        rn = "Context";        break;    case 5:        val = T0 & 0x01FFE000;        old = env->CP0_PageMask;        env->CP0_PageMask = val;        rn = "PageMask";        break;    case 6:        val = T0 & 0x0000000F;        old = env->CP0_Wired;        env->CP0_Wired = val;        rn = "Wired";        break;    case 9:        val = T0;        old = cpu_mips_get_count(env);        cpu_mips_store_count(env, val);        rn = "Count";        break;    case 10:        val = T0 & 0xFFFFF0FF;        old = env->CP0_EntryHi;        env->CP0_EntryHi = val;	/* If the ASID changes, flush qemu's TLB.  */	if ((old & 0xFF) != (val & 0xFF))	  tlb_flush (env, 1);        rn = "EntryHi";        break;    case 11:

⌨️ 快捷键说明

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