source: trunk/lib/bitblock.hpp @ 4032

Last change on this file since 4032 was 2719, checked in by cameron, 7 years ago

Some copyright and description fixes

File size: 4.0 KB
RevLine 
[1950]1#ifndef BITBLOCK_HPP
2#define BITBLOCK_HPP
3
4/*=============================================================================
[2428]5        Copyright (C) 2011, Robert D. Cameron, Kenneth S. Herdy
6        Licensed to the public under the Open Software License 3.0.
7        Licensed to International Characters Inc.
8           under the Academic Free License version 3.0.
[1950]9=============================================================================*/
[1500]10
[2039]11// #define NDEBUG // if NDEBUG then disable assertions
[1903]12
[1874]13#define __STDC_LIMIT_MACROS
[1542]14#include <stdint.h>
15#include <stdio.h>
[2712]16#include <assert.h>
[1898]17
[1542]18#include "config.hpp"
[1617]19#include "builtins.hpp"
[1542]20#include "idisa.hpp"
21
[1808]22#define BytePack BitBlock
[1576]23#ifndef BLOCK_SIZE
24#define BLOCK_SIZE 128
[1500]25#endif
[1933]26#ifndef ATTRIBUTE_SIMD_ALIGN
[2428]27        #if defined _MSC_VER
28                //note: MSVC++ cannot accept sizeof or division within __declspec(align(...))
29                #define ATTRIBUTE_SIMD_ALIGN __declspec(align(16))
30        #elif defined __GNUC__
31                #define ATTRIBUTE_SIMD_ALIGN __attribute__((aligned(sizeof(BitBlock))))
32        #else
33                #define ATTRIBUTE_SIMD_ALIGN
34        #endif
[1933]35#endif
[1500]36
[1617]37template<class T> void print_register(const char * var_name, T v);
38
[1890]39static IDISA_ALWAYS_INLINE uint32_t count_forward_zeroes(BitBlock v);
40static IDISA_ALWAYS_INLINE uint32_t count_reverse_zeroes(BitBlock v);
[2037]41static IDISA_ALWAYS_INLINE BitBlock mask_forward_zeroes(uint32_t count);
42static IDISA_ALWAYS_INLINE BitBlock mask_reverse_zeroes(uint32_t count);
[1890]43static IDISA_ALWAYS_INLINE uint32_t bitstream_scan(BitBlock * v, uint32_t pos);
44
[1815]45/*  BitBlock union type */
46union ubitblock;
47
[1576]48/*  Default BLOCK_SIZE is 128, compatible with SSE, Altivec, SPU */
49#if (BLOCK_SIZE == 128)
[1527]50#include "bitblock128.hpp"
[1500]51#endif
52
[1576]53/*  BLOCK_SIZE 256 for AVX */
54#if (BLOCK_SIZE == 256)
[1527]55#include "bitblock256.hpp"
[1500]56#endif
57
[1658]58template <class T> void print_register(const char * var_name, T v);
[1527]59template <class T>
60void print_register(const char * var_name, T v) {
61        unsigned char c;
[2614]62        printf("%40s = ", var_name);
[1527]63        for(int i=sizeof(T)-1; i>=0; i--) {
64                c = *(((unsigned char *)&v)+i);
65                printf("%02X ", c);
66        }
67        printf("\n");
68}
69
[1890]70IDISA_ALWAYS_INLINE uint32_t count_forward_zeroes(BitBlock v) {
[2594]71        union {BitBlock bitblock; ScanWord elems[sizeof(BitBlock)/sizeof(ScanWord)];} u;
[1890]72        u.bitblock = v;
73        uint32_t so_far = 0;
[2594]74        for (unsigned int i = 0; i < sizeof(BitBlock)/sizeof(ScanWord); i++) {
[2428]75                if (u.elems[i] != 0) return so_far | scan_forward_zeroes(u.elems[i]);
[2594]76                so_far += 8 * sizeof(ScanWord);
[1890]77        }
78        return so_far;
79}
80
[2037]81IDISA_ALWAYS_INLINE BitBlock mask_forward_zeroes(uint32_t count) {
82        if (count >= sizeof(BitBlock) * 8) return simd<1>::constant<0>();
[2428]83                else return bitblock::sll(simd<1>::constant<1>(), convert(count));
[2037]84}
85
[1890]86IDISA_ALWAYS_INLINE uint32_t count_reverse_zeroes(BitBlock v) {
[2594]87        union {BitBlock bitblock; ScanWord elems[sizeof(BitBlock)/sizeof(ScanWord)];} u;
[1890]88        u.bitblock = v;
89        uint32_t so_far = 0;
[2594]90        for (unsigned int i = (sizeof(BitBlock)/sizeof(ScanWord)); i != 0; ) {
[2428]91                if (u.elems[--i] != 0) return so_far | scan_backward_zeroes(u.elems[i]);
[2594]92                so_far += 8 * sizeof(ScanWord);
[1890]93        }
94        return so_far;
95}
96
[2037]97IDISA_ALWAYS_INLINE BitBlock mask_reverse_zeroes(uint32_t count) {
98        if (count >= sizeof(BitBlock) * 8) return simd<1>::constant<0>();
[2428]99                else return bitblock::srl(simd<1>::constant<1>(), convert(count));
[2037]100}
101
[1890]102IDISA_ALWAYS_INLINE uint32_t bitstream_scan(BitBlock * v, uint32_t pos) {
[2594]103        ScanWord * bitstream_ptr = (ScanWord *) (((intptr_t) v) + pos/8);
104        ScanWord bitstream_slice = ((*bitstream_ptr) >> (pos % 8));
[1890]105        if (bitstream_slice != 0) return pos + scan_forward_zeroes(bitstream_slice);
106        else {
107                do {
108                        bitstream_ptr++;
109                        bitstream_slice = *bitstream_ptr;
110                } while (bitstream_slice == 0);
111                uint32_t base_posn = 8*((intptr_t) bitstream_ptr - (intptr_t) v);
112                return base_posn + scan_forward_zeroes(bitstream_slice);
113        }
114}
115
[2152]116static IDISA_ALWAYS_INLINE void assert_bitblock_align(void * addr) {
[2428]117        assert(0 == ((intptr_t)(addr) & (sizeof(BitBlock)-1)));
[2152]118}
119
120static IDISA_ALWAYS_INLINE void assert_bitblock_align(BitBlock v) {
[2428]121        assert(0 == ((intptr_t)(&v) & (sizeof(BitBlock)-1)));
[2152]122}
123
124#define ASSERT_BITBLOCK_ALIGN(v) assert_bitblock_align(v)
125
[1950]126#endif // BITBLOCK_HPP
[1527]127
128
Note: See TracBrowser for help on using the repository browser.