File: itoa.S

package info (click to toggle)
avr-libc 20020203-2
  • links: PTS
  • area: main
  • in suites: woody
  • size: 1,448 kB
  • ctags: 6,562
  • sloc: ansic: 7,631; asm: 4,424; sh: 2,703; makefile: 338; pascal: 289
file content (80 lines) | stat: -rw-r--r-- 2,081 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
/*
   itoa.S

   Copyright (C) 2000 Michael Rickmann <mrickma@gwdg.de>
   Changes: Reiner Patommel <rpato@post4.tele.dk>
   	    (no stack space used anymore)

   Permission to use, copy, modify, and distribute this software and
   its documentation for any purpose and without fee is hereby granted,
   without any conditions or restrictions.  This software is provided
   "as is" without express or implied warranty.

   #include <stdlib.h>
   char *itoa(int value, char *string, int radix);
  ----------------------------------------------------------------------
*/

#include "macros.inc"
#include "ctoasm.inc"

   .global _U(itoa)
   .func _U(itoa)

/* arguments */
#define r_val_hi r25
#define r_val_lo r24
#define r_str_hi r23
#define r_str_lo r22
#define r_radix  r20

/* local variables */
#define r_lstr_hi r19
#define r_lstr_lo r18

_U(itoa):
	mov	ZL, r_str_lo	; *string
	mov	ZH, r_str_hi
	mov	r_lstr_lo, ZL	; save &string
	mov	r_lstr_hi, ZH
	cpi	r_radix, 2	; no radix < 2
	brlt	terminate
	cpi	r_radix, 10	; decimal number ?
	brne	divide_loop
	bst	r_val_hi, 7	; remember sign of value
	tst	r_val_hi	; sign of value ?
	brge	divide_loop
	com	r_val_hi	; make positive
	neg	r_val_lo
	sbci	r_val_hi, 0xff
divide_loop:
	mov	r22, r_radix	; radix
	clr	r23		;  dividend in r25:r24, divisor in r23:r22
	XCALL	_U(__udivmodhi4);  quotient in r23:r22, remainder in r25:r24
				;  clobbered: r0, r21, r26, r27
				;  call-used but preserved: r18, r19, r20, r30, r31
	subi	r24, 0xd0	; + '0'
	cpi	r24, 0x3a	; > '9' ?
	brlt	L_10
	subi	r24, 0xd9	; + 'a' - 10 - '0'
L_10:
	st	Z+, r24		; write char to string in reverse order
	mov	r_val_lo, r22	; quotient -> dividend
	mov	r_val_hi, r23
	sbiw	r_val_lo, 0	; value == 0 ?
	brne	divide_loop
	clr	r21
	bld	r21, 0		; get sign again
	tst	r21		; negative number?
	breq	n_terminate	; no, positive
	ldi	r21, '-'
	st	Z+, r21		; write minus sign to string
n_terminate:			; restore &string as return value
	mov	r_val_hi, r_lstr_hi
	mov	r_val_lo, r_lstr_lo
terminate:
	st	Z, __zero_reg__	; terminate string
	XJMP	_U(strrev)	; reverse string

	.endfunc