extract and deposit_z are similar operations, only differing in
that extract shifts the operand right and deposit_z shifts it left.
Like extract, it is possible to implement deposit_z as either AND+SHL or
SHL+SHR.  Use tcg_op_imm_match to check whether the processor supports the
immediate that is needed for the mask, and if not fall back to two shifts.

Signed-off-by: Paolo Bonzini <[email protected]>
---
 tcg/tcg-op.c | 28 ++++++++++++++++++++++++----
 1 file changed, 24 insertions(+), 4 deletions(-)

diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
index ccf66382623..e7d6702f9c4 100644
--- a/tcg/tcg-op.c
+++ b/tcg/tcg-op.c
@@ -960,8 +960,18 @@ void tcg_gen_deposit_z_i32(TCGv_i32 ret, TCGv_i32 arg,
             tcg_gen_extract_i32(ret, ret, 0, ofs + len);
             return;
         }
-        tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
-        tcg_gen_shli_i32(ret, ret, ofs);
+        /*
+         * Use TCG_TARGET_extract_valid to check for 8- and 16-bit extension
+         * opcodes, which tcg_gen_andi_i32 can produce.
+         */
+        if (TCG_TARGET_extract_valid(TCG_TYPE_I32, 0, len) ||
+            tcg_op_imm_match(INDEX_op_and, TCG_TYPE_I32, (1u << len) - 1)) {
+            tcg_gen_andi_i32(ret, arg, (1u << len) - 1);
+            tcg_gen_shli_i32(ret, ret, ofs);
+        } else {
+            tcg_gen_shli_i32(ret, arg, 32 - len);
+            tcg_gen_shri_i32(ret, ret, 32 - len - ofs);
+        }
     }
 }
 
@@ -2628,8 +2638,18 @@ void tcg_gen_deposit_z_i64(TCGv_i64 ret, TCGv_i64 arg,
             tcg_gen_extract_i64(ret, ret, 0, ofs + len);
             return;
         }
-        tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
-        tcg_gen_shli_i64(ret, ret, ofs);
+        /*
+         * Use TCG_TARGET_extract_valid to check for 8-, 16- and 32-bit 
extension
+         * opcodes, which tcg_gen_andi_i64 can produce.
+         */
+        if (TCG_TARGET_extract_valid(TCG_TYPE_I64, 0, len) ||
+           tcg_op_imm_match(INDEX_op_and, TCG_TYPE_I64, (1ull << len) - 1)) {
+            tcg_gen_andi_i64(ret, arg, (1ull << len) - 1);
+            tcg_gen_shli_i64(ret, ret, ofs);
+        } else {
+            tcg_gen_shli_i64(ret, arg, 64 - len);
+            tcg_gen_shri_i64(ret, ret, 64 - len - ofs);
+        }
     }
 }
 
-- 
2.52.0


Reply via email to