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