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