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