xref: /openbmc/linux/arch/powerpc/lib/xor_vmx.c (revision 293d5b43)
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);
192