Blame 0065-tcg-mips-implement-rotl-rotr-ops-on-MIPS32R2.patch

5544c1
From d19858a5515cd15dabf88b8f180754c1c3f3eb76 Mon Sep 17 00:00:00 2001
5544c1
From: Aurelien Jarno <aurelien@aurel32.net>
5544c1
Date: Fri, 21 Sep 2012 18:20:26 +0200
5544c1
Subject: [PATCH] tcg/mips: implement rotl/rotr ops on MIPS32R2
5544c1
5544c1
rotr operations can be optimized on MIPS32 Release 2 using the ROTR and
5544c1
ROTRV instructions. Also implemented rotl operations by subtracting the
5544c1
shift from 32.
5544c1
5544c1
Reviewed-by: Richard Henderson <rth@twiddle.net>
5544c1
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
5544c1
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
5544c1
---
5544c1
 tcg/mips/tcg-target.c | 20 ++++++++++++++++++++
5544c1
 tcg/mips/tcg-target.h |  3 ++-
5544c1
 2 files changed, 22 insertions(+), 1 deletion(-)
5544c1
5544c1
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
5544c1
index 8b2f9fc..592e42a 100644
5544c1
--- a/tcg/mips/tcg-target.c
5544c1
+++ b/tcg/mips/tcg-target.c
5544c1
@@ -300,9 +300,11 @@ enum {
5544c1
     OPC_SPECIAL  = 0x00 << 26,
5544c1
     OPC_SLL      = OPC_SPECIAL | 0x00,
5544c1
     OPC_SRL      = OPC_SPECIAL | 0x02,
5544c1
+    OPC_ROTR     = OPC_SPECIAL | (0x01 << 21) | 0x02,
5544c1
     OPC_SRA      = OPC_SPECIAL | 0x03,
5544c1
     OPC_SLLV     = OPC_SPECIAL | 0x04,
5544c1
     OPC_SRLV     = OPC_SPECIAL | 0x06,
5544c1
+    OPC_ROTRV    = OPC_SPECIAL | (0x01 <<  6) | 0x06,
5544c1
     OPC_SRAV     = OPC_SPECIAL | 0x07,
5544c1
     OPC_JR       = OPC_SPECIAL | 0x08,
5544c1
     OPC_JALR     = OPC_SPECIAL | 0x09,
5544c1
@@ -1420,6 +1422,22 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
5544c1
             tcg_out_opc_reg(s, OPC_SRLV, args[0], args[2], args[1]);
5544c1
         }
5544c1
         break;
5544c1
+    case INDEX_op_rotl_i32:
5544c1
+        if (const_args[2]) {
5544c1
+            tcg_out_opc_sa(s, OPC_ROTR, args[0], args[1], 0x20 - args[2]);
5544c1
+        } else {
5544c1
+            tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_AT, 32);
5544c1
+            tcg_out_opc_reg(s, OPC_SUBU, TCG_REG_AT, TCG_REG_AT, args[2]);
5544c1
+            tcg_out_opc_reg(s, OPC_ROTRV, args[0], TCG_REG_AT, args[1]);
5544c1
+        }
5544c1
+        break;
5544c1
+    case INDEX_op_rotr_i32:
5544c1
+        if (const_args[2]) {
5544c1
+            tcg_out_opc_sa(s, OPC_ROTR, args[0], args[1], args[2]);
5544c1
+        } else {
5544c1
+            tcg_out_opc_reg(s, OPC_ROTRV, args[0], args[2], args[1]);
5544c1
+        }
5544c1
+        break;
5544c1
 
5544c1
     /* The bswap routines do not work on non-R2 CPU. In that case
5544c1
        we let TCG generating the corresponding code. */
5544c1
@@ -1523,6 +1541,8 @@ static const TCGTargetOpDef mips_op_defs[] = {
5544c1
     { INDEX_op_shl_i32, { "r", "rZ", "ri" } },
5544c1
     { INDEX_op_shr_i32, { "r", "rZ", "ri" } },
5544c1
     { INDEX_op_sar_i32, { "r", "rZ", "ri" } },
5544c1
+    { INDEX_op_rotr_i32, { "r", "rZ", "ri" } },
5544c1
+    { INDEX_op_rotl_i32, { "r", "rZ", "ri" } },
5544c1
 
5544c1
     { INDEX_op_bswap16_i32, { "r", "r" } },
5544c1
     { INDEX_op_bswap32_i32, { "r", "r" } },
5544c1
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
5544c1
index c5c13f7..470314c 100644
5544c1
--- a/tcg/mips/tcg-target.h
5544c1
+++ b/tcg/mips/tcg-target.h
5544c1
@@ -80,7 +80,6 @@ typedef enum {
5544c1
 #define TCG_TARGET_HAS_div_i32          1
5544c1
 #define TCG_TARGET_HAS_not_i32          1
5544c1
 #define TCG_TARGET_HAS_nor_i32          1
5544c1
-#define TCG_TARGET_HAS_rot_i32          0
5544c1
 #define TCG_TARGET_HAS_ext8s_i32        1
5544c1
 #define TCG_TARGET_HAS_ext16s_i32       1
5544c1
 #define TCG_TARGET_HAS_andc_i32         0
5544c1
@@ -94,9 +93,11 @@ typedef enum {
5544c1
 #ifdef _MIPS_ARCH_MIPS32R2
5544c1
 #define TCG_TARGET_HAS_bswap16_i32      1
5544c1
 #define TCG_TARGET_HAS_bswap32_i32      1
5544c1
+#define TCG_TARGET_HAS_rot_i32          1
5544c1
 #else
5544c1
 #define TCG_TARGET_HAS_bswap16_i32      0
5544c1
 #define TCG_TARGET_HAS_bswap32_i32      0
5544c1
+#define TCG_TARGET_HAS_rot_i32          0
5544c1
 #endif
5544c1
 
5544c1
 /* optional instructions automatically implemented */
5544c1
-- 
5544c1
1.7.12.1
5544c1