This commit is contained in:
bluepython508 committed 2026-10-22 12:27:19 +01:00
1 parent 3530afb854
commit 6903fcff27
2146 files changed
+112256 -190703

No files matched your search

@@ -0,0 +1,107 @@
// SPDX-License-Identifier: BSD-3-Clause
//
// Generated from CryptoGAMS poly1305-armv4.pl by plan9-xlate.pl. The
// generated poly1305_arm.s carries the upstream BSD-3-Clause notice
// in its file header.
//go:build arm
//go:generate sh ../regen/regen.sh
// Package poly1305 implements Poly1305 with the CryptoGAMS ARMv4
// assembly inner loop, regenerated by tsasm/arm/regen/plan9-xlate.pl.
// It only builds on GOARCH=arm; other architectures should use
// golang.org/x/crypto/poly1305.
package poly1305
import "unsafe"
const (
KeySize = 32
TagSize = 16
)
// ctxSize is the byte size of the upstream poly1305 state struct.
// Scalar paths use the first 40 bytes (5 base-2^32 h limbs at 0..19,
// 4 r limbs at 20..35, an is_base2_26 flag at 36). The NEON paths
// use more; we size generously.
const ctxSize = 192
//go:noescape
func poly1305_init(ctx unsafe.Pointer, key unsafe.Pointer)
//go:noescape
func poly1305_blocks(ctx unsafe.Pointer, inp unsafe.Pointer, length uintptr, padbit uintptr)
//go:noescape
func poly1305_emit(ctx unsafe.Pointer, mac unsafe.Pointer, nonce unsafe.Pointer)
// Sum computes a Poly1305 MAC of m under key, writing the 16-byte tag
// to out.
func Sum(out *[TagSize]byte, m []byte, key *[KeySize]byte) {
var mac MAC
mac.Init(key)
mac.Write(m)
mac.Sum(out)
}
// MAC is an incremental Poly1305 message-authentication code computer.
// Single-use; not safe for concurrent use. Zero-value is not usable --
// call Init first.
type MAC struct {
ctx [ctxSize]byte
nonce [16]byte
buf [16]byte
n int
}
// New returns a fresh MAC keyed with key. Prefer (*MAC).Init for hot
// paths; this constructor heap-allocates.
func New(key *[KeySize]byte) *MAC {
m := new(MAC)
m.Init(key)
return m
}
// Init keys an existing (typically stack-allocated) MAC with key.
func (m *MAC) Init(key *[KeySize]byte) {
*m = MAC{}
poly1305_init(unsafe.Pointer(&m.ctx[0]), unsafe.Pointer(&key[0]))
copy(m.nonce[:], key[16:])
}
// Write feeds bytes into the MAC. Returns len(p), nil.
func (m *MAC) Write(p []byte) (int, error) {
n := len(p)
if m.n > 0 {
k := copy(m.buf[m.n:], p)
m.n += k
p = p[k:]
if m.n < 16 {
return n, nil
}
poly1305_blocks(unsafe.Pointer(&m.ctx[0]), unsafe.Pointer(&m.buf[0]), 16, 1)
m.n = 0
}
if blocks := len(p) >> 4; blocks > 0 {
poly1305_blocks(unsafe.Pointer(&m.ctx[0]), unsafe.Pointer(&p[0]), uintptr(blocks*16), 1)
p = p[blocks*16:]
}
if len(p) > 0 {
copy(m.buf[:], p)
m.n = len(p)
}
return n, nil
}
// Sum finalizes the MAC and writes the 16-byte tag to out.
func (m *MAC) Sum(out *[TagSize]byte) {
if m.n > 0 {
var pad [16]byte
copy(pad[:], m.buf[:m.n])
pad[m.n] = 1
poly1305_blocks(unsafe.Pointer(&m.ctx[0]), unsafe.Pointer(&pad[0]), 16, 0)
m.n = 0
}
poly1305_emit(unsafe.Pointer(&m.ctx[0]), unsafe.Pointer(&out[0]), unsafe.Pointer(&m.nonce[0]))
}
@@ -0,0 +1,908 @@
// Code generated by plan9-xlate.pl from CryptoGAMS Perl. DO NOT EDIT.
//
// Run `go generate ./tsasm/arm/...` (or tsasm/arm/regen/regen.sh) to
// regenerate. The upstream chacha-armv4.pl / poly1305-armv4.pl are
// fetched at a pinned commit by regen.sh; see that script for the
// upstream URL and SHA. Translation is by tsasm/arm/regen/plan9-xlate.pl.
//
// The original CryptoGAMS code this was derived from is dual-licensed
// under the BSD-3-Clause and OpenSSL licenses, at the holder's option.
// The CryptoGAMS BSD-3-Clause text is reproduced below; that license
// requires the copyright notice to travel with the source. Files in
// tsasm/arm/regen/ that are not derived from CryptoGAMS (plan9-xlate.pl
// and friends) are BSD-3-Clause without the dual-license option.
//
// ----------------------------------------------------------------
// Copyright (c) 2006, CRYPTOGAMS by <appro@openssl.org>
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain copyright
// notices, this list of conditions and the following
// disclaimer.
//
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials
// provided with the distribution.
//
// * Neither the name of the CRYPTOGAMS nor the names of its
// copyright holder and contributors may be used to endorse or
// promote products derived from this software without specific
// prior written permission.
//
// ALTERNATIVELY, provided that this notice is retained in full, this
// product may be distributed under the terms of the GNU General Public
// License (GPL), in which case the provisions of the GPL apply INSTEAD
// OF those given above.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// ----------------------------------------------------------------
#include "textflag.h"
#include "funcdata.h"
// func poly1305_init(ctx uintptr, key uintptr)
TEXT ·poly1305_init(SB), NOSPLIT, $36-8
PCDATA $PCDATA_UnsafePoint, $-2
NO_LOCAL_POINTERS
MOVW ctx+0(FP), R0
MOVW key+4(FP), R1
MOVW R4, 4(R13)
MOVW R5, 8(R13)
MOVW R6, 12(R13)
MOVW R7, 16(R13)
MOVW R8, 20(R13)
MOVW R9, 24(R13)
MOVW R11, 32(R13)
lb_Lpoly1305_init:
EOR R3, R3, R3
CMP $0, R1
MOVW R3, 0(R0) // zero hash value
MOVW R3, 4(R0)
MOVW R3, 8(R0)
MOVW R3, 12(R0)
MOVW R3, 16(R0)
MOVW R3, 36(R0) // clear is_base2_26
ADD $20, R0, R0
MOVW.EQ $0, R0
B.EQ lb_Lno_key
MOVBU 0(R1), R4
MOVW R14, 36(R13)
MOVW $0x0fffffff, R14
MOVW R14, 28(R13)
MOVBU 1(R1), R5
BIC $3, R14, R3 // 0x0ffffffc
MOVBU 2(R1), R6
MOVBU 3(R1), R7
ORR R5<<8, R4, R4
MOVBU 4(R1), R5
ORR R6<<16, R4, R4
MOVBU 5(R1), R6
ORR R7<<24, R4, R4
MOVBU 6(R1), R7
AND R14, R4, R4
MOVBU 7(R1), R8
ORR R6<<8, R5, R5
MOVBU 8(R1), R6
ORR R7<<16, R5, R5
MOVBU 9(R1), R7
ORR R8<<24, R5, R5
MOVBU 10(R1), R8
AND R3, R5, R5
MOVBU 11(R1), R9
ORR R7<<8, R6, R6
MOVBU 12(R1), R7
ORR R8<<16, R6, R6
MOVBU 13(R1), R8
ORR R9<<24, R6, R6
MOVBU 14(R1), R9
AND R3, R6, R6
MOVBU 15(R1), R14
MOVW R14, 28(R13)
ORR R8<<8, R7, R7
MOVW R4, 0(R0)
ORR R9<<16, R7, R7
MOVW R5, 4(R0)
ORR R14<<24, R7, R7
MOVW R6, 8(R0)
AND R3, R7, R7
MOVW R7, 12(R0)
MOVW $0, R0
MOVW 36(R13), R14
lb_Lno_key:
RET
// func poly1305_blocks(ctx uintptr, inp uintptr, len uintptr, padbit uintptr)
TEXT ·poly1305_blocks(SB), NOSPLIT, $72-16
PCDATA $PCDATA_UnsafePoint, $-2
NO_LOCAL_POINTERS
MOVW ctx+0(FP), R0
MOVW inp+4(FP), R1
MOVW len+8(FP), R2
MOVW padbit+12(FP), R3
MOVW R3, 36(R13)
MOVW R4, 40(R13)
MOVW R5, 44(R13)
MOVW R6, 48(R13)
MOVW R7, 52(R13)
MOVW R8, 56(R13)
MOVW R9, 60(R13)
MOVW R11, 68(R13)
lb_Lpoly1305_blocks:
BIC.S $15, R2, R2
B.EQ lb_Lno_data
ADD R1, R2, R2 // end pointer
MOVW R14, 72(R13)
MOVW 0(R0), R4
MOVW 4(R0), R5
MOVW 8(R0), R6
MOVW 12(R0), R7
MOVW 16(R0), R8
MOVW 20(R0), R9
MOVW 24(R0), R14
MOVW R14, 64(R13)
MOVW 28(R0), R11
MOVW 32(R0), R12
MOVW 72(R13), R14
ADD $20, R0, R0
MOVW R2, 20(R13) // offload stuff
MOVW R0, 16(R13)
MOVW R1, R14
CMP $0, R3
MOVW R14, 72(R13)
MOVW 64(R13), R14
MOVW R14, 24(R13)
MOVW R11, 28(R13)
MOVW R12, 32(R13)
MOVW 72(R13), R14
B lb_Loop
lb_Loop:
MOVBU.P 16(R14), R0 // load input
ADD.HI $1, R8, R8 // 1<<128
MOVBU -15(R14), R1
MOVBU -14(R14), R2
MOVBU -13(R14), R3
ORR R1<<8, R0, R1
MOVBU -12(R14), R0
ORR R2<<16, R1, R2
MOVBU -11(R14), R1
ORR R3<<24, R2, R3
MOVBU -10(R14), R2
ADD.S R3, R4, R4 // accumulate input
MOVBU -9(R14), R3
ORR R1<<8, R0, R1
MOVBU -8(R14), R0
ORR R2<<16, R1, R2
MOVBU -7(R14), R1
ORR R3<<24, R2, R3
MOVBU -6(R14), R2
ADC.S R3, R5, R5
MOVBU -5(R14), R3
ORR R1<<8, R0, R1
MOVBU -4(R14), R0
ORR R2<<16, R1, R2
MOVBU -3(R14), R1
ORR R3<<24, R2, R3
MOVBU -2(R14), R2
ADC.S R3, R6, R6
MOVBU -1(R14), R3
ORR R1<<8, R0, R1
MOVW R14, 12(R13) // offload input pointer
ORR R2<<16, R1, R2
MOVW R14, 72(R13)
MOVW 64(R13), R14
ADD R14>>2, R14, R14
MOVW R14, 64(R13)
ORR R3<<24, R2, R3
ADD R11>>2, R11, R11
ADC.S R3, R7, R7
ADD R12>>2, R12, R12
MULLU R5, R9, (R3, R2)
ADC $0, R8, R8
MULLU R4, R9, (R1, R0)
MULALU R8, R14, (R3, R2)
MULALU R7, R14, (R1, R0)
MOVW 24(R13), R14 // reload r10
MOVW R14, 64(R13)
MULALU R6, R12, (R3, R2)
MULALU R5, R12, (R1, R0)
MULALU R7, R11, (R3, R2)
MULALU R6, R11, (R1, R0)
MULALU R4, R14, (R3, R2)
MOVW R0, 4(R13) // future r4
MUL R8, R11, R0
MOVW 28(R13), R11 // reload r11
ADD.S R1, R2, R2 // d1+=d0>>32
EOR R1, R1, R1
MOVW 72(R13), R14
ADC $0, R3, R14 // future r6
MOVW R2, 8(R13) // future r5
MUL R8, R12, R2
EOR R3, R3, R3
MULALU R7, R12, (R1, R0)
MOVW 32(R13), R12 // reload r12
MULALU R7, R9, (R3, R2)
MULALU R6, R9, (R1, R0)
MOVW R14, 72(R13)
MOVW 64(R13), R14
MULALU R6, R14, (R3, R2)
MULALU R5, R14, (R1, R0)
MULALU R5, R11, (R3, R2)
MULALU R4, R11, (R1, R0)
MULALU R4, R12, (R3, R2)
MOVW 4(R13), R4
MUL R8, R9, R8
MOVW 8(R13), R5
MOVW 72(R13), R14
ADD.S R0, R14, R6 // d2+=d1>>32
MOVW 12(R13), R14 // reload input pointer
ADC $0, R1, R1
ADD.S R1, R2, R7 // d3+=d2>>32
MOVW 20(R13), R0 // reload end pointer
ADC $0, R3, R3
ADD R3, R8, R8 // h4+=d3>>32
BIC $3, R8, R1
AND $3, R8, R8
ADD R1>>2, R1, R1 // *=5
ADD.S R1, R4, R4
ADC.S $0, R5, R5
ADC.S $0, R6, R6
ADC.S $0, R7, R7
ADC $0, R8, R8
CMP R14, R0 // done yet?
B.HI lb_Loop
MOVW 16(R13), R0
MOVM.DB [R4, R5, R6, R7, R8], (R0) // store the result
lb_Lno_data:
RET
// func poly1305_emit(ctx uintptr, mac uintptr, nonce uintptr)
TEXT ·poly1305_emit(SB), NOSPLIT, $36-12
PCDATA $PCDATA_UnsafePoint, $-2
NO_LOCAL_POINTERS
MOVW ctx+0(FP), R0
MOVW mac+4(FP), R1
MOVW nonce+8(FP), R2
MOVW R4, 4(R13)
MOVW R5, 8(R13)
MOVW R6, 12(R13)
MOVW R7, 16(R13)
MOVW R8, 20(R13)
MOVW R9, 24(R13)
MOVW R11, 32(R13)
lb_Lpoly1305_emit:
MOVM.IA (R0), [R3, R4, R5, R6, R7]
ADD.S $5, R3, R8 // compare to modulus
ADC.S $0, R4, R9
MOVW R14, 36(R13)
ADC.S $0, R5, R14
MOVW R14, 28(R13)
ADC.S $0, R6, R11
ADC $0, R7, R0
TST $4, R0 // did it carry/borrow?
MOVW.NE R8, R3
MOVW 0(R2), R8
MOVW.NE R9, R4
MOVW 4(R2), R9
MOVW.NE R14, R5
MOVW 8(R2), R14
MOVW R14, 28(R13)
MOVW.NE R11, R6
MOVW 12(R2), R11
ADD.S R8, R3, R3
ADC.S R9, R4, R4
ADC.S R14, R5, R5
ADC R11, R6, R6
MOVB R3, 0(R1)
MOVW R3>>8, R3
MOVB R4, 4(R1)
MOVW R4>>8, R4
MOVB R5, 8(R1)
MOVW R5>>8, R5
MOVB R6, 12(R1)
MOVW R6>>8, R6
MOVB R3, 1(R1)
MOVW R3>>8, R3
MOVB R4, 5(R1)
MOVW R4>>8, R4
MOVB R5, 9(R1)
MOVW R5>>8, R5
MOVB R6, 13(R1)
MOVW R6>>8, R6
MOVB R3, 2(R1)
MOVW R3>>8, R3
MOVB R4, 6(R1)
MOVW R4>>8, R4
MOVB R5, 10(R1)
MOVW R5>>8, R5
MOVB R6, 14(R1)
MOVW R6>>8, R6
MOVB R3, 3(R1)
MOVB R4, 7(R1)
MOVB R5, 11(R1)
MOVB R6, 15(R1)
RET
TEXT ·poly1305_init_neon(SB), NOSPLIT, $0-8
PCDATA $PCDATA_UnsafePoint, $-2
NO_LOCAL_POINTERS
MOVW ctx+0(FP), R0
MOVW key+4(FP), R1
lb_Lpoly1305_init_neon:
MOVW 48(R0), R3 // first table element
CMP $-1, R3 // is value impossible?
B.NE lb_Lno_init_neon
MOVW 20(R0), R4 // load key base 2^32
MOVW 24(R0), R5
MOVW 28(R0), R6
MOVW 32(R0), R7
AND $0x03ffffff, R4, R2 // base 2^32 -> base 2^26
MOVW R4>>26, R3
MOVW R5>>20, R4
ORR R5<<6, R3, R3
MOVW R6>>14, R5
ORR R6<<12, R4, R4
MOVW R7>>8, R6
ORR R7<<18, R5, R5
AND $0x03ffffff, R3, R3
AND $0x03ffffff, R4, R4
AND $0x03ffffff, R5, R5
WORD $0xee802b10 // vdup.32 d0,r2
ADD R3<<2, R3, R2 // *5
WORD $0xee813b10 // vdup.32 d1,r3
ADD R4<<2, R4, R3
WORD $0xee822b10 // vdup.32 d2,r2
WORD $0xee834b10 // vdup.32 d3,r4
ADD R5<<2, R5, R4
WORD $0xee843b10 // vdup.32 d4,r3
WORD $0xee855b10 // vdup.32 d5,r5
ADD R6<<2, R6, R5
WORD $0xee864b10 // vdup.32 d6,r4
WORD $0xee876b10 // vdup.32 d7,r6
WORD $0xee885b10 // vdup.32 d8,r5
MOVW $2, R5 // counter
lb_Lsquare_neon:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
// d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
// d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
// d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
// d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
WORD $0xf3a0aa60 // vmull.u32 q5,d0,d0[1]
WORD $0xf3a1ca60 // vmull.u32 q6,d1,d0[1]
WORD $0xf3a3ea60 // vmull.u32 q7,d3,d0[1]
WORD $0xf3e50a60 // vmull.u32 q8,d5,d0[1]
WORD $0xf3e72a60 // vmull.u32 q9,d7,d0[1]
WORD $0xf3a7a262 // vmlal.u32 q5,d7,d2[1]
WORD $0xf3a0c261 // vmlal.u32 q6,d0,d1[1]
WORD $0xf3a1e261 // vmlal.u32 q7,d1,d1[1]
WORD $0xf3e30261 // vmlal.u32 q8,d3,d1[1]
WORD $0xf3e52261 // vmlal.u32 q9,d5,d1[1]
WORD $0xf3a5a264 // vmlal.u32 q5,d5,d4[1]
WORD $0xf3a7c264 // vmlal.u32 q6,d7,d4[1]
WORD $0xf3e10263 // vmlal.u32 q8,d1,d3[1]
WORD $0xf3a0e263 // vmlal.u32 q7,d0,d3[1]
WORD $0xf3e32263 // vmlal.u32 q9,d3,d3[1]
WORD $0xf3a3a266 // vmlal.u32 q5,d3,d6[1]
WORD $0xf3e00265 // vmlal.u32 q8,d0,d5[1]
WORD $0xf3a5c266 // vmlal.u32 q6,d5,d6[1]
WORD $0xf3a7e266 // vmlal.u32 q7,d7,d6[1]
WORD $0xf3e12265 // vmlal.u32 q9,d1,d5[1]
WORD $0xf3e70268 // vmlal.u32 q8,d7,d8[1]
WORD $0xf3a1a268 // vmlal.u32 q5,d1,d8[1]
WORD $0xf3a3c268 // vmlal.u32 q6,d3,d8[1]
WORD $0xf3a5e268 // vmlal.u32 q7,d5,d8[1]
WORD $0xf3e02267 // vmlal.u32 q9,d0,d7[1]
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// lazy reduction as discussed in "NEON crypto" by D.J. Bernstein
// and P. Schwabe
// H0>>+H1>>+H2>>+H3>>+H4
// H3>>+H4>>*5+H0>>+H1
// Trivia.
// Result of multiplication of n-bit number by m-bit number is
// n+m bits wide. However! Even though 2^n is a n+1-bit number,
// m-bit number multiplied by 2^n is still n+m bits wide.
// Sum of two n-bit numbers is n+1 bits wide, sum of three - n+2,
// and so is sum of four. Sum of 2^m n-m-bit numbers and n-bit
// one is n+1 bits wide.
// >>+ denotes Hnext += Hn>>26, Hn &= 0x3ffffff. This means that
// H0, H2, H3 are guaranteed to be 26 bits wide, while H1 and H4
// can be 27. However! In cases when their width exceeds 26 bits
// they are limited by 2^26+2^6. This in turn means that *sum*
// of the products with these values can still be viewed as sum
// of 52-bit numbers as long as the amount of addends is not a
// power of 2. For example,
// H4 = H4*R0 + H3*R1 + H2*R2 + H1*R3 + H0 * R4,
// which can't be larger than 5 * (2^26 + 2^6) * (2^26 + 2^6), or
// 5 * (2^52 + 2*2^32 + 2^12), which in turn is smaller than
// 8 * (2^52) or 2^55. However, the value is then multiplied by
// by 5, so we should be looking at 5 * 5 * (2^52 + 2^33 + 2^12),
// which is less than 32 * (2^52) or 2^57. And when processing
// data we are looking at triple as many addends...
// In key setup procedure pre-reduced H0 is limited by 5*4+1 and
// 5*H4 - by 5*5 52-bit addends, or 57 bits. But when hashing the
// input H0 is limited by (5*4+1)*3 addends, or 58 bits, while
// 5*H4 by 5*5*3, or 59[!] bits. How is this relevant? vmlal.u32
// instruction accepts 2x32-bit input and writes 2x64-bit result.
// This means that result of reduction have to be compressed upon
// loop wrap-around. This can be done in the process of reduction
// to minimize amount of instructions [as well as amount of
// 128-bit instructions, which benefits low-end processors], but
// one has to watch for H2 (which is narrower than H0) and 5*H4
// not being wider than 58 bits, so that result of right shift
// by 26 bits fits in 32 bits. This is also useful on x86,
// because it allows to use paddd in place for paddq, which
// benefits Atom, where paddq is ridiculously slow.
WORD $0xf3e6e0f0 // vshr.u64 q15,q8,#26
WORD $0xf3fa0220 // vmovn.i64 d16,q8
WORD $0xf3a680da // vshr.u64 q4,q5,#26
WORD $0xf3baa20a // vmovn.i64 d10,q5
WORD $0xf27228ee // vadd.i64 q9,q9,q15
WORD $0xf3c7073c // vbic.i32 d16,#0xfc000000
WORD $0xf23cc848 // vadd.i64 q6,q6,q4
WORD $0xf387a73c // vbic.i32 d10,#0xfc000000
WORD $0xf2e6e832 // vshrn.u64 d30,q9,#26
WORD $0xf3fa2222 // vmovn.i64 d18,q9
WORD $0xf3a680dc // vshr.u64 q4,q6,#26
WORD $0xf3bac20c // vmovn.i64 d12,q6
WORD $0xf23ee848 // vadd.i64 q7,q7,q4
WORD $0xf3c7273c // vbic.i32 d18,#0xfc000000
WORD $0xf387c73c // vbic.i32 d12,#0xfc000000
WORD $0xf22aa82e // vadd.i32 d10,d10,d30
WORD $0xf2e2e53e // vshl.u32 d30,d30,#2
WORD $0xf2a6881e // vshrn.u64 d8,q7,#26
WORD $0xf3bae20e // vmovn.i64 d14,q7
WORD $0xf22aa82e // vadd.i32 d10,d10,d30
WORD $0xf2600888 // vadd.i32 d16,d16,d8
WORD $0xf387e73c // vbic.i32 d14,#0xfc000000
WORD $0xf3e6e01a // vshr.u32 d30,d10,#26
WORD $0xf387a73c // vbic.i32 d10,#0xfc000000
WORD $0xf3a68030 // vshr.u32 d8,d16,#26
WORD $0xf3c7073c // vbic.i32 d16,#0xfc000000
WORD $0xf22cc82e // vadd.i32 d12,d12,d30
WORD $0xf2622888 // vadd.i32 d18,d18,d8
SUB.S $1, R5, R5
B.EQ lb_Lsquare_break_neon
ADD $(48+0*9*4), R0, R6
ADD $(48+1*9*4), R0, R7
WORD $0xf3ba008a // vtrn.32 d0,d10
WORD $0xf3ba308e // vtrn.32 d3,d14
WORD $0xf3ba50a0 // vtrn.32 d5,d16
WORD $0xf3ba108c // vtrn.32 d1,d12
WORD $0xf3ba70a2 // vtrn.32 d7,d18
WORD $0xf2a24513 // vshl.u32 d4,d3,#2
WORD $0xf2a26515 // vshl.u32 d6,d5,#2
WORD $0xf2a22511 // vshl.u32 d2,d1,#2
WORD $0xf2a28517 // vshl.u32 d8,d7,#2
WORD $0xf2244803 // vadd.i32 d4,d4,d3
WORD $0xf2222801 // vadd.i32 d2,d2,d1
WORD $0xf2266805 // vadd.i32 d6,d6,d5
WORD $0xf2288807 // vadd.i32 d8,d8,d7
WORD $0xf4860b0d // vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r6]!
WORD $0xf4870b8d // vst4.32 {d0[1],d1[1],d2[1],d3[1]},[r7]!
WORD $0xf4864b0d // vst4.32 {d4[0],d5[0],d6[0],d7[0]},[r6]!
WORD $0xf4874b8d // vst4.32 {d4[1],d5[1],d6[1],d7[1]},[r7]!
WORD $0xf486883f // vst1.32 {d8[0]},[r6,:32]
WORD $0xf48788bf // vst1.32 {d8[1]},[r7,:32]
B lb_Lsquare_neon
lb_Lsquare_break_neon:
ADD $(48+2*4*9), R0, R6
ADD $(48+3*4*9), R0, R7
WORD $0xf22a011a // vmov d0,d10
WORD $0xf2a2251c // vshl.u32 d2,d12,#2
WORD $0xf22c111c // vmov d1,d12
WORD $0xf2a2451e // vshl.u32 d4,d14,#2
WORD $0xf22e311e // vmov d3,d14
WORD $0xf2a26530 // vshl.u32 d6,d16,#2
WORD $0xf22051b0 // vmov d5,d16
WORD $0xf2a28532 // vshl.u32 d8,d18,#2
WORD $0xf22271b2 // vmov d7,d18
WORD $0xf222280c // vadd.i32 d2,d2,d12
WORD $0xf224480e // vadd.i32 d4,d4,d14
WORD $0xf2266820 // vadd.i32 d6,d6,d16
WORD $0xf2288822 // vadd.i32 d8,d8,d18
WORD $0xf4860b0d // vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r6]!
WORD $0xf4870b8d // vst4.32 {d0[1],d1[1],d2[1],d3[1]},[r7]!
WORD $0xf4864b0d // vst4.32 {d4[0],d5[0],d6[0],d7[0]},[r6]!
WORD $0xf4874b8d // vst4.32 {d4[1],d5[1],d6[1],d7[1]},[r7]!
WORD $0xf486880f // vst1.32 {d8[0]},[r6]
WORD $0xf487888f // vst1.32 {d8[1]},[r7]
lb_Lno_init_neon:
RET
// func poly1305_blocks_neon(ctx uintptr, inp uintptr, len uintptr, padbit uintptr)
TEXT ·poly1305_blocks_neon(SB), NOSPLIT, $96-16
PCDATA $PCDATA_UnsafePoint, $-2
NO_LOCAL_POINTERS
MOVW ctx+0(FP), R0
MOVW inp+4(FP), R1
MOVW len+8(FP), R2
MOVW padbit+12(FP), R3
MOVW R4, 84(R13)
MOVW R5, 88(R13)
MOVW R6, 92(R13)
MOVW R7, 96(R13)
lb_Lpoly1305_blocks_neon:
MOVW 36(R0), R12 // is_base2_26
CMP $64, R2
TST R12, R12 // is_base2_26?
B.NE lb_Lbase2_26_neon
MOVW R1, 4(R13)
MOVW R2, 8(R13)
MOVW R3, 12(R13)
BL ·poly1305_init_neon(SB)
MOVW 0(R0), R4 // load hash value base 2^32
MOVW 4(R0), R5
MOVW 8(R0), R6
MOVW 12(R0), R7
MOVW 16(R0), R12
AND $0x03ffffff, R4, R2 // base 2^32 -> base 2^26
MOVW R4>>26, R3
WORD $0xf30aa11a // veor d10,d10,d10
MOVW R5>>20, R4
ORR R5<<6, R3, R3
WORD $0xf30cc11c // veor d12,d12,d12
MOVW R6>>14, R5
ORR R6<<12, R4, R4
WORD $0xf30ee11e // veor d14,d14,d14
MOVW R7>>8, R6
ORR R7<<18, R5, R5
WORD $0xf34001b0 // veor d16,d16,d16
AND $0x03ffffff, R3, R3
ORR R12<<24, R6, R6
WORD $0xf34221b2 // veor d18,d18,d18
AND $0x03ffffff, R4, R4
MOVW $1, R1
AND $0x03ffffff, R5, R5
MOVW R1, 36(R0) // set is_base2_26
WORD $0xee0a2b10 // vmov.32 d10[0],r2
WORD $0xee0c3b10 // vmov.32 d12[0],r3
WORD $0xee0e4b10 // vmov.32 d14[0],r4
WORD $0xee005b90 // vmov.32 d16[0],r5
WORD $0xee026b90 // vmov.32 d18[0],r6
MOVW $zeros<>(SB), R5
MOVM.IA.W (R13), [R1, R2, R3, R14]
B lb_Lhash_loaded
lb_Lbase2_26_neon:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// load hash value
WORD $0xf30aa11a // veor d10,d10,d10
WORD $0xf30cc11c // veor d12,d12,d12
WORD $0xf30ee11e // veor d14,d14,d14
WORD $0xf34001b0 // veor d16,d16,d16
WORD $0xf34221b2 // veor d18,d18,d18
WORD $0xf4a0ab4d // vld4.32 {d10[0],d12[0],d14[0],d16[0]},[r0]!
MOVW $zeros<>(SB), R5
WORD $0xf4e0280f // vld1.32 {d18[0]},[r0]
SUB $16, R0, R0 // rewind
lb_Lhash_loaded:
ADD $32, R1, R4
MOVW R3<<24, R3
TST $31, R2
B.EQ lb_Leven
WORD $0xf4e14b4d // vld4.32 {d20[0],d22[0],d24[0],d26[0]},[r1]!
WORD $0xee0c3b90 // vmov.32 d28[0],r3
SUB $16, R2, R2
ADD $32, R1, R4
WORD $0xf3f8c43a // vsri.u32 d28,d26,#8
WORD $0xf2f2a53a // vshl.u32 d26,d26,#18
WORD $0xf3f2a438 // vsri.u32 d26,d24,#14
WORD $0xf2ec8538 // vshl.u32 d24,d24,#12
WORD $0xf26cd8a2 // vadd.i32 d29,d28,d18
WORD $0xf3c7a73c // vbic.i32 d26,#0xfc000000
WORD $0xf3ec8436 // vsri.u32 d24,d22,#20
WORD $0xf2e66536 // vshl.u32 d22,d22,#6
WORD $0xf3c7873c // vbic.i32 d24,#0xfc000000
WORD $0xf3e66434 // vsri.u32 d22,d20,#26
WORD $0xf26ab8a0 // vadd.i32 d27,d26,d16
WORD $0xf3c7473c // vbic.i32 d20,#0xfc000000
WORD $0xf3c7673c // vbic.i32 d22,#0xfc000000
WORD $0xf268988e // vadd.i32 d25,d24,d14
WORD $0xf264588a // vadd.i32 d21,d20,d10
WORD $0xf266788c // vadd.i32 d23,d22,d12
MOVW R5, R7
ADD $48, R0, R6
CMP R2, R2
B lb_Long_tail
lb_Leven:
SUB.S $64, R2, R2
MOVW.LO R5, R4
WORD $0xf2c0c651 // vmov.i32 q14,#1<<24
WORD $0xf461418f // vld4.32 {d20,d22,d24,d26},[r1]
ADD $64, R1, R1
WORD $0xf464518f // vld4.32 {d21,d23,d25,d27},[r4]
ADD $64, R4, R4
ADD.HI $(48+1*9*4), R0, R7
ADD.HI $(48+3*9*4), R0, R6
WORD $0xf3f8c47a // vsri.u32 q14,q13,#8
WORD $0xf2f2a57a // vshl.u32 q13,q13,#18
WORD $0xf3f2a478 // vsri.u32 q13,q12,#14
WORD $0xf2ec8578 // vshl.u32 q12,q12,#12
WORD $0xf3c7a77c // vbic.i32 q13,#0xfc000000
WORD $0xf3ec8476 // vsri.u32 q12,q11,#20
WORD $0xf2e66576 // vshl.u32 q11,q11,#6
WORD $0xf3c7877c // vbic.i32 q12,#0xfc000000
WORD $0xf3e66474 // vsri.u32 q11,q10,#26
WORD $0xf3c7477c // vbic.i32 q10,#0xfc000000
WORD $0xf3c7677c // vbic.i32 q11,#0xfc000000
B.LS lb_Lskip_loop
WORD $0xf4a70b8d // vld4.32 {d0[1],d1[1],d2[1],d3[1]},[r7]!
WORD $0xf4a60b0d // vld4.32 {d0[0],d1[0],d2[0],d3[0]},[r6]!
WORD $0xf4a74b8d // vld4.32 {d4[1],d5[1],d6[1],d7[1]},[r7]!
WORD $0xf4a64b0d // vld4.32 {d4[0],d5[0],d6[0],d7[0]},[r6]!
B lb_Loop_neon
lb_Loop_neon:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2
// ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^3+inp[7]*r
// ___________________/
// ((inp[0]*r^4+inp[2]*r^2+inp[4])*r^4+inp[6]*r^2+inp[8])*r^2
// ((inp[1]*r^4+inp[3]*r^2+inp[5])*r^4+inp[7]*r^2+inp[9])*r
// ___________________/ ____________________/
// Note that we start with inp[2:3]*r^2. This is because it
// doesn't depend on reduction in previous iteration.
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// d4 = h4*r0 + h3*r1 + h2*r2 + h1*r3 + h0*r4
// d3 = h3*r0 + h2*r1 + h1*r2 + h0*r3 + h4*5*r4
// d2 = h2*r0 + h1*r1 + h0*r2 + h4*5*r3 + h3*5*r4
// d1 = h1*r0 + h0*r1 + h4*5*r2 + h3*5*r3 + h2*5*r4
// d0 = h0*r0 + h4*5*r1 + h3*5*r2 + h2*5*r3 + h1*5*r4
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// inp[2:3]*r^2
WORD $0xf268888e // vadd.i32 d24,d24,d14
WORD $0xf3a9eae0 // vmull.u32 q7,d25,d0[1]
WORD $0xf264488a // vadd.i32 d20,d20,d10
WORD $0xf3a5aae0 // vmull.u32 q5,d21,d0[1]
WORD $0xf26aa8a0 // vadd.i32 d26,d26,d16
WORD $0xf3eb0ae0 // vmull.u32 q8,d27,d0[1]
WORD $0xf3a7e2e1 // vmlal.u32 q7,d23,d1[1]
WORD $0xf266688c // vadd.i32 d22,d22,d12
WORD $0xf3a7cae0 // vmull.u32 q6,d23,d0[1]
WORD $0xf26cc8a2 // vadd.i32 d28,d28,d18
WORD $0xf3ed2ae0 // vmull.u32 q9,d29,d0[1]
SUB.S $64, R2, R2
WORD $0xf3ada2e2 // vmlal.u32 q5,d29,d2[1]
MOVW.LO R5, R4
WORD $0xf3e902e1 // vmlal.u32 q8,d25,d1[1]
WORD $0xf4a788bf // vld1.32 d8[1],[r7,:32]
WORD $0xf3a5c2e1 // vmlal.u32 q6,d21,d1[1]
WORD $0xf3eb22e1 // vmlal.u32 q9,d27,d1[1]
WORD $0xf3aba2e4 // vmlal.u32 q5,d27,d4[1]
WORD $0xf3e702e3 // vmlal.u32 q8,d23,d3[1]
WORD $0xf3e922e3 // vmlal.u32 q9,d25,d3[1]
WORD $0xf3adc2e4 // vmlal.u32 q6,d29,d4[1]
WORD $0xf3a5e2e3 // vmlal.u32 q7,d21,d3[1]
WORD $0xf3e502e5 // vmlal.u32 q8,d21,d5[1]
WORD $0xf3a9a2e6 // vmlal.u32 q5,d25,d6[1]
WORD $0xf3e722e5 // vmlal.u32 q9,d23,d5[1]
WORD $0xf3abc2e6 // vmlal.u32 q6,d27,d6[1]
WORD $0xf3ade2e6 // vmlal.u32 q7,d29,d6[1]
WORD $0xf3ed02e8 // vmlal.u32 q8,d29,d8[1]
WORD $0xf3a7a2e8 // vmlal.u32 q5,d23,d8[1]
WORD $0xf3e522e7 // vmlal.u32 q9,d21,d7[1]
WORD $0xf3a9c2e8 // vmlal.u32 q6,d25,d8[1]
WORD $0xf3abe2e8 // vmlal.u32 q7,d27,d8[1]
WORD $0xf464518f // vld4.32 {d21,d23,d25,d27},[r4]
ADD $64, R4, R4
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// (hash+inp[0:1])*r^4 and accumulate
WORD $0xf3ea02c0 // vmlal.u32 q8,d26,d0[0]
WORD $0xf3a4a2c0 // vmlal.u32 q5,d20,d0[0]
WORD $0xf3ec22c0 // vmlal.u32 q9,d28,d0[0]
WORD $0xf3a6c2c0 // vmlal.u32 q6,d22,d0[0]
WORD $0xf3a8e2c0 // vmlal.u32 q7,d24,d0[0]
WORD $0xf4a6883f // vld1.32 d8[0],[r6,:32]
WORD $0xf3e802c1 // vmlal.u32 q8,d24,d1[0]
WORD $0xf3aca2c2 // vmlal.u32 q5,d28,d2[0]
WORD $0xf3ea22c1 // vmlal.u32 q9,d26,d1[0]
WORD $0xf3a4c2c1 // vmlal.u32 q6,d20,d1[0]
WORD $0xf3a6e2c1 // vmlal.u32 q7,d22,d1[0]
WORD $0xf3e602c3 // vmlal.u32 q8,d22,d3[0]
WORD $0xf3aaa2c4 // vmlal.u32 q5,d26,d4[0]
WORD $0xf3e822c3 // vmlal.u32 q9,d24,d3[0]
WORD $0xf3acc2c4 // vmlal.u32 q6,d28,d4[0]
WORD $0xf3a4e2c3 // vmlal.u32 q7,d20,d3[0]
WORD $0xf3e402c5 // vmlal.u32 q8,d20,d5[0]
WORD $0xf3a8a2c6 // vmlal.u32 q5,d24,d6[0]
WORD $0xf3e622c5 // vmlal.u32 q9,d22,d5[0]
WORD $0xf3aac2c6 // vmlal.u32 q6,d26,d6[0]
WORD $0xf3ec02c8 // vmlal.u32 q8,d28,d8[0]
WORD $0xf3ace2c6 // vmlal.u32 q7,d28,d6[0]
WORD $0xf3a6a2c8 // vmlal.u32 q5,d22,d8[0]
WORD $0xf3e422c7 // vmlal.u32 q9,d20,d7[0]
WORD $0xf2c0c651 // vmov.i32 q14,#1<<24
WORD $0xf3a8c2c8 // vmlal.u32 q6,d24,d8[0]
WORD $0xf3aae2c8 // vmlal.u32 q7,d26,d8[0]
WORD $0xf461418f // vld4.32 {d20,d22,d24,d26},[r1]
ADD $64, R1, R1
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// lazy reduction interleaved with base 2^32 -> base 2^26 of
// inp[0:3] previously loaded to q10-q13 and smashed to q10-q14.
WORD $0xf3e6e0f0 // vshr.u64 q15,q8,#26
WORD $0xf3fa0220 // vmovn.i64 d16,q8
WORD $0xf3a680da // vshr.u64 q4,q5,#26
WORD $0xf3baa20a // vmovn.i64 d10,q5
WORD $0xf27228ee // vadd.i64 q9,q9,q15
WORD $0xf3c7073c // vbic.i32 d16,#0xfc000000
WORD $0xf3f8c47a // vsri.u32 q14,q13,#8
WORD $0xf23cc848 // vadd.i64 q6,q6,q4
WORD $0xf2f2a57a // vshl.u32 q13,q13,#18
WORD $0xf387a73c // vbic.i32 d10,#0xfc000000
WORD $0xf2e6e832 // vshrn.u64 d30,q9,#26
WORD $0xf3fa2222 // vmovn.i64 d18,q9
WORD $0xf3a680dc // vshr.u64 q4,q6,#26
WORD $0xf3bac20c // vmovn.i64 d12,q6
WORD $0xf23ee848 // vadd.i64 q7,q7,q4
WORD $0xf3f2a478 // vsri.u32 q13,q12,#14
WORD $0xf3c7273c // vbic.i32 d18,#0xfc000000
WORD $0xf2ec8578 // vshl.u32 q12,q12,#12
WORD $0xf387c73c // vbic.i32 d12,#0xfc000000
WORD $0xf22aa82e // vadd.i32 d10,d10,d30
WORD $0xf2e2e53e // vshl.u32 d30,d30,#2
WORD $0xf3c7a77c // vbic.i32 q13,#0xfc000000
WORD $0xf2a6881e // vshrn.u64 d8,q7,#26
WORD $0xf3bae20e // vmovn.i64 d14,q7
WORD $0xf3aaa02e // vaddl.u32 q5,d10,d30
WORD $0xf3ec8476 // vsri.u32 q12,q11,#20
WORD $0xf2600888 // vadd.i32 d16,d16,d8
WORD $0xf2e66576 // vshl.u32 q11,q11,#6
WORD $0xf387e73c // vbic.i32 d14,#0xfc000000
WORD $0xf3c7877c // vbic.i32 q12,#0xfc000000
WORD $0xf2e6e81a // vshrn.u64 d30,q5,#26
WORD $0xf3baa20a // vmovn.i64 d10,q5
WORD $0xf3e66474 // vsri.u32 q11,q10,#26
WORD $0xf3c7477c // vbic.i32 q10,#0xfc000000
WORD $0xf3a68030 // vshr.u32 d8,d16,#26
WORD $0xf3c7073c // vbic.i32 d16,#0xfc000000
WORD $0xf387a73c // vbic.i32 d10,#0xfc000000
WORD $0xf22cc82e // vadd.i32 d12,d12,d30
WORD $0xf2622888 // vadd.i32 d18,d18,d8
WORD $0xf3c7677c // vbic.i32 q11,#0xfc000000
B.HI lb_Loop_neon
lb_Lskip_loop:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// multiply (inp[0:1]+hash) or inp[2:3] by r^2:r^1
ADD $(48+0*9*4), R0, R7
ADD $(48+1*9*4), R0, R6
ADD.S $32, R2, R2
MOVW.NE $0, R2
B.NE lb_Long_tail
WORD $0xf268988e // vadd.i32 d25,d24,d14
WORD $0xf264588a // vadd.i32 d21,d20,d10
WORD $0xf26ab8a0 // vadd.i32 d27,d26,d16
WORD $0xf266788c // vadd.i32 d23,d22,d12
WORD $0xf26cd8a2 // vadd.i32 d29,d28,d18
lb_Long_tail:
WORD $0xf4a70b8d // vld4.32 {d0[1],d1[1],d2[1],d3[1]},[r7]!
WORD $0xf4a60b0d // vld4.32 {d0[0],d1[0],d2[0],d3[0]},[r6]!
WORD $0xf268888e // vadd.i32 d24,d24,d14
WORD $0xf3a9ec80 // vmull.u32 q7,d25,d0
WORD $0xf264488a // vadd.i32 d20,d20,d10
WORD $0xf3a5ac80 // vmull.u32 q5,d21,d0
WORD $0xf26aa8a0 // vadd.i32 d26,d26,d16
WORD $0xf3eb0c80 // vmull.u32 q8,d27,d0
WORD $0xf266688c // vadd.i32 d22,d22,d12
WORD $0xf3a7cc80 // vmull.u32 q6,d23,d0
WORD $0xf26cc8a2 // vadd.i32 d28,d28,d18
WORD $0xf3ed2c80 // vmull.u32 q9,d29,d0
WORD $0xf3ada882 // vmlal.u32 q5,d29,d2
WORD $0xf4a74b8d // vld4.32 {d4[1],d5[1],d6[1],d7[1]},[r7]!
WORD $0xf3e90881 // vmlal.u32 q8,d25,d1
WORD $0xf4a64b0d // vld4.32 {d4[0],d5[0],d6[0],d7[0]},[r6]!
WORD $0xf3a5c881 // vmlal.u32 q6,d21,d1
WORD $0xf3eb2881 // vmlal.u32 q9,d27,d1
WORD $0xf3a7e881 // vmlal.u32 q7,d23,d1
WORD $0xf3e70883 // vmlal.u32 q8,d23,d3
WORD $0xf4a788bf // vld1.32 d8[1],[r7,:32]
WORD $0xf3aba884 // vmlal.u32 q5,d27,d4
WORD $0xf4a6883f // vld1.32 d8[0],[r6,:32]
WORD $0xf3e92883 // vmlal.u32 q9,d25,d3
WORD $0xf3adc884 // vmlal.u32 q6,d29,d4
WORD $0xf3a5e883 // vmlal.u32 q7,d21,d3
WORD $0xf3e50885 // vmlal.u32 q8,d21,d5
ADD.NE $(48+2*9*4), R0, R7
WORD $0xf3a9a886 // vmlal.u32 q5,d25,d6
ADD.NE $(48+3*9*4), R0, R6
WORD $0xf3e72885 // vmlal.u32 q9,d23,d5
WORD $0xf3abc886 // vmlal.u32 q6,d27,d6
WORD $0xf3ade886 // vmlal.u32 q7,d29,d6
WORD $0xf3ed0888 // vmlal.u32 q8,d29,d8
WORD $0xf2300150 // vorn q0,q0,q0
WORD $0xf3a7a888 // vmlal.u32 q5,d23,d8
WORD $0xf39a00d0 // vshr.u64 q0,q0,#38
WORD $0xf3e52887 // vmlal.u32 q9,d21,d7
WORD $0xf3a9c888 // vmlal.u32 q6,d25,d8
WORD $0xf3abe888 // vmlal.u32 q7,d27,d8
B.EQ lb_Lshort_tail
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// (hash+inp[0:1])*r^4:r^3 and accumulate
WORD $0xf4a70b8d // vld4.32 {d0[1],d1[1],d2[1],d3[1]},[r7]!
WORD $0xf4a60b0d // vld4.32 {d0[0],d1[0],d2[0],d3[0]},[r6]!
WORD $0xf3a8e880 // vmlal.u32 q7,d24,d0
WORD $0xf3a4a880 // vmlal.u32 q5,d20,d0
WORD $0xf3ea0880 // vmlal.u32 q8,d26,d0
WORD $0xf3a6c880 // vmlal.u32 q6,d22,d0
WORD $0xf3ec2880 // vmlal.u32 q9,d28,d0
WORD $0xf3aca882 // vmlal.u32 q5,d28,d2
WORD $0xf4a74b8d // vld4.32 {d4[1],d5[1],d6[1],d7[1]},[r7]!
WORD $0xf3e80881 // vmlal.u32 q8,d24,d1
WORD $0xf4a64b0d // vld4.32 {d4[0],d5[0],d6[0],d7[0]},[r6]!
WORD $0xf3a4c881 // vmlal.u32 q6,d20,d1
WORD $0xf3ea2881 // vmlal.u32 q9,d26,d1
WORD $0xf3a6e881 // vmlal.u32 q7,d22,d1
WORD $0xf3e60883 // vmlal.u32 q8,d22,d3
WORD $0xf4a788bf // vld1.32 d8[1],[r7,:32]
WORD $0xf3aaa884 // vmlal.u32 q5,d26,d4
WORD $0xf4a6883f // vld1.32 d8[0],[r6,:32]
WORD $0xf3e82883 // vmlal.u32 q9,d24,d3
WORD $0xf3acc884 // vmlal.u32 q6,d28,d4
WORD $0xf3a4e883 // vmlal.u32 q7,d20,d3
WORD $0xf3e40885 // vmlal.u32 q8,d20,d5
WORD $0xf3a8a886 // vmlal.u32 q5,d24,d6
WORD $0xf3e62885 // vmlal.u32 q9,d22,d5
WORD $0xf3aac886 // vmlal.u32 q6,d26,d6
WORD $0xf3ace886 // vmlal.u32 q7,d28,d6
WORD $0xf3ec0888 // vmlal.u32 q8,d28,d8
WORD $0xf2300150 // vorn q0,q0,q0
WORD $0xf3a6a888 // vmlal.u32 q5,d22,d8
WORD $0xf39a00d0 // vshr.u64 q0,q0,#38
WORD $0xf3e42887 // vmlal.u32 q9,d20,d7
WORD $0xf3a8c888 // vmlal.u32 q6,d24,d8
WORD $0xf3aae888 // vmlal.u32 q7,d26,d8
lb_Lshort_tail:
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// horizontal addition
WORD $0xf27008a1 // vadd.i64 d16,d16,d17
WORD $0xf23aa80b // vadd.i64 d10,d10,d11
WORD $0xf27228a3 // vadd.i64 d18,d18,d19
WORD $0xf23cc80d // vadd.i64 d12,d12,d13
WORD $0xf23ee80f // vadd.i64 d14,d14,d15
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// lazy reduction, but without narrowing
WORD $0xf3e6e0f0 // vshr.u64 q15,q8,#26
WORD $0xf24001d0 // vand.i64 q8,q8,q0
WORD $0xf3a680da // vshr.u64 q4,q5,#26
WORD $0xf20aa150 // vand.i64 q5,q5,q0
WORD $0xf27228ee // vadd.i64 q9,q9,q15
WORD $0xf23cc848 // vadd.i64 q6,q6,q4
WORD $0xf3e6e0f2 // vshr.u64 q15,q9,#26
WORD $0xf24221d0 // vand.i64 q9,q9,q0
WORD $0xf3a680dc // vshr.u64 q4,q6,#26
WORD $0xf20cc150 // vand.i64 q6,q6,q0
WORD $0xf23ee848 // vadd.i64 q7,q7,q4
WORD $0xf23aa86e // vadd.i64 q5,q5,q15
WORD $0xf2c2e5fe // vshl.u64 q15,q15,#2
WORD $0xf3a680de // vshr.u64 q4,q7,#26
WORD $0xf20ee150 // vand.i64 q7,q7,q0
WORD $0xf23aa86e // vadd.i64 q5,q5,q15
WORD $0xf27008c8 // vadd.i64 q8,q8,q4
WORD $0xf3e6e0da // vshr.u64 q15,q5,#26
WORD $0xf20aa150 // vand.i64 q5,q5,q0
WORD $0xf3a680f0 // vshr.u64 q4,q8,#26
WORD $0xf24001d0 // vand.i64 q8,q8,q0
WORD $0xf23cc86e // vadd.i64 q6,q6,q15
WORD $0xf27228c8 // vadd.i64 q9,q9,q4
CMP $0, R2
B.NE lb_Leven
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// store hash value
WORD $0xf480ab4d // vst4.32 {d10[0],d12[0],d14[0],d16[0]},[r0]!
WORD $0xf4c0280f // vst1.32 {d18[0]},[r0]
RET
lb_LOPENSSL_armcap: