Subversion Repositories Projects

Rev

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__ */