translate.c

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

C
2,286
字号
/* T0 &= ~T1.  Clobbers T1.  *//* FIXME: Implement bic natively.  */static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1){    TCGv tmp = new_tmp();    tcg_gen_not_i32(tmp, t1);    tcg_gen_and_i32(dest, t0, tmp);    dead_tmp(tmp);}static inline void gen_op_bicl_T0_T1(void){    gen_op_notl_T1();    gen_op_andl_T0_T1();}/* FIXME:  Implement this natively.  */#define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)/* FIXME:  Implement this natively.  */static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i){    TCGv tmp;    if (i == 0)        return;    tmp = new_tmp();    tcg_gen_shri_i32(tmp, t1, i);    tcg_gen_shli_i32(t1, t1, 32 - i);    tcg_gen_or_i32(t0, t1, tmp);    dead_tmp(tmp);}static void shifter_out_im(TCGv var, int shift){    TCGv tmp = new_tmp();    if (shift == 0) {        tcg_gen_andi_i32(tmp, var, 1);    } else {        tcg_gen_shri_i32(tmp, var, shift);        if (shift != 31);            tcg_gen_andi_i32(tmp, tmp, 1);    }    gen_set_CF(tmp);    dead_tmp(tmp);}/* Shift by immediate.  Includes special handling for shift == 0.  */static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags){    switch (shiftop) {    case 0: /* LSL */        if (shift != 0) {            if (flags)                shifter_out_im(var, 32 - shift);            tcg_gen_shli_i32(var, var, shift);        }        break;    case 1: /* LSR */        if (shift == 0) {            if (flags) {                tcg_gen_shri_i32(var, var, 31);                gen_set_CF(var);            }            tcg_gen_movi_i32(var, 0);        } else {            if (flags)                shifter_out_im(var, shift - 1);            tcg_gen_shri_i32(var, var, shift);        }        break;    case 2: /* ASR */        if (shift == 0)            shift = 32;        if (flags)            shifter_out_im(var, shift - 1);        if (shift == 32)          shift = 31;        tcg_gen_sari_i32(var, var, shift);        break;    case 3: /* ROR/RRX */        if (shift != 0) {            if (flags)                shifter_out_im(var, shift - 1);            tcg_gen_rori_i32(var, var, shift); break;        } else {            TCGv tmp = load_cpu_field(CF);            if (flags)                shifter_out_im(var, 0);            tcg_gen_shri_i32(var, var, 1);            tcg_gen_shli_i32(tmp, tmp, 31);            tcg_gen_or_i32(var, var, tmp);            dead_tmp(tmp);        }    }};static inline void gen_arm_shift_reg(TCGv var, int shiftop,                                     TCGv shift, int flags){    if (flags) {        switch (shiftop) {        case 0: gen_helper_shl_cc(var, var, shift); break;        case 1: gen_helper_shr_cc(var, var, shift); break;        case 2: gen_helper_sar_cc(var, var, shift); break;        case 3: gen_helper_ror_cc(var, var, shift); break;        }    } else {        switch (shiftop) {        case 0: gen_helper_shl(var, var, shift); break;        case 1: gen_helper_shr(var, var, shift); break;        case 2: gen_helper_sar(var, var, shift); break;        case 3: gen_helper_ror(var, var, shift); break;        }    }    dead_tmp(shift);}#define PAS_OP(pfx) \    switch (op2) {  \    case 0: gen_pas_helper(glue(pfx,add16)); break; \    case 1: gen_pas_helper(glue(pfx,addsubx)); break; \    case 2: gen_pas_helper(glue(pfx,subaddx)); break; \    case 3: gen_pas_helper(glue(pfx,sub16)); break; \    case 4: gen_pas_helper(glue(pfx,add8)); break; \    case 7: gen_pas_helper(glue(pfx,sub8)); break; \    }static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b){    TCGv tmp;    switch (op1) {#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)    case 1:        tmp = tcg_temp_new(TCG_TYPE_PTR);        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));        PAS_OP(s)        break;    case 5:        tmp = tcg_temp_new(TCG_TYPE_PTR);        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));        PAS_OP(u)        break;#undef gen_pas_helper#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)    case 2:        PAS_OP(q);        break;    case 3:        PAS_OP(sh);        break;    case 6:        PAS_OP(uq);        break;    case 7:        PAS_OP(uh);        break;#undef gen_pas_helper    }}#undef PAS_OP/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings.  */#define PAS_OP(pfx) \    switch (op2) {  \    case 0: gen_pas_helper(glue(pfx,add8)); break; \    case 1: gen_pas_helper(glue(pfx,add16)); break; \    case 2: gen_pas_helper(glue(pfx,addsubx)); break; \    case 4: gen_pas_helper(glue(pfx,sub8)); break; \    case 5: gen_pas_helper(glue(pfx,sub16)); break; \    case 6: gen_pas_helper(glue(pfx,subaddx)); break; \    }static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b){    TCGv tmp;    switch (op1) {#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)    case 0:        tmp = tcg_temp_new(TCG_TYPE_PTR);        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));        PAS_OP(s)        break;    case 4:        tmp = tcg_temp_new(TCG_TYPE_PTR);        tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));        PAS_OP(u)        break;#undef gen_pas_helper#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)    case 1:        PAS_OP(q);        break;    case 2:        PAS_OP(sh);        break;    case 5:        PAS_OP(uq);        break;    case 6:        PAS_OP(uh);        break;#undef gen_pas_helper    }}#undef PAS_OPstatic void gen_test_cc(int cc, int label){    TCGv tmp;    TCGv tmp2;    TCGv zero;    int inv;    zero = tcg_const_i32(0);    switch (cc) {    case 0: /* eq: Z */        tmp = load_cpu_field(ZF);        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);        break;    case 1: /* ne: !Z */        tmp = load_cpu_field(ZF);        tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);        break;    case 2: /* cs: C */        tmp = load_cpu_field(CF);        tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);        break;    case 3: /* cc: !C */        tmp = load_cpu_field(CF);        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);        break;    case 4: /* mi: N */        tmp = load_cpu_field(NF);        tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);        break;    case 5: /* pl: !N */        tmp = load_cpu_field(NF);        tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);        break;    case 6: /* vs: V */        tmp = load_cpu_field(VF);        tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);        break;    case 7: /* vc: !V */        tmp = load_cpu_field(VF);        tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);        break;    case 8: /* hi: C && !Z */        inv = gen_new_label();        tmp = load_cpu_field(CF);        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv);        dead_tmp(tmp);        tmp = load_cpu_field(ZF);        tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label);        gen_set_label(inv);        break;    case 9: /* ls: !C || Z */        tmp = load_cpu_field(CF);        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);        dead_tmp(tmp);        tmp = load_cpu_field(ZF);        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);        break;    case 10: /* ge: N == V -> N ^ V == 0 */        tmp = load_cpu_field(VF);        tmp2 = load_cpu_field(NF);        tcg_gen_xor_i32(tmp, tmp, tmp2);        dead_tmp(tmp2);        tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);        break;    case 11: /* lt: N != V -> N ^ V != 0 */        tmp = load_cpu_field(VF);        tmp2 = load_cpu_field(NF);        tcg_gen_xor_i32(tmp, tmp, tmp2);        dead_tmp(tmp2);        tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);        break;    case 12: /* gt: !Z && N == V */        inv = gen_new_label();        tmp = load_cpu_field(ZF);        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv);        dead_tmp(tmp);        tmp = load_cpu_field(VF);        tmp2 = load_cpu_field(NF);        tcg_gen_xor_i32(tmp, tmp, tmp2);        dead_tmp(tmp2);        tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label);        gen_set_label(inv);        break;    case 13: /* le: Z || N != V */        tmp = load_cpu_field(ZF);        tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label);        dead_tmp(tmp);        tmp = load_cpu_field(VF);        tmp2 = load_cpu_field(NF);        tcg_gen_xor_i32(tmp, tmp, tmp2);        dead_tmp(tmp2);        tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label);        break;    default:        fprintf(stderr, "Bad condition code 0x%x\n", cc);        abort();    }    dead_tmp(tmp);}const uint8_t table_logic_cc[16] = {    1, /* and */    1, /* xor */    0, /* sub */    0, /* rsb */    0, /* add */    0, /* adc */    0, /* sbc */    0, /* rsc */    1, /* andl */    1, /* xorl */    0, /* cmp */    0, /* cmn */    1, /* orr */    1, /* mov */    1, /* bic */    1, /* mvn */};/* Set PC and Thumb state from an immediate address.  */static inline void gen_bx_im(DisasContext *s, uint32_t addr){    TCGv tmp;    s->is_jmp = DISAS_UPDATE;    tmp = new_tmp();    if (s->thumb != (addr & 1)) {        tcg_gen_movi_i32(tmp, addr & 1);        tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));    }    tcg_gen_movi_i32(tmp, addr & ~1);    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[15]));    dead_tmp(tmp);}/* Set PC and Thumb state from var.  var is marked as dead.  */static inline void gen_bx(DisasContext *s, TCGv var){    TCGv tmp;    s->is_jmp = DISAS_UPDATE;    tmp = new_tmp();    tcg_gen_andi_i32(tmp, var, 1);    store_cpu_field(tmp, thumb);    tcg_gen_andi_i32(var, var, ~1);    store_cpu_field(var, regs[15]);}/* TODO: This should be removed.  Use gen_bx instead.  */static inline void gen_bx_T0(DisasContext *s){    TCGv tmp = new_tmp();    tcg_gen_mov_i32(tmp, cpu_T[0]);    gen_bx(s, tmp);}#if defined(CONFIG_USER_ONLY)#define gen_ldst(name, s) gen_op_##name##_raw()#else#define gen_ldst(name, s) do { \    s->is_mem = 1; \    if (IS_USER(s)) \        gen_op_##name##_user(); \    else \        gen_op_##name##_kernel(); \    } while (0)#endifstatic inline TCGv gen_ld8s(TCGv addr, int index){    TCGv tmp = new_tmp();    tcg_gen_qemu_ld8s(tmp, addr, index);    return tmp;}static inline TCGv gen_ld8u(TCGv addr, int index){    TCGv tmp = new_tmp();    tcg_gen_qemu_ld8u(tmp, addr, index);    return tmp;}static inline TCGv gen_ld16s(TCGv addr, int index){    TCGv tmp = new_tmp();    tcg_gen_qemu_ld16s(tmp, addr, index);    return tmp;}static inline TCGv gen_ld16u(TCGv addr, int index){    TCGv tmp = new_tmp();    tcg_gen_qemu_ld16u(tmp, addr, index);    return tmp;}static inline TCGv gen_ld32(TCGv addr, int index){    TCGv tmp = new_tmp();    tcg_gen_qemu_ld32u(tmp, addr, index);    return tmp;}static inline void gen_st8(TCGv val, TCGv addr, int index){    tcg_gen_qemu_st8(val, addr, index);    dead_tmp(val);}static inline void gen_st16(TCGv val, TCGv addr, int index){    tcg_gen_qemu_st16(val, addr, index);    dead_tmp(val);}static inline void gen_st32(TCGv val, TCGv addr, int index){    tcg_gen_qemu_st32(val, addr, index);    dead_tmp(val);}static inline void gen_movl_T0_reg(DisasContext *s, int reg){    load_reg_var(s, cpu_T[0], reg);}static inline void gen_movl_T1_reg(DisasContext *s, int reg){    load_reg_var(s, cpu_T[1], reg);}static inline void gen_movl_T2_reg(DisasContext *s, int reg){    load_reg_var(s, cpu_T[2], reg);}static inline void gen_set_pc_im(uint32_t val){    TCGv tmp = new_tmp();    tcg_gen_movi_i32(tmp, val);    store_cpu_field(tmp, regs[15]);}static inline void gen_movl_reg_TN(DisasContext *s, int reg, int t){    TCGv tmp;    if (reg == 15) {        tmp = new_tmp();        tcg_gen_andi_i32(tmp, cpu_T[t], ~1);    } else {        tmp = cpu_T[t];    }    tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[reg]));    if (reg == 15) {        dead_tmp(tmp);        s->is_jmp = DISAS_JUMP;    }}

⌨️ 快捷键说明

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