From bbb3c150027dbe52d06ac934383975a7d4a87671 Mon Sep 17 00:00:00 2001 From: Madeline Busig Date: Sun, 24 Mar 2024 01:07:24 -0600 Subject: [PATCH] Add armv4t assembly optimized integer to string conversion functions --- src/armv4t/to.s | 245 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 src/armv4t/to.s diff --git a/src/armv4t/to.s b/src/armv4t/to.s new file mode 100644 index 0000000..87f5c1a --- /dev/null +++ b/src/armv4t/to.s @@ -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 +