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

Diff of /qemu/op-i386.c

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

revision 1.29 by bellard, Sun May 25 16:46:15 2003 UTC revision 1.30 by bellard, Tue May 27 23:27:26 2003 UTC
# Line 364  void OPPROTO op_divb_AL_T0(void) Line 364  void OPPROTO op_divb_AL_T0(void)
364    
365      num = (EAX & 0xffff);      num = (EAX & 0xffff);
366      den = (T0 & 0xff);      den = (T0 & 0xff);
367      if (den == 0)      if (den == 0) {
368            EIP = PARAM1;
369          raise_exception(EXCP00_DIVZ);          raise_exception(EXCP00_DIVZ);
370        }
371      q = (num / den) & 0xff;      q = (num / den) & 0xff;
372      r = (num % den) & 0xff;      r = (num % den) & 0xff;
373      EAX = (EAX & 0xffff0000) | (r << 8) | q;      EAX = (EAX & 0xffff0000) | (r << 8) | q;
# Line 377  void OPPROTO op_idivb_AL_T0(void) Line 379  void OPPROTO op_idivb_AL_T0(void)
379    
380      num = (int16_t)EAX;      num = (int16_t)EAX;
381      den = (int8_t)T0;      den = (int8_t)T0;
382      if (den == 0)      if (den == 0) {
383            EIP = PARAM1;
384          raise_exception(EXCP00_DIVZ);          raise_exception(EXCP00_DIVZ);
385        }
386      q = (num / den) & 0xff;      q = (num / den) & 0xff;
387      r = (num % den) & 0xff;      r = (num % den) & 0xff;
388      EAX = (EAX & 0xffff0000) | (r << 8) | q;      EAX = (EAX & 0xffff0000) | (r << 8) | q;
# Line 390  void OPPROTO op_divw_AX_T0(void) Line 394  void OPPROTO op_divw_AX_T0(void)
394    
395      num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);      num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
396      den = (T0 & 0xffff);      den = (T0 & 0xffff);
397      if (den == 0)      if (den == 0) {
398            EIP = PARAM1;
399          raise_exception(EXCP00_DIVZ);          raise_exception(EXCP00_DIVZ);
400        }
401      q = (num / den) & 0xffff;      q = (num / den) & 0xffff;
402      r = (num % den) & 0xffff;      r = (num % den) & 0xffff;
403      EAX = (EAX & 0xffff0000) | q;      EAX = (EAX & 0xffff0000) | q;
# Line 404  void OPPROTO op_idivw_AX_T0(void) Line 410  void OPPROTO op_idivw_AX_T0(void)
410    
411      num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);      num = (EAX & 0xffff) | ((EDX & 0xffff) << 16);
412      den = (int16_t)T0;      den = (int16_t)T0;
413      if (den == 0)      if (den == 0) {
414            EIP = PARAM1;
415          raise_exception(EXCP00_DIVZ);          raise_exception(EXCP00_DIVZ);
416        }
417      q = (num / den) & 0xffff;      q = (num / den) & 0xffff;
418      r = (num % den) & 0xffff;      r = (num % den) & 0xffff;
419      EAX = (EAX & 0xffff0000) | q;      EAX = (EAX & 0xffff0000) | q;
# Line 435  void OPPROTO op_divl_EAX_T0(void) Line 443  void OPPROTO op_divl_EAX_T0(void)
443            
444      num = EAX | ((uint64_t)EDX << 32);      num = EAX | ((uint64_t)EDX << 32);
445      den = T0;      den = T0;
446      if (den == 0)      if (den == 0) {
447            EIP = PARAM1;
448          raise_exception(EXCP00_DIVZ);          raise_exception(EXCP00_DIVZ);
449        }
450  #ifdef BUGGY_GCC_DIV64  #ifdef BUGGY_GCC_DIV64
451      r = div64(&q, num, den);      r = div64(&q, num, den);
452  #else  #else
# Line 454  void OPPROTO op_idivl_EAX_T0(void) Line 464  void OPPROTO op_idivl_EAX_T0(void)
464            
465      num = EAX | ((uint64_t)EDX << 32);      num = EAX | ((uint64_t)EDX << 32);
466      den = T0;      den = T0;
467      if (den == 0)      if (den == 0) {
468            EIP = PARAM1;
469          raise_exception(EXCP00_DIVZ);          raise_exception(EXCP00_DIVZ);
470        }
471  #ifdef BUGGY_GCC_DIV64  #ifdef BUGGY_GCC_DIV64
472      r = idiv64(&q, num, den);      r = idiv64(&q, num, den);
473  #else  #else
# Line 614  void OPPROTO op_jmp_im(void) Line 626  void OPPROTO op_jmp_im(void)
626      EIP = PARAM1;      EIP = PARAM1;
627  }  }
628    
629  void OPPROTO op_int_im(void)  #if 0
630    /* full interrupt support (only useful for real CPU emulation, not
631       finished) - I won't do it any time soon, finish it if you want ! */
632    void raise_interrupt(int intno, int is_int, int error_code,
633                         unsigned int next_eip)
634    {
635        SegmentDescriptorTable *dt;
636        uint8_t *ptr;
637        int type, dpl, cpl;
638        uint32_t e1, e2;
639        
640        dt = &env->idt;
641        if (intno * 8 + 7 > dt->limit)
642            raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
643        ptr = dt->base + intno * 8;
644        e1 = ldl(ptr);
645        e2 = ldl(ptr + 4);
646        /* check gate type */
647        type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;
648        switch(type) {
649        case 5: /* task gate */
650        case 6: /* 286 interrupt gate */
651        case 7: /* 286 trap gate */
652        case 14: /* 386 interrupt gate */
653        case 15: /* 386 trap gate */
654            break;
655        default:
656            raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
657            break;
658        }
659        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
660        cpl = env->segs[R_CS] & 3;
661        /* check privledge if software int */
662        if (is_int && dpl < cpl)
663            raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
664        /* check valid bit */
665        if (!(e2 & DESC_P_MASK))
666            raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
667    }
668    
669    #else
670    
671    /*
672     * is_int is TRUE if coming from the int instruction. next_eip is the
673     * EIP value AFTER the interrupt instruction. It is only relevant if
674     * is_int is TRUE.  
675     */
676    void raise_interrupt(int intno, int is_int, int error_code,
677                         unsigned int next_eip)
678    {
679        SegmentDescriptorTable *dt;
680        uint8_t *ptr;
681        int dpl, cpl;
682        uint32_t e2;
683    
684        dt = &env->idt;
685        ptr = dt->base + (intno * 8);
686        e2 = ldl(ptr + 4);
687        
688        dpl = (e2 >> DESC_DPL_SHIFT) & 3;
689        cpl = 3;
690        /* check privledge if software int */
691        if (is_int && dpl < cpl)
692            raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
693    
694        /* Since we emulate only user space, we cannot do more than
695           exiting the emulation with the suitable exception and error
696           code */
697        if (is_int)
698            EIP = next_eip;
699        env->exception_index = intno;
700        env->error_code = error_code;
701    
702        cpu_loop_exit();
703    }
704    
705    #endif
706    
707    /* shortcuts to generate exceptions */
708    void raise_exception_err(int exception_index, int error_code)
709    {
710        raise_interrupt(exception_index, 0, error_code, 0);
711    }
712    
713    void raise_exception(int exception_index)
714    {
715        raise_interrupt(exception_index, 0, 0, 0);
716    }
717    
718    void OPPROTO op_raise_interrupt(void)
719  {  {
720      int intno;      int intno;
721        unsigned int next_eip;
722      intno = PARAM1;      intno = PARAM1;
723      EIP = PARAM2;      next_eip = PARAM2;
724      raise_exception_err(EXCP0D_GPF, intno * 8 + 2);      raise_interrupt(intno, 1, 0, next_eip);
725  }  }
726    
727  void OPPROTO op_raise_exception(void)  void OPPROTO op_raise_exception(void)
# Line 634  void OPPROTO op_into(void) Line 736  void OPPROTO op_into(void)
736      int eflags;      int eflags;
737      eflags = cc_table[CC_OP].compute_all();      eflags = cc_table[CC_OP].compute_all();
738      if (eflags & CC_O) {      if (eflags & CC_O) {
739          EIP = PARAM1;          raise_interrupt(EXCP04_INTO, 1, 0, PARAM1);
         raise_exception(EXCP04_INTO);  
740      }      }
741      FORCE_RET();      FORCE_RET();
742  }  }
# Line 674  void OPPROTO op_boundw(void) Line 775  void OPPROTO op_boundw(void)
775      low = ldsw((uint8_t *)A0);      low = ldsw((uint8_t *)A0);
776      high = ldsw((uint8_t *)A0 + 2);      high = ldsw((uint8_t *)A0 + 2);
777      v = (int16_t)T0;      v = (int16_t)T0;
778      if (v < low || v > high)      if (v < low || v > high) {
779            EIP = PARAM1;
780          raise_exception(EXCP05_BOUND);          raise_exception(EXCP05_BOUND);
781        }
782      FORCE_RET();      FORCE_RET();
783  }  }
784    
# Line 685  void OPPROTO op_boundl(void) Line 788  void OPPROTO op_boundl(void)
788      low = ldl((uint8_t *)A0);      low = ldl((uint8_t *)A0);
789      high = ldl((uint8_t *)A0 + 4);      high = ldl((uint8_t *)A0 + 4);
790      v = T0;      v = T0;
791      if (v < low || v > high)      if (v < low || v > high) {
792            EIP = PARAM1;
793          raise_exception(EXCP05_BOUND);          raise_exception(EXCP05_BOUND);
794        }
795      FORCE_RET();      FORCE_RET();
796  }  }
797    
# Line 1116  void OPPROTO op_das(void) Line 1221  void OPPROTO op_das(void)
1221    
1222  /* segment handling */  /* segment handling */
1223    
1224  /* XXX: use static VM86 information */  /* only works if protected mode and not VM86 */
1225  void load_seg(int seg_reg, int selector)  void load_seg(int seg_reg, int selector, unsigned cur_eip)
1226  {  {
1227      SegmentCache *sc;      SegmentCache *sc;
1228      SegmentDescriptorTable *dt;      SegmentDescriptorTable *dt;
# Line 1126  void load_seg(int seg_reg, int selector) Line 1231  void load_seg(int seg_reg, int selector)
1231      uint8_t *ptr;      uint8_t *ptr;
1232    
1233      sc = &env->seg_cache[seg_reg];      sc = &env->seg_cache[seg_reg];
1234      if (env->eflags & VM_MASK) {      if ((selector & 0xfffc) == 0) {
1235          sc->base = (void *)(selector << 4);          /* null selector case */
1236          sc->limit = 0xffff;          if (seg_reg == R_SS) {
1237          sc->seg_32bit = 0;              EIP = cur_eip;
1238                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1239            } else {
1240                /* XXX: each access should trigger an exception */
1241                sc->base = NULL;
1242                sc->limit = 0;
1243                sc->seg_32bit = 1;
1244            }
1245      } else {      } else {
1246          if (selector & 0x4)          if (selector & 0x4)
1247              dt = &env->ldt;              dt = &env->ldt;
1248          else          else
1249              dt = &env->gdt;              dt = &env->gdt;
1250          index = selector & ~7;          index = selector & ~7;
1251          if ((index + 7) > dt->limit)          if ((index + 7) > dt->limit) {
1252              raise_exception_err(EXCP0D_GPF, selector);              EIP = cur_eip;
1253                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1254            }
1255          ptr = dt->base + index;          ptr = dt->base + index;
1256          e1 = ldl(ptr);          e1 = ldl(ptr);
1257          e2 = ldl(ptr + 4);          e2 = ldl(ptr + 4);
1258            if (!(e2 & DESC_S_MASK) ||
1259                (e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) {
1260                EIP = cur_eip;
1261                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1262            }
1263    
1264            if (seg_reg == R_SS) {
1265                if ((e2 & (DESC_CS_MASK | DESC_W_MASK)) == 0) {
1266                    EIP = cur_eip;
1267                    raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1268                }
1269            } else {
1270                if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) {
1271                    EIP = cur_eip;
1272                    raise_exception_err(EXCP0D_GPF, selector & 0xfffc);
1273                }
1274            }
1275    
1276            if (!(e2 & DESC_P_MASK)) {
1277                EIP = cur_eip;
1278                if (seg_reg == R_SS)
1279                    raise_exception_err(EXCP0C_STACK, selector & 0xfffc);
1280                else
1281                    raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);
1282            }
1283            
1284          sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));          sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));
1285          sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);          sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);
1286          if (e2 & (1 << 23))          if (e2 & (1 << 23))
# Line 1156  void load_seg(int seg_reg, int selector) Line 1296  void load_seg(int seg_reg, int selector)
1296    
1297  void OPPROTO op_movl_seg_T0(void)  void OPPROTO op_movl_seg_T0(void)
1298  {  {
1299      load_seg(PARAM1, T0 & 0xffff);      load_seg(PARAM1, T0 & 0xffff, PARAM2);
1300    }
1301    
1302    /* faster VM86 version */
1303    void OPPROTO op_movl_seg_T0_vm(void)
1304    {
1305        int selector;
1306        
1307        selector = T0 & 0xffff;
1308        /* env->segs[] access */
1309        *(uint32_t *)((char *)env + PARAM1) = selector;
1310        /* env->seg_cache[] access */
1311        ((SegmentCache *)((char *)env + PARAM2))->base = (void *)(selector << 4);
1312  }  }
1313    
1314  void OPPROTO op_movl_T0_seg(void)  void OPPROTO op_movl_T0_seg(void)

Legend:
Removed from v.1.29  
changed lines
  Added in v.1.30

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