Change long long printing routine to a new technique not using division.

The core loop uses the 65816's decimal mode to create a BCD representation of the number, then we convert that to ASCII to print it. The idea is based on some code from Kent Dickey, with adjustments to fit this codebase. This technique should be faster, and also should typically result in smaller code, since the long long division routine will not need to be linked into every program that uses printf.
This commit is contained in:
Stephen Heumann 2021-02-21 18:33:04 -06:00
parent 52c011ab48
commit 9af245933c

View File

@ -4009,7 +4009,7 @@ rn3 inc argp
* Inputs: * Inputs:
* llValue - the unsigned long long value * llValue - the unsigned long long value
* strPtr - pointer to string buffer * strPtr - pointer to string buffer
* strLength - length of string buffer * strLength - length of string buffer (must be >= 20)
* *
**************************************************************** ****************************************************************
* *
@ -4018,36 +4018,68 @@ rn3 inc argp
dec strLength dec strLength
lb1 ph8 <llValue divide by 10 ldx #8
ph8 #10 initbcd stz bcdnum,x
jsl ~UDIV8 dex
pl8 llValue dex
pla get the last digit bpl initbcd
plx
plx ldy #64
plx sed use BCD
ora #$30 compute ASCII value for digit bitloop asl llValue
short M store ASCII value rol llValue+2
ldy strLength rol llValue+4
sta [strPtr],y rol llValue+6 carry is now high bit from llValue
long M ldx #8
dec strLength addloop lda bcdnum,x bcdNum := bcdNum*2 + carry (in BCD)
bmi ret adc bcdnum,x
lda llValue loop if remaining value is not 0 dey make fully big-endian on last iteration
ora llValue+2 bne notlast
ora llValue+4 xba
ora llValue+6 notlast iny
bne lb1 sta bcdnum,x
dex
short M pad with spaces dex
ldy strLength bpl addloop
lda #' '
lb2 sta [strPtr],y
dey dey
bpl lb2 bne bitloop
cld
short M convert BCD to ASCII
ldx #9
ldy strLength
bcdloop lda bcdnum,x
and #$0F
ora #$30 low digit to ASCII
sta [strPtr],y
dey
lda bcdnum,x
lsr a
lsr a
lsr a
lsr a
ora #$30 high digit to ASCII
sta [strPtr],y
dey
dex
bpl bcdloop
rmzeros iny remove leading zeros
lda [strPtr],y
cmp #'0'
bne padit
cpy strLength
bne rmzeros
padit dey pad with spaces
lda #' '
padloop sta [strPtr],y
dey
bpl padloop
long M long M
ret lret lret
bcdnum ds 10
end end
**************************************************************** ****************************************************************