Upgrade to softfloat3e.

This should solve licensing problems as well.
This commit is contained in:
TC1995
2024-06-09 23:08:46 +02:00
parent 4b77ef6823
commit 0f29bcddf1
271 changed files with 25882 additions and 10441 deletions

View File

@@ -34,5 +34,5 @@ if(DYNAREC)
codegen_timing_winchip.c codegen_timing_winchip2.c)
endif()
add_subdirectory(softfloat)
target_link_libraries(86Box softfloat)
add_subdirectory(softfloat3e)
target_link_libraries(86Box softfloat3e)

View File

@@ -21,7 +21,7 @@
#ifndef EMU_CPU_H
#define EMU_CPU_H
#include "softfloat/softfloat.h"
#include "softfloat3e/softfloat.h"
enum {
FPU_NONE,
@@ -592,8 +592,6 @@ extern uint32_t eip_msr;
extern uint64_t amd_efer;
extern uint64_t star;
#define FPU_CW_Reserved_Bits (0xe0c0)
#define cr0 cpu_state.CR0.l
#define msw cpu_state.CR0.w
extern uint32_t cr2;

View File

@@ -1,17 +0,0 @@
#
# 86Box A hypervisor and IBM PC system emulator that specializes in
# running old operating systems and software designed for IBM
# PC systems and compatibles from 1981 through fairly recent
# system designs based on the PCI bus.
#
# This file is part of the 86Box distribution.
#
# CMake build script.
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# Copyright 2020-2021 David Hrdlička.
#
add_library(softfloat OBJECT f2xm1.cc fpatan.cc fprem.cc fsincos.cc fyl2x.cc softfloat_poly.cc softfloat.cc softfloat16.cc
softfloat-muladd.cc softfloat-round-pack.cc softfloat-specialize.cc softfloatx80.cc)

View File

@@ -1,51 +0,0 @@
#ifndef EMU_SF_CONFIG_H
#define EMU_SF_CONFIG_H
#include <stdint.h>
typedef int8_t flag;
typedef uint8_t uint8;
typedef int8_t int8;
typedef uint16_t uint16;
typedef int16_t int16;
typedef uint32_t uint32;
typedef int32_t int32;
typedef uint64_t uint64;
typedef int64_t int64;
/*----------------------------------------------------------------------------
| Each of the following `typedef's defines a type that holds integers
| of _exactly_ the number of bits specified. For instance, for most
| implementation of C, `bits16' and `sbits16' should be `typedef'ed to
| `unsigned short int' and `signed short int' (or `short int'), respectively.
*----------------------------------------------------------------------------*/
typedef uint8_t bits8;
typedef int8_t sbits8;
typedef uint16_t bits16;
typedef int16_t sbits16;
typedef uint32_t bits32;
typedef int32_t sbits32;
typedef uint64_t bits64;
typedef int64_t sbits64;
typedef uint8_t Bit8u;
typedef int8_t Bit8s;
typedef uint16_t Bit16u;
typedef int16_t Bit16s;
typedef uint32_t Bit32u;
typedef int32_t Bit32s;
typedef uint64_t Bit64u;
typedef int64_t Bit64s;
/*----------------------------------------------------------------------------
| The `LIT64' macro takes as its argument a textual integer literal and
| if necessary ``marks'' the literal as having a 64-bit integer type.
| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be
| appended with the letters `LL' standing for `long long', which is `gcc's
| name for the 64-bit integer type. Some compilers may allow `LIT64' to be
| defined as the identity macro: `#define LIT64( a ) a'.
*----------------------------------------------------------------------------*/
#define BX_CONST64(a) a##LL
#define BX_CPP_INLINE static __inline
#endif /*EMU_SF_CONFIG_H*/

View File

@@ -1,496 +0,0 @@
/*============================================================================
This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
Package, Release 2b.
Written by John R. Hauser. This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704. Funding was partially provided by the
National Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
arithmetic/SoftFloat.html'.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.
=============================================================================*/
/*============================================================================
* Adapted for Bochs (x86 achitecture simulator) by
* Stanislav Shwartsman [sshwarts at sourceforge net]
* ==========================================================================*/
#ifndef _SOFTFLOAT_COMPARE_H_
#define _SOFTFLOAT_COMPARE_H_
#include "softfloat.h"
// ======= float32 ======= //
typedef int (*float32_compare_method)(float32, float32, struct float_status_t *status);
// 0x00
BX_CPP_INLINE int float32_eq_ordered_quiet(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_quiet(a, b, status);
return (relation == float_relation_equal);
}
// 0x01
BX_CPP_INLINE int float32_lt_ordered_signalling(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_two(a, b, status);
return (relation == float_relation_less);
}
// 0x02
BX_CPP_INLINE int float32_le_ordered_signalling(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_two(a, b, status);
return (relation == float_relation_less) || (relation == float_relation_equal);
}
// 0x03
BX_CPP_INLINE int float32_unordered_quiet(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_quiet(a, b, status);
return (relation == float_relation_unordered);
}
// 0x04
BX_CPP_INLINE int float32_neq_unordered_quiet(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_quiet(a, b, status);
return (relation != float_relation_equal);
}
// 0x05
BX_CPP_INLINE int float32_nlt_unordered_signalling(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_two(a, b, status);
return (relation != float_relation_less);
}
// 0x06
BX_CPP_INLINE int float32_nle_unordered_signalling(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_two(a, b, status);
return (relation != float_relation_less) && (relation != float_relation_equal);
}
// 0x07
BX_CPP_INLINE int float32_ordered_quiet(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_quiet(a, b, status);
return (relation != float_relation_unordered);
}
// 0x08
BX_CPP_INLINE int float32_eq_unordered_quiet(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_quiet(a, b, status);
return (relation == float_relation_equal) || (relation == float_relation_unordered);
}
// 0x09
BX_CPP_INLINE int float32_nge_unordered_signalling(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_two(a, b, status);
return (relation == float_relation_less) || (relation == float_relation_unordered);
}
// 0x0a
BX_CPP_INLINE int float32_ngt_unordered_signalling(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_two(a, b, status);
return (relation != float_relation_greater);
}
// 0x0b
BX_CPP_INLINE int float32_false_quiet(float32 a, float32 b, struct float_status_t *status)
{
float32_compare_quiet(a, b, status);
return 0;
}
// 0x0c
BX_CPP_INLINE int float32_neq_ordered_quiet(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_quiet(a, b, status);
return (relation != float_relation_equal) && (relation != float_relation_unordered);
}
// 0x0d
BX_CPP_INLINE int float32_ge_ordered_signalling(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_two(a, b, status);
return (relation == float_relation_greater) || (relation == float_relation_equal);
}
// 0x0e
BX_CPP_INLINE int float32_gt_ordered_signalling(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_two(a, b, status);
return (relation == float_relation_greater);
}
// 0x0f
BX_CPP_INLINE int float32_true_quiet(float32 a, float32 b, struct float_status_t *status)
{
float32_compare_quiet(a, b, status);
return 1;
}
// 0x10
BX_CPP_INLINE int float32_eq_ordered_signalling(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_two(a, b, status);
return (relation == float_relation_equal);
}
// 0x11
BX_CPP_INLINE int float32_lt_ordered_quiet(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_quiet(a, b, status);
return (relation == float_relation_less);
}
// 0x12
BX_CPP_INLINE int float32_le_ordered_quiet(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_quiet(a, b, status);
return (relation == float_relation_less) || (relation == float_relation_equal);
}
// 0x13
BX_CPP_INLINE int float32_unordered_signalling(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_two(a, b, status);
return (relation == float_relation_unordered);
}
// 0x14
BX_CPP_INLINE int float32_neq_unordered_signalling(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_two(a, b, status);
return (relation != float_relation_equal);
}
// 0x15
BX_CPP_INLINE int float32_nlt_unordered_quiet(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_quiet(a, b, status);
return (relation != float_relation_less);
}
// 0x16
BX_CPP_INLINE int float32_nle_unordered_quiet(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_quiet(a, b, status);
return (relation != float_relation_less) && (relation != float_relation_equal);
}
// 0x17
BX_CPP_INLINE int float32_ordered_signalling(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_two(a, b, status);
return (relation != float_relation_unordered);
}
// 0x18
BX_CPP_INLINE int float32_eq_unordered_signalling(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_two(a, b, status);
return (relation == float_relation_equal) || (relation == float_relation_unordered);
}
// 0x19
BX_CPP_INLINE int float32_nge_unordered_quiet(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_quiet(a, b, status);
return (relation == float_relation_less) || (relation == float_relation_unordered);
}
// 0x1a
BX_CPP_INLINE int float32_ngt_unordered_quiet(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_quiet(a, b, status);
return (relation != float_relation_greater);
}
// 0x1b
BX_CPP_INLINE int float32_false_signalling(float32 a, float32 b, struct float_status_t *status)
{
float32_compare_two(a, b, status);
return 0;
}
// 0x1c
BX_CPP_INLINE int float32_neq_ordered_signalling(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_two(a, b, status);
return (relation != float_relation_equal) && (relation != float_relation_unordered);
}
// 0x1d
BX_CPP_INLINE int float32_ge_ordered_quiet(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_quiet(a, b, status);
return (relation == float_relation_greater) || (relation == float_relation_equal);
}
// 0x1e
BX_CPP_INLINE int float32_gt_ordered_quiet(float32 a, float32 b, struct float_status_t *status)
{
int relation = float32_compare_quiet(a, b, status);
return (relation == float_relation_greater);
}
// 0x1f
BX_CPP_INLINE int float32_true_signalling(float32 a, float32 b, struct float_status_t *status)
{
float32_compare_two(a, b, status);
return 1;
}
// ======= float64 ======= //
typedef int (*float64_compare_method)(float64, float64, struct float_status_t *status);
// 0x00
BX_CPP_INLINE int float64_eq_ordered_quiet(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_quiet(a, b, status);
return (relation == float_relation_equal);
}
// 0x01
BX_CPP_INLINE int float64_lt_ordered_signalling(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_two(a, b, status);
return (relation == float_relation_less);
}
// 0x02
BX_CPP_INLINE int float64_le_ordered_signalling(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_two(a, b, status);
return (relation == float_relation_less) || (relation == float_relation_equal);
}
// 0x03
BX_CPP_INLINE int float64_unordered_quiet(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_quiet(a, b, status);
return (relation == float_relation_unordered);
}
// 0x04
BX_CPP_INLINE int float64_neq_unordered_quiet(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_quiet(a, b, status);
return (relation != float_relation_equal);
}
// 0x05
BX_CPP_INLINE int float64_nlt_unordered_signalling(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_two(a, b, status);
return (relation != float_relation_less);
}
// 0x06
BX_CPP_INLINE int float64_nle_unordered_signalling(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_two(a, b, status);
return (relation != float_relation_less) && (relation != float_relation_equal);
}
// 0x07
BX_CPP_INLINE int float64_ordered_quiet(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_quiet(a, b, status);
return (relation != float_relation_unordered);
}
// 0x08
BX_CPP_INLINE int float64_eq_unordered_quiet(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_quiet(a, b, status);
return (relation == float_relation_equal) || (relation == float_relation_unordered);
}
// 0x09
BX_CPP_INLINE int float64_nge_unordered_signalling(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_two(a, b, status);
return (relation == float_relation_less) || (relation == float_relation_unordered);
}
// 0x0a
BX_CPP_INLINE int float64_ngt_unordered_signalling(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_two(a, b, status);
return (relation != float_relation_greater);
}
// 0x0b
BX_CPP_INLINE int float64_false_quiet(float64 a, float64 b, struct float_status_t *status)
{
float64_compare_quiet(a, b, status);
return 0;
}
// 0x0c
BX_CPP_INLINE int float64_neq_ordered_quiet(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_quiet(a, b, status);
return (relation != float_relation_equal) && (relation != float_relation_unordered);
}
// 0x0d
BX_CPP_INLINE int float64_ge_ordered_signalling(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_two(a, b, status);
return (relation == float_relation_greater) || (relation == float_relation_equal);
}
// 0x0e
BX_CPP_INLINE int float64_gt_ordered_signalling(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_two(a, b, status);
return (relation == float_relation_greater);
}
// 0x0f
BX_CPP_INLINE int float64_true_quiet(float64 a, float64 b, struct float_status_t *status)
{
float64_compare_quiet(a, b, status);
return 1;
}
// 0x10
BX_CPP_INLINE int float64_eq_ordered_signalling(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_two(a, b, status);
return (relation == float_relation_equal);
}
// 0x11
BX_CPP_INLINE int float64_lt_ordered_quiet(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_quiet(a, b, status);
return (relation == float_relation_less);
}
// 0x12
BX_CPP_INLINE int float64_le_ordered_quiet(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_quiet(a, b, status);
return (relation == float_relation_less) || (relation == float_relation_equal);
}
// 0x13
BX_CPP_INLINE int float64_unordered_signalling(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_two(a, b, status);
return (relation == float_relation_unordered);
}
// 0x14
BX_CPP_INLINE int float64_neq_unordered_signalling(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_two(a, b, status);
return (relation != float_relation_equal);
}
// 0x15
BX_CPP_INLINE int float64_nlt_unordered_quiet(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_quiet(a, b, status);
return (relation != float_relation_less);
}
// 0x16
BX_CPP_INLINE int float64_nle_unordered_quiet(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_quiet(a, b, status);
return (relation != float_relation_less) && (relation != float_relation_equal);
}
// 0x17
BX_CPP_INLINE int float64_ordered_signalling(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_two(a, b, status);
return (relation != float_relation_unordered);
}
// 0x18
BX_CPP_INLINE int float64_eq_unordered_signalling(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_two(a, b, status);
return (relation == float_relation_equal) || (relation == float_relation_unordered);
}
// 0x19
BX_CPP_INLINE int float64_nge_unordered_quiet(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_quiet(a, b, status);
return (relation == float_relation_less) || (relation == float_relation_unordered);
}
// 0x1a
BX_CPP_INLINE int float64_ngt_unordered_quiet(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_quiet(a, b, status);
return (relation != float_relation_greater);
}
// 0x1b
BX_CPP_INLINE int float64_false_signalling(float64 a, float64 b, struct float_status_t *status)
{
float64_compare_two(a, b, status);
return 0;
}
// 0x1c
BX_CPP_INLINE int float64_neq_ordered_signalling(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_two(a, b, status);
return (relation != float_relation_equal) && (relation != float_relation_unordered);
}
// 0x1d
BX_CPP_INLINE int float64_ge_ordered_quiet(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_quiet(a, b, status);
return (relation == float_relation_greater) || (relation == float_relation_equal);
}
// 0x1e
BX_CPP_INLINE int float64_gt_ordered_quiet(float64 a, float64 b, struct float_status_t *status)
{
int relation = float64_compare_quiet(a, b, status);
return (relation == float_relation_greater);
}
// 0x1f
BX_CPP_INLINE int float64_true_signalling(float64 a, float64 b, struct float_status_t *status)
{
float64_compare_two(a, b, status);
return 1;
}
#endif

View File

@@ -1,686 +0,0 @@
/*============================================================================
This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
Arithmetic Package, Release 2b.
Written by John R. Hauser. This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704. Funding was partially provided by the
National Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
arithmetic/SoftFloat.html'.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.
=============================================================================*/
/*============================================================================
* Adapted for Bochs (x86 achitecture simulator) by
* Stanislav Shwartsman [sshwarts at sourceforge net]
* ==========================================================================*/
#ifndef _SOFTFLOAT_MACROS_H_
#define _SOFTFLOAT_MACROS_H_
/*----------------------------------------------------------------------------
| Shifts `a' right by the number of bits given in `count'. If any nonzero
| bits are shifted off, they are ``jammed'' into the least significant bit of
| the result by setting the least significant bit to 1. The value of `count'
| can be arbitrarily large; in particular, if `count' is greater than 16, the
| result will be either 0 or 1, depending on whether `a' is zero or nonzero.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit16u shift16RightJamming(Bit16u a, int count)
{
Bit16u z;
if (count == 0) {
z = a;
}
else if (count < 16) {
z = (a>>count) | ((a<<((-count) & 15)) != 0);
}
else {
z = (a != 0);
}
return z;
}
/*----------------------------------------------------------------------------
| Shifts `a' right by the number of bits given in `count'. If any nonzero
| bits are shifted off, they are ``jammed'' into the least significant bit of
| the result by setting the least significant bit to 1. The value of `count'
| can be arbitrarily large; in particular, if `count' is greater than 32, the
| result will be either 0 or 1, depending on whether `a' is zero or nonzero.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit32u shift32RightJamming(Bit32u a, int count)
{
Bit32u z;
if (count == 0) {
z = a;
}
else if (count < 32) {
z = (a>>count) | ((a<<((-count) & 31)) != 0);
}
else {
z = (a != 0);
}
return z;
}
/*----------------------------------------------------------------------------
| Shifts `a' right by the number of bits given in `count'. If any nonzero
| bits are shifted off, they are ``jammed'' into the least significant bit of
| the result by setting the least significant bit to 1. The value of `count'
| can be arbitrarily large; in particular, if `count' is greater than 64, the
| result will be either 0 or 1, depending on whether `a' is zero or nonzero.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit64u shift64RightJamming(Bit64u a, int count)
{
Bit64u z;
if (count == 0) {
z = a;
}
else if (count < 64) {
z = (a>>count) | ((a << ((-count) & 63)) != 0);
}
else {
z = (a != 0);
}
return z;
}
/*----------------------------------------------------------------------------
| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64
| _plus_ the number of bits given in `count'. The shifted result is at most
| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The
| bits shifted off form a second 64-bit result as follows: The _last_ bit
| shifted off is the most-significant bit of the extra result, and the other
| 63 bits of the extra result are all zero if and only if _all_but_the_last_
| bits shifted off were all zero. This extra result is stored in the location
| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large.
| (This routine makes more sense if `a0' and `a1' are considered to form
| a fixed-point value with binary point between `a0' and `a1'. This fixed-
| point value is shifted right by the number of bits given in `count', and
| the integer part of the result is returned at the location pointed to by
| `z0Ptr'. The fractional part of the result may be slightly corrupted as
| described above, and is returned at the location pointed to by `z1Ptr'.)
*----------------------------------------------------------------------------*/
BX_CPP_INLINE void shift64ExtraRightJamming(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr)
{
Bit64u z0, z1;
int negCount = (-count) & 63;
if (count == 0) {
z1 = a1;
z0 = a0;
}
else if (count < 64) {
z1 = (a0<<negCount) | (a1 != 0);
z0 = a0>>count;
}
else {
if (count == 64) {
z1 = a0 | (a1 != 0);
}
else {
z1 = ((a0 | a1) != 0);
}
z0 = 0;
}
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit
| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so
| any carry out is lost. The result is broken into two 64-bit pieces which
| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE void add128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1, Bit64u *z0Ptr, Bit64u *z1Ptr)
{
Bit64u z1 = a1 + b1;
*z1Ptr = z1;
*z0Ptr = a0 + b0 + (z1 < a1);
}
/*----------------------------------------------------------------------------
| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the
| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
| 2^128, so any borrow out (carry out) is lost. The result is broken into two
| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and
| `z1Ptr'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE void
sub128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1, Bit64u *z0Ptr, Bit64u *z1Ptr)
{
*z1Ptr = a1 - b1;
*z0Ptr = a0 - b0 - (a1 < b1);
}
/*----------------------------------------------------------------------------
| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken
| into two 64-bit pieces which are stored at the locations pointed to by
| `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE void mul64To128(Bit64u a, Bit64u b, Bit64u *z0Ptr, Bit64u *z1Ptr)
{
Bit32u aHigh, aLow, bHigh, bLow;
Bit64u z0, zMiddleA, zMiddleB, z1;
aLow = (Bit32u) a;
aHigh = (Bit32u)(a>>32);
bLow = (Bit32u) b;
bHigh = (Bit32u)(b>>32);
z1 = ((Bit64u) aLow) * bLow;
zMiddleA = ((Bit64u) aLow) * bHigh;
zMiddleB = ((Bit64u) aHigh) * bLow;
z0 = ((Bit64u) aHigh) * bHigh;
zMiddleA += zMiddleB;
z0 += (((Bit64u) (zMiddleA < zMiddleB))<<32) + (zMiddleA>>32);
zMiddleA <<= 32;
z1 += zMiddleA;
z0 += (z1 < zMiddleA);
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Returns an approximation to the 64-bit integer quotient obtained by dividing
| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The
| divisor `b' must be at least 2^63. If q is the exact quotient truncated
| toward zero, the approximation returned lies between q and q + 2 inclusive.
| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit
| unsigned integer is returned.
*----------------------------------------------------------------------------*/
#ifdef USE_estimateDiv128To64
static Bit64u estimateDiv128To64(Bit64u a0, Bit64u a1, Bit64u b)
{
Bit64u b0, b1;
Bit64u rem0, rem1, term0, term1;
Bit64u z;
if (b <= a0) return BX_CONST64(0xFFFFFFFFFFFFFFFF);
b0 = b>>32;
z = (b0<<32 <= a0) ? BX_CONST64(0xFFFFFFFF00000000) : (a0 / b0)<<32;
mul64To128(b, z, &term0, &term1);
sub128(a0, a1, term0, term1, &rem0, &rem1);
while (((Bit64s) rem0) < 0) {
z -= BX_CONST64(0x100000000);
b1 = b<<32;
add128(rem0, rem1, b0, b1, &rem0, &rem1);
}
rem0 = (rem0<<32) | (rem1>>32);
z |= (b0<<32 <= rem0) ? 0xFFFFFFFF : rem0 / b0;
return z;
}
#endif
/*----------------------------------------------------------------------------
| Returns an approximation to the square root of the 32-bit significand given
| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
| `aExp' (the least significant bit) is 1, the integer returned approximates
| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
| case, the approximation returned lies strictly within +/-2 of the exact
| value.
*----------------------------------------------------------------------------*/
#ifdef USE_estimateSqrt32
static Bit32u estimateSqrt32(Bit16s aExp, Bit32u a)
{
static const Bit16u sqrtOddAdjustments[] = {
0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
};
static const Bit16u sqrtEvenAdjustments[] = {
0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
};
Bit32u z;
int index = (a>>27) & 15;
if (aExp & 1) {
z = 0x4000 + (a>>17) - sqrtOddAdjustments[index];
z = ((a / z)<<14) + (z<<15);
a >>= 1;
}
else {
z = 0x8000 + (a>>17) - sqrtEvenAdjustments[index];
z = a / z + z;
z = (0x20000 <= z) ? 0xFFFF8000 : (z<<15);
if (z <= a) return (Bit32u) (((Bit32s) a)>>1);
}
return ((Bit32u) ((((Bit64u) a)<<31) / z)) + (z>>1);
}
#endif
static const int countLeadingZeros8[] = {
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#ifdef FLOAT16
/*----------------------------------------------------------------------------
| Returns the number of leading 0 bits before the most-significant 1 bit of
| `a'. If `a' is zero, 16 is returned.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int countLeadingZeros16(Bit16u a)
{
int shiftCount = 0;
if (a < 0x100) {
shiftCount += 8;
a <<= 8;
}
shiftCount += countLeadingZeros8[a>>8];
return shiftCount;
}
#endif
/*----------------------------------------------------------------------------
| Returns the number of leading 0 bits before the most-significant 1 bit of
| `a'. If `a' is zero, 32 is returned.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int countLeadingZeros32(Bit32u a)
{
int shiftCount = 0;
if (a < 0x10000) {
shiftCount += 16;
a <<= 16;
}
if (a < 0x1000000) {
shiftCount += 8;
a <<= 8;
}
shiftCount += countLeadingZeros8[a>>24];
return shiftCount;
}
/*----------------------------------------------------------------------------
| Returns the number of leading 0 bits before the most-significant 1 bit of
| `a'. If `a' is zero, 64 is returned.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int countLeadingZeros64(Bit64u a)
{
int shiftCount = 0;
if (a < BX_CONST64(0x100000000)) {
shiftCount += 32;
}
else {
a >>= 32;
}
shiftCount += countLeadingZeros32((Bit32u)(a));
return shiftCount;
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
| number of bits given in `count'. Any bits shifted off are lost. The value
| of `count' can be arbitrarily large; in particular, if `count' is greater
| than 128, the result will be 0. The result is broken into two 64-bit pieces
| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE void shift128Right(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr)
{
Bit64u z0, z1;
int negCount = (-count) & 63;
if (count == 0) {
z1 = a1;
z0 = a0;
}
else if (count < 64) {
z1 = (a0<<negCount) | (a1>>count);
z0 = a0>>count;
}
else {
z1 = (count < 128) ? (a0>>(count & 63)) : 0;
z0 = 0;
}
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
| number of bits given in `count'. If any nonzero bits are shifted off, they
| are ``jammed'' into the least significant bit of the result by setting the
| least significant bit to 1. The value of `count' can be arbitrarily large;
| in particular, if `count' is greater than 128, the result will be either
| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or
| nonzero. The result is broken into two 64-bit pieces which are stored at
| the locations pointed to by `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE void shift128RightJamming(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr)
{
Bit64u z0, z1;
int negCount = (-count) & 63;
if (count == 0) {
z1 = a1;
z0 = a0;
}
else if (count < 64) {
z1 = (a0<<negCount) | (a1>>count) | ((a1<<negCount) != 0);
z0 = a0>>count;
}
else {
if (count == 64) {
z1 = a0 | (a1 != 0);
}
else if (count < 128) {
z1 = (a0>>(count & 63)) | (((a0<<negCount) | a1) != 0);
}
else {
z1 = ((a0 | a1) != 0);
}
z0 = 0;
}
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
| number of bits given in `count'. Any bits shifted off are lost. The value
| of `count' must be less than 64. The result is broken into two 64-bit
| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE void shortShift128Left(Bit64u a0, Bit64u a1, int count, Bit64u *z0Ptr, Bit64u *z1Ptr)
{
*z1Ptr = a1<<count;
*z0Ptr = (count == 0) ? a0 : (a0<<count) | (a1>>((-count) & 63));
}
/*----------------------------------------------------------------------------
| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the
| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
| modulo 2^192, so any carry out is lost. The result is broken into three
| 64-bit pieces which are stored at the locations pointed to by `z0Ptr',
| `z1Ptr', and `z2Ptr'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE void add192(
Bit64u a0,
Bit64u a1,
Bit64u a2,
Bit64u b0,
Bit64u b1,
Bit64u b2,
Bit64u *z0Ptr,
Bit64u *z1Ptr,
Bit64u *z2Ptr
)
{
Bit64u z0, z1, z2;
unsigned carry0, carry1;
z2 = a2 + b2;
carry1 = (z2 < a2);
z1 = a1 + b1;
carry0 = (z1 < a1);
z0 = a0 + b0;
z1 += carry1;
z0 += (z1 < carry1);
z0 += carry0;
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2'
| from the 192-bit value formed by concatenating `a0', `a1', and `a2'.
| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The
| result is broken into three 64-bit pieces which are stored at the locations
| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE void sub192(
Bit64u a0,
Bit64u a1,
Bit64u a2,
Bit64u b0,
Bit64u b1,
Bit64u b2,
Bit64u *z0Ptr,
Bit64u *z1Ptr,
Bit64u *z2Ptr
)
{
Bit64u z0, z1, z2;
unsigned borrow0, borrow1;
z2 = a2 - b2;
borrow1 = (a2 < b2);
z1 = a1 - b1;
borrow0 = (a1 < b1);
z0 = a0 - b0;
z0 -= (z1 < borrow1);
z1 -= borrow1;
z0 -= borrow0;
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'
| is equal to the 128-bit value formed by concatenating `b0' and `b1'.
| Otherwise, returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int eq128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1)
{
return (a0 == b0) && (a1 == b1);
}
/*----------------------------------------------------------------------------
| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
| than or equal to the 128-bit value formed by concatenating `b0' and `b1'.
| Otherwise, returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int le128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1)
{
return (a0 < b0) || ((a0 == b0) && (a1 <= b1));
}
/*----------------------------------------------------------------------------
| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise,
| returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int lt128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1)
{
return (a0 < b0) || ((a0 == b0) && (a1 < b1));
}
#endif /* FLOATX80 */
/*----------------------------------------------------------------------------
| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by
| `b' to obtain a 192-bit product. The product is broken into three 64-bit
| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
| `z2Ptr'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE void mul128By64To192(
Bit64u a0,
Bit64u a1,
Bit64u b,
Bit64u *z0Ptr,
Bit64u *z1Ptr,
Bit64u *z2Ptr
)
{
Bit64u z0, z1, z2, more1;
mul64To128(a1, b, &z1, &z2);
mul64To128(a0, b, &z0, &more1);
add128(z0, more1, 0, z1, &z0, &z1);
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the
| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit
| product. The product is broken into four 64-bit pieces which are stored at
| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE void mul128To256(
Bit64u a0,
Bit64u a1,
Bit64u b0,
Bit64u b1,
Bit64u *z0Ptr,
Bit64u *z1Ptr,
Bit64u *z2Ptr,
Bit64u *z3Ptr
)
{
Bit64u z0, z1, z2, z3;
Bit64u more1, more2;
mul64To128(a1, b1, &z2, &z3);
mul64To128(a1, b0, &z1, &more2);
add128(z1, more2, 0, z2, &z1, &z2);
mul64To128(a0, b0, &z0, &more1);
add128(z0, more1, 0, z1, &z0, &z1);
mul64To128(a0, b1, &more1, &more2);
add128(more1, more2, 0, z2, &more1, &z2);
add128(z0, z1, 0, more1, &z0, &z1);
*z3Ptr = z3;
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
/*----------------------------------------------------------------------------
| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right
| by 64 _plus_ the number of bits given in `count'. The shifted result is
| at most 128 nonzero bits; these are broken into two 64-bit pieces which are
| stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
| off form a third 64-bit result as follows: The _last_ bit shifted off is
| the most-significant bit of the extra result, and the other 63 bits of the
| extra result are all zero if and only if _all_but_the_last_ bits shifted off
| were all zero. This extra result is stored in the location pointed to by
| `z2Ptr'. The value of `count' can be arbitrarily large.
| (This routine makes more sense if `a0', `a1', and `a2' are considered
| to form a fixed-point value with binary point between `a1' and `a2'. This
| fixed-point value is shifted right by the number of bits given in `count',
| and the integer part of the result is returned at the locations pointed to
| by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
| corrupted as described above, and is returned at the location pointed to by
| `z2Ptr'.)
*----------------------------------------------------------------------------*/
BX_CPP_INLINE void shift128ExtraRightJamming(
Bit64u a0,
Bit64u a1,
Bit64u a2,
int count,
Bit64u *z0Ptr,
Bit64u *z1Ptr,
Bit64u *z2Ptr
)
{
Bit64u z0, z1, z2;
int negCount = (-count) & 63;
if (count == 0) {
z2 = a2;
z1 = a1;
z0 = a0;
}
else {
if (count < 64) {
z2 = a1<<negCount;
z1 = (a0<<negCount) | (a1>>count);
z0 = a0>>count;
}
else {
if (count == 64) {
z2 = a1;
z1 = a0;
}
else {
a2 |= a1;
if (count < 128) {
z2 = a0<<negCount;
z1 = a0>>(count & 63);
}
else {
z2 = (count == 128) ? a0 : (a0 != 0);
z1 = 0;
}
}
z0 = 0;
}
z2 |= (a2 != 0);
}
*z2Ptr = z2;
*z1Ptr = z1;
*z0Ptr = z0;
}
#endif /* FLOAT128 */
#endif

View File

@@ -1,558 +0,0 @@
/*============================================================================
This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
Package, Release 2b.
Written by John R. Hauser. This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704. Funding was partially provided by the
National Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
arithmetic/SoftFloat.html'.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.
=============================================================================*/
/*============================================================================
* This code is based on QEMU patch by Peter Maydell
* Adapted for Bochs (x86 achitecture simulator) by
* Stanislav Shwartsman [sshwarts at sourceforge net]
* ==========================================================================*/
#include "softfloat.h"
#include "softfloat-round-pack.h"
/*----------------------------------------------------------------------------
| Primitive arithmetic functions, including multi-word arithmetic, and
| division and square root approximations. (Can be specialized to target
| if desired).
*----------------------------------------------------------------------------*/
#include "softfloat-macros.h"
/*----------------------------------------------------------------------------
| Functions and definitions to determine: (1) whether tininess for underflow
| is detected before or after rounding by default, (2) what (if anything)
| happens when exceptions are raised, (3) how signaling NaNs are distinguished
| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
| are propagated from function inputs to output. These details are target-
| specific.
*----------------------------------------------------------------------------*/
#include "softfloat-specialize.h"
/*----------------------------------------------------------------------------
| Takes three single-precision floating-point values `a', `b' and `c', one of
| which is a NaN, and returns the appropriate NaN result. If any of `a',
| `b' or `c' is a signaling NaN, the invalid exception is raised.
| The input infzero indicates whether a*b was 0*inf or inf*0 (in which case
| obviously c is a NaN, and whether to propagate c or some other NaN is
| implementation defined).
*----------------------------------------------------------------------------*/
static float32 propagateFloat32MulAddNaN(float32 a, float32 b, float32 c, struct float_status_t *status)
{
int aIsNaN = float32_is_nan(a);
int bIsNaN = float32_is_nan(b);
int aIsSignalingNaN = float32_is_signaling_nan(a);
int bIsSignalingNaN = float32_is_signaling_nan(b);
int cIsSignalingNaN = float32_is_signaling_nan(c);
a |= 0x00400000;
b |= 0x00400000;
c |= 0x00400000;
if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN)
float_raise(status, float_flag_invalid);
// operate according to float_first_operand_nan mode
if (aIsSignalingNaN | aIsNaN) {
return a;
}
else {
return (bIsSignalingNaN | bIsNaN) ? b : c;
}
}
/*----------------------------------------------------------------------------
| Takes three double-precision floating-point values `a', `b' and `c', one of
| which is a NaN, and returns the appropriate NaN result. If any of `a',
| `b' or `c' is a signaling NaN, the invalid exception is raised.
| The input infzero indicates whether a*b was 0*inf or inf*0 (in which case
| obviously c is a NaN, and whether to propagate c or some other NaN is
| implementation defined).
*----------------------------------------------------------------------------*/
static float64 propagateFloat64MulAddNaN(float64 a, float64 b, float64 c, struct float_status_t *status)
{
int aIsNaN = float64_is_nan(a);
int bIsNaN = float64_is_nan(b);
int aIsSignalingNaN = float64_is_signaling_nan(a);
int bIsSignalingNaN = float64_is_signaling_nan(b);
int cIsSignalingNaN = float64_is_signaling_nan(c);
a |= BX_CONST64(0x0008000000000000);
b |= BX_CONST64(0x0008000000000000);
c |= BX_CONST64(0x0008000000000000);
if (aIsSignalingNaN | bIsSignalingNaN | cIsSignalingNaN)
float_raise(status, float_flag_invalid);
// operate according to float_first_operand_nan mode
if (aIsSignalingNaN | aIsNaN) {
return a;
}
else {
return (bIsSignalingNaN | bIsNaN) ? b : c;
}
}
/*----------------------------------------------------------------------------
| Returns the result of multiplying the single-precision floating-point values
| `a' and `b' then adding 'c', with no intermediate rounding step after the
| multiplication. The operation is performed according to the IEC/IEEE
| Standard for Binary Floating-Point Arithmetic 754-2008.
| The flags argument allows the caller to select negation of the
| addend, the intermediate product, or the final result. (The difference
| between this and having the caller do a separate negation is that negating
| externally will flip the sign bit on NaNs.)
*----------------------------------------------------------------------------*/
float32 float32_muladd(float32 a, float32 b, float32 c, int flags, struct float_status_t *status)
{
int aSign, bSign, cSign, zSign;
Bit16s aExp, bExp, cExp, pExp, zExp;
Bit32u aSig, bSig, cSig;
int pInf, pZero, pSign;
Bit64u pSig64, cSig64, zSig64;
Bit32u pSig;
int shiftcount;
aSig = extractFloat32Frac(a);
aExp = extractFloat32Exp(a);
aSign = extractFloat32Sign(a);
bSig = extractFloat32Frac(b);
bExp = extractFloat32Exp(b);
bSign = extractFloat32Sign(b);
cSig = extractFloat32Frac(c);
cExp = extractFloat32Exp(c);
cSign = extractFloat32Sign(c);
/* It is implementation-defined whether the cases of (0,inf,qnan)
* and (inf,0,qnan) raise InvalidOperation or not (and what QNaN
* they return if they do), so we have to hand this information
* off to the target-specific pick-a-NaN routine.
*/
if (((aExp == 0xff) && aSig) ||
((bExp == 0xff) && bSig) ||
((cExp == 0xff) && cSig)) {
return propagateFloat32MulAddNaN(a, b, c, status);
}
if (get_denormals_are_zeros(status)) {
if (aExp == 0) aSig = 0;
if (bExp == 0) bSig = 0;
if (cExp == 0) cSig = 0;
}
int infzero = ((aExp == 0 && aSig == 0 && bExp == 0xff && bSig == 0) ||
(aExp == 0xff && aSig == 0 && bExp == 0 && bSig == 0));
if (infzero) {
float_raise(status, float_flag_invalid);
return float32_default_nan;
}
if (flags & float_muladd_negate_c) {
cSign ^= 1;
}
/* Work out the sign and type of the product */
pSign = aSign ^ bSign;
if (flags & float_muladd_negate_product) {
pSign ^= 1;
}
pInf = (aExp == 0xff) || (bExp == 0xff);
pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0);
if (cExp == 0xff) {
if (pInf && (pSign ^ cSign)) {
/* addition of opposite-signed infinities => InvalidOperation */
float_raise(status, float_flag_invalid);
return float32_default_nan;
}
/* Otherwise generate an infinity of the same sign */
if ((aSig && aExp == 0) || (bSig && bExp == 0)) {
float_raise(status, float_flag_denormal);
}
return packFloat32(cSign, 0xff, 0);
}
if (pInf) {
if ((aSig && aExp == 0) || (bSig && bExp == 0) || (cSig && cExp == 0)) {
float_raise(status, float_flag_denormal);
}
return packFloat32(pSign, 0xff, 0);
}
if (pZero) {
if (cExp == 0) {
if (cSig == 0) {
/* Adding two exact zeroes */
if (pSign == cSign) {
zSign = pSign;
} else if (get_float_rounding_mode(status) == float_round_down) {
zSign = 1;
} else {
zSign = 0;
}
return packFloat32(zSign, 0, 0);
}
/* Exact zero plus a denormal */
float_raise(status, float_flag_denormal);
if (get_flush_underflow_to_zero(status)) {
float_raise(status, float_flag_underflow | float_flag_inexact);
return packFloat32(cSign, 0, 0);
}
}
/* Zero plus something non-zero */
return packFloat32(cSign, cExp, cSig);
}
if (aExp == 0) {
float_raise(status, float_flag_denormal);
normalizeFloat32Subnormal(aSig, &aExp, &aSig);
}
if (bExp == 0) {
float_raise(status, float_flag_denormal);
normalizeFloat32Subnormal(bSig, &bExp, &bSig);
}
/* Calculate the actual result a * b + c */
/* Multiply first; this is easy. */
/* NB: we subtract 0x7e where float32_mul() subtracts 0x7f
* because we want the true exponent, not the "one-less-than"
* flavour that roundAndPackFloat32() takes.
*/
pExp = aExp + bExp - 0x7e;
aSig = (aSig | 0x00800000) << 7;
bSig = (bSig | 0x00800000) << 8;
pSig64 = (Bit64u)aSig * bSig;
if ((Bit64s)(pSig64 << 1) >= 0) {
pSig64 <<= 1;
pExp--;
}
zSign = pSign;
/* Now pSig64 is the significand of the multiply, with the explicit bit in
* position 62.
*/
if (cExp == 0) {
if (!cSig) {
/* Throw out the special case of c being an exact zero now */
pSig = (Bit32u) shift64RightJamming(pSig64, 32);
return roundAndPackFloat32(zSign, pExp - 1, pSig, status);
}
float_raise(status, float_flag_denormal);
normalizeFloat32Subnormal(cSig, &cExp, &cSig);
}
cSig64 = (Bit64u)cSig << 39;
cSig64 |= BX_CONST64(0x4000000000000000);
int expDiff = pExp - cExp;
if (pSign == cSign) {
/* Addition */
if (expDiff > 0) {
/* scale c to match p */
cSig64 = shift64RightJamming(cSig64, expDiff);
zExp = pExp;
} else if (expDiff < 0) {
/* scale p to match c */
pSig64 = shift64RightJamming(pSig64, -expDiff);
zExp = cExp;
} else {
/* no scaling needed */
zExp = cExp;
}
/* Add significands and make sure explicit bit ends up in posn 62 */
zSig64 = pSig64 + cSig64;
if ((Bit64s)zSig64 < 0) {
zSig64 = shift64RightJamming(zSig64, 1);
} else {
zExp--;
}
zSig64 = shift64RightJamming(zSig64, 32);
return roundAndPackFloat32(zSign, zExp, zSig64, status);
} else {
/* Subtraction */
if (expDiff > 0) {
cSig64 = shift64RightJamming(cSig64, expDiff);
zSig64 = pSig64 - cSig64;
zExp = pExp;
} else if (expDiff < 0) {
pSig64 = shift64RightJamming(pSig64, -expDiff);
zSig64 = cSig64 - pSig64;
zExp = cExp;
zSign ^= 1;
} else {
zExp = pExp;
if (cSig64 < pSig64) {
zSig64 = pSig64 - cSig64;
} else if (pSig64 < cSig64) {
zSig64 = cSig64 - pSig64;
zSign ^= 1;
} else {
/* Exact zero */
return packFloat32(get_float_rounding_mode(status) == float_round_down, 0, 0);
}
}
--zExp;
/* Do the equivalent of normalizeRoundAndPackFloat32() but
* starting with the significand in a Bit64u.
*/
shiftcount = countLeadingZeros64(zSig64) - 1;
zSig64 <<= shiftcount;
zExp -= shiftcount;
zSig64 = shift64RightJamming(zSig64, 32);
return roundAndPackFloat32(zSign, zExp, zSig64, status);
}
}
/*----------------------------------------------------------------------------
| Returns the result of multiplying the double-precision floating-point values
| `a' and `b' then adding 'c', with no intermediate rounding step after the
| multiplication. The operation is performed according to the IEC/IEEE
| Standard for Binary Floating-Point Arithmetic 754-2008.
| The flags argument allows the caller to select negation of the
| addend, the intermediate product, or the final result. (The difference
| between this and having the caller do a separate negation is that negating
| externally will flip the sign bit on NaNs.)
*----------------------------------------------------------------------------*/
float64 float64_muladd(float64 a, float64 b, float64 c, int flags, struct float_status_t *status)
{
int aSign, bSign, cSign, zSign;
Bit16s aExp, bExp, cExp, pExp, zExp;
Bit64u aSig, bSig, cSig;
int pInf, pZero, pSign;
Bit64u pSig0, pSig1, cSig0, cSig1, zSig0, zSig1;
int shiftcount;
aSig = extractFloat64Frac(a);
aExp = extractFloat64Exp(a);
aSign = extractFloat64Sign(a);
bSig = extractFloat64Frac(b);
bExp = extractFloat64Exp(b);
bSign = extractFloat64Sign(b);
cSig = extractFloat64Frac(c);
cExp = extractFloat64Exp(c);
cSign = extractFloat64Sign(c);
/* It is implementation-defined whether the cases of (0,inf,qnan)
* and (inf,0,qnan) raise InvalidOperation or not (and what QNaN
* they return if they do), so we have to hand this information
* off to the target-specific pick-a-NaN routine.
*/
if (((aExp == 0x7ff) && aSig) ||
((bExp == 0x7ff) && bSig) ||
((cExp == 0x7ff) && cSig)) {
return propagateFloat64MulAddNaN(a, b, c, status);
}
if (get_denormals_are_zeros(status)) {
if (aExp == 0) aSig = 0;
if (bExp == 0) bSig = 0;
if (cExp == 0) cSig = 0;
}
int infzero = ((aExp == 0 && aSig == 0 && bExp == 0x7ff && bSig == 0) ||
(aExp == 0x7ff && aSig == 0 && bExp == 0 && bSig == 0));
if (infzero) {
float_raise(status, float_flag_invalid);
return float64_default_nan;
}
if (flags & float_muladd_negate_c) {
cSign ^= 1;
}
/* Work out the sign and type of the product */
pSign = aSign ^ bSign;
if (flags & float_muladd_negate_product) {
pSign ^= 1;
}
pInf = (aExp == 0x7ff) || (bExp == 0x7ff);
pZero = ((aExp | aSig) == 0) || ((bExp | bSig) == 0);
if (cExp == 0x7ff) {
if (pInf && (pSign ^ cSign)) {
/* addition of opposite-signed infinities => InvalidOperation */
float_raise(status, float_flag_invalid);
return float64_default_nan;
}
/* Otherwise generate an infinity of the same sign */
if ((aSig && aExp == 0) || (bSig && bExp == 0)) {
float_raise(status, float_flag_denormal);
}
return packFloat64(cSign, 0x7ff, 0);
}
if (pInf) {
if ((aSig && aExp == 0) || (bSig && bExp == 0) || (cSig && cExp == 0)) {
float_raise(status, float_flag_denormal);
}
return packFloat64(pSign, 0x7ff, 0);
}
if (pZero) {
if (cExp == 0) {
if (cSig == 0) {
/* Adding two exact zeroes */
if (pSign == cSign) {
zSign = pSign;
} else if (get_float_rounding_mode(status) == float_round_down) {
zSign = 1;
} else {
zSign = 0;
}
return packFloat64(zSign, 0, 0);
}
/* Exact zero plus a denormal */
float_raise(status, float_flag_denormal);
if (get_flush_underflow_to_zero(status)) {
float_raise(status, float_flag_underflow | float_flag_inexact);
return packFloat64(cSign, 0, 0);
}
}
/* Zero plus something non-zero */
return packFloat64(cSign, cExp, cSig);
}
if (aExp == 0) {
float_raise(status, float_flag_denormal);
normalizeFloat64Subnormal(aSig, &aExp, &aSig);
}
if (bExp == 0) {
float_raise(status, float_flag_denormal);
normalizeFloat64Subnormal(bSig, &bExp, &bSig);
}
/* Calculate the actual result a * b + c */
/* Multiply first; this is easy. */
/* NB: we subtract 0x3fe where float64_mul() subtracts 0x3ff
* because we want the true exponent, not the "one-less-than"
* flavour that roundAndPackFloat64() takes.
*/
pExp = aExp + bExp - 0x3fe;
aSig = (aSig | BX_CONST64(0x0010000000000000))<<10;
bSig = (bSig | BX_CONST64(0x0010000000000000))<<11;
mul64To128(aSig, bSig, &pSig0, &pSig1);
if ((Bit64s)(pSig0 << 1) >= 0) {
shortShift128Left(pSig0, pSig1, 1, &pSig0, &pSig1);
pExp--;
}
zSign = pSign;
/* Now [pSig0:pSig1] is the significand of the multiply, with the explicit
* bit in position 126.
*/
if (cExp == 0) {
if (!cSig) {
/* Throw out the special case of c being an exact zero now */
shift128RightJamming(pSig0, pSig1, 64, &pSig0, &pSig1);
return roundAndPackFloat64(zSign, pExp - 1, pSig1, status);
}
float_raise(status, float_flag_denormal);
normalizeFloat64Subnormal(cSig, &cExp, &cSig);
}
cSig0 = cSig << 10;
cSig1 = 0;
cSig0 |= BX_CONST64(0x4000000000000000);
int expDiff = pExp - cExp;
if (pSign == cSign) {
/* Addition */
if (expDiff > 0) {
/* scale c to match p */
shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1);
zExp = pExp;
} else if (expDiff < 0) {
/* scale p to match c */
shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1);
zExp = cExp;
} else {
/* no scaling needed */
zExp = cExp;
}
/* Add significands and make sure explicit bit ends up in posn 126 */
add128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1);
if ((Bit64s)zSig0 < 0) {
shift128RightJamming(zSig0, zSig1, 1, &zSig0, &zSig1);
} else {
zExp--;
}
shift128RightJamming(zSig0, zSig1, 64, &zSig0, &zSig1);
return roundAndPackFloat64(zSign, zExp, zSig1, status);
} else {
/* Subtraction */
if (expDiff > 0) {
shift128RightJamming(cSig0, cSig1, expDiff, &cSig0, &cSig1);
sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1);
zExp = pExp;
} else if (expDiff < 0) {
shift128RightJamming(pSig0, pSig1, -expDiff, &pSig0, &pSig1);
sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1);
zExp = cExp;
zSign ^= 1;
} else {
zExp = pExp;
if (lt128(cSig0, cSig1, pSig0, pSig1)) {
sub128(pSig0, pSig1, cSig0, cSig1, &zSig0, &zSig1);
} else if (lt128(pSig0, pSig1, cSig0, cSig1)) {
sub128(cSig0, cSig1, pSig0, pSig1, &zSig0, &zSig1);
zSign ^= 1;
} else {
/* Exact zero */
return packFloat64(get_float_rounding_mode(status) == float_round_down, 0, 0);
}
}
--zExp;
/* Do the equivalent of normalizeRoundAndPackFloat64() but
* starting with the significand in a pair of Bit64u.
*/
if (zSig0) {
shiftcount = countLeadingZeros64(zSig0) - 1;
shortShift128Left(zSig0, zSig1, shiftcount, &zSig0, &zSig1);
if (zSig1) {
zSig0 |= 1;
}
zExp -= shiftcount;
} else {
shiftcount = countLeadingZeros64(zSig1) - 1;
zSig0 = zSig1 << shiftcount;
zExp -= (shiftcount + 64);
}
return roundAndPackFloat64(zSign, zExp, zSig0, status);
}
}

View File

@@ -1,896 +0,0 @@
/*============================================================================
This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
Package, Release 2b.
Written by John R. Hauser. This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704. Funding was partially provided by the
National Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
arithmetic/SoftFloat.html'.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.
=============================================================================*/
#define FLOAT128
/*============================================================================
* Adapted for Bochs (x86 achitecture simulator) by
* Stanislav Shwartsman [sshwarts at sourceforge net]
* ==========================================================================*/
#include "softfloat.h"
#include "softfloat-round-pack.h"
/*----------------------------------------------------------------------------
| Primitive arithmetic functions, including multi-word arithmetic, and
| division and square root approximations. (Can be specialized to target
| if desired).
*----------------------------------------------------------------------------*/
#include "softfloat-macros.h"
/*----------------------------------------------------------------------------
| Functions and definitions to determine: (1) whether tininess for underflow
| is detected before or after rounding by default, (2) what (if anything)
| happens when exceptions are raised, (3) how signaling NaNs are distinguished
| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
| are propagated from function inputs to output. These details are target-
| specific.
*----------------------------------------------------------------------------*/
#include "softfloat-specialize.h"
/*----------------------------------------------------------------------------
| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
| and 7, and returns the properly rounded 32-bit integer corresponding to the
| input. If `zSign' is 1, the input is negated before being converted to an
| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input
| is simply rounded to an integer, with the inexact exception raised if the
| input cannot be represented exactly as an integer. However, if the fixed-
| point input is too large, the invalid exception is raised and the integer
| indefinite value is returned.
*----------------------------------------------------------------------------*/
Bit32s roundAndPackInt32(int zSign, Bit64u exactAbsZ, struct float_status_t *status)
{
int roundingMode = get_float_rounding_mode(status);
int roundNearestEven = (roundingMode == float_round_nearest_even);
int roundIncrement = 0x40;
if (! roundNearestEven) {
if (roundingMode == float_round_to_zero) roundIncrement = 0;
else {
roundIncrement = 0x7F;
if (zSign) {
if (roundingMode == float_round_up) roundIncrement = 0;
}
else {
if (roundingMode == float_round_down) roundIncrement = 0;
}
}
}
int roundBits = (int)(exactAbsZ & 0x7F);
Bit64u absZ = (exactAbsZ + roundIncrement)>>7;
absZ &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven);
Bit32s z = (Bit32s) absZ;
if (zSign) z = -z;
if ((absZ>>32) || (z && ((z < 0) ^ zSign))) {
float_raise(status, float_flag_invalid);
return (Bit32s)(int32_indefinite);
}
if (roundBits) {
float_raise(status, float_flag_inexact);
if ((absZ << 7) > exactAbsZ)
set_float_rounding_up(status);
}
return z;
}
/*----------------------------------------------------------------------------
| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
| `absZ1', with binary point between bits 63 and 64 (between the input words),
| and returns the properly rounded 64-bit integer corresponding to the input.
| If `zSign' is 1, the input is negated before being converted to an integer.
| Ordinarily, the fixed-point input is simply rounded to an integer, with
| the inexact exception raised if the input cannot be represented exactly as
| an integer. However, if the fixed-point input is too large, the invalid
| exception is raised and the integer indefinite value is returned.
*----------------------------------------------------------------------------*/
Bit64s roundAndPackInt64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status)
{
Bit64s z;
int roundingMode = get_float_rounding_mode(status);
int roundNearestEven = (roundingMode == float_round_nearest_even);
int increment = ((Bit64s) absZ1 < 0);
if (! roundNearestEven) {
if (roundingMode == float_round_to_zero) increment = 0;
else {
if (zSign) {
increment = (roundingMode == float_round_down) && absZ1;
}
else {
increment = (roundingMode == float_round_up) && absZ1;
}
}
}
Bit64u exactAbsZ0 = absZ0;
if (increment) {
++absZ0;
if (absZ0 == 0) goto overflow;
absZ0 &= ~(((Bit64u) (absZ1<<1) == 0) & roundNearestEven);
}
z = absZ0;
if (zSign) z = -z;
if (z && ((z < 0) ^ zSign)) {
overflow:
float_raise(status, float_flag_invalid);
return (Bit64s)(int64_indefinite);
}
if (absZ1) {
float_raise(status, float_flag_inexact);
if (absZ0 > exactAbsZ0)
set_float_rounding_up(status);
}
return z;
}
/*----------------------------------------------------------------------------
| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
| `absZ1', with binary point between bits 63 and 64 (between the input words),
| and returns the properly rounded 64-bit unsigned integer corresponding to the
| input. Ordinarily, the fixed-point input is simply rounded to an integer,
| with the inexact exception raised if the input cannot be represented exactly
| as an integer. However, if the fixed-point input is too large, the invalid
| exception is raised and the largest unsigned integer is returned.
*----------------------------------------------------------------------------*/
Bit64u roundAndPackUint64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status)
{
int roundingMode = get_float_rounding_mode(status);
int roundNearestEven = (roundingMode == float_round_nearest_even);
int increment = ((Bit64s) absZ1 < 0);
if (!roundNearestEven) {
if (roundingMode == float_round_to_zero) {
increment = 0;
} else if (absZ1) {
if (zSign) {
increment = (roundingMode == float_round_down) && absZ1;
} else {
increment = (roundingMode == float_round_up) && absZ1;
}
}
}
if (increment) {
++absZ0;
if (absZ0 == 0) {
float_raise(status, float_flag_invalid);
return uint64_indefinite;
}
absZ0 &= ~(((Bit64u) (absZ1<<1) == 0) & roundNearestEven);
}
if (zSign && absZ0) {
float_raise(status, float_flag_invalid);
return uint64_indefinite;
}
if (absZ1) {
float_raise(status, float_flag_inexact);
}
return absZ0;
}
#ifdef FLOAT16
/*----------------------------------------------------------------------------
| Normalizes the subnormal half-precision floating-point value represented
| by the denormalized significand `aSig'. The normalized exponent and
| significand are stored at the locations pointed to by `zExpPtr' and
| `zSigPtr', respectively.
*----------------------------------------------------------------------------*/
void normalizeFloat16Subnormal(Bit16u aSig, Bit16s *zExpPtr, Bit16u *zSigPtr)
{
int shiftCount = countLeadingZeros16(aSig) - 5;
*zSigPtr = aSig<<shiftCount;
*zExpPtr = 1 - shiftCount;
}
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and significand `zSig', and returns the proper half-precision floating-
| point value corresponding to the abstract input. Ordinarily, the abstract
| value is simply rounded and packed into the half-precision format, with
| the inexact exception raised if the abstract input cannot be represented
| exactly. However, if the abstract value is too large, the overflow and
| inexact exceptions are raised and an infinity or maximal finite value is
| returned. If the abstract value is too small, the input value is rounded to
| a subnormal number, and the underflow and inexact exceptions are raised if
| the abstract input cannot be represented exactly as a subnormal single-
| precision floating-point number.
| The input significand `zSig' has its binary point between bits 14
| and 13, which is 4 bits to the left of the usual location. This shifted
| significand must be normalized or smaller. If `zSig' is not normalized,
| `zExp' must be 0; in that case, the result returned is a subnormal number,
| and it must not require rounding. In the usual case that `zSig' is
| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
| The handling of underflow and overflow follows the IEC/IEEE Standard for
| Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
float16 roundAndPackFloat16(int zSign, Bit16s zExp, Bit16u zSig, struct float_status_t *status)
{
Bit16s roundIncrement, roundBits, roundMask;
int roundingMode = get_float_rounding_mode(status);
int roundNearestEven = (roundingMode == float_round_nearest_even);
roundIncrement = 8;
roundMask = 0xF;
if (! roundNearestEven) {
if (roundingMode == float_round_to_zero) roundIncrement = 0;
else {
roundIncrement = roundMask;
if (zSign) {
if (roundingMode == float_round_up) roundIncrement = 0;
}
else {
if (roundingMode == float_round_down) roundIncrement = 0;
}
}
}
roundBits = zSig & roundMask;
if (0x1D <= (Bit16u) zExp) {
if ((0x1D < zExp)
|| ((zExp == 0x1D) && ((Bit16s) (zSig + roundIncrement) < 0)))
{
float_raise(status, float_flag_overflow);
if (roundBits || float_exception_masked(status, float_flag_overflow)) {
float_raise(status, float_flag_inexact);
}
return packFloat16(zSign, 0x1F, 0) - (roundIncrement == 0);
}
if (zExp < 0) {
int isTiny = (zExp < -1) || (zSig + roundIncrement < 0x8000);
zSig = shift16RightJamming(zSig, -zExp);
zExp = 0;
roundBits = zSig & roundMask;
if (isTiny) {
if(get_flush_underflow_to_zero(status)) {
float_raise(status, float_flag_underflow | float_flag_inexact);
return packFloat16(zSign, 0, 0);
}
// signal the #P according to roundBits calculated AFTER denormalization
if (roundBits || !float_exception_masked(status, float_flag_underflow)) {
float_raise(status, float_flag_underflow);
}
}
}
}
if (roundBits) float_raise(status, float_flag_inexact);
Bit16u zSigRound = ((zSig + roundIncrement) & ~roundMask) >> 4;
zSigRound &= ~(((roundBits ^ 0x10) == 0) & roundNearestEven);
if (zSigRound == 0) zExp = 0;
return packFloat16(zSign, zExp, zSigRound);
}
#endif
/*----------------------------------------------------------------------------
| Normalizes the subnormal single-precision floating-point value represented
| by the denormalized significand `aSig'. The normalized exponent and
| significand are stored at the locations pointed to by `zExpPtr' and
| `zSigPtr', respectively.
*----------------------------------------------------------------------------*/
void normalizeFloat32Subnormal(Bit32u aSig, Bit16s *zExpPtr, Bit32u *zSigPtr)
{
int shiftCount = countLeadingZeros32(aSig) - 8;
*zSigPtr = aSig<<shiftCount;
*zExpPtr = 1 - shiftCount;
}
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and significand `zSig', and returns the proper single-precision floating-
| point value corresponding to the abstract input. Ordinarily, the abstract
| value is simply rounded and packed into the single-precision format, with
| the inexact exception raised if the abstract input cannot be represented
| exactly. However, if the abstract value is too large, the overflow and
| inexact exceptions are raised and an infinity or maximal finite value is
| returned. If the abstract value is too small, the input value is rounded to
| a subnormal number, and the underflow and inexact exceptions are raised if
| the abstract input cannot be represented exactly as a subnormal single-
| precision floating-point number.
| The input significand `zSig' has its binary point between bits 30
| and 29, which is 7 bits to the left of the usual location. This shifted
| significand must be normalized or smaller. If `zSig' is not normalized,
| `zExp' must be 0; in that case, the result returned is a subnormal number,
| and it must not require rounding. In the usual case that `zSig' is
| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
| The handling of underflow and overflow follows the IEC/IEEE Standard for
| Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
float32 roundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status)
{
Bit32s roundIncrement, roundBits;
const Bit32s roundMask = 0x7F;
int roundingMode = get_float_rounding_mode(status);
int roundNearestEven = (roundingMode == float_round_nearest_even);
roundIncrement = 0x40;
if (! roundNearestEven) {
if (roundingMode == float_round_to_zero) roundIncrement = 0;
else {
roundIncrement = roundMask;
if (zSign) {
if (roundingMode == float_round_up) roundIncrement = 0;
}
else {
if (roundingMode == float_round_down) roundIncrement = 0;
}
}
}
roundBits = zSig & roundMask;
if (0xFD <= (Bit16u) zExp) {
if ((0xFD < zExp)
|| ((zExp == 0xFD) && ((Bit32s) (zSig + roundIncrement) < 0)))
{
float_raise(status, float_flag_overflow);
if (roundBits || float_exception_masked(status, float_flag_overflow)) {
float_raise(status, float_flag_inexact);
if (roundIncrement != 0) set_float_rounding_up(status);
}
return packFloat32(zSign, 0xFF, 0) - (roundIncrement == 0);
}
if (zExp < 0) {
int isTiny = (zExp < -1) || (zSig + roundIncrement < 0x80000000);
if (isTiny) {
if (!float_exception_masked(status, float_flag_underflow)) {
float_raise(status, float_flag_underflow);
zExp += 192; // bias unmasked underflow
}
}
if (zExp < 0) {
zSig = shift32RightJamming(zSig, -zExp);
zExp = 0;
roundBits = zSig & roundMask;
if (isTiny) {
// masked underflow
if(get_flush_underflow_to_zero(status)) {
float_raise(status, float_flag_underflow | float_flag_inexact);
return packFloat32(zSign, 0, 0);
}
if (roundBits) float_raise(status, float_flag_underflow);
}
}
}
}
Bit32u zSigRound = ((zSig + roundIncrement) & ~roundMask) >> 7;
zSigRound &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven);
if (zSigRound == 0) zExp = 0;
if (roundBits) {
float_raise(status, float_flag_inexact);
if ((zSigRound << 7) > zSig) set_float_rounding_up(status);
}
return packFloat32(zSign, zExp, zSigRound);
}
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and significand `zSig', and returns the proper single-precision floating-
| point value corresponding to the abstract input. This routine is just like
| `roundAndPackFloat32' except that `zSig' does not have to be normalized.
| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
| floating-point exponent.
*----------------------------------------------------------------------------*/
float32 normalizeRoundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status)
{
int shiftCount = countLeadingZeros32(zSig) - 1;
return roundAndPackFloat32(zSign, zExp - shiftCount, zSig<<shiftCount, status);
}
/*----------------------------------------------------------------------------
| Normalizes the subnormal double-precision floating-point value represented
| by the denormalized significand `aSig'. The normalized exponent and
| significand are stored at the locations pointed to by `zExpPtr' and
| `zSigPtr', respectively.
*----------------------------------------------------------------------------*/
void normalizeFloat64Subnormal(Bit64u aSig, Bit16s *zExpPtr, Bit64u *zSigPtr)
{
int shiftCount = countLeadingZeros64(aSig) - 11;
*zSigPtr = aSig<<shiftCount;
*zExpPtr = 1 - shiftCount;
}
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and significand `zSig', and returns the proper double-precision floating-
| point value corresponding to the abstract input. Ordinarily, the abstract
| value is simply rounded and packed into the double-precision format, with
| the inexact exception raised if the abstract input cannot be represented
| exactly. However, if the abstract value is too large, the overflow and
| inexact exceptions are raised and an infinity or maximal finite value is
| returned. If the abstract value is too small, the input value is rounded
| to a subnormal number, and the underflow and inexact exceptions are raised
| if the abstract input cannot be represented exactly as a subnormal double-
| precision floating-point number.
| The input significand `zSig' has its binary point between bits 62
| and 61, which is 10 bits to the left of the usual location. This shifted
| significand must be normalized or smaller. If `zSig' is not normalized,
| `zExp' must be 0; in that case, the result returned is a subnormal number,
| and it must not require rounding. In the usual case that `zSig' is
| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
| The handling of underflow and overflow follows the IEC/IEEE Standard for
| Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
float64 roundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status)
{
Bit16s roundIncrement, roundBits;
const Bit16s roundMask = 0x3FF;
int roundingMode = get_float_rounding_mode(status);
int roundNearestEven = (roundingMode == float_round_nearest_even);
roundIncrement = 0x200;
if (! roundNearestEven) {
if (roundingMode == float_round_to_zero) roundIncrement = 0;
else {
roundIncrement = roundMask;
if (zSign) {
if (roundingMode == float_round_up) roundIncrement = 0;
}
else {
if (roundingMode == float_round_down) roundIncrement = 0;
}
}
}
roundBits = (Bit16s)(zSig & roundMask);
if (0x7FD <= (Bit16u) zExp) {
if ((0x7FD < zExp)
|| ((zExp == 0x7FD)
&& ((Bit64s) (zSig + roundIncrement) < 0)))
{
float_raise(status, float_flag_overflow);
if (roundBits || float_exception_masked(status, float_flag_overflow)) {
float_raise(status, float_flag_inexact);
if (roundIncrement != 0) set_float_rounding_up(status);
}
return packFloat64(zSign, 0x7FF, 0) - (roundIncrement == 0);
}
if (zExp < 0) {
int isTiny = (zExp < -1) || (zSig + roundIncrement < BX_CONST64(0x8000000000000000));
if (isTiny) {
if (!float_exception_masked(status, float_flag_underflow)) {
float_raise(status, float_flag_underflow);
zExp += 1536; // bias unmasked underflow
}
}
if (zExp < 0) {
zSig = shift64RightJamming(zSig, -zExp);
zExp = 0;
roundBits = (Bit16s)(zSig & roundMask);
if (isTiny) {
// masked underflow
if(get_flush_underflow_to_zero(status)) {
float_raise(status, float_flag_underflow | float_flag_inexact);
return packFloat64(zSign, 0, 0);
}
if (roundBits) float_raise(status, float_flag_underflow);
}
}
}
}
Bit64u zSigRound = (zSig + roundIncrement)>>10;
zSigRound &= ~(((roundBits ^ 0x200) == 0) & roundNearestEven);
if (zSigRound == 0) zExp = 0;
if (roundBits) {
float_raise(status, float_flag_inexact);
if ((zSigRound << 10) > zSig) set_float_rounding_up(status);
}
return packFloat64(zSign, zExp, zSigRound);
}
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and significand `zSig', and returns the proper double-precision floating-
| point value corresponding to the abstract input. This routine is just like
| `roundAndPackFloat64' except that `zSig' does not have to be normalized.
| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
| floating-point exponent.
*----------------------------------------------------------------------------*/
float64 normalizeRoundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status)
{
int shiftCount = countLeadingZeros64(zSig) - 1;
return roundAndPackFloat64(zSign, zExp - shiftCount, zSig<<shiftCount, status);
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Normalizes the subnormal extended double-precision floating-point value
| represented by the denormalized significand `aSig'. The normalized exponent
| and significand are stored at the locations pointed to by `zExpPtr' and
| `zSigPtr', respectively.
*----------------------------------------------------------------------------*/
void normalizeFloatx80Subnormal(Bit64u aSig, Bit32s *zExpPtr, Bit64u *zSigPtr)
{
int shiftCount = countLeadingZeros64(aSig);
*zSigPtr = aSig<<shiftCount;
*zExpPtr = 1 - shiftCount;
}
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and extended significand formed by the concatenation of `zSig0' and `zSig1',
| and returns the proper extended double-precision floating-point value
| corresponding to the abstract input. Ordinarily, the abstract value is
| rounded and packed into the extended double-precision format, with the
| inexact exception raised if the abstract input cannot be represented
| exactly. However, if the abstract value is too large, the overflow and
| inexact exceptions are raised and an infinity or maximal finite value is
| returned. If the abstract value is too small, the input value is rounded to
| a subnormal number, and the underflow and inexact exceptions are raised if
| the abstract input cannot be represented exactly as a subnormal extended
| double-precision floating-point number.
| If `roundingPrecision' is 32 or 64, the result is rounded to the same
| number of bits as single or double precision, respectively. Otherwise, the
| result is rounded to the full precision of the extended double-precision
| format.
| The input significand must be normalized or smaller. If the input
| significand is not normalized, `zExp' must be 0; in that case, the result
| returned is a subnormal number, and it must not require rounding. The
| handling of underflow and overflow follows the IEC/IEEE Standard for Binary
| Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
floatx80 SoftFloatRoundAndPackFloatx80(int roundingPrecision,
int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status)
{
Bit64u roundIncrement, roundMask, roundBits;
int increment;
Bit64u zSigExact; /* support rounding-up response */
Bit8u roundingMode = get_float_rounding_mode(status);
int roundNearestEven = (roundingMode == float_round_nearest_even);
if (roundingPrecision == 64) {
roundIncrement = BX_CONST64(0x0000000000000400);
roundMask = BX_CONST64(0x00000000000007FF);
}
else if (roundingPrecision == 32) {
roundIncrement = BX_CONST64(0x0000008000000000);
roundMask = BX_CONST64(0x000000FFFFFFFFFF);
}
else goto precision80;
zSig0 |= (zSig1 != 0);
if (! roundNearestEven) {
if (roundingMode == float_round_to_zero) roundIncrement = 0;
else {
roundIncrement = roundMask;
if (zSign) {
if (roundingMode == float_round_up) roundIncrement = 0;
}
else {
if (roundingMode == float_round_down) roundIncrement = 0;
}
}
}
roundBits = zSig0 & roundMask;
if (0x7FFD <= (Bit32u) (zExp - 1)) {
if ((0x7FFE < zExp)
|| ((zExp == 0x7FFE) && (zSig0 + roundIncrement < zSig0)))
{
goto overflow;
}
if (zExp <= 0) {
int isTiny = (zExp < 0) || (zSig0 <= zSig0 + roundIncrement);
zSig0 = shift64RightJamming(zSig0, 1 - zExp);
zSigExact = zSig0;
zExp = 0;
roundBits = zSig0 & roundMask;
if (isTiny) {
if (roundBits || (zSig0 && !float_exception_masked(status, float_flag_underflow)))
float_raise(status, float_flag_underflow);
}
zSig0 += roundIncrement;
if ((Bit64s) zSig0 < 0) zExp = 1;
roundIncrement = roundMask + 1;
if (roundNearestEven && (roundBits<<1 == roundIncrement))
roundMask |= roundIncrement;
zSig0 &= ~roundMask;
if (roundBits) {
float_raise(status, float_flag_inexact);
if (zSig0 > zSigExact) set_float_rounding_up(status);
}
return packFloatx80(zSign, zExp, zSig0);
}
}
if (roundBits) float_raise(status, float_flag_inexact);
zSigExact = zSig0;
zSig0 += roundIncrement;
if (zSig0 < roundIncrement) {
// Basically scale by shifting right and keep overflow
++zExp;
zSig0 = BX_CONST64(0x8000000000000000);
zSigExact >>= 1; // must scale also, or else later tests will fail
}
roundIncrement = roundMask + 1;
if (roundNearestEven && (roundBits<<1 == roundIncrement))
roundMask |= roundIncrement;
zSig0 &= ~roundMask;
if (zSig0 > zSigExact) set_float_rounding_up(status);
if (zSig0 == 0) zExp = 0;
return packFloatx80(zSign, zExp, zSig0);
precision80:
increment = ((Bit64s) zSig1 < 0);
if (! roundNearestEven) {
if (roundingMode == float_round_to_zero) increment = 0;
else {
if (zSign) {
increment = (roundingMode == float_round_down) && zSig1;
}
else {
increment = (roundingMode == float_round_up) && zSig1;
}
}
}
if (0x7FFD <= (Bit32u) (zExp - 1)) {
if ((0x7FFE < zExp)
|| ((zExp == 0x7FFE)
&& (zSig0 == BX_CONST64(0xFFFFFFFFFFFFFFFF))
&& increment))
{
roundMask = 0;
overflow:
float_raise(status, float_flag_overflow | float_flag_inexact);
if ((roundingMode == float_round_to_zero)
|| (zSign && (roundingMode == float_round_up))
|| (! zSign && (roundingMode == float_round_down)))
{
return packFloatx80(zSign, 0x7FFE, ~roundMask);
}
set_float_rounding_up(status);
return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000));
}
if (zExp <= 0) {
int isTiny = (zExp < 0) || (! increment)
|| (zSig0 < BX_CONST64(0xFFFFFFFFFFFFFFFF));
shift64ExtraRightJamming(zSig0, zSig1, 1 - zExp, &zSig0, &zSig1);
zExp = 0;
if (isTiny) {
if (zSig1 || (zSig0 && !float_exception_masked(status, float_flag_underflow)))
float_raise(status, float_flag_underflow);
}
if (zSig1) float_raise(status, float_flag_inexact);
if (roundNearestEven) increment = ((Bit64s) zSig1 < 0);
else {
if (zSign) {
increment = (roundingMode == float_round_down) && zSig1;
} else {
increment = (roundingMode == float_round_up) && zSig1;
}
}
if (increment) {
zSigExact = zSig0++;
zSig0 &= ~(((Bit64u) (zSig1<<1) == 0) & roundNearestEven);
if (zSig0 > zSigExact) set_float_rounding_up(status);
if ((Bit64s) zSig0 < 0) zExp = 1;
}
return packFloatx80(zSign, zExp, zSig0);
}
}
if (zSig1) float_raise(status, float_flag_inexact);
if (increment) {
zSigExact = zSig0++;
if (zSig0 == 0) {
zExp++;
zSig0 = BX_CONST64(0x8000000000000000);
zSigExact >>= 1; // must scale also, or else later tests will fail
}
else {
zSig0 &= ~(((Bit64u) (zSig1<<1) == 0) & roundNearestEven);
}
if (zSig0 > zSigExact) set_float_rounding_up(status);
}
else {
if (zSig0 == 0) zExp = 0;
}
return packFloatx80(zSign, zExp, zSig0);
}
floatx80 roundAndPackFloatx80(int roundingPrecision,
int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status)
{
struct float_status_t *round_status = status;
floatx80 result = SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp, zSig0, zSig1, status);
// bias unmasked undeflow
if (status->float_exception_flags & ~status->float_exception_masks & float_flag_underflow) {
float_raise(round_status, float_flag_underflow);
return SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp + 0x6000, zSig0, zSig1, status = round_status);
}
// bias unmasked overflow
if (status->float_exception_flags & ~status->float_exception_masks & float_flag_overflow) {
float_raise(round_status, float_flag_overflow);
return SoftFloatRoundAndPackFloatx80(roundingPrecision, zSign, zExp - 0x6000, zSig0, zSig1, status = round_status);
}
return result;
}
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent
| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
| and returns the proper extended double-precision floating-point value
| corresponding to the abstract input. This routine is just like
| `roundAndPackFloatx80' except that the input significand does not have to be
| normalized.
*----------------------------------------------------------------------------*/
floatx80 normalizeRoundAndPackFloatx80(int roundingPrecision,
int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status)
{
if (zSig0 == 0) {
zSig0 = zSig1;
zSig1 = 0;
zExp -= 64;
}
int shiftCount = countLeadingZeros64(zSig0);
shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1);
zExp -= shiftCount;
return
roundAndPackFloatx80(roundingPrecision, zSign, zExp, zSig0, zSig1, status);
}
#endif
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| Normalizes the subnormal quadruple-precision floating-point value
| represented by the denormalized significand formed by the concatenation of
| `aSig0' and `aSig1'. The normalized exponent is stored at the location
| pointed to by `zExpPtr'. The most significant 49 bits of the normalized
| significand are stored at the location pointed to by `zSig0Ptr', and the
| least significant 64 bits of the normalized significand are stored at the
| location pointed to by `zSig1Ptr'.
*----------------------------------------------------------------------------*/
void normalizeFloat128Subnormal(
Bit64u aSig0, Bit64u aSig1, Bit32s *zExpPtr, Bit64u *zSig0Ptr, Bit64u *zSig1Ptr)
{
int shiftCount;
if (aSig0 == 0) {
shiftCount = countLeadingZeros64(aSig1) - 15;
if (shiftCount < 0) {
*zSig0Ptr = aSig1 >>(-shiftCount);
*zSig1Ptr = aSig1 << (shiftCount & 63);
}
else {
*zSig0Ptr = aSig1 << shiftCount;
*zSig1Ptr = 0;
}
*zExpPtr = - shiftCount - 63;
}
else {
shiftCount = countLeadingZeros64(aSig0) - 15;
shortShift128Left(aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr);
*zExpPtr = 1 - shiftCount;
}
}
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and extended significand formed by the concatenation of `zSig0', `zSig1',
| and `zSig2', and returns the proper quadruple-precision floating-point value
| corresponding to the abstract input. Ordinarily, the abstract value is
| simply rounded and packed into the quadruple-precision format, with the
| inexact exception raised if the abstract input cannot be represented
| exactly. However, if the abstract value is too large, the overflow and
| inexact exceptions are raised and an infinity or maximal finite value is
| returned. If the abstract value is too small, the input value is rounded to
| a subnormal number, and the underflow and inexact exceptions are raised if
| the abstract input cannot be represented exactly as a subnormal quadruple-
| precision floating-point number.
| The input significand must be normalized or smaller. If the input
| significand is not normalized, `zExp' must be 0; in that case, the result
| returned is a subnormal number, and it must not require rounding. In the
| usual case that the input significand is normalized, `zExp' must be 1 less
| than the ``true'' floating-point exponent. The handling of underflow and
| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
float128 roundAndPackFloat128(
int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, Bit64u zSig2, struct float_status_t *status)
{
int increment = ((Bit64s) zSig2 < 0);
if (0x7FFD <= (Bit32u) zExp) {
if ((0x7FFD < zExp)
|| ((zExp == 0x7FFD)
&& eq128(BX_CONST64(0x0001FFFFFFFFFFFF),
BX_CONST64(0xFFFFFFFFFFFFFFFF), zSig0, zSig1)
&& increment))
{
float_raise(status, float_flag_overflow | float_flag_inexact);
return packFloat128Four(zSign, 0x7FFF, 0, 0);
}
if (zExp < 0) {
int isTiny = (zExp < -1)
|| ! increment
|| lt128(zSig0, zSig1,
BX_CONST64(0x0001FFFFFFFFFFFF),
BX_CONST64(0xFFFFFFFFFFFFFFFF));
shift128ExtraRightJamming(
zSig0, zSig1, zSig2, -zExp, &zSig0, &zSig1, &zSig2);
zExp = 0;
if (isTiny && zSig2) float_raise(status, float_flag_underflow);
increment = ((Bit64s) zSig2 < 0);
}
}
if (zSig2) float_raise(status, float_flag_inexact);
if (increment) {
add128(zSig0, zSig1, 0, 1, &zSig0, &zSig1);
zSig1 &= ~((zSig2 + zSig2 == 0) & 1);
}
else {
if ((zSig0 | zSig1) == 0) zExp = 0;
}
return packFloat128Four(zSign, zExp, zSig0, zSig1);
}
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and significand formed by the concatenation of `zSig0' and `zSig1', and
| returns the proper quadruple-precision floating-point value corresponding
| to the abstract input. This routine is just like `roundAndPackFloat128'
| except that the input significand has fewer bits and does not have to be
| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
| point exponent.
*----------------------------------------------------------------------------*/
float128 normalizeRoundAndPackFloat128(
int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status)
{
Bit64u zSig2;
if (zSig0 == 0) {
zSig0 = zSig1;
zSig1 = 0;
zExp -= 64;
}
int shiftCount = countLeadingZeros64(zSig0) - 15;
if (0 <= shiftCount) {
zSig2 = 0;
shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1);
}
else {
shift128ExtraRightJamming(
zSig0, zSig1, 0, -shiftCount, &zSig0, &zSig1, &zSig2);
}
zExp -= shiftCount;
return roundAndPackFloat128(zSign, zExp, zSig0, zSig1, zSig2, status);
}
#endif

View File

@@ -1,309 +0,0 @@
/*============================================================================
This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
Package, Release 2b.
Written by John R. Hauser. This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704. Funding was partially provided by the
National Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
arithmetic/SoftFloat.html'.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.
=============================================================================*/
/*============================================================================
* Adapted for Bochs (x86 achitecture simulator) by
* Stanislav Shwartsman [sshwarts at sourceforge net]
* ==========================================================================*/
#ifndef _SOFTFLOAT_ROUND_PACK_H_
#define _SOFTFLOAT_ROUND_PACK_H_
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
| and 7, and returns the properly rounded 32-bit integer corresponding to the
| input. If `zSign' is 1, the input is negated before being converted to an
| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input
| is simply rounded to an integer, with the inexact exception raised if the
| input cannot be represented exactly as an integer. However, if the fixed-
| point input is too large, the invalid exception is raised and the integer
| indefinite value is returned.
*----------------------------------------------------------------------------*/
Bit32s roundAndPackInt32(int zSign, Bit64u absZ, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
| `absZ1', with binary point between bits 63 and 64 (between the input words),
| and returns the properly rounded 64-bit integer corresponding to the input.
| If `zSign' is 1, the input is negated before being converted to an integer.
| Ordinarily, the fixed-point input is simply rounded to an integer, with
| the inexact exception raised if the input cannot be represented exactly as
| an integer. However, if the fixed-point input is too large, the invalid
| exception is raised and the integer indefinite value is returned.
*----------------------------------------------------------------------------*/
Bit64s roundAndPackInt64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
| `absZ1', with binary point between bits 63 and 64 (between the input words),
| and returns the properly rounded 64-bit unsigned integer corresponding to the
| input. Ordinarily, the fixed-point input is simply rounded to an integer,
| with the inexact exception raised if the input cannot be represented exactly
| as an integer. However, if the fixed-point input is too large, the invalid
| exception is raised and the largest unsigned integer is returned.
*----------------------------------------------------------------------------*/
Bit64u roundAndPackUint64(int zSign, Bit64u absZ0, Bit64u absZ1, struct float_status_t *status);
#ifdef FLOAT16
/*----------------------------------------------------------------------------
| Normalizes the subnormal half-precision floating-point value represented
| by the denormalized significand `aSig'. The normalized exponent and
| significand are stored at the locations pointed to by `zExpPtr' and
| `zSigPtr', respectively.
*----------------------------------------------------------------------------*/
void normalizeFloat16Subnormal(Bit16u aSig, Bit16s *zExpPtr, Bit16u *zSigPtr);
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and significand `zSig', and returns the proper half-precision floating-
| point value corresponding to the abstract input. Ordinarily, the abstract
| value is simply rounded and packed into the half-precision format, with
| the inexact exception raised if the abstract input cannot be represented
| exactly. However, if the abstract value is too large, the overflow and
| inexact exceptions are raised and an infinity or maximal finite value is
| returned. If the abstract value is too small, the input value is rounded to
| a subnormal number, and the underflow and inexact exceptions are raised if
| the abstract input cannot be represented exactly as a subnormal single-
| precision floating-point number.
| The input significand `zSig' has its binary point between bits 14
| and 13, which is 4 bits to the left of the usual location. This shifted
| significand must be normalized or smaller. If `zSig' is not normalized,
| `zExp' must be 0; in that case, the result returned is a subnormal number,
| and it must not require rounding. In the usual case that `zSig' is
| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
| The handling of underflow and overflow follows the IEC/IEEE Standard for
| Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
float16 roundAndPackFloat16(int zSign, Bit16s zExp, Bit16u zSig, struct float_status_t *status);
#endif
/*----------------------------------------------------------------------------
| Normalizes the subnormal single-precision floating-point value represented
| by the denormalized significand `aSig'. The normalized exponent and
| significand are stored at the locations pointed to by `zExpPtr' and
| `zSigPtr', respectively.
*----------------------------------------------------------------------------*/
void normalizeFloat32Subnormal(Bit32u aSig, Bit16s *zExpPtr, Bit32u *zSigPtr);
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and significand `zSig', and returns the proper single-precision floating-
| point value corresponding to the abstract input. Ordinarily, the abstract
| value is simply rounded and packed into the single-precision format, with
| the inexact exception raised if the abstract input cannot be represented
| exactly. However, if the abstract value is too large, the overflow and
| inexact exceptions are raised and an infinity or maximal finite value is
| returned. If the abstract value is too small, the input value is rounded to
| a subnormal number, and the underflow and inexact exceptions are raised if
| the abstract input cannot be represented exactly as a subnormal single-
| precision floating-point number.
| The input significand `zSig' has its binary point between bits 30
| and 29, which is 7 bits to the left of the usual location. This shifted
| significand must be normalized or smaller. If `zSig' is not normalized,
| `zExp' must be 0; in that case, the result returned is a subnormal number,
| and it must not require rounding. In the usual case that `zSig' is
| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
| The handling of underflow and overflow follows the IEC/IEEE Standard for
| Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
float32 roundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and significand `zSig', and returns the proper single-precision floating-
| point value corresponding to the abstract input. This routine is just like
| `roundAndPackFloat32' except that `zSig' does not have to be normalized.
| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
| floating-point exponent.
*----------------------------------------------------------------------------*/
float32 normalizeRoundAndPackFloat32(int zSign, Bit16s zExp, Bit32u zSig, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Normalizes the subnormal double-precision floating-point value represented
| by the denormalized significand `aSig'. The normalized exponent and
| significand are stored at the locations pointed to by `zExpPtr' and
| `zSigPtr', respectively.
*----------------------------------------------------------------------------*/
void normalizeFloat64Subnormal(Bit64u aSig, Bit16s *zExpPtr, Bit64u *zSigPtr);
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and significand `zSig', and returns the proper double-precision floating-
| point value corresponding to the abstract input. Ordinarily, the abstract
| value is simply rounded and packed into the double-precision format, with
| the inexact exception raised if the abstract input cannot be represented
| exactly. However, if the abstract value is too large, the overflow and
| inexact exceptions are raised and an infinity or maximal finite value is
| returned. If the abstract value is too small, the input value is rounded
| to a subnormal number, and the underflow and inexact exceptions are raised
| if the abstract input cannot be represented exactly as a subnormal double-
| precision floating-point number.
| The input significand `zSig' has its binary point between bits 62
| and 61, which is 10 bits to the left of the usual location. This shifted
| significand must be normalized or smaller. If `zSig' is not normalized,
| `zExp' must be 0; in that case, the result returned is a subnormal number,
| and it must not require rounding. In the usual case that `zSig' is
| normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
| The handling of underflow and overflow follows the IEC/IEEE Standard for
| Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
float64 roundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and significand `zSig', and returns the proper double-precision floating-
| point value corresponding to the abstract input. This routine is just like
| `roundAndPackFloat64' except that `zSig' does not have to be normalized.
| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
| floating-point exponent.
*----------------------------------------------------------------------------*/
float64 normalizeRoundAndPackFloat64(int zSign, Bit16s zExp, Bit64u zSig, struct float_status_t *status);
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Normalizes the subnormal extended double-precision floating-point value
| represented by the denormalized significand `aSig'. The normalized exponent
| and significand are stored at the locations pointed to by `zExpPtr' and
| `zSigPtr', respectively.
*----------------------------------------------------------------------------*/
void normalizeFloatx80Subnormal(Bit64u aSig, Bit32s *zExpPtr, Bit64u *zSigPtr);
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and extended significand formed by the concatenation of `zSig0' and `zSig1',
| and returns the proper extended double-precision floating-point value
| corresponding to the abstract input. Ordinarily, the abstract value is
| rounded and packed into the extended double-precision format, with the
| inexact exception raised if the abstract input cannot be represented
| exactly. However, if the abstract value is too large, the overflow and
| inexact exceptions are raised and an infinity or maximal finite value is
| returned. If the abstract value is too small, the input value is rounded to
| a subnormal number, and the underflow and inexact exceptions are raised if
| the abstract input cannot be represented exactly as a subnormal extended
| double-precision floating-point number.
| If `roundingPrecision' is 32 or 64, the result is rounded to the same
| number of bits as single or double precision, respectively. Otherwise, the
| result is rounded to the full precision of the extended double-precision
| format.
| The input significand must be normalized or smaller. If the input
| significand is not normalized, `zExp' must be 0; in that case, the result
| returned is a subnormal number, and it must not require rounding. The
| handling of underflow and overflow follows the IEC/IEEE Standard for Binary
| Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
floatx80 roundAndPackFloatx80(int roundingPrecision,
int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent
| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
| and returns the proper extended double-precision floating-point value
| corresponding to the abstract input. This routine is just like
| `roundAndPackFloatx80' except that the input significand does not have to be
| normalized.
*----------------------------------------------------------------------------*/
floatx80 normalizeRoundAndPackFloatx80(int roundingPrecision,
int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status);
#endif // FLOATX80
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| Normalizes the subnormal quadruple-precision floating-point value
| represented by the denormalized significand formed by the concatenation of
| `aSig0' and `aSig1'. The normalized exponent is stored at the location
| pointed to by `zExpPtr'. The most significant 49 bits of the normalized
| significand are stored at the location pointed to by `zSig0Ptr', and the
| least significant 64 bits of the normalized significand are stored at the
| location pointed to by `zSig1Ptr'.
*----------------------------------------------------------------------------*/
void normalizeFloat128Subnormal(
Bit64u aSig0, Bit64u aSig1, Bit32s *zExpPtr, Bit64u *zSig0Ptr, Bit64u *zSig1Ptr);
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and extended significand formed by the concatenation of `zSig0', `zSig1',
| and `zSig2', and returns the proper quadruple-precision floating-point value
| corresponding to the abstract input. Ordinarily, the abstract value is
| simply rounded and packed into the quadruple-precision format, with the
| inexact exception raised if the abstract input cannot be represented
| exactly. However, if the abstract value is too large, the overflow and
| inexact exceptions are raised and an infinity or maximal finite value is
| returned. If the abstract value is too small, the input value is rounded to
| a subnormal number, and the underflow and inexact exceptions are raised if
| the abstract input cannot be represented exactly as a subnormal quadruple-
| precision floating-point number.
| The input significand must be normalized or smaller. If the input
| significand is not normalized, `zExp' must be 0; in that case, the result
| returned is a subnormal number, and it must not require rounding. In the
| usual case that the input significand is normalized, `zExp' must be 1 less
| than the ``true'' floating-point exponent. The handling of underflow and
| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
float128 roundAndPackFloat128(
int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, Bit64u zSig2, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Takes an abstract floating-point value having sign `zSign', exponent `zExp',
| and significand formed by the concatenation of `zSig0' and `zSig1', and
| returns the proper quadruple-precision floating-point value corresponding
| to the abstract input. This routine is just like `roundAndPackFloat128'
| except that the input significand has fewer bits and does not have to be
| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
| point exponent.
*----------------------------------------------------------------------------*/
float128 normalizeRoundAndPackFloat128(
int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, struct float_status_t *status);
#endif // FLOAT128
#endif

View File

@@ -1,187 +0,0 @@
/*============================================================================
This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
Arithmetic Package, Release 2b.
Written by John R. Hauser. This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704. Funding was partially provided by the
National Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
arithmetic/SoftFloat.html'.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.
=============================================================================*/
#define FLOAT128
/*============================================================================
* Adapted for Bochs (x86 achitecture simulator) by
* Stanislav Shwartsman [sshwarts at sourceforge net]
* ==========================================================================*/
#include "softfloat.h"
#include "softfloat-specialize.h"
/*----------------------------------------------------------------------------
| Takes two single-precision floating-point values `a' and `b', one of which
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
float32 propagateFloat32NaN(float32 a, float32 b, struct float_status_t *status)
{
int aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
aIsNaN = float32_is_nan(a);
aIsSignalingNaN = float32_is_signaling_nan(a);
bIsNaN = float32_is_nan(b);
bIsSignalingNaN = float32_is_signaling_nan(b);
a |= 0x00400000;
b |= 0x00400000;
if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid);
if (get_float_nan_handling_mode(status) == float_larger_significand_nan) {
if (aIsSignalingNaN) {
if (bIsSignalingNaN) goto returnLargerSignificand;
return bIsNaN ? b : a;
}
else if (aIsNaN) {
if (bIsSignalingNaN | ! bIsNaN) return a;
returnLargerSignificand:
if ((Bit32u) (a<<1) < (Bit32u) (b<<1)) return b;
if ((Bit32u) (b<<1) < (Bit32u) (a<<1)) return a;
return (a < b) ? a : b;
}
else {
return b;
}
} else {
return (aIsSignalingNaN | aIsNaN) ? a : b;
}
}
/*----------------------------------------------------------------------------
| Takes two double-precision floating-point values `a' and `b', one of which
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
float64 propagateFloat64NaN(float64 a, float64 b, struct float_status_t *status)
{
int aIsNaN = float64_is_nan(a);
int aIsSignalingNaN = float64_is_signaling_nan(a);
int bIsNaN = float64_is_nan(b);
int bIsSignalingNaN = float64_is_signaling_nan(b);
a |= BX_CONST64(0x0008000000000000);
b |= BX_CONST64(0x0008000000000000);
if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid);
if (get_float_nan_handling_mode(status) == float_larger_significand_nan) {
if (aIsSignalingNaN) {
if (bIsSignalingNaN) goto returnLargerSignificand;
return bIsNaN ? b : a;
}
else if (aIsNaN) {
if (bIsSignalingNaN | ! bIsNaN) return a;
returnLargerSignificand:
if ((Bit64u) (a<<1) < (Bit64u) (b<<1)) return b;
if ((Bit64u) (b<<1) < (Bit64u) (a<<1)) return a;
return (a < b) ? a : b;
}
else {
return b;
}
} else {
return (aIsSignalingNaN | aIsNaN) ? a : b;
}
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Takes two extended double-precision floating-point values `a' and `b', one
| of which is a NaN, and returns the appropriate NaN result. If either `a' or
| `b' is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, struct float_status_t *status)
{
int aIsNaN = floatx80_is_nan(a);
int aIsSignalingNaN = floatx80_is_signaling_nan(a);
int bIsNaN = floatx80_is_nan(b);
int bIsSignalingNaN = floatx80_is_signaling_nan(b);
a.fraction |= BX_CONST64(0xC000000000000000);
b.fraction |= BX_CONST64(0xC000000000000000);
if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid);
if (aIsSignalingNaN) {
if (bIsSignalingNaN) goto returnLargerSignificand;
return bIsNaN ? b : a;
}
else if (aIsNaN) {
if (bIsSignalingNaN | ! bIsNaN) return a;
returnLargerSignificand:
if (a.fraction < b.fraction) return b;
if (b.fraction < a.fraction) return a;
return (a.exp < b.exp) ? a : b;
}
else {
return b;
}
}
#endif /* FLOATX80 */
#ifdef FLOAT128
/*----------------------------------------------------------------------------
| Takes two quadruple-precision floating-point values `a' and `b', one of
| which is a NaN, and returns the appropriate NaN result. If either `a' or
| `b' is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
float128 propagateFloat128NaN(float128 a, float128 b, struct float_status_t *status)
{
int aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
aIsNaN = float128_is_nan(a);
aIsSignalingNaN = float128_is_signaling_nan(a);
bIsNaN = float128_is_nan(b);
bIsSignalingNaN = float128_is_signaling_nan(b);
a.hi |= BX_CONST64(0x0000800000000000);
b.hi |= BX_CONST64(0x0000800000000000);
if (aIsSignalingNaN | bIsSignalingNaN) float_raise(status, float_flag_invalid);
if (aIsSignalingNaN) {
if (bIsSignalingNaN) goto returnLargerSignificand;
return bIsNaN ? b : a;
}
else if (aIsNaN) {
if (bIsSignalingNaN | !bIsNaN) return a;
returnLargerSignificand:
if (lt128(a.hi<<1, a.lo, b.hi<<1, b.lo)) return b;
if (lt128(b.hi<<1, b.lo, a.hi<<1, a.lo)) return a;
return (a.hi < b.hi) ? a : b;
}
else {
return b;
}
}
/*----------------------------------------------------------------------------
| The pattern for a default generated quadruple-precision NaN.
*----------------------------------------------------------------------------*/
const float128 float128_default_nan =
packFloat128(float128_default_nan_hi, float128_default_nan_lo);
#endif /* FLOAT128 */

View File

@@ -1,789 +0,0 @@
/*============================================================================
This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
Arithmetic Package, Release 2b.
Written by John R. Hauser. This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704. Funding was partially provided by the
National Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
arithmetic/SoftFloat.html'.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.
=============================================================================*/
#ifndef _SOFTFLOAT_SPECIALIZE_H_
#define _SOFTFLOAT_SPECIALIZE_H_
#include "softfloat.h"
/*============================================================================
* Adapted for Bochs (x86 achitecture simulator) by
* Stanislav Shwartsman [sshwarts at sourceforge net]
* ==========================================================================*/
#define int16_indefinite ((Bit16s)0x8000)
#define int32_indefinite ((Bit32s)0x80000000)
#define int64_indefinite BX_CONST64(0x8000000000000000)
#define uint16_indefinite (0xffff)
#define uint32_indefinite (0xffffffff)
#define uint64_indefinite BX_CONST64(0xffffffffffffffff)
/*----------------------------------------------------------------------------
| Internal canonical NaN format.
*----------------------------------------------------------------------------*/
typedef struct {
int sign;
Bit64u hi, lo;
} commonNaNT;
#ifdef FLOAT16
/*----------------------------------------------------------------------------
| The pattern for a default generated half-precision NaN.
*----------------------------------------------------------------------------*/
extern const float16 float16_default_nan;
#define float16_fraction extractFloat16Frac
#define float16_exp extractFloat16Exp
#define float16_sign extractFloat16Sign
/*----------------------------------------------------------------------------
| Returns the fraction bits of the half-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit16u extractFloat16Frac(float16 a)
{
return a & 0x3FF;
}
/*----------------------------------------------------------------------------
| Returns the exponent bits of the half-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit16s extractFloat16Exp(float16 a)
{
return (a>>10) & 0x1F;
}
/*----------------------------------------------------------------------------
| Returns the sign bit of the half-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int extractFloat16Sign(float16 a)
{
return a>>15;
}
/*----------------------------------------------------------------------------
| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
| single-precision floating-point value, returning the result. After being
| shifted into the proper positions, the three fields are simply added
| together to form the result. This means that any integer portion of `zSig'
| will be added into the exponent. Since a properly normalized significand
| will have an integer portion equal to 1, the `zExp' input should be 1 less
| than the desired result exponent whenever `zSig' is a complete, normalized
| significand.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE float16 packFloat16(int zSign, int zExp, Bit16u zSig)
{
return (((Bit16u) zSign)<<15) + (((Bit16u) zExp)<<10) + zSig;
}
/*----------------------------------------------------------------------------
| Returns 1 if the half-precision floating-point value `a' is a NaN;
| otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int float16_is_nan(float16 a)
{
return (0xF800 < (Bit16u) (a<<1));
}
/*----------------------------------------------------------------------------
| Returns 1 if the half-precision floating-point value `a' is a signaling
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int float16_is_signaling_nan(float16 a)
{
return (((a>>9) & 0x3F) == 0x3E) && (a & 0x1FF);
}
/*----------------------------------------------------------------------------
| Returns 1 if the half-precision floating-point value `a' is denormal;
| otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int float16_is_denormal(float16 a)
{
return (extractFloat16Exp(a) == 0) && (extractFloat16Frac(a) != 0);
}
/*----------------------------------------------------------------------------
| Convert float16 denormals to zero.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE float16 float16_denormal_to_zero(float16 a)
{
if (float16_is_denormal(a)) a &= 0x8000;
return a;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the half-precision floating-point NaN
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE commonNaNT float16ToCommonNaN(float16 a, struct float_status_t *status)
{
commonNaNT z;
if (float16_is_signaling_nan(a)) float_raise(status, float_flag_invalid);
z.sign = a>>15;
z.lo = 0;
z.hi = ((Bit64u) a)<<54;
return z;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the half-
| precision floating-point format.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE float16 commonNaNToFloat16(commonNaNT a)
{
return (((Bit16u) a.sign)<<15) | 0x7E00 | (Bit16u)(a.hi>>54);
}
#endif
/*----------------------------------------------------------------------------
| Commonly used single-precision floating point constants
*----------------------------------------------------------------------------*/
extern const float32 float32_negative_inf;
extern const float32 float32_positive_inf;
extern const float32 float32_negative_zero;
extern const float32 float32_positive_zero;
extern const float32 float32_negative_one;
extern const float32 float32_positive_one;
extern const float32 float32_max_float;
extern const float32 float32_min_float;
/*----------------------------------------------------------------------------
| The pattern for a default generated single-precision NaN.
*----------------------------------------------------------------------------*/
extern const float32 float32_default_nan;
#define float32_fraction extractFloat32Frac
#define float32_exp extractFloat32Exp
#define float32_sign extractFloat32Sign
#define FLOAT32_EXP_BIAS 0x7F
/*----------------------------------------------------------------------------
| Returns the fraction bits of the single-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit32u extractFloat32Frac(float32 a)
{
return a & 0x007FFFFF;
}
/*----------------------------------------------------------------------------
| Returns the exponent bits of the single-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit16s extractFloat32Exp(float32 a)
{
return (a>>23) & 0xFF;
}
/*----------------------------------------------------------------------------
| Returns the sign bit of the single-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int extractFloat32Sign(float32 a)
{
return a>>31;
}
/*----------------------------------------------------------------------------
| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
| single-precision floating-point value, returning the result. After being
| shifted into the proper positions, the three fields are simply added
| together to form the result. This means that any integer portion of `zSig'
| will be added into the exponent. Since a properly normalized significand
| will have an integer portion equal to 1, the `zExp' input should be 1 less
| than the desired result exponent whenever `zSig' is a complete, normalized
| significand.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE float32 packFloat32(int zSign, Bit16s zExp, Bit32u zSig)
{
return (((Bit32u) zSign)<<31) + (((Bit32u) zExp)<<23) + zSig;
}
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is a NaN;
| otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int float32_is_nan(float32 a)
{
return (0xFF000000 < (Bit32u) (a<<1));
}
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is a signaling
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int float32_is_signaling_nan(float32 a)
{
return (((a>>22) & 0x1FF) == 0x1FE) && (a & 0x003FFFFF);
}
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is denormal;
| otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int float32_is_denormal(float32 a)
{
return (extractFloat32Exp(a) == 0) && (extractFloat32Frac(a) != 0);
}
/*----------------------------------------------------------------------------
| Convert float32 denormals to zero.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE float32 float32_denormal_to_zero(float32 a)
{
if (float32_is_denormal(a)) a &= 0x80000000;
return a;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the single-precision floating-point NaN
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE commonNaNT float32ToCommonNaN(float32 a, struct float_status_t *status)
{
commonNaNT z;
if (float32_is_signaling_nan(a)) float_raise(status, float_flag_invalid);
z.sign = a>>31;
z.lo = 0;
z.hi = ((Bit64u) a)<<41;
return z;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the single-
| precision floating-point format.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE float32 commonNaNToFloat32(commonNaNT a)
{
return (((Bit32u) a.sign)<<31) | 0x7FC00000 | (Bit32u)(a.hi>>41);
}
/*----------------------------------------------------------------------------
| Takes two single-precision floating-point values `a' and `b', one of which
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
float32 propagateFloat32NaN(float32 a, float32 b, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Takes single-precision floating-point NaN `a' and returns the appropriate
| NaN result. If `a' is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE float32 propagateFloat32NaNOne(float32 a, struct float_status_t *status)
{
if (float32_is_signaling_nan(a))
float_raise(status, float_flag_invalid);
return a | 0x00400000;
}
/*----------------------------------------------------------------------------
| Commonly used single-precision floating point constants
*----------------------------------------------------------------------------*/
extern const float64 float64_negative_inf;
extern const float64 float64_positive_inf;
extern const float64 float64_negative_zero;
extern const float64 float64_positive_zero;
extern const float64 float64_negative_one;
extern const float64 float64_positive_one;
extern const float64 float64_max_float;
extern const float64 float64_min_float;
/*----------------------------------------------------------------------------
| The pattern for a default generated double-precision NaN.
*----------------------------------------------------------------------------*/
extern const float64 float64_default_nan;
#define float64_fraction extractFloat64Frac
#define float64_exp extractFloat64Exp
#define float64_sign extractFloat64Sign
#define FLOAT64_EXP_BIAS 0x3FF
/*----------------------------------------------------------------------------
| Returns the fraction bits of the double-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit64u extractFloat64Frac(float64 a)
{
return a & BX_CONST64(0x000FFFFFFFFFFFFF);
}
/*----------------------------------------------------------------------------
| Returns the exponent bits of the double-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit16s extractFloat64Exp(float64 a)
{
return (Bit16s)(a>>52) & 0x7FF;
}
/*----------------------------------------------------------------------------
| Returns the sign bit of the double-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int extractFloat64Sign(float64 a)
{
return (int)(a>>63);
}
/*----------------------------------------------------------------------------
| Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
| double-precision floating-point value, returning the result. After being
| shifted into the proper positions, the three fields are simply added
| together to form the result. This means that any integer portion of `zSig'
| will be added into the exponent. Since a properly normalized significand
| will have an integer portion equal to 1, the `zExp' input should be 1 less
| than the desired result exponent whenever `zSig' is a complete, normalized
| significand.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE float64 packFloat64(int zSign, Bit16s zExp, Bit64u zSig)
{
return (((Bit64u) zSign)<<63) + (((Bit64u) zExp)<<52) + zSig;
}
/*----------------------------------------------------------------------------
| Returns 1 if the double-precision floating-point value `a' is a NaN;
| otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int float64_is_nan(float64 a)
{
return (BX_CONST64(0xFFE0000000000000) < (Bit64u) (a<<1));
}
/*----------------------------------------------------------------------------
| Returns 1 if the double-precision floating-point value `a' is a signaling
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int float64_is_signaling_nan(float64 a)
{
return (((a>>51) & 0xFFF) == 0xFFE) && (a & BX_CONST64(0x0007FFFFFFFFFFFF));
}
/*----------------------------------------------------------------------------
| Returns 1 if the double-precision floating-point value `a' is denormal;
| otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int float64_is_denormal(float64 a)
{
return (extractFloat64Exp(a) == 0) && (extractFloat64Frac(a) != 0);
}
/*----------------------------------------------------------------------------
| Convert float64 denormals to zero.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE float64 float64_denormal_to_zero(float64 a)
{
if (float64_is_denormal(a)) a &= ((Bit64u)(1) << 63);
return a;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the double-precision floating-point NaN
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE commonNaNT float64ToCommonNaN(float64 a, struct float_status_t *status)
{
commonNaNT z;
if (float64_is_signaling_nan(a)) float_raise(status, float_flag_invalid);
z.sign = (int)(a>>63);
z.lo = 0;
z.hi = a<<12;
return z;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the double-
| precision floating-point format.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE float64 commonNaNToFloat64(commonNaNT a)
{
return (((Bit64u) a.sign)<<63) | BX_CONST64(0x7FF8000000000000) | (a.hi>>12);
}
/*----------------------------------------------------------------------------
| Takes two double-precision floating-point values `a' and `b', one of which
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
| signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
float64 propagateFloat64NaN(float64 a, float64 b, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Takes double-precision floating-point NaN `a' and returns the appropriate
| NaN result. If `a' is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE float64 propagateFloat64NaNOne(float64 a, struct float_status_t *status)
{
if (float64_is_signaling_nan(a))
float_raise(status, float_flag_invalid);
return a | BX_CONST64(0x0008000000000000);
}
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN. The
| `high' and `low' values hold the most- and least-significant bits,
| respectively.
*----------------------------------------------------------------------------*/
#define floatx80_default_nan_exp 0xFFFF
#define floatx80_default_nan_fraction BX_CONST64(0xC000000000000000)
#define floatx80_fraction extractFloatx80Frac
#define floatx80_exp extractFloatx80Exp
#define floatx80_sign extractFloatx80Sign
#define FLOATX80_EXP_BIAS 0x3FFF
/*----------------------------------------------------------------------------
| Returns the fraction bits of the extended double-precision floating-point
| value `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit64u extractFloatx80Frac(floatx80 a)
{
return a.fraction;
}
/*----------------------------------------------------------------------------
| Returns the exponent bits of the extended double-precision floating-point
| value `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit32s extractFloatx80Exp(floatx80 a)
{
return a.exp & 0x7FFF;
}
/*----------------------------------------------------------------------------
| Returns the sign bit of the extended double-precision floating-point value
| `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int extractFloatx80Sign(floatx80 a)
{
return a.exp>>15;
}
/*----------------------------------------------------------------------------
| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
| extended double-precision floating-point value, returning the result.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE floatx80 packFloatx80(int zSign, Bit32s zExp, Bit64u zSig)
{
floatx80 z;
z.fraction = zSig;
z.exp = (zSign << 15) + zExp;
return z;
}
/*----------------------------------------------------------------------------
| Returns 1 if the extended double-precision floating-point value `a' is a
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int floatx80_is_nan(floatx80 a)
{
// return ((a.exp & 0x7FFF) == 0x7FFF) && (Bit64s) (a.fraction<<1);
return ((a.exp & 0x7FFF) == 0x7FFF) && (((Bit64s) (a.fraction<<1)) != 0);
}
/*----------------------------------------------------------------------------
| Returns 1 if the extended double-precision floating-point value `a' is a
| signaling NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int floatx80_is_signaling_nan(floatx80 a)
{
Bit64u aLow = a.fraction & ~BX_CONST64(0x4000000000000000);
return ((a.exp & 0x7FFF) == 0x7FFF) &&
((Bit64u) (aLow<<1)) && (a.fraction == aLow);
}
/*----------------------------------------------------------------------------
| Returns 1 if the extended double-precision floating-point value `a' is an
| unsupported; otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int floatx80_is_unsupported(floatx80 a)
{
return ((a.exp & 0x7FFF) && !(a.fraction & BX_CONST64(0x8000000000000000)));
}
/*----------------------------------------------------------------------------
| Returns the result of converting the extended double-precision floating-
| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
| invalid exception is raised.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE commonNaNT floatx80ToCommonNaN(floatx80 a, struct float_status_t *status)
{
commonNaNT z;
if (floatx80_is_signaling_nan(a)) float_raise(status, float_flag_invalid);
z.sign = a.exp >> 15;
z.lo = 0;
z.hi = a.fraction << 1;
return z;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the extended
| double-precision floating-point format.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE floatx80 commonNaNToFloatx80(commonNaNT a)
{
floatx80 z;
z.fraction = BX_CONST64(0xC000000000000000) | (a.hi>>1);
z.exp = (((Bit16u) a.sign)<<15) | 0x7FFF;
return z;
}
/*----------------------------------------------------------------------------
| Takes two extended double-precision floating-point values `a' and `b', one
| of which is a NaN, and returns the appropriate NaN result. If either `a' or
| `b' is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
floatx80 propagateFloatx80NaN(floatx80 a, floatx80 b, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Takes extended double-precision floating-point NaN `a' and returns the
| appropriate NaN result. If `a' is a signaling NaN, the invalid exception
| is raised.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE floatx80 propagateFloatx80NaNOne(floatx80 a, struct float_status_t *status)
{
if (floatx80_is_signaling_nan(a))
float_raise(status, float_flag_invalid);
a.fraction |= BX_CONST64(0xC000000000000000);
return a;
}
#endif /* FLOATX80 */
#ifdef FLOAT128
#include "softfloat-macros.h"
/*----------------------------------------------------------------------------
| The pattern for a default generated quadruple-precision NaN. The `high' and
| `low' values hold the most- and least-significant bits, respectively.
*----------------------------------------------------------------------------*/
#define float128_default_nan_hi BX_CONST64(0xFFFF800000000000)
#define float128_default_nan_lo BX_CONST64(0x0000000000000000)
#define float128_exp extractFloat128Exp
/*----------------------------------------------------------------------------
| Returns the least-significant 64 fraction bits of the quadruple-precision
| floating-point value `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit64u extractFloat128Frac1(float128 a)
{
return a.lo;
}
/*----------------------------------------------------------------------------
| Returns the most-significant 48 fraction bits of the quadruple-precision
| floating-point value `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit64u extractFloat128Frac0(float128 a)
{
return a.hi & BX_CONST64(0x0000FFFFFFFFFFFF);
}
/*----------------------------------------------------------------------------
| Returns the exponent bits of the quadruple-precision floating-point value
| `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE Bit32s extractFloat128Exp(float128 a)
{
return ((Bit32s)(a.hi>>48)) & 0x7FFF;
}
/*----------------------------------------------------------------------------
| Returns the sign bit of the quadruple-precision floating-point value `a'.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int extractFloat128Sign(float128 a)
{
return (int)(a.hi >> 63);
}
/*----------------------------------------------------------------------------
| Packs the sign `zSign', the exponent `zExp', and the significand formed
| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision
| floating-point value, returning the result. After being shifted into the
| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply
| added together to form the most significant 32 bits of the result. This
| means that any integer portion of `zSig0' will be added into the exponent.
| Since a properly normalized significand will have an integer portion equal
| to 1, the `zExp' input should be 1 less than the desired result exponent
| whenever `zSig0' and `zSig1' concatenated form a complete, normalized
| significand.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE float128 packFloat128Four(int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1)
{
float128 z;
z.lo = zSig1;
z.hi = (((Bit64u) zSign)<<63) + (((Bit64u) zExp)<<48) + zSig0;
return z;
}
/*----------------------------------------------------------------------------
| Packs two 64-bit precision integers into into the quadruple-precision
| floating-point value, returning the result.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE float128 packFloat128(Bit64u zHi, Bit64u zLo)
{
float128 z;
z.lo = zLo;
z.hi = zHi;
return z;
}
#ifdef _MSC_VER
#define PACK_FLOAT_128(hi,lo) { lo, hi }
#else
#define PACK_FLOAT_128(hi,lo) packFloat128(BX_CONST64(hi),BX_CONST64(lo))
#endif
/*----------------------------------------------------------------------------
| Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
| otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int float128_is_nan(float128 a)
{
return (BX_CONST64(0xFFFE000000000000) <= (Bit64u) (a.hi<<1))
&& (a.lo || (a.hi & BX_CONST64(0x0000FFFFFFFFFFFF)));
}
/*----------------------------------------------------------------------------
| Returns 1 if the quadruple-precision floating-point value `a' is a
| signaling NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int float128_is_signaling_nan(float128 a)
{
return (((a.hi>>47) & 0xFFFF) == 0xFFFE)
&& (a.lo || (a.hi & BX_CONST64(0x00007FFFFFFFFFFF)));
}
/*----------------------------------------------------------------------------
| Returns the result of converting the quadruple-precision floating-point NaN
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
| exception is raised.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE commonNaNT float128ToCommonNaN(float128 a, struct float_status_t *status)
{
commonNaNT z;
if (float128_is_signaling_nan(a)) float_raise(status, float_flag_invalid);
z.sign = (int)(a.hi>>63);
shortShift128Left(a.hi, a.lo, 16, &z.hi, &z.lo);
return z;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the quadruple-
| precision floating-point format.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE float128 commonNaNToFloat128(commonNaNT a)
{
float128 z;
shift128Right(a.hi, a.lo, 16, &z.hi, &z.lo);
z.hi |= (((Bit64u) a.sign)<<63) | BX_CONST64(0x7FFF800000000000);
return z;
}
/*----------------------------------------------------------------------------
| Takes two quadruple-precision floating-point values `a' and `b', one of
| which is a NaN, and returns the appropriate NaN result. If either `a' or
| `b' is a signaling NaN, the invalid exception is raised.
*----------------------------------------------------------------------------*/
float128 propagateFloat128NaN(float128 a, float128 b, struct float_status_t *status);
/*----------------------------------------------------------------------------
| The pattern for a default generated quadruple-precision NaN.
*----------------------------------------------------------------------------*/
extern const float128 float128_default_nan;
#endif /* FLOAT128 */
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,488 +0,0 @@
/*============================================================================
This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
Package, Release 2b.
Written by John R. Hauser. This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704. Funding was partially provided by the
National Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
arithmetic/SoftFloat.html'.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.
=============================================================================*/
/*============================================================================
* Adapted for Bochs (x86 achitecture simulator) by
* Stanislav Shwartsman [sshwarts at sourceforge net]
* ==========================================================================*/
#include "config.h" /* generated by configure script from config.h.in */
#ifndef _SOFTFLOAT_H_
#define _SOFTFLOAT_H_
#define FLOAT16
#define FLOATX80
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point types.
*----------------------------------------------------------------------------*/
#ifdef FLOAT16
typedef Bit16u float16;
#endif
typedef Bit32u float32;
typedef Bit64u float64;
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point class.
*----------------------------------------------------------------------------*/
typedef enum {
float_zero,
float_SNaN,
float_QNaN,
float_negative_inf,
float_positive_inf,
float_denormal,
float_normalized
} float_class_t;
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point NaN operands handling mode.
*----------------------------------------------------------------------------*/
enum float_nan_handling_mode_t {
float_larger_significand_nan = 0, // this mode used by x87 FPU
float_first_operand_nan = 1 // this mode used by SSE
};
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point rounding mode.
*----------------------------------------------------------------------------*/
enum float_round_t {
float_round_nearest_even = 0,
float_round_down = 1,
float_round_up = 2,
float_round_to_zero = 3
};
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point exception flags.
*----------------------------------------------------------------------------*/
enum float_exception_flag_t {
float_flag_invalid = 0x01,
float_flag_denormal = 0x02,
float_flag_divbyzero = 0x04,
float_flag_overflow = 0x08,
float_flag_underflow = 0x10,
float_flag_inexact = 0x20
};
extern const unsigned float_all_exceptions_mask;
#ifdef FLOATX80
#define RAISE_SW_C1 0x0200
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point ordering relations
*----------------------------------------------------------------------------*/
enum {
float_relation_less = -1,
float_relation_equal = 0,
float_relation_greater = 1,
float_relation_unordered = 2
};
/*----------------------------------------------------------------------------
| Options to indicate which negations to perform in float*_muladd()
| Using these differs from negating an input or output before calling
| the muladd function in that this means that a NaN doesn't have its
| sign bit inverted before it is propagated.
*----------------------------------------------------------------------------*/
enum {
float_muladd_negate_c = 1,
float_muladd_negate_product = 2,
float_muladd_negate_result = float_muladd_negate_c | float_muladd_negate_product
};
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point status structure.
*----------------------------------------------------------------------------*/
struct float_status_t
{
#ifdef FLOATX80
int float_rounding_precision; /* floatx80 only */
#endif
int float_rounding_mode;
int float_exception_flags;
int float_exception_masks;
int float_suppress_exception;
int float_nan_handling_mode; /* flag register */
int flush_underflow_to_zero; /* flag register */
int denormals_are_zeros; /* flag register */
};
/*----------------------------------------------------------------------------
| Routine to raise any or all of the software IEC/IEEE floating-point
| exception flags.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE void float_raise(struct float_status_t *status, int flags)
{
status->float_exception_flags |= flags;
}
/*----------------------------------------------------------------------------
| Returns raised IEC/IEEE floating-point exception flags.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int get_exception_flags(const struct float_status_t *status)
{
return status->float_exception_flags & ~status->float_suppress_exception;
}
/*----------------------------------------------------------------------------
| Routine to check if any or all of the software IEC/IEEE floating-point
| exceptions are masked.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int float_exception_masked(const struct float_status_t *status, int flag)
{
return status->float_exception_masks & flag;
}
/*----------------------------------------------------------------------------
| Returns current floating point rounding mode specified by status word.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int get_float_rounding_mode(const struct float_status_t *status)
{
return status->float_rounding_mode;
}
/*----------------------------------------------------------------------------
| Returns current floating point precision (floatx80 only).
*----------------------------------------------------------------------------*/
#ifdef FLOATX80
BX_CPP_INLINE int get_float_rounding_precision(const struct float_status_t *status)
{
return status->float_rounding_precision;
}
#endif
/*----------------------------------------------------------------------------
| Returns current floating point NaN operands handling mode specified
| by status word.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int get_float_nan_handling_mode(const struct float_status_t *status)
{
return status->float_nan_handling_mode;
}
/*----------------------------------------------------------------------------
| Raise floating point precision lost up flag (floatx80 only).
*----------------------------------------------------------------------------*/
#ifdef FLOATX80
BX_CPP_INLINE void set_float_rounding_up(struct float_status_t *status)
{
status->float_exception_flags |= RAISE_SW_C1;
}
#endif
/*----------------------------------------------------------------------------
| Returns 1 if the <denormals-are-zeros> feature is supported;
| otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int get_denormals_are_zeros(const struct float_status_t *status)
{
return status->denormals_are_zeros;
}
/*----------------------------------------------------------------------------
| Returns 1 if the <flush-underflow-to-zero> feature is supported;
| otherwise returns 0.
*----------------------------------------------------------------------------*/
BX_CPP_INLINE int get_flush_underflow_to_zero(const struct float_status_t *status)
{
return status->flush_underflow_to_zero;
}
/*----------------------------------------------------------------------------
| Software IEC/IEEE integer-to-floating-point conversion routines.
*----------------------------------------------------------------------------*/
float32 int32_to_float32(Bit32s, struct float_status_t *status);
float64 int32_to_float64(Bit32s);
float32 int64_to_float32(Bit64s, struct float_status_t *status);
float64 int64_to_float64(Bit64s, struct float_status_t *status);
float32 uint32_to_float32(Bit32u, struct float_status_t *status);
float64 uint32_to_float64(Bit32u);
float32 uint64_to_float32(Bit64u, struct float_status_t *status);
float64 uint64_to_float64(Bit64u, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision conversion routines.
*----------------------------------------------------------------------------*/
Bit32s float32_to_int32(float32, struct float_status_t *status);
Bit32s float32_to_int32_round_to_zero(float32, struct float_status_t *status);
Bit64s float32_to_int64(float32, struct float_status_t *status);
Bit64s float32_to_int64_round_to_zero(float32, struct float_status_t *status);
Bit32u float32_to_uint32(float32, struct float_status_t *status);
Bit32u float32_to_uint32_round_to_zero(float32, struct float_status_t *status);
Bit64u float32_to_uint64(float32, struct float_status_t *status);
Bit64u float32_to_uint64_round_to_zero(float32, struct float_status_t *status);
float64 float32_to_float64(float32, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision operations.
*----------------------------------------------------------------------------*/
float32 float32_round_to_int(float32, Bit8u scale, struct float_status_t *status);
float32 float32_add(float32, float32, struct float_status_t *status);
float32 float32_sub(float32, float32, struct float_status_t *status);
float32 float32_mul(float32, float32, struct float_status_t *status);
float32 float32_div(float32, float32, struct float_status_t *status);
float32 float32_sqrt(float32, struct float_status_t *status);
float32 float32_frc(float32, struct float_status_t *status);
float32 float32_muladd(float32, float32, float32, int flags, struct float_status_t *status);
float32 float32_scalef(float32, float32, struct float_status_t *status);
int float32_compare(float32, float32, int quiet, struct float_status_t *status);
BX_CPP_INLINE float32 float32_round_to_int_one(float32 a, struct float_status_t *status)
{
return float32_round_to_int(a, 0, status);
}
BX_CPP_INLINE float32 float32_fmadd(float32 a, float32 b, float32 c, struct float_status_t *status)
{
return float32_muladd(a, b, c, 0, status);
}
BX_CPP_INLINE float32 float32_fmsub(float32 a, float32 b, float32 c, struct float_status_t *status)
{
return float32_muladd(a, b, c, float_muladd_negate_c, status);
}
BX_CPP_INLINE float32 float32_fnmadd(float32 a, float32 b, float32 c, struct float_status_t *status)
{
return float32_muladd(a, b, c, float_muladd_negate_product, status);
}
BX_CPP_INLINE float32 float32_fnmsub(float32 a, float32 b, float32 c, struct float_status_t *status)
{
return float32_muladd(a, b, c, float_muladd_negate_result, status);
}
BX_CPP_INLINE int float32_compare_two(float32 a, float32 b, struct float_status_t *status)
{
return float32_compare(a, b, 0, status);
}
BX_CPP_INLINE int float32_compare_quiet(float32 a, float32 b, struct float_status_t *status)
{
return float32_compare(a, b, 1, status);
}
float_class_t float32_class(float32);
float32 float32_min(float32 a, float32 b, struct float_status_t *status);
float32 float32_max(float32 a, float32 b, struct float_status_t *status);
float32 float32_minmax(float32 a, float32 b, int is_max, int is_abs, struct float_status_t *status);
float32 float32_getexp(float32 a, struct float_status_t *status);
float32 float32_getmant(float32 a, struct float_status_t *status, int sign_ctrl, int interv);
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision conversion routines.
*----------------------------------------------------------------------------*/
Bit32s float64_to_int32(float64, struct float_status_t *status);
Bit32s float64_to_int32_round_to_zero(float64, struct float_status_t *status);
Bit64s float64_to_int64(float64, struct float_status_t *status);
Bit64s float64_to_int64_round_to_zero(float64, struct float_status_t *status);
Bit32u float64_to_uint32(float64, struct float_status_t *status);
Bit32u float64_to_uint32_round_to_zero(float64, struct float_status_t *status);
Bit64u float64_to_uint64(float64, struct float_status_t *status);
Bit64u float64_to_uint64_round_to_zero(float64, struct float_status_t *status);
float32 float64_to_float32(float64, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Software IEC/IEEE double-precision operations.
*----------------------------------------------------------------------------*/
float64 float64_round_to_int(float64, Bit8u scale, struct float_status_t *status);
float64 float64_add(float64, float64, struct float_status_t *status);
float64 float64_sub(float64, float64, struct float_status_t *status);
float64 float64_mul(float64, float64, struct float_status_t *status);
float64 float64_div(float64, float64, struct float_status_t *status);
float64 float64_sqrt(float64, struct float_status_t *status);
float64 float64_frc(float64, struct float_status_t *status);
float64 float64_muladd(float64, float64, float64, int flags, struct float_status_t *status);
float64 float64_scalef(float64, float64, struct float_status_t *status);
int float64_compare(float64, float64, int quiet, struct float_status_t *status);
BX_CPP_INLINE float64 float64_round_to_int_one(float64 a, struct float_status_t *status)
{
return float64_round_to_int(a, 0, status);
}
BX_CPP_INLINE float64 float64_fmadd(float64 a, float64 b, float64 c, struct float_status_t *status)
{
return float64_muladd(a, b, c, 0, status);
}
BX_CPP_INLINE float64 float64_fmsub(float64 a, float64 b, float64 c, struct float_status_t *status)
{
return float64_muladd(a, b, c, float_muladd_negate_c, status);
}
BX_CPP_INLINE float64 float64_fnmadd(float64 a, float64 b, float64 c, struct float_status_t *status)
{
return float64_muladd(a, b, c, float_muladd_negate_product, status);
}
BX_CPP_INLINE float64 float64_fnmsub(float64 a, float64 b, float64 c, struct float_status_t *status)
{
return float64_muladd(a, b, c, float_muladd_negate_result, status);
}
BX_CPP_INLINE int float64_compare_two(float64 a, float64 b, struct float_status_t *status)
{
return float64_compare(a, b, 0, status);
}
BX_CPP_INLINE int float64_compare_quiet(float64 a, float64 b, struct float_status_t *status)
{
return float64_compare(a, b, 1, status);
}
float_class_t float64_class(float64);
float64 float64_min(float64 a, float64 b, struct float_status_t *status);
float64 float64_max(float64 a, float64 b, struct float_status_t *status);
float64 float64_minmax(float64 a, float64 b, int is_max, int is_abs, struct float_status_t *status);
float64 float64_getexp(float64 a, struct float_status_t *status);
float64 float64_getmant(float64 a, struct float_status_t *status, int sign_ctrl, int interv);
#ifdef FLOAT16
float32 float16_to_float32(float16, struct float_status_t *status);
float16 float32_to_float16(float32, struct float_status_t *status);
float_class_t float16_class(float16);
#endif
#ifdef FLOATX80
/*----------------------------------------------------------------------------
| Software IEC/IEEE floating-point types.
*----------------------------------------------------------------------------*/
#ifdef BX_BIG_ENDIAN
typedef struct floatx80 { // leave alignment to compiler
Bit16u exp;
Bit64u fraction;
}; floatx80
#else
typedef struct floatx80 {
Bit64u fraction;
Bit16u exp;
} floatx80;
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE integer-to-floating-point conversion routines.
*----------------------------------------------------------------------------*/
floatx80 int32_to_floatx80(Bit32s);
floatx80 int64_to_floatx80(Bit64s);
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision conversion routines.
*----------------------------------------------------------------------------*/
floatx80 float32_to_floatx80(float32, struct float_status_t *status);
floatx80 float64_to_floatx80(float64, struct float_status_t *status);
Bit32s floatx80_to_int32(floatx80, struct float_status_t *status);
Bit32s floatx80_to_int32_round_to_zero(floatx80, struct float_status_t *status);
Bit64s floatx80_to_int64(floatx80, struct float_status_t *status);
Bit64s floatx80_to_int64_round_to_zero(floatx80, struct float_status_t *status);
float32 floatx80_to_float32(floatx80, struct float_status_t *status);
float64 floatx80_to_float64(floatx80, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision operations.
*----------------------------------------------------------------------------*/
floatx80 floatx80_round_to_int(floatx80, struct float_status_t *status);
floatx80 floatx80_add(floatx80, floatx80, struct float_status_t *status);
floatx80 floatx80_sub(floatx80, floatx80, struct float_status_t *status);
floatx80 floatx80_mul(floatx80, floatx80, struct float_status_t *status);
floatx80 floatx80_div(floatx80, floatx80, struct float_status_t *status);
floatx80 floatx80_sqrt(floatx80, struct float_status_t *status);
float_class_t floatx80_class(floatx80);
#ifdef __cplusplus
}
#endif
#endif /* FLOATX80 */
#ifdef FLOAT128
#ifdef BX_BIG_ENDIAN
typedef struct float128 {
Bit64u hi, lo;
} float128;
#else
typedef struct float128 {
Bit64u lo, hi;
} float128;
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------
| Software IEC/IEEE quadruple-precision conversion routines.
*----------------------------------------------------------------------------*/
float128 floatx80_to_float128(floatx80 a, struct float_status_t *status);
floatx80 float128_to_floatx80(float128 a, struct float_status_t *status);
float128 int64_to_float128(Bit64s a);
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision operations.
*----------------------------------------------------------------------------*/
floatx80 floatx80_128_mul(floatx80 a, float128 b, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Software IEC/IEEE quadruple-precision operations.
*----------------------------------------------------------------------------*/
float128 float128_add(float128 a, float128 b, struct float_status_t *status);
float128 float128_sub(float128 a, float128 b, struct float_status_t *status);
float128 float128_mul(float128 a, float128 b, struct float_status_t *status);
float128 float128_div(float128 a, float128 b, struct float_status_t *status);
#ifdef __cplusplus
}
#endif
#endif /* FLOAT128 */
#endif

View File

@@ -1,129 +0,0 @@
/*============================================================================
This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
Package, Release 2b.
Written by John R. Hauser. This work was made possible in part by the
International Computer Science Institute, located at Suite 600, 1947 Center
Street, Berkeley, California 94704. Funding was partially provided by the
National Science Foundation under grant MIP-9311980. The original version
of this code was written as part of a project to build a fixed-point vector
processor in collaboration with the University of California at Berkeley,
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
arithmetic/SoftFloat.html'.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.
=============================================================================*/
/*============================================================================
* Adapted for Bochs (x86 achitecture simulator) by
* Stanislav Shwartsman [sshwarts at sourceforge net]
* ==========================================================================*/
#include "softfloat.h"
#ifdef FLOAT16
#include "softfloat-round-pack.h"
#include "softfloat-specialize.h"
#include "softfloat-macros.h"
/*----------------------------------------------------------------------------
| Determine half-precision floating-point number class
*----------------------------------------------------------------------------*/
float_class_t float16_class(float16 a)
{
Bit16s aExp = extractFloat16Exp(a);
Bit16u aSig = extractFloat16Frac(a);
int aSign = extractFloat16Sign(a);
if(aExp == 0x1F) {
if (aSig == 0)
return (aSign) ? float_negative_inf : float_positive_inf;
return (aSig & 0x200) ? float_QNaN : float_SNaN;
}
if(aExp == 0) {
if (aSig == 0) return float_zero;
return float_denormal;
}
return float_normalized;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the half-precision floating-point value
| `a' to the single-precision floating-point format. The conversion is
| performed according to the IEC/IEEE Standard for Binary Floating-Point
| Arithmetic.
*----------------------------------------------------------------------------*/
float32 float16_to_float32(float16 a, struct float_status_t *status)
{
Bit16u aSig = extractFloat16Frac(a);
Bit16s aExp = extractFloat16Exp(a);
int aSign = extractFloat16Sign(a);
if (aExp == 0x1F) {
if (aSig) return commonNaNToFloat32(float16ToCommonNaN(a, status));
return packFloat32(aSign, 0xFF, 0);
}
if (aExp == 0) {
// ignore denormals_are_zeros flag
if (aSig == 0) return packFloat32(aSign, 0, 0);
float_raise(status, float_flag_denormal);
normalizeFloat16Subnormal(aSig, &aExp, &aSig);
--aExp;
}
return packFloat32(aSign, aExp + 0x70, ((Bit32u) aSig)<<13);
}
/*----------------------------------------------------------------------------
| Returns the result of converting the single-precision floating-point value
| `a' to the half-precision floating-point format. The conversion is
| performed according to the IEC/IEEE Standard for Binary Floating-Point
| Arithmetic.
*----------------------------------------------------------------------------*/
float16 float32_to_float16(float32 a, struct float_status_t *status)
{
Bit32u aSig = extractFloat32Frac(a);
Bit16s aExp = extractFloat32Exp(a);
int aSign = extractFloat32Sign(a);
if (aExp == 0xFF) {
if (aSig) return commonNaNToFloat16(float32ToCommonNaN(a, status));
return packFloat16(aSign, 0x1F, 0);
}
if (aExp == 0) {
if (get_denormals_are_zeros(status)) aSig = 0;
if (aSig == 0) return packFloat16(aSign, 0, 0);
float_raise(status, float_flag_denormal);
}
aSig = shift32RightJamming(aSig, 9);
Bit16u zSig = (Bit16u) aSig;
if (aExp || zSig) {
zSig |= 0x4000;
aExp -= 0x71;
}
return roundAndPackFloat16(aSign, aExp, zSig, status);
}
#endif

View File

@@ -1,384 +0,0 @@
/*============================================================================
This source file is an extension to the SoftFloat IEC/IEEE Floating-point
Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator)
floating point emulation.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.
=============================================================================*/
/*============================================================================
* Written for Bochs (x86 achitecture simulator) by
* Stanislav Shwartsman [sshwarts at sourceforge net]
* ==========================================================================*/
#include <stdio.h>
#include <stdint.h>
#include <86box/86box.h>
#include "../cpu.h"
#include "softfloatx80.h"
#include "softfloat-round-pack.h"
#include "softfloat-macros.h"
const floatx80 Const_QNaN = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
const floatx80 Const_Z = packFloatx80(0, 0x0000, 0);
const floatx80 Const_1 = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000));
const floatx80 Const_L2T = packFloatx80(0, 0x4000, BX_CONST64(0xd49a784bcd1b8afe));
const floatx80 Const_L2E = packFloatx80(0, 0x3fff, BX_CONST64(0xb8aa3b295c17f0bc));
const floatx80 Const_PI = packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235));
const floatx80 Const_LG2 = packFloatx80(0, 0x3ffd, BX_CONST64(0x9a209a84fbcff799));
const floatx80 Const_LN2 = packFloatx80(0, 0x3ffe, BX_CONST64(0xb17217f7d1cf79ac));
const floatx80 Const_INF = packFloatx80(0, 0x7fff, BX_CONST64(0x8000000000000000));
/*----------------------------------------------------------------------------
| Commonly used single-precision floating point constants
*----------------------------------------------------------------------------*/
const float32 float32_negative_inf = 0xff800000;
const float32 float32_positive_inf = 0x7f800000;
const float32 float32_negative_zero = 0x80000000;
const float32 float32_positive_zero = 0x00000000;
const float32 float32_negative_one = 0xbf800000;
const float32 float32_positive_one = 0x3f800000;
const float32 float32_max_float = 0x7f7fffff;
const float32 float32_min_float = 0xff7fffff;
/*----------------------------------------------------------------------------
| The pattern for a default generated single-precision NaN.
*----------------------------------------------------------------------------*/
const float32 float32_default_nan = 0xffc00000;
/*----------------------------------------------------------------------------
| Commonly used single-precision floating point constants
*----------------------------------------------------------------------------*/
const float64 float64_negative_inf = BX_CONST64(0xfff0000000000000);
const float64 float64_positive_inf = BX_CONST64(0x7ff0000000000000);
const float64 float64_negative_zero = BX_CONST64(0x8000000000000000);
const float64 float64_positive_zero = BX_CONST64(0x0000000000000000);
const float64 float64_negative_one = BX_CONST64(0xbff0000000000000);
const float64 float64_positive_one = BX_CONST64(0x3ff0000000000000);
const float64 float64_max_float = BX_CONST64(0x7fefffffffffffff);
const float64 float64_min_float = BX_CONST64(0xffefffffffffffff);
/*----------------------------------------------------------------------------
| The pattern for a default generated double-precision NaN.
*----------------------------------------------------------------------------*/
const float64 float64_default_nan = BX_CONST64(0xFFF8000000000000);
/*----------------------------------------------------------------------------
| Returns the result of converting the extended double-precision floating-
| point value `a' to the 16-bit two's complement integer format. The
| conversion is performed according to the IEC/IEEE Standard for Binary
| Floating-Point Arithmetic - which means in particular that the conversion
| is rounded according to the current rounding mode. If `a' is a NaN or the
| conversion overflows, the integer indefinite value is returned.
*----------------------------------------------------------------------------*/
Bit16s floatx80_to_int16(floatx80 a, struct float_status_t *status)
{
if (floatx80_is_unsupported(a)) {
float_raise(status, float_flag_invalid);
return int16_indefinite;
}
Bit32s v32 = floatx80_to_int32(a, status);
if ((v32 > 32767) || (v32 < -32768)) {
status->float_exception_flags = float_flag_invalid; // throw away other flags
return int16_indefinite;
}
return (Bit16s) v32;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the extended double-precision floating-
| point value `a' to the 16-bit two's complement integer format. The
| conversion is performed according to the IEC/IEEE Standard for Binary
| Floating-Point Arithmetic, except that the conversion is always rounded
| toward zero. If `a' is a NaN or the conversion overflows, the integer
| indefinite value is returned.
*----------------------------------------------------------------------------*/
Bit16s floatx80_to_int16_round_to_zero(floatx80 a, struct float_status_t *status)
{
if (floatx80_is_unsupported(a)) {
float_raise(status, float_flag_invalid);
return int16_indefinite;
}
Bit32s v32 = floatx80_to_int32_round_to_zero(a, status);
if ((v32 > 32767) || (v32 < -32768)) {
status->float_exception_flags = float_flag_invalid; // throw away other flags
return int16_indefinite;
}
return (Bit16s) v32;
}
/*----------------------------------------------------------------------------
| Separate the source extended double-precision floating point value `a'
| into its exponent and significand, store the significant back to the
| 'a' and return the exponent. The operation performed is a superset of
| the IEC/IEEE recommended logb(x) function.
*----------------------------------------------------------------------------*/
floatx80 floatx80_extract(floatx80 *a, struct float_status_t *status)
{
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN.
*----------------------------------------------------------------------------*/
const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
Bit64u aSig = extractFloatx80Frac(*a);
Bit32s aExp = extractFloatx80Exp(*a);
int aSign = extractFloatx80Sign(*a);
if (floatx80_is_unsupported(*a))
{
float_raise(status, float_flag_invalid);
*a = floatx80_default_nan;
return *a;
}
if (aExp == 0x7FFF) {
if ((Bit64u) (aSig<<1))
{
*a = propagateFloatx80NaNOne(*a, status);
return *a;
}
return packFloatx80(0, 0x7FFF, BX_CONST64(0x8000000000000000));
}
if (aExp == 0)
{
if (aSig == 0) {
float_raise(status, float_flag_divbyzero);
*a = packFloatx80(aSign, 0, 0);
return packFloatx80(1, 0x7FFF, BX_CONST64(0x8000000000000000));
}
float_raise(status, float_flag_denormal);
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
}
a->exp = (aSign << 15) + 0x3FFF;
a->fraction = aSig;
return int32_to_floatx80(aExp - 0x3FFF);
}
/*----------------------------------------------------------------------------
| Scales extended double-precision floating-point value in operand `a' by
| value `b'. The function truncates the value in the second operand 'b' to
| an integral value and adds that value to the exponent of the operand 'a'.
| The operation performed according to the IEC/IEEE Standard for Binary
| Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
floatx80 floatx80_scale(floatx80 a, floatx80 b, struct float_status_t *status)
{
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN.
*----------------------------------------------------------------------------*/
const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
Bit32s aExp, bExp;
Bit64u aSig, bSig;
// handle unsupported extended double-precision floating encodings
if (floatx80_is_unsupported(a) || floatx80_is_unsupported(b))
{
float_raise(status, float_flag_invalid);
return floatx80_default_nan;
}
aSig = extractFloatx80Frac(a);
aExp = extractFloatx80Exp(a);
int aSign = extractFloatx80Sign(a);
bSig = extractFloatx80Frac(b);
bExp = extractFloatx80Exp(b);
int bSign = extractFloatx80Sign(b);
if (aExp == 0x7FFF) {
if ((Bit64u) (aSig<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1)))
{
return propagateFloatx80NaN(a, b, status);
}
if ((bExp == 0x7FFF) && bSign) {
float_raise(status, float_flag_invalid);
return floatx80_default_nan;
}
if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
return a;
}
if (bExp == 0x7FFF) {
if ((Bit64u) (bSig<<1)) return propagateFloatx80NaN(a, b, status);
if ((aExp | aSig) == 0) {
if (! bSign) {
float_raise(status, float_flag_invalid);
return floatx80_default_nan;
}
return a;
}
if (aSig && (aExp == 0)) float_raise(status, float_flag_denormal);
if (bSign) return packFloatx80(aSign, 0, 0);
return packFloatx80(aSign, 0x7FFF, BX_CONST64(0x8000000000000000));
}
if (aExp == 0) {
if (bSig && (bExp == 0)) float_raise(status, float_flag_denormal);
if (aSig == 0) return a;
float_raise(status, float_flag_denormal);
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
if (bExp < 0x3FFF)
return normalizeRoundAndPackFloatx80(80, aSign, aExp, aSig, 0, status);
}
if (bExp == 0) {
if (bSig == 0) return a;
float_raise(status, float_flag_denormal);
normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
}
if (bExp > 0x400E) {
/* generate appropriate overflow/underflow */
return roundAndPackFloatx80(80, aSign,
bSign ? -0x3FFF : 0x7FFF, aSig, 0, status);
}
if (bExp < 0x3FFF) return a;
int shiftCount = 0x403E - bExp;
bSig >>= shiftCount;
Bit32s scale = (Bit32s) bSig;
if (bSign) scale = -scale; /* -32768..32767 */
return
roundAndPackFloatx80(80, aSign, aExp+scale, aSig, 0, status);
}
/*----------------------------------------------------------------------------
| Determine extended-precision floating-point number class.
*----------------------------------------------------------------------------*/
float_class_t floatx80_class(floatx80 a)
{
Bit32s aExp = extractFloatx80Exp(a);
Bit64u aSig = extractFloatx80Frac(a);
if(aExp == 0) {
if (aSig == 0)
return float_zero;
/* denormal or pseudo-denormal */
return float_denormal;
}
/* valid numbers have the MS bit set */
if (!(aSig & BX_CONST64(0x8000000000000000)))
return float_SNaN; /* report unsupported as SNaNs */
if(aExp == 0x7fff) {
int aSign = extractFloatx80Sign(a);
if (((Bit64u) (aSig<< 1)) == 0)
return (aSign) ? float_negative_inf : float_positive_inf;
return (aSig & BX_CONST64(0x4000000000000000)) ? float_QNaN : float_SNaN;
}
return float_normalized;
}
/*----------------------------------------------------------------------------
| Compare between two extended precision floating point numbers. Returns
| 'float_relation_equal' if the operands are equal, 'float_relation_less' if
| the value 'a' is less than the corresponding value `b',
| 'float_relation_greater' if the value 'a' is greater than the corresponding
| value `b', or 'float_relation_unordered' otherwise.
*----------------------------------------------------------------------------*/
int floatx80_compare(floatx80 a, floatx80 b, int quiet, struct float_status_t *status)
{
float_class_t aClass = floatx80_class(a);
float_class_t bClass = floatx80_class(b);
if (fpu_type < FPU_287XL) {
if ((aClass == float_positive_inf) && (bClass == float_negative_inf))
{
return float_relation_equal;
}
if ((aClass == float_negative_inf) && (bClass == float_positive_inf))
{
return float_relation_equal;
}
}
if (aClass == float_SNaN || bClass == float_SNaN)
{
/* unsupported reported as SNaN */
float_raise(status, float_flag_invalid);
return float_relation_unordered;
}
if (aClass == float_QNaN || bClass == float_QNaN) {
if (! quiet) float_raise(status, float_flag_invalid);
return float_relation_unordered;
}
if (aClass == float_denormal || bClass == float_denormal) {
float_raise(status, float_flag_denormal);
}
int aSign = extractFloatx80Sign(a);
int bSign = extractFloatx80Sign(b);
if (aClass == float_zero) {
if (bClass == float_zero) return float_relation_equal;
return bSign ? float_relation_greater : float_relation_less;
}
if (bClass == float_zero || aSign != bSign) {
return aSign ? float_relation_less : float_relation_greater;
}
Bit64u aSig = extractFloatx80Frac(a);
Bit32s aExp = extractFloatx80Exp(a);
Bit64u bSig = extractFloatx80Frac(b);
Bit32s bExp = extractFloatx80Exp(b);
if (aClass == float_denormal)
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
if (bClass == float_denormal)
normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
if (aExp == bExp && aSig == bSig)
return float_relation_equal;
int less_than =
aSign ? ((bExp < aExp) || ((bExp == aExp) && (bSig < aSig)))
: ((aExp < bExp) || ((aExp == bExp) && (aSig < bSig)));
if (less_than) return float_relation_less;
return float_relation_greater;
}
int floatx80_compare_two(floatx80 a, floatx80 b, struct float_status_t *status)
{
return floatx80_compare(a, b, 0, status);
}
int floatx80_compare_quiet(floatx80 a, floatx80 b, struct float_status_t *status)
{
return floatx80_compare(a, b, 1, status);
}

View File

@@ -1,121 +0,0 @@
/*============================================================================
This source file is an extension to the SoftFloat IEC/IEEE Floating-point
Arithmetic Package, Release 2b, written for Bochs (x86 achitecture simulator)
floating point emulation.
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
Derivative works are acceptable, even for commercial purposes, so long as
(1) the source code for the derivative work includes prominent notice that
the work is derivative, and (2) the source code includes prominent notice with
these four paragraphs for those parts of this code that are retained.
=============================================================================*/
/*============================================================================
* Written for Bochs (x86 achitecture simulator) by
* Stanislav Shwartsman [sshwarts at sourceforge net]
* ==========================================================================*/
#ifndef _SOFTFLOATX80_EXTENSIONS_H_
#define _SOFTFLOATX80_EXTENSIONS_H_
#include "softfloat.h"
#include "softfloat-specialize.h"
/*----------------------------------------------------------------------------
| Software IEC/IEEE integer-to-floating-point conversion routines.
*----------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
Bit16s floatx80_to_int16(floatx80, struct float_status_t *status);
Bit16s floatx80_to_int16_round_to_zero(floatx80, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision operations.
*----------------------------------------------------------------------------*/
floatx80 floatx80_extract(floatx80 *a, struct float_status_t *status);
floatx80 floatx80_scale(floatx80 a, floatx80 b, struct float_status_t *status);
int floatx80_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status);
int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 *r, Bit64u *q, struct float_status_t *status);
floatx80 f2xm1(floatx80 a, struct float_status_t *status);
floatx80 fyl2x(floatx80 a, floatx80 b, struct float_status_t *status);
floatx80 fyl2xp1(floatx80 a, floatx80 b, struct float_status_t *status);
floatx80 fpatan(floatx80 a, floatx80 b, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision trigonometric functions.
*----------------------------------------------------------------------------*/
int fsincos(floatx80 a, floatx80 *sin_a, floatx80 *cos_a, struct float_status_t *status);
int fsin(floatx80 *a, struct float_status_t *status);
int fcos(floatx80 *a, struct float_status_t *status);
int ftan(floatx80 *a, struct float_status_t *status);
/*----------------------------------------------------------------------------
| Software IEC/IEEE extended double-precision compare.
*----------------------------------------------------------------------------*/
int floatx80_compare(floatx80, floatx80, int quiet, struct float_status_t *status);
int floatx80_compare_two(floatx80 a, floatx80 b, struct float_status_t *status);
int floatx80_compare_quiet(floatx80 a, floatx80 b, struct float_status_t *status);
#ifdef __cplusplus
}
#endif
/*-----------------------------------------------------------------------------
| Calculates the absolute value of the extended double-precision floating-point
| value `a'. The operation is performed according to the IEC/IEEE Standard
| for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
#ifdef __cplusplus
BX_CPP_INLINE floatx80& floatx80_abs(floatx80 &reg)
#else
BX_CPP_INLINE floatx80 floatx80_abs(floatx80 reg)
#endif
{
reg.exp &= 0x7FFF;
return reg;
}
/*-----------------------------------------------------------------------------
| Changes the sign of the extended double-precision floating-point value 'a'.
| The operation is performed according to the IEC/IEEE Standard for Binary
| Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
#ifdef __cplusplus
BX_CPP_INLINE floatx80& floatx80_chs(floatx80 &reg)
#else
BX_CPP_INLINE floatx80 floatx80_chs(floatx80 reg)
#endif
{
reg.exp ^= 0x8000;
return reg;
}
/*-----------------------------------------------------------------------------
| Commonly used extended double-precision floating-point constants.
*----------------------------------------------------------------------------*/
extern const floatx80 Const_Z;
extern const floatx80 Const_1;
extern const floatx80 Const_L2T;
extern const floatx80 Const_L2E;
extern const floatx80 Const_PI;
extern const floatx80 Const_LG2;
extern const floatx80 Const_LN2;
extern const floatx80 Const_INF;
#endif

View File

@@ -0,0 +1,56 @@
#
# 86Box A hypervisor and IBM PC system emulator that specializes in
# running old operating systems and software designed for IBM
# PC systems and compatibles from 1981 through fairly recent
# system designs based on the PCI bus.
#
# This file is part of the 86Box distribution.
#
# CMake build script.
#
# Authors: David Hrdlička, <hrdlickadavid@outlook.com>
#
# Copyright 2020-2021 David Hrdlička.
#
add_library(softfloat3e OBJECT extF80_addsub.cc extF80_class.cc extF80_compare.cc
extF80_div.cc extF80_extract.cc extF80_mul.cc extF80_rem.cc extF80_roundToInt.cc
extF80_scale.cc extF80_sqrt.cc extF80_to_f16.cc extF80_to_f32.cc extF80_to_f64.cc
extF80_to_f128.cc extF80_to_i32.cc extF80_to_i32_r_minMag.cc extF80_to_i64.cc
extF80_to_i64_r_minMag.cc extF80_to_ui32.cc extF80_to_ui32_r_minMag.cc extF80_to_ui64.cc
extF80_to_ui64_r_minMag.cc f16_addsub.c f16_class.c f16_compare.c f16_div.c f16_getExp.c
f16_getMant.c f16_minmax.c f16_mul.c f16_mulAdd.c f16_range.c f16_roundToInt.c
f16_sqrt.c f16_to_extF80.cc f16_to_f32.c f16_to_f64.c f16_to_i32.c f16_to_i32_r_minMag.c
f16_to_i64.c f16_to_i64_r_minMag.c f16_to_ui32.c f16_to_ui32_r_minMag.c f16_to_ui64.c
f16_to_ui64_r_minMag.c f32_addsub.c f32_class.c f32_compare.c f32_div.c f32_frc.c
f32_getExp.c f32_getMant.c f32_minmax.c f32_mul.c f32_mulAdd.c f32_range.c
f32_roundToInt.c f32_scalef.c f32_sqrt.c f32_to_extF80.cc f32_to_f16.c f32_to_f64.c
f32_to_f128.cc f32_to_i32.c f32_to_i32_r_minMag.c f32_to_i64.c f32_to_i64_r_minMag.c
f32_to_ui32.c f32_to_ui32_r_minMag.c f32_to_ui64.c f32_to_ui64_r_minMag.c f64_addsub.c
f64_class.c f64_compare.c f64_div.c f64_frc.c f64_getExp.c f64_getMant.c f64_minmax.c
f64_mul.c f64_mulAdd.c f64_range.c f64_roundToInt.c f64_scalef.c f64_sqrt.c f64_to_extF80.cc
f64_to_f16.c f64_to_f32.c f64_to_f128.cc f64_to_i32.c f64_to_i32_r_minMag.c f64_to_i64.c
f64_to_i64_r_minMag.c f64_to_ui32.c f64_to_ui32_r_minMag.c f64_to_ui64.c f64_to_ui64_r_minMag.c
f128_addsub.cc f128_div.cc f128_mul.cc f128_mulAdd.cc f128_roundToInt.cc f128_to_extF80.cc
f128_to_f32.cc f128_to_f64.cc f128_to_i32.cc f128_to_i32_r_minMag.cc f128_to_i64.cc
f128_to_i64_r_minMag.cc f128_to_ui32.cc f128_to_ui32_r_minMag.cc f128_to_ui64.cc
f128_to_ui64_r_minMag.cc i32_to_extF80.cc i32_to_f16.c i32_to_f32.c i32_to_f64.c
i32_to_f128.cc i64_to_extF80.cc i64_to_f16.c i64_to_f32.c i64_to_f64.c i64_to_f128.cc
isNaN.cc isSignalingNaN.cc s_add128.cc s_add256M.c s_addMagsExtF80.cc s_addMagsF16.c
s_addMagsF32.c s_addMagsF64.c s_addMagsF128.cc s_approxRecip_1Ks.c s_approxRecipSqrt_1Ks.c
s_approxRecipSqrt32_1.c s_commonNaNToExtF80UI.cc s_commonNaNToF16UI.c s_commonNaNToF32UI.c
s_commonNaNToF64UI.c s_commonNaNToF128UI.cc s_countLeadingZeros8.c s_countLeadingZeros16.c
s_countLeadingZeros32.c s_countLeadingZeros64.c s_eq128.c s_le128.c s_lt128.c
s_mul64ByShifted32To128.cc s_mul64To128.cc s_mul128By32.cc s_mul128To256M.cc
s_normRoundPackToExtF80.cc s_normRoundPackToF16.c s_normRoundPackToF32.c s_normRoundPackToF64.c
s_normRoundPackToF128.cc s_normSubnormalExtF80Sig.cc s_normSubnormalF16Sig.c
s_normSubnormalF32Sig.c s_normSubnormalF64Sig.c s_normSubnormalF128Sig.cc s_packToExtF80.cc
s_propagateNaNExtF80UI.cc s_propagateNaNF16UI.c s_propagateNaNF32UI.c s_propagateNaNF64UI.c
s_propagateNaNF128UI.cc s_roundPackToExtF80.cc s_roundPackToF16.c s_roundPackToF32.c
s_roundPackToF64.c s_roundPackToF128.cc s_roundToI32.c s_roundToI64.c s_roundToUI32.c
s_roundToUI64.c s_shiftRightJam32.c s_shiftRightJam64.c s_shiftRightJam64Extra.c
s_shiftRightJam256M.c s_shortShiftLeft128.cc s_shortShiftRight128.cc s_shortShiftRightJam64.c
s_shortShiftRightJam64Extra.c s_sub128.cc s_sub256M.c s_subMagsExtF80.cc s_subMagsF16.c
s_subMagsF32.c s_subMagsF64.c s_subMagsF128.cc ui32_to_extF80.cc ui32_to_f16.c ui32_to_f32.c
ui32_to_f64.c ui32_to_f128.cc ui64_to_extF80.cc ui64_to_f16.c ui64_to_f32.c ui64_to_f64.c
ui64_to_f128.cc f2xm1.cc fpatan.cc fprem.cc fsincos.cc fyl2x.cc poly.cc consts.cc)

View File

@@ -0,0 +1,37 @@
License for Berkeley SoftFloat Release 3e
John R. Hauser
2018 January 20
The following applies to the whole of SoftFloat Release 3e as well as to
each source file individually.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions, and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,49 @@
<HTML>
<HEAD>
<TITLE>Berkeley SoftFloat Package Overview</TITLE>
</HEAD>
<BODY>
<H1>Package Overview for Berkeley SoftFloat Release 3e</H1>
<P>
John R. Hauser<BR>
2018 January 20<BR>
</P>
<P>
Berkeley SoftFloat is a software implementation of binary floating-point that
conforms to the IEEE Standard for Floating-Point Arithmetic.
SoftFloat is distributed in the form of C source code.
Building the SoftFloat sources generates a library file (typically
<CODE>softfloat.a</CODE> or <CODE>libsoftfloat.a</CODE>) containing the
floating-point subroutines.
</P>
<P>
The SoftFloat package is documented in the following files in the
<CODE>doc</CODE> subdirectory:
<BLOCKQUOTE>
<TABLE>
<TR>
<TD><A HREF="doc/SoftFloat.html"><NOBR><CODE>SoftFloat.html</CODE></NOBR></A></TD>
<TD>Documentation for using the SoftFloat functions.</TD>
</TR>
<TR>
<TD><A HREF="doc/SoftFloat-source.html"><NOBR><CODE>SoftFloat-source.html</CODE></NOBR></A></TD>
<TD>Documentation for building SoftFloat.</TD>
</TR>
<TR>
<TD><A HREF="doc/SoftFloat-history.html"><NOBR><CODE>SoftFloat-history.html</CODE></A><CODE>&nbsp;&nbsp;&nbsp;</CODE></NOBR></TD>
<TD>History of the major changes to SoftFloat.</TD>
</TR>
</TABLE>
</BLOCKQUOTE>
Other files in the package comprise the source code for SoftFloat.
</P>
</BODY>

View File

@@ -0,0 +1,21 @@
Package Overview for Berkeley SoftFloat Release 3e
John R. Hauser
2018 January 20
Berkeley SoftFloat is a software implementation of binary floating-point
that conforms to the IEEE Standard for Floating-Point Arithmetic. SoftFloat
is distributed in the form of C source code. Building the SoftFloat sources
generates a library file (typically "softfloat.a" or "libsoftfloat.a")
containing the floating-point subroutines.
The SoftFloat package is documented in the following files in the "doc"
subdirectory:
SoftFloat.html Documentation for using the SoftFloat functions.
SoftFloat-source.html Documentation for building SoftFloat.
SoftFloat-history.html History of the major changes to SoftFloat.
Other files in the package comprise the source code for SoftFloat.

View File

@@ -0,0 +1,14 @@
#ifndef EMU_SF_CONFIG_H
#define EMU_SF_CONFIG_H
/*----------------------------------------------------------------------------
| The `LIT64' macro takes as its argument a textual integer literal and
| if necessary ``marks'' the literal as having a 64-bit integer type.
| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be
| appended with the letters `LL' standing for `long long', which is `gcc's
| name for the 64-bit integer type. Some compilers may allow `LIT64' to be
| defined as the identity macro: `#define LIT64( a ) a'.
*----------------------------------------------------------------------------*/
#define BX_CONST64(a) a##LL
#endif /*EMU_SF_CONFIG_H*/

View File

@@ -0,0 +1,51 @@
/*============================================================================
This C header file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdio.h>
#include <stdint.h>
#include <86box/86box.h>
#include "../cpu.h"
#include "softfloat-specialize.h"
const floatx80 Const_QNaN = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
const floatx80 Const_Z = packFloatx80(0, 0x0000, 0);
const floatx80 Const_1 = packFloatx80(0, 0x3fff, BX_CONST64(0x8000000000000000));
const floatx80 Const_L2T = packFloatx80(0, 0x4000, BX_CONST64(0xd49a784bcd1b8afe));
const floatx80 Const_L2E = packFloatx80(0, 0x3fff, BX_CONST64(0xb8aa3b295c17f0bc));
const floatx80 Const_PI = packFloatx80(0, 0x4000, BX_CONST64(0xc90fdaa22168c235));
const floatx80 Const_LG2 = packFloatx80(0, 0x3ffd, BX_CONST64(0x9a209a84fbcff799));
const floatx80 Const_LN2 = packFloatx80(0, 0x3ffe, BX_CONST64(0xb17217f7d1cf79ac));
const floatx80 Const_INF = packFloatx80(0, 0x7fff, BX_CONST64(0x8000000000000000));

View File

@@ -0,0 +1,258 @@
<HTML>
<HEAD>
<TITLE>Berkeley SoftFloat History</TITLE>
</HEAD>
<BODY>
<H1>History of Berkeley SoftFloat, to Release 3e</H1>
<P>
John R. Hauser<BR>
2018 January 20<BR>
</P>
<H3>Release 3e (2018 January)</H3>
<UL>
<LI>
Changed the default numeric code for optional rounding mode <CODE>odd</CODE>
(round to odd, also known as <EM>jamming</EM>) from 5 to 6.
<LI>
Modified the behavior of rounding mode <CODE>odd</CODE> when rounding to an
integer value (either conversion to an integer format or a
&lsquo;<CODE>roundToInt</CODE>&rsquo; function).
Previously, for those cases only, rounding mode <CODE>odd</CODE> acted the same
as rounding to minimum magnitude.
Now all operations are rounded consistently.
<LI>
Fixed some errors in the specialization code modeling Intel x86 floating-point,
specifically the integers returned on invalid operations and the propagation of
NaN payloads in a few rare cases.
<LI>
Added specialization code modeling ARM floating-point, conforming to VFPv2 or
later.
<LI>
Added an example target for ARM processors.
<LI>
Fixed a minor bug whereby function <CODE>f16_to_ui64</CODE> might return a
different integer than expected in the case that the floating-point operand is
negative.
<LI>
Added example target-specific optimization for GCC, employing GCC instrinsics
and support for <NOBR>128-bit</NOBR> integer arithmetic.
<LI>
Made other minor improvements.
</UL>
<H3>Release 3d (2017 August)</H3>
<UL>
<LI>
Fixed bugs in the square root functions for <NOBR>64-bit</NOBR>
double-precision, <NOBR>80-bit</NOBR> double-extended-precision, and
<NOBR>128-bit</NOBR> quadruple-precision.
For <NOBR>64-bit</NOBR> double-precision (<CODE>f64_sqrt</CODE>), the result
could sometimes be off by <NOBR>1 unit</NOBR> in the last place
(<NOBR>1 ulp</NOBR>) from what it should be.
For the larger formats, the square root could be wrong in a large portion of
the less-significant bits.
(A bug in <CODE>f128_sqrt</CODE> was first reported by Alexei Sibidanov.)
</UL>
<H3>Release 3c (2017 February)</H3>
<UL>
<LI>
Added optional rounding mode <CODE>odd</CODE> (round to odd, also known as
<EM>jamming</EM>).
<LI>
Corrected the documentation concerning non-canonical representations in
<NOBR>80-bit</NOBR> double-extended-precision.
</UL>
<H3>Release 3b (2016 July)</H3>
<UL>
<LI>
Implemented the common <NOBR>16-bit</NOBR> &ldquo;half-precision&rdquo;
floating-point format (<CODE>float16_t</CODE>).
<LI>
Made the integer values returned on invalid conversions to integer formats
be determined by the port-specific specialization instead of being the same for
all ports.
<LI>
Added preprocessor macro <CODE>THREAD_LOCAL</CODE> to allow the floating-point
state (modes and exception flags) to be made per-thread.
<LI>
Modified the provided Makefiles to allow some options to be overridden from the
<CODE>make</CODE> command.
<LI>
Made other minor improvements.
</UL>
<H3>Release 3a (2015 October)</H3>
<UL>
<LI>
Replaced the license text supplied by the University of California, Berkeley.
</UL>
<H3>Release 3 (2015 February)</H3>
<UL>
<LI>
Complete rewrite, funded by the University of California, Berkeley, and
consequently having a different use license than earlier releases.
Major changes included renaming most types and functions, upgrading some
algorithms, restructuring the source files, and making SoftFloat into a true
library.
<LI>
Added functions to convert between floating-point and unsigned integers, both
<NOBR>32-bit</NOBR> and <NOBR>64-bit</NOBR> (<CODE>uint32_t</CODE> and
<CODE>uint64_t</CODE>).
<LI>
Added functions for fused multiply-add, for all supported floating-point
formats except <NOBR>80-bit</NOBR> double-extended-precision.
<LI>
Added support for a fifth rounding mode, <CODE>near_maxMag</CODE> (round to
nearest, with ties to maximum magnitude, away from zero).
<LI>
Dropped the <CODE>timesoftfloat</CODE> program (now part of the Berkeley
TestFloat package).
</UL>
<H3>Release 2c (2015 January)</H3>
<UL>
<LI>
Fixed mistakes affecting some <NOBR>64-bit</NOBR> processors.
<LI>
Further improved the documentation and the wording for the legal restrictions
on using SoftFloat releases <NOBR>through 2c</NOBR> (not applicable to
<NOBR>Release 3</NOBR> or later).
</UL>
<H3>Release 2b (2002 May)</H3>
<UL>
<LI>
Made minor updates to the documentation, including improved wording for the
legal restrictions on using SoftFloat.
</UL>
<H3>Release 2a (1998 December)</H3>
<UL>
<LI>
Added functions to convert between <NOBR>64-bit</NOBR> integers
(<CODE>int64</CODE>) and all supported floating-point formats.
<LI>
Fixed a bug in all <NOBR>64-bit</NOBR>-version square root functions except
<CODE>float32_sqrt</CODE> that caused the result sometimes to be off by
<NOBR>1 unit</NOBR> in the last place (<NOBR>1 ulp</NOBR>) from what it should
be.
(Bug discovered by Paul Donahue.)
<LI>
Improved the Makefiles.
</UL>
<H3>Release 2 (1997 June)</H3>
<UL>
<LI>
Created the <NOBR>64-bit</NOBR> (<CODE>bits64</CODE>) version, adding the
<CODE>floatx80</CODE> and <CODE>float128</CODE> formats.
<LI>
Changed the source directory structure, splitting the sources into a
<CODE>bits32</CODE> and a <CODE>bits64</CODE> version.
Renamed <CODE>environment.h</CODE> to <CODE>milieu.h</CODE> to avoid confusion
with environment variables.
<LI>
Fixed a small error that caused <CODE>float64_round_to_int</CODE> often to
round the wrong way in nearest/even mode when the operand was between
2<SUP>20</SUP> and 2<SUP>21</SUP> and halfway between two integers.
</UL>
<H3>Release 1a (1996 July)</H3>
<UL>
<LI>
Corrected a mistake that caused borderline underflow cases not to raise the
underflow flag when they should have.
(Problem reported by Doug Priest.)
<LI>
Added the <CODE>float_detect_tininess</CODE> variable to control whether
tininess is detected before or after rounding.
</UL>
<H3>Release 1 (1996 July)</H3>
<UL>
<LI>
Original release, based on work done for the International Computer Science
Institute (ICSI) in Berkeley, California.
</UL>
</BODY>

View File

@@ -0,0 +1,686 @@
<HTML>
<HEAD>
<TITLE>Berkeley SoftFloat Source Documentation</TITLE>
</HEAD>
<BODY>
<H1>Berkeley SoftFloat Release 3e: Source Documentation</H1>
<P>
John R. Hauser<BR>
2018 January 20<BR>
</P>
<H2>Contents</H2>
<BLOCKQUOTE>
<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0>
<COL WIDTH=25>
<COL WIDTH=*>
<TR><TD COLSPAN=2>1. Introduction</TD></TR>
<TR><TD COLSPAN=2>2. Limitations</TD></TR>
<TR><TD COLSPAN=2>3. Acknowledgments and License</TD></TR>
<TR><TD COLSPAN=2>4. SoftFloat Package Directory Structure</TD></TR>
<TR><TD COLSPAN=2>5. Issues for Porting SoftFloat to a New Target</TD></TR>
<TR>
<TD></TD>
<TD>5.1. Standard Headers <CODE>&lt;stdbool.h&gt;</CODE> and
<CODE>&lt;stdint.h&gt;</CODE></TD>
</TR>
<TR><TD></TD><TD>5.2. Specializing Floating-Point Behavior</TD></TR>
<TR><TD></TD><TD>5.3. Macros for Build Options</TD></TR>
<TR><TD></TD><TD>5.4. Adapting a Template Target Directory</TD></TR>
<TR>
<TD></TD><TD>5.5. Target-Specific Optimization of Primitive Functions</TD>
</TR>
<TR><TD COLSPAN=2>6. Testing SoftFloat</TD></TR>
<TR>
<TD COLSPAN=2>7. Providing SoftFloat as a Common Library for Applications</TD>
</TR>
<TR><TD COLSPAN=2>8. Contact Information</TD></TR>
</TABLE>
</BLOCKQUOTE>
<H2>1. Introduction</H2>
<P>
This document gives information needed for compiling and/or porting Berkeley
SoftFloat, a library of C functions implementing binary floating-point
conforming to the IEEE Standard for Floating-Point Arithmetic.
For basic documentation about SoftFloat refer to
<A HREF="SoftFloat.html"><NOBR><CODE>SoftFloat.html</CODE></NOBR></A>.
</P>
<P>
The source code for SoftFloat is intended to be relatively machine-independent
and should be compilable with any ISO-Standard C compiler that also supports
<NOBR>64-bit</NOBR> integers.
SoftFloat has been successfully compiled with the GNU C Compiler
(<CODE>gcc</CODE>) for several platforms.
</P>
<P>
<NOBR>Release 3</NOBR> of SoftFloat was a complete rewrite relative to
<NOBR>Release 2</NOBR> or earlier.
Changes to the interface of SoftFloat functions are documented in
<A HREF="SoftFloat.html"><NOBR><CODE>SoftFloat.html</CODE></NOBR></A>.
The current version of SoftFloat is <NOBR>Release 3e</NOBR>.
</P>
<H2>2. Limitations</H2>
<P>
SoftFloat assumes the computer has an addressable byte size of either 8 or
<NOBR>16 bits</NOBR>.
(Nearly all computers in use today have <NOBR>8-bit</NOBR> bytes.)
</P>
<P>
SoftFloat is written in C and is designed to work with other C code.
The C compiler used must conform at a minimum to the 1989 ANSI standard for the
C language (same as the 1990 ISO standard) and must in addition support basic
arithmetic on <NOBR>64-bit</NOBR> integers.
Earlier releases of SoftFloat included implementations of <NOBR>32-bit</NOBR>
single-precision and <NOBR>64-bit</NOBR> double-precision floating-point that
did not require <NOBR>64-bit</NOBR> integers, but this option is not supported
starting with <NOBR>Release 3</NOBR>.
Since 1999, ISO standards for C have mandated compiler support for
<NOBR>64-bit</NOBR> integers.
A compiler conforming to the 1999 C Standard or later is recommended but not
strictly required.
</P>
<P>
<NOBR>C Standard</NOBR> header files <CODE>&lt;stdbool.h&gt;</CODE> and
<CODE>&lt;stdint.h&gt;</CODE> are required for defining standard Boolean and
integer types.
If these headers are not supplied with the C compiler, minimal substitutes must
be provided.
SoftFloat&rsquo;s dependence on these headers is detailed later in
<NOBR>section 5.1</NOBR>, <I>Standard Headers <CODE>&lt;stdbool.h&gt;</CODE>
and <CODE>&lt;stdint.h&gt;</CODE></I>.
</P>
<H2>3. Acknowledgments and License</H2>
<P>
The SoftFloat package was written by me, <NOBR>John R.</NOBR> Hauser.
<NOBR>Release 3</NOBR> of SoftFloat was a completely new implementation
supplanting earlier releases.
The project to create <NOBR>Release 3</NOBR> (now <NOBR>through 3e</NOBR>) was
done in the employ of the University of California, Berkeley, within the
Department of Electrical Engineering and Computer Sciences, first for the
Parallel Computing Laboratory (Par Lab) and then for the ASPIRE Lab.
The work was officially overseen by Prof. Krste Asanovic, with funding provided
by these sources:
<BLOCKQUOTE>
<TABLE>
<COL>
<COL WIDTH=10>
<COL>
<TR>
<TD VALIGN=TOP><NOBR>Par Lab:</NOBR></TD>
<TD></TD>
<TD>
Microsoft (Award #024263), Intel (Award #024894), and U.C. Discovery
(Award #DIG07-10227), with additional support from Par Lab affiliates Nokia,
NVIDIA, Oracle, and Samsung.
</TD>
</TR>
<TR>
<TD VALIGN=TOP><NOBR>ASPIRE Lab:</NOBR></TD>
<TD></TD>
<TD>
DARPA PERFECT program (Award #HR0011-12-2-0016), with additional support from
ASPIRE industrial sponsor Intel and ASPIRE affiliates Google, Nokia, NVIDIA,
Oracle, and Samsung.
</TD>
</TR>
</TABLE>
</BLOCKQUOTE>
</P>
<P>
The following applies to the whole of SoftFloat <NOBR>Release 3e</NOBR> as well
as to each source file individually.
</P>
<P>
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the
University of California.
All rights reserved.
</P>
<P>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
<OL>
<LI>
<P>
Redistributions of source code must retain the above copyright notice, this
list of conditions, and the following disclaimer.
</P>
<LI>
<P>
Redistributions in binary form must reproduce the above copyright notice, this
list of conditions, and the following disclaimer in the documentation and/or
other materials provided with the distribution.
</P>
<LI>
<P>
Neither the name of the University nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.
</P>
</OL>
</P>
<P>
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS &ldquo;AS IS&rdquo;,
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED.
IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</P>
<H2>4. SoftFloat Package Directory Structure</H2>
<P>
Because SoftFloat is targeted to multiple platforms, its source code is
slightly scattered between target-specific and target-independent directories
and files.
The supplied directory structure is as follows:
<BLOCKQUOTE>
<PRE>
doc
source
include
8086
8086-SSE
ARM-VFPv2
ARM-VFPv2-defaultNaN
build
template-FAST_INT64
template-not-FAST_INT64
Linux-386-GCC
Linux-386-SSE2-GCC
Linux-x86_64-GCC
Linux-ARM-VFPv2-GCC
Win32-MinGW
Win32-SSE2-MinGW
Win64-MinGW-w64
</PRE>
</BLOCKQUOTE>
The majority of the SoftFloat sources are provided in the <CODE>source</CODE>
directory.
The <CODE>include</CODE> subdirectory contains several header files
(unsurprisingly), while the other subdirectories of <CODE>source</CODE> contain
source files that specialize the floating-point behavior to match particular
processor families:
<BLOCKQUOTE>
<DL>
<DT><CODE>8086</CODE></DT>
<DD>
Intel&rsquo;s older, 8087-derived floating-point, extended to all supported
floating-point types
</DD>
<DT><CODE>8086-SSE</CODE></DT>
<DD>
Intel&rsquo;s x86 processors with Streaming SIMD Extensions (SSE) and later
compatible extensions, having 8087 behavior for <NOBR>80-bit</NOBR>
double-extended-precision (<CODE>extFloat80_t</CODE>) and SSE behavior for
other floating-point types
</DD>
<DT><CODE>ARM-VFPv2</CODE></DT>
<DD>
ARM&rsquo;s VFPv2 or later floating-point, with NaN payload propagation
</DD>
<DT><CODE>ARM-VFPv2-defaultNaN</CODE></DT>
<DD>
ARM&rsquo;s VFPv2 or later floating-point, with the &ldquo;default NaN&rdquo;
option
</DD>
</DL>
</BLOCKQUOTE>
If other specializations are attempted, these would be expected to be other
subdirectories of <CODE>source</CODE> alongside the ones listed above.
Specialization is covered later, in <NOBR>section 5.2</NOBR>, <I>Specializing
Floating-Point Behavior</I>.
</P>
<P>
The <CODE>build</CODE> directory is intended to contain a subdirectory for each
target platform for which a build of the SoftFloat library may be created.
For each build target, the target&rsquo;s subdirectory is where all derived
object files and the completed SoftFloat library (typically
<CODE>softfloat.a</CODE> or <CODE>libsoftfloat.a</CODE>) are created.
The two <CODE>template</CODE> subdirectories are not actual build targets but
contain sample files for creating new target directories.
(The meaning of <CODE>FAST_INT64</CODE> will be explained later.)
</P>
<P>
Ignoring the <CODE>template</CODE> directories, the supplied target directories
are intended to follow a naming system of
<NOBR><CODE>&lt;<I>execution-environment</I>&gt;-&lt;<I>compiler</I>&gt;</CODE></NOBR>.
For the example targets,
<NOBR><CODE>&lt;<I>execution-environment</I>&gt;</CODE></NOBR> is
<NOBR><CODE>Linux-386</CODE></NOBR>, <NOBR><CODE>Linux-386-SSE2</CODE></NOBR>,
<NOBR><CODE>Linux-x86_64</CODE></NOBR>,
<NOBR><CODE>Linux-ARM-VFPv2</CODE></NOBR>, <CODE>Win32</CODE>,
<NOBR><CODE>Win32-SSE2</CODE></NOBR>, or <CODE>Win64</CODE>, and
<NOBR><CODE>&lt;<I>compiler</I>&gt;</CODE></NOBR> is <CODE>GCC</CODE>,
<CODE>MinGW</CODE>, or <NOBR><CODE>MinGW-w64</CODE></NOBR>.
</P>
<P>
All of the supplied target directories are merely examples that may or may not
be correct for compiling on any particular system.
Despite requests, there are currently no plans to include and maintain in the
SoftFloat package the build files needed for a great many users&rsquo;
compilation environments, which can span a huge range of operating systems,
compilers, and other tools.
</P>
<P>
As supplied, each target directory contains two files:
<BLOCKQUOTE>
<PRE>
Makefile
platform.h
</PRE>
</BLOCKQUOTE>
The provided <CODE>Makefile</CODE> is written for GNU <CODE>make</CODE>.
A build of SoftFloat for the specific target is begun by executing the
<CODE>make</CODE> command with the target directory as the current directory.
A completely different build tool can be used if an appropriate
<CODE>Makefile</CODE> equivalent is created.
</P>
<P>
The <CODE>platform.h</CODE> header file exists to provide a location for
additional C declarations specific to the build target.
Every C source file of SoftFloat contains a <CODE>#include</CODE> for
<CODE>platform.h</CODE>.
In many cases, the contents of <CODE>platform.h</CODE> can be as simple as one
or two lines of code.
At the other extreme, to get maximal performance from SoftFloat, it may be
desirable to include in header <CODE>platform.h</CODE> (directly or via
<CODE>#include</CODE>) declarations for numerous target-specific optimizations.
Such possibilities are discussed in the next section, <I>Issues for Porting
SoftFloat to a New Target</I>.
If the target&rsquo;s compiler or library has bugs or other shortcomings,
workarounds for these issues may also be possible with target-specific
declarations in <CODE>platform.h</CODE>, avoiding the need to modify the main
SoftFloat sources.
</P>
<H2>5. Issues for Porting SoftFloat to a New Target</H2>
<H3>5.1. Standard Headers <CODE>&lt;stdbool.h&gt;</CODE> and <CODE>&lt;stdint.h&gt;</CODE></H3>
<P>
The SoftFloat sources make use of standard headers
<CODE>&lt;stdbool.h&gt;</CODE> and <CODE>&lt;stdint.h&gt;</CODE>, which have
been part of the ISO C Standard Library since 1999.
With any recent compiler, these standard headers are likely to be supported,
even if the compiler does not claim complete conformance to the latest ISO C
Standard.
For older or nonstandard compilers, substitutes for
<CODE>&lt;stdbool.h&gt;</CODE> and <CODE>&lt;stdint.h&gt;</CODE> may need to be
created.
SoftFloat depends on these names from <CODE>&lt;stdbool.h&gt;</CODE>:
<BLOCKQUOTE>
<PRE>
bool
true
false
</PRE>
</BLOCKQUOTE>
and on these names from <CODE>&lt;stdint.h&gt;</CODE>:
<BLOCKQUOTE>
<PRE>
uint16_t
uint32_t
uint64_t
int32_t
int64_t
UINT64_C
INT64_C
uint_least8_t
uint_fast8_t
uint_fast16_t
uint_fast32_t
uint_fast64_t
int_fast8_t
int_fast16_t
int_fast32_t
int_fast64_t
</PRE>
</BLOCKQUOTE>
</P>
<H3>5.2. Specializing Floating-Point Behavior</H3>
<P>
The IEEE Floating-Point Standard allows for some flexibility in a conforming
implementation, particularly concerning NaNs.
The SoftFloat <CODE>source</CODE> directory is supplied with some
<I>specialization</I> subdirectories containing possible definitions for this
implementation-specific behavior.
For example, the <CODE>8086</CODE> and <NOBR><CODE>8086-SSE</CODE></NOBR>
subdirectories have source files that specialize SoftFloat&rsquo;s behavior to
match that of Intel&rsquo;s x86 line of processors.
The files in a specialization subdirectory must determine:
<UL>
<LI>
whether tininess for underflow is detected before or after rounding by default;
<LI>
how signaling NaNs are distinguished from quiet NaNs;
<LI>
what (if anything) special happens when exceptions are raised;
<LI>
the default generated quiet NaNs;
<LI>
how NaNs are propagated from function inputs to output; and
<LI>
the integer results returned when conversions to integer type raise the
<I>invalid</I> exception.
</UL>
</P>
<P>
As provided, the build process for a target expects to involve exactly
<EM>one</EM> specialization directory that defines <EM>all</EM> of these
implementation-specific details for the target.
A specialization directory such as <CODE>8086</CODE> is expected to contain a
header file called <CODE>specialize.h</CODE>, together with whatever other
source files are needed to complete the specialization.
</P>
<P>
A new build target may use an existing specialization, such as the ones
provided by the <CODE>8086</CODE> and <NOBR><CODE>8086-SSE</CODE></NOBR>
subdirectories.
If a build target needs a new specialization, different from any existing ones,
it is recommended that a new specialization directory be created for this
purpose.
The <CODE>specialize.h</CODE> header file from any of the provided
specialization subdirectories can be used as a model for what definitions are
needed.
</P>
<H3>5.3. Macros for Build Options</H3>
<P>
The SoftFloat source files adapt the floating-point implementation according to
several C preprocessor macros:
<BLOCKQUOTE>
<DL>
<DT><CODE>LITTLEENDIAN</CODE>
<DD>
Must be defined for little-endian machines; must not be defined for big-endian
machines.
<DT><CODE>INLINE</CODE>
<DD>
Specifies the sequence of tokens used to indicate that a C function should be
inlined.
If macro <CODE>INLINE_LEVEL</CODE> is defined with a value of 1 or higher, this
macro must be defined; otherwise, this macro is ignored and need not be
defined.
For compilers that conform to the C Standard&rsquo;s rules for inline
functions, this macro can be defined as the single keyword <CODE>inline</CODE>.
For other compilers that follow a convention pre-dating the standardization of
<CODE>inline</CODE>, this macro may need to be defined to <CODE>extern</CODE>
<CODE>inline</CODE>.
<DT><CODE>THREAD_LOCAL</CODE>
<DD>
Can be defined to a sequence of tokens that, when appearing at the start of a
variable declaration, indicates to the C compiler that the variable is
<I>per-thread</I>, meaning that each execution thread gets its own separate
instance of the variable.
This macro is used in header <CODE>softfloat.h</CODE> in the declarations of
variables <CODE>softfloat_roundingMode</CODE>,
<CODE>softfloat_detectTininess</CODE>, <CODE>extF80_roundingPrecision</CODE>,
and <CODE>softfloat_exceptionFlags</CODE>.
If macro <CODE>THREAD_LOCAL</CODE> is left undefined, these variables will
default to being ordinary global variables.
Depending on the compiler, possible valid definitions of this macro include
<CODE>_Thread_local</CODE> and <CODE>__thread</CODE>.
</DL>
<DL>
<DT><CODE>SOFTFLOAT_ROUND_ODD</CODE>
<DD>
Can be defined to enable support for optional rounding mode
<CODE>softfloat_round_odd</CODE>.
</DL>
<DL>
<DT><CODE>INLINE_LEVEL</CODE>
<DD>
Can be defined to an integer to determine the degree of inlining requested of
the compiler.
Larger numbers request that more inlining be done.
If this macro is not defined or is defined to a value less <NOBR>than 1</NOBR>
(zero or negative), no inlining is requested.
The maximum effective value is no higher <NOBR>than 5</NOBR>.
Defining this macro to a value greater than 5 is the same as defining it
<NOBR>to 5</NOBR>.
<DT><CODE>SOFTFLOAT_FAST_INT64</CODE>
<DD>
Can be defined to indicate that the build target&rsquo;s implementation of
<NOBR>64-bit</NOBR> arithmetic is efficient.
For newer <NOBR>64-bit</NOBR> processors, this macro should usually be defined.
For very small microprocessors whose buses and registers are <NOBR>8-bit</NOBR>
or <NOBR>16-bit</NOBR> in size, this macro should usually not be defined.
Whether this macro should be defined for a <NOBR>32-bit</NOBR> processor may
depend on the target machine and the applications that will use SoftFloat.
<DT><CODE>SOFTFLOAT_FAST_DIV32TO16</CODE>
<DD>
Can be defined to indicate that the target&rsquo;s division operator
<NOBR>in C</NOBR> (written as <CODE>/</CODE>) is reasonably efficient for
dividing a <NOBR>32-bit</NOBR> unsigned integer by a <NOBR>16-bit</NOBR>
unsigned integer.
Setting this macro may affect the performance of function <CODE>f16_div</CODE>.
<DT><CODE>SOFTFLOAT_FAST_DIV64TO32</CODE>
<DD>
Can be defined to indicate that the target&rsquo;s division operator
<NOBR>in C</NOBR> (written as <CODE>/</CODE>) is reasonably efficient for
dividing a <NOBR>64-bit</NOBR> unsigned integer by a <NOBR>32-bit</NOBR>
unsigned integer.
Setting this macro may affect the performance of division, remainder, and
square root operations other than <CODE>f16_div</CODE>.
</DL>
</BLOCKQUOTE>
</P>
<P>
Following the usual custom <NOBR>for C</NOBR>, for most of these macros (all
except <CODE>INLINE</CODE>, <CODE>THREAD_LOCAL</CODE>, and
<CODE>INLINE_LEVEL</CODE>), the content of any definition is irrelevant;
what matters is a macro&rsquo;s effect on <CODE>#ifdef</CODE> directives.
</P>
<P>
It is recommended that any definitions of macros <CODE>LITTLEENDIAN</CODE>,
<CODE>INLINE</CODE>, and <CODE>THREAD_LOCAL</CODE> be made in a build
target&rsquo;s <CODE>platform.h</CODE> header file, because these macros are
expected to be determined inflexibly by the target machine and compiler.
The other five macros select options and control optimization, and thus might
be better located in the target&rsquo;s Makefile (or its equivalent).
</P>
<H3>5.4. Adapting a Template Target Directory</H3>
<P>
In the <CODE>build</CODE> directory, two <CODE>template</CODE> subdirectories
provide models for new target directories.
Two different templates exist because different functions are needed in the
SoftFloat library depending on whether macro <CODE>SOFTFLOAT_FAST_INT64</CODE>
is defined.
If macro <CODE>SOFTFLOAT_FAST_INT64</CODE> will be defined,
<NOBR><CODE>template-FAST_INT64</CODE></NOBR> is the template to use;
otherwise, <NOBR><CODE>template-not-FAST_INT64</CODE></NOBR> is the appropriate
template.
A new target directory can be created by copying the correct template directory
and editing the files inside.
To avoid confusion, it would be wise to refrain from editing the files within a
template directory directly.
</P>
<H3>5.5. Target-Specific Optimization of Primitive Functions</H3>
<P>
Header file <CODE>primitives.h</CODE> (in directory
<CODE>source/include</CODE>) declares macros and functions for numerous
underlying arithmetic operations upon which many of SoftFloat&rsquo;s
floating-point functions are ultimately built.
The SoftFloat sources include implementations of all of these functions/macros,
written as standard C code, so a complete and correct SoftFloat library can be
created using only the supplied code for all functions.
However, for many targets, SoftFloat&rsquo;s performance can be improved by
substituting target-specific implementations of some of the functions/macros
declared in <CODE>primitives.h</CODE>.
</P>
<P>
For example, <CODE>primitives.h</CODE> declares a function called
<CODE>softfloat_countLeadingZeros32</CODE> that takes an unsigned
<NOBR>32-bit</NOBR> integer as an argument and returns the number of the
integer&rsquo;s most-significant bits that are zeros.
While the SoftFloat sources include an implementation of this function written
in <NOBR>standard C</NOBR>, many processors can perform this same function
directly in only one or two machine instructions.
An alternative, target-specific implementation that maps to those instructions
is likely to be more efficient than the generic C code from the SoftFloat
package.
</P>
<P>
A build target can replace the supplied version of any function or macro of
<CODE>primitives.h</CODE> by defining a macro with the same name in the
target&rsquo;s <CODE>platform.h</CODE> header file.
For this purpose, it may be helpful for <CODE>platform.h</CODE> to
<CODE>#include</CODE> header file <CODE>primitiveTypes.h</CODE>, which defines
types used for arguments and results of functions declared in
<CODE>primitives.h</CODE>.
When a desired replacement implementation is a function, not a macro, it is
sufficient for <CODE>platform.h</CODE> to include the line
<BLOCKQUOTE>
<PRE>
#define &lt;<I>function-name</I>&gt; &lt;<I>function-name</I>&gt;
</PRE>
</BLOCKQUOTE>
where <NOBR><CODE>&lt;<I>function-name</I>&gt;</CODE></NOBR> is the name of the
function.
This technically defines <NOBR><CODE>&lt;<I>function-name</I>&gt;</CODE></NOBR>
as a macro, but one that resolves to the same name, which may then be a
function.
(A preprocessor that conforms to the C Standard is required to limit recursive
macro expansion from being applied more than once.)
</P>
<P>
The supplied header file <CODE>opts-GCC.h</CODE> (in directory
<CODE>source/include</CODE>) provides an example of target-specific
optimization for the GCC compiler.
Each GCC target example in the <CODE>build</CODE> directory has
<BLOCKQUOTE>
<CODE>#include "opts-GCC.h"</CODE>
</BLOCKQUOTE>
in its <CODE>platform.h</CODE> header file.
Before <CODE>opts-GCC.h</CODE> is included, the following macros must be
defined (or not) to control which features are invoked:
<BLOCKQUOTE>
<DL>
<DT><CODE>SOFTFLOAT_BUILTIN_CLZ</CODE></DT>
<DD>
If defined, SoftFloat&rsquo;s internal
&lsquo;<CODE>countLeadingZeros</CODE>&rsquo; functions use intrinsics
<CODE>__builtin_clz</CODE> and <CODE>__builtin_clzll</CODE>.
</DD>
<DT><CODE>SOFTFLOAT_INTRINSIC_INT128</CODE></DT>
<DD>
If defined, SoftFloat makes use of GCC&rsquo;s nonstandard <NOBR>128-bit</NOBR>
integer type <CODE>__int128</CODE>.
</DD>
</DL>
</BLOCKQUOTE>
On some machines, these improvements are observed to increase the speeds of
<CODE>f64_mul</CODE> and <CODE>f128_mul</CODE> by around 20 to 25%, although
other functions receive less dramatic boosts, or none at all.
Results can vary greatly across different platforms.
</P>
<H2>6. Testing SoftFloat</H2>
<P>
SoftFloat can be tested using the <CODE>testsoftfloat</CODE> program by the
same author.
This program is part of the Berkeley TestFloat package available at the Web
page
<A HREF="http://www.jhauser.us/arithmetic/TestFloat.html"><NOBR><CODE>http://www.jhauser.us/arithmetic/TestFloat.html</CODE></NOBR></A>.
The TestFloat package also has a program called <CODE>timesoftfloat</CODE> that
measures the speed of SoftFloat&rsquo;s floating-point functions.
</P>
<H2>7. Providing SoftFloat as a Common Library for Applications</H2>
<P>
Header file <CODE>softfloat.h</CODE> defines the SoftFloat interface as seen by
clients.
If the SoftFloat library will be made a common library for programs on a
system, the supplied <CODE>softfloat.h</CODE> has a couple of deficiencies for
this purpose:
<UL>
<LI>
As supplied, <CODE>softfloat.h</CODE> depends on another header,
<CODE>softfloat_types.h</CODE>, that is not intended for public use but which
must also be visible to the programmer&rsquo;s compiler.
<LI>
More troubling, at the time <CODE>softfloat.h</CODE> is included in a C source
file, macros <CODE>SOFTFLOAT_FAST_INT64</CODE> and <CODE>THREAD_LOCAL</CODE>
must be defined, or not defined, consistent with how these macro were defined
when the SoftFloat library was built.
</UL>
In the situation that new programs may regularly <CODE>#include</CODE> header
file <CODE>softfloat.h</CODE>, it is recommended that a custom, self-contained
version of this header file be created that eliminates these issues.
</P>
<H2>8. Contact Information</H2>
<P>
At the time of this writing, the most up-to-date information about SoftFloat
and the latest release can be found at the Web page
<A HREF="http://www.jhauser.us/arithmetic/SoftFloat.html"><NOBR><CODE>http://www.jhauser.us/arithmetic/SoftFloat.html</CODE></NOBR></A>.
</P>
</BODY>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,106 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
extern extFloat80_t softfloat_addMagsExtF80(uint16_t, uint64_t, uint16_t, uint64_t, bool, struct softfloat_status_t *);
extern extFloat80_t softfloat_subMagsExtF80(uint16_t, uint64_t, uint16_t, uint64_t, bool, struct softfloat_status_t *);
extFloat80_t extF80_add(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status)
{
uint16_t uiA64;
uint64_t uiA0;
bool signA;
uint16_t uiB64;
uint64_t uiB0;
bool signB;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
a.signExp = defaultNaNExtF80UI64;
a.signif = defaultNaNExtF80UI0;
return a;
}
uiA64 = a.signExp;
uiA0 = a.signif;
signA = signExtF80UI64(uiA64);
uiB64 = b.signExp;
uiB0 = b.signif;
signB = signExtF80UI64(uiB64);
if (signA == signB) {
return softfloat_addMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status);
} else {
return softfloat_subMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status);
}
}
extFloat80_t extF80_sub(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status)
{
uint16_t uiA64;
uint64_t uiA0;
bool signA;
uint16_t uiB64;
uint64_t uiB0;
bool signB;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
a.signExp = defaultNaNExtF80UI64;
a.signif = defaultNaNExtF80UI0;
return a;
}
uiA64 = a.signExp;
uiA0 = a.signif;
signA = signExtF80UI64(uiA64);
uiB64 = b.signExp;
uiB0 = b.signif;
signB = signExtF80UI64(uiB64);
if (signA == signB) {
return softfloat_subMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status);
} else {
return softfloat_addMagsExtF80(uiA64, uiA0, uiB64, uiB0, signA, status);
}
}

View File

@@ -0,0 +1,71 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "softfloat.h"
softfloat_class_t extF80_class(extFloat80_t a)
{
uint16_t uiA64;
uint64_t uiA0;
bool signA;
int32_t expA;
uint64_t sigA;
uiA64 = a.signExp;
uiA0 = a.signif;
signA = signExtF80UI64(uiA64);
expA = expExtF80UI64(uiA64);
sigA = uiA0;
if (! expA) {
if (! sigA) return softfloat_zero;
return softfloat_denormal; /* denormal or pseudo-denormal */
}
/* valid numbers have the MS bit set */
if (!(sigA & UINT64_C(0x8000000000000000)))
return softfloat_SNaN; /* report unsupported as SNaNs */
if (expA == 0x7FFF) {
if ((sigA<<1) == 0)
return (signA) ? softfloat_negative_inf : softfloat_positive_inf;
return (sigA & UINT64_C(0x4000000000000000)) ? softfloat_QNaN : softfloat_SNaN;
}
return softfloat_normalized;
}

View File

@@ -0,0 +1,147 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdio.h>
#include <stdint.h>
#include <86box/86box.h>
#include "../cpu.h"
#include "internals.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Compare between two extended precision floating point numbers. Returns
| 'float_relation_equal' if the operands are equal, 'float_relation_less' if
| the value 'a' is less than the corresponding value `b',
| 'float_relation_greater' if the value 'a' is greater than the corresponding
| value `b', or 'float_relation_unordered' otherwise.
*----------------------------------------------------------------------------*/
int extF80_compare(extFloat80_t a, extFloat80_t b, int quiet, struct softfloat_status_t *status)
{
uint16_t uiA64;
uint64_t uiA0;
bool signA;
int32_t expA;
uint64_t sigA;
uint16_t uiB64;
uint64_t uiB0;
bool signB;
int32_t expB;
uint64_t sigB;
struct exp32_sig64 normExpSig;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
softfloat_class_t aClass = extF80_class(a);
softfloat_class_t bClass = extF80_class(b);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (fpu_type < FPU_287XL) {
if ((aClass == softfloat_positive_inf) && (bClass == softfloat_negative_inf))
{
return softfloat_relation_equal;
}
if ((aClass == softfloat_negative_inf) && (bClass == softfloat_positive_inf))
{
return softfloat_relation_equal;
}
}
if (aClass == softfloat_SNaN || bClass == softfloat_SNaN)
{
/* unsupported reported as SNaN */
softfloat_raiseFlags(status, softfloat_flag_invalid);
return softfloat_relation_unordered;
}
if (aClass == softfloat_QNaN || bClass == softfloat_QNaN) {
if (! quiet) softfloat_raiseFlags(status, softfloat_flag_invalid);
return softfloat_relation_unordered;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (aClass == softfloat_denormal || bClass == softfloat_denormal) {
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
uiA0 = a.signif;
signA = signExtF80UI64(uiA64);
expA = expExtF80UI64(uiA64);
sigA = uiA0;
uiB64 = b.signExp;
uiB0 = b.signif;
signB = signExtF80UI64(uiB64);
expB = expExtF80UI64(uiB64);
sigB = uiB0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (aClass == softfloat_zero) {
if (bClass == softfloat_zero) return softfloat_relation_equal;
return signB ? softfloat_relation_greater : softfloat_relation_less;
}
if (bClass == softfloat_zero || signA != signB) {
return signA ? softfloat_relation_less : softfloat_relation_greater;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (aClass == softfloat_denormal) {
normExpSig = softfloat_normSubnormalExtF80Sig(sigA);
expA += normExpSig.exp + 1;
sigA = normExpSig.sig;
}
if (bClass == softfloat_denormal) {
normExpSig = softfloat_normSubnormalExtF80Sig(sigB);
expB += normExpSig.exp + 1;
sigB = normExpSig.sig;
}
if (expA == expB && sigA == sigB)
return softfloat_relation_equal;
int less_than =
signA ? ((expB < expA) || ((expB == expA) && (sigB < sigA)))
: ((expA < expB) || ((expA == expB) && (sigA < sigB)));
if (less_than) return softfloat_relation_less;
return softfloat_relation_greater;
}

View File

@@ -0,0 +1,188 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
extFloat80_t extF80_div(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status)
{
uint16_t uiA64;
uint64_t uiA0;
bool signA;
int32_t expA;
uint64_t sigA;
uint16_t uiB64;
uint64_t uiB0;
bool signB;
int32_t expB;
uint64_t sigB;
bool signZ;
struct exp32_sig64 normExpSig;
int32_t expZ;
struct uint128 rem;
uint32_t recip32;
uint64_t sigZ;
int ix;
uint64_t q64;
uint32_t q;
struct uint128 term;
uint64_t sigZExtra;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a) || extF80_isUnsupported(b))
goto invalid;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
uiA0 = a.signif;
signA = signExtF80UI64(uiA64);
expA = expExtF80UI64(uiA64);
sigA = uiA0;
uiB64 = b.signExp;
uiB0 = b.signif;
signB = signExtF80UI64(uiB64);
expB = expExtF80UI64(uiB64);
sigB = uiB0;
signZ = signA ^ signB;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0x7FFF) {
if (sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN;
if (expB == 0x7FFF) {
if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN;
goto invalid;
}
if (! expB && sigB)
softfloat_raiseFlags(status, softfloat_flag_denormal);
return packToExtF80(signZ, 0x7FFF, UINT64_C(0x8000000000000000));
}
if (expB == 0x7FFF) {
if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN;
if (! expA && sigA)
softfloat_raiseFlags(status, softfloat_flag_denormal);
return packToExtF80(signZ, 0, 0);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expB) {
expB = 1;
if (sigB)
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
if (! (sigB & UINT64_C(0x8000000000000000))) {
if (! sigB) {
if (! sigA) goto invalid;
softfloat_raiseFlags(status, softfloat_flag_infinite);
return packToExtF80(signZ, 0x7FFF, UINT64_C(0x8000000000000000));
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalExtF80Sig(sigB);
expB += normExpSig.exp;
sigB = normExpSig.sig;
}
if (! expA) {
expA = 1;
if (sigA)
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
if (! (sigA & UINT64_C(0x8000000000000000))) {
if (! sigA) return packToExtF80(signZ, 0, 0);
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalExtF80Sig(sigA);
expA += normExpSig.exp;
sigA = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expZ = expA - expB + 0x3FFF;
if (sigA < sigB) {
--expZ;
rem = softfloat_shortShiftLeft128(0, sigA, 32);
} else {
rem = softfloat_shortShiftLeft128(0, sigA, 31);
}
recip32 = softfloat_approxRecip32_1(sigB>>32);
sigZ = 0;
ix = 2;
for (;;) {
q64 = (uint64_t) (uint32_t) (rem.v64>>2) * recip32;
q = (q64 + 0x80000000)>>32;
--ix;
if (ix < 0) break;
rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29);
term = softfloat_mul64ByShifted32To128(sigB, q);
rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0);
if (rem.v64 & UINT64_C(0x8000000000000000)) {
--q;
rem = softfloat_add128(rem.v64, rem.v0, sigB>>32, sigB<<32);
}
sigZ = (sigZ<<29) + q;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (((q + 1) & 0x3FFFFF) < 2) {
rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29);
term = softfloat_mul64ByShifted32To128(sigB, q);
rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0);
term = softfloat_shortShiftLeft128(0, sigB, 32);
if (rem.v64 & UINT64_C(0x8000000000000000)) {
--q;
rem = softfloat_add128(rem.v64, rem.v0, term.v64, term.v0);
} else if (softfloat_le128(term.v64, term.v0, rem.v64, rem.v0)) {
++q;
rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0);
}
if (rem.v64 | rem.v0) q |= 1;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sigZ = (sigZ<<6) + (q>>23);
sigZExtra = (uint64_t) ((uint64_t) q<<41);
return
softfloat_roundPackToExtF80(signZ, expZ, sigZ, sigZExtra, softfloat_extF80_roundingPrecision(status), status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
propagateNaN:
return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
invalid:
softfloat_raiseFlags(status, softfloat_flag_invalid);
return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0);
}

View File

@@ -0,0 +1,97 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Separate the source extended double-precision floating point value `a'
| into its exponent and significand, store the significant back to the
| 'a' and return the exponent. The operation performed is a superset of
| the IEC/IEEE recommended logb(x) function.
*----------------------------------------------------------------------------*/
extFloat80_t extF80_extract(extFloat80_t *a, struct softfloat_status_t *status)
{
uint16_t uiA64;
uint64_t uiA0;
bool signA;
int32_t expA;
uint64_t sigA;
struct exp32_sig64 normExpSig;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(*a)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
*a = packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0);
return *a;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a->signExp;
uiA0 = a->signif;
signA = signExtF80UI64(uiA64);
expA = expExtF80UI64(uiA64);
sigA = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0x7FFF) {
if (sigA<<1) {
*a = softfloat_propagateNaNExtF80UI(uiA64, uiA0, 0, 0, status);
return *a;
}
return packToExtF80(0, 0x7FFF, BX_CONST64(0x8000000000000000));
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expA) {
if (! sigA) {
softfloat_raiseFlags(status, softfloat_flag_divbyzero);
*a = packToExtF80(signA, 0, 0);
return packToExtF80(1, 0x7FFF, BX_CONST64(0x8000000000000000));
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalExtF80Sig(sigA);
expA = normExpSig.exp + 1;
sigA = normExpSig.sig;
}
*a = packToExtF80(signA, 0x3FFF, sigA);
return i32_to_extF80(expA - 0x3FFF);
}

View File

@@ -0,0 +1,153 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
extFloat80_t extF80_mul(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status)
{
uint16_t uiA64;
uint64_t uiA0;
bool signA;
int32_t expA;
uint64_t sigA;
uint16_t uiB64;
uint64_t uiB0;
bool signB;
int32_t expB;
uint64_t sigB;
bool signZ;
uint64_t magBits;
struct exp32_sig64 normExpSig;
int32_t expZ;
struct uint128 sig128Z;
uint16_t uiZ64;
uint64_t uiZ0;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
uiA0 = a.signif;
signA = signExtF80UI64(uiA64);
expA = expExtF80UI64(uiA64);
sigA = uiA0;
uiB64 = b.signExp;
uiB0 = b.signif;
signB = signExtF80UI64(uiB64);
expB = expExtF80UI64(uiB64);
sigB = uiB0;
signZ = signA ^ signB;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0x7FFF) {
if ((sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) || ((expB == 0x7FFF) && (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)))) {
goto propagateNaN;
}
magBits = expB | sigB;
goto infArg;
}
if (expB == 0x7FFF) {
if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN;
magBits = expA | sigA;
goto infArg;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expA) {
expA = 1;
if (sigA)
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
if (! (sigA & UINT64_C(0x8000000000000000))) {
if (! sigA) {
if (! expB && sigB)
softfloat_raiseFlags(status, softfloat_flag_denormal);
return packToExtF80(signZ, 0, 0);
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalExtF80Sig(sigA);
expA += normExpSig.exp;
sigA = normExpSig.sig;
}
if (! expB) {
expB = 1;
if (sigB)
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
if (! (sigB & UINT64_C(0x8000000000000000))) {
if (! sigB) return packToExtF80(signZ, 0, 0);
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalExtF80Sig(sigB);
expB += normExpSig.exp;
sigB = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expZ = expA + expB - 0x3FFE;
sig128Z = softfloat_mul64To128(sigA, sigB);
if (sig128Z.v64 < UINT64_C(0x8000000000000000)) {
--expZ;
sig128Z = softfloat_add128(sig128Z.v64, sig128Z.v0, sig128Z.v64, sig128Z.v0);
}
return
softfloat_roundPackToExtF80(signZ, expZ, sig128Z.v64, sig128Z.v0, softfloat_extF80_roundingPrecision(status), status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
propagateNaN:
return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
infArg:
if (! magBits) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
uiZ64 = defaultNaNExtF80UI64;
uiZ0 = defaultNaNExtF80UI0;
} else {
if ((! expA && sigA) || (! expB && sigB))
softfloat_raiseFlags(status, softfloat_flag_denormal);
uiZ64 = packToExtF80UI64(signZ, 0x7FFF);
uiZ0 = UINT64_C(0x8000000000000000);
}
return packToExtF80_twoargs(uiZ64, uiZ0);
}

View File

@@ -0,0 +1,199 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
extFloat80_t extF80_rem(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status)
{
uint16_t uiA64;
uint64_t uiA0;
bool signA;
int32_t expA;
uint64_t sigA;
uint16_t uiB64;
uint64_t uiB0;
int32_t expB;
uint64_t sigB;
struct exp32_sig64 normExpSig;
int32_t expDiff;
struct uint128 rem, shiftedSigB;
uint32_t q, recip32;
uint64_t q64;
struct uint128 term, altRem, meanRem;
bool signRem;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a) || extF80_isUnsupported(b))
goto invalid;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
uiA0 = a.signif;
signA = signExtF80UI64(uiA64);
expA = expExtF80UI64(uiA64);
sigA = uiA0;
uiB64 = b.signExp;
uiB0 = b.signif;
expB = expExtF80UI64(uiB64);
sigB = uiB0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0x7FFF) {
if ((sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) || ((expB == 0x7FFF) && (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)))) {
goto propagateNaN;
}
goto invalid;
}
if (expB == 0x7FFF) {
if (sigB & UINT64_C(0x7FFFFFFFFFFFFFFF)) goto propagateNaN;
/*--------------------------------------------------------------------
| Argument b is an infinity. Doubling `expB' is an easy way to ensure
| that `expDiff' later is less than -1, which will result in returning
| a canonicalized version of argument a.
*--------------------------------------------------------------------*/
expB += expB;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expB) {
expB = 1;
if (sigB)
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
if (! (sigB & UINT64_C(0x8000000000000000))) {
if (! sigB) goto invalid;
normExpSig = softfloat_normSubnormalExtF80Sig(sigB);
expB += normExpSig.exp;
sigB = normExpSig.sig;
}
if (! expA) {
expA = 1;
if (sigA)
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
if (! (sigA & UINT64_C(0x8000000000000000))) {
if (! sigA) {
expA = 0;
goto copyA;
}
normExpSig = softfloat_normSubnormalExtF80Sig(sigA);
expA += normExpSig.exp;
sigA = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expDiff = expA - expB;
if (expDiff < -1) goto copyA;
rem = softfloat_shortShiftLeft128(0, sigA, 32);
shiftedSigB = softfloat_shortShiftLeft128(0, sigB, 32);
if (expDiff < 1) {
if (expDiff) {
--expB;
shiftedSigB = softfloat_shortShiftLeft128(0, sigB, 33);
q = 0;
} else {
q = (sigB <= sigA);
if (q) {
rem = softfloat_sub128(rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0);
}
}
} else {
recip32 = softfloat_approxRecip32_1(sigB>>32);
expDiff -= 30;
for (;;) {
q64 = (uint64_t) (uint32_t) (rem.v64>>2) * recip32;
if (expDiff < 0) break;
q = (q64 + 0x80000000)>>32;
rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29);
term = softfloat_mul64ByShifted32To128(sigB, q);
rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0);
if (rem.v64 & UINT64_C(0x8000000000000000)) {
rem = softfloat_add128(rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0);
}
expDiff -= 29;
}
/*--------------------------------------------------------------------
| (`expDiff' cannot be less than -29 here.)
*--------------------------------------------------------------------*/
q = (uint32_t) (q64>>32)>>(~expDiff & 31);
rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, expDiff + 30);
term = softfloat_mul64ByShifted32To128(sigB, q);
rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0);
if (rem.v64 & UINT64_C(0x8000000000000000)) {
altRem = softfloat_add128(rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0);
goto selectRem;
}
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
do {
altRem = rem;
++q;
rem = softfloat_sub128(rem.v64, rem.v0, shiftedSigB.v64, shiftedSigB.v0);
} while (! (rem.v64 & UINT64_C(0x8000000000000000)));
selectRem:
meanRem = softfloat_add128(rem.v64, rem.v0, altRem.v64, altRem.v0);
if ((meanRem.v64 & UINT64_C(0x8000000000000000)) || (! (meanRem.v64 | meanRem.v0) && (q & 1))) {
rem = altRem;
}
signRem = signA;
if (rem.v64 & UINT64_C(0x8000000000000000)) {
signRem = ! signRem;
rem = softfloat_sub128(0, 0, rem.v64, rem.v0);
}
return softfloat_normRoundPackToExtF80(signRem, rem.v64 | rem.v0 ? expB + 32 : 0, rem.v64, rem.v0, 80, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
propagateNaN:
return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
invalid:
softfloat_raiseFlags(status, softfloat_flag_invalid);
return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
copyA:
if (expA < 1) {
sigA >>= 1 - expA;
expA = 0;
}
return packToExtF80(signA, expA, sigA);
}

View File

@@ -0,0 +1,123 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
extFloat80_t
extF80_roundToInt(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
uint16_t uiA64, signUI64;
int32_t exp;
uint64_t sigA;
uint16_t uiZ64;
uint64_t sigZ;
uint64_t lastBitMask, roundBitsMask;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
signUI64 = uiA64 & packToExtF80UI64(1, 0);
exp = expExtF80UI64(uiA64);
sigA = a.signif;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (0x403E <= exp) {
if ((exp == 0x7FFF) && (uint64_t) (sigA<<1)) {
return softfloat_propagateNaNExtF80UI(uiA64, sigA, 0, 0, status);
}
return a;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp <= 0x3FFE) {
if (! exp) {
if ((sigA<<1) == 0) return a;
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
switch (roundingMode) {
case softfloat_round_near_even:
if (!(sigA & UINT64_C(0x7FFFFFFFFFFFFFFF))) break;
case softfloat_round_near_maxMag:
if (exp == 0x3FFE) goto mag1;
break;
case softfloat_round_min:
if (signUI64) goto mag1;
break;
case softfloat_round_max:
if (!signUI64) goto mag1;
break;
}
return packToExtF80(signUI64, 0, 0);
mag1:
softfloat_setRoundingUp(status);
return packToExtF80(signUI64, 0x3FFF, UINT64_C(0x8000000000000000));
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiZ64 = signUI64 | exp;
lastBitMask = (uint64_t) 1<<(0x403E - exp);
roundBitsMask = lastBitMask - 1;
sigZ = sigA;
if (roundingMode == softfloat_round_near_maxMag) {
sigZ += lastBitMask>>1;
} else if (roundingMode == softfloat_round_near_even) {
sigZ += lastBitMask>>1;
if (!(sigZ & roundBitsMask)) sigZ &= ~lastBitMask;
} else if (roundingMode == (signUI64 ? softfloat_round_min : softfloat_round_max)) {
sigZ += roundBitsMask;
}
sigZ &= ~roundBitsMask;
if (!sigZ) {
++uiZ64;
sigZ = UINT64_C(0x8000000000000000);
softfloat_setRoundingUp(status);
}
if (sigZ != sigA) {
if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
if (sigZ > sigA)
softfloat_setRoundingUp(status);
}
return packToExtF80_twoargs(uiZ64, sigZ);
}

View File

@@ -0,0 +1,136 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Scales extended double-precision floating-point value in operand `a' by
| value `b'. The function truncates the value in the second operand 'b' to
| an integral value and adds that value to the exponent of the operand 'a'.
| The operation performed according to the IEC/IEEE Standard for Binary
| Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
extFloat80_t extF80_scale(extFloat80_t a, extFloat80_t b, struct softfloat_status_t *status)
{
uint16_t uiA64;
uint64_t uiA0;
bool signA;
int32_t expA;
uint64_t sigA;
uint16_t uiB64;
uint64_t uiB0;
bool signB;
int32_t expB;
uint64_t sigB;
struct exp32_sig64 normExpSig;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) {
invalid:
softfloat_raiseFlags(status, softfloat_flag_invalid);
return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
uiA0 = a.signif;
signA = signExtF80UI64(uiA64);
expA = expExtF80UI64(uiA64);
sigA = uiA0;
uiB64 = b.signExp;
uiB0 = b.signif;
signB = signExtF80UI64(uiB64);
expB = expExtF80UI64(uiB64);
sigB = uiB0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0x7FFF) {
if ((sigA<<1) || ((expB == 0x7FFF) && (sigB<<1))) {
return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status);
}
if ((expB == 0x7FFF) && signB) goto invalid;
if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
return a;
}
if (expB == 0x7FFF) {
if (sigB<<1) {
return softfloat_propagateNaNExtF80UI(uiA64, uiA0, uiB64, uiB0, status);
}
if ((expA | sigA) == 0) {
if (! signB) goto invalid;
return a;
}
if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal);
if (signB) return packToExtF80(signA, 0, 0);
return packToExtF80(signA, 0x7FFF, BX_CONST64(0x8000000000000000));
}
if (! expA) {
if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
if (! sigA) return a;
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalExtF80Sig(sigA);
expA = normExpSig.exp + 1;
sigA = normExpSig.sig;
if (expB < 0x3FFF)
return softfloat_normRoundPackToExtF80(signA, expA, sigA, 0, 80, status);
}
if (!expB) {
if (!sigB) return a;
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalExtF80Sig(sigB);
expB = normExpSig.exp + 1;
sigB = normExpSig.sig;
}
if (expB > 0x400E) {
/* generate appropriate overflow/underflow */
return softfloat_roundPackToExtF80(signA, signB ? -0x3FFF : 0x7FFF, sigA, 0, 80, status);
}
if (expB < 0x3FFF) return a;
int shiftCount = 0x403E - expB;
sigB >>= shiftCount;
int32_t scale = (int32_t) sigB;
if (signB) scale = -scale; /* -32768..32767 */
return softfloat_roundPackToExtF80(signA, expA + scale, sigA, 0, 80, status);
}

View File

@@ -0,0 +1,159 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
extFloat80_t extF80_sqrt(extFloat80_t a, struct softfloat_status_t *status)
{
uint16_t uiA64;
uint64_t uiA0;
bool signA;
int32_t expA;
uint64_t sigA;
struct exp32_sig64 normExpSig;
int32_t expZ;
uint32_t sig32A, recipSqrt32, sig32Z;
struct uint128 rem;
uint64_t q, x64, sigZ;
struct uint128 y, term;
uint64_t sigZExtra;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a))
goto invalid;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
uiA0 = a.signif;
signA = signExtF80UI64(uiA64);
expA = expExtF80UI64(uiA64);
sigA = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0x7FFF) {
if (sigA & UINT64_C(0x7FFFFFFFFFFFFFFF)) {
return softfloat_propagateNaNExtF80UI(uiA64, uiA0, 0, 0, status);
}
if (! signA) return a;
goto invalid;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (signA) {
if ((expA | sigA) == 0) return packToExtF80(signA, 0, 0);
goto invalid;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expA) {
expA = 1;
if (sigA)
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
if (! (sigA & UINT64_C(0x8000000000000000))) {
if (! sigA) return packToExtF80(signA, 0, 0);
normExpSig = softfloat_normSubnormalExtF80Sig(sigA);
expA += normExpSig.exp;
sigA = normExpSig.sig;
}
/*------------------------------------------------------------------------
| (`sig32Z' is guaranteed to be a lower bound on the square root of
| `sig32A', which makes `sig32Z' also a lower bound on the square root of
| `sigA'.)
*------------------------------------------------------------------------*/
expZ = ((expA - 0x3FFF)>>1) + 0x3FFF;
expA &= 1;
sig32A = sigA>>32;
recipSqrt32 = softfloat_approxRecipSqrt32_1(expA, sig32A);
sig32Z = ((uint64_t) sig32A * recipSqrt32)>>32;
if (expA) {
sig32Z >>= 1;
rem = softfloat_shortShiftLeft128(0, sigA, 61);
} else {
rem = softfloat_shortShiftLeft128(0, sigA, 62);
}
rem.v64 -= (uint64_t) sig32Z * sig32Z;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
q = ((uint32_t) (rem.v64>>2) * (uint64_t) recipSqrt32)>>32;
x64 = (uint64_t) sig32Z<<32;
sigZ = x64 + (q<<3);
y = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29);
/*------------------------------------------------------------------------
| (Repeating this loop is a rare occurrence.)
*------------------------------------------------------------------------*/
for (;;) {
term = softfloat_mul64ByShifted32To128(x64 + sigZ, q);
rem = softfloat_sub128(y.v64, y.v0, term.v64, term.v0);
if (! (rem.v64 & UINT64_C(0x8000000000000000))) break;
--q;
sigZ -= 1<<3;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
q = (((rem.v64>>2) * recipSqrt32)>>32) + 2;
x64 = sigZ;
sigZ = (sigZ<<1) + (q>>25);
sigZExtra = (uint64_t) (q<<39);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ((q & 0xFFFFFF) <= 2) {
q &= ~(uint64_t) 0xFFFF;
sigZExtra = (uint64_t) (q<<39);
term = softfloat_mul64ByShifted32To128(x64 + (q>>27), q);
x64 = (uint32_t) (q<<5) * (uint64_t) (uint32_t) q;
term = softfloat_add128(term.v64, term.v0, 0, x64);
rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 28);
rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0);
if (rem.v64 & UINT64_C(0x8000000000000000)) {
if (! sigZExtra) --sigZ;
--sigZExtra;
} else {
if (rem.v64 | rem.v0) sigZExtra |= 1;
}
}
return
softfloat_roundPackToExtF80(0, expZ, sigZ, sigZExtra, softfloat_extF80_roundingPrecision(status), status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
invalid:
softfloat_raiseFlags(status, softfloat_flag_invalid);
return packToExtF80_twoargs(defaultNaNExtF80UI64, defaultNaNExtF80UI0);
}

View File

@@ -0,0 +1,75 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
float128_t extF80_to_f128(extFloat80_t a, struct softfloat_status_t *status)
{
uint16_t uiA64;
uint64_t uiA0;
uint16_t exp;
uint64_t frac;
struct commonNaN commonNaN;
struct uint128 uiZ;
bool sign;
struct uint128 frac128;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
uiZ.v64 = defaultNaNF128UI64;
uiZ.v0 = defaultNaNF128UI0;
return uiZ;
}
uiA64 = a.signExp;
uiA0 = a.signif;
exp = expExtF80UI64(uiA64);
frac = uiA0 & UINT64_C(0x7FFFFFFFFFFFFFFF);
if ((exp == 0x7FFF) && frac) {
softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status);
uiZ = softfloat_commonNaNToF128UI(&commonNaN);
} else {
sign = signExtF80UI64(uiA64);
frac128 = softfloat_shortShiftLeft128(0, frac, 49);
uiZ.v64 = packToF128UI64(sign, exp, frac128.v64);
uiZ.v0 = frac128.v0;
}
return uiZ;
}

View File

@@ -0,0 +1,89 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
float16 extF80_to_f16(extFloat80_t a, struct softfloat_status_t *status)
{
uint16_t uiA64;
uint64_t uiA0;
bool sign;
int32_t exp;
uint64_t sig;
struct commonNaN commonNaN;
uint16_t uiZ, sig16;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return defaultNaNF16UI;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
uiA0 = a.signif;
sign = signExtF80UI64(uiA64);
exp = expExtF80UI64(uiA64);
sig = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp == 0x7FFF) {
if (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) {
softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status);
uiZ = softfloat_commonNaNToF16UI(&commonNaN);
} else {
uiZ = packToF16UI(sign, 0x1F, 0);
}
return uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sig16 = softfloat_shortShiftRightJam64(sig, 49);
if (! (exp | sig16)) {
return packToF16UI(sign, 0, 0);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
exp -= 0x3FF1;
if (sizeof (int16_t) < sizeof (int32_t)) {
if (exp < -0x40) exp = -0x40;
}
return softfloat_roundPackToF16(sign, exp, sig16, status);
}

View File

@@ -0,0 +1,89 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
float32 extF80_to_f32(extFloat80_t a, struct softfloat_status_t *status)
{
uint16_t uiA64;
uint64_t uiA0;
bool sign;
int32_t exp;
uint64_t sig;
struct commonNaN commonNaN;
uint32_t uiZ, sig32;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return defaultNaNF32UI;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
uiA0 = a.signif;
sign = signExtF80UI64(uiA64);
exp = expExtF80UI64(uiA64);
sig = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp == 0x7FFF) {
if (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) {
softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status);
uiZ = softfloat_commonNaNToF32UI(&commonNaN);
} else {
uiZ = packToF32UI(sign, 0xFF, 0);
}
return uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sig32 = softfloat_shortShiftRightJam64(sig, 33);
if (! (exp | sig32)) {
return packToF32UI(sign, 0, 0);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
exp -= 0x3F81;
if (sizeof (int16_t) < sizeof (int32_t)) {
if (exp < -0x1000) exp = -0x1000;
}
return softfloat_roundPackToF32(sign, exp, sig32, status);
}

View File

@@ -0,0 +1,89 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
float64 extF80_to_f64(extFloat80_t a, struct softfloat_status_t *status)
{
uint16_t uiA64;
uint64_t uiA0;
bool sign;
int32_t exp;
uint64_t sig;
struct commonNaN commonNaN;
uint64_t uiZ;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return defaultNaNF64UI;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
uiA0 = a.signif;
sign = signExtF80UI64(uiA64);
exp = expExtF80UI64(uiA64);
sig = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! (exp | sig)) {
return packToF64UI(sign, 0, 0);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp == 0x7FFF) {
if (sig & UINT64_C(0x7FFFFFFFFFFFFFFF)) {
softfloat_extF80UIToCommonNaN(uiA64, uiA0, &commonNaN, status);
uiZ = softfloat_commonNaNToF64UI(&commonNaN);
} else {
uiZ = packToF64UI(sign, 0x7FF, 0);
}
return uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sig = softfloat_shortShiftRightJam64(sig, 1);
exp -= 0x3C01;
if (sizeof (int16_t) < sizeof (int32_t)) {
if (exp < -0x1000) exp = -0x1000;
}
return softfloat_roundPackToF64(sign, exp, sig, status);
}

View File

@@ -0,0 +1,82 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
int32_t extF80_to_i32(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
uint16_t uiA64;
bool sign;
int32_t exp;
uint64_t sig;
int32_t shiftDist;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return i32_fromNaN;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
sign = signExtF80UI64(uiA64);
exp = expExtF80UI64(uiA64);
sig = a.signif;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow)
if ((exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))) {
#if (i32_fromNaN == i32_fromPosOverflow)
sign = 0;
#elif (i32_fromNaN == i32_fromNegOverflow)
sign = 1;
#else
softfloat_raiseFlags(status, softfloat_flag_invalid);
return i32_fromNaN;
#endif
}
#endif
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x4032 - exp;
if (shiftDist <= 0) shiftDist = 1;
sig = softfloat_shiftRightJam64(sig, shiftDist);
return softfloat_roundToI32(sign, sig, roundingMode, exact, status);
}

View File

@@ -0,0 +1,93 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
int32_t extF80_to_i32_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status)
{
uint16_t uiA64;
int32_t exp;
uint64_t sig;
int32_t shiftDist;
bool sign;
int32_t absZ;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return i32_fromNaN;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
exp = expExtF80UI64(uiA64);
sig = a.signif;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x403E - exp;
if (64 <= shiftDist) {
if (exact && (exp | sig)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signExtF80UI64(uiA64);
if (shiftDist < 33) {
if ((uiA64 == packToExtF80UI64(1, 0x401E)) && (sig < UINT64_C(0x8000000100000000))) {
if (exact && (sig & UINT64_C(0x00000000FFFFFFFF))) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return -0x7FFFFFFF - 1;
}
softfloat_raiseFlags(status, softfloat_flag_invalid);
return
(exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))
? i32_fromNaN
: sign ? i32_fromNegOverflow : i32_fromPosOverflow;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
absZ = sig>>shiftDist;
if (exact && ((uint64_t) (uint32_t) absZ<<shiftDist != sig)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return sign ? -absZ : absZ;
}

View File

@@ -0,0 +1,88 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
int64_t extF80_to_i64(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
uint16_t uiA64;
bool sign;
int32_t exp;
uint64_t sig;
int32_t shiftDist;
uint64_t sigExtra;
struct uint64_extra sig64Extra;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return i64_fromNaN;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
sign = signExtF80UI64(uiA64);
exp = expExtF80UI64(uiA64);
sig = a.signif;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x403E - exp;
if (shiftDist <= 0) {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (shiftDist) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return
(exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))
? i64_fromNaN
: sign ? i64_fromNegOverflow : i64_fromPosOverflow;
}
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
sigExtra = 0;
} else {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
sig64Extra = softfloat_shiftRightJam64Extra(sig, 0, shiftDist);
sig = sig64Extra.v;
sigExtra = sig64Extra.extra;
}
return softfloat_roundToI64(sign, sig, sigExtra, roundingMode, exact, status);
}

View File

@@ -0,0 +1,90 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
int64_t extF80_to_i64_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status)
{
uint16_t uiA64;
int32_t exp;
uint64_t sig;
int32_t shiftDist;
bool sign;
int64_t absZ;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return i64_fromNaN;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
exp = expExtF80UI64(uiA64);
sig = a.signif;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x403E - exp;
if (64 <= shiftDist) {
if (exact && (exp | sig)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signExtF80UI64(uiA64);
if (shiftDist <= 0) {
if ((uiA64 == packToExtF80UI64(1, 0x403E)) && (sig == UINT64_C(0x8000000000000000))) {
return -INT64_C(0x7FFFFFFFFFFFFFFF) - 1;
}
softfloat_raiseFlags(status, softfloat_flag_invalid);
return
(exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))
? i64_fromNaN
: sign ? i64_fromNegOverflow : i64_fromPosOverflow;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
absZ = sig>>shiftDist;
if (exact && (uint64_t) (sig<<(-shiftDist & 63))) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return sign ? -absZ : absZ;
}

View File

@@ -0,0 +1,83 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
uint32_t
extF80_to_ui32(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
uint16_t uiA64;
bool sign;
int32_t exp;
uint64_t sig;
int32_t shiftDist;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return ui32_fromNaN;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
sign = signExtF80UI64(uiA64);
exp = expExtF80UI64(uiA64);
sig = a.signif;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow)
if ((exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))) {
#if (ui32_fromNaN == ui32_fromPosOverflow)
sign = 0;
#elif (ui32_fromNaN == ui32_fromNegOverflow)
sign = 1;
#else
softfloat_raiseFlags(status, softfloat_flag_invalid);
return ui32_fromNaN;
#endif
}
#endif
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x4032 - exp;
if (shiftDist <= 0) shiftDist = 1;
sig = softfloat_shiftRightJam64(sig, shiftDist);
return softfloat_roundToUI32(sign, sig, roundingMode, exact, status);
}

View File

@@ -0,0 +1,87 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
uint32_t extF80_to_ui32_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status)
{
uint16_t uiA64;
int32_t exp;
uint64_t sig;
int32_t shiftDist;
bool sign;
uint32_t z;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return ui32_fromNaN;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
exp = expExtF80UI64(uiA64);
sig = a.signif;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x403E - exp;
if (64 <= shiftDist) {
if (exact && (exp | sig)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signExtF80UI64(uiA64);
if (sign || (shiftDist < 32)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return
(exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))
? ui32_fromNaN
: sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
z = sig>>shiftDist;
if (exact && ((uint64_t) z<<shiftDist != sig)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return z;
}

View File

@@ -0,0 +1,83 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
uint64_t extF80_to_ui64(extFloat80_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
uint16_t uiA64;
bool sign;
int32_t exp;
uint64_t sig;
int32_t shiftDist;
uint64_t sigExtra;
struct uint64_extra sig64Extra;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return ui64_fromNaN;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
sign = signExtF80UI64(uiA64);
exp = expExtF80UI64(uiA64);
sig = a.signif;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x403E - exp;
if (shiftDist < 0) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return
(exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))
? ui64_fromNaN
: sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sigExtra = 0;
if (shiftDist) {
sig64Extra = softfloat_shiftRightJam64Extra(sig, 0, shiftDist);
sig = sig64Extra.v;
sigExtra = sig64Extra.extra;
}
return softfloat_roundToUI64(sign, sig, sigExtra, roundingMode, exact, status);
}

View File

@@ -0,0 +1,87 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
uint64_t extF80_to_ui64_r_minMag(extFloat80_t a, bool exact, struct softfloat_status_t *status)
{
uint16_t uiA64;
int32_t exp;
uint64_t sig;
int32_t shiftDist;
bool sign;
uint64_t z;
// handle unsupported extended double-precision floating encodings
if (extF80_isUnsupported(a)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return ui64_fromNaN;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.signExp;
exp = expExtF80UI64(uiA64);
sig = a.signif;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x403E - exp;
if (64 <= shiftDist) {
if (exact && (exp | sig)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signExtF80UI64(uiA64);
if (sign || (shiftDist < 0)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return
(exp == 0x7FFF) && (sig & UINT64_C(0x7FFFFFFFFFFFFFFF))
? ui64_fromNaN
: sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
z = sig>>shiftDist;
if (exact && (z<<shiftDist != sig)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return z;
}

View File

@@ -0,0 +1,88 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "softfloat.h"
extern float128_t
softfloat_addMagsF128(uint64_t, uint64_t, uint64_t, uint64_t, bool, struct softfloat_status_t *);
extern float128_t
softfloat_subMagsF128(uint64_t, uint64_t, uint64_t, uint64_t, bool, struct softfloat_status_t *);
float128_t f128_add(float128_t a, float128_t b, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
bool signA;
uint64_t uiB64, uiB0;
bool signB;
uiA64 = a.v64;
uiA0 = a.v0;
signA = signF128UI64(uiA64);
uiB64 = b.v64;
uiB0 = b.v0;
signB = signF128UI64(uiB64);
if (signA == signB) {
return softfloat_addMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status);
} else {
return softfloat_subMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status);
}
}
float128_t f128_sub(float128_t a, float128_t b, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
bool signA;
uint64_t uiB64, uiB0;
bool signB;
uiA64 = a.v64;
uiA0 = a.v0;
signA = signF128UI64(uiA64);
uiB64 = b.v64;
uiB0 = b.v0;
signB = signF128UI64(uiB64);
if (signA == signB) {
return softfloat_subMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status);
} else {
return softfloat_addMagsF128(uiA64, uiA0, uiB64, uiB0, signA, status);
}
}

View File

@@ -0,0 +1,187 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
float128_t f128_div(float128_t a, float128_t b, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
bool signA;
int32_t expA;
struct uint128 sigA;
uint64_t uiB64, uiB0;
bool signB;
int32_t expB;
struct uint128 sigB;
bool signZ;
struct exp32_sig128 normExpSig;
int32_t expZ;
struct uint128 rem;
uint32_t recip32;
int ix;
uint64_t q64;
uint32_t q;
struct uint128 term;
uint32_t qs[3];
uint64_t sigZExtra;
struct uint128 sigZ, uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.v64;
uiA0 = a.v0;
signA = signF128UI64(uiA64);
expA = expF128UI64(uiA64);
sigA.v64 = fracF128UI64(uiA64);
sigA.v0 = uiA0;
uiB64 = b.v64;
uiB0 = b.v0;
signB = signF128UI64(uiB64);
expB = expF128UI64(uiB64);
sigB.v64 = fracF128UI64(uiB64);
sigB.v0 = uiB0;
signZ = signA ^ signB;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0x7FFF) {
if (sigA.v64 | sigA.v0) goto propagateNaN;
if (expB == 0x7FFF) {
if (sigB.v64 | sigB.v0) goto propagateNaN;
goto invalid;
}
goto infinity;
}
if (expB == 0x7FFF) {
if (sigB.v64 | sigB.v0) goto propagateNaN;
goto zero;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expB) {
if (! (sigB.v64 | sigB.v0)) {
if (! (expA | sigA.v64 | sigA.v0)) goto invalid;
softfloat_raiseFlags(status, softfloat_flag_infinite);
goto infinity;
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF128Sig(sigB.v64, sigB.v0);
expB = normExpSig.exp;
sigB = normExpSig.sig;
}
if (! expA) {
if (! (sigA.v64 | sigA.v0)) goto zero;
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF128Sig(sigA.v64, sigA.v0);
expA = normExpSig.exp;
sigA = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expZ = expA - expB + 0x3FFE;
sigA.v64 |= UINT64_C(0x0001000000000000);
sigB.v64 |= UINT64_C(0x0001000000000000);
rem = sigA;
if (softfloat_lt128(sigA.v64, sigA.v0, sigB.v64, sigB.v0)) {
--expZ;
rem = softfloat_add128(sigA.v64, sigA.v0, sigA.v64, sigA.v0);
}
recip32 = softfloat_approxRecip32_1(sigB.v64>>17);
ix = 3;
for (;;) {
q64 = (uint64_t) (uint32_t) (rem.v64>>19) * recip32;
q = (q64 + 0x80000000)>>32;
--ix;
if (ix < 0) break;
rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29);
term = softfloat_mul128By32(sigB.v64, sigB.v0, q);
rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0);
if (rem.v64 & UINT64_C(0x8000000000000000)) {
--q;
rem = softfloat_add128(rem.v64, rem.v0, sigB.v64, sigB.v0);
}
qs[ix] = q;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (((q + 1) & 7) < 2) {
rem = softfloat_shortShiftLeft128(rem.v64, rem.v0, 29);
term = softfloat_mul128By32(sigB.v64, sigB.v0, q);
rem = softfloat_sub128(rem.v64, rem.v0, term.v64, term.v0);
if (rem.v64 & UINT64_C(0x8000000000000000)) {
--q;
rem = softfloat_add128(rem.v64, rem.v0, sigB.v64, sigB.v0);
} else if (softfloat_le128(sigB.v64, sigB.v0, rem.v64, rem.v0)) {
++q;
rem = softfloat_sub128(rem.v64, rem.v0, sigB.v64, sigB.v0);
}
if (rem.v64 | rem.v0) q |= 1;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sigZExtra = (uint64_t) ((uint64_t) q<<60);
term = softfloat_shortShiftLeft128(0, qs[1], 54);
sigZ = softfloat_add128((uint64_t) qs[2]<<19, ((uint64_t) qs[0]<<25) + (q>>4), term.v64, term.v0);
return
softfloat_roundPackToF128(signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
propagateNaN:
uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status);
return uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
invalid:
softfloat_raiseFlags(status, softfloat_flag_invalid);
uiZ.v64 = defaultNaNF128UI64;
uiZ.v0 = defaultNaNF128UI0;
return uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
infinity:
uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0);
uiZ.v0 = 0;
return uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
zero:
uiZ.v64 = packToF128UI64(signZ, 0, 0);
uiZ.v0 = 0;
return uiZ;
}

View File

@@ -0,0 +1,148 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "primitiveTypes.h"
#include "specialize.h"
#include "softfloat.h"
float128_t f128_mul(float128_t a, float128_t b, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
bool signA;
int32_t expA;
struct uint128 sigA;
uint64_t uiB64, uiB0;
bool signB;
int32_t expB;
struct uint128 sigB;
bool signZ;
uint64_t magBits;
struct exp32_sig128 normExpSig;
int32_t expZ;
uint64_t sig256Z[4];
uint64_t sigZExtra;
struct uint128 sigZ;
struct uint128_extra sig128Extra;
struct uint128 uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.v64;
uiA0 = a.v0;
signA = signF128UI64(uiA64);
expA = expF128UI64(uiA64);
sigA.v64 = fracF128UI64(uiA64);
sigA.v0 = uiA0;
uiB64 = b.v64;
uiB0 = b.v0;
signB = signF128UI64(uiB64);
expB = expF128UI64(uiB64);
sigB.v64 = fracF128UI64(uiB64);
sigB.v0 = uiB0;
signZ = signA ^ signB;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0x7FFF) {
if ((sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))) {
goto propagateNaN;
}
magBits = expB | sigB.v64 | sigB.v0;
goto infArg;
}
if (expB == 0x7FFF) {
if (sigB.v64 | sigB.v0) goto propagateNaN;
magBits = expA | sigA.v64 | sigA.v0;
goto infArg;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expA) {
if (! (sigA.v64 | sigA.v0)) goto zero;
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF128Sig(sigA.v64, sigA.v0);
expA = normExpSig.exp;
sigA = normExpSig.sig;
}
if (! expB) {
if (! (sigB.v64 | sigB.v0)) goto zero;
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF128Sig(sigB.v64, sigB.v0);
expB = normExpSig.exp;
sigB = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expZ = expA + expB - 0x4000;
sigA.v64 |= UINT64_C(0x0001000000000000);
sigB = softfloat_shortShiftLeft128(sigB.v64, sigB.v0, 16);
softfloat_mul128To256M(sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z);
sigZExtra = sig256Z[indexWord(4, 1)] | (sig256Z[indexWord(4, 0)] != 0);
sigZ = softfloat_add128(sig256Z[indexWord(4, 3)], sig256Z[indexWord(4, 2)], sigA.v64, sigA.v0);
if (UINT64_C(0x0002000000000000) <= sigZ.v64) {
++expZ;
sig128Extra = softfloat_shortShiftRightJam128Extra(sigZ.v64, sigZ.v0, sigZExtra, 1);
sigZ = sig128Extra.v;
sigZExtra = sig128Extra.extra;
}
return
softfloat_roundPackToF128(signZ, expZ, sigZ.v64, sigZ.v0, sigZExtra, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
propagateNaN:
uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status);
return uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
infArg:
if (! magBits) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
uiZ.v64 = defaultNaNF128UI64;
uiZ.v0 = defaultNaNF128UI0;
return uiZ;
}
uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0);
uiZ.v0 = 0;
return uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
zero:
uiZ.v64 = packToF128UI64(signZ, 0, 0);
uiZ.v0 = 0;
return uiZ;
}

View File

@@ -0,0 +1,332 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "primitiveTypes.h"
#include "softfloat.h"
#include "specialize.h"
float128_t f128_mulAdd(float128_t a, float128_t b, float128_t c, uint8_t op, struct softfloat_status_t *status)
{
bool signA;
int32_t expA;
struct uint128 sigA;
bool signB;
int32_t expB;
struct uint128 sigB;
bool signC;
int32_t expC;
struct uint128 sigC;
bool signZ;
uint64_t magBits;
struct uint128 uiZ;
struct exp32_sig128 normExpSig;
int32_t expZ;
uint64_t sig256Z[4];
struct uint128 sigZ;
int32_t shiftDist, expDiff;
struct uint128 x128;
uint64_t sig256C[4];
static uint64_t zero256[4] = INIT_UINTM4(0, 0, 0, 0);
uint64_t sigZExtra, sig256Z0;
uint64_t uiA64, uiA0;
uint64_t uiB64, uiB0;
uint64_t uiC64, uiC0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.v64;
uiA0 = a.v0;
uiB64 = b.v64;
uiB0 = b.v0;
uiC64 = c.v64;
uiC0 = c.v0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
signA = signF128UI64(uiA64);
expA = expF128UI64(uiA64);
sigA.v64 = fracF128UI64(uiA64);
sigA.v0 = uiA0;
signB = signF128UI64(uiB64);
expB = expF128UI64(uiB64);
sigB.v64 = fracF128UI64(uiB64);
sigB.v0 = uiB0;
signC = signF128UI64(uiC64) ^ ((op & softfloat_mulAdd_subC) != 0);
expC = expF128UI64(uiC64);
sigC.v64 = fracF128UI64(uiC64);
sigC.v0 = uiC0;
signZ = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0x7FFF) {
if ((sigA.v64 | sigA.v0) || ((expB == 0x7FFF) && (sigB.v64 | sigB.v0))) {
goto propagateNaN_ABC;
}
magBits = expB | sigB.v64 | sigB.v0;
goto infProdArg;
}
if (expB == 0x7FFF) {
if (sigB.v64 | sigB.v0) goto propagateNaN_ABC;
magBits = expA | sigA.v64 | sigA.v0;
goto infProdArg;
}
if (expC == 0x7FFF) {
if (sigC.v64 | sigC.v0) {
uiZ.v64 = 0;
uiZ.v0 = 0;
goto propagateNaN_ZC;
}
uiZ.v64 = uiC64;
uiZ.v0 = uiC0;
return uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expA) {
if (! (sigA.v64 | sigA.v0)) goto zeroProd;
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF128Sig(sigA.v64, sigA.v0);
expA = normExpSig.exp;
sigA = normExpSig.sig;
}
if (! expB) {
if (! (sigB.v64 | sigB.v0)) goto zeroProd;
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF128Sig(sigB.v64, sigB.v0);
expB = normExpSig.exp;
sigB = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expZ = expA + expB - 0x3FFE;
sigA.v64 |= UINT64_C(0x0001000000000000);
sigB.v64 |= UINT64_C(0x0001000000000000);
sigA = softfloat_shortShiftLeft128(sigA.v64, sigA.v0, 8);
sigB = softfloat_shortShiftLeft128(sigB.v64, sigB.v0, 15);
softfloat_mul128To256M(sigA.v64, sigA.v0, sigB.v64, sigB.v0, sig256Z);
sigZ.v64 = sig256Z[indexWord(4, 3)];
sigZ.v0 = sig256Z[indexWord(4, 2)];
shiftDist = 0;
if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) {
--expZ;
shiftDist = -1;
}
if (! expC) {
if (! (sigC.v64 | sigC.v0)) {
shiftDist += 8;
goto sigZ;
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF128Sig(sigC.v64, sigC.v0);
expC = normExpSig.exp;
sigC = normExpSig.sig;
}
sigC.v64 |= UINT64_C(0x0001000000000000);
sigC = softfloat_shortShiftLeft128(sigC.v64, sigC.v0, 8);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expDiff = expZ - expC;
if (expDiff < 0) {
expZ = expC;
if ((signZ == signC) || (expDiff < -1)) {
shiftDist -= expDiff;
if (shiftDist) {
sigZ = softfloat_shiftRightJam128(sigZ.v64, sigZ.v0, shiftDist);
}
} else {
if (! shiftDist) {
x128 = softfloat_shortShiftRight128(sig256Z[indexWord(4, 1)], sig256Z[indexWord(4, 0)], 1);
sig256Z[indexWord(4, 1)] = (sigZ.v0<<63) | x128.v64;
sig256Z[indexWord(4, 0)] = x128.v0;
sigZ = softfloat_shortShiftRight128(sigZ.v64, sigZ.v0, 1);
sig256Z[indexWord(4, 3)] = sigZ.v64;
sig256Z[indexWord(4, 2)] = sigZ.v0;
}
}
} else {
if (shiftDist) softfloat_add256M(sig256Z, sig256Z, sig256Z);
if (! expDiff) {
sigZ.v64 = sig256Z[indexWord(4, 3)];
sigZ.v0 = sig256Z[indexWord(4, 2)];
} else {
sig256C[indexWord(4, 3)] = sigC.v64;
sig256C[indexWord(4, 2)] = sigC.v0;
sig256C[indexWord(4, 1)] = 0;
sig256C[indexWord(4, 0)] = 0;
softfloat_shiftRightJam256M(sig256C, expDiff, sig256C);
}
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 8;
if (signZ == signC) {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (expDiff <= 0) {
sigZ = softfloat_add128(sigC.v64, sigC.v0, sigZ.v64, sigZ.v0);
} else {
softfloat_add256M(sig256Z, sig256C, sig256Z);
sigZ.v64 = sig256Z[indexWord(4, 3)];
sigZ.v0 = sig256Z[indexWord(4, 2)];
}
if (sigZ.v64 & UINT64_C(0x0200000000000000)) {
++expZ;
shiftDist = 9;
}
} else {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (expDiff < 0) {
signZ = signC;
if (expDiff < -1) {
sigZ = softfloat_sub128(sigC.v64, sigC.v0, sigZ.v64, sigZ.v0);
sigZExtra = sig256Z[indexWord(4, 1)] | sig256Z[indexWord(4, 0)];
if (sigZExtra) {
sigZ = softfloat_sub128(sigZ.v64, sigZ.v0, 0, 1);
}
if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) {
--expZ;
shiftDist = 7;
}
goto shiftRightRoundPack;
} else {
sig256C[indexWord(4, 3)] = sigC.v64;
sig256C[indexWord(4, 2)] = sigC.v0;
sig256C[indexWord(4, 1)] = 0;
sig256C[indexWord(4, 0)] = 0;
softfloat_sub256M(sig256C, sig256Z, sig256Z);
}
} else if (! expDiff) {
sigZ = softfloat_sub128(sigZ.v64, sigZ.v0, sigC.v64, sigC.v0);
if (! (sigZ.v64 | sigZ.v0) && ! sig256Z[indexWord(4, 1)] && ! sig256Z[indexWord(4, 0)]) {
goto completeCancellation;
}
sig256Z[indexWord(4, 3)] = sigZ.v64;
sig256Z[indexWord(4, 2)] = sigZ.v0;
if (sigZ.v64 & UINT64_C(0x8000000000000000)) {
signZ = ! signZ;
softfloat_sub256M(zero256, sig256Z, sig256Z);
}
} else {
softfloat_sub256M(sig256Z, sig256C, sig256Z);
if (1 < expDiff) {
sigZ.v64 = sig256Z[indexWord(4, 3)];
sigZ.v0 = sig256Z[indexWord(4, 2)];
if (! (sigZ.v64 & UINT64_C(0x0100000000000000))) {
--expZ;
shiftDist = 7;
}
goto sigZ;
}
}
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
sigZ.v64 = sig256Z[indexWord(4, 3)];
sigZ.v0 = sig256Z[indexWord(4, 2)];
sigZExtra = sig256Z[indexWord(4, 1)];
sig256Z0 = sig256Z[indexWord(4, 0)];
if (sigZ.v64) {
if (sig256Z0) sigZExtra |= 1;
} else {
expZ -= 64;
sigZ.v64 = sigZ.v0;
sigZ.v0 = sigZExtra;
sigZExtra = sig256Z0;
if (! sigZ.v64) {
expZ -= 64;
sigZ.v64 = sigZ.v0;
sigZ.v0 = sigZExtra;
sigZExtra = 0;
if (! sigZ.v64) {
expZ -= 64;
sigZ.v64 = sigZ.v0;
sigZ.v0 = 0;
}
}
}
shiftDist = softfloat_countLeadingZeros64(sigZ.v64);
expZ += 7 - shiftDist;
shiftDist = 15 - shiftDist;
if (0 < shiftDist) goto shiftRightRoundPack;
if (shiftDist) {
shiftDist = -shiftDist;
sigZ = softfloat_shortShiftLeft128(sigZ.v64, sigZ.v0, shiftDist);
x128 = softfloat_shortShiftLeft128(0, sigZExtra, shiftDist);
sigZ.v0 |= x128.v64;
sigZExtra = x128.v0;
}
goto roundPack;
}
sigZ:
sigZExtra = sig256Z[indexWord(4, 1)] | sig256Z[indexWord(4, 0)];
shiftRightRoundPack:
sigZExtra = (uint64_t) (sigZ.v0<<(64 - shiftDist)) | (sigZExtra != 0);
sigZ = softfloat_shortShiftRight128(sigZ.v64, sigZ.v0, shiftDist);
roundPack:
return softfloat_roundPackToF128(signZ, expZ - 1, sigZ.v64, sigZ.v0, sigZExtra, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
propagateNaN_ABC:
uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, uiB64, uiB0, status);
goto propagateNaN_ZC;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
infProdArg:
if ((sigC.v64 | sigC.v0) && expC == 0x7FFF) goto propagateNaN_ZC;
if (magBits) {
uiZ.v64 = packToF128UI64(signZ, 0x7FFF, 0);
uiZ.v0 = 0;
if (expC != 0x7FFF) return uiZ;
if (signZ == signC) return uiZ;
}
softfloat_raiseFlags(status, softfloat_flag_invalid);
uiZ.v64 = defaultNaNF128UI64;
uiZ.v0 = defaultNaNF128UI0;
propagateNaN_ZC:
uiZ = softfloat_propagateNaNF128UI(uiZ.v64, uiZ.v0, uiC64, uiC0, status);
return uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
zeroProd:
uiZ.v64 = uiC64;
uiZ.v0 = uiC0;
if (! (expC | sigC.v64 | sigC.v0) && (signZ != signC)) {
completeCancellation:
uiZ.v64 = packToF128UI64((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0);
uiZ.v0 = 0;
}
return uiZ;
}

View File

@@ -0,0 +1,142 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
float128_t
f128_roundToInt(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
int32_t exp;
struct uint128 uiZ;
uint64_t lastBitMask0, roundBitsMask;
bool roundNearEven;
uint64_t lastBitMask64;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.v64;
uiA0 = a.v0;
exp = expF128UI64(uiA64);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (0x402F <= exp) {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (0x406F <= exp) {
if ((exp == 0x7FFF) && (fracF128UI64(uiA64) | uiA0)) {
uiZ = softfloat_propagateNaNF128UI(uiA64, uiA0, 0, 0, status);
return uiZ;
}
return a;
}
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
lastBitMask0 = (uint64_t) 2<<(0x406E - exp);
roundBitsMask = lastBitMask0 - 1;
uiZ.v64 = uiA64;
uiZ.v0 = uiA0;
roundNearEven = (roundingMode == softfloat_round_near_even);
if (roundNearEven || (roundingMode == softfloat_round_near_maxMag)) {
if (exp == 0x402F) {
if (UINT64_C(0x8000000000000000) <= uiZ.v0) {
++uiZ.v64;
if (roundNearEven && (uiZ.v0 == UINT64_C(0x8000000000000000))) {
uiZ.v64 &= ~1;
}
}
} else {
uiZ = softfloat_add128(uiZ.v64, uiZ.v0, 0, lastBitMask0>>1);
if (roundNearEven && !(uiZ.v0 & roundBitsMask)) {
uiZ.v0 &= ~lastBitMask0;
}
}
} else if (roundingMode == (signF128UI64(uiZ.v64) ? softfloat_round_min : softfloat_round_max)) {
uiZ = softfloat_add128(uiZ.v64, uiZ.v0, 0, roundBitsMask);
}
uiZ.v0 &= ~roundBitsMask;
lastBitMask64 = !lastBitMask0;
} else {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (exp < 0x3FFF) {
if (!((uiA64 & UINT64_C(0x7FFFFFFFFFFFFFFF)) | uiA0)) return a;
if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
uiZ.v64 = uiA64 & packToF128UI64(1, 0, 0);
uiZ.v0 = 0;
switch (roundingMode) {
case softfloat_round_near_even:
if (!(fracF128UI64(uiA64) | uiA0)) break;
case softfloat_round_near_maxMag:
if (exp == 0x3FFE) uiZ.v64 |= packToF128UI64(0, 0x3FFF, 0);
break;
case softfloat_round_min:
if (uiZ.v64) uiZ.v64 = packToF128UI64(1, 0x3FFF, 0);
break;
case softfloat_round_max:
if (!uiZ.v64) uiZ.v64 = packToF128UI64(0, 0x3FFF, 0);
break;
}
return uiZ;
}
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
uiZ.v64 = uiA64;
uiZ.v0 = 0;
lastBitMask64 = (uint64_t) 1<<(0x402F - exp);
roundBitsMask = lastBitMask64 - 1;
if (roundingMode == softfloat_round_near_maxMag) {
uiZ.v64 += lastBitMask64>>1;
} else if (roundingMode == softfloat_round_near_even) {
uiZ.v64 += lastBitMask64>>1;
if (!((uiZ.v64 & roundBitsMask) | uiA0)) {
uiZ.v64 &= ~lastBitMask64;
}
} else if (roundingMode == (signF128UI64(uiZ.v64) ? softfloat_round_min : softfloat_round_max)) {
uiZ.v64 = (uiZ.v64 | (uiA0 != 0)) + roundBitsMask;
}
uiZ.v64 &= ~roundBitsMask;
lastBitMask0 = 0;
}
if ((uiZ.v64 != uiA64) || (uiZ.v0 != uiA0)) {
if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return uiZ;
}

View File

@@ -0,0 +1,94 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
extFloat80_t f128_to_extF80(float128_t a, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
bool sign;
int32_t exp;
uint64_t frac64, frac0;
struct commonNaN commonNaN;
struct uint128 uiZ;
uint16_t uiZ64;
uint64_t uiZ0;
struct exp32_sig128 normExpSig;
struct uint128 sig128;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.v64;
uiA0 = a.v0;
sign = signF128UI64(uiA64);
exp = expF128UI64(uiA64);
frac64 = fracF128UI64(uiA64);
frac0 = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp == 0x7FFF) {
if (frac64 | frac0) {
softfloat_f128UIToCommonNaN(uiA64, uiA0, &commonNaN, status);
uiZ = softfloat_commonNaNToExtF80UI(&commonNaN);
uiZ64 = uiZ.v64;
uiZ0 = uiZ.v0;
} else {
uiZ64 = packToExtF80UI64(sign, 0x7FFF);
uiZ0 = UINT64_C(0x8000000000000000);
}
return packToExtF80_twoargs(uiZ64, uiZ0);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! exp) {
if (! (frac64 | frac0)) {
return packToExtF80(sign, 0, 0);
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF128Sig(frac64, frac0);
exp = normExpSig.exp;
frac64 = normExpSig.sig.v64;
frac0 = normExpSig.sig.v0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sig128 = softfloat_shortShiftLeft128(frac64 | UINT64_C(0x0001000000000000), frac0, 15);
return softfloat_roundPackToExtF80(sign, exp, sig128.v64, sig128.v0, 80, status);
}

View File

@@ -0,0 +1,83 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
float32 f128_to_f32(float128_t a, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
bool sign;
int32_t exp;
uint64_t frac64;
struct commonNaN commonNaN;
uint32_t uiZ, frac32;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.v64;
uiA0 = a.v0;
sign = signF128UI64(uiA64);
exp = expF128UI64(uiA64);
frac64 = fracF128UI64(uiA64) | (uiA0 != 0);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp == 0x7FFF) {
if (frac64) {
softfloat_f128UIToCommonNaN(uiA64, uiA0, &commonNaN, status);
uiZ = softfloat_commonNaNToF32UI(&commonNaN);
} else {
uiZ = packToF32UI(sign, 0xFF, 0);
}
return uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
frac32 = softfloat_shortShiftRightJam64(frac64, 18);
if (! (exp | frac32)) {
return packToF32UI(sign, 0, 0);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
exp -= 0x3F81;
if (sizeof (int16_t) < sizeof (int32_t)) {
if (exp < -0x1000) exp = -0x1000;
}
return softfloat_roundPackToF32(sign, exp, frac32 | 0x40000000, status);
}

View File

@@ -0,0 +1,87 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
float64 f128_to_f64(float128_t a, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
bool sign;
int32_t exp;
uint64_t frac64, frac0;
struct commonNaN commonNaN;
uint64_t uiZ;
struct uint128 frac128;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.v64;
uiA0 = a.v0;
sign = signF128UI64(uiA64);
exp = expF128UI64(uiA64);
frac64 = fracF128UI64(uiA64);
frac0 = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp == 0x7FFF) {
if (frac64 | frac0) {
softfloat_f128UIToCommonNaN(uiA64, uiA0, &commonNaN, status);
uiZ = softfloat_commonNaNToF64UI(&commonNaN);
} else {
uiZ = packToF64UI(sign, 0x7FF, 0);
}
return uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
frac128 = softfloat_shortShiftLeft128(frac64, frac0, 14);
frac64 = frac128.v64 | (frac128.v0 != 0);
if (! (exp | frac64)) {
return packToF64UI(sign, 0, 0);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
exp -= 0x3C01;
if (sizeof (int16_t) < sizeof (int32_t)) {
if (exp < -0x1000) exp = -0x1000;
}
return
softfloat_roundPackToF64(sign, exp, frac64 | UINT64_C(0x4000000000000000), status);
}

View File

@@ -0,0 +1,80 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
int32_t f128_to_i32(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
bool sign;
int32_t exp;
uint64_t sig64, sig0;
int32_t shiftDist;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.v64;
uiA0 = a.v0;
sign = signF128UI64(uiA64);
exp = expF128UI64(uiA64);
sig64 = fracF128UI64(uiA64);
sig0 = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
#if (i32_fromNaN != i32_fromPosOverflow) || (i32_fromNaN != i32_fromNegOverflow)
if ((exp == 0x7FFF) && (sig64 | sig0)) {
#if (i32_fromNaN == i32_fromPosOverflow)
sign = 0;
#elif (i32_fromNaN == i32_fromNegOverflow)
sign = 1;
#else
softfloat_raiseFlags(status, softfloat_flag_invalid);
return i32_fromNaN;
#endif
}
#endif
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp) sig64 |= UINT64_C(0x0001000000000000);
sig64 |= (sig0 != 0);
shiftDist = 0x4023 - exp;
if (0 < shiftDist) sig64 = softfloat_shiftRightJam64(sig64, shiftDist);
return softfloat_roundToI32(sign, sig64, roundingMode, exact, status);
}

View File

@@ -0,0 +1,89 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
int32_t f128_to_i32_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
int32_t exp;
uint64_t sig64;
int32_t shiftDist;
bool sign;
int32_t absZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.v64;
uiA0 = a.v0;
exp = expF128UI64(uiA64);
sig64 = fracF128UI64(uiA64) | (uiA0 != 0);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x402F - exp;
if (49 <= shiftDist) {
if (exact && (exp | sig64)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signF128UI64(uiA64);
if (shiftDist < 18) {
if (sign && (shiftDist == 17) && (sig64 < UINT64_C(0x0000000000020000))) {
if (exact && sig64) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return -0x7FFFFFFF - 1;
}
softfloat_raiseFlags(status, softfloat_flag_invalid);
return
(exp == 0x7FFF) && sig64 ? i32_fromNaN
: sign ? i32_fromNegOverflow : i32_fromPosOverflow;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sig64 |= UINT64_C(0x0001000000000000);
absZ = sig64>>shiftDist;
if (exact && ((uint64_t) (uint32_t) absZ<<shiftDist != sig64)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return sign ? -absZ : absZ;
}

View File

@@ -0,0 +1,90 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
int64_t f128_to_i64(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
bool sign;
int32_t exp;
uint64_t sig64, sig0;
int32_t shiftDist;
struct uint128 sig128;
struct uint64_extra sigExtra;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.v64;
uiA0 = a.v0;
sign = signF128UI64(uiA64);
exp = expF128UI64(uiA64);
sig64 = fracF128UI64(uiA64);
sig0 = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x402F - exp;
if (shiftDist <= 0) {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (shiftDist < -15) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return
(exp == 0x7FFF) && (sig64 | sig0) ? i64_fromNaN
: sign ? i64_fromNegOverflow : i64_fromPosOverflow;
}
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
sig64 |= UINT64_C(0x0001000000000000);
if (shiftDist) {
sig128 = softfloat_shortShiftLeft128(sig64, sig0, -shiftDist);
sig64 = sig128.v64;
sig0 = sig128.v0;
}
} else {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (exp) sig64 |= UINT64_C(0x0001000000000000);
sigExtra = softfloat_shiftRightJam64Extra(sig64, sig0, shiftDist);
sig64 = sigExtra.v;
sig0 = sigExtra.extra;
}
return softfloat_roundToI64(sign, sig64, sig0, roundingMode, exact, status);
}

View File

@@ -0,0 +1,104 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
int64_t f128_to_i64_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
bool sign;
int32_t exp;
uint64_t sig64, sig0;
int32_t shiftDist;
int8_t negShiftDist;
uint64_t absZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.v64;
uiA0 = a.v0;
sign = signF128UI64(uiA64);
exp = expF128UI64(uiA64);
sig64 = fracF128UI64(uiA64);
sig0 = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x402F - exp;
if (shiftDist < 0) {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (shiftDist < -14) {
if ((uiA64 == UINT64_C(0xC03E000000000000)) && (sig0 < UINT64_C(0x0002000000000000))) {
if (exact && sig0) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return -INT64_C(0x7FFFFFFFFFFFFFFF) - 1;
}
softfloat_raiseFlags(status, softfloat_flag_invalid);
return (exp == 0x7FFF) && (sig64 | sig0)
? i64_fromNaN
: sign ? i64_fromNegOverflow : i64_fromPosOverflow;
}
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
sig64 |= UINT64_C(0x0001000000000000);
negShiftDist = -shiftDist;
absZ = sig64<<negShiftDist | sig0>>(shiftDist & 63);
if (exact && (uint64_t) (sig0<<negShiftDist)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
} else {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (49 <= shiftDist) {
if (exact && (exp | sig64 | sig0)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return 0;
}
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
sig64 |= UINT64_C(0x0001000000000000);
absZ = sig64>>shiftDist;
if (exact && (sig0 || (absZ<<shiftDist != sig64))) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
}
return sign ? -absZ : absZ;
}

View File

@@ -0,0 +1,81 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
uint32_t f128_to_ui32(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
bool sign;
int32_t exp;
uint64_t sig64;
int32_t shiftDist;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.v64;
uiA0 = a.v0;
sign = signF128UI64(uiA64);
exp = expF128UI64(uiA64);
sig64 = fracF128UI64(uiA64) | (uiA0 != 0);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
#if (ui32_fromNaN != ui32_fromPosOverflow) || (ui32_fromNaN != ui32_fromNegOverflow)
if ((exp == 0x7FFF) && sig64) {
#if (ui32_fromNaN == ui32_fromPosOverflow)
sign = 0;
#elif (ui32_fromNaN == ui32_fromNegOverflow)
sign = 1;
#else
softfloat_raiseFlags(status, softfloat_flag_invalid);
return ui32_fromNaN;
#endif
}
#endif
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp) sig64 |= UINT64_C(0x0001000000000000);
shiftDist = 0x4023 - exp;
if (0 < shiftDist) {
sig64 = softfloat_shiftRightJam64(sig64, shiftDist);
}
return softfloat_roundToUI32(sign, sig64, roundingMode, exact, status);
}

View File

@@ -0,0 +1,83 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
uint32_t f128_to_ui32_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
int32_t exp;
uint64_t sig64;
int32_t shiftDist;
bool sign;
uint32_t z;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.v64;
uiA0 = a.v0;
exp = expF128UI64(uiA64);
sig64 = fracF128UI64(uiA64) | (uiA0 != 0);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x402F - exp;
if (49 <= shiftDist) {
if (exact && (exp | sig64)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signF128UI64(uiA64);
if (sign || (shiftDist < 17)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return
(exp == 0x7FFF) && sig64 ? ui32_fromNaN
: sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sig64 |= UINT64_C(0x0001000000000000);
z = sig64>>shiftDist;
if (exact && ((uint64_t) z<<shiftDist != sig64)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return z;
}

View File

@@ -0,0 +1,90 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
uint64_t f128_to_ui64(float128_t a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
bool sign;
int32_t exp;
uint64_t sig64, sig0;
int32_t shiftDist;
struct uint128 sig128;
struct uint64_extra sigExtra;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.v64;
uiA0 = a.v0;
sign = signF128UI64(uiA64);
exp = expF128UI64(uiA64);
sig64 = fracF128UI64(uiA64);
sig0 = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x402F - exp;
if (shiftDist <= 0) {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (shiftDist < -15) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return
(exp == 0x7FFF) && (sig64 | sig0) ? ui64_fromNaN
: sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
}
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
sig64 |= UINT64_C(0x0001000000000000);
if (shiftDist) {
sig128 = softfloat_shortShiftLeft128(sig64, sig0, -shiftDist);
sig64 = sig128.v64;
sig0 = sig128.v0;
}
} else {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (exp) sig64 |= UINT64_C(0x0001000000000000);
sigExtra = softfloat_shiftRightJam64Extra(sig64, sig0, shiftDist);
sig64 = sigExtra.v;
sig0 = sigExtra.extra;
}
return softfloat_roundToUI64(sign, sig64, sig0, roundingMode, exact, status);
}

View File

@@ -0,0 +1,99 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
uint64_t f128_to_ui64_r_minMag(float128_t a, bool exact, struct softfloat_status_t *status)
{
uint64_t uiA64, uiA0;
bool sign;
int32_t exp;
uint64_t sig64, sig0;
int32_t shiftDist;
int8_t negShiftDist;
uint64_t z;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA64 = a.v64;
uiA0 = a.v0;
sign = signF128UI64(uiA64);
exp = expF128UI64(uiA64);
sig64 = fracF128UI64(uiA64);
sig0 = uiA0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = 0x402F - exp;
if (shiftDist < 0) {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (sign || (shiftDist < -15)) goto invalid;
sig64 |= UINT64_C(0x0001000000000000);
negShiftDist = -shiftDist;
z = sig64<<negShiftDist | sig0>>(shiftDist & 63);
if (exact && (uint64_t) (sig0<<negShiftDist)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
} else {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (49 <= shiftDist) {
if (exact && (exp | sig64 | sig0)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return 0;
}
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (sign) goto invalid;
sig64 |= UINT64_C(0x0001000000000000);
z = sig64>>shiftDist;
if (exact && (sig0 || (z<<shiftDist != sig64))) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
}
return z;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
invalid:
softfloat_raiseFlags(status, softfloat_flag_invalid);
return
(exp == 0x7FFF) && (sig64 | sig0) ? ui64_fromNaN
: sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
}

View File

@@ -0,0 +1,60 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "softfloat.h"
extern float16 softfloat_addMagsF16(uint16_t, uint16_t, struct softfloat_status_t *);
extern float16 softfloat_subMagsF16(uint16_t, uint16_t, struct softfloat_status_t *);
float16 f16_add(float16 a, float16 b, struct softfloat_status_t *status)
{
if (signF16UI((uint16_t) a ^ (uint16_t) b)) {
return softfloat_subMagsF16(a, b, status);
} else {
return softfloat_addMagsF16(a, b, status);
}
}
float16 f16_sub(float16 a, float16 b, struct softfloat_status_t *status)
{
if (signF16UI((uint16_t) a ^ (uint16_t) b)) {
return softfloat_addMagsF16(a, b, status);
} else {
return softfloat_subMagsF16(a, b, status);
}
}

View File

@@ -0,0 +1,64 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "softfloat.h"
softfloat_class_t f16_class(float16 a)
{
bool signA;
int8_t expA;
uint16_t sigA;
signA = signF16UI(a);
expA = expF16UI(a);
sigA = fracF16UI(a);
if (expA == 0x1F) {
if (sigA == 0)
return (signA) ? softfloat_negative_inf : softfloat_positive_inf;
return (sigA & 0x200) ? softfloat_QNaN : softfloat_SNaN;
}
if (expA == 0) {
if (sigA == 0) return softfloat_zero;
return softfloat_denormal;
}
return softfloat_normalized;
}

View File

@@ -0,0 +1,92 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Compare between two half precision floating point numbers. Returns
| 'float_relation_equal' if the operands are equal, 'float_relation_less' if
| the value 'a' is less than the corresponding value `b',
| 'float_relation_greater' if the value 'a' is greater than the corresponding
| value `b', or 'float_relation_unordered' otherwise.
*----------------------------------------------------------------------------*/
int f16_compare(float16 a, float16 b, bool quiet, struct softfloat_status_t *status)
{
softfloat_class_t aClass;
softfloat_class_t bClass;
bool signA;
bool signB;
aClass = f16_class(a);
bClass = f16_class(b);
if (aClass == softfloat_SNaN || bClass == softfloat_SNaN) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return softfloat_relation_unordered;
}
if (aClass == softfloat_QNaN || bClass == softfloat_QNaN) {
if (! quiet) softfloat_raiseFlags(status, softfloat_flag_invalid);
return softfloat_relation_unordered;
}
if (aClass == softfloat_denormal) {
if (softfloat_denormalsAreZeros(status))
a = a & 0x8000;
else
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
if (bClass == softfloat_denormal) {
if (softfloat_denormalsAreZeros(status))
b = b & 0x8000;
else
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
if ((a == b) || ((uint16_t) ((a | b)<<1) == 0)) return softfloat_relation_equal;
signA = signF16UI(a);
signB = signF16UI(b);
if (signA != signB)
return (signA) ? softfloat_relation_less : softfloat_relation_greater;
if (signA ^ (a < b)) return softfloat_relation_less;
return softfloat_relation_greater;
}

View File

@@ -0,0 +1,149 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
#define SOFTFLOAT_FAST_DIV32TO16 1
extern const uint16_t softfloat_approxRecip_1k0s[];
extern const uint16_t softfloat_approxRecip_1k1s[];
float16 f16_div(float16 a, float16 b, struct softfloat_status_t *status)
{
bool signA;
int8_t expA;
uint16_t sigA;
bool signB;
int8_t expB;
uint16_t sigB;
bool signZ;
struct exp8_sig16 normExpSig;
int8_t expZ;
#ifdef SOFTFLOAT_FAST_DIV32TO16
uint32_t sig32A;
uint16_t sigZ;
#endif
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
signA = signF16UI(a);
expA = expF16UI(a);
sigA = fracF16UI(a);
signB = signF16UI(b);
expB = expF16UI(b);
sigB = fracF16UI(b);
signZ = signA ^ signB;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (softfloat_denormalsAreZeros(status)) {
if (!expA) sigA = 0;
if (!expB) sigB = 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0x1F) {
if (sigA) goto propagateNaN;
if (expB == 0x1F) {
if (sigB) goto propagateNaN;
goto invalid;
}
if (sigB && !expB)
softfloat_raiseFlags(status, softfloat_flag_denormal);
goto infinity;
}
if (expB == 0x1F) {
if (sigB) goto propagateNaN;
if (sigA && !expA)
softfloat_raiseFlags(status, softfloat_flag_denormal);
goto zero;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expB) {
if (! sigB) {
if (! (expA | sigA)) goto invalid;
softfloat_raiseFlags(status, softfloat_flag_infinite);
goto infinity;
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF16Sig(sigB);
expB = normExpSig.exp;
sigB = normExpSig.sig;
}
if (! expA) {
if (! sigA) goto zero;
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF16Sig(sigA);
expA = normExpSig.exp;
sigA = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expZ = expA - expB + 0xE;
sigA |= 0x0400;
sigB |= 0x0400;
#ifdef SOFTFLOAT_FAST_DIV32TO16
if (sigA < sigB) {
--expZ;
sig32A = (uint32_t) sigA<<15;
} else {
sig32A = (uint32_t) sigA<<14;
}
sigZ = sig32A / sigB;
if (! (sigZ & 7)) sigZ |= ((uint32_t) sigB * sigZ != sig32A);
#endif
return softfloat_roundPackToF16(signZ, expZ, sigZ, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
propagateNaN:
return softfloat_propagateNaNF16UI(a, b, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
invalid:
softfloat_raiseFlags(status, softfloat_flag_invalid);
return defaultNaNF16UI;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
infinity:
return packToF16UI(signZ, 0x1F, 0);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
zero:
return packToF16UI(signZ, 0, 0);
}

View File

@@ -0,0 +1,73 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Extracts the exponent portion of half-precision floating-point value 'a',
| and returns the result as a half-precision floating-point value
| representing unbiased integer exponent. The operation is performed according
| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
float16 f16_getExp(float16 a, struct softfloat_status_t *status)
{
int8_t expA;
uint16_t sigA;
struct exp8_sig16 normExpSig;
expA = expF16UI(a);
sigA = fracF16UI(a);
if (expA == 0x1F) {
if (sigA) return softfloat_propagateNaNF16UI(a, 0, status);
return (float16)packToF32UI(0, 0x1F, 0);
}
if (! expA) {
if (! sigA || softfloat_denormalsAreZeros(status))
return (float16)packToF32UI(1, 0x1F, 0);
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF16Sig(sigA);
expA = normExpSig.exp;
}
return i32_to_f16((int32_t)(expA) - 0xF, status);
}

View File

@@ -0,0 +1,108 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Extracts the mantissa of half-precision floating-point value 'a' and
| returns the result as a half-precision floating-point after applying
| the mantissa interval normalization and sign control. The operation is
| performed according to the IEC/IEEE Standard for Binary Floating-Point
| Arithmetic.
*----------------------------------------------------------------------------*/
float16 f16_getMant(float16 a, struct softfloat_status_t *status, int sign_ctrl, int interv)
{
bool signA;
int8_t expA;
uint16_t sigA;
struct exp8_sig16 normExpSig;
signA = signF16UI(a);
expA = expF16UI(a);
sigA = fracF16UI(a);
if (expA == 0x1F) {
if (sigA) return softfloat_propagateNaNF16UI(a, 0, status);
if (signA) {
if (sign_ctrl & 0x2) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return defaultNaNF16UI;
}
}
return packToF16UI(~sign_ctrl & signA, 0x1F, 0);
}
if (! expA && (! sigA || softfloat_denormalsAreZeros(status))) {
return packToF16UI(~sign_ctrl & signA, 0x1F, 0);
}
if (signA) {
if (sign_ctrl & 0x2) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return defaultNaNF16UI;
}
}
if (expA == 0) {
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF16Sig(sigA);
expA = normExpSig.exp;
sigA = normExpSig.sig;
sigA &= 0x3ff;
}
switch(interv) {
case 0x0: // interval [1,2)
expA = 0xF;
break;
case 0x1: // interval [1/2,2)
expA -= 0xF;
expA = 0xF - (expA & 0x1);
break;
case 0x2: // interval [1/2,1)
expA = 0xE;
break;
case 0x3: // interval [3/4,3/2)
expA = 0xF - ((sigA >> 9) & 0x1);
break;
}
return packToF16UI(~sign_ctrl & signA, expA, sigA);
}

View File

@@ -0,0 +1,69 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Compare between two half precision floating point numbers and return the
| smaller of them.
*----------------------------------------------------------------------------*/
float16 f16_min(float16 a, float16 b, struct softfloat_status_t *status)
{
if (softfloat_denormalsAreZeros(status)) {
a = f16_denormal_to_zero(a);
b = f16_denormal_to_zero(b);
}
return (f16_compare_normal(a, b, status) == softfloat_relation_less) ? a : b;
}
/*----------------------------------------------------------------------------
| Compare between two half precision floating point numbers and return the
| larger of them.
*----------------------------------------------------------------------------*/
float16 f16_max(float16 a, float16 b, struct softfloat_status_t *status)
{
if (softfloat_denormalsAreZeros(status)) {
a = f16_denormal_to_zero(a);
b = f16_denormal_to_zero(b);
}
return (f16_compare_normal(a, b, status) == softfloat_relation_greater) ? a : b;
}

View File

@@ -0,0 +1,139 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
float16 f16_mul(float16 a, float16 b, struct softfloat_status_t *status)
{
bool signA;
int8_t expA;
uint16_t sigA;
bool signB;
int8_t expB;
uint16_t sigB;
bool signZ;
uint16_t magBits;
struct exp8_sig16 normExpSig;
int8_t expZ;
uint32_t sig32Z;
uint16_t sigZ, uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
signA = signF16UI(a);
expA = expF16UI(a);
sigA = fracF16UI(a);
signB = signF16UI(b);
expB = expF16UI(b);
sigB = fracF16UI(b);
signZ = signA ^ signB;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (softfloat_denormalsAreZeros(status)) {
if (!expA) sigA = 0;
if (!expB) sigB = 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0x1F) {
if (sigA || ((expB == 0x1F) && sigB)) goto propagateNaN;
magBits = expB | sigB;
if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
goto infArg;
}
if (expB == 0x1F) {
if (sigB) goto propagateNaN;
magBits = expA | sigA;
if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal);
goto infArg;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expA) {
if (! sigA) {
if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
goto zero;
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF16Sig(sigA);
expA = normExpSig.exp;
sigA = normExpSig.sig;
}
if (! expB) {
if (! sigB) {
if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
goto zero;
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF16Sig(sigB);
expB = normExpSig.exp;
sigB = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expZ = expA + expB - 0xF;
sigA = (sigA | 0x0400)<<4;
sigB = (sigB | 0x0400)<<5;
sig32Z = (uint32_t) sigA * sigB;
sigZ = sig32Z>>16;
if (sig32Z & 0xFFFF) sigZ |= 1;
if (sigZ < 0x4000) {
--expZ;
sigZ <<= 1;
}
return softfloat_roundPackToF16(signZ, expZ, sigZ, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
propagateNaN:
return softfloat_propagateNaNF16UI(a, b, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
infArg:
if (! magBits) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
uiZ = defaultNaNF16UI;
} else {
uiZ = packToF16UI(signZ, 0x1F, 0);
}
return uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
zero:
return packToF16UI(signZ, 0, 0);
}

View File

@@ -0,0 +1,232 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "softfloat.h"
#include "specialize.h"
float16 f16_mulAdd(float16 a, float16 b, float16 c, uint8_t op, struct softfloat_status_t *status)
{
bool signA;
int8_t expA;
uint16_t sigA;
bool signB;
int8_t expB;
uint16_t sigB;
bool signC;
int8_t expC;
uint16_t sigC;
bool signProd;
uint16_t magBits, uiA, uiB, uiC, uiZ;
struct exp8_sig16 normExpSig;
int8_t expProd;
uint32_t sigProd;
bool signZ;
int8_t expZ;
uint16_t sigZ;
int8_t expDiff;
uint32_t sig32Z, sig32C;
int8_t shiftDist;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA = a;
uiB = b;
uiC = c;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
signA = signF16UI(uiA);
expA = expF16UI(uiA);
sigA = fracF16UI(uiA);
signB = signF16UI(uiB);
expB = expF16UI(uiB);
sigB = fracF16UI(uiB);
signC = signF16UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0);
expC = expF16UI(uiC);
sigC = fracF16UI(uiC);
signProd = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
bool aisNaN = (expA == 0x1F) && sigA;
bool bisNaN = (expB == 0x1F) && sigB;
bool cisNaN = (expC == 0x1F) && sigC;
if (aisNaN | bisNaN | cisNaN) {
uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF16UI(uiA, uiB, status) : 0;
return softfloat_propagateNaNF16UI(uiZ, uiC, status);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (softfloat_denormalsAreZeros(status)) {
if (!expA) sigA = 0;
if (!expB) sigB = 0;
if (!expC) sigC = 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0x1F) {
magBits = expB | sigB;
goto infProdArg;
}
if (expB == 0x1F) {
magBits = expA | sigA;
goto infProdArg;
}
if (expC == 0x1F) {
if ((sigA && !expA) || (sigB && !expB)) {
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
return packToF16UI(signC, 0x1F, 0);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expA) {
if (! sigA) goto zeroProd;
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF16Sig(sigA);
expA = normExpSig.exp;
sigA = normExpSig.sig;
}
if (! expB) {
if (! sigB) goto zeroProd;
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF16Sig(sigB);
expB = normExpSig.exp;
sigB = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expProd = expA + expB - 0xE;
sigA = (sigA | 0x0400)<<4;
sigB = (sigB | 0x0400)<<4;
sigProd = (uint32_t) sigA * sigB;
if (sigProd < 0x20000000) {
--expProd;
sigProd <<= 1;
}
signZ = signProd;
if (! expC) {
if (! sigC) {
expZ = expProd - 1;
sigZ = sigProd>>15 | ((sigProd & 0x7FFF) != 0);
goto roundPack;
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF16Sig(sigC);
expC = normExpSig.exp;
sigC = normExpSig.sig;
}
sigC = (sigC | 0x0400)<<3;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expDiff = expProd - expC;
if (signProd == signC) {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (expDiff <= 0) {
expZ = expC;
sigZ = sigC + softfloat_shiftRightJam32(sigProd, 16 - expDiff);
} else {
expZ = expProd;
sig32Z = sigProd + softfloat_shiftRightJam32((uint32_t) sigC<<16, expDiff);
sigZ = sig32Z>>16 | ((sig32Z & 0xFFFF) != 0);
}
if (sigZ < 0x4000) {
--expZ;
sigZ <<= 1;
}
} else {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
sig32C = (uint32_t) sigC<<16;
if (expDiff < 0) {
signZ = signC;
expZ = expC;
sig32Z = sig32C - softfloat_shiftRightJam32(sigProd, -expDiff);
} else if (! expDiff) {
expZ = expProd;
sig32Z = sigProd - sig32C;
if (! sig32Z) goto completeCancellation;
if (sig32Z & 0x80000000) {
signZ = ! signZ;
sig32Z = -sig32Z;
}
} else {
expZ = expProd;
sig32Z = sigProd - softfloat_shiftRightJam32(sig32C, expDiff);
}
shiftDist = softfloat_countLeadingZeros32(sig32Z) - 1;
expZ -= shiftDist;
shiftDist -= 16;
if (shiftDist < 0) {
sigZ = sig32Z>>(-shiftDist) | ((uint32_t) (sig32Z<<(shiftDist & 31)) != 0);
} else {
sigZ = (uint16_t) sig32Z<<shiftDist;
}
}
roundPack:
return softfloat_roundPackToF16(signZ, expZ, sigZ, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
infProdArg:
if (magBits) {
uiZ = packToF16UI(signProd, 0x1F, 0);
if (signProd == signC || expC != 0x1F) {
if ((sigA && !expA) || (sigB && !expB) || (sigC && !expC))
softfloat_raiseFlags(status, softfloat_flag_denormal);
return uiZ;
}
}
softfloat_raiseFlags(status, softfloat_flag_invalid);
uiZ = defaultNaNF16UI;
return softfloat_propagateNaNF16UI(uiZ, uiC, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
zeroProd:
uiZ = packToF16UI(signC, expC, sigC);
if (!expC && sigC) {
/* Exact zero plus a denormal */
softfloat_raiseFlags(status, softfloat_flag_denormal);
if (softfloat_flushUnderflowToZero(status)) {
softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact);
return packToF16UI(signC, 0, 0);
}
}
if (! (expC | sigC) && (signProd != signC)) {
completeCancellation:
uiZ = packToF16UI((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0);
}
return uiZ;
}

View File

@@ -0,0 +1,135 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
float16 f16_range(float16 a, float16 b, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *status)
{
bool signA;
int8_t expA;
uint16_t sigA;
bool signB;
int8_t expB;
uint16_t sigB;
bool aIsNaN, bIsNaN;
uint16_t z;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
signA = signF16UI(a);
expA = expF16UI(a);
sigA = fracF16UI(a);
signB = signF16UI(b);
expB = expF16UI(b);
sigB = fracF16UI(b);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (softfloat_isSigNaNF16UI(a)) {
return softfloat_propagateNaNF16UI(a, 0, status);
}
if (softfloat_isSigNaNF16UI(b)) {
return softfloat_propagateNaNF16UI(b, 0, status);
}
aIsNaN = isNaNF16UI(a);
bIsNaN = isNaNF16UI(b);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expA && sigA) {
if (softfloat_denormalsAreZeros(status)) {
a = packToF16UI(signA, 0, 0);
}
else if (! bIsNaN) {
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
}
if (! expB && sigB) {
if (softfloat_denormalsAreZeros(status)) {
b = packToF16UI(signB, 0, 0);
}
else if (! aIsNaN) {
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (bIsNaN) {
z = a;
}
else if (aIsNaN) {
z = b;
}
else if (signA != signB && ! is_abs) {
if (! is_max) {
z = signA ? a : b;
} else {
z = signA ? b : a;
}
} else {
float16 tmp_a = a, tmp_b = b;
if (is_abs) {
tmp_a = tmp_a & ~0x8000; // clear the sign bit
tmp_b = tmp_b & ~0x8000;
signA = 0;
}
if (! is_max) {
z = (signA ^ (tmp_a < tmp_b)) ? a : b;
} else {
z = (signA ^ (tmp_a < tmp_b)) ? b : a;
}
}
switch(sign_ctrl) {
case 0:
z = (z & ~0x8000) | (a & 0x8000); // keep sign of a
break;
case 1:
break; // preserve sign of compare result
case 2:
z = z & ~0x8000; // zero out the sign bit
break;
case 3:
z = z | 0x8000; // set the sign bit
break;
}
return z;
}

View File

@@ -0,0 +1,112 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2017 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
float16 f16_roundToInt(float16 a, uint8_t scale, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
int8_t exp;
uint16_t frac;
bool sign;
uint16_t uiZ, lastBitMask, roundBitsMask;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
scale &= 0xF;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
exp = expF16UI(a);
frac = fracF16UI(a);
sign = signF16UI(a);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (0x19 <= (exp + scale)) {
if ((exp == 0x1F) && frac) {
return softfloat_propagateNaNF16UI(a, 0, status);
}
return a;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (softfloat_denormalsAreZeros(status)) {
if (!exp) {
frac = 0;
a = packToF16UI(sign, 0, 0);
}
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ((exp + scale) <= 0xE) {
if (!(exp | frac)) return a;
if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
uiZ = packToF16UI(sign, 0, 0);
switch (roundingMode) {
case softfloat_round_near_even:
if (!frac) break;
case softfloat_round_near_maxMag:
if ((exp + scale) == 0xE) uiZ |= packToF16UI(0, 0xF - scale, 0);
break;
case softfloat_round_min:
if (uiZ) uiZ = packToF16UI(1, 0xF - scale, 0);
break;
case softfloat_round_max:
if (!uiZ) uiZ = packToF16UI(0, 0xF - scale, 0);
break;
}
return uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiZ = a;
lastBitMask = (uint16_t) 1<<(0x19 - exp - scale);
roundBitsMask = lastBitMask - 1;
if (roundingMode == softfloat_round_near_maxMag) {
uiZ += lastBitMask>>1;
} else if (roundingMode == softfloat_round_near_even) {
uiZ += lastBitMask>>1;
if (!(uiZ & roundBitsMask)) uiZ &= ~lastBitMask;
} else if (roundingMode == (signF16UI(uiZ) ? softfloat_round_min : softfloat_round_max)) {
uiZ += roundBitsMask;
}
uiZ &= ~roundBitsMask;
if (uiZ != a) {
if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return uiZ;
}

View File

@@ -0,0 +1,130 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
extern const uint16_t softfloat_approxRecipSqrt_1k0s[];
extern const uint16_t softfloat_approxRecipSqrt_1k1s[];
float16 f16_sqrt(float16 a, struct softfloat_status_t *status)
{
bool signA;
int8_t expA;
uint16_t sigA;
struct exp8_sig16 normExpSig;
int8_t expZ;
int index;
uint16_t r0;
uint32_t ESqrR0;
uint16_t sigma0;
uint16_t recipSqrt16, sigZ, shiftedSigZ;
uint16_t negRem;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
signA = signF16UI(a);
expA = expF16UI(a);
sigA = fracF16UI(a);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0x1F) {
if (sigA) {
return softfloat_propagateNaNF16UI(a, 0, status);
}
if (! signA) return a;
goto invalid;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (softfloat_denormalsAreZeros(status)) {
if (!expA) {
sigA = 0;
a = packToF16UI(signA, 0, 0);
}
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (signA) {
if (! (expA | sigA)) return a;
goto invalid;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expA) {
if (! sigA) return a;
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF16Sig(sigA);
expA = normExpSig.exp;
sigA = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expZ = ((expA - 0xF)>>1) + 0xE;
expA &= 1;
sigA |= 0x0400;
index = (sigA>>6 & 0xE) + expA;
r0 = softfloat_approxRecipSqrt_1k0s[index]
- (((uint32_t) softfloat_approxRecipSqrt_1k1s[index] * (sigA & 0x7F)) >>11);
ESqrR0 = ((uint32_t) r0 * r0)>>1;
if (expA) ESqrR0 >>= 1;
sigma0 = ~(uint16_t) ((ESqrR0 * sigA)>>16);
recipSqrt16 = r0 + (((uint32_t) r0 * sigma0)>>25);
if (! (recipSqrt16 & 0x8000)) recipSqrt16 = 0x8000;
sigZ = ((uint32_t) (sigA<<5) * recipSqrt16)>>16;
if (expA) sigZ >>= 1;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
++sigZ;
if (! (sigZ & 7)) {
shiftedSigZ = sigZ>>1;
negRem = shiftedSigZ * shiftedSigZ;
sigZ &= ~1;
if (negRem & 0x8000) {
sigZ |= 1;
} else {
if (negRem) --sigZ;
}
}
return softfloat_roundPackToF16(0, expZ, sigZ, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
invalid:
softfloat_raiseFlags(status, softfloat_flag_invalid);
return defaultNaNF16UI;
}

View File

@@ -0,0 +1,88 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
extFloat80_t f16_to_extF80(float16 a, struct softfloat_status_t *status)
{
bool sign;
int8_t exp;
uint16_t frac;
struct commonNaN commonNaN;
struct uint128 uiZ;
uint16_t uiZ64;
uint64_t uiZ0;
struct exp8_sig16 normExpSig;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signF16UI(a);
exp = expF16UI(a);
frac = fracF16UI(a);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp == 0x1F) {
if (frac) {
softfloat_f16UIToCommonNaN(a, &commonNaN, status);
uiZ = softfloat_commonNaNToExtF80UI(&commonNaN);
uiZ64 = uiZ.v64;
uiZ0 = uiZ.v0;
} else {
uiZ64 = packToExtF80UI64(sign, 0x7FFF);
uiZ0 = UINT64_C(0x8000000000000000);
}
return packToExtF80_twoargs(uiZ64, uiZ0);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! exp) {
if (! frac) {
return packToExtF80(sign, 0, 0);
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF16Sig(frac);
exp = normExpSig.exp;
frac = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiZ64 = packToExtF80UI64(sign, exp + 0x3FF0);
uiZ0 = (uint64_t) (frac | 0x0400)<<53;
return packToExtF80_twoargs(uiZ64, uiZ0);
}

View File

@@ -0,0 +1,81 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
float32 f16_to_f32(float16 a, struct softfloat_status_t *status)
{
bool sign;
int8_t exp;
uint16_t frac;
struct commonNaN commonNaN;
uint32_t uiZ;
struct exp8_sig16 normExpSig;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signF16UI(a);
exp = expF16UI(a);
frac = fracF16UI(a);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp == 0x1F) {
if (frac) {
softfloat_f16UIToCommonNaN(a, &commonNaN, status);
uiZ = softfloat_commonNaNToF32UI(&commonNaN);
} else {
uiZ = packToF32UI(sign, 0xFF, 0);
}
return uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! exp) {
if (! frac || softfloat_denormalsAreZeros(status)) {
return packToF32UI(sign, 0, 0);
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF16Sig(frac);
exp = normExpSig.exp - 1;
frac = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
return packToF32UI(sign, exp + 0x70, (uint32_t) frac<<13);
}

View File

@@ -0,0 +1,81 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
float64 f16_to_f64(float16 a, struct softfloat_status_t *status)
{
bool sign;
int8_t exp;
uint16_t frac;
struct commonNaN commonNaN;
uint64_t uiZ;
struct exp8_sig16 normExpSig;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signF16UI(a);
exp = expF16UI(a);
frac = fracF16UI(a);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp == 0x1F) {
if (frac) {
softfloat_f16UIToCommonNaN(a, &commonNaN, status);
uiZ = softfloat_commonNaNToF64UI(&commonNaN);
} else {
uiZ = packToF64UI(sign, 0x7FF, 0);
}
return uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! exp) {
if (! frac || softfloat_denormalsAreZeros(status)) {
return packToF64UI(sign, 0, 0);
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF16Sig(frac);
exp = normExpSig.exp - 1;
frac = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
return packToF64UI(sign, exp + 0x3F0, (uint64_t) frac<<42);
}

View File

@@ -0,0 +1,81 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
int32_t f16_to_i32(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
bool sign;
int8_t exp;
uint16_t frac;
int32_t sig32;
int8_t shiftDist;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signF16UI(a);
exp = expF16UI(a);
frac = fracF16UI(a);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp == 0x1F) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return
frac ? i32_fromNaN
: sign ? i32_fromNegOverflow : i32_fromPosOverflow;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sig32 = frac;
if (exp) {
sig32 |= 0x0400;
shiftDist = exp - 0x19;
if (0 <= shiftDist) {
sig32 <<= shiftDist;
return sign ? -sig32 : sig32;
}
shiftDist = exp - 0x0D;
if (0 < shiftDist) sig32 <<= shiftDist;
}
else {
if (softfloat_denormalsAreZeros(status)) sig32 = 0;
}
return softfloat_roundToI32(sign, (uint32_t) sig32, roundingMode, exact, status);
}

View File

@@ -0,0 +1,82 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
int32_t f16_to_i32_r_minMag(float16 a, bool exact, struct softfloat_status_t *status)
{
int8_t exp;
uint16_t frac;
int8_t shiftDist;
bool sign;
int32_t alignedSig;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
exp = expF16UI(a);
frac = fracF16UI(a);
if (softfloat_denormalsAreZeros(status))
if (!exp && frac) frac = 0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = exp - 0x0F;
if (shiftDist < 0) {
if (exact && (exp | frac)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signF16UI(a);
if (exp == 0x1F) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return (exp == 0x1F) && frac
? i32_fromNaN
: sign ? i32_fromNegOverflow : i32_fromPosOverflow;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
alignedSig = (int32_t) (frac | 0x0400)<<shiftDist;
if (exact && (alignedSig & 0x3FF)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
alignedSig >>= 10;
return sign ? -alignedSig : alignedSig;
}

View File

@@ -0,0 +1,80 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
int64_t f16_to_i64(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
bool sign;
int8_t exp;
uint16_t frac;
int32_t sig32;
int8_t shiftDist;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signF16UI(a);
exp = expF16UI(a);
frac = fracF16UI(a);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp == 0x1F) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return
frac ? i64_fromNaN
: sign ? i64_fromNegOverflow : i64_fromPosOverflow;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sig32 = frac;
if (exp) {
sig32 |= 0x0400;
shiftDist = exp - 0x19;
if (0 <= shiftDist) {
sig32 <<= shiftDist;
return sign ? -sig32 : sig32;
}
shiftDist = exp - 0x0D;
if (0 < shiftDist) sig32 <<= shiftDist;
}
else {
if (softfloat_denormalsAreZeros(status)) sig32 = 0;
}
return softfloat_roundToI32(sign, (uint32_t) sig32, roundingMode, exact, status);
}

View File

@@ -0,0 +1,82 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
int64_t f16_to_i64_r_minMag(float16 a, bool exact, struct softfloat_status_t *status)
{
int8_t exp;
uint16_t frac;
int8_t shiftDist;
bool sign;
int32_t alignedSig;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
exp = expF16UI(a);
frac = fracF16UI(a);
if (softfloat_denormalsAreZeros(status))
if (!exp && frac) frac = 0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = exp - 0x0F;
if (shiftDist < 0) {
if (exact && (exp | frac)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signF16UI(a);
if (exp == 0x1F) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return (exp == 0x1F) && frac
? i64_fromNaN
: sign ? i64_fromNegOverflow : i64_fromPosOverflow;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
alignedSig = (int32_t) (frac | 0x0400)<<shiftDist;
if (exact && (alignedSig & 0x3FF)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
alignedSig >>= 10;
return sign ? -alignedSig : alignedSig;
}

View File

@@ -0,0 +1,79 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
uint32_t f16_to_ui32(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
bool sign;
int8_t exp;
uint16_t frac;
uint32_t sig32;
int8_t shiftDist;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signF16UI(a);
exp = expF16UI(a);
frac = fracF16UI(a);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp == 0x1F) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return
frac ? ui32_fromNaN
: sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sig32 = frac;
if (exp) {
sig32 |= 0x0400;
shiftDist = exp - 0x19;
if ((0 <= shiftDist) && ! sign) {
return sig32<<shiftDist;
}
shiftDist = exp - 0x0D;
if (0 < shiftDist) sig32 <<= shiftDist;
}
else {
if (softfloat_denormalsAreZeros(status)) sig32 = 0;
}
return softfloat_roundToUI32(sign, sig32, roundingMode, exact, status);
}

View File

@@ -0,0 +1,81 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
uint32_t f16_to_ui32_r_minMag(float16 a, bool exact, struct softfloat_status_t *status)
{
int8_t exp;
uint16_t frac;
int8_t shiftDist;
bool sign;
uint32_t alignedSig;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
exp = expF16UI(a);
frac = fracF16UI(a);
if (softfloat_denormalsAreZeros(status))
if (!exp && frac) frac = 0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = exp - 0x0F;
if (shiftDist < 0) {
if (exact && (exp | frac)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signF16UI(a);
if (sign || (exp == 0x1F)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return (exp == 0x1F) && frac
? ui32_fromNaN
: sign ? ui32_fromNegOverflow : ui32_fromPosOverflow;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
alignedSig = (uint32_t) (frac | 0x0400)<<shiftDist;
if (exact && (alignedSig & 0x3FF)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return alignedSig>>10;
}

View File

@@ -0,0 +1,79 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 The Regents of the
University of California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
uint64_t f16_to_ui64(float16 a, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
bool sign;
int8_t exp;
uint16_t frac;
uint32_t sig32;
int8_t shiftDist;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signF16UI(a);
exp = expF16UI(a);
frac = fracF16UI(a);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (exp == 0x1F) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return
frac ? ui64_fromNaN
: sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sig32 = frac;
if (exp) {
sig32 |= 0x0400;
shiftDist = exp - 0x19;
if ((0 <= shiftDist) && ! sign) {
return sig32<<shiftDist;
}
shiftDist = exp - 0x0D;
if (0 < shiftDist) sig32 <<= shiftDist;
}
else {
if (softfloat_denormalsAreZeros(status)) sig32 = 0;
}
return softfloat_roundToUI64(sign, sig32>>12, (uint64_t) sig32<<52, roundingMode, exact, status);
}

View File

@@ -0,0 +1,81 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
uint64_t f16_to_ui64_r_minMag(float16 a, bool exact, struct softfloat_status_t *status)
{
int8_t exp;
uint16_t frac;
int8_t shiftDist;
bool sign;
uint32_t alignedSig;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
exp = expF16UI(a);
frac = fracF16UI(a);
if (softfloat_denormalsAreZeros(status))
if (!exp && frac) frac = 0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
shiftDist = exp - 0x0F;
if (shiftDist < 0) {
if (exact && (exp | frac)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
sign = signF16UI(a);
if (sign || (exp == 0x1F)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return (exp == 0x1F) && frac
? ui64_fromNaN
: sign ? ui64_fromNegOverflow : ui64_fromPosOverflow;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
alignedSig = (uint32_t) (frac | 0x0400)<<shiftDist;
if (exact && (alignedSig & 0x3FF)) {
softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return alignedSig>>10;
}

View File

@@ -25,12 +25,15 @@ these four paragraphs for those parts of this code that are retained.
#define FLOAT128
#include "softfloatx80.h"
#include "softfloat-round-pack.h"
#include "config.h"
#include "specialize.h"
#include "fpu_trans.h"
#include "softfloat-helpers.h"
static const floatx80 floatx80_negone = packFloatx80(1, 0x3fff, BX_CONST64(0x8000000000000000));
static const floatx80 floatx80_neghalf = packFloatx80(1, 0x3ffe, BX_CONST64(0x8000000000000000));
static const float128 float128_ln2 =
static const float128_t float128_ln2 =
packFloat128(BX_CONST64(0x3ffe62e42fefa39e), BX_CONST64(0xf35793c7673007e6));
#ifdef BETTER_THAN_PENTIUM
@@ -47,7 +50,7 @@ static const float128 float128_ln2 =
#define EXP_ARR_SIZE 15
static float128 exp_arr[EXP_ARR_SIZE] =
static float128_t exp_arr[EXP_ARR_SIZE] =
{
PACK_FLOAT_128(0x3fff000000000000, 0x0000000000000000), /* 1 */
PACK_FLOAT_128(0x3ffe000000000000, 0x0000000000000000), /* 2 */
@@ -66,10 +69,10 @@ static float128 exp_arr[EXP_ARR_SIZE] =
PACK_FLOAT_128(0x3fd6ae7f3e733b81, 0xf11d8656b0ee8cb0) /* 15 */
};
extern float128 EvalPoly(float128 x, float128 *arr, int n, struct float_status_t *status);
extern float128_t EvalPoly(float128_t x, const float128_t *arr, int n, struct softfloat_status_t *status);
/* required -1 < x < 1 */
static float128 poly_exp(float128 x, struct float_status_t *status)
static float128_t poly_exp(float128_t x, struct softfloat_status_t *status)
{
/*
// 2 3 4 5 6 7 8 9
@@ -92,8 +95,8 @@ static float128 poly_exp(float128 x, struct float_status_t *status)
// e - 1 ~ x * [ p(x) + x * q(x) ]
//
*/
float128 t = EvalPoly(x, exp_arr, EXP_ARR_SIZE, status);
return float128_mul(t, x, status);
float128_t t = EvalPoly(x, (const float128_t*) exp_arr, EXP_ARR_SIZE, status);
return f128_mul(t, x, status);
}
// =================================================
@@ -114,49 +117,51 @@ static float128 poly_exp(float128 x, struct float_status_t *status)
// e = 1 + --- + --- + --- + --- + --- + ... + --- + ...
// 1! 2! 3! 4! 5! n!
//
floatx80 f2xm1(floatx80 a, struct float_status_t *status)
floatx80 f2xm1(floatx80 a, struct softfloat_status_t *status)
{
/*----------------------------------------------------------------------------
| The pattern for a default generated extended double-precision NaN.
*----------------------------------------------------------------------------*/
const floatx80 floatx80_default_nan = packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
Bit64u zSig0, zSig1, zSig2;
static const floatx80 floatx80_default_nan =
packFloatx80(0, floatx80_default_nan_exp, floatx80_default_nan_fraction);
uint64_t zSig0, zSig1, zSig2;
struct exp32_sig64 normExpSig;
// handle unsupported extended double-precision floating encodings
if (floatx80_is_unsupported(a))
{
float_raise(status, float_flag_invalid);
if (extF80_isUnsupported(a)) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return floatx80_default_nan;
}
Bit64u aSig = extractFloatx80Frac(a);
Bit32s aExp = extractFloatx80Exp(a);
int aSign = extractFloatx80Sign(a);
uint64_t aSig = extF80_fraction(a);
int32_t aExp = extF80_exp(a);
int aSign = extF80_sign(a);
if (aExp == 0x7FFF) {
if ((Bit64u) (aSig<<1))
return propagateFloatx80NaNOne(a, status);
if (aSig << 1)
return softfloat_propagateNaNExtF80UI(a.signExp, aSig, 0, 0, status);
return (aSign) ? floatx80_negone : a;
}
if (aExp == 0) {
if (aSig == 0) return a;
float_raise(status, float_flag_denormal | float_flag_inexact);
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
if (! aExp) {
if (! aSig) return a;
softfloat_raiseFlags(status, softfloat_flag_denormal | softfloat_flag_inexact);
normExpSig = softfloat_normSubnormalExtF80Sig(aSig);
aExp = normExpSig.exp + 1;
aSig = normExpSig.sig;
tiny_argument:
mul128By64To192(LN2_SIG_HI, LN2_SIG_LO, aSig, &zSig0, &zSig1, &zSig2);
if (0 < (Bit64s) zSig0) {
if (0 < (int64_t) zSig0) {
shortShift128Left(zSig0, zSig1, 1, &zSig0, &zSig1);
--aExp;
}
return
roundAndPackFloatx80(80, aSign, aExp, zSig0, zSig1, status);
return softfloat_roundPackToExtF80(aSign, aExp, zSig0, zSig1, 80, status);
}
float_raise(status, float_flag_inexact);
softfloat_raiseFlags(status, softfloat_flag_inexact);
if (aExp < 0x3FFF)
{
@@ -167,14 +172,14 @@ floatx80 f2xm1(floatx80 a, struct float_status_t *status)
/* using float128 for approximation */
/* ******************************** */
float128 x = floatx80_to_float128(a, status);
x = float128_mul(x, float128_ln2, status);
float128_t x = extF80_to_f128(a, status);
x = f128_mul(x, float128_ln2, status);
x = poly_exp(x, status);
return float128_to_floatx80(x, status);
return f128_to_extF80(x, status);
}
else
{
if (a.exp == 0xBFFF && ! (aSig<<1))
if (a.signExp == 0xBFFF && ! (aSig<<1))
return floatx80_neghalf;
return a;

View File

@@ -0,0 +1,60 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "softfloat.h"
extern float32 softfloat_addMagsF32(uint32_t, uint32_t, struct softfloat_status_t *);
extern float32 softfloat_subMagsF32(uint32_t, uint32_t, struct softfloat_status_t *);
float32 f32_add(float32 a, float32 b, struct softfloat_status_t *status)
{
if (signF32UI((uint32_t) a ^ (uint32_t) b)) {
return softfloat_subMagsF32(a, b, status);
} else {
return softfloat_addMagsF32(a, b, status);
}
}
float32 f32_sub(float32 a, float32 b, struct softfloat_status_t *status)
{
if (signF32UI((uint32_t) a ^ (uint32_t) b)) {
return softfloat_addMagsF32(a, b, status);
} else {
return softfloat_subMagsF32(a, b, status);
}
}

View File

@@ -0,0 +1,64 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "softfloat.h"
softfloat_class_t f32_class(float32 a)
{
bool signA;
int16_t expA;
uint32_t sigA;
signA = signF32UI(a);
expA = expF32UI(a);
sigA = fracF32UI(a);
if (expA == 0xFF) {
if (sigA == 0)
return (signA) ? softfloat_negative_inf : softfloat_positive_inf;
return (sigA & 0x00400000) ? softfloat_QNaN : softfloat_SNaN;
}
if (expA == 0) {
if (sigA == 0) return softfloat_zero;
return softfloat_denormal;
}
return softfloat_normalized;
}

View File

@@ -0,0 +1,92 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Compare between two single precision floating point numbers. Returns
| 'float_relation_equal' if the operands are equal, 'float_relation_less' if
| the value 'a' is less than the corresponding value `b',
| 'float_relation_greater' if the value 'a' is greater than the corresponding
| value `b', or 'float_relation_unordered' otherwise.
*----------------------------------------------------------------------------*/
int f32_compare(float32 a, float32 b, bool quiet, struct softfloat_status_t *status)
{
softfloat_class_t aClass;
softfloat_class_t bClass;
bool signA;
bool signB;
aClass = f32_class(a);
bClass = f32_class(b);
if (aClass == softfloat_SNaN || bClass == softfloat_SNaN) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return softfloat_relation_unordered;
}
if (aClass == softfloat_QNaN || bClass == softfloat_QNaN) {
if (! quiet) softfloat_raiseFlags(status, softfloat_flag_invalid);
return softfloat_relation_unordered;
}
if (aClass == softfloat_denormal) {
if (softfloat_denormalsAreZeros(status))
a = a & 0x80000000;
else
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
if (bClass == softfloat_denormal) {
if (softfloat_denormalsAreZeros(status))
b = b & 0x80000000;
else
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
if ((a == b) || ((uint32_t) ((a | b)<<1) == 0)) return softfloat_relation_equal;
signA = signF32UI(a);
signB = signF32UI(b);
if (signA != signB)
return (signA) ? softfloat_relation_less : softfloat_relation_greater;
if (signA ^ (a < b)) return softfloat_relation_less;
return softfloat_relation_greater;
}

View File

@@ -0,0 +1,146 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
#define SOFTFLOAT_FAST_DIV64TO32
float32 f32_div(float32 a, float32 b, struct softfloat_status_t *status)
{
bool signA;
int16_t expA;
uint32_t sigA;
bool signB;
int16_t expB;
uint32_t sigB;
bool signZ;
struct exp16_sig32 normExpSig;
int16_t expZ;
#ifdef SOFTFLOAT_FAST_DIV64TO32
uint64_t sig64A;
uint32_t sigZ;
#endif
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
signA = signF32UI(a);
expA = expF32UI(a);
sigA = fracF32UI(a);
signB = signF32UI(b);
expB = expF32UI(b);
sigB = fracF32UI(b);
signZ = signA ^ signB;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (softfloat_denormalsAreZeros(status)) {
if (!expA) sigA = 0;
if (!expB) sigB = 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0xFF) {
if (sigA) goto propagateNaN;
if (expB == 0xFF) {
if (sigB) goto propagateNaN;
goto invalid;
}
if (sigB && !expB)
softfloat_raiseFlags(status, softfloat_flag_denormal);
goto infinity;
}
if (expB == 0xFF) {
if (sigB) goto propagateNaN;
if (sigA && !expA)
softfloat_raiseFlags(status, softfloat_flag_denormal);
goto zero;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expB) {
if (! sigB) {
if (! (expA | sigA)) goto invalid;
softfloat_raiseFlags(status, softfloat_flag_infinite);
goto infinity;
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF32Sig(sigB);
expB = normExpSig.exp;
sigB = normExpSig.sig;
}
if (! expA) {
if (! sigA) goto zero;
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF32Sig(sigA);
expA = normExpSig.exp;
sigA = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expZ = expA - expB + 0x7E;
sigA |= 0x00800000;
sigB |= 0x00800000;
#ifdef SOFTFLOAT_FAST_DIV64TO32
if (sigA < sigB) {
--expZ;
sig64A = (uint64_t) sigA<<31;
} else {
sig64A = (uint64_t) sigA<<30;
}
sigZ = sig64A / sigB;
if (! (sigZ & 0x3F)) sigZ |= ((uint64_t) sigB * sigZ != sig64A);
#endif
return softfloat_roundPackToF32(signZ, expZ, sigZ, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
propagateNaN:
return softfloat_propagateNaNF32UI(a, b, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
invalid:
softfloat_raiseFlags(status, softfloat_flag_invalid);
return defaultNaNF32UI;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
infinity:
return packToF32UI(signZ, 0xFF, 0);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
zero:
return packToF32UI(signZ, 0, 0);
}

View File

@@ -0,0 +1,101 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Extracts the fractional portion of single-precision floating-point value `a',
| and returns the result as a single-precision floating-point value. The
| fractional results are precise. The operation is performed according to the
| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
float32 f32_frc(float32 a, struct softfloat_status_t *status)
{
int roundingMode = softfloat_getRoundingMode(status);
bool signA;
int16_t expA;
uint32_t sigA;
uint32_t lastBitMask;
uint32_t roundBitsMask;
signA = signF32UI(a);
expA = expF32UI(a);
sigA = fracF32UI(a);
if (expA == 0xFF) {
if (sigA) return softfloat_propagateNaNF32UI(a, 0, status);
softfloat_raiseFlags(status, softfloat_flag_invalid);
return defaultNaNF32UI;
}
if (expA >= 0x96) {
return packToF32UI(roundingMode == softfloat_round_down, 0, 0);
}
if (expA < 0x7F) {
if (! expA) {
if (! sigA || softfloat_denormalsAreZeros(status))
return packToF32UI(roundingMode == softfloat_round_down, 0, 0);
softfloat_raiseFlags(status, softfloat_flag_denormal);
if (! softfloat_isMaskedException(status, softfloat_flag_underflow))
softfloat_raiseFlags(status, softfloat_flag_underflow);
if (softfloat_flushUnderflowToZero(status)) {
softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact);
return packToF32UI(signA, 0, 0);
}
}
return a;
}
lastBitMask = 1 << (0x96 - expA);
roundBitsMask = lastBitMask - 1;
sigA &= roundBitsMask;
sigA <<= 7;
expA--;
if (! sigA)
return packToF32UI(roundingMode == softfloat_round_down, 0, 0);
return softfloat_normRoundPackToF32(signA, expA, sigA, status);
}

View File

@@ -0,0 +1,73 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Extracts the exponent portion of single-precision floating-point value 'a',
| and returns the result as a single-precision floating-point value
| representing unbiased integer exponent. The operation is performed according
| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
float32 f32_getExp(float32 a, struct softfloat_status_t *status)
{
int16_t expA;
uint32_t sigA;
struct exp16_sig32 normExpSig;
expA = expF32UI(a);
sigA = fracF32UI(a);
if (expA == 0xFF) {
if (sigA) return softfloat_propagateNaNF32UI(a, 0, status);
return packToF32UI(0, 0xFF, 0);
}
if (! expA) {
if (! sigA || softfloat_denormalsAreZeros(status))
return packToF32UI(1, 0xFF, 0);
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF32Sig(sigA);
expA = normExpSig.exp;
}
return i32_to_f32((int32_t)(expA) - 0x7F, status);
}

View File

@@ -0,0 +1,108 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Extracts the mantissa of single-precision floating-point value 'a' and
| returns the result as a single-precision floating-point after applying
| the mantissa interval normalization and sign control. The operation is
| performed according to the IEC/IEEE Standard for Binary Floating-Point
| Arithmetic.
*----------------------------------------------------------------------------*/
float32 f32_getMant(float32 a, struct softfloat_status_t *status, int sign_ctrl, int interv)
{
bool signA;
int16_t expA;
uint32_t sigA;
struct exp16_sig32 normExpSig;
signA = signF32UI(a);
expA = expF32UI(a);
sigA = fracF32UI(a);
if (expA == 0xFF) {
if (sigA) return softfloat_propagateNaNF32UI(a, 0, status);
if (signA) {
if (sign_ctrl & 0x2) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return defaultNaNF32UI;
}
}
return packToF32UI(~sign_ctrl & signA, 0x7F, 0);
}
if (! expA && (! sigA || softfloat_denormalsAreZeros(status))) {
return packToF32UI(~sign_ctrl & signA, 0x7F, 0);
}
if (signA) {
if (sign_ctrl & 0x2) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return defaultNaNF32UI;
}
}
if (! expA) {
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF32Sig(sigA);
expA = normExpSig.exp;
sigA = normExpSig.sig;
sigA &= 0x7FFFFF;
}
switch(interv) {
case 0x0: // interval [1,2)
expA = 0x7F;
break;
case 0x1: // interval [1/2,2)
expA -= 0x7F;
expA = 0x7F - (expA & 0x1);
break;
case 0x2: // interval [1/2,1)
expA = 0x7E;
break;
case 0x3: // interval [3/4,3/2)
expA = 0x7F - ((sigA >> 22) & 0x1);
break;
}
return packToF32UI(~sign_ctrl & signA, expA, sigA);
}

View File

@@ -0,0 +1,69 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Compare between two single precision floating point numbers and return the
| smaller of them.
*----------------------------------------------------------------------------*/
float32 f32_min(float32 a, float32 b, struct softfloat_status_t *status)
{
if (softfloat_denormalsAreZeros(status)) {
a = f32_denormal_to_zero(a);
b = f32_denormal_to_zero(b);
}
return (f32_compare_normal(a, b, status) == softfloat_relation_less) ? a : b;
}
/*----------------------------------------------------------------------------
| Compare between two single precision floating point numbers and return the
| larger of them.
*----------------------------------------------------------------------------*/
float32 f32_max(float32 a, float32 b, struct softfloat_status_t *status)
{
if (softfloat_denormalsAreZeros(status)) {
a = f32_denormal_to_zero(a);
b = f32_denormal_to_zero(b);
}
return (f32_compare_normal(a, b, status) == softfloat_relation_greater) ? a : b;
}

View File

@@ -0,0 +1,137 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "specialize.h"
#include "softfloat.h"
float32 f32_mul(float32 a, float32 b, struct softfloat_status_t *status)
{
bool signA;
int16_t expA;
uint32_t sigA;
bool signB;
int16_t expB;
uint32_t sigB;
bool signZ;
uint32_t magBits;
struct exp16_sig32 normExpSig;
int16_t expZ;
uint32_t sigZ, uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
signA = signF32UI(a);
expA = expF32UI(a);
sigA = fracF32UI(a);
signB = signF32UI(b);
expB = expF32UI(b);
sigB = fracF32UI(b);
signZ = signA ^ signB;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (softfloat_denormalsAreZeros(status)) {
if (!expA) sigA = 0;
if (!expB) sigB = 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0xFF) {
if (sigA || ((expB == 0xFF) && sigB)) goto propagateNaN;
magBits = expB | sigB;
if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
goto infArg;
}
if (expB == 0xFF) {
if (sigB) goto propagateNaN;
magBits = expA | sigA;
if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal);
goto infArg;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expA) {
if (! sigA) {
if (sigB && !expB) softfloat_raiseFlags(status, softfloat_flag_denormal);
goto zero;
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF32Sig(sigA);
expA = normExpSig.exp;
sigA = normExpSig.sig;
}
if (! expB) {
if (! sigB) {
if (sigA && !expA) softfloat_raiseFlags(status, softfloat_flag_denormal);
goto zero;
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF32Sig(sigB);
expB = normExpSig.exp;
sigB = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expZ = expA + expB - 0x7F;
sigA = (sigA | 0x00800000)<<7;
sigB = (sigB | 0x00800000)<<8;
sigZ = softfloat_shortShiftRightJam64((uint64_t) sigA * sigB, 32);
if (sigZ < 0x40000000) {
--expZ;
sigZ <<= 1;
}
return softfloat_roundPackToF32(signZ, expZ, sigZ, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
propagateNaN:
return softfloat_propagateNaNF32UI(a, b, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
infArg:
if (! magBits) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
uiZ = defaultNaNF32UI;
} else {
uiZ = packToF32UI(signZ, 0xFF, 0);
}
return uiZ;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
zero:
return packToF32UI(signZ, 0, 0);
}

View File

@@ -0,0 +1,233 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014 The Regents of the University of California.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdint.h>
#include "internals.h"
#include "primitives.h"
#include "softfloat.h"
#include "specialize.h"
float32 f32_mulAdd(float32 a, float32 b, float32 c, uint8_t op, struct softfloat_status_t *status)
{
bool signA;
int16_t expA;
uint32_t sigA;
bool signB;
int16_t expB;
uint32_t sigB;
bool signC;
int16_t expC;
uint32_t sigC;
bool signProd;
uint32_t magBits, uiA, uiB, uiC, uiZ;
struct exp16_sig32 normExpSig;
int16_t expProd;
uint64_t sigProd;
bool signZ;
int16_t expZ;
uint32_t sigZ;
int16_t expDiff;
uint64_t sig64Z, sig64C;
int8_t shiftDist;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiA = a;
uiB = b;
uiC = c;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
signA = signF32UI(uiA);
expA = expF32UI(uiA);
sigA = fracF32UI(uiA);
signB = signF32UI(uiB);
expB = expF32UI(uiB);
sigB = fracF32UI(uiB);
signC = signF32UI(uiC) ^ ((op & softfloat_mulAdd_subC) != 0);
expC = expF32UI(uiC);
sigC = fracF32UI(uiC);
signProd = signA ^ signB ^ ((op & softfloat_mulAdd_subProd) != 0);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
bool aisNaN = (expA == 0xFF) && sigA;
bool bisNaN = (expB == 0xFF) && sigB;
bool cisNaN = (expC == 0xFF) && sigC;
if (aisNaN | bisNaN | cisNaN) {
uiZ = (aisNaN | bisNaN) ? softfloat_propagateNaNF32UI(uiA, uiB, status) : 0;
return softfloat_propagateNaNF32UI(uiZ, uiC, status);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (softfloat_denormalsAreZeros(status)) {
if (!expA) sigA = 0;
if (!expB) sigB = 0;
if (!expC) sigC = 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0xFF) {
magBits = expB | sigB;
goto infProdArg;
}
if (expB == 0xFF) {
magBits = expA | sigA;
goto infProdArg;
}
if (expC == 0xFF) {
if ((sigA && !expA) || (sigB && !expB)) {
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
return packToF32UI(signC, 0xFF, 0);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expA) {
if (! sigA) goto zeroProd;
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF32Sig(sigA);
expA = normExpSig.exp;
sigA = normExpSig.sig;
}
if (! expB) {
if (! sigB) goto zeroProd;
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF32Sig(sigB);
expB = normExpSig.exp;
sigB = normExpSig.sig;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expProd = expA + expB - 0x7E;
sigA = (sigA | 0x00800000)<<7;
sigB = (sigB | 0x00800000)<<7;
sigProd = (uint64_t) sigA * sigB;
if (sigProd < UINT64_C(0x2000000000000000)) {
--expProd;
sigProd <<= 1;
}
signZ = signProd;
if (! expC) {
if (! sigC) {
expZ = expProd - 1;
sigZ = softfloat_shortShiftRightJam64(sigProd, 31);
goto roundPack;
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
normExpSig = softfloat_normSubnormalF32Sig(sigC);
expC = normExpSig.exp;
sigC = normExpSig.sig;
}
sigC = (sigC | 0x00800000)<<6;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
expDiff = expProd - expC;
if (signProd == signC) {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
if (expDiff <= 0) {
expZ = expC;
sigZ = sigC + softfloat_shiftRightJam64(sigProd, 32 - expDiff);
} else {
expZ = expProd;
sig64Z = sigProd + softfloat_shiftRightJam64((uint64_t) sigC<<32, expDiff);
sigZ = softfloat_shortShiftRightJam64(sig64Z, 32);
}
if (sigZ < 0x40000000) {
--expZ;
sigZ <<= 1;
}
} else {
/*--------------------------------------------------------------------
*--------------------------------------------------------------------*/
sig64C = (uint64_t) sigC<<32;
if (expDiff < 0) {
signZ = signC;
expZ = expC;
sig64Z = sig64C - softfloat_shiftRightJam64(sigProd, -expDiff);
} else if (! expDiff) {
expZ = expProd;
sig64Z = sigProd - sig64C;
if (! sig64Z) goto completeCancellation;
if (sig64Z & UINT64_C(0x8000000000000000)) {
signZ = ! signZ;
sig64Z = -sig64Z;
}
} else {
expZ = expProd;
sig64Z = sigProd - softfloat_shiftRightJam64(sig64C, expDiff);
}
shiftDist = softfloat_countLeadingZeros64(sig64Z) - 1;
expZ -= shiftDist;
shiftDist -= 32;
if (shiftDist < 0) {
sigZ = softfloat_shortShiftRightJam64(sig64Z, -shiftDist);
} else {
sigZ = (uint32_t) sig64Z<<shiftDist;
}
}
roundPack:
return softfloat_roundPackToF32(signZ, expZ, sigZ, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
infProdArg:
if (magBits) {
uiZ = packToF32UI(signProd, 0xFF, 0);
if (signProd == signC || expC != 0xFF) {
if ((sigA && !expA) || (sigB && !expB) || (sigC && !expC))
softfloat_raiseFlags(status, softfloat_flag_denormal);
return uiZ;
}
}
softfloat_raiseFlags(status, softfloat_flag_invalid);
uiZ = defaultNaNF32UI;
return softfloat_propagateNaNF32UI(uiZ, uiC, status);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
zeroProd:
uiZ = packToF32UI(signC, expC, sigC);
if (!expC && sigC) {
/* Exact zero plus a denormal */
softfloat_raiseFlags(status, softfloat_flag_denormal);
if (softfloat_flushUnderflowToZero(status)) {
softfloat_raiseFlags(status, softfloat_flag_underflow | softfloat_flag_inexact);
return packToF32UI(signC, 0, 0);
}
}
if (! (expC | sigC) && (signProd != signC)) {
completeCancellation:
uiZ = packToF32UI((softfloat_getRoundingMode(status) == softfloat_round_min), 0, 0);
}
return uiZ;
}

View File

@@ -0,0 +1,134 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
float32 f32_range(float32 a, float32 b, bool is_max, bool is_abs, int sign_ctrl, struct softfloat_status_t *status)
{
bool signA;
int16_t expA;
uint32_t sigA;
bool signB;
int16_t expB;
uint32_t sigB;
bool aIsNaN, bIsNaN;
uint32_t z;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
signA = signF32UI(a);
expA = expF32UI(a);
sigA = fracF32UI(a);
signB = signF32UI(b);
expB = expF32UI(b);
sigB = fracF32UI(b);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (softfloat_isSigNaNF32UI(a)) {
return softfloat_propagateNaNF32UI(a, 0, status);
}
if (softfloat_isSigNaNF32UI(b)) {
return softfloat_propagateNaNF32UI(b, 0, status);
}
aIsNaN = isNaNF32UI(a);
bIsNaN = isNaNF32UI(b);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expA && sigA) {
if (softfloat_denormalsAreZeros(status)) {
a = packToF32UI(signA, 0, 0);
}
else if (! bIsNaN) {
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
}
if (! expB && sigB) {
if (softfloat_denormalsAreZeros(status)) {
b = packToF32UI(signB, 0, 0);
}
else if (! aIsNaN) {
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (bIsNaN) {
z = a;
}
else if (aIsNaN) {
z = b;
}
else if (signA != signB && ! is_abs) {
if (! is_max) {
z = signA ? a : b;
} else {
z = signA ? b : a;
}
} else {
float32 tmp_a = a, tmp_b = b;
if (is_abs) {
tmp_a = tmp_a & ~0x80000000; // clear the sign bit
tmp_b = tmp_b & ~0x80000000;
signA = 0;
}
if (! is_max) {
z = (signA ^ (tmp_a < tmp_b)) ? a : b;
} else {
z = (signA ^ (tmp_a < tmp_b)) ? b : a;
}
}
switch(sign_ctrl) {
case 0:
z = (z & ~0x80000000) | (a & 0x80000000); // keep sign of a
break;
case 1:
break; // preserve sign of compare result
case 2:
z = z & ~0x80000000; // zero out the sign bit
break;
case 3:
z = z | 0x80000000; // set the sign bit
break;
}
return z;
}

View File

@@ -0,0 +1,112 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2017 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
float32 f32_roundToInt(float32 a, uint8_t scale, uint8_t roundingMode, bool exact, struct softfloat_status_t *status)
{
int16_t exp;
int32_t frac;
uint32_t uiZ, lastBitMask, roundBitsMask;
bool sign;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
scale &= 0xF;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
exp = expF32UI(a);
frac = fracF32UI(a);
sign = signF32UI(a);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (0x96 <= (exp + scale)) {
if ((exp == 0xFF) && frac) {
return softfloat_propagateNaNF32UI(a, 0, status);
}
return a;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (softfloat_denormalsAreZeros(status)) {
if (!exp) {
frac = 0;
a = packToF32UI(sign, 0, 0);
}
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ((exp + scale) <= 0x7E) {
if (!(exp | frac)) return a;
if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
uiZ = packToF32UI(sign, 0, 0);
switch (roundingMode) {
case softfloat_round_near_even:
if (!frac) break;
case softfloat_round_near_maxMag:
if ((exp + scale) == 0x7E) uiZ |= packToF32UI(0, 0x7F - scale, 0);
break;
case softfloat_round_min:
if (uiZ) uiZ = packToF32UI(1, 0x7F - scale, 0);
break;
case softfloat_round_max:
if (!uiZ) uiZ = packToF32UI(0, 0x7F - scale, 0);
break;
}
return uiZ;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
uiZ = a;
lastBitMask = (uint32_t) 1<<(0x96 - exp - scale);
roundBitsMask = lastBitMask - 1;
if (roundingMode == softfloat_round_near_maxMag) {
uiZ += lastBitMask>>1;
} else if (roundingMode == softfloat_round_near_even) {
uiZ += lastBitMask>>1;
if (!(uiZ & roundBitsMask)) uiZ &= ~lastBitMask;
} else if (roundingMode == (signF32UI(uiZ) ? softfloat_round_min : softfloat_round_max)) {
uiZ += roundBitsMask;
}
uiZ &= ~roundBitsMask;
if (uiZ != a) {
if (exact) softfloat_raiseFlags(status, softfloat_flag_inexact);
}
return uiZ;
}

View File

@@ -0,0 +1,155 @@
/*============================================================================
This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic
Package, Release 3e, by John R. Hauser.
Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of
California. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions, and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions, and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the University nor the names of its contributors may
be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
=============================================================================*/
#include <stdbool.h>
#include <stdint.h>
#include "internals.h"
#include "specialize.h"
#include "softfloat.h"
/*----------------------------------------------------------------------------
| Return the result of a floating point scale of the single-precision floating
| point value `a' by multiplying it by 2 power of the single-precision
| floating point value 'b' converted to integral value. If the result cannot
| be represented in single precision, then the proper overflow response (for
| positive scaling operand), or the proper underflow response (for negative
| scaling operand) is issued. The operation is performed according to the
| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
float32 f32_scalef(float32 a, float32 b, struct softfloat_status_t *status)
{
bool signA;
int16_t expA;
uint32_t sigA;
bool signB;
int16_t expB;
uint32_t sigB;
int shiftCount;
int scale = 0;
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
signA = signF32UI(a);
expA = expF32UI(a);
sigA = fracF32UI(a);
signB = signF32UI(b);
expB = expF32UI(b);
sigB = fracF32UI(b);
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expB == 0xFF) {
if (sigB) return softfloat_propagateNaNF32UI(a, b, status);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (softfloat_denormalsAreZeros(status)) {
if (!expA) sigA = 0;
if (!expB) sigB = 0;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expA == 0xFF) {
if (sigA) {
int aIsSignalingNaN = (sigA & 0x00400000) == 0;
if (aIsSignalingNaN || expB != 0xFF || sigB)
return softfloat_propagateNaNF32UI(a, b, status);
return signB ? 0 : packToF32UI(0, 0xFF, 0);
}
if (expB == 0xFF && signB) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return defaultNaNF32UI;
}
return a;
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (! expA) {
if (! sigA) {
if (expB == 0xFF && ! signB) {
softfloat_raiseFlags(status, softfloat_flag_invalid);
return defaultNaNF32UI;
}
return packToF32UI(signA, 0, 0);
}
softfloat_raiseFlags(status, softfloat_flag_denormal);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if ((expB | sigB) == 0) return a;
if (expB == 0xFF) {
if (signB) return packToF32UI(signA, 0, 0);
return packToF32UI(signA, 0xFF, 0);
}
if (expB >= 0x8E) {
// handle obvious overflow/underflow result
return softfloat_roundPackToF32(signA, signB ? -0x7F : 0xFF, sigA, status);
}
/*------------------------------------------------------------------------
*------------------------------------------------------------------------*/
if (expB <= 0x7E) {
if (! expB)
softfloat_raiseFlags(status, softfloat_flag_denormal);
scale = -signB;
}
else {
shiftCount = expB - 0x9E;
sigB = (sigB | 0x800000)<<8;
scale = sigB>>(-shiftCount);
if (signB) {
if ((uint32_t) (sigB<<(shiftCount & 31))) scale++;
scale = -scale;
}
if (scale > 0x200) scale = 0x200;
if (scale < -0x200) scale = -0x200;
}
if (expA != 0) {
sigA |= 0x00800000;
} else {
expA++;
}
expA += scale - 1;
sigA <<= 7;
return softfloat_normRoundPackToF32(signA, expA, sigA, status);
}

Some files were not shown because too many files have changed in this diff Show More