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:
157 case MONO_TYPE_STRING:
163 case MONO_TYPE_VALUETYPE:
164 if (sig->ret->data.klass->enumtype) {
165 simpletype = sig->ret->data.klass->enum_basetype->type;
170 size = mono_class_native_size (sig->ret->data.klass, &align);
172 size = mono_class_value_size (sig->ret->data.klass, &align);
176 /*----------------------------------*/
177 /* On S/390, structures of size 1, */
178 /* 2, 4, and 8 bytes are returned */
179 /* in (a) register(s). */
180 /*----------------------------------*/
196 g_error ("tramp: cannot handle as return value 0x%x", sig->ret->type);
200 /*----------------------------------------------------------*/
201 /* We determine the size of the parameter code and stack */
202 /* requirements by checking the types and sizes of the */
204 /*----------------------------------------------------------*/
206 for (i = 0; i < sig->param_count; ++i) {
207 if (sig->params [i]->byref) {
208 add_general (&gr, sz, TRUE);
211 simpletype = sig->params [i]->type;
213 switch (simpletype) {
214 case MONO_TYPE_BOOLEAN:
225 case MONO_TYPE_CLASS:
226 case MONO_TYPE_OBJECT:
227 case MONO_TYPE_STRING:
228 add_general (&gr, sz, TRUE);
230 case MONO_TYPE_SZARRAY:
231 add_general (&gr, sz, TRUE);
233 case MONO_TYPE_VALUETYPE:
234 if (sig->params [i]->data.klass->enumtype) {
235 simpletype = sig->params [i]->data.klass->enum_basetype->type;
239 size = mono_class_native_size (sig->params [i]->data.klass, &align);
241 size = mono_class_value_size (sig->params [i]->data.klass, &align);
242 DEBUG(printf("%d typesize: %d (%d)\n",i,size,align));
244 /*----------------------------------*/
245 /* On S/390, structures of size 1, */
246 /* 2, 4, and 8 bytes are passed in */
247 /* (a) register(s). */
248 /*----------------------------------*/
253 add_general(&gr, sz, TRUE);
256 add_general(&gr, sz, FALSE);
259 sz->local_size += (size + (size % align));
264 add_general (&gr, sz, FALSE);
267 if (fr < FLOAT_REGS) {
277 if (fr < FLOAT_REGS) {
282 sz->stack_size += 8 + (sz->stack_size % 8);
286 g_error ("Can't trampoline 0x%x", sig->params [i]->type);
291 /* align stack size to 8 */
292 DEBUG (printf (" stack size: %d (%d)\n"
295 (sz->stack_size + 8) & ~8, sz->stack_size,
296 (sz->code_size),(sz->local_size + 8) & ~8));
297 sz->stack_size = (sz->stack_size + 8) & ~8;
298 sz->local_size = (sz->local_size + 8) & ~8;
301 /*========================= End of Function ========================*/
303 /*------------------------------------------------------------------*/
305 /* Name - emit_prolog */
307 /* Function - Create the instructions that implement the stand- */
308 /* ard function prolog according to the S/390 ABI. */
310 /*------------------------------------------------------------------*/
312 static inline guint8 *
313 emit_prolog (guint8 *p, MonoMethodSignature *sig, size_data *sz)
317 stack_size = sz->stack_size + sz->local_size;
319 /* function prolog */
320 s390_stm (p, s390_r6, STK_BASE, STK_BASE, 24);
321 s390_l (p, s390_r7, 0, STK_BASE, MINV_POS);
322 s390_lr (p, s390_r11, STK_BASE);
323 s390_ahi (p, STK_BASE, -stack_size);
324 s390_st (p, s390_r11, 0, STK_BASE, 0);
326 /*-----------------------------------------*/
328 /* - address of "callme" */
329 /* - address of "retval" */
330 /* - address of "arguments" */
331 /*-----------------------------------------*/
332 s390_lr (p, s390_r9, s390_r2);
333 s390_lr (p, s390_r8, s390_r3);
334 s390_lr (p, s390_r10, s390_r5);
339 /*========================= End of Function ========================*/
341 /*------------------------------------------------------------------*/
343 /* Name - emit_save_parameters */
345 /* Function - Create the instructions that load registers with */
346 /* parameters, place others on the stack according */
347 /* to the S/390 ABI. */
349 /* The resulting function takes the form: */
350 /* void func (void (*callme)(), void *retval, */
351 /* void *this_obj, stackval *arguments); */
353 /*------------------------------------------------------------------*/
355 inline static guint8*
356 emit_save_parameters (guint8 *p, MonoMethodSignature *sig, size_data *sz)
358 guint i, fr, gr, act_strs, align,
359 stack_par_pos, size, local_pos;
362 /*----------------------------------------------------------*/
363 /* If a structure on stack is being returned, reserve r2 */
364 /* to point to an area where it can be passed. */
365 /*----------------------------------------------------------*/
372 stack_par_pos = S390_MINIMAL_STACK_SIZE;
373 local_pos = sz->stack_size;
376 s390_lr (p, s390_r2 + gr, s390_r4);
381 for (i = 0; i < sig->param_count; ++i) {
382 DEBUG(printf("par: %d type: %d ref: %d\n",i,sig->params[i]->type,sig->params[i]->byref));
383 if (sig->params [i]->byref) {
384 if (gr < GENERAL_REGS) {
385 s390_l (p, s390_r2 + gr, 0, ARG_BASE, STKARG);
388 s390_l (p, s390_r0, 0, ARG_BASE, STKARG);
389 s390_st (p, s390_r0, 0, STK_BASE, stack_par_pos);
390 stack_par_pos += sizeof(long);
394 simpletype = sig->params [i]->type;
396 switch (simpletype) {
397 case MONO_TYPE_BOOLEAN:
408 case MONO_TYPE_CLASS:
409 case MONO_TYPE_OBJECT:
410 case MONO_TYPE_STRING:
411 case MONO_TYPE_SZARRAY:
412 if (gr < GENERAL_REGS) {
413 s390_l (p, s390_r2 + gr, 0, ARG_BASE, STKARG);
416 s390_l (p, s390_r0, 0, ARG_BASE, STKARG);
417 s390_st (p, s390_r0, 0, STK_BASE, stack_par_pos);
418 stack_par_pos += sizeof(long);
421 case MONO_TYPE_VALUETYPE:
422 if (sig->params [i]->data.klass->enumtype) {
423 simpletype = sig->params [i]->data.klass->enum_basetype->type;
427 size = mono_class_native_size (sig->params [i]->data.klass, &align);
429 size = mono_class_value_size (sig->params [i]->data.klass, &align);
430 DEBUG(printf("parStruct - size %d pinvoke: %d\n",size,sig->pinvoke));
436 if (gr < GENERAL_REGS) {
437 s390_l (p, s390_r2 + gr, 0,ARG_BASE, STKARG);
438 s390_l (p, s390_r2 + gr, 0, s390_r2 + gr, 0);
441 stack_par_pos += (stack_par_pos % align);
442 s390_l (p, s390_r10, 0,ARG_BASE, STKARG);
443 s390_l (p, s390_r10, 0, s390_r10, 0);
444 s390_st (p, s390_r10, 0, STK_BASE, stack_par_pos);
445 stack_par_pos += sizeof(long);
449 if (gr < GENERAL_REGS-1) {
450 s390_l (p, s390_r2 + gr, 0, ARG_BASE, STKARG);
451 s390_lm (p, s390_r2 + gr, s390_r3 + gr, s390_r2 + gr, 0);
453 stack_par_pos += (stack_par_pos % align);
454 s390_l (p, s390_r10, 0, ARG_BASE, STKARG);
455 s390_mvc (p, sizeof(long long), STK_BASE, stack_par_pos, s390_r10, 0);
456 stack_par_pos += sizeof(long long);
461 local_pos += (local_pos % align);
462 s390_l (p, s390_r13, 0, ARG_BASE, STKARG);
463 s390_mvc (p, size, STK_BASE, local_pos, s390_r13, 0);
464 s390_la (p, s390_r13, 0, STK_BASE, local_pos);
467 local_pos += (local_pos % align);
468 s390_bras (p, s390_r13, 4);
470 s390_l (p, s390_r1, 0, s390_r13, 0);
471 s390_l (p, s390_r0, 0, ARG_BASE, STKARG);
472 s390_lr (p, s390_r14, s390_r12);
473 s390_la (p, s390_r12, 0, STK_BASE, local_pos);
474 s390_lr (p, s390_r13, s390_r1);
475 s390_mvcl (p, s390_r12, s390_r0);
476 s390_lr (p, s390_r12, s390_r14);
477 s390_la (p, s390_r13, 0, STK_BASE, local_pos);
480 if (gr < GENERAL_REGS) {
481 s390_lr (p, s390_r2 + gr, s390_r13);
484 s390_st (p, s390_r13, 0, STK_BASE, stack_par_pos);
485 stack_par_pos += sizeof(long);
490 if (gr < GENERAL_REGS-1) {
491 s390_lm (p, s390_r2 + gr, s390_r2 + gr + 1, ARG_BASE, STKARG);
495 *(guint32 *) p &= ~7;
496 s390_mvc (p, sizeof(long long), STK_BASE, stack_par_pos, ARG_BASE, STKARG);
497 stack_par_pos += sizeof(long long) + (stack_par_pos % sizeof(long long));
501 if (fr < FLOAT_REGS) {
502 s390_le (p, s390_r0 + fr, 0, ARG_BASE, STKARG);
505 s390_mvc (p, sizeof(float), STK_BASE, stack_par_pos, ARG_BASE, STKARG);
506 stack_par_pos += sizeof(float);
510 if (fr < FLOAT_REGS) {
511 s390_ld (p, s390_r0 + fr, 0, ARG_BASE, STKARG);
515 *(guint32 *) p &= ~7;
516 s390_mvc (p, sizeof(double), STK_BASE, stack_par_pos, ARG_BASE, STKARG);
517 stack_par_pos += sizeof(long long) + (stack_par_pos % sizeof(long long));
521 g_error ("Can't trampoline 0x%x", sig->params [i]->type);
525 /*----------------------------------------------------------*/
526 /* If we're returning a structure but not in a register */
527 /* then point the result area for the called routine */
528 /*----------------------------------------------------------*/
530 s390_l (p, s390_r2, 0, s390_r8, 0);
536 /*========================= End of Function ========================*/
538 /*------------------------------------------------------------------*/
540 /* Name - alloc_code_memory */
542 /* Function - Allocate space to place the emitted code. */
544 /*------------------------------------------------------------------*/
546 static inline guint8 *
547 alloc_code_memory (guint code_size)
552 p = g_malloc (code_size + PAGESIZE - 1);
554 /* Align to a multiple of PAGESIZE, assumed to be a power of two */
555 p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1));
557 p = g_malloc (code_size);
559 DEBUG (printf (" align: %p (%d)\n", p, (guint)p % 4));
564 /*========================= End of Function ========================*/
566 /*------------------------------------------------------------------*/
568 /* Name - emit_call_and_store_retval */
570 /* Function - Emit code that will implement the call to the */
571 /* desired function, and unload the result according */
572 /* to the S390 ABI for the type of value returned */
574 /*------------------------------------------------------------------*/
576 static inline guint8 *
577 emit_call_and_store_retval (guint8 *p, MonoMethodSignature *sig,
578 size_data *sz, gboolean string_ctor)
581 guint retSize, align;
584 s390_basr (p, s390_r14, s390_r9);
586 /* get return value */
587 if (sig->ret->byref || string_ctor) {
588 s390_st (p, s390_r2, 0, s390_r8, 0);
590 simpletype = sig->ret->type;
592 switch (simpletype) {
593 case MONO_TYPE_BOOLEAN:
596 s390_stc (p, s390_r2, 0, s390_r8, 0);
601 s390_sth (p, s390_r2, 0, s390_r8, 0);
607 case MONO_TYPE_CLASS:
608 case MONO_TYPE_OBJECT:
609 case MONO_TYPE_SZARRAY:
610 case MONO_TYPE_ARRAY:
611 case MONO_TYPE_STRING:
612 s390_st (p, s390_r2, 0, s390_r8, 0);
615 s390_ste (p, s390_f0, 0, s390_r8, 0);
618 s390_std (p, s390_f0, 0, s390_r8, 0);
621 s390_stm (p, s390_r2, s390_r3, s390_r8, 0);
623 case MONO_TYPE_VALUETYPE:
624 if (sig->ret->data.klass->enumtype) {
625 simpletype = sig->ret->data.klass->enum_basetype->type;
629 retSize = mono_class_native_size (sig->ret->data.klass, &align);
631 retSize = mono_class_value_size (sig->ret->data.klass, &align);
632 printf("Returning %d bytes for type %d (%d)\n",retSize,simpletype,sig->pinvoke);
637 s390_stc (p, s390_r2, 0, s390_r8, 0);
640 s390_sth (p, s390_r2, 0, s390_r8, 0);
643 s390_st (p, s390_r2, 0, s390_r8, 0);
646 s390_stm (p, s390_r2, s390_r3, s390_r8, 0);
649 /*------------------------------------------*/
650 /* The callee has already placed the result */
651 /* in the required area */
652 /*------------------------------------------*/
659 g_error ("Can't handle as return value 0x%x",
667 /*========================= End of Function ========================*/
669 /*------------------------------------------------------------------*/
671 /* Name - emit_epilog */
673 /* Function - Create the instructions that implement the stand- */
674 /* ard function epilog according to the S/390 ABI. */
676 /*------------------------------------------------------------------*/
678 static inline guint8 *
679 emit_epilog (guint8 *p, MonoMethodSignature *sig, size_data *sz)
681 /* function epilog */
682 s390_l (p, STK_BASE, 0, STK_BASE, 0);
683 s390_l (p, s390_r4, 0, STK_BASE, 56);
684 s390_lm (p, s390_r6, STK_BASE, STK_BASE, 24);
685 s390_br (p, s390_r4);
690 /*========================= End of Function ========================*/
692 /*------------------------------------------------------------------*/
694 /* Name - mono_arch_create_trampoline. */
696 /* Function - Create the code that will allow a mono method to */
697 /* invoke a system subroutine. */
699 /*------------------------------------------------------------------*/
702 mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor)
704 guint8 *p, *code_buffer;
707 DEBUG (printf ("\nPInvoke [start emiting]\n"));
708 calculate_sizes (sig, &sz, string_ctor);
710 p = code_buffer = alloc_code_memory (sz.code_size);
711 p = emit_prolog (p, sig, &sz);
712 p = emit_save_parameters (p, sig, &sz);
713 p = emit_call_and_store_retval (p, sig, &sz, string_ctor);
714 p = emit_epilog (p, sig, &sz);
717 if (mprotect (code_buffer, 1024, PROT_READ | PROT_WRITE | PROT_EXEC)) {
718 g_error ("Cannot mprotect trampoline\n");
722 DEBUG (printf ("emited code size: %d\n", p - code_buffer));
724 DEBUG (printf ("PInvoke [end emiting]\n"));
726 return (MonoPIFunc) code_buffer;
729 /*========================= End of Function ========================*/
731 /*------------------------------------------------------------------*/
733 /* Name - mono_arch_create_method_pointer */
735 /* Function - Returns a pointer to a native function that can */
736 /* be used to call the specified method. */
738 /* The function created will receive the arguments */
739 /* according to the calling convention specified in */
742 /* This function works by creating a MonoInvocation */
743 /* structure, filling the fields in and calling */
744 /* ves_exec_method() on it. */
748 /* mono_arch_create_method_pointer (MonoMethod *method) */
749 /* create the unmanaged->managed wrapper */
750 /* register it with mono_jit_info_table_add() */
752 /* What does the unmanaged->managed wrapper do? */
753 /* allocate a MonoInvocation structure (inv) on the stack */
754 /* allocate an array of stackval on the stack with length = */
755 /* method->signature->param_count + 1 [call it stack_args] */
756 /* set inv->ex, inv->ex_handler, inv->parent to NULL */
757 /* set inv->method to method */
758 /* if method is an instance method, set inv->obj to the */
759 /* 'this' argument (the first argument) else set to NULL */
760 /* for each argument to the method call: */
761 /* stackval_from_data (sig->params[i], &stack_args[i], */
762 /* arg, sig->pinvoke); */
765 /* sig - is method->signature */
766 /* &stack_args[i] - is the pointer to the ith element */
767 /* in the stackval array */
768 /* arg - is a pointer to the argument re- */
769 /* ceived by the function according */
770 /* to the call convention. If it */
771 /* gets passed in a register, save */
772 /* on the stack first. */
774 /* set inv->retval to the address of the last element of */
775 /* stack_args [recall we allocated param_count+1 of them] */
776 /* call ves_exec_method(inv) */
777 /* copy the returned value from inv->retval where the calling */
778 /* convention expects to find it on return from the wrap- */
779 /* per [if it's a structure, use stackval_to_data] */
781 /*------------------------------------------------------------------*/
784 mono_arch_create_method_pointer (MonoMethod *method)
786 MonoMethodSignature *sig;
788 guint8 *p, *code_buffer;
789 guint i, align = 0, simple_type, retSize, reg_save = 0,
790 stackval_arg_pos, local_pos, float_pos,
791 local_start, reg_param = 0, stack_param,
792 this_flag, arg_pos, fpr_param, parSize;
795 int *vtbuf, cpos, vt_cur;
798 sz.stack_size = 1024;
803 sig = method->signature;
805 p = code_buffer = g_malloc (sz.code_size);
807 DEBUG (printf ("\nDelegate [start emiting] %s at 0x%08x\n",
810 /*----------------------------------------------------------*/
812 /*----------------------------------------------------------*/
813 s390_stm (p, s390_r6, STK_BASE, STK_BASE, 24);
814 s390_l (p, s390_r7, 0, STK_BASE, MINV_POS);
815 s390_lr (p, s390_r0, STK_BASE);
816 s390_ahi (p, STK_BASE, -(sz.stack_size+MINV_POS));
817 s390_st (p, s390_r0, 0, STK_BASE, 0);
818 s390_la (p, s390_r8, 0, STK_BASE, 4);
819 s390_lr (p, s390_r10, s390_r8);
820 s390_lhi (p, s390_r9, sz.stack_size+92);
821 s390_lhi (p, s390_r11, 0);
822 s390_mvcl(p, s390_r8, s390_r10);
824 /*----------------------------------------------------------*/
825 /* Let's fill MonoInvocation - first zero some fields */
826 /*----------------------------------------------------------*/
827 s390_lhi (p, s390_r0, 0);
828 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex)));
829 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler)));
830 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent)));
831 s390_lhi (p, s390_r0, 1);
832 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, invoke_trap)));
834 /*----------------------------------------------------------*/
835 /* set method pointer */
836 /*----------------------------------------------------------*/
837 s390_bras (p, s390_r13, 4);
838 s390_word (p, method);
839 s390_l (p, s390_r0, 0, s390_r13, 0);
840 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method)));
842 local_start = local_pos = MINV_POS +
843 sizeof (MonoInvocation) + (sig->param_count + 1) * sizeof (stackval);
844 this_flag = (sig->hasthis ? 1 : 0);
846 /*----------------------------------------------------------*/
847 /* if we are returning a structure, checks it's length to */
848 /* see if there's a "hidden" parameter that points to the */
849 /* area. If necessary save this hidden parameter for later */
850 /*----------------------------------------------------------*/
851 if (MONO_TYPE_ISSTRUCT(sig->ret)) {
853 retSize = mono_class_native_size (sig->ret->data.klass, &align);
855 retSize = mono_class_value_size (sig->ret->data.klass, &align);
866 s390_lr(p, s390_r8, s390_r2);
874 s390_st (p, s390_r2 + reg_save, 0, STK_BASE,
875 (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)));
878 s390_st (p, s390_r2 + reg_save, 0, STK_BASE, local_pos);
879 local_pos += sizeof(int);
880 s390_st (p, s390_r0, 0, STK_BASE,
881 (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)));
884 s390_stm (p, s390_r3 + reg_param, s390_r6, STK_BASE, local_pos);
885 local_pos += 4 * sizeof(long);
886 float_pos = local_pos;
887 s390_std (p, s390_f0, 0, STK_BASE, local_pos);
888 local_pos += sizeof(double);
889 s390_std (p, s390_f2, 0, STK_BASE, local_pos);
890 local_pos += sizeof(double);
892 /*----------------------------------------------------------*/
893 /* prepare space for valuetypes */
894 /*----------------------------------------------------------*/
896 vtbuf = alloca (sizeof(int)*sig->param_count);
898 for (i = 0; i < sig->param_count; i++) {
899 MonoType *type = sig->params [i];
901 DEBUG(printf("par: %d type: %d ref: %d\n",i,type->type,type->byref));
902 if (type->type == MONO_TYPE_VALUETYPE) {
903 MonoClass *klass = type->data.klass;
908 size = mono_class_native_size (klass, &align);
910 cpos &= ~(align - 1);
920 /*----------------------------------------------------------*/
921 /* set MonoInvocation::stack_args */
922 /*----------------------------------------------------------*/
923 stackval_arg_pos = MINV_POS + sizeof (MonoInvocation);
924 s390_la (p, s390_r0, 0, STK_BASE, stackval_arg_pos);
925 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args)));
927 /*----------------------------------------------------------*/
928 /* add stackval arguments */
929 /*----------------------------------------------------------*/
930 for (i = 0; i < sig->param_count; ++i) {
931 if (sig->params [i]->byref) {
932 ADD_ISTACK_PARM(0, 1);
934 simple_type = sig->params [i]->type;
936 switch (simple_type) {
938 ADD_ISTACK_PARM(-1, 2);
946 case MONO_TYPE_VALUETYPE:
947 if (sig->params [i]->data.klass->enumtype) {
948 simple_type = sig->params [i]->data.klass->enum_basetype->type;
952 parSize = mono_class_native_size (sig->params [i]->data.klass, &align);
954 parSize = mono_class_value_size (sig->params [i]->data.klass, &align);
960 ADD_PSTACK_PARM(0, 1);
963 ADD_PSTACK_PARM(-1, 2);
970 ADD_ISTACK_PARM(0, 1);
974 if (vtbuf [i] >= 0) {
975 s390_la (p, s390_r3, 0, STK_BASE, vt_cur);
976 s390_st (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
977 s390_la (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
980 s390_la (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
983 /*--------------------------------------*/
984 /* Load the parameter registers for the */
985 /* call to stackval_from_data */
986 /*--------------------------------------*/
987 s390_bras (p, s390_r13, 8);
988 s390_word (p, sig->params [i]);
989 s390_word (p, sig->pinvoke);
990 s390_word (p, stackval_from_data);
991 s390_l (p, s390_r2, 0, s390_r13, 0);
993 s390_l (p, s390_r5, 0, s390_r13, 4);
995 s390_l (p, s390_r1, 0, s390_r13, 8);
996 s390_basr (p, s390_r14, s390_r1);
998 stackval_arg_pos += sizeof(stackval);
1000 /* fixme: alignment */
1001 DEBUG (printf ("arg_pos %d --> ", arg_pos));
1003 arg_pos += mono_type_native_stack_size (sig->params [i], &align);
1005 arg_pos += mono_type_stack_size (sig->params [i], &align);
1007 DEBUG (printf ("%d\n", stackval_arg_pos));
1010 /*----------------------------------------------------------*/
1011 /* Set return area pointer. */
1012 /*----------------------------------------------------------*/
1013 s390_la (p, s390_r10, 0, STK_BASE, stackval_arg_pos);
1014 s390_st (p, s390_r10, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)));
1015 if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) {
1016 MonoClass *klass = sig->ret->data.klass;
1017 if (!klass->enumtype) {
1018 s390_la (p, s390_r9, 0, s390_r10, sizeof(stackval));
1019 s390_st (p, s390_r9, 0,STK_BASE, stackval_arg_pos);
1020 stackval_arg_pos += sizeof(stackval);
1024 /*----------------------------------------------------------*/
1025 /* call ves_exec_method */
1026 /*----------------------------------------------------------*/
1027 s390_bras (p, s390_r13, 4);
1028 s390_word (p, ves_exec_method);
1029 s390_l (p, s390_r1, 0, s390_r13, 0);
1030 s390_la (p, s390_r2, 0, STK_BASE, MINV_POS);
1031 s390_basr (p, s390_r14, s390_r1);
1033 /*----------------------------------------------------------*/
1034 /* move retval from stackval to proper place (r3/r4/...) */
1035 /*----------------------------------------------------------*/
1036 DEBUG(printf("retType: %d byRef: %d\n",sig->ret->type,sig->ret->byref));
1037 if (sig->ret->byref) {
1038 DEBUG (printf ("ret by ref\n"));
1039 s390_st (p, s390_r2, 0, s390_r10, 0);
1042 DEBUG(printf("Returns: %d\n",sig->ret->type));
1043 switch (sig->ret->type) {
1044 case MONO_TYPE_VOID:
1046 case MONO_TYPE_BOOLEAN:
1048 s390_lhi (p, s390_r2, 0);
1049 s390_ic (p, s390_r2, 0, s390_r10, 0);
1053 s390_lh (p, s390_r2, 0,s390_r10, 0);
1059 case MONO_TYPE_OBJECT:
1060 case MONO_TYPE_STRING:
1061 case MONO_TYPE_CLASS:
1062 s390_l (p, s390_r2, 0, s390_r10, 0);
1065 s390_lm (p, s390_r2, s390_r3, s390_r10, 0);
1068 s390_le (p, s390_f0, 0, s390_r10, 0);
1071 s390_ld (p, s390_f0, 0, s390_r10, 0);
1073 case MONO_TYPE_VALUETYPE:
1074 if (sig->ret->data.klass->enumtype) {
1075 simpletype = sig->ret->data.klass->enum_basetype->type;
1078 /*---------------------------------*/
1079 /* Call stackval_to_data to return */
1081 /*---------------------------------*/
1082 s390_bras (p, s390_r13, 8);
1083 s390_word (p, sig->ret);
1084 s390_word (p, sig->pinvoke);
1085 s390_word (p, stackval_to_data);
1086 s390_l (p, s390_r2, 0, s390_r13, 0);
1087 s390_l (p, s390_r3, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)));
1089 /*------------------------------------------*/
1090 /* Get stackval_to_data to set result area */
1091 /*------------------------------------------*/
1092 s390_lr (p, s390_r4, s390_r8);
1094 /*------------------------------------------*/
1095 /* Give stackval_to_data a temp result area */
1096 /*------------------------------------------*/
1097 s390_la (p, s390_r4, 0, STK_BASE, stackval_arg_pos);
1099 s390_l (p, s390_r5, 0,s390_r13, 4);
1100 s390_l (p, s390_r1, 0, s390_r13, 8);
1101 s390_basr (p, s390_r14, s390_r1);
1106 s390_lhi (p, s390_r2, 0);
1107 s390_ic (p, s390_r2, 0, s390_r10, 0);
1110 s390_lh (p, s390_r2, 0, s390_r10, 0);
1113 s390_l (p, s390_r2, 0, s390_r10, 0);
1116 s390_lm (p, s390_r2, s390_r3, s390_r10, 0);
1119 /*-------------------------------------------------*/
1120 /* stackval_to_data has placed data in result area */
1121 /*-------------------------------------------------*/
1126 g_error ("Type 0x%x not handled yet in thunk creation",
1132 /*----------------------------------------------------------*/
1134 /*----------------------------------------------------------*/
1135 s390_l (p, STK_BASE, 0, STK_BASE, 0);
1136 s390_l (p, s390_r4, 0, STK_BASE, S390_RET_ADDR_OFFSET);
1137 s390_lm (p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET);
1138 s390_br (p, s390_r4);
1140 DEBUG (printf ("emited code size: %d\n", p - code_buffer));
1142 DEBUG (printf ("Delegate [end emiting]\n"));
1144 ji = g_new0 (MonoJitInfo, 1);
1145 ji->method = method;
1146 ji->code_size = p - code_buffer;
1147 ji->code_start = code_buffer;
1149 mono_jit_info_table_add (mono_get_root_domain (), ji);
1151 return ji->code_start;
1154 /*========================= End of Function ========================*/