+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.
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));
/* 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);
/* 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);
/*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);
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;
/* 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;
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);
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;
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)
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;
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
*/
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
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
*/
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
}
}
+ memset (&rji, 0, sizeof (rji));
+
while (1) {
MonoContext new_ctx;
char *trace = NULL;
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,
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,
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;
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)
{
guint8 *code;
CallInfo *cinfo;
int tracing = 0;
+ int lmf_offset = 0;
if (mono_jit_trace_calls != NULL && mono_trace_eval (method))
tracing = 1;
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
(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);
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)
} 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 */
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;
#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
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
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 {