2 * Create trampolines to invoke arbitrary functions.
4 * Copyright (C) Radek Doulik
11 #include "ppc-codegen.h"
12 #include "mono/metadata/class.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/interpreter/interp.h"
15 #include "mono/metadata/appdomain.h"
19 #include <limits.h> /* for PAGESIZE */
28 fake_func (gpointer (*callme)(gpointer), stackval *retval, void *this_obj, stackval *arguments)
30 guint32 i = 0xc002becd;
32 callme = (gpointer) 0x100fabcd;
34 *(gpointer*)retval = (gpointer)(*callme) (arguments [0].data.p, arguments [1].data.p, arguments [2].data.p);
35 *(gdouble*) retval = (gdouble)(*callme) (arguments [0].data.f);
37 return (gpointer) (*callme) (((MonoType *)arguments [0]. data.p)->data.klass);
40 #define MIN_CACHE_LINE 8
43 flush_icache (guint8 *code, guint size)
49 for (i = 0; i < size; i += MIN_CACHE_LINE, p += MIN_CACHE_LINE) {
50 asm ("dcbst 0,%0;" : : "r"(p) : "memory");
54 for (i = 0; i < size; i += MIN_CACHE_LINE, p += MIN_CACHE_LINE) {
55 asm ("icbi 0,%0; sync;" : : "r"(p) : "memory");
61 #define NOT_IMPLEMENTED(x) \
62 g_error ("FIXME: %s is not yet implemented. (trampoline)", x);
68 #define GENERAL_REGS 8
70 #define MINIMAL_STACK_SIZE 10
71 #define ALWAYS_ON_STACK(s) s
72 #define FP_ALSO_IN_REG(s) s
73 #define RET_ADDR_OFFSET 8
74 #define STACK_PARAM_OFFSET 24
76 #define MINIMAL_STACK_SIZE 5
77 #define ALWAYS_ON_STACK(s)
78 #define FP_ALSO_IN_REG(s) s
80 #define RET_ADDR_OFFSET 4
81 #define STACK_PARAM_OFFSET 8
85 add_general (guint *gr, guint *stack_size, guint *code_size, gboolean simple)
88 if (*gr >= GENERAL_REGS) {
90 *code_size += 8; /* load from stack, save on stack */
92 ALWAYS_ON_STACK (*stack_size += 4);
93 *code_size += 4; /* load from stack */
96 if (*gr >= GENERAL_REGS - 1) {
99 *stack_size += (*stack_size % 8);
101 *code_size += 16; /* 2x load from stack, 2x save to stack */
103 ALWAYS_ON_STACK (*stack_size += 8);
104 *code_size += 8; /* 2x load from stack */
116 calculate_sizes (MonoMethodSignature *sig, guint *stack_size, guint *code_size, gboolean string_ctor, gboolean *use_memcpy)
122 *stack_size = MINIMAL_STACK_SIZE*4;
123 *code_size = (PROLOG_INS + CALL_INS + EPILOG_INS)*4;
126 add_general (&gr, stack_size, code_size, TRUE);
128 DEBUG(printf("params: %d\n", sig->param_count));
129 for (i = 0; i < sig->param_count; ++i) {
130 DEBUG(printf("param %d: ", i));
131 if (sig->params [i]->byref) {
132 DEBUG(printf("byref\n"));
133 add_general (&gr, stack_size, code_size, TRUE);
136 simpletype = sig->params [i]->type;
138 switch (simpletype) {
139 case MONO_TYPE_BOOLEAN:
150 case MONO_TYPE_CLASS:
151 case MONO_TYPE_OBJECT:
152 case MONO_TYPE_STRING:
153 add_general (&gr, stack_size, code_size, TRUE);
155 case MONO_TYPE_SZARRAY:
156 add_general (&gr, stack_size, code_size, TRUE);
159 case MONO_TYPE_VALUETYPE: {
161 if (sig->params [i]->data.klass->enumtype) {
162 simpletype = sig->params [i]->data.klass->enum_basetype->type;
165 size = mono_class_value_size (sig->params [i]->data.klass, NULL);
167 DEBUG(printf ("copy %d bytes struct on stack\n",
168 mono_class_value_size (sig->params [i]->data.klass, NULL)));
171 *stack_size += (size + 3) & (~3);
172 if (gr > GENERAL_REGS) {
177 DEBUG(printf ("load %d bytes struct\n",
178 mono_class_value_size (sig->params [i]->data.klass, NULL)));
179 add_general (&gr, stack_size, code_size, TRUE);
185 add_general (&gr, stack_size, code_size, FALSE);
191 FP_ALSO_IN_REG (gr ++);
192 ALWAYS_ON_STACK (*stack_size += 4);
194 NOT_IMPLEMENTED ("R4 arg");
201 FP_ALSO_IN_REG (gr += 2);
202 ALWAYS_ON_STACK (*stack_size += 8);
204 NOT_IMPLEMENTED ("R8 arg");
208 g_error ("Can't trampoline 0x%x", sig->params [i]->type);
212 if (sig->ret->byref || string_ctor) {
215 simpletype = sig->ret->type;
217 switch (simpletype) {
218 case MONO_TYPE_BOOLEAN:
228 case MONO_TYPE_CLASS:
229 case MONO_TYPE_OBJECT:
232 case MONO_TYPE_SZARRAY:
233 case MONO_TYPE_ARRAY:
234 case MONO_TYPE_STRING:
240 case MONO_TYPE_VALUETYPE:
241 if (sig->ret->data.klass->enumtype) {
242 simpletype = sig->ret->data.klass->enum_basetype->type;
250 g_error ("Can't handle as return value 0x%x", sig->ret->type);
255 *stack_size += 2*4; /* for r14, r15 */
258 *stack_size += 4; /* for r16 */
263 /* align stack size to 16 */
264 DEBUG (printf (" stack size: %d (%d)\n code size: %d\n", (*stack_size + 15) & ~15, *stack_size, *code_size));
265 *stack_size = (*stack_size + 15) & ~15;
268 static inline guint8 *
269 emit_prolog (guint8 *p, MonoMethodSignature *sig, guint stack_size)
271 /* function prolog */
272 ppc_stwu (p, ppc_r1, -stack_size, ppc_r1); /* sp <--- sp - stack_size, sp[0] <---- sp save sp, alloc stack */
273 ppc_mflr (p, ppc_r0); /* r0 <--- LR */
274 ppc_stw (p, ppc_r31, stack_size - 4, ppc_r1); /* sp[+4] <--- r31 save r31 */
275 ppc_stw (p, ppc_r0, stack_size + RET_ADDR_OFFSET, ppc_r1); /* sp[-4] <--- LR save return address for "callme" */
276 ppc_mr (p, ppc_r31, ppc_r1); /* r31 <--- sp */
281 #define ARG_BASE ppc_r12
282 #define SAVE_4_IN_GENERIC_REGISTER \
283 if (gr < GENERAL_REGS) { \
284 ppc_lwz (p, ppc_r3 + gr, i*16, ARG_BASE); \
287 ppc_lwz (p, ppc_r11, i*16, ARG_BASE); \
288 ppc_stw (p, ppc_r11, stack_par_pos, ppc_r1); \
289 stack_par_pos += 4; \
291 #define SAVE_4_VAL_IN_GENERIC_REGISTER \
292 if (gr < GENERAL_REGS) { \
293 ppc_lwz (p, ppc_r3 + gr, i*16, ARG_BASE); \
294 ppc_lwz (p, ppc_r3 + gr, 0, ppc_r3 + gr); \
296 ALWAYS_ON_STACK (stack_par_pos += 4); \
298 ppc_lwz (p, ppc_r11, i*16, ARG_BASE); \
299 ppc_lwz (p, ppc_r11, 0, ppc_r11); \
300 ppc_stw (p, ppc_r11, stack_par_pos, ppc_r1); \
301 stack_par_pos += 4; \
304 inline static guint8*
305 emit_save_parameters (guint8 *p, MonoMethodSignature *sig, guint stack_size, gboolean use_memcpy)
307 guint i, fr, gr, stack_par_pos, struct_pos, cur_struct_pos;
311 stack_par_pos = STACK_PARAM_OFFSET;
313 ppc_stw (p, ppc_r4, stack_size - 12, ppc_r31); /* preserve "retval", sp[+8] */
316 ppc_stw (p, ppc_r14, stack_size - 16, ppc_r31); /* save r14 */
317 ppc_stw (p, ppc_r15, stack_size - 20, ppc_r31); /* save r15 */
318 ppc_mr (p, ppc_r14, ppc_r3); /* keep "callme" in register */
319 ppc_mr (p, ppc_r15, ppc_r6); /* keep "arguments" in register */
321 ppc_mr (p, ppc_r12, ppc_r6); /* keep "arguments" in register */
322 ppc_mr (p, ppc_r0, ppc_r3); /* keep "callme" in register */
327 ppc_stw (p, ppc_r16, stack_size - 24, ppc_r31); /* save r16 */
328 ppc_mr (p, ppc_r16, ppc_r5);
330 ppc_mr (p, ppc_r3, ppc_r5);
332 ALWAYS_ON_STACK (stack_par_pos += 4);
336 cur_struct_pos = struct_pos = stack_par_pos;
337 for (i = 0; i < sig->param_count; ++i) {
338 if (sig->params [i]->byref)
340 if (sig->params [i]->type == MONO_TYPE_VALUETYPE && !sig->params [i]->data.klass->enumtype) {
343 size = mono_class_value_size (sig->params [i]->data.klass, NULL);
346 ppc_addi (p, ppc_r3, ppc_r1, stack_par_pos);
347 ppc_lwz (p, ppc_r4, i*16, ppc_r15);
348 /* FIXME check if size > 0xffff */
349 ppc_li (p, ppc_r5, size & 0xffff);
350 ppc_lis (p, ppc_r0, (guint32) memcpy >> 16);
351 ppc_ori (p, ppc_r0, ppc_r0, (guint32) memcpy & 0xffff);
352 ppc_mtlr (p, ppc_r0);
354 stack_par_pos += (size + 3) & (~3);
360 ppc_mr (p, ppc_r3, ppc_r16);
361 ppc_lwz (p, ppc_r16, stack_size - 24, ppc_r31); /* restore r16 */
363 ppc_mr (p, ppc_r0, ppc_r14);
364 ppc_mr (p, ppc_r12, ppc_r15);
365 ppc_lwz (p, ppc_r14, stack_size - 16, ppc_r31); /* restore r14 */
366 ppc_lwz (p, ppc_r15, stack_size - 20, ppc_r31); /* restore r15 */
369 if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) {
370 MonoClass *klass = sig->ret->data.klass;
371 if (!klass->enumtype) {
372 gint size = mono_class_native_size (klass, NULL);
374 DEBUG(printf ("retval value type size: %d\n", size));
376 ppc_lwz (p, ppc_r3, stack_size - 12, ppc_r31);
377 ppc_lwz (p, ppc_r3, 0, ppc_r3);
379 ALWAYS_ON_STACK (stack_par_pos += 4);
381 NOT_IMPLEMENTED ("retval valuetype <= 8 bytes");
386 for (i = 0; i < sig->param_count; ++i) {
387 if (sig->params [i]->byref) {
388 SAVE_4_IN_GENERIC_REGISTER;
391 simpletype = sig->params [i]->type;
393 switch (simpletype) {
394 case MONO_TYPE_BOOLEAN:
405 case MONO_TYPE_CLASS:
406 case MONO_TYPE_OBJECT:
407 case MONO_TYPE_STRING:
408 case MONO_TYPE_SZARRAY:
409 SAVE_4_IN_GENERIC_REGISTER;
411 case MONO_TYPE_VALUETYPE: {
413 if (sig->params [i]->data.klass->enumtype) {
414 simpletype = sig->params [i]->data.klass->enum_basetype->type;
417 size = mono_class_value_size (sig->params [i]->data.klass, NULL);
419 SAVE_4_VAL_IN_GENERIC_REGISTER;
421 if (gr < GENERAL_REGS) {
422 ppc_addi (p, ppc_r3 + gr, ppc_r1, cur_struct_pos);
425 ppc_lwz (p, ppc_r11, cur_struct_pos, ppc_r1);
426 ppc_stw (p, ppc_r11, stack_par_pos, ppc_r1);
429 cur_struct_pos += (size + 3) & (~3);
434 DEBUG(printf("Mono_Type_i8. gr = %d, arg_base = %d\n", gr, ARG_BASE));
440 ppc_lwz (p, ppc_r3 + gr, i*16, ARG_BASE);
441 ppc_lwz (p, ppc_r3 + gr + 1, i*16 + 4, ARG_BASE);
442 ALWAYS_ON_STACK (stack_par_pos += 8);
443 } else if (gr == 7) {
444 ppc_lwz (p, ppc_r3 + gr, i*16, ARG_BASE);
445 ppc_lwz (p, ppc_r11, i*16 + 4, ARG_BASE);
446 ppc_stw (p, ppc_r11, stack_par_pos + 4, ppc_r1);
449 ppc_lwz (p, ppc_r11, i*16, ARG_BASE);
450 ppc_stw (p, ppc_r11, stack_par_pos, ppc_r1);
451 ppc_lwz (p, ppc_r11, i*16 + 4, ARG_BASE);
452 ppc_stw (p, ppc_r11, stack_par_pos + 4, ppc_r1);
459 ppc_lfs (p, ppc_f1 + fr, i*16, ARG_BASE);
461 FP_ALSO_IN_REG (gr ++);
462 ALWAYS_ON_STACK (stack_par_pos += 4);
464 NOT_IMPLEMENTED ("r4 on stack");
469 ppc_lfd (p, ppc_f1 + fr, i*16, ARG_BASE);
471 FP_ALSO_IN_REG (gr += 2);
472 ALWAYS_ON_STACK (stack_par_pos += 8);
474 NOT_IMPLEMENTED ("r8 on stack");
478 g_error ("Can't trampoline 0x%x", sig->params [i]->type);
485 static inline guint8 *
486 alloc_code_memory (guint code_size)
491 p = g_malloc (code_size + PAGESIZE - 1);
493 /* Align to a multiple of PAGESIZE, assumed to be a power of two */
494 p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1));
496 p = g_malloc (code_size);
498 DEBUG (printf (" align: %p (%d)\n", p, (guint)p % 4));
503 /* static MonoString*
504 mono_string_new_wrapper (const char *text)
506 return text ? mono_string_new (mono_domain_get (), text) : NULL;
509 static inline guint8 *
510 emit_call_and_store_retval (guint8 *p, MonoMethodSignature *sig, guint stack_size, gboolean string_ctor)
515 ppc_mtlr (p, ppc_r0);
518 /* get return value */
519 if (sig->ret->byref || string_ctor) {
520 ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */
521 ppc_stw (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */
523 simpletype = sig->ret->type;
525 switch (simpletype) {
526 case MONO_TYPE_BOOLEAN:
529 ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */
530 ppc_stb (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */
535 ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */
536 ppc_sth (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */
542 case MONO_TYPE_CLASS:
543 case MONO_TYPE_OBJECT:
544 case MONO_TYPE_SZARRAY:
545 case MONO_TYPE_ARRAY:
546 case MONO_TYPE_STRING:
547 ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */
548 ppc_stw (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */
551 ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */
552 ppc_stfs (p, ppc_f1, 0, ppc_r9); /* save return value (f1) to "retval" */
555 ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */
556 ppc_stfd (p, ppc_f1, 0, ppc_r9); /* save return value (f1) to "retval" */
559 ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */
560 ppc_stw (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */
561 ppc_stw (p, ppc_r4, 4, ppc_r9); /* save return value (r3) to "retval" */
563 case MONO_TYPE_VALUETYPE:
564 if (sig->ret->data.klass->enumtype) {
565 simpletype = sig->ret->data.klass->enum_basetype->type;
572 g_error ("Can't handle as return value 0x%x", sig->ret->type);
579 static inline guint8 *
580 emit_epilog (guint8 *p, MonoMethodSignature *sig, guint stack_size)
582 /* function epilog */
583 ppc_lwz (p, ppc_r11, 0, ppc_r1); /* r11 <--- sp[0] load backchain from caller's function */
584 ppc_lwz (p, ppc_r0, RET_ADDR_OFFSET, ppc_r11); /* r0 <--- r11[4] load return address */
585 ppc_mtlr (p, ppc_r0); /* LR <--- r0 set return address */
586 ppc_lwz (p, ppc_r31, -4, ppc_r11); /* r31 <--- r11[-4] restore r31 */
587 ppc_mr (p, ppc_r1, ppc_r11); /* sp <--- r11 restore stack */
588 ppc_blr (p); /* return */
594 mono_arch_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor)
596 guint8 *p, *code_buffer;
597 guint stack_size, code_size;
598 gboolean use_memcpy = FALSE;
600 DEBUG (printf ("\nPInvoke [start emiting]\n"));
601 calculate_sizes (sig, &stack_size, &code_size, string_ctor, &use_memcpy);
603 p = code_buffer = alloc_code_memory (code_size);
604 p = emit_prolog (p, sig, stack_size);
605 p = emit_save_parameters (p, sig, stack_size, use_memcpy);
606 p = emit_call_and_store_retval (p, sig, stack_size, string_ctor);
607 p = emit_epilog (p, sig, stack_size);
611 printf (".text\n.align 4\n.globl main\n.type main,@function\nmain:\n");
612 for (cp = code_buffer; cp < p; cp++) {
613 printf (".byte 0x%x\n", *cp);
618 if (mprotect (code_buffer, 1024, PROT_READ | PROT_WRITE | PROT_EXEC)) {
619 g_error ("Cannot mprotect trampoline\n");
623 DEBUG (printf ("emited code size: %d\n", p - code_buffer));
624 flush_icache (code_buffer, p - code_buffer);
626 DEBUG (printf ("PInvoke [end emiting]\n"));
628 return (MonoPIFunc) code_buffer;
629 /* return fake_func; */
634 #define MINV_POS 24 /* MonoInvocation structure offset on stack */
636 #define MINV_POS 8 /* MonoInvocation structure offset on stack */
638 #define STACK_POS (MINV_POS - sizeof (stackval) * sig->param_count)
640 #define TYPE_OFFSET (G_STRUCT_OFFSET (stackval, type))
643 * Returns a pointer to a native function that can be used to
644 * call the specified method.
645 * The function created will receive the arguments according
646 * to the call convention specified in the method.
647 * This function works by creating a MonoInvocation structure,
648 * filling the fields in and calling ves_exec_method on it.
649 * Still need to figure out how to handle the exception stuff
650 * across the managed/unmanaged boundary.
653 mono_arch_create_method_pointer (MonoMethod *method)
655 MonoMethodSignature *sig;
657 guint8 *p, *code_buffer;
658 guint i, align = 0, code_size, stack_size, stackval_arg_pos, local_pos, local_start, reg_param, stack_param,
659 this_flag, cpos, vt_cur;
667 sig = method->signature;
669 p = code_buffer = g_malloc (code_size);
671 DEBUG (printf ("\nDelegate [start emiting] %s\n", method->name));
674 ppc_stwu (p, ppc_r1, -stack_size, ppc_r1); /* sp <--- sp - stack_size, sp[0] <---- sp save sp, alloc stack */
675 ppc_mflr (p, ppc_r0); /* r0 <--- LR */
676 ppc_stw (p, ppc_r31, stack_size - 4, ppc_r1); /* sp[+4] <--- r31 save r31 */
677 ppc_stw (p, ppc_r0, stack_size + RET_ADDR_OFFSET, ppc_r1); /* sp[-4] <--- LR save return address for "callme" */
678 ppc_mr (p, ppc_r31, ppc_r1); /* r31 <--- sp */
680 /* let's fill MonoInvocation */
681 /* first zero some fields */
682 ppc_li (p, ppc_r0, 0);
683 ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex)), ppc_r31);
684 ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler)), ppc_r31);
685 ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, child)), ppc_r31);
686 ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent)), ppc_r31);
688 /* set method pointer */
689 ppc_lis (p, ppc_r0, (guint32) method >> 16);
690 ppc_ori (p, ppc_r0, ppc_r0, (guint32) method & 0xffff);
691 ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method)), ppc_r31);
693 local_start = local_pos = MINV_POS + sizeof (MonoInvocation) + (sig->param_count + 1) * sizeof (stackval);
696 ppc_stw (p, ppc_r3, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)), ppc_r31);
698 } else if (sig->param_count) {
699 DEBUG (printf ("save r%d\n", 3));
700 ppc_stw (p, ppc_r3, local_pos, ppc_r31);
705 this_flag = (sig->hasthis ? 1 : 0);
706 if (sig->param_count) {
707 gint save_count = MIN (8, sig->param_count - 1);
708 for (i = reg_param; i < save_count; i ++) {
709 ppc_stw (p, ppc_r4 + i, local_pos, ppc_r31);
711 DEBUG (printf ("save r%d\n", 4 + i));
715 /* prepare space for valuetypes */
717 vtbuf = alloca (sizeof(int)*sig->param_count);
719 for (i = 0; i < sig->param_count; i++) {
720 MonoType *type = sig->params [i];
722 if (type->type == MONO_TYPE_VALUETYPE) {
723 MonoClass *klass = type->data.klass;
728 size = mono_class_native_size (klass, &align);
730 cpos &= ~(align - 1);
740 /* set MonoInvocation::stack_args */
741 stackval_arg_pos = MINV_POS + sizeof (MonoInvocation);
742 ppc_addi (p, ppc_r0, ppc_r31, stackval_arg_pos);
743 ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args)), ppc_r31);
745 /* add stackval arguments */
746 for (i = 0; i < sig->param_count; ++i) {
748 ppc_addi (p, ppc_r5, ppc_r31, local_start + (reg_param - this_flag)*4);
751 ppc_addi (p, ppc_r5, stack_size + 8 + stack_param, ppc_r31);
754 ppc_lis (p, ppc_r3, (guint32) sig->params [i] >> 16);
756 if (vtbuf [i] >= 0) {
757 ppc_addi (p, ppc_r4, ppc_r31, vt_cur);
758 ppc_stw (p, ppc_r4, stackval_arg_pos, ppc_r31);
759 ppc_addi (p, ppc_r4, ppc_r31, stackval_arg_pos);
760 ppc_lwz (p, ppc_r5, 0, ppc_r5);
763 ppc_addi (p, ppc_r4, ppc_r31, stackval_arg_pos);
765 ppc_ori (p, ppc_r3, ppc_r3, (guint32) sig->params [i] & 0xffff);
766 ppc_lis (p, ppc_r0, (guint32) stackval_from_data >> 16);
767 ppc_li (p, ppc_r6, sig->pinvoke);
768 ppc_ori (p, ppc_r0, ppc_r0, (guint32) stackval_from_data & 0xffff);
769 ppc_mtlr (p, ppc_r0);
772 /* fixme: alignment */
773 DEBUG (printf ("arg_pos %d --> ", stackval_arg_pos));
775 stackval_arg_pos += 4*mono_type_native_stack_size (sig->params [i], &align);
777 stackval_arg_pos += 4*mono_type_stack_size (sig->params [i], &align);
778 DEBUG (printf ("%d\n", stackval_arg_pos));
781 /* return value storage */
782 if (sig->param_count) {
783 ppc_addi (p, ppc_r0, ppc_r31, stackval_arg_pos);
785 ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)), ppc_r31);
787 /* call ves_exec_method */
788 ppc_lis (p, ppc_r0, (guint32) ves_exec_method >> 16);
789 ppc_addi (p, ppc_r3, ppc_r31, MINV_POS);
790 ppc_ori (p, ppc_r0, ppc_r0, (guint32) ves_exec_method & 0xffff);
791 ppc_mtlr (p, ppc_r0);
794 /* move retval from stackval to proper place (r3/r4/...) */
795 if (sig->ret->byref) {
796 DEBUG (printf ("ret by ref\n"));
797 ppc_lwz (p, ppc_r3, stackval_arg_pos, ppc_r31);
800 switch (sig->ret->type) {
803 case MONO_TYPE_BOOLEAN:
806 ppc_lbz (p, ppc_r3, stackval_arg_pos, ppc_r31);
810 ppc_lhz (p, ppc_r3, stackval_arg_pos, ppc_r31);
816 case MONO_TYPE_OBJECT:
817 case MONO_TYPE_STRING:
818 case MONO_TYPE_CLASS:
819 ppc_lwz (p, ppc_r3, stackval_arg_pos, ppc_r31);
822 ppc_lwz (p, ppc_r3, stackval_arg_pos, ppc_r31);
823 ppc_lwz (p, ppc_r4, stackval_arg_pos + 4, ppc_r31);
826 ppc_lfs (p, ppc_f1, stackval_arg_pos, ppc_r31);
829 ppc_lfd (p, ppc_f1, stackval_arg_pos, ppc_r31);
831 case MONO_TYPE_VALUETYPE:
832 if (sig->ret->data.klass->enumtype) {
833 simpletype = sig->ret->data.klass->enum_basetype->type;
836 NOT_IMPLEMENTED ("value type as ret val from delegate");
839 g_error ("Type 0x%x not handled yet in thunk creation", sig->ret->type);
845 ppc_lwz (p, ppc_r11, 0, ppc_r1); /* r11 <--- sp[0] load backchain from caller's function */
846 ppc_lwz (p, ppc_r0, RET_ADDR_OFFSET, ppc_r11); /* r0 <--- r11[4] load return address */
847 ppc_mtlr (p, ppc_r0); /* LR <--- r0 set return address */
848 ppc_lwz (p, ppc_r31, -4, ppc_r11); /* r31 <--- r11[-4] restore r31 */
849 ppc_mr (p, ppc_r1, ppc_r11); /* sp <--- r11 restore stack */
850 ppc_blr (p); /* return */
852 DEBUG (printf ("emited code size: %d\n", p - code_buffer));
853 flush_icache (code_buffer, p - code_buffer);
855 DEBUG (printf ("Delegate [end emiting]\n"));
857 ji = g_new0 (MonoJitInfo, 1);
859 ji->code_size = p - code_buffer;
860 ji->code_start = code_buffer;
862 mono_jit_info_table_add (mono_root_domain, ji);
864 return ji->code_start;