strings: use runtime assembly for IndexByte

Fixes #3751

R=golang-dev, khr
CC=golang-dev
https://golang.org/cl/12483043
diff --git a/src/pkg/runtime/asm_386.s b/src/pkg/runtime/asm_386.s
index f6204ac..863bcc3 100644
--- a/src/pkg/runtime/asm_386.s
+++ b/src/pkg/runtime/asm_386.s
@@ -504,7 +504,7 @@
 // so actually
 // void atomicload64(uint64 *res, uint64 volatile *addr);
 TEXT runtime·atomicload64(SB), 7, $0-8
-	MOVL    4(SP), BX
+	MOVL	4(SP), BX
 	MOVL	8(SP), AX
 	// MOVQ (%EAX), %MM0
 	BYTE $0x0f; BYTE $0x6f; BYTE $0x00
@@ -1220,6 +1220,20 @@
 	MOVL	DI, ret+16(FP)
 	RET
 
+TEXT strings·IndexByte(SB),7,$0
+	MOVL	s+0(FP), SI
+	MOVL	s_len+4(FP), CX
+	MOVB	c+8(FP), AL
+	MOVL	SI, DI
+	CLD; REPN; SCASB
+	JZ 3(PC)
+	MOVL	$-1, ret+12(FP)
+	RET
+	SUBL	SI, DI
+	SUBL	$1, DI
+	MOVL	DI, ret+12(FP)
+	RET
+
 // input:
 //   SI = a
 //   DI = b
diff --git a/src/pkg/runtime/asm_amd64.s b/src/pkg/runtime/asm_amd64.s
index d22c645..8cb06d9 100644
--- a/src/pkg/runtime/asm_amd64.s
+++ b/src/pkg/runtime/asm_amd64.s
@@ -1224,6 +1224,25 @@
 	MOVQ s+0(FP), SI
 	MOVQ s_len+8(FP), BX
 	MOVB c+24(FP), AL
+	CALL runtime·indexbytebody(SB)
+	MOVQ AX, ret+32(FP)
+	RET
+
+TEXT strings·IndexByte(SB),7,$0
+	MOVQ s+0(FP), SI
+	MOVQ s_len+8(FP), BX
+	MOVB c+16(FP), AL
+	CALL runtime·indexbytebody(SB)
+	MOVQ AX, ret+24(FP)
+	RET
+
+// input:
+//   SI: data
+//   BX: data len
+//   AL: byte sought
+// output:
+//   AX
+TEXT runtime·indexbytebody(SB),7,$0
 	MOVQ SI, DI
 
 	CMPQ BX, $16
@@ -1281,7 +1300,7 @@
 	JZ success
 
 failure:
-	MOVQ $-1, ret+32(FP)
+	MOVQ $-1, AX
 	RET
 
 // handle for lengths < 16
@@ -1289,7 +1308,7 @@
 	MOVQ BX, CX
 	REPN; SCASB
 	JZ success
-	MOVQ $-1, ret+32(FP)
+	MOVQ $-1, AX
 	RET
 
 // we've found the chunk containing the byte
@@ -1299,13 +1318,13 @@
 	BSFW DX, DX
 	SUBQ SI, DI
 	ADDQ DI, DX
-	MOVQ DX, ret+32(FP)
+	MOVQ DX, AX
 	RET
 
 success:
 	SUBQ SI, DI
 	SUBL $1, DI
-	MOVQ DI, ret+32(FP)
+	MOVQ DI, AX
 	RET
 
 TEXT bytes·Equal(SB),7,$0-49
diff --git a/src/pkg/runtime/asm_arm.s b/src/pkg/runtime/asm_arm.s
index b7c95fe..313e7b8 100644
--- a/src/pkg/runtime/asm_arm.s
+++ b/src/pkg/runtime/asm_arm.s
@@ -667,3 +667,27 @@
 	MOVW	$-1, R0
 	MOVW	R0, ret+16(FP)
 	RET
+
+TEXT strings·IndexByte(SB),7,$0
+	MOVW	s+0(FP), R0
+	MOVW	s_len+4(FP), R1
+	MOVBU	c+8(FP), R2	// byte to find
+	MOVW	R0, R4		// store base for later
+	ADD	R0, R1		// end 
+
+_sib_loop:
+	CMP	R0, R1
+	B.EQ	_sib_notfound
+	MOVBU.P	1(R0), R3
+	CMP	R2, R3
+	B.NE	_sib_loop
+
+	SUB	$1, R0		// R0 will be one beyond the position we want
+	SUB	R4, R0		// remove base
+	MOVW	R0, ret+12(FP) 
+	RET
+
+_sib_notfound:
+	MOVW	$-1, R0
+	MOVW	R0, ret+12(FP)
+	RET
diff --git a/src/pkg/strings/strings.go b/src/pkg/strings/strings.go
index c7ec04b..4d33f1e 100644
--- a/src/pkg/strings/strings.go
+++ b/src/pkg/strings/strings.go
@@ -160,16 +160,6 @@
 	return -1
 }
 
-// IndexByte returns the index of the first instance of c in s, or -1 if c is not present in s.
-func IndexByte(s string, c byte) int {
-	for i := 0; i < len(s); i++ {
-		if s[i] == c {
-			return i
-		}
-	}
-	return -1
-}
-
 // LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s.
 func LastIndex(s, sep string) int {
 	n := len(sep)
diff --git a/src/pkg/strings/strings.s b/src/pkg/strings/strings.s
new file mode 100644
index 0000000..55103ba
--- /dev/null
+++ b/src/pkg/strings/strings.s
@@ -0,0 +1,5 @@
+// Copyright 2013 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.
+
+// This file is here just to make the go tool happy.
diff --git a/src/pkg/strings/strings_decl.go b/src/pkg/strings/strings_decl.go
new file mode 100644
index 0000000..810a696
--- /dev/null
+++ b/src/pkg/strings/strings_decl.go
@@ -0,0 +1,8 @@
+// Copyright 2013 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.
+
+package strings
+
+// IndexByte returns the index of the first instance of c in s, or -1 if c is not present in s.
+func IndexByte(s string, c byte) int // ../runtime/asm_$GOARCH.s