github.com/sandwichdev/go-internals@v0.0.0-20210605002614-12311ac6b2c5/bytealg/compare_386.s (about)

     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(SB),NOSPLIT,$0-28
     9  	MOVL	a_base+0(FP), SI
    10  	MOVL	a_len+4(FP), BX
    11  	MOVL	b_base+12(FP), DI
    12  	MOVL	b_len+16(FP), DX
    13  	LEAL	ret+24(FP), AX
    14  	JMP	cmpbody<>(SB)
    15  
    16  TEXT runtime·cmpstring(SB),NOSPLIT,$0-20
    17  	MOVL	a_base+0(FP), SI
    18  	MOVL	a_len+4(FP), BX
    19  	MOVL	b_base+8(FP), DI
    20  	MOVL	b_len+12(FP), DX
    21  	LEAL	ret+16(FP), AX
    22  	JMP	cmpbody<>(SB)
    23  
    24  // input:
    25  //   SI = a
    26  //   DI = b
    27  //   BX = alen
    28  //   DX = blen
    29  //   AX = address of return word (set to 1/0/-1)
    30  TEXT cmpbody<>(SB),NOSPLIT,$0-0
    31  	MOVL	DX, BP
    32  	SUBL	BX, DX // DX = blen-alen
    33  	JLE	2(PC)
    34  	MOVL	BX, BP // BP = min(alen, blen)
    35  	CMPL	SI, DI
    36  	JEQ	allsame
    37  	CMPL	BP, $4
    38  	JB	small
    39  	CMPB	internal∕cpu·X86+const_offsetX86HasSSE2(SB), $1
    40  	JNE	mediumloop
    41  largeloop:
    42  	CMPL	BP, $16
    43  	JB	mediumloop
    44  	MOVOU	(SI), X0
    45  	MOVOU	(DI), X1
    46  	PCMPEQB X0, X1
    47  	PMOVMSKB X1, BX
    48  	XORL	$0xffff, BX	// convert EQ to NE
    49  	JNE	diff16	// branch if at least one byte is not equal
    50  	ADDL	$16, SI
    51  	ADDL	$16, DI
    52  	SUBL	$16, BP
    53  	JMP	largeloop
    54  
    55  diff16:
    56  	BSFL	BX, BX	// index of first byte that differs
    57  	XORL	DX, DX
    58  	MOVB	(SI)(BX*1), CX
    59  	CMPB	CX, (DI)(BX*1)
    60  	SETHI	DX
    61  	LEAL	-1(DX*2), DX	// convert 1/0 to +1/-1
    62  	MOVL	DX, (AX)
    63  	RET
    64  
    65  mediumloop:
    66  	CMPL	BP, $4
    67  	JBE	_0through4
    68  	MOVL	(SI), BX
    69  	MOVL	(DI), CX
    70  	CMPL	BX, CX
    71  	JNE	diff4
    72  	ADDL	$4, SI
    73  	ADDL	$4, DI
    74  	SUBL	$4, BP
    75  	JMP	mediumloop
    76  
    77  _0through4:
    78  	MOVL	-4(SI)(BP*1), BX
    79  	MOVL	-4(DI)(BP*1), CX
    80  	CMPL	BX, CX
    81  	JEQ	allsame
    82  
    83  diff4:
    84  	BSWAPL	BX	// reverse order of bytes
    85  	BSWAPL	CX
    86  	XORL	BX, CX	// find bit differences
    87  	BSRL	CX, CX	// index of highest bit difference
    88  	SHRL	CX, BX	// move a's bit to bottom
    89  	ANDL	$1, BX	// mask bit
    90  	LEAL	-1(BX*2), BX // 1/0 => +1/-1
    91  	MOVL	BX, (AX)
    92  	RET
    93  
    94  	// 0-3 bytes in common
    95  small:
    96  	LEAL	(BP*8), CX
    97  	NEGL	CX
    98  	JEQ	allsame
    99  
   100  	// load si
   101  	CMPB	SI, $0xfc
   102  	JA	si_high
   103  	MOVL	(SI), SI
   104  	JMP	si_finish
   105  si_high:
   106  	MOVL	-4(SI)(BP*1), SI
   107  	SHRL	CX, SI
   108  si_finish:
   109  	SHLL	CX, SI
   110  
   111  	// same for di
   112  	CMPB	DI, $0xfc
   113  	JA	di_high
   114  	MOVL	(DI), DI
   115  	JMP	di_finish
   116  di_high:
   117  	MOVL	-4(DI)(BP*1), DI
   118  	SHRL	CX, DI
   119  di_finish:
   120  	SHLL	CX, DI
   121  
   122  	BSWAPL	SI	// reverse order of bytes
   123  	BSWAPL	DI
   124  	XORL	SI, DI	// find bit differences
   125  	JEQ	allsame
   126  	BSRL	DI, CX	// index of highest bit difference
   127  	SHRL	CX, SI	// move a's bit to bottom
   128  	ANDL	$1, SI	// mask bit
   129  	LEAL	-1(SI*2), BX // 1/0 => +1/-1
   130  	MOVL	BX, (AX)
   131  	RET
   132  
   133  	// all the bytes in common are the same, so we just need
   134  	// to compare the lengths.
   135  allsame:
   136  	XORL	BX, BX
   137  	XORL	CX, CX
   138  	TESTL	DX, DX
   139  	SETLT	BX	// 1 if alen > blen
   140  	SETEQ	CX	// 1 if alen == blen
   141  	LEAL	-1(CX)(BX*2), BX	// 1,0,-1 result
   142  	MOVL	BX, (AX)
   143  	RET