Implement the eight AES round instructions by using QEMU's shared
crypto/aes-round.h, gated behind the crypto CPU feature:
- AES_EROUND01/23 and last variants
- AES_DROUND01/23 and last variants

Based on OSA (Oracle SPARC Architecture) 2011, section 7.3:
AES Cryptographic Operations (4 operand)

Signed-off-by: Stian Halseth <[email protected]>
---
 target/sparc/crypto_helper.c | 85 ++++++++++++++++++++++++++++++++++++
 target/sparc/helper.h        |  8 ++++
 target/sparc/insns.decode    |  9 ++++
 target/sparc/meson.build     |  2 +-
 target/sparc/translate.c     | 16 +++++++
 5 files changed, 119 insertions(+), 1 deletion(-)
 create mode 100644 target/sparc/crypto_helper.c

diff --git a/target/sparc/crypto_helper.c b/target/sparc/crypto_helper.c
new file mode 100644
index 0000000000..87cc19b930
--- /dev/null
+++ b/target/sparc/crypto_helper.c
@@ -0,0 +1,85 @@
+/*
+ * SPARC crypto instructions for QEMU
+ *
+ * Based on Oracle SPARC Architecture 2011
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "qemu/osdep.h"
+#include "exec/helper-proto.h"
+#include "crypto/aes-round.h"
+
+/*
+ * SPARC four-operand AES round (Section 7.3).
+ * s2:s3 holds the state in big-endian order; half selects output columns
+ * 0-1 or 2-3, and key supplies their round key.  dec selects decryption;
+ * last omits MixColumns/InvMixColumns.  Return the selected 64-bit half.
+ */
+static uint64_t aes_round(uint64_t key, uint64_t s2, uint64_t s3,
+                          int half, bool dec, bool last)
+{
+    AESState st, rk = { 0 }, r;
+    const unsigned first = HOST_BIG_ENDIAN ? 0 : 1;
+    const unsigned out = first ^ half;
+
+    st.d[first] = s2;       /* columns 0-1 */
+    st.d[first ^ 1] = s3;   /* columns 2-3 */
+    rk.d[out] = key;
+
+    if (dec) {
+        if (last) {
+            aesdec_ISB_ISR_AK(&r, &st, &rk, true);
+        } else {
+            aesdec_ISB_ISR_AK_IMC(&r, &st, &rk, true);
+        }
+    } else {
+        if (last) {
+            aesenc_SB_SR_AK(&r, &st, &rk, true);
+        } else {
+            aesenc_SB_SR_MC_AK(&r, &st, &rk, true);
+        }
+    }
+
+    return r.d[out];
+}
+
+uint64_t helper_aes_eround01(uint64_t key, uint64_t s2, uint64_t s3)
+{
+    return aes_round(key, s2, s3, 0, false, false);
+}
+
+uint64_t helper_aes_eround23(uint64_t key, uint64_t s2, uint64_t s3)
+{
+    return aes_round(key, s2, s3, 1, false, false);
+}
+
+uint64_t helper_aes_dround01(uint64_t key, uint64_t s2, uint64_t s3)
+{
+    return aes_round(key, s2, s3, 0, true, false);
+}
+
+uint64_t helper_aes_dround23(uint64_t key, uint64_t s2, uint64_t s3)
+{
+    return aes_round(key, s2, s3, 1, true, false);
+}
+
+uint64_t helper_aes_eround01_l(uint64_t key, uint64_t s2, uint64_t s3)
+{
+    return aes_round(key, s2, s3, 0, false, true);
+}
+
+uint64_t helper_aes_eround23_l(uint64_t key, uint64_t s2, uint64_t s3)
+{
+    return aes_round(key, s2, s3, 1, false, true);
+}
+
+uint64_t helper_aes_dround01_l(uint64_t key, uint64_t s2, uint64_t s3)
+{
+    return aes_round(key, s2, s3, 0, true, true);
+}
+
+uint64_t helper_aes_dround23_l(uint64_t key, uint64_t s2, uint64_t s3)
+{
+    return aes_round(key, s2, s3, 1, true, true);
+}
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index 3a7f7dc129..9bfd643b09 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -122,6 +122,14 @@ DEF_HELPER_FLAGS_2(fchksm16, TCG_CALL_NO_RWG_SE, i64, i64, 
i64)
 DEF_HELPER_FLAGS_2(fmean16, TCG_CALL_NO_RWG_SE, i64, i64, i64)
 DEF_HELPER_FLAGS_2(fslas16, TCG_CALL_NO_RWG_SE, i64, i64, i64)
 DEF_HELPER_FLAGS_2(fslas32, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_eround01, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_eround23, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_dround01, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_dround23, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_eround01_l, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_eround23_l, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_dround01_l, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_dround23_l, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64)
 #define VIS_CMPHELPER(name)                                  \
     DEF_HELPER_FLAGS_2(f##name##8, TCG_CALL_NO_RWG_SE,       \
                        i64, i64, i64)                        \
diff --git a/target/sparc/insns.decode b/target/sparc/insns.decode
index 55f8528ffe..99c9147e7d 100644
--- a/target/sparc/insns.decode
+++ b/target/sparc/insns.decode
@@ -596,6 +596,15 @@ FCMPEq      10 000 cc:2 110101 .....  0 0101 0111 .....    
\
   NCP           10 ----- 110111 ----- --------- -----      # v8 CPop2
 }
 
+AES_EROUND01    10 ..... 011001 ..... ..... 0000 .....     @d_d_d_d
+AES_EROUND23    10 ..... 011001 ..... ..... 0001 .....     @d_d_d_d
+AES_DROUND01    10 ..... 011001 ..... ..... 0010 .....     @d_d_d_d
+AES_DROUND23    10 ..... 011001 ..... ..... 0011 .....     @d_d_d_d
+AES_EROUND01_L  10 ..... 011001 ..... ..... 0100 .....     @d_d_d_d
+AES_EROUND23_L  10 ..... 011001 ..... ..... 0101 .....     @d_d_d_d
+AES_DROUND01_L  10 ..... 011001 ..... ..... 0110 .....     @d_d_d_d
+AES_DROUND23_L  10 ..... 011001 ..... ..... 0111 .....     @d_d_d_d
+
 ##
 ## Major Opcode 11 -- load and store instructions
 ##
diff --git a/target/sparc/meson.build b/target/sparc/meson.build
index 46289c8669..af65c933bf 100644
--- a/target/sparc/meson.build
+++ b/target/sparc/meson.build
@@ -12,7 +12,7 @@ sparc_ss.add(files(
   'win_helper.c',
 ))
 sparc_ss.add(when: 'TARGET_SPARC', if_true: files('int32_helper.c'))
-sparc_ss.add(when: 'TARGET_SPARC64', if_true: files('int64_helper.c', 
'vis_helper.c'))
+sparc_ss.add(when: 'TARGET_SPARC64', if_true: files('int64_helper.c', 
'vis_helper.c', 'crypto_helper.c'))
 
 sparc_system_ss = ss.source_set()
 sparc_system_ss.add(files(
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index 00a6988d62..e6f8d87866 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -101,6 +101,14 @@
 # define gen_helper_xmulx                ({ qemu_build_not_reached(); NULL; })
 # define gen_helper_xmulxhi              ({ qemu_build_not_reached(); NULL; })
 # define MAXTL_MASK                             0
+# define gen_helper_aes_eround01         ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_eround23         ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_dround01         ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_dround23         ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_eround01_l       ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_eround23_l       ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_dround01_l       ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_dround23_l       ({ qemu_build_not_reached(); NULL; })
 #endif
 
 #define DISAS_EXIT  DISAS_TARGET_0
@@ -5419,6 +5427,14 @@ TRANS(FNMSUBd, FMAF, do_dddd, a, gen_op_fnmsubd)
 TRANS(FNMADDd, FMAF, do_dddd, a, gen_op_fnmaddd)
 TRANS(FPMADDX, IMA, do_dddd, a, gen_op_fpmaddx)
 TRANS(FPMADDXHI, IMA, do_dddd, a, gen_op_fpmaddxhi)
+TRANS(AES_EROUND01, CRYPTO, do_dddd, a, gen_helper_aes_eround01)
+TRANS(AES_EROUND23, CRYPTO, do_dddd, a, gen_helper_aes_eround23)
+TRANS(AES_DROUND01, CRYPTO, do_dddd, a, gen_helper_aes_dround01)
+TRANS(AES_DROUND23, CRYPTO, do_dddd, a, gen_helper_aes_dround23)
+TRANS(AES_EROUND01_L, CRYPTO, do_dddd, a, gen_helper_aes_eround01_l)
+TRANS(AES_EROUND23_L, CRYPTO, do_dddd, a, gen_helper_aes_eround23_l)
+TRANS(AES_DROUND01_L, CRYPTO, do_dddd, a, gen_helper_aes_dround01_l)
+TRANS(AES_DROUND23_L, CRYPTO, do_dddd, a, gen_helper_aes_dround23_l)
 
 static bool trans_FALIGNDATAi(DisasContext *dc, arg_r_r_r *a)
 {
-- 
2.43.0


Reply via email to