/[qemu]/qemu/target-i386/helper.c
ViewVC logotype

Diff of /qemu/target-i386/helper.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.33 by bellard, Sun Nov 14 15:39:16 2004 UTC revision 1.34 by bellard, Mon Jan 3 23:50:08 2005 UTC
# Line 119  static inline int load_segment(uint32_t Line 119  static inline int load_segment(uint32_t
119  {  {
120      SegmentCache *dt;      SegmentCache *dt;
121      int index;      int index;
122      uint8_t *ptr;      target_ulong ptr;
123    
124      if (selector & 0x4)      if (selector & 0x4)
125          dt = &env->ldt;          dt = &env->ldt;
# Line 143  static inline unsigned int get_seg_limit Line 143  static inline unsigned int get_seg_limit
143      return limit;      return limit;
144  }  }
145    
146  static inline uint8_t *get_seg_base(uint32_t e1, uint32_t e2)  static inline uint32_t get_seg_base(uint32_t e1, uint32_t e2)
147  {  {
148      return (uint8_t *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));      return ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
149  }  }
150    
151  static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)  static inline void load_seg_cache_raw_dt(SegmentCache *sc, uint32_t e1, uint32_t e2)
# Line 160  static inline void load_seg_vm(int seg, Line 160  static inline void load_seg_vm(int seg,
160  {  {
161      selector &= 0xffff;      selector &= 0xffff;
162      cpu_x86_load_seg_cache(env, seg, selector,      cpu_x86_load_seg_cache(env, seg, selector,
163                             (uint8_t *)(selector << 4), 0xffff, 0);                             (selector << 4), 0xffff, 0);
164  }  }
165    
166  static inline void get_ss_esp_from_tss(uint32_t *ss_ptr,  static inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
# Line 258  static void switch_tss(int tss_selector, Line 258  static void switch_tss(int tss_selector,
258                         uint32_t next_eip)                         uint32_t next_eip)
259  {  {
260      int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;      int tss_limit, tss_limit_max, type, old_tss_limit_max, old_type, v1, v2, i;
261      uint8_t *tss_base;      target_ulong tss_base;
262      uint32_t new_regs[8], new_segs[6];      uint32_t new_regs[8], new_segs[6];
263      uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;      uint32_t new_eflags, new_eip, new_cr3, new_ldt, new_trap;
264      uint32_t old_eflags, eflags_mask;      uint32_t old_eflags, eflags_mask;
265      SegmentCache *dt;      SegmentCache *dt;
266      int index;      int index;
267      uint8_t *ptr;      target_ulong ptr;
268    
269      type = (e2 >> DESC_TYPE_SHIFT) & 0xf;      type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
270  #ifdef DEBUG_PCALL  #ifdef DEBUG_PCALL
# Line 345  static void switch_tss(int tss_selector, Line 345  static void switch_tss(int tss_selector,
345            
346      /* clear busy bit (it is restartable) */      /* clear busy bit (it is restartable) */
347      if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {      if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_IRET) {
348          uint8_t *ptr;          target_ulong ptr;
349          uint32_t e2;          uint32_t e2;
350          ptr = env->gdt.base + (env->tr.selector & ~7);          ptr = env->gdt.base + (env->tr.selector & ~7);
351          e2 = ldl_kernel(ptr + 4);          e2 = ldl_kernel(ptr + 4);
# Line 397  static void switch_tss(int tss_selector, Line 397  static void switch_tss(int tss_selector,
397    
398      /* set busy bit */      /* set busy bit */
399      if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {      if (source == SWITCH_TSS_JMP || source == SWITCH_TSS_CALL) {
400          uint8_t *ptr;          target_ulong ptr;
401          uint32_t e2;          uint32_t e2;
402          ptr = env->gdt.base + (tss_selector & ~7);          ptr = env->gdt.base + (tss_selector & ~7);
403          e2 = ldl_kernel(ptr + 4);          e2 = ldl_kernel(ptr + 4);
# Line 445  static void switch_tss(int tss_selector, Line 445  static void switch_tss(int tss_selector,
445          cpu_x86_set_cpl(env, new_segs[R_CS] & 3);          cpu_x86_set_cpl(env, new_segs[R_CS] & 3);
446          /* first just selectors as the rest may trigger exceptions */          /* first just selectors as the rest may trigger exceptions */
447          for(i = 0; i < 6; i++)          for(i = 0; i < 6; i++)
448              cpu_x86_load_seg_cache(env, i, new_segs[i], NULL, 0, 0);              cpu_x86_load_seg_cache(env, i, new_segs[i], 0, 0, 0);
449      }      }
450            
451      env->ldt.selector = new_ldt & ~4;      env->ldt.selector = new_ldt & ~4;
452      env->ldt.base = NULL;      env->ldt.base = 0;
453      env->ldt.limit = 0;      env->ldt.limit = 0;
454      env->ldt.flags = 0;      env->ldt.flags = 0;
455    
# Line 573  static inline unsigned int get_sp_mask(u Line 573  static inline unsigned int get_sp_mask(u
573    
574  #define POPL(ssp, sp, sp_mask, val)\  #define POPL(ssp, sp, sp_mask, val)\
575  {\  {\
576      val = ldl_kernel((ssp) + (sp & (sp_mask)));\      val = (uint32_t)ldl_kernel((ssp) + (sp & (sp_mask)));\
577      sp += 4;\      sp += 4;\
578  }  }
579    
# Line 582  static void do_interrupt_protected(int i Line 582  static void do_interrupt_protected(int i
582                                     unsigned int next_eip, int is_hw)                                     unsigned int next_eip, int is_hw)
583  {  {
584      SegmentCache *dt;      SegmentCache *dt;
585      uint8_t *ptr, *ssp;      target_ulong ptr, ssp;
586      int type, dpl, selector, ss_dpl, cpl, sp_mask;      int type, dpl, selector, ss_dpl, cpl, sp_mask;
587      int has_error_code, new_stack, shift;      int has_error_code, new_stack, shift;
588      uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;      uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
# Line 703  static void do_interrupt_protected(int i Line 703  static void do_interrupt_protected(int i
703          raise_exception_err(EXCP0D_GPF, selector & 0xfffc);          raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
704          new_stack = 0; /* avoid warning */          new_stack = 0; /* avoid warning */
705          sp_mask = 0; /* avoid warning */          sp_mask = 0; /* avoid warning */
706          ssp = NULL; /* avoid warning */          ssp = 0; /* avoid warning */
707          esp = 0; /* avoid warning */          esp = 0; /* avoid warning */
708      }      }
709    
# Line 754  static void do_interrupt_protected(int i Line 754  static void do_interrupt_protected(int i
754            
755      if (new_stack) {      if (new_stack) {
756          if (env->eflags & VM_MASK) {          if (env->eflags & VM_MASK) {
757              cpu_x86_load_seg_cache(env, R_ES, 0, NULL, 0, 0);              cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0, 0);
758              cpu_x86_load_seg_cache(env, R_DS, 0, NULL, 0, 0);              cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0, 0);
759              cpu_x86_load_seg_cache(env, R_FS, 0, NULL, 0, 0);              cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0, 0);
760              cpu_x86_load_seg_cache(env, R_GS, 0, NULL, 0, 0);              cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0, 0);
761          }          }
762          ss = (ss & ~3) | dpl;          ss = (ss & ~3) | dpl;
763          cpu_x86_load_seg_cache(env, R_SS, ss,          cpu_x86_load_seg_cache(env, R_SS, ss,
# Line 780  static void do_interrupt_protected(int i Line 780  static void do_interrupt_protected(int i
780      env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);      env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
781  }  }
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    
1035  /* real mode interrupt */  /* real mode interrupt */
1036  static void do_interrupt_real(int intno, int is_int, int error_code,  static void do_interrupt_real(int intno, int is_int, int error_code,
1037                                unsigned int next_eip)                                unsigned int next_eip)
1038  {  {
1039      SegmentCache *dt;      SegmentCache *dt;
1040      uint8_t *ptr, *ssp;      target_ulong ptr, ssp;
1041      int selector;      int selector;
1042      uint32_t offset, esp;      uint32_t offset, esp;
1043      uint32_t old_cs, old_eip;      uint32_t old_cs, old_eip;
# Line 813  static void do_interrupt_real(int intno, Line 1065  static void do_interrupt_real(int intno,
1065      ESP = (ESP & ~0xffff) | (esp & 0xffff);      ESP = (ESP & ~0xffff) | (esp & 0xffff);
1066      env->eip = offset;      env->eip = offset;
1067      env->segs[R_CS].selector = selector;      env->segs[R_CS].selector = selector;
1068      env->segs[R_CS].base = (uint8_t *)(selector << 4);      env->segs[R_CS].base = (selector << 4);
1069      env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);      env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
1070  }  }
1071    
1072  /* fake user mode interrupt */  /* fake user mode interrupt */
1073  void do_interrupt_user(int intno, int is_int, int error_code,  void do_interrupt_user(int intno, int is_int, int error_code,
1074                         unsigned int next_eip)                         target_ulong next_eip)
1075  {  {
1076      SegmentCache *dt;      SegmentCache *dt;
1077      uint8_t *ptr;      target_ulong ptr;
1078      int dpl, cpl;      int dpl, cpl;
1079      uint32_t e2;      uint32_t e2;
1080    
# Line 849  void do_interrupt_user(int intno, int is Line 1101  void do_interrupt_user(int intno, int is
1101   * instruction. It is only relevant if is_int is TRUE.     * instruction. It is only relevant if is_int is TRUE.  
1102   */   */
1103  void do_interrupt(int intno, int is_int, int error_code,  void do_interrupt(int intno, int is_int, int error_code,
1104                    unsigned int next_eip, int is_hw)                    target_ulong next_eip, int is_hw)
1105  {  {
1106  #ifdef DEBUG_PCALL  #ifdef DEBUG_PCALL
1107      if (loglevel & (CPU_LOG_PCALL | CPU_LOG_INT)) {      if (loglevel & (CPU_LOG_PCALL | CPU_LOG_INT)) {
1108          if ((env->cr[0] & CR0_PE_MASK)) {          if ((env->cr[0] & CR0_PE_MASK)) {
1109              static int count;              static int count;
1110              fprintf(logfile, "%6d: v=%02x e=%04x i=%d cpl=%d IP=%04x:%08x pc=%08x SP=%04x:%08x",              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,
1111                      count, intno, error_code, is_int,                      count, intno, error_code, is_int,
1112                      env->hflags & HF_CPL_MASK,                      env->hflags & HF_CPL_MASK,
1113                      env->segs[R_CS].selector, EIP,                      env->segs[R_CS].selector, EIP,
1114                      (int)env->segs[R_CS].base + EIP,                      (int)env->segs[R_CS].base + EIP,
1115                      env->segs[R_SS].selector, ESP);                      env->segs[R_SS].selector, ESP);
1116              if (intno == 0x0e) {              if (intno == 0x0e) {
1117                  fprintf(logfile, " CR2=%08x", env->cr[2]);                  fprintf(logfile, " CR2=" TARGET_FMT_lx, env->cr[2]);
1118              } else {              } else {
1119                  fprintf(logfile, " EAX=%08x", EAX);                  fprintf(logfile, " EAX=" TARGET_FMT_lx, EAX);
1120              }              }
1121              fprintf(logfile, "\n");              fprintf(logfile, "\n");
 #if 0  
1122              cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);              cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1123    #if 0
1124              {              {
1125                  int i;                  int i;
1126                  uint8_t *ptr;                  uint8_t *ptr;
# Line 885  void do_interrupt(int intno, int is_int, Line 1137  void do_interrupt(int intno, int is_int,
1137      }      }
1138  #endif  #endif
1139      if (env->cr[0] & CR0_PE_MASK) {      if (env->cr[0] & CR0_PE_MASK) {
1140          do_interrupt_protected(intno, is_int, error_code, next_eip, is_hw);  #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            }
1148      } else {      } else {
1149          do_interrupt_real(intno, is_int, error_code, next_eip);          do_interrupt_real(intno, is_int, error_code, next_eip);
1150      }      }
# Line 932  void raise_exception(int exception_index Line 1191  void raise_exception(int exception_index
1191  #ifdef BUGGY_GCC_DIV64  #ifdef BUGGY_GCC_DIV64
1192  /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we  /* gcc 2.95.4 on PowerPC does not seem to like using __udivdi3, so we
1193     call it from another function */     call it from another function */
1194  uint32_t div64(uint32_t *q_ptr, uint64_t num, uint32_t den)  uint32_t div32(uint32_t *q_ptr, uint64_t num, uint32_t den)
1195  {  {
1196      *q_ptr = num / den;      *q_ptr = num / den;
1197      return num % den;      return num % den;
1198  }  }
1199    
1200  int32_t idiv64(int32_t *q_ptr, int64_t num, int32_t den)  int32_t idiv32(int32_t *q_ptr, int64_t num, int32_t den)
1201  {  {
1202      *q_ptr = num / den;      *q_ptr = num / den;
1203      return num % den;      return num % den;
1204  }  }
1205  #endif  #endif
1206    
1207  void helper_divl_EAX_T0(uint32_t eip)  void helper_divl_EAX_T0(void)
1208  {  {
1209      unsigned int den, q, r;      unsigned int den, q, r;
1210      uint64_t num;      uint64_t num;
# Line 953  void helper_divl_EAX_T0(uint32_t eip) Line 1212  void helper_divl_EAX_T0(uint32_t eip)
1212      num = EAX | ((uint64_t)EDX << 32);      num = EAX | ((uint64_t)EDX << 32);
1213      den = T0;      den = T0;
1214      if (den == 0) {      if (den == 0) {
         EIP = eip;  
1215          raise_exception(EXCP00_DIVZ);          raise_exception(EXCP00_DIVZ);
1216      }      }
1217  #ifdef BUGGY_GCC_DIV64  #ifdef BUGGY_GCC_DIV64
1218      r = div64(&q, num, den);      r = div32(&q, num, den);
1219  #else  #else
1220      q = (num / den);      q = (num / den);
1221      r = (num % den);      r = (num % den);
1222  #endif  #endif
1223      EAX = q;      EAX = (uint32_t)q;
1224      EDX = r;      EDX = (uint32_t)r;
1225  }  }
1226    
1227  void helper_idivl_EAX_T0(uint32_t eip)  void helper_idivl_EAX_T0(void)
1228  {  {
1229      int den, q, r;      int den, q, r;
1230      int64_t num;      int64_t num;
# Line 974  void helper_idivl_EAX_T0(uint32_t eip) Line 1232  void helper_idivl_EAX_T0(uint32_t eip)
1232      num = EAX | ((uint64_t)EDX << 32);      num = EAX | ((uint64_t)EDX << 32);
1233      den = T0;      den = T0;
1234      if (den == 0) {      if (den == 0) {
         EIP = eip;  
1235          raise_exception(EXCP00_DIVZ);          raise_exception(EXCP00_DIVZ);
1236      }      }
1237  #ifdef BUGGY_GCC_DIV64  #ifdef BUGGY_GCC_DIV64
1238      r = idiv64(&q, num, den);      r = idiv32(&q, num, den);
1239  #else  #else
1240      q = (num / den);      q = (num / den);
1241      r = (num % den);      r = (num % den);
1242  #endif  #endif
1243      EAX = q;      EAX = (uint32_t)q;
1244      EDX = r;      EDX = (uint32_t)r;
1245  }  }
1246    
1247  void helper_cmpxchg8b(void)  void helper_cmpxchg8b(void)
# Line 993  void helper_cmpxchg8b(void) Line 1250  void helper_cmpxchg8b(void)
1250      int eflags;      int eflags;
1251    
1252      eflags = cc_table[CC_OP].compute_all();      eflags = cc_table[CC_OP].compute_all();
1253      d = ldq((uint8_t *)A0);      d = ldq(A0);
1254      if (d == (((uint64_t)EDX << 32) | EAX)) {      if (d == (((uint64_t)EDX << 32) | EAX)) {
1255          stq((uint8_t *)A0, ((uint64_t)ECX << 32) | EBX);          stq(A0, ((uint64_t)ECX << 32) | EBX);
1256          eflags |= CC_Z;          eflags |= CC_Z;
1257      } else {      } else {
1258          EDX = d >> 32;          EDX = d >> 32;
# Line 1005  void helper_cmpxchg8b(void) Line 1262  void helper_cmpxchg8b(void)
1262      CC_SRC = eflags;      CC_SRC = eflags;
1263  }  }
1264    
 #define CPUID_FP87 (1 << 0)  
 #define CPUID_VME  (1 << 1)  
 #define CPUID_DE   (1 << 2)  
 #define CPUID_PSE  (1 << 3)  
 #define CPUID_TSC  (1 << 4)  
 #define CPUID_MSR  (1 << 5)  
 #define CPUID_PAE  (1 << 6)  
 #define CPUID_MCE  (1 << 7)  
 #define CPUID_CX8  (1 << 8)  
 #define CPUID_APIC (1 << 9)  
 #define CPUID_SEP  (1 << 11) /* sysenter/sysexit */  
 #define CPUID_MTRR (1 << 12)  
 #define CPUID_PGE  (1 << 13)  
 #define CPUID_MCA  (1 << 14)  
 #define CPUID_CMOV (1 << 15)  
 /* ... */  
 #define CPUID_MMX  (1 << 23)  
 #define CPUID_FXSR (1 << 24)  
 #define CPUID_SSE  (1 << 25)  
 #define CPUID_SSE2 (1 << 26)  
   
1265  void helper_cpuid(void)  void helper_cpuid(void)
1266  {  {
1267      switch(EAX) {      switch((uint32_t)EAX) {
1268      case 0:      case 0:
1269          EAX = 2; /* max EAX index supported */          EAX = 2; /* max EAX index supported */
1270          EBX = 0x756e6547;          EBX = env->cpuid_vendor1;
1271          ECX = 0x6c65746e;          EDX = env->cpuid_vendor2;
1272          EDX = 0x49656e69;          ECX = env->cpuid_vendor3;
1273          break;          break;
1274      case 1:      case 1:
1275          {          EAX = env->cpuid_version;
1276              int family, model, stepping;          EBX = 0;
1277              /* EAX = 1 info */          ECX = 0;
1278  #if 0          EDX = env->cpuid_features;
             /* pentium 75-200 */  
             family = 5;  
             model = 2;  
             stepping = 11;  
 #else  
             /* pentium pro */  
             family = 6;  
             model = 1;  
             stepping = 3;  
 #endif  
             EAX = (family << 8) | (model << 4) | stepping;  
             EBX = 0;  
             ECX = 0;  
             EDX = CPUID_FP87 | CPUID_DE | CPUID_PSE |  
                 CPUID_TSC | CPUID_MSR | CPUID_MCE |  
                 CPUID_CX8 | CPUID_PGE | CPUID_CMOV;  
         }  
1279          break;          break;
1280      default:      default:
1281          /* cache info: needed for Pentium Pro compatibility */          /* cache info: needed for Pentium Pro compatibility */
# Line 1065  void helper_cpuid(void) Line 1284  void helper_cpuid(void)
1284          ECX = 0;          ECX = 0;
1285          EDX = 0;          EDX = 0;
1286          break;          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
1309      }      }
1310  }  }
1311    
1312  void helper_enter_level(int level, int data32)  void helper_enter_level(int level, int data32)
1313  {  {
1314      uint8_t *ssp;      target_ulong ssp;
1315      uint32_t esp_mask, esp, ebp;      uint32_t esp_mask, esp, ebp;
1316    
1317      esp_mask = get_sp_mask(env->segs[R_SS].flags);      esp_mask = get_sp_mask(env->segs[R_SS].flags);
# Line 1105  void helper_lldt_T0(void) Line 1346  void helper_lldt_T0(void)
1346      int selector;      int selector;
1347      SegmentCache *dt;      SegmentCache *dt;
1348      uint32_t e1, e2;      uint32_t e1, e2;
1349      int index;      int index, entry_limit;
1350      uint8_t *ptr;      target_ulong ptr;
1351            
1352      selector = T0 & 0xffff;      selector = T0 & 0xffff;
1353      if ((selector & 0xfffc) == 0) {      if ((selector & 0xfffc) == 0) {
1354          /* XXX: NULL selector case: invalid LDT */          /* XXX: NULL selector case: invalid LDT */
1355          env->ldt.base = NULL;          env->ldt.base = 0;
1356          env->ldt.limit = 0;          env->ldt.limit = 0;
1357      } else {      } else {
1358          if (selector & 0x4)          if (selector & 0x4)
1359              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1360          dt = &env->gdt;          dt = &env->gdt;
1361          index = selector & ~7;          index = selector & ~7;
1362          if ((index + 7) > dt->limit)  #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)
1369              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1370          ptr = dt->base + index;          ptr = dt->base + index;
1371          e1 = ldl_kernel(ptr);          e1 = ldl_kernel(ptr);
# Line 1127  void helper_lldt_T0(void) Line 1374  void helper_lldt_T0(void)
1374              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1375          if (!(e2 & DESC_P_MASK))          if (!(e2 & DESC_P_MASK))
1376              raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);              raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1377          load_seg_cache_raw_dt(&env->ldt, e1, e2);  #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            }
1388      }      }
1389      env->ldt.selector = selector;      env->ldt.selector = selector;
1390  }  }
# Line 1137  void helper_ltr_T0(void) Line 1394  void helper_ltr_T0(void)
1394      int selector;      int selector;
1395      SegmentCache *dt;      SegmentCache *dt;
1396      uint32_t e1, e2;      uint32_t e1, e2;
1397      int index, type;      int index, type, entry_limit;
1398      uint8_t *ptr;      target_ulong ptr;
1399            
1400      selector = T0 & 0xffff;      selector = T0 & 0xffff;
1401      if ((selector & 0xfffc) == 0) {      if ((selector & 0xfffc) == 0) {
1402          /* NULL selector case: invalid LDT */          /* NULL selector case: invalid TR */
1403          env->tr.base = NULL;          env->tr.base = 0;
1404          env->tr.limit = 0;          env->tr.limit = 0;
1405          env->tr.flags = 0;          env->tr.flags = 0;
1406      } else {      } else {
# Line 1151  void helper_ltr_T0(void) Line 1408  void helper_ltr_T0(void)
1408              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1409          dt = &env->gdt;          dt = &env->gdt;
1410          index = selector & ~7;          index = selector & ~7;
1411          if ((index + 7) > dt->limit)  #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)
1418              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1419          ptr = dt->base + index;          ptr = dt->base + index;
1420          e1 = ldl_kernel(ptr);          e1 = ldl_kernel(ptr);
# Line 1162  void helper_ltr_T0(void) Line 1425  void helper_ltr_T0(void)
1425              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1426          if (!(e2 & DESC_P_MASK))          if (!(e2 & DESC_P_MASK))
1427              raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);              raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1428          load_seg_cache_raw_dt(&env->tr, e1, e2);  #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            }
1439          e2 |= DESC_TSS_BUSY_MASK;          e2 |= DESC_TSS_BUSY_MASK;
1440          stl_kernel(ptr + 4, e2);          stl_kernel(ptr + 4, e2);
1441      }      }
# Line 1176  void load_seg(int seg_reg, int selector) Line 1449  void load_seg(int seg_reg, int selector)
1449      int cpl, dpl, rpl;      int cpl, dpl, rpl;
1450      SegmentCache *dt;      SegmentCache *dt;
1451      int index;      int index;
1452      uint8_t *ptr;      target_ulong ptr;
1453    
1454      selector &= 0xffff;      selector &= 0xffff;
1455      if ((selector & 0xfffc) == 0) {      if ((selector & 0xfffc) == 0) {
1456          /* null selector case */          /* null selector case */
1457          if (seg_reg == R_SS)          if (seg_reg == R_SS)
1458              raise_exception_err(EXCP0D_GPF, 0);              raise_exception_err(EXCP0D_GPF, 0);
1459          cpu_x86_load_seg_cache(env, seg_reg, selector, NULL, 0, 0);          cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);
1460      } else {      } else {
1461                    
1462          if (selector & 0x4)          if (selector & 0x4)
# Line 1196  void load_seg(int seg_reg, int selector) Line 1469  void load_seg(int seg_reg, int selector)
1469          ptr = dt->base + index;          ptr = dt->base + index;
1470          e1 = ldl_kernel(ptr);          e1 = ldl_kernel(ptr);
1471          e2 = ldl_kernel(ptr + 4);          e2 = ldl_kernel(ptr + 4);
1472            
1473          if (!(e2 & DESC_S_MASK))          if (!(e2 & DESC_S_MASK))
1474              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1475          rpl = selector & 3;          rpl = selector & 3;
# Line 1247  void load_seg(int seg_reg, int selector) Line 1520  void load_seg(int seg_reg, int selector)
1520  /* protected mode jump */  /* protected mode jump */
1521  void helper_ljmp_protected_T0_T1(int next_eip)  void helper_ljmp_protected_T0_T1(int next_eip)
1522  {  {
1523      int new_cs, new_eip, gate_cs, type;      int new_cs, gate_cs, type;
1524      uint32_t e1, e2, cpl, dpl, rpl, limit;      uint32_t e1, e2, cpl, dpl, rpl, limit;
1525        target_ulong new_eip;
1526        
1527      new_cs = T0;      new_cs = T0;
1528      new_eip = T1;      new_eip = T1;
1529      if ((new_cs & 0xfffc) == 0)      if ((new_cs & 0xfffc) == 0)
# Line 1312  void helper_ljmp_protected_T0_T1(int nex Line 1586  void helper_ljmp_protected_T0_T1(int nex
1586              if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=              if (((e2 & (DESC_S_MASK | DESC_CS_MASK)) !=
1587                   (DESC_S_MASK | DESC_CS_MASK)))                   (DESC_S_MASK | DESC_CS_MASK)))
1588                  raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);                  raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1589              if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||              if (((e2 & DESC_C_MASK) && (dpl > cpl)) ||
1590                  (!(e2 & DESC_C_MASK) && (dpl != cpl)))                  (!(e2 & DESC_C_MASK) && (dpl != cpl)))
1591                  raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);                  raise_exception_err(EXCP0D_GPF, gate_cs & 0xfffc);
1592              if (!(e2 & DESC_P_MASK))              if (!(e2 & DESC_P_MASK))
# Line 1336  void helper_lcall_real_T0_T1(int shift, Line 1610  void helper_lcall_real_T0_T1(int shift,
1610  {  {
1611      int new_cs, new_eip;      int new_cs, new_eip;
1612      uint32_t esp, esp_mask;      uint32_t esp, esp_mask;
1613      uint8_t *ssp;      target_ulong ssp;
1614    
1615      new_cs = T0;      new_cs = T0;
1616      new_eip = T1;      new_eip = T1;
# Line 1354  void helper_lcall_real_T0_T1(int shift, Line 1628  void helper_lcall_real_T0_T1(int shift,
1628      ESP = (ESP & ~esp_mask) | (esp & esp_mask);      ESP = (ESP & ~esp_mask) | (esp & esp_mask);
1629      env->eip = new_eip;      env->eip = new_eip;
1630      env->segs[R_CS].selector = new_cs;      env->segs[R_CS].selector = new_cs;
1631      env->segs[R_CS].base = (uint8_t *)(new_cs << 4);      env->segs[R_CS].base = (new_cs << 4);
1632  }  }
1633    
1634  /* protected mode call */  /* protected mode call */
# Line 1364  void helper_lcall_protected_T0_T1(int sh Line 1638  void helper_lcall_protected_T0_T1(int sh
1638      uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;      uint32_t e1, e2, cpl, dpl, rpl, selector, offset, param_count;
1639      uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;      uint32_t ss, ss_e1, ss_e2, sp, type, ss_dpl, sp_mask;
1640      uint32_t val, limit, old_sp_mask;      uint32_t val, limit, old_sp_mask;
1641      uint8_t *ssp, *old_ssp;      target_ulong ssp, old_ssp;
1642            
1643      new_cs = T0;      new_cs = T0;
1644      new_eip = T1;      new_eip = T1;
# Line 1471  void helper_lcall_protected_T0_T1(int sh Line 1745  void helper_lcall_protected_T0_T1(int sh
1745              get_ss_esp_from_tss(&ss, &sp, dpl);              get_ss_esp_from_tss(&ss, &sp, dpl);
1746  #ifdef DEBUG_PCALL  #ifdef DEBUG_PCALL
1747              if (loglevel & CPU_LOG_PCALL)              if (loglevel & CPU_LOG_PCALL)
1748                  fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=%x\n",                  fprintf(logfile, "new ss:esp=%04x:%08x param_count=%d ESP=" TARGET_FMT_lx "\n",
1749                          ss, sp, param_count, ESP);                          ss, sp, param_count, ESP);
1750  #endif  #endif
1751              if ((ss & 0xfffc) == 0)              if ((ss & 0xfffc) == 0)
# Line 1555  void helper_lcall_protected_T0_T1(int sh Line 1829  void helper_lcall_protected_T0_T1(int sh
1829  void helper_iret_real(int shift)  void helper_iret_real(int shift)
1830  {  {
1831      uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;      uint32_t sp, new_cs, new_eip, new_eflags, sp_mask;
1832      uint8_t *ssp;      target_ulong ssp;
1833      int eflags_mask;      int eflags_mask;
1834    
1835      sp_mask = 0xffff; /* XXXX: use SS segment size ? */      sp_mask = 0xffff; /* XXXX: use SS segment size ? */
# Line 1595  static inline void validate_seg(int seg_ Line 1869  static inline void validate_seg(int seg_
1869      if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {      if (!(e2 & DESC_CS_MASK) || !(e2 & DESC_C_MASK)) {
1870          /* data or non conforming code segment */          /* data or non conforming code segment */
1871          if (dpl < cpl) {          if (dpl < cpl) {
1872              cpu_x86_load_seg_cache(env, seg_reg, 0, NULL, 0, 0);              cpu_x86_load_seg_cache(env, seg_reg, 0, 0, 0, 0);
1873          }          }
1874      }      }
1875  }  }
# Line 1603  static inline void validate_seg(int seg_ Line 1877  static inline void validate_seg(int seg_
1877  /* protected mode iret */  /* protected mode iret */
1878  static inline void helper_ret_protected(int shift, int is_iret, int addend)  static inline void helper_ret_protected(int shift, int is_iret, int addend)
1879  {  {
1880      uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss, sp_mask;      uint32_t new_cs, new_eflags, new_ss;
1881      uint32_t new_es, new_ds, new_fs, new_gs;      uint32_t new_es, new_ds, new_fs, new_gs;
1882      uint32_t e1, e2, ss_e1, ss_e2;      uint32_t e1, e2, ss_e1, ss_e2;
1883      int cpl, dpl, rpl, eflags_mask, iopl;      int cpl, dpl, rpl, eflags_mask, iopl;
1884      uint8_t *ssp;      target_ulong ssp, sp, new_eip, new_esp, sp_mask;
1885            
1886      sp_mask = get_sp_mask(env->segs[R_SS].flags);  #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);
1892      sp = ESP;      sp = ESP;
1893      ssp = env->segs[R_SS].base;      ssp = env->segs[R_SS].base;
1894      new_eflags = 0; /* avoid warning */      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
1905      if (shift == 1) {      if (shift == 1) {
1906          /* 32 bits */          /* 32 bits */
1907          POPL(ssp, sp, sp_mask, new_eip);          POPL(ssp, sp, sp_mask, new_eip);
# Line 1632  static inline void helper_ret_protected( Line 1921  static inline void helper_ret_protected(
1921      }      }
1922  #ifdef DEBUG_PCALL  #ifdef DEBUG_PCALL
1923      if (loglevel & CPU_LOG_PCALL) {      if (loglevel & CPU_LOG_PCALL) {
1924          fprintf(logfile, "lret new %04x:%08x s=%d addend=0x%x\n",          fprintf(logfile, "lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",
1925                  new_cs, new_eip, shift, addend);                  new_cs, new_eip, shift, addend);
1926          cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);          cpu_dump_state(env, logfile, fprintf, X86_DUMP_CCOP);
1927      }      }
# Line 1660  static inline void helper_ret_protected( Line 1949  static inline void helper_ret_protected(
1949          raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);          raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
1950            
1951      sp += addend;      sp += addend;
1952      if (rpl == cpl) {      if (rpl == cpl && !(env->hflags & HF_CS64_MASK)) {
1953          /* return to same priledge level */          /* return to same priledge level */
1954          cpu_x86_load_seg_cache(env, R_CS, new_cs,          cpu_x86_load_seg_cache(env, R_CS, new_cs,
1955                         get_seg_base(e1, e2),                         get_seg_base(e1, e2),
# Line 1668  static inline void helper_ret_protected( Line 1957  static inline void helper_ret_protected(
1957                         e2);                         e2);
1958      } else {      } else {
1959          /* return to different priviledge level */          /* 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
1967          if (shift == 1) {          if (shift == 1) {
1968              /* 32 bits */              /* 32 bits */
1969              POPL(ssp, sp, sp_mask, new_esp);              POPL(ssp, sp, sp_mask, new_esp);
# Line 1680  static inline void helper_ret_protected( Line 1976  static inline void helper_ret_protected(
1976          }          }
1977  #ifdef DEBUG_PCALL  #ifdef DEBUG_PCALL
1978          if (loglevel & CPU_LOG_PCALL) {          if (loglevel & CPU_LOG_PCALL) {
1979              fprintf(logfile, "new ss:esp=%04x:%08x\n",              fprintf(logfile, "new ss:esp=%04x:" TARGET_FMT_lx "\n",
1980                      new_ss, new_esp);                      new_ss, new_esp);
1981          }          }
1982  #endif  #endif
1983                    if ((env->hflags & HF_LMA_MASK) && (new_ss & 0xfffc) == 0) {
1984          if ((new_ss & 3) != rpl)              /* NULL ss is allowed in long mode */
1985              raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);              cpu_x86_load_seg_cache(env, R_SS, new_ss,
1986          if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)                                     0, 0xffffffff,
1987              raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);                                     DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
1988          if (!(ss_e2 & DESC_S_MASK) ||                                     DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |
1989              (ss_e2 & DESC_CS_MASK) ||                                     DESC_W_MASK | DESC_A_MASK);
1990              !(ss_e2 & DESC_W_MASK))          } else {
1991              raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);              if ((new_ss & 3) != rpl)
1992          dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;                  raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1993          if (dpl != rpl)              if (load_segment(&ss_e1, &ss_e2, new_ss) != 0)
1994              raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);                  raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
1995          if (!(ss_e2 & DESC_P_MASK))              if (!(ss_e2 & DESC_S_MASK) ||
1996              raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);                  (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            }
2009    
2010          cpu_x86_load_seg_cache(env, R_CS, new_cs,          cpu_x86_load_seg_cache(env, R_CS, new_cs,
2011                         get_seg_base(e1, e2),                         get_seg_base(e1, e2),
2012                         get_seg_limit(e1, e2),                         get_seg_limit(e1, e2),
2013                         e2);                         e2);
         cpu_x86_load_seg_cache(env, R_SS, new_ss,  
                        get_seg_base(ss_e1, ss_e2),  
                        get_seg_limit(ss_e1, ss_e2),  
                        ss_e2);  
2014          cpu_x86_set_cpl(env, rpl);          cpu_x86_set_cpl(env, rpl);
2015          sp = new_esp;          sp = new_esp;
2016          sp_mask = get_sp_mask(ss_e2);  #ifdef TARGET_X86_64
2017            if (shift == 2)
2018                sp_mask = -1;
2019            else
2020    #endif
2021                sp_mask = get_sp_mask(ss_e2);
2022    
2023          /* validate data segments */          /* validate data segments */
2024          validate_seg(R_ES, cpl);          validate_seg(R_ES, cpl);
# Line 1765  void helper_iret_protected(int shift, in Line 2074  void helper_iret_protected(int shift, in
2074            
2075      /* specific case for TSS */      /* specific case for TSS */
2076      if (env->eflags & NT_MASK) {      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
2081          tss_selector = lduw_kernel(env->tr.base + 0);          tss_selector = lduw_kernel(env->tr.base + 0);
2082          if (tss_selector & 4)          if (tss_selector & 4)
2083              raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);              raise_exception_err(EXCP0A_TSS, tss_selector & 0xfffc);
# Line 1793  void helper_sysenter(void) Line 2106  void helper_sysenter(void)
2106      env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);      env->eflags &= ~(VM_MASK | IF_MASK | RF_MASK);
2107      cpu_x86_set_cpl(env, 0);      cpu_x86_set_cpl(env, 0);
2108      cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,      cpu_x86_load_seg_cache(env, R_CS, env->sysenter_cs & 0xfffc,
2109                             NULL, 0xffffffff,                             0, 0xffffffff,
2110                             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |                             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2111                             DESC_S_MASK |                             DESC_S_MASK |
2112                             DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);                             DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2113      cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,      cpu_x86_load_seg_cache(env, R_SS, (env->sysenter_cs + 8) & 0xfffc,
2114                             NULL, 0xffffffff,                             0, 0xffffffff,
2115                             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |                             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2116                             DESC_S_MASK |                             DESC_S_MASK |
2117                             DESC_W_MASK | DESC_A_MASK);                             DESC_W_MASK | DESC_A_MASK);
# Line 1816  void helper_sysexit(void) Line 2129  void helper_sysexit(void)
2129      }      }
2130      cpu_x86_set_cpl(env, 3);      cpu_x86_set_cpl(env, 3);
2131      cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,      cpu_x86_load_seg_cache(env, R_CS, ((env->sysenter_cs + 16) & 0xfffc) | 3,
2132                             NULL, 0xffffffff,                             0, 0xffffffff,
2133                             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |                             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2134                             DESC_S_MASK | (3 << DESC_DPL_SHIFT) |                             DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2135                             DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);                             DESC_CS_MASK | DESC_R_MASK | DESC_A_MASK);
2136      cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,      cpu_x86_load_seg_cache(env, R_SS, ((env->sysenter_cs + 24) & 0xfffc) | 3,
2137                             NULL, 0xffffffff,                             0, 0xffffffff,
2138                             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |                             DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
2139                             DESC_S_MASK | (3 << DESC_DPL_SHIFT) |                             DESC_S_MASK | (3 << DESC_DPL_SHIFT) |
2140                             DESC_W_MASK | DESC_A_MASK);                             DESC_W_MASK | DESC_A_MASK);
# Line 1863  void helper_rdtsc(void) Line 2176  void helper_rdtsc(void)
2176      uint64_t val;      uint64_t val;
2177            
2178      val = cpu_get_tsc(env);      val = cpu_get_tsc(env);
2179      EAX = val;      EAX = (uint32_t)(val);
2180      EDX = val >> 32;      EDX = (uint32_t)(val >> 32);
2181  }  }
2182    
2183    #if defined(CONFIG_USER_ONLY)
2184  void helper_wrmsr(void)  void helper_wrmsr(void)
2185  {  {
2186      switch(ECX) {  }
2187    
2188    void helper_rdmsr(void)
2189    {
2190    }
2191    #else
2192    void helper_wrmsr(void)
2193    {
2194        uint64_t val;
2195    
2196        val = ((uint32_t)EAX) | ((uint64_t)((uint32_t)EDX) << 32);
2197    
2198        switch((uint32_t)ECX) {
2199      case MSR_IA32_SYSENTER_CS:      case MSR_IA32_SYSENTER_CS:
2200          env->sysenter_cs = EAX & 0xffff;          env->sysenter_cs = val & 0xffff;
2201          break;          break;
2202      case MSR_IA32_SYSENTER_ESP:      case MSR_IA32_SYSENTER_ESP:
2203          env->sysenter_esp = EAX;          env->sysenter_esp = val;
2204          break;          break;
2205      case MSR_IA32_SYSENTER_EIP:      case MSR_IA32_SYSENTER_EIP:
2206          env->sysenter_eip = EAX;          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);
2217            break;
2218        case MSR_STAR:
2219            env->star = val;
2220            break;
2221        case MSR_LSTAR:
2222            env->lstar = val;
2223          break;          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
2240      default:      default:
2241          /* XXX: exception ? */          /* XXX: exception ? */
2242          break;          break;
# Line 1887  void helper_wrmsr(void) Line 2245  void helper_wrmsr(void)
2245    
2246  void helper_rdmsr(void)  void helper_rdmsr(void)
2247  {  {
2248      switch(ECX) {      uint64_t val;
2249        switch((uint32_t)ECX) {
2250      case MSR_IA32_SYSENTER_CS:      case MSR_IA32_SYSENTER_CS:
2251          EAX = env->sysenter_cs;          val = env->sysenter_cs;
         EDX = 0;  
2252          break;          break;
2253      case MSR_IA32_SYSENTER_ESP:      case MSR_IA32_SYSENTER_ESP:
2254          EAX = env->sysenter_esp;          val = env->sysenter_esp;
         EDX = 0;  
2255          break;          break;
2256      case MSR_IA32_SYSENTER_EIP:      case MSR_IA32_SYSENTER_EIP:
2257          EAX = env->sysenter_eip;          val = env->sysenter_eip;
         EDX = 0;  
2258          break;          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;
2283            break;
2284        case MSR_KERNELGSBASE:
2285            val = env->kernelgsbase;
2286            break;
2287    #endif
2288      default:      default:
2289          /* XXX: exception ? */          /* XXX: exception ? */
2290            val = 0;
2291          break;          break;
2292      }      }
2293        EAX = (uint32_t)(val);
2294        EDX = (uint32_t)(val >> 32);
2295  }  }
2296    #endif
2297    
2298  void helper_lsl(void)  void helper_lsl(void)
2299  {  {
# Line 2055  void helper_fldt_ST0_A0(void) Line 2444  void helper_fldt_ST0_A0(void)
2444  {  {
2445      int new_fpstt;      int new_fpstt;
2446      new_fpstt = (env->fpstt - 1) & 7;      new_fpstt = (env->fpstt - 1) & 7;
2447      env->fpregs[new_fpstt] = helper_fldt((uint8_t *)A0);      env->fpregs[new_fpstt] = helper_fldt(A0);
2448      env->fpstt = new_fpstt;      env->fpstt = new_fpstt;
2449      env->fptags[new_fpstt] = 0; /* validate stack entry */      env->fptags[new_fpstt] = 0; /* validate stack entry */
2450  }  }
2451    
2452  void helper_fstt_ST0_A0(void)  void helper_fstt_ST0_A0(void)
2453  {  {
2454      helper_fstt(ST0, (uint8_t *)A0);      helper_fstt(ST0, A0);
2455  }  }
2456    
2457  void fpu_set_exception(int mask)  void fpu_set_exception(int mask)
# Line 2102  void helper_fbld_ST0_A0(void) Line 2491  void helper_fbld_ST0_A0(void)
2491    
2492      val = 0;      val = 0;
2493      for(i = 8; i >= 0; i--) {      for(i = 8; i >= 0; i--) {
2494          v = ldub((uint8_t *)A0 + i);          v = ldub(A0 + i);
2495          val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);          val = (val * 100) + ((v >> 4) * 10) + (v & 0xf);
2496      }      }
2497      tmp = val;      tmp = val;
2498      if (ldub((uint8_t *)A0 + 9) & 0x80)      if (ldub(A0 + 9) & 0x80)
2499          tmp = -tmp;          tmp = -tmp;
2500      fpush();      fpush();
2501      ST0 = tmp;      ST0 = tmp;
# Line 2116  void helper_fbst_ST0_A0(void) Line 2505  void helper_fbst_ST0_A0(void)
2505  {  {
2506      CPU86_LDouble tmp;      CPU86_LDouble tmp;
2507      int v;      int v;
2508      uint8_t *mem_ref, *mem_end;      target_ulong mem_ref, mem_end;
2509      int64_t val;      int64_t val;
2510    
2511      tmp = rint(ST0);      tmp = rint(ST0);
2512      val = (int64_t)tmp;      val = (int64_t)tmp;
2513      mem_ref = (uint8_t *)A0;      mem_ref = A0;
2514      mem_end = mem_ref + 9;      mem_end = mem_ref + 9;
2515      if (val < 0) {      if (val < 0) {
2516          stb(mem_end, 0x80);          stb(mem_end, 0x80);
# Line 2402  void helper_fxam_ST0(void) Line 2791  void helper_fxam_ST0(void)
2791      }      }
2792  }  }
2793    
2794  void helper_fstenv(uint8_t *ptr, int data32)  void helper_fstenv(target_ulong ptr, int data32)
2795  {  {
2796      int fpus, fptag, exp, i;      int fpus, fptag, exp, i;
2797      uint64_t mant;      uint64_t mant;
# Line 2452  void helper_fstenv(uint8_t *ptr, int dat Line 2841  void helper_fstenv(uint8_t *ptr, int dat
2841      }      }
2842  }  }
2843    
2844  void helper_fldenv(uint8_t *ptr, int data32)  void helper_fldenv(target_ulong ptr, int data32)
2845  {  {
2846      int i, fpus, fptag;      int i, fpus, fptag;
2847    
# Line 2474  void helper_fldenv(uint8_t *ptr, int dat Line 2863  void helper_fldenv(uint8_t *ptr, int dat
2863      }      }
2864  }  }
2865    
2866  void helper_fsave(uint8_t *ptr, int data32)  void helper_fsave(target_ulong ptr, int data32)
2867  {  {
2868      CPU86_LDouble tmp;      CPU86_LDouble tmp;
2869      int i;      int i;
# Line 2502  void helper_fsave(uint8_t *ptr, int data Line 2891  void helper_fsave(uint8_t *ptr, int data
2891      env->fptags[7] = 1;      env->fptags[7] = 1;
2892  }  }
2893    
2894  void helper_frstor(uint8_t *ptr, int data32)  void helper_frstor(target_ulong ptr, int data32)
2895  {  {
2896      CPU86_LDouble tmp;      CPU86_LDouble tmp;
2897      int i;      int i;
# Line 2517  void helper_frstor(uint8_t *ptr, int dat Line 2906  void helper_frstor(uint8_t *ptr, int dat
2906      }      }
2907  }  }
2908    
2909  /* XXX: merge with helper_fstt ? */  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    }
2981    
2982  #ifndef USE_X86LDOUBLE  #ifndef USE_X86LDOUBLE
2983    
# Line 2575  CPU86_LDouble cpu_set_fp80(uint64_t mant Line 3035  CPU86_LDouble cpu_set_fp80(uint64_t mant
3035  }  }
3036  #endif  #endif
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        }
3202        r0 = EAX;
3203        r1 = EDX;
3204        idiv64(&r0, &r1, T0);
3205        EAX = r0;
3206        EDX = r1;
3207    }
3208    
3209    #endif
3210    
3211  #if !defined(CONFIG_USER_ONLY)  #if !defined(CONFIG_USER_ONLY)
3212    
3213  #define MMUSUFFIX _mmu  #define MMUSUFFIX _mmu
# Line 2598  CPU86_LDouble cpu_set_fp80(uint64_t mant Line 3231  CPU86_LDouble cpu_set_fp80(uint64_t mant
3231     NULL, it means that the function was called in C code (i.e. not     NULL, it means that the function was called in C code (i.e. not
3232     from generated code or from helper.c) */     from generated code or from helper.c) */
3233  /* XXX: fix it to restore all registers */  /* XXX: fix it to restore all registers */
3234  void tlb_fill(unsigned long addr, int is_write, int is_user, void *retaddr)  void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
3235  {  {
3236      TranslationBlock *tb;      TranslationBlock *tb;
3237      int ret;      int ret;

Legend:
Removed from v.1.33  
changed lines
  Added in v.1.34

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26