* mini-s390[x].c (is_regsize_var): Support PTR/FNPTR too.
[mono.git] / mono / mini / tramp-ppc.c
blobe5e59de1f49e45134e8b7c78998fc37312dcab53
1 /*
2 * tramp-ppc.c: JIT trampoline code for PowerPC
4 * Authors:
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Carlos Valiente <yo@virutass.net>
9 * (C) 2001 Ximian, Inc.
12 #include <config.h>
13 #include <glib.h>
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>
20 #include "mini.h"
21 #include "mini-ppc.h"
24 * get_unbox_trampoline:
25 * @m: method pointer
26 * @addr: pointer to native code for @m
28 * when value type methods are called through the vtable we need to unbox the
29 * this argument. This method returns a pointer to a trampoline which does
30 * unboxing before calling the method
32 static gpointer
33 get_unbox_trampoline (MonoMethod *m, gpointer addr)
35 guint8 *code, *start;
36 int this_pos = 3;
37 MonoDomain *domain = mono_domain_get ();
39 if (!mono_method_signature (m)->ret->byref && MONO_TYPE_ISSTRUCT (mono_method_signature (m)->ret))
40 this_pos = 4;
42 mono_domain_lock (domain);
43 start = code = mono_code_manager_reserve (domain->code_mp, 20);
44 mono_domain_unlock (domain);
46 ppc_load (code, ppc_r0, addr);
47 ppc_mtctr (code, ppc_r0);
48 ppc_addi (code, this_pos, this_pos, sizeof (MonoObject));
49 ppc_bcctr (code, 20, 0);
50 mono_arch_flush_icache (start, code - start);
51 g_assert ((code - start) <= 20);
52 /*g_print ("unbox trampoline at %d for %s:%s\n", this_pos, m->klass->name, m->name);
53 g_print ("unbox code is at %p for method at %p\n", start, addr);*/
55 return start;
58 /* Stack size for trampoline function
59 * PPC_MINIMAL_STACK_SIZE + 16 (args + alignment to ppc_magic_trampoline)
60 * + MonoLMF + 14 fp regs + 13 gregs + alignment
61 * #define STACK (PPC_MINIMAL_STACK_SIZE + 4 * sizeof (gulong) + sizeof (MonoLMF) + 14 * sizeof (double) + 13 * (sizeof (gulong)))
62 * STACK would be 444 for 32 bit darwin
64 #define STACK (448)
66 /* Method-specific trampoline code fragment size */
67 #define METHOD_TRAMPOLINE_SIZE 64
69 /* Jump-specific trampoline code fragment size */
70 #define JUMP_TRAMPOLINE_SIZE 64
72 /**
73 * ppc_magic_trampoline:
74 * @code: pointer into caller code
75 * @method: the method to translate
76 * @sp: stack pointer
78 * This method is called by the function 'arch_create_jit_trampoline', which in
79 * turn is called by the trampoline functions for virtual methods.
80 * After having called the JIT compiler to compile the method, it inspects the
81 * caller code to find the address of the method-specific part of the
82 * trampoline vtable slot for this method, updates it with a fragment that calls
83 * the newly compiled code and returns this address of the compiled code to
84 * 'arch_create_jit_trampoline'
86 static gpointer
87 ppc_magic_trampoline (MonoMethod *method, guint32 *code, char *sp)
89 char *o = NULL;
90 gpointer addr;
91 MonoJitInfo *ji, *target_ji;
92 int reg, offset = 0;
94 addr = mono_compile_method(method);
95 /*g_print ("method code at %p for %s:%s\n", addr, method->klass->name, method->name);*/
96 g_assert(addr);
98 if (!code){
99 return addr;
102 /* We can't trampoline across domains */
103 ji = mono_jit_info_table_find (mono_domain_get (), code);
104 target_ji = mono_jit_info_table_find (mono_domain_get (), addr);
105 if (!mono_method_same_domain (ji, target_ji))
106 return addr;
108 /* Locate the address of the method-specific trampoline. The call using
109 the vtable slot that took the processing flow to 'arch_create_jit_trampoline'
110 looks something like this:
112 mtlr rA ; Move rA (a register containing the
113 ; target address) to LR
114 blrl ; Call function at LR
116 PowerPC instructions are 32-bit long, which means that a 32-bit target
117 address cannot be encoded as an immediate value (because we already
118 have spent some bits to encode the branch instruction!). That's why a
119 'b'ranch to the contents of the 'l'ink 'r'egister (with 'l'ink register
120 update) is needed, instead of a simpler 'branch immediate'. This
121 complicates our purpose here, because 'blrl' overwrites LR, which holds
122 the value we're interested in.
124 Therefore, we need to locate the 'mtlr rA' instruction to know which
125 register LR was loaded from, and then retrieve the value from that
126 register */
128 /* This is the 'blrl' instruction */
129 --code;
132 * Note that methods are called also with the bl opcode.
134 if (((*code) >> 26) == 18) {
135 /*g_print ("direct patching\n");*/
136 ppc_patch ((char*)code, addr);
137 mono_arch_flush_icache ((char*)code, 4);
138 return addr;
141 /* Sanity check: instruction must be 'blrl' */
142 g_assert(*code == 0x4e800021);
144 /* the thunk-less direct call sequence: lis/ori/mtlr/blrl */
145 if ((code [-1] >> 26) == 31 && (code [-2] >> 26) == 24 && (code [-3] >> 26) == 15) {
146 ppc_patch ((char*)code, addr);
147 return addr;
150 /* OK, we're now at the 'blrl' instruction. Now walk backwards
151 till we get to a 'mtlr rA' */
152 for(; --code;) {
153 if((*code & 0x7c0803a6) == 0x7c0803a6) {
154 gint16 soff;
155 gint reg_offset;
156 /* Here we are: we reached the 'mtlr rA'.
157 Extract the register from the instruction */
158 reg = (*code & 0x03e00000) >> 21;
159 --code;
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);
165 offset = soff;
166 reg = (*code >> 16) & 0x1f;
167 g_assert (reg != ppc_r1);
168 /*g_print ("patching reg is %d\n", reg);*/
169 if (reg >= 13) {
170 /* saved in the MonoLMF structure */
171 reg_offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs);
172 reg_offset += (reg - 13) * sizeof (gulong);
173 } else {
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));
180 break;
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 && !mono_aot_is_got_entry (code, o))
189 addr = get_unbox_trampoline (method, addr);
191 o += offset;
192 if (mono_aot_is_got_entry (code, o) || mono_domain_owns_vtable_slot (mono_domain_get (), o))
193 *((gpointer *)o) = addr;
194 return addr;
197 static void
198 ppc_class_init_trampoline (void *vtable, guint32 *code, char *sp)
200 mono_runtime_class_init (vtable);
202 #if 0
203 /* This is the 'bl' instruction */
204 --code;
206 if (((*code) >> 26) == 18) {
207 ppc_ori (code, 0, 0, 0); /* nop */
208 mono_arch_flush_icache (code, 4);
209 return;
210 } else {
211 g_assert_not_reached ();
213 #endif
217 * Stack frame description when the generic trampoline is called.
218 * caller frame
219 * --------------------
220 * MonoLMF
221 * -------------------
222 * Saved FP registers 0-13
223 * -------------------
224 * Saved general registers 0-12
225 * -------------------
226 * param area for 3 args to ppc_magic_trampoline
227 * -------------------
228 * linkage area
229 * -------------------
231 guchar*
232 mono_arch_create_trampoline_code (MonoTrampolineType tramp_type)
234 guint8 *buf, *code = NULL;
235 int i, offset;
237 if(!code) {
238 /* Now we'll create in 'buf' the PowerPC trampoline code. This
239 is the trampoline code common to all methods */
241 code = buf = mono_global_codeman_reserve (512);
243 ppc_stwu (buf, ppc_r1, -STACK, ppc_r1);
245 /* start building the MonoLMF on the stack */
246 offset = STACK - sizeof (double) * MONO_SAVED_FREGS;
247 for (i = 14; i < 32; i++) {
248 ppc_stfd (buf, i, offset, ppc_r1);
249 offset += sizeof (double);
252 * now the integer registers. r13 is already saved in the trampoline,
253 * and at this point contains the method to compile, so we skip it.
255 offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs) + sizeof (gulong);
256 ppc_stmw (buf, ppc_r14, ppc_r1, offset);
258 /* Now save the rest of the registers below the MonoLMF struct, first 14
259 * fp regs and then the 13 gregs.
261 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double));
262 for (i = 0; i < 14; i++) {
263 ppc_stfd (buf, i, offset, ppc_r1);
264 offset += sizeof (double);
266 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
267 for (i = 0; i < 13; i++) {
268 ppc_stw (buf, i, offset, ppc_r1);
269 offset += sizeof (gulong);
271 /* we got here through a jump to the ctr reg, we must save the lr
272 * in the parent frame (we do it here to reduce the size of the
273 * method-specific trampoline)
275 ppc_mflr (buf, ppc_r0);
276 ppc_stw (buf, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
278 /* ok, now we can continue with the MonoLMF setup, mostly untouched
279 * from emit_prolog in mini-ppc.c
281 ppc_load (buf, ppc_r0, mono_get_lmf_addr);
282 ppc_mtlr (buf, ppc_r0);
283 ppc_blrl (buf);
284 /* we build the MonoLMF structure on the stack - see mini-ppc.h
285 * The pointer to the struct is put in ppc_r11.
287 ppc_addi (buf, ppc_r11, ppc_sp, STACK - sizeof (MonoLMF));
288 ppc_stw (buf, ppc_r3, G_STRUCT_OFFSET(MonoLMF, lmf_addr), ppc_r11);
289 /* new_lmf->previous_lmf = *lmf_addr */
290 ppc_lwz (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r3);
291 ppc_stw (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r11);
292 /* *(lmf_addr) = r11 */
293 ppc_stw (buf, ppc_r11, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r3);
294 /* save method info (it's in r13) */
295 ppc_stw (buf, ppc_r13, G_STRUCT_OFFSET(MonoLMF, method), ppc_r11);
296 ppc_stw (buf, ppc_sp, G_STRUCT_OFFSET(MonoLMF, ebp), ppc_r11);
297 /* save the IP (caller ip) */
298 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
299 ppc_li (buf, ppc_r0, 0);
300 } else {
301 ppc_lwz (buf, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
303 ppc_stw (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, eip), ppc_r11);
306 * Now we're ready to call ppc_magic_trampoline ().
308 /* Arg 1: MonoMethod *method. It was put in r13 */
309 ppc_mr (buf, ppc_r3, ppc_r13);
311 /* Arg 2: code (next address to the instruction that called us) */
312 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
313 ppc_li (buf, ppc_r4, 0);
314 } else {
315 ppc_lwz (buf, ppc_r4, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
318 /* Arg 3: stack pointer so that the magic trampoline can access the
319 * registers we saved above
321 ppc_mr (buf, ppc_r5, ppc_r1);
323 if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
324 ppc_lis (buf, ppc_r0, (guint32) ppc_class_init_trampoline >> 16);
325 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_class_init_trampoline & 0xffff);
326 } else {
327 ppc_lis (buf, ppc_r0, (guint32) ppc_magic_trampoline >> 16);
328 ppc_ori (buf, ppc_r0, ppc_r0, (guint32) ppc_magic_trampoline & 0xffff);
330 ppc_mtlr (buf, ppc_r0);
331 ppc_blrl (buf);
333 /* OK, code address is now on r3. Move it to the counter reg
334 * so it will be ready for the final jump: this is safe since we
335 * won't do any more calls.
337 ppc_mtctr (buf, ppc_r3);
340 * Now we restore the MonoLMF (see emit_epilogue in mini-ppc.c)
341 * and the rest of the registers, so the method called will see
342 * the same state as before we executed.
343 * The pointer to MonoLMF is in ppc_r11.
345 ppc_addi (buf, ppc_r11, ppc_r1, STACK - sizeof (MonoLMF));
346 /* r5 = previous_lmf */
347 ppc_lwz (buf, ppc_r5, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r11);
348 /* r6 = lmf_addr */
349 ppc_lwz (buf, ppc_r6, G_STRUCT_OFFSET(MonoLMF, lmf_addr), ppc_r11);
350 /* *(lmf_addr) = previous_lmf */
351 ppc_stw (buf, ppc_r5, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r6);
352 /* restore iregs: this time include r13 */
353 ppc_lmw (buf, ppc_r13, ppc_r11, G_STRUCT_OFFSET(MonoLMF, iregs));
354 /* restore fregs */
355 for (i = 14; i < 32; i++) {
356 ppc_lfd (buf, i, G_STRUCT_OFFSET(MonoLMF, fregs) + ((i-14) * sizeof (gdouble)), ppc_r11);
359 /* restore the volatile registers, we skip r1, of course */
360 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double));
361 for (i = 0; i < 14; i++) {
362 ppc_lfd (buf, i, offset, ppc_r1);
363 offset += sizeof (double);
365 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
366 ppc_lwz (buf, ppc_r0, offset, ppc_r1);
367 offset += 2 * sizeof (gulong);
368 for (i = 2; i < 13; i++) {
369 ppc_lwz (buf, i, offset, ppc_r1);
370 offset += sizeof (gulong);
373 /* Non-standard function epilogue. Instead of doing a proper
374 * return, we just hump to the compiled code.
376 /* Restore stack pointer and LR and jump to the code */
377 ppc_lwz (buf, ppc_r1, 0, ppc_r1);
378 ppc_lwz (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
379 ppc_mtlr (buf, ppc_r11);
380 ppc_bcctr (buf, 20, 0);
382 /* Flush instruction cache, since we've generated code */
383 mono_arch_flush_icache (code, buf - code);
385 /* Sanity check */
386 g_assert ((buf - code) <= 512);
389 return code;
392 static MonoJitInfo*
393 create_specific_tramp (MonoMethod *method, guint8* tramp, MonoDomain *domain) {
394 guint8 *code, *buf;
395 MonoJitInfo *ji;
397 mono_domain_lock (domain);
398 code = buf = mono_code_manager_reserve (domain->code_mp, 32);
399 mono_domain_unlock (domain);
401 /* Save r13 in the place it will have in the on-stack MonoLMF */
402 ppc_stw (buf, ppc_r13, -(MONO_SAVED_FREGS * 8 + MONO_SAVED_GREGS * sizeof (gpointer)), ppc_r1);
404 /* Prepare the jump to the generic trampoline code.*/
405 ppc_lis (buf, ppc_r13, (guint32) tramp >> 16);
406 ppc_ori (buf, ppc_r13, ppc_r13, (guint32) tramp & 0xffff);
407 ppc_mtctr (buf, ppc_r13);
409 /* And finally put 'method' in r13 and fly! */
410 ppc_lis (buf, ppc_r13, (guint32) method >> 16);
411 ppc_ori (buf, ppc_r13, ppc_r13, (guint32) method & 0xffff);
412 ppc_bcctr (buf, 20, 0);
414 /* Flush instruction cache, since we've generated code */
415 mono_arch_flush_icache (code, buf - code);
417 g_assert ((buf - code) <= 32);
419 ji = g_new0 (MonoJitInfo, 1);
420 ji->method = method;
421 ji->code_start = code;
422 ji->code_size = buf - code;
424 mono_jit_stats.method_trampolines++;
426 return ji;
429 MonoJitInfo*
430 mono_arch_create_jump_trampoline (MonoMethod *method)
432 guint8 *tramp;
433 MonoDomain* domain = mono_domain_get ();
435 tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_JUMP);
436 return create_specific_tramp (method, tramp, domain);
440 * arch_create_jit_trampoline:
441 * @method: pointer to the method info
443 * Creates a trampoline function for virtual methods. If the created
444 * code is called it first starts JIT compilation of method,
445 * and then calls the newly created method. It also replaces the
446 * corresponding vtable entry (see ppc_magic_trampoline).
448 * A trampoline consists of two parts: a main fragment, shared by all method
449 * trampolines, and some code specific to each method, which hard-codes a
450 * reference to that method and then calls the main fragment.
452 * The main fragment contains a call to 'ppc_magic_trampoline', which performs
453 * call to the JIT compiler and substitutes the method-specific fragment with
454 * some code that directly calls the JIT-compiled method.
456 * Returns: a pointer to the newly created code
458 gpointer
459 mono_arch_create_jit_trampoline (MonoMethod *method)
461 guint8 *tramp;
462 MonoJitInfo *ji;
463 MonoDomain* domain = mono_domain_get ();
464 gpointer code_start;
466 tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_GENERIC);
467 /* FIXME: should pass the domain down to this function */
468 ji = create_specific_tramp (method, tramp, domain);
469 code_start = ji->code_start;
470 g_free (ji);
472 return code_start;
476 * mono_arch_create_class_init_trampoline:
477 * @vtable: the type to initialize
479 * Creates a trampoline function to run a type initializer.
480 * If the trampoline is called, it calls mono_runtime_class_init with the
481 * given vtable, then patches the caller code so it does not get called any
482 * more.
484 * Returns: a pointer to the newly created code
486 gpointer
487 mono_arch_create_class_init_trampoline (MonoVTable *vtable)
489 guint8 *code, *buf, *tramp;
491 tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
493 /* This is the method-specific part of the trampoline. Its purpose is
494 to provide the generic part with the MonoMethod *method pointer. We'll
495 use r11 to keep that value, for instance. However, the generic part of
496 the trampoline relies on r11 having the same value it had before coming
497 here, so we must save it before. */
498 mono_domain_lock (vtable->domain);
499 code = buf = mono_code_manager_reserve (vtable->domain->code_mp, METHOD_TRAMPOLINE_SIZE);
500 mono_domain_unlock (vtable->domain);
502 ppc_mflr (buf, ppc_r4);
503 ppc_stw (buf, ppc_r4, PPC_RET_ADDR_OFFSET, ppc_sp);
504 ppc_stwu (buf, ppc_sp, -64, ppc_sp);
505 ppc_load (buf, ppc_r3, vtable);
506 ppc_load (buf, ppc_r5, 0);
508 ppc_load (buf, ppc_r0, ppc_class_init_trampoline);
509 ppc_mtlr (buf, ppc_r0);
510 ppc_blrl (buf);
512 ppc_lwz (buf, ppc_r0, 64 + PPC_RET_ADDR_OFFSET, ppc_sp);
513 ppc_mtlr (buf, ppc_r0);
514 ppc_addic (buf, ppc_sp, ppc_sp, 64);
515 ppc_blr (buf);
517 /* Flush instruction cache, since we've generated code */
518 mono_arch_flush_icache (code, buf - code);
520 /* Sanity check */
521 g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
523 mono_jit_stats.method_trampolines++;
525 return code;
529 * This method is only called when running in the Mono Debugger.
531 gpointer
532 mono_debugger_create_notification_function (MonoCodeManager *codeman)
534 guint8 *ptr, *buf;
536 codeman = mono_code_manager_reserve (codeman, 16);
537 ppc_break (buf);
538 ppc_blr (buf);
539 mono_arch_flush_icache (ptr, buf - ptr);
541 return ptr;