summaryrefslogtreecommitdiff
path: root/xserver/include/misc.h
diff options
context:
space:
mode:
Diffstat (limited to 'xserver/include/misc.h')
-rw-r--r--xserver/include/misc.h121
1 files changed, 59 insertions, 62 deletions
diff --git a/xserver/include/misc.h b/xserver/include/misc.h
index 2dedf6d63..546ed5c96 100644
--- a/xserver/include/misc.h
+++ b/xserver/include/misc.h
@@ -128,21 +128,6 @@ typedef struct _xReq *xReqPtr;
#define USE_BACKGROUND_PIXEL 3
#define USE_BORDER_PIXEL 3
-/* byte swap a 32-bit literal */
-static inline uint32_t
-lswapl(uint32_t x)
-{
- return ((x & 0xff) << 24) |
- ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x >> 24) & 0xff);
-}
-
-/* byte swap a 16-bit literal */
-static inline uint16_t
-lswaps(uint16_t x)
-{
- return (uint16_t)((x & 0xff) << 8) | ((x >> 8) & 0xff);
-}
-
#undef min
#undef max
@@ -311,88 +296,100 @@ __builtin_constant_p(int x)
}
#endif
-/* byte swap a 64-bit value */
-static inline void
-swap_uint64(uint64_t *x)
+#ifndef bswap_64
+static inline uint64_t
+bswap_64(uint64_t x)
{
- char n;
-
- n = ((char *) x)[0];
- ((char *) x)[0] = ((char *) x)[7];
- ((char *) x)[7] = n;
-
- n = ((char *) x)[1];
- ((char *) x)[1] = ((char *) x)[6];
- ((char *) x)[6] = n;
-
- n = ((char *) x)[2];
- ((char *) x)[2] = ((char *) x)[5];
- ((char *) x)[5] = n;
-
- n = ((char *) x)[3];
- ((char *) x)[3] = ((char *) x)[4];
- ((char *) x)[4] = n;
+ return (((x & 0xFF00000000000000ull) >> 56) |
+ ((x & 0x00FF000000000000ull) >> 40) |
+ ((x & 0x0000FF0000000000ull) >> 24) |
+ ((x & 0x000000FF00000000ull) >> 8) |
+ ((x & 0x00000000FF000000ull) << 8) |
+ ((x & 0x0000000000FF0000ull) << 24) |
+ ((x & 0x000000000000FF00ull) << 40) |
+ ((x & 0x00000000000000FFull) << 56));
}
+#endif
#define swapll(x) do { \
if (sizeof(*(x)) != 8) \
wrong_size(); \
- swap_uint64((uint64_t *)(x)); \
+ *(x) = bswap_64(*(x)); \
} while (0)
-/* byte swap a 32-bit value */
-static inline void
-swap_uint32(uint32_t * x)
+#ifndef bswap_32
+static inline uint32_t
+bswap_32(uint32_t x)
+{
+ return (((x & 0xFF000000) >> 24) |
+ ((x & 0x00FF0000) >> 8) |
+ ((x & 0x0000FF00) << 8) |
+ ((x & 0x000000FF) << 24));
+}
+#endif
+
+static inline Bool
+checked_int64_add(int64_t *out, int64_t a, int64_t b)
+{
+ /* Do the potentially overflowing math as uint64_t, as signed
+ * integers in C are undefined on overflow (and the compiler may
+ * optimize out our overflow check below, otherwise)
+ */
+ int64_t result = (uint64_t)a + (uint64_t)b;
+ /* signed addition overflows if operands have the same sign, and
+ * the sign of the result doesn't match the sign of the inputs.
+ */
+ Bool overflow = (a < 0) == (b < 0) && (a < 0) != (result < 0);
+
+ *out = result;
+
+ return overflow;
+}
+
+static inline Bool
+checked_int64_subtract(int64_t *out, int64_t a, int64_t b)
{
- char n = ((char *) x)[0];
+ int64_t result = (uint64_t)a - (uint64_t)b;
+ Bool overflow = (a < 0) != (b < 0) && (a < 0) != (result < 0);
- ((char *) x)[0] = ((char *) x)[3];
- ((char *) x)[3] = n;
- n = ((char *) x)[1];
- ((char *) x)[1] = ((char *) x)[2];
- ((char *) x)[2] = n;
+ *out = result;
+
+ return overflow;
}
#define swapl(x) do { \
if (sizeof(*(x)) != 4) \
wrong_size(); \
- if (__builtin_constant_p((uintptr_t)(x) & 3) && ((uintptr_t)(x) & 3) == 0) \
- *(x) = lswapl(*(x)); \
- else \
- swap_uint32((uint32_t *)(x)); \
+ *(x) = bswap_32(*(x)); \
} while (0)
-/* byte swap a 16-bit value */
-static inline void
-swap_uint16(uint16_t * x)
+#ifndef bswap_16
+static inline uint16_t
+bswap_16(uint16_t x)
{
- char n = ((char *) x)[0];
-
- ((char *) x)[0] = ((char *) x)[1];
- ((char *) x)[1] = n;
+ return (((x & 0xFF00) >> 8) |
+ ((x & 0x00FF) << 8));
}
+#endif
#define swaps(x) do { \
if (sizeof(*(x)) != 2) \
wrong_size(); \
- if (__builtin_constant_p((uintptr_t)(x) & 1) && ((uintptr_t)(x) & 1) == 0) \
- *(x) = lswaps(*(x)); \
- else \
- swap_uint16((uint16_t *)(x)); \
+ *(x) = bswap_16(*(x)); \
} while (0)
/* copy 32-bit value from src to dst byteswapping on the way */
#define cpswapl(src, dst) do { \
if (sizeof((src)) != 4 || sizeof((dst)) != 4) \
wrong_size(); \
- (dst) = lswapl((src)); \
+ (dst) = bswap_32((src)); \
} while (0)
/* copy short from src to dst byteswapping on the way */
#define cpswaps(src, dst) do { \
if (sizeof((src)) != 2 || sizeof((dst)) != 2) \
wrong_size(); \
- (dst) = lswaps((src)); \
+ (dst) = bswap_16((src)); \
} while (0)
extern _X_EXPORT void SwapLongs(CARD32 *list, unsigned long count);