Exemple #1
0
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;
}
Exemple #2
0
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;
}	
Exemple #3
0
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);
}	
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}
Exemple #7
0
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;
}
Exemple #8
0
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;
}