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 */
69 #define STACK (144 + 8*8)
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);
214 /* This is the 'bl' instruction */
217 if (((*code) >> 26) == 18) {
218 ppc_ori (code, 0, 0, 0); /* nop */
219 mono_arch_flush_icache (code, 4);
222 g_assert_not_reached ();
228 create_trampoline_code (MonoTrampolineType tramp_type)
230 guint8 *buf, *code = NULL;
231 static guint8* generic_jump_trampoline = NULL;
232 static guint8 *generic_class_init_trampoline = NULL;
235 switch (tramp_type) {
236 case MONO_TRAMPOLINE_GENERIC:
237 if (mono_generic_trampoline_code)
238 return mono_generic_trampoline_code;
240 case MONO_TRAMPOLINE_JUMP:
241 if (generic_jump_trampoline)
242 return generic_jump_trampoline;
244 case MONO_TRAMPOLINE_CLASS_INIT:
245 if (generic_class_init_trampoline)
246 return generic_class_init_trampoline;
251 /* Now we'll create in 'buf' the PowerPC trampoline code. This
252 is the trampoline code common to all methods */
254 code = buf = g_malloc(512);
256 /*-----------------------------------------------------------
257 STEP 0: First create a non-standard function prologue with a
258 stack size big enough to save our registers:
260 lr (We'll be calling functions here, so we
262 r0 (See ppc_magic_trampoline)
263 r1 (sp) (Stack pointer - must save)
264 r3-r10 Function arguments.
265 r11-r31 (See ppc_magic_trampoline)
266 method in r11 (See ppc_magic_trampoline)
268 This prologue is non-standard because r0 is not saved here - it
269 was saved in the method-specific trampoline code
270 -----------------------------------------------------------*/
272 ppc_stwu (buf, ppc_r1, -STACK, ppc_r1);
274 /* Save r0 before modifying it - we will need its contents in
275 'ppc_magic_trampoline' */
276 ppc_stw (buf, ppc_r0, STACK - 8, ppc_r1);
278 ppc_stw (buf, ppc_r31, STACK - 4, ppc_r1);
279 ppc_mr (buf, ppc_r31, ppc_r1);
281 /* Now save our registers. */
282 ppc_stw (buf, ppc_r3, STACK - 12, ppc_r1);
283 ppc_stw (buf, ppc_r4, STACK - 16, ppc_r1);
284 ppc_stw (buf, ppc_r5, STACK - 20, ppc_r1);
285 ppc_stw (buf, ppc_r6, STACK - 24, ppc_r1);
286 ppc_stw (buf, ppc_r7, STACK - 28, ppc_r1);
287 ppc_stw (buf, ppc_r8, STACK - 32, ppc_r1);
288 ppc_stw (buf, ppc_r9, STACK - 36, ppc_r1);
289 ppc_stw (buf, ppc_r10, STACK - 40, ppc_r1);
290 /* STACK - 44 contains r11, which is set in the method-specific
291 part of the trampoline (see bellow this 'if' block) */
292 ppc_stw (buf, ppc_r12, STACK - 48, ppc_r1);
293 ppc_stw (buf, ppc_r13, STACK - 52, ppc_r1);
294 ppc_stw (buf, ppc_r14, STACK - 56, ppc_r1);
295 ppc_stw (buf, ppc_r15, STACK - 60, ppc_r1);
296 ppc_stw (buf, ppc_r16, STACK - 64, ppc_r1);
297 ppc_stw (buf, ppc_r17, STACK - 68, ppc_r1);
298 ppc_stw (buf, ppc_r18, STACK - 72, ppc_r1);
299 ppc_stw (buf, ppc_r19, STACK - 76, ppc_r1);
300 ppc_stw (buf, ppc_r20, STACK - 80, ppc_r1);
301 ppc_stw (buf, ppc_r21, STACK - 84, ppc_r1);
302 ppc_stw (buf, ppc_r22, STACK - 88, ppc_r1);
303 ppc_stw (buf, ppc_r23, STACK - 92, ppc_r1);
304 ppc_stw (buf, ppc_r24, STACK - 96, ppc_r1);
305 ppc_stw (buf, ppc_r25, STACK - 100, ppc_r1);
306 ppc_stw (buf, ppc_r26, STACK - 104, ppc_r1);
307 ppc_stw (buf, ppc_r27, STACK - 108, ppc_r1);
308 ppc_stw (buf, ppc_r28, STACK - 112, ppc_r1);
309 ppc_stw (buf, ppc_r29, STACK - 116, ppc_r1);
310 ppc_stw (buf, ppc_r30, STACK - 120, ppc_r1);
311 /* Save 'method' pseudo-parameter - the one passed in r11 */
312 ppc_stw (buf, ppc_r11, STACK - 124, ppc_r1);
314 /* Save the FP registers */
315 offset = 124 + 4 + 8;
316 for (i = ppc_f1; i <= ppc_f8; ++i) {
317 ppc_stfd (buf, i, STACK - offset, ppc_r1);
321 /*----------------------------------------------------------
322 STEP 1: call 'mono_get_lmf_addr()' to get the address of our
323 LMF. We'll need to restore it after the call to
324 'ppc_magic_trampoline' and before the call to the native
326 ----------------------------------------------------------*/
328 /* Calculate the address and make the call. Keep in mind that
329 we're using r0, so we'll have to restore it before calling
330 'ppc_magic_trampoline' */
331 ppc_lis (buf, ppc_r0, (guint32) mono_get_lmf_addr >> 16);
332 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) mono_get_lmf_addr & 0xffff);
333 ppc_mtlr (buf, ppc_r0);
336 /* XXX Update LMF !!! */
338 /*----------------------------------------------------------
339 STEP 2: call 'ppc_magic_trampoline()', who will compile the
340 code and fix the method vtable entry for us
341 ----------------------------------------------------------*/
345 /* Arg 1: MonoMethod *method. It was put in r11 by the
346 method-specific trampoline code, and then saved before the call
347 to mono_get_lmf_addr()'. Restore r11, by the way :-) */
348 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
349 ppc_li (buf, ppc_r3, 0);
351 ppc_lwz (buf, ppc_r3, STACK - 124, ppc_r1);
352 ppc_lwz (buf, ppc_r11, STACK - 44, ppc_r1);
354 /* Arg 2: code (next address to the instruction that called us) */
355 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
356 ppc_li (buf, ppc_r4, 0);
358 ppc_lwz (buf, ppc_r4, STACK + 4, ppc_r1);
360 /* Arg 3: stack pointer */
361 ppc_mr (buf, ppc_r5, ppc_r1);
363 /* Calculate call address, restore r0 and call
364 'ppc_magic_trampoline'. Return value will be in r3 */
365 if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
366 ppc_lis (buf, ppc_r0, (guint32) ppc_class_init_trampoline >> 16);
367 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_class_init_trampoline & 0xffff);
369 ppc_lis (buf, ppc_r0, (guint32) ppc_magic_trampoline >> 16);
370 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_magic_trampoline & 0xffff);
372 ppc_mtlr (buf, ppc_r0);
373 ppc_lwz (buf, ppc_r0, STACK - 8, ppc_r1);
376 /* OK, code address is now on r3. Move it to r0, so that we
377 can restore r3 and use it from r0 later */
378 ppc_mr (buf, ppc_r0, ppc_r3);
381 /*----------------------------------------------------------
382 STEP 3: Restore the LMF
383 ----------------------------------------------------------*/
387 /*----------------------------------------------------------
388 STEP 4: call the compiled method
389 ----------------------------------------------------------*/
391 /* Restore registers */
393 ppc_lwz (buf, ppc_r3, STACK - 12, ppc_r1);
394 ppc_lwz (buf, ppc_r4, STACK - 16, ppc_r1);
395 ppc_lwz (buf, ppc_r5, STACK - 20, ppc_r1);
396 ppc_lwz (buf, ppc_r6, STACK - 24, ppc_r1);
397 ppc_lwz (buf, ppc_r7, STACK - 28, ppc_r1);
398 ppc_lwz (buf, ppc_r8, STACK - 32, ppc_r1);
399 ppc_lwz (buf, ppc_r9, STACK - 36, ppc_r1);
400 ppc_lwz (buf, ppc_r10, STACK - 40, ppc_r1);
402 /* Restore the FP registers */
403 offset = 124 + 4 + 8;
404 for (i = ppc_f1; i <= ppc_f8; ++i) {
405 ppc_lfd (buf, i, STACK - offset, ppc_r1);
408 /* We haven't touched any of these, so there's no need to
411 ppc_lwz (buf, ppc_r14, STACK - 56, ppc_r1);
412 ppc_lwz (buf, ppc_r15, STACK - 60, ppc_r1);
413 ppc_lwz (buf, ppc_r16, STACK - 64, ppc_r1);
414 ppc_lwz (buf, ppc_r17, STACK - 68, ppc_r1);
415 ppc_lwz (buf, ppc_r18, STACK - 72, ppc_r1);
416 ppc_lwz (buf, ppc_r19, STACK - 76, ppc_r1);
417 ppc_lwz (buf, ppc_r20, STACK - 80, ppc_r1);
418 ppc_lwz (buf, ppc_r21, STACK - 84, ppc_r1);
419 ppc_lwz (buf, ppc_r22, STACK - 88, ppc_r1);
420 ppc_lwz (buf, ppc_r23, STACK - 92, ppc_r1);
421 ppc_lwz (buf, ppc_r24, STACK - 96, ppc_r1);
422 ppc_lwz (buf, ppc_r25, STACK - 100, ppc_r1);
423 ppc_lwz (buf, ppc_r26, STACK - 104, ppc_r1);
424 ppc_lwz (buf, ppc_r27, STACK - 108, ppc_r1);
425 ppc_lwz (buf, ppc_r28, STACK - 112, ppc_r1);
426 ppc_lwz (buf, ppc_r29, STACK - 116, ppc_r1);
427 ppc_lwz (buf, ppc_r30, STACK - 120, ppc_r1);
430 /* Non-standard function epilogue. Instead of doing a proper
431 return, we just call the compiled code, so
432 that, when it finishes, the method returns here. */
434 ppc_mtlr (buf, ppc_r0);
437 /* Restore stack pointer, r31, LR and return to caller */
438 ppc_lwz (buf, ppc_r11, 0, ppc_r1);
439 ppc_lwz (buf, ppc_r31, -4, ppc_r11);
440 ppc_mr (buf, ppc_r1, ppc_r11);
441 ppc_lwz (buf, ppc_r0, 4, ppc_r1);
442 ppc_mtlr (buf, ppc_r0);
445 /* Flush instruction cache, since we've generated code */
446 mono_arch_flush_icache (code, buf - code);
449 g_assert ((buf - code) <= 512);
452 switch (tramp_type) {
453 case MONO_TRAMPOLINE_GENERIC:
454 mono_generic_trampoline_code = code;
456 case MONO_TRAMPOLINE_JUMP:
457 generic_jump_trampoline = code;
459 case MONO_TRAMPOLINE_CLASS_INIT:
460 generic_class_init_trampoline = code;
468 * arch_create_jit_trampoline:
469 * @method: pointer to the method info
471 * Creates a trampoline function for virtual methods. If the created
472 * code is called it first starts JIT compilation of method,
473 * and then calls the newly created method. It also replaces the
474 * corresponding vtable entry (see ppc_magic_trampoline).
476 * A trampoline consists of two parts: a main fragment, shared by all method
477 * trampolines, and some code specific to each method, which hard-codes a
478 * reference to that method and then calls the main fragment.
480 * The main fragment contains a call to 'ppc_magic_trampoline', which performs
481 * call to the JIT compiler and substitutes the method-specific fragment with
482 * some code that directly calls the JIT-compiled method.
484 * Returns: a pointer to the newly created code
487 mono_arch_create_jit_trampoline (MonoMethod *method)
490 static guint8 *vc = NULL;
492 /* previously created trampoline code */
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);
515 ppc_stw (buf, ppc_r11, 8, ppc_r1);
517 /* Prepare the jump to the generic trampoline code.*/
518 ppc_lis (buf, ppc_r11, (guint32) vc >> 16);
519 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) vc & 0xffff);
520 ppc_mtlr (buf, ppc_r11);
522 /* And finally put 'method' in r11 and fly! */
523 ppc_lis (buf, ppc_r11, (guint32) method >> 16);
524 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) method & 0xffff);
527 /* Flush instruction cache, since we've generated code */
528 mono_arch_flush_icache (code, buf - code);
531 g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
533 /* Store trampoline address */
536 mono_jit_stats.method_trampolines++;
544 * x86_magic_trampoline:
545 * @eax: saved x86 register
546 * @ecx: saved x86 register
547 * @edx: saved x86 register
548 * @esi: saved x86 register
549 * @edi: saved x86 register
550 * @ebx: saved x86 register
551 * @code: pointer into caller code
552 * @method: the method to translate
554 * This method is called by the trampoline functions for virtual
555 * methods. It inspects the caller code to find the address of the
556 * vtable slot, then calls the JIT compiler and writes the address
557 * of the compiled method back to the vtable. All virtual methods
558 * are called with: x86_call_membase (inst, basereg, disp). We always
559 * use 32 bit displacement to ensure that the length of the call
560 * instruction is 6 bytes. We need to get the value of the basereg
561 * and the constant displacement.
564 x86_magic_trampoline (int eax, int ecx, int edx, int esi, int edi,
565 int ebx, guint8 *code, MonoMethod *m)
572 addr = mono_compile_method (m);
575 /* go to the start of the call instruction
577 * address_byte = (m << 6) | (o << 3) | reg
578 * call opcode: 0xff address_byte displacement
583 if ((code [1] != 0xe8) && (code [3] == 0xff) && ((code [4] & 0x18) == 0x10) && ((code [4] >> 6) == 1)) {
584 reg = code [4] & 0x07;
585 disp = (signed char)code [5];
587 if ((code [0] == 0xff) && ((code [1] & 0x18) == 0x10) && ((code [1] >> 6) == 2)) {
588 reg = code [1] & 0x07;
589 disp = *((gint32*)(code + 2));
590 } else if ((code [1] == 0xe8)) {
591 *((guint32*)(code + 2)) = (guint)addr - ((guint)code + 1) - 5;
593 } else if ((code [4] == 0xff) && (((code [5] >> 6) & 0x3) == 0) && (((code [5] >> 3) & 0x7) == 2)) {
595 * This is a interface call: should check the above code can't catch it earlier
596 * 8b 40 30 mov 0x30(%eax),%eax
600 reg = code [5] & 0x07;
602 printf ("Invalid trampoline sequence: %x %x %x %x %x %x %x\n", code [0], code [1], code [2], code [3],
603 code [4], code [5], code [6]);
604 g_assert_not_reached ();
628 g_assert_not_reached ();
633 if (m->klass->valuetype) {
634 return *((gpointer *)o) = get_unbox_trampoline (m, addr);
636 return *((gpointer *)o) = addr;
641 * mono_arch_create_jit_trampoline:
642 * @method: pointer to the method info
644 * Creates a trampoline function for virtual methods. If the created
645 * code is called it first starts JIT compilation of method,
646 * and then calls the newly created method. I also replaces the
647 * corresponding vtable entry (see x86_magic_trampoline).
649 * Returns: a pointer to the newly created code
652 mono_arch_create_jit_trampoline (MonoMethod *method)
656 /* previously created trampoline code */
660 if (!mono_generic_trampoline_code) {
661 mono_generic_trampoline_code = buf = g_malloc (256);
662 /* save caller save regs because we need to do a call */
663 x86_push_reg (buf, X86_EDX);
664 x86_push_reg (buf, X86_EAX);
665 x86_push_reg (buf, X86_ECX);
669 /* save the IP (caller ip) */
670 x86_push_membase (buf, X86_ESP, 16);
672 x86_push_reg (buf, X86_EBX);
673 x86_push_reg (buf, X86_EDI);
674 x86_push_reg (buf, X86_ESI);
675 x86_push_reg (buf, X86_EBP);
677 /* save method info */
678 x86_push_membase (buf, X86_ESP, 32);
679 /* get the address of lmf for the current thread */
680 x86_call_code (buf, mono_get_lmf_addr);
682 x86_push_reg (buf, X86_EAX);
683 /* push *lfm (previous_lmf) */
684 x86_push_membase (buf, X86_EAX, 0);
686 x86_mov_membase_reg (buf, X86_EAX, 0, X86_ESP, 4);
689 /* push the method info */
690 x86_push_membase (buf, X86_ESP, 44);
691 /* push the return address onto the stack */
692 x86_push_membase (buf, X86_ESP, 52);
694 /* save all register values */
695 x86_push_reg (buf, X86_EBX);
696 x86_push_reg (buf, X86_EDI);
697 x86_push_reg (buf, X86_ESI);
698 x86_push_membase (buf, X86_ESP, 64); /* EDX */
699 x86_push_membase (buf, X86_ESP, 64); /* ECX */
700 x86_push_membase (buf, X86_ESP, 64); /* EAX */
702 x86_call_code (buf, x86_magic_trampoline);
703 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 8*4);
705 /* restore LMF start */
706 /* ebx = previous_lmf */
707 x86_pop_reg (buf, X86_EBX);
709 x86_pop_reg (buf, X86_EDI);
710 /* *(lmf) = previous_lmf */
711 x86_mov_membase_reg (buf, X86_EDI, 0, X86_EBX, 4);
712 /* discard method info */
713 x86_pop_reg (buf, X86_ESI);
714 /* restore caller saved regs */
715 x86_pop_reg (buf, X86_EBP);
716 x86_pop_reg (buf, X86_ESI);
717 x86_pop_reg (buf, X86_EDI);
718 x86_pop_reg (buf, X86_EBX);
719 /* discard save IP */
720 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 4);
721 /* restore LMF end */
723 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 16);
725 /* call the compiled method */
726 x86_jump_reg (buf, X86_EAX);
728 g_assert ((buf - mono_generic_trampoline_code) <= 256);
731 code = buf = g_malloc (16);
732 x86_push_imm (buf, method);
733 x86_jump_code (buf, mono_generic_trampoline_code);
734 g_assert ((buf - code) <= 16);
736 /* store trampoline address */
739 //mono_jit_stats.method_trampolines++;
747 * mono_arch_create_class_init_trampoline:
748 * @vtable: the type to initialize
750 * Creates a trampoline function to run a type initializer.
751 * If the trampoline is called, it calls mono_runtime_class_init with the
752 * given vtable, then patches the caller code so it does not get called any
755 * Returns: a pointer to the newly created code
758 mono_arch_create_class_init_trampoline (MonoVTable *vtable)
760 guint8 *code, *buf, *tramp;
762 tramp = create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
764 /* This is the method-specific part of the trampoline. Its purpose is
765 to provide the generic part with the MonoMethod *method pointer. We'll
766 use r11 to keep that value, for instance. However, the generic part of
767 the trampoline relies on r11 having the same value it had before coming
768 here, so we must save it before. */
769 code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
772 ppc_mflr (buf, ppc_r4);
773 ppc_stw (buf, ppc_r4, PPC_RET_ADDR_OFFSET, ppc_sp);
774 ppc_stwu (buf, ppc_sp, -32, ppc_sp);
775 ppc_load (buf, ppc_r3, vtable);
776 ppc_load (buf, ppc_r5, 0);
778 ppc_load (buf, ppc_r0, ppc_class_init_trampoline);
779 ppc_mtlr (buf, ppc_r0);
782 ppc_lwz (buf, ppc_r0, 32 + PPC_RET_ADDR_OFFSET, ppc_sp);
783 ppc_mtlr (buf, ppc_r0);
784 ppc_addic (buf, ppc_sp, ppc_sp, 32);
787 /* Save r11. There's nothing magic in the '44', its just an arbitrary
788 position - see above */
789 ppc_stw (buf, ppc_r11, -44, ppc_r1);
791 /* Now save LR - we'll overwrite it now */
792 ppc_mflr (buf, ppc_r11);
793 ppc_stw (buf, ppc_r11, 4, ppc_r1);
794 ppc_stw (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
796 /* Prepare the jump to the generic trampoline code.*/
797 ppc_lis (buf, ppc_r11, (guint32) tramp >> 16);
798 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) tramp & 0xffff);
799 ppc_mtlr (buf, ppc_r11);
801 /* And finally put 'vtable' in r11 and fly! */
802 ppc_lis (buf, ppc_r11, (guint32) vtable >> 16);
803 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) vtable & 0xffff);
805 ppc_lwz (buf, ppc_r0, PPC_RET_ADDR_OFFSET, ppc_r1);
806 ppc_mtlr (buf, ppc_r0);
811 /* Flush instruction cache, since we've generated code */
812 mono_arch_flush_icache (code, buf - code);
815 g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
817 mono_jit_stats.method_trampolines++;
823 * This method is only called when running in the Mono Debugger.
826 mono_debugger_create_notification_function (gpointer *notification_address)
830 ptr = buf = g_malloc0 (16);
832 if (notification_address)
833 *notification_address = buf;