From 8e0fdf0d28df347c18500aca9302a718de928900 Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Mon, 31 Aug 2026 10:08:44 +0200 Subject: [PATCH 01/40] start readme --- README.md | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 44ed975..f492266 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,36 @@ -# symphony_stdlib +# Symphony Stdlib + +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. +You'll also need to include globals.asm in the first line of your main assembly file. + +If you are using it as a learning resource have a look at the [teaching folder](teaching). + +If you are intersted in contributing have a look at [CONTRIBUTING.md] + +--- + +## ABI + +### Calling Convention +n.a. zr +preserved: sp, r8 - r12 +scratch: flags, r1 - r7 +arguments: r1 - r7 (r1 = 1st argument, r6 = 6th arg/stack args, r7 = 7th arg/stack res) +result: r1, r2 (r1 = low word, r2 = high word) +return address: r13 + +### Stack +grows downwards from top of memory +arguments are passed in reverse order with the stack so: +lowest address = 1st stack arg +highest address = last stack arg + +### Types + +#### String +Strings are stored in memory as null terminated sequences of bytes encoding ascii characters. +They should be passed by reference. -standard library for symphony \ No newline at end of file From af5a750031401d07623eabaf2205753c3f8233d7 Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Mon, 31 Aug 2026 10:10:10 +0200 Subject: [PATCH 02/40] link test --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f492266..63cdb77 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ You'll also need to include globals.asm in the first line of your main assembly If you are using it as a learning resource have a look at the [teaching folder](teaching). -If you are intersted in contributing have a look at [CONTRIBUTING.md] +If you are intersted in contributing have a look at [[CONTRIBUTING.md]] --- From 4bce47209a75a6d59c3fc2191485822eb0c5fd49 Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Mon, 31 Aug 2026 10:12:57 +0200 Subject: [PATCH 03/40] fix remaining links --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 63cdb77..1222934 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 [[stdlib.asm]] is your main header, include it after your code. You'll also need to include globals.asm in the first line of your main assembly file. If you are using it as a learning resource have a look at the [teaching folder](teaching). From daf4168129855f697199514299a27555489b018a Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Mon, 31 Aug 2026 10:17:25 +0200 Subject: [PATCH 04/40] format calling convention --- README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1222934..0a39d03 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,14 @@ If you are intersted in contributing have a look at [[CONTRIBUTING.md]] ## ABI ### Calling Convention -n.a. zr -preserved: sp, r8 - r12 -scratch: flags, r1 - r7 -arguments: r1 - r7 (r1 = 1st argument, r6 = 6th arg/stack args, r7 = 7th arg/stack res) -result: r1, r2 (r1 = low word, r2 = high word) -return address: r13 +| class | registers | +| ----- | --------- | +| n.a. | zr | +| preserved | sp, r8 - r12 | +| scratch | flags, r1 - r7 | +| arguments | r1 - r5, r6 = stack args, r7 = stack res | +| result | r1 = low word, r2 = high word | +| return address | r13 | ### Stack grows downwards from top of memory From 6ca77970b808240f99b91f84e441d8997fa931d1 Mon Sep 17 00:00:00 2001 From: Michal Isalski Date: Mon, 31 Aug 2026 13:44:07 +0200 Subject: [PATCH 05/40] 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 06/40] 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 07/40] 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 08/40] 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 09/40] 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 10/40] 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 11/40] 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 12/40] 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 13/40] 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 14/40] 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 15/40] 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 4b962a1f8766a2a906a18db4c94342bbac044bf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Isalski?= Date: Tue, 1 Sep 2026 00:38:37 +0200 Subject: [PATCH 16/40] Added read_line function --- console.asm | 32 ++++++++++++++++++++++++++++++++ stdlib.asm | 3 ++- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 console.asm diff --git a/console.asm b/console.asm new file mode 100644 index 0000000..a79c39e --- /dev/null +++ b/console.asm @@ -0,0 +1,32 @@ +; Reads a line from the keyboard and fills the specified buffer with it +; Does not support Shift or any other special keys +; Argument: r1 - pointer to the buffer +; Returns the pointer to the same buffer +; Clobbers r2, r3 and r4 +pub read_line: + + mov r4, 0 ; Storing the last key here, so we don't repeat the same key + mov r2, r1 ; Saving the buffer pointer for return + mov r3, r1 ; The pointer to after the last character + + read_line_keyloop: + keyboard r1 + + cmp r1, r4 + je read_line_keyloop ; If the current key is same as previous, we loop + mov r4, r1 ; Storing current key as previous + + cmp r1, 0x100 + jbe read_line_keyloop ; If the key was up, we loop + xor r1, r1, 0x100 ; We remove the "down" bit + + cmp r1, 10 ; Was the key Enter? + je read_line_finished ; If so, we're finished + + store_8 [r3], r1 ; Else, we store the key in the buffer + add r3, r3, 1 ; We advance forward + jmp read_line_keyloop + read_line_finished: + store_8 [r3], zr ; We store null at the end so the string is finished + mov r1, r2 ; Recovering the buffer pointer + jmp r13 diff --git a/stdlib.asm b/stdlib.asm index 5852f04..9742b85 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 console \ No newline at end of file From 9dfb8248a6f3fb3f86f6eb8faa111551deaf5b9b Mon Sep 17 00:00:00 2001 From: Michal Isalski Date: Tue, 1 Sep 2026 10:51:31 +0200 Subject: [PATCH 17/40] Added handling for skipping non-renderable characters Added handling for backspace character --- console.asm | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/console.asm b/console.asm index a79c39e..49c54ec 100644 --- a/console.asm +++ b/console.asm @@ -16,16 +16,30 @@ pub read_line: je read_line_keyloop ; If the current key is same as previous, we loop mov r4, r1 ; Storing current key as previous - cmp r1, 0x100 + cmp r1, 0x100 ; Is the key down or up? jbe read_line_keyloop ; If the key was up, we loop xor r1, r1, 0x100 ; We remove the "down" bit cmp r1, 10 ; Was the key Enter? je read_line_finished ; If so, we're finished - - store_8 [r3], r1 ; Else, we store the key in the buffer - add r3, r3, 1 ; We advance forward - jmp read_line_keyloop + + cmp r1, 32 ; Was the key under Space? i.e. non-renderable + jb read_line_keyloop ; If so, we loop + + cmp r1, 127 ; Was the key Backspace? + je read_line_backspace ; If yes we need to move one character back + + read_line_store: + store_8 [r3], r1 ; Else, we store the key in the buffer + add r3, r3, 1 ; We advance forward + jmp read_line_keyloop + + read_line_backspace: + cmp r3, r2 + je read_line_keyloop ; If we are at the start, we loop + sub r3, r3, 1 ; We move back one character + jmp read_line_keyloop + read_line_finished: store_8 [r3], zr ; We store null at the end so the string is finished mov r1, r2 ; Recovering the buffer pointer From 1dca8143886cf65b48f5cb7abbc9658b15847dd3 Mon Sep 17 00:00:00 2001 From: Michal Isalski Date: Tue, 1 Sep 2026 10:54:29 +0200 Subject: [PATCH 18/40] One instruction less by using another register --- console.asm | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/console.asm b/console.asm index 49c54ec..9e8c6ac 100644 --- a/console.asm +++ b/console.asm @@ -6,41 +6,39 @@ pub read_line: mov r4, 0 ; Storing the last key here, so we don't repeat the same key - mov r2, r1 ; Saving the buffer pointer for return mov r3, r1 ; The pointer to after the last character read_line_keyloop: - keyboard r1 + keyboard r2 - cmp r1, r4 + cmp r2, r4 je read_line_keyloop ; If the current key is same as previous, we loop - mov r4, r1 ; Storing current key as previous + mov r4, r2 ; Storing current key as previous - cmp r1, 0x100 ; Is the key down or up? + cmp r2, 0x100 ; Is the key down or up? jbe read_line_keyloop ; If the key was up, we loop - xor r1, r1, 0x100 ; We remove the "down" bit + xor r2, r2, 0x100 ; We remove the "down" bit - cmp r1, 10 ; Was the key Enter? + cmp r2, 10 ; Was the key Enter? je read_line_finished ; If so, we're finished - cmp r1, 32 ; Was the key under Space? i.e. non-renderable + cmp r2, 32 ; Was the key under Space? i.e. non-renderable jb read_line_keyloop ; If so, we loop - cmp r1, 127 ; Was the key Backspace? + cmp r2, 127 ; Was the key Backspace? je read_line_backspace ; If yes we need to move one character back read_line_store: - store_8 [r3], r1 ; Else, we store the key in the buffer + store_8 [r3], r2 ; Else, we store the key in the buffer add r3, r3, 1 ; We advance forward jmp read_line_keyloop read_line_backspace: - cmp r3, r2 + cmp r3, r1 ; Compare the current pointer to start of buffer je read_line_keyloop ; If we are at the start, we loop sub r3, r3, 1 ; We move back one character jmp read_line_keyloop read_line_finished: store_8 [r3], zr ; We store null at the end so the string is finished - mov r1, r2 ; Recovering the buffer pointer jmp r13 From 33b7886e7004718c4601a0089a73976afbf8fe8b Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Tue, 1 Sep 2026 13:07:13 +0200 Subject: [PATCH 19/40] add arrays to readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 0a39d03..fe2ddb7 100644 --- a/README.md +++ b/README.md @@ -36,3 +36,6 @@ highest address = last stack arg Strings are stored in memory as null terminated sequences of bytes encoding ascii characters. They should be passed by reference. +#### Array +Arrays are stored in memory with a reference to them being the tuple (pointer, length) stored in a register pair. +Array elements may only have a size of 8/16/32 bits From 60e7b6209f5e30ea4c650cd81601106cef0e8a67 Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Tue, 1 Sep 2026 13:18:46 +0200 Subject: [PATCH 20/40] basic contribution guidelines --- CONTRIBUTING.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..610468a --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,25 @@ +# Contributing + +## Code of Conduct +Be nice, we are all just doing this to have fun + +## General rules +- All text (names, comments, etc.) has to be in English +- You are responsible for ensuring that you have the rights for us to use the code you contribute to the project +- follow the guidelines, for code, documentation, etc. +- all code has to work with the standard symphony ISA + +## Documenting Functions +All functions in the standard library should follow the following outline: +```asm +; +; Arguments: +; Result: +; Clobbers: +fn_label: <;SHOULD BE INLINED> + CODE + +``` + +Functions should be in the appropriate asm file, if you are unsure where functionality fits make a seperate file and ask in the pull request + From 65caf8aff9cba5843e691894cf374f6d3b25327e Mon Sep 17 00:00:00 2001 From: Michal Isalski Date: Tue, 1 Sep 2026 13:47:09 +0200 Subject: [PATCH 21/40] Made read_line compliant to new doc guidelines --- console.asm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/console.asm b/console.asm index 9e8c6ac..fc7bce1 100644 --- a/console.asm +++ b/console.asm @@ -1,14 +1,15 @@ ; Reads a line from the keyboard and fills the specified buffer with it ; Does not support Shift or any other special keys -; Argument: r1 - pointer to the buffer -; Returns the pointer to the same buffer -; Clobbers r2, r3 and r4 +; Arguments: +; r1 - pointer to the buffer +; Result: +; r1 - pointer to the same buffer +; Clobbers: r2, r3, r4 pub read_line: - mov r4, 0 ; Storing the last key here, so we don't repeat the same key mov r3, r1 ; The pointer to after the last character - read_line_keyloop: + read_line_keyloop: keyboard r2 cmp r2, r4 From f2e5c830b345173c577c6e4a983f2c4833dfe70e Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Tue, 1 Sep 2026 13:48:12 +0200 Subject: [PATCH 22/40] explain inline comment --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 610468a..82a0201 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,7 +11,7 @@ Be nice, we are all just doing this to have fun ## Documenting Functions All functions in the standard library should follow the following outline: -```asm +``` ; ; Arguments: ; Result: @@ -22,4 +22,4 @@ fn_label: <;SHOULD BE INLINED> ``` Functions should be in the appropriate asm file, if you are unsure where functionality fits make a seperate file and ask in the pull request - +Functions that are provided for convenience/reference but should be inlined in production code should be marked with `;SHOULD BE INLINED` after their label From 625f01166af76b8900fd4d692e075ba45cca6741 Mon Sep 17 00:00:00 2001 From: Michal Isalski Date: Tue, 1 Sep 2026 13:52:26 +0200 Subject: [PATCH 23/40] 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 24/40] 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 9816111f387014142dedc9ef71473f968f8ce2f3 Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Tue, 1 Sep 2026 14:08:20 +0200 Subject: [PATCH 25/40] clarify stack arguments --- README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fe2ddb7..d16f476 100644 --- a/README.md +++ b/README.md @@ -20,16 +20,22 @@ If you are intersted in contributing have a look at [[CONTRIBUTING.md]] | n.a. | zr | | preserved | sp, r8 - r12 | | scratch | flags, r1 - r7 | -| arguments | r1 - r5, r6 = stack args, r7 = stack res | -| result | r1 = low word, r2 = high word | +| arguments | r1 - r7 | +| result | r1-r7 | | return address | r13 | -### Stack -grows downwards from top of memory -arguments are passed in reverse order with the stack so: +Arguments not fitting into the 7 registers should be passed on the top of the stack, meaning they should be the last values pushed before the function call. +Arguments are passed in reverse order with the stack so: lowest address = 1st stack arg highest address = last stack arg +Should a function return more values than fit into the 7 registers, the caller has to allocate space on the stack for them, and pass the pointer to that space in r7. +This reduces the amount of argument registers to 6 and all arguments above that shall go on the stack, the pointer to the result stack shall **always** be passed in r7. +r7 points at the highest available address for results, with the 8th result being stored there, the 9th below it and so on. + +### Stack +Grows downwards from top of memory. + ### Types #### String From f9bb69f1f51e6eefd9276d512c1bdeb32bd18e18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Isalski?= Date: Wed, 2 Sep 2026 02:03:00 +0200 Subject: [PATCH 26/40] Added storing shift status --- console.asm | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/console.asm b/console.asm index fc7bce1..4b87f04 100644 --- a/console.asm +++ b/console.asm @@ -4,9 +4,10 @@ ; r1 - pointer to the buffer ; Result: ; r1 - pointer to the same buffer -; Clobbers: r2, r3, r4 +; Clobbers: r2, r3, r4, r5 pub read_line: mov r4, 0 ; Storing the last key here, so we don't repeat the same key + mov r5, 0 ; Storing the shift status mov r3, r1 ; The pointer to after the last character read_line_keyloop: @@ -16,23 +17,32 @@ pub read_line: je read_line_keyloop ; If the current key is same as previous, we loop mov r4, r2 ; Storing current key as previous - cmp r2, 0x100 ; Is the key down or up? - jbe read_line_keyloop ; If the key was up, we loop - xor r2, r2, 0x100 ; We remove the "down" bit - - cmp r2, 10 ; Was the key Enter? - je read_line_finished ; If so, we're finished + cmp r2, 0x120 ; Is the key renderable or special? + jb read_line_special ; If the key was special, we handle it separately - cmp r2, 32 ; Was the key under Space? i.e. non-renderable - jb read_line_keyloop ; If so, we loop + ; TODO: Converting based on shift value + store_8 [r3], r2 ; Else, we store the key in the buffer + add r3, r3, 1 ; We advance forward + jmp read_line_keyloop - cmp r2, 127 ; Was the key Backspace? - je read_line_backspace ; If yes we need to move one character back + read_line_special: + cmp r2, 13 ; Was the key Backspace? + je read_line_backspace ; If yes we need to move one character back - read_line_store: - store_8 [r3], r2 ; Else, we store the key in the buffer - add r3, r3, 1 ; We advance forward - jmp read_line_keyloop + cmp r2, 10 ; Was the key Enter? + je read_line_finished ; If so, we're finished + + and r2, r2, 0x1FB ; Mask out the left/right shift direction bit + cmp r2, 0x110 ; Was the key Shift Down? + and flags, flags, 0x1 ; We care only about equality bit + or r5, r5, flags ; If shift was down before, it still is. If it was pressed now, it is down now + + cmp r2, 0x010 ; Was the key Shift Up? + and flags, flags, 0x1 ; We care only about equality bit + xor flags, flags, 0x1 ; We invert it, i.e. "if it's not up" + and r5, r5, flags ; The shift can be kept down if it's not currently up + + jmp read_line_keyloop ; If no special handling, we loop back read_line_backspace: cmp r3, r1 ; Compare the current pointer to start of buffer From a3d6cb64b5b2ac8c81e58ce874ae64c13f3a73fe Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Wed, 2 Sep 2026 11:17:18 +0200 Subject: [PATCH 27/40] remove duplicate documentation from stdlib.asm --- stdlib.asm | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/stdlib.asm b/stdlib.asm index 5852f04..1b352f1 100644 --- a/stdlib.asm +++ b/stdlib.asm @@ -1,25 +1,2 @@ -; ===== INTRODUCTION ===== -; This is supposed to provide some standard library functionality for stock symphony. -; In particular its supposed to work with an unmodified ISA, that means some choices are not -; optimal (RA being stored in flags for example) - -; ===== ABI ===== - -; ----- CALLING CONVENTION ----- -; n.a. zr -; preserved: sp, r8 - r12 -; scratch: flags, r1 - r7 -; arguments: r1 - r7 (r1 = 1st argument, r6 = 6th arg/stack args, r7 = 7th arg/stack res) -; result: r1, r2 (r1 = low word, r2 = high word) -; return address: r13 - -; ----- STACK ----- -; grows downwards from top of memory -; arguments are passed in reverse order with the stack so: -; lowest address = 1st stack arg -; highest address = last stack arg - -; ===== TYPES ===== - pub include bit -pub include imath \ No newline at end of file +pub include imath From ddca02d8a80a2344699f8ff833e878a103643ca6 Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Wed, 2 Sep 2026 11:21:03 +0200 Subject: [PATCH 28/40] relax r7 requirement for result stack --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d16f476..12c7afd 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,9 @@ Arguments are passed in reverse order with the stack so: lowest address = 1st stack arg highest address = last stack arg -Should a function return more values than fit into the 7 registers, the caller has to allocate space on the stack for them, and pass the pointer to that space in r7. -This reduces the amount of argument registers to 6 and all arguments above that shall go on the stack, the pointer to the result stack shall **always** be passed in r7. -r7 points at the highest available address for results, with the 8th result being stored there, the 9th below it and so on. +Should a function return more values than fit into the 7 registers, the caller has to allocate space on the stack for them, and pass the pointer to that space in the next free argument register. +This reduces the amount of argument registers to 6 and all arguments above that shall go on the stack, the pointer to the result stack shall **always** be passed in an argument register. +This register points at the highest available address for results, with the 8th result being stored there, the 9th below it and so on. ### Stack Grows downwards from top of memory. From 8f1b970a2f5e4cc535ce308e87564c094f69341c Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Wed, 2 Sep 2026 11:31:33 +0200 Subject: [PATCH 29/40] remove mention of non existent file --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 12c7afd..aec7650 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ 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. -You'll also need to include globals.asm in the first line of your main assembly file. If you are using it as a learning resource have a look at the [teaching folder](teaching). From dbd4865f1485ba747307377ec07550e34b7fa847 Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Wed, 2 Sep 2026 11:31:52 +0200 Subject: [PATCH 30/40] change stack start --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aec7650..1a3d693 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ This reduces the amount of argument registers to 6 and all arguments above that This register points at the highest available address for results, with the 8th result being stored there, the 9th below it and so on. ### Stack -Grows downwards from top of memory. +Grows downwards from 0xXXFE_0000 (so top of memory -0x1_0000). ### Types From 8301d5988a4b8ee0f31a43a1221d6253165e7db0 Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Wed, 2 Sep 2026 11:32:46 +0200 Subject: [PATCH 31/40] create teaching directory --- teaching/README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 teaching/README.md diff --git a/teaching/README.md b/teaching/README.md new file mode 100644 index 0000000..67ae43d --- /dev/null +++ b/teaching/README.md @@ -0,0 +1,5 @@ +# Teaching + +This is a collection of teaching advice regarding the stdlib. + +**WIP** From 84636799b6d1f65a819628419911da04a747dabe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Isalski?= Date: Tue, 1 Sep 2026 22:42:32 +0200 Subject: [PATCH 32/40] Changed docs of math functions to conform to new guidelines --- imath.asm | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/imath.asm b/imath.asm index 90056f0..0c08923 100644 --- a/imath.asm +++ b/imath.asm @@ -1,8 +1,15 @@ +; Multiplies r1 and r2, returning the lower part of the result +; Arguments: +; r1 - The first value +; r2 - The second value +; Result: +; r1 - The lower 32 bits of the result +; Clobbers: r2, r3, r4, r5 pub mul_low: mov r3, 0 ; result mov r4, 31 ; loop counter - mull_loop: + mul_low_loop: asr r5, r2, 31 and r5, r5, r1 lsl r5, r5, r4 @@ -10,14 +17,18 @@ pub mul_low: lsl r2, r2, 1 sub r4, r4, 1 cmp r4, 0 - jge mull_loop + jge mul_low_loop mov r1, r3 jmp r13 ; Calculates the absolute value of the value provided in the r1 register -; Based on Stanford's BitHacks -; Clobbers r2 +; Arguments: +; r1 - The value for which we want the absolute value +; Result: +; r1 - The calculated absolute value +; Clobbers: r2 +; Info: Based on Stanford's BitHacks pub abs: ; SHOULD BE INLINED ; mask = v >> 31 asr r2, r1, 31 @@ -28,8 +39,13 @@ pub abs: ; SHOULD BE INLINED jmp r13 ; Calculates the minimum value of the two values provided in the r1 and r2 registers -; Based on Stanford's BitHacks -; Clobbers flags +; Arguments: +; r1 - The first value +; r2 - The second value +; Result: +; r1 - The smaller value +; Clobbers: Nothing +; Info: Based on Stanford's BitHacks pub min: ; SHOULD BE INLINED ; x < y cmp r1, r2 @@ -45,8 +61,13 @@ pub min: ; SHOULD BE INLINED jmp r13 ; Calculates the maximum value of the two values provided in the r1 and r2 registers -; Based on Stanford's BitHacks -; Clobbers r2 and flags +; Arguments: +; r1 - The first value +; r2 - The second value +; Result: +; r1 - The smaller value +; Clobbers: r2 +; Info: Based on Stanford's BitHacks pub max: ; SHOULD BE INLINED ; x < y cmp r1, r2 From ca1ba67fd8a6a28c175344207fb13b1d7c5e3200 Mon Sep 17 00:00:00 2001 From: Michal Isalski Date: Wed, 2 Sep 2026 13:20:55 +0200 Subject: [PATCH 33/40] Added a shift conversion LUT and finished read_line (except Writeback) --- LUTs.asm | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++ console.asm | 60 +++++++++++++++++++------------ stdlib.asm | 5 ++- 3 files changed, 141 insertions(+), 24 deletions(-) create mode 100644 LUTs.asm diff --git a/LUTs.asm b/LUTs.asm new file mode 100644 index 0000000..b078cf8 --- /dev/null +++ b/LUTs.asm @@ -0,0 +1,100 @@ +@0x10000: ; Example address until we get a proper memory map for this + +; Shift conversion table +; It stores the mapping from value 32-127 of the ASCII table to their shifted equivalents (both ways) in the standard US keyboard layout +; e.g. 1 -> ! +U8 32 ; Space -> Space +U8 49 ; ! -> 1 +U8 39 ; " -> ' +U8 51 ; # -> 3 +U8 52 ; $ -> 4 +U8 53 ; % -> 5 +U8 55 ; & -> 7 +U8 34 ; ' -> " +U8 57 ; ( -> 9 +U8 48 ; ) -> 0 +U8 56 ; * -> 8 +U8 61 ; + -> = +U8 60 ; , -> < +U8 95 ; - -> _ +U8 62 ; . -> > +U8 63 ; / -> ? +U8 41 ; 0 -> ) +U8 33 ; 1 -> ! +U8 64 ; 2 -> @ +U8 35 ; 3 -> # +U8 36 ; 4 -> $ +U8 37 ; 5 -> % +U8 94 ; 6 -> ^ +U8 38 ; 7 -> & +U8 42 ; 8 -> * +U8 40 ; 9 -> ( +U8 59 ; : -> ; +U8 58 ; ; -> : +U8 44 ; < -> , +U8 43 ; = -> + +U8 46 ; > -> . +U8 47 ; ? -> / +U8 50 ; @ -> 2 +U8 97 ; A -> a +U8 98 ; B -> b +U8 99 ; C -> c +U8 100; D -> d +U8 101; E -> e +U8 102; F -> f +U8 103; G -> g +U8 104; H -> h +U8 105; I -> i +U8 106; J -> j +U8 107; K -> k +U8 108; L -> l +U8 109; M -> m +U8 110; N -> n +U8 111; O -> o +U8 112; P -> p +U8 113; Q -> q +U8 114; R -> r +U8 115; S -> s +U8 116; T -> t +U8 117; U -> u +U8 118; V -> v +U8 119; W -> w +U8 120; X -> x +U8 121; Y -> y +U8 122; Z -> z +U8 123; [ -> { +U8 124; \ -> | +U8 125; ] -> } +U8 125; ^ -> 6 +U8 45 ; _ -> - +U8 126; ` -> ~ +U8 65 ; a -> A +U8 66 ; b -> B +U8 67 ; c -> C +U8 68 ; d -> D +U8 69 ; e -> E +U8 70 ; f -> F +U8 71 ; g -> G +U8 72 ; h -> H +U8 73 ; i -> I +U8 74 ; j -> J +U8 75 ; k -> K +U8 76 ; l -> L +U8 77 ; m -> M +U8 78 ; n -> N +U8 79 ; o -> O +U8 80 ; p -> P +U8 81 ; q -> Q +U8 82 ; r -> R +U8 83 ; s -> S +U8 84 ; t -> T +U8 85 ; u -> U +U8 86 ; v -> V +U8 87 ; w -> W +U8 88 ; x -> X +U8 89 ; y -> Y +U8 90 ; z -> Z +U8 91 ; { -> [ +U8 92 ; | -> \ +U8 93 ; } -> ] +U8 96 ; ~ -> ` \ No newline at end of file diff --git a/console.asm b/console.asm index 4b87f04..2159454 100644 --- a/console.asm +++ b/console.asm @@ -4,43 +4,56 @@ ; r1 - pointer to the buffer ; Result: ; r1 - pointer to the same buffer -; Clobbers: r2, r3, r4, r5 +; Clobbers: r2, r3, r4, r5, r6, r7 pub read_line: + mov r6, 1 + lsl r6, r6, 16 + sub r6, r6, 32 ; Calculating the address to the shift LUT + mov r2, 0 ; Storing the shift status here mov r4, 0 ; Storing the last key here, so we don't repeat the same key - mov r5, 0 ; Storing the shift status mov r3, r1 ; The pointer to after the last character - - read_line_keyloop: - keyboard r2 - - cmp r2, r4 - je read_line_keyloop ; If the current key is same as previous, we loop - mov r4, r2 ; Storing current key as previous - - cmp r2, 0x120 ; Is the key renderable or special? - jb read_line_special ; If the key was special, we handle it separately - ; TODO: Converting based on shift value - store_8 [r3], r2 ; Else, we store the key in the buffer - add r3, r3, 1 ; We advance forward - jmp read_line_keyloop + read_line_keyloop: + keyboard r5 + + cmp r5, r4 + je read_line_keyloop ; If the current key is same as previous, we loop + mov r4, r5 ; Storing current key as previous + + cmp r5, 0x120 ; Is the key renderable or special? + jb read_line_special ; If the key was special, we handle it separately + xor r5, r5, 0x100 ; Clearing the "down" bit + + cmp r2, zr ; Checking for shift status + je read_line_store ; If shift is up, we skip conversion + + ;;; converting from shift-down to shift-up keys + add r7, r6, r5 ; Calculating the index of the shift conversion + load_8 r5, [r7] ; Loading the shifted value + ;;; + + read_line_store: + store_8 [r3], r5 ; Else, we store the key in the buffer + add r3, r3, 1 ; We advance forward + ; TODO: Writeback + jmp read_line_keyloop read_line_special: - cmp r2, 13 ; Was the key Backspace? + cmp r5, 13 ; Was the key Backspace? je read_line_backspace ; If yes we need to move one character back - cmp r2, 10 ; Was the key Enter? + cmp r5, 10 ; Was the key Enter? je read_line_finished ; If so, we're finished - and r2, r2, 0x1FB ; Mask out the left/right shift direction bit - cmp r2, 0x110 ; Was the key Shift Down? + and r5, r5, 0x1FB ; Mask out the left/right shift direction bit + cmp r5, 0x110 ; Was the key Shift Down? and flags, flags, 0x1 ; We care only about equality bit - or r5, r5, flags ; If shift was down before, it still is. If it was pressed now, it is down now + or r2, r2, flags ; If shift was down before, it still is. If it was pressed now, it is down now - cmp r2, 0x010 ; Was the key Shift Up? + cmp r5, 0x010 ; Was the key Shift Up? and flags, flags, 0x1 ; We care only about equality bit xor flags, flags, 0x1 ; We invert it, i.e. "if it's not up" - and r5, r5, flags ; The shift can be kept down if it's not currently up + and r2, r2, flags ; The shift can be kept down if it's not currently up jmp read_line_keyloop ; If no special handling, we loop back @@ -48,6 +61,7 @@ pub read_line: cmp r3, r1 ; Compare the current pointer to start of buffer je read_line_keyloop ; If we are at the start, we loop sub r3, r3, 1 ; We move back one character + ; TODO: Writeback jmp read_line_keyloop read_line_finished: diff --git a/stdlib.asm b/stdlib.asm index 9742b85..fdb3385 100644 --- a/stdlib.asm +++ b/stdlib.asm @@ -23,4 +23,7 @@ pub include bit pub include imath -pub include console \ No newline at end of file +pub include console + +; Needs to be last! +pub include LUTs \ No newline at end of file From 26d3a4d4f4f31749e98f319c6a73e1133f829669 Mon Sep 17 00:00:00 2001 From: ShatteredMINT Date: Wed, 2 Sep 2026 20:48:04 +0200 Subject: [PATCH 34/40] clean up confusion about function template --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 82a0201..ed897a3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,8 +16,8 @@ All functions in the standard library should follow the following outline: ; Arguments: ; Result: ; Clobbers: -fn_label: <;SHOULD BE INLINED> - CODE +