2 * tramp-ppc.c: JIT trampoline code for PowerPC
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_r0, addr);
60 ppc_mtctr (code, ppc_r0);
61 ppc_addi (code, this_pos, this_pos, sizeof (MonoObject));
62 ppc_bcctr (code, 20, 0);
63 mono_arch_flush_icache (start, code - start);
64 g_assert ((code - start) <= 20);
65 /*g_print ("unbox trampoline at %d for %s:%s\n", this_pos, m->klass->name, m->name);
66 g_print ("unbox code is at %p for method at %p\n", start, addr);*/
71 /* Stack size for trampoline function
72 * PPC_MINIMAL_STACK_SIZE + 16 (args + alignment to ppc_magic_trampoline)
73 * 32 * 4 gregs + 13 * 8 fregs
77 /* Method-specific trampoline code fragment size */
78 #define METHOD_TRAMPOLINE_SIZE 64
80 /* Jump-specific trampoline code fragment size */
81 #define JUMP_TRAMPOLINE_SIZE 64
84 * ppc_magic_trampoline:
85 * @code: pointer into caller code
86 * @method: the method to translate
89 * This method is called by the function 'arch_create_jit_trampoline', which in
90 * turn is called by the trampoline functions for virtual methods.
91 * After having called the JIT compiler to compile the method, it inspects the
92 * caller code to find the address of the method-specific part of the
93 * trampoline vtable slot for this method, updates it with a fragment that calls
94 * the newly compiled code and returns this address of the compiled code to
95 * 'arch_create_jit_trampoline'
98 ppc_magic_trampoline (MonoMethod *method, guint32 *code, char *sp)
104 addr = mono_compile_method(method);
105 /*g_print ("method code at %p for %s:%s\n", addr, method->klass->name, method->name);*/
112 /* Locate the address of the method-specific trampoline. The call using
113 the vtable slot that took the processing flow to 'arch_create_jit_trampoline'
114 looks something like this:
116 mtlr rA ; Move rA (a register containing the
117 ; target address) to LR
118 blrl ; Call function at LR
120 PowerPC instructions are 32-bit long, which means that a 32-bit target
121 address cannot be encoded as an immediate value (because we already
122 have spent some bits to encode the branch instruction!). That's why a
123 'b'ranch to the contents of the 'l'ink 'r'egister (with 'l'ink register
124 update) is needed, instead of a simpler 'branch immediate'. This
125 complicates our purpose here, because 'blrl' overwrites LR, which holds
126 the value we're interested in.
128 Therefore, we need to locate the 'mtlr rA' instruction to know which
129 register LR was loaded from, and then retrieve the value from that
132 /* This is the 'blrl' instruction */
136 * Note that methods are called also with the bl opcode.
138 if (((*code) >> 26) == 18) {
139 /*g_print ("direct patching\n");*/
140 ppc_patch (code, addr);
141 mono_arch_flush_icache (code, 4);
145 /* Sanity check: instruction must be 'blrl' */
146 g_assert(*code == 0x4e800021);
148 /* OK, we're now at the 'blrl' instruction. Now walk backwards
149 till we get to a 'mtlr rA' */
151 if((*code & 0x7c0803a6) == 0x7c0803a6) {
153 /* Here we are: we reached the 'mtlr rA'.
154 Extract the register from the instruction */
155 reg = (*code & 0x03e00000) >> 21;
157 /* ok, this is a lwz reg, offset (vtreg)
158 * it is emitted with:
159 * ppc_emit32 (c, (32 << 26) | ((D) << 21) | ((a) << 16) | (guint16)(d))
161 soff = (*code & 0xffff);
163 reg = (*code >> 16) & 0x1f;
164 /*g_print ("patching reg is %d\n", reg);*/
166 case 0 : o = *((int *) (sp + STACK - 8)); break;
167 case 3 : o = *((int *) (sp + STACK - 12)); break;
168 case 4 : o = *((int *) (sp + STACK - 16)); break;
169 case 5 : o = *((int *) (sp + STACK - 20)); break;
170 case 6 : o = *((int *) (sp + STACK - 24)); break;
171 case 7 : o = *((int *) (sp + STACK - 28)); break;
172 case 8 : o = *((int *) (sp + STACK - 32)); break;
173 case 9 : o = *((int *) (sp + STACK - 36)); break;
174 case 10: o = *((int *) (sp + STACK - 40)); break;
175 case 11: o = *((int *) (sp + STACK - 44)); break;
176 case 12: o = *((int *) (sp + STACK - 48)); break;
177 case 13: o = *((int *) (sp + STACK - 52)); break;
178 case 14: o = *((int *) (sp + STACK - 56)); break;
179 case 15: o = *((int *) (sp + STACK - 60)); break;
180 case 16: o = *((int *) (sp + STACK - 64)); break;
181 case 17: o = *((int *) (sp + STACK - 68)); break;
182 case 18: o = *((int *) (sp + STACK - 72)); break;
183 case 19: o = *((int *) (sp + STACK - 76)); break;
184 case 20: o = *((int *) (sp + STACK - 80)); break;
185 case 21: o = *((int *) (sp + STACK - 84)); break;
186 case 22: o = *((int *) (sp + STACK - 88)); break;
187 case 23: o = *((int *) (sp + STACK - 92)); break;
188 case 24: o = *((int *) (sp + STACK - 96)); break;
189 case 25: o = *((int *) (sp + STACK - 100)); break;
190 case 26: o = *((int *) (sp + STACK - 104)); break;
191 case 27: o = *((int *) (sp + STACK - 108)); break;
192 case 28: o = *((int *) (sp + STACK - 112)); break;
193 case 29: o = *((int *) (sp + STACK - 116)); break;
194 case 30: o = *((int *) (sp + STACK - 120)); break;
195 case 31: o = *((int *) (sp + STACK - 4)); break;
197 printf("%s: Unexpected register %d\n",
199 g_assert_not_reached();
205 /* this is not done for non-virtual calls, because in that case
206 we won't have an object, but the actual pointer to the
207 valuetype as the this argument
209 if (method->klass->valuetype)
210 addr = get_unbox_trampoline (method, addr);
213 *((gpointer *)o) = addr;
215 /* Finally, replace the method-specific trampoline code (which called
216 the generic trampoline code) with a fragment that calls directly the
221 /* FIXME: make the patching thread safe */
223 ppc_patch (o - 4, addr);
224 /*g_print ("patching at %p to %p\n", o, addr);*/
226 ppc_stwu (o, ppc_r1, -16, ppc_r1);
227 ppc_mflr (o, ppc_r0);
228 ppc_stw (o, ppc_r31, 12, ppc_r1);
229 ppc_stw (o, ppc_r0, 20, ppc_r1);
230 ppc_mr (o, ppc_r31, ppc_r1);
232 ppc_lis (o, ppc_r0, (guint32) addr >> 16);
233 ppc_ori (o, ppc_r0, ppc_r0, (guint32) addr & 0xffff);
234 ppc_mtlr (o, ppc_r0);
237 ppc_lwz (o, ppc_r11, 0, ppc_r1);
238 ppc_lwz (o, ppc_r0, 4, ppc_r11);
239 ppc_mtlr (o, ppc_r0);
240 ppc_lwz (o, ppc_r31, -4, ppc_r11);
241 ppc_mr (o, ppc_r1, ppc_r11);
244 mono_arch_flush_icache (start, o - start);
245 g_assert(o - start < METHOD_TRAMPOLINE_SIZE);
251 ppc_class_init_trampoline (void *vtable, guint32 *code, char *sp)
253 mono_runtime_class_init (vtable);
256 /* This is the 'bl' instruction */
259 if (((*code) >> 26) == 18) {
260 ppc_ori (code, 0, 0, 0); /* nop */
261 mono_arch_flush_icache (code, 4);
264 g_assert_not_reached ();
270 create_trampoline_code (MonoTrampolineType tramp_type)
272 guint8 *buf, *code = NULL;
273 static guint8* generic_jump_trampoline = NULL;
274 static guint8 *generic_class_init_trampoline = NULL;
277 switch (tramp_type) {
278 case MONO_TRAMPOLINE_GENERIC:
279 if (mono_generic_trampoline_code)
280 return mono_generic_trampoline_code;
282 case MONO_TRAMPOLINE_JUMP:
283 if (generic_jump_trampoline)
284 return generic_jump_trampoline;
286 case MONO_TRAMPOLINE_CLASS_INIT:
287 if (generic_class_init_trampoline)
288 return generic_class_init_trampoline;
293 /* Now we'll create in 'buf' the PowerPC trampoline code. This
294 is the trampoline code common to all methods */
296 code = buf = g_malloc(512);
298 /*-----------------------------------------------------------
299 STEP 0: First create a non-standard function prologue with a
300 stack size big enough to save our registers:
302 lr (We'll be calling functions here, so we
304 r0 (See ppc_magic_trampoline)
305 r1 (sp) (Stack pointer - must save)
306 r3-r10 Function arguments.
307 r11-r31 (See ppc_magic_trampoline)
308 method in r11 (See ppc_magic_trampoline)
310 This prologue is non-standard because r0 is not saved here - it
311 was saved in the method-specific trampoline code
312 -----------------------------------------------------------*/
314 ppc_stwu (buf, ppc_r1, -STACK, ppc_r1);
316 /* Save r0 before modifying it - we will need its contents in
317 'ppc_magic_trampoline' */
318 ppc_stw (buf, ppc_r0, STACK - 8, ppc_r1);
320 ppc_stw (buf, ppc_r31, STACK - 4, ppc_r1);
321 ppc_mr (buf, ppc_r31, ppc_r1);
323 /* Now save our registers. */
324 ppc_stw (buf, ppc_r3, STACK - 12, ppc_r1);
325 ppc_stw (buf, ppc_r4, STACK - 16, ppc_r1);
326 ppc_stw (buf, ppc_r5, STACK - 20, ppc_r1);
327 ppc_stw (buf, ppc_r6, STACK - 24, ppc_r1);
328 ppc_stw (buf, ppc_r7, STACK - 28, ppc_r1);
329 ppc_stw (buf, ppc_r8, STACK - 32, ppc_r1);
330 ppc_stw (buf, ppc_r9, STACK - 36, ppc_r1);
331 ppc_stw (buf, ppc_r10, STACK - 40, ppc_r1);
332 /* STACK - 44 contains r11, which is set in the method-specific
333 part of the trampoline (see bellow this 'if' block) */
334 ppc_stw (buf, ppc_r12, STACK - 48, ppc_r1);
335 ppc_stw (buf, ppc_r13, STACK - 52, ppc_r1);
336 ppc_stw (buf, ppc_r14, STACK - 56, ppc_r1);
337 ppc_stw (buf, ppc_r15, STACK - 60, ppc_r1);
338 ppc_stw (buf, ppc_r16, STACK - 64, ppc_r1);
339 ppc_stw (buf, ppc_r17, STACK - 68, ppc_r1);
340 ppc_stw (buf, ppc_r18, STACK - 72, ppc_r1);
341 ppc_stw (buf, ppc_r19, STACK - 76, ppc_r1);
342 ppc_stw (buf, ppc_r20, STACK - 80, ppc_r1);
343 ppc_stw (buf, ppc_r21, STACK - 84, ppc_r1);
344 ppc_stw (buf, ppc_r22, STACK - 88, ppc_r1);
345 ppc_stw (buf, ppc_r23, STACK - 92, ppc_r1);
346 ppc_stw (buf, ppc_r24, STACK - 96, ppc_r1);
347 ppc_stw (buf, ppc_r25, STACK - 100, ppc_r1);
348 ppc_stw (buf, ppc_r26, STACK - 104, ppc_r1);
349 ppc_stw (buf, ppc_r27, STACK - 108, ppc_r1);
350 ppc_stw (buf, ppc_r28, STACK - 112, ppc_r1);
351 ppc_stw (buf, ppc_r29, STACK - 116, ppc_r1);
352 ppc_stw (buf, ppc_r30, STACK - 120, ppc_r1);
353 /* Save 'method' pseudo-parameter - the one passed in r11 */
354 ppc_stw (buf, ppc_r11, STACK - 124, ppc_r1);
356 /* Save the FP registers */
357 offset = 124 + 4 + 8;
358 for (i = ppc_f1; i <= PPC_LAST_FPARG_REG; ++i) {
359 ppc_stfd (buf, i, STACK - offset, ppc_r1);
363 /*----------------------------------------------------------
364 STEP 1: call 'mono_get_lmf_addr()' to get the address of our
365 LMF. We'll need to restore it after the call to
366 'ppc_magic_trampoline' and before the call to the native
368 ----------------------------------------------------------*/
370 /* Calculate the address and make the call. Keep in mind that
371 we're using r0, so we'll have to restore it before calling
372 'ppc_magic_trampoline' */
373 ppc_lis (buf, ppc_r0, (guint32) mono_get_lmf_addr >> 16);
374 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) mono_get_lmf_addr & 0xffff);
375 ppc_mtlr (buf, ppc_r0);
378 /* XXX Update LMF !!! */
380 /*----------------------------------------------------------
381 STEP 2: call 'ppc_magic_trampoline()', who will compile the
382 code and fix the method vtable entry for us
383 ----------------------------------------------------------*/
387 /* Arg 1: MonoMethod *method. It was put in r11 by the
388 method-specific trampoline code, and then saved before the call
389 to mono_get_lmf_addr()'. Restore r11, by the way :-) */
390 ppc_lwz (buf, ppc_r3, STACK - 124, ppc_r1);
391 ppc_lwz (buf, ppc_r11, STACK - 44, ppc_r1);
393 /* Arg 2: code (next address to the instruction that called us) */
394 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
395 ppc_li (buf, ppc_r4, 0);
397 ppc_lwz (buf, ppc_r4, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
400 /* Arg 3: stack pointer */
401 ppc_mr (buf, ppc_r5, ppc_r1);
403 /* Calculate call address, restore r0 and call
404 'ppc_magic_trampoline'. Return value will be in r3 */
405 if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
406 ppc_lis (buf, ppc_r0, (guint32) ppc_class_init_trampoline >> 16);
407 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_class_init_trampoline & 0xffff);
409 ppc_lis (buf, ppc_r0, (guint32) ppc_magic_trampoline >> 16);
410 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_magic_trampoline & 0xffff);
412 ppc_mtlr (buf, ppc_r0);
413 ppc_lwz (buf, ppc_r0, STACK - 8, ppc_r1);
416 /* OK, code address is now on r3. Move it to r0, so that we
417 can restore r3 and use it from r0 later */
418 ppc_mr (buf, ppc_r0, ppc_r3);
421 /*----------------------------------------------------------
422 STEP 3: Restore the LMF
423 ----------------------------------------------------------*/
427 /*----------------------------------------------------------
428 STEP 4: call the compiled method
429 ----------------------------------------------------------*/
431 /* Restore registers */
433 ppc_lwz (buf, ppc_r3, STACK - 12, ppc_r1);
434 ppc_lwz (buf, ppc_r4, STACK - 16, ppc_r1);
435 ppc_lwz (buf, ppc_r5, STACK - 20, ppc_r1);
436 ppc_lwz (buf, ppc_r6, STACK - 24, ppc_r1);
437 ppc_lwz (buf, ppc_r7, STACK - 28, ppc_r1);
438 ppc_lwz (buf, ppc_r8, STACK - 32, ppc_r1);
439 ppc_lwz (buf, ppc_r9, STACK - 36, ppc_r1);
440 ppc_lwz (buf, ppc_r10, STACK - 40, ppc_r1);
441 ppc_lwz (buf, ppc_r11, STACK - 44, ppc_r1);
442 ppc_lwz (buf, ppc_r12, STACK - 48, ppc_r1);
443 ppc_stw (buf, ppc_r13, STACK - 52, ppc_r1);
445 /* Restore the FP registers */
446 offset = 124 + 4 + 8;
447 for (i = ppc_f1; i <= PPC_LAST_FPARG_REG; ++i) {
448 ppc_lfd (buf, i, STACK - offset, ppc_r1);
451 /* We haven't touched any of these, so there's no need to
454 ppc_lwz (buf, ppc_r14, STACK - 56, ppc_r1);
455 ppc_lwz (buf, ppc_r15, STACK - 60, ppc_r1);
456 ppc_lwz (buf, ppc_r16, STACK - 64, ppc_r1);
457 ppc_lwz (buf, ppc_r17, STACK - 68, ppc_r1);
458 ppc_lwz (buf, ppc_r18, STACK - 72, ppc_r1);
459 ppc_lwz (buf, ppc_r19, STACK - 76, ppc_r1);
460 ppc_lwz (buf, ppc_r20, STACK - 80, ppc_r1);
461 ppc_lwz (buf, ppc_r21, STACK - 84, ppc_r1);
462 ppc_lwz (buf, ppc_r22, STACK - 88, ppc_r1);
463 ppc_lwz (buf, ppc_r23, STACK - 92, ppc_r1);
464 ppc_lwz (buf, ppc_r24, STACK - 96, ppc_r1);
465 ppc_lwz (buf, ppc_r25, STACK - 100, ppc_r1);
466 ppc_lwz (buf, ppc_r26, STACK - 104, ppc_r1);
467 ppc_lwz (buf, ppc_r27, STACK - 108, ppc_r1);
468 ppc_lwz (buf, ppc_r28, STACK - 112, ppc_r1);
469 ppc_lwz (buf, ppc_r29, STACK - 116, ppc_r1);
470 ppc_lwz (buf, ppc_r30, STACK - 120, ppc_r1);
471 ppc_lwz (buf, ppc_r31, STACK - 4, ppc_r1);
474 /* Non-standard function epilogue. Instead of doing a proper
475 return, we just call the compiled code, so
476 that, when it finishes, the method returns here. */
479 /* Restore stack pointer, r31, LR and jump to the code */
480 ppc_lwz (buf, ppc_r1, 0, ppc_r1);
481 //ppc_lwz (buf, ppc_r31, -4, ppc_r1);
482 ppc_lwz (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
483 ppc_mtlr (buf, ppc_r11);
484 ppc_mtctr (buf, ppc_r0);
485 ppc_bcctr (buf, 20, 0);
487 ppc_mtlr (buf, ppc_r0);
490 /* Restore stack pointer, r31, LR and return to caller */
491 ppc_lwz (buf, ppc_r11, 0, ppc_r1);
492 ppc_lwz (buf, ppc_r31, -4, ppc_r11);
493 ppc_mr (buf, ppc_r1, ppc_r11);
494 ppc_lwz (buf, ppc_r0, 4, ppc_r1);
495 ppc_mtlr (buf, ppc_r0);
499 /* Flush instruction cache, since we've generated code */
500 mono_arch_flush_icache (code, buf - code);
503 g_assert ((buf - code) <= 512);
506 switch (tramp_type) {
507 case MONO_TRAMPOLINE_GENERIC:
508 mono_generic_trampoline_code = code;
510 case MONO_TRAMPOLINE_JUMP:
511 generic_jump_trampoline = code;
513 case MONO_TRAMPOLINE_CLASS_INIT:
514 generic_class_init_trampoline = code;
522 mono_arch_create_jump_trampoline (MonoMethod *method)
524 guint8 *code, *buf, *tramp = NULL;
526 MonoDomain* domain = mono_domain_get ();
528 tramp = create_trampoline_code (MONO_TRAMPOLINE_JUMP);
530 mono_domain_lock (domain);
531 code = buf = mono_code_manager_reserve (domain->code_mp, METHOD_TRAMPOLINE_SIZE);
532 mono_domain_unlock (domain);
534 /* Save r11. There's nothing magic in the '44', its just an arbitrary
535 position - see above */
536 ppc_stw (buf, ppc_r11, -44, ppc_r1);
538 /* Now save LR - we'll overwrite it now */
539 ppc_mflr (buf, ppc_r11);
540 ppc_stw (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
542 /* Prepare the jump to the generic trampoline code.*/
543 ppc_lis (buf, ppc_r11, (guint32) tramp >> 16);
544 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) tramp & 0xffff);
545 ppc_mtlr (buf, ppc_r11);
547 /* And finally put 'method' in r11 and fly! */
548 ppc_lis (buf, ppc_r11, (guint32) method >> 16);
549 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) method & 0xffff);
552 /* Flush instruction cache, since we've generated code */
553 mono_arch_flush_icache (code, buf - code);
555 g_assert ((buf - code) <= JUMP_TRAMPOLINE_SIZE);
557 ji = g_new0 (MonoJitInfo, 1);
559 ji->code_start = code;
560 ji->code_size = buf - code;
562 mono_jit_stats.method_trampolines++;
568 * arch_create_jit_trampoline:
569 * @method: pointer to the method info
571 * Creates a trampoline function for virtual methods. If the created
572 * code is called it first starts JIT compilation of method,
573 * and then calls the newly created method. It also replaces the
574 * corresponding vtable entry (see ppc_magic_trampoline).
576 * A trampoline consists of two parts: a main fragment, shared by all method
577 * trampolines, and some code specific to each method, which hard-codes a
578 * reference to that method and then calls the main fragment.
580 * The main fragment contains a call to 'ppc_magic_trampoline', which performs
581 * call to the JIT compiler and substitutes the method-specific fragment with
582 * some code that directly calls the JIT-compiled method.
584 * Returns: a pointer to the newly created code
587 mono_arch_create_jit_trampoline (MonoMethod *method)
590 static guint8 *vc = NULL;
591 MonoDomain* domain = mono_domain_get ();
593 /* previously created trampoline code */
597 if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
598 return mono_arch_create_jit_trampoline (mono_marshal_get_synchronized_wrapper (method));
600 vc = create_trampoline_code (MONO_TRAMPOLINE_GENERIC);
602 /* This is the method-specific part of the trampoline. Its purpose is
603 to provide the generic part with the MonoMethod *method pointer. We'll
604 use r11 to keep that value, for instance. However, the generic part of
605 the trampoline relies on r11 having the same value it had before coming
606 here, so we must save it before. */
607 //code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
608 // FIXME: should pass the domain down tot his function
609 mono_domain_lock (domain);
610 code = buf = mono_code_manager_reserve (domain->code_mp, METHOD_TRAMPOLINE_SIZE);
611 mono_domain_unlock (domain);
613 /* Save r11. There's nothing magic in the '44', its just an arbitrary
614 position - see above */
615 ppc_stw (buf, ppc_r11, -44, ppc_r1);
617 /* Now save LR - we'll overwrite it now */
618 ppc_mflr (buf, ppc_r11);
619 ppc_stw (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
621 /* Prepare the jump to the generic trampoline code.*/
622 ppc_lis (buf, ppc_r11, (guint32) vc >> 16);
623 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) vc & 0xffff);
624 ppc_mtlr (buf, ppc_r11);
626 /* And finally put 'method' in r11 and fly! */
627 ppc_lis (buf, ppc_r11, (guint32) method >> 16);
628 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) method & 0xffff);
631 /* Flush instruction cache, since we've generated code */
632 mono_arch_flush_icache (code, buf - code);
635 g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
637 /* Store trampoline address */
640 mono_jit_stats.method_trampolines++;
648 * x86_magic_trampoline:
649 * @eax: saved x86 register
650 * @ecx: saved x86 register
651 * @edx: saved x86 register
652 * @esi: saved x86 register
653 * @edi: saved x86 register
654 * @ebx: saved x86 register
655 * @code: pointer into caller code
656 * @method: the method to translate
658 * This method is called by the trampoline functions for virtual
659 * methods. It inspects the caller code to find the address of the
660 * vtable slot, then calls the JIT compiler and writes the address
661 * of the compiled method back to the vtable. All virtual methods
662 * are called with: x86_call_membase (inst, basereg, disp). We always
663 * use 32 bit displacement to ensure that the length of the call
664 * instruction is 6 bytes. We need to get the value of the basereg
665 * and the constant displacement.
668 x86_magic_trampoline (int eax, int ecx, int edx, int esi, int edi,
669 int ebx, guint8 *code, MonoMethod *m)
676 addr = mono_compile_method (m);
679 /* go to the start of the call instruction
681 * address_byte = (m << 6) | (o << 3) | reg
682 * call opcode: 0xff address_byte displacement
687 if ((code [1] != 0xe8) && (code [3] == 0xff) && ((code [4] & 0x18) == 0x10) && ((code [4] >> 6) == 1)) {
688 reg = code [4] & 0x07;
689 disp = (signed char)code [5];
691 if ((code [0] == 0xff) && ((code [1] & 0x18) == 0x10) && ((code [1] >> 6) == 2)) {
692 reg = code [1] & 0x07;
693 disp = *((gint32*)(code + 2));
694 } else if ((code [1] == 0xe8)) {
695 *((guint32*)(code + 2)) = (guint)addr - ((guint)code + 1) - 5;
697 } else if ((code [4] == 0xff) && (((code [5] >> 6) & 0x3) == 0) && (((code [5] >> 3) & 0x7) == 2)) {
699 * This is a interface call: should check the above code can't catch it earlier
700 * 8b 40 30 mov 0x30(%eax),%eax
704 reg = code [5] & 0x07;
706 printf ("Invalid trampoline sequence: %x %x %x %x %x %x %x\n", code [0], code [1], code [2], code [3],
707 code [4], code [5], code [6]);
708 g_assert_not_reached ();
732 g_assert_not_reached ();
737 if (m->klass->valuetype) {
738 return *((gpointer *)o) = get_unbox_trampoline (m, addr);
740 return *((gpointer *)o) = addr;
745 * mono_arch_create_jit_trampoline:
746 * @method: pointer to the method info
748 * Creates a trampoline function for virtual methods. If the created
749 * code is called it first starts JIT compilation of method,
750 * and then calls the newly created method. I also replaces the
751 * corresponding vtable entry (see x86_magic_trampoline).
753 * Returns: a pointer to the newly created code
756 mono_arch_create_jit_trampoline (MonoMethod *method)
760 /* previously created trampoline code */
764 if (!mono_generic_trampoline_code) {
765 mono_generic_trampoline_code = buf = g_malloc (256);
766 /* save caller save regs because we need to do a call */
767 x86_push_reg (buf, X86_EDX);
768 x86_push_reg (buf, X86_EAX);
769 x86_push_reg (buf, X86_ECX);
773 /* save the IP (caller ip) */
774 x86_push_membase (buf, X86_ESP, 16);
776 x86_push_reg (buf, X86_EBX);
777 x86_push_reg (buf, X86_EDI);
778 x86_push_reg (buf, X86_ESI);
779 x86_push_reg (buf, X86_EBP);
781 /* save method info */
782 x86_push_membase (buf, X86_ESP, 32);
783 /* get the address of lmf for the current thread */
784 x86_call_code (buf, mono_get_lmf_addr);
786 x86_push_reg (buf, X86_EAX);
787 /* push *lfm (previous_lmf) */
788 x86_push_membase (buf, X86_EAX, 0);
790 x86_mov_membase_reg (buf, X86_EAX, 0, X86_ESP, 4);
793 /* push the method info */
794 x86_push_membase (buf, X86_ESP, 44);
795 /* push the return address onto the stack */
796 x86_push_membase (buf, X86_ESP, 52);
798 /* save all register values */
799 x86_push_reg (buf, X86_EBX);
800 x86_push_reg (buf, X86_EDI);
801 x86_push_reg (buf, X86_ESI);
802 x86_push_membase (buf, X86_ESP, 64); /* EDX */
803 x86_push_membase (buf, X86_ESP, 64); /* ECX */
804 x86_push_membase (buf, X86_ESP, 64); /* EAX */
806 x86_call_code (buf, x86_magic_trampoline);
807 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 8*4);
809 /* restore LMF start */
810 /* ebx = previous_lmf */
811 x86_pop_reg (buf, X86_EBX);
813 x86_pop_reg (buf, X86_EDI);
814 /* *(lmf) = previous_lmf */
815 x86_mov_membase_reg (buf, X86_EDI, 0, X86_EBX, 4);
816 /* discard method info */
817 x86_pop_reg (buf, X86_ESI);
818 /* restore caller saved regs */
819 x86_pop_reg (buf, X86_EBP);
820 x86_pop_reg (buf, X86_ESI);
821 x86_pop_reg (buf, X86_EDI);
822 x86_pop_reg (buf, X86_EBX);
823 /* discard save IP */
824 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 4);
825 /* restore LMF end */
827 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 16);
829 /* call the compiled method */
830 x86_jump_reg (buf, X86_EAX);
832 g_assert ((buf - mono_generic_trampoline_code) <= 256);
835 code = buf = g_malloc (16);
836 x86_push_imm (buf, method);
837 x86_jump_code (buf, mono_generic_trampoline_code);
838 g_assert ((buf - code) <= 16);
840 /* store trampoline address */
843 //mono_jit_stats.method_trampolines++;
851 * mono_arch_create_class_init_trampoline:
852 * @vtable: the type to initialize
854 * Creates a trampoline function to run a type initializer.
855 * If the trampoline is called, it calls mono_runtime_class_init with the
856 * given vtable, then patches the caller code so it does not get called any
859 * Returns: a pointer to the newly created code
862 mono_arch_create_class_init_trampoline (MonoVTable *vtable)
864 guint8 *code, *buf, *tramp;
866 tramp = create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
868 /* This is the method-specific part of the trampoline. Its purpose is
869 to provide the generic part with the MonoMethod *method pointer. We'll
870 use r11 to keep that value, for instance. However, the generic part of
871 the trampoline relies on r11 having the same value it had before coming
872 here, so we must save it before. */
873 //code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
874 mono_domain_lock (vtable->domain);
875 code = buf = mono_code_manager_reserve (vtable->domain->code_mp, METHOD_TRAMPOLINE_SIZE);
876 mono_domain_unlock (vtable->domain);
879 ppc_mflr (buf, ppc_r4);
880 ppc_stw (buf, ppc_r4, PPC_RET_ADDR_OFFSET, ppc_sp);
881 ppc_stwu (buf, ppc_sp, -32, ppc_sp);
882 ppc_load (buf, ppc_r3, vtable);
883 ppc_load (buf, ppc_r5, 0);
885 ppc_load (buf, ppc_r0, ppc_class_init_trampoline);
886 ppc_mtlr (buf, ppc_r0);
889 ppc_lwz (buf, ppc_r0, 32 + PPC_RET_ADDR_OFFSET, ppc_sp);
890 ppc_mtlr (buf, ppc_r0);
891 ppc_addic (buf, ppc_sp, ppc_sp, 32);
894 /* Save r11. There's nothing magic in the '44', its just an arbitrary
895 position - see above */
896 ppc_stw (buf, ppc_r11, -44, ppc_r1);
898 /* Now save LR - we'll overwrite it now */
899 ppc_mflr (buf, ppc_r11);
900 ppc_stw (buf, ppc_r11, 4, ppc_r1);
901 ppc_stw (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
903 /* Prepare the jump to the generic trampoline code.*/
904 ppc_lis (buf, ppc_r11, (guint32) tramp >> 16);
905 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) tramp & 0xffff);
906 ppc_mtlr (buf, ppc_r11);
908 /* And finally put 'vtable' in r11 and fly! */
909 ppc_lis (buf, ppc_r11, (guint32) vtable >> 16);
910 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) vtable & 0xffff);
912 ppc_lwz (buf, ppc_r0, PPC_RET_ADDR_OFFSET, ppc_r1);
913 ppc_mtlr (buf, ppc_r0);
918 /* Flush instruction cache, since we've generated code */
919 mono_arch_flush_icache (code, buf - code);
922 g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
924 mono_jit_stats.method_trampolines++;
930 * This method is only called when running in the Mono Debugger.
933 mono_debugger_create_notification_function (gpointer *notification_address)
937 ptr = buf = g_malloc0 (16);
939 if (notification_address)
940 *notification_address = buf;