Commit 909e2256 by Jon Grimm Committed by Ben Elliston

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
parent 8da15291
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) \
......
This diff is collapsed. Click to expand it.
/* 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 */ \
......
......@@ -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
......
......@@ -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);
......
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