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
34RCSID("$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
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