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);
67 #define MINIMAL_STACK_SIZE 5
69 #define GENERAL_REGS 8
72 add_general (guint *gr, guint *stack_size, guint *code_size, gboolean simple)
75 if (*gr >= GENERAL_REGS) {
77 *code_size += 8; /* load from stack, save on stack */
79 *code_size += 4; /* load from stack */
82 if (*gr >= GENERAL_REGS - 1) {
83 *stack_size += 8 + (*stack_size % 8);
84 *code_size += 16; /* 2x load from stack, 2x save to stack */
86 *code_size += 16; /* 2x load from stack */
96 calculate_sizes (MonoMethodSignature *sig, guint *stack_size, guint *code_size, gboolean string_ctor, gboolean *use_memcpy)
102 *stack_size = MINIMAL_STACK_SIZE*4;
103 *code_size = (PROLOG_INS + CALL_INS + EPILOG_INS)*4;
106 add_general (&gr, stack_size, code_size, TRUE);
109 for (i = 0; i < sig->param_count; ++i) {
110 if (sig->params [i]->byref) {
111 add_general (&gr, stack_size, code_size, TRUE);
114 simpletype = sig->params [i]->type;
116 switch (simpletype) {
117 case MONO_TYPE_BOOLEAN:
128 case MONO_TYPE_CLASS:
129 case MONO_TYPE_OBJECT:
130 case MONO_TYPE_STRING:
131 add_general (&gr, stack_size, code_size, TRUE);
133 case MONO_TYPE_SZARRAY:
134 add_general (&gr, stack_size, code_size, TRUE);
137 case MONO_TYPE_VALUETYPE: {
139 if (sig->params [i]->data.klass->enumtype) {
140 simpletype = sig->params [i]->data.klass->enum_basetype->type;
143 size = mono_class_value_size (sig->params [i]->data.klass, NULL);
145 DEBUG(printf ("copy %d bytes struct on stack\n",
146 mono_class_value_size (sig->params [i]->data.klass, NULL)));
149 *stack_size += (size + 3) & (~3);
150 if (gr > GENERAL_REGS) {
155 DEBUG(printf ("load %d bytes struct\n",
156 mono_class_value_size (sig->params [i]->data.klass, NULL)));
157 add_general (&gr, stack_size, code_size, TRUE);
163 add_general (&gr, stack_size, code_size, FALSE);
171 NOT_IMPLEMENTED ("R8 arg");
175 g_error ("Can't trampoline 0x%x", sig->params [i]->type);
179 if (sig->ret->byref || string_ctor) {
182 simpletype = sig->ret->type;
184 switch (simpletype) {
185 case MONO_TYPE_BOOLEAN:
195 case MONO_TYPE_CLASS:
196 case MONO_TYPE_OBJECT:
199 case MONO_TYPE_SZARRAY:
200 case MONO_TYPE_ARRAY:
201 case MONO_TYPE_STRING:
207 case MONO_TYPE_VALUETYPE:
208 if (sig->ret->data.klass->enumtype) {
209 simpletype = sig->ret->data.klass->enum_basetype->type;
217 g_error ("Can't handle as return value 0x%x", sig->ret->type);
222 *stack_size += 2*4; /* for r14, r15 */
225 *stack_size += 4; /* for r16 */
230 /* align stack size to 16 */
231 DEBUG (printf (" stack size: %d (%d)\n code size: %d\n", (*stack_size + 15) & ~15, *stack_size, *code_size));
232 *stack_size = (*stack_size + 15) & ~15;
235 static inline guint8 *
236 emit_prolog (guint8 *p, MonoMethodSignature *sig, guint stack_size)
238 /* function prolog */
239 ppc_stwu (p, ppc_r1, -stack_size, ppc_r1); /* sp <--- sp - stack_size, sp[0] <---- sp save sp, alloc stack */
240 ppc_mflr (p, ppc_r0); /* r0 <--- LR */
241 ppc_stw (p, ppc_r31, stack_size - 4, ppc_r1); /* sp[+4] <--- r31 save r31 */
242 ppc_stw (p, ppc_r0, stack_size + 4, ppc_r1); /* sp[-4] <--- LR save return address for "callme" */
243 ppc_mr (p, ppc_r31, ppc_r1); /* r31 <--- sp */
248 #define ARG_BASE ppc_r12
249 #define SAVE_4_IN_GENERIC_REGISTER \
250 if (gr < GENERAL_REGS) { \
251 ppc_lwz (p, ppc_r3 + gr, i*16, ARG_BASE); \
254 ppc_lwz (p, ppc_r11, i*16, ARG_BASE); \
255 ppc_stw (p, ppc_r11, stack_par_pos, ppc_r1); \
256 stack_par_pos += 4; \
258 #define SAVE_4_VAL_IN_GENERIC_REGISTER \
259 if (gr < GENERAL_REGS) { \
260 ppc_lwz (p, ppc_r3 + gr, i*16, ARG_BASE); \
261 ppc_lwz (p, ppc_r3 + gr, 0, ppc_r3 + gr); \
264 ppc_lwz (p, ppc_r11, i*16, ARG_BASE); \
265 ppc_lwz (p, ppc_r11, 0, ppc_r11); \
266 ppc_stw (p, ppc_r11, stack_par_pos, ppc_r1); \
267 stack_par_pos += 4; \
270 inline static guint8*
271 emit_save_parameters (guint8 *p, MonoMethodSignature *sig, guint stack_size, gboolean use_memcpy)
273 guint i, fr, gr, stack_par_pos, struct_pos, cur_struct_pos;
279 ppc_stw (p, ppc_r4, stack_size - 12, ppc_r31); /* preserve "retval", sp[+8] */
282 ppc_stw (p, ppc_r14, stack_size - 16, ppc_r31); /* save r14 */
283 ppc_stw (p, ppc_r15, stack_size - 20, ppc_r31); /* save r15 */
284 ppc_mr (p, ppc_r14, ppc_r3); /* keep "callme" in register */
285 ppc_mr (p, ppc_r15, ppc_r6); /* keep "arguments" in register */
287 ppc_mr (p, ppc_r12, ppc_r6); /* keep "arguments" in register */
288 ppc_mr (p, ppc_r0, ppc_r3); /* keep "callme" in register */
293 ppc_stw (p, ppc_r16, stack_size - 24, ppc_r31); /* save r16 */
294 ppc_mr (p, ppc_r16, ppc_r5);
296 ppc_mr (p, ppc_r3, ppc_r5);
301 cur_struct_pos = struct_pos = stack_par_pos;
302 for (i = 0; i < sig->param_count; ++i) {
303 if (sig->params [i]->byref)
305 if (sig->params [i]->type == MONO_TYPE_VALUETYPE && !sig->params [i]->data.klass->enumtype) {
308 size = mono_class_value_size (sig->params [i]->data.klass, NULL);
311 ppc_addi (p, ppc_r3, ppc_r1, stack_par_pos);
312 ppc_lwz (p, ppc_r4, i*16, ppc_r15);
313 /* FIXME check if size > 0xffff */
314 ppc_li (p, ppc_r5, size & 0xffff);
315 ppc_lis (p, ppc_r0, (guint32) memcpy >> 16);
316 ppc_ori (p, ppc_r0, ppc_r0, (guint32) memcpy & 0xffff);
317 ppc_mtlr (p, ppc_r0);
319 stack_par_pos += (size + 3) & (~3);
325 ppc_mr (p, ppc_r3, ppc_r16);
326 ppc_lwz (p, ppc_r16, stack_size - 24, ppc_r31); /* restore r16 */
328 ppc_mr (p, ppc_r0, ppc_r14);
329 ppc_mr (p, ppc_r12, ppc_r15);
330 ppc_lwz (p, ppc_r14, stack_size - 16, ppc_r31); /* restore r14 */
331 ppc_lwz (p, ppc_r15, stack_size - 20, ppc_r31); /* restore r15 */
334 if (sig->ret->type == MONO_TYPE_VALUETYPE && !sig->ret->byref) {
335 MonoClass *klass = sig->ret->data.klass;
336 if (!klass->enumtype) {
337 gint size = mono_class_native_size (klass, NULL);
339 DEBUG(printf ("retval value type size: %d\n", size));
341 ppc_lwz (p, ppc_r3, stack_size - 12, ppc_r31);
342 ppc_lwz (p, ppc_r3, 0, ppc_r3);
345 NOT_IMPLEMENTED ("retval valuetype <= 8 bytes");
350 for (i = 0; i < sig->param_count; ++i) {
351 if (sig->params [i]->byref) {
352 SAVE_4_IN_GENERIC_REGISTER;
355 simpletype = sig->params [i]->type;
357 switch (simpletype) {
358 case MONO_TYPE_BOOLEAN:
369 case MONO_TYPE_CLASS:
370 case MONO_TYPE_OBJECT:
371 case MONO_TYPE_STRING:
372 case MONO_TYPE_SZARRAY:
373 SAVE_4_IN_GENERIC_REGISTER;
375 case MONO_TYPE_VALUETYPE: {
377 if (sig->params [i]->data.klass->enumtype) {
378 simpletype = sig->params [i]->data.klass->enum_basetype->type;
381 size = mono_class_value_size (sig->params [i]->data.klass, NULL);
383 SAVE_4_VAL_IN_GENERIC_REGISTER;
385 if (gr < GENERAL_REGS) {
386 ppc_addi (p, ppc_r3 + gr, ppc_r1, cur_struct_pos);
389 ppc_lwz (p, ppc_r11, cur_struct_pos, ppc_r1);
390 ppc_stw (p, ppc_r11, stack_par_pos, ppc_r1);
393 cur_struct_pos += (size + 3) & (~3);
401 ppc_lwz (p, ppc_r3 + gr, i*16, ARG_BASE);
403 ppc_lwz (p, ppc_r3 + gr, i*16 + 4, ARG_BASE);
406 NOT_IMPLEMENTED ("i8 on stack");
411 ppc_lfs (p, ppc_f1 + fr, i*16, ARG_BASE);
414 NOT_IMPLEMENTED ("r4 on stack");
419 ppc_lfd (p, ppc_f1 + fr, i*16, ARG_BASE);
422 NOT_IMPLEMENTED ("r8 on stack");
426 g_error ("Can't trampoline 0x%x", sig->params [i]->type);
433 static inline guint8 *
434 alloc_code_memory (guint code_size)
439 p = g_malloc (code_size + PAGESIZE - 1);
441 /* Align to a multiple of PAGESIZE, assumed to be a power of two */
442 p = (char *)(((int) p + PAGESIZE-1) & ~(PAGESIZE-1));
444 p = g_malloc (code_size);
446 DEBUG (printf (" align: %p (%d)\n", p, (guint)p % 4));
451 /* static MonoString*
452 mono_string_new_wrapper (const char *text)
454 return text ? mono_string_new (mono_domain_get (), text) : NULL;
457 static inline guint8 *
458 emit_call_and_store_retval (guint8 *p, MonoMethodSignature *sig, guint stack_size, gboolean string_ctor)
463 ppc_mtlr (p, ppc_r0);
466 /* get return value */
467 if (sig->ret->byref || string_ctor) {
468 ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */
469 ppc_stw (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */
471 simpletype = sig->ret->type;
473 switch (simpletype) {
474 case MONO_TYPE_BOOLEAN:
477 ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */
478 ppc_stb (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */
483 ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */
484 ppc_sth (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */
490 case MONO_TYPE_CLASS:
491 case MONO_TYPE_OBJECT:
492 case MONO_TYPE_SZARRAY:
493 case MONO_TYPE_ARRAY:
494 case MONO_TYPE_STRING:
495 ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */
496 ppc_stw (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */
499 ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */
500 ppc_stfs (p, ppc_f1, 0, ppc_r9); /* save return value (f1) to "retval" */
503 ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */
504 ppc_stfd (p, ppc_f1, 0, ppc_r9); /* save return value (f1) to "retval" */
507 ppc_lwz (p, ppc_r9, stack_size - 12, ppc_r31); /* load "retval" address */
508 ppc_stw (p, ppc_r3, 0, ppc_r9); /* save return value (r3) to "retval" */
509 ppc_stw (p, ppc_r4, 4, ppc_r9); /* save return value (r3) to "retval" */
511 case MONO_TYPE_VALUETYPE:
512 if (sig->ret->data.klass->enumtype) {
513 simpletype = sig->ret->data.klass->enum_basetype->type;
520 g_error ("Can't handle as return value 0x%x", sig->ret->type);
527 static inline guint8 *
528 emit_epilog (guint8 *p, MonoMethodSignature *sig, guint stack_size)
530 /* function epilog */
531 ppc_lwz (p, ppc_r11, 0, ppc_r1); /* r11 <--- sp[0] load backchain from caller's function */
532 ppc_lwz (p, ppc_r0, 4, ppc_r11); /* r0 <--- r11[4] load return address */
533 ppc_mtlr (p, ppc_r0); /* LR <--- r0 set return address */
534 ppc_lwz (p, ppc_r31, -4, ppc_r11); /* r31 <--- r11[-4] restore r31 */
535 ppc_mr (p, ppc_r1, ppc_r11); /* sp <--- r11 restore stack */
536 ppc_blr (p); /* return */
542 mono_create_trampoline (MonoMethodSignature *sig, gboolean string_ctor)
544 guint8 *p, *code_buffer;
545 guint stack_size, code_size;
546 gboolean use_memcpy = FALSE;
548 DEBUG (printf ("\nPInvoke [start emiting]\n"));
549 calculate_sizes (sig, &stack_size, &code_size, string_ctor, &use_memcpy);
551 p = code_buffer = alloc_code_memory (code_size);
552 p = emit_prolog (p, sig, stack_size);
553 p = emit_save_parameters (p, sig, stack_size, use_memcpy);
554 p = emit_call_and_store_retval (p, sig, stack_size, string_ctor);
555 p = emit_epilog (p, sig, stack_size);
559 printf (".text\n.align 4\n.globl main\n.type main,@function\nmain:\n");
560 for (cp = code_buffer; cp < p; cp++) {
561 printf (".byte 0x%x\n", *cp);
566 if (mprotect (code_buffer, 1024, PROT_READ | PROT_WRITE | PROT_EXEC)) {
567 g_error ("Cannot mprotect trampoline\n");
571 DEBUG (printf ("emited code size: %d\n", p - code_buffer));
572 flush_icache (code_buffer, p - code_buffer);
574 DEBUG (printf ("PInvoke [end emiting]\n"));
576 return (MonoPIFunc) code_buffer;
577 /* return fake_func; */
581 #define MINV_POS 8 /* MonoInvocation structure offset on stack */
582 #define STACK_POS (MINV_POS - sizeof (stackval) * sig->param_count)
584 #define TYPE_OFFSET (G_STRUCT_OFFSET (stackval, type))
587 * Returns a pointer to a native function that can be used to
588 * call the specified method.
589 * The function created will receive the arguments according
590 * to the call convention specified in the method.
591 * This function works by creating a MonoInvocation structure,
592 * filling the fields in and calling ves_exec_method on it.
593 * Still need to figure out how to handle the exception stuff
594 * across the managed/unmanaged boundary.
597 mono_create_method_pointer (MonoMethod *method)
599 MonoMethodSignature *sig;
601 guint8 *p, *code_buffer;
602 guint i, align = 0, code_size, stack_size, stackval_arg_pos, local_pos, local_start, reg_param, stack_param,
603 this_flag, cpos, vt_cur;
608 * If it is a static P/Invoke method, we can just return the pointer
609 * to the method implementation.
611 if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL && method->addr) {
612 ji = g_new0 (MonoJitInfo, 1);
615 ji->code_start = method->addr;
617 mono_jit_info_table_add (mono_root_domain, ji);
625 sig = method->signature;
627 p = code_buffer = g_malloc (code_size);
629 DEBUG (printf ("\nDelegate [start emiting] %s\n", method->name));
632 ppc_stwu (p, ppc_r1, -stack_size, ppc_r1); /* sp <--- sp - stack_size, sp[0] <---- sp save sp, alloc stack */
633 ppc_mflr (p, ppc_r0); /* r0 <--- LR */
634 ppc_stw (p, ppc_r31, stack_size - 4, ppc_r1); /* sp[+4] <--- r31 save r31 */
635 ppc_stw (p, ppc_r0, stack_size + 4, ppc_r1); /* sp[-4] <--- LR save return address for "callme" */
636 ppc_mr (p, ppc_r31, ppc_r1); /* r31 <--- sp */
638 /* let's fill MonoInvocation */
639 /* first zero some fields */
640 ppc_li (p, ppc_r0, 0);
641 ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex)), ppc_r31);
642 ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, ex_handler)), ppc_r31);
643 ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, child)), ppc_r31);
644 ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, parent)), ppc_r31);
646 /* set method pointer */
647 ppc_lis (p, ppc_r0, (guint32) method >> 16);
648 ppc_ori (p, ppc_r0, ppc_r0, (guint32) method & 0xffff);
649 ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, method)), ppc_r31);
651 local_start = local_pos = MINV_POS + sizeof (MonoInvocation) + (sig->param_count + 1) * sizeof (stackval);
654 ppc_stw (p, ppc_r3, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, obj)), ppc_r31);
656 } else if (sig->param_count) {
657 DEBUG (printf ("save r%d\n", 3));
658 ppc_stw (p, ppc_r3, local_pos, ppc_r31);
663 this_flag = (sig->hasthis ? 1 : 0);
664 if (sig->param_count) {
665 gint save_count = MIN (8, sig->param_count - 1);
666 for (i = reg_param; i < save_count; i ++) {
667 ppc_stw (p, ppc_r4 + i, local_pos, ppc_r31);
669 DEBUG (printf ("save r%d\n", 4 + i));
673 /* prepare space for valuetypes */
675 vtbuf = alloca (sizeof(int)*sig->param_count);
677 for (i = 0; i < sig->param_count; i++) {
678 MonoType *type = sig->params [i];
680 if (type->type == MONO_TYPE_VALUETYPE) {
681 MonoClass *klass = type->data.klass;
686 size = mono_class_native_size (klass, &align);
688 cpos &= ~(align - 1);
698 /* set MonoInvocation::stack_args */
699 stackval_arg_pos = MINV_POS + sizeof (MonoInvocation);
700 ppc_addi (p, ppc_r0, ppc_r31, stackval_arg_pos);
701 ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, stack_args)), ppc_r31);
703 /* add stackval arguments */
704 for (i = 0; i < sig->param_count; ++i) {
706 ppc_addi (p, ppc_r5, ppc_r31, local_start + (reg_param - this_flag)*4);
709 ppc_addi (p, ppc_r5, stack_size + 8 + stack_param, ppc_r31);
712 ppc_lis (p, ppc_r3, (guint32) sig->params [i] >> 16);
714 if (vtbuf [i] >= 0) {
715 ppc_addi (p, ppc_r4, ppc_r31, vt_cur);
716 ppc_stw (p, ppc_r4, stackval_arg_pos, ppc_r31);
717 ppc_addi (p, ppc_r4, ppc_r31, stackval_arg_pos);
718 ppc_lwz (p, ppc_r5, 0, ppc_r5);
721 ppc_addi (p, ppc_r4, ppc_r31, stackval_arg_pos);
723 ppc_ori (p, ppc_r3, ppc_r3, (guint32) sig->params [i] & 0xffff);
724 ppc_lis (p, ppc_r0, (guint32) stackval_from_data >> 16);
725 ppc_li (p, ppc_r6, sig->pinvoke);
726 ppc_ori (p, ppc_r0, ppc_r0, (guint32) stackval_from_data & 0xffff);
727 ppc_mtlr (p, ppc_r0);
730 /* fixme: alignment */
731 DEBUG (printf ("arg_pos %d --> ", stackval_arg_pos));
733 stackval_arg_pos += 4*mono_type_native_stack_size (sig->params [i], &align);
735 stackval_arg_pos += 4*mono_type_stack_size (sig->params [i], &align);
736 DEBUG (printf ("%d\n", stackval_arg_pos));
739 /* return value storage */
740 if (sig->param_count) {
741 ppc_addi (p, ppc_r0, ppc_r31, stackval_arg_pos);
743 ppc_stw (p, ppc_r0, (MINV_POS + G_STRUCT_OFFSET (MonoInvocation, retval)), ppc_r31);
745 /* call ves_exec_method */
746 ppc_lis (p, ppc_r0, (guint32) ves_exec_method >> 16);
747 ppc_addi (p, ppc_r3, ppc_r31, MINV_POS);
748 ppc_ori (p, ppc_r0, ppc_r0, (guint32) ves_exec_method & 0xffff);
749 ppc_mtlr (p, ppc_r0);
752 /* move retval from stackval to proper place (r3/r4/...) */
753 if (sig->ret->byref) {
754 DEBUG (printf ("ret by ref\n"));
755 ppc_lwz (p, ppc_r3, stackval_arg_pos, ppc_r31);
758 switch (sig->ret->type) {
761 case MONO_TYPE_BOOLEAN:
764 ppc_lbz (p, ppc_r3, stackval_arg_pos, ppc_r31);
768 ppc_lhz (p, ppc_r3, stackval_arg_pos, ppc_r31);
774 case MONO_TYPE_OBJECT:
775 case MONO_TYPE_STRING:
776 case MONO_TYPE_CLASS:
777 ppc_lwz (p, ppc_r3, stackval_arg_pos, ppc_r31);
780 ppc_lwz (p, ppc_r3, stackval_arg_pos, ppc_r31);
781 ppc_lwz (p, ppc_r4, stackval_arg_pos + 4, ppc_r31);
784 ppc_lfs (p, ppc_f1, stackval_arg_pos, ppc_r31);
787 ppc_lfd (p, ppc_f1, stackval_arg_pos, ppc_r31);
789 case MONO_TYPE_VALUETYPE:
790 if (sig->ret->data.klass->enumtype) {
791 simpletype = sig->ret->data.klass->enum_basetype->type;
794 NOT_IMPLEMENTED ("value type as ret val from delegate");
797 g_error ("Type 0x%x not handled yet in thunk creation", sig->ret->type);
803 ppc_lwz (p, ppc_r11, 0, ppc_r1); /* r11 <--- sp[0] load backchain from caller's function */
804 ppc_lwz (p, ppc_r0, 4, ppc_r11); /* r0 <--- r11[4] load return address */
805 ppc_mtlr (p, ppc_r0); /* LR <--- r0 set return address */
806 ppc_lwz (p, ppc_r31, -4, ppc_r11); /* r31 <--- r11[-4] restore r31 */
807 ppc_mr (p, ppc_r1, ppc_r11); /* sp <--- r11 restore stack */
808 ppc_blr (p); /* return */
810 DEBUG (printf ("emited code size: %d\n", p - code_buffer));
811 flush_icache (code_buffer, p - code_buffer);
813 DEBUG (printf ("Delegate [end emiting]\n"));
815 ji = g_new0 (MonoJitInfo, 1);
817 ji->code_size = p - code_buffer;
818 ji->code_start = code_buffer;
820 mono_jit_info_table_add (mono_root_domain, ji);
822 return ji->code_start;