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 (!mono_method_signature (m)->ret->byref && MONO_TYPE_ISSTRUCT (mono_method_signature (m)->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)
104 MonoJitInfo *ji, *target_ji;
107 addr = mono_compile_method(method);
108 /*g_print ("method code at %p for %s:%s\n", addr, method->klass->name, method->name);*/
115 /* We can't trampoline across domains */
116 ji = mono_jit_info_table_find (mono_domain_get (), code);
117 target_ji = mono_jit_info_table_find (mono_domain_get (), addr);
118 if (!mono_method_same_domain (ji, target_ji))
121 /* Locate the address of the method-specific trampoline. The call using
122 the vtable slot that took the processing flow to 'arch_create_jit_trampoline'
123 looks something like this:
125 mtlr rA ; Move rA (a register containing the
126 ; target address) to LR
127 blrl ; Call function at LR
129 PowerPC instructions are 32-bit long, which means that a 32-bit target
130 address cannot be encoded as an immediate value (because we already
131 have spent some bits to encode the branch instruction!). That's why a
132 'b'ranch to the contents of the 'l'ink 'r'egister (with 'l'ink register
133 update) is needed, instead of a simpler 'branch immediate'. This
134 complicates our purpose here, because 'blrl' overwrites LR, which holds
135 the value we're interested in.
137 Therefore, we need to locate the 'mtlr rA' instruction to know which
138 register LR was loaded from, and then retrieve the value from that
141 /* This is the 'blrl' instruction */
145 * Note that methods are called also with the bl opcode.
147 if (((*code) >> 26) == 18) {
148 /*g_print ("direct patching\n");*/
149 ppc_patch ((char*)code, addr);
150 mono_arch_flush_icache ((char*)code, 4);
154 /* Sanity check: instruction must be 'blrl' */
155 g_assert(*code == 0x4e800021);
157 /* OK, we're now at the 'blrl' instruction. Now walk backwards
158 till we get to a 'mtlr rA' */
160 if((*code & 0x7c0803a6) == 0x7c0803a6) {
163 /* Here we are: we reached the 'mtlr rA'.
164 Extract the register from the instruction */
165 reg = (*code & 0x03e00000) >> 21;
167 /* ok, this is a lwz reg, offset (vtreg)
168 * it is emitted with:
169 * ppc_emit32 (c, (32 << 26) | ((D) << 21) | ((a) << 16) | (guint16)(d))
171 soff = (*code & 0xffff);
173 reg = (*code >> 16) & 0x1f;
174 g_assert (reg != ppc_r1);
175 /*g_print ("patching reg is %d\n", reg);*/
177 /* saved in the MonoLMF structure */
178 reg_offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs);
179 reg_offset += (reg - 13) * sizeof (gulong);
181 /* saved in the stack, see frame diagram below */
182 reg_offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
183 reg_offset += reg * sizeof (gulong);
185 /* o contains now the value of register reg */
186 o = *((char**) (sp + reg_offset));
191 /* this is not done for non-virtual calls, because in that case
192 we won't have an object, but the actual pointer to the
193 valuetype as the this argument
195 if (method->klass->valuetype && !mono_aot_is_got_entry (code, o))
196 addr = get_unbox_trampoline (method, addr);
199 if (mono_aot_is_got_entry (code, o) || mono_domain_owns_vtable_slot (mono_domain_get (), o))
200 *((gpointer *)o) = addr;
205 ppc_class_init_trampoline (void *vtable, guint32 *code, char *sp)
207 mono_runtime_class_init (vtable);
210 /* This is the 'bl' instruction */
213 if (((*code) >> 26) == 18) {
214 ppc_ori (code, 0, 0, 0); /* nop */
215 mono_arch_flush_icache (code, 4);
218 g_assert_not_reached ();
224 * Stack frame description when the generic trampoline is called.
226 * --------------------
228 * -------------------
229 * Saved FP registers 0-13
230 * -------------------
231 * Saved general registers 0-12
232 * -------------------
233 * param area for 3 args to ppc_magic_trampoline
234 * -------------------
236 * -------------------
239 create_trampoline_code (MonoTrampolineType tramp_type)
241 guint8 *buf, *code = NULL;
242 static guint8* generic_jump_trampoline = NULL;
243 static guint8 *generic_class_init_trampoline = NULL;
246 switch (tramp_type) {
247 case MONO_TRAMPOLINE_GENERIC:
248 if (mono_generic_trampoline_code)
249 return mono_generic_trampoline_code;
251 case MONO_TRAMPOLINE_JUMP:
252 if (generic_jump_trampoline)
253 return generic_jump_trampoline;
255 case MONO_TRAMPOLINE_CLASS_INIT:
256 if (generic_class_init_trampoline)
257 return generic_class_init_trampoline;
262 /* Now we'll create in 'buf' the PowerPC trampoline code. This
263 is the trampoline code common to all methods */
265 code = buf = g_malloc(512);
267 ppc_stwu (buf, ppc_r1, -STACK, ppc_r1);
269 /* start building the MonoLMF on the stack */
270 offset = STACK - sizeof (double) * MONO_SAVED_FREGS;
271 for (i = 14; i < 32; i++) {
272 ppc_stfd (buf, i, offset, ppc_r1);
273 offset += sizeof (double);
276 * now the integer registers. r13 is already saved in the trampoline,
277 * and at this point contains the method to compile, so we skip it.
279 offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs) + sizeof (gulong);
280 ppc_stmw (buf, ppc_r14, ppc_r1, offset);
282 /* Now save the rest of the registers below the MonoLMF struct, first 14
283 * fp regs and then the 13 gregs.
285 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double));
286 for (i = 0; i < 14; i++) {
287 ppc_stfd (buf, i, offset, ppc_r1);
288 offset += sizeof (double);
290 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
291 for (i = 0; i < 13; i++) {
292 ppc_stw (buf, i, offset, ppc_r1);
293 offset += sizeof (gulong);
295 /* we got here through a jump to the ctr reg, we must save the lr
296 * in the parent frame (we do it here to reduce the size of the
297 * method-specific trampoline)
299 ppc_mflr (buf, ppc_r0);
300 ppc_stw (buf, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
302 /* ok, now we can continue with the MonoLMF setup, mostly untouched
303 * from emit_prolog in mini-ppc.c
305 ppc_load (buf, ppc_r0, mono_get_lmf_addr);
306 ppc_mtlr (buf, ppc_r0);
308 /* we build the MonoLMF structure on the stack - see mini-ppc.h
309 * The pointer to the struct is put in ppc_r11.
311 ppc_addi (buf, ppc_r11, ppc_sp, STACK - sizeof (MonoLMF));
312 ppc_stw (buf, ppc_r3, G_STRUCT_OFFSET(MonoLMF, lmf_addr), ppc_r11);
313 /* new_lmf->previous_lmf = *lmf_addr */
314 ppc_lwz (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r3);
315 ppc_stw (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r11);
316 /* *(lmf_addr) = r11 */
317 ppc_stw (buf, ppc_r11, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r3);
318 /* save method info (it's in r13) */
319 ppc_stw (buf, ppc_r13, G_STRUCT_OFFSET(MonoLMF, method), ppc_r11);
320 ppc_stw (buf, ppc_sp, G_STRUCT_OFFSET(MonoLMF, ebp), ppc_r11);
321 /* save the IP (caller ip) */
322 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
323 ppc_li (buf, ppc_r0, 0);
325 ppc_lwz (buf, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
327 ppc_stw (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, eip), ppc_r11);
330 * Now we're ready to call ppc_magic_trampoline ().
332 /* Arg 1: MonoMethod *method. It was put in r13 */
333 ppc_mr (buf, ppc_r3, ppc_r13);
335 /* Arg 2: code (next address to the instruction that called us) */
336 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
337 ppc_li (buf, ppc_r4, 0);
339 ppc_lwz (buf, ppc_r4, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
342 /* Arg 3: stack pointer so that the magic trampoline can access the
343 * registers we saved above
345 ppc_mr (buf, ppc_r5, ppc_r1);
347 if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
348 ppc_lis (buf, ppc_r0, (guint32) ppc_class_init_trampoline >> 16);
349 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_class_init_trampoline & 0xffff);
351 ppc_lis (buf, ppc_r0, (guint32) ppc_magic_trampoline >> 16);
352 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_magic_trampoline & 0xffff);
354 ppc_mtlr (buf, ppc_r0);
357 /* OK, code address is now on r3. Move it to the counter reg
358 * so it will be ready for the final jump: this is safe since we
359 * won't do any more calls.
361 ppc_mtctr (buf, ppc_r3);
364 * Now we restore the MonoLMF (see emit_epilogue in mini-ppc.c)
365 * and the rest of the registers, so the method called will see
366 * the same state as before we executed.
367 * The pointer to MonoLMF is in ppc_r11.
369 ppc_addi (buf, ppc_r11, ppc_r1, STACK - sizeof (MonoLMF));
370 /* r5 = previous_lmf */
371 ppc_lwz (buf, ppc_r5, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r11);
373 ppc_lwz (buf, ppc_r6, G_STRUCT_OFFSET(MonoLMF, lmf_addr), ppc_r11);
374 /* *(lmf_addr) = previous_lmf */
375 ppc_stw (buf, ppc_r5, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r6);
376 /* restore iregs: this time include r13 */
377 ppc_lmw (buf, ppc_r13, ppc_r11, G_STRUCT_OFFSET(MonoLMF, iregs));
379 for (i = 14; i < 32; i++) {
380 ppc_lfd (buf, i, G_STRUCT_OFFSET(MonoLMF, fregs) + ((i-14) * sizeof (gdouble)), ppc_r11);
383 /* restore the volatile registers, we skip r1, of course */
384 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double));
385 for (i = 0; i < 14; i++) {
386 ppc_lfd (buf, i, offset, ppc_r1);
387 offset += sizeof (double);
389 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
390 ppc_lwz (buf, ppc_r0, offset, ppc_r1);
391 offset += 2 * sizeof (gulong);
392 for (i = 2; i < 13; i++) {
393 ppc_lwz (buf, i, offset, ppc_r1);
394 offset += sizeof (gulong);
397 /* Non-standard function epilogue. Instead of doing a proper
398 * return, we just hump to the compiled code.
400 /* Restore stack pointer and LR and jump to the code */
401 ppc_lwz (buf, ppc_r1, 0, ppc_r1);
402 ppc_lwz (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
403 ppc_mtlr (buf, ppc_r11);
404 ppc_bcctr (buf, 20, 0);
406 /* Flush instruction cache, since we've generated code */
407 mono_arch_flush_icache (code, buf - code);
410 g_assert ((buf - code) <= 512);
413 switch (tramp_type) {
414 case MONO_TRAMPOLINE_GENERIC:
415 mono_generic_trampoline_code = code;
417 case MONO_TRAMPOLINE_JUMP:
418 generic_jump_trampoline = code;
420 case MONO_TRAMPOLINE_CLASS_INIT:
421 generic_class_init_trampoline = code;
429 create_specific_tramp (MonoMethod *method, guint8* tramp, MonoDomain *domain) {
433 mono_domain_lock (domain);
434 code = buf = mono_code_manager_reserve (domain->code_mp, 32);
435 mono_domain_unlock (domain);
437 /* Save r13 in the place it will have in the on-stack MonoLMF */
438 ppc_stw (buf, ppc_r13, -(MONO_SAVED_FREGS * 8 + MONO_SAVED_GREGS * sizeof (gpointer)), ppc_r1);
440 /* Prepare the jump to the generic trampoline code.*/
441 ppc_lis (buf, ppc_r13, (guint32) tramp >> 16);
442 ppc_ori (buf, ppc_r13, ppc_r13, (guint32) tramp & 0xffff);
443 ppc_mtctr (buf, ppc_r13);
445 /* And finally put 'method' in r13 and fly! */
446 ppc_lis (buf, ppc_r13, (guint32) method >> 16);
447 ppc_ori (buf, ppc_r13, ppc_r13, (guint32) method & 0xffff);
448 ppc_bcctr (buf, 20, 0);
450 /* Flush instruction cache, since we've generated code */
451 mono_arch_flush_icache (code, buf - code);
453 g_assert ((buf - code) <= 32);
455 ji = g_new0 (MonoJitInfo, 1);
457 ji->code_start = code;
458 ji->code_size = buf - code;
460 mono_jit_stats.method_trampolines++;
466 mono_arch_create_jump_trampoline (MonoMethod *method)
469 MonoDomain* domain = mono_domain_get ();
471 tramp = create_trampoline_code (MONO_TRAMPOLINE_JUMP);
472 return create_specific_tramp (method, tramp, domain);
476 * arch_create_jit_trampoline:
477 * @method: pointer to the method info
479 * Creates a trampoline function for virtual methods. If the created
480 * code is called it first starts JIT compilation of method,
481 * and then calls the newly created method. It also replaces the
482 * corresponding vtable entry (see ppc_magic_trampoline).
484 * A trampoline consists of two parts: a main fragment, shared by all method
485 * trampolines, and some code specific to each method, which hard-codes a
486 * reference to that method and then calls the main fragment.
488 * The main fragment contains a call to 'ppc_magic_trampoline', which performs
489 * call to the JIT compiler and substitutes the method-specific fragment with
490 * some code that directly calls the JIT-compiled method.
492 * Returns: a pointer to the newly created code
495 mono_arch_create_jit_trampoline (MonoMethod *method)
499 MonoDomain* domain = mono_domain_get ();
502 tramp = create_trampoline_code (MONO_TRAMPOLINE_GENERIC);
503 /* FIXME: should pass the domain down to this function */
504 ji = create_specific_tramp (method, tramp, domain);
505 code_start = ji->code_start;
512 * mono_arch_create_class_init_trampoline:
513 * @vtable: the type to initialize
515 * Creates a trampoline function to run a type initializer.
516 * If the trampoline is called, it calls mono_runtime_class_init with the
517 * given vtable, then patches the caller code so it does not get called any
520 * Returns: a pointer to the newly created code
523 mono_arch_create_class_init_trampoline (MonoVTable *vtable)
525 guint8 *code, *buf, *tramp;
527 tramp = create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
529 /* This is the method-specific part of the trampoline. Its purpose is
530 to provide the generic part with the MonoMethod *method pointer. We'll
531 use r11 to keep that value, for instance. However, the generic part of
532 the trampoline relies on r11 having the same value it had before coming
533 here, so we must save it before. */
534 //code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
535 mono_domain_lock (vtable->domain);
536 code = buf = mono_code_manager_reserve (vtable->domain->code_mp, METHOD_TRAMPOLINE_SIZE);
537 mono_domain_unlock (vtable->domain);
539 ppc_mflr (buf, ppc_r4);
540 ppc_stw (buf, ppc_r4, PPC_RET_ADDR_OFFSET, ppc_sp);
541 ppc_stwu (buf, ppc_sp, -64, ppc_sp);
542 ppc_load (buf, ppc_r3, vtable);
543 ppc_load (buf, ppc_r5, 0);
545 ppc_load (buf, ppc_r0, ppc_class_init_trampoline);
546 ppc_mtlr (buf, ppc_r0);
549 ppc_lwz (buf, ppc_r0, 64 + PPC_RET_ADDR_OFFSET, ppc_sp);
550 ppc_mtlr (buf, ppc_r0);
551 ppc_addic (buf, ppc_sp, ppc_sp, 64);
554 /* Flush instruction cache, since we've generated code */
555 mono_arch_flush_icache (code, buf - code);
558 g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
560 mono_jit_stats.method_trampolines++;
566 * This method is only called when running in the Mono Debugger.
569 mono_debugger_create_notification_function (gpointer *notification_address)
573 ptr = buf = g_malloc0 (16);
575 if (notification_address)
576 *notification_address = buf;