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