#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
/*------------------------------------------------------------------*/
-/* adapt to mini later... */
+/* Specific trampoline code fragment sizes */
/*------------------------------------------------------------------*/
-#define mono_jit_share_code (1)
-
-/*------------------------------------------------------------------*/
-/* Method-specific trampoline code fragment sizes */
-/*------------------------------------------------------------------*/
-#define METHOD_TRAMPOLINE_SIZE 64
-#define JUMP_TRAMPOLINE_SIZE 64
+#define SPECIFIC_TRAMPOLINE_SIZE 64
/*========================= End of Defines =========================*/
#include <mono/metadata/marshal.h>
#include <mono/metadata/tabledefs.h>
#include <mono/arch/s390/s390-codegen.h>
-#include <mono/metadata/mono-debug-debugger.h>
#include "mini.h"
#include "mini-s390.h"
/* T y p e d e f s */
/*------------------------------------------------------------------*/
-typedef enum {
- MONO_TRAMPOLINE_GENERIC,
- MONO_TRAMPOLINE_JUMP,
- MONO_TRAMPOLINE_CLASS_INIT
-} MonoTrampolineType;
-
/*========================= End of Typedefs ========================*/
/*------------------------------------------------------------------*/
/* P r o t o t y p e s */
/*------------------------------------------------------------------*/
-/*------------------------------------------------------------------*/
-/* Address of the generic trampoline code. This is used by the */
-/* debugger to check whether a method is a trampoline. */
-/*------------------------------------------------------------------*/
-guint8 *mono_generic_trampoline_code = NULL;
-
/*========================= End of Prototypes ======================*/
/*------------------------------------------------------------------*/
/*------------------------------------------------------------------*/
/* */
-/* 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. */
/* When value type methods are called through the */
/* vtable we need to unbox the 'this' argument. */
/* */
-/* Parameters - method - Methd pointer */
+/* Parameters - gsctx - Generic sharing context */
+/* method - Methd pointer */
/* addr - Pointer to native code for method */
/* */
/*------------------------------------------------------------------*/
-static gpointer
-get_unbox_trampoline (MonoMethod *method, gpointer addr)
+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 ((!method->signature->ret->byref) &&
- (MONO_TYPE_ISSTRUCT (method->signature->ret)))
+ if (MONO_TYPE_ISSTRUCT (mono_method_signature (method)->ret))
this_pos = s390_r3;
-
- start = code = mono_global_codeman_reserve (28);
+ mono_domain_lock (domain);
+ start = code = mono_code_manager_reserve (domain->code_mp, 28);
+ mono_domain_unlock (domain);
+
s390_basr (code, s390_r13, 0);
s390_j (code, 4);
s390_word (code, addr);
g_assert ((code - start) <= 28);
+ mono_arch_flush_icache (start, code - start);
+
return start;
}
/*------------------------------------------------------------------*/
/* */
-/* 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, 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 */
- (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 = *((int *) (sp + S390_REG_SAVE_OFFSET+
- sizeof(int)*(reg-6)));
- else
- base = *((int *) (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);
+}
+
+/*========================= End of Function ========================*/
- return addr;
+void
+mono_arch_patch_plt_entry (guint8 *code, 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, gssize *regs)
{
char patch[6] = {0x47, 0x00, 0x00, 0x00, 0x07, 0x00};
- mono_runtime_class_init (vtable);
-
code = code - 6;
memcpy(code, patch, sizeof(patch));
/*========================= End of Function ========================*/
+void
+mono_arch_nullify_plt_entry (guint8 *code)
+{
+ g_assert_not_reached ();
+}
+
+/*========================= End of Function ========================*/
+
/*------------------------------------------------------------------*/
/* */
-/* Name - 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, gpointer *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 ========================*/
+
+gpointer*
+mono_arch_get_vcall_slot_addr (guint8* code, gpointer *regs)
+{
+ gpointer vt;
+ int displacement;
+ vt = mono_arch_get_vcall_slot (code, regs, &displacement);
+ if (!vt)
+ return NULL;
+ return (gpointer*)((char*)vt + displacement);
+}
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/* */
+/* Name - mono_arch_create_trampoline_code */
/* */
/* Function - Create the designated type of trampoline according*/
/* to the 'tramp_type' parameter. */
/* */
/*------------------------------------------------------------------*/
-static guchar*
-create_trampoline_code (MonoTrampolineType tramp_type)
+guchar*
+mono_arch_create_trampoline_code (MonoTrampolineType tramp_type)
{
- guint8 *buf, *code = NULL;
- static guint8* generic_jump_trampoline = NULL;
- static guint8 *generic_class_init_trampoline = NULL;
+ guint8 *buf, *tramp, *code;
int i, offset, lmfOffset;
- switch (tramp_type) {
- case MONO_TRAMPOLINE_GENERIC:
- if (mono_generic_trampoline_code)
- return mono_generic_trampoline_code;
- break;
- case MONO_TRAMPOLINE_JUMP:
- if (generic_jump_trampoline)
- return generic_jump_trampoline;
- break;
- case MONO_TRAMPOLINE_CLASS_INIT:
- if (generic_class_init_trampoline)
- return generic_class_init_trampoline;
- break;
- }
-
- if(!code) {
- /* Now we'll create in 'buf' the S/390 trampoline code. This
- is the trampoline code common to all methods */
+ /* 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: gssize *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);
- }
-
- switch (tramp_type) {
- case MONO_TRAMPOLINE_GENERIC:
- mono_generic_trampoline_code = code;
- break;
- case MONO_TRAMPOLINE_JUMP:
- generic_jump_trampoline = code;
- break;
- case MONO_TRAMPOLINE_CLASS_INIT:
- generic_class_init_trampoline = code;
- break;
- }
-
- 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 = create_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 = create_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;
}
/*------------------------------------------------------------------*/
/* */
-/* 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. */
+/* Name - mono_arch_create_specific_trampoline */
/* */
-/* Parameter - vtable - The type to initialize */
-/* */
-/* 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 = create_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. */
+ /*----------------------------------------------------------*/
+ mono_domain_lock (domain);
+ code = buf = mono_code_manager_reserve (domain->code_mp, SPECIFIC_TRAMPOLINE_SIZE);
+ mono_domain_unlock (domain);
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 encoded_offset)
{
- 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 ========================*/