Skip to content

Commit

Permalink
Add most ti <-> Decimal conversions
Browse files Browse the repository at this point in the history
Credit goes to Steven Munroe <munroesj@linux.vnet.ibm.com>
for the float{uns,}titd routines.  ti -> {dd,sd} is still
a work in progress.

These still leaves plenty of room for optimization, but these
are a functional first pass.

This does a bit of build system shuffling as TImode is not
supported on all platforms, and thus a separate ABI list
needs to be kept for these cases.

Signed-off-by: Paul E. Murphy <murphyp@linux.vnet.ibm.com>
Signed-off-by: Steven Munroe <munroesj@linux.vnet.ibm.com>
  • Loading branch information
Paul E. Murphy committed Dec 16, 2015
1 parent d86a852 commit a45d232
Show file tree
Hide file tree
Showing 31 changed files with 2,447 additions and 7 deletions.
30 changes: 25 additions & 5 deletions Makefile.in
Expand Up @@ -86,6 +86,16 @@ cflags-cpu = $(libdfp_cv_submachine_opt)
asflags-cpu = $(libdfp_cv_submachine_opt)
endif

# Only try building TImode files if it is support.
dfp_ti_abi = @dfp_ti_abi@

# Need to check a different PLT file for int128
ifeq ($(dfp_ti_abi),yes)
dfp_abi_extn =
else
dfp_abi_extn = -no-ti
endif

picflag = @picflag@

# Yes this is a bit of a hack, but gcc/libdecnumber/Makefile won't allow
Expand Down Expand Up @@ -182,6 +192,12 @@ libdfp_files := dfptypeconv mapround decode fmt_d32 fmt_d64 fmt_d128 fe_decround
# they can add files to the libdfp_files list.
include $(foreach dir,$(makefile_dirs), $(dir)/Makefile )

# Build the TImode files if we support them.
# Note that this does change the ABI.
ifeq ($(dfp_ti_abi),yes)
libdfp_files += $(libdfp_ti_files)
endif

# Libdfp has a dependency on the backend so build that first.
all: first $(dfp_backend)/$(dfp_backend_lib) libdfp

Expand Down Expand Up @@ -220,16 +236,16 @@ CXX_WARNS := -W -Wall -Wwrite-strings -Wmissing-format-attribute -Wno-long-long

# Build the static object files.
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) $(mzarch) -c $< $(C_DEFINES) $(WARNS) -include $(top_srcdir)/include/libdfp-symbols.h -include $(top_builddir)/config.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@
$(CC) $(CFLAGS) $(CPPFLAGS) $(mzarch) -c $< $(C_DEFINES) $(WARNS) -include $(top_builddir)/config.h -include $(top_srcdir)/include/libdfp-symbols.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@
.S.o:
$(CC) $(CFLAGS) $(ASFLAGS) $(mzarch) -c $< $(ASM_DEFINES) $(WARNS) -include $(top_srcdir)/include/libdfp-symbols.h -include $(top_builddir)/config.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@
$(CC) $(CFLAGS) $(ASFLAGS) $(mzarch) -c $< $(ASM_DEFINES) $(WARNS) -include $(top_builddir)/config.h -include $(top_srcdir)/include/libdfp-symbols.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@

# Build the shared object files.
.c.os:
$(CC) $(CFLAGS) $(CPPFLAGS) $(mzarch) -c $< $(C_DEFINES) $(WARNS) -include $(top_srcdir)/include/libdfp-symbols.h -include $(top_builddir)/config.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@
$(CC) $(CFLAGS) $(CPPFLAGS) $(mzarch) -c $< $(C_DEFINES) $(WARNS) -include $(top_builddir)/config.h -include $(top_srcdir)/include/libdfp-symbols.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@

.S.os:
$(CC) $(CFLAGS) $(ASFLAGS) $(mzarch) -c $< $(ASM_DEFINES) $(WARNS) -include $(top_srcdir)/include/libdfp-symbols.h -include $(top_builddir)/config.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@
$(CC) $(CFLAGS) $(ASFLAGS) $(mzarch) -c $< $(ASM_DEFINES) $(WARNS) -include $(top_builddir)/config.h -include $(top_srcdir)/include/libdfp-symbols.h $(foreach dir, $(header_search_dirs), -I$(dir)) -o $@

# C++ compatibility test cases.
.cpp.os:
Expand Down Expand Up @@ -338,6 +354,10 @@ libdfp_c_tests = test-printf test-amort test-decode \
test-isless-d32 test-isless-d64 test-isless-d128 \
test-islessequal-d32 test-islessequal-d64 test-islessequal-d128

ifeq ($(dfp_ti_abi),yes)
libdfp_c_tests += test-fix test-float
endif

# Only enable C++ tests if compiler supports std::decimal (GCC 4.5+),
# otherwise just skip them.
ifeq ($(cxxdecimal), yes)
Expand Down Expand Up @@ -400,7 +420,7 @@ vpath %.abilist $(+sysdeps_dirs)
check-abi: check-abi-libdfp.out
$(warning $@)

check-abi-libdfp.out: libdfp.abilist libdfp.symlist
check-abi-libdfp.out: libdfp$(dfp_abi_extn).abilist libdfp.symlist
diff -p -U 0 $(filter %.abilist,$^) $(filter %.symlist,$^) > $@

%.symlist: $(top_srcdir)/scripts/abilist.awk %.dynsym
Expand Down
1 change: 1 addition & 0 deletions Versions.def
Expand Up @@ -9,5 +9,6 @@ libdfp {
LIBDFP_1.0.8
LIBDFP_1.0.9
LIBDFP_1.0.10
LIBDFP_1.0.13
LIBDFP_PRIVATE
}
7 changes: 5 additions & 2 deletions base-math/Makefile
Expand Up @@ -6,8 +6,7 @@
# redistribute it and/or modify it under the terms of the GNU Lesser
# General Public License version 2.1.
#
# The Decimal Floating Point C Library is distributed in the hope that
# it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# The Decimal Floating Point C Library 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 Lesser General Public License version 2.1 for more details.
#
Expand Down Expand Up @@ -46,3 +45,7 @@ libdfp_files += addsd3 adddd3 addtd3 \
trunctdsf trunctddf trunctdtf \
unordsd2 unorddd2 unordtd2 \
classify

libdfp_ti_files += fixsdti fixddti \
fixunssdti fixunsddti \
floattitd floatunstitd
31 changes: 31 additions & 0 deletions base-math/fixddti.c
@@ -0,0 +1,31 @@
/* fixddti implementation.
Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of the Decimal Floating Point C Library.
Author(s): Paul E. Murphy <murphyp@linux.vnet.ibm.com>
The Decimal Floating Point C Library is free software; you can
redistribute it and/or modify it under the terms of the GNU Lesser
General Public License version 2.1.
The Decimal Floating Point C Library 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 Lesser General Public License version 2.1 for more details.
You should have received a copy of the GNU Lesser General Public
License version 2.1 along with the Decimal Floating Point C Library;
if not, write to the Free Software Foundation, Inc., 59 Temple Place,
Suite 330, Boston, MA 02111-1307 USA.
Please see libdfp/COPYING.txt for more information. */

#define SRC_SIZE 64
#define FUNC fixddti
#define SHIFT_EXP 16
#define DSUFF DD
#define SIGNED 1

#include "fixsdti.c"
150 changes: 150 additions & 0 deletions base-math/fixsdti.c
@@ -0,0 +1,150 @@
/* Common fix*ti and fixsdti implementation.
Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of the Decimal Floating Point C Library.
Author(s): Paul E. Murphy <murphyp@linux.vnet.ibm.com>
The Decimal Floating Point C Library is free software; you can
redistribute it and/or modify it under the terms of the GNU Lesser
General Public License version 2.1.
The Decimal Floating Point C Library 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 Lesser General Public License version 2.1 for more details.
You should have received a copy of the GNU Lesser General Public
License version 2.1 along with the Decimal Floating Point C Library;
if not, write to the Free Software Foundation, Inc., 59 Temple Place,
Suite 330, Boston, MA 02111-1307 USA.
Please see libdfp/COPYING.txt for more information. */

#ifndef SRC_SIZE
# define SRC_SIZE 32
# define FUNC fixsdti
# define SHIFT_EXP 7
# define DSUFF DF
# define SIGNED 1
#endif

#define _DECIMAL_SIZE SRC_SIZE

#include <dfpacc.h>
#include <stdint.h>
#include <dfp/math.h>
#include <dfpmacro.h>
#include <ieee754r_private.h>

#if SIGNED == 1
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
# define MAX_RET_VAL {.di = {0x7FFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFFFLL}}
# define MIN_RET_VAL {.di = {0x8000000000000000LL, 0LL}}
# else
# define MAX_RET_VAL {.di = {0xFFFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL}}
# define MIN_RET_VAL {.di = { 0LL, 0x8000000000000000LL}}
# endif
# if SRC_SIZE == 32
# define MIN_VAL (-170141100000000000000000000000000000000.DF)
# define MAX_VAL ( 170141100000000000000000000000000000000.DF)
# elif SRC_SIZE == 64
# define MIN_VAL (-170141183460469200000000000000000000000.DD)
# define MAX_VAL ( 170141183460469200000000000000000000000.DD)
# else
# define MIN_VAL (-170141183460469231731687303715884100000.DL)
# define MAX_VAL ( 170141183460469231731687303715884100000.DL)
# endif
# define RET_TYPE __int128
# define QUICK_CONVERT(_x) ({ long long int _a_di = _x; _a_di;})
#else
# define MAX_RET_VAL {.di = {0xFFFFFFFFFFFFFFFFLL, 0xFFFFFFFFFFFFFFFFLL}}
# define MIN_RET_VAL {.di = {0LL, 0LL}}
# define MIN_VAL PASTE(0., DSUFF)
# if SRC_SIZE == 32
# define MAX_VAL (340282300000000000000000000000000000000.DF)
# elif SRC_SIZE == 64
# define MAX_VAL (340282366920938400000000000000000000000.DD)
# else
# define MAX_VAL (340282366920938463463374607431768200000.DL)
# endif
# define RET_TYPE unsigned __int128
# define QUICK_CONVERT(_x) ({ unsigned long long int _a_di = _x; _a_di;})
#endif

#define TRUNC(_x) (PASTE(__truncd, SRC_SIZE)(_x))
#define FREXP(_x,_y) (PASTE(__frexpd,SRC_SIZE)(_x,_y))
#define CLASSIFY(_x) (PASTE(__fpclassifyd,SRC_SIZE)(_x))
#define SHIFT_EXP_VAL PASTE(PASTE(1e,SHIFT_EXP),PASTE(DSUFF,))
#define SIGNBIT(_x) (PASTE(__signbitd,SRC_SIZE)(_x))

#if SIGNED == 1
# define FABS(_x) (PASTE(__fabsd,SRC_SIZE)(_x))
#else
# define FABS(_x) _x
#endif

extern const __int128 exp10_ti[39];

RET_TYPE __BACKEND_(FUNC) (DEC_TYPE a)
{
union ret_type
{
RET_TYPE ti;
uint64_t di[2];
};
union ret_type min = MIN_RET_VAL;
union ret_type max = MAX_RET_VAL;

switch (CLASSIFY (a))
{
case FP_ZERO:
return 0;

case FP_INFINITE:
DFP_EXCEPT (FE_INVALID);
return SIGNBIT(a) ? min.ti : max.ti;

case FP_NAN:
DFP_EXCEPT (FE_INVALID);
return min.ti;
}

if(a < MIN_VAL || a > MAX_VAL)
{
DFP_EXCEPT (FE_INVALID);
return (a < MIN_VAL) ? min.ti : max.ti;
}

/* A 64 bit mantissa is sufficient for dd/sd conversions. */
#if SRC_SIZE <= 64
RET_TYPE result;
int e;

if (FABS(a) < SHIFT_EXP_VAL)
{
return (RET_TYPE) QUICK_CONVERT (a);
}

DEC_TYPE a_int = TRUNC (a);
DEC_TYPE a_norm = FREXP (a_int, &e);


a_norm *= SHIFT_EXP_VAL;
e -= SHIFT_EXP;
/* Force a 64b conversion of the mantissa */
result = ((int64_t) a_norm);
if (e > 0)
return result * (RET_TYPE) exp10_ti[e];
else if (e < 0)
return result / (RET_TYPE) exp10_ti[-e];
else
return result;
#else
/* This requires specific knowledge of the encoding. Punt it. */
return D128_CONVERSION(a);
#endif
}

hidden_def (__BACKEND_(FUNC))
31 changes: 31 additions & 0 deletions base-math/fixunsddti.c
@@ -0,0 +1,31 @@
/* fixunsddti implementation.
Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of the Decimal Floating Point C Library.
Author(s): Paul E. Murphy <murphyp@linux.vnet.ibm.com>
The Decimal Floating Point C Library is free software; you can
redistribute it and/or modify it under the terms of the GNU Lesser
General Public License version 2.1.
The Decimal Floating Point C Library 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 Lesser General Public License version 2.1 for more details.
You should have received a copy of the GNU Lesser General Public
License version 2.1 along with the Decimal Floating Point C Library;
if not, write to the Free Software Foundation, Inc., 59 Temple Place,
Suite 330, Boston, MA 02111-1307 USA.
Please see libdfp/COPYING.txt for more information. */

#define SRC_SIZE 64
#define FUNC fixunsddti
#define SHIFT_EXP 16
#define DSUFF DD
#define SIGNED 0

#include "fixsdti.c"
31 changes: 31 additions & 0 deletions base-math/fixunssdti.c
@@ -0,0 +1,31 @@
/* fixunssdti implementation.
Copyright (C) 2015 Free Software Foundation, Inc.
This file is part of the Decimal Floating Point C Library.
Author(s): Paul E. Murphy <murphyp@linux.vnet.ibm.com>
The Decimal Floating Point C Library is free software; you can
redistribute it and/or modify it under the terms of the GNU Lesser
General Public License version 2.1.
The Decimal Floating Point C Library 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 Lesser General Public License version 2.1 for more details.
You should have received a copy of the GNU Lesser General Public
License version 2.1 along with the Decimal Floating Point C Library;
if not, write to the Free Software Foundation, Inc., 59 Temple Place,
Suite 330, Boston, MA 02111-1307 USA.
Please see libdfp/COPYING.txt for more information. */

#define SRC_SIZE 32
#define FUNC fixunssdti
#define SHIFT_EXP 7
#define DSUFF DF
#define SIGNED 0

#include "fixsdti.c"

0 comments on commit a45d232

Please sign in to comment.