summaryrefslogtreecommitdiff
path: root/boot/common-boot.s
diff options
context:
space:
mode:
Diffstat (limited to 'boot/common-boot.s')
-rw-r--r--boot/common-boot.s122
1 files changed, 120 insertions, 2 deletions
diff --git a/boot/common-boot.s b/boot/common-boot.s
index e5796f1..0cf31f1 100644
--- a/boot/common-boot.s
+++ b/boot/common-boot.s
@@ -1,6 +1,6 @@
.global _is_alpha, _is_digit, _is_alnum, _is_upper, _is_lower
.global _write_out, _read_file, _write_error, _put_char, _printi
-.global _get, _memcmp
+.global _get, _memcmp, _memchr, _memmem, _memcpy
.global _divide_by_zero_error, _exit
.section .rodata
@@ -16,7 +16,8 @@ new_line: .ascii "\n"
.section .text
-# Write the current token to stderr.
+# Write the current token to stderr. Ends the output with a newline.
+#
# a0 - String pointer.
# a1 - String length.
.type _write_error, @function
@@ -306,3 +307,120 @@ _put_char:
_get:
lw a0, (a0)
ret
+
+# Searches for the occurences of a character in the given memory block.
+#
+# Parameters:
+# a0 - Memory block.
+# a1 - Needle.
+# a2 - Memory size.
+#
+# Sets a0 to the pointer to the found character or to null if the character
+# doesn't occur in the memory block.
+.type _memchr, @function
+_memchr:
+.Lmemchr_loop:
+ beqz a2, .Lmemchr_nil # Exit if the length is 0.
+
+ lbu t0, (a0) # Load the character from the memory block.
+ beq t0, a1, .Lmemchr_end # Exit if the character was found.
+
+ # Otherwise, continue with the next character.
+ addi a0, a0, 1
+ addi a2, a2, -1
+
+ j .Lmemchr_loop
+
+.Lmemchr_nil:
+ li a0, 0
+
+.Lmemchr_end:
+ ret
+
+# Locates a substring.
+#
+# Parameters:
+# a0 - Haystack.
+# a1 - Haystack size.
+# a2 - Needle.
+# a3 - Needle size.
+#
+# Sets a0 to the pointer to the beginning of the substring in memory or to 0
+# if the substring doesn't occur in the block.
+.type _memmem, @function
+_memmem:
+ # Prologue.
+ addi sp, sp, -24
+ sw ra, 20(sp)
+ sw s0, 16(sp)
+ addi s0, sp, 24
+
+ # Save preserved registers. They are used to keep arguments.
+ sw s1, 12(sp)
+ sw s2, 8(sp)
+ sw s3, 4(sp)
+ sw s4, 0(sp)
+
+ mv s1, a0
+ mv s2, a1
+ mv s3, a2
+ mv s4, a3
+
+.Lmemmem_loop:
+ blt s2, s3, .Lmemmem_nil # Exit if the needle length is greater than memory.
+
+ mv a0, s1
+ mv a1, s3
+ mv a2, s4
+ call _memcmp
+
+ mv t0, a0 # memcmp result.
+ mv a0, s1 # Memory pointer for the case the substring was found.
+ beqz t0, .Lmemmem_end
+
+ addi s1, s1, 1
+ add s2, s2, -1
+
+ j .Lmemmem_loop
+
+.Lmemmem_nil:
+ li a0, 0
+
+.Lmemmem_end:
+
+ # Restore the preserved registers.
+ lw s1, 12(sp)
+ lw s2, 8(sp)
+ lw s3, 4(sp)
+ lw s4, 0(sp)
+
+ # Epilogue.
+ lw ra, 20(sp)
+ lw s0, 16(sp)
+ add sp, sp, 24
+ ret
+
+# Copies memory.
+#
+# Parameters:
+# a0 - Destination.
+# a1 - Source.
+# a2 - Size.
+#
+# Preserves a0.
+.type _memcpy, @function
+_memcpy:
+ mv t0, a0
+
+.Lmemcpy_loop:
+ beqz a2, .Lmemcpy_end
+
+ lbu t1, (a1)
+ sb t1, (a0)
+
+ addi a0, a0, 1
+ addi a1, a1, 1
+
+.Lmemcpy_end:
+ mv a0, t0
+ ret