1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * User string length functions for kernel
4 *
5 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
6 */
7
8#define isrc	r0
9#define max	r1	/*  Do not change!  */
10
11#define end	r2
12#define tmp1	r3
13
14#define obo	r6	/*  off-by-one  */
15#define start	r7
16#define mod8	r8
17#define dbuf    r15:14
18#define dcmp	r13:12
19
20/*
21 * The vector mask version of this turned out *really* badly.
22 * The hardware loop version also turned out *really* badly.
23 * Seems straight pointer arithmetic basically wins here.
24 */
25
26#define fname __strnlen_user
27
28	.text
29	.global fname
30	.type fname, @function
31	.p2align 5  /*  why?  */
32fname:
33	{
34		mod8 = and(isrc,#7);
35		end = add(isrc,max);
36		start = isrc;
37	}
38	{
39		P0 = cmp.eq(mod8,#0);
40		mod8 = and(end,#7);
41		dcmp = #0;
42		if (P0.new) jump:t dw_loop;	/*  fire up the oven  */
43	}
44
45alignment_loop:
46fail_1:	{
47		tmp1 = memb(start++#1);
48	}
49	{
50		P0 = cmp.eq(tmp1,#0);
51		if (P0.new) jump:nt exit_found;
52		P1 = cmp.gtu(end,start);
53		mod8 = and(start,#7);
54	}
55	{
56		if (!P1) jump exit_error;  /*  hit the end  */
57		P0 = cmp.eq(mod8,#0);
58	}
59	{
60		if (!P0) jump alignment_loop;
61	}
62
63
64
65dw_loop:
66fail_2:	{
67		dbuf = memd(start);
68		obo = add(start,#1);
69	}
70	{
71		P0 = vcmpb.eq(dbuf,dcmp);
72	}
73	{
74		tmp1 = P0;
75		P0 = cmp.gtu(end,start);
76	}
77	{
78		tmp1 = ct0(tmp1);
79		mod8 = and(end,#7);
80		if (!P0) jump end_check;
81	}
82	{
83		P0 = cmp.eq(tmp1,#32);
84		if (!P0.new) jump:nt exit_found;
85		if (!P0.new) start = add(obo,tmp1);
86	}
87	{
88		start = add(start,#8);
89		jump dw_loop;
90	}	/*  might be nice to combine these jumps...   */
91
92
93end_check:
94	{
95		P0 = cmp.gt(tmp1,mod8);
96		if (P0.new) jump:nt exit_error;	/*  neverfound!  */
97		start = add(obo,tmp1);
98	}
99
100exit_found:
101	{
102		R0 = sub(start,isrc);
103		jumpr R31;
104	}
105
106exit_error:
107	{
108		R0 = add(max,#1);
109		jumpr R31;
110	}
111
112	/*  Uh, what does the "fixup" return here?  */
113	.falign
114fix_1:
115	{
116		R0 = #0;
117		jumpr R31;
118	}
119
120	.size fname,.-fname
121
122
123.section __ex_table,"a"
124.long fail_1,fix_1
125.long fail_2,fix_1
126.previous
127