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