From: Julian Seward Date: Sat, 24 Jul 2004 13:12:23 +0000 (+0000) Subject: Add mechanisms for calling helper functions from generated code. X-Git-Tag: svn/VALGRIND_3_0_1^2~1222 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=40573eab36a6ef1e372373e3fe56dbf5a1a7ac78;p=thirdparty%2Fvalgrind.git Add mechanisms for calling helper functions from generated code. git-svn-id: svn://svn.valgrind.org/vex/trunk@112 --- diff --git a/VEX/Makefile b/VEX/Makefile index 8608a16e98..d102ae15c3 100644 --- a/VEX/Makefile +++ b/VEX/Makefile @@ -17,6 +17,7 @@ LIB_OBJS = priv/ir/ir_defs.o \ priv/host-x86/isel_x86.o \ priv/host-generic/host_regs.o \ priv/host-generic/reg_alloc.o \ + priv/guest-x86/x86helpers.o \ priv/guest-x86/x86toIR.o PUB_INCLUDES = -Ipub @@ -97,4 +98,8 @@ priv/host-generic/reg_alloc.o: $(ALL_HEADERS) priv/host-generic/reg_alloc.c priv/guest-x86/x86toIR.o: $(ALL_HEADERS) priv/guest-x86/x86toIR.c $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/guest-x86/x86toIR.o \ - -c priv/guest-x86/x86toIR.c \ No newline at end of file + -c priv/guest-x86/x86toIR.c + +priv/guest-x86/x86helpers.o: $(ALL_HEADERS) priv/guest-x86/x86helpers.c + $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/guest-x86/x86helpers.o \ + -c priv/guest-x86/x86helpers.c diff --git a/VEX/Makefile-icc b/VEX/Makefile-icc index 037e605632..720a4cf9eb 100644 --- a/VEX/Makefile-icc +++ b/VEX/Makefile-icc @@ -17,6 +17,7 @@ LIB_OBJS = priv/ir/ir_defs.o \ priv/host-x86/isel_x86.o \ priv/host-generic/host_regs.o \ priv/host-generic/reg_alloc.o \ + priv/guest-x86/x86helpers.o \ priv/guest-x86/x86toIR.o PUB_INCLUDES = -Ipub @@ -97,4 +98,8 @@ priv/host-generic/reg_alloc.o: $(ALL_HEADERS) priv/host-generic/reg_alloc.c priv/guest-x86/x86toIR.o: $(ALL_HEADERS) priv/guest-x86/x86toIR.c $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/guest-x86/x86toIR.o \ - -c priv/guest-x86/x86toIR.c \ No newline at end of file + -c priv/guest-x86/x86toIR.c + +priv/guest-x86/x86helpers.o: $(ALL_HEADERS) priv/guest-x86/x86helpers.c + $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/guest-x86/x86helpers.o \ + -c priv/guest-x86/x86helpers.c diff --git a/VEX/priv/guest-x86/x86guest_defs.h b/VEX/priv/guest-x86/x86guest_defs.h index 55cf447789..2baa51ce8d 100644 --- a/VEX/priv/guest-x86/x86guest_defs.h +++ b/VEX/priv/guest-x86/x86guest_defs.h @@ -26,6 +26,11 @@ IRBB* bbToIR_X86Instr ( UChar* x86code, Bool (*byte_accessible)(Addr64), Bool host_bigendian ); +/* Used by the back end to look up addresses of helper + function calls inserted by bbToIR_X86Instr. */ +extern +Addr64 x86guest_findhelper ( Char* function_name ); + /*---------------------------------------------------------*/ /*--- Condition code stuff ---*/ diff --git a/VEX/priv/guest-x86/x86helpers.c b/VEX/priv/guest-x86/x86helpers.c new file mode 100644 index 0000000000..ed25937dd5 --- /dev/null +++ b/VEX/priv/guest-x86/x86helpers.c @@ -0,0 +1,62 @@ + +/*---------------------------------------------------------------*/ +/*--- ---*/ +/*--- This file (x86helpers.c) is ---*/ +/*--- Copyright (c) 2004 OpenWorks LLP. All rights reserved. ---*/ +/*--- ---*/ +/*---------------------------------------------------------------*/ + +#include "libvex_basictypes.h" +#include "libvex_ir.h" +#include "vex_util.h" +#include "x86guest_defs.h" + +/* This file contains helper functions for x86 guest code. + Calls to these functions are generated by the back end. + These calls are of course in the host machine code and + this file will be compiled to host machine code, so that + all makes sense. + + x86guest_findhelper() is the only exported function. + + Only change the signatures of these helper functions very + carefully. If you change the signature here, you'll have to change + the parameters passed to it in the IR calls constructed by + x86toIR.c. +*/ + + +/* RUNS AS PART OF GENERATED CODE */ +static UInt calculate_eflags_all ( UInt cc_op, UInt cc_src, UInt cc_dst ) +{ + switch (cc_op) { + default: + /* shouldn't really make these calls from generated code */ + vex_printf("calculate_eflags_all: unhandled %d\n", cc_op); + vpanic("calculate_eflags_all"); + } +} + +/* RUNS AS PART OF GENERATED CODE */ +static UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst ) +{ + return calculate_eflags_all(cc_op,cc_src,cc_dst) & CC_MASK_C; +} + + +/* The only exported function. */ + +Addr64 x86guest_findhelper ( Char* function_name ) +{ + if (vex_streq(function_name, "calculate_eflags_all")) + return (Addr64)(& calculate_eflags_all); + if (vex_streq(function_name, "calculate_eflags_c")) + return (Addr64)(& calculate_eflags_c); + vex_printf("\nx86 guest: can't find helper: %s\n", function_name); + vpanic("x86guest_findhelper"); +} + + +/*---------------------------------------------------------------*/ +/*--- end x86helpers.c ---*/ +/*---------------------------------------------------------------*/ diff --git a/VEX/priv/host-x86/isel_x86.c b/VEX/priv/host-x86/isel_x86.c index b6a8177630..5ae49d0b10 100644 --- a/VEX/priv/host-x86/isel_x86.c +++ b/VEX/priv/host-x86/isel_x86.c @@ -135,6 +135,8 @@ static IRExpr* bind ( Int binder ) /* This carries around: + - A function for looking up the address of helper functions. + - A mapping from IRTemp to IRType, giving the type of any IRTemp we might encounter. This is computed before insn selection starts, and does not change. @@ -159,6 +161,8 @@ static IRExpr* bind ( Int binder ) typedef struct { + Addr64 (*find_helper)(Char*); + IRTypeEnv* type_env; HReg* vregmap; @@ -411,8 +415,9 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ) /* --------- CCALL --------- */ case Iex_CCall: { - Int i, nargs; - UInt target; + Addr64 helper; + Int i, nargs; + UInt target; IRExpr* arg; vassert(ty == Ity_I32); /* be very restrictive for now. Only 32-bit ints allowed @@ -428,7 +433,12 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e ) goto irreducible; addInstr(env, X86Instr_Push(iselIntExpr_RMI(env, arg))); } - target = 0x12345678; //FIND_HELPER(e->Iex.CCall.name); + /* Find the function to call. Since the host -- for which we + are generating code -- is a 32-bit machine (x86) -- the upper + 32 bit of the helper address should be zero. */ + helper = env->find_helper(e->Iex.CCall.name); + vassert((helper & 0xFFFFFFFF00000000LL) == 0); + target = helper & 0xFFFFFFFF; addInstr(env, X86Instr_Alu32R( Xalu_MOV, X86RMI_Imm(target), @@ -905,7 +915,7 @@ static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk ) /* Translate an entire BB to x86 code. */ -HInstrArray* iselBB_X86 ( IRBB* bb ) +HInstrArray* iselBB_X86 ( IRBB* bb, Addr64(*find_helper)(Char*) ) { Int i, j; HReg hreg, hregHI; @@ -915,6 +925,9 @@ HInstrArray* iselBB_X86 ( IRBB* bb ) ISelEnv* env = LibVEX_Alloc(sizeof(ISelEnv)); env->vreg_ctr = 0; + /* Register helper-function-finder. */ + env->find_helper = find_helper; + /* Set up output code array. */ env->code = newHInstrArray(); diff --git a/VEX/priv/host-x86/x86host_defs.c b/VEX/priv/host-x86/x86host_defs.c index 6ddd0cde95..84d1c8dfc2 100644 --- a/VEX/priv/host-x86/x86host_defs.c +++ b/VEX/priv/host-x86/x86host_defs.c @@ -670,7 +670,7 @@ void getRegUsage_X86Instr (HRegUsage* u, X86Instr* i) case Xin_Call: addHRegUse(u, HRmRead, i->Xin.Call.target); /* claim it trashes all the callee-saved regs */ - /* except I have no idea what they are */ + /* which I believe to be %eax,%ecx,%edx. */ addHRegUse(u, HRmWrite, hregX86_EAX()); addHRegUse(u, HRmWrite, hregX86_ECX()); addHRegUse(u, HRmWrite, hregX86_EDX()); @@ -1341,6 +1341,7 @@ Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* i ) } +#if 0 /* Self-contained test; can be called directly from main. */ void test_asm86 ( void ) @@ -1427,7 +1428,7 @@ T( X86Instr_Alu32M(Xalu_SUB, X86RI_Reg(ecx), X86AMode_IR(0x7F,ebp)) ); #undef T } - +#endif /*---------------------------------------------------------------*/ diff --git a/VEX/priv/host-x86/x86host_defs.h b/VEX/priv/host-x86/x86host_defs.h index c48716bdca..0801377006 100644 --- a/VEX/priv/host-x86/x86host_defs.h +++ b/VEX/priv/host-x86/x86host_defs.h @@ -375,7 +375,7 @@ extern Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr* ); extern X86Instr* genSpill_X86 ( HReg rreg, Int offset ); extern X86Instr* genReload_X86 ( HReg rreg, Int offset ); extern void getAllocableRegs_X86 ( Int*, HReg** ); -extern HInstrArray* iselBB_X86 ( IRBB* ); +extern HInstrArray* iselBB_X86 ( IRBB*, Addr64(*)(Char*) ); #endif /* ndef __LIBVEX_X86H_DEFS_H */ diff --git a/VEX/priv/main/vex_main.c b/VEX/priv/main/vex_main.c index 3e92d91a3e..656e768135 100644 --- a/VEX/priv/main/vex_main.c +++ b/VEX/priv/main/vex_main.c @@ -91,10 +91,11 @@ TranslateResult LibVEX_Translate ( HInstr* (*genReload) ( HReg, Int ); void (*ppInstr) ( HInstr* ); void (*ppReg) ( HReg ); - HInstrArray* (*iselBB) ( IRBB* ); + HInstrArray* (*iselBB) ( IRBB*, Addr64(*)(Char*) ); IRBB* (*bbToIR) ( UChar*, Addr64, Int*, Bool(*)(Addr64), Bool ); Int (*emit) ( UChar*, Int, HInstr* ); + Addr64 (*findHelper) ( Char* ); Bool host_is_bigendian = False; IRBB* irbb; @@ -103,6 +104,20 @@ TranslateResult LibVEX_Translate ( Int i, j, k, out_used; UChar insn_bytes[32]; + available_real_regs = NULL; + n_available_real_regs = 0; + isMove = NULL; + getRegUsage = NULL; + mapRegs = NULL; + genSpill = NULL; + genReload = NULL; + ppInstr = NULL; + ppReg = NULL; + iselBB = NULL; + bbToIR = NULL; + emit = NULL; + findHelper = NULL; + vassert(vex_initdone); LibVEX_ClearTemporary(False); @@ -129,7 +144,8 @@ TranslateResult LibVEX_Translate ( switch (iset_guest) { case InsnSetX86: - bbToIR = bbToIR_X86Instr; + bbToIR = bbToIR_X86Instr; + findHelper = x86guest_findhelper; break; default: vpanic("LibVEX_Translate: unsupported guest insn set"); @@ -153,7 +169,7 @@ TranslateResult LibVEX_Translate ( irbb = (*instrument)(irbb); /* Turn it into virtual-registerised code. */ - vcode = iselBB ( irbb ); + vcode = iselBB ( irbb, findHelper ); if (vex_verbosity > 0) { vex_printf("\n-------- Virtual registerised code --------\n"); diff --git a/VEX/priv/main/vex_util.c b/VEX/priv/main/vex_util.c index 98f41c30a0..601176bb23 100644 --- a/VEX/priv/main/vex_util.c +++ b/VEX/priv/main/vex_util.c @@ -168,6 +168,17 @@ static Int vex_strlen ( const Char* str ) return i; } +Bool vex_streq ( const Char* s1, const Char* s2 ) +{ + while (True) { + if (*s1 == 0 && *s2 == 0) + return True; + if (*s1 != *s2) + return False; + s1++; + s2++; + } +} /* Some flags. */ #define VG_MSG_SIGNED 1 /* The value is signed. */ diff --git a/VEX/priv/main/vex_util.h b/VEX/priv/main/vex_util.h index 97ffe9cdfe..2f1b53abca 100644 --- a/VEX/priv/main/vex_util.h +++ b/VEX/priv/main/vex_util.h @@ -42,6 +42,12 @@ extern UInt vex_printf ( const Char *format, ... ); __attribute__ ((format (printf, 2, 3))) extern UInt vex_sprintf ( Char* buf, const Char *format, ... ); + +/* String ops */ + +extern Bool vex_streq ( const Char* s1, const Char* s2 ); + + #endif /* ndef __VEX_UTIL_H */ /*---------------------------------------------------------------*/