14e1a33b1SSven Schmidt #ifndef __LZ4DEFS_H__
24e1a33b1SSven Schmidt #define __LZ4DEFS_H__
3cffb78b0SKyungsik Lee
4cffb78b0SKyungsik Lee /*
54e1a33b1SSven Schmidt * lz4defs.h -- common and architecture specific defines for the kernel usage
64e1a33b1SSven Schmidt
74e1a33b1SSven Schmidt * LZ4 - Fast LZ compression algorithm
84e1a33b1SSven Schmidt * Copyright (C) 2011-2016, Yann Collet.
94e1a33b1SSven Schmidt * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
104e1a33b1SSven Schmidt * Redistribution and use in source and binary forms, with or without
114e1a33b1SSven Schmidt * modification, are permitted provided that the following conditions are
124e1a33b1SSven Schmidt * met:
134e1a33b1SSven Schmidt * * Redistributions of source code must retain the above copyright
144e1a33b1SSven Schmidt * notice, this list of conditions and the following disclaimer.
154e1a33b1SSven Schmidt * * Redistributions in binary form must reproduce the above
164e1a33b1SSven Schmidt * copyright notice, this list of conditions and the following disclaimer
174e1a33b1SSven Schmidt * in the documentation and/or other materials provided with the
184e1a33b1SSven Schmidt * distribution.
194e1a33b1SSven Schmidt * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
204e1a33b1SSven Schmidt * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
214e1a33b1SSven Schmidt * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
224e1a33b1SSven Schmidt * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
234e1a33b1SSven Schmidt * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
244e1a33b1SSven Schmidt * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
254e1a33b1SSven Schmidt * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
264e1a33b1SSven Schmidt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
274e1a33b1SSven Schmidt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
284e1a33b1SSven Schmidt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
294e1a33b1SSven Schmidt * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
304e1a33b1SSven Schmidt * You can contact the author at :
314e1a33b1SSven Schmidt * - LZ4 homepage : http://www.lz4.org
324e1a33b1SSven Schmidt * - LZ4 source repository : https://github.com/lz4/lz4
334e1a33b1SSven Schmidt *
344e1a33b1SSven Schmidt * Changed for kernel usage by:
354e1a33b1SSven Schmidt * Sven Schmidt <4sschmid@informatik.uni-hamburg.de>
36cffb78b0SKyungsik Lee */
374e1a33b1SSven Schmidt
384e1a33b1SSven Schmidt #include <asm/unaligned.h>
39*22c03398SAndy Shevchenko
40*22c03398SAndy Shevchenko #include <linux/bitops.h>
414e1a33b1SSven Schmidt #include <linux/string.h> /* memset, memcpy */
424e1a33b1SSven Schmidt
434e1a33b1SSven Schmidt #define FORCE_INLINE __always_inline
444e1a33b1SSven Schmidt
454e1a33b1SSven Schmidt /*-************************************
464e1a33b1SSven Schmidt * Basic Types
474e1a33b1SSven Schmidt **************************************/
484e1a33b1SSven Schmidt #include <linux/types.h>
494e1a33b1SSven Schmidt
504e1a33b1SSven Schmidt typedef uint8_t BYTE;
514e1a33b1SSven Schmidt typedef uint16_t U16;
524e1a33b1SSven Schmidt typedef uint32_t U32;
534e1a33b1SSven Schmidt typedef int32_t S32;
544e1a33b1SSven Schmidt typedef uint64_t U64;
554e1a33b1SSven Schmidt typedef uintptr_t uptrval;
564e1a33b1SSven Schmidt
574e1a33b1SSven Schmidt /*-************************************
584e1a33b1SSven Schmidt * Architecture specifics
594e1a33b1SSven Schmidt **************************************/
603e26a691SRui Salvaterra #if defined(CONFIG_64BIT)
61cffb78b0SKyungsik Lee #define LZ4_ARCH64 1
62cffb78b0SKyungsik Lee #else
63cffb78b0SKyungsik Lee #define LZ4_ARCH64 0
64cffb78b0SKyungsik Lee #endif
65cffb78b0SKyungsik Lee
664e1a33b1SSven Schmidt #if defined(__LITTLE_ENDIAN)
674e1a33b1SSven Schmidt #define LZ4_LITTLE_ENDIAN 1
684e1a33b1SSven Schmidt #else
694e1a33b1SSven Schmidt #define LZ4_LITTLE_ENDIAN 0
70cffb78b0SKyungsik Lee #endif
71cffb78b0SKyungsik Lee
724e1a33b1SSven Schmidt /*-************************************
734e1a33b1SSven Schmidt * Constants
744e1a33b1SSven Schmidt **************************************/
754e1a33b1SSven Schmidt #define MINMATCH 4
764e1a33b1SSven Schmidt
774e1a33b1SSven Schmidt #define WILDCOPYLENGTH 8
784e1a33b1SSven Schmidt #define LASTLITERALS 5
794e1a33b1SSven Schmidt #define MFLIMIT (WILDCOPYLENGTH + MINMATCH)
802209fda3SGao Xiang /*
812209fda3SGao Xiang * ensure it's possible to write 2 x wildcopyLength
822209fda3SGao Xiang * without overflowing output buffer
832209fda3SGao Xiang */
842209fda3SGao Xiang #define MATCH_SAFEGUARD_DISTANCE ((2 * WILDCOPYLENGTH) - MINMATCH)
854e1a33b1SSven Schmidt
864e1a33b1SSven Schmidt /* Increase this value ==> compression run slower on incompressible data */
874e1a33b1SSven Schmidt #define LZ4_SKIPTRIGGER 6
884e1a33b1SSven Schmidt
894e1a33b1SSven Schmidt #define HASH_UNIT sizeof(size_t)
904e1a33b1SSven Schmidt
914e1a33b1SSven Schmidt #define KB (1 << 10)
924e1a33b1SSven Schmidt #define MB (1 << 20)
934e1a33b1SSven Schmidt #define GB (1U << 30)
944e1a33b1SSven Schmidt
954e1a33b1SSven Schmidt #define MAXD_LOG 16
964e1a33b1SSven Schmidt #define MAX_DISTANCE ((1 << MAXD_LOG) - 1)
974e1a33b1SSven Schmidt #define STEPSIZE sizeof(size_t)
984e1a33b1SSven Schmidt
99cffb78b0SKyungsik Lee #define ML_BITS 4
100cffb78b0SKyungsik Lee #define ML_MASK ((1U << ML_BITS) - 1)
101cffb78b0SKyungsik Lee #define RUN_BITS (8 - ML_BITS)
102cffb78b0SKyungsik Lee #define RUN_MASK ((1U << RUN_BITS) - 1)
103cffb78b0SKyungsik Lee
1044e1a33b1SSven Schmidt /*-************************************
1054e1a33b1SSven Schmidt * Reading and writing into memory
1064e1a33b1SSven Schmidt **************************************/
LZ4_read16(const void * ptr)1074e1a33b1SSven Schmidt static FORCE_INLINE U16 LZ4_read16(const void *ptr)
1084e1a33b1SSven Schmidt {
1094e1a33b1SSven Schmidt return get_unaligned((const U16 *)ptr);
1104e1a33b1SSven Schmidt }
111cffb78b0SKyungsik Lee
LZ4_read32(const void * ptr)1124e1a33b1SSven Schmidt static FORCE_INLINE U32 LZ4_read32(const void *ptr)
1134e1a33b1SSven Schmidt {
1144e1a33b1SSven Schmidt return get_unaligned((const U32 *)ptr);
1154e1a33b1SSven Schmidt }
116cffb78b0SKyungsik Lee
LZ4_read_ARCH(const void * ptr)1174e1a33b1SSven Schmidt static FORCE_INLINE size_t LZ4_read_ARCH(const void *ptr)
1184e1a33b1SSven Schmidt {
1194e1a33b1SSven Schmidt return get_unaligned((const size_t *)ptr);
1204e1a33b1SSven Schmidt }
121cffb78b0SKyungsik Lee
LZ4_write16(void * memPtr,U16 value)1224e1a33b1SSven Schmidt static FORCE_INLINE void LZ4_write16(void *memPtr, U16 value)
1234e1a33b1SSven Schmidt {
1244e1a33b1SSven Schmidt put_unaligned(value, (U16 *)memPtr);
1254e1a33b1SSven Schmidt }
126c72ac7a1SChanho Min
LZ4_write32(void * memPtr,U32 value)1274e1a33b1SSven Schmidt static FORCE_INLINE void LZ4_write32(void *memPtr, U32 value)
1284e1a33b1SSven Schmidt {
1294e1a33b1SSven Schmidt put_unaligned(value, (U32 *)memPtr);
1304e1a33b1SSven Schmidt }
1314e1a33b1SSven Schmidt
LZ4_readLE16(const void * memPtr)1324e1a33b1SSven Schmidt static FORCE_INLINE U16 LZ4_readLE16(const void *memPtr)
1334e1a33b1SSven Schmidt {
1344e1a33b1SSven Schmidt return get_unaligned_le16(memPtr);
1354e1a33b1SSven Schmidt }
1364e1a33b1SSven Schmidt
LZ4_writeLE16(void * memPtr,U16 value)1374e1a33b1SSven Schmidt static FORCE_INLINE void LZ4_writeLE16(void *memPtr, U16 value)
1384e1a33b1SSven Schmidt {
1394e1a33b1SSven Schmidt return put_unaligned_le16(value, memPtr);
1404e1a33b1SSven Schmidt }
1414e1a33b1SSven Schmidt
142b1a3e75eSNick Terrell /*
143b1a3e75eSNick Terrell * LZ4 relies on memcpy with a constant size being inlined. In freestanding
144b1a3e75eSNick Terrell * environments, the compiler can't assume the implementation of memcpy() is
145b1a3e75eSNick Terrell * standard compliant, so apply its specialized memcpy() inlining logic. When
146b1a3e75eSNick Terrell * possible, use __builtin_memcpy() to tell the compiler to analyze memcpy()
147b1a3e75eSNick Terrell * as-if it were standard compliant, so it can inline it in freestanding
148b1a3e75eSNick Terrell * environments. This is needed when decompressing the Linux Kernel, for example.
149b1a3e75eSNick Terrell */
150b1a3e75eSNick Terrell #define LZ4_memcpy(dst, src, size) __builtin_memcpy(dst, src, size)
15189b15863SGao Xiang #define LZ4_memmove(dst, src, size) __builtin_memmove(dst, src, size)
152b1a3e75eSNick Terrell
LZ4_copy8(void * dst,const void * src)1534e1a33b1SSven Schmidt static FORCE_INLINE void LZ4_copy8(void *dst, const void *src)
1544e1a33b1SSven Schmidt {
1554e1a33b1SSven Schmidt #if LZ4_ARCH64
1564e1a33b1SSven Schmidt U64 a = get_unaligned((const U64 *)src);
1574e1a33b1SSven Schmidt
1584e1a33b1SSven Schmidt put_unaligned(a, (U64 *)dst);
159c72ac7a1SChanho Min #else
1604e1a33b1SSven Schmidt U32 a = get_unaligned((const U32 *)src);
1614e1a33b1SSven Schmidt U32 b = get_unaligned((const U32 *)src + 1);
1624e1a33b1SSven Schmidt
1634e1a33b1SSven Schmidt put_unaligned(a, (U32 *)dst);
1644e1a33b1SSven Schmidt put_unaligned(b, (U32 *)dst + 1);
165c72ac7a1SChanho Min #endif
1664e1a33b1SSven Schmidt }
167cffb78b0SKyungsik Lee
1684e1a33b1SSven Schmidt /*
1694e1a33b1SSven Schmidt * customized variant of memcpy,
1704e1a33b1SSven Schmidt * which can overwrite up to 7 bytes beyond dstEnd
1714e1a33b1SSven Schmidt */
LZ4_wildCopy(void * dstPtr,const void * srcPtr,void * dstEnd)1724e1a33b1SSven Schmidt static FORCE_INLINE void LZ4_wildCopy(void *dstPtr,
1734e1a33b1SSven Schmidt const void *srcPtr, void *dstEnd)
1744e1a33b1SSven Schmidt {
1754e1a33b1SSven Schmidt BYTE *d = (BYTE *)dstPtr;
1764e1a33b1SSven Schmidt const BYTE *s = (const BYTE *)srcPtr;
1774e1a33b1SSven Schmidt BYTE *const e = (BYTE *)dstEnd;
178cffb78b0SKyungsik Lee
1794e1a33b1SSven Schmidt do {
1804e1a33b1SSven Schmidt LZ4_copy8(d, s);
1814e1a33b1SSven Schmidt d += 8;
1824e1a33b1SSven Schmidt s += 8;
1834e1a33b1SSven Schmidt } while (d < e);
1844e1a33b1SSven Schmidt }
185cffb78b0SKyungsik Lee
LZ4_NbCommonBytes(register size_t val)1864e1a33b1SSven Schmidt static FORCE_INLINE unsigned int LZ4_NbCommonBytes(register size_t val)
1874e1a33b1SSven Schmidt {
1884e1a33b1SSven Schmidt #if LZ4_LITTLE_ENDIAN
1894e1a33b1SSven Schmidt return __ffs(val) >> 3;
190c72ac7a1SChanho Min #else
1914e1a33b1SSven Schmidt return (BITS_PER_LONG - 1 - __fls(val)) >> 3;
1924e1a33b1SSven Schmidt #endif
1934e1a33b1SSven Schmidt }
1944e1a33b1SSven Schmidt
LZ4_count(const BYTE * pIn,const BYTE * pMatch,const BYTE * pInLimit)1954e1a33b1SSven Schmidt static FORCE_INLINE unsigned int LZ4_count(
1964e1a33b1SSven Schmidt const BYTE *pIn,
1974e1a33b1SSven Schmidt const BYTE *pMatch,
1984e1a33b1SSven Schmidt const BYTE *pInLimit)
1994e1a33b1SSven Schmidt {
2004e1a33b1SSven Schmidt const BYTE *const pStart = pIn;
2014e1a33b1SSven Schmidt
2024e1a33b1SSven Schmidt while (likely(pIn < pInLimit - (STEPSIZE - 1))) {
2034e1a33b1SSven Schmidt size_t const diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
2044e1a33b1SSven Schmidt
2054e1a33b1SSven Schmidt if (!diff) {
2064e1a33b1SSven Schmidt pIn += STEPSIZE;
2074e1a33b1SSven Schmidt pMatch += STEPSIZE;
2084e1a33b1SSven Schmidt continue;
2094e1a33b1SSven Schmidt }
2104e1a33b1SSven Schmidt
2114e1a33b1SSven Schmidt pIn += LZ4_NbCommonBytes(diff);
2124e1a33b1SSven Schmidt
2134e1a33b1SSven Schmidt return (unsigned int)(pIn - pStart);
2144e1a33b1SSven Schmidt }
2154e1a33b1SSven Schmidt
2164e1a33b1SSven Schmidt #if LZ4_ARCH64
2174e1a33b1SSven Schmidt if ((pIn < (pInLimit - 3))
2184e1a33b1SSven Schmidt && (LZ4_read32(pMatch) == LZ4_read32(pIn))) {
2194e1a33b1SSven Schmidt pIn += 4;
2204e1a33b1SSven Schmidt pMatch += 4;
2214e1a33b1SSven Schmidt }
222c72ac7a1SChanho Min #endif
223c72ac7a1SChanho Min
2244e1a33b1SSven Schmidt if ((pIn < (pInLimit - 1))
2254e1a33b1SSven Schmidt && (LZ4_read16(pMatch) == LZ4_read16(pIn))) {
2264e1a33b1SSven Schmidt pIn += 2;
2274e1a33b1SSven Schmidt pMatch += 2;
2284e1a33b1SSven Schmidt }
2294e1a33b1SSven Schmidt
2304e1a33b1SSven Schmidt if ((pIn < pInLimit) && (*pMatch == *pIn))
2314e1a33b1SSven Schmidt pIn++;
2324e1a33b1SSven Schmidt
2334e1a33b1SSven Schmidt return (unsigned int)(pIn - pStart);
2344e1a33b1SSven Schmidt }
2354e1a33b1SSven Schmidt
2364e1a33b1SSven Schmidt typedef enum { noLimit = 0, limitedOutput = 1 } limitedOutput_directive;
2374e1a33b1SSven Schmidt typedef enum { byPtr, byU32, byU16 } tableType_t;
2384e1a33b1SSven Schmidt
2394e1a33b1SSven Schmidt typedef enum { noDict = 0, withPrefix64k, usingExtDict } dict_directive;
2404e1a33b1SSven Schmidt typedef enum { noDictIssue = 0, dictSmall } dictIssue_directive;
2414e1a33b1SSven Schmidt
2424e1a33b1SSven Schmidt typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;
2432209fda3SGao Xiang typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive;
2442209fda3SGao Xiang
2452209fda3SGao Xiang #define LZ4_STATIC_ASSERT(c) BUILD_BUG_ON(!(c))
2464e1a33b1SSven Schmidt
247cffb78b0SKyungsik Lee #endif
248