From: <re...@ai...> - 2001-09-26 14:54:28
|
Date: Tue, 25 Sep 2001 12:23 EDT From: Sam Steingold <sd...@gn...> what does this evaluate to? (+ 0 0x43ffffffff) ==> Prints out as -1, but isn't EQL to typed in -1, hence I deduce it is an example of 0x43ffffffff. > what do you get when you replace > > return negfixnum(wbitm(intLsize)+(oint)wert); > > with > > return negfixnum(-wbitm(intLsize)+(oint)wert); > > ?? > > That fixed it. all cases? fixnum and bignum? make check now passes? Yes, sorry for not making that clear. > Just out of curiosity, what is bit 32 supposed to mean? all 3 cases: return negfixnum( wbitm(intLsize)+(oint)wert); return negfixnum(-wbitm(intLsize)+(oint)wert); return negfixnum( (oint)wert); are identical on win32, linux and solaris. You mean a 32-bit Linux, right? I'm planning to set up an Alpha Linux presently, and I presume it would behave the same way as Tru64. Is the Solaris on a 64-bit or 32-bit system? The code is conditionalized to allow more type bits for 64-bit systems, so it isn't surprisiing that 32-bit systems don't see any problems. I wonder what is going on here. There is something curious in lispbibl.c: /* Bits 63..33 = Typcode, Bits 32..0 = Adresse */ #if 1 /* Was ist besser?? */ #define oint_type_shift 32 #define oint_type_len 32 #else #define oint_type_shift 33 #define oint_type_len 31 #endif #define oint_type_mask 0xFFFFFFFE00000000UL #define oint_addr_shift 0 #define oint_addr_len 33 #define oint_addr_mask 0x00000001FFFFFFFFUL #define oint_data_shift 0 #define oint_data_len 32 #define oint_data_mask 0x00000000FFFFFFFFUL I'm guessing that the original code was the second leg of the #if 1, i.e. shift of 33 and length of 31, but someone was trying out the first branch, i.e. shift of 32 and length of 32. However, the oint_type_mask value looks like it goes with the original value (i.e. 31 bits starting in bit 33). This makes the type bits be shifted over one from where the should be, (i.e. fixnum is 0x40 instead of 0x20) and leaves room for the "don't care" bit which leads to the confusion between 0x43ffffffff and 0x42ffffffff. However, putting it back didn't fix this particular bug. From reading the code some more, I'm reasonably certain that bit 32 is intended to be the fixnum sign bit, and that the wbitm(intLsize)+ part of the expression is intended to be doing sign extension of the known to be negative sign of the C value into that sign bit. The various preprocessor macros used inside negfixnum (fixnum_inc which calls objectplus which calls pointerplus) seem to expect addition to be modulo 32-bits, i.e. not affecting the sign or type bits, but on a 64bit machine the addition is a 64-bit one, and if you supply the sign bit twice [in this case both from the Fixnum_minus1 in negfixnum's expansion and the wbitm(intLsize) in returning the result], the overflow out of the sign bit goes into the next higher order type bit, hence the bug of returning a short float result instead of a negative fixnum. (The type short float is next higher than fixnum.) My guess is that on a 64-bit machine, fixnum_inc needs to be a bit smarter and do a masked or 32-bit addition. Note that negfixnum() is used in just a couple of place in the whole of CLISP - actually, always with small constants, except for SF_to_I() and FF_to_I(). Kalman, could you please try coercing some negative single and short floats to fixnums? I'm not sure what you want me to do. The Common Lisp COERCE function won't accept fixnum as a type. Floor and ceiling work as expected, i.e. give correct negative integers, not the bogus ones. Bruno, I would greatly appreciate your insight. thanks. -- Sam Steingold (http://www.podval.org/~sds) Support Israel's right to defend herself! <http://www.i-charity.com/go/israel> Read what the Arab leaders say to their people on <http://www.memri.org/> Marriage is the sole cause of divorce. |