# This Source Code Form is subject to the terms of the Mozilla Public License, # v. 2.0. If a copy of the MPL was not distributed with this file, You can # obtain one at https://mozilla.org/MPL/2.0/. .global write_s, write_c .global memcmp, memchr, memmem, memcpy .section .text # a0 - First pointer. # a1 - Second pointer. # a2 - The length to compare. # # Returns 0 in a0 if memory regions are equal. .type memcmp, @function memcmp: mv t0, a0 li a0, 0 .Lmemcmp_loop: beqz a2, .Lmemcmp_end lbu t1, (t0) lbu t2, (a1) sub a0, t1, t2 bnez a0, .Lmemcmp_end addi t0, t0, 1 addi a1, a1, 1 addi a2, a2, -1 j .Lmemcmp_loop .Lmemcmp_end: ret # Prints a string. # # Parameters: # a0 - String pointer. # a1 - Length of the string. .type write_s, @function write_s: # Prologue. addi sp, sp, -32 sw ra, 28(sp) sw s0, 24(sp) addi s0, sp, 32 sw s1, 20(sp) sw s2, 16(sp) mv s1, a1 mv s2, a0 .Lwrite_s_if: beqz s1, .Lwrite_s_end lw a0, (s2) call write_c addi s1, s1, -1 addi s2, s2, 1 j .Lwrite_s_if .Lwrite_s_end: lw s1, 20(sp) lw s2, 16(sp) # Epilogue. lw ra, 28(sp) lw s0, 24(sp) addi sp, sp, 32 ret # Prints a character from a0. # # Arguments: # a0 - Character. .type write_c, @function write_c: li a1, 0 li a2, 0 li a3, 0 li a4, 0 li a5, 0 li a6, 0 li a7, 1 # sbi_console_putchar. ecall 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 addi a2, a2, -1 j .Lmemcpy_loop .Lmemcpy_end: mv a0, t0 ret