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