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
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
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
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
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 ---*/
--- /dev/null
+
+/*---------------------------------------------------------------*/
+/*--- ---*/
+/*--- 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 ---*/
+/*---------------------------------------------------------------*/
/* 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.
typedef
struct {
+ Addr64 (*find_helper)(Char*);
+
IRTypeEnv* type_env;
HReg* vregmap;
/* --------- 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
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),
/* 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;
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();
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());
}
+#if 0
/* Self-contained test; can be called directly from
main. */
void test_asm86 ( void )
#undef T
}
-
+#endif
/*---------------------------------------------------------------*/
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 */
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;
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);
switch (iset_guest) {
case InsnSetX86:
- bbToIR = bbToIR_X86Instr;
+ bbToIR = bbToIR_X86Instr;
+ findHelper = x86guest_findhelper;
break;
default:
vpanic("LibVEX_Translate: unsupported guest insn set");
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");
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. */
__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 */
/*---------------------------------------------------------------*/