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?  */
32 fname:
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 
45 alignment_loop:
46 fail_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 
65 dw_loop:
66 fail_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 
93 end_check:
94 	{
95 		P0 = cmp.gt(tmp1,mod8);
96 		if (P0.new) jump:nt exit_error;	/*  neverfound!  */
97 		start = add(obo,tmp1);
98 	}
99 
100 exit_found:
101 	{
102 		R0 = sub(start,isrc);
103 		jumpr R31;
104 	}
105 
106 exit_error:
107 	{
108 		R0 = add(max,#1);
109 		jumpr R31;
110 	}
111 
112 	/*  Uh, what does the "fixup" return here?  */
113 	.falign
114 fix_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