translate.c

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

C
2,182
字号
        generate_exception_err(ctx, EXCP_CpU, 1);}static always_inline void check_cp1_enabled(DisasContext *ctx){    if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))        generate_exception_err(ctx, EXCP_CpU, 1);}/* Verify that the processor is running with COP1X instructions enabled.   This is associated with the nabla symbol in the MIPS32 and MIPS64   opcode tables.  */static always_inline void check_cop1x(DisasContext *ctx){    if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))        generate_exception(ctx, EXCP_RI);}/* Verify that the processor is running with 64-bit floating-point   operations enabled.  */static always_inline void check_cp1_64bitmode(DisasContext *ctx){    if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))        generate_exception(ctx, EXCP_RI);}/* * Verify if floating point register is valid; an operation is not defined * if bit 0 of any register specification is set and the FR bit in the * Status register equals zero, since the register numbers specify an * even-odd pair of adjacent coprocessor general registers. When the FR bit * in the Status register equals one, both even and odd register numbers * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers. * * Multiple 64 bit wide registers can be checked by calling * gen_op_cp1_registers(freg1 | freg2 | ... | fregN); */void check_cp1_registers(DisasContext *ctx, int regs){    if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))        generate_exception(ctx, EXCP_RI);}/* This code generates a "reserved instruction" exception if the   CPU does not support the instruction set corresponding to flags. */static always_inline void check_insn(CPUState *env, DisasContext *ctx, int flags){    if (unlikely(!(env->insn_flags & flags)))        generate_exception(ctx, EXCP_RI);}/* This code generates a "reserved instruction" exception if 64-bit   instructions are not enabled. */static always_inline void check_mips_64(DisasContext *ctx){    if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))        generate_exception(ctx, EXCP_RI);}/* load/store instructions. */#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##_kernel,                                                \    &gen_op_l##width##_super,                                                 \    &gen_op_l##width##_user,                                                  \}#define OP_ST_TABLE(width)                                                    \static GenOpFunc *gen_op_s##width[] = {                                       \    &gen_op_s##width##_kernel,                                                \    &gen_op_s##width##_super,                                                 \    &gen_op_s##width##_user,                                                  \}#endif#if defined(TARGET_MIPS64)OP_LD_TABLE(dl);OP_LD_TABLE(dr);OP_ST_TABLE(dl);OP_ST_TABLE(dr);#endifOP_LD_TABLE(wl);OP_LD_TABLE(wr);OP_ST_TABLE(wl);OP_ST_TABLE(wr);OP_LD_TABLE(wc1);OP_ST_TABLE(wc1);OP_LD_TABLE(dc1);OP_ST_TABLE(dc1);OP_LD_TABLE(uxc1);OP_ST_TABLE(uxc1);#define OP_LD(insn,fname)                                        \void inline op_ldst_##insn(DisasContext *ctx)                    \{                                                                \    tcg_gen_qemu_##fname(cpu_T[0], cpu_T[0], ctx->mem_idx);      \}OP_LD(lb,ld8s);OP_LD(lbu,ld8u);OP_LD(lh,ld16s);OP_LD(lhu,ld16u);OP_LD(lw,ld32s);#if defined(TARGET_MIPS64)OP_LD(lwu,ld32u);OP_LD(ld,ld64);#endif#undef OP_LD#define OP_ST(insn,fname)                                        \void inline op_ldst_##insn(DisasContext *ctx)                    \{                                                                \    tcg_gen_qemu_##fname(cpu_T[1], cpu_T[0], ctx->mem_idx);      \}OP_ST(sb,st8);OP_ST(sh,st16);OP_ST(sw,st32);#if defined(TARGET_MIPS64)OP_ST(sd,st64);#endif#undef OP_ST#define OP_LD_ATOMIC(insn,fname)                                        \void inline op_ldst_##insn(DisasContext *ctx)                           \{                                                                       \    tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);                                 \    tcg_gen_qemu_##fname(cpu_T[0], cpu_T[0], ctx->mem_idx);             \    tcg_gen_st_tl(cpu_T[1], cpu_env, offsetof(CPUState, CP0_LLAddr));   \}OP_LD_ATOMIC(ll,ld32s);#if defined(TARGET_MIPS64)OP_LD_ATOMIC(lld,ld64);#endif#undef OP_LD_ATOMIC#define OP_ST_ATOMIC(insn,fname,almask)                                 \void inline op_ldst_##insn(DisasContext *ctx)                           \{                                                                       \    int r_tmp = tcg_temp_new(TCG_TYPE_TL);                              \    int l1 = gen_new_label();                                           \    int l2 = gen_new_label();                                           \    int l3 = gen_new_label();                                           \                                                                        \    tcg_gen_andi_tl(r_tmp, cpu_T[0], almask);                           \    tcg_gen_brcond_tl(TCG_COND_EQ, r_tmp, tcg_const_tl(0), l1);         \    tcg_gen_st_tl(cpu_T[0], cpu_env, offsetof(CPUState, CP0_BadVAddr)); \    generate_tcg_exception(ctx, EXCP_AdES);                             \    gen_set_label(l1);                                                  \    tcg_gen_ld_tl(r_tmp, cpu_env, offsetof(CPUState, CP0_LLAddr));      \    tcg_gen_brcond_tl(TCG_COND_NE, cpu_T[0], r_tmp, l2);                \    tcg_gen_qemu_##fname(cpu_T[1], cpu_T[0], ctx->mem_idx);             \    tcg_gen_movi_tl(cpu_T[0], 1);                                       \    tcg_gen_br(l3);                                                     \    gen_set_label(l2);                                                  \    tcg_gen_movi_tl(cpu_T[0], 0);                                       \    gen_set_label(l3);                                                  \}OP_ST_ATOMIC(sc,st32,0x3);#if defined(TARGET_MIPS64)OP_ST_ATOMIC(scd,st64,0x7);#endif#undef OP_ST_ATOMICvoid inline op_ldst_lwc1(DisasContext *ctx){    op_ldst(lwc1);}void inline op_ldst_ldc1(DisasContext *ctx){    op_ldst(ldc1);}void inline op_ldst_swc1(DisasContext *ctx){    op_ldst(swc1);}void inline op_ldst_sdc1(DisasContext *ctx){    op_ldst(sdc1);}/* Load and store */static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,                      int base, int16_t offset){    const char *opn = "ldst";    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_addr_add();    }    /* Don't do NOP if destination is zero: we must perform the actual       memory access. */    switch (opc) {#if defined(TARGET_MIPS64)    case OPC_LWU:        op_ldst_lwu(ctx);        GEN_STORE_T0_REG(rt);        opn = "lwu";        break;    case OPC_LD:        op_ldst_ld(ctx);        GEN_STORE_T0_REG(rt);        opn = "ld";        break;    case OPC_LLD:        op_ldst_lld(ctx);        GEN_STORE_T0_REG(rt);        opn = "lld";        break;    case OPC_SD:        GEN_LOAD_REG_T1(rt);        op_ldst_sd(ctx);        opn = "sd";        break;    case OPC_SCD:        save_cpu_state(ctx, 1);        GEN_LOAD_REG_T1(rt);        op_ldst_scd(ctx);        GEN_STORE_T0_REG(rt);        opn = "scd";        break;    case OPC_LDL:        GEN_LOAD_REG_T1(rt);        op_ldst(ldl);        GEN_STORE_T1_REG(rt);        opn = "ldl";        break;    case OPC_SDL:        GEN_LOAD_REG_T1(rt);        op_ldst(sdl);        opn = "sdl";        break;    case OPC_LDR:        GEN_LOAD_REG_T1(rt);        op_ldst(ldr);        GEN_STORE_T1_REG(rt);        opn = "ldr";        break;    case OPC_SDR:        GEN_LOAD_REG_T1(rt);        op_ldst(sdr);        opn = "sdr";        break;#endif    case OPC_LW:        op_ldst_lw(ctx);        GEN_STORE_T0_REG(rt);        opn = "lw";        break;    case OPC_SW:        GEN_LOAD_REG_T1(rt);        op_ldst_sw(ctx);        opn = "sw";        break;    case OPC_LH:        op_ldst_lh(ctx);        GEN_STORE_T0_REG(rt);        opn = "lh";        break;    case OPC_SH:        GEN_LOAD_REG_T1(rt);        op_ldst_sh(ctx);        opn = "sh";        break;    case OPC_LHU:        op_ldst_lhu(ctx);        GEN_STORE_T0_REG(rt);        opn = "lhu";        break;    case OPC_LB:        op_ldst_lb(ctx);        GEN_STORE_T0_REG(rt);        opn = "lb";        break;    case OPC_SB:        GEN_LOAD_REG_T1(rt);        op_ldst_sb(ctx);        opn = "sb";        break;    case OPC_LBU:        op_ldst_lbu(ctx);        GEN_STORE_T0_REG(rt);        opn = "lbu";        break;    case OPC_LWL:	GEN_LOAD_REG_T1(rt);        op_ldst(lwl);        GEN_STORE_T1_REG(rt);        opn = "lwl";        break;    case OPC_SWL:        GEN_LOAD_REG_T1(rt);        op_ldst(swl);        opn = "swr";        break;    case OPC_LWR:	GEN_LOAD_REG_T1(rt);        op_ldst(lwr);        GEN_STORE_T1_REG(rt);        opn = "lwr";        break;    case OPC_SWR:        GEN_LOAD_REG_T1(rt);        op_ldst(swr);        opn = "swr";        break;    case OPC_LL:        op_ldst_ll(ctx);        GEN_STORE_T0_REG(rt);        opn = "ll";        break;    case OPC_SC:        save_cpu_state(ctx, 1);        GEN_LOAD_REG_T1(rt);        op_ldst_sc(ctx);        GEN_STORE_T0_REG(rt);        opn = "sc";        break;    default:        MIPS_INVAL(opn);        generate_exception(ctx, EXCP_RI);        return;    }    MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);}/* Load and store */static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,                      int base, int16_t offset){    const char *opn = "flt_ldst";    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_addr_add();    }    /* Don't do NOP if destination is zero: we must perform the actual       memory access. */    switch (opc) {    case OPC_LWC1:        op_ldst_lwc1(ctx);        GEN_STORE_FTN_FREG(ft, WT0);        opn = "lwc1";        break;    case OPC_SWC1:        GEN_LOAD_FREG_FTN(WT0, ft);        op_ldst_swc1(ctx);        opn = "swc1";        break;    case OPC_LDC1:        op_ldst_ldc1(ctx);        GEN_STORE_FTN_FREG(ft, DT0);        opn = "ldc1";        break;    case OPC_SDC1:        GEN_LOAD_FREG_FTN(DT0, ft);        op_ldst_sdc1(ctx);        opn = "sdc1";        break;    default:        MIPS_INVAL(opn);        generate_exception(ctx, EXCP_RI);        return;    }    MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);}/* Arithmetic with immediate operand */static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,                           int rt, int rs, int16_t imm){    target_ulong uimm;    const char *opn = "imm arith";    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;    }    uimm = (uint16_t)imm;    switch (opc) {    case OPC_ADDI:    case OPC_ADDIU:#if defined(TARGET_MIPS64)    case OPC_DADDI:    case OPC_DADDIU:#endif    case OPC_SLTI:    case OPC_SLTIU:        uimm = (target_long)imm; /* Sign extend to 32/64 bits */        /* Fall through. */    case OPC_ANDI:    case OPC_ORI:    case OPC_XORI:        GEN_LOAD_REG_T0(rs);        GEN_LOAD_IMM_TN(T1, uimm);        break;    case OPC_LUI:        GEN_LOAD_IMM_TN(T0, imm << 16);        break;    case OPC_SLL:    case OPC_SRA:    case OPC_SRL:#if defined(TARGET_MIPS64)    case OPC_DSLL:    case OPC_DSRA:    case OPC_DSRL:    case OPC_DSLL32:    case OPC_DSRA32:    case OPC_DSRL32:#endif        uimm &= 0x1f;        GEN_LOAD_REG_T0(rs);        GEN_LOAD_IMM_TN(T1, uimm);        break;    }    switch (opc) {

⌨️ 快捷键说明

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