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.c < prev    next >
C/C++ Source or Header  |  2002-06-24  |  18KB  |  572 lines

  1. /*
  2.  * The simplest mpeg encoder (well, it was the simplest!)
  3.  * Copyright (c) 2000,2001 Fabrice Bellard.
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Lesser General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public
  16.  * License along with this library; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  * Optimized for ia32 cpus by Nick Kurshev <nickols_k@mail.ru>
  20.  * h263, mpeg1, mpeg2 dequantizer & draw_edges by Michael Niedermayer <michaelni@gmx.at>
  21.  */
  22.  
  23. #include "../dsputil.h"
  24. #include "../mpegvideo.h"
  25. #include "../avcodec.h"
  26.  
  27. extern UINT8 zigzag_end[64];
  28.  
  29. extern UINT8 zigzag_direct_noperm[64];
  30. extern UINT16 inv_zigzag_direct16[64];
  31. extern UINT32 inverse[256];
  32.  
  33. #if 0
  34.  
  35. /* XXX: GL: I don't understand why this function needs optimization
  36.    (it is called only once per frame!), so I disabled it */
  37.  
  38. void MPV_frame_start(MpegEncContext *s)
  39. {
  40.     if (s->pict_type == B_TYPE) {
  41.     __asm __volatile(
  42.         "movl    (%1), %%eax\n\t"
  43.         "movl    4(%1), %%edx\n\t"
  44.         "movl    8(%1), %%ecx\n\t"
  45.         "movl    %%eax, (%0)\n\t"
  46.         "movl    %%edx, 4(%0)\n\t"
  47.         "movl    %%ecx, 8(%0)\n\t"
  48.         :
  49.         :"r"(s->current_picture), "r"(s->aux_picture)
  50.         :"eax","edx","ecx","memory");
  51.     } else {
  52.             /* swap next and last */
  53.     __asm __volatile(
  54.         "movl    (%1), %%eax\n\t"
  55.         "movl    4(%1), %%edx\n\t"
  56.         "movl    8(%1), %%ecx\n\t"
  57.         "xchgl    (%0), %%eax\n\t"
  58.         "xchgl    4(%0), %%edx\n\t"
  59.         "xchgl    8(%0), %%ecx\n\t"
  60.         "movl    %%eax, (%1)\n\t"
  61.         "movl    %%edx, 4(%1)\n\t"
  62.         "movl    %%ecx, 8(%1)\n\t"
  63.         "movl    %%eax, (%2)\n\t"
  64.         "movl    %%edx, 4(%2)\n\t"
  65.         "movl    %%ecx, 8(%2)\n\t"
  66.         :
  67.         :"r"(s->last_picture), "r"(s->next_picture), "r"(s->current_picture)
  68.         :"eax","edx","ecx","memory");
  69.     }
  70. }
  71. #endif
  72.  
  73. static const unsigned long long int mm_wabs __attribute__ ((aligned(8))) = 0xffffffffffffffffULL;
  74. static const unsigned long long int mm_wone __attribute__ ((aligned(8))) = 0x0001000100010001ULL;
  75.  
  76.  
  77. static void dct_unquantize_h263_mmx(MpegEncContext *s,
  78.                                   DCTELEM *block, int n, int qscale)
  79. {
  80.     int i, level, qmul, qadd, nCoeffs;
  81.     
  82.     qmul = s->qscale << 1;
  83.     if (s->h263_aic && s->mb_intra)
  84.         qadd = 0;
  85.     else
  86.         qadd = (s->qscale - 1) | 1;
  87.  
  88.     if (s->mb_intra) {
  89.         if (!s->h263_aic) {
  90.             if (n < 4)
  91.                 block[0] = block[0] * s->y_dc_scale;
  92.             else
  93.                 block[0] = block[0] * s->c_dc_scale;
  94.         }
  95.         for(i=1; i<8; i++) {
  96.             level = block[i];
  97.             if (level) {
  98.                 if (level < 0) {
  99.                     level = level * qmul - qadd;
  100.                 } else {
  101.                     level = level * qmul + qadd;
  102.                 }
  103.                 block[i] = level;
  104.             }
  105.         }
  106.         nCoeffs=64;
  107.     } else {
  108.         i = 0;
  109.         nCoeffs= zigzag_end[ s->block_last_index[n] ];
  110.     }
  111. //printf("%d %d  ", qmul, qadd);
  112. asm volatile(
  113.         "movd %1, %%mm6            \n\t" //qmul
  114.         "packssdw %%mm6, %%mm6        \n\t"
  115.         "packssdw %%mm6, %%mm6        \n\t"
  116.         "movd %2, %%mm5            \n\t" //qadd
  117.         "pxor %%mm7, %%mm7        \n\t"
  118.         "packssdw %%mm5, %%mm5        \n\t"
  119.         "packssdw %%mm5, %%mm5        \n\t"
  120.         "psubw %%mm5, %%mm7        \n\t"
  121.         "pxor %%mm4, %%mm4        \n\t"
  122.         ".balign 16\n\t"
  123.         "1:                \n\t"
  124.         "movq (%0, %3), %%mm0        \n\t"
  125.         "movq 8(%0, %3), %%mm1        \n\t"
  126.  
  127.         "pmullw %%mm6, %%mm0        \n\t"
  128.         "pmullw %%mm6, %%mm1        \n\t"
  129.  
  130.         "movq (%0, %3), %%mm2        \n\t"
  131.         "movq 8(%0, %3), %%mm3        \n\t"
  132.  
  133.         "pcmpgtw %%mm4, %%mm2        \n\t" // block[i] < 0 ? -1 : 0
  134.         "pcmpgtw %%mm4, %%mm3        \n\t" // block[i] < 0 ? -1 : 0
  135.  
  136.         "pxor %%mm2, %%mm0        \n\t"
  137.         "pxor %%mm3, %%mm1        \n\t"
  138.  
  139.         "paddw %%mm7, %%mm0        \n\t"
  140.         "paddw %%mm7, %%mm1        \n\t"
  141.  
  142.         "pxor %%mm0, %%mm2        \n\t"
  143.         "pxor %%mm1, %%mm3        \n\t"
  144.  
  145.         "pcmpeqw %%mm7, %%mm0        \n\t" // block[i] == 0 ? -1 : 0
  146.         "pcmpeqw %%mm7, %%mm1        \n\t" // block[i] == 0 ? -1 : 0
  147.  
  148.         "pandn %%mm2, %%mm0        \n\t"
  149.         "pandn %%mm3, %%mm1        \n\t"
  150.  
  151.         "movq %%mm0, (%0, %3)        \n\t"
  152.         "movq %%mm1, 8(%0, %3)        \n\t"
  153.  
  154.         "addl $16, %3            \n\t"
  155.         "js 1b                \n\t"
  156.         ::"r" (block+nCoeffs), "g"(qmul), "g" (qadd), "r" (2*(i-nCoeffs))
  157.         : "memory"
  158.     );
  159. }
  160.  
  161.  
  162. /*
  163.   NK:
  164.   Note: looking at PARANOID:
  165.   "enable all paranoid tests for rounding, overflows, etc..."
  166.  
  167. #ifdef PARANOID
  168.                 if (level < -2048 || level > 2047)
  169.                     fprintf(stderr, "unquant error %d %d\n", i, level);
  170. #endif
  171.   We can suppose that result of two multiplications can't be greate of 0xFFFF
  172.   i.e. is 16-bit, so we use here only PMULLW instruction and can avoid
  173.   a complex multiplication.
  174. =====================================================
  175.  Full formula for multiplication of 2 integer numbers
  176.  which are represent as high:low words:
  177.  input: value1 = high1:low1
  178.         value2 = high2:low2
  179.  output: value3 = value1*value2
  180.  value3=high3:low3 (on overflow: modulus 2^32 wrap-around)
  181.  this mean that for 0x123456 * 0x123456 correct result is 0x766cb0ce4
  182.  but this algorithm will compute only 0x66cb0ce4
  183.  this limited by 16-bit size of operands
  184.  ---------------------------------
  185.  tlow1 = high1*low2
  186.  tlow2 = high2*low1
  187.  tlow1 = tlow1 + tlow2
  188.  high3:low3 = low1*low2
  189.  high3 += tlow1
  190. */
  191. static void dct_unquantize_mpeg1_mmx(MpegEncContext *s,
  192.                                      DCTELEM *block, int n, int qscale)
  193. {
  194.     int nCoeffs;
  195.     const UINT16 *quant_matrix;
  196.     
  197.     if(s->alternate_scan) nCoeffs= 64;
  198.     else nCoeffs= nCoeffs= zigzag_end[ s->block_last_index[n] ];
  199.  
  200.     if (s->mb_intra) {
  201.         int block0;
  202.         if (n < 4) 
  203.             block0 = block[0] * s->y_dc_scale;
  204.         else
  205.             block0 = block[0] * s->c_dc_scale;
  206.         /* XXX: only mpeg1 */
  207.         quant_matrix = s->intra_matrix;
  208. asm volatile(
  209.         "pcmpeqw %%mm7, %%mm7        \n\t"
  210.         "psrlw $15, %%mm7        \n\t"
  211.         "movd %2, %%mm6            \n\t"
  212.         "packssdw %%mm6, %%mm6        \n\t"
  213.         "packssdw %%mm6, %%mm6        \n\t"
  214.                 "movl %3, %%eax            \n\t"
  215.         ".balign 16\n\t"
  216.         "1:                \n\t"
  217.         "movq (%0, %%eax), %%mm0    \n\t"
  218.         "movq 8(%0, %%eax), %%mm1    \n\t"
  219.         "movq (%1, %%eax), %%mm4    \n\t"
  220.         "movq 8(%1, %%eax), %%mm5    \n\t"
  221.         "pmullw %%mm6, %%mm4        \n\t" // q=qscale*quant_matrix[i]
  222.         "pmullw %%mm6, %%mm5        \n\t" // q=qscale*quant_matrix[i]
  223.         "pxor %%mm2, %%mm2        \n\t"
  224.         "pxor %%mm3, %%mm3        \n\t"
  225.         "pcmpgtw %%mm0, %%mm2        \n\t" // block[i] < 0 ? -1 : 0
  226.         "pcmpgtw %%mm1, %%mm3        \n\t" // block[i] < 0 ? -1 : 0
  227.         "pxor %%mm2, %%mm0        \n\t"
  228.         "pxor %%mm3, %%mm1        \n\t"
  229.         "psubw %%mm2, %%mm0        \n\t" // abs(block[i])
  230.         "psubw %%mm3, %%mm1        \n\t" // abs(block[i])
  231.         "pmullw %%mm4, %%mm0        \n\t" // abs(block[i])*q
  232.         "pmullw %%mm5, %%mm1        \n\t" // abs(block[i])*q
  233.         "pxor %%mm4, %%mm4        \n\t"
  234.         "pxor %%mm5, %%mm5        \n\t" // FIXME slow
  235.         "pcmpeqw (%0, %%eax), %%mm4    \n\t" // block[i] == 0 ? -1 : 0
  236.         "pcmpeqw 8(%0, %%eax), %%mm5    \n\t" // block[i] == 0 ? -1 : 0
  237.         "psraw $3, %%mm0        \n\t"
  238.         "psraw $3, %%mm1        \n\t"
  239.         "psubw %%mm7, %%mm0        \n\t"
  240.         "psubw %%mm7, %%mm1        \n\t"
  241.         "por %%mm7, %%mm0        \n\t"
  242.         "por %%mm7, %%mm1        \n\t"
  243.         "pxor %%mm2, %%mm0        \n\t"
  244.         "pxor %%mm3, %%mm1        \n\t"
  245.         "psubw %%mm2, %%mm0        \n\t"
  246.         "psubw %%mm3, %%mm1        \n\t"
  247.         "pandn %%mm0, %%mm4        \n\t"
  248.         "pandn %%mm1, %%mm5        \n\t"
  249.         "movq %%mm4, (%0, %%eax)    \n\t"
  250.         "movq %%mm5, 8(%0, %%eax)    \n\t"
  251.  
  252.         "addl $16, %%eax        \n\t"
  253.         "js 1b                \n\t"
  254.         ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "g" (qscale), "g" (-2*nCoeffs)
  255.         : "%eax", "memory"
  256.     );    
  257.         block[0]= block0;
  258.  
  259.         } else {
  260.         quant_matrix = s->inter_matrix;
  261. asm volatile(
  262.         "pcmpeqw %%mm7, %%mm7        \n\t"
  263.         "psrlw $15, %%mm7        \n\t"
  264.         "movd %2, %%mm6            \n\t"
  265.         "packssdw %%mm6, %%mm6        \n\t"
  266.         "packssdw %%mm6, %%mm6        \n\t"
  267.                 "movl %3, %%eax            \n\t"
  268.         ".balign 16\n\t"
  269.         "1:                \n\t"
  270.         "movq (%0, %%eax), %%mm0    \n\t"
  271.         "movq 8(%0, %%eax), %%mm1    \n\t"
  272.         "movq (%1, %%eax), %%mm4    \n\t"
  273.         "movq 8(%1, %%eax), %%mm5    \n\t"
  274.         "pmullw %%mm6, %%mm4        \n\t" // q=qscale*quant_matrix[i]
  275.         "pmullw %%mm6, %%mm5        \n\t" // q=qscale*quant_matrix[i]
  276.         "pxor %%mm2, %%mm2        \n\t"
  277.         "pxor %%mm3, %%mm3        \n\t"
  278.         "pcmpgtw %%mm0, %%mm2        \n\t" // block[i] < 0 ? -1 : 0
  279.         "pcmpgtw %%mm1, %%mm3        \n\t" // block[i] < 0 ? -1 : 0
  280.         "pxor %%mm2, %%mm0        \n\t"
  281.         "pxor %%mm3, %%mm1        \n\t"
  282.         "psubw %%mm2, %%mm0        \n\t" // abs(block[i])
  283.         "psubw %%mm3, %%mm1        \n\t" // abs(block[i])
  284.         "paddw %%mm0, %%mm0        \n\t" // abs(block[i])*2
  285.         "paddw %%mm1, %%mm1        \n\t" // abs(block[i])*2
  286.         "paddw %%mm7, %%mm0        \n\t" // abs(block[i])*2 + 1
  287.         "paddw %%mm7, %%mm1        \n\t" // abs(block[i])*2 + 1
  288.         "pmullw %%mm4, %%mm0        \n\t" // (abs(block[i])*2 + 1)*q
  289.         "pmullw %%mm5, %%mm1        \n\t" // (abs(block[i])*2 + 1)*q
  290.         "pxor %%mm4, %%mm4        \n\t"
  291.         "pxor %%mm5, %%mm5        \n\t" // FIXME slow
  292.         "pcmpeqw (%0, %%eax), %%mm4    \n\t" // block[i] == 0 ? -1 : 0
  293.         "pcmpeqw 8(%0, %%eax), %%mm5    \n\t" // block[i] == 0 ? -1 : 0
  294.         "psraw $4, %%mm0        \n\t"
  295.         "psraw $4, %%mm1        \n\t"
  296.         "psubw %%mm7, %%mm0        \n\t"
  297.         "psubw %%mm7, %%mm1        \n\t"
  298.         "por %%mm7, %%mm0        \n\t"
  299.         "por %%mm7, %%mm1        \n\t"
  300.         "pxor %%mm2, %%mm0        \n\t"
  301.         "pxor %%mm3, %%mm1        \n\t"
  302.         "psubw %%mm2, %%mm0        \n\t"
  303.         "psubw %%mm3, %%mm1        \n\t"
  304.         "pandn %%mm0, %%mm4        \n\t"
  305.         "pandn %%mm1, %%mm5        \n\t"
  306.         "movq %%mm4, (%0, %%eax)    \n\t"
  307.         "movq %%mm5, 8(%0, %%eax)    \n\t"
  308.  
  309.         "addl $16, %%eax        \n\t"
  310.         "js 1b                \n\t"
  311.         ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "g" (qscale), "g" (-2*nCoeffs)
  312.         : "%eax", "memory"
  313.     );
  314.     }
  315. }
  316.  
  317. static void dct_unquantize_mpeg2_mmx(MpegEncContext *s,
  318.                                      DCTELEM *block, int n, int qscale)
  319. {
  320.     int nCoeffs;
  321.     const UINT16 *quant_matrix;
  322.     
  323.     if(s->alternate_scan) nCoeffs= 64;
  324.     else nCoeffs= nCoeffs= zigzag_end[ s->block_last_index[n] ];
  325.  
  326.     if (s->mb_intra) {
  327.         int block0;
  328.         if (n < 4) 
  329.             block0 = block[0] * s->y_dc_scale;
  330.         else
  331.             block0 = block[0] * s->c_dc_scale;
  332.         quant_matrix = s->intra_matrix;
  333. asm volatile(
  334.         "pcmpeqw %%mm7, %%mm7        \n\t"
  335.         "psrlw $15, %%mm7        \n\t"
  336.         "movd %2, %%mm6            \n\t"
  337.         "packssdw %%mm6, %%mm6        \n\t"
  338.         "packssdw %%mm6, %%mm6        \n\t"
  339.                 "movl %3, %%eax            \n\t"
  340.         ".balign 16\n\t"
  341.         "1:                \n\t"
  342.         "movq (%0, %%eax), %%mm0    \n\t"
  343.         "movq 8(%0, %%eax), %%mm1    \n\t"
  344.         "movq (%1, %%eax), %%mm4    \n\t"
  345.         "movq 8(%1, %%eax), %%mm5    \n\t"
  346.         "pmullw %%mm6, %%mm4        \n\t" // q=qscale*quant_matrix[i]
  347.         "pmullw %%mm6, %%mm5        \n\t" // q=qscale*quant_matrix[i]
  348.         "pxor %%mm2, %%mm2        \n\t"
  349.         "pxor %%mm3, %%mm3        \n\t"
  350.         "pcmpgtw %%mm0, %%mm2        \n\t" // block[i] < 0 ? -1 : 0
  351.         "pcmpgtw %%mm1, %%mm3        \n\t" // block[i] < 0 ? -1 : 0
  352.         "pxor %%mm2, %%mm0        \n\t"
  353.         "pxor %%mm3, %%mm1        \n\t"
  354.         "psubw %%mm2, %%mm0        \n\t" // abs(block[i])
  355.         "psubw %%mm3, %%mm1        \n\t" // abs(block[i])
  356.         "pmullw %%mm4, %%mm0        \n\t" // abs(block[i])*q
  357.         "pmullw %%mm5, %%mm1        \n\t" // abs(block[i])*q
  358.         "pxor %%mm4, %%mm4        \n\t"
  359.         "pxor %%mm5, %%mm5        \n\t" // FIXME slow
  360.         "pcmpeqw (%0, %%eax), %%mm4    \n\t" // block[i] == 0 ? -1 : 0
  361.         "pcmpeqw 8(%0, %%eax), %%mm5    \n\t" // block[i] == 0 ? -1 : 0
  362.         "psraw $3, %%mm0        \n\t"
  363.         "psraw $3, %%mm1        \n\t"
  364.         "pxor %%mm2, %%mm0        \n\t"
  365.         "pxor %%mm3, %%mm1        \n\t"
  366.         "psubw %%mm2, %%mm0        \n\t"
  367.         "psubw %%mm3, %%mm1        \n\t"
  368.         "pandn %%mm0, %%mm4        \n\t"
  369.         "pandn %%mm1, %%mm5        \n\t"
  370.         "movq %%mm4, (%0, %%eax)    \n\t"
  371.         "movq %%mm5, 8(%0, %%eax)    \n\t"
  372.  
  373.         "addl $16, %%eax        \n\t"
  374.         "js 1b                \n\t"
  375.         ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "g" (qscale), "g" (-2*nCoeffs)
  376.         : "%eax", "memory"
  377.     );    
  378.         block[0]= block0;
  379.         //Note, we dont do mismatch control for intra as errors cannot accumulate
  380.  
  381.     } else {
  382.         quant_matrix = s->inter_matrix;
  383. asm volatile(
  384.         "pcmpeqw %%mm7, %%mm7        \n\t"
  385.                 "psrlq $48, %%mm7        \n\t"
  386.         "movd %2, %%mm6            \n\t"
  387.         "packssdw %%mm6, %%mm6        \n\t"
  388.         "packssdw %%mm6, %%mm6        \n\t"
  389.                 "movl %3, %%eax            \n\t"
  390.         ".balign 16\n\t"
  391.         "1:                \n\t"
  392.         "movq (%0, %%eax), %%mm0    \n\t"
  393.         "movq 8(%0, %%eax), %%mm1    \n\t"
  394.         "movq (%1, %%eax), %%mm4    \n\t"
  395.         "movq 8(%1, %%eax), %%mm5    \n\t"
  396.         "pmullw %%mm6, %%mm4        \n\t" // q=qscale*quant_matrix[i]
  397.         "pmullw %%mm6, %%mm5        \n\t" // q=qscale*quant_matrix[i]
  398.         "pxor %%mm2, %%mm2        \n\t"
  399.         "pxor %%mm3, %%mm3        \n\t"
  400.         "pcmpgtw %%mm0, %%mm2        \n\t" // block[i] < 0 ? -1 : 0
  401.         "pcmpgtw %%mm1, %%mm3        \n\t" // block[i] < 0 ? -1 : 0
  402.         "pxor %%mm2, %%mm0        \n\t"
  403.         "pxor %%mm3, %%mm1        \n\t"
  404.         "psubw %%mm2, %%mm0        \n\t" // abs(block[i])
  405.         "psubw %%mm3, %%mm1        \n\t" // abs(block[i])
  406.         "paddw %%mm0, %%mm0        \n\t" // abs(block[i])*2
  407.         "paddw %%mm1, %%mm1        \n\t" // abs(block[i])*2
  408.         "pmullw %%mm4, %%mm0        \n\t" // abs(block[i])*2*q
  409.         "pmullw %%mm5, %%mm1        \n\t" // abs(block[i])*2*q
  410.         "paddw %%mm4, %%mm0        \n\t" // (abs(block[i])*2 + 1)*q
  411.         "paddw %%mm5, %%mm1        \n\t" // (abs(block[i])*2 + 1)*q
  412.         "pxor %%mm4, %%mm4        \n\t"
  413.         "pxor %%mm5, %%mm5        \n\t" // FIXME slow
  414.         "pcmpeqw (%0, %%eax), %%mm4    \n\t" // block[i] == 0 ? -1 : 0
  415.         "pcmpeqw 8(%0, %%eax), %%mm5    \n\t" // block[i] == 0 ? -1 : 0
  416.         "psrlw $4, %%mm0        \n\t"
  417.         "psrlw $4, %%mm1        \n\t"
  418.         "pxor %%mm2, %%mm0        \n\t"
  419.         "pxor %%mm3, %%mm1        \n\t"
  420.         "psubw %%mm2, %%mm0        \n\t"
  421.         "psubw %%mm3, %%mm1        \n\t"
  422.         "pandn %%mm0, %%mm4        \n\t"
  423.         "pandn %%mm1, %%mm5        \n\t"
  424.                 "pxor %%mm4, %%mm7        \n\t"
  425.                 "pxor %%mm5, %%mm7        \n\t"
  426.         "movq %%mm4, (%0, %%eax)    \n\t"
  427.         "movq %%mm5, 8(%0, %%eax)    \n\t"
  428.  
  429.         "addl $16, %%eax        \n\t"
  430.         "js 1b                \n\t"
  431.                 "movd 124(%0, %3), %%mm0    \n\t"
  432.                 "movq %%mm7, %%mm6        \n\t"
  433.                 "psrlq $32, %%mm7        \n\t"
  434.                 "pxor %%mm6, %%mm7        \n\t"
  435.                 "movq %%mm7, %%mm6        \n\t"
  436.                 "psrlq $16, %%mm7        \n\t"
  437.                 "pxor %%mm6, %%mm7        \n\t"
  438.                 "pslld $31, %%mm7        \n\t"
  439.                 "psrlq $15, %%mm7        \n\t"
  440.                 "pxor %%mm7, %%mm0        \n\t"
  441.                 "movd %%mm0, 124(%0, %3)    \n\t"
  442.                 
  443.         ::"r" (block+nCoeffs), "r"(quant_matrix+nCoeffs), "g" (qscale), "r" (-2*nCoeffs)
  444.         : "%eax", "memory"
  445.     );
  446.     }
  447. }
  448.  
  449. /* draw the edges of width 'w' of an image of size width, height 
  450.    this mmx version can only handle w==8 || w==16 */
  451. static void draw_edges_mmx(UINT8 *buf, int wrap, int width, int height, int w)
  452. {
  453.     UINT8 *ptr, *last_line;
  454.     int i;
  455.  
  456.     last_line = buf + (height - 1) * wrap;
  457.     /* left and right */
  458.     ptr = buf;
  459.     if(w==8)
  460.     {
  461.     asm volatile(
  462.         "1:                \n\t"
  463.         "movd (%0), %%mm0        \n\t"
  464.         "punpcklbw %%mm0, %%mm0        \n\t" 
  465.         "punpcklwd %%mm0, %%mm0        \n\t"
  466.         "punpckldq %%mm0, %%mm0        \n\t"
  467.         "movq %%mm0, -8(%0)        \n\t"
  468.         "movq -8(%0, %2), %%mm1        \n\t"
  469.         "punpckhbw %%mm1, %%mm1        \n\t"
  470.         "punpckhwd %%mm1, %%mm1        \n\t"
  471.         "punpckhdq %%mm1, %%mm1        \n\t"
  472.         "movq %%mm1, (%0, %2)        \n\t"
  473.         "addl %1, %0            \n\t"
  474.         "cmpl %3, %0            \n\t"
  475.         " jb 1b                \n\t"
  476.         : "+r" (ptr)
  477.         : "r" (wrap), "r" (width), "r" (ptr + wrap*height)
  478.     );
  479.     }
  480.     else
  481.     {
  482.     asm volatile(
  483.         "1:                \n\t"
  484.         "movd (%0), %%mm0        \n\t"
  485.         "punpcklbw %%mm0, %%mm0        \n\t" 
  486.         "punpcklwd %%mm0, %%mm0        \n\t"
  487.         "punpckldq %%mm0, %%mm0        \n\t"
  488.         "movq %%mm0, -8(%0)        \n\t"
  489.         "movq %%mm0, -16(%0)        \n\t"
  490.         "movq -8(%0, %2), %%mm1        \n\t"
  491.         "punpckhbw %%mm1, %%mm1        \n\t"
  492.         "punpckhwd %%mm1, %%mm1        \n\t"
  493.         "punpckhdq %%mm1, %%mm1        \n\t"
  494.         "movq %%mm1, (%0, %2)        \n\t"
  495.         "movq %%mm1, 8(%0, %2)        \n\t"
  496.         "addl %1, %0            \n\t"
  497.         "cmpl %3, %0            \n\t"
  498.         " jb 1b                \n\t"        
  499.         : "+r" (ptr)
  500.         : "r" (wrap), "r" (width), "r" (ptr + wrap*height)
  501.     );
  502.     }
  503.     
  504.     for(i=0;i<w;i+=4) {
  505.         /* top and bottom (and hopefully also the corners) */
  506.     ptr= buf - (i + 1) * wrap - w;
  507.     asm volatile(
  508.         "1:                \n\t"
  509.         "movq (%1, %0), %%mm0        \n\t"
  510.         "movq %%mm0, (%0)        \n\t"
  511.         "movq %%mm0, (%0, %2)        \n\t"
  512.         "movq %%mm0, (%0, %2, 2)    \n\t"
  513.         "movq %%mm0, (%0, %3)        \n\t"
  514.         "addl $8, %0            \n\t"
  515.         "cmpl %4, %0            \n\t"
  516.         " jb 1b                \n\t"
  517.         : "+r" (ptr)
  518.         : "r" ((int)buf - (int)ptr - w), "r" (-wrap), "r" (-wrap*3), "r" (ptr+width+2*w)
  519.     );
  520.     ptr= last_line + (i + 1) * wrap - w;
  521.     asm volatile(
  522.         "1:                \n\t"
  523.         "movq (%1, %0), %%mm0        \n\t"
  524.         "movq %%mm0, (%0)        \n\t"
  525.         "movq %%mm0, (%0, %2)        \n\t"
  526.         "movq %%mm0, (%0, %2, 2)    \n\t"
  527.         "movq %%mm0, (%0, %3)        \n\t"
  528.         "addl $8, %0            \n\t"
  529.         "cmpl %4, %0            \n\t"
  530.         " jb 1b                \n\t"
  531.         : "+r" (ptr)
  532.         : "r" ((int)last_line - (int)ptr - w), "r" (wrap), "r" (wrap*3), "r" (ptr+width+2*w)
  533.     );
  534.     }
  535. }
  536.  
  537. static volatile int esp_temp;
  538.  
  539. void unused_var_warning_killer(){
  540.     esp_temp++;
  541. }
  542.  
  543. #undef HAVE_MMX2
  544. #define RENAME(a) a ## _MMX
  545. #include "mpegvideo_mmx_template.c"
  546.  
  547. #define HAVE_MMX2
  548. #undef RENAME
  549. #define RENAME(a) a ## _MMX2
  550. #include "mpegvideo_mmx_template.c"
  551.  
  552. #ifndef OS2
  553. void MPV_common_init_mmx(MpegEncContext *s)
  554. #else
  555. void optlink MPV_common_init_mmx(MpegEncContext *s)
  556. #endif
  557. {
  558.     if (mm_flags & MM_MMX) {
  559.         s->dct_unquantize_h263 = dct_unquantize_h263_mmx;
  560.         s->dct_unquantize_mpeg1 = dct_unquantize_mpeg1_mmx;
  561.         s->dct_unquantize_mpeg2 = dct_unquantize_mpeg2_mmx;
  562.  
  563.         draw_edges = draw_edges_mmx;
  564.  
  565.         if(mm_flags & MM_MMXEXT){
  566.             dct_quantize= dct_quantize_MMX2;
  567.         } else {
  568.             dct_quantize= dct_quantize_MMX;
  569.         }
  570.     }
  571. }
  572.