Revision 14ce26e7 target-i386/helper.c

b/target-i386/helper.c
119 119
{
120 120
    SegmentCache *dt;
121 121
    int index;
122
    uint8_t *ptr;
122
    target_ulong ptr;
123 123

  
124 124
    if (selector & 0x4)
125 125
        dt = &env->ldt;
......
143 143
    return limit;
144 144
}
145 145

  
146
static inline uint8_t *get_seg_base(uint32_t e1, uint32_t e2)
146
static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
147 147
{
148
    return (uint8_t *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
148
    return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
149 149
}
150 150

  
151 151
static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
......
160 160
{
161 161
    selector &= 0xffff;
162 162
    cpu_x86_load_seg_cache(env, seg, selector, 
163
                           (uint8_t *)(selector << 4), 0xffff, 0);
163
                           (selector << 4), 0xffff, 0);
164 164
}
165 165

  
166 166
static inline void get_ss_esp_from_tss(uint32_t *ss_ptr, 
......
258 258
                       uint32_t next_eip)
259 259
{
260 260
    int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
261
    uint8_t *tss_base;
261
    target_ulong tss_base;
262 262
    uint32_t new_regs[8], new_segs[6];
263 263
    uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
264 264
    uint32_t old_eflags, eflags_mask;
265 265
    SegmentCache *dt;
266 266
    int index;
267
    uint8_t *ptr;
267
    target_ulong ptr;
268 268

  
269 269
    type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
270 270
#ifdef DEBUG_PCALL
......
345 345
    
346 346
    /* clear busy bit (it is restartable) */
347 347
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
348
        uint8_t *ptr;
348
        target_ulong ptr;
349 349
        uint32_t e2;
350 350
        ptr = env->gdt.base + (env->tr.selector & ~7);
351 351
        e2 = ldl_kernel(ptr + 4);
......
397 397

  
398 398
    /* set busy bit */
399 399
    if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
400
        uint8_t *ptr;
400
        target_ulong ptr;
401 401
        uint32_t e2;
402 402
        ptr = env->gdt.base + (tss_selector & ~7);
403 403
        e2 = ldl_kernel(ptr + 4);
......
445 445
        cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
446 446
        /* first just selectors as the rest may trigger exceptions */
447 447
        for(i = 0; i < 6; i++)
448
            cpu_x86_load_seg_cache(env, i, new_segs[i], NULL, 0, 0);
448
            cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
449 449
    }
450 450
    
451 451
    env->ldt.selector = new_ldt & ~4;
452
    env->ldt.base = NULL;
452
    env->ldt.base = 0;
453 453
    env->ldt.limit = 0;
454 454
    env->ldt.flags = 0;
455 455

  
......
573 573

  
574 574
#define POPL(ssp, sp, sp_mask, val)\
575 575
{\
576
    val = ldl_kernel((ssp) + (sp & (sp_mask)));\
576
    val = (uint32_t)ldl_kernel((ssp) + (sp & (sp_mask)));\
577 577
    sp += 4;\
578 578
}
579 579

  
......
582 582
                                   unsigned int next_eip, int is_hw)
583 583
{
584 584
    SegmentCache *dt;
585
    uint8_t *ptr, *ssp;
585
    target_ulong ptr, ssp;
586 586
    int type, dpl, selector, ss_dpl, cpl, sp_mask;
587 587
    int has_error_code, new_stack, shift;
588 588
    uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
......
703 703
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
704 704
        new_stack = 0; /* avoid warning */
705 705
        sp_mask = 0; /* avoid warning */
706
        ssp = NULL; /* avoid warning */
706
        ssp = 0; /* avoid warning */
707 707
        esp = 0; /* avoid warning */
708 708
    }
709 709

  
......
754 754
    
755 755
    if (new_stack) {
756 756
        if (env->eflags & VM_MASK) {
757
            cpu_x86_load_seg_cache(env, R_ES, 0, NULL, 0, 0);
758
            cpu_x86_load_seg_cache(env, R_DS, 0, NULL, 0, 0);
759
            cpu_x86_load_seg_cache(env, R_FS, 0, NULL, 0, 0);
760
            cpu_x86_load_seg_cache(env, R_GS, 0, NULL, 0, 0);
757
            cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
758
            cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
759
            cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
760
            cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
761 761
        }
762 762
        ss = (ss & ~3) | dpl;
763 763
        cpu_x86_load_seg_cache(env, R_SS, ss, 
......
780 780
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
781 781
}
782 782

  
783
#ifdef TARGET_X86_64
784

  
785
#define PUSHQ(sp, val)\
786
{\
787
    sp -= 8;\
788
    stq_kernel(sp, (val));\
789
}
790

  
791
#define POPQ(sp, val)\
792
{\
793
    val = ldq_kernel(sp);\
794
    sp += 8;\
795
}
796

  
797
static inline target_ulong get_rsp_from_tss(int level)
798
{
799
    int index;
800
    
801
#if 0
802
    printf("TR: base=" TARGET_FMT_lx " limit=%x\n", 
803
           env->tr.base, env->tr.limit);
804
#endif
805

  
806
    if (!(env->tr.flags & DESC_P_MASK))
807
        cpu_abort(env, "invalid tss");
808
    index = 8 * level + 4;
809
    if ((index + 7) > env->tr.limit)
810
        raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
811
    return ldq_kernel(env->tr.base + index);
812
}
813

  
814
/* 64 bit interrupt */
815
static void do_interrupt64(int intno, int is_int, int error_code,
816
                           target_ulong next_eip, int is_hw)
817
{
818
    SegmentCache *dt;
819
    target_ulong ptr;
820
    int type, dpl, selector, cpl, ist;
821
    int has_error_code, new_stack;
822
    uint32_t e1, e2, e3, ss;
823
    target_ulong old_eip, esp, offset;
824

  
825
    has_error_code = 0;
826
    if (!is_int && !is_hw) {
827
        switch(intno) {
828
        case 8:
829
        case 10:
830
        case 11:
831
        case 12:
832
        case 13:
833
        case 14:
834
        case 17:
835
            has_error_code = 1;
836
            break;
837
        }
838
    }
839
    if (is_int)
840
        old_eip = next_eip;
841
    else
842
        old_eip = env->eip;
843

  
844
    dt = &env->idt;
845
    if (intno * 16 + 15 > dt->limit)
846
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
847
    ptr = dt->base + intno * 16;
848
    e1 = ldl_kernel(ptr);
849
    e2 = ldl_kernel(ptr + 4);
850
    e3 = ldl_kernel(ptr + 8);
851
    /* check gate type */
852
    type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
853
    switch(type) {
854
    case 14: /* 386 interrupt gate */
855
    case 15: /* 386 trap gate */
856
        break;
857
    default:
858
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
859
        break;
860
    }
861
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
862
    cpl = env->hflags & HF_CPL_MASK;
863
    /* check privledge if software int */
864
    if (is_int && dpl < cpl)
865
        raise_exception_err(EXCP0D_GPF, intno * 16 + 2);
866
    /* check valid bit */
867
    if (!(e2 & DESC_P_MASK))
868
        raise_exception_err(EXCP0B_NOSEG, intno * 16 + 2);
869
    selector = e1 >> 16;
870
    offset = ((target_ulong)e3 << 32) | (e2 & 0xffff0000) | (e1 & 0x0000ffff);
871
    ist = e2 & 7;
872
    if ((selector & 0xfffc) == 0)
873
        raise_exception_err(EXCP0D_GPF, 0);
874

  
875
    if (load_segment(&e1, &e2, selector) != 0)
876
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
877
    if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
878
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
879
    dpl = (e2 >> DESC_DPL_SHIFT) & 3;
880
    if (dpl > cpl)
881
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
882
    if (!(e2 & DESC_P_MASK))
883
        raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
884
    if (!(e2 & DESC_L_MASK) || (e2 & DESC_B_MASK))
885
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
886
    if ((!(e2 & DESC_C_MASK) && dpl < cpl) || ist != 0) {
887
        /* to inner priviledge */
888
        if (ist != 0)
889
            esp = get_rsp_from_tss(ist + 3);
890
        else
891
            esp = get_rsp_from_tss(dpl);
892
        ss = 0;
893
        new_stack = 1;
894
    } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
895
        /* to same priviledge */
896
        if (env->eflags & VM_MASK)
897
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
898
        new_stack = 0;
899
        esp = ESP & ~0xf; /* align stack */
900
        dpl = cpl;
901
    } else {
902
        raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
903
        new_stack = 0; /* avoid warning */
904
        esp = 0; /* avoid warning */
905
    }
906

  
907
    PUSHQ(esp, env->segs[R_SS].selector);
908
    PUSHQ(esp, ESP);
909
    PUSHQ(esp, compute_eflags());
910
    PUSHQ(esp, env->segs[R_CS].selector);
911
    PUSHQ(esp, old_eip);
912
    if (has_error_code) {
913
        PUSHQ(esp, error_code);
914
    }
915
    
916
    if (new_stack) {
917
        ss = 0 | dpl;
918
        cpu_x86_load_seg_cache(env, R_SS, ss, 0, 0, 0);
919
    }
920
    ESP = esp;
921

  
922
    selector = (selector & ~3) | dpl;
923
    cpu_x86_load_seg_cache(env, R_CS, selector, 
924
                   get_seg_base(e1, e2),
925
                   get_seg_limit(e1, e2),
926
                   e2);
927
    cpu_x86_set_cpl(env, dpl);
928
    env->eip = offset;
929

  
930
    /* interrupt gate clear IF mask */
931
    if ((type & 1) == 0) {
932
        env->eflags &= ~IF_MASK;
933
    }
934
    env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
935
}
936

  
937
void helper_syscall(void)
938
{
939
    int selector;
940

  
941
    if (!(env->efer & MSR_EFER_SCE)) {
942
        raise_exception_err(EXCP06_ILLOP, 0);
943
    }
944
    selector = (env->star >> 32) & 0xffff;
945
    if (env->hflags & HF_LMA_MASK) {
946
        ECX = env->eip;
947
        env->regs[11] = compute_eflags();
948

  
949
        cpu_x86_set_cpl(env, 0);
950
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
951
                           0, 0xffffffff, 
952
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
953
                               DESC_S_MASK |
954
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | DESC_L_MASK);
955
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
956
                               0, 0xffffffff,
957
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
958
                               DESC_S_MASK |
959
                               DESC_W_MASK | DESC_A_MASK);
960
        env->eflags &= ~env->fmask;
961
        if (env->hflags & HF_CS64_MASK)
962
            env->eip = env->lstar;
963
        else
964
            env->eip = env->cstar;
965
    } else {
966
        ECX = (uint32_t)env->eip;
967
        
968
        cpu_x86_set_cpl(env, 0);
969
        cpu_x86_load_seg_cache(env, R_CS, selector & 0xfffc, 
970
                           0, 0xffffffff, 
971
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
972
                               DESC_S_MASK |
973
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
974
        cpu_x86_load_seg_cache(env, R_SS, (selector + 8) & 0xfffc, 
975
                               0, 0xffffffff,
976
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
977
                               DESC_S_MASK |
978
                               DESC_W_MASK | DESC_A_MASK);
979
        env->eflags &= ~(IF_MASK | RF_MASK | VM_MASK);
980
        env->eip = (uint32_t)env->star;
981
    }
982
}
983

  
984
void helper_sysret(int dflag)
985
{
986
    int cpl, selector;
987

  
988
    cpl = env->hflags & HF_CPL_MASK;
989
    if (!(env->cr[0] & CR0_PE_MASK) || cpl != 0) {
990
        raise_exception_err(EXCP0D_GPF, 0);
991
    }
992
    selector = (env->star >> 48) & 0xffff;
993
    if (env->hflags & HF_LMA_MASK) {
994
        if (dflag == 2) {
995
            cpu_x86_load_seg_cache(env, R_CS, (selector + 16) | 3, 
996
                                   0, 0xffffffff, 
997
                                   DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
998
                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
999
                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK | 
1000
                                   DESC_L_MASK);
1001
            env->eip = ECX;
1002
        } else {
1003
            cpu_x86_load_seg_cache(env, R_CS, selector | 3, 
1004
                                   0, 0xffffffff, 
1005
                                   DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1006
                                   DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1007
                                   DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1008
            env->eip = (uint32_t)ECX;
1009
        }
1010
        cpu_x86_load_seg_cache(env, R_SS, selector + 8, 
1011
                               0, 0xffffffff,
1012
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1013
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1014
                               DESC_W_MASK | DESC_A_MASK);
1015
        load_eflags((uint32_t)(env->regs[11]), 0xffffffff);
1016
        cpu_x86_set_cpl(env, 3);
1017
    } else {
1018
        cpu_x86_load_seg_cache(env, R_CS, selector | 3, 
1019
                               0, 0xffffffff, 
1020
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1021
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1022
                               DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1023
        env->eip = (uint32_t)ECX;
1024
        cpu_x86_load_seg_cache(env, R_SS, selector + 8, 
1025
                               0, 0xffffffff,
1026
                               DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1027
                               DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1028
                               DESC_W_MASK | DESC_A_MASK);
1029
        env->eflags |= IF_MASK;
1030
        cpu_x86_set_cpl(env, 3);
1031
    }
1032
}
1033
#endif
1034

  
783 1035
/* real mode interrupt */
784 1036
static void do_interrupt_real(int intno, int is_int, int error_code,
785 1037
                              unsigned int next_eip)
786 1038
{
787 1039
    SegmentCache *dt;
788
    uint8_t *ptr, *ssp;
1040
    target_ulong ptr, ssp;
789 1041
    int selector;
790 1042
    uint32_t offset, esp;
791 1043
    uint32_t old_cs, old_eip;
......
813 1065
    ESP = (ESP & ~0xffff) | (esp & 0xffff);
814 1066
    env->eip = offset;
815 1067
    env->segs[R_CS].selector = selector;
816
    env->segs[R_CS].base = (uint8_t *)(selector << 4);
1068
    env->segs[R_CS].base = (selector << 4);
817 1069
    env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
818 1070
}
819 1071

  
820 1072
/* fake user mode interrupt */
821 1073
void do_interrupt_user(int intno, int is_int, int error_code, 
822
                       unsigned int next_eip)
1074
                       target_ulong next_eip)
823 1075
{
824 1076
    SegmentCache *dt;
825
    uint8_t *ptr;
1077
    target_ulong ptr;
826 1078
    int dpl, cpl;
827 1079
    uint32_t e2;
828 1080

  
......
849 1101
 * instruction. It is only relevant if is_int is TRUE.  
850 1102
 */
851 1103
void do_interrupt(int intno, int is_int, int error_code, 
852
                  unsigned int next_eip, int is_hw)
1104
                  target_ulong next_eip, int is_hw)
853 1105
{
854 1106
#ifdef DEBUG_PCALL
855 1107
    if (loglevel & (CPU_LOG_PCALL | CPU_LOG_INT)) {
856 1108
        if ((env->cr[0] & CR0_PE_MASK)) {
857 1109
            static int count;
858
            fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:%08x pc=%08x SP=%04x:%08x",
1110
            fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:" TARGET_FMT_lx " pc=" TARGET_FMT_lx " SP=%04x:" TARGET_FMT_lx,
859 1111
                    count, intno, error_code, is_int,
860 1112
                    env->hflags & HF_CPL_MASK,
861 1113
                    env->segs[R_CS].selector, EIP,
862 1114
                    (int)env->segs[R_CS].base + EIP,
863 1115
                    env->segs[R_SS].selector, ESP);
864 1116
            if (intno == 0x0e) {
865
                fprintf(logfile, " CR2=%08x", env->cr[2]);
1117
                fprintf(logfile, " CR2=" TARGET_FMT_lx, env->cr[2]);
866 1118
            } else {
867
                fprintf(logfile, " EAX=%08x", EAX);
1119
                fprintf(logfile, " EAX=" TARGET_FMT_lx, EAX);
868 1120
            }
869 1121
            fprintf(logfile, "\n");
870
#if 0
871 1122
            cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1123
#if 0
872 1124
            {
873 1125
                int i;
874 1126
                uint8_t *ptr;
......
885 1137
    }
886 1138
#endif
887 1139
    if (env->cr[0] & CR0_PE_MASK) {
888
        do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
1140
#if TARGET_X86_64
1141
        if (env->hflags & HF_LMA_MASK) {
1142
            do_interrupt64(intno, is_int, error_code, next_eip, is_hw);
1143
        } else
1144
#endif
1145
        {
1146
            do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);
1147
        }
889 1148
    } else {
890 1149
        do_interrupt_real(intno, is_int, error_code, next_eip);
891 1150
    }
......
932 1191
#ifdef BUGGY_GCC_DIV64
933 1192
/* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
934 1193
   call it from another function */
935
uint32_t div64(uint32_t *q_ptr, uint64_t num, uint32_t den)
1194
uint32_t div32(uint32_t *q_ptr, uint64_t num, uint32_t den)
936 1195
{
937 1196
    *q_ptr = num / den;
938 1197
    return num % den;
939 1198
}
940 1199

  
941
int32_t idiv64(int32_t *q_ptr, int64_t num, int32_t den)
1200
int32_t idiv32(int32_t *q_ptr, int64_t num, int32_t den)
942 1201
{
943 1202
    *q_ptr = num / den;
944 1203
    return num % den;
945 1204
}
946 1205
#endif
947 1206

  
948
void helper_divl_EAX_T0(uint32_t eip)
1207
void helper_divl_EAX_T0(void)
949 1208
{
950 1209
    unsigned int den, q, r;
951 1210
    uint64_t num;
......
953 1212
    num = EAX | ((uint64_t)EDX << 32);
954 1213
    den = T0;
955 1214
    if (den == 0) {
956
        EIP = eip;
957 1215
        raise_exception(EXCP00_DIVZ);
958 1216
    }
959 1217
#ifdef BUGGY_GCC_DIV64
960
    r = div64(&q, num, den);
1218
    r = div32(&q, num, den);
961 1219
#else
962 1220
    q = (num / den);
963 1221
    r = (num % den);
964 1222
#endif
965
    EAX = q;
966
    EDX = r;
1223
    EAX = (uint32_t)q;
1224
    EDX = (uint32_t)r;
967 1225
}
968 1226

  
969
void helper_idivl_EAX_T0(uint32_t eip)
1227
void helper_idivl_EAX_T0(void)
970 1228
{
971 1229
    int den, q, r;
972 1230
    int64_t num;
......
974 1232
    num = EAX | ((uint64_t)EDX << 32);
975 1233
    den = T0;
976 1234
    if (den == 0) {
977
        EIP = eip;
978 1235
        raise_exception(EXCP00_DIVZ);
979 1236
    }
980 1237
#ifdef BUGGY_GCC_DIV64
981
    r = idiv64(&q, num, den);
1238
    r = idiv32(&q, num, den);
982 1239
#else
983 1240
    q = (num / den);
984 1241
    r = (num % den);
985 1242
#endif
986
    EAX = q;
987
    EDX = r;
1243
    EAX = (uint32_t)q;
1244
    EDX = (uint32_t)r;
988 1245
}
989 1246

  
990 1247
void helper_cmpxchg8b(void)
......
993 1250
    int eflags;
994 1251

  
995 1252
    eflags = cc_table[CC_OP].compute_all();
996
    d = ldq((uint8_t *)A0);
1253
    d = ldq(A0);
997 1254
    if (d == (((uint64_t)EDX << 32) | EAX)) {
998
        stq((uint8_t *)A0, ((uint64_t)ECX << 32) | EBX);
1255
        stq(A0, ((uint64_t)ECX << 32) | EBX);
999 1256
        eflags |= CC_Z;
1000 1257
    } else {
1001 1258
        EDX = d >> 32;
......
1005 1262
    CC_SRC = eflags;
1006 1263
}
1007 1264

  
1008
#define CPUID_FP87 (1 << 0)
1009
#define CPUID_VME  (1 << 1)
1010
#define CPUID_DE   (1 << 2)
1011
#define CPUID_PSE  (1 << 3)
1012
#define CPUID_TSC  (1 << 4)
1013
#define CPUID_MSR  (1 << 5)
1014
#define CPUID_PAE  (1 << 6)
1015
#define CPUID_MCE  (1 << 7)
1016
#define CPUID_CX8  (1 << 8)
1017
#define CPUID_APIC (1 << 9)
1018
#define CPUID_SEP  (1 << 11) /* sysenter/sysexit */
1019
#define CPUID_MTRR (1 << 12)
1020
#define CPUID_PGE  (1 << 13)
1021
#define CPUID_MCA  (1 << 14)
1022
#define CPUID_CMOV (1 << 15)
1023
/* ... */
1024
#define CPUID_MMX  (1 << 23)
1025
#define CPUID_FXSR (1 << 24)
1026
#define CPUID_SSE  (1 << 25)
1027
#define CPUID_SSE2 (1 << 26)
1028

  
1029 1265
void helper_cpuid(void)
1030 1266
{
1031
    switch(EAX) {
1267
    switch((uint32_t)EAX) {
1032 1268
    case 0:
1033 1269
        EAX = 2; /* max EAX index supported */
1034
        EBX = 0x756e6547;
1035
        ECX = 0x6c65746e;
1036
        EDX = 0x49656e69;
1270
        EBX = env->cpuid_vendor1;
1271
        EDX = env->cpuid_vendor2;
1272
        ECX = env->cpuid_vendor3;
1037 1273
        break;
1038 1274
    case 1:
1039
        {
1040
            int family, model, stepping;
1041
            /* EAX = 1 info */
1042
#if 0
1043
            /* pentium 75-200 */
1044
            family = 5;
1045
            model = 2;
1046
            stepping = 11;
1047
#else
1048
            /* pentium pro */
1049
            family = 6;
1050
            model = 1;
1051
            stepping = 3;
1052
#endif
1053
            EAX = (family << 8) | (model << 4) | stepping;
1054
            EBX = 0;
1055
            ECX = 0;
1056
            EDX = CPUID_FP87 | CPUID_DE | CPUID_PSE |
1057
                CPUID_TSC | CPUID_MSR | CPUID_MCE |
1058
                CPUID_CX8 | CPUID_PGE | CPUID_CMOV;
1059
        }
1275
        EAX = env->cpuid_version;
1276
        EBX = 0;
1277
        ECX = 0;
1278
        EDX = env->cpuid_features;
1060 1279
        break;
1061 1280
    default:
1062 1281
        /* cache info: needed for Pentium Pro compatibility */
......
1065 1284
        ECX = 0;
1066 1285
        EDX = 0;
1067 1286
        break;
1287
#ifdef TARGET_X86_64
1288
    case 0x80000000:
1289
        EAX = 0x80000008;
1290
        EBX = env->cpuid_vendor1;
1291
        EDX = env->cpuid_vendor2;
1292
        ECX = env->cpuid_vendor3;
1293
        break;
1294
    case 0x80000001:
1295
        EAX = env->cpuid_features;
1296
        EBX = 0;
1297
        ECX = 0;
1298
        /* long mode + syscall/sysret features */
1299
        EDX = (env->cpuid_features & 0x0183F3FF) | (1 << 29) | (1 << 11);
1300
        break;
1301
    case 0x80000008:
1302
        /* virtual & phys address size in low 2 bytes. */
1303
        EAX = 0x00003028;
1304
        EBX = 0;
1305
        ECX = 0;
1306
        EDX = 0;
1307
        break;
1308
#endif
1068 1309
    }
1069 1310
}
1070 1311

  
1071 1312
void helper_enter_level(int level, int data32)
1072 1313
{
1073
    uint8_t *ssp;
1314
    target_ulong ssp;
1074 1315
    uint32_t esp_mask, esp, ebp;
1075 1316

  
1076 1317
    esp_mask = get_sp_mask(env->segs[R_SS].flags);
......
1105 1346
    int selector;
1106 1347
    SegmentCache *dt;
1107 1348
    uint32_t e1, e2;
1108
    int index;
1109
    uint8_t *ptr;
1349
    int index, entry_limit;
1350
    target_ulong ptr;
1110 1351
    
1111 1352
    selector = T0 & 0xffff;
1112 1353
    if ((selector & 0xfffc) == 0) {
1113 1354
        /* XXX: NULL selector case: invalid LDT */
1114
        env->ldt.base = NULL;
1355
        env->ldt.base = 0;
1115 1356
        env->ldt.limit = 0;
1116 1357
    } else {
1117 1358
        if (selector & 0x4)
1118 1359
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1119 1360
        dt = &env->gdt;
1120 1361
        index = selector & ~7;
1121
        if ((index + 7) > dt->limit)
1362
#ifdef TARGET_X86_64
1363
        if (env->hflags & HF_LMA_MASK)
1364
            entry_limit = 15;
1365
        else
1366
#endif            
1367
            entry_limit = 7;
1368
        if ((index + entry_limit) > dt->limit)
1122 1369
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1123 1370
        ptr = dt->base + index;
1124 1371
        e1 = ldl_kernel(ptr);
......
1127 1374
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1128 1375
        if (!(e2 & DESC_P_MASK))
1129 1376
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1130
        load_seg_cache_raw_dt(&env->ldt, e1, e2);
1377
#ifdef TARGET_X86_64
1378
        if (env->hflags & HF_LMA_MASK) {
1379
            uint32_t e3;
1380
            e3 = ldl_kernel(ptr + 8);
1381
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
1382
            env->ldt.base |= (target_ulong)e3 << 32;
1383
        } else
1384
#endif
1385
        {
1386
            load_seg_cache_raw_dt(&env->ldt, e1, e2);
1387
        }
1131 1388
    }
1132 1389
    env->ldt.selector = selector;
1133 1390
}
......
1137 1394
    int selector;
1138 1395
    SegmentCache *dt;
1139 1396
    uint32_t e1, e2;
1140
    int index, type;
1141
    uint8_t *ptr;
1397
    int index, type, entry_limit;
1398
    target_ulong ptr;
1142 1399
    
1143 1400
    selector = T0 & 0xffff;
1144 1401
    if ((selector & 0xfffc) == 0) {
1145
        /* NULL selector case: invalid LDT */
1146
        env->tr.base = NULL;
1402
        /* NULL selector case: invalid TR */
1403
        env->tr.base = 0;
1147 1404
        env->tr.limit = 0;
1148 1405
        env->tr.flags = 0;
1149 1406
    } else {
......
1151 1408
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1152 1409
        dt = &env->gdt;
1153 1410
        index = selector & ~7;
1154
        if ((index + 7) > dt->limit)
1411
#ifdef TARGET_X86_64
1412
        if (env->hflags & HF_LMA_MASK)
1413
            entry_limit = 15;
1414
        else
1415
#endif            
1416
            entry_limit = 7;
1417
        if ((index + entry_limit) > dt->limit)
1155 1418
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1156 1419
        ptr = dt->base + index;
1157 1420
        e1 = ldl_kernel(ptr);
......
1162 1425
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1163 1426
        if (!(e2 & DESC_P_MASK))
1164 1427
            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1165
        load_seg_cache_raw_dt(&env->tr, e1, e2);
1428
#ifdef TARGET_X86_64
1429
        if (env->hflags & HF_LMA_MASK) {
1430
            uint32_t e3;
1431
            e3 = ldl_kernel(ptr + 8);
1432
            load_seg_cache_raw_dt(&env->tr, e1, e2);
1433
            env->tr.base |= (target_ulong)e3 << 32;
1434
        } else 
1435
#endif
1436
        {
1437
            load_seg_cache_raw_dt(&env->tr, e1, e2);
1438
        }
1166 1439
        e2 |= DESC_TSS_BUSY_MASK;
1167 1440
        stl_kernel(ptr + 4, e2);
1168 1441
    }
......
1176 1449
    int cpl, dpl, rpl;
1177 1450
    SegmentCache *dt;
1178 1451
    int index;
1179
    uint8_t *ptr;
1452
    target_ulong ptr;
1180 1453

  
1181 1454
    selector &= 0xffff;
1182 1455
    if ((selector & 0xfffc) == 0) {
1183 1456
        /* null selector case */
1184 1457
        if (seg_reg == R_SS)
1185 1458
            raise_exception_err(EXCP0D_GPF, 0);
1186
        cpu_x86_load_seg_cache(env, seg_reg, selector, NULL, 0, 0);
1459
        cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
1187 1460
    } else {
1188 1461
        
1189 1462
        if (selector & 0x4)
......
1196 1469
        ptr = dt->base + index;
1197 1470
        e1 = ldl_kernel(ptr);
1198 1471
        e2 = ldl_kernel(ptr + 4);
1199

  
1472
        
1200 1473
        if (!(e2 & DESC_S_MASK))
1201 1474
            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1202 1475
        rpl = selector & 3;
......
1247 1520
/* protected mode jump */
1248 1521
void helper_ljmp_protected_T0_T1(int next_eip)
1249 1522
{
1250
    int new_cs, new_eip, gate_cs, type;
1523
    int new_cs, gate_cs, type;
1251 1524
    uint32_t e1, e2, cpl, dpl, rpl, limit;
1252

  
1525
    target_ulong new_eip;
1526
    
1253 1527
    new_cs = T0;
1254 1528
    new_eip = T1;
1255 1529
    if ((new_cs & 0xfffc) == 0)
......
1312 1586
            if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) != 
1313 1587
                 (DESC_S_MASK | DESC_CS_MASK)))
1314 1588
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1315
            if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
1589
            if (((e2 & DESC_C_MASK) && (dpl > cpl)) || 
1316 1590
                (!(e2 & DESC_C_MASK) && (dpl != cpl)))
1317 1591
                raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1318 1592
            if (!(e2 & DESC_P_MASK))
......
1336 1610
{
1337 1611
    int new_cs, new_eip;
1338 1612
    uint32_t esp, esp_mask;
1339
    uint8_t *ssp;
1613
    target_ulong ssp;
1340 1614

  
1341 1615
    new_cs = T0;
1342 1616
    new_eip = T1;
......
1354 1628
    ESP = (ESP & ~esp_mask) | (esp & esp_mask);
1355 1629
    env->eip = new_eip;
1356 1630
    env->segs[R_CS].selector = new_cs;
1357
    env->segs[R_CS].base = (uint8_t *)(new_cs << 4);
1631
    env->segs[R_CS].base = (new_cs << 4);
1358 1632
}
1359 1633

  
1360 1634
/* protected mode call */
......
1364 1638
    uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
1365 1639
    uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
1366 1640
    uint32_t val, limit, old_sp_mask;
1367
    uint8_t *ssp, *old_ssp;
1641
    target_ulong ssp, old_ssp;
1368 1642
    
1369 1643
    new_cs = T0;
1370 1644
    new_eip = T1;
......
1471 1745
            get_ss_esp_from_tss(&ss, &sp, dpl);
1472 1746
#ifdef DEBUG_PCALL
1473 1747
            if (loglevel & CPU_LOG_PCALL)
1474
                fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=%x\n", 
1748
                fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n", 
1475 1749
                        ss, sp, param_count, ESP);
1476 1750
#endif
1477 1751
            if ((ss & 0xfffc) == 0)
......
1555 1829
void helper_iret_real(int shift)
1556 1830
{
1557 1831
    uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
1558
    uint8_t *ssp;
1832
    target_ulong ssp;
1559 1833
    int eflags_mask;
1560 1834

  
1561 1835
    sp_mask = 0xffff; /* XXXX: use SS segment size ? */
......
1595 1869
    if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
1596 1870
        /* data or non conforming code segment */
1597 1871
        if (dpl < cpl) {
1598
            cpu_x86_load_seg_cache(env, seg_reg, 0, NULL, 0, 0);
1872
            cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
1599 1873
        }
1600 1874
    }
1601 1875
}
......
1603 1877
/* protected mode iret */
1604 1878
static inline void helper_ret_protected(int shift, int is_iret, int addend)
1605 1879
{
1606
    uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss, sp_mask;
1880
    uint32_t new_cs, new_eflags, new_ss;
1607 1881
    uint32_t new_es, new_ds, new_fs, new_gs;
1608 1882
    uint32_t e1, e2, ss_e1, ss_e2;
1609 1883
    int cpl, dpl, rpl, eflags_mask, iopl;
1610
    uint8_t *ssp;
1884
    target_ulong ssp, sp, new_eip, new_esp, sp_mask;
1611 1885
    
1612
    sp_mask = get_sp_mask(env->segs[R_SS].flags);
1886
#ifdef TARGET_X86_64
1887
    if (shift == 2)
1888
        sp_mask = -1;
1889
    else
1890
#endif
1891
        sp_mask = get_sp_mask(env->segs[R_SS].flags);
1613 1892
    sp = ESP;
1614 1893
    ssp = env->segs[R_SS].base;
1615 1894
    new_eflags = 0; /* avoid warning */
1895
#ifdef TARGET_X86_64
1896
    if (shift == 2) {
1897
        POPQ(sp, new_eip);
1898
        POPQ(sp, new_cs);
1899
        new_cs &= 0xffff;
1900
        if (is_iret) {
1901
            POPQ(sp, new_eflags);
1902
        }
1903
    } else
1904
#endif
1616 1905
    if (shift == 1) {
1617 1906
        /* 32 bits */
1618 1907
        POPL(ssp, sp, sp_mask, new_eip);
......
1632 1921
    }
1633 1922
#ifdef DEBUG_PCALL
1634 1923
    if (loglevel & CPU_LOG_PCALL) {
1635
        fprintf(logfile, "lret new %04x:%08x s=%d addend=0x%x\n",
1924
        fprintf(logfile, "lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
1636 1925
                new_cs, new_eip, shift, addend);
1637 1926
        cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1638 1927
    }
......
1660 1949
        raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1661 1950
    
1662 1951
    sp += addend;
1663
    if (rpl == cpl) {
1952
    if (rpl == cpl && !(env->hflags & HF_CS64_MASK)) {
1664 1953
        /* return to same priledge level */
1665 1954
        cpu_x86_load_seg_cache(env, R_CS, new_cs, 
1666 1955
                       get_seg_base(e1, e2),
......
1668 1957
                       e2);
1669 1958
    } else {
1670 1959
        /* return to different priviledge level */
1960
#ifdef TARGET_X86_64
1961
        if (shift == 2) {
1962
            POPQ(sp, new_esp);
1963
            POPQ(sp, new_ss);
1964
            new_ss &= 0xffff;
1965
        } else
1966
#endif
1671 1967
        if (shift == 1) {
1672 1968
            /* 32 bits */
1673 1969
            POPL(ssp, sp, sp_mask, new_esp);
......
1680 1976
        }
1681 1977
#ifdef DEBUG_PCALL
1682 1978
        if (loglevel & CPU_LOG_PCALL) {
1683
            fprintf(logfile, "new ss:esp=%04x:%08x\n",
1979
            fprintf(logfile, "new ss:esp=%04x:" TARGET_FMT_lx "\n",
1684 1980
                    new_ss, new_esp);
1685 1981
        }
1686 1982
#endif
1687
        
1688
        if ((new_ss & 3) != rpl)
1689
            raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1690
        if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
1691
            raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1692
        if (!(ss_e2 & DESC_S_MASK) ||
1693
            (ss_e2 & DESC_CS_MASK) ||
1694
            !(ss_e2 & DESC_W_MASK))
1695
            raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1696
        dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
1697
        if (dpl != rpl)
1698
            raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1699
        if (!(ss_e2 & DESC_P_MASK))
1700
            raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
1983
        if ((env->hflags & HF_LMA_MASK) && (new_ss & 0xfffc) == 0) {
1984
            /* NULL ss is allowed in long mode */
1985
            cpu_x86_load_seg_cache(env, R_SS, new_ss, 
1986
                                   0, 0xffffffff,
1987
                                   DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1988
                                   DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
1989
                                   DESC_W_MASK | DESC_A_MASK);
1990
        } else {
1991
            if ((new_ss & 3) != rpl)
1992
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1993
            if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
1994
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1995
            if (!(ss_e2 & DESC_S_MASK) ||
1996
                (ss_e2 & DESC_CS_MASK) ||
1997
                !(ss_e2 & DESC_W_MASK))
1998
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1999
            dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
2000
            if (dpl != rpl)
2001
                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
2002
            if (!(ss_e2 & DESC_P_MASK))
2003
                raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
2004
            cpu_x86_load_seg_cache(env, R_SS, new_ss, 
2005
                                   get_seg_base(ss_e1, ss_e2),
2006
                                   get_seg_limit(ss_e1, ss_e2),
2007
                                   ss_e2);
2008
        }
1701 2009

  
1702 2010
        cpu_x86_load_seg_cache(env, R_CS, new_cs, 
1703 2011
                       get_seg_base(e1, e2),
1704 2012
                       get_seg_limit(e1, e2),
1705 2013
                       e2);
1706
        cpu_x86_load_seg_cache(env, R_SS, new_ss, 
1707
                       get_seg_base(ss_e1, ss_e2),
1708
                       get_seg_limit(ss_e1, ss_e2),
1709
                       ss_e2);
1710 2014
        cpu_x86_set_cpl(env, rpl);
1711 2015
        sp = new_esp;
1712
        sp_mask = get_sp_mask(ss_e2);
2016
#ifdef TARGET_X86_64
2017
        if (shift == 2)
2018
            sp_mask = -1;
2019
        else
2020
#endif
2021
            sp_mask = get_sp_mask(ss_e2);
1713 2022

  
1714 2023
        /* validate data segments */
1715 2024
        validate_seg(R_ES, cpl);
......
1765 2074
    
1766 2075
    /* specific case for TSS */
1767 2076
    if (env->eflags & NT_MASK) {
2077
#ifdef TARGET_X86_64
2078
        if (env->hflags & HF_LMA_MASK)
2079
            raise_exception_err(EXCP0D_GPF, 0);
2080
#endif
1768 2081
        tss_selector = lduw_kernel(env->tr.base + 0);
1769 2082
        if (tss_selector & 4)
1770 2083
            raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
......
1793 2106
    env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
1794 2107
    cpu_x86_set_cpl(env, 0);
1795 2108
    cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc, 
1796
                           NULL, 0xffffffff, 
2109
                           0, 0xffffffff, 
1797 2110
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1798 2111
                           DESC_S_MASK |
1799 2112
                           DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1800 2113
    cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc, 
1801
                           NULL, 0xffffffff,
2114
                           0, 0xffffffff,
1802 2115
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1803 2116
                           DESC_S_MASK |
1804 2117
                           DESC_W_MASK | DESC_A_MASK);
......
1816 2129
    }
1817 2130
    cpu_x86_set_cpl(env, 3);
1818 2131
    cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3, 
1819
                           NULL, 0xffffffff, 
2132
                           0, 0xffffffff, 
1820 2133
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1821 2134
                           DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1822 2135
                           DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
1823 2136
    cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3, 
1824
                           NULL, 0xffffffff,
2137
                           0, 0xffffffff,
1825 2138
                           DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1826 2139
                           DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
1827 2140
                           DESC_W_MASK | DESC_A_MASK);
......
1863 2176
    uint64_t val;
1864 2177
    
1865 2178
    val = cpu_get_tsc(env);
1866
    EAX = val;
1867
    EDX = val >> 32;
2179
    EAX = (uint32_t)(val);
2180
    EDX = (uint32_t)(val >> 32);
2181
}
2182

  
2183
#if defined(CONFIG_USER_ONLY) 
2184
void helper_wrmsr(void)
2185
{
1868 2186
}
1869 2187

  
2188
void helper_rdmsr(void)
2189
{
2190
}
2191
#else
1870 2192
void helper_wrmsr(void)
1871 2193
{
1872
    switch(ECX) {
2194
    uint64_t val;
2195

  
2196
    val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
2197

  
2198
    switch((uint32_t)ECX) {
1873 2199
    case MSR_IA32_SYSENTER_CS:
1874
        env->sysenter_cs = EAX & 0xffff;
2200
        env->sysenter_cs = val & 0xffff;
1875 2201
        break;
1876 2202
    case MSR_IA32_SYSENTER_ESP:
1877
        env->sysenter_esp = EAX;
2203
        env->sysenter_esp = val;
1878 2204
        break;
1879 2205
    case MSR_IA32_SYSENTER_EIP:
1880
        env->sysenter_eip = EAX;
2206
        env->sysenter_eip = val;
2207
        break;
2208
    case MSR_IA32_APICBASE:
2209
        cpu_set_apic_base(env, val);
2210
        break;
2211
#ifdef TARGET_X86_64
2212
    case MSR_EFER:
2213
#define MSR_EFER_UPDATE_MASK (MSR_EFER_SCE | MSR_EFER_LME | \
2214
                              MSR_EFER_NXE | MSR_EFER_FFXSR)
2215
        env->efer = (env->efer & ~MSR_EFER_UPDATE_MASK) | 
2216
            (val & MSR_EFER_UPDATE_MASK);
1881 2217
        break;
2218
    case MSR_STAR:
2219
        env->star = val;
2220
        break;
2221
    case MSR_LSTAR:
2222
        env->lstar = val;
2223
        break;
2224
    case MSR_CSTAR:
2225
        env->cstar = val;
2226
        break;
2227
    case MSR_FMASK:
2228
        env->fmask = val;
2229
        break;
2230
    case MSR_FSBASE:
2231
        env->segs[R_FS].base = val;
2232
        break;
2233
    case MSR_GSBASE:
2234
        env->segs[R_GS].base = val;
2235
        break;
2236
    case MSR_KERNELGSBASE:
2237
        env->kernelgsbase = val;
2238
        break;
2239
#endif
1882 2240
    default:
1883 2241
        /* XXX: exception ? */
1884 2242
        break; 
......
1887 2245

  
1888 2246
void helper_rdmsr(void)
1889 2247
{
1890
    switch(ECX) {
2248
    uint64_t val;
2249
    switch((uint32_t)ECX) {
1891 2250
    case MSR_IA32_SYSENTER_CS:
1892
        EAX = env->sysenter_cs;
1893
        EDX = 0;
2251
        val = env->sysenter_cs;
1894 2252
        break;
1895 2253
    case MSR_IA32_SYSENTER_ESP:
1896
        EAX = env->sysenter_esp;
1897
        EDX = 0;
2254
        val = env->sysenter_esp;
1898 2255
        break;
1899 2256
    case MSR_IA32_SYSENTER_EIP:
1900
        EAX = env->sysenter_eip;
1901
        EDX = 0;
2257
        val = env->sysenter_eip;
2258
        break;
2259
    case MSR_IA32_APICBASE:
2260
        val = cpu_get_apic_base(env);
2261
        break;
2262
#ifdef TARGET_X86_64
2263
    case MSR_EFER:
2264
        val = env->efer;
2265
        break;
2266
    case MSR_STAR:
2267
        val = env->star;
2268
        break;
2269
    case MSR_LSTAR:
2270
        val = env->lstar;
2271
        break;
2272
    case MSR_CSTAR:
2273
        val = env->cstar;
2274
        break;
2275
    case MSR_FMASK:
2276
        val = env->fmask;
2277
        break;
2278
    case MSR_FSBASE:
2279
        val = env->segs[R_FS].base;
2280
        break;
2281
    case MSR_GSBASE:
2282
        val = env->segs[R_GS].base;
1902 2283
        break;
2284
    case MSR_KERNELGSBASE:
2285
        val = env->kernelgsbase;
2286
        break;
2287
#endif
1903 2288
    default:
1904 2289
        /* XXX: exception ? */
2290
        val = 0;
1905 2291
        break; 
1906 2292
    }
2293
    EAX = (uint32_t)(val);
2294
    EDX = (uint32_t)(val >> 32);
1907 2295
}
2296
#endif
1908 2297

  
1909 2298
void helper_lsl(void)
1910 2299
{
......
2055 2444
{
2056 2445
    int new_fpstt;
2057 2446
    new_fpstt = (env->fpstt - 1) & 7;
2058
    env->fpregs[new_fpstt] = helper_fldt((uint8_t *)A0);
2447
    env->fpregs[new_fpstt] = helper_fldt(A0);
2059 2448
    env->fpstt = new_fpstt;
2060 2449
    env->fptags[new_fpstt] = 0; /* validate stack entry */
2061 2450
}
2062 2451

  
2063 2452
void helper_fstt_ST0_A0(void)
2064 2453
{
2065
    helper_fstt(ST0, (uint8_t *)A0);
2454
    helper_fstt(ST0, A0);
2066 2455
}
2067 2456

  
2068 2457
void fpu_set_exception(int mask)
......
2102 2491

  
2103 2492
    val = 0;
2104 2493
    for(i = 8; i >= 0; i--) {
2105
        v = ldub((uint8_t *)A0 + i);
2494
        v = ldub(A0 + i);
2106 2495
        val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
2107 2496
    }
2108 2497
    tmp = val;
2109
    if (ldub((uint8_t *)A0 + 9) & 0x80)
2498
    if (ldub(A0 + 9) & 0x80)
2110 2499
        tmp = -tmp;
2111 2500
    fpush();
2112 2501
    ST0 = tmp;
......
2116 2505
{
2117 2506
    CPU86_LDouble tmp;
2118 2507
    int v;
2119
    uint8_t *mem_ref, *mem_end;
2508
    target_ulong mem_ref, mem_end;
2120 2509
    int64_t val;
2121 2510

  
2122 2511
    tmp = rint(ST0);
2123 2512
    val = (int64_t)tmp;
2124
    mem_ref = (uint8_t *)A0;
2513
    mem_ref = A0;
2125 2514
    mem_end = mem_ref + 9;
2126 2515
    if (val < 0) {
2127 2516
        stb(mem_end, 0x80);
......
2402 2791
    }
2403 2792
}
2404 2793

  
2405
void helper_fstenv(uint8_t *ptr, int data32)
2794
void helper_fstenv(target_ulong ptr, int data32)
2406 2795
{
2407 2796
    int fpus, fptag, exp, i;
2408 2797
    uint64_t mant;
......
2452 2841
    }
2453 2842
}
2454 2843

  
2455
void helper_fldenv(uint8_t *ptr, int data32)
2844
void helper_fldenv(target_ulong ptr, int data32)
2456 2845
{
2457 2846
    int i, fpus, fptag;
2458 2847

  
......
2474 2863
    }
2475 2864
}
2476 2865

  
2477
void helper_fsave(uint8_t *ptr, int data32)
2866
void helper_fsave(target_ulong ptr, int data32)
2478 2867
{
2479 2868
    CPU86_LDouble tmp;
2480 2869
    int i;
......
2502 2891
    env->fptags[7] = 1;
2503 2892
}
2504 2893

  
2505
void helper_frstor(uint8_t *ptr, int data32)
2894
void helper_frstor(target_ulong ptr, int data32)
2506 2895
{
2507 2896
    CPU86_LDouble tmp;
2508 2897
    int i;
......
2517 2906
    }
2518 2907
}
2519 2908

  
2520
/* XXX: merge with helper_fstt ? */
2909
void helper_fxsave(target_ulong ptr, int data64)
2910
{
2911
    int fpus, fptag, i, nb_xmm_regs;
2912
    CPU86_LDouble tmp;
2913
    target_ulong addr;
2914

  
2915
    fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
2916
    fptag = 0;
2917
    for(i = 0; i < 8; i++) {
2918
        fptag |= ((!env->fptags[(env->fpstt + i) & 7]) << i);
2919
    }
2920
    stw(ptr, env->fpuc);
2921
    stw(ptr + 2, fpus);
2922
    stw(ptr + 4, fptag);
2923

  
2924
    addr = ptr + 0x20;
2925
    for(i = 0;i < 8; i++) {
2926
        tmp = ST(i);
2927
        helper_fstt(tmp, addr);
2928
        addr += 16;
2929
    }
2930
    
2931
    if (env->cr[4] & CR4_OSFXSR_MASK) {
2932
        /* XXX: finish it, endianness */
2933
        stl(ptr + 0x18, 0); /* mxcsr */
2934
        stl(ptr + 0x1c, 0); /* mxcsr_mask */
2935
        nb_xmm_regs = 8 << data64;
2936
        addr = ptr + 0xa0;
2937
        for(i = 0; i < nb_xmm_regs; i++) {
2938
            stq(addr, env->xmm_regs[i].u.q[0]);
2939
            stq(addr, env->xmm_regs[i].u.q[1]);
2940
            addr += 16;
2941
        }
2942
    }
2943
}
2944

  
2945
void helper_fxrstor(target_ulong ptr, int data64)
2946
{
2947
    int i, fpus, fptag, nb_xmm_regs;
2948
    CPU86_LDouble tmp;
2949
    target_ulong addr;
2950

  
2951
    env->fpuc = lduw(ptr);
2952
    fpus = lduw(ptr + 2);
2953
    fptag = ldub(ptr + 4);
2954
    env->fpstt = (fpus >> 11) & 7;
2955
    env->fpus = fpus & ~0x3800;
2956
    fptag ^= 0xff;
2957
    for(i = 0;i < 8; i++) {
2958
        env->fptags[(env->fpstt + i) & 7] = ((fptag >> i) & 1);
2959
    }
2960

  
2961
    addr = ptr + 0x20;
2962
    for(i = 0;i < 8; i++) {
2963
        tmp = helper_fldt(addr);
2964
        ST(i) = tmp;
2965
        addr += 16;
2966
    }
2967

  
2968
    if (env->cr[4] & CR4_OSFXSR_MASK) {
2969
        /* XXX: finish it, endianness */
2970
        //ldl(ptr + 0x18);
2971
        //ldl(ptr + 0x1c);
2972
        nb_xmm_regs = 8 << data64;
2973
        addr = ptr + 0xa0;
2974
        for(i = 0; i < nb_xmm_regs; i++) {
2975
            env->xmm_regs[i].u.q[0] = ldq(addr);
2976
            env->xmm_regs[i].u.q[1] = ldq(addr);
2977
            addr += 16;
2978
        }
2979
    }
2980
}
2521 2981

  
2522 2982
#ifndef USE_X86LDOUBLE
2523 2983

  
......
2575 3035
}
2576 3036
#endif
2577 3037

  
3038
#ifdef TARGET_X86_64
3039

  
3040
//#define DEBUG_MULDIV
3041

  
3042
static void add128(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
3043
{
3044
    *plow += a;
3045
    /* carry test */
3046
    if (*plow < a)
3047
        (*phigh)++;
3048
    *phigh += b;
3049
}
3050

  
3051
static void neg128(uint64_t *plow, uint64_t *phigh)
3052
{
3053
    *plow = ~ *plow;
3054
    *phigh = ~ *phigh;
3055
    add128(plow, phigh, 1, 0);
3056
}
3057

  
3058
static void mul64(uint64_t *plow, uint64_t *phigh, uint64_t a, uint64_t b)
3059
{
3060
    uint32_t a0, a1, b0, b1;
3061
    uint64_t v;
3062

  
3063
    a0 = a;
3064
    a1 = a >> 32;
3065

  
3066
    b0 = b;
3067
    b1 = b >> 32;
3068
    
3069
    v = (uint64_t)a0 * (uint64_t)b0;
3070
    *plow = v;
3071
    *phigh = 0;
3072

  
3073
    v = (uint64_t)a0 * (uint64_t)b1;
3074
    add128(plow, phigh, v << 32, v >> 32);
3075
    
3076
    v = (uint64_t)a1 * (uint64_t)b0;
3077
    add128(plow, phigh, v << 32, v >> 32);
3078
    
3079
    v = (uint64_t)a1 * (uint64_t)b1;
3080
    *phigh += v;
3081
#ifdef DEBUG_MULDIV
3082
    printf("mul: 0x%016llx * 0x%016llx = 0x%016llx%016llx\n",
3083
           a, b, *phigh, *plow);
3084
#endif
3085
}
3086

  
3087
static void imul64(uint64_t *plow, uint64_t *phigh, int64_t a, int64_t b)
3088
{
3089
    int sa, sb;
3090
    sa = (a < 0);
3091
    if (sa)
3092
        a = -a;
3093
    sb = (b < 0);
3094
    if (sb)
3095
        b = -b;
3096
    mul64(plow, phigh, a, b);
3097
    if (sa ^ sb) {
3098
        neg128(plow, phigh);
3099
    }
3100
}
3101

  
3102
static void div64(uint64_t *plow, uint64_t *phigh, uint64_t b)
3103
{
3104
    uint64_t q, r, a1, a0;
3105
    int i, qb;
3106

  
3107
    a0 = *plow;
3108
    a1 = *phigh;
3109
    if (a1 == 0) {
3110
        q = a0 / b;
3111
        r = a0 % b;
3112
        *plow = q;
3113
        *phigh = r;
3114
    } else {
3115
        /* XXX: use a better algorithm */
3116
        for(i = 0; i < 64; i++) {
3117
            if (a1 >= b) {
3118
                a1 -= b;
3119
                qb = 1;
3120
            } else {
3121
                qb = 0;
3122
            }
3123
            a1 = (a1 << 1) | (a0 >> 63);
3124
            a0 = (a0 << 1) | qb;
3125
        }
3126
#if defined(DEBUG_MULDIV) || 1
3127
        printf("div: 0x%016llx%016llx / 0x%016llx: q=0x%016llx r=0x%016llx\n",
3128
               *phigh, *plow, b, a0, a1);
3129
#endif
3130
        *plow = a0;
3131
        *phigh = a1;
3132
    }
3133
}
3134

  
3135
static void idiv64(uint64_t *plow, uint64_t *phigh, uint64_t b)
3136
{
3137
    int sa, sb;
3138
    sa = ((int64_t)*phigh < 0);
3139
    if (sa)
3140
        neg128(plow, phigh);
3141
    sb = (b < 0);
3142
    if (sb)
3143
        b = -b;
3144
    div64(plow, phigh, b);
3145
    if (sa ^ sb)
3146
        *plow = - *plow;
3147
    if (sb)
3148
        *phigh = - *phigh;
3149
}
3150

  
3151
void helper_mulq_EAX_T0(void)
3152
{
3153
    uint64_t r0, r1;
3154

  
3155
    mul64(&r0, &r1, EAX, T0);
3156
    EAX = r0;
3157
    EDX = r1;
3158
    CC_DST = r0;
3159
    CC_SRC = r1;
3160
}
3161

  
3162
void helper_imulq_EAX_T0(void)
3163
{
3164
    uint64_t r0, r1;
3165

  
3166
    imul64(&r0, &r1, EAX, T0);
3167
    EAX = r0;
3168
    EDX = r1;
3169
    CC_DST = r0;
3170
    CC_SRC = (r1 != (r0 >> 63));
3171
}
3172

  
3173
void helper_imulq_T0_T1(void)
3174
{
3175
    uint64_t r0, r1;
3176

  
3177
    imul64(&r0, &r1, T0, T1);
3178
    T0 = r0;
3179
    CC_DST = r0;
3180
    CC_SRC = ((int64_t)r1 != ((int64_t)r0 >> 63));
3181
}
3182

  
3183
void helper_divq_EAX_T0(void)
3184
{
3185
    uint64_t r0, r1;
3186
    if (T0 == 0) {
3187
        raise_exception(EXCP00_DIVZ);
3188
    }
3189
    r0 = EAX;
3190
    r1 = EDX;
3191
    div64(&r0, &r1, T0);
3192
    EAX = r0;
3193
    EDX = r1;
3194
}
3195

  
3196
void helper_idivq_EAX_T0(void)
3197
{
3198
    uint64_t r0, r1;
3199
    if (T0 == 0) {
3200
        raise_exception(EXCP00_DIVZ);
3201
    }
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff