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 * + MonoLMF + 14 fp regs + 13 gregs + alignment
74 * #define STACK (PPC_MINIMAL_STACK_SIZE + 4 * sizeof (gulong) + sizeof (MonoLMF) + 14 * sizeof (double) + 13 * (sizeof (gulong)))
75 * STACK would be 444 for 32 bit darwin
79 /* Method-specific trampoline code fragment size */
80 #define METHOD_TRAMPOLINE_SIZE 64
82 /* Jump-specific trampoline code fragment size */
83 #define JUMP_TRAMPOLINE_SIZE 64
86 * ppc_magic_trampoline:
87 * @code: pointer into caller code
88 * @method: the method to translate
91 * This method is called by the function 'arch_create_jit_trampoline', which in
92 * turn is called by the trampoline functions for virtual methods.
93 * After having called the JIT compiler to compile the method, it inspects the
94 * caller code to find the address of the method-specific part of the
95 * trampoline vtable slot for this method, updates it with a fragment that calls
96 * the newly compiled code and returns this address of the compiled code to
97 * 'arch_create_jit_trampoline'
100 ppc_magic_trampoline (MonoMethod *method, guint32 *code, char *sp)
106 addr = mono_compile_method(method);
107 /*g_print ("method code at %p for %s:%s\n", addr, method->klass->name, method->name);*/
114 /* Locate the address of the method-specific trampoline. The call using
115 the vtable slot that took the processing flow to 'arch_create_jit_trampoline'
116 looks something like this:
118 mtlr rA ; Move rA (a register containing the
119 ; target address) to LR
120 blrl ; Call function at LR
122 PowerPC instructions are 32-bit long, which means that a 32-bit target
123 address cannot be encoded as an immediate value (because we already
124 have spent some bits to encode the branch instruction!). That's why a
125 'b'ranch to the contents of the 'l'ink 'r'egister (with 'l'ink register
126 update) is needed, instead of a simpler 'branch immediate'. This
127 complicates our purpose here, because 'blrl' overwrites LR, which holds
128 the value we're interested in.
130 Therefore, we need to locate the 'mtlr rA' instruction to know which
131 register LR was loaded from, and then retrieve the value from that
134 /* This is the 'blrl' instruction */
138 * Note that methods are called also with the bl opcode.
140 if (((*code) >> 26) == 18) {
141 /*g_print ("direct patching\n");*/
142 ppc_patch ((char*)code, addr);
143 mono_arch_flush_icache ((char*)code, 4);
147 /* Sanity check: instruction must be 'blrl' */
148 g_assert(*code == 0x4e800021);
150 /* OK, we're now at the 'blrl' instruction. Now walk backwards
151 till we get to a 'mtlr rA' */
153 if((*code & 0x7c0803a6) == 0x7c0803a6) {
156 /* Here we are: we reached the 'mtlr rA'.
157 Extract the register from the instruction */
158 reg = (*code & 0x03e00000) >> 21;
160 /* ok, this is a lwz reg, offset (vtreg)
161 * it is emitted with:
162 * ppc_emit32 (c, (32 << 26) | ((D) << 21) | ((a) << 16) | (guint16)(d))
164 soff = (*code & 0xffff);
166 reg = (*code >> 16) & 0x1f;
167 g_assert (reg != ppc_r1);
168 /*g_print ("patching reg is %d\n", reg);*/
170 /* saved in the MonoLMF structure */
171 reg_offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs);
172 reg_offset += (reg - 13) * sizeof (gulong);
174 /* saved in the stack, see frame diagram below */
175 reg_offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
176 reg_offset += reg * sizeof (gulong);
178 /* o contains now the value of register reg */
179 o = *((char**) (sp + reg_offset));
184 /* this is not done for non-virtual calls, because in that case
185 we won't have an object, but the actual pointer to the
186 valuetype as the this argument
188 if (method->klass->valuetype)
189 addr = get_unbox_trampoline (method, addr);
192 *((gpointer *)o) = addr;
197 ppc_class_init_trampoline (void *vtable, guint32 *code, char *sp)
199 mono_runtime_class_init (vtable);
202 /* This is the 'bl' instruction */
205 if (((*code) >> 26) == 18) {
206 ppc_ori (code, 0, 0, 0); /* nop */
207 mono_arch_flush_icache (code, 4);
210 g_assert_not_reached ();
216 * Stack frame description when the generic trampoline is called.
218 * --------------------
220 * -------------------
221 * Saved FP registers 0-13
222 * -------------------
223 * Saved general registers 0-12
224 * -------------------
225 * param area for 3 args to ppc_magic_trampoline
226 * -------------------
228 * -------------------
231 create_trampoline_code (MonoTrampolineType tramp_type)
233 guint8 *buf, *code = NULL;
234 static guint8* generic_jump_trampoline = NULL;
235 static guint8 *generic_class_init_trampoline = NULL;
238 switch (tramp_type) {
239 case MONO_TRAMPOLINE_GENERIC:
240 if (mono_generic_trampoline_code)
241 return mono_generic_trampoline_code;
243 case MONO_TRAMPOLINE_JUMP:
244 if (generic_jump_trampoline)
245 return generic_jump_trampoline;
247 case MONO_TRAMPOLINE_CLASS_INIT:
248 if (generic_class_init_trampoline)
249 return generic_class_init_trampoline;
254 /* Now we'll create in 'buf' the PowerPC trampoline code. This
255 is the trampoline code common to all methods */
257 code = buf = g_malloc(512);
259 ppc_stwu (buf, ppc_r1, -STACK, ppc_r1);
261 /* start building the MonoLMF on the stack */
262 offset = STACK - sizeof (double) * MONO_SAVED_FREGS;
263 for (i = 14; i < 32; i++) {
264 ppc_stfd (buf, i, offset, ppc_r1);
265 offset += sizeof (double);
268 * now the integer registers. r13 is already saved in the trampoline,
269 * and at this point contains the method to compile, so we skip it.
271 offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs) + sizeof (gulong);
272 ppc_stmw (buf, ppc_r14, ppc_r1, offset);
274 /* Now save the rest of the registers below the MonoLMF struct, first 14
275 * fp regs and then the 13 gregs.
277 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double));
278 for (i = 0; i < 14; i++) {
279 ppc_stfd (buf, i, offset, ppc_r1);
280 offset += sizeof (double);
282 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
283 for (i = 0; i < 13; i++) {
284 ppc_stw (buf, i, offset, ppc_r1);
285 offset += sizeof (gulong);
287 /* we got here through a jump to the ctr reg, we must save the lr
288 * in the parent frame (we do it here to reduce the size of the
289 * method-specific trampoline)
291 ppc_mflr (buf, ppc_r0);
292 ppc_stw (buf, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
294 /* ok, now we can continue with the MonoLMF setup, mostly untouched
295 * from emit_prolog in mini-ppc.c
297 ppc_load (buf, ppc_r0, mono_get_lmf_addr);
298 ppc_mtlr (buf, ppc_r0);
300 /* we build the MonoLMF structure on the stack - see mini-ppc.h
301 * The pointer to the struct is put in ppc_r11.
303 ppc_addi (buf, ppc_r11, ppc_sp, STACK - sizeof (MonoLMF));
304 ppc_stw (buf, ppc_r3, G_STRUCT_OFFSET(MonoLMF, lmf_addr), ppc_r11);
305 /* new_lmf->previous_lmf = *lmf_addr */
306 ppc_lwz (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r3);
307 ppc_stw (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r11);
308 /* *(lmf_addr) = r11 */
309 ppc_stw (buf, ppc_r11, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r3);
310 /* save method info (it's in r13) */
311 ppc_stw (buf, ppc_r13, G_STRUCT_OFFSET(MonoLMF, method), ppc_r11);
312 ppc_stw (buf, ppc_sp, G_STRUCT_OFFSET(MonoLMF, ebp), ppc_r11);
313 /* save the IP (caller ip) */
314 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
315 ppc_li (buf, ppc_r0, 0);
317 ppc_lwz (buf, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
319 ppc_stw (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, eip), ppc_r11);
322 * Now we're ready to call ppc_magic_trampoline ().
324 /* Arg 1: MonoMethod *method. It was put in r13 */
325 ppc_mr (buf, ppc_r3, ppc_r13);
327 /* Arg 2: code (next address to the instruction that called us) */
328 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
329 ppc_li (buf, ppc_r4, 0);
331 ppc_lwz (buf, ppc_r4, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
334 /* Arg 3: stack pointer so that the magic trampoline can access the
335 * registers we saved above
337 ppc_mr (buf, ppc_r5, ppc_r1);
339 if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
340 ppc_lis (buf, ppc_r0, (guint32) ppc_class_init_trampoline >> 16);
341 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_class_init_trampoline & 0xffff);
343 ppc_lis (buf, ppc_r0, (guint32) ppc_magic_trampoline >> 16);
344 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_magic_trampoline & 0xffff);
346 ppc_mtlr (buf, ppc_r0);
349 /* OK, code address is now on r3. Move it to the counter reg
350 * so it will be ready for the final jump: this is safe since we
351 * won't do any more calls.
353 ppc_mtctr (buf, ppc_r3);
356 * Now we restore the MonoLMF (see emit_epilogue in mini-ppc.c)
357 * and the rest of the registers, so the method called will see
358 * the same state as before we executed.
359 * The pointer to MonoLMF is in ppc_r11.
361 ppc_addi (buf, ppc_r11, ppc_r1, STACK - sizeof (MonoLMF));
362 /* r5 = previous_lmf */
363 ppc_lwz (buf, ppc_r5, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r11);
365 ppc_lwz (buf, ppc_r6, G_STRUCT_OFFSET(MonoLMF, lmf_addr), ppc_r11);
366 /* *(lmf_addr) = previous_lmf */
367 ppc_stw (buf, ppc_r5, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r6);
368 /* restore iregs: this time include r13 */
369 ppc_lmw (buf, ppc_r13, ppc_r11, G_STRUCT_OFFSET(MonoLMF, iregs));
371 for (i = 14; i < 32; i++) {
372 ppc_lfd (buf, i, G_STRUCT_OFFSET(MonoLMF, fregs) + ((i-14) * sizeof (gdouble)), ppc_r11);
375 /* restore the volatile registers, we skip r1, of course */
376 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double));
377 for (i = 0; i < 14; i++) {
378 ppc_lfd (buf, i, offset, ppc_r1);
379 offset += sizeof (double);
381 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
382 ppc_lwz (buf, ppc_r0, offset, ppc_r1);
383 offset += 2 * sizeof (gulong);
384 for (i = 2; i < 13; i++) {
385 ppc_lwz (buf, i, offset, ppc_r1);
386 offset += sizeof (gulong);
389 /* Non-standard function epilogue. Instead of doing a proper
390 * return, we just hump to the compiled code.
392 /* Restore stack pointer and LR and jump to the code */
393 ppc_lwz (buf, ppc_r1, 0, ppc_r1);
394 ppc_lwz (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
395 ppc_mtlr (buf, ppc_r11);
396 ppc_bcctr (buf, 20, 0);
398 /* Flush instruction cache, since we've generated code */
399 mono_arch_flush_icache (code, buf - code);
402 g_assert ((buf - code) <= 512);
405 switch (tramp_type) {
406 case MONO_TRAMPOLINE_GENERIC:
407 mono_generic_trampoline_code = code;
409 case MONO_TRAMPOLINE_JUMP:
410 generic_jump_trampoline = code;
412 case MONO_TRAMPOLINE_CLASS_INIT:
413 generic_class_init_trampoline = code;
421 create_specific_tramp (MonoMethod *method, guint8* tramp, MonoDomain *domain) {
425 mono_domain_lock (domain);
426 code = buf = mono_code_manager_reserve (domain->code_mp, 32);
427 mono_domain_unlock (domain);
429 /* Save r13 in the place it will have in the on-stack MonoLMF */
430 ppc_stw (buf, ppc_r13, -(MONO_SAVED_FREGS * 8 + MONO_SAVED_GREGS * sizeof (gpointer)), ppc_r1);
432 /* Prepare the jump to the generic trampoline code.*/
433 ppc_lis (buf, ppc_r13, (guint32) tramp >> 16);
434 ppc_ori (buf, ppc_r13, ppc_r13, (guint32) tramp & 0xffff);
435 ppc_mtctr (buf, ppc_r13);
437 /* And finally put 'method' in r13 and fly! */
438 ppc_lis (buf, ppc_r13, (guint32) method >> 16);
439 ppc_ori (buf, ppc_r13, ppc_r13, (guint32) method & 0xffff);
440 ppc_bcctr (buf, 20, 0);
442 /* Flush instruction cache, since we've generated code */
443 mono_arch_flush_icache (code, buf - code);
445 g_assert ((buf - code) <= 32);
447 ji = g_new0 (MonoJitInfo, 1);
449 ji->code_start = code;
450 ji->code_size = buf - code;
452 mono_jit_stats.method_trampolines++;
458 mono_arch_create_jump_trampoline (MonoMethod *method)
461 MonoDomain* domain = mono_domain_get ();
463 tramp = create_trampoline_code (MONO_TRAMPOLINE_JUMP);
464 return create_specific_tramp (method, tramp, domain);
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)
491 MonoDomain* domain = mono_domain_get ();
493 /* previously created trampoline code */
497 if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
498 return mono_arch_create_jit_trampoline (mono_marshal_get_synchronized_wrapper (method));
500 tramp = create_trampoline_code (MONO_TRAMPOLINE_GENERIC);
501 /* FIXME: should pass the domain down tot his function */
502 ji = create_specific_tramp (method, tramp, domain);
503 /* Store trampoline address */
504 method->info = ji->code_start;
505 return ji->code_start;
509 * mono_arch_create_class_init_trampoline:
510 * @vtable: the type to initialize
512 * Creates a trampoline function to run a type initializer.
513 * If the trampoline is called, it calls mono_runtime_class_init with the
514 * given vtable, then patches the caller code so it does not get called any
517 * Returns: a pointer to the newly created code
520 mono_arch_create_class_init_trampoline (MonoVTable *vtable)
522 guint8 *code, *buf, *tramp;
524 tramp = create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
526 /* This is the method-specific part of the trampoline. Its purpose is
527 to provide the generic part with the MonoMethod *method pointer. We'll
528 use r11 to keep that value, for instance. However, the generic part of
529 the trampoline relies on r11 having the same value it had before coming
530 here, so we must save it before. */
531 //code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
532 mono_domain_lock (vtable->domain);
533 code = buf = mono_code_manager_reserve (vtable->domain->code_mp, METHOD_TRAMPOLINE_SIZE);
534 mono_domain_unlock (vtable->domain);
536 ppc_mflr (buf, ppc_r4);
537 ppc_stw (buf, ppc_r4, PPC_RET_ADDR_OFFSET, ppc_sp);
538 ppc_stwu (buf, ppc_sp, -64, ppc_sp);
539 ppc_load (buf, ppc_r3, vtable);
540 ppc_load (buf, ppc_r5, 0);
542 ppc_load (buf, ppc_r0, ppc_class_init_trampoline);
543 ppc_mtlr (buf, ppc_r0);
546 ppc_lwz (buf, ppc_r0, 64 + PPC_RET_ADDR_OFFSET, ppc_sp);
547 ppc_mtlr (buf, ppc_r0);
548 ppc_addic (buf, ppc_sp, ppc_sp, 64);
551 /* Flush instruction cache, since we've generated code */
552 mono_arch_flush_icache (code, buf - code);
555 g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
557 mono_jit_stats.method_trampolines++;
563 * This method is only called when running in the Mono Debugger.
566 mono_debugger_create_notification_function (gpointer *notification_address)
570 ptr = buf = g_malloc0 (16);
572 if (notification_address)
573 *notification_address = buf;