Hello,
This patch contains the main changes. It contains modifcations to the target-i386/translate.c file.
Those modifications are meant to generate TCG instructions to maintain the correct value for the variables fpop, fpip, fpdp, fpds and fpcs in the cpu state.
Best regards,
Jaume
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 6fcd824..8e490de 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -58,6 +58,9 @@
#endif
//#define MACRO_TEST 1
+#define IS_PROTECTED_MODE(s) (s->pe && !s->vm86)
+#define FP_EP_VALID 0x80000000
+#define FP_EP_INVALID 0
/* global register indexes */
static TCGv_ptr cpu_env;
@@ -65,6 +68,11 @@ static TCGv cpu_A0;
static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_srcT;
static TCGv_i32 cpu_cc_op;
static TCGv cpu_regs[CPU_NB_REGS];
+static TCGv_i32 cpu_fpop;
+static TCGv cpu_fpip;
+static TCGv cpu_fpdp;
+static TCGv_i32 cpu_fpds;
+static TCGv_i32 cpu_fpcs;
/* local temps */
static TCGv cpu_T[2];
/* local register indexes (only used inside old micro ops) */
@@ -74,6 +82,9 @@ static TCGv_i32 cpu_tmp2_i32, cpu_tmp3_i32;
static TCGv_i64 cpu_tmp1_i64;
static uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
+static uint16_t gen_opc_fp_op[OPC_BUF_SIZE];
+static uint16_t gen_opc_fp_cs[OPC_BUF_SIZE];
+static target_ulong gen_opc_fp_ip[OPC_BUF_SIZE];
#include "exec/gen-icount.h"
@@ -104,6 +115,10 @@ typedef struct DisasContext {
int ss32; /* 32 bit stack segment */
CCOp cc_op; /* current CC operation */
bool cc_op_dirty;
+ uint16_t fp_op;
+ bool fp_ep_dirty;
+ target_ulong fp_ip;
+ uint16_t fp_cs;
int addseg; /* non zero if either DS/ES/SS have a non zero base */
int f_st; /* currently unused */
int vm86; /* vm86 mode */
@@ -208,6 +223,62 @@ static const uint8_t cc_op_live[CC_OP_NB] = {
[CC_OP_CLR] = 0,
};
+static inline bool instr_is_x87_nc(int modrm, int b)
+{
+ int op, mod, rm;
+ switch (b) {
+ case 0xd8 ... 0xdf:
+ /* floats */
+ op = ((b & 7) << 3) | ((modrm >> 3) & 7);
+ mod = (modrm >> 6) & 3;
+ rm = modrm & 7;
+ if (mod != 3) {
+ /* memory */
+ switch (op) {
+ case 0x0c: /* fldenv */
+ case 0x0d: /* fldcw */
+ case 0x0e: /* fstenv, fnstenv */
+ case 0x0f: /* fstcw, fnstcw */
+ case 0x2c: /* frstor */
+ case 0x2e: /* fsave, fnsave */
+ case 0x2f: /* fstsw, fnstsw */
+ return false;
+ default:
+ return true;
+ }
+ } else {
+ /* register */
+ switch (op) {
+ case 0x0a:
+ return false; /* fnop, Illegal op */
+ case 0x0e: /* fdecstp, fincstp */
+ case 0x28: /* ffree */
+ return false;
+ case 0x1c:
+ switch (rm) {
+ case 1: /* feni */
+ return true;
+ case 2: /* fclex, fnclex */
+ case 3: /* finit, fninit */
+ return false;
+ case 4: /* fsetpm */
+ return true;
+ default: /* Illegal op */
+ return false;
+ }
+ case 0x3c:
+ return false; /* fstsw, fnstsw, Illegal op */
+ default:
+ return true;
+ }
+ }
+ /*case 0x9b: // fwait, wait
+ return false;*/
+ default:
+ return false;
+ }
+}
+
static void set_cc_op(DisasContext *s, CCOp op)
{
int dead;
@@ -253,6 +324,23 @@ static void gen_update_cc_op(DisasContext *s)
}
}
+static void set_ep(DisasContext *s, int fp_op, int fp_ip, int fp_cs) {
+ s->fp_op = FP_EP_VALID | fp_op;
+ s->fp_ip = fp_ip;
+ s->fp_cs = fp_cs;
+ s->fp_ep_dirty = true;
+}
+
+static void gen_update_ep(DisasContext *s)
+{
+ if (s->fp_ep_dirty) {
+ tcg_gen_movi_i32(cpu_fpop, s->fp_op);
+ tcg_gen_movi_tl(cpu_fpip, s->fp_ip);
+ tcg_gen_movi_i32(cpu_fpcs, s->fp_cs);
+ s->fp_ep_dirty = false;
+ }
+}
+
#ifdef TARGET_X86_64
#define NB_OP_SIZES 4
@@ -666,6 +754,7 @@ static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip,
state_saved = 0;
if (s->pe && (s->cpl > s->iopl || s->vm86)) {
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(cur_eip);
state_saved = 1;
tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
@@ -686,6 +775,7 @@ static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip,
if(s->flags & HF_SVMI_MASK) {
if (!state_saved) {
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(cur_eip);
}
svm_flags |= (1 << (4 + ot));
@@ -1097,6 +1187,7 @@ static inline void gen_jcc1(DisasContext *s, int b, int l1)
CCPrepare cc = gen_prepare_cc(s, b, cpu_T[0]);
gen_update_cc_op(s);
+ gen_update_ep(s);
if (cc.mask != -1) {
tcg_gen_andi_tl(cpu_T[0], cc.reg, cc.mask);
cc.reg = cpu_T[0];
@@ -1580,14 +1671,14 @@ static void gen_rot_rm_T1(DisasContext *s, TCGMemOp ot, int op1, int is_right)
t0 = tcg_const_i32(0);
t1 = tcg_temp_new_i32();
tcg_gen_trunc_tl_i32(t1, cpu_T[1]);
- tcg_gen_movi_i32(cpu_tmp2_i32, CC_OP_ADCOX);
+ tcg_gen_movi_i32(cpu_tmp2_i32, CC_OP_ADCOX);
tcg_gen_movi_i32(cpu_tmp3_i32, CC_OP_EFLAGS);
tcg_gen_movcond_i32(TCG_COND_NE, cpu_cc_op, t1, t0,
cpu_tmp2_i32, cpu_tmp3_i32);
tcg_temp_free_i32(t0);
tcg_temp_free_i32(t1);
- /* The CC_OP value is no longer predictable. */
+ /* The CC_OP value is no longer predictable. */
set_cc_op(s, CC_OP_DYNAMIC);
}
@@ -1863,7 +1954,7 @@ static void gen_shifti(DisasContext *s1, int op, TCGMemOp ot, int d, int c)
}
}
-static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
+static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm, int b)
{
target_long disp;
int havesib;
@@ -1871,6 +1962,7 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
int index;
int scale;
int mod, rm, code, override, must_add_seg;
+ int curr_instr_is_x87_nc;
TCGv sum;
override = s->override;
@@ -1950,6 +2042,13 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
tcg_gen_addi_tl(cpu_A0, sum, disp);
}
+ curr_instr_is_x87_nc = instr_is_x87_nc(modrm, b);
+ if (curr_instr_is_x87_nc) {
+ tcg_gen_mov_tl(cpu_fpdp, cpu_A0);
+ if (s->aflag == MO_32) {
+ tcg_gen_ext32u_tl(cpu_fpdp, cpu_fpdp);
+ }
+ }
if (must_add_seg) {
if (override < 0) {
if (base == R_EBP || base == R_ESP) {
@@ -1961,6 +2060,12 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
tcg_gen_ld_tl(cpu_tmp0, cpu_env,
offsetof(CPUX86State, segs[override].base));
+
+ if (curr_instr_is_x87_nc) {
+ tcg_gen_ld_i32(cpu_fpds, cpu_env,
+ offsetof(CPUX86State, segs[override].selector));
+ }
+
if (CODE64(s)) {
if (s->aflag == MO_32) {
tcg_gen_ext32u_tl(cpu_A0, cpu_A0);
@@ -1970,6 +2075,11 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
}
tcg_gen_add_tl(cpu_A0, cpu_A0, cpu_tmp0);
+ } else {
+ if (curr_instr_is_x87_nc) {
+ tcg_gen_ld_i32(cpu_fpds, cpu_env,
+ offsetof(CPUX86State, segs[R_DS].selector));
+ }
}
if (s->aflag == MO_32) {
@@ -2039,8 +2149,22 @@ static void gen_lea_modrm(CPUX86State *env, DisasContext *s, int modrm)
override = R_DS;
}
}
+ if (instr_is_x87_nc(modrm, b)) {
+ tcg_gen_mov_tl(cpu_fpdp, cpu_A0);
+ tcg_gen_ld_i32(cpu_fpds, cpu_env,
+ offsetof(CPUX86State, segs[override].selector));
+ }
gen_op_addl_A0_seg(s, override);
+ } else {
+ if (instr_is_x87_nc(modrm, b)) {
+ tcg_gen_mov_tl(cpu_fpdp, cpu_A0);
+ tcg_gen_ld_i32(cpu_fpds, cpu_env,
+ offsetof(CPUX86State, segs[R_DS].selector));
+ }
}
+#ifdef TARGET_X86_64
+ tcg_gen_andi_tl(cpu_fpdp, cpu_fpdp, 0xffffffff);
+#endif
break;
default:
@@ -2130,7 +2254,7 @@ static void gen_add_A0_ds_seg(DisasContext *s)
/* generate modrm memory load or store of 'reg'. TMP0 is used if reg ==
OR_TMP0 */
static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm,
- TCGMemOp ot, int reg, int is_store)
+ TCGMemOp ot, int reg, int is_store, int b)
{
int mod, rm;
@@ -2297,6 +2421,7 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, target_ulong cur_eip)
if (s->pe && !s->vm86) {
/* XXX: optimize by finding processor state dynamically */
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(cur_eip);
tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
gen_helper_load_seg(cpu_env, tcg_const_i32(seg_reg), cpu_tmp2_i32);
@@ -2326,6 +2451,7 @@ gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start,
if (likely(!(s->flags & HF_SVMI_MASK)))
return;
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
gen_helper_svm_check_intercept_param(cpu_env, tcg_const_i32(type),
tcg_const_i64(param));
@@ -2513,6 +2639,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
static void gen_exception(DisasContext *s, int trapno, target_ulong cur_eip)
{
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(cur_eip);
gen_helper_raise_exception(cpu_env, tcg_const_i32(trapno));
s->is_jmp = DISAS_TB_JUMP;
@@ -2524,6 +2651,7 @@ static void gen_interrupt(DisasContext *s, int intno,
target_ulong cur_eip, target_ulong next_eip)
{
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(cur_eip);
gen_helper_raise_interrupt(cpu_env, tcg_const_i32(intno),
tcg_const_i32(next_eip - cur_eip));
@@ -2533,6 +2661,7 @@ static void gen_interrupt(DisasContext *s, int intno,
static void gen_debug(DisasContext *s, target_ulong cur_eip)
{
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(cur_eip);
gen_helper_debug(cpu_env);
s->is_jmp = DISAS_TB_JUMP;
@@ -2543,6 +2672,7 @@ static void gen_debug(DisasContext *s, target_ulong cur_eip)
static void gen_eob(DisasContext *s)
{
gen_update_cc_op(s);
+ gen_update_ep(s);
if (s->tb->flags & HF_INHIBIT_IRQ_MASK) {
gen_helper_reset_inhibit_irq(cpu_env);
}
@@ -2564,6 +2694,7 @@ static void gen_eob(DisasContext *s)
static void gen_jmp_tb(DisasContext *s, target_ulong eip, int tb_num)
{
gen_update_cc_op(s);
+ gen_update_ep(s);
set_cc_op(s, CC_OP_DYNAMIC);
if (s->jmp_opt) {
gen_goto_tb(s, tb_num, eip);
@@ -4404,6 +4535,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
int modrm, reg, rm, mod, op, opreg, val;
target_ulong next_eip, tval;
int rex_w, rex_r;
+ int fp_op, fp_ip, fp_cs;
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
tcg_gen_debug_insn_start(pc_start);
@@ -4946,6 +5078,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
do_lcall:
if (s->pe && !s->vm86) {
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
gen_helper_lcall_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
@@ -4973,6 +5106,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
do_ljmp:
if (s->pe && !s->vm86) {
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
tcg_gen_trunc_tl_i32(cpu_tmp2_i32, cpu_T[0]);
gen_helper_ljmp_protected(cpu_env, cpu_tmp2_i32, cpu_T[1],
@@ -5832,7 +5966,9 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
case 0x0c: /* fldenv mem */
gen_update_cc_op(s);
gen_jmp_im(pc_start - s->cs_base);
- gen_helper_fldenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
+ gen_helper_fldenv(cpu_env, cpu_A0,
+ tcg_const_i32(dflag == MO_32),
+ tcg_const_i32(IS_PROTECTED_MODE(s)));
break;
case 0x0d: /* fldcw mem */
tcg_gen_qemu_ld_i32(cpu_tmp2_i32, cpu_A0,
@@ -5841,8 +5977,11 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
break;
case 0x0e: /* fnstenv mem */
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
- gen_helper_fstenv(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
+ gen_helper_fstenv(cpu_env, cpu_A0,
+ tcg_const_i32(dflag == MO_32),
+ tcg_const_i32(IS_PROTECTED_MODE(s)));
break;
case 0x0f: /* fnstcw mem */
gen_helper_fnstcw(cpu_tmp2_i32, cpu_env);
@@ -5863,12 +6002,17 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
case 0x2c: /* frstor mem */
gen_update_cc_op(s);
gen_jmp_im(pc_start - s->cs_base);
- gen_helper_frstor(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
+ gen_helper_frstor(cpu_env, cpu_A0,
+ tcg_const_i32(dflag == MO_32),
+ tcg_const_i32(IS_PROTECTED_MODE(s)));
break;
case 0x2e: /* fnsave mem */
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
- gen_helper_fsave(cpu_env, cpu_A0, tcg_const_i32(dflag - 1));
+ gen_helper_fsave(cpu_env, cpu_A0,
+ tcg_const_i32(dflag == MO_32),
+ tcg_const_i32(IS_PROTECTED_MODE(s)));
break;
case 0x2f: /* fnstsw mem */
gen_helper_fnstsw(cpu_tmp2_i32, cpu_env);
@@ -6209,6 +6353,12 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
goto illegal_op;
}
}
+ if (instr_is_x87_nc(modrm, b)) {
+ fp_op = ((b & 0x7) << 8) | (modrm & 0xff);
+ fp_ip = pc_start - s->cs_base;
+ fp_cs = env->segs[R_CS].selector;
+ set_ep(s, fp_op, fp_ip, fp_cs);
+ }
break;
/************************/
/* string ops */
@@ -6393,6 +6543,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
do_lret:
if (s->pe && !s->vm86) {
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
gen_helper_lret_protected(cpu_env, tcg_const_i32(dflag - 1),
tcg_const_i32(val));
@@ -6430,6 +6581,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
}
} else {
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
gen_helper_iret_protected(cpu_env, tcg_const_i32(dflag - 1),
tcg_const_i32(s->pc - s->cs_base));
@@ -6884,6 +7036,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
gen_exception(s, EXCP07_PREX, pc_start - s->cs_base);
} else {
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
gen_helper_fwait(cpu_env);
}
@@ -6903,6 +7056,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
if (CODE64(s))
goto illegal_op;
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
gen_helper_into(cpu_env, tcg_const_i32(s->pc - pc_start));
break;
@@ -7095,6 +7249,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
} else {
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
gen_helper_sysexit(cpu_env, tcg_const_i32(dflag - 1));
gen_eob(s);
@@ -7104,6 +7259,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
case 0x105: /* syscall */
/* XXX: is it usable in real mode ? */
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
gen_helper_syscall(cpu_env, tcg_const_i32(s->pc - pc_start));
gen_eob(s);
@@ -7113,6 +7269,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
} else {
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
gen_helper_sysret(cpu_env, tcg_const_i32(dflag - 1));
/* condition codes are modified only in long mode */
@@ -7133,6 +7290,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
} else {
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
gen_helper_hlt(cpu_env, tcg_const_i32(s->pc - pc_start));
s->is_jmp = DISAS_TB_JUMP;
@@ -7241,6 +7399,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
s->cpl != 0)
goto illegal_op;
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
gen_helper_mwait(cpu_env, tcg_const_i32(s->pc - pc_start));
gen_eob(s);
@@ -7446,6 +7606,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
if (!(s->cpuid_ext2_features & CPUID_EXT2_RDTSCP))
goto illegal_op;
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
if (use_icount)
gen_io_start();
@@ -7624,6 +7785,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
case 4:
case 8:
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(pc_start - s->cs_base);
if (b & 2) {
gen_op_mov_v_reg(ot, cpu_T[0], rm);
@@ -7704,6 +7866,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
op = (modrm >> 3) & 7;
switch(op) {
case 0: /* fxsave */
+ gen_update_ep(s);
if (mod == 3 || !(s->cpuid_features & CPUID_FXSR) ||
(s->prefix & PREFIX_LOCK))
goto illegal_op;
@@ -7783,6 +7951,7 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
if (!(s->flags & HF_SMM_MASK))
goto illegal_op;
gen_update_cc_op(s);
+ gen_update_ep(s);
gen_jmp_im(s->pc - s->cs_base);
gen_helper_rsm(cpu_env);
gen_eob(s);
@@ -7880,6 +8049,17 @@ void optimize_flags_init(void)
cpu_cc_src2 = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_src2),
"cc_src2");
+ cpu_fpop = tcg_global_mem_new_i32(TCG_AREG0,
+ offsetof(CPUX86State, fpop), "fpop");
+ cpu_fpip = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, fpip),
+ "fpip");
+ cpu_fpdp = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, fpdp),
+ "fpdp");
+ cpu_fpds = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUX86State, fpds),
+ "fpds");
+ cpu_fpcs = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUX86State, fpcs),
+ "fpcs");
+
for (i = 0; i < CPU_NB_REGS; ++i) {
cpu_regs[i] = tcg_global_mem_new(TCG_AREG0,
offsetof(CPUX86State, regs[i]),
@@ -7924,6 +8104,8 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
dc->singlestep_enabled = cs->singlestep_enabled;
dc->cc_op = CC_OP_DYNAMIC;
dc->cc_op_dirty = false;
+ dc->fp_op = FP_EP_INVALID;
+ dc->fp_ep_dirty = false;
dc->cs_base = cs_base;
dc->tb = tb;
dc->popl_esp_hack = 0;
@@ -7997,6 +8179,9 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
}
tcg_ctx.gen_opc_pc[lj] = pc_ptr;
gen_opc_cc_op[lj] = dc->cc_op;
+ gen_opc_fp_op[lj] = dc->fp_op;
+ gen_opc_fp_ip[lj] = dc->fp_ip;
+ gen_opc_fp_cs[lj] = dc->fp_cs;
tcg_ctx.gen_opc_instr_start[lj] = 1;
tcg_ctx.gen_opc_icount[lj] = num_insns;
}
@@ -8080,6 +8265,7 @@ void gen_intermediate_code_pc(CPUX86State *env, TranslationBlock *tb)
void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
{
int cc_op;
+ uint16_t fp_op;
#ifdef DEBUG_DISAS
if (qemu_loglevel_mask(CPU_LOG_TB_OP)) {
int i;
@@ -8099,4 +8285,10 @@ void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, int pc_pos)
cc_op = gen_opc_cc_op[pc_pos];
if (cc_op != CC_OP_DYNAMIC)
env->cc_op = cc_op;
+ fp_op = gen_opc_fp_op[pc_pos];
+ if (fp_op & FP_EP_VALID) {
+ tcg_gen_movi_i32(cpu_fpop, fp_op);
+ tcg_gen_movi_tl(cpu_fpip, gen_opc_fp_ip[pc_pos]);
+ tcg_gen_movi_i32(cpu_fpcs, gen_opc_fp_cs[pc_pos]);
+ }
}