e271f33fa208824e2548537ff36c1562fa9bb200
[fw/sdcc] / 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$
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 char x_cnvint_wrap(unsigned long num, __data char *buffer)
51 {
52   num;
53   buffer;
54   
55   __asm
56     movff       _vv0x00, _POSTDEC1
57     movff       _vv0x01, _POSTDEC1
58     movff       _vv0x02, _POSTDEC1
59     movff       _vv0x03, _POSTDEC1
60
61     movlw       2
62     movff       _PLUSW2, _vv0x00
63     movlw       3
64     movff       _PLUSW2, _vv0x01
65     movlw       4
66     movff       _PLUSW2, _vv0x02
67     movlw       5
68     movff       _PLUSW2, _vv0x03
69
70     movlw       6
71     movff       _PLUSW2, _FSR0L
72     movlw       7
73     movff       _PLUSW2, _FSR0H
74
75     call        _convert_int
76
77     /* return value is already in WREG */
78
79     movff       _PREINC1, _vv0x03
80     movff       _PREINC1, _vv0x02
81     movff       _PREINC1, _vv0x01
82     movff       _PREINC1, _vv0x00
83   __endasm ;
84 }
85
86 char x_cnvfrac_wrap(unsigned long num, __data char *buffer, unsigned char prec)
87 {
88   num;
89   buffer;
90   prec;
91   
92   __asm
93     movff       _vv0x00, _POSTDEC1
94     movff       _vv0x01, _POSTDEC1
95     movff       _vv0x02, _POSTDEC1
96     movff       _vv0x03, _POSTDEC1
97     movff       _vv0x04, _POSTDEC1
98
99     movlw       2
100     movff       _PLUSW2, _vv0x00
101     movlw       3
102     movff       _PLUSW2, _vv0x01
103     movlw       4
104     movff       _PLUSW2, _vv0x02
105     movlw       5
106     movff       _PLUSW2, _vv0x03
107     
108     movlw       6
109     movff       _PLUSW2, _FSR0L
110     movlw       7
111     movff       _PLUSW2, _FSR0H
112
113     movlw       8
114     movff       _PLUSW2, _vv0x04
115     
116     call        _convert_frac
117
118     /* return value is already in WREG */
119     
120     movff       _PREINC1, _vv0x04
121     movff       _PREINC1, _vv0x03
122     movff       _PREINC1, _vv0x02
123     movff       _PREINC1, _vv0x01
124     movff       _PREINC1, _vv0x00
125   __endasm ;
126 }
127
128
129
130 union float_long {
131   unsigned long l;
132   float f;
133 };
134
135 char x_ftoa(float num, __data char *buffer, unsigned char buflen, unsigned char prec)
136 {
137   char len;
138   char expn;
139   unsigned long ll;
140   unsigned long li;
141 //  volatile
142   union float_long f_l;
143
144     len = buflen;
145     while(len--)buffer[len] = 0;
146
147     f_l.f = num;
148
149     if((f_l.l & SIGNBIT) == SIGNBIT) {
150       f_l.l &= ~SIGNBIT;
151       *buffer = '-';
152       buffer++;
153     }
154
155     expn = EXCESS - EXP(f_l.l); // - 24;
156       
157     ll = MANT(f_l.l);
158     li = 0;
159     
160     while( expn ) {
161       if(expn < 0) {
162         li <<= 1;
163         if(ll & 0x00800000UL)li |= 1;
164         ll <<= 1;
165         expn++;
166       } else {
167         ll >>= 1;
168         expn--;
169       }
170     }
171
172     if(li)
173       len = x_cnvint_wrap(li, buffer);
174     else {
175       *buffer = '0'; len = 1;
176     }
177     
178     buffer += len;
179
180     if(prec) {
181       *buffer = '.'; len++;
182       buffer++;
183     
184       len += x_cnvfrac_wrap(ll, buffer, 24-prec);
185       buffer[ prec ] = '\0';
186     }
187     
188   return (len);
189 }