xref: /linux/lib/raid/xor/x86/xor-sse.c (revision 440d6635b20037bc9ad46b20817d7b61cef0fc1b)
177fd47e5SChristoph Hellwig // SPDX-License-Identifier: GPL-2.0-or-later
277fd47e5SChristoph Hellwig /*
377fd47e5SChristoph Hellwig  * Optimized XOR parity functions for SSE.
477fd47e5SChristoph Hellwig  *
577fd47e5SChristoph Hellwig  * Cache avoiding checksumming functions utilizing KNI instructions
677fd47e5SChristoph Hellwig  * Copyright (C) 1999 Zach Brown (with obvious credit due Ingo)
777fd47e5SChristoph Hellwig  *
877fd47e5SChristoph Hellwig  * Based on
977fd47e5SChristoph Hellwig  * High-speed RAID5 checksumming functions utilizing SSE instructions.
1077fd47e5SChristoph Hellwig  * Copyright (C) 1998 Ingo Molnar.
1177fd47e5SChristoph Hellwig  *
1277fd47e5SChristoph Hellwig  * x86-64 changes / gcc fixes from Andi Kleen.
1377fd47e5SChristoph Hellwig  * Copyright 2002 Andi Kleen, SuSE Labs.
1477fd47e5SChristoph Hellwig  */
1577fd47e5SChristoph Hellwig #include <asm/fpu/api.h>
16e20043b4SChristoph Hellwig #include "xor_impl.h"
17e20043b4SChristoph Hellwig #include "xor_arch.h"
1877fd47e5SChristoph Hellwig 
1977fd47e5SChristoph Hellwig #ifdef CONFIG_X86_32
2077fd47e5SChristoph Hellwig /* reduce register pressure */
2177fd47e5SChristoph Hellwig # define XOR_CONSTANT_CONSTRAINT "i"
2277fd47e5SChristoph Hellwig #else
2377fd47e5SChristoph Hellwig # define XOR_CONSTANT_CONSTRAINT "re"
2477fd47e5SChristoph Hellwig #endif
2577fd47e5SChristoph Hellwig 
2677fd47e5SChristoph Hellwig #define OFFS(x)		"16*("#x")"
2777fd47e5SChristoph Hellwig #define PF_OFFS(x)	"256+16*("#x")"
2877fd47e5SChristoph Hellwig #define PF0(x)		"	prefetchnta "PF_OFFS(x)"(%[p1])		;\n"
2977fd47e5SChristoph Hellwig #define LD(x, y)	"	movaps "OFFS(x)"(%[p1]), %%xmm"#y"	;\n"
3077fd47e5SChristoph Hellwig #define ST(x, y)	"	movaps %%xmm"#y", "OFFS(x)"(%[p1])	;\n"
3177fd47e5SChristoph Hellwig #define PF1(x)		"	prefetchnta "PF_OFFS(x)"(%[p2])		;\n"
3277fd47e5SChristoph Hellwig #define PF2(x)		"	prefetchnta "PF_OFFS(x)"(%[p3])		;\n"
3377fd47e5SChristoph Hellwig #define PF3(x)		"	prefetchnta "PF_OFFS(x)"(%[p4])		;\n"
3477fd47e5SChristoph Hellwig #define PF4(x)		"	prefetchnta "PF_OFFS(x)"(%[p5])		;\n"
3577fd47e5SChristoph Hellwig #define XO1(x, y)	"	xorps "OFFS(x)"(%[p2]), %%xmm"#y"	;\n"
3677fd47e5SChristoph Hellwig #define XO2(x, y)	"	xorps "OFFS(x)"(%[p3]), %%xmm"#y"	;\n"
3777fd47e5SChristoph Hellwig #define XO3(x, y)	"	xorps "OFFS(x)"(%[p4]), %%xmm"#y"	;\n"
3877fd47e5SChristoph Hellwig #define XO4(x, y)	"	xorps "OFFS(x)"(%[p5]), %%xmm"#y"	;\n"
3977fd47e5SChristoph Hellwig #define NOP(x)
4077fd47e5SChristoph Hellwig 
4177fd47e5SChristoph Hellwig #define BLK64(pf, op, i)				\
4277fd47e5SChristoph Hellwig 		pf(i)					\
4377fd47e5SChristoph Hellwig 		op(i, 0)				\
4477fd47e5SChristoph Hellwig 			op(i + 1, 1)			\
4577fd47e5SChristoph Hellwig 				op(i + 2, 2)		\
4677fd47e5SChristoph Hellwig 					op(i + 3, 3)
4777fd47e5SChristoph Hellwig 
4877fd47e5SChristoph Hellwig static void
4977fd47e5SChristoph Hellwig xor_sse_2(unsigned long bytes, unsigned long * __restrict p1,
5077fd47e5SChristoph Hellwig 	  const unsigned long * __restrict p2)
5177fd47e5SChristoph Hellwig {
5277fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 8;
5377fd47e5SChristoph Hellwig 
5477fd47e5SChristoph Hellwig 	asm volatile(
5577fd47e5SChristoph Hellwig #undef BLOCK
5677fd47e5SChristoph Hellwig #define BLOCK(i)					\
5777fd47e5SChristoph Hellwig 		LD(i, 0)				\
5877fd47e5SChristoph Hellwig 			LD(i + 1, 1)			\
5977fd47e5SChristoph Hellwig 		PF1(i)					\
6077fd47e5SChristoph Hellwig 				PF1(i + 2)		\
6177fd47e5SChristoph Hellwig 				LD(i + 2, 2)		\
6277fd47e5SChristoph Hellwig 					LD(i + 3, 3)	\
6377fd47e5SChristoph Hellwig 		PF0(i + 4)				\
6477fd47e5SChristoph Hellwig 				PF0(i + 6)		\
6577fd47e5SChristoph Hellwig 		XO1(i, 0)				\
6677fd47e5SChristoph Hellwig 			XO1(i + 1, 1)			\
6777fd47e5SChristoph Hellwig 				XO1(i + 2, 2)		\
6877fd47e5SChristoph Hellwig 					XO1(i + 3, 3)	\
6977fd47e5SChristoph Hellwig 		ST(i, 0)				\
7077fd47e5SChristoph Hellwig 			ST(i + 1, 1)			\
7177fd47e5SChristoph Hellwig 				ST(i + 2, 2)		\
7277fd47e5SChristoph Hellwig 					ST(i + 3, 3)	\
7377fd47e5SChristoph Hellwig 
7477fd47e5SChristoph Hellwig 
7577fd47e5SChristoph Hellwig 		PF0(0)
7677fd47e5SChristoph Hellwig 				PF0(2)
7777fd47e5SChristoph Hellwig 
7877fd47e5SChristoph Hellwig 	" .align 32			;\n"
7977fd47e5SChristoph Hellwig 	" 1:                            ;\n"
8077fd47e5SChristoph Hellwig 
8177fd47e5SChristoph Hellwig 		BLOCK(0)
8277fd47e5SChristoph Hellwig 		BLOCK(4)
8377fd47e5SChristoph Hellwig 		BLOCK(8)
8477fd47e5SChristoph Hellwig 		BLOCK(12)
8577fd47e5SChristoph Hellwig 
8677fd47e5SChristoph Hellwig 	"       add %[inc], %[p1]       ;\n"
8777fd47e5SChristoph Hellwig 	"       add %[inc], %[p2]       ;\n"
8877fd47e5SChristoph Hellwig 	"       dec %[cnt]              ;\n"
8977fd47e5SChristoph Hellwig 	"       jnz 1b                  ;\n"
9077fd47e5SChristoph Hellwig 	: [cnt] "+r" (lines),
9177fd47e5SChristoph Hellwig 	  [p1] "+r" (p1), [p2] "+r" (p2)
9277fd47e5SChristoph Hellwig 	: [inc] XOR_CONSTANT_CONSTRAINT (256UL)
9377fd47e5SChristoph Hellwig 	: "memory");
9477fd47e5SChristoph Hellwig }
9577fd47e5SChristoph Hellwig 
9677fd47e5SChristoph Hellwig static void
9777fd47e5SChristoph Hellwig xor_sse_2_pf64(unsigned long bytes, unsigned long * __restrict p1,
9877fd47e5SChristoph Hellwig 	       const unsigned long * __restrict p2)
9977fd47e5SChristoph Hellwig {
10077fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 8;
10177fd47e5SChristoph Hellwig 
10277fd47e5SChristoph Hellwig 	asm volatile(
10377fd47e5SChristoph Hellwig #undef BLOCK
10477fd47e5SChristoph Hellwig #define BLOCK(i)			\
10577fd47e5SChristoph Hellwig 		BLK64(PF0, LD, i)	\
10677fd47e5SChristoph Hellwig 		BLK64(PF1, XO1, i)	\
10777fd47e5SChristoph Hellwig 		BLK64(NOP, ST, i)	\
10877fd47e5SChristoph Hellwig 
10977fd47e5SChristoph Hellwig 	" .align 32			;\n"
11077fd47e5SChristoph Hellwig 	" 1:                            ;\n"
11177fd47e5SChristoph Hellwig 
11277fd47e5SChristoph Hellwig 		BLOCK(0)
11377fd47e5SChristoph Hellwig 		BLOCK(4)
11477fd47e5SChristoph Hellwig 		BLOCK(8)
11577fd47e5SChristoph Hellwig 		BLOCK(12)
11677fd47e5SChristoph Hellwig 
11777fd47e5SChristoph Hellwig 	"       add %[inc], %[p1]       ;\n"
11877fd47e5SChristoph Hellwig 	"       add %[inc], %[p2]       ;\n"
11977fd47e5SChristoph Hellwig 	"       dec %[cnt]              ;\n"
12077fd47e5SChristoph Hellwig 	"       jnz 1b                  ;\n"
12177fd47e5SChristoph Hellwig 	: [cnt] "+r" (lines),
12277fd47e5SChristoph Hellwig 	  [p1] "+r" (p1), [p2] "+r" (p2)
12377fd47e5SChristoph Hellwig 	: [inc] XOR_CONSTANT_CONSTRAINT (256UL)
12477fd47e5SChristoph Hellwig 	: "memory");
12577fd47e5SChristoph Hellwig }
12677fd47e5SChristoph Hellwig 
12777fd47e5SChristoph Hellwig static void
12877fd47e5SChristoph Hellwig xor_sse_3(unsigned long bytes, unsigned long * __restrict p1,
12977fd47e5SChristoph Hellwig 	  const unsigned long * __restrict p2,
13077fd47e5SChristoph Hellwig 	  const unsigned long * __restrict p3)
13177fd47e5SChristoph Hellwig {
13277fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 8;
13377fd47e5SChristoph Hellwig 
13477fd47e5SChristoph Hellwig 	asm volatile(
13577fd47e5SChristoph Hellwig #undef BLOCK
13677fd47e5SChristoph Hellwig #define BLOCK(i) \
13777fd47e5SChristoph Hellwig 		PF1(i)					\
13877fd47e5SChristoph Hellwig 				PF1(i + 2)		\
13977fd47e5SChristoph Hellwig 		LD(i, 0)				\
14077fd47e5SChristoph Hellwig 			LD(i + 1, 1)			\
14177fd47e5SChristoph Hellwig 				LD(i + 2, 2)		\
14277fd47e5SChristoph Hellwig 					LD(i + 3, 3)	\
14377fd47e5SChristoph Hellwig 		PF2(i)					\
14477fd47e5SChristoph Hellwig 				PF2(i + 2)		\
14577fd47e5SChristoph Hellwig 		PF0(i + 4)				\
14677fd47e5SChristoph Hellwig 				PF0(i + 6)		\
14777fd47e5SChristoph Hellwig 		XO1(i, 0)				\
14877fd47e5SChristoph Hellwig 			XO1(i + 1, 1)			\
14977fd47e5SChristoph Hellwig 				XO1(i + 2, 2)		\
15077fd47e5SChristoph Hellwig 					XO1(i + 3, 3)	\
15177fd47e5SChristoph Hellwig 		XO2(i, 0)				\
15277fd47e5SChristoph Hellwig 			XO2(i + 1, 1)			\
15377fd47e5SChristoph Hellwig 				XO2(i + 2, 2)		\
15477fd47e5SChristoph Hellwig 					XO2(i + 3, 3)	\
15577fd47e5SChristoph Hellwig 		ST(i, 0)				\
15677fd47e5SChristoph Hellwig 			ST(i + 1, 1)			\
15777fd47e5SChristoph Hellwig 				ST(i + 2, 2)		\
15877fd47e5SChristoph Hellwig 					ST(i + 3, 3)	\
15977fd47e5SChristoph Hellwig 
16077fd47e5SChristoph Hellwig 
16177fd47e5SChristoph Hellwig 		PF0(0)
16277fd47e5SChristoph Hellwig 				PF0(2)
16377fd47e5SChristoph Hellwig 
16477fd47e5SChristoph Hellwig 	" .align 32			;\n"
16577fd47e5SChristoph Hellwig 	" 1:                            ;\n"
16677fd47e5SChristoph Hellwig 
16777fd47e5SChristoph Hellwig 		BLOCK(0)
16877fd47e5SChristoph Hellwig 		BLOCK(4)
16977fd47e5SChristoph Hellwig 		BLOCK(8)
17077fd47e5SChristoph Hellwig 		BLOCK(12)
17177fd47e5SChristoph Hellwig 
17277fd47e5SChristoph Hellwig 	"       add %[inc], %[p1]       ;\n"
17377fd47e5SChristoph Hellwig 	"       add %[inc], %[p2]       ;\n"
17477fd47e5SChristoph Hellwig 	"       add %[inc], %[p3]       ;\n"
17577fd47e5SChristoph Hellwig 	"       dec %[cnt]              ;\n"
17677fd47e5SChristoph Hellwig 	"       jnz 1b                  ;\n"
17777fd47e5SChristoph Hellwig 	: [cnt] "+r" (lines),
17877fd47e5SChristoph Hellwig 	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3)
17977fd47e5SChristoph Hellwig 	: [inc] XOR_CONSTANT_CONSTRAINT (256UL)
18077fd47e5SChristoph Hellwig 	: "memory");
18177fd47e5SChristoph Hellwig }
18277fd47e5SChristoph Hellwig 
18377fd47e5SChristoph Hellwig static void
18477fd47e5SChristoph Hellwig xor_sse_3_pf64(unsigned long bytes, unsigned long * __restrict p1,
18577fd47e5SChristoph Hellwig 	       const unsigned long * __restrict p2,
18677fd47e5SChristoph Hellwig 	       const unsigned long * __restrict p3)
18777fd47e5SChristoph Hellwig {
18877fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 8;
18977fd47e5SChristoph Hellwig 
19077fd47e5SChristoph Hellwig 	asm volatile(
19177fd47e5SChristoph Hellwig #undef BLOCK
19277fd47e5SChristoph Hellwig #define BLOCK(i)			\
19377fd47e5SChristoph Hellwig 		BLK64(PF0, LD, i)	\
19477fd47e5SChristoph Hellwig 		BLK64(PF1, XO1, i)	\
19577fd47e5SChristoph Hellwig 		BLK64(PF2, XO2, i)	\
19677fd47e5SChristoph Hellwig 		BLK64(NOP, ST, i)	\
19777fd47e5SChristoph Hellwig 
19877fd47e5SChristoph Hellwig 	" .align 32			;\n"
19977fd47e5SChristoph Hellwig 	" 1:                            ;\n"
20077fd47e5SChristoph Hellwig 
20177fd47e5SChristoph Hellwig 		BLOCK(0)
20277fd47e5SChristoph Hellwig 		BLOCK(4)
20377fd47e5SChristoph Hellwig 		BLOCK(8)
20477fd47e5SChristoph Hellwig 		BLOCK(12)
20577fd47e5SChristoph Hellwig 
20677fd47e5SChristoph Hellwig 	"       add %[inc], %[p1]       ;\n"
20777fd47e5SChristoph Hellwig 	"       add %[inc], %[p2]       ;\n"
20877fd47e5SChristoph Hellwig 	"       add %[inc], %[p3]       ;\n"
20977fd47e5SChristoph Hellwig 	"       dec %[cnt]              ;\n"
21077fd47e5SChristoph Hellwig 	"       jnz 1b                  ;\n"
21177fd47e5SChristoph Hellwig 	: [cnt] "+r" (lines),
21277fd47e5SChristoph Hellwig 	  [p1] "+r" (p1), [p2] "+r" (p2), [p3] "+r" (p3)
21377fd47e5SChristoph Hellwig 	: [inc] XOR_CONSTANT_CONSTRAINT (256UL)
21477fd47e5SChristoph Hellwig 	: "memory");
21577fd47e5SChristoph Hellwig }
21677fd47e5SChristoph Hellwig 
21777fd47e5SChristoph Hellwig static void
21877fd47e5SChristoph Hellwig xor_sse_4(unsigned long bytes, unsigned long * __restrict p1,
21977fd47e5SChristoph Hellwig 	  const unsigned long * __restrict p2,
22077fd47e5SChristoph Hellwig 	  const unsigned long * __restrict p3,
22177fd47e5SChristoph Hellwig 	  const unsigned long * __restrict p4)
22277fd47e5SChristoph Hellwig {
22377fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 8;
22477fd47e5SChristoph Hellwig 
22577fd47e5SChristoph Hellwig 	asm volatile(
22677fd47e5SChristoph Hellwig #undef BLOCK
22777fd47e5SChristoph Hellwig #define BLOCK(i) \
22877fd47e5SChristoph Hellwig 		PF1(i)					\
22977fd47e5SChristoph Hellwig 				PF1(i + 2)		\
23077fd47e5SChristoph Hellwig 		LD(i, 0)				\
23177fd47e5SChristoph Hellwig 			LD(i + 1, 1)			\
23277fd47e5SChristoph Hellwig 				LD(i + 2, 2)		\
23377fd47e5SChristoph Hellwig 					LD(i + 3, 3)	\
23477fd47e5SChristoph Hellwig 		PF2(i)					\
23577fd47e5SChristoph Hellwig 				PF2(i + 2)		\
23677fd47e5SChristoph Hellwig 		XO1(i, 0)				\
23777fd47e5SChristoph Hellwig 			XO1(i + 1, 1)			\
23877fd47e5SChristoph Hellwig 				XO1(i + 2, 2)		\
23977fd47e5SChristoph Hellwig 					XO1(i + 3, 3)	\
24077fd47e5SChristoph Hellwig 		PF3(i)					\
24177fd47e5SChristoph Hellwig 				PF3(i + 2)		\
24277fd47e5SChristoph Hellwig 		PF0(i + 4)				\
24377fd47e5SChristoph Hellwig 				PF0(i + 6)		\
24477fd47e5SChristoph Hellwig 		XO2(i, 0)				\
24577fd47e5SChristoph Hellwig 			XO2(i + 1, 1)			\
24677fd47e5SChristoph Hellwig 				XO2(i + 2, 2)		\
24777fd47e5SChristoph Hellwig 					XO2(i + 3, 3)	\
24877fd47e5SChristoph Hellwig 		XO3(i, 0)				\
24977fd47e5SChristoph Hellwig 			XO3(i + 1, 1)			\
25077fd47e5SChristoph Hellwig 				XO3(i + 2, 2)		\
25177fd47e5SChristoph Hellwig 					XO3(i + 3, 3)	\
25277fd47e5SChristoph Hellwig 		ST(i, 0)				\
25377fd47e5SChristoph Hellwig 			ST(i + 1, 1)			\
25477fd47e5SChristoph Hellwig 				ST(i + 2, 2)		\
25577fd47e5SChristoph Hellwig 					ST(i + 3, 3)	\
25677fd47e5SChristoph Hellwig 
25777fd47e5SChristoph Hellwig 
25877fd47e5SChristoph Hellwig 		PF0(0)
25977fd47e5SChristoph Hellwig 				PF0(2)
26077fd47e5SChristoph Hellwig 
26177fd47e5SChristoph Hellwig 	" .align 32			;\n"
26277fd47e5SChristoph Hellwig 	" 1:                            ;\n"
26377fd47e5SChristoph Hellwig 
26477fd47e5SChristoph Hellwig 		BLOCK(0)
26577fd47e5SChristoph Hellwig 		BLOCK(4)
26677fd47e5SChristoph Hellwig 		BLOCK(8)
26777fd47e5SChristoph Hellwig 		BLOCK(12)
26877fd47e5SChristoph Hellwig 
26977fd47e5SChristoph Hellwig 	"       add %[inc], %[p1]       ;\n"
27077fd47e5SChristoph Hellwig 	"       add %[inc], %[p2]       ;\n"
27177fd47e5SChristoph Hellwig 	"       add %[inc], %[p3]       ;\n"
27277fd47e5SChristoph Hellwig 	"       add %[inc], %[p4]       ;\n"
27377fd47e5SChristoph Hellwig 	"       dec %[cnt]              ;\n"
27477fd47e5SChristoph Hellwig 	"       jnz 1b                  ;\n"
27577fd47e5SChristoph Hellwig 	: [cnt] "+r" (lines), [p1] "+r" (p1),
27677fd47e5SChristoph Hellwig 	  [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4)
27777fd47e5SChristoph Hellwig 	: [inc] XOR_CONSTANT_CONSTRAINT (256UL)
27877fd47e5SChristoph Hellwig 	: "memory");
27977fd47e5SChristoph Hellwig }
28077fd47e5SChristoph Hellwig 
28177fd47e5SChristoph Hellwig static void
28277fd47e5SChristoph Hellwig xor_sse_4_pf64(unsigned long bytes, unsigned long * __restrict p1,
28377fd47e5SChristoph Hellwig 	       const unsigned long * __restrict p2,
28477fd47e5SChristoph Hellwig 	       const unsigned long * __restrict p3,
28577fd47e5SChristoph Hellwig 	       const unsigned long * __restrict p4)
28677fd47e5SChristoph Hellwig {
28777fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 8;
28877fd47e5SChristoph Hellwig 
28977fd47e5SChristoph Hellwig 	asm volatile(
29077fd47e5SChristoph Hellwig #undef BLOCK
29177fd47e5SChristoph Hellwig #define BLOCK(i)			\
29277fd47e5SChristoph Hellwig 		BLK64(PF0, LD, i)	\
29377fd47e5SChristoph Hellwig 		BLK64(PF1, XO1, i)	\
29477fd47e5SChristoph Hellwig 		BLK64(PF2, XO2, i)	\
29577fd47e5SChristoph Hellwig 		BLK64(PF3, XO3, i)	\
29677fd47e5SChristoph Hellwig 		BLK64(NOP, ST, i)	\
29777fd47e5SChristoph Hellwig 
29877fd47e5SChristoph Hellwig 	" .align 32			;\n"
29977fd47e5SChristoph Hellwig 	" 1:                            ;\n"
30077fd47e5SChristoph Hellwig 
30177fd47e5SChristoph Hellwig 		BLOCK(0)
30277fd47e5SChristoph Hellwig 		BLOCK(4)
30377fd47e5SChristoph Hellwig 		BLOCK(8)
30477fd47e5SChristoph Hellwig 		BLOCK(12)
30577fd47e5SChristoph Hellwig 
30677fd47e5SChristoph Hellwig 	"       add %[inc], %[p1]       ;\n"
30777fd47e5SChristoph Hellwig 	"       add %[inc], %[p2]       ;\n"
30877fd47e5SChristoph Hellwig 	"       add %[inc], %[p3]       ;\n"
30977fd47e5SChristoph Hellwig 	"       add %[inc], %[p4]       ;\n"
31077fd47e5SChristoph Hellwig 	"       dec %[cnt]              ;\n"
31177fd47e5SChristoph Hellwig 	"       jnz 1b                  ;\n"
31277fd47e5SChristoph Hellwig 	: [cnt] "+r" (lines), [p1] "+r" (p1),
31377fd47e5SChristoph Hellwig 	  [p2] "+r" (p2), [p3] "+r" (p3), [p4] "+r" (p4)
31477fd47e5SChristoph Hellwig 	: [inc] XOR_CONSTANT_CONSTRAINT (256UL)
31577fd47e5SChristoph Hellwig 	: "memory");
31677fd47e5SChristoph Hellwig }
31777fd47e5SChristoph Hellwig 
31877fd47e5SChristoph Hellwig static void
31977fd47e5SChristoph Hellwig xor_sse_5(unsigned long bytes, unsigned long * __restrict p1,
32077fd47e5SChristoph Hellwig 	  const unsigned long * __restrict p2,
32177fd47e5SChristoph Hellwig 	  const unsigned long * __restrict p3,
32277fd47e5SChristoph Hellwig 	  const unsigned long * __restrict p4,
32377fd47e5SChristoph Hellwig 	  const unsigned long * __restrict p5)
32477fd47e5SChristoph Hellwig {
32577fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 8;
32677fd47e5SChristoph Hellwig 
32777fd47e5SChristoph Hellwig 	asm volatile(
32877fd47e5SChristoph Hellwig #undef BLOCK
32977fd47e5SChristoph Hellwig #define BLOCK(i) \
33077fd47e5SChristoph Hellwig 		PF1(i)					\
33177fd47e5SChristoph Hellwig 				PF1(i + 2)		\
33277fd47e5SChristoph Hellwig 		LD(i, 0)				\
33377fd47e5SChristoph Hellwig 			LD(i + 1, 1)			\
33477fd47e5SChristoph Hellwig 				LD(i + 2, 2)		\
33577fd47e5SChristoph Hellwig 					LD(i + 3, 3)	\
33677fd47e5SChristoph Hellwig 		PF2(i)					\
33777fd47e5SChristoph Hellwig 				PF2(i + 2)		\
33877fd47e5SChristoph Hellwig 		XO1(i, 0)				\
33977fd47e5SChristoph Hellwig 			XO1(i + 1, 1)			\
34077fd47e5SChristoph Hellwig 				XO1(i + 2, 2)		\
34177fd47e5SChristoph Hellwig 					XO1(i + 3, 3)	\
34277fd47e5SChristoph Hellwig 		PF3(i)					\
34377fd47e5SChristoph Hellwig 				PF3(i + 2)		\
34477fd47e5SChristoph Hellwig 		XO2(i, 0)				\
34577fd47e5SChristoph Hellwig 			XO2(i + 1, 1)			\
34677fd47e5SChristoph Hellwig 				XO2(i + 2, 2)		\
34777fd47e5SChristoph Hellwig 					XO2(i + 3, 3)	\
34877fd47e5SChristoph Hellwig 		PF4(i)					\
34977fd47e5SChristoph Hellwig 				PF4(i + 2)		\
35077fd47e5SChristoph Hellwig 		PF0(i + 4)				\
35177fd47e5SChristoph Hellwig 				PF0(i + 6)		\
35277fd47e5SChristoph Hellwig 		XO3(i, 0)				\
35377fd47e5SChristoph Hellwig 			XO3(i + 1, 1)			\
35477fd47e5SChristoph Hellwig 				XO3(i + 2, 2)		\
35577fd47e5SChristoph Hellwig 					XO3(i + 3, 3)	\
35677fd47e5SChristoph Hellwig 		XO4(i, 0)				\
35777fd47e5SChristoph Hellwig 			XO4(i + 1, 1)			\
35877fd47e5SChristoph Hellwig 				XO4(i + 2, 2)		\
35977fd47e5SChristoph Hellwig 					XO4(i + 3, 3)	\
36077fd47e5SChristoph Hellwig 		ST(i, 0)				\
36177fd47e5SChristoph Hellwig 			ST(i + 1, 1)			\
36277fd47e5SChristoph Hellwig 				ST(i + 2, 2)		\
36377fd47e5SChristoph Hellwig 					ST(i + 3, 3)	\
36477fd47e5SChristoph Hellwig 
36577fd47e5SChristoph Hellwig 
36677fd47e5SChristoph Hellwig 		PF0(0)
36777fd47e5SChristoph Hellwig 				PF0(2)
36877fd47e5SChristoph Hellwig 
36977fd47e5SChristoph Hellwig 	" .align 32			;\n"
37077fd47e5SChristoph Hellwig 	" 1:                            ;\n"
37177fd47e5SChristoph Hellwig 
37277fd47e5SChristoph Hellwig 		BLOCK(0)
37377fd47e5SChristoph Hellwig 		BLOCK(4)
37477fd47e5SChristoph Hellwig 		BLOCK(8)
37577fd47e5SChristoph Hellwig 		BLOCK(12)
37677fd47e5SChristoph Hellwig 
37777fd47e5SChristoph Hellwig 	"       add %[inc], %[p1]       ;\n"
37877fd47e5SChristoph Hellwig 	"       add %[inc], %[p2]       ;\n"
37977fd47e5SChristoph Hellwig 	"       add %[inc], %[p3]       ;\n"
38077fd47e5SChristoph Hellwig 	"       add %[inc], %[p4]       ;\n"
38177fd47e5SChristoph Hellwig 	"       add %[inc], %[p5]       ;\n"
38277fd47e5SChristoph Hellwig 	"       dec %[cnt]              ;\n"
38377fd47e5SChristoph Hellwig 	"       jnz 1b                  ;\n"
38477fd47e5SChristoph Hellwig 	: [cnt] "+r" (lines), [p1] "+r" (p1), [p2] "+r" (p2),
38577fd47e5SChristoph Hellwig 	  [p3] "+r" (p3), [p4] "+r" (p4), [p5] "+r" (p5)
38677fd47e5SChristoph Hellwig 	: [inc] XOR_CONSTANT_CONSTRAINT (256UL)
38777fd47e5SChristoph Hellwig 	: "memory");
38877fd47e5SChristoph Hellwig }
38977fd47e5SChristoph Hellwig 
39077fd47e5SChristoph Hellwig static void
39177fd47e5SChristoph Hellwig xor_sse_5_pf64(unsigned long bytes, unsigned long * __restrict p1,
39277fd47e5SChristoph Hellwig 	       const unsigned long * __restrict p2,
39377fd47e5SChristoph Hellwig 	       const unsigned long * __restrict p3,
39477fd47e5SChristoph Hellwig 	       const unsigned long * __restrict p4,
39577fd47e5SChristoph Hellwig 	       const unsigned long * __restrict p5)
39677fd47e5SChristoph Hellwig {
39777fd47e5SChristoph Hellwig 	unsigned long lines = bytes >> 8;
39877fd47e5SChristoph Hellwig 
39977fd47e5SChristoph Hellwig 	asm volatile(
40077fd47e5SChristoph Hellwig #undef BLOCK
40177fd47e5SChristoph Hellwig #define BLOCK(i)			\
40277fd47e5SChristoph Hellwig 		BLK64(PF0, LD, i)	\
40377fd47e5SChristoph Hellwig 		BLK64(PF1, XO1, i)	\
40477fd47e5SChristoph Hellwig 		BLK64(PF2, XO2, i)	\
40577fd47e5SChristoph Hellwig 		BLK64(PF3, XO3, i)	\
40677fd47e5SChristoph Hellwig 		BLK64(PF4, XO4, i)	\
40777fd47e5SChristoph Hellwig 		BLK64(NOP, ST, i)	\
40877fd47e5SChristoph Hellwig 
40977fd47e5SChristoph Hellwig 	" .align 32			;\n"
41077fd47e5SChristoph Hellwig 	" 1:                            ;\n"
41177fd47e5SChristoph Hellwig 
41277fd47e5SChristoph Hellwig 		BLOCK(0)
41377fd47e5SChristoph Hellwig 		BLOCK(4)
41477fd47e5SChristoph Hellwig 		BLOCK(8)
41577fd47e5SChristoph Hellwig 		BLOCK(12)
41677fd47e5SChristoph Hellwig 
41777fd47e5SChristoph Hellwig 	"       add %[inc], %[p1]       ;\n"
41877fd47e5SChristoph Hellwig 	"       add %[inc], %[p2]       ;\n"
41977fd47e5SChristoph Hellwig 	"       add %[inc], %[p3]       ;\n"
42077fd47e5SChristoph Hellwig 	"       add %[inc], %[p4]       ;\n"
42177fd47e5SChristoph Hellwig 	"       add %[inc], %[p5]       ;\n"
42277fd47e5SChristoph Hellwig 	"       dec %[cnt]              ;\n"
42377fd47e5SChristoph Hellwig 	"       jnz 1b                  ;\n"
42477fd47e5SChristoph Hellwig 	: [cnt] "+r" (lines), [p1] "+r" (p1), [p2] "+r" (p2),
42577fd47e5SChristoph Hellwig 	  [p3] "+r" (p3), [p4] "+r" (p4), [p5] "+r" (p5)
42677fd47e5SChristoph Hellwig 	: [inc] XOR_CONSTANT_CONSTRAINT (256UL)
42777fd47e5SChristoph Hellwig 	: "memory");
428*80dcf0a7SChristoph Hellwig }
42977fd47e5SChristoph Hellwig 
430*80dcf0a7SChristoph Hellwig DO_XOR_BLOCKS(sse_inner, xor_sse_2, xor_sse_3, xor_sse_4, xor_sse_5);
431*80dcf0a7SChristoph Hellwig 
432*80dcf0a7SChristoph Hellwig static void xor_gen_sse(void *dest, void **srcs, unsigned int src_cnt,
433*80dcf0a7SChristoph Hellwig 			unsigned int bytes)
434*80dcf0a7SChristoph Hellwig {
435*80dcf0a7SChristoph Hellwig 	kernel_fpu_begin();
436*80dcf0a7SChristoph Hellwig 	xor_gen_sse_inner(dest, srcs, src_cnt, bytes);
43777fd47e5SChristoph Hellwig 	kernel_fpu_end();
43877fd47e5SChristoph Hellwig }
43977fd47e5SChristoph Hellwig 
44077fd47e5SChristoph Hellwig struct xor_block_template xor_block_sse = {
44177fd47e5SChristoph Hellwig 	.name		= "sse",
442*80dcf0a7SChristoph Hellwig 	.xor_gen	= xor_gen_sse,
44377fd47e5SChristoph Hellwig };
44477fd47e5SChristoph Hellwig 
445*80dcf0a7SChristoph Hellwig DO_XOR_BLOCKS(sse_pf64_inner, xor_sse_2_pf64, xor_sse_3_pf64, xor_sse_4_pf64,
446*80dcf0a7SChristoph Hellwig 		xor_sse_5_pf64);
447*80dcf0a7SChristoph Hellwig 
448*80dcf0a7SChristoph Hellwig static void xor_gen_sse_pf64(void *dest, void **srcs, unsigned int src_cnt,
449*80dcf0a7SChristoph Hellwig 			unsigned int bytes)
450*80dcf0a7SChristoph Hellwig {
451*80dcf0a7SChristoph Hellwig 	kernel_fpu_begin();
452*80dcf0a7SChristoph Hellwig 	xor_gen_sse_pf64_inner(dest, srcs, src_cnt, bytes);
453*80dcf0a7SChristoph Hellwig 	kernel_fpu_end();
454*80dcf0a7SChristoph Hellwig }
455*80dcf0a7SChristoph Hellwig 
45677fd47e5SChristoph Hellwig struct xor_block_template xor_block_sse_pf64 = {
45777fd47e5SChristoph Hellwig 	.name		= "prefetch64-sse",
458*80dcf0a7SChristoph Hellwig 	.xor_gen	= xor_gen_sse_pf64,
45977fd47e5SChristoph Hellwig };
460