target/arm: Implement AESE (indexed)
Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20260826174213.614571-21-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Richard Henderson committed
Aug 26, 2026 at 10:42 UTC
f36ce45c69daa9ba37e57ee3c9c3c6a80eb87134
5 files changed
+92
-18
target/arm/cpu-features.h
+5
@@ -1544,6 +1544,11 @@ static inline bool isar_feature_aa64_sve_pmull128(const ARMISARegisters *id)
1544
return FIELD_EX64_IDREG(id, ID_AA64ZFR0, AES) >= 2;
1545
}
1546
1547
+static inline bool isar_feature_aa64_sve_aes2(const ARMISARegisters *id)
1548
+{
1549
+ return FIELD_EX64_IDREG(id, ID_AA64ZFR0, AES) >= 3;
1550
+}
1551
+
1552
static inline bool isar_feature_aa64_sve_bitperm(const ARMISARegisters *id)
1553
{
1554
return FIELD_EX64_IDREG(id, ID_AA64ZFR0, BITPERM) != 0;
target/arm/tcg/crypto_helper.c
+39
-16
@@ -47,6 +47,27 @@ static void clear_tail_16(void *vd, uint32_t desc)
47
48
static const AESState aes_zero = { };
49
50
+static void aese_kernel(AESState *ad, const AESState *st, const AESState *rk)
51
+{
52
+ AESState t;
53
+
54
+ /*
55
+ * Our uint64_t are in the wrong order for big-endian.
56
+ * The Arm AddRoundKey comes first, while the API AddRoundKey
57
+ * comes last: perform the xor here, and provide zero to API.
58
+ */
59
+ if (HOST_BIG_ENDIAN) {
60
+ t.d[0] = st->d[1] ^ rk->d[1];
61
+ t.d[1] = st->d[0] ^ rk->d[0];
62
+ aesenc_SB_SR_AK(&t, &t, &aes_zero, false);
63
+ ad->d[0] = t.d[1];
64
+ ad->d[1] = t.d[0];
65
+ } else {
66
+ t.v = st->v ^ rk->v;
67
+ aesenc_SB_SR_AK(ad, &t, &aes_zero, false);
68
+ }
69
+}
70
+
71
void HELPER(crypto_aese)(void *vd, void *vn, void *vm, uint32_t desc)
72
{
73
intptr_t i, opr_sz = simd_oprsz(desc);
@@ -55,27 +76,29 @@ void HELPER(crypto_aese)(void *vd, void *vn, void *vm, uint32_t desc)
76
AESState *ad = (AESState *)(vd + i);
77
AESState *st = (AESState *)(vn + i);
78
AESState *rk = (AESState *)(vm + i);
58
- AESState t;
79
60
- /*
61
- * Our uint64_t are in the wrong order for big-endian.
62
- * The Arm AddRoundKey comes first, while the API AddRoundKey
63
- * comes last: perform the xor here, and provide zero to API.
64
- */
65
- if (HOST_BIG_ENDIAN) {
66
- t.d[0] = st->d[1] ^ rk->d[1];
67
- t.d[1] = st->d[0] ^ rk->d[0];
68
- aesenc_SB_SR_AK(&t, &t, &aes_zero, false);
69
- ad->d[0] = t.d[1];
70
- ad->d[1] = t.d[0];
71
- } else {
72
- t.v = st->v ^ rk->v;
73
- aesenc_SB_SR_AK(ad, &t, &aes_zero, false);
74
- }
80
+ aese_kernel(ad, st, rk);
81
}
82
clear_tail(vd, opr_sz, simd_maxsz(desc));
83
}
84
85
+void HELPER(crypto_aese_idx)(void *vd, void *vn, void *vm, uint32_t desc)
86
+{
87
+ intptr_t opr_sz = simd_oprsz(desc);
88
+ intptr_t idx = simd_data(desc);
89
+ void *vm_idx = vm + idx * 16;
90
+ intptr_t s = opr_sz - 16;
91
+
92
+ do {
93
+ intptr_t base = ROUND_DOWN(s, 4 * 16);
94
+ AESState rk = *(AESState *)(vm_idx + base);
95
+ do {
96
+ aese_kernel(vd + s, vn + s, &rk);
97
+ s -= 16;
98
+ } while (s >= base);
99
+ } while (s > 0);
100
+}
101
+
102
void HELPER(crypto_aesd)(void *vd, void *vn, void *vm, uint32_t desc)
103
{
104
intptr_t i, opr_sz = simd_oprsz(desc);
target/arm/tcg/helper-defs.h
+2
@@ -461,6 +461,8 @@ DEF_HELPER_FLAGS_4(crypto_aesd, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
461
DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
462
DEF_HELPER_FLAGS_3(crypto_aesimc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
463
464
+DEF_HELPER_FLAGS_4(crypto_aese_idx, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
465
+
466
DEF_HELPER_FLAGS_4(crypto_sha1su0, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
467
DEF_HELPER_FLAGS_4(crypto_sha1c, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
468
DEF_HELPER_FLAGS_4(crypto_sha1p, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
target/arm/tcg/sve.decode
+11
-2
@@ -60,6 +60,8 @@
60
# as propagated via the MOVPRFX instruction.
61
%reg_movprfx 0:5
62
63
+%zd_ax2 1:4 !function=times_2
64
+%zd_ax4 2:3 !function=times_4
65
%rn_ax2 6:4 !function=times_2
66
67
%pnd 0:3 !function=plus_8
@@ -70,6 +72,7 @@
72
# when creating helpers common to those for the individual
73
# instruction patterns.
74
75
+&rx_n rdn rm index n
76
&rr_esz rd rn esz
77
&rri rd rn imm
78
&rr_dbm rd rn dbm
@@ -1974,6 +1977,14 @@ AESE 01000101 00 10001 0 11100 0 ..... ..... @rdn_rm_e0
1977
AESD 01000101 00 10001 0 11100 1 ..... ..... @rdn_rm_e0
1978
SM4E 01000101 00 10001 1 11100 0 ..... ..... @rdn_rm_e0
1979
1980
+@aes2_2 ........ .. . index:2 0........ rm:5 ..... \
1981
+ &rx_n n=2 rdn=%zd_ax2
1982
+@aes2_4 ........ .. . index:2 1........ rm:5 ..... \
1983
+ &rx_n n=4 rdn=%zd_ax4
1984
+
1985
+AESE_idx 01000101 00 1 .. .10111010 ..... ....0 @aes2_2
1986
+AESE_idx 01000101 00 1 .. .10111010 ..... ...00 @aes2_4
1987
+
1988
# SVE2 crypto constructive binary operations
1989
SM4EKEY 01000101 00 1 ..... 11110 0 ..... ..... @rd_rn_rm_e0
1990
RAX1 01000101 00 1 ..... 11110 1 ..... ..... @rd_rn_rm_e0
@@ -2078,8 +2089,6 @@ FCLAMP 01100100 .. 1 ..... 001001 ..... ..... @rda_rn_rm
2089
&zcrr_ldst rd png rn rm esz nreg
2090
&zcri_ldst rd png rn imm esz nreg
2091
%png 10:3 !function=plus_8
2081
-%zd_ax2 1:4 !function=times_2
2082
-%zd_ax4 2:3 !function=times_4
2092
2093
LD1_zcrr 10100000000 rm:5 0 esz:2 ... rn:5 .... - \
2094
&zcrr_ldst %png rd=%zd_ax2 nreg=2
target/arm/tcg/translate-sve.c
+35
@@ -8310,6 +8310,41 @@ TRANS_FEAT_NONSTREAMING(SM4EKEY, aa64_sve_sm4, gen_gvec_ool_arg_zzz,
8310
TRANS_FEAT_STREAMING_IF(RAX1, aa64_sve_sha3, aa64_sme2p1,
8311
gen_gvec_fn_arg_zzz, gen_gvec_rax1, a)
8312
8313
+static bool do_aes2_idx(DisasContext *s, arg_rx_n *a, gen_helper_gvec_3 *fn)
8314
+{
8315
+ if (sve_access_check(s)) {
8316
+ unsigned vsz = vec_full_reg_size(s);
8317
+ int overlap = -1;
8318
+ int index, mofs;
8319
+
8320
+ if (vsz == 16) {
8321
+ index = 0;
8322
+ } else if (vsz == 32) {
8323
+ index = a->index % 2;
8324
+ } else {
8325
+ index = a->index;
8326
+ }
8327
+
8328
+ mofs = vec_full_reg_offset(s, a->rm);
8329
+
8330
+ for (int i = 0, n = a->n; i < n; i++) {
8331
+ int dofs = vec_full_reg_offset(s, a->rdn + i);
8332
+ if (dofs == mofs) {
8333
+ overlap = i;
8334
+ } else {
8335
+ tcg_gen_gvec_3_ool(dofs, dofs, mofs, vsz, vsz, index, fn);
8336
+ }
8337
+ }
8338
+ if (overlap >= 0) {
8339
+ tcg_gen_gvec_3_ool(mofs, mofs, mofs, vsz, vsz, index, fn);
8340
+ }
8341
+ }
8342
+ return true;
8343
+}
8344
+
8345
+TRANS_FEAT_STREAMING_IF(AESE_idx, aa64_sve_aes2, aa64_ssve_aes,
8346
+ do_aes2_idx, a, gen_helper_crypto_aese_idx)
8347
+
8348
TRANS_FEAT(FCVTNT_sh_m, aa64_sme_or_sve2, gen_gvec_fpst_arg_zpz,
8349
gen_helper_sve2_fcvtnt_sh, a, 0, FPST_A64)
8350
TRANS_FEAT(FCVTNT_sh_z, aa64_sme2p2_or_sve2p2, gen_gvec_fpst_arg_zpz,