Commit d0a1ffc9573b15997ecdfbc9ec5ec2fc1403d0f1

Authored by bellard
1 parent df0f11a0

added fsave/frstor/fstenv/fldenv/fcomi - fixed cpuid - make lret/iret restartable


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@198 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-i386.h
@@ -436,6 +436,10 @@ void cpu_x86_close(CPUX86State *s); @@ -436,6 +436,10 @@ void cpu_x86_close(CPUX86State *s);
436 /* needed to load some predefinied segment registers */ 436 /* needed to load some predefinied segment registers */
437 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector); 437 void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector);
438 438
  439 +/* simulate fsave/frstor */
  440 +void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32);
  441 +void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32);
  442 +
439 /* you can call this signal handler from your SIGBUS and SIGSEGV 443 /* you can call this signal handler from your SIGBUS and SIGSEGV
440 signal handlers to inform the virtual CPU of exceptions. non zero 444 signal handlers to inform the virtual CPU of exceptions. non zero
441 is returned if the signal was handled by the virtual CPU. */ 445 is returned if the signal was handled by the virtual CPU. */
exec-i386.c
@@ -327,6 +327,30 @@ void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector) @@ -327,6 +327,30 @@ void cpu_x86_load_seg(CPUX86State *s, int seg_reg, int selector)
327 env = saved_env; 327 env = saved_env;
328 } 328 }
329 329
  330 +void cpu_x86_fsave(CPUX86State *s, uint8_t *ptr, int data32)
  331 +{
  332 + CPUX86State *saved_env;
  333 +
  334 + saved_env = env;
  335 + env = s;
  336 +
  337 + helper_fsave(ptr, data32);
  338 +
  339 + env = saved_env;
  340 +}
  341 +
  342 +void cpu_x86_frstor(CPUX86State *s, uint8_t *ptr, int data32)
  343 +{
  344 + CPUX86State *saved_env;
  345 +
  346 + saved_env = env;
  347 + env = s;
  348 +
  349 + helper_frstor(ptr, data32);
  350 +
  351 + env = saved_env;
  352 +}
  353 +
330 #undef EAX 354 #undef EAX
331 #undef ECX 355 #undef ECX
332 #undef EDX 356 #undef EDX
exec-i386.h
@@ -225,6 +225,8 @@ void raise_interrupt(int intno, int is_int, int error_code, @@ -225,6 +225,8 @@ void raise_interrupt(int intno, int is_int, int error_code,
225 void raise_exception_err(int exception_index, int error_code); 225 void raise_exception_err(int exception_index, int error_code);
226 void raise_exception(int exception_index); 226 void raise_exception(int exception_index);
227 void cpu_loop_exit(void); 227 void cpu_loop_exit(void);
  228 +void helper_fsave(uint8_t *ptr, int data32);
  229 +void helper_frstor(uint8_t *ptr, int data32);
228 230
229 void OPPROTO op_movl_eflags_T0(void); 231 void OPPROTO op_movl_eflags_T0(void);
230 void OPPROTO op_movl_T0_eflags(void); 232 void OPPROTO op_movl_T0_eflags(void);
op-i386.c
@@ -1073,7 +1073,7 @@ void helper_cpuid(void) @@ -1073,7 +1073,7 @@ void helper_cpuid(void)
1073 EBX = 0x756e6547; 1073 EBX = 0x756e6547;
1074 ECX = 0x6c65746e; 1074 ECX = 0x6c65746e;
1075 EDX = 0x49656e69; 1075 EDX = 0x49656e69;
1076 - } else { 1076 + } else if (EAX == 1) {
1077 /* EAX = 1 info */ 1077 /* EAX = 1 info */
1078 EAX = 0x52b; 1078 EAX = 0x52b;
1079 EBX = 0; 1079 EBX = 0;
@@ -1899,17 +1899,22 @@ void OPPROTO op_fldt_ST0_A0(void) @@ -1899,17 +1899,22 @@ void OPPROTO op_fldt_ST0_A0(void)
1899 ST0 = *(long double *)A0; 1899 ST0 = *(long double *)A0;
1900 } 1900 }
1901 #else 1901 #else
1902 -void helper_fldt_ST0_A0(void) 1902 +static inline CPU86_LDouble helper_fldt(uint8_t *ptr)
1903 { 1903 {
1904 CPU86_LDoubleU temp; 1904 CPU86_LDoubleU temp;
1905 int upper, e; 1905 int upper, e;
1906 /* mantissa */ 1906 /* mantissa */
1907 - upper = lduw((uint8_t *)A0 + 8); 1907 + upper = lduw(ptr + 8);
1908 /* XXX: handle overflow ? */ 1908 /* XXX: handle overflow ? */
1909 e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */ 1909 e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
1910 e |= (upper >> 4) & 0x800; /* sign */ 1910 e |= (upper >> 4) & 0x800; /* sign */
1911 - temp.ll = ((ldq((void *)A0) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52);  
1912 - ST0 = temp.d; 1911 + temp.ll = ((ldq(ptr) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52);
  1912 + return temp.d;
  1913 +}
  1914 +
  1915 +void helper_fldt_ST0_A0(void)
  1916 +{
  1917 + ST0 = helper_fldt((uint8_t *)A0);
1913 } 1918 }
1914 1919
1915 void OPPROTO op_fldt_ST0_A0(void) 1920 void OPPROTO op_fldt_ST0_A0(void)
@@ -2008,17 +2013,23 @@ void OPPROTO op_fstt_ST0_A0(void) @@ -2008,17 +2013,23 @@ void OPPROTO op_fstt_ST0_A0(void)
2008 *(long double *)A0 = ST0; 2013 *(long double *)A0 = ST0;
2009 } 2014 }
2010 #else 2015 #else
2011 -void helper_fstt_ST0_A0(void) 2016 +
  2017 +static inline void helper_fstt(CPU86_LDouble f, uint8_t *ptr)
2012 { 2018 {
2013 CPU86_LDoubleU temp; 2019 CPU86_LDoubleU temp;
2014 int e; 2020 int e;
2015 - temp.d = ST0; 2021 + temp.d = f;
2016 /* mantissa */ 2022 /* mantissa */
2017 - stq((void *)A0, (MANTD(temp) << 11) | (1LL << 63)); 2023 + stq(ptr, (MANTD(temp) << 11) | (1LL << 63));
2018 /* exponent + sign */ 2024 /* exponent + sign */
2019 e = EXPD(temp) - EXPBIAS + 16383; 2025 e = EXPD(temp) - EXPBIAS + 16383;
2020 e |= SIGND(temp) >> 16; 2026 e |= SIGND(temp) >> 16;
2021 - stw((uint8_t *)A0 + 8, e); 2027 + stw(ptr + 8, e);
  2028 +}
  2029 +
  2030 +void helper_fstt_ST0_A0(void)
  2031 +{
  2032 + helper_fstt(ST0, (uint8_t *)A0);
2022 } 2033 }
2023 2034
2024 void OPPROTO op_fstt_ST0_A0(void) 2035 void OPPROTO op_fstt_ST0_A0(void)
@@ -2254,6 +2265,34 @@ void OPPROTO op_fucom_ST0_FT0(void) @@ -2254,6 +2265,34 @@ void OPPROTO op_fucom_ST0_FT0(void)
2254 FORCE_RET(); 2265 FORCE_RET();
2255 } 2266 }
2256 2267
  2268 +/* XXX: handle nans */
  2269 +void OPPROTO op_fcomi_ST0_FT0(void)
  2270 +{
  2271 + int eflags;
  2272 + eflags = cc_table[CC_OP].compute_all();
  2273 + eflags &= ~(CC_Z | CC_P | CC_C);
  2274 + if (ST0 < FT0)
  2275 + eflags |= CC_C;
  2276 + else if (ST0 == FT0)
  2277 + eflags |= CC_Z;
  2278 + CC_SRC = eflags;
  2279 + FORCE_RET();
  2280 +}
  2281 +
  2282 +/* XXX: handle nans */
  2283 +void OPPROTO op_fucomi_ST0_FT0(void)
  2284 +{
  2285 + int eflags;
  2286 + eflags = cc_table[CC_OP].compute_all();
  2287 + eflags &= ~(CC_Z | CC_P | CC_C);
  2288 + if (ST0 < FT0)
  2289 + eflags |= CC_C;
  2290 + else if (ST0 == FT0)
  2291 + eflags |= CC_Z;
  2292 + CC_SRC = eflags;
  2293 + FORCE_RET();
  2294 +}
  2295 +
2257 void OPPROTO op_fadd_ST0_FT0(void) 2296 void OPPROTO op_fadd_ST0_FT0(void)
2258 { 2297 {
2259 ST0 += FT0; 2298 ST0 += FT0;
@@ -2750,6 +2789,149 @@ void OPPROTO op_fninit(void) @@ -2750,6 +2789,149 @@ void OPPROTO op_fninit(void)
2750 env->fptags[7] = 1; 2789 env->fptags[7] = 1;
2751 } 2790 }
2752 2791
  2792 +void helper_fstenv(uint8_t *ptr, int data32)
  2793 +{
  2794 + int fpus, fptag, exp, i;
  2795 + uint64_t mant;
  2796 + CPU86_LDoubleU tmp;
  2797 +
  2798 + fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
  2799 + fptag = 0;
  2800 + for (i=7; i>=0; i--) {
  2801 + fptag <<= 2;
  2802 + if (env->fptags[i]) {
  2803 + fptag |= 3;
  2804 + } else {
  2805 + tmp.d = env->fpregs[i];
  2806 + exp = EXPD(tmp);
  2807 + mant = MANTD(tmp);
  2808 + if (exp == 0 && mant == 0) {
  2809 + /* zero */
  2810 + fptag |= 1;
  2811 + } else if (exp == 0 || exp == MAXEXPD
  2812 +#ifdef USE_X86LDOUBLE
  2813 + || (mant & (1LL << 63)) == 0
  2814 +#endif
  2815 + ) {
  2816 + /* NaNs, infinity, denormal */
  2817 + fptag |= 2;
  2818 + }
  2819 + }
  2820 + }
  2821 + if (data32) {
  2822 + /* 32 bit */
  2823 + stl(ptr, env->fpuc);
  2824 + stl(ptr + 4, fpus);
  2825 + stl(ptr + 8, fptag);
  2826 + stl(ptr + 12, 0);
  2827 + stl(ptr + 16, 0);
  2828 + stl(ptr + 20, 0);
  2829 + stl(ptr + 24, 0);
  2830 + } else {
  2831 + /* 16 bit */
  2832 + stw(ptr, env->fpuc);
  2833 + stw(ptr + 2, fpus);
  2834 + stw(ptr + 4, fptag);
  2835 + stw(ptr + 6, 0);
  2836 + stw(ptr + 8, 0);
  2837 + stw(ptr + 10, 0);
  2838 + stw(ptr + 12, 0);
  2839 + }
  2840 +}
  2841 +
  2842 +void helper_fldenv(uint8_t *ptr, int data32)
  2843 +{
  2844 + int i, fpus, fptag;
  2845 +
  2846 + if (data32) {
  2847 + env->fpuc = lduw(ptr);
  2848 + fpus = lduw(ptr + 4);
  2849 + fptag = lduw(ptr + 8);
  2850 + }
  2851 + else {
  2852 + env->fpuc = lduw(ptr);
  2853 + fpus = lduw(ptr + 2);
  2854 + fptag = lduw(ptr + 4);
  2855 + }
  2856 + env->fpstt = (fpus >> 11) & 7;
  2857 + env->fpus = fpus & ~0x3800;
  2858 + for(i = 0;i < 7; i++) {
  2859 + env->fptags[i] = ((fptag & 3) == 3);
  2860 + fptag >>= 2;
  2861 + }
  2862 +}
  2863 +
  2864 +void helper_fsave(uint8_t *ptr, int data32)
  2865 +{
  2866 + CPU86_LDouble tmp;
  2867 + int i;
  2868 +
  2869 + helper_fstenv(ptr, data32);
  2870 +
  2871 + ptr += (14 << data32);
  2872 + for(i = 0;i < 8; i++) {
  2873 + tmp = ST(i);
  2874 +#ifdef USE_X86LDOUBLE
  2875 + *(long double *)ptr = tmp;
  2876 +#else
  2877 + helper_fstt(tmp, ptr);
  2878 +#endif
  2879 + ptr += 10;
  2880 + }
  2881 +
  2882 + /* fninit */
  2883 + env->fpus = 0;
  2884 + env->fpstt = 0;
  2885 + env->fpuc = 0x37f;
  2886 + env->fptags[0] = 1;
  2887 + env->fptags[1] = 1;
  2888 + env->fptags[2] = 1;
  2889 + env->fptags[3] = 1;
  2890 + env->fptags[4] = 1;
  2891 + env->fptags[5] = 1;
  2892 + env->fptags[6] = 1;
  2893 + env->fptags[7] = 1;
  2894 +}
  2895 +
  2896 +void helper_frstor(uint8_t *ptr, int data32)
  2897 +{
  2898 + CPU86_LDouble tmp;
  2899 + int i;
  2900 +
  2901 + helper_fldenv(ptr, data32);
  2902 + ptr += (14 << data32);
  2903 +
  2904 + for(i = 0;i < 8; i++) {
  2905 +#ifdef USE_X86LDOUBLE
  2906 + tmp = *(long double *)ptr;
  2907 +#else
  2908 + tmp = helper_fldt(ptr);
  2909 +#endif
  2910 + ST(i) = tmp;
  2911 + ptr += 10;
  2912 + }
  2913 +}
  2914 +
  2915 +void OPPROTO op_fnstenv_A0(void)
  2916 +{
  2917 + helper_fstenv((uint8_t *)A0, PARAM1);
  2918 +}
  2919 +
  2920 +void OPPROTO op_fldenv_A0(void)
  2921 +{
  2922 + helper_fldenv((uint8_t *)A0, PARAM1);
  2923 +}
  2924 +
  2925 +void OPPROTO op_fnsave_A0(void)
  2926 +{
  2927 + helper_fsave((uint8_t *)A0, PARAM1);
  2928 +}
  2929 +
  2930 +void OPPROTO op_frstor_A0(void)
  2931 +{
  2932 + helper_frstor((uint8_t *)A0, PARAM1);
  2933 +}
  2934 +
2753 /* threading support */ 2935 /* threading support */
2754 void OPPROTO op_lock(void) 2936 void OPPROTO op_lock(void)
2755 { 2937 {
translate-i386.c
@@ -1273,21 +1273,40 @@ static void gen_pop_T0(DisasContext *s) @@ -1273,21 +1273,40 @@ static void gen_pop_T0(DisasContext *s)
1273 } 1273 }
1274 } 1274 }
1275 1275
1276 -static void gen_pop_update(DisasContext *s) 1276 +static inline void gen_stack_update(DisasContext *s, int addend)
1277 { 1277 {
1278 if (s->ss32) { 1278 if (s->ss32) {
1279 - if (s->dflag)  
1280 - gen_op_addl_ESP_4();  
1281 - else 1279 + if (addend == 2)
1282 gen_op_addl_ESP_2(); 1280 gen_op_addl_ESP_2();
  1281 + else if (addend == 4)
  1282 + gen_op_addl_ESP_4();
  1283 + else
  1284 + gen_op_addl_ESP_im(addend);
1283 } else { 1285 } else {
1284 - if (s->dflag) 1286 + if (addend == 2)
  1287 + gen_op_addw_ESP_2();
  1288 + else if (addend == 4)
1285 gen_op_addw_ESP_4(); 1289 gen_op_addw_ESP_4();
1286 else 1290 else
1287 - gen_op_addw_ESP_2(); 1291 + gen_op_addw_ESP_im(addend);
1288 } 1292 }
1289 } 1293 }
1290 1294
  1295 +static void gen_pop_update(DisasContext *s)
  1296 +{
  1297 + gen_stack_update(s, 2 << s->dflag);
  1298 +}
  1299 +
  1300 +static void gen_stack_A0(DisasContext *s)
  1301 +{
  1302 + gen_op_movl_A0_ESP();
  1303 + if (!s->ss32)
  1304 + gen_op_andl_A0_ffff();
  1305 + gen_op_movl_T1_A0();
  1306 + if (s->addseg)
  1307 + gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
  1308 +}
  1309 +
1291 /* NOTE: wrap around in 16 bit not fully handled */ 1310 /* NOTE: wrap around in 16 bit not fully handled */
1292 static void gen_pusha(DisasContext *s) 1311 static void gen_pusha(DisasContext *s)
1293 { 1312 {
@@ -1957,7 +1976,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1957,7 +1976,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1957 } 1976 }
1958 break; 1977 break;
1959 case 0xc9: /* leave */ 1978 case 0xc9: /* leave */
1960 - /* XXX: exception not precise (ESP is update before potential exception) */ 1979 + /* XXX: exception not precise (ESP is updated before potential exception) */
1961 if (s->ss32) { 1980 if (s->ss32) {
1962 gen_op_mov_TN_reg[OT_LONG][0][R_EBP](); 1981 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1963 gen_op_mov_reg_T0[OT_LONG][R_ESP](); 1982 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
@@ -2453,9 +2472,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2453,9 +2472,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2453 break; 2472 break;
2454 } 2473 }
2455 break; 2474 break;
  2475 + case 0x0c: /* fldenv mem */
  2476 + gen_op_fldenv_A0(s->dflag);
  2477 + break;
2456 case 0x0d: /* fldcw mem */ 2478 case 0x0d: /* fldcw mem */
2457 gen_op_fldcw_A0(); 2479 gen_op_fldcw_A0();
2458 break; 2480 break;
  2481 + case 0x0e: /* fnstenv mem */
  2482 + gen_op_fnstenv_A0(s->dflag);
  2483 + break;
2459 case 0x0f: /* fnstcw mem */ 2484 case 0x0f: /* fnstcw mem */
2460 gen_op_fnstcw_A0(); 2485 gen_op_fnstcw_A0();
2461 break; 2486 break;
@@ -2467,6 +2492,12 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2467,6 +2492,12 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2467 gen_op_fstt_ST0_A0(); 2492 gen_op_fstt_ST0_A0();
2468 gen_op_fpop(); 2493 gen_op_fpop();
2469 break; 2494 break;
  2495 + case 0x2c: /* frstor mem */
  2496 + gen_op_frstor_A0(s->dflag);
  2497 + break;
  2498 + case 0x2e: /* fnsave mem */
  2499 + gen_op_fnsave_A0(s->dflag);
  2500 + break;
2470 case 0x2f: /* fnstsw mem */ 2501 case 0x2f: /* fnstsw mem */
2471 gen_op_fnstsw_A0(); 2502 gen_op_fnstsw_A0();
2472 break; 2503 break;
@@ -2672,6 +2703,20 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2672,6 +2703,20 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2672 goto illegal_op; 2703 goto illegal_op;
2673 } 2704 }
2674 break; 2705 break;
  2706 + case 0x1d: /* fucomi */
  2707 + if (s->cc_op != CC_OP_DYNAMIC)
  2708 + gen_op_set_cc_op(s->cc_op);
  2709 + gen_op_fmov_FT0_STN(opreg);
  2710 + gen_op_fucomi_ST0_FT0();
  2711 + s->cc_op = CC_OP_EFLAGS;
  2712 + break;
  2713 + case 0x1e: /* fcomi */
  2714 + if (s->cc_op != CC_OP_DYNAMIC)
  2715 + gen_op_set_cc_op(s->cc_op);
  2716 + gen_op_fmov_FT0_STN(opreg);
  2717 + gen_op_fcomi_ST0_FT0();
  2718 + s->cc_op = CC_OP_EFLAGS;
  2719 + break;
2675 case 0x2a: /* fst sti */ 2720 case 0x2a: /* fst sti */
2676 gen_op_fmov_STN_ST0(opreg); 2721 gen_op_fmov_STN_ST0(opreg);
2677 break; 2722 break;
@@ -2709,6 +2754,22 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2709,6 +2754,22 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2709 goto illegal_op; 2754 goto illegal_op;
2710 } 2755 }
2711 break; 2756 break;
  2757 + case 0x3d: /* fucomip */
  2758 + if (s->cc_op != CC_OP_DYNAMIC)
  2759 + gen_op_set_cc_op(s->cc_op);
  2760 + gen_op_fmov_FT0_STN(opreg);
  2761 + gen_op_fucomi_ST0_FT0();
  2762 + gen_op_fpop();
  2763 + s->cc_op = CC_OP_EFLAGS;
  2764 + break;
  2765 + case 0x3e: /* fcomip */
  2766 + if (s->cc_op != CC_OP_DYNAMIC)
  2767 + gen_op_set_cc_op(s->cc_op);
  2768 + gen_op_fmov_FT0_STN(opreg);
  2769 + gen_op_fcomi_ST0_FT0();
  2770 + gen_op_fpop();
  2771 + s->cc_op = CC_OP_EFLAGS;
  2772 + break;
2712 default: 2773 default:
2713 goto illegal_op; 2774 goto illegal_op;
2714 } 2775 }
@@ -2901,10 +2962,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2901,10 +2962,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2901 val = ldsw(s->pc); 2962 val = ldsw(s->pc);
2902 s->pc += 2; 2963 s->pc += 2;
2903 gen_pop_T0(s); 2964 gen_pop_T0(s);
2904 - if (s->ss32)  
2905 - gen_op_addl_ESP_im(val + (2 << s->dflag));  
2906 - else  
2907 - gen_op_addw_ESP_im(val + (2 << s->dflag)); 2965 + gen_stack_update(s, val + (2 << s->dflag));
2908 if (s->dflag == 0) 2966 if (s->dflag == 0)
2909 gen_op_andl_T0_ffff(); 2967 gen_op_andl_T0_ffff();
2910 gen_op_jmp_T0(); 2968 gen_op_jmp_T0();
@@ -2919,63 +2977,55 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2919,63 +2977,55 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2919 s->is_jmp = 1; 2977 s->is_jmp = 1;
2920 break; 2978 break;
2921 case 0xca: /* lret im */ 2979 case 0xca: /* lret im */
2922 - /* XXX: not restartable */  
2923 val = ldsw(s->pc); 2980 val = ldsw(s->pc);
2924 s->pc += 2; 2981 s->pc += 2;
  2982 + do_lret:
  2983 + gen_stack_A0(s);
2925 /* pop offset */ 2984 /* pop offset */
2926 - gen_pop_T0(s); 2985 + gen_op_ld_T0_A0[1 + s->dflag]();
2927 if (s->dflag == 0) 2986 if (s->dflag == 0)
2928 gen_op_andl_T0_ffff(); 2987 gen_op_andl_T0_ffff();
  2988 + /* NOTE: keeping EIP updated is not a problem in case of
  2989 + exception */
2929 gen_op_jmp_T0(); 2990 gen_op_jmp_T0();
2930 - gen_pop_update(s);  
2931 /* pop selector */ 2991 /* pop selector */
2932 - gen_pop_T0(s); 2992 + gen_op_addl_A0_im(2 << s->dflag);
  2993 + gen_op_ld_T0_A0[1 + s->dflag]();
2933 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base); 2994 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2934 - gen_pop_update(s);  
2935 /* add stack offset */ 2995 /* add stack offset */
2936 - if (s->ss32)  
2937 - gen_op_addl_ESP_im(val);  
2938 - else  
2939 - gen_op_addw_ESP_im(val); 2996 + gen_stack_update(s, val + (4 << s->dflag));
2940 s->is_jmp = 1; 2997 s->is_jmp = 1;
2941 break; 2998 break;
2942 case 0xcb: /* lret */ 2999 case 0xcb: /* lret */
2943 - /* XXX: not restartable */  
2944 - /* pop offset */  
2945 - gen_pop_T0(s);  
2946 - if (s->dflag == 0)  
2947 - gen_op_andl_T0_ffff();  
2948 - gen_op_jmp_T0();  
2949 - gen_pop_update(s);  
2950 - /* pop selector */  
2951 - gen_pop_T0(s);  
2952 - gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);  
2953 - gen_pop_update(s);  
2954 - s->is_jmp = 1;  
2955 - break; 3000 + val = 0;
  3001 + goto do_lret;
2956 case 0xcf: /* iret */ 3002 case 0xcf: /* iret */
2957 if (s->vm86 && s->iopl != 3) { 3003 if (s->vm86 && s->iopl != 3) {
2958 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 3004 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2959 } else { 3005 } else {
2960 /* XXX: not restartable */ 3006 /* XXX: not restartable */
  3007 + gen_stack_A0(s);
2961 /* pop offset */ 3008 /* pop offset */
2962 - gen_pop_T0(s); 3009 + gen_op_ld_T0_A0[1 + s->dflag]();
2963 if (s->dflag == 0) 3010 if (s->dflag == 0)
2964 gen_op_andl_T0_ffff(); 3011 gen_op_andl_T0_ffff();
2965 - gen_op_jmp_T0();  
2966 - gen_pop_update(s); 3012 + /* NOTE: keeping EIP updated is not a problem in case of
  3013 + exception */
  3014 + gen_op_jmp_T0();
2967 /* pop selector */ 3015 /* pop selector */
2968 - gen_pop_T0(s);  
2969 - gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);  
2970 - gen_pop_update(s); 3016 + gen_op_addl_A0_im(2 << s->dflag);
  3017 + gen_op_ld_T0_A0[1 + s->dflag]();
2971 /* pop eflags */ 3018 /* pop eflags */
2972 - gen_pop_T0(s); 3019 + gen_op_addl_A0_im(2 << s->dflag);
  3020 + gen_op_ld_T1_A0[1 + s->dflag]();
  3021 + gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
  3022 + gen_op_movl_T0_T1();
2973 if (s->dflag) { 3023 if (s->dflag) {
2974 gen_op_movl_eflags_T0(); 3024 gen_op_movl_eflags_T0();
2975 } else { 3025 } else {
2976 gen_op_movw_eflags_T0(); 3026 gen_op_movw_eflags_T0();
2977 } 3027 }
2978 - gen_pop_update(s); 3028 + gen_stack_update(s, (6 << s->dflag));
2979 s->cc_op = CC_OP_EFLAGS; 3029 s->cc_op = CC_OP_EFLAGS;
2980 } 3030 }
2981 s->is_jmp = 1; 3031 s->is_jmp = 1;
@@ -2997,6 +3047,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2997,6 +3047,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2997 case 0x9a: /* lcall im */ 3047 case 0x9a: /* lcall im */
2998 { 3048 {
2999 unsigned int selector, offset; 3049 unsigned int selector, offset;
  3050 + /* XXX: not restartable */
3000 3051
3001 ot = dflag ? OT_LONG : OT_WORD; 3052 ot = dflag ? OT_LONG : OT_WORD;
3002 offset = insn_get(s, ot); 3053 offset = insn_get(s, ot);
@@ -3613,6 +3664,8 @@ static uint16_t opc_write_flags[NB_OPS] = { @@ -3613,6 +3664,8 @@ static uint16_t opc_write_flags[NB_OPS] = {
3613 [INDEX_op_cmpxchg8b] = CC_Z, 3664 [INDEX_op_cmpxchg8b] = CC_Z,
3614 [INDEX_op_lar] = CC_Z, 3665 [INDEX_op_lar] = CC_Z,
3615 [INDEX_op_lsl] = CC_Z, 3666 [INDEX_op_lsl] = CC_Z,
  3667 + [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
  3668 + [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
3616 }; 3669 };
3617 3670
3618 /* simpler form of an operation if no flags need to be generated */ 3671 /* simpler form of an operation if no flags need to be generated */