diff mbox series

[net-next,v6,19/23] zinc: Curve25519 ARM implementation

Message ID 20180925145622.29959-20-Jason@zx2c4.com (mailing list archive)
State Not Applicable
Delegated to: Herbert Xu
Headers show
Series WireGuard: Secure Network Tunnel | expand

Commit Message

Jason A. Donenfeld Sept. 25, 2018, 2:56 p.m. UTC
This comes from Dan Bernstein and Peter Schwabe's public domain NEON
code, and has been modified to be friendly for kernel space, as well as
removing some qhasm strangeness to be more idiomatic.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Cc: Samuel Neves <sneves@dei.uc.pt>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Greg KH <gregkh@linuxfoundation.org>
Cc: Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: linux-arm-kernel@lists.infradead.org
---
 lib/zinc/Makefile                         |    1 +
 lib/zinc/curve25519/curve25519-arm-glue.h |   42 +
 lib/zinc/curve25519/curve25519-arm.S      | 2095 +++++++++++++++++++++
 lib/zinc/curve25519/curve25519.c          |    2 +
 4 files changed, 2140 insertions(+)
 create mode 100644 lib/zinc/curve25519/curve25519-arm-glue.h
 create mode 100644 lib/zinc/curve25519/curve25519-arm.S

Comments

Ard Biesheuvel Oct. 2, 2018, 4:59 p.m. UTC | #1
Hi Jason,

On 25 September 2018 at 16:56, Jason A. Donenfeld <Jason@zx2c4.com> wrote:
> This comes from Dan Bernstein and Peter Schwabe's public domain NEON
> code, and has been modified to be friendly for kernel space, as well as
> removing some qhasm strangeness to be more idiomatic.
>
> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
> Cc: Samuel Neves <sneves@dei.uc.pt>
> Cc: Andy Lutomirski <luto@kernel.org>
> Cc: Greg KH <gregkh@linuxfoundation.org>
> Cc: Jean-Philippe Aumasson <jeanphilippe.aumasson@gmail.com>
> Cc: Russell King <linux@armlinux.org.uk>
> Cc: linux-arm-kernel@lists.infradead.org
> ---
>  lib/zinc/Makefile                         |    1 +
>  lib/zinc/curve25519/curve25519-arm-glue.h |   42 +
>  lib/zinc/curve25519/curve25519-arm.S      | 2095 +++++++++++++++++++++
>  lib/zinc/curve25519/curve25519.c          |    2 +
>  4 files changed, 2140 insertions(+)
>  create mode 100644 lib/zinc/curve25519/curve25519-arm-glue.h
>  create mode 100644 lib/zinc/curve25519/curve25519-arm.S
>
> diff --git a/lib/zinc/Makefile b/lib/zinc/Makefile
> index 65440438c6e5..be73c342f9ba 100644
> --- a/lib/zinc/Makefile
> +++ b/lib/zinc/Makefile
> @@ -27,4 +27,5 @@ zinc_blake2s-$(CONFIG_ZINC_ARCH_X86_64) += blake2s/blake2s-x86_64.o
>  obj-$(CONFIG_ZINC_BLAKE2S) += zinc_blake2s.o
>
>  zinc_curve25519-y := curve25519/curve25519.o
> +zinc_curve25519-$(CONFIG_ZINC_ARCH_ARM) += curve25519/curve25519-arm.o
>  obj-$(CONFIG_ZINC_CURVE25519) += zinc_curve25519.o
> diff --git a/lib/zinc/curve25519/curve25519-arm-glue.h b/lib/zinc/curve25519/curve25519-arm-glue.h
> new file mode 100644
> index 000000000000..9211bcab5615
> --- /dev/null
> +++ b/lib/zinc/curve25519/curve25519-arm-glue.h
> @@ -0,0 +1,42 @@
> +/* SPDX-License-Identifier: GPL-2.0 OR MIT */
> +/*
> + * Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
> + */
> +
> +#include <asm/hwcap.h>
> +#include <asm/neon.h>
> +#include <asm/simd.h>
> +
> +#if defined(CONFIG_KERNEL_MODE_NEON)
> +asmlinkage void curve25519_neon(u8 mypublic[CURVE25519_KEY_SIZE],
> +                               const u8 secret[CURVE25519_KEY_SIZE],
> +                               const u8 basepoint[CURVE25519_KEY_SIZE]);
> +#endif
> +
> +static bool curve25519_use_neon __ro_after_init;
> +
> +static void __init curve25519_fpu_init(void)
> +{
> +       curve25519_use_neon = elf_hwcap & HWCAP_NEON;
> +}
> +
> +static inline bool curve25519_arch(u8 mypublic[CURVE25519_KEY_SIZE],
> +                                  const u8 secret[CURVE25519_KEY_SIZE],
> +                                  const u8 basepoint[CURVE25519_KEY_SIZE])
> +{
> +#if defined(CONFIG_KERNEL_MODE_NEON)
> +       if (curve25519_use_neon && may_use_simd()) {
> +               kernel_neon_begin();
> +               curve25519_neon(mypublic, secret, basepoint);
> +               kernel_neon_end();
> +               return true;
> +       }
> +#endif
> +       return false;
> +}
> +
> +static inline bool curve25519_base_arch(u8 pub[CURVE25519_KEY_SIZE],
> +                                       const u8 secret[CURVE25519_KEY_SIZE])
> +{
> +       return false;
> +}

Shouldn't this use the new simd abstraction as well?


> diff --git a/lib/zinc/curve25519/curve25519-arm.S b/lib/zinc/curve25519/curve25519-arm.S
> new file mode 100644
> index 000000000000..db6570c20fd1
> --- /dev/null
> +++ b/lib/zinc/curve25519/curve25519-arm.S
> @@ -0,0 +1,2095 @@
> +/* SPDX-License-Identifier: GPL-2.0 OR MIT */
> +/*
> + * Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
> + *
> + * Based on public domain code from Daniel J. Bernstein and Peter Schwabe. This
> + * has been built from SUPERCOP's curve25519/neon2/scalarmult.pq using qhasm,
> + * but has subsequently been manually reworked for use in kernel space.
> + */
> +
> +#ifdef CONFIG_KERNEL_MODE_NEON
> +#include <linux/linkage.h>
> +
> +.text
> +.fpu neon
> +.arch armv7-a
> +.align 4
> +
> +ENTRY(curve25519_neon)
> +       push            {r4-r11, lr}
> +       mov             ip, sp
> +       sub             r3, sp, #704
> +       and             r3, r3, #0xfffffff0
> +       mov             sp, r3
> +       movw            r4, #0
> +       movw            r5, #254
> +       vmov.i32        q0, #1
> +       vshr.u64        q1, q0, #7
> +       vshr.u64        q0, q0, #8
> +       vmov.i32        d4, #19
> +       vmov.i32        d5, #38
> +       add             r6, sp, #480
> +       vst1.8          {d2-d3}, [r6, : 128]
> +       add             r6, sp, #496
> +       vst1.8          {d0-d1}, [r6, : 128]
> +       add             r6, sp, #512
> +       vst1.8          {d4-d5}, [r6, : 128]

I guess qhasm means generated code, right?

Because many of these adds are completely redundant ...

> +       add             r6, r3, #0
> +       vmov.i32        q2, #0
> +       vst1.8          {d4-d5}, [r6, : 128]!
> +       vst1.8          {d4-d5}, [r6, : 128]!
> +       vst1.8          d4, [r6, : 64]
> +       add             r6, r3, #0

> +       movw            r7, #960
> +       sub             r7, r7, #2
> +       neg             r7, r7
> +       sub             r7, r7, r7, LSL #7

This looks odd as well.

Could you elaborate on what qhasm is exactly? And, as with the other
patches, I would prefer it if we could have your changes as a separate
patch (although having the qhasm base would be preferred)



> +       str             r7, [r6]
> +       add             r6, sp, #672
> +       vld1.8          {d4-d5}, [r1]!
> +       vld1.8          {d6-d7}, [r1]
> +       vst1.8          {d4-d5}, [r6, : 128]!
> +       vst1.8          {d6-d7}, [r6, : 128]
> +       sub             r1, r6, #16
> +       ldrb            r6, [r1]
> +       and             r6, r6, #248
> +       strb            r6, [r1]
> +       ldrb            r6, [r1, #31]
> +       and             r6, r6, #127
> +       orr             r6, r6, #64
> +       strb            r6, [r1, #31]
> +       vmov.i64        q2, #0xffffffff
> +       vshr.u64        q3, q2, #7
> +       vshr.u64        q2, q2, #6
> +       vld1.8          {d8}, [r2]
> +       vld1.8          {d10}, [r2]
> +       add             r2, r2, #6
> +       vld1.8          {d12}, [r2]
> +       vld1.8          {d14}, [r2]
> +       add             r2, r2, #6
> +       vld1.8          {d16}, [r2]
> +       add             r2, r2, #4
> +       vld1.8          {d18}, [r2]
> +       vld1.8          {d20}, [r2]
> +       add             r2, r2, #6
> +       vld1.8          {d22}, [r2]
> +       add             r2, r2, #2
> +       vld1.8          {d24}, [r2]
> +       vld1.8          {d26}, [r2]
> +       vshr.u64        q5, q5, #26
> +       vshr.u64        q6, q6, #3
> +       vshr.u64        q7, q7, #29
> +       vshr.u64        q8, q8, #6
> +       vshr.u64        q10, q10, #25
> +       vshr.u64        q11, q11, #3
> +       vshr.u64        q12, q12, #12
> +       vshr.u64        q13, q13, #38
> +       vand            q4, q4, q2
> +       vand            q6, q6, q2
> +       vand            q8, q8, q2
> +       vand            q10, q10, q2
> +       vand            q2, q12, q2
> +       vand            q5, q5, q3
> +       vand            q7, q7, q3
> +       vand            q9, q9, q3
> +       vand            q11, q11, q3
> +       vand            q3, q13, q3
> +       add             r2, r3, #48
> +       vadd.i64        q12, q4, q1
> +       vadd.i64        q13, q10, q1
> +       vshr.s64        q12, q12, #26
> +       vshr.s64        q13, q13, #26
> +       vadd.i64        q5, q5, q12
> +       vshl.i64        q12, q12, #26
> +       vadd.i64        q14, q5, q0
> +       vadd.i64        q11, q11, q13
> +       vshl.i64        q13, q13, #26
> +       vadd.i64        q15, q11, q0
> +       vsub.i64        q4, q4, q12
> +       vshr.s64        q12, q14, #25
> +       vsub.i64        q10, q10, q13
> +       vshr.s64        q13, q15, #25
> +       vadd.i64        q6, q6, q12
> +       vshl.i64        q12, q12, #25
> +       vadd.i64        q14, q6, q1
> +       vadd.i64        q2, q2, q13
> +       vsub.i64        q5, q5, q12
> +       vshr.s64        q12, q14, #26
> +       vshl.i64        q13, q13, #25
> +       vadd.i64        q14, q2, q1
> +       vadd.i64        q7, q7, q12
> +       vshl.i64        q12, q12, #26
> +       vadd.i64        q15, q7, q0
> +       vsub.i64        q11, q11, q13
> +       vshr.s64        q13, q14, #26
> +       vsub.i64        q6, q6, q12
> +       vshr.s64        q12, q15, #25
> +       vadd.i64        q3, q3, q13
> +       vshl.i64        q13, q13, #26
> +       vadd.i64        q14, q3, q0
> +       vadd.i64        q8, q8, q12
> +       vshl.i64        q12, q12, #25
> +       vadd.i64        q15, q8, q1
> +       add             r2, r2, #8
> +       vsub.i64        q2, q2, q13
> +       vshr.s64        q13, q14, #25
> +       vsub.i64        q7, q7, q12
> +       vshr.s64        q12, q15, #26
> +       vadd.i64        q14, q13, q13
> +       vadd.i64        q9, q9, q12
> +       vtrn.32         d12, d14
> +       vshl.i64        q12, q12, #26
> +       vtrn.32         d13, d15
> +       vadd.i64        q0, q9, q0
> +       vadd.i64        q4, q4, q14
> +       vst1.8          d12, [r2, : 64]!
> +       vshl.i64        q6, q13, #4
> +       vsub.i64        q7, q8, q12
> +       vshr.s64        q0, q0, #25
> +       vadd.i64        q4, q4, q6
> +       vadd.i64        q6, q10, q0
> +       vshl.i64        q0, q0, #25
> +       vadd.i64        q8, q6, q1
> +       vadd.i64        q4, q4, q13
> +       vshl.i64        q10, q13, #25
> +       vadd.i64        q1, q4, q1
> +       vsub.i64        q0, q9, q0
> +       vshr.s64        q8, q8, #26
> +       vsub.i64        q3, q3, q10
> +       vtrn.32         d14, d0
> +       vshr.s64        q1, q1, #26
> +       vtrn.32         d15, d1
> +       vadd.i64        q0, q11, q8
> +       vst1.8          d14, [r2, : 64]
> +       vshl.i64        q7, q8, #26
> +       vadd.i64        q5, q5, q1
> +       vtrn.32         d4, d6
> +       vshl.i64        q1, q1, #26
> +       vtrn.32         d5, d7
> +       vsub.i64        q3, q6, q7
> +       add             r2, r2, #16
> +       vsub.i64        q1, q4, q1
> +       vst1.8          d4, [r2, : 64]
> +       vtrn.32         d6, d0
> +       vtrn.32         d7, d1
> +       sub             r2, r2, #8
> +       vtrn.32         d2, d10
> +       vtrn.32         d3, d11
> +       vst1.8          d6, [r2, : 64]
> +       sub             r2, r2, #24
> +       vst1.8          d2, [r2, : 64]
> +       add             r2, r3, #96
> +       vmov.i32        q0, #0
> +       vmov.i64        d2, #0xff
> +       vmov.i64        d3, #0
> +       vshr.u32        q1, q1, #7
> +       vst1.8          {d2-d3}, [r2, : 128]!
> +       vst1.8          {d0-d1}, [r2, : 128]!
> +       vst1.8          d0, [r2, : 64]
> +       add             r2, r3, #144
> +       vmov.i32        q0, #0
> +       vst1.8          {d0-d1}, [r2, : 128]!
> +       vst1.8          {d0-d1}, [r2, : 128]!
> +       vst1.8          d0, [r2, : 64]
> +       add             r2, r3, #240
> +       vmov.i32        q0, #0
> +       vmov.i64        d2, #0xff
> +       vmov.i64        d3, #0
> +       vshr.u32        q1, q1, #7
> +       vst1.8          {d2-d3}, [r2, : 128]!
> +       vst1.8          {d0-d1}, [r2, : 128]!
> +       vst1.8          d0, [r2, : 64]
> +       add             r2, r3, #48
> +       add             r6, r3, #192
> +       vld1.8          {d0-d1}, [r2, : 128]!
> +       vld1.8          {d2-d3}, [r2, : 128]!
> +       vld1.8          {d4}, [r2, : 64]
> +       vst1.8          {d0-d1}, [r6, : 128]!
> +       vst1.8          {d2-d3}, [r6, : 128]!
> +       vst1.8          d4, [r6, : 64]
> +.Lmainloop:
> +       mov             r2, r5, LSR #3
> +       and             r6, r5, #7
> +       ldrb            r2, [r1, r2]
> +       mov             r2, r2, LSR r6
> +       and             r2, r2, #1
> +       str             r5, [sp, #456]
> +       eor             r4, r4, r2
> +       str             r2, [sp, #460]
> +       neg             r2, r4
> +       add             r4, r3, #96
> +       add             r5, r3, #192
> +       add             r6, r3, #144
> +       vld1.8          {d8-d9}, [r4, : 128]!
> +       add             r7, r3, #240
> +       vld1.8          {d10-d11}, [r5, : 128]!
> +       veor            q6, q4, q5
> +       vld1.8          {d14-d15}, [r6, : 128]!
> +       vdup.i32        q8, r2
> +       vld1.8          {d18-d19}, [r7, : 128]!
> +       veor            q10, q7, q9
> +       vld1.8          {d22-d23}, [r4, : 128]!
> +       vand            q6, q6, q8
> +       vld1.8          {d24-d25}, [r5, : 128]!
> +       vand            q10, q10, q8
> +       vld1.8          {d26-d27}, [r6, : 128]!
> +       veor            q4, q4, q6
> +       vld1.8          {d28-d29}, [r7, : 128]!
> +       veor            q5, q5, q6
> +       vld1.8          {d0}, [r4, : 64]
> +       veor            q6, q7, q10
> +       vld1.8          {d2}, [r5, : 64]
> +       veor            q7, q9, q10
> +       vld1.8          {d4}, [r6, : 64]
> +       veor            q9, q11, q12
> +       vld1.8          {d6}, [r7, : 64]
> +       veor            q10, q0, q1
> +       sub             r2, r4, #32
> +       vand            q9, q9, q8
> +       sub             r4, r5, #32
> +       vand            q10, q10, q8
> +       sub             r5, r6, #32
> +       veor            q11, q11, q9
> +       sub             r6, r7, #32
> +       veor            q0, q0, q10
> +       veor            q9, q12, q9
> +       veor            q1, q1, q10
> +       veor            q10, q13, q14
> +       veor            q12, q2, q3
> +       vand            q10, q10, q8
> +       vand            q8, q12, q8
> +       veor            q12, q13, q10
> +       veor            q2, q2, q8
> +       veor            q10, q14, q10
> +       veor            q3, q3, q8
> +       vadd.i32        q8, q4, q6
> +       vsub.i32        q4, q4, q6
> +       vst1.8          {d16-d17}, [r2, : 128]!
> +       vadd.i32        q6, q11, q12
> +       vst1.8          {d8-d9}, [r5, : 128]!
> +       vsub.i32        q4, q11, q12
> +       vst1.8          {d12-d13}, [r2, : 128]!
> +       vadd.i32        q6, q0, q2
> +       vst1.8          {d8-d9}, [r5, : 128]!
> +       vsub.i32        q0, q0, q2
> +       vst1.8          d12, [r2, : 64]
> +       vadd.i32        q2, q5, q7
> +       vst1.8          d0, [r5, : 64]
> +       vsub.i32        q0, q5, q7
> +       vst1.8          {d4-d5}, [r4, : 128]!
> +       vadd.i32        q2, q9, q10
> +       vst1.8          {d0-d1}, [r6, : 128]!
> +       vsub.i32        q0, q9, q10
> +       vst1.8          {d4-d5}, [r4, : 128]!
> +       vadd.i32        q2, q1, q3
> +       vst1.8          {d0-d1}, [r6, : 128]!
> +       vsub.i32        q0, q1, q3
> +       vst1.8          d4, [r4, : 64]
> +       vst1.8          d0, [r6, : 64]
> +       add             r2, sp, #512
> +       add             r4, r3, #96
> +       add             r5, r3, #144
> +       vld1.8          {d0-d1}, [r2, : 128]
> +       vld1.8          {d2-d3}, [r4, : 128]!
> +       vld1.8          {d4-d5}, [r5, : 128]!
> +       vzip.i32        q1, q2
> +       vld1.8          {d6-d7}, [r4, : 128]!
> +       vld1.8          {d8-d9}, [r5, : 128]!
> +       vshl.i32        q5, q1, #1
> +       vzip.i32        q3, q4
> +       vshl.i32        q6, q2, #1
> +       vld1.8          {d14}, [r4, : 64]
> +       vshl.i32        q8, q3, #1
> +       vld1.8          {d15}, [r5, : 64]
> +       vshl.i32        q9, q4, #1
> +       vmul.i32        d21, d7, d1
> +       vtrn.32         d14, d15
> +       vmul.i32        q11, q4, q0
> +       vmul.i32        q0, q7, q0
> +       vmull.s32       q12, d2, d2
> +       vmlal.s32       q12, d11, d1
> +       vmlal.s32       q12, d12, d0
> +       vmlal.s32       q12, d13, d23
> +       vmlal.s32       q12, d16, d22
> +       vmlal.s32       q12, d7, d21
> +       vmull.s32       q10, d2, d11
> +       vmlal.s32       q10, d4, d1
> +       vmlal.s32       q10, d13, d0
> +       vmlal.s32       q10, d6, d23
> +       vmlal.s32       q10, d17, d22
> +       vmull.s32       q13, d10, d4
> +       vmlal.s32       q13, d11, d3
> +       vmlal.s32       q13, d13, d1
> +       vmlal.s32       q13, d16, d0
> +       vmlal.s32       q13, d17, d23
> +       vmlal.s32       q13, d8, d22
> +       vmull.s32       q1, d10, d5
> +       vmlal.s32       q1, d11, d4
> +       vmlal.s32       q1, d6, d1
> +       vmlal.s32       q1, d17, d0
> +       vmlal.s32       q1, d8, d23
> +       vmull.s32       q14, d10, d6
> +       vmlal.s32       q14, d11, d13
> +       vmlal.s32       q14, d4, d4
> +       vmlal.s32       q14, d17, d1
> +       vmlal.s32       q14, d18, d0
> +       vmlal.s32       q14, d9, d23
> +       vmull.s32       q11, d10, d7
> +       vmlal.s32       q11, d11, d6
> +       vmlal.s32       q11, d12, d5
> +       vmlal.s32       q11, d8, d1
> +       vmlal.s32       q11, d19, d0
> +       vmull.s32       q15, d10, d8
> +       vmlal.s32       q15, d11, d17
> +       vmlal.s32       q15, d12, d6
> +       vmlal.s32       q15, d13, d5
> +       vmlal.s32       q15, d19, d1
> +       vmlal.s32       q15, d14, d0
> +       vmull.s32       q2, d10, d9
> +       vmlal.s32       q2, d11, d8
> +       vmlal.s32       q2, d12, d7
> +       vmlal.s32       q2, d13, d6
> +       vmlal.s32       q2, d14, d1
> +       vmull.s32       q0, d15, d1
> +       vmlal.s32       q0, d10, d14
> +       vmlal.s32       q0, d11, d19
> +       vmlal.s32       q0, d12, d8
> +       vmlal.s32       q0, d13, d17
> +       vmlal.s32       q0, d6, d6
> +       add             r2, sp, #480
> +       vld1.8          {d18-d19}, [r2, : 128]

If you append a ! here ...

> +       vmull.s32       q3, d16, d7
> +       vmlal.s32       q3, d10, d15
> +       vmlal.s32       q3, d11, d14
> +       vmlal.s32       q3, d12, d9
> +       vmlal.s32       q3, d13, d8
> +       add             r2, sp, #496

... you can drop this add

> +       vld1.8          {d8-d9}, [r2, : 128]
> +       vadd.i64        q5, q12, q9
> +       vadd.i64        q6, q15, q9
> +       vshr.s64        q5, q5, #26
> +       vshr.s64        q6, q6, #26
> +       vadd.i64        q7, q10, q5
> +       vshl.i64        q5, q5, #26
> +       vadd.i64        q8, q7, q4
> +       vadd.i64        q2, q2, q6
> +       vshl.i64        q6, q6, #26
> +       vadd.i64        q10, q2, q4
> +       vsub.i64        q5, q12, q5
> +       vshr.s64        q8, q8, #25
> +       vsub.i64        q6, q15, q6
> +       vshr.s64        q10, q10, #25
> +       vadd.i64        q12, q13, q8
> +       vshl.i64        q8, q8, #25
> +       vadd.i64        q13, q12, q9
> +       vadd.i64        q0, q0, q10
> +       vsub.i64        q7, q7, q8
> +       vshr.s64        q8, q13, #26
> +       vshl.i64        q10, q10, #25
> +       vadd.i64        q13, q0, q9
> +       vadd.i64        q1, q1, q8
> +       vshl.i64        q8, q8, #26
> +       vadd.i64        q15, q1, q4
> +       vsub.i64        q2, q2, q10
> +       vshr.s64        q10, q13, #26
> +       vsub.i64        q8, q12, q8
> +       vshr.s64        q12, q15, #25
> +       vadd.i64        q3, q3, q10
> +       vshl.i64        q10, q10, #26
> +       vadd.i64        q13, q3, q4
> +       vadd.i64        q14, q14, q12
> +       add             r2, r3, #288
> +       vshl.i64        q12, q12, #25
> +       add             r4, r3, #336
> +       vadd.i64        q15, q14, q9
> +       add             r2, r2, #8
> +       vsub.i64        q0, q0, q10
> +       add             r4, r4, #8
> +       vshr.s64        q10, q13, #25
> +       vsub.i64        q1, q1, q12
> +       vshr.s64        q12, q15, #26
> +       vadd.i64        q13, q10, q10
> +       vadd.i64        q11, q11, q12
> +       vtrn.32         d16, d2
> +       vshl.i64        q12, q12, #26
> +       vtrn.32         d17, d3
> +       vadd.i64        q1, q11, q4
> +       vadd.i64        q4, q5, q13
> +       vst1.8          d16, [r2, : 64]!
> +       vshl.i64        q5, q10, #4
> +       vst1.8          d17, [r4, : 64]!
> +       vsub.i64        q8, q14, q12
> +       vshr.s64        q1, q1, #25
> +       vadd.i64        q4, q4, q5
> +       vadd.i64        q5, q6, q1
> +       vshl.i64        q1, q1, #25
> +       vadd.i64        q6, q5, q9
> +       vadd.i64        q4, q4, q10
> +       vshl.i64        q10, q10, #25
> +       vadd.i64        q9, q4, q9
> +       vsub.i64        q1, q11, q1
> +       vshr.s64        q6, q6, #26
> +       vsub.i64        q3, q3, q10
> +       vtrn.32         d16, d2
> +       vshr.s64        q9, q9, #26
> +       vtrn.32         d17, d3
> +       vadd.i64        q1, q2, q6
> +       vst1.8          d16, [r2, : 64]
> +       vshl.i64        q2, q6, #26
> +       vst1.8          d17, [r4, : 64]
> +       vadd.i64        q6, q7, q9
> +       vtrn.32         d0, d6
> +       vshl.i64        q7, q9, #26
> +       vtrn.32         d1, d7
> +       vsub.i64        q2, q5, q2
> +       add             r2, r2, #16
> +       vsub.i64        q3, q4, q7
> +       vst1.8          d0, [r2, : 64]
> +       add             r4, r4, #16
> +       vst1.8          d1, [r4, : 64]
> +       vtrn.32         d4, d2
> +       vtrn.32         d5, d3
> +       sub             r2, r2, #8
> +       sub             r4, r4, #8
> +       vtrn.32         d6, d12
> +       vtrn.32         d7, d13
> +       vst1.8          d4, [r2, : 64]
> +       vst1.8          d5, [r4, : 64]
> +       sub             r2, r2, #24
> +       sub             r4, r4, #24
> +       vst1.8          d6, [r2, : 64]
> +       vst1.8          d7, [r4, : 64]
> +       add             r2, r3, #240
> +       add             r4, r3, #96
> +       vld1.8          {d0-d1}, [r4, : 128]!
> +       vld1.8          {d2-d3}, [r4, : 128]!
> +       vld1.8          {d4}, [r4, : 64]
> +       add             r4, r3, #144
> +       vld1.8          {d6-d7}, [r4, : 128]!
> +       vtrn.32         q0, q3
> +       vld1.8          {d8-d9}, [r4, : 128]!
> +       vshl.i32        q5, q0, #4
> +       vtrn.32         q1, q4
> +       vshl.i32        q6, q3, #4
> +       vadd.i32        q5, q5, q0
> +       vadd.i32        q6, q6, q3
> +       vshl.i32        q7, q1, #4
> +       vld1.8          {d5}, [r4, : 64]
> +       vshl.i32        q8, q4, #4
> +       vtrn.32         d4, d5
> +       vadd.i32        q7, q7, q1
> +       vadd.i32        q8, q8, q4
> +       vld1.8          {d18-d19}, [r2, : 128]!
> +       vshl.i32        q10, q2, #4
> +       vld1.8          {d22-d23}, [r2, : 128]!
> +       vadd.i32        q10, q10, q2
> +       vld1.8          {d24}, [r2, : 64]
> +       vadd.i32        q5, q5, q0
> +       add             r2, r3, #192
> +       vld1.8          {d26-d27}, [r2, : 128]!
> +       vadd.i32        q6, q6, q3
> +       vld1.8          {d28-d29}, [r2, : 128]!
> +       vadd.i32        q8, q8, q4
> +       vld1.8          {d25}, [r2, : 64]
> +       vadd.i32        q10, q10, q2
> +       vtrn.32         q9, q13
> +       vadd.i32        q7, q7, q1
> +       vadd.i32        q5, q5, q0
> +       vtrn.32         q11, q14
> +       vadd.i32        q6, q6, q3
> +       add             r2, sp, #528
> +       vadd.i32        q10, q10, q2
> +       vtrn.32         d24, d25
> +       vst1.8          {d12-d13}, [r2, : 128]

same here

> +       vshl.i32        q6, q13, #1
> +       add             r2, sp, #544
> +       vst1.8          {d20-d21}, [r2, : 128]

and here

> +       vshl.i32        q10, q14, #1
> +       add             r2, sp, #560
> +       vst1.8          {d12-d13}, [r2, : 128]

and here

> +       vshl.i32        q15, q12, #1
> +       vadd.i32        q8, q8, q4
> +       vext.32         d10, d31, d30, #0
> +       vadd.i32        q7, q7, q1
> +       add             r2, sp, #576
> +       vst1.8          {d16-d17}, [r2, : 128]

and here

> +       vmull.s32       q8, d18, d5
> +       vmlal.s32       q8, d26, d4
> +       vmlal.s32       q8, d19, d9
> +       vmlal.s32       q8, d27, d3
> +       vmlal.s32       q8, d22, d8
> +       vmlal.s32       q8, d28, d2
> +       vmlal.s32       q8, d23, d7
> +       vmlal.s32       q8, d29, d1
> +       vmlal.s32       q8, d24, d6
> +       vmlal.s32       q8, d25, d0
> +       add             r2, sp, #592
> +       vst1.8          {d14-d15}, [r2, : 128]

and here

> +       vmull.s32       q2, d18, d4
> +       vmlal.s32       q2, d12, d9
> +       vmlal.s32       q2, d13, d8
> +       vmlal.s32       q2, d19, d3
> +       vmlal.s32       q2, d22, d2
> +       vmlal.s32       q2, d23, d1
> +       vmlal.s32       q2, d24, d0
> +       add             r2, sp, #608
> +       vst1.8          {d20-d21}, [r2, : 128]

and here


> +       vmull.s32       q7, d18, d9
> +       vmlal.s32       q7, d26, d3
> +       vmlal.s32       q7, d19, d8
> +       vmlal.s32       q7, d27, d2
> +       vmlal.s32       q7, d22, d7
> +       vmlal.s32       q7, d28, d1
> +       vmlal.s32       q7, d23, d6
> +       vmlal.s32       q7, d29, d0
> +       add             r2, sp, #624
> +       vst1.8          {d10-d11}, [r2, : 128]

and here

> +       vmull.s32       q5, d18, d3
> +       vmlal.s32       q5, d19, d2
> +       vmlal.s32       q5, d22, d1
> +       vmlal.s32       q5, d23, d0
> +       vmlal.s32       q5, d12, d8
> +       add             r2, sp, #640
> +       vst1.8          {d16-d17}, [r2, : 128]
> +       vmull.s32       q4, d18, d8
> +       vmlal.s32       q4, d26, d2
> +       vmlal.s32       q4, d19, d7
> +       vmlal.s32       q4, d27, d1
> +       vmlal.s32       q4, d22, d6
> +       vmlal.s32       q4, d28, d0
> +       vmull.s32       q8, d18, d7
> +       vmlal.s32       q8, d26, d1
> +       vmlal.s32       q8, d19, d6
> +       vmlal.s32       q8, d27, d0
> +       add             r2, sp, #544
> +       vld1.8          {d20-d21}, [r2, : 128]
> +       vmlal.s32       q7, d24, d21
> +       vmlal.s32       q7, d25, d20
> +       vmlal.s32       q4, d23, d21
> +       vmlal.s32       q4, d29, d20
> +       vmlal.s32       q8, d22, d21
> +       vmlal.s32       q8, d28, d20
> +       vmlal.s32       q5, d24, d20
> +       add             r2, sp, #544

redundant add


I'll stop here - let me just note that this code does not strike me as
particularly well optimized for in-order cores (such as A7).

For instance, the sequence

vmlal.s32 q2, d18, d7
vmlal.s32 q2, d19, d6
vmlal.s32 q5, d18, d6
vmlal.s32 q5, d19, d21
vmlal.s32 q1, d18, d21
vmlal.s32 q1, d19, d29
vmlal.s32 q0, d18, d28
vmlal.s32 q0, d19, d9
vmlal.s32 q6, d18, d29
vmlal.s32 q6, d19, d28

can be reordered as

vmlal.s32 q2, d18, d7
vmlal.s32 q5, d18, d6
vmlal.s32 q1, d18, d21
vmlal.s32 q0, d18, d28
vmlal.s32 q6, d18, d29

vmlal.s32 q2, d19, d6
vmlal.s32 q5, d19, d21
vmlal.s32 q1, d19, d29
vmlal.s32 q0, d19, d9
vmlal.s32 q6, d19, d28

and not have every other instruction depend on the output of the previous one.

Obviously, the ultimate truth is in the benchmark numbers, but I'd
thought I'd mention it anyway.



> +       vst1.8          {d14-d15}, [r2, : 128]
> +       vmull.s32       q7, d18, d6
> +       vmlal.s32       q7, d26, d0
> +       add             r2, sp, #624
> +       vld1.8          {d30-d31}, [r2, : 128]
> +       vmlal.s32       q2, d30, d21
> +       vmlal.s32       q7, d19, d21
> +       vmlal.s32       q7, d27, d20
> +       add             r2, sp, #592
> +       vld1.8          {d26-d27}, [r2, : 128]
> +       vmlal.s32       q4, d25, d27
> +       vmlal.s32       q8, d29, d27
> +       vmlal.s32       q8, d25, d26
> +       vmlal.s32       q7, d28, d27
> +       vmlal.s32       q7, d29, d26
> +       add             r2, sp, #576
> +       vld1.8          {d28-d29}, [r2, : 128]
> +       vmlal.s32       q4, d24, d29
> +       vmlal.s32       q8, d23, d29
> +       vmlal.s32       q8, d24, d28
> +       vmlal.s32       q7, d22, d29
> +       vmlal.s32       q7, d23, d28
> +       add             r2, sp, #576
> +       vst1.8          {d8-d9}, [r2, : 128]
> +       add             r2, sp, #528
> +       vld1.8          {d8-d9}, [r2, : 128]
> +       vmlal.s32       q7, d24, d9
> +       vmlal.s32       q7, d25, d31
> +       vmull.s32       q1, d18, d2
> +       vmlal.s32       q1, d19, d1
> +       vmlal.s32       q1, d22, d0
> +       vmlal.s32       q1, d24, d27
> +       vmlal.s32       q1, d23, d20
> +       vmlal.s32       q1, d12, d7
> +       vmlal.s32       q1, d13, d6
> +       vmull.s32       q6, d18, d1
> +       vmlal.s32       q6, d19, d0
> +       vmlal.s32       q6, d23, d27
> +       vmlal.s32       q6, d22, d20
> +       vmlal.s32       q6, d24, d26
> +       vmull.s32       q0, d18, d0
> +       vmlal.s32       q0, d22, d27
> +       vmlal.s32       q0, d23, d26
> +       vmlal.s32       q0, d24, d31
> +       vmlal.s32       q0, d19, d20
> +       add             r2, sp, #608
> +       vld1.8          {d18-d19}, [r2, : 128]
> +       vmlal.s32       q2, d18, d7
> +       vmlal.s32       q2, d19, d6
> +       vmlal.s32       q5, d18, d6
> +       vmlal.s32       q5, d19, d21
> +       vmlal.s32       q1, d18, d21
> +       vmlal.s32       q1, d19, d29
> +       vmlal.s32       q0, d18, d28
> +       vmlal.s32       q0, d19, d9
> +       vmlal.s32       q6, d18, d29
> +       vmlal.s32       q6, d19, d28
> +       add             r2, sp, #560
> +       vld1.8          {d18-d19}, [r2, : 128]
> +       add             r2, sp, #480
> +       vld1.8          {d22-d23}, [r2, : 128]
> +       vmlal.s32       q5, d19, d7
> +       vmlal.s32       q0, d18, d21
> +       vmlal.s32       q0, d19, d29
> +       vmlal.s32       q6, d18, d6
> +       add             r2, sp, #496
> +       vld1.8          {d6-d7}, [r2, : 128]
> +       vmlal.s32       q6, d19, d21
> +       add             r2, sp, #544
> +       vld1.8          {d18-d19}, [r2, : 128]
> +       vmlal.s32       q0, d30, d8
> +       add             r2, sp, #640
> +       vld1.8          {d20-d21}, [r2, : 128]
> +       vmlal.s32       q5, d30, d29
> +       add             r2, sp, #576
> +       vld1.8          {d24-d25}, [r2, : 128]
> +       vmlal.s32       q1, d30, d28
> +       vadd.i64        q13, q0, q11
> +       vadd.i64        q14, q5, q11
> +       vmlal.s32       q6, d30, d9
> +       vshr.s64        q4, q13, #26
> +       vshr.s64        q13, q14, #26
> +       vadd.i64        q7, q7, q4
> +       vshl.i64        q4, q4, #26
> +       vadd.i64        q14, q7, q3
> +       vadd.i64        q9, q9, q13
> +       vshl.i64        q13, q13, #26
> +       vadd.i64        q15, q9, q3
> +       vsub.i64        q0, q0, q4
> +       vshr.s64        q4, q14, #25
> +       vsub.i64        q5, q5, q13
> +       vshr.s64        q13, q15, #25
> +       vadd.i64        q6, q6, q4
> +       vshl.i64        q4, q4, #25
> +       vadd.i64        q14, q6, q11
> +       vadd.i64        q2, q2, q13
> +       vsub.i64        q4, q7, q4
> +       vshr.s64        q7, q14, #26
> +       vshl.i64        q13, q13, #25
> +       vadd.i64        q14, q2, q11
> +       vadd.i64        q8, q8, q7
> +       vshl.i64        q7, q7, #26
> +       vadd.i64        q15, q8, q3
> +       vsub.i64        q9, q9, q13
> +       vshr.s64        q13, q14, #26
> +       vsub.i64        q6, q6, q7
> +       vshr.s64        q7, q15, #25
> +       vadd.i64        q10, q10, q13
> +       vshl.i64        q13, q13, #26
> +       vadd.i64        q14, q10, q3
> +       vadd.i64        q1, q1, q7
> +       add             r2, r3, #144
> +       vshl.i64        q7, q7, #25
> +       add             r4, r3, #96
> +       vadd.i64        q15, q1, q11
> +       add             r2, r2, #8
> +       vsub.i64        q2, q2, q13
> +       add             r4, r4, #8
> +       vshr.s64        q13, q14, #25
> +       vsub.i64        q7, q8, q7
> +       vshr.s64        q8, q15, #26
> +       vadd.i64        q14, q13, q13
> +       vadd.i64        q12, q12, q8
> +       vtrn.32         d12, d14
> +       vshl.i64        q8, q8, #26
> +       vtrn.32         d13, d15
> +       vadd.i64        q3, q12, q3
> +       vadd.i64        q0, q0, q14
> +       vst1.8          d12, [r2, : 64]!
> +       vshl.i64        q7, q13, #4
> +       vst1.8          d13, [r4, : 64]!
> +       vsub.i64        q1, q1, q8
> +       vshr.s64        q3, q3, #25
> +       vadd.i64        q0, q0, q7
> +       vadd.i64        q5, q5, q3
> +       vshl.i64        q3, q3, #25
> +       vadd.i64        q6, q5, q11
> +       vadd.i64        q0, q0, q13
> +       vshl.i64        q7, q13, #25
> +       vadd.i64        q8, q0, q11
> +       vsub.i64        q3, q12, q3
> +       vshr.s64        q6, q6, #26
> +       vsub.i64        q7, q10, q7
> +       vtrn.32         d2, d6
> +       vshr.s64        q8, q8, #26
> +       vtrn.32         d3, d7
> +       vadd.i64        q3, q9, q6
> +       vst1.8          d2, [r2, : 64]
> +       vshl.i64        q6, q6, #26
> +       vst1.8          d3, [r4, : 64]
> +       vadd.i64        q1, q4, q8
> +       vtrn.32         d4, d14
> +       vshl.i64        q4, q8, #26
> +       vtrn.32         d5, d15
> +       vsub.i64        q5, q5, q6
> +       add             r2, r2, #16
> +       vsub.i64        q0, q0, q4
> +       vst1.8          d4, [r2, : 64]
> +       add             r4, r4, #16
> +       vst1.8          d5, [r4, : 64]
> +       vtrn.32         d10, d6
> +       vtrn.32         d11, d7
> +       sub             r2, r2, #8
> +       sub             r4, r4, #8
> +       vtrn.32         d0, d2
> +       vtrn.32         d1, d3
> +       vst1.8          d10, [r2, : 64]
> +       vst1.8          d11, [r4, : 64]
> +       sub             r2, r2, #24
> +       sub             r4, r4, #24
> +       vst1.8          d0, [r2, : 64]
> +       vst1.8          d1, [r4, : 64]
> +       add             r2, r3, #288
> +       add             r4, r3, #336
> +       vld1.8          {d0-d1}, [r2, : 128]!
> +       vld1.8          {d2-d3}, [r4, : 128]!
> +       vsub.i32        q0, q0, q1
> +       vld1.8          {d2-d3}, [r2, : 128]!
> +       vld1.8          {d4-d5}, [r4, : 128]!
> +       vsub.i32        q1, q1, q2
> +       add             r5, r3, #240
> +       vld1.8          {d4}, [r2, : 64]
> +       vld1.8          {d6}, [r4, : 64]
> +       vsub.i32        q2, q2, q3
> +       vst1.8          {d0-d1}, [r5, : 128]!
> +       vst1.8          {d2-d3}, [r5, : 128]!
> +       vst1.8          d4, [r5, : 64]
> +       add             r2, r3, #144
> +       add             r4, r3, #96
> +       add             r5, r3, #144
> +       add             r6, r3, #192
> +       vld1.8          {d0-d1}, [r2, : 128]!
> +       vld1.8          {d2-d3}, [r4, : 128]!
> +       vsub.i32        q2, q0, q1
> +       vadd.i32        q0, q0, q1
> +       vld1.8          {d2-d3}, [r2, : 128]!
> +       vld1.8          {d6-d7}, [r4, : 128]!
> +       vsub.i32        q4, q1, q3
> +       vadd.i32        q1, q1, q3
> +       vld1.8          {d6}, [r2, : 64]
> +       vld1.8          {d10}, [r4, : 64]
> +       vsub.i32        q6, q3, q5
> +       vadd.i32        q3, q3, q5
> +       vst1.8          {d4-d5}, [r5, : 128]!
> +       vst1.8          {d0-d1}, [r6, : 128]!
> +       vst1.8          {d8-d9}, [r5, : 128]!
> +       vst1.8          {d2-d3}, [r6, : 128]!
> +       vst1.8          d12, [r5, : 64]
> +       vst1.8          d6, [r6, : 64]
> +       add             r2, r3, #0
> +       add             r4, r3, #240
> +       vld1.8          {d0-d1}, [r4, : 128]!
> +       vld1.8          {d2-d3}, [r4, : 128]!
> +       vld1.8          {d4}, [r4, : 64]
> +       add             r4, r3, #336
> +       vld1.8          {d6-d7}, [r4, : 128]!
> +       vtrn.32         q0, q3
> +       vld1.8          {d8-d9}, [r4, : 128]!
> +       vshl.i32        q5, q0, #4
> +       vtrn.32         q1, q4
> +       vshl.i32        q6, q3, #4
> +       vadd.i32        q5, q5, q0
> +       vadd.i32        q6, q6, q3
> +       vshl.i32        q7, q1, #4
> +       vld1.8          {d5}, [r4, : 64]
> +       vshl.i32        q8, q4, #4
> +       vtrn.32         d4, d5
> +       vadd.i32        q7, q7, q1
> +       vadd.i32        q8, q8, q4
> +       vld1.8          {d18-d19}, [r2, : 128]!
> +       vshl.i32        q10, q2, #4
> +       vld1.8          {d22-d23}, [r2, : 128]!
> +       vadd.i32        q10, q10, q2
> +       vld1.8          {d24}, [r2, : 64]
> +       vadd.i32        q5, q5, q0
> +       add             r2, r3, #288
> +       vld1.8          {d26-d27}, [r2, : 128]!
> +       vadd.i32        q6, q6, q3
> +       vld1.8          {d28-d29}, [r2, : 128]!
> +       vadd.i32        q8, q8, q4
> +       vld1.8          {d25}, [r2, : 64]
> +       vadd.i32        q10, q10, q2
> +       vtrn.32         q9, q13
> +       vadd.i32        q7, q7, q1
> +       vadd.i32        q5, q5, q0
> +       vtrn.32         q11, q14
> +       vadd.i32        q6, q6, q3
> +       add             r2, sp, #528
> +       vadd.i32        q10, q10, q2
> +       vtrn.32         d24, d25
> +       vst1.8          {d12-d13}, [r2, : 128]
> +       vshl.i32        q6, q13, #1
> +       add             r2, sp, #544
> +       vst1.8          {d20-d21}, [r2, : 128]
> +       vshl.i32        q10, q14, #1
> +       add             r2, sp, #560
> +       vst1.8          {d12-d13}, [r2, : 128]
> +       vshl.i32        q15, q12, #1
> +       vadd.i32        q8, q8, q4
> +       vext.32         d10, d31, d30, #0
> +       vadd.i32        q7, q7, q1
> +       add             r2, sp, #576
> +       vst1.8          {d16-d17}, [r2, : 128]
> +       vmull.s32       q8, d18, d5
> +       vmlal.s32       q8, d26, d4
> +       vmlal.s32       q8, d19, d9
> +       vmlal.s32       q8, d27, d3
> +       vmlal.s32       q8, d22, d8
> +       vmlal.s32       q8, d28, d2
> +       vmlal.s32       q8, d23, d7
> +       vmlal.s32       q8, d29, d1
> +       vmlal.s32       q8, d24, d6
> +       vmlal.s32       q8, d25, d0
> +       add             r2, sp, #592
> +       vst1.8          {d14-d15}, [r2, : 128]
> +       vmull.s32       q2, d18, d4
> +       vmlal.s32       q2, d12, d9
> +       vmlal.s32       q2, d13, d8
> +       vmlal.s32       q2, d19, d3
> +       vmlal.s32       q2, d22, d2
> +       vmlal.s32       q2, d23, d1
> +       vmlal.s32       q2, d24, d0
> +       add             r2, sp, #608
> +       vst1.8          {d20-d21}, [r2, : 128]
> +       vmull.s32       q7, d18, d9
> +       vmlal.s32       q7, d26, d3
> +       vmlal.s32       q7, d19, d8
> +       vmlal.s32       q7, d27, d2
> +       vmlal.s32       q7, d22, d7
> +       vmlal.s32       q7, d28, d1
> +       vmlal.s32       q7, d23, d6
> +       vmlal.s32       q7, d29, d0
> +       add             r2, sp, #624
> +       vst1.8          {d10-d11}, [r2, : 128]
> +       vmull.s32       q5, d18, d3
> +       vmlal.s32       q5, d19, d2
> +       vmlal.s32       q5, d22, d1
> +       vmlal.s32       q5, d23, d0
> +       vmlal.s32       q5, d12, d8
> +       add             r2, sp, #640
> +       vst1.8          {d16-d17}, [r2, : 128]
> +       vmull.s32       q4, d18, d8
> +       vmlal.s32       q4, d26, d2
> +       vmlal.s32       q4, d19, d7
> +       vmlal.s32       q4, d27, d1
> +       vmlal.s32       q4, d22, d6
> +       vmlal.s32       q4, d28, d0
> +       vmull.s32       q8, d18, d7
> +       vmlal.s32       q8, d26, d1
> +       vmlal.s32       q8, d19, d6
> +       vmlal.s32       q8, d27, d0
> +       add             r2, sp, #544
> +       vld1.8          {d20-d21}, [r2, : 128]
> +       vmlal.s32       q7, d24, d21
> +       vmlal.s32       q7, d25, d20
> +       vmlal.s32       q4, d23, d21
> +       vmlal.s32       q4, d29, d20
> +       vmlal.s32       q8, d22, d21
> +       vmlal.s32       q8, d28, d20
> +       vmlal.s32       q5, d24, d20
> +       add             r2, sp, #544
> +       vst1.8          {d14-d15}, [r2, : 128]
> +       vmull.s32       q7, d18, d6
> +       vmlal.s32       q7, d26, d0
> +       add             r2, sp, #624
> +       vld1.8          {d30-d31}, [r2, : 128]
> +       vmlal.s32       q2, d30, d21
> +       vmlal.s32       q7, d19, d21
> +       vmlal.s32       q7, d27, d20
> +       add             r2, sp, #592
> +       vld1.8          {d26-d27}, [r2, : 128]
> +       vmlal.s32       q4, d25, d27
> +       vmlal.s32       q8, d29, d27
> +       vmlal.s32       q8, d25, d26
> +       vmlal.s32       q7, d28, d27
> +       vmlal.s32       q7, d29, d26
> +       add             r2, sp, #576
> +       vld1.8          {d28-d29}, [r2, : 128]
> +       vmlal.s32       q4, d24, d29
> +       vmlal.s32       q8, d23, d29
> +       vmlal.s32       q8, d24, d28
> +       vmlal.s32       q7, d22, d29
> +       vmlal.s32       q7, d23, d28
> +       add             r2, sp, #576
> +       vst1.8          {d8-d9}, [r2, : 128]
> +       add             r2, sp, #528
> +       vld1.8          {d8-d9}, [r2, : 128]
> +       vmlal.s32       q7, d24, d9
> +       vmlal.s32       q7, d25, d31
> +       vmull.s32       q1, d18, d2
> +       vmlal.s32       q1, d19, d1
> +       vmlal.s32       q1, d22, d0
> +       vmlal.s32       q1, d24, d27
> +       vmlal.s32       q1, d23, d20
> +       vmlal.s32       q1, d12, d7
> +       vmlal.s32       q1, d13, d6
> +       vmull.s32       q6, d18, d1
> +       vmlal.s32       q6, d19, d0
> +       vmlal.s32       q6, d23, d27
> +       vmlal.s32       q6, d22, d20
> +       vmlal.s32       q6, d24, d26
> +       vmull.s32       q0, d18, d0
> +       vmlal.s32       q0, d22, d27
> +       vmlal.s32       q0, d23, d26
> +       vmlal.s32       q0, d24, d31
> +       vmlal.s32       q0, d19, d20
> +       add             r2, sp, #608
> +       vld1.8          {d18-d19}, [r2, : 128]
> +       vmlal.s32       q2, d18, d7
> +       vmlal.s32       q2, d19, d6
> +       vmlal.s32       q5, d18, d6
> +       vmlal.s32       q5, d19, d21
> +       vmlal.s32       q1, d18, d21
> +       vmlal.s32       q1, d19, d29
> +       vmlal.s32       q0, d18, d28
> +       vmlal.s32       q0, d19, d9
> +       vmlal.s32       q6, d18, d29
> +       vmlal.s32       q6, d19, d28
> +       add             r2, sp, #560
> +       vld1.8          {d18-d19}, [r2, : 128]
> +       add             r2, sp, #480
> +       vld1.8          {d22-d23}, [r2, : 128]
> +       vmlal.s32       q5, d19, d7
> +       vmlal.s32       q0, d18, d21
> +       vmlal.s32       q0, d19, d29
> +       vmlal.s32       q6, d18, d6
> +       add             r2, sp, #496
> +       vld1.8          {d6-d7}, [r2, : 128]
> +       vmlal.s32       q6, d19, d21
> +       add             r2, sp, #544
> +       vld1.8          {d18-d19}, [r2, : 128]
> +       vmlal.s32       q0, d30, d8
> +       add             r2, sp, #640
> +       vld1.8          {d20-d21}, [r2, : 128]
> +       vmlal.s32       q5, d30, d29
> +       add             r2, sp, #576
> +       vld1.8          {d24-d25}, [r2, : 128]
> +       vmlal.s32       q1, d30, d28
> +       vadd.i64        q13, q0, q11
> +       vadd.i64        q14, q5, q11
> +       vmlal.s32       q6, d30, d9
> +       vshr.s64        q4, q13, #26
> +       vshr.s64        q13, q14, #26
> +       vadd.i64        q7, q7, q4
> +       vshl.i64        q4, q4, #26
> +       vadd.i64        q14, q7, q3
> +       vadd.i64        q9, q9, q13
> +       vshl.i64        q13, q13, #26
> +       vadd.i64        q15, q9, q3
> +       vsub.i64        q0, q0, q4
> +       vshr.s64        q4, q14, #25
> +       vsub.i64        q5, q5, q13
> +       vshr.s64        q13, q15, #25
> +       vadd.i64        q6, q6, q4
> +       vshl.i64        q4, q4, #25
> +       vadd.i64        q14, q6, q11
> +       vadd.i64        q2, q2, q13
> +       vsub.i64        q4, q7, q4
> +       vshr.s64        q7, q14, #26
> +       vshl.i64        q13, q13, #25
> +       vadd.i64        q14, q2, q11
> +       vadd.i64        q8, q8, q7
> +       vshl.i64        q7, q7, #26
> +       vadd.i64        q15, q8, q3
> +       vsub.i64        q9, q9, q13
> +       vshr.s64        q13, q14, #26
> +       vsub.i64        q6, q6, q7
> +       vshr.s64        q7, q15, #25
> +       vadd.i64        q10, q10, q13
> +       vshl.i64        q13, q13, #26
> +       vadd.i64        q14, q10, q3
> +       vadd.i64        q1, q1, q7
> +       add             r2, r3, #288
> +       vshl.i64        q7, q7, #25
> +       add             r4, r3, #96
> +       vadd.i64        q15, q1, q11
> +       add             r2, r2, #8
> +       vsub.i64        q2, q2, q13
> +       add             r4, r4, #8
> +       vshr.s64        q13, q14, #25
> +       vsub.i64        q7, q8, q7
> +       vshr.s64        q8, q15, #26
> +       vadd.i64        q14, q13, q13
> +       vadd.i64        q12, q12, q8
> +       vtrn.32         d12, d14
> +       vshl.i64        q8, q8, #26
> +       vtrn.32         d13, d15
> +       vadd.i64        q3, q12, q3
> +       vadd.i64        q0, q0, q14
> +       vst1.8          d12, [r2, : 64]!
> +       vshl.i64        q7, q13, #4
> +       vst1.8          d13, [r4, : 64]!
> +       vsub.i64        q1, q1, q8
> +       vshr.s64        q3, q3, #25
> +       vadd.i64        q0, q0, q7
> +       vadd.i64        q5, q5, q3
> +       vshl.i64        q3, q3, #25
> +       vadd.i64        q6, q5, q11
> +       vadd.i64        q0, q0, q13
> +       vshl.i64        q7, q13, #25
> +       vadd.i64        q8, q0, q11
> +       vsub.i64        q3, q12, q3
> +       vshr.s64        q6, q6, #26
> +       vsub.i64        q7, q10, q7
> +       vtrn.32         d2, d6
> +       vshr.s64        q8, q8, #26
> +       vtrn.32         d3, d7
> +       vadd.i64        q3, q9, q6
> +       vst1.8          d2, [r2, : 64]
> +       vshl.i64        q6, q6, #26
> +       vst1.8          d3, [r4, : 64]
> +       vadd.i64        q1, q4, q8
> +       vtrn.32         d4, d14
> +       vshl.i64        q4, q8, #26
> +       vtrn.32         d5, d15
> +       vsub.i64        q5, q5, q6
> +       add             r2, r2, #16
> +       vsub.i64        q0, q0, q4
> +       vst1.8          d4, [r2, : 64]
> +       add             r4, r4, #16
> +       vst1.8          d5, [r4, : 64]
> +       vtrn.32         d10, d6
> +       vtrn.32         d11, d7
> +       sub             r2, r2, #8
> +       sub             r4, r4, #8
> +       vtrn.32         d0, d2
> +       vtrn.32         d1, d3
> +       vst1.8          d10, [r2, : 64]
> +       vst1.8          d11, [r4, : 64]
> +       sub             r2, r2, #24
> +       sub             r4, r4, #24
> +       vst1.8          d0, [r2, : 64]
> +       vst1.8          d1, [r4, : 64]
> +       add             r2, sp, #512
> +       add             r4, r3, #144
> +       add             r5, r3, #192
> +       vld1.8          {d0-d1}, [r2, : 128]
> +       vld1.8          {d2-d3}, [r4, : 128]!
> +       vld1.8          {d4-d5}, [r5, : 128]!
> +       vzip.i32        q1, q2
> +       vld1.8          {d6-d7}, [r4, : 128]!
> +       vld1.8          {d8-d9}, [r5, : 128]!
> +       vshl.i32        q5, q1, #1
> +       vzip.i32        q3, q4
> +       vshl.i32        q6, q2, #1
> +       vld1.8          {d14}, [r4, : 64]
> +       vshl.i32        q8, q3, #1
> +       vld1.8          {d15}, [r5, : 64]
> +       vshl.i32        q9, q4, #1
> +       vmul.i32        d21, d7, d1
> +       vtrn.32         d14, d15
> +       vmul.i32        q11, q4, q0
> +       vmul.i32        q0, q7, q0
> +       vmull.s32       q12, d2, d2
> +       vmlal.s32       q12, d11, d1
> +       vmlal.s32       q12, d12, d0
> +       vmlal.s32       q12, d13, d23
> +       vmlal.s32       q12, d16, d22
> +       vmlal.s32       q12, d7, d21
> +       vmull.s32       q10, d2, d11
> +       vmlal.s32       q10, d4, d1
> +       vmlal.s32       q10, d13, d0
> +       vmlal.s32       q10, d6, d23
> +       vmlal.s32       q10, d17, d22
> +       vmull.s32       q13, d10, d4
> +       vmlal.s32       q13, d11, d3
> +       vmlal.s32       q13, d13, d1
> +       vmlal.s32       q13, d16, d0
> +       vmlal.s32       q13, d17, d23
> +       vmlal.s32       q13, d8, d22
> +       vmull.s32       q1, d10, d5
> +       vmlal.s32       q1, d11, d4
> +       vmlal.s32       q1, d6, d1
> +       vmlal.s32       q1, d17, d0
> +       vmlal.s32       q1, d8, d23
> +       vmull.s32       q14, d10, d6
> +       vmlal.s32       q14, d11, d13
> +       vmlal.s32       q14, d4, d4
> +       vmlal.s32       q14, d17, d1
> +       vmlal.s32       q14, d18, d0
> +       vmlal.s32       q14, d9, d23
> +       vmull.s32       q11, d10, d7
> +       vmlal.s32       q11, d11, d6
> +       vmlal.s32       q11, d12, d5
> +       vmlal.s32       q11, d8, d1
> +       vmlal.s32       q11, d19, d0
> +       vmull.s32       q15, d10, d8
> +       vmlal.s32       q15, d11, d17
> +       vmlal.s32       q15, d12, d6
> +       vmlal.s32       q15, d13, d5
> +       vmlal.s32       q15, d19, d1
> +       vmlal.s32       q15, d14, d0
> +       vmull.s32       q2, d10, d9
> +       vmlal.s32       q2, d11, d8
> +       vmlal.s32       q2, d12, d7
> +       vmlal.s32       q2, d13, d6
> +       vmlal.s32       q2, d14, d1
> +       vmull.s32       q0, d15, d1
> +       vmlal.s32       q0, d10, d14
> +       vmlal.s32       q0, d11, d19
> +       vmlal.s32       q0, d12, d8
> +       vmlal.s32       q0, d13, d17
> +       vmlal.s32       q0, d6, d6
> +       add             r2, sp, #480
> +       vld1.8          {d18-d19}, [r2, : 128]
> +       vmull.s32       q3, d16, d7
> +       vmlal.s32       q3, d10, d15
> +       vmlal.s32       q3, d11, d14
> +       vmlal.s32       q3, d12, d9
> +       vmlal.s32       q3, d13, d8
> +       add             r2, sp, #496
> +       vld1.8          {d8-d9}, [r2, : 128]
> +       vadd.i64        q5, q12, q9
> +       vadd.i64        q6, q15, q9
> +       vshr.s64        q5, q5, #26
> +       vshr.s64        q6, q6, #26
> +       vadd.i64        q7, q10, q5
> +       vshl.i64        q5, q5, #26
> +       vadd.i64        q8, q7, q4
> +       vadd.i64        q2, q2, q6
> +       vshl.i64        q6, q6, #26
> +       vadd.i64        q10, q2, q4
> +       vsub.i64        q5, q12, q5
> +       vshr.s64        q8, q8, #25
> +       vsub.i64        q6, q15, q6
> +       vshr.s64        q10, q10, #25
> +       vadd.i64        q12, q13, q8
> +       vshl.i64        q8, q8, #25
> +       vadd.i64        q13, q12, q9
> +       vadd.i64        q0, q0, q10
> +       vsub.i64        q7, q7, q8
> +       vshr.s64        q8, q13, #26
> +       vshl.i64        q10, q10, #25
> +       vadd.i64        q13, q0, q9
> +       vadd.i64        q1, q1, q8
> +       vshl.i64        q8, q8, #26
> +       vadd.i64        q15, q1, q4
> +       vsub.i64        q2, q2, q10
> +       vshr.s64        q10, q13, #26
> +       vsub.i64        q8, q12, q8
> +       vshr.s64        q12, q15, #25
> +       vadd.i64        q3, q3, q10
> +       vshl.i64        q10, q10, #26
> +       vadd.i64        q13, q3, q4
> +       vadd.i64        q14, q14, q12
> +       add             r2, r3, #144
> +       vshl.i64        q12, q12, #25
> +       add             r4, r3, #192
> +       vadd.i64        q15, q14, q9
> +       add             r2, r2, #8
> +       vsub.i64        q0, q0, q10
> +       add             r4, r4, #8
> +       vshr.s64        q10, q13, #25
> +       vsub.i64        q1, q1, q12
> +       vshr.s64        q12, q15, #26
> +       vadd.i64        q13, q10, q10
> +       vadd.i64        q11, q11, q12
> +       vtrn.32         d16, d2
> +       vshl.i64        q12, q12, #26
> +       vtrn.32         d17, d3
> +       vadd.i64        q1, q11, q4
> +       vadd.i64        q4, q5, q13
> +       vst1.8          d16, [r2, : 64]!
> +       vshl.i64        q5, q10, #4
> +       vst1.8          d17, [r4, : 64]!
> +       vsub.i64        q8, q14, q12
> +       vshr.s64        q1, q1, #25
> +       vadd.i64        q4, q4, q5
> +       vadd.i64        q5, q6, q1
> +       vshl.i64        q1, q1, #25
> +       vadd.i64        q6, q5, q9
> +       vadd.i64        q4, q4, q10
> +       vshl.i64        q10, q10, #25
> +       vadd.i64        q9, q4, q9
> +       vsub.i64        q1, q11, q1
> +       vshr.s64        q6, q6, #26
> +       vsub.i64        q3, q3, q10
> +       vtrn.32         d16, d2
> +       vshr.s64        q9, q9, #26
> +       vtrn.32         d17, d3
> +       vadd.i64        q1, q2, q6
> +       vst1.8          d16, [r2, : 64]
> +       vshl.i64        q2, q6, #26
> +       vst1.8          d17, [r4, : 64]
> +       vadd.i64        q6, q7, q9
> +       vtrn.32         d0, d6
> +       vshl.i64        q7, q9, #26
> +       vtrn.32         d1, d7
> +       vsub.i64        q2, q5, q2
> +       add             r2, r2, #16
> +       vsub.i64        q3, q4, q7
> +       vst1.8          d0, [r2, : 64]
> +       add             r4, r4, #16
> +       vst1.8          d1, [r4, : 64]
> +       vtrn.32         d4, d2
> +       vtrn.32         d5, d3
> +       sub             r2, r2, #8
> +       sub             r4, r4, #8
> +       vtrn.32         d6, d12
> +       vtrn.32         d7, d13
> +       vst1.8          d4, [r2, : 64]
> +       vst1.8          d5, [r4, : 64]
> +       sub             r2, r2, #24
> +       sub             r4, r4, #24
> +       vst1.8          d6, [r2, : 64]
> +       vst1.8          d7, [r4, : 64]
> +       add             r2, r3, #336
> +       add             r4, r3, #288
> +       vld1.8          {d0-d1}, [r2, : 128]!
> +       vld1.8          {d2-d3}, [r4, : 128]!
> +       vadd.i32        q0, q0, q1
> +       vld1.8          {d2-d3}, [r2, : 128]!
> +       vld1.8          {d4-d5}, [r4, : 128]!
> +       vadd.i32        q1, q1, q2
> +       add             r5, r3, #288
> +       vld1.8          {d4}, [r2, : 64]
> +       vld1.8          {d6}, [r4, : 64]
> +       vadd.i32        q2, q2, q3
> +       vst1.8          {d0-d1}, [r5, : 128]!
> +       vst1.8          {d2-d3}, [r5, : 128]!
> +       vst1.8          d4, [r5, : 64]
> +       add             r2, r3, #48
> +       add             r4, r3, #144
> +       vld1.8          {d0-d1}, [r4, : 128]!
> +       vld1.8          {d2-d3}, [r4, : 128]!
> +       vld1.8          {d4}, [r4, : 64]
> +       add             r4, r3, #288
> +       vld1.8          {d6-d7}, [r4, : 128]!
> +       vtrn.32         q0, q3
> +       vld1.8          {d8-d9}, [r4, : 128]!
> +       vshl.i32        q5, q0, #4
> +       vtrn.32         q1, q4
> +       vshl.i32        q6, q3, #4
> +       vadd.i32        q5, q5, q0
> +       vadd.i32        q6, q6, q3
> +       vshl.i32        q7, q1, #4
> +       vld1.8          {d5}, [r4, : 64]
> +       vshl.i32        q8, q4, #4
> +       vtrn.32         d4, d5
> +       vadd.i32        q7, q7, q1
> +       vadd.i32        q8, q8, q4
> +       vld1.8          {d18-d19}, [r2, : 128]!
> +       vshl.i32        q10, q2, #4
> +       vld1.8          {d22-d23}, [r2, : 128]!
> +       vadd.i32        q10, q10, q2
> +       vld1.8          {d24}, [r2, : 64]
> +       vadd.i32        q5, q5, q0
> +       add             r2, r3, #240
> +       vld1.8          {d26-d27}, [r2, : 128]!
> +       vadd.i32        q6, q6, q3
> +       vld1.8          {d28-d29}, [r2, : 128]!
> +       vadd.i32        q8, q8, q4
> +       vld1.8          {d25}, [r2, : 64]
> +       vadd.i32        q10, q10, q2
> +       vtrn.32         q9, q13
> +       vadd.i32        q7, q7, q1
> +       vadd.i32        q5, q5, q0
> +       vtrn.32         q11, q14
> +       vadd.i32        q6, q6, q3
> +       add             r2, sp, #528
> +       vadd.i32        q10, q10, q2
> +       vtrn.32         d24, d25
> +       vst1.8          {d12-d13}, [r2, : 128]
> +       vshl.i32        q6, q13, #1
> +       add             r2, sp, #544
> +       vst1.8          {d20-d21}, [r2, : 128]
> +       vshl.i32        q10, q14, #1
> +       add             r2, sp, #560
> +       vst1.8          {d12-d13}, [r2, : 128]
> +       vshl.i32        q15, q12, #1
> +       vadd.i32        q8, q8, q4
> +       vext.32         d10, d31, d30, #0
> +       vadd.i32        q7, q7, q1
> +       add             r2, sp, #576
> +       vst1.8          {d16-d17}, [r2, : 128]
> +       vmull.s32       q8, d18, d5
> +       vmlal.s32       q8, d26, d4
> +       vmlal.s32       q8, d19, d9
> +       vmlal.s32       q8, d27, d3
> +       vmlal.s32       q8, d22, d8
> +       vmlal.s32       q8, d28, d2
> +       vmlal.s32       q8, d23, d7
> +       vmlal.s32       q8, d29, d1
> +       vmlal.s32       q8, d24, d6
> +       vmlal.s32       q8, d25, d0
> +       add             r2, sp, #592
> +       vst1.8          {d14-d15}, [r2, : 128]
> +       vmull.s32       q2, d18, d4
> +       vmlal.s32       q2, d12, d9
> +       vmlal.s32       q2, d13, d8
> +       vmlal.s32       q2, d19, d3
> +       vmlal.s32       q2, d22, d2
> +       vmlal.s32       q2, d23, d1
> +       vmlal.s32       q2, d24, d0
> +       add             r2, sp, #608
> +       vst1.8          {d20-d21}, [r2, : 128]
> +       vmull.s32       q7, d18, d9
> +       vmlal.s32       q7, d26, d3
> +       vmlal.s32       q7, d19, d8
> +       vmlal.s32       q7, d27, d2
> +       vmlal.s32       q7, d22, d7
> +       vmlal.s32       q7, d28, d1
> +       vmlal.s32       q7, d23, d6
> +       vmlal.s32       q7, d29, d0
> +       add             r2, sp, #624
> +       vst1.8          {d10-d11}, [r2, : 128]
> +       vmull.s32       q5, d18, d3
> +       vmlal.s32       q5, d19, d2
> +       vmlal.s32       q5, d22, d1
> +       vmlal.s32       q5, d23, d0
> +       vmlal.s32       q5, d12, d8
> +       add             r2, sp, #640
> +       vst1.8          {d16-d17}, [r2, : 128]
> +       vmull.s32       q4, d18, d8
> +       vmlal.s32       q4, d26, d2
> +       vmlal.s32       q4, d19, d7
> +       vmlal.s32       q4, d27, d1
> +       vmlal.s32       q4, d22, d6
> +       vmlal.s32       q4, d28, d0
> +       vmull.s32       q8, d18, d7
> +       vmlal.s32       q8, d26, d1
> +       vmlal.s32       q8, d19, d6
> +       vmlal.s32       q8, d27, d0
> +       add             r2, sp, #544
> +       vld1.8          {d20-d21}, [r2, : 128]
> +       vmlal.s32       q7, d24, d21
> +       vmlal.s32       q7, d25, d20
> +       vmlal.s32       q4, d23, d21
> +       vmlal.s32       q4, d29, d20
> +       vmlal.s32       q8, d22, d21
> +       vmlal.s32       q8, d28, d20
> +       vmlal.s32       q5, d24, d20
> +       add             r2, sp, #544
> +       vst1.8          {d14-d15}, [r2, : 128]
> +       vmull.s32       q7, d18, d6
> +       vmlal.s32       q7, d26, d0
> +       add             r2, sp, #624
> +       vld1.8          {d30-d31}, [r2, : 128]
> +       vmlal.s32       q2, d30, d21
> +       vmlal.s32       q7, d19, d21
> +       vmlal.s32       q7, d27, d20
> +       add             r2, sp, #592
> +       vld1.8          {d26-d27}, [r2, : 128]
> +       vmlal.s32       q4, d25, d27
> +       vmlal.s32       q8, d29, d27
> +       vmlal.s32       q8, d25, d26
> +       vmlal.s32       q7, d28, d27
> +       vmlal.s32       q7, d29, d26
> +       add             r2, sp, #576
> +       vld1.8          {d28-d29}, [r2, : 128]
> +       vmlal.s32       q4, d24, d29
> +       vmlal.s32       q8, d23, d29
> +       vmlal.s32       q8, d24, d28
> +       vmlal.s32       q7, d22, d29
> +       vmlal.s32       q7, d23, d28
> +       add             r2, sp, #576
> +       vst1.8          {d8-d9}, [r2, : 128]
> +       add             r2, sp, #528
> +       vld1.8          {d8-d9}, [r2, : 128]
> +       vmlal.s32       q7, d24, d9
> +       vmlal.s32       q7, d25, d31
> +       vmull.s32       q1, d18, d2
> +       vmlal.s32       q1, d19, d1
> +       vmlal.s32       q1, d22, d0
> +       vmlal.s32       q1, d24, d27
> +       vmlal.s32       q1, d23, d20
> +       vmlal.s32       q1, d12, d7
> +       vmlal.s32       q1, d13, d6
> +       vmull.s32       q6, d18, d1
> +       vmlal.s32       q6, d19, d0
> +       vmlal.s32       q6, d23, d27
> +       vmlal.s32       q6, d22, d20
> +       vmlal.s32       q6, d24, d26
> +       vmull.s32       q0, d18, d0
> +       vmlal.s32       q0, d22, d27
> +       vmlal.s32       q0, d23, d26
> +       vmlal.s32       q0, d24, d31
> +       vmlal.s32       q0, d19, d20
> +       add             r2, sp, #608
> +       vld1.8          {d18-d19}, [r2, : 128]
> +       vmlal.s32       q2, d18, d7
> +       vmlal.s32       q2, d19, d6
> +       vmlal.s32       q5, d18, d6
> +       vmlal.s32       q5, d19, d21
> +       vmlal.s32       q1, d18, d21
> +       vmlal.s32       q1, d19, d29
> +       vmlal.s32       q0, d18, d28
> +       vmlal.s32       q0, d19, d9
> +       vmlal.s32       q6, d18, d29
> +       vmlal.s32       q6, d19, d28
> +       add             r2, sp, #560
> +       vld1.8          {d18-d19}, [r2, : 128]
> +       add             r2, sp, #480
> +       vld1.8          {d22-d23}, [r2, : 128]
> +       vmlal.s32       q5, d19, d7
> +       vmlal.s32       q0, d18, d21
> +       vmlal.s32       q0, d19, d29
> +       vmlal.s32       q6, d18, d6
> +       add             r2, sp, #496
> +       vld1.8          {d6-d7}, [r2, : 128]
> +       vmlal.s32       q6, d19, d21
> +       add             r2, sp, #544
> +       vld1.8          {d18-d19}, [r2, : 128]
> +       vmlal.s32       q0, d30, d8
> +       add             r2, sp, #640
> +       vld1.8          {d20-d21}, [r2, : 128]
> +       vmlal.s32       q5, d30, d29
> +       add             r2, sp, #576
> +       vld1.8          {d24-d25}, [r2, : 128]
> +       vmlal.s32       q1, d30, d28
> +       vadd.i64        q13, q0, q11
> +       vadd.i64        q14, q5, q11
> +       vmlal.s32       q6, d30, d9
> +       vshr.s64        q4, q13, #26
> +       vshr.s64        q13, q14, #26
> +       vadd.i64        q7, q7, q4
> +       vshl.i64        q4, q4, #26
> +       vadd.i64        q14, q7, q3
> +       vadd.i64        q9, q9, q13
> +       vshl.i64        q13, q13, #26
> +       vadd.i64        q15, q9, q3
> +       vsub.i64        q0, q0, q4
> +       vshr.s64        q4, q14, #25
> +       vsub.i64        q5, q5, q13
> +       vshr.s64        q13, q15, #25
> +       vadd.i64        q6, q6, q4
> +       vshl.i64        q4, q4, #25
> +       vadd.i64        q14, q6, q11
> +       vadd.i64        q2, q2, q13
> +       vsub.i64        q4, q7, q4
> +       vshr.s64        q7, q14, #26
> +       vshl.i64        q13, q13, #25
> +       vadd.i64        q14, q2, q11
> +       vadd.i64        q8, q8, q7
> +       vshl.i64        q7, q7, #26
> +       vadd.i64        q15, q8, q3
> +       vsub.i64        q9, q9, q13
> +       vshr.s64        q13, q14, #26
> +       vsub.i64        q6, q6, q7
> +       vshr.s64        q7, q15, #25
> +       vadd.i64        q10, q10, q13
> +       vshl.i64        q13, q13, #26
> +       vadd.i64        q14, q10, q3
> +       vadd.i64        q1, q1, q7
> +       add             r2, r3, #240
> +       vshl.i64        q7, q7, #25
> +       add             r4, r3, #144
> +       vadd.i64        q15, q1, q11
> +       add             r2, r2, #8
> +       vsub.i64        q2, q2, q13
> +       add             r4, r4, #8
> +       vshr.s64        q13, q14, #25
> +       vsub.i64        q7, q8, q7
> +       vshr.s64        q8, q15, #26
> +       vadd.i64        q14, q13, q13
> +       vadd.i64        q12, q12, q8
> +       vtrn.32         d12, d14
> +       vshl.i64        q8, q8, #26
> +       vtrn.32         d13, d15
> +       vadd.i64        q3, q12, q3
> +       vadd.i64        q0, q0, q14
> +       vst1.8          d12, [r2, : 64]!
> +       vshl.i64        q7, q13, #4
> +       vst1.8          d13, [r4, : 64]!
> +       vsub.i64        q1, q1, q8
> +       vshr.s64        q3, q3, #25
> +       vadd.i64        q0, q0, q7
> +       vadd.i64        q5, q5, q3
> +       vshl.i64        q3, q3, #25
> +       vadd.i64        q6, q5, q11
> +       vadd.i64        q0, q0, q13
> +       vshl.i64        q7, q13, #25
> +       vadd.i64        q8, q0, q11
> +       vsub.i64        q3, q12, q3
> +       vshr.s64        q6, q6, #26
> +       vsub.i64        q7, q10, q7
> +       vtrn.32         d2, d6
> +       vshr.s64        q8, q8, #26
> +       vtrn.32         d3, d7
> +       vadd.i64        q3, q9, q6
> +       vst1.8          d2, [r2, : 64]
> +       vshl.i64        q6, q6, #26
> +       vst1.8          d3, [r4, : 64]
> +       vadd.i64        q1, q4, q8
> +       vtrn.32         d4, d14
> +       vshl.i64        q4, q8, #26
> +       vtrn.32         d5, d15
> +       vsub.i64        q5, q5, q6
> +       add             r2, r2, #16
> +       vsub.i64        q0, q0, q4
> +       vst1.8          d4, [r2, : 64]
> +       add             r4, r4, #16
> +       vst1.8          d5, [r4, : 64]
> +       vtrn.32         d10, d6
> +       vtrn.32         d11, d7
> +       sub             r2, r2, #8
> +       sub             r4, r4, #8
> +       vtrn.32         d0, d2
> +       vtrn.32         d1, d3
> +       vst1.8          d10, [r2, : 64]
> +       vst1.8          d11, [r4, : 64]
> +       sub             r2, r2, #24
> +       sub             r4, r4, #24
> +       vst1.8          d0, [r2, : 64]
> +       vst1.8          d1, [r4, : 64]
> +       ldr             r2, [sp, #456]
> +       ldr             r4, [sp, #460]
> +       subs            r5, r2, #1
> +       bge             .Lmainloop
> +       add             r1, r3, #144
> +       add             r2, r3, #336
> +       vld1.8          {d0-d1}, [r1, : 128]!
> +       vld1.8          {d2-d3}, [r1, : 128]!
> +       vld1.8          {d4}, [r1, : 64]
> +       vst1.8          {d0-d1}, [r2, : 128]!
> +       vst1.8          {d2-d3}, [r2, : 128]!
> +       vst1.8          d4, [r2, : 64]
> +       movw            r1, #0
> +.Linvertloop:
> +       add             r2, r3, #144
> +       movw            r4, #0
> +       movw            r5, #2
> +       cmp             r1, #1
> +       moveq           r5, #1
> +       addeq           r2, r3, #336
> +       addeq           r4, r3, #48
> +       cmp             r1, #2
> +       moveq           r5, #1
> +       addeq           r2, r3, #48
> +       cmp             r1, #3
> +       moveq           r5, #5
> +       addeq           r4, r3, #336
> +       cmp             r1, #4
> +       moveq           r5, #10
> +       cmp             r1, #5
> +       moveq           r5, #20
> +       cmp             r1, #6
> +       moveq           r5, #10
> +       addeq           r2, r3, #336
> +       addeq           r4, r3, #336
> +       cmp             r1, #7
> +       moveq           r5, #50
> +       cmp             r1, #8
> +       moveq           r5, #100
> +       cmp             r1, #9
> +       moveq           r5, #50
> +       addeq           r2, r3, #336
> +       cmp             r1, #10
> +       moveq           r5, #5
> +       addeq           r2, r3, #48
> +       cmp             r1, #11
> +       moveq           r5, #0
> +       addeq           r2, r3, #96
> +       add             r6, r3, #144
> +       add             r7, r3, #288
> +       vld1.8          {d0-d1}, [r6, : 128]!
> +       vld1.8          {d2-d3}, [r6, : 128]!
> +       vld1.8          {d4}, [r6, : 64]
> +       vst1.8          {d0-d1}, [r7, : 128]!
> +       vst1.8          {d2-d3}, [r7, : 128]!
> +       vst1.8          d4, [r7, : 64]
> +       cmp             r5, #0
> +       beq             .Lskipsquaringloop
> +.Lsquaringloop:
> +       add             r6, r3, #288
> +       add             r7, r3, #288
> +       add             r8, r3, #288
> +       vmov.i32        q0, #19
> +       vmov.i32        q1, #0
> +       vmov.i32        q2, #1
> +       vzip.i32        q1, q2
> +       vld1.8          {d4-d5}, [r7, : 128]!
> +       vld1.8          {d6-d7}, [r7, : 128]!
> +       vld1.8          {d9}, [r7, : 64]
> +       vld1.8          {d10-d11}, [r6, : 128]!
> +       add             r7, sp, #384
> +       vld1.8          {d12-d13}, [r6, : 128]!
> +       vmul.i32        q7, q2, q0
> +       vld1.8          {d8}, [r6, : 64]
> +       vext.32         d17, d11, d10, #1
> +       vmul.i32        q9, q3, q0
> +       vext.32         d16, d10, d8, #1
> +       vshl.u32        q10, q5, q1
> +       vext.32         d22, d14, d4, #1
> +       vext.32         d24, d18, d6, #1
> +       vshl.u32        q13, q6, q1
> +       vshl.u32        d28, d8, d2
> +       vrev64.i32      d22, d22
> +       vmul.i32        d1, d9, d1
> +       vrev64.i32      d24, d24
> +       vext.32         d29, d8, d13, #1
> +       vext.32         d0, d1, d9, #1
> +       vrev64.i32      d0, d0
> +       vext.32         d2, d9, d1, #1
> +       vext.32         d23, d15, d5, #1
> +       vmull.s32       q4, d20, d4
> +       vrev64.i32      d23, d23
> +       vmlal.s32       q4, d21, d1
> +       vrev64.i32      d2, d2
> +       vmlal.s32       q4, d26, d19
> +       vext.32         d3, d5, d15, #1
> +       vmlal.s32       q4, d27, d18
> +       vrev64.i32      d3, d3
> +       vmlal.s32       q4, d28, d15
> +       vext.32         d14, d12, d11, #1
> +       vmull.s32       q5, d16, d23
> +       vext.32         d15, d13, d12, #1
> +       vmlal.s32       q5, d17, d4
> +       vst1.8          d8, [r7, : 64]!
> +       vmlal.s32       q5, d14, d1
> +       vext.32         d12, d9, d8, #0
> +       vmlal.s32       q5, d15, d19
> +       vmov.i64        d13, #0
> +       vmlal.s32       q5, d29, d18
> +       vext.32         d25, d19, d7, #1
> +       vmlal.s32       q6, d20, d5
> +       vrev64.i32      d25, d25
> +       vmlal.s32       q6, d21, d4
> +       vst1.8          d11, [r7, : 64]!
> +       vmlal.s32       q6, d26, d1
> +       vext.32         d9, d10, d10, #0
> +       vmlal.s32       q6, d27, d19
> +       vmov.i64        d8, #0
> +       vmlal.s32       q6, d28, d18
> +       vmlal.s32       q4, d16, d24
> +       vmlal.s32       q4, d17, d5
> +       vmlal.s32       q4, d14, d4
> +       vst1.8          d12, [r7, : 64]!
> +       vmlal.s32       q4, d15, d1
> +       vext.32         d10, d13, d12, #0
> +       vmlal.s32       q4, d29, d19
> +       vmov.i64        d11, #0
> +       vmlal.s32       q5, d20, d6
> +       vmlal.s32       q5, d21, d5
> +       vmlal.s32       q5, d26, d4
> +       vext.32         d13, d8, d8, #0
> +       vmlal.s32       q5, d27, d1
> +       vmov.i64        d12, #0
> +       vmlal.s32       q5, d28, d19
> +       vst1.8          d9, [r7, : 64]!
> +       vmlal.s32       q6, d16, d25
> +       vmlal.s32       q6, d17, d6
> +       vst1.8          d10, [r7, : 64]
> +       vmlal.s32       q6, d14, d5
> +       vext.32         d8, d11, d10, #0
> +       vmlal.s32       q6, d15, d4
> +       vmov.i64        d9, #0
> +       vmlal.s32       q6, d29, d1
> +       vmlal.s32       q4, d20, d7
> +       vmlal.s32       q4, d21, d6
> +       vmlal.s32       q4, d26, d5
> +       vext.32         d11, d12, d12, #0
> +       vmlal.s32       q4, d27, d4
> +       vmov.i64        d10, #0
> +       vmlal.s32       q4, d28, d1
> +       vmlal.s32       q5, d16, d0
> +       sub             r6, r7, #32
> +       vmlal.s32       q5, d17, d7
> +       vmlal.s32       q5, d14, d6
> +       vext.32         d30, d9, d8, #0
> +       vmlal.s32       q5, d15, d5
> +       vld1.8          {d31}, [r6, : 64]!
> +       vmlal.s32       q5, d29, d4
> +       vmlal.s32       q15, d20, d0
> +       vext.32         d0, d6, d18, #1
> +       vmlal.s32       q15, d21, d25
> +       vrev64.i32      d0, d0
> +       vmlal.s32       q15, d26, d24
> +       vext.32         d1, d7, d19, #1
> +       vext.32         d7, d10, d10, #0
> +       vmlal.s32       q15, d27, d23
> +       vrev64.i32      d1, d1
> +       vld1.8          {d6}, [r6, : 64]
> +       vmlal.s32       q15, d28, d22
> +       vmlal.s32       q3, d16, d4
> +       add             r6, r6, #24
> +       vmlal.s32       q3, d17, d2
> +       vext.32         d4, d31, d30, #0
> +       vmov            d17, d11
> +       vmlal.s32       q3, d14, d1
> +       vext.32         d11, d13, d13, #0
> +       vext.32         d13, d30, d30, #0
> +       vmlal.s32       q3, d15, d0
> +       vext.32         d1, d8, d8, #0
> +       vmlal.s32       q3, d29, d3
> +       vld1.8          {d5}, [r6, : 64]
> +       sub             r6, r6, #16
> +       vext.32         d10, d6, d6, #0
> +       vmov.i32        q1, #0xffffffff
> +       vshl.i64        q4, q1, #25
> +       add             r7, sp, #480
> +       vld1.8          {d14-d15}, [r7, : 128]
> +       vadd.i64        q9, q2, q7
> +       vshl.i64        q1, q1, #26
> +       vshr.s64        q10, q9, #26
> +       vld1.8          {d0}, [r6, : 64]!
> +       vadd.i64        q5, q5, q10
> +       vand            q9, q9, q1
> +       vld1.8          {d16}, [r6, : 64]!
> +       add             r6, sp, #496
> +       vld1.8          {d20-d21}, [r6, : 128]
> +       vadd.i64        q11, q5, q10
> +       vsub.i64        q2, q2, q9
> +       vshr.s64        q9, q11, #25
> +       vext.32         d12, d5, d4, #0
> +       vand            q11, q11, q4
> +       vadd.i64        q0, q0, q9
> +       vmov            d19, d7
> +       vadd.i64        q3, q0, q7
> +       vsub.i64        q5, q5, q11
> +       vshr.s64        q11, q3, #26
> +       vext.32         d18, d11, d10, #0
> +       vand            q3, q3, q1
> +       vadd.i64        q8, q8, q11
> +       vadd.i64        q11, q8, q10
> +       vsub.i64        q0, q0, q3
> +       vshr.s64        q3, q11, #25
> +       vand            q11, q11, q4
> +       vadd.i64        q3, q6, q3
> +       vadd.i64        q6, q3, q7
> +       vsub.i64        q8, q8, q11
> +       vshr.s64        q11, q6, #26
> +       vand            q6, q6, q1
> +       vadd.i64        q9, q9, q11
> +       vadd.i64        d25, d19, d21
> +       vsub.i64        q3, q3, q6
> +       vshr.s64        d23, d25, #25
> +       vand            q4, q12, q4
> +       vadd.i64        d21, d23, d23
> +       vshl.i64        d25, d23, #4
> +       vadd.i64        d21, d21, d23
> +       vadd.i64        d25, d25, d21
> +       vadd.i64        d4, d4, d25
> +       vzip.i32        q0, q8
> +       vadd.i64        d12, d4, d14
> +       add             r6, r8, #8
> +       vst1.8          d0, [r6, : 64]
> +       vsub.i64        d19, d19, d9
> +       add             r6, r6, #16
> +       vst1.8          d16, [r6, : 64]
> +       vshr.s64        d22, d12, #26
> +       vand            q0, q6, q1
> +       vadd.i64        d10, d10, d22
> +       vzip.i32        q3, q9
> +       vsub.i64        d4, d4, d0
> +       sub             r6, r6, #8
> +       vst1.8          d6, [r6, : 64]
> +       add             r6, r6, #16
> +       vst1.8          d18, [r6, : 64]
> +       vzip.i32        q2, q5
> +       sub             r6, r6, #32
> +       vst1.8          d4, [r6, : 64]
> +       subs            r5, r5, #1
> +       bhi             .Lsquaringloop
> +.Lskipsquaringloop:
> +       mov             r2, r2
> +       add             r5, r3, #288
> +       add             r6, r3, #144
> +       vmov.i32        q0, #19
> +       vmov.i32        q1, #0
> +       vmov.i32        q2, #1
> +       vzip.i32        q1, q2
> +       vld1.8          {d4-d5}, [r5, : 128]!
> +       vld1.8          {d6-d7}, [r5, : 128]!
> +       vld1.8          {d9}, [r5, : 64]
> +       vld1.8          {d10-d11}, [r2, : 128]!
> +       add             r5, sp, #384
> +       vld1.8          {d12-d13}, [r2, : 128]!
> +       vmul.i32        q7, q2, q0
> +       vld1.8          {d8}, [r2, : 64]
> +       vext.32         d17, d11, d10, #1
> +       vmul.i32        q9, q3, q0
> +       vext.32         d16, d10, d8, #1
> +       vshl.u32        q10, q5, q1
> +       vext.32         d22, d14, d4, #1
> +       vext.32         d24, d18, d6, #1
> +       vshl.u32        q13, q6, q1
> +       vshl.u32        d28, d8, d2
> +       vrev64.i32      d22, d22
> +       vmul.i32        d1, d9, d1
> +       vrev64.i32      d24, d24
> +       vext.32         d29, d8, d13, #1
> +       vext.32         d0, d1, d9, #1
> +       vrev64.i32      d0, d0
> +       vext.32         d2, d9, d1, #1
> +       vext.32         d23, d15, d5, #1
> +       vmull.s32       q4, d20, d4
> +       vrev64.i32      d23, d23
> +       vmlal.s32       q4, d21, d1
> +       vrev64.i32      d2, d2
> +       vmlal.s32       q4, d26, d19
> +       vext.32         d3, d5, d15, #1
> +       vmlal.s32       q4, d27, d18
> +       vrev64.i32      d3, d3
> +       vmlal.s32       q4, d28, d15
> +       vext.32         d14, d12, d11, #1
> +       vmull.s32       q5, d16, d23
> +       vext.32         d15, d13, d12, #1
> +       vmlal.s32       q5, d17, d4
> +       vst1.8          d8, [r5, : 64]!
> +       vmlal.s32       q5, d14, d1
> +       vext.32         d12, d9, d8, #0
> +       vmlal.s32       q5, d15, d19
> +       vmov.i64        d13, #0
> +       vmlal.s32       q5, d29, d18
> +       vext.32         d25, d19, d7, #1
> +       vmlal.s32       q6, d20, d5
> +       vrev64.i32      d25, d25
> +       vmlal.s32       q6, d21, d4
> +       vst1.8          d11, [r5, : 64]!
> +       vmlal.s32       q6, d26, d1
> +       vext.32         d9, d10, d10, #0
> +       vmlal.s32       q6, d27, d19
> +       vmov.i64        d8, #0
> +       vmlal.s32       q6, d28, d18
> +       vmlal.s32       q4, d16, d24
> +       vmlal.s32       q4, d17, d5
> +       vmlal.s32       q4, d14, d4
> +       vst1.8          d12, [r5, : 64]!
> +       vmlal.s32       q4, d15, d1
> +       vext.32         d10, d13, d12, #0
> +       vmlal.s32       q4, d29, d19
> +       vmov.i64        d11, #0
> +       vmlal.s32       q5, d20, d6
> +       vmlal.s32       q5, d21, d5
> +       vmlal.s32       q5, d26, d4
> +       vext.32         d13, d8, d8, #0
> +       vmlal.s32       q5, d27, d1
> +       vmov.i64        d12, #0
> +       vmlal.s32       q5, d28, d19
> +       vst1.8          d9, [r5, : 64]!
> +       vmlal.s32       q6, d16, d25
> +       vmlal.s32       q6, d17, d6
> +       vst1.8          d10, [r5, : 64]
> +       vmlal.s32       q6, d14, d5
> +       vext.32         d8, d11, d10, #0
> +       vmlal.s32       q6, d15, d4
> +       vmov.i64        d9, #0
> +       vmlal.s32       q6, d29, d1
> +       vmlal.s32       q4, d20, d7
> +       vmlal.s32       q4, d21, d6
> +       vmlal.s32       q4, d26, d5
> +       vext.32         d11, d12, d12, #0
> +       vmlal.s32       q4, d27, d4
> +       vmov.i64        d10, #0
> +       vmlal.s32       q4, d28, d1
> +       vmlal.s32       q5, d16, d0
> +       sub             r2, r5, #32
> +       vmlal.s32       q5, d17, d7
> +       vmlal.s32       q5, d14, d6
> +       vext.32         d30, d9, d8, #0
> +       vmlal.s32       q5, d15, d5
> +       vld1.8          {d31}, [r2, : 64]!
> +       vmlal.s32       q5, d29, d4
> +       vmlal.s32       q15, d20, d0
> +       vext.32         d0, d6, d18, #1
> +       vmlal.s32       q15, d21, d25
> +       vrev64.i32      d0, d0
> +       vmlal.s32       q15, d26, d24
> +       vext.32         d1, d7, d19, #1
> +       vext.32         d7, d10, d10, #0
> +       vmlal.s32       q15, d27, d23
> +       vrev64.i32      d1, d1
> +       vld1.8          {d6}, [r2, : 64]
> +       vmlal.s32       q15, d28, d22
> +       vmlal.s32       q3, d16, d4
> +       add             r2, r2, #24
> +       vmlal.s32       q3, d17, d2
> +       vext.32         d4, d31, d30, #0
> +       vmov            d17, d11
> +       vmlal.s32       q3, d14, d1
> +       vext.32         d11, d13, d13, #0
> +       vext.32         d13, d30, d30, #0
> +       vmlal.s32       q3, d15, d0
> +       vext.32         d1, d8, d8, #0
> +       vmlal.s32       q3, d29, d3
> +       vld1.8          {d5}, [r2, : 64]
> +       sub             r2, r2, #16
> +       vext.32         d10, d6, d6, #0
> +       vmov.i32        q1, #0xffffffff
> +       vshl.i64        q4, q1, #25
> +       add             r5, sp, #480
> +       vld1.8          {d14-d15}, [r5, : 128]
> +       vadd.i64        q9, q2, q7
> +       vshl.i64        q1, q1, #26
> +       vshr.s64        q10, q9, #26
> +       vld1.8          {d0}, [r2, : 64]!
> +       vadd.i64        q5, q5, q10
> +       vand            q9, q9, q1
> +       vld1.8          {d16}, [r2, : 64]!
> +       add             r2, sp, #496
> +       vld1.8          {d20-d21}, [r2, : 128]
> +       vadd.i64        q11, q5, q10
> +       vsub.i64        q2, q2, q9
> +       vshr.s64        q9, q11, #25
> +       vext.32         d12, d5, d4, #0
> +       vand            q11, q11, q4
> +       vadd.i64        q0, q0, q9
> +       vmov            d19, d7
> +       vadd.i64        q3, q0, q7
> +       vsub.i64        q5, q5, q11
> +       vshr.s64        q11, q3, #26
> +       vext.32         d18, d11, d10, #0
> +       vand            q3, q3, q1
> +       vadd.i64        q8, q8, q11
> +       vadd.i64        q11, q8, q10
> +       vsub.i64        q0, q0, q3
> +       vshr.s64        q3, q11, #25
> +       vand            q11, q11, q4
> +       vadd.i64        q3, q6, q3
> +       vadd.i64        q6, q3, q7
> +       vsub.i64        q8, q8, q11
> +       vshr.s64        q11, q6, #26
> +       vand            q6, q6, q1
> +       vadd.i64        q9, q9, q11
> +       vadd.i64        d25, d19, d21
> +       vsub.i64        q3, q3, q6
> +       vshr.s64        d23, d25, #25
> +       vand            q4, q12, q4
> +       vadd.i64        d21, d23, d23
> +       vshl.i64        d25, d23, #4
> +       vadd.i64        d21, d21, d23
> +       vadd.i64        d25, d25, d21
> +       vadd.i64        d4, d4, d25
> +       vzip.i32        q0, q8
> +       vadd.i64        d12, d4, d14
> +       add             r2, r6, #8
> +       vst1.8          d0, [r2, : 64]
> +       vsub.i64        d19, d19, d9
> +       add             r2, r2, #16
> +       vst1.8          d16, [r2, : 64]
> +       vshr.s64        d22, d12, #26
> +       vand            q0, q6, q1
> +       vadd.i64        d10, d10, d22
> +       vzip.i32        q3, q9
> +       vsub.i64        d4, d4, d0
> +       sub             r2, r2, #8
> +       vst1.8          d6, [r2, : 64]
> +       add             r2, r2, #16
> +       vst1.8          d18, [r2, : 64]
> +       vzip.i32        q2, q5
> +       sub             r2, r2, #32
> +       vst1.8          d4, [r2, : 64]
> +       cmp             r4, #0
> +       beq             .Lskippostcopy
> +       add             r2, r3, #144
> +       mov             r4, r4
> +       vld1.8          {d0-d1}, [r2, : 128]!
> +       vld1.8          {d2-d3}, [r2, : 128]!
> +       vld1.8          {d4}, [r2, : 64]
> +       vst1.8          {d0-d1}, [r4, : 128]!
> +       vst1.8          {d2-d3}, [r4, : 128]!
> +       vst1.8          d4, [r4, : 64]
> +.Lskippostcopy:
> +       cmp             r1, #1
> +       bne             .Lskipfinalcopy
> +       add             r2, r3, #288
> +       add             r4, r3, #144
> +       vld1.8          {d0-d1}, [r2, : 128]!
> +       vld1.8          {d2-d3}, [r2, : 128]!
> +       vld1.8          {d4}, [r2, : 64]
> +       vst1.8          {d0-d1}, [r4, : 128]!
> +       vst1.8          {d2-d3}, [r4, : 128]!
> +       vst1.8          d4, [r4, : 64]
> +.Lskipfinalcopy:
> +       add             r1, r1, #1
> +       cmp             r1, #12
> +       blo             .Linvertloop
> +       add             r1, r3, #144
> +       ldr             r2, [r1], #4
> +       ldr             r3, [r1], #4
> +       ldr             r4, [r1], #4
> +       ldr             r5, [r1], #4
> +       ldr             r6, [r1], #4
> +       ldr             r7, [r1], #4
> +       ldr             r8, [r1], #4
> +       ldr             r9, [r1], #4
> +       ldr             r10, [r1], #4
> +       ldr             r1, [r1]
> +       add             r11, r1, r1, LSL #4
> +       add             r11, r11, r1, LSL #1
> +       add             r11, r11, #16777216
> +       mov             r11, r11, ASR #25
> +       add             r11, r11, r2
> +       mov             r11, r11, ASR #26
> +       add             r11, r11, r3
> +       mov             r11, r11, ASR #25
> +       add             r11, r11, r4
> +       mov             r11, r11, ASR #26
> +       add             r11, r11, r5
> +       mov             r11, r11, ASR #25
> +       add             r11, r11, r6
> +       mov             r11, r11, ASR #26
> +       add             r11, r11, r7
> +       mov             r11, r11, ASR #25
> +       add             r11, r11, r8
> +       mov             r11, r11, ASR #26
> +       add             r11, r11, r9
> +       mov             r11, r11, ASR #25
> +       add             r11, r11, r10
> +       mov             r11, r11, ASR #26
> +       add             r11, r11, r1
> +       mov             r11, r11, ASR #25
> +       add             r2, r2, r11
> +       add             r2, r2, r11, LSL #1
> +       add             r2, r2, r11, LSL #4
> +       mov             r11, r2, ASR #26
> +       add             r3, r3, r11
> +       sub             r2, r2, r11, LSL #26
> +       mov             r11, r3, ASR #25
> +       add             r4, r4, r11
> +       sub             r3, r3, r11, LSL #25
> +       mov             r11, r4, ASR #26
> +       add             r5, r5, r11
> +       sub             r4, r4, r11, LSL #26
> +       mov             r11, r5, ASR #25
> +       add             r6, r6, r11
> +       sub             r5, r5, r11, LSL #25
> +       mov             r11, r6, ASR #26
> +       add             r7, r7, r11
> +       sub             r6, r6, r11, LSL #26
> +       mov             r11, r7, ASR #25
> +       add             r8, r8, r11
> +       sub             r7, r7, r11, LSL #25
> +       mov             r11, r8, ASR #26
> +       add             r9, r9, r11
> +       sub             r8, r8, r11, LSL #26
> +       mov             r11, r9, ASR #25
> +       add             r10, r10, r11
> +       sub             r9, r9, r11, LSL #25
> +       mov             r11, r10, ASR #26
> +       add             r1, r1, r11
> +       sub             r10, r10, r11, LSL #26
> +       mov             r11, r1, ASR #25
> +       sub             r1, r1, r11, LSL #25
> +       add             r2, r2, r3, LSL #26
> +       mov             r3, r3, LSR #6
> +       add             r3, r3, r4, LSL #19
> +       mov             r4, r4, LSR #13
> +       add             r4, r4, r5, LSL #13
> +       mov             r5, r5, LSR #19
> +       add             r5, r5, r6, LSL #6
> +       add             r6, r7, r8, LSL #25
> +       mov             r7, r8, LSR #7
> +       add             r7, r7, r9, LSL #19
> +       mov             r8, r9, LSR #13
> +       add             r8, r8, r10, LSL #12
> +       mov             r9, r10, LSR #20
> +       add             r1, r9, r1, LSL #6
> +       str             r2, [r0]
> +       str             r3, [r0, #4]
> +       str             r4, [r0, #8]
> +       str             r5, [r0, #12]
> +       str             r6, [r0, #16]
> +       str             r7, [r0, #20]
> +       str             r8, [r0, #24]
> +       str             r1, [r0, #28]
> +       movw            r0, #0
> +       mov             sp, ip
> +       pop             {r4-r11, pc}
> +ENDPROC(curve25519_neon)
> +#endif
> diff --git a/lib/zinc/curve25519/curve25519.c b/lib/zinc/curve25519/curve25519.c
> index 32536340d39d..0d5ea97762d4 100644
> --- a/lib/zinc/curve25519/curve25519.c
> +++ b/lib/zinc/curve25519/curve25519.c
> @@ -21,6 +21,8 @@
>
>  #if defined(CONFIG_ZINC_ARCH_X86_64)
>  #include "curve25519-x86_64-glue.h"
> +#elif defined(CONFIG_ZINC_ARCH_ARM)
> +#include "curve25519-arm-glue.h"
>  #else
>  void __init curve25519_fpu_init(void)
>  {
> --
> 2.19.0
>
Richard Weinberger Oct. 2, 2018, 9:35 p.m. UTC | #2
Ard,

On Tue, Oct 2, 2018 at 7:06 PM Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> I guess qhasm means generated code, right?

Yes.
Please see: http://cr.yp.to/qhasm.html

It generates code from a q-file (the "template").
Actually it is a rather powerful tool, but as you noticed, sometimes
the code is not perfect.
Jason A. Donenfeld Oct. 3, 2018, 1:03 a.m. UTC | #3
(+Dan,Peter in CC. Replying to:
<https://lore.kernel.org/lkml/CAKv+Gu9FLDRLxHReKcveZYHNYerR5Y2pZd9gn-hWrU0jb2KgfA@mail.gmail.com/>
for context.)

Hi Ard,

On Tue, Oct 2, 2018 at 6:59 PM Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> Shouldn't this use the new simd abstraction as well?

Yes, it probably should, thanks.

> I guess qhasm means generated code, right?
> Because many of these adds are completely redundant ...
> This looks odd as well.
> Could you elaborate on what qhasm is exactly? And, as with the other
> patches, I would prefer it if we could have your changes as a separate
> patch (although having the qhasm base would be preferred)

Indeed qhasm converts this --
<https://github.com/floodyberry/supercop/blob/master/crypto_scalarmult/curve25519/neon2/scalarmult.pq>
-- into this. It's a thing from Dan (CC'd now) --
<http://cr.yp.to/qhasm.html>. As you've requested, I can layer the
patches to show our changes on top.

> ... you can drop this add
> same here
> and here
> and here
> and here
> and here
> and here
> and here
> redundant add
> I'll stop here - let me just note that this code does not strike me as
> particularly well optimized for in-order cores (such as A7).
> For instance, the sequence
> can be reordered as
> and not have every other instruction depend on the output of the previous one.
> Obviously, the ultimate truth is in the benchmark numbers, but I'd
> thought I'd mention it anyway.

Yes indeed the output is suboptimal in a lot of places. We can
gradually clean this up -- slowly and carefully over time -- if you
want. I can also look into producing a new implementation within HACL*
so that it's verified. Assurance-wise, though, I feel pretty good
about this implementation considering its origins, its breadth of use
(in BoringSSL), the fuzzing hours it's incurred, and the actual
implementation itself.

 Either way, performance-wise, it's really worth having.

For example, on a Cortex-A7, we get these results (according to get_cycles()):

neon: 23142 cycles per call
fiat32: 49136 cycles per call
donna32: 71988 cycles per call

And on a Cortex-A9, we get these results (according to get_cycles()):

neon: 5020 cycles per call
fiat32: 17326 cycles per call
donna32: 28076 cycles per call

Jason
Jason A. Donenfeld Oct. 3, 2018, 3:10 a.m. UTC | #4
On Tue, Oct 2, 2018 at 6:59 PM Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> Could you elaborate on what qhasm is exactly? And, as with the other
> patches, I would prefer it if we could have your changes as a separate
> patch (although having the qhasm base would be preferred)

By the way, as of a few minutes ago, if you look in the development
tree at the commit called "zinc: Curve25519 ARM implementation", that
now shows the diffs to the original, as you requested. I'll probably
obsess over that a little bit more before v7, but if you see anything
gnarly there beforehand, I'd be happy to hear.

Jason
D. J. Bernstein Oct. 5, 2018, 3:05 p.m. UTC | #5
For the in-order ARM Cortex-A8 (the target for this code), adjacent
multiply-add instructions forward summands quickly. A simple in-order
dot-product computation has no latency problems, while interleaving
computations, as suggested in this thread, creates problems. Also, on
this microarchitecture, occasional ARM instructions run in parallel with
NEON, so trying to manually eliminate ARM instructions through global
pointer tracking wouldn't gain speed; it would simply create unnecessary
code-maintenance problems.

See https://cr.yp.to/papers.html#neoncrypto for analysis of the
performance of---and remaining bottlenecks in---this code. Further
speedups should be possible on this microarchitecture, but, for anyone
interested in this, I recommend focusing on building a cycle-accurate
simulator (e.g., fixing inaccuracies in the Sobole simulator) first.

Of course, there are other ARM microarchitectures, and there are many
cases where different microarchitectures prefer different optimizations.
The kernel already has boot-time benchmarks for different optimizations
for raid6, and should do the same for crypto code, so that implementors
can focus on each microarchitecture separately rather than living in the
barbaric world of having to choose which CPUs to favor.

---Dan
Ard Biesheuvel Oct. 5, 2018, 3:16 p.m. UTC | #6
On 5 October 2018 at 17:05, D. J. Bernstein <djb@cr.yp.to> wrote:
> For the in-order ARM Cortex-A8 (the target for this code), adjacent
> multiply-add instructions forward summands quickly. A simple in-order
> dot-product computation has no latency problems, while interleaving
> computations, as suggested in this thread, creates problems. Also, on
> this microarchitecture, occasional ARM instructions run in parallel with
> NEON, so trying to manually eliminate ARM instructions through global
> pointer tracking wouldn't gain speed; it would simply create unnecessary
> code-maintenance problems.
>
> See https://cr.yp.to/papers.html#neoncrypto for analysis of the
> performance of---and remaining bottlenecks in---this code. Further
> speedups should be possible on this microarchitecture, but, for anyone
> interested in this, I recommend focusing on building a cycle-accurate
> simulator (e.g., fixing inaccuracies in the Sobole simulator) first.
>
> Of course, there are other ARM microarchitectures, and there are many
> cases where different microarchitectures prefer different optimizations.
> The kernel already has boot-time benchmarks for different optimizations
> for raid6, and should do the same for crypto code, so that implementors
> can focus on each microarchitecture separately rather than living in the
> barbaric world of having to choose which CPUs to favor.
>

Thanks Dan for the insight.

We have already established in a separate discussion that Cortex-A7,
which is main optimization target for future development, does not
have the microarchitectural peculiarity that you are referring to that
ARM instructions are essentially free when interleaved with NEON code.

But I take your point re benchmarking (as I already indicated in my
reply to Jason): if we optimize towards speed, we should ideally reuse
the existing benchmarking infrastructure we have to select the fastest
implementation at runtime. For instance, it turns out that scalar
ChaCha20 is almost as fast as NEON (or even faster?) on A7, and using
NEON in the kernel has some issues of its own.
Jason A. Donenfeld Oct. 5, 2018, 6:40 p.m. UTC | #7
Hey Dan,

On Fri, Oct 05, 2018 at 03:05:38PM -0000, D. J. Bernstein wrote:
> Of course, there are other ARM microarchitectures, and there are many
> cases where different microarchitectures prefer different optimizations.
> The kernel already has boot-time benchmarks for different optimizations
> for raid6, and should do the same for crypto code, so that implementors
> can focus on each microarchitecture separately rather than living in the
> barbaric world of having to choose which CPUs to favor.

I've been playing a bit with some code to do this sort of thing,
choosing a set of implementations to enable or disable by trying all the
combinations, and then calculating a quick median. I don't know if I'll
submit that for the initial merge of this patchset -- and in fact all
the current implementations I'm proposing are pretty much okay on
microarchitectures -- but down the line this could be useful as a
mechanism.

Jason
diff mbox series

Patch

diff --git a/lib/zinc/Makefile b/lib/zinc/Makefile
index 65440438c6e5..be73c342f9ba 100644
--- a/lib/zinc/Makefile
+++ b/lib/zinc/Makefile
@@ -27,4 +27,5 @@  zinc_blake2s-$(CONFIG_ZINC_ARCH_X86_64) += blake2s/blake2s-x86_64.o
 obj-$(CONFIG_ZINC_BLAKE2S) += zinc_blake2s.o
 
 zinc_curve25519-y := curve25519/curve25519.o
+zinc_curve25519-$(CONFIG_ZINC_ARCH_ARM) += curve25519/curve25519-arm.o
 obj-$(CONFIG_ZINC_CURVE25519) += zinc_curve25519.o
diff --git a/lib/zinc/curve25519/curve25519-arm-glue.h b/lib/zinc/curve25519/curve25519-arm-glue.h
new file mode 100644
index 000000000000..9211bcab5615
--- /dev/null
+++ b/lib/zinc/curve25519/curve25519-arm-glue.h
@@ -0,0 +1,42 @@ 
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ */
+
+#include <asm/hwcap.h>
+#include <asm/neon.h>
+#include <asm/simd.h>
+
+#if defined(CONFIG_KERNEL_MODE_NEON)
+asmlinkage void curve25519_neon(u8 mypublic[CURVE25519_KEY_SIZE],
+				const u8 secret[CURVE25519_KEY_SIZE],
+				const u8 basepoint[CURVE25519_KEY_SIZE]);
+#endif
+
+static bool curve25519_use_neon __ro_after_init;
+
+static void __init curve25519_fpu_init(void)
+{
+	curve25519_use_neon = elf_hwcap & HWCAP_NEON;
+}
+
+static inline bool curve25519_arch(u8 mypublic[CURVE25519_KEY_SIZE],
+				   const u8 secret[CURVE25519_KEY_SIZE],
+				   const u8 basepoint[CURVE25519_KEY_SIZE])
+{
+#if defined(CONFIG_KERNEL_MODE_NEON)
+	if (curve25519_use_neon && may_use_simd()) {
+		kernel_neon_begin();
+		curve25519_neon(mypublic, secret, basepoint);
+		kernel_neon_end();
+		return true;
+	}
+#endif
+	return false;
+}
+
+static inline bool curve25519_base_arch(u8 pub[CURVE25519_KEY_SIZE],
+					const u8 secret[CURVE25519_KEY_SIZE])
+{
+	return false;
+}
diff --git a/lib/zinc/curve25519/curve25519-arm.S b/lib/zinc/curve25519/curve25519-arm.S
new file mode 100644
index 000000000000..db6570c20fd1
--- /dev/null
+++ b/lib/zinc/curve25519/curve25519-arm.S
@@ -0,0 +1,2095 @@ 
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/*
+ * Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ *
+ * Based on public domain code from Daniel J. Bernstein and Peter Schwabe. This
+ * has been built from SUPERCOP's curve25519/neon2/scalarmult.pq using qhasm,
+ * but has subsequently been manually reworked for use in kernel space.
+ */
+
+#ifdef CONFIG_KERNEL_MODE_NEON
+#include <linux/linkage.h>
+
+.text
+.fpu neon
+.arch armv7-a
+.align 4
+
+ENTRY(curve25519_neon)
+	push		{r4-r11, lr}
+	mov		ip, sp
+	sub		r3, sp, #704
+	and		r3, r3, #0xfffffff0
+	mov		sp, r3
+	movw		r4, #0
+	movw		r5, #254
+	vmov.i32	q0, #1
+	vshr.u64	q1, q0, #7
+	vshr.u64	q0, q0, #8
+	vmov.i32	d4, #19
+	vmov.i32	d5, #38
+	add		r6, sp, #480
+	vst1.8		{d2-d3}, [r6, : 128]
+	add		r6, sp, #496
+	vst1.8		{d0-d1}, [r6, : 128]
+	add		r6, sp, #512
+	vst1.8		{d4-d5}, [r6, : 128]
+	add		r6, r3, #0
+	vmov.i32	q2, #0
+	vst1.8		{d4-d5}, [r6, : 128]!
+	vst1.8		{d4-d5}, [r6, : 128]!
+	vst1.8		d4, [r6, : 64]
+	add		r6, r3, #0
+	movw		r7, #960
+	sub		r7, r7, #2
+	neg		r7, r7
+	sub		r7, r7, r7, LSL #7
+	str		r7, [r6]
+	add		r6, sp, #672
+	vld1.8		{d4-d5}, [r1]!
+	vld1.8		{d6-d7}, [r1]
+	vst1.8		{d4-d5}, [r6, : 128]!
+	vst1.8		{d6-d7}, [r6, : 128]
+	sub		r1, r6, #16
+	ldrb		r6, [r1]
+	and		r6, r6, #248
+	strb		r6, [r1]
+	ldrb		r6, [r1, #31]
+	and		r6, r6, #127
+	orr		r6, r6, #64
+	strb		r6, [r1, #31]
+	vmov.i64	q2, #0xffffffff
+	vshr.u64	q3, q2, #7
+	vshr.u64	q2, q2, #6
+	vld1.8		{d8}, [r2]
+	vld1.8		{d10}, [r2]
+	add		r2, r2, #6
+	vld1.8		{d12}, [r2]
+	vld1.8		{d14}, [r2]
+	add		r2, r2, #6
+	vld1.8		{d16}, [r2]
+	add		r2, r2, #4
+	vld1.8		{d18}, [r2]
+	vld1.8		{d20}, [r2]
+	add		r2, r2, #6
+	vld1.8		{d22}, [r2]
+	add		r2, r2, #2
+	vld1.8		{d24}, [r2]
+	vld1.8		{d26}, [r2]
+	vshr.u64	q5, q5, #26
+	vshr.u64	q6, q6, #3
+	vshr.u64	q7, q7, #29
+	vshr.u64	q8, q8, #6
+	vshr.u64	q10, q10, #25
+	vshr.u64	q11, q11, #3
+	vshr.u64	q12, q12, #12
+	vshr.u64	q13, q13, #38
+	vand		q4, q4, q2
+	vand		q6, q6, q2
+	vand		q8, q8, q2
+	vand		q10, q10, q2
+	vand		q2, q12, q2
+	vand		q5, q5, q3
+	vand		q7, q7, q3
+	vand		q9, q9, q3
+	vand		q11, q11, q3
+	vand		q3, q13, q3
+	add		r2, r3, #48
+	vadd.i64	q12, q4, q1
+	vadd.i64	q13, q10, q1
+	vshr.s64	q12, q12, #26
+	vshr.s64	q13, q13, #26
+	vadd.i64	q5, q5, q12
+	vshl.i64	q12, q12, #26
+	vadd.i64	q14, q5, q0
+	vadd.i64	q11, q11, q13
+	vshl.i64	q13, q13, #26
+	vadd.i64	q15, q11, q0
+	vsub.i64	q4, q4, q12
+	vshr.s64	q12, q14, #25
+	vsub.i64	q10, q10, q13
+	vshr.s64	q13, q15, #25
+	vadd.i64	q6, q6, q12
+	vshl.i64	q12, q12, #25
+	vadd.i64	q14, q6, q1
+	vadd.i64	q2, q2, q13
+	vsub.i64	q5, q5, q12
+	vshr.s64	q12, q14, #26
+	vshl.i64	q13, q13, #25
+	vadd.i64	q14, q2, q1
+	vadd.i64	q7, q7, q12
+	vshl.i64	q12, q12, #26
+	vadd.i64	q15, q7, q0
+	vsub.i64	q11, q11, q13
+	vshr.s64	q13, q14, #26
+	vsub.i64	q6, q6, q12
+	vshr.s64	q12, q15, #25
+	vadd.i64	q3, q3, q13
+	vshl.i64	q13, q13, #26
+	vadd.i64	q14, q3, q0
+	vadd.i64	q8, q8, q12
+	vshl.i64	q12, q12, #25
+	vadd.i64	q15, q8, q1
+	add		r2, r2, #8
+	vsub.i64	q2, q2, q13
+	vshr.s64	q13, q14, #25
+	vsub.i64	q7, q7, q12
+	vshr.s64	q12, q15, #26
+	vadd.i64	q14, q13, q13
+	vadd.i64	q9, q9, q12
+	vtrn.32		d12, d14
+	vshl.i64	q12, q12, #26
+	vtrn.32		d13, d15
+	vadd.i64	q0, q9, q0
+	vadd.i64	q4, q4, q14
+	vst1.8		d12, [r2, : 64]!
+	vshl.i64	q6, q13, #4
+	vsub.i64	q7, q8, q12
+	vshr.s64	q0, q0, #25
+	vadd.i64	q4, q4, q6
+	vadd.i64	q6, q10, q0
+	vshl.i64	q0, q0, #25
+	vadd.i64	q8, q6, q1
+	vadd.i64	q4, q4, q13
+	vshl.i64	q10, q13, #25
+	vadd.i64	q1, q4, q1
+	vsub.i64	q0, q9, q0
+	vshr.s64	q8, q8, #26
+	vsub.i64	q3, q3, q10
+	vtrn.32		d14, d0
+	vshr.s64	q1, q1, #26
+	vtrn.32		d15, d1
+	vadd.i64	q0, q11, q8
+	vst1.8		d14, [r2, : 64]
+	vshl.i64	q7, q8, #26
+	vadd.i64	q5, q5, q1
+	vtrn.32		d4, d6
+	vshl.i64	q1, q1, #26
+	vtrn.32		d5, d7
+	vsub.i64	q3, q6, q7
+	add		r2, r2, #16
+	vsub.i64	q1, q4, q1
+	vst1.8		d4, [r2, : 64]
+	vtrn.32		d6, d0
+	vtrn.32		d7, d1
+	sub		r2, r2, #8
+	vtrn.32		d2, d10
+	vtrn.32		d3, d11
+	vst1.8		d6, [r2, : 64]
+	sub		r2, r2, #24
+	vst1.8		d2, [r2, : 64]
+	add		r2, r3, #96
+	vmov.i32	q0, #0
+	vmov.i64	d2, #0xff
+	vmov.i64	d3, #0
+	vshr.u32	q1, q1, #7
+	vst1.8		{d2-d3}, [r2, : 128]!
+	vst1.8		{d0-d1}, [r2, : 128]!
+	vst1.8		d0, [r2, : 64]
+	add		r2, r3, #144
+	vmov.i32	q0, #0
+	vst1.8		{d0-d1}, [r2, : 128]!
+	vst1.8		{d0-d1}, [r2, : 128]!
+	vst1.8		d0, [r2, : 64]
+	add		r2, r3, #240
+	vmov.i32	q0, #0
+	vmov.i64	d2, #0xff
+	vmov.i64	d3, #0
+	vshr.u32	q1, q1, #7
+	vst1.8		{d2-d3}, [r2, : 128]!
+	vst1.8		{d0-d1}, [r2, : 128]!
+	vst1.8		d0, [r2, : 64]
+	add		r2, r3, #48
+	add		r6, r3, #192
+	vld1.8		{d0-d1}, [r2, : 128]!
+	vld1.8		{d2-d3}, [r2, : 128]!
+	vld1.8		{d4}, [r2, : 64]
+	vst1.8		{d0-d1}, [r6, : 128]!
+	vst1.8		{d2-d3}, [r6, : 128]!
+	vst1.8		d4, [r6, : 64]
+.Lmainloop:
+	mov		r2, r5, LSR #3
+	and		r6, r5, #7
+	ldrb		r2, [r1, r2]
+	mov		r2, r2, LSR r6
+	and		r2, r2, #1
+	str		r5, [sp, #456]
+	eor		r4, r4, r2
+	str		r2, [sp, #460]
+	neg		r2, r4
+	add		r4, r3, #96
+	add		r5, r3, #192
+	add		r6, r3, #144
+	vld1.8		{d8-d9}, [r4, : 128]!
+	add		r7, r3, #240
+	vld1.8		{d10-d11}, [r5, : 128]!
+	veor		q6, q4, q5
+	vld1.8		{d14-d15}, [r6, : 128]!
+	vdup.i32	q8, r2
+	vld1.8		{d18-d19}, [r7, : 128]!
+	veor		q10, q7, q9
+	vld1.8		{d22-d23}, [r4, : 128]!
+	vand		q6, q6, q8
+	vld1.8		{d24-d25}, [r5, : 128]!
+	vand		q10, q10, q8
+	vld1.8		{d26-d27}, [r6, : 128]!
+	veor		q4, q4, q6
+	vld1.8		{d28-d29}, [r7, : 128]!
+	veor		q5, q5, q6
+	vld1.8		{d0}, [r4, : 64]
+	veor		q6, q7, q10
+	vld1.8		{d2}, [r5, : 64]
+	veor		q7, q9, q10
+	vld1.8		{d4}, [r6, : 64]
+	veor		q9, q11, q12
+	vld1.8		{d6}, [r7, : 64]
+	veor		q10, q0, q1
+	sub		r2, r4, #32
+	vand		q9, q9, q8
+	sub		r4, r5, #32
+	vand		q10, q10, q8
+	sub		r5, r6, #32
+	veor		q11, q11, q9
+	sub		r6, r7, #32
+	veor		q0, q0, q10
+	veor		q9, q12, q9
+	veor		q1, q1, q10
+	veor		q10, q13, q14
+	veor		q12, q2, q3
+	vand		q10, q10, q8
+	vand		q8, q12, q8
+	veor		q12, q13, q10
+	veor		q2, q2, q8
+	veor		q10, q14, q10
+	veor		q3, q3, q8
+	vadd.i32	q8, q4, q6
+	vsub.i32	q4, q4, q6
+	vst1.8		{d16-d17}, [r2, : 128]!
+	vadd.i32	q6, q11, q12
+	vst1.8		{d8-d9}, [r5, : 128]!
+	vsub.i32	q4, q11, q12
+	vst1.8		{d12-d13}, [r2, : 128]!
+	vadd.i32	q6, q0, q2
+	vst1.8		{d8-d9}, [r5, : 128]!
+	vsub.i32	q0, q0, q2
+	vst1.8		d12, [r2, : 64]
+	vadd.i32	q2, q5, q7
+	vst1.8		d0, [r5, : 64]
+	vsub.i32	q0, q5, q7
+	vst1.8		{d4-d5}, [r4, : 128]!
+	vadd.i32	q2, q9, q10
+	vst1.8		{d0-d1}, [r6, : 128]!
+	vsub.i32	q0, q9, q10
+	vst1.8		{d4-d5}, [r4, : 128]!
+	vadd.i32	q2, q1, q3
+	vst1.8		{d0-d1}, [r6, : 128]!
+	vsub.i32	q0, q1, q3
+	vst1.8		d4, [r4, : 64]
+	vst1.8		d0, [r6, : 64]
+	add		r2, sp, #512
+	add		r4, r3, #96
+	add		r5, r3, #144
+	vld1.8		{d0-d1}, [r2, : 128]
+	vld1.8		{d2-d3}, [r4, : 128]!
+	vld1.8		{d4-d5}, [r5, : 128]!
+	vzip.i32	q1, q2
+	vld1.8		{d6-d7}, [r4, : 128]!
+	vld1.8		{d8-d9}, [r5, : 128]!
+	vshl.i32	q5, q1, #1
+	vzip.i32	q3, q4
+	vshl.i32	q6, q2, #1
+	vld1.8		{d14}, [r4, : 64]
+	vshl.i32	q8, q3, #1
+	vld1.8		{d15}, [r5, : 64]
+	vshl.i32	q9, q4, #1
+	vmul.i32	d21, d7, d1
+	vtrn.32		d14, d15
+	vmul.i32	q11, q4, q0
+	vmul.i32	q0, q7, q0
+	vmull.s32	q12, d2, d2
+	vmlal.s32	q12, d11, d1
+	vmlal.s32	q12, d12, d0
+	vmlal.s32	q12, d13, d23
+	vmlal.s32	q12, d16, d22
+	vmlal.s32	q12, d7, d21
+	vmull.s32	q10, d2, d11
+	vmlal.s32	q10, d4, d1
+	vmlal.s32	q10, d13, d0
+	vmlal.s32	q10, d6, d23
+	vmlal.s32	q10, d17, d22
+	vmull.s32	q13, d10, d4
+	vmlal.s32	q13, d11, d3
+	vmlal.s32	q13, d13, d1
+	vmlal.s32	q13, d16, d0
+	vmlal.s32	q13, d17, d23
+	vmlal.s32	q13, d8, d22
+	vmull.s32	q1, d10, d5
+	vmlal.s32	q1, d11, d4
+	vmlal.s32	q1, d6, d1
+	vmlal.s32	q1, d17, d0
+	vmlal.s32	q1, d8, d23
+	vmull.s32	q14, d10, d6
+	vmlal.s32	q14, d11, d13
+	vmlal.s32	q14, d4, d4
+	vmlal.s32	q14, d17, d1
+	vmlal.s32	q14, d18, d0
+	vmlal.s32	q14, d9, d23
+	vmull.s32	q11, d10, d7
+	vmlal.s32	q11, d11, d6
+	vmlal.s32	q11, d12, d5
+	vmlal.s32	q11, d8, d1
+	vmlal.s32	q11, d19, d0
+	vmull.s32	q15, d10, d8
+	vmlal.s32	q15, d11, d17
+	vmlal.s32	q15, d12, d6
+	vmlal.s32	q15, d13, d5
+	vmlal.s32	q15, d19, d1
+	vmlal.s32	q15, d14, d0
+	vmull.s32	q2, d10, d9
+	vmlal.s32	q2, d11, d8
+	vmlal.s32	q2, d12, d7
+	vmlal.s32	q2, d13, d6
+	vmlal.s32	q2, d14, d1
+	vmull.s32	q0, d15, d1
+	vmlal.s32	q0, d10, d14
+	vmlal.s32	q0, d11, d19
+	vmlal.s32	q0, d12, d8
+	vmlal.s32	q0, d13, d17
+	vmlal.s32	q0, d6, d6
+	add		r2, sp, #480
+	vld1.8		{d18-d19}, [r2, : 128]
+	vmull.s32	q3, d16, d7
+	vmlal.s32	q3, d10, d15
+	vmlal.s32	q3, d11, d14
+	vmlal.s32	q3, d12, d9
+	vmlal.s32	q3, d13, d8
+	add		r2, sp, #496
+	vld1.8		{d8-d9}, [r2, : 128]
+	vadd.i64	q5, q12, q9
+	vadd.i64	q6, q15, q9
+	vshr.s64	q5, q5, #26
+	vshr.s64	q6, q6, #26
+	vadd.i64	q7, q10, q5
+	vshl.i64	q5, q5, #26
+	vadd.i64	q8, q7, q4
+	vadd.i64	q2, q2, q6
+	vshl.i64	q6, q6, #26
+	vadd.i64	q10, q2, q4
+	vsub.i64	q5, q12, q5
+	vshr.s64	q8, q8, #25
+	vsub.i64	q6, q15, q6
+	vshr.s64	q10, q10, #25
+	vadd.i64	q12, q13, q8
+	vshl.i64	q8, q8, #25
+	vadd.i64	q13, q12, q9
+	vadd.i64	q0, q0, q10
+	vsub.i64	q7, q7, q8
+	vshr.s64	q8, q13, #26
+	vshl.i64	q10, q10, #25
+	vadd.i64	q13, q0, q9
+	vadd.i64	q1, q1, q8
+	vshl.i64	q8, q8, #26
+	vadd.i64	q15, q1, q4
+	vsub.i64	q2, q2, q10
+	vshr.s64	q10, q13, #26
+	vsub.i64	q8, q12, q8
+	vshr.s64	q12, q15, #25
+	vadd.i64	q3, q3, q10
+	vshl.i64	q10, q10, #26
+	vadd.i64	q13, q3, q4
+	vadd.i64	q14, q14, q12
+	add		r2, r3, #288
+	vshl.i64	q12, q12, #25
+	add		r4, r3, #336
+	vadd.i64	q15, q14, q9
+	add		r2, r2, #8
+	vsub.i64	q0, q0, q10
+	add		r4, r4, #8
+	vshr.s64	q10, q13, #25
+	vsub.i64	q1, q1, q12
+	vshr.s64	q12, q15, #26
+	vadd.i64	q13, q10, q10
+	vadd.i64	q11, q11, q12
+	vtrn.32		d16, d2
+	vshl.i64	q12, q12, #26
+	vtrn.32		d17, d3
+	vadd.i64	q1, q11, q4
+	vadd.i64	q4, q5, q13
+	vst1.8		d16, [r2, : 64]!
+	vshl.i64	q5, q10, #4
+	vst1.8		d17, [r4, : 64]!
+	vsub.i64	q8, q14, q12
+	vshr.s64	q1, q1, #25
+	vadd.i64	q4, q4, q5
+	vadd.i64	q5, q6, q1
+	vshl.i64	q1, q1, #25
+	vadd.i64	q6, q5, q9
+	vadd.i64	q4, q4, q10
+	vshl.i64	q10, q10, #25
+	vadd.i64	q9, q4, q9
+	vsub.i64	q1, q11, q1
+	vshr.s64	q6, q6, #26
+	vsub.i64	q3, q3, q10
+	vtrn.32		d16, d2
+	vshr.s64	q9, q9, #26
+	vtrn.32		d17, d3
+	vadd.i64	q1, q2, q6
+	vst1.8		d16, [r2, : 64]
+	vshl.i64	q2, q6, #26
+	vst1.8		d17, [r4, : 64]
+	vadd.i64	q6, q7, q9
+	vtrn.32		d0, d6
+	vshl.i64	q7, q9, #26
+	vtrn.32		d1, d7
+	vsub.i64	q2, q5, q2
+	add		r2, r2, #16
+	vsub.i64	q3, q4, q7
+	vst1.8		d0, [r2, : 64]
+	add		r4, r4, #16
+	vst1.8		d1, [r4, : 64]
+	vtrn.32		d4, d2
+	vtrn.32		d5, d3
+	sub		r2, r2, #8
+	sub		r4, r4, #8
+	vtrn.32		d6, d12
+	vtrn.32		d7, d13
+	vst1.8		d4, [r2, : 64]
+	vst1.8		d5, [r4, : 64]
+	sub		r2, r2, #24
+	sub		r4, r4, #24
+	vst1.8		d6, [r2, : 64]
+	vst1.8		d7, [r4, : 64]
+	add		r2, r3, #240
+	add		r4, r3, #96
+	vld1.8		{d0-d1}, [r4, : 128]!
+	vld1.8		{d2-d3}, [r4, : 128]!
+	vld1.8		{d4}, [r4, : 64]
+	add		r4, r3, #144
+	vld1.8		{d6-d7}, [r4, : 128]!
+	vtrn.32		q0, q3
+	vld1.8		{d8-d9}, [r4, : 128]!
+	vshl.i32	q5, q0, #4
+	vtrn.32		q1, q4
+	vshl.i32	q6, q3, #4
+	vadd.i32	q5, q5, q0
+	vadd.i32	q6, q6, q3
+	vshl.i32	q7, q1, #4
+	vld1.8		{d5}, [r4, : 64]
+	vshl.i32	q8, q4, #4
+	vtrn.32		d4, d5
+	vadd.i32	q7, q7, q1
+	vadd.i32	q8, q8, q4
+	vld1.8		{d18-d19}, [r2, : 128]!
+	vshl.i32	q10, q2, #4
+	vld1.8		{d22-d23}, [r2, : 128]!
+	vadd.i32	q10, q10, q2
+	vld1.8		{d24}, [r2, : 64]
+	vadd.i32	q5, q5, q0
+	add		r2, r3, #192
+	vld1.8		{d26-d27}, [r2, : 128]!
+	vadd.i32	q6, q6, q3
+	vld1.8		{d28-d29}, [r2, : 128]!
+	vadd.i32	q8, q8, q4
+	vld1.8		{d25}, [r2, : 64]
+	vadd.i32	q10, q10, q2
+	vtrn.32		q9, q13
+	vadd.i32	q7, q7, q1
+	vadd.i32	q5, q5, q0
+	vtrn.32		q11, q14
+	vadd.i32	q6, q6, q3
+	add		r2, sp, #528
+	vadd.i32	q10, q10, q2
+	vtrn.32		d24, d25
+	vst1.8		{d12-d13}, [r2, : 128]
+	vshl.i32	q6, q13, #1
+	add		r2, sp, #544
+	vst1.8		{d20-d21}, [r2, : 128]
+	vshl.i32	q10, q14, #1
+	add		r2, sp, #560
+	vst1.8		{d12-d13}, [r2, : 128]
+	vshl.i32	q15, q12, #1
+	vadd.i32	q8, q8, q4
+	vext.32		d10, d31, d30, #0
+	vadd.i32	q7, q7, q1
+	add		r2, sp, #576
+	vst1.8		{d16-d17}, [r2, : 128]
+	vmull.s32	q8, d18, d5
+	vmlal.s32	q8, d26, d4
+	vmlal.s32	q8, d19, d9
+	vmlal.s32	q8, d27, d3
+	vmlal.s32	q8, d22, d8
+	vmlal.s32	q8, d28, d2
+	vmlal.s32	q8, d23, d7
+	vmlal.s32	q8, d29, d1
+	vmlal.s32	q8, d24, d6
+	vmlal.s32	q8, d25, d0
+	add		r2, sp, #592
+	vst1.8		{d14-d15}, [r2, : 128]
+	vmull.s32	q2, d18, d4
+	vmlal.s32	q2, d12, d9
+	vmlal.s32	q2, d13, d8
+	vmlal.s32	q2, d19, d3
+	vmlal.s32	q2, d22, d2
+	vmlal.s32	q2, d23, d1
+	vmlal.s32	q2, d24, d0
+	add		r2, sp, #608
+	vst1.8		{d20-d21}, [r2, : 128]
+	vmull.s32	q7, d18, d9
+	vmlal.s32	q7, d26, d3
+	vmlal.s32	q7, d19, d8
+	vmlal.s32	q7, d27, d2
+	vmlal.s32	q7, d22, d7
+	vmlal.s32	q7, d28, d1
+	vmlal.s32	q7, d23, d6
+	vmlal.s32	q7, d29, d0
+	add		r2, sp, #624
+	vst1.8		{d10-d11}, [r2, : 128]
+	vmull.s32	q5, d18, d3
+	vmlal.s32	q5, d19, d2
+	vmlal.s32	q5, d22, d1
+	vmlal.s32	q5, d23, d0
+	vmlal.s32	q5, d12, d8
+	add		r2, sp, #640
+	vst1.8		{d16-d17}, [r2, : 128]
+	vmull.s32	q4, d18, d8
+	vmlal.s32	q4, d26, d2
+	vmlal.s32	q4, d19, d7
+	vmlal.s32	q4, d27, d1
+	vmlal.s32	q4, d22, d6
+	vmlal.s32	q4, d28, d0
+	vmull.s32	q8, d18, d7
+	vmlal.s32	q8, d26, d1
+	vmlal.s32	q8, d19, d6
+	vmlal.s32	q8, d27, d0
+	add		r2, sp, #544
+	vld1.8		{d20-d21}, [r2, : 128]
+	vmlal.s32	q7, d24, d21
+	vmlal.s32	q7, d25, d20
+	vmlal.s32	q4, d23, d21
+	vmlal.s32	q4, d29, d20
+	vmlal.s32	q8, d22, d21
+	vmlal.s32	q8, d28, d20
+	vmlal.s32	q5, d24, d20
+	add		r2, sp, #544
+	vst1.8		{d14-d15}, [r2, : 128]
+	vmull.s32	q7, d18, d6
+	vmlal.s32	q7, d26, d0
+	add		r2, sp, #624
+	vld1.8		{d30-d31}, [r2, : 128]
+	vmlal.s32	q2, d30, d21
+	vmlal.s32	q7, d19, d21
+	vmlal.s32	q7, d27, d20
+	add		r2, sp, #592
+	vld1.8		{d26-d27}, [r2, : 128]
+	vmlal.s32	q4, d25, d27
+	vmlal.s32	q8, d29, d27
+	vmlal.s32	q8, d25, d26
+	vmlal.s32	q7, d28, d27
+	vmlal.s32	q7, d29, d26
+	add		r2, sp, #576
+	vld1.8		{d28-d29}, [r2, : 128]
+	vmlal.s32	q4, d24, d29
+	vmlal.s32	q8, d23, d29
+	vmlal.s32	q8, d24, d28
+	vmlal.s32	q7, d22, d29
+	vmlal.s32	q7, d23, d28
+	add		r2, sp, #576
+	vst1.8		{d8-d9}, [r2, : 128]
+	add		r2, sp, #528
+	vld1.8		{d8-d9}, [r2, : 128]
+	vmlal.s32	q7, d24, d9
+	vmlal.s32	q7, d25, d31
+	vmull.s32	q1, d18, d2
+	vmlal.s32	q1, d19, d1
+	vmlal.s32	q1, d22, d0
+	vmlal.s32	q1, d24, d27
+	vmlal.s32	q1, d23, d20
+	vmlal.s32	q1, d12, d7
+	vmlal.s32	q1, d13, d6
+	vmull.s32	q6, d18, d1
+	vmlal.s32	q6, d19, d0
+	vmlal.s32	q6, d23, d27
+	vmlal.s32	q6, d22, d20
+	vmlal.s32	q6, d24, d26
+	vmull.s32	q0, d18, d0
+	vmlal.s32	q0, d22, d27
+	vmlal.s32	q0, d23, d26
+	vmlal.s32	q0, d24, d31
+	vmlal.s32	q0, d19, d20
+	add		r2, sp, #608
+	vld1.8		{d18-d19}, [r2, : 128]
+	vmlal.s32	q2, d18, d7
+	vmlal.s32	q2, d19, d6
+	vmlal.s32	q5, d18, d6
+	vmlal.s32	q5, d19, d21
+	vmlal.s32	q1, d18, d21
+	vmlal.s32	q1, d19, d29
+	vmlal.s32	q0, d18, d28
+	vmlal.s32	q0, d19, d9
+	vmlal.s32	q6, d18, d29
+	vmlal.s32	q6, d19, d28
+	add		r2, sp, #560
+	vld1.8		{d18-d19}, [r2, : 128]
+	add		r2, sp, #480
+	vld1.8		{d22-d23}, [r2, : 128]
+	vmlal.s32	q5, d19, d7
+	vmlal.s32	q0, d18, d21
+	vmlal.s32	q0, d19, d29
+	vmlal.s32	q6, d18, d6
+	add		r2, sp, #496
+	vld1.8		{d6-d7}, [r2, : 128]
+	vmlal.s32	q6, d19, d21
+	add		r2, sp, #544
+	vld1.8		{d18-d19}, [r2, : 128]
+	vmlal.s32	q0, d30, d8
+	add		r2, sp, #640
+	vld1.8		{d20-d21}, [r2, : 128]
+	vmlal.s32	q5, d30, d29
+	add		r2, sp, #576
+	vld1.8		{d24-d25}, [r2, : 128]
+	vmlal.s32	q1, d30, d28
+	vadd.i64	q13, q0, q11
+	vadd.i64	q14, q5, q11
+	vmlal.s32	q6, d30, d9
+	vshr.s64	q4, q13, #26
+	vshr.s64	q13, q14, #26
+	vadd.i64	q7, q7, q4
+	vshl.i64	q4, q4, #26
+	vadd.i64	q14, q7, q3
+	vadd.i64	q9, q9, q13
+	vshl.i64	q13, q13, #26
+	vadd.i64	q15, q9, q3
+	vsub.i64	q0, q0, q4
+	vshr.s64	q4, q14, #25
+	vsub.i64	q5, q5, q13
+	vshr.s64	q13, q15, #25
+	vadd.i64	q6, q6, q4
+	vshl.i64	q4, q4, #25
+	vadd.i64	q14, q6, q11
+	vadd.i64	q2, q2, q13
+	vsub.i64	q4, q7, q4
+	vshr.s64	q7, q14, #26
+	vshl.i64	q13, q13, #25
+	vadd.i64	q14, q2, q11
+	vadd.i64	q8, q8, q7
+	vshl.i64	q7, q7, #26
+	vadd.i64	q15, q8, q3
+	vsub.i64	q9, q9, q13
+	vshr.s64	q13, q14, #26
+	vsub.i64	q6, q6, q7
+	vshr.s64	q7, q15, #25
+	vadd.i64	q10, q10, q13
+	vshl.i64	q13, q13, #26
+	vadd.i64	q14, q10, q3
+	vadd.i64	q1, q1, q7
+	add		r2, r3, #144
+	vshl.i64	q7, q7, #25
+	add		r4, r3, #96
+	vadd.i64	q15, q1, q11
+	add		r2, r2, #8
+	vsub.i64	q2, q2, q13
+	add		r4, r4, #8
+	vshr.s64	q13, q14, #25
+	vsub.i64	q7, q8, q7
+	vshr.s64	q8, q15, #26
+	vadd.i64	q14, q13, q13
+	vadd.i64	q12, q12, q8
+	vtrn.32		d12, d14
+	vshl.i64	q8, q8, #26
+	vtrn.32		d13, d15
+	vadd.i64	q3, q12, q3
+	vadd.i64	q0, q0, q14
+	vst1.8		d12, [r2, : 64]!
+	vshl.i64	q7, q13, #4
+	vst1.8		d13, [r4, : 64]!
+	vsub.i64	q1, q1, q8
+	vshr.s64	q3, q3, #25
+	vadd.i64	q0, q0, q7
+	vadd.i64	q5, q5, q3
+	vshl.i64	q3, q3, #25
+	vadd.i64	q6, q5, q11
+	vadd.i64	q0, q0, q13
+	vshl.i64	q7, q13, #25
+	vadd.i64	q8, q0, q11
+	vsub.i64	q3, q12, q3
+	vshr.s64	q6, q6, #26
+	vsub.i64	q7, q10, q7
+	vtrn.32		d2, d6
+	vshr.s64	q8, q8, #26
+	vtrn.32		d3, d7
+	vadd.i64	q3, q9, q6
+	vst1.8		d2, [r2, : 64]
+	vshl.i64	q6, q6, #26
+	vst1.8		d3, [r4, : 64]
+	vadd.i64	q1, q4, q8
+	vtrn.32		d4, d14
+	vshl.i64	q4, q8, #26
+	vtrn.32		d5, d15
+	vsub.i64	q5, q5, q6
+	add		r2, r2, #16
+	vsub.i64	q0, q0, q4
+	vst1.8		d4, [r2, : 64]
+	add		r4, r4, #16
+	vst1.8		d5, [r4, : 64]
+	vtrn.32		d10, d6
+	vtrn.32		d11, d7
+	sub		r2, r2, #8
+	sub		r4, r4, #8
+	vtrn.32		d0, d2
+	vtrn.32		d1, d3
+	vst1.8		d10, [r2, : 64]
+	vst1.8		d11, [r4, : 64]
+	sub		r2, r2, #24
+	sub		r4, r4, #24
+	vst1.8		d0, [r2, : 64]
+	vst1.8		d1, [r4, : 64]
+	add		r2, r3, #288
+	add		r4, r3, #336
+	vld1.8		{d0-d1}, [r2, : 128]!
+	vld1.8		{d2-d3}, [r4, : 128]!
+	vsub.i32	q0, q0, q1
+	vld1.8		{d2-d3}, [r2, : 128]!
+	vld1.8		{d4-d5}, [r4, : 128]!
+	vsub.i32	q1, q1, q2
+	add		r5, r3, #240
+	vld1.8		{d4}, [r2, : 64]
+	vld1.8		{d6}, [r4, : 64]
+	vsub.i32	q2, q2, q3
+	vst1.8		{d0-d1}, [r5, : 128]!
+	vst1.8		{d2-d3}, [r5, : 128]!
+	vst1.8		d4, [r5, : 64]
+	add		r2, r3, #144
+	add		r4, r3, #96
+	add		r5, r3, #144
+	add		r6, r3, #192
+	vld1.8		{d0-d1}, [r2, : 128]!
+	vld1.8		{d2-d3}, [r4, : 128]!
+	vsub.i32	q2, q0, q1
+	vadd.i32	q0, q0, q1
+	vld1.8		{d2-d3}, [r2, : 128]!
+	vld1.8		{d6-d7}, [r4, : 128]!
+	vsub.i32	q4, q1, q3
+	vadd.i32	q1, q1, q3
+	vld1.8		{d6}, [r2, : 64]
+	vld1.8		{d10}, [r4, : 64]
+	vsub.i32	q6, q3, q5
+	vadd.i32	q3, q3, q5
+	vst1.8		{d4-d5}, [r5, : 128]!
+	vst1.8		{d0-d1}, [r6, : 128]!
+	vst1.8		{d8-d9}, [r5, : 128]!
+	vst1.8		{d2-d3}, [r6, : 128]!
+	vst1.8		d12, [r5, : 64]
+	vst1.8		d6, [r6, : 64]
+	add		r2, r3, #0
+	add		r4, r3, #240
+	vld1.8		{d0-d1}, [r4, : 128]!
+	vld1.8		{d2-d3}, [r4, : 128]!
+	vld1.8		{d4}, [r4, : 64]
+	add		r4, r3, #336
+	vld1.8		{d6-d7}, [r4, : 128]!
+	vtrn.32		q0, q3
+	vld1.8		{d8-d9}, [r4, : 128]!
+	vshl.i32	q5, q0, #4
+	vtrn.32		q1, q4
+	vshl.i32	q6, q3, #4
+	vadd.i32	q5, q5, q0
+	vadd.i32	q6, q6, q3
+	vshl.i32	q7, q1, #4
+	vld1.8		{d5}, [r4, : 64]
+	vshl.i32	q8, q4, #4
+	vtrn.32		d4, d5
+	vadd.i32	q7, q7, q1
+	vadd.i32	q8, q8, q4
+	vld1.8		{d18-d19}, [r2, : 128]!
+	vshl.i32	q10, q2, #4
+	vld1.8		{d22-d23}, [r2, : 128]!
+	vadd.i32	q10, q10, q2
+	vld1.8		{d24}, [r2, : 64]
+	vadd.i32	q5, q5, q0
+	add		r2, r3, #288
+	vld1.8		{d26-d27}, [r2, : 128]!
+	vadd.i32	q6, q6, q3
+	vld1.8		{d28-d29}, [r2, : 128]!
+	vadd.i32	q8, q8, q4
+	vld1.8		{d25}, [r2, : 64]
+	vadd.i32	q10, q10, q2
+	vtrn.32		q9, q13
+	vadd.i32	q7, q7, q1
+	vadd.i32	q5, q5, q0
+	vtrn.32		q11, q14
+	vadd.i32	q6, q6, q3
+	add		r2, sp, #528
+	vadd.i32	q10, q10, q2
+	vtrn.32		d24, d25
+	vst1.8		{d12-d13}, [r2, : 128]
+	vshl.i32	q6, q13, #1
+	add		r2, sp, #544
+	vst1.8		{d20-d21}, [r2, : 128]
+	vshl.i32	q10, q14, #1
+	add		r2, sp, #560
+	vst1.8		{d12-d13}, [r2, : 128]
+	vshl.i32	q15, q12, #1
+	vadd.i32	q8, q8, q4
+	vext.32		d10, d31, d30, #0
+	vadd.i32	q7, q7, q1
+	add		r2, sp, #576
+	vst1.8		{d16-d17}, [r2, : 128]
+	vmull.s32	q8, d18, d5
+	vmlal.s32	q8, d26, d4
+	vmlal.s32	q8, d19, d9
+	vmlal.s32	q8, d27, d3
+	vmlal.s32	q8, d22, d8
+	vmlal.s32	q8, d28, d2
+	vmlal.s32	q8, d23, d7
+	vmlal.s32	q8, d29, d1
+	vmlal.s32	q8, d24, d6
+	vmlal.s32	q8, d25, d0
+	add		r2, sp, #592
+	vst1.8		{d14-d15}, [r2, : 128]
+	vmull.s32	q2, d18, d4
+	vmlal.s32	q2, d12, d9
+	vmlal.s32	q2, d13, d8
+	vmlal.s32	q2, d19, d3
+	vmlal.s32	q2, d22, d2
+	vmlal.s32	q2, d23, d1
+	vmlal.s32	q2, d24, d0
+	add		r2, sp, #608
+	vst1.8		{d20-d21}, [r2, : 128]
+	vmull.s32	q7, d18, d9
+	vmlal.s32	q7, d26, d3
+	vmlal.s32	q7, d19, d8
+	vmlal.s32	q7, d27, d2
+	vmlal.s32	q7, d22, d7
+	vmlal.s32	q7, d28, d1
+	vmlal.s32	q7, d23, d6
+	vmlal.s32	q7, d29, d0
+	add		r2, sp, #624
+	vst1.8		{d10-d11}, [r2, : 128]
+	vmull.s32	q5, d18, d3
+	vmlal.s32	q5, d19, d2
+	vmlal.s32	q5, d22, d1
+	vmlal.s32	q5, d23, d0
+	vmlal.s32	q5, d12, d8
+	add		r2, sp, #640
+	vst1.8		{d16-d17}, [r2, : 128]
+	vmull.s32	q4, d18, d8
+	vmlal.s32	q4, d26, d2
+	vmlal.s32	q4, d19, d7
+	vmlal.s32	q4, d27, d1
+	vmlal.s32	q4, d22, d6
+	vmlal.s32	q4, d28, d0
+	vmull.s32	q8, d18, d7
+	vmlal.s32	q8, d26, d1
+	vmlal.s32	q8, d19, d6
+	vmlal.s32	q8, d27, d0
+	add		r2, sp, #544
+	vld1.8		{d20-d21}, [r2, : 128]
+	vmlal.s32	q7, d24, d21
+	vmlal.s32	q7, d25, d20
+	vmlal.s32	q4, d23, d21
+	vmlal.s32	q4, d29, d20
+	vmlal.s32	q8, d22, d21
+	vmlal.s32	q8, d28, d20
+	vmlal.s32	q5, d24, d20
+	add		r2, sp, #544
+	vst1.8		{d14-d15}, [r2, : 128]
+	vmull.s32	q7, d18, d6
+	vmlal.s32	q7, d26, d0
+	add		r2, sp, #624
+	vld1.8		{d30-d31}, [r2, : 128]
+	vmlal.s32	q2, d30, d21
+	vmlal.s32	q7, d19, d21
+	vmlal.s32	q7, d27, d20
+	add		r2, sp, #592
+	vld1.8		{d26-d27}, [r2, : 128]
+	vmlal.s32	q4, d25, d27
+	vmlal.s32	q8, d29, d27
+	vmlal.s32	q8, d25, d26
+	vmlal.s32	q7, d28, d27
+	vmlal.s32	q7, d29, d26
+	add		r2, sp, #576
+	vld1.8		{d28-d29}, [r2, : 128]
+	vmlal.s32	q4, d24, d29
+	vmlal.s32	q8, d23, d29
+	vmlal.s32	q8, d24, d28
+	vmlal.s32	q7, d22, d29
+	vmlal.s32	q7, d23, d28
+	add		r2, sp, #576
+	vst1.8		{d8-d9}, [r2, : 128]
+	add		r2, sp, #528
+	vld1.8		{d8-d9}, [r2, : 128]
+	vmlal.s32	q7, d24, d9
+	vmlal.s32	q7, d25, d31
+	vmull.s32	q1, d18, d2
+	vmlal.s32	q1, d19, d1
+	vmlal.s32	q1, d22, d0
+	vmlal.s32	q1, d24, d27
+	vmlal.s32	q1, d23, d20
+	vmlal.s32	q1, d12, d7
+	vmlal.s32	q1, d13, d6
+	vmull.s32	q6, d18, d1
+	vmlal.s32	q6, d19, d0
+	vmlal.s32	q6, d23, d27
+	vmlal.s32	q6, d22, d20
+	vmlal.s32	q6, d24, d26
+	vmull.s32	q0, d18, d0
+	vmlal.s32	q0, d22, d27
+	vmlal.s32	q0, d23, d26
+	vmlal.s32	q0, d24, d31
+	vmlal.s32	q0, d19, d20
+	add		r2, sp, #608
+	vld1.8		{d18-d19}, [r2, : 128]
+	vmlal.s32	q2, d18, d7
+	vmlal.s32	q2, d19, d6
+	vmlal.s32	q5, d18, d6
+	vmlal.s32	q5, d19, d21
+	vmlal.s32	q1, d18, d21
+	vmlal.s32	q1, d19, d29
+	vmlal.s32	q0, d18, d28
+	vmlal.s32	q0, d19, d9
+	vmlal.s32	q6, d18, d29
+	vmlal.s32	q6, d19, d28
+	add		r2, sp, #560
+	vld1.8		{d18-d19}, [r2, : 128]
+	add		r2, sp, #480
+	vld1.8		{d22-d23}, [r2, : 128]
+	vmlal.s32	q5, d19, d7
+	vmlal.s32	q0, d18, d21
+	vmlal.s32	q0, d19, d29
+	vmlal.s32	q6, d18, d6
+	add		r2, sp, #496
+	vld1.8		{d6-d7}, [r2, : 128]
+	vmlal.s32	q6, d19, d21
+	add		r2, sp, #544
+	vld1.8		{d18-d19}, [r2, : 128]
+	vmlal.s32	q0, d30, d8
+	add		r2, sp, #640
+	vld1.8		{d20-d21}, [r2, : 128]
+	vmlal.s32	q5, d30, d29
+	add		r2, sp, #576
+	vld1.8		{d24-d25}, [r2, : 128]
+	vmlal.s32	q1, d30, d28
+	vadd.i64	q13, q0, q11
+	vadd.i64	q14, q5, q11
+	vmlal.s32	q6, d30, d9
+	vshr.s64	q4, q13, #26
+	vshr.s64	q13, q14, #26
+	vadd.i64	q7, q7, q4
+	vshl.i64	q4, q4, #26
+	vadd.i64	q14, q7, q3
+	vadd.i64	q9, q9, q13
+	vshl.i64	q13, q13, #26
+	vadd.i64	q15, q9, q3
+	vsub.i64	q0, q0, q4
+	vshr.s64	q4, q14, #25
+	vsub.i64	q5, q5, q13
+	vshr.s64	q13, q15, #25
+	vadd.i64	q6, q6, q4
+	vshl.i64	q4, q4, #25
+	vadd.i64	q14, q6, q11
+	vadd.i64	q2, q2, q13
+	vsub.i64	q4, q7, q4
+	vshr.s64	q7, q14, #26
+	vshl.i64	q13, q13, #25
+	vadd.i64	q14, q2, q11
+	vadd.i64	q8, q8, q7
+	vshl.i64	q7, q7, #26
+	vadd.i64	q15, q8, q3
+	vsub.i64	q9, q9, q13
+	vshr.s64	q13, q14, #26
+	vsub.i64	q6, q6, q7
+	vshr.s64	q7, q15, #25
+	vadd.i64	q10, q10, q13
+	vshl.i64	q13, q13, #26
+	vadd.i64	q14, q10, q3
+	vadd.i64	q1, q1, q7
+	add		r2, r3, #288
+	vshl.i64	q7, q7, #25
+	add		r4, r3, #96
+	vadd.i64	q15, q1, q11
+	add		r2, r2, #8
+	vsub.i64	q2, q2, q13
+	add		r4, r4, #8
+	vshr.s64	q13, q14, #25
+	vsub.i64	q7, q8, q7
+	vshr.s64	q8, q15, #26
+	vadd.i64	q14, q13, q13
+	vadd.i64	q12, q12, q8
+	vtrn.32		d12, d14
+	vshl.i64	q8, q8, #26
+	vtrn.32		d13, d15
+	vadd.i64	q3, q12, q3
+	vadd.i64	q0, q0, q14
+	vst1.8		d12, [r2, : 64]!
+	vshl.i64	q7, q13, #4
+	vst1.8		d13, [r4, : 64]!
+	vsub.i64	q1, q1, q8
+	vshr.s64	q3, q3, #25
+	vadd.i64	q0, q0, q7
+	vadd.i64	q5, q5, q3
+	vshl.i64	q3, q3, #25
+	vadd.i64	q6, q5, q11
+	vadd.i64	q0, q0, q13
+	vshl.i64	q7, q13, #25
+	vadd.i64	q8, q0, q11
+	vsub.i64	q3, q12, q3
+	vshr.s64	q6, q6, #26
+	vsub.i64	q7, q10, q7
+	vtrn.32		d2, d6
+	vshr.s64	q8, q8, #26
+	vtrn.32		d3, d7
+	vadd.i64	q3, q9, q6
+	vst1.8		d2, [r2, : 64]
+	vshl.i64	q6, q6, #26
+	vst1.8		d3, [r4, : 64]
+	vadd.i64	q1, q4, q8
+	vtrn.32		d4, d14
+	vshl.i64	q4, q8, #26
+	vtrn.32		d5, d15
+	vsub.i64	q5, q5, q6
+	add		r2, r2, #16
+	vsub.i64	q0, q0, q4
+	vst1.8		d4, [r2, : 64]
+	add		r4, r4, #16
+	vst1.8		d5, [r4, : 64]
+	vtrn.32		d10, d6
+	vtrn.32		d11, d7
+	sub		r2, r2, #8
+	sub		r4, r4, #8
+	vtrn.32		d0, d2
+	vtrn.32		d1, d3
+	vst1.8		d10, [r2, : 64]
+	vst1.8		d11, [r4, : 64]
+	sub		r2, r2, #24
+	sub		r4, r4, #24
+	vst1.8		d0, [r2, : 64]
+	vst1.8		d1, [r4, : 64]
+	add		r2, sp, #512
+	add		r4, r3, #144
+	add		r5, r3, #192
+	vld1.8		{d0-d1}, [r2, : 128]
+	vld1.8		{d2-d3}, [r4, : 128]!
+	vld1.8		{d4-d5}, [r5, : 128]!
+	vzip.i32	q1, q2
+	vld1.8		{d6-d7}, [r4, : 128]!
+	vld1.8		{d8-d9}, [r5, : 128]!
+	vshl.i32	q5, q1, #1
+	vzip.i32	q3, q4
+	vshl.i32	q6, q2, #1
+	vld1.8		{d14}, [r4, : 64]
+	vshl.i32	q8, q3, #1
+	vld1.8		{d15}, [r5, : 64]
+	vshl.i32	q9, q4, #1
+	vmul.i32	d21, d7, d1
+	vtrn.32		d14, d15
+	vmul.i32	q11, q4, q0
+	vmul.i32	q0, q7, q0
+	vmull.s32	q12, d2, d2
+	vmlal.s32	q12, d11, d1
+	vmlal.s32	q12, d12, d0
+	vmlal.s32	q12, d13, d23
+	vmlal.s32	q12, d16, d22
+	vmlal.s32	q12, d7, d21
+	vmull.s32	q10, d2, d11
+	vmlal.s32	q10, d4, d1
+	vmlal.s32	q10, d13, d0
+	vmlal.s32	q10, d6, d23
+	vmlal.s32	q10, d17, d22
+	vmull.s32	q13, d10, d4
+	vmlal.s32	q13, d11, d3
+	vmlal.s32	q13, d13, d1
+	vmlal.s32	q13, d16, d0
+	vmlal.s32	q13, d17, d23
+	vmlal.s32	q13, d8, d22
+	vmull.s32	q1, d10, d5
+	vmlal.s32	q1, d11, d4
+	vmlal.s32	q1, d6, d1
+	vmlal.s32	q1, d17, d0
+	vmlal.s32	q1, d8, d23
+	vmull.s32	q14, d10, d6
+	vmlal.s32	q14, d11, d13
+	vmlal.s32	q14, d4, d4
+	vmlal.s32	q14, d17, d1
+	vmlal.s32	q14, d18, d0
+	vmlal.s32	q14, d9, d23
+	vmull.s32	q11, d10, d7
+	vmlal.s32	q11, d11, d6
+	vmlal.s32	q11, d12, d5
+	vmlal.s32	q11, d8, d1
+	vmlal.s32	q11, d19, d0
+	vmull.s32	q15, d10, d8
+	vmlal.s32	q15, d11, d17
+	vmlal.s32	q15, d12, d6
+	vmlal.s32	q15, d13, d5
+	vmlal.s32	q15, d19, d1
+	vmlal.s32	q15, d14, d0
+	vmull.s32	q2, d10, d9
+	vmlal.s32	q2, d11, d8
+	vmlal.s32	q2, d12, d7
+	vmlal.s32	q2, d13, d6
+	vmlal.s32	q2, d14, d1
+	vmull.s32	q0, d15, d1
+	vmlal.s32	q0, d10, d14
+	vmlal.s32	q0, d11, d19
+	vmlal.s32	q0, d12, d8
+	vmlal.s32	q0, d13, d17
+	vmlal.s32	q0, d6, d6
+	add		r2, sp, #480
+	vld1.8		{d18-d19}, [r2, : 128]
+	vmull.s32	q3, d16, d7
+	vmlal.s32	q3, d10, d15
+	vmlal.s32	q3, d11, d14
+	vmlal.s32	q3, d12, d9
+	vmlal.s32	q3, d13, d8
+	add		r2, sp, #496
+	vld1.8		{d8-d9}, [r2, : 128]
+	vadd.i64	q5, q12, q9
+	vadd.i64	q6, q15, q9
+	vshr.s64	q5, q5, #26
+	vshr.s64	q6, q6, #26
+	vadd.i64	q7, q10, q5
+	vshl.i64	q5, q5, #26
+	vadd.i64	q8, q7, q4
+	vadd.i64	q2, q2, q6
+	vshl.i64	q6, q6, #26
+	vadd.i64	q10, q2, q4
+	vsub.i64	q5, q12, q5
+	vshr.s64	q8, q8, #25
+	vsub.i64	q6, q15, q6
+	vshr.s64	q10, q10, #25
+	vadd.i64	q12, q13, q8
+	vshl.i64	q8, q8, #25
+	vadd.i64	q13, q12, q9
+	vadd.i64	q0, q0, q10
+	vsub.i64	q7, q7, q8
+	vshr.s64	q8, q13, #26
+	vshl.i64	q10, q10, #25
+	vadd.i64	q13, q0, q9
+	vadd.i64	q1, q1, q8
+	vshl.i64	q8, q8, #26
+	vadd.i64	q15, q1, q4
+	vsub.i64	q2, q2, q10
+	vshr.s64	q10, q13, #26
+	vsub.i64	q8, q12, q8
+	vshr.s64	q12, q15, #25
+	vadd.i64	q3, q3, q10
+	vshl.i64	q10, q10, #26
+	vadd.i64	q13, q3, q4
+	vadd.i64	q14, q14, q12
+	add		r2, r3, #144
+	vshl.i64	q12, q12, #25
+	add		r4, r3, #192
+	vadd.i64	q15, q14, q9
+	add		r2, r2, #8
+	vsub.i64	q0, q0, q10
+	add		r4, r4, #8
+	vshr.s64	q10, q13, #25
+	vsub.i64	q1, q1, q12
+	vshr.s64	q12, q15, #26
+	vadd.i64	q13, q10, q10
+	vadd.i64	q11, q11, q12
+	vtrn.32		d16, d2
+	vshl.i64	q12, q12, #26
+	vtrn.32		d17, d3
+	vadd.i64	q1, q11, q4
+	vadd.i64	q4, q5, q13
+	vst1.8		d16, [r2, : 64]!
+	vshl.i64	q5, q10, #4
+	vst1.8		d17, [r4, : 64]!
+	vsub.i64	q8, q14, q12
+	vshr.s64	q1, q1, #25
+	vadd.i64	q4, q4, q5
+	vadd.i64	q5, q6, q1
+	vshl.i64	q1, q1, #25
+	vadd.i64	q6, q5, q9
+	vadd.i64	q4, q4, q10
+	vshl.i64	q10, q10, #25
+	vadd.i64	q9, q4, q9
+	vsub.i64	q1, q11, q1
+	vshr.s64	q6, q6, #26
+	vsub.i64	q3, q3, q10
+	vtrn.32		d16, d2
+	vshr.s64	q9, q9, #26
+	vtrn.32		d17, d3
+	vadd.i64	q1, q2, q6
+	vst1.8		d16, [r2, : 64]
+	vshl.i64	q2, q6, #26
+	vst1.8		d17, [r4, : 64]
+	vadd.i64	q6, q7, q9
+	vtrn.32		d0, d6
+	vshl.i64	q7, q9, #26
+	vtrn.32		d1, d7
+	vsub.i64	q2, q5, q2
+	add		r2, r2, #16
+	vsub.i64	q3, q4, q7
+	vst1.8		d0, [r2, : 64]
+	add		r4, r4, #16
+	vst1.8		d1, [r4, : 64]
+	vtrn.32		d4, d2
+	vtrn.32		d5, d3
+	sub		r2, r2, #8
+	sub		r4, r4, #8
+	vtrn.32		d6, d12
+	vtrn.32		d7, d13
+	vst1.8		d4, [r2, : 64]
+	vst1.8		d5, [r4, : 64]
+	sub		r2, r2, #24
+	sub		r4, r4, #24
+	vst1.8		d6, [r2, : 64]
+	vst1.8		d7, [r4, : 64]
+	add		r2, r3, #336
+	add		r4, r3, #288
+	vld1.8		{d0-d1}, [r2, : 128]!
+	vld1.8		{d2-d3}, [r4, : 128]!
+	vadd.i32	q0, q0, q1
+	vld1.8		{d2-d3}, [r2, : 128]!
+	vld1.8		{d4-d5}, [r4, : 128]!
+	vadd.i32	q1, q1, q2
+	add		r5, r3, #288
+	vld1.8		{d4}, [r2, : 64]
+	vld1.8		{d6}, [r4, : 64]
+	vadd.i32	q2, q2, q3
+	vst1.8		{d0-d1}, [r5, : 128]!
+	vst1.8		{d2-d3}, [r5, : 128]!
+	vst1.8		d4, [r5, : 64]
+	add		r2, r3, #48
+	add		r4, r3, #144
+	vld1.8		{d0-d1}, [r4, : 128]!
+	vld1.8		{d2-d3}, [r4, : 128]!
+	vld1.8		{d4}, [r4, : 64]
+	add		r4, r3, #288
+	vld1.8		{d6-d7}, [r4, : 128]!
+	vtrn.32		q0, q3
+	vld1.8		{d8-d9}, [r4, : 128]!
+	vshl.i32	q5, q0, #4
+	vtrn.32		q1, q4
+	vshl.i32	q6, q3, #4
+	vadd.i32	q5, q5, q0
+	vadd.i32	q6, q6, q3
+	vshl.i32	q7, q1, #4
+	vld1.8		{d5}, [r4, : 64]
+	vshl.i32	q8, q4, #4
+	vtrn.32		d4, d5
+	vadd.i32	q7, q7, q1
+	vadd.i32	q8, q8, q4
+	vld1.8		{d18-d19}, [r2, : 128]!
+	vshl.i32	q10, q2, #4
+	vld1.8		{d22-d23}, [r2, : 128]!
+	vadd.i32	q10, q10, q2
+	vld1.8		{d24}, [r2, : 64]
+	vadd.i32	q5, q5, q0
+	add		r2, r3, #240
+	vld1.8		{d26-d27}, [r2, : 128]!
+	vadd.i32	q6, q6, q3
+	vld1.8		{d28-d29}, [r2, : 128]!
+	vadd.i32	q8, q8, q4
+	vld1.8		{d25}, [r2, : 64]
+	vadd.i32	q10, q10, q2
+	vtrn.32		q9, q13
+	vadd.i32	q7, q7, q1
+	vadd.i32	q5, q5, q0
+	vtrn.32		q11, q14
+	vadd.i32	q6, q6, q3
+	add		r2, sp, #528
+	vadd.i32	q10, q10, q2
+	vtrn.32		d24, d25
+	vst1.8		{d12-d13}, [r2, : 128]
+	vshl.i32	q6, q13, #1
+	add		r2, sp, #544
+	vst1.8		{d20-d21}, [r2, : 128]
+	vshl.i32	q10, q14, #1
+	add		r2, sp, #560
+	vst1.8		{d12-d13}, [r2, : 128]
+	vshl.i32	q15, q12, #1
+	vadd.i32	q8, q8, q4
+	vext.32		d10, d31, d30, #0
+	vadd.i32	q7, q7, q1
+	add		r2, sp, #576
+	vst1.8		{d16-d17}, [r2, : 128]
+	vmull.s32	q8, d18, d5
+	vmlal.s32	q8, d26, d4
+	vmlal.s32	q8, d19, d9
+	vmlal.s32	q8, d27, d3
+	vmlal.s32	q8, d22, d8
+	vmlal.s32	q8, d28, d2
+	vmlal.s32	q8, d23, d7
+	vmlal.s32	q8, d29, d1
+	vmlal.s32	q8, d24, d6
+	vmlal.s32	q8, d25, d0
+	add		r2, sp, #592
+	vst1.8		{d14-d15}, [r2, : 128]
+	vmull.s32	q2, d18, d4
+	vmlal.s32	q2, d12, d9
+	vmlal.s32	q2, d13, d8
+	vmlal.s32	q2, d19, d3
+	vmlal.s32	q2, d22, d2
+	vmlal.s32	q2, d23, d1
+	vmlal.s32	q2, d24, d0
+	add		r2, sp, #608
+	vst1.8		{d20-d21}, [r2, : 128]
+	vmull.s32	q7, d18, d9
+	vmlal.s32	q7, d26, d3
+	vmlal.s32	q7, d19, d8
+	vmlal.s32	q7, d27, d2
+	vmlal.s32	q7, d22, d7
+	vmlal.s32	q7, d28, d1
+	vmlal.s32	q7, d23, d6
+	vmlal.s32	q7, d29, d0
+	add		r2, sp, #624
+	vst1.8		{d10-d11}, [r2, : 128]
+	vmull.s32	q5, d18, d3
+	vmlal.s32	q5, d19, d2
+	vmlal.s32	q5, d22, d1
+	vmlal.s32	q5, d23, d0
+	vmlal.s32	q5, d12, d8
+	add		r2, sp, #640
+	vst1.8		{d16-d17}, [r2, : 128]
+	vmull.s32	q4, d18, d8
+	vmlal.s32	q4, d26, d2
+	vmlal.s32	q4, d19, d7
+	vmlal.s32	q4, d27, d1
+	vmlal.s32	q4, d22, d6
+	vmlal.s32	q4, d28, d0
+	vmull.s32	q8, d18, d7
+	vmlal.s32	q8, d26, d1
+	vmlal.s32	q8, d19, d6
+	vmlal.s32	q8, d27, d0
+	add		r2, sp, #544
+	vld1.8		{d20-d21}, [r2, : 128]
+	vmlal.s32	q7, d24, d21
+	vmlal.s32	q7, d25, d20
+	vmlal.s32	q4, d23, d21
+	vmlal.s32	q4, d29, d20
+	vmlal.s32	q8, d22, d21
+	vmlal.s32	q8, d28, d20
+	vmlal.s32	q5, d24, d20
+	add		r2, sp, #544
+	vst1.8		{d14-d15}, [r2, : 128]
+	vmull.s32	q7, d18, d6
+	vmlal.s32	q7, d26, d0
+	add		r2, sp, #624
+	vld1.8		{d30-d31}, [r2, : 128]
+	vmlal.s32	q2, d30, d21
+	vmlal.s32	q7, d19, d21
+	vmlal.s32	q7, d27, d20
+	add		r2, sp, #592
+	vld1.8		{d26-d27}, [r2, : 128]
+	vmlal.s32	q4, d25, d27
+	vmlal.s32	q8, d29, d27
+	vmlal.s32	q8, d25, d26
+	vmlal.s32	q7, d28, d27
+	vmlal.s32	q7, d29, d26
+	add		r2, sp, #576
+	vld1.8		{d28-d29}, [r2, : 128]
+	vmlal.s32	q4, d24, d29
+	vmlal.s32	q8, d23, d29
+	vmlal.s32	q8, d24, d28
+	vmlal.s32	q7, d22, d29
+	vmlal.s32	q7, d23, d28
+	add		r2, sp, #576
+	vst1.8		{d8-d9}, [r2, : 128]
+	add		r2, sp, #528
+	vld1.8		{d8-d9}, [r2, : 128]
+	vmlal.s32	q7, d24, d9
+	vmlal.s32	q7, d25, d31
+	vmull.s32	q1, d18, d2
+	vmlal.s32	q1, d19, d1
+	vmlal.s32	q1, d22, d0
+	vmlal.s32	q1, d24, d27
+	vmlal.s32	q1, d23, d20
+	vmlal.s32	q1, d12, d7
+	vmlal.s32	q1, d13, d6
+	vmull.s32	q6, d18, d1
+	vmlal.s32	q6, d19, d0
+	vmlal.s32	q6, d23, d27
+	vmlal.s32	q6, d22, d20
+	vmlal.s32	q6, d24, d26
+	vmull.s32	q0, d18, d0
+	vmlal.s32	q0, d22, d27
+	vmlal.s32	q0, d23, d26
+	vmlal.s32	q0, d24, d31
+	vmlal.s32	q0, d19, d20
+	add		r2, sp, #608
+	vld1.8		{d18-d19}, [r2, : 128]
+	vmlal.s32	q2, d18, d7
+	vmlal.s32	q2, d19, d6
+	vmlal.s32	q5, d18, d6
+	vmlal.s32	q5, d19, d21
+	vmlal.s32	q1, d18, d21
+	vmlal.s32	q1, d19, d29
+	vmlal.s32	q0, d18, d28
+	vmlal.s32	q0, d19, d9
+	vmlal.s32	q6, d18, d29
+	vmlal.s32	q6, d19, d28
+	add		r2, sp, #560
+	vld1.8		{d18-d19}, [r2, : 128]
+	add		r2, sp, #480
+	vld1.8		{d22-d23}, [r2, : 128]
+	vmlal.s32	q5, d19, d7
+	vmlal.s32	q0, d18, d21
+	vmlal.s32	q0, d19, d29
+	vmlal.s32	q6, d18, d6
+	add		r2, sp, #496
+	vld1.8		{d6-d7}, [r2, : 128]
+	vmlal.s32	q6, d19, d21
+	add		r2, sp, #544
+	vld1.8		{d18-d19}, [r2, : 128]
+	vmlal.s32	q0, d30, d8
+	add		r2, sp, #640
+	vld1.8		{d20-d21}, [r2, : 128]
+	vmlal.s32	q5, d30, d29
+	add		r2, sp, #576
+	vld1.8		{d24-d25}, [r2, : 128]
+	vmlal.s32	q1, d30, d28
+	vadd.i64	q13, q0, q11
+	vadd.i64	q14, q5, q11
+	vmlal.s32	q6, d30, d9
+	vshr.s64	q4, q13, #26
+	vshr.s64	q13, q14, #26
+	vadd.i64	q7, q7, q4
+	vshl.i64	q4, q4, #26
+	vadd.i64	q14, q7, q3
+	vadd.i64	q9, q9, q13
+	vshl.i64	q13, q13, #26
+	vadd.i64	q15, q9, q3
+	vsub.i64	q0, q0, q4
+	vshr.s64	q4, q14, #25
+	vsub.i64	q5, q5, q13
+	vshr.s64	q13, q15, #25
+	vadd.i64	q6, q6, q4
+	vshl.i64	q4, q4, #25
+	vadd.i64	q14, q6, q11
+	vadd.i64	q2, q2, q13
+	vsub.i64	q4, q7, q4
+	vshr.s64	q7, q14, #26
+	vshl.i64	q13, q13, #25
+	vadd.i64	q14, q2, q11
+	vadd.i64	q8, q8, q7
+	vshl.i64	q7, q7, #26
+	vadd.i64	q15, q8, q3
+	vsub.i64	q9, q9, q13
+	vshr.s64	q13, q14, #26
+	vsub.i64	q6, q6, q7
+	vshr.s64	q7, q15, #25
+	vadd.i64	q10, q10, q13
+	vshl.i64	q13, q13, #26
+	vadd.i64	q14, q10, q3
+	vadd.i64	q1, q1, q7
+	add		r2, r3, #240
+	vshl.i64	q7, q7, #25
+	add		r4, r3, #144
+	vadd.i64	q15, q1, q11
+	add		r2, r2, #8
+	vsub.i64	q2, q2, q13
+	add		r4, r4, #8
+	vshr.s64	q13, q14, #25
+	vsub.i64	q7, q8, q7
+	vshr.s64	q8, q15, #26
+	vadd.i64	q14, q13, q13
+	vadd.i64	q12, q12, q8
+	vtrn.32		d12, d14
+	vshl.i64	q8, q8, #26
+	vtrn.32		d13, d15
+	vadd.i64	q3, q12, q3
+	vadd.i64	q0, q0, q14
+	vst1.8		d12, [r2, : 64]!
+	vshl.i64	q7, q13, #4
+	vst1.8		d13, [r4, : 64]!
+	vsub.i64	q1, q1, q8
+	vshr.s64	q3, q3, #25
+	vadd.i64	q0, q0, q7
+	vadd.i64	q5, q5, q3
+	vshl.i64	q3, q3, #25
+	vadd.i64	q6, q5, q11
+	vadd.i64	q0, q0, q13
+	vshl.i64	q7, q13, #25
+	vadd.i64	q8, q0, q11
+	vsub.i64	q3, q12, q3
+	vshr.s64	q6, q6, #26
+	vsub.i64	q7, q10, q7
+	vtrn.32		d2, d6
+	vshr.s64	q8, q8, #26
+	vtrn.32		d3, d7
+	vadd.i64	q3, q9, q6
+	vst1.8		d2, [r2, : 64]
+	vshl.i64	q6, q6, #26
+	vst1.8		d3, [r4, : 64]
+	vadd.i64	q1, q4, q8
+	vtrn.32		d4, d14
+	vshl.i64	q4, q8, #26
+	vtrn.32		d5, d15
+	vsub.i64	q5, q5, q6
+	add		r2, r2, #16
+	vsub.i64	q0, q0, q4
+	vst1.8		d4, [r2, : 64]
+	add		r4, r4, #16
+	vst1.8		d5, [r4, : 64]
+	vtrn.32		d10, d6
+	vtrn.32		d11, d7
+	sub		r2, r2, #8
+	sub		r4, r4, #8
+	vtrn.32		d0, d2
+	vtrn.32		d1, d3
+	vst1.8		d10, [r2, : 64]
+	vst1.8		d11, [r4, : 64]
+	sub		r2, r2, #24
+	sub		r4, r4, #24
+	vst1.8		d0, [r2, : 64]
+	vst1.8		d1, [r4, : 64]
+	ldr		r2, [sp, #456]
+	ldr		r4, [sp, #460]
+	subs		r5, r2, #1
+	bge		.Lmainloop
+	add		r1, r3, #144
+	add		r2, r3, #336
+	vld1.8		{d0-d1}, [r1, : 128]!
+	vld1.8		{d2-d3}, [r1, : 128]!
+	vld1.8		{d4}, [r1, : 64]
+	vst1.8		{d0-d1}, [r2, : 128]!
+	vst1.8		{d2-d3}, [r2, : 128]!
+	vst1.8		d4, [r2, : 64]
+	movw		r1, #0
+.Linvertloop:
+	add		r2, r3, #144
+	movw		r4, #0
+	movw		r5, #2
+	cmp		r1, #1
+	moveq		r5, #1
+	addeq		r2, r3, #336
+	addeq		r4, r3, #48
+	cmp		r1, #2
+	moveq		r5, #1
+	addeq		r2, r3, #48
+	cmp		r1, #3
+	moveq		r5, #5
+	addeq		r4, r3, #336
+	cmp		r1, #4
+	moveq		r5, #10
+	cmp		r1, #5
+	moveq		r5, #20
+	cmp		r1, #6
+	moveq		r5, #10
+	addeq		r2, r3, #336
+	addeq		r4, r3, #336
+	cmp		r1, #7
+	moveq		r5, #50
+	cmp		r1, #8
+	moveq		r5, #100
+	cmp		r1, #9
+	moveq		r5, #50
+	addeq		r2, r3, #336
+	cmp		r1, #10
+	moveq		r5, #5
+	addeq		r2, r3, #48
+	cmp		r1, #11
+	moveq		r5, #0
+	addeq		r2, r3, #96
+	add		r6, r3, #144
+	add		r7, r3, #288
+	vld1.8		{d0-d1}, [r6, : 128]!
+	vld1.8		{d2-d3}, [r6, : 128]!
+	vld1.8		{d4}, [r6, : 64]
+	vst1.8		{d0-d1}, [r7, : 128]!
+	vst1.8		{d2-d3}, [r7, : 128]!
+	vst1.8		d4, [r7, : 64]
+	cmp		r5, #0
+	beq		.Lskipsquaringloop
+.Lsquaringloop:
+	add		r6, r3, #288
+	add		r7, r3, #288
+	add		r8, r3, #288
+	vmov.i32	q0, #19
+	vmov.i32	q1, #0
+	vmov.i32	q2, #1
+	vzip.i32	q1, q2
+	vld1.8		{d4-d5}, [r7, : 128]!
+	vld1.8		{d6-d7}, [r7, : 128]!
+	vld1.8		{d9}, [r7, : 64]
+	vld1.8		{d10-d11}, [r6, : 128]!
+	add		r7, sp, #384
+	vld1.8		{d12-d13}, [r6, : 128]!
+	vmul.i32	q7, q2, q0
+	vld1.8		{d8}, [r6, : 64]
+	vext.32		d17, d11, d10, #1
+	vmul.i32	q9, q3, q0
+	vext.32		d16, d10, d8, #1
+	vshl.u32	q10, q5, q1
+	vext.32		d22, d14, d4, #1
+	vext.32		d24, d18, d6, #1
+	vshl.u32	q13, q6, q1
+	vshl.u32	d28, d8, d2
+	vrev64.i32	d22, d22
+	vmul.i32	d1, d9, d1
+	vrev64.i32	d24, d24
+	vext.32		d29, d8, d13, #1
+	vext.32		d0, d1, d9, #1
+	vrev64.i32	d0, d0
+	vext.32		d2, d9, d1, #1
+	vext.32		d23, d15, d5, #1
+	vmull.s32	q4, d20, d4
+	vrev64.i32	d23, d23
+	vmlal.s32	q4, d21, d1
+	vrev64.i32	d2, d2
+	vmlal.s32	q4, d26, d19
+	vext.32		d3, d5, d15, #1
+	vmlal.s32	q4, d27, d18
+	vrev64.i32	d3, d3
+	vmlal.s32	q4, d28, d15
+	vext.32		d14, d12, d11, #1
+	vmull.s32	q5, d16, d23
+	vext.32		d15, d13, d12, #1
+	vmlal.s32	q5, d17, d4
+	vst1.8		d8, [r7, : 64]!
+	vmlal.s32	q5, d14, d1
+	vext.32		d12, d9, d8, #0
+	vmlal.s32	q5, d15, d19
+	vmov.i64	d13, #0
+	vmlal.s32	q5, d29, d18
+	vext.32		d25, d19, d7, #1
+	vmlal.s32	q6, d20, d5
+	vrev64.i32	d25, d25
+	vmlal.s32	q6, d21, d4
+	vst1.8		d11, [r7, : 64]!
+	vmlal.s32	q6, d26, d1
+	vext.32		d9, d10, d10, #0
+	vmlal.s32	q6, d27, d19
+	vmov.i64	d8, #0
+	vmlal.s32	q6, d28, d18
+	vmlal.s32	q4, d16, d24
+	vmlal.s32	q4, d17, d5
+	vmlal.s32	q4, d14, d4
+	vst1.8		d12, [r7, : 64]!
+	vmlal.s32	q4, d15, d1
+	vext.32		d10, d13, d12, #0
+	vmlal.s32	q4, d29, d19
+	vmov.i64	d11, #0
+	vmlal.s32	q5, d20, d6
+	vmlal.s32	q5, d21, d5
+	vmlal.s32	q5, d26, d4
+	vext.32		d13, d8, d8, #0
+	vmlal.s32	q5, d27, d1
+	vmov.i64	d12, #0
+	vmlal.s32	q5, d28, d19
+	vst1.8		d9, [r7, : 64]!
+	vmlal.s32	q6, d16, d25
+	vmlal.s32	q6, d17, d6
+	vst1.8		d10, [r7, : 64]
+	vmlal.s32	q6, d14, d5
+	vext.32		d8, d11, d10, #0
+	vmlal.s32	q6, d15, d4
+	vmov.i64	d9, #0
+	vmlal.s32	q6, d29, d1
+	vmlal.s32	q4, d20, d7
+	vmlal.s32	q4, d21, d6
+	vmlal.s32	q4, d26, d5
+	vext.32		d11, d12, d12, #0
+	vmlal.s32	q4, d27, d4
+	vmov.i64	d10, #0
+	vmlal.s32	q4, d28, d1
+	vmlal.s32	q5, d16, d0
+	sub		r6, r7, #32
+	vmlal.s32	q5, d17, d7
+	vmlal.s32	q5, d14, d6
+	vext.32		d30, d9, d8, #0
+	vmlal.s32	q5, d15, d5
+	vld1.8		{d31}, [r6, : 64]!
+	vmlal.s32	q5, d29, d4
+	vmlal.s32	q15, d20, d0
+	vext.32		d0, d6, d18, #1
+	vmlal.s32	q15, d21, d25
+	vrev64.i32	d0, d0
+	vmlal.s32	q15, d26, d24
+	vext.32		d1, d7, d19, #1
+	vext.32		d7, d10, d10, #0
+	vmlal.s32	q15, d27, d23
+	vrev64.i32	d1, d1
+	vld1.8		{d6}, [r6, : 64]
+	vmlal.s32	q15, d28, d22
+	vmlal.s32	q3, d16, d4
+	add		r6, r6, #24
+	vmlal.s32	q3, d17, d2
+	vext.32		d4, d31, d30, #0
+	vmov		d17, d11
+	vmlal.s32	q3, d14, d1
+	vext.32		d11, d13, d13, #0
+	vext.32		d13, d30, d30, #0
+	vmlal.s32	q3, d15, d0
+	vext.32		d1, d8, d8, #0
+	vmlal.s32	q3, d29, d3
+	vld1.8		{d5}, [r6, : 64]
+	sub		r6, r6, #16
+	vext.32		d10, d6, d6, #0
+	vmov.i32	q1, #0xffffffff
+	vshl.i64	q4, q1, #25
+	add		r7, sp, #480
+	vld1.8		{d14-d15}, [r7, : 128]
+	vadd.i64	q9, q2, q7
+	vshl.i64	q1, q1, #26
+	vshr.s64	q10, q9, #26
+	vld1.8		{d0}, [r6, : 64]!
+	vadd.i64	q5, q5, q10
+	vand		q9, q9, q1
+	vld1.8		{d16}, [r6, : 64]!
+	add		r6, sp, #496
+	vld1.8		{d20-d21}, [r6, : 128]
+	vadd.i64	q11, q5, q10
+	vsub.i64	q2, q2, q9
+	vshr.s64	q9, q11, #25
+	vext.32		d12, d5, d4, #0
+	vand		q11, q11, q4
+	vadd.i64	q0, q0, q9
+	vmov		d19, d7
+	vadd.i64	q3, q0, q7
+	vsub.i64	q5, q5, q11
+	vshr.s64	q11, q3, #26
+	vext.32		d18, d11, d10, #0
+	vand		q3, q3, q1
+	vadd.i64	q8, q8, q11
+	vadd.i64	q11, q8, q10
+	vsub.i64	q0, q0, q3
+	vshr.s64	q3, q11, #25
+	vand		q11, q11, q4
+	vadd.i64	q3, q6, q3
+	vadd.i64	q6, q3, q7
+	vsub.i64	q8, q8, q11
+	vshr.s64	q11, q6, #26
+	vand		q6, q6, q1
+	vadd.i64	q9, q9, q11
+	vadd.i64	d25, d19, d21
+	vsub.i64	q3, q3, q6
+	vshr.s64	d23, d25, #25
+	vand		q4, q12, q4
+	vadd.i64	d21, d23, d23
+	vshl.i64	d25, d23, #4
+	vadd.i64	d21, d21, d23
+	vadd.i64	d25, d25, d21
+	vadd.i64	d4, d4, d25
+	vzip.i32	q0, q8
+	vadd.i64	d12, d4, d14
+	add		r6, r8, #8
+	vst1.8		d0, [r6, : 64]
+	vsub.i64	d19, d19, d9
+	add		r6, r6, #16
+	vst1.8		d16, [r6, : 64]
+	vshr.s64	d22, d12, #26
+	vand		q0, q6, q1
+	vadd.i64	d10, d10, d22
+	vzip.i32	q3, q9
+	vsub.i64	d4, d4, d0
+	sub		r6, r6, #8
+	vst1.8		d6, [r6, : 64]
+	add		r6, r6, #16
+	vst1.8		d18, [r6, : 64]
+	vzip.i32	q2, q5
+	sub		r6, r6, #32
+	vst1.8		d4, [r6, : 64]
+	subs		r5, r5, #1
+	bhi		.Lsquaringloop
+.Lskipsquaringloop:
+	mov		r2, r2
+	add		r5, r3, #288
+	add		r6, r3, #144
+	vmov.i32	q0, #19
+	vmov.i32	q1, #0
+	vmov.i32	q2, #1
+	vzip.i32	q1, q2
+	vld1.8		{d4-d5}, [r5, : 128]!
+	vld1.8		{d6-d7}, [r5, : 128]!
+	vld1.8		{d9}, [r5, : 64]
+	vld1.8		{d10-d11}, [r2, : 128]!
+	add		r5, sp, #384
+	vld1.8		{d12-d13}, [r2, : 128]!
+	vmul.i32	q7, q2, q0
+	vld1.8		{d8}, [r2, : 64]
+	vext.32		d17, d11, d10, #1
+	vmul.i32	q9, q3, q0
+	vext.32		d16, d10, d8, #1
+	vshl.u32	q10, q5, q1
+	vext.32		d22, d14, d4, #1
+	vext.32		d24, d18, d6, #1
+	vshl.u32	q13, q6, q1
+	vshl.u32	d28, d8, d2
+	vrev64.i32	d22, d22
+	vmul.i32	d1, d9, d1
+	vrev64.i32	d24, d24
+	vext.32		d29, d8, d13, #1
+	vext.32		d0, d1, d9, #1
+	vrev64.i32	d0, d0
+	vext.32		d2, d9, d1, #1
+	vext.32		d23, d15, d5, #1
+	vmull.s32	q4, d20, d4
+	vrev64.i32	d23, d23
+	vmlal.s32	q4, d21, d1
+	vrev64.i32	d2, d2
+	vmlal.s32	q4, d26, d19
+	vext.32		d3, d5, d15, #1
+	vmlal.s32	q4, d27, d18
+	vrev64.i32	d3, d3
+	vmlal.s32	q4, d28, d15
+	vext.32		d14, d12, d11, #1
+	vmull.s32	q5, d16, d23
+	vext.32		d15, d13, d12, #1
+	vmlal.s32	q5, d17, d4
+	vst1.8		d8, [r5, : 64]!
+	vmlal.s32	q5, d14, d1
+	vext.32		d12, d9, d8, #0
+	vmlal.s32	q5, d15, d19
+	vmov.i64	d13, #0
+	vmlal.s32	q5, d29, d18
+	vext.32		d25, d19, d7, #1
+	vmlal.s32	q6, d20, d5
+	vrev64.i32	d25, d25
+	vmlal.s32	q6, d21, d4
+	vst1.8		d11, [r5, : 64]!
+	vmlal.s32	q6, d26, d1
+	vext.32		d9, d10, d10, #0
+	vmlal.s32	q6, d27, d19
+	vmov.i64	d8, #0
+	vmlal.s32	q6, d28, d18
+	vmlal.s32	q4, d16, d24
+	vmlal.s32	q4, d17, d5
+	vmlal.s32	q4, d14, d4
+	vst1.8		d12, [r5, : 64]!
+	vmlal.s32	q4, d15, d1
+	vext.32		d10, d13, d12, #0
+	vmlal.s32	q4, d29, d19
+	vmov.i64	d11, #0
+	vmlal.s32	q5, d20, d6
+	vmlal.s32	q5, d21, d5
+	vmlal.s32	q5, d26, d4
+	vext.32		d13, d8, d8, #0
+	vmlal.s32	q5, d27, d1
+	vmov.i64	d12, #0
+	vmlal.s32	q5, d28, d19
+	vst1.8		d9, [r5, : 64]!
+	vmlal.s32	q6, d16, d25
+	vmlal.s32	q6, d17, d6
+	vst1.8		d10, [r5, : 64]
+	vmlal.s32	q6, d14, d5
+	vext.32		d8, d11, d10, #0
+	vmlal.s32	q6, d15, d4
+	vmov.i64	d9, #0
+	vmlal.s32	q6, d29, d1
+	vmlal.s32	q4, d20, d7
+	vmlal.s32	q4, d21, d6
+	vmlal.s32	q4, d26, d5
+	vext.32		d11, d12, d12, #0
+	vmlal.s32	q4, d27, d4
+	vmov.i64	d10, #0
+	vmlal.s32	q4, d28, d1
+	vmlal.s32	q5, d16, d0
+	sub		r2, r5, #32
+	vmlal.s32	q5, d17, d7
+	vmlal.s32	q5, d14, d6
+	vext.32		d30, d9, d8, #0
+	vmlal.s32	q5, d15, d5
+	vld1.8		{d31}, [r2, : 64]!
+	vmlal.s32	q5, d29, d4
+	vmlal.s32	q15, d20, d0
+	vext.32		d0, d6, d18, #1
+	vmlal.s32	q15, d21, d25
+	vrev64.i32	d0, d0
+	vmlal.s32	q15, d26, d24
+	vext.32		d1, d7, d19, #1
+	vext.32		d7, d10, d10, #0
+	vmlal.s32	q15, d27, d23
+	vrev64.i32	d1, d1
+	vld1.8		{d6}, [r2, : 64]
+	vmlal.s32	q15, d28, d22
+	vmlal.s32	q3, d16, d4
+	add		r2, r2, #24
+	vmlal.s32	q3, d17, d2
+	vext.32		d4, d31, d30, #0
+	vmov		d17, d11
+	vmlal.s32	q3, d14, d1
+	vext.32		d11, d13, d13, #0
+	vext.32		d13, d30, d30, #0
+	vmlal.s32	q3, d15, d0
+	vext.32		d1, d8, d8, #0
+	vmlal.s32	q3, d29, d3
+	vld1.8		{d5}, [r2, : 64]
+	sub		r2, r2, #16
+	vext.32		d10, d6, d6, #0
+	vmov.i32	q1, #0xffffffff
+	vshl.i64	q4, q1, #25
+	add		r5, sp, #480
+	vld1.8		{d14-d15}, [r5, : 128]
+	vadd.i64	q9, q2, q7
+	vshl.i64	q1, q1, #26
+	vshr.s64	q10, q9, #26
+	vld1.8		{d0}, [r2, : 64]!
+	vadd.i64	q5, q5, q10
+	vand		q9, q9, q1
+	vld1.8		{d16}, [r2, : 64]!
+	add		r2, sp, #496
+	vld1.8		{d20-d21}, [r2, : 128]
+	vadd.i64	q11, q5, q10
+	vsub.i64	q2, q2, q9
+	vshr.s64	q9, q11, #25
+	vext.32		d12, d5, d4, #0
+	vand		q11, q11, q4
+	vadd.i64	q0, q0, q9
+	vmov		d19, d7
+	vadd.i64	q3, q0, q7
+	vsub.i64	q5, q5, q11
+	vshr.s64	q11, q3, #26
+	vext.32		d18, d11, d10, #0
+	vand		q3, q3, q1
+	vadd.i64	q8, q8, q11
+	vadd.i64	q11, q8, q10
+	vsub.i64	q0, q0, q3
+	vshr.s64	q3, q11, #25
+	vand		q11, q11, q4
+	vadd.i64	q3, q6, q3
+	vadd.i64	q6, q3, q7
+	vsub.i64	q8, q8, q11
+	vshr.s64	q11, q6, #26
+	vand		q6, q6, q1
+	vadd.i64	q9, q9, q11
+	vadd.i64	d25, d19, d21
+	vsub.i64	q3, q3, q6
+	vshr.s64	d23, d25, #25
+	vand		q4, q12, q4
+	vadd.i64	d21, d23, d23
+	vshl.i64	d25, d23, #4
+	vadd.i64	d21, d21, d23
+	vadd.i64	d25, d25, d21
+	vadd.i64	d4, d4, d25
+	vzip.i32	q0, q8
+	vadd.i64	d12, d4, d14
+	add		r2, r6, #8
+	vst1.8		d0, [r2, : 64]
+	vsub.i64	d19, d19, d9
+	add		r2, r2, #16
+	vst1.8		d16, [r2, : 64]
+	vshr.s64	d22, d12, #26
+	vand		q0, q6, q1
+	vadd.i64	d10, d10, d22
+	vzip.i32	q3, q9
+	vsub.i64	d4, d4, d0
+	sub		r2, r2, #8
+	vst1.8		d6, [r2, : 64]
+	add		r2, r2, #16
+	vst1.8		d18, [r2, : 64]
+	vzip.i32	q2, q5
+	sub		r2, r2, #32
+	vst1.8		d4, [r2, : 64]
+	cmp		r4, #0
+	beq		.Lskippostcopy
+	add		r2, r3, #144
+	mov		r4, r4
+	vld1.8		{d0-d1}, [r2, : 128]!
+	vld1.8		{d2-d3}, [r2, : 128]!
+	vld1.8		{d4}, [r2, : 64]
+	vst1.8		{d0-d1}, [r4, : 128]!
+	vst1.8		{d2-d3}, [r4, : 128]!
+	vst1.8		d4, [r4, : 64]
+.Lskippostcopy:
+	cmp		r1, #1
+	bne		.Lskipfinalcopy
+	add		r2, r3, #288
+	add		r4, r3, #144
+	vld1.8		{d0-d1}, [r2, : 128]!
+	vld1.8		{d2-d3}, [r2, : 128]!
+	vld1.8		{d4}, [r2, : 64]
+	vst1.8		{d0-d1}, [r4, : 128]!
+	vst1.8		{d2-d3}, [r4, : 128]!
+	vst1.8		d4, [r4, : 64]
+.Lskipfinalcopy:
+	add		r1, r1, #1
+	cmp		r1, #12
+	blo		.Linvertloop
+	add		r1, r3, #144
+	ldr		r2, [r1], #4
+	ldr		r3, [r1], #4
+	ldr		r4, [r1], #4
+	ldr		r5, [r1], #4
+	ldr		r6, [r1], #4
+	ldr		r7, [r1], #4
+	ldr		r8, [r1], #4
+	ldr		r9, [r1], #4
+	ldr		r10, [r1], #4
+	ldr		r1, [r1]
+	add		r11, r1, r1, LSL #4
+	add		r11, r11, r1, LSL #1
+	add		r11, r11, #16777216
+	mov		r11, r11, ASR #25
+	add		r11, r11, r2
+	mov		r11, r11, ASR #26
+	add		r11, r11, r3
+	mov		r11, r11, ASR #25
+	add		r11, r11, r4
+	mov		r11, r11, ASR #26
+	add		r11, r11, r5
+	mov		r11, r11, ASR #25
+	add		r11, r11, r6
+	mov		r11, r11, ASR #26
+	add		r11, r11, r7
+	mov		r11, r11, ASR #25
+	add		r11, r11, r8
+	mov		r11, r11, ASR #26
+	add		r11, r11, r9
+	mov		r11, r11, ASR #25
+	add		r11, r11, r10
+	mov		r11, r11, ASR #26
+	add		r11, r11, r1
+	mov		r11, r11, ASR #25
+	add		r2, r2, r11
+	add		r2, r2, r11, LSL #1
+	add		r2, r2, r11, LSL #4
+	mov		r11, r2, ASR #26
+	add		r3, r3, r11
+	sub		r2, r2, r11, LSL #26
+	mov		r11, r3, ASR #25
+	add		r4, r4, r11
+	sub		r3, r3, r11, LSL #25
+	mov		r11, r4, ASR #26
+	add		r5, r5, r11
+	sub		r4, r4, r11, LSL #26
+	mov		r11, r5, ASR #25
+	add		r6, r6, r11
+	sub		r5, r5, r11, LSL #25
+	mov		r11, r6, ASR #26
+	add		r7, r7, r11
+	sub		r6, r6, r11, LSL #26
+	mov		r11, r7, ASR #25
+	add		r8, r8, r11
+	sub		r7, r7, r11, LSL #25
+	mov		r11, r8, ASR #26
+	add		r9, r9, r11
+	sub		r8, r8, r11, LSL #26
+	mov		r11, r9, ASR #25
+	add		r10, r10, r11
+	sub		r9, r9, r11, LSL #25
+	mov		r11, r10, ASR #26
+	add		r1, r1, r11
+	sub		r10, r10, r11, LSL #26
+	mov		r11, r1, ASR #25
+	sub		r1, r1, r11, LSL #25
+	add		r2, r2, r3, LSL #26
+	mov		r3, r3, LSR #6
+	add		r3, r3, r4, LSL #19
+	mov		r4, r4, LSR #13
+	add		r4, r4, r5, LSL #13
+	mov		r5, r5, LSR #19
+	add		r5, r5, r6, LSL #6
+	add		r6, r7, r8, LSL #25
+	mov		r7, r8, LSR #7
+	add		r7, r7, r9, LSL #19
+	mov		r8, r9, LSR #13
+	add		r8, r8, r10, LSL #12
+	mov		r9, r10, LSR #20
+	add		r1, r9, r1, LSL #6
+	str		r2, [r0]
+	str		r3, [r0, #4]
+	str		r4, [r0, #8]
+	str		r5, [r0, #12]
+	str		r6, [r0, #16]
+	str		r7, [r0, #20]
+	str		r8, [r0, #24]
+	str		r1, [r0, #28]
+	movw		r0, #0
+	mov		sp, ip
+	pop		{r4-r11, pc}
+ENDPROC(curve25519_neon)
+#endif
diff --git a/lib/zinc/curve25519/curve25519.c b/lib/zinc/curve25519/curve25519.c
index 32536340d39d..0d5ea97762d4 100644
--- a/lib/zinc/curve25519/curve25519.c
+++ b/lib/zinc/curve25519/curve25519.c
@@ -21,6 +21,8 @@ 
 
 #if defined(CONFIG_ZINC_ARCH_X86_64)
 #include "curve25519-x86_64-glue.h"
+#elif defined(CONFIG_ZINC_ARCH_ARM)
+#include "curve25519-arm-glue.h"
 #else
 void __init curve25519_fpu_init(void)
 {