Mon Jan 19 17:44:50 CET 2004 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / mini / tramp-ppc.c
index 9f13292e50832899d3bdc47b1fc30055fa229a3a..b2bfc48fa53099eef9834b28e43a00a748590f06 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * trampoline.c: JIT trampoline code
+ * tramp-ppc.c: JIT trampoline code for PowerPC
  *
  * Authors:
  *   Dietmar Maurer (dietmar@ximian.com)
@@ -56,8 +56,8 @@ get_unbox_trampoline (MonoMethod *m, gpointer addr)
            
        start = code = g_malloc (20);
 
-       ppc_load (code, ppc_r11, addr);
-       ppc_mtctr (code, ppc_r11);
+       ppc_load (code, ppc_r0, addr);
+       ppc_mtctr (code, ppc_r0);
        ppc_addi (code, this_pos, this_pos, sizeof (MonoObject));
        ppc_bcctr (code, 20, 0);
        g_assert ((code - start) <= 20);
@@ -66,7 +66,7 @@ get_unbox_trampoline (MonoMethod *m, gpointer addr)
 }
 
 /* Stack size for trampoline function */
-#define STACK 144
+#define STACK (144 + 8*8)
 
 /* Method-specific trampoline code framgment size */
 #define METHOD_TRAMPOLINE_SIZE 64
@@ -181,6 +181,11 @@ ppc_magic_trampoline (MonoMethod *method, guint32 *code, char *sp)
        compiled method */
        
        start = o;
+#if 1
+       /* FIXME: make the patching thread safe */
+       ppc_b (o, 0);
+       ppc_patch (o - 4, addr);
+#else
        ppc_stwu (o, ppc_r1, -16, ppc_r1);
        ppc_mflr (o, ppc_r0);
        ppc_stw  (o, ppc_r31, 12, ppc_r1);
@@ -198,7 +203,7 @@ ppc_magic_trampoline (MonoMethod *method, guint32 *code, char *sp)
        ppc_lwz  (o, ppc_r31, -4, ppc_r11);
        ppc_mr   (o, ppc_r1, ppc_r11);
        ppc_blr  (o);
-       
+#endif 
        mono_arch_flush_icache (start, o - start);
        g_assert(o - start < METHOD_TRAMPOLINE_SIZE);
        
@@ -230,6 +235,7 @@ create_trampoline_code (MonoTrampolineType tramp_type)
        guint8 *buf, *code = NULL;
        static guint8* generic_jump_trampoline = NULL;
        static guint8 *generic_class_init_trampoline = NULL;
+       int i, offset;
 
        switch (tramp_type) {
        case MONO_TRAMPOLINE_GENERIC:
@@ -310,6 +316,13 @@ create_trampoline_code (MonoTrampolineType tramp_type)
                /* Save 'method' pseudo-parameter - the one passed in r11 */
                ppc_stw  (buf, ppc_r11, STACK - 124, ppc_r1);
 
+               /* Save the FP registers */
+               offset = 124 + 4 + 8;
+               for (i = ppc_f1; i <= ppc_f8; ++i) {
+                       ppc_stfd  (buf, i, STACK - offset, ppc_r1);
+                       offset += 8;
+               }
+
                /*----------------------------------------------------------
                STEP 1: call 'mono_get_lmf_addr()' to get the address of our
                LMF. We'll need to restore it after the call to
@@ -347,7 +360,7 @@ create_trampoline_code (MonoTrampolineType tramp_type)
                if (tramp_type == MONO_TRAMPOLINE_JUMP) {
                        ppc_li (buf, ppc_r4, 0);
                } else
-                       ppc_lwz  (buf, ppc_r4, STACK + 4, ppc_r1);
+                       ppc_lwz  (buf, ppc_r4, STACK + PPC_RET_ADDR_OFFSET, ppc_r1);
                
                /* Arg 3: stack pointer */
                ppc_mr   (buf, ppc_r5, ppc_r1);
@@ -391,6 +404,12 @@ create_trampoline_code (MonoTrampolineType tramp_type)
                ppc_lwz  (buf, ppc_r9,  STACK - 36,  ppc_r1);
                ppc_lwz  (buf, ppc_r10, STACK - 40,  ppc_r1);
                
+               /* Restore the FP registers */
+               offset = 124 + 4 + 8;
+               for (i = ppc_f1; i <= ppc_f8; ++i) {
+                       ppc_lfd  (buf, i, STACK - offset, ppc_r1);
+                       offset += 8;
+               }
                /* We haven't touched any of these, so there's no need to
                restore them */
                /*
@@ -416,7 +435,16 @@ create_trampoline_code (MonoTrampolineType tramp_type)
                /* Non-standard function epilogue. Instead of doing a proper
                return, we just call the compiled code, so
                that, when it finishes, the method returns here. */
-               
+       
+#if 1
+               /* Restore stack pointer, r31, LR and jump to the code */
+               ppc_lwz  (buf, ppc_r1,  0, ppc_r1);
+               ppc_lwz  (buf, ppc_r31, -4, ppc_r1);
+               ppc_lwz  (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
+               ppc_mtlr (buf, ppc_r11);
+               ppc_mtctr (buf, ppc_r0);
+               ppc_bcctr (buf, 20, 0);
+#else
                ppc_mtlr (buf, ppc_r0);
                ppc_blrl (buf);
                
@@ -427,6 +455,7 @@ create_trampoline_code (MonoTrampolineType tramp_type)
                ppc_lwz  (buf, ppc_r0, 4, ppc_r1);
                ppc_mtlr (buf, ppc_r0);
                ppc_blr  (buf); 
+#endif
                
                /* Flush instruction cache, since we've generated code */
                mono_arch_flush_icache (code, buf - code);
@@ -490,15 +519,14 @@ mono_arch_create_jit_trampoline (MonoMethod *method)
        the trampoline relies on r11 having the same value it had before coming
        here, so we must save it before. */
        code = buf = g_malloc(METHOD_TRAMPOLINE_SIZE);
-       
+
        /* Save r11. There's nothing magic in the '44', its just an arbitrary
        position - see above */
        ppc_stw  (buf, ppc_r11, -44,  ppc_r1);
        
        /* Now save LR - we'll overwrite it now */
        ppc_mflr (buf, ppc_r11);
-       ppc_stw  (buf, ppc_r11, 4, ppc_r1);
-       ppc_stw  (buf, ppc_r11, 8, ppc_r1);
+       ppc_stw  (buf, ppc_r11, PPC_RET_ADDR_OFFSET, ppc_r1);
        
        /* Prepare the jump to the generic trampoline code.*/
        ppc_lis  (buf, ppc_r11, (guint32) vc >> 16);