Skip to content

Commit b7e023f

Browse files
committed
libgcc/m68k: Fixes for soft float
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 <keithp@keithp.com>
1 parent 862467c commit b7e023f

File tree

2 files changed

+37
-18
lines changed

2 files changed

+37
-18
lines changed

libgcc/config/m68k/fpgnulib.c

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,29 @@ __extenddfxf2 (double d)
475475
exp = EXPXMASK;
476476
ldl.l.upper |= exp << 16;
477477
ldl.l.middle = HIDDENX;
478+
479+
/* Recover from a denorm. */
480+
if (exp == -EXCESSD + EXCESSX)
481+
{
482+
exp++;
483+
while ((dl.l.upper & HIDDEND) == 0)
484+
{
485+
exp--;
486+
dl.l.upper = (dl.l.upper << 1) | (dl.l.lower >> 31);
487+
dl.l.lower = dl.l.lower << 1;
488+
}
489+
}
490+
491+
/* Handle inf and NaN */
492+
else if (exp == EXPDMASK - EXCESSD + EXCESSX)
493+
{
494+
exp = EXPXMASK;
495+
/* No hidden one bit for INF */
496+
if (dl.l.upper == 0 && dl.l.lower == 0)
497+
ldl.l.middle = 0;
498+
}
499+
500+
ldl.l.upper |= exp << 16;
478501
/* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */
479502
ldl.l.middle |= (dl.l.upper & MANTDMASK) << (31 - 20);
480503
/* 1+20: explicit-integer-bit + # mantissa bits in dl.l.upper */
@@ -585,36 +608,27 @@ __fixxfsi (long double a)
585608
{
586609
union long_double_long ldl;
587610
long exp;
588-
long l;
589611

590612
ldl.ld = a;
591613

592614
exp = EXPX (ldl);
593615
if (exp == 0 && ldl.l.middle == 0 && ldl.l.lower == 0)
594616
return 0;
595617

596-
exp = exp - EXCESSX - 63;
618+
exp = exp - EXCESSX - 32;
597619

598-
if (exp > 0)
620+
if (exp >= 0)
599621
{
600622
/* Return largest integer. */
601623
return SIGNX (ldl) ? 0x80000000L : 0x7fffffffL;
602624
}
603625

604-
if (exp <= -64)
626+
if (exp <= -32)
605627
return 0;
606628

607-
if (exp <= -32)
608-
{
609-
ldl.l.lower = ldl.l.middle >> (-exp - 32);
610-
}
611-
else if (exp < 0)
612-
{
613-
ldl.l.lower = ldl.l.lower >> -exp;
614-
ldl.l.lower |= ldl.l.middle << (32 + exp);
615-
}
629+
ldl.l.middle >>= -exp;
616630

617-
return SIGNX (ldl) ? -ldl.l.lower : ldl.l.lower;
631+
return SIGNX (ldl) ? -ldl.l.middle : ldl.l.middle;
618632
}
619633

620634
/* The remaining provide crude math support by working in double precision. */

libgcc/config/m68k/lb1sf68.S

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,7 @@ SYM (__modsi3):
635635
.globl SYM (_fpCCR)
636636
.globl $_exception_handler
637637

638-
QUIET_NaN = 0xffffffff
638+
QUIET_NaN = 0x7fffffff
639639

640640
D_MAX_EXP = 0x07ff
641641
D_BIAS = 1022
@@ -700,9 +700,10 @@ Ld$overflow:
700700
PICJUMP $_exception_handler
701701

702702
Ld$underflow:
703-
| Return 0 and set the exception flags
703+
| Return a properly signed 0 and set the exception flags
704704
movel IMM (0),d0
705705
movel d0,d1
706+
orl d7,d0
706707
movew IMM (INEXACT_RESULT+UNDERFLOW),d7
707708
moveq IMM (DOUBLE_FLOAT),d6
708709
PICJUMP $_exception_handler
@@ -711,6 +712,7 @@ Ld$inop:
711712
| Return a quiet NaN and set the exception flags
712713
movel IMM (QUIET_NaN),d0
713714
movel d0,d1
715+
bset IMM (31),d1
714716
movew IMM (INEXACT_RESULT+INVALID_OPERATION),d7
715717
moveq IMM (DOUBLE_FLOAT),d6
716718
PICJUMP $_exception_handler
@@ -2082,6 +2084,7 @@ Ldivdf$b$nf:
20822084
| If d2 == 0x7ff00000 we have to check d3.
20832085
tstl d3 |
20842086
bne Ld$inop | if d3 <> 0, b is NaN
2087+
movel a0,d7 | put a's sign
20852088
bra Ld$underflow | else b is +/-INFINITY, so signal underflow
20862089

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

2552-
QUIET_NaN = 0xffffffff
2556+
QUIET_NaN = 0x7fffffff
25532557
SIGNL_NaN = 0x7f800001
25542558
INFINITY = 0x7f800000
25552559

@@ -2615,8 +2619,9 @@ Lf$overflow:
26152619
PICJUMP $_exception_handler
26162620

26172621
Lf$underflow:
2618-
| Return 0 and set the exception flags
2622+
| Return a properly signed 0 and set the exception flags
26192623
moveq IMM (0),d0
2624+
orl d7,d0
26202625
moveq IMM (INEXACT_RESULT+UNDERFLOW),d7
26212626
moveq IMM (SINGLE_FLOAT),d6
26222627
PICJUMP $_exception_handler

0 commit comments

Comments
 (0)