xref: /netbsd/common/lib/libc/arch/mips/string/ffs.S (revision 6550d01e)
1/*	$NetBSD: ffs.S,v 1.3 2011/01/23 06:47:14 matt Exp $	*/
2
3/*-
4 * Copyright (c) 2010 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Matt Thomas of 3am Software Foundry.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <mips/asm.h>
33
34RCSID("$NetBSD: ffs.S,v 1.3 2011/01/23 06:47:14 matt Exp $")
35
36/* bit = ffs(value) */
37
38	.text
39	.set	noreorder
40
41#if __mips == 64 || __mips == 32
42LEAF(ffs)
43#ifndef _LP64
44XLEAF(ffsl)
45#endif
46	.set	push
47	.set	mips32
48	li	v1, 32
49#if __mips == 64
50	sll	a0, a0, 0
51#endif
52	negu	a1, a0
53	and	a0, a1
54	clz	v0, a0
55	j	ra
56	 subu	v0, v1, v0
57	.set	pop
58END(ffs)
59#if defined(_LP64) && __mips == 64
60LEAF(ffsl)
61	li	v1, 64
62	negu	a1, a0
63	and	a0, a1
64	dclz	v0, a0
65	j	ra
66	 subu	v0, v1, v0
67END(ffsl)
68#endif
69#else /* __mips != 64 && __mips != 32 */
70
71#ifdef _LP64
72XLEAF(ffsl)
73	beqz	a0, 6f			# fast escape if 0
74	 li	v0, 0
75
76	li	v0, 1
77	li	a3, 0xffffffff		# initial mask
78	b	1f
79	 li	a2, 32			# bit count of mask
80#endif /* _LP64 */
81LEAF(ffs)
82#ifndef _LP64
83XLEAF(ffsl)
84#endif /* !_LP64 */
85	beqz	a0, 6f
86	 li	v0, 0
87
88	li	v0, 1
89	li	a3, 0xffff		# initial mask
90	li	a2, 16			# bit count of mask
911:
92	and	v1, a0, a3		# focus no lower half of bits left
93	bnez	v1, 2f			# any of the lower half set?
94	 nop
95	addu	v0, a2			# nope, then bit is in the upper half
96#ifdef _LP64
97	dsrlv	a0, a0, a2		# discard low bits
98#else
99	srlv	a0, a0, a2		# discard low bits
100#endif
1012:
102	srl	a2, 1			# divide bit count by 2
103	bnez	a2, 1b			# still bits left to text?
104	 srlv	a3, a3, a2		# shrink mask in half
1056:
106	j	ra
107	 nop
108END(ffs)
109#endif /* __mips == 64 || __mips == 32 */
110