palm-os-sdk/sdk-4/include/Core/System/FloatMgr.h
2016-08-25 07:53:48 -03:00

525 lines
18 KiB
C

/******************************************************************************
*
* Copyright (c) 1996-2000 Palm, Inc. or its subsidiaries.
* All rights reserved.
*
* File: FloatMgr.h
*
* Release: Palm OS SDK 4.0 (63220)
*
* Description:
* New Floating point routines, provided by new IEEE arithmetic
* 68K software floating point emulator (sfpe) code.
*
* History:
* 9/23/96 - Created by SCL
* 11/15/96 - First build of NewFloatMgr.lib
* 11/26/96 - Added FlpCorrectedAdd and FlpCorrectedSub routines
* 12/30/96 - Added FlpVersion routine
* 2/ 4/97 - Fixed FlpDoubleBits definition - sign & exp now Int32s
* so total size of FlpCompDouble is 64 bits, not 96.
* 2/ 5/97 - Added note about FlpBase10Info reporting "negative" zero.
* 7/21/99 - Renamed NewFloatMgr.h to FloatMgr.h.
*
*****************************************************************************/
#ifndef __FLOATMGR_H__
#define __FLOATMGR_H__
#if defined(__MC68K__)
#if __option(IEEEdoubles) == off
//#error "IEEEdoubles ('8-UInt8 Doubles' option in the 68K Processor preference panel) MUST be on!!"
#pragma IEEEdoubles on // force 8-byte doubles for our initialization!!
#endif
#endif
#ifndef _DONT_USE_FP_TRAPS_
#if EMULATION_LEVEL != EMULATION_NONE
#define _DONT_USE_FP_TRAPS_ 1 // always direct link to FP for emulator builds
#endif
#endif
#include <PalmTypes.h>
#include <CoreTraps.h>
/************************************************************************
* Differences between FloatMgr (PalmOS v1.0) and (this) NewFloatMgr
***********************************************************************/
//
// FloatMgr (PalmOS v1.0) NewFloatMgr
// ---------------------- ---------------------------------------------
// FloatType (64-bits) use FlpFloat (32-bits) or FlpDouble (64-bits)
//
// fplErrOutOfRange use _fp_get_fpscr() to retrieve errors
//
// FplInit() not necessary
// FplFree() not necessary
//
// FplFToA() use FlpFToA()
// FplAToF() use FlpAToF()
// FplBase10Info() use FlpBase10Info() [*signP returns sign BIT: 1 if negative]
//
// FplLongToFloat() use _f_itof() or _d_itod()
// FplFloatToLong() use _f_ftoi() or _d_dtoi()
// FplFloatToULong() use _f_ftou() or _d_dtou()
//
// FplMul() use _f_mul() or _d_mul()
// FplAdd() use _f_add() or _d_add()
// FplSub() use _f_sub() or _d_sub()
// FplDiv() use _f_div() or _d_div()
/************************************************************************
* New Floating point manager constants
***********************************************************************/
#define flpVersion 0x02008000 // first version of NewFloatMgr (PalmOS 2.0)
/*
* These constants are passed to and received from the _fp_round routine.
*/
#define flpToNearest 0
#define flpTowardZero 1
#define flpUpward 3
#define flpDownward 2
#define flpModeMask 0x00000030
#define flpModeShift 4
/*
* These masks define the fpscr bits supported by the sfpe (software floating point emulator).
* These constants are used with the _fp_get_fpscr and _fp_set_fpscr routines.
*/
#define flpInvalid 0x00008000
#define flpOverflow 0x00004000
#define flpUnderflow 0x00002000
#define flpDivByZero 0x00001000
#define flpInexact 0x00000800
/*
* These constants are returned by _d_cmp, _d_cmpe, _f_cmp, and _f_cmpe:
*/
#define flpEqual 0
#define flpLess 1
#define flpGreater 2
#define flpUnordered 3
/************************************************************************
* New Floating point manager types (private)
***********************************************************************/
typedef struct {
Int32 high;
Int32 low;
} _sfpe_64_bits; // for internal use only
typedef _sfpe_64_bits sfpe_long_long; // for internal use only
typedef _sfpe_64_bits sfpe_unsigned_long_long; // for internal use only
/************************************************************************
* New Floating point manager types (public)
***********************************************************************/
typedef Int32 FlpFloat;
typedef _sfpe_64_bits FlpDouble;
typedef _sfpe_64_bits FlpLongDouble;
/*
* A double value comprises the fields:
* 0x80000000 0x00000000 -- sign bit (1 for negative)
* 0x7ff00000 0x00000000 -- exponent, biased by 0x3ff == 1023
* 0x000fffff 0xffffffff -- significand == the fraction after an implicit "1."
* So a double has the mathematical form:
* (-1)^sign_bit * 2^(exponent - bias) * 1.significand
* What follows are some structures (and macros) useful for decomposing numbers.
*/
typedef struct {
UInt32 sign : 1;
Int32 exp : 11;
UInt32 manH : 20;
UInt32 manL;
} FlpDoubleBits; // for accessing specific fields
typedef union {
double d; // for easy assignment of values
FlpDouble fd; // for calling New Floating point manager routines
UInt32 ul[2]; // for accessing upper and lower longs
FlpDoubleBits fdb; // for accessing specific fields
} FlpCompDouble;
typedef union {
float f; // for easy assignment of values
FlpFloat ff; // for calling New Floating point manager routines
UInt32 ul; // for accessing bits of the float
} FlpCompFloat;
/************************************************************************
* Useful macros...
***********************************************************************/
#define BIG_ENDIAN 1
#define __FIRST32(x) *((UInt32 *) &x)
#define __SECOND32(x) *((UInt32 *) &x + 1)
#define __ALL32(x) *((UInt32 *) &x)
#ifdef LITTLE_ENDIAN
#define __LO32(x) *((UInt32 *) &x)
#define __HI32(x) *((UInt32 *) &x + 1)
#define __HIX 1
#define __LOX 0
#else
#define __HI32(x) *((UInt32 *) &x)
#define __LO32(x) *((UInt32 *) &x + 1)
#define __HIX 0
#define __LOX 1
#endif
#define FlpGetSign(x) ((__HI32(x) & 0x80000000) != 0)
#define FlpIsZero(x) ( ((__HI32(x) & 0x7fffffff) | (__LO32(x))) == 0)
#define FlpGetExponent(x) (((__HI32(x) & 0x7ff00000) >> 20) - 1023)
#define FlpNegate(x) (((FlpCompDouble *)&x)->ul[__HIX] ^= 0x80000000)
#define FlpSetNegative(x) (((FlpCompDouble *)&x)->ul[__HIX] |= 0x80000000)
#define FlpSetPositive(x) (((FlpCompDouble *)&x)->ul[__HIX] &= ~0x80000000)
/*******************************************************************
* New Floating point manager errors
* The constant fplErrorClass is defined in SystemMgr.h
*******************************************************************/
#define flpErrOutOfRange (flpErrorClass | 1)
/************************************************************
* New Floating point manager trap macros
*************************************************************/
#if _DONT_USE_FP_TRAPS_
#define FLOAT_TRAP(floatSelectorNum)
#define FLOAT_EM_TRAP(floatSelectorNum)
#else
#define FLOAT_TRAP(sel) \
_SYSTEM_API(_CALL_WITH_SELECTOR)(_SYSTEM_TABLE, sysTrapFlpDispatch, sel)
#define FLOAT_EM_TRAP(sel) \
_SYSTEM_API(_CALL_WITH_SELECTOR)(_SYSTEM_TABLE, sysTrapFlpEmDispatch, sel)
#endif
/************************************************************
* New Floating point manager selectors
*************************************************************/
// The order of these #defines *MUST* match the
// corresponding table in NewFloatDispatch.c
#define sysFloatBase10Info 0
#define sysFloatFToA 1
#define sysFloatAToF 2
#define sysFloatCorrectedAdd 3
#define sysFloatCorrectedSub 4
#define sysFloatVersion 5
// used by NewFloatDispatch.c
#define flpMaxFloatSelector sysFloatVersion
// The order of these #defines *MUST* match the
// corresponding table in NewFloatDispatch.c
#define sysFloatEm_fp_round 0
#define sysFloatEm_fp_get_fpscr 1
#define sysFloatEm_fp_set_fpscr 2
#define sysFloatEm_f_utof 3
#define sysFloatEm_f_itof 4
#define sysFloatEm_f_ulltof 5
#define sysFloatEm_f_lltof 6
#define sysFloatEm_d_utod 7
#define sysFloatEm_d_itod 8
#define sysFloatEm_d_ulltod 9
#define sysFloatEm_d_lltod 10
#define sysFloatEm_f_ftod 11
#define sysFloatEm_d_dtof 12
#define sysFloatEm_f_ftoq 13
#define sysFloatEm_f_qtof 14
#define sysFloatEm_d_dtoq 15
#define sysFloatEm_d_qtod 16
#define sysFloatEm_f_ftou 17
#define sysFloatEm_f_ftoi 18
#define sysFloatEm_f_ftoull 19
#define sysFloatEm_f_ftoll 20
#define sysFloatEm_d_dtou 21
#define sysFloatEm_d_dtoi 22
#define sysFloatEm_d_dtoull 23
#define sysFloatEm_d_dtoll 24
#define sysFloatEm_f_cmp 25
#define sysFloatEm_f_cmpe 26
#define sysFloatEm_f_feq 27
#define sysFloatEm_f_fne 28
#define sysFloatEm_f_flt 29
#define sysFloatEm_f_fle 30
#define sysFloatEm_f_fgt 31
#define sysFloatEm_f_fge 32
#define sysFloatEm_f_fun 33
#define sysFloatEm_f_for 34
#define sysFloatEm_d_cmp 35
#define sysFloatEm_d_cmpe 36
#define sysFloatEm_d_feq 37
#define sysFloatEm_d_fne 38
#define sysFloatEm_d_flt 39
#define sysFloatEm_d_fle 40
#define sysFloatEm_d_fgt 41
#define sysFloatEm_d_fge 42
#define sysFloatEm_d_fun 43
#define sysFloatEm_d_for 44
#define sysFloatEm_f_neg 45
#define sysFloatEm_f_add 46
#define sysFloatEm_f_mul 47
#define sysFloatEm_f_sub 48
#define sysFloatEm_f_div 49
#define sysFloatEm_d_neg 50
#define sysFloatEm_d_add 51
#define sysFloatEm_d_mul 52
#define sysFloatEm_d_sub 53
#define sysFloatEm_d_div 54
#ifdef __cplusplus
extern "C" {
#endif
/************************************************************
* New Floating point manager routines
*************************************************************/
// Note: FlpBase10Info returns the actual sign bit in *signP (1 if negative)
// Note: FlpBase10Info reports that zero is "negative".
// A workaround is to check (*signP && *mantissaP) instead of just *signP.
Err FlpBase10Info(FlpDouble a, UInt32 *mantissaP, Int16 *exponentP, Int16 *signP)
FLOAT_TRAP(sysFloatBase10Info);
Err FlpFToA(FlpDouble a, Char *s)
FLOAT_TRAP(sysFloatFToA);
FlpDouble FlpAToF(const Char *s)
FLOAT_TRAP(sysFloatAToF);
FlpDouble FlpCorrectedAdd(FlpDouble firstOperand, FlpDouble secondOperand, Int16 howAccurate)
FLOAT_TRAP(sysFloatCorrectedAdd);
FlpDouble FlpCorrectedSub(FlpDouble firstOperand, FlpDouble secondOperand, Int16 howAccurate)
FLOAT_TRAP(sysFloatCorrectedSub);
#if EMULATION_LEVEL == EMULATION_NONE
// These next three functions correspond to the previous three above.
// The signatures are different, but in fact with CodeWarrior for Palm OS
// the structure return values above are implemented via a hidden pointer
// parameter, so corresponding functions are binary compatible. Programs
// using CodeWarrior to target m68k Palm OS can use either function
// interchangeably.
//
// However, a description of the handling of structure return values is
// missing from the defined Palm OS ABI, and m68k-palmos-gcc does it
// differently. So programs compiled with GCC using the standard functions
// above are likely to crash: GCC users must use the FlpBuffer* forms of
// these functions.
//
// The FlpBuffer* functions are not available on the Simulator, so you need
// to use the standard versions above if you want Simulator compatibility.
//
// Many of the _d_* functions further below suffer from the same problem.
// This is not an issue, because programs targeting Palm OS devices can use
// operators (+ - * / etc) instead of calling these functions directly.
// (GCC users may wish to use -lnfm -- see the documentation for details.)
//
// See the SDK's SampleCalc example for further discussion.
void FlpBufferAToF(FlpDouble *result, const Char *s)
FLOAT_TRAP(sysFloatAToF);
void FlpBufferCorrectedAdd(FlpDouble *result,
FlpDouble firstOperand, FlpDouble secondOperand, Int16 howAccurate)
FLOAT_TRAP(sysFloatCorrectedAdd);
void FlpBufferCorrectedSub(FlpDouble *result,
FlpDouble firstOperand, FlpDouble secondOperand, Int16 howAccurate)
FLOAT_TRAP(sysFloatCorrectedSub);
#endif
UInt32 FlpVersion(void)
FLOAT_TRAP(sysFloatVersion);
void FlpSelectorErrPrv (UInt16 flpSelector)
; // used only by NewFloatDispatch.c
// The following macros could be useful but are left undefined due to the
// confusion they might cause. What was called a "float" in PalmOS v1.0 was
// really a 64-bit; in v2.0 "float" is only 32-bits and "double" is 64-bits.
// However, if a v1.0 program is converted to use the NewFloatMgr, these
// macros could be re-defined, or the native _d_ routines could be called.
//#define FlpLongToFloat(x) _d_itod(x) // similar to 1.0 call, but returns double
//#define FlpFloatToLong(f) _d_dtoi(f) // similar to 1.0 call, but takes a double
//#define FlpFloatToULong(f) _d_dtou(f) // similar to 1.0 call, but takes a double
/************************************************************
* New Floating point emulator functions
*************************************************************/
/*
* These three functions define the interface to the (software) fpscr
* of the sfpe. _fp_round not only sets the rounding mode according
* the low two bits of its argument, but it also returns those masked
* two bits. This provides some hope of compatibility with less capable
* emulators, which support only rounding to nearest. A programmer
* concerned about getting the rounding mode requested can test the
* return value from _fp_round; it will indicate what the current mode is.
*
* Constants passed to and received from _fp_round are:
* flpToNearest, flpTowardZero, flpUpward, or flpDownward
*/
Int32 _fp_round(Int32) FLOAT_EM_TRAP(sysFloatEm_fp_round);
/*
* Constants passed to _fp_set_fpscr and received from _fp_get_fpscr are:
* flpInvalid, flpOverflow, flpUnderflow, flpDivByZero, or flpInexact
*/
Int32 _fp_get_fpscr(void) FLOAT_EM_TRAP(sysFloatEm_fp_get_fpscr);
void _fp_set_fpscr(Int32) FLOAT_EM_TRAP(sysFloatEm_fp_set_fpscr);
/*
* The shorthand here can be determined from the context:
* i --> long (Int32)
* u --> UInt32 (UInt32)
* ll --> long long int
* ull --> UInt32 long int
* f --> float
* d --> double
* q --> long double (defaults to double in this implementaton)
* XtoY--> map of type X to a value of type Y
*/
FlpFloat _f_utof(UInt32) FLOAT_EM_TRAP(sysFloatEm_f_utof);
FlpFloat _f_itof(Int32) FLOAT_EM_TRAP(sysFloatEm_f_itof);
FlpFloat _f_ulltof(sfpe_unsigned_long_long) FLOAT_EM_TRAP(sysFloatEm_f_ulltof);
FlpFloat _f_lltof(sfpe_long_long) FLOAT_EM_TRAP(sysFloatEm_f_lltof);
FlpDouble _d_utod(UInt32) FLOAT_EM_TRAP(sysFloatEm_d_utod);
FlpDouble _d_itod(Int32) FLOAT_EM_TRAP(sysFloatEm_d_itod);
FlpDouble _d_ulltod(sfpe_unsigned_long_long) FLOAT_EM_TRAP(sysFloatEm_d_ulltod);
FlpDouble _d_lltod(sfpe_long_long) FLOAT_EM_TRAP(sysFloatEm_d_lltod);
FlpDouble _f_ftod(FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_ftod);
FlpFloat _d_dtof(FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_dtof);
FlpLongDouble _f_ftoq(FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_ftoq);
FlpFloat _f_qtof(const FlpLongDouble *) FLOAT_EM_TRAP(sysFloatEm_f_qtof);
FlpLongDouble _d_dtoq(FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_dtoq);
FlpDouble _d_qtod(const FlpLongDouble *) FLOAT_EM_TRAP(sysFloatEm_d_qtod);
UInt32 _f_ftou(FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_ftou);
Int32 _f_ftoi(FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_ftoi);
sfpe_unsigned_long_long _f_ftoull(FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_ftoull);
sfpe_long_long _f_ftoll(FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_ftoll);
UInt32 _d_dtou(FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_dtou);
Int32 _d_dtoi(FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_dtoi);
sfpe_unsigned_long_long _d_dtoull(FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_dtoull);
sfpe_long_long _d_dtoll(FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_dtoll);
/*
* The comparison functions _T_Tcmp[e] compare their two arguments,
* of type T, and return one of the four values defined below.
* The functions _d_dcmpe and _f_fcmpe, in addition to returning
* the comparison code, also set the invalid flag in the fpscr if
* the operands are unordered. Two floating point values are unordered
* when they enjoy no numerical relationship, as is the case when one
* or both are NaNs.
*
* Return values for _d_cmp, _d_cmpe, _f_cmp, and _f_cmpe are:
* flpEqual, flpLess, flpGreater, or flpUnordered
*
* The function shorthand is:
* eq --> equal
* ne --> not equal
* lt --> less than
* le --> less than or equal to
* gt --> greater than
* ge --> greater than or equal to
* un --> unordered with
* or --> ordered with (i.e. less than, equal to, or greater than)
*/
Int32 _f_cmp(FlpFloat, FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_cmp);
Int32 _f_cmpe(FlpFloat, FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_cmpe);
Int32 _f_feq(FlpFloat, FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_feq);
Int32 _f_fne(FlpFloat, FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_fne);
Int32 _f_flt(FlpFloat, FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_flt);
Int32 _f_fle(FlpFloat, FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_fle);
Int32 _f_fgt(FlpFloat, FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_fgt);
Int32 _f_fge(FlpFloat, FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_fge);
Int32 _f_fun(FlpFloat, FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_fun);
Int32 _f_for(FlpFloat, FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_for);
Int32 _d_cmp(FlpDouble, FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_cmp);
Int32 _d_cmpe(FlpDouble, FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_cmpe);
Int32 _d_feq(FlpDouble, FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_feq);
Int32 _d_fne(FlpDouble, FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_fne);
Int32 _d_flt(FlpDouble, FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_flt);
Int32 _d_fle(FlpDouble, FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_fle);
Int32 _d_fgt(FlpDouble, FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_fgt);
Int32 _d_fge(FlpDouble, FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_fge);
Int32 _d_fun(FlpDouble, FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_fun);
Int32 _d_for(FlpDouble, FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_for);
FlpFloat _f_neg(FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_neg);
FlpFloat _f_add(FlpFloat, FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_add);
FlpFloat _f_mul(FlpFloat, FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_mul);
FlpFloat _f_sub(FlpFloat, FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_sub);
FlpFloat _f_div(FlpFloat, FlpFloat) FLOAT_EM_TRAP(sysFloatEm_f_div);
FlpDouble _d_neg(FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_neg);
FlpDouble _d_add(FlpDouble, FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_add);
FlpDouble _d_mul(FlpDouble, FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_mul);
FlpDouble _d_sub(FlpDouble, FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_sub);
FlpDouble _d_div(FlpDouble, FlpDouble) FLOAT_EM_TRAP(sysFloatEm_d_div);
#ifdef __cplusplus
}
#endif
#endif