Revision dbc5594c

b/translate-i386.c
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 */

Also available in: Unified diff