/[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.32 by bellard, Mon Jun 2 20:38:09 2003 UTC revision 1.33 by bellard, Thu Jun 5 00:53:17 2003 UTC
# Line 626  void OPPROTO op_jmp_im(void) Line 626  void OPPROTO op_jmp_im(void)
626      EIP = PARAM1;      EIP = PARAM1;
627  }  }
628    
 #if 0  
 /* full interrupt support (only useful for real CPU emulation, not  
    finished) - I won't do it any time soon, finish it if you want ! */  
 void raise_interrupt(int intno, int is_int, int error_code,  
                      unsigned int next_eip)  
 {  
     SegmentDescriptorTable *dt;  
     uint8_t *ptr;  
     int type, dpl, cpl;  
     uint32_t e1, e2;  
       
     dt = &env->idt;  
     if (intno * 8 + 7 > dt->limit)  
         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);  
     ptr = dt->base + intno * 8;  
     e1 = ldl(ptr);  
     e2 = ldl(ptr + 4);  
     /* check gate type */  
     type = (e2 >> DESC_TYPE_SHIFT) & 0x1f;  
     switch(type) {  
     case 5: /* task gate */  
     case 6: /* 286 interrupt gate */  
     case 7: /* 286 trap gate */  
     case 14: /* 386 interrupt gate */  
     case 15: /* 386 trap gate */  
         break;  
     default:  
         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);  
         break;  
     }  
     dpl = (e2 >> DESC_DPL_SHIFT) & 3;  
     cpl = env->segs[R_CS] & 3;  
     /* check privledge if software int */  
     if (is_int && dpl < cpl)  
         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);  
     /* check valid bit */  
     if (!(e2 & DESC_P_MASK))  
         raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);  
 }  
   
 #else  
   
 /*  
  * is_int is TRUE if coming from the int instruction. next_eip is the  
  * EIP value AFTER the interrupt instruction. It is only relevant if  
  * is_int is TRUE.    
  */  
 void raise_interrupt(int intno, int is_int, int error_code,  
                      unsigned int next_eip)  
 {  
     SegmentDescriptorTable *dt;  
     uint8_t *ptr;  
     int dpl, cpl;  
     uint32_t e2;  
   
     dt = &env->idt;  
     ptr = dt->base + (intno * 8);  
     e2 = ldl(ptr + 4);  
       
     dpl = (e2 >> DESC_DPL_SHIFT) & 3;  
     cpl = 3;  
     /* check privledge if software int */  
     if (is_int && dpl < cpl)  
         raise_exception_err(EXCP0D_GPF, intno * 8 + 2);  
   
     /* Since we emulate only user space, we cannot do more than  
        exiting the emulation with the suitable exception and error  
        code */  
     if (is_int)  
         EIP = next_eip;  
     env->exception_index = intno;  
     env->error_code = error_code;  
   
     cpu_loop_exit();  
 }  
   
 #endif  
   
 /* shortcuts to generate exceptions */  
 void raise_exception_err(int exception_index, int error_code)  
 {  
     raise_interrupt(exception_index, 0, error_code, 0);  
 }  
   
 void raise_exception(int exception_index)  
 {  
     raise_interrupt(exception_index, 0, 0, 0);  
 }  
   
629  void OPPROTO op_raise_interrupt(void)  void OPPROTO op_raise_interrupt(void)
630  {  {
631      int intno;      int intno;
# Line 833  label ## n:\ Line 744  label ## n:\
744  #define JUMP_TB(tbparam, n, eip)\  #define JUMP_TB(tbparam, n, eip)\
745  do {\  do {\
746      static void __attribute__((unused)) *__op_label ## n = &&label ## n;\      static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
747      goto *((TranslationBlock *)tbparam)->tb_next[n];\      goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
748  label ## n:\  label ## n:\
749      T0 = (long)(tbparam) + (n);\      T0 = (long)(tbparam) + (n);\
750      EIP = eip;\      EIP = eip;\
# Line 1044  void OPPROTO op_rdtsc(void) Line 955  void OPPROTO op_rdtsc(void)
955      EDX = val >> 32;      EDX = val >> 32;
956  }  }
957    
 /* We simulate a pre-MMX pentium as in valgrind */  
 #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)  
   
 void helper_cpuid(void)  
 {  
     if (EAX == 0) {  
         EAX = 1; /* max EAX index supported */  
         EBX = 0x756e6547;  
         ECX = 0x6c65746e;  
         EDX = 0x49656e69;  
     } else if (EAX == 1) {  
         /* EAX = 1 info */  
         EAX = 0x52b;  
         EBX = 0;  
         ECX = 0;  
         EDX = CPUID_FP87 | CPUID_DE | CPUID_PSE |  
             CPUID_TSC | CPUID_MSR | CPUID_MCE |  
             CPUID_CX8;  
     }  
 }  
   
958  void OPPROTO op_cpuid(void)  void OPPROTO op_cpuid(void)
959  {  {
960      helper_cpuid();      helper_cpuid();
# Line 1221  void OPPROTO op_das(void) Line 1092  void OPPROTO op_das(void)
1092    
1093  /* segment handling */  /* segment handling */
1094    
 /* only works if protected mode and not VM86 */  
 void load_seg(int seg_reg, int selector, unsigned cur_eip)  
 {  
     SegmentCache *sc;  
     SegmentDescriptorTable *dt;  
     int index;  
     uint32_t e1, e2;  
     uint8_t *ptr;  
   
     sc = &env->seg_cache[seg_reg];  
     if ((selector & 0xfffc) == 0) {  
         /* null selector case */  
         if (seg_reg == R_SS) {  
             EIP = cur_eip;  
             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);  
         } else {  
             /* XXX: each access should trigger an exception */  
             sc->base = NULL;  
             sc->limit = 0;  
             sc->seg_32bit = 1;  
         }  
     } else {  
         if (selector & 0x4)  
             dt = &env->ldt;  
         else  
             dt = &env->gdt;  
         index = selector & ~7;  
         if ((index + 7) > dt->limit) {  
             EIP = cur_eip;  
             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);  
         }  
         ptr = dt->base + index;  
         e1 = ldl(ptr);  
         e2 = ldl(ptr + 4);  
         if (!(e2 & DESC_S_MASK) ||  
             (e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) {  
             EIP = cur_eip;  
             raise_exception_err(EXCP0D_GPF, selector & 0xfffc);  
         }  
   
         if (seg_reg == R_SS) {  
             if ((e2 & (DESC_CS_MASK | DESC_W_MASK)) == 0) {  
                 EIP = cur_eip;  
                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);  
             }  
         } else {  
             if ((e2 & (DESC_CS_MASK | DESC_R_MASK)) == DESC_CS_MASK) {  
                 EIP = cur_eip;  
                 raise_exception_err(EXCP0D_GPF, selector & 0xfffc);  
             }  
         }  
   
         if (!(e2 & DESC_P_MASK)) {  
             EIP = cur_eip;  
             if (seg_reg == R_SS)  
                 raise_exception_err(EXCP0C_STACK, selector & 0xfffc);  
             else  
                 raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);  
         }  
           
         sc->base = (void *)((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000));  
         sc->limit = (e1 & 0xffff) | (e2 & 0x000f0000);  
         if (e2 & (1 << 23))  
             sc->limit = (sc->limit << 12) | 0xfff;  
         sc->seg_32bit = (e2 >> 22) & 1;  
 #if 0  
         fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n",  
                 selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit);  
 #endif  
     }  
     env->segs[seg_reg] = selector;  
 }  
   
1095  void OPPROTO op_movl_seg_T0(void)  void OPPROTO op_movl_seg_T0(void)
1096  {  {
1097      load_seg(PARAM1, T0 & 0xffff, PARAM2);      load_seg(PARAM1, T0 & 0xffff, PARAM2);
# Line 1326  void OPPROTO op_addl_A0_seg(void) Line 1124  void OPPROTO op_addl_A0_seg(void)
1124      A0 += *(unsigned long *)((char *)env + PARAM1);      A0 += *(unsigned long *)((char *)env + PARAM1);
1125  }  }
1126    
 void helper_lsl(void)  
 {  
     unsigned int selector, limit;  
     SegmentDescriptorTable *dt;  
     int index;  
     uint32_t e1, e2;  
     uint8_t *ptr;  
   
     CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;  
     selector = T0 & 0xffff;  
     if (selector & 0x4)  
         dt = &env->ldt;  
     else  
         dt = &env->gdt;  
     index = selector & ~7;  
     if ((index + 7) > dt->limit)  
         return;  
     ptr = dt->base + index;  
     e1 = ldl(ptr);  
     e2 = ldl(ptr + 4);  
     limit = (e1 & 0xffff) | (e2 & 0x000f0000);  
     if (e2 & (1 << 23))  
         limit = (limit << 12) | 0xfff;  
     T1 = limit;  
     CC_SRC |= CC_Z;  
 }  
   
1127  void OPPROTO op_lsl(void)  void OPPROTO op_lsl(void)
1128  {  {
1129      helper_lsl();      helper_lsl();
1130  }  }
1131    
 void helper_lar(void)  
 {  
     unsigned int selector;  
     SegmentDescriptorTable *dt;  
     int index;  
     uint32_t e2;  
     uint8_t *ptr;  
   
     CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;  
     selector = T0 & 0xffff;  
     if (selector & 0x4)  
         dt = &env->ldt;  
     else  
         dt = &env->gdt;  
     index = selector & ~7;  
     if ((index + 7) > dt->limit)  
         return;  
     ptr = dt->base + index;  
     e2 = ldl(ptr + 4);  
     T1 = e2 & 0x00f0ff00;  
     CC_SRC |= CC_Z;  
 }  
   
1132  void OPPROTO op_lar(void)  void OPPROTO op_lar(void)
1133  {  {
1134      helper_lar();      helper_lar();
# Line 1678  CCTable cc_table[CC_OP_NB] = { Line 1426  CCTable cc_table[CC_OP_NB] = {
1426     functions comes from the LGPL'ed x86 emulator found in the Willows     functions comes from the LGPL'ed x86 emulator found in the Willows
1427     TWIN windows emulator. */     TWIN windows emulator. */
1428    
 #ifdef USE_X86LDOUBLE  
 /* use long double functions */  
 #define lrint lrintl  
 #define llrint llrintl  
 #define fabs fabsl  
 #define sin sinl  
 #define cos cosl  
 #define sqrt sqrtl  
 #define pow powl  
 #define log logl  
 #define tan tanl  
 #define atan2 atan2l  
 #define floor floorl  
 #define ceil ceill  
 #define rint rintl  
 #endif  
   
 extern int lrint(CPU86_LDouble x);  
 extern int64_t llrint(CPU86_LDouble x);  
 extern CPU86_LDouble fabs(CPU86_LDouble x);  
 extern CPU86_LDouble sin(CPU86_LDouble x);  
 extern CPU86_LDouble cos(CPU86_LDouble x);  
 extern CPU86_LDouble sqrt(CPU86_LDouble x);  
 extern CPU86_LDouble pow(CPU86_LDouble, CPU86_LDouble);  
 extern CPU86_LDouble log(CPU86_LDouble x);  
 extern CPU86_LDouble tan(CPU86_LDouble x);  
 extern CPU86_LDouble atan2(CPU86_LDouble, CPU86_LDouble);  
 extern CPU86_LDouble floor(CPU86_LDouble x);  
 extern CPU86_LDouble ceil(CPU86_LDouble x);  
 extern CPU86_LDouble rint(CPU86_LDouble x);  
   
1429  #if defined(__powerpc__)  #if defined(__powerpc__)
1430  extern CPU86_LDouble copysign(CPU86_LDouble, CPU86_LDouble);  extern CPU86_LDouble copysign(CPU86_LDouble, CPU86_LDouble);
1431    
# Line 1729  double qemu_rint(double x) Line 1446  double qemu_rint(double x)
1446  #define rint qemu_rint  #define rint qemu_rint
1447  #endif  #endif
1448    
 #define RC_MASK         0xc00  
 #define RC_NEAR         0x000  
 #define RC_DOWN         0x400  
 #define RC_UP           0x800  
 #define RC_CHOP         0xc00  
   
 #define MAXTAN 9223372036854775808.0  
   
 #ifdef USE_X86LDOUBLE  
   
 /* only for x86 */  
 typedef union {  
     long double d;  
     struct {  
         unsigned long long lower;  
         unsigned short upper;  
     } l;  
 } CPU86_LDoubleU;  
   
 /* the following deal with x86 long double-precision numbers */  
 #define MAXEXPD 0x7fff  
 #define EXPBIAS 16383  
 #define EXPD(fp)        (fp.l.upper & 0x7fff)  
 #define SIGND(fp)       ((fp.l.upper) & 0x8000)  
 #define MANTD(fp)       (fp.l.lower)  
 #define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS  
   
 #else  
   
 typedef union {  
     double d;  
 #ifndef WORDS_BIGENDIAN  
     struct {  
         uint32_t lower;  
         int32_t upper;  
     } l;  
 #else  
     struct {  
         int32_t upper;  
         uint32_t lower;  
     } l;  
 #endif  
     int64_t ll;  
 } CPU86_LDoubleU;  
   
 /* the following deal with IEEE double-precision numbers */  
 #define MAXEXPD 0x7ff  
 #define EXPBIAS 1023  
 #define EXPD(fp)        (((fp.l.upper) >> 20) & 0x7FF)  
 #define SIGND(fp)       ((fp.l.upper) & 0x80000000)  
 #define MANTD(fp)       (fp.ll & ((1LL << 52) - 1))  
 #define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)  
 #endif  
   
1449  /* fp load FT0 */  /* fp load FT0 */
1450    
1451  void OPPROTO op_flds_FT0_A0(void)  void OPPROTO op_flds_FT0_A0(void)
# Line 1899  void OPPROTO op_fldt_ST0_A0(void) Line 1562  void OPPROTO op_fldt_ST0_A0(void)
1562      ST0 = *(long double *)A0;      ST0 = *(long double *)A0;
1563  }  }
1564  #else  #else
 static inline CPU86_LDouble helper_fldt(uint8_t *ptr)  
 {  
     CPU86_LDoubleU temp;  
     int upper, e;  
     /* mantissa */  
     upper = lduw(ptr + 8);  
     /* XXX: handle overflow ? */  
     e = (upper & 0x7fff) - 16383 + EXPBIAS; /* exponent */  
     e |= (upper >> 4) & 0x800; /* sign */  
     temp.ll = ((ldq(ptr) >> 11) & ((1LL << 52) - 1)) | ((uint64_t)e << 52);  
     return temp.d;  
 }  
   
 void helper_fldt_ST0_A0(void)  
 {  
     ST0 = helper_fldt((uint8_t *)A0);  
 }  
   
1565  void OPPROTO op_fldt_ST0_A0(void)  void OPPROTO op_fldt_ST0_A0(void)
1566  {  {
1567      helper_fldt_ST0_A0();      helper_fldt_ST0_A0();
# Line 2013  void OPPROTO op_fstt_ST0_A0(void) Line 1658  void OPPROTO op_fstt_ST0_A0(void)
1658      *(long double *)A0 = ST0;      *(long double *)A0 = ST0;
1659  }  }
1660  #else  #else
   
 static inline void helper_fstt(CPU86_LDouble f, uint8_t *ptr)  
 {  
     CPU86_LDoubleU temp;  
     int e;  
     temp.d = f;  
     /* mantissa */  
     stq(ptr, (MANTD(temp) << 11) | (1LL << 63));  
     /* exponent + sign */  
     e = EXPD(temp) - EXPBIAS + 16383;  
     e |= SIGND(temp) >> 16;  
     stw(ptr + 8, e);  
 }  
   
 void helper_fstt_ST0_A0(void)  
 {  
     helper_fstt(ST0, (uint8_t *)A0);  
 }  
   
1661  void OPPROTO op_fstt_ST0_A0(void)  void OPPROTO op_fstt_ST0_A0(void)
1662  {  {
1663      helper_fstt_ST0_A0();      helper_fstt_ST0_A0();
# Line 2080  void OPPROTO op_fistll_ST0_A0(void) Line 1706  void OPPROTO op_fistll_ST0_A0(void)
1706      stq((void *)A0, val);      stq((void *)A0, val);
1707  }  }
1708    
 /* BCD ops */  
   
 #define MUL10(iv) ( iv + iv + (iv << 3) )  
   
 void helper_fbld_ST0_A0(void)  
 {  
     uint8_t *seg;  
     CPU86_LDouble fpsrcop;  
     int m32i;  
     unsigned int v;  
   
     /* in this code, seg/m32i will be used as temporary ptr/int */  
     seg = (uint8_t *)A0 + 8;  
     v = ldub(seg--);  
     /* XXX: raise exception */  
     if (v != 0)  
         return;  
     v = ldub(seg--);  
     /* XXX: raise exception */  
     if ((v & 0xf0) != 0)  
         return;  
     m32i = v;  /* <-- d14 */  
     v = ldub(seg--);  
     m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d13 */  
     m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d12 */  
     v = ldub(seg--);  
     m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d11 */  
     m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d10 */  
     v = ldub(seg--);  
     m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d9 */  
     m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d8 */  
     fpsrcop = ((CPU86_LDouble)m32i) * 100000000.0;  
   
     v = ldub(seg--);  
     m32i = (v >> 4);  /* <-- d7 */  
     m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d6 */  
     v = ldub(seg--);  
     m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d5 */  
     m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d4 */  
     v = ldub(seg--);  
     m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d3 */  
     m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d2 */  
     v = ldub(seg);  
     m32i = MUL10(m32i) + (v >> 4);  /* <-- val * 10 + d1 */  
     m32i = MUL10(m32i) + (v & 0xf); /* <-- val * 10 + d0 */  
     fpsrcop += ((CPU86_LDouble)m32i);  
     if ( ldub(seg+9) & 0x80 )  
         fpsrcop = -fpsrcop;  
     ST0 = fpsrcop;  
 }  
   
1709  void OPPROTO op_fbld_ST0_A0(void)  void OPPROTO op_fbld_ST0_A0(void)
1710  {  {
1711      helper_fbld_ST0_A0();      helper_fbld_ST0_A0();
1712  }  }
1713    
 void helper_fbst_ST0_A0(void)  
 {  
     CPU86_LDouble fptemp;  
     CPU86_LDouble fpsrcop;  
     int v;  
     uint8_t *mem_ref, *mem_end;  
   
     fpsrcop = rint(ST0);  
     mem_ref = (uint8_t *)A0;  
     mem_end = mem_ref + 8;  
     if ( fpsrcop < 0.0 ) {  
         stw(mem_end, 0x8000);  
         fpsrcop = -fpsrcop;  
     } else {  
         stw(mem_end, 0x0000);  
     }  
     while (mem_ref < mem_end) {  
         if (fpsrcop == 0.0)  
             break;  
         fptemp = floor(fpsrcop/10.0);  
         v = ((int)(fpsrcop - fptemp*10.0));  
         if  (fptemp == 0.0)  {  
             stb(mem_ref++, v);  
             break;  
         }  
         fpsrcop = fptemp;  
         fptemp = floor(fpsrcop/10.0);  
         v |= (((int)(fpsrcop - fptemp*10.0)) << 4);  
         stb(mem_ref++, v);  
         fpsrcop = fptemp;  
     }  
     while (mem_ref < mem_end) {  
         stb(mem_ref++, 0);  
     }  
 }  
   
1714  void OPPROTO op_fbst_ST0_A0(void)  void OPPROTO op_fbst_ST0_A0(void)
1715  {  {
1716      helper_fbst_ST0_A0();      helper_fbst_ST0_A0();
# Line 2179  void OPPROTO op_fbst_ST0_A0(void) Line 1718  void OPPROTO op_fbst_ST0_A0(void)
1718    
1719  /* FPU move */  /* FPU move */
1720    
 static inline void fpush(void)  
 {  
     env->fpstt = (env->fpstt - 1) & 7;  
     env->fptags[env->fpstt] = 0; /* validate stack entry */  
 }  
   
 static inline void fpop(void)  
 {  
     env->fptags[env->fpstt] = 1; /* invvalidate stack entry */  
     env->fpstt = (env->fpstt + 1) & 7;  
 }  
   
1721  void OPPROTO op_fpush(void)  void OPPROTO op_fpush(void)
1722  {  {
1723      fpush();      fpush();
# Line 2370  void OPPROTO op_fabs_ST0(void) Line 1897  void OPPROTO op_fabs_ST0(void)
1897      ST0 = fabs(ST0);      ST0 = fabs(ST0);
1898  }  }
1899    
 void helper_fxam_ST0(void)  
 {  
     CPU86_LDoubleU temp;  
     int expdif;  
   
     temp.d = ST0;  
   
     env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */  
     if (SIGND(temp))  
         env->fpus |= 0x200; /* C1 <-- 1 */  
   
     expdif = EXPD(temp);  
     if (expdif == MAXEXPD) {  
         if (MANTD(temp) == 0)  
             env->fpus |=  0x500 /*Infinity*/;  
         else  
             env->fpus |=  0x100 /*NaN*/;  
     } else if (expdif == 0) {  
         if (MANTD(temp) == 0)  
             env->fpus |=  0x4000 /*Zero*/;  
         else  
             env->fpus |= 0x4400 /*Denormal*/;  
     } else {  
         env->fpus |= 0x400;  
     }  
 }  
   
1900  void OPPROTO op_fxam_ST0(void)  void OPPROTO op_fxam_ST0(void)
1901  {  {
1902      helper_fxam_ST0();      helper_fxam_ST0();
# Line 2442  void OPPROTO op_fldz_FT0(void) Line 1942  void OPPROTO op_fldz_FT0(void)
1942      ST0 = *(CPU86_LDouble *)&f15rk[0];      ST0 = *(CPU86_LDouble *)&f15rk[0];
1943  }  }
1944    
 void helper_f2xm1(void)  
 {  
     ST0 = pow(2.0,ST0) - 1.0;  
 }  
   
 void helper_fyl2x(void)  
 {  
     CPU86_LDouble fptemp;  
       
     fptemp = ST0;  
     if (fptemp>0.0){  
         fptemp = log(fptemp)/log(2.0);   /* log2(ST) */  
         ST1 *= fptemp;  
         fpop();  
     } else {  
         env->fpus &= (~0x4700);  
         env->fpus |= 0x400;  
     }  
 }  
   
 void helper_fptan(void)  
 {  
     CPU86_LDouble fptemp;  
   
     fptemp = ST0;  
     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {  
         env->fpus |= 0x400;  
     } else {  
         ST0 = tan(fptemp);  
         fpush();  
         ST0 = 1.0;  
         env->fpus &= (~0x400);  /* C2 <-- 0 */  
         /* the above code is for  |arg| < 2**52 only */  
     }  
 }  
   
 void helper_fpatan(void)  
 {  
     CPU86_LDouble fptemp, fpsrcop;  
   
     fpsrcop = ST1;  
     fptemp = ST0;  
     ST1 = atan2(fpsrcop,fptemp);  
     fpop();  
 }  
   
 void helper_fxtract(void)  
 {  
     CPU86_LDoubleU temp;  
     unsigned int expdif;  
   
     temp.d = ST0;  
     expdif = EXPD(temp) - EXPBIAS;  
     /*DP exponent bias*/  
     ST0 = expdif;  
     fpush();  
     BIASEXPONENT(temp);  
     ST0 = temp.d;  
 }  
   
 void helper_fprem1(void)  
 {  
     CPU86_LDouble dblq, fpsrcop, fptemp;  
     CPU86_LDoubleU fpsrcop1, fptemp1;  
     int expdif;  
     int q;  
   
     fpsrcop = ST0;  
     fptemp = ST1;  
     fpsrcop1.d = fpsrcop;  
     fptemp1.d = fptemp;  
     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);  
     if (expdif < 53) {  
         dblq = fpsrcop / fptemp;  
         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);  
         ST0 = fpsrcop - fptemp*dblq;  
         q = (int)dblq; /* cutting off top bits is assumed here */  
         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */  
                                 /* (C0,C1,C3) <-- (q2,q1,q0) */  
         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */  
         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */  
         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */  
     } else {  
         env->fpus |= 0x400;  /* C2 <-- 1 */  
         fptemp = pow(2.0, expdif-50);  
         fpsrcop = (ST0 / ST1) / fptemp;  
         /* fpsrcop = integer obtained by rounding to the nearest */  
         fpsrcop = (fpsrcop-floor(fpsrcop) < ceil(fpsrcop)-fpsrcop)?  
             floor(fpsrcop): ceil(fpsrcop);  
         ST0 -= (ST1 * fpsrcop * fptemp);  
     }  
 }  
   
 void helper_fprem(void)  
 {  
     CPU86_LDouble dblq, fpsrcop, fptemp;  
     CPU86_LDoubleU fpsrcop1, fptemp1;  
     int expdif;  
     int q;  
       
     fpsrcop = ST0;  
     fptemp = ST1;  
     fpsrcop1.d = fpsrcop;  
     fptemp1.d = fptemp;  
     expdif = EXPD(fpsrcop1) - EXPD(fptemp1);  
     if ( expdif < 53 ) {  
         dblq = fpsrcop / fptemp;  
         dblq = (dblq < 0.0)? ceil(dblq): floor(dblq);  
         ST0 = fpsrcop - fptemp*dblq;  
         q = (int)dblq; /* cutting off top bits is assumed here */  
         env->fpus &= (~0x4700); /* (C3,C2,C1,C0) <-- 0000 */  
                                 /* (C0,C1,C3) <-- (q2,q1,q0) */  
         env->fpus |= (q&0x4) << 6; /* (C0) <-- q2 */  
         env->fpus |= (q&0x2) << 8; /* (C1) <-- q1 */  
         env->fpus |= (q&0x1) << 14; /* (C3) <-- q0 */  
     } else {  
         env->fpus |= 0x400;  /* C2 <-- 1 */  
         fptemp = pow(2.0, expdif-50);  
         fpsrcop = (ST0 / ST1) / fptemp;  
         /* fpsrcop = integer obtained by chopping */  
         fpsrcop = (fpsrcop < 0.0)?  
             -(floor(fabs(fpsrcop))): floor(fpsrcop);  
         ST0 -= (ST1 * fpsrcop * fptemp);  
     }  
 }  
   
 void helper_fyl2xp1(void)  
 {  
     CPU86_LDouble fptemp;  
   
     fptemp = ST0;  
     if ((fptemp+1.0)>0.0) {  
         fptemp = log(fptemp+1.0) / log(2.0); /* log2(ST+1.0) */  
         ST1 *= fptemp;  
         fpop();  
     } else {  
         env->fpus &= (~0x4700);  
         env->fpus |= 0x400;  
     }  
 }  
   
 void helper_fsqrt(void)  
 {  
     CPU86_LDouble fptemp;  
   
     fptemp = ST0;  
     if (fptemp<0.0) {  
         env->fpus &= (~0x4700);  /* (C3,C2,C1,C0) <-- 0000 */  
         env->fpus |= 0x400;  
     }  
     ST0 = sqrt(fptemp);  
 }  
   
 void helper_fsincos(void)  
 {  
     CPU86_LDouble fptemp;  
   
     fptemp = ST0;  
     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {  
         env->fpus |= 0x400;  
     } else {  
         ST0 = sin(fptemp);  
         fpush();  
         ST0 = cos(fptemp);  
         env->fpus &= (~0x400);  /* C2 <-- 0 */  
         /* the above code is for  |arg| < 2**63 only */  
     }  
 }  
   
 void helper_frndint(void)  
 {  
     ST0 = rint(ST0);  
 }  
   
 void helper_fscale(void)  
 {  
     CPU86_LDouble fpsrcop, fptemp;  
   
     fpsrcop = 2.0;  
     fptemp = pow(fpsrcop,ST1);  
     ST0 *= fptemp;  
 }  
   
 void helper_fsin(void)  
 {  
     CPU86_LDouble fptemp;  
   
     fptemp = ST0;  
     if ((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {  
         env->fpus |= 0x400;  
     } else {  
         ST0 = sin(fptemp);  
         env->fpus &= (~0x400);  /* C2 <-- 0 */  
         /* the above code is for  |arg| < 2**53 only */  
     }  
 }  
   
 void helper_fcos(void)  
 {  
     CPU86_LDouble fptemp;  
   
     fptemp = ST0;  
     if((fptemp > MAXTAN)||(fptemp < -MAXTAN)) {  
         env->fpus |= 0x400;  
     } else {  
         ST0 = cos(fptemp);  
         env->fpus &= (~0x400);  /* C2 <-- 0 */  
         /* the above code is for  |arg5 < 2**63 only */  
     }  
 }  
   
1945  /* associated heplers to reduce generated code length and to simplify  /* associated heplers to reduce generated code length and to simplify
1946     relocation (FP constants are usually stored in .rodata section) */     relocation (FP constants are usually stored in .rodata section) */
1947    
# Line 2789  void OPPROTO op_fninit(void) Line 2078  void OPPROTO op_fninit(void)
2078      env->fptags[7] = 1;      env->fptags[7] = 1;
2079  }  }
2080    
 void helper_fstenv(uint8_t *ptr, int data32)  
 {  
     int fpus, fptag, exp, i;  
     uint64_t mant;  
     CPU86_LDoubleU tmp;  
   
     fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;  
     fptag = 0;  
     for (i=7; i>=0; i--) {  
         fptag <<= 2;  
         if (env->fptags[i]) {  
             fptag |= 3;  
         } else {  
             tmp.d = env->fpregs[i];  
             exp = EXPD(tmp);  
             mant = MANTD(tmp);  
             if (exp == 0 && mant == 0) {  
                 /* zero */  
                 fptag |= 1;  
             } else if (exp == 0 || exp == MAXEXPD  
 #ifdef USE_X86LDOUBLE  
                        || (mant & (1LL << 63)) == 0  
 #endif  
                        ) {  
                 /* NaNs, infinity, denormal */  
                 fptag |= 2;  
             }  
         }  
     }  
     if (data32) {  
         /* 32 bit */  
         stl(ptr, env->fpuc);  
         stl(ptr + 4, fpus);  
         stl(ptr + 8, fptag);  
         stl(ptr + 12, 0);  
         stl(ptr + 16, 0);  
         stl(ptr + 20, 0);  
         stl(ptr + 24, 0);  
     } else {  
         /* 16 bit */  
         stw(ptr, env->fpuc);  
         stw(ptr + 2, fpus);  
         stw(ptr + 4, fptag);  
         stw(ptr + 6, 0);  
         stw(ptr + 8, 0);  
         stw(ptr + 10, 0);  
         stw(ptr + 12, 0);  
     }  
 }  
   
 void helper_fldenv(uint8_t *ptr, int data32)  
 {  
     int i, fpus, fptag;  
   
     if (data32) {  
         env->fpuc = lduw(ptr);  
         fpus = lduw(ptr + 4);  
         fptag = lduw(ptr + 8);  
     }  
     else {  
         env->fpuc = lduw(ptr);  
         fpus = lduw(ptr + 2);  
         fptag = lduw(ptr + 4);  
     }  
     env->fpstt = (fpus >> 11) & 7;  
     env->fpus = fpus & ~0x3800;  
     for(i = 0;i < 7; i++) {  
         env->fptags[i] = ((fptag & 3) == 3);  
         fptag >>= 2;  
     }  
 }  
   
 void helper_fsave(uint8_t *ptr, int data32)  
 {  
     CPU86_LDouble tmp;  
     int i;  
   
     helper_fstenv(ptr, data32);  
   
     ptr += (14 << data32);  
     for(i = 0;i < 8; i++) {  
         tmp = ST(i);  
 #ifdef USE_X86LDOUBLE  
         *(long double *)ptr = tmp;  
 #else  
         helper_fstt(tmp, ptr);  
 #endif          
         ptr += 10;  
     }  
   
     /* fninit */  
     env->fpus = 0;  
     env->fpstt = 0;  
     env->fpuc = 0x37f;  
     env->fptags[0] = 1;  
     env->fptags[1] = 1;  
     env->fptags[2] = 1;  
     env->fptags[3] = 1;  
     env->fptags[4] = 1;  
     env->fptags[5] = 1;  
     env->fptags[6] = 1;  
     env->fptags[7] = 1;  
 }  
   
 void helper_frstor(uint8_t *ptr, int data32)  
 {  
     CPU86_LDouble tmp;  
     int i;  
   
     helper_fldenv(ptr, data32);  
     ptr += (14 << data32);  
   
     for(i = 0;i < 8; i++) {  
 #ifdef USE_X86LDOUBLE  
         tmp = *(long double *)ptr;  
 #else  
         tmp = helper_fldt(ptr);  
 #endif          
         ST(i) = tmp;  
         ptr += 10;  
     }  
 }  
   
2081  void OPPROTO op_fnstenv_A0(void)  void OPPROTO op_fnstenv_A0(void)
2082  {  {
2083      helper_fstenv((uint8_t *)A0, PARAM1);      helper_fstenv((uint8_t *)A0, PARAM1);
# Line 2942  void OPPROTO op_unlock(void) Line 2108  void OPPROTO op_unlock(void)
2108  {  {
2109      cpu_unlock();      cpu_unlock();
2110  }  }
2111    

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

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