gpointer mono_arch_get_unbox_trampoline (MonoGenericSharingContext *gsctx, MonoMethod *method, gpointer addr) { guint8 *code, *start; int this_pos = s390_r2; MonoDomain *domain = mono_domain_get (); start = addr; if (MONO_TYPE_ISSTRUCT (mono_method_signature (method)->ret)) this_pos = s390_r3; start = code = mono_domain_code_reserve (domain, 28); s390_basr (code, s390_r13, 0); s390_j (code, 4); s390_word (code, addr); s390_l (code, s390_r1, 0, s390_r13, 4); s390_ahi (code, this_pos, sizeof(MonoObject)); s390_br (code, s390_r1); g_assert ((code - start) <= 28); mono_arch_flush_icache (start, code - start); return start; }
gpointer mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len) { guint8 *code, *buf, *tramp; gint32 displace; tramp = mono_get_trampoline_code (tramp_type); /*----------------------------------------------------------*/ /* This is the method-specific part of the trampoline. Its */ /* purpose is to provide the generic part with the */ /* MonoMethod *method pointer. We'll use r1 to keep it. */ /*----------------------------------------------------------*/ code = buf = mono_domain_code_reserve (domain, SPECIFIC_TRAMPOLINE_SIZE); s390_basr (buf, s390_r1, 0); s390_j (buf, 6); s390_llong(buf, arg1); s390_lg (buf, s390_r1, 0, s390_r1, 4); displace = (tramp - buf) / 2; s390_jcl (buf, S390_CC_UN, displace); /* Flush instruction cache, since we've generated code */ mono_arch_flush_icache (code, buf - code); /* Sanity check */ g_assert ((buf - code) <= SPECIFIC_TRAMPOLINE_SIZE); if (code_len) *code_len = buf - code; return code; }
gpointer mono_arch_get_static_rgctx_trampoline (MonoMethod *m, MonoMethodRuntimeGenericContext *mrgctx, gpointer addr) { guint8 *code, *start; gint32 displace; int buf_len; MonoDomain *domain = mono_domain_get (); buf_len = 32; start = code = mono_domain_code_reserve (domain, buf_len); s390_basr (code, s390_r1, 0); s390_j (code, 6); s390_llong(code, mrgctx); s390_lg (code, MONO_ARCH_RGCTX_REG, 0, s390_r1, 4); displace = ((uintptr_t) addr - (uintptr_t) code) / 2; s390_jg (code, displace); g_assert ((code - start) < buf_len); mono_arch_flush_icache (start, code - start); return(start); }
gpointer mono_arch_get_unbox_trampoline (MonoMethod *method, gpointer addr) { guint8 *code, *start; int this_pos = s390_r2; MonoDomain *domain = mono_domain_get (); start = code = mono_domain_code_reserve (domain, 28); s390_basr (code, s390_r1, 0); s390_j (code, 6); s390_llong(code, addr); s390_lg (code, s390_r1, 0, s390_r1, 4); s390_aghi (code, this_pos, sizeof(MonoObject)); s390_br (code, s390_r1); g_assert ((code - start) <= 28); mono_arch_flush_icache (start, code - start); return start; }
guchar* mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInfo **info, gboolean aot) { guint8 *buf, *tramp, *code; int i, offset, lmfOffset; g_assert (!aot); if (info) *info = NULL; /* Now we'll create in 'buf' the S/390 trampoline code. This is the trampoline code common to all methods */ code = buf = mono_global_codeman_reserve(512); /*----------------------------------------------------------- STEP 0: First create a non-standard function prologue with a stack size big enough to save our registers. -----------------------------------------------------------*/ s390_stmg (buf, s390_r6, s390_r15, STK_BASE, S390_REG_SAVE_OFFSET); s390_lgr (buf, s390_r11, s390_r15); s390_aghi (buf, STK_BASE, -CREATE_STACK_SIZE); s390_stg (buf, s390_r11, 0, STK_BASE, 0); s390_stg (buf, s390_r1, 0, STK_BASE, METHOD_SAVE_OFFSET); s390_stmg (buf, s390_r2, s390_r5, STK_BASE, CREATE_GR_OFFSET); /* Save the FP registers */ offset = CREATE_FP_OFFSET; for (i = s390_f0; i <= s390_f15; ++i) { s390_std (buf, i, 0, STK_BASE, offset); offset += 8; } /*---------------------------------------------------------- STEP 1: call 'mono_get_lmf_addr()' to get the address of our LMF. We'll need to restore it after the call to 's390_magic_trampoline' and before the call to the native method. ----------------------------------------------------------*/ s390_basr (buf, s390_r13, 0); s390_j (buf, 6); s390_llong(buf, mono_get_lmf_addr); s390_lg (buf, s390_r1, 0, s390_r13, 4); s390_basr (buf, s390_r14, s390_r1); /*---------------------------------------------------------------*/ /* we build the MonoLMF structure on the stack - see mini-s390.h */ /* Keep in sync with the code in mono_arch_emit_prolog */ /*---------------------------------------------------------------*/ lmfOffset = CREATE_STACK_SIZE - sizeof(MonoLMF); s390_lgr (buf, s390_r13, STK_BASE); s390_aghi (buf, s390_r13, lmfOffset); /*---------------------------------------------------------------*/ /* Set lmf.lmf_addr = jit_tls->lmf */ /*---------------------------------------------------------------*/ s390_stg (buf, s390_r2, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, lmf_addr)); /*---------------------------------------------------------------*/ /* Get current lmf */ /*---------------------------------------------------------------*/ s390_lg (buf, s390_r0, 0, s390_r2, 0); /*---------------------------------------------------------------*/ /* Set our lmf as the current lmf */ /*---------------------------------------------------------------*/ s390_stg (buf, s390_r13, 0, s390_r2, 0); /*---------------------------------------------------------------*/ /* Have our lmf.previous_lmf point to the last lmf */ /*---------------------------------------------------------------*/ s390_stg (buf, s390_r0, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, previous_lmf)); /*---------------------------------------------------------------*/ /* save method info */ /*---------------------------------------------------------------*/ s390_lg (buf, s390_r1, 0, STK_BASE, METHOD_SAVE_OFFSET); s390_stg (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, method)); /*---------------------------------------------------------------*/ /* save the current SP */ /*---------------------------------------------------------------*/ s390_lg (buf, s390_r1, 0, STK_BASE, 0); s390_stg (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp)); /*---------------------------------------------------------------*/ /* save the current IP */ /*---------------------------------------------------------------*/ if (tramp_type == MONO_TRAMPOLINE_JUMP) { s390_lghi (buf, s390_r1, 0); } else { s390_lg (buf, s390_r1, 0, s390_r1, S390_RET_ADDR_OFFSET); // s390_la (buf, s390_r1, 0, s390_r1, 0); } s390_stg (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip)); /*---------------------------------------------------------------*/ /* Save general and floating point registers */ /*---------------------------------------------------------------*/ s390_mvc (buf, 4*sizeof(gulong), s390_r13, G_STRUCT_OFFSET(MonoLMF, gregs[2]), STK_BASE, CREATE_GR_OFFSET); s390_mvc (buf, 10*sizeof(gulong), s390_r13, G_STRUCT_OFFSET(MonoLMF, gregs[6]), s390_r11, S390_REG_SAVE_OFFSET); /* Simply copy fpregs already saved above */ s390_mvc (buf, 16*sizeof(double), s390_r13, G_STRUCT_OFFSET(MonoLMF, fregs[0]), STK_BASE, CREATE_FP_OFFSET); /*---------------------------------------------------------------*/ /* STEP 2: call the C trampoline function */ /*---------------------------------------------------------------*/ /* Set arguments */ /* Arg 1: mgreg_t *regs. We pass sp instead */ s390_la (buf, s390_r2, 0, STK_BASE, CREATE_STACK_SIZE); /* Arg 2: code (next address to the instruction that called us) */ if (tramp_type == MONO_TRAMPOLINE_JUMP) { s390_lghi (buf, s390_r3, 0); } else { s390_lg (buf, s390_r3, 0, s390_r11, S390_RET_ADDR_OFFSET); } /* Arg 3: MonoMethod *method. It was put in r1 by the method-specific trampoline code, and then saved before the call to mono_get_lmf_addr()'. */ s390_lg (buf, s390_r4, 0, STK_BASE, METHOD_SAVE_OFFSET); /* Arg 4: trampoline address. Ignore for now */ /* Calculate call address and call the C trampoline. Return value will be in r2 */ s390_basr (buf, s390_r13, 0); s390_j (buf, 6); tramp = (guint8*)mono_get_trampoline_func (tramp_type); s390_llong (buf, tramp); s390_lg (buf, s390_r1, 0, s390_r13, 4); s390_basr (buf, s390_r14, s390_r1); /* OK, code address is now on r2. Move it to r1, so that we can restore r2 and use it from r1 later */ s390_lgr (buf, s390_r1, s390_r2); /*---------------------------------------------------------- STEP 3: Restore the LMF ----------------------------------------------------------*/ restoreLMF(buf, STK_BASE, CREATE_STACK_SIZE); /*---------------------------------------------------------- STEP 4: call the compiled method ----------------------------------------------------------*/ /* Restore registers */ s390_lmg (buf, s390_r2, s390_r5, STK_BASE, CREATE_GR_OFFSET); /* Restore the FP registers */ offset = CREATE_FP_OFFSET; for (i = s390_f0; i <= s390_f15; ++i) { s390_ld (buf, i, 0, STK_BASE, offset); offset += 8; } /* Restore stack pointer and jump to the code - R14 contains the return address to our caller */ s390_lgr (buf, STK_BASE, s390_r11); s390_lmg (buf, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT || tramp_type == MONO_TRAMPOLINE_GENERIC_CLASS_INIT) s390_br (buf, s390_r14); else s390_br (buf, s390_r1); /* Flush instruction cache, since we've generated code */ mono_arch_flush_icache (code, buf - code); /* Sanity check */ g_assert ((buf - code) <= 512); return code; }
guchar* mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInfo **info, gboolean aot) { char *tramp_name; guint8 *buf, *tramp, *code; int i, offset, has_caller; GSList *unwind_ops = NULL; MonoJumpInfo *ji = NULL; g_assert (!aot); /* Now we'll create in 'buf' the S/390 trampoline code. This is the trampoline code common to all methods */ code = buf = mono_global_codeman_reserve(512); if ((tramp_type == MONO_TRAMPOLINE_JUMP) || (tramp_type == MONO_TRAMPOLINE_HANDLER_BLOCK_GUARD)) has_caller = 0; else has_caller = 1; /*----------------------------------------------------------- STEP 0: First create a non-standard function prologue with a stack size big enough to save our registers. -----------------------------------------------------------*/ s390_stmg (buf, s390_r6, s390_r15, STK_BASE, S390_REG_SAVE_OFFSET); s390_lgr (buf, s390_r11, s390_r15); s390_aghi (buf, STK_BASE, -sizeof(trampStack_t)); s390_stg (buf, s390_r11, 0, STK_BASE, 0); /*---------------------------------------------------------------*/ /* we build the MonoLMF structure on the stack - see mini-s390.h */ /* Keep in sync with the code in mono_arch_emit_prolog */ /*---------------------------------------------------------------*/ s390_lgr (buf, LMFReg, STK_BASE); s390_aghi (buf, LMFReg, G_STRUCT_OFFSET(trampStack_t, LMF)); /*---------------------------------------------------------------*/ /* Save general and floating point registers in LMF */ /*---------------------------------------------------------------*/ s390_stmg (buf, s390_r0, s390_r1, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[0])); s390_stmg (buf, s390_r2, s390_r5, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[2])); s390_mvc (buf, 10*sizeof(gulong), LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[6]), s390_r11, S390_REG_SAVE_OFFSET); offset = G_STRUCT_OFFSET(MonoLMF, fregs[0]); for (i = s390_f0; i <= s390_f15; ++i) { s390_std (buf, i, 0, LMFReg, offset); offset += sizeof(gdouble); } /*---------------------------------------------------------- STEP 1: call 'mono_get_lmf_addr()' to get the address of our LMF. We'll need to restore it after the call to 's390_magic_trampoline' and before the call to the native method. ----------------------------------------------------------*/ S390_SET (buf, s390_r1, mono_get_lmf_addr); s390_basr (buf, s390_r14, s390_r1); /*---------------------------------------------------------------*/ /* Set lmf.lmf_addr = jit_tls->lmf */ /*---------------------------------------------------------------*/ s390_stg (buf, s390_r2, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, lmf_addr)); /*---------------------------------------------------------------*/ /* Get current lmf */ /*---------------------------------------------------------------*/ s390_lg (buf, s390_r0, 0, s390_r2, 0); /*---------------------------------------------------------------*/ /* Set our lmf as the current lmf */ /*---------------------------------------------------------------*/ s390_stg (buf, LMFReg, 0, s390_r2, 0); /*---------------------------------------------------------------*/ /* Have our lmf.previous_lmf point to the last lmf */ /*---------------------------------------------------------------*/ s390_stg (buf, s390_r0, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, previous_lmf)); /*---------------------------------------------------------------*/ /* save method info */ /*---------------------------------------------------------------*/ s390_lg (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[1])); s390_stg (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, method)); /*---------------------------------------------------------------*/ /* save the current SP */ /*---------------------------------------------------------------*/ s390_lg (buf, s390_r1, 0, STK_BASE, 0); s390_stg (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, ebp)); /*---------------------------------------------------------------*/ /* save the current IP */ /*---------------------------------------------------------------*/ if (has_caller) { s390_lg (buf, s390_r1, 0, s390_r1, S390_RET_ADDR_OFFSET); } else { s390_lghi (buf, s390_r1, 0); } s390_stg (buf, s390_r1, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, eip)); /*---------------------------------------------------------------*/ /* STEP 2: call the C trampoline function */ /*---------------------------------------------------------------*/ /* Set arguments */ /* Arg 1: mgreg_t *regs */ s390_la (buf, s390_r2, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[0])); /* Arg 2: code (next address to the instruction that called us) */ if (has_caller) { s390_lg (buf, s390_r3, 0, s390_r11, S390_RET_ADDR_OFFSET); } else { s390_lghi (buf, s390_r3, 0); } /* Arg 3: Trampoline argument */ if (tramp_type == MONO_TRAMPOLINE_GENERIC_CLASS_INIT) s390_lg (buf, s390_r4, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[MONO_ARCH_VTABLE_REG])); else s390_lg (buf, s390_r4, 0, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[1])); /* Arg 4: trampoline address. */ S390_SET (buf, s390_r5, buf); /* Calculate call address and call the C trampoline. Return value will be in r2 */ tramp = (guint8*)mono_get_trampoline_func (tramp_type); S390_SET (buf, s390_r1, tramp); s390_basr (buf, s390_r14, s390_r1); /* OK, code address is now on r2. Move it to r1, so that we can restore r2 and use it from r1 later */ s390_lgr (buf, s390_r1, s390_r2); /*---------------------------------------------------------- STEP 3: Restore the LMF ----------------------------------------------------------*/ restoreLMF(buf, STK_BASE, sizeof(trampStack_t)); /*---------------------------------------------------------- STEP 4: call the compiled method ----------------------------------------------------------*/ /* Restore parameter registers */ s390_lmg (buf, s390_r2, s390_r5, LMFReg, G_STRUCT_OFFSET(MonoLMF, gregs[2])); /* Restore the FP registers */ offset = G_STRUCT_OFFSET(MonoLMF, fregs[0]); for (i = s390_f0; i <= s390_f15; ++i) { s390_ld (buf, i, 0, LMFReg, offset); offset += sizeof(gdouble); } /* Restore stack pointer and jump to the code - * R14 contains the return address to our caller */ s390_lgr (buf, STK_BASE, s390_r11); s390_lmg (buf, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); if (MONO_TRAMPOLINE_TYPE_MUST_RETURN(tramp_type)) { s390_lgr (buf, s390_r2, s390_r1); s390_br (buf, s390_r14); } else { s390_br (buf, s390_r1); } /* Flush instruction cache, since we've generated code */ mono_arch_flush_icache (code, buf - code); mono_profiler_code_buffer_new (buf, code - buf, MONO_PROFILER_CODE_BUFFER_GENERICS_TRAMPOLINE, NULL); g_assert (info); tramp_name = mono_get_generic_trampoline_name (tramp_type); *info = mono_tramp_info_create (tramp_name, buf, buf - code, ji, unwind_ops); g_free (tramp_name); /* Sanity check */ g_assert ((buf - code) <= 512); return code; }
void * mono_arch_create_method_pointer (MonoMethod *method) { MonoMethodSignature *sig; MonoJitInfo *ji; guint8 *p, *code_buffer; guint i, align = 0, simple_type, retSize, reg_save = 0, stackval_arg_pos, local_pos, float_pos, local_start, reg_param = 0, stack_param, this_flag, arg_pos, fpr_param, parSize; guint32 simpletype; size_data sz; int *vtbuf, cpos, vt_cur; sz.code_size = 1024; sz.stack_size = 1024; stack_param = 0; fpr_param = 0; arg_pos = 0; sig = method->signature; p = code_buffer = g_malloc (sz.code_size); DEBUG (printf ("\nDelegate [start emiting] %s at 0x%08x\n", method->name,p)); /*----------------------------------------------------------*/ /* prolog */ /*----------------------------------------------------------*/ s390_stmg(p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET); s390_lg (p, s390_r7, 0, STK_BASE, MINV_POS); s390_lgr (p, s390_r0, STK_BASE); s390_aghi(p, STK_BASE, -(sz.stack_size+MINV_POS)); s390_stg (p, s390_r0, 0, STK_BASE, 0); s390_la (p, s390_r8, 0, STK_BASE, 4); s390_lgr (p, s390_r10, s390_r8); s390_lghi(p, s390_r9, sz.stack_size+92); s390_lghi(p, s390_r11, 0); s390_mvcl(p, s390_r8, s390_r10); /*----------------------------------------------------------*/ /* Let's fill MonoInvocation - first zero some fields */ /*----------------------------------------------------------*/ s390_lghi (p, s390_r0, 0); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex))); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler))); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent))); s390_lghi (p, s390_r0, 1); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, invoke_trap))); /*----------------------------------------------------------*/ /* set method pointer */ /*----------------------------------------------------------*/ s390_bras (p, s390_r13, 4); s390_llong(p, method); s390_lg (p, s390_r0, 0, s390_r13, 0); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method))); local_start = local_pos = MINV_POS + sizeof (MonoInvocation) + (sig->param_count + 1) * sizeof (stackval); this_flag = (sig->hasthis ? 1 : 0); /*----------------------------------------------------------*/ /* if we are returning a structure, checks it's length to */ /* see if there's a "hidden" parameter that points to the */ /* area. If necessary save this hidden parameter for later */ /*----------------------------------------------------------*/ if (MONO_TYPE_ISSTRUCT(sig->ret)) { if (sig->pinvoke) retSize = mono_class_native_size (sig->ret->data.klass, &align); else retSize = mono_class_value_size (sig->ret->data.klass, &align); switch(retSize) { case 0: case 1: case 2: case 4: case 8: sz.retStruct = 0; break; default: sz.retStruct = 1; s390_lgr(p, s390_r8, s390_r2); reg_save = 1; } } else { reg_save = 0; } if (this_flag) { s390_stg (p, s390_r2 + reg_save, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj))); reg_param++; } else { s390_stg (p, s390_r2 + reg_save, 0, STK_BASE, local_pos); local_pos += sizeof(int); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj))); } s390_stmg (p, s390_r3 + reg_param, s390_r6, STK_BASE, local_pos); local_pos += 4 * sizeof(long); float_pos = local_pos; s390_std (p, s390_f0, 0, STK_BASE, local_pos); local_pos += sizeof(double); s390_std (p, s390_f2, 0, STK_BASE, local_pos); local_pos += sizeof(double); /*----------------------------------------------------------*/ /* prepare space for valuetypes */ /*----------------------------------------------------------*/ vt_cur = local_pos; vtbuf = alloca (sizeof(int)*sig->param_count); cpos = 0; for (i = 0; i < sig->param_count; i++) { MonoType *type = sig->params [i]; vtbuf [i] = -1; DEBUG(printf("par: %d type: %d ref: %d\n",i,type->type,type->byref)); if (type->type == MONO_TYPE_VALUETYPE) { MonoClass *klass = type->data.klass; gint size; if (klass->enumtype) continue; size = mono_class_native_size (klass, &align); cpos += align - 1; cpos &= ~(align - 1); vtbuf [i] = cpos; cpos += size; } } cpos += 3; cpos &= ~3; local_pos += cpos; /*----------------------------------------------------------*/ /* set MonoInvocation::stack_args */ /*----------------------------------------------------------*/ stackval_arg_pos = MINV_POS + sizeof (MonoInvocation); s390_la (p, s390_r0, 0, STK_BASE, stackval_arg_pos); s390_stg (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args))); /*----------------------------------------------------------*/ /* add stackval arguments */ /*----------------------------------------------------------*/ for (i = 0; i < sig->param_count; ++i) { if (sig->params [i]->byref) { ADD_ISTACK_PARM(0, 1); } else { simple_type = sig->params [i]->type; enum_savechk: switch (simple_type) { case MONO_TYPE_I8: ADD_ISTACK_PARM(-1, 2); break; case MONO_TYPE_R4: ADD_RSTACK_PARM(1); break; case MONO_TYPE_R8: ADD_RSTACK_PARM(2); break; case MONO_TYPE_VALUETYPE: if (sig->params [i]->data.klass->enumtype) { simple_type = sig->params [i]->data.klass->enum_basetype->type; goto enum_savechk; } if (sig->pinvoke) parSize = mono_class_native_size (sig->params [i]->data.klass, &align); else parSize = mono_class_value_size (sig->params [i]->data.klass, &align); switch(parSize) { case 0: case 1: case 2: case 4: ADD_PSTACK_PARM(0, 1); break; case 8: ADD_PSTACK_PARM(-1, 2); break; default: ADD_TSTACK_PARM; } break; default: ADD_ISTACK_PARM(0, 1); } } if (vtbuf [i] >= 0) { s390_la (p, s390_r3, 0, STK_BASE, vt_cur); s390_stg (p, s390_r3, 0, STK_BASE, stackval_arg_pos); s390_la (p, s390_r3, 0, STK_BASE, stackval_arg_pos); vt_cur += vtbuf [i]; } else { s390_la (p, s390_r3, 0, STK_BASE, stackval_arg_pos); } /*--------------------------------------*/ /* Load the parameter registers for the */ /* call to stackval_from_data */ /*--------------------------------------*/ s390_bras (p, s390_r13, 8); s390_llong(p, sig->params [i]); s390_llong(p, sig->pinvoke); s390_llong(p, stackval_from_data); s390_lg (p, s390_r2, 0, s390_r13, 0); s390_lg (p, s390_r5, 0, s390_r13, 4); s390_lg (p, s390_r1, 0, s390_r13, 8); s390_basr (p, s390_r14, s390_r1); stackval_arg_pos += sizeof(stackval); /* fixme: alignment */ DEBUG (printf ("arg_pos %d --> ", arg_pos)); if (sig->pinvoke) arg_pos += mono_type_native_stack_size (sig->params [i], &align); else arg_pos += mono_type_stack_size (sig->params [i], &align); DEBUG (printf ("%d\n", stackval_arg_pos)); } /*----------------------------------------------------------*/ /* Set return area pointer. */ /*----------------------------------------------------------*/ s390_la (p, s390_r10, 0, STK_BASE, stackval_arg_pos); s390_stg(p, s390_r10, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval))); if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) { MonoClass *klass = sig->ret->data.klass; if (!klass->enumtype) { s390_la (p, s390_r9, 0, s390_r10, sizeof(stackval)); s390_st (p, s390_r9, 0,STK_BASE, stackval_arg_pos); stackval_arg_pos += sizeof(stackval); } } /*----------------------------------------------------------*/ /* call ves_exec_method */ /*----------------------------------------------------------*/ s390_bras (p, s390_r13, 4); s390_llong(p, ves_exec_method); s390_lg (p, s390_r1, 0, s390_r13, 0); s390_la (p, s390_r2, 0, STK_BASE, MINV_POS); s390_basr (p, s390_r14, s390_r1); /*----------------------------------------------------------*/ /* move retval from stackval to proper place (r3/r4/...) */ /*----------------------------------------------------------*/ DEBUG(printf("retType: %d byRef: %d\n",sig->ret->type,sig->ret->byref)); if (sig->ret->byref) { DEBUG (printf ("ret by ref\n")); s390_stg(p, s390_r2, 0, s390_r10, 0); } else { enum_retvalue: switch (sig->ret->type) { case MONO_TYPE_VOID: break; case MONO_TYPE_BOOLEAN: case MONO_TYPE_U1: s390_lghi(p, s390_r2, 0); s390_ic (p, s390_r2, 0, s390_r10, 0); break; case MONO_TYPE_I2: case MONO_TYPE_U2: s390_lh (p, s390_r2, 0,s390_r10, 0); break; case MONO_TYPE_I4: case MONO_TYPE_U4: case MONO_TYPE_I: case MONO_TYPE_U: s390_lgf(p, s390_r2, 0, s390_r10, 0); break; case MONO_TYPE_OBJECT: case MONO_TYPE_STRING: case MONO_TYPE_CLASS: case MONO_TYPE_I8: s390_lg (p, s390_r2, 0, s390_r10, 0); break; case MONO_TYPE_R4: s390_le (p, s390_f0, 0, s390_r10, 0); break; case MONO_TYPE_R8: s390_ld (p, s390_f0, 0, s390_r10, 0); break; case MONO_TYPE_VALUETYPE: if (sig->ret->data.klass->enumtype) { simpletype = sig->ret->data.klass->enum_basetype->type; goto enum_retvalue; } /*---------------------------------*/ /* Call stackval_to_data to return */ /* the structure */ /*---------------------------------*/ s390_bras (p, s390_r13, 8); s390_llong(p, sig->ret); s390_llong(p, sig->pinvoke); s390_llong(p, stackval_to_data); s390_lg (p, s390_r2, 0, s390_r13, 0); s390_lg (p, s390_r3, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval))); if (sz.retStruct) { /*------------------------------------------*/ /* Get stackval_to_data to set result area */ /*------------------------------------------*/ s390_lgr (p, s390_r4, s390_r8); } else { /*------------------------------------------*/ /* Give stackval_to_data a temp result area */ /*------------------------------------------*/ s390_la (p, s390_r4, 0, STK_BASE, stackval_arg_pos); } s390_lg (p, s390_r5, 0,s390_r13, 4); s390_lg (p, s390_r1, 0, s390_r13, 8); s390_basr (p, s390_r14, s390_r1); switch (retSize) { case 0: break; case 1: s390_lghi(p, s390_r2, 0); s390_ic (p, s390_r2, 0, s390_r10, 0); break; case 2: s390_lh (p, s390_r2, 0, s390_r10, 0); break; case 4: s390_lgf(p, s390_r2, 0, s390_r10, 0); break; case 8: s390_lg (p, s390_r2, 0, s390_r10, 0); break; default: ; /*-------------------------------------------------*/ /* stackval_to_data has placed data in result area */ /*-------------------------------------------------*/ } break; default: g_error ("Type 0x%x not handled yet in thunk creation", sig->ret->type); break; } } /*----------------------------------------------------------*/ /* epilog */ /*----------------------------------------------------------*/ s390_lg (p, STK_BASE, 0, STK_BASE, 0); s390_lg (p, s390_r4, 0, STK_BASE, S390_RET_ADDR_OFFSET); s390_lmg (p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET); s390_br (p, s390_r4); DEBUG (printf ("emited code size: %d\n", p - code_buffer)); DEBUG (printf ("Delegate [end emiting]\n")); ji = g_new0 (MonoJitInfo, 1); ji->method = method; ji->code_size = p - code_buffer; ji->code_start = code_buffer; mono_jit_info_table_add (mono_get_root_domain (), ji); return ji->code_start; }
static inline guint8 * emit_call_and_store_retval (guint8 *p, MonoMethodSignature *sig, size_data *sz, gboolean string_ctor) { guint32 simpletype; guint retSize, align; /* call "callme" */ s390_basr (p, s390_r14, s390_r9); /* get return value */ if (sig->ret->byref || string_ctor) { s390_stg(p, s390_r2, 0, s390_r8, 0); } else { simpletype = sig->ret->type; enum_retvalue: switch (simpletype) { case MONO_TYPE_BOOLEAN: case MONO_TYPE_I1: case MONO_TYPE_U1: s390_stc (p, s390_r2, 0, s390_r8, 0); break; case MONO_TYPE_I2: case MONO_TYPE_U2: case MONO_TYPE_CHAR: s390_sth (p, s390_r2, 0, s390_r8, 0); break; case MONO_TYPE_I4: case MONO_TYPE_U4: case MONO_TYPE_I: case MONO_TYPE_U: case MONO_TYPE_CLASS: case MONO_TYPE_OBJECT: case MONO_TYPE_SZARRAY: case MONO_TYPE_ARRAY: case MONO_TYPE_STRING: s390_st (p, s390_r2, 0, s390_r8, 0); break; case MONO_TYPE_R4: s390_ste (p, s390_f0, 0, s390_r8, 0); break; case MONO_TYPE_R8: s390_std (p, s390_f0, 0, s390_r8, 0); break; case MONO_TYPE_I8: s390_stg (p, s390_r2, 0, s390_r8, 0); break; case MONO_TYPE_VALUETYPE: if (sig->ret->data.klass->enumtype) { simpletype = sig->ret->data.klass->enum_basetype->type; goto enum_retvalue; } if (sig->pinvoke) retSize = mono_class_native_size (sig->ret->data.klass, &align); else retSize = mono_class_value_size (sig->ret->data.klass, &align); printf("Returning %d bytes for type %d (%d)\n",retSize,simpletype,sig->pinvoke); switch(retSize) { case 0: break; case 1: s390_stc (p, s390_r2, 0, s390_r8, 0); break; case 2: s390_sth (p, s390_r2, 0, s390_r8, 0); break; case 4: s390_st (p, s390_r2, 0, s390_r8, 0); break; case 8: s390_stg (p, s390_r2, 0, s390_r8, 0); break; default: ; /*------------------------------------------*/ /* The callee has already placed the result */ /* in the required area */ /*------------------------------------------*/ } break; case MONO_TYPE_VOID: break; default: g_error ("Can't handle as return value 0x%x", sig->ret->type); } } return p; }