xref: /isa-l/igzip/huff_codes.c (revision e79c57c7e3faf1aa045fbf6eecd458abd504fe6c)
1660f49b0SGreg Tucker /**********************************************************************
2660f49b0SGreg Tucker   Copyright(c) 2011-2016 Intel Corporation All rights reserved.
3660f49b0SGreg Tucker 
4660f49b0SGreg Tucker   Redistribution and use in source and binary forms, with or without
5660f49b0SGreg Tucker   modification, are permitted provided that the following conditions
6660f49b0SGreg Tucker   are met:
7660f49b0SGreg Tucker     * Redistributions of source code must retain the above copyright
8660f49b0SGreg Tucker       notice, this list of conditions and the following disclaimer.
9660f49b0SGreg Tucker     * Redistributions in binary form must reproduce the above copyright
10660f49b0SGreg Tucker       notice, this list of conditions and the following disclaimer in
11660f49b0SGreg Tucker       the documentation and/or other materials provided with the
12660f49b0SGreg Tucker       distribution.
13660f49b0SGreg Tucker     * Neither the name of Intel Corporation nor the names of its
14660f49b0SGreg Tucker       contributors may be used to endorse or promote products derived
15660f49b0SGreg Tucker       from this software without specific prior written permission.
16660f49b0SGreg Tucker 
17660f49b0SGreg Tucker   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18660f49b0SGreg Tucker   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19660f49b0SGreg Tucker   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20660f49b0SGreg Tucker   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21660f49b0SGreg Tucker   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22660f49b0SGreg Tucker   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23660f49b0SGreg Tucker   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24660f49b0SGreg Tucker   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25660f49b0SGreg Tucker   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26660f49b0SGreg Tucker   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27660f49b0SGreg Tucker   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28660f49b0SGreg Tucker **********************************************************************/
29660f49b0SGreg Tucker 
30660f49b0SGreg Tucker #include <immintrin.h>
31660f49b0SGreg Tucker #include <stdint.h>
32660f49b0SGreg Tucker #include <string.h>
33660f49b0SGreg Tucker #include <assert.h>
34660f49b0SGreg Tucker #include "igzip_lib.h"
35660f49b0SGreg Tucker #include "huff_codes.h"
36660f49b0SGreg Tucker #include "huffman.h"
3701dfbcc4SRoy Oursler #include "bitbuf2.h"
3801dfbcc4SRoy Oursler #include "flatten_ll.h"
39660f49b0SGreg Tucker 
40660f49b0SGreg Tucker /* The order code length codes are written in the dynamic code header. This is
41660f49b0SGreg Tucker  * defined in RFC 1951 page 13 */
42660f49b0SGreg Tucker static const uint8_t code_length_code_order[] =
43660f49b0SGreg Tucker     { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
44660f49b0SGreg Tucker 
459992cc19SRoy Oursler const uint32_t len_code_extra_bits[] = {
469992cc19SRoy Oursler 	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
479992cc19SRoy Oursler 	0x1, 0x1, 0x1, 0x1, 0x2, 0x2, 0x2, 0x2,
489992cc19SRoy Oursler 	0x3, 0x3, 0x3, 0x3, 0x4, 0x4, 0x4, 0x4,
499992cc19SRoy Oursler 	0x5, 0x5, 0x5, 0x5, 0x0
509992cc19SRoy Oursler };
519992cc19SRoy Oursler 
529992cc19SRoy Oursler const uint32_t dist_code_extra_bits[] = {
539992cc19SRoy Oursler 	0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x2, 0x2,
549992cc19SRoy Oursler 	0x3, 0x3, 0x4, 0x4, 0x5, 0x5, 0x6, 0x6,
559992cc19SRoy Oursler 	0x7, 0x7, 0x8, 0x8, 0x9, 0x9, 0xa, 0xa,
569992cc19SRoy Oursler 	0xb, 0xb, 0xc, 0xc, 0xd, 0xd
579992cc19SRoy Oursler };
589992cc19SRoy Oursler 
599992cc19SRoy Oursler struct hufftables_icf static_hufftables = {
609992cc19SRoy Oursler 	.lit_len_table = {
619099918dSPeng Xiao 			  {{{.code_and_extra = 0x00c,.length2 = 0x8}}},
629099918dSPeng Xiao 			  {{{.code_and_extra = 0x08c,.length2 = 0x8}}},
639099918dSPeng Xiao 			  {{{.code_and_extra = 0x04c,.length2 = 0x8}}},
649099918dSPeng Xiao 			  {{{.code_and_extra = 0x0cc,.length2 = 0x8}}},
659099918dSPeng Xiao 			  {{{.code_and_extra = 0x02c,.length2 = 0x8}}},
669099918dSPeng Xiao 			  {{{.code_and_extra = 0x0ac,.length2 = 0x8}}},
679099918dSPeng Xiao 			  {{{.code_and_extra = 0x06c,.length2 = 0x8}}},
689099918dSPeng Xiao 			  {{{.code_and_extra = 0x0ec,.length2 = 0x8}}},
699099918dSPeng Xiao 			  {{{.code_and_extra = 0x01c,.length2 = 0x8}}},
709099918dSPeng Xiao 			  {{{.code_and_extra = 0x09c,.length2 = 0x8}}},
719099918dSPeng Xiao 			  {{{.code_and_extra = 0x05c,.length2 = 0x8}}},
729099918dSPeng Xiao 			  {{{.code_and_extra = 0x0dc,.length2 = 0x8}}},
739099918dSPeng Xiao 			  {{{.code_and_extra = 0x03c,.length2 = 0x8}}},
749099918dSPeng Xiao 			  {{{.code_and_extra = 0x0bc,.length2 = 0x8}}},
759099918dSPeng Xiao 			  {{{.code_and_extra = 0x07c,.length2 = 0x8}}},
769099918dSPeng Xiao 			  {{{.code_and_extra = 0x0fc,.length2 = 0x8}}},
779099918dSPeng Xiao 			  {{{.code_and_extra = 0x002,.length2 = 0x8}}},
789099918dSPeng Xiao 			  {{{.code_and_extra = 0x082,.length2 = 0x8}}},
799099918dSPeng Xiao 			  {{{.code_and_extra = 0x042,.length2 = 0x8}}},
809099918dSPeng Xiao 			  {{{.code_and_extra = 0x0c2,.length2 = 0x8}}},
819099918dSPeng Xiao 			  {{{.code_and_extra = 0x022,.length2 = 0x8}}},
829099918dSPeng Xiao 			  {{{.code_and_extra = 0x0a2,.length2 = 0x8}}},
839099918dSPeng Xiao 			  {{{.code_and_extra = 0x062,.length2 = 0x8}}},
849099918dSPeng Xiao 			  {{{.code_and_extra = 0x0e2,.length2 = 0x8}}},
859099918dSPeng Xiao 			  {{{.code_and_extra = 0x012,.length2 = 0x8}}},
869099918dSPeng Xiao 			  {{{.code_and_extra = 0x092,.length2 = 0x8}}},
879099918dSPeng Xiao 			  {{{.code_and_extra = 0x052,.length2 = 0x8}}},
889099918dSPeng Xiao 			  {{{.code_and_extra = 0x0d2,.length2 = 0x8}}},
899099918dSPeng Xiao 			  {{{.code_and_extra = 0x032,.length2 = 0x8}}},
909099918dSPeng Xiao 			  {{{.code_and_extra = 0x0b2,.length2 = 0x8}}},
919099918dSPeng Xiao 			  {{{.code_and_extra = 0x072,.length2 = 0x8}}},
929099918dSPeng Xiao 			  {{{.code_and_extra = 0x0f2,.length2 = 0x8}}},
939099918dSPeng Xiao 			  {{{.code_and_extra = 0x00a,.length2 = 0x8}}},
949099918dSPeng Xiao 			  {{{.code_and_extra = 0x08a,.length2 = 0x8}}},
959099918dSPeng Xiao 			  {{{.code_and_extra = 0x04a,.length2 = 0x8}}},
969099918dSPeng Xiao 			  {{{.code_and_extra = 0x0ca,.length2 = 0x8}}},
979099918dSPeng Xiao 			  {{{.code_and_extra = 0x02a,.length2 = 0x8}}},
989099918dSPeng Xiao 			  {{{.code_and_extra = 0x0aa,.length2 = 0x8}}},
999099918dSPeng Xiao 			  {{{.code_and_extra = 0x06a,.length2 = 0x8}}},
1009099918dSPeng Xiao 			  {{{.code_and_extra = 0x0ea,.length2 = 0x8}}},
1019099918dSPeng Xiao 			  {{{.code_and_extra = 0x01a,.length2 = 0x8}}},
1029099918dSPeng Xiao 			  {{{.code_and_extra = 0x09a,.length2 = 0x8}}},
1039099918dSPeng Xiao 			  {{{.code_and_extra = 0x05a,.length2 = 0x8}}},
1049099918dSPeng Xiao 			  {{{.code_and_extra = 0x0da,.length2 = 0x8}}},
1059099918dSPeng Xiao 			  {{{.code_and_extra = 0x03a,.length2 = 0x8}}},
1069099918dSPeng Xiao 			  {{{.code_and_extra = 0x0ba,.length2 = 0x8}}},
1079099918dSPeng Xiao 			  {{{.code_and_extra = 0x07a,.length2 = 0x8}}},
1089099918dSPeng Xiao 			  {{{.code_and_extra = 0x0fa,.length2 = 0x8}}},
1099099918dSPeng Xiao 			  {{{.code_and_extra = 0x006,.length2 = 0x8}}},
1109099918dSPeng Xiao 			  {{{.code_and_extra = 0x086,.length2 = 0x8}}},
1119099918dSPeng Xiao 			  {{{.code_and_extra = 0x046,.length2 = 0x8}}},
1129099918dSPeng Xiao 			  {{{.code_and_extra = 0x0c6,.length2 = 0x8}}},
1139099918dSPeng Xiao 			  {{{.code_and_extra = 0x026,.length2 = 0x8}}},
1149099918dSPeng Xiao 			  {{{.code_and_extra = 0x0a6,.length2 = 0x8}}},
1159099918dSPeng Xiao 			  {{{.code_and_extra = 0x066,.length2 = 0x8}}},
1169099918dSPeng Xiao 			  {{{.code_and_extra = 0x0e6,.length2 = 0x8}}},
1179099918dSPeng Xiao 			  {{{.code_and_extra = 0x016,.length2 = 0x8}}},
1189099918dSPeng Xiao 			  {{{.code_and_extra = 0x096,.length2 = 0x8}}},
1199099918dSPeng Xiao 			  {{{.code_and_extra = 0x056,.length2 = 0x8}}},
1209099918dSPeng Xiao 			  {{{.code_and_extra = 0x0d6,.length2 = 0x8}}},
1219099918dSPeng Xiao 			  {{{.code_and_extra = 0x036,.length2 = 0x8}}},
1229099918dSPeng Xiao 			  {{{.code_and_extra = 0x0b6,.length2 = 0x8}}},
1239099918dSPeng Xiao 			  {{{.code_and_extra = 0x076,.length2 = 0x8}}},
1249099918dSPeng Xiao 			  {{{.code_and_extra = 0x0f6,.length2 = 0x8}}},
1259099918dSPeng Xiao 			  {{{.code_and_extra = 0x00e,.length2 = 0x8}}},
1269099918dSPeng Xiao 			  {{{.code_and_extra = 0x08e,.length2 = 0x8}}},
1279099918dSPeng Xiao 			  {{{.code_and_extra = 0x04e,.length2 = 0x8}}},
1289099918dSPeng Xiao 			  {{{.code_and_extra = 0x0ce,.length2 = 0x8}}},
1299099918dSPeng Xiao 			  {{{.code_and_extra = 0x02e,.length2 = 0x8}}},
1309099918dSPeng Xiao 			  {{{.code_and_extra = 0x0ae,.length2 = 0x8}}},
1319099918dSPeng Xiao 			  {{{.code_and_extra = 0x06e,.length2 = 0x8}}},
1329099918dSPeng Xiao 			  {{{.code_and_extra = 0x0ee,.length2 = 0x8}}},
1339099918dSPeng Xiao 			  {{{.code_and_extra = 0x01e,.length2 = 0x8}}},
1349099918dSPeng Xiao 			  {{{.code_and_extra = 0x09e,.length2 = 0x8}}},
1359099918dSPeng Xiao 			  {{{.code_and_extra = 0x05e,.length2 = 0x8}}},
1369099918dSPeng Xiao 			  {{{.code_and_extra = 0x0de,.length2 = 0x8}}},
1379099918dSPeng Xiao 			  {{{.code_and_extra = 0x03e,.length2 = 0x8}}},
1389099918dSPeng Xiao 			  {{{.code_and_extra = 0x0be,.length2 = 0x8}}},
1399099918dSPeng Xiao 			  {{{.code_and_extra = 0x07e,.length2 = 0x8}}},
1409099918dSPeng Xiao 			  {{{.code_and_extra = 0x0fe,.length2 = 0x8}}},
1419099918dSPeng Xiao 			  {{{.code_and_extra = 0x001,.length2 = 0x8}}},
1429099918dSPeng Xiao 			  {{{.code_and_extra = 0x081,.length2 = 0x8}}},
1439099918dSPeng Xiao 			  {{{.code_and_extra = 0x041,.length2 = 0x8}}},
1449099918dSPeng Xiao 			  {{{.code_and_extra = 0x0c1,.length2 = 0x8}}},
1459099918dSPeng Xiao 			  {{{.code_and_extra = 0x021,.length2 = 0x8}}},
1469099918dSPeng Xiao 			  {{{.code_and_extra = 0x0a1,.length2 = 0x8}}},
1479099918dSPeng Xiao 			  {{{.code_and_extra = 0x061,.length2 = 0x8}}},
1489099918dSPeng Xiao 			  {{{.code_and_extra = 0x0e1,.length2 = 0x8}}},
1499099918dSPeng Xiao 			  {{{.code_and_extra = 0x011,.length2 = 0x8}}},
1509099918dSPeng Xiao 			  {{{.code_and_extra = 0x091,.length2 = 0x8}}},
1519099918dSPeng Xiao 			  {{{.code_and_extra = 0x051,.length2 = 0x8}}},
1529099918dSPeng Xiao 			  {{{.code_and_extra = 0x0d1,.length2 = 0x8}}},
1539099918dSPeng Xiao 			  {{{.code_and_extra = 0x031,.length2 = 0x8}}},
1549099918dSPeng Xiao 			  {{{.code_and_extra = 0x0b1,.length2 = 0x8}}},
1559099918dSPeng Xiao 			  {{{.code_and_extra = 0x071,.length2 = 0x8}}},
1569099918dSPeng Xiao 			  {{{.code_and_extra = 0x0f1,.length2 = 0x8}}},
1579099918dSPeng Xiao 			  {{{.code_and_extra = 0x009,.length2 = 0x8}}},
1589099918dSPeng Xiao 			  {{{.code_and_extra = 0x089,.length2 = 0x8}}},
1599099918dSPeng Xiao 			  {{{.code_and_extra = 0x049,.length2 = 0x8}}},
1609099918dSPeng Xiao 			  {{{.code_and_extra = 0x0c9,.length2 = 0x8}}},
1619099918dSPeng Xiao 			  {{{.code_and_extra = 0x029,.length2 = 0x8}}},
1629099918dSPeng Xiao 			  {{{.code_and_extra = 0x0a9,.length2 = 0x8}}},
1639099918dSPeng Xiao 			  {{{.code_and_extra = 0x069,.length2 = 0x8}}},
1649099918dSPeng Xiao 			  {{{.code_and_extra = 0x0e9,.length2 = 0x8}}},
1659099918dSPeng Xiao 			  {{{.code_and_extra = 0x019,.length2 = 0x8}}},
1669099918dSPeng Xiao 			  {{{.code_and_extra = 0x099,.length2 = 0x8}}},
1679099918dSPeng Xiao 			  {{{.code_and_extra = 0x059,.length2 = 0x8}}},
1689099918dSPeng Xiao 			  {{{.code_and_extra = 0x0d9,.length2 = 0x8}}},
1699099918dSPeng Xiao 			  {{{.code_and_extra = 0x039,.length2 = 0x8}}},
1709099918dSPeng Xiao 			  {{{.code_and_extra = 0x0b9,.length2 = 0x8}}},
1719099918dSPeng Xiao 			  {{{.code_and_extra = 0x079,.length2 = 0x8}}},
1729099918dSPeng Xiao 			  {{{.code_and_extra = 0x0f9,.length2 = 0x8}}},
1739099918dSPeng Xiao 			  {{{.code_and_extra = 0x005,.length2 = 0x8}}},
1749099918dSPeng Xiao 			  {{{.code_and_extra = 0x085,.length2 = 0x8}}},
1759099918dSPeng Xiao 			  {{{.code_and_extra = 0x045,.length2 = 0x8}}},
1769099918dSPeng Xiao 			  {{{.code_and_extra = 0x0c5,.length2 = 0x8}}},
1779099918dSPeng Xiao 			  {{{.code_and_extra = 0x025,.length2 = 0x8}}},
1789099918dSPeng Xiao 			  {{{.code_and_extra = 0x0a5,.length2 = 0x8}}},
1799099918dSPeng Xiao 			  {{{.code_and_extra = 0x065,.length2 = 0x8}}},
1809099918dSPeng Xiao 			  {{{.code_and_extra = 0x0e5,.length2 = 0x8}}},
1819099918dSPeng Xiao 			  {{{.code_and_extra = 0x015,.length2 = 0x8}}},
1829099918dSPeng Xiao 			  {{{.code_and_extra = 0x095,.length2 = 0x8}}},
1839099918dSPeng Xiao 			  {{{.code_and_extra = 0x055,.length2 = 0x8}}},
1849099918dSPeng Xiao 			  {{{.code_and_extra = 0x0d5,.length2 = 0x8}}},
1859099918dSPeng Xiao 			  {{{.code_and_extra = 0x035,.length2 = 0x8}}},
1869099918dSPeng Xiao 			  {{{.code_and_extra = 0x0b5,.length2 = 0x8}}},
1879099918dSPeng Xiao 			  {{{.code_and_extra = 0x075,.length2 = 0x8}}},
1889099918dSPeng Xiao 			  {{{.code_and_extra = 0x0f5,.length2 = 0x8}}},
1899099918dSPeng Xiao 			  {{{.code_and_extra = 0x00d,.length2 = 0x8}}},
1909099918dSPeng Xiao 			  {{{.code_and_extra = 0x08d,.length2 = 0x8}}},
1919099918dSPeng Xiao 			  {{{.code_and_extra = 0x04d,.length2 = 0x8}}},
1929099918dSPeng Xiao 			  {{{.code_and_extra = 0x0cd,.length2 = 0x8}}},
1939099918dSPeng Xiao 			  {{{.code_and_extra = 0x02d,.length2 = 0x8}}},
1949099918dSPeng Xiao 			  {{{.code_and_extra = 0x0ad,.length2 = 0x8}}},
1959099918dSPeng Xiao 			  {{{.code_and_extra = 0x06d,.length2 = 0x8}}},
1969099918dSPeng Xiao 			  {{{.code_and_extra = 0x0ed,.length2 = 0x8}}},
1979099918dSPeng Xiao 			  {{{.code_and_extra = 0x01d,.length2 = 0x8}}},
1989099918dSPeng Xiao 			  {{{.code_and_extra = 0x09d,.length2 = 0x8}}},
1999099918dSPeng Xiao 			  {{{.code_and_extra = 0x05d,.length2 = 0x8}}},
2009099918dSPeng Xiao 			  {{{.code_and_extra = 0x0dd,.length2 = 0x8}}},
2019099918dSPeng Xiao 			  {{{.code_and_extra = 0x03d,.length2 = 0x8}}},
2029099918dSPeng Xiao 			  {{{.code_and_extra = 0x0bd,.length2 = 0x8}}},
2039099918dSPeng Xiao 			  {{{.code_and_extra = 0x07d,.length2 = 0x8}}},
2049099918dSPeng Xiao 			  {{{.code_and_extra = 0x0fd,.length2 = 0x8}}},
2059099918dSPeng Xiao 			  {{{.code_and_extra = 0x013,.length2 = 0x9}}},
2069099918dSPeng Xiao 			  {{{.code_and_extra = 0x113,.length2 = 0x9}}},
2079099918dSPeng Xiao 			  {{{.code_and_extra = 0x093,.length2 = 0x9}}},
2089099918dSPeng Xiao 			  {{{.code_and_extra = 0x193,.length2 = 0x9}}},
2099099918dSPeng Xiao 			  {{{.code_and_extra = 0x053,.length2 = 0x9}}},
2109099918dSPeng Xiao 			  {{{.code_and_extra = 0x153,.length2 = 0x9}}},
2119099918dSPeng Xiao 			  {{{.code_and_extra = 0x0d3,.length2 = 0x9}}},
2129099918dSPeng Xiao 			  {{{.code_and_extra = 0x1d3,.length2 = 0x9}}},
2139099918dSPeng Xiao 			  {{{.code_and_extra = 0x033,.length2 = 0x9}}},
2149099918dSPeng Xiao 			  {{{.code_and_extra = 0x133,.length2 = 0x9}}},
2159099918dSPeng Xiao 			  {{{.code_and_extra = 0x0b3,.length2 = 0x9}}},
2169099918dSPeng Xiao 			  {{{.code_and_extra = 0x1b3,.length2 = 0x9}}},
2179099918dSPeng Xiao 			  {{{.code_and_extra = 0x073,.length2 = 0x9}}},
2189099918dSPeng Xiao 			  {{{.code_and_extra = 0x173,.length2 = 0x9}}},
2199099918dSPeng Xiao 			  {{{.code_and_extra = 0x0f3,.length2 = 0x9}}},
2209099918dSPeng Xiao 			  {{{.code_and_extra = 0x1f3,.length2 = 0x9}}},
2219099918dSPeng Xiao 			  {{{.code_and_extra = 0x00b,.length2 = 0x9}}},
2229099918dSPeng Xiao 			  {{{.code_and_extra = 0x10b,.length2 = 0x9}}},
2239099918dSPeng Xiao 			  {{{.code_and_extra = 0x08b,.length2 = 0x9}}},
2249099918dSPeng Xiao 			  {{{.code_and_extra = 0x18b,.length2 = 0x9}}},
2259099918dSPeng Xiao 			  {{{.code_and_extra = 0x04b,.length2 = 0x9}}},
2269099918dSPeng Xiao 			  {{{.code_and_extra = 0x14b,.length2 = 0x9}}},
2279099918dSPeng Xiao 			  {{{.code_and_extra = 0x0cb,.length2 = 0x9}}},
2289099918dSPeng Xiao 			  {{{.code_and_extra = 0x1cb,.length2 = 0x9}}},
2299099918dSPeng Xiao 			  {{{.code_and_extra = 0x02b,.length2 = 0x9}}},
2309099918dSPeng Xiao 			  {{{.code_and_extra = 0x12b,.length2 = 0x9}}},
2319099918dSPeng Xiao 			  {{{.code_and_extra = 0x0ab,.length2 = 0x9}}},
2329099918dSPeng Xiao 			  {{{.code_and_extra = 0x1ab,.length2 = 0x9}}},
2339099918dSPeng Xiao 			  {{{.code_and_extra = 0x06b,.length2 = 0x9}}},
2349099918dSPeng Xiao 			  {{{.code_and_extra = 0x16b,.length2 = 0x9}}},
2359099918dSPeng Xiao 			  {{{.code_and_extra = 0x0eb,.length2 = 0x9}}},
2369099918dSPeng Xiao 			  {{{.code_and_extra = 0x1eb,.length2 = 0x9}}},
2379099918dSPeng Xiao 			  {{{.code_and_extra = 0x01b,.length2 = 0x9}}},
2389099918dSPeng Xiao 			  {{{.code_and_extra = 0x11b,.length2 = 0x9}}},
2399099918dSPeng Xiao 			  {{{.code_and_extra = 0x09b,.length2 = 0x9}}},
2409099918dSPeng Xiao 			  {{{.code_and_extra = 0x19b,.length2 = 0x9}}},
2419099918dSPeng Xiao 			  {{{.code_and_extra = 0x05b,.length2 = 0x9}}},
2429099918dSPeng Xiao 			  {{{.code_and_extra = 0x15b,.length2 = 0x9}}},
2439099918dSPeng Xiao 			  {{{.code_and_extra = 0x0db,.length2 = 0x9}}},
2449099918dSPeng Xiao 			  {{{.code_and_extra = 0x1db,.length2 = 0x9}}},
2459099918dSPeng Xiao 			  {{{.code_and_extra = 0x03b,.length2 = 0x9}}},
2469099918dSPeng Xiao 			  {{{.code_and_extra = 0x13b,.length2 = 0x9}}},
2479099918dSPeng Xiao 			  {{{.code_and_extra = 0x0bb,.length2 = 0x9}}},
2489099918dSPeng Xiao 			  {{{.code_and_extra = 0x1bb,.length2 = 0x9}}},
2499099918dSPeng Xiao 			  {{{.code_and_extra = 0x07b,.length2 = 0x9}}},
2509099918dSPeng Xiao 			  {{{.code_and_extra = 0x17b,.length2 = 0x9}}},
2519099918dSPeng Xiao 			  {{{.code_and_extra = 0x0fb,.length2 = 0x9}}},
2529099918dSPeng Xiao 			  {{{.code_and_extra = 0x1fb,.length2 = 0x9}}},
2539099918dSPeng Xiao 			  {{{.code_and_extra = 0x007,.length2 = 0x9}}},
2549099918dSPeng Xiao 			  {{{.code_and_extra = 0x107,.length2 = 0x9}}},
2559099918dSPeng Xiao 			  {{{.code_and_extra = 0x087,.length2 = 0x9}}},
2569099918dSPeng Xiao 			  {{{.code_and_extra = 0x187,.length2 = 0x9}}},
2579099918dSPeng Xiao 			  {{{.code_and_extra = 0x047,.length2 = 0x9}}},
2589099918dSPeng Xiao 			  {{{.code_and_extra = 0x147,.length2 = 0x9}}},
2599099918dSPeng Xiao 			  {{{.code_and_extra = 0x0c7,.length2 = 0x9}}},
2609099918dSPeng Xiao 			  {{{.code_and_extra = 0x1c7,.length2 = 0x9}}},
2619099918dSPeng Xiao 			  {{{.code_and_extra = 0x027,.length2 = 0x9}}},
2629099918dSPeng Xiao 			  {{{.code_and_extra = 0x127,.length2 = 0x9}}},
2639099918dSPeng Xiao 			  {{{.code_and_extra = 0x0a7,.length2 = 0x9}}},
2649099918dSPeng Xiao 			  {{{.code_and_extra = 0x1a7,.length2 = 0x9}}},
2659099918dSPeng Xiao 			  {{{.code_and_extra = 0x067,.length2 = 0x9}}},
2669099918dSPeng Xiao 			  {{{.code_and_extra = 0x167,.length2 = 0x9}}},
2679099918dSPeng Xiao 			  {{{.code_and_extra = 0x0e7,.length2 = 0x9}}},
2689099918dSPeng Xiao 			  {{{.code_and_extra = 0x1e7,.length2 = 0x9}}},
2699099918dSPeng Xiao 			  {{{.code_and_extra = 0x017,.length2 = 0x9}}},
2709099918dSPeng Xiao 			  {{{.code_and_extra = 0x117,.length2 = 0x9}}},
2719099918dSPeng Xiao 			  {{{.code_and_extra = 0x097,.length2 = 0x9}}},
2729099918dSPeng Xiao 			  {{{.code_and_extra = 0x197,.length2 = 0x9}}},
2739099918dSPeng Xiao 			  {{{.code_and_extra = 0x057,.length2 = 0x9}}},
2749099918dSPeng Xiao 			  {{{.code_and_extra = 0x157,.length2 = 0x9}}},
2759099918dSPeng Xiao 			  {{{.code_and_extra = 0x0d7,.length2 = 0x9}}},
2769099918dSPeng Xiao 			  {{{.code_and_extra = 0x1d7,.length2 = 0x9}}},
2779099918dSPeng Xiao 			  {{{.code_and_extra = 0x037,.length2 = 0x9}}},
2789099918dSPeng Xiao 			  {{{.code_and_extra = 0x137,.length2 = 0x9}}},
2799099918dSPeng Xiao 			  {{{.code_and_extra = 0x0b7,.length2 = 0x9}}},
2809099918dSPeng Xiao 			  {{{.code_and_extra = 0x1b7,.length2 = 0x9}}},
2819099918dSPeng Xiao 			  {{{.code_and_extra = 0x077,.length2 = 0x9}}},
2829099918dSPeng Xiao 			  {{{.code_and_extra = 0x177,.length2 = 0x9}}},
2839099918dSPeng Xiao 			  {{{.code_and_extra = 0x0f7,.length2 = 0x9}}},
2849099918dSPeng Xiao 			  {{{.code_and_extra = 0x1f7,.length2 = 0x9}}},
2859099918dSPeng Xiao 			  {{{.code_and_extra = 0x00f,.length2 = 0x9}}},
2869099918dSPeng Xiao 			  {{{.code_and_extra = 0x10f,.length2 = 0x9}}},
2879099918dSPeng Xiao 			  {{{.code_and_extra = 0x08f,.length2 = 0x9}}},
2889099918dSPeng Xiao 			  {{{.code_and_extra = 0x18f,.length2 = 0x9}}},
2899099918dSPeng Xiao 			  {{{.code_and_extra = 0x04f,.length2 = 0x9}}},
2909099918dSPeng Xiao 			  {{{.code_and_extra = 0x14f,.length2 = 0x9}}},
2919099918dSPeng Xiao 			  {{{.code_and_extra = 0x0cf,.length2 = 0x9}}},
2929099918dSPeng Xiao 			  {{{.code_and_extra = 0x1cf,.length2 = 0x9}}},
2939099918dSPeng Xiao 			  {{{.code_and_extra = 0x02f,.length2 = 0x9}}},
2949099918dSPeng Xiao 			  {{{.code_and_extra = 0x12f,.length2 = 0x9}}},
2959099918dSPeng Xiao 			  {{{.code_and_extra = 0x0af,.length2 = 0x9}}},
2969099918dSPeng Xiao 			  {{{.code_and_extra = 0x1af,.length2 = 0x9}}},
2979099918dSPeng Xiao 			  {{{.code_and_extra = 0x06f,.length2 = 0x9}}},
2989099918dSPeng Xiao 			  {{{.code_and_extra = 0x16f,.length2 = 0x9}}},
2999099918dSPeng Xiao 			  {{{.code_and_extra = 0x0ef,.length2 = 0x9}}},
3009099918dSPeng Xiao 			  {{{.code_and_extra = 0x1ef,.length2 = 0x9}}},
3019099918dSPeng Xiao 			  {{{.code_and_extra = 0x01f,.length2 = 0x9}}},
3029099918dSPeng Xiao 			  {{{.code_and_extra = 0x11f,.length2 = 0x9}}},
3039099918dSPeng Xiao 			  {{{.code_and_extra = 0x09f,.length2 = 0x9}}},
3049099918dSPeng Xiao 			  {{{.code_and_extra = 0x19f,.length2 = 0x9}}},
3059099918dSPeng Xiao 			  {{{.code_and_extra = 0x05f,.length2 = 0x9}}},
3069099918dSPeng Xiao 			  {{{.code_and_extra = 0x15f,.length2 = 0x9}}},
3079099918dSPeng Xiao 			  {{{.code_and_extra = 0x0df,.length2 = 0x9}}},
3089099918dSPeng Xiao 			  {{{.code_and_extra = 0x1df,.length2 = 0x9}}},
3099099918dSPeng Xiao 			  {{{.code_and_extra = 0x03f,.length2 = 0x9}}},
3109099918dSPeng Xiao 			  {{{.code_and_extra = 0x13f,.length2 = 0x9}}},
3119099918dSPeng Xiao 			  {{{.code_and_extra = 0x0bf,.length2 = 0x9}}},
3129099918dSPeng Xiao 			  {{{.code_and_extra = 0x1bf,.length2 = 0x9}}},
3139099918dSPeng Xiao 			  {{{.code_and_extra = 0x07f,.length2 = 0x9}}},
3149099918dSPeng Xiao 			  {{{.code_and_extra = 0x17f,.length2 = 0x9}}},
3159099918dSPeng Xiao 			  {{{.code_and_extra = 0x0ff,.length2 = 0x9}}},
3169099918dSPeng Xiao 			  {{{.code_and_extra = 0x1ff,.length2 = 0x9}}},
3179099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x7}}},
3189099918dSPeng Xiao 			  {{{.code_and_extra = 0x040,.length2 = 0x7}}},
3199099918dSPeng Xiao 			  {{{.code_and_extra = 0x020,.length2 = 0x7}}},
3209099918dSPeng Xiao 			  {{{.code_and_extra = 0x060,.length2 = 0x7}}},
3219099918dSPeng Xiao 			  {{{.code_and_extra = 0x010,.length2 = 0x7}}},
3229099918dSPeng Xiao 			  {{{.code_and_extra = 0x050,.length2 = 0x7}}},
3239099918dSPeng Xiao 			  {{{.code_and_extra = 0x030,.length2 = 0x7}}},
3249099918dSPeng Xiao 			  {{{.code_and_extra = 0x070,.length2 = 0x7}}},
3259099918dSPeng Xiao 			  {{{.code_and_extra = 0x008,.length2 = 0x7}}},
3269099918dSPeng Xiao 			  {{{.code_and_extra = 0x048,.length2 = 0x7}}},
3279099918dSPeng Xiao 			  {{{.code_and_extra = 0x028,.length2 = 0x7}}},
3289099918dSPeng Xiao 			  {{{.code_and_extra = 0x068,.length2 = 0x7}}},
3299099918dSPeng Xiao 			  {{{.code_and_extra = 0x018,.length2 = 0x7}}},
3309099918dSPeng Xiao 			  {{{.code_and_extra = 0x058,.length2 = 0x7}}},
3319099918dSPeng Xiao 			  {{{.code_and_extra = 0x038,.length2 = 0x7}}},
3329099918dSPeng Xiao 			  {{{.code_and_extra = 0x078,.length2 = 0x7}}},
3339099918dSPeng Xiao 			  {{{.code_and_extra = 0x004,.length2 = 0x7}}},
3349099918dSPeng Xiao 			  {{{.code_and_extra = 0x044,.length2 = 0x7}}},
3359099918dSPeng Xiao 			  {{{.code_and_extra = 0x024,.length2 = 0x7}}},
3369099918dSPeng Xiao 			  {{{.code_and_extra = 0x064,.length2 = 0x7}}},
3379099918dSPeng Xiao 			  {{{.code_and_extra = 0x014,.length2 = 0x7}}},
3389099918dSPeng Xiao 			  {{{.code_and_extra = 0x054,.length2 = 0x7}}},
3399099918dSPeng Xiao 			  {{{.code_and_extra = 0x034,.length2 = 0x7}}},
3409099918dSPeng Xiao 			  {{{.code_and_extra = 0x074,.length2 = 0x7}}},
3419099918dSPeng Xiao 			  {{{.code_and_extra = 0x003,.length2 = 0x8}}},
3429099918dSPeng Xiao 			  {{{.code_and_extra = 0x083,.length2 = 0x8}}},
3439099918dSPeng Xiao 			  {{{.code_and_extra = 0x043,.length2 = 0x8}}},
3449099918dSPeng Xiao 			  {{{.code_and_extra = 0x0c3,.length2 = 0x8}}},
3459099918dSPeng Xiao 			  {{{.code_and_extra = 0x023,.length2 = 0x8}}},
3469099918dSPeng Xiao 			  {{{.code_and_extra = 0x0a3,.length2 = 0x8}}},
3479099918dSPeng Xiao 			  {{{.code_and_extra = 0x063,.length2 = 0x8}}},
3489099918dSPeng Xiao 			  {{{.code_and_extra = 0x0e3,.length2 = 0x8}}},
3499099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3509099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3519099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3529099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3539099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3549099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3559099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3569099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3579099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3589099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3599099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3609099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3619099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3629099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3639099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3649099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3659099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3669099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3679099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3689099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3699099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3709099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3719099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3729099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3739099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3749099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3759099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3769099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3779099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3789099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3799099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3809099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3819099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3829099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3839099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3849099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3859099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3869099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3879099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3889099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3899099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3909099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3919099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3929099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3939099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3949099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3959099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3969099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3979099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3989099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
3999099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4009099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4019099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4029099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4039099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4049099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4059099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4069099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4079099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4089099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4099099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4109099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4119099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4129099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4139099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4149099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4159099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4169099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4179099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4189099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4199099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4209099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4219099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4229099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4239099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4249099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4259099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4269099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4279099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4289099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4299099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4309099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4319099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4329099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4339099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4349099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4359099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4369099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4379099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4389099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4399099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4409099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4419099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4429099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4439099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4449099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4459099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4469099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4479099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4489099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4499099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4509099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4519099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4529099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4539099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4549099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4559099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4569099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4579099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4589099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4599099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4609099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4619099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4629099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4639099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4649099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4659099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4669099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4679099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4689099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4699099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4709099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4719099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4729099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4739099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4749099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4759099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4769099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4779099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4789099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4799099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4809099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4819099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4829099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4839099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4849099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4859099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4869099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4879099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4889099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4899099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4909099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4919099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4929099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4939099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4949099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4959099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4969099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4979099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4989099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
4999099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5009099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5019099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5029099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5039099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5049099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5059099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5069099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5079099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5089099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5099099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5109099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5119099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5129099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5139099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5149099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5159099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5169099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5179099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5189099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5199099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5209099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5219099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5229099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5239099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5249099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5259099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5269099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5279099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5289099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5299099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5309099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5319099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5329099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5339099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5349099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5359099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5369099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5379099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5389099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5399099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5409099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5419099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5429099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5439099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5449099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5459099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5469099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5479099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5489099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5499099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5509099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5519099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5529099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5539099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5549099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5559099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5569099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5579099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5589099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5599099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5609099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5619099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5629099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5639099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5649099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5659099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5669099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5679099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5689099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5699099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5709099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5719099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5729099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}},
5739099918dSPeng Xiao 			  {{{.code_and_extra = 0x000,.length2 = 0x0}}}},
5749992cc19SRoy Oursler 	.dist_table = {
5759099918dSPeng Xiao 		       {{{.code_and_extra = 0x000,.length2 = 0x5}}},
5769099918dSPeng Xiao 		       {{{.code_and_extra = 0x010,.length2 = 0x5}}},
5779099918dSPeng Xiao 		       {{{.code_and_extra = 0x008,.length2 = 0x5}}},
5789099918dSPeng Xiao 		       {{{.code_and_extra = 0x018,.length2 = 0x5}}},
5799099918dSPeng Xiao 		       {{{.code_and_extra = 0x10004,.length2 = 0x5}}},
5809099918dSPeng Xiao 		       {{{.code_and_extra = 0x10014,.length2 = 0x5}}},
5819099918dSPeng Xiao 		       {{{.code_and_extra = 0x2000c,.length2 = 0x5}}},
5829099918dSPeng Xiao 		       {{{.code_and_extra = 0x2001c,.length2 = 0x5}}},
5839099918dSPeng Xiao 		       {{{.code_and_extra = 0x30002,.length2 = 0x5}}},
5849099918dSPeng Xiao 		       {{{.code_and_extra = 0x30012,.length2 = 0x5}}},
5859099918dSPeng Xiao 		       {{{.code_and_extra = 0x4000a,.length2 = 0x5}}},
5869099918dSPeng Xiao 		       {{{.code_and_extra = 0x4001a,.length2 = 0x5}}},
5879099918dSPeng Xiao 		       {{{.code_and_extra = 0x50006,.length2 = 0x5}}},
5889099918dSPeng Xiao 		       {{{.code_and_extra = 0x50016,.length2 = 0x5}}},
5899099918dSPeng Xiao 		       {{{.code_and_extra = 0x6000e,.length2 = 0x5}}},
5909099918dSPeng Xiao 		       {{{.code_and_extra = 0x6001e,.length2 = 0x5}}},
5919099918dSPeng Xiao 		       {{{.code_and_extra = 0x70001,.length2 = 0x5}}},
5929099918dSPeng Xiao 		       {{{.code_and_extra = 0x70011,.length2 = 0x5}}},
5939099918dSPeng Xiao 		       {{{.code_and_extra = 0x80009,.length2 = 0x5}}},
5949099918dSPeng Xiao 		       {{{.code_and_extra = 0x80019,.length2 = 0x5}}},
5959099918dSPeng Xiao 		       {{{.code_and_extra = 0x90005,.length2 = 0x5}}},
5969099918dSPeng Xiao 		       {{{.code_and_extra = 0x90015,.length2 = 0x5}}},
5979099918dSPeng Xiao 		       {{{.code_and_extra = 0xa000d,.length2 = 0x5}}},
5989099918dSPeng Xiao 		       {{{.code_and_extra = 0xa001d,.length2 = 0x5}}},
5999099918dSPeng Xiao 		       {{{.code_and_extra = 0xb0003,.length2 = 0x5}}},
6009099918dSPeng Xiao 		       {{{.code_and_extra = 0xb0013,.length2 = 0x5}}},
6019099918dSPeng Xiao 		       {{{.code_and_extra = 0xc000b,.length2 = 0x5}}},
6029099918dSPeng Xiao 		       {{{.code_and_extra = 0xc001b,.length2 = 0x5}}},
6039099918dSPeng Xiao 		       {{{.code_and_extra = 0xd0007,.length2 = 0x5}}},
6049099918dSPeng Xiao 		       {{{.code_and_extra = 0xd0017,.length2 = 0x5}}},
6059099918dSPeng Xiao 		       {{{.code_and_extra = 0x000,.length2 = 0x0}}}}
6069992cc19SRoy Oursler };
6079992cc19SRoy Oursler 
608d06e14b9SRoy Oursler struct slver {
609d06e14b9SRoy Oursler 	uint16_t snum;
610d06e14b9SRoy Oursler 	uint8_t ver;
611d06e14b9SRoy Oursler 	uint8_t core;
612d06e14b9SRoy Oursler };
613d06e14b9SRoy Oursler 
614d06e14b9SRoy Oursler /* Version info */
615d06e14b9SRoy Oursler struct slver isal_update_histogram_slver_00010085;
616d06e14b9SRoy Oursler struct slver isal_update_histogram_slver = { 0x0085, 0x01, 0x00 };
61788f95d85SRoy Oursler 
618d06e14b9SRoy Oursler struct slver isal_create_hufftables_slver_00010086;
619d06e14b9SRoy Oursler struct slver isal_create_hufftables_slver = { 0x0086, 0x01, 0x00 };
620d06e14b9SRoy Oursler 
62188192ce5SGreg Tucker struct slver isal_create_hufftables_subset_slver_00010087;
62288192ce5SGreg Tucker struct slver isal_create_hufftables_subset_slver = { 0x0087, 0x01, 0x00 };
62388192ce5SGreg Tucker 
624ec6e5de6SGreg Tucker extern uint32_t build_huff_tree(struct heap_tree *heap, uint64_t heap_size, uint64_t node_ptr);
625ec6e5de6SGreg Tucker extern void build_heap(uint64_t * heap, uint64_t heap_size);
62601dfbcc4SRoy Oursler 
62701dfbcc4SRoy Oursler static const uint8_t bitrev8[0x100] = {
62801dfbcc4SRoy Oursler 	0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
62901dfbcc4SRoy Oursler 	0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
63001dfbcc4SRoy Oursler 	0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
63101dfbcc4SRoy Oursler 	0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
63201dfbcc4SRoy Oursler 	0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
63301dfbcc4SRoy Oursler 	0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
63401dfbcc4SRoy Oursler 	0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
63501dfbcc4SRoy Oursler 	0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
63601dfbcc4SRoy Oursler 	0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
63701dfbcc4SRoy Oursler 	0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
63801dfbcc4SRoy Oursler 	0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
63901dfbcc4SRoy Oursler 	0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
64001dfbcc4SRoy Oursler 	0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
64101dfbcc4SRoy Oursler 	0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
64201dfbcc4SRoy Oursler 	0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
64301dfbcc4SRoy Oursler 	0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
64401dfbcc4SRoy Oursler 	0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
64501dfbcc4SRoy Oursler 	0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
64601dfbcc4SRoy Oursler 	0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
64701dfbcc4SRoy Oursler 	0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
64801dfbcc4SRoy Oursler 	0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
64901dfbcc4SRoy Oursler 	0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
65001dfbcc4SRoy Oursler 	0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
65101dfbcc4SRoy Oursler 	0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
65201dfbcc4SRoy Oursler 	0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
65301dfbcc4SRoy Oursler 	0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
65401dfbcc4SRoy Oursler 	0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
65501dfbcc4SRoy Oursler 	0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
65601dfbcc4SRoy Oursler 	0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
65701dfbcc4SRoy Oursler 	0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
65801dfbcc4SRoy Oursler 	0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
65901dfbcc4SRoy Oursler 	0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
66001dfbcc4SRoy Oursler };
66101dfbcc4SRoy Oursler 
66201dfbcc4SRoy Oursler // bit reverse low order LENGTH bits in code, and return result in low order bits
66301dfbcc4SRoy Oursler static inline uint16_t bit_reverse(uint16_t code, uint32_t length)
664660f49b0SGreg Tucker {
66501dfbcc4SRoy Oursler 	code = (bitrev8[code & 0x00FF] << 8) | (bitrev8[code >> 8]);
66601dfbcc4SRoy Oursler 	return (code >> (16 - length));
667660f49b0SGreg Tucker }
668660f49b0SGreg Tucker 
66931814483SRoy Oursler void isal_update_histogram_base(uint8_t * start_stream, int length,
670660f49b0SGreg Tucker 				struct isal_huff_histogram *histogram)
671660f49b0SGreg Tucker {
672660f49b0SGreg Tucker 	uint32_t literal = 0, hash;
6738fe5cbeeSRoy Oursler 	uint16_t seen, *last_seen = histogram->hash_table;
6748fe5cbeeSRoy Oursler 	uint8_t *current, *end_stream, *next_hash, *end;
675660f49b0SGreg Tucker 	uint32_t match_length;
676660f49b0SGreg Tucker 	uint32_t dist;
677660f49b0SGreg Tucker 	uint64_t *lit_len_histogram = histogram->lit_len_histogram;
678660f49b0SGreg Tucker 	uint64_t *dist_histogram = histogram->dist_histogram;
679660f49b0SGreg Tucker 
680660f49b0SGreg Tucker 	if (length <= 0)
681660f49b0SGreg Tucker 		return;
682660f49b0SGreg Tucker 
683660f49b0SGreg Tucker 	end_stream = start_stream + length;
6848fe5cbeeSRoy Oursler 	memset(last_seen, 0, sizeof(histogram->hash_table));	/* Initialize last_seen to be 0. */
685660f49b0SGreg Tucker 	for (current = start_stream; current < end_stream - 3; current++) {
686660f49b0SGreg Tucker 		literal = *(uint32_t *) current;
687660f49b0SGreg Tucker 		hash = compute_hash(literal) & HASH_MASK;
688660f49b0SGreg Tucker 		seen = last_seen[hash];
689c28be0d3SGreg Tucker 		last_seen[hash] = (current - start_stream) & 0xFFFF;
690c28be0d3SGreg Tucker 		dist = (current - start_stream - seen) & 0xFFFF;
6918fe5cbeeSRoy Oursler 		if (dist - 1 < D - 1) {
692d4c6067dSRoy Oursler 			assert(start_stream <= current - dist);
6938fe5cbeeSRoy Oursler 			match_length =
6948fe5cbeeSRoy Oursler 			    compare258(current - dist, current, end_stream - current);
695660f49b0SGreg Tucker 			if (match_length >= SHORTEST_MATCH) {
696660f49b0SGreg Tucker 				next_hash = current;
69788f95d85SRoy Oursler #ifdef ISAL_LIMIT_HASH_UPDATE
698660f49b0SGreg Tucker 				end = next_hash + 3;
699660f49b0SGreg Tucker #else
700660f49b0SGreg Tucker 				end = next_hash + match_length;
701660f49b0SGreg Tucker #endif
702660f49b0SGreg Tucker 				if (end > end_stream - 3)
703660f49b0SGreg Tucker 					end = end_stream - 3;
704660f49b0SGreg Tucker 				next_hash++;
705660f49b0SGreg Tucker 				for (; next_hash < end; next_hash++) {
706660f49b0SGreg Tucker 					literal = *(uint32_t *) next_hash;
707660f49b0SGreg Tucker 					hash = compute_hash(literal) & HASH_MASK;
708c28be0d3SGreg Tucker 					last_seen[hash] = (next_hash - start_stream) & 0xFFFF;
709660f49b0SGreg Tucker 				}
710660f49b0SGreg Tucker 
711660f49b0SGreg Tucker 				dist_histogram[convert_dist_to_dist_sym(dist)] += 1;
712660f49b0SGreg Tucker 				lit_len_histogram[convert_length_to_len_sym(match_length)] +=
713660f49b0SGreg Tucker 				    1;
714660f49b0SGreg Tucker 				current += match_length - 1;
715660f49b0SGreg Tucker 				continue;
716660f49b0SGreg Tucker 			}
717660f49b0SGreg Tucker 		}
718660f49b0SGreg Tucker 		lit_len_histogram[literal & 0xFF] += 1;
719660f49b0SGreg Tucker 	}
720660f49b0SGreg Tucker 	literal = literal >> 8;
721660f49b0SGreg Tucker 	hash = compute_hash(literal) & HASH_MASK;
722660f49b0SGreg Tucker 	seen = last_seen[hash];
723c28be0d3SGreg Tucker 	last_seen[hash] = (current - start_stream) & 0xFFFF;
724c28be0d3SGreg Tucker 	dist = (current - start_stream - seen) & 0xFFFF;
725660f49b0SGreg Tucker 	if (dist < D) {
7268fe5cbeeSRoy Oursler 		match_length = compare258(current - dist, current, end_stream - current);
727660f49b0SGreg Tucker 		if (match_length >= SHORTEST_MATCH) {
728660f49b0SGreg Tucker 			dist_histogram[convert_dist_to_dist_sym(dist)] += 1;
729660f49b0SGreg Tucker 			lit_len_histogram[convert_length_to_len_sym(match_length)] += 1;
730660f49b0SGreg Tucker 			lit_len_histogram[256] += 1;
731660f49b0SGreg Tucker 			return;
732660f49b0SGreg Tucker 		}
733660f49b0SGreg Tucker 	} else
734660f49b0SGreg Tucker 		lit_len_histogram[literal & 0xFF] += 1;
735660f49b0SGreg Tucker 	lit_len_histogram[(literal >> 8) & 0xFF] += 1;
736660f49b0SGreg Tucker 	lit_len_histogram[(literal >> 16) & 0xFF] += 1;
737660f49b0SGreg Tucker 	lit_len_histogram[256] += 1;
738660f49b0SGreg Tucker 	return;
739660f49b0SGreg Tucker }
740660f49b0SGreg Tucker 
741660f49b0SGreg Tucker uint32_t convert_dist_to_dist_sym(uint32_t dist)
742660f49b0SGreg Tucker {
743660f49b0SGreg Tucker 	assert(dist <= 32768 && dist > 0);
744660f49b0SGreg Tucker 	if (dist <= 2)
745660f49b0SGreg Tucker 		return dist - 1;
746660f49b0SGreg Tucker 	else if (dist <= 4)
747660f49b0SGreg Tucker 		return 0 + (dist - 1) / 1;
748660f49b0SGreg Tucker 	else if (dist <= 8)
749660f49b0SGreg Tucker 		return 2 + (dist - 1) / 2;
750660f49b0SGreg Tucker 	else if (dist <= 16)
751660f49b0SGreg Tucker 		return 4 + (dist - 1) / 4;
752660f49b0SGreg Tucker 	else if (dist <= 32)
753660f49b0SGreg Tucker 		return 6 + (dist - 1) / 8;
754660f49b0SGreg Tucker 	else if (dist <= 64)
755660f49b0SGreg Tucker 		return 8 + (dist - 1) / 16;
756660f49b0SGreg Tucker 	else if (dist <= 128)
757660f49b0SGreg Tucker 		return 10 + (dist - 1) / 32;
758660f49b0SGreg Tucker 	else if (dist <= 256)
759660f49b0SGreg Tucker 		return 12 + (dist - 1) / 64;
760660f49b0SGreg Tucker 	else if (dist <= 512)
761660f49b0SGreg Tucker 		return 14 + (dist - 1) / 128;
762660f49b0SGreg Tucker 	else if (dist <= 1024)
763660f49b0SGreg Tucker 		return 16 + (dist - 1) / 256;
764660f49b0SGreg Tucker 	else if (dist <= 2048)
765660f49b0SGreg Tucker 		return 18 + (dist - 1) / 512;
766660f49b0SGreg Tucker 	else if (dist <= 4096)
767660f49b0SGreg Tucker 		return 20 + (dist - 1) / 1024;
768660f49b0SGreg Tucker 	else if (dist <= 8192)
769660f49b0SGreg Tucker 		return 22 + (dist - 1) / 2048;
770660f49b0SGreg Tucker 	else if (dist <= 16384)
771660f49b0SGreg Tucker 		return 24 + (dist - 1) / 4096;
772660f49b0SGreg Tucker 	else if (dist <= 32768)
773660f49b0SGreg Tucker 		return 26 + (dist - 1) / 8192;
774660f49b0SGreg Tucker 	else
775660f49b0SGreg Tucker 		return ~0;	/* ~0 is an invalid distance code */
776660f49b0SGreg Tucker 
777660f49b0SGreg Tucker }
778660f49b0SGreg Tucker 
779660f49b0SGreg Tucker uint32_t convert_length_to_len_sym(uint32_t length)
780660f49b0SGreg Tucker {
781660f49b0SGreg Tucker 	assert(length > 2 && length < 259);
782660f49b0SGreg Tucker 
783660f49b0SGreg Tucker 	/* Based on tables on page 11 in RFC 1951 */
784660f49b0SGreg Tucker 	if (length < 11)
785660f49b0SGreg Tucker 		return 257 + length - 3;
786660f49b0SGreg Tucker 	else if (length < 19)
787660f49b0SGreg Tucker 		return 261 + (length - 3) / 2;
788660f49b0SGreg Tucker 	else if (length < 35)
789660f49b0SGreg Tucker 		return 265 + (length - 3) / 4;
790660f49b0SGreg Tucker 	else if (length < 67)
791660f49b0SGreg Tucker 		return 269 + (length - 3) / 8;
792660f49b0SGreg Tucker 	else if (length < 131)
793660f49b0SGreg Tucker 		return 273 + (length - 3) / 16;
794660f49b0SGreg Tucker 	else if (length < 258)
795660f49b0SGreg Tucker 		return 277 + (length - 3) / 32;
796660f49b0SGreg Tucker 	else
797660f49b0SGreg Tucker 		return 285;
798660f49b0SGreg Tucker }
799660f49b0SGreg Tucker 
80001dfbcc4SRoy Oursler // Upon return, codes[] contains the code lengths,
80101dfbcc4SRoy Oursler // and bl_count is the count of the lengths
80201dfbcc4SRoy Oursler 
80301dfbcc4SRoy Oursler /* Init heap with the histogram, and return the histogram size */
804e38ed4b5SRoy Oursler static inline uint32_t init_heap32(struct heap_tree *heap_space, uint32_t * histogram,
80501dfbcc4SRoy Oursler 				   uint32_t hist_size)
806660f49b0SGreg Tucker {
80701dfbcc4SRoy Oursler 	uint32_t heap_size, i;
808660f49b0SGreg Tucker 
80901dfbcc4SRoy Oursler 	memset(heap_space, 0, sizeof(struct heap_tree));
810660f49b0SGreg Tucker 
81101dfbcc4SRoy Oursler 	heap_size = 0;
81201dfbcc4SRoy Oursler 	for (i = 0; i < hist_size; i++) {
81301dfbcc4SRoy Oursler 		if (histogram[i] != 0)
81401dfbcc4SRoy Oursler 			heap_space->heap[++heap_size] =
81501dfbcc4SRoy Oursler 			    (((uint64_t) histogram[i]) << FREQ_SHIFT) | i;
816660f49b0SGreg Tucker 	}
817660f49b0SGreg Tucker 
81801dfbcc4SRoy Oursler 	// make sure heap has at least two elements in it
81901dfbcc4SRoy Oursler 	if (heap_size < 2) {
82001dfbcc4SRoy Oursler 		if (heap_size == 0) {
82101dfbcc4SRoy Oursler 			heap_space->heap[1] = 1ULL << FREQ_SHIFT;
82201dfbcc4SRoy Oursler 			heap_space->heap[2] = (1ULL << FREQ_SHIFT) | 1;
82301dfbcc4SRoy Oursler 			heap_size = 2;
824660f49b0SGreg Tucker 		} else {
82501dfbcc4SRoy Oursler 			// heap size == 1
82601dfbcc4SRoy Oursler 			if (histogram[0] == 0)
82701dfbcc4SRoy Oursler 				heap_space->heap[2] = 1ULL << FREQ_SHIFT;
828660f49b0SGreg Tucker 			else
82901dfbcc4SRoy Oursler 				heap_space->heap[2] = (1ULL << FREQ_SHIFT) | 1;
83001dfbcc4SRoy Oursler 			heap_size = 2;
83101dfbcc4SRoy Oursler 		}
832660f49b0SGreg Tucker 	}
833660f49b0SGreg Tucker 
834f80a1ed6SRoy Oursler 	build_heap(heap_space->heap, heap_size);
83501dfbcc4SRoy Oursler 
83601dfbcc4SRoy Oursler 	return heap_size;
837660f49b0SGreg Tucker }
838660f49b0SGreg Tucker 
83901dfbcc4SRoy Oursler static inline uint32_t init_heap64(struct heap_tree *heap_space, uint64_t * histogram,
84001dfbcc4SRoy Oursler 				   uint64_t hist_size)
841660f49b0SGreg Tucker {
84201dfbcc4SRoy Oursler 	uint32_t heap_size, i;
84301dfbcc4SRoy Oursler 
84401dfbcc4SRoy Oursler 	memset(heap_space, 0, sizeof(struct heap_tree));
84501dfbcc4SRoy Oursler 
84601dfbcc4SRoy Oursler 	heap_size = 0;
84701dfbcc4SRoy Oursler 	for (i = 0; i < hist_size; i++) {
84801dfbcc4SRoy Oursler 		if (histogram[i] != 0)
84901dfbcc4SRoy Oursler 			heap_space->heap[++heap_size] = ((histogram[i]) << FREQ_SHIFT) | i;
850660f49b0SGreg Tucker 	}
851660f49b0SGreg Tucker 
85201dfbcc4SRoy Oursler 	// make sure heap has at least two elements in it
85301dfbcc4SRoy Oursler 	if (heap_size < 2) {
85401dfbcc4SRoy Oursler 		if (heap_size == 0) {
85501dfbcc4SRoy Oursler 			heap_space->heap[1] = 1ULL << FREQ_SHIFT;
85601dfbcc4SRoy Oursler 			heap_space->heap[2] = (1ULL << FREQ_SHIFT) | 1;
85701dfbcc4SRoy Oursler 			heap_size = 2;
85801dfbcc4SRoy Oursler 		} else {
85901dfbcc4SRoy Oursler 			// heap size == 1
86001dfbcc4SRoy Oursler 			if (histogram[0] == 0)
86101dfbcc4SRoy Oursler 				heap_space->heap[2] = 1ULL << FREQ_SHIFT;
86201dfbcc4SRoy Oursler 			else
86301dfbcc4SRoy Oursler 				heap_space->heap[2] = (1ULL << FREQ_SHIFT) | 1;
86401dfbcc4SRoy Oursler 			heap_size = 2;
86501dfbcc4SRoy Oursler 		}
86601dfbcc4SRoy Oursler 	}
86701dfbcc4SRoy Oursler 
868f80a1ed6SRoy Oursler 	build_heap(heap_space->heap, heap_size);
86901dfbcc4SRoy Oursler 
87001dfbcc4SRoy Oursler 	return heap_size;
87101dfbcc4SRoy Oursler }
87201dfbcc4SRoy Oursler 
873*e79c57c7SRoy Oursler static inline uint32_t init_heap64_semi_complete(struct heap_tree *heap_space,
874*e79c57c7SRoy Oursler 						 uint64_t * histogram, uint64_t hist_size,
875*e79c57c7SRoy Oursler 						 uint64_t complete_start)
876*e79c57c7SRoy Oursler {
877*e79c57c7SRoy Oursler 	uint32_t heap_size, i;
878*e79c57c7SRoy Oursler 
879*e79c57c7SRoy Oursler 	memset(heap_space, 0, sizeof(struct heap_tree));
880*e79c57c7SRoy Oursler 
881*e79c57c7SRoy Oursler 	heap_size = 0;
882*e79c57c7SRoy Oursler 	for (i = 0; i < complete_start; i++) {
883*e79c57c7SRoy Oursler 		if (histogram[i] != 0)
884*e79c57c7SRoy Oursler 			heap_space->heap[++heap_size] = ((histogram[i]) << FREQ_SHIFT) | i;
885*e79c57c7SRoy Oursler 	}
886*e79c57c7SRoy Oursler 
887*e79c57c7SRoy Oursler 	for (; i < hist_size; i++)
888*e79c57c7SRoy Oursler 		heap_space->heap[++heap_size] = ((histogram[i]) << FREQ_SHIFT) | i;
889*e79c57c7SRoy Oursler 
890*e79c57c7SRoy Oursler 	// make sure heap has at least two elements in it
891*e79c57c7SRoy Oursler 	if (heap_size < 2) {
892*e79c57c7SRoy Oursler 		if (heap_size == 0) {
893*e79c57c7SRoy Oursler 			heap_space->heap[1] = 1ULL << FREQ_SHIFT;
894*e79c57c7SRoy Oursler 			heap_space->heap[2] = (1ULL << FREQ_SHIFT) | 1;
895*e79c57c7SRoy Oursler 			heap_size = 2;
896*e79c57c7SRoy Oursler 		} else {
897*e79c57c7SRoy Oursler 			// heap size == 1
898*e79c57c7SRoy Oursler 			if (histogram[0] == 0)
899*e79c57c7SRoy Oursler 				heap_space->heap[2] = 1ULL << FREQ_SHIFT;
900*e79c57c7SRoy Oursler 			else
901*e79c57c7SRoy Oursler 				heap_space->heap[2] = (1ULL << FREQ_SHIFT) | 1;
902*e79c57c7SRoy Oursler 			heap_size = 2;
903*e79c57c7SRoy Oursler 		}
904*e79c57c7SRoy Oursler 	}
905*e79c57c7SRoy Oursler 
906*e79c57c7SRoy Oursler 	build_heap(heap_space->heap, heap_size);
907*e79c57c7SRoy Oursler 
908*e79c57c7SRoy Oursler 	return heap_size;
909*e79c57c7SRoy Oursler }
910*e79c57c7SRoy Oursler 
91101dfbcc4SRoy Oursler static inline uint32_t init_heap64_complete(struct heap_tree *heap_space, uint64_t * histogram,
91201dfbcc4SRoy Oursler 					    uint64_t hist_size)
91301dfbcc4SRoy Oursler {
91401dfbcc4SRoy Oursler 	uint32_t heap_size, i;
91501dfbcc4SRoy Oursler 
91601dfbcc4SRoy Oursler 	memset(heap_space, 0, sizeof(struct heap_tree));
91701dfbcc4SRoy Oursler 
91801dfbcc4SRoy Oursler 	heap_size = 0;
91901dfbcc4SRoy Oursler 	for (i = 0; i < hist_size; i++)
92001dfbcc4SRoy Oursler 		heap_space->heap[++heap_size] = ((histogram[i]) << FREQ_SHIFT) | i;
92101dfbcc4SRoy Oursler 
922f80a1ed6SRoy Oursler 	build_heap(heap_space->heap, heap_size);
92301dfbcc4SRoy Oursler 
92401dfbcc4SRoy Oursler 	return heap_size;
92501dfbcc4SRoy Oursler }
92601dfbcc4SRoy Oursler 
92701dfbcc4SRoy Oursler static inline uint32_t fix_code_lens(struct heap_tree *heap_space, uint32_t root_node,
92801dfbcc4SRoy Oursler 				     uint32_t * bl_count, uint32_t max_code_len)
92901dfbcc4SRoy Oursler {
93001dfbcc4SRoy Oursler 	struct tree_node *tree = heap_space->tree;
93101dfbcc4SRoy Oursler 	uint64_t *code_len_count = heap_space->code_len_count;
93201dfbcc4SRoy Oursler 	uint32_t i, j, k, child, depth, code_len;
93301dfbcc4SRoy Oursler 
93401dfbcc4SRoy Oursler 	// compute code lengths and code length counts
93501dfbcc4SRoy Oursler 	code_len = 0;
93601dfbcc4SRoy Oursler 	j = root_node;
93701dfbcc4SRoy Oursler 	for (i = root_node; i <= HEAP_TREE_NODE_START; i++) {
93801dfbcc4SRoy Oursler 		child = tree[i].child;
93901dfbcc4SRoy Oursler 		if (child > MAX_HISTHEAP_SIZE) {
94001dfbcc4SRoy Oursler 			depth = 1 + tree[i].depth;
94101dfbcc4SRoy Oursler 
94201dfbcc4SRoy Oursler 			tree[child].depth = depth;
94301dfbcc4SRoy Oursler 			tree[child - 1].depth = depth;
94401dfbcc4SRoy Oursler 		} else {
94501dfbcc4SRoy Oursler 			tree[j++] = tree[i];
94601dfbcc4SRoy Oursler 			depth = tree[i].depth;
94701dfbcc4SRoy Oursler 			while (code_len < depth) {
94801dfbcc4SRoy Oursler 				code_len++;
94901dfbcc4SRoy Oursler 				code_len_count[code_len] = 0;
95001dfbcc4SRoy Oursler 			}
95101dfbcc4SRoy Oursler 			code_len_count[depth]++;
95201dfbcc4SRoy Oursler 		}
95301dfbcc4SRoy Oursler 	}
95401dfbcc4SRoy Oursler 
95501dfbcc4SRoy Oursler 	if (code_len > max_code_len) {
95601dfbcc4SRoy Oursler 		while (code_len > max_code_len) {
95701dfbcc4SRoy Oursler 			assert(code_len_count[code_len] > 1);
95801dfbcc4SRoy Oursler 			for (i = max_code_len - 1; i != 0; i--)
95901dfbcc4SRoy Oursler 				if (code_len_count[i] != 0)
96001dfbcc4SRoy Oursler 					break;
96101dfbcc4SRoy Oursler 			assert(i != 0);
96201dfbcc4SRoy Oursler 			code_len_count[i]--;
96301dfbcc4SRoy Oursler 			code_len_count[i + 1] += 2;
96401dfbcc4SRoy Oursler 			code_len_count[code_len - 1]++;
96501dfbcc4SRoy Oursler 			code_len_count[code_len] -= 2;
96601dfbcc4SRoy Oursler 			if (code_len_count[code_len] == 0)
96701dfbcc4SRoy Oursler 				code_len--;
96801dfbcc4SRoy Oursler 		}
96901dfbcc4SRoy Oursler 
97001dfbcc4SRoy Oursler 		for (i = 1; i <= code_len; i++)
97101dfbcc4SRoy Oursler 			bl_count[i] = code_len_count[i];
97201dfbcc4SRoy Oursler 		for (; i <= max_code_len; i++)
97301dfbcc4SRoy Oursler 			bl_count[i] = 0;
97401dfbcc4SRoy Oursler 
97501dfbcc4SRoy Oursler 		for (k = 1; code_len_count[k] == 0; k++) ;
97601dfbcc4SRoy Oursler 		for (i = root_node; i < j; i++) {
97701dfbcc4SRoy Oursler 			tree[i].depth = k;
97801dfbcc4SRoy Oursler 			code_len_count[k]--;
97901dfbcc4SRoy Oursler 			for (; code_len_count[k] == 0; k++) ;
98001dfbcc4SRoy Oursler 		}
98101dfbcc4SRoy Oursler 	} else {
98201dfbcc4SRoy Oursler 		for (i = 1; i <= code_len; i++)
98301dfbcc4SRoy Oursler 			bl_count[i] = code_len_count[i];
98401dfbcc4SRoy Oursler 		for (; i <= max_code_len; i++)
98501dfbcc4SRoy Oursler 			bl_count[i] = 0;
98601dfbcc4SRoy Oursler 	}
98701dfbcc4SRoy Oursler 
98801dfbcc4SRoy Oursler 	return j;
98901dfbcc4SRoy Oursler 
99001dfbcc4SRoy Oursler }
99101dfbcc4SRoy Oursler 
99201dfbcc4SRoy Oursler static inline void
99301dfbcc4SRoy Oursler gen_huff_code_lens(struct heap_tree *heap_space, uint32_t heap_size, uint32_t * bl_count,
99401dfbcc4SRoy Oursler 		   struct huff_code *codes, uint32_t codes_count, uint32_t max_code_len)
99501dfbcc4SRoy Oursler {
99601dfbcc4SRoy Oursler 	struct tree_node *tree = heap_space->tree;
99701dfbcc4SRoy Oursler 	uint32_t root_node = HEAP_TREE_NODE_START, node_ptr;
99801dfbcc4SRoy Oursler 	uint32_t end_node;
99901dfbcc4SRoy Oursler 
100001dfbcc4SRoy Oursler 	root_node = build_huff_tree(heap_space, heap_size, root_node);
100101dfbcc4SRoy Oursler 
100201dfbcc4SRoy Oursler 	end_node = fix_code_lens(heap_space, root_node, bl_count, max_code_len);
100301dfbcc4SRoy Oursler 
100401dfbcc4SRoy Oursler 	memset(codes, 0, codes_count * sizeof(*codes));
100501dfbcc4SRoy Oursler 	for (node_ptr = root_node; node_ptr < end_node; node_ptr++)
100601dfbcc4SRoy Oursler 		codes[tree[node_ptr].child].length = tree[node_ptr].depth;
100701dfbcc4SRoy Oursler 
100801dfbcc4SRoy Oursler }
100901dfbcc4SRoy Oursler 
101001dfbcc4SRoy Oursler inline uint32_t set_huff_codes(struct huff_code *huff_code_table, int table_length,
101101dfbcc4SRoy Oursler 			       uint32_t * count)
1012660f49b0SGreg Tucker {
1013660f49b0SGreg Tucker 	/* Uses the algorithm mentioned in the deflate standard, Rfc 1951. */
1014660f49b0SGreg Tucker 	int i;
1015660f49b0SGreg Tucker 	uint16_t code = 0;
1016660f49b0SGreg Tucker 	uint16_t next_code[MAX_HUFF_TREE_DEPTH + 1];
101701dfbcc4SRoy Oursler 	uint32_t max_code = 0;
1018660f49b0SGreg Tucker 
1019660f49b0SGreg Tucker 	next_code[0] = code;
1020660f49b0SGreg Tucker 
1021660f49b0SGreg Tucker 	for (i = 1; i < MAX_HUFF_TREE_DEPTH + 1; i++)
1022660f49b0SGreg Tucker 		next_code[i] = (next_code[i - 1] + count[i - 1]) << 1;
1023660f49b0SGreg Tucker 
1024660f49b0SGreg Tucker 	for (i = 0; i < table_length; i++) {
1025660f49b0SGreg Tucker 		if (huff_code_table[i].length != 0) {
1026660f49b0SGreg Tucker 			huff_code_table[i].code =
1027660f49b0SGreg Tucker 			    bit_reverse(next_code[huff_code_table[i].length],
1028660f49b0SGreg Tucker 					huff_code_table[i].length);
1029660f49b0SGreg Tucker 			next_code[huff_code_table[i].length] += 1;
103001dfbcc4SRoy Oursler 			max_code = i;
1031660f49b0SGreg Tucker 		}
1032660f49b0SGreg Tucker 	}
1033660f49b0SGreg Tucker 
103401dfbcc4SRoy Oursler 	return max_code;
1035660f49b0SGreg Tucker }
1036660f49b0SGreg Tucker 
103701dfbcc4SRoy Oursler // on input, codes contain the code lengths
103801dfbcc4SRoy Oursler // on output, code contains:
103901dfbcc4SRoy Oursler // 23:16 code length
104001dfbcc4SRoy Oursler // 15:0  code value in low order bits
104101dfbcc4SRoy Oursler // returns max code value
104201dfbcc4SRoy Oursler static inline uint32_t set_dist_huff_codes(struct huff_code *codes, uint32_t * bl_count)
104301dfbcc4SRoy Oursler {
104401dfbcc4SRoy Oursler 	uint32_t code, code_len, bits, i;
104501dfbcc4SRoy Oursler 	uint32_t next_code[MAX_DEFLATE_CODE_LEN + 1];
104601dfbcc4SRoy Oursler 	uint32_t max_code = 0;
104701dfbcc4SRoy Oursler 	const uint32_t num_codes = DIST_LEN;
104801dfbcc4SRoy Oursler 
104901dfbcc4SRoy Oursler 	code = bl_count[0] = 0;
105001dfbcc4SRoy Oursler 	for (bits = 1; bits <= MAX_HUFF_TREE_DEPTH; bits++) {
105101dfbcc4SRoy Oursler 		code = (code + bl_count[bits - 1]) << 1;
105201dfbcc4SRoy Oursler 		next_code[bits] = code;
105301dfbcc4SRoy Oursler 	}
105401dfbcc4SRoy Oursler 	for (i = 0; i < num_codes; i++) {
105501dfbcc4SRoy Oursler 		code_len = codes[i].length;
105601dfbcc4SRoy Oursler 		if (code_len != 0) {
105701dfbcc4SRoy Oursler 			codes[i].code = bit_reverse(next_code[code_len], code_len);
10589992cc19SRoy Oursler 			codes[i].extra_bit_count = dist_code_extra_bits[i];
105901dfbcc4SRoy Oursler 			next_code[code_len] += 1;
106001dfbcc4SRoy Oursler 			max_code = i;
106101dfbcc4SRoy Oursler 		}
106201dfbcc4SRoy Oursler 	}
106301dfbcc4SRoy Oursler 	return max_code;
106401dfbcc4SRoy Oursler }
106501dfbcc4SRoy Oursler 
106601dfbcc4SRoy Oursler int create_huffman_header(struct BitBuf2 *header_bitbuf,
106701dfbcc4SRoy Oursler 			  struct huff_code *lookup_table,
106801dfbcc4SRoy Oursler 			  struct rl_code *huffman_rep,
106901dfbcc4SRoy Oursler 			  uint16_t huffman_rep_length, uint32_t end_of_block,
107001dfbcc4SRoy Oursler 			  uint32_t hclen, uint32_t hlit, uint32_t hdist)
107101dfbcc4SRoy Oursler {
107201dfbcc4SRoy Oursler 	/* hlit, hdist, hclen are as defined in the deflate standard, head is the
107301dfbcc4SRoy Oursler 	 * first three deflate header bits.*/
107401dfbcc4SRoy Oursler 	int i;
107501dfbcc4SRoy Oursler 	uint64_t bit_count;
107601dfbcc4SRoy Oursler 	uint64_t data;
107701dfbcc4SRoy Oursler 	struct huff_code huffman_value;
107801dfbcc4SRoy Oursler 	const uint32_t extra_bits[3] = { 2, 3, 7 };
107901dfbcc4SRoy Oursler 
108001dfbcc4SRoy Oursler 	bit_count = buffer_bits_used(header_bitbuf);
108101dfbcc4SRoy Oursler 
108201dfbcc4SRoy Oursler 	data = (end_of_block ? 5 : 4) | (hlit << 3) | (hdist << 8) | (hclen << 13);
108301dfbcc4SRoy Oursler 	data |= ((lookup_table[code_length_code_order[0]].length) << DYN_HDR_START_LEN);
108401dfbcc4SRoy Oursler 	write_bits(header_bitbuf, data, DYN_HDR_START_LEN + 3);
108501dfbcc4SRoy Oursler 	data = 0;
108601dfbcc4SRoy Oursler 	for (i = hclen + 3; i >= 1; i--)
108701dfbcc4SRoy Oursler 		data = (data << 3) | lookup_table[code_length_code_order[i]].length;
108801dfbcc4SRoy Oursler 
108901dfbcc4SRoy Oursler 	write_bits(header_bitbuf, data, (hclen + 3) * 3);
109001dfbcc4SRoy Oursler 
109101dfbcc4SRoy Oursler 	for (i = 0; i < huffman_rep_length; i++) {
109201dfbcc4SRoy Oursler 		huffman_value = lookup_table[huffman_rep[i].code];
109301dfbcc4SRoy Oursler 
109401dfbcc4SRoy Oursler 		write_bits(header_bitbuf, (uint64_t) huffman_value.code,
109501dfbcc4SRoy Oursler 			   (uint32_t) huffman_value.length);
109601dfbcc4SRoy Oursler 
109701dfbcc4SRoy Oursler 		if (huffman_rep[i].code > 15) {
109801dfbcc4SRoy Oursler 			write_bits(header_bitbuf, (uint64_t) huffman_rep[i].extra_bits,
109901dfbcc4SRoy Oursler 				   (uint32_t) extra_bits[huffman_rep[i].code - 16]);
110001dfbcc4SRoy Oursler 		}
110101dfbcc4SRoy Oursler 	}
110201dfbcc4SRoy Oursler 	bit_count = buffer_bits_used(header_bitbuf) - bit_count;
110301dfbcc4SRoy Oursler 
110401dfbcc4SRoy Oursler 	return bit_count;
110501dfbcc4SRoy Oursler }
110601dfbcc4SRoy Oursler 
110701dfbcc4SRoy Oursler inline int create_header(struct BitBuf2 *header_bitbuf, struct rl_code *huffman_rep,
110801dfbcc4SRoy Oursler 			 uint32_t length, uint64_t * histogram, uint32_t hlit,
110901dfbcc4SRoy Oursler 			 uint32_t hdist, uint32_t end_of_block)
1110660f49b0SGreg Tucker {
1111660f49b0SGreg Tucker 	int i;
111201dfbcc4SRoy Oursler 
111301dfbcc4SRoy Oursler 	uint32_t heap_size;
111401dfbcc4SRoy Oursler 	struct heap_tree heap_space;
111501dfbcc4SRoy Oursler 	uint32_t code_len_count[MAX_HUFF_TREE_DEPTH + 1];
1116660f49b0SGreg Tucker 	struct huff_code lookup_table[HUFF_LEN];
1117660f49b0SGreg Tucker 
1118660f49b0SGreg Tucker 	/* hlit, hdist, and hclen are defined in RFC 1951 page 13 */
111901dfbcc4SRoy Oursler 	uint32_t hclen;
1120660f49b0SGreg Tucker 	uint64_t bit_count;
1121660f49b0SGreg Tucker 
1122660f49b0SGreg Tucker 	/* Create a huffman tree to encode run length encoded representation. */
112301dfbcc4SRoy Oursler 	heap_size = init_heap64(&heap_space, histogram, HUFF_LEN);
112401dfbcc4SRoy Oursler 	gen_huff_code_lens(&heap_space, heap_size, code_len_count,
112501dfbcc4SRoy Oursler 			   (struct huff_code *)lookup_table, HUFF_LEN, 7);
112601dfbcc4SRoy Oursler 	set_huff_codes(lookup_table, HUFF_LEN, code_len_count);
1127660f49b0SGreg Tucker 
1128660f49b0SGreg Tucker 	/* Calculate hclen */
1129660f49b0SGreg Tucker 	for (i = CODE_LEN_CODES - 1; i > 3; i--)	/* i must be at least 4 */
1130660f49b0SGreg Tucker 		if (lookup_table[code_length_code_order[i]].length != 0)
1131660f49b0SGreg Tucker 			break;
1132660f49b0SGreg Tucker 
1133660f49b0SGreg Tucker 	hclen = i - 3;
1134660f49b0SGreg Tucker 
1135660f49b0SGreg Tucker 	/* Generate actual header. */
113601dfbcc4SRoy Oursler 	bit_count = create_huffman_header(header_bitbuf, lookup_table, huffman_rep,
113701dfbcc4SRoy Oursler 					  length, end_of_block, hclen, hlit, hdist);
1138660f49b0SGreg Tucker 
1139660f49b0SGreg Tucker 	return bit_count;
1140660f49b0SGreg Tucker }
1141660f49b0SGreg Tucker 
114201dfbcc4SRoy Oursler static inline
114301dfbcc4SRoy Oursler     struct rl_code *write_rl(struct rl_code *pout, uint16_t last_len, uint32_t run_len,
114401dfbcc4SRoy Oursler 			     uint64_t * counts)
1145660f49b0SGreg Tucker {
114601dfbcc4SRoy Oursler 	if (last_len == 0) {
114701dfbcc4SRoy Oursler 		while (run_len > 138) {
114801dfbcc4SRoy Oursler 			pout->code = 18;
114901dfbcc4SRoy Oursler 			pout->extra_bits = 138 - 11;
115001dfbcc4SRoy Oursler 			pout++;
115101dfbcc4SRoy Oursler 			run_len -= 138;
115201dfbcc4SRoy Oursler 			counts[18]++;
115301dfbcc4SRoy Oursler 		}
115401dfbcc4SRoy Oursler 		// 1 <= run_len <= 138
115501dfbcc4SRoy Oursler 		if (run_len > 10) {
115601dfbcc4SRoy Oursler 			pout->code = 18;
115701dfbcc4SRoy Oursler 			pout->extra_bits = run_len - 11;
115801dfbcc4SRoy Oursler 			pout++;
115901dfbcc4SRoy Oursler 			counts[18]++;
116001dfbcc4SRoy Oursler 		} else if (run_len > 2) {
116101dfbcc4SRoy Oursler 			pout->code = 17;
116201dfbcc4SRoy Oursler 			pout->extra_bits = run_len - 3;
116301dfbcc4SRoy Oursler 			pout++;
116401dfbcc4SRoy Oursler 			counts[17]++;
116501dfbcc4SRoy Oursler 		} else if (run_len == 1) {
116601dfbcc4SRoy Oursler 			pout->code = 0;
116701dfbcc4SRoy Oursler 			pout->extra_bits = 0;
116801dfbcc4SRoy Oursler 			pout++;
116901dfbcc4SRoy Oursler 			counts[0]++;
117001dfbcc4SRoy Oursler 		} else {
117101dfbcc4SRoy Oursler 			assert(run_len == 2);
117201dfbcc4SRoy Oursler 			pout[0].code = 0;
117301dfbcc4SRoy Oursler 			pout[0].extra_bits = 0;
117401dfbcc4SRoy Oursler 			pout[1].code = 0;
117501dfbcc4SRoy Oursler 			pout[1].extra_bits = 0;
117601dfbcc4SRoy Oursler 			pout += 2;
117701dfbcc4SRoy Oursler 			counts[0] += 2;
117801dfbcc4SRoy Oursler 		}
117901dfbcc4SRoy Oursler 	} else {
118001dfbcc4SRoy Oursler 		// last_len != 0
118101dfbcc4SRoy Oursler 		pout->code = last_len;
118201dfbcc4SRoy Oursler 		pout->extra_bits = 0;
118301dfbcc4SRoy Oursler 		pout++;
118401dfbcc4SRoy Oursler 		counts[last_len]++;
118501dfbcc4SRoy Oursler 		run_len--;
118601dfbcc4SRoy Oursler 		if (run_len != 0) {
118701dfbcc4SRoy Oursler 			while (run_len > 6) {
118801dfbcc4SRoy Oursler 				pout->code = 16;
118901dfbcc4SRoy Oursler 				pout->extra_bits = 6 - 3;
119001dfbcc4SRoy Oursler 				pout++;
119101dfbcc4SRoy Oursler 				run_len -= 6;
119201dfbcc4SRoy Oursler 				counts[16]++;
119301dfbcc4SRoy Oursler 			}
119401dfbcc4SRoy Oursler 			// 1 <= run_len <= 6
119501dfbcc4SRoy Oursler 			switch (run_len) {
119601dfbcc4SRoy Oursler 			case 1:
119701dfbcc4SRoy Oursler 				pout->code = last_len;
119801dfbcc4SRoy Oursler 				pout->extra_bits = 0;
119901dfbcc4SRoy Oursler 				pout++;
120001dfbcc4SRoy Oursler 				counts[last_len]++;
120101dfbcc4SRoy Oursler 				break;
120201dfbcc4SRoy Oursler 			case 2:
120301dfbcc4SRoy Oursler 				pout[0].code = last_len;
120401dfbcc4SRoy Oursler 				pout[0].extra_bits = 0;
120501dfbcc4SRoy Oursler 				pout[1].code = last_len;
120601dfbcc4SRoy Oursler 				pout[1].extra_bits = 0;
120701dfbcc4SRoy Oursler 				pout += 2;
120801dfbcc4SRoy Oursler 				counts[last_len] += 2;
120901dfbcc4SRoy Oursler 				break;
121001dfbcc4SRoy Oursler 			default:	// 3...6
121101dfbcc4SRoy Oursler 				pout->code = 16;
121201dfbcc4SRoy Oursler 				pout->extra_bits = run_len - 3;
121301dfbcc4SRoy Oursler 				pout++;
121401dfbcc4SRoy Oursler 				counts[16]++;
121501dfbcc4SRoy Oursler 			}
121601dfbcc4SRoy Oursler 		}
121701dfbcc4SRoy Oursler 	}
121801dfbcc4SRoy Oursler 	return pout;
1219660f49b0SGreg Tucker }
1220660f49b0SGreg Tucker 
122101dfbcc4SRoy Oursler // convert codes into run-length symbols, write symbols into OUT
122201dfbcc4SRoy Oursler // generate histogram into COUNTS (assumed to be initialized to 0)
122301dfbcc4SRoy Oursler // Format of OUT:
122401dfbcc4SRoy Oursler // 4:0  code (0...18)
122501dfbcc4SRoy Oursler // 15:8 Extra bits (0...127)
122601dfbcc4SRoy Oursler // returns number of symbols in out
122701dfbcc4SRoy Oursler static inline uint32_t rl_encode(uint16_t * codes, uint32_t num_codes, uint64_t * counts,
122801dfbcc4SRoy Oursler 				 struct rl_code *out)
1229660f49b0SGreg Tucker {
123001dfbcc4SRoy Oursler 	uint32_t i, run_len;
123101dfbcc4SRoy Oursler 	uint16_t last_len, len;
123201dfbcc4SRoy Oursler 	struct rl_code *pout;
1233660f49b0SGreg Tucker 
123401dfbcc4SRoy Oursler 	pout = out;
123501dfbcc4SRoy Oursler 	last_len = codes[0];
123601dfbcc4SRoy Oursler 	run_len = 1;
123701dfbcc4SRoy Oursler 	for (i = 1; i < num_codes; i++) {
123801dfbcc4SRoy Oursler 		len = codes[i];
123901dfbcc4SRoy Oursler 		if (len == last_len) {
124001dfbcc4SRoy Oursler 			run_len++;
124101dfbcc4SRoy Oursler 			continue;
1242660f49b0SGreg Tucker 		}
124301dfbcc4SRoy Oursler 		pout = write_rl(pout, last_len, run_len, counts);
124401dfbcc4SRoy Oursler 		last_len = len;
124501dfbcc4SRoy Oursler 		run_len = 1;
1246660f49b0SGreg Tucker 	}
124701dfbcc4SRoy Oursler 	pout = write_rl(pout, last_len, run_len, counts);
1248660f49b0SGreg Tucker 
124901dfbcc4SRoy Oursler 	return (uint32_t) (pout - out);
1250660f49b0SGreg Tucker }
1251660f49b0SGreg Tucker 
1252660f49b0SGreg Tucker void create_code_tables(uint16_t * code_table, uint8_t * code_length_table, uint32_t length,
1253660f49b0SGreg Tucker 			struct huff_code *hufftable)
1254660f49b0SGreg Tucker {
1255660f49b0SGreg Tucker 	int i;
1256660f49b0SGreg Tucker 	for (i = 0; i < length; i++) {
1257660f49b0SGreg Tucker 		code_table[i] = hufftable[i].code;
1258660f49b0SGreg Tucker 		code_length_table[i] = hufftable[i].length;
1259660f49b0SGreg Tucker 	}
1260660f49b0SGreg Tucker }
1261660f49b0SGreg Tucker 
1262660f49b0SGreg Tucker void create_packed_len_table(uint32_t * packed_table, struct huff_code *lit_len_hufftable)
1263660f49b0SGreg Tucker {
1264660f49b0SGreg Tucker 	int i, count = 0;
1265660f49b0SGreg Tucker 	uint16_t extra_bits;
1266660f49b0SGreg Tucker 	uint16_t extra_bits_count = 0;
1267660f49b0SGreg Tucker 
1268660f49b0SGreg Tucker 	/* Gain extra bits is the next place where the number of extra bits in
1269660f49b0SGreg Tucker 	 * lenght codes increases. */
1270660f49b0SGreg Tucker 	uint16_t gain_extra_bits = LEN_EXTRA_BITS_START;
1271660f49b0SGreg Tucker 
1272660f49b0SGreg Tucker 	for (i = 257; i < LIT_LEN - 1; i++) {
1273660f49b0SGreg Tucker 		for (extra_bits = 0; extra_bits < (1 << extra_bits_count); extra_bits++) {
1274660f49b0SGreg Tucker 			if (count > 254)
1275660f49b0SGreg Tucker 				break;
1276660f49b0SGreg Tucker 			packed_table[count++] =
1277660f49b0SGreg Tucker 			    (extra_bits << (lit_len_hufftable[i].length + LENGTH_BITS)) |
1278660f49b0SGreg Tucker 			    (lit_len_hufftable[i].code << LENGTH_BITS) |
1279660f49b0SGreg Tucker 			    (lit_len_hufftable[i].length + extra_bits_count);
1280660f49b0SGreg Tucker 		}
1281660f49b0SGreg Tucker 
1282660f49b0SGreg Tucker 		if (i == gain_extra_bits) {
1283660f49b0SGreg Tucker 			gain_extra_bits += LEN_EXTRA_BITS_INTERVAL;
1284660f49b0SGreg Tucker 			extra_bits_count += 1;
1285660f49b0SGreg Tucker 		}
1286660f49b0SGreg Tucker 	}
1287660f49b0SGreg Tucker 
1288660f49b0SGreg Tucker 	packed_table[count] = (lit_len_hufftable[LIT_LEN - 1].code << LENGTH_BITS) |
1289660f49b0SGreg Tucker 	    (lit_len_hufftable[LIT_LEN - 1].length);
1290660f49b0SGreg Tucker }
1291660f49b0SGreg Tucker 
1292660f49b0SGreg Tucker void create_packed_dist_table(uint32_t * packed_table, uint32_t length,
1293660f49b0SGreg Tucker 			      struct huff_code *dist_hufftable)
1294660f49b0SGreg Tucker {
1295660f49b0SGreg Tucker 	int i, count = 0;
1296660f49b0SGreg Tucker 	uint16_t extra_bits;
1297660f49b0SGreg Tucker 	uint16_t extra_bits_count = 0;
1298660f49b0SGreg Tucker 
1299660f49b0SGreg Tucker 	/* Gain extra bits is the next place where the number of extra bits in
1300660f49b0SGreg Tucker 	 * distance codes increases. */
1301660f49b0SGreg Tucker 	uint16_t gain_extra_bits = DIST_EXTRA_BITS_START;
1302660f49b0SGreg Tucker 
1303660f49b0SGreg Tucker 	for (i = 0; i < DIST_LEN; i++) {
1304660f49b0SGreg Tucker 		for (extra_bits = 0; extra_bits < (1 << extra_bits_count); extra_bits++) {
1305660f49b0SGreg Tucker 			if (count >= length)
1306660f49b0SGreg Tucker 				return;
1307660f49b0SGreg Tucker 
1308660f49b0SGreg Tucker 			packed_table[count++] =
1309660f49b0SGreg Tucker 			    (extra_bits << (dist_hufftable[i].length + LENGTH_BITS)) |
1310660f49b0SGreg Tucker 			    (dist_hufftable[i].code << LENGTH_BITS) |
1311660f49b0SGreg Tucker 			    (dist_hufftable[i].length + extra_bits_count);
1312660f49b0SGreg Tucker 
1313660f49b0SGreg Tucker 		}
1314660f49b0SGreg Tucker 
1315660f49b0SGreg Tucker 		if (i == gain_extra_bits) {
1316660f49b0SGreg Tucker 			gain_extra_bits += DIST_EXTRA_BITS_INTERVAL;
1317660f49b0SGreg Tucker 			extra_bits_count += 1;
1318660f49b0SGreg Tucker 		}
1319660f49b0SGreg Tucker 	}
1320660f49b0SGreg Tucker }
1321660f49b0SGreg Tucker 
1322660f49b0SGreg Tucker int are_hufftables_useable(struct huff_code *lit_len_hufftable,
1323660f49b0SGreg Tucker 			   struct huff_code *dist_hufftable)
1324660f49b0SGreg Tucker {
1325660f49b0SGreg Tucker 	int max_lit_code_len = 0, max_len_code_len = 0, max_dist_code_len = 0;
1326660f49b0SGreg Tucker 	int dist_extra_bits = 0, len_extra_bits = 0;
1327660f49b0SGreg Tucker 	int gain_dist_extra_bits = DIST_EXTRA_BITS_START;
1328660f49b0SGreg Tucker 	int gain_len_extra_bits = LEN_EXTRA_BITS_START;
1329660f49b0SGreg Tucker 	int max_code_len;
1330660f49b0SGreg Tucker 	int i;
1331660f49b0SGreg Tucker 
1332660f49b0SGreg Tucker 	for (i = 0; i < LIT_LEN; i++)
1333660f49b0SGreg Tucker 		if (lit_len_hufftable[i].length > max_lit_code_len)
1334660f49b0SGreg Tucker 			max_lit_code_len = lit_len_hufftable[i].length;
1335660f49b0SGreg Tucker 
1336660f49b0SGreg Tucker 	for (i = 257; i < LIT_LEN - 1; i++) {
1337660f49b0SGreg Tucker 		if (lit_len_hufftable[i].length + len_extra_bits > max_len_code_len)
1338660f49b0SGreg Tucker 			max_len_code_len = lit_len_hufftable[i].length + len_extra_bits;
1339660f49b0SGreg Tucker 
1340660f49b0SGreg Tucker 		if (i == gain_len_extra_bits) {
1341660f49b0SGreg Tucker 			gain_len_extra_bits += LEN_EXTRA_BITS_INTERVAL;
1342660f49b0SGreg Tucker 			len_extra_bits += 1;
1343660f49b0SGreg Tucker 		}
1344660f49b0SGreg Tucker 	}
1345660f49b0SGreg Tucker 
1346660f49b0SGreg Tucker 	for (i = 0; i < DIST_LEN; i++) {
1347660f49b0SGreg Tucker 		if (dist_hufftable[i].length + dist_extra_bits > max_dist_code_len)
1348660f49b0SGreg Tucker 			max_dist_code_len = dist_hufftable[i].length + dist_extra_bits;
1349660f49b0SGreg Tucker 
1350660f49b0SGreg Tucker 		if (i == gain_dist_extra_bits) {
1351660f49b0SGreg Tucker 			gain_dist_extra_bits += DIST_EXTRA_BITS_INTERVAL;
1352660f49b0SGreg Tucker 			dist_extra_bits += 1;
1353660f49b0SGreg Tucker 		}
1354660f49b0SGreg Tucker 	}
1355660f49b0SGreg Tucker 
1356660f49b0SGreg Tucker 	max_code_len = max_lit_code_len + max_len_code_len + max_dist_code_len;
1357660f49b0SGreg Tucker 
1358660f49b0SGreg Tucker 	/* Some versions of igzip can write upto one literal, one length and one
1359660f49b0SGreg Tucker 	 * distance code at the same time. This checks to make sure that is
1360660f49b0SGreg Tucker 	 * always writeable in bitbuf*/
1361660f49b0SGreg Tucker 	return (max_code_len > MAX_BITBUF_BIT_WRITE);
1362660f49b0SGreg Tucker }
1363660f49b0SGreg Tucker 
1364660f49b0SGreg Tucker int isal_create_hufftables(struct isal_hufftables *hufftables,
1365660f49b0SGreg Tucker 			   struct isal_huff_histogram *histogram)
1366660f49b0SGreg Tucker {
1367660f49b0SGreg Tucker 	struct huff_code lit_huff_table[LIT_LEN], dist_huff_table[DIST_LEN];
1368660f49b0SGreg Tucker 	uint64_t bit_count;
136988f95d85SRoy Oursler 	int max_dist = convert_dist_to_dist_sym(IGZIP_HIST_SIZE);
137001dfbcc4SRoy Oursler 	struct heap_tree heap_space;
137101dfbcc4SRoy Oursler 	uint32_t heap_size;
137201dfbcc4SRoy Oursler 	uint32_t code_len_count[MAX_HUFF_TREE_DEPTH + 1];
137301dfbcc4SRoy Oursler 	struct BitBuf2 header_bitbuf;
137401dfbcc4SRoy Oursler 	uint32_t max_lit_len_sym;
137501dfbcc4SRoy Oursler 	uint32_t max_dist_sym;
137601dfbcc4SRoy Oursler 	uint32_t hlit, hdist, i;
137701dfbcc4SRoy Oursler 	uint16_t combined_table[LIT_LEN + DIST_LEN];
137801dfbcc4SRoy Oursler 	uint64_t count_histogram[HUFF_LEN];
137901dfbcc4SRoy Oursler 	struct rl_code rl_huff[LIT_LEN + DIST_LEN];
138001dfbcc4SRoy Oursler 	uint32_t rl_huff_len;
1381660f49b0SGreg Tucker 
1382660f49b0SGreg Tucker 	uint32_t *dist_table = hufftables->dist_table;
1383660f49b0SGreg Tucker 	uint32_t *len_table = hufftables->len_table;
1384660f49b0SGreg Tucker 	uint16_t *lit_table = hufftables->lit_table;
1385660f49b0SGreg Tucker 	uint16_t *dcodes = hufftables->dcodes;
1386660f49b0SGreg Tucker 	uint8_t *lit_table_sizes = hufftables->lit_table_sizes;
1387660f49b0SGreg Tucker 	uint8_t *dcodes_sizes = hufftables->dcodes_sizes;
1388660f49b0SGreg Tucker 	uint8_t *deflate_hdr = hufftables->deflate_hdr;
1389660f49b0SGreg Tucker 	uint64_t *lit_len_histogram = histogram->lit_len_histogram;
1390660f49b0SGreg Tucker 	uint64_t *dist_histogram = histogram->dist_histogram;
1391660f49b0SGreg Tucker 
1392660f49b0SGreg Tucker 	memset(hufftables, 0, sizeof(struct isal_hufftables));
1393660f49b0SGreg Tucker 
139401dfbcc4SRoy Oursler 	heap_size = init_heap64_complete(&heap_space, lit_len_histogram, LIT_LEN);
139501dfbcc4SRoy Oursler 	gen_huff_code_lens(&heap_space, heap_size, code_len_count,
139601dfbcc4SRoy Oursler 			   (struct huff_code *)lit_huff_table, LIT_LEN, MAX_DEFLATE_CODE_LEN);
139701dfbcc4SRoy Oursler 	max_lit_len_sym = set_huff_codes(lit_huff_table, LIT_LEN, code_len_count);
1398660f49b0SGreg Tucker 
139901dfbcc4SRoy Oursler 	heap_size = init_heap64_complete(&heap_space, dist_histogram, DIST_LEN);
140001dfbcc4SRoy Oursler 	gen_huff_code_lens(&heap_space, heap_size, code_len_count,
140101dfbcc4SRoy Oursler 			   (struct huff_code *)dist_huff_table, max_dist,
140201dfbcc4SRoy Oursler 			   MAX_DEFLATE_CODE_LEN);
140301dfbcc4SRoy Oursler 	max_dist_sym = set_huff_codes(dist_huff_table, DIST_LEN, code_len_count);
1404660f49b0SGreg Tucker 
1405660f49b0SGreg Tucker 	if (are_hufftables_useable(lit_huff_table, dist_huff_table)) {
140601dfbcc4SRoy Oursler 		heap_size = init_heap64_complete(&heap_space, lit_len_histogram, LIT_LEN);
140701dfbcc4SRoy Oursler 		gen_huff_code_lens(&heap_space, heap_size, code_len_count,
140801dfbcc4SRoy Oursler 				   (struct huff_code *)lit_huff_table, LIT_LEN,
140901dfbcc4SRoy Oursler 				   MAX_SAFE_LIT_CODE_LEN);
141001dfbcc4SRoy Oursler 		max_lit_len_sym = set_huff_codes(lit_huff_table, LIT_LEN, code_len_count);
1411660f49b0SGreg Tucker 
141201dfbcc4SRoy Oursler 		heap_size = init_heap64_complete(&heap_space, dist_histogram, DIST_LEN);
141301dfbcc4SRoy Oursler 		gen_huff_code_lens(&heap_space, heap_size, code_len_count,
141401dfbcc4SRoy Oursler 				   (struct huff_code *)dist_huff_table, max_dist,
141501dfbcc4SRoy Oursler 				   MAX_SAFE_DIST_CODE_LEN);
141601dfbcc4SRoy Oursler 		max_dist_sym = set_huff_codes(dist_huff_table, DIST_LEN, code_len_count);
1417660f49b0SGreg Tucker 
1418660f49b0SGreg Tucker 	}
1419660f49b0SGreg Tucker 
1420660f49b0SGreg Tucker 	create_code_tables(dcodes, dcodes_sizes, DIST_LEN - DCODE_OFFSET,
1421660f49b0SGreg Tucker 			   dist_huff_table + DCODE_OFFSET);
1422660f49b0SGreg Tucker 
142388f95d85SRoy Oursler 	create_code_tables(lit_table, lit_table_sizes, IGZIP_LIT_TABLE_SIZE, lit_huff_table);
1424660f49b0SGreg Tucker 
1425660f49b0SGreg Tucker 	create_packed_len_table(len_table, lit_huff_table);
142688f95d85SRoy Oursler 	create_packed_dist_table(dist_table, IGZIP_DIST_TABLE_SIZE, dist_huff_table);
1427660f49b0SGreg Tucker 
142801dfbcc4SRoy Oursler 	set_buf(&header_bitbuf, deflate_hdr, sizeof(deflate_hdr));
142901dfbcc4SRoy Oursler 	init(&header_bitbuf);
143001dfbcc4SRoy Oursler 
143101dfbcc4SRoy Oursler 	hlit = max_lit_len_sym - 256;
143201dfbcc4SRoy Oursler 	hdist = max_dist_sym;
143301dfbcc4SRoy Oursler 
143401dfbcc4SRoy Oursler 	/* Run length encode the length and distance huffman codes */
143501dfbcc4SRoy Oursler 	memset(count_histogram, 0, sizeof(count_histogram));
143601dfbcc4SRoy Oursler 	for (i = 0; i < 257 + hlit; i++)
143701dfbcc4SRoy Oursler 		combined_table[i] = lit_huff_table[i].length;
143801dfbcc4SRoy Oursler 	for (i = 0; i < 1 + hdist; i++)
143901dfbcc4SRoy Oursler 		combined_table[i + hlit + 257] = dist_huff_table[i].length;
144001dfbcc4SRoy Oursler 	rl_huff_len =
144101dfbcc4SRoy Oursler 	    rl_encode(combined_table, hlit + 257 + hdist + 1, count_histogram, rl_huff);
144201dfbcc4SRoy Oursler 
144301dfbcc4SRoy Oursler 	/* Create header */
1444660f49b0SGreg Tucker 	bit_count =
144501dfbcc4SRoy Oursler 	    create_header(&header_bitbuf, rl_huff, rl_huff_len,
144601dfbcc4SRoy Oursler 			  count_histogram, hlit, hdist, LAST_BLOCK);
144701dfbcc4SRoy Oursler 	flush(&header_bitbuf);
1448660f49b0SGreg Tucker 
1449660f49b0SGreg Tucker 	hufftables->deflate_hdr_count = bit_count / 8;
1450660f49b0SGreg Tucker 	hufftables->deflate_hdr_extra_bits = bit_count % 8;
1451660f49b0SGreg Tucker 
1452660f49b0SGreg Tucker 	return 0;
1453660f49b0SGreg Tucker }
1454660f49b0SGreg Tucker 
1455660f49b0SGreg Tucker int isal_create_hufftables_subset(struct isal_hufftables *hufftables,
1456660f49b0SGreg Tucker 				  struct isal_huff_histogram *histogram)
1457660f49b0SGreg Tucker {
1458660f49b0SGreg Tucker 	struct huff_code lit_huff_table[LIT_LEN], dist_huff_table[DIST_LEN];
1459660f49b0SGreg Tucker 	uint64_t bit_count;
146001dfbcc4SRoy Oursler 	int max_dist = convert_dist_to_dist_sym(IGZIP_HIST_SIZE);
146101dfbcc4SRoy Oursler 	struct heap_tree heap_space;
146201dfbcc4SRoy Oursler 	uint32_t heap_size;
146301dfbcc4SRoy Oursler 	uint32_t code_len_count[MAX_HUFF_TREE_DEPTH + 1];
146401dfbcc4SRoy Oursler 	struct BitBuf2 header_bitbuf;
146501dfbcc4SRoy Oursler 	uint32_t max_lit_len_sym;
146601dfbcc4SRoy Oursler 	uint32_t max_dist_sym;
146701dfbcc4SRoy Oursler 	uint32_t hlit, hdist, i;
146801dfbcc4SRoy Oursler 	uint16_t combined_table[LIT_LEN + DIST_LEN];
146901dfbcc4SRoy Oursler 	uint64_t count_histogram[HUFF_LEN];
147001dfbcc4SRoy Oursler 	struct rl_code rl_huff[LIT_LEN + DIST_LEN];
147101dfbcc4SRoy Oursler 	uint32_t rl_huff_len;
1472660f49b0SGreg Tucker 
1473660f49b0SGreg Tucker 	uint32_t *dist_table = hufftables->dist_table;
1474660f49b0SGreg Tucker 	uint32_t *len_table = hufftables->len_table;
1475660f49b0SGreg Tucker 	uint16_t *lit_table = hufftables->lit_table;
1476660f49b0SGreg Tucker 	uint16_t *dcodes = hufftables->dcodes;
1477660f49b0SGreg Tucker 	uint8_t *lit_table_sizes = hufftables->lit_table_sizes;
1478660f49b0SGreg Tucker 	uint8_t *dcodes_sizes = hufftables->dcodes_sizes;
1479660f49b0SGreg Tucker 	uint8_t *deflate_hdr = hufftables->deflate_hdr;
1480660f49b0SGreg Tucker 	uint64_t *lit_len_histogram = histogram->lit_len_histogram;
1481660f49b0SGreg Tucker 	uint64_t *dist_histogram = histogram->dist_histogram;
1482660f49b0SGreg Tucker 
1483660f49b0SGreg Tucker 	memset(hufftables, 0, sizeof(struct isal_hufftables));
1484660f49b0SGreg Tucker 
1485*e79c57c7SRoy Oursler 	heap_size =
1486*e79c57c7SRoy Oursler 	    init_heap64_semi_complete(&heap_space, lit_len_histogram, LIT_LEN,
1487*e79c57c7SRoy Oursler 				      ISAL_DEF_LIT_SYMBOLS);
148801dfbcc4SRoy Oursler 	gen_huff_code_lens(&heap_space, heap_size, code_len_count,
148901dfbcc4SRoy Oursler 			   (struct huff_code *)lit_huff_table, LIT_LEN, MAX_DEFLATE_CODE_LEN);
149001dfbcc4SRoy Oursler 	max_lit_len_sym = set_huff_codes(lit_huff_table, LIT_LEN, code_len_count);
1491660f49b0SGreg Tucker 
149201dfbcc4SRoy Oursler 	heap_size = init_heap64_complete(&heap_space, dist_histogram, DIST_LEN);
149301dfbcc4SRoy Oursler 	gen_huff_code_lens(&heap_space, heap_size, code_len_count,
149401dfbcc4SRoy Oursler 			   (struct huff_code *)dist_huff_table, max_dist,
149501dfbcc4SRoy Oursler 			   MAX_DEFLATE_CODE_LEN);
149601dfbcc4SRoy Oursler 	max_dist_sym = set_huff_codes(dist_huff_table, DIST_LEN, code_len_count);
1497660f49b0SGreg Tucker 
1498660f49b0SGreg Tucker 	if (are_hufftables_useable(lit_huff_table, dist_huff_table)) {
149901dfbcc4SRoy Oursler 		heap_size = init_heap64_complete(&heap_space, lit_len_histogram, LIT_LEN);
150001dfbcc4SRoy Oursler 		gen_huff_code_lens(&heap_space, heap_size, code_len_count,
150101dfbcc4SRoy Oursler 				   (struct huff_code *)lit_huff_table, LIT_LEN,
150201dfbcc4SRoy Oursler 				   MAX_SAFE_LIT_CODE_LEN);
150301dfbcc4SRoy Oursler 		max_lit_len_sym = set_huff_codes(lit_huff_table, LIT_LEN, code_len_count);
1504660f49b0SGreg Tucker 
150501dfbcc4SRoy Oursler 		heap_size = init_heap64_complete(&heap_space, dist_histogram, DIST_LEN);
150601dfbcc4SRoy Oursler 		gen_huff_code_lens(&heap_space, heap_size, code_len_count,
150701dfbcc4SRoy Oursler 				   (struct huff_code *)dist_huff_table, max_dist,
150801dfbcc4SRoy Oursler 				   MAX_SAFE_DIST_CODE_LEN);
150901dfbcc4SRoy Oursler 		max_dist_sym = set_huff_codes(dist_huff_table, DIST_LEN, code_len_count);
1510660f49b0SGreg Tucker 
1511660f49b0SGreg Tucker 	}
1512660f49b0SGreg Tucker 
1513660f49b0SGreg Tucker 	create_code_tables(dcodes, dcodes_sizes, DIST_LEN - DCODE_OFFSET,
1514660f49b0SGreg Tucker 			   dist_huff_table + DCODE_OFFSET);
1515660f49b0SGreg Tucker 
151688f95d85SRoy Oursler 	create_code_tables(lit_table, lit_table_sizes, IGZIP_LIT_TABLE_SIZE, lit_huff_table);
1517660f49b0SGreg Tucker 
1518660f49b0SGreg Tucker 	create_packed_len_table(len_table, lit_huff_table);
151988f95d85SRoy Oursler 	create_packed_dist_table(dist_table, IGZIP_DIST_TABLE_SIZE, dist_huff_table);
1520660f49b0SGreg Tucker 
152101dfbcc4SRoy Oursler 	set_buf(&header_bitbuf, deflate_hdr, sizeof(deflate_hdr));
152201dfbcc4SRoy Oursler 	init(&header_bitbuf);
152301dfbcc4SRoy Oursler 
152401dfbcc4SRoy Oursler 	hlit = max_lit_len_sym - 256;
152501dfbcc4SRoy Oursler 	hdist = max_dist_sym;
152601dfbcc4SRoy Oursler 
152701dfbcc4SRoy Oursler 	/* Run length encode the length and distance huffman codes */
152801dfbcc4SRoy Oursler 	memset(count_histogram, 0, sizeof(count_histogram));
152901dfbcc4SRoy Oursler 	for (i = 0; i < 257 + hlit; i++)
153001dfbcc4SRoy Oursler 		combined_table[i] = lit_huff_table[i].length;
153101dfbcc4SRoy Oursler 	for (i = 0; i < 1 + hdist; i++)
153201dfbcc4SRoy Oursler 		combined_table[i + hlit + 257] = dist_huff_table[i].length;
153301dfbcc4SRoy Oursler 	rl_huff_len =
153401dfbcc4SRoy Oursler 	    rl_encode(combined_table, hlit + 257 + hdist + 1, count_histogram, rl_huff);
153501dfbcc4SRoy Oursler 
153601dfbcc4SRoy Oursler 	/* Create header */
1537660f49b0SGreg Tucker 	bit_count =
153801dfbcc4SRoy Oursler 	    create_header(&header_bitbuf, rl_huff, rl_huff_len,
153901dfbcc4SRoy Oursler 			  count_histogram, hlit, hdist, LAST_BLOCK);
154001dfbcc4SRoy Oursler 	flush(&header_bitbuf);
1541660f49b0SGreg Tucker 
1542660f49b0SGreg Tucker 	hufftables->deflate_hdr_count = bit_count / 8;
1543660f49b0SGreg Tucker 	hufftables->deflate_hdr_extra_bits = bit_count % 8;
1544660f49b0SGreg Tucker 
1545660f49b0SGreg Tucker 	return 0;
1546660f49b0SGreg Tucker }
154701dfbcc4SRoy Oursler 
154801dfbcc4SRoy Oursler void expand_hufftables_icf(struct hufftables_icf *hufftables)
154901dfbcc4SRoy Oursler {
155001dfbcc4SRoy Oursler 	uint32_t i, eb, j, k, len, code;
155101dfbcc4SRoy Oursler 	struct huff_code orig[21], *p_code;
155201dfbcc4SRoy Oursler 	struct huff_code *lit_len_codes = hufftables->lit_len_table;
155301dfbcc4SRoy Oursler 	struct huff_code *dist_codes = hufftables->dist_table;
155401dfbcc4SRoy Oursler 
155501dfbcc4SRoy Oursler 	for (i = 0; i < 21; i++)
155601dfbcc4SRoy Oursler 		orig[i] = lit_len_codes[i + 265];
155701dfbcc4SRoy Oursler 
155801dfbcc4SRoy Oursler 	p_code = &lit_len_codes[265];
155901dfbcc4SRoy Oursler 
156001dfbcc4SRoy Oursler 	i = 0;
156101dfbcc4SRoy Oursler 	for (eb = 1; eb < 6; eb++) {
156201dfbcc4SRoy Oursler 		for (k = 0; k < 4; k++) {
156301dfbcc4SRoy Oursler 			len = orig[i].length;
156401dfbcc4SRoy Oursler 			code = orig[i++].code;
156501dfbcc4SRoy Oursler 			for (j = 0; j < (1u << eb); j++) {
156601dfbcc4SRoy Oursler 				p_code->code_and_extra = code | (j << len);
156701dfbcc4SRoy Oursler 				p_code->length = len + eb;
156801dfbcc4SRoy Oursler 				p_code++;
156901dfbcc4SRoy Oursler 			}
157001dfbcc4SRoy Oursler 		}		// end for k
157101dfbcc4SRoy Oursler 	}			// end for eb
157201dfbcc4SRoy Oursler 	// fix up last record
157301dfbcc4SRoy Oursler 	p_code[-1] = orig[i];
157401dfbcc4SRoy Oursler 
157501dfbcc4SRoy Oursler 	dist_codes[DIST_LEN].code_and_extra = 0;
157601dfbcc4SRoy Oursler 	dist_codes[DIST_LEN].length = 0;
157701dfbcc4SRoy Oursler }
157801dfbcc4SRoy Oursler 
157964143a74SRoy Oursler uint64_t
158001dfbcc4SRoy Oursler create_hufftables_icf(struct BitBuf2 *bb, struct hufftables_icf *hufftables,
158101dfbcc4SRoy Oursler 		      struct isal_mod_hist *hist, uint32_t end_of_block)
158201dfbcc4SRoy Oursler {
158301dfbcc4SRoy Oursler 	uint32_t bl_count[MAX_DEFLATE_CODE_LEN + 1];
158401dfbcc4SRoy Oursler 	uint32_t max_ll_code, max_d_code;
158501dfbcc4SRoy Oursler 	struct heap_tree heap_space;
158601dfbcc4SRoy Oursler 	uint32_t heap_size;
158701dfbcc4SRoy Oursler 	struct rl_code cl_tokens[LIT_LEN + DIST_LEN];
158801dfbcc4SRoy Oursler 	uint32_t num_cl_tokens;
158901dfbcc4SRoy Oursler 	uint64_t cl_counts[CODE_LEN_CODES];
159001dfbcc4SRoy Oursler 	uint16_t combined_table[LIT_LEN + DIST_LEN];
159101dfbcc4SRoy Oursler 	int i;
15929992cc19SRoy Oursler 	uint64_t compressed_len = 0;
15939992cc19SRoy Oursler 	uint64_t static_compressed_len = 3;	/* The static header size */
15949992cc19SRoy Oursler 	struct BitBuf2 bb_tmp;
159501dfbcc4SRoy Oursler 
159601dfbcc4SRoy Oursler 	struct huff_code *ll_codes = hufftables->lit_len_table;
159701dfbcc4SRoy Oursler 	struct huff_code *d_codes = hufftables->dist_table;
1598e38ed4b5SRoy Oursler 	uint32_t *ll_hist = hist->ll_hist;
1599e38ed4b5SRoy Oursler 	uint32_t *d_hist = hist->d_hist;
16009992cc19SRoy Oursler 	struct huff_code *static_ll_codes = static_hufftables.lit_len_table;
16019992cc19SRoy Oursler 	struct huff_code *static_d_codes = static_hufftables.dist_table;
16029992cc19SRoy Oursler 
16039992cc19SRoy Oursler 	memcpy(&bb_tmp, bb, sizeof(struct BitBuf2));
160401dfbcc4SRoy Oursler 
160501dfbcc4SRoy Oursler 	flatten_ll(hist->ll_hist);
160601dfbcc4SRoy Oursler 
160701dfbcc4SRoy Oursler 	// make sure EOB is present
160801dfbcc4SRoy Oursler 	if (ll_hist[256] == 0)
160901dfbcc4SRoy Oursler 		ll_hist[256] = 1;
161001dfbcc4SRoy Oursler 
1611e38ed4b5SRoy Oursler 	heap_size = init_heap32(&heap_space, ll_hist, LIT_LEN);
161201dfbcc4SRoy Oursler 	gen_huff_code_lens(&heap_space, heap_size, bl_count,
161301dfbcc4SRoy Oursler 			   ll_codes, LIT_LEN, MAX_DEFLATE_CODE_LEN);
161401dfbcc4SRoy Oursler 	max_ll_code = set_huff_codes(ll_codes, LIT_LEN, bl_count);
161501dfbcc4SRoy Oursler 
1616e38ed4b5SRoy Oursler 	heap_size = init_heap32(&heap_space, d_hist, DIST_LEN);
161701dfbcc4SRoy Oursler 	gen_huff_code_lens(&heap_space, heap_size, bl_count, d_codes,
161801dfbcc4SRoy Oursler 			   DIST_LEN, MAX_DEFLATE_CODE_LEN);
161901dfbcc4SRoy Oursler 	max_d_code = set_dist_huff_codes(d_codes, bl_count);
162001dfbcc4SRoy Oursler 
162101dfbcc4SRoy Oursler 	assert(max_ll_code >= 256);	// must be EOB code
162201dfbcc4SRoy Oursler 	assert(max_d_code != 0);
162301dfbcc4SRoy Oursler 
162401dfbcc4SRoy Oursler 	/* Run length encode the length and distance huffman codes */
162501dfbcc4SRoy Oursler 	memset(cl_counts, 0, sizeof(cl_counts));
16269992cc19SRoy Oursler 
16279992cc19SRoy Oursler 	for (i = 0; i <= 256; i++) {
162801dfbcc4SRoy Oursler 		combined_table[i] = ll_codes[i].length;
16299992cc19SRoy Oursler 		compressed_len += ll_codes[i].length * ll_hist[i];
16309992cc19SRoy Oursler 		static_compressed_len += static_ll_codes[i].length * ll_hist[i];
16319992cc19SRoy Oursler 	}
16329992cc19SRoy Oursler 
16339992cc19SRoy Oursler 	for (; i < max_ll_code + 1; i++) {
16349992cc19SRoy Oursler 		combined_table[i] = ll_codes[i].length;
16359992cc19SRoy Oursler 		compressed_len +=
16369992cc19SRoy Oursler 		    (ll_codes[i].length + len_code_extra_bits[i - 257]) * ll_hist[i];
16379992cc19SRoy Oursler 		static_compressed_len +=
16389992cc19SRoy Oursler 		    (static_ll_codes[i].length + len_code_extra_bits[i - 257]) * ll_hist[i];
16399992cc19SRoy Oursler 	}
16409992cc19SRoy Oursler 
16419992cc19SRoy Oursler 	for (i = 0; i < max_d_code + 1; i++) {
164201dfbcc4SRoy Oursler 		combined_table[i + max_ll_code + 1] = d_codes[i].length;
16439992cc19SRoy Oursler 		compressed_len += (d_codes[i].length + dist_code_extra_bits[i]) * d_hist[i];
16449992cc19SRoy Oursler 		static_compressed_len +=
16459992cc19SRoy Oursler 		    (static_d_codes[i].length + dist_code_extra_bits[i]) * d_hist[i];
16469992cc19SRoy Oursler 	}
164701dfbcc4SRoy Oursler 
164864143a74SRoy Oursler 	if (static_compressed_len > compressed_len) {
164964143a74SRoy Oursler 		num_cl_tokens = rl_encode(combined_table, max_ll_code + max_d_code + 2,
165064143a74SRoy Oursler 					  cl_counts, cl_tokens);
165101dfbcc4SRoy Oursler 
165201dfbcc4SRoy Oursler 		/* Create header */
165364143a74SRoy Oursler 		create_header(bb, cl_tokens, num_cl_tokens, cl_counts, max_ll_code - 256,
165464143a74SRoy Oursler 			      max_d_code, end_of_block);
16559992cc19SRoy Oursler 		compressed_len += 8 * buffer_used(bb) + bb->m_bit_count;
165664143a74SRoy Oursler 	}
165701dfbcc4SRoy Oursler 
165864143a74SRoy Oursler 	/* Substitute in static block since it creates smaller block */
165964143a74SRoy Oursler 	if (static_compressed_len <= compressed_len) {
16609992cc19SRoy Oursler 		memcpy(hufftables, &static_hufftables, sizeof(struct hufftables_icf));
16619992cc19SRoy Oursler 		memcpy(bb, &bb_tmp, sizeof(struct BitBuf2));
16629992cc19SRoy Oursler 		end_of_block = end_of_block ? 1 : 0;
16639992cc19SRoy Oursler 		write_bits(bb, 0x2 | end_of_block, 3);
166464143a74SRoy Oursler 		compressed_len = static_compressed_len;
16659992cc19SRoy Oursler 	}
166664143a74SRoy Oursler 
166764143a74SRoy Oursler 	expand_hufftables_icf(hufftables);
166864143a74SRoy Oursler 	return compressed_len;
166901dfbcc4SRoy Oursler }
1670