Subversion Repositories svnkaklik

Rev

Details | Last modification | View Log

Rev Author Line No. Line
507 kaklik 1
;---------------------------------------------------------------------------;
2
; Extended itoa, puts, printf and atoi                     (C)ChaN, 2006
3
;
4
; Module size: 277/261 words (max)
5
;
6
 
7
#define USE_XPUTS
8
#define USE_XITOA
9
#define USE_XPRINTF
10
#define USE_XATOI
11
 
12
 
13
 
14
.nolist
15
#include <avr/io.h>	// Include device specific definitions.
16
.list
17
 
18
#ifdef SPM_PAGESIZE	// Recent devices have "lpm Rd,Z+" and "movw".
19
.macro	_LPMI	reg
20
	lpm	\reg, Z+
21
.endm
22
.macro	_MOVW	dh,dl, sh,sl
23
	movw	\dl, \sl
24
.endm
25
#else			// Earlier devices do not have "lpm Rd,Z+" nor "movw".
26
.macro	_LPMI	reg
27
	lpm
28
	mov	\reg, r0
29
	adiw	ZL, 1
30
.endm
31
.macro	_MOVW	dh,dl, sh,sl
32
	mov	\dl, \sl
33
	mov	\dh, \sh
34
.endm
35
#endif
36
 
37
 
38
 
39
;---------------------------------------------------------------------------
40
; Stub function to forward to user output function
41
;
42
;Prototype: void xputc (char chr	// a character to be output
43
;			);
44
;Size: 15/15 words
45
 
46
.section .bss
47
 
48
.global xfunc_out	; xfunc_out must be initialized before using this module.
49
xfunc_out:	.ds.w	1
50
 
51
.section .text
52
 
53
 
54
.global xputc
55
.func xputc
56
xputc:
57
	cpi	r24, 10		;LF --> CRLF
58
	brne	1f		;
59
	ldi	r24, 13		;
60
	rcall	1f		;
61
	ldi	r24, 10		;/
62
1:	push	ZH
63
	push	ZL
64
	lds	ZL, xfunc_out+0	;Pointer to the registered output function.
65
	lds	ZH, xfunc_out+1	;/
66
	icall
67
	pop	ZL
68
	pop	ZH
69
	ret
70
.endfunc
71
 
72
 
73
 
74
;---------------------------------------------------------------------------
75
; Direct ROM string output
76
;
77
;Prototype: void xputs (const prog_char *str // rom string to be output
78
;			);
79
;Size: 10/7 words
80
 
81
#ifdef USE_XPUTS
82
.global xputs
83
.func xputs
84
xputs:
85
	_MOVW	ZH,ZL, r25,r24	; Z = pointer to rom string
86
1:	_LPMI	r24
87
	cpi	r24, 0
88
	breq	2f
89
	rcall	xputc
90
	rjmp	1b
91
2:	ret
92
.endfunc
93
#endif
94
 
95
 
96
;---------------------------------------------------------------------------
97
; Extended direct numeral string output (32bit version)
98
;
99
;Prototype: void xitoa (long value,	// value to be output
100
;                       char radix,	// radix
101
;                       char width);	// minimum width
102
;Size: 59/59 words
103
;
104
 
105
#ifdef USE_XITOA
106
.global xitoa
107
.func xitoa
108
xitoa:
109
				;r25:r22 = value, r20 = base, r18 = digits
110
	clr	r31		;r31 = stack level
111
	ldi	r30, ' '	;r30 = sign
112
	ldi	r19, ' '	;r19 = filler
113
	sbrs	r20, 7		;When base indicates signd format and the value
114
	rjmp	0f		;is minus, add a '-'.
115
	neg	r20		;
116
	sbrs	r25, 7		;
117
	rjmp	0f		;
118
	ldi	r30, '-'	;
119
	com	r22		;
120
	com	r23		;
121
	com	r24		;
122
	com	r25		;
123
	adc	r22, r1		;
124
	adc	r23, r1		;
125
	adc	r24, r1		;
126
	adc	r25, r1		;/
127
0:	sbrs	r18, 7		;When digits indicates zero filled,
128
	rjmp	1f		;filler is '0'.
129
	neg	r18		;
130
	ldi	r19, '0'	;/
131
				;----- string conversion loop
132
1:	ldi	r21, 32		;r26 = r25:r22 % r20
133
	clr	r26		;r25:r22 /= r20
134
2:	lsl	r22		;
135
	rol	r23		;
136
	rol	r24		;
137
	rol	r25		;
138
	rol	r26		;
139
	cp	r26, r20	;
140
	brcs	3f		;
141
	sub	r26, r20	;
142
	inc	r22		;
143
3:	dec	r21		;
144
	brne	2b		;/
145
	cpi	r26, 10		;r26 is a numeral digit '0'-'F'
146
	brcs	4f		;
147
	subi	r26, -7		;
148
4:	subi	r26, -'0'	;/
149
	push	r26		;Stack it
150
	inc	r31		;/
151
	cp	r22, r1		;Repeat until r25:r22 gets zero
152
	cpc	r23, r1		;
153
	cpc	r24, r1		;
154
	cpc	r25, r1		;
155
	brne	1b		;/
156
 
157
	cpi	r30, '-'	;Minus sign if needed
158
	brne	5f		;
159
	push	r30		;
160
	inc	r31		;/
161
5:	cp	r31, r18	;Filler
162
	brcc	6f		;
163
	push	r19		;
164
	inc	r31		;
165
	rjmp	5b		;/
166
 
167
6:	pop	r24		;Flush stacked digits and exit
168
	rcall	xputc		;
169
	dec	r31		;
170
	brne	6b		;/
171
 
172
	ret
173
.endfunc
174
#endif
175
 
176
 
177
 
178
;---------------------------------------------------------------------------;
179
; Formatted string output (16/32bit version)
180
;
181
;Prototype:
182
; void xprintf (const prog_char *format, ...);
183
;Size: 104/94 words
184
;
185
 
186
#ifdef USE_XPRINTF
187
.global xprintf
188
.func xprintf
189
xprintf:
190
	push	YH
191
	push	YL
192
	in	YL, _SFR_IO_ADDR(SPL)
193
#ifdef SPH
194
	in	YH, _SFR_IO_ADDR(SPH)
195
#else
196
	clr	YH
197
#endif
198
#if FLASHEND > 0x1FFFF
199
	adiw	YL, 6		;Y = pointer to arguments
200
#else
201
	adiw	YL, 5		;Y = pointer to arguments
202
#endif
203
	ld	ZL, Y+		;Z = pointer to format string
204
	ld	ZH, Y+		;/
205
 
206
0:	_LPMI	r24		;Get a format char
207
	cpi	r24, 0		;End of format string?
208
	breq	90f		;/
209
	cpi	r24, '%'	;Is format?
210
	breq	20f		;/
211
1:	rcall	xputc		;Put a normal character
212
	rjmp	0b		;/
213
90:	pop	YL
214
	pop	YH
215
	ret
216
 
217
20:	ldi	r18, 0		;r18: digits
218
	clt			;T: filler
219
	_LPMI	r21		;Get flags
220
	cpi	r21, '%'	;Is a %?
221
	breq	1b		;/
222
	cpi	r21, '0'	;Zero filled?
223
	brne	23f		;
224
	set			;/
225
22:	_LPMI	r21		;Get width
226
23:	cpi	r21, '9'+1	;
227
	brcc	24f		;
228
	subi	r21, '0'	;
229
	brcs	90b		;
230
	lsl	r18		;
231
	mov	r0, r18		;
232
	lsl	r18		;
233
	lsl	r18		;
234
	add	r18, r0		;
235
	add	r18, r21	;
236
	rjmp	22b		;/
237
 
238
24:	brtc	25f		;get value (low word)
239
	neg	r18		;
240
25:	ld	r24, Y+		;
241
	ld	r25, Y+		;/
242
	cpi	r21, 'c'	;Is type character?
243
	breq	1b		;/
244
	cpi	r21, 's'	;Is type RAM string?
245
	breq	50f		;/
246
	cpi	r21, 'S'	;Is type ROM string?
247
	breq	60f		;/
248
	_MOVW	r23,r22,r25,r24	;r25:r22 = value
249
	clr	r24		;
250
	clr	r25		;
251
	clt			;/
252
	cpi	r21, 'l'	;Is long int?
253
	brne	26f		;
254
	ld	r24, Y+		;get value (high word)
255
	ld	r25, Y+		;
256
	set			;
257
	_LPMI	r21		;/
258
26:	cpi	r21, 'd'	;Is type signed decimal?
259
	brne	27f		;/
260
	ldi	r20, -10	;
261
	brts	40f		;
262
	sbrs	r23, 7		;
263
	rjmp	40f		;
264
	ldi	r24, -1		;
265
	ldi	r25, -1		;
266
	rjmp	40f		;/
267
27:	cpi	r21, 'u'	;Is type unsigned decimal?
268
	ldi	r20, 10		;
269
	breq	40f		;/
270
	cpi	r21, 'X'	;Is type hexdecimal?
271
	ldi	r20, 16		;
272
	breq	40f		;/
273
	cpi	r21, 'b'	;Is type binary?
274
	ldi	r20, 2		;
275
	breq	40f		;/
276
	rjmp	90b		;abort
277
40:	push	ZH		;Output the value
278
	push	ZL		;
279
	rcall	xitoa		;
280
42:	pop	ZL		;
281
	pop	ZH		;
282
	rjmp	0b		;/
283
 
284
50:	push	ZH		;Put a string on the RAM
285
	push	ZL
286
	_MOVW	ZH,ZL, r25,r24
287
51:	ld	r24, Z+
288
	cpi	r24, 0
289
	breq	42b
290
	rcall	xputc
291
	rjmp	51b
292
 
293
60:	push	ZH		;Put a string on the ROM
294
	push	ZL
295
	rcall	xputs
296
	rjmp	42b
297
 
298
.endfunc
299
#endif
300
 
301
 
302
 
303
;---------------------------------------------------------------------------
304
; Extended numeral string input
305
;
306
;Prototype:
307
; char xatoi (           /* 1: Successful, 0: Failed */
308
;      const char **str, /* pointer to pointer to source string */
309
;      long *res         /* result */
310
; );
311
;Size: 94/91 words
312
;
313
 
314
#ifdef USE_XATOI
315
.global xatoi
316
.func xatoi
317
xatoi:
318
	_MOVW	r1, r0, r23, r22
319
	_MOVW	XH, XL, r25, r24
320
	ld	ZL, X+
321
	ld	ZH, X+
322
	clr	r18		;r21:r18 = 0;
323
	clr	r19		;
324
	clr	r20		;
325
	clr	r21		;/
326
	clt			;T = 0;
327
 
328
	ldi	r25, 10		;r25 = 10;
329
	rjmp	41f		;/
330
40:	adiw	ZL, 1		;Z++;
331
41:	ld	r22, Z		;r22 = *Z;
332
	cpi	r22, ' '	;if(r22 == ' ') continue
333
	breq	40b		;/
334
	brcs	70f		;if(r22 < ' ') error;
335
	cpi	r22, '-'	;if(r22 == '-') {
336
	brne	42f		; T = 1;
337
	set			; continue;
338
	rjmp	40b		;}
339
42:	cpi	r22, '9'+1	;if(r22 > '9') error;
340
	brcc	70f		;/
341
	cpi	r22, '0'	;if(r22 < '0') error;
342
	brcs	70f		;/
343
	brne	51f		;if(r22 > '0') cv_start;
344
	ldi	r25, 8		;r25 = 8;
345
	adiw	ZL, 1		;r22 = *(++Z);
346
	ld	r22, Z		;/
347
	cpi	r22, ' '+1	;if(r22 <= ' ') exit;
348
	brcs	80f		;/
349
	cpi	r22, 'b'	;if(r22 == 'b') {
350
	brne	43f		; r25 = 2;
351
	ldi	r25, 2		; cv_start;
352
	rjmp	50f		;}
353
43:	cpi	r22, 'x'	;if(r22 != 'x') error;
354
	brne	51f		;/
355
	ldi	r25, 16		;r25 = 16;
356
 
357
50:	adiw	ZL, 1		;Z++;
358
	ld	r22, Z		;r22 = *Z;
359
51:	cpi	r22, ' '+1	;if(r22 <= ' ') break;
360
	brcs	80f		;/
361
	cpi	r22, 'a'	;if(r22 >= 'a') r22 =- 0x20;
362
	brcs	52f		;
363
	subi	r22, 0x20	;/
364
52:	subi	r22, '0'	;if((r22 -= '0') < 0) error;
365
	brcs	70f		;/
366
	cpi	r22, 10		;if(r22 >= 10) {
367
	brcs	53f		; r22 -= 7;
368
	subi	r22, 7		; if(r22 < 10) 
369
	cpi	r22, 10		;
370
	brcs	70f		;}
371
53:	cp	r22, r25	;if(r22 >= r25) error;
372
	brcc	70f		;/
373
60:	ldi	r24, 33		;r21:r18 *= r25;
374
	sub	r23, r23	;
375
61:	brcc	62f		;
376
	add	r23, r25	;
377
62:	lsr	r23		;
378
	ror	r21		;
379
	ror	r20		;
380
	ror	r19		;
381
	ror	r18		;
382
	dec	r24		;
383
	brne	61b		;/
384
	add	r18, r22	;r21:r18 += r22;
385
	adc	r19, r24	;
386
	adc	r20, r24	;
387
	adc	r21, r24	;/
388
	rjmp	50b		;repeat
389
 
390
70:	ldi	r24, 0
391
	rjmp	81f
392
80:	ldi	r24, 1
393
81:	brtc	82f
394
	clr	r22
395
	com	r18
396
	com	r19
397
	com	r20
398
	com	r21
399
	adc	r18, r22
400
	adc	r19, r22
401
	adc	r20, r22
402
	adc	r21, r22
403
82:	st	-X, ZH
404
	st	-X, ZL
405
	_MOVW	XH, XL, r1, r0
406
	st	X+, r18
407
	st	X+, r19
408
	st	X+, r20
409
	st	X+, r21
410
	clr	r1
411
	ret
412
.endfunc
413
#endif
414
 
415