1 /*
2     TiMidity++ -- MIDI to WAVE converter and player
3     Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4     Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20 
21 #ifdef HAVE_CONFIG_H
22 #  include "config.h"
23 #endif
24 
25 #ifdef STDC_HEADERS
26 #  include <string.h>
27 #elif HAVE_STRINGS_H
28 #  include <strings.h>
29 #endif /* stdc */
30 
31 #include "timidity.h"
32 
33 #if USE_ALTIVEC
34 #define sizeof_vector 16
35 
36 /* vector version of memset(). */
v_memset(void * destp,int c,size_t len)37 void v_memset(void* destp, int c, size_t len)
38 {
39     register int32 dest = (int)destp;
40 
41     /* If it's worth using altivec code */
42     if( len >= 2*sizeof_vector ) { /* 32 byte */
43         int i,xlen;
44 	int cccc[4] = { c, c, c, c, };
45         vint32* destv;
46 	vint32  pat = *(vint32*) cccc;
47 
48 	/* first, write things to word boundary. */
49 	if(( xlen = (int)dest % sizeof_vector ) != 0) {
50 	    libc_memset(destp,c,xlen);
51 	    len  -= xlen;
52 	    dest += xlen;
53 	}
54 
55 	/* this is the maion loop. */
56 	destv = (vint32*) dest;
57 	for( i = 0; i < len / sizeof_vector; i++ ) {
58   	    destv[i] = pat;
59 	}
60 	dest += i * sizeof_vector;
61 	len %= sizeof_vector;
62     }
63 
64     /* write remaining few bytes. */
65     libc_memset((void*)dest,0,len);
66 }
67 
68 /* a bit faster version. */
69 static vint32 vzero = (vint32)(0);
v_memzero(void * destp,size_t len)70 void v_memzero(void* destp, size_t len)
71 {
72     register int32 dest = (int)destp;
73 
74     /* If it's worth using altivec code */
75     if( len >= 2*sizeof_vector ) { /* 32 byte */
76         int i,xlen;
77         vint32* destv;
78 
79 	/* first, write things to word boundary. */
80 	if(( xlen = (int)dest % sizeof_vector ) != 0) {
81 	    libc_memset(destp,0,xlen);
82 	    len  -= xlen;
83 	    dest += xlen;
84 	}
85 
86 	/* this is the maion loop. */
87 	destv = (vint32*) dest;
88 	for( i = 0; i < len / sizeof_vector; i++ ) {
89   	    destv[i] = vzero;
90 	}
91 	dest += i * sizeof_vector;
92 	len %= sizeof_vector;
93     }
94 
95     /* write remaining few bytes. */
96     libc_memset((void*)dest,0,len);
97 }
98 
99 
100 /* this is an alternate version of set_dry_signal() in reverb.c */
v_set_dry_signal(void * destp,const int32 * buf,int32 n)101 void v_set_dry_signal(void* destp, const int32* buf, int32 n)
102 {
103     int i = 0;
104     if( n>=8 ) {
105         vint32* dest = (vint32*) destp;
106 	for( ; i < n / 4; i++) {
107             dest[i] = vec_add(dest[i],((vint32*) buf)[i]);
108 	}
109     }
110     /* write remaining few bytes. */
111     for( i *= 4; i < n; i++) {
112         ((int32*) destp)[i] += buf[i];
113     }
114 }
115 #endif /* USE_ALTIVEC */
116 
117 #if ( defined(__BORLANDC__) && (__BORLANDC__ >= 1380) )
imuldiv8(int32 a,int32 b)118 int32 imuldiv8(int32 a, int32 b) {
119 	_asm {
120 		mov eax, a
121 		mov edx, b
122 		imul edx
123 		shr eax, 8
124 		shl edx, 24
125 		or  eax, edx
126 	}
127 }
128 
imuldiv16(int32 a,int32 b)129 int32 imuldiv16(int32 a, int32 b) {
130 	_asm {
131 		mov eax, a
132 		mov edx, b
133 		imul edx
134 		shr eax, 16
135 		shl edx, 16
136 		or  eax, edx
137 	}
138 }
139 
imuldiv24(int32 a,int32 b)140 int32 imuldiv24(int32 a, int32 b) {
141 	_asm {
142 		mov eax, a
143 		mov edx, b
144 		imul edx
145 		shr eax, 24
146 		shl edx, 8
147 		or  eax, edx
148 	}
149 }
150 
imuldiv28(int32 a,int32 b)151 int32 imuldiv28(int32 a, int32 b) {
152 	_asm {
153 		mov eax, a
154 		mov edx, b
155 		imul edx
156 		shr eax, 28
157 		shl edx, 4
158 		or  eax, edx
159 	}
160 }
161 #endif
162