]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
x86 guest: implement fsave/frstor instructions
authorJulian Seward <jseward@acm.org>
Fri, 26 Nov 2004 17:57:40 +0000 (17:57 +0000)
committerJulian Seward <jseward@acm.org>
Fri, 26 Nov 2004 17:57:40 +0000 (17:57 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@591

VEX/priv/guest-x86/gdefs.h
VEX/priv/guest-x86/ghelpers.c
VEX/priv/guest-x86/toIR.c
VEX/pub/libvex_ir.h
VEX/test/frstor.c [new file with mode: 0644]
VEX/test/fsave.c [new file with mode: 0644]

index 77099c1cf829e5f77b14e9d19ea405253c1a3d31..2cca5032a2769a0b69dbf2327ccfa3a170cbfd7f 100644 (file)
@@ -160,6 +160,10 @@ extern void  x86g_storeF80le ( UInt, ULong );
 
 extern void  x86g_dirtyhelper_CPUID ( VexGuestX86State* );
 
+extern void  x86g_dirtyhelper_FSAVE ( VexGuestX86State*, HWord );
+
+extern void x86g_dirtyhelper_FRSTOR ( VexGuestX86State*, HWord );
+
 
 /*---------------------------------------------------------*/
 /*--- Condition code stuff                              ---*/
index af352b75aa0d579ed162255fe743e67c3baa2d05..54a425958109a3d5436bae5268bcdc01030489e1 100644 (file)
@@ -1543,7 +1543,7 @@ void LibVEX_GuestX86_initialise ( /*OUT*/VexGuestX86State* vex_state )
 
 
 /*----------------------------------------------*/
-/*--- Misc integer helpers                   ---*/
+/*--- Misc integer/fp helpers                ---*/
 /*----------------------------------------------*/
 
 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
@@ -1620,6 +1620,20 @@ void x86g_dirtyhelper_CPUID ( VexGuestX86State* st )
 }
 
 
+/* CALLED FROM GENERATED CODE */
+/* DIRTY HELPER (reads guest state, writes guest mem) */
+void x86g_dirtyhelper_FSAVE ( VexGuestX86State* gst, HWord addr )
+{
+   LibVEX_GuestX86_get_x87( gst, (UChar*)addr );
+}
+
+/* CALLED FROM GENERATED CODE */
+/* DIRTY HELPER (writes guest state, reads guest mem) */
+void x86g_dirtyhelper_FRSTOR ( VexGuestX86State* gst, HWord addr )
+{
+   LibVEX_GuestX86_put_x87( (UChar*)addr, gst );
+}
+
 
 /*----------------------------------------------*/
 /*--- Helpers for MMX                        ---*/
index ff333716920acf9ba88331ad21051ba841c66964..66646dd713ae13bf7966ddf0faaadac247ef0a06 100644 (file)
@@ -4171,7 +4171,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
             }
 
             case 7: { /* FSTP extended-real */
-               /* Uses dirty helper: void storeF80le ( UInt, ULong ) */
+               /* Uses dirty helper: void x86g_storeF80le ( UInt, ULong ) */
                IRExpr** args 
                   = mkIRExprVec_2( mkexpr(addr), 
                                    unop(Iop_ReinterpF64asI64, get_ST(0)) );
@@ -4366,6 +4366,92 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt delta )
                fp_pop();
                break;
 
+            case 4: { /* FRSTOR m108 */
+               /* Uses dirty helper: x86g_do_FRSTOR ( VexGuestX86State*, UInt ) */
+               IRDirty* d = unsafeIRDirty_0_N ( 
+                               0/*regparms*/, 
+                               "x86g_dirtyhelper_FRSTOR", 
+                               &x86g_dirtyhelper_FRSTOR,
+                               mkIRExprVec_1( mkexpr(addr) )
+                            );
+               d->needsBBP = True;
+               /* declare we're reading memory */
+               d->mFx   = Ifx_Read;
+               d->mAddr = mkexpr(addr);
+               d->mSize = 108;
+
+               /* declare we're writing guest state */
+              d->nFxState = 5;
+
+               d->fxState[0].fx     = Ifx_Write;
+               d->fxState[0].offset = offsetof(VexGuestX86State,guest_FTOP);
+               d->fxState[0].size   = sizeof(UInt);
+
+               d->fxState[1].fx     = Ifx_Write;
+               d->fxState[1].offset = offsetof(VexGuestX86State,guest_FPREG);
+               d->fxState[1].size   = 8 * sizeof(ULong);
+
+               d->fxState[2].fx     = Ifx_Write;
+               d->fxState[2].offset = offsetof(VexGuestX86State,guest_FPTAG);
+               d->fxState[2].size   = 8 * sizeof(UChar);
+
+               d->fxState[3].fx     = Ifx_Write;
+               d->fxState[3].offset = offsetof(VexGuestX86State,guest_FPUCW);
+               d->fxState[3].size   = sizeof(UInt);
+
+               d->fxState[4].fx     = Ifx_Write;
+               d->fxState[4].offset = offsetof(VexGuestX86State,guest_FC3210);
+               d->fxState[4].size   = sizeof(UInt);
+
+               stmt( IRStmt_Dirty(d) );
+
+               DIP("frstor %s", dis_buf);
+               break;
+            }
+
+            case 6: { /* FNSAVE m108 */
+               /* Uses dirty helper: x86g_do_FSAVE ( VexGuestX86State*, UInt ) */
+               IRDirty* d = unsafeIRDirty_0_N ( 
+                               0/*regparms*/, 
+                               "x86g_dirtyhelper_FSAVE", 
+                               &x86g_dirtyhelper_FSAVE,
+                               mkIRExprVec_1( mkexpr(addr) )
+                            );
+               d->needsBBP = True;
+               /* declare we're writing memory */
+               d->mFx   = Ifx_Write;
+               d->mAddr = mkexpr(addr);
+               d->mSize = 108;
+
+               /* declare we're reading guest state */
+              d->nFxState = 5;
+
+               d->fxState[0].fx     = Ifx_Read;
+               d->fxState[0].offset = offsetof(VexGuestX86State,guest_FTOP);
+               d->fxState[0].size   = sizeof(UInt);
+
+               d->fxState[1].fx     = Ifx_Read;
+               d->fxState[1].offset = offsetof(VexGuestX86State,guest_FPREG);
+               d->fxState[1].size   = 8 * sizeof(ULong);
+
+               d->fxState[2].fx     = Ifx_Read;
+               d->fxState[2].offset = offsetof(VexGuestX86State,guest_FPTAG);
+               d->fxState[2].size   = 8 * sizeof(UChar);
+
+               d->fxState[3].fx     = Ifx_Read;
+               d->fxState[3].offset = offsetof(VexGuestX86State,guest_FPUCW);
+               d->fxState[3].size   = sizeof(UInt);
+
+               d->fxState[4].fx     = Ifx_Read;
+               d->fxState[4].offset = offsetof(VexGuestX86State,guest_FC3210);
+               d->fxState[4].size   = sizeof(UInt);
+
+               stmt( IRStmt_Dirty(d) );
+
+               DIP("fnsave %s", dis_buf);
+               break;
+            }
+
             default:
                vex_printf("unhandled opc_aux = 0x%2x\n", gregOfRM(modrm));
                vex_printf("first_opcode == 0xDD\n");
index 9feb773584247aef273c8e1ec99a63788644e83a..aa847a3f0051c0d6f220e7256e6e5d7b69b1e4c5 100644 (file)
@@ -537,7 +537,7 @@ inline static Bool isAtom ( IRExpr* e ) {
    evaluation.
 */
 
-#define VEX_N_FXSTATE  4   /* enough for CPUID on x86 */
+#define VEX_N_FXSTATE  5   /* enough for FSAVE/FRSTOR on x86 */
 
 typedef
    enum {
diff --git a/VEX/test/frstor.c b/VEX/test/frstor.c
new file mode 100644 (file)
index 0000000..437f094
--- /dev/null
@@ -0,0 +1,35 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void do_fsave ( void* p )
+{
+   asm("movl 8(%esp), %eax ; fsave (%eax)");
+}
+
+void do_frstor ( void* p )
+{
+   asm("movl 8(%esp), %eax ; frstor (%eax)");
+}
+
+int main ( void )
+{
+   int i;
+   unsigned short* buf = malloc(54*sizeof(int));
+   for (i = 0; i < 54; i++)
+      buf[i] = i;
+   buf[0] = 0x037f;
+
+   for (i = 0; i < 8; i++)
+      *(long double *)(&buf[14+5 *i]) = 0.1234 * i;
+
+   do_frstor(buf);
+   do_fsave(buf);
+   for (i = 0; i < 54; i++) {
+      printf("%04x ", buf[i]);
+      if (i > 0 && ((i % 12) == 11))
+          printf("\n");
+   }
+   printf("\n");
+   return 0;
+}
diff --git a/VEX/test/fsave.c b/VEX/test/fsave.c
new file mode 100644 (file)
index 0000000..2e0ba15
--- /dev/null
@@ -0,0 +1,22 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void do_fsave ( void* p )
+{
+   asm("fldpi ; fld1; fldln2 ; movl 8(%esp), %eax ; fsave (%eax)");
+}
+
+int main ( void )
+{
+   int i;
+   unsigned int* buf = malloc(27*sizeof(int));
+   do_fsave(buf);
+   for (i = 0; i < 27; i++) {
+      printf("%08x ", buf[i]);
+      if (i > 0 && ((i % 6) == 5))
+          printf("\n");
+   }
+   printf("\n");
+   return 0;
+}