Commit 23c108af by Steve Ellcey Committed by Jim Wilson

Add ia64-hpux 128-bit long double support.

From-SVN: r43565
parent 62d73fa8
2001-06-25 Steve Ellcey <sje@cup.hp.com>
* config.gcc (ia64*-*-hpux*): Add ia64/hpux_longdouble.h to tm_file.
Define tmake_file to include ia64/t-hpux.
* real.c (INTEL_EXTENDED_IEEE_FORMAT): Test for value instead of
testing to see if it is defined.
* real.h (INTEL_EXTENDED_IEEE_FORMAT): Likewise. Default to 0 if
undefined.
* config/ia64/hpux_longdouble.h: New.
* config/ia64/ia64.c (hfa_element_mode): Add comment about incorrect
handling of long doubles.
(ia64_function_arg, ia64_function_value): Add checks for TFmode
and INTEL_EXTENDED_IEEE_FORMAT.
* config/ia64/ia64.h (INTEL_EXTENDED_IEEE_FORMAT): Define to one.
(HARD_REGNO_NREGS, HARD_REGNO_MODE_OK, LIBCALL_VALUE): Add checks for
TFmode and INTEL_EXTENDED_IEEE_FORMAT.
* config/ia64/ia64.md (all TFmode patterns): Test
INTEL_EXTENDED_IEEE_FORMAT in condition.
(floatdidf2, floatdisf2): New, for !INTEL_EXTENDED_IEEE_FORMAT.
* config/ia64/quadlib.c: New.
* config/ia64/t-hpux: New.
* config/i386/i386.h (INTEL_EXTENDED_IEEE_FORMAT): Define to one.
2001-06-25 Jim Wilson <wilson@redhat.com>
* config/i960/t-960bare (i960-c.o): Add missing header dependencies.
......
......@@ -1489,7 +1489,8 @@ ia64*-*-linux*)
float_format=i386
;;
ia64*-*-hpux*)
tm_file="ia64/ia64.h svr4.h ia64/sysv4.h ia64/hpux.h"
tm_file="ia64/ia64.h svr4.h ia64/sysv4.h ia64/hpux.h ia64/hpux_longdouble.h"
tmake_file="ia64/t-ia64 ia64/t-hpux"
target_cpu_default="MASK_GNU_AS"
if test x$enable_threads = xyes; then
thread_file='posix'
......
......@@ -575,7 +575,7 @@ extern int ix86_arch;
#endif
/* Tell real.c that this is the 80-bit Intel extended float format
packaged in a 128-bit or 96bit entity. */
#define INTEL_EXTENDED_IEEE_FORMAT
#define INTEL_EXTENDED_IEEE_FORMAT 1
#define SHORT_TYPE_SIZE 16
......
/* Definitions of long double support for GNU compiler.
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* Tell real.c that we are not using INTEL_EXTENDED_IEEE_FORMAT */
#undef INTEL_EXTENDED_IEEE_FORMAT
#define INTEL_EXTENDED_IEEE_FORMAT 0
/* Define library calls for quad FP operations. These are all part of the
IA32 and IA64 ABIs. */
#define ADDTF3_LIBCALL "_U_Qfadd"
#define SUBTF3_LIBCALL "_U_Qfsub"
#define MULTF3_LIBCALL "_U_Qfmpy"
#define DIVTF3_LIBCALL "_U_Qfdiv"
#define NEGTF2_LIBCALL "_U_Qfneg"
#define ABSTF2_LIBCALL "_U_Qfabs"
#define SMINTF3_LIBCALL "_U_Qfmin"
#define SMAXTF3_LIBCALL "_U_Qfmax"
#define EXTENDSFTF2_LIBCALL "_U_Qfcnvff_sgl_to_quad"
#define EXTENDDFTF2_LIBCALL "_U_Qfcnvff_dbl_to_quad"
#define TRUNCTFSF2_LIBCALL "_U_Qfcnvff_quad_to_sgl"
#define TRUNCTFDF2_LIBCALL "_U_Qfcnvff_quad_to_dbl"
#define FLOATSITF2_LIBCALL "_U_Qfcnvxf_sgl_to_quad"
#define FLOATDITF2_LIBCALL "_U_Qfcnvxf_dbl_to_quad"
#define FIX_TRUNCTFSI2_LIBCALL "_U_Qfcnvfxt_quad_to_sgl"
#define FIX_TRUNCTFDI2_LIBCALL "_U_Qfcnvfxt_quad_to_dbl"
#define EQTF2_LIBCALL "_U_Qfeq"
#define NETF2_LIBCALL "_U_Qfne"
#define GTTF2_LIBCALL "_U_Qfgt"
#define GETF2_LIBCALL "_U_Qfge"
#define LTTF2_LIBCALL "_U_Qflt"
#define LETF2_LIBCALL "_U_Qfle"
#undef INIT_TARGET_OPTABS
#define INIT_TARGET_OPTABS \
do { \
add_optab->handlers[(int) TFmode].libfunc \
= gen_rtx_SYMBOL_REF (Pmode, ADDTF3_LIBCALL); \
sub_optab->handlers[(int) TFmode].libfunc \
= gen_rtx_SYMBOL_REF (Pmode, SUBTF3_LIBCALL); \
smul_optab->handlers[(int) TFmode].libfunc \
= gen_rtx_SYMBOL_REF (Pmode, MULTF3_LIBCALL); \
flodiv_optab->handlers[(int) TFmode].libfunc \
= gen_rtx_SYMBOL_REF (Pmode, DIVTF3_LIBCALL); \
smin_optab->handlers[(int) TFmode].libfunc \
= gen_rtx_SYMBOL_REF (Pmode, SMINTF3_LIBCALL); \
smax_optab->handlers[(int) TFmode].libfunc \
= gen_rtx_SYMBOL_REF (Pmode, SMAXTF3_LIBCALL); \
abs_optab->handlers[(int) TFmode].libfunc \
= gen_rtx_SYMBOL_REF (Pmode, ABSTF2_LIBCALL); \
neg_optab->handlers[(int) TFmode].libfunc \
= gen_rtx_SYMBOL_REF (Pmode, NEGTF2_LIBCALL); \
extendsftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, EXTENDSFTF2_LIBCALL); \
extenddftf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, EXTENDDFTF2_LIBCALL); \
trunctfsf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, TRUNCTFSF2_LIBCALL); \
trunctfdf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, TRUNCTFDF2_LIBCALL); \
floatsitf_libfunc = gen_rtx_SYMBOL_REF (Pmode, FLOATSITF2_LIBCALL); \
floatditf_libfunc = gen_rtx_SYMBOL_REF (Pmode, FLOATDITF2_LIBCALL); \
fixtfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFSI2_LIBCALL);\
fixtfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFDI2_LIBCALL);\
fixunstfsi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFSI2_LIBCALL); \
fixunstfdi_libfunc = gen_rtx_SYMBOL_REF (Pmode, FIX_TRUNCTFDI2_LIBCALL); \
eqtf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, EQTF2_LIBCALL); \
netf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, NETF2_LIBCALL); \
gttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, GTTF2_LIBCALL); \
getf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, GETF2_LIBCALL); \
lttf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, LTTF2_LIBCALL); \
letf2_libfunc = gen_rtx_SYMBOL_REF (Pmode, LETF2_LIBCALL); \
\
sdiv_optab->handlers[(int) SImode].libfunc = 0; \
udiv_optab->handlers[(int) SImode].libfunc = 0; \
smod_optab->handlers[(int) SImode].libfunc = 0; \
umod_optab->handlers[(int) SImode].libfunc = 0; \
\
INIT_SUBTARGET_OPTABS; \
} while (0)
/* This is meant to be redefined in the host dependent files */
#define INIT_SUBTARGET_OPTABS
/* Nonzero if a floating point comparison library call for
mode MODE that will return a boolean value. Zero if one
of the libgcc2 functions is used. */
#define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) ((MODE) == TFmode)
......@@ -2714,6 +2714,7 @@ hfa_element_mode (type, nested)
return VOIDmode;
case REAL_TYPE:
/* ??? Should exclude 128-bit long double here. */
/* We want to return VOIDmode for raw REAL_TYPEs, but the actual
mode if this is contained within an aggregate. */
if (nested)
......@@ -2888,7 +2889,8 @@ ia64_function_arg (cum, mode, type, named, incoming)
/* Integral and aggregates go in general registers. If we have run out of
FR registers, then FP values must also go in general registers. This can
happen when we have a SFmode HFA. */
else if (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS)
else if (((mode == TFmode) && ! INTEL_EXTENDED_IEEE_FORMAT)
|| (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
return gen_rtx_REG (mode, basereg + cum->words + offset);
/* If there is a prototype, then FP values go in a FR register when
......@@ -3168,7 +3170,8 @@ ia64_function_value (valtype, func)
else
return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
}
else if (FLOAT_TYPE_P (valtype))
else if (FLOAT_TYPE_P (valtype) &&
((mode != TFmode) || INTEL_EXTENDED_IEEE_FORMAT))
return gen_rtx_REG (mode, FR_ARG_FIRST);
else
return gen_rtx_REG (mode, GR_RET_FIRST);
......
......@@ -470,7 +470,8 @@ while (0)
/* Tell real.c that this is the 80-bit Intel extended float format
packaged in a 128-bit entity. */
#define INTEL_EXTENDED_IEEE_FORMAT
#define INTEL_EXTENDED_IEEE_FORMAT 1
/* An expression whose value is 1 or 0, according to whether the type `char'
should be signed or unsigned by default. The user can always override this
......@@ -824,7 +825,7 @@ while (0)
((REGNO) == PR_REG (0) && (MODE) == DImode ? 64 \
: PR_REGNO_P (REGNO) && (MODE) == BImode ? 2 \
: PR_REGNO_P (REGNO) && (MODE) == CCImode ? 1 \
: FR_REGNO_P (REGNO) && (MODE) == TFmode ? 1 \
: FR_REGNO_P (REGNO) && (MODE) == TFmode && INTEL_EXTENDED_IEEE_FORMAT ? 1 \
: (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* A C expression that is nonzero if it is permissible to store a value of mode
......@@ -833,7 +834,10 @@ while (0)
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
(FR_REGNO_P (REGNO) ? \
GET_MODE_CLASS (MODE) != MODE_CC && (MODE) != TImode && (MODE) != BImode \
GET_MODE_CLASS (MODE) != MODE_CC && \
(MODE) != TImode && \
(MODE) != BImode && \
((MODE) != TFmode || INTEL_EXTENDED_IEEE_FORMAT) \
: PR_REGNO_P (REGNO) ? \
(MODE) == BImode || GET_MODE_CLASS (MODE) == MODE_CC \
: GR_REGNO_P (REGNO) ? (MODE) != CCImode && (MODE) != TFmode \
......@@ -1423,8 +1427,9 @@ do { \
#define LIBCALL_VALUE(MODE) \
gen_rtx_REG (MODE, \
((GET_MODE_CLASS (MODE) == MODE_FLOAT \
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) \
(((GET_MODE_CLASS (MODE) == MODE_FLOAT \
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT) && \
((MODE) != TFmode || INTEL_EXTENDED_IEEE_FORMAT)) \
? FR_RET_FIRST : GR_RET_FIRST))
/* A C expression that is nonzero if REGNO is the number of a hard register in
......
/* Subroutines for long double support.
Copyright (C) 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
In addition to the permissions in the GNU General Public License, the
Free Software Foundation gives you unlimited permission to link the
compiled version of this file into combinations with other programs,
and to distribute those combinations without any restriction coming
from the use of this file. (The General Public License restrictions
do apply in other respects; for example, they cover modification of
the file, and distribution when not linked into a combine
executable.)
GNU CC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
int _U_Qfcmp (long double a, long double b, int);
long _U_Qfcnvfxt_quad_to_sgl (long double);
int
_U_Qfeq (long double a, long double b)
{
return (_U_Qfcmp (a, b, 4) != 0);
}
int
_U_Qfne (long double a, long double b)
{
return (_U_Qfcmp (a, b, 4) == 0);
}
int
_U_Qfgt (long double a, long double b)
{
return (_U_Qfcmp (a, b, 17) != 0);
}
int
_U_Qfge (long double a, long double b)
{
return (_U_Qfcmp (a, b, 21) != 0);
}
int
_U_Qflt (long double a, long double b)
{
return (_U_Qfcmp (a, b, 9) != 0);
}
int
_U_Qfle (long double a, long double b)
{
return (_U_Qfcmp (a, b, 13) != 0);
}
int
_U_Qfcomp (long double a, long double b)
{
if (_U_Qfcmp (a, b, 4) == 0)
return 0;
return (_U_Qfcmp (a, b, 22) != 0 ? 1 : -1);
}
long double
_U_Qfneg (long double a)
{
return (0.0L - a);
}
# Support routines for HP-UX 128 bit floats.
LIB2FUNCS_EXTRA=quadlib.c
quadlib.c: $(srcdir)/config/ia64/quadlib.c
cat $(srcdir)/config/ia64/quadlib.c > quadlib.c
......@@ -95,9 +95,9 @@ netlib.att.com: netlib/cephes. */
The case LONG_DOUBLE_TYPE_SIZE = 128 activates TFmode support
and may deactivate XFmode since `long double' is used to refer
to both modes. Defining INTEL_EXTENDED_IEEE_FORMAT at the same
time enables 80387-style 80-bit floats in a 128-bit padded
image, as seen on IA-64.
to both modes. Defining INTEL_EXTENDED_IEEE_FORMAT to non-zero
at the same time enables 80387-style 80-bit floats in a 128-bit
padded image, as seen on IA-64.
The macros FLOAT_WORDS_BIG_ENDIAN, HOST_FLOAT_WORDS_BIG_ENDIAN,
contributed by Richard Earnshaw <Richard.Earnshaw@cl.cam.ac.uk>,
......@@ -247,7 +247,7 @@ unknown arithmetic type
in memory, with no holes. */
#if MAX_LONG_DOUBLE_TYPE_SIZE == 96 || \
(defined(INTEL_EXTENDED_IEEE_FORMAT) && MAX_LONG_DOUBLE_TYPE_SIZE == 128)
((INTEL_EXTENDED_IEEE_FORMAT != 0) && MAX_LONG_DOUBLE_TYPE_SIZE == 128)
/* Number of 16 bit words in external e type format */
# define NE 6
# define MAXDECEXP 4932
......@@ -407,7 +407,7 @@ static void emul PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *,
unsigned EMUSHORT *));
static void e53toe PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
static void e64toe PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
#ifndef INTEL_EXTENDED_IEEE_FORMAT
#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
static void e113toe PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
#endif
static void e24toe PARAMS ((unsigned EMUSHORT *, unsigned EMUSHORT *));
......@@ -441,7 +441,7 @@ static void etoasc PARAMS ((unsigned EMUSHORT *, char *, int));
static void asctoe24 PARAMS ((const char *, unsigned EMUSHORT *));
static void asctoe53 PARAMS ((const char *, unsigned EMUSHORT *));
static void asctoe64 PARAMS ((const char *, unsigned EMUSHORT *));
#ifndef INTEL_EXTENDED_IEEE_FORMAT
#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
static void asctoe113 PARAMS ((const char *, unsigned EMUSHORT *));
#endif
static void asctoe PARAMS ((const char *, unsigned EMUSHORT *));
......@@ -504,7 +504,7 @@ endian (e, x, mode)
switch (mode)
{
case TFmode:
#ifndef INTEL_EXTENDED_IEEE_FORMAT
#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
/* Swap halfwords in the fourth long. */
th = (unsigned long) e[6] & 0xffff;
t = (unsigned long) e[7] & 0xffff;
......@@ -548,7 +548,7 @@ endian (e, x, mode)
switch (mode)
{
case TFmode:
#ifndef INTEL_EXTENDED_IEEE_FORMAT
#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
/* Pack the fourth long. */
th = (unsigned long) e[7] & 0xffff;
t = (unsigned long) e[6] & 0xffff;
......@@ -749,7 +749,7 @@ ereal_atof (s, t)
break;
case TFmode:
#ifndef INTEL_EXTENDED_IEEE_FORMAT
#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
asctoe113 (s, tem);
e113toe (tem, e);
break;
......@@ -886,7 +886,7 @@ ereal_from_int (d, i, j, mode)
break;
case 128:
#ifndef INTEL_EXTENDED_IEEE_FORMAT
#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
etoe113 (dg, df);
e113toe (df, dg);
#else
......@@ -945,7 +945,7 @@ ereal_from_uint (d, i, j, mode)
break;
case 128:
#ifndef INTEL_EXTENDED_IEEE_FORMAT
#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
etoe113 (dg, df);
e113toe (df, dg);
#else
......@@ -1094,7 +1094,7 @@ real_value_truncate (mode, arg)
switch (mode)
{
case TFmode:
#ifndef INTEL_EXTENDED_IEEE_FORMAT
#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
etoe113 (e, t);
e113toe (t, t);
break;
......@@ -1513,7 +1513,7 @@ ereal_isneg (x)
/* e type constants used by high precision check routines */
#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && !defined(INTEL_EXTENDED_IEEE_FORMAT)
#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && (INTEL_EXTENDED_IEEE_FORMAT == 0)
/* 0.0 */
unsigned EMUSHORT ezero[NE] =
{0x0000, 0x0000, 0x0000, 0x0000,
......@@ -3331,7 +3331,7 @@ bigend_nan:
*q++ = *p++;
}
#ifndef INTEL_EXTENDED_IEEE_FORMAT
#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
/* Convert 128-bit long double precision float PE to e type Y. */
static void
......@@ -4587,7 +4587,7 @@ enormlz (x)
#define NTEN 12
#define MAXP 4096
#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && !defined(INTEL_EXTENDED_IEEE_FORMAT)
#if MAX_LONG_DOUBLE_TYPE_SIZE == 128 && (INTEL_EXTENDED_IEEE_FORMAT == 0)
static unsigned EMUSHORT etens[NTEN + 1][NE] =
{
{0x6576, 0x4a92, 0x804a, 0x153f,
......@@ -5107,7 +5107,7 @@ asctoe64 (s, y)
asctoeg (s, y, 64);
}
#ifndef INTEL_EXTENDED_IEEE_FORMAT
#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
/* Convert ASCII string S to 128-bit long double Y. */
static void
......@@ -6305,7 +6305,7 @@ make_nan (nan, sign, mode)
used like NaN's, but probably not in the same way as IEEE. */
#if !defined(DEC) && !defined(IBM) && !defined(C4X)
case TFmode:
#ifndef INTEL_EXTENDED_IEEE_FORMAT
#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
n = 8;
if (REAL_WORDS_BIG_ENDIAN)
p = TFbignan;
......@@ -6926,7 +6926,7 @@ switch (GET_MODE_BITSIZE (mode))
return 64;
case 128:
#ifndef INTEL_EXTENDED_IEEE_FORMAT
#if (INTEL_EXTENDED_IEEE_FORMAT == 0)
return 113;
#else
return 64;
......
......@@ -39,6 +39,10 @@ Boston, MA 02111-1307, USA. */
#define HOST_FLOAT_FORMAT IEEE_FLOAT_FORMAT
#endif
#ifndef INTEL_EXTENDED_IEEE_FORMAT
#define INTEL_EXTENDED_IEEE_FORMAT 0
#endif
#if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
#define REAL_INFINITY
#endif
......@@ -204,7 +208,7 @@ extern REAL_VALUE_TYPE ereal_from_double PARAMS ((HOST_WIDE_INT *));
ereal_from_uint (&d, lo, hi, mode)
/* IN is a REAL_VALUE_TYPE. OUT is an array of longs. */
#if defined(INTEL_EXTENDED_IEEE_FORMAT) && MAX_LONG_DOUBLE_TYPE_SIZE == 128
#if (INTEL_EXTENDED_IEEE_FORMAT != 0) && (MAX_LONG_DOUBLE_TYPE_SIZE == 128)
#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) (etarldouble ((IN), (OUT)))
#else
#define REAL_VALUE_TO_TARGET_LONG_DOUBLE(IN, OUT) \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment