Added various functions that make instrumentation easier, particularly
doing C calls.


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2262 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_instrument.c b/coregrind/vg_instrument.c
index d35f084..9b5e3c3 100644
--- a/coregrind/vg_instrument.c
+++ b/coregrind/vg_instrument.c
@@ -36,60 +36,215 @@
 #include "vg_skin.h"
 
 
-void VG_(call_helper_0_0)(UCodeBlock* cb, Addr f)
+void VG_(lit_to_reg)(UCodeBlock* cb, UInt lit, UInt t)
+{
+   uInstr2 (cb, MOV, 4, Literal, 0, TempReg, t);
+   uLiteral(cb, lit);
+}
+
+UInt VG_(lit_to_newreg)(UCodeBlock* cb, UInt lit)
+{
+   UInt t = newTemp(cb);
+   uInstr2 (cb, MOV, 4, Literal, 0, TempReg, t);
+   uLiteral(cb, lit);
+   return t;
+}
+
+// f()
+void VG_(ccall_0_0)(UCodeBlock* cb, Addr f)
 {
    uInstr0(cb, CCALL, 0);
-   uCCall(cb, f, 0, 0, 0);
+   uCCall(cb, f, 0, 0, /*retval*/False);
+}
+
+// f(reg)
+void VG_(ccall_R_0)(UCodeBlock* cb, Addr f, UInt t1, UInt regparms_n)
+{
+   sk_assert(regparms_n <= 1);
+   uInstr1(cb, CCALL, 0, TempReg, t1);
+   uCCall(cb, f, 1, regparms_n, /*retval*/False);
+}
+
+// f(lit)
+void VG_(ccall_L_0)(UCodeBlock* cb, Addr f, UInt lit1, UInt regparms_n)
+{
+   UInt t1 = VG_(lit_to_newreg)(cb, lit1);
+   VG_(ccall_R_0)(cb, f, t1, regparms_n);
+}
+
+// reg = f(reg)
+void VG_(ccall_R_R)(UCodeBlock* cb, Addr f, UInt t1, UInt t_ret,
+                    UInt regparms_n)
+{
+   sk_assert(regparms_n <= 1);
+   sk_assert(t1 < VG_(get_num_temps)(cb)); // help catch lits accidentally passed in
+   uInstr3(cb, CCALL, 0, TempReg, t1, NoValue, 0, TempReg, t_ret);
+   uCCall(cb, f, 1, regparms_n, /*retval*/True);
+}
+
+// reg = f(lit)
+void VG_(ccall_L_R)(UCodeBlock* cb, Addr f, UInt lit1, UInt t_ret,
+                    UInt regparms_n)
+{
+   UInt t1 = VG_(lit_to_newreg)(cb, lit1);
+   VG_(ccall_R_R)(cb, f, t1, t_ret, regparms_n);
+}
+
+// f(reg, reg)
+void VG_(ccall_RR_0)(UCodeBlock* cb, Addr f, UInt t1, UInt t2, UInt regparms_n)
+{
+   sk_assert(regparms_n <= 2);
+   sk_assert(t1 < VG_(get_num_temps)(cb));
+   sk_assert(t2 < VG_(get_num_temps)(cb));
+   uInstr2(cb, CCALL, 0, TempReg, t1, TempReg, t2);
+   uCCall(cb, f, 2, regparms_n, /*retval*/False);
+}
+
+// f(reg, lit)
+void VG_(ccall_RL_0)(UCodeBlock* cb, Addr f, UInt t1, UInt lit2,
+                     UInt regparms_n)
+{
+   UInt t2 = VG_(lit_to_newreg)(cb, lit2);
+   VG_(ccall_RR_0)(cb, f, t1, t2, regparms_n);
+}
+
+// f(lit, reg)
+void VG_(ccall_LR_0)(UCodeBlock* cb, Addr f, UInt lit1, UInt t2,
+                     UInt regparms_n)
+{
+   UInt t1 = VG_(lit_to_newreg)(cb, lit1);
+   VG_(ccall_RR_0)(cb, f, t1, t2, regparms_n);
+}
+
+// f(lit, lit)
+void VG_(ccall_LL_0)(UCodeBlock* cb, Addr f, UInt lit1, UInt lit2,
+                     UInt regparms_n)
+{
+   UInt t1 = VG_(lit_to_newreg)(cb, lit1);
+   UInt t2 = VG_(lit_to_newreg)(cb, lit2);
+   VG_(ccall_RR_0)(cb, f, t1, t2, regparms_n);
+}
+
+// reg = f(reg, reg)
+void VG_(ccall_RR_R)(UCodeBlock* cb, Addr f, UInt t1, UInt t2, UInt t_ret,
+                     UInt regparms_n)
+{
+   sk_assert(regparms_n <= 2);
+   sk_assert(t1 < VG_(get_num_temps)(cb));
+   sk_assert(t2 < VG_(get_num_temps)(cb));
+   uInstr3(cb, CCALL, 0, TempReg, t1, TempReg, t2, TempReg, t_ret);
+   uCCall(cb, f, 2, regparms_n, /*retval*/True);
+}
+
+// reg = f(reg, lit)
+void VG_(ccall_RL_R)(UCodeBlock* cb, Addr f, UInt t1, UInt lit2, UInt t_ret,
+                     UInt regparms_n)
+{
+   UInt t2 = VG_(lit_to_newreg)(cb, lit2);
+   VG_(ccall_RR_R)(cb, f, t1, t2, t_ret, regparms_n);
+}
+
+// reg = f(lit, reg)
+void VG_(ccall_LR_R)(UCodeBlock* cb, Addr f, UInt lit1, UInt t2, UInt t_ret,
+                     UInt regparms_n)
+{
+   UInt t1 = VG_(lit_to_newreg)(cb, lit1);
+   VG_(ccall_RR_R)(cb, f, t1, t2, t_ret, regparms_n);
+}
+
+// reg = f(lit, lit)
+void VG_(ccall_LL_R)(UCodeBlock* cb, Addr f, UInt lit1, UInt lit2, UInt t_ret,
+                     UInt regparms_n)
+{
+   UInt t1 = VG_(lit_to_newreg)(cb, lit2);
+   UInt t2 = VG_(lit_to_newreg)(cb, lit2);
+   VG_(ccall_RR_R)(cb, f, t1, t2, t_ret, regparms_n);
+}
+
+// f(reg, reg, reg)
+void VG_(ccall_RRR_0)(UCodeBlock* cb, Addr f, UInt t1, UInt t2,
+                      UInt t3, UInt regparms_n)
+{
+   sk_assert(regparms_n <= 3);
+   sk_assert(t1 < VG_(get_num_temps)(cb));
+   sk_assert(t2 < VG_(get_num_temps)(cb));
+   sk_assert(t3 < VG_(get_num_temps)(cb));
+   uInstr3(cb, CCALL, 0, TempReg, t1, TempReg, t2, TempReg, t3);
+   uCCall(cb, f, 3, regparms_n, /*retval*/False);
+}
+
+// f(reg, lit, lit)
+void VG_(ccall_RLL_0)(UCodeBlock* cb, Addr f, UInt t1, UInt lit2,
+                      UInt lit3, UInt regparms_n)
+{
+   UInt t2 = VG_(lit_to_newreg)(cb, lit2);
+   UInt t3 = VG_(lit_to_newreg)(cb, lit3);
+   VG_(ccall_RRR_0)(cb, f, t1, t2, t3, regparms_n);
+}
+
+// f(lit, lit, reg)
+void VG_(ccall_LLR_0)(UCodeBlock* cb, Addr f, UInt lit1, UInt lit2,
+                      UInt t3, UInt regparms_n)
+{
+   UInt t1 = VG_(lit_to_newreg)(cb, lit1);
+   UInt t2 = VG_(lit_to_newreg)(cb, lit2);
+   VG_(ccall_RRR_0)(cb, f, t1, t2, t3, regparms_n);
+}
+
+// f(lit, lit, lit)
+void VG_(ccall_LLL_0)(UCodeBlock* cb, Addr f, UInt lit1, UInt lit2,
+                      UInt lit3, UInt regparms_n)
+{
+   UInt t1 = VG_(lit_to_newreg)(cb, lit1);
+   UInt t2 = VG_(lit_to_newreg)(cb, lit2);
+   UInt t3 = VG_(lit_to_newreg)(cb, lit3);
+   VG_(ccall_RRR_0)(cb, f, t1, t2, t3, regparms_n);
+}
+
+void VG_(reg_to_globvar)(UCodeBlock* cb, UInt t, UInt* globvar_ptr)
+{
+   Int t_gv  = VG_(lit_to_newreg)(cb, (UInt)globvar_ptr);
+   uInstr2(cb, STORE, 4, TempReg, t, TempReg, t_gv);
+}
+
+void VG_(lit_to_globvar)(UCodeBlock* cb, UInt lit, UInt* globvar_ptr)
+{
+   Int t_lit = VG_(lit_to_newreg)(cb, lit);
+   VG_(reg_to_globvar)(cb, t_lit, globvar_ptr);
+}
+
+/*--------------------------------------------------------------------
+  Old versions of these functions, for backwards compatibility          
+  --------------------------------------------------------------------*/
+
+void VG_(call_helper_0_0)(UCodeBlock* cb, Addr f)
+{
+   VG_(ccall_0_0)(cb, f);
 }
 
 void VG_(call_helper_1_0)(UCodeBlock* cb, Addr f, UInt arg1, UInt regparms_n)
 {
-   UInt t1 = newTemp(cb);
-
-   sk_assert(regparms_n <= 1);
-   uInstr2(cb, MOV,   4, Literal, 0, TempReg, t1);
-   uLiteral(cb, arg1);
-   uInstr1(cb, CCALL, 0, TempReg, t1);
-   uCCall(cb, f, 1, regparms_n, 0);
+   VG_(ccall_L_0)(cb, f, arg1, regparms_n);
 }
 
 void VG_(call_helper_2_0)(UCodeBlock* cb, Addr f, UInt arg1, UInt arg2,
                          UInt regparms_n)
 {
-   UInt t1 = newTemp(cb);
-   UInt t2 = newTemp(cb);
-
-   sk_assert(regparms_n <= 2);
-   uInstr2(cb, MOV,   4, Literal, 0, TempReg, t1);
-   uLiteral(cb, arg1);
-   uInstr2(cb, MOV,   4, Literal, 0, TempReg, t2);
-   uLiteral(cb, arg2);
-   uInstr2(cb, CCALL, 0, TempReg, t1, TempReg, t2);
-   uCCall(cb, f, 2, regparms_n, 0);
+   VG_(ccall_LL_0)(cb, f, arg1, arg2, regparms_n);
 }
 
 void VG_(set_global_var)(UCodeBlock* cb, Addr globvar_ptr, UInt val)
 {
-   Int t_gv  = newTemp(cb);        
-   Int t_val = newTemp(cb);        
-
-   uInstr2(cb, MOV,   4, Literal, 0, TempReg, t_val);
-   uLiteral(cb, val);
-   uInstr2(cb, MOV,   4, Literal, 0, TempReg, t_gv);
-   uLiteral(cb, globvar_ptr);
-   uInstr2(cb, STORE, 4, TempReg, t_val, TempReg, t_gv);
+   VG_(lit_to_globvar)(cb, val, (UInt*)globvar_ptr);
 }
 
 void VG_(set_global_var_tempreg)(UCodeBlock* cb, Addr globvar_ptr, UInt t_val)
 {
-   Int t_gv  = newTemp(cb);        
-
-   uInstr2(cb, MOV,   4, Literal, 0, TempReg, t_gv);
-   uLiteral(cb, globvar_ptr);
-   uInstr2(cb, STORE, 4, TempReg, t_val, TempReg, t_gv);
+   VG_(reg_to_globvar)(cb, t_val, (UInt*)globvar_ptr);
 }
 
 /*--------------------------------------------------------------------*/
 /*--- end                                          vg_instrument.c ---*/
 /*--------------------------------------------------------------------*/
 
+
diff --git a/include/vg_skin.h.base b/include/vg_skin.h.base
index f456276..b0b24d1 100644
--- a/include/vg_skin.h.base
+++ b/include/vg_skin.h.base
@@ -845,7 +845,7 @@
       /* Not for translating x86 calls -- only to call C helper functions of
          up to three arguments (or two if the functions has a return value).
          Arguments and return value must be word-sized.  More arguments can
-         be faked with global variables (eg. use VG_(set_global_var)()).
+         be faked with global variables (eg. use VG_(lit_to_globvar)()).
 
          Seven possibilities: 'arg[123]' show where args go, 'ret' shows
          where return value goes (if present).
@@ -1116,17 +1116,56 @@
 
 /* ------------------------------------------------------------------ */
 /* Higher-level UInstr sequence builders */
+
+extern void VG_(lit_to_reg)    ( UCodeBlock* cb, UInt lit, UInt t );
+extern UInt VG_(lit_to_newreg) ( UCodeBlock* cb, UInt lit         );
+
+#define CB_F   UCodeBlock* cb, Addr f
+#define EV     extern void
+#define RPn    UInt regparms_n
+
+/* Various CCALL builders, of the form "ccall_<args>_<retval>".  'R'
+   represents a TempReg, 'L' represents a literal, '0' represents nothing
+   (ie. no args, or no return value). */
+
+EV VG_(ccall_0_0)   ( CB_F                                    );
+
+EV VG_(ccall_R_0)   ( CB_F, UInt r1,                      RPn );
+EV VG_(ccall_L_0)   ( CB_F, UInt r1,                      RPn );
+EV VG_(ccall_R_R)   ( CB_F, UInt r1, UInt r_ret,          RPn );
+EV VG_(ccall_L_R)   ( CB_F, UInt r1, UInt r_ret,          RPn );
+
+EV VG_(ccall_RR_0)  ( CB_F, UInt r1, UInt r2,             RPn );
+EV VG_(ccall_RL_0)  ( CB_F, UInt r1, UInt r2,             RPn );
+EV VG_(ccall_LR_0)  ( CB_F, UInt r1, UInt r2,             RPn );
+EV VG_(ccall_LL_0)  ( CB_F, UInt r1, UInt r2,             RPn );
+EV VG_(ccall_RR_R)  ( CB_F, UInt r1, UInt r2, UInt r_ret, RPn );
+EV VG_(ccall_RL_R)  ( CB_F, UInt r1, UInt r2, UInt r_ret, RPn );
+EV VG_(ccall_LR_R)  ( CB_F, UInt r1, UInt r2, UInt r_ret, RPn );
+EV VG_(ccall_LL_R)  ( CB_F, UInt r1, UInt r2, UInt r_ret, RPn );
+
+EV VG_(ccall_RRR_0) ( CB_F, UInt r1, UInt r2, UInt r3,    RPn );
+EV VG_(ccall_RLL_0) ( CB_F, UInt r1, UInt r2, UInt r3,    RPn );
+EV VG_(ccall_LLR_0) ( CB_F, UInt r1, UInt r2, UInt r3,    RPn );
+EV VG_(ccall_LLL_0) ( CB_F, UInt r1, UInt r2, UInt r3,    RPn );
+
+#undef CB_F
+#undef EV
+#undef RPn
+
+/* One way around the 3-arg C function limit is to pass args via global
+ * variables... ugly, but it works. */
+void VG_(reg_to_globvar)(UCodeBlock* cb, UInt t,   UInt* globvar_ptr);
+void VG_(lit_to_globvar)(UCodeBlock* cb, UInt lit, UInt* globvar_ptr);
+
+
+/* Old, deprecated versions of some of the helpers (DO NOT USE) */
 extern void VG_(call_helper_0_0) ( UCodeBlock* cb, Addr f);
 extern void VG_(call_helper_1_0) ( UCodeBlock* cb, Addr f, UInt arg1,
                                    UInt regparms_n);
 extern void VG_(call_helper_2_0) ( UCodeBlock* cb, Addr f, UInt arg1, UInt arg2,
                                    UInt regparms_n);
-
-/* One way around the 3-arg C function limit is to pass args via global
- * variables... ugly, but it works.  This one puts a literal in there. */
 extern void VG_(set_global_var) ( UCodeBlock* cb, Addr globvar_ptr, UInt val);
-
-/* This one puts the contents of a TempReg in the global variable. */
 extern void VG_(set_global_var_tempreg) ( UCodeBlock* cb, Addr globvar_ptr,
                                           UInt t_val);