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