]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
This commit introduces two new UInstructions: CCALL_1_0, CCALL_2_0.
authorNicholas Nethercote <njn@valgrind.org>
Sun, 28 Jul 2002 09:53:34 +0000 (09:53 +0000)
committerNicholas Nethercote <njn@valgrind.org>
Sun, 28 Jul 2002 09:53:34 +0000 (09:53 +0000)
These are the first of a generic family for calling C functions.  CCALL_M_N
calls a function with M word-sized arguments and N word-sized return values
(N == 0 or 1, of course).  All stack management is done automatically --
register saving, argument pushing, register restoring.  Rough timings show it's
marginally faster (~3%), probably because the instrumentation phase is slightly
simpler and translations are slighly more compact.

It was introduced because the way Cachegrind was calling its helper functions
was not really legitimate -- it involved pushing RealRegs at a point where
RealRegs shouldn't have been used.  This flukily worked for Cachegrind, but
caused obscure seg faults when I tried using the same technique for the DIDUCE
stuff.  Hence this more general approach.

CCALL_M_N where M+N <= 3 are easy.  More args might be done by abusing spare
fields in the UInstr struct, if really necessary.  But it's not, yet.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@546

cachegrind/cg_main.c
cachegrind/cg_sim_gen.c
coregrind/vg_from_ucode.c
coregrind/vg_include.h
coregrind/vg_translate.c
vg_cachesim.c
vg_cachesim_gen.c
vg_from_ucode.c
vg_include.h
vg_translate.c

index 4f1bf10716b96a50ff2b49ed1a9d351c87f15b94..05f4186f7b45eb744a5ed9b01842e144961759d3 100644 (file)
@@ -594,11 +594,6 @@ UCodeBlock* VG_(cachesim_instrument)(UCodeBlock* cb_in, Addr orig_addr)
             vg_assert(instr_size >= 1 && instr_size <= MAX_x86_INSTR_SIZE);
             vg_assert(0 != instr_addr);
 
-            /* Save the caller-save registers before we push our args */
-            uInstr1(cb, PUSH, 4, RealReg, R_EAX);
-            uInstr1(cb, PUSH, 4, RealReg, R_ECX);
-            uInstr1(cb, PUSH, 4, RealReg, R_EDX);
-
             if (!IS_(read) && !IS_(write)) {
                iCC* CC_ptr = (iCC*)(BBCC_ptr);
                vg_assert(INVALID_DATA_SIZE == data_size);
@@ -608,7 +603,13 @@ UCodeBlock* VG_(cachesim_instrument)(UCodeBlock* cb_in, Addr orig_addr)
                if (!BB_seen_before)
                    init_iCC(CC_ptr, instr_addr, instr_size);
 
-               helper = VGOFF_(cachesim_log_non_mem_instr);
+               /* 1st arg: CC addr */
+               t_CC_addr = newTemp(cb);
+               uInstr2(cb, MOV,   4, Literal, 0, TempReg, t_CC_addr);
+               uLiteral(cb, BBCC_ptr);
+
+               uInstr1(cb, CCALL_1_0, 0, TempReg, t_CC_addr);
+               uLiteral(cb, VGOFF_(cachesim_log_non_mem_instr));
 
             } else { 
                CC_type X_CC;
@@ -639,31 +640,19 @@ UCodeBlock* VG_(cachesim_instrument)(UCodeBlock* cb_in, Addr orig_addr)
                             INVALID_TEMPREG != t_write_addr);
                   t_data_addr = t_read_addr;
                }
-
+#undef IS_
                if (!BB_seen_before)
                   init_idCC(X_CC, CC_ptr, instr_addr, instr_size, data_size);
 
-               /* 2nd arg: data addr */
-               uInstr1(cb, PUSH,  4, TempReg, t_data_addr);
-               stack_used += 4;
-            }
-#undef IS_
+               /* 1st arg: CC addr */
+               t_CC_addr = newTemp(cb);
+               uInstr2(cb, MOV,   4, Literal, 0, TempReg, t_CC_addr);
+               uLiteral(cb, BBCC_ptr);
 
-            /* 1st arg: CC addr */
-            t_CC_addr = newTemp(cb);
-            uInstr2(cb, MOV,   4, Literal, 0, TempReg, t_CC_addr);
-            uLiteral(cb, BBCC_ptr);
-            uInstr1(cb, PUSH,  4, TempReg, t_CC_addr);
-            stack_used += 4;
-
-            /* Call function and return. */
-            uInstr1(cb, CALLM, 0, Lit16,   helper);
-            uInstr1(cb, CLEAR, 0, Lit16,   stack_used);
-
-            /* Restore the caller-save registers now the call is done */
-            uInstr1(cb, POP, 4, RealReg, R_EDX);
-            uInstr1(cb, POP, 4, RealReg, R_ECX);
-            uInstr1(cb, POP, 4, RealReg, R_EAX);
+               uInstr2(cb, CCALL_2_0, 0, TempReg, t_CC_addr, 
+                                         TempReg, t_data_addr);
+               uLiteral(cb, VGOFF_(cachesim_log_mem_instr));
+            }
 
             VG_(copyUInstr)(cb, u_in);
 
index f938bc4b0fd3497519db75942134bed48174127c..182a03138aa9d83a5a5341f1b2a1aec35d3a5fc0 100644 (file)
@@ -199,6 +199,7 @@ miss_treatment:                                                             \
       if (is_miss) { MISS_TREATMENT; }                                      \
                                                                             \
    } else {                                                                 \
+       VG_(printf)("addr: %x  size: %u  sets: %d %d", a, size, set1, set2); \
        VG_(panic)("item straddles more than two cache sets");               \
    }                                                                        \
    return;                                                                  \
index 573ee932716b68d77ad3dfcf9e6d15fdf9ae06d1..d11dd9b4ffe3ae63008bf3d482045212c577854a 100644 (file)
@@ -1067,6 +1067,43 @@ static void synth_call_baseBlock_method ( Bool ensure_shortform,
    emit_call_star_EBP_off ( 4 * word_offset );
 }
 
+static void synth_ccall_saveRegs ( void )
+{
+   emit_pushv_reg ( 4, R_EAX ); 
+   emit_pushv_reg ( 4, R_ECX ); 
+   emit_pushv_reg ( 4, R_EDX ); 
+}
+   
+static void synth_ccall_pushOneArg ( Int r1 )
+{
+   emit_pushv_reg ( 4, r1 );
+}
+
+static void synth_ccall_pushTwoArgs ( Int r1, Int r2 )
+{
+   /* must push in reverse order */
+   emit_pushv_reg ( 4, r2 );
+   emit_pushv_reg ( 4, r1 );
+}
+
+/* Synthesise a call to *baseBlock[offset], ie,
+   call * (4 x offset)(%ebp) with arguments
+*/
+static void synth_ccall_call_clearStack_restoreRegs ( Int word_offset, 
+                                                      UInt n_args_bytes )
+{
+   vg_assert(word_offset >= 0);
+   vg_assert(word_offset < VG_BASEBLOCK_WORDS);
+   vg_assert(n_args_bytes <= 12);           /* Max 3 word-sized args */
+   vg_assert(0 == (n_args_bytes & 0x3));    /* Divisible by four */
+
+   emit_call_star_EBP_off ( 4 * word_offset );
+   if ( 0 != n_args_bytes )
+      emit_add_lit_to_esp ( n_args_bytes );
+   emit_popv_reg ( 4, R_EDX ); 
+   emit_popv_reg ( 4, R_ECX ); 
+   emit_popv_reg ( 4, R_EAX ); 
+}
 
 static void load_ebp_from_JmpKind ( JmpKind jmpkind )
 {
@@ -2524,6 +2561,26 @@ static void emitUInstr ( Int i, UInstr* u )
             emit_put_eflags();
          break;
 
+      case CCALL_1_0:
+         vg_assert(u->tag1 == RealReg);
+         vg_assert(u->tag2 == NoValue);
+         vg_assert(u->size == 0);
+
+         synth_ccall_saveRegs();
+         synth_ccall_pushOneArg ( u->val1 );
+         synth_ccall_call_clearStack_restoreRegs ( u->lit32, 4 );
+         break;
+
+      case CCALL_2_0:
+         vg_assert(u->tag1 == RealReg);
+         vg_assert(u->tag2 == RealReg);
+         vg_assert(u->size == 0);
+
+         synth_ccall_saveRegs();
+         synth_ccall_pushTwoArgs ( u->val1, u->val2 );
+         synth_ccall_call_clearStack_restoreRegs ( u->lit32, 8 );
+         break;
+
       case CLEAR:
          vg_assert(u->tag1 == Lit16);
          vg_assert(u->tag2 == NoValue);
index 0d38c92332e4b868f90b24cf6c80a275cdd44010..74e10169716bda5d5664dd889c4054b7af06625d 100644 (file)
@@ -1066,6 +1066,10 @@ typedef
       PUSH, POP, CLEAR, /* Add/remove/zap args for helpers. */
       CALLM,  /* call to a machine-code helper */
 
+      /* for calling C functions -- CCALL_M_N passes M arguments and returns N
+       * (0 or 1) return values */
+      CCALL_1_0, CCALL_2_0,
+
       /* Hack for translating string (REP-) insns.  Jump to literal if
          TempReg/RealReg is zero. */
       JIFZ,
index 27a02754cfb967d858c12818958c6d2e5147ed94..a34c9093b2b7d1eab55d18e5ff1da474e335c660 100644 (file)
@@ -521,6 +521,10 @@ Bool VG_(saneUInstr) ( Bool beforeRA, UInstr* u )
          return CC0 && Ls1 && N2 && SZ0 && N3;
       case CALLM:
          return SZ0 && Ls1 && N2 && N3;
+      case CCALL_1_0:
+         return SZ0 && CC0 && TR1 && N2 && N3;
+      case CCALL_2_0:
+         return SZ0 && CC0 && TR1 && TR2 && N3;
       case PUSH: case POP:
          return CC0 && TR1 && N2 && N3;
       case AND: case OR:
@@ -802,6 +806,8 @@ Char* VG_(nameUOpcode) ( Bool upper, Opcode opc )
       case JMP:     return "J"    ;
       case JIFZ:    return "JIFZ" ;
       case CALLM:   return "CALLM";
+      case CCALL_1_0: return "CCALL_1_0";
+      case CCALL_2_0: return "CCALL_2_0";
       case PUSH:    return "PUSH" ;
       case POP:     return "POP"  ;
       case CLEAR:   return "CLEAR";
@@ -928,6 +934,20 @@ void VG_(ppUInstr) ( Int instrNo, UInstr* u )
          ppUOperand(u, 1, u->size, False);
          break;
 
+      case CCALL_1_0:
+         VG_(printf)(" ");
+         ppUOperand(u, 1, 0, False);
+         VG_(printf)(" (%u)", u->lit32);
+         break;
+
+      case CCALL_2_0:
+         VG_(printf)(" ");
+         ppUOperand(u, 1, 0, False);
+         VG_(printf)(", ");
+         ppUOperand(u, 2, 0, False);
+         VG_(printf)(" (%u)", u->lit32);
+         break;
+
       case JIFZ:
          VG_(printf)("\t");
          ppUOperand(u, 1, u->size, False);
@@ -1050,13 +1070,13 @@ Int getTempUsage ( UInstr* u, TempUse* arr )
       case GET:   WR(2); break;
       case PUT:   RD(1); break;
       case LOAD:  RD(1); WR(2); break;
-      case STORE: RD(1); RD(2); break;
+      case STORE: case CCALL_2_0: RD(1); RD(2); break;
       case MOV:   RD(1); WR(2); break;
 
       case JMP:   RD(1); break;
       case CLEAR: case CALLM: break;
 
-      case PUSH: RD(1); break;
+      case PUSH: case CCALL_1_0: RD(1); break;
       case POP:  WR(1); break;
 
       case TAG2:
index 4f1bf10716b96a50ff2b49ed1a9d351c87f15b94..05f4186f7b45eb744a5ed9b01842e144961759d3 100644 (file)
@@ -594,11 +594,6 @@ UCodeBlock* VG_(cachesim_instrument)(UCodeBlock* cb_in, Addr orig_addr)
             vg_assert(instr_size >= 1 && instr_size <= MAX_x86_INSTR_SIZE);
             vg_assert(0 != instr_addr);
 
-            /* Save the caller-save registers before we push our args */
-            uInstr1(cb, PUSH, 4, RealReg, R_EAX);
-            uInstr1(cb, PUSH, 4, RealReg, R_ECX);
-            uInstr1(cb, PUSH, 4, RealReg, R_EDX);
-
             if (!IS_(read) && !IS_(write)) {
                iCC* CC_ptr = (iCC*)(BBCC_ptr);
                vg_assert(INVALID_DATA_SIZE == data_size);
@@ -608,7 +603,13 @@ UCodeBlock* VG_(cachesim_instrument)(UCodeBlock* cb_in, Addr orig_addr)
                if (!BB_seen_before)
                    init_iCC(CC_ptr, instr_addr, instr_size);
 
-               helper = VGOFF_(cachesim_log_non_mem_instr);
+               /* 1st arg: CC addr */
+               t_CC_addr = newTemp(cb);
+               uInstr2(cb, MOV,   4, Literal, 0, TempReg, t_CC_addr);
+               uLiteral(cb, BBCC_ptr);
+
+               uInstr1(cb, CCALL_1_0, 0, TempReg, t_CC_addr);
+               uLiteral(cb, VGOFF_(cachesim_log_non_mem_instr));
 
             } else { 
                CC_type X_CC;
@@ -639,31 +640,19 @@ UCodeBlock* VG_(cachesim_instrument)(UCodeBlock* cb_in, Addr orig_addr)
                             INVALID_TEMPREG != t_write_addr);
                   t_data_addr = t_read_addr;
                }
-
+#undef IS_
                if (!BB_seen_before)
                   init_idCC(X_CC, CC_ptr, instr_addr, instr_size, data_size);
 
-               /* 2nd arg: data addr */
-               uInstr1(cb, PUSH,  4, TempReg, t_data_addr);
-               stack_used += 4;
-            }
-#undef IS_
+               /* 1st arg: CC addr */
+               t_CC_addr = newTemp(cb);
+               uInstr2(cb, MOV,   4, Literal, 0, TempReg, t_CC_addr);
+               uLiteral(cb, BBCC_ptr);
 
-            /* 1st arg: CC addr */
-            t_CC_addr = newTemp(cb);
-            uInstr2(cb, MOV,   4, Literal, 0, TempReg, t_CC_addr);
-            uLiteral(cb, BBCC_ptr);
-            uInstr1(cb, PUSH,  4, TempReg, t_CC_addr);
-            stack_used += 4;
-
-            /* Call function and return. */
-            uInstr1(cb, CALLM, 0, Lit16,   helper);
-            uInstr1(cb, CLEAR, 0, Lit16,   stack_used);
-
-            /* Restore the caller-save registers now the call is done */
-            uInstr1(cb, POP, 4, RealReg, R_EDX);
-            uInstr1(cb, POP, 4, RealReg, R_ECX);
-            uInstr1(cb, POP, 4, RealReg, R_EAX);
+               uInstr2(cb, CCALL_2_0, 0, TempReg, t_CC_addr, 
+                                         TempReg, t_data_addr);
+               uLiteral(cb, VGOFF_(cachesim_log_mem_instr));
+            }
 
             VG_(copyUInstr)(cb, u_in);
 
index f938bc4b0fd3497519db75942134bed48174127c..182a03138aa9d83a5a5341f1b2a1aec35d3a5fc0 100644 (file)
@@ -199,6 +199,7 @@ miss_treatment:                                                             \
       if (is_miss) { MISS_TREATMENT; }                                      \
                                                                             \
    } else {                                                                 \
+       VG_(printf)("addr: %x  size: %u  sets: %d %d", a, size, set1, set2); \
        VG_(panic)("item straddles more than two cache sets");               \
    }                                                                        \
    return;                                                                  \
index 573ee932716b68d77ad3dfcf9e6d15fdf9ae06d1..d11dd9b4ffe3ae63008bf3d482045212c577854a 100644 (file)
@@ -1067,6 +1067,43 @@ static void synth_call_baseBlock_method ( Bool ensure_shortform,
    emit_call_star_EBP_off ( 4 * word_offset );
 }
 
+static void synth_ccall_saveRegs ( void )
+{
+   emit_pushv_reg ( 4, R_EAX ); 
+   emit_pushv_reg ( 4, R_ECX ); 
+   emit_pushv_reg ( 4, R_EDX ); 
+}
+   
+static void synth_ccall_pushOneArg ( Int r1 )
+{
+   emit_pushv_reg ( 4, r1 );
+}
+
+static void synth_ccall_pushTwoArgs ( Int r1, Int r2 )
+{
+   /* must push in reverse order */
+   emit_pushv_reg ( 4, r2 );
+   emit_pushv_reg ( 4, r1 );
+}
+
+/* Synthesise a call to *baseBlock[offset], ie,
+   call * (4 x offset)(%ebp) with arguments
+*/
+static void synth_ccall_call_clearStack_restoreRegs ( Int word_offset, 
+                                                      UInt n_args_bytes )
+{
+   vg_assert(word_offset >= 0);
+   vg_assert(word_offset < VG_BASEBLOCK_WORDS);
+   vg_assert(n_args_bytes <= 12);           /* Max 3 word-sized args */
+   vg_assert(0 == (n_args_bytes & 0x3));    /* Divisible by four */
+
+   emit_call_star_EBP_off ( 4 * word_offset );
+   if ( 0 != n_args_bytes )
+      emit_add_lit_to_esp ( n_args_bytes );
+   emit_popv_reg ( 4, R_EDX ); 
+   emit_popv_reg ( 4, R_ECX ); 
+   emit_popv_reg ( 4, R_EAX ); 
+}
 
 static void load_ebp_from_JmpKind ( JmpKind jmpkind )
 {
@@ -2524,6 +2561,26 @@ static void emitUInstr ( Int i, UInstr* u )
             emit_put_eflags();
          break;
 
+      case CCALL_1_0:
+         vg_assert(u->tag1 == RealReg);
+         vg_assert(u->tag2 == NoValue);
+         vg_assert(u->size == 0);
+
+         synth_ccall_saveRegs();
+         synth_ccall_pushOneArg ( u->val1 );
+         synth_ccall_call_clearStack_restoreRegs ( u->lit32, 4 );
+         break;
+
+      case CCALL_2_0:
+         vg_assert(u->tag1 == RealReg);
+         vg_assert(u->tag2 == RealReg);
+         vg_assert(u->size == 0);
+
+         synth_ccall_saveRegs();
+         synth_ccall_pushTwoArgs ( u->val1, u->val2 );
+         synth_ccall_call_clearStack_restoreRegs ( u->lit32, 8 );
+         break;
+
       case CLEAR:
          vg_assert(u->tag1 == Lit16);
          vg_assert(u->tag2 == NoValue);
index 0d38c92332e4b868f90b24cf6c80a275cdd44010..74e10169716bda5d5664dd889c4054b7af06625d 100644 (file)
@@ -1066,6 +1066,10 @@ typedef
       PUSH, POP, CLEAR, /* Add/remove/zap args for helpers. */
       CALLM,  /* call to a machine-code helper */
 
+      /* for calling C functions -- CCALL_M_N passes M arguments and returns N
+       * (0 or 1) return values */
+      CCALL_1_0, CCALL_2_0,
+
       /* Hack for translating string (REP-) insns.  Jump to literal if
          TempReg/RealReg is zero. */
       JIFZ,
index 27a02754cfb967d858c12818958c6d2e5147ed94..a34c9093b2b7d1eab55d18e5ff1da474e335c660 100644 (file)
@@ -521,6 +521,10 @@ Bool VG_(saneUInstr) ( Bool beforeRA, UInstr* u )
          return CC0 && Ls1 && N2 && SZ0 && N3;
       case CALLM:
          return SZ0 && Ls1 && N2 && N3;
+      case CCALL_1_0:
+         return SZ0 && CC0 && TR1 && N2 && N3;
+      case CCALL_2_0:
+         return SZ0 && CC0 && TR1 && TR2 && N3;
       case PUSH: case POP:
          return CC0 && TR1 && N2 && N3;
       case AND: case OR:
@@ -802,6 +806,8 @@ Char* VG_(nameUOpcode) ( Bool upper, Opcode opc )
       case JMP:     return "J"    ;
       case JIFZ:    return "JIFZ" ;
       case CALLM:   return "CALLM";
+      case CCALL_1_0: return "CCALL_1_0";
+      case CCALL_2_0: return "CCALL_2_0";
       case PUSH:    return "PUSH" ;
       case POP:     return "POP"  ;
       case CLEAR:   return "CLEAR";
@@ -928,6 +934,20 @@ void VG_(ppUInstr) ( Int instrNo, UInstr* u )
          ppUOperand(u, 1, u->size, False);
          break;
 
+      case CCALL_1_0:
+         VG_(printf)(" ");
+         ppUOperand(u, 1, 0, False);
+         VG_(printf)(" (%u)", u->lit32);
+         break;
+
+      case CCALL_2_0:
+         VG_(printf)(" ");
+         ppUOperand(u, 1, 0, False);
+         VG_(printf)(", ");
+         ppUOperand(u, 2, 0, False);
+         VG_(printf)(" (%u)", u->lit32);
+         break;
+
       case JIFZ:
          VG_(printf)("\t");
          ppUOperand(u, 1, u->size, False);
@@ -1050,13 +1070,13 @@ Int getTempUsage ( UInstr* u, TempUse* arr )
       case GET:   WR(2); break;
       case PUT:   RD(1); break;
       case LOAD:  RD(1); WR(2); break;
-      case STORE: RD(1); RD(2); break;
+      case STORE: case CCALL_2_0: RD(1); RD(2); break;
       case MOV:   RD(1); WR(2); break;
 
       case JMP:   RD(1); break;
       case CLEAR: case CALLM: break;
 
-      case PUSH: RD(1); break;
+      case PUSH: case CCALL_1_0: RD(1); break;
       case POP:  WR(1); break;
 
       case TAG2: