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 /* the thunk-less direct call sequence: lis/ori/mtlr/blrl */
158 if ((code [-1] >> 26) == 31 && (code [-2] >> 26) == 24 && (code [-3] >> 26) == 15) {
159 ppc_patch ((char*)code, addr);
163 /* OK, we're now at the 'blrl' instruction. Now walk backwards
164 till we get to a 'mtlr rA' */
166 if((*code & 0x7c0803a6) == 0x7c0803a6) {
169 /* Here we are: we reached the 'mtlr rA'.
170 Extract the register from the instruction */
171 reg = (*code & 0x03e00000) >> 21;
173 /* ok, this is a lwz reg, offset (vtreg)
174 * it is emitted with:
175 * ppc_emit32 (c, (32 << 26) | ((D) << 21) | ((a) << 16) | (guint16)(d))
177 soff = (*code & 0xffff);
179 reg = (*code >> 16) & 0x1f;
180 g_assert (reg != ppc_r1);
181 /*g_print ("patching reg is %d\n", reg);*/
183 /* saved in the MonoLMF structure */
184 reg_offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs);
185 reg_offset += (reg - 13) * sizeof (gulong);
187 /* saved in the stack, see frame diagram below */
188 reg_offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
189 reg_offset += reg * sizeof (gulong);
191 /* o contains now the value of register reg */
192 o = *((char**) (sp + reg_offset));
197 /* this is not done for non-virtual calls, because in that case
198 we won't have an object, but the actual pointer to the
199 valuetype as the this argument
201 if (method->klass->valuetype && !mono_aot_is_got_entry (code, o))
202 addr = get_unbox_trampoline (method, addr);
205 if (mono_aot_is_got_entry (code, o) || mono_domain_owns_vtable_slot (mono_domain_get (), o))
206 *((gpointer *)o) = addr;
211 ppc_class_init_trampoline (void *vtable, guint32 *code, char *sp)
213 mono_runtime_class_init (vtable);
216 /* This is the 'bl' instruction */
219 if (((*code) >> 26) == 18) {
220 ppc_ori (code, 0, 0, 0); /* nop */
221 mono_arch_flush_icache (code, 4);
224 g_assert_not_reached ();
230 * Stack frame description when the generic trampoline is called.
232 * --------------------
234 * -------------------
235 * Saved FP registers 0-13
236 * -------------------
237 * Saved general registers 0-12
238 * -------------------
239 * param area for 3 args to ppc_magic_trampoline
240 * -------------------
242 * -------------------
245 create_trampoline_code (MonoTrampolineType tramp_type)
247 guint8 *buf, *code = NULL;
248 static guint8* generic_jump_trampoline = NULL;
249 static guint8 *generic_class_init_trampoline = NULL;
252 switch (tramp_type) {
253 case MONO_TRAMPOLINE_GENERIC:
254 if (mono_generic_trampoline_code)
255 return mono_generic_trampoline_code;
257 case MONO_TRAMPOLINE_JUMP:
258 if (generic_jump_trampoline)
259 return generic_jump_trampoline;
261 case MONO_TRAMPOLINE_CLASS_INIT:
262 if (generic_class_init_trampoline)
263 return generic_class_init_trampoline;
268 /* Now we'll create in 'buf' the PowerPC trampoline code. This
269 is the trampoline code common to all methods */
271 code = buf = g_malloc(512);
273 ppc_stwu (buf, ppc_r1, -STACK, ppc_r1);
275 /* start building the MonoLMF on the stack */
276 offset = STACK - sizeof (double) * MONO_SAVED_FREGS;
277 for (i = 14; i < 32; i++) {
278 ppc_stfd (buf, i, offset, ppc_r1);
279 offset += sizeof (double);
282 * now the integer registers. r13 is already saved in the trampoline,
283 * and at this point contains the method to compile, so we skip it.
285 offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs) + sizeof (gulong);
286 ppc_stmw (buf, ppc_r14, ppc_r1, offset);
288 /* Now save the rest of the registers below the MonoLMF struct, first 14
289 * fp regs and then the 13 gregs.
291 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double));
292 for (i = 0; i < 14; i++) {
293 ppc_stfd (buf, i, offset, ppc_r1);
294 offset += sizeof (double);
296 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
297 for (i = 0; i < 13; i++) {
298 ppc_stw (buf, i, offset, ppc_r1);
299 offset += sizeof (gulong);
301 /* we got here through a jump to the ctr reg, we must save the lr
302 * in the parent frame (we do it here to reduce the size of the
303 * method-specific trampoline)
305 ppc_mflr (buf, ppc_r0);
306 ppc_stw (buf, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
308 /* ok, now we can continue with the MonoLMF setup, mostly untouched
309 * from emit_prolog in mini-ppc.c
311 ppc_load (buf, ppc_r0, mono_get_lmf_addr);
312 ppc_mtlr (buf, ppc_r0);
314 /* we build the MonoLMF structure on the stack - see mini-ppc.h
315 * The pointer to the struct is put in ppc_r11.
317 ppc_addi (buf, ppc_r11, ppc_sp, STACK - sizeof (MonoLMF));
318 ppc_stw (buf, ppc_r3, G_STRUCT_OFFSET(MonoLMF, lmf_addr), ppc_r11);
319 /* new_lmf->previous_lmf = *lmf_addr */
320 ppc_lwz (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r3);
321 ppc_stw (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r11);
322 /* *(lmf_addr) = r11 */
323 ppc_stw (buf, ppc_r11, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r3);
324 /* save method info (it's in r13) */
325 ppc_stw (buf, ppc_r13, G_STRUCT_OFFSET(MonoLMF, method), ppc_r11);
326 ppc_stw (buf, ppc_sp, G_STRUCT_OFFSET(MonoLMF, ebp), ppc_r11);
327 /* save the IP (caller ip) */
328 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
329 ppc_li (buf, ppc_r0, 0);
331 ppc_lwz (buf, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
333 ppc_stw (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, eip), ppc_r11);
336 * Now we're ready to call ppc_magic_trampoline ().
338 /* Arg 1: MonoMethod *method. It was put in r13 */
339 ppc_mr (buf, ppc_r3, ppc_r13);
341 /* Arg 2: code (next address to the instruction that called us) */
342 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
343 ppc_li (buf, ppc_r4, 0);
345 ppc_lwz (buf, ppc_r4, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
348 /* Arg 3: stack pointer so that the magic trampoline can access the
349 * registers we saved above
351 ppc_mr (buf, ppc_r5, ppc_r1);
353 if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
354 ppc_lis (buf, ppc_r0, (guint32) ppc_class_init_trampoline >> 16);
355 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_class_init_trampoline & 0xffff);
357 ppc_lis (buf, ppc_r0, (guint32) ppc_magic_trampoline >> 16);
358 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_magic_trampoline & 0xffff);
360 ppc_mtlr (buf, ppc_r0);
363 /* OK, code address is now on r3. Move it to the counter reg
364 * so it will be ready for the final jump: this is safe since we
365 * won't do any more calls.
367 ppc_mtctr (buf, ppc_r3);
370 * Now we restore the MonoLMF (see emit_epilogue in mini-ppc.c)
371 * and the rest of the registers, so the method called will see
372 * the same state as before we executed.
373 * The pointer to MonoLMF is in ppc_r11.
375 ppc_addi (buf, ppc_r11, ppc_r1, STACK - sizeof (MonoLMF));
376 /* r5 = previous_lmf */
377 ppc_lwz (buf, ppc_r5, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r11);
379 ppc_lwz (buf, ppc_r6, G_STRUCT_OFFSET(MonoLMF, lmf_addr), ppc_r11);
380 /* *(lmf_addr) = previous_lmf */
381 ppc_stw (buf, ppc_r5, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r6);
382 /* restore iregs: this time include r13 */
383 ppc_lmw (buf, ppc_r13, ppc_r11, G_STRUCT_OFFSET(MonoLMF, iregs));
385 for (i = 14; i < 32; i++) {
386 ppc_lfd (buf, i, G_STRUCT_OFFSET(MonoLMF, fregs) + ((i-14) * sizeof (gdouble)), ppc_r11);
389 /* restore the volatile registers, we skip r1, of course */
390 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double));
391 for (i = 0; i < 14; i++) {
392 ppc_lfd (buf, i, offset, ppc_r1);
393 offset += sizeof (double);
395 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
396 ppc_lwz (buf, ppc_r0, offset, ppc_r1);
397 offset += 2 * sizeof (gulong);
398 for (i = 2; i < 13; i++) {
399 ppc_lwz (buf, i, offset, ppc_r1);
400 offset += sizeof (gulong);
403 /* Non-standard function epilogue. Instead of doing a proper
404 * return, we just hump to the compiled code.
406 /* Restore stack pointer and LR and jump to the code */
407 ppc_lwz (buf, ppc_r1, 0, ppc_r1);
408 ppc_lwz (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
409 ppc_mtlr (buf, ppc_r11);
410 ppc_bcctr (buf, 20, 0);
412 /* Flush instruction cache, since we've generated code */
413 mono_arch_flush_icache (code, buf - code);
416 g_assert ((buf - code) <= 512);
419 switch (tramp_type) {
420 case MONO_TRAMPOLINE_GENERIC:
421 mono_generic_trampoline_code = code;
423 case MONO_TRAMPOLINE_JUMP:
424 generic_jump_trampoline = code;
426 case MONO_TRAMPOLINE_CLASS_INIT:
427 generic_class_init_trampoline = code;
435 create_specific_tramp (MonoMethod *method, guint8* tramp, MonoDomain *domain) {
439 mono_domain_lock (domain);
440 code = buf = mono_code_manager_reserve (domain->code_mp, 32);
441 mono_domain_unlock (domain);
443 /* Save r13 in the place it will have in the on-stack MonoLMF */
444 ppc_stw (buf, ppc_r13, -(MONO_SAVED_FREGS * 8 + MONO_SAVED_GREGS * sizeof (gpointer)), ppc_r1);
446 /* Prepare the jump to the generic trampoline code.*/
447 ppc_lis (buf, ppc_r13, (guint32) tramp >> 16);
448 ppc_ori (buf, ppc_r13, ppc_r13, (guint32) tramp & 0xffff);
449 ppc_mtctr (buf, ppc_r13);
451 /* And finally put 'method' in r13 and fly! */
452 ppc_lis (buf, ppc_r13, (guint32) method >> 16);
453 ppc_ori (buf, ppc_r13, ppc_r13, (guint32) method & 0xffff);
454 ppc_bcctr (buf, 20, 0);
456 /* Flush instruction cache, since we've generated code */
457 mono_arch_flush_icache (code, buf - code);
459 g_assert ((buf - code) <= 32);
461 ji = g_new0 (MonoJitInfo, 1);
463 ji->code_start = code;
464 ji->code_size = buf - code;
466 mono_jit_stats.method_trampolines++;
472 mono_arch_create_jump_trampoline (MonoMethod *method)
475 MonoDomain* domain = mono_domain_get ();
477 tramp = create_trampoline_code (MONO_TRAMPOLINE_JUMP);
478 return create_specific_tramp (method, tramp, domain);
482 * arch_create_jit_trampoline:
483 * @method: pointer to the method info
485 * Creates a trampoline function for virtual methods. If the created
486 * code is called it first starts JIT compilation of method,
487 * and then calls the newly created method. It also replaces the
488 * corresponding vtable entry (see ppc_magic_trampoline).
490 * A trampoline consists of two parts: a main fragment, shared by all method
491 * trampolines, and some code specific to each method, which hard-codes a
492 * reference to that method and then calls the main fragment.
494 * The main fragment contains a call to 'ppc_magic_trampoline', which performs
495 * call to the JIT compiler and substitutes the method-specific fragment with
496 * some code that directly calls the JIT-compiled method.
498 * Returns: a pointer to the newly created code
501 mono_arch_create_jit_trampoline (MonoMethod *method)
505 MonoDomain* domain = mono_domain_get ();
508 tramp = create_trampoline_code (MONO_TRAMPOLINE_GENERIC);
509 /* FIXME: should pass the domain down to this function */
510 ji = create_specific_tramp (method, tramp, domain);
511 code_start = ji->code_start;
518 * mono_arch_create_class_init_trampoline:
519 * @vtable: the type to initialize
521 * Creates a trampoline function to run a type initializer.
522 * If the trampoline is called, it calls mono_runtime_class_init with the
523 * given vtable, then patches the caller code so it does not get called any
526 * Returns: a pointer to the newly created code
529 mono_arch_create_class_init_trampoline (MonoVTable *vtable)
531 guint8 *code, *buf, *tramp;
533 tramp = create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
535 /* This is the method-specific part of the trampoline. Its purpose is
536 to provide the generic part with the MonoMethod *method pointer. We'll
537 use r11 to keep that value, for instance. However, the generic part of
538 the trampoline relies on r11 having the same value it had before coming
539 here, so we must save it before. */
540 //code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
541 mono_domain_lock (vtable->domain);
542 code = buf = mono_code_manager_reserve (vtable->domain->code_mp, METHOD_TRAMPOLINE_SIZE);
543 mono_domain_unlock (vtable->domain);
545 ppc_mflr (buf, ppc_r4);
546 ppc_stw (buf, ppc_r4, PPC_RET_ADDR_OFFSET, ppc_sp);
547 ppc_stwu (buf, ppc_sp, -64, ppc_sp);
548 ppc_load (buf, ppc_r3, vtable);
549 ppc_load (buf, ppc_r5, 0);
551 ppc_load (buf, ppc_r0, ppc_class_init_trampoline);
552 ppc_mtlr (buf, ppc_r0);
555 ppc_lwz (buf, ppc_r0, 64 + PPC_RET_ADDR_OFFSET, ppc_sp);
556 ppc_mtlr (buf, ppc_r0);
557 ppc_addic (buf, ppc_sp, ppc_sp, 64);
560 /* Flush instruction cache, since we've generated code */
561 mono_arch_flush_icache (code, buf - code);
564 g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
566 mono_jit_stats.method_trampolines++;
572 * This method is only called when running in the Mono Debugger.
575 mono_debugger_create_notification_function (gpointer *notification_address)
579 ptr = buf = g_malloc0 (16);
581 if (notification_address)
582 *notification_address = buf;