+#include "gdb_assert.h"
+#include "gdb_string.h"
+
+#include "i386-tdep.h"
+#include "i387-tdep.h"
+
+/* Print the floating point number specified by RAW. */
+
+static void
+print_i387_value (const gdb_byte *raw, struct ui_file *file)
+{
+ DOUBLEST value;
+
+ /* Using extract_typed_floating here might affect the representation
+ of certain numbers such as NaNs, even if GDB is running natively.
+ This is fine since our caller already detects such special
+ numbers and we print the hexadecimal representation anyway. */
+ value = extract_typed_floating (raw, builtin_type_i387_ext);
+
+ /* We try to print 19 digits. The last digit may or may not contain
+ garbage, but we'd better print one too many. We need enough room
+ to print the value, 1 position for the sign, 1 for the decimal
+ point, 19 for the digits and 6 for the exponent adds up to 27. */
+#ifdef PRINTF_HAS_LONG_DOUBLE
+ fprintf_filtered (file, " %-+27.19Lg", (long double) value);
+#else
+ fprintf_filtered (file, " %-+27.19g", (double) value);
+#endif
+}
+
+/* Print the classification for the register contents RAW. */
+
+static void
+print_i387_ext (const gdb_byte *raw, struct ui_file *file)
+{
+ int sign;
+ int integer;
+ unsigned int exponent;
+ unsigned long fraction[2];
+
+ sign = raw[9] & 0x80;
+ integer = raw[7] & 0x80;
+ exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
+ fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
+ fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
+ | (raw[5] << 8) | raw[4]);
+
+ if (exponent == 0x7fff && integer)
+ {
+ if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
+ /* Infinity. */
+ fprintf_filtered (file, " %cInf", (sign ? '-' : '+'));
+ else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
+ /* Real Indefinite (QNaN). */
+ fputs_unfiltered (" Real Indefinite (QNaN)", file);
+ else if (fraction[1] & 0x40000000)
+ /* QNaN. */
+ fputs_filtered (" QNaN", file);
+ else
+ /* SNaN. */
+ fputs_filtered (" SNaN", file);
+ }
+ else if (exponent < 0x7fff && exponent > 0x0000 && integer)
+ /* Normal. */
+ print_i387_value (raw, file);
+ else if (exponent == 0x0000)
+ {
+ /* Denormal or zero. */
+ print_i387_value (raw, file);
+
+ if (integer)
+ /* Pseudo-denormal. */
+ fputs_filtered (" Pseudo-denormal", file);
+ else if (fraction[0] || fraction[1])
+ /* Denormal. */
+ fputs_filtered (" Denormal", file);
+ }
+ else
+ /* Unsupported. */
+ fputs_filtered (" Unsupported", file);
+}
+
+/* Print the status word STATUS. */
+
+static void
+print_i387_status_word (unsigned int status, struct ui_file *file)
+{
+ fprintf_filtered (file, "Status Word: %s",
+ hex_string_custom (status, 4));
+ fputs_filtered (" ", file);
+ fprintf_filtered (file, " %s", (status & 0x0001) ? "IE" : " ");
+ fprintf_filtered (file, " %s", (status & 0x0002) ? "DE" : " ");
+ fprintf_filtered (file, " %s", (status & 0x0004) ? "ZE" : " ");
+ fprintf_filtered (file, " %s", (status & 0x0008) ? "OE" : " ");
+ fprintf_filtered (file, " %s", (status & 0x0010) ? "UE" : " ");
+ fprintf_filtered (file, " %s", (status & 0x0020) ? "PE" : " ");
+ fputs_filtered (" ", file);
+ fprintf_filtered (file, " %s", (status & 0x0080) ? "ES" : " ");
+ fputs_filtered (" ", file);
+ fprintf_filtered (file, " %s", (status & 0x0040) ? "SF" : " ");
+ fputs_filtered (" ", file);
+ fprintf_filtered (file, " %s", (status & 0x0100) ? "C0" : " ");
+ fprintf_filtered (file, " %s", (status & 0x0200) ? "C1" : " ");
+ fprintf_filtered (file, " %s", (status & 0x0400) ? "C2" : " ");
+ fprintf_filtered (file, " %s", (status & 0x4000) ? "C3" : " ");
+
+ fputs_filtered ("\n", file);
+
+ fprintf_filtered (file,
+ " TOP: %d\n", ((status >> 11) & 7));
+}
+
+/* Print the control word CONTROL. */
+
+static void
+print_i387_control_word (unsigned int control, struct ui_file *file)
+{
+ fprintf_filtered (file, "Control Word: %s",
+ hex_string_custom (control, 4));
+ fputs_filtered (" ", file);
+ fprintf_filtered (file, " %s", (control & 0x0001) ? "IM" : " ");
+ fprintf_filtered (file, " %s", (control & 0x0002) ? "DM" : " ");
+ fprintf_filtered (file, " %s", (control & 0x0004) ? "ZM" : " ");
+ fprintf_filtered (file, " %s", (control & 0x0008) ? "OM" : " ");
+ fprintf_filtered (file, " %s", (control & 0x0010) ? "UM" : " ");
+ fprintf_filtered (file, " %s", (control & 0x0020) ? "PM" : " ");
+
+ fputs_filtered ("\n", file);
+
+ fputs_filtered (" PC: ", file);
+ switch ((control >> 8) & 3)
+ {
+ case 0:
+ fputs_filtered ("Single Precision (24-bits)\n", file);
+ break;
+ case 1:
+ fputs_filtered ("Reserved\n", file);
+ break;
+ case 2:
+ fputs_filtered ("Double Precision (53-bits)\n", file);
+ break;
+ case 3:
+ fputs_filtered ("Extended Precision (64-bits)\n", file);
+ break;
+ }
+
+ fputs_filtered (" RC: ", file);
+ switch ((control >> 10) & 3)
+ {
+ case 0:
+ fputs_filtered ("Round to nearest\n", file);
+ break;
+ case 1:
+ fputs_filtered ("Round down\n", file);
+ break;
+ case 2:
+ fputs_filtered ("Round up\n", file);
+ break;
+ case 3:
+ fputs_filtered ("Round toward zero\n", file);
+ break;
+ }
+}