aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
-rw-r--r--bits.h61
-rw-r--r--lib.h1
-rw-r--r--symbol.h8
3 files changed, 70 insertions, 0 deletions
diff --git a/bits.h b/bits.h
new file mode 100644
index 00000000..c0dc952e
--- /dev/null
+++ b/bits.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Helper functions for manipulation & testing of integer values
+ * like zero or sign-extensions.
+ *
+ * Copyright (C) 2017 Luc Van Oostenryck
+ *
+ */
+
+#ifndef BITS_H
+#define BITS_H
+
+static inline unsigned long long sign_bit(unsigned size)
+{
+ return 1ULL << (size - 1);
+}
+
+static inline unsigned long long sign_mask(unsigned size)
+{
+ unsigned long long sbit = sign_bit(size);
+ return sbit - 1;
+}
+
+static inline unsigned long long bits_mask(unsigned size)
+{
+ unsigned long long sbit = sign_bit(size);
+ return sbit | (sbit - 1);
+}
+
+
+static inline long long zero_extend(long long val, unsigned size)
+{
+ return val & bits_mask(size);
+}
+
+static inline long long sign_extend(long long val, unsigned size)
+{
+ if (val & sign_bit(size))
+ val |= ~sign_mask(size);
+ return val;
+}
+
+///
+// sign extend @val but only if exactly representable
+static inline long long sign_extend_safe(long long val, unsigned size)
+{
+ unsigned long long mask = bits_mask(size);
+ if (!(val & ~mask))
+ val = sign_extend(val, size);
+ return val;
+}
+
+static inline long long bits_extend(long long val, unsigned size, int is_signed)
+{
+ val = zero_extend(val, size);
+ if (is_signed)
+ val = sign_extend(val, size);
+ return val;
+}
+
+#endif
diff --git a/lib.h b/lib.h
index 7362111c..3cd8560a 100644
--- a/lib.h
+++ b/lib.h
@@ -34,6 +34,7 @@
#include "compat.h"
#include "ptrlist.h"
#include "utils.h"
+#include "bits.h"
#define DO_STRINGIFY(x) #x
#define STRINGIFY(x) DO_STRINGIFY(x)
diff --git a/symbol.h b/symbol.h
index 6b891edd..1cad6d05 100644
--- a/symbol.h
+++ b/symbol.h
@@ -453,6 +453,14 @@ static inline int get_sym_type(struct symbol *type)
return type->type;
}
+static inline long long extend_value(long long val, struct symbol *ctype)
+{
+ int is_signed = !(ctype->ctype.modifiers & MOD_UNSIGNED);
+ unsigned size = ctype->bit_size;
+
+ return bits_extend(val, size, is_signed);
+}
+
static inline struct symbol *lookup_keyword(struct ident *ident, enum namespace ns)
{
if (!ident->keyword)