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.4 by gbeauche, 2002-09-16T12:01:38Z

# 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
268 <        // FIXME: USE_QUAD_DOUBLE
269 <        fpu_extended result;
270 <        fp_declare_init_shape(srp, result, extended);
271 <        srp->ieee.negative      = (wrd1 >> 31) & 1;
272 <        srp->ieee.exponent      = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX;
273 <        srp->ieee.mantissa0     = wrd2;
274 <        srp->ieee.mantissa1     = wrd3;
275 <        fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
276 <        return result;
277 < #elif 0 /* original code */
249 >        // is it zero?
250          if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0)
251                  return 0.0;
252 <        
252 >
253          fpu_register result;
254 <        uae_u32 *p = (uae_u32 *)&result;
255 <        
256 <        uae_u32 sign =  wrd1 & 0x80000000;
285 <        uae_u32 exp  = (wrd1 >> 16) & 0x7fff;
254 > #ifndef USE_LONG_DOUBLE
255 >        uae_u32 sgn = (wrd1 >> 31) & 1;
256 >        uae_u32 exp = (wrd1 >> 16) & 0x7fff;
257  
258 <        // The explicit integer bit is not set, must normalize.
259 <        if((wrd2 & 0x80000000) == 0) {
258 >        // the explicit integer bit is not set, must normalize
259 >        if ((wrd2 & 0x80000000) == 0) {
260                  fpu_debug(("make_extended denormalized mantissa (%X,%X,%X)\n",wrd1,wrd2,wrd3));
261 <                if( wrd2 | wrd3 ) {
261 >                if (wrd2 | wrd3) {
262                          // mantissa, not fraction.
263                          uae_u64 man = ((uae_u64)wrd2 << 32) | wrd3;
264 <                        while( exp > 0 && (man & UVAL64(0x8000000000000000)) == 0 ) {
264 >                        while (exp > 0 && (man & UVAL64(0x8000000000000000)) == 0) {
265                                  man <<= 1;
266                                  exp--;
267                          }
268 <                        wrd2 = (uae_u32)( man >> 32 );
269 <                        wrd3 = (uae_u32)( man & 0xFFFFFFFF );
299 <                } else {
300 <                        if(exp == 0x7FFF) {
301 <                                // Infinity.
302 <                        } else {
303 <                                // Zero
304 <                                exp = 16383 - 1023;
305 <                        }
268 >                        wrd2 = (uae_u32)(man >> 32);
269 >                        wrd3 = (uae_u32)(man & 0xFFFFFFFF);
270                  }
271 +                else if (exp != 0x7fff) // zero
272 +                        exp = FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS;
273          }
274  
275 <        if(exp < 16383 - 1023) {
310 <                // should set underflow.
275 >        if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS)
276                  exp = 0;
277 <        } else if(exp > 16383 + 1023) {
278 <                // should set overflow.
279 <                exp = 2047;
280 <        } else {
281 <                exp = exp + 1023 - 16383;
282 <        }
283 <
284 <        // drop the explicit integer bit.
285 <        p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
286 <        p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
287 <
288 <        fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
289 <
290 <        return(result);
277 >        else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS)
278 >                exp = FP_DOUBLE_EXP_MAX;
279 >        else
280 >                exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS;
281 >        
282 >        fp_declare_init_shape(srp, result, double);
283 >        srp->ieee.negative  = sgn;
284 >        srp->ieee.exponent  = exp;
285 >        // drop the explicit integer bit
286 >        srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11;
287 >        srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11);
288 > #elif USE_QUAD_DOUBLE
289 >        fp_declare_init_shape(srp, result, extended);
290 >        srp->ieee.negative  = (wrd1 >> 31) & 1;
291 >        srp->ieee.exponent  = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX;
292 >        srp->ieee.mantissa0 = (wrd2 >> 16) & 0xffff;
293 >        srp->ieee.mantissa1 = ((wrd2 & 0xffff) << 16) | ((wrd3 >> 16) & 0xffff);
294 >        srp->ieee.mantissa2 = (wrd3 & 0xffff) << 16;
295 > #else
296 >        fp_declare_init_shape(srp, result, extended);
297 >        srp->ieee.negative      = (wrd1 >> 31) & 1;
298 >        srp->ieee.exponent      = (wrd1 >> 16) & FP_EXTENDED_EXP_MAX;
299 >        srp->ieee.mantissa0     = wrd2;
300 >        srp->ieee.mantissa1     = wrd3;
301   #endif
302 +        fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
303 +        return result;
304   }
305  
306   /*
# Line 335 | Line 312 | PRIVATE inline void FFPU make_extended_n
312          uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result
313   )
314   {
315 < #if 1
315 >        // is it zero?
316 >        if ((wrd1 && 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) {
317 >                make_zero_positive(result);
318 >                return;
319 >        }
320 >        // is it NaN?
321 >        if ((wrd1 & 0x7fff0000) == 0x7fff0000 && wrd2 != 0 && wrd3 != 0) {
322 >                make_nan(result);
323 >                return;
324 >        }
325 > #ifndef USE_LONG_DOUBLE
326 >        uae_u32 exp = (wrd1 >> 16) & 0x7fff;
327 >        if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS)
328 >                exp = 0;
329 >        else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS)
330 >                exp = FP_DOUBLE_EXP_MAX;
331 >        else
332 >                exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS;
333 >        
334 >        fp_declare_init_shape(srp, result, double);
335 >        srp->ieee.negative  = (wrd1 >> 31) & 1;
336 >        srp->ieee.exponent  = exp;
337 >        // drop the explicit integer bit
338 >        srp->ieee.mantissa0 = (wrd2 & 0x7fffffff) >> 11;
339 >        srp->ieee.mantissa1 = (wrd2 << 21) | (wrd3 >> 11);
340 > #else
341          // FIXME: USE_QUAD_DOUBLE
342          fp_declare_init_shape(srp, result, extended);
343          srp->ieee.negative      = (wrd1 & 0x80000000) != 0;
344          srp->ieee.exponent      = (wrd1 >> 16) & 0x7fff;
345          srp->ieee.mantissa0     = wrd2;
346          srp->ieee.mantissa1     = wrd3;
345 #elif 0 /* original code */
346        // Is it zero?
347        if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) {
348                make_zero_positive(result);
349                return;
350        }
351
352        // Is it NaN?
353        if( (wrd1 & 0x7FFF0000) == 0x7FFF0000 ) {
354                if( (wrd1 & 0x0000FFFF) || wrd2 || wrd3 ) {
355                        make_nan(result);
356                        return;
357                }
358        }
359        
360        uae_u32 sign =  wrd1 & 0x80000000;
361        uae_u32 exp  = (wrd1 >> 16) & 0x7fff;
362
363        if(exp < 16383 - 1023) {
364                // should set underflow.
365                exp = 0;
366        } else if(exp > 16383 + 1023) {
367                // should set overflow.
368                exp = 2047;
369        } else {
370                exp = exp + 1023 - 16383;
371        }
372
373        // drop the explicit integer bit.
374        uae_u32 *p = (uae_u32 *)&result;
375        p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
376        p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
377
378        fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(float)(*(double *)p)));
347   #endif
348 +        fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
349   }
350  
351   // from_exten
# Line 384 | Line 353 | PRIVATE inline void FFPU extract_extende
353          uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
354   )
355   {
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 */
356          if (src == 0.0) {
357                  *wrd1 = *wrd2 = *wrd3 = 0;
358                  return;
359          }
360 <        
361 <        uae_u32 *p = (uae_u32 *)&src;
362 <        
363 <        fpu_debug(("extract_extended (%X,%X)\n",p[FLO],p[FHI]));
360 > #ifndef USE_LONG_DOUBLE
361 >        fp_declare_init_shape(srp, src, double);
362 >        fpu_debug(("extract_extended (%d,%d,%X,%X)\n",
363 >                           srp->ieee.negative , srp->ieee.exponent,
364 >                           srp->ieee.mantissa0, srp->ieee.mantissa1));
365  
366 <        uae_u32 sign =  p[FHI] & 0x80000000;
366 >        uae_u32 exp = srp->ieee.exponent;
367  
368 <        uae_u32 exp  = ((p[FHI] >> 20) & 0x7ff);
369 <        // Check for maximum
370 <        if(exp == 0x7FF) {
371 <                exp = 0x7FFF;
410 <        } else {
411 <                exp  += 16383 - 1023;
412 <        }
368 >        if (exp == FP_DOUBLE_EXP_MAX)
369 >                exp = FP_EXTENDED_EXP_MAX;
370 >        else
371 >                exp += FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS;
372  
373 <        *wrd1 = sign | (exp << 16);
373 >        *wrd1 = (srp->ieee.negative << 31) | (exp << 16);
374          // always set the explicit integer bit.
375 <        *wrd2 = 0x80000000 | ((p[FHI] & 0x000FFFFF) << 11) | ((p[FLO] & 0xFFE00000) >> 21);
376 <        *wrd3 = p[FLO] << 11;
377 <
378 <        fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3));
375 >        *wrd2 = 0x80000000 | (srp->ieee.mantissa0 << 11) | ((srp->ieee.mantissa1 & 0xffe00000) >> 21);
376 >        *wrd3 = srp->ieee.mantissa1 << 11;
377 > #else
378 >        // FIXME: USE_QUAD_DOUBLE
379 >        uae_u32 *p = (uae_u32 *)&src;
380 > #ifdef WORDS_BIGENDIAN
381 >        *wrd1 = p[0];
382 >        *wrd2 = p[1];
383 >        *wrd3 = p[2];
384 > #else
385 >        *wrd3 = p[0];
386 >        *wrd2 = p[1];
387 >        *wrd1 = ( (uae_u32)*((uae_u16 *)&p[2]) ) << 16;
388 > #endif
389   #endif
390 +        fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3));
391   }
392  
393   // to_double
# Line 425 | Line 395 | PRIVATE inline fpu_register FFPU make_do
395   {
396          union {
397                  fpu_double value;
398 <                uae_u32   parts[2];
398 >                uae_u32    parts[2];
399          } dest;
400   #ifdef WORDS_BIGENDIAN
401          dest.parts[0] = wrd1;
# Line 445 | Line 415 | PRIVATE inline void FFPU extract_double(
415   {
416          union {
417                  fpu_double value;
418 <                uae_u32   parts[2];
418 >                uae_u32    parts[2];
419          } dest;
420          dest.value = (fpu_double)src;
421   #ifdef WORDS_BIGENDIAN
# Line 1989 | Line 1959 | void FFPU fpuop_arithmetic(uae_u32 opcod
1959  
1960                  case 0x26:              /* FSCALE */
1961                          fpu_debug(("FSCALE %.04f\n",(double)src));
1962 <
1963 <                        // TODO:
1964 <                        // Overflow, underflow
1965 <
1996 <                        if( isinf(FPU registers[reg]) ) {
1997 <                                make_nan( FPU registers[reg] );
1998 <                        }
1999 <                        else {
1962 >                        // TODO: overflow flags
1963 >                        get_dest_flags(FPU registers[reg]);
1964 >                        get_source_flags(src);
1965 >                        if (fl_source.in_range && fl_dest.in_range) {
1966                                  // When the absolute value of the source operand is >= 2^14,
1967                                  // an overflow or underflow always results.
1968                                  // Here (int) cast is okay.
1969 <                                fast_scale( FPU registers[reg], (int)fp_round_to_zero(src) );
1969 >                                int scale_factor = (int)fp_round_to_zero(src);
1970 > #ifndef USE_LONG_DOUBLE
1971 >                                fp_declare_init_shape(sxp, FPU registers[reg], double);
1972 >                                uae_u32 exp = sxp->ieee.exponent + scale_factor;
1973 >                                if (exp < FP_EXTENDED_EXP_BIAS - FP_DOUBLE_EXP_BIAS)
1974 >                                        exp = 0;
1975 >                                else if (exp > FP_EXTENDED_EXP_BIAS + FP_DOUBLE_EXP_BIAS)
1976 >                                        exp = FP_DOUBLE_EXP_MAX;
1977 >                                else
1978 >                                        exp += FP_DOUBLE_EXP_BIAS - FP_EXTENDED_EXP_BIAS;
1979 >                                sxp->ieee.exponent = exp;
1980 > #else
1981 >                                fp_declare_init_shape(sxp, FPU registers[reg], extended);
1982 >                                sxp->ieee.exponent += scale_factor;
1983 > #endif
1984 >                        }
1985 >                        else if (fl_source.infinity) {
1986 >                                // Returns NaN for any Infinity source
1987 >                                make_nan( FPU registers[reg] );
1988                          }
1989                          make_fpsr(FPU registers[reg]);
1990                          break;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines