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

📄 translate.c

📁 qemu性能直逼VMware的仿真器QEMU 的模擬速度約為實機的 25%;約為 Bochs 的 60 倍。Plex86、User-Mode-Linux、VMware 和 Virtual PC 則比
💻 C
📖 第 1 页 / 共 5 页
字号:
    gen_op_cmp_ ## fmt ## _ngt,                                         \};                                                                      \static inline void gen_cmp_ ## fmt(int n)                               \{                                                                       \    cond_ ## fmt ## _table[n]();                                        \}FOP_CONDS(d)FOP_CONDS(s)#endif /* MIPS_USES_FPU */typedef struct DisasContext {    struct TranslationBlock *tb;    target_ulong pc, saved_pc;    uint32_t opcode;    /* Routine used to access memory */    int mem_idx;    uint32_t hflags, saved_hflags;    uint32_t CP0_Status;    int bstate;    target_ulong btarget;} DisasContext;enum {    BS_NONE     = 0, /* We go out of the TB without reaching a branch or an                      * exception condition                      */    BS_STOP     = 1, /* We want to stop translation for any reason */    BS_BRANCH   = 2, /* We reached a branch condition     */    BS_EXCP     = 3, /* We reached an exception condition */};#if defined MIPS_DEBUG_DISAS#define MIPS_DEBUG(fmt, args...)                                              \do {                                                                          \    if (loglevel & CPU_LOG_TB_IN_ASM) {                                       \        fprintf(logfile, TLSZ ": %08x " fmt "\n",                             \                ctx->pc, ctx->opcode , ##args);                               \    }                                                                         \} while (0)#else#define MIPS_DEBUG(fmt, args...) do { } while(0)#endif#define MIPS_INVAL(op)                                                        \do {                                                                          \    MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26,            \               ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F));             \} while (0)#define GEN_LOAD_REG_TN(Tn, Rn)                                               \do {                                                                          \    if (Rn == 0) {                                                            \        glue(gen_op_reset_, Tn)();                                            \    } else {                                                                  \        glue(gen_op_load_gpr_, Tn)(Rn);                                       \    }                                                                         \} while (0)#define GEN_LOAD_IMM_TN(Tn, Imm)                                              \do {                                                                          \    if (Imm == 0) {                                                           \        glue(gen_op_reset_, Tn)();                                            \    } else {                                                                  \        glue(gen_op_set_, Tn)(Imm);                                           \    }                                                                         \} while (0)#define GEN_STORE_TN_REG(Rn, Tn)                                              \do {                                                                          \    if (Rn != 0) {                                                            \        glue(glue(gen_op_store_, Tn),_gpr)(Rn);                               \    }                                                                         \} while (0)#define GEN_LOAD_FREG_FTN(FTn, Fn)                                            \do {                                                                          \    glue(gen_op_load_fpr_, FTn)(Fn);                                          \} while (0)#define GEN_STORE_FTN_FREG(Fn, FTn)                                           \do {                                                                          \    glue(gen_op_store_fpr_, FTn)(Fn);                                         \} while (0)static inline void save_cpu_state (DisasContext *ctx, int do_save_pc){#if defined MIPS_DEBUG_DISAS    if (loglevel & CPU_LOG_TB_IN_ASM) {            fprintf(logfile, "hflags %08x saved %08x\n",                    ctx->hflags, ctx->saved_hflags);    }#endif    if (do_save_pc && ctx->pc != ctx->saved_pc) {        gen_op_save_pc(ctx->pc);        ctx->saved_pc = ctx->pc;    }    if (ctx->hflags != ctx->saved_hflags) {        gen_op_save_state(ctx->hflags);        ctx->saved_hflags = ctx->hflags;        if (ctx->hflags & MIPS_HFLAG_BR) {            gen_op_save_breg_target();        } else if (ctx->hflags & MIPS_HFLAG_B) {            gen_op_save_btarget(ctx->btarget);        } else if (ctx->hflags & MIPS_HFLAG_BMASK) {            gen_op_save_bcond();            gen_op_save_btarget(ctx->btarget);        }    }}static inline void generate_exception_err (DisasContext *ctx, int excp, int err){#if defined MIPS_DEBUG_DISAS    if (loglevel & CPU_LOG_TB_IN_ASM)            fprintf(logfile, "%s: raise exception %d\n", __func__, excp);#endif    save_cpu_state(ctx, 1);    if (err == 0)        gen_op_raise_exception(excp);    else        gen_op_raise_exception_err(excp, err);    ctx->bstate = BS_EXCP;}static inline void generate_exception (DisasContext *ctx, int excp){    generate_exception_err (ctx, excp, 0);}#if defined(CONFIG_USER_ONLY)#define op_ldst(name)        gen_op_##name##_raw()#define OP_LD_TABLE(width)#define OP_ST_TABLE(width)#else#define op_ldst(name)        (*gen_op_##name[ctx->mem_idx])()#define OP_LD_TABLE(width)                                                    \static GenOpFunc *gen_op_l##width[] = {                                       \    &gen_op_l##width##_user,                                                  \    &gen_op_l##width##_kernel,                                                \}#define OP_ST_TABLE(width)                                                    \static GenOpFunc *gen_op_s##width[] = {                                       \    &gen_op_s##width##_user,                                                  \    &gen_op_s##width##_kernel,                                                \}#endif#ifdef MIPS_HAS_MIPS64OP_LD_TABLE(d);OP_LD_TABLE(dl);OP_LD_TABLE(dr);OP_ST_TABLE(d);OP_ST_TABLE(dl);OP_ST_TABLE(dr);OP_LD_TABLE(ld);OP_ST_TABLE(cd);#endifOP_LD_TABLE(w);OP_LD_TABLE(wu);OP_LD_TABLE(wl);OP_LD_TABLE(wr);OP_ST_TABLE(w);OP_ST_TABLE(wl);OP_ST_TABLE(wr);OP_LD_TABLE(h);OP_LD_TABLE(hu);OP_ST_TABLE(h);OP_LD_TABLE(b);OP_LD_TABLE(bu);OP_ST_TABLE(b);OP_LD_TABLE(l);OP_ST_TABLE(c);#ifdef MIPS_USES_FPUOP_LD_TABLE(wc1);OP_ST_TABLE(wc1);OP_LD_TABLE(dc1);OP_ST_TABLE(dc1);#endif/* Load and store */static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,                      int base, int16_t offset){    const char *opn = "unk";    if (base == 0) {        GEN_LOAD_IMM_TN(T0, offset);    } else if (offset == 0) {        gen_op_load_gpr_T0(base);    } else {        gen_op_load_gpr_T0(base);        gen_op_set_T1(offset);        gen_op_add();    }    /* Don't do NOP if destination is zero: we must perform the actual     * memory access     */    switch (opc) {#ifdef MIPS_HAS_MIPS64    case OPC_LD:        op_ldst(ld);        GEN_STORE_TN_REG(rt, T0);        opn = "ld";        break;    case OPC_LLD:        op_ldst(lld);        GEN_STORE_TN_REG(rt, T0);        opn = "lld";        break;    case OPC_SD:        GEN_LOAD_REG_TN(T1, rt);        op_ldst(sd);        opn = "sd";        break;    case OPC_SCD:        GEN_LOAD_REG_TN(T1, rt);        op_ldst(scd);        opn = "scd";        break;    case OPC_LDL:        op_ldst(ldl);        GEN_STORE_TN_REG(rt, T0);        opn = "ldl";        break;    case OPC_SDL:        GEN_LOAD_REG_TN(T1, rt);        op_ldst(sdl);        opn = "sdl";        break;    case OPC_LDR:        op_ldst(ldr);        GEN_STORE_TN_REG(rt, T0);        opn = "ldr";        break;    case OPC_SDR:        GEN_LOAD_REG_TN(T1, rt);        op_ldst(sdr);        opn = "sdr";        break;#endif    case OPC_LW:        op_ldst(lw);        GEN_STORE_TN_REG(rt, T0);        opn = "lw";        break;    case OPC_LWU:        op_ldst(lwu);        GEN_STORE_TN_REG(rt, T0);        opn = "lwu";        break;    case OPC_SW:        GEN_LOAD_REG_TN(T1, rt);        op_ldst(sw);        opn = "sw";        break;    case OPC_LH:        op_ldst(lh);        GEN_STORE_TN_REG(rt, T0);        opn = "lh";        break;    case OPC_SH:        GEN_LOAD_REG_TN(T1, rt);        op_ldst(sh);        opn = "sh";        break;    case OPC_LHU:        op_ldst(lhu);        GEN_STORE_TN_REG(rt, T0);        opn = "lhu";        break;    case OPC_LB:        op_ldst(lb);        GEN_STORE_TN_REG(rt, T0);        opn = "lb";        break;    case OPC_SB:        GEN_LOAD_REG_TN(T1, rt);        op_ldst(sb);        opn = "sb";        break;    case OPC_LBU:        op_ldst(lbu);        GEN_STORE_TN_REG(rt, T0);        opn = "lbu";        break;    case OPC_LWL:	GEN_LOAD_REG_TN(T1, rt);        op_ldst(lwl);        GEN_STORE_TN_REG(rt, T0);        opn = "lwl";        break;    case OPC_SWL:        GEN_LOAD_REG_TN(T1, rt);        op_ldst(swl);        opn = "swr";        break;    case OPC_LWR:	GEN_LOAD_REG_TN(T1, rt);        op_ldst(lwr);        GEN_STORE_TN_REG(rt, T0);        opn = "lwr";        break;    case OPC_SWR:        GEN_LOAD_REG_TN(T1, rt);        op_ldst(swr);        opn = "swr";        break;    case OPC_LL:        op_ldst(ll);        GEN_STORE_TN_REG(rt, T0);        opn = "ll";        break;    case OPC_SC:        GEN_LOAD_REG_TN(T1, rt);        op_ldst(sc);        GEN_STORE_TN_REG(rt, T0);        opn = "sc";        break;    default:        MIPS_INVAL("load/store");        generate_exception(ctx, EXCP_RI);        return;    }    MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);}#ifdef MIPS_USES_FPU/* Load and store */static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,                      int base, int16_t offset){    const char *opn = "unk";    if (base == 0) {        GEN_LOAD_IMM_TN(T0, offset);    } else if (offset == 0) {        gen_op_load_gpr_T0(base);    } else {        gen_op_load_gpr_T0(base);        gen_op_set_T1(offset);        gen_op_add();    }    /* Don't do NOP if destination is zero: we must perform the actual     * memory access     */    switch (opc) {    case OPC_LWC1:        op_ldst(lwc1);        GEN_STORE_FTN_FREG(ft, WT0);        opn = "lwc1";        break;    case OPC_SWC1:        GEN_LOAD_FREG_FTN(WT0, ft);        op_ldst(swc1);        opn = "swc1";        break;    case OPC_LDC1:        op_ldst(ldc1);        GEN_STORE_FTN_FREG(ft, DT0);        opn = "ldc1";        break;    case OPC_SDC1:        GEN_LOAD_FREG_FTN(DT0, ft);        op_ldst(sdc1);        opn = "sdc1";        break;    default:        MIPS_INVAL("float load/store");        generate_exception_err(ctx, EXCP_CpU, 1);        return;    }    MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);}#endif /* MIPS_USES_FPU *//* Arithmetic with immediate operand */static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,                           int rs, int16_t imm){    uint32_t uimm;    const char *opn = "unk";    if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {        /* if no destination, treat it as a NOP          * For addi, we must generate the overflow exception when needed.         */        MIPS_DEBUG("NOP");        return;    }    if (opc == OPC_ADDI || opc == OPC_ADDIU ||        opc == OPC_DADDI || opc == OPC_DADDIU ||        opc == OPC_SLTI || opc == OPC_SLTIU)        uimm = (int32_t)imm; /* Sign extend to 32 bits */    else        uimm = (uint16_t)imm;    if (opc != OPC_LUI) {        GEN_LOAD_REG_TN(T0, rs);        GEN_LOAD_IMM_TN(T1, uimm);    } else {        uimm = uimm << 16;        GEN_LOAD_IMM_TN(T0, uimm);    }    switch (opc) {    case OPC_ADDI:        save_cpu_state(ctx, 1);        gen_op_addo();        opn = "addi";        break;    case OPC_ADDIU:        gen_op_add();        opn = "addiu";        break;#ifdef MIPS_HAS_MIPS64    case OPC_DADDI:        save_cpu_state(ctx, 1);        gen_op_daddo();        opn = "daddi";        break;    case OPC_DADDIU:        gen_op_dadd();        opn = "daddiu";        break;#endif    case OPC_SLTI:        gen_op_lt();        opn = "slti";        break;    case OPC_SLTIU:        gen_op_ltu();        opn = "sltiu";        break;    case OPC_ANDI:        gen_op_and();        opn = "andi";        break;    case OPC_ORI:        gen_op_or();        opn = "ori";        break;    case OPC_XORI:        gen_op_xor();        opn = "xori";        break;    case OPC_LUI:        opn = "lui";        break;    case OPC_SLL:        gen_op_sll();        opn = "sll";        break;    case OPC_SRA:        gen_op_sra();        opn = "sra";        break;    case OPC_SRL:       if ((ctx->opcode >> 21) & 1) {            gen_op_rotr();            opn = "rotr";       } else {            gen_op_srl();            opn = "srl";       }        break;#ifdef MIPS_HAS_MIPS64

⌨️ 快捷键说明

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