[Mono-dev] ARM PInvoke issue when using long

D M dm_mono_dev at yahoo.com
Tue Nov 14 16:48:10 EST 2006


This seems to work.

Thanks a lot,

Dan

Paolo Molaro <lupus at ximian.com> wrote: 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

-- 
-----------------------------------------------------------------
lupus at debian.org                                     debian/rules
lupus at ximian.com                             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 at lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list


 
---------------------------------
Cheap Talk? Check out Yahoo! Messenger's low PC-to-Phone call rates.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.ximian.com/pipermail/mono-devel-list/attachments/20061114/a3158a4b/attachment.html 


More information about the Mono-devel-list mailing list