Add armv4t assembly optimized integer to string conversion functions

This commit is contained in:
Myles Busig 2024-03-24 01:07:24 -06:00
parent 998e3adf4d
commit 0a84391c39

245
src/armv4t/to.s Normal file
View File

@ -0,0 +1,245 @@
.syntax unified
.include "mtl/armv4t/asm/math.s"
.section .rodata
.align 1
hex_digits_lo:
.string "0123456789abcdef"
hex_digits_up:
.string "0123456789ABCDEF"
.section .iwram, "ax", %progbits
.arm
.align 2
/*
* Writes the ASCII representation of the given unsigned value X to the buffer,
* writes the beginning address of the string to an output ptr, and returns
* the number of characters written. The value is written in hexidecimal
* format.
*
* r0 = x
* r1 = buffer start
* r2 = buffer size
* r3 = string start out ptr
* ret= num of characters written
*/
.global mtl_utostrx
.type mtl_utostrx STT_FUNC
mtl_utostrx:
// Store variables
push {r4-r7}
// Move buffer to end
add r1, r2
sub r1, $1
// Add null terminator and decrement
mov r6, $0
str r6, [r1], $-1
// Load digit address
ldr r4, =hex_digits_lo
// Zero num of characters
mov r7, $0
.Ldecode_digitx:
// Increment number of characters
add r7, $1
// Get least significant octet
and r6, r0, 0xF
// Write the ascii digit to the string
ldrb r5, [r4, r6]
strb r5, [r1], $-1
// Shift to remove the least significant octet
lsrs r0, $4
// Repeat if there are more digits left
bne .Ldecode_digitx
// Move to the start of the string and account for "0x",
// currently one character before
sub r1, $1
//add r1, $1
// Write "0x" to the beginning of the string
mov r6, '0'
strb r6, [r1]
mov r6, 'x'
strb r6, [r1, $1]
// Write the start of the string to the pointer
str r1, [r3]
// Return the number of characters written, account for "0x"
add r0, r7, $2
// Restore variables
pop {r4-r7}
bx lr
/*
* Writes the ASCII representation of the given unsigned value X to the buffer,
* writes the beginning address of the string to an output ptr, and returns
* the number of characters written. The value is written in decimal format.
*
* r0 = x
* r1 = buffer start
* r2 = buffer size
* r3 = string start out ptr
* ret= num of characters written
*/
.global mtl_utostr
.type mtl_utostr STT_FUNC
mtl_utostr:
// Store variables
push {r4-r7}
// Move buffer to end
add r1, r2
sub r1, $1
// Add null terminator and decrement
mov r6, $0
str r6, [r1], $-1
// Zero num of characters
mov r7, $0
.Ldecode_digit:
// Increment number of characters
add r7, $1
// Use % 10 to get the least significant digit
umod10 r6, r0, r12
// Write the ascii digit to the string
add r5, r6, '0'
strb r5, [r1], $-1
// Divide by 10 to remove the least significant digit
udiv10 r6, r0, r12
mov r0, r6
// Repeat if there are more digits left
bne .Ldecode_digit
// Move to the start of the string, currently one char before
add r1, $1
// Write the start of the string to the pointer
str r1, [r3]
// Return the number of characters written
mov r0, r7
// Restore variables
pop {r4-r7}
bx lr
/*
* Writes the ASCII representation of the given signed value X to the buffer,
* writes the beginning address of the string to an output ptr, and returns
* the number of characters written. The value is written in hexidecimal
* format.
*
* r0 = x
* r1 = buffer start
* r2 = buffer size
* r3 = string start out ptr
* ret= num of characters written
*/
.global mtl_itostrx
.type mtl_itostrx STT_FUNC
mtl_itostrx:
// Store variables
push {r4-r8}
// r8 = 1 if negative, 0 if positive. Negate if negative
lsrs r8, r0, $31
mvnne r0, r0
addne r0, $1
// Move buffer to end
add r1, r2
sub r1, $1
// Add null terminator and decrement
mov r6, $0
str r6, [r1], $-1
// Load digit address
ldr r4, =hex_digits_lo
// Zero num of characters
mov r7, $0
.Lsdecode_digitx:
// Increment number of characters
add r7, $1
// Get least significant octet
and r6, r0, 0xF
// Write the ascii digit to the string
ldrb r5, [r4, r6]
strb r5, [r1], $-1
// Shift to remove the least significant octet
lsrs r0, $4
// Repeat if there are more digits left
bne .Lsdecode_digitx
// Move to the start of the string and account for "0x",
// currently one character before
sub r1, $1
// Write "0x" to the beginning of the string
mov r6, '0'
strb r6, [r1]
mov r6, 'x'
strb r6, [r1, $1]
// Check if number is negative
cmp r8, $0
// Add the negative sign to the string and increase number of
// characters written if needed
subne r1, $1
movne r6, '-'
strbne r6, [r1]
addne r7, $1
// Write the start of the string to the pointer
str r1, [r3]
// Return the number of characters written, account for "0x"
add r0, r7, $2
// Restore variables
pop {r4-r8}
bx lr
/*
* Writes the ASCII representation of the given signed value X to the buffer,
* writes the beginning address of the string to an output ptr, and returns
* the number of characters written. The value is written in decimal format.
*
* r0 = x
* r1 = buffer start
* r2 = buffer size
* r3 = string start out ptr
* ret= num of characters written
*/
.global mtl_itostr
.type mtl_itostr STT_FUNC
mtl_itostr:
// Store variables
push {r4-r8}
// r8 = 1 if negative, 0 if positive. Negate if negative
lsrs r8, r0, $31
mvnne r0, r0
addne r0, $1
// Move buffer to end
add r1, r2
sub r1, $1
// Add null terminator and decrement
mov r6, $0
str r6, [r1], $-1
// Zero num of characters
mov r7, $0
.Lsdecode_digit:
// Increment number of characters
add r7, $1
// Use % 10 to get the least significant digit
umod10 r6, r0, r12
// Write the ascii digit to the string
add r5, r6, '0'
strb r5, [r1], $-1
// Divide by 10 to remove the least significant digit
udiv10 r6, r0, r12
mov r0, r6
// Repeat if there are more digits left
bne .Lsdecode_digit
// Check if number is negative
cmp r8, $0
// Add the negative sign to the string and increase number of
// characters written if needed
movne r6, '-'
strbne r6, [r1]
addne r7, $1
// If the number was positive, currently positioned one char before str
// If the number was negative, currently at the correct position
// Move one character forward if needed
addeq r1, $1
// Write the start of the string to the pointer
str r1, [r3]
// Return the number of characters written
mov r0, r7
// Restore variables
pop {r4-r8}
bx lr