Blame SOURCES/zlib-1.2.11-IBM-Z-hw-accelrated-inflate-small-window.patch

c55b40
--- a/contrib/s390/dfltcc.c
c55b40
+++ b/contrib/s390/dfltcc.c
c55b40
@@ -539,10 +539,6 @@ int ZLIB_INTERNAL dfltcc_can_inflate(strm)
c55b40
     struct inflate_state FAR *state = (struct inflate_state FAR *)strm->state;
c55b40
     struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state);
c55b40
 
c55b40
-    /* Unsupported compression settings */
c55b40
-    if (state->wbits != HB_BITS)
c55b40
-        return 0;
c55b40
-
c55b40
     /* Unsupported hardware */
c55b40
     return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) &&
c55b40
                is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0);
c55b40
@@ -606,8 +602,6 @@ dfltcc_inflate_action ZLIB_INTERNAL dfltcc_inflate(strm, flush, ret)
c55b40
     /* Translate stream to parameter block */
c55b40
     param->cvt = state->flags ? CVT_CRC32 : CVT_ADLER32;
c55b40
     param->sbb = state->bits;
c55b40
-    param->hl = state->whave; /* Software and hardware history formats match */
c55b40
-    param->ho = (state->wnext - state->whave) & ((1 << HB_BITS) - 1);
c55b40
     if (param->hl)
c55b40
         param->nt = 0; /* Honor history for the first block */
c55b40
     param->cv = state->flags ? ZSWAP32(state->check) : state->check;
c55b40
@@ -621,8 +615,6 @@ dfltcc_inflate_action ZLIB_INTERNAL dfltcc_inflate(strm, flush, ret)
c55b40
     strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
c55b40
     state->last = cc == DFLTCC_CC_OK;
c55b40
     state->bits = param->sbb;
c55b40
-    state->whave = param->hl;
c55b40
-    state->wnext = (param->ho + param->hl) & ((1 << HB_BITS) - 1);
c55b40
     strm->adler = state->check = state->flags ? ZSWAP32(param->cv) : param->cv;
c55b40
     if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) {
c55b40
         /* Report an error if stream is corrupted */
c55b40
@@ -644,11 +636,52 @@ int ZLIB_INTERNAL dfltcc_was_inflate_used(strm)
c55b40
     return !param->nt;
c55b40
 }
c55b40
 
c55b40
+/*
c55b40
+   Rotates a circular buffer.
c55b40
+   The implementation is based on https://cplusplus.com/reference/algorithm/rotate/
c55b40
+ */
c55b40
+local void rotate OF((Bytef *start, Bytef *pivot, Bytef *end));
c55b40
+local void rotate(start, pivot, end)
c55b40
+    Bytef *start;
c55b40
+    Bytef *pivot;
c55b40
+    Bytef *end;
c55b40
+{
c55b40
+    Bytef *p = pivot;
c55b40
+    Bytef tmp;
c55b40
+
c55b40
+    while (p != start) {
c55b40
+        tmp = *start;
c55b40
+        *start = *p;
c55b40
+        *p = tmp;
c55b40
+
c55b40
+        start++;
c55b40
+        p++;
c55b40
+
c55b40
+        if (p == end)
c55b40
+            p = pivot;
c55b40
+        else if (start == pivot)
c55b40
+            pivot = p;
c55b40
+    }
c55b40
+}
c55b40
+
c55b40
+#define MIN(x, y) ({    \
c55b40
+    typeof(x) _x = (x); \
c55b40
+    typeof(y) _y = (y); \
c55b40
+    _x < _y ? _x : _y;  \
c55b40
+})
c55b40
+
c55b40
+#define MAX(x, y) ({    \
c55b40
+    typeof(x) _x = (x); \
c55b40
+    typeof(y) _y = (y); \
c55b40
+    _x > _y ? _x : _y;  \
c55b40
+})
c55b40
+
c55b40
 int ZLIB_INTERNAL dfltcc_inflate_disable(strm)
c55b40
     z_streamp strm;
c55b40
 {
c55b40
     struct inflate_state FAR *state = (struct inflate_state FAR *)strm->state;
c55b40
     struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state);
c55b40
+    struct dfltcc_param_v0 *param = &dfltcc_state->param;
c55b40
 
c55b40
     if (!dfltcc_can_inflate(strm))
c55b40
         return 0;
c55b40
@@ -660,6 +693,9 @@ int ZLIB_INTERNAL dfltcc_inflate_disable(strm)
c55b40
         return 1;
c55b40
     /* DFLTCC was not used yet - decompress in software */
c55b40
     memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));
c55b40
+    /* Convert the window from the hardware to the software format */
c55b40
+    rotate(state->window, state->window + param->ho, state->window + HB_SIZE);
c55b40
+    state->whave = state->wnext = MIN(param->hl, state->wsize);
c55b40
     return 0;
c55b40
 }
c55b40
 
c55b40
@@ -830,9 +866,9 @@ voidpf ZLIB_INTERNAL dfltcc_alloc_window(strm, items, size)
c55b40
     voidpf p, w;
c55b40
 
c55b40
     /* To simplify freeing, we store the pointer to the allocated buffer right
c55b40
-     * before the window.
c55b40
+     * before the window. Note that DFLTCC always uses HB_SIZE bytes.
c55b40
      */
c55b40
-    p = ZALLOC(strm, sizeof(voidpf) + items * size + PAGE_ALIGN,
c55b40
+    p = ZALLOC(strm, sizeof(voidpf) + MAX(items * size, HB_SIZE) + PAGE_ALIGN,
c55b40
                sizeof(unsigned char));
c55b40
     if (p == NULL)
c55b40
         return NULL;
c55b40
@@ -841,6 +877,14 @@ voidpf ZLIB_INTERNAL dfltcc_alloc_window(strm, items, size)
c55b40
     return w;
c55b40
 }
c55b40
 
c55b40
+void ZLIB_INTERNAL dfltcc_copy_window(dest, src, n)
c55b40
+    void *dest;
c55b40
+    const void *src;
c55b40
+    size_t n;
c55b40
+{
c55b40
+    memcpy(dest, src, MAX(n, HB_SIZE));
c55b40
+}
c55b40
+
c55b40
 void ZLIB_INTERNAL dfltcc_free_window(strm, w)
c55b40
     z_streamp strm;
c55b40
     voidpf w;
c55b40
@@ -951,6 +995,24 @@ local void append_history(param, history, buf, count)
c55b40
     }
c55b40
 }
c55b40
 
c55b40
+local void get_history OF((struct dfltcc_param_v0 FAR *param,
c55b40
+                           const Bytef *history,
c55b40
+                           Bytef *buf));
c55b40
+local void get_history(param, history, buf)
c55b40
+    struct dfltcc_param_v0 FAR *param;
c55b40
+    const Bytef *history;
c55b40
+    Bytef *buf;
c55b40
+{
c55b40
+    if (param->ho + param->hl <= HB_SIZE)
c55b40
+        /* Circular history buffer does not wrap - copy one chunk */
c55b40
+        memcpy(buf, history + param->ho, param->hl);
c55b40
+    else {
c55b40
+        /* Circular history buffer wraps - copy two chunks */
c55b40
+        memcpy(buf, history + param->ho, HB_SIZE - param->ho);
c55b40
+        memcpy(buf + HB_SIZE - param->ho, history, param->ho + param->hl - HB_SIZE);
c55b40
+    }
c55b40
+}
c55b40
+
c55b40
 int ZLIB_INTERNAL dfltcc_deflate_set_dictionary(strm, dictionary, dict_length)
c55b40
     z_streamp strm;
c55b40
     const Bytef *dictionary;
c55b40
@@ -975,20 +1037,43 @@ int ZLIB_INTERNAL dfltcc_deflate_get_dictionary(strm, dictionary, dict_length)
c55b40
     struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state);
c55b40
     struct dfltcc_param_v0 FAR *param = &dfltcc_state->param;
c55b40
 
c55b40
-    if (dictionary) {
c55b40
-        if (param->ho + param->hl <= HB_SIZE)
c55b40
-            /* Circular history buffer does not wrap - copy one chunk */
c55b40
-            zmemcpy(dictionary, state->window + param->ho, param->hl);
c55b40
-        else {
c55b40
-            /* Circular history buffer wraps - copy two chunks */
c55b40
-            zmemcpy(dictionary,
c55b40
-                    state->window + param->ho,
c55b40
-                    HB_SIZE - param->ho);
c55b40
-            zmemcpy(dictionary + HB_SIZE - param->ho,
c55b40
-                    state->window,
c55b40
-                    param->ho + param->hl - HB_SIZE);
c55b40
-        }
c55b40
+    if (dictionary)
c55b40
+        get_history(param, state->window, dictionary);
c55b40
+    if (dict_length)
c55b40
+        *dict_length = param->hl;
c55b40
+    return Z_OK;
c55b40
+}
c55b40
+
c55b40
+int ZLIB_INTERNAL dfltcc_inflate_set_dictionary(strm, dictionary, dict_length)
c55b40
+    z_streamp strm;
c55b40
+    const Bytef *dictionary;
c55b40
+    uInt dict_length;
c55b40
+{
c55b40
+    struct inflate_state *state = (struct inflate_state *)strm->state;
c55b40
+    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
c55b40
+    struct dfltcc_param_v0 *param = &dfltcc_state->param;
c55b40
+
c55b40
+    if (inflate_ensure_window(state)) {
c55b40
+        state->mode = MEM;
c55b40
+        return Z_MEM_ERROR;
c55b40
     }
c55b40
+
c55b40
+    append_history(param, state->window, dictionary, dict_length);
c55b40
+    state->havedict = 1;
c55b40
+    return Z_OK;
c55b40
+}
c55b40
+
c55b40
+int ZLIB_INTERNAL dfltcc_inflate_get_dictionary(strm, dictionary, dict_length)
c55b40
+    z_streamp strm;
c55b40
+    Bytef *dictionary;
c55b40
+    uInt *dict_length;
c55b40
+{
c55b40
+    struct inflate_state *state = (struct inflate_state *)strm->state;
c55b40
+    struct dfltcc_state *dfltcc_state = GET_DFLTCC_STATE(state);
c55b40
+    struct dfltcc_param_v0 *param = &dfltcc_state->param;
c55b40
+
c55b40
+    if (dictionary && state->window)
c55b40
+        get_history(param, state->window, dictionary);
c55b40
     if (dict_length)
c55b40
         *dict_length = param->hl;
c55b40
     return Z_OK;
c55b40
--- a/contrib/s390/dfltcc.h
c55b40
+++ b/contrib/s390/dfltcc.h
c55b40
@@ -11,6 +11,8 @@ void ZLIB_INTERNAL dfltcc_copy_state OF((voidpf dst, const voidpf src,
c55b40
 void ZLIB_INTERNAL dfltcc_reset OF((z_streamp strm, uInt size));
c55b40
 voidpf ZLIB_INTERNAL dfltcc_alloc_window OF((z_streamp strm, uInt items,
c55b40
                                              uInt size));
c55b40
+void ZLIB_INTERNAL dfltcc_copy_window OF((void *dest, const void *src,
c55b40
+                                          size_t n));
c55b40
 void ZLIB_INTERNAL dfltcc_free_window OF((z_streamp strm, voidpf w));
c55b40
 #define DFLTCC_BLOCK_HEADER_BITS 3
c55b40
 #define DFLTCC_HLITS_COUNT_BITS 5
c55b40
@@ -44,11 +46,18 @@ dfltcc_inflate_action ZLIB_INTERNAL dfltcc_inflate OF((z_streamp strm,
c55b40
                                                        int flush, int *ret));
c55b40
 int ZLIB_INTERNAL dfltcc_was_inflate_used OF((z_streamp strm));
c55b40
 int ZLIB_INTERNAL dfltcc_inflate_disable OF((z_streamp strm));
c55b40
+int ZLIB_INTERNAL dfltcc_inflate_set_dictionary OF((z_streamp strm,
c55b40
+                                                    const Bytef *dictionary,
c55b40
+                                                    uInt dict_length));
c55b40
+int ZLIB_INTERNAL dfltcc_inflate_get_dictionary OF((z_streamp strm,
c55b40
+                                                    Bytef *dictionary,
c55b40
+                                                    uInt* dict_length));
c55b40
 
c55b40
 #define ZALLOC_STATE dfltcc_alloc_state
c55b40
 #define ZFREE_STATE ZFREE
c55b40
 #define ZCOPY_STATE dfltcc_copy_state
c55b40
 #define ZALLOC_WINDOW dfltcc_alloc_window
c55b40
+#define ZCOPY_WINDOW dfltcc_copy_window
c55b40
 #define ZFREE_WINDOW dfltcc_free_window
c55b40
 #define TRY_FREE_WINDOW dfltcc_free_window
c55b40
 #define INFLATE_RESET_KEEP_HOOK(strm) \
c55b40
@@ -77,5 +86,15 @@ int ZLIB_INTERNAL dfltcc_inflate_disable OF((z_streamp strm));
c55b40
     do { \
c55b40
         if (dfltcc_was_inflate_used((strm))) return Z_STREAM_ERROR; \
c55b40
     } while (0)
c55b40
+#define INFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) \
c55b40
+    do { \
c55b40
+        if (dfltcc_can_inflate(strm)) \
c55b40
+            return dfltcc_inflate_set_dictionary(strm, dict, dict_len); \
c55b40
+    } while (0)
c55b40
+#define INFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) \
c55b40
+    do { \
c55b40
+        if (dfltcc_can_inflate(strm)) \
c55b40
+            return dfltcc_inflate_get_dictionary(strm, dict, dict_len); \
c55b40
+    } while (0)
c55b40
 
c55b40
 #endif
c55b40
\ No newline at end of file
c55b40
diff --git a/inflate.c b/inflate.c
c55b40
index 3750152..a0e2169 100644
c55b40
--- a/inflate.c
c55b40
+++ b/inflate.c
c55b40
@@ -93,6 +93,7 @@
c55b40
 #define ZFREE_STATE ZFREE
c55b40
 #define ZCOPY_STATE zmemcpy
c55b40
 #define ZALLOC_WINDOW ZALLOC
c55b40
+#define ZCOPY_WINDOW zmemcpy
c55b40
 #define ZFREE_WINDOW ZFREE
c55b40
 #define INFLATE_RESET_KEEP_HOOK(strm) do {} while (0)
c55b40
 #define INFLATE_PRIME_HOOK(strm, bits, value) do {} while (0)
c55b40
@@ -101,6 +102,8 @@
c55b40
 #define INFLATE_NEED_UPDATEWINDOW(strm) 1
c55b40
 #define INFLATE_MARK_HOOK(strm) do {} while (0)
c55b40
 #define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0)
c55b40
+#define INFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0)
c55b40
+#define INFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0)
c55b40
 #endif
c55b40
 
c55b40
 #ifdef MAKEFIXED
c55b40
@@ -1330,6 +1333,8 @@ uInt *dictLength;
c55b40
     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
c55b40
     state = (struct inflate_state FAR *)strm->state;
c55b40
 
c55b40
+    INFLATE_GET_DICTIONARY_HOOK(strm, dictionary, dictLength);
c55b40
+
c55b40
     /* copy dictionary */
c55b40
     if (state->whave && dictionary != Z_NULL) {
c55b40
         zmemcpy(dictionary, state->window + state->wnext,
c55b40
@@ -1365,6 +1370,8 @@ uInt dictLength;
c55b40
             return Z_DATA_ERROR;
c55b40
     }
c55b40
 
c55b40
+    INFLATE_SET_DICTIONARY_HOOK(strm, dictionary, dictLength);
c55b40
+
c55b40
     /* copy dictionary to window using updatewindow(), which will amend the
c55b40
        existing dictionary if appropriate */
c55b40
     ret = updatewindow(strm, dictionary + dictLength, dictLength);
c55b40
@@ -1529,8 +1536,7 @@ z_streamp source;
c55b40
     }
c55b40
     copy->next = copy->codes + (state->next - state->codes);
c55b40
     if (window != Z_NULL) {
c55b40
-        wsize = 1U << state->wbits;
c55b40
-        zmemcpy(window, state->window, wsize);
c55b40
+        ZCOPY_WINDOW(window, state->window, 1U << state->wbits);
c55b40
     }
c55b40
     copy->window = window;
c55b40
     dest->state = (struct internal_state FAR *)copy;