diff options
| author | Miquel Sabaté Solà <mikisabate@gmail.com> | 2024-08-28 22:25:56 +0200 |
|---|---|---|
| committer | Miquel Sabaté Solà <mikisabate@gmail.com> | 2024-12-05 16:02:49 +0100 |
| commit | ab03d3be21f229be8c28dba292d5da237a929a73 (patch) | |
| tree | 8bc53e3031f644532fec255bb392a90cd4ad59fb /basics | |
| parent | 1a36e6211674f1a39c7cc0ddff705357a4add65a (diff) | |
| download | farga-ab03d3be21f229be8c28dba292d5da237a929a73.tar.gz farga-ab03d3be21f229be8c28dba292d5da237a929a73.zip | |
Restructure the whole thing
It will be something more than just messing around with RISC-V stuff.
Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
Diffstat (limited to 'basics')
| -rw-r--r-- | basics/Makefile | 20 | ||||
| -rw-r--r-- | basics/factorial.S | 28 | ||||
| -rw-r--r-- | basics/float.S | 40 | ||||
| -rw-r--r-- | basics/main.c | 89 | ||||
| -rw-r--r-- | basics/string.S | 93 |
5 files changed, 0 insertions, 270 deletions
diff --git a/basics/Makefile b/basics/Makefile deleted file mode 100644 index 6e36dd6..0000000 --- a/basics/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -CC = $(CROSS_COMPILE)gcc -LD = $(CROSS_COMPILE)ld -CCFLAGS = -EXE = basics - -DEBUG = -ifneq ($(strip $(DEBUG)),) - CCFLAGS += -g -endif - -.PHONY: all -all: clean $(EXE) - -.PHONY: $(EXE) -$(EXE): - gcc $(CCFLAGS) -o $(EXE) main.c factorial.S string.S float.S - -.PHONY: clean -clean: - @rm -f $(EXE) diff --git a/basics/factorial.S b/basics/factorial.S deleted file mode 100644 index 7e3df12..0000000 --- a/basics/factorial.S +++ /dev/null @@ -1,28 +0,0 @@ -.text -.globl factorial -.type factorial, @function - -factorial: - // If input <= 1, just return the given thing. - addi t0, zero, 1 - bgt a0, t0, else - jr ra -else: - // Preserve the argument and the return address before the call. - addi sp, sp, -16 - sd a0, 0(sp) - sd ra, 8(sp) - - // Call the same function but with a value of argument-1. - addi a0, a0, -1 - call factorial - - // Restore back the original argument and the return address. Then multiply - // the original argument with the returned one from the previous call. - ld t1, 0(sp) - ld ra, 8(sp) - addi sp, sp, 16 - mul a0, t1, a0 - - // And return to the caller. - jr ra diff --git a/basics/float.S b/basics/float.S deleted file mode 100644 index f481f3e..0000000 --- a/basics/float.S +++ /dev/null @@ -1,40 +0,0 @@ -.text -.globl greater_than_ten -.type greater_than_ten, @function - -// bool greater_than_ten(double a, uint64_t b); -greater_than_ten: - // Upon entry a -> fa0; and b -> a0. That is, the ABI increments the - //(f)a<n> register per argument type. - - // Change the rounding to "Rounds Towards Zero" (bits: 0b001). - li t0, 0b001 - fsrm t0 - - // Convert the second parameter to double. - fcvt.d.lu ft0, a0 - - // ret = a + b - fadd.d fa0, fa0, ft0 - - // ret = (ret * b) + b - fmv.d ft1, ft0 - fmadd.d fa0, fa0, ft0, ft1 - - // Now we need to compare the number with 10.0. There are multiple ways to - // load a floating point immediate: - // 1. Loading an integer immediate and then convert it into a double. This - // is discouraged on the RISC-V assembly manual. - // 2. Load a double with `fld` from a memory location on the data section. - // 3. Load a floating point immediate with `fli` (requires the `Zfa` - // extension). - // I don't have the `Zfa` extension on my board, so I'm opting for the - // second way. - fld ft1, .TEN, t0 - fle.d a0, ft1, fa0 - - ret - -.data -.TEN: - .double 10.0 diff --git a/basics/main.c b/basics/main.c deleted file mode 100644 index 4b5f289..0000000 --- a/basics/main.c +++ /dev/null @@ -1,89 +0,0 @@ -#include <assert.h> -#include <stdbool.h> -#include <stdio.h> -#include <stdint.h> -#include <string.h> - -/* - * Returns the factorial for the given unsigned 64-bit integer. - * - * Implemented in factorial.S - */ -int factorial(uint64_t n); - -void test_factorial(void) -{ - assert(factorial(0) == 0); - assert(factorial(1) == 1); - assert(factorial(2) == 2); - assert(factorial(3) == 6); - assert(factorial(4) == 24); - - printf("factorial:\t\tOK\n"); -} - -/* - * Returns a pointer with the same given string but reversed. Note that the - * string cannot be in read-only space since the reversal is done in-place. - * - * Implemented in string.S - */ -char * reverse_string(char *str); - -void test_reverse_string(void) -{ - assert(reverse_string(NULL) == NULL); - assert(reverse_string("") == ""); - - char s1[] = "This is a string."; - assert(strcmp(reverse_string(s1), ".gnirts a si sihT") == 0); - - char s2[] = "."; - assert(strcmp(reverse_string(s2), ".") == 0); - - printf("reverse_string:\t\tOK\n"); -} - -/* - * Returns true if the given string is a palindrome, false otherwise. - * - * Implemented in string.S - */ -bool is_palindrome(char *str); - -void test_is_palindrome(void) -{ - assert(is_palindrome(NULL) == 0); - assert(is_palindrome("") == 0); - assert(is_palindrome("aba") == 1); - assert(is_palindrome("aaa") == 1); - assert(is_palindrome("This is a a si sihT") == 1); - - printf("is_palindrome:\t\tOK\n"); -} - -/* - * This function computes the following: ((a + b) * b) + b. Don't try to make - * sense of it, that's the computation I ended up while messing with RISC-V - * floating point instructions. Anyways, with this in mind, it will return if - * the computed value is greater than 10. - * - * Implemented in float.S - */ -bool greater_than_ten(double a, uint64_t b); - -void test_greater_than_ten(void) -{ - assert(!greater_than_ten(2.3, 1)); // 4.3 - assert(greater_than_ten(2.3, 2)); // 10.6 - - printf("greater_than_ten:\tOK\n"); -} - -int main() -{ - test_factorial(); - test_reverse_string(); - test_is_palindrome(); - test_greater_than_ten(); -} diff --git a/basics/string.S b/basics/string.S deleted file mode 100644 index 0f3bcc1..0000000 --- a/basics/string.S +++ /dev/null @@ -1,93 +0,0 @@ -.text - -.globl reverse_string -.type reverse_string, @function - -// char * reverse_string(char *str); -reverse_string: - // Return early on null pointer. - beq a0, zero, end - - // Preserve the original pointer. - addi sp, sp, -8 - sd a0, 0(sp) - - // Set `t0` to point to the end of the string. - add t0, a0, zero -set_end_ptr: - lbu t2, 0(t0) - beq t2, zero, end_ptr_done - addi t0, t0, 1 - j set_end_ptr - - // We are done iterating, if `a0` and `t0` are equal, then there's nothing - // to be done and we can return early. Otherwise decrement `t0` so it points - // to the byte right before the null termination. -end_ptr_done: - beq a0, t0, reverse_done - addi t0, t0, -1 - -reverse_loop: - // Swap values between the two pointers. - lb t1, 0(a0) - lb t2, 0(t0) - sb t1, 0(t0) - sb t2, 0(a0) - - // Move pointers and check whether the pointers have already crossed. If - // they have not crossed yet there is still looping to be done. Otherwise - // we are done. - addi a0, a0, 1 - addi t0, t0, -1 - bltu a0, t0, reverse_loop - -reverse_done: - // Restore things back and return to the caller. - ld a0, 0(sp) - addi sp, sp, 8 -end: - jr ra - -.globl is_palindrome -.type is_palindrome, @function - -// bool is_palindrome(char *str); -is_palindrome: - // Return early on null pointer. - beq a0, zero, palindrome_no - - // Set `t0` to point to the end of the string. - add t0, a0, zero -pal_set_end_ptr: - lbu t2, 0(t0) - beq t2, zero, pal_end_ptr_done - addi t0, t0, 1 - j pal_set_end_ptr - - // We are done iterating, if `a0` and `t0` are equal, then there's nothing - // to be done and we can return early. Otherwise decrement `t0` so it points - // to the byte right before the null termination. -pal_end_ptr_done: - beq a0, t0, palindrome_no - addi t0, t0, -1 - -pal_loop: - // Swap values between the two pointers. - lb t1, 0(a0) - lb t2, 0(t0) - bne t1, t2, palindrome_no - - // Move pointers and check whether the pointers have already crossed. If - // they have not crossed yet there is still looping to be done. Otherwise - // we are done. - addi a0, a0, 1 - addi t0, t0, -1 - bleu a0, t0, pal_loop - -palindrome_yes: - li a0, 1 - jr ra - -palindrome_no: - li a0, 0 - jr ra |
