]> git.sesse.net Git - vlc/blob - modules/misc/memcpy/memcpyaltivec.c
Use <vlc_cpu.h>
[vlc] / modules / misc / memcpy / memcpyaltivec.c
1 /*****************************************************************************
2  * memcpyaltivec.c : AltiVec memcpy module
3  *****************************************************************************
4  * Copyright (C) 2001 the VideoLAN team
5  * $Id$
6  *
7  * Author: Christophe Massiot <massiot@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #ifndef __BUILD_ALTIVEC_ASM__
25
26 /*****************************************************************************
27  * Preamble
28  *****************************************************************************/
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <vlc_common.h>
35 #include <vlc_plugin.h>
36 #include <vlc_cpu.h>
37
38 #ifdef HAVE_ALTIVEC_H
39 #   include <altivec.h>
40 #endif
41
42 /*****************************************************************************
43  * Local prototypes.
44  *****************************************************************************/
45 static void * fast_memcpy ( void * to, const void * from, size_t len );
46
47 /*****************************************************************************
48  * Module initializer.
49  *****************************************************************************/
50 static int Activate ( vlc_object_t *p_this )
51 {
52     VLC_UNUSED(p_this);
53     vlc_fastmem_register( fast_memcpy, NULL );
54     return VLC_SUCCESS;
55 }
56
57 /*****************************************************************************
58  * Module descriptor.
59  *****************************************************************************/
60 vlc_module_begin ()
61     set_description( N_("AltiVec memcpy") )
62     set_category( CAT_ADVANCED )
63     set_subcategory( SUBCAT_ADVANCED_MISC )
64     add_requirement( ALTIVEC )
65     set_capability( "memcpy", 100 )
66     set_callbacks( Activate, NULL )
67     add_shortcut( "altivec" )
68 vlc_module_end ()
69
70 #else
71 typedef unsigned long size_t;
72 #endif /* __BUILD_ALTIVEC_ASM__ */
73
74 #if defined(CAN_COMPILE_C_ALTIVEC) || defined( __BUILD_ALTIVEC_ASM__ )
75
76 #define vector_s16_t vector signed short
77 #define vector_u16_t vector unsigned short
78 #define vector_s8_t vector signed char
79 #define vector_u8_t vector unsigned char
80 #define vector_s32_t vector signed int
81 #define vector_u32_t vector unsigned int
82 #define MMREG_SIZE 16
83
84 #define SMALL_MEMCPY(to, from, len)                                         \
85 {                                                                           \
86     unsigned char * end = to + len;                                         \
87     while( to < end )                                                       \
88     {                                                                       \
89         *to++ = *from++;                                                    \
90     }                                                                       \
91 }
92
93 static void * fast_memcpy( void * _to, const void * _from, size_t len )
94 {
95     void * retval = _to;
96     unsigned char * to = (unsigned char *)_to;
97     unsigned char * from = (unsigned char *)_from;
98
99     if( len > 16 )
100     {
101         /* Align destination to MMREG_SIZE -boundary */
102         register unsigned long int delta;
103
104         delta = ((unsigned long)to)&(MMREG_SIZE-1);
105         if( delta )
106         {
107             delta = MMREG_SIZE - delta;
108             len -= delta;
109             SMALL_MEMCPY(to, from, delta);
110         }
111
112         if( len & ~(MMREG_SIZE-1) )
113         {
114             vector_u8_t perm, ref0, ref1, tmp;
115
116             perm = vec_lvsl( 0, from );
117             ref0 = vec_ld( 0, from );
118             ref1 = vec_ld( 15, from );
119             from += 16;
120             len -= 16;
121             tmp = vec_perm( ref0, ref1, perm );
122             while( len & ~(MMREG_SIZE-1) )
123             {
124                 ref0 = vec_ld( 0, from );
125                 ref1 = vec_ld( 15, from );
126                 from += 16;
127                 len -= 16;
128                 vec_st( tmp, 0, to );
129                 tmp = vec_perm( ref0, ref1, perm );
130                 to += 16;
131             }
132             vec_st( tmp, 0, to );
133             to += 16;
134         }
135     }
136
137     if( len )
138     {
139         SMALL_MEMCPY( to, from, len );
140     }
141
142     return retval;
143 }
144
145 #endif
146
147 #if !defined(CAN_COMPILE_C_ALTIVEC) && !defined(__BUILD_ALTIVEC_ASM__)
148
149 /*
150  * The asm code is generated with:
151  *
152  * gcc-2.95 -fvec -D__BUILD_ALTIVEC_ASM__ -O9 -fomit-frame-pointer -mregnames -S *      memcpyaltivec.c
153  *
154  * sed 's/.L/._L/g' memcpyaltivec.s |
155  * awk '{args=""; len=split ($2, arg, ",");
156  *      for (i=1; i<=len; i++) { a=arg[i]; if (i<len) a=a",";
157  *                               args = args sprintf ("%-6s", a) }
158  *      printf ("\t\"\t%-16s%-24s\\n\"\n", $1, args) }' |
159  * unexpand -a
160  */
161
162 static void * fast_memcpy( void * _to, const void * _from, size_t len )
163 {
164     asm ("                                              \n"
165     "    cmplwi        %cr0, %r5,  16        \n"
166     "    mr        %r9,  %r3        \n"
167     "    bc        4,    1,    ._L3    \n"
168     "    andi.        %r0,  %r3,  15        \n"
169     "    bc        12,   2,    ._L4    \n"
170     "    subfic        %r0,  %r0,  16        \n"
171     "    add        %r11, %r3,  %r0        \n"
172     "    cmplw        %cr0, %r3,  %r11    \n"
173     "    subf        %r5,  %r0,  %r5        \n"
174     "    bc        4,    0,    ._L4    \n"
175     "    ._L7:                    \n"
176     "    lbz        %r0,  0(%r4)        \n"
177     "    stb        %r0,  0(%r9)        \n"
178     "    addi        %r9,  %r9,  1        \n"
179     "    cmplw        %cr0, %r9,  %r11    \n"
180     "    addi        %r4,  %r4,  1        \n"
181     "    bc        12,   0,    ._L7    \n"
182     "    ._L4:                    \n"
183     "    rlwinm.        %r0,  %r5,  0,      0,    27    \n"
184     "    bc        12,   2,    ._L3    \n"
185     "    addi        %r5,  %r5,  -16        \n"
186     "    li        %r11, 15        \n"
187     "    lvsl        %v12, 0,    %r4        \n"
188     "    lvx        %v1,  0,    %r4        \n"
189     "    lvx        %v0,  %r11, %r4        \n"
190     "    rlwinm.        %r0,  %r5,  0,      0,    27    \n"
191     "    vperm        %v13, %v1,  %v0,  %v12    \n"
192     "    addi        %r4,  %r4,  16        \n"
193     "    bc        12,   2,    ._L11    \n"
194     "    ._L12:                    \n"
195     "    addi        %r5,  %r5,  -16        \n"
196     "    li        %r11, 15        \n"
197     "    lvx        %v1,  0,    %r4        \n"
198     "    lvx        %v0,  %r11, %r4        \n"
199     "    rlwinm.        %r0,  %r5,  0,      0,    27    \n"
200     "    stvx        %v13, 0,    %r9        \n"
201     "    vperm        %v13, %v1,  %v0,  %v12    \n"
202     "    addi        %r4,  %r4,  16        \n"
203     "    addi        %r9,  %r9,  16        \n"
204     "    bc        4,    2,    ._L12    \n"
205     "    ._L11:                    \n"
206     "    stvx        %v13, 0,    %r9        \n"
207     "    addi        %r9,  %r9,  16        \n"
208     "    ._L3:                    \n"
209     "    cmpwi        %cr0, %r5,  0        \n"
210     "    bclr        12,   2            \n"
211     "    add        %r5,  %r9,  %r5        \n"
212     "    cmplw        %cr0, %r9,  %r5        \n"
213     "    bclr        4,    0            \n"
214     "    ._L17:                    \n"
215     "    lbz        %r0,  0(%r4)        \n"
216     "    stb        %r0,  0(%r9)        \n"
217     "    addi        %r9,  %r9,  1        \n"
218     "    cmplw        %cr0, %r9,  %r5        \n"
219     "    addi        %r4,  %r4,  1        \n"
220     "    bc        12,   0,    ._L17    \n"
221         );
222 }
223
224 #endif