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
-HWord x86guest_findhelper ( Char* function_name );
-
/* Used by the optimiser to specialise calls to helpers. */
extern
IRExpr* x86guest_spechelper ( Char* function_name,
VexGuestLayoutInfo x86guest_layout;
+/*---------------------------------------------------------*/
+/*--- x86 guest helpers ---*/
+/*---------------------------------------------------------*/
+
+/* --- CLEAN HELPERS --- */
+extern UInt calculate_eflags_all ( UInt cc_op, UInt cc_src, UInt cc_dst );
+extern UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst );
+extern UInt calculate_condition ( UInt/*Condcode*/ cond,
+ UInt cc_op, UInt cc_src, UInt cc_dst );
+extern UInt calculate_FXAM ( UInt tag, ULong dbl );
+extern ULong calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz );
+
+/* --- DIRTY HELPERS --- */
+extern ULong loadF80le ( UInt );
+extern void storeF80le ( UInt, ULong );
+extern void dirtyhelper_CPUID ( VexGuestX86State* );
+
+
/*---------------------------------------------------------*/
/*--- Condition code stuff ---*/
/*---------------------------------------------------------*/
#include "main/vex_util.h"
#include "guest-x86/gdefs.h"
-/* --- Forwardses --- */
-
-/* --- CLEAN HELPERS --- */
-static UInt calculate_eflags_all ( UInt cc_op, UInt cc_src, UInt cc_dst );
-static UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst );
-static UInt calculate_condition ( UInt/*Condcode*/ cond,
- UInt cc_op, UInt cc_src, UInt cc_dst );
-static UInt calculate_FXAM ( UInt tag, ULong dbl );
-static ULong calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz );
-
-/* --- DIRTY HELPERS --- */
-static ULong loadF80le ( UInt );
-static void storeF80le ( UInt, ULong );
-static void dirtyhelper_CPUID ( VexGuestX86State* );
-
/* This file contains helper functions for x86 guest code.
Calls to these functions are generated by the back end.
/* CALLED FROM GENERATED CODE: CLEAN HELPER */
/* Calculate all the 6 flags from the supplied thunk parameters. */
-static
UInt calculate_eflags_all ( UInt cc_op, UInt cc_src_formal, UInt cc_dst_formal )
{
# if PROFILE_EFLAGS
/* CALLED FROM GENERATED CODE: CLEAN HELPER */
/* Calculate just the carry flag from the supplied thunk parameters. */
-static UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst )
+UInt calculate_eflags_c ( UInt cc_op, UInt cc_src, UInt cc_dst )
{
/* Fast-case some common ones. */
switch (cc_op) {
}
-HWord x86guest_findhelper ( Char* function_name )
-{
- if (vex_streq(function_name, "calculate_condition"))
- return (HWord)(& calculate_condition);
- if (vex_streq(function_name, "calculate_eflags_c"))
- return (HWord)(& calculate_eflags_c);
- if (vex_streq(function_name, "calculate_eflags_all"))
- return (HWord)(& calculate_eflags_all);
- if (vex_streq(function_name, "calculate_FXAM"))
- return (HWord)(& calculate_FXAM);
- if (vex_streq(function_name, "storeF80le"))
- return (HWord)(& storeF80le);
- if (vex_streq(function_name, "loadF80le"))
- return (HWord)(& loadF80le);
- if (vex_streq(function_name, "calculate_RCR"))
- return (HWord)(& calculate_RCR);
- if (vex_streq(function_name, "dirtyhelper_CPUID"))
- return (HWord)(& dirtyhelper_CPUID);
- return 0; /* not found */
-}
-
/* Used by the optimiser to try specialisations. Returns an
equivalent expression, or NULL if none. */
}
/* CALLED FROM GENERATED CODE: CLEAN HELPER */
-static UInt calculate_FXAM ( UInt tag, ULong dbl )
+UInt calculate_FXAM ( UInt tag, ULong dbl )
{
Bool mantissaIsZero;
Int bexp;
/* CALLED FROM GENERATED CODE */
/* DIRTY HELPER (reads guest memory) */
-static ULong loadF80le ( UInt addrU )
+ULong loadF80le ( UInt addrU )
{
ULong f64;
convert_f80le_to_f64le ( (UChar*)addrU, (UChar*)&f64 );
/* CALLED FROM GENERATED CODE */
/* DIRTY HELPER (writes guest memory) */
-static void storeF80le ( UInt addrU, ULong f64 )
+void storeF80le ( UInt addrU, ULong f64 )
{
convert_f64le_to_f80le( (UChar*)&f64, (UChar*)addrU );
}
through the carry bit. Result in low 32 bits,
new flags (OSZACP) in high 32 bits.
*/
-static ULong calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz )
+ULong calculate_RCR ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz )
{
UInt tempCOUNT = rot_amt & 0x1F, cf=0, of=0, tempcf;
/* CALLED FROM GENERATED CODE */
/* DIRTY HELPER (modifies guest state) */
/* Claim to be a P54C P133 (pre-MMX Pentium) */
-static void dirtyhelper_CPUID ( VexGuestX86State* st )
+void dirtyhelper_CPUID ( VexGuestX86State* st )
{
if (st->guest_EAX == 0) {
st->guest_EAX = 0x1;
args[1] = IRExpr_Get(OFFB_CC_SRC, Ity_I32);
args[2] = IRExpr_Get(OFFB_CC_DST, Ity_I32);
args[3] = NULL;
- return IRExpr_CCall("calculate_eflags_all", Ity_I32, args);
+ return IRExpr_CCall(
+ mkIRCallee(0/*regparm*/, "calculate_eflags_all",
+ (HWord)&calculate_eflags_all),
+ Ity_I32,
+ args
+ );
}
/* Build IR to calculate just the carry flag from stored
args[1] = IRExpr_Get(OFFB_CC_SRC, Ity_I32);
args[2] = IRExpr_Get(OFFB_CC_DST, Ity_I32);
args[3] = NULL;
- return IRExpr_CCall("calculate_eflags_c", Ity_I32, args);
+ return IRExpr_CCall(
+ mkIRCallee(0/*regparm*/, "calculate_eflags_c",
+ (HWord)&calculate_eflags_c),
+ Ity_I32,
+ args
+ );
}
/* Build IR to calculate some particular condition from stored
CC_OP/CC_SRC/CC_DST. Returns an expression :: Ity_Bit. */
-static IRExpr* calculate_condition ( Condcode cond )
+static IRExpr* mk_calculate_condition ( Condcode cond )
{
IRExpr** args = LibVEX_Alloc(5 * sizeof(IRExpr*));
args[0] = mkU32(cond);
args[3] = IRExpr_Get(OFFB_CC_DST, Ity_I32);
args[4] = NULL;
return unop(Iop_32to1,
- IRExpr_CCall("calculate_condition", Ity_I32, args));
+ IRExpr_CCall(
+ mkIRCallee(0/*regparm*/, "calculate_condition",
+ (HWord)&calculate_condition),
+ Ity_I32,
+ args
+ )
+ );
}
Condcode condPos;
condPos = positiveIse_Condcode ( cond, &invert );
if (invert) {
- stmt( IRStmt_Exit( calculate_condition(condPos),
+ stmt( IRStmt_Exit( mk_calculate_condition(condPos),
IRConst_U32(d32_false) ) );
irbb->next = mkU32(d32_true);
irbb->jumpkind = Ijk_Boring;
} else {
- stmt( IRStmt_Exit( calculate_condition(condPos),
+ stmt( IRStmt_Exit( mk_calculate_condition(condPos),
IRConst_U32(d32_true) ) );
irbb->next = mkU32(d32_false);
irbb->jumpkind = Ijk_Boring;
IRTemp r64 = newTemp(Ity_I64);
IRExpr** args = LibVEX_Alloc(5 * sizeof(IRExpr*));
args[0] = widenUto32(mkexpr(dst0)); /* thing to rotate */
- args[1] = widenUto32(shift_expr); /* rotate amount */
+ args[1] = widenUto32(shift_expr); /* rotate amount */
args[2] = widenUto32(mk_calculate_eflags_all());
args[3] = mkU32(sz);
args[4] = NULL;
- assign( r64, IRExpr_CCall("calculate_RCR", Ity_I64, args) );
+ assign( r64, IRExpr_CCall(
+ mkIRCallee(0/*regparm*/, "calculate_RCR",
+ (HWord)&calculate_RCR),
+ Ity_I64,
+ args
+ ));
/* new eflags in hi half r64; new value in lo half r64 */
assign( dst1, narrowTo(ty, unop(Iop_64to32, mkexpr(r64))) );
stmt( IRStmt_Put( OFFB_CC_OP, mkU32(CC_OP_COPY) ));
if (cond == CondAlways) {
jmp_lit(Ijk_Boring,eip);
} else {
- stmt( IRStmt_Exit( calculate_condition(cond),
+ stmt( IRStmt_Exit( mk_calculate_condition(cond),
IRConst_U32(eip) ) );
jmp_lit(Ijk_Boring,eip_next);
}
args[0] = unop(Iop_8Uto32, get_ST_TAG(0));
args[1] = unop(Iop_ReinterpF64asI64, get_ST_UNCHECKED(0));
args[2] = NULL;
- put_C3210(IRExpr_CCall("calculate_FXAM", Ity_I32, args));
+ put_C3210(IRExpr_CCall(
+ mkIRCallee(0/*regparm*/, "calculate_FXAM",
+ (HWord)&calculate_FXAM),
+ Ity_I32,
+ args
+ ));
break;
}
DIP("fcmovz %%st(%d), %%st(0)", r_src);
put_ST_UNCHECKED(0,
IRExpr_Mux0X(
- unop(Iop_1Uto8,calculate_condition(CondZ)),
+ unop(Iop_1Uto8,mk_calculate_condition(CondZ)),
get_ST(0), get_ST(r_src)) );
break;
IRTemp val = newTemp(Ity_I64);
IRExpr** args = mkIRExprVec_1 ( mkexpr(addr) );
- IRDirty* d = unsafeIRDirty_1_N ( val, "loadF80le", args );
+ IRDirty* d = unsafeIRDirty_1_N (
+ val,
+ mkIRCallee(0, "loadF80le", (HWord)&loadF80le),
+ args
+ );
/* declare that we're reading memory */
d->mFx = Ifx_Read;
d->mAddr = mkexpr(addr);
= mkIRExprVec_2( mkexpr(addr),
unop(Iop_ReinterpF64asI64, get_ST(0)) );
- IRDirty* d = unsafeIRDirty_0_N ( "storeF80le", args );
+ IRDirty* d = unsafeIRDirty_0_N (
+ mkIRCallee(0, "storeF80le",
+ (HWord)&storeF80le),
+ args
+ );
/* declare we're writing memory */
d->mFx = Ifx_Write;
d->mAddr = mkexpr(addr);
DIP("fcmovnz %%st(%d), %%st(0)", r_src);
put_ST_UNCHECKED(0,
IRExpr_Mux0X(
- unop(Iop_1Uto8,calculate_condition(CondNZ)),
+ unop(Iop_1Uto8,mk_calculate_condition(CondNZ)),
get_ST(0), get_ST(r_src)) );
break;
assign( src, getIReg(size, gregOfRM(rm)) );
assign( acc, getIReg(size, R_EAX) );
setFlags_ADD_SUB(Iop_Sub8, dest, acc, ty);
- assign( cond8, unop(Iop_1Uto8, calculate_condition(CondZ)) );
+ assign( cond8, unop(Iop_1Uto8, mk_calculate_condition(CondZ)) );
assign( dest2, IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(src)) );
assign( acc2, IRExpr_Mux0X(mkexpr(cond8), mkexpr(dest), mkexpr(acc)) );
putIReg(size, R_EAX, mkexpr(acc2));
assign( tmpd, getIReg(sz, gregOfRM(rm)) );
putIReg(sz, gregOfRM(rm),
- IRExpr_Mux0X( unop(Iop_1Uto8,calculate_condition(cond)),
+ IRExpr_Mux0X( unop(Iop_1Uto8,mk_calculate_condition(cond)),
mkexpr(tmpd),
mkexpr(tmps) )
);
assign( tmpd, getIReg(sz, gregOfRM(rm)) );
putIReg(sz, gregOfRM(rm),
- IRExpr_Mux0X( unop(Iop_1Uto8,calculate_condition(cond)),
+ IRExpr_Mux0X( unop(Iop_1Uto8,mk_calculate_condition(cond)),
mkexpr(tmpd),
mkexpr(tmps) )
);
declared to mod eax, wr ebx, ecx, edx
*/
IRExpr** args = mkIRExprVec_0();
- IRDirty* d = unsafeIRDirty_0_N ( "dirtyhelper_CPUID", args );
+ IRDirty* d = unsafeIRDirty_0_N (
+ mkIRCallee(0, "dirtyhelper_CPUID",
+ (HWord)&dirtyhelper_CPUID),
+ args
+ );
/* declare guest state effects */
d->needsBBP = True;
d->nFxState = 4;
case 0x9E: /* set-LEb/set-NGb (jump less or equal) */
case 0x9F: /* set-Gb/set-NLEb (jump greater) */
t1 = newTemp(Ity_I8);
- assign( t1, unop(Iop_1Uto8,calculate_condition(opc-0x90)) );
+ assign( t1, unop(Iop_1Uto8,mk_calculate_condition(opc-0x90)) );
modrm = getIByte(delta);
if (epartIsReg(modrm)) {
delta++;
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*, HWord(*)(Char*),
- HWord(*)(Char*) );
+extern HInstrArray* iselBB_X86 ( IRBB* );
#endif /* ndef __LIBVEX_X86H_DEFS_H */
/* This carries around:
- - A function for looking up the address of vex front-end supplied
- helper functions.
-
- - A function for looking up the address of tool-supplied 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 {
- HWord (*find_helper_vex)(Char*);
- HWord (*find_helper_tool)(Char*);
-
IRTypeEnv* type_env;
HReg* vregmap;
}
-/* Find the address of a helper function, first by consulting vex's
- own front end, and if that doesn't work, by consulting the
- tool-supplied lookup function. */
-
-static
-HWord findHelper ( ISelEnv* env, Char* name )
-{
- HWord helper;
-
- /* Since the host -- for which we are generating code, and on which
- the helpers are compiled -- is a 32-bit machine (x86) -- HWord
- must be a 32-bit type. */
- vassert(sizeof(HWord) == 4);
-
- /* First see if vex's own front end has a binding for this fn. */
- helper = env->find_helper_vex(name);
-
- /* No? Try the tool-supplied function. */
- if (helper == 0 && env->find_helper_tool)
- helper = env->find_helper_tool(name);
-
- if (helper != 0)
- return helper;
-
- vex_printf("\nvex x86 back end: can't find helper: %s\n", name);
- vpanic("findHelper(x86,host)");
-}
-
-
/* Complete the call to a helper function, by calling the
helper and clearing the args off the stack. */
static
-void callHelperAndClearArgs ( ISelEnv* env, Char* name, Int n_arg_ws )
+void callHelperAndClearArgs ( ISelEnv* env, IRCallee* cee, Int n_arg_ws )
{
- HWord helper = findHelper( env, name );
vassert(sizeof(HWord) == 4);
-
addInstr(env, X86Instr_Alu32R(
Xalu_MOV,
- X86RMI_Imm(helper),
+ X86RMI_Imm(cee->addr),
hregX86_EAX()));
addInstr(env, X86Instr_Call(hregX86_EAX()));
if (n_arg_ws > 0)
n_arg_ws += pushArg(env, e->Iex.CCall.args[i]);
/* call the helper, and get the args off the stack afterwards. */
- callHelperAndClearArgs( env, e->Iex.CCall.name, n_arg_ws );
+ callHelperAndClearArgs( env, e->Iex.CCall.cee, n_arg_ws );
addInstr(env, mk_MOVsd_RR(hregX86_EAX(), dst));
return dst;
n_arg_ws += pushArg(env, e->Iex.CCall.args[i]);
/* call the helper, and get the args off the stack afterwards. */
- callHelperAndClearArgs( env, e->Iex.CCall.name, n_arg_ws );
+ callHelperAndClearArgs( env, e->Iex.CCall.cee, n_arg_ws );
addInstr(env, mk_MOVsd_RR(hregX86_EDX(), tHi));
addInstr(env, mk_MOVsd_RR(hregX86_EAX(), tLo));
}
/* call the helper, and get the args off the stack afterwards. */
- callHelperAndClearArgs( env, d->name, n_arg_ws );
+ callHelperAndClearArgs( env, d->cee, n_arg_ws );
/* Now figure out what to do with the returned value, if any. */
if (d->tmp == INVALID_IRTEMP)
/* Translate an entire BB to x86 code. */
-HInstrArray* iselBB_X86 ( IRBB* bb,
- HWord(*find_helper_vex)(Char*),
- HWord(*find_helper_tool)(Char*) )
+HInstrArray* iselBB_X86 ( IRBB* bb )
{
Int i, j;
HReg hreg, hregHI;
ISelEnv* env = LibVEX_Alloc(sizeof(ISelEnv));
env->vreg_ctr = 0;
- /* Register helper-function-finders. */
- env->find_helper_vex = find_helper_vex;
- env->find_helper_tool = find_helper_tool;
-
/* Set up output code array. */
env->code = newHInstrArray();
}
}
+void ppIRCallee ( IRCallee* ce )
+{
+ vex_printf("%s", ce->name);
+ if (ce->regparm > 0)
+ vex_printf("[%d]", ce->regparm);
+ vex_printf("{%p}", (void*)ce->addr);
+}
+
void ppIRArray ( IRArray* arr )
{
vex_printf("(%d:%dx", arr->base, arr->nElems);
ppIRConst(e->Iex.Const.con);
break;
case Iex_CCall:
- vex_printf("%s(", e->Iex.CCall.name);
+ ppIRCallee(e->Iex.CCall.cee);
+ vex_printf("(");
for (i = 0; e->Iex.CCall.args[i] != NULL; i++) {
ppIRExpr(e->Iex.CCall.args[i]);
if (e->Iex.CCall.args[i+1] != NULL)
ppIRTemp(d->tmp);
vex_printf(" = ");
}
- vex_printf("%s(", d->name);
+ ppIRCallee(d->cee);
+ vex_printf("(");
for (i = 0; d->args[i] != NULL; i++) {
ppIRExpr(d->args[i]);
if (d->args[i+1] != NULL) {
}
-/* Constructors -- IRExpr */
+/* Constructors -- IRCallee */
+
+IRCallee* mkIRCallee ( Int regparm, Char* name, HWord addr )
+{
+ IRCallee* ce = LibVEX_Alloc(sizeof(IRCallee));
+ ce->regparm = regparm;
+ ce->name = name;
+ ce->addr = addr;
+ vassert(regparm >= 0);
+ vassert(name != NULL);
+ vassert(addr != 0);
+ return ce;
+}
+
+
+/* Constructors -- IRArray */
IRArray* mkIRArray ( Int base, IRType elemTy, Int nElems )
{
e->Iex.Const.con = con;
return e;
}
-IRExpr* IRExpr_CCall ( Char* name, IRType retty, IRExpr** args ) {
+IRExpr* IRExpr_CCall ( IRCallee* cee, IRType retty, IRExpr** args ) {
IRExpr* e = LibVEX_Alloc(sizeof(IRExpr));
e->tag = Iex_CCall;
- e->Iex.CCall.name = name;
+ e->Iex.CCall.cee = cee;
e->Iex.CCall.retty = retty;
e->Iex.CCall.args = args;
return e;
IRDirty* emptyIRDirty ( void ) {
IRDirty* d = LibVEX_Alloc(sizeof(IRDirty));
- d->name = NULL;
+ d->cee = NULL;
d->args = NULL;
d->tmp = INVALID_IRTEMP;
d->mFx = Ifx_None;
return d;
}
-IRDirty* unsafeIRDirty_0_N ( Char* name, IRExpr** args ) {
+IRDirty* unsafeIRDirty_0_N ( IRCallee* cee, IRExpr** args ) {
IRDirty* d = emptyIRDirty();
- d->name = name;
+ d->cee = cee;
d->args = args;
return d;
}
-IRDirty* unsafeIRDirty_1_N ( IRTemp dst, Char* name, IRExpr** args ) {
+IRDirty* unsafeIRDirty_1_N ( IRTemp dst, IRCallee* cee, IRExpr** args ) {
IRDirty* d = emptyIRDirty();
- d->name = name;
+ d->cee = cee;
d->args = args;
d->tmp = dst;
return d;
}
}
+IRCallee* dopyIRCallee ( IRCallee* ce )
+{
+ return mkIRCallee(ce->regparm, ce->name, ce->addr);
+}
+
IRArray* dopyIRArray ( IRArray* d )
{
return mkIRArray(d->base, d->elemTy, d->nElems);
case Iex_Const:
return IRExpr_Const(dopyIRConst(e->Iex.Const.con));
case Iex_CCall:
- return IRExpr_CCall(e->Iex.CCall.name,
+ return IRExpr_CCall(dopyIRCallee(e->Iex.CCall.cee),
e->Iex.CCall.retty,
dopyIRExprVec(e->Iex.CCall.args));
{
Int i;
IRDirty* d2 = emptyIRDirty();
- d2->name = d->name;
+ d2->cee = dopyIRCallee(d->cee);
d2->args = dopyIRExprVec(d->args);
d2->tmp = d->tmp;
d2->mFx = d->mFx;
return True;
}
+static Bool saneIRCallee ( IRCallee* cee )
+{
+ if (cee->name == NULL)
+ return False;
+ if (cee->addr == 0)
+ return False;
+ if (cee->regparm < 0 || cee->regparm > 3)
+ return False;
+ return True;
+}
+
/* Traverse a Stmt/Expr, inspecting IRTemp uses. Report any out of
range ones. Report any which are read and for which the current
case Ist_Dirty:
/* Mostly check for various kinds of ill-formed dirty calls. */
d = stmt->Ist.Dirty.details;
- if (d->name == NULL) goto bad_dirty;
+ if (d->cee == NULL) goto bad_dirty;
+ if (!saneIRCallee(d->cee)) goto bad_dirty;
if (d->mFx == Ifx_None) {
if (d->mAddr != NULL || d->mSize != 0)
goto bad_dirty;
newargs[i] = flatten_Expr(bb, newargs[i]);
t1 = newIRTemp(bb->tyenv, ty);
addStmtToIRBB(bb, IRStmt_Tmp(t1,
- IRExpr_CCall(ex->Iex.CCall.name,
+ IRExpr_CCall(ex->Iex.CCall.cee,
ex->Iex.CCall.retty,
newargs)));
return IRExpr_Tmp(t1);
args2[i] = subst_Expr(env, args2[i]);
}
return IRExpr_CCall(
- ex->Iex.CCall.name,
+ ex->Iex.CCall.cee,
ex->Iex.CCall.retty,
args2
);
|| st->Ist.Tmp.data->tag != Iex_CCall)
continue;
- ex = (*specHelper)( st->Ist.Tmp.data->Iex.CCall.name,
+ ex = (*specHelper)( st->Ist.Tmp.data->Iex.CCall.cee->name,
st->Ist.Tmp.data->Iex.CCall.args );
if (!ex)
/* the front end can't think of a suitable replacement */
args2 = sopyIRExprVec(e->Iex.CCall.args);
for (i = 0; args2[i]; i++)
args2[i] = tbSubst_Expr(env,args2[i]);
- return IRExpr_CCall(e->Iex.CCall.name,
+ return IRExpr_CCall(e->Iex.CCall.cee,
e->Iex.CCall.retty,
args2
);
/* IN: optionally, two instrumentation functions. */
IRBB* (*instrument1) ( IRBB*, VexGuestLayoutInfo* ),
IRBB* (*instrument2) ( IRBB*, VexGuestLayoutInfo* ),
- HWord (*tool_findhelper) ( Char* ),
/* IN: optionally, an access check function for guest code. */
Bool (*byte_accessible) ( Addr64 ),
/* IN: debug: trace vex activity at various points */
HInstr* (*genReload) ( HReg, Int );
void (*ppInstr) ( HInstr* );
void (*ppReg) ( HReg );
- HInstrArray* (*iselBB) ( IRBB*, HWord(*)(Char*), HWord(*)(Char*) );
+ HInstrArray* (*iselBB) ( IRBB* );
IRBB* (*bbToIR) ( UChar*, Addr64, Int*,
Bool(*)(Addr64), Bool );
Int (*emit) ( UChar*, Int, HInstr* );
- HWord (*findHelper) ( Char* );
IRExpr* (*specHelper) ( Char*, IRExpr** );
Bool (*preciseMemExnsFn) ( Int, Int );
iselBB = NULL;
bbToIR = NULL;
emit = NULL;
- findHelper = NULL;
specHelper = NULL;
preciseMemExnsFn = NULL;
guest_word_size = Ity_INVALID;
case InsnSetX86:
preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
bbToIR = bbToIR_X86Instr;
- findHelper = x86guest_findhelper;
specHelper = x86guest_spechelper;
guest_sizeB = sizeof(VexGuestX86State);
guest_word_size = Ity_I32;
" Instruction selection "
"------------------------\n");
- vcode = iselBB ( irbb, findHelper, tool_findhelper );
+ vcode = iselBB ( irbb );
if (vex_traceflags & VEX_TRACE_VCODE)
vex_printf("\n");
/* IN: optionally, two instrumentation functions. */
IRBB* (*instrument1) ( IRBB*, VexGuestLayoutInfo* ),
IRBB* (*instrument2) ( IRBB*, VexGuestLayoutInfo* ),
- HWord (*tool_findhelper) ( Char* ),
/* IN: optionally, an access check function for guest code. */
Bool (*byte_accessible) ( Addr64 ),
/* IN: debug: trace vex activity at various points */
extern Bool eqIRConst ( IRConst*, IRConst* );
+/* ------------------ Call targets ------------------ */
+
+/* Describes a helper function to call. The name part is purely for
+ pretty printing and not actually used. regparm=n tells the back
+ end that the callee has been declared
+ "__attribute__((regparm(n)))". On some targets (x86) the back end
+ will need to construct a non-standard sequence to call a function
+ declared like this. */
+
+typedef
+ struct {
+ Int regparm;
+ Char* name;
+ HWord addr;
+ }
+ IRCallee;
+
+extern IRCallee* mkIRCallee ( Int regparm, Char* name, HWord addr );
+
+extern IRCallee* dopyIRCallee ( IRCallee* );
+
+extern void ppIRCallee ( IRCallee* );
+
+
/* ------------------ Guest state arrays ------------------ */
typedef
IRConst* con;
} Const;
struct {
- Char* name;
- IRType retty;
+ IRCallee* cee;
+ IRType retty;
struct _IRExpr** args;
} CCall;
struct {
extern IRExpr* IRExpr_Unop ( IROp op, IRExpr* arg );
extern IRExpr* IRExpr_LDle ( IRType ty, IRExpr* addr );
extern IRExpr* IRExpr_Const ( IRConst* con );
-extern IRExpr* IRExpr_CCall ( Char* name, IRType retty, IRExpr** args );
+extern IRExpr* IRExpr_CCall ( IRCallee* cee, IRType retty, IRExpr** args );
extern IRExpr* IRExpr_Mux0X ( IRExpr* cond, IRExpr* expr0, IRExpr* exprX );
extern IRExpr* dopyIRExpr ( IRExpr* );
typedef
struct {
/* What to call, and details of args/results */
- Char* name; /* name of the function to call */
- IRExpr** args; /* arg list, ends in NULL */
- IRTemp tmp; /* to assign result to, or INVALID_IRTEMP if none */
+ IRCallee* cee; /* where to call */
+ IRExpr** args; /* arg list, ends in NULL */
+ IRTemp tmp; /* to assign result to, or INVALID_IRTEMP if none */
/* Mem effects; we allow only one R/W/M region to be stated */
- IREffect mFx; /* indicates memory effects, if any */
- IRExpr* mAddr; /* of access, or NULL if mFx==Ifx_None */
- Int mSize; /* of access, or zero if mFx==Ifx_None */
+ IREffect mFx; /* indicates memory effects, if any */
+ IRExpr* mAddr; /* of access, or NULL if mFx==Ifx_None */
+ Int mSize; /* of access, or zero if mFx==Ifx_None */
/* Guest state effects; up to N allowed */
Bool needsBBP; /* True => also pass guest state ptr to callee */
any value. The call is marked as accessing neither guest state nor
memory (hence the "unsafe" designation) -- you can mess with this
later if need be.*/
-extern IRDirty* unsafeIRDirty_0_N ( Char* name, IRExpr** args );
+extern IRDirty* unsafeIRDirty_0_N ( IRCallee* cee, IRExpr** args );
/* Similarly, make a zero-annotation dirty call which returns a value,
and assign that to the given temp. */
-extern IRDirty* unsafeIRDirty_1_N ( IRTemp dst, Char* name, IRExpr** args );
+extern IRDirty* unsafeIRDirty_1_N ( IRTemp dst, IRCallee* cee, IRExpr** args );
/* ------------------ Statements ------------------ */