2004-10-21 <vargaz@freemail.hu>
[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 (!m->signature->ret->byref && MONO_TYPE_ISSTRUCT (m->signature->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         int reg, offset = 0;
105
106         addr = mono_compile_method(method);
107         /*g_print ("method code at %p for %s:%s\n", addr, method->klass->name, method->name);*/
108         g_assert(addr);
109
110         if (!code){
111                 return addr;
112         }
113
114         /* Locate the address of the method-specific trampoline. The call using
115         the vtable slot that took the processing flow to 'arch_create_jit_trampoline' 
116         looks something like this:
117         
118                 mtlr rA                 ; Move rA (a register containing the
119                                         ; target address) to LR
120                 blrl                    ; Call function at LR
121         
122         PowerPC instructions are 32-bit long, which means that a 32-bit target
123         address cannot be encoded as an immediate value (because we already
124         have spent some bits to encode the branch instruction!). That's why a
125         'b'ranch to the contents of the 'l'ink 'r'egister (with 'l'ink register
126         update) is needed, instead of a simpler 'branch immediate'. This
127         complicates our purpose here, because 'blrl' overwrites LR, which holds
128         the value we're interested in.
129         
130         Therefore, we need to locate the 'mtlr rA' instruction to know which
131         register LR was loaded from, and then retrieve the value from that
132         register */
133         
134         /* This is the 'blrl' instruction */
135         --code;
136         
137         /*
138          * Note that methods are called also with the bl opcode.
139          */
140         if (((*code) >> 26) == 18) {
141                 /*g_print ("direct patching\n");*/
142                 ppc_patch ((char*)code, addr);
143                 mono_arch_flush_icache ((char*)code, 4);
144                 return addr;
145         }
146         
147         /* Sanity check: instruction must be 'blrl' */
148         g_assert(*code == 0x4e800021);
149         
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))
163                          */
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);
177                         }
178                         /* o contains now the value of register reg */
179                         o = *((char**) (sp + reg_offset));
180                         break;
181                 }
182         }
183
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
187          */
188         if (method->klass->valuetype)
189                 addr = get_unbox_trampoline (method, addr);
190
191         o += offset;
192         *((gpointer *)o) = addr;
193         return addr;
194 }
195
196 static void
197 ppc_class_init_trampoline (void *vtable, guint32 *code, char *sp)
198 {
199         mono_runtime_class_init (vtable);
200
201 #if 0
202         /* This is the 'bl' instruction */
203         --code;
204         
205         if (((*code) >> 26) == 18) {
206                 ppc_ori (code, 0, 0, 0); /* nop */
207                 mono_arch_flush_icache (code, 4);
208                 return;
209         } else {
210                 g_assert_not_reached ();
211         }
212 #endif
213 }
214
215 /*
216  * Stack frame description when the generic trampoline is called.
217  * caller frame
218  * --------------------
219  *  MonoLMF
220  *  -------------------
221  *  Saved FP registers 0-13
222  *  -------------------
223  *  Saved general registers 0-12
224  *  -------------------
225  *  param area for 3 args to ppc_magic_trampoline
226  *  -------------------
227  *  linkage area
228  *  -------------------
229  */
230 static guchar*
231 create_trampoline_code (MonoTrampolineType tramp_type)
232 {
233         guint8 *buf, *code = NULL;
234         static guint8* generic_jump_trampoline = NULL;
235         static guint8 *generic_class_init_trampoline = NULL;
236         int i, offset;
237
238         switch (tramp_type) {
239         case MONO_TRAMPOLINE_GENERIC:
240                 if (mono_generic_trampoline_code)
241                         return mono_generic_trampoline_code;
242                 break;
243         case MONO_TRAMPOLINE_JUMP:
244                 if (generic_jump_trampoline)
245                         return generic_jump_trampoline;
246                 break;
247         case MONO_TRAMPOLINE_CLASS_INIT:
248                 if (generic_class_init_trampoline)
249                         return generic_class_init_trampoline;
250                 break;
251         }
252
253         if(!code) {
254                 /* Now we'll create in 'buf' the PowerPC trampoline code. This
255                  is the trampoline code common to all methods  */
256                 
257                 code = buf = g_malloc(512);
258                 
259                 ppc_stwu (buf, ppc_r1, -STACK, ppc_r1);
260
261                 /* start building the MonoLMF on the stack */
262                 offset = STACK - sizeof (double) * MONO_SAVED_FREGS;
263                 for (i = 14; i < 32; i++) {
264                         ppc_stfd (buf, i, offset, ppc_r1);
265                         offset += sizeof (double);
266                 }
267                 /* 
268                  * now the integer registers. r13 is already saved in the trampoline,
269                  * and at this point contains the method to compile, so we skip it.
270                  */
271                 offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs) + sizeof (gulong);
272                 ppc_stmw (buf, ppc_r14, ppc_r1, offset);
273
274                 /* Now save the rest of the registers below the MonoLMF struct, first 14
275                  * fp regs and then the 13 gregs.
276                  */
277                 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double));
278                 for (i = 0; i < 14; i++) {
279                         ppc_stfd (buf, i, offset, ppc_r1);
280                         offset += sizeof (double);
281                 }
282                 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
283                 for (i = 0; i < 13; i++) {
284                         ppc_stw (buf, i, offset, ppc_r1);
285                         offset += sizeof (gulong);
286                 }
287                 /* we got here through a jump to the ctr reg, we must save the lr
288                  * in the parent frame (we do it here to reduce the size of the
289                  * method-specific trampoline)
290                  */
291                 ppc_mflr (buf, ppc_r0);
292                 ppc_stw (buf, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
293
294                 /* ok, now we can continue with the MonoLMF setup, mostly untouched 
295                  * from emit_prolog in mini-ppc.c
296                  */
297                 ppc_load (buf, ppc_r0, mono_get_lmf_addr);
298                 ppc_mtlr (buf, ppc_r0);
299                 ppc_blrl (buf);
300                 /* we build the MonoLMF structure on the stack - see mini-ppc.h
301                  * The pointer to the struct is put in ppc_r11.
302                  */
303                 ppc_addi (buf, ppc_r11, ppc_sp, STACK - sizeof (MonoLMF));
304                 ppc_stw (buf, ppc_r3, G_STRUCT_OFFSET(MonoLMF, lmf_addr), ppc_r11);
305                 /* new_lmf->previous_lmf = *lmf_addr */
306                 ppc_lwz (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r3);
307                 ppc_stw (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r11);
308                 /* *(lmf_addr) = r11 */
309                 ppc_stw (buf, ppc_r11, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r3);
310                 /* save method info (it's in r13) */
311                 ppc_stw (buf, ppc_r13, G_STRUCT_OFFSET(MonoLMF, method), ppc_r11);
312                 ppc_stw (buf, ppc_sp, G_STRUCT_OFFSET(MonoLMF, ebp), ppc_r11);
313                 /* save the IP (caller ip) */
314                 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
315                         ppc_li (buf, ppc_r0, 0);
316                 } else {
317                         ppc_lwz (buf, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
318                 }
319                 ppc_stw (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, eip), ppc_r11);
320
321                 /*
322                  * Now we're ready to call ppc_magic_trampoline ().
323                  */
324                 /* Arg 1: MonoMethod *method. It was put in r13 */
325                 ppc_mr  (buf, ppc_r3, ppc_r13);
326                 
327                 /* Arg 2: code (next address to the instruction that called us) */
328                 if (tramp_type == MONO_TRAMPOLINE_JUMP) {
329                         ppc_li (buf, ppc_r4, 0);
330                 } else {
331                         ppc_lwz  (buf, ppc_r4, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
332                 }
333                 
334                 /* Arg 3: stack pointer so that the magic trampoline can access the
335                  * registers we saved above
336                  */
337                 ppc_mr   (buf, ppc_r5, ppc_r1);
338                 
339                 if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
340                         ppc_lis  (buf, ppc_r0, (guint32) ppc_class_init_trampoline >> 16);
341                         ppc_ori  (buf, ppc_r0, ppc_r0, (guint32) ppc_class_init_trampoline & 0xffff);
342                 } else {
343                         ppc_lis  (buf, ppc_r0, (guint32) ppc_magic_trampoline >> 16);
344                         ppc_ori  (buf, ppc_r0, ppc_r0, (guint32) ppc_magic_trampoline & 0xffff);
345                 }
346                 ppc_mtlr (buf, ppc_r0);
347                 ppc_blrl (buf);
348                 
349                 /* OK, code address is now on r3. Move it to the counter reg
350                  * so it will be ready for the final jump: this is safe since we
351                  * won't do any more calls.
352                  */
353                 ppc_mtctr (buf, ppc_r3);
354
355                 /*
356                  * Now we restore the MonoLMF (see emit_epilogue in mini-ppc.c)
357                  * and the rest of the registers, so the method called will see
358                  * the same state as before we executed.
359                  * The pointer to MonoLMF is in ppc_r11.
360                  */
361                 ppc_addi (buf, ppc_r11, ppc_r1, STACK - sizeof (MonoLMF));
362                 /* r5 = previous_lmf */
363                 ppc_lwz (buf, ppc_r5, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r11);
364                 /* r6 = lmf_addr */
365                 ppc_lwz (buf, ppc_r6, G_STRUCT_OFFSET(MonoLMF, lmf_addr), ppc_r11);
366                 /* *(lmf_addr) = previous_lmf */
367                 ppc_stw (buf, ppc_r5, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r6);
368                 /* restore iregs: this time include r13 */
369                 ppc_lmw (buf, ppc_r13, ppc_r11, G_STRUCT_OFFSET(MonoLMF, iregs));
370                 /* restore fregs */
371                 for (i = 14; i < 32; i++) {
372                         ppc_lfd (buf, i, G_STRUCT_OFFSET(MonoLMF, fregs) + ((i-14) * sizeof (gdouble)), ppc_r11);
373                 }
374
375                 /* restore the volatile registers, we skip r1, of course */
376                 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double));
377                 for (i = 0; i < 14; i++) {
378                         ppc_lfd (buf, i, offset, ppc_r1);
379                         offset += sizeof (double);
380                 }
381                 offset = STACK - sizeof (MonoLMF) - (14 * sizeof (double)) - (13 * sizeof (gulong));
382                 ppc_lwz (buf, ppc_r0, offset, ppc_r1);
383                 offset += 2 * sizeof (gulong);
384                 for (i = 2; i < 13; i++) {
385                         ppc_lwz (buf, i, offset, ppc_r1);
386                         offset += sizeof (gulong);
387                 }
388
389                 /* Non-standard function epilogue. Instead of doing a proper
390                  * return, we just hump to the compiled code.
391                  */
392                 /* Restore stack pointer and LR and jump to the code */
393                 ppc_lwz  (buf, ppc_r1,  0, ppc_r1);
394                 ppc_lwz  (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
395                 ppc_mtlr (buf, ppc_r11);
396                 ppc_bcctr (buf, 20, 0);
397
398                 /* Flush instruction cache, since we've generated code */
399                 mono_arch_flush_icache (code, buf - code);
400         
401                 /* Sanity check */
402                 g_assert ((buf - code) <= 512);
403         }
404
405         switch (tramp_type) {
406         case MONO_TRAMPOLINE_GENERIC:
407                 mono_generic_trampoline_code = code;
408                 break;
409         case MONO_TRAMPOLINE_JUMP:
410                 generic_jump_trampoline = code;
411                 break;
412         case MONO_TRAMPOLINE_CLASS_INIT:
413                 generic_class_init_trampoline = code;
414                 break;
415         }
416
417         return code;
418 }
419
420 static MonoJitInfo*
421 create_specific_tramp (MonoMethod *method, guint8* tramp, MonoDomain *domain) {
422         guint8 *code, *buf;
423         MonoJitInfo *ji;
424
425         mono_domain_lock (domain);
426         code = buf = mono_code_manager_reserve (domain->code_mp, 32);
427         mono_domain_unlock (domain);
428
429         /* Save r13 in the place it will have in the on-stack MonoLMF */
430         ppc_stw  (buf, ppc_r13, -(MONO_SAVED_FREGS * 8 + MONO_SAVED_GREGS * sizeof (gpointer)),  ppc_r1);
431         
432         /* Prepare the jump to the generic trampoline code.*/
433         ppc_lis  (buf, ppc_r13, (guint32) tramp >> 16);
434         ppc_ori  (buf, ppc_r13, ppc_r13, (guint32) tramp & 0xffff);
435         ppc_mtctr (buf, ppc_r13);
436         
437         /* And finally put 'method' in r13 and fly! */
438         ppc_lis  (buf, ppc_r13, (guint32) method >> 16);
439         ppc_ori  (buf, ppc_r13, ppc_r13, (guint32) method & 0xffff);
440         ppc_bcctr (buf, 20, 0);
441         
442         /* Flush instruction cache, since we've generated code */
443         mono_arch_flush_icache (code, buf - code);
444
445         g_assert ((buf - code) <= 32);
446
447         ji = g_new0 (MonoJitInfo, 1);
448         ji->method = method;
449         ji->code_start = code;
450         ji->code_size = buf - code;
451
452         mono_jit_stats.method_trampolines++;
453
454         return ji;
455 }
456
457 MonoJitInfo*
458 mono_arch_create_jump_trampoline (MonoMethod *method)
459 {
460         guint8 *tramp;
461         MonoDomain* domain = mono_domain_get ();
462         
463         tramp = create_trampoline_code (MONO_TRAMPOLINE_JUMP);
464         return create_specific_tramp (method, tramp, domain);
465 }
466
467 /**
468  * arch_create_jit_trampoline:
469  * @method: pointer to the method info
470  *
471  * Creates a trampoline function for virtual methods. If the created
472  * code is called it first starts JIT compilation of method,
473  * and then calls the newly created method. It also replaces the
474  * corresponding vtable entry (see ppc_magic_trampoline).
475  *
476  * A trampoline consists of two parts: a main fragment, shared by all method
477  * trampolines, and some code specific to each method, which hard-codes a
478  * reference to that method and then calls the main fragment.
479  *
480  * The main fragment contains a call to 'ppc_magic_trampoline', which performs
481  * call to the JIT compiler and substitutes the method-specific fragment with
482  * some code that directly calls the JIT-compiled method.
483  * 
484  * Returns: a pointer to the newly created code 
485  */
486 gpointer
487 mono_arch_create_jit_trampoline (MonoMethod *method)
488 {
489         guint8 *tramp;
490         MonoJitInfo *ji;
491         MonoDomain* domain = mono_domain_get ();
492
493         /* previously created trampoline code */
494         if (method->info)
495                 return method->info;
496
497         if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
498                 return mono_arch_create_jit_trampoline (mono_marshal_get_synchronized_wrapper (method));
499
500         tramp = create_trampoline_code (MONO_TRAMPOLINE_GENERIC);
501         /* FIXME: should pass the domain down tot his function */
502         ji = create_specific_tramp (method, tramp, domain);
503         /* Store trampoline address */
504         method->info = ji->code_start;
505         return ji->code_start;
506 }
507
508 /**
509  * mono_arch_create_class_init_trampoline:
510  *  @vtable: the type to initialize
511  *
512  * Creates a trampoline function to run a type initializer. 
513  * If the trampoline is called, it calls mono_runtime_class_init with the
514  * given vtable, then patches the caller code so it does not get called any
515  * more.
516  * 
517  * Returns: a pointer to the newly created code 
518  */
519 gpointer
520 mono_arch_create_class_init_trampoline (MonoVTable *vtable)
521 {
522         guint8 *code, *buf, *tramp;
523
524         tramp = create_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
525
526         /* This is the method-specific part of the trampoline. Its purpose is
527         to provide the generic part with the MonoMethod *method pointer. We'll
528         use r11 to keep that value, for instance. However, the generic part of
529         the trampoline relies on r11 having the same value it had before coming
530         here, so we must save it before. */
531         //code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
532         mono_domain_lock (vtable->domain);
533         code = buf = mono_code_manager_reserve (vtable->domain->code_mp, METHOD_TRAMPOLINE_SIZE);
534         mono_domain_unlock (vtable->domain);
535
536         ppc_mflr (buf, ppc_r4);
537         ppc_stw  (buf, ppc_r4, PPC_RET_ADDR_OFFSET, ppc_sp);
538         ppc_stwu (buf, ppc_sp, -64, ppc_sp);
539         ppc_load (buf, ppc_r3, vtable);
540         ppc_load (buf, ppc_r5, 0);
541
542         ppc_load (buf, ppc_r0, ppc_class_init_trampoline);
543         ppc_mtlr (buf, ppc_r0);
544         ppc_blrl (buf);
545
546         ppc_lwz (buf, ppc_r0, 64 + PPC_RET_ADDR_OFFSET, ppc_sp);
547         ppc_mtlr (buf, ppc_r0);
548         ppc_addic (buf, ppc_sp, ppc_sp, 64);
549         ppc_blr (buf);
550
551         /* Flush instruction cache, since we've generated code */
552         mono_arch_flush_icache (code, buf - code);
553                 
554         /* Sanity check */
555         g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
556
557         mono_jit_stats.method_trampolines++;
558
559         return code;
560 }
561
562 /*
563  * This method is only called when running in the Mono Debugger.
564  */
565 gpointer
566 mono_debugger_create_notification_function (gpointer *notification_address)
567 {
568         guint8 *ptr, *buf;
569
570         ptr = buf = g_malloc0 (16);
571         ppc_break (buf);
572         if (notification_address)
573                 *notification_address = buf;
574         ppc_blr (buf);
575
576         return ptr;
577 }
578