|
@@ -0,0 +1,172 @@
|
|
|
+/*
|
|
|
+===============================================================================
|
|
|
+
|
|
|
+This C source file is part of the SoftFloat IEC/IEEE Floating-point
|
|
|
+Arithmetic Package, Release 2.
|
|
|
+
|
|
|
+Written by John R. Hauser. This work was made possible in part by the
|
|
|
+International Computer Science Institute, located at Suite 600, 1947 Center
|
|
|
+Street, Berkeley, California 94704. Funding was partially provided by the
|
|
|
+National Science Foundation under grant MIP-9311980. The original version
|
|
|
+of this code was written as part of a project to build a fixed-point vector
|
|
|
+processor in collaboration with the University of California at Berkeley,
|
|
|
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
|
|
|
+is available through the web page
|
|
|
+http://www.jhauser.us/arithmetic/SoftFloat-2b/SoftFloat-source.txt
|
|
|
+
|
|
|
+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 three paragraphs for those parts of
|
|
|
+this code that are retained.
|
|
|
+
|
|
|
+===============================================================================
|
|
|
+*/
|
|
|
+
|
|
|
+#include <asm/div64.h>
|
|
|
+
|
|
|
+#include "fpa11.h"
|
|
|
+//#include "milieu.h"
|
|
|
+//#include "softfloat.h"
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Primitive arithmetic functions, including multi-word arithmetic, and
|
|
|
+division and square root approximations. (Can be specialized to target if
|
|
|
+desired.)
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+#include "softfloat-macros"
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Functions and definitions to determine: (1) whether tininess for underflow
|
|
|
+is detected before or after rounding by default, (2) what (if anything)
|
|
|
+happens when exceptions are raised, (3) how signaling NaNs are distinguished
|
|
|
+from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
|
|
|
+are propagated from function inputs to output. These details are target-
|
|
|
+specific.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+#include "softfloat-specialize"
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
|
|
|
+and 7, and returns the properly rounded 32-bit integer corresponding to the
|
|
|
+input. If `zSign' is nonzero, the input is negated before being converted
|
|
|
+to an integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point
|
|
|
+input is simply rounded to an integer, with the inexact exception raised if
|
|
|
+the input cannot be represented exactly as an integer. If the fixed-point
|
|
|
+input is too large, however, the invalid exception is raised and the largest
|
|
|
+positive or negative integer is returned.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+static int32 roundAndPackInt32( struct roundingData *roundData, flag zSign, bits64 absZ )
|
|
|
+{
|
|
|
+ int8 roundingMode;
|
|
|
+ flag roundNearestEven;
|
|
|
+ int8 roundIncrement, roundBits;
|
|
|
+ int32 z;
|
|
|
+
|
|
|
+ roundingMode = roundData->mode;
|
|
|
+ roundNearestEven = ( roundingMode == float_round_nearest_even );
|
|
|
+ roundIncrement = 0x40;
|
|
|
+ if ( ! roundNearestEven ) {
|
|
|
+ if ( roundingMode == float_round_to_zero ) {
|
|
|
+ roundIncrement = 0;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ roundIncrement = 0x7F;
|
|
|
+ if ( zSign ) {
|
|
|
+ if ( roundingMode == float_round_up ) roundIncrement = 0;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if ( roundingMode == float_round_down ) roundIncrement = 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ roundBits = absZ & 0x7F;
|
|
|
+ absZ = ( absZ + roundIncrement )>>7;
|
|
|
+ absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
|
|
|
+ z = absZ;
|
|
|
+ if ( zSign ) z = - z;
|
|
|
+ if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
|
|
|
+ roundData->exception |= float_flag_invalid;
|
|
|
+ return zSign ? 0x80000000 : 0x7FFFFFFF;
|
|
|
+ }
|
|
|
+ if ( roundBits ) roundData->exception |= float_flag_inexact;
|
|
|
+ return z;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Returns the fraction bits of the single-precision floating-point value `a'.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+INLINE bits32 extractFloat32Frac( float32 a )
|
|
|
+{
|
|
|
+
|
|
|
+ return a & 0x007FFFFF;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Returns the exponent bits of the single-precision floating-point value `a'.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+INLINE int16 extractFloat32Exp( float32 a )
|
|
|
+{
|
|
|
+
|
|
|
+ return ( a>>23 ) & 0xFF;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Returns the sign bit of the single-precision floating-point value `a'.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+#if 0 /* in softfloat.h */
|
|
|
+INLINE flag extractFloat32Sign( float32 a )
|
|
|
+{
|
|
|
+
|
|
|
+ return a>>31;
|
|
|
+
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Normalizes the subnormal single-precision floating-point value represented
|
|
|
+by the denormalized significand `aSig'. The normalized exponent and
|
|
|
+significand are stored at the locations pointed to by `zExpPtr' and
|
|
|
+`zSigPtr', respectively.
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+*/
|
|
|
+static void
|
|
|
+ normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr )
|
|
|
+{
|
|
|
+ int8 shiftCount;
|
|
|
+
|
|
|
+ shiftCount = countLeadingZeros32( aSig ) - 8;
|
|
|
+ *zSigPtr = aSig<<shiftCount;
|
|
|
+ *zExpPtr = 1 - shiftCount;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+/*
|
|
|
+-------------------------------------------------------------------------------
|
|
|
+Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
|
|
|
+single-precision floating-point value, returning the result. After being
|
|
|
+shifted into the proper positions, the three fields are simply added
|
|
|
+together to form the result. This means that any integer portion of `zSig'
|
|
|
+will be added into the exponent. Since a properly normalized significand
|
|
|
+will have an integer portion equal to 1, the `zExp' input should be 1 less
|