Merge remote-tracking branch 'asoc/fix/ux500' into asoc-linus
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / arch / hexagon / mm / strnlen_user.S
1 /*
2 * User string length functions for kernel
3 *
4 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and
8 * only version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 * 02110-1301, USA.
19 */
20
21 #define isrc r0
22 #define max r1 /* Do not change! */
23
24 #define end r2
25 #define tmp1 r3
26
27 #define obo r6 /* off-by-one */
28 #define start r7
29 #define mod8 r8
30 #define dbuf r15:14
31 #define dcmp r13:12
32
33 /*
34 * The vector mask version of this turned out *really* badly.
35 * The hardware loop version also turned out *really* badly.
36 * Seems straight pointer arithmetic basically wins here.
37 */
38
39 #define fname __strnlen_user
40
41 .text
42 .global fname
43 .type fname, @function
44 .p2align 5 /* why? */
45 fname:
46 {
47 mod8 = and(isrc,#7);
48 end = add(isrc,max);
49 start = isrc;
50 }
51 {
52 P0 = cmp.eq(mod8,#0);
53 mod8 = and(end,#7);
54 dcmp = #0;
55 if (P0.new) jump:t dw_loop; /* fire up the oven */
56 }
57
58 alignment_loop:
59 fail_1: {
60 tmp1 = memb(start++#1);
61 }
62 {
63 P0 = cmp.eq(tmp1,#0);
64 if (P0.new) jump:nt exit_found;
65 P1 = cmp.gtu(end,start);
66 mod8 = and(start,#7);
67 }
68 {
69 if (!P1) jump exit_error; /* hit the end */
70 P0 = cmp.eq(mod8,#0);
71 }
72 {
73 if (!P0) jump alignment_loop;
74 }
75
76
77
78 dw_loop:
79 fail_2: {
80 dbuf = memd(start);
81 obo = add(start,#1);
82 }
83 {
84 P0 = vcmpb.eq(dbuf,dcmp);
85 }
86 {
87 tmp1 = P0;
88 P0 = cmp.gtu(end,start);
89 }
90 {
91 tmp1 = ct0(tmp1);
92 mod8 = and(end,#7);
93 if (!P0) jump end_check;
94 }
95 {
96 P0 = cmp.eq(tmp1,#32);
97 if (!P0.new) jump:nt exit_found;
98 if (!P0.new) start = add(obo,tmp1);
99 }
100 {
101 start = add(start,#8);
102 jump dw_loop;
103 } /* might be nice to combine these jumps... */
104
105
106 end_check:
107 {
108 P0 = cmp.gt(tmp1,mod8);
109 if (P0.new) jump:nt exit_error; /* neverfound! */
110 start = add(obo,tmp1);
111 }
112
113 exit_found:
114 {
115 R0 = sub(start,isrc);
116 jumpr R31;
117 }
118
119 exit_error:
120 {
121 R0 = add(max,#1);
122 jumpr R31;
123 }
124
125 /* Uh, what does the "fixup" return here? */
126 .falign
127 fix_1:
128 {
129 R0 = #0;
130 jumpr R31;
131 }
132
133 .size fname,.-fname
134
135
136 .section __ex_table,"a"
137 .long fail_1,fix_1
138 .long fail_2,fix_1
139 .previous