Merge branch 'main' into bitblt

This commit is contained in:
Michał Isalski
2026-09-07 01:46:43 +02:00
12 changed files with 1105 additions and 24 deletions
Executable
+27
View File
@@ -0,0 +1,27 @@
; Error numbers should be 16 bit ODD numbers, so they can be loaded as immediates
; and can be checked with:
;
; qcall falible_function
; jne falible_ok ; Jump no error
; ; handle error
; falible_ok:
; ; Happy path
; ; ...
; OR
; qcall falible_function
; je handle_error ; Jump if error
; ; Happy path
; ; ...
; handle_error:
; ; handle error
pub const OK = 0x0000
pub const SCREEN_INVALID_MODE = 0x0001
pub const SCREEN_INVALID_WIDTH = 0x0003
pub const SCREEN_FB_TOO_SMALL = 0x0005
pub const SCREEN_OUTSIDE_FB = 0x0007
pub const MAGIC_BAD = 0x8001
; Extended error codes, these would require loading a 32 bit value.
pub const EXT_OK = 0x00000000
+30
View File
@@ -0,0 +1,30 @@
; Addresses of global variables
pub const MAGIC_ADDRESS_LONG = 0x0c ; U32 Location of the magic value
pub const MAGIC_VALUE_LONG = 0xb301534c ; U32 Full 32 bits of the magic value
pub const MAGIC_ADDRESS = 0x0e ; U16 Location of the low 16 bits of magic value
pub const MAGIC_VALUE = 0x534c ; U16 Low 16 bits of the magic value
; If not double buffering these point to the same buffer
; If double buffering they must the same size
pub const FB_DISPLAY_PTR = 0x10 ; U32 Currently displayed buffer
pub const FB_DISPLAY_STRIDE = 0x14 ; U16 Bytes in each row of the displayed buffer
pub const FB_DISPLAY_DEPTH = 0x16 ; U16 Bits per pixel of the display buffer
pub const FB_DRAW_PTR = 0x18 ; U32 Draw to this buffer
pub const FB_DRAW_STRIDE = 0x1c ; U16 Bytes in each row of the draw buffer == FB_DISPLAY_STRIDE
pub const FB_DRAW_DEPTH = 0x1e ; U16 Bits per pixel of the draw buffer == FB_DISPLAY_DEPTH
pub const FB_SIZE_BYTE = 0x20 ; U32 In bytes
pub const FB_WIDTH_PX = 0x24 ; U16 Width of screen in pixels
pub const FB_HEIGHT_PX = 0x26 ; U16 Height of screen in pixels
; Log2 of width in pixels, e.g.
; * 10 => 1024 * 768
; * 8 => 256 * 192
pub const FB_LOG_WIDTH = 0x28 ; U8
pub const FB_LOG_STRIDE = 0x29 ; U8 Log2 of FB_xxx_STRIDE in bytes
pub const FB_BYTES_PER_PIXEL = 0x2a ; U8 Specialisations should hardcode this
; Log2 of bytes per pixel
; * 0 => 8 bits per pixel
; * 2 => 32 bits per pixel
pub const FB_LOG_BPP = 0x2b ; U8 Specialisations should hardcode this
+43 -21
View File
@@ -4,29 +4,51 @@
; r2 - The second value
; Result:
; r1 - The lower 32 bits of the result
; Clobbers: r2, r3, r4, r5
; Clobbers: r2, r3, r4, r5, r6
pub mul_low:
add r3, r2, r2 ; r3 = r2 * 2
cmp r1, r2
jbe mul_low_noswap
xor r1, r2, r1
xor r2, r1, r2
xor r1, r2, r1
; Passthrough
; Multiplies r1 and r2, returning the lower part of the result
; This method assumes r1 is smaller than r2, which results in faster execution
; Arguments:
; r1 - The first value
; r2 - The second value
; Result:
; r1 - The lower 32 bits of the result
; Clobbers: r2, r3, r4, r5, r6
pub mul_low_noswap:
mov r4, 0 ; r4 has the result
mul_low_loop:
and r5, r1, 1 ; a0
neg r5, r5 ; mask
and r5, r2, r5 ; a0 ? r2 : 0
add r4, r4, r5
and r5, r1, 2 ; a1 is now 0 or 2
lsr r5, r5, 1 ; normalize to 0/1
neg r5, r5 ; mask
and r5, r3, r5 ; a1 ? r2 * 2 : 0
add r4, r4, r5
lsl r2, r2, 2
lsl r3, r3, 2
lsr r1, r1, 2
cmp r1, zr
jne mul_low_loop
mov r6, mul_loop_end
add r3, r2, r2
mul_loop:
and r5, r1, 14 ; Taking the first four bits, discarding the odd
lsl r5, r5, 1 ; 0000 - 0, 0001 - 2, 0010 - 4, 0011 - 8, etc.
sub r5, r6, r5
jmp r5
add r4, r4, r3
add r4, r4, r3
add r4, r4, r3
add r4, r4, r3
add r4, r4, r3
add r4, r4, r3
add r4, r4, r3
mul_loop_end:
mov flags, r1
jne mul_skip_one
add r4, r4, r2
mul_skip_one:
lsl r2, r2, 4
lsl r3, r3, 4
lsr r1, r1, 4
cmp r1, zr
jne mul_loop
mov r1, r4
jmp r13
Executable
+19
View File
@@ -0,0 +1,19 @@
;@0 ; Reserve space for globals
; First initialise the stack pointer
nor sp, zr, 0xffff
; Jump over the globals to user code
jmp 0x100
U32 0 ; 4 bytes
; MAGIC_VALUE
;@0x0c
U32 0xb301534c
; Pad with zeroes since the @addr feature is currently broken.
; * https://discord.com/channels/828292123936948244/1545010596246847568
;
U1920 0 ; 240 bytes
;@0x100 ; start of user code
+1
View File
@@ -3,6 +3,7 @@ pub include imath
pub include array
pub include console
pub include mem
pub include string_to_int
; Needs to be last!
pub include LUTs
+188
View File
@@ -0,0 +1,188 @@
; Internal register assignments:
; r1 - Partially parsed output integer
; r2 - Parsing position
; r3 - Character being parsed
; r4 - Set to -1 if the input is negative
; Convert string to integer (akin to libc atoi(), strotoi())
; Arguments:
; r1 - Pointer to string
; Result:
; r1 - Parsed integer
; r2 - Pointer to first rejected input byte
; Clobbers:
; flags
; r3 - last character read
; r4 - Negative marker
; Note: Unless the input is "0", tail-calls into a base-specific specialization.
pub auto:
mov r2, r1
mov r1, 0
mov r4, 0
load_8 r3, [r2]
cmp r3, 0x2D ; '-'
jne auto_positive
sub r4, zr, 1 ; Set r4 to -1
add r2, r2, 1
auto_positive:
load_16 r3, [r2] ; 2-byte prefix "0b", "0o", "0x", etc.
or r3, r3, 0x20 ; 2nd char to lower case
add r2, r2, 2
cmp r3, 0x3062 ; "0b"
je bin_loop
cmp r3, 0x306F ; "0o"
je oct_loop
cmp r3, 0x3078 ; "0x"
je hex_loop
sub r2, r2, 2 ; no matching prefix, move pointer back
jmp dec_loop
; Epilogue
done:
add r1, r1, r4 ; If r4 is -1, negate r1. Else it's 0 and no effect.
xor r1, r1, r4
mov flags, 0 ; No error
jmp r13
; Convert decimal string to integer
; Arguments:
; r1 - Pointer to string
; Result:
; r1 - Parsed integer
; r2 - Pointer to first rejected input byte
; Clobbers:
; flags
; r3 - last character read
; r4 - Negative marker
pub dec:
mov r2, r1
mov r1, 0
mov r4, 0
load_8 r3, [r2]
cmp r3, 0x2D ; '-'
jne dec_positive
sub r4, zr, 1 ; Set r4 to -1
add r2, r2, 1
dec_loop:
load_8 r3, [r2]
dec_positive:
sub r3, r3, 0x30 ; '0'
cmp r3, 9
ja done
add r2, r2, 1
lsl flags, r1, 2 ; Use flags to help multiply by 10
add r1, r1, flags
lsl r1, r1, 1
add r1, r1, r3
jmp dec_loop
; Convert binary string to integer
; Arguments:
; r1 - Pointer to string
; Result:
; r1 - Parsed integer
; r2 - Pointer to first rejected input byte
; Clobbers:
; flags
; r3 - last character read
; r4 - Negative marker
pub bin:
mov r2, r1
mov r1, 0
mov r4, 0
load_8 r3, [r2]
cmp r3, 0x2D ; '-'
jne bin_positive
sub r4, zr, 1 ; Set r4 to -1
add r2, r2, 1
bin_positive:
load_16 r3, [r2] ; check for prefix
or r3, r3, 0x20 ; 2nd char to lower case
cmp r3, 0x3062 ; "0b"
jne bin_loop
add r2, r2, 2
bin_loop:
load_8 r3, [r2]
sub r3, r3, 0x30 ; '0'
cmp r3, 1
ja done
add r2, r2, 1
lsl r1, r1, 1
add r1, r1, r3
jmp bin_loop
; Convert octal string to integer
; Arguments:
; r1 - Pointer to string
; Result:
; r1 - Parsed integer
; r2 - Pointer to first rejected input byte
; Clobbers:
; flags
; r3 - last character read
; r4 - Negative marker
pub oct:
mov r2, r1
mov r1, 0
mov r4, 0
load_8 r3, [r2]
cmp r3, 0x2D ; '-'
jne oct_positive
sub r4, zr, 1 ; Set r4 to -1
add r2, r2, 1
oct_positive:
load_16 r3, [r2] ; check for prefix
or r3, r3, 0x20 ; 2nd char to lower case
cmp r3, 0x306F ; "0o"
jne oct_loop
add r2, r2, 2
oct_loop:
load_8 r3, [r2]
sub r3, r3, 0x30 ; '0'
cmp r3, 7
ja done
add r2, r2, 1
lsl r1, r1, 3
add r1, r1, r3
jmp oct_loop
; Convert hexadecimal string to integer
; Arguments:
; r1 - Pointer to string
; Result:
; r1 - Parsed integer
; r2 - Pointer to first rejected input byte
; Clobbers:
; flags
; r3 - last character read
; r4 - Negative marker
pub hex:
mov r2, r1
mov r1, 0
mov r4, 0
load_8 r3, [r2]
cmp r3, 0x2D ; '-'
jne hex_positive
sub r4, zr, 1 ; Set r4 to -1
add r2, r2, 1
hex_positive:
load_16 r3, [r2] ; check for prefix
or r3, r3, 0x20 ; 2nd char to lower case
cmp r3, 0x3078 ; "0x"
jne hex_loop
add r2, r2, 2
hex_loop:
load_8 r3, [r2]
sub r3, r3, 0x30 ; '0'
cmp r3, 10
jb hex_add
sub r3, r3, 0x11 ; 'A' - '0'
and r3, r3, 0xdf ; to lower case
cmp r3, 5 ; 0-5: 6 letters
ja done
add r3, r3, 10 ; Adjust for digits below
hex_add:
add r2, r2, 1
lsl r1, r1, 4
add r1, r1, r3
jmp hex_loop