home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wvis0626.zip / warpvision_20020626.zip / libavcodec / i386 / mpegvideo_mmx_template.c < prev    next >
C/C++ Source or Header  |  2002-06-19  |  8KB  |  226 lines

  1. /*
  2.  * MPEG video MMX templates
  3.  *
  4.  * Copyright (c) 2002 Michael Niedermayer <michaelni@gmx.at>
  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20. #undef SPREADW
  21. #undef PMAXW
  22. #ifdef HAVE_MMX2
  23. #define SPREADW(a) "pshufw $0, " #a ", " #a " \n\t"
  24. #define PMAXW(a,b) "pmaxsw " #a ", " #b " \n\t"
  25.  
  26. #else
  27. #define SPREADW(a) \
  28.     "punpcklwd " #a ", " #a " \n\t"\
  29.     "punpcklwd " #a ", " #a " \n\t"
  30. #define PMAXW(a,b) \
  31.     "psubusw " #a ", " #b " \n\t"\
  32.     "paddw " #a ", " #b " \n\t"
  33. #endif
  34.  
  35. static int RENAME(dct_quantize)(MpegEncContext *s,
  36.                             DCTELEM *block, int n,
  37.                             int qscale, int *overflow)
  38. {
  39.     int level=0, last_non_zero_p1, q; //=0 is cuz gcc says uninitalized ...
  40.     const UINT16 *qmat, *bias;
  41.     static __align8 INT16 temp_block[64];
  42.  
  43.     av_fdct (block);
  44.  
  45.     if (s->mb_intra) {
  46.         int dummy;
  47.         if (n < 4)
  48.             q = s->y_dc_scale;
  49.         else
  50.             q = s->c_dc_scale;
  51.         /* note: block[0] is assumed to be positive */
  52.         if (!s->h263_aic) {
  53. #if 1
  54.         asm volatile (
  55.             "xorl %%edx, %%edx    \n\t"
  56.             "mul %%ecx        \n\t"
  57.             : "=d" (level), "=a"(dummy)
  58.             : "a" (block[0] + (q >> 1)), "c" (inverse[q])
  59.         );
  60. #else
  61.         asm volatile (
  62.             "xorl %%edx, %%edx    \n\t"
  63.             "divw %%cx        \n\t"
  64.             "movzwl %%ax, %%eax    \n\t"
  65.             : "=a" (level)
  66.             : "a" (block[0] + (q >> 1)), "c" (q)
  67.             : "%edx"
  68.         );
  69. #endif
  70.         } else
  71.             /* For AIC we skip quant/dequant of INTRADC */
  72.             level = block[0];
  73.             
  74.         block[0]=0; //avoid fake overflow
  75. //        temp_block[0] = (block[0] + (q >> 1)) / q;
  76.         last_non_zero_p1 = 1;
  77.         bias = s->q_intra_matrix16_bias[qscale];
  78.         qmat = s->q_intra_matrix16[qscale];
  79.     } else {
  80.         last_non_zero_p1 = 0;
  81.         bias = s->q_inter_matrix16_bias[qscale];
  82.         qmat = s->q_inter_matrix16[qscale];
  83.     }
  84.  
  85.     if(s->out_format == FMT_H263){
  86.     
  87.         asm volatile(
  88.             "movd %%eax, %%mm3            \n\t" // last_non_zero_p1
  89.             SPREADW(%%mm3)
  90.             "pxor %%mm7, %%mm7            \n\t" // 0
  91.             "pxor %%mm4, %%mm4            \n\t" // 0
  92.             "movq (%2), %%mm5            \n\t" // qmat[0]
  93.             "pxor %%mm6, %%mm6            \n\t"
  94.             "psubw (%3), %%mm6            \n\t" // -bias[0]
  95.             "movl $-128, %%eax            \n\t"
  96.             ".balign 16                \n\t"
  97.             "1:                    \n\t"
  98.             "pxor %%mm1, %%mm1            \n\t" // 0
  99.             "movq (%1, %%eax), %%mm0        \n\t" // block[i]
  100.             "pcmpgtw %%mm0, %%mm1        \n\t" // block[i] <= 0 ? 0xFF : 0x00
  101.             "pxor %%mm1, %%mm0            \n\t" 
  102.             "psubw %%mm1, %%mm0            \n\t" // ABS(block[i])
  103.             "psubusw %%mm6, %%mm0        \n\t" // ABS(block[i]) + bias[0]
  104.             "pmulhw %%mm5, %%mm0        \n\t" // (ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16
  105.             "por %%mm0, %%mm4            \n\t" 
  106.             "pxor %%mm1, %%mm0            \n\t" 
  107.             "psubw %%mm1, %%mm0            \n\t" // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i])
  108.             "movq %%mm0, (%5, %%eax)        \n\t"
  109.             "pcmpeqw %%mm7, %%mm0        \n\t" // out==0 ? 0xFF : 0x00
  110.             "movq (%4, %%eax), %%mm1        \n\t" 
  111.             "movq %%mm7, (%1, %%eax)        \n\t" // 0
  112.             "pandn %%mm1, %%mm0            \n\t"
  113.         PMAXW(%%mm0, %%mm3)
  114.             "addl $8, %%eax            \n\t"
  115.             " js 1b                \n\t"
  116.             "movq %%mm3, %%mm0            \n\t"
  117.             "psrlq $32, %%mm3            \n\t"
  118.         PMAXW(%%mm0, %%mm3)
  119.             "movq %%mm3, %%mm0            \n\t"
  120.             "psrlq $16, %%mm3            \n\t"
  121.         PMAXW(%%mm0, %%mm3)
  122.             "movd %%mm3, %%eax            \n\t"
  123.             "movzbl %%al, %%eax            \n\t" // last_non_zero_p1
  124.         : "+a" (last_non_zero_p1)
  125.             : "r" (block+64), "r" (qmat), "r" (bias),
  126.               "r" (inv_zigzag_direct16+64), "r" (temp_block+64)
  127.         );
  128.         // note the asm is split cuz gcc doesnt like that many operands ...
  129.         asm volatile(
  130.             "movd %1, %%mm1            \n\t" // max_qcoeff
  131.         SPREADW(%%mm1)
  132.             "psubusw %%mm1, %%mm4        \n\t" 
  133.             "packuswb %%mm4, %%mm4        \n\t"
  134.             "movd %%mm4, %0            \n\t" // *overflow
  135.         : "=g" (*overflow)
  136.         : "g" (s->max_qcoeff)
  137.         );
  138.     }else{ // FMT_H263
  139.         asm volatile(
  140.             "movd %%eax, %%mm3            \n\t" // last_non_zero_p1
  141.             SPREADW(%%mm3)
  142.             "pxor %%mm7, %%mm7            \n\t" // 0
  143.             "pxor %%mm4, %%mm4            \n\t" // 0
  144.             "movl $-128, %%eax            \n\t"
  145.             ".balign 16                \n\t"
  146.             "1:                    \n\t"
  147.             "pxor %%mm1, %%mm1            \n\t" // 0
  148.             "movq (%1, %%eax), %%mm0        \n\t" // block[i]
  149.             "pcmpgtw %%mm0, %%mm1        \n\t" // block[i] <= 0 ? 0xFF : 0x00
  150.             "pxor %%mm1, %%mm0            \n\t" 
  151.             "psubw %%mm1, %%mm0            \n\t" // ABS(block[i])
  152.             "movq (%3, %%eax), %%mm6        \n\t" // bias[0]
  153.             "paddusw %%mm6, %%mm0        \n\t" // ABS(block[i]) + bias[0]
  154.             "movq (%2, %%eax), %%mm5        \n\t" // qmat[i]
  155.             "pmulhw %%mm5, %%mm0        \n\t" // (ABS(block[i])*qmat[0] + bias[0]*qmat[0])>>16
  156.             "por %%mm0, %%mm4            \n\t" 
  157.             "pxor %%mm1, %%mm0            \n\t" 
  158.             "psubw %%mm1, %%mm0            \n\t" // out=((ABS(block[i])*qmat[0] - bias[0]*qmat[0])>>16)*sign(block[i])
  159.             "movq %%mm0, (%5, %%eax)        \n\t"
  160.             "pcmpeqw %%mm7, %%mm0        \n\t" // out==0 ? 0xFF : 0x00
  161.             "movq (%4, %%eax), %%mm1        \n\t" 
  162.             "movq %%mm7, (%1, %%eax)        \n\t" // 0
  163.             "pandn %%mm1, %%mm0            \n\t"
  164.         PMAXW(%%mm0, %%mm3)
  165.             "addl $8, %%eax            \n\t"
  166.             " js 1b                \n\t"
  167.             "movq %%mm3, %%mm0            \n\t"
  168.             "psrlq $32, %%mm3            \n\t"
  169.         PMAXW(%%mm0, %%mm3)
  170.             "movq %%mm3, %%mm0            \n\t"
  171.             "psrlq $16, %%mm3            \n\t"
  172.         PMAXW(%%mm0, %%mm3)
  173.             "movd %%mm3, %%eax            \n\t"
  174.             "movzbl %%al, %%eax            \n\t" // last_non_zero_p1
  175.         : "+a" (last_non_zero_p1)
  176.             : "r" (block+64), "r" (qmat+64), "r" (bias+64),
  177.               "r" (inv_zigzag_direct16+64), "r" (temp_block+64)
  178.         );
  179.         // note the asm is split cuz gcc doesnt like that many operands ...
  180.         asm volatile(
  181.             "movd %1, %%mm1            \n\t" // max_qcoeff
  182.         SPREADW(%%mm1)
  183.             "psubusw %%mm1, %%mm4        \n\t" 
  184.             "packuswb %%mm4, %%mm4        \n\t"
  185.             "movd %%mm4, %0            \n\t" // *overflow
  186.         : "=g" (*overflow)
  187.         : "g" (s->max_qcoeff)
  188.         );
  189.     }
  190.  
  191.     if(s->mb_intra) temp_block[0]= level; //FIXME move afer permute
  192. // last_non_zero_p1=64;       
  193.     /* permute for IDCT */
  194.     asm volatile(
  195.         "movl %0, %%eax            \n\t"
  196.     "pushl %%ebp            \n\t"
  197.     "movl %%esp, " MANGLE(esp_temp) "\n\t"
  198.     "1:                \n\t"
  199.     "movzbl (%1, %%eax), %%ebx    \n\t"
  200.     "movzbl 1(%1, %%eax), %%ebp    \n\t"
  201.     "movw (%2, %%ebx, 2), %%cx    \n\t"
  202.     "movw (%2, %%ebp, 2), %%sp    \n\t"
  203.     "movzbl " MANGLE(permutation) "(%%ebx), %%ebx\n\t"
  204.     "movzbl " MANGLE(permutation) "(%%ebp), %%ebp\n\t"
  205.     "movw %%cx, (%3, %%ebx, 2)    \n\t"
  206.     "movw %%sp, (%3, %%ebp, 2)    \n\t"
  207.     "addl $2, %%eax            \n\t"
  208.     " js 1b                \n\t"
  209.     "movl " MANGLE(esp_temp) ", %%esp\n\t"
  210.     "popl %%ebp            \n\t"
  211.     : 
  212.     : "g" (-last_non_zero_p1), "d" (zigzag_direct_noperm+last_non_zero_p1), "S" (temp_block), "D" (block)
  213.     : "%eax", "%ebx", "%ecx"
  214.     );
  215. /*
  216.     for(i=0; i<last_non_zero_p1; i++)
  217.     {
  218.        int j= zigzag_direct_noperm[i];
  219.        block[block_permute_op(j)]= temp_block[j];
  220.     }
  221. */
  222. //block_permute(block);
  223.  
  224.     return last_non_zero_p1 - 1;
  225. }
  226.