mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-23 18:11:15 +08:00
dfp.h, dfp.c: New files.
2005-12-02 Jon Grimm <jgrimm2@us.ibm.com> Janis Johnson <janis187@us.ibm.com> David Edelsohn <dje@watson.ibm.com> Ben Elliston <bje@au.ibm.com> * dfp.h, dfp.c: New files. * Makefile.in (DECNUM, DECNUMINC, LIBDECNUMBER): New variables. (DECNUM_H): Likewise. (LIBDEPS, LIBS, BACKEND): Append $(LIBDECNUMBER). (INCLUDES): Append $(DECNUMINC). (OBJS-common): Add dfp.o. (dfp.o): New rule. * real.h (EXP_BITS): Pinch one bit to .. (struct real_value): Add decimal field. (real_format): Change table size, update documentation. (REAL_MODE_FORMAT): Update for to handle float, decimal float. (real_from_string3): Declare. (decimal_single_format): Declare. (decimal_double_format): Declare. (decimal_quad_format): Declare. (REAL_VALUE_TO_TARGET_DECIMAL32): New. (REAL_VALUE_TO_TARGET_DECIMAL64): New. (REAL_VALUE_TO_TARGET_DECIMAL128): New. * real.c: Include dfp.h. (normalize): Early return for decimal floats. (do_add): Zero decimal field. (do_compare): Call do_decimal_compare for decimal floats. (do_fix_trunc): Likewise, call decimal_do_fix_trunc. (real_arithmetic): Call decimal_real_arithmetic for decimal floating point operands. (real_identical): If a and b are of differing radix, return false. (real_to_integer): Call decimal_real_to_integer if the value is a decimal float. (real_to_integer2): Likewise, call decimal_real_to_integer2. (real_to_decimal): Likewise, call decimal_real_to_decimal. (real_to_hexadecimal): Place "N/A" in the return string for decimal float. (real_from_string3): New variant, given a mode. (real_maxval): Use decimal_real_maxval for decimal floats. (round_for_format): Use decimal_round_for_format for decimals. (real_convert): Use decimal_real_convert where appropriate. (significand_size): Handle base 10. (encode_decimal_single, decode_decimal_single, encode_decimal_double, decode_decimal_double, encode_decimal_quad, decode_decimal_quad): New functions. (decimal_single_format): New. (decimal_double_format): New. (decimal_quad_format): New. * machmode.def: Add SD, DD and TD decimal floating point modes. * machmode.h (FLOAT_MODE_P, SCALAR_FLOAT_MODE_P, MODES_WIDEN_P): Include MODE_DECIMAL_FLOAT. (DECIMAL_FLOAT_MODE_P): New. * mode-classes.def (MODE_DECIMAL_FLOAT): New mode class. * genmodes.c (struct mode_data): Add counter field. (struct mode_data): Update comment for format. (blank_mode): Initialise counter field. (new_mode): Increment counter field for each mode defined. (complete_mode): Handle MODE_DECIMAL_FLOAT, update check for mode using a format. (make_complex_modes): Handle modes containing `D'. (DECIMAL_FLOAT_MODE, FRACTIONAL_DECIMAL_FLOAT_MODE): New. (make_decimal_float_mode): New. (reset_float_format): Handle MODE_DECIMAL_FLOAT. (cmp_modes): Compare counter field if other characteristics similar. (emit_real_format_for_mode): Support formats for decimal floats. * doc/rtl.texi (Machine Modes): Document SD, DD and TDmodes. Document MODE_DECIMAL_FLOAT. Co-Authored-By: Ben Elliston <bje@au.ibm.com> Co-Authored-By: David Edelsohn <dje@watson.ibm.com> Co-Authored-By: Janis Johnson <janis187@us.ibm.com> From-SVN: r107861
This commit is contained in:
parent
8da15291d0
commit
909e225622
@ -1,3 +1,72 @@
|
||||
2005-12-02 Jon Grimm <jgrimm2@us.ibm.com>
|
||||
Janis Johnson <janis187@us.ibm.com>
|
||||
David Edelsohn <dje@watson.ibm.com>
|
||||
Ben Elliston <bje@au.ibm.com>
|
||||
|
||||
* dfp.h, dfp.c: New files.
|
||||
* Makefile.in (DECNUM, DECNUMINC, LIBDECNUMBER): New variables.
|
||||
(DECNUM_H): Likewise.
|
||||
(LIBDEPS, LIBS, BACKEND): Append $(LIBDECNUMBER).
|
||||
(INCLUDES): Append $(DECNUMINC).
|
||||
(OBJS-common): Add dfp.o.
|
||||
(dfp.o): New rule.
|
||||
* real.h (EXP_BITS): Pinch one bit to ..
|
||||
(struct real_value): Add decimal field.
|
||||
(real_format): Change table size, update documentation.
|
||||
(REAL_MODE_FORMAT): Update for to handle float, decimal float.
|
||||
(real_from_string3): Declare.
|
||||
(decimal_single_format): Declare.
|
||||
(decimal_double_format): Declare.
|
||||
(decimal_quad_format): Declare.
|
||||
(REAL_VALUE_TO_TARGET_DECIMAL32): New.
|
||||
(REAL_VALUE_TO_TARGET_DECIMAL64): New.
|
||||
(REAL_VALUE_TO_TARGET_DECIMAL128): New.
|
||||
* real.c: Include dfp.h.
|
||||
(normalize): Early return for decimal floats.
|
||||
(do_add): Zero decimal field.
|
||||
(do_compare): Call do_decimal_compare for decimal floats.
|
||||
(do_fix_trunc): Likewise, call decimal_do_fix_trunc.
|
||||
(real_arithmetic): Call decimal_real_arithmetic for decimal
|
||||
floating point operands.
|
||||
(real_identical): If a and b are of differing radix, return false.
|
||||
(real_to_integer): Call decimal_real_to_integer if the value is a
|
||||
decimal float.
|
||||
(real_to_integer2): Likewise, call decimal_real_to_integer2.
|
||||
(real_to_decimal): Likewise, call decimal_real_to_decimal.
|
||||
(real_to_hexadecimal): Place "N/A" in the return string for
|
||||
decimal float.
|
||||
(real_from_string3): New variant, given a mode.
|
||||
(real_maxval): Use decimal_real_maxval for decimal floats.
|
||||
(round_for_format): Use decimal_round_for_format for decimals.
|
||||
(real_convert): Use decimal_real_convert where appropriate.
|
||||
(significand_size): Handle base 10.
|
||||
(encode_decimal_single, decode_decimal_single,
|
||||
encode_decimal_double, decode_decimal_double, encode_decimal_quad,
|
||||
decode_decimal_quad): New functions.
|
||||
(decimal_single_format): New.
|
||||
(decimal_double_format): New.
|
||||
(decimal_quad_format): New.
|
||||
* machmode.def: Add SD, DD and TD decimal floating point modes.
|
||||
* machmode.h (FLOAT_MODE_P, SCALAR_FLOAT_MODE_P, MODES_WIDEN_P):
|
||||
Include MODE_DECIMAL_FLOAT.
|
||||
(DECIMAL_FLOAT_MODE_P): New.
|
||||
* mode-classes.def (MODE_DECIMAL_FLOAT): New mode class.
|
||||
* genmodes.c (struct mode_data): Add counter field.
|
||||
(struct mode_data): Update comment for format.
|
||||
(blank_mode): Initialise counter field.
|
||||
(new_mode): Increment counter field for each mode defined.
|
||||
(complete_mode): Handle MODE_DECIMAL_FLOAT, update check for mode
|
||||
using a format.
|
||||
(make_complex_modes): Handle modes containing `D'.
|
||||
(DECIMAL_FLOAT_MODE, FRACTIONAL_DECIMAL_FLOAT_MODE): New.
|
||||
(make_decimal_float_mode): New.
|
||||
(reset_float_format): Handle MODE_DECIMAL_FLOAT.
|
||||
(cmp_modes): Compare counter field if other characteristics
|
||||
similar.
|
||||
(emit_real_format_for_mode): Support formats for decimal floats.
|
||||
* doc/rtl.texi (Machine Modes): Document SD, DD and TDmodes.
|
||||
Document MODE_DECIMAL_FLOAT.
|
||||
|
||||
2005-12-02 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* simplify-rtx.c (simplify_plus_minus): Do simplify constants.
|
||||
|
@ -298,6 +298,11 @@ GMPINC = @GMPINC@
|
||||
CPPLIB = ../libcpp/libcpp.a
|
||||
CPPINC = -I$(srcdir)/../libcpp/include
|
||||
|
||||
# Where to find decNumber
|
||||
DECNUM = $(srcdir)/../libdecnumber
|
||||
DECNUMINC = -I$(DECNUM)
|
||||
LIBDECNUMBER = ../libdecnumber/libdecnumber.a
|
||||
|
||||
# Substitution type for target's getgroups 2nd arg.
|
||||
TARGET_GETGROUPS_T = @TARGET_GETGROUPS_T@
|
||||
|
||||
@ -766,6 +771,8 @@ SYSTEM_H = system.h hwint.h $(srcdir)/../include/libiberty.h
|
||||
PREDICT_H = predict.h predict.def
|
||||
CPPLIB_H = $(srcdir)/../libcpp/include/line-map.h \
|
||||
$(srcdir)/../libcpp/include/cpplib.h
|
||||
DECNUM_H = $(DECNUM)/decContext.h $(DECNUM)/decDPD.h $(DECNUM)/decNumber.h \
|
||||
$(DECNUM)/decimal32.h $(DECNUM)/decimal64.h $(DECNUM)/decimal128.h
|
||||
MKDEPS_H = $(srcdir)/../libcpp/include/mkdeps.h
|
||||
SYMTAB_H = $(srcdir)/../libcpp/include/symtab.h
|
||||
CPP_ID_DATA_H = $(CPPLIB_H) $(srcdir)/../libcpp/include/cpp-id-data.h
|
||||
@ -806,7 +813,7 @@ LIBIBERTY = ../libiberty/libiberty.a
|
||||
BUILD_LIBIBERTY = $(build_objdir)/libiberty/libiberty.a
|
||||
|
||||
# Dependencies on the intl and portability libraries.
|
||||
LIBDEPS= $(CPPLIB) $(LIBIBERTY) $(LIBINTL_DEP) $(LIBICONV_DEP)
|
||||
LIBDEPS= $(CPPLIB) $(LIBIBERTY) $(LIBINTL_DEP) $(LIBICONV_DEP) $(LIBDECNUMBER)
|
||||
|
||||
# Likewise, for use in the tools that must run on this machine
|
||||
# even if we are cross-building GCC.
|
||||
@ -814,7 +821,7 @@ BUILD_LIBDEPS= $(BUILD_LIBIBERTY)
|
||||
|
||||
# How to link with both our special library facilities
|
||||
# and the system's installed libraries.
|
||||
LIBS = @LIBS@ $(CPPLIB) $(LIBINTL) $(LIBICONV) $(LIBIBERTY)
|
||||
LIBS = @LIBS@ $(CPPLIB) $(LIBINTL) $(LIBICONV) $(LIBIBERTY) $(LIBDECNUMBER)
|
||||
|
||||
# Any system libraries needed just for GNAT.
|
||||
SYSLIBS = @GNAT_LIBEXC@
|
||||
@ -844,7 +851,7 @@ BUILD_VARRAY = build/varray.o
|
||||
# libintl.h will be found in ../intl if we are using the included libintl.
|
||||
INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
|
||||
-I$(srcdir)/../include @INCINTL@ \
|
||||
$(CPPINC) $(GMPINC)
|
||||
$(CPPINC) $(GMPINC) $(DECNUMINC)
|
||||
|
||||
.c.o:
|
||||
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $< $(OUTPUT_OPTION)
|
||||
@ -963,7 +970,7 @@ OBJS-common = \
|
||||
cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o \
|
||||
cfgrtl.o combine.o conflict.o convert.o coverage.o cse.o cselib.o \
|
||||
dbxout.o ddg.o tree-ssa-loop-ch.o loop-invariant.o tree-ssa-loop-im.o \
|
||||
debug.o df.o diagnostic.o dojump.o dominance.o loop-doloop.o \
|
||||
debug.o df.o dfp.o diagnostic.o dojump.o dominance.o loop-doloop.o \
|
||||
dwarf2asm.o dwarf2out.o emit-rtl.o except.o explow.o loop-iv.o \
|
||||
expmed.o expr.o final.o flow.o fold-const.o function.o gcse.o \
|
||||
genrtl.o ggc-common.o global.o graph.o gtype-desc.o \
|
||||
@ -997,7 +1004,7 @@ OBJS = $(OBJS-common) $(out_object_file) $(OBJS-archive)
|
||||
|
||||
OBJS-onestep = libbackend.o $(OBJS-archive)
|
||||
|
||||
BACKEND = main.o @TREEBROWSER@ libbackend.a $(CPPLIB)
|
||||
BACKEND = main.o @TREEBROWSER@ libbackend.a $(CPPLIB) $(LIBDECNUMBER)
|
||||
|
||||
# Files to be copied after each stage in building.
|
||||
STAGECOPYSTUFF = insn-flags.h insn-config.h insn-codes.h \
|
||||
@ -2146,6 +2153,8 @@ emit-rtl.o : emit-rtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
$(HASHTAB_H) $(TM_P_H) debug.h langhooks.h tree-pass.h gt-emit-rtl.h
|
||||
real.o : real.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
|
||||
toplev.h $(TM_P_H) real.h
|
||||
dfp.o : dfp.c dfp.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
|
||||
toplev.h $(TM_P_H) real.h $(DECNUM_H)
|
||||
integrate.o : integrate.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
|
||||
$(RTL_H) $(TREE_H) $(FLAGS_H) debug.h $(INTEGRATE_H) insn-config.h \
|
||||
$(EXPR_H) real.h $(REGS_H) intl.h function.h output.h $(RECOG_H) \
|
||||
|
725
gcc/dfp.c
Normal file
725
gcc/dfp.c
Normal file
@ -0,0 +1,725 @@
|
||||
/* Decimal floating point support.
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC 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.
|
||||
|
||||
GCC 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 GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "tree.h"
|
||||
#include "toplev.h"
|
||||
#include "real.h"
|
||||
#include "tm_p.h"
|
||||
#include "dfp.h"
|
||||
|
||||
/* The order of the following headers is important for making sure
|
||||
decNumber structure is large enough to hold decimal128 digits. */
|
||||
|
||||
#include "decimal128.h"
|
||||
#include "decimal64.h"
|
||||
#include "decimal32.h"
|
||||
#include "decNumber.h"
|
||||
|
||||
static unsigned long
|
||||
dfp_byte_swap (unsigned long in)
|
||||
{
|
||||
unsigned long out;
|
||||
unsigned char *p = (unsigned char *) &out;
|
||||
union {
|
||||
unsigned long i;
|
||||
unsigned char b[4];
|
||||
} u;
|
||||
|
||||
u.i = in;
|
||||
p[0] = u.b[3];
|
||||
p[1] = u.b[2];
|
||||
p[2] = u.b[1];
|
||||
p[3] = u.b[0];
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Initialize R (a real with the decimal flag set) from DN. Can
|
||||
utilize status passed in via CONTEXT, if a previous operation had
|
||||
interesting status. */
|
||||
|
||||
static void
|
||||
decimal_from_decnumber (REAL_VALUE_TYPE *r, decNumber *dn, decContext *context)
|
||||
{
|
||||
memset (r, 0, sizeof (REAL_VALUE_TYPE));
|
||||
|
||||
r->cl = rvc_normal;
|
||||
if (decNumberIsZero (dn))
|
||||
r->cl = rvc_zero;
|
||||
if (decNumberIsNaN (dn))
|
||||
r->cl = rvc_nan;
|
||||
if (decNumberIsInfinite (dn))
|
||||
r->cl = rvc_inf;
|
||||
if (context->status & DEC_Overflow)
|
||||
r->cl = rvc_inf;
|
||||
if (decNumberIsNegative (dn))
|
||||
r->sign = 1;
|
||||
r->decimal = 1;
|
||||
|
||||
if (r->cl != rvc_normal)
|
||||
return;
|
||||
|
||||
decContextDefault (context, DEC_INIT_DECIMAL128);
|
||||
context->traps = 0;
|
||||
|
||||
decimal128FromNumber ((decimal128 *) r->sig, dn, context);
|
||||
}
|
||||
|
||||
/* Create decimal encoded R from string S. */
|
||||
|
||||
void
|
||||
decimal_real_from_string (REAL_VALUE_TYPE *r, const char *s)
|
||||
{
|
||||
decNumber dn;
|
||||
decContext set;
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
|
||||
decNumberFromString (&dn, (char *) s, &set);
|
||||
|
||||
/* It would be more efficient to store directly in decNumber format,
|
||||
but that is impractical from current data structure size.
|
||||
Encoding as a decimal128 is much more compact. */
|
||||
decimal_from_decnumber (r, &dn, &set);
|
||||
}
|
||||
|
||||
/* Initialize a decNumber from a REAL_VALUE_TYPE. */
|
||||
|
||||
static void
|
||||
decimal_to_decnumber (const REAL_VALUE_TYPE *r, decNumber *dn)
|
||||
{
|
||||
decContext set;
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
|
||||
switch (r->cl)
|
||||
{
|
||||
case rvc_zero:
|
||||
decNumberZero (dn);
|
||||
break;
|
||||
case rvc_inf:
|
||||
decNumberFromString (dn, (char *)"Infinity", &set);
|
||||
break;
|
||||
case rvc_nan:
|
||||
if (r->signalling)
|
||||
decNumberFromString (dn, (char *)"snan", &set);
|
||||
else
|
||||
decNumberFromString (dn, (char *)"nan", &set);
|
||||
break;
|
||||
case rvc_normal:
|
||||
gcc_assert (r->decimal);
|
||||
decimal128ToNumber ((decimal128 *) r->sig, dn);
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* Fix up sign bit. */
|
||||
if (r->sign != decNumberIsNegative (dn))
|
||||
decNumberNegate (dn);
|
||||
}
|
||||
|
||||
/* Encode a real into an IEEE 754R decimal32 type. */
|
||||
|
||||
void
|
||||
encode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
||||
long *buf, const REAL_VALUE_TYPE *r)
|
||||
{
|
||||
decNumber dn;
|
||||
decimal32 d32;
|
||||
decContext set;
|
||||
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
|
||||
decimal_to_decnumber (r, &dn);
|
||||
decimal32FromNumber (&d32, &dn, &set);
|
||||
|
||||
if (FLOAT_WORDS_BIG_ENDIAN)
|
||||
buf[0] = *(uint32_t *) d32.bytes;
|
||||
else
|
||||
buf[0] = dfp_byte_swap (*(uint32_t *) d32.bytes);
|
||||
}
|
||||
|
||||
/* Decode an IEEE 754R decimal32 type into a real. */
|
||||
|
||||
void decode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
||||
REAL_VALUE_TYPE *r, const long *buf)
|
||||
{
|
||||
decNumber dn;
|
||||
decimal32 d32;
|
||||
decContext set;
|
||||
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
|
||||
if (FLOAT_WORDS_BIG_ENDIAN)
|
||||
*((uint32_t *) d32.bytes) = (uint32_t) buf[0];
|
||||
else
|
||||
*((uint32_t *) d32.bytes) = dfp_byte_swap ((uint32_t) buf[0]);
|
||||
|
||||
decimal32ToNumber (&d32, &dn);
|
||||
decimal_from_decnumber (r, &dn, &set);
|
||||
}
|
||||
|
||||
/* Encode a real into an IEEE 754R decimal64 type. */
|
||||
|
||||
void
|
||||
encode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
||||
long *buf, const REAL_VALUE_TYPE *r)
|
||||
{
|
||||
decNumber dn;
|
||||
decimal64 d64;
|
||||
decContext set;
|
||||
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
|
||||
decimal_to_decnumber (r, &dn);
|
||||
decimal64FromNumber (&d64, &dn, &set);
|
||||
|
||||
if (FLOAT_WORDS_BIG_ENDIAN)
|
||||
{
|
||||
buf[0] = *(uint32_t *) &d64.bytes[0];
|
||||
buf[1] = *(uint32_t *) &d64.bytes[4];
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[1] = dfp_byte_swap (*(uint32_t *) &d64.bytes[0]);
|
||||
buf[0] = dfp_byte_swap (*(uint32_t *) &d64.bytes[4]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Decode an IEEE 754R decimal64 type into a real. */
|
||||
|
||||
void
|
||||
decode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
||||
REAL_VALUE_TYPE *r, const long *buf)
|
||||
{
|
||||
decNumber dn;
|
||||
decimal64 d64;
|
||||
decContext set;
|
||||
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
|
||||
if (FLOAT_WORDS_BIG_ENDIAN)
|
||||
{
|
||||
*((uint32_t *) &d64.bytes[0]) = (uint32_t) buf[0];
|
||||
*((uint32_t *) &d64.bytes[4]) = (uint32_t) buf[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
*((uint32_t *) &d64.bytes[0]) = dfp_byte_swap ((uint32_t) buf[1]);
|
||||
*((uint32_t *) &d64.bytes[4]) = dfp_byte_swap ((uint32_t) buf[0]);
|
||||
}
|
||||
|
||||
decimal64ToNumber (&d64, &dn);
|
||||
decimal_from_decnumber (r, &dn, &set);
|
||||
}
|
||||
|
||||
/* Encode a real into an IEEE 754R decimal128 type. */
|
||||
|
||||
void
|
||||
encode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
||||
long *buf, const REAL_VALUE_TYPE *r)
|
||||
{
|
||||
decNumber dn;
|
||||
decContext set;
|
||||
decimal128 d128;
|
||||
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
|
||||
decimal_to_decnumber (r, &dn);
|
||||
decimal128FromNumber (&d128, &dn, &set);
|
||||
|
||||
if (FLOAT_WORDS_BIG_ENDIAN)
|
||||
{
|
||||
buf[0] = *(uint32_t *) &d128.bytes[0];
|
||||
buf[1] = *(uint32_t *) &d128.bytes[4];
|
||||
buf[2] = *(uint32_t *) &d128.bytes[8];
|
||||
buf[3] = *(uint32_t *) &d128.bytes[12];
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[0] = dfp_byte_swap (*(uint32_t *) &d128.bytes[12]);
|
||||
buf[1] = dfp_byte_swap (*(uint32_t *) &d128.bytes[8]);
|
||||
buf[2] = dfp_byte_swap (*(uint32_t *) &d128.bytes[4]);
|
||||
buf[3] = dfp_byte_swap (*(uint32_t *) &d128.bytes[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Decode an IEEE 754R decimal128 type into a real. */
|
||||
|
||||
void
|
||||
decode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
||||
REAL_VALUE_TYPE *r, const long *buf)
|
||||
{
|
||||
decNumber dn;
|
||||
decimal128 d128;
|
||||
decContext set;
|
||||
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
|
||||
if (FLOAT_WORDS_BIG_ENDIAN)
|
||||
{
|
||||
*((uint32_t *) &d128.bytes[0]) = (uint32_t) buf[0];
|
||||
*((uint32_t *) &d128.bytes[4]) = (uint32_t) buf[1];
|
||||
*((uint32_t *) &d128.bytes[8]) = (uint32_t) buf[2];
|
||||
*((uint32_t *) &d128.bytes[12]) = (uint32_t) buf[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
*((uint32_t *) &d128.bytes[0]) = dfp_byte_swap ((uint32_t) buf[3]);
|
||||
*((uint32_t *) &d128.bytes[4]) = dfp_byte_swap ((uint32_t) buf[2]);
|
||||
*((uint32_t *) &d128.bytes[8]) = dfp_byte_swap ((uint32_t) buf[1]);
|
||||
*((uint32_t *) &d128.bytes[12]) = dfp_byte_swap ((uint32_t) buf[0]);
|
||||
}
|
||||
|
||||
decimal128ToNumber (&d128, &dn);
|
||||
decimal_from_decnumber (r, &dn, &set);
|
||||
}
|
||||
|
||||
/* Helper function to convert from a binary real internal
|
||||
representation. */
|
||||
|
||||
static void
|
||||
decimal_to_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from,
|
||||
enum machine_mode mode)
|
||||
{
|
||||
char string[256];
|
||||
decimal128 *d128;
|
||||
d128 = (decimal128 *) from->sig;
|
||||
|
||||
decimal128ToString (d128, string);
|
||||
real_from_string3 (to, string, mode);
|
||||
}
|
||||
|
||||
|
||||
/* Helper function to convert from a binary real internal
|
||||
representation. */
|
||||
|
||||
static void
|
||||
decimal_from_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from)
|
||||
{
|
||||
char string[256];
|
||||
|
||||
/* We convert to string, then to decNumber then to decimal128. */
|
||||
real_to_decimal (string, from, sizeof (string), 0, 1);
|
||||
decimal_real_from_string (to, string);
|
||||
}
|
||||
|
||||
/* Helper function to real.c:do_compare() to handle decimal internal
|
||||
represenation including when one of the operands is still in the
|
||||
binary internal representation. */
|
||||
|
||||
int
|
||||
decimal_do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b,
|
||||
int nan_result)
|
||||
{
|
||||
decContext set;
|
||||
decNumber dn, dn2, dn3;
|
||||
REAL_VALUE_TYPE a1, b1;
|
||||
|
||||
/* If either operand is non-decimal, create temporary versions. */
|
||||
if (!a->decimal)
|
||||
{
|
||||
decimal_from_binary (&a1, a);
|
||||
a = &a1;
|
||||
}
|
||||
if (!b->decimal)
|
||||
{
|
||||
decimal_from_binary (&b1, b);
|
||||
b = &b1;
|
||||
}
|
||||
|
||||
/* Convert into decNumber form for comparison operation. */
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
decimal128ToNumber ((decimal128 *) a->sig, &dn2);
|
||||
decimal128ToNumber ((decimal128 *) b->sig, &dn3);
|
||||
|
||||
/* Finally, do the comparison. */
|
||||
decNumberCompare (&dn, &dn2, &dn3, &set);
|
||||
|
||||
/* Return the comparison result. */
|
||||
if (decNumberIsNaN (&dn))
|
||||
return nan_result;
|
||||
else if (decNumberIsZero (&dn))
|
||||
return 0;
|
||||
else if (decNumberIsNegative (&dn))
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Helper to round_for_format, handling decimal float types. */
|
||||
|
||||
void
|
||||
decimal_round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
|
||||
{
|
||||
decNumber dn;
|
||||
decContext set;
|
||||
|
||||
/* Real encoding occurs later. */
|
||||
if (r->cl != rvc_normal)
|
||||
return;
|
||||
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
decimal128ToNumber ((decimal128 *) r->sig, &dn);
|
||||
|
||||
if (fmt == &decimal_quad_format)
|
||||
{
|
||||
/* The internal format is already in this format. */
|
||||
return;
|
||||
}
|
||||
else if (fmt == &decimal_single_format)
|
||||
{
|
||||
decimal32 d32;
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL32);
|
||||
set.traps = 0;
|
||||
|
||||
decimal32FromNumber (&d32, &dn, &set);
|
||||
decimal32ToNumber (&d32, &dn);
|
||||
}
|
||||
else if (fmt == &decimal_double_format)
|
||||
{
|
||||
decimal64 d64;
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL64);
|
||||
set.traps = 0;
|
||||
|
||||
decimal64FromNumber (&d64, &dn, &set);
|
||||
decimal64ToNumber (&d64, &dn);
|
||||
}
|
||||
else
|
||||
gcc_unreachable ();
|
||||
|
||||
decimal_from_decnumber (r, &dn, &set);
|
||||
}
|
||||
|
||||
/* Extend or truncate to a new mode. Handles conversions between
|
||||
binary and decimal types. */
|
||||
|
||||
void
|
||||
decimal_real_convert (REAL_VALUE_TYPE *r, enum machine_mode mode,
|
||||
const REAL_VALUE_TYPE *a)
|
||||
{
|
||||
const struct real_format *fmt = REAL_MODE_FORMAT (mode);
|
||||
|
||||
if (a->decimal && fmt->b == 10)
|
||||
return;
|
||||
if (a->decimal)
|
||||
decimal_to_binary (r, a, mode);
|
||||
else
|
||||
decimal_from_binary (r, a);
|
||||
}
|
||||
|
||||
/* Render R_ORIG as a decimal floating point constant. Emit DIGITS
|
||||
significant digits in the result, bounded by BUF_SIZE. If DIGITS
|
||||
is 0, choose the maximum for the representation. If
|
||||
CROP_TRAILING_ZEROS, strip trailing zeros. Currently, not honoring
|
||||
DIGITS or CROP_TRAILING_ZEROS. */
|
||||
|
||||
void decimal_real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig,
|
||||
size_t buf_size,
|
||||
size_t digits ATTRIBUTE_UNUSED,
|
||||
int crop_trailing_zeros ATTRIBUTE_UNUSED)
|
||||
{
|
||||
decimal128 *d128 = (decimal128*) r_orig->sig;
|
||||
|
||||
/* decimal128ToString requires space for at least 24 characters;
|
||||
Require two more for suffix. */
|
||||
gcc_assert (buf_size >= 24);
|
||||
decimal128ToString (d128, str);
|
||||
}
|
||||
|
||||
static bool
|
||||
decimal_do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0,
|
||||
const REAL_VALUE_TYPE *op1, int subtract_p)
|
||||
{
|
||||
decNumber dn;
|
||||
decContext set;
|
||||
decNumber dn2, dn3;
|
||||
|
||||
decimal_to_decnumber (op0, &dn2);
|
||||
decimal_to_decnumber (op1, &dn3);
|
||||
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
|
||||
if (subtract_p)
|
||||
decNumberSubtract (&dn, &dn2, &dn3, &set);
|
||||
else
|
||||
decNumberAdd (&dn, &dn2, &dn3, &set);
|
||||
|
||||
decimal_from_decnumber (r, &dn, &set);
|
||||
|
||||
/* Return true, if inexact. */
|
||||
return (set.status & DEC_Inexact);
|
||||
}
|
||||
|
||||
/* Compute R = OP0 * OP1. */
|
||||
|
||||
static bool
|
||||
decimal_do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0,
|
||||
const REAL_VALUE_TYPE *op1)
|
||||
{
|
||||
decContext set;
|
||||
decNumber dn, dn2, dn3;
|
||||
|
||||
decimal_to_decnumber (op0, &dn2);
|
||||
decimal_to_decnumber (op1, &dn3);
|
||||
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
|
||||
decNumberMultiply (&dn, &dn2, &dn3, &set);
|
||||
decimal_from_decnumber (r, &dn, &set);
|
||||
|
||||
/* Return true, if inexact. */
|
||||
return (set.status & DEC_Inexact);
|
||||
}
|
||||
|
||||
/* Compute R = OP0 / OP1. */
|
||||
|
||||
static bool
|
||||
decimal_do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0,
|
||||
const REAL_VALUE_TYPE *op1)
|
||||
{
|
||||
decContext set;
|
||||
decNumber dn, dn2, dn3;
|
||||
|
||||
decimal_to_decnumber (op0, &dn2);
|
||||
decimal_to_decnumber (op1, &dn3);
|
||||
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
|
||||
decNumberDivide (&dn, &dn2, &dn3, &set);
|
||||
decimal_from_decnumber (r, &dn, &set);
|
||||
|
||||
/* Return true, if inexact. */
|
||||
return (set.status & DEC_Inexact);
|
||||
}
|
||||
|
||||
/* Set R to A truncated to an integral value toward zero (decimal
|
||||
floating point). */
|
||||
|
||||
void
|
||||
decimal_do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
|
||||
{
|
||||
decNumber dn, dn2;
|
||||
decContext set;
|
||||
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
set.round = DEC_ROUND_DOWN;
|
||||
decimal128ToNumber ((decimal128 *) a->sig, &dn2);
|
||||
|
||||
decNumberToIntegralValue (&dn, &dn2, &set);
|
||||
decimal_from_decnumber (r, &dn, &set);
|
||||
}
|
||||
|
||||
/* Render decimal float value R as an integer. */
|
||||
|
||||
HOST_WIDE_INT
|
||||
decimal_real_to_integer (const REAL_VALUE_TYPE *r)
|
||||
{
|
||||
decContext set;
|
||||
decNumber dn, dn2, dn3;
|
||||
REAL_VALUE_TYPE to;
|
||||
char string[256];
|
||||
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
set.round = DEC_ROUND_DOWN;
|
||||
decimal128ToNumber ((decimal128 *) r->sig, &dn);
|
||||
|
||||
decNumberToIntegralValue (&dn2, &dn, &set);
|
||||
decNumberZero (&dn3);
|
||||
decNumberRescale (&dn, &dn2, &dn3, &set);
|
||||
|
||||
/* Convert to REAL_VALUE_TYPE and call appropriate conversion
|
||||
function. */
|
||||
decNumberToString (&dn, string);
|
||||
real_from_string (&to, string);
|
||||
return real_to_integer (&to);
|
||||
}
|
||||
|
||||
/* Likewise, but to an integer pair, HI+LOW. */
|
||||
|
||||
void
|
||||
decimal_real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh,
|
||||
const REAL_VALUE_TYPE *r)
|
||||
{
|
||||
decContext set;
|
||||
decNumber dn, dn2, dn3;
|
||||
REAL_VALUE_TYPE to;
|
||||
char string[256];
|
||||
|
||||
decContextDefault (&set, DEC_INIT_DECIMAL128);
|
||||
set.traps = 0;
|
||||
set.round = DEC_ROUND_DOWN;
|
||||
decimal128ToNumber ((decimal128 *) r->sig, &dn);
|
||||
|
||||
decNumberToIntegralValue (&dn2, &dn, &set);
|
||||
decNumberZero (&dn3);
|
||||
decNumberRescale (&dn, &dn2, &dn3, &set);
|
||||
|
||||
/* Conver to REAL_VALUE_TYPE and call appropriate conversion
|
||||
function. */
|
||||
decNumberToString (&dn, string);
|
||||
real_from_string (&to, string);
|
||||
real_to_integer2 (plow, phigh, &to);
|
||||
}
|
||||
|
||||
/* Perform the decimal floating point operation described by COODE.
|
||||
For a unary operation, leave OP1 NULL. This function returns true
|
||||
if the result may be inexact due to loss of precision. */
|
||||
|
||||
bool
|
||||
decimal_real_arithmetic (REAL_VALUE_TYPE *r, int icode,
|
||||
const REAL_VALUE_TYPE *op0,
|
||||
const REAL_VALUE_TYPE *op1)
|
||||
{
|
||||
enum tree_code code = icode;
|
||||
REAL_VALUE_TYPE a1;
|
||||
REAL_VALUE_TYPE b1;
|
||||
|
||||
/* If either op is not a decimal, create a temporary decimal
|
||||
versions. */
|
||||
if (!op0->decimal)
|
||||
{
|
||||
decimal_from_binary (&a1, op0);
|
||||
op0 = &a1;
|
||||
}
|
||||
if (op1 && !op1->decimal)
|
||||
{
|
||||
decimal_from_binary (&b1, op1);
|
||||
op1 = &b1;
|
||||
}
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case PLUS_EXPR:
|
||||
(void) decimal_do_add (r, op0, op1, 0);
|
||||
break;
|
||||
|
||||
case MINUS_EXPR:
|
||||
(void) decimal_do_add (r, op0, op1, 1);
|
||||
break;
|
||||
|
||||
case MULT_EXPR:
|
||||
(void) decimal_do_multiply (r, op0, op1);
|
||||
break;
|
||||
|
||||
case RDIV_EXPR:
|
||||
(void) decimal_do_divide (r, op0, op1);
|
||||
break;
|
||||
|
||||
case MIN_EXPR:
|
||||
if (op1->cl == rvc_nan)
|
||||
*r = *op1;
|
||||
else if (real_compare (UNLT_EXPR, op0, op1))
|
||||
*r = *op0;
|
||||
else
|
||||
*r = *op1;
|
||||
break;
|
||||
|
||||
case MAX_EXPR:
|
||||
if (op1->cl == rvc_nan)
|
||||
*r = *op1;
|
||||
else if (real_compare (LT_EXPR, op0, op1))
|
||||
*r = *op1;
|
||||
else
|
||||
*r = *op0;
|
||||
break;
|
||||
|
||||
case NEGATE_EXPR:
|
||||
{
|
||||
decimal128 *d128;
|
||||
*r = *op0;
|
||||
d128 = (decimal128 *) r->sig;
|
||||
/* Flip high bit. */
|
||||
d128->bytes[0] ^= 1 << 7;
|
||||
/* Keep sign field in sync. */
|
||||
r->sign ^= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ABS_EXPR:
|
||||
{
|
||||
decimal128 *d128;
|
||||
*r = *op0;
|
||||
d128 = (decimal128 *) r->sig;
|
||||
/* Clear high bit. */
|
||||
d128->bytes[0] &= 0x7f;
|
||||
/* Keep sign field in sync. */
|
||||
r->sign = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case FIX_TRUNC_EXPR:
|
||||
decimal_do_fix_trunc (r, op0);
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* FIXME: Indicate all operations as inexact for now due to unknown
|
||||
working precision. */
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Fills R with the largest finite value representable in mode MODE.
|
||||
If SIGN is nonzero, R is set to the most negative finite value. */
|
||||
|
||||
void
|
||||
decimal_real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode)
|
||||
{
|
||||
char *max;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case SDmode:
|
||||
max = (char *) "9.999999E96";
|
||||
break;
|
||||
case DDmode:
|
||||
max = (char *) "9.999999999999999E384";
|
||||
break;
|
||||
case TDmode:
|
||||
max = (char *) "9.999999999999999999999999999999999E6144";
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
decimal_real_from_string (r, max);
|
||||
if (sign)
|
||||
r->sig[0] |= 0x80000000;
|
||||
}
|
47
gcc/dfp.h
Normal file
47
gcc/dfp.h
Normal file
@ -0,0 +1,47 @@
|
||||
/* Decimal floating point support functions for GNU compiler.
|
||||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC 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.
|
||||
|
||||
GCC 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 GCC; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
02110-1301, USA. */
|
||||
|
||||
#ifndef GCC_DFP_H
|
||||
#define GCC_DFP_H
|
||||
|
||||
/* Encode REAL_VALUE_TYPEs into 32/64/128-bit IEEE 754R encoded values. */
|
||||
void encode_decimal32 (const struct real_format *fmt, long *, const REAL_VALUE_TYPE *);
|
||||
void encode_decimal64 (const struct real_format *fmt, long *, const REAL_VALUE_TYPE *);
|
||||
void decode_decimal128 (const struct real_format *, REAL_VALUE_TYPE *, const long *);
|
||||
|
||||
/* Decode 32/64/128-bit IEEE 754R encoded values into REAL_VALUE_TYPEs. */
|
||||
void decode_decimal32 (const struct real_format *, REAL_VALUE_TYPE *, const long *);
|
||||
void decode_decimal64 (const struct real_format *, REAL_VALUE_TYPE *, const long *);
|
||||
void encode_decimal128 (const struct real_format *fmt, long *, const REAL_VALUE_TYPE *);
|
||||
|
||||
/* Arithmetic and conversion functions. */
|
||||
int decimal_do_compare (const REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *, int);
|
||||
void decimal_real_from_string (REAL_VALUE_TYPE *, const char *);
|
||||
void decimal_round_for_format (const struct real_format *, REAL_VALUE_TYPE *);
|
||||
void decimal_real_convert (REAL_VALUE_TYPE *, enum machine_mode, const REAL_VALUE_TYPE *);
|
||||
void decimal_real_to_decimal (char *, const REAL_VALUE_TYPE *, size_t, size_t, int);
|
||||
void decimal_do_fix_trunc (REAL_VALUE_TYPE *, const REAL_VALUE_TYPE *);
|
||||
bool decimal_real_arithmetic (REAL_VALUE_TYPE *, int, const REAL_VALUE_TYPE *,
|
||||
const REAL_VALUE_TYPE *);
|
||||
void decimal_real_maxval (REAL_VALUE_TYPE *, int, enum machine_mode);
|
||||
void decimal_real_to_integer2 (HOST_WIDE_INT *, HOST_WIDE_INT *, const REAL_VALUE_TYPE *);
|
||||
HOST_WIDE_INT decimal_real_to_integer (const REAL_VALUE_TYPE *);
|
||||
|
||||
#endif /* GCC_DFP_H */
|
@ -60,7 +60,7 @@ struct mode_data
|
||||
unsigned int bytesize; /* storage size in addressable units */
|
||||
unsigned int ncomponents; /* number of subunits */
|
||||
unsigned int alignment; /* mode alignment */
|
||||
const char *format; /* floating point format - MODE_FLOAT only */
|
||||
const char *format; /* floating point format - float modes only */
|
||||
|
||||
struct mode_data *component; /* mode of components */
|
||||
struct mode_data *wider; /* next wider mode */
|
||||
@ -72,6 +72,7 @@ struct mode_data
|
||||
|
||||
const char *file; /* file and line of definition, */
|
||||
unsigned int line; /* for error reporting */
|
||||
unsigned int counter; /* Rank ordering of modes */
|
||||
};
|
||||
|
||||
static struct mode_data *modes[MAX_MODE_CLASS];
|
||||
@ -82,7 +83,7 @@ static const struct mode_data blank_mode = {
|
||||
0, "<unknown>", MAX_MODE_CLASS,
|
||||
-1U, -1U, -1U, -1U,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
"<unknown>", 0
|
||||
"<unknown>", 0, 0
|
||||
};
|
||||
|
||||
static htab_t modes_by_name;
|
||||
@ -146,6 +147,7 @@ new_mode (enum mode_class cl, const char *name,
|
||||
const char *file, unsigned int line)
|
||||
{
|
||||
struct mode_data *m;
|
||||
static unsigned int count = 0;
|
||||
|
||||
m = find_mode (name);
|
||||
if (m)
|
||||
@ -163,6 +165,7 @@ new_mode (enum mode_class cl, const char *name,
|
||||
if (file)
|
||||
m->file = trim_filename (file);
|
||||
m->line = line;
|
||||
m->counter = count++;
|
||||
|
||||
m->next = modes[cl];
|
||||
modes[cl] = m;
|
||||
@ -323,11 +326,12 @@ complete_mode (struct mode_data *m)
|
||||
|
||||
case MODE_INT:
|
||||
case MODE_FLOAT:
|
||||
case MODE_DECIMAL_FLOAT:
|
||||
/* A scalar mode must have a byte size, may have a bit size,
|
||||
and must not have components. A float mode must have a
|
||||
format. */
|
||||
validate_mode (m, OPTIONAL, SET, UNSET, UNSET,
|
||||
m->cl == MODE_FLOAT ? SET : UNSET);
|
||||
m->cl != MODE_INT ? SET : UNSET);
|
||||
|
||||
m->ncomponents = 1;
|
||||
m->component = 0;
|
||||
@ -429,17 +433,22 @@ make_complex_modes (enum mode_class cl,
|
||||
This inconsistency should be eliminated. */
|
||||
if (cl == MODE_FLOAT)
|
||||
{
|
||||
char *p;
|
||||
char *p, *q = 0;
|
||||
strncpy (buf, m->name, sizeof buf);
|
||||
p = strchr (buf, 'F');
|
||||
if (p == 0)
|
||||
q = strchr (buf, 'D');
|
||||
if (p == 0 && q == 0)
|
||||
{
|
||||
error ("%s:%d: float mode \"%s\" has no 'F'",
|
||||
error ("%s:%d: float mode \"%s\" has no 'F' or 'D'",
|
||||
m->file, m->line, m->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
*p = 'C';
|
||||
if (p != 0)
|
||||
*p = 'C';
|
||||
else
|
||||
snprintf (buf, sizeof buf, "C%s", m->name);
|
||||
}
|
||||
else
|
||||
snprintf (buf, sizeof buf, "C%s", m->name);
|
||||
@ -540,6 +549,23 @@ make_float_mode (const char *name,
|
||||
m->format = format;
|
||||
}
|
||||
|
||||
#define DECIMAL_FLOAT_MODE(N, Y, F) \
|
||||
FRACTIONAL_DECIMAL_FLOAT_MODE (N, -1U, Y, F)
|
||||
#define FRACTIONAL_DECIMAL_FLOAT_MODE(N, B, Y, F) \
|
||||
make_decimal_float_mode (#N, B, Y, #F, __FILE__, __LINE__)
|
||||
|
||||
static void
|
||||
make_decimal_float_mode (const char *name,
|
||||
unsigned int precision, unsigned int bytesize,
|
||||
const char *format,
|
||||
const char *file, unsigned int line)
|
||||
{
|
||||
struct mode_data *m = new_mode (MODE_DECIMAL_FLOAT, name, file, line);
|
||||
m->bytesize = bytesize;
|
||||
m->precision = precision;
|
||||
m->format = format;
|
||||
}
|
||||
|
||||
#define RESET_FLOAT_FORMAT(N, F) \
|
||||
reset_float_format (#N, #F, __FILE__, __LINE__)
|
||||
static void ATTRIBUTE_UNUSED
|
||||
@ -552,9 +578,9 @@ reset_float_format (const char *name, const char *format,
|
||||
error ("%s:%d: no mode \"%s\"", file, line, name);
|
||||
return;
|
||||
}
|
||||
if (m->cl != MODE_FLOAT)
|
||||
if (m->cl != MODE_FLOAT && m->cl != MODE_DECIMAL_FLOAT)
|
||||
{
|
||||
error ("%s:%d: mode \"%s\" is not class FLOAT", file, line, name);
|
||||
error ("%s:%d: mode \"%s\" is not a FLOAT class", file, line, name);
|
||||
return;
|
||||
}
|
||||
m->format = format;
|
||||
@ -675,7 +701,12 @@ cmp_modes (const void *a, const void *b)
|
||||
return -1;
|
||||
|
||||
if (!m->component && !n->component)
|
||||
return 0;
|
||||
{
|
||||
if (m->counter < n->counter)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (m->component->bytesize > n->component->bytesize)
|
||||
return 1;
|
||||
@ -687,7 +718,10 @@ cmp_modes (const void *a, const void *b)
|
||||
else if (m->component->precision < n->component->precision)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
if (m->counter < n->counter)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1083,15 +1117,24 @@ emit_real_format_for_mode (void)
|
||||
format);
|
||||
#else
|
||||
print_decl ("struct real_format *\n", "real_format_for_mode",
|
||||
"MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1");
|
||||
"MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1 "
|
||||
"+ MAX_MODE_DECIMAL_FLOAT - MIN_MODE_DECIMAL_FLOAT + 1");
|
||||
#endif
|
||||
|
||||
/* The beginning of the table is entries for float modes. */
|
||||
for (m = modes[MODE_FLOAT]; m; m = m->next)
|
||||
if (!strcmp (m->format, "0"))
|
||||
tagged_printf ("%s", m->format, m->name);
|
||||
else
|
||||
tagged_printf ("&%s", m->format, m->name);
|
||||
|
||||
/* The end of the table is entries for decimal float modes. */
|
||||
for (m = modes[MODE_DECIMAL_FLOAT]; m; m = m->next)
|
||||
if (!strcmp (m->format, "0"))
|
||||
tagged_printf ("%s", m->format, m->name);
|
||||
else
|
||||
tagged_printf ("&%s", m->format, m->name);
|
||||
|
||||
print_closer ();
|
||||
}
|
||||
|
||||
|
@ -87,6 +87,10 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
using floating point format FORMAT.
|
||||
All of the bits of its representation are significant.
|
||||
|
||||
DECIMAL FLOAT_MODE (MODE, BYTESIZE);
|
||||
declares MODE to be of class DECIMAL_FLOAT and BYTESIZE bytes
|
||||
wide. All of the bits of its representation are significant.
|
||||
|
||||
FRACTIONAL_FLOAT_MODE (MODE, PRECISION, BYTESIZE, FORMAT);
|
||||
declares MODE to be of class FLOAT, BYTESIZE bytes wide in
|
||||
storage, but with only PRECISION significant bits, using
|
||||
@ -186,6 +190,11 @@ CC_MODE (CC);
|
||||
COMPLEX_MODES (INT);
|
||||
COMPLEX_MODES (FLOAT);
|
||||
|
||||
/* Decimal floating point modes. */
|
||||
DECIMAL_FLOAT_MODE (SD, 4, decimal_single_format);
|
||||
DECIMAL_FLOAT_MODE (DD, 8, decimal_double_format);
|
||||
DECIMAL_FLOAT_MODE (TD, 16, decimal_quad_format);
|
||||
|
||||
/* The symbol Pmode stands for one of the above machine modes (usually SImode).
|
||||
The tm.h file specifies which one. It is not a distinct mode. */
|
||||
|
||||
|
@ -54,6 +54,7 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES];
|
||||
/* Nonzero if MODE is a floating-point mode. */
|
||||
#define FLOAT_MODE_P(MODE) \
|
||||
(GET_MODE_CLASS (MODE) == MODE_FLOAT \
|
||||
|| GET_MODE_CLASS (MODE) == MODE_DECIMAL_FLOAT \
|
||||
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \
|
||||
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT)
|
||||
|
||||
@ -74,12 +75,18 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES];
|
||||
|
||||
/* Nonzero if MODE is a scalar floating point mode. */
|
||||
#define SCALAR_FLOAT_MODE_P(MODE) \
|
||||
(GET_MODE_CLASS (MODE) == MODE_FLOAT)
|
||||
(GET_MODE_CLASS (MODE) == MODE_FLOAT \
|
||||
|| GET_MODE_CLASS (MODE) == MODE_DECIMAL_FLOAT)
|
||||
|
||||
/* Nonzero if MODE is a decimal floating point mode. */
|
||||
#define DECIMAL_FLOAT_MODE_P(MODE) \
|
||||
(GET_MODE_CLASS (MODE) == MODE_DECIMAL_FLOAT)
|
||||
|
||||
/* Nonzero if CLASS modes can be widened. */
|
||||
#define CLASS_HAS_WIDER_MODES_P(CLASS) \
|
||||
(CLASS == MODE_INT \
|
||||
|| CLASS == MODE_FLOAT \
|
||||
|| CLASS == MODE_DECIMAL_FLOAT \
|
||||
|| CLASS == MODE_COMPLEX_FLOAT)
|
||||
|
||||
/* Get the size in bytes and bits of an object of mode MODE. */
|
||||
|
@ -25,6 +25,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
DEF_MODE_CLASS (MODE_INT), /* integer */ \
|
||||
DEF_MODE_CLASS (MODE_PARTIAL_INT), /* integer with padding bits */ \
|
||||
DEF_MODE_CLASS (MODE_FLOAT), /* floating point */ \
|
||||
DEF_MODE_CLASS (MODE_DECIMAL_FLOAT), /* decimal floating point */ \
|
||||
DEF_MODE_CLASS (MODE_COMPLEX_INT), /* complex numbers */ \
|
||||
DEF_MODE_CLASS (MODE_COMPLEX_FLOAT), \
|
||||
DEF_MODE_CLASS (MODE_VECTOR_INT), /* SIMD vectors */ \
|
||||
|
217
gcc/real.c
217
gcc/real.c
@ -29,6 +29,7 @@
|
||||
#include "toplev.h"
|
||||
#include "real.h"
|
||||
#include "tm_p.h"
|
||||
#include "dfp.h"
|
||||
|
||||
/* The floating point model used internally is not exactly IEEE 754
|
||||
compliant, and close to the description in the ISO C99 standard,
|
||||
@ -480,6 +481,9 @@ normalize (REAL_VALUE_TYPE *r)
|
||||
int shift = 0, exp;
|
||||
int i, j;
|
||||
|
||||
if (r->decimal)
|
||||
return;
|
||||
|
||||
/* Find the first word that is nonzero. */
|
||||
for (i = SIGSZ - 1; i >= 0; i--)
|
||||
if (r->sig[i] == 0)
|
||||
@ -643,6 +647,7 @@ do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a,
|
||||
/* Zero out the remaining fields. */
|
||||
r->signalling = 0;
|
||||
r->canonical = 0;
|
||||
r->decimal = 0;
|
||||
|
||||
/* Re-normalize the result. */
|
||||
normalize (r);
|
||||
@ -938,6 +943,9 @@ do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b,
|
||||
if (a->sign != b->sign)
|
||||
return -a->sign - -b->sign;
|
||||
|
||||
if (a->decimal || b->decimal)
|
||||
return decimal_do_compare (a, b, nan_result);
|
||||
|
||||
if (REAL_EXP (a) > REAL_EXP (b))
|
||||
ret = 1;
|
||||
else if (REAL_EXP (a) < REAL_EXP (b))
|
||||
@ -963,6 +971,11 @@ do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a)
|
||||
break;
|
||||
|
||||
case rvc_normal:
|
||||
if (r->decimal)
|
||||
{
|
||||
decimal_do_fix_trunc (r, a);
|
||||
return;
|
||||
}
|
||||
if (REAL_EXP (r) <= 0)
|
||||
get_zero (r, r->sign);
|
||||
else if (REAL_EXP (r) < SIGNIFICAND_BITS)
|
||||
@ -984,6 +997,9 @@ real_arithmetic (REAL_VALUE_TYPE *r, int icode, const REAL_VALUE_TYPE *op0,
|
||||
{
|
||||
enum tree_code code = icode;
|
||||
|
||||
if (op0->decimal || (op1 && op1->decimal))
|
||||
return decimal_real_arithmetic (r, icode, op0, op1);
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case PLUS_EXPR:
|
||||
@ -1187,6 +1203,8 @@ real_identical (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b)
|
||||
return true;
|
||||
|
||||
case rvc_normal:
|
||||
if (a->decimal != b->decimal)
|
||||
return false;
|
||||
if (REAL_EXP (a) != REAL_EXP (b))
|
||||
return false;
|
||||
break;
|
||||
@ -1269,6 +1287,9 @@ real_to_integer (const REAL_VALUE_TYPE *r)
|
||||
return i;
|
||||
|
||||
case rvc_normal:
|
||||
if (r->decimal)
|
||||
return decimal_real_to_integer (r);
|
||||
|
||||
if (REAL_EXP (r) <= 0)
|
||||
goto underflow;
|
||||
/* Only force overflow for unsigned overflow. Signed overflow is
|
||||
@ -1330,6 +1351,12 @@ real_to_integer2 (HOST_WIDE_INT *plow, HOST_WIDE_INT *phigh,
|
||||
break;
|
||||
|
||||
case rvc_normal:
|
||||
if (r->decimal)
|
||||
{
|
||||
decimal_real_to_integer2 (plow, phigh, r);
|
||||
return;
|
||||
}
|
||||
|
||||
exp = REAL_EXP (r);
|
||||
if (exp <= 0)
|
||||
goto underflow;
|
||||
@ -1448,6 +1475,12 @@ real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, size_t buf_size,
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
if (r.decimal)
|
||||
{
|
||||
decimal_real_to_decimal (str, &r, buf_size, digits, crop_trailing_zeros);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Bound the number of digits printed by the size of the representation. */
|
||||
max_digits = SIGNIFICAND_BITS * M_LOG10_2;
|
||||
if (digits == 0 || digits > max_digits)
|
||||
@ -1714,6 +1747,13 @@ real_to_hexadecimal (char *str, const REAL_VALUE_TYPE *r, size_t buf_size,
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
if (r->decimal)
|
||||
{
|
||||
/* Hexadecimal format for decimal floats is not interesting. */
|
||||
strcpy (str, "N/A");
|
||||
return;
|
||||
}
|
||||
|
||||
if (digits == 0)
|
||||
digits = SIGNIFICAND_BITS / 4;
|
||||
|
||||
@ -1957,6 +1997,20 @@ real_from_string2 (const char *s, enum machine_mode mode)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Initialize R from string S and desired MODE. */
|
||||
|
||||
void
|
||||
real_from_string3 (REAL_VALUE_TYPE *r, const char *s, enum machine_mode mode)
|
||||
{
|
||||
if (DECIMAL_FLOAT_MODE_P (mode))
|
||||
decimal_real_from_string (r, s);
|
||||
else
|
||||
real_from_string (r, s);
|
||||
|
||||
if (mode != VOIDmode)
|
||||
real_convert (r, mode, r);
|
||||
}
|
||||
|
||||
/* Initialize R from the integer pair HIGH+LOW. */
|
||||
|
||||
void
|
||||
@ -2202,16 +2256,20 @@ real_maxval (REAL_VALUE_TYPE *r, int sign, enum machine_mode mode)
|
||||
|
||||
fmt = REAL_MODE_FORMAT (mode);
|
||||
gcc_assert (fmt);
|
||||
memset (r, 0, sizeof (*r));
|
||||
|
||||
if (fmt->b == 10)
|
||||
decimal_real_maxval (r, sign, mode);
|
||||
else
|
||||
{
|
||||
r->cl = rvc_normal;
|
||||
r->sign = sign;
|
||||
SET_REAL_EXP (r, fmt->emax * fmt->log2_b);
|
||||
|
||||
r->cl = rvc_normal;
|
||||
r->sign = sign;
|
||||
r->signalling = 0;
|
||||
r->canonical = 0;
|
||||
SET_REAL_EXP (r, fmt->emax * fmt->log2_b);
|
||||
|
||||
np2 = SIGNIFICAND_BITS - fmt->p * fmt->log2_b;
|
||||
memset (r->sig, -1, SIGSZ * sizeof (unsigned long));
|
||||
clear_significand_below (r, np2);
|
||||
np2 = SIGNIFICAND_BITS - fmt->p * fmt->log2_b;
|
||||
memset (r->sig, -1, SIGSZ * sizeof (unsigned long));
|
||||
clear_significand_below (r, np2);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fills R with 2**N. */
|
||||
@ -2243,6 +2301,20 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
|
||||
bool guard, lsb;
|
||||
int emin2m1, emax2;
|
||||
|
||||
if (r->decimal)
|
||||
{
|
||||
if (fmt->b == 10)
|
||||
{
|
||||
decimal_round_for_format (fmt, r);
|
||||
return;
|
||||
}
|
||||
/* FIXME. We can come here via fp_easy_constant
|
||||
(e.g. -O0 on '_Decimal32 x = 1.0 + 2.0dd'), but have not
|
||||
investigated whether this convert needs to be here, or
|
||||
something else is missing. */
|
||||
decimal_real_convert (r, DFmode, r);
|
||||
}
|
||||
|
||||
p2 = fmt->p * fmt->log2_b;
|
||||
emin2m1 = (fmt->emin - 1) * fmt->log2_b;
|
||||
emax2 = fmt->emax * fmt->log2_b;
|
||||
@ -2277,7 +2349,10 @@ round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r)
|
||||
the true base. */
|
||||
if (fmt->log2_b != 1)
|
||||
{
|
||||
int shift = REAL_EXP (r) & (fmt->log2_b - 1);
|
||||
int shift;
|
||||
|
||||
gcc_assert (fmt->b != 10);
|
||||
shift = REAL_EXP (r) & (fmt->log2_b - 1);
|
||||
if (shift)
|
||||
{
|
||||
shift = fmt->log2_b - shift;
|
||||
@ -2377,6 +2452,10 @@ real_convert (REAL_VALUE_TYPE *r, enum machine_mode mode,
|
||||
gcc_assert (fmt);
|
||||
|
||||
*r = *a;
|
||||
|
||||
if (a->decimal || fmt->b == 10)
|
||||
decimal_real_convert (r, mode, a);
|
||||
|
||||
round_for_format (fmt, r);
|
||||
|
||||
/* round_for_format de-normalizes denormals. Undo just that part. */
|
||||
@ -2476,7 +2555,8 @@ real_from_target (REAL_VALUE_TYPE *r, const long *buf, enum machine_mode mode)
|
||||
(*fmt->decode) (fmt, r, buf);
|
||||
}
|
||||
|
||||
/* Return the number of bits in the significand for MODE. */
|
||||
/* Return the number of bits of the largest binary value that the
|
||||
significand of MODE will hold. */
|
||||
/* ??? Legacy. Should get access to real_format directly. */
|
||||
|
||||
int
|
||||
@ -2488,6 +2568,15 @@ significand_size (enum machine_mode mode)
|
||||
if (fmt == NULL)
|
||||
return 0;
|
||||
|
||||
if (fmt->b == 10)
|
||||
{
|
||||
/* Return the size in bits of the largest binary value that can be
|
||||
held by the decimal coefficient for this mode. This is one more
|
||||
than the number of bits required to hold the largest coefficient
|
||||
of this mode. */
|
||||
double log2_10 = 3.3219281;
|
||||
return fmt->p * log2_10;
|
||||
}
|
||||
return fmt->p * fmt->log2_b;
|
||||
}
|
||||
|
||||
@ -4234,6 +4323,112 @@ const struct real_format i370_double_format =
|
||||
false
|
||||
};
|
||||
|
||||
static void
|
||||
encode_decimal_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
||||
long *buf ATTRIBUTE_UNUSED,
|
||||
const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED)
|
||||
{
|
||||
encode_decimal32 (fmt, buf, r);
|
||||
}
|
||||
|
||||
static void
|
||||
decode_decimal_single (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
||||
REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED,
|
||||
const long *buf ATTRIBUTE_UNUSED)
|
||||
{
|
||||
decode_decimal32 (fmt, r, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
encode_decimal_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
||||
long *buf ATTRIBUTE_UNUSED,
|
||||
const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED)
|
||||
{
|
||||
encode_decimal64 (fmt, buf, r);
|
||||
}
|
||||
|
||||
static void
|
||||
decode_decimal_double (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
||||
REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED,
|
||||
const long *buf ATTRIBUTE_UNUSED)
|
||||
{
|
||||
decode_decimal64 (fmt, r, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
encode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
||||
long *buf ATTRIBUTE_UNUSED,
|
||||
const REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED)
|
||||
{
|
||||
encode_decimal128 (fmt, buf, r);
|
||||
}
|
||||
|
||||
static void
|
||||
decode_decimal_quad (const struct real_format *fmt ATTRIBUTE_UNUSED,
|
||||
REAL_VALUE_TYPE *r ATTRIBUTE_UNUSED,
|
||||
const long *buf ATTRIBUTE_UNUSED)
|
||||
{
|
||||
decode_decimal128 (fmt, r, buf);
|
||||
}
|
||||
|
||||
/* Proposed IEEE 754r decimal floating point. */
|
||||
const struct real_format decimal_single_format =
|
||||
{
|
||||
encode_decimal_single,
|
||||
decode_decimal_single,
|
||||
10,
|
||||
1, /* log10 */
|
||||
7,
|
||||
7,
|
||||
-95,
|
||||
96,
|
||||
31,
|
||||
31,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
};
|
||||
|
||||
const struct real_format decimal_double_format =
|
||||
{
|
||||
encode_decimal_double,
|
||||
decode_decimal_double,
|
||||
10,
|
||||
1, /* log10 */
|
||||
16,
|
||||
16,
|
||||
-383,
|
||||
384,
|
||||
63,
|
||||
63,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
};
|
||||
|
||||
const struct real_format decimal_quad_format =
|
||||
{
|
||||
encode_decimal_quad,
|
||||
decode_decimal_quad,
|
||||
10,
|
||||
1, /* log10 */
|
||||
34,
|
||||
34,
|
||||
-6414,
|
||||
6413,
|
||||
127,
|
||||
127,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
};
|
||||
|
||||
/* The "twos-complement" c4x format is officially defined as
|
||||
|
||||
x = s(~s).f * 2**e
|
||||
|
37
gcc/real.h
37
gcc/real.h
@ -35,7 +35,7 @@ enum real_value_class {
|
||||
};
|
||||
|
||||
#define SIGNIFICAND_BITS (128 + HOST_BITS_PER_LONG)
|
||||
#define EXP_BITS (32 - 5)
|
||||
#define EXP_BITS (32 - 6)
|
||||
#define MAX_EXP ((1 << (EXP_BITS - 1)) - 1)
|
||||
#define SIGSZ (SIGNIFICAND_BITS / HOST_BITS_PER_LONG)
|
||||
#define SIG_MSB ((unsigned long)1 << (HOST_BITS_PER_LONG - 1))
|
||||
@ -46,6 +46,7 @@ struct real_value GTY(())
|
||||
sure they're packed together, otherwise REAL_VALUE_TYPE_SIZE will
|
||||
be miscomputed. */
|
||||
unsigned int /* ENUM_BITFIELD (real_value_class) */ cl : 2;
|
||||
unsigned int decimal : 1;
|
||||
unsigned int sign : 1;
|
||||
unsigned int signalling : 1;
|
||||
unsigned int canonical : 1;
|
||||
@ -155,12 +156,20 @@ struct real_format
|
||||
};
|
||||
|
||||
|
||||
/* The target format used for each floating floating point mode.
|
||||
Indexed by MODE - QFmode. */
|
||||
/* The target format used for each floating point mode.
|
||||
Float modes are followed by decimal float modes, with entries for
|
||||
float modes indexed by (MODE - first float mode), and entries for
|
||||
decimal float modes indexed by (MODE - first decimal float mode) +
|
||||
the number of float modes. */
|
||||
extern const struct real_format *
|
||||
real_format_for_mode[MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1];
|
||||
real_format_for_mode[MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1
|
||||
+ MAX_MODE_DECIMAL_FLOAT - MIN_MODE_DECIMAL_FLOAT + 1];
|
||||
|
||||
#define REAL_MODE_FORMAT(MODE) (real_format_for_mode[(MODE) - MIN_MODE_FLOAT])
|
||||
#define REAL_MODE_FORMAT(MODE) \
|
||||
(real_format_for_mode[DECIMAL_FLOAT_MODE_P (MODE) \
|
||||
? ((MODE - MIN_MODE_DECIMAL_FLOAT) \
|
||||
+ (MAX_MODE_FLOAT - MIN_MODE_FLOAT + 1)) \
|
||||
: (MODE - MIN_MODE_FLOAT)])
|
||||
|
||||
/* The following macro determines whether the floating point format is
|
||||
composite, i.e. may contain non-consecutive mantissa bits, in which
|
||||
@ -214,6 +223,8 @@ extern void real_to_integer2 (HOST_WIDE_INT *, HOST_WIDE_INT *,
|
||||
|
||||
/* Initialize R from a decimal or hexadecimal string. */
|
||||
extern void real_from_string (REAL_VALUE_TYPE *, const char *);
|
||||
/* Wrapper to allow different internal representation for decimal floats. */
|
||||
extern void real_from_string3 (REAL_VALUE_TYPE *, const char *, enum machine_mode);
|
||||
|
||||
/* Initialize R from an integer pair HIGH/LOW. */
|
||||
extern void real_from_integer (REAL_VALUE_TYPE *, enum machine_mode,
|
||||
@ -260,6 +271,9 @@ extern const struct real_format i370_double_format;
|
||||
extern const struct real_format c4x_single_format;
|
||||
extern const struct real_format c4x_extended_format;
|
||||
extern const struct real_format real_internal_format;
|
||||
extern const struct real_format decimal_single_format;
|
||||
extern const struct real_format decimal_double_format;
|
||||
extern const struct real_format decimal_quad_format;
|
||||
|
||||
|
||||
/* ====================================================================== */
|
||||
@ -302,6 +316,19 @@ extern const struct real_format real_internal_format;
|
||||
#define REAL_VALUE_FROM_UNSIGNED_INT(r, lo, hi, mode) \
|
||||
real_from_integer (&(r), mode, lo, hi, 1)
|
||||
|
||||
/* Real values to IEEE 754R decimal floats. */
|
||||
|
||||
/* IN is a REAL_VALUE_TYPE. OUT is an array of longs. */
|
||||
#define REAL_VALUE_TO_TARGET_DECIMAL128(IN, OUT) \
|
||||
real_to_target (OUT, &(IN), mode_for_size (128, MODE_DECIMAL_FLOAT, 0))
|
||||
|
||||
#define REAL_VALUE_TO_TARGET_DECIMAL64(IN, OUT) \
|
||||
real_to_target (OUT, &(IN), mode_for_size (64, MODE_DECIMAL_FLOAT, 0))
|
||||
|
||||
/* IN is a REAL_VALUE_TYPE. OUT is a long. */
|
||||
#define REAL_VALUE_TO_TARGET_DECIMAL32(IN, OUT) \
|
||||
((OUT) = real_to_target (NULL, &(IN), mode_for_size (32, MODE_DECIMAL_FLOAT, 0)))
|
||||
|
||||
extern REAL_VALUE_TYPE real_value_truncate (enum machine_mode,
|
||||
REAL_VALUE_TYPE);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user