|
From: <sv...@va...> - 2012-06-01 16:10:04
|
sewardj 2012-06-01 17:09:50 +0100 (Fri, 01 Jun 2012)
New Revision: 2362
Log:
Enhance the guest state effects notation on IRDirty calls, so as to be
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.
Modified files:
trunk/priv/guest_amd64_toIR.c
trunk/priv/guest_ppc_toIR.c
trunk/priv/guest_s390_toIR.c
trunk/priv/guest_x86_toIR.c
trunk/priv/host_s390_isel.c
trunk/priv/ir_defs.c
trunk/priv/main_main.c
trunk/priv/main_util.c
trunk/priv/main_util.h
trunk/pub/libvex_ir.h
Modified: trunk/priv/guest_x86_toIR.c (+10 -2)
===================================================================
--- trunk/priv/guest_x86_toIR.c 2012-05-31 16:46:18 +01:00 (rev 2361)
+++ trunk/priv/guest_x86_toIR.c 2012-06-01 17:09:50 +01:00 (rev 2362)
@@ -3954,6 +3954,7 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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;
Modified: trunk/priv/guest_s390_toIR.c (+6 -2)
===================================================================
--- trunk/priv/guest_s390_toIR.c 2012-05-31 16:46:18 +01:00 (rev 2361)
+++ trunk/priv/guest_s390_toIR.c 2012-06-01 17:09:50 +01:00 (rev 2362)
@@ -2120,10 +2120,12 @@
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 @@
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 */
Modified: trunk/priv/guest_ppc_toIR.c (+2 -0)
===================================================================
--- trunk/priv/guest_ppc_toIR.c 2012-05-31 16:46:18 +01:00 (rev 2361)
+++ trunk/priv/guest_ppc_toIR.c 2012-06-01 17:09:50 +01:00 (rev 2362)
@@ -12801,6 +12801,7 @@
/* 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 @@
/* 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);
Modified: trunk/priv/guest_amd64_toIR.c (+25 -8)
===================================================================
--- trunk/priv/guest_amd64_toIR.c 2012-05-31 16:46:18 +01:00 (rev 2361)
+++ trunk/priv/guest_amd64_toIR.c 2012-06-01 17:09:50 +01:00 (rev 2362)
@@ -5174,6 +5174,7 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
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 @@
/* 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;
Modified: trunk/pub/libvex_ir.h (+22 -5)
===================================================================
--- trunk/pub/libvex_ir.h 2012-05-31 16:46:18 +01:00 (rev 2361)
+++ trunk/pub/libvex_ir.h 2012-06-01 17:09:50 +01:00 (rev 2362)
@@ -1870,7 +1870,7 @@
/* 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 @@
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 @@
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* deepCopyIRPutI ( IRPutI* );
+
/* ------------------ Statements ------------------ */
/* The different kinds of statements. Their meaning is explained
Modified: trunk/priv/main_util.h (+2 -1)
===================================================================
--- trunk/priv/main_util.h 2012-05-31 16:46:18 +01:00 (rev 2361)
+++ trunk/priv/main_util.h 2012-06-01 17:09:50 +01:00 (rev 2362)
@@ -75,7 +75,8 @@
/* 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. */
Modified: trunk/priv/main_util.c (+9 -0)
===================================================================
--- trunk/priv/main_util.c 2012-05-31 16:46:18 +01:00 (rev 2361)
+++ trunk/priv/main_util.c 2012-06-01 17:09:50 +01:00 (rev 2362)
@@ -254,7 +254,16 @@
}
}
+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. */
static
Modified: trunk/priv/host_s390_isel.c (+3 -0)
===================================================================
--- trunk/priv/host_s390_isel.c 2012-05-31 16:46:18 +01:00 (rev 2361)
+++ trunk/priv/host_s390_isel.c 2012-06-01 17:09:50 +01:00 (rev 2362)
@@ -2419,6 +2419,9 @@
/* 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)
Modified: trunk/priv/ir_defs.c (+16 -1)
===================================================================
--- trunk/priv/ir_defs.c 2012-05-31 16:46:18 +01:00 (rev 2361)
+++ trunk/priv/ir_defs.c 2012-06-01 17:09:50 +01:00 (rev 2362)
@@ -1120,7 +1120,13 @@
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 @@
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;
Modified: trunk/priv/main_main.c (+1 -0)
===================================================================
--- trunk/priv/main_main.c 2012-05-31 16:46:18 +01:00 (rev 2361)
+++ trunk/priv/main_main.c 2012-06-01 17:09:50 +01:00 (rev 2362)
@@ -147,6 +147,7 @@
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*));
|