211 #if defined(__i386__) && defined(__GNUC__) && (__GNUC__ >= 2) |
211 #if defined(__i386__) && defined(__GNUC__) && (__GNUC__ >= 2) |
212 # define USE_LONGLONG_FOR_MUL |
212 # define USE_LONGLONG_FOR_MUL |
213 #endif |
213 #endif |
214 |
214 |
215 if (__isSmallInteger(aNumber)) { |
215 if (__isSmallInteger(aNumber)) { |
216 myValue = __intVal(self); |
216 myValue = __intVal(self); |
217 otherValue = __intVal(aNumber); |
217 otherValue = __intVal(aNumber); |
218 |
218 |
219 #if defined(USE_LONGLONG_FOR_MUL) |
219 #if defined(USE_LONGLONG_FOR_MUL) |
220 { |
220 { |
221 # if defined(__alpha__) && !defined(__alpha64__) |
221 # if defined(__alpha__) && !defined(__alpha64__) |
222 # define LONGLONG INT64 |
222 # define LONGLONG INT64 |
223 # else |
223 # else |
224 # define LONGLONG long long |
224 # define LONGLONG long long |
225 # endif |
225 # endif |
226 LONGLONG product; |
226 LONGLONG product; |
227 |
227 |
228 product = (LONGLONG)myValue * (LONGLONG)otherValue; |
228 product = (LONGLONG)myValue * (LONGLONG)otherValue; |
229 if ((product >= (LONGLONG)_MIN_INT) |
229 if ((product >= (LONGLONG)_MIN_INT) |
230 && (product <= (LONGLONG)_MAX_INT)) { |
230 && (product <= (LONGLONG)_MAX_INT)) { |
231 RETURN ( __mkSmallInteger((INT)product) ); |
231 RETURN ( __mkSmallInteger((INT)product) ); |
232 } |
232 } |
233 if (product < 0) { |
233 if (product < 0) { |
234 negative = -1; |
234 negative = -1; |
235 product = -product; |
235 product = -product; |
236 } else { |
236 } else { |
237 negative = 1; |
237 negative = 1; |
238 } |
238 } |
239 productHi = product >> 32; |
239 productHi = product >> 32; |
240 productLow = product & 0xFFFFFFFFL; |
240 productLow = product & 0xFFFFFFFFL; |
241 } |
241 } |
242 #else /* no long-long */ |
242 #else /* no long-long */ |
243 negative = 1; |
243 negative = 1; |
244 if (myValue < 0) { |
244 if (myValue < 0) { |
245 negative = -1; |
245 negative = -1; |
246 myValue = -myValue; |
246 myValue = -myValue; |
247 } |
247 } |
248 if (otherValue < 0) { |
248 if (otherValue < 0) { |
249 negative = -negative; |
249 negative = -negative; |
250 otherValue = -otherValue; |
250 otherValue = -otherValue; |
251 } |
251 } |
252 |
252 |
253 # if defined(__GNUC__) && defined(__mc68k__) |
253 # if defined(__GNUC__) && defined(__mc68k__) |
254 asm ("mulu%.l %3,%1:%0" |
254 asm ("mulu%.l %3,%1:%0" |
255 : "=d" ((unsigned long)(productLow)), |
255 : "=d" ((unsigned long)(productLow)), |
256 "=d" ((unsigned long)(productHi)) |
256 "=d" ((unsigned long)(productHi)) |
257 : "%0" ((unsigned long)(myValue)), |
257 : "%0" ((unsigned long)(myValue)), |
258 "dmi" ((unsigned long)(otherValue))); |
258 "dmi" ((unsigned long)(otherValue))); |
259 # else |
259 # else |
260 # if defined (__GNUC__) && defined(__i386__) |
260 # if defined (__GNUC__) && defined(__i386__) |
261 asm ("mull %3" |
261 asm ("mull %3" |
262 : "=a" ((unsigned long)(productLow)), |
262 : "=a" ((unsigned long)(productLow)), |
263 "=d" ((unsigned long)(productHi)) |
263 "=d" ((unsigned long)(productHi)) |
264 : "%0" ((unsigned long)(myValue)), |
264 : "%0" ((unsigned long)(myValue)), |
265 "rm" ((unsigned long)(otherValue))); |
265 "rm" ((unsigned long)(otherValue))); |
266 # else |
266 # else |
267 # if defined(WIN32) && defined(__BORLANDC__) |
267 # if defined(WIN32) && defined(__BORLANDC__) |
268 asm { |
268 asm { |
269 mov eax, myValue |
269 mov eax, myValue |
270 mov edx, otherValue |
270 mov edx, otherValue |
271 mul edx |
271 mul edx |
272 mov productLow, eax |
272 mov productLow, eax |
273 mov productHi, edx |
273 mov productHi, edx |
274 } |
274 } |
275 # else /* generic */ |
275 # else /* generic */ |
276 { |
276 { |
277 unsigned INT pHH, pHL, pLH, pLL; |
277 unsigned INT pHH, pHL, pLH, pLL; |
278 unsigned INT low1, low2, hi1, hi2; |
278 unsigned INT low1, low2, hi1, hi2; |
279 unsigned INT t; |
279 unsigned INT t; |
280 |
280 |
281 /* unsigned multiply myValue * otherValue -> productHi, productLow |
281 /* unsigned multiply myValue * otherValue -> productHi, productLow |
282 * |
282 * |
283 * this is too slow: |
283 * this is too slow: |
284 * since most machines can do 32*32 to 64 bit multiply, |
284 * since most machines can do 32*32 to 64 bit multiply, |
285 * (or at least 32*32 with Overflow check) |
285 * (or at least 32*32 with Overflow check) |
286 * - need more assembler (inline) functions here |
286 * - need more assembler (inline) functions here |
287 */ |
287 */ |
288 # if __POINTER_SIZE__ == 8 |
288 # if __POINTER_SIZE__ == 8 |
289 low1 = low32Bits((unsigned INT)myValue); |
289 low1 = low32Bits((unsigned INT)myValue); |
290 hi1 = hi32Bits((unsigned INT)myValue); |
290 hi1 = hi32Bits((unsigned INT)myValue); |
291 low2 = low32Bits((unsigned INT)otherValue); |
291 low2 = low32Bits((unsigned INT)otherValue); |
292 hi2 = hi32Bits((unsigned INT)otherValue); |
292 hi2 = hi32Bits((unsigned INT)otherValue); |
293 # define LLMASK 0xC000000000000000L |
293 # define LLMASK 0xC000000000000000L |
294 # else |
294 # else |
295 low1 = low16Bits((unsigned INT)myValue); |
295 low1 = low16Bits((unsigned INT)myValue); |
296 hi1 = hi16Bits((unsigned INT)myValue); |
296 hi1 = hi16Bits((unsigned INT)myValue); |
297 low2 = low16Bits((unsigned INT)otherValue); |
297 low2 = low16Bits((unsigned INT)otherValue); |
298 hi2 = hi16Bits((unsigned INT)otherValue); |
298 hi2 = hi16Bits((unsigned INT)otherValue); |
299 # define LLMASK 0xC0000000 |
299 # define LLMASK 0xC0000000 |
300 # endif |
300 # endif |
301 |
301 |
302 pLH = low1 * hi2; |
302 pLH = low1 * hi2; |
303 pHL = hi1 * low2; |
303 pHL = hi1 * low2; |
304 pLL = low1 * low2; |
304 pLL = low1 * low2; |
305 pHH = hi1 * hi2; |
305 pHH = hi1 * hi2; |
306 |
306 |
307 /* |
307 /* |
308 * the common case ... |
308 * the common case ... |
309 */ |
309 */ |
310 if ((pHL == 0) |
310 if ((pHL == 0) |
311 && (pLH == 0) |
311 && (pLH == 0) |
312 && (pHH == 0) |
312 && (pHH == 0) |
313 && ((pLL & LLMASK) == 0)) { |
313 && ((pLL & LLMASK) == 0)) { |
314 if (negative < 0) { |
314 if (negative < 0) { |
315 RETURN ( __mkSmallInteger(- ((INT)pLL)) ); |
315 RETURN ( __mkSmallInteger(- ((INT)pLL)) ); |
316 } |
316 } |
317 RETURN ( __mkSmallInteger((INT)pLL) ); |
317 RETURN ( __mkSmallInteger((INT)pLL) ); |
318 } |
318 } |
319 |
319 |
320 /* |
320 /* |
321 * pHH |--------|--------| |
321 * pHH |--------|--------| |
322 * pLH |--------|--------| |
322 * pLH |--------|--------| |
323 * pHL |--------|--------| |
323 * pHL |--------|--------| |
324 * pLL |--------|--------| |
324 * pLL |--------|--------| |
325 */ |
325 */ |
326 |
326 |
327 # if __POINTER_SIZE__ == 8 |
327 # if __POINTER_SIZE__ == 8 |
328 t = low32Bits(pLH) + low32Bits(pHL) + hi32Bits(pLL); |
328 t = low32Bits(pLH) + low32Bits(pHL) + hi32Bits(pLL); |
329 productLow = (t << 32) + low32Bits(pLL); |
329 productLow = (t << 32) + low32Bits(pLL); |
330 productHi = pHH + hi32Bits(t) + hi32Bits(pHL) + hi32Bits(pLH); |
330 productHi = pHH + hi32Bits(t) + hi32Bits(pHL) + hi32Bits(pLH); |
331 # else |
331 # else |
332 t = low16Bits(pLH) + low16Bits(pHL) + hi16Bits(pLL); |
332 t = low16Bits(pLH) + low16Bits(pHL) + hi16Bits(pLL); |
333 productLow = (t << 16) + low16Bits(pLL); |
333 productLow = (t << 16) + low16Bits(pLL); |
334 productHi = pHH + hi16Bits(t) + hi16Bits(pHL) + hi16Bits(pLH); |
334 productHi = pHH + hi16Bits(t) + hi16Bits(pHL) + hi16Bits(pLH); |
335 # endif |
335 # endif |
336 } |
336 } |
337 # endif /* ! WIN32 */ |
337 # endif /* ! WIN32 */ |
338 # endif /* ! (__GNUC__ && __i386__) */ |
338 # endif /* ! (__GNUC__ && __i386__) */ |
339 # endif /* ! (__GNUC__ && __mc68k__) */ |
339 # endif /* ! (__GNUC__ && __mc68k__) */ |
340 |
340 |
341 if (productHi == 0) { |
341 if (productHi == 0) { |
342 if (negative < 0) { |
342 if (negative < 0) { |
343 if (productLow <= -(_MIN_INT)) { |
343 if (productLow <= -(_MIN_INT)) { |
344 RETURN ( __mkSmallInteger(-((INT)productLow)) ); |
344 RETURN ( __mkSmallInteger(-((INT)productLow)) ); |
345 } |
345 } |
346 } else { |
346 } else { |
347 if (productLow <= _MAX_INT) { |
347 if (productLow <= _MAX_INT) { |
348 RETURN ( __mkSmallInteger(productLow) ); |
348 RETURN ( __mkSmallInteger(productLow) ); |
349 } |
349 } |
350 } |
350 } |
351 } |
351 } |
352 #endif /* ! USE_LONGLONG */ |
352 #endif /* ! USE_LONGLONG */ |
353 |
353 |
354 #if __POINTER_SIZE__ == 8 |
354 #if __POINTER_SIZE__ == 8 |
355 RETURN (__MKLARGEINT128(negative, productLow, productHi)); |
355 RETURN (__MKLARGEINT128(negative, productLow, productHi)); |
356 #else |
356 #else |
357 RETURN (__MKLARGEINT64(negative, productLow, productHi)); |
357 RETURN (__MKLARGEINT64(negative, productLow, productHi)); |
358 #endif |
358 #endif |
359 } else if (__isFloatLike(aNumber)) { |
359 } else if (__isFloatLike(aNumber)) { |
360 OBJ newFloat; |
360 OBJ newFloat; |
361 double val = (double)__intVal(self) * __floatVal(aNumber); |
361 double val = (double)__intVal(self) * __floatVal(aNumber); |
362 |
362 |
363 __qMKFLOAT(newFloat, val); |
363 __qMKFLOAT(newFloat, val); |
364 RETURN ( newFloat ); |
364 RETURN ( newFloat ); |
365 } else if (__isShortFloat(aNumber)) { |
365 } else if (__isShortFloat(aNumber)) { |
366 OBJ newFloat; |
366 OBJ newFloat; |
367 float val = (float)__intVal(self) * __shortFloatVal(aNumber); |
367 float val = (float)__intVal(self) * __shortFloatVal(aNumber); |
368 |
368 |
369 __qMKSFLOAT(newFloat, val); |
369 __qMKSFLOAT(newFloat, val); |
370 RETURN ( newFloat ); |
370 RETURN ( newFloat ); |
371 } |
371 } |
372 %}. |
372 %}. |
373 ^ aNumber productFromInteger:self |
373 ^ aNumber productFromInteger:self |
374 ! |
374 ! |
375 |
375 |