Skip to content

Commit

Permalink
libgcc/m68k: Fixes for soft float
Browse files Browse the repository at this point in the history
Return correctly signed zero on float and double divide underflow

Return positive qNaN instead of negative.

Fix __fixxfsi which was off by a factor of two. Simplify the code
having realized that the lower 32 bits of the significand can never
appear in the results.

Signed-off-by: Keith Packard <[email protected]>
  • Loading branch information
keith-packard committed Dec 29, 2024
1 parent 862467c commit b7e023f
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 18 deletions.
42 changes: 28 additions & 14 deletions libgcc/config/m68k/fpgnulib.c
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,29 @@ __extenddfxf2 (double d)
exp = EXPXMASK;
ldl.l.upper |= exp << 16;
ldl.l.middle = HIDDENX;

/* Recover from a denorm. */
if (exp == -EXCESSD + EXCESSX)
{
exp++;
while ((dl.l.upper & HIDDEND) == 0)
{
exp--;
dl.l.upper = (dl.l.upper << 1) | (dl.l.lower >> 31);
dl.l.lower = dl.l.lower << 1;
}
}

/* Handle inf and NaN */
else if (exp == EXPDMASK - EXCESSD + EXCESSX)
{
exp = EXPXMASK;
/* No hidden one bit for INF */
if (dl.l.upper == 0 && dl.l.lower == 0)
ldl.l.middle = 0;
}

ldl.l.upper |= exp << 16;
/* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */
ldl.l.middle |= (dl.l.upper & MANTDMASK) << (31 - 20);
/* 1+20: explicit-integer-bit + # mantissa bits in dl.l.upper */
Expand Down Expand Up @@ -585,36 +608,27 @@ __fixxfsi (long double a)
{
union long_double_long ldl;
long exp;
long l;

ldl.ld = a;

exp = EXPX (ldl);
if (exp == 0 && ldl.l.middle == 0 && ldl.l.lower == 0)
return 0;

exp = exp - EXCESSX - 63;
exp = exp - EXCESSX - 32;

if (exp > 0)
if (exp >= 0)
{
/* Return largest integer. */
return SIGNX (ldl) ? 0x80000000L : 0x7fffffffL;
}

if (exp <= -64)
if (exp <= -32)
return 0;

if (exp <= -32)
{
ldl.l.lower = ldl.l.middle >> (-exp - 32);
}
else if (exp < 0)
{
ldl.l.lower = ldl.l.lower >> -exp;
ldl.l.lower |= ldl.l.middle << (32 + exp);
}
ldl.l.middle >>= -exp;

return SIGNX (ldl) ? -ldl.l.lower : ldl.l.lower;
return SIGNX (ldl) ? -ldl.l.middle : ldl.l.middle;
}

/* The remaining provide crude math support by working in double precision. */
Expand Down
13 changes: 9 additions & 4 deletions libgcc/config/m68k/lb1sf68.S
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ SYM (__modsi3):
.globl SYM (_fpCCR)
.globl $_exception_handler

QUIET_NaN = 0xffffffff
QUIET_NaN = 0x7fffffff

D_MAX_EXP = 0x07ff
D_BIAS = 1022
Expand Down Expand Up @@ -700,9 +700,10 @@ Ld$overflow:
PICJUMP $_exception_handler

Ld$underflow:
| Return 0 and set the exception flags
| Return a properly signed 0 and set the exception flags
movel IMM (0),d0
movel d0,d1
orl d7,d0
movew IMM (INEXACT_RESULT+UNDERFLOW),d7
moveq IMM (DOUBLE_FLOAT),d6
PICJUMP $_exception_handler
Expand All @@ -711,6 +712,7 @@ Ld$inop:
| Return a quiet NaN and set the exception flags
movel IMM (QUIET_NaN),d0
movel d0,d1
bset IMM (31),d1
movew IMM (INEXACT_RESULT+INVALID_OPERATION),d7
moveq IMM (DOUBLE_FLOAT),d6
PICJUMP $_exception_handler
Expand Down Expand Up @@ -2082,6 +2084,7 @@ Ldivdf$b$nf:
| If d2 == 0x7ff00000 we have to check d3.
tstl d3 |
bne Ld$inop | if d3 <> 0, b is NaN
movel a0,d7 | put a's sign
bra Ld$underflow | else b is +/-INFINITY, so signal underflow

Ldivdf$a$nf:
Expand Down Expand Up @@ -2187,6 +2190,7 @@ Lround$exit:
#endif
beq 2f | if not loop back
bra 1b |
movel a0,d7
bra Ld$underflow | safety check, shouldn't execute '
2: orl d6,d2 | this is a trick so we don't lose '
orl d7,d3 | the bits which were flushed right
Expand Down Expand Up @@ -2549,7 +2553,7 @@ Lround$to$minus:
.globl SYM (_fpCCR)
.globl $_exception_handler

QUIET_NaN = 0xffffffff
QUIET_NaN = 0x7fffffff
SIGNL_NaN = 0x7f800001
INFINITY = 0x7f800000

Expand Down Expand Up @@ -2615,8 +2619,9 @@ Lf$overflow:
PICJUMP $_exception_handler

Lf$underflow:
| Return 0 and set the exception flags
| Return a properly signed 0 and set the exception flags
moveq IMM (0),d0
orl d7,d0
moveq IMM (INEXACT_RESULT+UNDERFLOW),d7
moveq IMM (SINGLE_FLOAT),d6
PICJUMP $_exception_handler
Expand Down

0 comments on commit b7e023f

Please sign in to comment.