[Mono-dev] Little-endian MIPS support -- first draft

Rayson Ho raysonlogin at gmail.com
Mon Jun 22 03:56:03 EDT 2009


These are the core changes for supporting Mono on MIPS-EL. The problem
in the existing code (MIPS in big-endian mode) is that it is assuming
"lower-numbered reg is most significant", which is not true.

Test code:
  long long abc = 929;
  func(abc);

gcc generates:
        li      $2,929                  # 0x3a1
        move    $3,$0
        sw      $2,24($fp)
        sw      $3,28($fp)
        .loc 1 12 0
        lw      $4,24($fp)
        lw      $5,28($fp)
        lw      $25,%call16(func)($28)

Note that the lower-numbered reg ($4) holds the less significant word,
while $5 holds the more significant word.


# svn diff mono/mini/mini-mips.c
Index: mono/mini/mini-mips.c
===================================================================
--- mono/mini/mini-mips.c       (revision 136576)
+++ mono/mini/mini-mips.c       (working copy)
@@ -1467,13 +1464,13 @@
                                ins->dreg = mono_alloc_ireg (cfg);
                                ins->sreg1 = in->dreg + 1;
                                MONO_ADD_INS (cfg->cbb, ins);
-                               mono_call_inst_add_outarg_reg (cfg,
call, ins->dreg, ainfo->reg + 1, FALSE);
+                               mono_call_inst_add_outarg_reg (cfg,
call, ins->dreg, ainfo->reg + REGPAIR_LOW, FALSE);

                                MONO_INST_NEW (cfg, ins, OP_MOVE);
                                ins->dreg = mono_alloc_ireg (cfg);
                                ins->sreg1 = in->dreg + 2;
                                MONO_ADD_INS (cfg->cbb, ins);
-                               mono_call_inst_add_outarg_reg (cfg,
call, ins->dreg, ainfo->reg, FALSE);
+                               mono_call_inst_add_outarg_reg (cfg,
call, ins->dreg, ainfo->reg + REGPAIR_HIGH, FALSE);
                        } else
 #endif
                        if (!t->byref && (t->type == MONO_TYPE_R4)) {
@@ -1694,8 +1691,8 @@
                        MonoInst *ins;

                        MONO_INST_NEW (cfg, ins, OP_SETLRET);
-                       ins->sreg1 = val->dreg + 1;
-                       ins->sreg2 = val->dreg + 2;
+                       ins->sreg1 = val->dreg + 1 + REGPAIR_HIGH;
+                       ins->sreg2 = val->dreg + 1 + REGPAIR_LOW;
                        MONO_ADD_INS (cfg->cbb, ins);
                        return;
                }
@@ -3552,8 +3549,8 @@
                        mips_mtc1 (code, ins->dreg, ins->sreg1);
                        break;
                case OP_MIPS_MTC1S_2:
-                       mips_mtc1 (code, ins->dreg, ins->sreg1);
-                       mips_mtc1 (code, ins->dreg+1, ins->sreg2);
+                       mips_mtc1 (code, ins->dreg + REGPAIR_HIGH, ins->sreg1);
+                       mips_mtc1 (code, ins->dreg + REGPAIR_LOW,  ins->sreg2);
                        break;
                case OP_MIPS_MFC1S:
                        mips_mfc1 (code, ins->dreg, ins->sreg1);
@@ -3565,8 +3562,8 @@
 #if 0
                        mips_dmfc1 (code, ins->dreg, ins->sreg1);
 #else
-                       mips_mfc1 (code, ins->dreg+1, ins->sreg1);
-                       mips_mfc1 (code, ins->dreg, ins->sreg1+1);
+                       mips_mfc1 (code, ins->dreg,   ins->sreg1 + REGPAIR_LOW);
+                       mips_mfc1 (code, ins->dreg+1, ins->sreg1 +
REGPAIR_HIGH);
 #endif
                        break;

@@ -4012,8 +4009,8 @@
                        mips_ldc1 (code, ins->dreg, mips_at,
((guint32)ins->inst_p0) & 0xffff);
 #else
                        mips_load_const (code, mips_at, ins->inst_p0);
-                       mips_lwc1 (code, ins->dreg, mips_at, 4);
-                       mips_lwc1 (code, ins->dreg+1, mips_at, 0);
+                       mips_lwc1 (code, ins->dreg + REGPAIR_LOW,  mips_at, 0);
+                       mips_lwc1 (code, ins->dreg + REGPAIR_HIGH, mips_at, 4);
 #endif
                        break;
                case OP_R4CONST:
@@ -4029,31 +4026,31 @@
                case OP_STORER8_MEMBASE_REG:
                        if (mips_is_imm16 (ins->inst_offset)) {
 #if _MIPS_SIM == _ABIO32
-                               mips_swc1 (code, ins->sreg1,
ins->inst_destbasereg, ins->inst_offset+4);
-                               mips_swc1 (code, ins->sreg1+1,
ins->inst_destbasereg, ins->inst_offset);
+                                mips_swc1 (code, ins->sreg1 +
REGPAIR_LOW,  ins->inst_destbasereg, ins->inst_offset);
+                               mips_swc1 (code, ins->sreg1 +
REGPAIR_HIGH, ins->inst_destbasereg, ins->inst_offset+4);
 #elif _MIPS_SIM == _ABIN32
                                mips_sdc1 (code, ins->sreg1,
ins->inst_destbasereg, ins->inst_offset);
 #endif
                        } else {
                                mips_load_const (code, mips_at,
ins->inst_offset);
                                mips_addu (code, mips_at, mips_at,
ins->inst_destbasereg);
-                               mips_swc1 (code, ins->sreg1, mips_at, 4);
-                               mips_swc1 (code, ins->sreg1+1, mips_at, 0);
+                               mips_swc1 (code, ins->sreg1 +
REGPAIR_LOW,  mips_at, 0);
+                               mips_swc1 (code, ins->sreg1 +
REGPAIR_HIGH, mips_at, 4);
                        }
                        break;
                case OP_LOADR8_MEMBASE:
                        if (mips_is_imm16 (ins->inst_offset)) {
 #if _MIPS_SIM == _ABIO32
-                               mips_lwc1 (code, ins->dreg,
ins->inst_basereg, ins->inst_offset+4);
-                               mips_lwc1 (code, ins->dreg+1,
ins->inst_basereg, ins->inst_offset);
+                                mips_lwc1 (code, ins->dreg +
REGPAIR_LOW,  ins->inst_basereg, ins->inst_offset);
+                               mips_lwc1 (code, ins->dreg +
REGPAIR_HIGH, ins->inst_basereg, ins->inst_offset+4);
 #elif _MIPS_SIM == _ABIN32
                                mips_ldc1 (code, ins->dreg,
ins->inst_basereg, ins->inst_offset);
 #endif
                        } else {
                                mips_load_const (code, mips_at,
ins->inst_offset);
                                mips_addu (code, mips_at, mips_at,
ins->inst_basereg);
-                               mips_lwc1 (code, ins->dreg, mips_at, 4);
-                               mips_lwc1 (code, ins->dreg+1, mips_at, 0);
+                               mips_lwc1 (code, ins->dreg +
REGPAIR_LOW,  mips_at, 0);
+                               mips_lwc1 (code, ins->dreg +
REGPAIR_HIGH, mips_at, 4);
                        }
                        break;
                case OP_STORER4_MEMBASE_REG:
@@ -4781,8 +4778,8 @@
                                g_assert (mips_is_imm16 (inst->inst_offset));
                                if (ainfo->size == 8) {
 #if _MIPS_SIM == _ABIO32
-                                       mips_swc1 (code, ainfo->reg,
inst->inst_basereg, inst->inst_offset+4);
-                                       mips_swc1 (code, ainfo->reg+1,
inst->inst_basereg, inst->inst_offset);
+                                       mips_swc1 (code, ainfo->reg +
REGPAIR_LOW,  inst->inst_basereg, inst->inst_offset);
+                                       mips_swc1 (code, ainfo->reg +
REGPAIR_HIGH, inst->inst_basereg, inst->inst_offset + 4);
 #elif _MIPS_SIM == _ABIN32
                                        mips_sdc1 (code, ainfo->reg,
inst->inst_basereg, inst->inst_offset);
 #endif


# svn diff mono/mini/mini-mips.h
Index: mono/mini/mini-mips.h
===================================================================
--- mono/mini/mini-mips.h       (revision 136576)
+++ mono/mini/mini-mips.h       (working copy)
@@ -175,16 +175,18 @@

 /* Parameters used by the register allocator */

-/* On Mips, for regpairs, the lower-numbered reg is most significant
- * This is true in both big and little endian
- */
-
 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
 #define RET_REG1 mips_v0
 #define RET_REG2 mips_v1
+
+#define REGPAIR_LOW   0
+#define REGPAIR_HIGH  1
 #else
 #define RET_REG1 mips_v1
 #define RET_REG2 mips_v0
+
+#define REGPAIR_LOW   1
+#define REGPAIR_HIGH  0
 #endif

 #define MONO_ARCH_INST_SREG2_MASK(ins)         (0)

Would be great if someone can take a quick look at my code.

Thanks,
Rayson


More information about the Mono-devel-list mailing list