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 */ | ... | ... |