GNU Linux-libre 4.9.317-gnu1
[releases.git] / arch / powerpc / lib / xor_vmx.c
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15  *
16  * Copyright (C) IBM Corporation, 2012
17  *
18  * Author: Anton Blanchard <anton@au.ibm.com>
19  */
20
21 /*
22  * Sparse (as at v0.5.0) gets very, very confused by this file.
23  * Make it a bit simpler for it.
24  */
25 #if !defined(__CHECKER__)
26 #include <altivec.h>
27 #else
28 #define vec_xor(a, b) a ^ b
29 #define vector __attribute__((vector_size(16)))
30 #endif
31
32 #include <linux/preempt.h>
33 #include <linux/export.h>
34 #include <linux/sched.h>
35 #include <asm/switch_to.h>
36
37 typedef vector signed char unative_t;
38
39 #define DEFINE(V)                               \
40         unative_t *V = (unative_t *)V##_in;     \
41         unative_t V##_0, V##_1, V##_2, V##_3
42
43 #define LOAD(V)                 \
44         do {                    \
45                 V##_0 = V[0];   \
46                 V##_1 = V[1];   \
47                 V##_2 = V[2];   \
48                 V##_3 = V[3];   \
49         } while (0)
50
51 #define STORE(V)                \
52         do {                    \
53                 V[0] = V##_0;   \
54                 V[1] = V##_1;   \
55                 V[2] = V##_2;   \
56                 V[3] = V##_3;   \
57         } while (0)
58
59 #define XOR(V1, V2)                                     \
60         do {                                            \
61                 V1##_0 = vec_xor(V1##_0, V2##_0);       \
62                 V1##_1 = vec_xor(V1##_1, V2##_1);       \
63                 V1##_2 = vec_xor(V1##_2, V2##_2);       \
64                 V1##_3 = vec_xor(V1##_3, V2##_3);       \
65         } while (0)
66
67 void xor_altivec_2(unsigned long bytes, unsigned long *v1_in,
68                    unsigned long *v2_in)
69 {
70         DEFINE(v1);
71         DEFINE(v2);
72         unsigned long lines = bytes / (sizeof(unative_t)) / 4;
73
74         preempt_disable();
75         enable_kernel_altivec();
76
77         do {
78                 LOAD(v1);
79                 LOAD(v2);
80                 XOR(v1, v2);
81                 STORE(v1);
82
83                 v1 += 4;
84                 v2 += 4;
85         } while (--lines > 0);
86
87         disable_kernel_altivec();
88         preempt_enable();
89 }
90 EXPORT_SYMBOL(xor_altivec_2);
91
92 void xor_altivec_3(unsigned long bytes, unsigned long *v1_in,
93                    unsigned long *v2_in, unsigned long *v3_in)
94 {
95         DEFINE(v1);
96         DEFINE(v2);
97         DEFINE(v3);
98         unsigned long lines = bytes / (sizeof(unative_t)) / 4;
99
100         preempt_disable();
101         enable_kernel_altivec();
102
103         do {
104                 LOAD(v1);
105                 LOAD(v2);
106                 LOAD(v3);
107                 XOR(v1, v2);
108                 XOR(v1, v3);
109                 STORE(v1);
110
111                 v1 += 4;
112                 v2 += 4;
113                 v3 += 4;
114         } while (--lines > 0);
115
116         disable_kernel_altivec();
117         preempt_enable();
118 }
119 EXPORT_SYMBOL(xor_altivec_3);
120
121 void xor_altivec_4(unsigned long bytes, unsigned long *v1_in,
122                    unsigned long *v2_in, unsigned long *v3_in,
123                    unsigned long *v4_in)
124 {
125         DEFINE(v1);
126         DEFINE(v2);
127         DEFINE(v3);
128         DEFINE(v4);
129         unsigned long lines = bytes / (sizeof(unative_t)) / 4;
130
131         preempt_disable();
132         enable_kernel_altivec();
133
134         do {
135                 LOAD(v1);
136                 LOAD(v2);
137                 LOAD(v3);
138                 LOAD(v4);
139                 XOR(v1, v2);
140                 XOR(v3, v4);
141                 XOR(v1, v3);
142                 STORE(v1);
143
144                 v1 += 4;
145                 v2 += 4;
146                 v3 += 4;
147                 v4 += 4;
148         } while (--lines > 0);
149
150         disable_kernel_altivec();
151         preempt_enable();
152 }
153 EXPORT_SYMBOL(xor_altivec_4);
154
155 void xor_altivec_5(unsigned long bytes, unsigned long *v1_in,
156                    unsigned long *v2_in, unsigned long *v3_in,
157                    unsigned long *v4_in, unsigned long *v5_in)
158 {
159         DEFINE(v1);
160         DEFINE(v2);
161         DEFINE(v3);
162         DEFINE(v4);
163         DEFINE(v5);
164         unsigned long lines = bytes / (sizeof(unative_t)) / 4;
165
166         preempt_disable();
167         enable_kernel_altivec();
168
169         do {
170                 LOAD(v1);
171                 LOAD(v2);
172                 LOAD(v3);
173                 LOAD(v4);
174                 LOAD(v5);
175                 XOR(v1, v2);
176                 XOR(v3, v4);
177                 XOR(v1, v5);
178                 XOR(v1, v3);
179                 STORE(v1);
180
181                 v1 += 4;
182                 v2 += 4;
183                 v3 += 4;
184                 v4 += 4;
185                 v5 += 4;
186         } while (--lines > 0);
187
188         disable_kernel_altivec();
189         preempt_enable();
190 }
191 EXPORT_SYMBOL(xor_altivec_5);