8ba288308458f85ed7c4b3388edb14c306dd74e7
[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 #include <mono/metadata/mono-debug-debugger.h>
20
21 #include "mini.h"
22 #include "mini-ppc.h"
23
24 typedef enum {
25         MONO_TRAMPOLINE_GENERIC,
26         MONO_TRAMPOLINE_JUMP,
27         MONO_TRAMPOLINE_CLASS_INIT
28 } MonoTrampolineType;
29
30 /* adapt to mini later... */
31 #define mono_jit_share_code (1)
32
33 /*
34  * Address of the x86 trampoline code.  This is used by the debugger to check
35  * whether a method is a trampoline.
36  */
37 guint8 *mono_generic_trampoline_code = NULL;
38
39 /*
40  * get_unbox_trampoline:
41  * @m: method pointer
42  * @addr: pointer to native code for @m
43  *
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
47  */
48 static gpointer
49 get_unbox_trampoline (MonoMethod *m, gpointer addr)
50 {
51         guint8 *code, *start;
52         int this_pos = 3;
53
54         if (!mono_method_signature (m)->ret->byref && MONO_TYPE_ISSTRUCT (mono_method_signature (m)->ret))
55                 this_pos = 4;
56             
57         start = code = g_malloc (20);
58
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);*/
67
68         return start;
69 }
70
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
76  */
77 #define STACK (448)
78
79 /* Method-specific trampoline code fragment size */
80 #define METHOD_TRAMPOLINE_SIZE 64
81
82 /* Jump-specific trampoline code fragment size */
83 #define JUMP_TRAMPOLINE_SIZE   64
84
85 /**
86  * ppc_magic_trampoline:
87  * @code: pointer into caller code
88  * @method: the method to translate
89  * @sp: stack pointer
90  *
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' 
98  */
99 static gpointer
100 ppc_magic_trampoline (MonoMethod *method, guint32 *code, char *sp)
101 {
102         char *o = NULL;
103         gpointer addr;
104         MonoJitInfo *ji, *target_ji;
105         int reg, offset = 0;
106
107         addr = mono_compile_method(method);
108         /*g_print ("method code at %p for %s:%s\n", addr, method->klass->name, method->name);*/
109         g_assert(addr);
110
111         if (!code){
112                 return addr;
113         }
114
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))
119                 return addr;
120
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:
124         
125                 mtlr rA                 ; Move rA (a register containing the
126                                         ; target address) to LR
127                 blrl                    ; Call function at LR
128         
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.
136         
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
139         register */
140         
141         /* This is the 'blrl' instruction */
142         --code;
143         
144         /*
145          * Note that methods are called also with the bl opcode.
146          */
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);
151                 return addr;
152         }
153         
154         /* Sanity check: instruction must be 'blrl' */
155         g_assert(*code == 0x4e800021);
156         
157         /* OK, we're now at the 'blrl' instruction. Now walk backwards
158         till we get to a 'mtlr rA' */
159         for(; --code;) {
160                 if((*code & 0x7c0803a6) == 0x7c0803a6) {
161                         gint16 soff;
162                         gint reg_offset;
163                         /* Here we are: we reached the 'mtlr rA'.
164                         Extract the register from the instruction */
165                         reg = (*code & 0x03e00000) >> 21;
166                         --code;
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))
170                          */
171                         soff = (*code & 0xffff);
172                         offset = soff;
173                         reg = (*code >> 16) & 0x1f;
174                         g_assert (reg != ppc_r1);
175                         /*g_print ("patching reg is %d\n", reg);*/
176                         if (reg >= 13) {
177                                 /* saved in the MonoLMF structure */
178                                 reg_offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs);
179                                 reg_offset += (reg - 13) * sizeof (gulong);
180                         } else {
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);
184                         }
185                         /* o contains now the value of register reg */
186                         o = *((char**) (sp + reg_offset));
187                         break;
188                 }
189         }
190
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
194          */
195         if (method->klass->valuetype && !mono_aot_is_got_entry (code, o))
196                 addr = get_unbox_trampoline (method, addr);
197
198         o += offset;
199         if (mono_aot_is_got_entry (code, o) || mono_domain_owns_vtable_slot (mono_domain_get (), o))
200                 *((gpointer *)o) = addr;
201         return addr;
202 }
203
204 static void
205 ppc_class_init_trampoline (void *vtable, guint32 *code, char *sp)
206 {
207         mono_runtime_class_init (vtable);
208
209 #if 0
210         /* This is the 'bl' instruction */
211         --code;
212         
213         if (((*code) >> 26) == 18) {
214                 ppc_ori (code, 0, 0, 0); /* nop */
215                 mono_arch_flush_icache (code, 4);
216                 return;
217         } else {
218                 g_assert_not_reached ();
219         }
220 #endif
221 }
222
223 /*
224  * Stack frame description when the generic trampoline is called.
225  * caller frame
226  * --------------------
227  *  MonoLMF
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  *  -------------------
235  *  linkage area
236  *  -------------------
237  */
238 static guchar*
239 create_trampoline_code (MonoTrampolineType tramp_type)
240 {
241         guint8 *buf, *code = NULL;
242         static guint8* generic_jump_trampoline = NULL;
243         static guint8 *generic_class_init_trampoline = NULL;
244         int i, offset;
245
246         switch (tramp_type) {
247         case MONO_TRAMPOLINE_GENERIC:
248                 if (mono_generic_trampoline_code)
249                         return mono_generic_trampoline_code;
250                 break;
251         case MONO_TRAMPOLINE_JUMP:
252                 if (generic_jump_trampoline)
253                         return generic_jump_trampoline;
254                 break;
255         case MONO_TRAMPOLINE_CLASS_INIT:
256                 if (generic_class_init_trampoline)
257                         return generic_class_init_trampoline;
258                 break;
259         }
260
261         if(!code) {
262                 /* Now we'll create in 'buf' the PowerPC trampoline code. This
263                  is the trampoline code common to all methods  */
264                 
265                 code = buf = g_malloc(512);
266                 
267                 ppc_stwu (buf, ppc_r1, -STACK, ppc_r1);
268
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);
274                 }
275                 /* 
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.
278                  */
279                 offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs) + sizeof (gulong);
280                 ppc_stmw (buf, ppc_r14, ppc_r1, offset);
281
282                 /* Now save the rest of the registers below the MonoLMF struct, first 14
283                  * fp regs and then the 13 gregs.
284                  */
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);
289                 }
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);
294                 }
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)
298                  */
299                 ppc_mflr (buf, ppc_r0);
300                 ppc_stw (buf, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
301
302                 /* ok, now we can continue with the MonoLMF setup, mostly untouched 
303                  * from emit_prolog in mini-ppc.c
304                  */
305                 ppc_load (buf, ppc_r0, mono_get_lmf_addr);
306                 ppc_mtlr (buf, ppc_r0);
307                 ppc_blrl (buf);
308                 /* we build the MonoLMF structure on the stack - see mini-ppc.h
309                  * The pointer to the struct is put in ppc_r11.
310                  */
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);
324                 } else {
325                         ppc_lwz (buf, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
326                 }
327                 ppc_stw (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, eip), ppc_r11);
328
329                 /*
330                  * Now we're ready to call ppc_magic_trampoline ().
331                  */
332                 /* Arg 1: MonoMethod *method. It was put in r13 */
333                 ppc_mr  (buf, ppc_r3, ppc_r13);
334                 
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);
338                 } else {
339                         ppc_lwz  (buf, ppc_r4, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
340                 }
341                 
342                 /* Arg 3: stack pointer so that the magic trampoline can access the
343                  * registers we saved above
344                  */
345                 ppc_mr   (buf, ppc_r5, ppc_r1);
346                 
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);
350                 } else {
351                         ppc_lis  (buf, ppc_r0, (guint32) ppc_magic_trampoline >> 16);
352                         ppc_ori  (buf, ppc_r0, ppc_r0, (guint32) ppc_magic_trampoline & 0xffff);
353                 }
354                 ppc_mtlr (buf, ppc_r0);
355                 ppc_blrl (buf);
356                 
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.
360                  */
361                 ppc_mtctr (buf, ppc_r3);
362
363                 /*
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.
368                  */
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);
372                 /* r6 = lmf_addr */
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));
378                 /* restore fregs */
379                 for (i = 14; i < 32; i++) {
380                         ppc_lfd (buf, i, G_STRUCT_OFFSET(MonoLMF, fregs) + ((i-14) * sizeof (gdouble)), ppc_r11);
381                 }
382
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);
388                 }
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);
395                 }
396
397                 /* Non-standard function epilogue. Instead of doing a proper
398                  * return, we just hump to the compiled code.
399                  */
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);
405
406                 /* Flush instruction cache, since we've generated code */
407                 mono_arch_flush_icache (code, buf - code);
408         
409                 /* Sanity check */
410                 g_assert ((buf - code) <= 512);
411         }
412
413         switch (tramp_type) {
414         case MONO_TRAMPOLINE_GENERIC:
415                 mono_generic_trampoline_code = code;
416                 break;
417         case MONO_TRAMPOLINE_JUMP:
418                 generic_jump_trampoline = code;
419                 break;
420         case MONO_TRAMPOLINE_CLASS_INIT:
421                 generic_class_init_trampoline = code;
422                 break;
423         }
424
425         return code;
426 }
427
428 static MonoJitInfo*
429 create_specific_tramp (MonoMethod *method, guint8* tramp, MonoDomain *domain) {
430         guint8 *code, *buf;
431         MonoJitInfo *ji;
432
433         mono_domain_lock (domain);
434         code = buf = mono_code_manager_reserve (domain->code_mp, 32);
435         mono_domain_unlock (domain);
436
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);
439         
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);
444         
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);
449         
450         /* Flush instruction cache, since we've generated code */
451         mono_arch_flush_icache (code, buf - code);
452
453         g_assert ((buf - code) <= 32);
454
455         ji = g_new0 (MonoJitInfo, 1);
456         ji->method = method;
457         ji->code_start = code;
458         ji->code_size = buf - code;
459
460         mono_jit_stats.method_trampolines++;
461
462         return ji;
463 }
464
465 MonoJitInfo*
466 mono_arch_create_jump_trampoline (MonoMethod *method)
467 {
468         guint8 *tramp;
469         MonoDomain* domain = mono_domain_get ();
470         
471         tramp = create_trampoline_code (MONO_TRAMPOLINE_JUMP);
472         return create_specific_tramp (method, tramp, domain);
473 }
474
475 /**
476  * arch_create_jit_trampoline:
477  * @method: pointer to the method info
478  *
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).
483  *
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.
487  *
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.
491  * 
492  * Returns: a pointer to the newly created code 
493  */
494 gpointer
495 mono_arch_create_jit_trampoline (MonoMethod *method)
496 {
497         guint8 *tramp;
498         MonoJitInfo *ji;
499         MonoDomain* domain = mono_domain_get ();
500         gpointer code_start;
501
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;
506         g_free (ji);
507
508         return code_start;
509 }
510
511 /**
512  * mono_arch_create_class_init_trampoline:
513  *  @vtable: the type to initialize
514  *
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
518  * more.
519  * 
520  * Returns: a pointer to the newly created code 
521  */
522 gpointer
523 mono_arch_create_class_init_trampoline (MonoVTable *vtable)
524 {
525         guint8 *code, *buf, *tramp;
526
527         tramp = create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
528
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);
538
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);
544
545         ppc_load (buf, ppc_r0, ppc_class_init_trampoline);
546         ppc_mtlr (buf, ppc_r0);
547         ppc_blrl (buf);
548
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);
552         ppc_blr (buf);
553
554         /* Flush instruction cache, since we've generated code */
555         mono_arch_flush_icache (code, buf - code);
556                 
557         /* Sanity check */
558         g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
559
560         mono_jit_stats.method_trampolines++;
561
562         return code;
563 }
564
565 /*
566  * This method is only called when running in the Mono Debugger.
567  */
568 gpointer
569 mono_debugger_create_notification_function (gpointer *notification_address)
570 {
571         guint8 *ptr, *buf;
572
573         ptr = buf = g_malloc0 (16);
574         ppc_break (buf);
575         if (notification_address)
576                 *notification_address = buf;
577         ppc_blr (buf);
578
579         return ptr;
580 }
581