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