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