1
/* Copyright (c) 2002, Reiner Patommel
1
/* Copyright (c) 2002, 2007 Reiner Patommel
4
4
Redistribution and use in source and binary forms, with or without
26
26
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
27
POSSIBILITY OF SUCH DAMAGE. */
29
/* $Id: atol.S,v 1.9 2005/11/09 23:51:43 aesok Exp $ */
29
/* $Id: atol.S,v 1.9.2.2 2007/03/25 14:35:00 dmix Exp $ */
35
35
Created by Reiner Patommel
36
36
Modified by Reiner Patommel 8 Feb 2003, Bug #2481
37
37
Modified by Reiner Patommel 13 May 2003, (DOXYGEN)
39
TODO: this implementation uses an inline isspace(). If Avr-libc will
40
use locales other than C/POSIX it is needed to call an external isspace().
42
ATTENTION: an external __mulsi_const_10() function is used: nonstandart
43
call conventions: some registers and bit T must be nochanged.
40
46
#include "macros.inc"
51
59
/** \ingroup avr_stdlib
52
\fn long int atol(const char *string)
60
\fn long atol(const char *s)
53
61
\brief Convert a string to a long integer.
55
63
The atol() function converts the initial portion of the string
56
pointed to by \c stringp to integer representation.
60
\code strtol(nptr, (char **)NULL, 10); \endcode
61
except that atol() does not detect errors.
64
pointed to by \p s to long integer representation. In contrast to
66
\code strtol(s, (char **)NULL, 10); \endcode
68
this function does not detect overflow (\c errno is not changed and
69
the result value is not predictable), uses smaller memory (flash and
70
stack) and works more quickly.
64
73
#if !defined(__DOXYGEN__)
73
82
no numeric characters.
85
/* This fact is used below. */
86
.if ('\t'-9) | ('\n'-10) | ('\f'-12) | ('\r'-13) ; '\v' is 11
78
92
X_movw ZL, str_lo ; set pointer to string
82
CLR num_lo_lo ; clear number
95
X_movw num_lo_lo, num_hi_lo ; clear number
86
99
LD tmp, Z+ ; get (next) character
87
TST tmp ; is it end of string?
89
100
CPI tmp, ' ' ; skip whitespace
101
107
CPI tmp, '+' ; if '+' go on
102
108
BREQ .L_atol_loop2
103
109
CPI tmp, '-' ; if '-' remember sign
104
110
BRNE .L_atol_digit
107
111
SET ; remember number is negative
114
2: XCALL __mulsi_const_10 ; r25:r24:r23:r22 *= 10
115
ADD num_lo_lo, tmp ; num = (num * 10) + (tmp - '0')
116
ADC num_lo_hi, __zero_reg__
117
ADC num_hi_lo, __zero_reg__
118
ADC num_hi_hi, __zero_reg__
115
CPI tmp, '0' ; test on [0 .. 9]
119
122
SUBI tmp, '0' ; make figure a number
120
XCALL __mulsi_const_10 ; r25:r24:r23:r22 *= 10
121
ADD num_lo_lo, tmp ; num = (num * 10) + (tmp - '0')
122
ADC num_lo_hi, __zero_reg__
123
ADC num_hi_lo, __zero_reg__
124
ADC num_hi_hi, __zero_reg__
125
RJMP .L_atol_loop2 ; next figure
128
CP num_lo_lo, __zero_reg__
129
CPC num_lo_hi, __zero_reg__
130
CPC num_hi_lo, __zero_reg__
131
CPC num_hi_hi, __zero_reg__ ; did we get a number?
132
BREQ .L_atol_done ; no, drop sign and return
133
126
BRTC .L_atol_done ; positive number? -> return