/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1986,1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:index.s 12.0$ */
/* $ACIS:index.s 12.0$ */
/* $Source: /ibm/acis/usr/src/lib/libc/ca/gen/RCS/index.s,v $ */

	.data
rcsid:	.asciz	"$Header:index.s 12.0$"
	.text

#include "LINKG.h"

/*
 * version of index written in assembler for speed
 *	index(string, c) char *string, c;
 */

/* Registers containing 4 possible values of 'c' in a word.
 * mask byte 0	r0
 * mask	byte 1	r4
 * mask byte 2	r5
 * mask byte 3	r3	(r3 is an input parameter, used as a tmp later)
 */

ENTRY(index)
	put	r6,-4(sp)	# r6 is a tmp register.
	mr	r0,r3		# r0(000c) <- c
	sli16	r0,8		# r0(c000) <- r0 << 24
	mr	r4,r3		# r4(000c) <- c
	slpi	r4,8		# r5(00c0) <- r4 << 8
	sli16	r4,0		# r4(0c00) <- r4 << 16

	nilz	r6,r2,0x03	# Round string addr down to word boundary
	s	r2,r6		# More of the rounding
	mr	r3,r6		# r3 is a tmp reg from now on.
	sli	r6,3		# n = n * 8
	a	r6,r3		# n = n * 9
	a	r6,r3		# n = n * 10
	get	r3,$0f		# get address of beginning of switch statement
	a	r3,r6		# calc branch address
	brx	r3		# branch to calculated case and
	ls	r3,0(r2)	# get first word (possibly rounded down).
 # at this point:
 # r2 points to string or the nearest word boundary before string.
 # r4 contains 4 byes with string's initial bytes somewhere in r2
 # Other tmp registers contain masks for the various positions of
 # 'c' in a register.
 # The following is a switch statement. Initially, control jumps to one of
 # the labels 0, 1, 2 or 3 depending on where string's first byte is in r2
 # 
9:	inc	r2,4		# point to next word
 # code at 0f, 1f, 2f must be exactly 10 bytes long to match switch above
0:
	niuz	r6,r3,0xff00	# get byte 0 from r3		(4)
	jeq	Lret0		# branch if byte 0 is null	(2)
	c	r6,r0		# r6 == r0(c000)		(2)
	jeq	0f		#				(2)

1:
	niuz	r6,r3,0x00ff	# get byte 1 from r3
	jeq	Lret1		# branch if byte 1 is null
	c	r6,r4		# r6 == r4(0c00)
	jeq	1f

2:
	nilz	r6,r3,0xff00	# get byte 2 from r3
	jeq	Lret2		# branch if byte 2 is null
	c	r6,r5		# r6 == r5(00c0)
	jeq	2f

3:
	sli16	r3,8		# r3(c000) <- r3(000c) << 24
	jeq	Lret3		# branch if byte 3 is null
	c	r3,r0		# r3 == r0(c000)
	bnex	9b
	 ls	r3,4(r2)	#	pick up next data value

 # Jackpot, found 'c'. adjust pointer to correct position and
3:	inc	r2,1
2:	inc	r2,1
1:	inc	r2,1
0:
	brx	r15	# return while restoring r6
 	get	r6,-4(sp)

 # Jackpot? only if 'c' is zero.
Lret3:
	cis	r0,0
	jne	Lnotfound
	inc	r2,1
Lret2:
	cis	r0,0
	jne	Lnotfound
	inc	r2,1
Lret1:
	cis	r0,0
	jne	Lnotfound
	inc	r2,1
Lret0:
	cis	r0,0
	jne	Lnotfound

	brx	r15		# Jackpot: 'c' was the zero character
	get	r6,-4(sp)

Lnotfound:			# no dice
	get	r2,$0
	brx	r15		# return zero while restoring r6
 	get	r6,-4(sp)

	TTNOFRM
