/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1986,1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */

/* $Header:rindex.s 12.0$ */
/* $ACIS:rindex.s 12.0$ */
/* $Source: /ibm/acis/usr/src/lib/libc/ca/gen/RCS/rindex.s,v $ */

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

#include "LINKG.h"

 #
 # version of rindex written in assembler for speed
 #	rindex(string, c) char *string, c;
 # 'c' may be zero to indicate a scanf for the null terminator.

 # 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(rindex)
	put	r6,-4(sp)	# r6 is a tmp register.
	put	r7,-8(sp)	# r7 keeps track of address of found 'c'
	get	r7,$0		# put default return in r7
 # set up 'c' masks
	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.
 # 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	L0		#				(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	L1

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	L2

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

 # branch to one of L{0,1,2,3} if 'c' was found.
 # set r7 to position of 'c' in string and continue processing.
 # it is assumed that 'c' is relatively rare in s, otherwise
 # performance improvements are minimal due to lots of branching.
L0:
	bx	1b
	ai	r7,r2,0
L1:
	bx	2b
	ai	r7,r2,1
L2:
	bx	3b
	ai	r7,r2,2
L3:
	ai	r7,r2,3
	bx	9b
	ls	r3,4(r2)

 # The retN labels are to handle the case of 'c' being zero.
 
Lret3:
	ci	r0,0	# if not scanning for 0
	jne	Lreturn	# 	do a return
	inc	r2,1	# else	increment r2
Lret2:
	ci	r0,0
	jne	Lreturn
	inc	r2,1
Lret1:
	ci	r0,0
	jne	Lreturn
	inc	r2,1
Lret0:
	ci	r0,0
	jne	Lreturn

	get	r7,-8(sp)	# restore old r7
	brx	r15		# return while restoring r6
 	get	r6,-4(sp)

Lreturn:
	mr	r2,r7		# return 0 or pointer as in r7
	get	r7,-8(sp)	# restore old r7
	brx	r15		# return while restoring r6
 	get	r6,-4(sp)

	TTNOFRM
