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 <aurel...@aurel32.net>
Cc: James Hogan <james.ho...@imgtec.com>
Signed-off-by: Richard Henderson <r...@twiddle.net>
Signed-off-by: Jin Guojie <jinguo...@loongson.cn>
---
 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



Reply via email to