// 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" TEXT ·Compare(SB),NOSPLIT,$0-28 MOVL a_base+0(FP), SI MOVL a_len+4(FP), BX MOVL b_base+12(FP), DI MOVL b_len+16(FP), DX CALL cmpbody<>(SB) MOVL AX, ret+24(FP) RET TEXT runtime·cmpstring(SB),NOSPLIT,$0-20 MOVL a_base+0(FP), SI MOVL a_len+4(FP), BX MOVL b_base+8(FP), DI MOVL b_len+12(FP), DX CALL cmpbody<>(SB) MOVL AX, ret+16(FP) RET // input: // SI = a // DI = b // BX = alen // DX = blen // output: // AX = 1/0/-1 TEXT cmpbody<>(SB),NOSPLIT,$0-0 CMPQ SI, DI JEQ allsame CMPQ BX, DX MOVQ DX, R8 CMOVQLT BX, R8 // R8 = min(alen, blen) = # of bytes to compare CMPQ R8, $8 JB small loop: CMPQ R8, $16 JBE _0through16 MOVOU (SI), X0 MOVOU (DI), X1 PCMPEQB X0, X1 PMOVMSKB X1, AX XORQ $0xffff, AX // convert EQ to NE JNE diff16 // branch if at least one byte is not equal ADDQ $16, SI ADDQ $16, DI SUBQ $16, R8 JMP loop // AX = bit mask of differences diff16: BSFQ AX, BX // index of first byte that differs XORQ AX, AX ADDQ BX, SI MOVB (SI), CX ADDQ BX, DI CMPB CX, (DI) SETHI AX LEAQ -1(AX*2), AX // convert 1/0 to +1/-1 RET // 0 through 16 bytes left, alen>=8, blen>=8 _0through16: CMPQ R8, $8 JBE _0through8 MOVQ (SI), AX MOVQ (DI), CX CMPQ AX, CX JNE diff8 _0through8: ADDQ R8, SI ADDQ R8, DI MOVQ -8(SI), AX MOVQ -8(DI), CX CMPQ AX, CX JEQ allsame // AX and CX contain parts of a and b that differ. diff8: BSWAPQ AX // reverse order of bytes BSWAPQ CX XORQ AX, CX BSRQ CX, CX // index of highest bit difference SHRQ CX, AX // move a's bit to bottom ANDQ $1, AX // mask bit LEAQ -1(AX*2), AX // 1/0 => +1/-1 RET // 0-7 bytes in common small: LEAQ (R8*8), CX // bytes left -> bits left NEGQ CX // - bits lift (== 64 - bits left mod 64) JEQ allsame // load bytes of a into high bytes of AX CMPB SI, $0xf8 JA si_high MOVQ (SI), SI JMP si_finish si_high: ADDQ R8, SI MOVQ -8(SI), SI SHRQ CX, SI si_finish: SHLQ CX, SI // load bytes of b in to high bytes of BX CMPB DI, $0xf8 JA di_high MOVQ (DI), DI JMP di_finish di_high: ADDQ R8, DI MOVQ -8(DI), DI SHRQ CX, DI di_finish: SHLQ CX, DI BSWAPQ SI // reverse order of bytes BSWAPQ DI XORQ SI, DI // find bit differences JEQ allsame BSRQ DI, CX // index of highest bit difference SHRQ CX, SI // move a's bit to bottom ANDQ $1, SI // mask bit LEAQ -1(SI*2), AX // 1/0 => +1/-1 RET allsame: XORQ AX, AX XORQ CX, CX CMPQ BX, DX SETGT AX // 1 if alen > blen SETEQ CX // 1 if alen == blen LEAQ -1(CX)(AX*2), AX // 1,0,-1 result RET