1*0a6a1f1dSLionel Sambuc/* $NetBSD: ffs.S,v 1.9 2015/05/17 22:14:38 justin Exp $ */ 2b6cbf720SGianluca Guida/* 3b6cbf720SGianluca Guida * Copyright (c) 2001 Christopher Gilbert 4b6cbf720SGianluca Guida * All rights reserved. 5b6cbf720SGianluca Guida * 6b6cbf720SGianluca Guida * Redistribution and use in source and binary forms, with or without 7b6cbf720SGianluca Guida * modification, are permitted provided that the following conditions 8b6cbf720SGianluca Guida * are met: 9b6cbf720SGianluca Guida * 1. Redistributions of source code must retain the above copyright 10b6cbf720SGianluca Guida * notice, this list of conditions and the following disclaimer. 11b6cbf720SGianluca Guida * 2. Redistributions in binary form must reproduce the above copyright 12b6cbf720SGianluca Guida * notice, this list of conditions and the following disclaimer in the 13b6cbf720SGianluca Guida * documentation and/or other materials provided with the distribution. 14b6cbf720SGianluca Guida * 3. The name of the company nor the name of the author may be used to 15b6cbf720SGianluca Guida * endorse or promote products derived from this software without specific 16b6cbf720SGianluca Guida * prior written permission. 17b6cbf720SGianluca Guida * 18b6cbf720SGianluca Guida * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19b6cbf720SGianluca Guida * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20b6cbf720SGianluca Guida * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21b6cbf720SGianluca Guida * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 22b6cbf720SGianluca Guida * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23b6cbf720SGianluca Guida * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24b6cbf720SGianluca Guida * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25b6cbf720SGianluca Guida * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26b6cbf720SGianluca Guida * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27b6cbf720SGianluca Guida * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28b6cbf720SGianluca Guida * SUCH DAMAGE. 29b6cbf720SGianluca Guida */ 30b6cbf720SGianluca Guida 31b6cbf720SGianluca Guida#include <machine/asm.h> 32b6cbf720SGianluca Guida 33*0a6a1f1dSLionel SambucRCSID("$NetBSD: ffs.S,v 1.9 2015/05/17 22:14:38 justin Exp $") 34b6cbf720SGianluca Guida 35b6cbf720SGianluca Guida/* 36b6cbf720SGianluca Guida * ffs - find first set bit, this algorithm isolates the first set 37b6cbf720SGianluca Guida * bit, then multiplies the number by 0x0450fbaf which leaves the top 38b6cbf720SGianluca Guida * 6 bits as an index into the table. This algorithm should be a win 39b6cbf720SGianluca Guida * over the checking each bit in turn as per the C compiled version. 40b6cbf720SGianluca Guida * 41b6cbf720SGianluca Guida * On ARMv5 we use CLZ (count leading Zero's) and then subtract the result 42b6cbf720SGianluca Guida * from 32. 43b6cbf720SGianluca Guida * 44b6cbf720SGianluca Guida * This is the ffs algorithm devised by d.seal and posted to comp.sys.arm on 45b6cbf720SGianluca Guida * 16 Feb 1994. 46b6cbf720SGianluca Guida */ 47*0a6a1f1dSLionel Sambuc#ifndef _RUMPKERNEL 48*0a6a1f1dSLionel SambucSTRONG_ALIAS(__ffssi2,ffs) 49*0a6a1f1dSLionel Sambuc#endif 5084d9c625SLionel Sambuc#if (defined(_ARM_ARCH_5) && !defined(__thumb__)) || defined(_ARM_ARCH_T2) 5184d9c625SLionel Sambuc#if defined(_ARM_ARCH_T2) 52b6cbf720SGianluca GuidaENTRY(ffs) 5384d9c625SLionel Sambuc#else 5484d9c625SLionel SambucARM_ENTRY(ffs) 5584d9c625SLionel Sambuc#endif 56b6cbf720SGianluca Guida /* (X & -X) gives LSB or zero. */ 5784d9c625SLionel Sambuc neg r1, r0 58b6cbf720SGianluca Guida and r0, r0, r1 59b6cbf720SGianluca Guida clz r0, r0 60b6cbf720SGianluca Guida rsb r0, r0, #32 61b6cbf720SGianluca Guida RET 6284d9c625SLionel SambucEND(ffs) 63b6cbf720SGianluca Guida#else 6484d9c625SLionel SambucARM_ENTRY(ffs) 65b6cbf720SGianluca Guida /* Standard trick to isolate bottom bit in r0 or 0 if r0 = 0 on entry */ 6684d9c625SLionel Sambuc neg r1, r0 67b6cbf720SGianluca Guida ands r0, r0, r1 68b6cbf720SGianluca Guida /* 69b6cbf720SGianluca Guida * now r0 has at most one set bit, call this X 70b6cbf720SGianluca Guida * if X = 0, all further instructions are skipped 71b6cbf720SGianluca Guida */ 72b6cbf720SGianluca Guida adrne r2, .L_ffs_table 73b6cbf720SGianluca Guida orrne r0, r0, r0, lsl #4 /* r0 = X * 0x11 */ 74b6cbf720SGianluca Guida orrne r0, r0, r0, lsl #6 /* r0 = X * 0x451 */ 75b6cbf720SGianluca Guida rsbne r0, r0, r0, lsl #16 /* r0 = X * 0x0450fbaf */ 76b6cbf720SGianluca Guida 77b6cbf720SGianluca Guida /* now lookup in table indexed on top 6 bits of r0 */ 7884d9c625SLionel Sambuc ldrbne r0, [r2, r0, lsr #26] 79b6cbf720SGianluca Guida 80b6cbf720SGianluca Guida RET 81b6cbf720SGianluca Guida.text; 82b6cbf720SGianluca Guida.type .L_ffs_table, _ASM_TYPE_OBJECT; 83b6cbf720SGianluca Guida.L_ffs_table: 84b6cbf720SGianluca Guida/* 0 1 2 3 4 5 6 7 */ 85b6cbf720SGianluca Guida .byte 0, 1, 2, 13, 3, 7, 0, 14 /* 0- 7 */ 86b6cbf720SGianluca Guida .byte 4, 0, 8, 0, 0, 0, 0, 15 /* 8-15 */ 87b6cbf720SGianluca Guida .byte 11, 5, 0, 0, 9, 0, 0, 26 /* 16-23 */ 88b6cbf720SGianluca Guida .byte 0, 0, 0, 0, 0, 22, 28, 16 /* 24-31 */ 89b6cbf720SGianluca Guida .byte 32, 12, 6, 0, 0, 0, 0, 0 /* 32-39 */ 90b6cbf720SGianluca Guida .byte 10, 0, 0, 25, 0, 0, 21, 27 /* 40-47 */ 91b6cbf720SGianluca Guida .byte 31, 0, 0, 0, 0, 24, 0, 20 /* 48-55 */ 92b6cbf720SGianluca Guida .byte 30, 0, 23, 19, 29, 18, 17, 0 /* 56-63 */ 9384d9c625SLionel SambucEND(ffs) 94b6cbf720SGianluca Guida#endif 95