Commit dbc5594cb6294f34c257df11bef484e45493f85e

Authored by bellard
1 parent 4cbb86e1

finished simplifying string operations - correct TF flag handling for string ope…

…rations and ss loading - simplified basic block exit code generation


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@381 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 247 additions and 296 deletions
translate-i386.c
... ... @@ -60,11 +60,15 @@ typedef struct DisasContext {
60 60 int cpl;
61 61 int iopl;
62 62 int tf; /* TF cpu flag */
  63 + int jmp_opt; /* use direct block chaining for direct jumps */
63 64 int mem_index; /* select memory access functions */
64 65 struct TranslationBlock *tb;
65 66 int popl_esp_hack; /* for correct popl with esp base handling */
66 67 } DisasContext;
67 68  
  69 +static void gen_eob(DisasContext *s);
  70 +static void gen_jmp(DisasContext *s, unsigned int eip);
  71 +
68 72 /* i386 arith/logic operations */
69 73 enum {
70 74 OP_ADDL,
... ... @@ -635,31 +639,6 @@ static GenOpFunc *gen_op_st_T0_A0[3 * 3] = {
635 639 gen_op_stl_user_T0_A0,
636 640 };
637 641  
638   -/* the _a32 and _a16 string operations use A0 as the base register. */
639   -
640   -#define STRINGOP_NB 9
641   -
642   -#define STRINGOP(x) \
643   - gen_op_ ## x ## b_fast, \
644   - gen_op_ ## x ## w_fast, \
645   - gen_op_ ## x ## l_fast, \
646   - gen_op_ ## x ## b_a32, \
647   - gen_op_ ## x ## w_a32, \
648   - gen_op_ ## x ## l_a32, \
649   - gen_op_ ## x ## b_a16, \
650   - gen_op_ ## x ## w_a16, \
651   - gen_op_ ## x ## l_a16,
652   -
653   -static GenOpFunc *gen_op_scas[STRINGOP_NB * 3] = {
654   - STRINGOP(repz_scas)
655   - STRINGOP(repnz_scas)
656   -};
657   -
658   -static GenOpFunc *gen_op_cmps[STRINGOP_NB * 3] = {
659   - STRINGOP(repz_cmps)
660   - STRINGOP(repnz_cmps)
661   -};
662   -
663 642 static inline void gen_string_movl_A0_ESI(DisasContext *s)
664 643 {
665 644 int override;
... ... @@ -712,12 +691,17 @@ static GenOpFunc2 *gen_op_jz_ecx[2] = {
712 691 gen_op_jz_ecxl,
713 692 };
714 693  
  694 +static GenOpFunc1 *gen_op_jz_ecx_im[2] = {
  695 + gen_op_jz_ecxw_im,
  696 + gen_op_jz_ecxl_im,
  697 +};
  698 +
715 699 static GenOpFunc *gen_op_dec_ECX[2] = {
716 700 gen_op_decw_ECX,
717 701 gen_op_decl_ECX,
718 702 };
719 703  
720   -static GenOpFunc2 *gen_op_string_jnz_sub[2][3] = {
  704 +static GenOpFunc1 *gen_op_string_jnz_sub[2][3] = {
721 705 {
722 706 gen_op_string_jnz_subb,
723 707 gen_op_string_jnz_subw,
... ... @@ -730,6 +714,19 @@ static GenOpFunc2 *gen_op_string_jnz_sub[2][3] = {
730 714 },
731 715 };
732 716  
  717 +static GenOpFunc1 *gen_op_string_jnz_sub_im[2][3] = {
  718 + {
  719 + gen_op_string_jnz_subb_im,
  720 + gen_op_string_jnz_subw_im,
  721 + gen_op_string_jnz_subl_im,
  722 + },
  723 + {
  724 + gen_op_string_jz_subb_im,
  725 + gen_op_string_jz_subw_im,
  726 + gen_op_string_jz_subl_im,
  727 + },
  728 +};
  729 +
733 730 static GenOpFunc *gen_op_in_DX_T0[3] = {
734 731 gen_op_inb_DX_T0,
735 732 gen_op_inw_DX_T0,
... ... @@ -758,18 +755,23 @@ static inline void gen_movs(DisasContext *s, int ot)
758 755 }
759 756 }
760 757  
761   -/* same method as Valgrind : we generate jumps to current or next
762   - instruction */
763   -static inline void gen_repz_movs(DisasContext *s, int ot,
764   - unsigned int cur_eip, unsigned int next_eip)
  758 +static inline void gen_update_cc_op(DisasContext *s)
765 759 {
766   - if (s->cc_op != CC_OP_DYNAMIC)
  760 + if (s->cc_op != CC_OP_DYNAMIC) {
767 761 gen_op_set_cc_op(s->cc_op);
768   - gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
769   - gen_movs(s, ot);
770   - gen_op_dec_ECX[s->aflag]();
771   - gen_op_jmp_tb_next((long)s->tb, cur_eip);
772   - s->is_jmp = 3;
  762 + s->cc_op = CC_OP_DYNAMIC;
  763 + }
  764 +}
  765 +
  766 +static inline void gen_jz_ecx_string(DisasContext *s, unsigned int next_eip)
  767 +{
  768 + if (s->jmp_opt) {
  769 + gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
  770 + } else {
  771 + /* XXX: does not work with gdbstub "ice" single step - not a
  772 + serious problem */
  773 + gen_op_jz_ecx_im[s->aflag](next_eip);
  774 + }
773 775 }
774 776  
775 777 static inline void gen_stos(DisasContext *s, int ot)
... ... @@ -785,18 +787,6 @@ static inline void gen_stos(DisasContext *s, int ot)
785 787 }
786 788 }
787 789  
788   -static inline void gen_repz_stos(DisasContext *s, int ot,
789   - unsigned int cur_eip, unsigned int next_eip)
790   -{
791   - if (s->cc_op != CC_OP_DYNAMIC)
792   - gen_op_set_cc_op(s->cc_op);
793   - gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
794   - gen_stos(s, ot);
795   - gen_op_dec_ECX[s->aflag]();
796   - gen_op_jmp_tb_next((long)s->tb, cur_eip);
797   - s->is_jmp = 3;
798   -}
799   -
800 790 static inline void gen_lods(DisasContext *s, int ot)
801 791 {
802 792 gen_string_movl_A0_ESI(s);
... ... @@ -810,18 +800,6 @@ static inline void gen_lods(DisasContext *s, int ot)
810 800 }
811 801 }
812 802  
813   -static inline void gen_repz_lods(DisasContext *s, int ot,
814   - unsigned int cur_eip, unsigned int next_eip)
815   -{
816   - if (s->cc_op != CC_OP_DYNAMIC)
817   - gen_op_set_cc_op(s->cc_op);
818   - gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
819   - gen_lods(s, ot);
820   - gen_op_dec_ECX[s->aflag]();
821   - gen_op_jmp_tb_next((long)s->tb, cur_eip);
822   - s->is_jmp = 3;
823   -}
824   -
825 803 static inline void gen_scas(DisasContext *s, int ot)
826 804 {
827 805 gen_op_mov_TN_reg[OT_LONG][0][R_EAX]();
... ... @@ -836,23 +814,6 @@ static inline void gen_scas(DisasContext *s, int ot)
836 814 }
837 815 }
838 816  
839   -#if 0
840   -static inline void gen_repz_scas(DisasContext *s, int ot,
841   - unsigned int cur_eip, unsigned int next_eip,
842   - int nz)
843   -{
844   - if (s->cc_op != CC_OP_DYNAMIC)
845   - gen_op_set_cc_op(s->cc_op);
846   - gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
847   - gen_scas(s, ot);
848   - gen_op_set_cc_op(CC_OP_SUBB + ot);
849   - gen_op_string_jnz_sub[nz][ot]((long)s->tb, next_eip);
850   - gen_op_dec_ECX[s->aflag]();
851   - gen_op_jmp_tb_next((long)s->tb, cur_eip);
852   - s->is_jmp = 3;
853   -}
854   -#endif
855   -
856 817 static inline void gen_cmps(DisasContext *s, int ot)
857 818 {
858 819 gen_string_movl_A0_ESI(s);
... ... @@ -883,18 +844,6 @@ static inline void gen_ins(DisasContext *s, int ot)
883 844 }
884 845 }
885 846  
886   -static inline void gen_repz_ins(DisasContext *s, int ot,
887   - unsigned int cur_eip, unsigned int next_eip)
888   -{
889   - if (s->cc_op != CC_OP_DYNAMIC)
890   - gen_op_set_cc_op(s->cc_op);
891   - gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
892   - gen_ins(s, ot);
893   - gen_op_dec_ECX[s->aflag]();
894   - gen_op_jmp_tb_next((long)s->tb, cur_eip);
895   - s->is_jmp = 3;
896   -}
897   -
898 847 static inline void gen_outs(DisasContext *s, int ot)
899 848 {
900 849 gen_string_movl_A0_ESI(s);
... ... @@ -908,59 +857,50 @@ static inline void gen_outs(DisasContext *s, int ot)
908 857 }
909 858 }
910 859  
911   -static inline void gen_repz_outs(DisasContext *s, int ot,
912   - unsigned int cur_eip, unsigned int next_eip)
913   -{
914   - if (s->cc_op != CC_OP_DYNAMIC)
915   - gen_op_set_cc_op(s->cc_op);
916   - gen_op_jz_ecx[s->aflag]((long)s->tb, next_eip);
917   - gen_outs(s, ot);
918   - gen_op_dec_ECX[s->aflag]();
919   - gen_op_jmp_tb_next((long)s->tb, cur_eip);
920   - s->is_jmp = 3;
  860 +/* same method as Valgrind : we generate jumps to current or next
  861 + instruction */
  862 +#define GEN_REPZ(op) \
  863 +static inline void gen_repz_ ## op(DisasContext *s, int ot, \
  864 + unsigned int cur_eip, unsigned int next_eip) \
  865 +{ \
  866 + gen_update_cc_op(s); \
  867 + gen_jz_ecx_string(s, next_eip); \
  868 + gen_ ## op(s, ot); \
  869 + gen_op_dec_ECX[s->aflag](); \
  870 + /* a loop would cause two single step exceptions if ECX = 1 \
  871 + before rep string_insn */ \
  872 + if (!s->jmp_opt) \
  873 + gen_op_jz_ecx_im[s->aflag](next_eip); \
  874 + gen_jmp(s, cur_eip); \
921 875 }
922 876  
923   -static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
924   -{
925   - int index, override;
926   -
927   - override = s->override;
928   - if (s->aflag) {
929   - /* 32 bit address */
930   - if (s->addseg && override < 0)
931   - override = R_DS;
932   - if (override >= 0) {
933   - gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
934   - index = 3 + ot;
935   - } else {
936   - index = ot;
937   - }
938   - } else {
939   - if (override < 0)
940   - override = R_DS;
941   - gen_op_movl_A0_seg(offsetof(CPUX86State,segs[override].base));
942   - /* 16 address, always override */
943   - index = 6 + ot;
944   - }
945   - func[index]();
946   -}
947   -
948   -static inline void gen_string_es(DisasContext *s, int ot, GenOpFunc **func)
949   -{
950   - int index;
951   -
952   - if (s->aflag) {
953   - if (s->addseg) {
954   - index = 3 + ot;
955   - } else {
956   - index = ot;
957   - }
958   - } else {
959   - index = 6 + ot;
960   - }
961   - func[index]();
  877 +#define GEN_REPZ2(op) \
  878 +static inline void gen_repz_ ## op(DisasContext *s, int ot, \
  879 + unsigned int cur_eip, \
  880 + unsigned int next_eip, \
  881 + int nz) \
  882 +{ \
  883 + gen_update_cc_op(s); \
  884 + gen_jz_ecx_string(s, next_eip); \
  885 + gen_ ## op(s, ot); \
  886 + gen_op_dec_ECX[s->aflag](); \
  887 + gen_op_set_cc_op(CC_OP_SUBB + ot); \
  888 + if (!s->jmp_opt) \
  889 + gen_op_string_jnz_sub_im[nz][ot](next_eip); \
  890 + else \
  891 + gen_op_string_jnz_sub[nz][ot]((long)s->tb); \
  892 + if (!s->jmp_opt) \
  893 + gen_op_jz_ecx_im[s->aflag](next_eip); \
  894 + gen_jmp(s, cur_eip); \
962 895 }
963 896  
  897 +GEN_REPZ(movs)
  898 +GEN_REPZ(stos)
  899 +GEN_REPZ(lods)
  900 +GEN_REPZ(ins)
  901 +GEN_REPZ(outs)
  902 +GEN_REPZ2(scas)
  903 +GEN_REPZ2(cmps)
964 904  
965 905 static GenOpFunc *gen_op_in[3] = {
966 906 gen_op_inb_T0_T1,
... ... @@ -1420,71 +1360,86 @@ static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1420 1360  
1421 1361 inv = b & 1;
1422 1362 jcc_op = (b >> 1) & 7;
1423   - switch(s->cc_op) {
1424   - /* we optimize the cmp/jcc case */
1425   - case CC_OP_SUBB:
1426   - case CC_OP_SUBW:
1427   - case CC_OP_SUBL:
1428   - func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1429   - break;
1430   -
1431   - /* some jumps are easy to compute */
1432   - case CC_OP_ADDB:
1433   - case CC_OP_ADDW:
1434   - case CC_OP_ADDL:
1435   - case CC_OP_ADCB:
1436   - case CC_OP_ADCW:
1437   - case CC_OP_ADCL:
1438   - case CC_OP_SBBB:
1439   - case CC_OP_SBBW:
1440   - case CC_OP_SBBL:
1441   - case CC_OP_LOGICB:
1442   - case CC_OP_LOGICW:
1443   - case CC_OP_LOGICL:
1444   - case CC_OP_INCB:
1445   - case CC_OP_INCW:
1446   - case CC_OP_INCL:
1447   - case CC_OP_DECB:
1448   - case CC_OP_DECW:
1449   - case CC_OP_DECL:
1450   - case CC_OP_SHLB:
1451   - case CC_OP_SHLW:
1452   - case CC_OP_SHLL:
1453   - case CC_OP_SARB:
1454   - case CC_OP_SARW:
1455   - case CC_OP_SARL:
1456   - switch(jcc_op) {
1457   - case JCC_Z:
1458   - func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
  1363 +
  1364 + if (s->jmp_opt) {
  1365 + switch(s->cc_op) {
  1366 + /* we optimize the cmp/jcc case */
  1367 + case CC_OP_SUBB:
  1368 + case CC_OP_SUBW:
  1369 + case CC_OP_SUBL:
  1370 + func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1459 1371 break;
1460   - case JCC_S:
1461   - func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
  1372 +
  1373 + /* some jumps are easy to compute */
  1374 + case CC_OP_ADDB:
  1375 + case CC_OP_ADDW:
  1376 + case CC_OP_ADDL:
  1377 + case CC_OP_ADCB:
  1378 + case CC_OP_ADCW:
  1379 + case CC_OP_ADCL:
  1380 + case CC_OP_SBBB:
  1381 + case CC_OP_SBBW:
  1382 + case CC_OP_SBBL:
  1383 + case CC_OP_LOGICB:
  1384 + case CC_OP_LOGICW:
  1385 + case CC_OP_LOGICL:
  1386 + case CC_OP_INCB:
  1387 + case CC_OP_INCW:
  1388 + case CC_OP_INCL:
  1389 + case CC_OP_DECB:
  1390 + case CC_OP_DECW:
  1391 + case CC_OP_DECL:
  1392 + case CC_OP_SHLB:
  1393 + case CC_OP_SHLW:
  1394 + case CC_OP_SHLL:
  1395 + case CC_OP_SARB:
  1396 + case CC_OP_SARW:
  1397 + case CC_OP_SARL:
  1398 + switch(jcc_op) {
  1399 + case JCC_Z:
  1400 + func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
  1401 + break;
  1402 + case JCC_S:
  1403 + func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
  1404 + break;
  1405 + default:
  1406 + func = NULL;
  1407 + break;
  1408 + }
1462 1409 break;
1463 1410 default:
1464 1411 func = NULL;
1465 1412 break;
1466 1413 }
1467   - break;
1468   - default:
1469   - func = NULL;
1470   - break;
1471   - }
1472 1414  
1473   - if (s->cc_op != CC_OP_DYNAMIC)
1474   - gen_op_set_cc_op(s->cc_op);
  1415 + if (s->cc_op != CC_OP_DYNAMIC)
  1416 + gen_op_set_cc_op(s->cc_op);
1475 1417  
1476   - if (!func) {
1477   - gen_setcc_slow[jcc_op]();
1478   - func = gen_op_jcc;
1479   - }
  1418 + if (!func) {
  1419 + gen_setcc_slow[jcc_op]();
  1420 + func = gen_op_jcc;
  1421 + }
1480 1422  
1481   - tb = s->tb;
1482   - if (!inv) {
1483   - func((long)tb, val, next_eip);
  1423 + tb = s->tb;
  1424 + if (!inv) {
  1425 + func((long)tb, val, next_eip);
  1426 + } else {
  1427 + func((long)tb, next_eip, val);
  1428 + }
  1429 + s->is_jmp = 3;
1484 1430 } else {
1485   - func((long)tb, next_eip, val);
  1431 + if (s->cc_op != CC_OP_DYNAMIC) {
  1432 + gen_op_set_cc_op(s->cc_op);
  1433 + s->cc_op = CC_OP_DYNAMIC;
  1434 + }
  1435 + gen_setcc_slow[jcc_op]();
  1436 + if (!inv) {
  1437 + gen_op_jcc_im(val, next_eip);
  1438 + } else {
  1439 + gen_op_jcc_im(next_eip, val);
  1440 + }
  1441 + gen_eob(s);
1486 1442 }
1487   - s->is_jmp = 3;
1488 1443 }
1489 1444  
1490 1445 static void gen_setcc(DisasContext *s, int b)
... ... @@ -1557,7 +1512,7 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
1557 1512 stop as a special handling must be done to disable hardware
1558 1513 interrupts for the next instruction */
1559 1514 if (seg_reg == R_SS || (!s->addseg && seg_reg < R_FS))
1560   - s->is_jmp = 2;
  1515 + s->is_jmp = 3;
1561 1516 }
1562 1517  
1563 1518 /* generate a push. It depends on ss32, addseg and dflag */
... ... @@ -1727,7 +1682,7 @@ static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip)
1727 1682 gen_op_set_cc_op(s->cc_op);
1728 1683 gen_op_jmp_im(cur_eip);
1729 1684 gen_op_raise_exception(trapno);
1730   - s->is_jmp = 1;
  1685 + s->is_jmp = 3;
1731 1686 }
1732 1687  
1733 1688 /* an interrupt is different from an exception because of the
... ... @@ -1739,7 +1694,7 @@ static void gen_interrupt(DisasContext *s, int intno,
1739 1694 gen_op_set_cc_op(s->cc_op);
1740 1695 gen_op_jmp_im(cur_eip);
1741 1696 gen_op_raise_interrupt(intno, next_eip);
1742   - s->is_jmp = 1;
  1697 + s->is_jmp = 3;
1743 1698 }
1744 1699  
1745 1700 static void gen_debug(DisasContext *s, unsigned int cur_eip)
... ... @@ -1748,7 +1703,22 @@ static void gen_debug(DisasContext *s, unsigned int cur_eip)
1748 1703 gen_op_set_cc_op(s->cc_op);
1749 1704 gen_op_jmp_im(cur_eip);
1750 1705 gen_op_debug();
1751   - s->is_jmp = 1;
  1706 + s->is_jmp = 3;
  1707 +}
  1708 +
  1709 +/* generate a generic end of block. Trace exception is also generated
  1710 + if needed */
  1711 +static void gen_eob(DisasContext *s)
  1712 +{
  1713 + if (s->cc_op != CC_OP_DYNAMIC)
  1714 + gen_op_set_cc_op(s->cc_op);
  1715 + if (s->tf) {
  1716 + gen_op_raise_exception(EXCP01_SSTP);
  1717 + } else {
  1718 + gen_op_movl_T0_0();
  1719 + gen_op_exit_tb();
  1720 + }
  1721 + s->is_jmp = 3;
1752 1722 }
1753 1723  
1754 1724 /* generate a jump to eip. No segment change must happen before as a
... ... @@ -1757,16 +1727,20 @@ static void gen_jmp(DisasContext *s, unsigned int eip)
1757 1727 {
1758 1728 TranslationBlock *tb = s->tb;
1759 1729  
1760   - if (s->cc_op != CC_OP_DYNAMIC)
1761   - gen_op_set_cc_op(s->cc_op);
1762   - gen_op_jmp_tb_next((long)tb, eip);
1763   - s->is_jmp = 3;
  1730 + if (s->jmp_opt) {
  1731 + if (s->cc_op != CC_OP_DYNAMIC)
  1732 + gen_op_set_cc_op(s->cc_op);
  1733 + gen_op_jmp((long)tb, eip);
  1734 + s->is_jmp = 3;
  1735 + } else {
  1736 + gen_op_jmp_im(eip);
  1737 + gen_eob(s);
  1738 + }
1764 1739 }
1765 1740  
1766   -/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1767   - is set to true if the instruction sets the PC (last instruction of
1768   - a basic block) */
1769   -long disas_insn(DisasContext *s, uint8_t *pc_start)
  1741 +/* convert one instruction. s->is_jmp is set if the translation must
  1742 + be stopped. Return the next pc value */
  1743 +static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
1770 1744 {
1771 1745 int b, prefixes, aflag, dflag;
1772 1746 int shift, ot;
... ... @@ -2106,9 +2080,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2106 2080 next_eip = s->pc - s->cs_base;
2107 2081 gen_op_movl_T0_im(next_eip);
2108 2082 gen_push_T0(s);
2109   - s->is_jmp = 1;
  2083 + gen_eob(s);
2110 2084 break;
2111   - case 3: /* lcall Ev */
  2085 + case 3: /*< lcall Ev */
2112 2086 gen_op_ld_T1_A0[ot + s->mem_index]();
2113 2087 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2114 2088 gen_op_ld_T0_A0[OT_WORD + s->mem_index]();
... ... @@ -2121,13 +2095,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2121 2095 } else {
2122 2096 gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
2123 2097 }
2124   - s->is_jmp = 1;
  2098 + gen_eob(s);
2125 2099 break;
2126 2100 case 4: /* jmp Ev */
2127 2101 if (s->dflag == 0)
2128 2102 gen_op_andl_T0_ffff();
2129 2103 gen_op_jmp_T0();
2130   - s->is_jmp = 1;
  2104 + gen_eob(s);
2131 2105 break;
2132 2106 case 5: /* ljmp Ev */
2133 2107 gen_op_ld_T1_A0[ot + s->mem_index]();
... ... @@ -2144,7 +2118,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2144 2118 gen_op_movl_T0_T1();
2145 2119 gen_op_jmp_T0();
2146 2120 }
2147   - s->is_jmp = 1;
  2121 + gen_eob(s);
2148 2122 break;
2149 2123 case 6: /* push Ev */
2150 2124 gen_push_T0(s);
... ... @@ -2366,6 +2340,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2366 2340 if (reg == R_SS) {
2367 2341 /* if reg == SS, inhibit interrupts/trace */
2368 2342 gen_op_set_inhibit_irq();
  2343 + s->tf = 0;
  2344 + }
  2345 + if (s->is_jmp) {
  2346 + gen_op_jmp_im(s->pc - s->cs_base);
  2347 + gen_eob(s);
2369 2348 }
2370 2349 break;
2371 2350 case 0x1a1: /* pop fs */
... ... @@ -2373,6 +2352,10 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2373 2352 gen_pop_T0(s);
2374 2353 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
2375 2354 gen_pop_update(s);
  2355 + if (s->is_jmp) {
  2356 + gen_op_jmp_im(s->pc - s->cs_base);
  2357 + gen_eob(s);
  2358 + }
2376 2359 break;
2377 2360  
2378 2361 /**************************/
... ... @@ -2428,6 +2411,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2428 2411 if (reg == R_SS) {
2429 2412 /* if reg == SS, inhibit interrupts/trace */
2430 2413 gen_op_set_inhibit_irq();
  2414 + s->tf = 0;
  2415 + }
  2416 + if (s->is_jmp) {
  2417 + gen_op_jmp_im(s->pc - s->cs_base);
  2418 + gen_eob(s);
2431 2419 }
2432 2420 break;
2433 2421 case 0x8c: /* mov Gv, seg */
... ... @@ -2635,6 +2623,10 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2635 2623 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
2636 2624 /* then put the data */
2637 2625 gen_op_mov_reg_T1[ot][reg]();
  2626 + if (s->is_jmp) {
  2627 + gen_op_jmp_im(s->pc - s->cs_base);
  2628 + gen_eob(s);
  2629 + }
2638 2630 break;
2639 2631  
2640 2632 /************************/
... ... @@ -3191,15 +3183,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3191 3183 else
3192 3184 ot = dflag ? OT_LONG : OT_WORD;
3193 3185 if (prefixes & PREFIX_REPNZ) {
3194   - if (s->cc_op != CC_OP_DYNAMIC)
3195   - gen_op_set_cc_op(s->cc_op);
3196   - gen_string_es(s, ot, gen_op_scas + STRINGOP_NB);
3197   - s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
  3186 + gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
3198 3187 } else if (prefixes & PREFIX_REPZ) {
3199   - if (s->cc_op != CC_OP_DYNAMIC)
3200   - gen_op_set_cc_op(s->cc_op);
3201   - gen_string_es(s, ot, gen_op_scas);
3202   - s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
  3188 + gen_repz_scas(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
3203 3189 } else {
3204 3190 gen_scas(s, ot);
3205 3191 s->cc_op = CC_OP_SUBB + ot;
... ... @@ -3213,15 +3199,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3213 3199 else
3214 3200 ot = dflag ? OT_LONG : OT_WORD;
3215 3201 if (prefixes & PREFIX_REPNZ) {
3216   - if (s->cc_op != CC_OP_DYNAMIC)
3217   - gen_op_set_cc_op(s->cc_op);
3218   - gen_string_ds(s, ot, gen_op_cmps + STRINGOP_NB);
3219   - s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
  3202 + gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 1);
3220 3203 } else if (prefixes & PREFIX_REPZ) {
3221   - if (s->cc_op != CC_OP_DYNAMIC)
3222   - gen_op_set_cc_op(s->cc_op);
3223   - gen_string_ds(s, ot, gen_op_cmps);
3224   - s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
  3204 + gen_repz_cmps(s, ot, pc_start - s->cs_base, s->pc - s->cs_base, 0);
3225 3205 } else {
3226 3206 gen_cmps(s, ot);
3227 3207 s->cc_op = CC_OP_SUBB + ot;
... ... @@ -3333,7 +3313,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3333 3313 if (s->dflag == 0)
3334 3314 gen_op_andl_T0_ffff();
3335 3315 gen_op_jmp_T0();
3336   - s->is_jmp = 1;
  3316 + gen_eob(s);
3337 3317 break;
3338 3318 case 0xc3: /* ret */
3339 3319 gen_pop_T0(s);
... ... @@ -3341,7 +3321,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3341 3321 if (s->dflag == 0)
3342 3322 gen_op_andl_T0_ffff();
3343 3323 gen_op_jmp_T0();
3344   - s->is_jmp = 1;
  3324 + gen_eob(s);
3345 3325 break;
3346 3326 case 0xca: /* lret im */
3347 3327 val = ldsw(s->pc);
... ... @@ -3368,7 +3348,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3368 3348 /* add stack offset */
3369 3349 gen_stack_update(s, val + (4 << s->dflag));
3370 3350 }
3371   - s->is_jmp = 1;
  3351 + gen_eob(s);
3372 3352 break;
3373 3353 case 0xcb: /* lret */
3374 3354 val = 0;
... ... @@ -3387,7 +3367,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3387 3367 gen_op_iret_protected(s->dflag);
3388 3368 s->cc_op = CC_OP_EFLAGS;
3389 3369 }
3390   - s->is_jmp = 1;
  3370 + gen_eob(s);
3391 3371 break;
3392 3372 case 0xe8: /* call im */
3393 3373 {
... ... @@ -3512,7 +3492,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3512 3492 }
3513 3493 gen_pop_update(s);
3514 3494 s->cc_op = CC_OP_EFLAGS;
3515   - s->is_jmp = 2; /* abort translation because TF flag may change */
  3495 + /* abort translation because TF flag may change */
  3496 + gen_op_jmp_im(s->pc - s->cs_base);
  3497 + gen_eob(s);
3516 3498 }
3517 3499 break;
3518 3500 case 0x9e: /* sahf */
... ... @@ -3713,19 +3695,19 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3713 3695 case 0xfb: /* sti */
3714 3696 if (!s->vm86) {
3715 3697 if (s->cpl <= s->iopl) {
  3698 + gen_sti:
3716 3699 gen_op_sti();
3717 3700 /* interruptions are enabled only the first insn after sti */
3718 3701 gen_op_set_inhibit_irq();
3719   - s->is_jmp = 2; /* give a chance to handle pending irqs */
  3702 + /* give a chance to handle pending irqs */
  3703 + gen_op_jmp_im(s->pc - s->cs_base);
  3704 + gen_eob(s);
3720 3705 } else {
3721 3706 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3722 3707 }
3723 3708 } else {
3724 3709 if (s->iopl == 3) {
3725   - gen_op_sti();
3726   - /* interruptions are enabled only the first insn after sti */
3727   - gen_op_set_inhibit_irq();
3728   - s->is_jmp = 2; /* give a chance to handle pending irqs */
  3710 + goto gen_sti;
3729 3711 } else {
3730 3712 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3731 3713 }
... ... @@ -3769,7 +3751,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3769 3751 if (s->dflag == 0)
3770 3752 val &= 0xffff;
3771 3753 gen_op_loop[s->aflag][b & 3](val, next_eip);
3772   - s->is_jmp = 1;
  3754 + gen_eob(s);
3773 3755 break;
3774 3756 case 0x130: /* wrmsr */
3775 3757 case 0x132: /* rdmsr */
... ... @@ -3796,7 +3778,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3796 3778 gen_op_set_cc_op(s->cc_op);
3797 3779 gen_op_jmp_im(s->pc - s->cs_base);
3798 3780 gen_op_hlt();
3799   - s->is_jmp = 1;
  3781 + s->is_jmp = 3;
3800 3782 }
3801 3783 break;
3802 3784 case 0x100:
... ... @@ -3968,7 +3950,8 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3968 3950 if (b & 2) {
3969 3951 gen_op_mov_TN_reg[OT_LONG][0][rm]();
3970 3952 gen_op_movl_crN_T0(reg);
3971   - s->is_jmp = 2;
  3953 + gen_op_jmp_im(s->pc - s->cs_base);
  3954 + gen_eob(s);
3972 3955 } else {
3973 3956 gen_op_movl_T0_env(offsetof(CPUX86State,cr[reg]));
3974 3957 gen_op_mov_reg_T0[OT_LONG][rm]();
... ... @@ -3995,7 +3978,8 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3995 3978 if (b & 2) {
3996 3979 gen_op_mov_TN_reg[OT_LONG][0][rm]();
3997 3980 gen_op_movl_drN_T0(reg);
3998   - s->is_jmp = 2;
  3981 + gen_op_jmp_im(s->pc - s->cs_base);
  3982 + gen_eob(s);
3999 3983 } else {
4000 3984 gen_op_movl_T0_env(offsetof(CPUX86State,dr[reg]));
4001 3985 gen_op_mov_reg_T0[OT_LONG][rm]();
... ... @@ -4015,10 +3999,11 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
4015 3999 /* lock generation */
4016 4000 if (s->prefix & PREFIX_LOCK)
4017 4001 gen_op_unlock();
4018   - return (long)s->pc;
  4002 + return s->pc;
4019 4003 illegal_op:
4020 4004 /* XXX: ensure that no lock was generated */
4021   - return -1;
  4005 + gen_exception(s, EXCP06_ILLOP, pc_start - s->cs_base);
  4006 + return s->pc;
4022 4007 }
4023 4008  
4024 4009 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
... ... @@ -4265,23 +4250,6 @@ static uint16_t opc_write_flags[NB_OPS] = {
4265 4250 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
4266 4251 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
4267 4252  
4268   -#undef STRINGOP
4269   -#define STRINGOP(x) \
4270   - [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
4271   - [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
4272   - [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
4273   - [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
4274   - [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
4275   - [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
4276   - [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
4277   - [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
4278   - [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
4279   -
4280   - STRINGOP(repz_scas)
4281   - STRINGOP(repnz_scas)
4282   - STRINGOP(repz_cmps)
4283   - STRINGOP(repnz_cmps)
4284   -
4285 4253 [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
4286 4254 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
4287 4255 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
... ... @@ -4383,7 +4351,6 @@ static inline int gen_intermediate_code_internal(CPUState *env,
4383 4351 uint8_t *pc_ptr;
4384 4352 uint16_t *gen_opc_end;
4385 4353 int flags, j, lj;
4386   - long ret;
4387 4354 uint8_t *pc_start;
4388 4355 uint8_t *cs_base;
4389 4356  
... ... @@ -4413,7 +4380,11 @@ static inline int gen_intermediate_code_internal(CPUState *env,
4413 4380 else
4414 4381 dc->mem_index = 3;
4415 4382 }
4416   -
  4383 + dc->jmp_opt = !(dc->tf || env->singlestep_enabled
  4384 +#ifndef CONFIG_SOFT_MMU
  4385 + || (flags & HF_SOFTMMU_MASK)
  4386 +#endif
  4387 + );
4417 4388 gen_opc_ptr = gen_opc_buf;
4418 4389 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
4419 4390 gen_opparam_ptr = gen_opparam_buf;
... ... @@ -4428,12 +4399,12 @@ static inline int gen_intermediate_code_internal(CPUState *env,
4428 4399 if (flags & HF_INHIBIT_IRQ_MASK) {
4429 4400 gen_op_reset_inhibit_irq();
4430 4401 }
4431   - do {
  4402 + for(;;) {
4432 4403 if (env->nb_breakpoints > 0) {
4433 4404 for(j = 0; j < env->nb_breakpoints; j++) {
4434 4405 if (env->breakpoints[j] == (unsigned long)pc_ptr) {
4435 4406 gen_debug(dc, pc_ptr - dc->cs_base);
4436   - goto the_end;
  4407 + break;
4437 4408 }
4438 4409 }
4439 4410 }
... ... @@ -4448,44 +4419,24 @@ static inline int gen_intermediate_code_internal(CPUState *env,
4448 4419 gen_opc_cc_op[lj] = dc->cc_op;
4449 4420 gen_opc_instr_start[lj] = 1;
4450 4421 }
4451   - ret = disas_insn(dc, pc_ptr);
4452   - if (ret == -1) {
4453   - /* we trigger an illegal instruction operation only if it
4454   - is the first instruction. Otherwise, we simply stop
4455   - generating the code just before it */
4456   - if (pc_ptr == pc_start)
4457   - return -1;
4458   - else
4459   - break;
4460   - }
4461   - pc_ptr = (void *)ret;
  4422 + pc_ptr = disas_insn(dc, pc_ptr);
  4423 + /* stop translation if indicated */
  4424 + if (dc->is_jmp)
  4425 + break;
4462 4426 /* if single step mode, we generate only one instruction and
4463 4427 generate an exception */
4464   - if (dc->tf)
  4428 + if (dc->tf) {
  4429 + gen_op_jmp_im(pc_ptr - dc->cs_base);
  4430 + gen_eob(dc);
  4431 + break;
  4432 + }
  4433 + /* if too long translation, stop generation too */
  4434 + if (gen_opc_ptr >= gen_opc_end ||
  4435 + (pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
  4436 + gen_op_jmp_im(pc_ptr - dc->cs_base);
  4437 + gen_eob(dc);
4465 4438 break;
4466   - } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
4467   - (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
4468   - if (!dc->tf && dc->is_jmp == DISAS_NEXT) {
4469   - gen_jmp(dc, ret - (unsigned long)dc->cs_base);
4470   - }
4471   -
4472   - /* we must store the eflags state if it is not already done */
4473   - if (dc->is_jmp != DISAS_TB_JUMP) {
4474   - if (dc->cc_op != CC_OP_DYNAMIC)
4475   - gen_op_set_cc_op(dc->cc_op);
4476   - if (dc->is_jmp != DISAS_JUMP) {
4477   - /* we add an additionnal jmp to update the simulated PC */
4478   - gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
4479 4439 }
4480   - }
4481   - if (dc->tf) {
4482   - gen_op_raise_exception(EXCP01_SSTP);
4483   - }
4484   - the_end:
4485   - if (dc->is_jmp != DISAS_TB_JUMP) {
4486   - /* indicate that the hash table must be used to find the next TB */
4487   - gen_op_movl_T0_0();
4488   - gen_op_exit_tb();
4489 4440 }
4490 4441 *gen_opc_ptr = INDEX_op_end;
4491 4442 /* we don't forget to fill the last values */
... ...