[Mplayer-cvslog] CVS: main/libvo fastmemcpy.h,1.12,1.13

Nick Kurshev nickols_k at users.sourceforge.net
Sat May 5 15:30:02 CEST 2001


Update of /cvsroot/mplayer/main/libvo
In directory usw-pr-cvs1:/tmp/cvs-serv21992/main/libvo

Modified Files:
	fastmemcpy.h 
Log Message:
Moving fast_memcpy to separate file (Size optimization)

Index: fastmemcpy.h
===================================================================
RCS file: /cvsroot/mplayer/main/libvo/fastmemcpy.h,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -r1.12 -r1.13
*** fastmemcpy.h	2001/05/02 00:29:16	1.12
--- fastmemcpy.h	2001/05/05 13:30:00	1.13
***************
*** 2,241 ****
  #define __MPLAYER_MEMCPY 1
  
- #ifdef USE_FASTMEMCPY
- #include <stddef.h>
- 
- // Enable this code, if SSE version works (faster) for you!
- #if 0
- #ifdef HAVE_SSE
- #define FASTMEMCPY_SSE
- #endif
- #endif
- 
- /*
-  This part of code was taken by from Linux-2.4.3 and slightly modified
- for MMX, MMX2, SSE instruction set. I have done it since linux uses page aligned
- blocks but mplayer uses weakly ordered data and original sources can not
- speedup them. Only using PREFETCHNTA and MOVNTQ together have effect!
- 
- >From IA-32 Intel Architecture Software Developer's Manual Volume 1,
- 
- Order Number 245470:
- "10.4.6. Cacheability Control, Prefetch, and Memory Ordering Instructions"
- 
- Data referenced by a program can be temporal (data will be used again) or
- non-temporal (data will be referenced once and not reused in the immediate
- future). To make efficient use of the processor's caches, it is generally
- desirable to cache temporal data and not cache non-temporal data. Overloading
- the processor's caches with non-temporal data is sometimes referred to as
- "polluting the caches".
- The non-temporal data is written to memory with Write-Combining semantics.
- 
- The PREFETCHh instructions permits a program to load data into the processor
- at a suggested cache level, so that it is closer to the processors load and
- store unit when it is needed. If the data is already present in a level of
- the cache hierarchy that is closer to the processor, the PREFETCHh instruction
- will not result in any data movement.
- But we should you PREFETCHNTA: Non-temporal data fetch data into location
- close to the processor, minimizing cache pollution.
- 
- The MOVNTQ (store quadword using non-temporal hint) instruction stores
- packed integer data from an MMX register to memory, using a non-temporal hint.
- The MOVNTPS (store packed single-precision floating-point values using
- non-temporal hint) instruction stores packed floating-point data from an
- XMM register to memory, using a non-temporal hint.
- 
- The SFENCE (Store Fence) instruction controls write ordering by creating a
- fence for memory store operations. This instruction guarantees that the results
- of every store instruction that precedes the store fence in program order is
- globally visible before any store instruction that follows the fence. The
- SFENCE instruction provides an efficient way of ensuring ordering between
- procedures that produce weakly-ordered data and procedures that consume that
- data.
- 
- If you have questions please contact with me: Nick Kurshev: nickols_k at mail.ru.
- */
- 
- // 3dnow memcpy support from kernel 2.4.2
- //  by Pontscho/fresh!mindworkz
- 
  #if defined( HAVE_MMX2 ) || defined( HAVE_3DNOW ) || defined( HAVE_MMX )
! 
! #undef HAVE_MMX1
! #if defined(HAVE_MMX) && !defined(HAVE_MMX2) && !defined(HAVE_3DNOW) && !defined(FASTMEMCPY_SSE)
! /*  means: mmx v.1. Note: Since we added alignment of destinition it speedups
!     of memory copying on PentMMX, Celeron-1 and P2 upto 12% versus
!     standard (non MMX-optimized) version.
!     Note: on K6-2+ it speedups memory copying upto 25% and
!           on K7 and P3 about 500% (5 times). */
! #define HAVE_MMX1
! #endif
! 
! 
! #undef HAVE_K6_2PLUS
! #if !defined( HAVE_MMX2) && defined( HAVE_3DNOW)
! #define HAVE_K6_2PLUS
! #endif
! 
! /* for small memory blocks (<256 bytes) this version is faster */
! #define small_memcpy(to,from,n)\
! {\
! __asm__ __volatile__(\
!         "rep; movsb"\
!         :"=D"(to), "=S"(from), "=c"(n)\
! /* It's most portable way to notify compiler */\
! /* that edi, esi and ecx are clobbered in asm block. */\
! /* Thanks to A'rpi for hint!!! */\
!         :"0" (to), "1" (from),"2" (n)\
!         : "memory");\
! }
! 
! #ifdef FASTMEMCPY_SSE
! #define MMREG_SIZE 16
! #else
! #define MMREG_SIZE 8
! #endif
! 
! /* Small defines (for readability only) ;) */
! #ifdef HAVE_K6_2PLUS
! #define PREFETCH "prefetch"
! /* On K6 femms is faster of emms. On K7 femms is directly mapped on emms. */
! #define EMMS     "femms"
! #else
! #define PREFETCH "prefetchnta"
! #define EMMS     "emms"
! #endif
! 
! #ifdef HAVE_MMX2
! #define MOVNTQ "movntq"
! #else
! #define MOVNTQ "movq"
! #endif
! 
! inline static void * fast_memcpy(void * to, const void * from, size_t len)
! {
!          void *retval;
!          int i;
!          retval = to;
!         if(len >= 0x200) /* 512-byte blocks */
!          {
!           register unsigned long int delta;
!           /* Align destinition to MMREG_SIZE -boundary */
!           delta = ((unsigned long int)to)&(MMREG_SIZE-1);
!           if(delta)
!           {
!             delta=MMREG_SIZE-delta;
!             len -= delta;
!             small_memcpy(to, from, delta);
!           }
!           i = len >> 6; /* len/64 */
!           len&=63;
  
! #ifndef HAVE_MMX1
!          __asm__ __volatile__ (
!                 PREFETCH" (%0)\n"
!                 PREFETCH" 64(%0)\n"
!                 PREFETCH" 128(%0)\n"
!                 PREFETCH" 192(%0)\n"
!                 PREFETCH" 256(%0)\n"
!                 : : "r" (from) );
! #endif
!         /*
!            This algorithm is top effective when the code consequently
!            reads and writes blocks which have size of cache line.
!            Size of cache line is processor-dependent.
!            It will, however, be a minimum of 32 bytes on any processors.
!            It would be better to have a number of instructions which
!            perform reading and writing to be multiple to a number of
!            processor's decoders, but it's not always possible.
!         */
! #ifdef FASTMEMCPY_SSE /* Only P3 (may be Cyrix3) */
!          if(((unsigned long)from) & 15)
!          /* if SRC is misaligned */
!          for(; i>0; i--)
!          {
!                  __asm__ __volatile__ (
!                  PREFETCH" 320(%0)\n"
!                  "movups (%0), %%xmm0\n"
!                  "movups 16(%0), %%xmm1\n"
!                  "movntps %%xmm0, (%1)\n"
!                  "movntps %%xmm1, 16(%1)\n"
!                  "movups 32(%0), %%xmm0\n"
!                  "movups 48(%0), %%xmm1\n"
!                  "movntps %%xmm0, 32(%1)\n"
!                  "movntps %%xmm1, 48(%1)\n"
!                  :: "r" (from), "r" (to) : "memory");
!                  ((const unsigned char *)from)+=64;
!                  ((unsigned char *)to)+=64;
!          }
!          else
!          /*
!            Only if SRC is aligned on 16-byte boundary.
!            It allows to use movaps instead of movups, which required data
!            to be aligned or a general-protection exception (#GP) is generated.
!          */
!          for(; i>0; i--)
!          {
!                  __asm__ __volatile__ (
!                  PREFETCH" 320(%0)\n"
!                  "movaps (%0), %%xmm0\n"
!                  "movaps 16(%0), %%xmm1\n"
!                  "movntps %%xmm0, (%1)\n"
!                  "movntps %%xmm1, 16(%1)\n"
!                  "movaps 32(%0), %%xmm0\n"
!                  "movaps 48(%0), %%xmm1\n"
!                  "movntps %%xmm0, 32(%1)\n"
!                  "movntps %%xmm1, 48(%1)\n"
!                  :: "r" (from), "r" (to) : "memory");
!                  ((const unsigned char *)from)+=64;
!                  ((unsigned char *)to)+=64;
!          }
! #else
!          for(; i>0; i--)
!          {
!                  __asm__ __volatile__ (
! #ifndef HAVE_MMX1
!                  PREFETCH" 320(%0)\n"
! #endif
!                  "movq (%0), %%mm0\n"
!                  "movq 8(%0), %%mm1\n"
!                  "movq 16(%0), %%mm2\n"
!                  "movq 24(%0), %%mm3\n"
!                  MOVNTQ" %%mm0, (%1)\n"
!                  MOVNTQ" %%mm1, 8(%1)\n"
!                  MOVNTQ" %%mm2, 16(%1)\n"
!                  MOVNTQ" %%mm3, 24(%1)\n"
!                  "movq 32(%0), %%mm0\n"
!                  "movq 40(%0), %%mm1\n"
!                  "movq 48(%0), %%mm2\n"
!                  "movq 56(%0), %%mm3\n"
!                  MOVNTQ" %%mm0, 32(%1)\n"
!                  MOVNTQ" %%mm1, 40(%1)\n"
!                  MOVNTQ" %%mm2, 48(%1)\n"
!                  MOVNTQ" %%mm3, 56(%1)\n"
!                  :: "r" (from), "r" (to) : "memory");
!                  ((const unsigned char *)from)+=64;
!                  ((unsigned char *)to)+=64;
!          }
! #endif /* Have SSE */
! #ifdef HAVE_MMX2
!                 /* since movntq is weakly-ordered, a "sfence"
!                  * is needed to become ordered again. */
!                  __asm__ __volatile__ ("sfence":::"memory");
! #endif
! #ifndef FASTMEMCPY_SSE
!                  /* enables to use FPU */
!                  __asm__ __volatile__ (EMMS:::"memory");
! #endif
!          }
!          /*
!          *      Now do the tail of the block
!          */
!          if(len) small_memcpy(to, from, len);
!          return retval;
! }
  #define memcpy(a,b,c) fast_memcpy(a,b,c)
- #undef small_memcpy
- 
- #endif
  
  #endif
--- 2,10 ----
  #define __MPLAYER_MEMCPY 1
  
  #if defined( HAVE_MMX2 ) || defined( HAVE_3DNOW ) || defined( HAVE_MMX )
! #include <stddef.h>
  
! extern void * fast_memcpy(void * to, const void * from, size_t len);
  #define memcpy(a,b,c) fast_memcpy(a,b,c)
  
  #endif


_______________________________________________
Mplayer-cvslog mailing list
Mplayer-cvslog at lists.sourceforge.net
http://lists.sourceforge.net/lists/listinfo/mplayer-cvslog



More information about the MPlayer-cvslog mailing list