Linux 5.7.6
[linux/fpc-iii.git] / arch / hexagon / mm / strnlen_user.S
blob4b5574a7cc9cfac19eb953606db48147fae10e8c
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  */
8 #define isrc    r0
9 #define max     r1      /*  Do not change!  */
11 #define end     r2
12 #define tmp1    r3
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
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  */
26 #define fname __strnlen_user
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         }
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         }
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...   */
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         }
100 exit_found:
101         {
102                 R0 = sub(start,isrc);
103                 jumpr R31;
104         }
106 exit_error:
107         {
108                 R0 = add(max,#1);
109                 jumpr R31;
110         }
112         /*  Uh, what does the "fixup" return here?  */
113         .falign
114 fix_1:
115         {
116                 R0 = #0;
117                 jumpr R31;
118         }
120         .size fname,.-fname
123 .section __ex_table,"a"
124 .long fail_1,fix_1
125 .long fail_2,fix_1
126 .previous