we can get away with.
git-svn-id: svn://svn.valgrind.org/vex/trunk@423
}
}
+/*-----------------------------------------------------------*/
+/*--- Describing the x86 guest state, for the benefit ---*/
+/*--- of iropt and instrumenters. ---*/
+/*-----------------------------------------------------------*/
+
+/* Figure out if any part of the guest state contained in minoff
+ .. maxoff requires precise memory exceptions. If in doubt return
+ True (but this is generates significantly slower code).
+
+ We enforce precise exns for guest %ESP and %EIP only.
+*/
+Bool guest_x86_state_requires_precise_mem_exns ( Int minoff,
+ Int maxoff)
+{
+ Int esp_min = offsetof(VexGuestX86State, guest_ESP);
+ Int esp_max = esp_min + 4 - 1;
+ Int eip_min = offsetof(VexGuestX86State, guest_EIP);
+ Int eip_max = eip_min + 4 - 1;
+
+ if (maxoff < esp_min || minoff > esp_max) {
+ /* no overlap with esp */
+ } else {
+ return True;
+ }
+
+ if (maxoff < eip_min || minoff > eip_max) {
+ /* no overlap with eip */
+ } else {
+ return True;
+ }
+
+ return False;
+}
+
+
/*---------------------------------------------------------------*/
/*--- end guest-x86/ghelpers.c ---*/
/*---------------------------------------------------------------*/
/*--- 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)
overlapping ranges listed in env. Due to the flattening phase, the
only stmt kind we expect to find a Get on is IRStmt_Tmp. */
-static void handle_gets_Stmt ( HashHW* env, IRStmt* st )
+static void handle_gets_Stmt (
+ HashHW* env,
+ IRStmt* st,
+ Bool (*preciseMemExnsFn)(Int,Int)
+ )
{
Int j;
UInt key = 0; /* keep gcc -O happy */
be reordered with respect to memory references. That means
at least the stack pointer. */
for (j = 0; j < env->used; j++) {
-#if 0
- if (env->inuse[j]
- && env->key[j] == (HWord)((16 << 16) | 19)) {
- //vex_printf("found esp assignment\n");
+ if (!env->inuse[j])
+ continue;
+ if (vex_control.iropt_precise_memory_exns) {
+ /* Precise exceptions required. Flush all guest state. */
env->inuse[j] = False;
- }
-#else
- env->inuse[j] = False;
-#endif
+ } else {
+ /* Just flush the minimal amount required, as computed by
+ preciseMemExnsFn. */
+ HWord k_lo = (env->key[j] >> 16) & 0xFFFF;
+ HWord k_hi = env->key[j] & 0xFFFF;
+ if (preciseMemExnsFn( k_lo, k_hi ))
+ env->inuse[j] = False;
+ }
}
- }
+ } /* if (memRW) */
+
}
overlapping (minoff,maxoff).
*/
-static void redundant_put_removal_BB ( IRBB* bb )
+static void redundant_put_removal_BB (
+ IRBB* bb,
+ Bool (*preciseMemExnsFn)(Int,Int)
+ )
{
Int i, j;
Bool isPut;
/* Deal with Gets. These remove bits of the environment since
appearance of a Get means that the next event for that slice
of the guest state is no longer a write, but a read. */
- handle_gets_Stmt( env, st );
+ handle_gets_Stmt( env, st, preciseMemExnsFn );
}
}
static
IRBB* cheap_transformations (
IRBB* bb,
- IRExpr* (*specHelper) ( Char*, IRExpr**) )
+ IRExpr* (*specHelper) ( Char*, IRExpr**),
+ Bool (*preciseMemExnsFn)(Int,Int)
+ )
{
redundant_get_removal_BB ( bb );
if (iropt_verbose) {
ppIRBB(bb);
}
- redundant_put_removal_BB ( bb );
+ redundant_put_removal_BB ( bb, preciseMemExnsFn );
if (iropt_verbose) {
vex_printf("\n========= REDUNDANT PUT\n\n" );
ppIRBB(bb);
IRBB* do_iropt_BB ( IRBB* bb0,
IRExpr* (*specHelper) ( Char*, IRExpr**),
+ Bool (*preciseMemExnsFn)(Int,Int),
Addr64 guest_addr )
{
static UInt n_total = 0;
If needed, do expensive transformations and then another cheap
cleanup pass. */
- bb = cheap_transformations( bb, specHelper );
+ bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
if (vex_control.iropt_level > 1) {
do_expensive = hasGetIorPutI(bb);
if (DEBUG_IROPT)
vex_printf("***** EXPENSIVE %d %d\n", n_total, n_expensive);
bb = expensive_transformations( bb );
- bb = cheap_transformations( bb, specHelper );
+ bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
}
/* Now have a go at unrolling simple (single-BB) loops. If
bb2 = maybe_loop_unroll_BB( bb, guest_addr );
if (bb2) {
show_res = False; //True;
- bb = cheap_transformations( bb2, specHelper );
+ bb = cheap_transformations( bb2, specHelper, preciseMemExnsFn );
if (do_expensive) {
bb = expensive_transformations( bb );
- bb = cheap_transformations( bb, specHelper );
+ bb = cheap_transformations( bb, specHelper, preciseMemExnsFn );
} else {
/* at least do CSE and dead code removal */
cse_BB( bb );
extern IRBB* do_iropt_BB ( IRBB* bb,
IRExpr* (*specHelper) ( Char*, IRExpr**),
+ Bool (*preciseMemExnsFn)(Int,Int),
Addr64 guest_addr );
/*---------------------------------------------------------------*/
/*---------------------------------------------------------------*/
#include "libvex.h"
+#include "libvex_guest_x86.h"
#include "main/vex_globals.h"
#include "main/vex_util.h"
Int (*emit) ( UChar*, Int, HInstr* );
Addr64 (*findHelper) ( Char* );
IRExpr* (*specHelper) ( Char*, IRExpr** );
+ Bool (*preciseMemExnsFn) ( Int, Int );
Bool host_is_bigendian = False;
IRBB* irbb;
emit = NULL;
findHelper = NULL;
specHelper = NULL;
+ preciseMemExnsFn = NULL;
saved_verbosity = vex_verbosity;
if (bb_verbosity > 0)
switch (iset_guest) {
case InsnSetX86:
- bbToIR = bbToIR_X86Instr;
- findHelper = x86guest_findhelper;
- specHelper = x86guest_spechelper;
+ preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
+ bbToIR = bbToIR_X86Instr;
+ findHelper = x86guest_findhelper;
+ specHelper = x86guest_spechelper;
break;
default:
vpanic("LibVEX_Translate: unsupported guest insn set");
sanityCheckIRBB(irbb, Ity_I32);
/* Clean it up, hopefully a lot. */
- irbb = do_iropt_BB ( irbb, specHelper, guest_bytes_addr );
+ irbb = do_iropt_BB ( irbb, specHelper, preciseMemExnsFn,
+ guest_bytes_addr );
sanityCheckIRBB(irbb, Ity_I32);
if (vex_verbosity > 0) {
typedef unsigned long HWord;
+/* This is so useful it should be visible absolutely everywhere. */
+#define offsetof(type,memb) ((Int)&((type*)0)->memb)
+
+
#endif /* ndef __LIBVEX_BASICTYPES_H */
VexGuestX86State;
+/* This is logically part of the guest state description. */
+/* Not visible to library client. */
+extern Bool guest_x86_state_requires_precise_mem_exns ( Int, Int );
+
+
+
/*---------------------------------------------------------------*/
/*--- Utility functions for x86 guest stuff. ---*/
/*---------------------------------------------------------------*/
+
+
+
+/* ALL THE FOLLOWING ARE VISIBLE TO LIBRARY CLIENT */
+
/* 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.