xref: /freebsd/lib/libc/riscv/string/strchrnul.S (revision 08af0bbc9c7d71bbaadb31ad31f8492f40537c5c)
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