On 11/14/06 D M wrote: > I think the issue is with the mini-arm.c add_general (guint *gr, guint > *stack_size, ArgInfo *ainfo, gboolean simple) function. > It doesn't work properly for MONO_TYPE_I8/MONO_TYPE_R8 if just the first half > fits in one register and the other on the stack. > mono_arch_create_trampoline seems to handle this case. > Is there an easy fix ?
You may want to try this mostly untested patch. lupus -- ----------------------------------------------------------------- [EMAIL PROTECTED] debian/rules [EMAIL PROTECTED] Monkeys do it better
Index: inssel-arm.brg =================================================================== --- inssel-arm.brg (revision 67852) +++ inssel-arm.brg (working copy) @@ -274,6 +274,21 @@ stmt: OP_OUTARG_MEMBASE (lreg) { int offset = tree->backend.arg_info >> 8; + int partial = (tree->backend.arg_info & 0xff) == 0xff; + if (partial) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right; + if (G_BYTE_ORDER == G_BIG_ENDIAN) { + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset, state->left->reg1); + } else { + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset, state->left->reg2); + } + tree->opcode = OP_SETREG; + tree->dreg = mono_regstate_next_int (s->rs); + tree->sreg1 = G_BYTE_ORDER == G_BIG_ENDIAN? state->left->reg2: state->left->reg1; + mono_bblock_add_inst (s->cbb, tree); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, ARMREG_R3, FALSE); + return; + } if (G_BYTE_ORDER == G_BIG_ENDIAN) { MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset, state->left->reg2); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset + 4, state->left->reg1); @@ -286,6 +301,7 @@ stmt: OP_OUTARG_MEMBASE (freg) { int offset = tree->backend.arg_info >> 8; if (SOFT_FLOAT_IMPL) { + int partial = (tree->backend.arg_info & 0xff) == 0xff; /* same as OP_OUTARG_MEMBASE (lreg) */ if (G_BYTE_ORDER == G_BIG_ENDIAN) { MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset, state->left->reg2); @@ -299,7 +315,17 @@ MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, ARMREG_SP, offset, state->left->reg1); else if ((tree->backend.arg_info & 0xff) == 4) MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, ARMREG_SP, offset, state->left->reg1); - else + else if ((tree->backend.arg_info & 0xff) == 0xff) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right; + int creg; + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, ARMREG_SP, (s->param_area - 8), state->left->reg1); + creg = mono_regstate_next_int (s->rs); + mono_call_inst_add_outarg_reg (s, call, creg, ARMREG_R3, FALSE); + MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, creg, ARMREG_SP, (s->param_area - 8)); + creg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOAD_MEMBASE, creg, ARMREG_SP, (s->param_area - 4)); + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, ARMREG_SP, offset, creg); + } else g_assert_not_reached (); } } Index: mini-arm.c =================================================================== --- mini-arm.c (revision 67852) +++ mini-arm.c (working copy) @@ -318,6 +318,7 @@ enum { RegTypeGeneral, RegTypeBase, + RegTypeBaseGen, RegTypeFP, RegTypeStructByVal, RegTypeStructByAddr @@ -355,7 +356,13 @@ ainfo->reg = *gr; } } else { - if (*gr > ARMREG_R2) { + if (*gr == ARMREG_R3) { + /* first word in r3 and the second on the stack */ + ainfo->offset = *stack_size; + ainfo->reg = ARMREG_SP; /* in the caller */ + ainfo->regtype = RegTypeBaseGen; + *stack_size += 4; + } else if (*gr > ARMREG_R3) { /**stack_size += 7; *stack_size &= ~7;*/ ainfo->offset = *stack_size; @@ -820,6 +827,12 @@ } else if (ainfo->regtype == RegTypeBase) { arg->opcode = OP_OUTARG_MEMBASE; arg->backend.arg_info = (ainfo->offset << 8) | ainfo->size; + } else if (ainfo->regtype == RegTypeBaseGen) { + call->used_iregs |= 1 << ARMREG_R3; + arg->opcode = OP_OUTARG_MEMBASE; + arg->backend.arg_info = (ainfo->offset << 8) | 0xff; + if (arg->type == STACK_R8) + cfg->flags |= MONO_CFG_HAS_FPOUT; } else if (ainfo->regtype == RegTypeFP) { arg->backend.reg3 = ainfo->reg; /* FP args are passed in int regs */ @@ -2984,6 +2997,12 @@ } break; } + } else if (ainfo->regtype == RegTypeBaseGen) { + g_assert (arm_is_imm12 (prev_sp_offset + ainfo->offset)); + g_assert (arm_is_imm12 (inst->inst_offset)); + ARM_LDR_IMM (code, ARMREG_LR, ARMREG_SP, (prev_sp_offset + ainfo->offset)); + ARM_STR_IMM (code, ARMREG_LR, inst->inst_basereg, inst->inst_offset + 4); + ARM_STR_IMM (code, ARMREG_R3, inst->inst_basereg, inst->inst_offset); } else if (ainfo->regtype == RegTypeBase) { g_assert (arm_is_imm12 (prev_sp_offset + ainfo->offset)); switch (ainfo->size) {
_______________________________________________ Mono-devel-list mailing list Mono-devel-list@lists.ximian.com http://lists.ximian.com/mailman/listinfo/mono-devel-list