1/*
2 *  Fast C2P (Chunky-to-Planar) Conversion
3 *
4 *  NOTES:
5 *    - This code was inspired by Scout's C2P tutorial
6 *    - It assumes to run on a big endian system
7 *
8 *  Copyright © 2003-2008 Geert Uytterhoeven
9 *
10 *  Permission is hereby granted, free of charge, to any person obtaining a
11 *  copy of this software and associated documentation files (the "Software"),
12 *  to deal in the Software without restriction, including without limitation
13 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 *  and/or sell copies of the Software, and to permit persons to whom the
15 *  Software is furnished to do so, subject to the following conditions:
16 *
17 *  The above copyright notice and this permission notice (including the next
18 *  paragraph) shall be included in all copies or substantial portions of the
19 *  Software.
20 *
21 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24 *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 *  DEALINGS IN THE SOFTWARE.
28 */
29
30
31    /*
32     *  Basic transpose step
33     */
34
35static inline void _transp(CARD32 d[], unsigned int i1, unsigned int i2,
36                           unsigned int shift, CARD32 mask)
37{
38    CARD32 t = (d[i1] ^ (d[i2] >> shift)) & mask;
39
40    d[i1] ^= t;
41    d[i2] ^= t << shift;
42}
43
44
45static inline void c2p_unsupported(void) {
46    BUG_WARN(1);
47}
48
49static inline CARD32 get_mask(unsigned int n)
50{
51    switch (n) {
52    case 1:
53        return 0x55555555;
54
55    case 2:
56        return 0x33333333;
57
58    case 4:
59        return 0x0f0f0f0f;
60
61    case 8:
62        return 0x00ff00ff;
63
64    case 16:
65        return 0x0000ffff;
66    }
67
68    c2p_unsupported();
69    return 0;
70}
71
72
73    /*
74     *  Transpose operations on 8 32-bit words
75     */
76
77static inline void transp8(CARD32 d[], unsigned int n, unsigned int m)
78{
79    CARD32 mask = get_mask(n);
80
81    switch (m) {
82    case 1:
83        /* First n x 1 block */
84        _transp(d, 0, 1, n, mask);
85        /* Second n x 1 block */
86        _transp(d, 2, 3, n, mask);
87        /* Third n x 1 block */
88        _transp(d, 4, 5, n, mask);
89        /* Fourth n x 1 block */
90        _transp(d, 6, 7, n, mask);
91        return;
92
93    case 2:
94        /* First n x 2 block */
95        _transp(d, 0, 2, n, mask);
96        _transp(d, 1, 3, n, mask);
97        /* Second n x 2 block */
98        _transp(d, 4, 6, n, mask);
99        _transp(d, 5, 7, n, mask);
100        return;
101
102    case 4:
103        /* Single n x 4 block */
104        _transp(d, 0, 4, n, mask);
105        _transp(d, 1, 5, n, mask);
106        _transp(d, 2, 6, n, mask);
107        _transp(d, 3, 7, n, mask);
108        return;
109    }
110
111    c2p_unsupported();
112}
113
114
115    /*
116     *  Transpose operations on 4 32-bit words
117     */
118
119static inline void transp4(CARD32 d[], unsigned int n, unsigned int m)
120{
121    CARD32 mask = get_mask(n);
122
123    switch (m) {
124    case 1:
125        /* First n x 1 block */
126        _transp(d, 0, 1, n, mask);
127        /* Second n x 1 block */
128        _transp(d, 2, 3, n, mask);
129        return;
130
131    case 2:
132        /* Single n x 2 block */
133        _transp(d, 0, 2, n, mask);
134        _transp(d, 1, 3, n, mask);
135        return;
136    }
137
138    c2p_unsupported();
139}
140
141
142    /*
143     *  Transpose operations on 4 32-bit words (reverse order)
144     */
145
146static inline void transp4x(CARD32 d[], unsigned int n, unsigned int m)
147{
148    CARD32 mask = get_mask(n);
149
150    switch (m) {
151    case 2:
152        /* Single n x 2 block */
153        _transp(d, 2, 0, n, mask);
154        _transp(d, 3, 1, n, mask);
155        return;
156    }
157
158    c2p_unsupported();
159}
160
161
162    /*
163     *  Transpose operations on 2 32-bit words
164     */
165
166static inline void transp2(CARD32 d[], unsigned int n)
167{
168    CARD32 mask = get_mask(n);
169
170    /* Single n x 1 block */
171    _transp(d, 0, 1, n, mask);
172    return;
173}
174
175
176    /*
177     *  Transpose operations on 2 32-bit words (reverse order)
178     */
179
180static inline void transp2x(CARD32 d[], unsigned int n)
181{
182    CARD32 mask = get_mask(n);
183
184    /* Single n x 1 block */
185    _transp(d, 1, 0, n, mask);
186    return;
187}
188