1/*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2024 Strahinja Stanisic <strajabot@FreeBSD.org> 5 */ 6 7#include <machine/asm.h> 8 9 .weak strchrnul 10 .set strchrnul, __strchrnul 11 12/* 13 * a0 - const char *str 14 * a1 - int c; 15 */ 16ENTRY(__strchrnul) 17 /* 18 * a0 - const char *ptr; 19 * a1 - char cccccccc[8]; 20 * a2 - char iter[8]; 21 * a3 - char mask_end 22 */ 23 24 /* int to char */ 25 andi a1, a1, 0xFF 26 27 /* t0 = 0x0101010101010101 */ 28 li t0, 0x01010101 29 slli t1, t0, 32 30 or t0, t0, t1 31 32 /* t1 = 0x8080808080808080 */ 33 slli t1, t0, 7 34 35 /* spread char across bytes */ 36 mul a1, a1, t0 37 38 /* align_offset */ 39 andi t2, a0, 0b111 40 41 /* align pointer */ 42 andi a0, a0, ~0b111 43 44 /* if pointer is aligned skip to loop */ 45 beqz t2, .Lloop 46 47 ld a2, (a0) 48 49 /* mask_start calculation */ 50 slli t2, t2, 3 51 neg t2, t2 52 srl t2, t0, t2 53 54 /* fill bytes before start with non-zero */ 55 or a3, a2, t2 56 57 xor a2, a2, a1 58 or a2, a2, t2 59 60 /* has_zero for \0 */ 61 not t3, a3 62 not t2, a2 63 sub a3, a3, t0 64 sub a2, a2, t0 65 and a3, a3, t3 66 and a2, a2, t2 67 and a3, a3, t1 68 and a2, a2, t1 69 70 71 /* if \0 or c was found, exit */ 72 or a2, a2, a3 73 addi a0, a0, 8 74 bnez a2, .Lfind_char 75 76 77.Lloop: 78 ld a2, (a0) 79 80 /* has_zero for both \0 or c */ 81 xor a3, a2, a1 82 83 not t2, a2 84 not t3, a3 85 sub a2, a2, t0 86 sub a3, a3, t0 87 and a2, a2, t2 88 and a3, a3, t3 89 and a2, a2, t1 90 and a3, a3, t1 91 92 /* if \0 or c was found, exit */ 93 or a2, a2, a3 94 addi a0, a0, 8 95 beqz a2, .Lloop 96 97.Lfind_char: 98 addi a0, a0, -8 99 100 /* isolate lowest set bit */ 101 neg t0, a2 102 and a2, a2, t0 103 104 li t0, 0x0001020304050607 105 srli a2, a2, 7 106 107 /* lowest set bit is 2^(8*k) 108 * multiplying by it shifts the idx array in t0 by k bytes to the left */ 109 mul a2, a2, t0 110 111 /* highest byte contains idx of first zero */ 112 srli a2, a2, 56 113 114 add a0, a0, a2 115 ret 116END(__strchrnul) 117