swd: Improve parity calculation and move it to types.h
authorAndreas Fritiofson <andreas.fritiofson@gmail.com>
Sun, 16 Feb 2014 23:27:09 +0000 (00:27 +0100)
committerAndreas Fritiofson <andreas.fritiofson@gmail.com>
Sat, 28 Jun 2014 09:27:19 +0000 (09:27 +0000)
It could be reused by SWD drivers and in other places.

Change-Id: Ieed0cf70c111a73d3a42ed59f46a0cdd177a73d5
Signed-off-by: Andreas Fritiofson <andreas.fritiofson@gmail.com>
Reviewed-on: http://openocd.zylin.com/1957
Tested-by: jenkins
Reviewed-by: Paul Fertser <fercerpav@gmail.com>
src/helper/types.h
src/jtag/swd.h

index 210d3c3e92fd3d2f1354e8eb0066a41da9a703cd..3f0724c3a65c429f3052094459a46e8493b2cea9 100644 (file)
@@ -270,6 +270,25 @@ static inline void buf_bswap32(uint8_t *dst, const uint8_t *src, size_t len)
        }
 }
 
+/**
+ * Calculate the (even) parity of a 32-bit datum.
+ * @param x The datum.
+ * @return 1 if the number of set bits in x is odd, 0 if it is even.
+ */
+static inline int parity_u32(uint32_t x)
+{
+#ifdef __GNUC__
+       return __builtin_parityl(x);
+#else
+       x ^= x >> 16;
+       x ^= x >> 8;
+       x ^= x >> 4;
+       x ^= x >> 2;
+       x ^= x >> 1;
+       return x & 1;
+#endif
+}
+
 #if defined(__ECOS)
 
 /* eCos plain lacks these definition... A series of upstream patches
index c628fa84b00e1c1374ac5336f0e85ca3f9b3eb67..b75a83e369cdc81205d44ac62fbf62086a9405d1 100644 (file)
 #define SWD_CMD_PARK   (0 << 7)        /* not driven by host (pull high) */
 /* followed by TRN, 3-bits of ACK, TRN */
 
-/* pbit16 holds precomputed parity bits for each nibble */
-#define pbit(parity, nibble) ((parity) << (nibble))
-
-static const uint16_t pbit16 =
-       pbit(0, 0) | pbit(1, 1) | pbit(1, 2) | pbit(0, 3)
-       | pbit(1, 4) | pbit(0, 5) | pbit(0, 6) | pbit(1, 7)
-       | pbit(1, 8) | pbit(0, 9) | pbit(0, 0xa) | pbit(1, 0xb)
-       | pbit(0, 0xc) | pbit(1, 0xd) | pbit(1, 0xe) | pbit(0, 0xf);
-
-#define nibble_parity(nibble) (pbit16 & pbit(1, (nibble)))
-
 /**
  * Construct a "cmd" byte, in lSB bit order, which swd_driver.read_reg()
  * and swd_driver.write_reg() methods will use directly.
@@ -54,7 +43,7 @@ static inline uint8_t swd_cmd(bool is_read, bool is_ap, uint8_t regnum)
                | ((regnum & 0xc) << 1);
 
        /* 8 cmd bits 4:1 may be set */
-       if (nibble_parity(cmd >> 1))
+       if (parity_u32(cmd))
                cmd |= SWD_CMD_PARITY;
 
        /* driver handles START, STOP, and TRN */