* some modifications to allow gcc to compile same code for -fPIC

- introduced MOVQ_WONE, MOVQ_WTWO
* unrolled put_pixels_clamped_mmx
* added .baling where the jump address would be compiled on odd address
* added some testing code to disable all these routines (for time measurement)

Originally committed as revision 308 to svn://svn.ffmpeg.org/ffmpeg/trunk
pull/126/head
Zdenek Kabelac 23 years ago
parent 38d171ebbe
commit d6a4c0b111
  1. 252
      libavcodec/i386/dsputil_mmx.c

@ -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_wone[4] __attribute__ ((aligned(8))) = { 0x1, 0x1, 0x1, 0x1 };
//static const unsigned short mm_wtwo[4] __attribute__ ((aligned(8))) = { 0x2, 0x2, 0x2, 0x2 }; //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 */ /* 3Dnow specific */
@ -77,7 +98,7 @@ static void get_pixels_mmx(DCTELEM *block, const UINT8 *pixels, int line_size)
/* read the pixels */ /* read the pixels */
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile("pxor %%mm7, %%mm7":); MOVQ_ZERO(mm7);
for(i=0;i<4;i++) { for(i=0;i<4;i++) {
__asm __volatile( __asm __volatile(
"movq %1, %%mm0\n\t" "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; const DCTELEM *p;
UINT8 *pix; UINT8 *pix;
int i;
/* read the pixels */ /* read the pixels */
p = block; p = block;
pix = pixels; pix = pixels;
for(i=0;i<2;i++) { /* unrolled loop */
__asm __volatile( __asm __volatile(
"movq %3, %%mm0\n\t" "movq %3, %%mm0\n\t"
"movq 8%3, %%mm1\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"); :"memory");
pix += line_size*4; pix += line_size*4;
p += 32; 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) 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 */ /* read the pixels */
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile("pxor %%mm7, %%mm7":); MOVQ_ZERO(mm7);
for(i=0;i<4;i++) { i = 4;
while (i) {
__asm __volatile( __asm __volatile(
"movq %2, %%mm0\n\t" "movq %2, %%mm0\n\t"
"movq 8%2, %%mm1\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"); :"memory");
pix += line_size*2; pix += line_size*2;
p += 16; p += 16;
} i--;
};
} }
static void put_pixels_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int h) static void put_pixels_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int h)
{ {
int dh, hh; int hh;
UINT8 *p; UINT8 *p;
const UINT8 *pix; const UINT8 *pix;
p = block; 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; hh=h>>2;
dh=h&3; while (hh) {
while(hh--) {
__asm __volatile( __asm __volatile(
"movq (%1), %%mm0 \n\t" "movq (%1), %%mm0 \n\t"
"movq (%1, %2), %%mm1 \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" "movq %%mm3, (%0, %3) \n\t"
::"r"(p), "r"(pix), "r"(line_size), "r"(line_size*3) ::"r"(p), "r"(pix), "r"(line_size), "r"(line_size*3)
:"memory"); :"memory");
pix = pix + line_size*4; pix += line_size*4;
p = p + line_size*4; p += line_size*4;
} hh--;
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;
} }
#endif
} }
static void put_pixels_x2_mmx(UINT8 *block, const UINT8 *pixels, int line_size, int h) 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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile( MOVQ_ZERO(mm7);
"pxor %%mm7, %%mm7\n\t" MOVQ_WONE(mm4);
"movq %0, %%mm4\n\t" JUMPALIGN();
::"m"(mm_wone));
do { do {
__asm __volatile( __asm __volatile(
"movq %1, %%mm0\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile( MOVQ_ZERO(mm7);
"pxor %%mm7, %%mm7\n\t" MOVQ_WONE(mm4);
"movq %0, %%mm4\n\t" JUMPALIGN();
::"m"(mm_wone));
do { do {
__asm __volatile( __asm __volatile(
"movq %1, %%mm0\n\t" "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; UINT8 *p;
const UINT8 *pix; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels; // 1s
__asm __volatile( MOVQ_ZERO(mm7);
"pxor %%mm7, %%mm7\n\t" MOVQ_WTWO(mm6);
"movq %0, %%mm6\n\t" JUMPALIGN();
::"m"(mm_wtwo));
do { do {
__asm __volatile( __asm __volatile(
"movq %1, %%mm0\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile("pxor %%mm7, %%mm7\n\t":); MOVQ_ZERO(mm7);
do { do {
__asm __volatile( __asm __volatile(
"movq %1, %%mm0\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile("pxor %%mm7, %%mm7\n\t":); MOVQ_ZERO(mm7);
JUMPALIGN();
do { do {
__asm __volatile( __asm __volatile(
"movq %1, %%mm0\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile( MOVQ_ZERO(mm7);
"pxor %%mm7, %%mm7\n\t" MOVQ_WONE(mm6);
"movq %0, %%mm6\n\t" JUMPALIGN();
::"m"(mm_wone));
do { do {
__asm __volatile( __asm __volatile(
"movq %1, %%mm0\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile( MOVQ_ZERO(mm7);
"pxor %%mm7, %%mm7\n\t" MOVQ_WONE(mm6);
"movq %0, %%mm6\n\t" JUMPALIGN();
::"m"(mm_wone));
do { do {
__asm __volatile( __asm __volatile(
"movq %0, %%mm0\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile( MOVQ_ZERO(mm7);
"pxor %%mm7, %%mm7\n\t" MOVQ_WONE(mm6);
"movq %0, %%mm6\n\t" JUMPALIGN();
::"m"(mm_wone));
do { do {
__asm __volatile( __asm __volatile(
"movq %1, %%mm1\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile( MOVQ_ZERO(mm7);
"pxor %%mm7, %%mm7\n\t" MOVQ_WONE(mm6);
"movq %0, %%mm6\n\t" JUMPALIGN();
::"m"(mm_wone));
do { do {
__asm __volatile( __asm __volatile(
"movq %1, %%mm1\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile( MOVQ_ZERO(mm7);
"pxor %%mm7, %%mm7\n\t" // this doesn't seem to be used offten - so
"movq %0, %%mm6\n\t" // the inside usage of mm_wone is not optimized
::"m"(mm_wtwo)); MOVQ_WTWO(mm6);
do { do {
__asm __volatile( __asm __volatile(
"movq %1, %%mm0\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile("pxor %%mm7, %%mm7\n\t":); MOVQ_ZERO(mm7);
do { do {
__asm __volatile( __asm __volatile(
"movq %1, %%mm0\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile( MOVQ_ZERO(mm7);
"pxor %%mm7, %%mm7\n\t":);
do { do {
__asm __volatile( __asm __volatile(
"movq %1, %%mm0\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile( MOVQ_ZERO(mm7);
"pxor %%mm7, %%mm7\n\t":);
do { do {
__asm __volatile( __asm __volatile(
"movq %1, %%mm0\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile( MOVQ_ZERO(mm7);
"pxor %%mm7, %%mm7\n\t" MOVQ_WONE(mm6);
"movq %0, %%mm6\n\t" JUMPALIGN();
::"m"(mm_wone));
do { do {
__asm __volatile( __asm __volatile(
"movq %1, %%mm0\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile("pxor %%mm7, %%mm7":); MOVQ_ZERO(mm7);
do { do {
__asm __volatile( __asm __volatile(
"movq %0, %%mm0\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile( MOVQ_ZERO(mm7);
"pxor %%mm7, %%mm7\n\t" MOVQ_WONE(mm6);
"movq %0, %%mm6" JUMPALIGN();
::"m"(mm_wone));
do { do {
__asm __volatile( __asm __volatile(
"movq %0, %%mm0\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile( MOVQ_ZERO(mm7);
"pxor %%mm7, %%mm7\n\t" MOVQ_WONE(mm6);
"movq %0, %%mm6"
::"m"(mm_wone));
do { do {
__asm __volatile( __asm __volatile(
"movq %0, %%mm0\n\t" "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; const UINT8 *pix;
p = block; p = block;
pix = pixels; pix = pixels;
__asm __volatile( MOVQ_ZERO(mm7);
"pxor %%mm7, %%mm7\n\t" MOVQ_WTWO(mm6);
"movq %0, %%mm6\n\t" JUMPALIGN();
::"m"(mm_wtwo));
do { do {
__asm __volatile( __asm __volatile(
"movq %1, %%mm0\n\t" "movq %1, %%mm0\n\t"
@ -960,6 +1010,8 @@ static void sub_pixels_xy2_mmx( DCTELEM *block, const UINT8 *pixels, int line
} while(--h); } while(--h);
} }
static void just_return() { return; }
void dsputil_init_mmx(void) void dsputil_init_mmx(void)
{ {
mm_flags = mm_support(); mm_flags = mm_support();
@ -1053,4 +1105,44 @@ void dsputil_init_mmx(void)
ff_idct = simple_idct_mmx; ff_idct = simple_idct_mmx;
#endif #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
} }

Loading…
Cancel
Save