| // 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 | |
| LEAL ret+24(FP), AX | |
| JMP cmpbody<>(SB) | |
| 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 | |
| LEAL ret+16(FP), AX | |
| JMP cmpbody<>(SB) | |
| // input: | |
| // SI = a | |
| // DI = b | |
| // BX = alen | |
| // DX = blen | |
| // AX = address of return word (set to 1/0/-1) | |
| TEXT cmpbody<>(SB),NOSPLIT,$0-0 | |
| MOVL DX, BP | |
| SUBL BX, DX // DX = blen-alen | |
| JLE 2(PC) | |
| MOVL BX, BP // BP = min(alen, blen) | |
| CMPL SI, DI | |
| JEQ allsame | |
| CMPL BP, $4 | |
| JB small | |
| #ifdef GO386_softfloat | |
| JMP mediumloop | |
| #endif | |
| largeloop: | |
| CMPL BP, $16 | |
| JB mediumloop | |
| MOVOU (SI), X0 | |
| MOVOU (DI), X1 | |
| PCMPEQB X0, X1 | |
| PMOVMSKB X1, BX | |
| XORL $0xffff, BX // convert EQ to NE | |
| JNE diff16 // branch if at least one byte is not equal | |
| ADDL $16, SI | |
| ADDL $16, DI | |
| SUBL $16, BP | |
| JMP largeloop | |
| diff16: | |
| BSFL BX, BX // index of first byte that differs | |
| XORL DX, DX | |
| MOVB (SI)(BX*1), CX | |
| CMPB CX, (DI)(BX*1) | |
| SETHI DX | |
| LEAL -1(DX*2), DX // convert 1/0 to +1/-1 | |
| MOVL DX, (AX) | |
| RET | |
| mediumloop: | |
| CMPL BP, $4 | |
| JBE _0through4 | |
| MOVL (SI), BX | |
| MOVL (DI), CX | |
| CMPL BX, CX | |
| JNE diff4 | |
| ADDL $4, SI | |
| ADDL $4, DI | |
| SUBL $4, BP | |
| JMP mediumloop | |
| _0through4: | |
| MOVL -4(SI)(BP*1), BX | |
| MOVL -4(DI)(BP*1), CX | |
| CMPL BX, CX | |
| JEQ allsame | |
| diff4: | |
| BSWAPL BX // reverse order of bytes | |
| BSWAPL CX | |
| XORL BX, CX // find bit differences | |
| BSRL CX, CX // index of highest bit difference | |
| SHRL CX, BX // move a's bit to bottom | |
| ANDL $1, BX // mask bit | |
| LEAL -1(BX*2), BX // 1/0 => +1/-1 | |
| MOVL BX, (AX) | |
| RET | |
| // 0-3 bytes in common | |
| small: | |
| LEAL (BP*8), CX | |
| NEGL CX | |
| JEQ allsame | |
| // load si | |
| CMPB SI, $0xfc | |
| JA si_high | |
| MOVL (SI), SI | |
| JMP si_finish | |
| si_high: | |
| MOVL -4(SI)(BP*1), SI | |
| SHRL CX, SI | |
| si_finish: | |
| SHLL CX, SI | |
| // same for di | |
| CMPB DI, $0xfc | |
| JA di_high | |
| MOVL (DI), DI | |
| JMP di_finish | |
| di_high: | |
| MOVL -4(DI)(BP*1), DI | |
| SHRL CX, DI | |
| di_finish: | |
| SHLL CX, DI | |
| BSWAPL SI // reverse order of bytes | |
| BSWAPL DI | |
| XORL SI, DI // find bit differences | |
| JEQ allsame | |
| BSRL DI, CX // index of highest bit difference | |
| SHRL CX, SI // move a's bit to bottom | |
| ANDL $1, SI // mask bit | |
| LEAL -1(SI*2), BX // 1/0 => +1/-1 | |
| MOVL BX, (AX) | |
| RET | |
| // all the bytes in common are the same, so we just need | |
| // to compare the lengths. | |
| allsame: | |
| XORL BX, BX | |
| XORL CX, CX | |
| TESTL DX, DX | |
| SETLT BX // 1 if alen > blen | |
| SETEQ CX // 1 if alen == blen | |
| LEAL -1(CX)(BX*2), BX // 1,0,-1 result | |
| MOVL BX, (AX) | |
| RET |