[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 09/10] tcg/mips: Support r6 SEL{NE, EQ}Z instead of M
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PULL 09/10] tcg/mips: Support r6 SEL{NE, EQ}Z instead of MOVN/MOVZ |
Date: |
Wed, 21 Oct 2015 11:42:58 -1000 |
From: James Hogan <address@hidden>
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
Reviewed-by: Aurelien Jarno <address@hidden>
Signed-off-by: James Hogan <address@hidden>
Signed-off-by: Richard Henderson <address@hidden>
Message-Id: <address@hidden>
---
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 a937b14..79e052f 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", "rZ" } },
+#else
{ INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rZ", "0" } },
+#endif
{ INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
{ INDEX_op_setcond2_i32, { "r", "rZ", "rZ", "rZ", "rZ" } },
--
2.4.3
- [Qemu-devel] [PULL 00/10] collected tcg patches, Richard Henderson, 2015/10/21
- [Qemu-devel] [PULL 01/10] tcg/ppc: Adjust exit_tb for change in prologue placement, Richard Henderson, 2015/10/21
- [Qemu-devel] [PULL 02/10] tcg/ppc: Revise goto_tb implementation, Richard Henderson, 2015/10/21
- [Qemu-devel] [PULL 03/10] tcg/ppc: Prefer mask over andi., Richard Henderson, 2015/10/21
- [Qemu-devel] [PULL 04/10] tcg-opc.h: Simplify insn_start def, Richard Henderson, 2015/10/21
- [Qemu-devel] [PULL 05/10] disas/mips: Add R6 jr/jr.hb to disassembler, Richard Henderson, 2015/10/21
- [Qemu-devel] [PULL 06/10] tcg/mips: Add use_mips32r6_instructions definition, Richard Henderson, 2015/10/21
- [Qemu-devel] [PULL 07/10] tcg/mips: Support r6 JR encoding, Richard Henderson, 2015/10/21
- [Qemu-devel] [PULL 09/10] tcg/mips: Support r6 SEL{NE, EQ}Z instead of MOVN/MOVZ,
Richard Henderson <=
- [Qemu-devel] [PULL 08/10] tcg/mips: Support r6 multiply/divide encodings, Richard Henderson, 2015/10/21
- [Qemu-devel] [PULL 10/10] cpu-exec: Add "nochain" debug flag, Richard Henderson, 2015/10/21
- Re: [Qemu-devel] [PULL 00/10] collected tcg patches, Peter Maydell, 2015/10/22