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). 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. diff --git a/LUTs.asm b/src/LUTs.asm similarity index 100% rename from LUTs.asm rename to src/LUTs.asm diff --git a/src/array.asm b/src/array.asm new file mode 100644 index 0000000..c90ba38 --- /dev/null +++ b/src/array.asm @@ -0,0 +1,77 @@ +; 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. +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 final address here + push r8 ; We will store the mask here + + mov r12, r4 + mov r11, r1 + mov r10, r3 + mov r9, r2 + 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 + 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 + + 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 + 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 + 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 + jne find_index_loop ; If we did not reach the end we jump back into the loop + + find_index_not_found: + 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 + jmp find_index_postamble + + find_index_found_item: + add sp, sp, 4 ; The predicate context is not useful + 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 + + find_index_postamble: + pop r8 + pop r9 + pop r10 + pop r11 + pop r12 + jmp r13 ; Return 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/mem.asm b/src/mem.asm similarity index 100% rename from mem.asm rename to src/mem.asm diff --git a/stdlib.asm b/src/stdlib.asm similarity index 85% rename from stdlib.asm rename to src/stdlib.asm index 4f91d48..512c6c3 100644 --- a/stdlib.asm +++ b/src/stdlib.asm @@ -1,7 +1,8 @@ pub include bit pub include imath -pub include mem +pub include array pub include console +pub include mem ; Needs to be last! pub include LUTs diff --git a/unsafe_mem.asm b/src/unsafe_mem.asm similarity index 100% rename from unsafe_mem.asm rename to src/unsafe_mem.asm 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.