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
41WEAK_ALIAS(__ffssi2,ffs)
42#if __mips == 64 || __mips == 32
43LEAF(ffs)
44#ifndef _LP64
45XLEAF(ffsl)
46#endif
47	.set	push
48	.set	mips32
49	li	v1, 32
50#if __mips == 64
51	sll	a0, a0, 0
52#endif
53	negu	a1, a0
54	and	a0, a1
55	clz	v0, a0
56	j	ra
57	 subu	v0, v1, v0
58	.set	pop
59END(ffs)
60#if defined(_LP64) && __mips == 64
61LEAF(ffsl)
62	li	v1, 64
63	negu	a1, a0
64	and	a0, a1
65	dclz	v0, a0
66	j	ra
67	 subu	v0, v1, v0
68END(ffsl)
69#endif
70#else /* __mips != 64 && __mips != 32 */
71
72#ifdef _LP64
73XLEAF(ffsl)
74	beqz	a0, 6f			# fast escape if 0
75	 li	v0, 0
76
77	li	v0, 1
78	li	a3, 0xffffffff		# initial mask
79	b	1f
80	 li	a2, 32			# bit count of mask
81#endif /* _LP64 */
82LEAF(ffs)
83#ifndef _LP64
84XLEAF(ffsl)
85#endif /* !_LP64 */
86	beqz	a0, 6f
87	 li	v0, 0
88
89	li	v0, 1
90	li	a3, 0xffff		# initial mask
91	li	a2, 16			# bit count of mask
921:
93	and	v1, a0, a3		# focus no lower half of bits left
94	bnez	v1, 2f			# any of the lower half set?
95	 nop
96	addu	v0, a2			# nope, then bit is in the upper half
97#ifdef _LP64
98	dsrlv	a0, a0, a2		# discard low bits
99#else
100	srlv	a0, a0, a2		# discard low bits
101#endif
1022:
103	srl	a2, 1			# divide bit count by 2
104	bnez	a2, 1b			# still bits left to text?
105	 srlv	a3, a3, a2		# shrink mask in half
1066:
107	j	ra
108	 nop
109END(ffs)
110#endif /* __mips == 64 || __mips == 32 */
111