home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2004 March / PCWELT_3_2004.ISO / pcwsoft / flaskmpeg_078_39_src.z.exe / flaskmpeg / Video / recon.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-10-28  |  50.4 KB  |  1,774 lines

  1. /* Predict.c, motion compensation routines                                    */
  2. /* Last modified by PX3 July 30 2000  Optimizations done                    */
  3.  
  4. /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
  5.  
  6. /*
  7.  * Disclaimer of Warranty
  8.  *
  9.  * These software programs are available to the user without any license fee or
  10.  * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims
  11.  * any and all warranties, whether express, implied, or statuary, including any
  12.  * implied warranties or merchantability or of fitness for a particular
  13.  * purpose.  In no event shall the copyright-holder be liable for any
  14.  * incidental, punitive, or consequential damages of any kind whatsoever
  15.  * arising from the use of these programs.
  16.  *
  17.  * This disclaimer of warranty extends to the user of these programs and user's
  18.  * customers, employees, agents, transferees, successors, and assigns.
  19.  *
  20.  * The MPEG Software Simulation Group does not represent or warrant that the
  21.  * programs furnished hereunder are free of infringement of any third-party
  22.  * patents.
  23.  *
  24.  * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
  25.  * are subject to royalty fees to patent holders.  Many of these patents are
  26.  * general enough such that they are unavoidable regardless of implementation
  27.  * design.
  28.  *
  29.  */
  30.  
  31. #include <stdio.h>
  32.  
  33. #include "config.h"
  34. #include "global.h"
  35. //#include "getbits.h"
  36.  
  37. /* private prototypes */
  38. __inline static void form_prediction _ANSI_ARGS_((unsigned char *src[], int sfield,
  39.   unsigned char *dst[], int dfield,
  40.   int lx, int lx2, int w, int h, int x, int y, int dx, int dy,
  41.   int average_flag));
  42.  
  43. __inline static void form_component_prediction _ANSI_ARGS_((unsigned char *src, unsigned char *dst,
  44.   int lx, int lx2, int w, int h, int x, int y, int dx, int dy, int average_flag));
  45.  
  46. /* private data */
  47. // 0.16B3, global scope declaration ensures proper data alignment
  48. static const __int64 mmMask0001= 0x0001000100010001;
  49. static const __int64 mmMask0002= 0x0002000200020002;
  50. static const __int64 mmMask0004= 0x0004000400040004;
  51. static const __int64 mmMask0101= 0x0101010101010101;
  52. static const __int64 mmMask00FF= 0x00FF00FF00FF00FF;
  53. static const __int64 mmMaskFFFF= 0xFFFFFFFFFFFFFFFF;
  54. static const __int64 mmMaskFEFE= 0xFEFEFEFEFEFEFEFE;
  55. static const __int64 mmMask9th = 0x00FF000000000000;
  56.  
  57.  
  58. void 
  59. form_predictions(bx,by,macroblock_type,motion_type,PMV,motion_vertical_field_select,dmvector,stwtype)
  60. int bx, by;
  61. int macroblock_type;
  62. int motion_type;
  63. int PMV[2][2][2], motion_vertical_field_select[2][2], dmvector[2];
  64. int stwtype;
  65. {
  66.   static int currentfield;
  67.   static unsigned char **predframe;
  68.   static int DMV[2][2];
  69.   static int stwtop, stwbot;
  70.  
  71.   stwtop = stwtype%3; /* 0:temporal, 1:(spat+temp)/2, 2:spatial */
  72.   stwbot = stwtype/3;
  73.  
  74.   if ((macroblock_type & MACROBLOCK_MOTION_FORWARD) 
  75.    || (picture_coding_type==P_TYPE))
  76.   {
  77.     if (picture_structure==FRAME_PICTURE)
  78.     {
  79.       if ((motion_type==MC_FRAME) 
  80.         || !(macroblock_type & MACROBLOCK_MOTION_FORWARD))
  81.       {
  82.         /* frame-based prediction (broken into top and bottom halves
  83.              for spatial scalability prediction purposes) */
  84.         if (stwtop<2)
  85.           form_prediction(forward_reference_frame,0,current_frame,0,
  86.             Coded_Picture_Width,Coded_Picture_Width<<1,16,8,bx,by,
  87.             PMV[0][0][0],PMV[0][0][1],stwtop);
  88.  
  89.         if (stwbot<2)
  90.           form_prediction(forward_reference_frame,1,current_frame,1,
  91.             Coded_Picture_Width,Coded_Picture_Width<<1,16,8,bx,by,
  92.             PMV[0][0][0],PMV[0][0][1],stwbot);
  93.       }
  94.       else if (motion_type==MC_FIELD) /* field-based prediction */
  95.       {
  96.         /* top field prediction */
  97.         if (stwtop<2)
  98.           form_prediction(forward_reference_frame,motion_vertical_field_select[0][0],
  99.             current_frame,0,Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,8,
  100.             bx,by>>1,PMV[0][0][0],PMV[0][0][1]>>1,stwtop);
  101.  
  102.         /* bottom field prediction */
  103.         if (stwbot<2)
  104.           form_prediction(forward_reference_frame,motion_vertical_field_select[1][0],
  105.             current_frame,1,Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,8,
  106.             bx,by>>1,PMV[1][0][0],PMV[1][0][1]>>1,stwbot);
  107.       }
  108.       else if (motion_type==MC_DMV) /* dual prime prediction */
  109.       {
  110.         /* calculate derived motion vectors */
  111.         Dual_Prime_Arithmetic(DMV,dmvector,PMV[0][0][0],PMV[0][0][1]>>1);
  112.  
  113.         if (stwtop<2)
  114.         {
  115.           /* predict top field from top field */
  116.           form_prediction(forward_reference_frame,0,current_frame,0,
  117.             Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,8,bx,by>>1,
  118.             PMV[0][0][0],PMV[0][0][1]>>1,0);
  119.  
  120.           /* predict and add to top field from bottom field */
  121.           form_prediction(forward_reference_frame,1,current_frame,0,
  122.             Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,8,bx,by>>1,
  123.             DMV[0][0],DMV[0][1],1);
  124.         }
  125.  
  126.         if (stwbot<2)
  127.         {
  128.           /* predict bottom field from bottom field */
  129.           form_prediction(forward_reference_frame,1,current_frame,1,
  130.             Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,8,bx,by>>1,
  131.             PMV[0][0][0],PMV[0][0][1]>>1,0);
  132.  
  133.           /* predict and add to bottom field from top field */
  134.           form_prediction(forward_reference_frame,0,current_frame,1,
  135.             Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,8,bx,by>>1,
  136.             DMV[1][0],DMV[1][1],1);
  137.         }
  138.       }
  139.       else
  140.         /* invalid motion_type */
  141.         printf("invalid motion_type\n");
  142.     }
  143.     else /* TOP_FIELD or BOTTOM_FIELD */
  144.     {
  145.       /* field picture */
  146.       currentfield = (picture_structure==BOTTOM_FIELD);
  147.  
  148.       /* determine which frame to use for prediction */
  149.       if ((picture_coding_type==P_TYPE) && Second_Field
  150.          && (currentfield!=motion_vertical_field_select[0][0]))
  151.         predframe = backward_reference_frame; /* same frame */
  152.       else
  153.         predframe = forward_reference_frame; /* previous frame */
  154.  
  155.       if ((motion_type==MC_FIELD)
  156.         || !(macroblock_type & MACROBLOCK_MOTION_FORWARD))
  157.       {
  158.         /* field-based prediction */
  159.         if (stwtop<2)
  160.           form_prediction(predframe,motion_vertical_field_select[0][0],current_frame,0,
  161.             Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,16,bx,by,
  162.             PMV[0][0][0],PMV[0][0][1],stwtop);
  163.       }
  164.       else if (motion_type==MC_16X8)
  165.       {
  166.         if (stwtop<2)
  167.         {
  168.           form_prediction(predframe,motion_vertical_field_select[0][0],current_frame,0,
  169.             Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,8,bx,by,
  170.             PMV[0][0][0],PMV[0][0][1],stwtop);
  171.  
  172.           /* determine which frame to use for lower half prediction */
  173.           if ((picture_coding_type==P_TYPE) && Second_Field
  174.              && (currentfield!=motion_vertical_field_select[1][0]))
  175.             predframe = backward_reference_frame; /* same frame */
  176.           else
  177.             predframe = forward_reference_frame; /* previous frame */
  178.  
  179.           form_prediction(predframe,motion_vertical_field_select[1][0],current_frame,0,
  180.             Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,8,bx,by+8,
  181.             PMV[1][0][0],PMV[1][0][1],stwtop);
  182.         }
  183.       }
  184.       else if (motion_type==MC_DMV) /* dual prime prediction */
  185.       {
  186.         if (Second_Field)
  187.           predframe = backward_reference_frame; /* same frame */
  188.         else
  189.           predframe = forward_reference_frame; /* previous frame */
  190.  
  191.         /* calculate derived motion vectors */
  192.         Dual_Prime_Arithmetic(DMV,dmvector,PMV[0][0][0],PMV[0][0][1]);
  193.  
  194.         /* predict from field of same parity */
  195.         form_prediction(forward_reference_frame,currentfield,current_frame,0,
  196.           Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,16,bx,by,
  197.           PMV[0][0][0],PMV[0][0][1],0);
  198.  
  199.         /* predict from field of opposite parity */
  200.         form_prediction(predframe,!currentfield,current_frame,0,
  201.           Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,16,bx,by,
  202.           DMV[0][0],DMV[0][1],1);
  203.       }
  204.       else
  205.         /* invalid motion_type */
  206.         printf("invalid motion_type\n");
  207.     }
  208.     stwtop = stwbot = 1;
  209.   }
  210.  
  211.   if (macroblock_type & MACROBLOCK_MOTION_BACKWARD)
  212.   {
  213.     if (picture_structure==FRAME_PICTURE)
  214.     {
  215.       if (motion_type==MC_FRAME)
  216.       {
  217.         /* frame-based prediction */
  218.         if (stwtop<2)
  219.           form_prediction(backward_reference_frame,0,current_frame,0,
  220.             Coded_Picture_Width,Coded_Picture_Width<<1,16,8,bx,by,
  221.             PMV[0][1][0],PMV[0][1][1],stwtop);
  222.  
  223.         if (stwbot<2)
  224.           form_prediction(backward_reference_frame,1,current_frame,1,
  225.             Coded_Picture_Width,Coded_Picture_Width<<1,16,8,bx,by,
  226.             PMV[0][1][0],PMV[0][1][1],stwbot);
  227.       }
  228.       else /* field-based prediction */
  229.       {
  230.         /* top field prediction */
  231.         if (stwtop<2)
  232.           form_prediction(backward_reference_frame,motion_vertical_field_select[0][1],
  233.             current_frame,0,Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,8,
  234.             bx,by>>1,PMV[0][1][0],PMV[0][1][1]>>1,stwtop);
  235.  
  236.         /* bottom field prediction */
  237.         if (stwbot<2)
  238.           form_prediction(backward_reference_frame,motion_vertical_field_select[1][1],
  239.             current_frame,1,Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,8,
  240.             bx,by>>1,PMV[1][1][0],PMV[1][1][1]>>1,stwbot);
  241.       }
  242.     }
  243.     else /* TOP_FIELD or BOTTOM_FIELD */
  244.     {
  245.       /* field picture */
  246.       if (motion_type==MC_FIELD)
  247.       {
  248.         /* field-based prediction */
  249.         form_prediction(backward_reference_frame,motion_vertical_field_select[0][1],
  250.           current_frame,0,Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,16,
  251.           bx,by,PMV[0][1][0],PMV[0][1][1],stwtop);
  252.       }
  253.       else if (motion_type==MC_16X8)
  254.       {
  255.         form_prediction(backward_reference_frame,motion_vertical_field_select[0][1],
  256.           current_frame,0,Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,8,
  257.           bx,by,PMV[0][1][0],PMV[0][1][1],stwtop);
  258.  
  259.         form_prediction(backward_reference_frame,motion_vertical_field_select[1][1],
  260.           current_frame,0,Coded_Picture_Width<<1,Coded_Picture_Width<<1,16,8,
  261.           bx,by+8,PMV[1][1][0],PMV[1][1][1],stwtop);
  262.       }
  263.       else
  264.         /* invalid motion_type */
  265.         printf("invalid motion_type\n");
  266.     }
  267.   }
  268. }
  269.  
  270. static void form_prediction(src,sfield,dst,dfield,lx,lx2,w,h,x,y,dx,dy,average_flag)
  271. unsigned char *src[]; /* prediction source buffer */
  272. int sfield;           /* prediction source field number (0 or 1) */
  273. unsigned char *dst[]; /* prediction destination buffer */
  274. int dfield;           /* prediction destination field number (0 or 1)*/
  275. int lx,lx2;           /* line strides */
  276. int w,h;              /* prediction block/sub-block width, height */
  277. int x,y;              /* pixel co-ordinates of top-left sample in current MB */
  278. int dx,dy;            /* horizontal, vertical prediction address */
  279. int average_flag;     /* add prediction error to prediction ? */
  280. {
  281.   /* Y */
  282.   form_component_prediction(src[0]+(sfield?lx2>>1:0),dst[0]+(dfield?lx2>>1:0),
  283.     lx,lx2,w,h,x,y,dx,dy,average_flag);
  284. /*
  285.   if (chroma_format!=CHROMA444)
  286.   {
  287.     lx>>=1; lx2>>=1; w>>=1; x>>=1; dx/=2;
  288.   }
  289.  
  290.   if (chroma_format==CHROMA420)
  291.   {
  292.     h>>=1; y>>=1; dy/=2;
  293.   }
  294. */
  295.   if (chroma_format!=CHROMA444)
  296.   {
  297.       lx>>=1; lx2>>=1; w>>=1; x>>=1; dx/=2;
  298.  
  299.       if (chroma_format==CHROMA420)
  300.       {
  301.         h>>=1; y>>=1; dy/=2;
  302.       }
  303.   }
  304.  
  305.  
  306.   /* Cb */
  307.   form_component_prediction(src[1]+(sfield?lx2>>1:0),dst[1]+(dfield?lx2>>1:0),
  308.     lx,lx2,w,h,x,y,dx,dy,average_flag);
  309.  
  310.   /* Cr */
  311.   form_component_prediction(src[2]+(sfield?lx2>>1:0),dst[2]+(dfield?lx2>>1:0),
  312.     lx,lx2,w,h,x,y,dx,dy,average_flag);
  313.  
  314. }
  315.  
  316. /* ISO/IEC 13818-2 section 7.6.4: Forming predictions */
  317. /* NOTE: the arithmetic below produces numerically equivalent results
  318.  *  to 7.6.4, yet is more elegant. It differs in the following ways:
  319.  *
  320.  *   1. the vectors (dx, dy) are based on cartesian frame 
  321.  *      coordiantes along a half-pel grid (always positive numbers)
  322.  *      In contrast, vector[r][s][t] are differential (with positive and 
  323.  *      negative values). As a result, deriving the integer vectors 
  324.  *      (int_vec[t]) from dx, dy is accomplished by a simple right shift.
  325.  *
  326.  *   2. Half pel flags (xh, yh) are equivalent to the LSB (Least
  327.  *      Significant Bit) of the half-pel coordinates (dx,dy).
  328.  * 
  329.  *
  330.  *  NOTE: the work of combining predictions (ISO/IEC 13818-2 section 7.6.7)
  331.  *  is distributed among several other stages.  This is accomplished by 
  332.  *  folding line offsets into the source and destination (src,dst)
  333.  *  addresses (note the call arguments to form_prediction() in Predict()),
  334.  *  line stride variables lx and lx2, the block dimension variables (w,h), 
  335.  *  average_flag, and by the very order in which Predict() is called.  
  336.  *  This implementation design (implicitly different than the spec) 
  337.  *  was chosen for its elegance.
  338. */
  339.  
  340. #define IS_XHALF ( dx & 0x01 )
  341. #define IS_YHALF ( dy & 0x01 )
  342.  
  343. static 
  344. void form_component_prediction(src,dst,lx,lx2,w,h,x,y,dx,dy,average_flag)
  345. unsigned char *src;
  346. unsigned char *dst;
  347. int lx;          /* raster line increment */ 
  348. int lx2;
  349. int w,h;
  350. int x,y;
  351. int dx,dy;
  352. int average_flag;      /* flag that signals bi-directional or Dual-Prime 
  353.                           averaging (7.6.7.1 and 7.6.7.4). if average_flag==1,
  354.                           a previously formed prediction has been stored in 
  355.                           pel_pred[] */
  356. {
  357.  
  358. #if 0
  359.     static const __int64 mmmask_0001 = 0x0001000100010001;
  360.     static const __int64 mmmask_0002 = 0x0002000200020002;
  361.     static const __int64 mmmask_0003 = 0x0003000300030003;
  362.     static const __int64 mmmask_0006 = 0x0006000600060006;
  363.  
  364.     unsigned char *s = src + lx * (y + (dy>>1)) + x + (dx>>1);
  365.     unsigned char *d = dst + lx * y + x;
  366.     int flag = (average_flag<<2) + ((dx & 1)<<1) + (dy & 1);
  367.  
  368.     switch (flag)
  369.     {
  370.         case 0:
  371.             // d[i] = s[i];
  372.             __asm
  373.             {
  374.                 mov            eax, [s]
  375.                 mov            ebx, [d]
  376.                 mov            esi, 0x00
  377.                 mov            edi, [h]
  378. mc0:
  379.                 movq        mm1, [eax+esi]
  380.                 add            esi, 0x08
  381.                 cmp            esi, [w]
  382.                 movq        [ebx+esi-8], mm1
  383.                 jl            mc0
  384.  
  385.                 add            eax, [lx2]
  386.                 add            ebx, [lx2]
  387.                 sub            edi, 0x01
  388.                 mov            esi, 0x00
  389.                 cmp            edi, 0x00
  390.                 jg            mc0
  391.  
  392.                 emms
  393.             }
  394.             break;
  395.  
  396.         case 1:
  397.             // d[i] = (s[i]+s[i+lx]+1)>>1;
  398.             __asm
  399.             {
  400.                 pxor        mm0, mm0
  401.                 movq        mm7, [mmmask_0001]
  402.                 mov            eax, [s]
  403.                 mov            ebx, [d]
  404.                 mov            ecx, eax
  405.                 add            ecx, [lx]
  406.                 mov            esi, 0x00
  407.                 mov            edi, [h]
  408. mc1:
  409.                 movq        mm1, [eax+esi]
  410.                 movq        mm2, [ecx+esi]
  411.  
  412.                 movq        mm3, mm1
  413.                 movq        mm4, mm2
  414.  
  415.                 punpcklbw    mm1, mm0
  416.                 punpckhbw    mm3, mm0
  417.                 punpcklbw    mm2, mm0
  418.                 punpckhbw    mm4, mm0
  419.  
  420.                 paddsw        mm1, mm2
  421.                 paddsw        mm3, mm4
  422.  
  423.                 paddsw        mm1, mm7
  424.                 paddsw        mm3, mm7
  425.  
  426.                 psrlw        mm1, 1
  427.                 psrlw        mm3, 1
  428.  
  429.                 packuswb    mm1, mm0
  430.                 packuswb    mm3, mm0
  431.  
  432.                 psllq        mm3, 32
  433.                 por            mm1, mm3
  434.  
  435.                 add            esi, 0x08
  436.                 cmp            esi, [w]
  437.                 movq        [ebx+esi-8], mm1
  438.                 jl            mc1
  439.  
  440.                 add            eax, [lx2]
  441.                 add            ebx, [lx2]
  442.                 add            ecx, [lx2]
  443.                 sub            edi, 0x01
  444.                 mov            esi, 0x00
  445.                 cmp            edi, 0x00
  446.                 jg            mc1
  447.  
  448.                 emms
  449.             }
  450.             break;
  451.  
  452.         case 2:
  453.             // d[i] = (s[i]+s[i+1]+1)>>1;
  454.             __asm
  455.             {
  456.                 pxor        mm0, mm0
  457.                 movq        mm7, [mmmask_0001]
  458.                 mov            eax, [s]
  459.                 mov            ebx, [d]
  460.                 mov            esi, 0x00
  461.                 mov            edi, [h]
  462. mc2:
  463.                 movq        mm1, [eax+esi]
  464.                 movq        mm2, [eax+esi+1]
  465.  
  466.                 movq        mm3, mm1
  467.                 movq        mm4, mm2
  468.  
  469.                 punpcklbw    mm1, mm0
  470.                 punpckhbw    mm3, mm0
  471.  
  472.                 punpcklbw    mm2, mm0
  473.                 punpckhbw    mm4, mm0
  474.  
  475.                 paddsw        mm1, mm2
  476.                 paddsw        mm3, mm4
  477.  
  478.                 paddsw        mm1, mm7
  479.                 paddsw        mm3, mm7
  480.  
  481.                 psrlw        mm1, 1
  482.                 psrlw        mm3, 1
  483.  
  484.                 packuswb    mm1, mm0
  485.                 packuswb    mm3, mm0
  486.  
  487.                 psllq        mm3, 32
  488.                 por            mm1, mm3
  489.  
  490.                 add            esi, 0x08
  491.                 cmp            esi, [w]
  492.                 movq        [ebx+esi-8], mm1
  493.                 jl            mc2
  494.  
  495.                 add            eax, [lx2]
  496.                 add            ebx, [lx2]
  497.                 sub            edi, 0x01
  498.                 mov            esi, 0x00
  499.                 cmp            edi, 0x00
  500.                 jg            mc2
  501.  
  502.                 emms
  503.             }
  504.             break;
  505.  
  506.         case 3:
  507.             // d[i] = (s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2;
  508.             __asm
  509.             {
  510.                 pxor        mm0, mm0
  511.                 movq        mm7, [mmmask_0002]
  512.                 mov            eax, [s]
  513.                 mov            ebx, [d]
  514.                 mov            ecx, eax
  515.                 add            ecx, [lx]
  516.                 mov            esi, 0x00
  517.                 mov            edi, [h]
  518. mc3:
  519.                 movq        mm1, [eax+esi]
  520.                 movq        mm2, [eax+esi+1]
  521.                 movq        mm3, mm1
  522.                 movq        mm4, mm2
  523.  
  524.                 punpcklbw    mm1, mm0
  525.                 punpckhbw    mm3, mm0
  526.  
  527.                 punpcklbw    mm2, mm0
  528.                 punpckhbw    mm4, mm0
  529.  
  530.                 paddsw        mm1, mm2
  531.                 paddsw        mm3, mm4
  532.  
  533.                 movq        mm5, [ecx+esi]
  534.                 paddsw        mm1, mm7
  535.  
  536.                 movq        mm6, [ecx+esi+1]
  537.                 paddsw        mm3, mm7
  538.  
  539.                 movq        mm2, mm5
  540.                 movq        mm4, mm6
  541.  
  542.                 punpcklbw    mm2, mm0
  543.                 punpckhbw    mm5, mm0
  544.  
  545.                 punpcklbw    mm4, mm0
  546.                 punpckhbw    mm6, mm0
  547.                 
  548.                 paddsw        mm2, mm4
  549.                 paddsw        mm5, mm6
  550.  
  551.                 paddsw        mm1, mm2
  552.                 paddsw        mm3, mm5
  553.  
  554.                 psrlw        mm1, 2
  555.                 psrlw        mm3, 2
  556.  
  557.                 packuswb    mm1, mm0
  558.                 packuswb    mm3, mm0
  559.  
  560.                 psllq        mm3, 32
  561.                 por            mm1, mm3
  562.  
  563.                 add            esi, 0x08
  564.                 cmp            esi, [w]
  565.                 movq        [ebx+esi-8], mm1
  566.                 jl            mc3
  567.  
  568.                 add            eax, [lx2]
  569.                 add            ebx, [lx2]
  570.                 add            ecx, [lx2]
  571.                 sub            edi, 0x01
  572.                 mov            esi, 0x00
  573.                 cmp            edi, 0x00
  574.                 jg            mc3
  575.  
  576.                 emms
  577.             }
  578.             break;
  579.  
  580.         case 4:
  581.             // d[i] = (s[i]+d[i]+1)>>1;
  582.             __asm
  583.             {
  584.                 pxor        mm0, mm0
  585.                 movq        mm7, [mmmask_0001]
  586.                 mov            eax, [s]
  587.                 mov            ebx, [d]
  588.                 mov            esi, 0x00
  589.                 mov            edi, [h]
  590. mc4:
  591.                 movq        mm1, [eax+esi]
  592.                 movq        mm2, [ebx+esi]
  593.                 movq        mm3, mm1
  594.                 movq        mm4, mm2
  595.  
  596.                 punpcklbw    mm1, mm0
  597.                 punpckhbw    mm3, mm0
  598.  
  599.                 punpcklbw    mm2, mm0
  600.                 punpckhbw    mm4, mm0
  601.  
  602.                 paddsw        mm1, mm2
  603.                 paddsw        mm3, mm4
  604.  
  605.                 paddsw        mm1, mm7
  606.                 paddsw        mm3, mm7
  607.  
  608.                 psrlw        mm1, 1
  609.                 psrlw        mm3, 1
  610.  
  611.                 packuswb    mm1, mm0
  612.                 packuswb    mm3, mm0
  613.  
  614.                 psllq        mm3, 32
  615.                 por            mm1, mm3
  616.  
  617.                 add            esi, 0x08
  618.                 cmp            esi, [w]
  619.                 movq        [ebx+esi-8], mm1
  620.                 jl            mc4
  621.  
  622.                 add            eax, [lx2]
  623.                 add            ebx, [lx2]
  624.                 sub            edi, 0x01
  625.                 mov            esi, 0x00
  626.                 cmp            edi, 0x00
  627.                 jg            mc4
  628.  
  629.                 emms
  630.             }
  631.             break;
  632.  
  633.         case 5:
  634.             // d[i] = ((d[i]<<1) + s[i]+s[i+lx] + 3)>>2;
  635.             __asm
  636.             {
  637.                 pxor        mm0, mm0
  638.                 movq        mm7, [mmmask_0003]
  639.                 mov            eax, [s]
  640.                 mov            ebx, [d]
  641.                 mov            ecx, eax
  642.                 add            ecx, [lx]
  643.                 mov            esi, 0x00
  644.                 mov            edi, [h]
  645. mc5:
  646.                 movq        mm1, [eax+esi]
  647.                 movq        mm2, [ecx+esi]
  648.                 movq        mm3, mm1
  649.                 movq        mm4, mm2
  650.  
  651.                 punpcklbw    mm1, mm0
  652.                 punpckhbw    mm3, mm0
  653.  
  654.                 punpcklbw    mm2, mm0
  655.                 punpckhbw    mm4, mm0
  656.  
  657.                 paddsw        mm1, mm2
  658.                 paddsw        mm3, mm4
  659.  
  660.                 movq        mm5, [ebx+esi]
  661.  
  662.                 paddsw        mm1, mm7
  663.                 paddsw        mm3, mm7
  664.  
  665.                 movq        mm6, mm5
  666.                 punpcklbw    mm5, mm0
  667.                 punpckhbw    mm6, mm0
  668.  
  669.                 psllw        mm5, 1
  670.                 psllw        mm6, 1
  671.  
  672.                 paddsw        mm1, mm5
  673.                 paddsw        mm3, mm6
  674.  
  675.                 psrlw        mm1, 2
  676.                 psrlw        mm3, 2
  677.  
  678.                 packuswb    mm1, mm0
  679.                 packuswb    mm3, mm0
  680.  
  681.                 psllq        mm3, 32
  682.                 por            mm1, mm3
  683.  
  684.                 add            esi, 0x08
  685.                 cmp            esi, [w]
  686.                 movq        [ebx+esi-8], mm1
  687.                 jl            mc5
  688.  
  689.                 add            eax, [lx2]
  690.                 add            ebx, [lx2]
  691.                 add            ecx, [lx2]
  692.                 sub            edi, 0x01
  693.                 mov            esi, 0x00
  694.                 cmp            edi, 0x00
  695.                 jg            mc5
  696.  
  697.                 emms
  698.             }
  699.             break;
  700.  
  701.         case 6:
  702.             // d[i] = ((d[i]<<1) + s[i]+s[i+1] + 3) >> 2;
  703.             __asm
  704.             {
  705.                 pxor        mm0, mm0
  706.                 movq        mm7, [mmmask_0003]
  707.                 mov            eax, [s]
  708.                 mov            ebx, [d]
  709.                 mov            esi, 0x00
  710.                 mov            edi, [h]
  711. mc6:
  712.                 movq        mm1, [eax+esi]
  713.                 movq        mm2, [eax+esi+1]
  714.                 movq        mm3, mm1
  715.                 movq        mm4, mm2
  716.  
  717.                 punpcklbw    mm1, mm0
  718.                 punpckhbw    mm3, mm0
  719.  
  720.                 punpcklbw    mm2, mm0
  721.                 punpckhbw    mm4, mm0
  722.  
  723.                 paddsw        mm1, mm2
  724.                 paddsw        mm3, mm4
  725.  
  726.                 movq        mm5, [ebx+esi]
  727.  
  728.                 paddsw        mm1, mm7
  729.                 paddsw        mm3, mm7
  730.  
  731.                 movq        mm6, mm5
  732.                 punpcklbw    mm5, mm0
  733.                 punpckhbw    mm6, mm0
  734.  
  735.                 psllw        mm5, 1
  736.                 psllw        mm6, 1
  737.  
  738.                 paddsw        mm1, mm5
  739.                 paddsw        mm3, mm6
  740.  
  741.                 psrlw        mm1, 2
  742.                 psrlw        mm3, 2
  743.  
  744.                 packuswb    mm1, mm0
  745.                 packuswb    mm3, mm0
  746.  
  747.                 psllq        mm3, 32
  748.                 por            mm1, mm3
  749.  
  750.                 add            esi, 0x08
  751.                 cmp            esi, [w]
  752.                 movq        [ebx+esi-8], mm1
  753.                 jl            mc6
  754.  
  755.                 add            eax, [lx2]
  756.                 add            ebx, [lx2]
  757.                 sub            edi, 0x01
  758.                 mov            esi, 0x00
  759.                 cmp            edi, 0x00
  760.                 jg            mc6
  761.  
  762.                 emms
  763.             }
  764.             break;
  765.  
  766.         default:
  767.             // d[i] = ((d[i]<<2) + s[i]+s[i+1]+s[i+lx]+s[i+lx+1] + 6)>>3;
  768.             __asm
  769.             {
  770.                 pxor        mm0, mm0
  771.                 movq        mm7, [mmmask_0006]
  772.                 mov            eax, [s]
  773.                 mov            ebx, [d]
  774.                 mov            ecx, eax
  775.                 add            ecx, [lx]
  776.                 mov            esi, 0x00
  777.                 mov            edi, [h]
  778. mc7:
  779.                 movq        mm1, [eax+esi]
  780.                 movq        mm2, [eax+esi+1]
  781.                 movq        mm3, mm1
  782.                 movq        mm4, mm2
  783.  
  784.                 punpcklbw    mm1, mm0
  785.                 punpckhbw    mm3, mm0
  786.  
  787.                 punpcklbw    mm2, mm0
  788.                 punpckhbw    mm4, mm0
  789.  
  790.                 paddsw        mm1, mm2
  791.                 paddsw        mm3, mm4
  792.  
  793.                 movq        mm5, [ecx+esi]
  794.                 paddsw        mm1, mm7
  795.  
  796.                 movq        mm6, [ecx+esi+1]
  797.                 paddsw        mm3, mm7
  798.  
  799.                 movq        mm2, mm5
  800.                 movq        mm4, mm6
  801.  
  802.                 punpcklbw    mm2, mm0
  803.                 punpckhbw    mm5, mm0
  804.  
  805.                 punpcklbw    mm4, mm0
  806.                 punpckhbw    mm6, mm0
  807.                 
  808.                 paddsw        mm2, mm4
  809.                 paddsw        mm5, mm6
  810.  
  811.                 paddsw        mm1, mm2
  812.                 paddsw        mm3, mm5
  813.  
  814.                 movq        mm6, [ebx+esi]
  815.  
  816.                 movq        mm4, mm6
  817.                 punpcklbw    mm4, mm0
  818.                 punpckhbw    mm6, mm0
  819.  
  820.                 psllw        mm4, 2
  821.                 psllw        mm6, 2
  822.  
  823.                 paddsw        mm1, mm4
  824.                 paddsw        mm3, mm6
  825.  
  826.                 psrlw        mm1, 3
  827.                 psrlw        mm3, 3
  828.  
  829.                 packuswb    mm1, mm0
  830.                 packuswb    mm3, mm0
  831.  
  832.                 psllq        mm3, 32
  833.                 por            mm1, mm3
  834.  
  835.                 add            esi, 0x08
  836.                 cmp            esi, [w]
  837.                 movq        [ebx+esi-8], mm1
  838.                 jl            mc7
  839.  
  840.                 add            eax, [lx2]
  841.                 add            ebx, [lx2]
  842.                 add            ecx, [lx2]
  843.                 sub            edi, 0x01
  844.                 mov            esi, 0x00
  845.                 cmp            edi, 0x00
  846.                 jg            mc7
  847.  
  848.                 emms
  849.             }
  850.             break;
  851.     }
  852.  
  853. #else
  854.  
  855.   static int xint;      /* horizontal integer sample vector: analogous to int_vec[0] */
  856.   static int yint;      /* vertical integer sample vectors: analogous to int_vec[1] */
  857. //  static int xh;        /* horizontal half sample flag: analogous to half_flag[0]  */
  858. //  static int yh;        /* vertical half sample flag: analogous to half_flag[1]  */
  859.   static int lx2_x2;
  860.   /*int i, j, v;*/
  861.   static unsigned char *s;    /* source pointer: analogous to pel_ref[][]   */
  862.   static unsigned char *d;    /* destination pointer:  analogous to pel_pred[][]  */
  863. //  static unsigned long *p_lsrc;  /* DWORD pointer to source */
  864. //  static unsigned long *p_ldst;  /* DWORD pointer to dest */
  865.   static unsigned long *p_Alsrc; /* QWORD aligned version of p_lsrc */
  866.   static unsigned long *p_Aldst; /* QWORD aligned version of p_ldst */
  867.   static __int64 dSLLamt, dSRLamt; /* dst shift amount for alignment */
  868.   static DWORD sSLLamt, sSRLamt; /* src shift amount for alignment */
  869.   static DWORD sSLLamt_minus_8;
  870.  
  871.   // mmMask definitions moved to global scope, to enforce QWORD alignment
  872.  
  873.   lx2_x2 = (lx2<<1); /* two times lx2 */
  874.  
  875.   /* half pel scaling for integer vectors */
  876.   xint = dx>>1;
  877.   yint = dy>>1;
  878.  
  879.   /* derive half pel flags */
  880. //  xh = dx & 1;
  881. //  yh = dy & 1;
  882.  
  883.   /* compute the linear address of pel_ref[][] and pel_pred[][] 
  884.      based on cartesian/raster cordinates provided */
  885.   s = src + lx*(y+yint) + x + xint;
  886.   d = dst + lx*y + x;
  887.  
  888. //  p_lsrc = (unsigned long *) s;
  889. //  p_ldst = (unsigned long *) d;
  890.  
  891.   p_Alsrc = (unsigned long*)((DWORD)s & 0xFFFFFFF8); // calculate QWORD aligned address
  892.   p_Aldst = (unsigned long*)((DWORD)d & 0xFFFFFFF8); // calculate QWORD aligned address
  893.  
  894.       // calculate byte shift amounts
  895.   sSRLamt = ((DWORD) s )- ((DWORD) p_Alsrc );
  896.   dSRLamt = (__int64)(((DWORD) d )- ((DWORD) p_Aldst ));
  897.   sSRLamt = sSRLamt << 3;    // convert byte-shift amt to bit shift amount
  898.   dSRLamt = dSRLamt << 3;    // convert byte-shift amt to bit shift amount
  899.   sSLLamt = 64 - sSRLamt;
  900.   dSLLamt = 64 - dSRLamt;
  901.   sSLLamt_minus_8 = sSLLamt - 8;
  902.  
  903.   if (average_flag)
  904.   { 
  905.     if (!IS_XHALF && !IS_YHALF) /* no horizontal nor vertical half-pel */
  906.     {
  907. //      for (j=0; j<h; j++) /* yes average, fullX, fullY */
  908. //      {
  909. //        for (i=0; i<w; i++)
  910. //        {
  911. //          v = d[i]+s[i];
  912. //          /*d[i] = (v+(v>=0?1:0))>>1;*/
  913. //          d[i] = (v+1)>>1;
  914. //        }
  915. //
  916. //        s+= lx2;
  917. //        d+= lx2;
  918. //      }
  919.       __asm
  920.       { // yes average, fullX, fullY
  921.         // each processes 8-pixels, 8 pixels are written per iteration
  922.         // there is some minor software pipelining to reduce the
  923.         // store latency
  924.         mov edx, [lx2]    ; edx <= lx2
  925.          mov ecx, 0x00 ; ecx <= 0
  926.  
  927.         movd mm5, dword ptr [sSRLamt ];    // mm5 = right-shift src alignment
  928.  
  929.         movd mm6, dword ptr [sSLLamt ];    // mm6 = left-shift src alignment
  930.  
  931.         movq mm7, qword ptr [mmMaskFEFE];    mm7 <= 0xFEFEFEFEFE...
  932.         
  933.         mov esi, dword ptr [p_Alsrc ]        ;esi <= aligned p_lsrc[]
  934.  
  935.         mov edi, dword ptr [d ]        ;edi <= p_ldst[0]
  936.  
  937.         mov ebx, dword ptr [p_Aldst]    ; ebx <= aligned p_ldst[]
  938.  
  939.         //srl  ebx, 3        ; ebx <= (w >> 3)  (width / 8)
  940.         mov eax, [h]    ; eax <= h
  941.          jmp lp_afxfy;    // skip the first store
  942.  
  943.       lp_afxfy_st: // outer loop for( y =0; y < H; ++y )
  944.         movq qword ptr [ edi + ecx - 8], mm3    ;p_ldst[ i ] <= mm3
  945.  
  946.         // begin inner loop for ( ecx=0; ecx < ebx; ecx += 8 )
  947.       lp_afxfy : // Average, FullX/FullY
  948.         // the read data operation is fairly invovled, to enforce QWORD 
  949.         // aligned reads
  950.  
  951.         movq mm0, qword ptr [ esi + ecx ]    ;mm1 <= p_Alsrc[ 8..1 ]
  952. //         movq mm3, mm0    ; mm3 <= Mask
  953.         movq mm1, qword ptr [ esi + ecx +8]    ;mm1 <= p_Alsrc[ 16..9 ]
  954.          psrlq mm0, mm5;    // align [8..1]
  955.  
  956.         movq mm2, qword ptr [ ebx + ecx ]    ;mm2 <= p_Aldst[ 8..1 ]
  957.          psllq mm1, mm6;    // align [16..9]
  958.  
  959.         movq mm3, qword ptr [ ebx + ecx +8]    ;mm2 <= p_Aldst[ 8..1 ]
  960.          por mm0, mm1;    // mm0 = desired pixels src[8..1]
  961.  
  962.         psrlq mm2, qword ptr [ dSRLamt ];
  963.          movq mm1, mm0;    // mm1 = copy of mm0, pixels src[8..1]
  964.  
  965.         psllq mm3, qword ptr [ dSLLamt ];
  966.          pand mm0, mm7; // mm0 = MSB7 of src[8..1]
  967.  
  968.         por mm2, mm3;    // mm2 = desired pixels dst[8..1]
  969.          psrlw mm0, 1;    // mm0 = src[8..1] / 2
  970.  
  971.         movq mm3, mm2;    // mm3 = copy of mm2, pixels dst[8..1]
  972.          pand mm2, mm7; // mm2 = MSB7 of dst[8..1]
  973.  
  974.         psrlw mm2, 1;    // mm2 = dst[8..1] / 2
  975.          por mm3, mm1;    // mm3 = SRC[] OR DST[]
  976.  
  977.         pand mm3, qword ptr [mmMask0101]; // mm3 = "+1" rounding compensation
  978.          paddusb mm2, mm0;    // mm2 = (src+dst) / 2
  979.  
  980.         add ecx, 0x08;
  981.          paddusb mm3, mm2;    // mm3 = final result dst[8..1]
  982.  
  983.         cmp ecx, [w];  ; // compare i <> width 
  984.     // instead of storing result here, causing a stall, the store
  985.     // is moved to the beginning of the loop (past the branch-compare)
  986.  
  987.     //    movq qword ptr [ edi + ecx - 8], mm3    ;p_ldst[ i ] <= mm3
  988.  
  989.         jb lp_afxfy_st;       ; // if ( i < width ) loop
  990.          sub eax, 0x01        ; j = j -1
  991.  
  992.     // since we moved the store *after* the branch, we need to duplicate
  993.     // the store statement for each branch-possibility
  994.         movq qword ptr [ edi + ecx - 8], mm3    ;p_ldst[ i ] <= mm3
  995.          add esi, edx    ;p_Alsrc += lx2
  996.  
  997.         add ebx, edx    ;p_Aldst += lx2
  998.         add edi, edx    ;p_ldst += lx2
  999.          mov ecx, 0x00000000        ; i = 0;
  1000.  
  1001.         cmp eax, 0        ; compare j <> 0
  1002.          jg    lp_afxfy        ; if ( j >= 0 ) loop
  1003.       } // end __asm, end of yes average, fullX, fullY
  1004.     }
  1005.     else if (!IS_XHALF && IS_YHALF) /* no horizontal but vertical half-pel */
  1006.     {
  1007.         // this MMX routine reads 4 x 2 pixels per iteration
  1008.         // this MMX routine outputs 4 pixels per iteration.
  1009.         // all reads (source and dest) are DWORD aligned
  1010.     __asm    
  1011.       {    // yes average, fullX, halfY
  1012.  
  1013.         // since the function processes only 4 pixels per iteration, we must
  1014.         // convert sSRLamt and dSRLamt to DWORD alignment values
  1015.         mov edx, dword ptr [sSRLamt ];    // left-shift src alignment
  1016.          mov eax, 0x00;    // eax = x
  1017.  
  1018.         mov esi, dword ptr [s]    ;//esi = source s[] (row y)
  1019.          and edx, 0x1F;    // convert edx -> right-shift src alignment (DWORD)
  1020.         
  1021.         mov ebx, dword ptr [dSRLamt ]; // left-shift dst alignment
  1022.          and esi, 0xFFFFFFFC ; // esi = DWORD aligned source
  1023.  
  1024.         mov ecx, esi;    // ecx = copy of esi
  1025.          and ebx, 0x1F; / convert ebx -> right-shift dst alignment (DWORD)
  1026.  
  1027.         movd mm4, dword ptr [d]    ;//edi = destination d[]
  1028.          movd mm5, edx;    // mm5 = right-shift src alignment (DWORD)
  1029.  
  1030.         add ecx, [lx];    // ecx = source s[] (row y+1)
  1031.          movd mm6, ebx;    // mm6 = right-shift dest alignment (DWORD)
  1032.  
  1033.         mov edx, [lx2];    // edx = stride [lx2]
  1034.          pxor mm0, mm0; // mm0 = 0x0000_0000
  1035.  
  1036.         mov ebx, [h];    // ebx =[heihgt]
  1037.  
  1038.         movq mm7, qword ptr [mmMask0002]; // mm7 = 0x00020002_...
  1039.  
  1040.         jmp lp_afxhy; // skip over initial store
  1041.  
  1042.     lp_afxhya: // for ( y = h; y > 0; --y)
  1043.         movd dword ptr [ edi + eax - 4], mm3; // store dst[4..1]
  1044.  
  1045.     lp_afxhy : // for ( x = 0; x < w; x+= 4)
  1046.         // the read data operation is fairly invovled, to enforce QWORD 
  1047.         // aligned reads
  1048.  
  1049.         movd mm1, dword ptr [esi + eax]; // read src[4..1] (y)
  1050.          movd edi, mm4;    
  1051.  
  1052.         punpckldq mm1, dword ptr [esi + eax + 4]; // mm1 = src[8..1] (y)
  1053.          and edi, 0xFFFFFFFC;    // edi = DWORD aligned dst[4..1]
  1054.  
  1055.         movd mm2, dword ptr [ecx + eax]; // read src[4..1] (y+1)
  1056.          psrlq mm1, mm5;    // mm1 = desired input src[4..1] (y)
  1057.  
  1058.         punpckldq mm2, dword ptr [ecx + eax + 4]; // mm2 = src[8..1] (y+1)
  1059.  
  1060.         movd mm3, dword ptr [ edi + eax ]; // mm3 = dst[4..1]
  1061.          psrlq mm2, mm5;    // mm2 = desired input src[4..1] (y+1)
  1062.  
  1063.         punpckldq mm3, dword ptr [ edi + eax + 4]; // mm3 = dst[8..1]
  1064.  
  1065.         punpcklbw mm1, mm0;    // mm1 = input src[_4 _3 _2 _1] (y) 
  1066.  
  1067.          punpcklbw mm2, mm0;    // mm2 = input src[_4 _3 _2 _1 ] (y+1)
  1068.  
  1069.         psrlq mm3, mm6;    // mm3 = desired input dst[4..1] 
  1070.          paddusw mm1, mm7;    // mm1 = "+2" src[4..1]  (rounding compensation)
  1071.  
  1072.     // we now have all the desired inputs, mm1, mm2, mm3
  1073.  
  1074.          punpcklbw mm3, mm0;    // mm3 = dst[_4 _3 _2 _1] (16-bit values)
  1075.          paddusw mm2, mm1;    // mm2 = (src+src) (row y, y+1)
  1076.  
  1077.          movd edi, mm4;    // restore copy
  1078.          psllw mm3, 0x01; // mm1 = (dst[ _4 _3 _2 _1] << 1 )
  1079.  
  1080.         paddusw mm3, mm2; // mm2 = [ src(y)+src(y+1)+ 2*dst ]
  1081.          add eax, 0x04;    // x += 4
  1082.  
  1083.         cmp eax, [w];    // compare ( x <> w )
  1084.          psrlw mm3, 0x02;    // mm3 = (src+src+2*dst)/4 (desired output)
  1085.  
  1086.         packuswb mm3, mm3;    // mm3 = ready for output
  1087.  
  1088.     // this store has been relocated to beginning of loop to avoid stall
  1089.     //    movd dword ptr [ edi + eax -4], mm3; // store dst[4..1]
  1090.  
  1091.          jl lp_afxhya;  // end for ( x =0 ... )
  1092.  
  1093.     // since we moved store after the branch, we must replicate the store
  1094.     //  for all possible outcomes of branch
  1095.         movd dword ptr [ edi + eax -4], mm3; // store dst[4..1]
  1096.          sub ebx, 0x01;    // --y
  1097.  
  1098.         add esi, edx; // p_lsrc += lx2; row(y)
  1099.          add edi, edx; // p_ldst += lx2;
  1100.  
  1101.         add ecx, edx; // p_lsrc += lx2; row(y+1)
  1102.          mov eax, 0x00;    // x = 0
  1103.  
  1104.         movd mm4, edi;    // move edi => mm4 (backup copy of dest[] pointer )
  1105.          cmp ebx, 0x00; // compare y <> 0
  1106.  
  1107.         jg lp_afxhy    ;    // end for ( y = 0 ... )
  1108.       
  1109.       } // end __asm, end of yes average, fullX, halfY
  1110.  
  1111.     /*
  1112.       for (j=0; j<h; j++) // yes average, fullX, halfY
  1113.       {
  1114.         for (i=0; i<w; i++)
  1115.         {
  1116.           v = (((unsigned int)d[i])<<1) + ((unsigned int)(s[i]+s[i+lx]));
  1117.           //d[i]=(v+(v>=0?1:0))>>1;
  1118.           d[i]=(v+2)>>2;
  1119.         }
  1120.      
  1121.         s+= lx2;
  1122.         d+= lx2;
  1123.       }
  1124.       */
  1125.     }
  1126.     else if (IS_XHALF && !IS_YHALF) /* horizontal but no vertical half-pel */
  1127.     {
  1128.     // this MMX loop generates 8 output-pixels per iteration.
  1129.     // all reads are qword aligned
  1130.       __asm    
  1131.       {    // yes average, halfX, fullY
  1132.         mov edx, dword ptr [p_Aldst ]; // QWORD aligned dest[]
  1133.          mov eax, 0x00;    // eax = x
  1134.  
  1135.         mov esi, dword ptr [p_Alsrc ]; // QWORD aligned src[]
  1136. //         pxor mm2, mm2;    // mm2 = 0x0000_0000
  1137.  
  1138.         mov edi, dword ptr [d]    ;//edi = destination d[]
  1139.  
  1140.         mov ebx, [h];    // ebx = y 
  1141.  
  1142.         movd mm6, dword ptr [sSLLamt ];    // mm6 = left-shift src alignment
  1143.  
  1144.         movd mm7, dword ptr [sSRLamt ];    // mm7 = right-shift src alignment
  1145.          jmp lp_ahxfy;    // skip first store operation
  1146.  
  1147.     lp_ahxfya: // for ( y = h; y > 0; --y )
  1148.         movq qword ptr [ edi + eax-8], mm1;
  1149.     lp_ahxfy : // for ( x = 0; x < w; x+= 8)
  1150.         // the read data operation is fairly involved, to enforce QWORD 
  1151.         // aligned reads
  1152.  
  1153.         movq mm0, qword ptr [ esi + eax ];    // mm0 = p_Alsrc[8..1]
  1154. //         pxor mm2, mm2;    // mm2 = 0x0000_0000
  1155.  
  1156.         movq mm1, qword ptr [ esi + eax + 8];    // mm1 = p_Alsrc[16..9]
  1157.          psrlq mm0, mm7;    // sSRL amount
  1158.  
  1159. //        movq mm3, mm1;    // copy mm1 to mm3
  1160.         movq mm2, mm1;    // copy mm1 to mm2
  1161.          psllq mm1, mm6;    // sSLL amount
  1162.  
  1163.         movq mm4, qword ptr [ edx + eax];    // mm4 = p_Aldst[8..1]
  1164.          psrlq mm2, mm7;    // shift right ( "9th pixel src[xxxxxx9]")
  1165.  
  1166.         movq mm5, qword ptr [ edx + eax + 8];    // mm5 = p_Aldst[16..9]
  1167.          psllw mm2, 8;    // mm2 = "[ x_ x_ | x_ 9_ ]"
  1168. //         punpcklbw mm2, mm3; // mm2 = src[12_ 11_ 10_ 9_], desired input
  1169.  
  1170.         psrlq mm4, qword ptr [ dSRLamt ]; // dSRL amount
  1171.          por mm0, mm1; // mm0 = desired input src[8..1]
  1172.  
  1173.         psllq mm5, qword ptr [ dSLLamt ]; // dSLL amount
  1174.          movq mm1, mm0;    // mm1 = copy of desired input src[8..1]
  1175.  
  1176.         por mm5, mm4; // desired input mm5 = dst[8..1]
  1177.          psrlw mm0, 8;    // mm0 = src[ _8 _6 _4 _2] (even pixels)
  1178.  
  1179.     // we have read all the desired inputs, mm0, mm5, mm2 (and mm1)
  1180.          
  1181.         pand mm1, [mmMask00FF];    // mm1 = src[ _7 _5 _3 _1] (odd pixels)
  1182.          psllq mm2, 40;    // mm2 = src [ _9 _ _ _ ]
  1183.  
  1184.         paddusw mm0, [mmMask0002];    // mm0 = "+2" round-up adjustment
  1185.          movq mm4, mm1;    // mm4 = copy of [src 7 5 3 1] (odd)
  1186.  
  1187.         psrlq mm4, 16;    // mm4 = [ src _ 7 5 3 ]
  1188.          movq mm3, mm5;    // mm3 = copy of dest[8..1]
  1189.         
  1190.         psrlw mm5, 0x08;    // mm5 = dst[ _8 _6 _4 _2] 
  1191.          paddusw mm1, mm0;    // mm1 = src[8..0] even+odd pixels
  1192.  
  1193.         pand mm3, [mmMask00FF];    // mm3 = 2*dest[ _7 _5 _4 _1]
  1194.          psllw mm5, 0x01;    // mm5 = 2*dst[ _8 _6 _4 _2] 
  1195.  
  1196.         por mm2, mm4;    // mm4 = src [ _9 _7 _5 _3]
  1197.          psllw mm3, 0x01;    // mm3 = 2*dst[ _7 _5 _3 _1]
  1198.  
  1199.     // pixel alignment should look like this
  1200.     // from source [98 87 76 65 54 43 32 21]
  1201.     // from dest-> [ 8  7  6  5  4  3  2  1]
  1202.     //              EV ODD EV O  E  O  E  O
  1203.  
  1204.         paddusw mm1, mm3;    // mm1 = (src+src+2*dst) [ odd pixels ]
  1205.          paddusw mm2, mm5; // mm2 = (src+src+2*dst) [ even pixels ]
  1206.  
  1207.         psrlw mm1, 2;    // mm1 = (src+src+2*dst)/4 (__87 __65 __43 __21)
  1208.          paddusw mm2, mm0; // mm2 = (src+src) (__98 __76 __54 __32)
  1209.  
  1210.         psrlw mm2, 2;    // mm2 = (src+src)/4 [ __98 __76 __54 __32 ]
  1211.          add eax, 0x08;
  1212.  
  1213.         cmp eax, [ w ];    // compare x <> w
  1214.           psllw mm2, 8;    // mm2 = (src+src)/4 [ 98__ 76__ 54__ 32__ ]
  1215.  
  1216.         por mm1, mm2;    // mm1 = (src+src)/4 [ 98 87 76 65 54 43 21 ]
  1217.     // this store has been relocated to beginning of loop to avoid stall
  1218.     //    movq qword ptr [ edi + eax-8], mm1;
  1219.          jl lp_ahxfya    ;  // end for ( x =0 ... )
  1220.  
  1221.         add esi, [lx2]; // p_lsrc += lx2;
  1222.          sub ebx, 0x01;    // --y
  1223.  
  1224.     // since we moved store after the branch, we must replicate the store
  1225.     //  for all possible outcomes of branch
  1226.         movq qword ptr [ edi + eax-8], mm1;
  1227.     
  1228.         add edi, [lx2]; // p_ldst += lx2;
  1229.          mov eax, 0x00;    // x = 0
  1230.         
  1231.         add edx, [lx2]; // p_Alsrc += lx2;
  1232.          cmp ebx, 0x00; // compare y <> 0
  1233.  
  1234.         jg lp_ahxfy    ;    // end for ( y = height ... )
  1235.       
  1236.       } // end __asm , end of yes-average, halfX, fullY
  1237.       /*
  1238.       for (j=0; j<h; j++) // yes average, halfX, fullY 
  1239.       {
  1240.         for (i=0; i<w; i++)
  1241.         {
  1242.           //v = d[i] + ((unsigned int)(s[i]+s[i+1]+1)>>1);
  1243.           v = (((unsigned int)d[i])<<1) + ((unsigned int)(s[i]+s[i+1]));
  1244.           //d[i] = (v+(v>=0?1:0))>>1;
  1245.           d[i] = (v+2)>>2;
  1246.         }
  1247.      
  1248.         s+= lx2;
  1249.         d+= lx2;
  1250.       }
  1251.       */
  1252.     }
  1253.     else /* if (xh && yh) horizontal and vertical half-pel */
  1254.     {
  1255.         // this MMX loop generates 4 output-pixels per iteration.
  1256.         // 8 bytes are read from src[] and dst[] each iteration, but
  1257.         // the upper 3 bytes are discarded.
  1258.       __asm    
  1259.       {    // yes average, halfX, halfY
  1260.         mov esi, dword ptr [p_Alsrc]    ;//esi = aligned source p_Alsrc[]
  1261.          mov eax, 0x00;    // eax = x
  1262.  
  1263.         movd mm5, dword ptr [sSLLamt ];    // mm5 = left-shift src alignment
  1264.  
  1265.         movd mm6, dword ptr [sSRLamt ];    // mm6 = right-shift src alignment
  1266.  
  1267.         mov edi, dword ptr [d]    ;//edi = destination d[]
  1268.          mov ebx, 0x00;    // ebx = y 
  1269.  
  1270.         mov edx, dword ptr [p_Aldst]    ;//edx = aligned dest p_Aldst[]
  1271.         mov ecx, [lx];    //vertical stride (for row y+1)
  1272.          pxor mm7, mm7;    // mm7 = 0x0000_0000
  1273.  
  1274. //        movq mm6, qword ptr [mmMask0004]; // mm6 = 0x00040004_...
  1275.          jmp lp_ahxhy;    // skip first store operation
  1276.  
  1277.     lp_ahxhya: // for ( y = 0; y < h; ++y )
  1278.         movd dword ptr [ edi + eax - 4], mm2;
  1279.  
  1280.     lp_ahxhy : // for ( x = 0; x < w; x+= 4)
  1281.         movq mm0, qword ptr [ esi + eax ];    // 0a) mm0 = p_Alsrc[8..1] row(y)
  1282.  
  1283.         movq mm2, qword ptr [ esi + eax + 8];    // 0a) mm2 = p_Alsrc[16..9] row(y)
  1284.          psrlq mm0, mm6;    // shift right mm0
  1285.  
  1286.         movq mm1, qword ptr [ edx + eax ];    // 2a) mm1 = p_Aldst[8..1]
  1287.          add esi, ecx;    // esi = src[] row(y+1)
  1288.  
  1289.         movq mm3, qword ptr [ edx + eax + 8 ];    // 2a) mm3 = p_Aldst[16..9]
  1290.          psllq mm2, mm5;    // shift left mm2
  1291.  
  1292.         psrlq mm1, [ dSRLamt ];
  1293.          por mm0, mm2;  //0a) mm0 = src[8..1] row(y) desired input
  1294.  
  1295.         psllq mm3, [ dSLLamt ];
  1296.          movq mm4, mm0;    // 1b) mm4 = copy of src[8..1] row(y)
  1297.  
  1298.         movq mm2, qword ptr [ esi + eax ];    // 3a) mm2 = src[8..1] row(y+1)
  1299.          por mm1, mm3;    // mm1 = dst[8..1]  desired input
  1300.  
  1301.         movq mm3, qword ptr [ esi + eax +8];    // 3a) mm2 = src[16..9] row(y+1)
  1302.          psrlq mm2, mm6;
  1303.  
  1304.         paddusw mm4, [mmMask0004];
  1305.          psllq mm3, mm5;
  1306.  
  1307.         por mm2, mm3;    // mm2 = src[7..1] row(y+1) desired input
  1308.          punpcklbw mm4, mm7; // 1c) mm4 = src [4..1] row(y)
  1309.  
  1310.         // 1*) mm4 = src [4..1] row(y) "+04" (rounding comp)
  1311.         psrlq mm0, 0x08; // 1d) mm0 = src [ _8765432 ] row(y)
  1312.          movq mm3, mm2;    // 3b) mm3 = copy of src[8..1] row(y+1)
  1313.  
  1314.         punpcklbw mm0, mm7; // 1e) mm0 = src [5..2] row(y)
  1315.          add eax, 0x04;    // x += 4;
  1316.  
  1317.         punpcklbw mm1, mm7;    // 2b) mm1 = dst [4..1] row(y)
  1318.          paddusw mm0, mm4; // 1f) mm0 = (src+src) [54 43 32 21] row(y)
  1319.                         // mm0 = partial result
  1320.  
  1321.         psllw mm1, 0x02; // 2c) mm1 = 4*dst[4..1] 
  1322.          sub esi, ecx;    // conver esi = p_Alsrc[] row(y), used to be row(y+1)
  1323.  
  1324.         paddusw mm0, mm1;    // 2d) mm0 = (4*dst+src(y)), partial result
  1325.          punpcklbw mm3, mm7;    // 3c) mm3 = src[4..1] row(y+1)
  1326.  
  1327.         psrlq mm2, 0x08;    // 3d) mm2 = src[ _8765432 ] row(y+1)
  1328.          paddusw mm0, mm3;    // mm0 = (4*dst+src(y)+(even)src(y+1)) partial result
  1329.  
  1330.         punpcklbw mm2, mm7; // 3e) mm2 = src[5..2] row(y+1)
  1331.          ;//slot
  1332.  
  1333.         paddusw mm2, mm0 // 5) mm2 = (4*dst+src(y)+src(y+1), almost final result
  1334.          ;//slot
  1335.  
  1336.         cmp eax, [w]
  1337.          psrlw mm2, 0x03; // 6) mm2 = [ 4...2 ] / 8 average
  1338.  
  1339.         packuswb mm2, mm2;    // 6) mm0 = final result, ready to store
  1340.  
  1341.     // the store has been moved to AFTER the loop, to avoid stall
  1342.      //    movd dword ptr [ edi + eax ], mm2;
  1343.  
  1344.          jl lp_ahxhya;    // end for ( x = 0; x< w; x+=4 );
  1345.  
  1346.     // 1 copy of the store is here, because of our software pipelining
  1347.         add esi, [lx2];
  1348.          add ebx, 0x01; // ++y;
  1349.  
  1350.          movd dword ptr [ edi + eax - 4], mm2;
  1351.  
  1352.         add edi, [lx2];
  1353.          mov eax, 0x00;    // x = 0;
  1354.  
  1355.         add edx, [lx2];
  1356.  
  1357.         cmp ebx, [h]
  1358.          jl lp_ahxhy;    // end for ( y = 0; y < h; ++y )
  1359.  
  1360.       }    // end __asm ,  end of yes average, halfX, halfy
  1361.  
  1362.         ;
  1363.     /*
  1364.       for (j=0; j<h; j++) // yes average, halfX, halfY
  1365.       {
  1366.         for (i=0; i<w; i++)
  1367.         {
  1368.           //v = d[i] + ((unsigned int)(s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2);
  1369.           v = (((unsigned int)d[i])<<2) + 
  1370.               ((unsigned int)(s[i]+s[i+1]+s[i+lx]+s[i+lx+1]));
  1371.           //d[i] = (v+(v>=0?1:0))>>1;
  1372.           d[i] = (v+4)>>3;
  1373.         }
  1374.      
  1375.         s+= lx2;
  1376.         d+= lx2;
  1377.       }*/
  1378.     
  1379.     } 
  1380.   }
  1381.   else
  1382.   {  /* -------- NO AVERAGE -------- */
  1383.  
  1384.     if (!IS_XHALF && !IS_YHALF) /* no horizontal nor vertical half-pel */
  1385.     {
  1386. //      for (j=0; j<h; j++) /* no average, fullX, fullY */
  1387. //      {
  1388. //        for (i=0; i<(w>>2); ++i)
  1389. //        {
  1390. //          p_ldst[i] = p_lsrc[i];
  1391. //        }
  1392. //
  1393. //        p_lsrc += ( lx2 >> 2 );
  1394. //        p_ldst += ( lx2 >> 2 );
  1395. //      }
  1396.  
  1397.       __asm
  1398.       {    // no average, fullX, fullY
  1399.         // processes 8*2 pixels per iteration (two rows, 8-pixels per row)
  1400.         // all reads (source and dest) are QWORD aligned
  1401.  
  1402.         movd mm6, [sSRLamt]; // mm6 =right-shift amount to QW align source
  1403.          mov ecx, 0x00;    // ecx = x
  1404.  
  1405.         mov edi, dword ptr [d ]        ;//edi <= p_ldst[0]
  1406.  
  1407.         mov ebx, [lx2]    ; // ebx <= lx2
  1408.  
  1409.         mov esi, dword ptr [p_Alsrc ]        ;esi <= p_lsrc[0]
  1410.          mov edx, ebx    ; //edx <= lx2
  1411.         //srl  ebx, 3        ; ebx <= (w >> 3)  (width / 8)
  1412.         mov eax, [h]    ; //eax <= h
  1413.          add edx, edi    ; //edx <= p_ldst[] row(y+1)
  1414.  
  1415.         movd mm7, [sSLLamt]; // mm7 =left-shift amount to QW align source
  1416.          add ebx, esi    ; //ebx <= p_lsrc[] row(y+1)
  1417.  
  1418.         jmp lp_fxfy;    // skip intial store
  1419.  
  1420.     lp_fxfy_st2:
  1421.         movq qword ptr [ edi + ecx -8], mm0    ;dst[ i ] <= mm1
  1422.  
  1423.         movq qword ptr [ edx + ecx -8], mm2    ;dst[ i ] <= mm1
  1424.  
  1425.         // begin inner loop for ( ecx=0; ecx < [w]; ecx += 8 )
  1426.     lp_fxfy : // no average, FullX/FullY
  1427.  
  1428.     movq mm0, qword ptr [ esi + ecx ]    ;mm0 <= p_Alsrc[ i ] (row y)
  1429.  
  1430.         movq mm1, qword ptr [ esi + ecx + 8]    ;mm0 <= p_Alsrc[ i ] (row y)
  1431.          psrlq mm0, mm6;    // right shift [7..0] to align
  1432.  
  1433.         movq mm2, qword ptr [ ebx + ecx ]    ;mm1 <= p_Alsrc[i] (row y+1)
  1434.          psllq mm1, mm7;    // left shift [15..8] to align
  1435.  
  1436.         movq mm3, qword ptr [ ebx + ecx + 8]    ;mm1 <= p_Alsrc[i] (row y+1)
  1437.          psrlq mm2, mm6;    // right shift [7..0] to align
  1438.  
  1439.         por mm0, mm1;        // mm0 = desired src[] 8-pixels (row y)
  1440.          psllq mm3, mm7;        // left shift [15..8] to align
  1441.  
  1442.         por mm2, mm3;        // mm2 = desired src[] 8-pixels (row y+1)
  1443.          add ecx, 0x08;
  1444.  
  1445.     // software pipelining, store-operation has been moved AFTER branch.
  1446.  
  1447.         cmp ecx, [w];  ; // compare i <> width 
  1448.          jb lp_fxfy_st2;       ; // if ( i < width ) loop
  1449.  
  1450.     // increment src/dst by two rows ( 2*lx2)
  1451.         movq qword ptr [ edi + ecx -8], mm0    ;p_ldst[ i ] <= mm1
  1452.  
  1453.         add esi, [lx2_x2]    ;//p_Alsrc += lx2 ( row y)
  1454.  
  1455.         movq qword ptr [ edx + ecx -8], mm2    ;p_ldst[ i ] <= mm1
  1456.  
  1457.         add ebx, [lx2_x2]    ;//p_Alsrc += lx2 ( row y+1)
  1458.          sub eax, 2        ;// j = j -2
  1459.  
  1460.         add edi, [lx2_x2]    ;//p_ldst += lx2 ( row y)
  1461.          mov ecx, 0x00    ;// i = 0;
  1462.  
  1463.         add edx, [lx2_x2]    ;//p_ldst += lx2 ( row y+1)
  1464.          cmp eax, 0        ; compare j <> 0
  1465.  
  1466.         jg lp_fxfy        ; if ( j > 0 ) loop
  1467.       } // end __asm ,  end of no average, fullX, fullY
  1468.     }
  1469.     else if (!IS_XHALF && IS_YHALF) /* no horizontal but vertical half-pel */
  1470.     {
  1471.         // this MMX routine produces 8 pixels per iteration.
  1472.         // all source reads are qword aligned
  1473.     __asm    
  1474.       {    // no average, fullX, halfY 
  1475.         mov esi, dword ptr [p_Alsrc]    ;//esi = aligned source s[] (row y)
  1476.          mov eax, 0x00;    // eax = x
  1477.  
  1478.         movq mm7, qword ptr [mmMask0101]; // mm7 = 0x01010101_...
  1479.          mov ecx, esi;    // ecx = copy of esi
  1480.  
  1481.         movq mm4, qword ptr [mmMaskFEFE]; // mm4 = 0xFEFEFEFE_...
  1482.         mov edi, dword ptr [d]    ;//edi = destination d[]
  1483.          mov ebx, 0x00;    // ebx = y 
  1484.  
  1485.         add ecx, [lx];    // ecx = source s[] (row y+1)
  1486.  
  1487.         mov edx, [lx2];    // edx = stride [lx2]
  1488.  
  1489.         movd mm5, [sSRLamt]; // mm5=source right shift amount to align
  1490.  
  1491.         movd mm6, [sSLLamt]; // mm6=source left shift amount to align
  1492.  
  1493.         jmp lp_fxhy; // skip over initial store
  1494.  
  1495.     lp_fxhya: // for ( y = 0; y < h; ++y)
  1496.         movq qword ptr [ edi + eax - 8], mm3; // store dst[8..1]
  1497.          pxor mm2,mm2;    // mm2 = 0x0000_0000
  1498.     lp_fxhy : // for ( x = 0; x < w; x+= 8)
  1499.         movq mm0, qword ptr [ esi + eax ];    // mm0 = src[8..1] (y)
  1500.  
  1501.         movq mm1, qword ptr [ esi + eax + 8 ];    // mm1 = src[16..9] (y)
  1502.          psrlq mm0, mm5;    // align src[8..1] (y)
  1503.  
  1504.         movq mm2, qword ptr [ ecx + eax ];    // mm2 = src[8..1] (y+1)
  1505.           psllq mm1, mm6;    // align src[16..9] (y)
  1506.  
  1507.         movq mm3, qword ptr [ ecx + eax +8];    // mm3 = src[16..9] (y+1)
  1508.          psrlq mm2, mm5;    // align src[8..1] (y+1)
  1509.  
  1510.          psllq mm3, mm6;    // align src[16..9] (y+1)
  1511.          por mm0, mm1;    // mm0 = desired pixels, src[ 8..1] (y)
  1512.  
  1513.         movq mm1, mm0;    // mm1 = copy of mm0, src[ 8..1] (y)
  1514.          por mm2, mm3;    // mm2 = desired pixels, src[8..1] (y+1)
  1515.  
  1516.         movq mm3, mm2;    // mm3 = copy of mm2, src[ 8..1] (y+1)
  1517.          por mm2, mm0; // mm2 = src(y) OR src(y+1)
  1518.  
  1519.         pand mm1, mm4;    // mm1 = MSB7 of src[8..1] (y)
  1520.          pand mm2, mm7; // mm2 = "+1" src[8..1] (round adjustment)
  1521.  
  1522.         pand mm3, mm4;    // mm3 = MSB7 of src[8..1] (y+1)
  1523.          psrlw mm1, 1;    // mm1 = src[8..1] / 2    (y)
  1524.  
  1525.         psrlw mm3, 1;    // mm3 = src[8..1] / 2    (y+1)
  1526.          paddusb mm2, mm1;    // mm2 = partial result
  1527.  
  1528.         paddusb mm3, mm2; // mm3 = (src+src) src[8..1] final result
  1529.          add eax, 0x08;    // x += 8
  1530.  
  1531.         cmp eax, [w];    // compare x <> w
  1532.  
  1533.     // this store has been relocated to beginning of loop to avoid stall
  1534.     //    movd dword ptr [ edi + eax -8], mm2; // store dst[8..1]
  1535.  
  1536.          jl lp_fxhya;  // end for ( x =0 ... )
  1537.  
  1538.     // since we moved store after the branch, we must replicate the store
  1539.     //  for all possible outcomes of branch
  1540.         movq qword ptr [ edi + eax -8], mm3; // store dst[8..1]
  1541.          add ebx, 0x01;    // ++y
  1542.  
  1543.         add esi, edx; // p_lsrc += lx2; row(y)
  1544.          pxor mm2,mm2;    // mm2 = 0x0000_0000
  1545.         
  1546.         add edi, edx; // p_ldst += lx2;
  1547.          mov eax, 0x00;    // x = 0
  1548.     
  1549.         add ecx, edx; // p_lsrc += lx2; row(y+1)
  1550.  
  1551.         cmp ebx, [ h ]; // compare y <> height
  1552.          jl lp_fxhy    ;    // end for ( y = 0 ... )
  1553.       
  1554.       } // end __asm , end of  no average, fullX, halfY 
  1555.  
  1556.     /*
  1557.       for (j=0; j<h; j++) // no average, fullX, halfY 
  1558.       {
  1559.         for (i=0; i<w; i++)
  1560.         {
  1561.           d[i] = (unsigned int)(s[i]+s[i+lx]+1)>>1;
  1562.         }
  1563.  
  1564.         s+= lx2;
  1565.         d+= lx2;
  1566.       }
  1567.     */
  1568.     }
  1569.     else if (IS_XHALF && !IS_YHALF) /* horizontal but no vertical half-pel */
  1570.     {
  1571.  
  1572.     // this MMX loop generates 8 output-pixels per iteration.
  1573.     // all reads are QWORD aligned
  1574.       __asm    
  1575.       {    /* no average, halfX, fullY */
  1576.         mov esi, dword ptr [p_Alsrc ]    ;//esi = aligned source s[]
  1577.          mov eax, 0x00;    // eax = x
  1578.  
  1579.         movd mm5, [sSRLamt]; // mm5 = src shift-right amount...
  1580.  
  1581.         movd mm6, [sSLLamt]; // mm6 = src shift-left amount...
  1582.  
  1583.         movd mm4, [sSLLamt_minus_8]; // mm4 = (mm6 - 8)
  1584.  
  1585.         mov edi, dword ptr [d]    ;//edi = destination d[]
  1586.  
  1587.         mov ebx, [h];    // ebx = y 
  1588.  
  1589.         movq mm7, qword ptr [mmMask0101]; // mm7 = 0x01010101_...
  1590.          jmp lp_hxfy;    // skip first store operation
  1591.  
  1592.     lp_hxfya: // for ( y = 0; y < h; ++y )
  1593.         movq qword ptr [ edi + eax-8], mm3;
  1594.  
  1595.     lp_hxfy : // for ( x = 0; x < w; x+= 8)
  1596.         movq mm0, qword ptr [ esi + eax ];    // mm0 = p_Alsrc[8..1]
  1597.  
  1598.         movq mm1, qword ptr [ esi + eax + 8];    // mm0 = p_Alsrc[16..9]
  1599.          psrlq mm0, mm5;    // align src[8..1] (y)
  1600.  
  1601.         movq mm3, mm1;        // copy mm3 = p_Alsrc[16..9]
  1602.           psllq mm1, mm6;    // align src[16..] (y)
  1603.  
  1604.         movq mm2, mm0;        // copy mm2 = src[ 8..1] (post shift)
  1605.          psllq mm3, mm4;    // mm3 = src[16..9] 
  1606.  
  1607.         psrlq mm2, 8;        // mm2 = src[ _ 8..2] (top byte 00'd)
  1608.          por mm0, mm1;        // mm0 = desired data src[8..1]
  1609.  
  1610.         por mm2, mm3;    // mm2 = desired data src[9..2]
  1611.          movq mm1, mm0;        // mm1 = copy of mm0, src[8..1]
  1612.          
  1613.         movq mm3, mm2;        // mm3 = copy of mm2, src[9..2]
  1614.          por mm2, mm0;    // mm0 = LSBits of src[ 8..1 ]
  1615.  
  1616.         pand mm1, qword ptr [mmMaskFEFE]; // mm1 = MSB7 of src[8..1]
  1617.          pand mm2, mm7;    // mm2 = "+1" round compensation
  1618.  
  1619.         pand mm3, qword ptr [mmMaskFEFE]; // mm3 = MSB7 of src[9..2]
  1620.          psrlw mm1, 1;    // mm1 = 1/2 src[8..1]
  1621.  
  1622.         paddusb mm2, mm1;  // mm2 = partial result
  1623.          psrlw mm3, 1;    // mm3 = 1/2 src[9..2]
  1624.  
  1625.         paddusb mm3, mm2; // mm3 = final result (src+src) [98 87 76 65 54 43 32 21]
  1626.          add eax, 0x08;
  1627.  
  1628.         cmp eax, [ w ];    // compare x <> w
  1629.          jl lp_hxfya    ;  // end for ( x =0 ... )
  1630.  
  1631.         add esi, [lx2]; // p_lsrc += lx2;
  1632.          sub ebx, 0x01;    // ++y
  1633.  
  1634.     // since we moved store after the branch, we must replicate the store
  1635.     //  for all possible outcomes of branch
  1636.         movq qword ptr [ edi + eax-8], mm3;
  1637.          mov eax, 0x00;    // x = 0
  1638.     
  1639.         add edi, [lx2]; // p_ldst += lx2;
  1640.         
  1641.         cmp ebx, 0; // compare y <> 0
  1642.          jg lp_hxfy    ;    // end for ( y = 0 ... )
  1643.       
  1644.       } // end __asm
  1645.  
  1646.  
  1647.     /*
  1648.       for (j=0; j<h; j++) // no average, halfX, fullY 
  1649.       {
  1650.         for (i=0; i<w; i++)
  1651.         {
  1652.           d[i] = (unsigned int)(s[i]+s[i+1]+1)>>1;
  1653.         }
  1654.  
  1655.         s+= lx2;
  1656.         d+= lx2;
  1657.       }
  1658.       */
  1659.     }
  1660.     else /* if (xh && yh) horizontal and vertical half-pel */
  1661.     {
  1662.         // this MMX loop generates 4 output-pixels per iteration.
  1663.         // 8 bytes are read from src[] and dst[] each iteration, but
  1664.         // the upper bytes are discarded.
  1665.         // the reads are QWORD aligned
  1666.       __asm    
  1667.       {    /* no average, halfX, halfy*/
  1668.         mov esi, dword ptr [p_Alsrc];//esi = aligned source row(y)
  1669.          mov eax, 0x00;    // eax = x
  1670.  
  1671.         mov edi, dword ptr [d]    ;//edi = destination d[]
  1672.          mov ebx, 0x00;    // ebx = y 
  1673.  
  1674.         mov edx, [lx2];    // edx = stride [lx2]
  1675.          mov ecx, esi;    // copy of esi
  1676.         
  1677.         add ecx, [lx];    // ecx = source s[] row(y+1)
  1678.          pxor mm7, mm7;    // mm7 = 0x0000_0000
  1679.  
  1680.         movd mm5, [sSRLamt]; // mm5 = src shift-right amount...
  1681.  
  1682.         movd mm6, [sSLLamt]; // mm6 = src shift-left amount...
  1683.  
  1684. //        movq mm6, qword ptr [mmMask0002]; // mm6 = 0x00020002_..
  1685.          jmp lp_hxhy;    // skip first store operation
  1686.  
  1687.     lp_hxhya: // for ( y = 0; y < h; ++y )
  1688.         movd dword ptr [ edi + eax - 4], mm2;
  1689.  
  1690.     lp_hxhy : // for ( x = 0; x < w; x+= 4)
  1691.         movq mm0, qword ptr [ esi + eax ];    // 1a) mm0 = src[8..1] row(y)
  1692.  
  1693.         movq mm1, qword ptr [ esi + eax +8];    // 1a) mm0 = src[16..9] row(y)
  1694.          psrlq mm0, mm5;    // align src[8..1] row(y)
  1695.  
  1696.         movq mm2, qword ptr [ ecx + eax ];    // 3a) mm2 = src[8..1] row(y+1)
  1697.          psllq mm1, mm6;    // align src[16..9] row(y)
  1698.  
  1699.         movq mm3, qword ptr [ ecx + eax +8];    // 3a) mm2 = src[16..9] row(y+1)
  1700.          psrlq mm2, mm5;    // align src[8..1] row(y+1)
  1701.  
  1702.         por mm0, mm1;    // mm0 = desired pixels src[8..1] row(y)
  1703.          psllq mm3, mm6;    // align src[16..9] row(y+1)
  1704.  
  1705.         por mm2, mm3;    // mm2 = desired pixels src[8..1] row(y+1)
  1706.          movq mm4, mm0;    // 1b) mm4 = copy of src[8..1] row(y)
  1707.  
  1708.         punpcklbw mm4, mm7; // 1c) mm4 = src [4..1] row(y)
  1709.          add eax, 0x04;    // x += 4;
  1710.  
  1711.         paddusw mm4, [mmMask0002];    // 1*) mm4 = src [4..1] row(y) "+02" (rounding comp)
  1712.          psrlq mm0, 0x08; // 1d) mm0 = src [ _8765432 ] row(y)
  1713.  
  1714.         punpcklbw mm0, mm7; // 1e) mm0 = src [5..2] row(y)
  1715.          movq mm3, mm2;    // 3b) mm3 = copy of src[8..1] row(y+1)
  1716.  
  1717.         punpcklbw mm3, mm7;    // 3c) mm3 = src[4..1] row(y+1)
  1718.          paddusw mm0, mm4; // 1f) mm0 = (src+src) [54 43 32 21] row(y)
  1719.                         // mm0 = partial result
  1720.  
  1721.         psrlq mm2, 0x08;    // 3d) mm2 = src[ _8765432 ] row(y+1)
  1722.          paddusw mm3, mm0;    // partial result mm3 = src(y) + (even)src(y+1)
  1723.  
  1724.         punpcklbw mm2, mm7; // 3e) mm2 = src[5..2] row(y+1)
  1725.          ;//slot
  1726.  
  1727.         paddusw mm2, mm3 ;// 5) mm2 = (src(y)+src(y+1), partial result
  1728.          ;//slot
  1729.         
  1730.         psrlw mm2, 0x02; // mm2 = (src+src)/4 average, 16-bit, almost final
  1731.          ;//slot
  1732.  
  1733.         packuswb mm2, mm2;    // 6) mm2 = 8-bit pix final result, ready to store
  1734.          cmp eax, [w]
  1735.  
  1736.     // the store has been moved to AFTER the loop, to avoid stall
  1737.      //    movd dword ptr [ edi + eax ], mm2;
  1738.  
  1739.         jl lp_hxhya;    // end for ( x = 0; x< w; x+=4 );
  1740.  
  1741.     // 1 copy of the store is here, because of our software pipelining
  1742.          movd dword ptr [ edi + eax - 4], mm2;
  1743.          add ebx, 0x01; // ++y;
  1744.  
  1745.         add esi, edx; // src(row y) += lx2
  1746.          mov eax, 0x00;    // x = 0;
  1747.  
  1748.         add ecx, edx; // src(row y+1) += lx2
  1749.          add edi, edx; // dst(row y) += lx2
  1750.  
  1751.         cmp ebx, [h]
  1752.          jl lp_hxhy;    // end for ( y = 0; y < h; ++y )
  1753.  
  1754.       }    // end __asm
  1755.         /*
  1756.       for (j=0; j<h; j++) // no average, halfX, halfY
  1757.       {
  1758.         for (i=0; i<w; i++)
  1759.         {
  1760.           d[i] = (unsigned int)(s[i]+s[i+1]+s[i+lx]+s[i+lx+1]+2)>>2;
  1761.         }
  1762.  
  1763.         s+= lx2;
  1764.         d+= lx2;
  1765.       }
  1766.       */
  1767.     }
  1768.   }
  1769.  
  1770.   __asm emms;
  1771. #endif
  1772. } // form_component_prediction()
  1773.  
  1774.