xref: /linux/lib/raid/raid6/x86/mmx.c (revision 30bf04bd13a58cd9b877589569aa0abd06f04e52)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright 2002 H. Peter Anvin - All Rights Reserved
4  *
5  * MMX implementation of RAID-6 syndrome functions.
6  */
7 
8 #include <asm/cpufeature.h>
9 #include <asm/fpu/api.h>
10 #include "algos.h"
11 
12 /* Shared with raid6/sse1.c */
13 const struct raid6_mmx_constants {
14 	u64 x1d;
15 } raid6_mmx_constants = {
16 	0x1d1d1d1d1d1d1d1dULL,
17 };
18 
19 /*
20  * Plain MMX implementation
21  */
22 static void raid6_mmx1_gen_syndrome(int disks, size_t bytes, void **ptrs)
23 {
24 	u8 **dptr = (u8 **)ptrs;
25 	u8 *p, *q;
26 	int d, z, z0;
27 
28 	z0 = disks - 3;		/* Highest data disk */
29 	p = dptr[z0+1];		/* XOR parity */
30 	q = dptr[z0+2];		/* RS syndrome */
31 
32 	kernel_fpu_begin();
33 
34 	asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d));
35 	asm volatile("pxor %mm5,%mm5");	/* Zero temp */
36 
37 	for ( d = 0 ; d < bytes ; d += 8 ) {
38 		asm volatile("movq %0,%%mm2" : : "m" (dptr[z0][d])); /* P[0] */
39 		asm volatile("movq %mm2,%mm4");	/* Q[0] */
40 		for ( z = z0-1 ; z >= 0 ; z-- ) {
41 			asm volatile("movq %0,%%mm6" : : "m" (dptr[z][d]));
42 			asm volatile("pcmpgtb %mm4,%mm5");
43 			asm volatile("paddb %mm4,%mm4");
44 			asm volatile("pand %mm0,%mm5");
45 			asm volatile("pxor %mm5,%mm4");
46 			asm volatile("pxor %mm5,%mm5");
47 			asm volatile("pxor %mm6,%mm2");
48 			asm volatile("pxor %mm6,%mm4");
49 		}
50 		asm volatile("movq %%mm2,%0" : "=m" (p[d]));
51 		asm volatile("pxor %mm2,%mm2");
52 		asm volatile("movq %%mm4,%0" : "=m" (q[d]));
53 		asm volatile("pxor %mm4,%mm4");
54 	}
55 
56 	kernel_fpu_end();
57 }
58 
59 const struct raid6_calls raid6_mmxx1 = {
60 	.gen_syndrome	= raid6_mmx1_gen_syndrome,
61 	.name		= "mmxx1",
62 };
63 
64 /*
65  * Unrolled-by-2 MMX implementation
66  */
67 static void raid6_mmx2_gen_syndrome(int disks, size_t bytes, void **ptrs)
68 {
69 	u8 **dptr = (u8 **)ptrs;
70 	u8 *p, *q;
71 	int d, z, z0;
72 
73 	z0 = disks - 3;		/* Highest data disk */
74 	p = dptr[z0+1];		/* XOR parity */
75 	q = dptr[z0+2];		/* RS syndrome */
76 
77 	kernel_fpu_begin();
78 
79 	asm volatile("movq %0,%%mm0" : : "m" (raid6_mmx_constants.x1d));
80 	asm volatile("pxor %mm5,%mm5");	/* Zero temp */
81 	asm volatile("pxor %mm7,%mm7"); /* Zero temp */
82 
83 	for ( d = 0 ; d < bytes ; d += 16 ) {
84 		asm volatile("movq %0,%%mm2" : : "m" (dptr[z0][d])); /* P[0] */
85 		asm volatile("movq %0,%%mm3" : : "m" (dptr[z0][d+8]));
86 		asm volatile("movq %mm2,%mm4"); /* Q[0] */
87 		asm volatile("movq %mm3,%mm6"); /* Q[1] */
88 		for ( z = z0-1 ; z >= 0 ; z-- ) {
89 			asm volatile("pcmpgtb %mm4,%mm5");
90 			asm volatile("pcmpgtb %mm6,%mm7");
91 			asm volatile("paddb %mm4,%mm4");
92 			asm volatile("paddb %mm6,%mm6");
93 			asm volatile("pand %mm0,%mm5");
94 			asm volatile("pand %mm0,%mm7");
95 			asm volatile("pxor %mm5,%mm4");
96 			asm volatile("pxor %mm7,%mm6");
97 			asm volatile("movq %0,%%mm5" : : "m" (dptr[z][d]));
98 			asm volatile("movq %0,%%mm7" : : "m" (dptr[z][d+8]));
99 			asm volatile("pxor %mm5,%mm2");
100 			asm volatile("pxor %mm7,%mm3");
101 			asm volatile("pxor %mm5,%mm4");
102 			asm volatile("pxor %mm7,%mm6");
103 			asm volatile("pxor %mm5,%mm5");
104 			asm volatile("pxor %mm7,%mm7");
105 		}
106 		asm volatile("movq %%mm2,%0" : "=m" (p[d]));
107 		asm volatile("movq %%mm3,%0" : "=m" (p[d+8]));
108 		asm volatile("movq %%mm4,%0" : "=m" (q[d]));
109 		asm volatile("movq %%mm6,%0" : "=m" (q[d+8]));
110 	}
111 
112 	kernel_fpu_end();
113 }
114 
115 const struct raid6_calls raid6_mmxx2 = {
116 	.gen_syndrome	= raid6_mmx2_gen_syndrome,
117 	.name		= "mmxx2",
118 };
119