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

📄 translate.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 5 页
字号:
        set_cc = (insn >> 20) & 1;        logic_cc = table_logic_cc[op1] & set_cc;        /* data processing instruction */        if (insn & (1 << 25)) {            /* immediate operand */            val = insn & 0xff;            shift = ((insn >> 8) & 0xf) * 2;            if (shift)                val = (val >> shift) | (val << (32 - shift));            gen_op_movl_T1_im(val);            if (logic_cc && shift)                gen_op_mov_CF_T1();        } else {            /* register */            rm = (insn) & 0xf;            gen_movl_T1_reg(s, rm);            shiftop = (insn >> 5) & 3;            if (!(insn & (1 << 4))) {                shift = (insn >> 7) & 0x1f;                if (shift != 0) {                    if (logic_cc) {                        gen_shift_T1_im_cc[shiftop](shift);                    } else {                        gen_shift_T1_im[shiftop](shift);                    }                } else if (shiftop != 0) {                    if (logic_cc) {                        gen_shift_T1_0_cc[shiftop]();                    } else {                        gen_shift_T1_0[shiftop]();                    }                }            } else {                rs = (insn >> 8) & 0xf;                gen_movl_T0_reg(s, rs);                if (logic_cc) {                    gen_shift_T1_T0_cc[shiftop]();                } else {                    gen_shift_T1_T0[shiftop]();                }            }        }        if (op1 != 0x0f && op1 != 0x0d) {            rn = (insn >> 16) & 0xf;            gen_movl_T0_reg(s, rn);        }        rd = (insn >> 12) & 0xf;        switch(op1) {        case 0x00:            gen_op_andl_T0_T1();            gen_movl_reg_T0(s, rd);            if (logic_cc)                gen_op_logic_T0_cc();            break;        case 0x01:            gen_op_xorl_T0_T1();            gen_movl_reg_T0(s, rd);            if (logic_cc)                gen_op_logic_T0_cc();            break;        case 0x02:            if (set_cc && rd == 15) {                /* SUBS r15, ... is used for exception return.  */                if (IS_USER(s))                    goto illegal_op;                gen_op_subl_T0_T1_cc();                gen_exception_return(s);            } else {                if (set_cc)                    gen_op_subl_T0_T1_cc();                else                    gen_op_subl_T0_T1();                gen_movl_reg_T0(s, rd);            }            break;        case 0x03:            if (set_cc)                gen_op_rsbl_T0_T1_cc();            else                gen_op_rsbl_T0_T1();            gen_movl_reg_T0(s, rd);            break;        case 0x04:            if (set_cc)                gen_op_addl_T0_T1_cc();            else                gen_op_addl_T0_T1();            gen_movl_reg_T0(s, rd);            break;        case 0x05:            if (set_cc)                gen_op_adcl_T0_T1_cc();            else                gen_op_adcl_T0_T1();            gen_movl_reg_T0(s, rd);            break;        case 0x06:            if (set_cc)                gen_op_sbcl_T0_T1_cc();            else                gen_op_sbcl_T0_T1();            gen_movl_reg_T0(s, rd);            break;        case 0x07:            if (set_cc)                gen_op_rscl_T0_T1_cc();            else                gen_op_rscl_T0_T1();            gen_movl_reg_T0(s, rd);            break;        case 0x08:            if (set_cc) {                gen_op_andl_T0_T1();                gen_op_logic_T0_cc();            }            break;        case 0x09:            if (set_cc) {                gen_op_xorl_T0_T1();                gen_op_logic_T0_cc();            }            break;        case 0x0a:            if (set_cc) {                gen_op_subl_T0_T1_cc();            }            break;        case 0x0b:            if (set_cc) {                gen_op_addl_T0_T1_cc();            }            break;        case 0x0c:            gen_op_orl_T0_T1();            gen_movl_reg_T0(s, rd);            if (logic_cc)                gen_op_logic_T0_cc();            break;        case 0x0d:            if (logic_cc && rd == 15) {                /* MOVS r15, ... is used for exception return.  */                if (IS_USER(s))                    goto illegal_op;                gen_op_movl_T0_T1();                gen_exception_return(s);            } else {                gen_movl_reg_T1(s, rd);                if (logic_cc)                    gen_op_logic_T1_cc();            }            break;        case 0x0e:            gen_op_bicl_T0_T1();            gen_movl_reg_T0(s, rd);            if (logic_cc)                gen_op_logic_T0_cc();            break;        default:        case 0x0f:            gen_op_notl_T1();            gen_movl_reg_T1(s, rd);            if (logic_cc)                gen_op_logic_T1_cc();            break;        }    } else {        /* other instructions */        op1 = (insn >> 24) & 0xf;        switch(op1) {        case 0x0:        case 0x1:            /* multiplies, extra load/stores */            sh = (insn >> 5) & 3;            if (sh == 0) {                if (op1 == 0x0) {                    rd = (insn >> 16) & 0xf;                    rn = (insn >> 12) & 0xf;                    rs = (insn >> 8) & 0xf;                    rm = (insn) & 0xf;                    if (((insn >> 22) & 3) == 0) {                        /* 32 bit mul */                        gen_movl_T0_reg(s, rs);                        gen_movl_T1_reg(s, rm);                        gen_op_mul_T0_T1();                        if (insn & (1 << 21)) {                            gen_movl_T1_reg(s, rn);                            gen_op_addl_T0_T1();                        }                        if (insn & (1 << 20))                             gen_op_logic_T0_cc();                        gen_movl_reg_T0(s, rd);                    } else {                        /* 64 bit mul */                        gen_movl_T0_reg(s, rs);                        gen_movl_T1_reg(s, rm);                        if (insn & (1 << 22))                             gen_op_imull_T0_T1();                        else                            gen_op_mull_T0_T1();                        if (insn & (1 << 21)) /* mult accumulate */                            gen_op_addq_T0_T1(rn, rd);                        if (!(insn & (1 << 23))) { /* double accumulate */                            ARCH(6);                            gen_op_addq_lo_T0_T1(rn);                            gen_op_addq_lo_T0_T1(rd);                        }                        if (insn & (1 << 20))                             gen_op_logicq_cc();                        gen_movl_reg_T0(s, rn);                        gen_movl_reg_T1(s, rd);                    }                } else {                    rn = (insn >> 16) & 0xf;                    rd = (insn >> 12) & 0xf;                    if (insn & (1 << 23)) {                        /* load/store exclusive */                        goto illegal_op;                    } else {                        /* SWP instruction */                        rm = (insn) & 0xf;                                                gen_movl_T0_reg(s, rm);                        gen_movl_T1_reg(s, rn);                        if (insn & (1 << 22)) {                            gen_ldst(swpb, s);                        } else {                            gen_ldst(swpl, s);                        }                        gen_movl_reg_T0(s, rd);                    }                }            } else {                /* Misc load/store */                rn = (insn >> 16) & 0xf;                rd = (insn >> 12) & 0xf;                gen_movl_T1_reg(s, rn);                if (insn & (1 << 24))                    gen_add_datah_offset(s, insn);                if (insn & (1 << 20)) {                    /* load */                    switch(sh) {                    case 1:                        gen_ldst(lduw, s);                        break;                    case 2:                        gen_ldst(ldsb, s);                        break;                    default:                    case 3:                        gen_ldst(ldsw, s);                        break;                    }                    gen_movl_reg_T0(s, rd);                } else if (sh & 2) {                    /* doubleword */                    if (sh & 1) {                        /* store */                        gen_movl_T0_reg(s, rd);                        gen_ldst(stl, s);                        gen_op_addl_T1_im(4);                        gen_movl_T0_reg(s, rd + 1);                        gen_ldst(stl, s);                        if ((insn & (1 << 24)) || (insn & (1 << 20)))                            gen_op_addl_T1_im(-4);                    } else {                        /* load */                        gen_ldst(ldl, s);                        gen_movl_reg_T0(s, rd);                        gen_op_addl_T1_im(4);                        gen_ldst(ldl, s);                        gen_movl_reg_T0(s, rd + 1);                        if ((insn & (1 << 24)) || (insn & (1 << 20)))                            gen_op_addl_T1_im(-4);                    }                } else {                    /* store */                    gen_movl_T0_reg(s, rd);                    gen_ldst(stw, s);                }                if (!(insn & (1 << 24))) {                    gen_add_datah_offset(s, insn);                    gen_movl_reg_T1(s, rn);                } else if (insn & (1 << 21)) {                    gen_movl_reg_T1(s, rn);                }            }            break;        case 0x4:        case 0x5:        case 0x6:        case 0x7:            /* load/store byte/word */            rn = (insn >> 16) & 0xf;            rd = (insn >> 12) & 0xf;            gen_movl_T1_reg(s, rn);            i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);            if (insn & (1 << 24))                gen_add_data_offset(s, insn);            if (insn & (1 << 20)) {                /* load */#if defined(CONFIG_USER_ONLY)                if (insn & (1 << 22))                    gen_op_ldub_raw();                else                    gen_op_ldl_raw();#else                if (insn & (1 << 22)) {                    if (i)                        gen_op_ldub_user();                    else                        gen_op_ldub_kernel();                } else {                    if (i)                        gen_op_ldl_user();                    else                        gen_op_ldl_kernel();                }#endif                if (rd == 15)                    gen_bx(s);                else                    gen_movl_reg_T0(s, rd);            } else {                /* store */                gen_movl_T0_reg(s, rd);#if defined(CONFIG_USER_ONLY)                if (insn & (1 << 22))                    gen_op_stb_raw();                else                    gen_op_stl_raw();#else                if (insn & (1 << 22)) {                    if (i)                        gen_op_stb_user();                    else                        gen_op_stb_kernel();                } else {                    if (i)                        gen_op_stl_user();                    else                        gen_op_stl_kernel();                }#endif            }            if (!(insn & (1 << 24))) {                gen_add_data_offset(s, insn);                gen_movl_reg_T1(s, rn);            } else if (insn & (1 << 21))                gen_movl_reg_T1(s, rn); {            }            break;        case 0x08:        case 0x09:            {                int j, n, user, loaded_base;                /* load/store multiple words */                /* XXX: store correct base if write back */                user = 0;                if (insn & (1 << 22)) {                    if (IS_USER(s))                        goto illegal_op; /* only usable in supervisor mode */                    if ((insn & (1 << 15)) == 0)                        user = 1;                }                rn = (insn >> 16) & 0xf;                gen_movl_T1_reg(s, rn);                                /* compute total size */                loaded_base = 0;                n = 0;                for(i=0;i<16;i++) {                    if (insn & (1 << i))                        n++;                }                /* XXX: test invalid n == 0 case ? */                if (insn & (1 << 23)) {                    if (insn & (1 << 24)) {                        /* pre increment */                        gen_op_addl_T1_im(4);                    } else {                        /* post increment */                    }                } else {                    if (insn & (1 << 24)) {                        /* pre decrement */                        gen_op_addl_T1_im(-(n * 4));                    } else {                        /* post decrement */                        if (n != 1)                            gen_op_addl_T1_im(-((n - 1) * 4));                    }                }                j = 0;                for(i=0;i<16;i++) {                    if (insn & (1 << i)) {                        if (insn & (1 << 20)) {                            /* load */                            gen_ldst(ldl, s);                            if (i == 15) {                                gen_bx(s);                            } else if (user) {                                gen_op_movl_user_T0(i);                            } else if (i == rn) {                                gen_op_movl_T2_T0();                                loaded_base = 1;                            } else {                                gen_movl_reg_T0(s, i);                            }                        } else {                            /* store */                            if (i == 15) {                                /* special case: r15 = PC + 12 */                                val = (long)s->pc + 8;                                gen_op_movl_TN_im[0](val);                            } else if (user) {                                gen_op_movl_T0_user(i);                            } else {                                gen_movl_T0_reg(s, i);                            }                            gen_ldst(stl, s);                        }                        j++;                        /* no need to add after the last transfer */                        if (j != n)                            gen_op_addl_T1_im(4);                    }                }                if (insn & (1 << 21)) {                    /* write back */                    if (insn & (1 << 23)) {                        if (insn & (1 << 24)) {

⌨️ 快捷键说明

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