@ -40,6 +40,27 @@ static const unsigned long long int mm_wtwo __attribute__ ((aligned(8))) = 0x000
//static const unsigned short mm_wone[4] __attribute__ ((aligned(8))) = { 0x1, 0x1, 0x1, 0x1 };
//static const unsigned short mm_wtwo[4] __attribute__ ((aligned(8))) = { 0x2, 0x2, 0x2, 0x2 };
# define JUMPALIGN() __asm __volatile (".balign 8"::)
# define MOVQ_ZERO(regd) __asm __volatile ("pxor %%" #regd ", %%" #regd ::)
# ifndef PIC
# define MOVQ_WONE(regd) __asm __volatile ("movq %0, %%" #regd " \n\t" ::"m"(mm_wone))
# define MOVQ_WTWO(regd) __asm __volatile ("movq %0, %%" #regd " \n\t" ::"m"(mm_wtwo))
# else
// for shared library it's better to use this way for accessing constants
// pcmpeqd -> -1
# define MOVQ_WONE(regd) \
__asm __volatile ( \
" pcmpeqd %% " # regd " , %% " # regd " \n \t " \
" psrlw $15, %% " # regd : : )
# define MOVQ_WTWO(regd) \
__asm __volatile ( \
" pcmpeqd %% " # regd " , %% " # regd " \n \t " \
" psrlw $15, %% " # regd " \n \t " \
" psllw $1, %% " # regd : : )
# endif
/***********************************/
/* 3Dnow specific */
@ -77,7 +98,7 @@ static void get_pixels_mmx(DCTELEM *block, const UINT8 *pixels, int line_size)
/* read the pixels */
p = block ;
pix = pixels ;
__asm __volatile ( " pxor %%mm7, %%mm7 " : ) ;
MOVQ_ZERO ( mm7 ) ;
for ( i = 0 ; i < 4 ; i + + ) {
__asm __volatile (
" movq %1, %%mm0 \n \t "
@ -104,12 +125,11 @@ static void put_pixels_clamped_mmx(const DCTELEM *block, UINT8 *pixels, int line
{
const DCTELEM * p ;
UINT8 * pix ;
int i ;
/* read the pixels */
p = block ;
pix = pixels ;
for ( i = 0 ; i < 2 ; i + + ) {
/* unrolled loop */
__asm __volatile (
" movq %3, %%mm0 \n \t "
" movq 8%3, %%mm1 \n \t "
@ -131,7 +151,29 @@ static void put_pixels_clamped_mmx(const DCTELEM *block, UINT8 *pixels, int line
: " memory " ) ;
pix + = line_size * 4 ;
p + = 32 ;
}
// if here would be an exact copy of the code above
// compiler would generate some very strange code
// thus using "r"
__asm __volatile (
" movq (%3), %%mm0 \n \t "
" movq 8(%3), %%mm1 \n \t "
" movq 16(%3), %%mm2 \n \t "
" movq 24(%3), %%mm3 \n \t "
" movq 32(%3), %%mm4 \n \t "
" movq 40(%3), %%mm5 \n \t "
" movq 48(%3), %%mm6 \n \t "
" movq 56(%3), %%mm7 \n \t "
" packuswb %%mm1, %%mm0 \n \t "
" packuswb %%mm3, %%mm2 \n \t "
" packuswb %%mm5, %%mm4 \n \t "
" packuswb %%mm7, %%mm6 \n \t "
" movq %%mm0, (%0) \n \t "
" movq %%mm2, (%0, %1) \n \t "
" movq %%mm4, (%0, %1, 2) \n \t "
" movq %%mm6, (%0, %2) \n \t "
: : " r " ( pix ) , " r " ( line_size ) , " r " ( line_size * 3 ) , " r " ( p )
: " memory " ) ;
}
static void add_pixels_clamped_mmx ( const DCTELEM * block , UINT8 * pixels , int line_size )
@ -143,8 +185,9 @@ static void add_pixels_clamped_mmx(const DCTELEM *block, UINT8 *pixels, int line
/* read the pixels */
p = block ;
pix = pixels ;
__asm __volatile ( " pxor %%mm7, %%mm7 " : ) ;
for ( i = 0 ; i < 4 ; i + + ) {
MOVQ_ZERO ( mm7 ) ;
i = 4 ;
while ( i ) {
__asm __volatile (
" movq %2, %%mm0 \n \t "
" movq 8%2, %%mm1 \n \t "
@ -171,19 +214,47 @@ static void add_pixels_clamped_mmx(const DCTELEM *block, UINT8 *pixels, int line
: " memory " ) ;
pix + = line_size * 2 ;
p + = 16 ;
}
i - - ;
} ;
}
static void put_pixels_mmx ( UINT8 * block , const UINT8 * pixels , int line_size , int h )
{
int dh , hh ;
int hh ;
UINT8 * p ;
const UINT8 * pix ;
p = block ;
pix = pixels ;
pix = pixels ; // 2s
#if 0
do {
__asm __volatile (
" movq %1, %%mm0 \n \t "
" movq %%mm0, %0 \n \t "
: " =m " ( * p )
: " m " ( * pix )
: " memory " ) ;
pix + = line_size ;
p + = line_size ;
} while ( - - h ) ;
# else
// this optimized code is not very usefull
// the above loop is definitely faster
// at least on Celeron 500MHz
hh = h & 3 ;
while ( hh ) {
__asm __volatile (
" movq %1, %%mm0 \n \t "
" movq %%mm0, %0 \n \t "
: " =m " ( * p )
: " m " ( * pix )
: " memory " ) ;
pix + = line_size ;
p + = line_size ;
hh - - ;
}
hh = h > > 2 ;
dh = h & 3 ;
while ( hh - - ) {
while ( hh ) {
__asm __volatile (
" movq (%1), %%mm0 \n \t "
" movq (%1, %2), %%mm1 \n \t "
@ -195,19 +266,11 @@ static void put_pixels_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int
" movq %%mm3, (%0, %3) \n \t "
: : " r " ( p ) , " r " ( pix ) , " r " ( line_size ) , " r " ( line_size * 3 )
: " memory " ) ;
pix = pix + line_size * 4 ;
p = p + line_size * 4 ;
}
while ( dh - - ) {
__asm __volatile (
" movq %1, %%mm0 \n \t "
" movq %%mm0, %0 \n \t "
: " =m " ( * p )
: " m " ( * pix )
: " memory " ) ;
pix = pix + line_size ;
p = p + line_size ;
pix + = line_size * 4 ;
p + = line_size * 4 ;
hh - - ;
}
# endif
}
static void put_pixels_x2_mmx ( UINT8 * block , const UINT8 * pixels , int line_size , int h )
@ -216,10 +279,9 @@ static void put_pixels_x2_mmx(UINT8 *block, const UINT8 *pixels, int line_size,
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile (
" pxor %%mm7, %%mm7 \n \t "
" movq %0, %%mm4 \n \t "
: : " m " ( mm_wone ) ) ;
MOVQ_ZERO ( mm7 ) ;
MOVQ_WONE ( mm4 ) ;
JUMPALIGN ( ) ;
do {
__asm __volatile (
" movq %1, %%mm0 \n \t "
@ -251,10 +313,9 @@ static void put_pixels_y2_mmx(UINT8 *block, const UINT8 *pixels, int line_size,
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile (
" pxor %%mm7, %%mm7 \n \t "
" movq %0, %%mm4 \n \t "
: : " m " ( mm_wone ) ) ;
MOVQ_ZERO ( mm7 ) ;
MOVQ_WONE ( mm4 ) ;
JUMPALIGN ( ) ;
do {
__asm __volatile (
" movq %1, %%mm0 \n \t "
@ -287,11 +348,10 @@ static void put_pixels_xy2_mmx(UINT8 *block, const UINT8 *pixels, int line_size,
UINT8 * p ;
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile (
" pxor %%mm7, %%mm7 \n \t "
" movq %0, %%mm6 \n \t "
: : " m " ( mm_wtwo ) ) ;
pix = pixels ; // 1s
MOVQ_ZERO ( mm7 ) ;
MOVQ_WTWO ( mm6 ) ;
JUMPALIGN ( ) ;
do {
__asm __volatile (
" movq %1, %%mm0 \n \t "
@ -337,7 +397,7 @@ static void put_no_rnd_pixels_x2_mmx( UINT8 *block, const UINT8 *pixels, int
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile ( " pxor %%mm7, %%mm7 \n \t " : ) ;
MOVQ_ZERO ( mm7 ) ;
do {
__asm __volatile (
" movq %1, %%mm0 \n \t "
@ -368,7 +428,8 @@ static void put_no_rnd_pixels_y2_mmx( UINT8 *block, const UINT8 *pixels, int li
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile ( " pxor %%mm7, %%mm7 \n \t " : ) ;
MOVQ_ZERO ( mm7 ) ;
JUMPALIGN ( ) ;
do {
__asm __volatile (
" movq %1, %%mm0 \n \t "
@ -400,10 +461,9 @@ static void put_no_rnd_pixels_xy2_mmx( UINT8 *block, const UINT8 *pixels, int
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile (
" pxor %%mm7, %%mm7 \n \t "
" movq %0, %%mm6 \n \t "
: : " m " ( mm_wone ) ) ;
MOVQ_ZERO ( mm7 ) ;
MOVQ_WONE ( mm6 ) ;
JUMPALIGN ( ) ;
do {
__asm __volatile (
" movq %1, %%mm0 \n \t "
@ -449,10 +509,9 @@ static void avg_pixels_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile (
" pxor %%mm7, %%mm7 \n \t "
" movq %0, %%mm6 \n \t "
: : " m " ( mm_wone ) ) ;
MOVQ_ZERO ( mm7 ) ;
MOVQ_WONE ( mm6 ) ;
JUMPALIGN ( ) ;
do {
__asm __volatile (
" movq %0, %%mm0 \n \t "
@ -486,10 +545,9 @@ static void avg_pixels_x2_mmx( UINT8 *block, const UINT8 *pixels, int line_si
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile (
" pxor %%mm7, %%mm7 \n \t "
" movq %0, %%mm6 \n \t "
: : " m " ( mm_wone ) ) ;
MOVQ_ZERO ( mm7 ) ;
MOVQ_WONE ( mm6 ) ;
JUMPALIGN ( ) ;
do {
__asm __volatile (
" movq %1, %%mm1 \n \t "
@ -532,10 +590,9 @@ static void avg_pixels_y2_mmx( UINT8 *block, const UINT8 *pixels, int line_si
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile (
" pxor %%mm7, %%mm7 \n \t "
" movq %0, %%mm6 \n \t "
: : " m " ( mm_wone ) ) ;
MOVQ_ZERO ( mm7 ) ;
MOVQ_WONE ( mm6 ) ;
JUMPALIGN ( ) ;
do {
__asm __volatile (
" movq %1, %%mm1 \n \t "
@ -578,10 +635,10 @@ static void avg_pixels_xy2_mmx( UINT8 *block, const UINT8 *pixels, int line_s
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile (
" pxor %%mm7, %%mm7 \n \t "
" movq %0, %%mm6 \n \t "
: : " m " ( mm_wtwo ) ) ;
MOVQ_ZERO ( mm7 ) ;
// this doesn't seem to be used offten - so
// the inside usage of mm_wone is not optimized
MOVQ_WTWO ( mm6 ) ;
do {
__asm __volatile (
" movq %1, %%mm0 \n \t "
@ -638,7 +695,7 @@ static void avg_no_rnd_pixels_mmx( UINT8 *block, const UINT8 *pixels, int line_
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile ( " pxor %%mm7, %%mm7 \n \t " : ) ;
MOVQ_ZERO ( mm7 ) ;
do {
__asm __volatile (
" movq %1, %%mm0 \n \t "
@ -669,8 +726,7 @@ static void avg_no_rnd_pixels_x2_mmx( UINT8 *block, const UINT8 *pixels, int
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile (
" pxor %%mm7, %%mm7 \n \t " : ) ;
MOVQ_ZERO ( mm7 ) ;
do {
__asm __volatile (
" movq %1, %%mm0 \n \t "
@ -709,8 +765,7 @@ static void avg_no_rnd_pixels_y2_mmx( UINT8 *block, const UINT8 *pixels, int
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile (
" pxor %%mm7, %%mm7 \n \t " : ) ;
MOVQ_ZERO ( mm7 ) ;
do {
__asm __volatile (
" movq %1, %%mm0 \n \t "
@ -749,10 +804,9 @@ static void avg_no_rnd_pixels_xy2_mmx( UINT8 *block, const UINT8 *pixels, int
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile (
" pxor %%mm7, %%mm7 \n \t "
" movq %0, %%mm6 \n \t "
: : " m " ( mm_wone ) ) ;
MOVQ_ZERO ( mm7 ) ;
MOVQ_WONE ( mm6 ) ;
JUMPALIGN ( ) ;
do {
__asm __volatile (
" movq %1, %%mm0 \n \t "
@ -806,7 +860,7 @@ static void sub_pixels_mmx( DCTELEM *block, const UINT8 *pixels, int line_size,
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile ( " pxor %%mm7, %%mm7 " : ) ;
MOVQ_ZERO ( mm7 ) ;
do {
__asm __volatile (
" movq %0, %%mm0 \n \t "
@ -833,10 +887,9 @@ static void sub_pixels_x2_mmx( DCTELEM *block, const UINT8 *pixels, int line_si
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile (
" pxor %%mm7, %%mm7 \n \t "
" movq %0, %%mm6 "
: : " m " ( mm_wone ) ) ;
MOVQ_ZERO ( mm7 ) ;
MOVQ_WONE ( mm6 ) ;
JUMPALIGN ( ) ;
do {
__asm __volatile (
" movq %0, %%mm0 \n \t "
@ -873,10 +926,8 @@ static void sub_pixels_y2_mmx( DCTELEM *block, const UINT8 *pixels, int line_si
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile (
" pxor %%mm7, %%mm7 \n \t "
" movq %0, %%mm6 "
: : " m " ( mm_wone ) ) ;
MOVQ_ZERO ( mm7 ) ;
MOVQ_WONE ( mm6 ) ;
do {
__asm __volatile (
" movq %0, %%mm0 \n \t "
@ -913,10 +964,9 @@ static void sub_pixels_xy2_mmx( DCTELEM *block, const UINT8 *pixels, int line
const UINT8 * pix ;
p = block ;
pix = pixels ;
__asm __volatile (
" pxor %%mm7, %%mm7 \n \t "
" movq %0, %%mm6 \n \t "
: : " m " ( mm_wtwo ) ) ;
MOVQ_ZERO ( mm7 ) ;
MOVQ_WTWO ( mm6 ) ;
JUMPALIGN ( ) ;
do {
__asm __volatile (
" movq %1, %%mm0 \n \t "
@ -960,6 +1010,8 @@ static void sub_pixels_xy2_mmx( DCTELEM *block, const UINT8 *pixels, int line
} while ( - - h ) ;
}
static void just_return ( ) { return ; }
void dsputil_init_mmx ( void )
{
mm_flags = mm_support ( ) ;
@ -1053,4 +1105,44 @@ void dsputil_init_mmx(void)
ff_idct = simple_idct_mmx ;
# endif
}
#if 0
// for speed testing
get_pixels = just_return ;
put_pixels_clamped = just_return ;
add_pixels_clamped = just_return ;
pix_abs16x16 = just_return ;
pix_abs16x16_x2 = just_return ;
pix_abs16x16_y2 = just_return ;
pix_abs16x16_xy2 = just_return ;
put_pixels_tab [ 0 ] = just_return ;
put_pixels_tab [ 1 ] = just_return ;
put_pixels_tab [ 2 ] = just_return ;
put_pixels_tab [ 3 ] = just_return ;
put_no_rnd_pixels_tab [ 0 ] = just_return ;
put_no_rnd_pixels_tab [ 1 ] = just_return ;
put_no_rnd_pixels_tab [ 2 ] = just_return ;
put_no_rnd_pixels_tab [ 3 ] = just_return ;
avg_pixels_tab [ 0 ] = just_return ;
avg_pixels_tab [ 1 ] = just_return ;
avg_pixels_tab [ 2 ] = just_return ;
avg_pixels_tab [ 3 ] = just_return ;
avg_no_rnd_pixels_tab [ 0 ] = just_return ;
avg_no_rnd_pixels_tab [ 1 ] = just_return ;
avg_no_rnd_pixels_tab [ 2 ] = just_return ;
avg_no_rnd_pixels_tab [ 3 ] = just_return ;
sub_pixels_tab [ 0 ] = just_return ;
sub_pixels_tab [ 1 ] = just_return ;
sub_pixels_tab [ 2 ] = just_return ;
sub_pixels_tab [ 3 ] = just_return ;
//av_fdct = just_return;
//ff_idct = just_return;
# endif
}