diff --git a/apps/plugins/CATEGORIES b/apps/plugins/CATEGORIES
index 09a4476..4d4418e 100644
--- a/apps/plugins/CATEGORIES
+++ b/apps/plugins/CATEGORIES
@@ -93,6 +93,7 @@ test_scanrate,apps
test_touchscreen,apps
test_viewports,apps
test_greylib_bitmap_scale,viewers
+test_clz_speed,apps
text_editor,apps
vbrfix,viewers
video,viewers
diff --git a/apps/plugins/SOURCES b/apps/plugins/SOURCES
index 6257a22..e8f1f8d 100644
--- a/apps/plugins/SOURCES
+++ b/apps/plugins/SOURCES
@@ -28,6 +28,7 @@ firmware_flash.c
#if (CONFIG_CPU == SH7034)
rockbox_flash.c
#endif /* CONFIG_CPU */
+test_clz_speed.c

#ifndef OLYMPUS_MROBE_500

diff --git a/apps/plugins/test_clz_speed.c b/apps/plugins/test_clz_speed.c
new file mode 100644
index 0000000..3d9a530
--- /dev/null
+++ b/apps/plugins/test_clz_speed.c
@@ -0,0 +1,173 @@
+/*****************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// __ \_/ ___\| |/ /| __ \ / __ \ \/ /
+ * Jukebox | | ( (__) ) \___| ( | \_\ ( (__) ) (
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 Andrew Mahone
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "plugin.h"
+#include "lib/pluginlib_actions.h"
+
+PLUGIN_HEADER
+
+static const char clz_lut1[16] = { 4, 3, 2, 2, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0 };
+/* This clz is based on the log2(n) implementation at
+ * http://graphics.stanford.edu/~seander/bithacks.html#IntegerLogLookup
+ */
+int clz1(uint32_t v)
+{
+ int r = 28;
+ if (v >= 0x10000)
+ {
+ v >>= 16;
+ r -= 16;
+ }
+ if (v & 0xff00)
+ {
+ v >>= 8;
+ r -= 8;
+ }
+ if (v & 0xf0)
+ {
+ v >>= 4;
+ r -= 4;
+ }
+ return r + clz_lut1[v];
+}
+
+static const char clz_lut2[256] = {
+ 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+int clz2(uint32_t v)
+{
+ int r = 24;
+ if (v >= 0x10000)
+ {
+ v >>= 16;
+ r -= 16;
+ }
+ if (v & 0xff00)
+ {
+ v >>= 8;
+ r -= 8;
+ }
+ return r + clz_lut2[v];
+}
+
+static const char clz_lut3[53] = {
+ 32, 31, 30, 25, 29, 6, 24, 0, 28, 0, 19, 5, 23, 12, 0, 0, 27, 8, 0,
+ 14, 16, 18, 4, 0, 2, 22, 11, 0, 0, 0, 0, 0, 0, 26, 7, 0, 0, 20,
+ 13, 0, 9, 15, 17, 0, 3, 0, 0, 0,1, 0, 21, 0, 10
+};
+int clz3(uint32_t v)
+{
+ v |= v >> 16;
+ v |= v >> 8;
+ v |= v >> 4;
+ v |= v >> 2;
+ v |= v >> 1;
+ v ^= v >> 1;
+ return clz_lut3[(v * 70428299UL)>>26];
+}
+
+int clz4(uint32_t v)
+{
+ int r = 32;
+ if (v >= 0x10000)
+ {
+ v >>= 16;
+ r -= 16;
+ }
+ if (v & 0xff00)
+ {
+ v >>= 8;
+ r -= 8;
+ }
+ if (v & 0xf0)
+ {
+ v >>= 4;
+ r -= 4;
+ }
+ if (v & 0xc)
+ {
+ v >>= 2;
+ r -= 2;
+ }
+ if (v & 2)
+ {
+ v >>= 1;
+ r -= 1;
+ }
+ r -= v;
+ return r;
+}
+
+int (*func_table[])(uint32_t) =
+{
+ clz1,
+ clz2,
+ clz3,
+ clz4,
+ NULL,
+};
+
+const struct button_mapping *plugin_contexts[] = {generic_actions};
+
+/* this is the plugin entry point */
+enum plugin_status plugin_start(const void* parameter)
+{
+ (void) parameter;
+ int y = 0, w=0, h=0, n;
+ char buf[16];
+ h = rb->lcd_getstringsize("0", &w, &h);
+ rb->lcd_set_drawmode(DRMODE_FG);
+ for (n = 0 ; func_table[n]; n++)
+ {
+ long t1 = *(rb->current_tick);
+ uint32_t i, lz;
+ for(i = 0; i < 1UL<<31; i+= 1023)
+ lz = (*(func_table[n]))(i);
+ long t2 = *(rb->current_tick);
+ rb->snprintf(buf, sizeof(buf), "%d:%d", n, (int)(t2-t1));
+ rb->lcd_putsxy(0, y, buf);
+ rb->lcd_update();
+ y += h * 2;
+ }
+ while(1)
+ {
+ int button = pluginlib_getaction(1, plugin_contexts, 1);
+ if (button == PLA_QUIT)
+ return PLUGIN_OK;
+ rb->yield();
+ }
+}