ffs.S revision 1.4 1 /* $NetBSD: ffs.S,v 1.4 2011/07/04 11:35:26 mrg 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
34 RCSID("$NetBSD: ffs.S,v 1.4 2011/07/04 11:35:26 mrg Exp $")
35
36 /* bit = ffs(value) */
37
38 .text
39 .set noreorder
40
41 WEAK_ALIAS(__ffssi2,ffs)
42 #if __mips == 64 || __mips == 32
43 LEAF(ffs)
44 #ifndef _LP64
45 XLEAF(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
59 END(ffs)
60 #if defined(_LP64) && __mips == 64
61 LEAF(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
68 END(ffsl)
69 #endif
70 #else /* __mips != 64 && __mips != 32 */
71
72 #ifdef _LP64
73 XLEAF(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 */
82 LEAF(ffs)
83 #ifndef _LP64
84 XLEAF(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
92 1:
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
102 2:
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
106 6:
107 j ra
108 nop
109 END(ffs)
110 #endif /* __mips == 64 || __mips == 32 */
111