From 6ca77970b808240f99b91f84e441d8997fa931d1 Mon Sep 17 00:00:00 2001 From: Michal Isalski Date: Mon, 31 Aug 2026 13:44:07 +0200 Subject: [PATCH 01/18] Added find_index array function --- array.asm | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ stdlib.asm | 3 ++- 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 array.asm diff --git a/array.asm b/array.asm new file mode 100644 index 0000000..798d8d8 --- /dev/null +++ b/array.asm @@ -0,0 +1,76 @@ +; Returns the index of the first element matching the provided predicate function (or -1 if not found) +; r1 - The array pointer +; r2 - The array length (number of items) +; r3 - The stride (size of one item) - either 1, 2 or 4 (bytes) +; r4 - The predicate +; r5 - Predicate context +; The predicate function should follow the stdlib calling convention +; and receive one argument and return either a zero when the value is not the one we search for +; , or any other result if it is the searched-for item. +pub find_index: + push r12 ; We will store the predicate pointer here + push r11 ; We will store the current pointer here + push r10 ; We will store the stride here + push r9 ; We will store the bytes left here + push r8 ; We will store the mask here + push r1 ; We need the array pointer to calculate the item index + + mov r12, r4 + mov r11, r1 + mov r10, r3 + mov r9, r2 + lsl r9, r9, r3 + + push r13 ; We save up the return address because we will provide our own to the predicate + counter r13 + add r13, r13, 40 ; Point to just after the predicate call - we can set this up now so we don't waste loop cycles + + mov r8, 0 + not r8, r8 ; We create a mask of 0xFFFFFFFF + mov r6, 4 + sub r6, r6, r3 ; We create a "negative stride", e.g. 4 -> 0, 2 -> 2, 1 -> 3 + lsl r6, r6, 3 + lsr r8, r8, r6 ; We shift the mask by the negative stride to obtain the proper mask for a value + ; e.g. stride 4 -> mask is 0xFFFFFFFF + ; stride 2 -> mask is 0x0000FFFF + ; stride 1 -> mask is 0x000000FF + + push r5 ; We save the predicate context on the stack + find_index_loop: + load_32 r1, [r11] ; We load the element + and r1, r1, r8 ; We mask it to handle stride 2 and 1 cases + load_32 r2, [sp] ; We load the predicate context into r2 + jmp r12 ; We call the predicate + cmp r1, zr + jneq find_index_found_item ; If we found the item, we jump out + ; If we didn't, move to next item + add r11, r11, r10 ; We add the stride to the pointer + sub r9, r9, r10 ; We decrease bytes left + cmp r9, zr + jeq find_index_not_found ; If we reached the end we're done + jmp find_index_loop + + find_index_not_found: + add sp, sp, 4 ; The predicate context is not useful + pop r13 ; We get our return address + mov r1, 0 + not r1, r1 ; We put -1 in r1 + add sp, sp, 4 ; The old array pointer are not useful + jmp find_index_postamble + + find_index_found_item: + add sp, sp, 4 ; The predicate context is not useful + pop r13 ; We get our return address + pop r1 ; We get the array pointer + sub r1, r11, r1 ; We calculate the bytes from the start + lsr r10, r10, 1 ; We shift the stride to get the amount to shift the bytes for + lsr r1, r1, r10 ; We shift to get the index of the item + + find_index_postamble: + pop r8 + pop r9 + pop r10 + pop r11 + pop r12 + jmp r13 ; Return + diff --git a/stdlib.asm b/stdlib.asm index 5852f04..5b29575 100644 --- a/stdlib.asm +++ b/stdlib.asm @@ -22,4 +22,5 @@ ; ===== TYPES ===== pub include bit -pub include imath \ No newline at end of file +pub include imath +pub include array \ No newline at end of file From 837e8ba0a6757cd089e282d3350dc151cc1d241d Mon Sep 17 00:00:00 2001 From: Michal Isalski Date: Mon, 31 Aug 2026 13:52:27 +0200 Subject: [PATCH 02/18] Fixed the predicate return address --- array.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/array.asm b/array.asm index 798d8d8..bfcb3ed 100644 --- a/array.asm +++ b/array.asm @@ -23,7 +23,7 @@ pub find_index: push r13 ; We save up the return address because we will provide our own to the predicate counter r13 - add r13, r13, 40 ; Point to just after the predicate call - we can set this up now so we don't waste loop cycles + add r13, r13, 52 ; Point to just after the predicate call - we can set this up now so we don't waste loop cycles mov r8, 0 not r8, r8 ; We create a mask of 0xFFFFFFFF From 29103d43354db2b254fe93834a67a88936684c87 Mon Sep 17 00:00:00 2001 From: Michal Isalski Date: Mon, 31 Aug 2026 15:30:11 +0200 Subject: [PATCH 03/18] Reduced operations to get -1 in register --- array.asm | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/array.asm b/array.asm index bfcb3ed..3d06c91 100644 --- a/array.asm +++ b/array.asm @@ -11,7 +11,7 @@ pub find_index: push r12 ; We will store the predicate pointer here push r11 ; We will store the current pointer here push r10 ; We will store the stride here - push r9 ; We will store the bytes left here + push r9 ; We will store the final address here push r8 ; We will store the mask here push r1 ; We need the array pointer to calculate the item index @@ -19,14 +19,14 @@ pub find_index: mov r11, r1 mov r10, r3 mov r9, r2 - lsl r9, r9, r3 + lsl r9, r9, r3 ; We calculate bytes left + add r9, r9, r1 ; We add the start address to get the final address push r13 ; We save up the return address because we will provide our own to the predicate counter r13 add r13, r13, 52 ; Point to just after the predicate call - we can set this up now so we don't waste loop cycles - mov r8, 0 - not r8, r8 ; We create a mask of 0xFFFFFFFF + nand r8, zr, zr ; We create a mask of 0xFFFFFFFF mov r6, 4 sub r6, r6, r3 ; We create a "negative stride", e.g. 4 -> 0, 2 -> 2, 1 -> 3 lsl r6, r6, 3 @@ -45,16 +45,14 @@ pub find_index: jneq find_index_found_item ; If we found the item, we jump out ; If we didn't, move to next item add r11, r11, r10 ; We add the stride to the pointer - sub r9, r9, r10 ; We decrease bytes left - cmp r9, zr + cmp r11, r9 ; We compare with the final address jeq find_index_not_found ; If we reached the end we're done jmp find_index_loop find_index_not_found: add sp, sp, 4 ; The predicate context is not useful pop r13 ; We get our return address - mov r1, 0 - not r1, r1 ; We put -1 in r1 + nand r1, zr, zr ; We put -1 in r1 add sp, sp, 4 ; The old array pointer are not useful jmp find_index_postamble From bddb153d9be9712247b586f3b42b4718aa8ea05d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Isalski?= Date: Mon, 31 Aug 2026 23:03:23 +0200 Subject: [PATCH 04/18] Tested and fixed stride->shift conversion missing --- array.asm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/array.asm b/array.asm index 3d06c91..c6e34d5 100644 --- a/array.asm +++ b/array.asm @@ -19,7 +19,8 @@ pub find_index: mov r11, r1 mov r10, r3 mov r9, r2 - lsl r9, r9, r3 ; We calculate bytes left + lsr r6, r3, 1 ; We turn the stride into a byte shift + lsl r9, r9, r6 ; We calculate bytes left add r9, r9, r1 ; We add the start address to get the final address push r13 ; We save up the return address because we will provide our own to the predicate @@ -42,11 +43,11 @@ pub find_index: load_32 r2, [sp] ; We load the predicate context into r2 jmp r12 ; We call the predicate cmp r1, zr - jneq find_index_found_item ; If we found the item, we jump out + jne find_index_found_item ; If we found the item, we jump out ; If we didn't, move to next item add r11, r11, r10 ; We add the stride to the pointer cmp r11, r9 ; We compare with the final address - jeq find_index_not_found ; If we reached the end we're done + je find_index_not_found ; If we reached the end we're done jmp find_index_loop find_index_not_found: @@ -71,4 +72,3 @@ pub find_index: pop r11 pop r12 jmp r13 ; Return - From b476b8aaa3b7640a956e4472340a87d90219645b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Isalski?= Date: Mon, 31 Aug 2026 23:06:40 +0200 Subject: [PATCH 05/18] Added comment about predicate context --- array.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/array.asm b/array.asm index c6e34d5..13dfc4b 100644 --- a/array.asm +++ b/array.asm @@ -5,7 +5,7 @@ ; r4 - The predicate ; r5 - Predicate context ; The predicate function should follow the stdlib calling convention -; and receive one argument and return either a zero when the value is not the one we search for +; The predicate receives two arguments (the value and the predicate context) and should return either a zero when the value is not the one we search for ; , or any other result if it is the searched-for item. pub find_index: push r12 ; We will store the predicate pointer here From 7abfcabd73246a6eea6a5c92b81690f256ebbfe1 Mon Sep 17 00:00:00 2001 From: Michal Isalski Date: Mon, 31 Aug 2026 13:44:07 +0200 Subject: [PATCH 06/18] Added find_index array function --- array.asm | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ stdlib.asm | 3 ++- 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 array.asm diff --git a/array.asm b/array.asm new file mode 100644 index 0000000..798d8d8 --- /dev/null +++ b/array.asm @@ -0,0 +1,76 @@ +; Returns the index of the first element matching the provided predicate function (or -1 if not found) +; r1 - The array pointer +; r2 - The array length (number of items) +; r3 - The stride (size of one item) - either 1, 2 or 4 (bytes) +; r4 - The predicate +; r5 - Predicate context +; The predicate function should follow the stdlib calling convention +; and receive one argument and return either a zero when the value is not the one we search for +; , or any other result if it is the searched-for item. +pub find_index: + push r12 ; We will store the predicate pointer here + push r11 ; We will store the current pointer here + push r10 ; We will store the stride here + push r9 ; We will store the bytes left here + push r8 ; We will store the mask here + push r1 ; We need the array pointer to calculate the item index + + mov r12, r4 + mov r11, r1 + mov r10, r3 + mov r9, r2 + lsl r9, r9, r3 + + push r13 ; We save up the return address because we will provide our own to the predicate + counter r13 + add r13, r13, 40 ; Point to just after the predicate call - we can set this up now so we don't waste loop cycles + + mov r8, 0 + not r8, r8 ; We create a mask of 0xFFFFFFFF + mov r6, 4 + sub r6, r6, r3 ; We create a "negative stride", e.g. 4 -> 0, 2 -> 2, 1 -> 3 + lsl r6, r6, 3 + lsr r8, r8, r6 ; We shift the mask by the negative stride to obtain the proper mask for a value + ; e.g. stride 4 -> mask is 0xFFFFFFFF + ; stride 2 -> mask is 0x0000FFFF + ; stride 1 -> mask is 0x000000FF + + push r5 ; We save the predicate context on the stack + find_index_loop: + load_32 r1, [r11] ; We load the element + and r1, r1, r8 ; We mask it to handle stride 2 and 1 cases + load_32 r2, [sp] ; We load the predicate context into r2 + jmp r12 ; We call the predicate + cmp r1, zr + jneq find_index_found_item ; If we found the item, we jump out + ; If we didn't, move to next item + add r11, r11, r10 ; We add the stride to the pointer + sub r9, r9, r10 ; We decrease bytes left + cmp r9, zr + jeq find_index_not_found ; If we reached the end we're done + jmp find_index_loop + + find_index_not_found: + add sp, sp, 4 ; The predicate context is not useful + pop r13 ; We get our return address + mov r1, 0 + not r1, r1 ; We put -1 in r1 + add sp, sp, 4 ; The old array pointer are not useful + jmp find_index_postamble + + find_index_found_item: + add sp, sp, 4 ; The predicate context is not useful + pop r13 ; We get our return address + pop r1 ; We get the array pointer + sub r1, r11, r1 ; We calculate the bytes from the start + lsr r10, r10, 1 ; We shift the stride to get the amount to shift the bytes for + lsr r1, r1, r10 ; We shift to get the index of the item + + find_index_postamble: + pop r8 + pop r9 + pop r10 + pop r11 + pop r12 + jmp r13 ; Return + diff --git a/stdlib.asm b/stdlib.asm index 5852f04..5b29575 100644 --- a/stdlib.asm +++ b/stdlib.asm @@ -22,4 +22,5 @@ ; ===== TYPES ===== pub include bit -pub include imath \ No newline at end of file +pub include imath +pub include array \ No newline at end of file From a02f0646b49be3323c6393e82fb09b6cbea35801 Mon Sep 17 00:00:00 2001 From: Michal Isalski Date: Mon, 31 Aug 2026 13:52:27 +0200 Subject: [PATCH 07/18] Fixed the predicate return address --- array.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/array.asm b/array.asm index 798d8d8..bfcb3ed 100644 --- a/array.asm +++ b/array.asm @@ -23,7 +23,7 @@ pub find_index: push r13 ; We save up the return address because we will provide our own to the predicate counter r13 - add r13, r13, 40 ; Point to just after the predicate call - we can set this up now so we don't waste loop cycles + add r13, r13, 52 ; Point to just after the predicate call - we can set this up now so we don't waste loop cycles mov r8, 0 not r8, r8 ; We create a mask of 0xFFFFFFFF From 88c91a8eecfc118f57f1946d364e44b3d903e596 Mon Sep 17 00:00:00 2001 From: Michal Isalski Date: Mon, 31 Aug 2026 15:30:11 +0200 Subject: [PATCH 08/18] Reduced operations to get -1 in register --- array.asm | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/array.asm b/array.asm index bfcb3ed..3d06c91 100644 --- a/array.asm +++ b/array.asm @@ -11,7 +11,7 @@ pub find_index: push r12 ; We will store the predicate pointer here push r11 ; We will store the current pointer here push r10 ; We will store the stride here - push r9 ; We will store the bytes left here + push r9 ; We will store the final address here push r8 ; We will store the mask here push r1 ; We need the array pointer to calculate the item index @@ -19,14 +19,14 @@ pub find_index: mov r11, r1 mov r10, r3 mov r9, r2 - lsl r9, r9, r3 + lsl r9, r9, r3 ; We calculate bytes left + add r9, r9, r1 ; We add the start address to get the final address push r13 ; We save up the return address because we will provide our own to the predicate counter r13 add r13, r13, 52 ; Point to just after the predicate call - we can set this up now so we don't waste loop cycles - mov r8, 0 - not r8, r8 ; We create a mask of 0xFFFFFFFF + nand r8, zr, zr ; We create a mask of 0xFFFFFFFF mov r6, 4 sub r6, r6, r3 ; We create a "negative stride", e.g. 4 -> 0, 2 -> 2, 1 -> 3 lsl r6, r6, 3 @@ -45,16 +45,14 @@ pub find_index: jneq find_index_found_item ; If we found the item, we jump out ; If we didn't, move to next item add r11, r11, r10 ; We add the stride to the pointer - sub r9, r9, r10 ; We decrease bytes left - cmp r9, zr + cmp r11, r9 ; We compare with the final address jeq find_index_not_found ; If we reached the end we're done jmp find_index_loop find_index_not_found: add sp, sp, 4 ; The predicate context is not useful pop r13 ; We get our return address - mov r1, 0 - not r1, r1 ; We put -1 in r1 + nand r1, zr, zr ; We put -1 in r1 add sp, sp, 4 ; The old array pointer are not useful jmp find_index_postamble From 6981ff027df7dc2a6631bca2acd415332ab471ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Isalski?= Date: Mon, 31 Aug 2026 23:03:23 +0200 Subject: [PATCH 09/18] Tested and fixed stride->shift conversion missing --- array.asm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/array.asm b/array.asm index 3d06c91..c6e34d5 100644 --- a/array.asm +++ b/array.asm @@ -19,7 +19,8 @@ pub find_index: mov r11, r1 mov r10, r3 mov r9, r2 - lsl r9, r9, r3 ; We calculate bytes left + lsr r6, r3, 1 ; We turn the stride into a byte shift + lsl r9, r9, r6 ; We calculate bytes left add r9, r9, r1 ; We add the start address to get the final address push r13 ; We save up the return address because we will provide our own to the predicate @@ -42,11 +43,11 @@ pub find_index: load_32 r2, [sp] ; We load the predicate context into r2 jmp r12 ; We call the predicate cmp r1, zr - jneq find_index_found_item ; If we found the item, we jump out + jne find_index_found_item ; If we found the item, we jump out ; If we didn't, move to next item add r11, r11, r10 ; We add the stride to the pointer cmp r11, r9 ; We compare with the final address - jeq find_index_not_found ; If we reached the end we're done + je find_index_not_found ; If we reached the end we're done jmp find_index_loop find_index_not_found: @@ -71,4 +72,3 @@ pub find_index: pop r11 pop r12 jmp r13 ; Return - From 63b37ab0947dba2931c02ca868ce93f96e83c3a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Isalski?= Date: Mon, 31 Aug 2026 23:06:40 +0200 Subject: [PATCH 10/18] Added comment about predicate context --- array.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/array.asm b/array.asm index c6e34d5..13dfc4b 100644 --- a/array.asm +++ b/array.asm @@ -5,7 +5,7 @@ ; r4 - The predicate ; r5 - Predicate context ; The predicate function should follow the stdlib calling convention -; and receive one argument and return either a zero when the value is not the one we search for +; The predicate receives two arguments (the value and the predicate context) and should return either a zero when the value is not the one we search for ; , or any other result if it is the searched-for item. pub find_index: push r12 ; We will store the predicate pointer here From e6a0739e95df68f6d647fe0a749e98c68b07d914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Isalski?= Date: Mon, 31 Aug 2026 23:57:55 +0200 Subject: [PATCH 11/18] pleegwat's code review fixes --- array.asm | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/array.asm b/array.asm index 13dfc4b..0ba4e6b 100644 --- a/array.asm +++ b/array.asm @@ -13,7 +13,6 @@ pub find_index: push r10 ; We will store the stride here push r9 ; We will store the final address here push r8 ; We will store the mask here - push r1 ; We need the array pointer to calculate the item index mov r12, r4 mov r11, r1 @@ -24,6 +23,7 @@ pub find_index: add r9, r9, r1 ; We add the start address to get the final address push r13 ; We save up the return address because we will provide our own to the predicate + push r1 ; We need the array pointer to calculate the item index counter r13 add r13, r13, 52 ; Point to just after the predicate call - we can set this up now so we don't waste loop cycles @@ -47,14 +47,12 @@ pub find_index: ; If we didn't, move to next item add r11, r11, r10 ; We add the stride to the pointer cmp r11, r9 ; We compare with the final address - je find_index_not_found ; If we reached the end we're done - jmp find_index_loop + jne find_index_loop ; If we did not reach the end we jump back into the loop find_index_not_found: - add sp, sp, 4 ; The predicate context is not useful + add sp, sp, 8 ; The predicate context and old array pointer are not useful pop r13 ; We get our return address nand r1, zr, zr ; We put -1 in r1 - add sp, sp, 4 ; The old array pointer are not useful jmp find_index_postamble find_index_found_item: From 625f01166af76b8900fd4d692e075ba45cca6741 Mon Sep 17 00:00:00 2001 From: Michal Isalski Date: Tue, 1 Sep 2026 13:52:26 +0200 Subject: [PATCH 12/18] Made find_index conform to new doc guidelines --- array.asm | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/array.asm b/array.asm index 0ba4e6b..582ca7b 100644 --- a/array.asm +++ b/array.asm @@ -1,9 +1,14 @@ ; Returns the index of the first element matching the provided predicate function (or -1 if not found) +; Arguments: ; r1 - The array pointer ; r2 - The array length (number of items) ; r3 - The stride (size of one item) - either 1, 2 or 4 (bytes) ; r4 - The predicate ; r5 - Predicate context +; Result: +; r1 - The index of the first element matching the provided predicate function (or -1 if not found) +; Clobbers: r2, r3, r4, r5, r6, + what the predicate clobbers +; Info: ; The predicate function should follow the stdlib calling convention ; The predicate receives two arguments (the value and the predicate context) and should return either a zero when the value is not the one we search for ; , or any other result if it is the searched-for item. From 20e1f171810bb5efedf4bb330b8f9db769478aef Mon Sep 17 00:00:00 2001 From: Michal Isalski Date: Tue, 1 Sep 2026 13:52:45 +0200 Subject: [PATCH 13/18] Fixed swapped pop instructions --- array.asm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/array.asm b/array.asm index 582ca7b..c90ba38 100644 --- a/array.asm +++ b/array.asm @@ -62,8 +62,8 @@ pub find_index: find_index_found_item: add sp, sp, 4 ; The predicate context is not useful - pop r13 ; We get our return address pop r1 ; We get the array pointer + pop r13 ; We get our return address sub r1, r11, r1 ; We calculate the bytes from the start lsr r10, r10, 1 ; We shift the stride to get the amount to shift the bytes for lsr r1, r1, r10 ; We shift to get the index of the item From 7c49c5212e11552a8a1973d9bbc5047aecc0baf7 Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Thu, 3 Sep 2026 20:32:40 +0200 Subject: [PATCH 14/18] move assembly files into src directory --- LUTs.asm => src/LUTs.asm | 0 array.asm => src/array.asm | 0 bit.asm => src/bit.asm | 0 console.asm => src/console.asm | 0 imath.asm => src/imath.asm | 0 stdlib.asm => src/stdlib.asm | 0 6 files changed, 0 insertions(+), 0 deletions(-) rename LUTs.asm => src/LUTs.asm (100%) rename array.asm => src/array.asm (100%) rename bit.asm => src/bit.asm (100%) rename console.asm => src/console.asm (100%) rename imath.asm => src/imath.asm (100%) rename stdlib.asm => src/stdlib.asm (100%) diff --git a/LUTs.asm b/src/LUTs.asm similarity index 100% rename from LUTs.asm rename to src/LUTs.asm diff --git a/array.asm b/src/array.asm similarity index 100% rename from array.asm rename to src/array.asm diff --git a/bit.asm b/src/bit.asm similarity index 100% rename from bit.asm rename to src/bit.asm diff --git a/console.asm b/src/console.asm similarity index 100% rename from console.asm rename to src/console.asm diff --git a/imath.asm b/src/imath.asm similarity index 100% rename from imath.asm rename to src/imath.asm diff --git a/stdlib.asm b/src/stdlib.asm similarity index 100% rename from stdlib.asm rename to src/stdlib.asm From 697445feec8ef3d38a29cb99ca1de7be85bf3ca6 Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Thu, 3 Sep 2026 20:34:16 +0200 Subject: [PATCH 15/18] add tests folder --- tests/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/README.md diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..5a89224 --- /dev/null +++ b/tests/README.md @@ -0,0 +1,3 @@ +# Tests + +Tests for the standard library go here, tests are allowed to depend on the recommended spec.isa changes. From 6bf0c0a4fc91dc52a7666ff79e0c9b99b9f0a863 Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Thu, 3 Sep 2026 20:34:56 +0200 Subject: [PATCH 16/18] add examples directory --- examples/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 examples/README.md diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..7607445 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,3 @@ +# Examples + +Examples of how to use the standard library to accomplish a task. From c83269fcf77b0694cb8e32ba047e4dab2c0d9560 Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Thu, 3 Sep 2026 20:35:41 +0200 Subject: [PATCH 17/18] fix path to stdlib.asm --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1a3d693..b973fa2 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This is a standard library for symphony. It is both intended as a practical toolkit to develop more complex software as well as a teaching resource. -If you just want to use the standard library [[stdlib.asm]] is your main header, include it after your code. +If you just want to use the standard library [[src/stdlib.asm]] is your main header, include it after your code. If you are using it as a learning resource have a look at the [teaching folder](teaching). From 257735d77628562f411511998e3a6cb2d6476d88 Mon Sep 17 00:00:00 2001 From: MutexRaceCondition Date: Thu, 3 Sep 2026 21:01:07 +0200 Subject: [PATCH 18/18] Remove leftover files --- mem.asm | 174 ----------------------------------------------------- unsafe.asm | 75 ----------------------- 2 files changed, 249 deletions(-) delete mode 100644 mem.asm delete mode 100644 unsafe.asm diff --git a/mem.asm b/mem.asm deleted file mode 100644 index bf82a2e..0000000 --- a/mem.asm +++ /dev/null @@ -1,174 +0,0 @@ -; int compare(uint8_t* a, uint8_t* b, size_t count); -; Compares two memory segment of equal length lexicographically. -; -; Arguments: -; - `r1`: A pointer to the first memory segment. -; - `r2`: A pointer to the second memory segment. -; - `r3`: The size of both memory segments. -; Results: -; - `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. -; -pub compare: - ; Exclusive end point of the first segment. - add r3, r3, r1 - sub r3, r3, 4 -_compare__loop: - load_32 r4, [r1] - add r1, r1, 4 - load_32 r5, [r2] - add r2, r2, 4 - ; Comparing two sequences of 4 bytes lexicographically is equivalent to - ; comparing the corresponding big endian 32 bit words. - cmp r4, r5 - jne _compare__break - ; Check if there are enough bytes left to continue with the vectorized loop. - cmp r1, r3 - jbe _compare__loop - ; `r3 + 4 - r1 = = r3 - r1 mod 4` - sub flags, r3, r1 - ; Check if one of the lowest 2 bits is non-zero - jbe _compare__rem - ; If not, we are done. Both segments are equal. - mov r1, 0 - jmp r13 -_compare__break: - ; `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 -_compare__rem: - ; Compute `S = 8*(4 - )` and - ; [r1] >> S, [r2] >> S - mov r3, 8 - load_32 r4, [r1] - sub r3, r3, flags - load_32 r5, [r2] - lsl r3, r3, 3 - lsr r4, r4, r3 - lsr r5, r5, r3 - ; Compare both values, now with garbage bytes removed. - cmp r4, r5 - jmp _compare__break - - -; void copy(void* src, void* dest, size_t count); -; Copies `count` bytes from `src` to `dest`. The two memory segments must not overlap. -; -; Arguments: -; - `r1`: Pointer to the memory segment to be copied. -; - `r2`: Pointer to the memory segment to be copied into. -; - `r3`: Byte size of both the `src` and `dest` segments. -; -pub copy: - ; Exclusive end point of the source segment. - add r3, r1, r3 - ; Last index from where we can safely copy 8 bytes per loop iteration. - sub r3, r3, 8 - jmp _copy__loop_entry -_copy__loop: - ; Copy 8 bytes from `src` to `dest`. - load_32 flags, [r1] - add r1, r1, 4 - store_32 [r2], flags - add r2, r2, 4 - load_32 flags, [r1] - add r1, r1, 4 - store_32 [r2], flags - add r2, r2, 4 -_copy__loop_entry: - ; Check if we can process more data in the vectorized loop. - cmp r1, r3 - jbe _copy__loop - ; The remaining amount of bytes `R` is `R = r3 + 8 - r1 = r3 - r1 mod 8`. - sub flags, r3, r1 - ; Test if `R` is not a multiple of `4`, i.e. the lowest 2 bits are non-zero. - jbe _copy__rem - ; `R` is a multiple of `4`. Special case this. - ; Check if `R` is `0`, i.e. the third bit is also 0. In that case, we are already done. - ; There are no conditional indirect jumps, so we can't return immediately. - jge _copy__ret - ; `R = 4`. No need to update `r1` or `r2`, we don't need them anymore. - load_32 flags, [r1] - store_32 [r2], flags -_copy__ret: - ; Return - jmp r13 -_copy__rem: - ; Optimize the remaining cases for code size. - ; End point of the source segment. - add r3, r3, 8 - ; We already handled the case `R = 0` earlier, - ; so no bounds check needed for the first iteration. -_copy__rem_loop: - ; Copy 1 byte. - load_8 flags, [r1] - add r1, r1, 1 - store_8 [r2], flags - add r2, r2, 1 - ; Check if we are still within the bounds. - cmp r1, r3 - jb _copy__rem_loop - jmp r13 - -; void fill32(uint8_t* dest, size_t count, uint32_t value); -; Fills `count` bytes in `dest` with `value`. If `count` is not a multiple of 4, -; the least significant bytes of `value` are cut off for the last entry. -; -; Arguments: -; - `r1`: A pointer to the destination segment. -; - `r2`: The size of the destination segment. -; - `r3`: The 32 bit value that the segment is filled with. -; -pub fill32: - ; Exclusive end point of the destination segment. - add r2, r1, r2 - ; Last index from where we can safely write 8 bytes per loop iteration. - sub r2, r2, 8 - jmp _fill32__entry -_fill32__loop: - ; Set 8 bytes per loop iteraion. - store_32 [r1], r3 - add r1, r1, 4 - store_32 [r1], r3 - add r1, r1, 4 -_fill32__entry: - ; Check if we can process more data in the vectorized loop. - cmp r1, r2 - jbe _fill32__loop - ; The remaining amount of bytes `R` is `R = r2 + 8 - r1 = r2 - r1 mod 8`. - sub flags, r2, r1 - ; Check if the third bit of the remainder is cleared. - jge _fill32__r4 - ; Otherwise set 4 bytes. - store_32 [r1], r3 - add r1, r1, 4 -_fill32__r4: - ; Check if the two least significant bits of the remainder are zero. - ja _fill32__ret - ; Handle the remaining bytes `R` individually, in reverse order. - add r2, r2, 4 - ; `r1 + 4 - r2 = 4 - R`. - sub flags, r1, r2 - ; Exclusive end point of the destination segment. - add r2, r2, 4 - ; Shift out the least significant `8*(4 - R)` bits of the value. - lsl flags, flags, 3 - lsr r3, r3, flags - jmp _fill32__loop2_entry -_fill32__loop2: - sub r2, r2, 1 - ; Write the least significant byte of the value... - store_8 [r2], r3 - ; and then shift it out. - lsr r3, r3, 8 -_fill32__loop2_entry: - cmp r1, r2 - jb _fill32__loop2 -_fill32__ret: - jmp r13 diff --git a/unsafe.asm b/unsafe.asm deleted file mode 100644 index e2ce635..0000000 --- a/unsafe.asm +++ /dev/null @@ -1,75 +0,0 @@ -; int memcmp(uint8_t* a, uint8_t* b, size_t count); -; Compares two memory segment of equal length lexicographically. -; Temporarily modifies the byte at address `a + count`. -; -; Arguments: -; - `r1`: A pointer to the first memory segment. -; - `r2`: A pointer to the second memory segment. -; - `r3`: The size of both memory segments. -; Results: -; - `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. -pub fn_memcmp: - ; Exclusive end point of the second segment. - add r4, r3, r2 - ; Exclusive end point of the first segment. - add r3, r3, r1 - load_8 r6, [r3] - load_8 flags, [r4] - ; Check if the first bytes behind the sequences are equal. - cmp flags, r6 - jne _memcmp__loop - ; Change the byte directly behind the first segment. - xor r4, r6, 1 - ; This would be problematic if someone calls memcmp with a first segment - ; whose end point overlaps the program memory of this function. - store_8 [r3], r4 -_memcmp__loop: - load_32 r4, [r1] - add r1, r1, 4 - load_32 r5, [r2] - add r2, r2, 4 - ; Comparing two sequences of 4 bytes lexicographically is equivalent to - ; comparing the corresponding big endian 32 bit words. - cmp r4, r5 - je _memcmp__loop - ; We overshot in the loop; decrement r1 again. (Only by 2, we backtrack the rest if necessary later) - sub r1, r1, 2 - ; Restore the byte we changed. - store_8 [r3], r6 - ; We encountered two different words. Figure out what byte they differ on. - xor r4, r4, r5 - ; Store the flags for later, to figure out the return value. - mov r5, flags - ; Check if at least one of the two most significant bytes is not 0. - cmp r4, 0xffff - jbe _memcmp__low2 - ; If it is, backtrack the remaining 2 indices. - ; Shift the most significant bytes to the least significant ones. - sub r1, r1, 2 - lsr r4, r4, 16 -_memcmp__low2: - ; r1 now points to a non-zero 16 bit value. - ; If the 16 bit value at r1-2 is in-bounds, then it is 0. - ; Check if the most significant byte of the 16 bit value is 0. - cmp r4, 0xff - ja _memcmp__low1 - ; If it is, our target is the least significant byte. - add r1, r1, 1 -_memcmp__low1: - ; Otherwise, the target is that non-zero byte. - ; Check if the target is out of bounds, i.e. the loop terminated through the "bounds check". - cmp r1, r3 - jae _memcmp__oob - ; r5 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, r5, 1 - lsl r1, r1, 30 - jmp r13 -_memcmp__oob: - mov r1, 0 - jmp r13