Skip to content

Commit

Permalink
swap out Linux fls for FreeBSD fls implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
dstndstn committed Feb 12, 2021
1 parent 7f899ef commit e1b21dc
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 126 deletions.
171 changes: 48 additions & 123 deletions libkd/an-fls.h
@@ -1,14 +1,35 @@
/**
This file includes code copied from three source files in the Linux kernel
v 2.6.23.1:
- include/asm-generic/bitops/fls.h
- include/asm-i386/bitops.h
- include/asm-x86_64/bitops.h
The second and third files contain this notice:
* Copyright 1992, Linus Torvalds.
And of course the kernel is distributed under the terms of the GPL v2.
/*-
* This file is derived from FreeBSD's sys/libkern/fls.c, with modifications
* by the Astrometry.net team.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/

#ifndef AN_FLS_H
Expand All @@ -17,125 +38,29 @@
#include <stdint.h>
#include <assert.h>

/**
* fls - find last (most-significant) bit set
*
* @x: the word to search
*
* This is defined the same way as ffs.
*
* Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
/*
* Find Last Set bit
*/
static inline int an_fls(int x);
static inline int
BSD_fls(int mask)
{
int bit;

if (mask == 0)
return (0);
for (bit = 1; mask != 1; bit++)
mask = (unsigned int)mask >> 1;
return (bit);
}

/**

/*
* flsB() = fls() - 1.
*
* Note that x MUST be > 0.
*/
static inline uint8_t an_flsB(uint32_t x);



/**** Below this line are the implementations for different CPUs. ****/

#if AN_I386

static inline int an_fls(int x) {
int r;
__asm__("bsrl %1,%0\n\t"
"jnz 1f\n\t"
"movl $-1,%0\n"
"1:" : "=r" (r) : "rm" (x));
return r+1;
}

static inline uint8_t an_flsB(uint32_t x) {
int r;
assert(x);
__asm__("bsrl %1,%0\n\t"
"jnz 1f\n\t"
"movl $-1,%0\n"
"1:" : "=r" (r) : "rm" (x));
return r;
}

#elif AN_X86_64

static __inline__ int an_fls(int x) {
int r;
__asm__("bsrl %1,%0\n\t"
"cmovzl %2,%0"
: "=&r" (r) : "rm" (x), "rm" (-1));
return r+1;
}

static inline uint8_t an_flsB(uint32_t x) {
int r;
assert(x);
__asm__("bsrl %1,%0\n\t"
"cmovzl %2,%0"
: "=&r" (r) : "rm" (x), "rm" (-1));
return r;
}

#else

static inline int an_fls(int x) {
int r = 32;
if (!x)
return 0;
if (!(x & 0xffff0000u)) {
x <<= 16;
r -= 16;
}
if (!(x & 0xff000000u)) {
x <<= 8;
r -= 8;
}
if (!(x & 0xf0000000u)) {
x <<= 4;
r -= 4;
}
if (!(x & 0xc0000000u)) {
x <<= 2;
r -= 2;
}
if (!(x & 0x80000000u)) {
x <<= 1;
r -= 1;
}
return r;
}

static inline uint8_t an_flsB(uint32_t x) {
int r = 31;
assert(x);
if (!(x & 0xffff0000u)) {
x <<= 16;
r -= 16;
}
if (!(x & 0xff000000u)) {
x <<= 8;
r -= 8;
}
if (!(x & 0xf0000000u)) {
x <<= 4;
r -= 4;
}
if (!(x & 0xc0000000u)) {
x <<= 2;
r -= 2;
}
if (!(x & 0x80000000u)) {
x <<= 1;
r -= 1;
}
return r;
return BSD_fls(x)-1;
}

#endif

#endif


3 changes: 0 additions & 3 deletions libkd/test_libkd.c
Expand Up @@ -242,10 +242,7 @@ void test_2(CuTest* ct) {

for (i=0; i<N; i++) {
int L1 = node_level(i);
int L2 = an_fls(i+1) - 1;
int L3 = an_flsB(i+1);
//printf("%i %i %i\n", L1, L2, L3);
CuAssertIntEquals(ct, L1, L2);
CuAssertIntEquals(ct, L1, L3);
}
}
Expand Down

0 comments on commit e1b21dc

Please sign in to comment.