--- a/SmallInteger.st Tue Aug 31 16:26:30 2004 +0200
+++ b/SmallInteger.st Tue Aug 31 21:29:22 2004 +0200
@@ -2998,19 +2998,156 @@
%{ /* NOCONTEXT */
+ INT myValue, otherValue;
+ unsigned INT productLow, productHi;
+ int negative;
+
+# define low16Bits(foo) ((foo) & 0xFFFF)
+# define hi16Bits(foo) ((foo) >> 16)
+# define low32Bits(foo) ((foo) & 0xFFFFFFFFL)
+# define hi32Bits(foo) ((foo) >> 32)
+
+ /*
+ * can we use long long arithmetic ?
+ *
+ * long-long arithmetic seems to be buggy with some systems
+ * (took me a while to find this out :-(
+ * (try 10000 * 10000)
+ */
+#if defined(sparc) && defined(__GNUC__) && (__GNUC__ >= 2)
+# define USE_LONGLONG_FOR_MUL
+#endif
+
+#if defined(i386) && defined(__GNUC__) && (__GNUC__ >= 2)
+# define USE_LONGLONG_FOR_MUL
+#endif
+
if (__isSmallInteger(aNumber)) {
+ myValue = __intVal(self);
+ otherValue = __intVal(aNumber);
+
+#if defined(USE_LONGLONG_FOR_MUL)
+ {
# if defined(alpha) && !defined(alpha64)
# define LONGLONG INT64
# else
# define LONGLONG long long
# endif
- LONGLONG product;
-
- /* keep the sign */
- product = ((LONGLONG)__intVal(self) * (LONGLONG)__intVal(aNumber)) % _MAX_INT;
- RETURN ( __MKSMALLINT((INT)product));
+ LONGLONG product;
+
+ product = (LONGLONG)myValue * (LONGLONG)otherValue;
+ if (product < 0) {
+ RETURN ( __MKSMALLINT(-(INT)(-product & 0x3FFFFFFF)));
+ }
+ RETURN ( __MKSMALLINT((INT)(product & 0x3FFFFFFF)));
+ }
+#else /* no long-long */
+ negative = 1;
+ if (myValue < 0) {
+ negative = -1;
+ myValue = -myValue;
+ }
+ if (otherValue < 0) {
+ negative = -negative;
+ otherValue = -otherValue;
+ }
+
+# if defined(__GNUC__) && defined(mc68k)
+ asm ("mulu%.l %3,%1:%0"
+ : "=d" ((unsigned long)(productLow)),
+ "=d" ((unsigned long)(productHi))
+ : "%0" ((unsigned long)(myValue)),
+ "dmi" ((unsigned long)(otherValue)));
+# else
+# if defined (__GNUC__) && defined(i386)
+ asm ("mull %3"
+ : "=a" ((unsigned long)(productLow)),
+ "=d" ((unsigned long)(productHi))
+ : "%0" ((unsigned long)(myValue)),
+ "rm" ((unsigned long)(otherValue)));
+# else
+# if defined(WIN32)
+ asm {
+ mov eax, myValue
+ mov edx, otherValue
+ mul edx
+ mov productLow, eax
+ mov productHi, edx
+ }
+# else /* generic */
+ {
+ unsigned INT pHH, pHL, pLH, pLL;
+ unsigned INT low1, low2, hi1, hi2;
+ unsigned INT t;
+
+ /* unsigned multiply myValue * otherValue -> productHi, productLow
+ *
+ * this is too slow:
+ * since most machines can do 32*32 to 64 bit multiply,
+ * (or at least 32*32 with Overflow check)
+ * - need more assembler (inline) functions here
+ */
+# ifdef alpha64
+ low1 = low32Bits((unsigned INT)myValue);
+ hi1 = hi32Bits((unsigned INT)myValue);
+ low2 = low32Bits((unsigned INT)otherValue);
+ hi2 = hi32Bits((unsigned INT)otherValue);
+# define LLMASK 0xC000000000000000L
+# else
+ low1 = low16Bits((unsigned INT)myValue);
+ hi1 = hi16Bits((unsigned INT)myValue);
+ low2 = low16Bits((unsigned INT)otherValue);
+ hi2 = hi16Bits((unsigned INT)otherValue);
+# define LLMASK 0xC0000000
+# endif
+
+ pLH = low1 * hi2;
+ pHL = hi1 * low2;
+ pLL = low1 * low2;
+ pHH = hi1 * hi2;
+
+ /*
+ * the common case ...
+ */
+ if ((pHL == 0)
+ && (pLH == 0)
+ && (pHH == 0)
+ && ((pLL & LLMASK) == 0)) {
+ if (negative < 0) {
+ RETURN ( __MKSMALLINT(- ((INT)pLL)) );
+ }
+ RETURN ( __MKSMALLINT((INT)pLL) );
+ }
+
+ /*
+ * pHH |--------|--------|
+ * pLH |--------|--------|
+ * pHL |--------|--------|
+ * pLL |--------|--------|
+ */
+
+# ifdef alpha64
+ t = low32Bits(pLH) + low32Bits(pHL) + hi32Bits(pLL);
+ productLow = (t << 32) + low32Bits(pLL);
+ productHi = pHH + hi32Bits(t) + hi32Bits(pHL) + hi32Bits(pLH);
+# else
+ t = low16Bits(pLH) + low16Bits(pHL) + hi16Bits(pLL);
+ productLow = (t << 16) + low16Bits(pLL);
+ productHi = pHH + hi16Bits(t) + hi16Bits(pHL) + hi16Bits(pLH);
+# endif
+ }
+# endif /* ! WIN32 */
+# endif /* ! (__GNUC__ && i386) */
+# endif /* ! (__GNUC__ && mc68k) */
+
+ if (negative < 0) {
+ RETURN ( __MKSMALLINT(-(INT)(productLow & 0x3FFFFFFF)));
+ }
+ RETURN ( __MKSMALLINT((INT)(productLow & 0x3FFFFFFF)));
+#endif /* ! USE_LONGLONG */
}
%}.
+
self primitiveFailed
"
@@ -3018,7 +3155,7 @@
5 times:1
self maxVal-1 times:2
self maxVal-1 times:-2
- self maxVal-1 * 2
+ self maxVal-1 * 2 bitAnd:16r3fffffff
"
! !
@@ -3447,5 +3584,5 @@
!SmallInteger class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/SmallInteger.st,v 1.161 2004-08-30 16:44:27 stefan Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/SmallInteger.st,v 1.162 2004-08-31 19:29:22 stefan Exp $'
! !