X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Ftramp-s390.c;h=284e419751839252880a9870107a6cd37ecccf6c;hb=f70afd2b76174d2c78c2074805c80eddbc36d953;hp=47453ea4413a0a099689e00b2fd120a8de97cb1b;hpb=38f320d19a29a3e7d6a92cdb0b3ebec149d7c1a7;p=mono.git diff --git a/mono/mini/tramp-s390.c b/mono/mini/tramp-s390.c index 47453ea4413..284e4197518 100644 --- a/mono/mini/tramp-s390.c +++ b/mono/mini/tramp-s390.c @@ -22,17 +22,16 @@ #define GR_SAVE_SIZE 4*sizeof(long) #define FP_SAVE_SIZE 16*sizeof(double) -#define CREATE_GR_OFFSET S390_MINIMAL_STACK_SIZE +#define METHOD_SAVE_OFFSET S390_MINIMAL_STACK_SIZE +#define CREATE_GR_OFFSET METHOD_SAVE_OFFSET+sizeof(gpointer) #define CREATE_FP_OFFSET CREATE_GR_OFFSET+GR_SAVE_SIZE #define CREATE_LMF_OFFSET CREATE_FP_OFFSET+FP_SAVE_SIZE #define CREATE_STACK_SIZE (CREATE_LMF_OFFSET+2*sizeof(long)+sizeof(MonoLMF)) -#define METHOD_SAVE_OFFSET S390_RET_ADDR_OFFSET-4 /*------------------------------------------------------------------*/ -/* Method-specific trampoline code fragment sizes */ +/* Specific trampoline code fragment sizes */ /*------------------------------------------------------------------*/ -#define METHOD_TRAMPOLINE_SIZE 64 -#define JUMP_TRAMPOLINE_SIZE 64 +#define SPECIFIC_TRAMPOLINE_SIZE 64 /*========================= End of Defines =========================*/ @@ -48,7 +47,6 @@ #include #include #include -#include #include "mini.h" #include "mini-s390.h" @@ -76,7 +74,7 @@ /*------------------------------------------------------------------*/ /* */ -/* Name - get_unbox_trampoline */ +/* Name - mono_arch_get_unbox_trampoline */ /* */ /* Function - Return a pointer to a trampoline which does the */ /* unboxing before calling the method. */ @@ -89,19 +87,19 @@ /* */ /*------------------------------------------------------------------*/ -static gpointer -get_unbox_trampoline (MonoMethod *method, gpointer addr) +gpointer +mono_arch_get_unbox_trampoline (MonoMethod *method, gpointer addr) { guint8 *code, *start; int this_pos = s390_r2; + MonoDomain *domain = mono_domain_get (); start = addr; - if ((!mono_method_signature (method)->ret->byref) && - (MONO_TYPE_ISSTRUCT (mono_method_signature (method)->ret))) + if (MONO_TYPE_ISSTRUCT (mono_method_signature (method)->ret)) this_pos = s390_r3; - - start = code = mono_global_codeman_reserve (28); + start = code = mono_domain_code_reserve (domain, 28); + s390_basr (code, s390_r13, 0); s390_j (code, 4); s390_word (code, addr); @@ -111,6 +109,8 @@ get_unbox_trampoline (MonoMethod *method, gpointer addr) g_assert ((code - start) <= 28); + mono_arch_flush_icache (start, code - start); + return start; } @@ -118,114 +118,50 @@ get_unbox_trampoline (MonoMethod *method, gpointer addr) /*------------------------------------------------------------------*/ /* */ -/* Name - s390_magic_trampoline */ -/* */ -/* Function - This method is called by the function */ -/* "arch_create_jit_trampoline", which in turn is */ -/* called by the trampoline functions for virtual */ -/* methods. After having called the JIT compiler to */ -/* compile the method, it inspects the caller code */ -/* to find the address of the method-specific part */ -/* of the trampoline vtable slot for this method, */ -/* updates it with a fragment that calls the newly */ -/* compiled code and returns this address. The calls */ -/* generated by mono for S/390 will look like either:*/ -/* 1. l %r1,xxx(%rx) */ -/* bras %r14,%r1 */ -/* 2. brasl %r14,xxxxxx */ +/* Name - mono_arch_patch_callsite */ /* */ -/* Parameters - code - Pointer into caller code */ -/* method - The method to compile */ -/* sp - Stack pointer */ +/* Function - Patch a non-virtual callsite so it calls @addr. */ /* */ /*------------------------------------------------------------------*/ -static gpointer -s390_magic_trampoline (MonoMethod *method, guchar *code, char *sp) +void +mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr) { - gpointer addr; gint32 displace; - int reg; - guchar* base; unsigned short opcode; - char *fname; - MonoJitInfo *codeJi, - *addrJi; - - addr = mono_compile_method(method); - g_assert(addr); - - - if (code) { - - /* The top bit needs to be ignored on S/390 */ - code = (guchar*)((guint32)code & 0x7fffffff); - - fname = mono_method_full_name (method, TRUE); - codeJi = mono_jit_info_table_find (mono_domain_get(), code); - addrJi = mono_jit_info_table_find (mono_domain_get(), addr); - if (mono_method_same_domain (codeJi, addrJi)) { - - opcode = *((unsigned short *) (code - 6)); - switch (opcode) { - case 0x5810 : - /* This is a bras r14,r1 instruction */ - code -= 4; - reg = *code >> 4; - displace = *((short *)code) & 0x0fff; - if (reg > 5) - base = *((guchar **) (sp + S390_REG_SAVE_OFFSET+ - sizeof(int)*(reg-6))); - else - base = *((guchar **) (sp + CREATE_GR_OFFSET+ - sizeof(int)*(reg-2))); - - if ((method->klass->valuetype) && - (!mono_aot_is_got_entry(code, base))) - addr = get_unbox_trampoline(method, addr); - - code = base + displace; - if (mono_domain_owns_vtable_slot(mono_domain_get(), - code)) - s390_patch(code, addr); - break; - case 0xc0e5 : - /* This is the 'brasl' instruction */ - code -= 4; - displace = ((gint32) addr - (gint32) (code - 2)) / 2; - if (mono_method_same_domain (codeJi, addrJi)) { - s390_patch (code, displace); - mono_arch_flush_icache (code, 4); - } - break; - default : - g_error("Unable to patch instruction prior to %p",code); - } - } - } + opcode = *((unsigned short *) (orig_code - 6)); + /* This should be a 'brasl' instruction */ + g_assert (opcode == 0xc0e5); + orig_code -= 4; + displace = ((gint32) addr - (gint32) (orig_code - 2)) / 2; + s390_patch (orig_code, displace); + mono_arch_flush_icache (orig_code, 4); +} - return addr; +/*========================= End of Function ========================*/ + +void +mono_arch_patch_plt_entry (guint8 *code, gpointer *got, mgreg_t *regs, guint8 *addr) +{ + g_assert_not_reached (); } /*========================= End of Function ========================*/ /*------------------------------------------------------------------*/ /* */ -/* Name - s390_class_init_trampoline */ +/* Name - mono_arch_nullify_class_init_trampoline */ /* */ -/* Function - Initialize a class and then no-op the call to */ -/* the trampoline. */ +/* Function - Nullify a call which calls a class init trampoline */ /* */ /*------------------------------------------------------------------*/ -static void -s390_class_init_trampoline (void *vtable, guchar *code, char *sp) +void +mono_arch_nullify_class_init_trampoline (guint8 *code, mgreg_t *regs) { char patch[6] = {0x47, 0x00, 0x00, 0x00, 0x07, 0x00}; - mono_runtime_class_init (vtable); - code = code - 6; memcpy(code, patch, sizeof(patch)); @@ -233,9 +169,92 @@ s390_class_init_trampoline (void *vtable, guchar *code, char *sp) /*========================= End of Function ========================*/ +void +mono_arch_nullify_plt_entry (guint8 *code, mgreg_t *regs) +{ + g_assert_not_reached (); +} + +/*========================= End of Function ========================*/ + /*------------------------------------------------------------------*/ /* */ -/* Name - mono_arch_create_trampoline_code */ +/* Name - mono_arch_get_vcall_slot */ +/* */ +/* Function - This method is called by the arch independent */ +/* trampoline code to determine the vtable slot used by */ +/* the call which invoked the trampoline. */ +/* The calls */ +/* generated by mono for S/390 will look like either:*/ +/* 1. l %r1,xxx(%rx) */ +/* bras %r14,%r1 */ +/* 2. brasl %r14,xxxxxx */ +/* */ +/* Parameters - code - Pointer into caller code */ +/* regs - Register state at the point of the call */ +/* displacement - Out parameter which will receive */ +/* the displacement of the vtable slot */ +/* */ +/*------------------------------------------------------------------*/ + +gpointer +mono_arch_get_vcall_slot (guint8 *code, mgreg_t *regs, int *displacement) +{ + int reg; + guchar* base; + unsigned short opcode; + char *sp; + + // We are passed sp instead of the register array + sp = (char*)regs; + + *displacement = 0; + + opcode = *((unsigned short *) (code - 6)); + switch (opcode) { + case 0x5810 : + /* This is a bras r14,r1 instruction */ + code -= 4; + reg = *code >> 4; + *displacement = *((short *)code) & 0x0fff; + if (reg > 5) + base = *((guchar **) (sp + S390_REG_SAVE_OFFSET+ + sizeof(int)*(reg-6))); + else + base = *((guchar **) ((sp - CREATE_STACK_SIZE) + + CREATE_GR_OFFSET + + sizeof(int)*(reg-2))); + return base; + case 0x581d : + /* l %r1,OFFSET(%r13,%r7) */ + code -= 4; + reg = *code >> 4; + *displacement = *((short *)code) & 0x0fff; + if (reg > 5) + base = *((guchar **) (sp + S390_REG_SAVE_OFFSET+ + sizeof(int)*(reg-6))); + else + base = *((guchar **) ((sp - CREATE_STACK_SIZE) + + CREATE_GR_OFFSET + + sizeof(int)*(reg-2))); + base += *((guint32*) (sp + S390_REG_SAVE_OFFSET+ + sizeof(int)*(s390_r13-6))); + return base; + case 0xc0e5 : + /* This is the 'brasl' instruction */ + return NULL; + default : + g_error("Unable to patch instruction prior to %p",code); + } + + return NULL; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_create_trampoline_code */ /* */ /* Function - Create the designated type of trampoline according*/ /* to the 'tramp_type' parameter. */ @@ -243,293 +262,195 @@ s390_class_init_trampoline (void *vtable, guchar *code, char *sp) /*------------------------------------------------------------------*/ guchar* -mono_arch_create_trampoline_code (MonoTrampolineType tramp_type) +mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInfo **info, gboolean aot) { - - guint8 *buf, *code = NULL; + guint8 *buf, *tramp, *code; int i, offset, lmfOffset; - if(!code) { - /* Now we'll create in 'buf' the S/390 trampoline code. This - is the trampoline code common to all methods */ + 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); + 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. - -----------------------------------------------------------*/ + /*----------------------------------------------------------- + STEP 0: First create a non-standard function prologue with a + stack size big enough to save our registers. + -----------------------------------------------------------*/ - s390_stm (buf, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); - s390_lr (buf, s390_r11, s390_r15); - s390_ahi (buf, STK_BASE, -CREATE_STACK_SIZE); - s390_st (buf, s390_r11, 0, STK_BASE, 0); - s390_stm (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_stm (buf, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); + s390_lr (buf, s390_r11, s390_r15); + s390_ahi (buf, STK_BASE, -CREATE_STACK_SIZE); + s390_st (buf, s390_r11, 0, STK_BASE, 0); + s390_st (buf, s390_r1, 0, STK_BASE, METHOD_SAVE_OFFSET); + s390_stm (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, 4); - s390_word (buf, mono_get_lmf_addr); - s390_l (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_basr (buf, s390_r13, 0); + s390_j (buf, 4); + s390_word (buf, mono_get_lmf_addr); + s390_l (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_lr (buf, s390_r13, STK_BASE); - s390_ahi (buf, s390_r13, lmfOffset); + s390_lr (buf, s390_r13, STK_BASE); + s390_ahi (buf, s390_r13, lmfOffset); - /*---------------------------------------------------------------*/ - /* Set lmf.lmf_addr = jit_tls->lmf */ - /*---------------------------------------------------------------*/ - s390_st (buf, s390_r2, 0, s390_r13, + /*---------------------------------------------------------------*/ + /* Set lmf.lmf_addr = jit_tls->lmf */ + /*---------------------------------------------------------------*/ + s390_st (buf, s390_r2, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, lmf_addr)); - /*---------------------------------------------------------------*/ - /* Get current lmf */ - /*---------------------------------------------------------------*/ - s390_l (buf, s390_r0, 0, s390_r2, 0); + /*---------------------------------------------------------------*/ + /* Get current lmf */ + /*---------------------------------------------------------------*/ + s390_l (buf, s390_r0, 0, s390_r2, 0); - /*---------------------------------------------------------------*/ - /* Set our lmf as the current lmf */ - /*---------------------------------------------------------------*/ - s390_st (buf, s390_r13, 0, s390_r2, 0); + /*---------------------------------------------------------------*/ + /* Set our lmf as the current lmf */ + /*---------------------------------------------------------------*/ + s390_st (buf, s390_r13, 0, s390_r2, 0); - /*---------------------------------------------------------------*/ - /* Have our lmf.previous_lmf point to the last lmf */ - /*---------------------------------------------------------------*/ - s390_st (buf, s390_r0, 0, s390_r13, + /*---------------------------------------------------------------*/ + /* Have our lmf.previous_lmf point to the last lmf */ + /*---------------------------------------------------------------*/ + s390_st (buf, s390_r0, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, previous_lmf)); - /*---------------------------------------------------------------*/ - /* save method info */ - /*---------------------------------------------------------------*/ - s390_l (buf, s390_r1, 0, s390_r11, METHOD_SAVE_OFFSET); - s390_st (buf, s390_r1, 0, s390_r13, + /*---------------------------------------------------------------*/ + /* save method info */ + /*---------------------------------------------------------------*/ + s390_l (buf, s390_r1, 0, STK_BASE, METHOD_SAVE_OFFSET); + s390_st (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, method)); - /*---------------------------------------------------------------*/ - /* save the current SP */ - /*---------------------------------------------------------------*/ - s390_l (buf, s390_r1, 0, STK_BASE, 0); - s390_st (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp)); + /*---------------------------------------------------------------*/ + /* save the current SP */ + /*---------------------------------------------------------------*/ + s390_l (buf, s390_r1, 0, STK_BASE, 0); + s390_st (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, ebp)); - /*---------------------------------------------------------------*/ - /* save the current IP */ - /*---------------------------------------------------------------*/ - if (tramp_type == MONO_TRAMPOLINE_JUMP) { - s390_lhi (buf, s390_r1, 0); - } else { - s390_l (buf, s390_r1, 0, s390_r1, S390_RET_ADDR_OFFSET); - s390_la (buf, s390_r1, 0, s390_r1, 0); - } - s390_st (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip)); + /*---------------------------------------------------------------*/ + /* save the current IP */ + /*---------------------------------------------------------------*/ + if (tramp_type == MONO_TRAMPOLINE_JUMP) { + s390_lhi (buf, s390_r1, 0); + } else { + s390_l (buf, s390_r1, 0, s390_r1, S390_RET_ADDR_OFFSET); + s390_la (buf, s390_r1, 0, s390_r1, 0); + } + s390_st (buf, s390_r1, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, eip)); - /*---------------------------------------------------------------*/ - /* Save general and floating point registers */ - /*---------------------------------------------------------------*/ - s390_stm (buf, s390_r2, s390_r12, s390_r13, + /*---------------------------------------------------------------*/ + /* Save general and floating point registers */ + /*---------------------------------------------------------------*/ + s390_stm (buf, s390_r2, s390_r12, s390_r13, G_STRUCT_OFFSET(MonoLMF, gregs[2])); - for (i = 0; i < 16; i++) { - s390_std (buf, i, 0, s390_r13, + for (i = 0; i < 16; i++) { + s390_std (buf, i, 0, s390_r13, G_STRUCT_OFFSET(MonoLMF, fregs[i])); - } + } - /*---------------------------------------------------------------*/ - /* STEP 2: call 's390_magic_trampoline()', who will compile the */ - /* code and fix the method vtable entry for us */ - /*---------------------------------------------------------------*/ + /*---------------------------------------------------------------*/ + /* STEP 2: call the C trampoline function */ + /*---------------------------------------------------------------*/ - /* Set arguments */ - - /* Arg 1: MonoMethod *method. It was put in r11 by the - method-specific trampoline code, and then saved before the call - to mono_get_lmf_addr()'. Restore r13, by the way :-) */ - s390_l (buf, s390_r2, 0, s390_r11, METHOD_SAVE_OFFSET); - - /* Arg 2: code (next address to the instruction that called us) */ - if (tramp_type == MONO_TRAMPOLINE_JUMP) { - s390_lhi (buf, s390_r3, 0); - } else { - s390_l (buf, s390_r3, 0, s390_r11, S390_RET_ADDR_OFFSET); - } - - /* Arg 3: stack pointer */ - s390_lr (buf, s390_r4, STK_BASE); + /* Set arguments */ + + /* Arg 1: mgreg_t *regs. We pass sp instead */ + s390_lr (buf, s390_r2, STK_BASE); + s390_ahi (buf, s390_r2, CREATE_STACK_SIZE); - /* Calculate call address and call - 's390_magic_trampoline'. Return value will be in r2 */ + /* Arg 2: code (next address to the instruction that called us) */ + if (tramp_type == MONO_TRAMPOLINE_JUMP) { + s390_lhi (buf, s390_r3, 0); + } else { + s390_l (buf, s390_r3, 0, s390_r11, S390_RET_ADDR_OFFSET); + + /* Mask out bit 31 */ s390_basr (buf, s390_r13, 0); s390_j (buf, 4); - if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) { - s390_word (buf, s390_class_init_trampoline); - } else { - s390_word (buf, s390_magic_trampoline); - } - s390_l (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_lr (buf, s390_r1, s390_r2); - - /*---------------------------------------------------------- - STEP 3: Restore the LMF - ----------------------------------------------------------*/ - restoreLMF(buf, STK_BASE, CREATE_STACK_SIZE); - - /*---------------------------------------------------------- - STEP 4: call the compiled method - ----------------------------------------------------------*/ + s390_word (buf, (~(1 << 31))); + s390_n (buf, s390_r3, 0, s390_r13, 4); + } - /* Restore registers */ + /* 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_l (buf, s390_r4, 0, STK_BASE, METHOD_SAVE_OFFSET); - s390_lm (buf, s390_r2, s390_r5, STK_BASE, CREATE_GR_OFFSET); + /* Arg 4: trampoline address. Ignore for now */ - /* 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_lr (buf, STK_BASE, s390_r11); - s390_lm (buf, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); - 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; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - mono_arch_create_jump_trampoline */ -/* */ -/* Function - Create the designated type of trampoline according*/ -/* to the 'tramp_type' parameter. */ -/* */ -/*------------------------------------------------------------------*/ - -MonoJitInfo * -mono_arch_create_jump_trampoline (MonoMethod *method) -{ - guint8 *code, *buf, *tramp = NULL; - MonoJitInfo *ji; - MonoDomain *domain = mono_domain_get(); - gint32 displace; - - tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_JUMP); - - mono_domain_lock (domain); - code = buf = mono_code_manager_reserve (domain->code_mp, METHOD_TRAMPOLINE_SIZE); - mono_domain_unlock (domain); - + /* Calculate call address and call the C trampoline. Return value will be in r2 */ s390_basr (buf, s390_r13, 0); s390_j (buf, 4); - s390_word (buf, method); - s390_l (buf, s390_r13, 0, s390_r13, 4); - displace = (tramp - buf) / 2; - s390_jcl (buf, S390_CC_UN, displace); - - mono_arch_flush_icache (code, buf-code); - - g_assert ((buf - code) <= JUMP_TRAMPOLINE_SIZE); - - ji = g_new0 (MonoJitInfo, 1); - ji->method = method; - ji->code_start = code; - ji->code_size = buf - code; + tramp = (guint8*)mono_get_trampoline_func (tramp_type); + s390_word (buf, tramp); + s390_l (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_lr (buf, s390_r1, s390_r2); + + /*---------------------------------------------------------- + STEP 3: Restore the LMF + ----------------------------------------------------------*/ + restoreLMF(buf, STK_BASE, CREATE_STACK_SIZE); - mono_jit_stats.method_trampolines++; - - return ji; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - mono_arch_create_jit_trampoline */ -/* */ -/* Function - Creates a trampoline function for virtual methods.*/ -/* If the created code is called it first starts JIT */ -/* compilation and then calls the newly created */ -/* method. It also replaces the corresponding vtable */ -/* entry (see s390_magic_trampoline). */ -/* */ -/* A trampoline consists of two parts: a main */ -/* fragment, shared by all method trampolines, and */ -/* and some code specific to each method, which */ -/* hard-codes a reference to that method and then */ -/* calls the main fragment. */ -/* */ -/* The main fragment contains a call to */ -/* 's390_magic_trampoline', which performs a call */ -/* to the JIT compiler and substitutes the method- */ -/* specific fragment with some code that directly */ -/* calls the JIT-compiled method. */ -/* */ -/* Parameter - method - Pointer to the method information */ -/* */ -/* Returns - A pointer to the newly created code */ -/* */ -/*------------------------------------------------------------------*/ - -gpointer -mono_arch_create_jit_trampoline (MonoMethod *method) -{ - guint8 *code, *buf; - static guint8 *vc = NULL; - gint32 displace; + /*---------------------------------------------------------- + STEP 4: call the compiled method + ----------------------------------------------------------*/ + + /* Restore registers */ - vc = mono_get_trampoline_code (MONO_TRAMPOLINE_GENERIC); + s390_lm (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; + } - /* 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 r13 to keep that value, for instance. However, the generic part of - the trampoline relies on r11 having the same value it had before coming - here, so we must save it before. */ - code = buf = mono_global_codeman_reserve(METHOD_TRAMPOLINE_SIZE); + /* Restore stack pointer and jump to the code - + R14 contains the return address to our caller */ + s390_lr (buf, STK_BASE, s390_r11); + s390_lm (buf, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET); - s390_basr (buf, s390_r13, 0); - s390_j (buf, 4); - s390_word (buf, method); - s390_l (buf, s390_r13, 0, s390_r13, 4); - displace = (vc - buf) / 2; - s390_jcl (buf, S390_CC_UN, displace); + 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) <= METHOD_TRAMPOLINE_SIZE); + /* Sanity check */ + g_assert ((buf - code) <= 512); + return code; } @@ -537,89 +458,52 @@ mono_arch_create_jit_trampoline (MonoMethod *method) /*------------------------------------------------------------------*/ /* */ -/* Name - mono_arch_create_class_init_trampoline */ -/* */ -/* Function - Creates a trampoline function to run a type init- */ -/* ializer. If the trampoline is called, it calls */ -/* mono_runtime_class_init with the given vtable, */ -/* then patches the caller code so it does not get */ -/* called any more. */ -/* */ -/* Parameter - vtable - The type to initialize */ +/* Name - mono_arch_create_specific_trampoline */ /* */ -/* Returns - A pointer to the newly created code */ +/* Function - Creates the given kind of specific trampoline */ /* */ /*------------------------------------------------------------------*/ gpointer -mono_arch_create_class_init_trampoline (MonoVTable *vtable) +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 (MONO_TRAMPOLINE_CLASS_INIT); - - /*-----------------------------------------------------------*/ - /* 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 r11 to keep that value, for */ - /* instance. However, the generic part of the trampoline */ - /* relies on r11 having the same value it had before coming */ - /* here, so we must save it before. */ - /*-----------------------------------------------------------*/ - code = buf = mono_global_codeman_reserve(METHOD_TRAMPOLINE_SIZE); + tramp = mono_get_trampoline_code (tramp_type); - s390_st (buf, s390_r14, 0, STK_BASE, S390_RET_ADDR_OFFSET); - s390_ahi (buf, STK_BASE, -S390_MINIMAL_STACK_SIZE); + /*----------------------------------------------------------*/ + /* 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_word (buf, vtable); - s390_word (buf, s390_class_init_trampoline); - s390_lr (buf, s390_r3, s390_r14); - s390_l (buf, s390_r2, 0, s390_r1, 4); - s390_lhi (buf, s390_r4, 0); - s390_l (buf, s390_r1, 0, s390_r1, 8); - s390_basr (buf, s390_r14, s390_r1); - - s390_ahi (buf, STK_BASE, S390_MINIMAL_STACK_SIZE); - s390_l (buf, s390_r14, 0, STK_BASE, S390_RET_ADDR_OFFSET); - s390_br (buf, s390_r14); + s390_j (buf, 4); + s390_word (buf, arg1); + s390_l (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) <= METHOD_TRAMPOLINE_SIZE); - mono_jit_stats.method_trampolines++; + /* Sanity check */ + g_assert ((buf - code) <= SPECIFIC_TRAMPOLINE_SIZE); + if (code_len) + *code_len = buf - code; + return code; -} +} /*========================= End of Function ========================*/ -/*------------------------------------------------------------------*/ -/* */ -/* Name - mono_debuger_create_notification_function */ -/* */ -/* Function - This method is only called when running in the */ -/* Mono debugger. It returns a pointer to the */ -/* arch specific notification function. */ -/* */ -/*------------------------------------------------------------------*/ - gpointer -mono_debugger_create_notification_function (gpointer *notification_address) +mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot) { - guint8 *ptr, *buf; - - ptr = buf = mono_global_codeman_reserve (16); - s390_break (buf); - if (notification_address) - *notification_address = buf; - s390_br (buf, s390_r14); - - return ptr; + /* FIXME: implement! */ + g_assert_not_reached (); + return NULL; } - -/*========================= End of Function ========================*/