Skip to contentSkip to conversation

target-ppc: Decimal Floating Point

RFC In review Tom Musta 2 participants 16 messages Mar 13, 2014 – Apr 11, 2014 Kbuild

lore
Share & tools
lore

Tom Musta

author
#0 lore raw

cover target-ppc: Decimal Floating Point

This patch series provides a prototype of Decimal Floating Point (DFP) instruction support in QEMU. The topic was briefly discussed here:
http://lists.nongnu.org/archive/html/qemu-ppc/2014-02/msg00129.html

I. Overview

The core of the DFP model is a library named libdecnumber, which is a sub-library of GCC's libdfp. Libdecnumber's model uses an expanded internal representation of a decimal floating point number as:

- exponent (base 10)
- the number of digits (aka declets)
- flags (sign bit and "special" bits for NaNs and infinities)
- an array of units. Each unit contains DECPUN declets.

Libdecnumber provides routines for various arithmetic operations (e.g. decNumberAdd for addition) as well as converters for going to/from binary form.

PowerPC's support of DFP uses Densely Packed Decimal (DPD) format. The standard floating point registers are re-used to hold DFP operands. There are typically PowerPC instructions for both the long (64 bit) and extended (128 bit, aka quad) formats. The extended format instructions use adjacent pairs of FPRs to hold the 128 bit operands.

II. A Simple Example

PowerPC DFP instructions are implemented using helpers, which in turn use libdecnumber routines to perform the detailed computations. This is similar to how softfloat is used to model binary floating point instructions.

For example, the implementation of the helper for DFP Add Long (dadd) looks like this:

1) Establish a libdecnumber context for 64-bit computation (decContext)
2) Convert the two source FPRs from DPD to decNumbers (the expanded internal representation)
3) Invoke the add operation (decNumberAdd)
4) Inspect the context's flags for various exception situations (e.g. overflow), mapping them to the corresponding FPSCR status flags.
5) Convert the summand to DPD form and store into the target FPR.

The helper for the DPD Add Extended (daddq) is nearly identical. It differs only in that it establishes a 128 bit context and the conversions are from and to 128 bit DPD format.

III. Integration of libdecnumber in QEMU

The appoach taken here is direct and simple:

1) A copy of libdecnumber code is imported into QEMU. The header files are placed under include/libdecnumber and the code is placed under libdecnumber. A minimalist approach is taken -- only the source required to support PPC DFP instruction models is imported.

2) The code is modified to account for this structure (see patch 02/12)

3) The libdecnumber configuration script is jettisoned. Instead, the configuration header that is normally generated is modified to integrate properly with QEMU's configuration. See patch 03/12.

4) Some trivial modifications to source are made to address compiler warnings. See patches 04/12 - 06/12

5) Compilation is enabled for PowerPC emulation models (see patch 07/12).

Tom Musta (12):
target-ppc: Introduce libdecnumber Code
target-ppc: Prepare libdecnumber for QEMU include structure
target-ppc: Modify dconfig.h to Integrate with QEMU
target-ppc: Change gstdint.h to stdint.h
target-ppc: Eliminate redundant declarations
target-ppc: Eliminate Unused Variable in decSetSubnormal
target-ppc: Enable Building of libdecnumber
target-ppc: Define FPR Pointer Type for Helpers
target-ppc: Introduce Translation Macros for DFP Arithmetic Forms
target-ppc: Introduce DFP Helper Utilities
target-ppc: Introduce DFP Post Processor Utilities
target-ppc: Introduce DFP Add

 Makefile.target                              |    5 +
 default-configs/ppc-linux-user.mak           |    1 +
 default-configs/ppc-softmmu.mak              |    1 +
 default-configs/ppc64-linux-user.mak         |    1 +
 default-configs/ppc64-softmmu.mak            |    1 +
 include/libdecnumber/dconfig.h               |   35 +
 include/libdecnumber/decCommonSymbols.h      |   14 +
 include/libdecnumber/decContext.h            |  253 +
 include/libdecnumber/decContextSymbols.h     |   44 +
 include/libdecnumber/decDPD.h                | 1211 ++++
 include/libdecnumber/decDPDSymbols.h         |   26 +
 include/libdecnumber/decDouble.h             |  161 +
 include/libdecnumber/decDoubleSymbols.h      |  165 +
 include/libdecnumber/decNumber.h             |  195 +
 include/libdecnumber/decNumberLocal.h        |  662 +++
 include/libdecnumber/decNumberSymbols.h      |  143 +
 include/libdecnumber/decQuad.h               |  183 +
 include/libdecnumber/decQuadSymbols.h        |  160 +
 include/libdecnumber/dpd/decimal128.h        |   96 +
 include/libdecnumber/dpd/decimal128Local.h   |   42 +
 include/libdecnumber/dpd/decimal128Symbols.h |   48 +
 include/libdecnumber/dpd/decimal64.h         |   96 +
 include/libdecnumber/dpd/decimal64Symbols.h  |   48 +
 libdecnumber/decContext.c                    |  427 ++
 libdecnumber/decNumber.c                     | 8115 ++++++++++++++++++++++++++
 libdecnumber/dpd/decimal128.c                |  559 ++
 libdecnumber/dpd/decimal128Local.h           |   42 +
 libdecnumber/dpd/decimal64.c                 |  845 +++
 target-ppc/Makefile.objs                     |    1 +
 target-ppc/dfp_helper.c                      |  264 +
 target-ppc/helper.h                          |    7 +
 target-ppc/translate.c                       |   65 +
 32 files changed, 13916 insertions(+), 0 deletions(-)
 create mode 100644 include/libdecnumber/dconfig.h
 create mode 100644 include/libdecnumber/decCommonSymbols.h
 create mode 100644 include/libdecnumber/decContext.h
 create mode 100644 include/libdecnumber/decContextSymbols.h
 create mode 100644 include/libdecnumber/decDPD.h
 create mode 100644 include/libdecnumber/decDPDSymbols.h
 create mode 100644 include/libdecnumber/decDouble.h
 create mode 100644 include/libdecnumber/decDoubleSymbols.h
 create mode 100644 include/libdecnumber/decNumber.h
 create mode 100644 include/libdecnumber/decNumberLocal.h
 create mode 100644 include/libdecnumber/decNumberSymbols.h
 create mode 100644 include/libdecnumber/decQuad.h
 create mode 100644 include/libdecnumber/decQuadSymbols.h
 create mode 100644 include/libdecnumber/dpd/decimal128.h
 create mode 100644 include/libdecnumber/dpd/decimal128Local.h
 create mode 100644 include/libdecnumber/dpd/decimal128Symbols.h
 create mode 100644 include/libdecnumber/dpd/decimal64.h
 create mode 100644 include/libdecnumber/dpd/decimal64Symbols.h
 create mode 100644 libdecnumber/decContext.c
 create mode 100644 libdecnumber/decNumber.c
 create mode 100644 libdecnumber/dpd/decimal128.c
 create mode 100644 libdecnumber/dpd/decimal128Local.h
 create mode 100644 libdecnumber/dpd/decimal64.c
 create mode 100644 target-ppc/dfp_helper.c
author
#1 lore raw

RFC 1/12 target-ppc: Introduce libdecnumber Code

This patch adds files from the libdecnumber decimal floating point library. This library is originally optionally part of GCC and contains code that is useful in emulating the PowerPC decimal floating point (DFP) instructions.

The patch does not alter any Makefile targets. The code will be altered by subsequent patches prior to doing so.

Question: What needs to be done with the GCC boilerplate? I assume that the existing licensing statements are acceptable for QEMU. I probably should change "This file is part of GCC." to something like "This file was originally part of GCC."

---
 include/libdecnumber/dconfig.h               |   47 +
 include/libdecnumber/decCommonSymbols.h      |   14 +
 include/libdecnumber/decContext.h            |  253 +
 include/libdecnumber/decContextSymbols.h     |   44 +
 include/libdecnumber/decDPD.h                | 1211 ++++
 include/libdecnumber/decDPDSymbols.h         |   26 +
 include/libdecnumber/decDouble.h             |  161 +
 include/libdecnumber/decDoubleSymbols.h      |  165 +
 include/libdecnumber/decNumber.h             |  195 +
 include/libdecnumber/decNumberLocal.h        |  662 +++
 include/libdecnumber/decNumberSymbols.h      |  143 +
 include/libdecnumber/decQuad.h               |  183 +
 include/libdecnumber/decQuadSymbols.h        |  160 +
 include/libdecnumber/dpd/decimal128.h        |   96 +
 include/libdecnumber/dpd/decimal128Local.h   |   42 +
 include/libdecnumber/dpd/decimal128Symbols.h |   48 +
 include/libdecnumber/dpd/decimal64.h         |   96 +
 include/libdecnumber/dpd/decimal64Symbols.h  |   48 +
 libdecnumber/decContext.c                    |  427 ++
 libdecnumber/decNumber.c                     | 8117 ++++++++++++++++++++++++++
 libdecnumber/dpd/decimal128.c                |  561 ++
 libdecnumber/dpd/decimal128Local.h           |   42 +
 libdecnumber/dpd/decimal64.c                 |  847 +++
 23 files changed, 13588 insertions(+), 0 deletions(-)
 create mode 100644 include/libdecnumber/dconfig.h
 create mode 100644 include/libdecnumber/decCommonSymbols.h
 create mode 100644 include/libdecnumber/decContext.h
 create mode 100644 include/libdecnumber/decContextSymbols.h
 create mode 100644 include/libdecnumber/decDPD.h
 create mode 100644 include/libdecnumber/decDPDSymbols.h
 create mode 100644 include/libdecnumber/decDouble.h
 create mode 100644 include/libdecnumber/decDoubleSymbols.h
 create mode 100644 include/libdecnumber/decNumber.h
 create mode 100644 include/libdecnumber/decNumberLocal.h
 create mode 100644 include/libdecnumber/decNumberSymbols.h
 create mode 100644 include/libdecnumber/decQuad.h
 create mode 100644 include/libdecnumber/decQuadSymbols.h
 create mode 100644 include/libdecnumber/dpd/decimal128.h
 create mode 100644 include/libdecnumber/dpd/decimal128Local.h
 create mode 100644 include/libdecnumber/dpd/decimal128Symbols.h
 create mode 100644 include/libdecnumber/dpd/decimal64.h
 create mode 100644 include/libdecnumber/dpd/decimal64Symbols.h
 create mode 100644 libdecnumber/decContext.c
 create mode 100644 libdecnumber/decNumber.c
 create mode 100644 libdecnumber/dpd/decimal128.c
 create mode 100644 libdecnumber/dpd/decimal128Local.h
 create mode 100644 libdecnumber/dpd/decimal64.c
include/libdecnumber/dconfig.h new file +47 -0
new file mode 100644
index 0000000..91aa334
@@ -0,0 +1,47 @@
+/* Configure decNumber for either host or target.
+   Copyright (C) 2008, 2009 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 3, 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.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+#ifdef IN_LIBGCC2
+
+#include "tconfig.h"
+#include "coretypes.h"
+#include "tm.h"
+
+#ifndef LIBGCC2_WORDS_BIG_ENDIAN
+#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
+#endif
+
+#ifndef LIBGCC2_FLOAT_WORDS_BIG_ENDIAN
+#define LIBGCC2_FLOAT_WORDS_BIG_ENDIAN LIBGCC2_WORDS_BIG_ENDIAN
+#endif
+
+#if LIBGCC2_FLOAT_WORDS_BIG_ENDIAN
+#define WORDS_BIGENDIAN 1
+#endif
+
+#else
+
+#include "config.h"
+
+#endif
include/libdecnumber/decCommonSymbols.h new file +14 -0
new file mode 100644
index 0000000..277b1bb
@@ -0,0 +1,14 @@
+#if !defined(DECCOMMONSYMBOLS)
+#define DECCOMMONSYMBOLS
+
+#ifdef IN_LIBGCC2
+#define DECCOMBFROM __decCOMBFROM
+#define DECCOMBMSD __decCOMBMSD
+#endif
+
+#ifdef __STDC_DEC_FP__
+#define DECCOMBFROM ___decCOMBFROM
+#define DECCOMBMSD ___decCOMBMSD
+#endif
+
+#endif
include/libdecnumber/decContext.h new file +253 -0

253 lines not on this page · raw message

include/libdecnumber/decContextSymbols.h new file +44 -0

44 lines not on this page · raw message

include/libdecnumber/decDPD.h new file +1211 -0

1,211 lines not on this page · raw message

include/libdecnumber/decDPDSymbols.h new file +26 -0
new file mode 100644
index 0000000..523ec55
@@ -0,0 +1,26 @@
+#if !defined(DECDPDSYMBOLS)
+#define DECDPDSYMBOLS
+
+#ifdef IN_LIBGCC2
+#define BCD2DPD __decBCD2DPD
+#define BIN2BCD8 __decBIN2BCD8
+#define BIN2CHAR __decBIN2CHAR
+#define BIN2DPD __decBIN2DPD
+#define DPD2BCD8 __decDPD2BCD8
+#define DPD2BIN __decDPD2BIN
+#define DPD2BINK __decDPD2BINK
+#define DPD2BINM __decDPD2BINM
+#endif
+
+#ifdef __STDC_DEC_FP__
+#define BCD2DPD ___decBCD2DPD
+#define BIN2BCD8 ___decBIN2BCD8
+#define BIN2CHAR ___decBIN2CHAR
+#define BIN2DPD ___decBIN2DPD
+#define DPD2BCD8 ___decDPD2BCD8
+#define DPD2BIN ___decDPD2BIN
+#define DPD2BINK ___decDPD2BINK
+#define DPD2BINM ___decDPD2BINM
+#endif
+
+#endif
include/libdecnumber/decDouble.h new file +161 -0

161 lines not on this page · raw message

include/libdecnumber/decDoubleSymbols.h new file +165 -0

165 lines not on this page · raw message

include/libdecnumber/decNumber.h new file +195 -0

195 lines not on this page · raw message

include/libdecnumber/decNumberLocal.h new file +662 -0

662 lines not on this page · raw message

include/libdecnumber/decNumberSymbols.h new file +143 -0

143 lines not on this page · raw message

include/libdecnumber/decQuad.h new file +183 -0

79 lines not on this page · raw message

include/libdecnumber/decQuadSymbols.h new file +160 -0

160 lines not on this page · raw message

include/libdecnumber/dpd/decimal128.h new file +96 -0

96 lines not on this page · raw message

include/libdecnumber/dpd/decimal128Local.h new file +42 -0

42 lines not on this page · raw message

include/libdecnumber/dpd/decimal128Symbols.h new file +48 -0

48 lines not on this page · raw message

include/libdecnumber/dpd/decimal64.h new file +96 -0

96 lines not on this page · raw message

include/libdecnumber/dpd/decimal64Symbols.h new file +48 -0

48 lines not on this page · raw message

libdecnumber/decContext.c new file +427 -0

427 lines not on this page · raw message

libdecnumber/decNumber.c new file +8117 -0

8,117 lines not on this page · raw message

libdecnumber/dpd/decimal128.c new file +561 -0

561 lines not on this page · raw message

libdecnumber/dpd/decimal128Local.h new file +42 -0

42 lines not on this page · raw message

libdecnumber/dpd/decimal64.c new file +847 -0

847 lines not on this page · raw message

The rest of this diff is not shown. View the raw message.

Signature · 1 line
1.7.1

Part of the diff is not shown here. View the raw message.

author
#2 lore raw

RFC 2/12 target-ppc: Prepare libdecnumber for QEMU include structure

In reply to Tom Musta

This patch modifies the libdecnumber source code so that it fits properly with QEMU's include directory structure. Specifically, directives of the form

    #include "xxx.h"

are modified to look like:

    #include "libdecnumber/xxx.h"
---
 include/libdecnumber/decContext.h     |    2 +-
 include/libdecnumber/decDouble.h      |    2 +-
 include/libdecnumber/decNumber.h      |    4 ++--
 include/libdecnumber/decNumberLocal.h |    2 +-
 include/libdecnumber/decQuad.h        |    2 +-
 include/libdecnumber/dpd/decimal128.h |    2 +-
 include/libdecnumber/dpd/decimal64.h  |    2 +-
 libdecnumber/decContext.c             |    6 +++---
 libdecnumber/decNumber.c              |    6 +++---
 libdecnumber/dpd/decimal128.c         |    8 ++++----
 libdecnumber/dpd/decimal64.c          |   12 ++++++------
 11 files changed, 24 insertions(+), 24 deletions(-)
include/libdecnumber/decContext.h +1 -1
index cdbb244..2e8f2e1 100644
@@ -232,7 +232,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
   /* decContext routines					      */
 
-  #include "decContextSymbols.h"
+  #include "libdecnumber/decContextSymbols.h"
 
   extern decContext  * decContextClearStatus(decContext *, uint32_t);
   extern decContext  * decContextDefault(decContext *, int32_t);
include/libdecnumber/decDouble.h +1 -1
index 136bb9d..ddbafd1 100644
@@ -50,7 +50,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
   #define DECDOUBLE_Ehigh (DECDOUBLE_Emax + DECDOUBLE_Bias - (DECDOUBLE_Pmax-1))
 
   /* Required includes						      */
-  #include "decContext.h"
+  #include "libdecnumber/decContext.h"
   #include "decQuad.h"
 
   /* The decDouble decimal 64-bit type, accessible by various types */
include/libdecnumber/decNumber.h +2 -2
index 5cf18ab..0e912db 100644
@@ -34,7 +34,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
   #define DECAUTHOR   "Mike Cowlishaw"		      /* Who to blame */
 
   #if !defined(DECCONTEXT)
-    #include "decContext.h"
+    #include "libdecnumber/decContext.h"
   #endif
 
   /* Bit settings for decNumber.bits				      */
@@ -106,7 +106,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
   /* decNumber public functions and macros			      */
   /* ---------------------------------------------------------------- */
 
-  #include "decNumberSymbols.h"
+  #include "libdecnumber/decNumberSymbols.h"
 
   /* Conversions						      */
   decNumber * decNumberFromInt32(decNumber *, int32_t);
include/libdecnumber/decNumberLocal.h +1 -1
index 71c8467..431e4e6 100644
@@ -39,7 +39,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
   #include <stdlib.h>	      /* for abs			      */
   #include <string.h>	      /* for memset, strcpy		      */
-  #include "dconfig.h"	      /* for WORDS_BIGENDIAN                  */
+  #include "libdecnumber/dconfig.h"
 
   /* Conditional code flag -- set this to match hardware platform     */
   /* 1=little-endian, 0=big-endian	                              */
include/libdecnumber/decQuad.h +1 -1
index c8ec11c..ed91c39 100644
@@ -52,7 +52,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
   #define DECQUAD_Ehigh (DECQUAD_Emax + DECQUAD_Bias - (DECQUAD_Pmax-1))
 
   /* Required include						      */
-  #include "decContext.h"
+  #include "libdecnumber/decContext.h"
 
   /* The decQuad decimal 128-bit type, accessible by various types */
   typedef union {
include/libdecnumber/dpd/decimal128.h +1 -1
index 9fc532b..ee29b2d 100644
@@ -55,7 +55,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     #define DECNUMDIGITS DECIMAL128_Pmax /* size if not already defined*/
   #endif
   #ifndef DECNUMBER
-    #include "decNumber.h"		/* context and number library */
+    #include "libdecnumber/decNumber.h"
   #endif
 
   /* Decimal 128-bit type, accessible by bytes			      */
include/libdecnumber/dpd/decimal64.h +1 -1
index 7a9f8ee..180e458 100644
@@ -57,7 +57,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     #define DECNUMDIGITS DECIMAL64_Pmax /* size if not already defined*/
   #endif
   #ifndef DECNUMBER
-    #include "decNumber.h"		/* context and number library */
+    #include "libdecnumber/decNumber.h"
   #endif
 
   /* Decimal 64-bit type, accessible by bytes			      */
libdecnumber/decContext.c +3 -3
index c68101b..a8b3483 100644
@@ -32,9 +32,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 #include <string.h>	      /* for strcmp */
 #include <stdio.h>	      /* for printf if DECCHECK */
-#include "dconfig.h"	      /* for GCC definitions */
-#include "decContext.h"	      /* context and base types */
-#include "decNumberLocal.h"   /* decNumber local types, etc. */
+#include "libdecnumber/dconfig.h"
+#include "libdecnumber/decContext.h"
+#include "libdecnumber/decNumberLocal.h"
 
 #if DECCHECK
 /* compile-time endian tester [assumes sizeof(Int)>1] */
libdecnumber/decNumber.c +3 -3
index ba57163..c0429e5 100644
@@ -165,9 +165,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include <stdio.h>		   /* for printf [if needed] */
 #include <string.h>		   /* for strcpy */
 #include <ctype.h>		   /* for lower */
-#include "dconfig.h"		   /* for GCC definitions */
-#include "decNumber.h"		   /* base number library */
-#include "decNumberLocal.h"	   /* decNumber local types, etc. */
+#include "libdecnumber/dconfig.h"
+#include "libdecnumber/decNumber.h"
+#include "libdecnumber/decNumberLocal.h"
 
 /* Constants */
 /* Public lookup table used by the D2U macro */
libdecnumber/dpd/decimal128.c +4 -4
index 9fb2b3e..c0f5786 100644
@@ -37,11 +37,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include <string.h>	      /* [for memset/memcpy] */
 #include <stdio.h>	      /* [for printf] */
 
-#include "dconfig.h"	      /* GCC definitions */
+#include "libdecnumber/dconfig.h"
 #define	 DECNUMDIGITS 34      /* make decNumbers with space for 34 */
-#include "decNumber.h"	      /* base number library */
-#include "decNumberLocal.h"   /* decNumber local types, etc. */
-#include "decimal128.h"	      /* our primary include */
+#include "libdecnumber/decNumber.h"
+#include "libdecnumber/decNumberLocal.h"
+#include "libdecnumber/dpd/decimal128.h"
 
 /* Utility routines and tables [in decimal64.c] */
 extern const uInt   COMBEXP[32], COMBMSD[32];
libdecnumber/dpd/decimal64.c +6 -6
index 1456133..53386ab 100644
@@ -37,11 +37,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include <string.h>	      /* [for memset/memcpy] */
 #include <stdio.h>	      /* [for printf] */
 
-#include "dconfig.h"	      /* GCC definitions */
+#include "libdecnumber/dconfig.h"
 #define	 DECNUMDIGITS 16      /* make decNumbers with space for 16 */
-#include "decNumber.h"	      /* base number library */
-#include "decNumberLocal.h"   /* decNumber local types, etc. */
-#include "decimal64.h"	      /* our primary include */
+#include "libdecnumber/decNumber.h"
+#include "libdecnumber/decNumberLocal.h"
+#include "libdecnumber/dpd/decimal64.h"
 
 /* Utility routines and tables [in decimal64.c]; externs for C++ */
 extern const uInt COMBEXP[32], COMBMSD[32];
@@ -65,7 +65,7 @@ extern void decNumberShow(const decNumber *);	  /* .. */
 #define DEC_BIN2CHAR 1
 #define DEC_DPD2BIN  1
 #define DEC_BIN2DPD  1		   /* used for all sizes */
-#include "decDPD.h"		   /* lookup tables */
+#include "libdecnumber/decDPD.h"
 
 /* ------------------------------------------------------------------ */
 /* decimal64FromNumber -- convert decNumber to decimal64	      */
@@ -554,7 +554,7 @@ void decimal64Show(const decimal64 *d64) {
 #else
   #define DEC_DPD2BCD 1
 #endif
-#include "decDPD.h"	      /* lookup tables */
+#include "libdecnumber/decDPD.h"
 
 /* The maximum number of decNumberUnits needed for a working copy of */
 /* the units array is the ceiling of digits/DECDPUN, where digits is */
Signature · 1 line
1.7.1
author
#3 lore raw

RFC 3/12 target-ppc: Modify dconfig.h to Integrate with QEMU

In reply to Tom Musta

This patch modifies the dconfig.h header file so that libdecnumber code integrates correctly with QEMU. Normally, this file is generated from a configuration script, but it can be replaced with a static file for this usage within QEMU:

- the WORDS_BIGENDIAN preprocessor macro is used in libdecnumber code to determines endianness. It is derived from the existing QEMU macro HOST_WORDS_BIGENDIAN which is defined in config-host.h.

- the DECPUN macro determines the number of decimal digits (aka declets) per unit (byte). This is 3 for PowerPC DFP.

---
 include/libdecnumber/dconfig.h |   24 ++++++------------------
 1 files changed, 6 insertions(+), 18 deletions(-)
include/libdecnumber/dconfig.h +6 -18
index 91aa334..d4fed0d 100644
@@ -22,26 +22,14 @@ a copy of the GCC Runtime Library Exception along with this program;
 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 <http://www.gnu.org/licenses/>.  */
 
-#ifdef IN_LIBGCC2
+#include "config-host.h"
 
-#include "tconfig.h"
-#include "coretypes.h"
-#include "tm.h"
-
-#ifndef LIBGCC2_WORDS_BIG_ENDIAN
-#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
-#endif
-
-#ifndef LIBGCC2_FLOAT_WORDS_BIG_ENDIAN
-#define LIBGCC2_FLOAT_WORDS_BIG_ENDIAN LIBGCC2_WORDS_BIG_ENDIAN
-#endif
-
-#if LIBGCC2_FLOAT_WORDS_BIG_ENDIAN
+#if defined(HOST_WORDS_BIGENDIAN)
 #define WORDS_BIGENDIAN 1
-#endif
-
 #else
+#define WORDS_BIGENDIAN 0
+#endif
 
-#include "config.h"
-
+#ifndef DECDPUN
+#define DECDPUN 3
 #endif
Signature · 1 line
1.7.1
author
#4 lore raw

RFC 4/12 target-ppc: Change gstdint.h to stdint.h

In reply to Tom Musta

This patch replaces the inclusion of gstdint.h to the standard stdint.h.

---
 include/libdecnumber/decContext.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
include/libdecnumber/decContext.h +1 -1
index 2e8f2e1..ffed769 100644
@@ -51,7 +51,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
   #define DECCFULLNAME "Decimal Context Descriptor"   /* Verbose name */
   #define DECCAUTHOR   "Mike Cowlishaw"		      /* Who to blame */
 
-  #include "gstdint.h"		   /* C99 standard integers	      */
+  #include <stdint.h>		   /* C99 standard integers	      */
   #include <stdio.h>		   /* for printf, etc.		      */
   #include <signal.h>		   /* for traps			      */
 
Signature · 1 line
1.7.1
author
#5 lore raw

RFC 5/12 target-ppc: Eliminate redundant declarations

In reply to Tom Musta

This patch eliminates redundant declarations of symbols DPD2BIN and BIN2DPD. These will trigger 'redundant redeclaration of ?XXX?' warnings and thus may fail QEMU compilation.

---
 libdecnumber/dpd/decimal128.c |    2 --
 libdecnumber/dpd/decimal64.c  |    2 --
 2 files changed, 0 insertions(+), 4 deletions(-)
libdecnumber/dpd/decimal128.c +0 -2
index c0f5786..3183612 100644
@@ -45,8 +45,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 /* Utility routines and tables [in decimal64.c] */
 extern const uInt   COMBEXP[32], COMBMSD[32];
-extern const uShort DPD2BIN[1024];
-extern const uShort BIN2DPD[1000];	/* [not used] */
 extern const uByte  BIN2CHAR[4001];
 
 extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
libdecnumber/dpd/decimal64.c +0 -2
index 53386ab..ccd7f6b 100644
@@ -45,8 +45,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 /* Utility routines and tables [in decimal64.c]; externs for C++ */
 extern const uInt COMBEXP[32], COMBMSD[32];
-extern const uShort DPD2BIN[1024];
-extern const uShort BIN2DPD[1000];
 extern const uByte  BIN2CHAR[4001];
 
 extern void decDigitsFromDPD(decNumber *, const uInt *, Int);
Signature · 1 line
1.7.1
author
#6 lore raw

RFC 6/12 target-ppc: Eliminate Unused Variable in decSetSubnormal

In reply to Tom Musta

This patch eliminates an unused variable in the decSetSubnormal routine. The variable dnexp is declared and eventually set but never used. This triggers a unused-but-set-variable warning, which can fail QEMU compilation.

---
 libdecnumber/decNumber.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)
libdecnumber/decNumber.c +0 -2
index c0429e5..f60837b 100644
@@ -7398,7 +7398,6 @@ static void decSetMaxValue(decNumber *dn, decContext *set) {
 /* ------------------------------------------------------------------ */
 static void decSetSubnormal(decNumber *dn, decContext *set, Int *residue,
 			    uInt *status) {
-  Int	     dnexp;	      /* saves original exponent */
   decContext workset;	      /* work */
   Int	     etiny, adjust;   /* .. */
 
@@ -7443,7 +7442,6 @@ static void decSetSubnormal(decNumber *dn, decContext *set, Int *residue,
 
   /* adjust>0, so need to rescale the result so exponent becomes Etiny */
   /* [this code is similar to that in rescale] */
-  dnexp=dn->exponent;			/* save exponent */
   workset=*set;				/* clone rounding, etc. */
   workset.digits=dn->digits-adjust;	/* set requested length */
   workset.emin-=adjust;			/* and adjust emin to match */
Signature · 1 line
1.7.1
author
#7 lore raw

RFC 7/12 target-ppc: Enable Building of libdecnumber

In reply to Tom Musta

This patch enables compilation of the newly added libdecnumber library code. Object file targets are added to Makefile.target using the newly added flag CONFIG_LIBDECNUMBER. The flag is added to the PowerPC targets (ppc[64]-linux-user, ppc[64]-softmmu).

---
 Makefile.target                      |    5 +++++
 default-configs/ppc-linux-user.mak   |    1 +
 default-configs/ppc-softmmu.mak      |    1 +
 default-configs/ppc64-linux-user.mak |    1 +
 default-configs/ppc64-softmmu.mak    |    1 +
 5 files changed, 9 insertions(+), 0 deletions(-)
Makefile.target +5 -0
index ba12340..8d31da9 100644
@@ -82,6 +82,11 @@ obj-y += disas.o
 obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o
 obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
 
+obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/decContext.o
+obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/decNumber.o
+obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/dpd/decimal64.o
+obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/dpd/decimal128.o
+
 #########################################################
 # Linux user emulator target
 
default-configs/ppc-linux-user.mak +1 -0
index 6273df2..260ba41 100644
@@ -1 +1,2 @@
 # Default configuration for ppc-linux-user
+CONFIG_LIBDECNUMBER=y
default-configs/ppc-softmmu.mak +1 -0
index 07c51ce..33f8d84 100644
@@ -49,3 +49,4 @@ CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
 CONFIG_MC146818RTC=y
 CONFIG_ETSEC=y
 CONFIG_ISA_TESTDEV=y
+CONFIG_LIBDECNUMBER=y
default-configs/ppc64-linux-user.mak +1 -0
index 422d3fb..e731ce0 100644
@@ -1 +1,2 @@
 # Default configuration for ppc64-linux-user
+CONFIG_LIBDECNUMBER=y
default-configs/ppc64-softmmu.mak +1 -0
index e2beac6..37a15b7 100644
@@ -58,3 +58,4 @@ CONFIG_I82374=y
 CONFIG_I8257=y
 CONFIG_MC146818RTC=y
 CONFIG_ISA_TESTDEV=y
+CONFIG_LIBDECNUMBER=y
Signature · 1 line
1.7.1
author
#8 lore raw

RFC 8/12 target-ppc: Define FPR Pointer Type for Helpers

In reply to Tom Musta

This patch defines a floating pointer register pointer type in the PowerPC helper header. The type will be used to pass FPR register operands to Decimal Floating Point (DFP) helpers. A pointer is used because the quadword forms of PowerPC DFP instructions operate on adjacent pairs of floating point registers and thus can be thought of as arrays of length 2.

---
 target-ppc/helper.h |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)
target-ppc/helper.h +4 -0
index 99f10de..1bebc8e 100644
@@ -614,4 +614,8 @@ DEF_HELPER_3(store_601_batl, void, env, i32, tl)
 DEF_HELPER_3(store_601_batu, void, env, i32, tl)
 #endif
 
+#define dh_alias_fprp ptr
+#define dh_ctype_fprp uint64_t *
+#define dh_is_signed_fprp dh_is_signed_ptr
+
 #include "exec/def-helper.h"
Signature · 1 line
1.7.1
author
#9 lore raw

RFC 9/12 target-ppc: Introduce Translation Macros for DFP Arithmetic Forms

In reply to Tom Musta

This patch adds macros to the PowerPC translate.c file that will be used by the Decimal Floating Point (DFP) arithmetic instructions. These instruction forms have a target operand (FRT) and two source operands (FRA, FRB). These forms also use the "Rc" bit to set the CR6 field of the PowerPC Condition Register (CR6), which is always a copy of bits 32-35 of the Floating Point Status and Control Register (FPSCR).

The quadword form instructions use pairs of floating point registers. In these instructions, the FRT, FRA and FRB instruction fields must be even; this is handled via the illegal mask that is passed to the GEN_HANDLER_E macro.

---
 target-ppc/translate.c |   63 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 63 insertions(+), 0 deletions(-)
target-ppc/translate.c +63 -0
index 91c33dc..26bfebc 100644
@@ -8180,6 +8180,58 @@ static void gen_xxsldwi(DisasContext *ctx)
     tcg_temp_free_i64(xtl);
 }
 
+/*** Decimal Floating Point ***/
+
+static inline TCGv_ptr gen_fprp_ptr(int reg)
+{
+    TCGv_ptr r = tcg_temp_new_ptr();
+    tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, fpr[reg]));
+    return r;
+}
+
+#if defined(TARGET_PPC64)
+static void gen_set_cr6_from_fpscr(DisasContext *ctx)
+{
+    TCGv_i32 tmp = tcg_temp_new_i32();
+    tcg_gen_trunc_tl_i32(tmp, cpu_fpscr);
+    tcg_gen_shri_i32(cpu_crf[1], tmp, 28);
+    tcg_temp_free_i32(tmp);
+}
+#else
+static void gen_set_cr6_from_fpscr(DisasContext *ctx)
+{
+        tcg_gen_shri_tl(cpu_crf[1], cpu_fpscr, 28);
+}
+#endif
+
+#define _GEN_DFP_TAB(name, op1, op2)             \
+static void gen_##name(DisasContext *ctx)        \
+{                                                \
+    TCGv_ptr rd, ra, rb;                         \
+    if (unlikely(!ctx->fpu_enabled)) {           \
+        gen_exception(ctx, POWERPC_EXCP_FPU);    \
+        return;                                  \
+    }                                            \
+    gen_update_nip(ctx, ctx->nip - 4);           \
+    rd = gen_fprp_ptr(rD(ctx->opcode));          \
+    ra = gen_fprp_ptr(rA(ctx->opcode));          \
+    rb = gen_fprp_ptr(rB(ctx->opcode));          \
+    gen_helper_##name(cpu_env, rd, ra, rb);      \
+    if (unlikely(Rc(ctx->opcode) != 0)) {        \
+        gen_set_cr6_from_fpscr(ctx);             \
+    }                                            \
+    tcg_temp_free_ptr(rd);                       \
+    tcg_temp_free_ptr(ra);                       \
+    tcg_temp_free_ptr(rb);                       \
+}
+
+#define GEN_DFP_TAB(name, op1, op2) \
+    _GEN_DFP_TAB(name, op1, op2)    \
+    _GEN_DFP_TAB(name##q, op1, op2)
+
+/* Avoid 'defined but not used' warnings ... this will be removed in */
+/* a subsequent patch. */
+void *_TempCr6_[] = { (void *)gen_set_cr6_from_fpscr, };
 
 /***                           SPE extension                               ***/
 /* Register moves */
@@ -10999,6 +11051,17 @@ GEN_XXSEL_ROW(0x1F)
 
 GEN_XX3FORM_DM(xxpermdi, 0x08, 0x01),
 
+#undef _GEN_DFP_TAB
+#undef GEN_DFP_TAB
+#define GEN_DFP_TAB_LONG(name, op1, op2) \
+    GEN_HANDLER_E(name, 0x3B, op1, op2, 0, PPC_NONE, PPC2_DFP)
+
+#define GEN_DFP_TAB_QUAD(name, op1, op2) \
+    GEN_HANDLER_E(name, 0x3F, op1, op2, 0x00210800, PPC_NONE, PPC2_DFP)
+
+#define GEN_DFP_TAB(name, op1, op2) \
+GEN_DFP_TAB_LONG(name, op1, op2),    \
+GEN_DFP_TAB_QUAD(name##q, op1, op2),
 #undef GEN_SPE
 #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
     GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE)
Signature · 1 line
1.7.1
author
#10 lore raw

RFC 10/12 target-ppc: Introduce DFP Helper Utilities

In reply to Tom Musta

This patch adds a new helper file to the PowerPC implementation (dfp_helper.c). This first version of the file declares a structure that will be used by various Decimal Floating Point (DFP) instructions. It also implements utilities that will initialize such a structure for either a long, 64-bit DFP instruction with two operands, or an extended, 128-bit (aka quad) DFP instruction with two operands.

Since there is not yet any code that invokes these utilities, a temporary pointer array is declared; this avoids 'defined but not used' warnings and thus preserves build bisection.

---
 target-ppc/Makefile.objs |    1 +
 target-ppc/dfp_helper.c  |  111 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 112 insertions(+), 0 deletions(-)
 create mode 100644 target-ppc/dfp_helper.c
target-ppc/Makefile.objs +1 -0
index 3cb23e0..a7ae392 100644
@@ -6,6 +6,7 @@ obj-$(TARGET_PPC64) += mmu-hash64.o arch_dump.o
 endif
 obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o
 obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
+obj-y += dfp_helper.o
 obj-y += excp_helper.o
 obj-y += fpu_helper.o
 obj-y += int_helper.o
target-ppc/dfp_helper.c new file +111 -0

111 lines not on this page · raw message

Signature · 1 line
1.7.1
author
#11 lore raw

RFC 11/12 target-ppc: Introduce DFP Post Processor Utilities

In reply to Tom Musta

This patch adds post-processing utilities to the PowerPC Decimal Floating Point (DFP) helper code. Post-processors are small routines that execute after a preliminary DFP result is computed. They are used, among other things, to compute status bits.

This patch defines a function type for post processors as well as a generic routine to run a list (array) of post-processors. It also adds several post processors that will be used in subsequent instructions.

NOTE: This is not the complete set of post processors; it is the minimal set required to demonstrate the two instructions implemented in this patch series.

---
 target-ppc/dfp_helper.c |  140 +++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 140 insertions(+), 0 deletions(-)
target-ppc/dfp_helper.c +140 -0
index 3c5988a..a3381ef 100644
@@ -103,9 +103,149 @@ static void ppc_dfp_prepare_decimal128_fra_frb(struct PPC_DFP *dfp, uint64_t *a,
     decimal128ToNumber((decimal128 *)dfp->b64, &dfp->b);
 }
 
+#define FP_FX       (1ull << FPSCR_FX)
+#define FP_FEX      (1ull << FPSCR_FEX)
+#define FP_OX       (1ull << FPSCR_OX)
+#define FP_OE       (1ull << FPSCR_OE)
+#define FP_UX       (1ull << FPSCR_UX)
+#define FP_UE       (1ull << FPSCR_UE)
+#define FP_XX       (1ull << FPSCR_XX)
+#define FP_XE       (1ull << FPSCR_XE)
+#define FP_VX       (1ull << FPSCR_VX)
+#define FP_VXSNAN   (1ull << FPSCR_VXSNAN)
+#define FP_VXISI    (1ull << FPSCR_VXISI)
+#define FP_VE       (1ull << FPSCR_VE)
+#define FP_FI       (1ull << FPSCR_FI)
+
+static void ppc_dfp_set_FPSCR_flag(struct PPC_DFP *dfp, uint64_t flag,
+                uint64_t enabled)
+{
+    dfp->env->fpscr |= (flag | FP_FX);
+    if (dfp->env->fpscr & enabled) {
+        dfp->env->fpscr |= FP_FEX;
+    }
+}
+
+typedef void (*PPC_DFP_PostProc)(struct PPC_DFP *);
+
+static void ppc_dfp_set_FPRF_from_FRT_with_context(struct PPC_DFP *dfp,
+                decContext *context)
+{
+    uint64_t fprf = 0;
+
+    /* construct FPRF */
+    switch (decNumberClass(&dfp->t, context)) {
+    case DEC_CLASS_SNAN:
+        fprf = 0x01;
+        break;
+    case DEC_CLASS_QNAN:
+        fprf = 0x11;
+        break;
+    case DEC_CLASS_NEG_INF:
+        fprf = 0x09;
+        break;
+    case DEC_CLASS_NEG_NORMAL:
+        fprf = 0x08;
+        break;
+    case DEC_CLASS_NEG_SUBNORMAL:
+        fprf = 0x18;
+        break;
+    case DEC_CLASS_NEG_ZERO:
+        fprf = 0x12;
+        break;
+    case DEC_CLASS_POS_ZERO:
+        fprf = 0x02;
+        break;
+    case DEC_CLASS_POS_SUBNORMAL:
+        fprf = 0x14;
+        break;
+    case DEC_CLASS_POS_NORMAL:
+        fprf = 0x04;
+        break;
+    case DEC_CLASS_POS_INF:
+        fprf = 0x05;
+        break;
+    default:
+        assert(0); /* should never get here */
+    }
+    dfp->env->fpscr &= ~(0x1F << 12);
+    dfp->env->fpscr |= (fprf << 12);
+}
+
+static void ppc_dfp_set_FPRF_from_FRT(struct PPC_DFP *dfp)
+{
+    ppc_dfp_set_FPRF_from_FRT_with_context(dfp, &dfp->context);
+}
+
+static void ppc_dfp_check_for_OX(struct PPC_DFP *dfp)
+{
+    if (dfp->context.status & DEC_Overflow) {
+        ppc_dfp_set_FPSCR_flag(dfp, FP_OX, FP_OE);
+    }
+}
+
+static void ppc_dfp_check_for_UX(struct PPC_DFP *dfp)
+{
+    if (dfp->context.status & DEC_Underflow) {
+        ppc_dfp_set_FPSCR_flag(dfp, FP_UX, FP_UE);
+    }
+}
+
+static void ppc_dfp_check_for_XX(struct PPC_DFP *dfp)
+{
+    if (dfp->context.status & DEC_Inexact) {
+        ppc_dfp_set_FPSCR_flag(dfp, FP_XX | FP_FI, FP_XE);
+    }
+}
+
+static void ppc_dfp_check_for_VXSNAN(struct PPC_DFP *dfp)
+{
+    if (dfp->context.status & DEC_Invalid_operation) {
+        if (decNumberIsSNaN(&dfp->a) || decNumberIsSNaN(&dfp->b)) {
+            ppc_dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FP_VE);
+        }
+    }
+}
+
+static void ppc_dfp_check_for_VXISI(struct PPC_DFP *dfp, int testForSameSign)
+{
+    if (dfp->context.status & DEC_Invalid_operation) {
+        if (decNumberIsInfinite(&dfp->a) && decNumberIsInfinite(&dfp->b)) {
+            int same = decNumberClass(&dfp->a, &dfp->context) ==
+                       decNumberClass(&dfp->b, &dfp->context);
+            if ((same && testForSameSign) || (!same && !testForSameSign)) {
+                ppc_dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXISI, FP_VE);
+            }
+        }
+    }
+}
+
+static void ppc_dfp_check_for_VXISI_add(struct PPC_DFP *dfp)
+{
+    ppc_dfp_check_for_VXISI(dfp, 0);
+}
+
+static void ppc_dfp_run_post_processors(struct PPC_DFP *dfp,
+                PPC_DFP_PostProc post_processors[], const size_t n)
+{
+    int i;
+
+    for (i = 0; i < n; i++) {
+        post_processors[i](dfp);
+    }
+}
+
+
 void *_TmpAvoidDefinedButNotUsedWarnings_[] = {
     (void *)ppc_dfp_prepare_decimal64_fra_frb,
     (void *)ppc_dfp_prepare_decimal128_fra_frb,
+    (void *)ppc_dfp_run_post_processors,
+    (void *)ppc_dfp_set_FPRF_from_FRT,
+    (void *)ppc_dfp_check_for_OX,
+    (void *)ppc_dfp_check_for_UX,
+    (void *)ppc_dfp_check_for_XX,
+    (void *)ppc_dfp_check_for_VXSNAN,
+    (void *)ppc_dfp_check_for_VXISI_add,
 };
 
 
Signature · 1 line
1.7.1
author
#12 lore raw

RFC 12/12 target-ppc: Introduce DFP Add

In reply to Tom Musta

This patch provides the implementation for the Decimal Floating Point (DFP) Add instructions (dadd, daddq).

---
 target-ppc/dfp_helper.c |   35 ++++++++++++++++++++++++-----------
 target-ppc/helper.h     |    3 +++
 target-ppc/translate.c  |    8 +++++---
 3 files changed, 32 insertions(+), 14 deletions(-)
target-ppc/dfp_helper.c +24 -11
index a3381ef..46a83e4 100644
@@ -235,17 +235,30 @@ static void ppc_dfp_run_post_processors(struct PPC_DFP *dfp,
     }
 }
 
+#define DFP_HELPER_TAB(op, dnop, postprocs, size)                              \
+void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b)      \
+{                                                                              \
+    struct PPC_DFP dfp;                                                        \
+    ppc_dfp_prepare_decimal##size##_fra_frb(&dfp, a, b, env);                  \
+    dnop(&dfp.t, &dfp.a, &dfp.b, &dfp.context);                                \
+    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \
+    ppc_dfp_run_post_processors(&dfp, postprocs, ARRAY_SIZE(postprocs));       \
+    if (size == 64) {                                                          \
+        t[0] = dfp.t64[0];                                                     \
+    } else if (size == 128) {                                                  \
+        t[0] = dfp.t64[HI_IDX];                                                \
+        t[1] = dfp.t64[LO_IDX];                                                \
+    }                                                                          \
+}
 
-void *_TmpAvoidDefinedButNotUsedWarnings_[] = {
-    (void *)ppc_dfp_prepare_decimal64_fra_frb,
-    (void *)ppc_dfp_prepare_decimal128_fra_frb,
-    (void *)ppc_dfp_run_post_processors,
-    (void *)ppc_dfp_set_FPRF_from_FRT,
-    (void *)ppc_dfp_check_for_OX,
-    (void *)ppc_dfp_check_for_UX,
-    (void *)ppc_dfp_check_for_XX,
-    (void *)ppc_dfp_check_for_VXSNAN,
-    (void *)ppc_dfp_check_for_VXISI_add,
+PPC_DFP_PostProc ADD_PPs[] = {
+    ppc_dfp_set_FPRF_from_FRT,
+    ppc_dfp_check_for_OX,
+    ppc_dfp_check_for_UX,
+    ppc_dfp_check_for_XX,
+    ppc_dfp_check_for_VXSNAN,
+    ppc_dfp_check_for_VXISI_add,
 };
 
-
+DFP_HELPER_TAB(dadd, decNumberAdd, ADD_PPs, 64)
+DFP_HELPER_TAB(daddq, decNumberAdd, ADD_PPs, 128)
target-ppc/helper.h +3 -0
index 1bebc8e..6054554 100644
@@ -618,4 +618,7 @@ DEF_HELPER_3(store_601_batu, void, env, i32, tl)
 #define dh_ctype_fprp uint64_t *
 #define dh_is_signed_fprp dh_is_signed_ptr
 
+DEF_HELPER_4(dadd, void, env, fprp, fprp, fprp)
+DEF_HELPER_4(daddq, void, env, fprp, fprp, fprp)
+
 #include "exec/def-helper.h"
target-ppc/translate.c +5 -3
index 26bfebc..de9ddb6 100644
@@ -8229,9 +8229,8 @@ static void gen_##name(DisasContext *ctx)        \
     _GEN_DFP_TAB(name, op1, op2)    \
     _GEN_DFP_TAB(name##q, op1, op2)
 
-/* Avoid 'defined but not used' warnings ... this will be removed in */
-/* a subsequent patch. */
-void *_TempCr6_[] = { (void *)gen_set_cr6_from_fpscr, };
+GEN_DFP_TAB(dadd, 0x02, 0x00)
+
 
 /***                           SPE extension                               ***/
 /* Register moves */
@@ -11062,6 +11061,9 @@ GEN_XX3FORM_DM(xxpermdi, 0x08, 0x01),
 #define GEN_DFP_TAB(name, op1, op2) \
 GEN_DFP_TAB_LONG(name, op1, op2),    \
 GEN_DFP_TAB_QUAD(name##q, op1, op2),
+
+GEN_DFP_TAB(dadd, 0x02, 0x00)
+
 #undef GEN_SPE
 #define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
     GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE)
Signature · 1 line
1.7.1
#13 lore raw
In reply to Tom Musta
Quoted 44 lines · Tom Musta

This patch series provides a prototype of Decimal Floating Point (DFP) instruction support in QEMU. The topic was briefly discussed here:
http://lists.nongnu.org/archive/html/qemu-ppc/2014-02/msg00129.html

I. Overview

The core of the DFP model is a library named libdecnumber, which is a sub-library of GCC's libdfp. Libdecnumber's model uses an expanded internal representation of a decimal floating point number as:

- exponent (base 10)
- the number of digits (aka declets)
- flags (sign bit and "special" bits for NaNs and infinities)
- an array of units. Each unit contains DECPUN declets.

Libdecnumber provides routines for various arithmetic operations (e.g. decNumberAdd for addition) as well as converters for going to/from binary form.

PowerPC's support of DFP uses Densely Packed Decimal (DPD) format. The standard floating point registers are re-used to hold DFP operands. There are typically PowerPC instructions for both the long (64 bit) and extended (128 bit, aka quad) formats. The extended format instructions use adjacent pairs of FPRs to hold the 128 bit operands.

II. A Simple Example

PowerPC DFP instructions are implemented using helpers, which in turn use libdecnumber routines to perform the detailed computations. This is similar to how softfloat is used to model binary floating point instructions.

For example, the implementation of the helper for DFP Add Long (dadd) looks like this:

1) Establish a libdecnumber context for 64-bit computation (decContext)
2) Convert the two source FPRs from DPD to decNumbers (the expanded internal representation)
3) Invoke the add operation (decNumberAdd)
4) Inspect the context's flags for various exception situations (e.g. overflow), mapping them to the corresponding FPSCR status flags.
5) Convert the summand to DPD form and store into the target FPR.

The helper for the DPD Add Extended (daddq) is nearly identical. It differs only in that it establishes a 128 bit context and the conversions are from and to 128 bit DPD format.

Quoted 5 lines

III. Integration of libdecnumber in QEMU

The appoach taken here is direct and simple:

1) A copy of libdecnumber code is imported into QEMU. The header files are placed under

I don't think this is possible. Libdecnumber is GPLv3+ code while QEMU overall is licensed at GPLv2 only. Gotta love licenses...

Is there an older, GPLv2 licensed version available?

Alex

author
#14 lore raw
Quoted 3 lines · Alexander Graf

I don't think this is possible. Libdecnumber is GPLv3+ code while QEMU overall is licensed at GPLv2 only. Gotta love licenses...

Is there an older, GPLv2 licensed version available?

Interesting timing .... I was just about to put out a complete patch set for all of DFP.

In earlier feedback, Richard had suggested that I go further upstream inside of IBM ... which I did. But of course, that is also GPLv3.

The original copy comes from here : http://spelotrove.com/decimal/#decNumber which was published with something called the ICU 1.8.1 license. I am not at all familiar with that license.

Looks like I'm going to have to "lawyer up" :)

#15 lore raw
Quoted 6 lines · Tom Musta
Quoted 3 lines · Alexander Graf

I don't think this is possible. Libdecnumber is GPLv3+ code while QEMU overall is licensed at GPLv2 only. Gotta love licenses...

Is there an older, GPLv2 licensed version available?

Interesting timing .... I was just about to put out a complete patch set for all of DFP.

Quoted 7 lines

In earlier feedback, Richard had suggested that I go further upstream inside of IBM ... which I did. But of course, that is also GPLv3.

The original copy comes from here : http://spelotrove.com/decimal/#decNumber which was published with something called the ICU 1.8.1 license. I am not at all familiar with that license.

Looks like I'm going to have to "lawyer up" :)

Yes, please do. I'm sure IBM has plenty lawyers who are happy to help out here :).

Alex