2 * trampoline.c: JIT trampoline code
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Carlos Valiente <yo@virutass.net>
9 * (C) 2001 Ximian, Inc.
15 #include <mono/metadata/appdomain.h>
16 #include <mono/metadata/marshal.h>
17 #include <mono/metadata/tabledefs.h>
18 #include <mono/arch/ppc/ppc-codegen.h>
19 #include <mono/metadata/mono-debug-debugger.h>
25 MONO_TRAMPOLINE_GENERIC,
27 MONO_TRAMPOLINE_CLASS_INIT
30 /* adapt to mini later... */
31 #define mono_jit_share_code (1)
34 * Address of the x86 trampoline code. This is used by the debugger to check
35 * whether a method is a trampoline.
37 guint8 *mono_generic_trampoline_code = NULL;
40 * get_unbox_trampoline:
42 * @addr: pointer to native code for @m
44 * when value type methods are called through the vtable we need to unbox the
45 * this argument. This method returns a pointer to a trampoline which does
46 * unboxing before calling the method
49 get_unbox_trampoline (MonoMethod *m, gpointer addr)
54 if (!m->signature->ret->byref && MONO_TYPE_ISSTRUCT (m->signature->ret))
57 start = code = g_malloc (20);
59 ppc_load (code, ppc_r11, addr);
60 ppc_mtctr (code, ppc_r11);
61 ppc_addi (code, this_pos, this_pos, sizeof (MonoObject));
62 ppc_bcctr (code, 20, 0);
63 g_assert ((code - start) <= 20);
68 /* Stack size for trampoline function */
71 /* Method-specific trampoline code framgment size */
72 #define METHOD_TRAMPOLINE_SIZE 64
75 * ppc_magic_trampoline:
76 * @code: pointer into caller code
77 * @method: the method to translate
80 * This method is called by the function 'arch_create_jit_trampoline', which in
81 * turn is called by the trampoline functions for virtual methods.
82 * After having called the JIT compiler to compile the method, it inspects the
83 * caller code to find the address of the method-specific part of the
84 * trampoline vtable slot for this method, updates it with a fragment that calls
85 * the newly compiled code and returns this address of the compiled code to
86 * 'arch_create_jit_trampoline'
89 ppc_magic_trampoline (MonoMethod *method, guint32 *code, char *sp)
95 addr = mono_compile_method(method);
98 /* Locate the address of the method-specific trampoline. The call using
99 the vtable slot that took the processing flow to 'arch_create_jit_trampoline'
100 looks something like this:
102 mtlr rA ; Move rA (a register containing the
103 ; target address) to LR
104 blrl ; Call function at LR
106 PowerPC instructions are 32-bit long, which means that a 32-bit target
107 address cannot be encoded as an immediate value (because we already
108 have spent some bits to encode the branch instruction!). That's why a
109 'b'ranch to the contents of the 'l'ink 'r'egister (with 'l'ink register
110 update) is needed, instead of a simpler 'branch immediate'. This
111 complicates our purpose here, because 'blrl' overwrites LR, which holds
112 the value we're interested in.
114 Therefore, we need to locate the 'mtlr rA' instruction to know which
115 register LR was loaded from, and then retrieve the value from that
118 /* This is the 'blrl' instruction */
122 * Note that methods are called also with the bl opcode.
124 if (((*code) >> 26) == 18) {
125 ppc_patch (code, addr);
126 mono_arch_flush_icache (code, 4);
130 /* Sanity check: instruction must be 'blrl' */
131 g_assert(*code == 0x4e800021);
133 /* OK, we're now at the 'blrl' instruction. Now walk backwards
134 till we get to a 'mtlr rA' */
136 if((*code & 0x7c0803a6) == 0x7c0803a6) {
137 /* Here we are: we reached the 'mtlr rA'.
138 Extract the register from the instruction */
139 reg = (*code & 0x03e00000) >> 21;
141 case 0 : o = *((int *) (sp + STACK - 8)); break;
142 case 11: o = *((int *) (sp + STACK - 24)); break;
143 case 12: o = *((int *) (sp + STACK - 28)); break;
144 case 13: o = *((int *) (sp + STACK - 32)); break;
145 case 14: o = *((int *) (sp + STACK - 36)); break;
146 case 15: o = *((int *) (sp + STACK - 40)); break;
147 case 16: o = *((int *) (sp + STACK - 44)); break;
148 case 17: o = *((int *) (sp + STACK - 48)); break;
149 case 18: o = *((int *) (sp + STACK - 52)); break;
150 case 19: o = *((int *) (sp + STACK - 56)); break;
151 case 20: o = *((int *) (sp + STACK - 60)); break;
152 case 21: o = *((int *) (sp + STACK - 64)); break;
153 case 22: o = *((int *) (sp + STACK - 68)); break;
154 case 23: o = *((int *) (sp + STACK - 72)); break;
155 case 24: o = *((int *) (sp + STACK - 76)); break;
156 case 25: o = *((int *) (sp + STACK - 80)); break;
157 case 26: o = *((int *) (sp + STACK - 84)); break;
158 case 27: o = *((int *) (sp + STACK - 88)); break;
159 case 28: o = *((int *) (sp + STACK - 92)); break;
160 case 29: o = *((int *) (sp + STACK - 96)); break;
161 case 30: o = *((int *) (sp + STACK - 100)); break;
162 case 31: o = *((int *) (sp + STACK - 4)); break;
164 printf("%s: Unexpected register %d\n",
166 g_assert_not_reached();
172 /* this is not done for non-virtual calls, because in that case
173 we won't have an object, but the actual pointer to the
174 valuetype as the this argument
176 if (method->klass->valuetype)
177 addr = get_unbox_trampoline (method, addr);
179 /* Finally, replace the method-specific trampoline code (which called
180 the generic trampoline code) with a fragment that calls directly the
184 ppc_stwu (o, ppc_r1, -16, ppc_r1);
185 ppc_mflr (o, ppc_r0);
186 ppc_stw (o, ppc_r31, 12, ppc_r1);
187 ppc_stw (o, ppc_r0, 20, ppc_r1);
188 ppc_mr (o, ppc_r31, ppc_r1);
190 ppc_lis (o, ppc_r0, (guint32) addr >> 16);
191 ppc_ori (o, ppc_r0, ppc_r0, (guint32) addr & 0xffff);
192 ppc_mtlr (o, ppc_r0);
195 ppc_lwz (o, ppc_r11, 0, ppc_r1);
196 ppc_lwz (o, ppc_r0, 4, ppc_r11);
197 ppc_mtlr (o, ppc_r0);
198 ppc_lwz (o, ppc_r31, -4, ppc_r11);
199 ppc_mr (o, ppc_r1, ppc_r11);
202 mono_arch_flush_icache (start, o - start);
203 g_assert(o - start < METHOD_TRAMPOLINE_SIZE);
209 ppc_class_init_trampoline (void *vtable, guint32 *code, char *sp)
211 mono_runtime_class_init (vtable);
213 /* This is the 'bl' instruction */
216 if (((*code) >> 26) == 18) {
217 ppc_ori (code, 0, 0, 0); /* nop */
218 mono_arch_flush_icache (code, 4);
221 g_assert_not_reached ();
226 create_trampoline_code (MonoTrampolineType tramp_type)
228 guint8 *buf, *code = NULL;
229 static guint8* generic_jump_trampoline = NULL;
230 static guint8 *generic_class_init_trampoline = NULL;
232 switch (tramp_type) {
233 case MONO_TRAMPOLINE_GENERIC:
234 if (mono_generic_trampoline_code)
235 return mono_generic_trampoline_code;
237 case MONO_TRAMPOLINE_JUMP:
238 if (generic_jump_trampoline)
239 return generic_jump_trampoline;
241 case MONO_TRAMPOLINE_CLASS_INIT:
242 if (generic_class_init_trampoline)
243 return generic_class_init_trampoline;
248 /* Now we'll create in 'buf' the PowerPC trampoline code. This
249 is the trampoline code common to all methods */
251 code = buf = g_malloc(512);
253 /*-----------------------------------------------------------
254 STEP 0: First create a non-standard function prologue with a
255 stack size big enough to save our registers:
257 lr (We'll be calling functions here, so we
259 r0 (See ppc_magic_trampoline)
260 r1 (sp) (Stack pointer - must save)
261 r3-r10 Function arguments.
262 r11-r31 (See ppc_magic_trampoline)
263 method in r11 (See ppc_magic_trampoline)
265 This prologue is non-standard because r0 is not saved here - it
266 was saved in the method-specific trampoline code
267 -----------------------------------------------------------*/
269 ppc_stwu (buf, ppc_r1, -STACK, ppc_r1);
271 /* Save r0 before modifying it - we will need its contents in
272 'ppc_magic_trampoline' */
273 ppc_stw (buf, ppc_r0, STACK - 8, ppc_r1);
275 ppc_stw (buf, ppc_r31, STACK - 4, ppc_r1);
276 ppc_mr (buf, ppc_r31, ppc_r1);
278 /* Now save our registers. */
279 ppc_stw (buf, ppc_r3, STACK - 12, ppc_r1);
280 ppc_stw (buf, ppc_r4, STACK - 16, ppc_r1);
281 ppc_stw (buf, ppc_r5, STACK - 20, ppc_r1);
282 ppc_stw (buf, ppc_r6, STACK - 24, ppc_r1);
283 ppc_stw (buf, ppc_r7, STACK - 28, ppc_r1);
284 ppc_stw (buf, ppc_r8, STACK - 32, ppc_r1);
285 ppc_stw (buf, ppc_r9, STACK - 36, ppc_r1);
286 ppc_stw (buf, ppc_r10, STACK - 40, ppc_r1);
287 /* STACK - 44 contains r11, which is set in the method-specific
288 part of the trampoline (see bellow this 'if' block) */
289 ppc_stw (buf, ppc_r12, STACK - 48, ppc_r1);
290 ppc_stw (buf, ppc_r13, STACK - 52, ppc_r1);
291 ppc_stw (buf, ppc_r14, STACK - 56, ppc_r1);
292 ppc_stw (buf, ppc_r15, STACK - 60, ppc_r1);
293 ppc_stw (buf, ppc_r16, STACK - 64, ppc_r1);
294 ppc_stw (buf, ppc_r17, STACK - 68, ppc_r1);
295 ppc_stw (buf, ppc_r18, STACK - 72, ppc_r1);
296 ppc_stw (buf, ppc_r19, STACK - 76, ppc_r1);
297 ppc_stw (buf, ppc_r20, STACK - 80, ppc_r1);
298 ppc_stw (buf, ppc_r21, STACK - 84, ppc_r1);
299 ppc_stw (buf, ppc_r22, STACK - 88, ppc_r1);
300 ppc_stw (buf, ppc_r23, STACK - 92, ppc_r1);
301 ppc_stw (buf, ppc_r24, STACK - 96, ppc_r1);
302 ppc_stw (buf, ppc_r25, STACK - 100, ppc_r1);
303 ppc_stw (buf, ppc_r26, STACK - 104, ppc_r1);
304 ppc_stw (buf, ppc_r27, STACK - 108, ppc_r1);
305 ppc_stw (buf, ppc_r28, STACK - 112, ppc_r1);
306 ppc_stw (buf, ppc_r29, STACK - 116, ppc_r1);
307 ppc_stw (buf, ppc_r30, STACK - 120, ppc_r1);
308 /* Save 'method' pseudo-parameter - the one passed in r11 */
309 ppc_stw (buf, ppc_r11, STACK - 124, ppc_r1);
311 /*----------------------------------------------------------
312 STEP 1: call 'mono_get_lmf_addr()' to get the address of our
313 LMF. We'll need to restore it after the call to
314 'ppc_magic_trampoline' and before the call to the native
316 ----------------------------------------------------------*/
318 /* Calculate the address and make the call. Keep in mind that
319 we're using r0, so we'll have to restore it before calling
320 'ppc_magic_trampoline' */
321 ppc_lis (buf, ppc_r0, (guint32) mono_get_lmf_addr >> 16);
322 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) mono_get_lmf_addr & 0xffff);
323 ppc_mtlr (buf, ppc_r0);
326 /* XXX Update LMF !!! */
328 /*----------------------------------------------------------
329 STEP 2: call 'ppc_magic_trampoline()', who will compile the
330 code and fix the method vtable entry for us
331 ----------------------------------------------------------*/
335 /* Arg 1: MonoMethod *method. It was put in r11 by the
336 method-specific trampoline code, and then saved before the call
337 to mono_get_lmf_addr()'. Restore r11, by the way :-) */
338 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
339 ppc_li (buf, ppc_r3, 0);
341 ppc_lwz (buf, ppc_r3, STACK - 124, ppc_r1);
342 ppc_lwz (buf, ppc_r11, STACK - 44, ppc_r1);
344 /* Arg 2: code (next address to the instruction that called us) */
345 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
346 ppc_li (buf, ppc_r4, 0);
348 ppc_lwz (buf, ppc_r4, STACK + 4, ppc_r1);
350 /* Arg 3: stack pointer */
351 ppc_mr (buf, ppc_r5, ppc_r1);
353 /* Calculate call address, restore r0 and call
354 'ppc_magic_trampoline'. Return value will be in r3 */
355 if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
356 ppc_lis (buf, ppc_r0, (guint32) ppc_class_init_trampoline >> 16);
357 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_class_init_trampoline & 0xffff);
359 ppc_lis (buf, ppc_r0, (guint32) ppc_magic_trampoline >> 16);
360 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_magic_trampoline & 0xffff);
362 ppc_mtlr (buf, ppc_r0);
363 ppc_lwz (buf, ppc_r0, STACK - 8, ppc_r1);
366 /* OK, code address is now on r3. Move it to r0, so that we
367 can restore r3 and use it from r0 later */
368 ppc_mr (buf, ppc_r0, ppc_r3);
371 /*----------------------------------------------------------
372 STEP 3: Restore the LMF
373 ----------------------------------------------------------*/
377 /*----------------------------------------------------------
378 STEP 4: call the compiled method
379 ----------------------------------------------------------*/
381 /* Restore registers */
383 ppc_lwz (buf, ppc_r3, STACK - 12, ppc_r1);
384 ppc_lwz (buf, ppc_r4, STACK - 16, ppc_r1);
385 ppc_lwz (buf, ppc_r5, STACK - 20, ppc_r1);
386 ppc_lwz (buf, ppc_r6, STACK - 24, ppc_r1);
387 ppc_lwz (buf, ppc_r7, STACK - 28, ppc_r1);
388 ppc_lwz (buf, ppc_r8, STACK - 32, ppc_r1);
389 ppc_lwz (buf, ppc_r9, STACK - 36, ppc_r1);
390 ppc_lwz (buf, ppc_r10, STACK - 40, ppc_r1);
392 /* We haven't touched any of these, so there's no need to
395 ppc_lwz (buf, ppc_r14, STACK - 56, ppc_r1);
396 ppc_lwz (buf, ppc_r15, STACK - 60, ppc_r1);
397 ppc_lwz (buf, ppc_r16, STACK - 64, ppc_r1);
398 ppc_lwz (buf, ppc_r17, STACK - 68, ppc_r1);
399 ppc_lwz (buf, ppc_r18, STACK - 72, ppc_r1);
400 ppc_lwz (buf, ppc_r19, STACK - 76, ppc_r1);
401 ppc_lwz (buf, ppc_r20, STACK - 80, ppc_r1);
402 ppc_lwz (buf, ppc_r21, STACK - 84, ppc_r1);
403 ppc_lwz (buf, ppc_r22, STACK - 88, ppc_r1);
404 ppc_lwz (buf, ppc_r23, STACK - 92, ppc_r1);
405 ppc_lwz (buf, ppc_r24, STACK - 96, ppc_r1);
406 ppc_lwz (buf, ppc_r25, STACK - 100, ppc_r1);
407 ppc_lwz (buf, ppc_r26, STACK - 104, ppc_r1);
408 ppc_lwz (buf, ppc_r27, STACK - 108, ppc_r1);
409 ppc_lwz (buf, ppc_r28, STACK - 112, ppc_r1);
410 ppc_lwz (buf, ppc_r29, STACK - 116, ppc_r1);
411 ppc_lwz (buf, ppc_r30, STACK - 120, ppc_r1);
414 /* Non-standard function epilogue. Instead of doing a proper
415 return, we just call the compiled code, so
416 that, when it finishes, the method returns here. */
418 ppc_mtlr (buf, ppc_r0);
421 /* Restore stack pointer, r31, LR and return to caller */
422 ppc_lwz (buf, ppc_r11, 0, ppc_r1);
423 ppc_lwz (buf, ppc_r31, -4, ppc_r11);
424 ppc_mr (buf, ppc_r1, ppc_r11);
425 ppc_lwz (buf, ppc_r0, 4, ppc_r1);
426 ppc_mtlr (buf, ppc_r0);
429 /* Flush instruction cache, since we've generated code */
430 mono_arch_flush_icache (code, buf - code);
433 g_assert ((buf - code) <= 512);
436 switch (tramp_type) {
437 case MONO_TRAMPOLINE_GENERIC:
438 mono_generic_trampoline_code = code;
440 case MONO_TRAMPOLINE_JUMP:
441 generic_jump_trampoline = code;
443 case MONO_TRAMPOLINE_CLASS_INIT:
444 generic_class_init_trampoline = code;
452 * arch_create_jit_trampoline:
453 * @method: pointer to the method info
455 * Creates a trampoline function for virtual methods. If the created
456 * code is called it first starts JIT compilation of method,
457 * and then calls the newly created method. It also replaces the
458 * corresponding vtable entry (see ppc_magic_trampoline).
460 * A trampoline consists of two parts: a main fragment, shared by all method
461 * trampolines, and some code specific to each method, which hard-codes a
462 * reference to that method and then calls the main fragment.
464 * The main fragment contains a call to 'ppc_magic_trampoline', which performs
465 * call to the JIT compiler and substitutes the method-specific fragment with
466 * some code that directly calls the JIT-compiled method.
468 * Returns: a pointer to the newly created code
471 mono_arch_create_jit_trampoline (MonoMethod *method)
474 static guint8 *vc = NULL;
476 /* previously created trampoline code */
480 /* we immediately compile runtime provided functions */
481 if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
482 method->info = mono_compile_method (method);
486 /* icalls use method->addr */
487 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
488 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
491 nm = mono_marshal_get_native_wrapper (method);
492 method->info = mono_compile_method (nm);
496 if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
497 return mono_arch_create_jit_trampoline (mono_marshal_get_synchronized_wrapper (method));
499 vc = create_trampoline_code (MONO_TRAMPOLINE_GENERIC);
501 /* This is the method-specific part of the trampoline. Its purpose is
502 to provide the generic part with the MonoMethod *method pointer. We'll
503 use r11 to keep that value, for instance. However, the generic part of
504 the trampoline relies on r11 having the same value it had before coming
505 here, so we must save it before. */
506 code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
508 /* Save r11. There's nothing magic in the '44', its just an arbitrary
509 position - see above */
510 ppc_stw (buf, ppc_r11, -44, ppc_r1);
512 /* Now save LR - we'll overwrite it now */
513 ppc_mflr (buf, ppc_r11);
514 ppc_stw (buf, ppc_r11, 4, ppc_r1);
516 /* Prepare the jump to the generic trampoline code.*/
517 ppc_lis (buf, ppc_r11, (guint32) vc >> 16);
518 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) vc & 0xffff);
519 ppc_mtlr (buf, ppc_r11);
521 /* And finally put 'method' in r11 and fly! */
522 ppc_lis (buf, ppc_r11, (guint32) method >> 16);
523 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) method & 0xffff);
526 /* Flush instruction cache, since we've generated code */
527 mono_arch_flush_icache (code, buf - code);
530 g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
532 /* Store trampoline address */
535 mono_jit_stats.method_trampolines++;
543 * x86_magic_trampoline:
544 * @eax: saved x86 register
545 * @ecx: saved x86 register
546 * @edx: saved x86 register
547 * @esi: saved x86 register
548 * @edi: saved x86 register
549 * @ebx: saved x86 register
550 * @code: pointer into caller code
551 * @method: the method to translate
553 * This method is called by the trampoline functions for virtual
554 * methods. It inspects the caller code to find the address of the
555 * vtable slot, then calls the JIT compiler and writes the address
556 * of the compiled method back to the vtable. All virtual methods
557 * are called with: x86_call_membase (inst, basereg, disp). We always
558 * use 32 bit displacement to ensure that the length of the call
559 * instruction is 6 bytes. We need to get the value of the basereg
560 * and the constant displacement.
563 x86_magic_trampoline (int eax, int ecx, int edx, int esi, int edi,
564 int ebx, guint8 *code, MonoMethod *m)
571 addr = mono_compile_method (m);
574 /* go to the start of the call instruction
576 * address_byte = (m << 6) | (o << 3) | reg
577 * call opcode: 0xff address_byte displacement
582 if ((code [1] != 0xe8) && (code [3] == 0xff) && ((code [4] & 0x18) == 0x10) && ((code [4] >> 6) == 1)) {
583 reg = code [4] & 0x07;
584 disp = (signed char)code [5];
586 if ((code [0] == 0xff) && ((code [1] & 0x18) == 0x10) && ((code [1] >> 6) == 2)) {
587 reg = code [1] & 0x07;
588 disp = *((gint32*)(code + 2));
589 } else if ((code [1] == 0xe8)) {
590 *((guint32*)(code + 2)) = (guint)addr - ((guint)code + 1) - 5;
592 } else if ((code [4] == 0xff) && (((code [5] >> 6) & 0x3) == 0) && (((code [5] >> 3) & 0x7) == 2)) {
594 * This is a interface call: should check the above code can't catch it earlier
595 * 8b 40 30 mov 0x30(%eax),%eax
599 reg = code [5] & 0x07;
601 printf ("Invalid trampoline sequence: %x %x %x %x %x %x %x\n", code [0], code [1], code [2], code [3],
602 code [4], code [5], code [6]);
603 g_assert_not_reached ();
627 g_assert_not_reached ();
632 if (m->klass->valuetype) {
633 return *((gpointer *)o) = get_unbox_trampoline (m, addr);
635 return *((gpointer *)o) = addr;
640 * mono_arch_create_jit_trampoline:
641 * @method: pointer to the method info
643 * Creates a trampoline function for virtual methods. If the created
644 * code is called it first starts JIT compilation of method,
645 * and then calls the newly created method. I also replaces the
646 * corresponding vtable entry (see x86_magic_trampoline).
648 * Returns: a pointer to the newly created code
651 mono_arch_create_jit_trampoline (MonoMethod *method)
655 /* previously created trampoline code */
659 /* we immediately compile runtime provided functions */
660 if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
661 method->info = mono_compile_method (method);
665 /* icalls use method->addr */
666 if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
667 (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
670 nm = mono_marshal_get_native_wrapper (method);
671 method->info = mono_compile_method (nm);
675 if (!mono_generic_trampoline_code) {
676 mono_generic_trampoline_code = buf = g_malloc (256);
677 /* save caller save regs because we need to do a call */
678 x86_push_reg (buf, X86_EDX);
679 x86_push_reg (buf, X86_EAX);
680 x86_push_reg (buf, X86_ECX);
684 /* save the IP (caller ip) */
685 x86_push_membase (buf, X86_ESP, 16);
687 x86_push_reg (buf, X86_EBX);
688 x86_push_reg (buf, X86_EDI);
689 x86_push_reg (buf, X86_ESI);
690 x86_push_reg (buf, X86_EBP);
692 /* save method info */
693 x86_push_membase (buf, X86_ESP, 32);
694 /* get the address of lmf for the current thread */
695 x86_call_code (buf, mono_get_lmf_addr);
697 x86_push_reg (buf, X86_EAX);
698 /* push *lfm (previous_lmf) */
699 x86_push_membase (buf, X86_EAX, 0);
701 x86_mov_membase_reg (buf, X86_EAX, 0, X86_ESP, 4);
704 /* push the method info */
705 x86_push_membase (buf, X86_ESP, 44);
706 /* push the return address onto the stack */
707 x86_push_membase (buf, X86_ESP, 52);
709 /* save all register values */
710 x86_push_reg (buf, X86_EBX);
711 x86_push_reg (buf, X86_EDI);
712 x86_push_reg (buf, X86_ESI);
713 x86_push_membase (buf, X86_ESP, 64); /* EDX */
714 x86_push_membase (buf, X86_ESP, 64); /* ECX */
715 x86_push_membase (buf, X86_ESP, 64); /* EAX */
717 x86_call_code (buf, x86_magic_trampoline);
718 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 8*4);
720 /* restore LMF start */
721 /* ebx = previous_lmf */
722 x86_pop_reg (buf, X86_EBX);
724 x86_pop_reg (buf, X86_EDI);
725 /* *(lmf) = previous_lmf */
726 x86_mov_membase_reg (buf, X86_EDI, 0, X86_EBX, 4);
727 /* discard method info */
728 x86_pop_reg (buf, X86_ESI);
729 /* restore caller saved regs */
730 x86_pop_reg (buf, X86_EBP);
731 x86_pop_reg (buf, X86_ESI);
732 x86_pop_reg (buf, X86_EDI);
733 x86_pop_reg (buf, X86_EBX);
734 /* discard save IP */
735 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 4);
736 /* restore LMF end */
738 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 16);
740 /* call the compiled method */
741 x86_jump_reg (buf, X86_EAX);
743 g_assert ((buf - mono_generic_trampoline_code) <= 256);
746 code = buf = g_malloc (16);
747 x86_push_imm (buf, method);
748 x86_jump_code (buf, mono_generic_trampoline_code);
749 g_assert ((buf - code) <= 16);
751 /* store trampoline address */
754 //mono_jit_stats.method_trampolines++;
762 * mono_arch_create_class_init_trampoline:
763 * @vtable: the type to initialize
765 * Creates a trampoline function to run a type initializer.
766 * If the trampoline is called, it calls mono_runtime_class_init with the
767 * given vtable, then patches the caller code so it does not get called any
770 * Returns: a pointer to the newly created code
773 mono_arch_create_class_init_trampoline (MonoVTable *vtable)
775 guint8 *code, *buf, *tramp;
777 tramp = create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
779 /* This is the method-specific part of the trampoline. Its purpose is
780 to provide the generic part with the MonoMethod *method pointer. We'll
781 use r11 to keep that value, for instance. However, the generic part of
782 the trampoline relies on r11 having the same value it had before coming
783 here, so we must save it before. */
784 code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
786 /* Save r11. There's nothing magic in the '44', its just an arbitrary
787 position - see above */
788 ppc_stw (buf, ppc_r11, -44, ppc_r1);
790 /* Now save LR - we'll overwrite it now */
791 ppc_mflr (buf, ppc_r11);
792 ppc_stw (buf, ppc_r11, 4, ppc_r1);
794 /* Prepare the jump to the generic trampoline code.*/
795 ppc_lis (buf, ppc_r11, (guint32) tramp >> 16);
796 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) tramp & 0xffff);
797 ppc_mtlr (buf, ppc_r11);
799 /* And finally put 'vtable' in r11 and fly! */
800 ppc_lis (buf, ppc_r11, (guint32) vtable >> 16);
801 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) vtable & 0xffff);
804 /* Flush instruction cache, since we've generated code */
805 mono_arch_flush_icache (code, buf - code);
808 g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
810 mono_jit_stats.method_trampolines++;
816 * This method is only called when running in the Mono Debugger.
819 mono_debugger_create_notification_function (gpointer *notification_address)
823 ptr = buf = g_malloc0 (16);
825 if (notification_address)
826 *notification_address = buf;