📄 translate.c
字号:
}static inline void gen_movl_reg_TN(int reg, int t){ if (reg) gen_op_movl_reg_TN[t][reg] (); else gen_movl_imm_TN(t, 0);}static inline void gen_movl_reg_T0(int reg){ gen_movl_reg_TN(reg, 0);}static inline void gen_movl_reg_T1(int reg){ gen_movl_reg_TN(reg, 1);}static inline void gen_movl_reg_T2(int reg){ gen_movl_reg_TN(reg, 2);}static inline void gen_movl_TN_reg(int reg, int t){ if (reg) gen_op_movl_TN_reg[t][reg] ();}static inline void gen_movl_T0_reg(int reg){ gen_movl_TN_reg(reg, 0);}static inline void gen_movl_T1_reg(int reg){ gen_movl_TN_reg(reg, 1);}static inline void gen_jmp_im(target_ulong pc){#ifdef TARGET_SPARC64 if (pc == (uint32_t)pc) { gen_op_jmp_im(pc); } else { gen_op_jmp_im64(pc >> 32, pc); }#else gen_op_jmp_im(pc);#endif}static inline void gen_movl_npc_im(target_ulong npc){#ifdef TARGET_SPARC64 if (npc == (uint32_t)npc) { gen_op_movl_npc_im(npc); } else { gen_op_movq_npc_im64(npc >> 32, npc); }#else gen_op_movl_npc_im(npc);#endif}static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong pc, target_ulong npc){ TranslationBlock *tb; tb = s->tb; if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) && (npc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK)) { /* jump to same page: we can use a direct jump */ if (tb_num == 0) gen_op_goto_tb0(TBPARAM(tb)); else gen_op_goto_tb1(TBPARAM(tb)); gen_jmp_im(pc); gen_movl_npc_im(npc); gen_op_movl_T0_im((long)tb + tb_num); gen_op_exit_tb(); } else { /* jump to another page: currently not optimized */ gen_jmp_im(pc); gen_movl_npc_im(npc); gen_op_movl_T0_0(); gen_op_exit_tb(); }}static inline void gen_branch2(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2){ int l1; l1 = gen_new_label(); gen_op_jz_T2_label(l1); gen_goto_tb(dc, 0, pc1, pc1 + 4); gen_set_label(l1); gen_goto_tb(dc, 1, pc2, pc2 + 4);}static inline void gen_branch_a(DisasContext *dc, long tb, target_ulong pc1, target_ulong pc2){ int l1; l1 = gen_new_label(); gen_op_jz_T2_label(l1); gen_goto_tb(dc, 0, pc2, pc1); gen_set_label(l1); gen_goto_tb(dc, 1, pc2 + 4, pc2 + 8);}static inline void gen_branch(DisasContext *dc, long tb, target_ulong pc, target_ulong npc){ gen_goto_tb(dc, 0, pc, npc);}static inline void gen_generic_branch(DisasContext *dc, target_ulong npc1, target_ulong npc2){ int l1, l2; l1 = gen_new_label(); l2 = gen_new_label(); gen_op_jz_T2_label(l1); gen_movl_npc_im(npc1); gen_op_jmp_label(l2); gen_set_label(l1); gen_movl_npc_im(npc2); gen_set_label(l2);}/* call this function before using T2 as it may have been set for a jump */static inline void flush_T2(DisasContext * dc){ if (dc->npc == JUMP_PC) { gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]); dc->npc = DYNAMIC_PC; }}static inline void save_npc(DisasContext * dc){ if (dc->npc == JUMP_PC) { gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]); dc->npc = DYNAMIC_PC; } else if (dc->npc != DYNAMIC_PC) { gen_movl_npc_im(dc->npc); }}static inline void save_state(DisasContext * dc){ gen_jmp_im(dc->pc); save_npc(dc);}static inline void gen_mov_pc_npc(DisasContext * dc){ if (dc->npc == JUMP_PC) { gen_generic_branch(dc, dc->jump_pc[0], dc->jump_pc[1]); gen_op_mov_pc_npc(); dc->pc = DYNAMIC_PC; } else if (dc->npc == DYNAMIC_PC) { gen_op_mov_pc_npc(); dc->pc = DYNAMIC_PC; } else { dc->pc = dc->npc; }}static GenOpFunc * const gen_cond[2][16] = { { gen_op_eval_ba, gen_op_eval_be, gen_op_eval_ble, gen_op_eval_bl, gen_op_eval_bleu, gen_op_eval_bcs, gen_op_eval_bneg, gen_op_eval_bvs, gen_op_eval_bn, gen_op_eval_bne, gen_op_eval_bg, gen_op_eval_bge, gen_op_eval_bgu, gen_op_eval_bcc, gen_op_eval_bpos, gen_op_eval_bvc, }, {#ifdef TARGET_SPARC64 gen_op_eval_ba, gen_op_eval_xbe, gen_op_eval_xble, gen_op_eval_xbl, gen_op_eval_xbleu, gen_op_eval_xbcs, gen_op_eval_xbneg, gen_op_eval_xbvs, gen_op_eval_bn, gen_op_eval_xbne, gen_op_eval_xbg, gen_op_eval_xbge, gen_op_eval_xbgu, gen_op_eval_xbcc, gen_op_eval_xbpos, gen_op_eval_xbvc,#endif },};static GenOpFunc * const gen_fcond[4][16] = { { gen_op_eval_ba, gen_op_eval_fbne, gen_op_eval_fblg, gen_op_eval_fbul, gen_op_eval_fbl, gen_op_eval_fbug, gen_op_eval_fbg, gen_op_eval_fbu, gen_op_eval_bn, gen_op_eval_fbe, gen_op_eval_fbue, gen_op_eval_fbge, gen_op_eval_fbuge, gen_op_eval_fble, gen_op_eval_fbule, gen_op_eval_fbo, },#ifdef TARGET_SPARC64 { gen_op_eval_ba, gen_op_eval_fbne_fcc1, gen_op_eval_fblg_fcc1, gen_op_eval_fbul_fcc1, gen_op_eval_fbl_fcc1, gen_op_eval_fbug_fcc1, gen_op_eval_fbg_fcc1, gen_op_eval_fbu_fcc1, gen_op_eval_bn, gen_op_eval_fbe_fcc1, gen_op_eval_fbue_fcc1, gen_op_eval_fbge_fcc1, gen_op_eval_fbuge_fcc1, gen_op_eval_fble_fcc1, gen_op_eval_fbule_fcc1, gen_op_eval_fbo_fcc1, }, { gen_op_eval_ba, gen_op_eval_fbne_fcc2, gen_op_eval_fblg_fcc2, gen_op_eval_fbul_fcc2, gen_op_eval_fbl_fcc2, gen_op_eval_fbug_fcc2, gen_op_eval_fbg_fcc2, gen_op_eval_fbu_fcc2, gen_op_eval_bn, gen_op_eval_fbe_fcc2, gen_op_eval_fbue_fcc2, gen_op_eval_fbge_fcc2, gen_op_eval_fbuge_fcc2, gen_op_eval_fble_fcc2, gen_op_eval_fbule_fcc2, gen_op_eval_fbo_fcc2, }, { gen_op_eval_ba, gen_op_eval_fbne_fcc3, gen_op_eval_fblg_fcc3, gen_op_eval_fbul_fcc3, gen_op_eval_fbl_fcc3, gen_op_eval_fbug_fcc3, gen_op_eval_fbg_fcc3, gen_op_eval_fbu_fcc3, gen_op_eval_bn, gen_op_eval_fbe_fcc3, gen_op_eval_fbue_fcc3, gen_op_eval_fbge_fcc3, gen_op_eval_fbuge_fcc3, gen_op_eval_fble_fcc3, gen_op_eval_fbule_fcc3, gen_op_eval_fbo_fcc3, },#else {}, {}, {},#endif};#ifdef TARGET_SPARC64static void gen_cond_reg(int cond){ switch (cond) { case 0x1: gen_op_eval_brz(); break; case 0x2: gen_op_eval_brlez(); break; case 0x3: gen_op_eval_brlz(); break; case 0x5: gen_op_eval_brnz(); break; case 0x6: gen_op_eval_brgz(); break; default: case 0x7: gen_op_eval_brgez(); break; }}#endif/* XXX: potentially incorrect if dynamic npc */static void do_branch(DisasContext * dc, int32_t offset, uint32_t insn, int cc){ unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29)); target_ulong target = dc->pc + offset; if (cond == 0x0) { /* unconditional not taken */ if (a) { dc->pc = dc->npc + 4; dc->npc = dc->pc + 4; } else { dc->pc = dc->npc; dc->npc = dc->pc + 4; } } else if (cond == 0x8) { /* unconditional taken */ if (a) { dc->pc = target; dc->npc = dc->pc + 4; } else { dc->pc = dc->npc; dc->npc = target; } } else { flush_T2(dc); gen_cond[cc][cond](); if (a) { gen_branch_a(dc, (long)dc->tb, target, dc->npc); dc->is_br = 1; } else { dc->pc = dc->npc; dc->jump_pc[0] = target; dc->jump_pc[1] = dc->npc + 4; dc->npc = JUMP_PC; } }}/* XXX: potentially incorrect if dynamic npc */static void do_fbranch(DisasContext * dc, int32_t offset, uint32_t insn, int cc){ unsigned int cond = GET_FIELD(insn, 3, 6), a = (insn & (1 << 29)); target_ulong target = dc->pc + offset; if (cond == 0x0) { /* unconditional not taken */ if (a) { dc->pc = dc->npc + 4; dc->npc = dc->pc + 4; } else { dc->pc = dc->npc; dc->npc = dc->pc + 4; } } else if (cond == 0x8) { /* unconditional taken */ if (a) { dc->pc = target; dc->npc = dc->pc + 4; } else { dc->pc = dc->npc; dc->npc = target; } } else { flush_T2(dc); gen_fcond[cc][cond](); if (a) { gen_branch_a(dc, (long)dc->tb, target, dc->npc); dc->is_br = 1; } else { dc->pc = dc->npc; dc->jump_pc[0] = target; dc->jump_pc[1] = dc->npc + 4; dc->npc = JUMP_PC; } }}#ifdef TARGET_SPARC64/* XXX: potentially incorrect if dynamic npc */static void do_branch_reg(DisasContext * dc, int32_t offset, uint32_t insn){ unsigned int cond = GET_FIELD_SP(insn, 25, 27), a = (insn & (1 << 29)); target_ulong target = dc->pc + offset; flush_T2(dc); gen_cond_reg(cond); if (a) { gen_branch_a(dc, (long)dc->tb, target, dc->npc); dc->is_br = 1; } else { dc->pc = dc->npc; dc->jump_pc[0] = target; dc->jump_pc[1] = dc->npc + 4; dc->npc = JUMP_PC; }}static GenOpFunc * const gen_fcmps[4] = { gen_op_fcmps, gen_op_fcmps_fcc1, gen_op_fcmps_fcc2, gen_op_fcmps_fcc3,};static GenOpFunc * const gen_fcmpd[4] = { gen_op_fcmpd, gen_op_fcmpd_fcc1, gen_op_fcmpd_fcc2, gen_op_fcmpd_fcc3,};#endif/* before an instruction, dc->pc must be static */static void disas_sparc_insn(DisasContext * dc){ unsigned int insn, opc, rs1, rs2, rd; insn = ldl_code(dc->pc); opc = GET_FIELD(insn, 0, 1); rd = GET_FIELD(insn, 2, 6); switch (opc) { case 0: /* branches/sethi */ { unsigned int xop = GET_FIELD(insn, 7, 9); int32_t target; switch (xop) {#ifdef TARGET_SPARC64 case 0x1: /* V9 BPcc */ { int cc; target = GET_FIELD_SP(insn, 0, 18); target <<= 2; target = sign_extend(target, 18); cc = GET_FIELD_SP(insn, 20, 21); if (cc == 0) do_branch(dc, target, insn, 0); else if (cc == 2) do_branch(dc, target, insn, 1); else goto illegal_insn; goto jmp_insn; } case 0x3: /* V9 BPr */ { target = GET_FIELD_SP(insn, 0, 13) | (GET_FIELD_SP(insn, 20, 21) >> 7); target <<= 2; target = sign_extend(target, 16); rs1 = GET_FIELD(insn, 13, 17); gen_movl_reg_T0(rs1); do_branch_reg(dc, target, insn); goto jmp_insn; } case 0x5: /* V9 FBPcc */ { int cc = GET_FIELD_SP(insn, 20, 21);#if !defined(CONFIG_USER_ONLY) gen_op_trap_ifnofpu();#endif target = GET_FIELD_SP(insn, 0, 18); target <<= 2; target = sign_extend(target, 19); do_fbranch(dc, target, insn, cc); goto jmp_insn; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -