]> git.sur5r.net Git - openocd/blobdiff - src/helper/types.h
helper/types: cast to uint32_t,uint16_t to avoid UB by shifting int too far
[openocd] / src / helper / types.h
index 12b95150b4999fbe115c2950cd86ac0edcc73c23..5e35c13b796c520487fcb2b8f4e1a85bf7ed55ef 100644 (file)
  *   GNU General Public License for more details.                          *
  *                                                                         *
  *   You should have received a copy of the GNU General Public License     *
- *   along with this program; if not, write to the                         *
- *   Free Software Foundation, Inc.,                                       *
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
  ***************************************************************************/
-#ifndef TYPES_H
-#define TYPES_H
+
+#ifndef OPENOCD_HELPER_TYPES_H
+#define OPENOCD_HELPER_TYPES_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 
 #include <stddef.h>
+#include <assert.h>
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #endif
@@ -110,35 +114,82 @@ typedef bool _Bool;
  * Again, note that the "buf" pointer in memory is probably unaligned.
  */
 
+static inline uint64_t le_to_h_u64(const uint8_t *buf)
+{
+       return (uint64_t)((uint64_t)buf[0] |
+                         (uint64_t)buf[1] << 8 |
+                         (uint64_t)buf[2] << 16 |
+                         (uint64_t)buf[3] << 24 |
+                         (uint64_t)buf[4] << 32 |
+                         (uint64_t)buf[5] << 40 |
+                         (uint64_t)buf[6] << 48 |
+                         (uint64_t)buf[7] << 56);
+}
 
 static inline uint32_t le_to_h_u32(const uint8_t* buf)
 {
-       return (uint32_t)(buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24);
+       return (uint32_t)((uint32_t)buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16 | (uint32_t)buf[3] << 24);
 }
 
 static inline uint32_t le_to_h_u24(const uint8_t* buf)
 {
-       return (uint32_t)(buf[0] | buf[1] << 8 | buf[2] << 16);
+       return (uint32_t)((uint32_t)buf[0] | (uint32_t)buf[1] << 8 | (uint32_t)buf[2] << 16);
 }
 
 static inline uint16_t le_to_h_u16(const uint8_t* buf)
 {
-       return (uint16_t)(buf[0] | buf[1] << 8);
+       return (uint16_t)((uint16_t)buf[0] | (uint16_t)buf[1] << 8);
+}
+
+static inline uint64_t be_to_h_u64(const uint8_t *buf)
+{
+       return (uint64_t)((uint64_t)buf[7] |
+                         (uint64_t)buf[6] << 8 |
+                         (uint64_t)buf[5] << 16 |
+                         (uint64_t)buf[4] << 24 |
+                         (uint64_t)buf[3] << 32 |
+                         (uint64_t)buf[2] << 40 |
+                         (uint64_t)buf[1] << 48 |
+                         (uint64_t)buf[0] << 56);
 }
 
 static inline uint32_t be_to_h_u32(const uint8_t* buf)
 {
-       return (uint32_t)(buf[3] | buf[2] << 8 | buf[1] << 16 | buf[0] << 24);
+       return (uint32_t)((uint32_t)buf[3] | (uint32_t)buf[2] << 8 | (uint32_t)buf[1] << 16 | (uint32_t)buf[0] << 24);
 }
 
 static inline uint32_t be_to_h_u24(const uint8_t* buf)
 {
-       return (uint32_t)(buf[2] | buf[1] << 8 | buf[0] << 16);
+       return (uint32_t)((uint32_t)buf[2] | (uint32_t)buf[1] << 8 | (uint32_t)buf[0] << 16);
 }
 
 static inline uint16_t be_to_h_u16(const uint8_t* buf)
 {
-       return (uint16_t)(buf[1] | buf[0] << 8);
+       return (uint16_t)((uint16_t)buf[1] | (uint16_t)buf[0] << 8);
+}
+
+static inline void h_u64_to_le(uint8_t *buf, int64_t val)
+{
+       buf[7] = (uint8_t) (val >> 56);
+       buf[6] = (uint8_t) (val >> 48);
+       buf[5] = (uint8_t) (val >> 40);
+       buf[4] = (uint8_t) (val >> 32);
+       buf[3] = (uint8_t) (val >> 24);
+       buf[2] = (uint8_t) (val >> 16);
+       buf[1] = (uint8_t) (val >> 8);
+       buf[0] = (uint8_t) (val >> 0);
+}
+
+static inline void h_u64_to_be(uint8_t *buf, int64_t val)
+{
+       buf[0] = (uint8_t) (val >> 56);
+       buf[1] = (uint8_t) (val >> 48);
+       buf[2] = (uint8_t) (val >> 40);
+       buf[3] = (uint8_t) (val >> 32);
+       buf[4] = (uint8_t) (val >> 24);
+       buf[5] = (uint8_t) (val >> 16);
+       buf[6] = (uint8_t) (val >> 8);
+       buf[7] = (uint8_t) (val >> 0);
 }
 
 static inline void h_u32_to_le(uint8_t* buf, int val)
@@ -183,6 +234,65 @@ static inline void h_u16_to_be(uint8_t* buf, int val)
        buf[1] = (uint8_t) (val >> 0);
 }
 
+/**
+ * Byte-swap buffer 16-bit.
+ *
+ * Len must be even, dst and src must be either the same or non-overlapping.
+ *
+ * @param dst Destination buffer.
+ * @param src Source buffer.
+ * @param len Length of source (and destination) buffer, in bytes.
+ */
+static inline void buf_bswap16(uint8_t *dst, const uint8_t *src, size_t len)
+{
+       assert(len % 2 == 0);
+       assert(dst == src || dst + len <= src || src + len <= dst);
+
+       for (size_t n = 0; n < len; n += 2) {
+               uint16_t x = be_to_h_u16(src + n);
+               h_u16_to_le(dst + n, x);
+       }
+}
+
+/**
+ * Byte-swap buffer 32-bit.
+ *
+ * Len must be divisible by four, dst and src must be either the same or non-overlapping.
+ *
+ * @param dst Destination buffer.
+ * @param src Source buffer.
+ * @param len Length of source (and destination) buffer, in bytes.
+ */
+static inline void buf_bswap32(uint8_t *dst, const uint8_t *src, size_t len)
+{
+       assert(len % 4 == 0);
+       assert(dst == src || dst + len <= src || src + len <= dst);
+
+       for (size_t n = 0; n < len; n += 4) {
+               uint32_t x = be_to_h_u32(src + n);
+               h_u32_to_le(dst + n, x);
+       }
+}
+
+/**
+ * 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
@@ -191,12 +301,21 @@ static inline void h_u16_to_be(uint8_t* buf, int val)
  */
 
 #if !defined(_STDINT_H)
-#define PRIx32 "x"
 #define PRId32 "d"
-#define SCNx32 "x"
 #define PRIi32 "i"
+#define PRIo32 "o"
 #define PRIu32 "u"
+#define PRIx32 "x"
+#define PRIX32 "X"
+#define SCNx32 "x"
 #define PRId8 PRId32
+#define SCNx64 "llx"
+#define PRId64 "lld"
+#define PRIi64 "lli"
+#define PRIo64 "llo"
+#define PRIu64 "llu"
+#define PRIx64 "llx"
+#define PRIX64 "llX"
 
 typedef CYG_ADDRWORD intptr_t;
 typedef int64_t intmax_t;
@@ -215,11 +334,11 @@ typedef uint64_t uintmax_t;
 #define UINT64_MAX (__CONCAT(INT64_MAX, U) * 2ULL + 1ULL)
 #endif
 
-    #ifndef LLONG_MAX
+       #ifndef LLONG_MAX
        #define ULLONG_MAX      UINT64_C(0xFFFFFFFFFFFFFFFF)
        #define LLONG_MAX       INT64_C(0x7FFFFFFFFFFFFFFF)
        #define LLONG_MIN       ULLONG_MAX
-    #endif
+       #endif
 
 
 #define ULLONG_MAX 18446744073709551615
@@ -230,4 +349,23 @@ typedef uint64_t uintmax_t;
 
 #endif
 
-#endif /* TYPES_H */
+#if BUILD_TARGET64
+typedef uint64_t target_addr_t;
+#define TARGET_ADDR_MAX UINT64_MAX
+#define TARGET_PRIdADDR PRId64
+#define TARGET_PRIuADDR PRIu64
+#define TARGET_PRIoADDR PRIo64
+#define TARGET_PRIxADDR PRIx64
+#define TARGET_PRIXADDR PRIX64
+#else
+typedef uint32_t target_addr_t;
+#define TARGET_ADDR_MAX UINT32_MAX
+#define TARGET_PRIdADDR PRId32
+#define TARGET_PRIuADDR PRIu32
+#define TARGET_PRIoADDR PRIo32
+#define TARGET_PRIxADDR PRIx32
+#define TARGET_PRIXADDR PRIX32
+#endif
+#define TARGET_ADDR_FMT "0x%8.8" TARGET_PRIxADDR
+
+#endif /* OPENOCD_HELPER_TYPES_H */