/* ----------------------------------------------------------------------- * * * Copyright 1996-2018 The NASM Authors - All Rights Reserved * See the file AUTHORS included with the NASM distribution for * the specific copyright holders. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following * conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 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. * * 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 OWNER 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. * * ----------------------------------------------------------------------- */ /* * float.c floating-point constant support for the Netwide Assembler */ #include "compiler.h" #include "nctype.h" #include "nasm.h" #include "floats.h" #include "error.h" /* * ----------------- * local variables * ----------------- */ static bool daz = …; /* denormals as zero */ static enum float_round rc = …; /* rounding control */ /* * ----------- * constants * ----------- */ /* "A limb is like a digit but bigger */ fp_limb; fp_2limb; #define LIMB_BITS … #define LIMB_BYTES … #define LIMB_TOP_BIT … #define LIMB_MASK … #define LIMB_ALL_BYTES … #define LIMB_BYTE(x) … /* 112 bits + 64 bits for accuracy + 16 bits for rounding */ #define MANT_LIMBS … /* 52 digits fit in 176 bits because 10^53 > 2^176 > 10^52 */ #define MANT_DIGITS … /* the format and the argument list depend on MANT_LIMBS */ #define MANT_FMT … #define MANT_ARG … #define SOME_ARG(a,i) … /* * --------------------------------------------------------------------------- * emit a printf()-like debug message... but only if DEBUG_FLOAT was defined * --------------------------------------------------------------------------- */ #ifdef DEBUG_FLOAT #define dprintf … #else #define dprintf(x) … #endif /* * --------------------------------------------------------------------------- * multiply * --------------------------------------------------------------------------- */ static int float_multiply(fp_limb *to, fp_limb *from) { … } /* * --------------------------------------------------------------------------- * read an exponent; returns INT32_MAX on error * --------------------------------------------------------------------------- */ static int32_t read_exponent(const char *string, int32_t max) { … } /* * --------------------------------------------------------------------------- * convert * --------------------------------------------------------------------------- */ static bool ieee_flconvert(const char *string, fp_limb *mant, int32_t * exponent) { … } /* * --------------------------------------------------------------------------- * operations of specific bits * --------------------------------------------------------------------------- */ /* Set a bit, using *bigendian* bit numbering (0 = MSB) */ static void set_bit(fp_limb *mant, int bit) { … } /* Test a single bit */ static int test_bit(const fp_limb *mant, int bit) { … } /* Report if the mantissa value is all zero */ static bool is_zero(const fp_limb *mant) { … } /* * --------------------------------------------------------------------------- * round a mantissa off after i words * --------------------------------------------------------------------------- */ #define ROUND_COLLECT_BITS … #define ROUND_ABS_DOWN … #define ROUND_ABS_UP … static bool ieee_round(bool minus, fp_limb *mant, int bits) { … } /* Returns a value >= 16 if not a valid hex digit */ static unsigned int hexval(char c) { … } /* Handle floating-point numbers with radix 2^bits and binary exponent */ static bool ieee_flconvert_bin(const char *string, int bits, fp_limb *mant, int32_t *exponent) { … } /* * Shift a mantissa to the right by i bits. */ static void ieee_shr(fp_limb *mant, int i) { … } /* Produce standard IEEE formats, with implicit or explicit integer bit; this makes the following assumptions: - the sign bit is the MSB, followed by the exponent, followed by the integer bit if present. - the sign bit plus exponent fit in 16 bits. - the exponent bias is 2^(n-1)-1 for an n-bit exponent */ struct ieee_format { … }; /* * The 16- and 128-bit formats are expected to be in IEEE 754r. * AMD SSE5 uses the 16-bit format. * * The 32- and 64-bit formats are the original IEEE 754 formats. * * The 80-bit format is x87-specific, but widely used. * * The 8-bit format appears to be the consensus 8-bit floating-point * format. It is apparently used in graphics applications. */ static const struct ieee_format ieee_8 = …; static const struct ieee_format ieee_16 = …; static const struct ieee_format ieee_32 = …; static const struct ieee_format ieee_64 = …; static const struct ieee_format ieee_80 = …; static const struct ieee_format ieee_128 = …; /* Types of values we can generate */ enum floats { … }; static int to_packed_bcd(const char *str, const char *p, int s, uint8_t *result, const struct ieee_format *fmt) { … } static int to_float(const char *str, int s, uint8_t *result, const struct ieee_format *fmt) { … } int float_const(const char *number, int sign, uint8_t *result, int bytes) { … } /* Set floating-point options */ int float_option(const char *option) { … }