aboutsummaryrefslogtreecommitdiff
path: root/arch/riscv/user/basics/string.S
diff options
context:
space:
mode:
authorMiquel Sabaté Solà <mikisabate@gmail.com>2024-12-04 21:42:37 +0100
committerMiquel Sabaté Solà <mikisabate@gmail.com>2024-12-05 16:02:51 +0100
commitf463d544793ff83efd8b95d0bce5ec80fd8170f3 (patch)
tree9dc6cfe5d5d9a5abb9bbe1ba401dc22308c7649e /arch/riscv/user/basics/string.S
parentbab3fdfd61b3488e1879bc3e53ac17f41d2e8b67 (diff)
downloadfarga-f463d544793ff83efd8b95d0bce5ec80fd8170f3.tar.gz
farga-f463d544793ff83efd8b95d0bce5ec80fd8170f3.zip
Remove old test code
There is some code that I had there after messing with some of the topics on Uros' blog (https://popovicu.com/), but that became irrelevant after working on some other projects (e.g. fbos) or on other examples. This commit also brings about a major overhaul on the structure of the project. Hopefully it's now at a more ready state. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
Diffstat (limited to 'arch/riscv/user/basics/string.S')
-rw-r--r--arch/riscv/user/basics/string.S111
1 files changed, 111 insertions, 0 deletions
diff --git a/arch/riscv/user/basics/string.S b/arch/riscv/user/basics/string.S
new file mode 100644
index 0000000..3878074
--- /dev/null
+++ b/arch/riscv/user/basics/string.S
@@ -0,0 +1,111 @@
+.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
+
+.globl mstrcmp
+.type mstrcmp, @function
+
+// int mstrcmp(const char *, const char *);
+mstrcmp:
+1:
+ lbu t0, 0(a0)
+ lbu t1, 0(a1)
+ bne t0, t1, 2f
+ addi a0, a0, 1
+ addi a1, a1, 1
+ bnez t0, 1b
+ li a0, 0
+ ret
+2:
+ sub a0, t0, t1
+ ret