]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Remove all references to hardwired guest state offsets. Instead,
authorJulian Seward <jseward@acm.org>
Tue, 19 Oct 2004 01:03:46 +0000 (01:03 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 19 Oct 2004 01:03:46 +0000 (01:03 +0000)
allow definition of a struct containing the guest state (eg,
VexGuestX86State in pub/libvex_guest_x86.h) and derive all offsets
from that struct.

git-svn-id: svn://svn.valgrind.org/vex/trunk@365

VEX/priv/guest-x86/gdefs.h
VEX/priv/guest-x86/ghelpers.c
VEX/priv/guest-x86/toIR.c
VEX/pub/libvex_guest_x86.h

index 521ccf6b5a5b18028a3e72ed8415f42ae21c8c5c..758fe68372f6588abc1f1d18e2042bf8ee91e490 100644 (file)
@@ -144,99 +144,6 @@ typedef
    }
    Condcode;
 
-
-/*---------------------------------------------------------*/
-/*--- Simulated state offsets                           ---*/
-/*---------------------------------------------------------*/
-
-/* Hmm, subregisters.  The simulated state is stored in memory in the
-   host's byte ordering, so we can't say here what the offsets of %ax,
-   %al, %ah etc are since that depends on the host's byte ordering,
-   which we don't know. */
-
-#define OFFB_EAX     (0*4)
-#define OFFB_ECX     (1*4)
-#define OFFB_EDX     (2*4)
-#define OFFB_EBX     (3*4)
-#define OFFB_ESP     (4*4)
-#define OFFB_EBP     (5*4)
-#define OFFB_ESI     (6*4)
-#define OFFB_EDI     (7*4)
-/* 3-word thunk used to calculate O S Z A C P flags. */
-#define OFFB_CC_OP   (8*4)
-#define OFFB_CC_SRC  (9*4)
-#define OFFB_CC_DST  (10*4)
-/* The D flag is stored here, as either -1 or +1 */
-#define OFFB_DFLAG   (11*4)
-/* EIP */
-#define OFFB_EIP     (12*4)
-
-/* FPU.  For now, just simulate 8 64-bit registers, their tags, and
-   the reg-stack top pointer, of which only the least significant
-   three bits are relevant.
-
-   The model is:
-     F0 .. F7 are the 8 registers.  FTOP[2:0] contains the 
-     index of the current 'stack top' -- pretty meaningless, but
-     still.  FTOP is a 32-bit value.  FTOP[31:3] can be anything
-     (not guaranteed to be zero).
-
-     When a value is pushed onto the stack, ftop is first replaced by 
-     (ftop-1) & 7, and then F[ftop] is assigned the value.
-
-     When a value is popped off the stack, the value is read from
-     F[ftop], and then ftop is replaced by (ftop+1) & 7.
-
-     In general, a reference to a register ST(i) actually references
-     F[ (ftop+i) & 7 ].
-
-   FTAG0 .. FTAG0+7 are the tags.  Each is a byte, zero means empty,
-   non-zero means non-empty.
-
-   The general rule appears to be that a read or modify of a register
-   gets a stack underflow fault if the register is empty.  A write of
-   a register (only a write, not a modify) gets a stack overflow fault
-   if the register is full.  Note that "over" vs "under" is pretty
-   meaningless since the FP stack pointer can move around arbitrarily,
-   so it's really just two different kinds of exceptions:
-   register-empty and register full.
-
-   Naturally Intel (in its infinite wisdom) has seen fit to throw in
-   some ad-hoc inconsistencies to the fault-generation rules of the
-   above para, just to complicate everything.  Known inconsistencies:
-
-   * fxam can read a register in any state without taking an underflow
-     fault.
-
-   * fst from st(0) to st(i) does not take an overflow fault even if the
-     destination is already full.
-
-   FPUCW[15:0] is the FPU's control word.  FPUCW[31:16] is unused.
-
-   FC3210 contains the C3, C2, C1 and C0 bits in the same place they
-   are in the FPU's status word.  (bits 14, 10, 9, 8 respectively).
-   All other bits should be zero.  The relevant mask to select just
-   those bits is 0x4700.  To select C3, C2 and C0 only, the mask is
-   0x4500.
-*/
-#define OFFB_FTOP    (13*4)
-#define OFFB_F0      (14*4)
-#define OFFB_F1      (16*4)
-#define OFFB_F2      (18*4)
-#define OFFB_F3      (20*4)
-#define OFFB_F4      (22*4)
-#define OFFB_F5      (24*4)
-#define OFFB_F6      (26*4)
-#define OFFB_F7      (28*4)
-#define OFFB_FTAG0   (30*4) // up to 30*4 + 7
-#define OFFB_FPUCW   (32*4)
-#define OFFB_FC3210  (33*4)
-
-/* Don't forget to keep this up to date. */
-#define SIZEOF_X86H_STATE  (OFFB_FC3210 + 4)
-
-
-
 #endif /* ndef __LIBVEX_X86GUEST_DEFS_H */
 
 /*---------------------------------------------------------------*/
index 13b5cec428dc962c3aec928bd7458b77bb44148f..ecc12226bae6b56250ec2eec38f18952ced299d2 100644 (file)
@@ -1218,12 +1218,13 @@ typedef
 
 
 /* VISIBLE TO LIBVEX CLIENT */
-void x87_to_vex ( /*IN*/UChar* x87_state, /*OUT*/UChar* vex_state )
+void x87_to_vex ( /*IN*/UChar* x87_state,
+                  /*OUT*/VexGuestX86State* vex_state )
 {
    Int        r;
    UInt       tag;
-   Double*    vexRegs = (Double*)(vex_state + OFFB_F0);
-   UChar*     vexTags = (UChar*)(vex_state + OFFB_FTAG0);
+   Double*    vexRegs = (Double*)(&vex_state->guest_FPREG[0]);
+   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
    Fpu_State* x87     = (Fpu_State*)x87_state;
    UInt       ftop    = (x87->env[FP_ENV_STAT] >> 11) & 7;
    UInt       tagw    = x87->env[FP_ENV_TAG];
@@ -1245,32 +1246,33 @@ void x87_to_vex ( /*IN*/UChar* x87_state, /*OUT*/UChar* vex_state )
    }
 
    /* stack pointer */
-   *(UInt*)(vex_state + OFFB_FTOP) = ftop;
+   vex_state->guest_FTOP = ftop;
 
    /* control word */
-   *(UInt*)(vex_state + OFFB_FPUCW) = fpucw;
+   vex_state->guest_FPUCW = fpucw;
 
    /* status word */
-   *(UInt*)(vex_state + OFFB_FC3210) = c3210;
+   vex_state->guest_FC3210 = c3210;
 }
 
 
 /* VISIBLE TO LIBVEX CLIENT */
-void vex_to_x87 ( /*IN*/UChar* vex_state, /*OUT*/UChar* x87_state )
+void vex_to_x87 ( /*IN*/VexGuestX86State* vex_state,
+                  /*OUT*/UChar* x87_state )
 {
    Int        i, r;
    UInt       tagw;
-   Double*    vexRegs = (Double*)(vex_state + OFFB_F0);
-   UChar*     vexTags = (UChar*)(vex_state + OFFB_FTAG0);
+   Double*    vexRegs = (Double*)(&vex_state->guest_FPREG[0]);
+   UChar*     vexTags = (UChar*)(&vex_state->guest_FPTAG[0]);
    Fpu_State* x87     = (Fpu_State*)x87_state;
-   UInt       ftop    = *(UInt*)(vex_state + OFFB_FTOP);
-   UInt       c3210   = *(UInt*)(vex_state + OFFB_FC3210);
+   UInt       ftop    = vex_state->guest_FTOP;
+   UInt       c3210   = vex_state->guest_FC3210;
 
    for (i = 0; i < 14; i++)
       x87->env[i] = 0;
 
    x87->env[1] = x87->env[3] = x87->env[5] = x87->env[13] = 0xFFFF;
-   x87->env[FP_ENV_CTRL] = (UShort)( *(UInt*)(vex_state + OFFB_FPUCW) );
+   x87->env[FP_ENV_CTRL] = (UShort)( vex_state->guest_FPUCW );
    x87->env[FP_ENV_STAT] = ((ftop & 7) << 11) | (c3210 & 0x4700);
 
    tagw = 0;
@@ -1289,6 +1291,42 @@ void vex_to_x87 ( /*IN*/UChar* vex_state, /*OUT*/UChar* x87_state )
 }
 
 
+/* VISIBLE TO LIBVEX CLIENT */
+void eflags_to_vex ( UInt eflags_native,
+                     /*OUT*/VexGuestX86State* vex_state )
+{
+   vex_state->guest_DFLAG
+      = (eflags_native & (1<<10)) ? 0xFFFFFFFF : 0x00000001;
+
+   /* Mask out everything except O S Z A C P. */
+   eflags_native
+      &= (CC_MASK_C | CC_MASK_P | CC_MASK_A 
+          | CC_MASK_Z | CC_MASK_S | CC_MASK_O);
+
+   vex_state->guest_CC_OP  = CC_OP_COPY;
+   vex_state->guest_CC_DST = 0;
+   vex_state->guest_CC_DST = eflags_native;
+}
+
+
+/* VISIBLE TO LIBVEX CLIENT */
+UInt vex_to_eflags ( /*IN*/VexGuestX86State* vex_state )
+{
+   UInt eflags = calculate_eflags_all(
+                    vex_state->guest_CC_OP,
+                    vex_state->guest_CC_SRC,
+                    vex_state->guest_CC_DST
+                 );
+   UInt dflag = vex_state->guest_DFLAG;
+   vassert(dflag == 1 || dflag == 0xFFFFFFFF);
+   if (dflag == 0xFFFFFFFF)
+      eflags |= (1<<10);
+                                            
+   return eflags;
+}
+
+
+
 /*---------------------------------------------------------------*/
 /*--- end                                guest-x86/ghelpers.c ---*/
 /*---------------------------------------------------------------*/
index 310f30f9b915aecd7361ae598a98ace5bd92e1a4..5b2773d3b444975258438c267b89696e695eb31b 100644 (file)
@@ -27,6 +27,7 @@
 #include "libvex_basictypes.h"
 #include "libvex_ir.h"
 #include "libvex.h"
+#include "libvex_guest_x86.h"
 
 #include "main/vex_util.h"
 #include "main/vex_globals.h"
@@ -198,6 +199,24 @@ IRBB* bbToIR_X86Instr ( UChar* x86code,
 }
 
 
+/*------------------------------------------------------------*/
+/*--- Offsets of various parts of the x86 guest state.     ---*/
+/*------------------------------------------------------------*/
+
+#define offsetof(type,memb) ((Int)&((type*)0)->memb)
+
+#define OFFB_FPREGS  offsetof(VexGuestX86State,guest_FPREG[0])
+#define OFFB_FPTAGS  offsetof(VexGuestX86State,guest_FPTAG[0])
+#define OFFB_EAX     offsetof(VexGuestX86State,guest_EAX)
+#define OFFB_CC_OP   offsetof(VexGuestX86State,guest_CC_OP)
+#define OFFB_CC_SRC  offsetof(VexGuestX86State,guest_CC_SRC)
+#define OFFB_CC_DST  offsetof(VexGuestX86State,guest_CC_DST)
+#define OFFB_DFLAG   offsetof(VexGuestX86State,guest_DFLAG)
+#define OFFB_FTOP    offsetof(VexGuestX86State,guest_FTOP)
+#define OFFB_FC3210  offsetof(VexGuestX86State,guest_FC3210)
+#define OFFB_FPUCW   offsetof(VexGuestX86State,guest_FPUCW)
+
+
 /*------------------------------------------------------------*/
 /*--- Helper bits and pieces for deconstructing the        ---*/
 /*--- x86 insn stream.                                     ---*/
@@ -3217,7 +3236,7 @@ static void put_ST_TAG ( Int i, IRExpr* value )
 {
    IRArray* descr;
    vassert(typeOfIRExpr(irbb->tyenv, value) == Ity_I8);
-   descr = mkIRArray( OFFB_FTAG0, Ity_I8, 8 );
+   descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
    stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
 }
 
@@ -3226,7 +3245,7 @@ static void put_ST_TAG ( Int i, IRExpr* value )
 
 static IRExpr* get_ST_TAG ( Int i )
 {
-   IRArray* descr = mkIRArray( OFFB_FTAG0, Ity_I8, 8 );
+   IRArray* descr = mkIRArray( OFFB_FPTAGS, Ity_I8, 8 );
    return IRExpr_GetI( descr, get_ftop(), i );
 }
 
@@ -3241,7 +3260,7 @@ static void put_ST_UNCHECKED ( Int i, IRExpr* value )
 {
    IRArray* descr;
    vassert(typeOfIRExpr(irbb->tyenv, value) == Ity_F64);
-   descr = mkIRArray( OFFB_F0, Ity_F64, 8 );
+   descr = mkIRArray( OFFB_FPREGS, Ity_F64, 8 );
    stmt( IRStmt_PutI( descr, get_ftop(), i, value ) );
    /* Mark the register as in-use. */
    put_ST_TAG(i, mkU8(1));
@@ -3269,7 +3288,7 @@ static void put_ST ( Int i, IRExpr* value )
 
 static IRExpr* get_ST_UNCHECKED ( Int i )
 {
-   IRArray* descr = mkIRArray( OFFB_F0, Ity_F64, 8 );
+   IRArray* descr = mkIRArray( OFFB_FPREGS, Ity_F64, 8 );
    return IRExpr_GetI( descr, get_ftop(), i );
 }
 
index cf71dc20a64d03e64fc728fe9c00b6184167e09e..efa64331a47617e21c8e6ded4d5ff13e6df3daef 100644 (file)
 
 #include "libvex_basictypes.h"
 
+/*---------------------------------------------------------------*/
+/*--- Vex's representation of the x86 CPU state.              ---*/
+/*---------------------------------------------------------------*/
+
+/* The integer parts should be pretty straightforward. */
+
+/* Hmm, subregisters.  The simulated state is stored in memory in the
+   host's byte ordering, so we can't say here what the offsets of %ax,
+   %al, %ah etc are since that depends on the host's byte ordering,
+   which we don't know. */
+
+/* FPU.  For now, just simulate 8 64-bit registers, their tags, and
+   the reg-stack top pointer, of which only the least significant
+   three bits are relevant.
+
+   The model is:
+     F0 .. F7 are the 8 registers.  FTOP[2:0] contains the 
+     index of the current 'stack top' -- pretty meaningless, but
+     still.  FTOP is a 32-bit value.  FTOP[31:3] can be anything
+     (not guaranteed to be zero).
+
+     When a value is pushed onto the stack, ftop is first replaced by 
+     (ftop-1) & 7, and then F[ftop] is assigned the value.
+
+     When a value is popped off the stack, the value is read from
+     F[ftop], and then ftop is replaced by (ftop+1) & 7.
+
+     In general, a reference to a register ST(i) actually references
+     F[ (ftop+i) & 7 ].
+
+   FTAG0 .. FTAG0+7 are the tags.  Each is a byte, zero means empty,
+   non-zero means non-empty.
+
+   The general rule appears to be that a read or modify of a register
+   gets a stack underflow fault if the register is empty.  A write of
+   a register (only a write, not a modify) gets a stack overflow fault
+   if the register is full.  Note that "over" vs "under" is pretty
+   meaningless since the FP stack pointer can move around arbitrarily,
+   so it's really just two different kinds of exceptions:
+   register-empty and register full.
+
+   Naturally Intel (in its infinite wisdom) has seen fit to throw in
+   some ad-hoc inconsistencies to the fault-generation rules of the
+   above para, just to complicate everything.  Known inconsistencies:
+
+   * fxam can read a register in any state without taking an underflow
+     fault.
+
+   * fst from st(0) to st(i) does not take an overflow fault even if the
+     destination is already full.
+
+   FPUCW[15:0] is the FPU's control word.  FPUCW[31:16] is unused.
+
+   FC3210 contains the C3, C2, C1 and C0 bits in the same place they
+   are in the FPU's status word.  (bits 14, 10, 9, 8 respectively).
+   All other bits should be zero.  The relevant mask to select just
+   those bits is 0x4700.  To select C3, C2 and C0 only, the mask is
+   0x4500.
+*/
+
+typedef
+   struct {
+      UInt  guest_EAX;
+      UInt  guest_ECX;
+      UInt  guest_EDX;
+      UInt  guest_EBX;
+      UInt  guest_ESP;
+      UInt  guest_EBP;
+      UInt  guest_ESI;
+      UInt  guest_EDI;
+      /* 3-word thunk used to calculate O S Z A C P flags. */
+      UInt  guest_CC_OP;
+      UInt  guest_CC_SRC;
+      UInt  guest_CC_DST;
+      /* The D flag is stored here, as either -1 or +1 */
+      UInt  guest_DFLAG;
+      /* EIP */
+      UInt  guest_EIP;
+      /* FPU */
+      UInt  guest_FTOP;
+      ULong guest_FPREG[8];
+      UChar guest_FPTAG[8];
+      UInt  guest_FPUCW;
+      UInt  guest_FC3210;
+   }
+   VexGuestX86State;
+
+
 /*---------------------------------------------------------------*/
 /*--- Utility functions for x86 guest stuff.                  ---*/
 /*---------------------------------------------------------------*/
 
-/* Convert a saved x87 FPU image (as created by fsave) into the
-   equivalent vex representation. 
+/* Convert a saved x87 FPU image (as created by fsave) and write it
+   into the supplied VexGuestX86State structure.  The non-FP parts of
+   said structure are left unchanged.  
 */
-extern void x87_to_vex ( /*IN*/UChar* x87_state, 
-                         /*OUT*/UChar* vex_state );
+extern 
+void x87_to_vex ( /*IN*/UChar* x87_state, 
+                  /*OUT*/VexGuestX86State* vex_state );
+
+/* Extract from the supplied VexGuestX86State structure, an x87 FPU
+   image. */
+extern 
+void vex_to_x87 ( /*IN*/VexGuestX86State* vex_state, 
+                  /*OUT*/UChar* x87_state );
+
+
+/* Given a 32-bit word containing native x86 %eflags values, set the
+   eflag-related fields in the supplied VexGuestX86State accordingly.
+   All other fields are left unchanged.  */
+
+extern
+void eflags_to_vex ( UInt eflags_native,
+                     /*OUT*/VexGuestX86State* vex_state );
+
+/* Extract from the supplied VexGuestX86State structure the
+   corresponding native %eflags value. */
+
+extern 
+UInt vex_to_eflags ( /*IN*/VexGuestX86State* vex_state );
 
-/* Extract from the vex representation, an x87 FPU image. */
-extern void vex_to_x87 ( /*IN*/UChar* vex_state, 
-                         /*OUT*/UChar* x87_state );
 
 #endif /* ndef __LIBVEX_PUB_GUEST_X86_H */