]> 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 7a845284e4467cd8f4db5fad568eebfe02f50828..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.,                                       *
- *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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)
@@ -223,6 +274,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
@@ -231,14 +301,21 @@ static inline void buf_bswap32(uint8_t *dst, const uint8_t *src, size_t len)
  */
 
 #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;
@@ -272,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 */