Revision 2c1794c4

b/exec-i386.h
123 123
extern CCTable cc_table[];
124 124

  
125 125
void load_seg(int seg_reg, int selector, unsigned cur_eip);
126
void jmp_seg(int selector, unsigned int new_eip);
126
void helper_ljmp_protected_T0_T1(void);
127
void helper_lcall_real_T0_T1(int shift, int next_eip);
128
void helper_lcall_protected_T0_T1(int shift, int next_eip);
129
void helper_iret_real(int shift);
127 130
void helper_iret_protected(int shift);
131
void helper_lret_protected(int shift, int addend);
128 132
void helper_lldt_T0(void);
129 133
void helper_ltr_T0(void);
130 134
void helper_movl_crN_T0(int reg);
b/helper-i386.c
185 185

  
186 186
/* protected mode interrupt */
187 187
static void do_interrupt_protected(int intno, int is_int, int error_code,
188
                                      unsigned int next_eip)
188
                                   unsigned int next_eip)
189 189
{
190 190
    SegmentCache *dt;
191 191
    uint8_t *ptr, *ssp;
......
378 378
    ptr = dt->base + intno * 4;
379 379
    offset = lduw(ptr);
380 380
    selector = lduw(ptr + 2);
381
    esp = env->regs[R_ESP] & 0xffff;
382
    ssp = env->segs[R_SS].base + esp;
381
    esp = env->regs[R_ESP];
382
    ssp = env->segs[R_SS].base;
383 383
    if (is_int)
384 384
        old_eip = next_eip;
385 385
    else
386 386
        old_eip = env->eip;
387 387
    old_cs = env->segs[R_CS].selector;
388
    ssp -= 2;
389
    stw(ssp, compute_eflags());
390
    ssp -= 2;
391
    stw(ssp, old_cs);
392
    ssp -= 2;
393
    stw(ssp, old_eip);
394
    esp -= 6;
388
    esp -= 2;
389
    stw(ssp + (esp & 0xffff), compute_eflags());
390
    esp -= 2;
391
    stw(ssp + (esp & 0xffff), old_cs);
392
    esp -= 2;
393
    stw(ssp + (esp & 0xffff), old_eip);
395 394
    
396 395
    /* update processor state */
397 396
    env->regs[R_ESP] = (env->regs[R_ESP] & ~0xffff) | (esp & 0xffff);
......
733 732
}
734 733

  
735 734
/* protected mode jump */
736
void jmp_seg(int selector, unsigned int new_eip)
735
void helper_ljmp_protected_T0_T1(void)
737 736
{
737
    int new_cs, new_eip;
738 738
    SegmentCache sc1;
739 739
    uint32_t e1, e2, cpl, dpl, rpl;
740 740

  
741
    if ((selector & 0xfffc) == 0) {
741
    new_cs = T0;
742
    new_eip = T1;
743
    if ((new_cs & 0xfffc) == 0)
742 744
        raise_exception_err(EXCP0D_GPF, 0);
745
    if (load_segment(&e1, &e2, new_cs) != 0)
746
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
747
    cpl = env->segs[R_CS].selector & 3;
748
    if (e2 & DESC_S_MASK) {
749
        if (!(e2 & DESC_CS_MASK))
750
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
751
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
752
        if (e2 & DESC_CS_MASK) {
753
            /* conforming code segment */
754
            if (dpl > cpl)
755
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
756
        } else {
757
            /* non conforming code segment */
758
            rpl = new_cs & 3;
759
            if (rpl > cpl)
760
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
761
            if (dpl != cpl)
762
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
763
        }
764
        if (!(e2 & DESC_P_MASK))
765
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
766
        load_seg_cache(&sc1, e1, e2);
767
        if (new_eip > sc1.limit)
768
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
769
        env->segs[R_CS].base = sc1.base;
770
        env->segs[R_CS].limit = sc1.limit;
771
        env->segs[R_CS].flags = sc1.flags;
772
        env->segs[R_CS].selector = (new_cs & 0xfffc) | cpl;
773
        EIP = new_eip;
774
    } else {
775
        cpu_abort(env, "jmp to call/task gate not supported 0x%04x:0x%08x", 
776
                  new_cs, new_eip);
743 777
    }
778
}
744 779

  
745
    if (load_segment(&e1, &e2, selector) != 0)
746
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
780
/* real mode call */
781
void helper_lcall_real_T0_T1(int shift, int next_eip)
782
{
783
    int new_cs, new_eip;
784
    uint32_t esp, esp_mask;
785
    uint8_t *ssp;
786
    
787
    new_cs = T0;
788
    new_eip = T1;
789
    esp = env->regs[R_ESP];
790
    esp_mask = 0xffffffff;
791
    if (!(env->segs[R_SS].flags & DESC_B_MASK))
792
        esp_mask = 0xffff;
793
    ssp = env->segs[R_SS].base;
794
    if (shift) {
795
        esp -= 4;
796
        stl(ssp + (esp & esp_mask), env->segs[R_CS].selector);
797
        esp -= 4;
798
        stl(ssp + (esp & esp_mask), next_eip);
799
    } else {
800
        esp -= 2;
801
        stw(ssp + (esp & esp_mask), env->segs[R_CS].selector);
802
        esp -= 2;
803
        stw(ssp + (esp & esp_mask), next_eip);
804
    }
805

  
806
    if (!(env->segs[R_SS].flags & DESC_B_MASK))
807
        env->regs[R_ESP] = (env->regs[R_ESP] & ~0xffff) | (esp & 0xffff);
808
    else
809
        env->regs[R_ESP] = esp;
810
    env->eip = new_eip;
811
    env->segs[R_CS].selector = new_cs;
812
    env->segs[R_CS].base = (uint8_t *)(new_cs << 4);
813
}
814

  
815
/* protected mode call */
816
void helper_lcall_protected_T0_T1(int shift, int next_eip)
817
{
818
    int new_cs, new_eip;
819
    SegmentCache sc1;
820
    uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
821
    uint32_t ss, ss_e1, ss_e2, push_size, sp, type, ss_dpl;
822
    uint32_t old_ss, old_esp, val, i;
823
    uint8_t *ssp, *old_ssp;
824
    
825
    new_cs = T0;
826
    new_eip = T1;
827
    if ((new_cs & 0xfffc) == 0)
828
        raise_exception_err(EXCP0D_GPF, 0);
829
    if (load_segment(&e1, &e2, new_cs) != 0)
830
        raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
747 831
    cpl = env->segs[R_CS].selector & 3;
748 832
    if (e2 & DESC_S_MASK) {
749 833
        if (!(e2 & DESC_CS_MASK))
750
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
834
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
751 835
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
752 836
        if (e2 & DESC_CS_MASK) {
753 837
            /* conforming code segment */
754 838
            if (dpl > cpl)
755
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
839
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
756 840
        } else {
757 841
            /* non conforming code segment */
758
            rpl = selector & 3;
842
            rpl = new_cs & 3;
759 843
            if (rpl > cpl)
760
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
844
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
761 845
            if (dpl != cpl)
762
                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
846
                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
763 847
        }
764 848
        if (!(e2 & DESC_P_MASK))
765
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
849
            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
850

  
851
        sp = env->regs[R_ESP];
852
        if (!(env->segs[R_SS].flags & DESC_B_MASK))
853
            sp &= 0xffff;
854
        ssp = env->segs[R_SS].base + sp;
855
        if (shift) {
856
            ssp -= 4;
857
            stl(ssp, env->segs[R_CS].selector);
858
            ssp -= 4;
859
            stl(ssp, next_eip);
860
        } else {
861
            ssp -= 2;
862
            stw(ssp, env->segs[R_CS].selector);
863
            ssp -= 2;
864
            stw(ssp, next_eip);
865
        }
866
        sp -= (4 << shift);
867
        
766 868
        load_seg_cache(&sc1, e1, e2);
767 869
        if (new_eip > sc1.limit)
768
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
870
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
871
        /* from this point, not restartable */
872
        if (!(env->segs[R_SS].flags & DESC_B_MASK))
873
            env->regs[R_ESP] = (env->regs[R_ESP] & 0xffff0000) | (sp & 0xffff);
874
        else
875
            env->regs[R_ESP] = sp;
769 876
        env->segs[R_CS].base = sc1.base;
770 877
        env->segs[R_CS].limit = sc1.limit;
771 878
        env->segs[R_CS].flags = sc1.flags;
772
        env->segs[R_CS].selector = (selector & 0xfffc) | cpl;
879
        env->segs[R_CS].selector = (new_cs & 0xfffc) | cpl;
773 880
        EIP = new_eip;
774 881
    } else {
775
        cpu_abort(env, "jmp to call/task gate not supported 0x%04x:0x%08x", 
776
                  selector, new_eip);
882
        /* check gate type */
883
        type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
884
        switch(type) {
885
        case 1: /* available 286 TSS */
886
        case 9: /* available 386 TSS */
887
        case 5: /* task gate */
888
            cpu_abort(env, "task gate not supported");
889
            break;
890
        case 4: /* 286 call gate */
891
        case 12: /* 386 call gate */
892
            break;
893
        default:
894
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
895
            break;
896
        }
897
        shift = type >> 3;
898

  
899
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
900
        rpl = new_cs & 3;
901
        if (dpl < cpl || dpl < rpl)
902
            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
903
        /* check valid bit */
904
        if (!(e2 & DESC_P_MASK))
905
            raise_exception_err(EXCP0B_NOSEG,  new_cs & 0xfffc);
906
        selector = e1 >> 16;
907
        offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
908
        if ((selector & 0xfffc) == 0)
909
            raise_exception_err(EXCP0D_GPF, 0);
910

  
911
        if (load_segment(&e1, &e2, selector) != 0)
912
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
913
        if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
914
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
915
        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
916
        if (dpl > cpl)
917
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
918
        if (!(e2 & DESC_P_MASK))
919
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
920

  
921
        if (!(e2 & DESC_C_MASK) && dpl < cpl) {
922
            /* to inner priviledge */
923
            get_ss_esp_from_tss(&ss, &sp, dpl);
924
            if ((ss & 0xfffc) == 0)
925
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
926
            if ((ss & 3) != dpl)
927
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
928
            if (load_segment(&ss_e1, &ss_e2, ss) != 0)
929
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
930
            ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
931
            if (ss_dpl != dpl)
932
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
933
            if (!(ss_e2 & DESC_S_MASK) ||
934
                (ss_e2 & DESC_CS_MASK) ||
935
                !(ss_e2 & DESC_W_MASK))
936
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
937
            if (!(ss_e2 & DESC_P_MASK))
938
                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
939
            
940
            param_count = e2 & 0x1f;
941
            push_size = ((param_count * 2) + 8) << shift;
942

  
943
            old_esp = env->regs[R_ESP];
944
            old_ss = env->segs[R_SS].selector;
945
            if (!(env->segs[R_SS].flags & DESC_B_MASK))
946
                old_esp &= 0xffff;
947
            old_ssp = env->segs[R_SS].base + old_esp;
948
            
949
            /* XXX: from this point not restartable */
950
            load_seg(R_SS, ss, env->eip);
951

  
952
            if (!(env->segs[R_SS].flags & DESC_B_MASK))
953
                sp &= 0xffff;
954
            ssp = env->segs[R_SS].base + sp;
955
            if (shift) {
956
                ssp -= 4;
957
                stl(ssp, old_ss);
958
                ssp -= 4;
959
                stl(ssp, old_esp);
960
                ssp -= 4 * param_count;
961
                for(i = 0; i < param_count; i++) {
962
                    val = ldl(old_ssp + i * 4);
963
                    stl(ssp + i * 4, val);
964
                }
965
            } else {
966
                ssp -= 2;
967
                stw(ssp, old_ss);
968
                ssp -= 2;
969
                stw(ssp, old_esp);
970
                ssp -= 2 * param_count;
971
                for(i = 0; i < param_count; i++) {
972
                    val = lduw(old_ssp + i * 2);
973
                    stw(ssp + i * 2, val);
974
                }
975
            }
976
        } else {
977
            /* to same priviledge */
978
            if (!(env->segs[R_SS].flags & DESC_B_MASK))
979
                sp &= 0xffff;
980
            ssp = env->segs[R_SS].base + sp;
981
            push_size = (4 << shift);
982
        }
983

  
984
        if (shift) {
985
            ssp -= 4;
986
            stl(ssp, env->segs[R_CS].selector);
987
            ssp -= 4;
988
            stl(ssp, next_eip);
989
        } else {
990
            ssp -= 2;
991
            stw(ssp, env->segs[R_CS].selector);
992
            ssp -= 2;
993
            stw(ssp, next_eip);
994
        }
995

  
996
        sp -= push_size;
997
        load_seg(R_CS, selector, env->eip);
998
        /* from this point, not restartable if same priviledge */
999
        if (!(env->segs[R_SS].flags & DESC_B_MASK))
1000
            env->regs[R_ESP] = (env->regs[R_ESP] & 0xffff0000) | (sp & 0xffff);
1001
        else
1002
            env->regs[R_ESP] = sp;
1003
        EIP = offset;
777 1004
    }
778 1005
}
779 1006

  
......
820 1047
}
821 1048

  
822 1049
/* protected mode iret */
823
void helper_iret_protected(int shift)
1050
static inline void helper_ret_protected(int shift, int is_iret, int addend)
824 1051
{
825 1052
    uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss;
826 1053
    uint32_t new_es, new_ds, new_fs, new_gs;
......
834 1061
    ssp = env->segs[R_SS].base + sp;
835 1062
    if (shift == 1) {
836 1063
        /* 32 bits */
837
        new_eflags = ldl(ssp + 8);
1064
        if (is_iret)
1065
            new_eflags = ldl(ssp + 8);
838 1066
        new_cs = ldl(ssp + 4) & 0xffff;
839 1067
        new_eip = ldl(ssp);
840
        if (new_eflags & VM_MASK)
1068
        if (is_iret && (new_eflags & VM_MASK))
841 1069
            goto return_to_vm86;
842 1070
    } else {
843 1071
        /* 16 bits */
844
        new_eflags = lduw(ssp + 4);
1072
        if (is_iret)
1073
            new_eflags = lduw(ssp + 4);
845 1074
        new_cs = lduw(ssp + 2);
846 1075
        new_eip = lduw(ssp);
847 1076
    }
......
870 1099
    if (rpl == cpl) {
871 1100
        /* return to same priledge level */
872 1101
        load_seg(R_CS, new_cs, env->eip);
873
        new_esp = sp + (6 << shift);
1102
        new_esp = sp + (4 << shift) + ((2 * is_iret) << shift) + addend;
874 1103
    } else {
875
        /* return to differentr priviledge level */
1104
        /* return to different priviledge level */
1105
        ssp += (4 << shift) + ((2 * is_iret) << shift) + addend;
876 1106
        if (shift == 1) {
877 1107
            /* 32 bits */
878
            new_esp = ldl(ssp + 12);
879
            new_ss = ldl(ssp + 16) & 0xffff;
1108
            new_esp = ldl(ssp);
1109
            new_ss = ldl(ssp + 4) & 0xffff;
880 1110
        } else {
881 1111
            /* 16 bits */
882
            new_esp = lduw(ssp + 6);
883
            new_ss = lduw(ssp + 8);
1112
            new_esp = lduw(ssp);
1113
            new_ss = lduw(ssp + 2);
884 1114
        }
885 1115
        
886 1116
        if ((new_ss & 3) != rpl)
......
906 1136
        env->regs[R_ESP] = (env->regs[R_ESP] & 0xffff0000) | 
907 1137
            (new_esp & 0xffff);
908 1138
    env->eip = new_eip;
909
    if (cpl == 0)
910
        eflags_mask = FL_UPDATE_CPL0_MASK;
911
    else
912
        eflags_mask = FL_UPDATE_MASK32;
913
    if (shift == 0)
914
        eflags_mask &= 0xffff;
915
    load_eflags(new_eflags, eflags_mask);
1139
    if (is_iret) {
1140
        if (cpl == 0)
1141
            eflags_mask = FL_UPDATE_CPL0_MASK;
1142
        else
1143
            eflags_mask = FL_UPDATE_MASK32;
1144
        if (shift == 0)
1145
            eflags_mask &= 0xffff;
1146
        load_eflags(new_eflags, eflags_mask);
1147
    }
916 1148
    return;
917 1149

  
918 1150
 return_to_vm86:
......
936 1168
    env->regs[R_ESP] = new_esp;
937 1169
}
938 1170

  
1171
void helper_iret_protected(int shift)
1172
{
1173
    helper_ret_protected(shift, 1, 0);
1174
}
1175

  
1176
void helper_lret_protected(int shift, int addend)
1177
{
1178
    helper_ret_protected(shift, 0, addend);
1179
}
1180

  
939 1181
void helper_movl_crN_T0(int reg)
940 1182
{
941 1183
    env->cr[reg] = T0;
b/op-i386.c
948 948
}
949 949

  
950 950
/* T0: segment, T1:eip */
951
void OPPROTO op_ljmp_T0_T1(void)
951
void OPPROTO op_ljmp_protected_T0_T1(void)
952 952
{
953
    jmp_seg(T0 & 0xffff, T1);
953
    helper_ljmp_protected_T0_T1();
954
}
955

  
956
void OPPROTO op_lcall_real_T0_T1(void)
957
{
958
    helper_lcall_real_T0_T1(PARAM1, PARAM2);
959
}
960

  
961
void OPPROTO op_lcall_protected_T0_T1(void)
962
{
963
    helper_lcall_protected_T0_T1(PARAM1, PARAM2);
954 964
}
955 965

  
956 966
void OPPROTO op_iret_real(void)
......
963 973
    helper_iret_protected(PARAM1);
964 974
}
965 975

  
976
void OPPROTO op_lret_protected(void)
977
{
978
    helper_lret_protected(PARAM1, PARAM2);
979
}
980

  
966 981
void OPPROTO op_lldt_T0(void)
967 982
{
968 983
    helper_lldt_T0();
b/translate-i386.c
1832 1832
            s->is_jmp = 1;
1833 1833
            break;
1834 1834
        case 3: /* lcall Ev */
1835
            /* push return segment + offset */
1836
            gen_op_movl_T0_seg(R_CS);
1837
            gen_push_T0(s);
1838
            next_eip = s->pc - s->cs_base;
1839
            gen_op_movl_T0_im(next_eip);
1840
            gen_push_T0(s);
1841

  
1842 1835
            gen_op_ld_T1_A0[ot]();
1843 1836
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1844 1837
            gen_op_lduw_T0_A0();
1845
            gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1846
            gen_op_movl_T0_T1();
1847
            gen_op_jmp_T0();
1838
        do_lcall:
1839
            if (s->pe && !s->vm86) {
1840
                if (s->cc_op != CC_OP_DYNAMIC)
1841
                    gen_op_set_cc_op(s->cc_op);
1842
                gen_op_jmp_im(pc_start - s->cs_base);
1843
                gen_op_lcall_protected_T0_T1(dflag, s->pc - s->cs_base);
1844
            } else {
1845
                gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base);
1846
            }
1848 1847
            s->is_jmp = 1;
1849 1848
            break;
1850 1849
        case 4: /* jmp Ev */
......
1857 1856
            gen_op_ld_T1_A0[ot]();
1858 1857
            gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1859 1858
            gen_op_lduw_T0_A0();
1859
        do_ljmp:
1860 1860
            if (s->pe && !s->vm86) {
1861
                /* we compute EIP to handle the exception case */
1861
                if (s->cc_op != CC_OP_DYNAMIC)
1862
                    gen_op_set_cc_op(s->cc_op);
1862 1863
                gen_op_jmp_im(pc_start - s->cs_base);
1863
                gen_op_ljmp_T0_T1();
1864
                gen_op_ljmp_protected_T0_T1();
1864 1865
            } else {
1865 1866
                gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
1866 1867
                gen_op_movl_T0_T1();
......
2867 2868
        else
2868 2869
            ot = dflag ? OT_LONG : OT_WORD;
2869 2870

  
2870
        if (prefixes & PREFIX_REPZ) {
2871
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
2871 2872
            gen_string_ds(s, ot, gen_op_movs + 9);
2872 2873
        } else {
2873 2874
            gen_string_ds(s, ot, gen_op_movs);
......
2881 2882
        else
2882 2883
            ot = dflag ? OT_LONG : OT_WORD;
2883 2884

  
2884
        if (prefixes & PREFIX_REPZ) {
2885
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
2885 2886
            gen_string_es(s, ot, gen_op_stos + 9);
2886 2887
        } else {
2887 2888
            gen_string_es(s, ot, gen_op_stos);
......
2893 2894
            ot = OT_BYTE;
2894 2895
        else
2895 2896
            ot = dflag ? OT_LONG : OT_WORD;
2896
        if (prefixes & PREFIX_REPZ) {
2897
        if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
2897 2898
            gen_string_ds(s, ot, gen_op_lods + 9);
2898 2899
        } else {
2899 2900
            gen_string_ds(s, ot, gen_op_lods);
......
2952 2953
                ot = OT_BYTE;
2953 2954
            else
2954 2955
                ot = dflag ? OT_LONG : OT_WORD;
2955
            if (prefixes & PREFIX_REPZ) {
2956
            if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
2956 2957
                gen_string_es(s, ot, gen_op_ins + 9);
2957 2958
            } else {
2958 2959
                gen_string_es(s, ot, gen_op_ins);
......
2969 2970
                ot = OT_BYTE;
2970 2971
            else
2971 2972
                ot = dflag ? OT_LONG : OT_WORD;
2972
            if (prefixes & PREFIX_REPZ) {
2973
            if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) {
2973 2974
                gen_string_ds(s, ot, gen_op_outs + 9);
2974 2975
            } else {
2975 2976
                gen_string_ds(s, ot, gen_op_outs);
......
3062 3063
        val = ldsw(s->pc);
3063 3064
        s->pc += 2;
3064 3065
    do_lret:
3065
        gen_stack_A0(s);
3066
        /* pop offset */
3067
        gen_op_ld_T0_A0[1 + s->dflag]();
3068
        if (s->dflag == 0)
3069
            gen_op_andl_T0_ffff();
3070
        /* NOTE: keeping EIP updated is not a problem in case of
3071
           exception */
3072
        gen_op_jmp_T0();
3073
        /* pop selector */
3074
        gen_op_addl_A0_im(2 << s->dflag);
3075
        gen_op_ld_T0_A0[1 + s->dflag]();
3076
        gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3077
        /* add stack offset */
3078
        gen_stack_update(s, val + (4 << s->dflag));
3066
        if (s->pe && !s->vm86) {
3067
            if (s->cc_op != CC_OP_DYNAMIC)
3068
                gen_op_set_cc_op(s->cc_op);
3069
            gen_op_jmp_im(pc_start - s->cs_base);
3070
            gen_op_lret_protected(s->dflag, val);
3071
        } else {
3072
            gen_stack_A0(s);
3073
            /* pop offset */
3074
            gen_op_ld_T0_A0[1 + s->dflag]();
3075
            if (s->dflag == 0)
3076
                gen_op_andl_T0_ffff();
3077
            /* NOTE: keeping EIP updated is not a problem in case of
3078
               exception */
3079
            gen_op_jmp_T0();
3080
            /* pop selector */
3081
            gen_op_addl_A0_im(2 << s->dflag);
3082
            gen_op_ld_T0_A0[1 + s->dflag]();
3083
            gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3084
            /* add stack offset */
3085
            gen_stack_update(s, val + (4 << s->dflag));
3086
        }
3079 3087
        s->is_jmp = 1;
3080 3088
        break;
3081 3089
    case 0xcb: /* lret */
......
3114 3122
    case 0x9a: /* lcall im */
3115 3123
        {
3116 3124
            unsigned int selector, offset;
3117
            /* XXX: not restartable */
3118 3125

  
3119 3126
            ot = dflag ? OT_LONG : OT_WORD;
3120 3127
            offset = insn_get(s, ot);
3121 3128
            selector = insn_get(s, OT_WORD);
3122 3129
            
3123
            /* push return segment + offset */
3124
            gen_op_movl_T0_seg(R_CS);
3125
            gen_push_T0(s);
3126
            next_eip = s->pc - s->cs_base;
3127
            gen_op_movl_T0_im(next_eip);
3128
            gen_push_T0(s);
3129

  
3130
            /* change cs and pc */
3131 3130
            gen_op_movl_T0_im(selector);
3132
            gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3133
            gen_op_jmp_im((unsigned long)offset);
3134
            s->is_jmp = 1;
3131
            gen_op_movl_T1_im(offset);
3135 3132
        }
3136
        break;
3133
        goto do_lcall;
3137 3134
    case 0xe9: /* jmp */
3138 3135
        ot = dflag ? OT_LONG : OT_WORD;
3139 3136
        val = insn_get(s, ot);
......
3150 3147
            offset = insn_get(s, ot);
3151 3148
            selector = insn_get(s, OT_WORD);
3152 3149
            
3153
            /* change cs and pc */
3154 3150
            gen_op_movl_T0_im(selector);
3155
            if (s->pe && !s->vm86) {
3156
                /* we compute EIP to handle the exception case */
3157
                gen_op_jmp_im(pc_start - s->cs_base);
3158
                gen_op_movl_T1_im(offset);
3159
                gen_op_ljmp_T0_T1();
3160
            } else {
3161
                gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS]));
3162
                gen_op_jmp_im((unsigned long)offset);
3163
            }
3164
            s->is_jmp = 1;
3151
            gen_op_movl_T1_im(offset);
3165 3152
        }
3166
        break;
3153
        goto do_ljmp;
3167 3154
    case 0xeb: /* jmp Jb */
3168 3155
        val = (int8_t)insn_get(s, OT_BYTE);
3169 3156
        val += s->pc - s->cs_base;

Also available in: Unified diff