File: atoi.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 (97 lines) | stat: -rw-r--r-- 2,571 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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
/*
   atoi.S

   Contributors:
     Created by Reiner Patommel
     Changes: Jochen Pernsteiner, Marek Michalkiewicz

   THIS SOFTWARE IS NOT COPYRIGHTED

   This source code is offered for use in the public domain.  You may
   use, modify or distribute it freely.

   This code is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY.  ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
   DISCLAIMED.  This includes but is not limited to warranties of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "macros.inc"

#define str_hi r25
#define str_lo r24
#define num_hi r25
#define num_lo r24
#define sign   r19
#define tmp    r18

; int atoi(const char *string)

    .text
    .global _U(atoi)
    .type   _U(atoi), @function

/*
   Skip leading spaces and tabs.  Process optional sign.  Stop conversion
   on detection of a non-numeric character.  Return 0 if string contains
   no numeric characters. No check is performed whether the value is within
   the range of an 'int' i.e. 32768 becomes -32768.
 */

_U(atoi):
	LOAD_Z(str_lo, str_hi)      ; set pointer to string
	CLR   num_lo
	CLR   num_hi
	CLR   sign                  ; sign
.atoi_loop:
	LD    tmp, Z+               ; get (next) character
	TST   tmp                   ; is it end of string
	BREQ  .atoi_sig
	CPI   tmp, ' '              ; if space, skip
	BREQ  .atoi_loop
	CPI   tmp, '\t'	            ; if tab, skip
	BREQ  .atoi_loop
	CPI   tmp, '\n'             ; skip other whitespace
	BREQ  .atoi_loop
	CPI   tmp, '\f'
	BREQ  .atoi_loop
	CPI   tmp, '\r'
	BREQ  .atoi_loop
	CPI   tmp, '\v'
	BREQ  .atoi_loop
	CPI   tmp, '+'	            ; if '+' go on
	BREQ  .atoi_loop2
	CPI   tmp, '-'              ; if '-' remember sign
	BRNE  .atoi_digit
.atoi_neg:
	LDI   sign, 1               ; remember number is negative

.atoi_loop2:
	LD    tmp, Z+
	TST tmp
	BREQ .atoi_sig
.atoi_digit:
	CPI  tmp, '0'               ; test on [0 .. 9]
	BRLT  .atoi_sig
	CPI  tmp, '9'+1
	BRGE  .atoi_sig
	SUBI  tmp, '0'              ; make figure a number
	XCALL __mulhi_const_10      ; r25:r24 *= 10
	ADD   num_lo, tmp           ; num = (num * 10) + (tmp - '0')
	ADC   num_hi, __zero_reg__
	RJMP  .atoi_loop2           ; next figure
.atoi_sig:
	CP    num_lo, __zero_reg__
	CPC   num_hi, __zero_reg__  ; did we get a number?
	BREQ  .atoi_done            ; no, drop sign and return
	TST    sign                 ; positive number?
	BREQ  .atoi_done
	COM   num_lo
	COM   num_hi
	ADIW  num_lo, 1             ; make number negative

.atoi_done:
	RET
.atoi_end:
	.size _U(atoi), .atoi_end - _U(atoi)