File zlib-1.2.12-IBM-Z-hw-accelerated-deflate-s390x.patch of Package zlib

From e1d7e6dc9698968a8536b00ebd9e9b4e429b4306 Mon Sep 17 00:00:00 2001
From: Ilya Leoshkevich <iii@linux.ibm.com>
Date: Wed, 27 Apr 2022 14:37:24 +0200
Subject: [PATCH] zlib-1.2.12-IBM-Z-hw-accelrated-deflate-s390x.patch

---
 Makefile.in                   |   8 +
 compress.c                    |  14 +-
 configure                     |  24 +
 contrib/README.contrib        |   4 +
 contrib/s390/README.txt       |  17 +
 contrib/s390/dfltcc.c         | 996 ++++++++++++++++++++++++++++++++++
 contrib/s390/dfltcc.h         |  81 +++
 contrib/s390/dfltcc_deflate.h |  55 ++
 deflate.c                     |  81 ++-
 deflate.h                     |  12 +
 gzguts.h                      |   4 +
 inflate.c                     |  87 ++-
 inflate.h                     |   2 +
 test/infcover.c               |   4 +-
 test/minigzip.c               |   4 +
 trees.c                       |  13 +-
 zutil.h                       |   2 +
 17 files changed, 1348 insertions(+), 60 deletions(-)
 create mode 100644 contrib/s390/README.txt
 create mode 100644 contrib/s390/dfltcc.c
 create mode 100644 contrib/s390/dfltcc.h
 create mode 100644 contrib/s390/dfltcc_deflate.h

Index: zlib-1.2.12/Makefile.in
===================================================================
--- zlib-1.2.12.orig/Makefile.in
+++ zlib-1.2.12/Makefile.in
@@ -143,6 +143,14 @@ match.lo: match.S
 	mv _match.o match.lo
 	rm -f _match.s
 
+dfltcc.o: $(SRCDIR)contrib/s390/dfltcc.c $(SRCDIR)zlib.h zconf.h
+	$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)contrib/s390/dfltcc.c
+
+dfltcc.lo: $(SRCDIR)contrib/s390/dfltcc.c $(SRCDIR)zlib.h zconf.h
+	-@mkdir objs 2>/dev/null || test -d objs
+	$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/dfltcc.o $(SRCDIR)contrib/s390/dfltcc.c
+	-@mv objs/dfltcc.o $@
+
 example.o: $(SRCDIR)test/example.c $(SRCDIR)zlib.h zconf.h
 	$(CC) $(CFLAGS) $(ZINCOUT) -c -o $@ $(SRCDIR)test/example.c
 
Index: zlib-1.2.12/compress.c
===================================================================
--- zlib-1.2.12.orig/compress.c
+++ zlib-1.2.12/compress.c
@@ -5,9 +5,15 @@
 
 /* @(#) $Id$ */
 
-#define ZLIB_INTERNAL
+#include "zutil.h"
 #include "zlib.h"
 
+#ifdef DFLTCC
+#  include "contrib/s390/dfltcc.h"
+#else
+#define DEFLATE_BOUND_COMPLEN(source_len) 0
+#endif
+
 /* ===========================================================================
      Compresses the source buffer into the destination buffer. The level
    parameter has the same meaning as in deflateInit.  sourceLen is the byte
@@ -81,6 +87,12 @@ int ZEXPORT compress (dest, destLen, sou
 uLong ZEXPORT compressBound (sourceLen)
     uLong sourceLen;
 {
+    uLong complen = DEFLATE_BOUND_COMPLEN(sourceLen);
+
+    if (complen > 0)
+	/* Architecture-specific code provided an upper bound. */
+	return complen + ZLIB_WRAPLEN;
+
     return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
            (sourceLen >> 25) + 13;
 }
Index: zlib-1.2.12/configure
===================================================================
--- zlib-1.2.12.orig/configure
+++ zlib-1.2.12/configure
@@ -115,6 +115,7 @@ case "$1" in
       echo '  configure [--const] [--zprefix] [--prefix=PREFIX]  [--eprefix=EXPREFIX]' | tee -a configure.log
       echo '    [--static] [--64] [--libdir=LIBDIR] [--sharedlibdir=LIBDIR]' | tee -a configure.log
       echo '    [--includedir=INCLUDEDIR] [--archs="-arch i386 -arch x86_64"]' | tee -a configure.log
+      echo '    [--dfltcc] [--dfltcc-level-mask=MASK]' | tee -a configure.log
         exit 0 ;;
     -p*=* | --prefix=*) prefix=`echo $1 | sed 's/.*=//'`; shift ;;
     -e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/.*=//'`; shift ;;
@@ -139,6 +140,16 @@ case "$1" in
     -w* | --warn) warn=1; shift ;;
     -d* | --debug) debug=1; shift ;;
     --sanitize) sanitize=1; shift ;;
+    --dfltcc)
+      CFLAGS="$CFLAGS -DDFLTCC"
+      OBJC="$OBJC dfltcc.o"
+      PIC_OBJC="$PIC_OBJC dfltcc.lo"
+      shift
+      ;;
+    --dfltcc-level-mask=*)
+      CFLAGS="$CFLAGS -DDFLTCC_LEVEL_MASK=`echo $1 | sed 's/.*=//'`"
+      shift
+      ;;
     *)
       echo "unknown option: $1" | tee -a configure.log
       echo "$0 --help for help" | tee -a configure.log
@@ -833,6 +844,19 @@ EOF
   fi
 fi
 
+# Check whether sys/sdt.h is available
+cat > $test.c << EOF
+#include <sys/sdt.h>
+int main() { return 0; }
+EOF
+if try $CC -c $CFLAGS $test.c; then
+    echo "Checking for sys/sdt.h ... Yes." | tee -a configure.log
+    CFLAGS="$CFLAGS -DHAVE_SYS_SDT_H"
+    SFLAGS="$SFLAGS -DHAVE_SYS_SDT_H"
+else
+    echo "Checking for sys/sdt.h ... No." | tee -a configure.log
+fi
+
 # show the results in the log
 echo >> configure.log
 echo ALL = $ALL >> configure.log
Index: zlib-1.2.12/contrib/README.contrib
===================================================================
--- zlib-1.2.12.orig/contrib/README.contrib
+++ zlib-1.2.12/contrib/README.contrib
@@ -46,6 +46,10 @@ puff/       by Mark Adler <madler@alumni
         Small, low memory usage inflate.  Also serves to provide an
         unambiguous description of the deflate format.
 
+s390/       by Ilya Leoshkevich <iii@linux.ibm.com>
+        Hardware-accelerated deflate on IBM Z with DEFLATE CONVERSION CALL
+        instruction.
+
 testzlib/   by Gilles Vollant <info@winimage.com>
         Example of the use of zlib
 
Index: zlib-1.2.12/contrib/s390/README.txt
===================================================================
--- /dev/null
+++ zlib-1.2.12/contrib/s390/README.txt
@@ -0,0 +1,17 @@
+IBM Z mainframes starting from version z15 provide DFLTCC instruction,
+which implements deflate algorithm in hardware with estimated
+compression and decompression performance orders of magnitude faster
+than the current zlib and ratio comparable with that of level 1.
+
+This directory adds DFLTCC support. In order to enable it, the following
+build commands should be used:
+
+    $ ./configure --dfltcc
+    $ make
+
+When built like this, zlib would compress in hardware on level 1, and in
+software on all other levels. Decompression will always happen in
+hardware. In order to enable DFLTCC compression for levels 1-6 (i.e. to
+make it used by default) one could either configure with
+--dfltcc-level-mask=0x7e or set the environment variable
+DFLTCC_LEVEL_MASK to 0x7e at run time.
Index: zlib-1.2.12/contrib/s390/dfltcc.c
===================================================================
--- /dev/null
+++ zlib-1.2.12/contrib/s390/dfltcc.c
@@ -0,0 +1,996 @@
+/* dfltcc.c - SystemZ DEFLATE CONVERSION CALL support. */
+
+/*
+   Use the following commands to build zlib with DFLTCC support:
+
+        $ ./configure --dfltcc
+        $ make
+*/
+
+#define _GNU_SOURCE
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include "../../zutil.h"
+#include "../../deflate.h"
+#include "../../inftrees.h"
+#include "../../inflate.h"
+#include "dfltcc.h"
+#include "dfltcc_deflate.h"
+#ifdef HAVE_SYS_SDT_H
+#include <sys/sdt.h>
+#endif
+
+/*
+   C wrapper for the DEFLATE CONVERSION CALL instruction.
+ */
+typedef enum {
+    DFLTCC_CC_OK = 0,
+    DFLTCC_CC_OP1_TOO_SHORT = 1,
+    DFLTCC_CC_OP2_TOO_SHORT = 2,
+    DFLTCC_CC_OP2_CORRUPT = 2,
+    DFLTCC_CC_AGAIN = 3,
+} dfltcc_cc;
+
+#define DFLTCC_QAF 0
+#define DFLTCC_GDHT 1
+#define DFLTCC_CMPR 2
+#define DFLTCC_XPND 4
+#define HBT_CIRCULAR (1 << 7)
+#define HB_BITS 15
+#define HB_SIZE (1 << HB_BITS)
+#define DFLTCC_FACILITY 151
+
+local inline dfltcc_cc dfltcc OF((int fn, void *param,
+                                  Bytef **op1, size_t *len1,
+                                  z_const Bytef **op2, size_t *len2,
+                                  void *hist));
+local inline dfltcc_cc dfltcc(fn, param, op1, len1, op2, len2, hist)
+    int fn;
+    void *param;
+    Bytef **op1;
+    size_t *len1;
+    z_const Bytef **op2;
+    size_t *len2;
+    void *hist;
+{
+    Bytef *t2 = op1 ? *op1 : NULL;
+    size_t t3 = len1 ? *len1 : 0;
+    z_const Bytef *t4 = op2 ? *op2 : NULL;
+    size_t t5 = len2 ? *len2 : 0;
+    register int r0 __asm__("r0") = fn;
+    register void *r1 __asm__("r1") = param;
+    register Bytef *r2 __asm__("r2") = t2;
+    register size_t r3 __asm__("r3") = t3;
+    register z_const Bytef *r4 __asm__("r4") = t4;
+    register size_t r5 __asm__("r5") = t5;
+    int cc;
+
+    __asm__ volatile(
+#ifdef HAVE_SYS_SDT_H
+                     STAP_PROBE_ASM(zlib, dfltcc_entry,
+                                    STAP_PROBE_ASM_TEMPLATE(5))
+#endif
+                     ".insn rrf,0xb9390000,%[r2],%[r4],%[hist],0\n"
+#ifdef HAVE_SYS_SDT_H
+                     STAP_PROBE_ASM(zlib, dfltcc_exit,
+                                    STAP_PROBE_ASM_TEMPLATE(5))
+#endif
+                     "ipm %[cc]\n"
+                     : [r2] "+r" (r2)
+                     , [r3] "+r" (r3)
+                     , [r4] "+r" (r4)
+                     , [r5] "+r" (r5)
+                     , [cc] "=r" (cc)
+                     : [r0] "r" (r0)
+                     , [r1] "r" (r1)
+                     , [hist] "r" (hist)
+#ifdef HAVE_SYS_SDT_H
+                     , STAP_PROBE_ASM_OPERANDS(5, r2, r3, r4, r5, hist)
+#endif
+                     : "cc", "memory");
+    t2 = r2; t3 = r3; t4 = r4; t5 = r5;
+
+    if (op1)
+        *op1 = t2;
+    if (len1)
+        *len1 = t3;
+    if (op2)
+        *op2 = t4;
+    if (len2)
+        *len2 = t5;
+    return (cc >> 28) & 3;
+}
+
+/*
+   Parameter Block for Query Available Functions.
+ */
+#define static_assert(c, msg) \
+        __attribute__((unused)) \
+        static char static_assert_failed_ ## msg[c ? 1 : -1]
+
+struct dfltcc_qaf_param {
+    char fns[16];
+    char reserved1[8];
+    char fmts[2];
+    char reserved2[6];
+};
+
+static_assert(sizeof(struct dfltcc_qaf_param) == 32,
+              sizeof_struct_dfltcc_qaf_param_is_32);
+
+local inline int is_bit_set OF((const char *bits, int n));
+local inline int is_bit_set(bits, n)
+    const char *bits;
+    int n;
+{
+    return bits[n / 8] & (1 << (7 - (n % 8)));
+}
+
+local inline void clear_bit OF((char *bits, int n));
+local inline void clear_bit(bits, n)
+    char *bits;
+    int n;
+{
+    bits[n / 8] &= ~(1 << (7 - (n % 8)));
+}
+
+#define DFLTCC_FMT0 0
+
+/*
+   Parameter Block for Generate Dynamic-Huffman Table, Compress and Expand.
+ */
+#define CVT_CRC32 0
+#define CVT_ADLER32 1
+#define HTT_FIXED 0
+#define HTT_DYNAMIC 1
+
+struct dfltcc_param_v0 {
+    uint16_t pbvn;                     /* Parameter-Block-Version Number */
+    uint8_t mvn;                       /* Model-Version Number */
+    uint8_t ribm;                      /* Reserved for IBM use */
+    unsigned reserved32 : 31;
+    unsigned cf : 1;                   /* Continuation Flag */
+    uint8_t reserved64[8];
+    unsigned nt : 1;                   /* New Task */
+    unsigned reserved129 : 1;
+    unsigned cvt : 1;                  /* Check Value Type */
+    unsigned reserved131 : 1;
+    unsigned htt : 1;                  /* Huffman-Table Type */
+    unsigned bcf : 1;                  /* Block-Continuation Flag */
+    unsigned bcc : 1;                  /* Block Closing Control */
+    unsigned bhf : 1;                  /* Block Header Final */
+    unsigned reserved136 : 1;
+    unsigned reserved137 : 1;
+    unsigned dhtgc : 1;                /* DHT Generation Control */
+    unsigned reserved139 : 5;
+    unsigned reserved144 : 5;
+    unsigned sbb : 3;                  /* Sub-Byte Boundary */
+    uint8_t oesc;                      /* Operation-Ending-Supplemental Code */
+    unsigned reserved160 : 12;
+    unsigned ifs : 4;                  /* Incomplete-Function Status */
+    uint16_t ifl;                      /* Incomplete-Function Length */
+    uint8_t reserved192[8];
+    uint8_t reserved256[8];
+    uint8_t reserved320[4];
+    uint16_t hl;                       /* History Length */
+    unsigned reserved368 : 1;
+    uint16_t ho : 15;                  /* History Offset */
+    uint32_t cv;                       /* Check Value */
+    unsigned eobs : 15;                /* End-of-block Symbol */
+    unsigned reserved431: 1;
+    uint8_t eobl : 4;                  /* End-of-block Length */
+    unsigned reserved436 : 12;
+    unsigned reserved448 : 4;
+    uint16_t cdhtl : 12;               /* Compressed-Dynamic-Huffman Table
+                                          Length */
+    uint8_t reserved464[6];
+    uint8_t cdht[288];
+    uint8_t reserved[32];
+    uint8_t csb[1152];
+};
+
+static_assert(sizeof(struct dfltcc_param_v0) == 1536,
+              sizeof_struct_dfltcc_param_v0_is_1536);
+
+local z_const char *oesc_msg OF((char *buf, int oesc));
+local z_const char *oesc_msg(buf, oesc)
+    char *buf;
+    int oesc;
+{
+    if (oesc == 0x00)
+        return NULL; /* Successful completion */
+    else {
+        sprintf(buf, "Operation-Ending-Supplemental Code is 0x%.2X", oesc);
+        return buf;
+    }
+}
+
+/*
+   Extension of inflate_state and deflate_state. Must be doubleword-aligned.
+*/
+struct dfltcc_state {
+    struct dfltcc_param_v0 param;      /* Parameter block. */
+    struct dfltcc_qaf_param af;        /* Available functions. */
+    uLong level_mask;                  /* Levels on which to use DFLTCC */
+    uLong block_size;                  /* New block each X bytes */
+    uLong block_threshold;             /* New block after total_in > X */
+    uLong dht_threshold;               /* New block only if avail_in >= X */
+    char msg[64];                      /* Buffer for strm->msg */
+};
+
+#define ALIGN_UP(p, size) \
+        (__typeof__(p))(((uintptr_t)(p) + ((size) - 1)) & ~((size) - 1))
+
+#define GET_DFLTCC_STATE(state) ((struct dfltcc_state FAR *)( \
+        (char FAR *)(state) + ALIGN_UP(sizeof(*state), 8)))
+
+/*
+   Compress.
+ */
+local inline int dfltcc_can_deflate_with_params(z_streamp strm,
+                                                int level,
+                                                uInt window_bits,
+                                                int strategy);
+local inline int dfltcc_can_deflate_with_params(strm,
+                                                level,
+                                                window_bits,
+                                                strategy)
+    z_streamp strm;
+    int level;
+    uInt window_bits;
+    int strategy;
+{
+    deflate_state FAR *state = (deflate_state FAR *)strm->state;
+    struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state);
+
+    /* Unsupported compression settings */
+    if ((dfltcc_state->level_mask & (1 << level)) == 0)
+        return 0;
+    if (window_bits != HB_BITS)
+        return 0;
+    if (strategy != Z_FIXED && strategy != Z_DEFAULT_STRATEGY)
+        return 0;
+
+    /* Unsupported hardware */
+    if (!is_bit_set(dfltcc_state->af.fns, DFLTCC_GDHT) ||
+            !is_bit_set(dfltcc_state->af.fns, DFLTCC_CMPR) ||
+            !is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0))
+        return 0;
+
+    return 1;
+}
+
+int ZLIB_INTERNAL dfltcc_can_deflate(strm)
+    z_streamp strm;
+{
+    deflate_state FAR *state = (deflate_state FAR *)strm->state;
+
+    return dfltcc_can_deflate_with_params(strm,
+                                          state->level,
+                                          state->w_bits,
+                                          state->strategy);
+}
+
+local void dfltcc_gdht OF((z_streamp strm));
+local void dfltcc_gdht(strm)
+    z_streamp strm;
+{
+    deflate_state FAR *state = (deflate_state FAR *)strm->state;
+    struct dfltcc_param_v0 FAR *param = &GET_DFLTCC_STATE(state)->param;
+    size_t avail_in = avail_in = strm->avail_in;
+
+    dfltcc(DFLTCC_GDHT,
+           param, NULL, NULL,
+           &strm->next_in, &avail_in, NULL);
+}
+
+local dfltcc_cc dfltcc_cmpr OF((z_streamp strm));
+local dfltcc_cc dfltcc_cmpr(strm)
+    z_streamp strm;
+{
+    deflate_state FAR *state = (deflate_state FAR *)strm->state;
+    struct dfltcc_param_v0 FAR *param = &GET_DFLTCC_STATE(state)->param;
+    size_t avail_in = strm->avail_in;
+    size_t avail_out = strm->avail_out;
+    dfltcc_cc cc;
+
+    cc = dfltcc(DFLTCC_CMPR | HBT_CIRCULAR,
+                param, &strm->next_out, &avail_out,
+                &strm->next_in, &avail_in, state->window);
+    strm->total_in += (strm->avail_in - avail_in);
+    strm->total_out += (strm->avail_out - avail_out);
+    strm->avail_in = avail_in;
+    strm->avail_out = avail_out;
+    return cc;
+}
+
+local void send_eobs OF((z_streamp strm,
+                         z_const struct dfltcc_param_v0 FAR *param));
+local void send_eobs(strm, param)
+    z_streamp strm;
+    z_const struct dfltcc_param_v0 FAR *param;
+{
+    deflate_state FAR *state = (deflate_state FAR *)strm->state;
+
+    _tr_send_bits(
+          state,
+          bi_reverse(param->eobs >> (15 - param->eobl), param->eobl),
+          param->eobl);
+    flush_pending(strm);
+    if (state->pending != 0) {
+        /* The remaining data is located in pending_out[0:pending]. If someone
+         * calls put_byte() - this might happen in deflate() - the byte will be
+         * placed into pending_buf[pending], which is incorrect. Move the
+         * remaining data to the beginning of pending_buf so that put_byte() is
+         * usable again.
+         */
+        memmove(state->pending_buf, state->pending_out, state->pending);
+        state->pending_out = state->pending_buf;
+    }
+#ifdef ZLIB_DEBUG
+    state->compressed_len += param->eobl;
+#endif
+}
+
+int ZLIB_INTERNAL dfltcc_deflate(strm, flush, result)
+    z_streamp strm;
+    int flush;
+    block_state *result;
+{
+    deflate_state FAR *state = (deflate_state FAR *)strm->state;
+    struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state);
+    struct dfltcc_param_v0 FAR *param = &dfltcc_state->param;
+    uInt masked_avail_in;
+    dfltcc_cc cc;
+    int need_empty_block;
+    int soft_bcc;
+    int no_flush;
+
+    if (!dfltcc_can_deflate(strm)) {
+        /* Clear history. */
+        if (flush == Z_FULL_FLUSH)
+            param->hl = 0;
+        return 0;
+    }
+
+again:
+    masked_avail_in = 0;
+    soft_bcc = 0;
+    no_flush = flush == Z_NO_FLUSH;
+
+    /* No input data. Return, except when Continuation Flag is set, which means
+     * that DFLTCC has buffered some output in the parameter block and needs to
+     * be called again in order to flush it.
+     */
+    if (strm->avail_in == 0 && !param->cf) {
+        /* A block is still open, and the hardware does not support closing
+         * blocks without adding data. Thus, close it manually.
+         */
+        if (!no_flush && param->bcf) {
+            send_eobs(strm, param);
+            param->bcf = 0;
+        }
+        /* Let one of deflate_* functions write a trailing empty block. */
+        if (flush == Z_FINISH)
+            return 0;
+        /* Clear history. */
+        if (flush == Z_FULL_FLUSH)
+            param->hl = 0;
+        /* Trigger block post-processing if necessary. */
+        *result = no_flush ? need_more : block_done;
+        return 1;
+    }
+
+    /* There is an open non-BFINAL block, we are not going to close it just
+     * yet, we have compressed more than DFLTCC_BLOCK_SIZE bytes and we see
+     * more than DFLTCC_DHT_MIN_SAMPLE_SIZE bytes. Open a new block with a new
+     * DHT in order to adapt to a possibly changed input data distribution.
+     */
+    if (param->bcf && no_flush &&
+            strm->total_in > dfltcc_state->block_threshold &&
+            strm->avail_in >= dfltcc_state->dht_threshold) {
+        if (param->cf) {
+            /* We need to flush the DFLTCC buffer before writing the
+             * End-of-block Symbol. Mask the input data and proceed as usual.
+             */
+            masked_avail_in += strm->avail_in;
+            strm->avail_in = 0;
+            no_flush = 0;
+        } else {
+            /* DFLTCC buffer is empty, so we can manually write the
+             * End-of-block Symbol right away.
+             */
+            send_eobs(strm, param);
+            param->bcf = 0;
+            dfltcc_state->block_threshold =
+                strm->total_in + dfltcc_state->block_size;
+        }
+    }
+
+    /* No space for compressed data. If we proceed, dfltcc_cmpr() will return
+     * DFLTCC_CC_OP1_TOO_SHORT without buffering header bits, but we will still
+     * set BCF=1, which is wrong. Avoid complications and return early.
+     */
+    if (strm->avail_out == 0) {
+        *result = need_more;
+        return 1;
+    }
+
+    /* The caller gave us too much data. Pass only one block worth of
+     * uncompressed data to DFLTCC and mask the rest, so that on the next
+     * iteration we start a new block.
+     */
+    if (no_flush && strm->avail_in > dfltcc_state->block_size) {
+        masked_avail_in += (strm->avail_in - dfltcc_state->block_size);
+        strm->avail_in = dfltcc_state->block_size;
+    }
+
+    /* When we have an open non-BFINAL deflate block and caller indicates that
+     * the stream is ending, we need to close an open deflate block and open a
+     * BFINAL one.
+     */
+    need_empty_block = flush == Z_FINISH && param->bcf && !param->bhf;
+
+    /* Translate stream to parameter block */
+    param->cvt = state->wrap == 2 ? CVT_CRC32 : CVT_ADLER32;
+    if (!no_flush)
+        /* We need to close a block. Always do this in software - when there is
+         * no input data, the hardware will not honor BCC. */
+        soft_bcc = 1;
+    if (flush == Z_FINISH && !param->bcf)
+        /* We are about to open a BFINAL block, set Block Header Final bit
+         * until the stream ends.
+         */
+        param->bhf = 1;
+    /* DFLTCC-CMPR will write to next_out, so make sure that buffers with
+     * higher precedence are empty.
+     */
+    Assert(state->pending == 0, "There must be no pending bytes");
+    Assert(state->bi_valid < 8, "There must be less than 8 pending bits");
+    param->sbb = (unsigned int)state->bi_valid;
+    if (param->sbb > 0)
+        *strm->next_out = (Bytef)state->bi_buf;
+    /* Honor history and check value */
+    param->nt = 0;
+    param->cv = state->wrap == 2 ? ZSWAP32(strm->adler) : strm->adler;
+
+    /* When opening a block, choose a Huffman-Table Type */
+    if (!param->bcf) {
+        if (state->strategy == Z_FIXED ||
+                (strm->total_in == 0 && dfltcc_state->block_threshold > 0))
+            param->htt = HTT_FIXED;
+        else {
+            param->htt = HTT_DYNAMIC;
+            dfltcc_gdht(strm);
+        }
+    }
+
+    /* Deflate */
+    do {
+        cc = dfltcc_cmpr(strm);
+        if (strm->avail_in < 4096 && masked_avail_in > 0)
+            /* We are about to call DFLTCC with a small input buffer, which is
+             * inefficient. Since there is masked data, there will be at least
+             * one more DFLTCC call, so skip the current one and make the next
+             * one handle more data.
+             */
+            break;
+    } while (cc == DFLTCC_CC_AGAIN);
+
+    /* Translate parameter block to stream */
+    strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
+    state->bi_valid = param->sbb;
+    if (state->bi_valid == 0)
+        state->bi_buf = 0; /* Avoid accessing next_out */
+    else
+        state->bi_buf = *strm->next_out & ((1 << state->bi_valid) - 1);
+    strm->adler = state->wrap == 2 ? ZSWAP32(param->cv) : param->cv;
+
+    /* Unmask the input data */
+    strm->avail_in += masked_avail_in;
+    masked_avail_in = 0;
+
+    /* If we encounter an error, it means there is a bug in DFLTCC call */
+    Assert(cc != DFLTCC_CC_OP2_CORRUPT || param->oesc == 0, "BUG");
+
+    /* Update Block-Continuation Flag. It will be used to check whether to call
+     * GDHT the next time.
+     */
+    if (cc == DFLTCC_CC_OK) {
+        if (soft_bcc) {
+            send_eobs(strm, param);
+            param->bcf = 0;
+            dfltcc_state->block_threshold =
+                strm->total_in + dfltcc_state->block_size;
+        } else
+            param->bcf = 1;
+        if (flush == Z_FINISH) {
+            if (need_empty_block)
+                /* Make the current deflate() call also close the stream */
+                return 0;
+            else {
+                bi_windup(state);
+                *result = finish_done;
+            }
+        } else {
+            if (flush == Z_FULL_FLUSH)
+                param->hl = 0; /* Clear history */
+            *result = flush == Z_NO_FLUSH ? need_more : block_done;
+        }
+    } else {
+        param->bcf = 1;
+        *result = need_more;
+    }
+    if (strm->avail_in != 0 && strm->avail_out != 0)
+        goto again; /* deflate() must use all input or all output */
+    return 1;
+}
+
+/*
+   Expand.
+ */
+int ZLIB_INTERNAL dfltcc_can_inflate(strm)
+    z_streamp strm;
+{
+    struct inflate_state FAR *state = (struct inflate_state FAR *)strm->state;
+    struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state);
+
+    /* Unsupported compression settings */
+    if (state->wbits != HB_BITS)
+        return 0;
+
+    /* Unsupported hardware */
+    return is_bit_set(dfltcc_state->af.fns, DFLTCC_XPND) &&
+               is_bit_set(dfltcc_state->af.fmts, DFLTCC_FMT0);
+}
+
+local dfltcc_cc dfltcc_xpnd OF((z_streamp strm));
+local dfltcc_cc dfltcc_xpnd(strm)
+    z_streamp strm;
+{
+    struct inflate_state FAR *state = (struct inflate_state FAR *)strm->state;
+    struct dfltcc_param_v0 FAR *param = &GET_DFLTCC_STATE(state)->param;
+    size_t avail_in = strm->avail_in;
+    size_t avail_out = strm->avail_out;
+    dfltcc_cc cc;
+
+    cc = dfltcc(DFLTCC_XPND | HBT_CIRCULAR,
+                param, &strm->next_out, &avail_out,
+                &strm->next_in, &avail_in, state->window);
+    strm->avail_in = avail_in;
+    strm->avail_out = avail_out;
+    return cc;
+}
+
+dfltcc_inflate_action ZLIB_INTERNAL dfltcc_inflate(strm, flush, ret)
+    z_streamp strm;
+    int flush;
+    int *ret;
+{
+    struct inflate_state FAR *state = (struct inflate_state FAR *)strm->state;
+    struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state);
+    struct dfltcc_param_v0 FAR *param = &dfltcc_state->param;
+    dfltcc_cc cc;
+
+    if (flush == Z_BLOCK || flush == Z_TREES) {
+        /* DFLTCC does not support stopping on block boundaries */
+        if (dfltcc_inflate_disable(strm)) {
+            *ret = Z_STREAM_ERROR;
+            return DFLTCC_INFLATE_BREAK;
+        } else
+            return DFLTCC_INFLATE_SOFTWARE;
+    }
+
+    if (state->last) {
+        if (state->bits != 0) {
+            strm->next_in++;
+            strm->avail_in--;
+            state->bits = 0;
+        }
+        state->mode = CHECK;
+        return DFLTCC_INFLATE_CONTINUE;
+    }
+
+    if (strm->avail_in == 0 && !param->cf)
+        return DFLTCC_INFLATE_BREAK;
+
+    if (inflate_ensure_window(state)) {
+        state->mode = MEM;
+        return DFLTCC_INFLATE_CONTINUE;
+    }
+
+    /* Translate stream to parameter block */
+    param->cvt = state->flags ? CVT_CRC32 : CVT_ADLER32;
+    param->sbb = state->bits;
+    param->hl = state->whave; /* Software and hardware history formats match */
+    param->ho = (state->wnext - state->whave) & ((1 << HB_BITS) - 1);
+    if (param->hl)
+        param->nt = 0; /* Honor history for the first block */
+    param->cv = state->flags ? ZSWAP32(state->check) : state->check;
+
+    /* Inflate */
+    do {
+        cc = dfltcc_xpnd(strm);
+    } while (cc == DFLTCC_CC_AGAIN);
+
+    /* Translate parameter block to stream */
+    strm->msg = oesc_msg(dfltcc_state->msg, param->oesc);
+    state->last = cc == DFLTCC_CC_OK;
+    state->bits = param->sbb;
+    state->whave = param->hl;
+    state->wnext = (param->ho + param->hl) & ((1 << HB_BITS) - 1);
+    state->check = state->flags ? ZSWAP32(param->cv) : param->cv;
+    if (cc == DFLTCC_CC_OP2_CORRUPT && param->oesc != 0) {
+        /* Report an error if stream is corrupted */
+        state->mode = BAD;
+        return DFLTCC_INFLATE_CONTINUE;
+    }
+    state->mode = TYPEDO;
+    /* Break if operands are exhausted, otherwise continue looping */
+    return (cc == DFLTCC_CC_OP1_TOO_SHORT || cc == DFLTCC_CC_OP2_TOO_SHORT) ?
+        DFLTCC_INFLATE_BREAK : DFLTCC_INFLATE_CONTINUE;
+}
+
+int ZLIB_INTERNAL dfltcc_was_inflate_used(strm)
+    z_streamp strm;
+{
+    struct inflate_state FAR *state = (struct inflate_state FAR *)strm->state;
+    struct dfltcc_param_v0 FAR *param = &GET_DFLTCC_STATE(state)->param;
+
+    return !param->nt;
+}
+
+int ZLIB_INTERNAL dfltcc_inflate_disable(strm)
+    z_streamp strm;
+{
+    struct inflate_state FAR *state = (struct inflate_state FAR *)strm->state;
+    struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state);
+
+    if (!dfltcc_can_inflate(strm))
+        return 0;
+    if (dfltcc_was_inflate_used(strm))
+        /* DFLTCC has already decompressed some data. Since there is not
+         * enough information to resume decompression in software, the call
+         * must fail.
+         */
+        return 1;
+    /* DFLTCC was not used yet - decompress in software */
+    memset(&dfltcc_state->af, 0, sizeof(dfltcc_state->af));
+    return 0;
+}
+
+local int env_dfltcc_disabled;
+local int env_source_date_epoch;
+local unsigned long env_level_mask;
+local unsigned long env_block_size;
+local unsigned long env_block_threshold;
+local unsigned long env_dht_threshold;
+local unsigned long env_ribm;
+local uint64_t cpu_facilities[(DFLTCC_FACILITY / 64) + 1];
+local struct dfltcc_qaf_param cpu_af __attribute__((aligned(8)));
+
+local inline int is_dfltcc_enabled OF((void));
+local inline int is_dfltcc_enabled(void)
+{
+    if (env_dfltcc_disabled)
+      /* User has explicitly disabled DFLTCC. */
+      return 0;
+
+    return is_bit_set((const char *)cpu_facilities, DFLTCC_FACILITY);
+}
+
+local unsigned long xstrtoul OF((const char *s, unsigned long _default));
+local unsigned long xstrtoul(s, _default)
+    const char *s;
+    unsigned long _default;
+{
+    char *endptr;
+    unsigned long result;
+
+    if (!(s && *s))
+        return _default;
+    errno = 0;
+    result = strtoul(s, &endptr, 0);
+    return (errno || *endptr) ? _default : result;
+}
+
+__attribute__((constructor)) local void init_globals OF((void));
+__attribute__((constructor)) local void init_globals(void)
+{
+    const char *endptr;
+    const char *env;
+    register char r0 __asm__("r0");
+
+    env = secure_getenv("DFLTCC");
+    env_dfltcc_disabled = env && !strcmp(env, "0");
+
+    env = secure_getenv("SOURCE_DATE_EPOCH");
+    env_source_date_epoch = !!env;
+
+#ifndef DFLTCC_LEVEL_MASK
+#define DFLTCC_LEVEL_MASK 0x2
+#endif
+    env_level_mask = xstrtoul(secure_getenv("DFLTCC_LEVEL_MASK"),
+                              DFLTCC_LEVEL_MASK);
+
+#ifndef DFLTCC_BLOCK_SIZE
+#define DFLTCC_BLOCK_SIZE 1048576
+#endif
+    env_block_size = xstrtoul(secure_getenv("DFLTCC_BLOCK_SIZE"),
+                              DFLTCC_BLOCK_SIZE);
+
+#ifndef DFLTCC_FIRST_FHT_BLOCK_SIZE
+#define DFLTCC_FIRST_FHT_BLOCK_SIZE 4096
+#endif
+    env_block_threshold = xstrtoul(secure_getenv("DFLTCC_FIRST_FHT_BLOCK_SIZE"),
+                                   DFLTCC_FIRST_FHT_BLOCK_SIZE);
+
+#ifndef DFLTCC_DHT_MIN_SAMPLE_SIZE
+#define DFLTCC_DHT_MIN_SAMPLE_SIZE 4096
+#endif
+    env_dht_threshold = xstrtoul(secure_getenv("DFLTCC_DHT_MIN_SAMPLE_SIZE"),
+                                 DFLTCC_DHT_MIN_SAMPLE_SIZE);
+
+#ifndef DFLTCC_RIBM
+#define DFLTCC_RIBM 0
+#endif
+    env_ribm = xstrtoul(secure_getenv("DFLTCC_RIBM"), DFLTCC_RIBM);
+
+    memset(cpu_facilities, 0, sizeof(cpu_facilities));
+    r0 = sizeof(cpu_facilities) / sizeof(cpu_facilities[0]) - 1;
+    /* STFLE is supported since z9-109 and only in z/Architecture mode. When
+     * compiling with -m31, gcc defaults to ESA mode, however, since the kernel
+     * is 64-bit, it's always z/Architecture mode at runtime.
+     */
+    __asm__ volatile(
+#ifndef __clang__
+                     ".machinemode push\n"
+                     ".machinemode zarch\n"
+#endif
+                     "stfle %[facilities]\n"
+#ifndef __clang__
+                     ".machinemode pop\n"
+#endif
+                     : [facilities] "=Q" (cpu_facilities)
+                     , [r0] "+r" (r0)
+                     :
+                     : "cc");
+
+    /* Initialize available functions */
+    if (is_dfltcc_enabled())
+        dfltcc(DFLTCC_QAF, &cpu_af, NULL, NULL, NULL, NULL, NULL);
+    else
+        memset(&cpu_af, 0, sizeof(cpu_af));
+}
+
+/*
+   Memory management.
+
+   DFLTCC requires parameter blocks and window to be aligned. zlib allows
+   users to specify their own allocation functions, so using e.g.
+   `posix_memalign' is not an option. Thus, we overallocate and take the
+   aligned portion of the buffer.
+*/
+void ZLIB_INTERNAL dfltcc_reset(strm, size)
+    z_streamp strm;
+    uInt size;
+{
+    struct dfltcc_state *dfltcc_state =
+        (struct dfltcc_state *)((char FAR *)strm->state + ALIGN_UP(size, 8));
+
+    memcpy(&dfltcc_state->af, &cpu_af, sizeof(dfltcc_state->af));
+
+    if (env_source_date_epoch)
+        /* User needs reproducible results, but the output of DFLTCC_CMPR
+         * depends on buffers' page offsets.
+         */
+        clear_bit(dfltcc_state->af.fns, DFLTCC_CMPR);
+
+    /* Initialize parameter block */
+    memset(&dfltcc_state->param, 0, sizeof(dfltcc_state->param));
+    dfltcc_state->param.nt = 1;
+
+    /* Initialize tuning parameters */
+    dfltcc_state->level_mask = env_level_mask;
+    dfltcc_state->block_size = env_block_size;
+    dfltcc_state->block_threshold = env_block_threshold;
+    dfltcc_state->dht_threshold = env_dht_threshold;
+    dfltcc_state->param.ribm = env_ribm;
+}
+
+voidpf ZLIB_INTERNAL dfltcc_alloc_state(strm, items, size)
+    z_streamp strm;
+    uInt items;
+    uInt size;
+{
+    return ZALLOC(strm,
+                  ALIGN_UP(items * size, 8) + sizeof(struct dfltcc_state),
+                  sizeof(unsigned char));
+}
+
+void ZLIB_INTERNAL dfltcc_copy_state(dst, src, size)
+    voidpf dst;
+    const voidpf src;
+    uInt size;
+{
+    zmemcpy(dst, src, ALIGN_UP(size, 8) + sizeof(struct dfltcc_state));
+}
+
+static const int PAGE_ALIGN = 0x1000;
+
+voidpf ZLIB_INTERNAL dfltcc_alloc_window(strm, items, size)
+    z_streamp strm;
+    uInt items;
+    uInt size;
+{
+    voidpf p, w;
+
+    /* To simplify freeing, we store the pointer to the allocated buffer right
+     * before the window.
+     */
+    p = ZALLOC(strm, sizeof(voidpf) + items * size + PAGE_ALIGN,
+               sizeof(unsigned char));
+    if (p == NULL)
+        return NULL;
+    w = ALIGN_UP((char FAR *)p + sizeof(voidpf), PAGE_ALIGN);
+    *(voidpf *)((char FAR *)w - sizeof(voidpf)) = p;
+    return w;
+}
+
+void ZLIB_INTERNAL dfltcc_free_window(strm, w)
+    z_streamp strm;
+    voidpf w;
+{
+    if (w)
+        ZFREE(strm, *(voidpf *)((unsigned char FAR *)w - sizeof(voidpf)));
+}
+
+/*
+   Switching between hardware and software compression.
+
+   DFLTCC does not support all zlib settings, e.g. generation of non-compressed
+   blocks or alternative window sizes. When such settings are applied on the
+   fly with deflateParams, we need to convert between hardware and software
+   window formats.
+*/
+int ZLIB_INTERNAL dfltcc_deflate_params(strm, level, strategy, flush)
+    z_streamp strm;
+    int level;
+    int strategy;
+    int *flush;
+{
+    deflate_state FAR *state = (deflate_state FAR *)strm->state;
+    struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state);
+    struct dfltcc_param_v0 FAR *param = &dfltcc_state->param;
+    int could_deflate = dfltcc_can_deflate(strm);
+    int can_deflate = dfltcc_can_deflate_with_params(strm,
+                                                     level,
+                                                     state->w_bits,
+                                                     strategy);
+
+    if (can_deflate == could_deflate)
+        /* We continue to work in the same mode - no changes needed */
+        return Z_OK;
+
+    if (strm->total_in == 0 && param->nt == 1 && param->hl == 0)
+        /* DFLTCC was not used yet - no changes needed */
+        return Z_OK;
+
+    /* For now, do not convert between window formats - simply get rid of the
+     * old data instead.
+     */
+    *flush = Z_FULL_FLUSH;
+    return Z_OK;
+}
+
+int ZLIB_INTERNAL dfltcc_deflate_done(strm, flush)
+    z_streamp strm;
+    int flush;
+{
+    deflate_state FAR *state = (deflate_state FAR *)strm->state;
+    struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state);
+    struct dfltcc_param_v0 FAR *param = &dfltcc_state->param;
+
+    /* When deflate(Z_FULL_FLUSH) is called with small avail_out, it might
+     * close the block without resetting the compression state. Detect this
+     * situation and return that deflation is not done.
+     */
+    if (flush == Z_FULL_FLUSH && strm->avail_out == 0)
+        return 0;
+
+    /* Return that deflation is not done if DFLTCC is used and either it
+     * buffered some data (Continuation Flag is set), or has not written EOBS
+     * yet (Block-Continuation Flag is set).
+     */
+    return !dfltcc_can_deflate(strm) || (!param->cf && !param->bcf);
+}
+
+/*
+   Preloading history.
+*/
+local void append_history OF((struct dfltcc_param_v0 FAR *param,
+                              Bytef *history,
+                              const Bytef *buf,
+                              uInt count));
+local void append_history(param, history, buf, count)
+    struct dfltcc_param_v0 FAR *param;
+    Bytef *history;
+    const Bytef *buf;
+    uInt count;
+{
+    size_t offset;
+    size_t n;
+
+    /* Do not use more than 32K */
+    if (count > HB_SIZE) {
+        buf += count - HB_SIZE;
+        count = HB_SIZE;
+    }
+    offset = (param->ho + param->hl) % HB_SIZE;
+    if (offset + count <= HB_SIZE)
+        /* Circular history buffer does not wrap - copy one chunk */
+        zmemcpy(history + offset, buf, count);
+    else {
+        /* Circular history buffer wraps - copy two chunks */
+        n = HB_SIZE - offset;
+        zmemcpy(history + offset, buf, n);
+        zmemcpy(history, buf + n, count - n);
+    }
+    n = param->hl + count;
+    if (n <= HB_SIZE)
+        /* All history fits into buffer - no need to discard anything */
+        param->hl = n;
+    else {
+        /* History does not fit into buffer - discard extra bytes */
+        param->ho = (param->ho + (n - HB_SIZE)) % HB_SIZE;
+        param->hl = HB_SIZE;
+    }
+}
+
+int ZLIB_INTERNAL dfltcc_deflate_set_dictionary(strm, dictionary, dict_length)
+    z_streamp strm;
+    const Bytef *dictionary;
+    uInt dict_length;
+{
+    deflate_state FAR *state = (deflate_state FAR *)strm->state;
+    struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state);
+    struct dfltcc_param_v0 FAR *param = &dfltcc_state->param;
+
+    append_history(param, state->window, dictionary, dict_length);
+    state->strstart = 1; /* Add FDICT to zlib header */
+    state->block_start = state->strstart; /* Make deflate_stored happy */
+    return Z_OK;
+}
+
+int ZLIB_INTERNAL dfltcc_deflate_get_dictionary(strm, dictionary, dict_length)
+    z_streamp strm;
+    Bytef *dictionary;
+    uInt *dict_length;
+{
+    deflate_state FAR *state = (deflate_state FAR *)strm->state;
+    struct dfltcc_state FAR *dfltcc_state = GET_DFLTCC_STATE(state);
+    struct dfltcc_param_v0 FAR *param = &dfltcc_state->param;
+
+    if (dictionary) {
+        if (param->ho + param->hl <= HB_SIZE)
+            /* Circular history buffer does not wrap - copy one chunk */
+            zmemcpy(dictionary, state->window + param->ho, param->hl);
+        else {
+            /* Circular history buffer wraps - copy two chunks */
+            zmemcpy(dictionary,
+                    state->window + param->ho,
+                    HB_SIZE - param->ho);
+            zmemcpy(dictionary + HB_SIZE - param->ho,
+                    state->window,
+                    param->ho + param->hl - HB_SIZE);
+        }
+    }
+    if (dict_length)
+        *dict_length = param->hl;
+    return Z_OK;
+}
Index: zlib-1.2.12/contrib/s390/dfltcc.h
===================================================================
--- /dev/null
+++ zlib-1.2.12/contrib/s390/dfltcc.h
@@ -0,0 +1,81 @@
+#ifndef DFLTCC_H
+#define DFLTCC_H
+
+#include "../../zlib.h"
+#include "../../zutil.h"
+
+voidpf ZLIB_INTERNAL dfltcc_alloc_state OF((z_streamp strm, uInt items,
+                                            uInt size));
+void ZLIB_INTERNAL dfltcc_copy_state OF((voidpf dst, const voidpf src,
+                                         uInt size));
+void ZLIB_INTERNAL dfltcc_reset OF((z_streamp strm, uInt size));
+voidpf ZLIB_INTERNAL dfltcc_alloc_window OF((z_streamp strm, uInt items,
+                                             uInt size));
+void ZLIB_INTERNAL dfltcc_free_window OF((z_streamp strm, voidpf w));
+#define DFLTCC_BLOCK_HEADER_BITS 3
+#define DFLTCC_HLITS_COUNT_BITS 5
+#define DFLTCC_HDISTS_COUNT_BITS 5
+#define DFLTCC_HCLENS_COUNT_BITS 4
+#define DFLTCC_MAX_HCLENS 19
+#define DFLTCC_HCLEN_BITS 3
+#define DFLTCC_MAX_HLITS 286
+#define DFLTCC_MAX_HDISTS 30
+#define DFLTCC_MAX_HLIT_HDIST_BITS 7
+#define DFLTCC_MAX_SYMBOL_BITS 16
+#define DFLTCC_MAX_EOBS_BITS 15
+#define DFLTCC_MAX_PADDING_BITS 7
+#define DEFLATE_BOUND_COMPLEN(source_len) \
+    ((DFLTCC_BLOCK_HEADER_BITS + \
+      DFLTCC_HLITS_COUNT_BITS + \
+      DFLTCC_HDISTS_COUNT_BITS + \
+      DFLTCC_HCLENS_COUNT_BITS + \
+      DFLTCC_MAX_HCLENS * DFLTCC_HCLEN_BITS + \
+      (DFLTCC_MAX_HLITS + DFLTCC_MAX_HDISTS) * DFLTCC_MAX_HLIT_HDIST_BITS + \
+      (source_len) * DFLTCC_MAX_SYMBOL_BITS + \
+      DFLTCC_MAX_EOBS_BITS + \
+      DFLTCC_MAX_PADDING_BITS) >> 3)
+int ZLIB_INTERNAL dfltcc_can_inflate OF((z_streamp strm));
+typedef enum {
+    DFLTCC_INFLATE_CONTINUE,
+    DFLTCC_INFLATE_BREAK,
+    DFLTCC_INFLATE_SOFTWARE,
+} dfltcc_inflate_action;
+dfltcc_inflate_action ZLIB_INTERNAL dfltcc_inflate OF((z_streamp strm,
+                                                       int flush, int *ret));
+int ZLIB_INTERNAL dfltcc_was_inflate_used OF((z_streamp strm));
+int ZLIB_INTERNAL dfltcc_inflate_disable OF((z_streamp strm));
+
+#define ZALLOC_STATE dfltcc_alloc_state
+#define ZFREE_STATE ZFREE
+#define ZCOPY_STATE dfltcc_copy_state
+#define ZALLOC_WINDOW dfltcc_alloc_window
+#define ZFREE_WINDOW dfltcc_free_window
+#define TRY_FREE_WINDOW dfltcc_free_window
+#define INFLATE_RESET_KEEP_HOOK(strm) \
+    dfltcc_reset((strm), sizeof(struct inflate_state))
+#define INFLATE_PRIME_HOOK(strm, bits, value) \
+    do { if (dfltcc_inflate_disable((strm))) return Z_STREAM_ERROR; } while (0)
+#define INFLATE_TYPEDO_HOOK(strm, flush) \
+    if (dfltcc_can_inflate((strm))) { \
+        dfltcc_inflate_action action; \
+\
+        RESTORE(); \
+        action = dfltcc_inflate((strm), (flush), &ret); \
+        LOAD(); \
+        if (action == DFLTCC_INFLATE_CONTINUE) \
+            break; \
+        else if (action == DFLTCC_INFLATE_BREAK) \
+            goto inf_leave; \
+    }
+#define INFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_inflate((strm)))
+#define INFLATE_NEED_UPDATEWINDOW(strm) (!dfltcc_can_inflate((strm)))
+#define INFLATE_MARK_HOOK(strm) \
+    do { \
+        if (dfltcc_was_inflate_used((strm))) return -(1L << 16); \
+    } while (0)
+#define INFLATE_SYNC_POINT_HOOK(strm) \
+    do { \
+        if (dfltcc_was_inflate_used((strm))) return Z_STREAM_ERROR; \
+    } while (0)
+
+#endif
Index: zlib-1.2.12/contrib/s390/dfltcc_deflate.h
===================================================================
--- /dev/null
+++ zlib-1.2.12/contrib/s390/dfltcc_deflate.h
@@ -0,0 +1,55 @@
+#ifndef DFLTCC_DEFLATE_H
+#define DFLTCC_DEFLATE_H
+
+#include "dfltcc.h"
+
+int ZLIB_INTERNAL dfltcc_can_deflate OF((z_streamp strm));
+int ZLIB_INTERNAL dfltcc_deflate OF((z_streamp strm,
+                                     int flush,
+                                     block_state *result));
+int ZLIB_INTERNAL dfltcc_deflate_params OF((z_streamp strm,
+                                            int level,
+                                            int strategy,
+                                            int *flush));
+int ZLIB_INTERNAL dfltcc_deflate_done OF((z_streamp strm, int flush));
+int ZLIB_INTERNAL dfltcc_deflate_set_dictionary OF((z_streamp strm,
+                                                    const Bytef *dictionary,
+                                                    uInt dict_length));
+int ZLIB_INTERNAL dfltcc_deflate_get_dictionary OF((z_streamp strm,
+                                                    Bytef *dictionary,
+                                                    uInt* dict_length));
+
+#define DEFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) \
+    do { \
+        if (dfltcc_can_deflate((strm))) \
+            return dfltcc_deflate_set_dictionary((strm), (dict), (dict_len)); \
+    } while (0)
+#define DEFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) \
+    do { \
+        if (dfltcc_can_deflate((strm))) \
+            return dfltcc_deflate_get_dictionary((strm), (dict), (dict_len)); \
+    } while (0)
+#define DEFLATE_RESET_KEEP_HOOK(strm) \
+    dfltcc_reset((strm), sizeof(deflate_state))
+#define DEFLATE_PARAMS_HOOK(strm, level, strategy, hook_flush) \
+    do { \
+        int err; \
+\
+        err = dfltcc_deflate_params((strm), \
+                                    (level), \
+                                    (strategy), \
+                                    (hook_flush)); \
+        if (err == Z_STREAM_ERROR) \
+            return err; \
+    } while (0)
+#define DEFLATE_DONE dfltcc_deflate_done
+#define DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, source_len) \
+    do { \
+        if (dfltcc_can_deflate((strm))) \
+            (complen) = DEFLATE_BOUND_COMPLEN(source_len); \
+    } while (0)
+#define DEFLATE_NEED_CONSERVATIVE_BOUND(strm) (dfltcc_can_deflate((strm)))
+#define DEFLATE_HOOK dfltcc_deflate
+#define DEFLATE_NEED_CHECKSUM(strm) (!dfltcc_can_deflate((strm)))
+
+#endif
Index: zlib-1.2.12/deflate.c
===================================================================
--- zlib-1.2.12.orig/deflate.c
+++ zlib-1.2.12/deflate.c
@@ -61,15 +61,30 @@ const char deflate_copyright[] =
  */
 
 /* ===========================================================================
- *  Function prototypes.
+ *  Architecture-specific bits.
  */
-typedef enum {
-    need_more,      /* block not completed, need more input or more output */
-    block_done,     /* block flush performed */
-    finish_started, /* finish started, need only more output at next deflate */
-    finish_done     /* finish done, accept no more input or output */
-} block_state;
+#ifdef DFLTCC
+#  include "contrib/s390/dfltcc_deflate.h"
+#else
+#define ZALLOC_STATE ZALLOC
+#define ZFREE_STATE ZFREE
+#define ZCOPY_STATE zmemcpy
+#define ZALLOC_WINDOW ZALLOC
+#define TRY_FREE_WINDOW TRY_FREE
+#define DEFLATE_SET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0)
+#define DEFLATE_GET_DICTIONARY_HOOK(strm, dict, dict_len) do {} while (0)
+#define DEFLATE_RESET_KEEP_HOOK(strm) do {} while (0)
+#define DEFLATE_PARAMS_HOOK(strm, level, strategy, hook_flush) do {} while (0)
+#define DEFLATE_DONE(strm, flush) 1
+#define DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, sourceLen) do {} while (0)
+#define DEFLATE_NEED_CONSERVATIVE_BOUND(strm) 0
+#define DEFLATE_HOOK(strm, flush, bstate) 0
+#define DEFLATE_NEED_CHECKSUM(strm) 1
+#endif
 
+/* ===========================================================================
+ *  Function prototypes.
+ */
 typedef block_state (*compress_func) OF((deflate_state *s, int flush));
 /* Compression function. Returns the block state after the call. */
 
@@ -85,7 +100,6 @@ local block_state deflate_rle    OF((def
 local block_state deflate_huff   OF((deflate_state *s, int flush));
 local void lm_init        OF((deflate_state *s));
 local void putShortMSB    OF((deflate_state *s, uInt b));
-local void flush_pending  OF((z_streamp strm));
 local unsigned read_buf   OF((z_streamp strm, Bytef *buf, unsigned size));
 #ifdef ASMV
 #  pragma message("Assembler code may have bugs -- use at your own risk")
@@ -294,7 +308,7 @@ int ZEXPORT deflateInit2_(strm, level, m
         return Z_STREAM_ERROR;
     }
     if (windowBits == 8) windowBits = 9;  /* until 256-byte window bug fixed */
-    s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state));
+    s = (deflate_state *) ZALLOC_STATE(strm, 1, sizeof(deflate_state));
     if (s == Z_NULL) return Z_MEM_ERROR;
     strm->state = (struct internal_state FAR *)s;
     s->strm = strm;
@@ -311,7 +325,7 @@ int ZEXPORT deflateInit2_(strm, level, m
     s->hash_mask = s->hash_size - 1;
     s->hash_shift =  ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH);
 
-    s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte));
+    s->window = (Bytef *) ZALLOC_WINDOW(strm, s->w_size, 2*sizeof(Byte));
     s->prev   = (Posf *)  ZALLOC(strm, s->w_size, sizeof(Pos));
     s->head   = (Posf *)  ZALLOC(strm, s->hash_size, sizeof(Pos));
 
@@ -429,6 +443,7 @@ int ZEXPORT deflateSetDictionary (strm,
     /* when using zlib wrappers, compute Adler-32 for provided dictionary */
     if (wrap == 1)
         strm->adler = adler32(strm->adler, dictionary, dictLength);
+    DEFLATE_SET_DICTIONARY_HOOK(strm, dictionary, dictLength);
     s->wrap = 0;                    /* avoid computing Adler-32 in read_buf */
 
     /* if dictionary would fill window, just replace the history */
@@ -487,6 +502,7 @@ int ZEXPORT deflateGetDictionary (strm,
 
     if (deflateStateCheck(strm))
         return Z_STREAM_ERROR;
+    DEFLATE_GET_DICTIONARY_HOOK(strm, dictionary, dictLength);
     s = strm->state;
     len = s->strstart + s->lookahead;
     if (len > s->w_size)
@@ -533,6 +549,8 @@ int ZEXPORT deflateResetKeep (strm)
 
     _tr_init(s);
 
+    DEFLATE_RESET_KEEP_HOOK(strm);
+
     return Z_OK;
 }
 
@@ -608,6 +626,7 @@ int ZEXPORT deflateParams(strm, level, s
 {
     deflate_state *s;
     compress_func func;
+    int hook_flush = Z_NO_FLUSH;
 
     if (deflateStateCheck(strm)) return Z_STREAM_ERROR;
     s = strm->state;
@@ -620,15 +639,18 @@ int ZEXPORT deflateParams(strm, level, s
     if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
         return Z_STREAM_ERROR;
     }
+    DEFLATE_PARAMS_HOOK(strm, level, strategy, &hook_flush);
     func = configuration_table[s->level].func;
 
-    if ((strategy != s->strategy || func != configuration_table[level].func) &&
-        s->last_flush != -2) {
+    if (((strategy != s->strategy || func != configuration_table[level].func) &&
+         s->last_flush != -2) || hook_flush != Z_NO_FLUSH) {
         /* Flush the last buffer: */
-        int err = deflate(strm, Z_BLOCK);
+        int flush = RANK(hook_flush) > RANK(Z_BLOCK) ? hook_flush : Z_BLOCK;
+        int err = deflate(strm, flush);
         if (err == Z_STREAM_ERROR)
             return err;
-        if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead)
+        if (strm->avail_in || (s->strstart - s->block_start) + s->lookahead ||
+            !DEFLATE_DONE(strm, flush))
             return Z_BUF_ERROR;
     }
     if (s->level != level) {
@@ -695,6 +717,7 @@ uLong ZEXPORT deflateBound(strm, sourceL
     /* conservative upper bound for compressed data */
     complen = sourceLen +
               ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
+    DEFLATE_BOUND_ADJUST_COMPLEN(strm, complen, sourceLen);
 
     /* if can't get parameters, return conservative bound plus zlib wrapper */
     if (deflateStateCheck(strm))
@@ -736,7 +759,8 @@ uLong ZEXPORT deflateBound(strm, sourceL
     }
 
     /* if not default parameters, return conservative bound */
-    if (s->w_bits != 15 || s->hash_bits != 8 + 7)
+    if (DEFLATE_NEED_CONSERVATIVE_BOUND(strm) ||
+            s->w_bits != 15 || s->hash_bits != 8 + 7)
         return complen + wraplen;
 
     /* default settings: return tight bound for that case */
@@ -763,7 +787,7 @@ local void putShortMSB (s, b)
  * applications may wish to modify it to avoid allocating a large
  * strm->next_out buffer and copying into it. (See also read_buf()).
  */
-local void flush_pending(strm)
+void ZLIB_INTERNAL flush_pending(strm)
     z_streamp strm;
 {
     unsigned len;
@@ -1035,7 +1059,8 @@ int ZEXPORT deflate (strm, flush)
         (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
         block_state bstate;
 
-        bstate = s->level == 0 ? deflate_stored(s, flush) :
+        bstate = DEFLATE_HOOK(strm, flush, &bstate) ? bstate :
+                 s->level == 0 ? deflate_stored(s, flush) :
                  s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
                  s->strategy == Z_RLE ? deflate_rle(s, flush) :
                  (*(configuration_table[s->level].func))(s, flush);
@@ -1082,7 +1107,6 @@ int ZEXPORT deflate (strm, flush)
     }
 
     if (flush != Z_FINISH) return Z_OK;
-    if (s->wrap <= 0) return Z_STREAM_END;
 
     /* Write the trailer */
 #ifdef GZIP
@@ -1098,7 +1122,7 @@ int ZEXPORT deflate (strm, flush)
     }
     else
 #endif
-    {
+    if (s->wrap == 1) {
         putShortMSB(s, (uInt)(strm->adler >> 16));
         putShortMSB(s, (uInt)(strm->adler & 0xffff));
     }
@@ -1107,7 +1131,11 @@ int ZEXPORT deflate (strm, flush)
      * to flush the rest.
      */
     if (s->wrap > 0) s->wrap = -s->wrap; /* write the trailer only once! */
-    return s->pending != 0 ? Z_OK : Z_STREAM_END;
+    if (s->pending == 0) {
+        Assert(s->bi_valid == 0, "bi_buf not flushed");
+        return Z_STREAM_END;
+    }
+    return Z_OK;
 }
 
 /* ========================================================================= */
@@ -1124,9 +1152,9 @@ int ZEXPORT deflateEnd (strm)
     TRY_FREE(strm, strm->state->pending_buf);
     TRY_FREE(strm, strm->state->head);
     TRY_FREE(strm, strm->state->prev);
-    TRY_FREE(strm, strm->state->window);
+    TRY_FREE_WINDOW(strm, strm->state->window);
 
-    ZFREE(strm, strm->state);
+    ZFREE_STATE(strm, strm->state);
     strm->state = Z_NULL;
 
     return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
@@ -1156,13 +1184,13 @@ int ZEXPORT deflateCopy (dest, source)
 
     zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
 
-    ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
+    ds = (deflate_state *) ZALLOC_STATE(dest, 1, sizeof(deflate_state));
     if (ds == Z_NULL) return Z_MEM_ERROR;
     dest->state = (struct internal_state FAR *) ds;
-    zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));
+    ZCOPY_STATE((voidpf)ds, (voidpf)ss, sizeof(deflate_state));
     ds->strm = dest;
 
-    ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
+    ds->window = (Bytef *) ZALLOC_WINDOW(dest, ds->w_size, 2*sizeof(Byte));
     ds->prev   = (Posf *)  ZALLOC(dest, ds->w_size, sizeof(Pos));
     ds->head   = (Posf *)  ZALLOC(dest, ds->hash_size, sizeof(Pos));
     ds->pending_buf = (uchf *) ZALLOC(dest, ds->lit_bufsize, 4);
@@ -1209,7 +1237,8 @@ local unsigned read_buf(strm, buf, size)
     strm->avail_in  -= len;
 
     zmemcpy(buf, strm->next_in, len);
-    if (strm->state->wrap == 1) {
+    if (!DEFLATE_NEED_CHECKSUM(strm)) {}
+    else if (strm->state->wrap == 1) {
         strm->adler = adler32(strm->adler, buf, len);
     }
 #ifdef GZIP
Index: zlib-1.2.12/deflate.h
===================================================================
--- zlib-1.2.12.orig/deflate.h
+++ zlib-1.2.12/deflate.h
@@ -299,6 +299,7 @@ void ZLIB_INTERNAL _tr_flush_bits OF((de
 void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
 void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
                         ulg stored_len, int last));
+void ZLIB_INTERNAL _tr_send_bits OF((deflate_state *s, int value, int length));
 
 #define d_code(dist) \
    ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
@@ -343,4 +344,15 @@ void ZLIB_INTERNAL _tr_stored_block OF((
               flush = _tr_tally(s, distance, length)
 #endif
 
+typedef enum {
+    need_more,      /* block not completed, need more input or more output */
+    block_done,     /* block flush performed */
+    finish_started, /* finish started, need only more output at next deflate */
+    finish_done     /* finish done, accept no more input or output */
+} block_state;
+
+unsigned ZLIB_INTERNAL bi_reverse OF((unsigned code, int len));
+void ZLIB_INTERNAL bi_windup OF((deflate_state *s));
+void ZLIB_INTERNAL flush_pending OF((z_streamp strm));
+
 #endif /* DEFLATE_H */
Index: zlib-1.2.12/gzguts.h
===================================================================
--- zlib-1.2.12.orig/gzguts.h
+++ zlib-1.2.12/gzguts.h
@@ -153,7 +153,11 @@
 
 /* default i/o buffer size -- double this for output when reading (this and
    twice this must be able to fit in an unsigned type) */
+#ifdef DFLTCC
+#define GZBUFSIZE 131072
+#else
 #define GZBUFSIZE 8192
+#endif
 
 /* gzip modes, also provide a little integrity check on the passed structure */
 #define GZ_NONE 0
Index: zlib-1.2.12/inflate.c
===================================================================
--- zlib-1.2.12.orig/inflate.c
+++ zlib-1.2.12/inflate.c
@@ -85,6 +85,24 @@
 #include "inflate.h"
 #include "inffast.h"
 
+/* architecture-specific bits */
+#ifdef DFLTCC
+#  include "contrib/s390/dfltcc.h"
+#else
+#define ZALLOC_STATE ZALLOC
+#define ZFREE_STATE ZFREE
+#define ZCOPY_STATE zmemcpy
+#define ZALLOC_WINDOW ZALLOC
+#define ZFREE_WINDOW ZFREE
+#define INFLATE_RESET_KEEP_HOOK(strm) do {} while (0)
+#define INFLATE_PRIME_HOOK(strm, bits, value) do {} while (0)
+#define INFLATE_TYPEDO_HOOK(strm, flush) do {} while (0)
+#define INFLATE_NEED_CHECKSUM(strm) 1
+#define INFLATE_NEED_UPDATEWINDOW(strm) 1
+#define INFLATE_MARK_HOOK(strm) do {} while (0)
+#define INFLATE_SYNC_POINT_HOOK(strm) do {} while (0)
+#endif
+
 #ifdef MAKEFIXED
 #  ifndef BUILDFIXED
 #    define BUILDFIXED
@@ -138,6 +156,7 @@ z_streamp strm;
     state->lencode = state->distcode = state->next = state->codes;
     state->sane = 1;
     state->back = -1;
+    INFLATE_RESET_KEEP_HOOK(strm);
     Tracev((stderr, "inflate: reset\n"));
     return Z_OK;
 }
@@ -183,7 +202,7 @@ int windowBits;
     if (windowBits && (windowBits < 8 || windowBits > 15))
         return Z_STREAM_ERROR;
     if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
-        ZFREE(strm, state->window);
+        ZFREE_WINDOW(strm, state->window);
         state->window = Z_NULL;
     }
 
@@ -219,7 +238,7 @@ int stream_size;
         strm->zfree = zcfree;
 #endif
     state = (struct inflate_state FAR *)
-            ZALLOC(strm, 1, sizeof(struct inflate_state));
+            ZALLOC_STATE(strm, 1, sizeof(struct inflate_state));
     if (state == Z_NULL) return Z_MEM_ERROR;
     Tracev((stderr, "inflate: allocated\n"));
     strm->state = (struct internal_state FAR *)state;
@@ -228,7 +247,7 @@ int stream_size;
     state->mode = HEAD;     /* to pass state test in inflateReset2() */
     ret = inflateReset2(strm, windowBits);
     if (ret != Z_OK) {
-        ZFREE(strm, state);
+        ZFREE_STATE(strm, state);
         strm->state = Z_NULL;
     }
     return ret;
@@ -250,6 +269,7 @@ int value;
     struct inflate_state FAR *state;
 
     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    INFLATE_PRIME_HOOK(strm, bits, value);
     state = (struct inflate_state FAR *)strm->state;
     if (bits < 0) {
         state->hold = 0;
@@ -377,6 +397,27 @@ void makefixed()
 }
 #endif /* MAKEFIXED */
 
+int ZLIB_INTERNAL inflate_ensure_window(state)
+    struct inflate_state *state;
+{
+    /* if it hasn't been done already, allocate space for the window */
+    if (state->window == Z_NULL) {
+        state->window = (unsigned char FAR *)
+                        ZALLOC_WINDOW(state->strm, 1U << state->wbits,
+                                      sizeof(unsigned char));
+        if (state->window == Z_NULL) return 1;
+    }
+
+    /* if window not in use yet, initialize */
+    if (state->wsize == 0) {
+        state->wsize = 1U << state->wbits;
+        state->wnext = 0;
+        state->whave = 0;
+    }
+
+    return 0;
+}
+
 /*
    Update the window with the last wsize (normally 32K) bytes written before
    returning.  If window does not exist yet, create it.  This is only called
@@ -401,20 +442,7 @@ unsigned copy;
 
     state = (struct inflate_state FAR *)strm->state;
 
-    /* if it hasn't been done already, allocate space for the window */
-    if (state->window == Z_NULL) {
-        state->window = (unsigned char FAR *)
-                        ZALLOC(strm, 1U << state->wbits,
-                               sizeof(unsigned char));
-        if (state->window == Z_NULL) return 1;
-    }
-
-    /* if window not in use yet, initialize */
-    if (state->wsize == 0) {
-        state->wsize = 1U << state->wbits;
-        state->wnext = 0;
-        state->whave = 0;
-    }
+    if (inflate_ensure_window(state)) return 1;
 
     /* copy state->wsize or less output bytes into the circular window */
     if (copy >= state->wsize) {
@@ -857,6 +885,7 @@ int flush;
             if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
                 /* fallthrough */
         case TYPEDO:
+            INFLATE_TYPEDO_HOOK(strm, flush);
             if (state->last) {
                 BYTEBITS();
                 state->mode = CHECK;
@@ -1218,7 +1247,7 @@ int flush;
                 out -= left;
                 strm->total_out += out;
                 state->total += out;
-                if ((state->wrap & 4) && out)
+                if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4) && out)
                     strm->adler = state->check =
                         UPDATE_CHECK(state->check, put - out, out);
                 out = left;
@@ -1273,8 +1302,9 @@ int flush;
      */
   inf_leave:
     RESTORE();
-    if (state->wsize || (out != strm->avail_out && state->mode < BAD &&
-            (state->mode < CHECK || flush != Z_FINISH)))
+    if (INFLATE_NEED_UPDATEWINDOW(strm) &&
+            (state->wsize || (out != strm->avail_out && state->mode < BAD &&
+                 (state->mode < CHECK || flush != Z_FINISH))))
         if (updatewindow(strm, strm->next_out, out - strm->avail_out)) {
             state->mode = MEM;
             return Z_MEM_ERROR;
@@ -1284,7 +1314,7 @@ int flush;
     strm->total_in += in;
     strm->total_out += out;
     state->total += out;
-    if ((state->wrap & 4) && out)
+    if (INFLATE_NEED_CHECKSUM(strm) && (state->wrap & 4) && out)
         strm->adler = state->check =
             UPDATE_CHECK(state->check, strm->next_out - out, out);
     strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
@@ -1302,8 +1332,8 @@ z_streamp strm;
     if (inflateStateCheck(strm))
         return Z_STREAM_ERROR;
     state = (struct inflate_state FAR *)strm->state;
-    if (state->window != Z_NULL) ZFREE(strm, state->window);
-    ZFREE(strm, strm->state);
+    if (state->window != Z_NULL) ZFREE_WINDOW(strm, state->window);
+    ZFREE_STATE(strm, strm->state);
     strm->state = Z_NULL;
     Tracev((stderr, "inflate: end\n"));
     return Z_OK;
@@ -1482,6 +1512,7 @@ z_streamp strm;
     struct inflate_state FAR *state;
 
     if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
+    INFLATE_SYNC_POINT_HOOK(strm);
     state = (struct inflate_state FAR *)strm->state;
     return state->mode == STORED && state->bits == 0;
 }
@@ -1502,21 +1533,22 @@ z_streamp source;
 
     /* allocate space */
     copy = (struct inflate_state FAR *)
-           ZALLOC(source, 1, sizeof(struct inflate_state));
+           ZALLOC_STATE(source, 1, sizeof(struct inflate_state));
     if (copy == Z_NULL) return Z_MEM_ERROR;
     window = Z_NULL;
     if (state->window != Z_NULL) {
         window = (unsigned char FAR *)
-                 ZALLOC(source, 1U << state->wbits, sizeof(unsigned char));
+                 ZALLOC_WINDOW(source, 1U << state->wbits,
+                               sizeof(unsigned char));
         if (window == Z_NULL) {
-            ZFREE(source, copy);
+            ZFREE_STATE(source, copy);
             return Z_MEM_ERROR;
         }
     }
 
     /* copy state */
     zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));
-    zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
+    ZCOPY_STATE((voidpf)copy, (voidpf)state, sizeof(struct inflate_state));
     copy->strm = dest;
     if (state->lencode >= state->codes &&
         state->lencode <= state->codes + ENOUGH - 1) {
@@ -1573,6 +1605,7 @@ z_streamp strm;
 
     if (inflateStateCheck(strm))
         return -(1L << 16);
+    INFLATE_MARK_HOOK(strm);
     state = (struct inflate_state FAR *)strm->state;
     return (long)(((unsigned long)((long)state->back)) << 16) +
         (state->mode == COPY ? state->length :
Index: zlib-1.2.12/inflate.h
===================================================================
--- zlib-1.2.12.orig/inflate.h
+++ zlib-1.2.12/inflate.h
@@ -124,3 +124,5 @@ struct inflate_state {
     int back;                   /* bits back of last unprocessed length/lit */
     unsigned was;               /* initial length of match */
 };
+
+int ZLIB_INTERNAL inflate_ensure_window OF((struct inflate_state *state));
Index: zlib-1.2.12/test/infcover.c
===================================================================
--- zlib-1.2.12.orig/test/infcover.c
+++ zlib-1.2.12/test/infcover.c
@@ -373,7 +373,7 @@ local void cover_support(void)
     mem_setup(&strm);
     strm.avail_in = 0;
     strm.next_in = Z_NULL;
-    ret = inflateInit_(&strm, ZLIB_VERSION - 1, (int)sizeof(z_stream));
+    ret = inflateInit_(&strm, &ZLIB_VERSION[1], (int)sizeof(z_stream));
                                                 assert(ret == Z_VERSION_ERROR);
     mem_done(&strm, "wrong version");
 
@@ -444,7 +444,7 @@ local void cover_wrap(void)
 }
 
 /* input and output functions for inflateBack() */
-local unsigned pull(void *desc, unsigned char **buf)
+local unsigned pull(void *desc, z_const unsigned char **buf)
 {
     static unsigned int next = 0;
     static unsigned char dat[] = {0x63, 0, 2, 0};
Index: zlib-1.2.12/test/minigzip.c
===================================================================
--- zlib-1.2.12.orig/test/minigzip.c
+++ zlib-1.2.12/test/minigzip.c
@@ -132,7 +132,11 @@ static void pwinerror (s)
 #endif
 #define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1)
 
+#ifdef DFLTCC
+#define BUFLEN      262144
+#else
 #define BUFLEN      16384
+#endif
 #define MAX_NAME_LEN 1024
 
 #ifdef MAXSEG_64K
Index: zlib-1.2.12/trees.c
===================================================================
--- zlib-1.2.12.orig/trees.c
+++ zlib-1.2.12/trees.c
@@ -149,8 +149,6 @@ local void send_all_trees OF((deflate_st
 local void compress_block OF((deflate_state *s, const ct_data *ltree,
                               const ct_data *dtree));
 local int  detect_data_type OF((deflate_state *s));
-local unsigned bi_reverse OF((unsigned code, int len));
-local void bi_windup      OF((deflate_state *s));
 local void bi_flush       OF((deflate_state *s));
 
 #ifdef GEN_TREES_H
@@ -223,6 +221,13 @@ local void send_bits(s, value, length)
 }
 #endif /* ZLIB_DEBUG */
 
+void ZLIB_INTERNAL _tr_send_bits(s, value, length)
+    deflate_state *s;
+    int value;
+    int length;
+{
+    send_bits(s, value, length);
+}
 
 /* the arguments must not have side effects */
 
@@ -1134,7 +1139,7 @@ local int detect_data_type(s)
  * method would use a table)
  * IN assertion: 1 <= len <= 15
  */
-local unsigned bi_reverse(code, len)
+unsigned ZLIB_INTERNAL bi_reverse(code, len)
     unsigned code; /* the value to invert */
     int len;       /* its bit length */
 {
@@ -1166,7 +1171,7 @@ local void bi_flush(s)
 /* ===========================================================================
  * Flush the bit buffer and align the output on a byte boundary
  */
-local void bi_windup(s)
+void ZLIB_INTERNAL bi_windup(s)
     deflate_state *s;
 {
     if (s->bi_valid > 8) {
Index: zlib-1.2.12/zutil.h
===================================================================
--- zlib-1.2.12.orig/zutil.h
+++ zlib-1.2.12/zutil.h
@@ -87,6 +87,8 @@ extern z_const char * const z_errmsg[10]
 
 #define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
 
+#define ZLIB_WRAPLEN 6 /* zlib format overhead */
+
         /* target dependencies */
 
 #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
openSUSE Build Service is sponsored by