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 * get_unbox_trampoline:
27 * @addr: pointer to native code for @m
29 * when value type methods are called through the vtable we need to unbox the
30 * this argument. This method returns a pointer to a trampoline which does
31 * unboxing before calling the method
34 get_unbox_trampoline (MonoMethod *m, gpointer addr)
39 if (!mono_method_signature (m)->ret->byref && MONO_TYPE_ISSTRUCT (mono_method_signature (m)->ret))
42 start = code = g_malloc (20);
44 ppc_load (code, ppc_r0, addr);
45 ppc_mtctr (code, ppc_r0);
46 ppc_addi (code, this_pos, this_pos, sizeof (MonoObject));
47 ppc_bcctr (code, 20, 0);
48 mono_arch_flush_icache (start, code - start);
49 g_assert ((code - start) <= 20);
50 /*g_print ("unbox trampoline at %d for %s:%s\n", this_pos, m->klass->name, m->name);
51 g_print ("unbox code is at %p for method at %p\n", start, addr);*/
56 /* Stack size for trampoline function
57 * PPC_MINIMAL_STACK_SIZE + 16 (args + alignment to ppc_magic_trampoline)
58 * + MonoLMF + 14 fp regs + 13 gregs + alignment
59 * #define STACK (PPC_MINIMAL_STACK_SIZE + 4 * sizeof (gulong) + sizeof (MonoLMF) + 14 * sizeof (double) + 13 * (sizeof (gulong)))
60 * STACK would be 444 for 32 bit darwin
64 /* Method-specific trampoline code fragment size */
65 #define METHOD_TRAMPOLINE_SIZE 64
67 /* Jump-specific trampoline code fragment size */
68 #define JUMP_TRAMPOLINE_SIZE 64
71 * ppc_magic_trampoline:
72 * @code: pointer into caller code
73 * @method: the method to translate
76 * This method is called by the function 'arch_create_jit_trampoline', which in
77 * turn is called by the trampoline functions for virtual methods.
78 * After having called the JIT compiler to compile the method, it inspects the
79 * caller code to find the address of the method-specific part of the
80 * trampoline vtable slot for this method, updates it with a fragment that calls
81 * the newly compiled code and returns this address of the compiled code to
82 * 'arch_create_jit_trampoline'
85 ppc_magic_trampoline (MonoMethod *method, guint32 *code, char *sp)
89 MonoJitInfo *ji, *target_ji;
92 addr = mono_compile_method(method);
93 /*g_print ("method code at %p for %s:%s\n", addr, method->klass->name, method->name);*/
100 /* We can't trampoline across domains */
101 ji = mono_jit_info_table_find (mono_domain_get (), code);
102 target_ji = mono_jit_info_table_find (mono_domain_get (), addr);
103 if (!mono_method_same_domain (ji, target_ji))
106 /* Locate the address of the method-specific trampoline. The call using
107 the vtable slot that took the processing flow to 'arch_create_jit_trampoline'
108 looks something like this:
110 mtlr rA ; Move rA (a register containing the
111 ; target address) to LR
112 blrl ; Call function at LR
114 PowerPC instructions are 32-bit long, which means that a 32-bit target
115 address cannot be encoded as an immediate value (because we already
116 have spent some bits to encode the branch instruction!). That's why a
117 'b'ranch to the contents of the 'l'ink 'r'egister (with 'l'ink register
118 update) is needed, instead of a simpler 'branch immediate'. This
119 complicates our purpose here, because 'blrl' overwrites LR, which holds
120 the value we're interested in.
122 Therefore, we need to locate the 'mtlr rA' instruction to know which
123 register LR was loaded from, and then retrieve the value from that
126 /* This is the 'blrl' instruction */
130 * Note that methods are called also with the bl opcode.
132 if (((*code) >> 26) == 18) {
133 /*g_print ("direct patching\n");*/
134 ppc_patch ((char*)code, addr);
135 mono_arch_flush_icache ((char*)code, 4);
139 /* Sanity check: instruction must be 'blrl' */
140 g_assert(*code == 0x4e800021);
142 /* the thunk-less direct call sequence: lis/ori/mtlr/blrl */
143 if ((code [-1] >> 26) == 31 && (code [-2] >> 26) == 24 && (code [-3] >> 26) == 15) {
144 ppc_patch ((char*)code, addr);
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) {
154 /* Here we are: we reached the 'mtlr rA'.
155 Extract the register from the instruction */
156 reg = (*code & 0x03e00000) >> 21;
158 /* ok, this is a lwz reg, offset (vtreg)
159 * it is emitted with:
160 * ppc_emit32 (c, (32 << 26) | ((D) << 21) | ((a) << 16) | (guint16)(d))
162 soff = (*code & 0xffff);
164 reg = (*code >> 16) & 0x1f;
165 g_assert (reg != ppc_r1);
166 /*g_print ("patching reg is %d\n", reg);*/
168 /* saved in the MonoLMF structure */
169 reg_offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs);
170 reg_offset += (reg - 13) * sizeof (gulong);
172 /* saved in the stack, see frame diagram below */
173 reg_offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
174 reg_offset += reg * sizeof (gulong);
176 /* o contains now the value of register reg */
177 o = *((char**) (sp + reg_offset));
182 /* this is not done for non-virtual calls, because in that case
183 we won't have an object, but the actual pointer to the
184 valuetype as the this argument
186 if (method->klass->valuetype && !mono_aot_is_got_entry (code, o))
187 addr = get_unbox_trampoline (method, addr);
190 if (mono_aot_is_got_entry (code, o) || mono_domain_owns_vtable_slot (mono_domain_get (), o))
191 *((gpointer *)o) = addr;
196 ppc_class_init_trampoline (void *vtable, guint32 *code, char *sp)
198 mono_runtime_class_init (vtable);
201 /* This is the 'bl' instruction */
204 if (((*code) >> 26) == 18) {
205 ppc_ori (code, 0, 0, 0); /* nop */
206 mono_arch_flush_icache (code, 4);
209 g_assert_not_reached ();
215 * Stack frame description when the generic trampoline is called.
217 * --------------------
219 * -------------------
220 * Saved FP registers 0-13
221 * -------------------
222 * Saved general registers 0-12
223 * -------------------
224 * param area for 3 args to ppc_magic_trampoline
225 * -------------------
227 * -------------------
230 mono_arch_create_trampoline_code (MonoTrampolineType tramp_type)
232 guint8 *buf, *code = NULL;
236 /* Now we'll create in 'buf' the PowerPC trampoline code. This
237 is the trampoline code common to all methods */
239 code = buf = g_malloc(512);
241 ppc_stwu (buf, ppc_r1, -STACK, ppc_r1);
243 /* start building the MonoLMF on the stack */
244 offset = STACK - sizeof (double) * MONO_SAVED_FREGS;
245 for (i = 14; i < 32; i++) {
246 ppc_stfd (buf, i, offset, ppc_r1);
247 offset += sizeof (double);
250 * now the integer registers. r13 is already saved in the trampoline,
251 * and at this point contains the method to compile, so we skip it.
253 offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs) + sizeof (gulong);
254 ppc_stmw (buf, ppc_r14, ppc_r1, offset);
256 /* Now save the rest of the registers below the MonoLMF struct, first 14
257 * fp regs and then the 13 gregs.
259 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double));
260 for (i = 0; i < 14; i++) {
261 ppc_stfd (buf, i, offset, ppc_r1);
262 offset += sizeof (double);
264 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
265 for (i = 0; i < 13; i++) {
266 ppc_stw (buf, i, offset, ppc_r1);
267 offset += sizeof (gulong);
269 /* we got here through a jump to the ctr reg, we must save the lr
270 * in the parent frame (we do it here to reduce the size of the
271 * method-specific trampoline)
273 ppc_mflr (buf, ppc_r0);
274 ppc_stw (buf, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
276 /* ok, now we can continue with the MonoLMF setup, mostly untouched
277 * from emit_prolog in mini-ppc.c
279 ppc_load (buf, ppc_r0, mono_get_lmf_addr);
280 ppc_mtlr (buf, ppc_r0);
282 /* we build the MonoLMF structure on the stack - see mini-ppc.h
283 * The pointer to the struct is put in ppc_r11.
285 ppc_addi (buf, ppc_r11, ppc_sp, STACK - sizeof (MonoLMF));
286 ppc_stw (buf, ppc_r3, G_STRUCT_OFFSET(MonoLMF, lmf_addr), ppc_r11);
287 /* new_lmf->previous_lmf = *lmf_addr */
288 ppc_lwz (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r3);
289 ppc_stw (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r11);
290 /* *(lmf_addr) = r11 */
291 ppc_stw (buf, ppc_r11, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r3);
292 /* save method info (it's in r13) */
293 ppc_stw (buf, ppc_r13, G_STRUCT_OFFSET(MonoLMF, method), ppc_r11);
294 ppc_stw (buf, ppc_sp, G_STRUCT_OFFSET(MonoLMF, ebp), ppc_r11);
295 /* save the IP (caller ip) */
296 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
297 ppc_li (buf, ppc_r0, 0);
299 ppc_lwz (buf, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
301 ppc_stw (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, eip), ppc_r11);
304 * Now we're ready to call ppc_magic_trampoline ().
306 /* Arg 1: MonoMethod *method. It was put in r13 */
307 ppc_mr (buf, ppc_r3, ppc_r13);
309 /* Arg 2: code (next address to the instruction that called us) */
310 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
311 ppc_li (buf, ppc_r4, 0);
313 ppc_lwz (buf, ppc_r4, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
316 /* Arg 3: stack pointer so that the magic trampoline can access the
317 * registers we saved above
319 ppc_mr (buf, ppc_r5, ppc_r1);
321 if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
322 ppc_lis (buf, ppc_r0, (guint32) ppc_class_init_trampoline >> 16);
323 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_class_init_trampoline & 0xffff);
325 ppc_lis (buf, ppc_r0, (guint32) ppc_magic_trampoline >> 16);
326 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_magic_trampoline & 0xffff);
328 ppc_mtlr (buf, ppc_r0);
331 /* OK, code address is now on r3. Move it to the counter reg
332 * so it will be ready for the final jump: this is safe since we
333 * won't do any more calls.
335 ppc_mtctr (buf, ppc_r3);
338 * Now we restore the MonoLMF (see emit_epilogue in mini-ppc.c)
339 * and the rest of the registers, so the method called will see
340 * the same state as before we executed.
341 * The pointer to MonoLMF is in ppc_r11.
343 ppc_addi (buf, ppc_r11, ppc_r1, STACK - sizeof (MonoLMF));
344 /* r5 = previous_lmf */
345 ppc_lwz (buf, ppc_r5, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r11);
347 ppc_lwz (buf, ppc_r6, G_STRUCT_OFFSET(MonoLMF, lmf_addr), ppc_r11);
348 /* *(lmf_addr) = previous_lmf */
349 ppc_stw (buf, ppc_r5, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r6);
350 /* restore iregs: this time include r13 */
351 ppc_lmw (buf, ppc_r13, ppc_r11, G_STRUCT_OFFSET(MonoLMF, iregs));
353 for (i = 14; i < 32; i++) {
354 ppc_lfd (buf, i, G_STRUCT_OFFSET(MonoLMF, fregs) + ((i-14) * sizeof (gdouble)), ppc_r11);
357 /* restore the volatile registers, we skip r1, of course */
358 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double));
359 for (i = 0; i < 14; i++) {
360 ppc_lfd (buf, i, offset, ppc_r1);
361 offset += sizeof (double);
363 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
364 ppc_lwz (buf, ppc_r0, offset, ppc_r1);
365 offset += 2 * sizeof (gulong);
366 for (i = 2; i < 13; i++) {
367 ppc_lwz (buf, i, offset, ppc_r1);
368 offset += sizeof (gulong);
371 /* Non-standard function epilogue. Instead of doing a proper
372 * return, we just hump to the compiled code.
374 /* Restore stack pointer and LR and jump to the code */
375 ppc_lwz (buf, ppc_r1, 0, ppc_r1);
376 ppc_lwz (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
377 ppc_mtlr (buf, ppc_r11);
378 ppc_bcctr (buf, 20, 0);
380 /* Flush instruction cache, since we've generated code */
381 mono_arch_flush_icache (code, buf - code);
384 g_assert ((buf - code) <= 512);
391 create_specific_tramp (MonoMethod *method, guint8* tramp, MonoDomain *domain) {
395 mono_domain_lock (domain);
396 code = buf = mono_code_manager_reserve (domain->code_mp, 32);
397 mono_domain_unlock (domain);
399 /* Save r13 in the place it will have in the on-stack MonoLMF */
400 ppc_stw (buf, ppc_r13, -(MONO_SAVED_FREGS * 8 + MONO_SAVED_GREGS * sizeof (gpointer)), ppc_r1);
402 /* Prepare the jump to the generic trampoline code.*/
403 ppc_lis (buf, ppc_r13, (guint32) tramp >> 16);
404 ppc_ori (buf, ppc_r13, ppc_r13, (guint32) tramp & 0xffff);
405 ppc_mtctr (buf, ppc_r13);
407 /* And finally put 'method' in r13 and fly! */
408 ppc_lis (buf, ppc_r13, (guint32) method >> 16);
409 ppc_ori (buf, ppc_r13, ppc_r13, (guint32) method & 0xffff);
410 ppc_bcctr (buf, 20, 0);
412 /* Flush instruction cache, since we've generated code */
413 mono_arch_flush_icache (code, buf - code);
415 g_assert ((buf - code) <= 32);
417 ji = g_new0 (MonoJitInfo, 1);
419 ji->code_start = code;
420 ji->code_size = buf - code;
422 mono_jit_stats.method_trampolines++;
428 mono_arch_create_jump_trampoline (MonoMethod *method)
431 MonoDomain* domain = mono_domain_get ();
433 tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_JUMP);
434 return create_specific_tramp (method, tramp, domain);
438 * arch_create_jit_trampoline:
439 * @method: pointer to the method info
441 * Creates a trampoline function for virtual methods. If the created
442 * code is called it first starts JIT compilation of method,
443 * and then calls the newly created method. It also replaces the
444 * corresponding vtable entry (see ppc_magic_trampoline).
446 * A trampoline consists of two parts: a main fragment, shared by all method
447 * trampolines, and some code specific to each method, which hard-codes a
448 * reference to that method and then calls the main fragment.
450 * The main fragment contains a call to 'ppc_magic_trampoline', which performs
451 * call to the JIT compiler and substitutes the method-specific fragment with
452 * some code that directly calls the JIT-compiled method.
454 * Returns: a pointer to the newly created code
457 mono_arch_create_jit_trampoline (MonoMethod *method)
461 MonoDomain* domain = mono_domain_get ();
464 tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_GENERIC);
465 /* FIXME: should pass the domain down to this function */
466 ji = create_specific_tramp (method, tramp, domain);
467 code_start = ji->code_start;
474 * mono_arch_create_class_init_trampoline:
475 * @vtable: the type to initialize
477 * Creates a trampoline function to run a type initializer.
478 * If the trampoline is called, it calls mono_runtime_class_init with the
479 * given vtable, then patches the caller code so it does not get called any
482 * Returns: a pointer to the newly created code
485 mono_arch_create_class_init_trampoline (MonoVTable *vtable)
487 guint8 *code, *buf, *tramp;
489 tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
491 /* This is the method-specific part of the trampoline. Its purpose is
492 to provide the generic part with the MonoMethod *method pointer. We'll
493 use r11 to keep that value, for instance. However, the generic part of
494 the trampoline relies on r11 having the same value it had before coming
495 here, so we must save it before. */
496 //code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
497 mono_domain_lock (vtable->domain);
498 code = buf = mono_code_manager_reserve (vtable->domain->code_mp, METHOD_TRAMPOLINE_SIZE);
499 mono_domain_unlock (vtable->domain);
501 ppc_mflr (buf, ppc_r4);
502 ppc_stw (buf, ppc_r4, PPC_RET_ADDR_OFFSET, ppc_sp);
503 ppc_stwu (buf, ppc_sp, -64, ppc_sp);
504 ppc_load (buf, ppc_r3, vtable);
505 ppc_load (buf, ppc_r5, 0);
507 ppc_load (buf, ppc_r0, ppc_class_init_trampoline);
508 ppc_mtlr (buf, ppc_r0);
511 ppc_lwz (buf, ppc_r0, 64 + PPC_RET_ADDR_OFFSET, ppc_sp);
512 ppc_mtlr (buf, ppc_r0);
513 ppc_addic (buf, ppc_sp, ppc_sp, 64);
516 /* Flush instruction cache, since we've generated code */
517 mono_arch_flush_icache (code, buf - code);
520 g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
522 mono_jit_stats.method_trampolines++;
528 * This method is only called when running in the Mono Debugger.
531 mono_debugger_create_notification_function (gpointer *notification_address)
535 ptr = buf = g_malloc0 (16);
537 if (notification_address)
538 *notification_address = buf;
540 mono_arch_flush_icache (ptr, buf - ptr);