1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-23 19:29:37 +00:00
cc65/libsrc/common/atoi.s

139 lines
2.9 KiB
ArmAsm

;
; Ullrich von Bassewitz, 05.06.1998
;
; int atoi (const char* s);
; long atol (const char* s);
;
.export _atoi, _atol
.import negeax, __ctype
.importzp sreg, ptr1, ptr2, tmp1
.include "ctype.inc"
;
; Conversion routine (32 bit)
;
_atoi:
_atol: sta ptr1 ; Store s
stx ptr1+1
ldy #0
sty ptr2
sty ptr2+1 ; initial value (32 bit)
sty sreg
sty sreg+1
; Skip whitespace
L1: lda (ptr1),y
tax
lda __ctype,x ; get character classification
and #CT_SPACE_TAB ; tab or space?
beq L2 ; jump if no
iny
bne L1
inc ptr1+1
bne L1 ; branch always
; Check for a sign. The character is in X
L2: txa ; get char
ldx #0 ; flag: positive
cmp #'+' ; ### portable?
beq L3
cmp #'-' ; ### portable?
bne L5
dex ; flag: negative
L3: iny
bne L5
inc ptr1+1
; Store the sign flag and setup for conversion
L5: stx tmp1 ; remember sign flag
L6: lda (ptr1),y ; get next char
tax
lda __ctype,x ; get character classification
and #$04 ; digit?
beq L8 ; done
; Multiply ptr2 (the converted value) by 10
jsr mul2 ; * 2
lda sreg+1
pha
lda sreg
pha
lda ptr2+1
pha
lda ptr2
pha ; Save value
jsr mul2 ; * 4
jsr mul2 ; * 8
clc
pla
adc ptr2
sta ptr2
pla
adc ptr2+1
sta ptr2+1
pla
adc sreg
sta sreg
pla
adc sreg+1
sta sreg+1 ; x*2 + x*8 = x*10
; Get the character back and add it
txa ; get char back
sec
sbc #'0' ; make numeric value
clc
adc ptr2
sta ptr2
bcc L7
inc ptr2+1
bne L7
inc sreg
bne L7
inc sreg+1
; Next character
L7: iny
bne L6
inc ptr1+1
bne L6
; Conversion done. Load the low 16 bit into A/X
L8: lda ptr2
ldx ptr2+1
; Negate the value if necessary, otherwise we're done
ldy tmp1 ; sign
beq L9 ; Branch if positive
; Negate the 32 bit value in ptr2/sreg
jmp negeax
;
; Helper functions
;
mul2: asl ptr2
rol ptr2+1
rol sreg
rol sreg+1 ; * 2
L9: rts