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

📄 translate.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 4 页
字号:
            generate_exception(ctx, EXCP_RI);            return;        }    } else {        switch (opc) {        case OPC_TEQ:        case OPC_TEQI:            gen_op_eq();            break;        case OPC_TGE:        case OPC_TGEI:            gen_op_ge();            break;        case OPC_TGEU:        case OPC_TGEIU:            gen_op_geu();            break;        case OPC_TLT:        case OPC_TLTI:            gen_op_lt();            break;        case OPC_TLTU:        case OPC_TLTIU:            gen_op_ltu();            break;        case OPC_TNE:        case OPC_TNEI:            gen_op_ne();            break;        default:            MIPS_INVAL("TRAP");            generate_exception(ctx, EXCP_RI);            return;        }    }    save_cpu_state(ctx, 1);    gen_op_trap();    ctx->bstate = BS_STOP;}static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest){    TranslationBlock *tb;    tb = ctx->tb;    if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {        if (n == 0)            gen_op_goto_tb0(TBPARAM(tb));        else            gen_op_goto_tb1(TBPARAM(tb));        gen_op_save_pc(dest);        gen_op_set_T0((long)tb + n);        gen_op_exit_tb();    } else {        gen_op_save_pc(dest);        gen_op_set_T0(0);        gen_op_exit_tb();    }}/* Branches (before delay slot) */static void gen_compute_branch (DisasContext *ctx, uint16_t opc,                                int rs, int rt, int32_t offset){    target_ulong btarget;    int blink, bcond;    btarget = -1;    blink = 0;    bcond = 0;    /* Load needed operands */    switch (opc) {    case OPC_BEQ:    case OPC_BEQL:    case OPC_BNE:    case OPC_BNEL:        /* Compare two registers */        if (rs != rt) {            GEN_LOAD_REG_TN(T0, rs);            GEN_LOAD_REG_TN(T1, rt);            bcond = 1;        }        btarget = ctx->pc + 4 + offset;        break;    case OPC_BGEZ:    case OPC_BGEZAL:    case OPC_BGEZALL:    case OPC_BGEZL:    case OPC_BGTZ:    case OPC_BGTZL:    case OPC_BLEZ:    case OPC_BLEZL:    case OPC_BLTZ:    case OPC_BLTZAL:    case OPC_BLTZALL:    case OPC_BLTZL:        /* Compare to zero */        if (rs != 0) {            gen_op_load_gpr_T0(rs);            bcond = 1;        }        btarget = ctx->pc + 4 + offset;        break;    case OPC_J:    case OPC_JAL:        /* Jump to immediate */        btarget = ((ctx->pc + 4) & 0xF0000000) | offset;        break;    case OPC_JR:    case OPC_JALR:        /* Jump to register */        if (offset != 0) {            /* Only hint = 0 is valid */            generate_exception(ctx, EXCP_RI);            return;        }        GEN_LOAD_REG_TN(T2, rs);        break;    default:        MIPS_INVAL("branch/jump");        generate_exception(ctx, EXCP_RI);        return;    }    if (bcond == 0) {        /* No condition to be computed */        switch (opc) {        case OPC_BEQ:     /* rx == rx        */        case OPC_BEQL:    /* rx == rx likely */        case OPC_BGEZ:    /* 0 >= 0          */        case OPC_BGEZL:   /* 0 >= 0 likely   */        case OPC_BLEZ:    /* 0 <= 0          */        case OPC_BLEZL:   /* 0 <= 0 likely   */            /* Always take */            ctx->hflags |= MIPS_HFLAG_B;            MIPS_DEBUG("balways");            break;        case OPC_BGEZAL:  /* 0 >= 0          */        case OPC_BGEZALL: /* 0 >= 0 likely   */            /* Always take and link */            blink = 31;            ctx->hflags |= MIPS_HFLAG_B;            MIPS_DEBUG("balways and link");            break;        case OPC_BNE:     /* rx != rx        */        case OPC_BGTZ:    /* 0 > 0           */        case OPC_BLTZ:    /* 0 < 0           */            /* Treated as NOP */            MIPS_DEBUG("bnever (NOP)");            return;        case OPC_BLTZAL:  /* 0 < 0           */            gen_op_set_T0(ctx->pc + 8);            gen_op_store_T0_gpr(31);            return;        case OPC_BLTZALL: /* 0 < 0 likely */            gen_op_set_T0(ctx->pc + 8);            gen_op_store_T0_gpr(31);            gen_goto_tb(ctx, 0, ctx->pc + 4);            return;        case OPC_BNEL:    /* rx != rx likely */        case OPC_BGTZL:   /* 0 > 0 likely */        case OPC_BLTZL:   /* 0 < 0 likely */            /* Skip the instruction in the delay slot */            MIPS_DEBUG("bnever and skip");            gen_goto_tb(ctx, 0, ctx->pc + 4);            return;        case OPC_J:            ctx->hflags |= MIPS_HFLAG_B;            MIPS_DEBUG("j %08x", btarget);            break;        case OPC_JAL:            blink = 31;            ctx->hflags |= MIPS_HFLAG_B;            MIPS_DEBUG("jal %08x", btarget);            break;        case OPC_JR:            ctx->hflags |= MIPS_HFLAG_BR;            MIPS_DEBUG("jr %s", regnames[rs]);            break;        case OPC_JALR:            blink = rt;            ctx->hflags |= MIPS_HFLAG_BR;            MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);            break;        default:            MIPS_INVAL("branch/jump");            generate_exception(ctx, EXCP_RI);            return;        }    } else {        switch (opc) {        case OPC_BEQ:            gen_op_eq();            MIPS_DEBUG("beq %s, %s, %08x",                       regnames[rs], regnames[rt], btarget);            goto not_likely;        case OPC_BEQL:            gen_op_eq();            MIPS_DEBUG("beql %s, %s, %08x",                       regnames[rs], regnames[rt], btarget);            goto likely;        case OPC_BNE:            gen_op_ne();            MIPS_DEBUG("bne %s, %s, %08x",                       regnames[rs], regnames[rt], btarget);            goto not_likely;        case OPC_BNEL:            gen_op_ne();            MIPS_DEBUG("bnel %s, %s, %08x",                       regnames[rs], regnames[rt], btarget);            goto likely;        case OPC_BGEZ:            gen_op_gez();            MIPS_DEBUG("bgez %s, %08x", regnames[rs], btarget);            goto not_likely;        case OPC_BGEZL:            gen_op_gez();            MIPS_DEBUG("bgezl %s, %08x", regnames[rs], btarget);            goto likely;        case OPC_BGEZAL:            gen_op_gez();            MIPS_DEBUG("bgezal %s, %08x", regnames[rs], btarget);            blink = 31;            goto not_likely;        case OPC_BGEZALL:            gen_op_gez();            blink = 31;            MIPS_DEBUG("bgezall %s, %08x", regnames[rs], btarget);            goto likely;        case OPC_BGTZ:            gen_op_gtz();            MIPS_DEBUG("bgtz %s, %08x", regnames[rs], btarget);            goto not_likely;        case OPC_BGTZL:            gen_op_gtz();            MIPS_DEBUG("bgtzl %s, %08x", regnames[rs], btarget);            goto likely;        case OPC_BLEZ:            gen_op_lez();            MIPS_DEBUG("blez %s, %08x", regnames[rs], btarget);            goto not_likely;        case OPC_BLEZL:            gen_op_lez();            MIPS_DEBUG("blezl %s, %08x", regnames[rs], btarget);            goto likely;        case OPC_BLTZ:            gen_op_ltz();            MIPS_DEBUG("bltz %s, %08x", regnames[rs], btarget);            goto not_likely;        case OPC_BLTZL:            gen_op_ltz();            MIPS_DEBUG("bltzl %s, %08x", regnames[rs], btarget);            goto likely;        case OPC_BLTZAL:            gen_op_ltz();            blink = 31;            MIPS_DEBUG("bltzal %s, %08x", regnames[rs], btarget);        not_likely:            ctx->hflags |= MIPS_HFLAG_BC;            break;        case OPC_BLTZALL:            gen_op_ltz();            blink = 31;            MIPS_DEBUG("bltzall %s, %08x", regnames[rs], btarget);        likely:            ctx->hflags |= MIPS_HFLAG_BL;            break;        }        gen_op_set_bcond();    }    MIPS_DEBUG("enter ds: link %d cond %02x target %08x",               blink, ctx->hflags, btarget);    ctx->btarget = btarget;    if (blink > 0) {        gen_op_set_T0(ctx->pc + 8);        gen_op_store_T0_gpr(blink);    }    return;}/* CP0 (MMU and control) */static void gen_cp0 (DisasContext *ctx, uint16_t opc, int rt, int rd){    const unsigned char *opn = "unk";    if (!(ctx->CP0_Status & (1 << CP0St_CU0)) &&        (ctx->hflags & MIPS_HFLAG_UM) &&        !(ctx->hflags & MIPS_HFLAG_ERL) &&        !(ctx->hflags & MIPS_HFLAG_EXL)) {        if (loglevel & CPU_LOG_TB_IN_ASM) {            fprintf(logfile, "CP0 is not usable\n");        }        generate_exception_err (ctx, EXCP_CpU, 0);        return;    }    switch (opc) {    case OPC_MFC0:        if (rt == 0) {            /* Treat as NOP */            return;        }        gen_op_mfc0(rd, ctx->opcode & 0x7);        gen_op_store_T0_gpr(rt);        opn = "mfc0";        break;    case OPC_MTC0:        /* If we get an exception, we want to restart at next instruction */        ctx->pc += 4;        save_cpu_state(ctx, 1);        ctx->pc -= 4;        GEN_LOAD_REG_TN(T0, rt);        gen_op_mtc0(rd, ctx->opcode & 0x7);        /* Stop translation as we may have switched the execution mode */        ctx->bstate = BS_STOP;        opn = "mtc0";        break;#if defined(MIPS_USES_R4K_TLB)    case OPC_TLBWI:        gen_op_tlbwi();        opn = "tlbwi";        break;    case OPC_TLBWR:        gen_op_tlbwr();        opn = "tlbwr";        break;    case OPC_TLBP:        gen_op_tlbp();        opn = "tlbp";        break;    case OPC_TLBR:        gen_op_tlbr();        opn = "tlbr";        break;#endif    case OPC_ERET:        opn = "eret";        save_cpu_state(ctx, 0);        gen_op_eret();        ctx->bstate = BS_EXCP;        break;    case OPC_DERET:        opn = "deret";        if (!(ctx->hflags & MIPS_HFLAG_DM)) {            generate_exception(ctx, EXCP_RI);        } else {            save_cpu_state(ctx, 0);            gen_op_deret();            ctx->bstate = BS_EXCP;        }        break;    case OPC_WAIT:        opn = "wait";        /* If we get an exception, we want to restart at next instruction */        ctx->pc += 4;        save_cpu_state(ctx, 1);        ctx->pc -= 4;        gen_op_wait();        ctx->bstate = BS_EXCP;        break;    default:        if (loglevel & CPU_LOG_TB_IN_ASM) {            fprintf(logfile, "Invalid CP0 opcode: %08x %03x %03x %03x\n",                    ctx->opcode, ctx->opcode >> 26, ctx->opcode & 0x3F,                    ((ctx->opcode >> 16) & 0x1F));        }        generate_exception(ctx, EXCP_RI);        return;    }    MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);}/* Coprocessor 1 (FPU) *//* ISA extensions *//* MIPS16 extension to MIPS32 *//* SmartMIPS extension to MIPS32 */#ifdef TARGET_MIPS64static void gen_arith64 (DisasContext *ctx, uint16_t opc){    if (func == 0x02 && rd == 0) {        /* NOP */        return;    }    if (rs == 0 || rt == 0) {        gen_op_reset_T0();        gen_op_save64();    } else {        gen_op_load_gpr_T0(rs);        gen_op_load_gpr_T1(rt);        gen_op_save64();        if (func & 0x01)            gen_op_mul64u();        else            gen_op_mul64s();    }    if (func & 0x02)        gen_op_add64();    else        gen_op_sub64();}/* Coprocessor 3 (FPU) *//* MDMX extension to MIPS64 *//* MIPS-3D extension to MIPS64 */#endifstatic void gen_blikely(DisasContext *ctx){    int l1;    l1 = gen_new_label();    gen_op_jnz_T2(l1);    gen_op_save_state(ctx->hflags & ~MIPS_HFLAG_BMASK);    gen_goto_tb(ctx, 1, ctx->pc + 4);    gen_set_label(l1);}static void decode_opc (DisasContext *ctx){    int32_t offset;    int rs, rt, rd, sa;    uint16_t op, op1;    int16_t imm;    if ((ctx->hflags & MIPS_HFLAG_BMASK) == MIPS_HFLAG_BL) {        /* Handle blikely not taken case */        MIPS_DEBUG("blikely condition (%08x)", ctx->pc + 4);        gen_blikely(ctx);    }    op = ctx->opcode >> 26;    rs = ((ctx->opcode >> 21) & 0x1F);    rt = ((ctx->opcode >> 16) & 0x1F);    rd = ((ctx->opcode >> 11) & 0x1F);    sa = ((ctx->opcode >> 6) & 0x1F);    imm = (int16_t)ctx->opcode;    switch (op) {    case 0x00:          /* Special opcode */        op1 = ctx->opcode & 0x3F;        switch (op1) {        case 0x00:          /* Arithmetic with immediate */        case 0x02 ... 0x03:            gen_arith_imm(ctx, op1 | EXT_SPECIAL, rd, rt, sa);            break;        case 0x04:          /* Arithmetic */        case 0x06 ... 0x07:        case 0x0A ... 0x0B:        case 0x20 ... 0x27:        case 0x2A ... 0x2B:            gen_arith(ctx, op1 | EXT_SPECIAL, rd, rs, rt);

⌨️ 快捷键说明

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