~ubuntu-branches/ubuntu/raring/avr-libc/raring-proposed

« back to all changes in this revision

Viewing changes to libm/fplib/dtostre.S

  • Committer: Bazaar Package Importer
  • Author(s): Hakan Ardo
  • Date: 2008-04-04 17:05:32 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20080404170532-tiwwl2e2qln7ri0w
Tags: 1:1.6.2-1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*  -*- Mode: Asm -*-  */
2
 
 
3
 
/* Copyright (c) 2002  Michael Stumpf  <mistumpf@de.pepperl-fuchs.com>
4
 
   All rights reserved.
5
 
 
6
 
 
7
 
   Redistribution and use in source and binary forms, with or without
8
 
   modification, are permitted provided that the following conditions are met:
9
 
 
10
 
   * Redistributions of source code must retain the above copyright
11
 
     notice, this list of conditions and the following disclaimer.
12
 
   
13
 
   * Redistributions in binary form must reproduce the above copyright
14
 
     notice, this list of conditions and the following disclaimer in
15
 
     the documentation and/or other materials provided with the
16
 
     distribution.
17
 
     
18
 
   * Neither the name of the copyright holders nor the names of
19
 
     contributors may be used to endorse or promote products derived
20
 
     from this software without specific prior written permission.
21
 
 
22
 
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
 
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
 
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
 
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26
 
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27
 
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28
 
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29
 
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30
 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31
 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32
 
   POSSIBILITY OF SUCH DAMAGE. 
33
 
*/
34
 
 
35
 
/* $Id: dtostre.S,v 1.13 2005/09/13 13:29:54 joerg_wunsch Exp $ */
36
 
 
37
 
/*
38
 
    dtostre.S is an addition to     FPlib V 0.3.0       ported to avr-as
39
 
    for details see readme.dtostre
40
 
 
41
 
  const char * dtostre( double f[r22::r25], char * s[r20:r21], byte prec[r18],
42
 
        byte flags[r16] )
43
 
 
44
 
 *------------------------------------------------------------------------------*/
45
 
 
46
 
#if !defined(__DOXYGEN__)
47
 
 
48
 
#include "gasava.inc"
49
 
#include "macros.inc"
50
 
#include "fplib.inc"
51
 
 
52
 
#include <stdlib.h>
53
 
 
54
 
/* Verify assumptions implied in the code below. */
55
 
#if DTOSTR_ALWAYS_SIGN != 0x01
56
 
#error "DTOSTR_ALWAYS_SIGN must be 0x01"
57
 
#endif
58
 
#if DTOSTR_PLUS_SIGN != 0x02
59
 
#error "DTOSTR_PLUS_SIGN must be 0x02"
60
 
#endif
61
 
#if DTOSTR_UPPERCASE != 0x04
62
 
#error "DTOSTR_UPPERCASE must be 0x04"
63
 
#endif
64
 
 
65
 
#define FP_0_1     0x3dcccccd
66
 
#define FP_0_30103 0x3e9a209b
67
 
#define FP_0_5     0x3f000000
68
 
#define FP_10      0x41200000
69
 
 
70
 
          TEXT_SEG(fplib, dtostre)
71
 
          FUNCTION(dtostre)
72
 
 
73
 
GLOBAL(dtostre)
74
 
/* new call convention, move last two args of type "char" */
75
 
        mov     rP6, r18        /* rP6 == r19 */
76
 
        mov     rP7, r16        /* rP7 == r18 */
77
 
 
78
 
        push    r11
79
 
        push    r12
80
 
        push    r13
81
 
        push    r14
82
 
        push    r15
83
 
        push    r16
84
 
        push    r17
85
 
        push    YH
86
 
        push    YL
87
 
        push    rP4             ; return this
88
 
        push    rP5
89
 
        mov     YH, rP4
90
 
        mov     YL, rP5
91
 
 
92
 
        mov     rSI0, rA3       ; copy sign
93
 
        mov     rSI1, rA2       ; and ..
94
 
        add     rSI1, rSI1
95
 
        adc     rSI0, rSI0
96
 
        brne    3f              ; not zero
97
 
 
98
 
        ldi     rSI1, ' '
99
 
        sbrc    rP7, 1
100
 
        ldi     rSI1, '+'       ; rSI1 = (flags & DTOSTRE_PLUS_SIGN?'+':' ')
101
 
        sbrc    rP7, 0          ; if (!(flags & DTOSTRE_ALWAYS_SIGN)) skip
102
 
        st      Y+, rSI1
103
 
        ldi     rA3, '0'
104
 
        ldi     rA2, '.'
105
 
        ldi     rA1, 'E'
106
 
        sbrs    rP7, 2          ; if DTOSTRE_UPPERCASE was set
107
 
        ori     rA1, 'E' ^ 'e'
108
 
        ldi     rA0, '+'
109
 
        st      Y+,rA3
110
 
        tst     rP6             ; if (prec == 0) don't print ".0"
111
 
        breq    2f
112
 
        dec     rP6
113
 
        st      Y+,rA2
114
 
1:      st      Y+, rA3
115
 
        dec     rP6
116
 
        brpl    1b
117
 
2:      st      Y+, rA1         /* 'E' */
118
 
        st      Y+, rA0         /* '+' */
119
 
        st      Y+, rA3         /* '0' */
120
 
        st      Y+, rA3         /* '0' */
121
 
        rjmp    99f             ; exit
122
 
 
123
 
3:
124
 
        cpi     rSI0, 0xff
125
 
        brne    4f              ; check for zero and NaN
126
 
 
127
 
        ldi     rA3, 'N'
128
 
        ldi     rA2, 'a'
129
 
        st      Y+, rA3         /* 'N' */
130
 
        st      Y+, rA2         /* 'a' */
131
 
        st      Y+, rA3         /* 'N' */
132
 
        rjmp    99f             ; exit
133
 
 
134
 
4:                              ; not NaN
135
 
        tst     rA3
136
 
        brpl    5f
137
 
        ldi     rSI1, '-'
138
 
        andi    rA3, 0x7F       ; now f is positive
139
 
        rjmp    6f
140
 
5:      ldi     rSI1, ' '
141
 
        sbrc    rP7, 1
142
 
        ldi     rSI1, '+'       ; rSI1 = (flags & DTOSTRE_PLUS_SIGN?'+':' ')
143
 
        sbrc    rP7, 0          ; if (!(flags & DTOSTRE_ALWAYS_SIGN)) skip
144
 
6:
145
 
        st      Y+, rSI1
146
 
 
147
 
        mov     rSI0, rP6       ; store prec
148
 
        push    rP7             ; and flags
149
 
 
150
 
        mov     rS0, rA0        ; store dblno
151
 
        mov     rS1, rA1
152
 
        mov     rS2, rA2
153
 
        mov     rS3, rA3
154
 
 
155
 
; frexp(dblno, (int*) dest);
156
 
        mov     rB2, YL
157
 
        mov     rB3, YH
158
 
        XCALL   _U(frexp)       ; destroys argument_1
159
 
 
160
 
; iexp = *(int*) dest * log10(2);
161
 
        ldd     rA0, Y+0
162
 
        ldd     rA1, Y+1        ; exponent
163
 
        eor     rA2, rA2        ; to longint argument
164
 
        sbrc    rA1, 7
165
 
        com     rA2
166
 
        mov     rA3, rA2
167
 
        XCALL   _U(__floatsisf) ; to float
168
 
        FPLOAD(rB, FP_0_30103)
169
 
        XCALL   _U(__mulsf3)    ; multiply
170
 
        XCALL   _U(__fixsfsi)   ; to integer
171
 
        mov     rS4, rA0        ; save exponent, 1 byte only
172
 
 
173
 
; if ( iexp  != 0 )
174
 
        tst     rA0
175
 
        breq    1f
176
 
 
177
 
; dblno *= pow(10.0, -(double) iexp)
178
 
        XCALL   _U(__floatsisf) ; to float
179
 
        XCALL   _U(__negsf2)    ; negative
180
 
        FPMOV(rB, rA)
181
 
        FPLOAD(rA, FP_10)
182
 
        XCALL   _U(pow)
183
 
        FPMOV(rB, rS)           ; argument_2 = dblno
184
 
        XCALL   _U(__mulsf3)
185
 
        FPMOV(rS, rA)           ; new dblno
186
 
1:
187
 
; determine rounding:
188
 
; if (prec < ACCURACY) { t = .5; t *= 0.1**prec; dblno += t; }
189
 
        cpi     rSI0, ACCURACY
190
 
        brcc    1f
191
 
        FPLOAD(rA, FP_0_5)
192
 
        eor     rSI1, rSI1      ; for (rSI1 = 0; rSI1 < prec; rSI1++)
193
 
        rjmp    3f
194
 
2:      FPLOAD(rB, FP_0_1)
195
 
        XCALL   _U(__mulsf3)    ; t *= 0.1
196
 
        inc     rSI1
197
 
3:      cp      rSI1, rSI0
198
 
        brlo    2b
199
 
        FPMOV(rB, rS)
200
 
        XCALL   _U(__addsf3)    ; dblno += t
201
 
        FPMOV(rS, rA)           ; new dblno
202
 
1:
203
 
; The algorithm to determine the decimal exponent above has the
204
 
; potential to erroneously return an exponent that might be too
205
 
; large.  So we need to give it a try before applying the rounding
206
 
; below.  If we find the first digit to become 0, we decrease the
207
 
; exponent, and multiply our number again by 10.
208
 
 
209
 
        FPMOV(rA, rS)
210
 
        mov     rB2, YL
211
 
        mov     rB3, YH
212
 
        XCALL   _U(modf)
213
 
        ldd     rSI1, Y+3       ; no need to convert from float to int,
214
 
        tst     rSI1            ; float 0.0 always has 0 in the MSB
215
 
        brne    1f
216
 
 
217
 
        dec     rS4             ; exp--
218
 
        FPLOAD(rB, FP_10)
219
 
        XCALL   _U(__mulsf3)
220
 
        FPMOV(rS, rA)           ; dblno
221
 
        rjmp    1b
222
 
 
223
 
1:
224
 
                                ; for (rSI1 = 0; rSI1 <= prec; rSI1++)
225
 
        eor     rSI1, rSI1
226
 
        rjmp    8f
227
 
2:
228
 
        cpi     rSI1, ACCURACY
229
 
        brcc    5f              ; more digits than accuracy => pad 0s
230
 
 
231
 
; dblno = modf(dblno, (double *) dest) * 10.0;
232
 
        FPMOV(rA, rS)           ; next digit
233
 
        mov     rB2, YL
234
 
        mov     rB3, YH
235
 
        XCALL   _U(modf)
236
 
        FPLOAD(rB, FP_10)
237
 
        XCALL   _U(__mulsf3)
238
 
        FPMOV(rS, rA)           ; dblno
239
 
 
240
 
; *dest++ = '0' + (char)(*(double *) dest);
241
 
        ldd     rA0, Y+0
242
 
        ldd     rA1, Y+1
243
 
        ldd     rA2, Y+2
244
 
        ldd     rA3, Y+3
245
 
        XCALL   _U(__fixsfsi)   ; to long int
246
 
        mov     rA2, rA0
247
 
        subi    rA2, -'0'
248
 
        st      Y+, rA2
249
 
 
250
 
; if (i == 0)
251
 
        tst     rSI1
252
 
        brne    7f
253
 
        tst     rSI0            ; if (prec == 0) don't print "."
254
 
        breq    7f
255
 
        ldi     rA2, '.'
256
 
        rjmp    6f
257
 
5:                              ; pad with zeros
258
 
        ldi     rA2, '0'
259
 
6:      st      Y+, rA2
260
 
7:      inc     rSI1            ; rSI1++
261
 
8:                              ; loop test rSI1 <= rSI0
262
 
        cp      rSI0, rSI1      ; compare count - prec
263
 
        brcc    2b
264
 
 
265
 
        pop     rA2             ; and flags
266
 
        ldi     rA1, 'E'
267
 
        sbrs    rA2, 2          ; if DTOSTRE_UPPERCASE was set
268
 
        ori     rA1, 'E' ^ 'e'
269
 
        ST      Y+, rA1         ; put exponent
270
 
        ldi     rA1, '+'        ;
271
 
        tst     rS4             ; exponent
272
 
        brpl    1f
273
 
        neg     rS4
274
 
        ldi     rA1, '-'
275
 
1:
276
 
        st      Y+, rA1
277
 
 
278
 
        ; dividend in r24, divisor in r22
279
 
        mov     r24, rS4
280
 
        ldi     r22, 10         ; divisor
281
 
        XCALL   _U(__udivmodqi4)
282
 
        ; quotient in r24, remainder in r25
283
 
 
284
 
        subi    rByte, -'0'
285
 
        st      Y+, rByte
286
 
        subi    r25, -'0'
287
 
        st      Y+, r25
288
 
99:
289
 
        st      Y,__zero_reg__
290
 
 
291
 
        pop     rByte           ; char *dest
292
 
        pop     r25
293
 
        pop     YL              ; frame pointer
294
 
        pop     YH
295
 
        pop     r17
296
 
        pop     r16
297
 
        pop     r15
298
 
        pop     r14
299
 
        pop     r13
300
 
        pop     r12
301
 
        pop     r11
302
 
        ret
303
 
 
304
 
          ENDFUNC
305
 
 
306
 
#endif /* not __DOXYGEN__ */