From 44e6a135c307b86281896c3c196a4336eb24328a Mon Sep 17 00:00:00 2001
From: Kostyantyn Vorobyov <kostyantyn.vorobyov@cea.fr>
Date: Wed, 16 Mar 2016 17:37:12 +0100
Subject: [PATCH] [RTL] Added e_acsl_bits macro to provide common macros and
 functions for bit manipulations

---
 src/plugins/e-acsl/share/e-acsl/e_acsl_bits.h | 128 ++++++++++++++++++
 1 file changed, 128 insertions(+)
 create mode 100644 src/plugins/e-acsl/share/e-acsl/e_acsl_bits.h

diff --git a/src/plugins/e-acsl/share/e-acsl/e_acsl_bits.h b/src/plugins/e-acsl/share/e-acsl/e_acsl_bits.h
new file mode 100644
index 00000000000..e849d0ab750
--- /dev/null
+++ b/src/plugins/e-acsl/share/e-acsl/e_acsl_bits.h
@@ -0,0 +1,128 @@
+/**************************************************************************/
+/*                                                                        */
+/*  This file is part of the Frama-C's E-ACSL plug-in.                    */
+/*                                                                        */
+/*  Copyright (C) 2012-2015                                               */
+/*    CEA (Commissariat à l'énergie atomique et aux énergies              */
+/*         alternatives)                                                  */
+/*                                                                        */
+/*  you can redistribute it and/or modify it under the terms of the GNU   */
+/*  Lesser General Public License as published by the Free Software       */
+/*  Foundation, version 2.1.                                              */
+/*                                                                        */
+/*  It is distributed in the hope that it will be useful,                 */
+/*  but WITHOUT ANY WARRANTY; without even the implied warranty of        */
+/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         */
+/*  GNU Lesser General Public License for more details.                   */
+/*                                                                        */
+/*  See the GNU Lesser General Public License version 2.1                 */
+/*  for more details (enclosed in the file license/LGPLv2.1).             */
+/*                                                                        */
+/**************************************************************************/
+
+#ifndef E_ACSL_BITS
+#define E_ACSL_BITS
+
+/* FIXME: Present implementation is built for little-endian byte order.  That
+ * is, the implementation assumes that least significant bytes are stored at
+ * the highest memory addresses. In future support for big-endian/PDP byte
+ * orders should also be provided. */
+
+/* Check if we have little-endian and abort the execution otherwise. */
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#  error "Big-endian byte order is unsupported"
+#elif __BYTE_ORDER__ == __ORDER_PDP_ENDIAN__
+#  error "PDP byte order is unsupported"
+#elif __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
+#  error "UNknown byte order"
+#endif
+
+/* Bit-level manipulations {{{ */
+/* Set a given bit in a number to '1'.
+ * Example: bitset(7, x) changes 7th lowest bit of x to 1 */
+#define bitset(_bit,_number) (_number |= 1 << _bit)
+
+/* Same as bitset but the bit is set of 0 */
+#define bitclear(_bit, _number) (_number &= ~(1 << _bit))
+
+/* Evaluates to a true value if a given bit in a number is set to 1. */
+#define bitcheck(_bit, _number) ((_number >> _bit) & 1)
+
+/* Toggle a given bit. */
+#define bittoggle(_bit, _number) (_number ^= 1 << _bit)
+
+/* Set a given bit to a specified value (e.g., 0 or 1). */
+#define bitchange(_bit, _val, _number) \
+  (_number ^= (-_val ^ _number) & (1 << _bit))
+
+/* Fill the first n + skip bits of the memory area pointed to by s with ones
+ * (c != 0) or zeroes (c == 0).
+ *
+ * Example:
+ *  let p1 be a pointer to  1111 1111 1111 1111 and
+ *  p0 be a pointer to 0000 0000 0000 0000, then
+ *
+ *  bitwise_memset(p0, 4, 1, 0)
+ *    1111 0000 0000 0000
+ *  bitwise_memset(p1, 3, 0, 2)
+ *    1100 0111 1111 1111
+ *
+ * NB: In the grand scheme of things it is convenient to have a function that
+ * can set bits in a universal manner (such as the function below). On the other
+ * hand for blocks smaller than 64 bits using integers may be a faster way of
+ * dealing with bitwise operations. */
+static void bitwise_memset(void *s, size_t n, int c, unsigned int skip) {
+  char *p = (char*)s;
+
+  if (skip) {
+    p += (skip/8);
+    skip = skip%8;
+
+    if (skip) {
+      int mask = 255;
+
+      if (skip)
+        mask = (mask << skip);
+      if (n < 8 - skip)
+        mask = mask & (255 >> (8 - skip - n));
+
+      n = (n >= 8 - skip) ? n - 8 + skip : 0;
+
+      if (c)
+        p[0]  = p[0] | mask;
+      else
+        p[0]  = p[0] & (mask ^ 255);
+      p++;
+    }
+  }
+
+  if (n) {
+    size_t bytes = n/8;
+    if (bytes)
+      memset(p, c ? 255 : 0, bytes);
+
+    if (c)
+      p[bytes]  = p[bytes] | (255 >> (8 - n%8));
+    else
+      p[bytes]  = p[bytes] & (255 << n%8);
+  }
+}
+
+/* Same as bitwise_memset with skip parameter 0 but sets the bits from right
+ * to left. Example:
+ *  let p1 be a pointer to  1111 1111 1111 1111, then
+ *    bitwise_memset_backwards(p1, 5, 0) will lead to
+ *      1111 1111 1110 0000 */
+static void bitwise_memset_backwards(void *s, size_t n, int c) {
+  char *p = (char*)s;
+  int bytes = n/8;
+  p -= bytes;
+  memset(p, c ? 255 : 0, bytes);
+  p--;
+  if (!c)
+    p[0]  = p[0] & (255 >> n%8);
+  else
+    p[0]  = p[0] | (255 << (8 - n%8));
+}
+/* }}} */
+#endif
-- 
GitLab