本文整理汇总了C++中x86_mov_reg_membase函数的典型用法代码示例。如果您正苦于以下问题:C++ x86_mov_reg_membase函数的具体用法?C++ x86_mov_reg_membase怎么用?C++ x86_mov_reg_membase使用的例子?那么, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了x86_mov_reg_membase函数的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: mono_arch_create_general_rgctx_lazy_fetch_trampoline
/*
* mono_arch_create_general_rgctx_lazy_fetch_trampoline:
*
* This is a general variant of the rgctx fetch trampolines. It receives a pointer to gpointer[2] in the rgctx reg. The first entry contains the slot, the second
* the trampoline to call if the slot is not filled.
*/
gpointer
mono_arch_create_general_rgctx_lazy_fetch_trampoline (MonoTrampInfo **info, gboolean aot)
{
guint8 *code, *buf;
int tramp_size;
MonoJumpInfo *ji = NULL;
GSList *unwind_ops = NULL;
g_assert (aot);
unwind_ops = mono_arch_get_cie_program ();
tramp_size = 64;
code = buf = mono_global_codeman_reserve (tramp_size);
// FIXME: Currently, we always go to the slow path.
/* Load trampoline addr */
x86_mov_reg_membase (code, X86_EAX, MONO_ARCH_RGCTX_REG, 4, 4);
/* Load mrgctx/vtable */
x86_mov_reg_membase (code, MONO_ARCH_VTABLE_REG, X86_ESP, 4, 4);
x86_jump_reg (code, X86_EAX);
mono_arch_flush_icache (buf, code - buf);
MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
g_assert (code - buf <= tramp_size);
*info = mono_tramp_info_create ("rgctx_fetch_trampoline_general", buf, code - buf, ji, unwind_ops);
return buf;
}
示例2: mono_arch_get_restore_context
/*
* mono_arch_get_restore_context:
*
* Returns a pointer to a method which restores a previously saved sigcontext.
*/
gpointer
mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
{
guint8 *start = NULL;
guint8 *code;
MonoJumpInfo *ji = NULL;
GSList *unwind_ops = NULL;
/* restore_contect (MonoContext *ctx) */
start = code = mono_global_codeman_reserve (128);
/* load ctx */
x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4);
/* get return address, stored in ECX */
x86_mov_reg_membase (code, X86_ECX, X86_EAX, G_STRUCT_OFFSET (MonoContext, eip), 4);
/* restore EBX */
x86_mov_reg_membase (code, X86_EBX, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebx), 4);
/* restore EDI */
x86_mov_reg_membase (code, X86_EDI, X86_EAX, G_STRUCT_OFFSET (MonoContext, edi), 4);
/* restore ESI */
x86_mov_reg_membase (code, X86_ESI, X86_EAX, G_STRUCT_OFFSET (MonoContext, esi), 4);
/* restore ESP */
x86_mov_reg_membase (code, X86_ESP, X86_EAX, G_STRUCT_OFFSET (MonoContext, esp), 4);
/* save the return addr to the restored stack */
x86_push_reg (code, X86_ECX);
/* restore EBP */
x86_mov_reg_membase (code, X86_EBP, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebp), 4);
/* restore ECX */
x86_mov_reg_membase (code, X86_ECX, X86_EAX, G_STRUCT_OFFSET (MonoContext, ecx), 4);
/* restore EDX */
x86_mov_reg_membase (code, X86_EDX, X86_EAX, G_STRUCT_OFFSET (MonoContext, edx), 4);
/* restore EAX */
x86_mov_reg_membase (code, X86_EAX, X86_EAX, G_STRUCT_OFFSET (MonoContext, eax), 4);
/* jump to the saved IP */
x86_ret (code);
nacl_global_codeman_validate(&start, 128, &code);
if (info)
*info = mono_tramp_info_create (g_strdup_printf ("restore_context"), start, code - start, ji, unwind_ops);
else {
GSList *l;
for (l = unwind_ops; l; l = l->next)
g_free (l->data);
g_slist_free (unwind_ops);
}
return start;
}
示例3: mono_tasklets_arch_restore
MonoContinuationRestore
mono_tasklets_arch_restore (void)
{
static guint8* saved = NULL;
guint8 *code, *start;
#ifdef __native_client_codegen__
g_print("mono_tasklets_arch_restore needs to be aligned for Native Client\n");
#endif
if (saved)
return (MonoContinuationRestore)saved;
code = start = mono_global_codeman_reserve (48);
/* the signature is: restore (MonoContinuation *cont, int state, MonoLMF **lmf_addr) */
/* put cont in edx */
x86_mov_reg_membase (code, X86_EDX, X86_ESP, 4, 4);
/* state in eax, so it's setup as the return value */
x86_mov_reg_membase (code, X86_EAX, X86_ESP, 8, 4);
/* setup the copy of the stack */
x86_mov_reg_membase (code, X86_ECX, X86_EDX, G_STRUCT_OFFSET (MonoContinuation, stack_used_size), 4);
x86_shift_reg_imm (code, X86_SHR, X86_ECX, 2);
x86_cld (code);
x86_mov_reg_membase (code, X86_ESI, X86_EDX, G_STRUCT_OFFSET (MonoContinuation, saved_stack), 4);
x86_mov_reg_membase (code, X86_EDI, X86_EDX, G_STRUCT_OFFSET (MonoContinuation, return_sp), 4);
x86_prefix (code, X86_REP_PREFIX);
x86_movsl (code);
/* now restore the registers from the LMF */
x86_mov_reg_membase (code, X86_ECX, X86_EDX, G_STRUCT_OFFSET (MonoContinuation, lmf), 4);
x86_mov_reg_membase (code, X86_EBX, X86_ECX, G_STRUCT_OFFSET (MonoLMF, ebx), 4);
x86_mov_reg_membase (code, X86_EBP, X86_ECX, G_STRUCT_OFFSET (MonoLMF, ebp), 4);
x86_mov_reg_membase (code, X86_ESI, X86_ECX, G_STRUCT_OFFSET (MonoLMF, esi), 4);
x86_mov_reg_membase (code, X86_EDI, X86_ECX, G_STRUCT_OFFSET (MonoLMF, edi), 4);
/* restore the lmf chain */
/*x86_mov_reg_membase (code, X86_ECX, X86_ESP, 12, 4);
x86_mov_membase_reg (code, X86_ECX, 0, X86_EDX, 4);*/
x86_jump_membase (code, X86_EDX, G_STRUCT_OFFSET (MonoContinuation, return_ip));
g_assert ((code - start) <= 48);
saved = start;
return (MonoContinuationRestore)saved;
}
示例4: mono_arch_get_restore_context
/*
* mono_arch_get_restore_context:
*
* Returns a pointer to a method which restores a previously saved sigcontext.
*/
gpointer
mono_arch_get_restore_context (void)
{
static guint8 *start = NULL;
guint8 *code;
if (start)
return start;
/* restore_contect (MonoContext *ctx) */
start = code = mono_global_codeman_reserve (128);
/* load ctx */
x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4);
/* get return address, stored in ECX */
x86_mov_reg_membase (code, X86_ECX, X86_EAX, G_STRUCT_OFFSET (MonoContext, eip), 4);
/* restore EBX */
x86_mov_reg_membase (code, X86_EBX, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebx), 4);
/* restore EDI */
x86_mov_reg_membase (code, X86_EDI, X86_EAX, G_STRUCT_OFFSET (MonoContext, edi), 4);
/* restore ESI */
x86_mov_reg_membase (code, X86_ESI, X86_EAX, G_STRUCT_OFFSET (MonoContext, esi), 4);
/* restore ESP */
x86_mov_reg_membase (code, X86_ESP, X86_EAX, G_STRUCT_OFFSET (MonoContext, esp), 4);
/* save the return addr to the restored stack */
x86_push_reg (code, X86_ECX);
/* restore EBP */
x86_mov_reg_membase (code, X86_EBP, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebp), 4);
/* restore ECX */
x86_mov_reg_membase (code, X86_ECX, X86_EAX, G_STRUCT_OFFSET (MonoContext, ecx), 4);
/* restore EDX */
x86_mov_reg_membase (code, X86_EDX, X86_EAX, G_STRUCT_OFFSET (MonoContext, edx), 4);
/* restore EAX */
x86_mov_reg_membase (code, X86_EAX, X86_EAX, G_STRUCT_OFFSET (MonoContext, eax), 4);
/* jump to the saved IP */
x86_ret (code);
return start;
}
示例5: mono_arch_get_call_filter
/*
* mono_arch_get_call_filter:
*
* Returns a pointer to a method which calls an exception filter. We
* also use this function to call finally handlers (we pass NULL as
* @exc object in this case).
*/
gpointer
mono_arch_get_call_filter (void)
{
static guint8* start;
static int inited = 0;
guint8 *code;
if (inited)
return start;
inited = 1;
/* call_filter (MonoContext *ctx, unsigned long eip) */
start = code = mono_global_codeman_reserve (64);
x86_push_reg (code, X86_EBP);
x86_mov_reg_reg (code, X86_EBP, X86_ESP, 4);
x86_push_reg (code, X86_EBX);
x86_push_reg (code, X86_EDI);
x86_push_reg (code, X86_ESI);
/* load ctx */
x86_mov_reg_membase (code, X86_EAX, X86_EBP, 8, 4);
/* load eip */
x86_mov_reg_membase (code, X86_ECX, X86_EBP, 12, 4);
/* save EBP */
x86_push_reg (code, X86_EBP);
/* set new EBP */
x86_mov_reg_membase (code, X86_EBP, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebp), 4);
/* restore registers used by global register allocation (EBX & ESI) */
x86_mov_reg_membase (code, X86_EBX, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebx), 4);
x86_mov_reg_membase (code, X86_ESI, X86_EAX, G_STRUCT_OFFSET (MonoContext, esi), 4);
x86_mov_reg_membase (code, X86_EDI, X86_EAX, G_STRUCT_OFFSET (MonoContext, edi), 4);
/* align stack and save ESP */
x86_mov_reg_reg (code, X86_EDX, X86_ESP, 4);
x86_alu_reg_imm (code, X86_AND, X86_ESP, -MONO_ARCH_FRAME_ALIGNMENT);
g_assert (MONO_ARCH_FRAME_ALIGNMENT >= 8);
x86_alu_reg_imm (code, X86_SUB, X86_ESP, MONO_ARCH_FRAME_ALIGNMENT - 8);
x86_push_reg (code, X86_EDX);
/* call the handler */
x86_call_reg (code, X86_ECX);
/* restore ESP */
x86_pop_reg (code, X86_ESP);
/* restore EBP */
x86_pop_reg (code, X86_EBP);
/* restore saved regs */
x86_pop_reg (code, X86_ESI);
x86_pop_reg (code, X86_EDI);
x86_pop_reg (code, X86_EBX);
x86_leave (code);
x86_ret (code);
g_assert ((code - start) < 64);
return start;
}
示例6: mono_tasklets_arch_restore
MonoContinuationRestore
mono_tasklets_arch_restore (void)
{
static guint8* saved = NULL;
guint8 *code, *start;
if (saved)
return (MonoContinuationRestore)saved;
code = start = mono_global_codeman_reserve (48);
/* the signature is: restore (MonoContinuation *cont, int state, MonoLMF **lmf_addr) */
/* put cont in edx */
x86_mov_reg_membase (code, X86_EDX, X86_ESP, 4, 4);
/* state in eax, so it's setup as the return value */
x86_mov_reg_membase (code, X86_EAX, X86_ESP, 8, 4);
/* lmf_addr in ebx */
x86_mov_reg_membase(code, X86_EBX, X86_ESP, 0x0C, 4);
/* setup the copy of the stack */
x86_mov_reg_membase (code, X86_ECX, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, stack_used_size), 4);
x86_shift_reg_imm (code, X86_SHR, X86_ECX, 2);
x86_cld (code);
x86_mov_reg_membase (code, X86_ESI, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, saved_stack), 4);
x86_mov_reg_membase (code, X86_EDI, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, return_sp), 4);
x86_prefix (code, X86_REP_PREFIX);
x86_movsl (code);
/* now restore the registers from the LMF */
x86_mov_reg_membase (code, X86_ECX, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, lmf), 4);
x86_mov_reg_membase (code, X86_EBP, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, ebp), 4);
x86_mov_reg_membase (code, X86_ESP, X86_ECX, MONO_STRUCT_OFFSET (MonoLMF, esp), 4);
/* restore the lmf chain */
/*x86_mov_reg_membase (code, X86_ECX, X86_ESP, 12, 4);
x86_mov_membase_reg (code, X86_ECX, 0, X86_EDX, 4);*/
x86_jump_membase (code, X86_EDX, MONO_STRUCT_OFFSET (MonoContinuation, return_ip));
mono_arch_flush_icache (start, code - start);
MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
g_assert ((code - start) <= 48);
saved = start;
return (MonoContinuationRestore)saved;
}
示例7: Check2DArrayAccess
/*
* Check a 2D array access operation for exception conditions.
*/
static void Check2DArrayAccess(MDUnroll *unroll, int reg, int reg2, int reg3,
unsigned char *pc, unsigned char *label)
{
#ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS
unsigned char *patch1;
#endif
unsigned char *patch2;
unsigned char *patch3;
#ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS
/* Check the array reference against NULL */
x86_alu_reg_reg(unroll->out, X86_OR, reg, reg);
patch1 = unroll->out;
x86_branch8(unroll->out, X86_CC_EQ, 0, 0);
#endif
/* Check the array bounds */
x86_alu_reg_membase(unroll->out, X86_SUB, reg2, reg, 12);
x86_alu_reg_membase(unroll->out, X86_CMP, reg2, reg, 16);
patch2 = unroll->out;
x86_branch32(unroll->out, X86_CC_LT, 0, 0);
x86_alu_reg_membase(unroll->out, X86_ADD, reg2, reg, 12);
patch3 = unroll->out;
x86_jump8(unroll->out, 0);
x86_patch(patch2, unroll->out);
x86_alu_reg_membase(unroll->out, X86_SUB, reg3, reg, 24);
x86_alu_reg_membase(unroll->out, X86_CMP, reg3, reg, 28);
patch2 = unroll->out;
x86_branch32(unroll->out, X86_CC_LT, 0, 0);
x86_alu_reg_membase(unroll->out, X86_ADD, reg2, reg, 12);
x86_alu_reg_membase(unroll->out, X86_ADD, reg3, reg, 28);
/* Re-execute the current instruction in the interpreter */
#ifndef IL_USE_INTERRUPT_BASED_NULL_POINTER_CHECKS
x86_patch(patch1, unroll->out);
#endif
x86_patch(patch3, unroll->out);
ReExecute(unroll, pc, label);
/* Compute the address of the array element */
x86_patch(patch2, unroll->out);
x86_imul_reg_membase(unroll->out, reg2, reg, 20);
x86_imul_reg_membase(unroll->out, reg3, reg, 32);
x86_alu_reg_reg(unroll->out, X86_ADD, reg2, reg3);
x86_imul_reg_membase(unroll->out, reg2, reg, 4);
x86_mov_reg_membase(unroll->out, reg, reg, 8, 4);
x86_alu_reg_reg(unroll->out, X86_ADD, reg, reg2);
}
示例8: mono_win32_get_handle_stackoverflow
/*
* mono_win32_get_handle_stackoverflow (void):
*
* Returns a pointer to a method which restores the current context stack
* and calls handle_exceptions, when done restores the original stack.
*/
static gpointer
mono_win32_get_handle_stackoverflow (void)
{
static guint8 *start = NULL;
guint8 *code;
if (start)
return start;
/* restore_contect (void *sigctx) */
start = code = mono_global_codeman_reserve (128);
/* load context into ebx */
x86_mov_reg_membase (code, X86_EBX, X86_ESP, 4, 4);
/* move current stack into edi for later restore */
x86_mov_reg_reg (code, X86_EDI, X86_ESP, 4);
/* use the new freed stack from sigcontext */
x86_mov_reg_membase (code, X86_ESP, X86_EBX, G_STRUCT_OFFSET (struct sigcontext, esp), 4);
/* get the current domain */
x86_call_code (code, mono_domain_get);
/* get stack overflow exception from domain object */
x86_mov_reg_membase (code, X86_EAX, X86_EAX, G_STRUCT_OFFSET (MonoDomain, stack_overflow_ex), 4);
/* call mono_arch_handle_exception (sctx, stack_overflow_exception_obj, FALSE) */
x86_push_imm (code, 0);
x86_push_reg (code, X86_EAX);
x86_push_reg (code, X86_EBX);
x86_call_code (code, mono_arch_handle_exception);
/* restore the SEH handler stack */
x86_mov_reg_reg (code, X86_ESP, X86_EDI, 4);
/* return */
x86_ret (code);
return start;
}
示例9: get_throw_exception
/*
* get_throw_exception:
*
* Generate a call to mono_x86_throw_exception/
* mono_x86_throw_corlib_exception.
* If LLVM is true, generate code which assumes the caller is LLVM generated code,
* which doesn't push the arguments.
*/
static guint8*
get_throw_exception (const char *name, gboolean rethrow, gboolean llvm, gboolean corlib)
{
guint8 *start, *code;
GSList *unwind_ops = NULL;
int i, stack_size, stack_offset, arg_offsets [5], regs_offset;
start = code = mono_global_codeman_reserve (128);
stack_size = 128;
/*
* On apple, the stack is misaligned by the pushing of the return address.
*/
if (!llvm && corlib)
/* On OSX, we don't generate alignment code to save space */
stack_size += 4;
else
stack_size += MONO_ARCH_FRAME_ALIGNMENT - 4;
/*
* The stack looks like this:
* <pc offset> (only if corlib is TRUE)
* <exception object>/<type token>
* <return addr> <- esp (unaligned on apple)
*/
mono_add_unwind_op_def_cfa (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_ESP, 4);
mono_add_unwind_op_offset (unwind_ops, (guint8*)NULL, (guint8*)NULL, X86_NREG, -4);
/* Alloc frame */
x86_alu_reg_imm (code, X86_SUB, X86_ESP, stack_size);
mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, stack_size + 4);
arg_offsets [0] = 0;
arg_offsets [1] = 4;
arg_offsets [2] = 8;
arg_offsets [3] = 12;
regs_offset = 16;
/* Save registers */
for (i = 0; i < X86_NREG; ++i)
if (i != X86_ESP)
x86_mov_membase_reg (code, X86_ESP, regs_offset + (i * 4), i, 4);
/* Calculate the offset between the current sp and the sp of the caller */
if (llvm) {
/* LLVM doesn't push the arguments */
stack_offset = stack_size + 4;
} else {
if (corlib) {
/* Two arguments */
stack_offset = stack_size + 4 + 8;
#ifdef __APPLE__
/* We don't generate stack alignment code on osx to save space */
#endif
} else {
/* One argument */
stack_offset = stack_size + 4 + 4;
#ifdef __APPLE__
/* Pop the alignment added by OP_THROW too */
stack_offset += MONO_ARCH_FRAME_ALIGNMENT - 4;
#endif
}
}
/* Save ESP */
x86_lea_membase (code, X86_EAX, X86_ESP, stack_offset);
x86_mov_membase_reg (code, X86_ESP, regs_offset + (X86_ESP * 4), X86_EAX, 4);
/* Set arg1 == regs */
x86_lea_membase (code, X86_EAX, X86_ESP, regs_offset);
x86_mov_membase_reg (code, X86_ESP, arg_offsets [0], X86_EAX, 4);
/* Set arg2 == exc */
x86_mov_reg_membase (code, X86_EAX, X86_ESP, stack_size + 4, 4);
x86_mov_membase_reg (code, X86_ESP, arg_offsets [1], X86_EAX, 4);
/* Set arg3 == eip */
x86_mov_reg_membase (code, X86_EAX, X86_ESP, stack_size, 4);
x86_mov_membase_reg (code, X86_ESP, arg_offsets [2], X86_EAX, 4);
if (corlib) {
/* Set arg4 == offset */
x86_mov_reg_membase (code, X86_EAX, X86_ESP, stack_size + 8, 4);
x86_mov_membase_reg (code, X86_ESP, arg_offsets [3], X86_EAX, 4);
} else {
/* Set arg4 == rethrow */
x86_mov_membase_imm (code, X86_ESP, arg_offsets [3], rethrow, 4);
}
/* Make the call */
x86_call_code (code, corlib ? (gpointer)mono_x86_throw_corlib_exception : (gpointer)mono_x86_throw_exception);
x86_breakpoint (code);
g_assert ((code - start) < 128);
mono_save_trampoline_xdebug_info (corlib ? "llvm_throw_corlib_exception_trampoline" : "llvm_throw_exception_trampoline", start, code - start, unwind_ops);
//.........这里部分代码省略.........
示例10: mono_arch_get_gsharedvt_trampoline
gpointer
mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
{
guint8 *code, *buf;
int buf_len, cfa_offset;
GSList *unwind_ops = NULL;
MonoJumpInfo *ji = NULL;
guint8 *br_out, *br [16];
int info_offset, mrgctx_offset;
buf_len = 320;
buf = code = mono_global_codeman_reserve (buf_len);
/*
* This trampoline is responsible for marshalling calls between normal code and gsharedvt code. The
* caller is a normal or gshared method which uses the signature of the inflated method to make the call, while
* the callee is a gsharedvt method which has a signature which uses valuetypes in place of type parameters, i.e.
* caller:
* foo<bool> (bool b)
* callee:
* T=<type used to represent vtype type arguments, currently TypedByRef>
* foo<T> (T b)
* The trampoline is responsible for marshalling the arguments and marshalling the result back. To simplify
* things, we create our own stack frame, and do most of the work in a C function, which receives a
* GSharedVtCallInfo structure as an argument. The structure should contain information to execute the C function to
* be as fast as possible. The argument is received in EAX from a gsharedvt trampoline. So the real
* call sequence looks like this:
* caller -> gsharedvt trampoline -> gsharevt in trampoline -> start_gsharedvt_call
* FIXME: Optimize this.
*/
cfa_offset = sizeof (gpointer);
mono_add_unwind_op_def_cfa (unwind_ops, code, buf, X86_ESP, cfa_offset);
mono_add_unwind_op_offset (unwind_ops, code, buf, X86_NREG, -cfa_offset);
x86_push_reg (code, X86_EBP);
cfa_offset += sizeof (gpointer);
mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
mono_add_unwind_op_offset (unwind_ops, code, buf, X86_EBP, - cfa_offset);
x86_mov_reg_reg (code, X86_EBP, X86_ESP, sizeof (gpointer));
mono_add_unwind_op_def_cfa_reg (unwind_ops, code, buf, X86_EBP);
/* Alloc stack frame/align stack */
x86_alu_reg_imm (code, X86_SUB, X86_ESP, 8);
info_offset = -4;
mrgctx_offset = - 8;
/* The info struct is put into EAX by the gsharedvt trampoline */
/* Save info struct addr */
x86_mov_membase_reg (code, X86_EBP, info_offset, X86_EAX, 4);
/* Save rgctx */
x86_mov_membase_reg (code, X86_EBP, mrgctx_offset, MONO_ARCH_RGCTX_REG, 4);
/* Allocate stack area used to pass arguments to the method */
x86_mov_reg_membase (code, X86_EAX, X86_EAX, MONO_STRUCT_OFFSET (GSharedVtCallInfo, stack_usage), sizeof (gpointer));
x86_alu_reg_reg (code, X86_SUB, X86_ESP, X86_EAX);
#if 0
/* Stack alignment check */
x86_mov_reg_reg (code, X86_ECX, X86_ESP, 4);
x86_alu_reg_imm (code, X86_AND, X86_ECX, MONO_ARCH_FRAME_ALIGNMENT - 1);
x86_alu_reg_imm (code, X86_CMP, X86_ECX, 0);
x86_branch_disp (code, X86_CC_EQ, 3, FALSE);
x86_breakpoint (code);
#endif
/* ecx = caller argument area */
x86_mov_reg_reg (code, X86_ECX, X86_EBP, 4);
x86_alu_reg_imm (code, X86_ADD, X86_ECX, 8);
/* eax = callee argument area */
x86_mov_reg_reg (code, X86_EAX, X86_ESP, 4);
/* Call start_gsharedvt_call */
/* Arg 4 */
x86_push_membase (code, X86_EBP, mrgctx_offset);
/* Arg3 */
x86_push_reg (code, X86_EAX);
/* Arg2 */
x86_push_reg (code, X86_ECX);
/* Arg1 */
x86_push_membase (code, X86_EBP, info_offset);
if (aot) {
code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_x86_start_gsharedvt_call");
x86_call_reg (code, X86_EAX);
} else {
x86_call_code (code, mono_x86_start_gsharedvt_call);
}
x86_alu_reg_imm (code, X86_ADD, X86_ESP, 4 * 4);
/* The address to call is in eax */
/* The stack is now setup for the real call */
/* Load info struct */
x86_mov_reg_membase (code, X86_ECX, X86_EBP, info_offset, 4);
/* Load rgctx */
x86_mov_reg_membase (code, MONO_ARCH_RGCTX_REG, X86_EBP, mrgctx_offset, sizeof (gpointer));
/* Make the call */
x86_call_reg (code, X86_EAX);
/* The return value is either in registers, or stored to an area beginning at sp [info->vret_slot] */
/* EAX/EDX might contain the return value, only ECX is free */
/* Load info struct */
x86_mov_reg_membase (code, X86_ECX, X86_EBP, info_offset, 4);
/* Branch to the in/out handling code */
x86_alu_membase_imm (code, X86_CMP, X86_ECX, MONO_STRUCT_OFFSET (GSharedVtCallInfo, gsharedvt_in), 1);
//.........这里部分代码省略.........
示例11: Divide
/*
* Perform an integer division or remainder.
*/
static void Divide(MDUnroll *unroll, int isSigned, int wantRemainder,
unsigned char *pc, unsigned char *label)
{
#if !defined(IL_USE_INTERRUPT_BASED_INT_DIVIDE_BY_ZERO_CHECKS)
#define IL_NEED_DIVIDE_REEXECUTE 1
unsigned char *patch1;
#endif
#if !defined(IL_USE_INTERRUPT_BASED_INT_OVERFLOW_CHECKS)
#define IL_NEED_DIVIDE_REEXECUTE 1
unsigned char *patch2, *patch3;
#endif
/* Get the arguments into EAX and ECX so we know where they are */
if(unroll->pseudoStackSize != 2 ||
unroll->pseudoStack[0] != X86_EAX ||
unroll->pseudoStack[1] != X86_ECX)
{
FlushRegisterStack(unroll);
unroll->stackHeight -= 8;
x86_mov_reg_membase(unroll->out, X86_EAX, MD_REG_STACK,
unroll->stackHeight, 4);
x86_mov_reg_membase(unroll->out, X86_ECX, MD_REG_STACK,
unroll->stackHeight + 4, 4);
unroll->pseudoStack[0] = X86_EAX;
unroll->pseudoStack[1] = X86_ECX;
unroll->pseudoStackSize = 2;
unroll->regsUsed |= ((1 << X86_EAX) | (1 << X86_ECX));
}
/* Check for conditions that may cause an exception */
#if !defined(IL_USE_INTERRUPT_BASED_INT_DIVIDE_BY_ZERO_CHECKS)
x86_alu_reg_imm(unroll->out, X86_CMP, X86_ECX, 0);
patch1 = unroll->out;
x86_branch8(unroll->out, X86_CC_EQ, 0, 0);
#endif
#if !defined(IL_USE_INTERRUPT_BASED_INT_OVERFLOW_CHECKS)
x86_alu_reg_imm(unroll->out, X86_CMP, X86_ECX, -1);
patch2 = unroll->out;
x86_branch32(unroll->out, X86_CC_NE, 0, 0);
x86_alu_reg_imm(unroll->out, X86_CMP, X86_EAX, (int)0x80000000);
patch3 = unroll->out;
x86_branch32(unroll->out, X86_CC_NE, 0, 0);
#endif
#if !defined(IL_USE_INTERRUPT_BASED_INT_DIVIDE_BY_ZERO_CHECKS)
x86_patch(patch1, unroll->out);
#endif
#if defined(IL_NEED_DIVIDE_REEXECUTE)
/* Re-execute the division instruction to throw the exception */
ReExecute(unroll, pc, label);
#endif
#if !defined(IL_USE_INTERRUPT_BASED_INT_OVERFLOW_CHECKS)
x86_patch(patch2, unroll->out);
x86_patch(patch3, unroll->out);
#endif
/* Perform the division */
if(isSigned)
{
x86_cdq(unroll->out);
}
else
{
x86_clear_reg(unroll->out, X86_EDX);
}
x86_div_reg(unroll->out, X86_ECX, isSigned);
/* Pop ECX from the pseudo stack */
FreeTopRegister(unroll, -1);
/* If we want the remainder, then replace EAX with EDX on the stack */
if(wantRemainder)
{
unroll->pseudoStack[0] = X86_EDX;
unroll->regsUsed = (1 << X86_EDX);
}
}
示例12: mono_arch_create_rgctx_lazy_fetch_trampoline
gpointer
mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot)
{
guint8 *tramp;
guint8 *code, *buf;
guint8 **rgctx_null_jumps;
int tramp_size;
int depth, index;
int i;
gboolean mrgctx;
MonoJumpInfo *ji = NULL;
GSList *unwind_ops = NULL;
unwind_ops = mono_arch_get_cie_program ();
mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
index = MONO_RGCTX_SLOT_INDEX (slot);
if (mrgctx)
index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (target_mgreg_t);
for (depth = 0; ; ++depth) {
int size = mono_class_rgctx_get_array_size (depth, mrgctx);
if (index < size - 1)
break;
index -= size - 1;
}
tramp_size = (aot ? 64 : 36) + 6 * depth;
code = buf = mono_global_codeman_reserve (tramp_size);
rgctx_null_jumps = g_malloc (sizeof (guint8*) * (depth + 2));
/* load vtable/mrgctx ptr */
x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4);
if (!mrgctx) {
/* load rgctx ptr from vtable */
x86_mov_reg_membase (code, X86_EAX, X86_EAX, MONO_STRUCT_OFFSET (MonoVTable, runtime_generic_context), 4);
/* is the rgctx ptr null? */
x86_test_reg_reg (code, X86_EAX, X86_EAX);
/* if yes, jump to actual trampoline */
rgctx_null_jumps [0] = code;
x86_branch8 (code, X86_CC_Z, -1, 1);
}
for (i = 0; i < depth; ++i) {
/* load ptr to next array */
if (mrgctx && i == 0)
x86_mov_reg_membase (code, X86_EAX, X86_EAX, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT, 4);
else
x86_mov_reg_membase (code, X86_EAX, X86_EAX, 0, 4);
/* is the ptr null? */
x86_test_reg_reg (code, X86_EAX, X86_EAX);
/* if yes, jump to actual trampoline */
rgctx_null_jumps [i + 1] = code;
x86_branch8 (code, X86_CC_Z, -1, 1);
}
/* fetch slot */
x86_mov_reg_membase (code, X86_EAX, X86_EAX, sizeof (target_mgreg_t) * (index + 1), 4);
/* is the slot null? */
x86_test_reg_reg (code, X86_EAX, X86_EAX);
/* if yes, jump to actual trampoline */
rgctx_null_jumps [depth + 1] = code;
x86_branch8 (code, X86_CC_Z, -1, 1);
/* otherwise return */
x86_ret (code);
for (i = mrgctx ? 1 : 0; i <= depth + 1; ++i)
x86_patch (rgctx_null_jumps [i], code);
g_free (rgctx_null_jumps);
x86_mov_reg_membase (code, MONO_ARCH_VTABLE_REG, X86_ESP, 4, 4);
if (aot) {
code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_SPECIFIC_TRAMPOLINE_LAZY_FETCH_ADDR, GUINT_TO_POINTER (slot));
x86_jump_reg (code, X86_EAX);
} else {
tramp = (guint8*)mono_arch_create_specific_trampoline (GUINT_TO_POINTER (slot), MONO_TRAMPOLINE_RGCTX_LAZY_FETCH, mono_get_root_domain (), NULL);
/* jump to the actual trampoline */
x86_jump_code (code, tramp);
}
mono_arch_flush_icache (buf, code - buf);
MONO_PROFILER_RAISE (jit_code_buffer, (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL));
g_assert (code - buf <= tramp_size);
char *name = mono_get_rgctx_fetch_trampoline_name (slot);
*info = mono_tramp_info_create (name, buf, code - buf, ji, unwind_ops);
g_free (name);
return buf;
}
示例13: mono_arch_create_generic_trampoline
guchar*
mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInfo **info, gboolean aot)
{
const char *tramp_name;
guint8 *buf, *code, *tramp, *br_ex_check;
GSList *unwind_ops = NULL;
MonoJumpInfo *ji = NULL;
int i, offset, frame_size, regarray_offset, lmf_offset, caller_ip_offset, arg_offset;
int cfa_offset; /* cfa = cfa_reg + cfa_offset */
code = buf = mono_global_codeman_reserve (256);
/* Note that there is a single argument to the trampoline
* and it is stored at: esp + pushed_args * sizeof (target_mgreg_t)
* the ret address is at: esp + (pushed_args + 1) * sizeof (target_mgreg_t)
*/
/* Compute frame offsets relative to the frame pointer %ebp */
arg_offset = sizeof (target_mgreg_t);
caller_ip_offset = 2 * sizeof (target_mgreg_t);
offset = 0;
offset += sizeof (MonoLMF);
lmf_offset = -offset;
offset += X86_NREG * sizeof (target_mgreg_t);
regarray_offset = -offset;
/* Argument area */
offset += 4 * sizeof (target_mgreg_t);
frame_size = ALIGN_TO (offset, MONO_ARCH_FRAME_ALIGNMENT);
/* ret addr and arg are on the stack */
cfa_offset = 2 * sizeof (target_mgreg_t);
mono_add_unwind_op_def_cfa (unwind_ops, code, buf, X86_ESP, cfa_offset);
// IP saved at CFA - 4
mono_add_unwind_op_offset (unwind_ops, code, buf, X86_NREG, -4);
/* Allocate frame */
x86_push_reg (code, X86_EBP);
cfa_offset += sizeof (target_mgreg_t);
mono_add_unwind_op_def_cfa_offset (unwind_ops, code, buf, cfa_offset);
mono_add_unwind_op_offset (unwind_ops, code, buf, X86_EBP, -cfa_offset);
x86_mov_reg_reg (code, X86_EBP, X86_ESP);
mono_add_unwind_op_def_cfa_reg (unwind_ops, code, buf, X86_EBP);
/* There are three words on the stack, adding + 4 aligns the stack to 16, which is needed on osx */
x86_alu_reg_imm (code, X86_SUB, X86_ESP, frame_size + sizeof (target_mgreg_t));
/* Save all registers */
for (i = X86_EAX; i <= X86_EDI; ++i) {
int reg = i;
if (i == X86_EBP) {
/* Save original ebp */
/* EAX is already saved */
x86_mov_reg_membase (code, X86_EAX, X86_EBP, 0, sizeof (target_mgreg_t));
reg = X86_EAX;
} else if (i == X86_ESP) {
/* Save original esp */
/* EAX is already saved */
x86_mov_reg_reg (code, X86_EAX, X86_EBP);
/* Saved ebp + trampoline arg + return addr */
x86_alu_reg_imm (code, X86_ADD, X86_EAX, 3 * sizeof (target_mgreg_t));
reg = X86_EAX;
}
x86_mov_membase_reg (code, X86_EBP, regarray_offset + (i * sizeof (target_mgreg_t)), reg, sizeof (target_mgreg_t));
}
/* Setup LMF */
/* eip */
if (tramp_type == MONO_TRAMPOLINE_JUMP) {
x86_mov_membase_imm (code, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, eip), 0, sizeof (target_mgreg_t));
} else {
x86_mov_reg_membase (code, X86_EAX, X86_EBP, caller_ip_offset, sizeof (target_mgreg_t));
x86_mov_membase_reg (code, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, eip), X86_EAX, sizeof (target_mgreg_t));
}
/* method */
if ((tramp_type == MONO_TRAMPOLINE_JIT) || (tramp_type == MONO_TRAMPOLINE_JUMP)) {
x86_mov_reg_membase (code, X86_EAX, X86_EBP, arg_offset, sizeof (target_mgreg_t));
x86_mov_membase_reg (code, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, method), X86_EAX, sizeof (target_mgreg_t));
} else {
x86_mov_membase_imm (code, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, method), 0, sizeof (target_mgreg_t));
}
/* esp */
x86_mov_reg_membase (code, X86_EAX, X86_EBP, regarray_offset + (X86_ESP * sizeof (target_mgreg_t)), sizeof (target_mgreg_t));
x86_mov_membase_reg (code, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, esp), X86_EAX, sizeof (target_mgreg_t));
/* callee save registers */
x86_mov_reg_membase (code, X86_EAX, X86_EBP, regarray_offset + (X86_EBX * sizeof (target_mgreg_t)), sizeof (target_mgreg_t));
x86_mov_membase_reg (code, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, ebx), X86_EAX, sizeof (target_mgreg_t));
x86_mov_reg_membase (code, X86_EAX, X86_EBP, regarray_offset + (X86_EDI * sizeof (target_mgreg_t)), sizeof (target_mgreg_t));
x86_mov_membase_reg (code, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, edi), X86_EAX, sizeof (target_mgreg_t));
x86_mov_reg_membase (code, X86_EAX, X86_EBP, regarray_offset + (X86_ESI * sizeof (target_mgreg_t)), sizeof (target_mgreg_t));
x86_mov_membase_reg (code, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, esi), X86_EAX, sizeof (target_mgreg_t));
x86_mov_reg_membase (code, X86_EAX, X86_EBP, regarray_offset + (X86_EBP * sizeof (target_mgreg_t)), sizeof (target_mgreg_t));
x86_mov_membase_reg (code, X86_EBP, lmf_offset + G_STRUCT_OFFSET (MonoLMF, ebp), X86_EAX, sizeof (target_mgreg_t));
/* Push LMF */
/* get the address of lmf for the current thread */
if (aot) {
code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_get_lmf_addr");
x86_call_reg (code, X86_EAX);
//.........这里部分代码省略.........
示例14: _jit_gen_epilog
//.........这里部分代码省略.........
/* The this is in ECX register */
if(pop_bytes > (1 * sizeof(void *)))
{
pop_bytes -= 1 * sizeof(void *);
}
else
{
pop_bytes = 0;
}
struct_return_offset = 0;
}
}
else if(!(func->nested_parent) &&
jit_type_return_via_pointer(jit_type_get_return(signature)))
{
#if JIT_APPLY_X86_POP_STRUCT_RETURN == 1
pop_bytes += sizeof(void *);
#endif
struct_return_offset = 2 * sizeof(void *);
}
}
#else
{
/* We only need to pop structure pointers in non-nested functions */
jit_type_t signature;
signature = func->signature;
if(!(func->nested_parent) &&
jit_type_return_via_pointer(jit_type_get_return(signature)))
{
#if JIT_APPLY_X86_POP_STRUCT_RETURN == 1
pop_bytes += sizeof(void *);
#endif
struct_return_offset = 2 * sizeof(void *);
}
}
#endif
/* Perform fixups on any blocks that jump to the epilog */
inst = gen->posn.ptr;
fixup = (void **)(gen->epilog_fixup);
while(fixup != 0)
{
next = (void **)(fixup[0]);
fixup[0] = (void *)(((jit_nint)inst) - ((jit_nint)fixup) - 4);
fixup = next;
}
gen->epilog_fixup = 0;
/* If we are returning a structure via a pointer, then copy
the pointer value into EAX when we return */
if(struct_return_offset != 0)
{
x86_mov_reg_membase(inst, X86_EAX, X86_EBP, struct_return_offset, 4);
}
/* Restore the callee save registers that we used */
if(gen->stack_changed)
{
offset = -(func->builder->frame_size);
for(reg = 0; reg <= 7; ++reg)
{
if(jit_reg_is_used(gen->touched, reg) &&
(_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
{
offset -= sizeof(void *);
x86_mov_reg_membase(inst, _jit_reg_info[reg].cpu_reg,
X86_EBP, offset, sizeof(void *));
}
}
}
else
{
for(reg = 7; reg >= 0; --reg)
{
if(jit_reg_is_used(gen->touched, reg) &&
(_jit_reg_info[reg].flags & JIT_REG_CALL_USED) == 0)
{
x86_pop_reg(inst, _jit_reg_info[reg].cpu_reg);
}
}
}
/* Pop the stack frame and restore the saved copy of ebp */
if(gen->stack_changed || func->builder->frame_size > 0)
{
x86_mov_reg_reg(inst, X86_ESP, X86_EBP, sizeof(void *));
}
x86_pop_reg(inst, X86_EBP);
/* Return from the current function */
if(pop_bytes > 0)
{
x86_ret_imm(inst, pop_bytes);
}
else
{
x86_ret(inst);
}
gen->posn.ptr = inst;
}
示例15: mono_arch_get_restore_context
/*
* mono_arch_get_restore_context:
*
* Returns a pointer to a method which restores a previously saved sigcontext.
*/
gpointer
mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
{
guint8 *start = NULL;
guint8 *code;
MonoJumpInfo *ji = NULL;
GSList *unwind_ops = NULL;
/* restore_contect (MonoContext *ctx) */
start = code = mono_global_codeman_reserve (128);
/* load ctx */
x86_mov_reg_membase (code, X86_EAX, X86_ESP, 4, 4);
/* restore EBX */
x86_mov_reg_membase (code, X86_EBX, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebx), 4);
/* restore EDI */
x86_mov_reg_membase (code, X86_EDI, X86_EAX, G_STRUCT_OFFSET (MonoContext, edi), 4);
/* restore ESI */
x86_mov_reg_membase (code, X86_ESI, X86_EAX, G_STRUCT_OFFSET (MonoContext, esi), 4);
/* restore EDX */
x86_mov_reg_membase (code, X86_EDX, X86_EAX, G_STRUCT_OFFSET (MonoContext, edx), 4);
/*
* The context resides on the stack, in the stack frame of the
* caller of this function. The stack pointer that we need to
* restore is potentially many stack frames higher up, so the
* distance between them can easily be more than the red zone
* size. Hence the stack pointer can be restored only after
* we have finished loading everything from the context.
*/
/* load ESP into EBP */
x86_mov_reg_membase (code, X86_EBP, X86_EAX, G_STRUCT_OFFSET (MonoContext, esp), 4);
/* Align it, it can be unaligned if it was captured asynchronously */
x86_alu_reg_imm (code, X86_AND, X86_EBP, ~(MONO_ARCH_LOCALLOC_ALIGNMENT - 1));
/* load return address into ECX */
x86_mov_reg_membase (code, X86_ECX, X86_EAX, G_STRUCT_OFFSET (MonoContext, eip), 4);
/* save the return addr to the restored stack - 4 */
x86_mov_membase_reg (code, X86_EBP, -4, X86_ECX, 4);
/* load EBP into ECX */
x86_mov_reg_membase (code, X86_ECX, X86_EAX, G_STRUCT_OFFSET (MonoContext, ebp), 4);
/* save EBP to the restored stack - 8 */
x86_mov_membase_reg (code, X86_EBP, -8, X86_ECX, 4);
/* load EAX into ECX */
x86_mov_reg_membase (code, X86_ECX, X86_EAX, G_STRUCT_OFFSET (MonoContext, eax), 4);
/* save EAX to the restored stack - 12 */
x86_mov_membase_reg (code, X86_EBP, -12, X86_ECX, 4);
/* restore ECX */
x86_mov_reg_membase (code, X86_ECX, X86_EAX, G_STRUCT_OFFSET (MonoContext, ecx), 4);
/* restore ESP - 12 */
x86_lea_membase (code, X86_ESP, X86_EBP, -12);
/* restore EAX */
x86_pop_reg (code, X86_EAX);
/* restore EBP */
x86_pop_reg (code, X86_EBP);
/* jump to the saved IP */
x86_ret (code);
nacl_global_codeman_validate(&start, 128, &code);
if (info)
*info = mono_tramp_info_create ("restore_context", start, code - start, ji, unwind_ops);
else {
GSList *l;
for (l = unwind_ops; l; l = l->next)
g_free (l->data);
g_slist_free (unwind_ops);
}
return start;
}