xref: /netbsd-src/common/lib/libc/arch/mips/string/ffs.S (revision 259d2a08e1b6d46677ef1757721cfcc877257bfc)
1*259d2a08Smrg/*	$NetBSD: ffs.S,v 1.4 2011/07/04 11:35:26 mrg Exp $	*/
237c9f0a6Schristos
337c9f0a6Schristos/*-
43c6f3faaSmatt * Copyright (c) 2010 The NetBSD Foundation, Inc.
53c6f3faaSmatt * All rights reserved.
637c9f0a6Schristos *
73c6f3faaSmatt * This code is derived from software contributed to The NetBSD Foundation
83c6f3faaSmatt * by Matt Thomas of 3am Software Foundry.
937c9f0a6Schristos *
1037c9f0a6Schristos * Redistribution and use in source and binary forms, with or without
1137c9f0a6Schristos * modification, are permitted provided that the following conditions
1237c9f0a6Schristos * are met:
1337c9f0a6Schristos * 1. Redistributions of source code must retain the above copyright
1437c9f0a6Schristos *    notice, this list of conditions and the following disclaimer.
1537c9f0a6Schristos * 2. Redistributions in binary form must reproduce the above copyright
1637c9f0a6Schristos *    notice, this list of conditions and the following disclaimer in the
1737c9f0a6Schristos *    documentation and/or other materials provided with the distribution.
1837c9f0a6Schristos *
193c6f3faaSmatt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
203c6f3faaSmatt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
213c6f3faaSmatt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
223c6f3faaSmatt * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
233c6f3faaSmatt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
243c6f3faaSmatt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
253c6f3faaSmatt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
263c6f3faaSmatt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
273c6f3faaSmatt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
283c6f3faaSmatt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
293c6f3faaSmatt * POSSIBILITY OF SUCH DAMAGE.
3037c9f0a6Schristos */
3137c9f0a6Schristos
3237c9f0a6Schristos#include <mips/asm.h>
3337c9f0a6Schristos
34*259d2a08SmrgRCSID("$NetBSD: ffs.S,v 1.4 2011/07/04 11:35:26 mrg Exp $")
3537c9f0a6Schristos
3637c9f0a6Schristos/* bit = ffs(value) */
3737c9f0a6Schristos
383c6f3faaSmatt	.text
393c6f3faaSmatt	.set	noreorder
403c6f3faaSmatt
41*259d2a08SmrgWEAK_ALIAS(__ffssi2,ffs)
423c6f3faaSmatt#if __mips == 64 || __mips == 32
4337c9f0a6SchristosLEAF(ffs)
443c6f3faaSmatt#ifndef _LP64
453c6f3faaSmattXLEAF(ffsl)
463c6f3faaSmatt#endif
473c6f3faaSmatt	.set	push
483c6f3faaSmatt	.set	mips32
493c6f3faaSmatt	li	v1, 32
503c6f3faaSmatt#if __mips == 64
513c6f3faaSmatt	sll	a0, a0, 0
523c6f3faaSmatt#endif
533c6f3faaSmatt	negu	a1, a0
543c6f3faaSmatt	and	a0, a1
553c6f3faaSmatt	clz	v0, a0
5637c9f0a6Schristos	j	ra
573c6f3faaSmatt	 subu	v0, v1, v0
583c6f3faaSmatt	.set	pop
5937c9f0a6SchristosEND(ffs)
603c6f3faaSmatt#if defined(_LP64) && __mips == 64
613c6f3faaSmattLEAF(ffsl)
623c6f3faaSmatt	li	v1, 64
633c6f3faaSmatt	negu	a1, a0
643c6f3faaSmatt	and	a0, a1
653c6f3faaSmatt	dclz	v0, a0
663c6f3faaSmatt	j	ra
673c6f3faaSmatt	 subu	v0, v1, v0
683c6f3faaSmattEND(ffsl)
693c6f3faaSmatt#endif
703c6f3faaSmatt#else /* __mips != 64 && __mips != 32 */
713c6f3faaSmatt
723c6f3faaSmatt#ifdef _LP64
733c6f3faaSmattXLEAF(ffsl)
743c6f3faaSmatt	beqz	a0, 6f			# fast escape if 0
753c6f3faaSmatt	 li	v0, 0
763c6f3faaSmatt
773c6f3faaSmatt	li	v0, 1
783c6f3faaSmatt	li	a3, 0xffffffff		# initial mask
793c6f3faaSmatt	b	1f
803c6f3faaSmatt	 li	a2, 32			# bit count of mask
813c6f3faaSmatt#endif /* _LP64 */
823c6f3faaSmattLEAF(ffs)
833c6f3faaSmatt#ifndef _LP64
843c6f3faaSmattXLEAF(ffsl)
853c6f3faaSmatt#endif /* !_LP64 */
863c6f3faaSmatt	beqz	a0, 6f
873c6f3faaSmatt	 li	v0, 0
883c6f3faaSmatt
893c6f3faaSmatt	li	v0, 1
903c6f3faaSmatt	li	a3, 0xffff		# initial mask
913c6f3faaSmatt	li	a2, 16			# bit count of mask
923c6f3faaSmatt1:
933c6f3faaSmatt	and	v1, a0, a3		# focus no lower half of bits left
943c6f3faaSmatt	bnez	v1, 2f			# any of the lower half set?
953c6f3faaSmatt	 nop
963c6f3faaSmatt	addu	v0, a2			# nope, then bit is in the upper half
973c6f3faaSmatt#ifdef _LP64
983c6f3faaSmatt	dsrlv	a0, a0, a2		# discard low bits
993c6f3faaSmatt#else
1003c6f3faaSmatt	srlv	a0, a0, a2		# discard low bits
1013c6f3faaSmatt#endif
1023c6f3faaSmatt2:
1033c6f3faaSmatt	srl	a2, 1			# divide bit count by 2
1043c6f3faaSmatt	bnez	a2, 1b			# still bits left to text?
1053c6f3faaSmatt	 srlv	a3, a3, a2		# shrink mask in half
1063c6f3faaSmatt6:
1073c6f3faaSmatt	j	ra
1083c6f3faaSmatt	 nop
1093c6f3faaSmattEND(ffs)
1103c6f3faaSmatt#endif /* __mips == 64 || __mips == 32 */
111