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