]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Enhance the guest state effects notation on IRDirty calls, so as to be
authorJulian Seward <jseward@acm.org>
Fri, 1 Jun 2012 16:09:50 +0000 (16:09 +0000)
committerJulian Seward <jseward@acm.org>
Fri, 1 Jun 2012 16:09:50 +0000 (16:09 +0000)
able to describe accesses to arrays of non-consecutive guest state
sections.  This is needed to describe the behaviour of FXSAVE and
FXRSTOR in an environment where we also support AVX.

The IRDirty struct has got smaller (112 bytes vs 136 before, for a 64
bit target) whilst holding more information.

The new facility is then used to describe said FXSAVE and FXRSTOR on
amd64.  For x86 there is no change since we don't model AVX state for
x86.

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

VEX/priv/guest_amd64_toIR.c
VEX/priv/guest_ppc_toIR.c
VEX/priv/guest_s390_toIR.c
VEX/priv/guest_x86_toIR.c
VEX/priv/host_s390_isel.c
VEX/priv/ir_defs.c
VEX/priv/main_main.c
VEX/priv/main_util.c
VEX/priv/main_util.h
VEX/pub/libvex_ir.h

index 1896b9cfa5ebcd38972f1abc1f1ef2fa3d2259a4..68760684b346ed461e7787c5d8ac27be512ea729 100644 (file)
@@ -5174,6 +5174,7 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
 
                /* declare we're writing guest state */
                d->nFxState = 4;
+               vex_bzero(&d->fxState, sizeof(d->fxState));
 
                d->fxState[0].fx     = Ifx_Write;
                d->fxState[0].offset = OFFB_FTOP;
@@ -5270,6 +5271,7 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
 
                /* declare we're reading guest state */
                d->nFxState = 4;
+               vex_bzero(&d->fxState, sizeof(d->fxState));
 
                d->fxState[0].fx     = Ifx_Read;
                d->fxState[0].offset = OFFB_FTOP;
@@ -5927,6 +5929,7 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
 
                /* declare we're writing guest state */
                d->nFxState = 5;
+               vex_bzero(&d->fxState, sizeof(d->fxState));
 
                d->fxState[0].fx     = Ifx_Write;
                d->fxState[0].offset = OFFB_FTOP;
@@ -6150,6 +6153,7 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
 
                /* declare we're writing guest state */
                d->nFxState = 5;
+               vex_bzero(&d->fxState, sizeof(d->fxState));
 
                d->fxState[0].fx     = Ifx_Write;
                d->fxState[0].offset = OFFB_FTOP;
@@ -6227,6 +6231,7 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
 
                /* declare we're reading guest state */
                d->nFxState = 5;
+               vex_bzero(&d->fxState, sizeof(d->fxState));
 
                d->fxState[0].fx     = Ifx_Read;
                d->fxState[0].offset = OFFB_FTOP;
@@ -11850,10 +11855,11 @@ Long dis_ESC_0F__SSE2 ( Bool* decode_OK,
          /* declare we're writing memory */
          d->mFx   = Ifx_Write;
          d->mAddr = mkexpr(addr);
-         d->mSize = 512;
+         d->mSize = 464; /* according to recent Intel docs */
 
          /* declare we're reading guest state */
          d->nFxState = 7;
+         vex_bzero(&d->fxState, sizeof(d->fxState));
 
          d->fxState[0].fx     = Ifx_Read;
          d->fxState[0].offset = OFFB_FTOP;
@@ -11877,15 +11883,18 @@ Long dis_ESC_0F__SSE2 ( Bool* decode_OK,
 
          d->fxState[5].fx     = Ifx_Read;
          d->fxState[5].offset = OFFB_YMM0;
-         d->fxState[5].size   = 16 * sizeof(U128);
+         d->fxState[5].size   = sizeof(U128);
+         /* plus 15 more of the above, spaced out in YMM sized steps */
+         d->fxState[5].nRepeats  = 15; 
+         d->fxState[5].repeatLen = sizeof(U256);
 
          d->fxState[6].fx     = Ifx_Read;
          d->fxState[6].offset = OFFB_SSEROUND;
          d->fxState[6].size   = sizeof(ULong);
 
          /* Be paranoid ... this assertion tries to ensure the 16 %ymm
-        images are packed back-to-back.  If not, the value of
-        d->fxState[5].size is wrong. */
+            images are packed back-to-back.  If not, the settings for
+            d->fxState[5] are wrong. */
          vassert(32 == sizeof(U256));
          vassert(OFFB_YMM15 == (OFFB_YMM0 + 15 * 32));
 
@@ -11925,10 +11934,11 @@ Long dis_ESC_0F__SSE2 ( Bool* decode_OK,
          /* declare we're reading memory */
          d->mFx   = Ifx_Read;
          d->mAddr = mkexpr(addr);
-         d->mSize = 512;
+         d->mSize = 464; /* according to recent Intel docs */
 
          /* declare we're writing guest state */
          d->nFxState = 7;
+         vex_bzero(&d->fxState, sizeof(d->fxState));
 
          d->fxState[0].fx     = Ifx_Write;
          d->fxState[0].offset = OFFB_FTOP;
@@ -11952,15 +11962,18 @@ Long dis_ESC_0F__SSE2 ( Bool* decode_OK,
 
          d->fxState[5].fx     = Ifx_Write;
          d->fxState[5].offset = OFFB_YMM0;
-         d->fxState[5].size   = 16 * sizeof(U128);
+         d->fxState[5].size   = sizeof(U128);
+         /* plus 15 more of the above, spaced out in YMM sized steps */
+         d->fxState[5].nRepeats  = 15; 
+         d->fxState[5].repeatLen = sizeof(U256);
 
          d->fxState[6].fx     = Ifx_Write;
          d->fxState[6].offset = OFFB_SSEROUND;
          d->fxState[6].size   = sizeof(ULong);
 
          /* Be paranoid ... this assertion tries to ensure the 16 %ymm
-        images are packed back-to-back.  If not, the value of
-        d->fxState[5].size is wrong. */
+            images are packed back-to-back.  If not, the settings for
+            d->fxState[5] are wrong. */
          vassert(32 == sizeof(U256));
          vassert(OFFB_YMM15 == (OFFB_YMM0 + 15 * 32));
 
@@ -15399,6 +15412,7 @@ Long dis_ESC_0F38__SSE4 ( Bool* decode_OK,
             this roundabout scheme. */
          d->needsBBP = True;
          d->nFxState = 2;
+         vex_bzero(&d->fxState, sizeof(d->fxState));
          /* AES{ENC,ENCLAST,DEC,DECLAST} read both registers, and writes
             the second.
             AESIMC (0xDB) reads the first register, and writes the second. */
@@ -15644,6 +15658,7 @@ static Long dis_PCMPxSTRx ( VexAbiInfo* vbi, Prefix pfx,
       roundabout scheme. */
    d->needsBBP = True;
    d->nFxState = 2;
+   vex_bzero(&d->fxState, sizeof(d->fxState));
    d->fxState[0].fx     = Ifx_Read;
    d->fxState[0].offset = gstOffL;
    d->fxState[0].size   = sizeof(U128);
@@ -16826,6 +16841,7 @@ Long dis_ESC_0F3A__SSE4 ( Bool* decode_OK,
             this roundabout scheme. */
          d->needsBBP = True;
          d->nFxState = 2;
+         vex_bzero(&d->fxState, sizeof(d->fxState));
          d->fxState[0].fx     = Ifx_Read;
          d->fxState[0].offset = gstOffL;
          d->fxState[0].size   = sizeof(U128);
@@ -18656,6 +18672,7 @@ Long dis_ESC_0F (
       /* declare guest state effects */
       d->needsBBP = True;
       d->nFxState = 4;
+      vex_bzero(&d->fxState, sizeof(d->fxState));
       d->fxState[0].fx     = Ifx_Modify;
       d->fxState[0].offset = OFFB_RAX;
       d->fxState[0].size   = 8;
index d4ee47d85bae5942e25ca0be304439f99cd684d0..54a2c4d39df3553518eb9d772183d7fa3905d6d1 100644 (file)
@@ -12801,6 +12801,7 @@ static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr )
       /* declare guest state effects */
       d->needsBBP = True;
       d->nFxState = 1;
+      vex_bzero(&d->fxState, sizeof(d->fxState));
       d->fxState[0].fx     = Ifx_Write;
       d->fxState[0].offset = vD_off;
       d->fxState[0].size   = sizeof(U128);
@@ -12834,6 +12835,7 @@ static Bool dis_av_load ( VexAbiInfo* vbi, UInt theInstr )
       /* declare guest state effects */
       d->needsBBP = True;
       d->nFxState = 1;
+      vex_bzero(&d->fxState, sizeof(d->fxState));
       d->fxState[0].fx     = Ifx_Write;
       d->fxState[0].offset = vD_off;
       d->fxState[0].size   = sizeof(U128);
index 4cc4a159d44ddd41b0953d7f5c8bedc994814ff4..17d31b3ad280494a7fea64a03e7976070a29b2d9 100644 (file)
@@ -2120,10 +2120,12 @@ s390_irgen_00(UChar r1 __attribute__((unused)),
                           mkIRExprVec_0());
    d->needsBBP = 1;  /* Need to pass pointer to guest state to helper */
 
+   d->nFxState = 1;
+   vex_bzero(&d->fxState, sizeof(d->fxState));
+
    d->fxState[0].fx     = Ifx_Modify;  /* read then write */
    d->fxState[0].offset = S390X_GUEST_OFFSET(guest_IA);
    d->fxState[0].size   = sizeof(ULong);
-   d->nFxState = 1;
 
    stmt(IRStmt_Dirty(d));
 
@@ -10779,10 +10781,12 @@ s390_irgen_STFLE(IRTemp op2addr)
 
    d->needsBBP = 1;  /* Need to pass pointer to guest state to helper */
 
+   d->nFxState = 1;
+   vex_bzero(&d->fxState, sizeof(d->fxState));
+
    d->fxState[0].fx     = Ifx_Modify;  /* read then write */
    d->fxState[0].offset = S390X_GUEST_OFFSET(guest_r0);
    d->fxState[0].size   = sizeof(ULong);
-   d->nFxState = 1;
 
    d->mAddr = mkexpr(op2addr);
    /* Pretend all double words are written */
index 5cbb244ee69a52f8a97a41cfb32978941f13e486..2cbe442f5836973124de900834ab933878459729 100644 (file)
@@ -3954,6 +3954,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
 
                /* declare we're writing guest state */
                d->nFxState = 4;
+               vex_bzero(&d->fxState, sizeof(d->fxState));
 
                d->fxState[0].fx     = Ifx_Write;
                d->fxState[0].offset = OFFB_FTOP;
@@ -4049,6 +4050,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
 
                /* declare we're reading guest state */
                d->nFxState = 4;
+               vex_bzero(&d->fxState, sizeof(d->fxState));
 
                d->fxState[0].fx     = Ifx_Read;
                d->fxState[0].offset = OFFB_FTOP;
@@ -4738,6 +4740,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
 
                /* declare we're writing guest state */
                d->nFxState = 5;
+               vex_bzero(&d->fxState, sizeof(d->fxState));
 
                d->fxState[0].fx     = Ifx_Write;
                d->fxState[0].offset = OFFB_FTOP;
@@ -4942,6 +4945,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
 
                /* declare we're writing guest state */
                d->nFxState = 5;
+               vex_bzero(&d->fxState, sizeof(d->fxState));
 
                d->fxState[0].fx     = Ifx_Write;
                d->fxState[0].offset = OFFB_FTOP;
@@ -5000,6 +5004,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, Int delta )
 
                /* declare we're reading guest state */
                d->nFxState = 5;
+               vex_bzero(&d->fxState, sizeof(d->fxState));
 
                d->fxState[0].fx     = Ifx_Read;
                d->fxState[0].offset = OFFB_FTOP;
@@ -8138,10 +8143,11 @@ DisResult disInstr_X86_WRK (
       /* declare we're writing memory */
       d->mFx   = Ifx_Write;
       d->mAddr = mkexpr(addr);
-      d->mSize = 512;
+      d->mSize = 464; /* according to recent Intel docs */
 
       /* declare we're reading guest state */
       d->nFxState = 7;
+      vex_bzero(&d->fxState, sizeof(d->fxState));
 
       d->fxState[0].fx     = Ifx_Read;
       d->fxState[0].offset = OFFB_FTOP;
@@ -8212,10 +8218,11 @@ DisResult disInstr_X86_WRK (
       /* declare we're reading memory */
       d->mFx   = Ifx_Read;
       d->mAddr = mkexpr(addr);
-      d->mSize = 512;
+      d->mSize = 464; /* according to recent Intel docs */
 
       /* declare we're writing guest state */
       d->nFxState = 7;
+      vex_bzero(&d->fxState, sizeof(d->fxState));
 
       d->fxState[0].fx     = Ifx_Write;
       d->fxState[0].offset = OFFB_FTOP;
@@ -14608,6 +14615,7 @@ DisResult disInstr_X86_WRK (
          /* declare guest state effects */
          d->needsBBP = True;
          d->nFxState = 4;
+         vex_bzero(&d->fxState, sizeof(d->fxState));
          d->fxState[0].fx     = Ifx_Modify;
          d->fxState[0].offset = OFFB_EAX;
          d->fxState[0].size   = 4;
index 76173d24055f08384a09c367de8ff733a543c0d0..a4696328c66530439dd47bf55a1db3012cd90df8 100644 (file)
@@ -2419,6 +2419,9 @@ s390_isel_stmt(ISelEnv *env, IRStmt *stmt)
       /* Invalidate tracked values of those guest state registers that are
          modified by this helper. */
       for (i = 0; i < d->nFxState; ++i) {
+         /* JRS 1 June 2012: AFAICS, s390 guest doesn't use 'repeat'
+            descriptors in guest state effect descriptions.  Hence: */
+         vassert(d->fxState[i].nRepeats == 0 && d->fxState[i].repeatLen == 0);
          if ((d->fxState[i].fx == Ifx_Write || d->fxState[i].fx == Ifx_Modify)) {
             Int guest_reg = get_guest_reg(d->fxState[i].offset);
             if (guest_reg != GUEST_UNKNOWN)
index 502fc20fec9b6befb0ce9abef330c53af3c2552a..8571bdff166162c3d8f21e514e9144ecf40633da 100644 (file)
@@ -1120,7 +1120,13 @@ void ppIRDirty ( IRDirty* d )
    for (i = 0; i < d->nFxState; i++) {
       vex_printf(" ");
       ppIREffect(d->fxState[i].fx);
-      vex_printf("-gst(%d,%d)", d->fxState[i].offset, d->fxState[i].size);
+      vex_printf("-gst(%u,%u", (UInt)d->fxState[i].offset,
+                               (UInt)d->fxState[i].size);
+      if (d->fxState[i].nRepeats > 0) {
+         vex_printf(",reps%u,step%u", (UInt)d->fxState[i].nRepeats,
+                                      (UInt)d->fxState[i].repeatLen);
+      }
+      vex_printf(")");
    }
    vex_printf(" ::: ");
    ppIRCallee(d->cee);
@@ -3567,6 +3573,15 @@ void tcStmt ( IRSB* bb, IRStmt* stmt, IRType gWordTy )
          for (i = 0; i < d->nFxState; i++) {
             if (d->fxState[i].fx == Ifx_None) goto bad_dirty;
             if (d->fxState[i].size <= 0) goto bad_dirty;
+            if (d->fxState[i].nRepeats == 0) {
+               if (d->fxState[i].repeatLen != 0) goto bad_dirty;
+            } else {
+               if (d->fxState[i].repeatLen <= d->fxState[i].size)
+                  goto bad_dirty;
+               /* the % is safe because of the .size check above */
+               if ((d->fxState[i].repeatLen % d->fxState[i].size) != 0)
+                  goto bad_dirty;
+            }
          }
          /* check types, minimally */
          if (d->guard == NULL) goto bad_dirty;
index a65867d9821df1150a2349ffe3ab6566f3734cfa..b3ab987b03d183553d037102a78773884c19a4d4 100644 (file)
@@ -147,6 +147,7 @@ void LibVEX_Init (
    vassert(8 == sizeof(Addr64));
    vassert(16 == sizeof(U128));
    vassert(16 == sizeof(V128));
+   vassert(32 == sizeof(U256));
 
    vassert(sizeof(void*) == 4 || sizeof(void*) == 8);
    vassert(sizeof(void*) == sizeof(int*));
index 618254b69a2ddd01e1379d845f0001a9d914bd3d..7630d02513ed9a7f3a5a0bd42b77c5b2e18c0aac 100644 (file)
@@ -254,6 +254,15 @@ Bool vex_streq ( const HChar* s1, const HChar* s2 )
    }
 }
 
+void vex_bzero ( void* sV, UInt n )
+{
+   UInt i;
+   UChar* s = (UChar*)sV;
+   /* No laughing, please.  Just don't call this too often.  Thank you
+      for your attention. */
+   for (i = 0; i < n; i++) s[i] = 0;
+}
+
 
 /* Convert N0 into ascii in BUF, which is assumed to be big enough (at
    least 67 bytes long).  Observe BASE, SYNED and HEXCAPS. */
index 914dc64efb091e6d09ce935cdbe0221d6e985c08..6a2e6daf8d01c80b4392392d3fd4e1fafcfa151b 100644 (file)
@@ -75,7 +75,8 @@ extern UInt vex_sprintf ( HChar* buf, HChar *format, ... );
 /* String ops */
 
 extern Bool vex_streq ( const HChar* s1, const HChar* s2 );
-extern Int vex_strlen ( const HChar* str );
+extern Int  vex_strlen ( const HChar* str );
+extern void vex_bzero ( void* s, UInt n );
 
 
 /* Storage management: clear the area, and allocate from it. */
index ed5961732a36ea8cf34587806beb9ff6db7a8c3a..f88a094a96d0d69175310f0031b6bda9745fca91 100644 (file)
@@ -1870,7 +1870,7 @@ extern void ppIRJumpKind ( IRJumpKind );
 /* Effects on resources (eg. registers, memory locations) */
 typedef
    enum {
-      Ifx_None = 0x17000,   /* no effect */
+      Ifx_None = 0x1700   /* no effect */
       Ifx_Read,             /* reads the resource */
       Ifx_Write,            /* writes the resource */
       Ifx_Modify,           /* modifies the resource */
@@ -1882,7 +1882,7 @@ extern void ppIREffect ( IREffect );
 
 
 typedef
-   struct {
+   struct _IRDirty {
       /* What to call, and details of args/results */
       IRCallee* cee;    /* where to call */
       IRExpr*   guard;  /* :: Ity_Bit.  Controls whether call happens */
@@ -1898,10 +1898,26 @@ typedef
       Bool needsBBP; /* True => also pass guest state ptr to callee */
       Int  nFxState; /* must be 0 .. VEX_N_FXSTATE */
       struct {
-         IREffect fx;   /* read, write or modify?  Ifx_None is invalid. */
-         Int      offset;
-         Int      size;
+         IREffect fx:16;   /* read, write or modify?  Ifx_None is invalid. */
+         UShort   offset;
+         UShort   size;
+         UChar    nRepeats;
+         UChar    repeatLen;
       } fxState[VEX_N_FXSTATE];
+      /* The access can be repeated, as specified by nRepeats and
+         repeatLen.  To describe only a single access, nRepeats and
+         repeatLen should be zero.  Otherwise, repeatLen must be a
+         multiple of size and greater than size. */
+      /* Overall, the parts of the guest state denoted by (offset,
+         size, nRepeats, repeatLen) is
+               [offset, +size)
+            and, if nRepeats > 0,
+               for (i = 1; i <= nRepeats; i++)
+                  [offset + i * repeatLen, +size)
+         A convenient way to enumerate all segments is therefore
+            for (i = 0; i < 1 + nRepeats; i++)
+               [offset + i * repeatLen, +size)
+      */
    }
    IRDirty;
 
@@ -2051,6 +2067,7 @@ extern IRPutI* mkIRPutI ( IRRegArray* descr, IRExpr* ix,
 
 extern IRPutI* deepCopyIRPutI ( IRPutI* );
 
+
 /* ------------------ Statements ------------------ */
 
 /* The different kinds of statements.  Their meaning is explained