// Copyright 2009 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. | |
TEXT ·IndexByte(SB),7,$0 | |
MOVQ p+0(FP), SI | |
MOVL len+8(FP), BX | |
MOVB b+16(FP), AL | |
MOVQ SI, DI | |
CMPL BX, $16 | |
JLT small | |
// round up to first 16-byte boundary | |
TESTQ $15, SI | |
JZ aligned | |
MOVQ SI, CX | |
ANDQ $~15, CX | |
ADDQ $16, CX | |
// search the beginning | |
SUBQ SI, CX | |
REPN; SCASB | |
JZ success | |
// DI is 16-byte aligned; get ready to search using SSE instructions | |
aligned: | |
// round down to last 16-byte boundary | |
MOVQ BX, R11 | |
ADDQ SI, R11 | |
ANDQ $~15, R11 | |
// shuffle X0 around so that each byte contains c | |
MOVD AX, X0 | |
PUNPCKLBW X0, X0 | |
PUNPCKLBW X0, X0 | |
PSHUFL $0, X0, X0 | |
JMP condition | |
sse: | |
// move the next 16-byte chunk of the buffer into X1 | |
MOVO (DI), X1 | |
// compare bytes in X0 to X1 | |
PCMPEQB X0, X1 | |
// take the top bit of each byte in X1 and put the result in DX | |
PMOVMSKB X1, DX | |
TESTL DX, DX | |
JNZ ssesuccess | |
ADDQ $16, DI | |
condition: | |
CMPQ DI, R11 | |
JLT sse | |
// search the end | |
MOVQ SI, CX | |
ADDQ BX, CX | |
SUBQ R11, CX | |
// if CX == 0, the zero flag will be set and we'll end up | |
// returning a false success | |
JZ failure | |
REPN; SCASB | |
JZ success | |
failure: | |
MOVL $-1, ret+24(FP) | |
RET | |
// handle for lengths < 16 | |
small: | |
MOVL BX, CX | |
REPN; SCASB | |
JZ success | |
MOVL $-1, ret+24(FP) | |
RET | |
// we've found the chunk containing the byte | |
// now just figure out which specific byte it is | |
ssesuccess: | |
// get the index of the least significant set bit | |
BSFW DX, DX | |
SUBQ SI, DI | |
ADDQ DI, DX | |
MOVL DX, ret+24(FP) | |
RET | |
success: | |
SUBQ SI, DI | |
SUBL $1, DI | |
MOVL DI, ret+24(FP) | |
RET | |