Commit 77f8dd5add8f02253dcea1454c9d2c76d7c788a7
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
Showing
6 changed files
with
285 additions
and
26 deletions
Makefile
... | ... | @@ -83,6 +83,7 @@ cpu-i386.h gemu.h op-i386.c syscall-i386.h translate-i386.c\ |
83 | 83 | dis-asm.h gen-i386.h op-i386.h syscall.c\ |
84 | 84 | dis-buf.c i386-dis.c opreg_template.h syscall_defs.h\ |
85 | 85 | i386.ld ppc.ld\ |
86 | +tests/Makefile\ | |
86 | 87 | tests/test-i386.c tests/test-i386-shift.h tests/test-i386.h\ |
87 | 88 | tests/test-i386-muldiv.h\ |
88 | 89 | tests/test2.c tests/hello.c tests/sha1.c tests/test1.c | ... | ... |
TODO
cpu-i386.h
... | ... | @@ -114,7 +114,7 @@ enum { |
114 | 114 | }; |
115 | 115 | |
116 | 116 | #ifdef __i386__ |
117 | -#define USE_X86LDOUBLE | |
117 | +//#define USE_X86LDOUBLE | |
118 | 118 | #endif |
119 | 119 | |
120 | 120 | #ifdef USE_X86LDOUBLE |
... | ... | @@ -201,7 +201,7 @@ static inline void stl(void *ptr, int v) |
201 | 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 | 206 | *(uint64_t *)ptr = v; |
207 | 207 | } | ... | ... |
op-i386.c
... | ... | @@ -1055,7 +1055,7 @@ typedef union { |
1055 | 1055 | |
1056 | 1056 | #else |
1057 | 1057 | |
1058 | -typedef { | |
1058 | +typedef union { | |
1059 | 1059 | double d; |
1060 | 1060 | #ifndef WORDS_BIGENDIAN |
1061 | 1061 | struct { |
... | ... | @@ -1119,6 +1119,31 @@ void OPPROTO op_fldl_ST0_A0(void) |
1119 | 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 | 1147 | void OPPROTO op_fild_ST0_A0(void) |
1123 | 1148 | { |
1124 | 1149 | ST0 = (CPU86_LDouble)ldsw((void *)A0); |
... | ... | @@ -1143,9 +1168,34 @@ void OPPROTO op_fsts_ST0_A0(void) |
1143 | 1168 | |
1144 | 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 | 1199 | void OPPROTO op_fist_ST0_A0(void) |
1150 | 1200 | { |
1151 | 1201 | int val; |
... | ... | @@ -1167,6 +1217,103 @@ void OPPROTO op_fistll_ST0_A0(void) |
1167 | 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 | 1317 | /* FPU move */ |
1171 | 1318 | |
1172 | 1319 | static inline void fpush(void) |
... | ... | @@ -1244,6 +1391,17 @@ void OPPROTO op_fcom_ST0_FT0(void) |
1244 | 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 | 1405 | void OPPROTO op_fadd_ST0_FT0(void) |
1248 | 1406 | { |
1249 | 1407 | ST0 += FT0; |
... | ... | @@ -1321,7 +1479,7 @@ void OPPROTO op_fabs_ST0(void) |
1321 | 1479 | ST0 = fabs(ST0); |
1322 | 1480 | } |
1323 | 1481 | |
1324 | -void OPPROTO op_fxam_ST0(void) | |
1482 | +void helper_fxam_ST0(void) | |
1325 | 1483 | { |
1326 | 1484 | CPU86_LDoubleU temp; |
1327 | 1485 | int expdif; |
... | ... | @@ -1346,7 +1504,11 @@ void OPPROTO op_fxam_ST0(void) |
1346 | 1504 | } else { |
1347 | 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 | 1514 | void OPPROTO op_fld1_ST0(void) |
... | ... | @@ -1354,12 +1516,12 @@ void OPPROTO op_fld1_ST0(void) |
1354 | 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 | 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 | 1526 | ST0 = *(CPU86_LDouble *)&f15rk[5]; |
1365 | 1527 | } |
... | ... | @@ -1681,6 +1843,13 @@ void OPPROTO op_fnstsw_A0(void) |
1681 | 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 | 1853 | void OPPROTO op_fnstcw_A0(void) |
1685 | 1854 | { |
1686 | 1855 | stw((void *)A0, env->fpuc); |
... | ... | @@ -1784,6 +1953,10 @@ int cpu_x86_exec(CPUX86State *env1) |
1784 | 1953 | eflags & CC_P ? 'P' : '-', |
1785 | 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 | 1961 | #endif |
1789 | 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 | 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 | 672 | #endif |
637 | 673 | |
638 | 674 | /* string operations */ | ... | ... |
translate-i386.c
... | ... | @@ -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 | 445 | static GenOpFunc *gen_op_lds_T0_A0[3] = { |
435 | 446 | gen_op_ldsb_T0_A0, |
436 | 447 | gen_op_ldsw_T0_A0, |
... | ... | @@ -652,15 +663,16 @@ static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = { |
652 | 663 | gen_op_fdivr_ST0_FT0, |
653 | 664 | }; |
654 | 665 | |
666 | +/* NOTE the exception in "r" op ordering */ | |
655 | 667 | static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = { |
656 | 668 | gen_op_fadd_STN_ST0, |
657 | 669 | gen_op_fmul_STN_ST0, |
658 | 670 | NULL, |
659 | 671 | NULL, |
660 | - gen_op_fsub_STN_ST0, | |
661 | 672 | gen_op_fsubr_STN_ST0, |
662 | - gen_op_fdiv_STN_ST0, | |
673 | + gen_op_fsub_STN_ST0, | |
663 | 674 | gen_op_fdivr_STN_ST0, |
675 | + gen_op_fdiv_STN_ST0, | |
664 | 676 | }; |
665 | 677 | |
666 | 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 | 1878 | case 0x0f: /* fnstcw mem */ |
1867 | 1879 | gen_op_fnstcw_A0(); |
1868 | 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 | 1889 | case 0x2f: /* fnstsw mem */ |
1870 | 1890 | gen_op_fnstsw_A0(); |
1871 | 1891 | break; |
1872 | 1892 | case 0x3c: /* fbld */ |
1893 | + gen_op_fpush(); | |
1894 | + op_fbld_ST0_A0(); | |
1895 | + break; | |
1873 | 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 | 1900 | case 0x3d: /* fildll */ |
1877 | 1901 | gen_op_fpush(); |
1878 | 1902 | gen_op_fildll_ST0_A0(); |
... | ... | @@ -1882,7 +1906,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) |
1882 | 1906 | gen_op_fpop(); |
1883 | 1907 | break; |
1884 | 1908 | default: |
1885 | - error("unhandled memory FP [op=0x%02x]\n", op); | |
1909 | + error("unhandled FPm [op=0x%02x]\n", op); | |
1886 | 1910 | return -1; |
1887 | 1911 | } |
1888 | 1912 | } else { |
... | ... | @@ -1895,7 +1919,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) |
1895 | 1919 | gen_op_fmov_ST0_STN((opreg + 1) & 7); |
1896 | 1920 | break; |
1897 | 1921 | case 0x09: /* fxchg sti */ |
1898 | - gen_op_fxchg_ST0_STN((opreg + 1) & 7); | |
1922 | + gen_op_fxchg_ST0_STN(opreg); | |
1899 | 1923 | break; |
1900 | 1924 | case 0x0a: /* grp d9/2 */ |
1901 | 1925 | switch(rm) { |
... | ... | @@ -1929,24 +1953,31 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) |
1929 | 1953 | { |
1930 | 1954 | switch(rm) { |
1931 | 1955 | case 0: |
1956 | + gen_op_fpush(); | |
1932 | 1957 | gen_op_fld1_ST0(); |
1933 | 1958 | break; |
1934 | 1959 | case 1: |
1935 | - gen_op_fld2t_ST0(); | |
1960 | + gen_op_fpush(); | |
1961 | + gen_op_fldl2t_ST0(); | |
1936 | 1962 | break; |
1937 | 1963 | case 2: |
1938 | - gen_op_fld2e_ST0(); | |
1964 | + gen_op_fpush(); | |
1965 | + gen_op_fldl2e_ST0(); | |
1939 | 1966 | break; |
1940 | 1967 | case 3: |
1968 | + gen_op_fpush(); | |
1941 | 1969 | gen_op_fldpi_ST0(); |
1942 | 1970 | break; |
1943 | 1971 | case 4: |
1972 | + gen_op_fpush(); | |
1944 | 1973 | gen_op_fldlg2_ST0(); |
1945 | 1974 | break; |
1946 | 1975 | case 5: |
1976 | + gen_op_fpush(); | |
1947 | 1977 | gen_op_fldln2_ST0(); |
1948 | 1978 | break; |
1949 | 1979 | case 6: |
1980 | + gen_op_fpush(); | |
1950 | 1981 | gen_op_fldz_ST0(); |
1951 | 1982 | break; |
1952 | 1983 | default: |
... | ... | @@ -2021,12 +2052,12 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) |
2021 | 2052 | op1 = op & 7; |
2022 | 2053 | if (op >= 0x20) { |
2023 | 2054 | gen_op_fp_arith_STN_ST0[op1](opreg); |
2055 | + if (op >= 0x30) | |
2056 | + gen_op_fpop(); | |
2024 | 2057 | } else { |
2025 | 2058 | gen_op_fmov_FT0_STN(opreg); |
2026 | 2059 | gen_op_fp_arith_ST0_FT0[op1](); |
2027 | 2060 | } |
2028 | - if (op >= 0x30) | |
2029 | - gen_op_fpop(); | |
2030 | 2061 | } |
2031 | 2062 | break; |
2032 | 2063 | case 0x02: /* fcom */ |
... | ... | @@ -2042,7 +2073,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) |
2042 | 2073 | switch(rm) { |
2043 | 2074 | case 1: /* fucompp */ |
2044 | 2075 | gen_op_fmov_FT0_STN(1); |
2045 | - gen_op_fcom_ST0_FT0(); | |
2076 | + gen_op_fucom_ST0_FT0(); | |
2046 | 2077 | gen_op_fpop(); |
2047 | 2078 | gen_op_fpop(); |
2048 | 2079 | break; |
... | ... | @@ -2057,6 +2088,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) |
2057 | 2088 | gen_op_fmov_STN_ST0(opreg); |
2058 | 2089 | gen_op_fpop(); |
2059 | 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 | 2100 | case 0x33: /* de/3 */ |
2061 | 2101 | switch(rm) { |
2062 | 2102 | case 1: /* fcompp */ |
... | ... | @@ -2071,18 +2111,16 @@ long disas_insn(DisasContext *s, uint8_t *pc_start, int *is_jmp_ptr) |
2071 | 2111 | break; |
2072 | 2112 | case 0x3c: /* df/4 */ |
2073 | 2113 | switch(rm) { |
2074 | -#if 0 | |
2075 | 2114 | case 0: |
2076 | - gen_insn3(OP_FNSTS, OR_EAX, OR_ZERO, OR_ZERO); | |
2115 | + gen_op_fnstsw_EAX(); | |
2077 | 2116 | break; |
2078 | -#endif | |
2079 | 2117 | default: |
2080 | - error("unhandled FP df/4\n"); | |
2118 | + error("unhandled FP %x df/4\n", rm); | |
2081 | 2119 | return -1; |
2082 | 2120 | } |
2083 | 2121 | break; |
2084 | 2122 | default: |
2085 | - error("unhandled FP\n"); | |
2123 | + error("unhandled FPr [op=0x%x]\n", op); | |
2086 | 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 | 2451 | gen_op_mov_reg_T0[ot][rm](); |
2414 | 2452 | } |
2415 | 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 | 2467 | /* misc */ |
2419 | 2468 | case 0x90: /* nop */ | ... | ... |