83 lines
2.4 KiB
ArmAsm
83 lines
2.4 KiB
ArmAsm
.global fmt_decimal
|
|
.global count_digits
|
|
|
|
.extern clz
|
|
.extern divmod
|
|
|
|
.section .rodata
|
|
|
|
hexchars:
|
|
.ascii "0123456789ABCDEF"
|
|
|
|
powers10:
|
|
.word 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
|
|
.set powers10_end, .
|
|
|
|
.text
|
|
|
|
# Write decimal representation of word into buffer
|
|
# arguments:
|
|
# a0: value to format
|
|
# a1: address of buffer to write to
|
|
# buffer must have room for at least 10 bytes
|
|
# temporaries used:
|
|
# t0
|
|
# return:
|
|
# a0: length of string written to buffer
|
|
fmt_decimal:
|
|
# until the value is zero:
|
|
# divmod value by 10
|
|
# write remainder to output buffer as ASCII char
|
|
# increment string length
|
|
# subtract remainder from value
|
|
# if we can know how many digits there will be up front we can write to the buffer
|
|
# in the right order, if not the buffer will have to be reversed at the end
|
|
addi sp, sp, -16
|
|
sw ra, 12(sp)
|
|
sw s1, 8(sp)
|
|
sw s0, 4(sp)
|
|
mv s0, a0 # save value in a0 to s0
|
|
mv s1, a1 # save buffer address to s1
|
|
jal count_digits
|
|
sw a0, 0(sp) # save digit count to return at the end
|
|
addi a0, a0, -1 # a0 -= 1
|
|
add s1, s1, a0 # add the digit count to the buffer address
|
|
1:
|
|
mv a0, s0 # load dividend from s0
|
|
li a1, 10 # set divisor to 10
|
|
jal divmod # divmod value by 10, a1 = remainder
|
|
mv s0, a0 # move quotent to s0
|
|
addi a1, a1, 0x30 # turn remainder into ASCII digit
|
|
sb a1, 0(s1) # write the digit to the output buffer
|
|
addi s1, s1, -1 # decrement buffer address
|
|
bnez s0, 1b
|
|
|
|
lw a0, 0(sp) # load digit count into a0
|
|
lw s0, 4(sp)
|
|
lw s1, 8(sp)
|
|
lw ra, 12(sp)
|
|
addi sp, sp, 16
|
|
ret
|
|
|
|
|
|
# Calculate number of decimal digits input word has.
|
|
# arguments:
|
|
# a0: value to count
|
|
# return:
|
|
# a0: count of decimal digits
|
|
count_digits:
|
|
mv a2, a0 # a2 = value
|
|
la a1, powers10 # a1 = powers10
|
|
la a4, powers10_end # a4 = powers10_end
|
|
li a0, 0 # a0 = powers array offset * 4
|
|
1:
|
|
bgeu a1, a4, 2f # if a1 >= powers10_end return 10
|
|
lw a3, 0(a1) # a3 = load value from powers array
|
|
addi a0, a0, 1 # increment offset
|
|
bltu a2, a3, 3f # if a2 < a3 return
|
|
addi a1, a1, 4 # a1 = index into powers array
|
|
j 1b # loop
|
|
2:
|
|
li a0, 10
|
|
3:
|
|
ret
|