1
0
mirror of https://github.com/cc65/cc65.git synced 2024-11-14 05:05:45 +00:00
cc65/libsrc/common/atoi.s

157 lines
2.1 KiB
ArmAsm
Raw Normal View History

;
; Ullrich von Bassewitz, 05.06.1998
;
; int atoi (const char* s);
; long atol (const char* s);
;
.export _atoi, _atol
.import __ctype
.importzp sreg, ptr1, ptr2, tmp1
;
; 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 #$80 ; 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. Be shure to negate the value if needed.
L8: lda ptr2
ldx ptr2+1
ldy tmp1 ; sign
beq L9
; Negate the 32 bit value in ptr2/sreg
sec
lda ptr2
eor #$FF
adc #0
sta ptr2
lda ptr2+1
eor #$FF
adc #0
sta ptr2+1
lda sreg
eor #$FF
adc #0
sta sreg
lda sreg+1
eor #$FF
adc #0
sta sreg+1
; Done, load the low 16 bit into A/X
L9: lda ptr2
ldx ptr2+1 ; get value
rts
;
; Helper functions
;
mul2:
asl ptr2
rol ptr2+1
rol sreg
rol sreg+1 ; * 2
rts