NASM 2.11
[platform/upstream/nasm.git] / nasmlib.h
index 64afa45..d11e6e0 100644 (file)
--- a/nasmlib.h
+++ b/nasmlib.h
@@ -1,9 +1,38 @@
-/* nasmlib.h   header file for nasmlib.c
+/* ----------------------------------------------------------------------- *
  *
- * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
- * Julian Hall. All rights reserved. The software is
- * redistributable under the licence given in the file "Licence"
- * distributed in the NASM archive.
+ *   Copyright 1996-2009 The NASM Authors - All Rights Reserved
+ *   See the file AUTHORS included with the NASM distribution for
+ *   the specific copyright holders.
+ *
+ *   Redistribution and use in source and binary forms, with or without
+ *   modification, are permitted provided that the following
+ *   conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above
+ *     copyright notice, this list of conditions and the following
+ *     disclaimer in the documentation and/or other materials provided
+ *     with the distribution.
+ *
+ *     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ *     CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *     INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ *     OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * nasmlib.h    header file for nasmlib.c
  */
 
 #ifndef NASM_NASMLIB_H
 #endif
 
 /*
+ * tolower table -- avoids a function call on some platforms.
+ * NOTE: unlike the tolower() function in ctype, EOF is *NOT*
+ * a permitted value, for obvious reasons.
+ */
+void tolower_init(void);
+extern unsigned char nasm_tolower_tab[256];
+#define nasm_tolower(x) nasm_tolower_tab[(unsigned char)(x)]
+
+/* Wrappers around <ctype.h> functions */
+/* These are only valid for values that cannot include EOF */
+#define nasm_isspace(x)  isspace((unsigned char)(x))
+#define nasm_isalpha(x)  isalpha((unsigned char)(x))
+#define nasm_isdigit(x)  isdigit((unsigned char)(x))
+#define nasm_isalnum(x)  isalnum((unsigned char)(x))
+#define nasm_isxdigit(x) isxdigit((unsigned char)(x))
+
+/*
  * If this is defined, the wrappers around malloc et al will
  * transform into logging variants, which will cause NASM to create
  * a file called `malloc.log' when run, and spew details of all its
  * An error reporting function should look like this.
  */
 typedef void (*efunc) (int severity, const char *fmt, ...);
+typedef void (*vefunc) (int severity, const char *fmt, va_list ap);
+#ifdef __GNUC__
+void nasm_error(int severity, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
+#else
+void nasm_error(int severity, const char *fmt, ...);
+#endif
+void nasm_set_verror(vefunc);
 
 /*
  * These are the error severity codes which get passed as the first
  * argument to an efunc.
  */
 
-#define ERR_DEBUG      0x00000008      /* put out debugging message */
-#define ERR_WARNING    0x00000000      /* warn only: no further action */
-#define ERR_NONFATAL   0x00000001      /* terminate assembly after phase */
-#define ERR_FATAL      0x00000002      /* instantly fatal: exit with error */
-#define ERR_PANIC      0x00000003      /* internal error: panic instantly
+#define ERR_DEBUG       0x00000008      /* put out debugging message */
+#define ERR_WARNING     0x00000000      /* warn only: no further action */
+#define ERR_NONFATAL    0x00000001      /* terminate assembly after phase */
+#define ERR_FATAL       0x00000002      /* instantly fatal: exit with error */
+#define ERR_PANIC       0x00000003      /* internal error: panic instantly
                                          * and dump core for reference */
-#define ERR_MASK       0x0000000F      /* mask off the above codes */
-#define ERR_NOFILE     0x00000010      /* don't give source file name/line */
-#define ERR_USAGE      0x00000020      /* print a usage message */
-#define ERR_PASS1      0x00000040      /* only print this error on pass one */
+#define ERR_MASK        0x0000000F      /* mask off the above codes */
+#define ERR_NOFILE      0x00000010      /* don't give source file name/line */
+#define ERR_USAGE       0x00000020      /* print a usage message */
+#define ERR_PASS1       0x00000040      /* only print this error on pass one */
+#define ERR_PASS2       0x00000080
+#define ERR_NO_SEVERITY 0x00000100      /* suppress printing severity */
 
 /*
  * These codes define specific types of suppressible warning.
  */
 
-#define ERR_WARN_MASK  0x0000FF00      /* the mask for this feature */
-#define ERR_WARN_SHR  8         /* how far to shift right */
-
-#define ERR_WARN_MNP   0x00000100      /* macro-num-parameters warning */
-#define ERR_WARN_MSR   0x00000200      /* macro self-reference */
-#define ERR_WARN_OL    0x00000300      /* orphan label (no colon, and
-                                         * alone on line) */
-#define ERR_WARN_NOV   0x00000400      /* numeric overflow */
-#define ERR_WARN_GNUELF        0x00000500      /* using GNU ELF extensions */
-#define ERR_WARN_MAX   5       /* the highest numbered one */
+#define ERR_WARN_MASK   0xFFFFF000      /* the mask for this feature */
+#define ERR_WARN_SHR    12              /* how far to shift right */
+
+#define WARN(x)         ((x) << ERR_WARN_SHR)
+#define WARN_IDX(x)     (((x) & ERR_WARN_MASK) >> ERR_WARN_SHR)
+
+#define ERR_WARN_TERM           WARN( 0) /* treat warnings as errors */
+#define ERR_WARN_MNP            WARN( 1) /* macro-num-parameters warning */
+#define ERR_WARN_MSR            WARN( 2) /* macro self-reference */
+#define ERR_WARN_MDP            WARN( 3) /* macro default parameters check */
+#define ERR_WARN_OL             WARN( 4) /* orphan label (no colon, and
+                                          * alone on line) */
+#define ERR_WARN_NOV            WARN( 5) /* numeric overflow */
+#define ERR_WARN_GNUELF         WARN( 6) /* using GNU ELF extensions */
+#define ERR_WARN_FL_OVERFLOW    WARN( 7) /* FP overflow */
+#define ERR_WARN_FL_DENORM      WARN( 8) /* FP denormal */
+#define ERR_WARN_FL_UNDERFLOW   WARN( 9) /* FP underflow */
+#define ERR_WARN_FL_TOOLONG     WARN(10) /* FP too many digits */
+#define ERR_WARN_USER           WARN(11) /* %warning directives */
+#define ERR_WARN_LOCK          WARN(12) /* bad LOCK prefixes */
+#define ERR_WARN_HLE           WARN(13) /* bad HLE prefixes */
+#define ERR_WARN_BND           WARN(14) /* bad BND prefixes */
+#define ERR_WARN_MAX            14       /* the highest numbered one */
 
 /*
  * Wrappers around malloc, realloc and free. nasm_malloc will
@@ -76,23 +144,23 @@ typedef void (*efunc) (int severity, const char *fmt, ...);
  * passed a NULL pointer; nasm_free will do nothing if it is passed
  * a NULL pointer.
  */
-void nasm_set_malloc_error(efunc);
+void nasm_init_malloc_error(void);
 #ifndef LOGALLOC
 void *nasm_malloc(size_t);
 void *nasm_zalloc(size_t);
 void *nasm_realloc(void *, size_t);
 void nasm_free(void *);
 char *nasm_strdup(const char *);
-char *nasm_strndup(char *, size_t);
+char *nasm_strndup(const char *, size_t);
 #else
-void *nasm_malloc_log(char *, int, size_t);
-void *nasm_zalloc_log(char *, int, size_t);
-void *nasm_realloc_log(char *, int, void *, size_t);
-void nasm_free_log(char *, int, void *);
-char *nasm_strdup_log(char *, int, const char *);
-char *nasm_strndup_log(char *, int, char *, size_t);
+void *nasm_malloc_log(const char *, int, size_t);
+void *nasm_zalloc_log(const char *, int, size_t);
+void *nasm_realloc_log(const char *, int, void *, size_t);
+void nasm_free_log(const char *, int, void *);
+char *nasm_strdup_log(const char *, int, const char *);
+char *nasm_strndup_log(const char *, int, const char *, size_t);
 #define nasm_malloc(x) nasm_malloc_log(__FILE__,__LINE__,x)
-#define nasm_zalloc(x) nasm_malloc_log(__FILE__,__LINE__,x)
+#define nasm_zalloc(x) nasm_zalloc_log(__FILE__,__LINE__,x)
 #define nasm_realloc(x,y) nasm_realloc_log(__FILE__,__LINE__,x,y)
 #define nasm_free(x) nasm_free_log(__FILE__,__LINE__,x)
 #define nasm_strdup(x) nasm_strdup_log(__FILE__,__LINE__,x)
@@ -100,6 +168,21 @@ char *nasm_strndup_log(char *, int, char *, size_t);
 #endif
 
 /*
+ * NASM assert failure
+ */
+no_return nasm_assert_failed(const char *, int, const char *);
+#define nasm_assert(x)                                          \
+    do {                                                        \
+        if (unlikely(!(x)))                                     \
+            nasm_assert_failed(__FILE__,__LINE__,#x);           \
+    } while (0)
+
+/*
+ * NASM failure at build time if x != 0
+ */
+#define nasm_build_assert(x) (void)(sizeof(char[1-2*!!(x)]))
+
+/*
  * ANSI doesn't guarantee the presence of `stricmp' or
  * `strcasecmp'.
  */
@@ -116,29 +199,33 @@ int nasm_stricmp(const char *, const char *);
 #elif defined(HAVE_STRNICMP)
 #define nasm_strnicmp strnicmp
 #else
-int nasm_strnicmp(const char *, const char *, int);
+int nasm_strnicmp(const char *, const char *, size_t);
 #endif
 
+int nasm_memicmp(const char *, const char *, size_t);
+
 #if defined(HAVE_STRSEP)
 #define nasm_strsep strsep
 #else
 char *nasm_strsep(char **stringp, const char *delim);
 #endif
 
+/* This returns the numeric value of a given 'digit'. */
+#define numvalue(c)         ((c) >= 'a' ? (c) - 'a' + 10 : (c) >= 'A' ? (c) - 'A' + 10 : (c) - '0')
 
 /*
  * Convert a string into a number, using NASM number rules. Sets
- * `*error' to TRUE if an error occurs, and FALSE otherwise.
+ * `*error' to true if an error occurs, and false otherwise.
  */
-int64_t readnum(char *str, int *error);
+int64_t readnum(char *str, bool *error);
 
 /*
  * Convert a character constant into a number. Sets
- * `*warn' to TRUE if an overflow occurs, and FALSE otherwise.
+ * `*warn' to true if an overflow occurs, and false otherwise.
  * str points to and length covers the middle of the string,
  * without the quotes.
  */
-int64_t readstrnum(char *str, int length, int *warn);
+int64_t readstrnum(char *str, int length, bool *warn);
 
 /*
  * seg_init: Initialise the segment-number allocator.
@@ -151,132 +238,156 @@ int32_t seg_alloc(void);
  * many output formats will be able to make use of this: a standard
  * function to add an extension to the name of the input file
  */
-#ifdef NASM_NASM_H
-void standard_extension(char *inname, char *outname, char *extension,
-                        efunc error);
-#endif
+void standard_extension(char *inname, char *outname, char *extension);
 
 /*
- * some handy macros that will probably be of use in more than one
- * output format: convert integers into little-endian byte packed
- * format in memory
+ * Utility macros...
+ *
+ * This is a useful #define which I keep meaning to use more often:
+ * the number of elements of a statically defined array.
  */
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
 
-#define WRITECHAR(p,v) \
-  do { \
-    *(p)++ = (v) & 0xFF; \
-  } while (0)
-
-#define WRITESHORT(p,v) \
-  do { \
-    WRITECHAR(p,v); \
-    WRITECHAR(p,(v) >> 8); \
-  } while (0)
-
-#define WRITELONG(p,v) \
-  do { \
-    WRITECHAR(p,v); \
-    WRITECHAR(p,(v) >> 8); \
-    WRITECHAR(p,(v) >> 16); \
-    WRITECHAR(p,(v) >> 24); \
-  } while (0)
-  
-#define WRITEDLONG(p,v) \
-  do { \
-    WRITECHAR(p,v); \
-    WRITECHAR(p,(v) >> 8); \
-    WRITECHAR(p,(v) >> 16); \
-    WRITECHAR(p,(v) >> 24); \
-    WRITECHAR(p,(v) >> 32); \
-    WRITECHAR(p,(v) >> 40); \
-    WRITECHAR(p,(v) >> 48); \
-    WRITECHAR(p,(v) >> 56); \
-  } while (0)
+/*
+ * List handling
+ *
+ *  list_for_each - regular iterator over list
+ *  list_for_each_safe - the same but safe against list items removal
+ *  list_last - find the last element in a list
+ */
+#define list_for_each(pos, head)                        \
+    for (pos = head; pos; pos = pos->next)
+#define list_for_each_safe(pos, n, head)                \
+    for (pos = head, n = (pos ? pos->next : NULL); pos; \
+        pos = n, n = (n ? n->next : NULL))
+#define list_last(pos, head)                            \
+    for (pos = head; pos && pos->next; pos = pos->next) \
+        ;
+#define list_reverse(head, prev, next)                  \
+    do {                                                \
+        if (!head || !head->next)                       \
+            break;                                      \
+        prev = NULL;                                    \
+        while (head) {                                  \
+            next = head->next;                          \
+            head->next = prev;                          \
+            prev = head;                                \
+            head = next;                                \
+        }                                               \
+        head = prev;                                    \
+    } while (0)
 
 /*
- * and routines to do the same thing to a file
+ * Power of 2 align helpers
  */
-void fwriteint16_t(int data, FILE * fp);
-void fwriteint32_t(int32_t data, FILE * fp);
-void fwriteint64_t(int64_t data, FILE * fp);
+#define ALIGN_MASK(v, mask)     (((v) + (mask)) & ~(mask))
+#define ALIGN(v, a)             ALIGN_MASK(v, (a) - 1)
+#define IS_ALIGNED(v, a)        (((v) & ((a) - 1)) == 0)
 
 /*
- * Routines to manage a dynamic random access array of int32_ts which
- * may grow in size to be more than the largest single malloc'able
- * chunk.
+ * some handy macros that will probably be of use in more than one
+ * output format: convert integers into little-endian byte packed
+ * format in memory
  */
 
-#define RAA_BLKSIZE 4096        /* this many longs allocated at once */
-#define RAA_LAYERSIZE 1024      /* this many _pointers_ allocated */
-
-typedef struct RAA RAA;
-typedef union RAA_UNION RAA_UNION;
-typedef struct RAA_LEAF RAA_LEAF;
-typedef struct RAA_BRANCH RAA_BRANCH;
-
-struct RAA {
-    /*
-     * Number of layers below this one to get to the real data. 0
-     * means this structure is a leaf, holding RAA_BLKSIZE real
-     * data items; 1 and above mean it's a branch, holding
-     * RAA_LAYERSIZE pointers to the next level branch or leaf
-     * structures.
-     */
-    int layers;
-    /*
-     * Number of real data items spanned by one position in the
-     * `data' array at this level. This number is 1, trivially, for
-     * a leaf (level 0): for a level 1 branch it should be
-     * RAA_BLKSIZE, and for a level 2 branch it's
-     * RAA_LAYERSIZE*RAA_BLKSIZE.
-     */
-    int32_t stepsize;
-    union RAA_UNION {
-        struct RAA_LEAF {
-            int32_t data[RAA_BLKSIZE];
-        } l;
-        struct RAA_BRANCH {
-            struct RAA *data[RAA_LAYERSIZE];
-        } b;
-    } u;
-};
-
-struct RAA *raa_init(void);
-void raa_free(struct RAA *);
-int32_t raa_read(struct RAA *, int32_t);
-struct RAA *raa_write(struct RAA *r, int32_t posn, int32_t value);
+#if X86_MEMORY
+
+#define WRITECHAR(p,v)                          \
+    do {                                        \
+        *(uint8_t *)(p) = (v);                  \
+        (p) += 1;                               \
+    } while (0)
+
+#define WRITESHORT(p,v)                         \
+    do {                                        \
+        *(uint16_t *)(p) = (v);                 \
+        (p) += 2;                               \
+    } while (0)
+
+#define WRITELONG(p,v)                          \
+    do {                                        \
+        *(uint32_t *)(p) = (v);                 \
+        (p) += 4;                               \
+    } while (0)
+
+#define WRITEDLONG(p,v)                         \
+    do {                                        \
+        *(uint64_t *)(p) = (v);                 \
+        (p) += 8;                               \
+    } while (0)
+
+#define WRITEADDR(p,v,s)                        \
+    do {                                        \
+        uint64_t _wa_v = (v);                   \
+        memcpy((p), &_wa_v, (s));               \
+        (p) += (s);                             \
+    } while (0)
+
+#else /* !X86_MEMORY */
+
+#define WRITECHAR(p,v)                          \
+    do {                                        \
+        uint8_t *_wc_p = (uint8_t *)(p);        \
+        uint8_t _wc_v = (v);                    \
+        _wc_p[0] = _wc_v;                       \
+        (p) = (void *)(_wc_p + 1);              \
+    } while (0)
+
+#define WRITESHORT(p,v)                         \
+    do {                                        \
+        uint8_t *_ws_p = (uint8_t *)(p);        \
+        uint16_t _ws_v = (v);                   \
+        _ws_p[0] = _ws_v;                       \
+        _ws_p[1] = _ws_v >> 8;                  \
+        (p) = (void *)(_ws_p + 2);              \
+    } while (0)
+
+#define WRITELONG(p,v)                          \
+    do {                                        \
+        uint8_t *_wl_p = (uint8_t *)(p);        \
+        uint32_t _wl_v = (v);                   \
+        _wl_p[0] = _wl_v;                       \
+        _wl_p[1] = _wl_v >> 8;                  \
+        _wl_p[2] = _wl_v >> 16;                 \
+        _wl_p[3] = _wl_v >> 24;                 \
+        (p) = (void *)(_wl_p + 4);              \
+    } while (0)
+
+#define WRITEDLONG(p,v)                         \
+    do {                                        \
+        uint8_t *_wq_p = (uint8_t *)(p);        \
+        uint64_t _wq_v = (v);                   \
+        _wq_p[0] = _wq_v;                       \
+        _wq_p[1] = _wq_v >> 8;                  \
+        _wq_p[2] = _wq_v >> 16;                 \
+        _wq_p[3] = _wq_v >> 24;                 \
+        _wq_p[4] = _wq_v >> 32;                 \
+        _wq_p[5] = _wq_v >> 40;                 \
+        _wq_p[6] = _wq_v >> 48;                 \
+        _wq_p[7] = _wq_v >> 56;                 \
+        (p) = (void *)(_wq_p + 8);              \
+    } while (0)
+
+#define WRITEADDR(p,v,s)                        \
+    do {                                        \
+        int _wa_s = (s);                        \
+        uint64_t _wa_v = (v);                   \
+        while (_wa_s--) {                       \
+            WRITECHAR(p,_wa_v);                 \
+            _wa_v >>= 8;                        \
+        }                                       \
+    } while(0)
+
+#endif
 
 /*
- * Routines to manage a dynamic sequential-access array, under the
- * same restriction on maximum mallocable block. This array may be
- * written to in two ways: a contiguous chunk can be reserved of a
- * given size with a pointer returned OR single-byte data may be
- * written. The array can also be read back in the same two ways:
- * as a series of big byte-data blocks or as a list of structures
- * of a given size.
+ * and routines to do the same thing to a file
  */
-
-struct SAA {
-    /*
-     * members `end' and `elem_len' are only valid in first link in
-     * list; `rptr' and `rpos' are used for reading
-     */
-    struct SAA *next, *end, *rptr;
-    int32_t elem_len, length, posn, start, rpos;
-    char *data;
-};
-
-struct SAA *saa_init(int32_t elem_len);    /* 1 == byte */
-void saa_free(struct SAA *);
-void *saa_wstruct(struct SAA *);        /* return a structure of elem_len */
-void saa_wbytes(struct SAA *, const void *, int32_t);      /* write arbitrary bytes */
-void saa_rewind(struct SAA *);  /* for reading from beginning */
-void *saa_rstruct(struct SAA *);        /* return NULL on EOA */
-void *saa_rbytes(struct SAA *, int32_t *); /* return 0 on EOA */
-void saa_rnbytes(struct SAA *, void *, int32_t);   /* read a given no. of bytes */
-void saa_fread(struct SAA *s, int32_t posn, void *p, int32_t len);    /* fixup */
-void saa_fwrite(struct SAA *s, int32_t posn, void *p, int32_t len);   /* fixup */
-void saa_fpwrite(struct SAA *, FILE *);
+#define fwriteint8_t(d,f) putc(d,f)
+void fwriteint16_t(uint16_t data, FILE * fp);
+void fwriteint32_t(uint32_t data, FILE * fp);
+void fwriteint64_t(uint64_t data, FILE * fp);
+void fwriteaddr(uint64_t data, int size, FILE * fp);
 
 /*
  * Binary search routine. Returns index into `array' of an entry
@@ -285,8 +396,8 @@ void saa_fpwrite(struct SAA *, FILE *);
  *
  * bsi() is case sensitive, bsii() is case insensitive.
  */
-int bsi(char *string, const char **array, int size);
-int bsii(char *string, const char **array, int size);
+int bsi(const char *string, const char **array, int size);
+int bsii(const char *string, const char **array, int size);
 
 char *src_set_fname(char *newname);
 int32_t src_set_linnum(int32_t newline);
@@ -299,13 +410,92 @@ int32_t src_get_linnum(void);
  */
 int src_get(int32_t *xline, char **xname);
 
-void nasm_quote(char **str);
-char *nasm_strcat(char *one, char *two);
+char *nasm_strcat(const char *one, const char *two);
 
-void null_debug_routine(const char *directive, const char *params);
-extern struct dfmt null_debug_form;
-extern struct dfmt *null_debug_arr[2];
+char *nasm_skip_spaces(const char *p);
+char *nasm_skip_word(const char *p);
+char *nasm_zap_spaces_fwd(char *p);
+char *nasm_zap_spaces_rev(char *p);
+char *nasm_trim_spaces(char *p);
+char *nasm_get_word(char *p, char **tail);
+char *nasm_opt_val(char *p, char **opt, char **val);
 
 const char *prefix_name(int);
 
+#define ZERO_BUF_SIZE 4096
+extern const uint8_t zero_buffer[ZERO_BUF_SIZE];
+size_t fwritezero(size_t bytes, FILE *fp);
+
+static inline bool overflow_general(int64_t value, int bytes)
+{
+    int sbit;
+    int64_t vmax, vmin;
+
+    if (bytes >= 8)
+        return false;
+
+    sbit = (bytes << 3) - 1;
+    vmax =  ((int64_t)2 << sbit) - 1;
+    vmin = -((int64_t)1 << sbit);
+
+    return value < vmin || value > vmax;
+}
+
+static inline bool overflow_signed(int64_t value, int bytes)
+{
+    int sbit;
+    int64_t vmax, vmin;
+
+    if (bytes >= 8)
+        return false;
+
+    sbit = (bytes << 3) - 1;
+    vmax =  ((int64_t)1 << sbit) - 1;
+    vmin = -((int64_t)1 << sbit);
+
+    return value < vmin || value > vmax;
+}
+
+static inline bool overflow_unsigned(int64_t value, int bytes)
+{
+    int sbit;
+    int64_t vmax, vmin;
+
+    if (bytes >= 8)
+        return false;
+
+    sbit = (bytes << 3) - 1;
+    vmax = ((int64_t)2 << sbit) - 1;
+    vmin = 0;
+
+    return value < vmin || value > vmax;
+}
+
+static inline int64_t signed_bits(int64_t value, int bits)
+{
+    if (bits < 64) {
+        value &= ((int64_t)1 << bits) - 1;
+        if (value & (int64_t)1 << (bits - 1))
+            value |= (int64_t)-1 << bits;
+    }
+    return value;
+}
+
+int idata_bytes(int opcode);
+
+/* check if value is power of 2 */
+#define is_power2(v)   ((v) && ((v) & ((v) - 1)) == 0)
+
+/*
+ * floor(log2(v))
+ */
+int ilog2_32(uint32_t v);
+int ilog2_64(uint64_t v);
+
+/*
+ * v == 0 ? 0 : is_power2(x) ? ilog2_X(v) : -1
+ */
+int alignlog2_32(uint32_t v);
+int alignlog2_64(uint64_t v);
+
 #endif