• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 #include <stdio.h>
3 #include <assert.h>
4 
5 
6 /* ------------------------------------------------- */
7 
8 typedef unsigned char          UChar;
9 typedef unsigned short         UShort;
10 typedef unsigned int           UInt;
11 typedef unsigned long long int ULong;
12 
13 typedef signed char     Char;
14 typedef short           Short;
15 typedef int             Int;
16 typedef long long int   Long;
17 
18 typedef
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 
60 char* fp_tag_names[4]
61    = { "Valid", "Zero", "Spec", "Empty" };
62 
63 char* fp_exception_names[6]
64    = { "INVAL", "DENOR", "DIVZ", "OVERF", "UNDERF", "LOS" };
65 
66 Fpu_State m_fpu_state;
67 
68 
69 
fp_get_tos(void)70 UInt fp_get_tos ( void )
71 {
72    return (m_fpu_state.env[FP_ENV_STAT] >> FP_F_TOS_LO) & 7;
73 }
74 
fp_get_tag(UInt regno)75 UInt 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 
fp_get_statusword_flag(UInt flagno)81 UInt 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 
fp_get_controlword_flag(UInt flagno)87 UInt 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 
93 static
printFpuState(void)94 void 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 
show(unsigned char * st)151 void 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 
main(void)165 int 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