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

Reply via email to