ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp
(Generate patch)

Comparing BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp (file contents):
Revision 1.2 by gbeauche, 2002-09-13T15:06:42Z vs.
Revision 1.7 by gbeauche, 2002-11-16T15:28:25Z

# Line 80 | Line 80
80   fpu_t fpu;
81  
82   /* -------------------------------------------------------------------------- */
83 /* --- Endianness                                                         --- */
84 /* -------------------------------------------------------------------------- */
85
86 // Taken from glibc 2.1.x: endian.h
87 #define UAE_LITTLE_ENDIAN               1234
88 #define UAE_BIG_ENDIAN                  4321
89
90 #if WORDS_BIGENDIAN
91 #define UAE_BYTE_ORDER                  UAE_BIG_ENDIAN
92 #else
93 #define UAE_BYTE_ORDER                  UAE_LITTLE_ENDIAN
94 #endif
95
96 // Some machines may need to use a different endianness for floating point values
97 // e.g. ARM in which case it is big endian
98 #define UAE_FLOAT_WORD_ORDER    UAE_BYTE_ORDER
99
100 /* -------------------------------------------------------------------------- */
83   /* --- Scopes Definition                                                  --- */
84   /* -------------------------------------------------------------------------- */
85  
# Line 264 | Line 246 | PRIVATE inline uae_u32 FFPU extract_sing
246   // to_exten
247   PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3)
248   {
249 < #if 1
250 <        // FIXME: USE_QUAD_DOUBLE
251 <        fpu_extended result;
249 >        // is it zero?
250 >        if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0)
251 >                return 0.0;
252 >
253 >        fpu_register result;
254 > #if USE_QUAD_DOUBLE
255 >        // is it NaN?
256 >        if ((wrd1 & 0x7fff0000) == 0x7fff0000 && wrd2 != 0 && wrd3 != 0) {
257 >                make_nan(result);
258 >                return result;
259 >        }
260 >        // is it inf?
261 >        if ((wrd1 & 0x7ffff000) == 0x7fff0000 && wrd2 == 0 && wrd3 == 0) {
262 >                if ((wrd1 & 0x80000000) == 0)
263 >                        make_inf_positive(result);
264 >                else
265 >                        make_inf_negative(result);
266 >                return result;
267 >        }
268 >        fp_declare_init_shape(srp, result, extended);
269 >        srp->ieee.negative  = (wrd1 >> 31) & 1;
270 >        srp->ieee.exponent  = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX;
271 >        srp->ieee.mantissa0 = (wrd2 >> 16) & 0xffff;
272 >        srp->ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff);
273 >        srp->ieee.mantissa2 = (wrd3 & 0xffff) << 16;
274 >        srp->ieee.mantissa3 = 0;
275 > #elif USE_LONG_DOUBLE
276          fp_declare_init_shape(srp, result, extended);
277          srp->ieee.negative      = (wrd1 >> 31) & 1;
278          srp->ieee.exponent      = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX;
279          srp->ieee.mantissa0     = wrd2;
280          srp->ieee.mantissa1     = wrd3;
281 <        fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
282 <        return result;
283 < #elif 0 /* original code */
278 <        if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0)
279 <                return 0.0;
280 <        
281 <        fpu_register result;
282 <        uae_u32 *p = (uae_u32 *)&result;
283 <        
284 <        uae_u32 sign =  wrd1 & 0x80000000;
285 <        uae_u32 exp  = (wrd1 >> 16) & 0x7fff;
281 > #else
282 >        uae_u32 sgn = (wrd1 >> 31) & 1;
283 >        uae_u32 exp = (wrd1 >> 16) & 0x7fff;
284  
285 <        // The explicit integer bit is not set, must normalize.
286 <        if((wrd2 & 0x80000000) == 0) {
285 >        // the explicit integer bit is not set, must normalize
286 >        if ((wrd2 & 0x80000000) == 0) {
287                  fpu_debug(("make_extended denormalized mantissa (%X,%X,%X)\n",wrd1,wrd2,wrd3));
288 <                if( wrd2 | wrd3 ) {
288 >                if (wrd2 | wrd3) {
289                          // mantissa, not fraction.
290                          uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3;
291 <                        while( exp > 0 && (man & UVAL64(0x8000000000000000)) == 0 ) {
291 >                        while (exp > 0 && (man & UVAL64(0x8000000000000000)) == 0) {
292                                  man <<= 1;
293                                  exp--;
294                          }
295 <                        wrd2 = (uae_u32)( man >> 32 );
296 <                        wrd3 = (uae_u32)( man & 0xFFFFFFFF );
299 <                } else {
300 <                        if(exp == 0x7FFF) {
301 <                                // Infinity.
302 <                        } else {
303 <                                // Zero
304 <                                exp = 16383 - 1023;
305 <                        }
295 >                        wrd2 = (uae_u32)(man >> 32);
296 >                        wrd3 = (uae_u32)(man & 0xFFFFFFFF);
297                  }
298 +                else if (exp != 0x7fff) // zero
299 +                        exp = FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS;
300          }
301  
302 <        if(exp < 16383 - 1023) {
310 <                // should set underflow.
302 >        if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS)
303                  exp = 0;
304 <        } else if(exp > 16383 + 1023) {
305 <                // should set overflow.
306 <                exp = 2047;
307 <        } else {
308 <                exp = exp + 1023 - 16383;
309 <        }
310 <
311 <        // drop the explicit integer bit.
312 <        p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
313 <        p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
314 <
323 <        fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
324 <
325 <        return(result);
304 >        else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS)
305 >                exp = FP_DOUBLE_EXP_MAX;
306 >        else
307 >                exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS;
308 >        
309 >        fp_declare_init_shape(srp, result, double);
310 >        srp->ieee.negative  = sgn;
311 >        srp->ieee.exponent  = exp;
312 >        // drop the explicit integer bit
313 >        srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11;
314 >        srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11);
315   #endif
316 +        fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
317 +        return result;
318   }
319  
320   /*
# Line 335 | Line 326 | PRIVATE inline void FFPU make_extended_n
326          uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result
327   )
328   {
329 < #if 1
330 <        // FIXME: USE_QUAD_DOUBLE
340 <        fp_declare_init_shape(srp, result, extended);
341 <        srp->ieee.negative      = (wrd1 & 0x80000000) != 0;
342 <        srp->ieee.exponent      = (wrd1 >> 16) & 0x7fff;
343 <        srp->ieee.mantissa0     = wrd2;
344 <        srp->ieee.mantissa1     = wrd3;
345 < #elif 0 /* original code */
346 <        // Is it zero?
347 <        if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) {
329 >        // is it zero?
330 >        if ((wrd1 && 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) {
331                  make_zero_positive(result);
332                  return;
333          }
334 <
335 <        // Is it NaN?
336 <        if( (wrd1 & 0x7FFF0000) == 0x7FFF0000 ) {
337 <                if( (wrd1 & 0x0000FFFF) || wrd2 || wrd3 ) {
355 <                        make_nan(result);
356 <                        return;
357 <                }
334 >        // is it NaN?
335 >        if ((wrd1 & 0x7fff0000) == 0x7fff0000 && wrd2 != 0 && wrd3 != 0) {
336 >                make_nan(result);
337 >                return;
338          }
339 <        
340 <        uae_u32 sign =  wrd1 & 0x80000000;
341 <        uae_u32 exp  = (wrd1 >> 16) & 0x7fff;
342 <
343 <        if(exp < 16383 - 1023) {
344 <                // should set underflow.
345 <                exp = 0;
346 <        } else if(exp > 16383 + 1023) {
367 <                // should set overflow.
368 <                exp = 2047;
369 <        } else {
370 <                exp = exp + 1023 - 16383;
339 > #if USE_QUAD_DOUBLE
340 >        // is it inf?
341 >        if ((wrd1 & 0x7ffff000) == 0x7fff0000 && wrd2 == 0 && wrd3 == 0) {
342 >                if ((wrd1 & 0x80000000) == 0)
343 >                        make_inf_positive(result);
344 >                else
345 >                        make_inf_negative(result);
346 >                return;
347          }
348 <
349 <        // drop the explicit integer bit.
350 <        uae_u32 *p = (uae_u32 *)&result;
351 <        p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
352 <        p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
353 <
354 <        fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(float)(*(double *)p)));
348 >        fp_declare_init_shape(srp, result, extended);
349 >        srp->ieee.negative  = (wrd1 >> 31) & 1;
350 >        srp->ieee.exponent  = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX;
351 >        srp->ieee.mantissa0 = (wrd2 >> 16) & 0xffff;
352 >        srp->ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff);
353 >        srp->ieee.mantissa2 = (wrd3 & 0xffff) << 16;
354 >        srp->ieee.mantissa3 = 0;
355 > #elif USE_LONG_DOUBLE
356 >        fp_declare_init_shape(srp, result, extended);
357 >        srp->ieee.negative      = (wrd1 >> 31) & 1;
358 >        srp->ieee.exponent      = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX;
359 >        srp->ieee.mantissa0     = wrd2;
360 >        srp->ieee.mantissa1     = wrd3;
361 > #else
362 >        uae_u32 exp = (wrd1 >> 16) & 0x7fff;
363 >        if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS)
364 >                exp = 0;
365 >        else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS)
366 >                exp = FP_DOUBLE_EXP_MAX;
367 >        else
368 >                exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS;
369 >        
370 >        fp_declare_init_shape(srp, result, double);
371 >        srp->ieee.negative  = (wrd1 >> 31) & 1;
372 >        srp->ieee.exponent  = exp;
373 >        // drop the explicit integer bit
374 >        srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11;
375 >        srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11);
376   #endif
377 +        fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
378   }
379  
380   // from_exten
# Line 384 | Line 382 | PRIVATE inline void FFPU extract_extende
382          uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
383   )
384   {
387 #if 1
388        // FIXME: USE_QUAD_DOUBLE and non little-endian specificities
389        uae_u32 *p = (uae_u32 *)&src;
390        *wrd3 = p[0];
391        *wrd2 = p[1];
392        *wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16;
393        fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3));
394 #elif 0 /* original code */
385          if (src == 0.0) {
386                  *wrd1 = *wrd2 = *wrd3 = 0;
387                  return;
388          }
389 <        
389 > #if USE_QUAD_DOUBLE
390 >        // FIXME: deal with denormals?
391 >        fp_declare_init_shape(srp, src, extended);
392 >        *wrd1 = (srp->ieee.negative << 31) | (srp->ieee.exponent << 16);
393 >        // always set the explicit integer bit.
394 >        *wrd2 = 0x80000000 | (srp->ieee.mantissa0 << 15) | ((srp->ieee.mantissa1 & 0xfffe0000) >> 17);
395 >        *wrd3 = (srp->ieee.mantissa1 << 15) | ((srp->ieee.mantissa2 & 0xfffe0000) >> 17);
396 > #elif USE_LONG_DOUBLE
397          uae_u32 *p = (uae_u32 *)&src;
398 <        
399 <        fpu_debug(("extract_extended (%X,%X)\n",p[FLO],p[FHI]));
398 > #ifdef WORDS_BIGENDIAN
399 >        *wrd1 = p[0];
400 >        *wrd2 = p[1];
401 >        *wrd3 = p[2];
402 > #else
403 >        *wrd3 = p[0];
404 >        *wrd2 = p[1];
405 >        *wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16;
406 > #endif
407 > #else
408 >        fp_declare_init_shape(srp, src, double);
409 >        fpu_debug(("extract_extended (%d,%d,%X,%X)\n",
410 >                           srp->ieee.negative , srp->ieee.exponent,
411 >                           srp->ieee.mantissa0, srp->ieee.mantissa1));
412  
413 <        uae_u32 sign =  p[FHI] & 0x80000000;
413 >        uae_u32 exp = srp->ieee.exponent;
414  
415 <        uae_u32 exp  = ((p[FHI] >> 20) & 0x7ff);
416 <        // Check for maximum
417 <        if(exp == 0x7FF) {
418 <                exp = 0x7FFF;
410 <        } else {
411 <                exp  += 16383 - 1023;
412 <        }
415 >        if (exp == FP_DOUBLE_EXP_MAX)
416 >                exp = FP_EXTENDED_EXP_MAX;
417 >        else
418 >                exp += FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS;
419  
420 <        *wrd1 = sign | (exp << 16);
420 >        *wrd1 = (srp->ieee.negative << 31) | (exp << 16);
421          // always set the explicit integer bit.
422 <        *wrd2 = 0x80000000 | ((p[FHI] & 0x000FFFFF) << 11) | ((p[FLO] & 0xFFE00000) >> 21);
423 <        *wrd3 = p[FLO] << 11;
418 <
419 <        fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3));
422 >        *wrd2 = 0x80000000 | (srp->ieee.mantissa0 << 11) | ((srp->ieee.mantissa1 & 0xffe00000) >> 21);
423 >        *wrd3 = srp->ieee.mantissa1 << 11;
424   #endif
425 +        fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3));
426   }
427  
428   // to_double
# Line 425 | Line 430 | PRIVATE inline fpu_register FFPU make_do
430   {
431          union {
432                  fpu_double value;
433 <                uae_u32   parts[2];
433 >                uae_u32    parts[2];
434          } dest;
435   #ifdef WORDS_BIGENDIAN
436          dest.parts[0] = wrd1;
# Line 445 | Line 450 | PRIVATE inline void FFPU extract_double(
450   {
451          union {
452                  fpu_double value;
453 <                uae_u32   parts[2];
453 >                uae_u32    parts[2];
454          } dest;
455          dest.value = (fpu_double)src;
456   #ifdef WORDS_BIGENDIAN
# Line 1621 | Line 1626 | void FFPU fpuop_arithmetic(uae_u32 opcod
1626                                  FPU registers[reg] = 1.0e256;
1627                                  fpu_debug(("FP const: 1.0e256\n"));
1628                                  break;
1629 < #if USE_LONG_DOUBLE
1629 > #if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
1630                          case 0x3c:
1631                                  FPU registers[reg] = 1.0e512;
1632                                  fpu_debug(("FP const: 1.0e512\n"));
# Line 1989 | Line 1994 | void FFPU fpuop_arithmetic(uae_u32 opcod
1994  
1995                  case 0x26:              /* FSCALE */
1996                          fpu_debug(("FSCALE %.04f\n",(double)src));
1997 <
1998 <                        // TODO:
1999 <                        // Overflow, underflow
2000 <
1996 <                        if( isinf(FPU registers[reg]) ) {
1997 <                                make_nan( FPU registers[reg] );
1998 <                        }
1999 <                        else {
1997 >                        // TODO: overflow flags
1998 >                        get_dest_flags(FPU registers[reg]);
1999 >                        get_source_flags(src);
2000 >                        if (fl_source.in_range && fl_dest.in_range) {
2001                                  // When the absolute value of the source operand is >= 2^14,
2002                                  // an overflow or underflow always results.
2003                                  // Here (int) cast is okay.
2004 <                                fast_scale( FPU registers[reg], (int)fp_round_to_zero(src) );
2004 >                                int scale_factor = (int)fp_round_to_zero(src);
2005 > #if USE_LONG_DOUBLE || USE_QUAD_DOUBLE
2006 >                                fp_declare_init_shape(sxp, FPU registers[reg], extended);
2007 >                                sxp->ieee.exponent += scale_factor;
2008 > #else
2009 >                                fp_declare_init_shape(sxp, FPU registers[reg], double);
2010 >                                uae_u32 exp = sxp->ieee.exponent + scale_factor;
2011 >                                if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS)
2012 >                                        exp = 0;
2013 >                                else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS)
2014 >                                        exp = FP_DOUBLE_EXP_MAX;
2015 >                                else
2016 >                                        exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS;
2017 >                                sxp->ieee.exponent = exp;
2018 > #endif
2019 >                        }
2020 >                        else if (fl_source.infinity) {
2021 >                                // Returns NaN for any Infinity source
2022 >                                make_nan( FPU registers[reg] );
2023                          }
2024                          make_fpsr(FPU registers[reg]);
2025                          break;
# Line 2086 | Line 2105 | PUBLIC void FFPU fpu_init (bool integral
2105   #if defined(FPU_USE_X86_ROUNDING)
2106          // Initial state after boot, reset and frestore(null frame)
2107          x86_control_word = CW_INITIAL;
2108 < #elif defined(__i386__) && defined(X86_ASSEMBLY)
2108 > #elif defined(USE_X87_ASSEMBLY)
2109          volatile unsigned short int cw;
2110          __asm__ __volatile__("fnstcw %0" : "=m" (cw));
2111          cw &= ~0x0300; cw |= 0x0300; // CW_PC_EXTENDED

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines