1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
/*----------------------------------------------------------------------------------------------
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
----------------------------------------------------------------------------------------------*/
|