Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1702 | - | 1 | /* Copyright (c) 2005,2007 Dmitry Xmelkov |
2 | All rights reserved. |
||
3 | |||
4 | Redistribution and use in source and binary forms, with or without |
||
5 | modification, are permitted provided that the following conditions are met: |
||
6 | |||
7 | * Redistributions of source code must retain the above copyright |
||
8 | notice, this list of conditions and the following disclaimer. |
||
9 | * Redistributions in binary form must reproduce the above copyright |
||
10 | notice, this list of conditions and the following disclaimer in |
||
11 | the documentation and/or other materials provided with the |
||
12 | distribution. |
||
13 | * Neither the name of the copyright holders nor the names of |
||
14 | contributors may be used to endorse or promote products derived |
||
15 | from this software without specific prior written permission. |
||
16 | |||
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
||
18 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
||
19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
||
20 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
||
21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
||
22 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
||
23 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
||
24 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
||
25 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
||
26 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
||
27 | POSSIBILITY OF SUCH DAMAGE. */ |
||
28 | |||
29 | /* $Id: ultoa_invert.S 1944 2009-04-01 23:12:20Z arcanum $ */ |
||
30 | |||
31 | #ifndef __DOXYGEN__ |
||
32 | |||
33 | #include "macros.inc" |
||
34 | #include "ntz.h" |
||
35 | #include "xtoa_fast.h" |
||
36 | |||
37 | /* -------------------------------------------------------------------- |
||
38 | char * __ultoa_invert (unsigned long val, char * str, int base) |
||
39 | |||
40 | This function is intended for usage as internal printf's one. |
||
41 | It differs from others of `xtoa_fast' family: |
||
42 | * srt[] will NOT 0 terminated. |
||
43 | * Sequence of digits is inverted. |
||
44 | * It returns pointer to first byte after a string. |
||
45 | * Only `XTOA_UPPER' flag is operated. |
||
46 | Notes: |
||
47 | * base: check only 8 and 16, all others are treated as 10. |
||
48 | (internal printf's function). |
||
49 | */ |
||
50 | |||
51 | /* Input */ |
||
52 | #define v_lo r22 |
||
53 | #define v_hi r23 |
||
54 | #define v_hlo r24 |
||
55 | #define v_hhi r25 |
||
56 | #define str_lo r20 |
||
57 | #define str_hi r21 |
||
58 | #define base r18 |
||
59 | #define flags r19 |
||
60 | |||
61 | /* Used */ |
||
62 | #define v_fifth r26 /* val: bits 39..32 */ |
||
63 | #define t_lo r18 /* temporary for shifted `val' */ |
||
64 | #define t_hi r19 |
||
65 | #define t_hlo r20 |
||
66 | #define t_hhi r21 |
||
67 | #define symb r20 /* write to string */ |
||
68 | #define cnt r27 /* shift loop counter, local arg */ |
||
69 | |||
70 | /* Fixed */ |
||
71 | #define rzero r1 |
||
72 | |||
73 | /* ASSEMBLY_CLIB_SECTION */ |
||
74 | .global __ultoa_invert |
||
75 | .type __ultoa_invert, "function" |
||
76 | |||
77 | __ultoa_invert: |
||
78 | X_movw ZL, str_lo |
||
79 | clr v_fifth ; needed for all (ultoa_lsr) |
||
80 | cpi base, 8 |
||
81 | breq .L_oct |
||
82 | cpi base, 16 |
||
83 | breq .L_hex |
||
84 | |||
85 | ; decimal format |
||
86 | clt ; flag of val == 0 |
||
87 | .L_dec_loop: |
||
88 | push v_lo ; to calculate remander |
||
89 | ; val &= ~1 |
||
90 | andi v_lo, ~1 |
||
91 | ; val += 2 |
||
92 | subi v_lo, lo8(-2) |
||
93 | sbci v_hi, hi8(-2) |
||
94 | sbci v_hlo, hlo8(-2) |
||
95 | sbci v_hhi, hhi8(-2) |
||
96 | sbci v_fifth, hhi8(-2) |
||
97 | ; val += val/2 |
||
98 | ldi cnt, 1 |
||
99 | rcall .L_div_add |
||
100 | ; val += val/16 |
||
101 | ldi cnt, 4 |
||
102 | rcall .L_div_add |
||
103 | ; val += val/256 |
||
104 | add v_lo, v_hi |
||
105 | adc v_hi, v_hlo |
||
106 | adc v_hlo, v_hhi |
||
107 | adc v_hhi, v_fifth |
||
108 | adc v_fifth, rzero |
||
109 | ; val += val/65536 |
||
110 | add v_lo, v_hlo |
||
111 | adc v_hi, v_hhi |
||
112 | adc v_hlo, v_fifth |
||
113 | adc v_hhi, rzero |
||
114 | adc v_fifth, rzero |
||
115 | ; val += val >> 32 |
||
116 | add v_lo, v_fifth |
||
117 | adc v_hi, rzero |
||
118 | adc v_hlo, rzero |
||
119 | adc v_hhi, rzero |
||
120 | adc v_fifth, rzero |
||
121 | ; division result: val /= 16 |
||
122 | rcall .L_lsr_4 ; v_fitth := 0 |
||
123 | brne 1f |
||
124 | set ; T := Z flag |
||
125 | 1: |
||
126 | ; rem: val_original - 10*val |
||
127 | pop t_hi |
||
128 | #if defined(__AVR_ENHANCED__) && __AVR_ENHANCED__ |
||
129 | ldi t_lo, 10 |
||
130 | mul t_lo, v_lo |
||
131 | clr r1 |
||
132 | #else |
||
133 | mov r0, v_lo |
||
134 | lsl r0 |
||
135 | sub t_hi, r0 |
||
136 | lsl r0 |
||
137 | lsl r0 |
||
138 | #endif |
||
139 | sub t_hi, r0 |
||
140 | ; output digit |
||
141 | subi t_hi, lo8(-'0') |
||
142 | st Z+, t_hi |
||
143 | ; quotient == 0 ? |
||
144 | brtc .L_dec_loop |
||
145 | ; end of string |
||
146 | .L_eos: |
||
147 | X_movw r24, ZL |
||
148 | ret |
||
149 | |||
150 | ; octal format |
||
151 | .L_oct: |
||
152 | mov symb, v_lo |
||
153 | andi symb, 7 |
||
154 | subi symb, lo8(-'0') |
||
155 | st Z+, symb |
||
156 | ldi cnt, 3 |
||
157 | rcall .L_lsr |
||
158 | brne .L_oct |
||
159 | rjmp .L_eos |
||
160 | |||
161 | ; hex format |
||
162 | .L_hex: |
||
163 | mov symb, v_lo |
||
164 | andi symb, 0x0f |
||
165 | subi symb, lo8(-'0') |
||
166 | cpi symb, '9' + 1 |
||
167 | brlo 3f |
||
168 | subi symb, lo8('9' + 1 - 'a') |
||
169 | sbrc flags, ntz(XTOA_UPPER) - 8 |
||
170 | subi symb, lo8('a' - 'A') |
||
171 | 3: st Z+, symb |
||
172 | rcall .L_lsr_4 |
||
173 | brne .L_hex |
||
174 | rjmp .L_eos |
||
175 | |||
176 | .L_lsr_4: |
||
177 | ldi cnt, 4 |
||
178 | .L_lsr: |
||
179 | lsr v_fifth |
||
180 | ror v_hhi |
||
181 | ror v_hlo |
||
182 | ror v_hi |
||
183 | ror v_lo |
||
184 | dec cnt |
||
185 | brne .L_lsr |
||
186 | ; tst |
||
187 | sbiw v_hlo, 0 ; only Z flag is needed |
||
188 | cpc v_lo, rzero |
||
189 | cpc v_hi, rzero |
||
190 | ret |
||
191 | |||
192 | .L_div_add: |
||
193 | ; copy to temporary |
||
194 | X_movw t_lo, v_lo |
||
195 | X_movw t_hlo, v_hlo |
||
196 | mov r0, v_fifth |
||
197 | ; lsr temporary |
||
198 | 7: lsr r0 |
||
199 | ror t_hhi |
||
200 | ror t_hlo |
||
201 | ror t_hi |
||
202 | ror t_lo |
||
203 | dec cnt |
||
204 | brne 7b |
||
205 | ; add |
||
206 | add v_lo, t_lo |
||
207 | adc v_hi, t_hi |
||
208 | adc v_hlo, t_hlo |
||
209 | adc v_hhi, t_hhi |
||
210 | adc v_fifth, r0 ; here r0 == 0 |
||
211 | ret |
||
212 | |||
213 | .size __ultoa_invert, . - __ultoa_invert |
||
214 | .end |
||
215 | |||
216 | #endif /* !__DOXYGEN__ */ |