Commit afc8b7d3 authored by Richard Henderson's avatar Richard Henderson Committed by Peter Maydell
Browse files

target/arm: Split helper_crypto_sha1_3reg



Rather than passing an opcode to a helper, fully decode the
operation at translate time.  Use clear_tail_16 to zap the
balance of the SVE register with the AdvSIMD write.

Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Message-id: 20200514212831.31248-6-richard.henderson@linaro.org
Reviewed-by: default avatarPeter Maydell <peter.maydell@linaro.org>
Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parent effa992f
Loading
Loading
Loading
Loading
+64 −39
Original line number Diff line number Diff line
@@ -24,11 +24,11 @@ union CRYPTO_STATE {
};

#ifdef HOST_WORDS_BIGENDIAN
#define CR_ST_BYTE(state, i)   (state.bytes[(15 - (i)) ^ 8])
#define CR_ST_WORD(state, i)   (state.words[(3 - (i)) ^ 2])
#define CR_ST_BYTE(state, i)   ((state).bytes[(15 - (i)) ^ 8])
#define CR_ST_WORD(state, i)   ((state).words[(3 - (i)) ^ 2])
#else
#define CR_ST_BYTE(state, i)   (state.bytes[i])
#define CR_ST_WORD(state, i)   (state.words[i])
#define CR_ST_BYTE(state, i)   ((state).bytes[i])
#define CR_ST_WORD(state, i)   ((state).words[i])
#endif

/*
@@ -258,37 +258,31 @@ static uint32_t maj(uint32_t x, uint32_t y, uint32_t z)
    return (x & y) | ((x | y) & z);
}

void HELPER(crypto_sha1_3reg)(void *vd, void *vn, void *vm, uint32_t op)
void HELPER(crypto_sha1su0)(void *vd, void *vn, void *vm, uint32_t desc)
{
    uint64_t *d = vd, *n = vn, *m = vm;
    uint64_t d0, d1;

    d0 = d[1] ^ d[0] ^ m[0];
    d1 = n[0] ^ d[1] ^ m[1];
    d[0] = d0;
    d[1] = d1;

    clear_tail_16(vd, desc);
}

static inline void crypto_sha1_3reg(uint64_t *rd, uint64_t *rn,
                                    uint64_t *rm, uint32_t desc,
                                    uint32_t (*fn)(union CRYPTO_STATE *d))
{
    uint64_t *rd = vd;
    uint64_t *rn = vn;
    uint64_t *rm = vm;
    union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
    union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
    union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };

    if (op == 3) { /* sha1su0 */
        d.l[0] ^= d.l[1] ^ m.l[0];
        d.l[1] ^= n.l[0] ^ m.l[1];
    } else {
    int i;

    for (i = 0; i < 4; i++) {
            uint32_t t;
        uint32_t t = fn(&d);

            switch (op) {
            case 0: /* sha1c */
                t = cho(CR_ST_WORD(d, 1), CR_ST_WORD(d, 2), CR_ST_WORD(d, 3));
                break;
            case 1: /* sha1p */
                t = par(CR_ST_WORD(d, 1), CR_ST_WORD(d, 2), CR_ST_WORD(d, 3));
                break;
            case 2: /* sha1m */
                t = maj(CR_ST_WORD(d, 1), CR_ST_WORD(d, 2), CR_ST_WORD(d, 3));
                break;
            default:
                g_assert_not_reached();
            }
        t += rol32(CR_ST_WORD(d, 0), 5) + CR_ST_WORD(n, 0)
             + CR_ST_WORD(m, i);

@@ -298,9 +292,40 @@ void HELPER(crypto_sha1_3reg)(void *vd, void *vn, void *vm, uint32_t op)
        CR_ST_WORD(d, 1) = CR_ST_WORD(d, 0);
        CR_ST_WORD(d, 0) = t;
    }
    }
    rd[0] = d.l[0];
    rd[1] = d.l[1];

    clear_tail_16(rd, desc);
}

static uint32_t do_sha1c(union CRYPTO_STATE *d)
{
    return cho(CR_ST_WORD(*d, 1), CR_ST_WORD(*d, 2), CR_ST_WORD(*d, 3));
}

void HELPER(crypto_sha1c)(void *vd, void *vn, void *vm, uint32_t desc)
{
    crypto_sha1_3reg(vd, vn, vm, desc, do_sha1c);
}

static uint32_t do_sha1p(union CRYPTO_STATE *d)
{
    return par(CR_ST_WORD(*d, 1), CR_ST_WORD(*d, 2), CR_ST_WORD(*d, 3));
}

void HELPER(crypto_sha1p)(void *vd, void *vn, void *vm, uint32_t desc)
{
    crypto_sha1_3reg(vd, vn, vm, desc, do_sha1p);
}

static uint32_t do_sha1m(union CRYPTO_STATE *d)
{
    return maj(CR_ST_WORD(*d, 1), CR_ST_WORD(*d, 2), CR_ST_WORD(*d, 3));
}

void HELPER(crypto_sha1m)(void *vd, void *vn, void *vm, uint32_t desc)
{
    crypto_sha1_3reg(vd, vn, vm, desc, do_sha1m);
}

void HELPER(crypto_sha1h)(void *vd, void *vm, uint32_t desc)
+4 −1
Original line number Diff line number Diff line
@@ -513,7 +513,10 @@ DEF_HELPER_FLAGS_2(neon_qzip32, TCG_CALL_NO_RWG, void, ptr, ptr)
DEF_HELPER_FLAGS_4(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)

DEF_HELPER_FLAGS_4(crypto_sha1_3reg, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(crypto_sha1su0, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(crypto_sha1c, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(crypto_sha1p, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_4(crypto_sha1m, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
DEF_HELPER_FLAGS_3(crypto_sha1h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
DEF_HELPER_FLAGS_3(crypto_sha1su1, TCG_CALL_NO_RWG, void, ptr, ptr, i32)

+4 −2
Original line number Diff line number Diff line
@@ -168,8 +168,10 @@ VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
@3same_crypto    .... .... .... .... .... .... .... .... \
                 &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=0 q=1

SHA1_3s          1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \
                 vm=%vm_dp vn=%vn_dp vd=%vd_dp
SHA1C_3s         1111 001 0 0 . 00 .... .... 1100 . 1 . 0 .... @3same_crypto
SHA1P_3s         1111 001 0 0 . 01 .... .... 1100 . 1 . 0 .... @3same_crypto
SHA1M_3s         1111 001 0 0 . 10 .... .... 1100 . 1 . 0 .... @3same_crypto
SHA1SU0_3s       1111 001 0 0 . 11 .... .... 1100 . 1 . 0 .... @3same_crypto
SHA256H_3s       1111 001 1 0 . 00 .... .... 1100 . 1 . 0 .... @3same_crypto
SHA256H2_3s      1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... @3same_crypto
SHA256SU1_3s     1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... @3same_crypto
+11 −18
Original line number Diff line number Diff line
@@ -13475,10 +13475,19 @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)

    switch (opcode) {
    case 0: /* SHA1C */
        genfn = gen_helper_crypto_sha1c;
        feature = dc_isar_feature(aa64_sha1, s);
        break;
    case 1: /* SHA1P */
        genfn = gen_helper_crypto_sha1p;
        feature = dc_isar_feature(aa64_sha1, s);
        break;
    case 2: /* SHA1M */
        genfn = gen_helper_crypto_sha1m;
        feature = dc_isar_feature(aa64_sha1, s);
        break;
    case 3: /* SHA1SU0 */
        genfn = NULL;
        genfn = gen_helper_crypto_sha1su0;
        feature = dc_isar_feature(aa64_sha1, s);
        break;
    case 4: /* SHA256H */
@@ -13506,23 +13515,7 @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
    if (!fp_access_check(s)) {
        return;
    }

    if (genfn) {
    gen_gvec_op3_ool(s, true, rd, rn, rm, 0, genfn);
    } else {
        TCGv_i32 tcg_opcode = tcg_const_i32(opcode);
        TCGv_ptr tcg_rd_ptr = vec_full_reg_ptr(s, rd);
        TCGv_ptr tcg_rn_ptr = vec_full_reg_ptr(s, rn);
        TCGv_ptr tcg_rm_ptr = vec_full_reg_ptr(s, rm);

        gen_helper_crypto_sha1_3reg(tcg_rd_ptr, tcg_rn_ptr,
                                    tcg_rm_ptr, tcg_opcode);

        tcg_temp_free_i32(tcg_opcode);
        tcg_temp_free_ptr(tcg_rd_ptr);
        tcg_temp_free_ptr(tcg_rn_ptr);
        tcg_temp_free_ptr(tcg_rm_ptr);
    }
}

/* Crypto two-reg SHA
+12 −34
Original line number Diff line number Diff line
@@ -693,42 +693,20 @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
DO_VQRDMLAH(VQRDMLAH, gen_gvec_sqrdmlah_qc)
DO_VQRDMLAH(VQRDMLSH, gen_gvec_sqrdmlsh_qc)

static bool trans_SHA1_3s(DisasContext *s, arg_SHA1_3s *a)
{
    TCGv_ptr ptr1, ptr2, ptr3;
    TCGv_i32 tmp;

    if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
        !dc_isar_feature(aa32_sha1, s)) {
        return false;
    }

    /* UNDEF accesses to D16-D31 if they don't exist. */
    if (!dc_isar_feature(aa32_simd_r32, s) &&
        ((a->vd | a->vn | a->vm) & 0x10)) {
        return false;
    }

    if ((a->vn | a->vm | a->vd) & 1) {
        return false;
    }

    if (!vfp_access_check(s)) {
        return true;
#define DO_SHA1(NAME, FUNC)                                             \
    WRAP_OOL_FN(gen_##NAME##_3s, FUNC)                                  \
    static bool trans_##NAME##_3s(DisasContext *s, arg_3same *a)        \
    {                                                                   \
        if (!dc_isar_feature(aa32_sha1, s)) {                           \
            return false;                                               \
        }                                                               \
        return do_3same(s, a, gen_##NAME##_3s);                         \
    }

    ptr1 = vfp_reg_ptr(true, a->vd);
    ptr2 = vfp_reg_ptr(true, a->vn);
    ptr3 = vfp_reg_ptr(true, a->vm);
    tmp = tcg_const_i32(a->optype);
    gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp);
    tcg_temp_free_i32(tmp);
    tcg_temp_free_ptr(ptr1);
    tcg_temp_free_ptr(ptr2);
    tcg_temp_free_ptr(ptr3);

    return true;
}
DO_SHA1(SHA1C, gen_helper_crypto_sha1c)
DO_SHA1(SHA1P, gen_helper_crypto_sha1p)
DO_SHA1(SHA1M, gen_helper_crypto_sha1m)
DO_SHA1(SHA1SU0, gen_helper_crypto_sha1su0)

#define DO_SHA2(NAME, FUNC)                                             \
    WRAP_OOL_FN(gen_##NAME##_3s, FUNC)                                  \