32-bit condition functions(like brcond_i32) should only
compare the low half parts of two 64-bit host registers.
However, MIPS64 does not have distinct instruction for
such operation. The operands should be sign extended
to fit the case.
Gcc handles 32-bit comparison in the same way, as the
following example shows:
[a.c]
main()
{
long a = 0xcccccccc;
long b = 0xdddddddd;
int c = (int)a > (int)b;
}
$ gcc a.c -S -mabi=64
$ vi a.s
.......
sd $2,0($fp)
sd $3,8($fp)
lw $2,0($fp)
lw $3,8($fp)
slt $1,$2,$3
........
Cc: Aurelien Jarno <[email protected]>
Cc: James Hogan <[email protected]>
Signed-off-by: Richard Henderson <[email protected]>
Signed-off-by: Jin Guojie <[email protected]>
---
tcg/mips/tcg-target.inc.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c
index 95090b6..0eb48ce 100644
--- a/tcg/mips/tcg-target.inc.c
+++ b/tcg/mips/tcg-target.inc.c
@@ -696,6 +696,11 @@ static inline void tcg_out_ext32u(TCGContext *s, TCGReg
ret, TCGReg arg)
}
}
+static inline void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
+{
+ tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
+}
+
static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data,
TCGReg addr, intptr_t ofs)
{
@@ -2023,6 +2028,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode
opc,
break;
case INDEX_op_brcond_i32:
+#if TCG_TARGET_REG_BITS == 64
+ tcg_out_ext32s(s, a0, a0);
+ tcg_out_ext32s(s, a1, a1);
+ /* FALLTHRU */
+#endif
case INDEX_op_brcond_i64:
tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
break;
@@ -2031,11 +2041,21 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode
opc,
break;
case INDEX_op_movcond_i32:
+#if TCG_TARGET_REG_BITS == 64
+ tcg_out_ext32s(s, a1, a1);
+ tcg_out_ext32s(s, a2, a2);
+ /* FALLTHRU */
+#endif
case INDEX_op_movcond_i64:
tcg_out_movcond(s, args[5], a0, a1, a2, args[3], args[4]);
break;
case INDEX_op_setcond_i32:
+#if TCG_TARGET_REG_BITS == 64
+ tcg_out_ext32s(s, a1, a1);
+ tcg_out_ext32s(s, a2, a2);
+ /* FALLTHRU */
+#endif
case INDEX_op_setcond_i64:
tcg_out_setcond(s, args[3], a0, a1, a2);
break;
--
2.1.0