translate.c
来自「xen虚拟机源代码安装包」· C语言 代码 · 共 2,711 行 · 第 1/5 页
C
2,711 行
*/static inline void t_gen_swapr(TCGv d, TCGv s){ struct { int shift; /* LSL when positive, LSR when negative. */ uint32_t mask; } bitrev [] = { {7, 0x80808080}, {5, 0x40404040}, {3, 0x20202020}, {1, 0x10101010}, {-1, 0x08080808}, {-3, 0x04040404}, {-5, 0x02020202}, {-7, 0x01010101} }; int i; TCGv t, org_s; /* d and s refer the same object. */ t = tcg_temp_new(TCG_TYPE_TL); org_s = tcg_temp_new(TCG_TYPE_TL); tcg_gen_mov_tl(org_s, s); tcg_gen_shli_tl(t, org_s, bitrev[0].shift); tcg_gen_andi_tl(d, t, bitrev[0].mask); for (i = 1; i < sizeof bitrev / sizeof bitrev[0]; i++) { if (bitrev[i].shift >= 0) { tcg_gen_shli_tl(t, org_s, bitrev[i].shift); } else { tcg_gen_shri_tl(t, org_s, -bitrev[i].shift); } tcg_gen_andi_tl(t, t, bitrev[i].mask); tcg_gen_or_tl(d, d, t); } tcg_gen_discard_tl(t); tcg_gen_discard_tl(org_s);}static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false){ TCGv btaken; int l1; l1 = gen_new_label(); btaken = tcg_temp_new(TCG_TYPE_TL); /* Conditional jmp. */ t_gen_mov_TN_env(btaken, btaken); tcg_gen_mov_tl(env_pc, pc_false); tcg_gen_brcond_tl(TCG_COND_EQ, btaken, tcg_const_tl(0), l1); tcg_gen_mov_tl(env_pc, pc_true); gen_set_label(l1); tcg_gen_discard_tl(btaken);}static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest){ TranslationBlock *tb; tb = dc->tb; if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) { tcg_gen_goto_tb(n); tcg_gen_movi_tl(env_pc, dest); tcg_gen_exit_tb((long)tb + n); } else { tcg_gen_mov_tl(env_pc, cpu_T[0]); tcg_gen_exit_tb(0); }}/* Sign extend at translation time. */static int sign_extend(unsigned int val, unsigned int width){ int sval; /* LSL. */ val <<= 31 - width; sval = val; /* ASR. */ sval >>= 31 - width; return sval;}static inline void cris_clear_x_flag(DisasContext *dc){ if (!dc->flagx_live || (dc->flagx_live && dc->flags_x) || dc->cc_op == CC_OP_FLAGS) tcg_gen_andi_i32(cpu_PR[PR_CCS], cpu_PR[PR_CCS], ~X_FLAG); dc->flagx_live = 1; dc->flags_x = 0;}static void cris_evaluate_flags(DisasContext *dc){ if (!dc->flags_live) { tcg_gen_movi_tl(cc_op, dc->cc_op); tcg_gen_movi_tl(cc_size, dc->cc_size); tcg_gen_movi_tl(cc_mask, dc->cc_mask); switch (dc->cc_op) { case CC_OP_MCP: tcg_gen_helper_0_0(helper_evaluate_flags_mcp); break; case CC_OP_MULS: tcg_gen_helper_0_0(helper_evaluate_flags_muls); break; case CC_OP_MULU: tcg_gen_helper_0_0(helper_evaluate_flags_mulu); break; case CC_OP_MOVE: switch (dc->cc_size) { case 4: tcg_gen_helper_0_0(helper_evaluate_flags_move_4); break; case 2: tcg_gen_helper_0_0(helper_evaluate_flags_move_2); break; default: tcg_gen_helper_0_0(helper_evaluate_flags); break; } break; case CC_OP_FLAGS: /* live. */ break; default: { switch (dc->cc_size) { case 4: tcg_gen_helper_0_0(helper_evaluate_flags_alu_4); break; default: tcg_gen_helper_0_0(helper_evaluate_flags); break; } } break; } dc->flags_live = 1; }}static void cris_cc_mask(DisasContext *dc, unsigned int mask){ uint32_t ovl; /* Check if we need to evaluate the condition codes due to CC overlaying. */ ovl = (dc->cc_mask ^ mask) & ~mask; if (ovl) { /* TODO: optimize this case. It trigs all the time. */ cris_evaluate_flags (dc); } dc->cc_mask = mask; dc->update_cc = 1; if (mask == 0) dc->update_cc = 0; else dc->flags_live = 0;}static void cris_update_cc_op(DisasContext *dc, int op, int size){ dc->cc_op = op; dc->cc_size = size; dc->flags_live = 0;}/* op is the operation. T0, T1 are the operands. dst is the destination reg.*/static void crisv32_alu_op(DisasContext *dc, int op, int rd, int size){ int writeback = 1; if (dc->update_cc) { cris_update_cc_op(dc, op, size); if (op != CC_OP_MOVE) tcg_gen_mov_tl(cc_dest, cpu_T[0]); /* FIXME: This shouldn't be needed. But we don't pass the tests without it. Investigate. */ t_gen_mov_env_TN(cc_x_live, tcg_const_tl(dc->flagx_live)); t_gen_mov_env_TN(cc_x, tcg_const_tl(dc->flags_x)); } /* Emit the ALU insns. */ switch (op) { case CC_OP_ADD: tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); /* Extended arithmetics. */ t_gen_addx_carry(cpu_T[0]); break; case CC_OP_ADDC: tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); t_gen_add_flag(cpu_T[0], 0); /* C_FLAG. */ break; case CC_OP_MCP: tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); t_gen_add_flag(cpu_T[0], 8); /* R_FLAG. */ break; case CC_OP_SUB: tcg_gen_neg_tl(cpu_T[1], cpu_T[1]); tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]); tcg_gen_neg_tl(cpu_T[1], cpu_T[1]); /* CRIS flag evaluation needs ~src. */ tcg_gen_xori_tl(cpu_T[1], cpu_T[1], -1); /* Extended arithmetics. */ t_gen_subx_carry(dc, cpu_T[0]); break; case CC_OP_MOVE: tcg_gen_mov_tl(cpu_T[0], cpu_T[1]); break; case CC_OP_OR: tcg_gen_or_tl(cpu_T[0], cpu_T[0], cpu_T[1]); break; case CC_OP_AND: tcg_gen_and_tl(cpu_T[0], cpu_T[0], cpu_T[1]); break; case CC_OP_XOR: tcg_gen_xor_tl(cpu_T[0], cpu_T[0], cpu_T[1]); break; case CC_OP_LSL: t_gen_lsl(cpu_T[0], cpu_T[0], cpu_T[1]); break; case CC_OP_LSR: t_gen_lsr(cpu_T[0], cpu_T[0], cpu_T[1]); break; case CC_OP_ASR: t_gen_asr(cpu_T[0], cpu_T[0], cpu_T[1]); break; case CC_OP_NEG: tcg_gen_neg_tl(cpu_T[0], cpu_T[1]); /* Extended arithmetics. */ t_gen_subx_carry(dc, cpu_T[0]); break; case CC_OP_LZ: t_gen_lz_i32(cpu_T[0], cpu_T[1]); break; case CC_OP_BTST: t_gen_btst(cpu_T[0], cpu_T[1]); writeback = 0; break; case CC_OP_MULS: { TCGv mof; mof = tcg_temp_new(TCG_TYPE_TL); t_gen_muls(cpu_T[0], mof, cpu_T[0], cpu_T[1]); t_gen_mov_preg_TN(dc, PR_MOF, mof); tcg_gen_discard_tl(mof); } break; case CC_OP_MULU: { TCGv mof; mof = tcg_temp_new(TCG_TYPE_TL); t_gen_mulu(cpu_T[0], mof, cpu_T[0], cpu_T[1]); t_gen_mov_preg_TN(dc, PR_MOF, mof); tcg_gen_discard_tl(mof); } break; case CC_OP_DSTEP: t_gen_cris_dstep(cpu_T[0], cpu_T[1]); break; case CC_OP_BOUND: { int l1; l1 = gen_new_label(); tcg_gen_brcond_tl(TCG_COND_LEU, cpu_T[0], cpu_T[1], l1); tcg_gen_mov_tl(cpu_T[0], cpu_T[1]); gen_set_label(l1); } break; case CC_OP_CMP: tcg_gen_sub_tl(cpu_T[0], cpu_T[0], cpu_T[1]); /* CRIS flag evaluation needs ~src. */ tcg_gen_xori_tl(cpu_T[1], cpu_T[1], ~0); /* Extended arithmetics. */ t_gen_subx_carry(dc, cpu_T[0]); writeback = 0; break; default: fprintf (logfile, "illegal ALU op.\n"); BUG(); break; } if (dc->update_cc) tcg_gen_mov_tl(cc_src, cpu_T[1]); if (size == 1) tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xff); else if (size == 2) tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 0xffff); /* Writeback. */ if (writeback) { if (size == 4) tcg_gen_mov_tl(cpu_R[rd], cpu_T[0]); else { if (size == 1) tcg_gen_andi_tl(cpu_R[rd], cpu_R[rd], ~0xff); else tcg_gen_andi_tl(cpu_R[rd], cpu_R[rd], ~0xffff); tcg_gen_or_tl(cpu_R[rd], cpu_R[rd], cpu_T[0]); } } if (dc->update_cc) tcg_gen_mov_tl(cc_result, cpu_T[0]);}static int arith_cc(DisasContext *dc){ if (dc->update_cc) { switch (dc->cc_op) { case CC_OP_ADD: return 1; case CC_OP_SUB: return 1; case CC_OP_LSL: return 1; case CC_OP_LSR: return 1; case CC_OP_ASR: return 1; case CC_OP_CMP: return 1; default: return 0; } } return 0;}static void gen_tst_cc (DisasContext *dc, int cond){ int arith_opt; /* TODO: optimize more condition codes. */ /* * If the flags are live, we've gotta look into the bits of CCS. * Otherwise, if we just did an arithmetic operation we try to * evaluate the condition code faster. * * When this function is done, T0 should be non-zero if the condition * code is true. */ arith_opt = arith_cc(dc) && !dc->flags_live; switch (cond) { case CC_EQ: if (arith_opt) { /* If cc_result is zero, T0 should be non-zero otherwise T0 should be zero. */ int l1; l1 = gen_new_label(); tcg_gen_movi_tl(cpu_T[0], 0); tcg_gen_brcond_tl(TCG_COND_NE, cc_result, tcg_const_tl(0), l1); tcg_gen_movi_tl(cpu_T[0], 1); gen_set_label(l1); } else { cris_evaluate_flags(dc); tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], Z_FLAG); } break; case CC_NE: if (arith_opt) tcg_gen_mov_tl(cpu_T[0], cc_result); else { cris_evaluate_flags(dc); tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS], Z_FLAG); tcg_gen_andi_tl(cpu_T[0], cpu_T[0], Z_FLAG); } break; case CC_CS: cris_evaluate_flags(dc); tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], C_FLAG); break; case CC_CC: cris_evaluate_flags(dc); tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS], C_FLAG); tcg_gen_andi_tl(cpu_T[0], cpu_T[0], C_FLAG); break; case CC_VS: cris_evaluate_flags(dc); tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], V_FLAG); break; case CC_VC: cris_evaluate_flags(dc); tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS], V_FLAG); tcg_gen_andi_tl(cpu_T[0], cpu_T[0], V_FLAG); break; case CC_PL: if (arith_opt) tcg_gen_shli_tl(cpu_T[0], cc_result, 31); else { cris_evaluate_flags(dc); tcg_gen_xori_tl(cpu_T[0], cpu_PR[PR_CCS], N_FLAG); tcg_gen_andi_tl(cpu_T[0], cpu_T[0], N_FLAG); } break; case CC_MI: if (arith_opt) { tcg_gen_shli_tl(cpu_T[0], cc_result, 31); tcg_gen_xori_tl(cpu_T[0], cpu_T[0], 1); } else { cris_evaluate_flags(dc); tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], N_FLAG); } break; case CC_LS: cris_evaluate_flags(dc); tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], C_FLAG | Z_FLAG); break; case CC_HI: cris_evaluate_flags(dc); { TCGv tmp; tmp = tcg_temp_new(TCG_TYPE_TL); tcg_gen_xori_tl(tmp, cpu_PR[PR_CCS], C_FLAG | Z_FLAG); /* Overlay the C flag on top of the Z. */ tcg_gen_shli_tl(cpu_T[0], tmp, 2); tcg_gen_and_tl(cpu_T[0], tmp, cpu_T[0]); tcg_gen_andi_tl(cpu_T[0], cpu_T[0], Z_FLAG); tcg_gen_discard_tl(tmp); } break; case CC_GE: cris_evaluate_flags(dc); /* Overlay the V flag on top of the N. */ tcg_gen_shli_tl(cpu_T[0], cpu_PR[PR_CCS], 2); tcg_gen_xor_tl(cpu_T[0], cpu_PR[PR_CCS], cpu_T[0]); tcg_gen_andi_tl(cpu_T[0], cpu_T[0], N_FLAG); tcg_gen_xori_tl(cpu_T[0], cpu_T[0], N_FLAG); break; case CC_LT: cris_evaluate_flags(dc); /* Overlay the V flag on top of the N. */ tcg_gen_shli_tl(cpu_T[0], cpu_PR[PR_CCS], 2); tcg_gen_xor_tl(cpu_T[0], cpu_PR[PR_CCS], cpu_T[0]); tcg_gen_andi_tl(cpu_T[0], cpu_T[0], N_FLAG); break; case CC_GT: cris_evaluate_flags(dc); { TCGv n, z; n = tcg_temp_new(TCG_TYPE_TL); z = tcg_temp_new(TCG_TYPE_TL); /* To avoid a shift we overlay everything on the V flag. */ tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2); tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1); /* invert Z. */ tcg_gen_xori_tl(z, z, 2); tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]); tcg_gen_xori_tl(n, n, 2); tcg_gen_and_tl(cpu_T[0], z, n); tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 2); tcg_gen_discard_tl(n); tcg_gen_discard_tl(z); } break; case CC_LE: cris_evaluate_flags(dc); { TCGv n, z; n = tcg_temp_new(TCG_TYPE_TL); z = tcg_temp_new(TCG_TYPE_TL); /* To avoid a shift we overlay everything on the V flag. */ tcg_gen_shri_tl(n, cpu_PR[PR_CCS], 2); tcg_gen_shri_tl(z, cpu_PR[PR_CCS], 1); tcg_gen_xor_tl(n, n, cpu_PR[PR_CCS]); tcg_gen_or_tl(cpu_T[0], z, n); tcg_gen_andi_tl(cpu_T[0], cpu_T[0], 2); tcg_gen_discard_tl(n); tcg_gen_discard_tl(z); } break; case CC_P: cris_evaluate_flags(dc); tcg_gen_andi_tl(cpu_T[0], cpu_PR[PR_CCS], P_FLAG); break; case CC_A: tcg_gen_movi_tl(cpu_T[0], 1); break; default: BUG(); break; };}static void cris_prepare_cc_branch (DisasContext *dc, int offset, int cond){ /* This helps us re-schedule the micro-code to insns in delay-slots before the actual jump. */ dc->delayed_branch = 2; if (cond != CC_A) { gen_tst_cc (dc, cond); t_gen_mov_env_TN(btaken, cpu_T[0]); } else t_gen_mov_env_TN(btaken, tcg_const_tl(1)); tcg_gen_movi_tl(env_btarget, dc->pc + offset);}/* Dynamic jumps, when the dest is in a live reg for example. */void cris_prepare_dyn_jmp (DisasContext *dc){ /* This helps us re-schedule the micro-code to insns in delay-slots before the actual jump. */ dc->delayed_branch = 2; t_gen_mov_env_TN(btaken, tcg_const_tl(1));}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?