Commit 77f8dd5add8f02253dcea1454c9d2c76d7c788a7

Authored by bellard
1 parent c5e9815d

float fixes - added bsr/bsf support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@23 c046a42c-6fe2-441c-8c8c-71466251a162
Makefile
@@ -83,6 +83,7 @@ cpu-i386.h gemu.h op-i386.c syscall-i386.h translate-i386.c\ @@ -83,6 +83,7 @@ cpu-i386.h gemu.h op-i386.c syscall-i386.h translate-i386.c\
83 dis-asm.h gen-i386.h op-i386.h syscall.c\ 83 dis-asm.h gen-i386.h op-i386.h syscall.c\
84 dis-buf.c i386-dis.c opreg_template.h syscall_defs.h\ 84 dis-buf.c i386-dis.c opreg_template.h syscall_defs.h\
85 i386.ld ppc.ld\ 85 i386.ld ppc.ld\
  86 +tests/Makefile\
86 tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h\ 87 tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h\
87 tests/test-i386-muldiv.h\ 88 tests/test-i386-muldiv.h\
88 tests/test2.c tests/hello.c tests/sha1.c tests/test1.c 89 tests/test2.c tests/hello.c tests/sha1.c tests/test1.c
@@ -3,4 +3,4 @@ @@ -3,4 +3,4 @@
3 - threads 3 - threads
4 - fix printf for doubles (fp87.c bug ?) 4 - fix printf for doubles (fp87.c bug ?)
5 - make it self runnable (use same trick as ld.so : include its own relocator and libc) 5 - make it self runnable (use same trick as ld.so : include its own relocator and libc)
6 -- better FPU comparisons (ucom/com) 6 +- fix FPU exceptions (in particular: gen_op_fpush not before mem load)
cpu-i386.h
@@ -114,7 +114,7 @@ enum { @@ -114,7 +114,7 @@ enum {
114 }; 114 };
115 115
116 #ifdef __i386__ 116 #ifdef __i386__
117 -#define USE_X86LDOUBLE 117 +//#define USE_X86LDOUBLE
118 #endif 118 #endif
119 119
120 #ifdef USE_X86LDOUBLE 120 #ifdef USE_X86LDOUBLE
@@ -201,7 +201,7 @@ static inline void stl(void *ptr, int v) @@ -201,7 +201,7 @@ static inline void stl(void *ptr, int v)
201 *(uint32_t *)ptr = v; 201 *(uint32_t *)ptr = v;
202 } 202 }
203 203
204 -static inline void stq(void *ptr, int v) 204 +static inline void stq(void *ptr, uint64_t v)
205 { 205 {
206 *(uint64_t *)ptr = v; 206 *(uint64_t *)ptr = v;
207 } 207 }
op-i386.c
@@ -1055,7 +1055,7 @@ typedef union { @@ -1055,7 +1055,7 @@ typedef union {
1055 1055
1056 #else 1056 #else
1057 1057
1058 -typedef { 1058 +typedef union {
1059 double d; 1059 double d;
1060 #ifndef WORDS_BIGENDIAN 1060 #ifndef WORDS_BIGENDIAN
1061 struct { 1061 struct {
@@ -1119,6 +1119,31 @@ void OPPROTO op_fldl_ST0_A0(void) @@ -1119,6 +1119,31 @@ void OPPROTO op_fldl_ST0_A0(void)
1119 ST0 = ldfq((void *)A0); 1119 ST0 = ldfq((void *)A0);
1120 } 1120 }
1121 1121
  1122 +#ifdef USE_X86LDOUBLE
  1123 +void OPPROTO op_fldt_ST0_A0(void)
  1124 +{
  1125 + ST0 = *(long double *)A0;
  1126 +}
  1127 +#else
  1128 +void helper_fldt_ST0_A0(void)
  1129 +{
  1130 + CPU86_LDoubleU temp;
  1131 + int upper, e;
  1132 + /* mantissa */
  1133 + upper = lduw((uint8_t *)A0 + 8);
  1134 + /* XXX: handle overflow ? */
  1135 + e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */
  1136 + e |= (upper >> 4) & 0x800; /* sign */
  1137 + temp.ll = ((ldq((void *)A0) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52);
  1138 + ST0 = temp.d;
  1139 +}
  1140 +
  1141 +void OPPROTO op_fldt_ST0_A0(void)
  1142 +{
  1143 + helper_fldt_ST0_A0();
  1144 +}
  1145 +#endif
  1146 +
1122 void OPPROTO op_fild_ST0_A0(void) 1147 void OPPROTO op_fild_ST0_A0(void)
1123 { 1148 {
1124 ST0 = (CPU86_LDouble)ldsw((void *)A0); 1149 ST0 = (CPU86_LDouble)ldsw((void *)A0);
@@ -1143,9 +1168,34 @@ void OPPROTO op_fsts_ST0_A0(void) @@ -1143,9 +1168,34 @@ void OPPROTO op_fsts_ST0_A0(void)
1143 1168
1144 void OPPROTO op_fstl_ST0_A0(void) 1169 void OPPROTO op_fstl_ST0_A0(void)
1145 { 1170 {
1146 - ST0 = ldfq((void *)A0); 1171 + stfq((void *)A0, (double)ST0);
1147 } 1172 }
1148 1173
  1174 +#ifdef USE_X86LDOUBLE
  1175 +void OPPROTO op_fstt_ST0_A0(void)
  1176 +{
  1177 + *(long double *)A0 = ST0;
  1178 +}
  1179 +#else
  1180 +void helper_fstt_ST0_A0(void)
  1181 +{
  1182 + CPU86_LDoubleU temp;
  1183 + int e;
  1184 + temp.d = ST0;
  1185 + /* mantissa */
  1186 + stq((void *)A0, (MANTD(temp) << 11) | (1LL << 63));
  1187 + /* exponent + sign */
  1188 + e = EXPD(temp) - EXPBIAS + 16383;
  1189 + e |= SIGND(temp) >> 16;
  1190 + stw((uint8_t *)A0 + 8, e);
  1191 +}
  1192 +
  1193 +void OPPROTO op_fstt_ST0_A0(void)
  1194 +{
  1195 + helper_fstt_ST0_A0();
  1196 +}
  1197 +#endif
  1198 +
1149 void OPPROTO op_fist_ST0_A0(void) 1199 void OPPROTO op_fist_ST0_A0(void)
1150 { 1200 {
1151 int val; 1201 int val;
@@ -1167,6 +1217,103 @@ void OPPROTO op_fistll_ST0_A0(void) @@ -1167,6 +1217,103 @@ void OPPROTO op_fistll_ST0_A0(void)
1167 stq((void *)A0, val); 1217 stq((void *)A0, val);
1168 } 1218 }
1169 1219
  1220 +/* BCD ops */
  1221 +
  1222 +#define MUL10(iv) ( iv + iv + (iv << 3) )
  1223 +
  1224 +void helper_fbld_ST0_A0(void)
  1225 +{
  1226 + uint8_t *seg;
  1227 + CPU86_LDouble fpsrcop;
  1228 + int m32i;
  1229 + unsigned int v;
  1230 +
  1231 + /* in this code, seg/m32i will be used as temporary ptr/int */
  1232 + seg = (uint8_t *)A0 + 8;
  1233 + v = ldub(seg--);
  1234 + /* XXX: raise exception */
  1235 + if (v != 0)
  1236 + return;
  1237 + v = ldub(seg--);
  1238 + /* XXX: raise exception */
  1239 + if ((v & 0xf0) != 0)
  1240 + return;
  1241 + m32i = v; /* <-- d14 */
  1242 + v = ldub(seg--);
  1243 + m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d13 */
  1244 + m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */
  1245 + v = ldub(seg--);
  1246 + m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d11 */
  1247 + m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */
  1248 + v = ldub(seg--);
  1249 + m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d9 */
  1250 + m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */
  1251 + fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0;
  1252 +
  1253 + v = ldub(seg--);
  1254 + m32i = (v >> 4); /* <-- d7 */
  1255 + m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */
  1256 + v = ldub(seg--);
  1257 + m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d5 */
  1258 + m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */
  1259 + v = ldub(seg--);
  1260 + m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d3 */
  1261 + m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */
  1262 + v = ldub(seg);
  1263 + m32i = MUL10(m32i) + (v >> 4); /* <-- val * 10 + d1 */
  1264 + m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */
  1265 + fpsrcop += ((CPU86_LDouble)m32i);
  1266 + if ( ldub(seg+9) & 0x80 )
  1267 + fpsrcop = -fpsrcop;
  1268 + ST0 = fpsrcop;
  1269 +}
  1270 +
  1271 +void OPPROTO op_fbld_ST0_A0(void)
  1272 +{
  1273 + helper_fbld_ST0_A0();
  1274 +}
  1275 +
  1276 +void helper_fbst_ST0_A0(void)
  1277 +{
  1278 + CPU86_LDouble fptemp;
  1279 + CPU86_LDouble fpsrcop;
  1280 + int v;
  1281 + uint8_t *mem_ref, *mem_end;
  1282 +
  1283 + fpsrcop = rint(ST0);
  1284 + mem_ref = (uint8_t *)A0;
  1285 + mem_end = mem_ref + 8;
  1286 + if ( fpsrcop < 0.0 ) {
  1287 + stw(mem_end, 0x8000);
  1288 + fpsrcop = -fpsrcop;
  1289 + } else {
  1290 + stw(mem_end, 0x0000);
  1291 + }
  1292 + while (mem_ref < mem_end) {
  1293 + if (fpsrcop == 0.0)
  1294 + break;
  1295 + fptemp = floor(fpsrcop/10.0);
  1296 + v = ((int)(fpsrcop - fptemp*10.0));
  1297 + if (fptemp == 0.0) {
  1298 + stb(mem_ref++, v);
  1299 + break;
  1300 + }
  1301 + fpsrcop = fptemp;
  1302 + fptemp = floor(fpsrcop/10.0);
  1303 + v |= (((int)(fpsrcop - fptemp*10.0)) << 4);
  1304 + stb(mem_ref++, v);
  1305 + fpsrcop = fptemp;
  1306 + }
  1307 + while (mem_ref < mem_end) {
  1308 + stb(mem_ref++, 0);
  1309 + }
  1310 +}
  1311 +
  1312 +void OPPROTO op_fbst_ST0_A0(void)
  1313 +{
  1314 + helper_fbst_ST0_A0();
  1315 +}
  1316 +
1170 /* FPU move */ 1317 /* FPU move */
1171 1318
1172 static inline void fpush(void) 1319 static inline void fpush(void)
@@ -1244,6 +1391,17 @@ void OPPROTO op_fcom_ST0_FT0(void) @@ -1244,6 +1391,17 @@ void OPPROTO op_fcom_ST0_FT0(void)
1244 FORCE_RET(); 1391 FORCE_RET();
1245 } 1392 }
1246 1393
  1394 +/* XXX: handle nans */
  1395 +void OPPROTO op_fucom_ST0_FT0(void)
  1396 +{
  1397 + env->fpus &= (~0x4500); /* (C3,C2,C0) <-- 000 */
  1398 + if (ST0 < FT0)
  1399 + env->fpus |= 0x100; /* (C3,C2,C0) <-- 001 */
  1400 + else if (ST0 == FT0)
  1401 + env->fpus |= 0x4000; /* (C3,C2,C0) <-- 100 */
  1402 + FORCE_RET();
  1403 +}
  1404 +
1247 void OPPROTO op_fadd_ST0_FT0(void) 1405 void OPPROTO op_fadd_ST0_FT0(void)
1248 { 1406 {
1249 ST0 += FT0; 1407 ST0 += FT0;
@@ -1321,7 +1479,7 @@ void OPPROTO op_fabs_ST0(void) @@ -1321,7 +1479,7 @@ void OPPROTO op_fabs_ST0(void)
1321 ST0 = fabs(ST0); 1479 ST0 = fabs(ST0);
1322 } 1480 }
1323 1481
1324 -void OPPROTO op_fxam_ST0(void) 1482 +void helper_fxam_ST0(void)
1325 { 1483 {
1326 CPU86_LDoubleU temp; 1484 CPU86_LDoubleU temp;
1327 int expdif; 1485 int expdif;
@@ -1346,7 +1504,11 @@ void OPPROTO op_fxam_ST0(void) @@ -1346,7 +1504,11 @@ void OPPROTO op_fxam_ST0(void)
1346 } else { 1504 } else {
1347 env->fpus |= 0x400; 1505 env->fpus |= 0x400;
1348 } 1506 }
1349 - FORCE_RET(); 1507 +}
  1508 +
  1509 +void OPPROTO op_fxam_ST0(void)
  1510 +{
  1511 + helper_fxam_ST0();
1350 } 1512 }
1351 1513
1352 void OPPROTO op_fld1_ST0(void) 1514 void OPPROTO op_fld1_ST0(void)
@@ -1354,12 +1516,12 @@ void OPPROTO op_fld1_ST0(void) @@ -1354,12 +1516,12 @@ void OPPROTO op_fld1_ST0(void)
1354 ST0 = *(CPU86_LDouble *)&f15rk[1]; 1516 ST0 = *(CPU86_LDouble *)&f15rk[1];
1355 } 1517 }
1356 1518
1357 -void OPPROTO op_fld2t_ST0(void) 1519 +void OPPROTO op_fldl2t_ST0(void)
1358 { 1520 {
1359 ST0 = *(CPU86_LDouble *)&f15rk[6]; 1521 ST0 = *(CPU86_LDouble *)&f15rk[6];
1360 } 1522 }
1361 1523
1362 -void OPPROTO op_fld2e_ST0(void) 1524 +void OPPROTO op_fldl2e_ST0(void)
1363 { 1525 {
1364 ST0 = *(CPU86_LDouble *)&f15rk[5]; 1526 ST0 = *(CPU86_LDouble *)&f15rk[5];
1365 } 1527 }
@@ -1681,6 +1843,13 @@ void OPPROTO op_fnstsw_A0(void) @@ -1681,6 +1843,13 @@ void OPPROTO op_fnstsw_A0(void)
1681 stw((void *)A0, fpus); 1843 stw((void *)A0, fpus);
1682 } 1844 }
1683 1845
  1846 +void OPPROTO op_fnstsw_EAX(void)
  1847 +{
  1848 + int fpus;
  1849 + fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
  1850 + EAX = (EAX & 0xffff0000) | fpus;
  1851 +}
  1852 +
1684 void OPPROTO op_fnstcw_A0(void) 1853 void OPPROTO op_fnstcw_A0(void)
1685 { 1854 {
1686 stw((void *)A0, env->fpuc); 1855 stw((void *)A0, env->fpuc);
@@ -1784,6 +1953,10 @@ int cpu_x86_exec(CPUX86State *env1) @@ -1784,6 +1953,10 @@ int cpu_x86_exec(CPUX86State *env1)
1784 eflags & CC_P ? 'P' : '-', 1953 eflags & CC_P ? 'P' : '-',
1785 eflags & CC_C ? 'C' : '-' 1954 eflags & CC_C ? 'C' : '-'
1786 ); 1955 );
  1956 +#if 1
  1957 + fprintf(logfile, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
  1958 + (double)ST0, (double)ST1, (double)ST(2), (double)ST(3));
  1959 +#endif
1787 } 1960 }
1788 #endif 1961 #endif
1789 cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc); 1962 cpu_x86_gen_code(code_gen_buffer, &code_gen_size, (uint8_t *)env->pc);
ops_template.h
@@ -633,6 +633,42 @@ void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void) @@ -633,6 +633,42 @@ void OPPROTO glue(glue(op_btc, SUFFIX), _T0_T1_cc)(void)
633 T0 ^= (1 << count); 633 T0 ^= (1 << count);
634 } 634 }
635 635
  636 +void OPPROTO glue(glue(op_bsf, SUFFIX), _T0_cc)(void)
  637 +{
  638 + int res, count;
  639 + res = T0 & DATA_MASK;
  640 + if (res != 0) {
  641 + count = 0;
  642 + while ((res & 1) == 0) {
  643 + count++;
  644 + res >>= 1;
  645 + }
  646 + T0 = count;
  647 + CC_DST = 1; /* ZF = 1 */
  648 + } else {
  649 + CC_DST = 0; /* ZF = 1 */
  650 + }
  651 + FORCE_RET();
  652 +}
  653 +
  654 +void OPPROTO glue(glue(op_bsr, SUFFIX), _T0_cc)(void)
  655 +{
  656 + int res, count;
  657 + res = T0 & DATA_MASK;
  658 + if (res != 0) {
  659 + count = DATA_BITS - 1;
  660 + while ((res & SIGN_MASK) == 0) {
  661 + count--;
  662 + res <<= 1;
  663 + }
  664 + T0 = count;
  665 + CC_DST = 1; /* ZF = 1 */
  666 + } else {
  667 + CC_DST = 0; /* ZF = 1 */
  668 + }
  669 + FORCE_RET();
  670 +}
  671 +
636 #endif 672 #endif
637 673
638 /* string operations */ 674 /* string operations */
translate-i386.c
@@ -431,6 +431,17 @@ static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = { @@ -431,6 +431,17 @@ static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
431 }, 431 },
432 }; 432 };
433 433
  434 +static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
  435 + [0] = {
  436 + gen_op_bsfw_T0_cc,
  437 + gen_op_bsrw_T0_cc,
  438 + },
  439 + [1] = {
  440 + gen_op_bsfl_T0_cc,
  441 + gen_op_bsrl_T0_cc,
  442 + },
  443 +};
  444 +
434 static GenOpFunc *gen_op_lds_T0_A0[3] = { 445 static GenOpFunc *gen_op_lds_T0_A0[3] = {
435 gen_op_ldsb_T0_A0, 446 gen_op_ldsb_T0_A0,
436 gen_op_ldsw_T0_A0, 447 gen_op_ldsw_T0_A0,
@@ -652,15 +663,16 @@ static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = { @@ -652,15 +663,16 @@ static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
652 gen_op_fdivr_ST0_FT0, 663 gen_op_fdivr_ST0_FT0,
653 }; 664 };
654 665
  666 +/* NOTE the exception in "r" op ordering */
655 static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = { 667 static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
656 gen_op_fadd_STN_ST0, 668 gen_op_fadd_STN_ST0,
657 gen_op_fmul_STN_ST0, 669 gen_op_fmul_STN_ST0,
658 NULL, 670 NULL,
659 NULL, 671 NULL,
660 - gen_op_fsub_STN_ST0,  
661 gen_op_fsubr_STN_ST0, 672 gen_op_fsubr_STN_ST0,
662 - gen_op_fdiv_STN_ST0, 673 + gen_op_fsub_STN_ST0,
663 gen_op_fdivr_STN_ST0, 674 gen_op_fdivr_STN_ST0,
  675 + gen_op_fdiv_STN_ST0,
664 }; 676 };
665 677
666 static void gen_op(DisasContext *s1, int op, int ot, int d, int s) 678 static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
@@ -1866,13 +1878,25 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -1866,13 +1878,25 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1866 case 0x0f: /* fnstcw mem */ 1878 case 0x0f: /* fnstcw mem */
1867 gen_op_fnstcw_A0(); 1879 gen_op_fnstcw_A0();
1868 break; 1880 break;
  1881 + case 0x1d: /* fldt mem */
  1882 + gen_op_fpush();
  1883 + gen_op_fldt_ST0_A0();
  1884 + break;
  1885 + case 0x1f: /* fstpt mem */
  1886 + gen_op_fstt_ST0_A0();
  1887 + gen_op_fpop();
  1888 + break;
1869 case 0x2f: /* fnstsw mem */ 1889 case 0x2f: /* fnstsw mem */
1870 gen_op_fnstsw_A0(); 1890 gen_op_fnstsw_A0();
1871 break; 1891 break;
1872 case 0x3c: /* fbld */ 1892 case 0x3c: /* fbld */
  1893 + gen_op_fpush();
  1894 + op_fbld_ST0_A0();
  1895 + break;
1873 case 0x3e: /* fbstp */ 1896 case 0x3e: /* fbstp */
1874 - error("float BCD not hanlded");  
1875 - return -1; 1897 + gen_op_fbst_ST0_A0();
  1898 + gen_op_fpop();
  1899 + break;
1876 case 0x3d: /* fildll */ 1900 case 0x3d: /* fildll */
1877 gen_op_fpush(); 1901 gen_op_fpush();
1878 gen_op_fildll_ST0_A0(); 1902 gen_op_fildll_ST0_A0();
@@ -1882,7 +1906,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -1882,7 +1906,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1882 gen_op_fpop(); 1906 gen_op_fpop();
1883 break; 1907 break;
1884 default: 1908 default:
1885 - error("unhandled memory FP [op=0x%02x]\n", op); 1909 + error("unhandled FPm [op=0x%02x]\n", op);
1886 return -1; 1910 return -1;
1887 } 1911 }
1888 } else { 1912 } else {
@@ -1895,7 +1919,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -1895,7 +1919,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1895 gen_op_fmov_ST0_STN((opreg + 1) & 7); 1919 gen_op_fmov_ST0_STN((opreg + 1) & 7);
1896 break; 1920 break;
1897 case 0x09: /* fxchg sti */ 1921 case 0x09: /* fxchg sti */
1898 - gen_op_fxchg_ST0_STN((opreg + 1) & 7); 1922 + gen_op_fxchg_ST0_STN(opreg);
1899 break; 1923 break;
1900 case 0x0a: /* grp d9/2 */ 1924 case 0x0a: /* grp d9/2 */
1901 switch(rm) { 1925 switch(rm) {
@@ -1929,24 +1953,31 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -1929,24 +1953,31 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
1929 { 1953 {
1930 switch(rm) { 1954 switch(rm) {
1931 case 0: 1955 case 0:
  1956 + gen_op_fpush();
1932 gen_op_fld1_ST0(); 1957 gen_op_fld1_ST0();
1933 break; 1958 break;
1934 case 1: 1959 case 1:
1935 - gen_op_fld2t_ST0(); 1960 + gen_op_fpush();
  1961 + gen_op_fldl2t_ST0();
1936 break; 1962 break;
1937 case 2: 1963 case 2:
1938 - gen_op_fld2e_ST0(); 1964 + gen_op_fpush();
  1965 + gen_op_fldl2e_ST0();
1939 break; 1966 break;
1940 case 3: 1967 case 3:
  1968 + gen_op_fpush();
1941 gen_op_fldpi_ST0(); 1969 gen_op_fldpi_ST0();
1942 break; 1970 break;
1943 case 4: 1971 case 4:
  1972 + gen_op_fpush();
1944 gen_op_fldlg2_ST0(); 1973 gen_op_fldlg2_ST0();
1945 break; 1974 break;
1946 case 5: 1975 case 5:
  1976 + gen_op_fpush();
1947 gen_op_fldln2_ST0(); 1977 gen_op_fldln2_ST0();
1948 break; 1978 break;
1949 case 6: 1979 case 6:
  1980 + gen_op_fpush();
1950 gen_op_fldz_ST0(); 1981 gen_op_fldz_ST0();
1951 break; 1982 break;
1952 default: 1983 default:
@@ -2021,12 +2052,12 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -2021,12 +2052,12 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2021 op1 = op & 7; 2052 op1 = op & 7;
2022 if (op >= 0x20) { 2053 if (op >= 0x20) {
2023 gen_op_fp_arith_STN_ST0[op1](opreg); 2054 gen_op_fp_arith_STN_ST0[op1](opreg);
  2055 + if (op >= 0x30)
  2056 + gen_op_fpop();
2024 } else { 2057 } else {
2025 gen_op_fmov_FT0_STN(opreg); 2058 gen_op_fmov_FT0_STN(opreg);
2026 gen_op_fp_arith_ST0_FT0[op1](); 2059 gen_op_fp_arith_ST0_FT0[op1]();
2027 } 2060 }
2028 - if (op >= 0x30)  
2029 - gen_op_fpop();  
2030 } 2061 }
2031 break; 2062 break;
2032 case 0x02: /* fcom */ 2063 case 0x02: /* fcom */
@@ -2042,7 +2073,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -2042,7 +2073,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2042 switch(rm) { 2073 switch(rm) {
2043 case 1: /* fucompp */ 2074 case 1: /* fucompp */
2044 gen_op_fmov_FT0_STN(1); 2075 gen_op_fmov_FT0_STN(1);
2045 - gen_op_fcom_ST0_FT0(); 2076 + gen_op_fucom_ST0_FT0();
2046 gen_op_fpop(); 2077 gen_op_fpop();
2047 gen_op_fpop(); 2078 gen_op_fpop();
2048 break; 2079 break;
@@ -2057,6 +2088,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -2057,6 +2088,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2057 gen_op_fmov_STN_ST0(opreg); 2088 gen_op_fmov_STN_ST0(opreg);
2058 gen_op_fpop(); 2089 gen_op_fpop();
2059 break; 2090 break;
  2091 + case 0x2c: /* fucom st(i) */
  2092 + gen_op_fmov_FT0_STN(opreg);
  2093 + gen_op_fucom_ST0_FT0();
  2094 + break;
  2095 + case 0x2d: /* fucomp st(i) */
  2096 + gen_op_fmov_FT0_STN(opreg);
  2097 + gen_op_fucom_ST0_FT0();
  2098 + gen_op_fpop();
  2099 + break;
2060 case 0x33: /* de/3 */ 2100 case 0x33: /* de/3 */
2061 switch(rm) { 2101 switch(rm) {
2062 case 1: /* fcompp */ 2102 case 1: /* fcompp */
@@ -2071,18 +2111,16 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -2071,18 +2111,16 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2071 break; 2111 break;
2072 case 0x3c: /* df/4 */ 2112 case 0x3c: /* df/4 */
2073 switch(rm) { 2113 switch(rm) {
2074 -#if 0  
2075 case 0: 2114 case 0:
2076 - gen_insn3(OP_FNSTS, OR_EAX, OR_ZERO, OR_ZERO); 2115 + gen_op_fnstsw_EAX();
2077 break; 2116 break;
2078 -#endif  
2079 default: 2117 default:
2080 - error("unhandled FP df/4\n"); 2118 + error("unhandled FP %x df/4\n", rm);
2081 return -1; 2119 return -1;
2082 } 2120 }
2083 break; 2121 break;
2084 default: 2122 default:
2085 - error("unhandled FP\n"); 2123 + error("unhandled FPr [op=0x%x]\n", op);
2086 return -1; 2124 return -1;
2087 } 2125 }
2088 } 2126 }
@@ -2413,7 +2451,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) @@ -2413,7 +2451,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr)
2413 gen_op_mov_reg_T0[ot][rm](); 2451 gen_op_mov_reg_T0[ot][rm]();
2414 } 2452 }
2415 break; 2453 break;
2416 - 2454 + case 0x1bc: /* bsf */
  2455 + case 0x1bd: /* bsr */
  2456 + ot = dflag ? OT_LONG : OT_WORD;
  2457 + modrm = ldub(s->pc++);
  2458 + reg = (modrm >> 3) & 7;
  2459 + gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
  2460 + gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
  2461 + /* NOTE: we always write back the result. Intel doc says it is
  2462 + undefined if T0 == 0 */
  2463 + gen_op_mov_reg_T0[ot][reg]();
  2464 + s->cc_op = CC_OP_LOGICB + ot;
  2465 + break;
2417 /************************/ 2466 /************************/
2418 /* misc */ 2467 /* misc */
2419 case 0x90: /* nop */ 2468 case 0x90: /* nop */