All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Maydell <peter.maydell@linaro.org>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PULL 02/22] bitops.h: Implement half-shuffle and half-unshuffle ops
Date: Fri, 17 Jun 2016 15:25:32 +0100	[thread overview]
Message-ID: <1466173552-25482-3-git-send-email-peter.maydell@linaro.org> (raw)
In-Reply-To: <1466173552-25482-1-git-send-email-peter.maydell@linaro.org>

A half-shuffle operation takes a word with zeros in the high half:
 0000 0000 0000 0000 ABCD EFGH IJKL MNOP
and spreads the bits out so they are in every other bit of the word:
 0A0B 0C0D 0E0F 0G0H 0I0J 0K0L 0M0N 0O0P
A half-unshuffle performs the reverse operation.

Provide functions in bitops.h which implement these operations
for 32-bit and 64-bit inputs, and add tests for them.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Shannon Zhao <shannon.zhao@linaro.org>
Tested-by: Shannon Zhao <shannon.zhao@linaro.org>
Message-id: 1465915112-29272-3-git-send-email-peter.maydell@linaro.org
---
 include/qemu/bitops.h | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tests/test-bitops.c   |  72 +++++++++++++++++++++++++++++++++
 2 files changed, 180 insertions(+)

diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h
index 755fdd1..15418a8 100644
--- a/include/qemu/bitops.h
+++ b/include/qemu/bitops.h
@@ -428,4 +428,112 @@ static inline uint64_t deposit64(uint64_t value, int start, int length,
     return (value & ~mask) | ((fieldval << start) & mask);
 }
 
+/**
+ * half_shuffle32:
+ * @value: 32-bit value (of which only the bottom 16 bits are of interest)
+ *
+ * Given an input value:
+ *  xxxx xxxx xxxx xxxx ABCD EFGH IJKL MNOP
+ * return the value where the bottom 16 bits are spread out into
+ * the odd bits in the word, and the even bits are zeroed:
+ *  0A0B 0C0D 0E0F 0G0H 0I0J 0K0L 0M0N 0O0P
+ *
+ * Any bits set in the top half of the input are ignored.
+ *
+ * Returns: the shuffled bits.
+ */
+static inline uint32_t half_shuffle32(uint32_t x)
+{
+    /* This algorithm is from _Hacker's Delight_ section 7-2 "Shuffling Bits".
+     * It ignores any bits set in the top half of the input.
+     */
+    x = ((x & 0xFF00) << 8) | (x & 0x00FF);
+    x = ((x << 4) | x) & 0x0F0F0F0F;
+    x = ((x << 2) | x) & 0x33333333;
+    x = ((x << 1) | x) & 0x55555555;
+    return x;
+}
+
+/**
+ * half_shuffle64:
+ * @value: 64-bit value (of which only the bottom 32 bits are of interest)
+ *
+ * Given an input value:
+ *  xxxx xxxx xxxx .... xxxx xxxx ABCD EFGH IJKL MNOP QRST UVWX YZab cdef
+ * return the value where the bottom 32 bits are spread out into
+ * the odd bits in the word, and the even bits are zeroed:
+ *  0A0B 0C0D 0E0F 0G0H 0I0J 0K0L 0M0N .... 0U0V 0W0X 0Y0Z 0a0b 0c0d 0e0f
+ *
+ * Any bits set in the top half of the input are ignored.
+ *
+ * Returns: the shuffled bits.
+ */
+static inline uint64_t half_shuffle64(uint64_t x)
+{
+    /* This algorithm is from _Hacker's Delight_ section 7-2 "Shuffling Bits".
+     * It ignores any bits set in the top half of the input.
+     */
+    x = ((x & 0xFFFF0000ULL) << 16) | (x & 0xFFFF);
+    x = ((x << 8) | x) & 0x00FF00FF00FF00FFULL;
+    x = ((x << 4) | x) & 0x0F0F0F0F0F0F0F0FULL;
+    x = ((x << 2) | x) & 0x3333333333333333ULL;
+    x = ((x << 1) | x) & 0x5555555555555555ULL;
+    return x;
+}
+
+/**
+ * half_unshuffle32:
+ * @value: 32-bit value (of which only the odd bits are of interest)
+ *
+ * Given an input value:
+ *  xAxB xCxD xExF xGxH xIxJ xKxL xMxN xOxP
+ * return the value where all the odd bits are compressed down
+ * into the low half of the word, and the high half is zeroed:
+ *  0000 0000 0000 0000 ABCD EFGH IJKL MNOP
+ *
+ * Any even bits set in the input are ignored.
+ *
+ * Returns: the unshuffled bits.
+ */
+static inline uint32_t half_unshuffle32(uint32_t x)
+{
+    /* This algorithm is from _Hacker's Delight_ section 7-2 "Shuffling Bits".
+     * where it is called an inverse half shuffle.
+     */
+    x &= 0x55555555;
+    x = ((x >> 1) | x) & 0x33333333;
+    x = ((x >> 2) | x) & 0x0F0F0F0F;
+    x = ((x >> 4) | x) & 0x00FF00FF;
+    x = ((x >> 8) | x) & 0x0000FFFF;
+    return x;
+}
+
+/**
+ * half_unshuffle64:
+ * @value: 64-bit value (of which only the odd bits are of interest)
+ *
+ * Given an input value:
+ *  xAxB xCxD xExF xGxH xIxJ xKxL xMxN .... xUxV xWxX xYxZ xaxb xcxd xexf
+ * return the value where all the odd bits are compressed down
+ * into the low half of the word, and the high half is zeroed:
+ *  0000 0000 0000 .... 0000 0000 ABCD EFGH IJKL MNOP QRST UVWX YZab cdef
+ *
+ * Any even bits set in the input are ignored.
+ *
+ * Returns: the unshuffled bits.
+ */
+static inline uint64_t half_unshuffle64(uint64_t x)
+{
+    /* This algorithm is from _Hacker's Delight_ section 7-2 "Shuffling Bits".
+     * where it is called an inverse half shuffle.
+     */
+    x &= 0x5555555555555555ULL;
+    x = ((x >> 1) | x) & 0x3333333333333333ULL;
+    x = ((x >> 2) | x) & 0x0F0F0F0F0F0F0F0FULL;
+    x = ((x >> 4) | x) & 0x00FF00FF00FF00FFULL;
+    x = ((x >> 8) | x) & 0x0000FFFF0000FFFFULL;
+    x = ((x >> 16) | x) & 0x00000000FFFFFFFFULL;
+    return x;
+}
+
 #endif
diff --git a/tests/test-bitops.c b/tests/test-bitops.c
index eb19a36..5a791d2 100644
--- a/tests/test-bitops.c
+++ b/tests/test-bitops.c
@@ -65,10 +65,82 @@ static void test_sextract64(void)
     }
 }
 
+typedef struct {
+    uint32_t unshuffled;
+    uint32_t shuffled;
+} Shuffle32Test;
+
+typedef struct {
+    uint64_t unshuffled;
+    uint64_t shuffled;
+} Shuffle64Test;
+
+static const Shuffle32Test test_shuffle32_data[] = {
+    { 0x0000FFFF, 0x55555555 },
+    { 0x000081C5, 0x40015011 },
+};
+
+static const Shuffle64Test test_shuffle64_data[] = {
+    { 0x00000000FFFFFFFFULL, 0x5555555555555555ULL },
+    { 0x00000000493AB02CULL, 0x1041054445000450ULL },
+};
+
+static void test_half_shuffle32(void)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(test_shuffle32_data); i++) {
+        const Shuffle32Test *test = &test_shuffle32_data[i];
+        uint32_t r = half_shuffle32(test->unshuffled);
+
+        g_assert_cmpint(r, ==, test->shuffled);
+    }
+}
+
+static void test_half_shuffle64(void)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(test_shuffle64_data); i++) {
+        const Shuffle64Test *test = &test_shuffle64_data[i];
+        uint64_t r = half_shuffle64(test->unshuffled);
+
+        g_assert_cmpint(r, ==, test->shuffled);
+    }
+}
+
+static void test_half_unshuffle32(void)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(test_shuffle32_data); i++) {
+        const Shuffle32Test *test = &test_shuffle32_data[i];
+        uint32_t r = half_unshuffle32(test->shuffled);
+
+        g_assert_cmpint(r, ==, test->unshuffled);
+    }
+}
+
+static void test_half_unshuffle64(void)
+{
+    int i;
+
+    for (i = 0; i < ARRAY_SIZE(test_shuffle64_data); i++) {
+        const Shuffle64Test *test = &test_shuffle64_data[i];
+        uint64_t r = half_unshuffle64(test->shuffled);
+
+        g_assert_cmpint(r, ==, test->unshuffled);
+    }
+}
+
 int main(int argc, char **argv)
 {
     g_test_init(&argc, &argv, NULL);
     g_test_add_func("/bitops/sextract32", test_sextract32);
     g_test_add_func("/bitops/sextract64", test_sextract64);
+    g_test_add_func("/bitops/half_shuffle32", test_half_shuffle32);
+    g_test_add_func("/bitops/half_shuffle64", test_half_shuffle64);
+    g_test_add_func("/bitops/half_unshuffle32", test_half_unshuffle32);
+    g_test_add_func("/bitops/half_unshuffle64", test_half_unshuffle64);
     return g_test_run();
 }
-- 
1.9.1

  parent reply	other threads:[~2016-06-17 14:26 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-17 14:25 [Qemu-devel] [PULL 00/22] target-arm queue Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 01/22] migration: Define VMSTATE_UINT64_2DARRAY Peter Maydell
2016-06-17 14:25 ` Peter Maydell [this message]
2016-06-17 14:25 ` [Qemu-devel] [PULL 03/22] target-arm: Define new arm_is_el3_or_mon() function Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 04/22] target-arm: Provide hook to tell GICv3 about changes of security state Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 05/22] target-arm: Add mp-affinity property for ARM CPU class Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 06/22] hw/intc/arm_gicv3: Add state information Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 07/22] hw/intc/arm_gicv3: Move irq lines into GICv3CPUState structure Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 08/22] hw/intc/arm_gicv3: Add vmstate descriptors Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 09/22] hw/intc/arm_gicv3: ARM GICv3 device framework Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 10/22] hw/intc/arm_gicv3: Implement functions to identify next pending irq Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 11/22] hw/intc/arm_gicv3: Implement GICv3 distributor registers Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 12/22] hw/intc/arm_gicv3: Implement GICv3 redistributor registers Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 13/22] hw/intc/arm_gicv3: Wire up distributor and redistributor MMIO regions Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 14/22] hw/intc/arm_gicv3: Implement gicv3_set_irq() Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 15/22] hw/intc/arm_gicv3: Implement GICv3 CPU interface registers Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 16/22] hw/intc/arm_gicv3: Implement gicv3_cpuif_update() Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 17/22] hw/intc/arm_gicv3: Implement CPU i/f SGI generation registers Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 18/22] hw/intc/arm_gicv3: Add IRQ handling CPU interface registers Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 19/22] target-arm/machine.c: Allow user to request GICv3 emulation Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 20/22] target-arm/monitor.c: Advertise emulated GICv3 in capabilities Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 21/22] hw/timer: Add value matching support to aspeed_timer Peter Maydell
2016-06-17 14:25 ` [Qemu-devel] [PULL 22/22] ACPI: ARM: Present GIC version in MADT table Peter Maydell
2016-06-17 16:06 ` [Qemu-devel] [PULL 00/22] target-arm queue Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1466173552-25482-3-git-send-email-peter.maydell@linaro.org \
    --to=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.