[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