blob: 8bc290da061dd92a979a67262fe29faf623b5647 [file]
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#include "go_asm.h"
#include "textflag.h"
// memequal_varlen(a, b unsafe.Pointer) bool
TEXT runtime·memequal_varlen<ABIInternal>(SB),NOSPLIT,$0-17
MOVD 8(R26), R2 // compiler stores size at offset 8 in the closure
CBZ R2, eq
B runtime·memequal<ABIInternal>(SB)
eq:
MOVD $1, R0
RET
// input:
// R0: pointer a
// R1: pointer b
// R2: data len
// at return: result in R0
// memequal(a, b unsafe.Pointer, size uintptr) bool
TEXT runtime·memequal<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-25
// short path to handle 0-byte case
CBZ R2, equal
// short path to handle equal pointers
CMP R0, R1
BEQ equal
CMP $1, R2
// handle 1-byte special case for better performance
BEQ one
CMP $16, R2
// handle specially if length < 16
BLO tail
CMP $33, R2
BHS large
pairwise_16_32:
// use pairwise loads for 16 <= len <= 32
LDP (R0), (R16, R17)
LDP (R1), (R24, R26)
CMP R16, R24
CCMP EQ, R17, R26, $0
BNE not_equal
SUB $16, R2, R16
CBZ R16, equal
ADD R0, R16, R24
ADD R1, R16, R25
LDP (R24), (R16, R17)
LDP (R25), (R24, R26)
CMP R16, R24
CCMP EQ, R17, R26, $0
CSET EQ, R0
RET
PCALIGN $16
tail:
// special compare of tail with length < 16
TBZ $3, R2, lt_8
MOVD (R0), R16
MOVD (R1), R17
CMP R16, R17
BNE not_equal
SUB $8, R2, R26 // offset of the last 8 bytes
MOVD (R0)(R26), R16
MOVD (R1)(R26), R17
CMP R16, R17
CSET EQ, R0
RET
PCALIGN $16
lt_8:
TBZ $2, R2, lt_4
MOVWU (R0), R16
MOVWU (R1), R17
CMP R16, R17
BNE not_equal
SUB $4, R2, R26 // offset of the last 4 bytes
MOVWU (R0)(R26), R16
MOVWU (R1)(R26), R17
CMP R16, R17
CSET EQ, R0
RET
PCALIGN $16
lt_4:
TBZ $1, R2, lt_2
MOVHU.P 2(R0), R16
MOVHU.P 2(R1), R17
CMP R16, R17
BNE not_equal
lt_2:
TBZ $0, R2, equal
one:
MOVBU (R0), R16
MOVBU (R1), R17
CMP R16, R17
BNE not_equal
equal:
MOVD $1, R0
RET
not_equal:
MOVB ZR, R0
RET
large:
BIC $0x3f, R2, R26
CBZ R26, remainder_33_64
// work with 64-byte chunks
ADD R0, R26 // end of chunks
chunk64_loop:
VLD1.P (R0), [V21.D2, V22.D2, V23.D2, V24.D2]
VLD1.P (R1), [V25.D2, V26.D2, V27.D2, V28.D2]
VCMEQ V21.D2, V25.D2, V21.D2
VCMEQ V22.D2, V26.D2, V22.D2
VCMEQ V23.D2, V27.D2, V23.D2
VCMEQ V24.D2, V28.D2, V24.D2
VAND V21.B16, V22.B16, V21.B16
VAND V23.B16, V24.B16, V23.B16
VAND V21.B16, V23.B16, V21.B16
CMP R0, R26
VMOV V21.D[0], R16
VMOV V21.D[1], R17
CBZ R16, not_equal
CBZ R17, not_equal
BNE chunk64_loop
AND $0x3f, R2, R2
CBZ R2, equal
CMP $16, R2
BLO tail
CMP $33, R2
BLO pairwise_16_32
remainder_33_64:
// 33 <= len < 64
VLD1 (R0), [V21.D2, V22.D2]
VLD1 (R1), [V23.D2, V24.D2]
SUB $32, R2, R26
ADD R0, R26, R24
ADD R1, R26, R25
VEOR V23.B16, V21.B16, V21.B16
VEOR V24.B16, V22.B16, V22.B16
VORR V22.B16, V21.B16, V21.B16
VMOV V21.D[0], R16
VMOV V21.D[1], R17
ORR R17, R16, R16
CBNZ R16, not_equal
VLD1 (R24), [V21.D2, V22.D2]
VLD1 (R25), [V23.D2, V24.D2]
VEOR V23.B16, V21.B16, V21.B16
VEOR V24.B16, V22.B16, V22.B16
VORR V22.B16, V21.B16, V21.B16
VMOV V21.D[0], R16
VMOV V21.D[1], R17
ORR R17, R16, R16
CBNZ R16, not_equal
B equal