Compare commits

..

14 Commits

21 changed files with 256 additions and 118 deletions

1
.gitignore vendored
View File

@@ -2,6 +2,7 @@ compile_commands.json
core core
/.ccls-cache/ /.ccls-cache/
/test/test/ /test/test/
.lastbuild
# /test/cutest/ # /test/cutest/
/tmp/ /tmp/
# created when building # created when building

View File

@@ -44,30 +44,88 @@ BIN := $(addprefix $(BINDIR)/,$(TEST_FN:.c=))
CCLSCMDS := compile_commands.json CCLSCMDS := compile_commands.json
##################################### Check for compiler and requested build
BUILDS := release dev perf debug
# last compilation build
BUILDFILE := .lastbuild
lastbuild := $(file < $(BUILDFILE))
$(info brlib last:$(lastbuild))
# default to gcc
CC ?= cc
ifeq ($(CC),cc)
CC = gcc
endif
# if no build specified, use last one
ifeq ($(build),)
build := $(lastbuild)
endif
# if build is still undefined, set a default
ifeq ($(build),)
build := release
endif
$(info brlib build=$(build))
# check for valid build
ifeq ($(filter $(build),$(BUILDS)),)
$(error Error: Unknown build=`$(build)`. Possible builds are: $(BUILDS))
endif
# if new build, rewrite BUILDFILE
ifneq ($(build),$(lastbuild))
$(info New build:`$(build)` (was:$(lastbuild)))
$(file >$(BUILDFILE),$(build))
endif
##################################### pre-processor flags ##################################### pre-processor flags
CPPFLAGS := -I $(INCDIR) override CPPFLAGS += -I $(INCDIR)
#CPPFLAGS += -DDEBUG # global
#CPPFLAGS += -DDEBUG_DEBUG_C # log() funcs debug ifeq ($(BUILD),release)
CPPFLAGS += -DDEBUG_DEBUG # activate logs funcs CPPFLAGS += -DNDEBUG # assert (unused)
CPPFLAGS += -DDEBUG_POOL # mem pools CPPFLAGS += -DBUG_ON=0 CPPFLAGS += -DWARN_ON=0 else # ifeq ($(BUILD),dev)
#CPPFLAGS += -DDEBUG #CPPFLAGS += -DDEBUG_DEBUG_C CPPFLAGS += -DDEBUG_DEBUG CPPFLAGS += -DDEBUG_POOL CPPFLAGS += -DBUG_ON=1 CPPFLAGS += -DWARN_ON=1 # warn_on in bug.h
endif
# remove extraneous spaces (due to spaces before comments) # remove extraneous spaces (due to spaces before comments)
CPPFLAGS := $(strip $(CPPFLAGS)) CPPFLAGS := $(strip $(CPPFLAGS))
##################################### compiler flags ##################################### compiler flags
CFLAGS := -std=gnu11 CFLAGS := -std=gnu11
CFLAGS += -O2
CFLAGS += -g
CFLAGS += -Wall CFLAGS += -Wall
CFLAGS += -Wextra CFLAGS += -Wextra
CFLAGS += -march=native CFLAGS += -march=native
CFLAGS += -Wmissing-declarations CFLAGS += -Wmissing-declarations
CFLAGS += -Wno-unused-result CFLAGS += -Wno-unused-result
# TODO: specific to dynamic
CFLAGS += -fPIC CFLAGS += -fPIC
# for gprof
#CFLAGS += -pg ### dev OR release
# Next one may be useful for valgrind (some invalid instructions) ifeq ($(BUILD),release)
# CFLAGS += -mno-tbm CFLAGS += -O3
CFLAGS += -funroll-loops
CFLAGS += -flto
else ifeq ($(BUILD),dev)
CFLAGS += -Og
CFLAGS += -g
CFLAGS += -ginline-points # inlined funcs debug info
# for gprof
#CFLAGS += -pg
# Next one may be useful for valgrind (some invalid instructions)
# CFLAGS += -mno-tbm
else ifeq ($(BUILD),perf)
CFLAGS += -O3
CFLAGS += -g # symbols (gdb, perf, etc.)
CFLAGS += -ginline-points # inlined funcs debug info
CFLAGS += -funroll-loops
else ifeq ($(BUILD),debug)
CFLAGS += -O0
CFLAGS += -g # symbols (gdb, perf, etc.)
# for gprof
#CFLAGS += -pg
# Next one may be useful for valgrind (when invalid instructions)
#CFLAGS += -mno-tbm
endif
CFLAGS := $(strip $(CFLAGS)) CFLAGS := $(strip $(CFLAGS))
@@ -77,14 +135,21 @@ LDFLAGS := -L$(LIBDIR)
LIBS := -l$(LIB) LIBS := -l$(LIB)
DEPFLAGS = -MMD -MP -MF $(DEPDIR)/$*.d DEPFLAGS = -MMD -MP -MF $(DEPDIR)/$*.d
ifeq ($(BUILD),release)
LDFLAGS += -flto
endif
##################################### General targets ##################################### General targets
.PHONY: all libs compile test emacs ccls bear clean cleanall cleanallall .PHONY: all libs lib-static lib-dynamic compile test emacs ccls bear clean \
cleanall cleanallall
# default: build libraries # default: build libraries
all: libs all: libs
# default: build libraries # libraries
libs: $(DLIB) $(SLIB) libs: lib-static lib-dynamic
lib-static: $(SLIB)
lib-dynamic: $(DLIB)
# build objects # build objects
compile: $(OBJ) compile: $(OBJ)
@@ -178,7 +243,8 @@ cleanobj:
cleanobjdir: cleanobjdir:
$(call rmdir,$(OBJDIR),brlib objects) $(call rmdir,$(OBJDIR),brlib objects)
$(OBJDIR)/%.o: $(SRCDIR)/%.c | $(OBJDIR) $(DEPDIR) # $(OBJDIR)/%.o: $(BUILDFILE)
$(OBJDIR)/%.o: $(SRCDIR)/%.c $(BUILDFILE) | $(OBJDIR) $(DEPDIR)
@echo compiling $< "->" $@. @echo compiling $< "->" $@.
$(CC) -c $(DEPFLAGS) $(CPPFLAGS) $(CFLAGS) $< -o $@ $(CC) -c $(DEPFLAGS) $(CPPFLAGS) $(CFLAGS) $< -o $@
@@ -248,7 +314,7 @@ cleanccls:
# maybe run cleanobj cleanlibobj in commands ? # maybe run cleanobj cleanlibobj in commands ?
$(CCLSCMDS): cleanobj $(SRC) | $(CCLSROOT) $(CCLSCMDS): cleanobj $(SRC) | $(CCLSROOT)
@echo "Generating ccls compile commands file ($@)." @echo "Generating ccls compile commands file ($@)."
@$(BEAR) -- make test @$(BEAR) -- $(MAKE) test
##################################### valgrind (mem check) ##################################### valgrind (mem check)
.PHONY: memcheck .PHONY: memcheck

View File

@@ -7,16 +7,16 @@
This work is, with exceptions below, Copyright (C) 2021-2024 Bruno Raoult This work is, with exceptions below, Copyright (C) 2021-2024 Bruno Raoult
("br"), and licensed under the GNU General Public License v3.0 or later. ("br"), and licensed under the GNU General Public License v3.0 or later.
Some rights reserved. See COPYING. Some rights reserved. See COPYING.
*The licence exceptions are:** *** The licence exceptions are:*
_Cutest testing framework.__
You can find the original work on **** _Cutest testing framework.__
[[https://sourceforge.net/projects/cutest/files/cutest/][sourceforge]]. You can find the original work on [[https://sourceforge.net/projects/cutest/files/cutest/][sourceforge]].
This software is (C) 2000-2003 Asim Jalis, under the zlib License. This software is (C) 2000-2003 Asim Jalis, under the zlib License.
See [[test/cutest/license.txt][license local copy]] or See [[test/cutest/license.txt][license local copy]] or <https://spdx.org/licenses/Zlib.html>.
<https://spdx.org/licenses/Zlib.html>.
** Installation: ** Installation:
*** clone repository *** clone repository
@@ -31,7 +31,8 @@ $ git clone https://git.raoult.com/bruno/brlib.git
#+BEGIN_EXAMPLE #+BEGIN_EXAMPLE
$ git clone git@git.raoult.com:bruno/brlib.git $ git clone git@git.raoult.com:bruno/brlib.git
$ cd brlib $ cd brlib
$ git remote add github git@github.com/braoult/brlib.git $ git remote add github git@github.com:braoult/brlib.git
$ git fetch --all
#+END_EXAMPLE #+END_EXAMPLE
*Add CuTest submodule (optional)* *Add CuTest submodule (optional)*

View File

@@ -0,0 +1,38 @@
/* generic-bswap.h - generic bswap implementations.
*
* Copyright (C) 2024 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*
*/
#ifndef _GENERIC_BSWAP_H_
#define _GENERIC_BSWAP_H_
#include "brlib.h"
/* Adapted from: http://www-graphics.stanford.edu/%7Eseander/bithacks.html
*/
static __always_inline u32 __bswap32_emulated(u32 n)
{
const u32 k = 0x00FF00FF;
n = ((n >> 8) & k) | ((n & k) << 8);
n = ( n >> 16) | ( n << 16);
return n;
}
static __always_inline u64 __bswap64_emulated(u64 n)
{
const u64 k1 = 0x00FF00FF00FF00FFull;
const u64 k2 = 0x0000FFFF0000FFFFull;
n = ((n >> 8) & k1) | ((n & k1) << 8);
n = ((n >> 16) & k2) | ((n & k2) << 16);
n = ( n >> 32) | ( n << 32);
return n;
}
#endif /* _GENERIC_BSWAP_H_ */

View File

@@ -13,7 +13,7 @@
#ifndef _GENERIC_CLZ_H_ #ifndef _GENERIC_CLZ_H_
#define _GENERIC_CLZ_H_ #define _GENERIC_CLZ_H_
#include "br.h" #include "brlib.h"
/* Adapted from: http://www-graphics.stanford.edu/%7Eseander/bithacks.html /* Adapted from: http://www-graphics.stanford.edu/%7Eseander/bithacks.html
*/ */

View File

@@ -13,7 +13,7 @@
#ifndef _GENERIC_CTZ_H_ #ifndef _GENERIC_CTZ_H_
#define _GENERIC_CTZ_H_ #define _GENERIC_CTZ_H_
#include "br.h" #include "brlib.h"
/* Adapted from: http://www-graphics.stanford.edu/%7Eseander/bithacks.html /* Adapted from: http://www-graphics.stanford.edu/%7Eseander/bithacks.html
*/ */

View File

@@ -13,7 +13,7 @@
#ifndef _GENERIC_ILOG2_H_ #ifndef _GENERIC_ILOG2_H_
#define _GENERIC_ILOG2_H_ #define _GENERIC_ILOG2_H_
#include "br.h" #include "brlib.h"
/* /*
* See https://stackoverflow.com/a/11398748/3079831 * See https://stackoverflow.com/a/11398748/3079831

View File

@@ -13,9 +13,10 @@
#ifndef _BITS_H #ifndef _BITS_H
#define _BITS_H #define _BITS_H
#include "br.h" #include "brlib.h"
#include "bitops-emulated/generic-ctz.h" #include "bitops-emulated/generic-ctz.h"
#include "bitops-emulated/generic-clz.h" #include "bitops-emulated/generic-clz.h"
#include "bitops-emulated/generic-bswap.h"
#ifndef __has_builtin #ifndef __has_builtin
#define __has_builtin(x) 0 #define __has_builtin(x) 0
@@ -35,7 +36,9 @@
#if __has_builtin(__builtin_ffs) #if __has_builtin(__builtin_ffs)
# define HAS_FFS # define HAS_FFS
#endif #endif
#if __has_builtin(__builtin_bswap32)
# define HAS_BSWAP
#endif
/** /**
* print_bitops_impl() - print bitops implementation. * print_bitops_impl() - print bitops implementation.
@@ -174,6 +177,24 @@ void print_bitops_impl(void);
#define ffz32(n) ffs32(~(n)) #define ffz32(n) ffs32(~(n))
#define ffz64(n) ffs64(~(n)) #define ffz64(n) ffs64(~(n))
/**
* bswap32, bswap64 - reverse bytes: 0x01020304 -> 0x04030201
* @n: unsigned 32 or 64 bits integer.
*
* ffs(n) is similar to ctz(n) + 1, but returns 0 if n == 0 (except
* for ctz version, where ffs(0) is undefined).
* ffz(n) is ffz(~n), with undefine value if n = 0.
*/
#if defined(HAS_BSWAP)
# define __bswap32_native(n) __builtin_bswap32(n)
# define __bswap64_native(n) __builtin_bswap64(n)
# define bswap32(n) __bswap32_native(n)
# define bswap64(n) __bswap64_native(n)
#else
# define bswap32(n) __bswap32_emulated(n)
# define bswap64(n) __bswap64_emulated(n)
#endif
/** /**
* fls32, fls64 - return one plus MSB index: 00101000 -> 6 * fls32, fls64 - return one plus MSB index: 00101000 -> 6
* @n: unsigned 32 or 64 bits integer. * @n: unsigned 32 or 64 bits integer.

View File

@@ -1,4 +1,4 @@
/* br.h - misc macros. /* brlib.h - misc types/macros.
* *
* Copyright (C) 2021-2024 Bruno Raoult ("br") * Copyright (C) 2021-2024 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later. * Licensed under the GNU General Public License v3.0 or later.
@@ -15,9 +15,10 @@
* This header contains generic stuff. * This header contains generic stuff.
*/ */
#ifndef _BR_H #ifndef _BRLIB_H
#define _BR_H #define _BRLIB_H
#include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include <bits/wordsize.h> /* defines __WORDSIZE: 32 or 64 */ #include <bits/wordsize.h> /* defines __WORDSIZE: 32 or 64 */
@@ -267,4 +268,4 @@ typedef signed char schar;
({ signed type __x = (x); __x < 0 ? -__x : __x; }), other) ({ signed type __x = (x); __x < 0 ? -__x : __x; }), other)
#endif /* _BR_H */ #endif /* _BRLIB_H */

View File

@@ -1,68 +1,61 @@
/* SPDX-License-Identifier: GPL-2.0 */ /* bug.h - bug_on/warn_on/warn functions.
#ifndef _BR_BUG_H *
#define _BR_BUG_H * Copyright (C) 2021-2024 Bruno Raoult ("br")
* Licensed under the GNU General Public License v3.0 or later.
* Some rights reserved. See COPYING.
*
* You should have received a copy of the GNU General Public License along with this
* program. If not, see <https://www.gnu.org/licenses/gpl-3.0-standalone.html>.
*
* SPDX-License-Identifier: GPL-3.0-or-later <https://spdx.org/licenses/GPL-3.0-or-later.html>
*
*/
#ifndef BUG_H
#define BUG_H
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <stdarg.h> #include <stdarg.h>
#include "likely.h"
#include "debug.h"
/* BUG functions inspired by Linux kernel's <asm/bug.h> #define bug_on_always(expr) do { \
*/ if (expr) { \
fprintf(stderr, \
#define panic() exit(0xff) "** BUG ON %s[%s:%d]: assertion '%s' failed.\n", \
__func__, __FILE__,__LINE__, #expr); \
/* abort(); \
* Don't use BUG() or BUG_ON() unless there's really no way out; one /* not reached */ \
* example might be detecting data structure corruption in the middle } \
* of an operation that can't be backed out of. If the (sub)system
* can somehow continue operating, perhaps with reduced functionality,
* it's probably not BUG-worthy.
*
*/
#define BUG() do { \
fprintf(stderr, "BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
panic(); \
} while (0) } while (0)
#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0) #define warn(expr, args...) ({ \
int _ret = !!(expr); \
if (_ret) \
fprintf(stderr, ##args); \
_ret; \
})
/* #define warn_on_always(expr) ({ \
* WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report significant warn(expr, \
* issues that need prompt attention if they should ever appear at runtime. "** WARN ON %s[%s:%d]: assertion '%s' failed.\n", \
* __func__, __FILE__,__LINE__, #expr); \
* Do not use these macros when checking for invalid external inputs
* (e.g. invalid system call arguments, or invalid data coming from
* network/devices), and on transient conditions like ENOMEM or EAGAIN.
* These macros should be used for recoverable kernel issues only.
* For invalid external inputs, transient conditions, etc use
* pr_err[_once/_ratelimited]() followed by dump_stack(), if necessary.
* Do not include "BUG"/"WARNING" in format strings manually to make these
* conditions distinguishable from kernel issues.
*
* Use the versions with printk format strings to provide better diagnostics.
*/
#define __WARN() do { \
fprintf(stderr, "WARNING: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \
} while (0)
#define __WARN_printf(arg...) do { \
vfprintf(stderr, arg); \
} while (0)
#define WARN_ON(condition) ({ \
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \
__WARN(); \
unlikely(__ret_warn_on); \
}) })
#define WARN(condition, format...) ({ \ #ifdef BUG_ON
int __ret_warn_on = !!(condition); \
if (unlikely(__ret_warn_on)) \
__WARN_printf(format); \
unlikely(__ret_warn_on); \
})
#endif /* _BR_BUG_H */ #define bug_on(expr) bug_on_always(expr)
#define warn_on(expr) warn_on_always(expr)
#define warn_on_or_eval(expr) warn_on(expr)
#else
#define bug_on(expr)
#define warn_on(expr)
#define warn_on_or_eval(expr) (expr)
#endif /* BUG_ON */
#endif /* BUG_H */

View File

@@ -17,7 +17,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include <br.h> #include "brlib.h"
#define NANOSEC 1000000000 /* nano sec in sec */ #define NANOSEC 1000000000 /* nano sec in sec */
#define MILLISEC 1000000 /* milli sec in sec */ #define MILLISEC 1000000 /* milli sec in sec */

View File

@@ -10,7 +10,7 @@
#include <asm/bitsperlong.h> #include <asm/bitsperlong.h>
#include "br.h" #include "brlib.h"
#include "bitops.h" #include "bitops.h"
/* /*

View File

@@ -14,7 +14,7 @@
#ifndef _PJWHASH_INLINE_H #ifndef _PJWHASH_INLINE_H
#define _PJWHASH_INLINE_H #define _PJWHASH_INLINE_H
#include "br.h" #include "brlib.h"
#define THREE_QUARTERS ((int) ((BITS_PER_INT * 3) / 4)) #define THREE_QUARTERS ((int) ((BITS_PER_INT * 3) / 4))
#define ONE_EIGHTH ((int) (BITS_PER_INT / 8)) #define ONE_EIGHTH ((int) (BITS_PER_INT / 8))

View File

@@ -13,7 +13,7 @@
#ifndef _PJWHASH_H #ifndef _PJWHASH_H
#define _PJWHASH_H #define _PJWHASH_H
#include "br.h" #include "brlib.h"
/** /**
* unsigned int pjwhash - PJW hash function * unsigned int pjwhash - PJW hash function

View File

@@ -279,7 +279,7 @@ static inline int plist_node_empty(const struct plist_node *node)
#ifdef CONFIG_DEBUG_PLIST #ifdef CONFIG_DEBUG_PLIST
# define plist_first_entry(head, type, member) \ # define plist_first_entry(head, type, member) \
({ \ ({ \
WARN_ON(plist_head_empty(head)); \ warn_on(plist_head_empty(head)); \
container_of(plist_first(head), type, member); \ container_of(plist_first(head), type, member); \
}) })
#else #else
@@ -296,7 +296,7 @@ static inline int plist_node_empty(const struct plist_node *node)
#ifdef CONFIG_DEBUG_PLIST #ifdef CONFIG_DEBUG_PLIST
# define plist_last_entry(head, type, member) \ # define plist_last_entry(head, type, member) \
({ \ ({ \
WARN_ON(plist_head_empty(head)); \ warn_on(plist_head_empty(head)); \
container_of(plist_last(head), type, member); \ container_of(plist_last(head), type, member); \
}) })
#else #else

View File

@@ -17,7 +17,7 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include "br.h" #include "brlib.h"
#include "list.h" #include "list.h"
#define POOL_NAME_LENGTH (16) /* max name length including trailing \0 */ #define POOL_NAME_LENGTH (16) /* max name length including trailing \0 */

View File

@@ -3,7 +3,7 @@
/* /*
* Taken from linux kernel: lib/list_sort.c * Taken from linux kernel: lib/list_sort.c
*/ */
#include "br.h" #include "brlib.h"
#include "list_sort.h" #include "list_sort.h"
#include "list.h" #include "list.h"
#include "likely.h" #include "likely.h"

View File

@@ -32,7 +32,7 @@ static struct plist_head test_head;
static void plist_check_prev_next(struct list_head *t, struct list_head *p, static void plist_check_prev_next(struct list_head *t, struct list_head *p,
struct list_head *n) struct list_head *n)
{ {
WARN(n->prev != p || p->next != n, warn(n->prev != p || p->next != n,
"top: %p, n: %p, p: %p\n" "top: %p, n: %p, p: %p\n"
"prev: %p, n: %p, p: %p\n" "prev: %p, n: %p, p: %p\n"
"next: %p, n: %p, p: %p\n", "next: %p, n: %p, p: %p\n",
@@ -76,8 +76,8 @@ void plist_add(struct plist_node *node, struct plist_head *head)
struct list_head *node_next = &head->node_list; struct list_head *node_next = &head->node_list;
plist_check_head(head); plist_check_head(head);
WARN_ON(!plist_node_empty(node)); warn_on(!plist_node_empty(node));
WARN_ON(!list_empty(&node->prio_list)); warn_on(!list_empty(&node->prio_list));
if (plist_head_empty(head)) if (plist_head_empty(head))
goto ins_node; goto ins_node;
@@ -148,8 +148,8 @@ void plist_requeue(struct plist_node *node, struct plist_head *head)
struct list_head *node_next = &head->node_list; struct list_head *node_next = &head->node_list;
plist_check_head(head); plist_check_head(head);
BUG_ON(plist_head_empty(head)); bug_on(plist_head_empty(head));
BUG_ON(plist_node_empty(node)); bug_on(plist_node_empty(node));
if (node == plist_last(head)) if (node == plist_last(head))
return; return;

View File

@@ -17,7 +17,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include "br.h" #include "brlib.h"
#include "list.h" #include "list.h"
#include "pool.h" #include "pool.h"
#include "debug.h" #include "debug.h"

View File

@@ -14,12 +14,13 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "br.h" #include "brlib.h"
#include "bitops.h" #include "bitops.h"
#include "cutest/CuTest.h" #include "cutest/CuTest.h"
static const struct test32_1 { static const struct test32_1 {
u32 t32; /* input */ u32 t32; /* input */
u32 bswap;
int popc; int popc;
int ctz; int ctz;
int clz; int clz;
@@ -32,19 +33,19 @@ static const struct test32_1 {
uchar bfe[32]; uchar bfe[32];
}; };
} test32_1[] = { } test32_1[] = {
{ 0x00000000, 0, 32, 32, 0, 1, 0, 0, /* sometimes undefined */ { 0x00000000, 0x00000000, 0, 32, 32, 0, 1, 0, 0, /* sometimes undefined */
{ 0, { 0 } } }, { 0, { 0 } } },
{ 0xffffffff, 32, 0, 0, 1, 0, 32, 31, { 0xffffffff, 0xffffffff, 32, 0, 0, 1, 0, 32, 31,
{ 32, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, { 32, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 } } }, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 } } },
{ 0x00000001, 1, 0, 31, 1, 2, 1, 0, { 0x00000001, 0x01000000, 1, 0, 31, 1, 2, 1, 0,
{ 1, { 0 } } }, { 1, { 0 } } },
{ 0x80000000, 1, 31, 0, 32, 1, 32, 31, { 0x80000000, 0x00000080, 1, 31, 0, 32, 1, 32, 31,
{ 1, { 31 } } }, { 1, { 31 } } },
{ 0x71800718, 10, 3, 1, 4, 1, 31, 30, { 0x71800718, 0x18078071, 10, 3, 1, 4, 1, 31, 30,
/* 0111 0001 1000 0000 0000 0111 0001 1000 */ /* 0111 0001 1000 0000 0000 0111 0001 1000 */
{ 10, { 3, 4, 8, 9, 10, 23, 24, 28, 29, 30 } } }, { 10, { 3, 4, 8, 9, 10, 23, 24, 28, 29, 30 } } },
{ 0x07eeeef7, 22, 0, 5, 1, 4, 27, 26, { 0x07eeeef7, 0xf7eeee07, 22, 0, 5, 1, 4, 27, 26,
/* 0000 0111 1110 1110 1110 1110 0111 1111*/ /* 0000 0111 1110 1110 1110 1110 0111 1111*/
{ 22, { 0, 1, 2, 4, 5, 6, 7, 9, 10, 11, 13, { 22, { 0, 1, 2, 4, 5, 6, 7, 9, 10, 11, 13,
14, 15, 17, 18, 19, 21, 22, 23, 24, 25, 26 } } }, 14, 15, 17, 18, 19, 21, 22, 23, 24, 25, 26 } } },
@@ -52,7 +53,8 @@ static const struct test32_1 {
static const struct test64_1 { static const struct test64_1 {
u64 t64; /* input */ u64 t64; /* input */
int popc; u64 bswap;
int popc; /* some values may be undefined */
int ctz; int ctz;
int clz; int clz;
int ffs; int ffs;
@@ -64,22 +66,22 @@ static const struct test64_1 {
uchar bfe[64]; uchar bfe[64];
}; };
} test64_1[] = { } test64_1[] = {
{ 0x0000000000000000, 0, 64, 64, 0, 1, 0, 0, /* sometimes undefined */ { 0x0000000000000000, 0x0000000000000000, 0, 64, 64, 0, 1, 0, 0,
{ 0, { 0 } } }, { 0, { 0 } } },
{ 0xffffffffffffffff, 64, 0, 0, 1, 0, 64, 63, { 0xffffffffffffffff, 0xffffffffffffffff, 64, 0, 0, 1, 0, 64, 63,
{ 64, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, { 64, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 } } }, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 } } },
{ 0x0000000100000001, 2, 0, 31, 1, 2, 33, 32, { 0x0000000100000001, 0x0100000001000000, 2, 0, 31, 1, 2, 33, 32,
{ 2, { 0, 32 } } }, { 2, { 0, 32 } } },
{ 0x8000000000000000, 1, 63, 0, 64, 1, 64, 63, { 0x8000000000000000, 0x0000000000000080, 1, 63, 0, 64, 1, 64, 63,
{ 1, { 63 } } }, { 1, { 63 } } },
{ 0x7180071871800718, 20, 3, 1, 4, 1, 63, 62, { 0x7180071871800718, 0x1807807118078071, 20, 3, 1, 4, 1, 63, 62,
/* 2 x 0111 0001 1000 0000 0000 0111 0001 1000 */ /* 2 x 0111 0001 1000 0000 0000 0111 0001 1000 */
{ 20, { 3, 4, 8, 9, 10, 23, 24, 28, 29, 30, { 20, { 3, 4, 8, 9, 10, 23, 24, 28, 29, 30,
35, 36, 40, 41, 42, 55, 56, 60, 61, 62 } } }, 35, 36, 40, 41, 42, 55, 56, 60, 61, 62 } } },
{ 0x07eeeef707eeeef7, 44, 0, 5, 1, 4, 59, 58 , { 0x07eeeef707eeeef7, 0xf7eeee07f7eeee07, 44, 0, 5, 1, 4, 59, 58 ,
/* 2 x 0000 0111 1110 1110 1110 1110 0111 1111*/ /* 2 x 0000 0111 1110 1110 1110 1110 0111 1111*/
{ 44, { 0, 1, 2, 4, 5, 6, 7, 9, 10, 11, 13, { 44, { 0, 1, 2, 4, 5, 6, 7, 9, 10, 11, 13,
14, 15, 17, 18, 19, 21, 22, 23, 24, 25, 26, 14, 15, 17, 18, 19, 21, 22, 23, 24, 25, 26,
@@ -167,6 +169,20 @@ static void cutest_fls(CuTest *tc)
} }
} }
static void cutest_bswap(CuTest *tc)
{
for (uint i = 0; i < ARRAY_SIZE(test32_1); ++i) {
int res = bswap32(test32_1[i].t32);
//printf("fls32 t=%#x r=%d e=%d\n", test32_1[i].t32, res, test32_1[i].fls);
CuAssertIntEquals(tc, test32_1[i].bswap, res);
}
for (uint i = 0; i < ARRAY_SIZE(test64_1); ++i) {
int res = bswap64(test64_1[i].t64);
//printf("fls64 t=%#llx r=%d e=%d\n", test64_1[i].t64, res, test64_1[i].fls);
CuAssertIntEquals(tc, test64_1[i].bswap, res);
}
}
static void cutest_ilog(CuTest *tc) static void cutest_ilog(CuTest *tc)
{ {
for (uint i = 0; i < ARRAY_SIZE(test32_1); ++i) { for (uint i = 0; i < ARRAY_SIZE(test32_1); ++i) {
@@ -322,6 +338,7 @@ static CuSuite *bitops_GetSuite()
SUITE_ADD_TEST(suite, cutest_fls); SUITE_ADD_TEST(suite, cutest_fls);
SUITE_ADD_TEST(suite, cutest_ilog); SUITE_ADD_TEST(suite, cutest_ilog);
SUITE_ADD_TEST(suite, cutest_bfe); SUITE_ADD_TEST(suite, cutest_bfe);
SUITE_ADD_TEST(suite, cutest_bswap);
SUITE_ADD_TEST(suite, cutest_rol); SUITE_ADD_TEST(suite, cutest_rol);
SUITE_ADD_TEST(suite, cutest_ror); SUITE_ADD_TEST(suite, cutest_ror);

View File

@@ -1,7 +1,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "br.h" #include "brlib.h"
#include "pool.h" #include "pool.h"
#include "debug.h" #include "debug.h"