1
2#include <stdio.h>
3#include <assert.h>
4
5
6/* ------------------------------------------------- */
7
8typedef unsigned char          UChar;
9typedef unsigned short         UShort;
10typedef unsigned int           UInt;
11typedef unsigned long long int ULong;
12
13typedef signed char     Char;
14typedef short           Short;
15typedef int             Int;
16typedef long long int   Long;
17
18typedef
19   struct {
20      UShort env[14];
21      UChar  reg[80];
22   }
23   Fpu_State;
24
25/* Offsets, in 16-bit ints, into the FPU environment (env) area. */
26#define FP_ENV_CTRL   0
27#define FP_ENV_STAT   2
28#define FP_ENV_TAG    4
29#define FP_ENV_IP     6 /* and 7 */
30#define FP_ENV_CS     8
31#define FP_ENV_OPOFF  10 /* and 11 */
32#define FP_ENV_OPSEL  12
33#define FP_REG(ii)    (10*(7-(ii)))
34
35/* Bitfield offsets for exceptions in the FPU status and control words. */
36#define FP_E_INVAL    0
37#define FP_E_DENOR    1
38#define FP_E_DIVZ     2
39#define FP_E_OVERF    3
40#define FP_E_UNDER    4
41#define FP_E_LOS      5
42
43/* More bitfield offsets, but for the status word only. */
44#define FP_E_STACKF   6
45#define FP_E_SUMMARY  7
46#define FP_F_C0       8
47#define FP_F_C1       9
48#define FP_F_C2      10
49#define FP_F_C3      14
50/* top-of-stack ptr is bits 13,12,11 of the word */
51#define FP_F_TOS_LO  11
52#define FP_F_TOS_HI  13
53
54/* Register tags. */
55#define FP_TAG_VALID 0
56#define FP_TAG_ZERO  1
57#define FP_TAG_SPEC  2
58#define FP_TAG_EMPTY 3
59
60char* fp_tag_names[4]
61   = { "Valid", "Zero", "Spec", "Empty" };
62
63char* fp_exception_names[6]
64   = { "INVAL", "DENOR", "DIVZ", "OVERF", "UNDERF", "LOS" };
65
66Fpu_State m_fpu_state;
67
68
69
70UInt fp_get_tos ( void )
71{
72   return (m_fpu_state.env[FP_ENV_STAT] >> FP_F_TOS_LO) & 7;
73}
74
75UInt fp_get_tag ( UInt regno )
76{
77   assert(!(regno < 0 || regno > 7));
78   return (m_fpu_state.env[FP_ENV_TAG] >> (2*regno)) & 3;
79}
80
81UInt fp_get_statusword_flag ( UInt flagno )
82{
83   assert(!(flagno < 0 || flagno > 15));
84   return (m_fpu_state.env[FP_ENV_STAT] >> flagno) & 0x1;
85}
86
87UInt fp_get_controlword_flag ( UInt flagno )
88{
89   assert(!(flagno < 0 || flagno > 15));
90   return (m_fpu_state.env[FP_ENV_CTRL] >> flagno) & 0x1;
91}
92
93static
94void printFpuState ( void )
95{
96   Int i, j, k;
97   assert(sizeof(Fpu_State)==108);
98   for (i = 7; i >= 0; i--) {
99      printf ( " %s fpreg%d: 0x",
100               (UInt)i == fp_get_tos() ? "**" : "  ", i );
101      for (k = 0, j = FP_REG(i)+9; k < 10; k++,j--)
102         printf ( "%02x", (UInt)m_fpu_state.reg[j]);
103      printf ( "  %5s  ", fp_tag_names[fp_get_tag(i)] );
104      printf("\n");
105      //printf ( "%20.16e\n", fp_get_reg(i) );
106   }
107   printf("     fctrl:     0x%04x  masked: ",
108          (UInt)m_fpu_state.env[FP_ENV_CTRL] );
109   for (i = FP_E_INVAL; i <= FP_E_LOS; i++)
110      if (fp_get_controlword_flag(i))
111         printf ( "%s ", fp_exception_names[i] );
112   printf ( "\n" );
113
114   printf("     fstat:     0x%04x  except:",
115          (UInt)m_fpu_state.env[FP_ENV_STAT] );
116   for (i = FP_E_INVAL; i <= FP_E_LOS; i++)
117      if (fp_get_statusword_flag(i))
118         printf ( "%s ", fp_exception_names[i] );
119   printf ( "  top: %d  ", fp_get_tos() );
120   printf ( "c3210: %d%d%d%d",
121            fp_get_statusword_flag(FP_F_C3),
122            fp_get_statusword_flag(FP_F_C2),
123            fp_get_statusword_flag(FP_F_C1),
124            fp_get_statusword_flag(FP_F_C0) );
125   printf ( "  STACKF: %d\n", fp_get_statusword_flag(FP_E_STACKF) );
126
127   printf("      ftag:     0x%04x  ", (UInt)m_fpu_state.env[FP_ENV_TAG] );
128   for (i = 7; i >= 0; i--)
129      printf ( "%d:%s ", i, fp_tag_names[fp_get_tag(i)] );
130   printf("\n");
131
132   printf("       fip: 0x%08x\n",
133           (((UInt)m_fpu_state.env[FP_ENV_IP+1]) << 16) |
134            ((UInt)m_fpu_state.env[FP_ENV_IP]) );
135   printf("       fcs:     0x%04x\n",
136           ((UInt)m_fpu_state.env[FP_ENV_CS]) );
137   printf("    fopoff: 0x%08x\n",
138           (((UInt)m_fpu_state.env[FP_ENV_OPOFF+1]) << 16) |
139            ((UInt)m_fpu_state.env[FP_ENV_OPOFF]) );
140   printf("    fopsel:     0x%04x\n",
141           ((UInt)m_fpu_state.env[FP_ENV_OPSEL]) );
142}
143
144
145/* ------------------------------------------------- */
146
147
148/* Initialise the FPU, dump its state, and print it. */
149
150
151void show ( unsigned char* st )
152{
153  int i;
154  for (i = 0; i < 28; i++) {
155    printf("%02x ", st[i]);
156    if (i > 0 && ((i & 3) == 3)) printf("\n");
157  }
158  for (i = 0; i < 80; i++) {
159    printf("%02x ", st[i+28]);
160    if (i > 0 && ((i % 10) == 9)) printf("\n");
161  }
162  printf("\n");
163}
164
165int main ( void )
166{
167  Fpu_State* st = &m_fpu_state;
168  assert(sizeof(m_fpu_state) == 108);
169  asm volatile ("finit ; fnsave %0"
170                : "=m" (m_fpu_state)
171                :
172                : "memory" );
173  printFpuState();
174  printf("\n\n");
175
176  asm volatile ("fildl 0(%%esp) ; pushl $17 ; fildl 0(%%esp) ; addl $4, %%esp ;  fnsave %0"
177                : "=m" (m_fpu_state)
178                :
179                : "memory" );
180  printFpuState();
181  printf("\n");
182  show(st);
183  return 0;
184}
185