xref: /original-bsd/lib/libc/vax/string/strrchr.s (revision 04dd0305)
1/*
2 * Copyright (c) 1988, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8#if defined(LIBC_SCCS) && !defined(lint)
9	.asciz "@(#)strrchr.s	8.1 (Berkeley) 06/04/93"
10#endif /* LIBC_SCCS and not lint */
11
12/*
13 * Find the last occurence of c in the string cp.
14 * Return pointer to match or null pointer.
15 *
16 * char *
17 * strrchr(cp, c)
18 *	char *cp, c;
19 */
20#include "DEFS.h"
21
22	.lcomm	tbl,256
23
24ENTRY(strrchr, 0)
25	movzwl	$65535,r4	/* handy 65535 */
26	movq	4(ap),r1	/* r1 = cp; r2 = c */
27	movzbl	r2,r2
28	beql	Lzero		/* special case for c == '\0' */
29
30	clrl	r5		/* r5 = pointer to last match */
31
32/*
33 * Fancy scanc version.  Alas, it is not reentrant.
34 */
35	movab	tbl,r3		/* r3 = address of table */
36	bbss	$0,(r3),Lreent	/* ensure not reentering */
37	movab	(r3)[r2],r4
38	incb	(r4)		/* mark both '\0' and c */
390:
40	scanc	$65535,(r1),(r3),$1	/* look for c or '\0' */
41	beql	0b		/* keep looking */
42	tstb	(r1)
43	beql	1f		/* done if '\0' */
44	movab	(r1)+,r5	/* save most recently found, and skip over it */
45	jbr	0b		/* keep looking */
461:
47	movl	r5,r0		/* return last found (if any) */
48	clrb	(r4)		/* clean up table */
49	clrb	(r3)
50	ret
51
52/*
53 * Special case for \0.
54 */
55Lzero:
56	locc	$0,r4,(r1)	/* just find end of string */
57	beql	Lzero		/* still looking */
58	movl	r1,r0		/* found it */
59	ret
60
61/*
62 * Slower reentrant version is two two-step searches.  The first
63 * phase runs until we know where the string ends; it locates any
64 * occurrences of c within a 65535-byte block.  Once we have found
65 * the end of the string, we find any further occurrences before
66 * that location.
67 */
68Lreent:
690:	/* first phase */
70	movl	r1,r3
71	locc	$0,r4,(r3)	/* look for '\0' */
72	bneq	1f
73	locc	r2,r4,(r3)	/* continue phase 1 search for c */
74	beql	0b
75	movab	(r1)+,r5	/* found c: save and increment pointer */
76	brb	0b		/* and continue */
77
781:	/* second phase */
79	subl3	r3,r1,r0	/* length of short block */
80	movl	r3,r1
812:
82	locc	r2,r0,(r1)	/* look for c */
83	beql	3f		/* skip if not found */
84	movab	(r1)+,r5	/* save pointer as before */
85	sobgtr	r0,2b		/* adjust count and loop */
863:
87	movl	r5,r0		/* return stashed pointer */
88	ret
89