diff options
| author | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2017-02-19 10:44:44 +0100 |
|---|---|---|
| committer | Luc Van Oostenryck <luc.vanoostenryck@gmail.com> | 2018-07-23 20:24:42 +0200 |
| commit | c2fcd59e6f0813171ea870f508964d1715efd7ec (patch) | |
| tree | 7d0f20e27d8c9006576dfdac2a082d7eb471a883 | |
| parent | 68e67287e6f373e100813dbebd10b01ab722dd18 (diff) | |
| download | sparse-dev-c2fcd59e6f0813171ea870f508964d1715efd7ec.tar.gz | |
bits: add helpers for zero & sign-extension
Zero & sign-extensions are relatively common operations
which are currently open-coded at each use.
Define helpers for doing these operations.
Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
| -rw-r--r-- | bits.h | 61 | ||||
| -rw-r--r-- | lib.h | 1 | ||||
| -rw-r--r-- | symbol.h | 8 |
3 files changed, 70 insertions, 0 deletions
@@ -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 @@ -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) @@ -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) |
