aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/tools/yasm/libyasm/floatnum.c
diff options
context:
space:
mode:
authorsomov <somov@yandex-team.ru>2022-02-10 16:45:47 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:47 +0300
commita5950576e397b1909261050b8c7da16db58f10b1 (patch)
tree7ba7677f6a4c3e19e2cefab34d16df2c8963b4d4 /contrib/tools/yasm/libyasm/floatnum.c
parent81eddc8c0b55990194e112b02d127b87d54164a9 (diff)
downloadydb-a5950576e397b1909261050b8c7da16db58f10b1.tar.gz
Restoring authorship annotation for <somov@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/yasm/libyasm/floatnum.c')
-rw-r--r--contrib/tools/yasm/libyasm/floatnum.c1520
1 files changed, 760 insertions, 760 deletions
diff --git a/contrib/tools/yasm/libyasm/floatnum.c b/contrib/tools/yasm/libyasm/floatnum.c
index ab67c2b2e4b..98eabeebcf8 100644
--- a/contrib/tools/yasm/libyasm/floatnum.c
+++ b/contrib/tools/yasm/libyasm/floatnum.c
@@ -1,760 +1,760 @@
-/*
- * Floating point number functions.
- *
- * Copyright (C) 2001-2007 Peter Johnson
- *
- * Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
- *
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER 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 AUTHOR OR OTHER 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 "util.h"
-
-#include <ctype.h>
-
-#include "coretype.h"
-#include "bitvect.h"
-#include "file.h"
-
-#include "errwarn.h"
-#include "floatnum.h"
-
-
-/* 97-bit internal floating point format:
- * 0000000s eeeeeeee eeeeeeee m.....................................m
- * Sign exponent mantissa (80 bits)
- * 79 0
- *
- * Only L.O. bit of Sign byte is significant. The rest is zero.
- * Exponent is bias 32767.
- * Mantissa does NOT have an implied one bit (it's explicit).
- */
-struct yasm_floatnum {
- /*@only@*/ wordptr mantissa; /* Allocated to MANT_BITS bits */
- unsigned short exponent;
- unsigned char sign;
- unsigned char flags;
-};
-
-/* constants describing parameters of internal floating point format */
-#define MANT_BITS 80
-#define MANT_BYTES 10
-#define MANT_SIGDIGITS 24
-#define EXP_BIAS 0x7FFF
-#define EXP_INF 0xFFFF
-#define EXP_MAX 0xFFFE
-#define EXP_MIN 1
-#define EXP_ZERO 0
-
-/* Flag settings for flags field */
-#define FLAG_ISZERO 1<<0
-
-/* Note this structure integrates the floatnum structure */
-typedef struct POT_Entry_s {
- yasm_floatnum f;
- int dec_exponent;
-} POT_Entry;
-
-/* "Source" for POT_Entry. */
-typedef struct POT_Entry_Source_s {
- unsigned char mantissa[MANT_BYTES]; /* little endian mantissa */
- unsigned short exponent; /* Bias 32767 exponent */
-} POT_Entry_Source;
-
-/* Power of ten tables used by the floating point I/O routines.
- * The POT_Table? arrays are built from the POT_Table?_Source arrays at
- * runtime by POT_Table_Init().
- */
-
-/* This table contains the powers of ten raised to negative powers of two:
- *
- * entry[12-n] = 10 ** (-2 ** n) for 0 <= n <= 12.
- * entry[13] = 1.0
- */
-static /*@only@*/ POT_Entry *POT_TableN;
-static POT_Entry_Source POT_TableN_Source[] = {
- {{0xe3,0x2d,0xde,0x9f,0xce,0xd2,0xc8,0x04,0xdd,0xa6},0x4ad8}, /* 1e-4096 */
- {{0x25,0x49,0xe4,0x2d,0x36,0x34,0x4f,0x53,0xae,0xce},0x656b}, /* 1e-2048 */
- {{0xa6,0x87,0xbd,0xc0,0x57,0xda,0xa5,0x82,0xa6,0xa2},0x72b5}, /* 1e-1024 */
- {{0x33,0x71,0x1c,0xd2,0x23,0xdb,0x32,0xee,0x49,0x90},0x795a}, /* 1e-512 */
- {{0x91,0xfa,0x39,0x19,0x7a,0x63,0x25,0x43,0x31,0xc0},0x7cac}, /* 1e-256 */
- {{0x7d,0xac,0xa0,0xe4,0xbc,0x64,0x7c,0x46,0xd0,0xdd},0x7e55}, /* 1e-128 */
- {{0x24,0x3f,0xa5,0xe9,0x39,0xa5,0x27,0xea,0x7f,0xa8},0x7f2a}, /* 1e-64 */
- {{0xde,0x67,0xba,0x94,0x39,0x45,0xad,0x1e,0xb1,0xcf},0x7f94}, /* 1e-32 */
- {{0x2f,0x4c,0x5b,0xe1,0x4d,0xc4,0xbe,0x94,0x95,0xe6},0x7fc9}, /* 1e-16 */
- {{0xc2,0xfd,0xfc,0xce,0x61,0x84,0x11,0x77,0xcc,0xab},0x7fe4}, /* 1e-8 */
- {{0xc3,0xd3,0x2b,0x65,0x19,0xe2,0x58,0x17,0xb7,0xd1},0x7ff1}, /* 1e-4 */
- {{0x71,0x3d,0x0a,0xd7,0xa3,0x70,0x3d,0x0a,0xd7,0xa3},0x7ff8}, /* 1e-2 */
- {{0xcd,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc},0x7ffb}, /* 1e-1 */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80},0x7fff}, /* 1e-0 */
-};
-
-/* This table contains the powers of ten raised to positive powers of two:
- *
- * entry[12-n] = 10 ** (2 ** n) for 0 <= n <= 12.
- * entry[13] = 1.0
- * entry[-1] = entry[0];
- *
- * There is a -1 entry since it is possible for the algorithm to back up
- * before the table. This -1 entry is created at runtime by duplicating the
- * 0 entry.
- */
-static /*@only@*/ POT_Entry *POT_TableP;
-static POT_Entry_Source POT_TableP_Source[] = {
- {{0x4c,0xc9,0x9a,0x97,0x20,0x8a,0x02,0x52,0x60,0xc4},0xb525}, /* 1e+4096 */
- {{0x4d,0xa7,0xe4,0x5d,0x3d,0xc5,0x5d,0x3b,0x8b,0x9e},0x9a92}, /* 1e+2048 */
- {{0x0d,0x65,0x17,0x0c,0x75,0x81,0x86,0x75,0x76,0xc9},0x8d48}, /* 1e+1024 */
- {{0x65,0xcc,0xc6,0x91,0x0e,0xa6,0xae,0xa0,0x19,0xe3},0x86a3}, /* 1e+512 */
- {{0xbc,0xdd,0x8d,0xde,0xf9,0x9d,0xfb,0xeb,0x7e,0xaa},0x8351}, /* 1e+256 */
- {{0x6f,0xc6,0xdf,0x8c,0xe9,0x80,0xc9,0x47,0xba,0x93},0x81a8}, /* 1e+128 */
- {{0xbf,0x3c,0xd5,0xa6,0xcf,0xff,0x49,0x1f,0x78,0xc2},0x80d3}, /* 1e+64 */
- {{0x20,0xf0,0x9d,0xb5,0x70,0x2b,0xa8,0xad,0xc5,0x9d},0x8069}, /* 1e+32 */
- {{0x00,0x00,0x00,0x00,0x00,0x04,0xbf,0xc9,0x1b,0x8e},0x8034}, /* 1e+16 */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xbc,0xbe},0x8019}, /* 1e+8 */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x9c},0x800c}, /* 1e+4 */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8},0x8005}, /* 1e+2 */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0},0x8002}, /* 1e+1 */
- {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80},0x7fff}, /* 1e+0 */
-};
-
-
-static void
-POT_Table_Init_Entry(/*@out@*/ POT_Entry *e, POT_Entry_Source *s, int dec_exp)
-{
- /* Save decimal exponent */
- e->dec_exponent = dec_exp;
-
- /* Initialize mantissa */
- e->f.mantissa = BitVector_Create(MANT_BITS, FALSE);
- BitVector_Block_Store(e->f.mantissa, s->mantissa, MANT_BYTES);
-
- /* Initialize exponent */
- e->f.exponent = s->exponent;
-
- /* Set sign to 0 (positive) */
- e->f.sign = 0;
-
- /* Clear flags */
- e->f.flags = 0;
-}
-
-/*@-compdef@*/
-void
-yasm_floatnum_initialize(void)
-/*@globals undef POT_TableN, undef POT_TableP, POT_TableP_Source,
- POT_TableN_Source @*/
-{
- int dec_exp = 1;
- int i;
-
- /* Allocate space for two POT tables */
- POT_TableN = yasm_xmalloc(14*sizeof(POT_Entry));
- POT_TableP = yasm_xmalloc(15*sizeof(POT_Entry)); /* note 1 extra for -1 */
-
- /* Initialize entry[0..12] */
- for (i=12; i>=0; i--) {
- POT_Table_Init_Entry(&POT_TableN[i], &POT_TableN_Source[i], 0-dec_exp);
- POT_Table_Init_Entry(&POT_TableP[i+1], &POT_TableP_Source[i], dec_exp);
- dec_exp *= 2; /* Update decimal exponent */
- }
-
- /* Initialize entry[13] */
- POT_Table_Init_Entry(&POT_TableN[13], &POT_TableN_Source[13], 0);
- POT_Table_Init_Entry(&POT_TableP[14], &POT_TableP_Source[13], 0);
-
- /* Initialize entry[-1] for POT_TableP */
- POT_Table_Init_Entry(&POT_TableP[0], &POT_TableP_Source[0], 4096);
-
- /* Offset POT_TableP so that [0] becomes [-1] */
- POT_TableP++;
-}
-/*@=compdef@*/
-
-/*@-globstate@*/
-void
-yasm_floatnum_cleanup(void)
-{
- int i;
-
- /* Un-offset POT_TableP */
- POT_TableP--;
-
- for (i=0; i<14; i++) {
- BitVector_Destroy(POT_TableN[i].f.mantissa);
- BitVector_Destroy(POT_TableP[i].f.mantissa);
- }
- BitVector_Destroy(POT_TableP[14].f.mantissa);
-
- yasm_xfree(POT_TableN);
- yasm_xfree(POT_TableP);
-}
-/*@=globstate@*/
-
-static void
-floatnum_normalize(yasm_floatnum *flt)
-{
- long norm_amt;
-
- if (BitVector_is_empty(flt->mantissa)) {
- flt->exponent = 0;
- return;
- }
-
- /* Look for the highest set bit, shift to make it the MSB, and adjust
- * exponent. Don't let exponent go negative. */
- norm_amt = (MANT_BITS-1)-Set_Max(flt->mantissa);
- if (norm_amt > (long)flt->exponent)
- norm_amt = (long)flt->exponent;
- BitVector_Move_Left(flt->mantissa, (N_int)norm_amt);
- flt->exponent -= (unsigned short)norm_amt;
-}
-
-/* acc *= op */
-static void
-floatnum_mul(yasm_floatnum *acc, const yasm_floatnum *op)
-{
- long expon;
- wordptr product, op1, op2;
- long norm_amt;
-
- /* Compute the new sign */
- acc->sign ^= op->sign;
-
- /* Check for multiply by 0 */
- if (BitVector_is_empty(acc->mantissa) || BitVector_is_empty(op->mantissa)) {
- BitVector_Empty(acc->mantissa);
- acc->exponent = EXP_ZERO;
- return;
- }
-
- /* Add exponents, checking for overflow/underflow. */
- expon = (((int)acc->exponent)-EXP_BIAS) + (((int)op->exponent)-EXP_BIAS);
- expon += EXP_BIAS;
- if (expon > EXP_MAX) {
- /* Overflow; return infinity. */
- BitVector_Empty(acc->mantissa);
- acc->exponent = EXP_INF;
- return;
- } else if (expon < EXP_MIN) {
- /* Underflow; return zero. */
- BitVector_Empty(acc->mantissa);
- acc->exponent = EXP_ZERO;
- return;
- }
-
- /* Add one to the final exponent, as the multiply shifts one extra time. */
- acc->exponent = (unsigned short)(expon+1);
-
- /* Allocate space for the multiply result */
- product = BitVector_Create((N_int)((MANT_BITS+1)*2), FALSE);
-
- /* Allocate 1-bit-longer fields to force the operands to be unsigned */
- op1 = BitVector_Create((N_int)(MANT_BITS+1), FALSE);
- op2 = BitVector_Create((N_int)(MANT_BITS+1), FALSE);
-
- /* Make the operands unsigned after copying from original operands */
- BitVector_Copy(op1, acc->mantissa);
- BitVector_MSB(op1, 0);
- BitVector_Copy(op2, op->mantissa);
- BitVector_MSB(op2, 0);
-
- /* Compute the product of the mantissas */
- BitVector_Multiply(product, op1, op2);
-
- /* Normalize the product. Note: we know the product is non-zero because
- * both of the original operands were non-zero.
- *
- * Look for the highest set bit, shift to make it the MSB, and adjust
- * exponent. Don't let exponent go negative.
- */
- norm_amt = (MANT_BITS*2-1)-Set_Max(product);
- if (norm_amt > (long)acc->exponent)
- norm_amt = (long)acc->exponent;
- BitVector_Move_Left(product, (N_int)norm_amt);
- acc->exponent -= (unsigned short)norm_amt;
-
- /* Store the highest bits of the result */
- BitVector_Interval_Copy(acc->mantissa, product, 0, MANT_BITS, MANT_BITS);
-
- /* Free allocated variables */
- BitVector_Destroy(product);
- BitVector_Destroy(op1);
- BitVector_Destroy(op2);
-}
-
-yasm_floatnum *
-yasm_floatnum_create(const char *str)
-{
- yasm_floatnum *flt;
- int dec_exponent, dec_exp_add; /* decimal (powers of 10) exponent */
- int POT_index;
- wordptr operand[2];
- int sig_digits;
- int decimal_pt;
- boolean carry;
-
- flt = yasm_xmalloc(sizeof(yasm_floatnum));
-
- flt->mantissa = BitVector_Create(MANT_BITS, TRUE);
-
- /* allocate and initialize calculation variables */
- operand[0] = BitVector_Create(MANT_BITS, TRUE);
- operand[1] = BitVector_Create(MANT_BITS, TRUE);
- dec_exponent = 0;
- sig_digits = 0;
- decimal_pt = 1;
-
- /* set initial flags to 0 */
- flt->flags = 0;
-
- /* check for + or - character and skip */
- if (*str == '-') {
- flt->sign = 1;
- str++;
- } else if (*str == '+') {
- flt->sign = 0;
- str++;
- } else
- flt->sign = 0;
-
- /* eliminate any leading zeros (which do not count as significant digits) */
- while (*str == '0')
- str++;
-
- /* When we reach the end of the leading zeros, first check for a decimal
- * point. If the number is of the form "0---0.0000" we need to get rid
- * of the zeros after the decimal point and not count them as significant
- * digits.
- */
- if (*str == '.') {
- str++;
- while (*str == '0') {
- str++;
- dec_exponent--;
- }
- } else {
- /* The number is of the form "yyy.xxxx" (where y <> 0). */
- while (isdigit(*str)) {
- /* See if we've processed more than the max significant digits: */
- if (sig_digits < MANT_SIGDIGITS) {
- /* Multiply mantissa by 10 [x = (x<<1)+(x<<3)] */
- BitVector_shift_left(flt->mantissa, 0);
- BitVector_Copy(operand[0], flt->mantissa);
- BitVector_Move_Left(flt->mantissa, 2);
- carry = 0;
- BitVector_add(operand[1], operand[0], flt->mantissa, &carry);
-
- /* Add in current digit */
- BitVector_Empty(operand[0]);
- BitVector_Chunk_Store(operand[0], 4, 0, (N_long)(*str-'0'));
- carry = 0;
- BitVector_add(flt->mantissa, operand[1], operand[0], &carry);
- } else {
- /* Can't integrate more digits with mantissa, so instead just
- * raise by a power of ten.
- */
- dec_exponent++;
- }
- sig_digits++;
- str++;
- }
-
- if (*str == '.')
- str++;
- else
- decimal_pt = 0;
- }
-
- if (decimal_pt) {
- /* Process the digits to the right of the decimal point. */
- while (isdigit(*str)) {
- /* See if we've processed more than 19 significant digits: */
- if (sig_digits < 19) {
- /* Raise by a power of ten */
- dec_exponent--;
-
- /* Multiply mantissa by 10 [x = (x<<1)+(x<<3)] */
- BitVector_shift_left(flt->mantissa, 0);
- BitVector_Copy(operand[0], flt->mantissa);
- BitVector_Move_Left(flt->mantissa, 2);
- carry = 0;
- BitVector_add(operand[1], operand[0], flt->mantissa, &carry);
-
- /* Add in current digit */
- BitVector_Empty(operand[0]);
- BitVector_Chunk_Store(operand[0], 4, 0, (N_long)(*str-'0'));
- carry = 0;
- BitVector_add(flt->mantissa, operand[1], operand[0], &carry);
- }
- sig_digits++;
- str++;
- }
- }
-
- if (*str == 'e' || *str == 'E') {
- str++;
- /* We just saw the "E" character, now read in the exponent value and
- * add it into dec_exponent.
- */
- dec_exp_add = 0;
- sscanf(str, "%d", &dec_exp_add);
- dec_exponent += dec_exp_add;
- }
-
- /* Free calculation variables. */
- BitVector_Destroy(operand[1]);
- BitVector_Destroy(operand[0]);
-
- /* Normalize the number, checking for 0 first. */
- if (BitVector_is_empty(flt->mantissa)) {
- /* Mantissa is 0, zero exponent too. */
- flt->exponent = 0;
- /* Set zero flag so output functions don't see 0 value as underflow. */
- flt->flags |= FLAG_ISZERO;
- /* Return 0 value. */
- return flt;
- }
- /* Exponent if already norm. */
- flt->exponent = (unsigned short)(0x7FFF+(MANT_BITS-1));
- floatnum_normalize(flt);
-
- /* The number is normalized. Now multiply by 10 the number of times
- * specified in DecExponent. This uses the power of ten tables to speed
- * up this operation (and make it more accurate).
- */
- if (dec_exponent > 0) {
- POT_index = 0;
- /* Until we hit 1.0 or finish exponent or overflow */
- while ((POT_index < 14) && (dec_exponent != 0) &&
- (flt->exponent != EXP_INF)) {
- /* Find the first power of ten in the table which is just less than
- * the exponent.
- */
- while (dec_exponent < POT_TableP[POT_index].dec_exponent)
- POT_index++;
-
- if (POT_index < 14) {
- /* Subtract out what we're multiplying in from exponent */
- dec_exponent -= POT_TableP[POT_index].dec_exponent;
-
- /* Multiply by current power of 10 */
- floatnum_mul(flt, &POT_TableP[POT_index].f);
- }
- }
- } else if (dec_exponent < 0) {
- POT_index = 0;
- /* Until we hit 1.0 or finish exponent or underflow */
- while ((POT_index < 14) && (dec_exponent != 0) &&
- (flt->exponent != EXP_ZERO)) {
- /* Find the first power of ten in the table which is just less than
- * the exponent.
- */
- while (dec_exponent > POT_TableN[POT_index].dec_exponent)
- POT_index++;
-
- if (POT_index < 14) {
- /* Subtract out what we're multiplying in from exponent */
- dec_exponent -= POT_TableN[POT_index].dec_exponent;
-
- /* Multiply by current power of 10 */
- floatnum_mul(flt, &POT_TableN[POT_index].f);
- }
- }
- }
-
- /* Round the result. (Don't round underflow or overflow). Also don't
- * increment if this would cause the mantissa to wrap.
- */
- if ((flt->exponent != EXP_INF) && (flt->exponent != EXP_ZERO) &&
- !BitVector_is_full(flt->mantissa))
- BitVector_increment(flt->mantissa);
-
- return flt;
-}
-
-yasm_floatnum *
-yasm_floatnum_copy(const yasm_floatnum *flt)
-{
- yasm_floatnum *f = yasm_xmalloc(sizeof(yasm_floatnum));
-
- f->mantissa = BitVector_Clone(flt->mantissa);
- f->exponent = flt->exponent;
- f->sign = flt->sign;
- f->flags = flt->flags;
-
- return f;
-}
-
-void
-yasm_floatnum_destroy(yasm_floatnum *flt)
-{
- BitVector_Destroy(flt->mantissa);
- yasm_xfree(flt);
-}
-
-int
-yasm_floatnum_calc(yasm_floatnum *acc, yasm_expr_op op,
- /*@unused@*/ yasm_floatnum *operand)
-{
- if (op != YASM_EXPR_NEG) {
- yasm_error_set(YASM_ERROR_FLOATING_POINT,
- N_("Unsupported floating-point arithmetic operation"));
- return 1;
- }
- acc->sign ^= 1;
- return 0;
-}
-
-int
-yasm_floatnum_get_int(const yasm_floatnum *flt, unsigned long *ret_val)
-{
- unsigned char t[4];
-
- if (yasm_floatnum_get_sized(flt, t, 4, 32, 0, 0, 0)) {
- *ret_val = 0xDEADBEEFUL; /* Obviously incorrect return value */
- return 1;
- }
-
- YASM_LOAD_32_L(*ret_val, &t[0]);
- return 0;
-}
-
-/* Function used by conversion routines to actually perform the conversion.
- *
- * ptr -> the array to return the little-endian floating point value into.
- * flt -> the floating point value to convert.
- * byte_size -> the size in bytes of the output format.
- * mant_bits -> the size in bits of the output mantissa.
- * implicit1 -> does the output format have an implicit 1? 1=yes, 0=no.
- * exp_bits -> the size in bits of the output exponent.
- *
- * Returns 0 on success, 1 if overflow, -1 if underflow.
- */
-static int
-floatnum_get_common(const yasm_floatnum *flt, /*@out@*/ unsigned char *ptr,
- N_int byte_size, N_int mant_bits, int implicit1,
- N_int exp_bits)
-{
- long exponent = (long)flt->exponent;
- wordptr output;
- charptr buf;
- unsigned int len;
- unsigned int overflow = 0, underflow = 0;
- int retval = 0;
- long exp_bias = (1<<(exp_bits-1))-1;
- long exp_inf = (1<<exp_bits)-1;
-
- output = BitVector_Create(byte_size*8, TRUE);
-
- /* copy mantissa */
- BitVector_Interval_Copy(output, flt->mantissa, 0,
- (N_int)((MANT_BITS-implicit1)-mant_bits),
- mant_bits);
-
- /* round mantissa */
- if (BitVector_bit_test(flt->mantissa, (MANT_BITS-implicit1)-(mant_bits+1)))
- BitVector_increment(output);
-
- if (BitVector_bit_test(output, mant_bits)) {
- /* overflowed, so zero mantissa (and set explicit bit if necessary) */
- BitVector_Empty(output);
- BitVector_Bit_Copy(output, mant_bits-1, !implicit1);
- /* and up the exponent (checking for overflow) */
- if (exponent+1 >= EXP_INF)
- overflow = 1;
- else
- exponent++;
- }
-
- /* adjust the exponent to the output bias, checking for overflow */
- exponent -= EXP_BIAS-exp_bias;
- if (exponent >= exp_inf)
- overflow = 1;
- else if (exponent <= 0)
- underflow = 1;
-
- /* underflow and overflow both set!? */
- if (underflow && overflow)
- yasm_internal_error(N_("Both underflow and overflow set"));
-
- /* check for underflow or overflow and set up appropriate output */
- if (underflow) {
- BitVector_Empty(output);
- exponent = 0;
- if (!(flt->flags & FLAG_ISZERO))
- retval = -1;
- } else if (overflow) {
- BitVector_Empty(output);
- exponent = exp_inf;
- retval = 1;
- }
-
- /* move exponent into place */
- BitVector_Chunk_Store(output, exp_bits, mant_bits, (N_long)exponent);
-
- /* merge in sign bit */
- BitVector_Bit_Copy(output, byte_size*8-1, flt->sign);
-
- /* get little-endian bytes */
- buf = BitVector_Block_Read(output, &len);
- if (len < byte_size)
- yasm_internal_error(
- N_("Byte length of BitVector does not match bit length"));
-
- /* copy to output */
- memcpy(ptr, buf, byte_size*sizeof(unsigned char));
-
- /* free allocated resources */
- yasm_xfree(buf);
-
- BitVector_Destroy(output);
-
- return retval;
-}
-
-/* IEEE-754r "half precision" format:
- * 16 bits:
- * 15 9 Bit 0
- * | | |
- * seee eemm mmmm mmmm
- *
- * e = bias 15 exponent
- * s = sign bit
- * m = mantissa bits, bit 10 is an implied one bit.
- *
- * IEEE-754 (Intel) "single precision" format:
- * 32 bits:
- * Bit 31 Bit 22 Bit 0
- * | | |
- * seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
- *
- * e = bias 127 exponent
- * s = sign bit
- * m = mantissa bits, bit 23 is an implied one bit.
- *
- * IEEE-754 (Intel) "double precision" format:
- * 64 bits:
- * bit 63 bit 51 bit 0
- * | | |
- * seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
- *
- * e = bias 1023 exponent.
- * s = sign bit.
- * m = mantissa bits. Bit 52 is an implied one bit.
- *
- * IEEE-754 (Intel) "extended precision" format:
- * 80 bits:
- * bit 79 bit 63 bit 0
- * | | |
- * seeeeeee eeeeeeee mmmmmmmm m...m m...m m...m m...m m...m
- *
- * e = bias 16383 exponent
- * m = 64 bit mantissa with NO implied bit!
- * s = sign (for mantissa)
- */
-int
-yasm_floatnum_get_sized(const yasm_floatnum *flt, unsigned char *ptr,
- size_t destsize, size_t valsize, size_t shift,
- int bigendian, int warn)
-{
- int retval;
- if (destsize*8 != valsize || shift>0 || bigendian) {
- /* TODO */
- yasm_internal_error(N_("unsupported floatnum functionality"));
- }
- switch (destsize) {
- case 2:
- retval = floatnum_get_common(flt, ptr, 2, 10, 1, 5);
- break;
- case 4:
- retval = floatnum_get_common(flt, ptr, 4, 23, 1, 8);
- break;
- case 8:
- retval = floatnum_get_common(flt, ptr, 8, 52, 1, 11);
- break;
- case 10:
- retval = floatnum_get_common(flt, ptr, 10, 64, 0, 15);
- break;
- default:
- yasm_internal_error(N_("Invalid float conversion size"));
- /*@notreached@*/
- return 1;
- }
- if (warn) {
- if (retval < 0)
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("underflow in floating point expression"));
- else if (retval > 0)
- yasm_warn_set(YASM_WARN_GENERAL,
- N_("overflow in floating point expression"));
- }
- return retval;
-}
-
-/* 1 if the size is valid, 0 if it isn't */
-int
-yasm_floatnum_check_size(/*@unused@*/ const yasm_floatnum *flt, size_t size)
-{
- switch (size) {
- case 16:
- case 32:
- case 64:
- case 80:
- return 1;
- default:
- return 0;
- }
-}
-
-void
-yasm_floatnum_print(const yasm_floatnum *flt, FILE *f)
-{
- unsigned char out[10];
- unsigned char *str;
- int i;
-
- /* Internal format */
- str = BitVector_to_Hex(flt->mantissa);
- fprintf(f, "%c %s *2^%04x\n", flt->sign?'-':'+', (char *)str,
- flt->exponent);
- yasm_xfree(str);
-
- /* 32-bit (single precision) format */
- fprintf(f, "32-bit: %d: ",
- yasm_floatnum_get_sized(flt, out, 4, 32, 0, 0, 0));
- for (i=0; i<4; i++)
- fprintf(f, "%02x ", out[i]);
- fprintf(f, "\n");
-
- /* 64-bit (double precision) format */
- fprintf(f, "64-bit: %d: ",
- yasm_floatnum_get_sized(flt, out, 8, 64, 0, 0, 0));
- for (i=0; i<8; i++)
- fprintf(f, "%02x ", out[i]);
- fprintf(f, "\n");
-
- /* 80-bit (extended precision) format */
- fprintf(f, "80-bit: %d: ",
- yasm_floatnum_get_sized(flt, out, 10, 80, 0, 0, 0));
- for (i=0; i<10; i++)
- fprintf(f, "%02x ", out[i]);
- fprintf(f, "\n");
-}
+/*
+ * Floating point number functions.
+ *
+ * Copyright (C) 2001-2007 Peter Johnson
+ *
+ * Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER 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 AUTHOR OR OTHER 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 "util.h"
+
+#include <ctype.h>
+
+#include "coretype.h"
+#include "bitvect.h"
+#include "file.h"
+
+#include "errwarn.h"
+#include "floatnum.h"
+
+
+/* 97-bit internal floating point format:
+ * 0000000s eeeeeeee eeeeeeee m.....................................m
+ * Sign exponent mantissa (80 bits)
+ * 79 0
+ *
+ * Only L.O. bit of Sign byte is significant. The rest is zero.
+ * Exponent is bias 32767.
+ * Mantissa does NOT have an implied one bit (it's explicit).
+ */
+struct yasm_floatnum {
+ /*@only@*/ wordptr mantissa; /* Allocated to MANT_BITS bits */
+ unsigned short exponent;
+ unsigned char sign;
+ unsigned char flags;
+};
+
+/* constants describing parameters of internal floating point format */
+#define MANT_BITS 80
+#define MANT_BYTES 10
+#define MANT_SIGDIGITS 24
+#define EXP_BIAS 0x7FFF
+#define EXP_INF 0xFFFF
+#define EXP_MAX 0xFFFE
+#define EXP_MIN 1
+#define EXP_ZERO 0
+
+/* Flag settings for flags field */
+#define FLAG_ISZERO 1<<0
+
+/* Note this structure integrates the floatnum structure */
+typedef struct POT_Entry_s {
+ yasm_floatnum f;
+ int dec_exponent;
+} POT_Entry;
+
+/* "Source" for POT_Entry. */
+typedef struct POT_Entry_Source_s {
+ unsigned char mantissa[MANT_BYTES]; /* little endian mantissa */
+ unsigned short exponent; /* Bias 32767 exponent */
+} POT_Entry_Source;
+
+/* Power of ten tables used by the floating point I/O routines.
+ * The POT_Table? arrays are built from the POT_Table?_Source arrays at
+ * runtime by POT_Table_Init().
+ */
+
+/* This table contains the powers of ten raised to negative powers of two:
+ *
+ * entry[12-n] = 10 ** (-2 ** n) for 0 <= n <= 12.
+ * entry[13] = 1.0
+ */
+static /*@only@*/ POT_Entry *POT_TableN;
+static POT_Entry_Source POT_TableN_Source[] = {
+ {{0xe3,0x2d,0xde,0x9f,0xce,0xd2,0xc8,0x04,0xdd,0xa6},0x4ad8}, /* 1e-4096 */
+ {{0x25,0x49,0xe4,0x2d,0x36,0x34,0x4f,0x53,0xae,0xce},0x656b}, /* 1e-2048 */
+ {{0xa6,0x87,0xbd,0xc0,0x57,0xda,0xa5,0x82,0xa6,0xa2},0x72b5}, /* 1e-1024 */
+ {{0x33,0x71,0x1c,0xd2,0x23,0xdb,0x32,0xee,0x49,0x90},0x795a}, /* 1e-512 */
+ {{0x91,0xfa,0x39,0x19,0x7a,0x63,0x25,0x43,0x31,0xc0},0x7cac}, /* 1e-256 */
+ {{0x7d,0xac,0xa0,0xe4,0xbc,0x64,0x7c,0x46,0xd0,0xdd},0x7e55}, /* 1e-128 */
+ {{0x24,0x3f,0xa5,0xe9,0x39,0xa5,0x27,0xea,0x7f,0xa8},0x7f2a}, /* 1e-64 */
+ {{0xde,0x67,0xba,0x94,0x39,0x45,0xad,0x1e,0xb1,0xcf},0x7f94}, /* 1e-32 */
+ {{0x2f,0x4c,0x5b,0xe1,0x4d,0xc4,0xbe,0x94,0x95,0xe6},0x7fc9}, /* 1e-16 */
+ {{0xc2,0xfd,0xfc,0xce,0x61,0x84,0x11,0x77,0xcc,0xab},0x7fe4}, /* 1e-8 */
+ {{0xc3,0xd3,0x2b,0x65,0x19,0xe2,0x58,0x17,0xb7,0xd1},0x7ff1}, /* 1e-4 */
+ {{0x71,0x3d,0x0a,0xd7,0xa3,0x70,0x3d,0x0a,0xd7,0xa3},0x7ff8}, /* 1e-2 */
+ {{0xcd,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc},0x7ffb}, /* 1e-1 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80},0x7fff}, /* 1e-0 */
+};
+
+/* This table contains the powers of ten raised to positive powers of two:
+ *
+ * entry[12-n] = 10 ** (2 ** n) for 0 <= n <= 12.
+ * entry[13] = 1.0
+ * entry[-1] = entry[0];
+ *
+ * There is a -1 entry since it is possible for the algorithm to back up
+ * before the table. This -1 entry is created at runtime by duplicating the
+ * 0 entry.
+ */
+static /*@only@*/ POT_Entry *POT_TableP;
+static POT_Entry_Source POT_TableP_Source[] = {
+ {{0x4c,0xc9,0x9a,0x97,0x20,0x8a,0x02,0x52,0x60,0xc4},0xb525}, /* 1e+4096 */
+ {{0x4d,0xa7,0xe4,0x5d,0x3d,0xc5,0x5d,0x3b,0x8b,0x9e},0x9a92}, /* 1e+2048 */
+ {{0x0d,0x65,0x17,0x0c,0x75,0x81,0x86,0x75,0x76,0xc9},0x8d48}, /* 1e+1024 */
+ {{0x65,0xcc,0xc6,0x91,0x0e,0xa6,0xae,0xa0,0x19,0xe3},0x86a3}, /* 1e+512 */
+ {{0xbc,0xdd,0x8d,0xde,0xf9,0x9d,0xfb,0xeb,0x7e,0xaa},0x8351}, /* 1e+256 */
+ {{0x6f,0xc6,0xdf,0x8c,0xe9,0x80,0xc9,0x47,0xba,0x93},0x81a8}, /* 1e+128 */
+ {{0xbf,0x3c,0xd5,0xa6,0xcf,0xff,0x49,0x1f,0x78,0xc2},0x80d3}, /* 1e+64 */
+ {{0x20,0xf0,0x9d,0xb5,0x70,0x2b,0xa8,0xad,0xc5,0x9d},0x8069}, /* 1e+32 */
+ {{0x00,0x00,0x00,0x00,0x00,0x04,0xbf,0xc9,0x1b,0x8e},0x8034}, /* 1e+16 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0xbc,0xbe},0x8019}, /* 1e+8 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x9c},0x800c}, /* 1e+4 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8},0x8005}, /* 1e+2 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa0},0x8002}, /* 1e+1 */
+ {{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80},0x7fff}, /* 1e+0 */
+};
+
+
+static void
+POT_Table_Init_Entry(/*@out@*/ POT_Entry *e, POT_Entry_Source *s, int dec_exp)
+{
+ /* Save decimal exponent */
+ e->dec_exponent = dec_exp;
+
+ /* Initialize mantissa */
+ e->f.mantissa = BitVector_Create(MANT_BITS, FALSE);
+ BitVector_Block_Store(e->f.mantissa, s->mantissa, MANT_BYTES);
+
+ /* Initialize exponent */
+ e->f.exponent = s->exponent;
+
+ /* Set sign to 0 (positive) */
+ e->f.sign = 0;
+
+ /* Clear flags */
+ e->f.flags = 0;
+}
+
+/*@-compdef@*/
+void
+yasm_floatnum_initialize(void)
+/*@globals undef POT_TableN, undef POT_TableP, POT_TableP_Source,
+ POT_TableN_Source @*/
+{
+ int dec_exp = 1;
+ int i;
+
+ /* Allocate space for two POT tables */
+ POT_TableN = yasm_xmalloc(14*sizeof(POT_Entry));
+ POT_TableP = yasm_xmalloc(15*sizeof(POT_Entry)); /* note 1 extra for -1 */
+
+ /* Initialize entry[0..12] */
+ for (i=12; i>=0; i--) {
+ POT_Table_Init_Entry(&POT_TableN[i], &POT_TableN_Source[i], 0-dec_exp);
+ POT_Table_Init_Entry(&POT_TableP[i+1], &POT_TableP_Source[i], dec_exp);
+ dec_exp *= 2; /* Update decimal exponent */
+ }
+
+ /* Initialize entry[13] */
+ POT_Table_Init_Entry(&POT_TableN[13], &POT_TableN_Source[13], 0);
+ POT_Table_Init_Entry(&POT_TableP[14], &POT_TableP_Source[13], 0);
+
+ /* Initialize entry[-1] for POT_TableP */
+ POT_Table_Init_Entry(&POT_TableP[0], &POT_TableP_Source[0], 4096);
+
+ /* Offset POT_TableP so that [0] becomes [-1] */
+ POT_TableP++;
+}
+/*@=compdef@*/
+
+/*@-globstate@*/
+void
+yasm_floatnum_cleanup(void)
+{
+ int i;
+
+ /* Un-offset POT_TableP */
+ POT_TableP--;
+
+ for (i=0; i<14; i++) {
+ BitVector_Destroy(POT_TableN[i].f.mantissa);
+ BitVector_Destroy(POT_TableP[i].f.mantissa);
+ }
+ BitVector_Destroy(POT_TableP[14].f.mantissa);
+
+ yasm_xfree(POT_TableN);
+ yasm_xfree(POT_TableP);
+}
+/*@=globstate@*/
+
+static void
+floatnum_normalize(yasm_floatnum *flt)
+{
+ long norm_amt;
+
+ if (BitVector_is_empty(flt->mantissa)) {
+ flt->exponent = 0;
+ return;
+ }
+
+ /* Look for the highest set bit, shift to make it the MSB, and adjust
+ * exponent. Don't let exponent go negative. */
+ norm_amt = (MANT_BITS-1)-Set_Max(flt->mantissa);
+ if (norm_amt > (long)flt->exponent)
+ norm_amt = (long)flt->exponent;
+ BitVector_Move_Left(flt->mantissa, (N_int)norm_amt);
+ flt->exponent -= (unsigned short)norm_amt;
+}
+
+/* acc *= op */
+static void
+floatnum_mul(yasm_floatnum *acc, const yasm_floatnum *op)
+{
+ long expon;
+ wordptr product, op1, op2;
+ long norm_amt;
+
+ /* Compute the new sign */
+ acc->sign ^= op->sign;
+
+ /* Check for multiply by 0 */
+ if (BitVector_is_empty(acc->mantissa) || BitVector_is_empty(op->mantissa)) {
+ BitVector_Empty(acc->mantissa);
+ acc->exponent = EXP_ZERO;
+ return;
+ }
+
+ /* Add exponents, checking for overflow/underflow. */
+ expon = (((int)acc->exponent)-EXP_BIAS) + (((int)op->exponent)-EXP_BIAS);
+ expon += EXP_BIAS;
+ if (expon > EXP_MAX) {
+ /* Overflow; return infinity. */
+ BitVector_Empty(acc->mantissa);
+ acc->exponent = EXP_INF;
+ return;
+ } else if (expon < EXP_MIN) {
+ /* Underflow; return zero. */
+ BitVector_Empty(acc->mantissa);
+ acc->exponent = EXP_ZERO;
+ return;
+ }
+
+ /* Add one to the final exponent, as the multiply shifts one extra time. */
+ acc->exponent = (unsigned short)(expon+1);
+
+ /* Allocate space for the multiply result */
+ product = BitVector_Create((N_int)((MANT_BITS+1)*2), FALSE);
+
+ /* Allocate 1-bit-longer fields to force the operands to be unsigned */
+ op1 = BitVector_Create((N_int)(MANT_BITS+1), FALSE);
+ op2 = BitVector_Create((N_int)(MANT_BITS+1), FALSE);
+
+ /* Make the operands unsigned after copying from original operands */
+ BitVector_Copy(op1, acc->mantissa);
+ BitVector_MSB(op1, 0);
+ BitVector_Copy(op2, op->mantissa);
+ BitVector_MSB(op2, 0);
+
+ /* Compute the product of the mantissas */
+ BitVector_Multiply(product, op1, op2);
+
+ /* Normalize the product. Note: we know the product is non-zero because
+ * both of the original operands were non-zero.
+ *
+ * Look for the highest set bit, shift to make it the MSB, and adjust
+ * exponent. Don't let exponent go negative.
+ */
+ norm_amt = (MANT_BITS*2-1)-Set_Max(product);
+ if (norm_amt > (long)acc->exponent)
+ norm_amt = (long)acc->exponent;
+ BitVector_Move_Left(product, (N_int)norm_amt);
+ acc->exponent -= (unsigned short)norm_amt;
+
+ /* Store the highest bits of the result */
+ BitVector_Interval_Copy(acc->mantissa, product, 0, MANT_BITS, MANT_BITS);
+
+ /* Free allocated variables */
+ BitVector_Destroy(product);
+ BitVector_Destroy(op1);
+ BitVector_Destroy(op2);
+}
+
+yasm_floatnum *
+yasm_floatnum_create(const char *str)
+{
+ yasm_floatnum *flt;
+ int dec_exponent, dec_exp_add; /* decimal (powers of 10) exponent */
+ int POT_index;
+ wordptr operand[2];
+ int sig_digits;
+ int decimal_pt;
+ boolean carry;
+
+ flt = yasm_xmalloc(sizeof(yasm_floatnum));
+
+ flt->mantissa = BitVector_Create(MANT_BITS, TRUE);
+
+ /* allocate and initialize calculation variables */
+ operand[0] = BitVector_Create(MANT_BITS, TRUE);
+ operand[1] = BitVector_Create(MANT_BITS, TRUE);
+ dec_exponent = 0;
+ sig_digits = 0;
+ decimal_pt = 1;
+
+ /* set initial flags to 0 */
+ flt->flags = 0;
+
+ /* check for + or - character and skip */
+ if (*str == '-') {
+ flt->sign = 1;
+ str++;
+ } else if (*str == '+') {
+ flt->sign = 0;
+ str++;
+ } else
+ flt->sign = 0;
+
+ /* eliminate any leading zeros (which do not count as significant digits) */
+ while (*str == '0')
+ str++;
+
+ /* When we reach the end of the leading zeros, first check for a decimal
+ * point. If the number is of the form "0---0.0000" we need to get rid
+ * of the zeros after the decimal point and not count them as significant
+ * digits.
+ */
+ if (*str == '.') {
+ str++;
+ while (*str == '0') {
+ str++;
+ dec_exponent--;
+ }
+ } else {
+ /* The number is of the form "yyy.xxxx" (where y <> 0). */
+ while (isdigit(*str)) {
+ /* See if we've processed more than the max significant digits: */
+ if (sig_digits < MANT_SIGDIGITS) {
+ /* Multiply mantissa by 10 [x = (x<<1)+(x<<3)] */
+ BitVector_shift_left(flt->mantissa, 0);
+ BitVector_Copy(operand[0], flt->mantissa);
+ BitVector_Move_Left(flt->mantissa, 2);
+ carry = 0;
+ BitVector_add(operand[1], operand[0], flt->mantissa, &carry);
+
+ /* Add in current digit */
+ BitVector_Empty(operand[0]);
+ BitVector_Chunk_Store(operand[0], 4, 0, (N_long)(*str-'0'));
+ carry = 0;
+ BitVector_add(flt->mantissa, operand[1], operand[0], &carry);
+ } else {
+ /* Can't integrate more digits with mantissa, so instead just
+ * raise by a power of ten.
+ */
+ dec_exponent++;
+ }
+ sig_digits++;
+ str++;
+ }
+
+ if (*str == '.')
+ str++;
+ else
+ decimal_pt = 0;
+ }
+
+ if (decimal_pt) {
+ /* Process the digits to the right of the decimal point. */
+ while (isdigit(*str)) {
+ /* See if we've processed more than 19 significant digits: */
+ if (sig_digits < 19) {
+ /* Raise by a power of ten */
+ dec_exponent--;
+
+ /* Multiply mantissa by 10 [x = (x<<1)+(x<<3)] */
+ BitVector_shift_left(flt->mantissa, 0);
+ BitVector_Copy(operand[0], flt->mantissa);
+ BitVector_Move_Left(flt->mantissa, 2);
+ carry = 0;
+ BitVector_add(operand[1], operand[0], flt->mantissa, &carry);
+
+ /* Add in current digit */
+ BitVector_Empty(operand[0]);
+ BitVector_Chunk_Store(operand[0], 4, 0, (N_long)(*str-'0'));
+ carry = 0;
+ BitVector_add(flt->mantissa, operand[1], operand[0], &carry);
+ }
+ sig_digits++;
+ str++;
+ }
+ }
+
+ if (*str == 'e' || *str == 'E') {
+ str++;
+ /* We just saw the "E" character, now read in the exponent value and
+ * add it into dec_exponent.
+ */
+ dec_exp_add = 0;
+ sscanf(str, "%d", &dec_exp_add);
+ dec_exponent += dec_exp_add;
+ }
+
+ /* Free calculation variables. */
+ BitVector_Destroy(operand[1]);
+ BitVector_Destroy(operand[0]);
+
+ /* Normalize the number, checking for 0 first. */
+ if (BitVector_is_empty(flt->mantissa)) {
+ /* Mantissa is 0, zero exponent too. */
+ flt->exponent = 0;
+ /* Set zero flag so output functions don't see 0 value as underflow. */
+ flt->flags |= FLAG_ISZERO;
+ /* Return 0 value. */
+ return flt;
+ }
+ /* Exponent if already norm. */
+ flt->exponent = (unsigned short)(0x7FFF+(MANT_BITS-1));
+ floatnum_normalize(flt);
+
+ /* The number is normalized. Now multiply by 10 the number of times
+ * specified in DecExponent. This uses the power of ten tables to speed
+ * up this operation (and make it more accurate).
+ */
+ if (dec_exponent > 0) {
+ POT_index = 0;
+ /* Until we hit 1.0 or finish exponent or overflow */
+ while ((POT_index < 14) && (dec_exponent != 0) &&
+ (flt->exponent != EXP_INF)) {
+ /* Find the first power of ten in the table which is just less than
+ * the exponent.
+ */
+ while (dec_exponent < POT_TableP[POT_index].dec_exponent)
+ POT_index++;
+
+ if (POT_index < 14) {
+ /* Subtract out what we're multiplying in from exponent */
+ dec_exponent -= POT_TableP[POT_index].dec_exponent;
+
+ /* Multiply by current power of 10 */
+ floatnum_mul(flt, &POT_TableP[POT_index].f);
+ }
+ }
+ } else if (dec_exponent < 0) {
+ POT_index = 0;
+ /* Until we hit 1.0 or finish exponent or underflow */
+ while ((POT_index < 14) && (dec_exponent != 0) &&
+ (flt->exponent != EXP_ZERO)) {
+ /* Find the first power of ten in the table which is just less than
+ * the exponent.
+ */
+ while (dec_exponent > POT_TableN[POT_index].dec_exponent)
+ POT_index++;
+
+ if (POT_index < 14) {
+ /* Subtract out what we're multiplying in from exponent */
+ dec_exponent -= POT_TableN[POT_index].dec_exponent;
+
+ /* Multiply by current power of 10 */
+ floatnum_mul(flt, &POT_TableN[POT_index].f);
+ }
+ }
+ }
+
+ /* Round the result. (Don't round underflow or overflow). Also don't
+ * increment if this would cause the mantissa to wrap.
+ */
+ if ((flt->exponent != EXP_INF) && (flt->exponent != EXP_ZERO) &&
+ !BitVector_is_full(flt->mantissa))
+ BitVector_increment(flt->mantissa);
+
+ return flt;
+}
+
+yasm_floatnum *
+yasm_floatnum_copy(const yasm_floatnum *flt)
+{
+ yasm_floatnum *f = yasm_xmalloc(sizeof(yasm_floatnum));
+
+ f->mantissa = BitVector_Clone(flt->mantissa);
+ f->exponent = flt->exponent;
+ f->sign = flt->sign;
+ f->flags = flt->flags;
+
+ return f;
+}
+
+void
+yasm_floatnum_destroy(yasm_floatnum *flt)
+{
+ BitVector_Destroy(flt->mantissa);
+ yasm_xfree(flt);
+}
+
+int
+yasm_floatnum_calc(yasm_floatnum *acc, yasm_expr_op op,
+ /*@unused@*/ yasm_floatnum *operand)
+{
+ if (op != YASM_EXPR_NEG) {
+ yasm_error_set(YASM_ERROR_FLOATING_POINT,
+ N_("Unsupported floating-point arithmetic operation"));
+ return 1;
+ }
+ acc->sign ^= 1;
+ return 0;
+}
+
+int
+yasm_floatnum_get_int(const yasm_floatnum *flt, unsigned long *ret_val)
+{
+ unsigned char t[4];
+
+ if (yasm_floatnum_get_sized(flt, t, 4, 32, 0, 0, 0)) {
+ *ret_val = 0xDEADBEEFUL; /* Obviously incorrect return value */
+ return 1;
+ }
+
+ YASM_LOAD_32_L(*ret_val, &t[0]);
+ return 0;
+}
+
+/* Function used by conversion routines to actually perform the conversion.
+ *
+ * ptr -> the array to return the little-endian floating point value into.
+ * flt -> the floating point value to convert.
+ * byte_size -> the size in bytes of the output format.
+ * mant_bits -> the size in bits of the output mantissa.
+ * implicit1 -> does the output format have an implicit 1? 1=yes, 0=no.
+ * exp_bits -> the size in bits of the output exponent.
+ *
+ * Returns 0 on success, 1 if overflow, -1 if underflow.
+ */
+static int
+floatnum_get_common(const yasm_floatnum *flt, /*@out@*/ unsigned char *ptr,
+ N_int byte_size, N_int mant_bits, int implicit1,
+ N_int exp_bits)
+{
+ long exponent = (long)flt->exponent;
+ wordptr output;
+ charptr buf;
+ unsigned int len;
+ unsigned int overflow = 0, underflow = 0;
+ int retval = 0;
+ long exp_bias = (1<<(exp_bits-1))-1;
+ long exp_inf = (1<<exp_bits)-1;
+
+ output = BitVector_Create(byte_size*8, TRUE);
+
+ /* copy mantissa */
+ BitVector_Interval_Copy(output, flt->mantissa, 0,
+ (N_int)((MANT_BITS-implicit1)-mant_bits),
+ mant_bits);
+
+ /* round mantissa */
+ if (BitVector_bit_test(flt->mantissa, (MANT_BITS-implicit1)-(mant_bits+1)))
+ BitVector_increment(output);
+
+ if (BitVector_bit_test(output, mant_bits)) {
+ /* overflowed, so zero mantissa (and set explicit bit if necessary) */
+ BitVector_Empty(output);
+ BitVector_Bit_Copy(output, mant_bits-1, !implicit1);
+ /* and up the exponent (checking for overflow) */
+ if (exponent+1 >= EXP_INF)
+ overflow = 1;
+ else
+ exponent++;
+ }
+
+ /* adjust the exponent to the output bias, checking for overflow */
+ exponent -= EXP_BIAS-exp_bias;
+ if (exponent >= exp_inf)
+ overflow = 1;
+ else if (exponent <= 0)
+ underflow = 1;
+
+ /* underflow and overflow both set!? */
+ if (underflow && overflow)
+ yasm_internal_error(N_("Both underflow and overflow set"));
+
+ /* check for underflow or overflow and set up appropriate output */
+ if (underflow) {
+ BitVector_Empty(output);
+ exponent = 0;
+ if (!(flt->flags & FLAG_ISZERO))
+ retval = -1;
+ } else if (overflow) {
+ BitVector_Empty(output);
+ exponent = exp_inf;
+ retval = 1;
+ }
+
+ /* move exponent into place */
+ BitVector_Chunk_Store(output, exp_bits, mant_bits, (N_long)exponent);
+
+ /* merge in sign bit */
+ BitVector_Bit_Copy(output, byte_size*8-1, flt->sign);
+
+ /* get little-endian bytes */
+ buf = BitVector_Block_Read(output, &len);
+ if (len < byte_size)
+ yasm_internal_error(
+ N_("Byte length of BitVector does not match bit length"));
+
+ /* copy to output */
+ memcpy(ptr, buf, byte_size*sizeof(unsigned char));
+
+ /* free allocated resources */
+ yasm_xfree(buf);
+
+ BitVector_Destroy(output);
+
+ return retval;
+}
+
+/* IEEE-754r "half precision" format:
+ * 16 bits:
+ * 15 9 Bit 0
+ * | | |
+ * seee eemm mmmm mmmm
+ *
+ * e = bias 15 exponent
+ * s = sign bit
+ * m = mantissa bits, bit 10 is an implied one bit.
+ *
+ * IEEE-754 (Intel) "single precision" format:
+ * 32 bits:
+ * Bit 31 Bit 22 Bit 0
+ * | | |
+ * seeeeeee emmmmmmm mmmmmmmm mmmmmmmm
+ *
+ * e = bias 127 exponent
+ * s = sign bit
+ * m = mantissa bits, bit 23 is an implied one bit.
+ *
+ * IEEE-754 (Intel) "double precision" format:
+ * 64 bits:
+ * bit 63 bit 51 bit 0
+ * | | |
+ * seeeeeee eeeemmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm mmmmmmmm
+ *
+ * e = bias 1023 exponent.
+ * s = sign bit.
+ * m = mantissa bits. Bit 52 is an implied one bit.
+ *
+ * IEEE-754 (Intel) "extended precision" format:
+ * 80 bits:
+ * bit 79 bit 63 bit 0
+ * | | |
+ * seeeeeee eeeeeeee mmmmmmmm m...m m...m m...m m...m m...m
+ *
+ * e = bias 16383 exponent
+ * m = 64 bit mantissa with NO implied bit!
+ * s = sign (for mantissa)
+ */
+int
+yasm_floatnum_get_sized(const yasm_floatnum *flt, unsigned char *ptr,
+ size_t destsize, size_t valsize, size_t shift,
+ int bigendian, int warn)
+{
+ int retval;
+ if (destsize*8 != valsize || shift>0 || bigendian) {
+ /* TODO */
+ yasm_internal_error(N_("unsupported floatnum functionality"));
+ }
+ switch (destsize) {
+ case 2:
+ retval = floatnum_get_common(flt, ptr, 2, 10, 1, 5);
+ break;
+ case 4:
+ retval = floatnum_get_common(flt, ptr, 4, 23, 1, 8);
+ break;
+ case 8:
+ retval = floatnum_get_common(flt, ptr, 8, 52, 1, 11);
+ break;
+ case 10:
+ retval = floatnum_get_common(flt, ptr, 10, 64, 0, 15);
+ break;
+ default:
+ yasm_internal_error(N_("Invalid float conversion size"));
+ /*@notreached@*/
+ return 1;
+ }
+ if (warn) {
+ if (retval < 0)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("underflow in floating point expression"));
+ else if (retval > 0)
+ yasm_warn_set(YASM_WARN_GENERAL,
+ N_("overflow in floating point expression"));
+ }
+ return retval;
+}
+
+/* 1 if the size is valid, 0 if it isn't */
+int
+yasm_floatnum_check_size(/*@unused@*/ const yasm_floatnum *flt, size_t size)
+{
+ switch (size) {
+ case 16:
+ case 32:
+ case 64:
+ case 80:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+void
+yasm_floatnum_print(const yasm_floatnum *flt, FILE *f)
+{
+ unsigned char out[10];
+ unsigned char *str;
+ int i;
+
+ /* Internal format */
+ str = BitVector_to_Hex(flt->mantissa);
+ fprintf(f, "%c %s *2^%04x\n", flt->sign?'-':'+', (char *)str,
+ flt->exponent);
+ yasm_xfree(str);
+
+ /* 32-bit (single precision) format */
+ fprintf(f, "32-bit: %d: ",
+ yasm_floatnum_get_sized(flt, out, 4, 32, 0, 0, 0));
+ for (i=0; i<4; i++)
+ fprintf(f, "%02x ", out[i]);
+ fprintf(f, "\n");
+
+ /* 64-bit (double precision) format */
+ fprintf(f, "64-bit: %d: ",
+ yasm_floatnum_get_sized(flt, out, 8, 64, 0, 0, 0));
+ for (i=0; i<8; i++)
+ fprintf(f, "%02x ", out[i]);
+ fprintf(f, "\n");
+
+ /* 80-bit (extended precision) format */
+ fprintf(f, "80-bit: %d: ",
+ yasm_floatnum_get_sized(flt, out, 10, 80, 0, 0, 0));
+ for (i=0; i<10; i++)
+ fprintf(f, "%02x ", out[i]);
+ fprintf(f, "\n");
+}