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

Diff of /qemu/helper-i386.c

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

revision 1.4 by bellard, Sat Jun 21 13:10:39 2003 UTC revision 1.5 by bellard, Tue Jun 24 13:27:18 2003 UTC
# Line 126  void cpu_loop_exit(void) Line 126  void cpu_loop_exit(void)
126      longjmp(env->jmp_env, 1);      longjmp(env->jmp_env, 1);
127  }  }
128    
129    static inline void get_ss_esp_from_tss(uint32_t *ss_ptr,
130                                           uint32_t *esp_ptr, int dpl)
131    {
132        int type, index, shift;
133        
134  #if 0  #if 0
135  /* full interrupt support (only useful for real CPU emulation, not      {
136     finished) - I won't do it any time soon, finish it if you want ! */          int i;
137  void raise_interrupt(int intno, int is_int, int error_code,          printf("TR: base=%p limit=%x\n", env->tr.base, env->tr.limit);
138                       unsigned int next_eip)          for(i=0;i<env->tr.limit;i++) {
139                printf("%02x ", env->tr.base[i]);
140                if ((i & 7) == 7) printf("\n");
141            }
142            printf("\n");
143        }
144    #endif
145    
146        if (!(env->tr.flags & DESC_P_MASK))
147            cpu_abort(env, "invalid tss");
148        type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
149        if ((type & 7) != 1)
150            cpu_abort(env, "invalid tss type");
151        shift = type >> 3;
152        index = (dpl * 4 + 2) << shift;
153        if (index + (4 << shift) - 1 > env->tr.limit)
154            raise_exception_err(EXCP0A_TSS, env->tr.selector & 0xfffc);
155        if (shift == 0) {
156            *esp_ptr = lduw(env->tr.base + index);
157            *ss_ptr = lduw(env->tr.base + index + 2);
158        } else {
159            *esp_ptr = ldl(env->tr.base + index);
160            *ss_ptr = lduw(env->tr.base + index + 4);
161        }
162    }
163    
164    /* return non zero if error */
165    static inline int load_segment(uint32_t *e1_ptr, uint32_t *e2_ptr,
166                                   int selector)
167  {  {
168      SegmentDescriptorTable *dt;      SegmentCache *dt;
169        int index;
170      uint8_t *ptr;      uint8_t *ptr;
171      int type, dpl, cpl;  
172      uint32_t e1, e2;      if (selector & 0x4)
173                dt = &env->ldt;
174        else
175            dt = &env->gdt;
176        index = selector & ~7;
177        if ((index + 7) > dt->limit)
178            return -1;
179        ptr = dt->base + index;
180        *e1_ptr = ldl(ptr);
181        *e2_ptr = ldl(ptr + 4);
182        return 0;
183    }
184                                        
185    
186    /* protected mode interrupt */
187    static void do_interrupt_protected(int intno, int is_int, int error_code,
188                                          unsigned int next_eip)
189    {
190        SegmentCache *dt;
191        uint8_t *ptr, *ssp;
192        int type, dpl, cpl, selector, ss_dpl;
193        int has_error_code, new_stack, shift;
194        uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2, push_size;
195        uint32_t old_cs, old_ss, old_esp, old_eip;
196    
197      dt = &env->idt;      dt = &env->idt;
198      if (intno * 8 + 7 > dt->limit)      if (intno * 8 + 7 > dt->limit)
199          raise_exception_err(EXCP0D_GPF, intno * 8 + 2);          raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
# Line 147  void raise_interrupt(int intno, int is_i Line 204  void raise_interrupt(int intno, int is_i
204      type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;      type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
205      switch(type) {      switch(type) {
206      case 5: /* task gate */      case 5: /* task gate */
207            cpu_abort(env, "task gate not supported");
208            break;
209      case 6: /* 286 interrupt gate */      case 6: /* 286 interrupt gate */
210      case 7: /* 286 trap gate */      case 7: /* 286 trap gate */
211      case 14: /* 386 interrupt gate */      case 14: /* 386 interrupt gate */
# Line 164  void raise_interrupt(int intno, int is_i Line 223  void raise_interrupt(int intno, int is_i
223      /* check valid bit */      /* check valid bit */
224      if (!(e2 & DESC_P_MASK))      if (!(e2 & DESC_P_MASK))
225          raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);          raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
226        selector = e1 >> 16;
227        offset = (e2 & 0xffff0000) | (e1 & 0x0000ffff);
228        if ((selector & 0xfffc) == 0)
229            raise_exception_err(EXCP0D_GPF, 0);
230    
231        if (load_segment(&e1, &e2, selector) != 0)
232            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
233        if (!(e2 & DESC_S_MASK) || !(e2 & (DESC_CS_MASK)))
234            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
235        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
236        if (dpl > cpl)
237            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
238        if (!(e2 & DESC_P_MASK))
239            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
240        if (!(e2 & DESC_C_MASK) && dpl < cpl) {
241            /* to inner priviledge */
242            get_ss_esp_from_tss(&ss, &esp, dpl);
243            if ((ss & 0xfffc) == 0)
244                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
245            if ((ss & 3) != dpl)
246                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
247            if (load_segment(&ss_e1, &ss_e2, ss) != 0)
248                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
249            ss_dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;
250            if (ss_dpl != dpl)
251                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
252            if (!(ss_e2 & DESC_S_MASK) ||
253                (ss_e2 & DESC_CS_MASK) ||
254                !(ss_e2 & DESC_W_MASK))
255                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
256            if (!(ss_e2 & DESC_P_MASK))
257                raise_exception_err(EXCP0A_TSS, ss & 0xfffc);
258            new_stack = 1;
259        } else if ((e2 & DESC_C_MASK) || dpl == cpl) {
260            /* to same priviledge */
261            new_stack = 0;
262        } else {
263            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
264            new_stack = 0; /* avoid warning */
265        }
266    
267        shift = type >> 3;
268        has_error_code = 0;
269        if (!is_int) {
270            switch(intno) {
271            case 8:
272            case 10:
273            case 11:
274            case 12:
275            case 13:
276            case 14:
277            case 17:
278                has_error_code = 1;
279                break;
280            }
281        }
282        push_size = 6 + (new_stack << 2) + (has_error_code << 1);
283        if (env->eflags & VM_MASK)
284            push_size += 8;
285        push_size <<= shift;
286    
287        /* XXX: check that enough room is available */
288        if (new_stack) {
289            old_esp = env->regs[R_ESP];
290            old_ss = env->segs[R_SS].selector;
291            load_seg(R_SS, ss, env->eip);
292        } else {
293            old_esp = 0;
294            old_ss = 0;
295            esp = env->regs[R_ESP];
296        }
297        if (is_int)
298            old_eip = next_eip;
299        else
300            old_eip = env->eip;
301        old_cs = env->segs[R_CS].selector;
302        load_seg(R_CS, selector, env->eip);
303        env->eip = offset;
304        env->regs[R_ESP] = esp - push_size;
305        ssp = env->segs[R_SS].base + esp;
306        if (shift == 1) {
307            int old_eflags;
308            if (env->eflags & VM_MASK) {
309                ssp -= 4;
310                stl(ssp, env->segs[R_GS].selector);
311                ssp -= 4;
312                stl(ssp, env->segs[R_FS].selector);
313                ssp -= 4;
314                stl(ssp, env->segs[R_DS].selector);
315                ssp -= 4;
316                stl(ssp, env->segs[R_ES].selector);
317            }
318            if (new_stack) {
319                ssp -= 4;
320                stl(ssp, old_ss);
321                ssp -= 4;
322                stl(ssp, old_esp);
323            }
324            ssp -= 4;
325            old_eflags = compute_eflags();
326            stl(ssp, old_eflags);
327            ssp -= 4;
328            stl(ssp, old_cs);
329            ssp -= 4;
330            stl(ssp, old_eip);
331            if (has_error_code) {
332                ssp -= 4;
333                stl(ssp, error_code);
334            }
335        } else {
336            if (new_stack) {
337                ssp -= 2;
338                stw(ssp, old_ss);
339                ssp -= 2;
340                stw(ssp, old_esp);
341            }
342            ssp -= 2;
343            stw(ssp, compute_eflags());
344            ssp -= 2;
345            stw(ssp, old_cs);
346            ssp -= 2;
347            stw(ssp, old_eip);
348            if (has_error_code) {
349                ssp -= 2;
350                stw(ssp, error_code);
351            }
352        }
353        
354        /* interrupt gate clear IF mask */
355        if ((type & 1) == 0) {
356            env->eflags &= ~IF_MASK;
357        }
358        env->eflags &= ~(TF_MASK | VM_MASK | RF_MASK | NT_MASK);
359  }  }
360    
361  #else  /* real mode interrupt */
362    static void do_interrupt_real(int intno, int is_int, int error_code,
363                                     unsigned int next_eip)
364    {
365        SegmentCache *dt;
366        uint8_t *ptr, *ssp;
367        int selector;
368        uint32_t offset, esp;
369        uint32_t old_cs, old_eip;
370    
371  /*      /* real mode (simpler !) */
372   * is_int is TRUE if coming from the int instruction. next_eip is the      dt = &env->idt;
373   * EIP value AFTER the interrupt instruction. It is only relevant if      if (intno * 4 + 3 > dt->limit)
374   * is_int is TRUE.            raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
375   */      ptr = dt->base + intno * 4;
376  void raise_interrupt(int intno, int is_int, int error_code,      offset = lduw(ptr);
377                       unsigned int next_eip)      selector = lduw(ptr + 2);
378        esp = env->regs[R_ESP] & 0xffff;
379        ssp = env->segs[R_SS].base + esp;
380        if (is_int)
381            old_eip = next_eip;
382        else
383            old_eip = env->eip;
384        old_cs = env->segs[R_CS].selector;
385        ssp -= 2;
386        stw(ssp, compute_eflags());
387        ssp -= 2;
388        stw(ssp, old_cs);
389        ssp -= 2;
390        stw(ssp, old_eip);
391        esp -= 6;
392        
393        /* update processor state */
394        env->regs[R_ESP] = (env->regs[R_ESP] & ~0xffff) | (esp & 0xffff);
395        env->eip = offset;
396        env->segs[R_CS].selector = selector;
397        env->segs[R_CS].base = (uint8_t *)(selector << 4);
398        env->eflags &= ~(IF_MASK | TF_MASK | AC_MASK | RF_MASK);
399    }
400    
401    /* fake user mode interrupt */
402    void do_interrupt_user(int intno, int is_int, int error_code,
403                           unsigned int next_eip)
404  {  {
405      SegmentCache *dt;      SegmentCache *dt;
406      uint8_t *ptr;      uint8_t *ptr;
# Line 196  void raise_interrupt(int intno, int is_i Line 422  void raise_interrupt(int intno, int is_i
422         code */         code */
423      if (is_int)      if (is_int)
424          EIP = next_eip;          EIP = next_eip;
425    }
426    
427    /*
428     * Begin excution of an interruption. is_int is TRUE if coming from
429     * the int instruction. next_eip is the EIP value AFTER the interrupt
430     * instruction. It is only relevant if is_int is TRUE.  
431     */
432    void do_interrupt(int intno, int is_int, int error_code,
433                      unsigned int next_eip)
434    {
435        if (env->cr[0] & CR0_PE_MASK) {
436            do_interrupt_protected(intno, is_int, error_code, next_eip);
437        } else {
438            do_interrupt_real(intno, is_int, error_code, next_eip);
439        }
440    }
441    
442    /*
443     * Signal an interruption. It is executed in the main CPU loop.
444     * is_int is TRUE if coming from the int instruction. next_eip is the
445     * EIP value AFTER the interrupt instruction. It is only relevant if
446     * is_int is TRUE.  
447     */
448    void raise_interrupt(int intno, int is_int, int error_code,
449                         unsigned int next_eip)
450    {
451      env->exception_index = intno;      env->exception_index = intno;
452      env->error_code = error_code;      env->error_code = error_code;
453        env->exception_is_int = is_int;
454        env->exception_next_eip = next_eip;
455      cpu_loop_exit();      cpu_loop_exit();
456  }  }
457    
 #endif  
   
458  /* shortcuts to generate exceptions */  /* shortcuts to generate exceptions */
459  void raise_exception_err(int exception_index, int error_code)  void raise_exception_err(int exception_index, int error_code)
460  {  {
# Line 335  static inline void load_seg_cache(Segmen Line 586  static inline void load_seg_cache(Segmen
586  {  {
587      sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));      sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
588      sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);      sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);
589      if (e2 & (1 << 23))      if (e2 & DESC_G_MASK)
590          sc->limit = (sc->limit << 12) | 0xfff;          sc->limit = (sc->limit << 12) | 0xfff;
591      sc->seg_32bit = (e2 >> 22) & 1;      sc->flags = e2;
592  }  }
593    
594  void helper_lldt_T0(void)  void helper_lldt_T0(void)
# Line 382  void helper_ltr_T0(void) Line 633  void helper_ltr_T0(void)
633            
634      selector = T0 & 0xffff;      selector = T0 & 0xffff;
635      if ((selector & 0xfffc) == 0) {      if ((selector & 0xfffc) == 0) {
636          /* XXX: NULL selector case: invalid LDT */          /* NULL selector case: invalid LDT */
637          env->tr.base = NULL;          env->tr.base = NULL;
638          env->tr.limit = 0;          env->tr.limit = 0;
639            env->tr.flags = 0;
640      } else {      } else {
641          if (selector & 0x4)          if (selector & 0x4)
642              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
# Line 412  void helper_ltr_T0(void) Line 664  void helper_ltr_T0(void)
664  void load_seg(int seg_reg, int selector, unsigned int cur_eip)  void load_seg(int seg_reg, int selector, unsigned int cur_eip)
665  {  {
666      SegmentCache *sc;      SegmentCache *sc;
     SegmentCache *dt;  
     int index;  
667      uint32_t e1, e2;      uint32_t e1, e2;
     uint8_t *ptr;  
668            
669      sc = &env->segs[seg_reg];      sc = &env->segs[seg_reg];
670      if ((selector & 0xfffc) == 0) {      if ((selector & 0xfffc) == 0) {
# Line 427  void load_seg(int seg_reg, int selector, Line 676  void load_seg(int seg_reg, int selector,
676              /* XXX: each access should trigger an exception */              /* XXX: each access should trigger an exception */
677              sc->base = NULL;              sc->base = NULL;
678              sc->limit = 0;              sc->limit = 0;
679              sc->seg_32bit = 1;              sc->flags = 0;
680          }          }
681      } else {      } else {
682          if (selector & 0x4)          if (load_segment(&e1, &e2, selector) != 0) {
             dt = &env->ldt;  
         else  
             dt = &env->gdt;  
         index = selector & ~7;  
         if ((index + 7) > dt->limit) {  
683              EIP = cur_eip;              EIP = cur_eip;
684              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);              raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
685          }          }
         ptr = dt->base + index;  
         e1 = ldl(ptr);  
         e2 = ldl(ptr + 4);  
686          if (!(e2 & DESC_S_MASK) ||          if (!(e2 & DESC_S_MASK) ||
687              (e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) {              (e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) {
688              EIP = cur_eip;              EIP = cur_eip;
# Line 469  void load_seg(int seg_reg, int selector, Line 710  void load_seg(int seg_reg, int selector,
710          }          }
711          load_seg_cache(sc, e1, e2);          load_seg_cache(sc, e1, e2);
712  #if 0  #if 0
713          fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n",          fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx flags=%08x\n",
714                  selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit);                  selector, (unsigned long)sc->base, sc->limit, sc->flags);
715  #endif  #endif
716      }      }
717      sc->selector = selector;      sc->selector = selector;
# Line 480  void load_seg(int seg_reg, int selector, Line 721  void load_seg(int seg_reg, int selector,
721  void jmp_seg(int selector, unsigned int new_eip)  void jmp_seg(int selector, unsigned int new_eip)
722  {  {
723      SegmentCache sc1;      SegmentCache sc1;
     SegmentCache *dt;  
     int index;  
724      uint32_t e1, e2, cpl, dpl, rpl;      uint32_t e1, e2, cpl, dpl, rpl;
     uint8_t *ptr;  
725    
726      if ((selector & 0xfffc) == 0) {      if ((selector & 0xfffc) == 0) {
727          raise_exception_err(EXCP0D_GPF, 0);          raise_exception_err(EXCP0D_GPF, 0);
728      }      }
729    
730      if (selector & 0x4)      if (load_segment(&e1, &e2, selector) != 0)
       dt = &env->ldt;  
     else  
       dt = &env->gdt;  
     index = selector & ~7;  
     if ((index + 7) > dt->limit)  
731          raise_exception_err(EXCP0D_GPF, selector & 0xfffc);          raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
     ptr = dt->base + index;  
     e1 = ldl(ptr);  
     e2 = ldl(ptr + 4);  
732      cpl = env->segs[R_CS].selector & 3;      cpl = env->segs[R_CS].selector & 3;
733      if (e2 & DESC_S_MASK) {      if (e2 & DESC_S_MASK) {
734          if (!(e2 & DESC_CS_MASK))          if (!(e2 & DESC_CS_MASK))
# Line 530  void jmp_seg(int selector, unsigned int Line 760  void jmp_seg(int selector, unsigned int
760      }      }
761  }  }
762    
763  /* XXX: do more */  /* init the segment cache in vm86 mode */
764    static inline void load_seg_vm(int seg, int selector)
765    {
766        SegmentCache *sc = &env->segs[seg];
767        selector &= 0xffff;
768        sc->base = (uint8_t *)(selector << 4);
769        sc->selector = selector;
770        sc->flags = 0;
771        sc->limit = 0xffff;
772    }
773    
774    /* protected mode iret */
775    void helper_iret_protected(int shift)
776    {
777        uint32_t sp, new_cs, new_eip, new_eflags, new_esp, new_ss;
778        uint32_t new_es, new_ds, new_fs, new_gs;
779        uint32_t e1, e2;
780        int cpl, dpl, rpl, eflags_mask;
781        uint8_t *ssp;
782        
783        sp = env->regs[R_ESP];
784        if (!(env->segs[R_SS].flags & DESC_B_MASK))
785            sp &= 0xffff;
786        ssp = env->segs[R_SS].base + sp;
787        if (shift == 1) {
788            /* 32 bits */
789            new_eflags = ldl(ssp + 8);
790            new_cs = ldl(ssp + 4) & 0xffff;
791            new_eip = ldl(ssp);
792            if (new_eflags & VM_MASK)
793                goto return_to_vm86;
794        } else {
795            /* 16 bits */
796            new_eflags = lduw(ssp + 4);
797            new_cs = lduw(ssp + 2);
798            new_eip = lduw(ssp);
799        }
800        if ((new_cs & 0xfffc) == 0)
801            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
802        if (load_segment(&e1, &e2, new_cs) != 0)
803            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
804        if (!(e2 & DESC_S_MASK) ||
805            !(e2 & DESC_CS_MASK))
806            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
807        cpl = env->segs[R_CS].selector & 3;
808        rpl = new_cs & 3;
809        if (rpl < cpl)
810            raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
811        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
812        if (e2 & DESC_CS_MASK) {
813            if (dpl > rpl)
814                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
815        } else {
816            if (dpl != rpl)
817                raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
818        }
819        if (!(e2 & DESC_P_MASK))
820            raise_exception_err(EXCP0B_NOSEG, new_cs & 0xfffc);
821        
822        if (rpl == cpl) {
823            /* return to same priledge level */
824            load_seg(R_CS, new_cs, env->eip);
825            new_esp = sp + (6 << shift);
826        } else {
827            /* return to differentr priviledge level */
828            if (shift == 1) {
829                /* 32 bits */
830                new_esp = ldl(ssp + 12);
831                new_ss = ldl(ssp + 16) & 0xffff;
832            } else {
833                /* 16 bits */
834                new_esp = lduw(ssp + 6);
835                new_ss = lduw(ssp + 8);
836            }
837            
838            if ((new_ss & 3) != rpl)
839                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
840            if (load_segment(&e1, &e2, new_ss) != 0)
841                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
842            if (!(e2 & DESC_S_MASK) ||
843                (e2 & DESC_CS_MASK) ||
844                !(e2 & DESC_W_MASK))
845                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
846            dpl = (e2 >> DESC_DPL_SHIFT) & 3;
847            if (dpl != rpl)
848                raise_exception_err(EXCP0D_GPF, new_ss & 0xfffc);
849            if (!(e2 & DESC_P_MASK))
850                raise_exception_err(EXCP0B_NOSEG, new_ss & 0xfffc);
851    
852            load_seg(R_CS, new_cs, env->eip);
853            load_seg(R_SS, new_ss, env->eip);
854        }
855        if (env->segs[R_SS].flags & DESC_B_MASK)
856            env->regs[R_ESP] = new_esp;
857        else
858            env->regs[R_ESP] = (env->regs[R_ESP] & 0xffff0000) |
859                (new_esp & 0xffff);
860        env->eip = new_eip;
861        if (cpl == 0)
862            eflags_mask = FL_UPDATE_CPL0_MASK;
863        else
864            eflags_mask = FL_UPDATE_MASK32;
865        if (shift == 0)
866            eflags_mask &= 0xffff;
867        load_eflags(new_eflags, eflags_mask);
868        return;
869    
870     return_to_vm86:
871        new_esp = ldl(ssp + 12);
872        new_ss = ldl(ssp + 16);
873        new_es = ldl(ssp + 20);
874        new_ds = ldl(ssp + 24);
875        new_fs = ldl(ssp + 28);
876        new_gs = ldl(ssp + 32);
877        
878        /* modify processor state */
879        load_eflags(new_eflags, FL_UPDATE_CPL0_MASK | VM_MASK | VIF_MASK | VIP_MASK);
880        load_seg_vm(R_CS, new_cs);
881        load_seg_vm(R_SS, new_ss);
882        load_seg_vm(R_ES, new_es);
883        load_seg_vm(R_DS, new_ds);
884        load_seg_vm(R_FS, new_fs);
885        load_seg_vm(R_GS, new_gs);
886        
887        env->eip = new_eip;
888        env->regs[R_ESP] = new_esp;
889    }
890    
891  void helper_movl_crN_T0(int reg)  void helper_movl_crN_T0(int reg)
892  {  {
893        env->cr[reg] = T0;
894      switch(reg) {      switch(reg) {
895      case 0:      case 0:
896      default:          cpu_x86_update_cr0(env);
         env->cr[0] = reg;  
         break;  
     case 2:  
         env->cr[2] = reg;  
897          break;          break;
898      case 3:      case 3:
899          env->cr[3] = reg;          cpu_x86_update_cr3(env);
         break;  
     case 4:  
         env->cr[4] = reg;  
900          break;          break;
901      }      }
902  }  }
# Line 556  void helper_movl_drN_T0(int reg) Line 907  void helper_movl_drN_T0(int reg)
907      env->dr[reg] = T0;      env->dr[reg] = T0;
908  }  }
909    
910    void helper_invlpg(unsigned int addr)
911    {
912        cpu_x86_flush_tlb(env, addr);
913    }
914    
915  /* rdtsc */  /* rdtsc */
916  #ifndef __i386__  #ifndef __i386__
917  uint64_t emu_time;  uint64_t emu_time;
# Line 577  void helper_rdtsc(void) Line 933  void helper_rdtsc(void)
933  void helper_lsl(void)  void helper_lsl(void)
934  {  {
935      unsigned int selector, limit;      unsigned int selector, limit;
     SegmentCache *dt;  
     int index;  
936      uint32_t e1, e2;      uint32_t e1, e2;
     uint8_t *ptr;  
937    
938      CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;      CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
939      selector = T0 & 0xffff;      selector = T0 & 0xffff;
940      if (selector & 0x4)      if (load_segment(&e1, &e2, selector) != 0)
         dt = &env->ldt;  
     else  
         dt = &env->gdt;  
     index = selector & ~7;  
     if ((index + 7) > dt->limit)  
941          return;          return;
     ptr = dt->base + index;  
     e1 = ldl(ptr);  
     e2 = ldl(ptr + 4);  
942      limit = (e1 & 0xffff) | (e2 & 0x000f0000);      limit = (e1 & 0xffff) | (e2 & 0x000f0000);
943      if (e2 & (1 << 23))      if (e2 & (1 << 23))
944          limit = (limit << 12) | 0xfff;          limit = (limit << 12) | 0xfff;
# Line 604  void helper_lsl(void) Line 949  void helper_lsl(void)
949  void helper_lar(void)  void helper_lar(void)
950  {  {
951      unsigned int selector;      unsigned int selector;
952      SegmentCache *dt;      uint32_t e1, e2;
     int index;  
     uint32_t e2;  
     uint8_t *ptr;  
953    
954      CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;      CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
955      selector = T0 & 0xffff;      selector = T0 & 0xffff;
956      if (selector & 0x4)      if (load_segment(&e1, &e2, selector) != 0)
         dt = &env->ldt;  
     else  
         dt = &env->gdt;  
     index = selector & ~7;  
     if ((index + 7) > dt->limit)  
957          return;          return;
     ptr = dt->base + index;  
     e2 = ldl(ptr + 4);  
958      T1 = e2 & 0x00f0ff00;      T1 = e2 & 0x00f0ff00;
959      CC_SRC |= CC_Z;      CC_SRC |= CC_Z;
960  }  }

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.5

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