1 /*------------------------------------------------------------------*/
5 /* Function - Create trampolines to invoke arbitrary functions. */
7 /* Name - Neale Ferguson. */
9 /* Date - October, 2002 */
12 /*------------------------------------------------------------------*/
14 /*------------------------------------------------------------------*/
16 /*------------------------------------------------------------------*/
18 #define PROLOG_INS 24 /* Size of emitted prolog */
19 #define CALL_INS 4 /* Size of emitted call */
20 #define EPILOG_INS 18 /* Size of emitted epilog */
24 /*========================= End of Defines =========================*/
26 /*------------------------------------------------------------------*/
28 /*------------------------------------------------------------------*/
31 # include <sys/mman.h>
32 # include <limits.h> /* for PAGESIZE */
34 # define PAGESIZE 4096
41 #include "s390-codegen.h"
42 #include "mono/metadata/class.h"
43 #include "mono/metadata/tabledefs.h"
44 #include "mono/interpreter/interp.h"
45 #include "mono/metadata/appdomain.h"
46 #include "mono/metadata/marshal.h"
48 /*========================= End of Includes ========================*/
50 /*------------------------------------------------------------------*/
52 /*------------------------------------------------------------------*/
54 /*------------------------------------------------------------------*/
55 /* Structure used to accummulate size of stack, code, and locals */
56 /*------------------------------------------------------------------*/
64 /*========================= End of Typedefs ========================*/
66 /*------------------------------------------------------------------*/
68 /* Name - add_general */
70 /* Function - Determine code and stack size incremements for a */
73 /*------------------------------------------------------------------*/
76 add_general (guint *gr, size_data *sz, gboolean simple)
79 if (*gr >= GENERAL_REGS) {
80 sz->stack_size += sizeof(long);
86 if (*gr >= GENERAL_REGS - 1) {
87 sz->stack_size += 8 + (sz->stack_size % 8);
97 /*========================= End of Function ========================*/
99 /*------------------------------------------------------------------*/
101 /* Name - calculate_sizes */
103 /* Function - Determine the amount of space required for code */
104 /* and stack. In addition determine starting points */
105 /* for stack-based parameters, and area for struct- */
106 /* ures being returned on the stack. */
108 /*------------------------------------------------------------------*/
111 calculate_sizes (MonoMethodSignature *sig, size_data *sz,
112 gboolean string_ctor)
114 guint i, fr, gr, size;
115 guint32 simpletype, align;
120 sz->stack_size = S390_MINIMAL_STACK_SIZE;
121 sz->code_size = (PROLOG_INS + CALL_INS + EPILOG_INS);
125 add_general (&gr, sz, TRUE);
128 /*----------------------------------------------------------*/
129 /* We determine the size of the return code/stack in case we*/
130 /* need to reserve a register to be used to address a stack */
131 /* area that the callee will use. */
132 /*----------------------------------------------------------*/
134 if (sig->ret->byref || string_ctor) {
137 simpletype = sig->ret->type;
139 switch (simpletype) {
140 case MONO_TYPE_BOOLEAN:
150 case MONO_TYPE_CLASS:
151 case MONO_TYPE_OBJECT:
154 case MONO_TYPE_SZARRAY:
155 case MONO_TYPE_ARRAY:
156 case MONO_TYPE_STRING:
162 case MONO_TYPE_VALUETYPE:
163 if (sig->ret->data.klass->enumtype) {
164 simpletype = sig->ret->data.klass->enum_basetype->type;
169 size = mono_class_native_size (sig->ret->data.klass, &align);
171 size = mono_class_value_size (sig->ret->data.klass, &align);
175 /*----------------------------------*/
176 /* On S/390, structures of size 1, */
177 /* 2, 4, and 8 bytes are returned */
178 /* in (a) register(s). */
179 /*----------------------------------*/
195 g_error ("Can't handle as return value 0x%x", sig->ret->type);
199 /*----------------------------------------------------------*/
200 /* We determine the size of the parameter code and stack */
201 /* requirements by checking the types and sizes of the */
203 /*----------------------------------------------------------*/
205 for (i = 0; i < sig->param_count; ++i) {
206 if (sig->params [i]->byref) {
207 add_general (&gr, sz, TRUE);
210 simpletype = sig->params [i]->type;
212 switch (simpletype) {
213 case MONO_TYPE_BOOLEAN:
224 case MONO_TYPE_CLASS:
225 case MONO_TYPE_OBJECT:
226 case MONO_TYPE_STRING:
227 add_general (&gr, sz, TRUE);
229 case MONO_TYPE_SZARRAY:
230 add_general (&gr, sz, TRUE);
232 case MONO_TYPE_VALUETYPE:
233 if (sig->params [i]->data.klass->enumtype) {
234 simpletype = sig->params [i]->data.klass->enum_basetype->type;
238 size = mono_class_native_size (sig->params [i]->data.klass, &align);
240 size = mono_class_value_size (sig->params [i]->data.klass, &align);
241 DEBUG(printf("%d typesize: %d (%d)\n",i,size,align));
243 /*----------------------------------*/
244 /* On S/390, structures of size 1, */
245 /* 2, 4, and 8 bytes are passed in */
246 /* (a) register(s). */
247 /*----------------------------------*/
252 add_general(&gr, sz, TRUE);
255 add_general(&gr, sz, FALSE);
258 sz->local_size += (size + (size % align));
263 add_general (&gr, sz, FALSE);
266 if (fr < FLOAT_REGS) {
276 if (fr < FLOAT_REGS) {
281 sz->stack_size += 8 + (sz->stack_size % 8);
285 g_error ("Can't trampoline 0x%x", sig->params [i]->type);
290 /* align stack size to 8 */
291 DEBUG (printf (" stack size: %d (%d)\n"
294 (sz->stack_size + 8) & ~8, sz->stack_size,
295 (sz->code_size),(sz->local_size + 8) & ~8));
296 sz->stack_size = (sz->stack_size + 8) & ~8;
297 sz->local_size = (sz->local_size + 8) & ~8;
300 /*========================= End of Function ========================*/
302 /*------------------------------------------------------------------*/
304 /* Name - emit_prolog */
306 /* Function - Create the instructions that implement the stand- */
307 /* ard function prolog according to the S/390 ABI. */
309 /*------------------------------------------------------------------*/
311 static inline guint8 *
312 emit_prolog (guint8 *p, MonoMethodSignature *sig, size_data *sz)
316 stack_size = sz->stack_size + sz->local_size;
318 /* function prolog */
319 s390_stm (p, s390_r6, STK_BASE, STK_BASE, 24);
320 s390_l (p, s390_r7, 0, STK_BASE, MINV_POS);
321 s390_lr (p, s390_r11, STK_BASE);
322 s390_ahi (p, STK_BASE, -stack_size);
323 s390_st (p, s390_r11, 0, STK_BASE, 0);
325 /*-----------------------------------------*/
327 /* - address of "callme" */
328 /* - address of "retval" */
329 /* - address of "arguments" */
330 /*-----------------------------------------*/
331 s390_lr (p, s390_r9, s390_r2);
332 s390_lr (p, s390_r8, s390_r3);
333 s390_lr (p, s390_r10, s390_r5);
338 /*========================= End of Function ========================*/
340 /*------------------------------------------------------------------*/
342 /* Name - emit_save_parameters */
344 /* Function - Create the instructions that load registers with */
345 /* parameters, place others on the stack according */
346 /* to the S/390 ABI. */
348 /* The resulting function takes the form: */
349 /* void func (void (*callme)(), void *retval, */
350 /* void *this_obj, stackval *arguments); */
352 /*------------------------------------------------------------------*/
354 inline static guint8*
355 emit_save_parameters (guint8 *p, MonoMethodSignature *sig, size_data *sz)
357 guint i, fr, gr, act_strs, align,
358 stack_par_pos, size, local_pos;
361 /*----------------------------------------------------------*/
362 /* If a structure on stack is being returned, reserve r2 */
363 /* to point to an area where it can be passed. */
364 /*----------------------------------------------------------*/
371 stack_par_pos = S390_MINIMAL_STACK_SIZE;
372 local_pos = sz->stack_size;
375 s390_lr (p, s390_r2 + gr, s390_r4);
380 for (i = 0; i < sig->param_count; ++i) {
381 DEBUG(printf("par: %d type: %d ref: %d\n",i,sig->params[i]->type,sig->params[i]->byref));
382 if (sig->params [i]->byref) {
383 if (gr < GENERAL_REGS) {
384 s390_l (p, s390_r2 + gr, 0, ARG_BASE, STKARG);
387 s390_l (p, s390_r0, 0, ARG_BASE, STKARG);
388 s390_st (p, s390_r0, 0, STK_BASE, stack_par_pos);
389 stack_par_pos += sizeof(long);
393 simpletype = sig->params [i]->type;
395 switch (simpletype) {
396 case MONO_TYPE_BOOLEAN:
407 case MONO_TYPE_CLASS:
408 case MONO_TYPE_OBJECT:
409 case MONO_TYPE_STRING:
410 case MONO_TYPE_SZARRAY:
411 if (gr < GENERAL_REGS) {
412 s390_l (p, s390_r2 + gr, 0, ARG_BASE, STKARG);
415 s390_l (p, s390_r0, 0, ARG_BASE, STKARG);
416 s390_st (p, s390_r0, 0, STK_BASE, stack_par_pos);
417 stack_par_pos += sizeof(long);
420 case MONO_TYPE_VALUETYPE:
421 if (sig->params [i]->data.klass->enumtype) {
422 simpletype = sig->params [i]->data.klass->enum_basetype->type;
426 size = mono_class_native_size (sig->params [i]->data.klass, &align);
428 size = mono_class_value_size (sig->params [i]->data.klass, &align);
429 DEBUG(printf("parStruct - size %d pinvoke: %d\n",size,sig->pinvoke));
435 if (gr < GENERAL_REGS) {
436 s390_l (p, s390_r2 + gr, 0,ARG_BASE, STKARG);
437 s390_l (p, s390_r2 + gr, 0, s390_r2 + gr, 0);
440 stack_par_pos += (stack_par_pos % align);
441 s390_l (p, s390_r10, 0,ARG_BASE, STKARG);
442 s390_l (p, s390_r10, 0, s390_r10, 0);
443 s390_st (p, s390_r10, 0, STK_BASE, stack_par_pos);
444 stack_par_pos += sizeof(long);
448 if (gr < GENERAL_REGS-1) {
449 s390_l (p, s390_r2 + gr, 0, ARG_BASE, STKARG);
450 s390_lm (p, s390_r2 + gr, s390_r3 + gr, s390_r2 + gr, 0);
452 stack_par_pos += (stack_par_pos % align);
453 s390_l (p, s390_r10, 0, ARG_BASE, STKARG);
454 s390_mvc (p, sizeof(long long), STK_BASE, stack_par_pos, s390_r10, 0);
455 stack_par_pos += sizeof(long long);
460 local_pos += (local_pos % align);
461 s390_l (p, s390_r13, 0, ARG_BASE, STKARG);
462 s390_mvc (p, size, STK_BASE, local_pos, s390_r13, 0);
463 s390_la (p, s390_r13, 0, STK_BASE, local_pos);
466 local_pos += (local_pos % align);
467 s390_bras (p, s390_r13, 4);
469 s390_l (p, s390_r1, 0, s390_r13, 0);
470 s390_l (p, s390_r0, 0, ARG_BASE, STKARG);
471 s390_lr (p, s390_r14, s390_r12);
472 s390_la (p, s390_r12, 0, STK_BASE, local_pos);
473 s390_lr (p, s390_r13, s390_r1);
474 s390_mvcl (p, s390_r12, s390_r0);
475 s390_lr (p, s390_r12, s390_r14);
476 s390_la (p, s390_r13, 0, STK_BASE, local_pos);
479 if (gr < GENERAL_REGS) {
480 s390_lr (p, s390_r2 + gr, s390_r13);
483 s390_st (p, s390_r13, 0, STK_BASE, stack_par_pos);
484 stack_par_pos += sizeof(long);
489 if (gr < GENERAL_REGS-1) {
490 s390_lm (p, s390_r2 + gr, s390_r2 + gr + 1, ARG_BASE, STKARG);
494 *(guint32 *) p &= ~7;
495 s390_mvc (p, sizeof(long long), STK_BASE, stack_par_pos, ARG_BASE, STKARG);
496 stack_par_pos += sizeof(long long) + (stack_par_pos % sizeof(long long));
500 if (fr < FLOAT_REGS) {
501 s390_le (p, s390_r0 + fr, 0, ARG_BASE, STKARG);
504 s390_mvc (p, sizeof(float), STK_BASE, stack_par_pos, ARG_BASE, STKARG);
505 stack_par_pos += sizeof(float);
509 if (fr < FLOAT_REGS) {
510 s390_ld (p, s390_r0 + fr, 0, ARG_BASE, STKARG);
514 *(guint32 *) p &= ~7;
515 s390_mvc (p, sizeof(double), STK_BASE, stack_par_pos, ARG_BASE, STKARG);
516 stack_par_pos += sizeof(long long) + (stack_par_pos % sizeof(long long));
520 g_error ("Can't trampoline 0x%x", sig->params [i]->type);
524 /*----------------------------------------------------------*/
525 /* If we're returning a structure but not in a register */
526 /* then point the result area for the called routine */
527 /*----------------------------------------------------------*/
529 s390_l (p, s390_r2, 0, s390_r8, 0);
535 /*========================= End of Function ========================*/
537 /*------------------------------------------------------------------*/
539 /* Name - alloc_code_memory */
541 /* Function - Allocate space to place the emitted code. */
543 /*------------------------------------------------------------------*/
545 static inline guint8 *
546 alloc_code_memory (guint code_size)
551 p = g_malloc (code_size + PAGESIZE - 1);
553 /* Align to a multiple of PAGESIZE, assumed to be a power of two */
554 p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1));
556 p = g_malloc (code_size);
558 DEBUG (printf (" align: %p (%d)\n", p, (guint)p % 4));
563 /*========================= End of Function ========================*/
565 /*------------------------------------------------------------------*/
567 /* Name - emit_call_and_store_retval */
569 /* Function - Emit code that will implement the call to the */
570 /* desired function, and unload the result according */
571 /* to the S390 ABI for the type of value returned */
573 /*------------------------------------------------------------------*/
575 static inline guint8 *
576 emit_call_and_store_retval (guint8 *p, MonoMethodSignature *sig,
577 size_data *sz, gboolean string_ctor)
580 guint retSize, align;
583 s390_basr (p, s390_r14, s390_r9);
585 /* get return value */
586 if (sig->ret->byref || string_ctor) {
587 s390_st (p, s390_r2, 0, s390_r8, 0);
589 simpletype = sig->ret->type;
591 switch (simpletype) {
592 case MONO_TYPE_BOOLEAN:
595 s390_stc (p, s390_r2, 0, s390_r8, 0);
600 s390_sth (p, s390_r2, 0, s390_r8, 0);
606 case MONO_TYPE_CLASS:
607 case MONO_TYPE_OBJECT:
608 case MONO_TYPE_SZARRAY:
609 case MONO_TYPE_ARRAY:
610 case MONO_TYPE_STRING:
611 s390_st (p, s390_r2, 0, s390_r8, 0);
614 s390_ste (p, s390_f0, 0, s390_r8, 0);
617 s390_std (p, s390_f0, 0, s390_r8, 0);
620 s390_stm (p, s390_r2, s390_r3, s390_r8, 0);
622 case MONO_TYPE_VALUETYPE:
623 if (sig->ret->data.klass->enumtype) {
624 simpletype = sig->ret->data.klass->enum_basetype->type;
628 retSize = mono_class_native_size (sig->ret->data.klass, &align);
630 retSize = mono_class_value_size (sig->ret->data.klass, &align);
631 printf("Returning %d bytes for type %d (%d)\n",retSize,simpletype,sig->pinvoke);
636 s390_stc (p, s390_r2, 0, s390_r8, 0);
639 s390_sth (p, s390_r2, 0, s390_r8, 0);
642 s390_st (p, s390_r2, 0, s390_r8, 0);
645 s390_stm (p, s390_r2, s390_r3, s390_r8, 0);
648 /*------------------------------------------*/
649 /* The callee has already placed the result */
650 /* in the required area */
651 /*------------------------------------------*/
657 g_error ("Can't handle as return value 0x%x",
665 /*========================= End of Function ========================*/
667 /*------------------------------------------------------------------*/
669 /* Name - emit_epilog */
671 /* Function - Create the instructions that implement the stand- */
672 /* ard function epilog according to the S/390 ABI. */
674 /*------------------------------------------------------------------*/
676 static inline guint8 *
677 emit_epilog (guint8 *p, MonoMethodSignature *sig, size_data *sz)
679 /* function epilog */
680 s390_l (p, STK_BASE, 0, STK_BASE, 0);
681 s390_l (p, s390_r4, 0, STK_BASE, 56);
682 s390_lm (p, s390_r6, STK_BASE, STK_BASE, 24);
683 s390_br (p, s390_r4);
688 /*========================= End of Function ========================*/
690 /*------------------------------------------------------------------*/
692 /* Name - mono_arch_create_trampoline. */
694 /* Function - Create the code that will allow a mono method to */
695 /* invoke a system subroutine. */
697 /*------------------------------------------------------------------*/
700 mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor)
702 guint8 *p, *code_buffer;
705 DEBUG (printf ("\nPInvoke [start emiting]\n"));
706 calculate_sizes (sig, &sz, string_ctor);
708 p = code_buffer = alloc_code_memory (sz.code_size);
709 p = emit_prolog (p, sig, &sz);
710 p = emit_save_parameters (p, sig, &sz);
711 p = emit_call_and_store_retval (p, sig, &sz, string_ctor);
712 p = emit_epilog (p, sig, &sz);
715 if (mprotect (code_buffer, 1024, PROT_READ | PROT_WRITE | PROT_EXEC)) {
716 g_error ("Cannot mprotect trampoline\n");
720 DEBUG (printf ("emited code size: %d\n", p - code_buffer));
722 DEBUG (printf ("PInvoke [end emiting]\n"));
724 return (MonoPIFunc) code_buffer;
727 /*========================= End of Function ========================*/
729 /*------------------------------------------------------------------*/
731 /* Name - mono_arch_create_method_pointer */
733 /* Function - Returns a pointer to a native function that can */
734 /* be used to call the specified method. */
736 /* The function created will receive the arguments */
737 /* according to the calling convention specified in */
740 /* This function works by creating a MonoInvocation */
741 /* structure, filling the fields in and calling */
742 /* ves_exec_method() on it. */
746 /* mono_arch_create_method_pointer (MonoMethod *method) */
747 /* create the unmanaged->managed wrapper */
748 /* register it with mono_jit_info_table_add() */
750 /* What does the unmanaged->managed wrapper do? */
751 /* allocate a MonoInvocation structure (inv) on the stack */
752 /* allocate an array of stackval on the stack with length = */
753 /* method->signature->param_count + 1 [call it stack_args] */
754 /* set inv->ex, inv->ex_handler, inv->parent to NULL */
755 /* set inv->method to method */
756 /* if method is an instance method, set inv->obj to the */
757 /* 'this' argument (the first argument) else set to NULL */
758 /* for each argument to the method call: */
759 /* stackval_from_data (sig->params[i], &stack_args[i], */
760 /* arg, sig->pinvoke); */
763 /* sig - is method->signature */
764 /* &stack_args[i] - is the pointer to the ith element */
765 /* in the stackval array */
766 /* arg - is a pointer to the argument re- */
767 /* ceived by the function according */
768 /* to the call convention. If it */
769 /* gets passed in a register, save */
770 /* on the stack first. */
772 /* set inv->retval to the address of the last element of */
773 /* stack_args [recall we allocated param_count+1 of them] */
774 /* call ves_exec_method(inv) */
775 /* copy the returned value from inv->retval where the calling */
776 /* convention expects to find it on return from the wrap- */
777 /* per [if it's a structure, use stackval_to_data] */
779 /*------------------------------------------------------------------*/
782 mono_arch_create_method_pointer (MonoMethod *method)
784 MonoMethodSignature *sig;
786 guint8 *p, *code_buffer;
787 guint i, align = 0, simple_type, retSize, reg_save = 0,
788 stackval_arg_pos, local_pos, float_pos,
789 local_start, reg_param = 0, stack_param,
790 this_flag, arg_pos, fpr_param, parSize;
793 int *vtbuf, cpos, vt_cur;
796 sz.stack_size = 1024;
801 sig = method->signature;
803 p = code_buffer = g_malloc (sz.code_size);
805 DEBUG (printf ("\nDelegate [start emiting] %s at 0x%08x\n",
808 /*----------------------------------------------------------*/
810 /*----------------------------------------------------------*/
811 s390_stm (p, s390_r6, STK_BASE, STK_BASE, 24);
812 s390_l (p, s390_r7, 0, STK_BASE, MINV_POS);
813 s390_lr (p, s390_r0, STK_BASE);
814 s390_ahi (p, STK_BASE, -(sz.stack_size+MINV_POS));
815 s390_st (p, s390_r0, 0, STK_BASE, 0);
816 s390_la (p, s390_r8, 0, STK_BASE, 4);
817 s390_lr (p, s390_r10, s390_r8);
818 s390_lhi (p, s390_r9, sz.stack_size+92);
819 s390_lhi (p, s390_r11, 0);
820 s390_mvcl(p, s390_r8, s390_r10);
822 /*----------------------------------------------------------*/
823 /* Let's fill MonoInvocation - first zero some fields */
824 /*----------------------------------------------------------*/
825 s390_lhi (p, s390_r0, 0);
826 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex)));
827 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler)));
828 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent)));
829 s390_lhi (p, s390_r0, 1);
830 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, invoke_trap)));
832 /*----------------------------------------------------------*/
833 /* set method pointer */
834 /*----------------------------------------------------------*/
835 s390_bras (p, s390_r13, 4);
836 s390_word (p, method);
837 s390_l (p, s390_r0, 0, s390_r13, 0);
838 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method)));
840 local_start = local_pos = MINV_POS +
841 sizeof (MonoInvocation) + (sig->param_count + 1) * sizeof (stackval);
842 this_flag = (sig->hasthis ? 1 : 0);
844 /*----------------------------------------------------------*/
845 /* if we are returning a structure, checks it's length to */
846 /* see if there's a "hidden" parameter that points to the */
847 /* area. If necessary save this hidden parameter for later */
848 /*----------------------------------------------------------*/
849 if (MONO_TYPE_ISSTRUCT(sig->ret)) {
851 retSize = mono_class_native_size (sig->ret->data.klass, &align);
853 retSize = mono_class_value_size (sig->ret->data.klass, &align);
864 s390_lr(p, s390_r8, s390_r2);
872 s390_st (p, s390_r2 + reg_save, 0, STK_BASE,
873 (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)));
876 s390_st (p, s390_r2 + reg_save, 0, STK_BASE, local_pos);
877 local_pos += sizeof(int);
878 s390_st (p, s390_r0, 0, STK_BASE,
879 (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)));
882 s390_stm (p, s390_r3 + reg_param, s390_r6, STK_BASE, local_pos);
883 local_pos += 4 * sizeof(long);
884 float_pos = local_pos;
885 s390_std (p, s390_f0, 0, STK_BASE, local_pos);
886 local_pos += sizeof(double);
887 s390_std (p, s390_f2, 0, STK_BASE, local_pos);
888 local_pos += sizeof(double);
890 /*----------------------------------------------------------*/
891 /* prepare space for valuetypes */
892 /*----------------------------------------------------------*/
894 vtbuf = alloca (sizeof(int)*sig->param_count);
896 for (i = 0; i < sig->param_count; i++) {
897 MonoType *type = sig->params [i];
899 DEBUG(printf("par: %d type: %d ref: %d\n",i,type->type,type->byref));
900 if (type->type == MONO_TYPE_VALUETYPE) {
901 MonoClass *klass = type->data.klass;
906 size = mono_class_native_size (klass, &align);
908 cpos &= ~(align - 1);
918 /*----------------------------------------------------------*/
919 /* set MonoInvocation::stack_args */
920 /*----------------------------------------------------------*/
921 stackval_arg_pos = MINV_POS + sizeof (MonoInvocation);
922 s390_la (p, s390_r0, 0, STK_BASE, stackval_arg_pos);
923 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args)));
925 /*----------------------------------------------------------*/
926 /* add stackval arguments */
927 /*----------------------------------------------------------*/
928 for (i = 0; i < sig->param_count; ++i) {
929 if (sig->params [i]->byref) {
930 ADD_ISTACK_PARM(0, 1);
932 simple_type = sig->params [i]->type;
934 switch (simple_type) {
936 ADD_ISTACK_PARM(-1, 2);
944 case MONO_TYPE_VALUETYPE:
945 if (sig->params [i]->data.klass->enumtype) {
946 simple_type = sig->params [i]->data.klass->enum_basetype->type;
950 parSize = mono_class_native_size (sig->params [i]->data.klass, &align);
952 parSize = mono_class_value_size (sig->params [i]->data.klass, &align);
958 ADD_PSTACK_PARM(0, 1);
961 ADD_PSTACK_PARM(-1, 2);
968 ADD_ISTACK_PARM(0, 1);
972 if (vtbuf [i] >= 0) {
973 s390_la (p, s390_r3, 0, STK_BASE, vt_cur);
974 s390_st (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
975 s390_la (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
978 s390_la (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
981 /*--------------------------------------*/
982 /* Load the parameter registers for the */
983 /* call to stackval_from_data */
984 /*--------------------------------------*/
985 s390_bras (p, s390_r13, 8);
986 s390_word (p, sig->params [i]);
987 s390_word (p, sig->pinvoke);
988 s390_word (p, stackval_from_data);
989 s390_l (p, s390_r2, 0, s390_r13, 0);
991 s390_l (p, s390_r5, 0, s390_r13, 4);
993 s390_l (p, s390_r1, 0, s390_r13, 8);
994 s390_basr (p, s390_r14, s390_r1);
996 stackval_arg_pos += sizeof(stackval);
998 /* fixme: alignment */
999 DEBUG (printf ("arg_pos %d --> ", arg_pos));
1001 arg_pos += mono_type_native_stack_size (sig->params [i], &align);
1003 arg_pos += mono_type_stack_size (sig->params [i], &align);
1005 DEBUG (printf ("%d\n", stackval_arg_pos));
1008 /*----------------------------------------------------------*/
1009 /* Set return area pointer. */
1010 /*----------------------------------------------------------*/
1011 s390_la (p, s390_r10, 0, STK_BASE, stackval_arg_pos);
1012 s390_st (p, s390_r10, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)));
1013 if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) {
1014 MonoClass *klass = sig->ret->data.klass;
1015 if (!klass->enumtype) {
1016 s390_la (p, s390_r9, 0, s390_r10, sizeof(stackval));
1017 s390_st (p, s390_r9, 0,STK_BASE, stackval_arg_pos);
1018 stackval_arg_pos += sizeof(stackval);
1022 /*----------------------------------------------------------*/
1023 /* call ves_exec_method */
1024 /*----------------------------------------------------------*/
1025 s390_bras (p, s390_r13, 4);
1026 s390_word (p, ves_exec_method);
1027 s390_l (p, s390_r1, 0, s390_r13, 0);
1028 s390_la (p, s390_r2, 0, STK_BASE, MINV_POS);
1029 s390_basr (p, s390_r14, s390_r1);
1031 /*----------------------------------------------------------*/
1032 /* move retval from stackval to proper place (r3/r4/...) */
1033 /*----------------------------------------------------------*/
1034 DEBUG(printf("retType: %d byRef: %d\n",sig->ret->type,sig->ret->byref));
1035 if (sig->ret->byref) {
1036 DEBUG (printf ("ret by ref\n"));
1037 s390_st (p, s390_r2, 0, s390_r10, 0);
1040 DEBUG(printf("Returns: %d\n",sig->ret->type));
1041 switch (sig->ret->type) {
1042 case MONO_TYPE_VOID:
1044 case MONO_TYPE_BOOLEAN:
1046 s390_lhi (p, s390_r2, 0);
1047 s390_ic (p, s390_r2, 0, s390_r10, 0);
1051 s390_lh (p, s390_r2, 0,s390_r10, 0);
1057 case MONO_TYPE_OBJECT:
1058 case MONO_TYPE_STRING:
1059 case MONO_TYPE_CLASS:
1060 s390_l (p, s390_r2, 0, s390_r10, 0);
1063 s390_lm (p, s390_r2, s390_r3, s390_r10, 0);
1066 s390_le (p, s390_f0, 0, s390_r10, 0);
1069 s390_ld (p, s390_f0, 0, s390_r10, 0);
1071 case MONO_TYPE_VALUETYPE:
1072 if (sig->ret->data.klass->enumtype) {
1073 simpletype = sig->ret->data.klass->enum_basetype->type;
1076 /*---------------------------------*/
1077 /* Call stackval_to_data to return */
1079 /*---------------------------------*/
1080 s390_bras (p, s390_r13, 8);
1081 s390_word (p, sig->ret);
1082 s390_word (p, sig->pinvoke);
1083 s390_word (p, stackval_to_data);
1084 s390_l (p, s390_r2, 0, s390_r13, 0);
1085 s390_l (p, s390_r3, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)));
1087 /*------------------------------------------*/
1088 /* Get stackval_to_data to set result area */
1089 /*------------------------------------------*/
1090 s390_lr (p, s390_r4, s390_r8);
1092 /*------------------------------------------*/
1093 /* Give stackval_to_data a temp result area */
1094 /*------------------------------------------*/
1095 s390_la (p, s390_r4, 0, STK_BASE, stackval_arg_pos);
1097 s390_l (p, s390_r5, 0,s390_r13, 4);
1098 s390_l (p, s390_r1, 0, s390_r13, 8);
1099 s390_basr (p, s390_r14, s390_r1);
1104 s390_lhi (p, s390_r2, 0);
1105 s390_ic (p, s390_r2, 0, s390_r10, 0);
1108 s390_lh (p, s390_r2, 0, s390_r10, 0);
1111 s390_l (p, s390_r2, 0, s390_r10, 0);
1114 s390_lm (p, s390_r2, s390_r3, s390_r10, 0);
1117 /*-------------------------------------------------*/
1118 /* stackval_to_data has placed data in result area */
1119 /*-------------------------------------------------*/
1123 g_error ("Type 0x%x not handled yet in thunk creation",
1129 /*----------------------------------------------------------*/
1131 /*----------------------------------------------------------*/
1132 s390_l (p, STK_BASE, 0, STK_BASE, 0);
1133 s390_l (p, s390_r4, 0, STK_BASE, S390_RET_ADDR_OFFSET);
1134 s390_lm (p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET);
1135 s390_br (p, s390_r4);
1137 DEBUG (printf ("emited code size: %d\n", p - code_buffer));
1139 DEBUG (printf ("Delegate [end emiting]\n"));
1141 ji = g_new0 (MonoJitInfo, 1);
1142 ji->method = method;
1143 ji->code_size = p - code_buffer;
1144 ji->code_start = code_buffer;
1146 mono_jit_info_table_add (mono_get_root_domain (), ji);
1148 return ji->code_start;
1151 /*========================= End of Function ========================*/