Branch data Line data Source code
1 : : /* -*- linux-c -*- ------------------------------------------------------- *
2 : : *
3 : : * Copyright 2002-2004 H. Peter Anvin - All Rights Reserved
4 : : *
5 : : * This program is free software; you can redistribute it and/or modify
6 : : * it under the terms of the GNU General Public License as published by
7 : : * the Free Software Foundation, Inc., 53 Temple Place Ste 330,
8 : : * Boston MA 02111-1307, USA; either version 2 of the License, or
9 : : * (at your option) any later version; incorporated herein by reference.
10 : : *
11 : : * ----------------------------------------------------------------------- */
12 : :
13 : : /*
14 : : * int4.c
15 : : *
16 : : * 4-way unrolled portable integer math RAID-6 instruction set
17 : : *
18 : : * This file is postprocessed using unroll.awk
19 : : */
20 : :
21 : : #include <linux/raid/pq.h>
22 : :
23 : : /*
24 : : * This is the C data type to use
25 : : */
26 : :
27 : : /* Change this from BITS_PER_LONG if there is something better... */
28 : : #if BITS_PER_LONG == 64
29 : : # define NBYTES(x) ((x) * 0x0101010101010101UL)
30 : : # define NSIZE 8
31 : : # define NSHIFT 3
32 : : # define NSTRING "64"
33 : : typedef u64 unative_t;
34 : : #else
35 : : # define NBYTES(x) ((x) * 0x01010101U)
36 : : # define NSIZE 4
37 : : # define NSHIFT 2
38 : : # define NSTRING "32"
39 : : typedef u32 unative_t;
40 : : #endif
41 : :
42 : :
43 : :
44 : : /*
45 : : * IA-64 wants insane amounts of unrolling. On other architectures that
46 : : * is just a waste of space.
47 : : */
48 : : #if (4 <= 8) || defined(__ia64__)
49 : :
50 : :
51 : : /*
52 : : * These sub-operations are separate inlines since they can sometimes be
53 : : * specially optimized using architecture-specific hacks.
54 : : */
55 : :
56 : : /*
57 : : * The SHLBYTE() operation shifts each byte left by 1, *not*
58 : : * rolling over into the next byte
59 : : */
60 : : static inline __attribute_const__ unative_t SHLBYTE(unative_t v)
61 : : {
62 : : unative_t vv;
63 : :
64 : 0 : vv = (v << 1) & NBYTES(0xfe);
65 : : return vv;
66 : : }
67 : :
68 : : /*
69 : : * The MASK() operation returns 0xFF in any byte for which the high
70 : : * bit is 1, 0x00 for any byte for which the high bit is 0.
71 : : */
72 : : static inline __attribute_const__ unative_t MASK(unative_t v)
73 : : {
74 : : unative_t vv;
75 : :
76 : 0 : vv = v & NBYTES(0x80);
77 : 0 : vv = (vv << 1) - (vv >> 7); /* Overflow on the top bit is OK */
78 : : return vv;
79 : : }
80 : :
81 : :
82 : 0 : static void raid6_int4_gen_syndrome(int disks, size_t bytes, void **ptrs)
83 : : {
84 : : u8 **dptr = (u8 **)ptrs;
85 : : u8 *p, *q;
86 : : int d, z, z0;
87 : :
88 : : unative_t wd0, wq0, wp0, w10, w20;
89 : : unative_t wd1, wq1, wp1, w11, w21;
90 : : unative_t wd2, wq2, wp2, w12, w22;
91 : : unative_t wd3, wq3, wp3, w13, w23;
92 : :
93 : 0 : z0 = disks - 3; /* Highest data disk */
94 : 0 : p = dptr[z0+1]; /* XOR parity */
95 : 0 : q = dptr[z0+2]; /* RS syndrome */
96 : :
97 [ # # ]: 0 : for ( d = 0 ; d < bytes ; d += NSIZE*4 ) {
98 : 0 : wq0 = wp0 = *(unative_t *)&dptr[z0][d+0*NSIZE];
99 : 0 : wq1 = wp1 = *(unative_t *)&dptr[z0][d+1*NSIZE];
100 : 0 : wq2 = wp2 = *(unative_t *)&dptr[z0][d+2*NSIZE];
101 : 0 : wq3 = wp3 = *(unative_t *)&dptr[z0][d+3*NSIZE];
102 [ # # ]: 0 : for ( z = z0-1 ; z >= 0 ; z-- ) {
103 : 0 : wd0 = *(unative_t *)&dptr[z][d+0*NSIZE];
104 : 0 : wd1 = *(unative_t *)&dptr[z][d+1*NSIZE];
105 : 0 : wd2 = *(unative_t *)&dptr[z][d+2*NSIZE];
106 : 0 : wd3 = *(unative_t *)&dptr[z][d+3*NSIZE];
107 : 0 : wp0 ^= wd0;
108 : 0 : wp1 ^= wd1;
109 : 0 : wp2 ^= wd2;
110 : 0 : wp3 ^= wd3;
111 : : w20 = MASK(wq0);
112 : : w21 = MASK(wq1);
113 : : w22 = MASK(wq2);
114 : : w23 = MASK(wq3);
115 : : w10 = SHLBYTE(wq0);
116 : : w11 = SHLBYTE(wq1);
117 : : w12 = SHLBYTE(wq2);
118 : : w13 = SHLBYTE(wq3);
119 : 0 : w20 &= NBYTES(0x1d);
120 : 0 : w21 &= NBYTES(0x1d);
121 : 0 : w22 &= NBYTES(0x1d);
122 : 0 : w23 &= NBYTES(0x1d);
123 : 0 : w10 ^= w20;
124 : 0 : w11 ^= w21;
125 : 0 : w12 ^= w22;
126 : 0 : w13 ^= w23;
127 : 0 : wq0 = w10 ^ wd0;
128 : 0 : wq1 = w11 ^ wd1;
129 : 0 : wq2 = w12 ^ wd2;
130 : 0 : wq3 = w13 ^ wd3;
131 : : }
132 : 0 : *(unative_t *)&p[d+NSIZE*0] = wp0;
133 : 0 : *(unative_t *)&p[d+NSIZE*1] = wp1;
134 : 0 : *(unative_t *)&p[d+NSIZE*2] = wp2;
135 : 0 : *(unative_t *)&p[d+NSIZE*3] = wp3;
136 : 0 : *(unative_t *)&q[d+NSIZE*0] = wq0;
137 : 0 : *(unative_t *)&q[d+NSIZE*1] = wq1;
138 : 0 : *(unative_t *)&q[d+NSIZE*2] = wq2;
139 : 0 : *(unative_t *)&q[d+NSIZE*3] = wq3;
140 : : }
141 : 0 : }
142 : :
143 : : const struct raid6_calls raid6_intx4 = {
144 : : raid6_int4_gen_syndrome,
145 : : NULL, /* always valid */
146 : : "int" NSTRING "x4",
147 : : 0
148 : : };
149 : :
150 : : #endif
|