Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libgcc/m68k: Fixes for soft float #93

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions gcc/config/m68k/m68k.cc
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ static void m68k_asm_final_postscan_insn (FILE *, rtx_insn *insn, rtx [], int);
static HARD_REG_SET m68k_zero_call_used_regs (HARD_REG_SET);
static machine_mode m68k_c_mode_for_floating_type (enum tree_index);
static bool m68k_use_lra_p (void);
static bool m68k_can_change_mode_class (machine_mode from, machine_mode to, reg_class_t rclass);

/* Initialize the GCC target structure. */

Expand Down Expand Up @@ -370,6 +371,9 @@ static bool m68k_use_lra_p (void);
#undef TARGET_C_MODE_FOR_FLOATING_TYPE
#define TARGET_C_MODE_FOR_FLOATING_TYPE m68k_c_mode_for_floating_type

#undef TARGET_CAN_CHANGE_MODE_CLASS
#define TARGET_CAN_CHANGE_MODE_CLASS m68k_can_change_mode_class

TARGET_GNU_ATTRIBUTES (m68k_attribute_table,
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req,
Expand Down Expand Up @@ -7269,4 +7273,22 @@ m68k_use_lra_p ()
return m68k_lra_p;
}

/* Implement TARGET_CAN_CHANGE_MODE_CLASS. */

static bool
m68k_can_change_mode_class (machine_mode from,
machine_mode to,
reg_class_t rclass)
{
if (from == to)
return true;

/* 68881 registers can't do subreg at all, as all values are reformatted
to extended precision. */
if (reg_classes_intersect_p(rclass, FP_REGS))
return false;

return true;
}

#include "gt-m68k.h"
78 changes: 36 additions & 42 deletions libgcc/config/m68k/fpgnulib.c
Original file line number Diff line number Diff line change
Expand Up @@ -449,34 +449,37 @@ __extenddfxf2 (double d)
}

exp = EXPD (dl) - EXCESSD + EXCESSX;
/* Check for underflow and denormals. */
if (exp < 0)

dl.l.upper &= MANTDMASK;

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

/* Handle inf and NaN */
if (exp == EXPDMASK - EXCESSD + EXCESSX)
exp = EXPXMASK;
else if (exp == EXPDMASK - EXCESSD + EXCESSX)
{
exp = EXPXMASK;
/* Add hidden one bit for NaN */
if (dl.l.upper != 0 || dl.l.lower != 0)
dl.l.upper |= HIDDEND;
}
else
{
dl.l.upper |= HIDDEND;
}

ldl.l.upper |= exp << 16;
ldl.l.middle = HIDDENX;
/* 31-20: # mantissa bits in ldl.l.middle - # mantissa bits in dl.l.upper */
ldl.l.middle |= (dl.l.upper & MANTDMASK) << (31 - 20);
ldl.l.middle = dl.l.upper << (31 - 20);
/* 1+20: explicit-integer-bit + # mantissa bits in dl.l.upper */
ldl.l.middle |= dl.l.lower >> (1 + 20);
/* 32 - 21: # bits of dl.l.lower in ldl.l.middle */
Expand Down Expand Up @@ -508,21 +511,21 @@ __truncxfdf2 (long double ld)
/* Check for underflow and denormals. */
if (exp <= 0)
{
if (exp < -53)
long shift = 1 - exp;
if (shift > 52)
{
ldl.l.middle = 0;
ldl.l.lower = 0;
}
else if (exp < -30)
else if (shift >= 32)
{
ldl.l.lower = (ldl.l.middle & MANTXMASK) >> ((1 - exp) - 32);
ldl.l.middle &= ~MANTXMASK;
ldl.l.lower = (ldl.l.middle) >> (shift - 32);
ldl.l.middle = 0;
}
else
{
ldl.l.lower >>= 1 - exp;
ldl.l.lower |= (ldl.l.middle & MANTXMASK) << (32 - (1 - exp));
ldl.l.middle = (ldl.l.middle & ~MANTXMASK) | (ldl.l.middle & MANTXMASK >> (1 - exp));
ldl.l.lower = (ldl.l.middle << (32 - shift)) | (ldl.l.lower >> shift);
ldl.l.middle = ldl.l.middle >> shift;
}
exp = 0;
}
Expand Down Expand Up @@ -585,36 +588,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 | get back sign bit into 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