xref: /linux/lib/raid/xor/x86/xor-mmx.c (revision 440d6635b20037bc9ad46b20817d7b61cef0fc1b)
177fd47e5SChristoph Hellwig // SPDX-License-Identifier: GPL-2.0-or-later
277fd47e5SChristoph Hellwig /*
377fd47e5SChristoph Hellwig  * Optimized XOR parity functions for MMX.
477fd47e5SChristoph Hellwig  *
577fd47e5SChristoph Hellwig  * Copyright (C) 1998 Ingo Molnar.
677fd47e5SChristoph Hellwig  */
777fd47e5SChristoph Hellwig #include <asm/fpu/api.h>
8e20043b4SChristoph Hellwig #include "xor_impl.h"
9e20043b4SChristoph Hellwig #include "xor_arch.h"
1077fd47e5SChristoph Hellwig 
1177fd47e5SChristoph Hellwig #define LD(x, y)	"       movq   8*("#x")(%1), %%mm"#y"   ;\n"
1277fd47e5SChristoph Hellwig #define ST(x, y)	"       movq %%mm"#y",   8*("#x")(%1)   ;\n"
1377fd47e5SChristoph Hellwig #define XO1(x, y)	"       pxor   8*("#x")(%2), %%mm"#y"   ;\n"
1477fd47e5SChristoph Hellwig #define XO2(x, y)	"       pxor   8*("#x")(%3), %%mm"#y"   ;\n"
1577fd47e5SChristoph Hellwig #define XO3(x, y)	"       pxor   8*("#x")(%4), %%mm"#y"   ;\n"
1677fd47e5SChristoph Hellwig #define XO4(x, y)	"       pxor   8*("#x")(%5), %%mm"#y"   ;\n"
1777fd47e5SChristoph Hellwig 
1877fd47e5SChristoph Hellwig static void
1977fd47e5SChristoph Hellwig xor_pII_mmx_2(unsigned long bytes, unsigned long * __restrict p1,
2077fd47e5SChristoph Hellwig 	      const unsigned long * __restrict p2)
2177fd47e5SChristoph Hellwig {
2277fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 7;
2377fd47e5SChristoph Hellwig 
2477fd47e5SChristoph Hellwig 	asm volatile(
2577fd47e5SChristoph Hellwig #undef BLOCK
2677fd47e5SChristoph Hellwig #define BLOCK(i)				\
2777fd47e5SChristoph Hellwig 	LD(i, 0)				\
2877fd47e5SChristoph Hellwig 		LD(i + 1, 1)			\
2977fd47e5SChristoph Hellwig 			LD(i + 2, 2)		\
3077fd47e5SChristoph Hellwig 				LD(i + 3, 3)	\
3177fd47e5SChristoph Hellwig 	XO1(i, 0)				\
3277fd47e5SChristoph Hellwig 	ST(i, 0)				\
3377fd47e5SChristoph Hellwig 		XO1(i+1, 1)			\
3477fd47e5SChristoph Hellwig 		ST(i+1, 1)			\
3577fd47e5SChristoph Hellwig 			XO1(i + 2, 2)		\
3677fd47e5SChristoph Hellwig 			ST(i + 2, 2)		\
3777fd47e5SChristoph Hellwig 				XO1(i + 3, 3)	\
3877fd47e5SChristoph Hellwig 				ST(i + 3, 3)
3977fd47e5SChristoph Hellwig 
4077fd47e5SChristoph Hellwig 	" .align 32			;\n"
4177fd47e5SChristoph Hellwig 	" 1:                            ;\n"
4277fd47e5SChristoph Hellwig 
4377fd47e5SChristoph Hellwig 	BLOCK(0)
4477fd47e5SChristoph Hellwig 	BLOCK(4)
4577fd47e5SChristoph Hellwig 	BLOCK(8)
4677fd47e5SChristoph Hellwig 	BLOCK(12)
4777fd47e5SChristoph Hellwig 
4877fd47e5SChristoph Hellwig 	"       addl $128, %1         ;\n"
4977fd47e5SChristoph Hellwig 	"       addl $128, %2         ;\n"
5077fd47e5SChristoph Hellwig 	"       decl %0               ;\n"
5177fd47e5SChristoph Hellwig 	"       jnz 1b                ;\n"
5277fd47e5SChristoph Hellwig 	: "+r" (lines),
5377fd47e5SChristoph Hellwig 	  "+r" (p1), "+r" (p2)
5477fd47e5SChristoph Hellwig 	:
5577fd47e5SChristoph Hellwig 	: "memory");
5677fd47e5SChristoph Hellwig }
5777fd47e5SChristoph Hellwig 
5877fd47e5SChristoph Hellwig static void
5977fd47e5SChristoph Hellwig xor_pII_mmx_3(unsigned long bytes, unsigned long * __restrict p1,
6077fd47e5SChristoph Hellwig 	      const unsigned long * __restrict p2,
6177fd47e5SChristoph Hellwig 	      const unsigned long * __restrict p3)
6277fd47e5SChristoph Hellwig {
6377fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 7;
6477fd47e5SChristoph Hellwig 
6577fd47e5SChristoph Hellwig 	asm volatile(
6677fd47e5SChristoph Hellwig #undef BLOCK
6777fd47e5SChristoph Hellwig #define BLOCK(i)				\
6877fd47e5SChristoph Hellwig 	LD(i, 0)				\
6977fd47e5SChristoph Hellwig 		LD(i + 1, 1)			\
7077fd47e5SChristoph Hellwig 			LD(i + 2, 2)		\
7177fd47e5SChristoph Hellwig 				LD(i + 3, 3)	\
7277fd47e5SChristoph Hellwig 	XO1(i, 0)				\
7377fd47e5SChristoph Hellwig 		XO1(i + 1, 1)			\
7477fd47e5SChristoph Hellwig 			XO1(i + 2, 2)		\
7577fd47e5SChristoph Hellwig 				XO1(i + 3, 3)	\
7677fd47e5SChristoph Hellwig 	XO2(i, 0)				\
7777fd47e5SChristoph Hellwig 	ST(i, 0)				\
7877fd47e5SChristoph Hellwig 		XO2(i + 1, 1)			\
7977fd47e5SChristoph Hellwig 		ST(i + 1, 1)			\
8077fd47e5SChristoph Hellwig 			XO2(i + 2, 2)		\
8177fd47e5SChristoph Hellwig 			ST(i + 2, 2)		\
8277fd47e5SChristoph Hellwig 				XO2(i + 3, 3)	\
8377fd47e5SChristoph Hellwig 				ST(i + 3, 3)
8477fd47e5SChristoph Hellwig 
8577fd47e5SChristoph Hellwig 	" .align 32			;\n"
8677fd47e5SChristoph Hellwig 	" 1:                            ;\n"
8777fd47e5SChristoph Hellwig 
8877fd47e5SChristoph Hellwig 	BLOCK(0)
8977fd47e5SChristoph Hellwig 	BLOCK(4)
9077fd47e5SChristoph Hellwig 	BLOCK(8)
9177fd47e5SChristoph Hellwig 	BLOCK(12)
9277fd47e5SChristoph Hellwig 
9377fd47e5SChristoph Hellwig 	"       addl $128, %1         ;\n"
9477fd47e5SChristoph Hellwig 	"       addl $128, %2         ;\n"
9577fd47e5SChristoph Hellwig 	"       addl $128, %3         ;\n"
9677fd47e5SChristoph Hellwig 	"       decl %0               ;\n"
9777fd47e5SChristoph Hellwig 	"       jnz 1b                ;\n"
9877fd47e5SChristoph Hellwig 	: "+r" (lines),
9977fd47e5SChristoph Hellwig 	  "+r" (p1), "+r" (p2), "+r" (p3)
10077fd47e5SChristoph Hellwig 	:
10177fd47e5SChristoph Hellwig 	: "memory");
10277fd47e5SChristoph Hellwig }
10377fd47e5SChristoph Hellwig 
10477fd47e5SChristoph Hellwig static void
10577fd47e5SChristoph Hellwig xor_pII_mmx_4(unsigned long bytes, unsigned long * __restrict p1,
10677fd47e5SChristoph Hellwig 	      const unsigned long * __restrict p2,
10777fd47e5SChristoph Hellwig 	      const unsigned long * __restrict p3,
10877fd47e5SChristoph Hellwig 	      const unsigned long * __restrict p4)
10977fd47e5SChristoph Hellwig {
11077fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 7;
11177fd47e5SChristoph Hellwig 
11277fd47e5SChristoph Hellwig 	asm volatile(
11377fd47e5SChristoph Hellwig #undef BLOCK
11477fd47e5SChristoph Hellwig #define BLOCK(i)				\
11577fd47e5SChristoph Hellwig 	LD(i, 0)				\
11677fd47e5SChristoph Hellwig 		LD(i + 1, 1)			\
11777fd47e5SChristoph Hellwig 			LD(i + 2, 2)		\
11877fd47e5SChristoph Hellwig 				LD(i + 3, 3)	\
11977fd47e5SChristoph Hellwig 	XO1(i, 0)				\
12077fd47e5SChristoph Hellwig 		XO1(i + 1, 1)			\
12177fd47e5SChristoph Hellwig 			XO1(i + 2, 2)		\
12277fd47e5SChristoph Hellwig 				XO1(i + 3, 3)	\
12377fd47e5SChristoph Hellwig 	XO2(i, 0)				\
12477fd47e5SChristoph Hellwig 		XO2(i + 1, 1)			\
12577fd47e5SChristoph Hellwig 			XO2(i + 2, 2)		\
12677fd47e5SChristoph Hellwig 				XO2(i + 3, 3)	\
12777fd47e5SChristoph Hellwig 	XO3(i, 0)				\
12877fd47e5SChristoph Hellwig 	ST(i, 0)				\
12977fd47e5SChristoph Hellwig 		XO3(i + 1, 1)			\
13077fd47e5SChristoph Hellwig 		ST(i + 1, 1)			\
13177fd47e5SChristoph Hellwig 			XO3(i + 2, 2)		\
13277fd47e5SChristoph Hellwig 			ST(i + 2, 2)		\
13377fd47e5SChristoph Hellwig 				XO3(i + 3, 3)	\
13477fd47e5SChristoph Hellwig 				ST(i + 3, 3)
13577fd47e5SChristoph Hellwig 
13677fd47e5SChristoph Hellwig 	" .align 32			;\n"
13777fd47e5SChristoph Hellwig 	" 1:                            ;\n"
13877fd47e5SChristoph Hellwig 
13977fd47e5SChristoph Hellwig 	BLOCK(0)
14077fd47e5SChristoph Hellwig 	BLOCK(4)
14177fd47e5SChristoph Hellwig 	BLOCK(8)
14277fd47e5SChristoph Hellwig 	BLOCK(12)
14377fd47e5SChristoph Hellwig 
14477fd47e5SChristoph Hellwig 	"       addl $128, %1         ;\n"
14577fd47e5SChristoph Hellwig 	"       addl $128, %2         ;\n"
14677fd47e5SChristoph Hellwig 	"       addl $128, %3         ;\n"
14777fd47e5SChristoph Hellwig 	"       addl $128, %4         ;\n"
14877fd47e5SChristoph Hellwig 	"       decl %0               ;\n"
14977fd47e5SChristoph Hellwig 	"       jnz 1b                ;\n"
15077fd47e5SChristoph Hellwig 	: "+r" (lines),
15177fd47e5SChristoph Hellwig 	  "+r" (p1), "+r" (p2), "+r" (p3), "+r" (p4)
15277fd47e5SChristoph Hellwig 	:
15377fd47e5SChristoph Hellwig 	: "memory");
15477fd47e5SChristoph Hellwig }
15577fd47e5SChristoph Hellwig 
15677fd47e5SChristoph Hellwig 
15777fd47e5SChristoph Hellwig static void
15877fd47e5SChristoph Hellwig xor_pII_mmx_5(unsigned long bytes, unsigned long * __restrict p1,
15977fd47e5SChristoph Hellwig 	      const unsigned long * __restrict p2,
16077fd47e5SChristoph Hellwig 	      const unsigned long * __restrict p3,
16177fd47e5SChristoph Hellwig 	      const unsigned long * __restrict p4,
16277fd47e5SChristoph Hellwig 	      const unsigned long * __restrict p5)
16377fd47e5SChristoph Hellwig {
16477fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 7;
16577fd47e5SChristoph Hellwig 
16677fd47e5SChristoph Hellwig 	/* Make sure GCC forgets anything it knows about p4 or p5,
16777fd47e5SChristoph Hellwig 	   such that it won't pass to the asm volatile below a
16877fd47e5SChristoph Hellwig 	   register that is shared with any other variable.  That's
16977fd47e5SChristoph Hellwig 	   because we modify p4 and p5 there, but we can't mark them
17077fd47e5SChristoph Hellwig 	   as read/write, otherwise we'd overflow the 10-asm-operands
17177fd47e5SChristoph Hellwig 	   limit of GCC < 3.1.  */
17277fd47e5SChristoph Hellwig 	asm("" : "+r" (p4), "+r" (p5));
17377fd47e5SChristoph Hellwig 
17477fd47e5SChristoph Hellwig 	asm volatile(
17577fd47e5SChristoph Hellwig #undef BLOCK
17677fd47e5SChristoph Hellwig #define BLOCK(i)				\
17777fd47e5SChristoph Hellwig 	LD(i, 0)				\
17877fd47e5SChristoph Hellwig 		LD(i + 1, 1)			\
17977fd47e5SChristoph Hellwig 			LD(i + 2, 2)		\
18077fd47e5SChristoph Hellwig 				LD(i + 3, 3)	\
18177fd47e5SChristoph Hellwig 	XO1(i, 0)				\
18277fd47e5SChristoph Hellwig 		XO1(i + 1, 1)			\
18377fd47e5SChristoph Hellwig 			XO1(i + 2, 2)		\
18477fd47e5SChristoph Hellwig 				XO1(i + 3, 3)	\
18577fd47e5SChristoph Hellwig 	XO2(i, 0)				\
18677fd47e5SChristoph Hellwig 		XO2(i + 1, 1)			\
18777fd47e5SChristoph Hellwig 			XO2(i + 2, 2)		\
18877fd47e5SChristoph Hellwig 				XO2(i + 3, 3)	\
18977fd47e5SChristoph Hellwig 	XO3(i, 0)				\
19077fd47e5SChristoph Hellwig 		XO3(i + 1, 1)			\
19177fd47e5SChristoph Hellwig 			XO3(i + 2, 2)		\
19277fd47e5SChristoph Hellwig 				XO3(i + 3, 3)	\
19377fd47e5SChristoph Hellwig 	XO4(i, 0)				\
19477fd47e5SChristoph Hellwig 	ST(i, 0)				\
19577fd47e5SChristoph Hellwig 		XO4(i + 1, 1)			\
19677fd47e5SChristoph Hellwig 		ST(i + 1, 1)			\
19777fd47e5SChristoph Hellwig 			XO4(i + 2, 2)		\
19877fd47e5SChristoph Hellwig 			ST(i + 2, 2)		\
19977fd47e5SChristoph Hellwig 				XO4(i + 3, 3)	\
20077fd47e5SChristoph Hellwig 				ST(i + 3, 3)
20177fd47e5SChristoph Hellwig 
20277fd47e5SChristoph Hellwig 	" .align 32			;\n"
20377fd47e5SChristoph Hellwig 	" 1:                            ;\n"
20477fd47e5SChristoph Hellwig 
20577fd47e5SChristoph Hellwig 	BLOCK(0)
20677fd47e5SChristoph Hellwig 	BLOCK(4)
20777fd47e5SChristoph Hellwig 	BLOCK(8)
20877fd47e5SChristoph Hellwig 	BLOCK(12)
20977fd47e5SChristoph Hellwig 
21077fd47e5SChristoph Hellwig 	"       addl $128, %1         ;\n"
21177fd47e5SChristoph Hellwig 	"       addl $128, %2         ;\n"
21277fd47e5SChristoph Hellwig 	"       addl $128, %3         ;\n"
21377fd47e5SChristoph Hellwig 	"       addl $128, %4         ;\n"
21477fd47e5SChristoph Hellwig 	"       addl $128, %5         ;\n"
21577fd47e5SChristoph Hellwig 	"       decl %0               ;\n"
21677fd47e5SChristoph Hellwig 	"       jnz 1b                ;\n"
21777fd47e5SChristoph Hellwig 	: "+r" (lines),
21877fd47e5SChristoph Hellwig 	  "+r" (p1), "+r" (p2), "+r" (p3)
21977fd47e5SChristoph Hellwig 	: "r" (p4), "r" (p5)
22077fd47e5SChristoph Hellwig 	: "memory");
22177fd47e5SChristoph Hellwig 
22277fd47e5SChristoph Hellwig 	/* p4 and p5 were modified, and now the variables are dead.
22377fd47e5SChristoph Hellwig 	   Clobber them just to be sure nobody does something stupid
22477fd47e5SChristoph Hellwig 	   like assuming they have some legal value.  */
22577fd47e5SChristoph Hellwig 	asm("" : "=r" (p4), "=r" (p5));
22677fd47e5SChristoph Hellwig }
22777fd47e5SChristoph Hellwig 
22877fd47e5SChristoph Hellwig #undef LD
22977fd47e5SChristoph Hellwig #undef XO1
23077fd47e5SChristoph Hellwig #undef XO2
23177fd47e5SChristoph Hellwig #undef XO3
23277fd47e5SChristoph Hellwig #undef XO4
23377fd47e5SChristoph Hellwig #undef ST
23477fd47e5SChristoph Hellwig #undef BLOCK
23577fd47e5SChristoph Hellwig 
23677fd47e5SChristoph Hellwig static void
23777fd47e5SChristoph Hellwig xor_p5_mmx_2(unsigned long bytes, unsigned long * __restrict p1,
23877fd47e5SChristoph Hellwig 	     const unsigned long * __restrict p2)
23977fd47e5SChristoph Hellwig {
24077fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 6;
24177fd47e5SChristoph Hellwig 
24277fd47e5SChristoph Hellwig 	asm volatile(
24377fd47e5SChristoph Hellwig 	" .align 32	             ;\n"
24477fd47e5SChristoph Hellwig 	" 1:                         ;\n"
24577fd47e5SChristoph Hellwig 	"       movq   (%1), %%mm0   ;\n"
24677fd47e5SChristoph Hellwig 	"       movq  8(%1), %%mm1   ;\n"
24777fd47e5SChristoph Hellwig 	"       pxor   (%2), %%mm0   ;\n"
24877fd47e5SChristoph Hellwig 	"       movq 16(%1), %%mm2   ;\n"
24977fd47e5SChristoph Hellwig 	"       movq %%mm0,   (%1)   ;\n"
25077fd47e5SChristoph Hellwig 	"       pxor  8(%2), %%mm1   ;\n"
25177fd47e5SChristoph Hellwig 	"       movq 24(%1), %%mm3   ;\n"
25277fd47e5SChristoph Hellwig 	"       movq %%mm1,  8(%1)   ;\n"
25377fd47e5SChristoph Hellwig 	"       pxor 16(%2), %%mm2   ;\n"
25477fd47e5SChristoph Hellwig 	"       movq 32(%1), %%mm4   ;\n"
25577fd47e5SChristoph Hellwig 	"       movq %%mm2, 16(%1)   ;\n"
25677fd47e5SChristoph Hellwig 	"       pxor 24(%2), %%mm3   ;\n"
25777fd47e5SChristoph Hellwig 	"       movq 40(%1), %%mm5   ;\n"
25877fd47e5SChristoph Hellwig 	"       movq %%mm3, 24(%1)   ;\n"
25977fd47e5SChristoph Hellwig 	"       pxor 32(%2), %%mm4   ;\n"
26077fd47e5SChristoph Hellwig 	"       movq 48(%1), %%mm6   ;\n"
26177fd47e5SChristoph Hellwig 	"       movq %%mm4, 32(%1)   ;\n"
26277fd47e5SChristoph Hellwig 	"       pxor 40(%2), %%mm5   ;\n"
26377fd47e5SChristoph Hellwig 	"       movq 56(%1), %%mm7   ;\n"
26477fd47e5SChristoph Hellwig 	"       movq %%mm5, 40(%1)   ;\n"
26577fd47e5SChristoph Hellwig 	"       pxor 48(%2), %%mm6   ;\n"
26677fd47e5SChristoph Hellwig 	"       pxor 56(%2), %%mm7   ;\n"
26777fd47e5SChristoph Hellwig 	"       movq %%mm6, 48(%1)   ;\n"
26877fd47e5SChristoph Hellwig 	"       movq %%mm7, 56(%1)   ;\n"
26977fd47e5SChristoph Hellwig 
27077fd47e5SChristoph Hellwig 	"       addl $64, %1         ;\n"
27177fd47e5SChristoph Hellwig 	"       addl $64, %2         ;\n"
27277fd47e5SChristoph Hellwig 	"       decl %0              ;\n"
27377fd47e5SChristoph Hellwig 	"       jnz 1b               ;\n"
27477fd47e5SChristoph Hellwig 	: "+r" (lines),
27577fd47e5SChristoph Hellwig 	  "+r" (p1), "+r" (p2)
27677fd47e5SChristoph Hellwig 	:
27777fd47e5SChristoph Hellwig 	: "memory");
27877fd47e5SChristoph Hellwig }
27977fd47e5SChristoph Hellwig 
28077fd47e5SChristoph Hellwig static void
28177fd47e5SChristoph Hellwig xor_p5_mmx_3(unsigned long bytes, unsigned long * __restrict p1,
28277fd47e5SChristoph Hellwig 	     const unsigned long * __restrict p2,
28377fd47e5SChristoph Hellwig 	     const unsigned long * __restrict p3)
28477fd47e5SChristoph Hellwig {
28577fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 6;
28677fd47e5SChristoph Hellwig 
28777fd47e5SChristoph Hellwig 	asm volatile(
28877fd47e5SChristoph Hellwig 	" .align 32,0x90             ;\n"
28977fd47e5SChristoph Hellwig 	" 1:                         ;\n"
29077fd47e5SChristoph Hellwig 	"       movq   (%1), %%mm0   ;\n"
29177fd47e5SChristoph Hellwig 	"       movq  8(%1), %%mm1   ;\n"
29277fd47e5SChristoph Hellwig 	"       pxor   (%2), %%mm0   ;\n"
29377fd47e5SChristoph Hellwig 	"       movq 16(%1), %%mm2   ;\n"
29477fd47e5SChristoph Hellwig 	"       pxor  8(%2), %%mm1   ;\n"
29577fd47e5SChristoph Hellwig 	"       pxor   (%3), %%mm0   ;\n"
29677fd47e5SChristoph Hellwig 	"       pxor 16(%2), %%mm2   ;\n"
29777fd47e5SChristoph Hellwig 	"       movq %%mm0,   (%1)   ;\n"
29877fd47e5SChristoph Hellwig 	"       pxor  8(%3), %%mm1   ;\n"
29977fd47e5SChristoph Hellwig 	"       pxor 16(%3), %%mm2   ;\n"
30077fd47e5SChristoph Hellwig 	"       movq 24(%1), %%mm3   ;\n"
30177fd47e5SChristoph Hellwig 	"       movq %%mm1,  8(%1)   ;\n"
30277fd47e5SChristoph Hellwig 	"       movq 32(%1), %%mm4   ;\n"
30377fd47e5SChristoph Hellwig 	"       movq 40(%1), %%mm5   ;\n"
30477fd47e5SChristoph Hellwig 	"       pxor 24(%2), %%mm3   ;\n"
30577fd47e5SChristoph Hellwig 	"       movq %%mm2, 16(%1)   ;\n"
30677fd47e5SChristoph Hellwig 	"       pxor 32(%2), %%mm4   ;\n"
30777fd47e5SChristoph Hellwig 	"       pxor 24(%3), %%mm3   ;\n"
30877fd47e5SChristoph Hellwig 	"       pxor 40(%2), %%mm5   ;\n"
30977fd47e5SChristoph Hellwig 	"       movq %%mm3, 24(%1)   ;\n"
31077fd47e5SChristoph Hellwig 	"       pxor 32(%3), %%mm4   ;\n"
31177fd47e5SChristoph Hellwig 	"       pxor 40(%3), %%mm5   ;\n"
31277fd47e5SChristoph Hellwig 	"       movq 48(%1), %%mm6   ;\n"
31377fd47e5SChristoph Hellwig 	"       movq %%mm4, 32(%1)   ;\n"
31477fd47e5SChristoph Hellwig 	"       movq 56(%1), %%mm7   ;\n"
31577fd47e5SChristoph Hellwig 	"       pxor 48(%2), %%mm6   ;\n"
31677fd47e5SChristoph Hellwig 	"       movq %%mm5, 40(%1)   ;\n"
31777fd47e5SChristoph Hellwig 	"       pxor 56(%2), %%mm7   ;\n"
31877fd47e5SChristoph Hellwig 	"       pxor 48(%3), %%mm6   ;\n"
31977fd47e5SChristoph Hellwig 	"       pxor 56(%3), %%mm7   ;\n"
32077fd47e5SChristoph Hellwig 	"       movq %%mm6, 48(%1)   ;\n"
32177fd47e5SChristoph Hellwig 	"       movq %%mm7, 56(%1)   ;\n"
32277fd47e5SChristoph Hellwig 
32377fd47e5SChristoph Hellwig 	"       addl $64, %1         ;\n"
32477fd47e5SChristoph Hellwig 	"       addl $64, %2         ;\n"
32577fd47e5SChristoph Hellwig 	"       addl $64, %3         ;\n"
32677fd47e5SChristoph Hellwig 	"       decl %0              ;\n"
32777fd47e5SChristoph Hellwig 	"       jnz 1b               ;\n"
32877fd47e5SChristoph Hellwig 	: "+r" (lines),
32977fd47e5SChristoph Hellwig 	  "+r" (p1), "+r" (p2), "+r" (p3)
33077fd47e5SChristoph Hellwig 	:
33177fd47e5SChristoph Hellwig 	: "memory" );
33277fd47e5SChristoph Hellwig }
33377fd47e5SChristoph Hellwig 
33477fd47e5SChristoph Hellwig static void
33577fd47e5SChristoph Hellwig xor_p5_mmx_4(unsigned long bytes, unsigned long * __restrict p1,
33677fd47e5SChristoph Hellwig 	     const unsigned long * __restrict p2,
33777fd47e5SChristoph Hellwig 	     const unsigned long * __restrict p3,
33877fd47e5SChristoph Hellwig 	     const unsigned long * __restrict p4)
33977fd47e5SChristoph Hellwig {
34077fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 6;
34177fd47e5SChristoph Hellwig 
34277fd47e5SChristoph Hellwig 	asm volatile(
34377fd47e5SChristoph Hellwig 	" .align 32,0x90             ;\n"
34477fd47e5SChristoph Hellwig 	" 1:                         ;\n"
34577fd47e5SChristoph Hellwig 	"       movq   (%1), %%mm0   ;\n"
34677fd47e5SChristoph Hellwig 	"       movq  8(%1), %%mm1   ;\n"
34777fd47e5SChristoph Hellwig 	"       pxor   (%2), %%mm0   ;\n"
34877fd47e5SChristoph Hellwig 	"       movq 16(%1), %%mm2   ;\n"
34977fd47e5SChristoph Hellwig 	"       pxor  8(%2), %%mm1   ;\n"
35077fd47e5SChristoph Hellwig 	"       pxor   (%3), %%mm0   ;\n"
35177fd47e5SChristoph Hellwig 	"       pxor 16(%2), %%mm2   ;\n"
35277fd47e5SChristoph Hellwig 	"       pxor  8(%3), %%mm1   ;\n"
35377fd47e5SChristoph Hellwig 	"       pxor   (%4), %%mm0   ;\n"
35477fd47e5SChristoph Hellwig 	"       movq 24(%1), %%mm3   ;\n"
35577fd47e5SChristoph Hellwig 	"       pxor 16(%3), %%mm2   ;\n"
35677fd47e5SChristoph Hellwig 	"       pxor  8(%4), %%mm1   ;\n"
35777fd47e5SChristoph Hellwig 	"       movq %%mm0,   (%1)   ;\n"
35877fd47e5SChristoph Hellwig 	"       movq 32(%1), %%mm4   ;\n"
35977fd47e5SChristoph Hellwig 	"       pxor 24(%2), %%mm3   ;\n"
36077fd47e5SChristoph Hellwig 	"       pxor 16(%4), %%mm2   ;\n"
36177fd47e5SChristoph Hellwig 	"       movq %%mm1,  8(%1)   ;\n"
36277fd47e5SChristoph Hellwig 	"       movq 40(%1), %%mm5   ;\n"
36377fd47e5SChristoph Hellwig 	"       pxor 32(%2), %%mm4   ;\n"
36477fd47e5SChristoph Hellwig 	"       pxor 24(%3), %%mm3   ;\n"
36577fd47e5SChristoph Hellwig 	"       movq %%mm2, 16(%1)   ;\n"
36677fd47e5SChristoph Hellwig 	"       pxor 40(%2), %%mm5   ;\n"
36777fd47e5SChristoph Hellwig 	"       pxor 32(%3), %%mm4   ;\n"
36877fd47e5SChristoph Hellwig 	"       pxor 24(%4), %%mm3   ;\n"
36977fd47e5SChristoph Hellwig 	"       movq %%mm3, 24(%1)   ;\n"
37077fd47e5SChristoph Hellwig 	"       movq 56(%1), %%mm7   ;\n"
37177fd47e5SChristoph Hellwig 	"       movq 48(%1), %%mm6   ;\n"
37277fd47e5SChristoph Hellwig 	"       pxor 40(%3), %%mm5   ;\n"
37377fd47e5SChristoph Hellwig 	"       pxor 32(%4), %%mm4   ;\n"
37477fd47e5SChristoph Hellwig 	"       pxor 48(%2), %%mm6   ;\n"
37577fd47e5SChristoph Hellwig 	"       movq %%mm4, 32(%1)   ;\n"
37677fd47e5SChristoph Hellwig 	"       pxor 56(%2), %%mm7   ;\n"
37777fd47e5SChristoph Hellwig 	"       pxor 40(%4), %%mm5   ;\n"
37877fd47e5SChristoph Hellwig 	"       pxor 48(%3), %%mm6   ;\n"
37977fd47e5SChristoph Hellwig 	"       pxor 56(%3), %%mm7   ;\n"
38077fd47e5SChristoph Hellwig 	"       movq %%mm5, 40(%1)   ;\n"
38177fd47e5SChristoph Hellwig 	"       pxor 48(%4), %%mm6   ;\n"
38277fd47e5SChristoph Hellwig 	"       pxor 56(%4), %%mm7   ;\n"
38377fd47e5SChristoph Hellwig 	"       movq %%mm6, 48(%1)   ;\n"
38477fd47e5SChristoph Hellwig 	"       movq %%mm7, 56(%1)   ;\n"
38577fd47e5SChristoph Hellwig 
38677fd47e5SChristoph Hellwig 	"       addl $64, %1         ;\n"
38777fd47e5SChristoph Hellwig 	"       addl $64, %2         ;\n"
38877fd47e5SChristoph Hellwig 	"       addl $64, %3         ;\n"
38977fd47e5SChristoph Hellwig 	"       addl $64, %4         ;\n"
39077fd47e5SChristoph Hellwig 	"       decl %0              ;\n"
39177fd47e5SChristoph Hellwig 	"       jnz 1b               ;\n"
39277fd47e5SChristoph Hellwig 	: "+r" (lines),
39377fd47e5SChristoph Hellwig 	  "+r" (p1), "+r" (p2), "+r" (p3), "+r" (p4)
39477fd47e5SChristoph Hellwig 	:
39577fd47e5SChristoph Hellwig 	: "memory");
39677fd47e5SChristoph Hellwig }
39777fd47e5SChristoph Hellwig 
39877fd47e5SChristoph Hellwig static void
39977fd47e5SChristoph Hellwig xor_p5_mmx_5(unsigned long bytes, unsigned long * __restrict p1,
40077fd47e5SChristoph Hellwig 	     const unsigned long * __restrict p2,
40177fd47e5SChristoph Hellwig 	     const unsigned long * __restrict p3,
40277fd47e5SChristoph Hellwig 	     const unsigned long * __restrict p4,
40377fd47e5SChristoph Hellwig 	     const unsigned long * __restrict p5)
40477fd47e5SChristoph Hellwig {
40577fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 6;
40677fd47e5SChristoph Hellwig 
40777fd47e5SChristoph Hellwig 	/* Make sure GCC forgets anything it knows about p4 or p5,
40877fd47e5SChristoph Hellwig 	   such that it won't pass to the asm volatile below a
40977fd47e5SChristoph Hellwig 	   register that is shared with any other variable.  That's
41077fd47e5SChristoph Hellwig 	   because we modify p4 and p5 there, but we can't mark them
41177fd47e5SChristoph Hellwig 	   as read/write, otherwise we'd overflow the 10-asm-operands
41277fd47e5SChristoph Hellwig 	   limit of GCC < 3.1.  */
41377fd47e5SChristoph Hellwig 	asm("" : "+r" (p4), "+r" (p5));
41477fd47e5SChristoph Hellwig 
41577fd47e5SChristoph Hellwig 	asm volatile(
41677fd47e5SChristoph Hellwig 	" .align 32,0x90             ;\n"
41777fd47e5SChristoph Hellwig 	" 1:                         ;\n"
41877fd47e5SChristoph Hellwig 	"       movq   (%1), %%mm0   ;\n"
41977fd47e5SChristoph Hellwig 	"       movq  8(%1), %%mm1   ;\n"
42077fd47e5SChristoph Hellwig 	"       pxor   (%2), %%mm0   ;\n"
42177fd47e5SChristoph Hellwig 	"       pxor  8(%2), %%mm1   ;\n"
42277fd47e5SChristoph Hellwig 	"       movq 16(%1), %%mm2   ;\n"
42377fd47e5SChristoph Hellwig 	"       pxor   (%3), %%mm0   ;\n"
42477fd47e5SChristoph Hellwig 	"       pxor  8(%3), %%mm1   ;\n"
42577fd47e5SChristoph Hellwig 	"       pxor 16(%2), %%mm2   ;\n"
42677fd47e5SChristoph Hellwig 	"       pxor   (%4), %%mm0   ;\n"
42777fd47e5SChristoph Hellwig 	"       pxor  8(%4), %%mm1   ;\n"
42877fd47e5SChristoph Hellwig 	"       pxor 16(%3), %%mm2   ;\n"
42977fd47e5SChristoph Hellwig 	"       movq 24(%1), %%mm3   ;\n"
43077fd47e5SChristoph Hellwig 	"       pxor   (%5), %%mm0   ;\n"
43177fd47e5SChristoph Hellwig 	"       pxor  8(%5), %%mm1   ;\n"
43277fd47e5SChristoph Hellwig 	"       movq %%mm0,   (%1)   ;\n"
43377fd47e5SChristoph Hellwig 	"       pxor 16(%4), %%mm2   ;\n"
43477fd47e5SChristoph Hellwig 	"       pxor 24(%2), %%mm3   ;\n"
43577fd47e5SChristoph Hellwig 	"       movq %%mm1,  8(%1)   ;\n"
43677fd47e5SChristoph Hellwig 	"       pxor 16(%5), %%mm2   ;\n"
43777fd47e5SChristoph Hellwig 	"       pxor 24(%3), %%mm3   ;\n"
43877fd47e5SChristoph Hellwig 	"       movq 32(%1), %%mm4   ;\n"
43977fd47e5SChristoph Hellwig 	"       movq %%mm2, 16(%1)   ;\n"
44077fd47e5SChristoph Hellwig 	"       pxor 24(%4), %%mm3   ;\n"
44177fd47e5SChristoph Hellwig 	"       pxor 32(%2), %%mm4   ;\n"
44277fd47e5SChristoph Hellwig 	"       movq 40(%1), %%mm5   ;\n"
44377fd47e5SChristoph Hellwig 	"       pxor 24(%5), %%mm3   ;\n"
44477fd47e5SChristoph Hellwig 	"       pxor 32(%3), %%mm4   ;\n"
44577fd47e5SChristoph Hellwig 	"       pxor 40(%2), %%mm5   ;\n"
44677fd47e5SChristoph Hellwig 	"       movq %%mm3, 24(%1)   ;\n"
44777fd47e5SChristoph Hellwig 	"       pxor 32(%4), %%mm4   ;\n"
44877fd47e5SChristoph Hellwig 	"       pxor 40(%3), %%mm5   ;\n"
44977fd47e5SChristoph Hellwig 	"       movq 48(%1), %%mm6   ;\n"
45077fd47e5SChristoph Hellwig 	"       movq 56(%1), %%mm7   ;\n"
45177fd47e5SChristoph Hellwig 	"       pxor 32(%5), %%mm4   ;\n"
45277fd47e5SChristoph Hellwig 	"       pxor 40(%4), %%mm5   ;\n"
45377fd47e5SChristoph Hellwig 	"       pxor 48(%2), %%mm6   ;\n"
45477fd47e5SChristoph Hellwig 	"       pxor 56(%2), %%mm7   ;\n"
45577fd47e5SChristoph Hellwig 	"       movq %%mm4, 32(%1)   ;\n"
45677fd47e5SChristoph Hellwig 	"       pxor 48(%3), %%mm6   ;\n"
45777fd47e5SChristoph Hellwig 	"       pxor 56(%3), %%mm7   ;\n"
45877fd47e5SChristoph Hellwig 	"       pxor 40(%5), %%mm5   ;\n"
45977fd47e5SChristoph Hellwig 	"       pxor 48(%4), %%mm6   ;\n"
46077fd47e5SChristoph Hellwig 	"       pxor 56(%4), %%mm7   ;\n"
46177fd47e5SChristoph Hellwig 	"       movq %%mm5, 40(%1)   ;\n"
46277fd47e5SChristoph Hellwig 	"       pxor 48(%5), %%mm6   ;\n"
46377fd47e5SChristoph Hellwig 	"       pxor 56(%5), %%mm7   ;\n"
46477fd47e5SChristoph Hellwig 	"       movq %%mm6, 48(%1)   ;\n"
46577fd47e5SChristoph Hellwig 	"       movq %%mm7, 56(%1)   ;\n"
46677fd47e5SChristoph Hellwig 
46777fd47e5SChristoph Hellwig 	"       addl $64, %1         ;\n"
46877fd47e5SChristoph Hellwig 	"       addl $64, %2         ;\n"
46977fd47e5SChristoph Hellwig 	"       addl $64, %3         ;\n"
47077fd47e5SChristoph Hellwig 	"       addl $64, %4         ;\n"
47177fd47e5SChristoph Hellwig 	"       addl $64, %5         ;\n"
47277fd47e5SChristoph Hellwig 	"       decl %0              ;\n"
47377fd47e5SChristoph Hellwig 	"       jnz 1b               ;\n"
47477fd47e5SChristoph Hellwig 	: "+r" (lines),
47577fd47e5SChristoph Hellwig 	  "+r" (p1), "+r" (p2), "+r" (p3)
47677fd47e5SChristoph Hellwig 	: "r" (p4), "r" (p5)
47777fd47e5SChristoph Hellwig 	: "memory");
47877fd47e5SChristoph Hellwig 
47977fd47e5SChristoph Hellwig 	/* p4 and p5 were modified, and now the variables are dead.
48077fd47e5SChristoph Hellwig 	   Clobber them just to be sure nobody does something stupid
48177fd47e5SChristoph Hellwig 	   like assuming they have some legal value.  */
48277fd47e5SChristoph Hellwig 	asm("" : "=r" (p4), "=r" (p5));
483*80dcf0a7SChristoph Hellwig }
48477fd47e5SChristoph Hellwig 
485*80dcf0a7SChristoph Hellwig DO_XOR_BLOCKS(pII_mmx_inner, xor_pII_mmx_2, xor_pII_mmx_3, xor_pII_mmx_4,
486*80dcf0a7SChristoph Hellwig 		xor_pII_mmx_5);
487*80dcf0a7SChristoph Hellwig 
488*80dcf0a7SChristoph Hellwig static void xor_gen_pII_mmx(void *dest, void **srcs, unsigned int src_cnt,
489*80dcf0a7SChristoph Hellwig 		unsigned int bytes)
490*80dcf0a7SChristoph Hellwig {
491*80dcf0a7SChristoph Hellwig 	kernel_fpu_begin();
492*80dcf0a7SChristoph Hellwig 	xor_gen_pII_mmx_inner(dest, srcs, src_cnt, bytes);
49377fd47e5SChristoph Hellwig 	kernel_fpu_end();
49477fd47e5SChristoph Hellwig }
49577fd47e5SChristoph Hellwig 
49677fd47e5SChristoph Hellwig struct xor_block_template xor_block_pII_mmx = {
49777fd47e5SChristoph Hellwig 	.name		= "pII_mmx",
498*80dcf0a7SChristoph Hellwig 	.xor_gen	= xor_gen_pII_mmx,
49977fd47e5SChristoph Hellwig };
50077fd47e5SChristoph Hellwig 
501*80dcf0a7SChristoph Hellwig DO_XOR_BLOCKS(p5_mmx_inner, xor_p5_mmx_2, xor_p5_mmx_3, xor_p5_mmx_4,
502*80dcf0a7SChristoph Hellwig 		xor_p5_mmx_5);
503*80dcf0a7SChristoph Hellwig 
504*80dcf0a7SChristoph Hellwig static void xor_gen_p5_mmx(void *dest, void **srcs, unsigned int src_cnt,
505*80dcf0a7SChristoph Hellwig 		unsigned int bytes)
506*80dcf0a7SChristoph Hellwig {
507*80dcf0a7SChristoph Hellwig 	kernel_fpu_begin();
508*80dcf0a7SChristoph Hellwig 	xor_gen_p5_mmx_inner(dest, srcs, src_cnt, bytes);
509*80dcf0a7SChristoph Hellwig 	kernel_fpu_end();
510*80dcf0a7SChristoph Hellwig }
511*80dcf0a7SChristoph Hellwig 
51277fd47e5SChristoph Hellwig struct xor_block_template xor_block_p5_mmx = {
51377fd47e5SChristoph Hellwig 	.name		= "p5_mmx",
514*80dcf0a7SChristoph Hellwig 	.xor_gen	= xor_gen_p5_mmx,
51577fd47e5SChristoph Hellwig };
516