This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH libiberty/floatformat.c VAX formats
- From: RDBrown at mira dot net
- To: gcc-patches at gcc dot gnu dot org
- Cc: ac131313 at cynus dot com, dj at redhat dot com
- Date: Mon, 28 Jan 2002 23:52:52 +1100 (EST)
- Subject: PATCH libiberty/floatformat.c VAX formats
- Reply-to: RDBrown at mira dot net,RBrown64 at csc dot com dot au
This patch is to provide the beginnings of VAX floating point support in
floatformat.c - necessary if someone wants to revive VAX support in gdb.
See <http://sources.redhat.com/ml/gdb-patches/2002-01/msg00544.html>.
The other examples may help converting data from tape someday.
By inspection, the routines in floatformat.c can't cope with
floatformat_littlebyte_bigword or floatformat_arm_ext_littlebyte_bigword
or the VAX formats since the floatformat_littlebyte_bigword enum value
isn't referenced in in floatformat.c(get_field, put_field).
Perhaps enum floatformat_byteorders values should be the size in bytes
of the largest datum loaded as a little-endian value (or log2 of it).
Assuming log2
floatformat_big = 0, /* 1 byte, Big Endian */
floatformat_littlebyte_bighalfword = 1, /* 2 bytes as Little Endian */
floatformat_littlebyte_bigword = 2, /* 4 bytes as Little Endian */
floatformat_little = 4, /* 16 bytes as Little Endian */
That should be able to directly drive the byte loads in
floatformat.c:get_field and put_field.
I agree with Andrew about the VAX 11 Architecture reference. The other two
references described the formats in halfwords (16-bit) which made it much
clearer.
NB My corporate assignment is in abeyance at the moment, most of this is
straight out of the references mentioned. The endian test is from autoconf.
2002-01-28 Rodney Brown <rbrown64@csc.com.au>
* include/floatformat.h(enum floatformat_byteorders):
Add floatformat_littlebyte_bighalfword.
* libiberty/floatformat.c: Add VAX, HP3000 float formats.
(ieee_test, main): Cope with little_endian IEEE (ix86).
--- include/floatformat.h.orig Tue Aug 21 10:09:07 2001
+++ include/floatformat.h Wed Jan 23 09:21:03 2002
@@ -45,7 +45,13 @@ enum floatformat_byteorders {
/* Little endian byte order but big endian word order.
EX: 1.2345678e10 => e0 fe 06 42 00 00 80 c5 */
- floatformat_littlebyte_bigword
+ floatformat_littlebyte_bigword,
+
+
+ /* Little endian byte order but big endian halfword (16-bit) order.
+ EX: 1.2345678e10 => 06 42 e0 fe 80 c5 00 00 */
+
+ floatformat_littlebyte_bighalfword
};
--- libiberty/floatformat.c.orig Tue Aug 21 10:09:09 2001
+++ libiberty/floatformat.c Mon Jan 28 14:44:53 2002
@@ -148,6 +148,153 @@ const struct floatformat floatformat_ia6
floatformat_intbit_no,
"floatformat_ia64_quad_little"
};
+
+#ifdef DEC_ARCHAEOLOGY
+/* For VAX Floating point formats,
+ zero is represented by sign bit of zero and an exponent value of zero.
+ A sign bit of 1 and exponent of zero causes a reserved operand fault.
+ This implies exp_nan should be zero (?).
+ The VAX F & D formats are compatible with the PDP-11 formats, which
+ explains the `littlebyte_bighalfword' byte ordering.
+
+ VAX Architecture Reference Manual, 1987, ISBN 0-932376-86-X
+ pgs 7 .. 9
+ VAX-11 Assembly Language Programming Sara Baase, 1983, ISBN 0-13-940957-2
+ pgs 305 .. 309
+ Alpha Architecture Handbook, 1992, EC-H1689-10 REL# 4/92
+ pgs 2-3 .. p 2-5 */
+
+const struct floatformat floatformat_vax_F =
+{
+ floatformat_littlebyte_bighalfword, 32, 0, 1, 8, 128, 0, 9, 23,
+ floatformat_intbit_no,
+ "floatformat_vax_F"
+};
+const struct floatformat floatformat_vax_D =
+{
+ floatformat_littlebyte_bighalfword, 64, 0, 1, 8, 128, 0, 9, 55,
+ floatformat_intbit_no,
+ "floatformat_vax_D"
+};
+const struct floatformat floatformat_vax_G =
+{
+ floatformat_littlebyte_bighalfword, 64, 0, 1, 11, 1024, 0, 12, 52,
+ floatformat_intbit_no,
+ "floatformat_vax_G"
+};
+const struct floatformat floatformat_vax_H =
+{
+ floatformat_littlebyte_bighalfword, 128, 0, 1, 15, 16384, 0, 16, 112,
+ floatformat_intbit_no,
+ "floatformat_vax_H"
+};
+#endif /* DEC_ARCHAEOLOGY */
+#ifdef HP_ARCHAEOLOGY
+/* HP3000 Floating point formats.
+ HP3000 Machine Instruction Set Reference Manual, 1984, 30000-90022
+ pgs 2-98, 3-17, 3-18 */
+
+const struct floatformat floatformat_hp3000_single =
+{
+ floatformat_big, 32, 0, 1, 9, 256, 0, 10, 22,
+ floatformat_intbit_no,
+ "floatformat_hp3000_single"
+};
+const struct floatformat floatformat_hp3000_double =
+{
+ floatformat_big, 64, 0, 1, 9, 256, 0, 10, 54,
+ floatformat_intbit_no,
+ "floatformat_hp3000_double"
+};
+#endif /* HP_ARCHAEOLOGY */
+
+/* DG ECLIPSE Floating point formats
+ AOS/VS Macroassembler Reference Manual, 1987, 093-000242-02
+ pg 2-13
+
+This 32-bit format can't be represented with the floatformat struct
+since the exponent is a power of 16 not 2. Otherwise it would be :-
+
+const struct floatformat floatformat_dg_eclipse_single =
+{
+ floatformat_big, 32, 0, 1, 7, 64, 0, 8, 24,
+ floatformat_intbit_yes,
+ "floatformat_dg_eclipse_single"
+};
+
+Non-zero numbers are normalized to have a one in the first 4 bits
+of the mantissa.
+
+ Burroughs B 6700 / B 7700 ALGOL Language Reference Manual, 1974, 500649
+ pg B-4, B-5, B-7, B-8
+
+This 48-bit format can't be represented with the floatformat struct
+since the exponent is a power of 8 not 2, Bit 2 is the sign bit for the
+exponent. Integers on the platform are single floating point numbers with
+an exponent of 0.
+Otherwise it would be (maybe) :-
+
+const struct floatformat floatformat_dg_b6700_single =
+{
+ floatformat_big?, 48, 1, 3, 6, 0, 0, 9, 39,
+ floatformat_intbit_yes,
+ "floatformat_dg_b6700_single"
+};
+
+ 0.5 => 0x26C000000000 10 => 0x00000000000A
+ 99999999999 => 0x00174876E7FF -10 => 0x40000000000A
+549755813887 => 0x007FFFFFFFFF
+
+The double precision format uses two 48-bit words to give a 15-bit exponent
++ exponent sign bit and a 78-bit mantissa. The first word is as the
+single precision format, but contains the least significant 6-bits of the
+exponent and the most-significant 39-bits of the mantissa. The second 48-bit
+word has the most significant 9 bits of the exponent (0, 9) and the least
+significant 39-bits of the mantissa (9, 39).
+A number that can be exactly represented in single precision has a second
+48-bit word identically zero in double precision.
+
+0x1D0 => 0x261000000000 0x000000000000 */
+
+/* Digital Portable Mathematics Library, 1996, AA-PV6VC-TE
+ Appendix A, Critical Floating-Point Values pg A1-A2
+
+ Values for max_float
+Type Hex Decimal
+F FFFF7FFF 1.701411e38 32-bit VAX single-precision
+G FFFFFFFFFFFF7FFF 8.988465674311579e307 64-bit VAX double-precision
+S 7F7FFFFF 3.402823e28 32-bit IEEE single-precision
+T 7FEFFFFFFFFFFFFF 1.797693134862316e308 64-bit IEEE double-precision
+X 7FFEFFFFFFFFFFFFFFFFFFFFFFFFFFFF 128-bit IEEE extended-precision
+ 1.189731495357231765085759326628007016196477e4932
+
+ Values for min_float
+Type Hex Decimal
+F 00000080 2.9387359e-39
+G 0000000000000010 5.562684646268003e-309
+S 00000001 1.4012985e-45
+T 0000000000000001 4.940656458412465e-324
+X 00000000000000000000000000000001
+ 6.4751751194380251109244389582276465524996e-4966
+
+ Values for ln(max_float)
+Type Hex Decimal
+F 0F3443B0 88.029692
+G 7B616E3A28B740A6 709.0895657128241
+S 42B17218 88.7228391
+T 40862E42FEFA39EF 709.7827128933840
+X 400C62E42FEFA39EF35793C7673007E6
+ 11356.5234062941439494919310779707648912527
+
+ Values for ln(min_float)
+Type Hex Decimal
+F 7218C3B1 -88.72284
+G 39EFFEFA2E42C0A6 -709.7827128933840
+S C2CE8ED0 -103.2789
+T C0874385446D71C3 -744.4400719213813
+X C00C6546282207802C89D24D65E96274
+ -11432.7695961557379335278266113311643138373
+*/
static unsigned long get_field PARAMS ((unsigned char *,
enum floatformat_byteorders,
@@ -413,6 +560,8 @@ floatformat_from_double (fmt, from, to)
#ifdef IEEE_DEBUG
+static const struct floatformat *floatformat_ieee_double = NULL;
+
/* This is to be run on a host which uses IEEE floating point. */
void
@@ -422,10 +571,10 @@ ieee_test (n)
double result;
char exten[16];
- floatformat_to_double (&floatformat_ieee_double_big, &n, &result);
+ floatformat_to_double (floatformat_ieee_double, &n, &result);
if (n != result)
printf ("Differ(to): %.20g -> %.20g\n", n, result);
- floatformat_from_double (&floatformat_ieee_double_big, &n, &result);
+ floatformat_from_double (floatformat_ieee_double, &n, &result);
if (n != result)
printf ("Differ(from): %.20g -> %.20g\n", n, result);
@@ -447,6 +596,18 @@ ieee_test (n)
int
main ()
{
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long l;
+ char c[sizeof (long)];
+ } u;
+ u.l = 1;
+ floatformat_ieee_double =
+ ((u.c[sizeof (long) - 1] == 1)
+ ? &floatformat_ieee_double_big
+ : &floatformat_ieee_double_little);
+
ieee_test (0.5);
ieee_test (256.0);
ieee_test (0.12345);