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
