123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419 |
- /*
- * QEMU float support
- *
- * The code in this source file is derived from release 2a of the SoftFloat
- * IEC/IEEE Floating-point Arithmetic Package. Those parts of the code (and
- * some later contributions) are provided under that license, as detailed below.
- * It has subsequently been modified by contributors to the QEMU Project,
- * so some portions are provided under:
- * the SoftFloat-2a license
- * the BSD license
- * GPL-v2-or-later
- *
- * This header holds definitions for code that might be dealing with
- * softfloat types but not need access to the actual library functions.
- */
- /*
- ===============================================================================
- This C header file is part of the SoftFloat IEC/IEEE Floating-point
- Arithmetic Package, Release 2a.
- 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://HTTP.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 ANY
- AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
- Derivative works are acceptable, even for commercial purposes, so long as
- (1) they include prominent notice that the work is derivative, and (2) they
- include prominent notice akin to these four paragraphs for those parts of
- this code that are retained.
- ===============================================================================
- */
- /* BSD licensing:
- * Copyright (c) 2006, Fabrice Bellard
- * 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 copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
- */
- /* Portions of this work are licensed under the terms of the GNU GPL,
- * version 2 or later. See the COPYING file in the top-level directory.
- */
- #ifndef SOFTFLOAT_TYPES_H
- #define SOFTFLOAT_TYPES_H
- #include "hw/registerfields.h"
- /*
- * Software IEC/IEEE floating-point types.
- */
- typedef uint16_t float16;
- typedef uint32_t float32;
- typedef uint64_t float64;
- #define float16_val(x) (x)
- #define float32_val(x) (x)
- #define float64_val(x) (x)
- #define make_float16(x) (x)
- #define make_float32(x) (x)
- #define make_float64(x) (x)
- #define const_float16(x) (x)
- #define const_float32(x) (x)
- #define const_float64(x) (x)
- typedef struct {
- uint64_t low;
- uint16_t high;
- } floatx80;
- #define make_floatx80(exp, mant) ((floatx80) { mant, exp })
- #define make_floatx80_init(exp, mant) { .low = mant, .high = exp }
- typedef struct {
- #if HOST_BIG_ENDIAN
- uint64_t high, low;
- #else
- uint64_t low, high;
- #endif
- } float128;
- #define make_float128(high_, low_) ((float128) { .high = high_, .low = low_ })
- #define make_float128_init(high_, low_) { .high = high_, .low = low_ }
- /*
- * Software neural-network floating-point types.
- */
- typedef uint16_t bfloat16;
- /*
- * Software IEC/IEEE floating-point underflow tininess-detection mode.
- */
- #define float_tininess_after_rounding false
- #define float_tininess_before_rounding true
- /*
- *Software IEC/IEEE floating-point rounding mode.
- */
- typedef enum __attribute__((__packed__)) {
- float_round_nearest_even = 0,
- float_round_down = 1,
- float_round_up = 2,
- float_round_to_zero = 3,
- float_round_ties_away = 4,
- /* Not an IEEE rounding mode: round to closest odd, overflow to max */
- float_round_to_odd = 5,
- /* Not an IEEE rounding mode: round to closest odd, overflow to inf */
- float_round_to_odd_inf = 6,
- /* Not an IEEE rounding mode: round to nearest even, overflow to max */
- float_round_nearest_even_max = 7,
- } FloatRoundMode;
- /*
- * Software IEC/IEEE floating-point exception flags.
- */
- enum {
- float_flag_invalid = 0x0001,
- float_flag_divbyzero = 0x0002,
- float_flag_overflow = 0x0004,
- float_flag_underflow = 0x0008,
- float_flag_inexact = 0x0010,
- /* We flushed an input denormal to 0 (because of flush_inputs_to_zero) */
- float_flag_input_denormal_flushed = 0x0020,
- /* We flushed an output denormal to 0 (because of flush_to_zero) */
- float_flag_output_denormal_flushed = 0x0040,
- float_flag_invalid_isi = 0x0080, /* inf - inf */
- float_flag_invalid_imz = 0x0100, /* inf * 0 */
- float_flag_invalid_idi = 0x0200, /* inf / inf */
- float_flag_invalid_zdz = 0x0400, /* 0 / 0 */
- float_flag_invalid_sqrt = 0x0800, /* sqrt(-x) */
- float_flag_invalid_cvti = 0x1000, /* non-nan to integer */
- float_flag_invalid_snan = 0x2000, /* any operand was snan */
- /*
- * An input was denormal and we used it (without flushing it to zero).
- * Not set if we do not actually use the denormal input (e.g.
- * because some other input was a NaN, or because the operation
- * wasn't actually carried out (divide-by-zero; invalid))
- */
- float_flag_input_denormal_used = 0x4000,
- };
- /*
- * Rounding precision for floatx80.
- */
- typedef enum __attribute__((__packed__)) {
- floatx80_precision_x,
- floatx80_precision_d,
- floatx80_precision_s,
- } FloatX80RoundPrec;
- /*
- * 2-input NaN propagation rule. Individual architectures have
- * different rules for which input NaN is propagated to the output
- * when there is more than one NaN on the input.
- *
- * If default_nan_mode is enabled then it is valid not to set a
- * NaN propagation rule, because the softfloat code guarantees
- * not to try to pick a NaN to propagate in default NaN mode.
- * When not in default-NaN mode, it is an error for the target
- * not to set the rule in float_status, and we will assert if
- * we need to handle an input NaN and no rule was selected.
- */
- typedef enum __attribute__((__packed__)) {
- /* No propagation rule specified */
- float_2nan_prop_none = 0,
- /* Prefer SNaN over QNaN, then operand A over B */
- float_2nan_prop_s_ab,
- /* Prefer SNaN over QNaN, then operand B over A */
- float_2nan_prop_s_ba,
- /* Prefer A over B regardless of SNaN vs QNaN */
- float_2nan_prop_ab,
- /* Prefer B over A regardless of SNaN vs QNaN */
- float_2nan_prop_ba,
- /*
- * This implements x87 NaN propagation rules:
- * SNaN + QNaN => return the QNaN
- * two SNaNs => return the one with the larger significand, silenced
- * two QNaNs => return the one with the larger significand
- * SNaN and a non-NaN => return the SNaN, silenced
- * QNaN and a non-NaN => return the QNaN
- *
- * If we get down to comparing significands and they are the same,
- * return the NaN with the positive sign bit (if any).
- */
- float_2nan_prop_x87,
- } Float2NaNPropRule;
- /*
- * 3-input NaN propagation rule, for fused multiply-add. Individual
- * architectures have different rules for which input NaN is
- * propagated to the output when there is more than one NaN on the
- * input.
- *
- * If default_nan_mode is enabled then it is valid not to set a NaN
- * propagation rule, because the softfloat code guarantees not to try
- * to pick a NaN to propagate in default NaN mode. When not in
- * default-NaN mode, it is an error for the target not to set the rule
- * in float_status if it uses a muladd, and we will assert if we need
- * to handle an input NaN and no rule was selected.
- *
- * The naming scheme for Float3NaNPropRule values is:
- * float_3nan_prop_s_abc:
- * = "Prefer SNaN over QNaN, then operand A over B over C"
- * float_3nan_prop_abc:
- * = "Prefer A over B over C regardless of SNaN vs QNAN"
- *
- * For QEMU, the multiply-add operation is A * B + C.
- */
- /*
- * We set the Float3NaNPropRule enum values up so we can select the
- * right value in pickNaNMulAdd in a data driven way.
- */
- FIELD(3NAN, 1ST, 0, 2) /* which operand is most preferred ? */
- FIELD(3NAN, 2ND, 2, 2) /* which operand is next most preferred ? */
- FIELD(3NAN, 3RD, 4, 2) /* which operand is least preferred ? */
- FIELD(3NAN, SNAN, 6, 1) /* do we prefer SNaN over QNaN ? */
- #define PROPRULE(X, Y, Z) \
- ((X << R_3NAN_1ST_SHIFT) | (Y << R_3NAN_2ND_SHIFT) | (Z << R_3NAN_3RD_SHIFT))
- typedef enum __attribute__((__packed__)) {
- float_3nan_prop_none = 0, /* No propagation rule specified */
- float_3nan_prop_abc = PROPRULE(0, 1, 2),
- float_3nan_prop_acb = PROPRULE(0, 2, 1),
- float_3nan_prop_bac = PROPRULE(1, 0, 2),
- float_3nan_prop_bca = PROPRULE(1, 2, 0),
- float_3nan_prop_cab = PROPRULE(2, 0, 1),
- float_3nan_prop_cba = PROPRULE(2, 1, 0),
- float_3nan_prop_s_abc = float_3nan_prop_abc | R_3NAN_SNAN_MASK,
- float_3nan_prop_s_acb = float_3nan_prop_acb | R_3NAN_SNAN_MASK,
- float_3nan_prop_s_bac = float_3nan_prop_bac | R_3NAN_SNAN_MASK,
- float_3nan_prop_s_bca = float_3nan_prop_bca | R_3NAN_SNAN_MASK,
- float_3nan_prop_s_cab = float_3nan_prop_cab | R_3NAN_SNAN_MASK,
- float_3nan_prop_s_cba = float_3nan_prop_cba | R_3NAN_SNAN_MASK,
- } Float3NaNPropRule;
- #undef PROPRULE
- /*
- * Rule for result of fused multiply-add 0 * Inf + NaN.
- * This must be a NaN, but implementations differ on whether this
- * is the input NaN or the default NaN.
- *
- * You don't need to set this if default_nan_mode is enabled.
- * When not in default-NaN mode, it is an error for the target
- * not to set the rule in float_status if it uses muladd, and we
- * will assert if we need to handle an input NaN and no rule was
- * selected.
- */
- typedef enum __attribute__((__packed__)) {
- /* No propagation rule specified */
- float_infzeronan_none = 0,
- /* Result is never the default NaN (so always the input NaN) */
- float_infzeronan_dnan_never = 1,
- /* Result is always the default NaN */
- float_infzeronan_dnan_always = 2,
- /* Result is the default NaN if the input NaN is quiet */
- float_infzeronan_dnan_if_qnan = 3,
- /*
- * Don't raise Invalid for 0 * Inf + NaN. Default is to raise.
- * IEEE 754-2008 section 7.2 makes it implementation defined whether
- * 0 * Inf + QNaN raises Invalid or not. Note that 0 * Inf + SNaN will
- * raise the Invalid flag for the SNaN anyway.
- *
- * This is a flag which can be ORed in with any of the above
- * DNaN behaviour options.
- */
- float_infzeronan_suppress_invalid = (1 << 7),
- } FloatInfZeroNaNRule;
- /*
- * When flush_to_zero is set, should we detect denormal results to
- * be flushed before or after rounding? For most architectures this
- * should be set to match the tininess_before_rounding setting,
- * but a few architectures, e.g. MIPS MSA, detect FTZ before
- * rounding but tininess after rounding.
- *
- * This enum is arranged so that the default if the target doesn't
- * configure it matches the default for tininess_before_rounding
- * (i.e. "after rounding").
- */
- typedef enum __attribute__((__packed__)) {
- float_ftz_after_rounding = 0,
- float_ftz_before_rounding = 1,
- } FloatFTZDetection;
- /*
- * floatx80 is primarily used by x86 and m68k, and there are
- * differences in the handling, largely related to the explicit
- * Integer bit which floatx80 has and the other float formats do not.
- * These flag values allow specification of the target's requirements
- * and can be ORed together to set floatx80_behaviour.
- */
- typedef enum __attribute__((__packed__)) {
- /* In the default Infinity value, is the Integer bit 0 ? */
- floatx80_default_inf_int_bit_is_zero = 1,
- /*
- * Are Pseudo-infinities (Inf with the Integer bit zero) valid?
- * If so, floatx80_is_infinity() will return true for them.
- * If not, floatx80_invalid_encoding will return false for them,
- * and using them as inputs to a float op will raise Invalid.
- */
- floatx80_pseudo_inf_valid = 2,
- /*
- * Are Pseudo-NaNs (NaNs where the Integer bit is zero) valid?
- * If not, floatx80_invalid_encoding() will return false for them,
- * and using them as inputs to a float op will raise Invalid.
- */
- floatx80_pseudo_nan_valid = 4,
- /*
- * Are Unnormals (0 < exp < 0x7fff, Integer bit zero) valid?
- * If not, floatx80_invalid_encoding() will return false for them,
- * and using them as inputs to a float op will raise Invalid.
- */
- floatx80_unnormal_valid = 8,
- /*
- * If the exponent is 0 and the Integer bit is set, Intel call
- * this a "pseudo-denormal"; x86 supports that only on input
- * (treating them as denormals by ignoring the Integer bit).
- * For m68k, the integer bit is considered validly part of the
- * input value when the exponent is 0, and may be 0 or 1,
- * giving extra range. They may also be generated as outputs.
- * (The m68k manual actually calls these values part of the
- * normalized number range, not the denormalized number range.)
- *
- * By default you get the Intel behaviour where the Integer
- * bit is ignored; if this is set then the Integer bit value
- * is honoured, m68k-style.
- *
- * Either way, floatx80_invalid_encoding() will always accept
- * pseudo-denormals.
- */
- floatx80_pseudo_denormal_valid = 16,
- } FloatX80Behaviour;
- /*
- * Floating Point Status. Individual architectures may maintain
- * several versions of float_status for different functions. The
- * correct status for the operation is then passed by reference to
- * most of the softfloat functions.
- */
- typedef struct float_status {
- uint16_t float_exception_flags;
- FloatRoundMode float_rounding_mode;
- FloatX80RoundPrec floatx80_rounding_precision;
- FloatX80Behaviour floatx80_behaviour;
- Float2NaNPropRule float_2nan_prop_rule;
- Float3NaNPropRule float_3nan_prop_rule;
- FloatInfZeroNaNRule float_infzeronan_rule;
- bool tininess_before_rounding;
- /* should denormalised results go to zero and set output_denormal_flushed? */
- bool flush_to_zero;
- /* do we detect and flush denormal results before or after rounding? */
- FloatFTZDetection ftz_detection;
- /* should denormalised inputs go to zero and set input_denormal_flushed? */
- bool flush_inputs_to_zero;
- bool default_nan_mode;
- /*
- * The pattern to use for the default NaN. Here the high bit specifies
- * the default NaN's sign bit, and bits 6..0 specify the high bits of the
- * fractional part. The low bits of the fractional part are copies of bit 0.
- * The exponent of the default NaN is (as for any NaN) always all 1s.
- * Note that a value of 0 here is not a valid NaN. The target must set
- * this to the correct non-zero value, or we will assert when trying to
- * create a default NaN.
- */
- uint8_t default_nan_pattern;
- /*
- * The flags below are not used on all specializations and may
- * constant fold away (see snan_bit_is_one()/no_signalling_nans() in
- * softfloat-specialize.inc.c)
- */
- bool snan_bit_is_one;
- bool no_signaling_nans;
- /* should overflowed results subtract re_bias to its exponent? */
- bool rebias_overflow;
- /* should underflowed results add re_bias to its exponent? */
- bool rebias_underflow;
- } float_status;
- #endif /* SOFTFLOAT_TYPES_H */
|