1 /* SPDX-License-Identifier: MIT */
   2 /*
   3  * Helper functions for manipulation & testing of integer values
   4  * like zero or sign-extensions.
   5  *
   6  * Copyright (C) 2017 Luc Van Oostenryck
   7  *
   8  */
   9 
  10 #ifndef BITS_H
  11 #define BITS_H
  12 
  13 static inline unsigned long long sign_bit(unsigned size)
  14 {
  15         return 1ULL << (size - 1);
  16 }
  17 
  18 static inline unsigned long long sign_mask(unsigned size)
  19 {
  20         unsigned long long sbit = sign_bit(size);
  21         return sbit - 1;
  22 }
  23 
  24 static inline unsigned long long bits_mask(unsigned size)
  25 {
  26         unsigned long long sbit = sign_bit(size);
  27         return sbit | (sbit - 1);
  28 }
  29 
  30 
  31 static inline long long zero_extend(long long val, unsigned size)
  32 {
  33         return val & bits_mask(size);
  34 }
  35 
  36 static inline long long sign_extend(long long val, unsigned size)
  37 {
  38         if (val & sign_bit(size))
  39                 val |= ~sign_mask(size);
  40         return val;
  41 }
  42 
  43 ///
  44 // sign extend @val but only if exactly representable
  45 static inline long long sign_extend_safe(long long val, unsigned size)
  46 {
  47         unsigned long long mask = bits_mask(size);
  48         if (!(val & ~mask))
  49                 val = sign_extend(val, size);
  50         return val;
  51 }
  52 
  53 static inline long long bits_extend(long long val, unsigned size, int is_signed)
  54 {
  55         val = zero_extend(val, size);
  56         if (is_signed)
  57                 val = sign_extend(val, size);
  58         return val;
  59 }
  60 
  61 #endif