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