Imported Upstream version 2.9.0
[debian/cc1111] / device / lib / pic16 / libc / stdlib / x_ftoa.c
1
2 /*
3  * wrapper function to use _convert_float
4  *
5  * written by Vangelis Rokas, 2004, <vrokas AT otenet.gr>
6  *
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  */
22
23 /*
24  * $Id: x_ftoa.c 3835 2005-08-07 20:09:11Z tecodev $
25  */
26
27 #include <float.h>
28
29 extern convert_frac;
30 extern convert_int;
31
32 /* char x_ftoa(float, __data char *, unsigned char, unsigned char); */
33
34
35 extern POSTDEC1;
36 extern PLUSW2;
37 extern FSR0L;
38 extern FSR0H;
39 extern PREINC1;
40 extern PREINC2;
41 extern FSR2L;
42 extern FSR2H;
43
44 #define _vv0x00 0x00
45 #define _vv0x01 0x01
46 #define _vv0x02 0x02
47 #define _vv0x03 0x03
48 #define _vv0x04 0x04
49
50 /* do not warn about unreferenced arguments/missing return values */
51 #pragma save
52 #pragma disable_warning 59
53 #pragma disable_warning 85
54
55 char x_cnvint_wrap(unsigned long num, __data char *buffer)
56 {
57   __asm
58     movff       _vv0x00, _POSTDEC1
59     movff       _vv0x01, _POSTDEC1
60     movff       _vv0x02, _POSTDEC1
61     movff       _vv0x03, _POSTDEC1
62
63     movlw       2
64     movff       _PLUSW2, _vv0x00
65     movlw       3
66     movff       _PLUSW2, _vv0x01
67     movlw       4
68     movff       _PLUSW2, _vv0x02
69     movlw       5
70     movff       _PLUSW2, _vv0x03
71
72     movlw       6
73     movff       _PLUSW2, _FSR0L
74     movlw       7
75     movff       _PLUSW2, _FSR0H
76
77     call        _convert_int
78
79     /* return value is already in WREG */
80
81     movff       _PREINC1, _vv0x03
82     movff       _PREINC1, _vv0x02
83     movff       _PREINC1, _vv0x01
84     movff       _PREINC1, _vv0x00
85   __endasm ;
86 }
87
88 char x_cnvfrac_wrap(unsigned long num, __data char *buffer, unsigned char prec)
89 {
90   num;
91   buffer;
92   prec;
93   
94   __asm
95     movff       _vv0x00, _POSTDEC1
96     movff       _vv0x01, _POSTDEC1
97     movff       _vv0x02, _POSTDEC1
98     movff       _vv0x03, _POSTDEC1
99     movff       _vv0x04, _POSTDEC1
100
101     movlw       2
102     movff       _PLUSW2, _vv0x00
103     movlw       3
104     movff       _PLUSW2, _vv0x01
105     movlw       4
106     movff       _PLUSW2, _vv0x02
107     movlw       5
108     movff       _PLUSW2, _vv0x03
109     
110     movlw       6
111     movff       _PLUSW2, _FSR0L
112     movlw       7
113     movff       _PLUSW2, _FSR0H
114
115     movlw       8
116     movff       _PLUSW2, _vv0x04
117     
118     call        _convert_frac
119
120     /* return value is already in WREG */
121     
122     movff       _PREINC1, _vv0x04
123     movff       _PREINC1, _vv0x03
124     movff       _PREINC1, _vv0x02
125     movff       _PREINC1, _vv0x01
126     movff       _PREINC1, _vv0x00
127   __endasm ;
128 }
129 #pragma restore
130
131
132 union float_long {
133   unsigned long l;
134   float f;
135 };
136
137 char x_ftoa(float num, __data char *buffer, unsigned char buflen, unsigned char prec)
138 {
139   char len;
140   char expn;
141   unsigned long ll;
142   unsigned long li;
143 //  volatile
144   union float_long f_l;
145
146     len = buflen;
147     while(len--)buffer[len] = 0;
148
149     f_l.f = num;
150
151     if((f_l.l & SIGNBIT) == SIGNBIT) {
152       f_l.l &= ~SIGNBIT;
153       *buffer = '-';
154       buffer++;
155     }
156
157     expn = EXCESS - EXP(f_l.l); // - 24;
158       
159     ll = MANT(f_l.l);
160     li = 0;
161     
162     while( expn ) {
163       if(expn < 0) {
164         li <<= 1;
165         if(ll & 0x00800000UL)li |= 1;
166         ll <<= 1;
167         expn++;
168       } else {
169         ll >>= 1;
170         expn--;
171       }
172     }
173
174     if(li)
175       len = x_cnvint_wrap(li, buffer);
176     else {
177       *buffer = '0'; len = 1;
178     }
179     
180     buffer += len;
181
182     if(prec) {
183       *buffer = '.'; len++;
184       buffer++;
185     
186       len += x_cnvfrac_wrap(ll, buffer, 24-prec);
187       buffer[ prec ] = '\0';
188     }
189     
190   return (len);
191 }