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 + -
显示快捷键?