Int to string conversion
Initially only binary output
This commit is contained in:
+4
-1
@@ -21,7 +21,10 @@ pub const SCREEN_INVALID_WIDTH = 0x0003
|
|||||||
pub const SCREEN_FB_TOO_SMALL = 0x0005
|
pub const SCREEN_FB_TOO_SMALL = 0x0005
|
||||||
pub const SCREEN_OUTSIDE_FB = 0x0007
|
pub const SCREEN_OUTSIDE_FB = 0x0007
|
||||||
|
|
||||||
|
pub const INTTOSTR_BAD_BASE = 0x0101
|
||||||
|
pub const INTTOSTR_BAD_BUFFER = 0x0103
|
||||||
|
|
||||||
pub const MAGIC_BAD = 0x8001
|
pub const MAGIC_BAD = 0x8001
|
||||||
|
|
||||||
; Extended error codes, these would require loading a 32 bit value.
|
; Extended error codes, these would require loading a 32 bit value.
|
||||||
pub const EXT_OK = 0x00000000
|
pub const EXT_OK = 0x00000000
|
||||||
|
|||||||
@@ -0,0 +1,66 @@
|
|||||||
|
include errno
|
||||||
|
|
||||||
|
; Convert integer to string
|
||||||
|
; Arguments:
|
||||||
|
; r1 - Integer
|
||||||
|
; r2 - Start of buffer
|
||||||
|
; r3 - Buffer length
|
||||||
|
; r4 - Base (2, 8, 10, or 16)
|
||||||
|
; Result:
|
||||||
|
; none
|
||||||
|
; Clobbers:
|
||||||
|
; Based on specialization
|
||||||
|
pub auto:
|
||||||
|
cmp r4, 2
|
||||||
|
je bin
|
||||||
|
mov flags, errno.INTTOSTR_BAD_BASE
|
||||||
|
jmp r13
|
||||||
|
|
||||||
|
; Convert integer to binary string
|
||||||
|
; Arguments:
|
||||||
|
; r1 - Integer
|
||||||
|
; r2 - Start of buffer (assumed 'big enough')
|
||||||
|
; r3 - Buffer length (ignored)
|
||||||
|
; Result:
|
||||||
|
; none
|
||||||
|
; Clobbers:
|
||||||
|
; flags
|
||||||
|
; r4 - counter
|
||||||
|
; r5 - result character
|
||||||
|
pub bin:
|
||||||
|
mov r4, 31
|
||||||
|
cmp r2, 2
|
||||||
|
jl badbuffer
|
||||||
|
|
||||||
|
bin_find_one:
|
||||||
|
lsr r5, r1, r4 ; Select bit and advance counter
|
||||||
|
and r5, r5, 1
|
||||||
|
sub r4, r4, 1
|
||||||
|
|
||||||
|
cmp r4, 0 ; Start printing if last bit ...
|
||||||
|
jl bin_print
|
||||||
|
cmp r5, zr ; .. or if nonzero
|
||||||
|
je bin_find_one
|
||||||
|
|
||||||
|
add flags, r4, 3 ; Check buffer size
|
||||||
|
cmp flags, r3
|
||||||
|
ja badbuffer
|
||||||
|
|
||||||
|
bin_print:
|
||||||
|
add r5, r5, 0x30 ; '0' ; Add digit to buffer
|
||||||
|
store_8 [r2], r5
|
||||||
|
add r2, r2, 1
|
||||||
|
cmp r4, 0 ; Done if last bit
|
||||||
|
jl done
|
||||||
|
lsr r5, r1, r4 ; Select bit and advance counter
|
||||||
|
and r5, r5, 1
|
||||||
|
sub r4, r4, 1
|
||||||
|
jmp bin_print
|
||||||
|
|
||||||
|
badbuffer:
|
||||||
|
mov flags, errno.INTTOSTR_BAD_BUFFER
|
||||||
|
jmp r13
|
||||||
|
|
||||||
|
done:
|
||||||
|
store_8 [r2], zr
|
||||||
|
jmp r13
|
||||||
@@ -3,7 +3,9 @@ pub include imath
|
|||||||
pub include array
|
pub include array
|
||||||
pub include console
|
pub include console
|
||||||
pub include mem
|
pub include mem
|
||||||
|
pub include string
|
||||||
pub include string_to_int
|
pub include string_to_int
|
||||||
|
pub include int_to_string
|
||||||
|
|
||||||
; Needs to be last!
|
; Needs to be last!
|
||||||
pub include LUTs
|
pub include LUTs
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
; Compare two strings
|
||||||
|
; Arguments:
|
||||||
|
; r1 - Pointer to string 1
|
||||||
|
; r2 - Pointer to string 2
|
||||||
|
; Result:
|
||||||
|
; r1:
|
||||||
|
; - `0` if both segments are equal.
|
||||||
|
; - `<0` if the first segment is less than the second segment.
|
||||||
|
; - `>0` if the first segment is greater than the second segment.
|
||||||
|
; flags - Compare result
|
||||||
|
; Clobbers:
|
||||||
|
; r3 - last byte of r1 tested
|
||||||
|
; r4 - last byte of r2 tested
|
||||||
|
pub compare:
|
||||||
|
load_8 r3, [r1]
|
||||||
|
add r1, r1, 1
|
||||||
|
load_8 r4, [r2]
|
||||||
|
add r2, r2, 1
|
||||||
|
cmp zr, r3 ; End of string 1
|
||||||
|
je done
|
||||||
|
cmp zr, r4 ; End of string 2
|
||||||
|
je done
|
||||||
|
cmp r3, r4
|
||||||
|
je compare ; Loop, tail recursion, what's the difference
|
||||||
|
done:
|
||||||
|
cmp r3, r4
|
||||||
|
; `flags` is the comparison result in the format of `cmp`. Convert it to the desired format.
|
||||||
|
; 00 => 0x40000000 > 0
|
||||||
|
; 01 => 0x00000000 = 0
|
||||||
|
; 10 => 0xC0000000 < 0
|
||||||
|
xor r1, flags, 1
|
||||||
|
lsl r1, r1, 30
|
||||||
|
jmp r13
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
; test harness for int_to_string
|
||||||
|
; Registers:
|
||||||
|
; r8 - test address
|
||||||
|
; r9 - test method
|
||||||
|
; r12 - end of tests address
|
||||||
|
li r8, tests
|
||||||
|
li r12, end_of_tests
|
||||||
|
next_test:
|
||||||
|
; Set up arguments and run test
|
||||||
|
load_32 r1, [r8] ; Input value
|
||||||
|
li r2, scratch ; Output buffer
|
||||||
|
mov r3, 64 ; Output buffer size
|
||||||
|
add r4, r8, 4 ; Base
|
||||||
|
load_8 r4, [r4]
|
||||||
|
mov r13, itoa_test_ret ; return address
|
||||||
|
jmp stdlib.int_to_string.auto
|
||||||
|
itoa_test_ret:
|
||||||
|
|
||||||
|
; Strcmp to check results
|
||||||
|
add r1, r8, 5 ; expected output
|
||||||
|
li r2, scratch ; actual output
|
||||||
|
mov r13, itoa_strcmp_ret
|
||||||
|
jmp stdlib.string.compare
|
||||||
|
itoa_strcmp_ret:
|
||||||
|
|
||||||
|
; Verify results
|
||||||
|
halt.ne
|
||||||
|
|
||||||
|
; Next test
|
||||||
|
add r8, r8, 0x40
|
||||||
|
cmp r8, r12
|
||||||
|
jl next_test
|
||||||
|
|
||||||
|
; Done
|
||||||
|
halt
|
||||||
|
|
||||||
|
include ../src/stdlib
|
||||||
|
|
||||||
|
@0x20000
|
||||||
|
tests:
|
||||||
|
; inlen is the number of input bytes the function is expected to consume
|
||||||
|
; addr int base result
|
||||||
|
@0x20000 U32 0b0 U8 2 "0\0"
|
||||||
|
@0x20040 U32 0xFFFFFFFF U8 2 "11111111111111111111111111111111\0"
|
||||||
|
@0x20080 U32 0b101010 U8 2 "101010\0"
|
||||||
|
@0x200c0
|
||||||
|
end_of_tests:
|
||||||
|
scratch: U1024 0
|
||||||
|
|
||||||
Reference in New Issue
Block a user