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
//----------------------------