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).
5 Includes code from fp_80_64.c.
8 #include "../pub/libvex_basictypes.h"
9 #include "../pub/libvex_ir.h"
10 #include "../priv/guest-x86/gdefs.h"
15 /* Get definitions of convert_f64le_to_f80le and
16 convert_f80le_to_f64le. */
17 #define USED_AS_INCLUDE
19 #undef USED_AS_INCLUDE
22 ////////////////////////////////////////////////////////////////
24 /* Layout of the real x87 state. */
33 /* Offsets, in 16-bit ints, into the FPU environment (env) area. */
37 #define FP_ENV_IP 6 /* and 7 */
39 #define FP_ENV_OPOFF 10 /* and 11 */
40 #define FP_ENV_OPSEL 12
41 #define FP_REG(ii) (10*(7-(ii)))
44 /* Layout of vex's FP state is defined in ../priv/guest-x86/gdefs.h */
46 static void x87_to_vex ( /*IN*/UChar
* x87_state
, /*OUT*/UChar
* vex_state
)
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
];
56 /* Copy registers and tags */
57 for (r
= 0; r
< 8; r
++) {
58 tag
= (tagw
>> (2*r
)) & 3;
60 /* register is empty */
64 /* register is non-empty */
65 convert_f80le_to_f64le( &x87
->reg
[FP_REG(r
)], (UChar
*)&vexRegs
[r
] );
71 *(UInt
*)(vex_state
+ OFFB_FTOP
) = ftop
;
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,
80 static void vex_to_x87 ( /*IN*/UChar
* vex_state
, /*OUT*/UChar
* x87_state
)
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
);
89 for (i
= 0; i
< 14; i
++)
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;
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
)] );
103 /* register is full. */
104 tagw
|= (0 << (2*r
));
105 convert_f64le_to_f80le( (UChar
*)&vexRegs
[r
], &x87
->reg
[FP_REG(r
)] );
108 x87
->env
[FP_ENV_TAG
] = tagw
;
111 ////////////////////////////////////////////////////////////////
114 static void printFpuState ( UChar
* fpu_state
);
115 static void printVexState ( UChar
* vex_state
);
118 /* Capture the FPU state. Convert it to vex. Convert it back
119 to x87. Print it at all stages.
121 void capture_convert_show ( /* preallocated storage */
126 asm volatile ("fsave (%0)"
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
);
135 printVexState(vex_state
);
138 asm volatile("frstor (%0) ; fsave (%0)"
143 printFpuState(x87_state1
);
145 x87_to_vex(x87_state1
, vex_state
);
146 printVexState(vex_state
);
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
);
165 ////////////////////////////////////////////////////////////////
167 /* Bitfield offsets for exceptions in the FPU status and control words. */
175 /* More bitfield offsets, but for the status word only. */
176 #define FP_E_STACKF 6
177 #define FP_E_SUMMARY 7
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
187 #define FP_TAG_VALID 0
188 #define FP_TAG_ZERO 1
189 #define FP_TAG_SPEC 2
190 #define FP_TAG_EMPTY 3
192 char* fp_tag_names
[4]
193 = { "Valid", "Zero", "Spec", "Empty" };
195 char* fp_exception_names
[6]
196 = { "INVAL", "DENOR", "DIVZ", "OVERF", "UNDERF", "LOS" };
199 UInt
fp_get_tos ( Fpu_State
* x87
)
201 return (x87
->env
[FP_ENV_STAT
] >> FP_F_TOS_LO
) & 7;
204 UInt
fp_get_tag ( Fpu_State
* x87
, UInt regno
)
206 assert(!(regno
< 0 || regno
> 7));
207 return (x87
->env
[FP_ENV_TAG
] >> (2*regno
)) & 3;
210 UInt
fp_get_statusword_flag ( Fpu_State
* x87
, UInt flagno
)
212 assert(!(flagno
< 0 || flagno
> 15));
213 return (x87
->env
[FP_ENV_STAT
] >> flagno
) & 0x1;
216 UInt
fp_get_controlword_flag ( Fpu_State
* x87
, UInt flagno
)
218 assert(!(flagno
< 0 || flagno
> 15));
219 return (x87
->env
[FP_ENV_CTRL
] >> flagno
) & 0x1;
223 static void printFpuState ( UChar
* fpu_state
)
225 Fpu_State
* x87
= (Fpu_State
*)fpu_state
;
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
)] );
236 //printf ( "%20.16e\n", fp_get_reg(i) );
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
] );
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
) );
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
)] );
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
]) );
276 static void printVexState ( UChar
* vex_state
)
279 ULong
* vexRegs
= (ULong
*)(vex_state
+ OFFB_F0
);
280 UChar
* vexTags
= (UChar
*)(vex_state
+ OFFB_FTAG0
);
281 UInt ftop
= *(UInt
*)(vex_state
+ OFFB_FTOP
);
283 for (r
= 7; r
>= 0; r
--) {
284 printf("%s %%f%d: 0x%llx %s\n",
285 r
== ftop
? "##" : " ",
288 vexTags
[r
] == 0 ? "Empty" : "Full" );