Signed-off-by: Richard Henderson
---
target/arm/translate-a64.c | 423 +
1 file changed, 350 insertions(+), 73 deletions(-)
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 48088dbb29..38400560db 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -87,6 +87,8 @@ typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
/* Note that the gvec expanders operate on offsets + sizes. */
typedef void GVecGen2Fn(unsigned, uint32_t, uint32_t, uint32_t, uint32_t);
+typedef void GVecGen2iFn(unsigned, uint32_t, uint32_t, int64_t,
+ uint32_t, uint32_t);
typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t,
uint32_t, uint32_t, uint32_t);
@@ -640,6 +642,16 @@ static void gen_gvec_fn2(DisasContext *s, bool is_q, int
rd, int rn,
is_q ? 16 : 8, vec_full_reg_size(s));
}
+/* Expand a 2-operand + immediate AdvSIMD vector operation using
+ * an expander function.
+ */
+static void gen_gvec_fn2i(DisasContext *s, bool is_q, int rd, int rn,
+ int64_t imm, GVecGen2iFn *gvec_fn, int vece)
+{
+gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
+imm, is_q ? 16 : 8, vec_full_reg_size(s));
+}
+
/* Expand a 3-operand AdvSIMD vector operation using an expander function. */
static void gen_gvec_fn3(DisasContext *s, bool is_q, int rd, int rn, int rm,
GVecGen3Fn *gvec_fn, int vece)
@@ -648,6 +660,16 @@ static void gen_gvec_fn3(DisasContext *s, bool is_q, int
rd, int rn, int rm,
vec_full_reg_offset(s, rm), is_q ? 16 : 8, vec_full_reg_size(s));
}
+/* Expand a 2-operand + immediate AdvSIMD vector operation using
+ * an op descriptor.
+ */
+static void gen_gvec_op2i(DisasContext *s, bool is_q, int rd,
+ int rn, int64_t imm, const GVecGen2i *gvec_op)
+{
+tcg_gen_gvec_2i(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
+is_q ? 16 : 8, vec_full_reg_size(s), imm, gvec_op);
+}
+
/* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */
static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
int rn, int rm, const GVecGen3 *gvec_op)
@@ -6512,32 +6534,6 @@ static void handle_shri_with_rndacc(TCGv_i64 tcg_res,
TCGv_i64 tcg_src,
}
}
-/* Common SHL/SLI - Shift left with an optional insert */
-static void handle_shli_with_ins(TCGv_i64 tcg_res, TCGv_i64 tcg_src,
- bool insert, int shift)
-{
-if (insert) { /* SLI */
-tcg_gen_deposit_i64(tcg_res, tcg_res, tcg_src, shift, 64 - shift);
-} else { /* SHL */
-tcg_gen_shli_i64(tcg_res, tcg_src, shift);
-}
-}
-
-/* SRI: shift right with insert */
-static void handle_shri_with_ins(TCGv_i64 tcg_res, TCGv_i64 tcg_src,
- int size, int shift)
-{
-int esize = 8 << size;
-
-/* shift count same as element size is valid but does nothing;
- * special case to avoid potential shift by 64.
- */
-if (shift != esize) {
-tcg_gen_shri_i64(tcg_src, tcg_src, shift);
-tcg_gen_deposit_i64(tcg_res, tcg_res, tcg_src, 0, esize - shift);
-}
-}
-
/* SSHR[RA]/USHR[RA] - Scalar shift right (optional rounding/accumulate) */
static void handle_scalar_simd_shri(DisasContext *s,
bool is_u, int immh, int immb,
@@ -6588,7 +6584,14 @@ static void handle_scalar_simd_shri(DisasContext *s,
tcg_rd = (accumulate || insert) ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
if (insert) {
-handle_shri_with_ins(tcg_rd, tcg_rn, size, shift);
+/* shift count same as element size is valid but does nothing;
+ * special case to avoid potential shift by 64.
+ */
+int esize = 8 << size;
+if (shift != esize) {
+tcg_gen_shri_i64(tcg_rn, tcg_rn, shift);
+tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, 0, esize - shift);
+}
} else {
handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
accumulate, is_u, size, shift);
@@ -6626,7 +6629,11 @@ static void handle_scalar_simd_shli(DisasContext *s,
bool insert,
tcg_rn = read_fp_dreg(s, rn);
tcg_rd = insert ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
-handle_shli_with_ins(tcg_rd, tcg_rn, insert, shift);
+if (insert) {
+tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, shift, 64 - shift);
+} else {
+tcg_gen_shli_i64(tcg_rd, tcg_rn, shift);
+}
write_fp_dreg(s, rd, tcg_rd);
@@ -8356,16 +8363,195 @@ static void
disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
}
}
+static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
+{
+tcg_gen_vec_sar8i_i64(a, a, shift);
+tcg_gen_vec_add8_i64(d, d, a);
+}
+
+static void gen_ssra16_i64(TCGv_i64 d,