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);