Skip to contentSkip to conversation

tcg-sparc improvements

PATCH Applied Richard Henderson 3 participants 9 messages Jan 11, 2010 – Jan 12, 2010

lore
Share & tools
lore
#0 lore raw

cover tcg-sparc improvements

As noticed elsewhere on the list mulu2_i32 is missing. Which led me to notice that add2_i32 and sub2_i32 were also missing and also led me to notice that division was incorrectly implemented.

My initial implementation of 32-bit division copied the existing practice of using the 64-bit division insns for sparcv9, with proper sign/zero extensions on the input operands. But that required extra temporaries and quickly got ugly. In the end I thought it was clearer to simply use the 32-bit division insns unconditionally.

That excercise, however, made me notice that 32-bit extension was not special-cased, leading to the final patch.

r~

Richard Henderson (5):
tcg-sparc: Add tcg_out_arithc.
tcg-sparc: Implement add2, sub2, mulu2.
tcg-sparc: Do not remove %o[012] from 'r' constraint.
tcg-sparc: Implement division properly.
tcg-sparc: Implement ext32[su]_i64

 tcg/sparc/tcg-target.c |  206 ++++++++++++++++++++++++++++++++----------------
 tcg/sparc/tcg-target.h |    8 ++
 2 files changed, 145 insertions(+), 69 deletions(-)
#1 lore raw

PATCH 1/5 tcg-sparc: Add tcg_out_arithc.

Add a function to handle the register-vs-immediate test for arithmetic.

Also, adjust the OP_32_64 macro so that it auto-indents properly. Rename the gen_arith32 label to gen_arith, since it handles 64-bit arithmetic as well.

---
 tcg/sparc/tcg-target.c |   86 ++++++++++++++++++++++++------------------------
 1 files changed, 43 insertions(+), 43 deletions(-)
tcg/sparc/tcg-target.c +43 -43
index 8f094e5..067e26e 100644
@@ -285,6 +285,13 @@ static inline void tcg_out_arithi(TCGContext *s, int rd, int rs1,
               INSN_IMM13(offset));
 }
 
+static void tcg_out_arithc(TCGContext *s, int rd, int rs1,
+			   int val2, int val2const, int op)
+{
+    tcg_out32(s, op | INSN_RD(rd) | INSN_RS1(rs1)
+              | (val2const ? INSN_IMM13(val2) : INSN_RS2(val2)));
+}
+
 static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
 {
     tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR);
@@ -481,10 +488,7 @@ static const uint8_t tcg_cond_to_bcond[10] = {
 
 static void tcg_out_cmp(TCGContext *s, TCGArg c1, TCGArg c2, int c2const)
 {
-    if (c2const)
-        tcg_out_arithi(s, TCG_REG_G0, c1, c2, ARITH_SUBCC);
-    else
-        tcg_out_arith(s, TCG_REG_G0, c1, c2, ARITH_SUBCC);
+    tcg_out_arithc(s, TCG_REG_G0, c1, c2, c2const, ARITH_SUBCC);
 }
 
 static void tcg_out_brcond_i32(TCGContext *s, int cond,
@@ -1036,22 +1040,22 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
 
 #if TCG_TARGET_REG_BITS == 64
 #define OP_32_64(x)                             \
-        glue(glue(case INDEX_op_, x), _i32:)    \
-        glue(glue(case INDEX_op_, x), _i64:)
+        glue(glue(case INDEX_op_, x), _i32):    \
+        glue(glue(case INDEX_op_, x), _i64)
 #else
 #define OP_32_64(x)                             \
-        glue(glue(case INDEX_op_, x), _i32:)
+        glue(glue(case INDEX_op_, x), _i32)
 #endif
-        OP_32_64(ld8u);
+    OP_32_64(ld8u):
         tcg_out_ldst(s, args[0], args[1], args[2], LDUB);
         break;
-        OP_32_64(ld8s);
+    OP_32_64(ld8s):
         tcg_out_ldst(s, args[0], args[1], args[2], LDSB);
         break;
-        OP_32_64(ld16u);
+    OP_32_64(ld16u):
         tcg_out_ldst(s, args[0], args[1], args[2], LDUH);
         break;
-        OP_32_64(ld16s);
+    OP_32_64(ld16s):
         tcg_out_ldst(s, args[0], args[1], args[2], LDSH);
         break;
     case INDEX_op_ld_i32:
@@ -1060,10 +1064,10 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
 #endif
         tcg_out_ldst(s, args[0], args[1], args[2], LDUW);
         break;
-        OP_32_64(st8);
+    OP_32_64(st8):
         tcg_out_ldst(s, args[0], args[1], args[2], STB);
         break;
-        OP_32_64(st16);
+    OP_32_64(st16):
         tcg_out_ldst(s, args[0], args[1], args[2], STH);
         break;
     case INDEX_op_st_i32:
@@ -1072,50 +1076,50 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
 #endif
         tcg_out_ldst(s, args[0], args[1], args[2], STW);
         break;
-        OP_32_64(add);
+    OP_32_64(add):
         c = ARITH_ADD;
-        goto gen_arith32;
-        OP_32_64(sub);
+        goto gen_arith;
+    OP_32_64(sub):
         c = ARITH_SUB;
-        goto gen_arith32;
-        OP_32_64(and);
+        goto gen_arith;
+    OP_32_64(and):
         c = ARITH_AND;
-        goto gen_arith32;
-        OP_32_64(or);
+        goto gen_arith;
+    OP_32_64(or):
         c = ARITH_OR;
-        goto gen_arith32;
-        OP_32_64(xor);
+        goto gen_arith;
+    OP_32_64(xor):
         c = ARITH_XOR;
-        goto gen_arith32;
+        goto gen_arith;
     case INDEX_op_shl_i32:
         c = SHIFT_SLL;
-        goto gen_arith32;
+        goto gen_arith;
     case INDEX_op_shr_i32:
         c = SHIFT_SRL;
-        goto gen_arith32;
+        goto gen_arith;
     case INDEX_op_sar_i32:
         c = SHIFT_SRA;
-        goto gen_arith32;
+        goto gen_arith;
     case INDEX_op_mul_i32:
         c = ARITH_UMUL;
-        goto gen_arith32;
+        goto gen_arith;
     case INDEX_op_div2_i32:
 #if defined(__sparc_v9__) || defined(__sparc_v8plus__)
         c = ARITH_SDIVX;
-        goto gen_arith32;
+        goto gen_arith;
 #else
         tcg_out_sety(s, 0);
         c = ARITH_SDIV;
-        goto gen_arith32;
+        goto gen_arith;
 #endif
     case INDEX_op_divu2_i32:
 #if defined(__sparc_v9__) || defined(__sparc_v8plus__)
         c = ARITH_UDIVX;
-        goto gen_arith32;
+        goto gen_arith;
 #else
         tcg_out_sety(s, 0);
         c = ARITH_UDIV;
-        goto gen_arith32;
+        goto gen_arith;
 #endif
 
     case INDEX_op_brcond_i32:
@@ -1173,22 +1177,22 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
         break;
     case INDEX_op_shl_i64:
         c = SHIFT_SLLX;
-        goto gen_arith32;
+        goto gen_arith;
     case INDEX_op_shr_i64:
         c = SHIFT_SRLX;
-        goto gen_arith32;
+        goto gen_arith;
     case INDEX_op_sar_i64:
         c = SHIFT_SRAX;
-        goto gen_arith32;
+        goto gen_arith;
     case INDEX_op_mul_i64:
         c = ARITH_MULX;
-        goto gen_arith32;
+        goto gen_arith;
     case INDEX_op_div2_i64:
         c = ARITH_SDIVX;
-        goto gen_arith32;
+        goto gen_arith;
     case INDEX_op_divu2_i64:
         c = ARITH_UDIVX;
-        goto gen_arith32;
+        goto gen_arith;
 
     case INDEX_op_brcond_i64:
         tcg_out_brcond_i64(s, args[2], args[0], args[1], const_args[1],
@@ -1202,12 +1206,8 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
         break;
 
 #endif
-    gen_arith32:
-        if (const_args[2]) {
-            tcg_out_arithi(s, args[0], args[1], args[2], c);
-        } else {
-            tcg_out_arith(s, args[0], args[1], args[2], c);
-        }
+    gen_arith:
+        tcg_out_arithc(s, args[0], args[1], args[2], const_args[2], c);
         break;
 
     default:
Signature · 1 line
1.6.5.2
#2 lore raw

PATCH 2/5 tcg-sparc: Implement add2, sub2, mulu2.

In reply to Richard Henderson

Add missing 32-bit double-word support opcodes.

---
 tcg/sparc/tcg-target.c |   27 +++++++++++++++++++++++++++
 1 files changed, 27 insertions(+), 0 deletions(-)
tcg/sparc/tcg-target.c +27 -0
index 067e26e..6934580 100644
@@ -215,6 +215,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
 #define BA         (INSN_OP(0) | INSN_COND(COND_A, 0) | INSN_OP2(0x2))
 
 #define ARITH_ADD  (INSN_OP(2) | INSN_OP3(0x00))
+#define ARITH_ADDCC (INSN_OP(2) | INSN_OP3(0x10))
 #define ARITH_AND  (INSN_OP(2) | INSN_OP3(0x01))
 #define ARITH_OR   (INSN_OP(2) | INSN_OP3(0x02))
 #define ARITH_ORCC (INSN_OP(2) | INSN_OP3(0x12))
@@ -238,6 +239,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
 #define SHIFT_SRLX (INSN_OP(2) | INSN_OP3(0x26) | (1 << 12))
 #define SHIFT_SRAX (INSN_OP(2) | INSN_OP3(0x27) | (1 << 12))
 
+#define RDY        (INSN_OP(2) | INSN_OP3(0x28) | INSN_RS1(0))
 #define WRY        (INSN_OP(2) | INSN_OP3(0x30))
 #define JMPL       (INSN_OP(2) | INSN_OP3(0x38))
 #define SAVE       (INSN_OP(2) | INSN_OP3(0x3c))
@@ -410,6 +412,11 @@ static inline void tcg_out_sety(TCGContext *s, tcg_target_long val)
         fprintf(stderr, "unimplemented sety %ld\n", (long)val);
 }
 
+static inline void tcg_out_rdy(TCGContext *s, int rd)
+{
+    tcg_out32(s, RDY | INSN_RD(rd));
+}
+
 static inline void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
 {
     if (val != 0) {
@@ -1132,6 +1139,23 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
                             args[2], const_args[2],
                             args[3], const_args[3], args[5]);
         break;
+    case INDEX_op_add2_i32:
+        tcg_out_arithc(s, args[0], args[2], args[4], const_args[4],
+                       ARITH_ADDCC);
+        tcg_out_arithc(s, args[1], args[3], args[5], const_args[5],
+                       ARITH_ADDX);
+        break;
+    case INDEX_op_sub2_i32:
+        tcg_out_arithc(s, args[0], args[2], args[4], const_args[4],
+                       ARITH_SUBCC);
+        tcg_out_arithc(s, args[1], args[3], args[5], const_args[5],
+                       ARITH_SUBX);
+        break;
+    case INDEX_op_mulu2_i32:
+        tcg_out_arithc(s, args[0], args[2], args[3], const_args[3],
+                       ARITH_UMUL);
+        tcg_out_rdy(s, args[1]);
+        break;
 #endif
 
     case INDEX_op_qemu_ld8u:
@@ -1250,6 +1274,9 @@ static const TCGTargetOpDef sparc_op_defs[] = {
     { INDEX_op_brcond_i32, { "r", "rJ" } },
 #if TCG_TARGET_REG_BITS == 32
     { INDEX_op_brcond2_i32, { "r", "r", "rJ", "rJ" } },
+    { INDEX_op_add2_i32, { "r", "r", "r", "r", "rJ", "rJ" } },
+    { INDEX_op_sub2_i32, { "r", "r", "r", "r", "rJ", "rJ" } },
+    { INDEX_op_mulu2_i32, { "r", "r", "r", "rJ" } },
 #endif
 
     { INDEX_op_qemu_ld8u, { "r", "L" } },
Signature · 1 line
1.6.5.2
#3 lore raw

PATCH 3/5 tcg-sparc: Do not remove %o[012] from 'r' constraint.

In reply to Richard Henderson

Only 'L' constraint needs that.

---
 tcg/sparc/tcg-target.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
tcg/sparc/tcg-target.c +3 -0
index 6934580..8675fce 100644
@@ -143,6 +143,9 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
     ct_str = *pct_str;
     switch (ct_str[0]) {
     case 'r':
+        ct->ct |= TCG_CT_REG;
+        tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
+        break;
     case 'L': /* qemu_ld/st constraint */
         ct->ct |= TCG_CT_REG;
         tcg_regset_set32(ct->u.regs, 0, 0xffffffff);
Signature · 1 line
1.6.5.2
#4 lore raw

PATCH 4/5 tcg-sparc: Implement division properly.

In reply to Richard Henderson

The {div,divu}2 opcodes are intended for systems for which the division instruction produces both quotient and remainder. Sparc is not such a system. Indeed, the remainder must be computed as

quot = a / b
rem = a - (quot * b)

Split out a tcg_out_div32 function that properly initializes Y with the extension of the input to 64-bits. Discard the code that used the 64-bit DIVX on sparc9/sparcv8plus without extending the inputs to 64-bits. Implement remainders in terms of division followed by multiplication.

---
 tcg/sparc/tcg-target.c |   82 ++++++++++++++++++++++++++++++-----------------
 tcg/sparc/tcg-target.h |    3 ++
 2 files changed, 55 insertions(+), 30 deletions(-)
tcg/sparc/tcg-target.c +52 -30
index 8675fce..1bef2fb 100644
@@ -243,7 +243,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
 #define SHIFT_SRAX (INSN_OP(2) | INSN_OP3(0x27) | (1 << 12))
 
 #define RDY        (INSN_OP(2) | INSN_OP3(0x28) | INSN_RS1(0))
-#define WRY        (INSN_OP(2) | INSN_OP3(0x30))
+#define WRY        (INSN_OP(2) | INSN_OP3(0x30) | INSN_RD(0))
 #define JMPL       (INSN_OP(2) | INSN_OP3(0x38))
 #define SAVE       (INSN_OP(2) | INSN_OP3(0x3c))
 #define RESTORE    (INSN_OP(2) | INSN_OP3(0x3d))
@@ -407,12 +407,9 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
         tcg_out_ldst(s, arg, arg1, arg2, STX);
 }
 
-static inline void tcg_out_sety(TCGContext *s, tcg_target_long val)
+static inline void tcg_out_sety(TCGContext *s, int rs)
 {
-    if (val == 0 || val == -1)
-        tcg_out32(s, WRY | INSN_IMM13(val));
-    else
-        fprintf(stderr, "unimplemented sety %ld\n", (long)val);
+    tcg_out32(s, WRY | INSN_RS1(TCG_REG_G0) | INSN_RS2(rs));
 }
 
 static inline void tcg_out_rdy(TCGContext *s, int rd)
@@ -444,6 +441,21 @@ static inline void tcg_out_andi(TCGContext *s, int reg, tcg_target_long val)
     }
 }
 
+static void tcg_out_div32(TCGContext *s, int rd, int rs1,
+                          int val2, int val2const, int uns)
+{
+    /* Load Y with the sign/zero extension of RS1 to 64-bits.  */
+    if (uns) {
+        tcg_out_sety(s, TCG_REG_G0);
+    } else {
+        tcg_out_arith(s, TCG_REG_I5, rs1, 31, SHIFT_SRA);
+        tcg_out_sety(s, TCG_REG_I5);
+    }
+
+    tcg_out_arithc(s, rd, rs1, val2, val2const,
+                   uns ? ARITH_UDIV : ARITH_SDIV);
+}
+
 static inline void tcg_out_nop(TCGContext *s)
 {
     tcg_out_sethi(s, TCG_REG_G0, 0);
@@ -1113,24 +1125,22 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
     case INDEX_op_mul_i32:
         c = ARITH_UMUL;
         goto gen_arith;
-    case INDEX_op_div2_i32:
-#if defined(__sparc_v9__) || defined(__sparc_v8plus__)
-        c = ARITH_SDIVX;
-        goto gen_arith;
-#else
-        tcg_out_sety(s, 0);
-        c = ARITH_SDIV;
-        goto gen_arith;
-#endif
-    case INDEX_op_divu2_i32:
-#if defined(__sparc_v9__) || defined(__sparc_v8plus__)
-        c = ARITH_UDIVX;
-        goto gen_arith;
-#else
-        tcg_out_sety(s, 0);
-        c = ARITH_UDIV;
-        goto gen_arith;
-#endif
+
+    case INDEX_op_div_i32:
+        tcg_out_div32(s, args[0], args[1], args[2], const_args[2], 0);
+        break;
+    case INDEX_op_divu_i32:
+        tcg_out_div32(s, args[0], args[1], args[2], const_args[2], 1);
+        break;
+        
+    case INDEX_op_rem_i32:
+    case INDEX_op_remu_i32:
+        tcg_out_div32(s, TCG_REG_I5, args[1], args[2], const_args[2],
+                      opc == INDEX_op_remu_i32);
+        tcg_out_arithc(s, TCG_REG_I5, TCG_REG_I5, args[2], const_args[2],
+                       ARITH_UMUL);
+        tcg_out_arith(s, args[0], args[1], TCG_REG_I5, ARITH_SUB);
+        break;
 
     case INDEX_op_brcond_i32:
         tcg_out_brcond_i32(s, args[2], args[0], args[1], const_args[1],
@@ -1214,12 +1224,20 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
     case INDEX_op_mul_i64:
         c = ARITH_MULX;
         goto gen_arith;
-    case INDEX_op_div2_i64:
+    case INDEX_op_div_i64:
         c = ARITH_SDIVX;
         goto gen_arith;
-    case INDEX_op_divu2_i64:
+    case INDEX_op_divu_i64:
         c = ARITH_UDIVX;
         goto gen_arith;
+    case INDEX_op_rem_i64:
+    case INDEX_op_remu_i64:
+        tcg_out_arithc(s, TCG_REG_I5, args[1], args[2], const_args[2],
+                       opc == INDEX_op_rem_i64 ? ARITH_SDIVX : ARITH_UDIVX);
+        tcg_out_arithc(s, TCG_REG_I5, TCG_REG_I5, args[2], const_args[2],
+                       ARITH_MULX);
+        tcg_out_arith(s, args[0], args[1], TCG_REG_I5, ARITH_SUB);
+        break;
 
     case INDEX_op_brcond_i64:
         tcg_out_brcond_i64(s, args[2], args[0], args[1], const_args[1],
@@ -1263,8 +1281,10 @@ static const TCGTargetOpDef sparc_op_defs[] = {
 
     { INDEX_op_add_i32, { "r", "r", "rJ" } },
     { INDEX_op_mul_i32, { "r", "r", "rJ" } },
-    { INDEX_op_div2_i32, { "r", "r", "0", "1", "r" } },
-    { INDEX_op_divu2_i32, { "r", "r", "0", "1", "r" } },
+    { INDEX_op_div_i32, { "r", "r", "rJ" } },
+    { INDEX_op_divu_i32, { "r", "r", "rJ" } },
+    { INDEX_op_rem_i32, { "r", "r", "rJ" } },
+    { INDEX_op_remu_i32, { "r", "r", "rJ" } },
     { INDEX_op_sub_i32, { "r", "r", "rJ" } },
     { INDEX_op_and_i32, { "r", "r", "rJ" } },
     { INDEX_op_or_i32, { "r", "r", "rJ" } },
@@ -1312,8 +1332,10 @@ static const TCGTargetOpDef sparc_op_defs[] = {
 
     { INDEX_op_add_i64, { "r", "r", "rJ" } },
     { INDEX_op_mul_i64, { "r", "r", "rJ" } },
-    { INDEX_op_div2_i64, { "r", "r", "0", "1", "r" } },
-    { INDEX_op_divu2_i64, { "r", "r", "0", "1", "r" } },
+    { INDEX_op_div_i64, { "r", "r", "rJ" } },
+    { INDEX_op_divu_i64, { "r", "r", "rJ" } },
+    { INDEX_op_rem_i64, { "r", "r", "rJ" } },
+    { INDEX_op_remu_i64, { "r", "r", "rJ" } },
     { INDEX_op_sub_i64, { "r", "r", "rJ" } },
     { INDEX_op_and_i64, { "r", "r", "rJ" } },
     { INDEX_op_or_i64, { "r", "r", "rJ" } },
tcg/sparc/tcg-target.h +3 -0
index e8f8f65..e00707b 100644
@@ -88,6 +88,9 @@ enum {
 #endif
 
 /* optional instructions */
+#define TCG_TARGET_HAS_div_i32
+#define TCG_TARGET_HAS_div_i64
+
 //#define TCG_TARGET_HAS_bswap32_i32
 //#define TCG_TARGET_HAS_bswap64_i64
 //#define TCG_TARGET_HAS_neg_i32
Signature · 1 line
1.6.5.2
#5 lore raw

Re: [Qemu-devel] [PATCH 4/5] tcg-sparc: Implement division properly.

tcg/sparc/tcg-target.c static inline void tcg_out_andi(TCGContext *s, int reg, tcg_target_long val) · line 451

Quoted 5 lines · Richard Henderson
tcg/sparc/tcg-target.c +5 -0
+    /* Load Y with the sign/zero extension of RS1 to 64-bits.  */
+    if (uns) {
+        tcg_out_sety(s, TCG_REG_G0);
+    } else {
+        tcg_out_arith(s, TCG_REG_I5, rs1, 31, SHIFT_SRA);

Bah. tcg_out_arithi.

Programming by code inspection only sucks.

r~

#6 lore raw

PATCH 5/5 tcg-sparc: Implement ext32[su]_i64

In reply to Richard Henderson

The 32-bit right-shift instructions is defined to extend the shifted output to 64-bits. A shift count of zero therefore is a simple extension without actually shifting.

---
 tcg/sparc/tcg-target.c |   16 ++++++++++++++++
 tcg/sparc/tcg-target.h |    5 +++++
 2 files changed, 21 insertions(+), 0 deletions(-)
tcg/sparc/tcg-target.c +16 -0
index 1bef2fb..bc28f43 100644
@@ -1238,6 +1238,20 @@ static inline void tcg_out_op(TCGContext *s, int opc, const TCGArg *args,
                        ARITH_MULX);
         tcg_out_arith(s, args[0], args[1], TCG_REG_I5, ARITH_SUB);
         break;
+    case INDEX_op_ext32s_i64:
+        if (const_args[1]) {
+            tcg_out_movi(s, TCG_TYPE_I64, args[0], (int32_t)args[1]);
+        } else {
+            tcg_out_arithi(s, args[0], args[1], 0, SHIFT_SRA);
+        }
+        break;
+    case INDEX_op_ext32u_i64:
+        if (const_args[1]) {
+            tcg_out_movi_imm32(s, args[0], args[1]);
+        } else {
+            tcg_out_arithi(s, args[0], args[1], 0, SHIFT_SRL);
+        }
+        break;
 
     case INDEX_op_brcond_i64:
         tcg_out_brcond_i64(s, args[2], args[0], args[1], const_args[1],
@@ -1344,6 +1358,8 @@ static const TCGTargetOpDef sparc_op_defs[] = {
     { INDEX_op_shl_i64, { "r", "r", "rJ" } },
     { INDEX_op_shr_i64, { "r", "r", "rJ" } },
     { INDEX_op_sar_i64, { "r", "r", "rJ" } },
+    { INDEX_op_ext32s_i64, { "r", "ri" } },
+    { INDEX_op_ext32u_i64, { "r", "ri" } },
 
     { INDEX_op_brcond_i64, { "r", "rJ" } },
 #endif
tcg/sparc/tcg-target.h +5 -0
index e00707b..d27ed5a 100644
@@ -91,6 +91,11 @@ enum {
 #define TCG_TARGET_HAS_div_i32
 #define TCG_TARGET_HAS_div_i64
 
+#if TCG_TARGET_REG_BITS == 64
+#define TCG_TARGET_HAS_ext32s_i64
+#define TCG_TARGET_HAS_ext32u_i64
+#endif
+
 //#define TCG_TARGET_HAS_bswap32_i32
 //#define TCG_TARGET_HAS_bswap64_i64
 //#define TCG_TARGET_HAS_neg_i32
Signature · 1 line
1.6.5.2
#7 lore raw
In reply to Richard Henderson
Quoted 8 lines · Richard Henderson

Richard Henderson (5):
tcg-sparc: Add tcg_out_arithc.
tcg-sparc: Implement add2, sub2, mulu2.
tcg-sparc: Do not remove %o[012] from 'r' constraint.
tcg-sparc: Implement division properly.
tcg-sparc: Implement ext32[su]_i64

Great work :-) Now the NetBSD malta kernel boots using qemu-system-mips on a sparc target!

log:

uname -a
SunOS opensolaris 5.11 snv_111b sun4u sparc SUNW,Ultra-5_10 Solaris

./mips-softmmu/qemu-system-mips --kernel ../../netbsd_malta -m 64 -nographic

MIPS32/64 params: cpu arch: 32
MIPS32/64 params: TLB entries: 16
MIPS32/64 params: Icache: line = 16, total = 2048, ways = 2

                 sets = 64
MIPS32/64 params: Dcache: line = 16, total = 2048, ways = 2
                 sets = 64

picache_stride = 1024
picache_loopcount = 2
pdcache_stride = 1024
pdcache_loopcount = 2
[ Kernel symbol table missing! ]
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007, 2008, 2009
The NetBSD Foundation, Inc. All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
The Regents of the University of California. All rights reserved.

NetBSD 5.0.1 (MALTA) #0: Wed Jul 29 19:36:39 UTC 2009

[email protected]:/home/builds/ab/netbsd-5-0-1-RELEASE/evbmips-mipseb/200907292356Z-obj/home/builds/ab/netbsd-5-0-1-RELEASE/src/sys/arch/evbmips/compile/MALTA total memory = 65536 KB
avail memory = 59460 KB
mainbus0 (root)
cpu0 at mainbus0: 2152.04MHz (hz cycles = 10760233, delay divisor = 1076)
cpu0: MIPS 24K (0x19300) Rev. 0 with software emulated floating point
cpu0: 2KB/16B 2-way set-associative L1 Instruction cache, 16 TLB entries
cpu0: 2KB/16B 2-way set-associative write-back L1 Data cache
gt0 at mainbus0 addr 0x1be00000
pci0 at gt0

Applied
#8 lore raw
In reply to Richard Henderson
Quoted 4 lines · Richard Henderson

As noticed elsewhere on the list mulu2_i32 is missing.  Which led me to notice that add2_i32 and sub2_i32 were also missing and also led me to notice that division was incorrectly implemented.

Quoted 8 lines

My initial implementation of 32-bit division copied the existing practice of using the 64-bit division insns for sparcv9, with proper sign/zero extensions on the input operands.  But that required extra temporaries and quickly got ugly.  In the end I thought it was clearer to simply use the 32-bit division insns unconditionally.

That excercise, however, made me notice that 32-bit extension was not special-cased, leading to the final patch.

Thanks, applied all (4/5 with your fix).