| // Copyright 2016 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. |
| |
| // +build !appengine |
| // +build gc |
| // +build !noasm |
| |
| #include "textflag.h" |
| |
| // The asm code generally follows the pure Go code in encode_other.go, except |
| // where marked with a "!!!". |
| |
| // func extendMatch(src []byte, i, j int) int |
| // |
| // All local variables fit into registers. The register allocation: |
| // - CX &src[0] |
| // - DX &src[len(src)] |
| // - SI &src[i] |
| // - DI &src[j] |
| // - R9 &src[len(src) - 8] |
| TEXT ·extendMatch(SB), NOSPLIT, $0-48 |
| MOVQ src_base+0(FP), CX |
| MOVQ src_len+8(FP), DX |
| MOVQ i+24(FP), SI |
| MOVQ j+32(FP), DI |
| ADDQ CX, DX |
| ADDQ CX, SI |
| ADDQ CX, DI |
| MOVQ DX, R9 |
| SUBQ $8, R9 |
| |
| cmp8: |
| // As long as we are 8 or more bytes before the end of src, we can load and |
| // compare 8 bytes at a time. If those 8 bytes are equal, repeat. |
| CMPQ DI, R9 |
| JA cmp1 |
| MOVQ (SI), AX |
| MOVQ (DI), BX |
| CMPQ AX, BX |
| JNE bsf |
| ADDQ $8, SI |
| ADDQ $8, DI |
| JMP cmp8 |
| |
| bsf: |
| // If those 8 bytes were not equal, XOR the two 8 byte values, and return |
| // the index of the first byte that differs. The BSF instruction finds the |
| // least significant 1 bit, the amd64 architecture is little-endian, and |
| // the shift by 3 converts a bit index to a byte index. |
| XORQ AX, BX |
| BSFQ BX, BX |
| SHRQ $3, BX |
| ADDQ BX, DI |
| |
| // Convert from &src[ret] to ret. |
| SUBQ CX, DI |
| MOVQ DI, ret+40(FP) |
| RET |
| |
| cmp1: |
| // In src's tail, compare 1 byte at a time. |
| CMPQ DI, DX |
| JAE end |
| MOVB (SI), AX |
| MOVB (DI), BX |
| CMPB AX, BX |
| JNE end |
| ADDQ $1, SI |
| ADDQ $1, DI |
| JMP cmp1 |
| |
| end: |
| // Convert from &src[ret] to ret. |
| SUBQ CX, DI |
| MOVQ DI, ret+40(FP) |
| RET |