Date: Sat, 24 Apr 2010 12:11:42 +0000 (UTC) From: Marius Strobl <marius@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r207151 - in head/tools/test: . testfloat testfloat/sparc64 Message-ID: <201004241211.o3OCBgXD027190@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: marius Date: Sat Apr 24 12:11:41 2010 New Revision: 207151 URL: http://svn.freebsd.org/changeset/base/207151 Log: Add a TestFloat based test suite for floating-point implementations currently supporting sparc64. After a `make depend all` there are three programs; testsoftfloat for testing against the SoftFloat in src/lib/libc/softfloat for reference purposes, testemufloat for testing the emulator source in src/lib/libc/sparc64/fpu and testfloat for testing with the installed libc. Support for other architectures can be added as needed. PR: 144900 Submitted by: Peter Jeremy Added: head/tools/test/testfloat/ head/tools/test/testfloat/README.txt - copied unchanged from r207134, vendor/testfloat/dist/testfloat/README.txt head/tools/test/testfloat/fail.c - copied unchanged from r207134, vendor/testfloat/dist/testfloat/fail.c head/tools/test/testfloat/fail.h - copied unchanged from r207134, vendor/testfloat/dist/testfloat/fail.h head/tools/test/testfloat/random.c (contents, props changed) - copied, changed from r207134, vendor/testfloat/dist/testfloat/random.c head/tools/test/testfloat/random.h - copied unchanged from r207134, vendor/testfloat/dist/testfloat/random.h head/tools/test/testfloat/slowfloat-32.c - copied unchanged from r207134, vendor/testfloat/dist/testfloat/slowfloat-32.c head/tools/test/testfloat/slowfloat-64.c - copied unchanged from r207134, vendor/testfloat/dist/testfloat/slowfloat-64.c head/tools/test/testfloat/slowfloat.c - copied unchanged from r207134, vendor/testfloat/dist/testfloat/slowfloat.c head/tools/test/testfloat/slowfloat.h - copied unchanged from r207134, vendor/testfloat/dist/testfloat/slowfloat.h head/tools/test/testfloat/sparc64/ head/tools/test/testfloat/sparc64/Makefile (contents, props changed) head/tools/test/testfloat/sparc64/fpu_emul.S (contents, props changed) head/tools/test/testfloat/sparc64/fpu_reg.h (contents, props changed) head/tools/test/testfloat/sparc64/fpu_util.c (contents, props changed) head/tools/test/testfloat/sparc64/libc_private.h (contents, props changed) head/tools/test/testfloat/sparc64/milieu.h (contents, props changed) head/tools/test/testfloat/sparc64/namespace.h (contents, props changed) head/tools/test/testfloat/sparc64/softfloat.h (contents, props changed) head/tools/test/testfloat/sparc64/sparc64.h (contents, props changed) head/tools/test/testfloat/sparc64/systflags.c (contents, props changed) head/tools/test/testfloat/sparc64/systfloat.S (contents, props changed) head/tools/test/testfloat/sparc64/systfloat.h (contents, props changed) head/tools/test/testfloat/sparc64/systmodes.c (contents, props changed) head/tools/test/testfloat/sparc64/un-namespace.h (contents, props changed) head/tools/test/testfloat/systemBugs.txt - copied unchanged from r207134, vendor/testfloat/dist/testfloat/systemBugs.txt head/tools/test/testfloat/systflags.h - copied unchanged from r207134, vendor/testfloat/dist/testfloat/systflags.h head/tools/test/testfloat/systfloat.c - copied unchanged from r207134, vendor/testfloat/dist/testfloat/systfloat.c head/tools/test/testfloat/systmodes.h - copied unchanged from r207134, vendor/testfloat/dist/testfloat/systmodes.h head/tools/test/testfloat/testCases.c (contents, props changed) - copied, changed from r207134, vendor/testfloat/dist/testfloat/testCases.c head/tools/test/testfloat/testCases.h - copied unchanged from r207134, vendor/testfloat/dist/testfloat/testCases.h head/tools/test/testfloat/testFunction.c - copied unchanged from r207134, vendor/testfloat/dist/testfloat/testFunction.c head/tools/test/testfloat/testFunction.h - copied unchanged from r207134, vendor/testfloat/dist/testfloat/testFunction.h head/tools/test/testfloat/testLoops.c - copied unchanged from r207134, vendor/testfloat/dist/testfloat/testLoops.c head/tools/test/testfloat/testLoops.h - copied unchanged from r207134, vendor/testfloat/dist/testfloat/testLoops.h head/tools/test/testfloat/testfloat-history.txt - copied unchanged from r207134, vendor/testfloat/dist/testfloat/testfloat-history.txt head/tools/test/testfloat/testfloat-source.txt - copied unchanged from r207134, vendor/testfloat/dist/testfloat/testfloat-source.txt head/tools/test/testfloat/testfloat.c (contents, props changed) - copied, changed from r207134, vendor/testfloat/dist/testfloat/testfloat.c head/tools/test/testfloat/testfloat.txt - copied unchanged from r207134, vendor/testfloat/dist/testfloat/testfloat.txt head/tools/test/testfloat/testsoftfloat.c (contents, props changed) - copied, changed from r207134, vendor/testfloat/dist/testfloat/testsoftfloat.c head/tools/test/testfloat/writeHex.c - copied unchanged from r207134, vendor/testfloat/dist/testfloat/writeHex.c head/tools/test/testfloat/writeHex.h - copied unchanged from r207134, vendor/testfloat/dist/testfloat/writeHex.h Modified: head/tools/test/README Modified: head/tools/test/README ============================================================================== --- head/tools/test/README Sat Apr 24 10:22:08 2010 (r207150) +++ head/tools/test/README Sat Apr 24 12:11:41 2010 (r207151) @@ -11,3 +11,4 @@ devrandom Programs to test /dev/*random. dtrace DTrace test suite malloc A program to test and benchmark malloc(). posixshm A program to test POSIX shared memory. +testfloat Programs to test floating-point implementations Copied: head/tools/test/testfloat/README.txt (from r207134, vendor/testfloat/dist/testfloat/README.txt) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/test/testfloat/README.txt Sat Apr 24 12:11:41 2010 (r207151, copy of r207134, vendor/testfloat/dist/testfloat/README.txt) @@ -0,0 +1,50 @@ + +Package Overview for TestFloat Release 2a + +John R. Hauser +1998 December 16 + + +TestFloat is a program for testing that a floating-point implementation +conforms to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. +TestFloat is distributed in the form of C source code. The TestFloat +package actually provides two related programs: + +-- The `testfloat' program tests a system's floating-point for conformance + to the IEC/IEEE Standard. This program uses the SoftFloat software + floating-point implementation as a basis for comparison. + +-- The `testsoftfloat' program tests SoftFloat itself for conformance to + the IEC/IEEE Standard. These tests are performed by comparing against a + separate, slower software floating-point that is included in the TestFloat + package. + +TestFloat depends on SoftFloat, but SoftFloat is not included in the +TestFloat package. SoftFloat can be obtained through the Web page `http:// +HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/SoftFloat.html'. + +TestFloat is documented in three text files: + + testfloat.txt Documentation for using the TestFloat programs + (both `testfloat' and `testsoftfloat'). + testfloat-source.txt Documentation for porting and compiling TestFloat. + testfloat-history.txt History of major changes to TestFloat. + +The following file is also provided: + + systemBugs.txt Information about processor bugs found using + TestFloat. + +Other files in the package comprise the source code for TestFloat. + +Please be aware that some work is involved in porting this software to other +targets. It is not just a matter of getting `make' to complete without +error messages. I would have written the code that way if I could, but +there are fundamental differences between systems that I can't make go away. +You should not attempt to compile the TestFloat sources without first +reading `testfloat-source.txt'. + +At the time of this writing, the most up-to-date information about +TestFloat and the latest release can be found at the Web page `http:// +HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + Copied: head/tools/test/testfloat/fail.c (from r207134, vendor/testfloat/dist/testfloat/fail.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/test/testfloat/fail.c Sat Apr 24 12:11:41 2010 (r207151, copy of r207134, vendor/testfloat/dist/testfloat/fail.c) @@ -0,0 +1,46 @@ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +#include <stdlib.h> +#include <stdarg.h> +#include <stdio.h> +#include "milieu.h" +#include "fail.h" + +char *fail_programName = ""; + +void fail( const char *message, ... ) +{ + va_list varArgs; + + fprintf( stderr, "%s: ", fail_programName ); + va_start( varArgs, message ); + vfprintf( stderr, message, varArgs ); + va_end( varArgs ); + fputs( ".\n", stderr ); + exit( EXIT_FAILURE ); + +} + Copied: head/tools/test/testfloat/fail.h (from r207134, vendor/testfloat/dist/testfloat/fail.h) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/test/testfloat/fail.h Sat Apr 24 12:11:41 2010 (r207151, copy of r207134, vendor/testfloat/dist/testfloat/fail.h) @@ -0,0 +1,29 @@ + +/* +=============================================================================== + +This C header file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +extern char *fail_programName; + +void fail( const char *, ... ); + Copied and modified: head/tools/test/testfloat/random.c (from r207134, vendor/testfloat/dist/testfloat/random.c) ============================================================================== --- vendor/testfloat/dist/testfloat/random.c Fri Apr 23 19:48:31 2010 (r207134, copy source) +++ head/tools/test/testfloat/random.c Sat Apr 24 12:11:41 2010 (r207151) @@ -23,6 +23,9 @@ this code that are retained. =============================================================================== */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + #include <stdlib.h> #include "milieu.h" #include "random.h" @@ -30,26 +33,21 @@ this code that are retained. uint8 randomUint8( void ) { - return (bits8) ( rand()>>4 ); + return (bits8) ( random()>>4 ); } uint16 randomUint16( void ) { - return ( ( rand() & 0x0FF0 )<<4 ) | ( ( rand()>>4 ) & 0xFF ); + return ( random() & 0x0000ffff ); } uint32 randomUint32( void ) { - return - ( ( (uint32) ( rand() & 0x0FF0 ) )<<20 ) - | ( ( (uint32) ( rand() & 0x0FF0 ) )<<12 ) - | ( ( rand() & 0x0FF0 )<<4 ) - | ( ( rand()>>4 ) & 0xFF ); - + return ( ( (uint32) random()<<16) | ( (uint32) random() & 0x0000ffff) ); } #ifdef BITS64 Copied: head/tools/test/testfloat/random.h (from r207134, vendor/testfloat/dist/testfloat/random.h) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/test/testfloat/random.h Sat Apr 24 12:11:41 2010 (r207151, copy of r207134, vendor/testfloat/dist/testfloat/random.h) @@ -0,0 +1,32 @@ + +/* +=============================================================================== + +This C header file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +uint8 randomUint8( void ); +uint16 randomUint16( void ); +uint32 randomUint32( void ); +#ifdef BITS64 +uint64 randomUint64( void ); +#endif + Copied: head/tools/test/testfloat/slowfloat-32.c (from r207134, vendor/testfloat/dist/testfloat/slowfloat-32.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/tools/test/testfloat/slowfloat-32.c Sat Apr 24 12:11:41 2010 (r207151, copy of r207134, vendor/testfloat/dist/testfloat/slowfloat-32.c) @@ -0,0 +1,1183 @@ + +/* +=============================================================================== + +This C source file is part of TestFloat, Release 2a, a package of programs +for testing the correctness of floating-point arithmetic complying to the +IEC/IEEE Standard for Floating-Point. + +Written by John R. Hauser. More information is available through the Web +page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY +AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + +Derivative works are acceptable, even for commercial purposes, so long as +(1) they include prominent notice that the work is derivative, and (2) they +include prominent notice akin to these four paragraphs for those parts of +this code that are retained. + +=============================================================================== +*/ + +int8 slow_float_rounding_mode; +int8 slow_float_exception_flags; +int8 slow_float_detect_tininess; + +typedef struct { + bits32 a0, a1; +} bits64X; + +typedef struct { + flag isNaN; + flag isInf; + flag isZero; + flag sign; + int16 exp; + bits64X sig; +} floatX; + +static const floatX floatXNaN = { TRUE, FALSE, FALSE, FALSE, 0, { 0, 0 } }; +static const floatX floatXPositiveZero = + { FALSE, FALSE, TRUE, FALSE, 0, { 0, 0 } }; +static const floatX floatXNegativeZero = + { FALSE, FALSE, TRUE, TRUE, 0, { 0, 0 } }; + +static bits64X shortShift64Left( bits64X a, int8 shiftCount ) +{ + int8 negShiftCount; + + negShiftCount = ( - shiftCount & 31 ); + a.a0 = ( a.a0<<shiftCount ) | ( a.a1>>negShiftCount ); + a.a1 <<= shiftCount; + return a; + +} + +static bits64X shortShift64RightJamming( bits64X a, int8 shiftCount ) +{ + int8 negShiftCount; + bits32 extra; + + negShiftCount = ( - shiftCount & 31 ); + extra = a.a1<<negShiftCount; + a.a1 = ( a.a0<<negShiftCount ) | ( a.a1>>shiftCount ) | ( extra != 0 ); + a.a0 >>= shiftCount; + return a; + +} + +static bits64X neg64( bits64X a ) +{ + + if ( a.a1 == 0 ) { + a.a0 = - a.a0; + } + else { + a.a1 = - a.a1; + a.a0 = ~ a.a0; + } + return a; + +} + +static bits64X add64( bits64X a, bits64X b ) +{ + + a.a1 += b.a1; + a.a0 += b.a0 + ( a.a1 < b.a1 ); + return a; + +} + +static flag eq64( bits64X a, bits64X b ) +{ + + return ( a.a0 == b.a0 ) && ( a.a1 == b.a1 ); + +} + +static flag le64( bits64X a, bits64X b ) +{ + + return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 <= b.a1 ) ); + +} + +static flag lt64( bits64X a, bits64X b ) +{ + + return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 < b.a1 ) ); + +} + +static floatX roundFloatXTo24( flag isTiny, floatX zx ) +{ + + if ( zx.sig.a1 ) { + slow_float_exception_flags |= float_flag_inexact; + if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + if ( zx.sig.a1 < 0x80000000 ) goto noIncrement; + if ( ( zx.sig.a1 == 0x80000000 ) && ! ( zx.sig.a0 & 1 ) ) { + goto noIncrement; + } + break; + case float_round_to_zero: + goto noIncrement; + case float_round_down: + if ( ! zx.sign ) goto noIncrement; + break; + case float_round_up: + if ( zx.sign ) goto noIncrement; + break; + } + ++zx.sig.a0; + if ( zx.sig.a0 == 0x01000000 ) { + zx.sig.a0 = 0x00800000; + ++zx.exp; + } + } + noIncrement: + zx.sig.a1 = 0; + return zx; + +} + +static floatX roundFloatXTo53( flag isTiny, floatX zx ) +{ + int8 roundBits; + + roundBits = zx.sig.a1 & 7; + zx.sig.a1 -= roundBits; + if ( roundBits ) { + slow_float_exception_flags |= float_flag_inexact; + if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + if ( roundBits < 4 ) goto noIncrement; + if ( ( roundBits == 4 ) && ! ( zx.sig.a1 & 8 ) ) goto noIncrement; + break; + case float_round_to_zero: + goto noIncrement; + case float_round_down: + if ( ! zx.sign ) goto noIncrement; + break; + case float_round_up: + if ( zx.sign ) goto noIncrement; + break; + } + zx.sig.a1 += 8; + zx.sig.a0 += ( zx.sig.a1 == 0 ); + if ( zx.sig.a0 == 0x01000000 ) { + zx.sig.a0 = 0x00800000; + ++zx.exp; + } + } + noIncrement: + return zx; + +} + +static floatX int32ToFloatX( int32 a ) +{ + floatX ax; + + ax.isNaN = FALSE; + ax.isInf = FALSE; + ax.sign = ( a < 0 ); + ax.sig.a1 = ax.sign ? - a : a; + ax.sig.a0 = 0; + if ( a == 0 ) { + ax.isZero = TRUE; + return ax; + } + ax.isZero = FALSE; + ax.sig = shortShift64Left( ax.sig, 23 ); + ax.exp = 32; + while ( ax.sig.a0 < 0x00800000 ) { + ax.sig = shortShift64Left( ax.sig, 1 ); + --ax.exp; + } + return ax; + +} + +static int32 floatXToInt32( floatX ax ) +{ + int8 savedExceptionFlags; + int16 shiftCount; + int32 z; + + if ( ax.isInf || ax.isNaN ) { + slow_float_exception_flags |= float_flag_invalid; + return ( ax.isInf & ax.sign ) ? 0x80000000 : 0x7FFFFFFF; + } + if ( ax.isZero ) return 0; + savedExceptionFlags = slow_float_exception_flags; + shiftCount = 52 - ax.exp; + if ( 56 < shiftCount ) { + ax.sig.a1 = 1; + ax.sig.a0 = 0; + } + else { + while ( 0 < shiftCount ) { + ax.sig = shortShift64RightJamming( ax.sig, 1 ); + --shiftCount; + } + } + ax = roundFloatXTo53( FALSE, ax ); + ax.sig = shortShift64RightJamming( ax.sig, 3 ); + z = ax.sig.a1; + if ( ax.sign ) z = - z; + if ( ( shiftCount < 0 ) + || ax.sig.a0 + || ( ( z != 0 ) && ( ( ax.sign ^ ( z < 0 ) ) != 0 ) ) + ) { + slow_float_exception_flags = savedExceptionFlags | float_flag_invalid; + return ax.sign ? 0x80000000 : 0x7FFFFFFF; + } + return z; + +} + +static floatX float32ToFloatX( float32 a ) +{ + int16 expField; + floatX ax; + + ax.isNaN = FALSE; + ax.isInf = FALSE; + ax.isZero = FALSE; + ax.sign = ( ( a & 0x80000000 ) != 0 ); + expField = ( a>>23 ) & 0xFF; + ax.sig.a1 = 0; + ax.sig.a0 = a & 0x007FFFFF; + if ( expField == 0 ) { + if ( ax.sig.a0 == 0 ) { + ax.isZero = TRUE; + } + else { + expField = 1 - 0x7F; + do { + ax.sig.a0 <<= 1; + --expField; + } while ( ax.sig.a0 < 0x00800000 ); + ax.exp = expField; + } + } + else if ( expField == 0xFF ) { + if ( ax.sig.a0 == 0 ) { + ax.isInf = TRUE; + } + else { + ax.isNaN = TRUE; + } + } + else { + ax.sig.a0 |= 0x00800000; + ax.exp = expField - 0x7F; + } + return ax; + +} + +static float32 floatXToFloat32( floatX zx ) +{ + floatX savedZ; + flag isTiny; + int16 expField; + float32 z; + + if ( zx.isZero ) return zx.sign ? 0x80000000 : 0; + if ( zx.isInf ) return zx.sign ? 0xFF800000 : 0x7F800000; + if ( zx.isNaN ) return 0xFFFFFFFF; + while ( 0x01000000 <= zx.sig.a0 ) { + zx.sig = shortShift64RightJamming( zx.sig, 1 ); + ++zx.exp; + } + while ( zx.sig.a0 < 0x00800000 ) { + zx.sig = shortShift64Left( zx.sig, 1 ); + --zx.exp; + } + savedZ = zx; + isTiny = + ( slow_float_detect_tininess == float_tininess_before_rounding ) + && ( zx.exp + 0x7F <= 0 ); + zx = roundFloatXTo24( isTiny, zx ); + expField = zx.exp + 0x7F; + if ( 0xFF <= expField ) { + slow_float_exception_flags |= + float_flag_overflow | float_flag_inexact; + if ( zx.sign ) { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_down: + z = 0xFF800000; + break; + case float_round_to_zero: + case float_round_up: + z = 0xFF7FFFFF; + break; + } + } + else { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_up: + z = 0x7F800000; + break; + case float_round_to_zero: + case float_round_down: + z = 0x7F7FFFFF; + break; + } + } + return z; + } + if ( expField <= 0 ) { + isTiny = TRUE; + zx = savedZ; + expField = zx.exp + 0x7F; + if ( expField < -27 ) { + zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); + zx.sig.a0 = 0; + } + else { + while ( expField <= 0 ) { + zx.sig = shortShift64RightJamming( zx.sig, 1 ); + ++expField; + } + } + zx = roundFloatXTo24( isTiny, zx ); + expField = ( 0x00800000 <= zx.sig.a0 ) ? 1 : 0; + } + z = expField; + z <<= 23; + if ( zx.sign ) z |= 0x80000000; + z |= zx.sig.a0 & 0x007FFFFF; + return z; + +} + +static floatX float64ToFloatX( float64 a ) +{ + int16 expField; + floatX ax; + + ax.isNaN = FALSE; + ax.isInf = FALSE; + ax.isZero = FALSE; +#ifdef BITS64 + ax.sign = ( ( a & LIT64( 0x8000000000000000 ) ) != 0 ); + expField = ( a>>52 ) & 0x7FF; + ax.sig.a1 = a; + ax.sig.a0 = ( a>>32 ) & 0x000FFFFF; +#else + ax.sign = ( ( a.high & 0x80000000 ) != 0 ); + expField = ( a.high>>( 52 - 32 ) ) & 0x7FF; + ax.sig.a1 = a.low; + ax.sig.a0 = a.high & 0x000FFFFF; +#endif + if ( expField == 0 ) { + if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) { + ax.isZero = TRUE; + } + else { + expField = 1 - 0x3FF; + do { + ax.sig = shortShift64Left( ax.sig, 1 ); + --expField; + } while ( ax.sig.a0 < 0x00100000 ); + ax.exp = expField; + } + } + else if ( expField == 0x7FF ) { + if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) { + ax.isInf = TRUE; + } + else { + ax.isNaN = TRUE; + } + } + else { + ax.exp = expField - 0x3FF; + ax.sig.a0 |= 0x00100000; + } + ax.sig = shortShift64Left( ax.sig, 3 ); + return ax; + +} + +static float64 floatXToFloat64( floatX zx ) +{ + floatX savedZ; + flag isTiny; + int16 expField; + float64 z; + +#ifdef BITS64 + if ( zx.isZero ) return zx.sign ? LIT64( 0x8000000000000000 ) : 0; + if ( zx.isInf ) { + return + zx.sign ? LIT64( 0xFFF0000000000000 ) + : LIT64( 0x7FF0000000000000 ); + } + if ( zx.isNaN ) return LIT64( 0xFFFFFFFFFFFFFFFF ); +#else + if ( zx.isZero ) { + z.low = 0; + z.high = zx.sign ? 0x80000000 : 0; + return z; + } + if ( zx.isInf ) { + z.low = 0; + z.high = zx.sign ? 0xFFF00000 : 0x7FF00000; + return z; + } + if ( zx.isNaN ) { + z.high = z.low = 0xFFFFFFFF; + return z; + } +#endif + while ( 0x01000000 <= zx.sig.a0 ) { + zx.sig = shortShift64RightJamming( zx.sig, 1 ); + ++zx.exp; + } + while ( zx.sig.a0 < 0x00800000 ) { + zx.sig = shortShift64Left( zx.sig, 1 ); + --zx.exp; + } + savedZ = zx; + isTiny = + ( slow_float_detect_tininess == float_tininess_before_rounding ) + && ( zx.exp + 0x3FF <= 0 ); + zx = roundFloatXTo53( isTiny, zx ); + expField = zx.exp + 0x3FF; + if ( 0x7FF <= expField ) { + slow_float_exception_flags |= + float_flag_overflow | float_flag_inexact; +#ifdef BITS64 + if ( zx.sign ) { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_down: + z = LIT64( 0xFFF0000000000000 ); + break; + case float_round_to_zero: + case float_round_up: + z = LIT64( 0xFFEFFFFFFFFFFFFF ); + break; + } + } + else { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_up: + z = LIT64( 0x7FF0000000000000 ); + break; + case float_round_to_zero: + case float_round_down: + z = LIT64( 0x7FEFFFFFFFFFFFFF ); + break; + } + } +#else + if ( zx.sign ) { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_down: + z.low = 0; + z.high = 0xFFF00000; + break; + case float_round_to_zero: + case float_round_up: + z.low = 0xFFFFFFFF; + z.high = 0xFFEFFFFF; + break; + } + } + else { + switch ( slow_float_rounding_mode ) { + case float_round_nearest_even: + case float_round_up: + z.low = 0; + z.high = 0x7FF00000; + break; + case float_round_to_zero: + case float_round_down: + z.low = 0xFFFFFFFF; + z.high = 0x7FEFFFFF; + break; + } + } +#endif + return z; + } + if ( expField <= 0 ) { + isTiny = TRUE; + zx = savedZ; + expField = zx.exp + 0x3FF; + if ( expField < -56 ) { + zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); + zx.sig.a0 = 0; + } + else { + while ( expField <= 0 ) { + zx.sig = shortShift64RightJamming( zx.sig, 1 ); + ++expField; + } + } + zx = roundFloatXTo53( isTiny, zx ); + expField = ( 0x00800000 <= zx.sig.a0 ) ? 1 : 0; + } + zx.sig = shortShift64RightJamming( zx.sig, 3 ); +#ifdef BITS64 + z = expField; + z <<= 52; + if ( zx.sign ) z |= LIT64( 0x8000000000000000 ); + z |= ( ( (bits64) ( zx.sig.a0 & 0x000FFFFF ) )<<32 ) | zx.sig.a1; +#else + z.low = zx.sig.a1; + z.high = expField; + z.high <<= 52 - 32; + if ( zx.sign ) z.high |= 0x80000000; + z.high |= zx.sig.a0 & 0x000FFFFF; +#endif + return z; + +} + +static floatX floatXInvalid( void ) +{ + + slow_float_exception_flags |= float_flag_invalid; + return floatXNaN; + +} + +static floatX floatXRoundToInt( floatX ax ) +{ + int16 shiftCount, i; + + if ( ax.isNaN || ax.isInf ) return ax; + shiftCount = 52 - ax.exp; + if ( shiftCount <= 0 ) return ax; + if ( 55 < shiftCount ) { + ax.exp = 52; + ax.sig.a1 = ! ax.isZero; + ax.sig.a0 = 0; + } + else { + while ( 0 < shiftCount ) { + ax.sig = shortShift64RightJamming( ax.sig, 1 ); + ++ax.exp; + --shiftCount; + } + } + ax = roundFloatXTo53( FALSE, ax ); + if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE; + return ax; + +} + +static floatX floatXAdd( floatX ax, floatX bx ) +{ + int16 expDiff; + floatX zx; + + if ( ax.isNaN ) return ax; + if ( bx.isNaN ) return bx; + if ( ax.isInf && bx.isInf ) { + if ( ax.sign == bx.sign ) return ax; + return floatXInvalid(); + } + if ( ax.isInf ) return ax; + if ( bx.isInf ) return bx; + if ( ax.isZero && bx.isZero ) { + if ( ax.sign == bx.sign ) return ax; + goto completeCancellation; + } + if ( ( ax.sign != bx.sign ) + && ( ax.exp == bx.exp ) + && eq64( ax.sig, bx.sig ) + ) { + completeCancellation: + return + ( slow_float_rounding_mode == float_round_down ) ? + floatXNegativeZero + : floatXPositiveZero; + } + if ( ax.isZero ) return bx; + if ( bx.isZero ) return ax; + expDiff = ax.exp - bx.exp; + if ( expDiff < 0 ) { + zx = ax; + zx.exp = bx.exp; + if ( expDiff < -56 ) { + zx.sig.a1 = 1; + zx.sig.a0 = 0; + } + else { + while ( expDiff < 0 ) { + zx.sig = shortShift64RightJamming( zx.sig, 1 ); + ++expDiff; + } + } + if ( ax.sign != bx.sign ) zx.sig = neg64( zx.sig ); + zx.sign = bx.sign; + zx.sig = add64( zx.sig, bx.sig ); + } + else { + zx = bx; + zx.exp = ax.exp; + if ( 56 < expDiff ) { + zx.sig.a1 = 1; + zx.sig.a0 = 0; + } + else { + while ( 0 < expDiff ) { + zx.sig = shortShift64RightJamming( zx.sig, 1 ); + --expDiff; + } + } + if ( ax.sign != bx.sign ) zx.sig = neg64( zx.sig ); + zx.sign = ax.sign; + zx.sig = add64( zx.sig, ax.sig ); + } + if ( zx.sig.a0 & 0x80000000 ) { + zx.sig = neg64( zx.sig ); + zx.sign = ! zx.sign; + } + return zx; + +} + +static floatX floatXMul( floatX ax, floatX bx ) +{ + int8 bitNum; + floatX zx; + + if ( ax.isNaN ) return ax; + if ( bx.isNaN ) return bx; + if ( ax.isInf ) { + if ( bx.isZero ) return floatXInvalid(); + if ( bx.sign ) ax.sign = ! ax.sign; + return ax; + } + if ( bx.isInf ) { + if ( ax.isZero ) return floatXInvalid(); + if ( ax.sign ) bx.sign = ! bx.sign; + return bx; + } + zx = ax; + zx.sign ^= bx.sign; + if ( ax.isZero || bx.isZero ) { + return zx.sign ? floatXNegativeZero : floatXPositiveZero; + } + zx.exp += bx.exp + 1; + zx.sig.a1 = 0; + zx.sig.a0 = 0; + for ( bitNum = 0; bitNum < 55; ++bitNum ) { + if ( bx.sig.a1 & 2 ) zx.sig = add64( zx.sig, ax.sig ); + bx.sig = shortShift64RightJamming( bx.sig, 1 ); + zx.sig = shortShift64RightJamming( zx.sig, 1 ); + } + return zx; + +} + +static floatX floatXDiv( floatX ax, floatX bx ) +{ + bits64X negBSig; + int8 bitNum; + floatX zx; + + if ( ax.isNaN ) return ax; + if ( bx.isNaN ) return bx; + if ( ax.isInf ) { + if ( bx.isInf ) return floatXInvalid(); + if ( bx.sign ) ax.sign = ! ax.sign; + return ax; + } + if ( bx.isZero ) { + if ( ax.isZero ) return floatXInvalid(); + slow_float_exception_flags |= float_flag_divbyzero; + if ( ax.sign ) bx.sign = ! bx.sign; + bx.isZero = FALSE; + bx.isInf = TRUE; + return bx; + } + zx = ax; + zx.sign ^= bx.sign; + if ( ax.isZero || bx.isInf ) { + return zx.sign ? floatXNegativeZero : floatXPositiveZero; + } + zx.exp -= bx.exp + 1; + zx.sig.a1 = 0; + zx.sig.a0 = 0; + negBSig = neg64( bx.sig ); + for ( bitNum = 0; bitNum < 56; ++bitNum ) { + if ( le64( bx.sig, ax.sig ) ) { + zx.sig.a1 |= 1; + ax.sig = add64( ax.sig, negBSig ); + } + ax.sig = shortShift64Left( ax.sig, 1 ); + zx.sig = shortShift64Left( zx.sig, 1 ); + } + if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1; + return zx; + +} + +static floatX floatXRem( floatX ax, floatX bx ) +{ + bits64X negBSig; + flag lastQuotientBit; + bits64X savedASig; + + if ( ax.isNaN ) return ax; + if ( bx.isNaN ) return bx; + if ( ax.isInf || bx.isZero ) return floatXInvalid(); + if ( ax.isZero || bx.isInf ) return ax; + --bx.exp; + if ( ax.exp < bx.exp ) return ax; + bx.sig = shortShift64Left( bx.sig, 1 ); + negBSig = neg64( bx.sig ); + while ( bx.exp < ax.exp ) { + if ( le64( bx.sig, ax.sig ) ) ax.sig = add64( ax.sig, negBSig ); + ax.sig = shortShift64Left( ax.sig, 1 ); + --ax.exp; + } + lastQuotientBit = le64( bx.sig, ax.sig ); + if ( lastQuotientBit ) ax.sig = add64( ax.sig, negBSig ); + savedASig = ax.sig; + ax.sig = neg64( add64( ax.sig, negBSig ) ); + if ( lt64( ax.sig, savedASig ) ) { + ax.sign = ! ax.sign; + } + else if ( lt64( savedASig, ax.sig ) ) { + ax.sig = savedASig; + } + else { + if ( lastQuotientBit ) { + ax.sign = ! ax.sign; + } + else { + ax.sig = savedASig; + } + } + if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE; + return ax; + +} + +static floatX floatXSqrt( floatX ax ) *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201004241211.o3OCBgXD027190>