/*----------------------------------------------------------------------------------------------

    Port of Michael Stumpfs FPlib.s to the binutils version of avr-gcc.
    Issues specific to the state of porting are found at the end of this file.
 */
/*----------------------------------------------------------------------------------------------

    FPlib.s

    V 0.3.0

    Copyright (c) Michael Stumpf   <mistumpf@de.pepperl-fuchs.com>

    Floating point library for Atmel AVR uC
    full arithmetic and maths functionality
    do not mix up this file with the FPalib source - doesn't work!

    Author : Michael Stumpf
             mistumpf@de.pepperl-fuchs.com

    Versions : The floating point library comes in three different versions (sometimes...)
               FPlibOs.s90 - optimized for size, rather slow
               FPlibO5.s90 - optimized for speed, rather large
               FPlib  .s90 - something in between .._O2 and .._Os
                             optimized for size if it doesn't cost too much time
                             optimized for speed in loops etc
               implemented is floating point arithmetic for float and double the same size of 4 byte
               right now simple Nans are realized -
               anything with exp == 0xFF is a NaN and remains NaN
               (and the only point that I know turning an exp==0xFF off is
                the division of x/ħINF -> 0.0)

   Implementation limits:

   * only one type of NaN supported : 0xFFC0XXXX
   * only one type of zero supported : 0x00000000
     (no -0)
   * no subnormals supported
     mathematical functions :
   * no call to matherr or _matherr
   * overflow/underflow may occur even when result is withing valid range e.g. sinh etc.
   *
 ================================================================================
  Version Date         Changes
  0.1                  * first release        different version numbers
  0.1.1   (immidiately after first release)
                       * bug in ___addsf3x      adding 0.0 + 0.0 the result was FLT_MIN instead of 0.0
                       * bug in _fmod          sign was incorrect
  0.2.0                * version numbers set to 0.2.0
                       * bug fix in _sin       sin(A) = cos( A + 3PI/2 )
                          least significant byte of constant 3PI/2 was nibble swapped
                       * change in coefficient tables no need for extended precision to store
                         saves time and space
                       * fabs added
                       * _fabs does the same inline
                       * modf added
                       * bug in ___fixsfsi   one of my stupid errors
  0.2.1                * changed segment names from
                               seg removable flash.code.FPaddx
                          to
                               seg removable flash.code.FPlib.FPaddx
                       * tables now placed in (e.g.)
                               seg removable flash.table.FPlin.FPcos
                       * _C_FPsquare and _C_FPinv (which exist and are used anyway)
                         new named to _square and _inverse and made public (two non-standard functions)
  0.2.2                * include "AVR.inc" for macros and target
  0.2.3  18.8.1999     * bug in frexp : 1- parameter pointer to integer handled correctly
                                       2- exponent calculated correctly
                       * include "CtoASM.inc" for parameter passing
                       * ldexp added
                       * exp added
                       * sinh added
                       * cosh added
                       * tanh added
                       * fp_merge : clear __zero_reg__ on all return paths!
  0.2.4  25.8.1999     * ___negsf2 declared public
                       * ___cmpsf2 ; returns 1 for A>B ; 0 for A==B ; -1 for A<B
                       * return values for ___cmpsf2, ___eqsf2 etc. passed in rByte
  0.2.5  07.09.1999    * added some more comments :)
  (not released)       * removed obsolete labels _C_xxx
                          internal functions now are named fp_xxxx
                       * ___floatsisf changed
                       * fp_powerloop : save Z over add
  0.2.6  17.09.1999    * function fp_zero now public
  (not released)       * function _C_FP_PFTtoBX renamed to fp_flashconst
                         and made public (-Os version will use that later on)
                       * macro LPMRdZpp instead of
                          code LPM MOV Rd,R0 ADIW ZL,1 (use of Atmega161 instruction)
                       * #undef all define register nicknames at end of file
  0.2.7  01.10.1999    * fp_powerseries : load constants now with sign : exp[rB3]:sign[rB2.7]:mantissae[rB2.6::rB0.0]
  (not released)       * seg removable flash.table.FPlib.FPasin renamed seg removable flash.table.FPlib.asin
                         seg removable flash.table.FPlib.FPacos renamed seg removable flash.code.FPlib.acos
                       * _exp and _tanh now public ;-)
                       * _modf : don't store integer part twice with ST Y+,..!!
         14.10.1999    * new : _strtod  (seperate file strtod.s)
                       * new : _dtostre (seperate file dtostre.s)
   ...  18.10.1999    * _exp debugged
   ...  19.10.1999    * _log added
                      * _log10, _pow added
                      * bug : call fp_split *allways* before pushing anything to stack
                              -> modf, fp_powerseries
   ...  25.10.1999    * rounding / normalizing error in fp_powerseries
                        leads to low precision sometimes
 0.2.8  27.10.1999    * bug : rare rounding error if the extended results
  (not released)        mantissae is like 80NNNN , NNNN != 0
                        only sub/add & mul, problem solved
                      * fp comparison functions return 1 rather than 0xFF if true
                      * size optimization : fp_split3 moves sign(A)^sign(B) to T
                      * add: changed shift right break criterium:
                             now get diff of exp(B)-exp(A) (negative!) and count up
                             break if diff is < -25
                      * bug in ___gtsf2: BREQ isfalse rather than BRNE isfalse

                      * changes in fp_cmp
                      * changes in sqrt
 0.2.9                * changes in sin: if arg < 397FFFFF -> sin(A) = A
  (not released)                   tan: if arg < 39000000 -> tan(A) = A
                              ((   cos: if arg < 39000000 -> cos(A) = 1.0  ))
                      * fp_powerseries : sign handling optimized
          21.11.99    * bug in frexp frexp(0,&int) -> 0 / 0 (was 0x00800000!)
          30.11.99    * bug in ldexp
 0.3.0    30.11.99      Release version
                      * lots of testing/benchmarking - see file FPlib.bench

  AVRgcc interface:
             All functions use the AVR-gcc function call interface :

             double func( double A [, double B] )

             A := R25:R24:R23:R22 with R25 holding sign and exponent, R22 LSB of mantissa
             B := R21:R20:R19:R18 with R21 holding sign and exponent, R18 LSB of mantissa
             return value := A

             register usage
             R0      scratch register
             R1      allways zero (cleared after use)
             R2-R17  left unchanged (pushed)
             R18-R27 used
             R29:R28 Y unused (pushed)
             R31:R30 Z used

----------------------------------------------------------------------------------------------*/

