1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2011 Christian König. 4848b8605Smrg * All Rights Reserved. 5848b8605Smrg * 6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 7848b8605Smrg * copy of this software and associated documentation files (the 8848b8605Smrg * "Software"), to deal in the Software without restriction, including 9848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 10848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 11848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 12848b8605Smrg * the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice (including the 15848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 16848b8605Smrg * of the Software. 17848b8605Smrg * 18848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20848b8605Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21848b8605Smrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22848b8605Smrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23848b8605Smrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24848b8605Smrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25848b8605Smrg * 26848b8605Smrg **************************************************************************/ 27848b8605Smrg 28848b8605Smrg/* 29848b8605Smrg * Functions for fast bitwise access to multiple probably unaligned input buffers 30848b8605Smrg */ 31848b8605Smrg 32848b8605Smrg#ifndef vl_vlc_h 33848b8605Smrg#define vl_vlc_h 34848b8605Smrg 35848b8605Smrg#include "pipe/p_compiler.h" 36848b8605Smrg 37848b8605Smrg#include "util/u_math.h" 38848b8605Smrg#include "util/u_pointer.h" 39848b8605Smrg#include "util/u_debug.h" 40848b8605Smrg 41848b8605Smrgstruct vl_vlc 42848b8605Smrg{ 43848b8605Smrg uint64_t buffer; 44848b8605Smrg signed invalid_bits; 45848b8605Smrg const uint8_t *data; 46848b8605Smrg const uint8_t *end; 47848b8605Smrg 48848b8605Smrg const void *const *inputs; 49848b8605Smrg const unsigned *sizes; 50848b8605Smrg unsigned bytes_left; 51848b8605Smrg}; 52848b8605Smrg 53848b8605Smrgstruct vl_vlc_entry 54848b8605Smrg{ 55848b8605Smrg int8_t length; 56848b8605Smrg int8_t value; 57848b8605Smrg}; 58848b8605Smrg 59848b8605Smrgstruct vl_vlc_compressed 60848b8605Smrg{ 61848b8605Smrg uint16_t bitcode; 62848b8605Smrg struct vl_vlc_entry entry; 63848b8605Smrg}; 64848b8605Smrg 65848b8605Smrg/** 66848b8605Smrg * initalize and decompress a lookup table 67848b8605Smrg */ 68b8e80941Smrgstatic inline void 69848b8605Smrgvl_vlc_init_table(struct vl_vlc_entry *dst, unsigned dst_size, const struct vl_vlc_compressed *src, unsigned src_size) 70848b8605Smrg{ 71848b8605Smrg unsigned i, bits = util_logbase2(dst_size); 72848b8605Smrg 73848b8605Smrg assert(dst && dst_size); 74848b8605Smrg assert(src && src_size); 75848b8605Smrg 76848b8605Smrg for (i=0;i<dst_size;++i) { 77848b8605Smrg dst[i].length = 0; 78848b8605Smrg dst[i].value = 0; 79848b8605Smrg } 80848b8605Smrg 81848b8605Smrg for(; src_size > 0; --src_size, ++src) { 82b8e80941Smrg for(i = 0; i < (1u << (bits - src->entry.length)); ++i) 83848b8605Smrg dst[src->bitcode >> (16 - bits) | i] = src->entry; 84848b8605Smrg } 85848b8605Smrg} 86848b8605Smrg 87848b8605Smrg/** 88848b8605Smrg * switch over to next input buffer 89848b8605Smrg */ 90b8e80941Smrgstatic inline void 91848b8605Smrgvl_vlc_next_input(struct vl_vlc *vlc) 92848b8605Smrg{ 93848b8605Smrg unsigned len = vlc->sizes[0]; 94848b8605Smrg 95848b8605Smrg assert(vlc); 96848b8605Smrg assert(vlc->bytes_left); 97848b8605Smrg 98848b8605Smrg if (len < vlc->bytes_left) 99848b8605Smrg vlc->bytes_left -= len; 100848b8605Smrg else { 101848b8605Smrg len = vlc->bytes_left; 102848b8605Smrg vlc->bytes_left = 0; 103848b8605Smrg } 104848b8605Smrg 105848b8605Smrg vlc->data = vlc->inputs[0]; 106848b8605Smrg vlc->end = vlc->data + len; 107848b8605Smrg 108848b8605Smrg ++vlc->inputs; 109848b8605Smrg ++vlc->sizes; 110848b8605Smrg} 111848b8605Smrg 112848b8605Smrg/** 113848b8605Smrg * align the data pointer to the next dword 114848b8605Smrg */ 115b8e80941Smrgstatic inline void 116848b8605Smrgvl_vlc_align_data_ptr(struct vl_vlc *vlc) 117848b8605Smrg{ 118848b8605Smrg /* align the data pointer */ 119848b8605Smrg while (vlc->data != vlc->end && pointer_to_uintptr(vlc->data) & 3) { 120848b8605Smrg vlc->buffer |= (uint64_t)*vlc->data << (24 + vlc->invalid_bits); 121848b8605Smrg ++vlc->data; 122848b8605Smrg vlc->invalid_bits -= 8; 123848b8605Smrg } 124848b8605Smrg} 125848b8605Smrg 126848b8605Smrg/** 127848b8605Smrg * fill the bit buffer, so that at least 32 bits are valid 128848b8605Smrg */ 129b8e80941Smrgstatic inline void 130848b8605Smrgvl_vlc_fillbits(struct vl_vlc *vlc) 131848b8605Smrg{ 132848b8605Smrg assert(vlc); 133848b8605Smrg 134848b8605Smrg /* as long as the buffer needs to be filled */ 135848b8605Smrg while (vlc->invalid_bits > 0) { 136848b8605Smrg unsigned bytes_left = vlc->end - vlc->data; 137848b8605Smrg 138848b8605Smrg /* if this input is depleted */ 139848b8605Smrg if (bytes_left == 0) { 140848b8605Smrg 141848b8605Smrg if (vlc->bytes_left) { 142848b8605Smrg /* go on to next input */ 143848b8605Smrg vl_vlc_next_input(vlc); 144848b8605Smrg vl_vlc_align_data_ptr(vlc); 145848b8605Smrg } else 146848b8605Smrg /* or give up since we don't have anymore inputs */ 147848b8605Smrg return; 148848b8605Smrg 149848b8605Smrg } else if (bytes_left >= 4) { 150848b8605Smrg 151848b8605Smrg /* enough bytes in buffer, read in a whole dword */ 152848b8605Smrg uint64_t value = *(const uint32_t*)vlc->data; 153848b8605Smrg 154848b8605Smrg#ifndef PIPE_ARCH_BIG_ENDIAN 155848b8605Smrg value = util_bswap32(value); 156848b8605Smrg#endif 157848b8605Smrg 158848b8605Smrg vlc->buffer |= value << vlc->invalid_bits; 159848b8605Smrg vlc->data += 4; 160848b8605Smrg vlc->invalid_bits -= 32; 161848b8605Smrg 162848b8605Smrg /* buffer is now definitely filled up avoid the loop test */ 163848b8605Smrg break; 164848b8605Smrg 165848b8605Smrg } else while (vlc->data < vlc->end) { 166848b8605Smrg 167848b8605Smrg /* not enough bytes left in buffer, read single bytes */ 168848b8605Smrg vlc->buffer |= (uint64_t)*vlc->data << (24 + vlc->invalid_bits); 169848b8605Smrg ++vlc->data; 170848b8605Smrg vlc->invalid_bits -= 8; 171848b8605Smrg } 172848b8605Smrg } 173848b8605Smrg} 174848b8605Smrg 175848b8605Smrg/** 176848b8605Smrg * initialize vlc structure and start reading from first input buffer 177848b8605Smrg */ 178b8e80941Smrgstatic inline void 179848b8605Smrgvl_vlc_init(struct vl_vlc *vlc, unsigned num_inputs, 180848b8605Smrg const void *const *inputs, const unsigned *sizes) 181848b8605Smrg{ 182848b8605Smrg unsigned i; 183848b8605Smrg 184848b8605Smrg assert(vlc); 185848b8605Smrg assert(num_inputs); 186848b8605Smrg 187848b8605Smrg vlc->buffer = 0; 188848b8605Smrg vlc->invalid_bits = 32; 189848b8605Smrg vlc->inputs = inputs; 190848b8605Smrg vlc->sizes = sizes; 191848b8605Smrg vlc->bytes_left = 0; 192848b8605Smrg 193848b8605Smrg for (i = 0; i < num_inputs; ++i) 194848b8605Smrg vlc->bytes_left += sizes[i]; 195848b8605Smrg 196848b8605Smrg if (vlc->bytes_left) { 197848b8605Smrg vl_vlc_next_input(vlc); 198848b8605Smrg vl_vlc_align_data_ptr(vlc); 199848b8605Smrg vl_vlc_fillbits(vlc); 200848b8605Smrg } 201848b8605Smrg} 202848b8605Smrg 203848b8605Smrg/** 204848b8605Smrg * number of bits still valid in bit buffer 205848b8605Smrg */ 206b8e80941Smrgstatic inline unsigned 207848b8605Smrgvl_vlc_valid_bits(struct vl_vlc *vlc) 208848b8605Smrg{ 209848b8605Smrg return 32 - vlc->invalid_bits; 210848b8605Smrg} 211848b8605Smrg 212848b8605Smrg/** 213848b8605Smrg * number of bits left over all inbut buffers 214848b8605Smrg */ 215b8e80941Smrgstatic inline unsigned 216848b8605Smrgvl_vlc_bits_left(struct vl_vlc *vlc) 217848b8605Smrg{ 218848b8605Smrg signed bytes_left = vlc->end - vlc->data; 219848b8605Smrg bytes_left += vlc->bytes_left; 220848b8605Smrg return bytes_left * 8 + vl_vlc_valid_bits(vlc); 221848b8605Smrg} 222848b8605Smrg 223848b8605Smrg/** 224848b8605Smrg * get num_bits from bit buffer without removing them 225848b8605Smrg */ 226b8e80941Smrgstatic inline unsigned 227848b8605Smrgvl_vlc_peekbits(struct vl_vlc *vlc, unsigned num_bits) 228848b8605Smrg{ 229848b8605Smrg assert(vl_vlc_valid_bits(vlc) >= num_bits || vlc->data >= vlc->end); 230848b8605Smrg return vlc->buffer >> (64 - num_bits); 231848b8605Smrg} 232848b8605Smrg 233848b8605Smrg/** 234848b8605Smrg * remove num_bits from bit buffer 235848b8605Smrg */ 236b8e80941Smrgstatic inline void 237848b8605Smrgvl_vlc_eatbits(struct vl_vlc *vlc, unsigned num_bits) 238848b8605Smrg{ 239848b8605Smrg assert(vl_vlc_valid_bits(vlc) >= num_bits); 240848b8605Smrg 241848b8605Smrg vlc->buffer <<= num_bits; 242848b8605Smrg vlc->invalid_bits += num_bits; 243848b8605Smrg} 244848b8605Smrg 245848b8605Smrg/** 246848b8605Smrg * get num_bits from bit buffer with removing them 247848b8605Smrg */ 248b8e80941Smrgstatic inline unsigned 249848b8605Smrgvl_vlc_get_uimsbf(struct vl_vlc *vlc, unsigned num_bits) 250848b8605Smrg{ 251848b8605Smrg unsigned value; 252848b8605Smrg 253848b8605Smrg assert(vl_vlc_valid_bits(vlc) >= num_bits); 254848b8605Smrg 255848b8605Smrg value = vlc->buffer >> (64 - num_bits); 256848b8605Smrg vl_vlc_eatbits(vlc, num_bits); 257848b8605Smrg 258848b8605Smrg return value; 259848b8605Smrg} 260848b8605Smrg 261848b8605Smrg/** 262848b8605Smrg * treat num_bits as signed value and remove them from bit buffer 263848b8605Smrg */ 264b8e80941Smrgstatic inline signed 265848b8605Smrgvl_vlc_get_simsbf(struct vl_vlc *vlc, unsigned num_bits) 266848b8605Smrg{ 267848b8605Smrg signed value; 268848b8605Smrg 269848b8605Smrg assert(vl_vlc_valid_bits(vlc) >= num_bits); 270848b8605Smrg 271848b8605Smrg value = ((int64_t)vlc->buffer) >> (64 - num_bits); 272848b8605Smrg vl_vlc_eatbits(vlc, num_bits); 273848b8605Smrg 274848b8605Smrg return value; 275848b8605Smrg} 276848b8605Smrg 277848b8605Smrg/** 278848b8605Smrg * lookup a value and length in a decompressed table 279848b8605Smrg */ 280b8e80941Smrgstatic inline int8_t 281848b8605Smrgvl_vlc_get_vlclbf(struct vl_vlc *vlc, const struct vl_vlc_entry *tbl, unsigned num_bits) 282848b8605Smrg{ 283848b8605Smrg tbl += vl_vlc_peekbits(vlc, num_bits); 284848b8605Smrg vl_vlc_eatbits(vlc, tbl->length); 285848b8605Smrg return tbl->value; 286848b8605Smrg} 287848b8605Smrg 288848b8605Smrg/** 289848b8605Smrg * fast forward search for a specific byte value 290848b8605Smrg */ 291b8e80941Smrgstatic inline boolean 292848b8605Smrgvl_vlc_search_byte(struct vl_vlc *vlc, unsigned num_bits, uint8_t value) 293848b8605Smrg{ 294848b8605Smrg /* make sure we are on a byte boundary */ 295848b8605Smrg assert((vl_vlc_valid_bits(vlc) % 8) == 0); 296b8e80941Smrg assert(num_bits == ~0u || (num_bits % 8) == 0); 297848b8605Smrg 298848b8605Smrg /* deplete the bit buffer */ 299848b8605Smrg while (vl_vlc_valid_bits(vlc) > 0) { 300848b8605Smrg 301848b8605Smrg if (vl_vlc_peekbits(vlc, 8) == value) { 302848b8605Smrg vl_vlc_fillbits(vlc); 303848b8605Smrg return TRUE; 304848b8605Smrg } 305848b8605Smrg 306848b8605Smrg vl_vlc_eatbits(vlc, 8); 307848b8605Smrg 308b8e80941Smrg if (num_bits != ~0u) { 309848b8605Smrg num_bits -= 8; 310848b8605Smrg if (num_bits == 0) 311848b8605Smrg return FALSE; 312848b8605Smrg } 313848b8605Smrg } 314848b8605Smrg 315848b8605Smrg /* deplete the byte buffers */ 316848b8605Smrg while (1) { 317848b8605Smrg 318848b8605Smrg /* if this input is depleted */ 319848b8605Smrg if (vlc->data == vlc->end) { 320848b8605Smrg if (vlc->bytes_left) 321848b8605Smrg /* go on to next input */ 322848b8605Smrg vl_vlc_next_input(vlc); 323848b8605Smrg else 324848b8605Smrg /* or give up since we don't have anymore inputs */ 325848b8605Smrg return FALSE; 326848b8605Smrg } 327848b8605Smrg 328848b8605Smrg if (*vlc->data == value) { 329848b8605Smrg vl_vlc_align_data_ptr(vlc); 330848b8605Smrg vl_vlc_fillbits(vlc); 331848b8605Smrg return TRUE; 332848b8605Smrg } 333848b8605Smrg 334848b8605Smrg ++vlc->data; 335b8e80941Smrg if (num_bits != ~0u) { 336848b8605Smrg num_bits -= 8; 337848b8605Smrg if (num_bits == 0) { 338848b8605Smrg vl_vlc_align_data_ptr(vlc); 339848b8605Smrg return FALSE; 340848b8605Smrg } 341848b8605Smrg } 342848b8605Smrg } 343848b8605Smrg} 344848b8605Smrg 345848b8605Smrg/** 346848b8605Smrg * remove num_bits bits starting at pos from the bitbuffer 347848b8605Smrg */ 348b8e80941Smrgstatic inline void 349848b8605Smrgvl_vlc_removebits(struct vl_vlc *vlc, unsigned pos, unsigned num_bits) 350848b8605Smrg{ 351848b8605Smrg uint64_t lo = (vlc->buffer & (~0UL >> (pos + num_bits))) << num_bits; 352848b8605Smrg uint64_t hi = (vlc->buffer & (~0UL << (64 - pos))); 353848b8605Smrg vlc->buffer = lo | hi; 354848b8605Smrg vlc->invalid_bits += num_bits; 355848b8605Smrg} 356848b8605Smrg 357848b8605Smrg/** 358848b8605Smrg * limit the number of bits left for fetching 359848b8605Smrg */ 360b8e80941Smrgstatic inline void 361848b8605Smrgvl_vlc_limit(struct vl_vlc *vlc, unsigned bits_left) 362848b8605Smrg{ 363848b8605Smrg assert(bits_left <= vl_vlc_bits_left(vlc)); 364848b8605Smrg 365848b8605Smrg vl_vlc_fillbits(vlc); 366848b8605Smrg if (bits_left < vl_vlc_valid_bits(vlc)) { 367848b8605Smrg vlc->invalid_bits = 32 - bits_left; 368848b8605Smrg vlc->buffer &= ~0L << (vlc->invalid_bits + 32); 369848b8605Smrg vlc->end = vlc->data; 370848b8605Smrg vlc->bytes_left = 0; 371848b8605Smrg } else { 372848b8605Smrg assert((bits_left - vl_vlc_valid_bits(vlc)) % 8 == 0); 373848b8605Smrg vlc->bytes_left = (bits_left - vl_vlc_valid_bits(vlc)) / 8; 374848b8605Smrg if (vlc->bytes_left < (vlc->end - vlc->data)) { 375848b8605Smrg vlc->end = vlc->data + vlc->bytes_left; 376848b8605Smrg vlc->bytes_left = 0; 377848b8605Smrg } else 378848b8605Smrg vlc->bytes_left -= vlc->end - vlc->data; 379848b8605Smrg } 380848b8605Smrg} 381848b8605Smrg 382848b8605Smrg#endif /* vl_vlc_h */ 383