blob: ed5de3dcd287b54404472d542925d0a5e3c11811 [file] [log] [blame]
sewardj07e09622004-09-06 20:39:20 +00001
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
26typedef
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
46static 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
80static 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 ...
114static void printFpuState ( UChar* fpu_state );
115static 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*/
121void 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");
sewardj6c54d112004-09-06 23:17:37 +0000137#if 0
138 asm volatile("frstor (%0) ; fsave (%0)"
139 :
140 : "r" (x87_state1)
141 : "memory" );
142#endif
sewardj07e09622004-09-06 20:39:20 +0000143 printFpuState(x87_state1);
144 printf("\n\n");
sewardj6c54d112004-09-06 23:17:37 +0000145 x87_to_vex(x87_state1, vex_state);
146 printVexState(vex_state);
147 printf("\n\n");
sewardj07e09622004-09-06 20:39:20 +0000148}
149
150int 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)");
sewardj6c54d112004-09-06 23:17:37 +0000160 asm volatile ("fldln2 ; fldlg2 ; fchs ; fsqrt");
sewardj07e09622004-09-06 20:39:20 +0000161 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
192char* fp_tag_names[4]
193 = { "Valid", "Zero", "Spec", "Empty" };
194
195char* fp_exception_names[6]
196 = { "INVAL", "DENOR", "DIVZ", "OVERF", "UNDERF", "LOS" };
197
198
199UInt fp_get_tos ( Fpu_State* x87 )
200{
201 return (x87->env[FP_ENV_STAT] >> FP_F_TOS_LO) & 7;
202}
203
204UInt 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
210UInt 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
216UInt 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
223static 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
276static 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}