*
* Copyright (C) 2001 Peter Johnson
*
+ * Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
+ *
* This file is part of YASM.
*
* YASM is free software; you can redistribute it and/or modify
#ifdef STDC_HEADERS
# include <stdlib.h>
+# include <string.h>
+#endif
+
+#include <libintl.h>
+#define _(String) gettext(String)
+#ifdef gettext_noop
+#define N_(String) gettext_noop(String)
+#else
+#define N_(String) (String)
#endif
+#include "bitvect.h"
+#include "file.h"
+
#include "errwarn.h"
#include "floatnum.h"
floatnum *flt = malloc(sizeof(floatnum));
if (!flt)
Fatal(FATAL_NOMEM);
- /* TODO */
+
+ flt->mantissa = BitVector_Create(64, TRUE);
+ if (!flt->mantissa)
+ Fatal(FATAL_NOMEM);
+
+ /* check for + or - character and skip */
+ if (*str == '-') {
+ flt->sign = 1;
+ str++;
+ } else if (*str == '+') {
+ flt->sign = 0;
+ str++;
+ } else
+ flt->sign = 0;
+
return flt;
}
-unsigned long
-floatnum_get_int(floatnum *flt)
+int
+floatnum_get_int(unsigned long *ret_val, const floatnum *flt)
{
- return 0; /* TODO */
+ unsigned char t[4];
+
+ if (floatnum_get_single(t, flt))
+ return 1;
+
+ LOAD_LONG(*ret_val, &t[0]);
+ return 0;
}
-unsigned char *
-floatnum_get_single(unsigned char *ptr, floatnum *flt)
+/* 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.
+ */
+int
+floatnum_get_single(unsigned char *ptr, const floatnum *flt)
{
- return ptr; /* TODO */
+ unsigned long exponent = flt->exponent;
+ unsigned int *output;
+ unsigned char *buf;
+ unsigned int len;
+
+ output = BitVector_Create(32, TRUE);
+ if (!output)
+ Fatal(FATAL_NOMEM);
+
+ /* copy mantissa */
+ BitVector_Interval_Copy(output, flt->mantissa, 0, 40, 23);
+
+ /* round mantissa */
+ BitVector_increment(output);
+
+ if (BitVector_bit_test(output, 23)) {
+ /* overflowed, so divide mantissa by 2 (shift right) */
+ BitVector_shift_right(output, 0);
+ /* and up the exponent (checking for overflow) */
+ if (exponent+1 >= 0x10000) {
+ BitVector_Destroy(output);
+ return 1; /* exponent too large */
+ }
+ exponent++;
+ }
+
+ /* adjust the exponent to bias 127 */
+ exponent -= 32767-127;
+ if (exponent >= 256) {
+ BitVector_Destroy(output);
+ return 1; /* exponent too large */
+ }
+
+ /* move exponent into place */
+ BitVector_Chunk_Store(output, 8, 23, exponent);
+
+ /* merge in sign bit */
+ BitVector_Bit_Copy(output, 31, flt->sign);
+
+ /* get little-endian bytes */
+ buf = BitVector_Block_Read(output, &len);
+ if (!buf)
+ Fatal(FATAL_NOMEM);
+ if (len != 4)
+ InternalError(__LINE__, __FILE__,
+ _("Length of 32-bit BitVector not 4"));
+
+ /* copy to output */
+ memcpy(ptr, buf, 4*sizeof(unsigned char));
+
+ /* free allocated resources */
+ free(buf);
+
+ BitVector_Destroy(output);
+
+ return 0;
}
-unsigned char *
-floatnum_get_double(unsigned char *ptr, floatnum *flt)
+/* 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.
+ */
+int
+floatnum_get_double(unsigned char *ptr, const floatnum *flt)
{
- return ptr; /* TODO */
+ unsigned long exponent = flt->exponent;
+ unsigned int *output;
+ unsigned char *buf;
+ unsigned int len;
+
+ output = BitVector_Create(64, TRUE);
+ if (!output)
+ Fatal(FATAL_NOMEM);
+
+ /* copy mantissa */
+ BitVector_Interval_Copy(output, flt->mantissa, 0, 11, 52);
+
+ /* round mantissa */
+ BitVector_increment(output);
+
+ if (BitVector_bit_test(output, 52)) {
+ /* overflowed, so divide mantissa by 2 (shift right) */
+ BitVector_shift_right(output, 0);
+ /* and up the exponent (checking for overflow) */
+ if (exponent+1 >= 0x10000) {
+ BitVector_Destroy(output);
+ return 1; /* exponent too large */
+ }
+ exponent++;
+ }
+
+ /* adjust the exponent to bias 1023 */
+ exponent -= 32767-1023;
+ if (exponent >= 2048) {
+ BitVector_Destroy(output);
+ return 1; /* exponent too large */
+ }
+
+ /* move exponent into place */
+ BitVector_Chunk_Store(output, 11, 52, exponent);
+
+ /* merge in sign bit */
+ BitVector_Bit_Copy(output, 63, flt->sign);
+
+ /* get little-endian bytes */
+ buf = BitVector_Block_Read(output, &len);
+ if (!buf)
+ Fatal(FATAL_NOMEM);
+ if (len != 8)
+ InternalError(__LINE__, __FILE__,
+ _("Length of 64-bit BitVector not 8"));
+
+ /* copy to output */
+ memcpy(ptr, buf, 8*sizeof(unsigned char));
+
+ /* free allocated resources */
+ free(buf);
+
+ BitVector_Destroy(output);
+
+ return 0;
}
-unsigned char *
-floatnum_get_extended(unsigned char *ptr, floatnum *flt)
+/* 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 16384 exponent
+ * m = 64 bit mantissa with NO implied bit!
+ * s = sign (for mantissa)
+ */
+int
+floatnum_get_extended(unsigned char *ptr, const floatnum *flt)
{
- return ptr; /* TODO */
+ unsigned short exponent = flt->exponent;
+ unsigned char *buf;
+ unsigned int len;
+
+ /* Adjust the exponent to bias 16384 */
+ exponent -= 0x4000;
+ if (exponent >= 0x8000)
+ return 1; /* exponent too large */
+
+ /* get little-endian bytes */
+ buf = BitVector_Block_Read(flt->mantissa, &len);
+ if (!buf)
+ Fatal(FATAL_NOMEM);
+ if (len != 8)
+ InternalError(__LINE__, __FILE__,
+ _("Length of 64-bit BitVector not 8"));
+
+ /* copy to output */
+ memcpy(ptr, buf, 8*sizeof(unsigned char));
+
+ /* Save exponent and sign in proper location */
+ SAVE_SHORT(&ptr[8], exponent);
+ if (flt->sign)
+ ptr[9] |= 0x80;
+
+ /* free allocated resources */
+ free(buf);
+
+ return 0;
}
void
-floatnum_print(floatnum *flt)
+floatnum_print(const floatnum *flt)
{
/* TODO */
}
*
* Copyright (C) 2001 Peter Johnson
*
+ * Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
+ *
* This file is part of YASM.
*
* YASM is free software; you can redistribute it and/or modify
#ifndef YASM_FLOATNUM_H
#define YASM_FLOATNUM_H
+/* 88-bit internal floating point format:
+ * xxxxxxxs eeeeeeee eeeeeeee m..m m..m m..m m..m m..m m..m m..m m..m
+ * Sign exponent mantissa (64 bits)
+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0|
+ * 63 55 47 39 31 23 15 7 0
+ *
+ * Only L.O. bit of Sign byte is significant. The rest is garbage.
+ * Exponent is bias 32767 exponent.
+ * Mantissa does NOT have an implied one bit (it's explicit).
+ */
typedef struct floatnum_s {
- unsigned char extval[10]; /* float stored in extended precision */
+ unsigned int *mantissa; /* Allocated to 64 bits */
+ unsigned short exponent;
+ unsigned char sign;
} floatnum;
floatnum *floatnum_new(char *str);
-unsigned long floatnum_get_int(floatnum *flt);
-unsigned char *floatnum_get_single(unsigned char *ptr, floatnum *flt);
-unsigned char *floatnum_get_double(unsigned char *ptr, floatnum *flt);
-unsigned char *floatnum_get_extended(unsigned char *ptr, floatnum *flt);
-void floatnum_print(floatnum *flt);
+/* The get functions return nonzero if flt can't fit into that size format. */
+
+/* Essentially a convert to single-precision and return as 32-bit value.
+ * The 32-bit value is a "standard" C value (eg, of unknown endian).
+ */
+int floatnum_get_int(unsigned long *ret_val, const floatnum *flt);
+
+/* ptr will point to the Intel-format little-endian byte string after a
+ * successful call (eg, [0] should be the first byte output to the file).
+ */
+int floatnum_get_single(unsigned char *ptr, const floatnum *flt);
+int floatnum_get_double(unsigned char *ptr, const floatnum *flt);
+int floatnum_get_extended(unsigned char *ptr, const floatnum *flt);
+
+void floatnum_print(const floatnum *flt);
#endif
*ret_val = sym->value.int_val;
break;
case SYM_CONSTANT_FLOAT:
- *ret_val = floatnum_get_int(sym->value.flt);
+ /* FIXME: Line number on this error will be incorrect. */
+ if (floatnum_get_int(ret_val, sym->value.flt))
+ Error(_("Floating point value cannot fit in 32-bit single precision"));
break;
case SYM_LABEL:
if (!bytecode_get_offset(sym->value.label.sect,
if CHECK
TESTS = \
- bytecode_test
+ bytecode_test \
+ floatnum_test
noinst_PROGRAMS = \
- bytecode_test
+ bytecode_test \
+ floatnum_test
else
TESTS =
noinst_PROGRAMS =
bytecode_test_SOURCES = \
bytecode_test.c
+floatnum_test_SOURCES = \
+ floatnum_test.c
+
INCLUDES= -I$(top_srcdir) -I$(top_srcdir)/src -I$(top_srcdir)/check
LDADD = \
$(top_builddir)/check/libcheck.a \
--- /dev/null
+/* $IdPath$
+ *
+ */
+#include <stdlib.h>
+#include "check.h"
+
+#include "bitvect.h"
+
+#include "floatnum.h"
+
+floatnum *flt;
+void get_family_setup(void)
+{
+
+ flt = malloc(sizeof(floatnum));
+ flt->mantissa = BitVector_Create(64, TRUE);
+}
+
+void get_family_teardown(void)
+{
+ BitVector_Destroy(flt->mantissa);
+ free(flt);
+}
+
+void pi_setup(void)
+{
+ /* test value: 3.141592653589793 */
+ /* 80-bit little endian hex: E9 BD 68 21 A2 DA 0F C9 00 40 */
+ unsigned char val[] = {0xE9, 0xBD, 0x68, 0x21, 0xA2, 0xDA, 0x0F, 0xC9};
+ unsigned char sign = 0;
+ unsigned short exp = 32767 + 1;
+
+ BitVector_Block_Store(flt->mantissa, val, 8);
+ flt->sign = sign;
+ flt->exponent = exp;
+}
+
+START_TEST(test_get_single_pi)
+{
+ unsigned char outval[] = {0x00, 0x00, 0x00, 0x00};
+ unsigned char correct[] = {0xDB, 0x0F, 0x49, 0x40};
+ int i;
+
+ pi_setup();
+
+ fail_unless(floatnum_get_single(outval, flt) == 0,
+ "Should not fail on this value");
+
+ /* Compare result with what we should get. */
+ for (i=0;i<4;i++)
+ fail_unless(outval[i] == correct[i], "Invalid result generated");
+}
+END_TEST
+
+START_TEST(test_get_double_pi)
+{
+ unsigned char outval[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ unsigned char correct[] = {0x18, 0x2D, 0x44, 0x54, 0xFB, 0x21, 0x09, 0x40};
+ int i;
+
+ pi_setup();
+
+ fail_unless(floatnum_get_double(outval, flt) == 0,
+ "Should not fail on this value");
+
+ /* Compare result with what we should get. */
+ for (i=0;i<8;i++)
+ fail_unless(outval[i] == correct[i], "Invalid result generated");
+}
+END_TEST
+
+START_TEST(test_get_extended_pi)
+{
+ unsigned char outval[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ unsigned char correct[] = {0xE9, 0xBD, 0x68, 0x21, 0xA2, 0xDA, 0x0F, 0xC9, 0x00, 0x40};
+ int i;
+
+ pi_setup();
+
+ fail_unless(floatnum_get_extended(outval, flt) == 0,
+ "Should not fail on this value");
+
+ /* Compare result with what we should get. */
+ for (i=0;i<10;i++)
+ fail_unless(outval[i] == correct[i], "Invalid result generated");
+}
+END_TEST
+
+Suite *bytecode_suite(void)
+{
+ Suite *s = suite_create("floatnum");
+ TCase *tc_get_single = tcase_create("get_single");
+ TCase *tc_get_double = tcase_create("get_double");
+ TCase *tc_get_extended = tcase_create("get_extended");
+
+ suite_add_tcase(s, tc_get_single);
+ tcase_add_test(tc_get_single, test_get_single_pi);
+ tcase_set_fixture(tc_get_single, get_family_setup, get_family_teardown);
+
+ suite_add_tcase(s, tc_get_double);
+ tcase_add_test(tc_get_double, test_get_double_pi);
+ tcase_set_fixture(tc_get_double, get_family_setup, get_family_teardown);
+
+ suite_add_tcase(s, tc_get_extended);
+ tcase_add_test(tc_get_extended, test_get_extended_pi);
+ tcase_set_fixture(tc_get_extended, get_family_setup, get_family_teardown);
+
+ return s;
+}
+
+int main(void)
+{
+ int nf;
+ Suite *s = bytecode_suite();
+ SRunner *sr = srunner_create(s);
+ BitVector_Boot();
+ srunner_run_all(sr, CRNORMAL);
+ nf = srunner_ntests_failed(sr);
+ srunner_free(sr);
+ suite_free(s);
+ return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
*
* Copyright (C) 2001 Peter Johnson
*
+ * Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
+ *
* This file is part of YASM.
*
* YASM is free software; you can redistribute it and/or modify
#ifdef STDC_HEADERS
# include <stdlib.h>
+# include <string.h>
+#endif
+
+#include <libintl.h>
+#define _(String) gettext(String)
+#ifdef gettext_noop
+#define N_(String) gettext_noop(String)
+#else
+#define N_(String) (String)
#endif
+#include "bitvect.h"
+#include "file.h"
+
#include "errwarn.h"
#include "floatnum.h"
floatnum *flt = malloc(sizeof(floatnum));
if (!flt)
Fatal(FATAL_NOMEM);
- /* TODO */
+
+ flt->mantissa = BitVector_Create(64, TRUE);
+ if (!flt->mantissa)
+ Fatal(FATAL_NOMEM);
+
+ /* check for + or - character and skip */
+ if (*str == '-') {
+ flt->sign = 1;
+ str++;
+ } else if (*str == '+') {
+ flt->sign = 0;
+ str++;
+ } else
+ flt->sign = 0;
+
return flt;
}
-unsigned long
-floatnum_get_int(floatnum *flt)
+int
+floatnum_get_int(unsigned long *ret_val, const floatnum *flt)
{
- return 0; /* TODO */
+ unsigned char t[4];
+
+ if (floatnum_get_single(t, flt))
+ return 1;
+
+ LOAD_LONG(*ret_val, &t[0]);
+ return 0;
}
-unsigned char *
-floatnum_get_single(unsigned char *ptr, floatnum *flt)
+/* 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.
+ */
+int
+floatnum_get_single(unsigned char *ptr, const floatnum *flt)
{
- return ptr; /* TODO */
+ unsigned long exponent = flt->exponent;
+ unsigned int *output;
+ unsigned char *buf;
+ unsigned int len;
+
+ output = BitVector_Create(32, TRUE);
+ if (!output)
+ Fatal(FATAL_NOMEM);
+
+ /* copy mantissa */
+ BitVector_Interval_Copy(output, flt->mantissa, 0, 40, 23);
+
+ /* round mantissa */
+ BitVector_increment(output);
+
+ if (BitVector_bit_test(output, 23)) {
+ /* overflowed, so divide mantissa by 2 (shift right) */
+ BitVector_shift_right(output, 0);
+ /* and up the exponent (checking for overflow) */
+ if (exponent+1 >= 0x10000) {
+ BitVector_Destroy(output);
+ return 1; /* exponent too large */
+ }
+ exponent++;
+ }
+
+ /* adjust the exponent to bias 127 */
+ exponent -= 32767-127;
+ if (exponent >= 256) {
+ BitVector_Destroy(output);
+ return 1; /* exponent too large */
+ }
+
+ /* move exponent into place */
+ BitVector_Chunk_Store(output, 8, 23, exponent);
+
+ /* merge in sign bit */
+ BitVector_Bit_Copy(output, 31, flt->sign);
+
+ /* get little-endian bytes */
+ buf = BitVector_Block_Read(output, &len);
+ if (!buf)
+ Fatal(FATAL_NOMEM);
+ if (len != 4)
+ InternalError(__LINE__, __FILE__,
+ _("Length of 32-bit BitVector not 4"));
+
+ /* copy to output */
+ memcpy(ptr, buf, 4*sizeof(unsigned char));
+
+ /* free allocated resources */
+ free(buf);
+
+ BitVector_Destroy(output);
+
+ return 0;
}
-unsigned char *
-floatnum_get_double(unsigned char *ptr, floatnum *flt)
+/* 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.
+ */
+int
+floatnum_get_double(unsigned char *ptr, const floatnum *flt)
{
- return ptr; /* TODO */
+ unsigned long exponent = flt->exponent;
+ unsigned int *output;
+ unsigned char *buf;
+ unsigned int len;
+
+ output = BitVector_Create(64, TRUE);
+ if (!output)
+ Fatal(FATAL_NOMEM);
+
+ /* copy mantissa */
+ BitVector_Interval_Copy(output, flt->mantissa, 0, 11, 52);
+
+ /* round mantissa */
+ BitVector_increment(output);
+
+ if (BitVector_bit_test(output, 52)) {
+ /* overflowed, so divide mantissa by 2 (shift right) */
+ BitVector_shift_right(output, 0);
+ /* and up the exponent (checking for overflow) */
+ if (exponent+1 >= 0x10000) {
+ BitVector_Destroy(output);
+ return 1; /* exponent too large */
+ }
+ exponent++;
+ }
+
+ /* adjust the exponent to bias 1023 */
+ exponent -= 32767-1023;
+ if (exponent >= 2048) {
+ BitVector_Destroy(output);
+ return 1; /* exponent too large */
+ }
+
+ /* move exponent into place */
+ BitVector_Chunk_Store(output, 11, 52, exponent);
+
+ /* merge in sign bit */
+ BitVector_Bit_Copy(output, 63, flt->sign);
+
+ /* get little-endian bytes */
+ buf = BitVector_Block_Read(output, &len);
+ if (!buf)
+ Fatal(FATAL_NOMEM);
+ if (len != 8)
+ InternalError(__LINE__, __FILE__,
+ _("Length of 64-bit BitVector not 8"));
+
+ /* copy to output */
+ memcpy(ptr, buf, 8*sizeof(unsigned char));
+
+ /* free allocated resources */
+ free(buf);
+
+ BitVector_Destroy(output);
+
+ return 0;
}
-unsigned char *
-floatnum_get_extended(unsigned char *ptr, floatnum *flt)
+/* 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 16384 exponent
+ * m = 64 bit mantissa with NO implied bit!
+ * s = sign (for mantissa)
+ */
+int
+floatnum_get_extended(unsigned char *ptr, const floatnum *flt)
{
- return ptr; /* TODO */
+ unsigned short exponent = flt->exponent;
+ unsigned char *buf;
+ unsigned int len;
+
+ /* Adjust the exponent to bias 16384 */
+ exponent -= 0x4000;
+ if (exponent >= 0x8000)
+ return 1; /* exponent too large */
+
+ /* get little-endian bytes */
+ buf = BitVector_Block_Read(flt->mantissa, &len);
+ if (!buf)
+ Fatal(FATAL_NOMEM);
+ if (len != 8)
+ InternalError(__LINE__, __FILE__,
+ _("Length of 64-bit BitVector not 8"));
+
+ /* copy to output */
+ memcpy(ptr, buf, 8*sizeof(unsigned char));
+
+ /* Save exponent and sign in proper location */
+ SAVE_SHORT(&ptr[8], exponent);
+ if (flt->sign)
+ ptr[9] |= 0x80;
+
+ /* free allocated resources */
+ free(buf);
+
+ return 0;
}
void
-floatnum_print(floatnum *flt)
+floatnum_print(const floatnum *flt)
{
/* TODO */
}
*
* Copyright (C) 2001 Peter Johnson
*
+ * Based on public-domain x86 assembly code by Randall Hyde (8/28/91).
+ *
* This file is part of YASM.
*
* YASM is free software; you can redistribute it and/or modify
#ifndef YASM_FLOATNUM_H
#define YASM_FLOATNUM_H
+/* 88-bit internal floating point format:
+ * xxxxxxxs eeeeeeee eeeeeeee m..m m..m m..m m..m m..m m..m m..m m..m
+ * Sign exponent mantissa (64 bits)
+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0|
+ * 63 55 47 39 31 23 15 7 0
+ *
+ * Only L.O. bit of Sign byte is significant. The rest is garbage.
+ * Exponent is bias 32767 exponent.
+ * Mantissa does NOT have an implied one bit (it's explicit).
+ */
typedef struct floatnum_s {
- unsigned char extval[10]; /* float stored in extended precision */
+ unsigned int *mantissa; /* Allocated to 64 bits */
+ unsigned short exponent;
+ unsigned char sign;
} floatnum;
floatnum *floatnum_new(char *str);
-unsigned long floatnum_get_int(floatnum *flt);
-unsigned char *floatnum_get_single(unsigned char *ptr, floatnum *flt);
-unsigned char *floatnum_get_double(unsigned char *ptr, floatnum *flt);
-unsigned char *floatnum_get_extended(unsigned char *ptr, floatnum *flt);
-void floatnum_print(floatnum *flt);
+/* The get functions return nonzero if flt can't fit into that size format. */
+
+/* Essentially a convert to single-precision and return as 32-bit value.
+ * The 32-bit value is a "standard" C value (eg, of unknown endian).
+ */
+int floatnum_get_int(unsigned long *ret_val, const floatnum *flt);
+
+/* ptr will point to the Intel-format little-endian byte string after a
+ * successful call (eg, [0] should be the first byte output to the file).
+ */
+int floatnum_get_single(unsigned char *ptr, const floatnum *flt);
+int floatnum_get_double(unsigned char *ptr, const floatnum *flt);
+int floatnum_get_extended(unsigned char *ptr, const floatnum *flt);
+
+void floatnum_print(const floatnum *flt);
#endif
*ret_val = sym->value.int_val;
break;
case SYM_CONSTANT_FLOAT:
- *ret_val = floatnum_get_int(sym->value.flt);
+ /* FIXME: Line number on this error will be incorrect. */
+ if (floatnum_get_int(ret_val, sym->value.flt))
+ Error(_("Floating point value cannot fit in 32-bit single precision"));
break;
case SYM_LABEL:
if (!bytecode_get_offset(sym->value.label.sect,
if CHECK
TESTS = \
- bytecode_test
+ bytecode_test \
+ floatnum_test
noinst_PROGRAMS = \
- bytecode_test
+ bytecode_test \
+ floatnum_test
else
TESTS =
noinst_PROGRAMS =
bytecode_test_SOURCES = \
bytecode_test.c
+floatnum_test_SOURCES = \
+ floatnum_test.c
+
INCLUDES= -I$(top_srcdir) -I$(top_srcdir)/src -I$(top_srcdir)/check
LDADD = \
$(top_builddir)/check/libcheck.a \
--- /dev/null
+/* $IdPath$
+ *
+ */
+#include <stdlib.h>
+#include "check.h"
+
+#include "bitvect.h"
+
+#include "floatnum.h"
+
+floatnum *flt;
+void get_family_setup(void)
+{
+
+ flt = malloc(sizeof(floatnum));
+ flt->mantissa = BitVector_Create(64, TRUE);
+}
+
+void get_family_teardown(void)
+{
+ BitVector_Destroy(flt->mantissa);
+ free(flt);
+}
+
+void pi_setup(void)
+{
+ /* test value: 3.141592653589793 */
+ /* 80-bit little endian hex: E9 BD 68 21 A2 DA 0F C9 00 40 */
+ unsigned char val[] = {0xE9, 0xBD, 0x68, 0x21, 0xA2, 0xDA, 0x0F, 0xC9};
+ unsigned char sign = 0;
+ unsigned short exp = 32767 + 1;
+
+ BitVector_Block_Store(flt->mantissa, val, 8);
+ flt->sign = sign;
+ flt->exponent = exp;
+}
+
+START_TEST(test_get_single_pi)
+{
+ unsigned char outval[] = {0x00, 0x00, 0x00, 0x00};
+ unsigned char correct[] = {0xDB, 0x0F, 0x49, 0x40};
+ int i;
+
+ pi_setup();
+
+ fail_unless(floatnum_get_single(outval, flt) == 0,
+ "Should not fail on this value");
+
+ /* Compare result with what we should get. */
+ for (i=0;i<4;i++)
+ fail_unless(outval[i] == correct[i], "Invalid result generated");
+}
+END_TEST
+
+START_TEST(test_get_double_pi)
+{
+ unsigned char outval[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ unsigned char correct[] = {0x18, 0x2D, 0x44, 0x54, 0xFB, 0x21, 0x09, 0x40};
+ int i;
+
+ pi_setup();
+
+ fail_unless(floatnum_get_double(outval, flt) == 0,
+ "Should not fail on this value");
+
+ /* Compare result with what we should get. */
+ for (i=0;i<8;i++)
+ fail_unless(outval[i] == correct[i], "Invalid result generated");
+}
+END_TEST
+
+START_TEST(test_get_extended_pi)
+{
+ unsigned char outval[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ unsigned char correct[] = {0xE9, 0xBD, 0x68, 0x21, 0xA2, 0xDA, 0x0F, 0xC9, 0x00, 0x40};
+ int i;
+
+ pi_setup();
+
+ fail_unless(floatnum_get_extended(outval, flt) == 0,
+ "Should not fail on this value");
+
+ /* Compare result with what we should get. */
+ for (i=0;i<10;i++)
+ fail_unless(outval[i] == correct[i], "Invalid result generated");
+}
+END_TEST
+
+Suite *bytecode_suite(void)
+{
+ Suite *s = suite_create("floatnum");
+ TCase *tc_get_single = tcase_create("get_single");
+ TCase *tc_get_double = tcase_create("get_double");
+ TCase *tc_get_extended = tcase_create("get_extended");
+
+ suite_add_tcase(s, tc_get_single);
+ tcase_add_test(tc_get_single, test_get_single_pi);
+ tcase_set_fixture(tc_get_single, get_family_setup, get_family_teardown);
+
+ suite_add_tcase(s, tc_get_double);
+ tcase_add_test(tc_get_double, test_get_double_pi);
+ tcase_set_fixture(tc_get_double, get_family_setup, get_family_teardown);
+
+ suite_add_tcase(s, tc_get_extended);
+ tcase_add_test(tc_get_extended, test_get_extended_pi);
+ tcase_set_fixture(tc_get_extended, get_family_setup, get_family_teardown);
+
+ return s;
+}
+
+int main(void)
+{
+ int nf;
+ Suite *s = bytecode_suite();
+ SRunner *sr = srunner_create(s);
+ BitVector_Boot();
+ srunner_run_all(sr, CRNORMAL);
+ nf = srunner_ntests_failed(sr);
+ srunner_free(sr);
+ suite_free(s);
+ return (nf == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}