www.pudn.com > coremp4-1.0.zip > mcomp.cpp


/***************************************************************************** 
 * 
 * This program is free software ; you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation; either version 2 of the License, or 
 * (at your option) any later version. 
 * 
 * This program is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
 * 
 * The Core Pocket Media Player 
 * Copyright (c) 2004-2005 Gabor Kovacs 
 * 
 ****************************************************************************/ 
 
#include "Rules.h" 
 
//---------------------------- 
 
//#define USE_PLD 
 
#if defined _WIN32_WCE || defined __PALMOS__ 
#define USE_IDCT_WMMX 
#endif 
 
//---------------------------- 
#ifdef ARM 
#include "DynamicArmCode.h" 
//---------------------------- 
 
static void PreLoad(C_dyn_code &dc, bool ARM5, int Pos){ 
#ifdef USE_PLD 
   if(ARM5){ 
      if(Pos >= 0){ 
         if(Pos > 0){ 
            dc.Pld(dc.r0, dc.r2, dc.LSL, 1); 
            dc.Add(dc.r0, dc.r0, 8); 
            dc.Pld(dc.r0, dc.r2, dc.LSL, 1); 
            dc.Sub(dc.r0, dc.r0, 8); 
         }else{ 
            dc.Pld(dc.r0, dc.r2, dc.LSL, 1); 
            dc.Add(dc.r0, dc.r0, 4); 
            dc.Pld(dc.r0, dc.r2, dc.LSL, 1); 
            dc.Sub(dc.r0, dc.r0, 4); 
         } 
      }else{ 
         dc.Pld(dc.r0, dc.r2, dc.LSL, 1); 
         dc.Add(dc.r0, dc.r0, 7); 
         dc.Pld(dc.r0, dc.r2, dc.LSL, 1); 
         dc.Sub(dc.r0, dc.r0, 7); 
      } 
   } 
#endif 
} 
 
//---------------------------- 
 
static void PreLoad2Init(C_dyn_code &dc, bool ARM5, int Pos){ 
#ifdef USE_PLD 
   if(ARM5){ 
      if(Pos >= 0){ 
         if(Pos > 0){ 
            dc.Add(dc.r10, dc.r2, dc.r2); 
            dc.Add(dc.r10, dc.r10, 8); 
         }else{ 
            dc.Add(dc.r10, dc.r2, dc.r2); 
            dc.Add(dc.r10, dc.r10, 4); 
         } 
      }else{ 
         dc.Add(dc.r10, dc.r2, dc.r2); 
         dc.Add(dc.r10, dc.r10, 7); 
      } 
   } 
#endif 
} 
 
//---------------------------- 
 
static void PreLoad2(C_dyn_code &dc, bool ARM5, int Pos){ 
#ifdef USE_PLD 
   if(ARM5){ 
      dc.Pld(dc.r0, dc.r2, dc.LSL, 1); 
      dc.Pld(dc.r0, dc.r10); 
   } 
#endif 
} 
 
//---------------------------- 
 
static void AddBlockRow(C_dyn_code &dc, int Pos){ 
 
   if(Pos < 0){ 
      dc.Byte(); dc.Ldr(dc.r4, dc.r0, 0); 
      dc.Byte(); dc.Ldr(dc.r6, dc.r0, 1); 
      dc.Byte(); dc.Ldr(dc.r5, dc.r0, 4); 
      dc.Byte(); dc.Ldr(dc.r7, dc.r0, 5); 
      dc.Orr(dc.r4, dc.r4, dc.r6, dc.LSL, 8); 
      dc.Byte(); dc.Ldr(dc.r6, dc.r0, 2); 
      dc.Orr(dc.r5, dc.r5, dc.r7, dc.LSL, 8); 
      dc.Byte(); dc.Ldr(dc.r7, dc.r0, 6); 
      dc.Orr(dc.r4, dc.r4, dc.r6, dc.LSL, 16); 
      dc.Byte(); dc.Ldr(dc.r6, dc.r0, 3); 
      dc.Orr(dc.r5, dc.r5, dc.r7, dc.LSL, 16); 
      dc.Byte(); dc.Ldr(dc.r7, dc.r0, 7); 
      dc.Orr(dc.r4, dc.r4, dc.r6, dc.LSL, 24); 
      dc.Add(dc.r0, dc.r0, dc.r2); 
      dc.Orr(dc.r5, dc.r5, dc.r7, dc.LSL, 24); 
   }else{ 
      if(Pos > 0){ 
        dc.Ldr(dc.r5, dc.r0, 8); 
        dc.Ldr(dc.r6, dc.r0, 4); 
        dc.LdrAdvance(dc.r4, dc.r0, dc.r2); 
       
        dc.Mov(dc.r5, dc.r5, dc.LSL, 32-Pos); 
        dc.Orr(dc.r5, dc.r5, dc.r6, dc.LSR, Pos); 
        dc.Mov(dc.r4, dc.r4, dc.LSR, Pos); 
        dc.Orr(dc.r4, dc.r4, dc.r6, dc.LSL, 32-Pos); 
      }else{ 
        dc.Ldr(dc.r5, dc.r0, 4); 
        dc.LdrAdvance(dc.r4, dc.r0, dc.r2); 
      } 
   } 
   dc.Ldr(dc.r7, dc.r1, 4); 
   dc.Ldr(dc.r6, dc.r1, 0); 
   dc.And(dc.r9, dc.r12, dc.r5, dc.LSR, 1); 
   dc.And(dc.r8, dc.r12, dc.r4, dc.LSR, 1); 
   dc.Orr(dc.r5, dc.r7, dc.r5); 
   dc.Orr(dc.r4, dc.r6, dc.r4); 
   dc.And(dc.r7, dc.r12, dc.r7, dc.LSR, 1); 
   dc.And(dc.r6, dc.r12, dc.r6, dc.LSR, 1); 
   dc.Add(dc.r7, dc.r7, dc.r9); 
   dc.Add(dc.r6, dc.r6, dc.r8); 
   dc.And(dc.r5, dc.r5, dc.r14); 
   dc.And(dc.r4, dc.r4, dc.r14); 
   dc.Add(dc.r7, dc.r7, dc.r5); 
   dc.Add(dc.r6, dc.r6, dc.r4); 
   dc.Str(dc.r7, dc.r1, 4); 
   dc.StrAdvance(dc.r6, dc.r1, 8); 
} 
 
//---------------------------- 
 
static void LoadHorRow(C_dyn_code &dc, int Pos){ 
    //result is r4, dc.r5 dc.And(dc.r8, dc.r9 (one pixel to the right) 
    //r6, dc.r7 can be used 
   if(Pos < 0){ 
      dc.Byte(); dc.Ldr(dc.r4, dc.r0, 0); 
      dc.Byte(); dc.Ldr(dc.r6, dc.r0, 1); 
      dc.Byte(); dc.Ldr(dc.r5, dc.r0, 4); 
      dc.Byte(); dc.Ldr(dc.r7, dc.r0, 5); 
      dc.Orr(dc.r4, dc.r4, dc.r6, dc.LSL, 8); 
      dc.Byte(); dc.Ldr(dc.r6, dc.r0, 2); 
      dc.Orr(dc.r5, dc.r5, dc.r7, dc.LSL, 8); 
      dc.Byte(); dc.Ldr(dc.r7, dc.r0, 6); 
      dc.Orr(dc.r4, dc.r4, dc.r6, dc.LSL, 16); 
      dc.Byte(); dc.Ldr(dc.r6, dc.r0, 3); 
      dc.Orr(dc.r5, dc.r5, dc.r7, dc.LSL, 16); 
      dc.Byte(); dc.Ldr(dc.r7, dc.r0, 7); 
      dc.Orr(dc.r4, dc.r4, dc.r6, dc.LSL, 24); 
      dc.Byte(); dc.Ldr(dc.r6, dc.r0, 8); 
      dc.Orr(dc.r5, dc.r5, dc.r7, dc.LSL, 24); 
 
      dc.Mov(dc.r8, dc.r4, dc.LSR, 8); 
      dc.Mov(dc.r9, dc.r5, dc.LSR, 8); 
      dc.Orr(dc.r8, dc.r8, dc.r5, dc.LSL, 24); 
      dc.Orr(dc.r9, dc.r9, dc.r6, dc.LSL, 24); 
 
      dc.Add(dc.r0, dc.r0, dc.r2); 
   }else{ 
      dc.Ldr(dc.r5, dc.r0, 4); 
      dc.Ldr(dc.r6, dc.r0, 8); 
      dc.LdrAdvance(dc.r4, dc.r0, dc.r2); 
 
      if(Pos+8 < 32){ 
         dc.Mov(dc.r9, dc.r5, dc.LSR, Pos+8); 
         dc.Orr(dc.r9, dc.r9, dc.r6, dc.LSL, 32-Pos-8); 
         dc.Mov(dc.r8, dc.r4, dc.LSR, Pos+8); 
         dc.Orr(dc.r8, dc.r8, dc.r5, dc.LSL, 32-Pos-8); 
      }else{ 
         dc.Mov(dc.r8, dc.r5); 
         dc.Mov(dc.r9, dc.r6); 
      } 
      if(Pos > 0){ 
         dc.Mov(dc.r4, dc.r4, dc.LSR, Pos); 
         dc.Mov(dc.r6, dc.r6, dc.LSL, 32-Pos); 
         dc.Orr(dc.r4, dc.r4, dc.r5, dc.LSL, 32-Pos); 
         dc.Orr(dc.r5, dc.r6, dc.r5, dc.LSR, Pos); 
      } 
   } 
} 
 
//---------------------------- 
 
static void CopyHorRow(C_dyn_code &dc, int Pos, bool round, bool add){ 
 
                              //r14 01010101 
                              //r12 7f7f7f7f 
   LoadHorRow(dc, Pos); 
   dc.And(dc.r6, dc.r12, dc.r4, dc.LSR, 1); 
   dc.And(dc.r7, dc.r12, dc.r5, dc.LSR, 1); 
 
   if(round){ 
     dc.And(dc.r4, dc.r4, dc.r8); 
     dc.And(dc.r5, dc.r5, dc.r9); 
   }else{ 
     dc.Orr(dc.r4, dc.r4, dc.r8); 
     dc.Orr(dc.r5, dc.r5, dc.r9); 
   } 
   dc.And(dc.r8, dc.r12, dc.r8, dc.LSR, 1); 
   dc.And(dc.r9, dc.r12, dc.r9, dc.LSR, 1); 
 
   dc.And(dc.r4, dc.r4, dc.r14); 
   dc.And(dc.r5, dc.r5, dc.r14); 
 
   dc.Add(dc.r4, dc.r4, dc.r6); 
   dc.Add(dc.r5, dc.r5, dc.r7); 
   dc.Add(dc.r4, dc.r4, dc.r8); 
   dc.Add(dc.r5, dc.r5, dc.r9); 
    
   if(add){ 
     dc.Ldr(dc.r7, dc.r1, 4); 
     dc.Ldr(dc.r6, dc.r1, 0); 
     dc.And(dc.r9, dc.r12, dc.r5, dc.LSR, 1); 
     dc.And(dc.r8, dc.r12, dc.r4, dc.LSR, 1); 
     dc.Orr(dc.r5, dc.r7, dc.r5); 
     dc.Orr(dc.r4, dc.r6, dc.r4); 
     dc.And(dc.r7, dc.r12, dc.r7, dc.LSR, 1); 
     dc.And(dc.r6, dc.r12, dc.r6, dc.LSR, 1); 
     dc.Add(dc.r7, dc.r7, dc.r9); 
     dc.Add(dc.r6, dc.r6, dc.r8); 
     dc.And(dc.r5, dc.r5, dc.r14); 
     dc.And(dc.r4, dc.r4, dc.r14); 
     dc.Add(dc.r7, dc.r7, dc.r5); 
     dc.Add(dc.r6, dc.r6, dc.r4); 
     dc.Str(dc.r7, dc.r1, 4); 
     dc.StrAdvance(dc.r6, dc.r1, 8); 
   }else{ 
     dc.Str(dc.r5, dc.r1, 4); 
     dc.StrAdvance(dc.r4, dc.r1, dc.r3); 
   } 
} 
 
//---------------------------- 
 
static void LoadVerRow(C_dyn_code &dc, int Pos, bool parity){ 
    
   if(parity){ 
                              //result is r8, dc.r9 (r10=r8>>1, dc.r11=r9>>1)  
                              //r10, dc.r11 can be used 
      if(Pos < 0){ 
         dc.Byte(); dc.Ldr(dc.r8, dc.r0, 0); 
         dc.Byte(); dc.Ldr(dc.r10, dc.r0, 1); 
         dc.Byte(); dc.Ldr(dc.r9, dc.r0, 4); 
         dc.Byte(); dc.Ldr(dc.r11, dc.r0, 5); 
         dc.Orr(dc.r8, dc.r8, dc.r10,dc.LSL, 8); 
         dc.Byte(); dc.Ldr(dc.r10, dc.r0, 2); 
         dc.Orr(dc.r9, dc.r9, dc.r11, dc.LSL, 8); 
         dc.Byte(); dc.Ldr(dc.r11, dc.r0, 6); 
         dc.Orr(dc.r8, dc.r8, dc.r10, dc.LSL, 16); 
         dc.Byte(); dc.Ldr(dc.r10, dc.r0, 3); 
         dc.Orr(dc.r9, dc.r9, dc.r11, dc.LSL, 16); 
         dc.Byte(); dc.Ldr(dc.r11, dc.r0, 7); 
         dc.Orr(dc.r8, dc.r8, dc.r10, dc.LSL, 24); 
         dc.Add(dc.r0, dc.r0, dc.r2); 
         dc.Orr(dc.r9, dc.r9, dc.r11, dc.LSL, 24); 
      }else{ 
         if(Pos > 0){ 
            dc.Ldr(dc.r9, dc.r0, 8); 
            dc.Ldr(dc.r10, dc.r0, 4); 
            dc.LdrAdvance(dc.r8, dc.r0, dc.r2); 
                
            dc.Mov(dc.r9, dc.r9, dc.LSL, 32-Pos); 
            dc.Orr(dc.r9, dc.r9, dc.r10, dc.LSR, Pos); 
            dc.Mov(dc.r8, dc.r8, dc.LSR, Pos); 
            dc.Orr(dc.r8, dc.r8, dc.r10, dc.LSL, 32-Pos); 
         }else{ 
            dc.Ldr(dc.r9, dc.r0, 4); 
            dc.LdrAdvance(dc.r8, dc.r0, dc.r2); 
         } 
      } 
      dc.And(dc.r11, dc.r12, dc.r9, dc.LSR, 1); 
      dc.And(dc.r10, dc.r12, dc.r8, dc.LSR, 1); 
   }else{ 
                              //result is r4, dc.r5 (r6=r4>>1, dc.r7=r5>>1)  
                              //r6, dc.r7 can be used 
      if(Pos < 0){ 
         dc.Byte(); dc.Ldr(dc.r4, dc.r0, 0); 
         dc.Byte(); dc.Ldr(dc.r6, dc.r0, 1); 
         dc.Byte(); dc.Ldr(dc.r5, dc.r0, 4); 
         dc.Byte(); dc.Ldr(dc.r7, dc.r0, 5); 
         dc.Orr(dc.r4, dc.r4, dc.r6, dc.LSL, 8); 
         dc.Byte(); dc.Ldr(dc.r6, dc.r0, 2); 
         dc.Orr(dc.r5, dc.r5, dc.r7, dc.LSL, 8); 
         dc.Byte(); dc.Ldr(dc.r7, dc.r0, 6); 
         dc.Orr(dc.r4, dc.r4, dc.r6, dc.LSL, 16); 
         dc.Byte(); dc.Ldr(dc.r6, dc.r0, 3); 
         dc.Orr(dc.r5, dc.r5, dc.r7, dc.LSL, 16); 
         dc.Byte(); dc.Ldr(dc.r7, dc.r0, 7); 
         dc.Orr(dc.r4, dc.r4, dc.r6, dc.LSL, 24); 
         dc.Add(dc.r0, dc.r0, dc.r2); 
         dc.Orr(dc.r5, dc.r5, dc.r7, dc.LSL, 24); 
      }else{ 
         if(Pos > 0){ 
            dc.Ldr(dc.r5, dc.r0, 8); 
            dc.Ldr(dc.r6, dc.r0, 4); 
            dc.LdrAdvance(dc.r4, dc.r0, dc.r2); 
 
            dc.Mov(dc.r5, dc.r5, dc.LSL, 32-Pos); 
            dc.Orr(dc.r5, dc.r5, dc.r6, dc.LSR, Pos); 
            dc.Mov(dc.r4, dc.r4, dc.LSR, Pos); 
            dc.Orr(dc.r4, dc.r4, dc.r6, dc.LSL, 32-Pos); 
         }else{ 
            dc.Ldr(dc.r5, dc.r0, 4); 
            dc.LdrAdvance(dc.r4, dc.r0, dc.r2); 
         } 
      } 
      dc.And(dc.r7, dc.r12, dc.r5, dc.LSR, 1); 
      dc.And(dc.r6, dc.r12, dc.r4, dc.LSR, 1); 
   } 
} 
 
//---------------------------- 
 
static void CopyVerRow(C_dyn_code &dc, int Pos, bool parity, bool round, bool add){ 
 
                              //r14 01010101 
                              //r12 7f7f7f7f 
   LoadVerRow(dc, Pos, parity); 
   if(parity){ 
      if(round){ 
         dc.And(dc.r4, dc.r4, dc.r8); 
         dc.And(dc.r5, dc.r5, dc.r9); 
      }else{ 
         dc.Orr(dc.r4, dc.r4, dc.r8); 
         dc.Orr(dc.r5, dc.r5, dc.r9); 
      } 
      dc.And(dc.r4, dc.r4, dc.r14); 
      dc.And(dc.r5, dc.r5, dc.r14); 
 
      dc.Add(dc.r4, dc.r4, dc.r6); 
      dc.Add(dc.r5, dc.r5, dc.r7); 
 
      dc.Add(dc.r4, dc.r4, dc.r10); 
      dc.Add(dc.r5, dc.r5, dc.r11); 
 
      if(add){ 
         dc.Ldr(dc.r7, dc.r1, 4); 
         dc.Ldr(dc.r6, dc.r1, 0); 
         dc.And(dc.r3, dc.r12, dc.r5, dc.LSR,  1); 
         dc.Orr(dc.r5, dc.r7, dc.r5); 
         dc.And(dc.r7, dc.r12, dc.r7, dc.LSR,  1); 
         dc.Add(dc.r7, dc.r7, dc.r3); 
         dc.And(dc.r3, dc.r12, dc.r4, dc.LSR,  1); 
         dc.Orr(dc.r4, dc.r6, dc.r4); 
         dc.And(dc.r6, dc.r12, dc.r6, dc.LSR,  1); 
         dc.Add(dc.r6, dc.r6, dc.r3); 
         dc.And(dc.r5, dc.r5, dc.r14); 
         dc.And(dc.r4, dc.r4, dc.r14); 
         dc.Add(dc.r5, dc.r5, dc.r7); 
         dc.Add(dc.r4, dc.r4, dc.r6); 
         dc.Ldr(dc.r7, dc.sp, 0);     //end src for loop compare 
         dc.Str(dc.r5, dc.r1, 4); 
         dc.StrAdvance(dc.r4, dc.r1, 8); 
      }else{ 
         dc.Ldr(dc. r7, dc.sp, 0);     //end src for loop compare 
         dc.Str(dc.r5, dc.r1, 4); 
         dc.StrAdvance(dc.r4, dc.r1, dc.r3); 
      } 
   }else{ 
      if(round){ 
         dc.And(dc.r8, dc.r8, dc.r4); 
         dc.And(dc.r9, dc.r9, dc.r5); 
      }else{ 
         dc.Orr(dc.r8, dc.r8, dc.r4); 
         dc.Orr(dc.r9, dc.r9, dc.r5); 
      } 
      dc.And(dc.r8, dc.r8, dc.r14); 
      dc.And(dc.r9, dc.r9, dc.r14); 
       
      dc.Add(dc.r8, dc.r8, dc.r10); 
      dc.Add(dc.r9, dc.r9, dc.r11); 
      dc.Add(dc.r8, dc.r8, dc.r6); 
      dc.Add(dc.r9, dc.r9, dc.r7); 
       
      if(add){ 
         dc.Ldr(dc.r11, dc.r1, 4); 
         dc.Ldr(dc.r10, dc.r1, 0); 
         dc.And(dc.r3, dc.r12, dc.r9, dc.LSR,  1); 
         dc.Orr(dc.r9, dc.r11, dc.r9); 
         dc.And(dc.r11, dc.r12, dc.r11, dc.LSR,  1); 
         dc.Add(dc.r11, dc.r11, dc.r3); 
         dc.And(dc.r3, dc.r12, dc.r8, dc.LSR,  1); 
         dc.Orr(dc.r8, dc.r10, dc.r8); 
         dc.And(dc.r10, dc.r12, dc.r10, dc.LSR,  1); 
         dc.Add(dc.r10, dc.r10, dc.r3); 
         dc.And(dc.r9, dc.r9, dc.r14); 
         dc.And(dc.r8, dc.r8, dc.r14); 
         dc.Add(dc.r11, dc.r11, dc.r9); 
         dc.Add(dc.r10, dc.r10, dc.r8); 
         dc.Str(dc.r11, dc.r1, 4); 
         dc.StrAdvance(dc.r10, dc.r1, 8); 
      }else{ 
         dc.Str(dc.r9, dc.r1, 4); 
         dc.StrAdvance(dc.r8, dc.r1, dc.r3); 
      } 
   } 
} 
 
//---------------------------- 
// load needs r2, dc.r3 for temporary (r2 is restored from stack) 
 
static void LoadHorVerRow(C_dyn_code &dc, int Pos, bool parity){ 
   if(parity){ 
                              //read result r4, dc.r5 dc.And(dc.r2, dc.r3 (one pixel to right) 
                              //r6, dc.r7 can be used 
      if(Pos<0){ 
         dc.Byte(); dc.Ldr(dc.r4, dc.r0, 0); 
         dc.Byte(); dc.Ldr(dc.r6, dc.r0, 1); 
         dc.Byte(); dc.Ldr(dc.r5, dc.r0, 4); 
         dc.Byte(); dc.Ldr(dc.r7, dc.r0, 5); 
         dc.Orr(dc.r4, dc.r4, dc.r6, dc.LSL, 8); 
         dc.Byte(); dc.Ldr(dc.r6, dc.r0, 2); 
         dc.Orr(dc.r5, dc.r5, dc.r7, dc.LSL, 8); 
         dc.Byte(); dc.Ldr(dc.r7, dc.r0, 6); 
         dc.Orr(dc.r4, dc.r4, dc.r6, dc.LSL, 16); 
         dc.Byte(); dc.Ldr(dc.r6, dc.r0, 3); 
         dc.Orr(dc.r5, dc.r5, dc.r7, dc.LSL, 16); 
         dc.Byte(); dc.Ldr(dc.r7, dc.r0, 7); 
         dc.Orr(dc.r4, dc.r4, dc.r6, dc.LSL, 24); 
         dc.Byte(); dc.Ldr(dc.r6, dc.r0, 8); 
         dc.Orr(dc.r5, dc.r5, dc.r7, dc.LSL, 24); 
         dc.Add(dc.r0, dc.r0, dc.r2); 
          
         dc.Mov(dc.r2, dc.r4, dc.LSR, 8); 
         dc.Mov(dc.r3, dc.r5, dc.LSR, 8); 
         dc.Orr(dc.r2, dc.r2, dc.r5, dc.LSL, 24); 
         dc.Orr(dc.r3, dc.r3, dc.r6, dc.LSL, 24); 
      }else{ 
         dc.Ldr(dc.r5, dc.r0, 4); 
         dc.Ldr(dc.r6, dc.r0, 8); 
         dc.LdrAdvance(dc.r4, dc.r0, dc.r2); 
          
         if(Pos+8 < 32){ 
            dc.Mov(dc.r3, dc.r5, dc.LSR, Pos+8); 
            dc.Orr(dc.r3, dc.r3, dc.r6, dc.LSL, 32-Pos-8); 
            dc.Mov(dc.r2, dc.r4, dc.LSR, Pos+8); 
            dc.Orr(dc.r2, dc.r2, dc.r5, dc.LSL, 32-Pos-8); 
         }else{ 
            dc.Mov(dc.r2, dc.r5); 
            dc.Mov(dc.r3, dc.r6); 
         } 
          
         if(Pos > 0){ 
            dc.Mov(dc.r4, dc.r4, dc.LSR, Pos); 
            dc.Mov(dc.r6, dc.r6, dc.LSL, 32-Pos); 
            dc.Orr(dc.r4, dc.r4, dc.r5, dc.LSL, 32-Pos); 
            dc.Orr(dc.r5, dc.r6, dc.r5, dc.LSR, Pos); 
         } 
      } 
      dc.And(dc.r6, dc.r2, dc.r14); 
      dc.And(dc.r2, dc.r12, dc.r2, dc.LSR, 2); 
      dc.And(dc.r7, dc.r4, dc.r14); 
      dc.And(dc.r4, dc.r12, dc.r4, dc.LSR, 2); 
      dc.Add(dc.r4, dc.r4, dc.r2); 
      dc.Add(dc.r6, dc.r6, dc.r7); 
       
      dc.And(dc.r2, dc.r3, dc.r14); 
      dc.And(dc.r3, dc.r12, dc.r3, dc.LSR, 2); 
      dc.And(dc.r7, dc.r5, dc.r14); 
      dc.And(dc.r5, dc.r12, dc.r5, dc.LSR, 2); 
      dc.Add(dc.r5, dc.r5, dc.r3); 
      dc.Add(dc.r7, dc.r2, dc.r7); 
   }else{ 
                              //read result r8, dc.r9 dc.And(dc.r2, dc.r3 (one pixel to right) 
                              //r10, dc.r11 can be used 
      if(Pos<0){ 
          
         dc.Byte(); dc.Ldr(dc.r8, dc.r0, 0); 
         dc.Byte(); dc.Ldr(dc.r10, dc.r0, 1); 
         dc.Byte(); dc.Ldr(dc.r9, dc.r0, 4); 
         dc.Byte(); dc.Ldr(dc.r11, dc.r0, 5); 
         dc.Orr(dc.r8, dc.r8, dc.r10, dc.LSL, 8); 
         dc.Byte(); dc.Ldr(dc.r10, dc.r0, 2); 
         dc.Orr(dc.r9, dc.r9, dc.r11, dc.LSL, 8); 
         dc.Byte(); dc.Ldr(dc.r11, dc.r0, 6); 
         dc.Orr(dc.r8, dc.r8, dc.r10, dc.LSL, 16); 
         dc.Byte(); dc.Ldr(dc.r10, dc.r0, 3); 
         dc.Orr(dc.r9, dc.r9, dc.r11, dc.LSL, 16); 
         dc.Byte(); dc.Ldr(dc.r11, dc.r0, 7); 
         dc.Orr(dc.r8, dc.r8, dc.r10, dc.LSL, 24); 
         dc.Byte(); dc.Ldr(dc.r10, dc.r0, 8); 
         dc.Orr(dc.r9, dc.r9, dc.r11, dc.LSL, 24); 
         dc.Add(dc.r0, dc.r0, dc.r2); 
          
         dc.Mov(dc.r2, dc.r8, dc.LSR, 8); 
         dc.Mov(dc.r3, dc.r9, dc.LSR, 8); 
         dc.Orr(dc.r2, dc.r2, dc.r9, dc.LSL, 24); 
         dc.Orr(dc.r3, dc.r3, dc.r10, dc.LSL, 24); 
          
      }else{ 
         dc.Ldr(dc.r9, dc.r0, 4); 
         dc.Ldr(dc.r10, dc.r0, 8); 
         dc.LdrAdvance(dc.r8, dc.r0, dc.r2); 
          
         if(Pos+8 < 32){ 
            dc.Mov(dc.r3, dc.r9, dc.LSR, Pos+8); 
            dc.Orr(dc.r3, dc.r3, dc.r10, dc.LSL, 32-Pos-8); 
            dc.Mov(dc.r2, dc.r8, dc.LSR, Pos+8); 
            dc.Orr(dc.r2, dc.r2, dc.r9, dc.LSL, 32-Pos-8); 
         }else{ 
            dc.Mov(dc.r2, dc.r9); 
            dc.Mov(dc.r3, dc.r10); 
         } 
          
         if(Pos > 0){ 
            dc.Mov(dc.r8, dc.r8, dc.LSR, Pos); 
            dc.Mov(dc.r10, dc.r10, dc.LSL, 32-Pos); 
            dc.Orr(dc.r8, dc.r8, dc.r9, dc.LSL, 32-Pos); 
            dc.Orr(dc.r9, dc.r10, dc.r9, dc.LSR, Pos); 
         } 
      } 
       
      dc.And(dc.r10, dc.r2, dc.r14); 
      dc.And(dc.r2, dc.r12, dc.r2, dc.LSR, 2); 
      dc.And(dc.r11, dc.r8, dc.r14); 
      dc.And(dc.r8, dc.r12, dc.r8, dc.LSR, 2); 
      dc.Add(dc.r8, dc.r8, dc.r2); 
      dc.Add(dc.r10, dc.r10, dc.r11); 
       
      dc.And(dc.r2, dc.r3, dc.r14); 
      dc.And(dc.r3, dc.r12, dc.r3, dc.LSR, 2); 
      dc.And(dc.r11, dc.r9, dc.r14); 
      dc.And(dc.r9, dc.r12, dc.r9, dc.LSR, 2); 
      dc.Add(dc.r9, dc.r9, dc.r3); 
      dc.Add(dc.r11, dc.r2, dc.r11); 
   } 
   dc.Ldr(dc.r2, dc.sp, 0); 
} 
 
//---------------------------- 
   
static void CopyHorVerRow(C_dyn_code &dc, int Pos, bool parity, bool round, bool add){ 
 
                              //r14 03030303 
                              //r12 3f3f3f3f 
   LoadHorVerRow(dc, Pos, parity); 
 
   if(round){ 
      dc.And(dc.r3, dc.r14, dc.r14, dc.LSR, 1);    //0x01010101 
   }else{ 
      dc.And(dc.r3, dc.r14, dc.r14, dc.LSL, 1);    //0x02020202 
   } 
   if(parity){ 
      dc.Add(dc.r8, dc.r8, dc.r4); 
      dc.Add(dc.r9, dc.r9, dc.r5); 
      dc.Add(dc.r10, dc.r10, dc.r6); 
      dc.Add(dc.r11, dc.r11, dc.r7); 
       
      dc.Add(dc.r10, dc.r10, dc.r3); 
      dc.Add(dc.r11, dc.r11, dc.r3); 
      dc.And(dc.r10, dc.r14, dc.r10, dc.LSR, 2); 
      dc.And(dc.r11, dc.r14, dc.r11, dc.LSR, 2); 
       
      if(add){ 
         dc.Add(dc. r8, dc.r8, dc.r10); 
         dc.Add(dc. r9, dc.r9, dc.r11); 
         dc.Orr(dc.  r12, dc.r12, dc.r12, dc.LSL, 1);  //0x7F7F7F7F 
         dc.Ldr(dc.r11, dc.r1, 4); 
         dc.Ldr(dc.r10, dc.r1, 0); 
         dc.And(dc. r3, dc.r12, dc.r9, dc.LSR, 1); 
         dc.Orr(dc.r9, dc.r11, dc.r9); 
         dc.And(dc. r11, dc.r12, dc.r11, dc.LSR, 1); 
         dc.Add(dc.r11, dc.r11, dc.r3); 
         dc.And(dc. r3, dc.r12, dc.r8, dc.LSR, 1); 
         dc.Orr(dc.r8, dc.r10, dc.r8); 
         dc.And(dc. r10, dc.r12, dc.r10, dc.LSR, 1); 
         dc.Add(dc.r10, dc.r10, dc.r3); 
         dc.And(dc.r3, dc.r14, dc.r14, dc.LSR, 1); //0x01010101 
         dc.Mvn(dc.r12, dc.r14, dc.LSL, 6);    //restore r12 
         dc.And(dc.r9, dc.r9, dc.r3); 
         dc.And(dc.r8, dc.r8, dc.r3); 
         dc.Add(dc.r11, dc.r11, dc.r9); 
         dc.Add(dc.r10, dc.r10, dc.r8); 
         dc.Ldr(dc.r3, dc.sp, 4);  //end src for loop compare 
         dc.Str(dc.r11, dc.r1, 4); 
         dc.StrAdvance(dc.r10, dc.r1, 8); 
      }else{ 
         dc.Add(dc. r8, dc.r8, dc.r10); 
         dc.Ldr(dc.r10, dc.sp, 8);  //dstpitch 
         dc.Add(dc. r9, dc.r9, dc.r11); 
         dc.Ldr(dc.r3, dc.sp, 4);  //end src for loop compare 
         dc.Str(dc.r9, dc.r1, 4); 
         dc.StrAdvance(dc.r8, dc.r1, dc.r10); 
      } 
   }else{ 
      dc.Add(dc.r4, dc.r4, dc.r8); 
      dc.Add(dc.r5, dc.r5, dc.r9); 
      dc.Add(dc.r6, dc.r6, dc.r10); 
      dc.Add(dc.r7, dc.r7, dc.r11); 
       
      dc.Add(dc.r6, dc.r6, dc.r3); 
      dc.Add(dc.r7, dc.r7, dc.r3); 
      dc.And(dc.r6, dc.r14, dc.r6, dc.LSR, 2); 
      dc.And(dc.r7, dc.r14, dc.r7, dc.LSR, 2); 
       
      if(add){ 
         dc.Add(dc. r4, dc.r4, dc.r6); 
         dc.Add(dc. r5, dc.r5, dc.r7); 
         dc.Orr(dc.  r12, dc.r12, dc.r12, dc.LSL, 1);  //0x7F7F7F7F 
         dc.Ldr(dc.r7, dc.r1, 4); 
         dc.Ldr(dc.r6, dc.r1, 0); 
         dc.And(dc. r3, dc.r12, dc.r5, dc.LSR, 1); 
         dc.Orr(dc.r5, dc.r7, dc.r5); 
         dc.And(dc. r7, dc.r12, dc.r7, dc.LSR, 1); 
         dc.Add(dc.r7, dc.r7, dc.r3); 
         dc.And(dc. r3, dc.r12, dc.r4, dc.LSR, 1); 
         dc.Orr(dc.r4, dc.r6, dc.r4); 
         dc.And(dc. r6, dc.r12, dc.r6, dc.LSR, 1); 
         dc.Add(dc.r6, dc.r6, dc.r3); 
         dc.And(dc.r3, dc.r14, dc.r14, dc.LSR, 1); //0x01010101 
         dc.Mvn(dc.r12, dc.r14, dc.LSL, 6);    //restore r12 
         dc.And(dc.r5, dc.r5, dc.r3); 
         dc.And(dc.r4, dc.r4, dc.r3); 
         dc.Add(dc.r7, dc.r7, dc.r5); 
         dc.Add(dc.r6, dc.r6, dc.r4); 
         dc.Str(dc.r7, dc.r1, 4); 
         dc.StrAdvance(dc.r6, dc.r1, 8); 
      }else{ 
         dc.Ldr(dc.r3, dc.sp, 8);  //dstpitch 
         dc.Add(dc. r4, dc.r4, dc.r6); 
         dc.Add(dc. r5, dc.r5, dc.r7); 
         dc.Str(dc.r5, dc.r1, 4); 
         dc.StrAdvance(dc.r4, dc.r1, dc.r3); 
      } 
   } 
} 
 
//---------------------------- 
 
typedef void (*t_BuldFunc)(C_dyn_code &dc, int Pos, bool round, bool add, bool ARM5); 
 
static void BuildAddBlock(C_dyn_code &dc, int Pos, bool round, bool add, bool ARM5){ 
 
   void *data = dc.DeclareData(0x01010101); 
 
   PreLoad2Init(dc, ARM5, -1); 
   dc.Ldr(dc.r14, data); 
   dc.Mov(dc.r11, 8); 
   dc.Mvn(dc.r12, dc.r14, dc.LSL, 7); 
   { 
      void *loop = dc.Label(); 
      PreLoad2(dc, ARM5, Pos); 
      AddBlockRow(dc, Pos); 
      dc.Set(); dc.Sub(dc.r11, dc.r11, 1); 
      dc.Branch(dc.NE, loop); 
   } 
   dc.FunctionEnd(); 
 
   dc.PutLabel(data); 
} 
 
//---------------------------- 
 
static void BuildCopyBlockHor(C_dyn_code &dc, int Pos, bool round, bool add, bool ARM5){ 
 
   void *data = dc.DeclareData(0x01010101); 
 
   PreLoad2Init(dc, ARM5, Pos); 
   dc.Ldr(dc.r14, data); 
   dc.Mov(dc.r11, 8); 
   dc.Mvn(dc.r12, dc.r14, dc.LSL, 7); 
   { 
      void *loop = dc.Label(); 
      PreLoad2(dc, ARM5, Pos); 
      CopyHorRow(dc, Pos, round, add); 
      dc.Set(); dc.Sub(dc.r11, dc.r11, 1); 
      dc.Branch(dc.NE, loop); 
   } 
   dc.FunctionEnd(); 
 
   dc.PutLabel(data); 
} 
 
//---------------------------- 
 
static void BuildCopyBlockVer(C_dyn_code &dc, int Pos, bool round, bool add, bool ARM5){ 
 
   void *data = dc.DeclareData(0x01010101); 
 
   dc.Sub(dc.sp, dc.sp, 4); 
   dc.Add(dc.r4, dc.r0, dc.r2, dc.LSL, 3); 
   dc.Add(dc.r4, dc.r4, dc.r2); 
   dc.Str(dc.r4, dc.sp, 0);     //end src 
 
   dc.Ldr(dc.r14, data); 
   dc.Mvn(dc.r12, dc.r14, dc.LSL, 7); 
 
   PreLoad(dc, ARM5, Pos); 
   LoadVerRow(dc, Pos, true); 
   { 
      void *loop = dc.Label(); 
      PreLoad(dc, ARM5, Pos); 
      CopyVerRow(dc, Pos, 0, round, add); 
      PreLoad(dc, ARM5, Pos); 
      CopyVerRow(dc, Pos, 1, round, add); 
 
      dc.Cmp(dc.r0, dc.r7); 
      dc.Branch(dc.NE, loop); 
   } 
   dc.Add(dc.sp, dc.sp, 4); 
   dc.FunctionEnd(); 
 
   dc.PutLabel(data); 
} 
 
//---------------------------- 
 
static void BuildCopyBlockHorVer(C_dyn_code &dc, int Pos, bool round, bool add, bool ARM5){ 
 
   void *data = dc.DeclareData(0x03030303); 
 
   dc.Sub(dc.sp, dc.sp, 12); 
   dc.Add(dc.r4, dc.r0, dc.r2, dc.LSL, 3); 
   dc.Add(dc.r4, dc.r4, dc.r2); 
   dc.Str(dc.r2, dc.sp, 0);     //srcpitch 
   dc.Str(dc.r4, dc.sp, 4);  //end src 
   dc.Str(dc.r3, dc.sp, 8);  //dstpitch 
 
   dc.Ldr(dc.r14, data); 
   dc.Mvn(dc.r12, dc.r14, dc.LSL, 6); 
   PreLoad(dc, ARM5, Pos); 
   LoadHorVerRow(dc, Pos, 1); 
   { 
      void *loop = dc.Label(); 
      PreLoad(dc, ARM5, Pos); 
      CopyHorVerRow(dc, Pos, 0, round, add); 
      PreLoad(dc, ARM5, Pos); 
      CopyHorVerRow(dc, Pos, 1, round, add); 
      dc.Cmp(dc.r0, dc.r3); 
      dc.Branch(dc.NE, loop); 
   } 
   dc.Add(dc.sp, dc.sp, 12); 
   dc.FunctionEnd(); 
 
   dc.PutLabel(data); 
} 
 
//---------------------------- 
 
static void BuildCopyBlockRow(C_dyn_code &dc, int Pos){ 
 
   if(Pos > 0){ 
      dc.Ldr(dc.r5, dc.r0, 8); 
      dc.Ldr(dc.r6, dc.r0, 4); 
      dc.LdrAdvance(dc.r4, dc.r0, dc.r2); 
       
      dc.Mov(dc.r5, dc.r5, dc.LSL, 32-Pos); 
      dc.Orr(dc.r5, dc.r5, dc.r6, dc.LSR, Pos); 
      dc.Mov(dc.r4, dc.r4, dc.LSR, Pos); 
      dc.Orr(dc.r4, dc.r4, dc.r6, dc.LSL, 32-Pos); 
   }else{ 
      dc.Ldr(dc.r5, dc.r0, 4); 
      dc.LdrAdvance(dc.r4, dc.r0, dc.r2); 
   } 
   dc.Str(dc.r5, dc.r1, 4); 
   dc.StrAdvance(dc.r4, dc.r1, dc.r3); 
} 
 
//---------------------------- 
 
static void BuildCopyBlock(C_dyn_code &dc, int Pos, bool round, bool add, bool ARM5){ 
 
   PreLoad2Init(dc, ARM5, Pos); 
   PreLoad2(dc, ARM5, Pos); 
   BuildCopyBlockRow(dc, Pos); 
   PreLoad2(dc, ARM5, Pos); 
   BuildCopyBlockRow(dc, Pos); 
   PreLoad2(dc, ARM5, Pos); 
   BuildCopyBlockRow(dc, Pos); 
   PreLoad2(dc, ARM5, Pos); 
   BuildCopyBlockRow(dc, Pos); 
   PreLoad2(dc, ARM5, Pos); 
   BuildCopyBlockRow(dc, Pos); 
   PreLoad2(dc, ARM5, Pos); 
   BuildCopyBlockRow(dc, Pos); 
   PreLoad2(dc, ARM5, Pos); 
   BuildCopyBlockRow(dc, Pos); 
   PreLoad2(dc, ARM5, Pos); 
   BuildCopyBlockRow(dc, Pos); 
 
   dc.FunctionEnd(); 
} 
 
//---------------------------- 
 
static void BuildCopyBlock8x8(C_dyn_code &dc, int Pos, bool round, bool add, bool ARM5){ 
 
   dc.Mov(dc.r11, 3); 
   { 
      void *loop = dc.Label(); 
#ifdef USE_PLD 
      if(ARM5) 
         dc.Pld(dc.r0, dc.r2,dc.LSL, 1); 
#endif 
      dc.Ldr(dc.r7, dc.r0, 4); 
      dc.LdrAdvance(dc.r6, dc.r0, dc.r2); 
#ifdef USE_PLD 
      if(ARM5) 
         dc.Pld(dc.r0, dc.r2, dc.LSL, 1); 
#endif 
      dc.Ldr(dc.r5, dc.r0, 4); 
      dc.LdrAdvance(dc.r4, dc.r0, dc.r2); 
      dc.Str(dc.r7, dc.r1, 4); 
      dc.StrAdvance(dc.r6, dc.r1, dc.r3); 
      dc.Str(dc.r5, dc.r1, 4); 
      dc.StrAdvance(dc.r4, dc.r1, dc.r3); 
      dc.Set(); dc.Sub(dc.r11, dc.r11, 1); 
      dc.Branch(dc.NE, loop); 
   } 
                              //unroll last (no preload needed) 
   dc.Ldr(dc.r7, dc.r0, 4); 
   dc.LdrAdvance(dc.r6,dc.r0, dc.r2); 
   dc.Ldr(dc.r5, dc.r0, 4); 
   dc.LdrAdvance(dc.r4,dc.r0, dc.r2); 
   dc.Str(dc.r7, dc.r1, 4); 
   dc.StrAdvance(dc.r6, dc.r1, dc.r3); 
   dc.Str(dc.r5, dc.r1, 4); 
   dc.StrAdvance(dc.r4, dc.r1, dc.r3); 
 
   dc.FunctionEnd(); 
} 
 
//---------------------------- 
 
static void CopyBlock16x16Row(C_dyn_code &dc){ 
 
   dc.Ldr(dc.r7, dc.r0, 12); 
   dc.Ldr(dc.r6, dc.r0, 8); 
   dc.Ldr(dc.r5, dc.r0, 4); 
   dc.LdrAdvance(dc.r4, dc.r0, dc.r2); 
   dc.Str(dc.r7, dc.r1, 12); 
   dc.Str(dc.r6, dc.r1, 8); 
   dc.Str(dc.r5, dc.r1, 4); 
   dc.StrAdvance(dc.r4, dc.r1, dc.r3); 
} 
 
//---------------------------- 
 
static void BuildCopyBlock16x16(C_dyn_code &dc, int Pos, bool round, bool add, bool ARM5){ 
 
   dc.Mov(dc.r11, 15); 
   { 
      void *loop = dc.Label(); 
#ifdef USE_PLD 
      if(ARM5) 
         dc.Pld(dc.r0, dc.r2, dc.LSL, 1); 
#endif 
      CopyBlock16x16Row(dc); 
      dc.Set(); dc.Sub(dc.r11, dc.r11, 1); 
      dc.Branch(dc.NE, loop); 
   } 
                              //unroll last (no preload needed) 
   CopyBlock16x16Row(dc); 
 
   dc.FunctionEnd(); 
} 
 
//---------------------------- 
 
static void BuildCopyFunction(C_dyn_code &dc, t_BuldFunc Func, bool round, bool add, bool fast = true, bool ARM5 = false){ 
 
   dc.Align(16); 
   dc.FunctionBegin(); 
#ifdef USE_PLD 
   if(ARM5){ 
      dc.Add(dc.r12, dc.r2, 7); 
      dc.Pld(dc.r0, dc.r2); 
      dc.Pld(dc.r0, 7); 
      dc.Pld(dc.r0, dc.r12); 
      dc.Pld(dc.r0, 0); 
   } 
#endif 
   if(fast){ 
      void *L00 = dc.Label(false); 
      void *L10 = dc.Label(false); 
      void *L11 = dc.Label(false); 
 
      dc.Set(); dc.Mov(dc.r4, dc.r0, dc.LSL, 30); 
      dc.Branch(dc.EQ, L00); 
      dc.Bic(dc.r0, dc.r0, 3); 
      dc.Set(); dc.Cmp(dc.r4, 0x80000000); 
      dc.Branch(dc.EQ, L10); 
      dc.Branch(dc.HI, L11); 
      Func(dc, 8, round, add, ARM5); 
 
      dc.PutLabel(L10); 
      Func(dc, 16, round, add, ARM5); 
 
      dc.PutLabel(L11); 
      Func(dc, 24, round, add, ARM5); 
 
      dc.PutLabel(L00); 
      Func(dc, 0, round, add, ARM5); 
   }else{ 
      Func(dc, -1, round, add, ARM5); 
   } 
} 
 
//---------------------------- 
#ifdef USE_IDCT_WMMX 
//---------------------------- 
 
static void BuildWMMXCopyBegin(C_dyn_code &dc){ 
 
   dc.FunctionBegin(); 
   dc.Add(dc.r12, dc.r2, 7); 
   dc.Pld(dc.r0, dc.r2); 
   dc.Pld(dc.r0, 7); 
 
   dc.Pld(dc.r0, dc.r12); 
   dc.Pld(dc.r0, 0); 
} 
 
//---------------------------- 
 
static void BuildWMMXPreLoad(C_dyn_code &dc){ 
   dc.Pld(dc.r0, dc.r2, dc.LSL, 1); 
} 
 
//---------------------------- 
 
static void BuildWMMXPreLoad2Init(C_dyn_code &dc){ 
   dc.Add(dc.r12, dc.r2, 4); 
} 
 
//---------------------------- 
 
static void BuildWMMXPreLoad2(C_dyn_code &dc){ 
   dc.Pld(dc.r0, dc.r2, dc.LSL, 1); //2*pitch 
   dc.Pld(dc.r0, dc.r12, dc.LSL, 1); //2*pitch+8 
} 
 
//---------------------------- 
 
static void BuildWMMXPrepareAlignVer(C_dyn_code &dc, void *label_aligned){ 
 
   dc.Set(); dc.And(dc.r14, dc.r0, 7); 
   dc.Tmcr(dc.wcgr1, dc.r14); 
   dc.Mov(dc.r14, 8); 
   dc.Branch(dc.EQ, label_aligned); 
   dc.Bic(dc.r0, dc.r0, 7); 
} 
 
//---------------------------- 
 
static void BuildWMMXPrepareAlignHor(C_dyn_code &dc, void *label_wrap){ 
 
   dc.And(dc.r14, dc.r0, 7); 
   dc.Tmcr(dc.wcgr1, dc.r14); 
   dc.Add(dc.r14, dc.r14, 1); 
   dc.Bic(dc.r0, dc.r0, 7); 
   dc.Cmp(dc.r14, 8); 
   dc.Branch(dc.EQ, label_wrap); 
   dc.Tmcr(dc.wcgr2, dc.r14); 
   dc.Mov(dc.r14, 8); 
} 
 
//---------------------------- 
 
static void BuildWMMXCopyBlock(C_dyn_code &dc){ 
 
   void *label_aligned = dc.Label(false); 
   dc.Align(16); 
 
   BuildWMMXCopyBegin(dc); 
 
   dc.Sub(dc.r1, dc.r1, dc.r3); 
   BuildWMMXPrepareAlignVer(dc, label_aligned); 
 
   BuildWMMXPreLoad2Init(dc); 
   { 
      void *loop = dc.Label(); 
      BuildWMMXPreLoad2(dc); 
      dc.Wldrd(dc.wr0, dc.r0, 0); 
      dc.Wldrd(dc.wr1, dc.r0, 8); 
      dc.Add(dc.r0, dc.r0, dc.r2); 
      dc.Add(dc.r1, dc.r1, dc.r3); 
      dc.Walignr(1, dc.wr0, dc.wr0, dc.wr1); 
      dc.Wstrd(dc.wr0, dc.r1, 0); 
      dc.Set(); dc.Sub(dc.r14, dc.r14, 1); 
      dc.Branch(dc.NE, loop); 
   } 
   dc.FunctionEnd(); 
 
dc.PutLabel(label_aligned); 
   { 
      BuildWMMXPreLoad(dc); 
      dc.Wldrd(dc.wr0, dc.r0, 0); 
      dc.Add(dc.r0, dc.r0, dc.r2); 
      dc.Add(dc.r1, dc.r1, dc.r3); 
      dc.Wstrd(dc.wr0, dc.r1, 0); 
      dc.Set(); dc.Sub(dc.r14, dc.r14, 1); 
      dc.Branch(dc.NE, label_aligned); 
   } 
   dc.FunctionEnd(); 
} 
 
//---------------------------- 
 
static void BuildWMMXAddBlock(C_dyn_code &dc){ 
 
   void *label_aligned = dc.Label(false); 
   dc.Align(16); 
 
   BuildWMMXCopyBegin(dc); 
   BuildWMMXPrepareAlignVer(dc, label_aligned); 
 
   BuildWMMXPreLoad2Init(dc); 
   { 
      void *loop = dc.Label(); 
      BuildWMMXPreLoad2(dc); 
      dc.Wldrd(dc.wr0, dc.r0, 0); 
      dc.Wldrd(dc.wr1, dc.r0, 8); 
      dc.Add(dc.r0, dc.r0, dc.r2); 
      dc.Wldrd(dc.wr5, dc.r1, 0); 
      dc.Walignr(1, dc.wr0, dc.wr0, dc.wr1); 
      dc.Wavg2b(true, dc.wr0, dc.wr0, dc.wr5); 
      dc.WstrdAdvance(dc.wr0, dc.r1, 8); 
      dc.Set(); dc.Sub(dc.r14, dc.r14, 1); 
      dc.Branch(dc.NE, loop); 
   } 
   dc.FunctionEnd(); 
 
dc.PutLabel(label_aligned); 
   { 
      BuildWMMXPreLoad(dc); 
      dc.Wldrd(dc.wr0, dc.r0, 0); 
      dc.Add(dc.r0, dc.r0, dc.r2); 
      dc.Wldrd(dc.wr5, dc.r1, 0); 
      dc.Wavg2b(true, dc.wr0, dc.wr0, dc.wr5); 
      dc.WstrdAdvance(dc.wr0, dc.r1, 8); 
      dc.Set(); dc.Sub(dc.r14, dc.r14, 1); 
      dc.Branch(dc.NE, label_aligned); 
   } 
   dc.FunctionEnd(); 
} 
 
//---------------------------- 
 
static void BuildWMMXCopyHorRow(C_dyn_code &dc, bool round, bool add, bool wrap){ 
 
   BuildWMMXPreLoad2(dc); 
   dc.Wldrd(dc.wr0, dc.r0, 0); 
   dc.Wldrd(dc.wr1, dc.r0, 8); 
   dc.Add(dc.r0, dc.r0, dc.r2); 
   if(add){ 
      dc.Wldrd(dc.wr5, dc.r1, 0); 
   }else{ 
      dc.Add(dc.r1, dc.r1, dc.r3); 
   } 
   dc.Walignr(1, dc.wr2, dc.wr0, dc.wr1); 
   if(!wrap){ 
      dc.Walignr(2, dc.wr1, dc.wr0, dc.wr1); 
   } 
   if(round){ 
      dc.Wavg2b(false, dc.wr0, dc.wr1, dc.wr2); 
   }else{ 
      dc.Wavg2b(true, dc.wr0, dc.wr1, dc.wr2); 
   } 
   if(add){ 
      dc.Wavg2b(true, dc.wr0, dc.wr0, dc.wr5); 
      dc.WstrdAdvance(dc.wr0, dc.r1, 8); 
   }else{ 
      dc.Wstrd(dc.wr0, dc.r1, 0); 
   } 
} 
 
//---------------------------- 
 
static void BuildWMMXCopyBlockHor(C_dyn_code &dc, bool round, bool add){ 
 
   void *label_wrap = dc.Label(false); 
   dc.Align(16); 
 
   BuildWMMXCopyBegin(dc); 
   if(!add){ 
      dc.Sub(dc.r1, dc.r1, dc.r3); 
   } 
   BuildWMMXPreLoad2Init(dc); 
   BuildWMMXPrepareAlignHor(dc, label_wrap); 
   { 
      void *loop = dc.Label(); 
      BuildWMMXCopyHorRow(dc, round, add, false); 
      dc.Set(); dc.Sub(dc.r14, dc.r14, 1); 
      dc.Branch(dc.NE, loop); 
   } 
   dc.FunctionEnd(); 
 
dc.PutLabel(label_wrap); 
   { 
      BuildWMMXCopyHorRow(dc, round, add, true); 
      dc.Set(); dc.Sub(dc.r14, dc.r14, 1); 
      dc.Branch(dc.NE, label_wrap); 
   } 
   dc.FunctionEnd(); 
} 
 
//---------------------------- 
 
static void BuildWMMXSetVerRow(C_dyn_code &dc, bool round, bool add){ 
 
   if(add){ 
      dc.Wldrd(dc.wr5, dc.r1, 0); 
   }else{ 
      dc.Add(dc.r1, dc.r1, dc.r3); 
   } 
   if(round){ 
      dc.Wavg2b(false, dc.wr1, dc.wr0, dc.wr2); 
   }else{ 
      dc.Wavg2b(true, dc.wr1, dc.wr0, dc.wr2); 
   } 
   if(add){ 
      dc.Wavg2b(true, dc.wr1, dc.wr1, dc.wr5); 
      dc.WstrdAdvance(dc.wr1, dc.r1, 8); 
   }else{ 
      dc.Wstrd(dc.wr1, dc.r1, 0); 
   } 
} 
 
//---------------------------- 
 
static void BuildWMMXCopyBlockVer(C_dyn_code &dc, bool round, bool add){ 
 
   void *label_aligned = dc.Label(false); 
 
   dc.Align(16); 
 
   BuildWMMXCopyBegin(dc); 
   if(!add){ 
     dc.Sub(dc.r1, dc.r1, dc.r3); 
   } 
   BuildWMMXPrepareAlignVer(dc, label_aligned); 
 
   BuildWMMXPreLoad2Init(dc); 
   BuildWMMXPreLoad2(dc); 
   dc.Wldrd(dc.wr0, dc.r0, 0); 
   dc.Wldrd(dc.wr1, dc.r0, 8); 
   dc.Add(dc.r0, dc.r0, dc.r2); 
   dc.Walignr(1, dc.wr0, dc.wr0, dc.wr1); 
   { 
      void *loop = dc.Label(); 
      BuildWMMXPreLoad2(dc); 
      dc.Wldrd(dc.wr2, dc.r0, 0); 
      dc.Wldrd(dc.wr1, dc.r0, 8); 
      dc.Add(dc.r0, dc.r0, dc.r2); 
      dc.Walignr(1, dc.wr2, dc.wr2, dc.wr1); 
      BuildWMMXSetVerRow(dc, round, add); 
      BuildWMMXPreLoad2(dc); 
      dc.Wldrd(dc.wr0, dc.r0, 0); 
      dc.Wldrd(dc.wr1, dc.r0, 8); 
      dc.Add(dc.r0, dc.r0, dc.r2); 
      dc.Walignr(1, dc.wr0, dc.wr0, dc.wr1); 
      BuildWMMXSetVerRow(dc, round, add); 
      dc.Set(); dc.Sub(dc.r14, dc.r14, 2); 
      dc.Branch(dc.NE, loop); 
   } 
   dc.FunctionEnd(); 
 
dc.PutLabel(label_aligned); 
 
   BuildWMMXPreLoad(dc);   
   dc.Wldrd(dc.wr0, dc.r0, 0); 
   dc.Add(dc.r0, dc.r0, dc.r2); 
   { 
      void *loop = dc.Label(); 
      BuildWMMXPreLoad(dc);   
      dc.Wldrd(dc.wr2, dc.r0, 0); 
      dc.Add(dc.r0, dc.r0, dc.r2); 
      BuildWMMXSetVerRow(dc, round, add); 
      BuildWMMXPreLoad(dc);   
      dc.Wldrd(dc.wr0, dc.r0, 0); 
      dc.Add(dc.r0, dc.r0, dc.r2); 
      BuildWMMXSetVerRow(dc, round, add); 
      dc.Set(); dc.Sub(dc.r14, dc.r14, 2); 
      dc.Branch(dc.NE, loop); 
   } 
   dc.FunctionEnd(); 
} 
 
//---------------------------- 
// wr6 0x03 
// wr7 ~0x03 
static void BuildWMMXLoadHorVerRow(C_dyn_code &dc, bool parity, bool wrap){ 
   
  BuildWMMXPreLoad2(dc); 
  if(parity){ 
      dc.Wldrd(dc.wr0, dc.r0, 0); 
      dc.Wldrd(dc.wr1, dc.r0, 8); 
      dc.Add(dc.r0, dc.r0, dc.r2); 
      dc.Walignr(1, dc.wr2, dc.wr0, dc.wr1); 
      if(!wrap){ 
         dc.Walignr(2, dc.wr1, dc.wr0, dc.wr1); 
      } 
      dc.Wand(dc.wr0, dc.wr2, dc.wr6); 
      dc.Wand(dc.wr3, dc.wr1, dc.wr6); 
      dc.Wand(dc.wr2, dc.wr2, dc.wr7); 
      dc.Wand(dc.wr1, dc.wr1, dc.wr7); 
      dc.Wsrldg(dc.wr2, dc.wr2, dc.wcgr0); 
      dc.Wsrldg(dc.wr1, dc.wr1, dc.wcgr0); 
      dc.Waddb(dc.wr2, dc.wr2, dc.wr1); 
      dc.Waddb(dc.wr1, dc.wr3, dc.wr0); 
   }else{ 
      dc.Wldrd(dc.wr3, dc.r0, 0); 
      dc.Wldrd(dc.wr4, dc.r0, 8); 
      dc.Add(dc.r0, dc.r0, dc.r2); 
      dc.Walignr(1, dc.wr5, dc.wr3, dc.wr4); 
      if(!wrap){ 
         dc.Walignr(2, dc.wr4, dc.wr3, dc.wr4); 
      } 
      dc.Wand(dc.wr0, dc.wr5, dc.wr6); 
      dc.Wand(dc.wr3, dc.wr4, dc.wr6); 
      dc.Wand(dc.wr5, dc.wr5, dc.wr7); 
      dc.Wand(dc.wr4, dc.wr4, dc.wr7); 
      dc.Wsrldg(dc.wr5, dc.wr5, dc.wcgr0); 
      dc.Wsrldg(dc.wr4, dc.wr4, dc.wcgr0); 
      dc.Waddb(dc.wr5, dc.wr5, dc.wr4); 
      dc.Waddb(dc.wr4, dc.wr3, dc.wr0); 
   } 
} 
 
//---------------------------- 
 
static void BuildWMMXSetHorVerRow(C_dyn_code &dc, bool add){ 
 
   if(add){ 
      dc.Wldrd(dc.wr9, dc.r1, 0); 
   }else{ 
      dc.Add(dc.r1, dc.r1, dc.r3); 
   } 
   dc.Waddb(dc.wr0, dc.wr1, dc.wr4); 
   dc.Waddb(dc.wr0, dc.wr0, dc.wr8);   //rounding 
   dc.Wand(dc.wr0, dc.wr0, dc.wr7); 
   dc.Waddb(dc.wr3, dc.wr2, dc.wr5); 
   dc.Wsrldg(dc.wr0, dc.wr0, dc.wcgr0); 
   dc.Waddb(dc.wr0, dc.wr0, dc.wr3); 
   if(add){ 
      dc.Wavg2b(true, dc.wr0, dc.wr0, dc.wr9); 
      dc.WstrdAdvance(dc.wr0, dc.r1, 8); 
   }else{ 
      dc.Wstrd(dc.wr0, dc.r1, 0); 
   } 
} 
 
//---------------------------- 
 
static void BuildWMMXCopyBlockHorVer(C_dyn_code &dc, bool round, bool add){ 
 
   void *label_wrap = dc.Label(false); 
   dc.Align(16); 
   BuildWMMXCopyBegin(dc); 
   if(!add){ 
      dc.Sub(dc.r1, dc.r1, dc.r3); 
   } 
   if(round){ 
      dc.Mov(dc.r14, 1); 
   }else{ 
      dc.Mov(dc.r14, 2); 
   } 
   dc.Tbcstb(dc.wr8, dc.r14); 
   dc.Mov(dc.r14, 3); 
   dc.Tbcstb(dc.wr6, dc.r14); 
   dc.Mvn(dc.r14, 3); 
   dc.Tbcstb(dc.wr7, dc.r14); 
   dc.Mov(dc.r14, 2); 
   dc.Tmcr(dc.wcgr0, dc.r14); 
   BuildWMMXPreLoad2Init(dc); 
   BuildWMMXPrepareAlignHor(dc, label_wrap); 
 
   BuildWMMXLoadHorVerRow(dc, true, false); 
   { 
      void *loop = dc.Label(); 
      BuildWMMXLoadHorVerRow(dc, false, false); 
      BuildWMMXSetHorVerRow(dc, add); 
      BuildWMMXLoadHorVerRow(dc, true, false); 
      BuildWMMXSetHorVerRow(dc, add); 
      dc.Set(); dc.Sub(dc.r14, dc.r14, 2); 
      dc.Branch(dc.NE, loop); 
   } 
   dc.FunctionEnd(); 
 
dc.PutLabel(label_wrap); 
   BuildWMMXLoadHorVerRow(dc, true, true); 
 
   { 
      void *loop = dc.Label(); 
      BuildWMMXLoadHorVerRow(dc, false, true); 
      BuildWMMXSetHorVerRow(dc, add); 
      BuildWMMXLoadHorVerRow(dc, true, true); 
      BuildWMMXSetHorVerRow(dc, add); 
      dc.Set(); dc.Sub(dc.r14, dc.r14, 2); 
      dc.Branch(dc.NE, loop); 
   } 
   dc.FunctionEnd(); 
} 
 
//---------------------------- 
#endif//USE_IDCT_WMMX 
//---------------------------- 
 
void BuildMotionCompensationFunctions(C_dyn_code &dc, bool use_wmmx){ 
 
#ifdef USE_IDCT_WMMX 
   if(use_wmmx){ 
                              //AddBlock 
      BuildWMMXAddBlock(dc); 
                              //AddBlockHor 
      BuildWMMXCopyBlockHor(dc, false, true); 
                              //AddBlockVer 
      BuildWMMXCopyBlockVer(dc, false, true); 
                              //AddBlockHorVer 
      BuildWMMXCopyBlockHorVer(dc, false, true); 
 
                              //CopyBlock 
      BuildWMMXCopyBlock(dc); 
                              //CopyBlockHor 
      BuildWMMXCopyBlockHor(dc, false, false); 
                              //CopyBlockHorRound 
      BuildWMMXCopyBlockHor(dc, true, false); 
                              //CopyBlockVer 
      BuildWMMXCopyBlockVer(dc, false, false); 
                              //CopyBlockVerRound 
      BuildWMMXCopyBlockVer(dc, true, false); 
                              //CopyBlockHorVer 
      BuildWMMXCopyBlockHorVer(dc, false, false); 
                              //CopyBlockHorVerRound 
      BuildWMMXCopyBlockHorVer(dc, true, false); 
   }else 
#endif 
   { 
                              //0 - 3 
                              //AddBlock 
      BuildCopyFunction(dc, BuildAddBlock, false, true); 
                              //AddBlockHor 
      BuildCopyFunction(dc, BuildCopyBlockHor, false, true); 
                              //AddBlockVer 
      BuildCopyFunction(dc, BuildCopyBlockVer, false, true); 
                              //AddBlockHorVer 
      BuildCopyFunction(dc, BuildCopyBlockHorVer, false, true); 
 
                              //4 - 10 
                              //CopyBlock 
      BuildCopyFunction(dc, BuildCopyBlock, false, false, true); 
                              //CopyBlockHor 
      BuildCopyFunction(dc, BuildCopyBlockHor, false, false); 
                              //CopyBlockHorRound 
      BuildCopyFunction(dc, BuildCopyBlockHor, true, false); 
                              //CopyBlockVer 
      BuildCopyFunction(dc, BuildCopyBlockVer, false, false); 
                              //CopyBlockVerRound 
      BuildCopyFunction(dc, BuildCopyBlockVer, true, false); 
                              //CopyBlockHorVer 
      BuildCopyFunction(dc, BuildCopyBlockHorVer, false, false); 
                              //CopyBlockHorVerRound 
      BuildCopyFunction(dc, BuildCopyBlockHorVer, true, false); 
   } 
                              //11, 12 
                              //CopyBlock8x8 
   BuildCopyFunction(dc, BuildCopyBlock8x8, false, false, false); 
                              //CopyBlock16x16 
   BuildCopyFunction(dc, BuildCopyBlock16x16, false, false, false); 
} 
 
 
//---------------------------- 
#else//ARM 
//---------------------------- 
 
#define LoadRow(a,b,o) { \ 
   a=Src[o+0]|(Src[o+1]<<8)|((Src[o+2]|((char)Src[o+3]<<8))<<16); \ 
   b=Src[o+4]|(Src[o+5]<<8)|((Src[o+6]|((char)Src[o+7]<<8))<<16); \ 
} 
#define LoadMRow(a,b,c,d,o)   \ 
{                    \ 
   a=Src[o+0]|(Src[o+1]<<8)|(Src[o+2]<<16)|(Src[o+3]<<24); \ 
   b=Src[o+4]|(Src[o+5]<<8)|(Src[o+6]<<16)|(Src[o+7]<<24); \ 
   c=Src[o+8]|(Src[o+9]<<8)|(Src[o+10]<<16)|(Src[o+11]<<24); \ 
   d=Src[o+12]|(Src[o+13]<<8)|(Src[o+14]<<16)|(Src[o+15]<<24); \ 
} 
 
#define SaveRow(a,b) \ 
{                 \ 
   ((dword*)Dst)[0]=a;\ 
   ((dword*)Dst)[1]=b;\ 
} 
#define SaveMRow(a,b,c,d)  \ 
{                    \ 
   ((dword*)Dst)[0]=a;  \ 
   ((dword*)Dst)[1]=b;  \ 
   ((dword*)Dst)[2]=c;  \ 
   ((dword*)Dst)[3]=d;  \ 
} 
#define AddRow(a,b,c,d)       \ 
{                       \ 
   dword q,w;           \ 
   c=((dword*)Dst)[0];     \ 
   d=((dword*)Dst)[1];     \ 
   q=(a|c) & 0x01010101;      \ 
   w=(b|d) & 0x01010101;      \ 
   q+=(a>>1) & 0x7F7F7F7F;    \ 
   w+=(b>>1) & 0x7F7F7F7F;    \ 
   q+=(c>>1) & 0x7F7F7F7F;    \ 
   w+=(d>>1) & 0x7F7F7F7F;    \ 
   ((dword*)Dst)[0]=q;     \ 
   ((dword*)Dst)[1]=w;     \ 
} 
#define Avg2(a,b,c,d,e,f)              \ 
{                                \ 
   e=(a|c) & 0x01010101;               \ 
   f=(b|d) & 0x01010101;               \ 
   e+=(a>>1) & 0x7F7F7F7F;             \ 
   f+=(b>>1) & 0x7F7F7F7F;             \ 
   e+=(c>>1) & 0x7F7F7F7F;             \ 
   f+=(d>>1) & 0x7F7F7F7F;             \ 
} 
#define Avg2Round(a,b,c,d,e,f)            \ 
{                                \ 
   e=(a&c) & 0x01010101;               \ 
   f=(b&d) & 0x01010101;               \ 
   e+=(a>>1) & 0x7F7F7F7F;             \ 
   f+=(b>>1) & 0x7F7F7F7F;             \ 
   e+=(c>>1) & 0x7F7F7F7F;             \ 
   f+=(d>>1) & 0x7F7F7F7F;             \ 
} 
#define PrepareAvg4(a,b,c,d)           \ 
{                                \ 
   dword q,w;                    \ 
   q=(a & 0x03030303);                 \ 
   w=(b & 0x03030303);                 \ 
   q+=(c & 0x03030303);             \ 
   w+=(d & 0x03030303);             \ 
   a=(a>>2) & 0x3F3F3F3F;              \ 
   b=(b>>2) & 0x3F3F3F3F;              \ 
   a+=(c>>2) & 0x3F3F3F3F;             \ 
   b+=(d>>2) & 0x3F3F3F3F;             \ 
   c=q;                          \ 
   d=w;                          \ 
} 
#define Avg4(a,b,c,d,g,h,i,j)          \ 
{                                \ 
   a+=g;                         \ 
   b+=h;                         \ 
   c+=i+0x02020202;                 \ 
   d+=j+0x02020202;                 \ 
   a+=(c>>2) & 0x03030303;             \ 
   b+=(d>>2) & 0x03030303;             \ 
} 
#define Avg4Round(a,b,c,d,g,h,i,j)        \ 
{                                \ 
   a+=g;                         \ 
   b+=h;                         \ 
   c+=i+0x01010101;                 \ 
   d+=j+0x01010101;                 \ 
   a+=(c>>2) & 0x03030303;             \ 
   b+=(d>>2) & 0x03030303;             \ 
} 
 
//---------------------------- 
// Dst[p] = Src[p] 
void CopyBlock(const byte *Src, byte *Dst, int SrcPitch, int DstPitch){ 
   const byte *SrcEnd = Src + 8*SrcPitch; 
   dword a,b; 
   do { 
      LoadRow(a,b,0) 
      SaveRow(a,b) 
      Dst += DstPitch; 
      Src += SrcPitch; 
   } while (Src != SrcEnd); 
} 
 
//---------------------------- 
// Dst[p] = (Src[p] + Src[p+1]+1) >> 1; 
void CopyBlockHor(const byte *Src, byte *Dst, int SrcPitch, int DstPitch){ 
   const byte *SrcEnd = Src + 8*SrcPitch; 
   dword a,b,c,d,e,f; 
   do { 
      LoadRow(a,b,0) 
      LoadRow(c,d,1) 
      Avg2(a,b,c,d,e,f) 
      SaveRow(e,f) 
      Dst += DstPitch; 
      Src += SrcPitch; 
   } while (Src != SrcEnd); 
} 
 
//---------------------------- 
// Dst[p] = (Src[p] + Src[p+SrcPitch]+1) >> 1; 
void CopyBlockVer(const byte *Src, byte *Dst, int SrcPitch, int DstPitch){ 
   const byte *SrcEnd = Src + 8*SrcPitch; 
   dword a,b,c,d,e,f; 
   LoadRow(a,b,0) 
   do { 
      Src += SrcPitch; 
      LoadRow(c,d,0) 
      Avg2(a,b,c,d,e,f) 
      SaveRow(e,f) 
      Dst += DstPitch; 
 
      Src += SrcPitch; 
      LoadRow(a,b,0) 
      Avg2(c,d,a,b,e,f) 
      SaveRow(e,f) 
      Dst += DstPitch; 
   } while (Src != SrcEnd); 
} 
 
//---------------------------- 
// Dst[p] = (Src[p] + Src[p+1] + Src[p+SrcPitch] + Src[p+SrcPitch+1] + 2) >> 2; 
void CopyBlockHorVer(const byte *Src, byte *Dst, int SrcPitch, int DstPitch){ 
   const byte *SrcEnd = Src + 8*SrcPitch; 
   dword a,b,c,d,g,h,i,j; 
   LoadRow(a,b,0) 
   LoadRow(c,d,1) 
   PrepareAvg4(a,b,c,d) 
   do { 
      Src += SrcPitch; 
      LoadRow(g,h,0) 
      LoadRow(i,j,1) 
      PrepareAvg4(g,h,i,j) 
      Avg4(a,b,c,d,g,h,i,j) 
      SaveRow(a,b) 
      Dst += DstPitch; 
 
      Src += SrcPitch; 
      LoadRow(a,b,0) 
      LoadRow(c,d,1) 
      PrepareAvg4(a,b,c,d) 
      Avg4(g,h,i,j,a,b,c,d) 
      SaveRow(g,h) 
      Dst += DstPitch; 
   } while (Src != SrcEnd); 
} 
 
//---------------------------- 
// Dst[p] = (Src[p] + Src[p+1]) >> 1; 
void CopyBlockHorRound(const byte *Src, byte *Dst, int SrcPitch, int DstPitch){ 
   const byte *SrcEnd = Src + 8*SrcPitch; 
   dword a,b,c,d,e,f; 
   do { 
      LoadRow(a,b,0) 
      LoadRow(c,d,1) 
      Avg2Round(a,b,c,d,e,f) 
      SaveRow(e,f) 
      Dst += DstPitch; 
      Src += SrcPitch; 
   } while (Src != SrcEnd); 
} 
 
//---------------------------- 
// Dst[p] = (Src[p] + Src[p+SrcPitch]) >> 1; 
void CopyBlockVerRound(const byte *Src, byte *Dst, int SrcPitch, int DstPitch){ 
   const byte *SrcEnd = Src + 8*SrcPitch; 
   dword a,b,c,d,e,f; 
   LoadRow(a,b,0) 
   do{ 
      Src += SrcPitch; 
      LoadRow(c,d,0) 
      Avg2Round(a,b,c,d,e,f) 
      SaveRow(e,f) 
      Dst += DstPitch; 
 
      Src += SrcPitch; 
      LoadRow(a,b,0) 
      Avg2Round(c,d,a,b,e,f) 
      SaveRow(e,f) 
      Dst += DstPitch; 
   }while (Src != SrcEnd); 
} 
 
//---------------------------- 
// Dst[p] = (Src[p] + Src[p+1] + Src[p+SrcPitch] + Src[p+SrcPitch+1] + 1) >> 2; 
void CopyBlockHorVerRound(const byte *Src, byte *Dst, int SrcPitch, int DstPitch){ 
   const byte *SrcEnd = Src + 8*SrcPitch; 
   dword a,b,c,d,g,h,i,j; 
   LoadRow(a,b,0) 
   LoadRow(c,d,1) 
   PrepareAvg4(a,b,c,d) 
   do{ 
      Src += SrcPitch; 
      LoadRow(g,h,0) 
      LoadRow(i,j,1) 
      PrepareAvg4(g,h,i,j) 
      Avg4Round(a,b,c,d,g,h,i,j) 
      SaveRow(a,b) 
      Dst += DstPitch; 
 
      Src += SrcPitch; 
      LoadRow(a,b,0) 
      LoadRow(c,d,1) 
      PrepareAvg4(a,b,c,d) 
      Avg4Round(g,h,i,j,a,b,c,d) 
      SaveRow(g,h) 
      Dst += DstPitch; 
   } while (Src != SrcEnd); 
} 
 
//---------------------------- 
// Dst[p] = (Src[p] + Dst[p] + 1) >> 1 
void AddBlock(const byte *Src, byte *Dst, int SrcPitch){ 
   const byte *SrcEnd = Src + 8*SrcPitch; 
   dword a,b,c,d; 
   do { 
      LoadRow(a,b,0) 
      AddRow(a,b,c,d) 
      Dst += 8; 
      Src += SrcPitch; 
   } while (Src != SrcEnd); 
} 
 
//---------------------------- 
// Dst[p] = (((Src[p] + Src[p+1]+1) >> 1) + Dst[p] + 1) >> 1 
void AddBlockHor(const byte *Src, byte *Dst, int SrcPitch){ 
   const byte *SrcEnd = Src + 8*SrcPitch; 
   dword a,b,c,d,e,f; 
   do { 
      LoadRow(a,b,0) 
      LoadRow(c,d,1) 
      Avg2(a,b,c,d,e,f) 
      AddRow(e,f,a,b) 
      Dst += 8; 
      Src += SrcPitch; 
   } 
   while (Src != SrcEnd); 
} 
 
//---------------------------- 
// Dst[p] = (((Src[p] + Src[p+SrcPitch]+1) >> 1) + Dst[p] + 1) >> 1 
void AddBlockVer(const byte *Src, byte *Dst, int SrcPitch){ 
   const byte *SrcEnd = Src + 8*SrcPitch; 
   dword a,b,c,d,e,f; 
   LoadRow(a,b,0) 
   do { 
      Src += SrcPitch; 
      LoadRow(c,d,0) 
      Avg2(a,b,c,d,e,f) 
      AddRow(e,f,a,b) 
      a=c; 
      b=d; 
      Dst += 8; 
   } while (Src != SrcEnd); 
} 
 
//---------------------------- 
// Dst[p] = (((Src[p] + Src[p+1] + Src[p+SrcPitch] + Src[p+SrcPitch+1] + 2) >> 2) + Dst[p] + 1) >> 1 
void AddBlockHorVer(const byte *Src, byte *Dst, int SrcPitch){ 
   const byte *SrcEnd = Src + 8*SrcPitch; 
   dword a,b,c,d,g,h,i,j; 
   LoadRow(a,b,0) 
   LoadRow(c,d,1) 
   PrepareAvg4(a,b,c,d) 
   do{ 
      Src += SrcPitch; 
      LoadRow(g,h,0) 
      LoadRow(i,j,1) 
      PrepareAvg4(g,h,i,j) 
      Avg4(a,b,c,d,g,h,i,j) 
      AddRow(a,b,c,d) 
      a=g; 
      b=h; 
      c=i; 
      d=j; 
      Dst += 8; 
   }while (Src != SrcEnd); 
} 
 
//---------------------------- 
// Dst[p] = Src[p] 
void CopyBlock16x16(const byte *Src, byte *Dst, int SrcPitch,int DstPitch){ 
   const byte *SrcEnd = Src + 16*SrcPitch; 
   dword a,b,c,d; 
   do { 
      a=((dword*)Src)[0]; 
      b=((dword*)Src)[1]; 
      c=((dword*)Src)[2]; 
      d=((dword*)Src)[3]; 
      ((dword*)Dst)[0]=a; 
      ((dword*)Dst)[1]=b; 
      ((dword*)Dst)[2]=c; 
      ((dword*)Dst)[3]=d; 
      Dst += DstPitch; 
      Src += SrcPitch; 
   } while (Src != SrcEnd); 
} 
 
//---------------------------- 
// Dst[p] = Src[p] 
void CopyBlock8x8(const byte *Src, byte *Dst, int SrcPitch,int DstPitch){ 
   const byte *SrcEnd = Src + 8*SrcPitch; 
   dword a,b,c,d; 
   do { 
      a=((dword*)Src)[0]; 
      b=((dword*)Src)[1]; 
      Src += SrcPitch; 
      c=((dword*)Src)[0]; 
      d=((dword*)Src)[1]; 
      Src += SrcPitch; 
      ((dword*)Dst)[0]=a; 
      ((dword*)Dst)[1]=b; 
      Dst += DstPitch; 
      ((dword*)Dst)[0]=c; 
      ((dword*)Dst)[1]=d; 
      Dst += DstPitch; 
   } while (Src != SrcEnd); 
} 
 
#endif//!ARM 
 
//----------------------------