Text file src/internal/bytealg/compare_arm64.s

     1  // Copyright 2018 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  #include "go_asm.h"
     6  #include "textflag.h"
     7  
     8  TEXT ·Compare<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-56
     9  	// R0 = a_base (want in R0)
    10  	// R1 = a_len  (want in R1)
    11  	// R2 = a_cap  (unused)
    12  	// R3 = b_base (want in R2)
    13  	// R4 = b_len  (want in R3)
    14  	// R5 = b_cap  (unused)
    15  	MOVD	R3, R2
    16  	MOVD	R4, R3
    17  	B	cmpbody<>(SB)
    18  
    19  TEXT runtime·cmpstring<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-40
    20  	// R0 = a_base
    21  	// R1 = a_len
    22  	// R2 = b_base
    23  	// R3 = b_len
    24  	B	cmpbody<>(SB)
    25  
    26  // On entry:
    27  // R0 points to the start of a
    28  // R1 is the length of a
    29  // R2 points to the start of b
    30  // R3 is the length of b
    31  //
    32  // On exit:
    33  // R0 is the result
    34  // R4, R5, R6, R8, R9, R10 and V0-V11 are clobbered
    35  TEXT cmpbody<>(SB),NOSPLIT|NOFRAME,$0-0
    36  	CMP	R0, R2
    37  	BEQ	samebytes         // same starting pointers; compare lengths
    38  	CMP	R1, R3
    39  	CSEL	LT, R3, R1, R6    // R6 is min(R1, R3)
    40  
    41  	CBZ	R6, samebytes
    42  	BIC	$0x3f, R6, R10
    43  	CBZ	R10, less_than_64 // length < 64, use scalar path
    44  	ADD	R0, R10           // end of 64-byte chunks
    45  
    46  	// Process 64 bytes per iteration using NEON.
    47  	// Compare 4x16-byte chunks and reduce the result to a single byte.
    48  	// On mismatch, rewind and fall back to the scalar path.
    49  	PCALIGN	$16
    50  chunk64_loop:
    51  	VLD1.P	(R0), [V0.D2, V1.D2, V2.D2, V3.D2]
    52  	VLD1.P	(R2), [V4.D2, V5.D2, V6.D2, V7.D2]
    53  	VCMEQ	V0.B16, V4.B16, V8.B16
    54  	VCMEQ	V1.B16, V5.B16, V9.B16
    55  	VCMEQ	V2.B16, V6.B16, V10.B16
    56  	VCMEQ	V3.B16, V7.B16, V11.B16
    57  	VAND	V8.B16, V9.B16, V8.B16
    58  	VAND	V10.B16, V11.B16, V10.B16
    59  	VAND	V8.B16, V10.B16, V8.B16
    60  	VUMINV	V8.B16, V8
    61  	VMOV	V8.B[0], R4
    62  	CBZ	R4, neon_mismatch
    63  	CMP	R10, R0
    64  	BNE	chunk64_loop
    65  
    66  	AND	$0x3f, R6, R6     // remaining 0-63 bytes
    67  	CBZ	R6, samebytes
    68  
    69  less_than_64:
    70  	// Scalar 16-byte loop for up to 63 bytes, then byte-level tail.
    71  	BIC	$0xf, R6, R10
    72  	CBZ	R10, small        // length < 16
    73  	ADD	R0, R10
    74  	PCALIGN	$16
    75  chunk16_loop:
    76  	LDP.P	16(R0), (R4, R8)
    77  	LDP.P	16(R2), (R5, R9)
    78  	CMP	R4, R5
    79  	BNE	cmp
    80  	CMP	R8, R9
    81  	BNE	cmpnext
    82  	CMP	R10, R0
    83  	BNE	chunk16_loop
    84  	AND	$0xf, R6, R6
    85  	CBZ	R6, samebytes
    86  	SUBS	$8, R6
    87  	BLT	tail
    88  	// the length of tail > 8 bytes
    89  	MOVD.P	8(R0), R4
    90  	MOVD.P	8(R2), R5
    91  	CMP	R4, R5
    92  	BNE	cmp
    93  	SUB	$8, R6
    94  	// compare last 8 bytes
    95  	// tail always reads the final 8-byte window at R0+R6. R6 may be
    96  	// negative here, overlapping already-verified bytes, which is harmless.
    97  tail:
    98  	MOVD	(R0)(R6), R4
    99  	MOVD	(R2)(R6), R5
   100  	CMP	R4, R5
   101  	BEQ	samebytes
   102  cmp:
   103  	REV	R4, R4
   104  	REV	R5, R5
   105  	CMP	R4, R5
   106  ret:
   107  	MOVD	$1, R0
   108  	CNEG	HI, R0, R0
   109  	RET
   110  
   111  neon_mismatch:
   112  	// A mismatch was found in the last 64-byte NEON chunk. Rewind both
   113  	// pointers and let the scalar path locate the first differing byte.
   114  	SUB	$64, R0
   115  	SUB	$64, R2
   116  	MOVD	$64, R6
   117  	B	less_than_64
   118  
   119  small:
   120  	TBZ	$3, R6, lt_8
   121  	MOVD	(R0), R4
   122  	MOVD	(R2), R5
   123  	CMP	R4, R5
   124  	BNE	cmp
   125  	SUBS	$8, R6
   126  	BEQ	samebytes
   127  	B	tail
   128  lt_8:
   129  	TBZ	$2, R6, lt_4
   130  	MOVWU	(R0), R4
   131  	MOVWU	(R2), R5
   132  	CMPW	R4, R5
   133  	BNE	cmp
   134  	SUBS	$4, R6
   135  	BEQ	samebytes
   136  	ADD	$4, R0
   137  	ADD	$4, R2
   138  lt_4:
   139  	TBZ	$1, R6, lt_2
   140  	MOVHU	(R0), R4
   141  	MOVHU	(R2), R5
   142  	CMPW	R4, R5
   143  	BNE	cmp
   144  	ADD	$2, R0
   145  	ADD	$2, R2
   146  lt_2:
   147  	TBZ	$0, R6, samebytes
   148  one:
   149  	MOVBU	(R0), R4
   150  	MOVBU	(R2), R5
   151  	CMPW	R4, R5
   152  	BNE	ret
   153  samebytes:
   154  	CMP	R3, R1
   155  	CSET	NE, R0
   156  	CNEG	LO, R0, R0
   157  	RET
   158  cmpnext:
   159  	REV	R8, R4
   160  	REV	R9, R5
   161  	CMP	R4, R5
   162  	B	ret
   163  

View as plain text