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 /*------------------------------------------*/
658 g_error ("Can't handle as return value 0x%x",
666 /*========================= End of Function ========================*/
668 /*------------------------------------------------------------------*/
670 /* Name - emit_epilog */
672 /* Function - Create the instructions that implement the stand- */
673 /* ard function epilog according to the S/390 ABI. */
675 /*------------------------------------------------------------------*/
677 static inline guint8 *
678 emit_epilog (guint8 *p, MonoMethodSignature *sig, size_data *sz)
680 /* function epilog */
681 s390_l (p, STK_BASE, 0, STK_BASE, 0);
682 s390_l (p, s390_r4, 0, STK_BASE, 56);
683 s390_lm (p, s390_r6, STK_BASE, STK_BASE, 24);
684 s390_br (p, s390_r4);
689 /*========================= End of Function ========================*/
691 /*------------------------------------------------------------------*/
693 /* Name - mono_arch_create_trampoline. */
695 /* Function - Create the code that will allow a mono method to */
696 /* invoke a system subroutine. */
698 /*------------------------------------------------------------------*/
701 mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor)
703 guint8 *p, *code_buffer;
706 DEBUG (printf ("\nPInvoke [start emiting]\n"));
707 calculate_sizes (sig, &sz, string_ctor);
709 p = code_buffer = alloc_code_memory (sz.code_size);
710 p = emit_prolog (p, sig, &sz);
711 p = emit_save_parameters (p, sig, &sz);
712 p = emit_call_and_store_retval (p, sig, &sz, string_ctor);
713 p = emit_epilog (p, sig, &sz);
716 if (mprotect (code_buffer, 1024, PROT_READ | PROT_WRITE | PROT_EXEC)) {
717 g_error ("Cannot mprotect trampoline\n");
721 DEBUG (printf ("emited code size: %d\n", p - code_buffer));
723 DEBUG (printf ("PInvoke [end emiting]\n"));
725 return (MonoPIFunc) code_buffer;
728 /*========================= End of Function ========================*/
730 /*------------------------------------------------------------------*/
732 /* Name - mono_arch_create_method_pointer */
734 /* Function - Returns a pointer to a native function that can */
735 /* be used to call the specified method. */
737 /* The function created will receive the arguments */
738 /* according to the calling convention specified in */
741 /* This function works by creating a MonoInvocation */
742 /* structure, filling the fields in and calling */
743 /* ves_exec_method() on it. */
747 /* mono_arch_create_method_pointer (MonoMethod *method) */
748 /* create the unmanaged->managed wrapper */
749 /* register it with mono_jit_info_table_add() */
751 /* What does the unmanaged->managed wrapper do? */
752 /* allocate a MonoInvocation structure (inv) on the stack */
753 /* allocate an array of stackval on the stack with length = */
754 /* method->signature->param_count + 1 [call it stack_args] */
755 /* set inv->ex, inv->ex_handler, inv->parent to NULL */
756 /* set inv->method to method */
757 /* if method is an instance method, set inv->obj to the */
758 /* 'this' argument (the first argument) else set to NULL */
759 /* for each argument to the method call: */
760 /* stackval_from_data (sig->params[i], &stack_args[i], */
761 /* arg, sig->pinvoke); */
764 /* sig - is method->signature */
765 /* &stack_args[i] - is the pointer to the ith element */
766 /* in the stackval array */
767 /* arg - is a pointer to the argument re- */
768 /* ceived by the function according */
769 /* to the call convention. If it */
770 /* gets passed in a register, save */
771 /* on the stack first. */
773 /* set inv->retval to the address of the last element of */
774 /* stack_args [recall we allocated param_count+1 of them] */
775 /* call ves_exec_method(inv) */
776 /* copy the returned value from inv->retval where the calling */
777 /* convention expects to find it on return from the wrap- */
778 /* per [if it's a structure, use stackval_to_data] */
780 /*------------------------------------------------------------------*/
783 mono_arch_create_method_pointer (MonoMethod *method)
785 MonoMethodSignature *sig;
787 guint8 *p, *code_buffer;
788 guint i, align = 0, simple_type, retSize, reg_save = 0,
789 stackval_arg_pos, local_pos, float_pos,
790 local_start, reg_param = 0, stack_param,
791 this_flag, arg_pos, fpr_param, parSize;
794 int *vtbuf, cpos, vt_cur;
797 sz.stack_size = 1024;
802 sig = method->signature;
804 p = code_buffer = g_malloc (sz.code_size);
806 DEBUG (printf ("\nDelegate [start emiting] %s at 0x%08x\n",
809 /*----------------------------------------------------------*/
811 /*----------------------------------------------------------*/
812 s390_stm (p, s390_r6, STK_BASE, STK_BASE, 24);
813 s390_l (p, s390_r7, 0, STK_BASE, MINV_POS);
814 s390_lr (p, s390_r0, STK_BASE);
815 s390_ahi (p, STK_BASE, -(sz.stack_size+MINV_POS));
816 s390_st (p, s390_r0, 0, STK_BASE, 0);
817 s390_la (p, s390_r8, 0, STK_BASE, 4);
818 s390_lr (p, s390_r10, s390_r8);
819 s390_lhi (p, s390_r9, sz.stack_size+92);
820 s390_lhi (p, s390_r11, 0);
821 s390_mvcl(p, s390_r8, s390_r10);
823 /*----------------------------------------------------------*/
824 /* Let's fill MonoInvocation - first zero some fields */
825 /*----------------------------------------------------------*/
826 s390_lhi (p, s390_r0, 0);
827 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex)));
828 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler)));
829 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent)));
830 s390_lhi (p, s390_r0, 1);
831 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, invoke_trap)));
833 /*----------------------------------------------------------*/
834 /* set method pointer */
835 /*----------------------------------------------------------*/
836 s390_bras (p, s390_r13, 4);
837 s390_word (p, method);
838 s390_l (p, s390_r0, 0, s390_r13, 0);
839 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method)));
841 local_start = local_pos = MINV_POS +
842 sizeof (MonoInvocation) + (sig->param_count + 1) * sizeof (stackval);
843 this_flag = (sig->hasthis ? 1 : 0);
845 /*----------------------------------------------------------*/
846 /* if we are returning a structure, checks it's length to */
847 /* see if there's a "hidden" parameter that points to the */
848 /* area. If necessary save this hidden parameter for later */
849 /*----------------------------------------------------------*/
850 if (MONO_TYPE_ISSTRUCT(sig->ret)) {
852 retSize = mono_class_native_size (sig->ret->data.klass, &align);
854 retSize = mono_class_value_size (sig->ret->data.klass, &align);
865 s390_lr(p, s390_r8, s390_r2);
873 s390_st (p, s390_r2 + reg_save, 0, STK_BASE,
874 (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)));
877 s390_st (p, s390_r2 + reg_save, 0, STK_BASE, local_pos);
878 local_pos += sizeof(int);
879 s390_st (p, s390_r0, 0, STK_BASE,
880 (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)));
883 s390_stm (p, s390_r3 + reg_param, s390_r6, STK_BASE, local_pos);
884 local_pos += 4 * sizeof(long);
885 float_pos = local_pos;
886 s390_std (p, s390_f0, 0, STK_BASE, local_pos);
887 local_pos += sizeof(double);
888 s390_std (p, s390_f2, 0, STK_BASE, local_pos);
889 local_pos += sizeof(double);
891 /*----------------------------------------------------------*/
892 /* prepare space for valuetypes */
893 /*----------------------------------------------------------*/
895 vtbuf = alloca (sizeof(int)*sig->param_count);
897 for (i = 0; i < sig->param_count; i++) {
898 MonoType *type = sig->params [i];
900 DEBUG(printf("par: %d type: %d ref: %d\n",i,type->type,type->byref));
901 if (type->type == MONO_TYPE_VALUETYPE) {
902 MonoClass *klass = type->data.klass;
907 size = mono_class_native_size (klass, &align);
909 cpos &= ~(align - 1);
919 /*----------------------------------------------------------*/
920 /* set MonoInvocation::stack_args */
921 /*----------------------------------------------------------*/
922 stackval_arg_pos = MINV_POS + sizeof (MonoInvocation);
923 s390_la (p, s390_r0, 0, STK_BASE, stackval_arg_pos);
924 s390_st (p, s390_r0, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args)));
926 /*----------------------------------------------------------*/
927 /* add stackval arguments */
928 /*----------------------------------------------------------*/
929 for (i = 0; i < sig->param_count; ++i) {
930 if (sig->params [i]->byref) {
931 ADD_ISTACK_PARM(0, 1);
933 simple_type = sig->params [i]->type;
935 switch (simple_type) {
937 ADD_ISTACK_PARM(-1, 2);
945 case MONO_TYPE_VALUETYPE:
946 if (sig->params [i]->data.klass->enumtype) {
947 simple_type = sig->params [i]->data.klass->enum_basetype->type;
951 parSize = mono_class_native_size (sig->params [i]->data.klass, &align);
953 parSize = mono_class_value_size (sig->params [i]->data.klass, &align);
959 ADD_PSTACK_PARM(0, 1);
962 ADD_PSTACK_PARM(-1, 2);
969 ADD_ISTACK_PARM(0, 1);
973 if (vtbuf [i] >= 0) {
974 s390_la (p, s390_r3, 0, STK_BASE, vt_cur);
975 s390_st (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
976 s390_la (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
979 s390_la (p, s390_r3, 0, STK_BASE, stackval_arg_pos);
982 /*--------------------------------------*/
983 /* Load the parameter registers for the */
984 /* call to stackval_from_data */
985 /*--------------------------------------*/
986 s390_bras (p, s390_r13, 8);
987 s390_word (p, sig->params [i]);
988 s390_word (p, sig->pinvoke);
989 s390_word (p, stackval_from_data);
990 s390_l (p, s390_r2, 0, s390_r13, 0);
992 s390_l (p, s390_r5, 0, s390_r13, 4);
994 s390_l (p, s390_r1, 0, s390_r13, 8);
995 s390_basr (p, s390_r14, s390_r1);
997 stackval_arg_pos += sizeof(stackval);
999 /* fixme: alignment */
1000 DEBUG (printf ("arg_pos %d --> ", arg_pos));
1002 arg_pos += mono_type_native_stack_size (sig->params [i], &align);
1004 arg_pos += mono_type_stack_size (sig->params [i], &align);
1006 DEBUG (printf ("%d\n", stackval_arg_pos));
1009 /*----------------------------------------------------------*/
1010 /* Set return area pointer. */
1011 /*----------------------------------------------------------*/
1012 s390_la (p, s390_r10, 0, STK_BASE, stackval_arg_pos);
1013 s390_st (p, s390_r10, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)));
1014 if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) {
1015 MonoClass *klass = sig->ret->data.klass;
1016 if (!klass->enumtype) {
1017 s390_la (p, s390_r9, 0, s390_r10, sizeof(stackval));
1018 s390_st (p, s390_r9, 0,STK_BASE, stackval_arg_pos);
1019 stackval_arg_pos += sizeof(stackval);
1023 /*----------------------------------------------------------*/
1024 /* call ves_exec_method */
1025 /*----------------------------------------------------------*/
1026 s390_bras (p, s390_r13, 4);
1027 s390_word (p, ves_exec_method);
1028 s390_l (p, s390_r1, 0, s390_r13, 0);
1029 s390_la (p, s390_r2, 0, STK_BASE, MINV_POS);
1030 s390_basr (p, s390_r14, s390_r1);
1032 /*----------------------------------------------------------*/
1033 /* move retval from stackval to proper place (r3/r4/...) */
1034 /*----------------------------------------------------------*/
1035 DEBUG(printf("retType: %d byRef: %d\n",sig->ret->type,sig->ret->byref));
1036 if (sig->ret->byref) {
1037 DEBUG (printf ("ret by ref\n"));
1038 s390_st (p, s390_r2, 0, s390_r10, 0);
1041 DEBUG(printf("Returns: %d\n",sig->ret->type));
1042 switch (sig->ret->type) {
1043 case MONO_TYPE_VOID:
1045 case MONO_TYPE_BOOLEAN:
1047 s390_lhi (p, s390_r2, 0);
1048 s390_ic (p, s390_r2, 0, s390_r10, 0);
1052 s390_lh (p, s390_r2, 0,s390_r10, 0);
1058 case MONO_TYPE_OBJECT:
1059 case MONO_TYPE_STRING:
1060 case MONO_TYPE_CLASS:
1061 s390_l (p, s390_r2, 0, s390_r10, 0);
1064 s390_lm (p, s390_r2, s390_r3, s390_r10, 0);
1067 s390_le (p, s390_f0, 0, s390_r10, 0);
1070 s390_ld (p, s390_f0, 0, s390_r10, 0);
1072 case MONO_TYPE_VALUETYPE:
1073 if (sig->ret->data.klass->enumtype) {
1074 simpletype = sig->ret->data.klass->enum_basetype->type;
1077 /*---------------------------------*/
1078 /* Call stackval_to_data to return */
1080 /*---------------------------------*/
1081 s390_bras (p, s390_r13, 8);
1082 s390_word (p, sig->ret);
1083 s390_word (p, sig->pinvoke);
1084 s390_word (p, stackval_to_data);
1085 s390_l (p, s390_r2, 0, s390_r13, 0);
1086 s390_l (p, s390_r3, 0, STK_BASE, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)));
1088 /*------------------------------------------*/
1089 /* Get stackval_to_data to set result area */
1090 /*------------------------------------------*/
1091 s390_lr (p, s390_r4, s390_r8);
1093 /*------------------------------------------*/
1094 /* Give stackval_to_data a temp result area */
1095 /*------------------------------------------*/
1096 s390_la (p, s390_r4, 0, STK_BASE, stackval_arg_pos);
1098 s390_l (p, s390_r5, 0,s390_r13, 4);
1099 s390_l (p, s390_r1, 0, s390_r13, 8);
1100 s390_basr (p, s390_r14, s390_r1);
1105 s390_lhi (p, s390_r2, 0);
1106 s390_ic (p, s390_r2, 0, s390_r10, 0);
1109 s390_lh (p, s390_r2, 0, s390_r10, 0);
1112 s390_l (p, s390_r2, 0, s390_r10, 0);
1115 s390_lm (p, s390_r2, s390_r3, s390_r10, 0);
1118 /*-------------------------------------------------*/
1119 /* stackval_to_data has placed data in result area */
1120 /*-------------------------------------------------*/
1125 g_error ("Type 0x%x not handled yet in thunk creation",
1131 /*----------------------------------------------------------*/
1133 /*----------------------------------------------------------*/
1134 s390_l (p, STK_BASE, 0, STK_BASE, 0);
1135 s390_l (p, s390_r4, 0, STK_BASE, S390_RET_ADDR_OFFSET);
1136 s390_lm (p, s390_r6, STK_BASE, STK_BASE, S390_REG_SAVE_OFFSET);
1137 s390_br (p, s390_r4);
1139 DEBUG (printf ("emited code size: %d\n", p - code_buffer));
1141 DEBUG (printf ("Delegate [end emiting]\n"));
1143 ji = g_new0 (MonoJitInfo, 1);
1144 ji->method = method;
1145 ji->code_size = p - code_buffer;
1146 ji->code_start = code_buffer;
1148 mono_jit_info_table_add (mono_get_root_domain (), ji);
1150 return ji->code_start;
1153 /*========================= End of Function ========================*/