部分GNU代码片 19、快速的memcpy

原创 2008年04月23日 15:32:00
#include <stdio.h>
#include 
<stdlib.h>


/**//* for small memory blocks (<256 bytes) this version is faster */
#define small_memcpy(to,from,n)
...{
register unsigned 
long int dummy;
__asm__ __volatile__(
  
"rep; movsb"
  :
"=&D"(to), "=&S"(from), "=&c"(dummy)
  :
"0" (to), "1" (from),"2" (n)
  : 
"memory");
}



/**//* linux kernel __memcpy (from: /include/asm/string.h) */
static inline void * __memcpy(void * to, const void * from, size_t n)
...{
     
int d0, d1, d2;

     
if ( n < 4 ) ...{
          small_memcpy(to,from,n);
     }

     
else
          __asm__ __volatile__(
                              
"rep ; movsl "
                              
"testb $2,%b4 "
                              
"je 1f "
                              
"movsw "
                              
"1: testb $1,%b4 "
                              
"je 2f "
                              
"movsb "
                              
"2:"
                              : 
"=&c" (d0), "=&D" (d1), "=&S" (d2)
                              :
"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
                              : 
"memory");

     
return(to);
}


#ifdef HAVE_3DNOW
#define EMMS     "femms"
#else
#define EMMS     "emms"
#endif

#ifdef HAVE_MMX2
#define PREFETCH "prefetchnta"
#elif defined ( HAVE_3DNOW )
#define PREFETCH  "prefetch"
#else
#define PREFETCH "/nop"
#endif


#undef MOVNTQ
#ifdef HAVE_MMX2
#define MOVNTQ "movntq"
#else
#define MOVNTQ "movq"
#endif

#undef MIN_LEN
#ifdef HAVE_MMX1
#define MIN_LEN 0x800  /* 2K blocks */
#else
#define MIN_LEN 0x40  /* 64-byte blocks */
#endif


static void * big_memcpy(void *to, const void *from , size_t len) ...{
    
void *retval;
    size_t i;
    retval 
= to;
       
if(len >= MIN_LEN)
    
...{
      register unsigned 
long int delta;
          
/**//* Align destinition to MMREG_SIZE -boundary */
          delta 
= ((unsigned long int)to)&7;
          
if(delta)
      
...{
        delta
=8-delta;
        len 
-= delta;
        small_memcpy(to, from, delta);
      }

      i 
= len >> 6/**//* len/64 */
      len 
&= 63;
        
/**//*
           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.
        
*/

    
for(; i>0; i--)
    
...{
        __asm__ __volatile__ (
            PREFETCH
" 320(%0) "
        
"movq (%0), %%mm0 "
        
"movq 8(%0), %%mm1 "
        
"movq 16(%0), %%mm2 "
        
"movq 24(%0), %%mm3 "
        
"movq 32(%0), %%mm4 "
        
"movq 40(%0), %%mm5 "
        
"movq 48(%0), %%mm6 "
        
"movq 56(%0), %%mm7 "
        MOVNTQ
" %%mm0, (%1) "
        MOVNTQ
" %%mm1, 8(%1) "
        MOVNTQ
" %%mm2, 16(%1) "
        MOVNTQ
" %%mm3, 24(%1) "
        MOVNTQ
" %%mm4, 32(%1) "
        MOVNTQ
" %%mm5, 40(%1) "
        MOVNTQ
" %%mm6, 48(%1) "
        MOVNTQ
" %%mm7, 56(%1) "
        :: 
"r" (from), "r" (to) : "memory");
        ((
const unsigned char *)from)+=64;
        ((unsigned 
char *)to)+=64;
    }

#ifdef HAVE_MMX2
                
/**//* since movntq is weakly-ordered, a "sfence"
         * is needed to become ordered again. 
*/

        __asm__ __volatile__ (
"sfence":::"memory");
#endif
        
/**//* enables to use FPU */
        __asm__ __volatile__ (EMMS:::
"memory");
    }

    
/**//*
     *  Now do the tail of the block
     
*/

    
if(len) small_memcpy(to, from, len);
    
return retval;
}


char src[1270];
char dest[1270];

void init_src()
...{
    
int i;
    
for(i = 0; i < 1260; i++)
        src[i] 
= i+1;
}


void output(int beg, int end)
...{
    
int i;
    
for(i = beg-1; i < end; i++)
        printf(
" %d, ", dest[i]);
    printf(
" ");
}


void test_last16()
...{
//    __memcpy(dest, src, 15);
    big_memcpy(dest, src, 1100);
    output(
11100);
}


int main()
...{
    init_src();

    test_last16();

    
return 0;
}




    

部分GNU代码片 2、read_configfile

//读取配置文件的内容//获取配置文件的参数信息bool read_configfile(        char* configfile, stCFG &ostCFG){    FILE* f;  ...
  • eqxu
  • eqxu
  • 2008年03月16日 22:15
  • 499

部分GNU代码片 18、字符串操作

size_t strlcat(        register char* s, register const char* t, register size_t n){    const char* ...
  • eqxu
  • eqxu
  • 2008年04月22日 21:00
  • 552

部分GNU代码片 1、trim

//去掉前后的空字符void trim_whitespace(        char* str){    //查找前面的空字符    char* p;    int i;    p=str;    ...
  • eqxu
  • eqxu
  • 2008年03月16日 22:14
  • 312

部分GNU代码片 6、split

/***************************************************************************** * @brief 函数find_keywo...
  • eqxu
  • eqxu
  • 2008年03月16日 22:21
  • 570

部分GNU代码片 11、合并文件

//合并文件static inline int Merge(const char* src_filename, const char* dst_filename){    int dst_fd = 0...
  • eqxu
  • eqxu
  • 2008年03月19日 17:37
  • 477

快速存拷贝 fast_memcpy

精确拷贝到字节,三种拷贝方式:1. movsd 2.SSE 系列 + 软预取 3.SSE系列+硬预取方式,要注意的是,不是所有的拷贝SSE都更优,正如为了行进100米,是开飞机还是步行咧?嘿嘿。所以,...
  • G_Spider
  • G_Spider
  • 2010年12月24日 22:35
  • 2766

部分GNU代码片 10、二叉堆(Binary Heap)

n个关键字序列Kl,K2,…,Kn称为堆,当且仅当该序列满足如下性质(简称为堆性质):(1) a[i]≤a[i*2]且a[i]≤a[2*i+1] 或(2)a[i]≥a[i*2]且a[i]≥a[2*i+...
  • eqxu
  • eqxu
  • 2008年03月17日 21:37
  • 672

部分GNU代码片 7、mysql接口

//头文件#ifndef MYSQL_TOOL_H_#define MYSQL_TOOL_H_#include #include #include #include /** * /file Magic...
  • eqxu
  • eqxu
  • 2008年03月16日 22:24
  • 589

部分GNU代码片 3、字符串2二维数组

  /***************************************************************************** * @brief 函数string2I...
  • eqxu
  • eqxu
  • 2008年03月16日 22:16
  • 457

部分GNU代码片 4、折半查找算法

//折半查找算法 /***************************************************************************** * @brief 函数b...
  • eqxu
  • eqxu
  • 2008年03月16日 22:18
  • 510
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:部分GNU代码片 19、快速的memcpy
举报原因:
原因补充:

(最多只允许输入30个字)