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 #ifndef OPTCODE_H_INCLUDED
22 #define OPTCODE_H_INCLUDED 1
23 
24 /* optimizing mode */
25 /* 0: none         */
26 /* 1: x86 asm      */
27 #define OPT_MODE 1
28 
29 /* PowerPC's AltiVec enhancement */
30 /* 0: none                       */
31 /* 1: use altivec                */
32 /*    (need -faltivec option)    */
33 #ifndef USE_ALTIVEC
34 #define USE_ALTIVEC 0
35 #endif
36 
37 /*****************************************************************************/
38 
39 #ifdef HAVE_SYS_PARAM_H
40 #include <sys/param.h>
41 #endif/* <sys/param.h> */
42 #ifdef HAVE_SYS_SYSCTL_H
43 #include <sys/sysctl.h>
44 #endif/* <sys/sysctl.h> */
45 #ifdef STDC_HEADERS
46 #include <string.h>
47 #elif HAVE_STRINGS_H
48 #include <strings.h>
49 #endif/* <string.h> */
50 
51 #if __STDC_VERSION__ == 199901L
52 # include <stdbool.h>
53 #endif
54 
55 /*****************************************************************************/
56 #if OPT_MODE == 1
57 
58 #ifdef LITTLE_ENDIAN
59 #define iman_ 0
60 #else
61 #define iman_ 1
62 #endif
63 #define _double2fixmagic 68719476736.0 * 1.5
64 
65 #if defined(__GNUC__) && defined(__i386__)
imuldiv8(int32 a,int32 b)66 static inline int32 imuldiv8(int32 a, int32 b)
67 {
68     int32 result;
69     __asm__("movl %1, %%eax\n\t"
70 	    "movl %2, %%edx\n\t"
71 	    "imull %%edx\n\t"
72 	    "shr $8, %%eax\n\t"
73 	    "shl $24, %%edx\n\t"
74 	    "or %%edx, %%eax\n\t"
75 	    "movl %%eax, %0\n\t"
76 	    : "=g"(result)
77 	    : "g"(a), "g"(b)
78 	    : "eax", "edx");
79     return result;
80 }
81 
imuldiv16(int32 a,int32 b)82 static inline int32 imuldiv16(int32 a, int32 b)
83 {
84     int32 result;
85     __asm__("movl %1, %%eax\n\t"
86 	    "movl %2, %%edx\n\t"
87 	    "imull %%edx\n\t"
88 	    "shr $16, %%eax\n\t"
89 	    "shl $16, %%edx\n\t"
90 	    "or %%edx, %%eax\n\t"
91 	    "movl %%eax, %0\n\t"
92 	    : "=g"(result)
93 	    : "g"(a), "g"(b)
94 	    : "eax", "edx");
95     return result;
96 }
97 
imuldiv24(int32 a,int32 b)98 static inline int32 imuldiv24(int32 a, int32 b)
99 {
100     int32 result;
101     __asm__("movl %1, %%eax\n\t"
102 	    "movl %2, %%edx\n\t"
103 	    "imull %%edx\n\t"
104 	    "shr $24, %%eax\n\t"
105 	    "shl $8, %%edx\n\t"
106 	    "or %%edx, %%eax\n\t"
107 	    "movl %%eax, %0\n\t"
108 	    : "=g"(result)
109 	    : "g"(a), "g"(b)
110 	    : "eax", "edx");
111     return result;
112 }
113 
imuldiv28(int32 a,int32 b)114 static inline int32 imuldiv28(int32 a, int32 b)
115 {
116     int32 result;
117     __asm__("movl %1, %%eax\n\t"
118 	    "movl %2, %%edx\n\t"
119 	    "imull %%edx\n\t"
120 	    "shr $28, %%eax\n\t"
121 	    "shl $4, %%edx\n\t"
122 	    "or %%edx, %%eax\n\t"
123 	    "movl %%eax, %0\n\t"
124 	    : "=g"(result)
125 	    : "g"(a), "g"(b)
126 	    : "eax", "edx");
127     return result;
128 }
129 
130 #elif ( defined(_MSC_VER) || defined(__DMC__) || defined(__WATCOMC__) ) && !defined(_AMD64_)
imuldiv8(int32 a,int32 b)131 inline int32 imuldiv8(int32 a, int32 b) {
132 	_asm {
133 		mov eax, a
134 		mov edx, b
135 		imul edx
136 		shr eax, 8
137 		shl edx, 24
138 		or  eax, edx
139 	}
140 }
141 
imuldiv16(int32 a,int32 b)142 inline int32 imuldiv16(int32 a, int32 b) {
143 	_asm {
144 		mov eax, a
145 		mov edx, b
146 		imul edx
147 		shr eax, 16
148 		shl edx, 16
149 		or  eax, edx
150 	}
151 }
152 
imuldiv24(int32 a,int32 b)153 inline int32 imuldiv24(int32 a, int32 b) {
154 	_asm {
155 		mov eax, a
156 		mov edx, b
157 		imul edx
158 		shr eax, 24
159 		shl edx, 8
160 		or  eax, edx
161 	}
162 }
163 
imuldiv28(int32 a,int32 b)164 inline int32 imuldiv28(int32 a, int32 b) {
165 	_asm {
166 		mov eax, a
167 		mov edx, b
168 		imul edx
169 		shr eax, 28
170 		shl edx, 4
171 		or  eax, edx
172 	}
173 }
174 
175 #elif ( defined(__BORLANDC__) && (__BORLANDC__ >= 1380) )
176 extern int32 imuldiv8(int32 a, int32 b) ;
177 extern int32 imuldiv16(int32 a, int32 b) ;
178 extern int32 imuldiv24(int32 a, int32 b) ;
179 extern int32 imuldiv28(int32 a, int32 b) ;
180 
181 #elif defined(__GNUC__) && defined(__ppc__)
imuldiv8(int32 a,int32 b)182 static inline int32 imuldiv8(int32 a, int32 b)
183 {
184     register int32 ret,rah,ral,rlh,rll;
185     __asm__ ("mulhw %0,%7,%8\n\t"
186 	     "mullw %1,%7,%8\n\t"
187 	     "rlwinm %2,%0,24,0,7\n\t"
188 	     "rlwinm %3,%1,24,8,31\n\t"
189 	     "or %4,%2,%3"
190 	     :"=r"(rah),"=r"(ral),
191 	      "=r"(rlh),"=r"(rll),
192 	      "=r"(ret),
193 	      "=r"(a),"=r"(b)
194 	     :"5"(a),"6"(b));
195     return ret;
196 }
197 
imuldiv16(int32 a,int32 b)198 static inline int32 imuldiv16(int32 a, int32 b)
199 {
200     register int32 ret,rah,ral,rlh,rll;
201     __asm__ ("mulhw %0,%7,%8\n\t"
202 	     "mullw %1,%7,%8\n\t"
203 	     "rlwinm %2,%0,16,0,15\n\t"
204 	     "rlwinm %3,%1,16,16,31\n\t"
205 	     "or %4,%2,%3"
206 	     :"=r"(rah),"=r"(ral),
207 	      "=r"(rlh),"=r"(rll),
208 	      "=r"(ret),
209 	      "=r"(a),"=r"(b)
210 	     :"5"(a),"6"(b));
211     return ret;
212 }
213 
imuldiv24(int32 a,int32 b)214 static inline int32 imuldiv24(int32 a, int32 b)
215 {
216     register int32 ret,rah,ral,rlh,rll;
217     __asm__ ("mulhw %0,%7,%8\n\t"
218 	     "mullw %1,%7,%8\n\t"
219 	     "rlwinm %2,%0,8,0,23\n\t"
220 	     "rlwinm %3,%1,8,24,31\n\t"
221 	     "or %4,%2,%3"
222 	     :"=r"(rah),"=r"(ral),
223 	      "=r"(rlh),"=r"(rll),
224 	      "=r"(ret),
225 	      "=r"(a),"=r"(b)
226 	     :"5"(a),"6"(b));
227     return ret;
228 }
229 
imuldiv28(int32 a,int32 b)230 static inline int32 imuldiv28(int32 a, int32 b)
231 {
232     register int32 ret,rah,ral,rlh,rll;
233     __asm__ ("mulhw %0,%7,%8\n\t"
234 	     "mullw %1,%7,%8\n\t"
235 	     "rlwinm %2,%0,4,0,27\n\t"
236 	     "rlwinm %3,%1,4,28,31\n\t"
237 	     "or %4,%2,%3"
238 	     :"=r"(rah),"=r"(ral),
239 	      "=r"(rlh),"=r"(rll),
240 	      "=r"(ret),
241 	      "=r"(a),"=r"(b)
242 	     :"5"(a),"6"(b));
243     return ret;
244 }
245 
246 #else
247 /* Generic version of imuldiv. */
248 #define imuldiv8(a, b) \
249     (int32)(((int64)(a) * (int64)(b)) >> 8)
250 
251 #define imuldiv16(a, b) \
252     (int32)(((int64)(a) * (int64)(b)) >> 16)
253 
254 #define imuldiv24(a, b) \
255     (int32)(((int64)(a) * (int64)(b)) >> 24)
256 
257 #define imuldiv28(a, b) \
258     (int32)(((int64)(a) * (int64)(b)) >> 28)
259 
260 #endif /* architectures */
261 
signlong(int32 a)262 static inline int32 signlong(int32 a)
263 {
264 	return ((a | 0x7fffffff) >> 30);
265 }
266 #endif /* OPT_MODE != 0 */
267 
268 /*****************************************************************************/
269 #if USE_ALTIVEC
270 
271 #ifndef __bool_true_false_are_defined
272 #define bool _Bool
273 typedef enum { false = 0, true = 1 } bool;
274 #endif /* C99 Hack */
275 
276 /* typedefs */
277 typedef vector signed int  vint32;
278 typedef vector signed char vint8;
279 
280 /* prototypes */
281 void v_memset(void* dest, int c, size_t len);
282 void v_memzero(void* dest, size_t len);
283 void v_set_dry_signal(void* dest, const int32* buf, int32 n);
284 
285 /* inline functions */
is_altivec_available(void)286 extern inline bool is_altivec_available(void)
287 {
288   int sel[2] = { CTL_HW, HW_VECTORUNIT };
289   int has_altivec = false;
290   size_t len = sizeof(has_altivec);
291   int error = sysctl(sel, 2, &has_altivec, &len, NULL, 0);
292   if(!error) {
293     return (bool)!!has_altivec;
294   } else {
295     return false;
296   }
297 }
298 
libc_memset(void * destp,int c,size_t len)299 extern inline void libc_memset(void* destp, int c, size_t len)
300 {
301     memset(destp,c,len);
302 }
303 
switch_memset(void * destp,int c,size_t len)304 static inline void* switch_memset(void* destp, int c, size_t len)
305 {
306     void* keepdestp = destp;
307     if(!is_altivec_available()) {
308         libc_memset(destp,c,len);
309     } else if (c) {
310         v_memset(destp,c,len);
311     } else {
312         v_memzero(destp,len);
313     }
314     return keepdestp;
315 }
316 
317 #define memset switch_memset
318 #endif /* altivec */
319 
320 #endif /* OPTCODE_H_INCLUDED */
321