Implement the AES key expansion instructions according to
OSA (Oracle SPARC Architecture) 2011 sections 7.3 and 7.4.

4 operand form (7.3):
- AES_KEXPAND1

3 operand form (7.4):
- AES_KEXPAND0
- AES_KEXPAND2

As the AES round instructions, they are gated behind the
crypto CPU feature and disabled for sparc32.

Signed-off-by: Stian Halseth <[email protected]>
---
 target/sparc/crypto_helper.c | 58 ++++++++++++++++++++++++++++++++++++
 target/sparc/helper.h        |  3 ++
 target/sparc/insns.decode    |  7 +++++
 target/sparc/translate.c     | 28 +++++++++++++++++
 4 files changed, 96 insertions(+)

diff --git a/target/sparc/crypto_helper.c b/target/sparc/crypto_helper.c
index 87cc19b930..5d2940b825 100644
--- a/target/sparc/crypto_helper.c
+++ b/target/sparc/crypto_helper.c
@@ -9,6 +9,7 @@
 #include "qemu/osdep.h"
 #include "exec/helper-proto.h"
 #include "crypto/aes-round.h"
+#include "crypto/aes.h"
 
 /*
  * SPARC four-operand AES round (Section 7.3).
@@ -83,3 +84,60 @@ uint64_t helper_aes_dround23_l(uint64_t key, uint64_t s2, 
uint64_t s3)
 {
     return aes_round(key, s2, s3, 1, true, true);
 }
+
+/* Combine the transformed word with the two words in rs1. */
+static uint64_t aes_kexpand(uint64_t rs1, uint32_t t)
+{
+    uint32_t hi = (rs1 >> 32) ^ t;
+    uint32_t lo = (uint32_t)rs1 ^ hi;
+
+    return ((uint64_t)hi << 32) | lo;
+}
+
+/* Apply the AES S-box to each byte, preserving byte positions. */
+static uint32_t aes_subword(uint32_t x)
+{
+    return ((uint32_t)AES_sbox[x >> 24] << 24) |
+           ((uint32_t)AES_sbox[(x >> 16) & 0xff] << 16) |
+           ((uint32_t)AES_sbox[(x >> 8) & 0xff] << 8) |
+           (uint32_t)AES_sbox[x & 0xff];
+}
+
+/*
+ * AES Cryptographic Operations 4 operand (Section 7.3)
+ * AES key expansion with RotWord, SubWord, and RCON.
+ */
+uint64_t helper_aes_kexpand1(uint64_t rs1, uint64_t rs2, uint32_t imm)
+{
+    static const uint8_t rcon[10] = {
+        0x01, 0x02, 0x04, 0x08, 0x10,
+        0x20, 0x40, 0x80, 0x1b, 0x36,
+    };
+    uint32_t t = rol32((uint32_t)rs2, 8);
+
+    t = aes_subword(t);
+
+    if (imm < ARRAY_SIZE(rcon)) {
+        t ^= (uint32_t)rcon[imm] << 24;
+    }
+
+    return aes_kexpand(rs1, t);
+}
+
+/*
+ * AES Cryptographic Operations 3 operand (Section 7.4)
+ * AES key expansion with SubWord, without RotWord or RCON.
+ */
+uint64_t helper_aes_kexpand0(uint64_t rs1, uint64_t rs2)
+{
+    return aes_kexpand(rs1, aes_subword(rs2));
+}
+
+/*
+ * AES Cryptographic Operations 3 operand (Section 7.4)
+ * AES key expansion without SubWord, RotWord, or RCON.
+ */
+uint64_t helper_aes_kexpand2(uint64_t rs1, uint64_t rs2)
+{
+    return aes_kexpand(rs1, (uint32_t)rs2);
+}
diff --git a/target/sparc/helper.h b/target/sparc/helper.h
index 9bfd643b09..685b89d9c5 100644
--- a/target/sparc/helper.h
+++ b/target/sparc/helper.h
@@ -130,6 +130,9 @@ 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)
+DEF_HELPER_FLAGS_2(aes_kexpand0, TCG_CALL_NO_RWG_SE, i64, i64, i64)
+DEF_HELPER_FLAGS_3(aes_kexpand1, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32)
+DEF_HELPER_FLAGS_2(aes_kexpand2, TCG_CALL_NO_RWG_SE, 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 99c9147e7d..96791c7658 100644
--- a/target/sparc/insns.decode
+++ b/target/sparc/insns.decode
@@ -86,6 +86,10 @@ CALL    01 i:s30
 @d_d_d_d    .. ..... ...... ..... ..... .... .....         \
             &r_r_r_r rd=%dfp_rd rs1=%dfp_rs1 rs2=%dfp_rs2 rs3=%dfp_rs3
 
+&r_r_i_r    rd rs1 imm rs2
+@d_d_i_d    .. ..... ...... ..... imm:5 .... .....         \
+            &r_r_i_r rd=%dfp_rd rs1=%dfp_rs1 rs2=%dfp_rs2
+
 {
   [
     STBAR_v9        10 00000 101000 01111 0 0000000000000
@@ -571,6 +575,8 @@ FCMPEq      10 000 cc:2 110101 .....  0 0101 0111 .....    \
     FPMAXU8     10 ..... 110110 ..... 1 0101 1101 .....    @d_d_d
     FPMAXU16    10 ..... 110110 ..... 1 0101 1110 .....    @d_d_d
     FPMAXU32    10 ..... 110110 ..... 1 0101 1111 .....    @d_d_d
+    AES_KEXPAND0 10 ..... 110110 ..... 1 0011 0000 .....   @d_d_d
+    AES_KEXPAND2 10 ..... 110110 ..... 1 0011 0001 .....   @d_d_d
 
     FLCMPs      10 000 cc:2 110110 rs1:5 1 0101 0001 rs2:5
     FLCMPd      10 000 cc:2 110110 ..... 1 0101 0010 ..... \
@@ -604,6 +610,7 @@ 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
+AES_KEXPAND1    10 ..... 011001 ..... ..... 1000 .....     @d_d_i_d
 
 ##
 ## Major Opcode 11 -- load and store instructions
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
index e6f8d87866..8cb405c8bd 100644
--- a/target/sparc/translate.c
+++ b/target/sparc/translate.c
@@ -109,6 +109,8 @@
 # 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; })
+# define gen_helper_aes_kexpand0         ({ qemu_build_not_reached(); NULL; })
+# define gen_helper_aes_kexpand2         ({ qemu_build_not_reached(); NULL; })
 #endif
 
 #define DISAS_EXIT  DISAS_TARGET_0
@@ -5435,6 +5437,32 @@ 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)
+TRANS(AES_KEXPAND0, CRYPTO, do_ddd, a, gen_helper_aes_kexpand0)
+TRANS(AES_KEXPAND2, CRYPTO, do_ddd, a, gen_helper_aes_kexpand2)
+
+/* AES key expansion with RCON selected by the 5-bit immediate in imm */
+static bool trans_AES_KEXPAND1(DisasContext *dc, arg_r_r_i_r *a)
+{
+    #ifdef TARGET_SPARC64
+        TCGv_i64 dst, src1, src2;
+
+        if (!avail_CRYPTO(dc)) {
+            return false;
+        }
+        if (gen_trap_ifnofpu(dc)) {
+            return true;
+        }
+
+        dst = tcg_temp_new_i64();
+        src1 = gen_load_fpr_D(dc, a->rs1);
+        src2 = gen_load_fpr_D(dc, a->rs2);
+        gen_helper_aes_kexpand1(dst, src1, src2, tcg_constant_i32(a->imm));
+        gen_store_fpr_D(dc, a->rd, dst);
+        return advance_pc(dc);
+    #else
+        return false;
+    #endif
+}
 
 static bool trans_FALIGNDATAi(DisasContext *dc, arg_r_r_r *a)
 {
-- 
2.43.0


Reply via email to