Cleanup
[ffmpeg.git] / libavcodec / ppc / dsputil_ppc.c
1 /*
2  * Copyright (c) 2002 Brian Foley
3  * Copyright (c) 2002 Dieter Shirley
4  * Copyright (c) 2003-2004 Romain Dolbeau <romain@dolbeau.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 #include "../dsputil.h"
22
23 #include "dsputil_ppc.h"
24
25 #ifdef HAVE_ALTIVEC
26 #include "dsputil_altivec.h"
27
28 extern void fdct_altivec(int16_t *block);
29 extern void idct_put_altivec(uint8_t *dest, int line_size, int16_t *block);
30 extern void idct_add_altivec(uint8_t *dest, int line_size, int16_t *block);
31 extern void ff_snow_horizontal_compose97i_altivec(DWTELEM *b, int width);
32 extern void ff_snow_vertical_compose97i_altivec(DWTELEM *b0, DWTELEM *b1,
33                                                 DWTELEM *b2, DWTELEM *b3,
34                                                 DWTELEM *b4, DWTELEM *b5,
35                                                 int width);
36 extern void ff_snow_inner_add_yblock_altivec(uint8_t *obmc,
37                                              const int obmc_stride,
38                                              uint8_t * * block, int b_w,
39                                              int b_h, int src_x, int src_y,
40                                              int src_stride, slice_buffer * sb,
41                                              int add, uint8_t * dst8);
42
43 void dsputil_h264_init_ppc(DSPContext* c, AVCodecContext *avctx);
44 void vc1dsp_init_altivec(DSPContext* c, AVCodecContext *avctx);
45
46 #endif
47
48 int mm_flags = 0;
49
50 int mm_support(void)
51 {
52     int result = 0;
53 #ifdef HAVE_ALTIVEC
54     if (has_altivec()) {
55         result |= MM_ALTIVEC;
56     }
57 #endif /* result */
58     return result;
59 }
60
61 #ifdef POWERPC_PERFORMANCE_REPORT
62 unsigned long long perfdata[POWERPC_NUM_PMC_ENABLED][powerpc_perf_total][powerpc_data_total];
63 /* list below must match enum in dsputil_ppc.h */
64 static unsigned char* perfname[] = {
65   "ff_fft_calc_altivec",
66   "gmc1_altivec",
67   "dct_unquantize_h263_altivec",
68   "fdct_altivec",
69   "idct_add_altivec",
70   "idct_put_altivec",
71   "put_pixels16_altivec",
72   "avg_pixels16_altivec",
73   "avg_pixels8_altivec",
74   "put_pixels8_xy2_altivec",
75   "put_no_rnd_pixels8_xy2_altivec",
76   "put_pixels16_xy2_altivec",
77   "put_no_rnd_pixels16_xy2_altivec",
78   "hadamard8_diff8x8_altivec",
79   "hadamard8_diff16_altivec",
80   "avg_pixels8_xy2_altivec",
81   "clear_blocks_dcbz32_ppc",
82   "clear_blocks_dcbz128_ppc",
83   "put_h264_chroma_mc8_altivec",
84   "avg_h264_chroma_mc8_altivec",
85   "put_h264_qpel16_h_lowpass_altivec",
86   "avg_h264_qpel16_h_lowpass_altivec",
87   "put_h264_qpel16_v_lowpass_altivec",
88   "avg_h264_qpel16_v_lowpass_altivec",
89   "put_h264_qpel16_hv_lowpass_altivec",
90   "avg_h264_qpel16_hv_lowpass_altivec",
91   ""
92 };
93 #include <stdio.h>
94 #endif
95
96 #ifdef POWERPC_PERFORMANCE_REPORT
97 void powerpc_display_perf_report(void)
98 {
99   int i, j;
100   av_log(NULL, AV_LOG_INFO, "PowerPC performance report\n Values are from the PMC registers, and represent whatever the registers are set to record.\n");
101   for(i = 0 ; i < powerpc_perf_total ; i++)
102   {
103     for (j = 0; j < POWERPC_NUM_PMC_ENABLED ; j++)
104       {
105         if (perfdata[j][i][powerpc_data_num] != (unsigned long long)0)
106           av_log(NULL, AV_LOG_INFO,
107                   " Function \"%s\" (pmc%d):\n\tmin: %llu\n\tmax: %llu\n\tavg: %1.2lf (%llu)\n",
108                   perfname[i],
109                   j+1,
110                   perfdata[j][i][powerpc_data_min],
111                   perfdata[j][i][powerpc_data_max],
112                   (double)perfdata[j][i][powerpc_data_sum] /
113                   (double)perfdata[j][i][powerpc_data_num],
114                   perfdata[j][i][powerpc_data_num]);
115       }
116   }
117 }
118 #endif /* POWERPC_PERFORMANCE_REPORT */
119
120 /* ***** WARNING ***** WARNING ***** WARNING ***** */
121 /*
122   clear_blocks_dcbz32_ppc will not work properly
123   on PowerPC processors with a cache line size
124   not equal to 32 bytes.
125   Fortunately all processor used by Apple up to
126   at least the 7450 (aka second generation G4)
127   use 32 bytes cache line.
128   This is due to the use of the 'dcbz' instruction.
129   It simply clear to zero a single cache line,
130   so you need to know the cache line size to use it !
131   It's absurd, but it's fast...
132
133   update 24/06/2003 : Apple released yesterday the G5,
134   with a PPC970. cache line size : 128 bytes. Oups.
135   The semantic of dcbz was changed, it always clear
136   32 bytes. so the function below will work, but will
137   be slow. So I fixed check_dcbz_effect to use dcbzl,
138   which is defined to clear a cache line (as dcbz before).
139   So we still can distinguish, and use dcbz (32 bytes)
140   or dcbzl (one cache line) as required.
141
142   see <http://developer.apple.com/technotes/tn/tn2087.html>
143   and <http://developer.apple.com/technotes/tn/tn2086.html>
144 */
145 void clear_blocks_dcbz32_ppc(DCTELEM *blocks)
146 {
147 POWERPC_PERF_DECLARE(powerpc_clear_blocks_dcbz32, 1);
148     register int misal = ((unsigned long)blocks & 0x00000010);
149     register int i = 0;
150 POWERPC_PERF_START_COUNT(powerpc_clear_blocks_dcbz32, 1);
151 #if 1
152     if (misal) {
153       ((unsigned long*)blocks)[0] = 0L;
154       ((unsigned long*)blocks)[1] = 0L;
155       ((unsigned long*)blocks)[2] = 0L;
156       ((unsigned long*)blocks)[3] = 0L;
157       i += 16;
158     }
159     for ( ; i < sizeof(DCTELEM)*6*64-31 ; i += 32) {
160 #ifndef __MWERKS__
161       asm volatile("dcbz %0,%1" : : "b" (blocks), "r" (i) : "memory");
162 #else
163       __dcbz( blocks, i );
164 #endif
165     }
166     if (misal) {
167       ((unsigned long*)blocks)[188] = 0L;
168       ((unsigned long*)blocks)[189] = 0L;
169       ((unsigned long*)blocks)[190] = 0L;
170       ((unsigned long*)blocks)[191] = 0L;
171       i += 16;
172     }
173 #else
174     memset(blocks, 0, sizeof(DCTELEM)*6*64);
175 #endif
176 POWERPC_PERF_STOP_COUNT(powerpc_clear_blocks_dcbz32, 1);
177 }
178
179 /* same as above, when dcbzl clear a whole 128B cache line
180    i.e. the PPC970 aka G5 */
181 #ifndef NO_DCBZL
182 void clear_blocks_dcbz128_ppc(DCTELEM *blocks)
183 {
184 POWERPC_PERF_DECLARE(powerpc_clear_blocks_dcbz128, 1);
185     register int misal = ((unsigned long)blocks & 0x0000007f);
186     register int i = 0;
187 POWERPC_PERF_START_COUNT(powerpc_clear_blocks_dcbz128, 1);
188 #if 1
189  if (misal) {
190    // we could probably also optimize this case,
191    // but there's not much point as the machines
192    // aren't available yet (2003-06-26)
193       memset(blocks, 0, sizeof(DCTELEM)*6*64);
194     }
195     else
196       for ( ; i < sizeof(DCTELEM)*6*64 ; i += 128) {
197         asm volatile("dcbzl %0,%1" : : "b" (blocks), "r" (i) : "memory");
198       }
199 #else
200     memset(blocks, 0, sizeof(DCTELEM)*6*64);
201 #endif
202 POWERPC_PERF_STOP_COUNT(powerpc_clear_blocks_dcbz128, 1);
203 }
204 #else
205 void clear_blocks_dcbz128_ppc(DCTELEM *blocks)
206 {
207   memset(blocks, 0, sizeof(DCTELEM)*6*64);
208 }
209 #endif
210
211 #ifndef NO_DCBZL
212 /* check dcbz report how many bytes are set to 0 by dcbz */
213 /* update 24/06/2003 : replace dcbz by dcbzl to get
214    the intended effect (Apple "fixed" dcbz)
215    unfortunately this cannot be used unless the assembler
216    knows about dcbzl ... */
217 long check_dcbzl_effect(void)
218 {
219   register char *fakedata = (char*)av_malloc(1024);
220   register char *fakedata_middle;
221   register long zero = 0;
222   register long i = 0;
223   long count = 0;
224
225   if (!fakedata)
226   {
227     return 0L;
228   }
229
230   fakedata_middle = (fakedata + 512);
231
232   memset(fakedata, 0xFF, 1024);
233
234   /* below the constraint "b" seems to mean "Address base register"
235      in gcc-3.3 / RS/6000 speaks. seems to avoid using r0, so.... */
236   asm volatile("dcbzl %0, %1" : : "b" (fakedata_middle), "r" (zero));
237
238   for (i = 0; i < 1024 ; i ++)
239   {
240     if (fakedata[i] == (char)0)
241       count++;
242   }
243
244   av_free(fakedata);
245
246   return count;
247 }
248 #else
249 long check_dcbzl_effect(void)
250 {
251   return 0;
252 }
253 #endif
254
255 void dsputil_init_ppc(DSPContext* c, AVCodecContext *avctx)
256 {
257     // Common optimizations whether Altivec is available or not
258
259   switch (check_dcbzl_effect()) {
260   case 32:
261     c->clear_blocks = clear_blocks_dcbz32_ppc;
262     break;
263   case 128:
264     c->clear_blocks = clear_blocks_dcbz128_ppc;
265     break;
266   default:
267     break;
268   }
269
270 #ifdef HAVE_ALTIVEC
271   dsputil_h264_init_ppc(c, avctx);
272
273     if (has_altivec()) {
274         mm_flags |= MM_ALTIVEC;
275
276         // Altivec specific optimisations
277         c->pix_abs[0][1] = sad16_x2_altivec;
278         c->pix_abs[0][2] = sad16_y2_altivec;
279         c->pix_abs[0][3] = sad16_xy2_altivec;
280         c->pix_abs[0][0] = sad16_altivec;
281         c->pix_abs[1][0] = sad8_altivec;
282         c->sad[0]= sad16_altivec;
283         c->sad[1]= sad8_altivec;
284         c->pix_norm1 = pix_norm1_altivec;
285         c->sse[1]= sse8_altivec;
286         c->sse[0]= sse16_altivec;
287         c->pix_sum = pix_sum_altivec;
288         c->diff_pixels = diff_pixels_altivec;
289         c->get_pixels = get_pixels_altivec;
290 // next one disabled as it's untested.
291 #if 0
292         c->add_bytes= add_bytes_altivec;
293 #endif /* 0 */
294         c->put_pixels_tab[0][0] = put_pixels16_altivec;
295         /* the two functions do the same thing, so use the same code */
296         c->put_no_rnd_pixels_tab[0][0] = put_pixels16_altivec;
297         c->avg_pixels_tab[0][0] = avg_pixels16_altivec;
298         c->avg_pixels_tab[1][0] = avg_pixels8_altivec;
299         c->avg_pixels_tab[1][3] = avg_pixels8_xy2_altivec;
300         c->put_pixels_tab[1][3] = put_pixels8_xy2_altivec;
301         c->put_no_rnd_pixels_tab[1][3] = put_no_rnd_pixels8_xy2_altivec;
302         c->put_pixels_tab[0][3] = put_pixels16_xy2_altivec;
303         c->put_no_rnd_pixels_tab[0][3] = put_no_rnd_pixels16_xy2_altivec;
304
305         c->gmc1 = gmc1_altivec;
306
307         c->hadamard8_diff[0] = hadamard8_diff16_altivec;
308         c->hadamard8_diff[1] = hadamard8_diff8x8_altivec;
309
310         c->horizontal_compose97i = ff_snow_horizontal_compose97i_altivec;
311         c->vertical_compose97i = ff_snow_vertical_compose97i_altivec;
312         c->inner_add_yblock = ff_snow_inner_add_yblock_altivec;
313
314         vc1dsp_init_altivec(c, avctx);
315 #ifdef CONFIG_ENCODERS
316         if (avctx->dct_algo == FF_DCT_AUTO ||
317             avctx->dct_algo == FF_DCT_ALTIVEC)
318         {
319             c->fdct = fdct_altivec;
320         }
321 #endif //CONFIG_ENCODERS
322
323       if (avctx->lowres==0)
324       {
325         if ((avctx->idct_algo == FF_IDCT_AUTO) ||
326                 (avctx->idct_algo == FF_IDCT_ALTIVEC))
327         {
328             c->idct_put = idct_put_altivec;
329             c->idct_add = idct_add_altivec;
330 #ifndef ALTIVEC_USE_REFERENCE_C_CODE
331             c->idct_permutation_type = FF_TRANSPOSE_IDCT_PERM;
332 #else /* ALTIVEC_USE_REFERENCE_C_CODE */
333             c->idct_permutation_type = FF_NO_IDCT_PERM;
334 #endif /* ALTIVEC_USE_REFERENCE_C_CODE */
335         }
336       }
337
338 #ifdef POWERPC_PERFORMANCE_REPORT
339         {
340           int i, j;
341           for (i = 0 ; i < powerpc_perf_total ; i++)
342           {
343             for (j = 0; j < POWERPC_NUM_PMC_ENABLED ; j++)
344               {
345                 perfdata[j][i][powerpc_data_min] = 0xFFFFFFFFFFFFFFFFULL;
346                 perfdata[j][i][powerpc_data_max] = 0x0000000000000000ULL;
347                 perfdata[j][i][powerpc_data_sum] = 0x0000000000000000ULL;
348                 perfdata[j][i][powerpc_data_num] = 0x0000000000000000ULL;
349               }
350           }
351         }
352 #endif /* POWERPC_PERFORMANCE_REPORT */
353     } else
354 #endif /* HAVE_ALTIVEC */
355     {
356         // Non-AltiVec PPC optimisations
357
358         // ... pending ...
359     }
360 }