diff options
Diffstat (limited to 'src/isa-l/igzip/bitbuf2.h')
-rw-r--r-- | src/isa-l/igzip/bitbuf2.h | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/src/isa-l/igzip/bitbuf2.h b/src/isa-l/igzip/bitbuf2.h new file mode 100644 index 00000000..0f018b0b --- /dev/null +++ b/src/isa-l/igzip/bitbuf2.h @@ -0,0 +1,172 @@ +/********************************************************************** + Copyright(c) 2011-2016 Intel Corporation All rights reserved. + + 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. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + 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. +**********************************************************************/ +#ifndef BITBUF2_H +#define BITBUF2_H + +#include "igzip_lib.h" + +/* bit buffer types + * BITBUF8: (e) Always write 8 bytes of data + * BITBUFB: (b) Always write data + */ +#if !(defined(USE_BITBUFB) || defined(USE_BITBUF8) || defined(USE_BITBUF_ELSE)) +# define USE_BITBUFB +#endif + +#if defined (__unix__) || (__APPLE__) || (__MINGW32__) +#define _mm_stream_si64x(dst, src) *((uint64_t*)dst) = src +#else +#include <intrin.h> +#endif + +#ifdef _WIN64 +#pragma warning(disable: 4996) +#endif + +#ifdef _MSC_VER +#define inline __inline +#endif + + +/* MAX_BITBUF_BIT WRITE is the maximum number of bits than can be safely written + * by consecutive calls of write_bits. Note this assumes the bitbuf is in a + * state that is possible at the exit of write_bits */ +#ifdef USE_BITBUF8 /*Write bits safe */ +# define MAX_BITBUF_BIT_WRITE 63 +#elif defined(USE_BITBUFB) /* Write bits always */ +# define MAX_BITBUF_BIT_WRITE 56 +#else /* USE_BITBUF_ELSE */ +# define MAX_BITBUF_BIT_WRITE 56 +#endif + + +static + inline void construct(struct BitBuf2 *me) +{ + me->m_bits = 0; + me->m_bit_count = 0; + me->m_out_buf = me->m_out_start = me->m_out_end = NULL; +} + +static inline void init(struct BitBuf2 *me) +{ + me->m_bits = 0; + me->m_bit_count = 0; +} + +static inline void set_buf(struct BitBuf2 *me, unsigned char *buf, unsigned int len) +{ + unsigned int slop = 8; + me->m_out_buf = me->m_out_start = buf; + me->m_out_end = buf + len - slop; +} + +static inline int is_full(struct BitBuf2 *me) +{ + return (me->m_out_buf > me->m_out_end); +} + +static inline uint8_t * buffer_ptr(struct BitBuf2 *me) +{ + return me->m_out_buf; +} + +static inline uint32_t buffer_used(struct BitBuf2 *me) +{ + return (uint32_t)(me->m_out_buf - me->m_out_start); +} + +static inline uint32_t buffer_bits_used(struct BitBuf2 *me) +{ + return (8 * (uint32_t)(me->m_out_buf - me->m_out_start) + me->m_bit_count); +} + +static inline void flush_bits(struct BitBuf2 *me) +{ + uint32_t bits; + _mm_stream_si64x((int64_t *) me->m_out_buf, me->m_bits); + bits = me->m_bit_count & ~7; + me->m_bit_count -= bits; + me->m_out_buf += bits/8; + me->m_bits >>= bits; + +} + +static inline void check_space(struct BitBuf2 *me, uint32_t num_bits) +{ + /* Checks if bitbuf has num_bits extra space and flushes the bytes in + * the bitbuf if it doesn't. */ + if (63 - me->m_bit_count < num_bits) + flush_bits(me); +} + +static inline void write_bits_unsafe(struct BitBuf2 *me, uint64_t code, uint32_t count) +{ + me->m_bits |= code << me->m_bit_count; + me->m_bit_count += count; +} + +static inline void write_bits(struct BitBuf2 *me, uint64_t code, uint32_t count) +{ +#ifdef USE_BITBUF8 /*Write bits safe */ + me->m_bits |= code << me->m_bit_count; + me->m_bit_count += count; + if (me->m_bit_count >= 64) { + _mm_stream_si64x((int64_t *) me->m_out_buf, me->m_bits); + me->m_out_buf += 8; + me->m_bit_count -= 64; + me->m_bits = code >> (count - me->m_bit_count); + } +#elif defined(USE_BITBUFB) /* Write bits always */ + /* Assumes there is space to fit code into m_bits. */ + me->m_bits |= code << me->m_bit_count; + me->m_bit_count += count; + if (me->m_bit_count >= 8) + flush_bits(me); +#else /* USE_BITBUF_ELSE */ + check_space(me, count); + write_bits_unsafe(me, code, count); +#endif + +} + +/* Can write up to 8 bytes to output buffer */ +static inline void flush(struct BitBuf2 *me) +{ + uint32_t bytes; + if (me->m_bit_count) { + _mm_stream_si64x((int64_t *) me->m_out_buf, me->m_bits); + bytes = (me->m_bit_count + 7) / 8; + me->m_out_buf += bytes; + } + me->m_bits = 0; + me->m_bit_count = 0; +} + +#endif //BITBUF2_H |