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 #define STACK (144 + 8*8)
74 /* Method-specific trampoline code fragment size */
75 #define METHOD_TRAMPOLINE_SIZE 64
77 /* Jump-specific trampoline code fragment size */
78 #define JUMP_TRAMPOLINE_SIZE 64
81 * ppc_magic_trampoline:
82 * @code: pointer into caller code
83 * @method: the method to translate
86 * This method is called by the function 'arch_create_jit_trampoline', which in
87 * turn is called by the trampoline functions for virtual methods.
88 * After having called the JIT compiler to compile the method, it inspects the
89 * caller code to find the address of the method-specific part of the
90 * trampoline vtable slot for this method, updates it with a fragment that calls
91 * the newly compiled code and returns this address of the compiled code to
92 * 'arch_create_jit_trampoline'
95 ppc_magic_trampoline (MonoMethod *method, guint32 *code, char *sp)
101 addr = mono_compile_method(method);
102 /*g_print ("method code at %p for %s:%s\n", addr, method->klass->name, method->name);*/
109 /* Locate the address of the method-specific trampoline. The call using
110 the vtable slot that took the processing flow to 'arch_create_jit_trampoline'
111 looks something like this:
113 mtlr rA ; Move rA (a register containing the
114 ; target address) to LR
115 blrl ; Call function at LR
117 PowerPC instructions are 32-bit long, which means that a 32-bit target
118 address cannot be encoded as an immediate value (because we already
119 have spent some bits to encode the branch instruction!). That's why a
120 'b'ranch to the contents of the 'l'ink 'r'egister (with 'l'ink register
121 update) is needed, instead of a simpler 'branch immediate'. This
122 complicates our purpose here, because 'blrl' overwrites LR, which holds
123 the value we're interested in.
125 Therefore, we need to locate the 'mtlr rA' instruction to know which
126 register LR was loaded from, and then retrieve the value from that
129 /* This is the 'blrl' instruction */
133 * Note that methods are called also with the bl opcode.
135 if (((*code) >> 26) == 18) {
136 /*g_print ("direct patching\n");*/
137 ppc_patch (code, addr);
138 mono_arch_flush_icache (code, 4);
142 /* Sanity check: instruction must be 'blrl' */
143 g_assert(*code == 0x4e800021);
145 /* OK, we're now at the 'blrl' instruction. Now walk backwards
146 till we get to a 'mtlr rA' */
148 if((*code & 0x7c0803a6) == 0x7c0803a6) {
150 /* Here we are: we reached the 'mtlr rA'.
151 Extract the register from the instruction */
152 reg = (*code & 0x03e00000) >> 21;
154 /* ok, this is a lwz reg, offset (vtreg)
155 * it is emitted with:
156 * ppc_emit32 (c, (32 << 26) | ((D) << 21) | ((a) << 16) | (guint16)(d))
158 soff = (*code & 0xffff);
160 reg = (*code >> 16) & 0x1f;
161 /*g_print ("patching reg is %d\n", reg);*/
163 case 0 : o = *((int *) (sp + STACK - 8)); break;
164 case 3 : o = *((int *) (sp + STACK - 12)); break;
165 case 4 : o = *((int *) (sp + STACK - 16)); break;
166 case 5 : o = *((int *) (sp + STACK - 20)); break;
167 case 6 : o = *((int *) (sp + STACK - 24)); break;
168 case 7 : o = *((int *) (sp + STACK - 28)); break;
169 case 8 : o = *((int *) (sp + STACK - 32)); break;
170 case 9 : o = *((int *) (sp + STACK - 36)); break;
171 case 10: o = *((int *) (sp + STACK - 40)); break;
172 case 11: o = *((int *) (sp + STACK - 44)); break;
173 case 12: o = *((int *) (sp + STACK - 48)); break;
174 case 13: o = *((int *) (sp + STACK - 52)); break;
175 case 14: o = *((int *) (sp + STACK - 56)); break;
176 case 15: o = *((int *) (sp + STACK - 60)); break;
177 case 16: o = *((int *) (sp + STACK - 64)); break;
178 case 17: o = *((int *) (sp + STACK - 68)); break;
179 case 18: o = *((int *) (sp + STACK - 72)); break;
180 case 19: o = *((int *) (sp + STACK - 76)); break;
181 case 20: o = *((int *) (sp + STACK - 80)); break;
182 case 21: o = *((int *) (sp + STACK - 84)); break;
183 case 22: o = *((int *) (sp + STACK - 88)); break;
184 case 23: o = *((int *) (sp + STACK - 92)); break;
185 case 24: o = *((int *) (sp + STACK - 96)); break;
186 case 25: o = *((int *) (sp + STACK - 100)); break;
187 case 26: o = *((int *) (sp + STACK - 104)); break;
188 case 27: o = *((int *) (sp + STACK - 108)); break;
189 case 28: o = *((int *) (sp + STACK - 112)); break;
190 case 29: o = *((int *) (sp + STACK - 116)); break;
191 case 30: o = *((int *) (sp + STACK - 120)); break;
192 case 31: o = *((int *) (sp + STACK - 4)); break;
194 printf("%s: Unexpected register %d\n",
196 g_assert_not_reached();
202 /* this is not done for non-virtual calls, because in that case
203 we won't have an object, but the actual pointer to the
204 valuetype as the this argument
206 if (method->klass->valuetype)
207 addr = get_unbox_trampoline (method, addr);
210 *((gpointer *)o) = addr;
212 /* Finally, replace the method-specific trampoline code (which called
213 the generic trampoline code) with a fragment that calls directly the
218 /* FIXME: make the patching thread safe */
220 ppc_patch (o - 4, addr);
221 /*g_print ("patching at %p to %p\n", o, addr);*/
223 ppc_stwu (o, ppc_r1, -16, ppc_r1);
224 ppc_mflr (o, ppc_r0);
225 ppc_stw (o, ppc_r31, 12, ppc_r1);
226 ppc_stw (o, ppc_r0, 20, ppc_r1);
227 ppc_mr (o, ppc_r31, ppc_r1);
229 ppc_lis (o, ppc_r0, (guint32) addr >> 16);
230 ppc_ori (o, ppc_r0, ppc_r0, (guint32) addr & 0xffff);
231 ppc_mtlr (o, ppc_r0);
234 ppc_lwz (o, ppc_r11, 0, ppc_r1);
235 ppc_lwz (o, ppc_r0, 4, ppc_r11);
236 ppc_mtlr (o, ppc_r0);
237 ppc_lwz (o, ppc_r31, -4, ppc_r11);
238 ppc_mr (o, ppc_r1, ppc_r11);
241 mono_arch_flush_icache (start, o - start);
242 g_assert(o - start < METHOD_TRAMPOLINE_SIZE);
248 ppc_class_init_trampoline (void *vtable, guint32 *code, char *sp)
250 mono_runtime_class_init (vtable);
253 /* This is the 'bl' instruction */
256 if (((*code) >> 26) == 18) {
257 ppc_ori (code, 0, 0, 0); /* nop */
258 mono_arch_flush_icache (code, 4);
261 g_assert_not_reached ();
267 create_trampoline_code (MonoTrampolineType tramp_type)
269 guint8 *buf, *code = NULL;
270 static guint8* generic_jump_trampoline = NULL;
271 static guint8 *generic_class_init_trampoline = NULL;
274 switch (tramp_type) {
275 case MONO_TRAMPOLINE_GENERIC:
276 if (mono_generic_trampoline_code)
277 return mono_generic_trampoline_code;
279 case MONO_TRAMPOLINE_JUMP:
280 if (generic_jump_trampoline)
281 return generic_jump_trampoline;
283 case MONO_TRAMPOLINE_CLASS_INIT:
284 if (generic_class_init_trampoline)
285 return generic_class_init_trampoline;
290 /* Now we'll create in 'buf' the PowerPC trampoline code. This
291 is the trampoline code common to all methods */
293 code = buf = g_malloc(512);
295 /*-----------------------------------------------------------
296 STEP 0: First create a non-standard function prologue with a
297 stack size big enough to save our registers:
299 lr (We'll be calling functions here, so we
301 r0 (See ppc_magic_trampoline)
302 r1 (sp) (Stack pointer - must save)
303 r3-r10 Function arguments.
304 r11-r31 (See ppc_magic_trampoline)
305 method in r11 (See ppc_magic_trampoline)
307 This prologue is non-standard because r0 is not saved here - it
308 was saved in the method-specific trampoline code
309 -----------------------------------------------------------*/
311 ppc_stwu (buf, ppc_r1, -STACK, ppc_r1);
313 /* Save r0 before modifying it - we will need its contents in
314 'ppc_magic_trampoline' */
315 ppc_stw (buf, ppc_r0, STACK - 8, ppc_r1);
317 ppc_stw (buf, ppc_r31, STACK - 4, ppc_r1);
318 ppc_mr (buf, ppc_r31, ppc_r1);
320 /* Now save our registers. */
321 ppc_stw (buf, ppc_r3, STACK - 12, ppc_r1);
322 ppc_stw (buf, ppc_r4, STACK - 16, ppc_r1);
323 ppc_stw (buf, ppc_r5, STACK - 20, ppc_r1);
324 ppc_stw (buf, ppc_r6, STACK - 24, ppc_r1);
325 ppc_stw (buf, ppc_r7, STACK - 28, ppc_r1);
326 ppc_stw (buf, ppc_r8, STACK - 32, ppc_r1);
327 ppc_stw (buf, ppc_r9, STACK - 36, ppc_r1);
328 ppc_stw (buf, ppc_r10, STACK - 40, ppc_r1);
329 /* STACK - 44 contains r11, which is set in the method-specific
330 part of the trampoline (see bellow this 'if' block) */
331 ppc_stw (buf, ppc_r12, STACK - 48, ppc_r1);
332 ppc_stw (buf, ppc_r13, STACK - 52, ppc_r1);
333 ppc_stw (buf, ppc_r14, STACK - 56, ppc_r1);
334 ppc_stw (buf, ppc_r15, STACK - 60, ppc_r1);
335 ppc_stw (buf, ppc_r16, STACK - 64, ppc_r1);
336 ppc_stw (buf, ppc_r17, STACK - 68, ppc_r1);
337 ppc_stw (buf, ppc_r18, STACK - 72, ppc_r1);
338 ppc_stw (buf, ppc_r19, STACK - 76, ppc_r1);
339 ppc_stw (buf, ppc_r20, STACK - 80, ppc_r1);
340 ppc_stw (buf, ppc_r21, STACK - 84, ppc_r1);
341 ppc_stw (buf, ppc_r22, STACK - 88, ppc_r1);
342 ppc_stw (buf, ppc_r23, STACK - 92, ppc_r1);
343 ppc_stw (buf, ppc_r24, STACK - 96, ppc_r1);
344 ppc_stw (buf, ppc_r25, STACK - 100, ppc_r1);
345 ppc_stw (buf, ppc_r26, STACK - 104, ppc_r1);
346 ppc_stw (buf, ppc_r27, STACK - 108, ppc_r1);
347 ppc_stw (buf, ppc_r28, STACK - 112, ppc_r1);
348 ppc_stw (buf, ppc_r29, STACK - 116, ppc_r1);
349 ppc_stw (buf, ppc_r30, STACK - 120, ppc_r1);
350 /* Save 'method' pseudo-parameter - the one passed in r11 */
351 ppc_stw (buf, ppc_r11, STACK - 124, ppc_r1);
353 /* Save the FP registers */
354 offset = 124 + 4 + 8;
355 for (i = ppc_f1; i <= ppc_f8; ++i) {
356 ppc_stfd (buf, i, STACK - offset, ppc_r1);
360 /*----------------------------------------------------------
361 STEP 1: call 'mono_get_lmf_addr()' to get the address of our
362 LMF. We'll need to restore it after the call to
363 'ppc_magic_trampoline' and before the call to the native
365 ----------------------------------------------------------*/
367 /* Calculate the address and make the call. Keep in mind that
368 we're using r0, so we'll have to restore it before calling
369 'ppc_magic_trampoline' */
370 ppc_lis (buf, ppc_r0, (guint32) mono_get_lmf_addr >> 16);
371 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) mono_get_lmf_addr & 0xffff);
372 ppc_mtlr (buf, ppc_r0);
375 /* XXX Update LMF !!! */
377 /*----------------------------------------------------------
378 STEP 2: call 'ppc_magic_trampoline()', who will compile the
379 code and fix the method vtable entry for us
380 ----------------------------------------------------------*/
384 /* Arg 1: MonoMethod *method. It was put in r11 by the
385 method-specific trampoline code, and then saved before the call
386 to mono_get_lmf_addr()'. Restore r11, by the way :-) */
387 ppc_lwz (buf, ppc_r3, STACK - 124, ppc_r1);
388 ppc_lwz (buf, ppc_r11, STACK - 44, ppc_r1);
390 /* Arg 2: code (next address to the instruction that called us) */
391 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
392 ppc_li (buf, ppc_r4, 0);
394 ppc_lwz (buf, ppc_r4, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
397 /* Arg 3: stack pointer */
398 ppc_mr (buf, ppc_r5, ppc_r1);
400 /* Calculate call address, restore r0 and call
401 'ppc_magic_trampoline'. Return value will be in r3 */
402 if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
403 ppc_lis (buf, ppc_r0, (guint32) ppc_class_init_trampoline >> 16);
404 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_class_init_trampoline & 0xffff);
406 ppc_lis (buf, ppc_r0, (guint32) ppc_magic_trampoline >> 16);
407 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_magic_trampoline & 0xffff);
409 ppc_mtlr (buf, ppc_r0);
410 ppc_lwz (buf, ppc_r0, STACK - 8, ppc_r1);
413 /* OK, code address is now on r3. Move it to r0, so that we
414 can restore r3 and use it from r0 later */
415 ppc_mr (buf, ppc_r0, ppc_r3);
418 /*----------------------------------------------------------
419 STEP 3: Restore the LMF
420 ----------------------------------------------------------*/
424 /*----------------------------------------------------------
425 STEP 4: call the compiled method
426 ----------------------------------------------------------*/
428 /* Restore registers */
430 ppc_lwz (buf, ppc_r3, STACK - 12, ppc_r1);
431 ppc_lwz (buf, ppc_r4, STACK - 16, ppc_r1);
432 ppc_lwz (buf, ppc_r5, STACK - 20, ppc_r1);
433 ppc_lwz (buf, ppc_r6, STACK - 24, ppc_r1);
434 ppc_lwz (buf, ppc_r7, STACK - 28, ppc_r1);
435 ppc_lwz (buf, ppc_r8, STACK - 32, ppc_r1);
436 ppc_lwz (buf, ppc_r9, STACK - 36, ppc_r1);
437 ppc_lwz (buf, ppc_r10, STACK - 40, ppc_r1);
439 /* Restore the FP registers */
440 offset = 124 + 4 + 8;
441 for (i = ppc_f1; i <= ppc_f8; ++i) {
442 ppc_lfd (buf, i, STACK - offset, ppc_r1);
445 /* We haven't touched any of these, so there's no need to
448 ppc_lwz (buf, ppc_r14, STACK - 56, ppc_r1);
449 ppc_lwz (buf, ppc_r15, STACK - 60, ppc_r1);
450 ppc_lwz (buf, ppc_r16, STACK - 64, ppc_r1);
451 ppc_lwz (buf, ppc_r17, STACK - 68, ppc_r1);
452 ppc_lwz (buf, ppc_r18, STACK - 72, ppc_r1);
453 ppc_lwz (buf, ppc_r19, STACK - 76, ppc_r1);
454 ppc_lwz (buf, ppc_r20, STACK - 80, ppc_r1);
455 ppc_lwz (buf, ppc_r21, STACK - 84, ppc_r1);
456 ppc_lwz (buf, ppc_r22, STACK - 88, ppc_r1);
457 ppc_lwz (buf, ppc_r23, STACK - 92, ppc_r1);
458 ppc_lwz (buf, ppc_r24, STACK - 96, ppc_r1);
459 ppc_lwz (buf, ppc_r25, STACK - 100, ppc_r1);
460 ppc_lwz (buf, ppc_r26, STACK - 104, ppc_r1);
461 ppc_lwz (buf, ppc_r27, STACK - 108, ppc_r1);
462 ppc_lwz (buf, ppc_r28, STACK - 112, ppc_r1);
463 ppc_lwz (buf, ppc_r29, STACK - 116, ppc_r1);
464 ppc_lwz (buf, ppc_r30, STACK - 120, ppc_r1);
467 /* Non-standard function epilogue. Instead of doing a proper
468 return, we just call the compiled code, so
469 that, when it finishes, the method returns here. */
472 /* Restore stack pointer, r31, LR and jump to the code */
473 ppc_lwz (buf, ppc_r1, 0, ppc_r1);
474 ppc_lwz (buf, ppc_r31, -4, ppc_r1);
475 ppc_lwz (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
476 ppc_mtlr (buf, ppc_r11);
477 ppc_mtctr (buf, ppc_r0);
478 ppc_bcctr (buf, 20, 0);
480 ppc_mtlr (buf, ppc_r0);
483 /* Restore stack pointer, r31, LR and return to caller */
484 ppc_lwz (buf, ppc_r11, 0, ppc_r1);
485 ppc_lwz (buf, ppc_r31, -4, ppc_r11);
486 ppc_mr (buf, ppc_r1, ppc_r11);
487 ppc_lwz (buf, ppc_r0, 4, ppc_r1);
488 ppc_mtlr (buf, ppc_r0);
492 /* Flush instruction cache, since we've generated code */
493 mono_arch_flush_icache (code, buf - code);
496 g_assert ((buf - code) <= 512);
499 switch (tramp_type) {
500 case MONO_TRAMPOLINE_GENERIC:
501 mono_generic_trampoline_code = code;
503 case MONO_TRAMPOLINE_JUMP:
504 generic_jump_trampoline = code;
506 case MONO_TRAMPOLINE_CLASS_INIT:
507 generic_class_init_trampoline = code;
515 mono_arch_create_jump_trampoline (MonoMethod *method)
517 guint8 *code, *buf, *tramp = NULL;
519 MonoDomain* domain = mono_domain_get ();
521 tramp = create_trampoline_code (MONO_TRAMPOLINE_JUMP);
523 mono_domain_lock (domain);
524 code = buf = mono_code_manager_reserve (domain->code_mp, METHOD_TRAMPOLINE_SIZE);
525 mono_domain_unlock (domain);
527 /* Save r11. There's nothing magic in the '44', its just an arbitrary
528 position - see above */
529 ppc_stw (buf, ppc_r11, -44, ppc_r1);
531 /* Now save LR - we'll overwrite it now */
532 ppc_mflr (buf, ppc_r11);
533 ppc_stw (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
535 /* Prepare the jump to the generic trampoline code.*/
536 ppc_lis (buf, ppc_r11, (guint32) tramp >> 16);
537 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) tramp & 0xffff);
538 ppc_mtlr (buf, ppc_r11);
540 /* And finally put 'method' in r11 and fly! */
541 ppc_lis (buf, ppc_r11, (guint32) method >> 16);
542 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) method & 0xffff);
545 /* Flush instruction cache, since we've generated code */
546 mono_arch_flush_icache (code, buf - code);
548 g_assert ((buf - code) <= JUMP_TRAMPOLINE_SIZE);
550 ji = g_new0 (MonoJitInfo, 1);
552 ji->code_start = code;
553 ji->code_size = buf - code;
555 mono_jit_stats.method_trampolines++;
561 * arch_create_jit_trampoline:
562 * @method: pointer to the method info
564 * Creates a trampoline function for virtual methods. If the created
565 * code is called it first starts JIT compilation of method,
566 * and then calls the newly created method. It also replaces the
567 * corresponding vtable entry (see ppc_magic_trampoline).
569 * A trampoline consists of two parts: a main fragment, shared by all method
570 * trampolines, and some code specific to each method, which hard-codes a
571 * reference to that method and then calls the main fragment.
573 * The main fragment contains a call to 'ppc_magic_trampoline', which performs
574 * call to the JIT compiler and substitutes the method-specific fragment with
575 * some code that directly calls the JIT-compiled method.
577 * Returns: a pointer to the newly created code
580 mono_arch_create_jit_trampoline (MonoMethod *method)
583 static guint8 *vc = NULL;
584 MonoDomain* domain = mono_domain_get ();
586 /* previously created trampoline code */
590 if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
591 return mono_arch_create_jit_trampoline (mono_marshal_get_synchronized_wrapper (method));
593 vc = create_trampoline_code (MONO_TRAMPOLINE_GENERIC);
595 /* This is the method-specific part of the trampoline. Its purpose is
596 to provide the generic part with the MonoMethod *method pointer. We'll
597 use r11 to keep that value, for instance. However, the generic part of
598 the trampoline relies on r11 having the same value it had before coming
599 here, so we must save it before. */
600 //code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
601 // FIXME: should pass the domain down tot his function
602 mono_domain_lock (domain);
603 code = buf = mono_code_manager_reserve (domain->code_mp, METHOD_TRAMPOLINE_SIZE);
604 mono_domain_unlock (domain);
606 /* Save r11. There's nothing magic in the '44', its just an arbitrary
607 position - see above */
608 ppc_stw (buf, ppc_r11, -44, ppc_r1);
610 /* Now save LR - we'll overwrite it now */
611 ppc_mflr (buf, ppc_r11);
612 ppc_stw (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
614 /* Prepare the jump to the generic trampoline code.*/
615 ppc_lis (buf, ppc_r11, (guint32) vc >> 16);
616 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) vc & 0xffff);
617 ppc_mtlr (buf, ppc_r11);
619 /* And finally put 'method' in r11 and fly! */
620 ppc_lis (buf, ppc_r11, (guint32) method >> 16);
621 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) method & 0xffff);
624 /* Flush instruction cache, since we've generated code */
625 mono_arch_flush_icache (code, buf - code);
628 g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
630 /* Store trampoline address */
633 mono_jit_stats.method_trampolines++;
641 * x86_magic_trampoline:
642 * @eax: saved x86 register
643 * @ecx: saved x86 register
644 * @edx: saved x86 register
645 * @esi: saved x86 register
646 * @edi: saved x86 register
647 * @ebx: saved x86 register
648 * @code: pointer into caller code
649 * @method: the method to translate
651 * This method is called by the trampoline functions for virtual
652 * methods. It inspects the caller code to find the address of the
653 * vtable slot, then calls the JIT compiler and writes the address
654 * of the compiled method back to the vtable. All virtual methods
655 * are called with: x86_call_membase (inst, basereg, disp). We always
656 * use 32 bit displacement to ensure that the length of the call
657 * instruction is 6 bytes. We need to get the value of the basereg
658 * and the constant displacement.
661 x86_magic_trampoline (int eax, int ecx, int edx, int esi, int edi,
662 int ebx, guint8 *code, MonoMethod *m)
669 addr = mono_compile_method (m);
672 /* go to the start of the call instruction
674 * address_byte = (m << 6) | (o << 3) | reg
675 * call opcode: 0xff address_byte displacement
680 if ((code [1] != 0xe8) && (code [3] == 0xff) && ((code [4] & 0x18) == 0x10) && ((code [4] >> 6) == 1)) {
681 reg = code [4] & 0x07;
682 disp = (signed char)code [5];
684 if ((code [0] == 0xff) && ((code [1] & 0x18) == 0x10) && ((code [1] >> 6) == 2)) {
685 reg = code [1] & 0x07;
686 disp = *((gint32*)(code + 2));
687 } else if ((code [1] == 0xe8)) {
688 *((guint32*)(code + 2)) = (guint)addr - ((guint)code + 1) - 5;
690 } else if ((code [4] == 0xff) && (((code [5] >> 6) & 0x3) == 0) && (((code [5] >> 3) & 0x7) == 2)) {
692 * This is a interface call: should check the above code can't catch it earlier
693 * 8b 40 30 mov 0x30(%eax),%eax
697 reg = code [5] & 0x07;
699 printf ("Invalid trampoline sequence: %x %x %x %x %x %x %x\n", code [0], code [1], code [2], code [3],
700 code [4], code [5], code [6]);
701 g_assert_not_reached ();
725 g_assert_not_reached ();
730 if (m->klass->valuetype) {
731 return *((gpointer *)o) = get_unbox_trampoline (m, addr);
733 return *((gpointer *)o) = addr;
738 * mono_arch_create_jit_trampoline:
739 * @method: pointer to the method info
741 * Creates a trampoline function for virtual methods. If the created
742 * code is called it first starts JIT compilation of method,
743 * and then calls the newly created method. I also replaces the
744 * corresponding vtable entry (see x86_magic_trampoline).
746 * Returns: a pointer to the newly created code
749 mono_arch_create_jit_trampoline (MonoMethod *method)
753 /* previously created trampoline code */
757 if (!mono_generic_trampoline_code) {
758 mono_generic_trampoline_code = buf = g_malloc (256);
759 /* save caller save regs because we need to do a call */
760 x86_push_reg (buf, X86_EDX);
761 x86_push_reg (buf, X86_EAX);
762 x86_push_reg (buf, X86_ECX);
766 /* save the IP (caller ip) */
767 x86_push_membase (buf, X86_ESP, 16);
769 x86_push_reg (buf, X86_EBX);
770 x86_push_reg (buf, X86_EDI);
771 x86_push_reg (buf, X86_ESI);
772 x86_push_reg (buf, X86_EBP);
774 /* save method info */
775 x86_push_membase (buf, X86_ESP, 32);
776 /* get the address of lmf for the current thread */
777 x86_call_code (buf, mono_get_lmf_addr);
779 x86_push_reg (buf, X86_EAX);
780 /* push *lfm (previous_lmf) */
781 x86_push_membase (buf, X86_EAX, 0);
783 x86_mov_membase_reg (buf, X86_EAX, 0, X86_ESP, 4);
786 /* push the method info */
787 x86_push_membase (buf, X86_ESP, 44);
788 /* push the return address onto the stack */
789 x86_push_membase (buf, X86_ESP, 52);
791 /* save all register values */
792 x86_push_reg (buf, X86_EBX);
793 x86_push_reg (buf, X86_EDI);
794 x86_push_reg (buf, X86_ESI);
795 x86_push_membase (buf, X86_ESP, 64); /* EDX */
796 x86_push_membase (buf, X86_ESP, 64); /* ECX */
797 x86_push_membase (buf, X86_ESP, 64); /* EAX */
799 x86_call_code (buf, x86_magic_trampoline);
800 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 8*4);
802 /* restore LMF start */
803 /* ebx = previous_lmf */
804 x86_pop_reg (buf, X86_EBX);
806 x86_pop_reg (buf, X86_EDI);
807 /* *(lmf) = previous_lmf */
808 x86_mov_membase_reg (buf, X86_EDI, 0, X86_EBX, 4);
809 /* discard method info */
810 x86_pop_reg (buf, X86_ESI);
811 /* restore caller saved regs */
812 x86_pop_reg (buf, X86_EBP);
813 x86_pop_reg (buf, X86_ESI);
814 x86_pop_reg (buf, X86_EDI);
815 x86_pop_reg (buf, X86_EBX);
816 /* discard save IP */
817 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 4);
818 /* restore LMF end */
820 x86_alu_reg_imm (buf, X86_ADD, X86_ESP, 16);
822 /* call the compiled method */
823 x86_jump_reg (buf, X86_EAX);
825 g_assert ((buf - mono_generic_trampoline_code) <= 256);
828 code = buf = g_malloc (16);
829 x86_push_imm (buf, method);
830 x86_jump_code (buf, mono_generic_trampoline_code);
831 g_assert ((buf - code) <= 16);
833 /* store trampoline address */
836 //mono_jit_stats.method_trampolines++;
844 * mono_arch_create_class_init_trampoline:
845 * @vtable: the type to initialize
847 * Creates a trampoline function to run a type initializer.
848 * If the trampoline is called, it calls mono_runtime_class_init with the
849 * given vtable, then patches the caller code so it does not get called any
852 * Returns: a pointer to the newly created code
855 mono_arch_create_class_init_trampoline (MonoVTable *vtable)
857 guint8 *code, *buf, *tramp;
859 tramp = create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
861 /* This is the method-specific part of the trampoline. Its purpose is
862 to provide the generic part with the MonoMethod *method pointer. We'll
863 use r11 to keep that value, for instance. However, the generic part of
864 the trampoline relies on r11 having the same value it had before coming
865 here, so we must save it before. */
866 //code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
867 mono_domain_lock (vtable->domain);
868 code = buf = mono_code_manager_reserve (vtable->domain->code_mp, METHOD_TRAMPOLINE_SIZE);
869 mono_domain_unlock (vtable->domain);
872 ppc_mflr (buf, ppc_r4);
873 ppc_stw (buf, ppc_r4, PPC_RET_ADDR_OFFSET, ppc_sp);
874 ppc_stwu (buf, ppc_sp, -32, ppc_sp);
875 ppc_load (buf, ppc_r3, vtable);
876 ppc_load (buf, ppc_r5, 0);
878 ppc_load (buf, ppc_r0, ppc_class_init_trampoline);
879 ppc_mtlr (buf, ppc_r0);
882 ppc_lwz (buf, ppc_r0, 32 + PPC_RET_ADDR_OFFSET, ppc_sp);
883 ppc_mtlr (buf, ppc_r0);
884 ppc_addic (buf, ppc_sp, ppc_sp, 32);
887 /* Save r11. There's nothing magic in the '44', its just an arbitrary
888 position - see above */
889 ppc_stw (buf, ppc_r11, -44, ppc_r1);
891 /* Now save LR - we'll overwrite it now */
892 ppc_mflr (buf, ppc_r11);
893 ppc_stw (buf, ppc_r11, 4, ppc_r1);
894 ppc_stw (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
896 /* Prepare the jump to the generic trampoline code.*/
897 ppc_lis (buf, ppc_r11, (guint32) tramp >> 16);
898 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) tramp & 0xffff);
899 ppc_mtlr (buf, ppc_r11);
901 /* And finally put 'vtable' in r11 and fly! */
902 ppc_lis (buf, ppc_r11, (guint32) vtable >> 16);
903 ppc_ori (buf, ppc_r11, ppc_r11, (guint32) vtable & 0xffff);
905 ppc_lwz (buf, ppc_r0, PPC_RET_ADDR_OFFSET, ppc_r1);
906 ppc_mtlr (buf, ppc_r0);
911 /* Flush instruction cache, since we've generated code */
912 mono_arch_flush_icache (code, buf - code);
915 g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
917 mono_jit_stats.method_trampolines++;
923 * This method is only called when running in the Mono Debugger.
926 mono_debugger_create_notification_function (gpointer *notification_address)
930 ptr = buf = g_malloc0 (16);
932 if (notification_address)
933 *notification_address = buf;