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
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
diff --git a/apps/tagcache.c b/apps/tagcache.c
index 3d0ab7f..0918825 100644
--- a/apps/tagcache.c
+++ b/apps/tagcache.c
@@ -108,28 +108,10 @@ static long tempbuf_left; /* Buffer space left. */
 static long tempbuf_pos;

 #define SORTED_TAGS_COUNT 8
-#ifdef CPU_SH /* SH lacks a variable shift instruction */
-/* Numeric tags (we can use these tags with conditional clauses). */
-const char tagcache_numeric_tags[] =       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
-                                             1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1,
-                                             1, 1, 1, 1, 1 };
-
-/* Uniqued tags (we can use these tags with filters and conditional clauses). */
-static const char tagcache_unique_tags[] = { 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0,
-                                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                             0, 0, 0, 0, 0 };
-
-/* Tags we want to get sorted (loaded to the tempbuf). */
-static const char tagcache_sorted_tags[] = { 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0,
-                                             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                                             0, 0, 0, 0, 0 };
-
-#define TAGCACHE_IS_UNIQUE(tag) ((bool)tagcache_unique_tags[tag])
-#define TAGCACHE_IS_SORTED(tag) ((bool)tagcache_sorted_tags[tag])
-
-#else
-#define TAGCACHE_IS_UNIQUE(tag) ((1LU << tag) & TAGCACHE_UNIQUE_TAGS)
-#define TAGCACHE_IS_SORTED(tag) ((1LU << tag) & TAGCACHE_SORTED_TAGS)
+#define TAGCACHE_IS_UNIQUE(tag) TEST_BIT_N(tag, TAGCACHE_UNIQUE_TAGS)
+#define TAGCACHE_IS_SORTED(tag) TEST_BIT_N(tag, TAGCACHE_SORTED_TAGS)
+#define TAGCACHE_IS_NUMERIC_OR_NONUNIQUE(tag) \
+    TEST_BIT_N(tag, TAGCACHE_NUMERIC_TAGS | TAGCACHE_UNIQUE_TAGS)

 /* Tags we want to get sorted (loaded to the tempbuf). */
 #define TAGCACHE_SORTED_TAGS ((1LU << tag_artist) | (1LU << tag_album) | \
@@ -140,7 +122,6 @@ static const char tagcache_sorted_tags[] = { 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0,
 #define TAGCACHE_UNIQUE_TAGS ((1LU << tag_artist) | (1LU << tag_album) | \
     (1LU << tag_genre) | (1LU << tag_composer) | (1LU << tag_comment) | \
     (1LU << tag_albumartist) | (1LU << tag_grouping))
-#endif

 /* String presentation of the tags defined in tagcache.h. Must be in correct order! */
 static const char *tags_str[] = { "artist", "album", "genre", "title", 
@@ -1248,7 +1229,7 @@ bool tagcache_search_add_filter(struct tagcache_search *tcs,
     if (tcs->filter_count == TAGCACHE_MAX_FILTERS)
         return false;

-    if (!TAGCACHE_IS_UNIQUE(tag) || TAGCACHE_IS_NUMERIC(tag))
+    if (TAGCACHE_IS_NUMERIC_OR_NONUNIQUE(tag))
         return false;

     tcs->filter_tag[tcs->filter_count] = tag;
diff --git a/apps/tagcache.h b/apps/tagcache.h
index d704717..58ba620 100644
--- a/apps/tagcache.h
+++ b/apps/tagcache.h
@@ -22,6 +22,7 @@
 #ifndef _TAGCACHE_H
 #define _TAGCACHE_H

+#include "system.h"
 #include "metadata.h"

 /**
@@ -103,12 +104,7 @@ enum tag_type { tag_artist = 0, tag_album, tag_genre, tag_title,
     (1LU << tag_virt_playtime_min) | (1LU << tag_virt_playtime_sec) | \
     (1LU << tag_virt_entryage) | (1LU << tag_virt_autoscore))

-#ifdef CPU_SH
-extern const char tagcache_numeric_tags[];
-#define TAGCACHE_IS_NUMERIC(tag) ((bool)tagcache_numeric_tags[tag])
-#else
-#define TAGCACHE_IS_NUMERIC(tag) ((1LU << tag) & TAGCACHE_NUMERIC_TAGS)
-#endif
+#define TAGCACHE_IS_NUMERIC(tag) TEST_BIT_N(tag, TAGCACHE_NUMERIC_TAGS)

 /* Flags */
 #define FLAG_DELETED     0x0001  /* Entry has been removed from db */
diff --git a/firmware/export/system.h b/firmware/export/system.h
index b44600d..489ed8d 100644
--- a/firmware/export/system.h
+++ b/firmware/export/system.h
@@ -266,6 +266,10 @@ static inline uint32_t swap_odd_even32(uint32_t value)

 #endif /* !SIMULATOR */

+#ifndef TEST_BIT_N
+#define TEST_BIT_N(n, mask) ((1UL << (n)) & (mask))
+#endif
+
 /* Declare this as HIGHEST_IRQ_LEVEL if they don't differ */
 #ifndef DISABLE_INTERRUPTS
 #define DISABLE_INTERRUPTS  HIGHEST_IRQ_LEVEL
diff --git a/firmware/target/sh/system-sh.c b/firmware/target/sh/system-sh.c
index 02af402..63b2d39 100644
--- a/firmware/target/sh/system-sh.c
+++ b/firmware/target/sh/system-sh.c
@@ -27,6 +27,11 @@
 #include "font.h"
 #include "led.h"

+unsigned int test_bit_n(int n, unsigned int mask)
+{
+    return (1LU << n) & mask;
+}
+
 static const char* const irqname[] = {
     "", "", "", "", "IllInstr", "", "IllSltIn","","",
     "CPUAdrEr", "DMAAdrEr", "NMI", "UserBrk",
diff --git a/firmware/target/sh/system-target.h b/firmware/target/sh/system-target.h
index 3c225fb..27a612b 100644
--- a/firmware/target/sh/system-target.h
+++ b/firmware/target/sh/system-target.h
@@ -126,4 +126,11 @@ static inline uint32_t swap_odd_even32(uint32_t value)
     return value;
 }

+unsigned int test_bit_n(int n, unsigned int mask);
+#define TEST_BIT_N(n, mask) ( \
+    __builtin_constant_p(n) \
+    ? ((1LU << (n)) & (mask)) \
+    : test_bit_n(n, mask) \
+)
+
 #endif /* SYSTEM_TARGET_H */