struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / device / lib / z80n / __itoa.s
blob7b439fad28f78f9d4ec52e8b328f20b17e43c1d3
1 ;--------------------------------------------------------------------------
2 ; __itoa.s
4 ; Copyright (C) 2020-2021, Sergey Belyashov
6 ; This library is free software; you can redistribute it and/or modify it
7 ; under the terms of the GNU General Public License as published by the
8 ; Free Software Foundation; either version 2, or (at your option) any
9 ; later version.
11 ; This library is distributed in the hope that it will be useful,
12 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ; GNU General Public License for more details.
16 ; You should have received a copy of the GNU General Public License
17 ; along with this library; see the file COPYING. If not, write to the
18 ; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
19 ; MA 02110-1301, USA.
21 ; As a special exception, if you link this library with other files,
22 ; some of which are compiled with SDCC, to produce an executable,
23 ; this library does not by itself cause the resulting executable to
24 ; be covered by the GNU General Public License. This exception does
25 ; not however invalidate any other reasons why the executable file
26 ; might be covered by the GNU General Public License.
27 ;--------------------------------------------------------------------------
29 .area _CODE
31 .globl ___itoa
32 .globl ___uitoa
34 ;void __itoa(int value, char *string, unsigned char radix);
36 ___itoa::
37 push ix
38 ld ix, #0
39 add ix, sp
41 push de
43 ; HL - value
44 ; DE - string
45 ; 4 (ix) - radix
47 ex de, hl
48 bit 7, d
49 jr Z, ___uitoa_de
50 ;positive/negative numbers are supported only for radix=10
51 ld a, 4 (ix)
52 cp a, #10
53 jr NZ, ___uitoa_de
54 ;add minus sign to result and inverse value (Carry Flag is 0 here)
55 ld hl, #0
56 sbc hl, de
57 ex de, hl
58 ld l, -2 (ix)
59 ld h, -1 (ix)
60 ld (hl), #0x2D ;minus symbol
61 inc hl
62 ld -2 (ix), l
63 ld -1 (ix), h
64 jr ___uitoa_dehl
66 ;void __uitoa(unsigned int value, char *string, unsigned char radix);
68 ___uitoa::
69 push ix
70 ld ix, #0
71 add ix, sp
73 push de
75 ; HL - value
76 ; DE - string
77 ; 4 (ix) - radix
79 ex de, hl
81 ___uitoa_de:
82 ld l, -2 (ix)
83 ld h, -1 (ix)
85 ___uitoa_dehl: ;DE - value, HL - string, 6 (ix) - radix
86 ld a, e
87 or a, d
88 jr NZ, 100$
90 ld (hl), #0x30
91 inc hl
92 jp 190$
93 100$:
94 ld a, 4 (ix)
95 cp a, #10 ;most popular radix
96 jr NZ, 110$
98 ;-------- decimal conversion
99 ; this algorithm up to 2 times faster than generic
101 ld c, l
102 ld b, h
103 ld hl, #-4
104 add hl, sp
105 ld sp, hl
106 push hl
107 push bc ;BC - pointer to string
108 ex de, hl
109 call ___uitobcd ;HL - value, DE - pointer to BCD value
110 pop de ;DE - pointer to string
111 pop hl ;HL - pointer to BCD value
112 ld b, #3 ;number of bytes in BCD value
113 ld a, #0x30 ;ASCII code of '0'
114 103$:
116 ld (de), a
117 inc de
119 ld (de), a
120 inc de
121 inc hl
122 djnz 103$
124 ; pop af
125 ; pop af
126 ;skip trailing zeroes
127 ld b, #5 ;real BCD number is at most 5 digits
128 dec de ;so always skip last zero
129 105$:
130 dec de
131 ld a, (de)
132 cp a, #0x30
133 jr NZ, 107$ ;break loop if non-zero found
134 djnz 105$
135 107$:
136 inc de ;always point to symbol next to last significant
137 ex de, hl
138 jr 190$
140 ;---------------------------
142 110$:
143 cp a, #2
144 jr C, 190$ ;radix is less than 2
146 ld c, a
147 dec c
148 and a, c
149 jr NZ, 150$
151 ;-------- radix is power of 2
153 ; DE - value, HL - pointer to string, C - mask
154 120$:
155 ld a, e
156 ld b, c
157 125$:
158 srl d
159 rr e
160 srl b
161 jr NZ, 125$
163 and a, c
164 add a, #0x30
165 cp a, #0x3A ;convert to 0...9A...Z
166 jr C, 130$
167 add a, #7
168 130$:
169 ld (hl), a
170 inc hl
171 ld a, e
172 or a, d
173 jr NZ, 120$
174 jr 190$
176 ;---------------------------
178 ;-------- custom radix (generic algorithm)
180 150$:
181 ex de, hl
182 160$:
183 ld c, 4 (ix)
184 call ___divu16_8
185 add a, #0x30
186 cp a, #0x3A
187 jr C, 165$
188 add a, #7
189 165$:
190 ld (de), a
191 inc de
192 ld a, l
193 or a, h
194 jr NZ, 160$
195 ex de, hl
196 ; jr 190$
198 ;---------------------------
200 ;-------- finish string and reverse its order
201 190$:
202 ld (hl), #0
203 ld e, -2 (ix)
204 ld d, -1 (ix)
205 call ___strreverse_reg
206 ld sp, ix
207 pop ix
208 pop hl
209 inc sp
210 jp (hl)
213 ;in: HL - divident, C - divisor
214 ;out: HL - quotient, A - remainder
215 ___divu16_8:
216 xor a, a
217 ld b, #16
218 100$:
219 add hl, hl
221 jr c, 110$
222 cp a, c
223 jr c, 120$
224 110$:
225 sub a, c
226 inc l
227 120$:
228 djnz 100$