Thu Apr 29 13:50:51 CEST 2004 Paolo Molaro <lupus@ximian.com>
authorPaolo Molaro <lupus@oddwiz.org>
Thu, 29 Apr 2004 11:14:03 +0000 (11:14 -0000)
committerPaolo Molaro <lupus@oddwiz.org>
Thu, 29 Apr 2004 11:14:03 +0000 (11:14 -0000)
* exceptions-ppc.c, mini-ppc.h, mini-ppc.c: fixed localloc
and prolog/epilog for methods that use it. Allow
enough param area room for varargs methods. Fix miguel's
breakage in exception handling.

svn path=/trunk/mono/; revision=26293

mono/mini/ChangeLog
mono/mini/exceptions-ppc.c
mono/mini/mini-ppc.c
mono/mini/mini-ppc.h

index 04dffd6d6799ad16a28a686de70392445c9699a5..77164350046131f22575e8e7504fdd4256cc86e9 100644 (file)
@@ -1,4 +1,11 @@
 
+Thu Apr 29 13:50:51 CEST 2004 Paolo Molaro <lupus@ximian.com>
+
+       * exceptions-ppc.c, mini-ppc.h, mini-ppc.c: fixed localloc
+       and prolog/epilog for methods that use it. Allow
+       enough param area room for varargs methods. Fix miguel's
+       breakage in exception handling.
+
 Thu Apr 29 12:06:51 CEST 2004 Paolo Molaro <lupus@ximian.com>
 
        * Makefile.am: run genmdesc only on current arch.
index 7f4c8758c872541c2575d2654a099ba62a5aa157..51c3d2555825c949a0ad1f7a6be574651260a609 100644 (file)
@@ -524,7 +524,7 @@ arch_get_call_filter (void)
 
        ppc_mflr (code, ppc_r0);
        ppc_stw (code, ppc_r0, PPC_RET_ADDR_OFFSET, ppc_sp);
-       alloc_size = 32 + PPC_MINIMAL_STACK_SIZE + (sizeof (gulong) * 19 + sizeof (gdouble) * 18);
+       alloc_size = 32 + PPC_MINIMAL_STACK_SIZE + (sizeof (gulong) * MONO_SAVED_GREGS + sizeof (gdouble) * MONO_SAVED_FREGS);
        // align to PPC_STACK_ALIGNMENT bytes
        if (alloc_size & (PPC_STACK_ALIGNMENT - 1))
                alloc_size += PPC_STACK_ALIGNMENT - (alloc_size & (PPC_STACK_ALIGNMENT - 1));
@@ -533,7 +533,9 @@ arch_get_call_filter (void)
        /* save all the regs on the stack */
        pos = 32 + PPC_MINIMAL_STACK_SIZE;
        ppc_stmw (code, ppc_r13, ppc_sp, pos);
-       pos += sizeof (gulong) * 19;
+       pos += sizeof (gulong) * MONO_SAVED_GREGS;
+       pos += 7;
+       pos &= ~7;
        for (i = 14; i < 32; ++i) {
                ppc_stfd (code, i, pos, ppc_sp);
                pos += sizeof (gdouble);
@@ -548,7 +550,9 @@ arch_get_call_filter (void)
        /* restore all the regs from the stack */
        pos = 32 + PPC_MINIMAL_STACK_SIZE;
        ppc_lmw (code, ppc_r13, ppc_sp, pos);
-       pos += sizeof (gulong) * 19;
+       pos += sizeof (gulong) * MONO_SAVED_GREGS;
+       pos += 7;
+       pos &= ~7;
        for (i = 14; i < 32; ++i) {
                ppc_lfd (code, i, pos, ppc_sp);
                pos += sizeof (gdouble);
@@ -579,7 +583,7 @@ throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gulong *
        /*printf ("stack in throw: %p\n", esp);*/
        MONO_CONTEXT_SET_BP (&ctx, esp);
        MONO_CONTEXT_SET_IP (&ctx, eip);
-       memcpy (&ctx.regs, int_regs, sizeof (gulong) * 19);
+       memcpy (&ctx.regs, int_regs, sizeof (gulong) * MONO_SAVED_GREGS);
 
        arch_handle_exception (&ctx, exc, FALSE);
        restore_context (&ctx);
@@ -606,7 +610,7 @@ mono_arch_get_throw_exception_generic (guint8 *start, int size, int by_name)
 
        ppc_mflr (code, ppc_r0);
        ppc_stw (code, ppc_r0, PPC_RET_ADDR_OFFSET, ppc_sp);
-       alloc_size = 32 + PPC_MINIMAL_STACK_SIZE + (sizeof (gulong) * 19 + sizeof (gdouble) * 18);
+       alloc_size = 32 + PPC_MINIMAL_STACK_SIZE + (sizeof (gulong) * MONO_SAVED_GREGS + sizeof (gdouble) * MONO_SAVED_FREGS);
        // align to PPC_STACK_ALIGNMENT bytes
        if (alloc_size & (PPC_STACK_ALIGNMENT - 1)) {
                alloc_size += PPC_STACK_ALIGNMENT - 1;
@@ -626,7 +630,7 @@ mono_arch_get_throw_exception_generic (guint8 *start, int size, int by_name)
        /* save all the regs on the stack */
        pos = 32 + PPC_MINIMAL_STACK_SIZE;
        ppc_stmw (code, ppc_r13, ppc_sp, pos);
-       pos += sizeof (gulong) * 19;
+       pos += sizeof (gulong) * MONO_SAVED_GREGS;
        /* align for doubles */
        pos += 7;
        pos &= ~7;
@@ -646,7 +650,10 @@ mono_arch_get_throw_exception_generic (guint8 *start, int size, int by_name)
        pos = 32 + PPC_MINIMAL_STACK_SIZE;
        ppc_addi (code, ppc_r6, ppc_sp, pos);
        /* pointer to the saved fp regs */
-       pos += sizeof (gulong) * 19;
+       pos += sizeof (gulong) * MONO_SAVED_GREGS;
+       /* align for doubles */
+       pos += 7;
+       pos &= ~7;
        ppc_addi (code, ppc_r7, ppc_sp, pos);
        ppc_bl (code, 0);
        ppc_patch (code - 4, throw_exception);
@@ -879,7 +886,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf
                MONO_CONTEXT_SET_IP (new_ctx, sframe->lr);*/
                MONO_CONTEXT_SET_BP (new_ctx, (*lmf)->ebp);
                MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip);
-               memcpy (&new_ctx->regs, (*lmf)->iregs, sizeof (gulong) * 19);
+               memcpy (&new_ctx->regs, (*lmf)->iregs, sizeof (gulong) * MONO_SAVED_GREGS);
                *lmf = (*lmf)->previous_lmf;
 
                return res;
@@ -956,7 +963,7 @@ mono_jit_walk_stack (MonoStackWalk func, gpointer user_data) {
 
        while (MONO_CONTEXT_GET_BP (&ctx) < jit_tls->end_of_stack) {
                
-               ji = mono_arch_find_jit_info (domain, jit_tls, &rji, &rji, &ctx, &new_ctx, NULL, &lmf, &native_offset, &managed);
+               ji = mono_arch_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, &native_offset, &managed);
                g_assert (ji);
 
                if (ji == (gpointer)-1)
@@ -990,7 +997,7 @@ ves_icall_get_frame_info (gint32 skip, MonoBoolean need_file_info,
        skip++;
 
        do {
-               ji = mono_arch_find_jit_info (domain, jit_tls, &rji, &rji, &ctx, &new_ctx, NULL, &lmf, native_offset, NULL);
+               ji = mono_arch_find_jit_info (domain, jit_tls, &rji, NULL, &ctx, &new_ctx, NULL, &lmf, native_offset, NULL);
 
                ctx = new_ctx;
                
@@ -1037,8 +1044,8 @@ mono_arch_handle_exception (void *ctx, gpointer obj, gboolean test_only)
        
        mctx.sc_ir = uc->uc_mcontext->ss.srr0;
        mctx.sc_sp = uc->uc_mcontext->ss.r1;
-       memcpy (&mctx.regs, &uc->uc_mcontext->ss.r13, sizeof (gulong) * 19);
-       memcpy (&mctx.fregs, &uc->uc_mcontext->fs.fpregs [14], sizeof (double) * 20);
+       memcpy (&mctx.regs, &uc->uc_mcontext->ss.r13, sizeof (gulong) * MONO_SAVED_GREGS);
+       memcpy (&mctx.fregs, &uc->uc_mcontext->fs.fpregs [14], sizeof (double) * MONO_SAVED_FREGS);
 
        result = arch_handle_exception (&mctx, obj, test_only);
        /* restore the context so that returning from the signal handler will invoke
@@ -1046,8 +1053,8 @@ mono_arch_handle_exception (void *ctx, gpointer obj, gboolean test_only)
         */
        uc->uc_mcontext->ss.srr0 = mctx.sc_ir;
        uc->uc_mcontext->ss.r1 = mctx.sc_sp;
-       memcpy (&uc->uc_mcontext->ss.r13, &mctx.regs, sizeof (gulong) * 19);
-       memcpy (&uc->uc_mcontext->fs.fpregs [14], &mctx.fregs, sizeof (double) * 20);
+       memcpy (&uc->uc_mcontext->ss.r13, &mctx.regs, sizeof (gulong) * MONO_SAVED_GREGS);
+       memcpy (&uc->uc_mcontext->fs.fpregs [14], &mctx.fregs, sizeof (double) * MONO_SAVED_FREGS);
        return result;
 }
 #else
@@ -1061,8 +1068,8 @@ mono_arch_handle_exception (void *ctx, gpointer obj, gboolean test_only)
        
        mctx.sc_ir = uc->uc_mcontext.uc_regs->gregs [PT_NIP];
        mctx.sc_sp = uc->uc_mcontext.uc_regs->gregs [PT_R1];
-       memcpy (&mctx.regs, &uc->uc_mcontext.uc_regs->gregs [PT_R13], sizeof (gulong) * 19);
-       memcpy (&mctx.fregs, &uc->uc_mcontext.uc_regs->fpregs.fpregs [14], sizeof (double) * 20);
+       memcpy (&mctx.regs, &uc->uc_mcontext.uc_regs->gregs [PT_R13], sizeof (gulong) * MONO_SAVED_GREGS);
+       memcpy (&mctx.fregs, &uc->uc_mcontext.uc_regs->fpregs.fpregs [14], sizeof (double) * MONO_SAVED_FREGS);
 
        result = arch_handle_exception (&mctx, obj, test_only);
        /* restore the context so that returning from the signal handler will invoke
@@ -1070,8 +1077,8 @@ mono_arch_handle_exception (void *ctx, gpointer obj, gboolean test_only)
         */
        uc->uc_mcontext.uc_regs->gregs [PT_NIP] = mctx.sc_ir;
        uc->uc_mcontext.uc_regs->gregs [PT_R1] = mctx.sc_sp;
-       memcpy (&uc->uc_mcontext.uc_regs->gregs [PT_R13], &mctx.regs, sizeof (gulong) * 19);
-       memcpy (&uc->uc_mcontext.uc_regs->fpregs.fpregs [14], &mctx.fregs, sizeof (double) * 20);
+       memcpy (&uc->uc_mcontext.uc_regs->gregs [PT_R13], &mctx.regs, sizeof (gulong) * MONO_SAVED_GREGS);
+       memcpy (&uc->uc_mcontext.uc_regs->fpregs.fpregs [14], &mctx.fregs, sizeof (double) * MONO_SAVED_FREGS);
        return result;
 }
 #endif
@@ -1130,6 +1137,8 @@ arch_handle_exception (MonoContext *ctx, gpointer obj, gboolean test_only)
                }
        }
 
+       memset (&rji, 0, sizeof (rji));
+
        while (1) {
                MonoContext new_ctx;
                char *trace = NULL;
index c633b6766f47d3baefecae16d0b8a7326f738d75..d00e3bac91048de7d2af7dc0367c4f06c0ef937b 100644 (file)
@@ -571,6 +571,10 @@ mono_arch_allocate_vars (MonoCompile *m)
        int i, offset, size, align, curinst;
        int frame_reg = ppc_sp;
 
+       /* allow room for the vararg method args: void* and long/double */
+       if (mono_jit_trace_calls != NULL && mono_trace_eval (m->method))
+               m->param_area = MAX (m->param_area, 16);
+
        /* 
         * FIXME: we'll use the frame register also for any method that has
         * filter clauses. This way, when the handlers are called,
@@ -619,9 +623,7 @@ mono_arch_allocate_vars (MonoCompile *m)
        offset += 16 - 1;
        offset &= ~(16 - 1);
 
-       /* FIXME: check how to handle this stuff... reserve space to save LMF and caller saved registers */
-       if (m->method->save_lmf)
-               offset += sizeof (MonoLMF);
+       /* the MonoLMF structure is stored just below the stack pointer */
 
 #if 0
        /* this stuff should not be needed on ppc and the new jit,
@@ -2711,15 +2713,17 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_OUTARG:
                        g_assert_not_reached ();
                        break;
-               case OP_LOCALLOC:
+               case OP_LOCALLOC: {
                        /* keep alignment */
-                       ppc_addi (code, ppc_r0, ins->sreg1, PPC_STACK_ALIGNMENT-1);
-                       ppc_rlwinm (code, ppc_r0, ppc_r0, 0, 0, 27);
-                       ppc_lwz (code, ppc_r11, 0, ppc_sp);
-                       ppc_neg (code, ppc_r0, ppc_r0);
-                       ppc_stwux (code, ppc_r11, ppc_r0, ppc_sp);
-                       ppc_addi (code, ins->dreg, ppc_sp, PPC_STACK_PARAM_OFFSET);
+                       int alloca_waste = PPC_STACK_PARAM_OFFSET + cfg->param_area + 15;
+                       ppc_addi (code, ppc_r11, ins->sreg1, alloca_waste);
+                       ppc_rlwinm (code, ppc_r11, ppc_r11, 0, 0, 27);
+                       ppc_lwz (code, ppc_r0, 0, ppc_sp);
+                       ppc_neg (code, ppc_r11, ppc_r11);
+                       ppc_stwux (code, ppc_r0, ppc_r11, ppc_sp);
+                       ppc_addi (code, ins->dreg, ppc_sp, PPC_STACK_PARAM_OFFSET + cfg->param_area);
                        break;
+               }
                case CEE_RET:
                        ppc_blr (code);
                        break;
@@ -3237,6 +3241,22 @@ mono_arch_max_epilog_size (MonoCompile *cfg)
        return max_epilog_size;
 }
 
+/*
+ * Stack frame layout:
+ * 
+ *   ------------------- sp
+ *     optional 8 bytes for tracing (later use a proper local variable?)
+ *   -------------------
+ *     MonoLMF structure or saved registers
+ *   -------------------
+ *     locals
+ *   -------------------
+ *     param area
+ *   -------------------
+ *     linkage area
+ *   ------------------- sp
+ *     red zone
+ */
 guint8 *
 mono_arch_emit_prolog (MonoCompile *cfg)
 {
@@ -3248,6 +3268,7 @@ mono_arch_emit_prolog (MonoCompile *cfg)
        guint8 *code;
        CallInfo *cinfo;
        int tracing = 0;
+       int lmf_offset = 0;
 
        if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
                tracing = 1;
@@ -3283,6 +3304,15 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                                ppc_stfd (code, i, -pos, ppc_sp);
                        }
                }*/
+       } else {
+               int ofs;
+               pos += sizeof (MonoLMF);
+               lmf_offset = pos;
+               ofs = -pos + G_STRUCT_OFFSET(MonoLMF, iregs);
+               ppc_stmw (code, ppc_r13, ppc_r1, ofs);
+               for (i = 14; i < 32; i++) {
+                       ppc_stfd (code, i, (-pos + G_STRUCT_OFFSET(MonoLMF, fregs) + ((i-14) * sizeof (gdouble))), ppc_r1);
+               }
        }
        alloc_size += pos;
        // align to PPC_STACK_ALIGNMENT bytes
@@ -3418,13 +3448,15 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                                     (gpointer)"mono_get_lmf_addr");
                ppc_bl (code, 0);
                /* we build the MonoLMF structure on the stack - see mini-ppc.h */
-               pos = PPC_MINIMAL_STACK_SIZE + cfg->param_area;
-               pos += 16-1;
-               pos &= ~(16-1);
-               ppc_addi (code, ppc_r11, ppc_sp, pos);
+               /* lmf_offset is the offset from the previous stack pointer,
+                * alloc_size is the total stack space allocated, so the offset
+                * of MonoLMF from the current stack ptr is alloc_size - lmf_offset.
+                * The pointer to the struct is put in ppc_r11.
+                */
+               ppc_addi (code, ppc_r11, ppc_sp, alloc_size - lmf_offset);
                ppc_stw (code, ppc_r3, G_STRUCT_OFFSET(MonoLMF, lmf_addr), ppc_r11);
                /* new_lmf->previous_lmf = *lmf_addr */
-               ppc_lwz (code, ppc_r0, 0, ppc_r3);
+               ppc_lwz (code, ppc_r0, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r3);
                ppc_stw (code, ppc_r0, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r11);
                /* *(lmf_addr) = r11 */
                ppc_stw (code, ppc_r11, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r3);
@@ -3436,10 +3468,6 @@ mono_arch_emit_prolog (MonoCompile *cfg)
                mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_IP, NULL);
                ppc_load (code, ppc_r0, 0x01010101);
                ppc_stw (code, ppc_r0, G_STRUCT_OFFSET(MonoLMF, eip), ppc_r11);
-               ppc_stmw (code, ppc_r13, ppc_r11, G_STRUCT_OFFSET(MonoLMF, iregs));
-               for (i = 14; i < 32; i++) {
-                       ppc_stfd (code, i, G_STRUCT_OFFSET(MonoLMF, fregs) + ((i-14) * sizeof (gdouble)), ppc_r11);
-               }
        }
 
        if (tracing)
@@ -3470,12 +3498,14 @@ mono_arch_emit_epilog (MonoCompile *cfg)
        } else {
                pos = 0;
        }
-       
+
        if (method->save_lmf) {
-               int ofst = PPC_MINIMAL_STACK_SIZE + cfg->param_area;
-               ofst += 16-1;
-               ofst &= ~(16-1);
-               ppc_addi (code, ppc_r11, cfg->frame_reg, ofst);
+               int lmf_offset;
+               pos +=  sizeof (MonoLMF);
+               lmf_offset = pos;
+               /* save the frame reg in r8 */
+               ppc_mr (code, ppc_r8, cfg->frame_reg);
+               ppc_addi (code, ppc_r11, cfg->frame_reg, cfg->stack_usage - lmf_offset);
                /* r5 = previous_lmf */
                ppc_lwz (code, ppc_r5, G_STRUCT_OFFSET(MonoLMF, previous_lmf), ppc_r11);
                /* r6 = lmf_addr */
@@ -3488,14 +3518,19 @@ mono_arch_emit_epilog (MonoCompile *cfg)
                for (i = 14; i < 32; i++) {
                        ppc_lfd (code, i, G_STRUCT_OFFSET(MonoLMF, fregs) + ((i-14) * sizeof (gdouble)), ppc_r11);
                }
-       }
+               /* use the saved copy of the frame reg in r8 */
+               if (1 || cfg->flags & MONO_CFG_HAS_CALLS) {
+                       ppc_lwz (code, ppc_r0, cfg->stack_usage + PPC_RET_ADDR_OFFSET, ppc_r8);
+                       ppc_mtlr (code, ppc_r0);
+               }
+               ppc_addic (code, ppc_sp, ppc_r8, cfg->stack_usage);
+       } else {
+               if (1 || cfg->flags & MONO_CFG_HAS_CALLS) {
+                       ppc_lwz (code, ppc_r0, cfg->stack_usage + PPC_RET_ADDR_OFFSET, cfg->frame_reg);
+                       ppc_mtlr (code, ppc_r0);
+               }
+               ppc_addic (code, ppc_sp, cfg->frame_reg, cfg->stack_usage);
 
-       if (1 || cfg->flags & MONO_CFG_HAS_CALLS) {
-               ppc_lwz (code, ppc_r0, cfg->stack_usage + PPC_RET_ADDR_OFFSET, cfg->frame_reg);
-               ppc_mtlr (code, ppc_r0);
-       }
-       ppc_addic (code, ppc_sp, cfg->frame_reg, cfg->stack_usage);
-       if (!method->save_lmf) {
                for (i = 13; i < 32; ++i) {
                        if (cfg->used_int_regs & (1 << i)) {
                                pos += 4;
index 1d16c30ecceacafa5a586b749ad45878a15f3fc4..bdef6c10d5a7ed303919b693ba992048f2f869e1 100644 (file)
@@ -7,6 +7,9 @@
 #define MONO_MAX_IREGS 32
 #define MONO_MAX_FREGS 32
 
+#define MONO_SAVED_GREGS 19
+#define MONO_SAVED_FREGS 18
+
 #define MONO_ARCH_FRAME_ALIGNMENT 4
 
 /* fixme: align to 16byte instead of 32byte (we align to 32byte to get 
@@ -21,8 +24,8 @@ struct MonoLMF {
        MonoMethod *method;
        gulong     ebp;
        gulong     eip;
-       gulong     iregs [19]; /* 13..31 */
-       gdouble    fregs [20]; /* 14..31 */
+       gulong     iregs [MONO_SAVED_GREGS]; /* 13..31 */
+       gdouble    fregs [MONO_SAVED_FREGS]; /* 14..31 */
 };
 
 /* we define our own structure and we'll copy the data
@@ -34,8 +37,8 @@ struct MonoLMF {
 typedef struct {
        gulong sc_ir;          // pc 
        gulong sc_sp;          // r1
-       gulong regs [19];
-       double fregs [20];
+       gulong regs [MONO_SAVED_GREGS];
+       double fregs [MONO_SAVED_FREGS];
 } MonoContext;
 
 typedef struct MonoCompileArch {