Published on Wednesday, September 12th, 2007 at 8:24 pm

Ever have those demons inside your computer that you swear are messing with your bits and producing random errors? Me too. During one of these bug chasing marathons, I wrote a FPU dumper that prints out the state of the x87 FPU whenever it is called. The program that I was working on was getting random numerical corruption on an older version of Cygwin’s GCC. I traced the corruption to a single line that had a floating point divide. The value was fine before the line was run and clobbered to a NaN after the line was run. Great, demons. The FPU dumper helped me realize what was going on. Long story short, there was a bug in newlib (Cygwin’s standard C library) which caused it to not conform to C99. The bug didn’t show up in my newer version of GCC because GCC provided a builtin for the missing C99 math function. I sent off a description to the bug to the newlib mailing list and Jeff Johnston had a patch within an hour. Thanks Jeff!

Regarding the FPU dumper, it is a header file that you include in whatever code you want to check the FPU from. If you uncomment the #define FPU_DUMP_VERBOSE line in the header or define it in the compile line (-DFPU_DUMP_VERBOSE), it prints off a bit more info on the status registers. To do the actual dumping, simply call FPUDUMP from anywhere in your code. The FPU state is saved into a struct, parsed, printed, and the FPU state is restored from the struct lest something like printf messes with the FPU in some way.

The code is licensed under the zlib license. The output format is borrowed from the excellent OllyDbg, my favorite Windows debugger. Feel free to comment/criticize my code!
Here is the code!

Example code calling the dumper:

  1. #include "fpu_dump.h"
  2.  
  3. double x = 243;
  4. FPUDUMP;
  5. x = x / 3.14;
  6. FPUDUMP;

An example of the verbose output:

  1. ================== MAGICAL FPU INSPECTOR ==================
  2. From fpu_dump.c line 20:
  3.  
  4. Status: 0×0020
  5. Invalid: 0, Denorm: 0, Zero Div: 0
  6. Overflow: 0, Underflow: 0, Precision: 1
  7. Stack fault: 0, Error summary: 0, TOP: 0
  8. C3: 0, C2: 0, C1: 0, C0: 0
  9.  
  10. Control: 0×037F
  11. Invalid Mask: 1, Denorm Mask: 1, Zero Div Mask: 1
  12. Overflow Mask: 1, Underflow Mask: 1, Precision Mask: 1
  13. Rounding: NEAR, Precision: 64, Infinity: 0
  14.  
  15. 3 2 1 0      E S P U O Z D I
  16. FST 0020  Cond 0 0 0 0  Err 0 0 1 0 0 0 0 0  (GT)
  17. FCW 037F  Prec NEAR,64  Mask    1 1 1 1 1 1
  18.  
  19. ST0  EMPTY                        NAN   REG0
  20. FFFF 00000000 00000000
  21.  
  22. ST1  EMPTY                          0   REG1
  23. 0000 00000000 00000000
  24.  
  25. ST2  EMPTY                          0   REG2
  26. 0000 00000000 00000000
  27.  
  28. ST3  EMPTY                          0   REG3
  29. 0000 00000000 00000000
  30.  
  31. ST4  EMPTY                          0   REG4
  32. 0000 00000000 00000000
  33.  
  34. ST5  EMPTY                          0   REG5
  35. 0000 00000000 00000000
  36.  
  37. ST6  EMPTY       16045690984229361664   REG6
  38. 403E DEADBEEF BAADD800
  39.  
  40. ST7  EMPTY       16045690984229355520   REG7
  41. 403E DEADBEEF BAADC0DF
  42.  
  43. ========================= GOODBYE =========================

Related Posts

3 Responses to “x87 FPU State Dumper”

  1. I am not a true nerd. I don’t understand even 90% of this post. I love it.

  2. Need update! Have not had on in many months!

  3. Oh yea. What happened to PPH?

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>