1
2 /* Testing framework, for developing code to copy vex's x87 simulation
3 state to and from a real x87 state image (the 108-byte thing).
4
5 Includes code from fp_80_64.c.
6 */
7
8 #include "../pub/libvex_basictypes.h"
9 #include "../pub/libvex_ir.h"
10 #include "../priv/guest-x86/gdefs.h"
11 #include <stdio.h>
12 #include <assert.h>
13 #include <stdlib.h>
14
15 /* Get definitions of convert_f64le_to_f80le and
16 convert_f80le_to_f64le. */
17 #define USED_AS_INCLUDE
18 #include "fp_80_64.c"
19 #undef USED_AS_INCLUDE
20
21
22 ////////////////////////////////////////////////////////////////
23
24 /* Layout of the real x87 state. */
25
26 typedef
27 struct {
28 UShort env[14];
29 UChar reg[80];
30 }
31 Fpu_State;
32
33 /* Offsets, in 16-bit ints, into the FPU environment (env) area. */
34 #define FP_ENV_CTRL 0
35 #define FP_ENV_STAT 2
36 #define FP_ENV_TAG 4
37 #define FP_ENV_IP 6 /* and 7 */
38 #define FP_ENV_CS 8
39 #define FP_ENV_OPOFF 10 /* and 11 */
40 #define FP_ENV_OPSEL 12
41 #define FP_REG(ii) (10*(7-(ii)))
42
43
44 /* Layout of vex's FP state is defined in ../priv/guest-x86/gdefs.h */
45
x87_to_vex(UChar * x87_state,UChar * vex_state)46 static void x87_to_vex ( /*IN*/UChar* x87_state, /*OUT*/UChar* vex_state )
47 {
48 Int r;
49 UInt tag;
50 Double* vexRegs = (Double*)(vex_state + OFFB_F0);
51 UChar* vexTags = (UChar*)(vex_state + OFFB_FTAG0);
52 Fpu_State* x87 = (Fpu_State*)x87_state;
53 UInt ftop = (x87->env[FP_ENV_STAT] >> 11) & 7;
54 UInt tagw = x87->env[FP_ENV_TAG];
55
56 /* Copy registers and tags */
57 for (r = 0; r < 8; r++) {
58 tag = (tagw >> (2*r)) & 3;
59 if (tag == 3) {
60 /* register is empty */
61 vexRegs[r] = 0.0;
62 vexTags[r] = 0;
63 } else {
64 /* register is non-empty */
65 convert_f80le_to_f64le( &x87->reg[FP_REG(r)], (UChar*)&vexRegs[r] );
66 vexTags[r] = 1;
67 }
68 }
69
70 /* stack pointer */
71 *(UInt*)(vex_state + OFFB_FTOP) = ftop;
72
73 /* TODO: Check the CW is 037F. Or at least, bottom 6 bits are 1
74 (all exceptions masked), and 11:10, which is rounding control,
75 is set to ..?
76 */
77 }
78
79
vex_to_x87(UChar * vex_state,UChar * x87_state)80 static void vex_to_x87 ( /*IN*/UChar* vex_state, /*OUT*/UChar* x87_state )
81 {
82 Int i, r;
83 UInt tagw;
84 Double* vexRegs = (Double*)(vex_state + OFFB_F0);
85 UChar* vexTags = (UChar*)(vex_state + OFFB_FTAG0);
86 Fpu_State* x87 = (Fpu_State*)x87_state;
87 UInt ftop = *(UInt*)(vex_state + OFFB_FTOP);
88
89 for (i = 0; i < 14; i++)
90 x87->env[i] = 0;
91
92 x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
93 x87->env[FP_ENV_CTRL] = 0x037F;
94 x87->env[FP_ENV_STAT] = (ftop & 7) << 11;
95
96 tagw = 0;
97 for (r = 0; r < 8; r++) {
98 if (vexTags[r] == 0) {
99 /* register is empty */
100 tagw |= (3 << (2*r));
101 convert_f64le_to_f80le( (UChar*)&vexRegs[r], &x87->reg[FP_REG(r)] );
102 } else {
103 /* register is full. */
104 tagw |= (0 << (2*r));
105 convert_f64le_to_f80le( (UChar*)&vexRegs[r], &x87->reg[FP_REG(r)] );
106 }
107 }
108 x87->env[FP_ENV_TAG] = tagw;
109 }
110
111 ////////////////////////////////////////////////////////////////
112
113 // fwds ...
114 static void printFpuState ( UChar* fpu_state );
115 static void printVexState ( UChar* vex_state );
116
117
118 /* Capture the FPU state. Convert it to vex. Convert it back
119 to x87. Print it at all stages.
120 */
capture_convert_show(UChar * x87_state0,UChar * x87_state1,UChar * vex_state)121 void capture_convert_show ( /* preallocated storage */
122 UChar* x87_state0,
123 UChar* x87_state1,
124 UChar* vex_state )
125 {
126 asm volatile ("fsave (%0)"
127 :
128 : "r" (x87_state0)
129 : "memory" );
130 x87_to_vex(x87_state0, vex_state);
131 vex_to_x87(vex_state, x87_state1);
132 printf("\n\n=================================================\n\n");
133 printFpuState(x87_state0);
134 printf("\n\n");
135 printVexState(vex_state);
136 printf("\n\n");
137 #if 0
138 asm volatile("frstor (%0) ; fsave (%0)"
139 :
140 : "r" (x87_state1)
141 : "memory" );
142 #endif
143 printFpuState(x87_state1);
144 printf("\n\n");
145 x87_to_vex(x87_state1, vex_state);
146 printVexState(vex_state);
147 printf("\n\n");
148 }
149
main(void)150 int main ( void )
151 {
152 UChar* x87_state0 = malloc(sizeof(Fpu_State));
153 UChar* x87_state1 = malloc(sizeof(Fpu_State));
154 UChar* vex_state = malloc(1000);
155 asm volatile ("finit");
156 capture_convert_show(x87_state0, x87_state1, vex_state);
157 asm volatile ("fldpi");
158 capture_convert_show(x87_state0, x87_state1, vex_state);
159 asm volatile ("fldz ; fld1 ; fdiv %st(1)");
160 asm volatile ("fldln2 ; fldlg2 ; fchs ; fsqrt");
161 capture_convert_show(x87_state0, x87_state1, vex_state);
162 return 1;
163 }
164
165 ////////////////////////////////////////////////////////////////
166
167 /* Bitfield offsets for exceptions in the FPU status and control words. */
168 #define FP_E_INVAL 0
169 #define FP_E_DENOR 1
170 #define FP_E_DIVZ 2
171 #define FP_E_OVERF 3
172 #define FP_E_UNDER 4
173 #define FP_E_LOS 5
174
175 /* More bitfield offsets, but for the status word only. */
176 #define FP_E_STACKF 6
177 #define FP_E_SUMMARY 7
178 #define FP_F_C0 8
179 #define FP_F_C1 9
180 #define FP_F_C2 10
181 #define FP_F_C3 14
182 /* top-of-stack ptr is bits 13,12,11 of the word */
183 #define FP_F_TOS_LO 11
184 #define FP_F_TOS_HI 13
185
186 /* Register tags. */
187 #define FP_TAG_VALID 0
188 #define FP_TAG_ZERO 1
189 #define FP_TAG_SPEC 2
190 #define FP_TAG_EMPTY 3
191
192 char* fp_tag_names[4]
193 = { "Valid", "Zero", "Spec", "Empty" };
194
195 char* fp_exception_names[6]
196 = { "INVAL", "DENOR", "DIVZ", "OVERF", "UNDERF", "LOS" };
197
198
fp_get_tos(Fpu_State * x87)199 UInt fp_get_tos ( Fpu_State* x87 )
200 {
201 return (x87->env[FP_ENV_STAT] >> FP_F_TOS_LO) & 7;
202 }
203
fp_get_tag(Fpu_State * x87,UInt regno)204 UInt fp_get_tag ( Fpu_State* x87, UInt regno )
205 {
206 assert(!(regno < 0 || regno > 7));
207 return (x87->env[FP_ENV_TAG] >> (2*regno)) & 3;
208 }
209
fp_get_statusword_flag(Fpu_State * x87,UInt flagno)210 UInt fp_get_statusword_flag ( Fpu_State* x87, UInt flagno )
211 {
212 assert(!(flagno < 0 || flagno > 15));
213 return (x87->env[FP_ENV_STAT] >> flagno) & 0x1;
214 }
215
fp_get_controlword_flag(Fpu_State * x87,UInt flagno)216 UInt fp_get_controlword_flag ( Fpu_State* x87, UInt flagno )
217 {
218 assert(!(flagno < 0 || flagno > 15));
219 return (x87->env[FP_ENV_CTRL] >> flagno) & 0x1;
220 }
221
222
printFpuState(UChar * fpu_state)223 static void printFpuState ( UChar* fpu_state )
224 {
225 Fpu_State* x87 = (Fpu_State*)fpu_state;
226
227 Int i, j, k;
228 assert(sizeof(Fpu_State)==108);
229 for (i = 7; i >= 0; i--) {
230 printf ( " %s fpreg%d: 0x",
231 (UInt)i == fp_get_tos(x87) ? "**" : " ", i );
232 for (k = 0, j = FP_REG(i)+9; k < 10; k++,j--)
233 printf ( "%02x", (UInt)x87->reg[j]);
234 printf ( " %5s ", fp_tag_names[fp_get_tag(x87,i)] );
235 printf("\n");
236 //printf ( "%20.16e\n", fp_get_reg(i) );
237 }
238 printf(" fctrl: 0x%04x masked: ",
239 (UInt)x87->env[FP_ENV_CTRL] );
240 for (i = FP_E_INVAL; i <= FP_E_LOS; i++)
241 if (fp_get_controlword_flag(x87,i))
242 printf ( "%s ", fp_exception_names[i] );
243 printf ( "\n" );
244
245 printf(" fstat: 0x%04x except:",
246 (UInt)x87->env[FP_ENV_STAT] );
247 for (i = FP_E_INVAL; i <= FP_E_LOS; i++)
248 if (fp_get_statusword_flag(x87,i))
249 printf ( "%s ", fp_exception_names[i] );
250 printf ( " top: %d ", fp_get_tos(x87) );
251 printf ( "c3210: %d%d%d%d",
252 fp_get_statusword_flag(x87,FP_F_C3),
253 fp_get_statusword_flag(x87,FP_F_C2),
254 fp_get_statusword_flag(x87,FP_F_C1),
255 fp_get_statusword_flag(x87,FP_F_C0) );
256 printf ( " STACKF: %d\n", fp_get_statusword_flag(x87,FP_E_STACKF) );
257
258 printf(" ftag: 0x%04x ", (UInt)x87->env[FP_ENV_TAG] );
259 for (i = 7; i >= 0; i--)
260 printf ( "%d:%s ", i, fp_tag_names[fp_get_tag(x87,i)] );
261 printf("\n");
262
263 printf(" fip: 0x%08x\n",
264 (((UInt)x87->env[FP_ENV_IP+1]) << 16) |
265 ((UInt)x87->env[FP_ENV_IP]) );
266 printf(" fcs: 0x%04x\n",
267 ((UInt)x87->env[FP_ENV_CS]) );
268 printf(" fopoff: 0x%08x\n",
269 (((UInt)x87->env[FP_ENV_OPOFF+1]) << 16) |
270 ((UInt)x87->env[FP_ENV_OPOFF]) );
271 printf(" fopsel: 0x%04x\n",
272 ((UInt)x87->env[FP_ENV_OPSEL]) );
273 }
274
275
printVexState(UChar * vex_state)276 static void printVexState ( UChar* vex_state )
277 {
278 Int r;
279 ULong* vexRegs = (ULong*)(vex_state + OFFB_F0);
280 UChar* vexTags = (UChar*)(vex_state + OFFB_FTAG0);
281 UInt ftop = *(UInt*)(vex_state + OFFB_FTOP);
282
283 for (r = 7; r >= 0; r--) {
284 printf("%s %%f%d: 0x%llx %s\n",
285 r == ftop ? "##" : " ",
286 r,
287 vexRegs[r],
288 vexTags[r] == 0 ? "Empty" : "Full" );
289 }
290
291 }
292