qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: James Hogan <james.hogan@imgtec.com>
To: qemu-devel@nongnu.org
Cc: James Hogan <james.hogan@imgtec.com>,
	Leon Alrae <leon.alrae@imgtec.com>,
	Aurelien Jarno <aurelien@aurel32.net>,
	Richard Henderson <rth@twiddle.net>
Subject: [Qemu-devel] [PATCH v3 6/6] tcg/mips: Support r6 SEL{NE, EQ}Z instead of MOVN/MOVZ
Date: Fri, 2 Oct 2015 13:24:17 +0100	[thread overview]
Message-ID: <1443788657-14537-7-git-send-email-james.hogan@imgtec.com> (raw)
In-Reply-To: <1443788657-14537-1-git-send-email-james.hogan@imgtec.com>

Extend MIPS movcond implementation to support the SELNEZ/SELEQZ
instructions introduced in MIPS r6 (where MOVN/MOVZ have been removed).

Whereas the "MOVN/MOVZ rd, rs, rt" instructions have the following
semantics:
 rd = [!]rt ? rs : rd

The "SELNEZ/SELEQZ rd, rs, rt" instructions are slightly different:
 rd = [!]rt ? rs : 0

First we ensure that if one of the movcond input values is zero that it
comes last (we can swap the input arguments if we invert the condition).
This is so that it can exactly match one of the SELNEZ/SELEQZ
instructions and avoid the need to emit the other one.

Otherwise we emit the opposite instruction first into a temporary
register, and OR that into the result:
 SELNEZ/SELEQZ  TMP1, v2, c1
 SELEQZ/SELNEZ  ret, v1, c1
 OR             ret, ret, TMP1

Which does the following:
 ret = cond ? v1 : v2

Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v3:
- Switch to using bool eqz to indicate whether to use SELEQZ / MOVZ
  instead of SELNEZ / MOVN (Richard).
- Add tcg_debug_assert(v2 == ret) for pre-r6 case with comment to remind
  reader that it should be guaranteed via constraints (Richard).

Changes in v2:
- Combine with patch 6 from v1, and drop functional changes to movcond
  implementation pre-r6. We now provide different constraints for
  movcond depending on presence of r6. (thanks Richard for feedback).
---
 tcg/mips/tcg-target.c | 43 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 37 insertions(+), 6 deletions(-)

diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index a937b1475d04..eff498991096 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -314,6 +314,8 @@ typedef enum {
     OPC_NOR      = OPC_SPECIAL | 0x27,
     OPC_SLT      = OPC_SPECIAL | 0x2A,
     OPC_SLTU     = OPC_SPECIAL | 0x2B,
+    OPC_SELEQZ   = OPC_SPECIAL | 0x35,
+    OPC_SELNEZ   = OPC_SPECIAL | 0x37,
 
     OPC_REGIMM   = 0x01 << 26,
     OPC_BLTZ     = OPC_REGIMM | (0x00 << 16),
@@ -858,13 +860,20 @@ static void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
 }
 
 static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
-                            TCGReg c1, TCGReg c2, TCGReg v)
+                            TCGReg c1, TCGReg c2, TCGReg v1, TCGReg v2)
 {
-    MIPSInsn m_opc = OPC_MOVN;
+    bool eqz = false;
+
+    /* If one of the values is zero, put it last to match SEL*Z instructions */
+    if (use_mips32r6_instructions && v1 == 0) {
+        v1 = v2;
+        v2 = 0;
+        cond = tcg_invert_cond(cond);
+    }
 
     switch (cond) {
     case TCG_COND_EQ:
-        m_opc = OPC_MOVZ;
+        eqz = true;
         /* FALLTHRU */
     case TCG_COND_NE:
         if (c2 != 0) {
@@ -877,14 +886,32 @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
         /* Minimize code size by preferring a compare not requiring INV.  */
         if (mips_cmp_map[cond] & MIPS_CMP_INV) {
             cond = tcg_invert_cond(cond);
-            m_opc = OPC_MOVZ;
+            eqz = true;
         }
         tcg_out_setcond(s, cond, TCG_TMP0, c1, c2);
         c1 = TCG_TMP0;
         break;
     }
 
-    tcg_out_opc_reg(s, m_opc, ret, v, c1);
+    if (use_mips32r6_instructions) {
+        MIPSInsn m_opc_t = eqz ? OPC_SELEQZ : OPC_SELNEZ;
+        MIPSInsn m_opc_f = eqz ? OPC_SELNEZ : OPC_SELEQZ;
+
+        if (v2 != 0) {
+            tcg_out_opc_reg(s, m_opc_f, TCG_TMP1, v2, c1);
+        }
+        tcg_out_opc_reg(s, m_opc_t, ret, v1, c1);
+        if (v2 != 0) {
+            tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP1);
+        }
+    } else {
+        MIPSInsn m_opc = eqz ? OPC_MOVZ : OPC_MOVN;
+
+        tcg_out_opc_reg(s, m_opc, ret, v1, c1);
+
+        /* This should be guaranteed via constraints */
+        tcg_debug_assert(v2 == ret);
+    }
 }
 
 static void tcg_out_call_int(TCGContext *s, tcg_insn_unit *arg, bool tail)
@@ -1577,7 +1604,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
 
     case INDEX_op_movcond_i32:
-        tcg_out_movcond(s, args[5], a0, a1, a2, args[3]);
+        tcg_out_movcond(s, args[5], a0, a1, a2, args[3], args[4]);
         break;
 
     case INDEX_op_setcond_i32:
@@ -1666,7 +1693,11 @@ static const TCGTargetOpDef mips_op_defs[] = {
     { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
 
     { INDEX_op_brcond_i32, { "rZ", "rZ" } },
+#if !use_mips32r6_instructions
     { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } },
+#else
+    { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
+#endif
     { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
     { INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
 
-- 
2.4.9

  parent reply	other threads:[~2015-10-02 12:24 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-02 12:24 [Qemu-devel] [PATCH v3 0/6] tcg/mips: Minimal R6 support James Hogan
2015-10-02 12:24 ` [Qemu-devel] [PATCH v3 1/6] tcg-opc.h: Simplify debug_insn_start def James Hogan
2015-10-08 16:12   ` Aurelien Jarno
2015-10-02 12:24 ` [Qemu-devel] [PATCH v3 2/6] disas/mips: Add R6 jr/jr.hb to disassembler James Hogan
2015-10-08 16:12   ` Aurelien Jarno
2015-10-02 12:24 ` [Qemu-devel] [PATCH v3 3/6] tcg/mips: Add use_mips32r6_instructions definition James Hogan
2015-10-08 16:12   ` Aurelien Jarno
2015-10-02 12:24 ` [Qemu-devel] [PATCH v3 4/6] tcg/mips: Support r6 JR encoding James Hogan
2015-10-08 16:15   ` Aurelien Jarno
2015-10-02 12:24 ` [Qemu-devel] [PATCH v3 5/6] tcg/mips: Support r6 multiply/divide encodings James Hogan
2015-10-08 16:19   ` Aurelien Jarno
2015-10-02 12:24 ` James Hogan [this message]
2015-10-07  9:46   ` [Qemu-devel] [PATCH v3 6/6] tcg/mips: Support r6 SEL{NE, EQ}Z instead of MOVN/MOVZ Richard Henderson
2015-10-07 10:34     ` James Hogan
2015-10-07 19:54       ` Richard Henderson
2015-10-07 11:47     ` Leon Alrae
2015-10-08 16:32       ` Aurelien Jarno
2015-10-08 16:31   ` Aurelien Jarno
2015-10-09 21:26     ` James Hogan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1443788657-14537-7-git-send-email-james.hogan@imgtec.com \
    --to=james.hogan@imgtec.com \
    --cc=aurelien@aurel32.net \
    --cc=leon.alrae@imgtec.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).