Signed-off-by: Richard Henderson
---
target/arm/tcg/a64.decode | 8 ++
target/arm/tcg/translate-a64.c | 132 +++--
2 files changed, 51 insertions(+), 89 deletions(-)
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
index 5a46205751..ef6902e86a 100644
--- a/target/arm/tcg/a64.decode
+++ b/target/arm/tcg/a64.decode
@@ -27,11 +27,13 @@
imm
_e q rd rn esz
_e q rd rn rm esz
+_eq rd rn rm ra esz
@rr_q1e0 .. rn:5 rd:5 _e q=1 esz=0
@r2r_q1e0 .. rm:5 rd:5 _e rn=%rd q=1
esz=0
@rrr_q1e0 ... rm:5 .. rn:5 rd:5 _e q=1 esz=0
@rrr_q1e3 ... rm:5 .. rn:5 rd:5 _e q=1 esz=3
+@_q1e3 ... rm:5 . ra:5 rn:5 rd:5 _e q=1 esz=3
### Data Processing - Immediate
@@ -636,3 +638,9 @@ SM4EKEY 1100 1110 011 . 110010 . .
@rrr_q1e0
SHA512SU0 1100 1110 110 0 10 . . @rr_q1e0
SM4E1100 1110 110 0 11 . . @r2r_q1e0
+
+### Cryptographic four-register
+
+EOR31100 1110 000 . 0 . . . @_q1e3
+BCAX1100 1110 001 . 0 . . . @_q1e3
+SM3SS1 1100 1110 010 . 0 . . . @_q1e3
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 1bfee2583a..a20da75423 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -1353,6 +1353,17 @@ static bool do_gvec_fn3(DisasContext *s, arg_qrrr_e *a,
GVecGen3Fn *fn)
return true;
}
+static bool do_gvec_fn4(DisasContext *s, arg_q_e *a, GVecGen4Fn *fn)
+{
+if (!a->q && a->esz == MO_64) {
+return false;
+}
+if (fp_access_check(s)) {
+gen_gvec_fn4(s, a->q, a->rd, a->rn, a->rm, a->ra, fn, a->esz);
+}
+return true;
+}
+
/*
* This utility function is for doing register extension with an
* optional shift. You will likely want to pass a temporary for the
@@ -4633,6 +4644,38 @@ TRANS_FEAT(SM4EKEY, aa64_sm4, do_gvec_op3_ool, a, 0,
gen_helper_crypto_sm4ekey)
TRANS_FEAT(SHA512SU0, aa64_sha512, do_gvec_op2_ool, a, 0,
gen_helper_crypto_sha512su0)
TRANS_FEAT(SM4E, aa64_sm4, do_gvec_op3_ool, a, 0, gen_helper_crypto_sm4e)
+TRANS_FEAT(EOR3, aa64_sha3, do_gvec_fn4, a, gen_gvec_eor3)
+TRANS_FEAT(BCAX, aa64_sha3, do_gvec_fn4, a, gen_gvec_bcax)
+
+static bool trans_SM3SS1(DisasContext *s, arg_SM3SS1 *a)
+{
+if (!dc_isar_feature(aa64_sm3, s)) {
+return false;
+}
+if (fp_access_check(s)) {
+TCGv_i32 tcg_op1 = tcg_temp_new_i32();
+TCGv_i32 tcg_op2 = tcg_temp_new_i32();
+TCGv_i32 tcg_op3 = tcg_temp_new_i32();
+TCGv_i32 tcg_res = tcg_temp_new_i32();
+unsigned vsz, dofs;
+
+read_vec_element_i32(s, tcg_op1, a->rn, 3, MO_32);
+read_vec_element_i32(s, tcg_op2, a->rm, 3, MO_32);
+read_vec_element_i32(s, tcg_op3, a->ra, 3, MO_32);
+
+tcg_gen_rotri_i32(tcg_res, tcg_op1, 20);
+tcg_gen_add_i32(tcg_res, tcg_res, tcg_op2);
+tcg_gen_add_i32(tcg_res, tcg_res, tcg_op3);
+tcg_gen_rotri_i32(tcg_res, tcg_res, 25);
+
+/* Clear the whole register first, then store bits [127:96]. */
+vsz = vec_full_reg_size(s);
+dofs = vec_full_reg_offset(s, a->rd);
+tcg_gen_gvec_dup_imm(MO_64, dofs, vsz, vsz, 0);
+write_vec_element_i32(s, tcg_res, a->rd, 3, MO_32);
+}
+return true;
+}
/* Shift a TCGv src by TCGv shift_amount, put result in dst.
* Note that it is the caller's responsibility to ensure that the
@@ -13527,94 +13570,6 @@ static void disas_simd_indexed(DisasContext *s,
uint32_t insn)
}
}
-/* Crypto four-register
- * 31 23 22 21 20 16 15 14 10 95 40
- * +---+-+--+---+--+--+--+
- * | 1 1 0 0 1 1 1 0 0 | Op0 | Rm | 0 | Ra | Rn | Rd |
- * +---+-+--+---+--+--+--+
- */
-static void disas_crypto_four_reg(DisasContext *s, uint32_t insn)
-{
-int op0 = extract32(insn, 21, 2);
-int rm = extract32(insn, 16, 5);
-int ra = extract32(insn, 10, 5);
-int rn = extract32(insn, 5, 5);
-int rd = extract32(insn, 0, 5);
-bool feature;
-
-switch (op0) {
-case 0: /* EOR3 */
-case 1: /* BCAX */
-feature = dc_isar_feature(aa64_sha3, s);
-break;
-case 2: /* SM3SS1 */
-feature = dc_isar_feature(aa64_sm3, s);
-break;
-default:
-unallocated_encoding(s);
-return;
-}
-
-if (!feature) {
-unallocated_encoding(s);
-return;
-}
-
-if (!fp_access_check(s)) {
-return;
-}
-
-if (op0 < 2) {
-TCGv_i64 tcg_op1, tcg_op2, tcg_op3, tcg_res[2];
-int pass;
-
-tcg_op1 = tcg_temp_new_i64();
-tcg_op2 = tcg_temp_new_i64();
-tcg_op3 = tcg_temp_new_i64();
-