Date: Thu, 10 Jun 1999 10:45:48 +0300 (IDT) From: Eli Zaretskii X-Sender: eliz AT is To: djgpp-workers AT delorie DOT com cc: Morten Welinder Subject: emu387.cc bug Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Reply-To: djgpp-workers AT delorie DOT com See the thread "Linking in the math library produces peculiar results" on c.o.m.d., for the problem description. This one was a bitch to debug (mainly because debuggers break programs which use signals that are based on fake exceptions, like SIGFPE). At the end of the day, I can only reiterate what Morten said a long time ago: mixing signed and unsigned int's is looking for trouble. (The `sigh' and `sigl' members of the structure used by the emulator are declared unsigned, and the results of subtraction are tested for their sign, see below.) Finding such problems makes you wonder how many years can a serious bug lie low without being fixed. After all, addition, subtraction and comparison, all affected by this problem, are somthing a typical FP program does all the time, so how come this never came up? *** src/libemu/src/emu387.c~1 Tue Jun 8 13:36:22 1999 --- src/libemu/src/emu387.cc Wed Jun 9 19:06:00 1999 *************** static int compare(reg& a, reg& b) *** 220,227 **** b.exp--; } int diff = a.exp - b.exp; ! if (diff == 0) diff = a.sigh - b.sigh; ! if (diff == 0) diff = a.sigl - b.sigl; if (a.sign == SIGN_NEG) diff = -diff; if (diff > 0) return COMP_A_GT_B; --- 220,227 ---- b.exp--; } int diff = a.exp - b.exp; ! if (diff == 0) diff = a.sigh > b.sigh ? 1 : (a.sigh < b.sigh ? -1 : 0); ! if (diff == 0) diff = a.sigl > b.sigl ? 1 : (a.sigl < b.sigl ? -1 : 0); if (a.sign == SIGN_NEG) diff = -diff; if (diff > 0) return COMP_A_GT_B; *************** static void r_uadd(reg& a, reg& b, reg& *** 457,464 **** { reg t; int dif = a.exp - b.exp; ! if (!dif) dif = a.sigh - b.sigh; ! if (!dif) dif = a.sigl - b.sigl; if (dif > 0) { s = a; --- 457,464 ---- { reg t; int dif = a.exp - b.exp; ! if (!dif) dif = a.sigh > b.sigh ? 1 : (a.sigh < b.sigh ? -1 : 0); ! if (!dif) dif = a.sigl > b.sigl ? 1 : (a.sigl < b.sigl ? -1 : 0); if (dif > 0) { s = a; *************** static void r_sub(reg& a, reg& b, reg& d *** 583,591 **** int mdif; mdif = a.exp - b.exp; if (!mdif) ! mdif = a.sigh - b.sigh; if (!mdif) ! mdif = a.sigl - b.sigl; switch (a.sign*2 + b.sign) { --- 583,591 ---- int mdif; mdif = a.exp - b.exp; if (!mdif) ! mdif = a.sigh > b.sigh ? 1 : (a.sigh < b.sigh ? -1 : 0); if (!mdif) ! mdif = a.sigl > b.sigl ? 1 : (a.sigl < b.sigl ? -1 : 0); switch (a.sign*2 + b.sign) {