/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2024 Strahinja Stanisic <[email protected]>4*/56#include <machine/asm.h>78.weak strchrnul9.set strchrnul, __strchrnul1011/*12* a0 - const char *str13* a1 - int c;14*/15ENTRY(__strchrnul)16/*17* a0 - const char *ptr;18* a1 - char cccccccc[8];19* a2 - char iter[8];20* a3 - char mask_end21*/2223/* int to char */24andi a1, a1, 0xFF2526/* t0 = 0x0101010101010101 */27li t0, 0x0101010128slli t1, t0, 3229or t0, t0, t13031/* t1 = 0x8080808080808080 */32slli t1, t0, 73334/* spread char across bytes */35mul a1, a1, t03637/* align_offset */38andi t2, a0, 0b1113940/* align pointer */41andi a0, a0, ~0b1114243/* if pointer is aligned skip to loop */44beqz t2, .Lloop4546ld a2, (a0)4748/* mask_start calculation */49slli t2, t2, 350neg t2, t251srl t2, t0, t25253/* fill bytes before start with non-zero */54or a3, a2, t25556xor a2, a2, a157or a2, a2, t25859/* has_zero for \0 */60not t3, a361not t2, a262sub a3, a3, t063sub a2, a2, t064and a3, a3, t365and a2, a2, t266and a3, a3, t167and a2, a2, t1686970/* if \0 or c was found, exit */71or a2, a2, a372addi a0, a0, 873bnez a2, .Lfind_char747576.Lloop:77ld a2, (a0)7879/* has_zero for both \0 or c */80xor a3, a2, a18182not t2, a283not t3, a384sub a2, a2, t085sub a3, a3, t086and a2, a2, t287and a3, a3, t388and a2, a2, t189and a3, a3, t19091/* if \0 or c was found, exit */92or a2, a2, a393addi a0, a0, 894beqz a2, .Lloop9596.Lfind_char:97addi a0, a0, -89899/* isolate lowest set bit */100neg t0, a2101and a2, a2, t0102103li t0, 0x0001020304050607104srli a2, a2, 7105106/* lowest set bit is 2^(8*k)107* multiplying by it shifts the idx array in t0 by k bytes to the left */108mul a2, a2, t0109110/* highest byte contains idx of first zero */111srli a2, a2, 56112113add a0, a0, a2114ret115END(__strchrnul)116117118