yaffs: Refactor bit counting code
authorCharles Manning <cdhmanning@gmail.com>
Tue, 30 Nov 2010 01:00:00 +0000 (14:00 +1300)
committerCharles Manning <cdhmanning@gmail.com>
Tue, 30 Nov 2010 01:00:00 +0000 (14:00 +1300)
For Linux kernel we use hweight8() and hweight32(). This allows
use of special bit-counting code instructions in processors that
do this.

The yaffs direct we now only use one set of code. There were two.

NB On x86 the yaffs hweight8 code is actually a lot faster
than the sofwtare implementation in Linux kernel.

Signed-off-by: Charles Manning <cdhmanning@gmail.com>
direct/basic-test/Makefile
direct/python/Makefile
direct/tests/Makefile
direct/timothy_tests/quick_tests/Makefile
direct/yaffs_hweight.c [new file with mode: 0644]
direct/yaffs_hweight.h [new file with mode: 0644]
direct/ydirectenv.h
yaffs_ecc.c
yaffs_tagscompat.c
yportenv_multi.h
yportenv_single.h

index cc9094e..214f4e9 100644 (file)
@@ -33,7 +33,7 @@ CFLAGS+=   -Werror=undef
 CFLAGS+=   -DCONFIG_YAFFS_USE_PTHREADS -lpthread
 
 
-COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o \
+COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o yaffs_hweight.o \
                 yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \
                 yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \
                 yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \
@@ -65,7 +65,8 @@ YAFFSDIRECTSYMLINKS =  yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\
                       yaffsfs.h yaffs_osglue.h ydirectenv.h \
                       yaffs_flashif.c yaffscfg.h yaffs_list.h \
                       yaffs_qsort.c yportenv.h yaffs_attribs.c \
-                      yaffs_nandif.c yaffs_nandif.h yaffs_nandemul2k.h
+                      yaffs_nandif.c yaffs_nandif.h yaffs_nandemul2k.h \
+                      yaffs_hweight.h yaffs_hweight.c \
 
 
 
index ad5b47f..6e0c5fd 100644 (file)
@@ -29,7 +29,7 @@ CFLAGS +=    -O0 -fPIC
 #CFLAGS+=   -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline
 
 
-COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o \
+COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o yaffs_hweight.o\
                 yramsim.o yaffs_fileem2k.o\
                 yaffs_nandif.o yaffs_attribs.o \
                 yaffsfs.o  yaffs_ecc.o yaffs_guts.o \
@@ -64,7 +64,8 @@ YAFFSSYMLINKS = yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffs_tagscomp
 YAFFSDIRECTSYMLINKS =  yaffsfs.c yaffsfs.h yaffscfg.h yaffs_osglue.h  ydirectenv.h \
                       yaffs_flashif.c yaffs_flashif.h yaffs_flashif2.h yaffs_list.h \
                       yaffs_nandif.c yaffs_nandif.h yaffs_qsort.c yaffs_nandemul2k.h \
-                      yportenv.h yaffs_attribs.c
+                      yportenv.h yaffs_attribs.c \
+                      yaffs_hweight.c yaffs_hweight.h
 
 DIRECTEXTRASYMLINKS =   yaffscfg2k.c yaffs_fileem2k.c yaffs_fileem2k.h\
                         yaffs_fileem.c yaffs_norif1.c yaffs_norif1.h \
index bbeb8de..00db67d 100644 (file)
@@ -30,7 +30,7 @@ CFLAGS +=    -Wextra -Wpointer-arith
 #CFLAGS+=   -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline
 
 
-COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o \
+COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o yaffs_hweight.o\
                 yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \
                 yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \
                 yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \
@@ -67,7 +67,8 @@ YAFFSDIRECTSYMLINKS =  yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\
                       yaffs_flashif.c yaffscfg.h yaffs_qsort.c \
                       yaffs_nandemul2k.h yaffs_list.h \
                       yaffs_attribs.c \
-                      yaffs_nandif.c yaffs_nandif.h yportenv.h
+                      yaffs_nandif.c yaffs_nandif.h yportenv.h \
+                      yaffs_hweight.c yaffs_hweight.h
 
 
 DIRECTEXTRASYMLINKS =  yaffscfg2k.c yaffs_fileem2k.c yaffs_fileem2k.h\
index 1d8a025..6001261 100644 (file)
@@ -30,7 +30,7 @@ CFLAGS +=    -Wextra -Wpointer-arith
 #CFLAGS+=   -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline
 
 
-COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o \
+COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o yaffs_hweight.o \
                 yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \
                 yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \
                 yaffs_tagscompat.o yaffs_packedtags2.o yaffs_tagsvalidity.o yaffs_nand.o \
@@ -125,7 +125,8 @@ YAFFSDIRECTSYMLINKS =  yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\
                       yaffs_flashif.c yaffscfg.h yaffs_qsort.c \
                       yaffs_nandemul2k.h yaffs_list.h \
                       yaffs_attribs.c yaffs_osglue.h \
-                      yaffs_nandif.c yaffs_nandif.h yportenv.h
+                      yaffs_nandif.c yaffs_nandif.h yportenv.h \
+                      yaffs_hweight.h yaffs_hweight.c
 
 
 DIRECTEXTRASYMLINKS =  yaffscfg2k.c yaffs_fileem2k.c yaffs_fileem2k.h\
diff --git a/direct/yaffs_hweight.c b/direct/yaffs_hweight.c
new file mode 100644 (file)
index 0000000..d283b87
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2010 Aleph One Ltd.
+ *   for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+ /* These functions have been renamed to hweightxx to match the
+  * equivaqlent functions in the Linux kernel.
+  */
+
+#include "yaffs_hweight.h"
+
+static const char yaffs_count_bits_table[256] = {
+       0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+       4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+};
+
+int yaffs_hweight8(u8 x)
+{
+       int ret_val;
+       ret_val = yaffs_count_bits_table[x];
+       return ret_val;
+}
+
+int yaffs_hweight32(u32 x)
+{
+       return hweight8(x & 0xff) + 
+               hweight8((x >> 8) & 0xff) +
+               hweight8((x >> 16) & 0xff) +
+               hweight8((x >> 24) & 0xff);
+}
+
diff --git a/direct/yaffs_hweight.h b/direct/yaffs_hweight.h
new file mode 100644 (file)
index 0000000..cfe38dd
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system. 
+ *
+ * Copyright (C) 2002-2010 Aleph One Ltd.
+ *   for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __YAFFS_HWEIGHT_H__
+#define __YAFFS_HWEIGHT_H__
+
+#include "yportenv.h"
+
+int yaffs_hweight8(u8 x);
+int yaffs_hweight32(u32 x);
+
+#endif
index be80e68..ceaa6c8 100644 (file)
@@ -26,6 +26,7 @@
 #include "stdio.h"
 #include "string.h"
 #include "yaffs_osglue.h"
+#include "yaffs_hweight.h"
 
 #include "assert.h"
 #define YBUG() assert(0)
@@ -43,6 +44,9 @@
 #define yaffs_sprintf       sprintf
 #define yaffs_toupper(a)     toupper(a)
 
+#define hweight8(x)    yaffs_hweight8(x)
+#define hweight32(x)   yaffs_hweight32(x)
+
 void yaffs_qsort(void *aa, size_t n, size_t es,
         int (*cmp)(const void *, const void *));
 
@@ -94,7 +98,6 @@ void yaffs_qsort(void *aa, size_t n, size_t es,
 
 #include "yaffs_list.h"
 
-
 #include "yaffsfs.h"
 
 #endif
index 0ea0305..e95a806 100644 (file)
@@ -67,29 +67,6 @@ static const unsigned char column_parity_table[] = {
        0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
 };
 
-/* Count the bits in an unsigned char or a U32 */
-
-static int yaffs_count_bits(unsigned char x)
-{
-       int r = 0;
-       while (x) {
-               if (x & 1)
-                       r++;
-               x >>= 1;
-       }
-       return r;
-}
-
-static int yaffs_count_bits32(unsigned x)
-{
-       int r = 0;
-       while (x) {
-               if (x & 1)
-                       r++;
-               x >>= 1;
-       }
-       return r;
-}
 
 /* Calculate the ECC for a 256-byte block of data */
 void yaffs_ecc_cacl(const unsigned char *data, unsigned char *ecc)
@@ -222,8 +199,7 @@ int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc,
                return 1;       /* Corrected the error */
        }
 
-       if ((yaffs_count_bits(d0) +
-            yaffs_count_bits(d1) + yaffs_count_bits(d2)) == 1) {
+       if ((hweight8(d0) + hweight8(d1) + hweight8(d2)) == 1) {
                /* Reccoverable error in ecc */
 
                read_ecc[0] = test_ecc[0];
@@ -307,9 +283,9 @@ int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes,
                return 1;       /* corrected */
        }
 
-       if ((yaffs_count_bits32(delta_line) +
-            yaffs_count_bits32(delta_line_prime) +
-            yaffs_count_bits(delta_col)) == 1) {
+       if ((hweight32(delta_line) +
+            hweight32(delta_line_prime) +
+            hweight8(delta_col)) == 1) {
                /* Reccoverable error in ecc */
 
                *read_ecc = *test_ecc;
index 3a9a157..a35e0f3 100644 (file)
 
 static void yaffs_handle_rd_data_error(struct yaffs_dev *dev, int nand_chunk);
 
-static const char yaffs_count_bits_table[256] = {
-       0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
-       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-       1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
-       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-       2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
-       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-       3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
-       4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
-};
-
-int yaffs_count_bits(u8 x)
-{
-       int ret_val;
-       ret_val = yaffs_count_bits_table[x];
-       return ret_val;
-}
 
 /********** Tags ECC calculations  *********/
 
@@ -370,7 +345,7 @@ int yaffs_tags_compat_rd(struct yaffs_dev *dev,
                if (ext_tags) {
 
                        int deleted =
-                           (yaffs_count_bits(spare.page_status) < 7) ? 1 : 0;
+                           (hweight8(spare.page_status) < 7) ? 1 : 0;
 
                        ext_tags->is_deleted = deleted;
                        ext_tags->ecc_result = ecc_result;
@@ -443,7 +418,7 @@ int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
        yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block + 1,
                            NULL, &spare1, &dummy, 1);
 
-       if (yaffs_count_bits(spare0.block_status & spare1.block_status) < 7)
+       if (hweight8(spare0.block_status & spare1.block_status) < 7)
                *state = YAFFS_BLOCK_STATE_DEAD;
        else if (memcmp(&spare_ff, &spare0, sizeof(spare_ff)) == 0)
                *state = YAFFS_BLOCK_STATE_EMPTY;
index ec43fd5..4b058a7 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/sort.h>
+#include <linux/bitops.h>
 
 #define YCHAR char
 #define YUCHAR unsigned char
index 2eae429..8fd0da5 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/fs.h>
 #include <linux/stat.h>
 #include <linux/sort.h>
+#include <linux/bitops.h>
 
 #define YCHAR char
 #define YUCHAR unsigned char