Assembly version of put_pixels. This is currently the function that
[ffmpeg.git] / libavcodec / alpha / dsputil_alpha.c
1 /*
2  * Alpha optimized DSP utils
3  * Copyright (c) 2002 Falk Hueffner <falk@debian.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include "asm.h"
21 #include "../dsputil.h"
22
23 void simple_idct_axp(DCTELEM *block);
24
25 void put_pixels_axp_asm(uint8_t *block, const uint8_t *pixels,
26                         int line_size, int h);
27 void put_pixels_clamped_mvi_asm(const DCTELEM *block, uint8_t *pixels,
28                                 int line_size);
29 void add_pixels_clamped_mvi_asm(const DCTELEM *block, uint8_t *pixels, 
30                                 int line_size);
31
32 #if 0
33 /* These functions were the base for the optimized assembler routines,
34    and remain here for documentation purposes.  */
35 static void put_pixels_clamped_mvi(const DCTELEM *block, uint8_t *pixels, 
36                                    int line_size)
37 {
38     int i = 8;
39     uint64_t clampmask = zap(-1, 0xaa); /* 0x00ff00ff00ff00ff */
40
41     ASM_ACCEPT_MVI;
42
43     do {
44         uint64_t shorts0, shorts1;
45
46         shorts0 = ldq(block);
47         shorts0 = maxsw4(shorts0, 0);
48         shorts0 = minsw4(shorts0, clampmask);
49         stl(pkwb(shorts0), pixels);
50
51         shorts1 = ldq(block + 4);
52         shorts1 = maxsw4(shorts1, 0);
53         shorts1 = minsw4(shorts1, clampmask);
54         stl(pkwb(shorts1), pixels + 4);
55
56         pixels += line_size;
57         block += 8;
58     } while (--i);
59 }
60
61 void add_pixels_clamped_mvi(const DCTELEM *block, uint8_t *pixels, 
62                             int line_size)
63 {
64     int h = 8;
65     /* Keep this function a leaf function by generating the constants
66        manually (mainly for the hack value ;-).  */
67     uint64_t clampmask = zap(-1, 0xaa); /* 0x00ff00ff00ff00ff */
68     uint64_t signmask  = zap(-1, 0x33);
69     signmask ^= signmask >> 1;  /* 0x8000800080008000 */
70
71     ASM_ACCEPT_MVI;
72
73     do {
74         uint64_t shorts0, pix0, signs0;
75         uint64_t shorts1, pix1, signs1;
76
77         shorts0 = ldq(block);
78         shorts1 = ldq(block + 4);
79
80         pix0    = unpkbw(ldl(pixels));
81         /* Signed subword add (MMX paddw).  */
82         signs0  = shorts0 & signmask;
83         shorts0 &= ~signmask;
84         shorts0 += pix0;
85         shorts0 ^= signs0;
86         /* Clamp. */
87         shorts0 = maxsw4(shorts0, 0);
88         shorts0 = minsw4(shorts0, clampmask);   
89
90         /* Next 4.  */
91         pix1    = unpkbw(ldl(pixels + 4));
92         signs1  = shorts1 & signmask;
93         shorts1 &= ~signmask;
94         shorts1 += pix1;
95         shorts1 ^= signs1;
96         shorts1 = maxsw4(shorts1, 0);
97         shorts1 = minsw4(shorts1, clampmask);
98
99         stl(pkwb(shorts0), pixels);
100         stl(pkwb(shorts1), pixels + 4);
101
102         pixels += line_size;
103         block += 8;
104     } while (--h);
105 }
106 #endif
107
108 /* Average 8 unsigned bytes in parallel: (b1 + b2) >> 1
109    Since the immediate result could be greater than 255, we do the
110    shift first. The result is too low by one if the bytes were both
111    odd, so we need to add (l1 & l2) & BYTE_VEC(0x01).  */
112 static inline UINT64 avg2_no_rnd(UINT64 l1, UINT64 l2)
113 {
114     UINT64 correction = (l1 & l2) & BYTE_VEC(0x01);
115     l1 = (l1 & ~BYTE_VEC(0x01)) >> 1;
116     l2 = (l2 & ~BYTE_VEC(0x01)) >> 1;
117     return l1 + l2 + correction;
118 }
119
120 /* Average 8 bytes with rounding: (b1 + b2 + 1) >> 1
121    The '1' only has an effect when one byte is even and the other odd,
122    i. e. we also need to add (l1 ^ l2) & BYTE_VEC(0x01).
123    Incidentally, that is equivalent to (l1 | l2) & BYTE_VEC(0x01).  */
124 static inline UINT64 avg2(UINT64 l1, UINT64 l2)
125 {
126     UINT64 correction = (l1 | l2) & BYTE_VEC(0x01);
127     l1 = (l1 & ~BYTE_VEC(0x01)) >> 1;
128     l2 = (l2 & ~BYTE_VEC(0x01)) >> 1;
129     return l1 + l2 + correction;
130 }
131
132 static inline UINT64 avg4(UINT64 l1, UINT64 l2, UINT64 l3, UINT64 l4)
133 {
134     UINT64 r1 = ((l1 & ~BYTE_VEC(0x03)) >> 2)
135               + ((l2 & ~BYTE_VEC(0x03)) >> 2)
136               + ((l3 & ~BYTE_VEC(0x03)) >> 2)
137               + ((l4 & ~BYTE_VEC(0x03)) >> 2);
138     UINT64 r2 = ((  (l1 & BYTE_VEC(0x03))
139                   + (l2 & BYTE_VEC(0x03))
140                   + (l3 & BYTE_VEC(0x03))
141                   + (l4 & BYTE_VEC(0x03))
142                   + BYTE_VEC(0x02)) >> 2) & BYTE_VEC(0x03);
143     return r1 + r2;
144 }
145
146 static inline UINT64 avg4_no_rnd(UINT64 l1, UINT64 l2, UINT64 l3, UINT64 l4)
147 {
148     UINT64 r1 = ((l1 & ~BYTE_VEC(0x03)) >> 2)
149               + ((l2 & ~BYTE_VEC(0x03)) >> 2)
150               + ((l3 & ~BYTE_VEC(0x03)) >> 2)
151               + ((l4 & ~BYTE_VEC(0x03)) >> 2);
152     UINT64 r2 = (( (l1 & BYTE_VEC(0x03))
153                  + (l2 & BYTE_VEC(0x03))
154                  + (l3 & BYTE_VEC(0x03))
155                  + (l4 & BYTE_VEC(0x03))
156                  + BYTE_VEC(0x01)) >> 2) & BYTE_VEC(0x03);
157     return r1 + r2;
158 }
159
160 #define PIXOPNAME(suffix) put ## suffix
161 #define BTYPE UINT8
162 #define AVG2 avg2
163 #define AVG4 avg4
164 #define STORE(l, b) stq(l, b)
165 #include "pixops.h"
166 #undef PIXOPNAME
167 #undef BTYPE
168 #undef AVG2
169 #undef AVG4
170 #undef STORE
171
172 #define PIXOPNAME(suffix) put_no_rnd ## suffix
173 #define BTYPE UINT8
174 #define AVG2 avg2_no_rnd
175 #define AVG4 avg4_no_rnd
176 #define STORE(l, b) stq(l, b)
177 #include "pixops.h"
178 #undef PIXOPNAME
179 #undef BTYPE
180 #undef AVG2
181 #undef AVG4
182 #undef STORE
183
184 /* The following functions are untested.  */
185 #if 0
186
187 #define PIXOPNAME(suffix) avg ## suffix
188 #define BTYPE UINT8
189 #define AVG2 avg2
190 #define AVG4 avg4
191 #define STORE(l, b) stq(AVG2(l, ldq(b)), b);
192 #include "pixops.h"
193 #undef PIXOPNAME
194 #undef BTYPE
195 #undef AVG2
196 #undef AVG4
197 #undef STORE
198
199 #define PIXOPNAME(suffix) avg_no_rnd ## suffix
200 #define BTYPE UINT8
201 #define AVG2 avg2_no_rnd
202 #define AVG4 avg4_no_rnd
203 #define STORE(l, b) stq(AVG2(l, ldq(b)), b);
204 #include "pixops.h"
205 #undef PIXOPNAME
206 #undef BTYPE
207 #undef AVG2
208 #undef AVG4
209 #undef STORE
210
211 #define PIXOPNAME(suffix) sub ## suffix
212 #define BTYPE DCTELEM
213 #define AVG2 avg2
214 #define AVG4 avg4
215 #define STORE(l, block) do {            \
216     UINT64 xxx = l;                     \
217     (block)[0] -= (xxx >>  0) & 0xff;   \
218     (block)[1] -= (xxx >>  8) & 0xff;   \
219     (block)[2] -= (xxx >> 16) & 0xff;   \
220     (block)[3] -= (xxx >> 24) & 0xff;   \
221     (block)[4] -= (xxx >> 32) & 0xff;   \
222     (block)[5] -= (xxx >> 40) & 0xff;   \
223     (block)[6] -= (xxx >> 48) & 0xff;   \
224     (block)[7] -= (xxx >> 56) & 0xff;   \
225 } while (0)
226 #include "pixops.h"
227 #undef PIXOPNAME
228 #undef BTYPE
229 #undef AVG2
230 #undef AVG4
231 #undef STORE
232
233 #endif
234
235 void dsputil_init_alpha(void)
236 {
237     put_pixels_tab[0] = put_pixels_axp_asm;
238     put_pixels_tab[1] = put_pixels_x2_axp;
239     put_pixels_tab[2] = put_pixels_y2_axp;
240     put_pixels_tab[3] = put_pixels_xy2_axp;
241
242     put_no_rnd_pixels_tab[0] = put_pixels_axp_asm;
243     put_no_rnd_pixels_tab[1] = put_no_rnd_pixels_x2_axp;
244     put_no_rnd_pixels_tab[2] = put_no_rnd_pixels_y2_axp;
245     put_no_rnd_pixels_tab[3] = put_no_rnd_pixels_xy2_axp;
246
247     /* amask clears all bits that correspond to present features.  */
248     if (amask(AMASK_MVI) == 0) {
249         put_pixels_clamped = put_pixels_clamped_mvi_asm;
250         add_pixels_clamped = add_pixels_clamped_mvi_asm;
251     }
252 }