Implement negative number parsing

This commit is contained in:
PleegWat
2026-09-03 13:42:11 +02:00
parent 2c6e025dff
commit 836b977fc9
2 changed files with 65 additions and 36 deletions
+50 -22
View File
@@ -1,3 +1,9 @@
; Internal convention:
; r1 - Partially parsed output integer
; r2 - Parsing position
; r3 - Character being parsed
; r4 - Flag set if negative
; Convert string to integer ; Convert string to integer
; Arguments: ; Arguments:
; r1 - Pointer to string ; r1 - Pointer to string
@@ -9,30 +15,37 @@
; r3 - last character read ; r3 - last character read
; Note: Unless the input is "0", tail-calls into a base-specific specialization. ; Note: Unless the input is "0", tail-calls into a base-specific specialization.
pub atoi: pub atoi:
load_8 r3, [r1]
cmp r3, 0x30 ; '0'
jne atoi_dec ; No prefix, parse decimal
add r1, r1, 1
load_8 r3, [r1] ; From "boxBOX", or an octal digit
cmp r3, 0x30 ; '0'
jl atoi_badprefix
cmp r3, 0x37 ; '7'
jle atoi_oct
add r1, r1, 1 ; Not octal; 2-byte prefix
and r3, r3, 0x5f ; to uppercase
cmp r3, 0x42 ; 'B'
je atoi_bin
cmp r3, 0x4F ; 'O'
je atoi_oct
cmp r3, 0x58 ; 'X'
je atoi_hex
; not a valid prefix, but we did see a zero
atoi_badprefix:
mov r2, r1 mov r2, r1
mov r1, 0 mov r1, 0
; Only exists because conditional register jumps are not allowed mov r4, 0
load_8 r3, [r2]
cmp r3, 0x2D ; '-'
jne atoi_positive
sub r4, zr, 1 ; Set r4 to -1
add r2, r2, 1
load_8 r3, [r2]
atoi_positive:
cmp r3, 0x30 ; '0'
jne atoi_dec_loop ; No prefix, parse decimal
add r2, r2, 1
load_8 r3, [r2] ; From "boxBOX", or an octal digit
cmp r3, 0x30 ; '0'
jl atoi_done
cmp r3, 0x37 ; '7'
jle atoi_oct_loop ; Octal with just '0' prefix
add r2, r2, 1 ; 2-byte prefix
and r3, r3, 0x5F ; to uppercase
cmp r3, 0x42 ; 'B'
je atoi_bin_loop
cmp r3, 0x4F ; 'O'
je atoi_oct_loop
cmp r3, 0x58 ; 'X'
je atoi_hex_loop
; FALLTHROUGH: not a valid prefix, but we did see a zero
atoi_done: atoi_done:
add r1, r1, r4
xor r1, r1, r4
jmp r13 jmp r13
; Convert decimal string to integer ; Convert decimal string to integer
@@ -73,6 +86,11 @@ jmp atoi_dec_loop
pub atoi_bin: pub atoi_bin:
mov r2, r1 mov r2, r1
mov r1, 0 mov r1, 0
load_16 r3, [r2] ; check for prefix
and r3, r3, 0xFF5F ; to uppercase
cmp r3, 0x3042 ; "0B"
jne atoi_bin_loop
add r2, r2, 2
atoi_bin_loop: atoi_bin_loop:
load_8 r3, [r2] load_8 r3, [r2]
cmp r3, 0x30 ; '0' cmp r3, 0x30 ; '0'
@@ -97,6 +115,11 @@ jmp atoi_bin_loop
pub atoi_oct: pub atoi_oct:
mov r2, r1 mov r2, r1
mov r1, 0 mov r1, 0
load_16 r3, [r2] ; check for prefix
and r3, r3, 0xFF5F ; to uppercase
cmp r3, 0x304F ; "0O"
jne atoi_oct_loop
add r2, r2, 2
atoi_oct_loop: atoi_oct_loop:
load_8 r3, [r2] load_8 r3, [r2]
cmp r3, 0x30 ; '0' cmp r3, 0x30 ; '0'
@@ -121,6 +144,11 @@ jmp atoi_oct_loop
pub atoi_hex: pub atoi_hex:
mov r2, r1 mov r2, r1
mov r1, 0 mov r1, 0
load_16 r3, [r2] ; check for prefix
and r3, r3, 0xFF5F ; to uppercase
cmp r3, 0x3058 ; "0X"
jne atoi_oct_loop
add r2, r2, 2
atoi_hex_loop: atoi_hex_loop:
load_8 r3, [r2] load_8 r3, [r2]
cmp r3, 0x30 ; '0' cmp r3, 0x30 ; '0'
@@ -134,7 +162,7 @@ add r1, r1, r3
jmp atoi_hex_loop jmp atoi_hex_loop
atoi_hex_letter: atoi_hex_letter:
and r3, r3, 0x5f ; to uppercase and r3, r3, 0x5F ; to uppercase
cmp r3, 0x41 ; 'A' cmp r3, 0x41 ; 'A'
jl atoi_done jl atoi_done
cmp r3, 0x46 ; 'F' cmp r3, 0x46 ; 'F'
+14 -13
View File
@@ -33,21 +33,22 @@ jl next_test
; Done ; Done
success: jmp success success: jmp success
include stdlib include stdlib
@0x1000 @0x1000
tests: tests:
; addr result inlen instr ; inlen is the number of input bytes the function is expected to consume
@0x1000 U32 0 U8 0 "\0" ; addr result inlen instr
@0x1010 U32 0 U8 1 "0\0" @0x1000 U32 0 U8 0 "\0"
@0x1020 U32 1 U8 1 "1\0" @0x1010 U32 0 U8 1 "0\0"
@0x1030 U32 2 U8 1 "2\0" @0x1020 U32 1 U8 1 "1\0"
@0x1040 U32 42 U8 2 "42\0" @0x1030 U32 2 U8 1 "2\0"
@0x1050 U32 67 U8 2 "67lol\0" @0x1040 U32 42 U8 2 "42\0"
@0x1060 U32 0x69a U8 5 "0x69a\0" @0x1050 U32 67 U8 2 "67lol\0"
@0x1070 U32 0o23 U8 3 "0239\0" @0x1060 U32 0x69a U8 5 "0x69a\0"
@0x1080 U32 0b1011 U8 6 "0b1011\0" @0x1070 U32 0o23 U8 3 "0239\0"
@0x1090 U32 0b10001 U8 7 "0b100012\0" @0x1080 U32 0b1011 U8 6 "0b1011\0"
@0x1090 U32 0b10001 U8 7 "0b100012\0"
@0x10a0 U32 0xFFFFFFEB U8 3 "-21\0" ; Yuk
@0x10b0
end_of_tests: end_of_tests: