checkasm.c
上传用户:hjq518
上传日期:2021-12-09
资源大小:5084k
文件大小:46k
源码类别:

Audio

开发平台:

Visual C++

  1. /*****************************************************************************
  2.  * checkasm.c: assembly check tool
  3.  *****************************************************************************
  4.  * Copyright (C) 2003-2008 x264 project
  5.  *
  6.  * Authors: Loren Merritt <lorenm@u.washington.edu>
  7.  *          Laurent Aimar <fenrir@via.ecp.fr>
  8.  *          Jason Garrett-Glaser <darkshikari@gmail.com>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. #include <ctype.h>
  25. #include <stdlib.h>
  26. #include <limits.h>
  27. #include <math.h>
  28. #include "common/common.h"
  29. #include "common/cpu.h"
  30. /* buf1, buf2: initialised to random data and shouldn't write into them */
  31. uint8_t * buf1, * buf2;
  32. /* buf3, buf4: used to store output */
  33. uint8_t * buf3, * buf4;
  34. int quiet = 0;
  35. #define report( name ) { 
  36.     if( used_asm && !quiet ) 
  37.         fprintf( stderr, " - %-21s [%s]n", name, ok ? "OK" : "FAILED" ); 
  38.     if( !ok ) ret = -1; 
  39. }
  40. #define BENCH_RUNS 100  // tradeoff between accuracy and speed
  41. #define BENCH_ALIGNS 16 // number of stack+heap data alignments (another accuracy vs speed tradeoff)
  42. #define MAX_FUNCS 1000  // just has to be big enough to hold all the existing functions
  43. #define MAX_CPUS 10     // number of different combinations of cpu flags
  44. typedef struct {
  45.     void *pointer; // just for detecting duplicates
  46.     uint32_t cpu;
  47.     uint32_t cycles;
  48.     uint32_t den;
  49. } bench_t;
  50. typedef struct {
  51.     char *name;
  52.     bench_t vers[MAX_CPUS];
  53. } bench_func_t;
  54. int do_bench = 0;
  55. int bench_pattern_len = 0;
  56. const char *bench_pattern = "";
  57. char func_name[100];
  58. static bench_func_t benchs[MAX_FUNCS];
  59. static const char *pixel_names[10] = { "16x16", "16x8", "8x16", "8x8", "8x4", "4x8", "4x4", "4x2", "2x4", "2x2" };
  60. static const char *intra_predict_16x16_names[7] = { "v", "h", "dc", "p", "dcl", "dct", "dc8" };
  61. static const char *intra_predict_8x8c_names[7] = { "dc", "h", "v", "p", "dcl", "dct", "dc8" };
  62. static const char *intra_predict_4x4_names[12] = { "v", "h", "dc", "ddl", "ddr", "vr", "hd", "vl", "hu", "dcl", "dct", "dc8" };
  63. static const char **intra_predict_8x8_names = intra_predict_4x4_names;
  64. #define set_func_name(...) snprintf( func_name, sizeof(func_name), __VA_ARGS__ )
  65. static inline uint32_t read_time(void)
  66. {
  67. #if defined(__GNUC__) && (defined(ARCH_X86) || defined(ARCH_X86_64))
  68.     uint32_t a;
  69.     asm volatile( "rdtsc" :"=a"(a) ::"edx" );
  70.     return a;
  71. #else
  72.     return 0;
  73. #endif
  74. }
  75. static bench_t* get_bench( const char *name, int cpu )
  76. {
  77.     int i, j;
  78.     for( i=0; benchs[i].name && strcmp(name, benchs[i].name); i++ )
  79.         assert( i < MAX_FUNCS );
  80.     if( !benchs[i].name )
  81.         benchs[i].name = strdup( name );
  82.     if( !cpu )
  83.         return &benchs[i].vers[0];
  84.     for( j=1; benchs[i].vers[j].cpu && benchs[i].vers[j].cpu != cpu; j++ )
  85.         assert( j < MAX_CPUS );
  86.     benchs[i].vers[j].cpu = cpu;
  87.     return &benchs[i].vers[j];
  88. }
  89. static int cmp_nop( const void *a, const void *b )
  90. {
  91.     return *(uint16_t*)a - *(uint16_t*)b;
  92. }
  93. static int cmp_bench( const void *a, const void *b )
  94. {
  95.     // asciibetical sort except preserving numbers
  96.     const char *sa = ((bench_func_t*)a)->name;
  97.     const char *sb = ((bench_func_t*)b)->name;
  98.     for(;; sa++, sb++)
  99.     {
  100.         if( !*sa && !*sb ) return 0;
  101.         if( isdigit(*sa) && isdigit(*sb) && isdigit(sa[1]) != isdigit(sb[1]) )
  102.             return isdigit(sa[1]) - isdigit(sb[1]);
  103.         if( *sa != *sb ) return *sa - *sb;
  104.     }
  105. }
  106. static void print_bench(void)
  107. {
  108.     uint16_t nops[10000] = {0};
  109.     int i, j, k, nfuncs, nop_time=0;
  110.     for( i=0; i<10000; i++ )
  111.     {
  112.         int t = read_time();
  113.         nops[i] = read_time() - t;
  114.     }
  115.     qsort( nops, 10000, sizeof(uint16_t), cmp_nop );
  116.     for( i=500; i<9500; i++ )
  117.         nop_time += nops[i];
  118.     nop_time /= 900;
  119.     printf( "nop: %dn", nop_time );
  120.     for( i=0; i<MAX_FUNCS && benchs[i].name; i++ );
  121.     nfuncs=i;
  122.     qsort( benchs, nfuncs, sizeof(bench_func_t), cmp_bench );
  123.     for( i=0; i<nfuncs; i++ )
  124.         for( j=0; j<MAX_CPUS && (!j || benchs[i].vers[j].cpu); j++ )
  125.         {
  126.             bench_t *b = &benchs[i].vers[j];
  127.             if( !b->den ) continue;
  128.             for( k=0; k<j && benchs[i].vers[k].pointer != b->pointer; k++ );
  129.             if( k<j ) continue;
  130.             printf( "%s_%s%s: %"PRId64"n", benchs[i].name,
  131.                     b->cpu&X264_CPU_PHADD_IS_FAST ? "phadd" :
  132.                     b->cpu&X264_CPU_SSSE3 ? "ssse3" :
  133.                     b->cpu&X264_CPU_SSE3 ? "sse3" :
  134.                     /* print sse2slow only if there's also a sse2fast version of the same func */
  135.                     b->cpu&X264_CPU_SSE2_IS_SLOW && j<MAX_CPUS && b[1].cpu&X264_CPU_SSE2_IS_FAST && !(b[1].cpu&X264_CPU_SSE3) ? "sse2slow" :
  136.                     b->cpu&X264_CPU_SSE2 ? "sse2" :
  137.                     b->cpu&X264_CPU_MMX ? "mmx" : "c",
  138.                     b->cpu&X264_CPU_CACHELINE_32 ? "_c32" :
  139.                     b->cpu&X264_CPU_CACHELINE_64 ? "_c64" : "",
  140.                     ((int64_t)10*b->cycles/b->den - nop_time)/4 );
  141.         }
  142. }
  143. #if defined(ARCH_X86) || defined(ARCH_X86_64)
  144. int x264_stack_pagealign( int (*func)(), int align );
  145. #else
  146. #define x264_stack_pagealign( func, align ) func()
  147. #endif
  148. #define call_c1(func,...) func(__VA_ARGS__)
  149. #ifdef ARCH_X86
  150. /* detect when callee-saved regs aren't saved.
  151.  * needs an explicit asm check because it only sometimes crashes in normal use. */
  152. long x264_checkasm_call( long (*func)(), int *ok, ... );
  153. #define call_a1(func,...) x264_checkasm_call((long(*)())func, &ok, __VA_ARGS__)
  154. #else
  155. #define call_a1 call_c1
  156. #endif
  157. #define call_bench(func,cpu,...)
  158.     if( do_bench && !strncmp(func_name, bench_pattern, bench_pattern_len) )
  159.     {
  160.         uint32_t tsum = 0;
  161.         int tcount = 0;
  162.         int ti;
  163.         call_a1(func, __VA_ARGS__);
  164.         for( ti=0; ti<(cpu?BENCH_RUNS:BENCH_RUNS/4); ti++ )
  165.         {
  166.             uint32_t t = read_time();
  167.             func(__VA_ARGS__);
  168.             func(__VA_ARGS__);
  169.             func(__VA_ARGS__);
  170.             func(__VA_ARGS__);
  171.             t = read_time() - t;
  172.             if( t*tcount <= tsum*4 && ti > 0 )
  173.             {
  174.                 tsum += t;
  175.                 tcount++;
  176.             }
  177.         }
  178.         bench_t *b = get_bench( func_name, cpu );
  179.         b->cycles += tsum;
  180.         b->den += tcount;
  181.         b->pointer = func;
  182.     }
  183. /* for most functions, run benchmark and correctness test at the same time.
  184.  * for those that modify their inputs, run the above macros separately */
  185. #define call_a(func,...) ({ call_a2(func,__VA_ARGS__); call_a1(func,__VA_ARGS__); })
  186. #define call_c(func,...) ({ call_c2(func,__VA_ARGS__); call_c1(func,__VA_ARGS__); })
  187. #define call_a2(func,...) ({ call_bench(func,cpu_new,__VA_ARGS__); })
  188. #define call_c2(func,...) ({ call_bench(func,0,__VA_ARGS__); })
  189. static int check_pixel( int cpu_ref, int cpu_new )
  190. {
  191.     x264_pixel_function_t pixel_c;
  192.     x264_pixel_function_t pixel_ref;
  193.     x264_pixel_function_t pixel_asm;
  194.     x264_predict_t predict_16x16[4+3];
  195.     x264_predict_t predict_8x8c[4+3];
  196.     x264_predict_t predict_4x4[9+3];
  197.     x264_predict8x8_t predict_8x8[9+3];
  198.     DECLARE_ALIGNED_16( uint8_t edge[33] );
  199.     uint16_t cost_mv[32];
  200.     int ret = 0, ok, used_asm;
  201.     int i, j;
  202.     x264_pixel_init( 0, &pixel_c );
  203.     x264_pixel_init( cpu_ref, &pixel_ref );
  204.     x264_pixel_init( cpu_new, &pixel_asm );
  205.     x264_predict_16x16_init( 0, predict_16x16 );
  206.     x264_predict_8x8c_init( 0, predict_8x8c );
  207.     x264_predict_8x8_init( 0, predict_8x8 );
  208.     x264_predict_4x4_init( 0, predict_4x4 );
  209.     x264_predict_8x8_filter( buf2+40, edge, ALL_NEIGHBORS, ALL_NEIGHBORS );
  210. #define TEST_PIXEL( name, align ) 
  211.     for( i = 0, ok = 1, used_asm = 0; i < 7; i++ ) 
  212.     { 
  213.         int res_c, res_asm; 
  214.         if( pixel_asm.name[i] != pixel_ref.name[i] ) 
  215.         { 
  216.             set_func_name( "%s_%s", #name, pixel_names[i] ); 
  217.             for( j=0; j<64; j++ ) 
  218.             { 
  219.                 used_asm = 1; 
  220.                 res_c   = call_c( pixel_c.name[i], buf1, 16, buf2+j*!align, 64 ); 
  221.                 res_asm = call_a( pixel_asm.name[i], buf1, 16, buf2+j*!align, 64 ); 
  222.                 if( res_c != res_asm ) 
  223.                 { 
  224.                     ok = 0; 
  225.                     fprintf( stderr, #name "[%d]: %d != %d [FAILED]n", i, res_c, res_asm ); 
  226.                     break; 
  227.                 } 
  228.             } 
  229.         } 
  230.     } 
  231.     report( "pixel " #name " :" );
  232.     TEST_PIXEL( sad, 0 );
  233.     TEST_PIXEL( sad_aligned, 1 );
  234.     TEST_PIXEL( ssd, 1 );
  235.     TEST_PIXEL( satd, 0 );
  236.     TEST_PIXEL( sa8d, 0 );
  237. #define TEST_PIXEL_X( N ) 
  238.     for( i = 0, ok = 1, used_asm = 0; i < 7; i++ ) 
  239.     { 
  240.         int res_c[4]={0}, res_asm[4]={0}; 
  241.         if( pixel_asm.sad_x##N[i] && pixel_asm.sad_x##N[i] != pixel_ref.sad_x##N[i] ) 
  242.         { 
  243.             set_func_name( "sad_x%d_%s", N, pixel_names[i] ); 
  244.             for( j=0; j<64; j++) 
  245.             { 
  246.                 uint8_t *pix2 = buf2+j; 
  247.                 used_asm = 1; 
  248.                 res_c[0] = pixel_c.sad[i]( buf1, 16, pix2, 64 ); 
  249.                 res_c[1] = pixel_c.sad[i]( buf1, 16, pix2+6, 64 ); 
  250.                 res_c[2] = pixel_c.sad[i]( buf1, 16, pix2+1, 64 ); 
  251.                 if(N==4) 
  252.                 { 
  253.                     res_c[3] = pixel_c.sad[i]( buf1, 16, pix2+10, 64 ); 
  254.                     call_a( pixel_asm.sad_x4[i], buf1, pix2, pix2+6, pix2+1, pix2+10, 64, res_asm ); 
  255.                 } 
  256.                 else 
  257.                     call_a( pixel_asm.sad_x3[i], buf1, pix2, pix2+6, pix2+1, 64, res_asm ); 
  258.                 if( memcmp(res_c, res_asm, sizeof(res_c)) ) 
  259.                 { 
  260.                     ok = 0; 
  261.                     fprintf( stderr, "sad_x"#N"[%d]: %d,%d,%d,%d != %d,%d,%d,%d [FAILED]n", 
  262.                              i, res_c[0], res_c[1], res_c[2], res_c[3], 
  263.                              res_asm[0], res_asm[1], res_asm[2], res_asm[3] ); 
  264.                 } 
  265.                 if(N==4) 
  266.                     call_c2( pixel_c.sad_x4[i], buf1, pix2, pix2+6, pix2+1, pix2+10, 64, res_asm ); 
  267.                 else 
  268.                     call_c2( pixel_c.sad_x3[i], buf1, pix2, pix2+6, pix2+1, 64, res_asm ); 
  269.             } 
  270.         } 
  271.     } 
  272.     report( "pixel sad_x"#N" :" );
  273.     TEST_PIXEL_X(3);
  274.     TEST_PIXEL_X(4);
  275. #define TEST_PIXEL_VAR( i ) 
  276.     if( pixel_asm.var[i] != pixel_ref.var[i] ) 
  277.     { 
  278.         uint32_t res_c, res_asm; 
  279.         uint32_t sad_c, sad_asm; 
  280.         set_func_name( "%s_%s", "var", pixel_names[i] ); 
  281.         used_asm = 1; 
  282.         res_c   = call_c( pixel_c.var[i], buf1, 16, &sad_c ); 
  283.         res_asm = call_a( pixel_asm.var[i], buf1, 16, &sad_asm ); 
  284.         if( (res_c != res_asm) || (sad_c != sad_asm) ) 
  285.         { 
  286.             ok = 0; 
  287.             fprintf( stderr, "var[%d]: %d,%d != %d,%d [FAILED]n", i, res_c, sad_c, res_asm, sad_asm ); 
  288.         } 
  289.     }
  290.     ok = 1; used_asm = 0;
  291.     TEST_PIXEL_VAR( PIXEL_16x16 );
  292.     TEST_PIXEL_VAR( PIXEL_8x8 );
  293.     report( "pixel var :" );
  294. #define TEST_INTRA_MBCMP( name, pred, satd, i8x8, ... ) 
  295.     if( pixel_asm.name && pixel_asm.name != pixel_ref.name ) 
  296.     { 
  297.         int res_c[3], res_asm[3]; 
  298.         set_func_name( #name );
  299.         used_asm = 1; 
  300.         memcpy( buf3, buf2, 1024 ); 
  301.         for( i=0; i<3; i++ ) 
  302.         { 
  303.             pred[i]( buf3+48, ##__VA_ARGS__ ); 
  304.             res_c[i] = pixel_c.satd( buf1+48, 16, buf3+48, 32 ); 
  305.         } 
  306.         call_a( pixel_asm.name, buf1+48, i8x8 ? edge : buf3+48, res_asm ); 
  307.         if( memcmp(res_c, res_asm, sizeof(res_c)) ) 
  308.         { 
  309.             ok = 0; 
  310.             fprintf( stderr, #name": %d,%d,%d != %d,%d,%d [FAILED]n", 
  311.                      res_c[0], res_c[1], res_c[2], 
  312.                      res_asm[0], res_asm[1], res_asm[2] ); 
  313.         } 
  314.     }
  315.     ok = 1; used_asm = 0;
  316.     TEST_INTRA_MBCMP( intra_satd_x3_16x16, predict_16x16, satd[PIXEL_16x16], 0 );
  317.     TEST_INTRA_MBCMP( intra_satd_x3_8x8c , predict_8x8c , satd[PIXEL_8x8]  , 0 );
  318.     TEST_INTRA_MBCMP( intra_satd_x3_4x4  , predict_4x4  , satd[PIXEL_4x4]  , 0 );
  319.     TEST_INTRA_MBCMP( intra_sa8d_x3_8x8  , predict_8x8  , sa8d[PIXEL_8x8]  , 1, edge );
  320.     report( "intra satd_x3 :" );
  321.     TEST_INTRA_MBCMP( intra_sad_x3_16x16 , predict_16x16, sad [PIXEL_16x16], 0 );
  322.     report( "intra sad_x3 :" );
  323.     if( pixel_asm.ssim_4x4x2_core != pixel_ref.ssim_4x4x2_core ||
  324.         pixel_asm.ssim_end4 != pixel_ref.ssim_end4 )
  325.     {
  326.         float res_c, res_a;
  327.         int sums[5][4] = {{0}};
  328.         used_asm = ok = 1;
  329.         x264_emms();
  330.         res_c = x264_pixel_ssim_wxh( &pixel_c,   buf1+2, 32, buf2+2, 32, 32, 28 );
  331.         res_a = x264_pixel_ssim_wxh( &pixel_asm, buf1+2, 32, buf2+2, 32, 32, 28 );
  332.         if( fabs(res_c - res_a) > 1e-6 )
  333.         {
  334.             ok = 0;
  335.             fprintf( stderr, "ssim: %.7f != %.7f [FAILED]n", res_c, res_a );
  336.         }
  337.         set_func_name( "ssim_core" );
  338.         call_c2( pixel_c.ssim_4x4x2_core,   buf1+2, 32, buf2+2, 32, sums );
  339.         call_a2( pixel_asm.ssim_4x4x2_core, buf1+2, 32, buf2+2, 32, sums );
  340.         set_func_name( "ssim_end" );
  341.         call_c2( pixel_c.ssim_end4,   sums, sums, 4 );
  342.         call_a2( pixel_asm.ssim_end4, sums, sums, 4 );
  343.         report( "ssim :" );
  344.     }
  345.     ok = 1; used_asm = 0;
  346.     for( i=0; i<32; i++ )
  347.         cost_mv[i] = i*10;
  348.     for( i=0; i<100 && ok; i++ )
  349.         if( pixel_asm.ads[i&3] != pixel_ref.ads[i&3] )
  350.         {
  351.             DECLARE_ALIGNED_16( uint16_t sums[72] );
  352.             DECLARE_ALIGNED_16( int dc[4] );
  353.             int16_t mvs_a[32], mvs_c[32];
  354.             int mvn_a, mvn_c;
  355.             int thresh = rand() & 0x3fff;
  356.             set_func_name( "esa_ads" );
  357.             for( j=0; j<72; j++ )
  358.                 sums[j] = rand() & 0x3fff;
  359.             for( j=0; j<4; j++ )
  360.                 dc[j] = rand() & 0x3fff;
  361.             used_asm = 1;
  362.             mvn_c = call_c( pixel_c.ads[i&3], dc, sums, 32, cost_mv, mvs_c, 28, thresh );
  363.             mvn_a = call_a( pixel_asm.ads[i&3], dc, sums, 32, cost_mv, mvs_a, 28, thresh );
  364.             if( mvn_c != mvn_a || memcmp( mvs_c, mvs_a, mvn_c*sizeof(*mvs_c) ) )
  365.             {
  366.                 ok = 0;
  367.                 printf("c%d: ", i&3);
  368.                 for(j=0; j<mvn_c; j++)
  369.                     printf("%d ", mvs_c[j]);
  370.                 printf("na%d: ", i&3);
  371.                 for(j=0; j<mvn_a; j++)
  372.                     printf("%d ", mvs_a[j]);
  373.                 printf("nn");
  374.             }
  375.         }
  376.     report( "esa ads:" );
  377.     return ret;
  378. }
  379. static int check_dct( int cpu_ref, int cpu_new )
  380. {
  381.     x264_dct_function_t dct_c;
  382.     x264_dct_function_t dct_ref;
  383.     x264_dct_function_t dct_asm;
  384.     x264_quant_function_t qf;
  385.     int ret = 0, ok, used_asm, i, interlace;
  386.     DECLARE_ALIGNED_16( int16_t dct1[16][4][4] );
  387.     DECLARE_ALIGNED_16( int16_t dct2[16][4][4] );
  388.     DECLARE_ALIGNED_16( int16_t dct4[16][4][4] );
  389.     DECLARE_ALIGNED_16( int16_t dct8[4][8][8] );
  390.     x264_t h_buf;
  391.     x264_t *h = &h_buf;
  392.     x264_dct_init( 0, &dct_c );
  393.     x264_dct_init( cpu_ref, &dct_ref);
  394.     x264_dct_init( cpu_new, &dct_asm );
  395.     memset( h, 0, sizeof(*h) );
  396.     h->pps = h->pps_array;
  397.     x264_param_default( &h->param );
  398.     h->param.analyse.i_luma_deadzone[0] = 0;
  399.     h->param.analyse.i_luma_deadzone[1] = 0;
  400.     h->param.analyse.b_transform_8x8 = 1;
  401.     for( i=0; i<6; i++ )
  402.         h->pps->scaling_list[i] = x264_cqm_flat16;
  403.     x264_cqm_init( h );
  404.     x264_quant_init( h, 0, &qf );
  405. #define TEST_DCT( name, t1, t2, size ) 
  406.     if( dct_asm.name != dct_ref.name ) 
  407.     { 
  408.         set_func_name( #name );
  409.         used_asm = 1; 
  410.         call_c( dct_c.name, t1, buf1, buf2 ); 
  411.         call_a( dct_asm.name, t2, buf1, buf2 ); 
  412.         if( memcmp( t1, t2, size ) ) 
  413.         { 
  414.             ok = 0; 
  415.             fprintf( stderr, #name " [FAILED]n" ); 
  416.         } 
  417.     }
  418.     ok = 1; used_asm = 0;
  419.     TEST_DCT( sub4x4_dct, dct1[0], dct2[0], 16*2 );
  420.     TEST_DCT( sub8x8_dct, dct1, dct2, 16*2*4 );
  421.     TEST_DCT( sub16x16_dct, dct1, dct2, 16*2*16 );
  422.     report( "sub_dct4 :" );
  423.     ok = 1; used_asm = 0;
  424.     TEST_DCT( sub8x8_dct8, (void*)dct1[0], (void*)dct2[0], 64*2 );
  425.     TEST_DCT( sub16x16_dct8, (void*)dct1, (void*)dct2, 64*2*4 );
  426.     report( "sub_dct8 :" );
  427. #undef TEST_DCT
  428.     // fdct and idct are denormalized by different factors, so quant/dequant
  429.     // is needed to force the coefs into the right range.
  430.     dct_c.sub16x16_dct( dct4, buf1, buf2 );
  431.     dct_c.sub16x16_dct8( dct8, buf1, buf2 );
  432.     for( i=0; i<16; i++ )
  433.     {
  434.         qf.quant_4x4( dct4[i], h->quant4_mf[CQM_4IY][20], h->quant4_bias[CQM_4IY][20] );
  435.         qf.dequant_4x4( dct4[i], h->dequant4_mf[CQM_4IY], 20 );
  436.     }
  437.     for( i=0; i<4; i++ )
  438.     {
  439.         qf.quant_8x8( dct8[i], h->quant8_mf[CQM_8IY][20], h->quant8_bias[CQM_8IY][20] );
  440.         qf.dequant_8x8( dct8[i], h->dequant8_mf[CQM_8IY], 20 );
  441.     }
  442. #define TEST_IDCT( name, src ) 
  443.     if( dct_asm.name != dct_ref.name ) 
  444.     { 
  445.         set_func_name( #name );
  446.         used_asm = 1; 
  447.         memcpy( buf3, buf1, 32*32 ); 
  448.         memcpy( buf4, buf1, 32*32 ); 
  449.         memcpy( dct1, src, 512 ); 
  450.         memcpy( dct2, src, 512 ); 
  451.         call_c1( dct_c.name, buf3, (void*)dct1 ); 
  452.         call_a1( dct_asm.name, buf4, (void*)dct2 ); 
  453.         if( memcmp( buf3, buf4, 32*32 ) ) 
  454.         { 
  455.             ok = 0; 
  456.             fprintf( stderr, #name " [FAILED]n" ); 
  457.         } 
  458.         call_c2( dct_c.name, buf3, (void*)dct1 ); 
  459.         call_a2( dct_asm.name, buf4, (void*)dct2 ); 
  460.     }
  461.     ok = 1; used_asm = 0;
  462.     TEST_IDCT( add4x4_idct, dct4 );
  463.     TEST_IDCT( add8x8_idct, dct4 );
  464.     TEST_IDCT( add16x16_idct, dct4 );
  465.     report( "add_idct4 :" );
  466.     ok = 1; used_asm = 0;
  467.     TEST_IDCT( add8x8_idct8, dct8 );
  468.     TEST_IDCT( add16x16_idct8, dct8 );
  469.     report( "add_idct8 :" );
  470. #undef TEST_IDCT
  471.     ok = 1; used_asm = 0;
  472.     if( dct_asm.dct4x4dc != dct_ref.dct4x4dc )
  473.     {
  474.         DECLARE_ALIGNED_16( int16_t dct1[4][4] ) = {{-12, 42, 23, 67},{2, 90, 89,56},{67,43,-76,91},{56,-78,-54,1}};
  475.         DECLARE_ALIGNED_16( int16_t dct2[4][4] ) = {{-12, 42, 23, 67},{2, 90, 89,56},{67,43,-76,91},{56,-78,-54,1}};
  476.         set_func_name( "dct4x4dc" );
  477.         used_asm = 1;
  478.         call_c1( dct_c.dct4x4dc, dct1 );
  479.         call_a1( dct_asm.dct4x4dc, dct2 );
  480.         if( memcmp( dct1, dct2, 32 ) )
  481.         {
  482.             ok = 0;
  483.             fprintf( stderr, " - dct4x4dc :        [FAILED]n" );
  484.         }
  485.         call_c2( dct_c.dct4x4dc, dct1 );
  486.         call_a2( dct_asm.dct4x4dc, dct2 );
  487.     }
  488.     if( dct_asm.idct4x4dc != dct_ref.idct4x4dc )
  489.     {
  490.         DECLARE_ALIGNED_16( int16_t dct1[4][4] ) = {{-12, 42, 23, 67},{2, 90, 89,56},{67,43,-76,91},{56,-78,-54,1}};
  491.         DECLARE_ALIGNED_16( int16_t dct2[4][4] ) = {{-12, 42, 23, 67},{2, 90, 89,56},{67,43,-76,91},{56,-78,-54,1}};
  492.         set_func_name( "idct4x4dc" );
  493.         used_asm = 1;
  494.         call_c1( dct_c.idct4x4dc, dct1 );
  495.         call_a1( dct_asm.idct4x4dc, dct2 );
  496.         if( memcmp( dct1, dct2, 32 ) )
  497.         {
  498.             ok = 0;
  499.             fprintf( stderr, " - idct4x4dc :        [FAILED]n" );
  500.         }
  501.         call_c2( dct_c.idct4x4dc, dct1 );
  502.         call_a2( dct_asm.idct4x4dc, dct2 );
  503.     }
  504.     report( "(i)dct4x4dc :" );
  505.     ok = 1; used_asm = 0;
  506.     if( dct_asm.dct2x2dc != dct_ref.dct2x2dc )
  507.     {
  508.         DECLARE_ALIGNED_16( int16_t dct1[2][2] ) = {{-12, 42},{2, 90}};
  509.         DECLARE_ALIGNED_16( int16_t dct2[2][2] ) = {{-12, 42},{2, 90}};
  510.         set_func_name( "dct2x2dc" );
  511.         used_asm = 1;
  512.         call_c( dct_c.dct2x2dc, dct1 );
  513.         call_a( dct_asm.dct2x2dc, dct2 );
  514.         if( memcmp( dct1, dct2, 4*2 ) )
  515.         {
  516.             ok = 0;
  517.             fprintf( stderr, " - dct2x2dc :        [FAILED]n" );
  518.         }
  519.     }
  520.     if( dct_asm.idct2x2dc != dct_ref.idct2x2dc )
  521.     {
  522.         DECLARE_ALIGNED_16( int16_t dct1[2][2] ) = {{-12, 42},{2, 90}};
  523.         DECLARE_ALIGNED_16( int16_t dct2[2][2] ) = {{-12, 42},{2, 90}};
  524.         set_func_name( "idct2x2dc" );
  525.         used_asm = 1;
  526.         call_c( dct_c.idct2x2dc, dct1 );
  527.         call_a( dct_asm.idct2x2dc, dct2 );
  528.         if( memcmp( dct1, dct2, 4*2 ) )
  529.         {
  530.             ok = 0;
  531.             fprintf( stderr, " - idct2x2dc :       [FAILED]n" );
  532.         }
  533.     }
  534.     report( "(i)dct2x2dc :" );
  535.     x264_zigzag_function_t zigzag_c;
  536.     x264_zigzag_function_t zigzag_ref;
  537.     x264_zigzag_function_t zigzag_asm;
  538.     DECLARE_ALIGNED_16( int16_t level1[64] );
  539.     DECLARE_ALIGNED_16( int16_t level2[64] );
  540. #define TEST_ZIGZAG_SCAN( name, t1, t2, dct, size )   
  541.     if( zigzag_asm.name != zigzag_ref.name ) 
  542.     { 
  543.         set_func_name( "zigzag_"#name"_%s", interlace?"field":"frame" );
  544.         used_asm = 1; 
  545.         memcpy(dct, buf1, size*sizeof(int16_t));
  546.         call_c( zigzag_c.name, t1, dct ); 
  547.         call_a( zigzag_asm.name, t2, dct ); 
  548.         if( memcmp( t1, t2, size*sizeof(int16_t) ) ) 
  549.         { 
  550.             ok = 0; 
  551.             fprintf( stderr, #name " [FAILED]n" ); 
  552.         } 
  553.     }
  554. #define TEST_ZIGZAG_SUB( name, t1, t2, size ) 
  555.     if( zigzag_asm.name != zigzag_ref.name ) 
  556.     { 
  557.         set_func_name( "zigzag_"#name"_%s", interlace?"field":"frame" );
  558.         used_asm = 1; 
  559.         memcpy( buf3, buf1, 16*FDEC_STRIDE ); 
  560.         memcpy( buf4, buf1, 16*FDEC_STRIDE ); 
  561.         call_c1( zigzag_c.name, t1, buf2, buf3 );  
  562.         call_a1( zigzag_asm.name, t2, buf2, buf4 ); 
  563.         if( memcmp( t1, t2, size*sizeof(int16_t) )|| memcmp( buf3, buf4, 16*FDEC_STRIDE ) )  
  564.         { 
  565.             ok = 0; 
  566.             fprintf( stderr, #name " [FAILED]n" ); 
  567.         } 
  568.         call_c2( zigzag_c.name, t1, buf2, buf3 );  
  569.         call_a2( zigzag_asm.name, t2, buf2, buf4 ); 
  570.     }
  571.     interlace = 0;
  572.     x264_zigzag_init( 0, &zigzag_c, 0 );
  573.     x264_zigzag_init( cpu_ref, &zigzag_ref, 0 );
  574.     x264_zigzag_init( cpu_new, &zigzag_asm, 0 );
  575.     ok = 1; used_asm = 0;
  576.     TEST_ZIGZAG_SCAN( scan_8x8, level1, level2, (void*)dct1, 64 );
  577.     TEST_ZIGZAG_SCAN( scan_4x4, level1, level2, dct1[0], 16  );
  578.     TEST_ZIGZAG_SUB( sub_4x4, level1, level2, 16 );
  579.     report( "zigzag_frame :" );
  580.     interlace = 1;
  581.     x264_zigzag_init( 0, &zigzag_c, 1 );
  582.     x264_zigzag_init( cpu_ref, &zigzag_ref, 1 );
  583.     x264_zigzag_init( cpu_new, &zigzag_asm, 1 );
  584.     ok = 1; used_asm = 0;
  585.     TEST_ZIGZAG_SCAN( scan_8x8, level1, level2, (void*)dct1, 64 );
  586.     TEST_ZIGZAG_SCAN( scan_4x4, level1, level2, dct1[0], 16  );
  587.     TEST_ZIGZAG_SUB( sub_4x4, level1, level2, 16 );
  588.     report( "zigzag_field :" );
  589. #undef TEST_ZIGZAG_SCAN
  590. #undef TEST_ZIGZAG_SUB
  591.     return ret;
  592. }
  593. static int check_mc( int cpu_ref, int cpu_new )
  594. {
  595.     x264_mc_functions_t mc_c;
  596.     x264_mc_functions_t mc_ref;
  597.     x264_mc_functions_t mc_a;
  598.     x264_pixel_function_t pixel;
  599.     uint8_t *src     = &buf1[2*32+2];
  600.     uint8_t *src2[4] = { &buf1[3*64+2], &buf1[5*64+2],
  601.                          &buf1[7*64+2], &buf1[9*64+2] };
  602.     uint8_t *dst1    = buf3;
  603.     uint8_t *dst2    = buf4;
  604.     int dx, dy, i, j, k, w;
  605.     int ret = 0, ok, used_asm;
  606.     x264_mc_init( 0, &mc_c );
  607.     x264_mc_init( cpu_ref, &mc_ref );
  608.     x264_mc_init( cpu_new, &mc_a );
  609.     x264_pixel_init( 0, &pixel );
  610. #define MC_TEST_LUMA( w, h ) 
  611.         if( mc_a.mc_luma != mc_ref.mc_luma && !(w&(w-1)) && h<=16 ) 
  612.         { 
  613.             set_func_name( "mc_luma_%dx%d", w, h );
  614.             used_asm = 1; 
  615.             memset(buf3, 0xCD, 1024); 
  616.             memset(buf4, 0xCD, 1024); 
  617.             call_c( mc_c.mc_luma, dst1, 32, src2, 64, dx, dy, w, h ); 
  618.             call_a( mc_a.mc_luma, dst2, 32, src2, 64, dx, dy, w, h ); 
  619.             if( memcmp( buf3, buf4, 1024 ) ) 
  620.             { 
  621.                 fprintf( stderr, "mc_luma[mv(%d,%d) %2dx%-2d]     [FAILED]n", dx, dy, w, h ); 
  622.                 ok = 0; 
  623.             } 
  624.         } 
  625.         if( mc_a.get_ref != mc_ref.get_ref ) 
  626.         { 
  627.             uint8_t *ref = dst2; 
  628.             int ref_stride = 32; 
  629.             set_func_name( "get_ref_%dx%d", w, h );
  630.             used_asm = 1; 
  631.             memset(buf3, 0xCD, 1024); 
  632.             memset(buf4, 0xCD, 1024); 
  633.             call_c( mc_c.mc_luma, dst1, 32, src2, 64, dx, dy, w, h ); 
  634.             ref = (uint8_t*) call_a( mc_a.get_ref, ref, &ref_stride, src2, 64, dx, dy, w, h ); 
  635.             for( i=0; i<h; i++ ) 
  636.                 if( memcmp( dst1+i*32, ref+i*ref_stride, w ) ) 
  637.                 { 
  638.                     fprintf( stderr, "get_ref[mv(%d,%d) %2dx%-2d]     [FAILED]n", dx, dy, w, h ); 
  639.                     ok = 0; 
  640.                     break; 
  641.                 } 
  642.         }
  643. #define MC_TEST_CHROMA( w, h ) 
  644.         if( mc_a.mc_chroma != mc_ref.mc_chroma ) 
  645.         { 
  646.             set_func_name( "mc_chroma_%dx%d", w, h );
  647.             used_asm = 1; 
  648.             memset(buf3, 0xCD, 1024); 
  649.             memset(buf4, 0xCD, 1024); 
  650.             call_c( mc_c.mc_chroma, dst1, 16, src, 32, dx, dy, w, h ); 
  651.             call_a( mc_a.mc_chroma, dst2, 16, src, 32, dx, dy, w, h ); 
  652.             /* mc_chroma width=2 may write garbage to the right of dst. ignore that. */
  653.             for( j=0; j<h; j++ ) 
  654.                 for( i=w; i<4; i++ ) 
  655.                     dst2[i+j*16] = dst1[i+j*16]; 
  656.             if( memcmp( buf3, buf4, 1024 ) ) 
  657.             { 
  658.                 fprintf( stderr, "mc_chroma[mv(%d,%d) %2dx%-2d]     [FAILED]n", dx, dy, w, h ); 
  659.                 ok = 0; 
  660.             } 
  661.         }
  662.     ok = 1; used_asm = 0;
  663.     for( dy = -8; dy < 8; dy++ )
  664.         for( dx = -128; dx < 128; dx++ )
  665.         {
  666.             if( rand()&15 ) continue; // running all of them is too slow
  667.             MC_TEST_LUMA( 20, 18 );
  668.             MC_TEST_LUMA( 16, 16 );
  669.             MC_TEST_LUMA( 16, 8 );
  670.             MC_TEST_LUMA( 12, 10 );
  671.             MC_TEST_LUMA( 8, 16 );
  672.             MC_TEST_LUMA( 8, 8 );
  673.             MC_TEST_LUMA( 8, 4 );
  674.             MC_TEST_LUMA( 4, 8 );
  675.             MC_TEST_LUMA( 4, 4 );
  676.         }
  677.     report( "mc luma :" );
  678.     ok = 1; used_asm = 0;
  679.     for( dy = -1; dy < 9; dy++ )
  680.         for( dx = -1; dx < 9; dx++ )
  681.         {
  682.             MC_TEST_CHROMA( 8, 8 );
  683.             MC_TEST_CHROMA( 8, 4 );
  684.             MC_TEST_CHROMA( 4, 8 );
  685.             MC_TEST_CHROMA( 4, 4 );
  686.             MC_TEST_CHROMA( 4, 2 );
  687.             MC_TEST_CHROMA( 2, 4 );
  688.             MC_TEST_CHROMA( 2, 2 );
  689.         }
  690.     report( "mc chroma :" );
  691. #undef MC_TEST_LUMA
  692. #undef MC_TEST_CHROMA
  693. #define MC_TEST_AVG( name, ... ) 
  694.     for( i = 0, ok = 1, used_asm = 0; i < 10; i++ ) 
  695.     { 
  696.         memcpy( buf3, buf1, 1024 ); 
  697.         memcpy( buf4, buf1, 1024 ); 
  698.         if( mc_a.name[i] != mc_ref.name[i] ) 
  699.         { 
  700.             set_func_name( "%s_%s", #name, pixel_names[i] );
  701.             used_asm = 1; 
  702.             call_c1( mc_c.name[i], buf3, 32, buf2, 16, ##__VA_ARGS__ ); 
  703.             call_a1( mc_a.name[i], buf4, 32, buf2, 16, ##__VA_ARGS__ ); 
  704.             if( memcmp( buf3, buf4, 1024 ) )               
  705.             { 
  706.                 ok = 0; 
  707.                 fprintf( stderr, #name "[%d]: [FAILED]n", i ); 
  708.             } 
  709.             call_c2( mc_c.name[i], buf3, 32, buf2, 16, ##__VA_ARGS__ ); 
  710.             call_a2( mc_a.name[i], buf4, 32, buf2, 16, ##__VA_ARGS__ ); 
  711.         } 
  712.     }
  713.     MC_TEST_AVG( avg );
  714.     report( "mc avg :" );
  715.     ok = 1; used_asm = 0;
  716.     for( w = -64; w <= 128 && ok; w++ )
  717.         MC_TEST_AVG( avg_weight, w );
  718.     report( "mc wpredb :" );
  719.     if( mc_a.hpel_filter != mc_ref.hpel_filter )
  720.     {
  721.         uint8_t *src = buf1+8+2*64;
  722.         uint8_t *dstc[3] = { buf3+8, buf3+8+16*64, buf3+8+32*64 };
  723.         uint8_t *dsta[3] = { buf4+8, buf4+8+16*64, buf4+8+32*64 };
  724.         set_func_name( "hpel_filter" );
  725.         ok = 1; used_asm = 1;
  726.         memset( buf3, 0, 4096 );
  727.         memset( buf4, 0, 4096 );
  728.         call_c( mc_c.hpel_filter, dstc[0], dstc[1], dstc[2], src, 64, 48, 10 );
  729.         call_a( mc_a.hpel_filter, dsta[0], dsta[1], dsta[2], src, 64, 48, 10 );
  730.         for( i=0; i<3; i++ )
  731.             for( j=0; j<10; j++ )
  732.                 //FIXME ideally the first pixels would match too, but they aren't actually used
  733.                 if( memcmp( dstc[i]+j*64+2, dsta[i]+j*64+2, 43 ) )
  734.                 {
  735.                     ok = 0;
  736.                     fprintf( stderr, "hpel filter differs at plane %c line %dn", "hvc"[i], j );
  737.                     for( k=0; k<48; k++ )
  738.                         printf("%02x%s", dstc[i][j*64+k], (k+1)&3 ? "" : " ");
  739.                     printf("n");
  740.                     for( k=0; k<48; k++ )
  741.                         printf("%02x%s", dsta[i][j*64+k], (k+1)&3 ? "" : " ");
  742.                     printf("n");
  743.                     break;
  744.                 }
  745.         report( "hpel filter :" );
  746.     }
  747.     if( mc_a.frame_init_lowres_core != mc_ref.frame_init_lowres_core )
  748.     {
  749.         uint8_t *dstc[4] = { buf3, buf3+1024, buf3+2048, buf3+3072 };
  750.         uint8_t *dsta[4] = { buf4, buf4+1024, buf4+2048, buf3+3072 };
  751.         set_func_name( "lowres_init" );
  752.         for( w=40; w<=48; w+=8 )
  753.             if( mc_a.frame_init_lowres_core != mc_ref.frame_init_lowres_core )
  754.             {
  755.                 int stride = (w+8)&~15;
  756.                 used_asm = 1;
  757.                 call_c( mc_c.frame_init_lowres_core, buf1, dstc[0], dstc[1], dstc[2], dstc[3], w*2, stride, w, 16 );
  758.                 call_a( mc_a.frame_init_lowres_core, buf1, dsta[0], dsta[1], dsta[2], dsta[3], w*2, stride, w, 16 );
  759.                 for( i=0; i<16; i++)
  760.                 {
  761.                     for( j=0; j<4; j++)
  762.                         if( memcmp( dstc[j]+i*stride, dsta[j]+i*stride, w ) )
  763.                         {
  764.                             ok = 0;
  765.                             fprintf( stderr, "frame_init_lowres differs at plane %d line %dn", j, i );
  766.                             for( k=0; k<w; k++ )
  767.                                 printf( "%d ", dstc[j][k+i*stride] );
  768.                             printf("n");
  769.                             for( k=0; k<w; k++ )
  770.                                 printf( "%d ", dsta[j][k+i*stride] );
  771.                             printf("n");
  772.                             break;
  773.                         }
  774.                 }
  775.             }
  776.         report( "lowres init :" );
  777.     }
  778.     return ret;
  779. }
  780. static int check_deblock( int cpu_ref, int cpu_new )
  781. {
  782.     x264_deblock_function_t db_c;
  783.     x264_deblock_function_t db_ref;
  784.     x264_deblock_function_t db_a;
  785.     int ret = 0, ok = 1, used_asm = 0;
  786.     int alphas[36], betas[36];
  787.     int8_t tcs[36][4];
  788.     int a, c, i, j;
  789.     x264_deblock_init( 0, &db_c );
  790.     x264_deblock_init( cpu_ref, &db_ref );
  791.     x264_deblock_init( cpu_new, &db_a );
  792.     /* not exactly the real values of a,b,tc but close enough */
  793.     a = 255; c = 250;
  794.     for( i = 35; i >= 0; i-- )
  795.     {
  796.         alphas[i] = a;
  797.         betas[i] = (i+1)/2;
  798.         tcs[i][0] = tcs[i][2] = (c+6)/10;
  799.         tcs[i][1] = tcs[i][3] = (c+9)/20;
  800.         a = a*9/10;
  801.         c = c*9/10;
  802.     }
  803. #define TEST_DEBLOCK( name, align, ... ) 
  804.     for( i = 0; i < 36; i++ ) 
  805.     { 
  806.         int off = 8*32 + (i&15)*4*!align; /* benchmark various alignments of h filter */
  807.         for( j = 0; j < 1024; j++ ) 
  808.             /* two distributions of random to excersize different failure modes */
  809.             buf3[j] = rand() & (i&1 ? 0xf : 0xff ); 
  810.         memcpy( buf4, buf3, 1024 ); 
  811.         if( db_a.name != db_ref.name ) 
  812.         { 
  813.             set_func_name( #name );
  814.             used_asm = 1; 
  815.             call_c1( db_c.name, buf3+off, 32, alphas[i], betas[i], ##__VA_ARGS__ ); 
  816.             call_a1( db_a.name, buf4+off, 32, alphas[i], betas[i], ##__VA_ARGS__ ); 
  817.             if( memcmp( buf3, buf4, 1024 ) ) 
  818.             { 
  819.                 ok = 0; 
  820.                 fprintf( stderr, #name "(a=%d, b=%d): [FAILED]n", alphas[i], betas[i] ); 
  821.                 break; 
  822.             } 
  823.             call_c2( db_c.name, buf3+off, 32, alphas[i], betas[i], ##__VA_ARGS__ ); 
  824.             call_a2( db_a.name, buf4+off, 32, alphas[i], betas[i], ##__VA_ARGS__ ); 
  825.         } 
  826.     }
  827.     TEST_DEBLOCK( deblock_h_luma, 0, tcs[i] );
  828.     TEST_DEBLOCK( deblock_v_luma, 1, tcs[i] );
  829.     TEST_DEBLOCK( deblock_h_chroma, 0, tcs[i] );
  830.     TEST_DEBLOCK( deblock_v_chroma, 1, tcs[i] );
  831.     TEST_DEBLOCK( deblock_h_luma_intra, 0 );
  832.     TEST_DEBLOCK( deblock_v_luma_intra, 1 );
  833.     TEST_DEBLOCK( deblock_h_chroma_intra, 0 );
  834.     TEST_DEBLOCK( deblock_v_chroma_intra, 1 );
  835.     report( "deblock :" );
  836.     return ret;
  837. }
  838. static int check_quant( int cpu_ref, int cpu_new )
  839. {
  840.     x264_quant_function_t qf_c;
  841.     x264_quant_function_t qf_ref;
  842.     x264_quant_function_t qf_a;
  843.     DECLARE_ALIGNED_16( int16_t dct1[64] );
  844.     DECLARE_ALIGNED_16( int16_t dct2[64] );
  845.     DECLARE_ALIGNED_16( uint8_t cqm_buf[64] );
  846.     int ret = 0, ok, used_asm;
  847.     int oks[2] = {1,1}, used_asms[2] = {0,0};
  848.     int i, i_cqm, qp;
  849.     x264_t h_buf;
  850.     x264_t *h = &h_buf;
  851.     memset( h, 0, sizeof(*h) );
  852.     h->pps = h->pps_array;
  853.     x264_param_default( &h->param );
  854.     h->param.rc.i_qp_min = 26;
  855.     h->param.analyse.b_transform_8x8 = 1;
  856.     for( i_cqm = 0; i_cqm < 4; i_cqm++ )
  857.     {
  858.         if( i_cqm == 0 )
  859.         {
  860.             for( i = 0; i < 6; i++ )
  861.                 h->pps->scaling_list[i] = x264_cqm_flat16;
  862.             h->param.i_cqm_preset = h->pps->i_cqm_preset = X264_CQM_FLAT;
  863.         }
  864.         else if( i_cqm == 1 )
  865.         {
  866.             for( i = 0; i < 6; i++ )
  867.                 h->pps->scaling_list[i] = x264_cqm_jvt[i];
  868.             h->param.i_cqm_preset = h->pps->i_cqm_preset = X264_CQM_JVT;
  869.         }
  870.         else
  871.         {
  872.             if( i_cqm == 2 )
  873.                 for( i = 0; i < 64; i++ )
  874.                     cqm_buf[i] = 10 + rand() % 246;
  875.             else
  876.                 for( i = 0; i < 64; i++ )
  877.                     cqm_buf[i] = 1;
  878.             for( i = 0; i < 6; i++ )
  879.                 h->pps->scaling_list[i] = cqm_buf;
  880.             h->param.i_cqm_preset = h->pps->i_cqm_preset = X264_CQM_CUSTOM;
  881.         }
  882.         x264_cqm_init( h );
  883.         x264_quant_init( h, 0, &qf_c );
  884.         x264_quant_init( h, cpu_ref, &qf_ref );
  885.         x264_quant_init( h, cpu_new, &qf_a );
  886. #define INIT_QUANT8() 
  887.         { 
  888.             static const int scale1d[8] = {32,31,24,31,32,31,24,31}; 
  889.             int x, y; 
  890.             for( y = 0; y < 8; y++ ) 
  891.                 for( x = 0; x < 8; x++ ) 
  892.                 { 
  893.                     unsigned int scale = (255*scale1d[y]*scale1d[x])/16; 
  894.                     dct1[y*8+x] = dct2[y*8+x] = (rand()%(2*scale+1))-scale; 
  895.                 } 
  896.         }
  897. #define INIT_QUANT4() 
  898.         { 
  899.             static const int scale1d[4] = {4,6,4,6}; 
  900.             int x, y; 
  901.             for( y = 0; y < 4; y++ ) 
  902.                 for( x = 0; x < 4; x++ ) 
  903.                 { 
  904.                     unsigned int scale = 255*scale1d[y]*scale1d[x]; 
  905.                     dct1[y*4+x] = dct2[y*4+x] = (rand()%(2*scale+1))-scale; 
  906.                 } 
  907.         }
  908. #define TEST_QUANT_DC( name, cqm ) 
  909.         if( qf_a.name != qf_ref.name ) 
  910.         { 
  911.             set_func_name( #name ); 
  912.             used_asms[0] = 1; 
  913.             for( qp = 51; qp > 0; qp-- ) 
  914.             { 
  915.                 for( i = 0; i < 16; i++ ) 
  916.                     dct1[i] = dct2[i] = (rand() & 0x1fff) - 0xfff; 
  917.                 call_c1( qf_c.name, (void*)dct1, h->quant4_mf[CQM_4IY][qp][0], h->quant4_bias[CQM_4IY][qp][0] ); 
  918.                 call_a1( qf_a.name, (void*)dct2, h->quant4_mf[CQM_4IY][qp][0], h->quant4_bias[CQM_4IY][qp][0] ); 
  919.                 if( memcmp( dct1, dct2, 16*2 ) )       
  920.                 { 
  921.                     oks[0] = 0; 
  922.                     fprintf( stderr, #name "(cqm=%d): [FAILED]n", i_cqm ); 
  923.                     break; 
  924.                 } 
  925.                 call_c2( qf_c.name, (void*)dct1, h->quant4_mf[CQM_4IY][qp][0], h->quant4_bias[CQM_4IY][qp][0] ); 
  926.                 call_a2( qf_a.name, (void*)dct2, h->quant4_mf[CQM_4IY][qp][0], h->quant4_bias[CQM_4IY][qp][0] ); 
  927.             } 
  928.         }
  929. #define TEST_QUANT( qname, block, w ) 
  930.         if( qf_a.qname != qf_ref.qname ) 
  931.         { 
  932.             set_func_name( #qname ); 
  933.             used_asms[0] = 1; 
  934.             for( qp = 51; qp > 0; qp-- ) 
  935.             { 
  936.                 INIT_QUANT##w() 
  937.                 call_c1( qf_c.qname, (void*)dct1, h->quant##w##_mf[block][qp], h->quant##w##_bias[block][qp] ); 
  938.                 call_a1( qf_a.qname, (void*)dct2, h->quant##w##_mf[block][qp], h->quant##w##_bias[block][qp] ); 
  939.                 if( memcmp( dct1, dct2, w*w*2 ) ) 
  940.                 { 
  941.                     oks[0] = 0; 
  942.                     fprintf( stderr, #qname "(qp=%d, cqm=%d, block="#block"): [FAILED]n", qp, i_cqm ); 
  943.                     break; 
  944.                 } 
  945.                 call_c2( qf_c.qname, (void*)dct1, h->quant##w##_mf[block][qp], h->quant##w##_bias[block][qp] ); 
  946.                 call_a2( qf_a.qname, (void*)dct2, h->quant##w##_mf[block][qp], h->quant##w##_bias[block][qp] ); 
  947.             } 
  948.         }
  949.         TEST_QUANT( quant_8x8, CQM_8IY, 8 );
  950.         TEST_QUANT( quant_8x8, CQM_8PY, 8 );
  951.         TEST_QUANT( quant_4x4, CQM_4IY, 4 );
  952.         TEST_QUANT( quant_4x4, CQM_4PY, 4 );
  953.         TEST_QUANT_DC( quant_4x4_dc, **h->quant4_mf[CQM_4IY] );
  954.         TEST_QUANT_DC( quant_2x2_dc, **h->quant4_mf[CQM_4IC] );
  955. #define TEST_DEQUANT( qname, dqname, block, w ) 
  956.         if( qf_a.dqname != qf_ref.dqname ) 
  957.         { 
  958.             set_func_name( "%s_%s", #dqname, i_cqm?"cqm":"flat" ); 
  959.             used_asms[1] = 1; 
  960.             for( qp = 51; qp > 0; qp-- ) 
  961.             { 
  962.                 INIT_QUANT##w() 
  963.                 call_c( qf_c.qname, (void*)dct1, h->quant##w##_mf[block][qp], h->quant##w##_bias[block][qp] ); 
  964.                 memcpy( dct2, dct1, w*w*2 ); 
  965.                 call_c1( qf_c.dqname, (void*)dct1, h->dequant##w##_mf[block], qp ); 
  966.                 call_a1( qf_a.dqname, (void*)dct2, h->dequant##w##_mf[block], qp ); 
  967.                 if( memcmp( dct1, dct2, w*w*2 ) ) 
  968.                 { 
  969.                     oks[1] = 0; 
  970.                     fprintf( stderr, #dqname "(qp=%d, cqm=%d, block="#block"): [FAILED]n", qp, i_cqm ); 
  971.                     break; 
  972.                 } 
  973.                 call_c2( qf_c.dqname, (void*)dct1, h->dequant##w##_mf[block], qp ); 
  974.                 call_a2( qf_a.dqname, (void*)dct2, h->dequant##w##_mf[block], qp ); 
  975.             } 
  976.         }
  977.         TEST_DEQUANT( quant_8x8, dequant_8x8, CQM_8IY, 8 );
  978.         TEST_DEQUANT( quant_8x8, dequant_8x8, CQM_8PY, 8 );
  979.         TEST_DEQUANT( quant_4x4, dequant_4x4, CQM_4IY, 4 );
  980.         TEST_DEQUANT( quant_4x4, dequant_4x4, CQM_4PY, 4 );
  981.         x264_cqm_delete( h );
  982.     }
  983.     ok = oks[0]; used_asm = used_asms[0];
  984.     report( "quant :" );
  985.     ok = oks[1]; used_asm = used_asms[1];
  986.     report( "dequant :" );
  987.     if( qf_a.denoise_dct != qf_ref.denoise_dct )
  988.     {
  989.         int size;
  990.         for( size = 16; size <= 64; size += 48 )
  991.         {
  992.             set_func_name( "denoise_dct" );
  993.             used_asm = 1;
  994.             memcpy(dct1, buf1, size*2);
  995.             memcpy(dct2, buf1, size*2);
  996.             memcpy(buf3+256, buf3, 256);
  997.             call_c1( qf_c.denoise_dct, dct1, (uint32_t*)buf3, (uint16_t*)buf2, size );
  998.             call_a1( qf_a.denoise_dct, dct2, (uint32_t*)(buf3+256), (uint16_t*)buf2, size );
  999.             if( memcmp( dct1, dct2, size*2 ) || memcmp( buf3+4, buf3+256+4, (size-1)*sizeof(uint32_t) ) )
  1000.                 ok = 0;
  1001.             call_c2( qf_c.denoise_dct, dct1, (uint32_t*)buf3, (uint16_t*)buf2, size );
  1002.             call_a2( qf_a.denoise_dct, dct2, (uint32_t*)(buf3+256), (uint16_t*)buf2, size );
  1003.         }
  1004.     }
  1005.     report( "denoise dct :" );
  1006.     return ret;
  1007. }
  1008. static int check_intra( int cpu_ref, int cpu_new )
  1009. {
  1010.     int ret = 0, ok = 1, used_asm = 0;
  1011.     int i;
  1012.     DECLARE_ALIGNED_16( uint8_t edge[33] );
  1013.     struct
  1014.     {
  1015.         x264_predict_t      predict_16x16[4+3];
  1016.         x264_predict_t      predict_8x8c[4+3];
  1017.         x264_predict8x8_t   predict_8x8[9+3];
  1018.         x264_predict_t      predict_4x4[9+3];
  1019.     } ip_c, ip_ref, ip_a;
  1020.     x264_predict_16x16_init( 0, ip_c.predict_16x16 );
  1021.     x264_predict_8x8c_init( 0, ip_c.predict_8x8c );
  1022.     x264_predict_8x8_init( 0, ip_c.predict_8x8 );
  1023.     x264_predict_4x4_init( 0, ip_c.predict_4x4 );
  1024.     x264_predict_16x16_init( cpu_ref, ip_ref.predict_16x16 );
  1025.     x264_predict_8x8c_init( cpu_ref, ip_ref.predict_8x8c );
  1026.     x264_predict_8x8_init( cpu_ref, ip_ref.predict_8x8 );
  1027.     x264_predict_4x4_init( cpu_ref, ip_ref.predict_4x4 );
  1028.     x264_predict_16x16_init( cpu_new, ip_a.predict_16x16 );
  1029.     x264_predict_8x8c_init( cpu_new, ip_a.predict_8x8c );
  1030.     x264_predict_8x8_init( cpu_new, ip_a.predict_8x8 );
  1031.     x264_predict_4x4_init( cpu_new, ip_a.predict_4x4 );
  1032.     x264_predict_8x8_filter( buf1+48, edge, ALL_NEIGHBORS, ALL_NEIGHBORS );
  1033. #define INTRA_TEST( name, dir, w, ... ) 
  1034.     if( ip_a.name[dir] != ip_ref.name[dir] )
  1035.     { 
  1036.         set_func_name( "intra_%s_%s", #name, intra_##name##_names[dir] );
  1037.         used_asm = 1; 
  1038.         memcpy( buf3, buf1, 32*20 );
  1039.         memcpy( buf4, buf1, 32*20 );
  1040.         call_c( ip_c.name[dir], buf3+48, ##__VA_ARGS__ );
  1041.         call_a( ip_a.name[dir], buf4+48, ##__VA_ARGS__ );
  1042.         if( memcmp( buf3, buf4, 32*20 ) )
  1043.         {
  1044.             fprintf( stderr, #name "[%d] :  [FAILED]n", dir );
  1045.             ok = 0;
  1046.             int j,k;
  1047.             for(k=-1; k<16; k++)
  1048.                 printf("%2x ", edge[16+k]);
  1049.             printf("n");
  1050.             for(j=0; j<w; j++){
  1051.                 printf("%2x ", edge[14-j]);
  1052.                 for(k=0; k<w; k++)
  1053.                     printf("%2x ", buf4[48+k+j*32]);
  1054.                 printf("n");
  1055.             }
  1056.             printf("n");
  1057.             for(j=0; j<w; j++){
  1058.                 printf("   ");
  1059.                 for(k=0; k<w; k++)
  1060.                     printf("%2x ", buf3[48+k+j*32]);
  1061.                 printf("n");
  1062.             }
  1063.         }
  1064.     }
  1065.     for( i = 0; i < 12; i++ )
  1066.         INTRA_TEST( predict_4x4, i, 4 );
  1067.     for( i = 0; i < 7; i++ )
  1068.         INTRA_TEST( predict_8x8c, i, 8 );
  1069.     for( i = 0; i < 7; i++ )
  1070.         INTRA_TEST( predict_16x16, i, 16 );
  1071.     for( i = 0; i < 12; i++ )
  1072.         INTRA_TEST( predict_8x8, i, 8, edge );
  1073.     report( "intra pred :" );
  1074.     return ret;
  1075. }
  1076. #define DECL_CABAC(cpu) 
  1077. static void run_cabac_##cpu( uint8_t *dst )
  1078. {
  1079.     int i;
  1080.     x264_cabac_t cb;
  1081.     x264_cabac_context_init( &cb, SLICE_TYPE_P, 26, 0 );
  1082.     x264_cabac_encode_init( &cb, dst, dst+0xff0 );
  1083.     for( i=0; i<0x1000; i++ )
  1084.         x264_cabac_encode_decision_##cpu( &cb, buf1[i]>>1, buf1[i]&1 );
  1085. }
  1086. DECL_CABAC(c)
  1087. #ifdef HAVE_MMX
  1088. DECL_CABAC(asm)
  1089. #else
  1090. #define run_cabac_asm run_cabac_c
  1091. #endif
  1092. static int check_cabac( int cpu_ref, int cpu_new )
  1093. {
  1094.     int ret = 0, ok, used_asm = 1;
  1095.     if( cpu_ref || run_cabac_c == run_cabac_asm)
  1096.         return 0;
  1097.     set_func_name( "cabac_encode_decision" );
  1098.     memcpy( buf4, buf3, 0x1000 );
  1099.     call_c( run_cabac_c, buf3 );
  1100.     call_a( run_cabac_asm, buf4 );
  1101.     ok = !memcmp( buf3, buf4, 0x1000 );
  1102.     report( "cabac :" );
  1103.     return ret;
  1104. }
  1105. static int check_all_funcs( int cpu_ref, int cpu_new )
  1106. {
  1107.     return check_pixel( cpu_ref, cpu_new )
  1108.          + check_dct( cpu_ref, cpu_new )
  1109.          + check_mc( cpu_ref, cpu_new )
  1110.          + check_intra( cpu_ref, cpu_new )
  1111.          + check_deblock( cpu_ref, cpu_new )
  1112.          + check_quant( cpu_ref, cpu_new )
  1113.          + check_cabac( cpu_ref, cpu_new );
  1114. }
  1115. static int add_flags( int *cpu_ref, int *cpu_new, int flags, const char *name )
  1116. {
  1117.     *cpu_ref = *cpu_new;
  1118.     *cpu_new |= flags;
  1119.     if( *cpu_new & X264_CPU_SSE2_IS_FAST )
  1120.         *cpu_new &= ~X264_CPU_SSE2_IS_SLOW;
  1121.     if( !quiet )
  1122.         fprintf( stderr, "x264: %sn", name );
  1123.     return check_all_funcs( *cpu_ref, *cpu_new );
  1124. }
  1125. static int check_all_flags( void )
  1126. {
  1127.     int ret = 0;
  1128.     int cpu0 = 0, cpu1 = 0;
  1129. #ifdef HAVE_MMX
  1130.     if( x264_cpu_detect() & X264_CPU_MMXEXT )
  1131.     {
  1132.         ret |= add_flags( &cpu0, &cpu1, X264_CPU_MMX | X264_CPU_MMXEXT, "MMX" );
  1133.         ret |= add_flags( &cpu0, &cpu1, X264_CPU_CACHELINE_64, "MMX Cache64" );
  1134.         cpu1 &= ~X264_CPU_CACHELINE_64;
  1135. #ifdef ARCH_X86
  1136.         ret |= add_flags( &cpu0, &cpu1, X264_CPU_CACHELINE_32, "MMX Cache32" );
  1137.         cpu1 &= ~X264_CPU_CACHELINE_32;
  1138. #endif
  1139.     }
  1140.     if( x264_cpu_detect() & X264_CPU_SSE2 )
  1141.     {
  1142.         ret |= add_flags( &cpu0, &cpu1, X264_CPU_SSE | X264_CPU_SSE2 | X264_CPU_SSE2_IS_SLOW, "SSE2Slow" );
  1143.         ret |= add_flags( &cpu0, &cpu1, X264_CPU_SSE2_IS_FAST, "SSE2Fast" );
  1144.         ret |= add_flags( &cpu0, &cpu1, X264_CPU_CACHELINE_64, "SSE2Fast Cache64" );
  1145.     }
  1146.     if( x264_cpu_detect() & X264_CPU_SSE3 )
  1147.         ret |= add_flags( &cpu0, &cpu1, X264_CPU_SSE3 | X264_CPU_CACHELINE_64, "SSE3" );
  1148.     if( x264_cpu_detect() & X264_CPU_SSSE3 )
  1149.     {
  1150.         cpu1 &= ~X264_CPU_CACHELINE_64;
  1151.         ret |= add_flags( &cpu0, &cpu1, X264_CPU_SSSE3, "SSSE3" );
  1152.         ret |= add_flags( &cpu0, &cpu1, X264_CPU_CACHELINE_64, "SSSE3 Cache64" );
  1153.         ret |= add_flags( &cpu0, &cpu1, X264_CPU_PHADD_IS_FAST, "PHADD" );
  1154.     }
  1155. #elif ARCH_PPC
  1156.     if( x264_cpu_detect() & X264_CPU_ALTIVEC )
  1157.     {
  1158.         fprintf( stderr, "x264: ALTIVEC against Cn" );
  1159.         ret = check_all_funcs( 0, X264_CPU_ALTIVEC );
  1160.     }
  1161. #endif
  1162.     return ret;
  1163. }
  1164. int main(int argc, char *argv[])
  1165. {
  1166.     int ret = 0;
  1167.     int i;
  1168.     if( argc > 1 && !strncmp( argv[1], "--bench", 7 ) )
  1169.     {
  1170. #if !defined(ARCH_X86) && !defined(ARCH_X86_64)
  1171.         fprintf( stderr, "no --bench for your cpu until you port rdtscn" );
  1172.         return 1;
  1173. #endif
  1174.         do_bench = 1;
  1175.         if( argv[1][7] == '=' )
  1176.         {
  1177.             bench_pattern = argv[1]+8;
  1178.             bench_pattern_len = strlen(bench_pattern);
  1179.         }
  1180.         argc--;
  1181.         argv++;
  1182.     }
  1183.     i = ( argc > 1 ) ? atoi(argv[1]) : x264_mdate();
  1184.     fprintf( stderr, "x264: using random seed %un", i );
  1185.     srand( i );
  1186.     buf1 = x264_malloc( 0x3e00 + 16*BENCH_ALIGNS );
  1187.     buf2 = buf1 + 0xf00;
  1188.     buf3 = buf2 + 0xf00;
  1189.     buf4 = buf3 + 0x1000;
  1190.     for( i=0; i<0x1e00; i++ )
  1191.         buf1[i] = rand() & 0xFF;
  1192.     memset( buf1+0x1e00, 0, 0x2000 );
  1193.     /* 16-byte alignment is guaranteed whenever it's useful, but some functions also vary in speed depending on %64 */
  1194.     if( do_bench )
  1195.         for( i=0; i<BENCH_ALIGNS && !ret; i++ )
  1196.         {
  1197.             buf2 = buf1 + 0xf00;
  1198.             buf3 = buf2 + 0xf00;
  1199.             buf4 = buf3 + 0x1000;
  1200.             ret |= x264_stack_pagealign( check_all_flags, i*16 );
  1201.             buf1 += 16;
  1202.             quiet = 1;
  1203.             fprintf( stderr, "%d/%dr", i+1, BENCH_ALIGNS );
  1204.         }
  1205.     else
  1206.         ret = check_all_flags();
  1207.     if( ret )
  1208.     {
  1209.         fprintf( stderr, "x264: at least one test has failed. Go and fix that Right Now!n" );
  1210.         return -1;
  1211.     }
  1212.     fprintf( stderr, "x264: All tests passed Yeah :)n" );
  1213.     if( do_bench )
  1214.         print_bench();
  1215.     return 0;
  1216. }