New test.
[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         MonoDomain *domain = mono_domain_get ();
38
39         if (!mono_method_signature (m)->ret->byref && MONO_TYPE_ISSTRUCT (mono_method_signature (m)->ret))
40                 this_pos = 4;
41             
42         mono_domain_lock (domain);
43         start = code = mono_code_manager_reserve (domain->code_mp, 20);
44         mono_domain_unlock (domain);
45
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);*/
54
55         return start;
56 }
57
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
63  */
64 #define STACK (448)
65
66 /* Method-specific trampoline code fragment size */
67 #define METHOD_TRAMPOLINE_SIZE 64
68
69 /* Jump-specific trampoline code fragment size */
70 #define JUMP_TRAMPOLINE_SIZE   64
71
72 /**
73  * ppc_magic_trampoline:
74  * @code: pointer into caller code
75  * @method: the method to translate
76  * @sp: stack pointer
77  *
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' 
85  */
86 static gpointer
87 ppc_magic_trampoline (MonoMethod *method, guint32 *code, char *sp)
88 {
89         char *o = NULL;
90         gpointer addr;
91         MonoJitInfo *ji, *target_ji;
92         int reg, offset = 0;
93
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);
97
98         if (!code){
99                 return addr;
100         }
101
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;
107
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:
111         
112                 mtlr rA                 ; Move rA (a register containing the
113                                         ; target address) to LR
114                 blrl                    ; Call function at LR
115         
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.
123         
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 */
127         
128         /* This is the 'blrl' instruction */
129         --code;
130         
131         /*
132          * Note that methods are called also with the bl opcode.
133          */
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;
139         }
140         
141         /* Sanity check: instruction must be 'blrl' */
142         g_assert(*code == 0x4e800021);
143
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;
148         }
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 && !mono_aot_is_got_entry (code, o))
189                 addr = get_unbox_trampoline (method, addr);
190
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;
195 }
196
197 static void
198 ppc_class_init_trampoline (void *vtable, guint32 *code, char *sp)
199 {
200         mono_runtime_class_init (vtable);
201
202 #if 0
203         /* This is the 'bl' instruction */
204         --code;
205         
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 ();
212         }
213 #endif
214 }
215
216 /*
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  *  -------------------
230  */
231 guchar*
232 mono_arch_create_trampoline_code (MonoTrampolineType tramp_type)
233 {
234         guint8 *buf, *code = NULL;
235         int i, offset;
236
237         if(!code) {
238                 /* Now we'll create in 'buf' the PowerPC trampoline code. This
239                  is the trampoline code common to all methods  */
240                 
241                 code = buf = mono_global_codeman_reserve (512);
242                 
243                 ppc_stwu (buf, ppc_r1, -STACK, ppc_r1);
244
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);
250                 }
251                 /* 
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.
254                  */
255                 offset = STACK - sizeof (MonoLMF) + G_STRUCT_OFFSET (MonoLMF, iregs) + sizeof (gulong);
256                 ppc_stmw (buf, ppc_r14, ppc_r1, offset);
257
258                 /* Now save the rest of the registers below the MonoLMF struct, first 14
259                  * fp regs and then the 13 gregs.
260                  */
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);
265                 }
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);
270                 }
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)
274                  */
275                 ppc_mflr (buf, ppc_r0);
276                 ppc_stw (buf, ppc_r0, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
277
278                 /* ok, now we can continue with the MonoLMF setup, mostly untouched 
279                  * from emit_prolog in mini-ppc.c
280                  */
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.
286                  */
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);
302                 }
303                 ppc_stw (buf, ppc_r0, G_STRUCT_OFFSET(MonoLMF, eip), ppc_r11);
304
305                 /*
306                  * Now we're ready to call ppc_magic_trampoline ().
307                  */
308                 /* Arg 1: MonoMethod *method. It was put in r13 */
309                 ppc_mr  (buf, ppc_r3, ppc_r13);
310                 
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);
316                 }
317                 
318                 /* Arg 3: stack pointer so that the magic trampoline can access the
319                  * registers we saved above
320                  */
321                 ppc_mr   (buf, ppc_r5, ppc_r1);
322                 
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);
329                 }
330                 ppc_mtlr (buf, ppc_r0);
331                 ppc_blrl (buf);
332                 
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.
336                  */
337                 ppc_mtctr (buf, ppc_r3);
338
339                 /*
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.
344                  */
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);
357                 }
358
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);
364                 }
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);
371                 }
372
373                 /* Non-standard function epilogue. Instead of doing a proper
374                  * return, we just hump to the compiled code.
375                  */
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);
381
382                 /* Flush instruction cache, since we've generated code */
383                 mono_arch_flush_icache (code, buf - code);
384         
385                 /* Sanity check */
386                 g_assert ((buf - code) <= 512);
387         }
388
389         return code;
390 }
391
392 static MonoJitInfo*
393 create_specific_tramp (MonoMethod *method, guint8* tramp, MonoDomain *domain) {
394         guint8 *code, *buf;
395         MonoJitInfo *ji;
396
397         mono_domain_lock (domain);
398         code = buf = mono_code_manager_reserve (domain->code_mp, 32);
399         mono_domain_unlock (domain);
400
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);
403         
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);
408         
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);
413         
414         /* Flush instruction cache, since we've generated code */
415         mono_arch_flush_icache (code, buf - code);
416
417         g_assert ((buf - code) <= 32);
418
419         ji = g_new0 (MonoJitInfo, 1);
420         ji->method = method;
421         ji->code_start = code;
422         ji->code_size = buf - code;
423
424         mono_jit_stats.method_trampolines++;
425
426         return ji;
427 }
428
429 MonoJitInfo*
430 mono_arch_create_jump_trampoline (MonoMethod *method)
431 {
432         guint8 *tramp;
433         MonoDomain* domain = mono_domain_get ();
434         
435         tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_JUMP);
436         return create_specific_tramp (method, tramp, domain);
437 }
438
439 /**
440  * arch_create_jit_trampoline:
441  * @method: pointer to the method info
442  *
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).
447  *
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.
451  *
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.
455  * 
456  * Returns: a pointer to the newly created code 
457  */
458 gpointer
459 mono_arch_create_jit_trampoline (MonoMethod *method)
460 {
461         guint8 *tramp;
462         MonoJitInfo *ji;
463         MonoDomain* domain = mono_domain_get ();
464         gpointer code_start;
465
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);
471
472         return code_start;
473 }
474
475 /**
476  * mono_arch_create_class_init_trampoline:
477  *  @vtable: the type to initialize
478  *
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.
483  * 
484  * Returns: a pointer to the newly created code 
485  */
486 gpointer
487 mono_arch_create_class_init_trampoline (MonoVTable *vtable)
488 {
489         guint8 *code, *buf, *tramp;
490
491         tramp = mono_get_trampoline_code (MONO_TRAMPOLINE_CLASS_INIT);
492
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);
501
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);
507
508         ppc_load (buf, ppc_r0, ppc_class_init_trampoline);
509         ppc_mtlr (buf, ppc_r0);
510         ppc_blrl (buf);
511
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);
516
517         /* Flush instruction cache, since we've generated code */
518         mono_arch_flush_icache (code, buf - code);
519                 
520         /* Sanity check */
521         g_assert ((buf - code) <= METHOD_TRAMPOLINE_SIZE);
522
523         mono_jit_stats.method_trampolines++;
524
525         return code;
526 }
527
528 /*
529  * This method is only called when running in the Mono Debugger.
530  */
531 gpointer
532 mono_debugger_create_notification_function (MonoCodeManager *codeman)
533 {
534         guint8 *ptr, *buf;
535
536         codeman = mono_code_manager_reserve (codeman, 16);
537         ppc_break (buf);
538         ppc_blr (buf);
539         mono_arch_flush_icache (ptr, buf - ptr);
540
541         return ptr;
542 }
543