xref: /linux/lib/raid/xor/arm/xor.c (revision 440d6635b20037bc9ad46b20817d7b61cef0fc1b)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  Copyright (C) 2001 Russell King
4  */
5 #include "xor_impl.h"
6 #include "xor_arch.h"
7 
8 #define __XOR(a1, a2) a1 ^= a2
9 
10 #define GET_BLOCK_2(dst) \
11 	__asm__("ldmia	%0, {%1, %2}" \
12 		: "=r" (dst), "=r" (a1), "=r" (a2) \
13 		: "0" (dst))
14 
15 #define GET_BLOCK_4(dst) \
16 	__asm__("ldmia	%0, {%1, %2, %3, %4}" \
17 		: "=r" (dst), "=r" (a1), "=r" (a2), "=r" (a3), "=r" (a4) \
18 		: "0" (dst))
19 
20 #define XOR_BLOCK_2(src) \
21 	__asm__("ldmia	%0!, {%1, %2}" \
22 		: "=r" (src), "=r" (b1), "=r" (b2) \
23 		: "0" (src)); \
24 	__XOR(a1, b1); __XOR(a2, b2);
25 
26 #define XOR_BLOCK_4(src) \
27 	__asm__("ldmia	%0!, {%1, %2, %3, %4}" \
28 		: "=r" (src), "=r" (b1), "=r" (b2), "=r" (b3), "=r" (b4) \
29 		: "0" (src)); \
30 	__XOR(a1, b1); __XOR(a2, b2); __XOR(a3, b3); __XOR(a4, b4)
31 
32 #define PUT_BLOCK_2(dst) \
33 	__asm__ __volatile__("stmia	%0!, {%2, %3}" \
34 		: "=r" (dst) \
35 		: "0" (dst), "r" (a1), "r" (a2))
36 
37 #define PUT_BLOCK_4(dst) \
38 	__asm__ __volatile__("stmia	%0!, {%2, %3, %4, %5}" \
39 		: "=r" (dst) \
40 		: "0" (dst), "r" (a1), "r" (a2), "r" (a3), "r" (a4))
41 
42 static void
43 xor_arm4regs_2(unsigned long bytes, unsigned long * __restrict p1,
44 	       const unsigned long * __restrict p2)
45 {
46 	unsigned int lines = bytes / sizeof(unsigned long) / 4;
47 	register unsigned int a1 __asm__("r4");
48 	register unsigned int a2 __asm__("r5");
49 	register unsigned int a3 __asm__("r6");
50 	register unsigned int a4 __asm__("r10");
51 	register unsigned int b1 __asm__("r8");
52 	register unsigned int b2 __asm__("r9");
53 	register unsigned int b3 __asm__("ip");
54 	register unsigned int b4 __asm__("lr");
55 
56 	do {
57 		GET_BLOCK_4(p1);
58 		XOR_BLOCK_4(p2);
59 		PUT_BLOCK_4(p1);
60 	} while (--lines);
61 }
62 
63 static void
64 xor_arm4regs_3(unsigned long bytes, unsigned long * __restrict p1,
65 	       const unsigned long * __restrict p2,
66 	       const unsigned long * __restrict p3)
67 {
68 	unsigned int lines = bytes / sizeof(unsigned long) / 4;
69 	register unsigned int a1 __asm__("r4");
70 	register unsigned int a2 __asm__("r5");
71 	register unsigned int a3 __asm__("r6");
72 	register unsigned int a4 __asm__("r10");
73 	register unsigned int b1 __asm__("r8");
74 	register unsigned int b2 __asm__("r9");
75 	register unsigned int b3 __asm__("ip");
76 	register unsigned int b4 __asm__("lr");
77 
78 	do {
79 		GET_BLOCK_4(p1);
80 		XOR_BLOCK_4(p2);
81 		XOR_BLOCK_4(p3);
82 		PUT_BLOCK_4(p1);
83 	} while (--lines);
84 }
85 
86 static void
87 xor_arm4regs_4(unsigned long bytes, unsigned long * __restrict p1,
88 	       const unsigned long * __restrict p2,
89 	       const unsigned long * __restrict p3,
90 	       const unsigned long * __restrict p4)
91 {
92 	unsigned int lines = bytes / sizeof(unsigned long) / 2;
93 	register unsigned int a1 __asm__("r8");
94 	register unsigned int a2 __asm__("r9");
95 	register unsigned int b1 __asm__("ip");
96 	register unsigned int b2 __asm__("lr");
97 
98 	do {
99 		GET_BLOCK_2(p1);
100 		XOR_BLOCK_2(p2);
101 		XOR_BLOCK_2(p3);
102 		XOR_BLOCK_2(p4);
103 		PUT_BLOCK_2(p1);
104 	} while (--lines);
105 }
106 
107 static void
108 xor_arm4regs_5(unsigned long bytes, unsigned long * __restrict p1,
109 	       const unsigned long * __restrict p2,
110 	       const unsigned long * __restrict p3,
111 	       const unsigned long * __restrict p4,
112 	       const unsigned long * __restrict p5)
113 {
114 	unsigned int lines = bytes / sizeof(unsigned long) / 2;
115 	register unsigned int a1 __asm__("r8");
116 	register unsigned int a2 __asm__("r9");
117 	register unsigned int b1 __asm__("ip");
118 	register unsigned int b2 __asm__("lr");
119 
120 	do {
121 		GET_BLOCK_2(p1);
122 		XOR_BLOCK_2(p2);
123 		XOR_BLOCK_2(p3);
124 		XOR_BLOCK_2(p4);
125 		XOR_BLOCK_2(p5);
126 		PUT_BLOCK_2(p1);
127 	} while (--lines);
128 }
129 
130 DO_XOR_BLOCKS(arm4regs, xor_arm4regs_2, xor_arm4regs_3, xor_arm4regs_4,
131 		xor_arm4regs_5);
132 
133 struct xor_block_template xor_block_arm4regs = {
134 	.name		= "arm4regs",
135 	.xor_gen	= xor_gen_arm4regs,
136 };
137