Add helper support for the Octeon HSH hash selectors. This includes the
base HSH data/IV windows, MD5, SHA1, SHA256, and SHA512 transform paths,
and the shared HSH/SHA512 register-window readback and write operations.

The SHA512 path shares the wide HSH register bank with SHA3, SNOW3G, and
ZUC. Keep the mode tracking centralized so later explicit DMFC2/DMTC2
selector decode can route aliased register accesses through these helpers
when side effects or active-engine views are required.

Signed-off-by: James Hilliard <[email protected]>
---
Changes v8 -> v9:
  - Split HSH/SHA helpers into their own COP2 helper patch.
  - Replace generic selector dispatch with per-operation HSH helpers.
  - Keep shared-window readback and write helpers grouped with HSH.
  - Add matching helper.h declarations with the helper implementation.
---
 target/mips/helper.h            |  53 ++++
 target/mips/tcg/octeon_crypto.c | 570 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 623 insertions(+)

diff --git a/target/mips/helper.h b/target/mips/helper.h
index 23c712cfb7..6d6ceaea08 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -28,6 +28,30 @@ DEF_HELPER_FLAGS_4(rotx, TCG_CALL_NO_RWG_SE, tl, tl, i32, 
i32, i32)
 /* Octeon COP2 selector operation helpers. */
 DEF_HELPER_1(octeon_cp2_mf_crc_iv_reflect, i64, env)
 DEF_HELPER_1(octeon_cp2_mf_sha3_dat24, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw0, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw1, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw2, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw3, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw4, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw5, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw6, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw7, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw8, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw9, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw10, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw11, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw12, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw13, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw14, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_datw15, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_ivw0, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_ivw1, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_ivw2, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_ivw3, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_ivw4, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_ivw5, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_ivw6, i64, env)
+DEF_HELPER_1(octeon_cp2_mf_hsh_ivw7, i64, env)
 DEF_HELPER_2(octeon_cp2_mt_crc_write_iv_reflect, void, env, i64)
 DEF_HELPER_2(octeon_cp2_mt_crc_write_byte, void, env, i64)
 DEF_HELPER_2(octeon_cp2_mt_crc_write_half, void, env, i64)
@@ -83,6 +107,35 @@ DEF_HELPER_2(octeon_cp2_mt_des3_dec, void, env, i64)
 DEF_HELPER_2(octeon_cp2_mt_camellia_fl, void, env, i64)
 DEF_HELPER_2(octeon_cp2_mt_camellia_flinv, void, env, i64)
 DEF_HELPER_2(octeon_cp2_mt_camellia_round, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_startsha_compat, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw0, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw1, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw2, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw3, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw4, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw5, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw6, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw7, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw8, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw9, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw10, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw11, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw12, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw13, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw14, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_datw15, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_ivw0, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_ivw1, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_ivw2, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_ivw3, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_ivw4, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_ivw5, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_ivw6, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_ivw7, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_startmd5, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_startsha256, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_startsha, void, env, i64)
+DEF_HELPER_2(octeon_cp2_mt_hsh_startsha512, void, env, i64)
 
 /* microMIPS functions */
 DEF_HELPER_4(lwm, void, env, tl, tl, i32)
diff --git a/target/mips/tcg/octeon_crypto.c b/target/mips/tcg/octeon_crypto.c
index d26dd2924d..6282226cfc 100644
--- a/target/mips/tcg/octeon_crypto.c
+++ b/target/mips/tcg/octeon_crypto.c
@@ -136,6 +136,367 @@ static void octeon_gfm_mul_reflect(MIPSOcteonCryptoState 
*crypto, uint64_t data)
                           crypto->gfm_poly, crypto->gfm_reflect_resinp);
     crypto->gfm_reflect_xor0 = 0;
 }
+static inline void octeon_hsh_load_reg_words_be(uint64_t reg,
+                                                 uint32_t *hi, uint32_t *lo)
+{
+    uint8_t buf[8];
+
+    stq_be_p(buf, reg);
+    *hi = ldl_be_p(buf);
+    *lo = ldl_be_p(buf + 4);
+}
+
+static inline void octeon_hsh_load_reg_words_le(uint64_t reg,
+                                                 uint32_t *lo0, uint32_t *lo1)
+{
+    uint8_t buf[8];
+
+    stq_be_p(buf, reg);
+    *lo0 = ldl_le_p(buf);
+    *lo1 = ldl_le_p(buf + 4);
+}
+
+static inline uint64_t octeon_hsh_store_reg_words_be(uint32_t hi, uint32_t lo)
+{
+    uint8_t buf[8];
+
+    stl_be_p(buf, hi);
+    stl_be_p(buf + 4, lo);
+    return ldq_be_p(buf);
+}
+
+static inline uint64_t octeon_hsh_store_reg_words_le(uint32_t lo0,
+                                                      uint32_t lo1)
+{
+    uint8_t buf[8];
+
+    stl_le_p(buf, lo0);
+    stl_le_p(buf + 4, lo1);
+    return ldq_be_p(buf);
+}
+
+static void octeon_md5_transform(MIPSOcteonCryptoState *crypto)
+{
+    static const uint32_t k[64] = {
+        0xd76aa478U, 0xe8c7b756U, 0x242070dbU, 0xc1bdceeeU,
+        0xf57c0fafU, 0x4787c62aU, 0xa8304613U, 0xfd469501U,
+        0x698098d8U, 0x8b44f7afU, 0xffff5bb1U, 0x895cd7beU,
+        0x6b901122U, 0xfd987193U, 0xa679438eU, 0x49b40821U,
+        0xf61e2562U, 0xc040b340U, 0x265e5a51U, 0xe9b6c7aaU,
+        0xd62f105dU, 0x02441453U, 0xd8a1e681U, 0xe7d3fbc8U,
+        0x21e1cde6U, 0xc33707d6U, 0xf4d50d87U, 0x455a14edU,
+        0xa9e3e905U, 0xfcefa3f8U, 0x676f02d9U, 0x8d2a4c8aU,
+        0xfffa3942U, 0x8771f681U, 0x6d9d6122U, 0xfde5380cU,
+        0xa4beea44U, 0x4bdecfa9U, 0xf6bb4b60U, 0xbebfbc70U,
+        0x289b7ec6U, 0xeaa127faU, 0xd4ef3085U, 0x04881d05U,
+        0xd9d4d039U, 0xe6db99e5U, 0x1fa27cf8U, 0xc4ac5665U,
+        0xf4292244U, 0x432aff97U, 0xab9423a7U, 0xfc93a039U,
+        0x655b59c3U, 0x8f0ccc92U, 0xffeff47dU, 0x85845dd1U,
+        0x6fa87e4fU, 0xfe2ce6e0U, 0xa3014314U, 0x4e0811a1U,
+        0xf7537e82U, 0xbd3af235U, 0x2ad7d2bbU, 0xeb86d391U,
+    };
+    static const uint8_t s[64] = {
+        7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
+        5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
+        4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
+        6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21,
+    };
+    uint8_t block_bytes[64];
+    uint32_t m[16];
+    uint32_t a, b, c, d;
+    uint32_t aa, bb, cc, dd;
+    int i;
+
+    for (i = 0; i < 8; i++) {
+        stq_be_p(block_bytes + (i * 8), crypto->hsh_dat[i]);
+        m[i * 2] = ldl_le_p(block_bytes + (i * 8));
+        m[i * 2 + 1] = ldl_le_p(block_bytes + (i * 8) + 4);
+    }
+
+    octeon_hsh_load_reg_words_le(crypto->hsh_iv[0], &a, &b);
+    octeon_hsh_load_reg_words_le(crypto->hsh_iv[1], &c, &d);
+    aa = a;
+    bb = b;
+    cc = c;
+    dd = d;
+
+    for (i = 0; i < 64; i++) {
+        uint32_t f, g, tmp;
+
+        if (i < 16) {
+            f = (b & c) | ((~b) & d);
+            g = i;
+        } else if (i < 32) {
+            f = (d & b) | ((~d) & c);
+            g = (5 * i + 1) & 0xf;
+        } else if (i < 48) {
+            f = b ^ c ^ d;
+            g = (3 * i + 5) & 0xf;
+        } else {
+            f = c ^ (b | (~d));
+            g = (7 * i) & 0xf;
+        }
+
+        tmp = d;
+        d = c;
+        c = b;
+        b = b + rol32(a + f + k[i] + m[g], s[i]);
+        a = tmp;
+    }
+
+    a += aa;
+    b += bb;
+    c += cc;
+    d += dd;
+    crypto->hsh_iv[0] = octeon_hsh_store_reg_words_le(a, b);
+    crypto->hsh_iv[1] = octeon_hsh_store_reg_words_le(c, d);
+}
+
+static void octeon_sha1_transform(MIPSOcteonCryptoState *crypto)
+{
+    uint32_t w[80];
+    uint32_t a, b, c, d, e;
+    int i;
+
+    for (i = 0; i < 8; i++) {
+        octeon_hsh_load_reg_words_be(crypto->hsh_dat[i],
+                                      &w[i * 2], &w[i * 2 + 1]);
+    }
+    for (i = 16; i < 80; i++) {
+        w[i] = rol32(w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16], 1);
+    }
+
+    octeon_hsh_load_reg_words_be(crypto->hsh_iv[0], &a, &b);
+    octeon_hsh_load_reg_words_be(crypto->hsh_iv[1], &c, &d);
+    e = crypto->hsh_iv[2] >> 32;
+
+    for (i = 0; i < 80; i++) {
+        uint32_t f, k, temp;
+
+        if (i < 20) {
+            f = (b & c) | ((~b) & d);
+            k = 0x5a827999;
+        } else if (i < 40) {
+            f = b ^ c ^ d;
+            k = 0x6ed9eba1;
+        } else if (i < 60) {
+            f = (b & c) | (b & d) | (c & d);
+            k = 0x8f1bbcdc;
+        } else {
+            f = b ^ c ^ d;
+            k = 0xca62c1d6;
+        }
+
+        temp = rol32(a, 5) + f + e + k + w[i];
+        e = d;
+        d = c;
+        c = rol32(b, 30);
+        b = a;
+        a = temp;
+    }
+
+    octeon_hsh_load_reg_words_be(crypto->hsh_iv[0], &w[0], &w[1]);
+    octeon_hsh_load_reg_words_be(crypto->hsh_iv[1], &w[2], &w[3]);
+    w[4] = crypto->hsh_iv[2] >> 32;
+    w[0] += a;
+    w[1] += b;
+    w[2] += c;
+    w[3] += d;
+    w[4] += e;
+    crypto->hsh_iv[0] = octeon_hsh_store_reg_words_be(w[0], w[1]);
+    crypto->hsh_iv[1] = octeon_hsh_store_reg_words_be(w[2], w[3]);
+    crypto->hsh_iv[2] = (uint64_t)w[4] << 32;
+}
+
+static void octeon_sha256_transform(MIPSOcteonCryptoState *crypto)
+{
+    static const uint32_t k[64] = {
+        0x428a2f98U, 0x71374491U, 0xb5c0fbcfU, 0xe9b5dba5U,
+        0x3956c25bU, 0x59f111f1U, 0x923f82a4U, 0xab1c5ed5U,
+        0xd807aa98U, 0x12835b01U, 0x243185beU, 0x550c7dc3U,
+        0x72be5d74U, 0x80deb1feU, 0x9bdc06a7U, 0xc19bf174U,
+        0xe49b69c1U, 0xefbe4786U, 0x0fc19dc6U, 0x240ca1ccU,
+        0x2de92c6fU, 0x4a7484aaU, 0x5cb0a9dcU, 0x76f988daU,
+        0x983e5152U, 0xa831c66dU, 0xb00327c8U, 0xbf597fc7U,
+        0xc6e00bf3U, 0xd5a79147U, 0x06ca6351U, 0x14292967U,
+        0x27b70a85U, 0x2e1b2138U, 0x4d2c6dfcU, 0x53380d13U,
+        0x650a7354U, 0x766a0abbU, 0x81c2c92eU, 0x92722c85U,
+        0xa2bfe8a1U, 0xa81a664bU, 0xc24b8b70U, 0xc76c51a3U,
+        0xd192e819U, 0xd6990624U, 0xf40e3585U, 0x106aa070U,
+        0x19a4c116U, 0x1e376c08U, 0x2748774cU, 0x34b0bcb5U,
+        0x391c0cb3U, 0x4ed8aa4aU, 0x5b9cca4fU, 0x682e6ff3U,
+        0x748f82eeU, 0x78a5636fU, 0x84c87814U, 0x8cc70208U,
+        0x90befffaU, 0xa4506cebU, 0xbef9a3f7U, 0xc67178f2U,
+    };
+    uint32_t w[64];
+    uint32_t a, b, c, d, e, f, g, h;
+    uint32_t orig[8];
+    int i;
+
+    for (i = 0; i < 8; i++) {
+        octeon_hsh_load_reg_words_be(crypto->hsh_dat[i],
+                                      &w[i * 2], &w[i * 2 + 1]);
+    }
+    for (i = 16; i < 64; i++) {
+        uint32_t s0 = ror32(w[i - 15], 7) ^
+                      ror32(w[i - 15], 18) ^
+                      (w[i - 15] >> 3);
+        uint32_t s1 = ror32(w[i - 2], 17) ^
+                      ror32(w[i - 2], 19) ^
+                      (w[i - 2] >> 10);
+        w[i] = w[i - 16] + s0 + w[i - 7] + s1;
+    }
+
+    for (i = 0; i < 4; i++) {
+        octeon_hsh_load_reg_words_be(crypto->hsh_iv[i],
+                                      &orig[i * 2], &orig[i * 2 + 1]);
+    }
+    a = orig[0];
+    b = orig[1];
+    c = orig[2];
+    d = orig[3];
+    e = orig[4];
+    f = orig[5];
+    g = orig[6];
+    h = orig[7];
+
+    for (i = 0; i < 64; i++) {
+        uint32_t s1 = ror32(e, 6) ^
+                      ror32(e, 11) ^
+                      ror32(e, 25);
+        uint32_t ch = (e & f) ^ ((~e) & g);
+        uint32_t temp1 = h + s1 + ch + k[i] + w[i];
+        uint32_t s0 = ror32(a, 2) ^
+                      ror32(a, 13) ^
+                      ror32(a, 22);
+        uint32_t maj = (a & b) ^ (a & c) ^ (b & c);
+        uint32_t temp2 = s0 + maj;
+
+        h = g;
+        g = f;
+        f = e;
+        e = d + temp1;
+        d = c;
+        c = b;
+        b = a;
+        a = temp1 + temp2;
+    }
+
+    orig[0] += a;
+    orig[1] += b;
+    orig[2] += c;
+    orig[3] += d;
+    orig[4] += e;
+    orig[5] += f;
+    orig[6] += g;
+    orig[7] += h;
+    for (i = 0; i < 4; i++) {
+        crypto->hsh_iv[i] =
+            octeon_hsh_store_reg_words_be(orig[i * 2], orig[i * 2 + 1]);
+    }
+}
+
+static void octeon_sha512_transform(MIPSOcteonCryptoState *crypto)
+{
+    static const uint64_t k[80] = {
+        0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+        0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+        0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+        0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+        0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+        0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+        0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+        0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+        0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+        0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+        0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+        0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+        0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+        0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+        0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+        0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+        0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+        0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+        0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+        0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+        0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+        0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+        0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+        0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+        0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+        0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+        0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+        0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+        0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+        0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+        0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+        0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+        0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+        0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+        0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+        0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+        0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+        0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+        0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+        0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL,
+    };
+    uint64_t w[80];
+    uint64_t a, b, c, d, e, f, g, h;
+    int i;
+
+    for (i = 0; i < 16; i++) {
+        w[i] = crypto->hsh_datw[i];
+    }
+    for (i = 16; i < 80; i++) {
+        uint64_t s0 = ror64(w[i - 15], 1) ^
+                      ror64(w[i - 15], 8) ^
+                      (w[i - 15] >> 7);
+        uint64_t s1 = ror64(w[i - 2], 19) ^
+                      ror64(w[i - 2], 61) ^
+                      (w[i - 2] >> 6);
+        w[i] = w[i - 16] + s0 + w[i - 7] + s1;
+    }
+
+    a = crypto->hsh_ivw[0];
+    b = crypto->hsh_ivw[1];
+    c = crypto->hsh_ivw[2];
+    d = crypto->hsh_ivw[3];
+    e = crypto->hsh_ivw[4];
+    f = crypto->hsh_ivw[5];
+    g = crypto->hsh_ivw[6];
+    h = crypto->hsh_ivw[7];
+
+    for (i = 0; i < 80; i++) {
+        uint64_t s0 = ror64(a, 28) ^
+                      ror64(a, 34) ^
+                      ror64(a, 39);
+        uint64_t s1 = ror64(e, 14) ^
+                      ror64(e, 18) ^
+                      ror64(e, 41);
+        uint64_t ch = (e & f) ^ ((~e) & g);
+        uint64_t maj = (a & b) ^ (a & c) ^ (b & c);
+        uint64_t temp1 = h + s1 + ch + k[i] + w[i];
+        uint64_t temp2 = s0 + maj;
+
+        h = g;
+        g = f;
+        f = e;
+        e = d + temp1;
+        d = c;
+        c = b;
+        b = a;
+        a = temp1 + temp2;
+    }
+
+    crypto->hsh_ivw[0] += a;
+    crypto->hsh_ivw[1] += b;
+    crypto->hsh_ivw[2] += c;
+    crypto->hsh_ivw[3] += d;
+    crypto->hsh_ivw[4] += e;
+    crypto->hsh_ivw[5] += f;
+    crypto->hsh_ivw[6] += g;
+    crypto->hsh_ivw[7] += h;
+}
 static const uint64_t octeon_sha3_round_constants[24] = {
     0x0000000000000001ULL, 0x0000000000008082ULL,
     0x800000000000808aULL, 0x8000000080008000ULL,
@@ -1533,6 +1894,116 @@ static void octeon_gfm_mul(const uint64_t x[2], const 
uint64_t y[2],
     out[0] = zh;
     out[1] = zl;
 }
+static uint64_t octeon_hsh_mf_window(MIPSOcteonCryptoState *crypto,
+                                     uint32_t sel)
+{
+    if (crypto->shared_mode == OCTEON_SHARED_MODE_ZUC &&
+        octeon_zuc_is_shared_dmfc2_sel(sel)) {
+        if (sel >= OCTEON_HSH_DATW(0) &&
+            sel <= OCTEON_HSH_DATW(7)) {
+            unsigned int idx = sel - OCTEON_HSH_DATW(0);
+
+            return octeon_zuc_pack_pair(crypto->zuc_lfsr[idx * 2],
+                                        crypto->zuc_lfsr[idx * 2 + 1]);
+        }
+        switch (sel) {
+        case OCTEON_HSH_DATW(8):
+            return octeon_zuc_pack_pair(crypto->zuc_fsm[0],
+                                        crypto->zuc_fsm[1]);
+        case OCTEON_HSH_DATW(9):
+        case OCTEON_HSH_IVW(0):
+            return octeon_zuc_pack_pair(crypto->zuc_window[0],
+                                        crypto->zuc_window[1]);
+        case OCTEON_HSH_DATW(10):
+            return crypto->zuc_window[2];
+        case OCTEON_HSH_DATW(11):
+        case OCTEON_HSH_IVW(3):
+            return crypto->zuc_tresult;
+        case OCTEON_HSH_DATW(15):
+        case OCTEON_SHA3_DAT24_SEL:
+            return 0;
+        case OCTEON_HSH_IVW(1):
+            return crypto->zuc_fsm[0];
+        case OCTEON_HSH_IVW(2):
+            return crypto->zuc_fsm[1];
+        default:
+            g_assert_not_reached();
+        }
+    }
+
+    if (crypto->shared_mode == OCTEON_SHARED_MODE_SNOW3G) {
+        if (sel >= OCTEON_SNOW3G_LFSR(0) &&
+            sel <= OCTEON_SNOW3G_LFSR(7)) {
+            unsigned int idx = sel - OCTEON_SNOW3G_LFSR(0);
+
+            return ((uint64_t)crypto->snow3g_lfsr[idx * 2] << 32) |
+                   crypto->snow3g_lfsr[idx * 2 + 1];
+        }
+        switch (sel) {
+        case OCTEON_SNOW3G_RESULT_SEL:
+            return crypto->snow3g_result;
+        case OCTEON_SNOW3G_FSM(0):
+        case OCTEON_SNOW3G_FSM(1):
+        case OCTEON_SNOW3G_FSM(2):
+            return crypto->snow3g_fsm[sel - OCTEON_SNOW3G_FSM(0)];
+        default:
+            break;
+        }
+    }
+
+    if (crypto->shared_mode == OCTEON_SHARED_MODE_SHA3 &&
+        octeon_sha3_is_dat_sel(sel)) {
+        int sha3_pos = octeon_sha3_dat_pos_from_sel(sel);
+
+        return octeon_sha3_lane_to_reg(crypto->sha3_state[sha3_pos]);
+    }
+
+    if (sel >= OCTEON_HSH_DATW(0) &&
+        sel <= OCTEON_HSH_DATW(15)) {
+        return crypto->hsh_datw[sel - OCTEON_HSH_DATW(0)];
+    }
+    return crypto->hsh_ivw[sel - OCTEON_HSH_IVW(0)];
+}
+
+#define OCTEON_HSH_MF_DATW(N) \
+uint64_t helper_octeon_cp2_mf_hsh_datw ## N(CPUMIPSState *env) \
+{ \
+    return octeon_hsh_mf_window(&env->octeon_crypto, \
+                                OCTEON_HSH_DATW(N)); \
+}
+OCTEON_HSH_MF_DATW(0)
+OCTEON_HSH_MF_DATW(1)
+OCTEON_HSH_MF_DATW(2)
+OCTEON_HSH_MF_DATW(3)
+OCTEON_HSH_MF_DATW(4)
+OCTEON_HSH_MF_DATW(5)
+OCTEON_HSH_MF_DATW(6)
+OCTEON_HSH_MF_DATW(7)
+OCTEON_HSH_MF_DATW(8)
+OCTEON_HSH_MF_DATW(9)
+OCTEON_HSH_MF_DATW(10)
+OCTEON_HSH_MF_DATW(11)
+OCTEON_HSH_MF_DATW(12)
+OCTEON_HSH_MF_DATW(13)
+OCTEON_HSH_MF_DATW(14)
+OCTEON_HSH_MF_DATW(15)
+#undef OCTEON_HSH_MF_DATW
+
+#define OCTEON_HSH_MF_IVW(N) \
+uint64_t helper_octeon_cp2_mf_hsh_ivw ## N(CPUMIPSState *env) \
+{ \
+    return octeon_hsh_mf_window(&env->octeon_crypto, \
+                                OCTEON_HSH_IVW(N)); \
+}
+OCTEON_HSH_MF_IVW(0)
+OCTEON_HSH_MF_IVW(1)
+OCTEON_HSH_MF_IVW(2)
+OCTEON_HSH_MF_IVW(3)
+OCTEON_HSH_MF_IVW(4)
+OCTEON_HSH_MF_IVW(5)
+OCTEON_HSH_MF_IVW(6)
+OCTEON_HSH_MF_IVW(7)
+#undef OCTEON_HSH_MF_IVW
 uint64_t helper_octeon_cp2_mf_sha3_dat24(CPUMIPSState *env)
 {
     MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
@@ -1591,6 +2062,105 @@ static bool 
octeon_zuc_store_shared(MIPSOcteonCryptoState *crypto,
         g_assert_not_reached();
     }
 }
+static void octeon_hsh_mt_datw(MIPSOcteonCryptoState *crypto,
+                               unsigned int index, uint64_t value)
+{
+    uint32_t sel = OCTEON_HSH_DATW(index);
+
+    if (octeon_zuc_store_shared(crypto, sel, value)) {
+        return;
+    }
+    if (index == 15) {
+        crypto->hsh_datw[15] = value;
+        octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_SHA512);
+        octeon_sha512_transform(crypto);
+    } else {
+        octeon_store_shared_hsh_window(crypto, sel, value);
+    }
+}
+
+static void octeon_hsh_mt_ivw(MIPSOcteonCryptoState *crypto,
+                              unsigned int index, uint64_t value)
+{
+    uint32_t sel = OCTEON_HSH_IVW(index);
+
+    if (!octeon_zuc_store_shared(crypto, sel, value)) {
+        octeon_store_shared_hsh_window(crypto, sel, value);
+    }
+}
+
+#define OCTEON_HSH_MT_DATW(N) \
+void helper_octeon_cp2_mt_hsh_datw ## N(CPUMIPSState *env, uint64_t value) \
+{ \
+    octeon_hsh_mt_datw(&env->octeon_crypto, N, value); \
+}
+OCTEON_HSH_MT_DATW(0)
+OCTEON_HSH_MT_DATW(1)
+OCTEON_HSH_MT_DATW(2)
+OCTEON_HSH_MT_DATW(3)
+OCTEON_HSH_MT_DATW(4)
+OCTEON_HSH_MT_DATW(5)
+OCTEON_HSH_MT_DATW(6)
+OCTEON_HSH_MT_DATW(7)
+OCTEON_HSH_MT_DATW(8)
+OCTEON_HSH_MT_DATW(9)
+OCTEON_HSH_MT_DATW(10)
+OCTEON_HSH_MT_DATW(11)
+OCTEON_HSH_MT_DATW(12)
+OCTEON_HSH_MT_DATW(13)
+OCTEON_HSH_MT_DATW(14)
+OCTEON_HSH_MT_DATW(15)
+#undef OCTEON_HSH_MT_DATW
+
+#define OCTEON_HSH_MT_IVW(N) \
+void helper_octeon_cp2_mt_hsh_ivw ## N(CPUMIPSState *env, uint64_t value) \
+{ \
+    octeon_hsh_mt_ivw(&env->octeon_crypto, N, value); \
+}
+OCTEON_HSH_MT_IVW(0)
+OCTEON_HSH_MT_IVW(1)
+OCTEON_HSH_MT_IVW(2)
+OCTEON_HSH_MT_IVW(3)
+OCTEON_HSH_MT_IVW(4)
+OCTEON_HSH_MT_IVW(5)
+OCTEON_HSH_MT_IVW(6)
+OCTEON_HSH_MT_IVW(7)
+#undef OCTEON_HSH_MT_IVW
+
+void helper_octeon_cp2_mt_hsh_startsha_compat(CPUMIPSState *env,
+                                              uint64_t value)
+{
+    env->octeon_crypto.hsh_dat[7] = value;
+    octeon_sha1_transform(&env->octeon_crypto);
+}
+
+void helper_octeon_cp2_mt_hsh_startmd5(CPUMIPSState *env, uint64_t value)
+{
+    env->octeon_crypto.hsh_dat[7] = value;
+    octeon_md5_transform(&env->octeon_crypto);
+}
+
+void helper_octeon_cp2_mt_hsh_startsha256(CPUMIPSState *env, uint64_t value)
+{
+    env->octeon_crypto.hsh_dat[7] = value;
+    octeon_sha256_transform(&env->octeon_crypto);
+}
+
+void helper_octeon_cp2_mt_hsh_startsha(CPUMIPSState *env, uint64_t value)
+{
+    env->octeon_crypto.hsh_dat[7] = value;
+    octeon_sha1_transform(&env->octeon_crypto);
+}
+
+void helper_octeon_cp2_mt_hsh_startsha512(CPUMIPSState *env, uint64_t value)
+{
+    MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
+
+    crypto->hsh_datw[15] = value;
+    octeon_set_shared_mode(crypto, OCTEON_SHARED_MODE_SHA512);
+    octeon_sha512_transform(crypto);
+}
+
 static void octeon_sha3_mt_dat(MIPSOcteonCryptoState *crypto,
                                uint32_t sel, uint64_t value)
 {

-- 
2.54.0


Reply via email to