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