If we are doing cache simulation, refuse to start at all if the minimum
cache line size is smaller than the maximum guest register size.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12606 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/callgrind/global.h b/callgrind/global.h
index 63f6e10..b10165d 100644
--- a/callgrind/global.h
+++ b/callgrind/global.h
@@ -827,6 +827,8 @@
 /* Function active counter array, indexed by function number */
 extern UInt* CLG_(fn_active_array);
 extern Bool CLG_(instrument_state);
+ /* min of L1 and LL cache line sizes */
+extern Int CLG_(min_line_size);
 
 extern call_stack CLG_(current_call_stack);
 extern fn_stack   CLG_(current_fn_stack);
diff --git a/callgrind/main.c b/callgrind/main.c
index 62ca8c9..66af64b 100644
--- a/callgrind/main.c
+++ b/callgrind/main.c
@@ -52,6 +52,10 @@
 /* thread and signal handler specific */
 exec_state CLG_(current_state);
 
+/* min of L1 and LL cache line sizes.  This only gets set to a
+   non-zero value if we are doing cache simulation. */
+Int CLG_(min_line_size) = 0;
+
 
 /*------------------------------------------------------------*/
 /*--- Statistics                                           ---*/
@@ -613,8 +617,9 @@
 {
    Event* evt;
    tl_assert(isIRAtom(ea));
-   tl_assert(datasize >= 1 && datasize <= MIN_LINE_SIZE);
+   tl_assert(datasize >= 1);
    if (!CLG_(clo).simulate_cache) return;
+   tl_assert(datasize <= CLG_(min_line_size));
 
    if (clgs->events_used == N_EVENTS)
       flushEvents(clgs);
@@ -634,8 +639,9 @@
    Event* lastEvt;
    Event* evt;
    tl_assert(isIRAtom(ea));
-   tl_assert(datasize >= 1 && datasize <= MIN_LINE_SIZE);
+   tl_assert(datasize >= 1);
    if (!CLG_(clo).simulate_cache) return;
+   tl_assert(datasize <= CLG_(min_line_size));
 
    /* Is it possible to merge this write with the preceding read? */
    lastEvt = &clgs->events[clgs->events_used-1];
@@ -1027,8 +1033,8 @@
 	       // instructions will be done inaccurately, but they're
 	       // very rare and this avoids errors from hitting more
 	       // than two cache lines in the simulation.
-	       if (dataSize > MIN_LINE_SIZE)
-		  dataSize = MIN_LINE_SIZE;
+	       if (CLG_(clo).simulate_cache && dataSize > CLG_(min_line_size))
+		  dataSize = CLG_(min_line_size);
 	       if (d->mFx == Ifx_Read || d->mFx == Ifx_Modify)
 		  addEvent_Dr( &clgs, curr_inode, dataSize, d->mAddr );
 	       if (d->mFx == Ifx_Write || d->mFx == Ifx_Modify)
diff --git a/callgrind/sim.c b/callgrind/sim.c
index c1deff7..8703c60 100644
--- a/callgrind/sim.c
+++ b/callgrind/sim.c
@@ -1307,6 +1307,28 @@
   D1.name = "D1";
   LL.name = "LL";
 
+  // min_line_size is used to make sure that we never feed
+  // accesses to the simulator straddling more than two
+  // cache lines at any cache level
+  CLG_(min_line_size) = (I1c.line_size < D1c.line_size)
+                           ? I1c.line_size : D1c.line_size;
+  CLG_(min_line_size) = (LLc.line_size < CLG_(min_line_size))
+                           ? LLc.line_size : CLG_(min_line_size);
+
+  Int largest_load_or_store_size
+     = VG_(machine_get_size_of_largest_guest_register)();
+  if (CLG_(min_line_size) < largest_load_or_store_size) {
+     /* We can't continue, because the cache simulation might
+        straddle more than 2 lines, and it will assert.  So let's
+        just stop before we start. */
+     VG_(umsg)("Callgrind: cannot continue: the minimum line size (%d)\n",
+               (Int)CLG_(min_line_size));
+     VG_(umsg)("  must be equal to or larger than the maximum register size (%d)\n",
+               largest_load_or_store_size );
+     VG_(umsg)("  but it is not.  Exiting now.\n");
+     VG_(exit)(1);
+  }
+
   cachesim_initcache(I1c, &I1);
   cachesim_initcache(D1c, &D1);
   cachesim_initcache(LLc, &LL);