From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com [IPv6:2a00:1450:4864:20::32b]) by sourceware.org (Postfix) with ESMTPS id 61FB83858D1E for ; Sun, 6 Aug 2023 12:26:15 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 61FB83858D1E Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=linaro.org Received: by mail-wm1-x32b.google.com with SMTP id 5b1f17b1804b1-3fe5c0e58c0so458045e9.3 for ; Sun, 06 Aug 2023 05:26:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1691324774; x=1691929574; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :from:to:cc:subject:date:message-id:reply-to; bh=5cdnvl0j5xHpr9gA7grb/HkKgcf1YF7IgJ3yiTtsADU=; b=YeWqyU84ykvnAuZgtyDfBc82UmMrOaZTQ3DkJYIL/OXN+zShefnwGn0xmqnz5oStsF gkll6/HkIzdttJy+RUu0UPzlpk2r7PSpwUubSKzrjJP0UQLyhrzOtwyLIxtEuX6hOu4V 3rx0XN8j7Iv5zEn6ih4tCWtPgMo5Ishash9xV/PK+tWUHa5xFdKshgSE4r5yLFp3uyXJ 4g62BK7/KEoIlYHRV2Uscb9v2qevVfjSv5RLcqheZBJIxjVth9euA9ZPNHGrJFrC3edn O0TQd5TrTOnAuoXXKIrbQ62lAgFEGUjtZ37OHE+Kinpem+J6QedbSbCERDqXSPD4Bs5d oU3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1691324774; x=1691929574; h=to:subject:message-id:date:from:in-reply-to:references:mime-version :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=5cdnvl0j5xHpr9gA7grb/HkKgcf1YF7IgJ3yiTtsADU=; b=Kb9CzxkqFfkCeIQXEZ3f42/15hfsJ49QCMZjvZi1u6xtC5/Sls/7xX+KKqVC0/Lupx 0u7ysm4x4ZDudGpBZv63ASEogTsdp41w7UdubMUrkNiBcLynjNYSXQ3998yamigK9yJ7 SLLw0yNtx8hqa0p7ZAhnV+0y+tIGQb/zDoTcUjrZQS1webc40WHqgqmd1Ucplh13kOJK EMdUAu8I3vzyGHSqFn2yzGZ7exU1cnfzAeXTo+Ffq7rD7Y85aLwkB1+9gOhtGhLXPS2g FshlDWpvZH/OP+4zML281+HdlYoYzq0H0AerMd0yNsli9ywQtFpQsRl0sCgdYDtWcYbO 04yw== X-Gm-Message-State: AOJu0YwUUwM+6qH3ap3npzOR9mOOUOcE9LzRRH3/cRAhV5uYvHnrUcXa Ma2a+xxpC626BANhLOonSA6SKUukZmiirhGHMHXQXGCL5FDjTEK5 X-Google-Smtp-Source: AGHT+IEJpwjFxNsioE5SX46CvILK8HfgyOdhGl85OTlGf1bE6/mmlgkoHubT1r92s9qJB10fmDw0TSo83UIOzs7WwVI= X-Received: by 2002:a5d:4b8b:0:b0:317:6d9d:1250 with SMTP id b11-20020a5d4b8b000000b003176d9d1250mr4572854wrt.61.1691324773707; Sun, 06 Aug 2023 05:26:13 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Prathamesh Kulkarni Date: Sun, 6 Aug 2023 17:55:37 +0530 Message-ID: Subject: Re: [RFC] [v2] Extend fold_vec_perm to handle VLA vectors To: Prathamesh Kulkarni , gcc Patches , richard.sandiford@arm.com Content-Type: multipart/mixed; boundary="0000000000005664650602403c24" X-Spam-Status: No, score=-8.9 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,RCVD_IN_DNSWL_NONE,SCC_5_SHORT_WORD_LINES,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: --0000000000005664650602403c24 Content-Type: text/plain; charset="UTF-8" On Fri, 4 Aug 2023 at 20:36, Richard Sandiford wrote: > > Full review this time, sorry for the skipping the tests earlier. Thanks for the detailed review! Please find my responses inline below. > > Prathamesh Kulkarni writes: > > diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc > > index 7e5494dfd39..680d0e54fd4 100644 > > --- a/gcc/fold-const.cc > > +++ b/gcc/fold-const.cc > > @@ -85,6 +85,10 @@ along with GCC; see the file COPYING3. If not see > > #include "vec-perm-indices.h" > > #include "asan.h" > > #include "gimple-range.h" > > +#include > > This should be included by defining INCLUDE_ALGORITHM instead. Done. Just curious, why do we use this macro instead of directly including ? > > > +#include "tree-pretty-print.h" > > +#include "gimple-pretty-print.h" > > +#include "print-tree.h" > > Are these still needed, or were they for debugging? Just for debugging, removed. > > > > > /* Nonzero if we are folding constants inside an initializer or a C++ > > manifestly-constant-evaluated context; zero otherwise. > > @@ -10494,15 +10498,9 @@ fold_mult_zconjz (location_t loc, tree type, tree expr) > > static bool > > vec_cst_ctor_to_array (tree arg, unsigned int nelts, tree *elts) > > { > > - unsigned HOST_WIDE_INT i, nunits; > > + unsigned HOST_WIDE_INT i; > > > > - if (TREE_CODE (arg) == VECTOR_CST > > - && VECTOR_CST_NELTS (arg).is_constant (&nunits)) > > - { > > - for (i = 0; i < nunits; ++i) > > - elts[i] = VECTOR_CST_ELT (arg, i); > > - } > > - else if (TREE_CODE (arg) == CONSTRUCTOR) > > + if (TREE_CODE (arg) == CONSTRUCTOR) > > { > > constructor_elt *elt; > > > > @@ -10520,6 +10518,192 @@ vec_cst_ctor_to_array (tree arg, unsigned int nelts, tree *elts) > > return true; > > } > > > > +/* Helper routine for fold_vec_perm_cst to check if SEL is a suitable > > + mask for VLA vec_perm folding. > > + REASON if specified, will contain the reason why SEL is not suitable. > > + Used only for debugging and unit-testing. > > + VERBOSE if enabled is used for debugging output. */ > > + > > +static bool > > +valid_mask_for_fold_vec_perm_cst_p (tree arg0, tree arg1, > > + const vec_perm_indices &sel, > > + const char **reason = NULL, > > + ATTRIBUTE_UNUSED bool verbose = false) > > Since verbose is no longer needed (good!), I think we should just remove it. Done. > > > +{ > > + unsigned sel_npatterns = sel.encoding ().npatterns (); > > + unsigned sel_nelts_per_pattern = sel.encoding ().nelts_per_pattern (); > > + > > + if (!(pow2p_hwi (sel_npatterns) > > + && pow2p_hwi (VECTOR_CST_NPATTERNS (arg0)) > > + && pow2p_hwi (VECTOR_CST_NPATTERNS (arg1)))) > > + { > > + if (reason) > > + *reason = "npatterns is not power of 2"; > > + return false; > > + } > > + > > + /* We want to avoid cases where sel.length is not a multiple of npatterns. > > + For eg: sel.length = 2 + 2x, and sel npatterns = 4. */ > > + poly_uint64 esel; > > + if (!multiple_p (sel.length (), sel_npatterns, &esel)) > > + { > > + if (reason) > > + *reason = "sel.length is not multiple of sel_npatterns"; > > + return false; > > + } > > + > > + if (sel_nelts_per_pattern < 3) > > + return true; > > + > > + for (unsigned pattern = 0; pattern < sel_npatterns; pattern++) > > + { > > + poly_uint64 a1 = sel[pattern + sel_npatterns]; > > + poly_uint64 a2 = sel[pattern + 2 * sel_npatterns]; > > + HOST_WIDE_INT S; > > Trailing whitespace. The convention is to use lowercase variable > names, so please call this "step". Fixed, thanks. > > > + if (!poly_int64 (a2 - a1).is_constant (&S)) > > + { > > + if (reason) > > + *reason = "step is not constant"; > > + return false; > > + } > > + // FIXME: Punt on S < 0 for now, revisit later. > > + if (S < 0) > > + return false; > > + if (S == 0) > > + continue; > > + > > + if (!pow2p_hwi (S)) > > + { > > + if (reason) > > + *reason = "step is not power of 2"; > > + return false; > > + } > > + > > + /* Ensure that stepped sequence of the pattern selects elements > > + only from the same input vector if it's VLA. */ > > s/ if it's VLA// Oops sorry, that was a relic of something else I was trying :) Fixed, thanks. > > > + uint64_t q1, qe; > > + poly_uint64 r1, re; > > + poly_uint64 ae = a1 + (esel - 2) * S; > > + poly_uint64 arg_len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + if (!(can_div_trunc_p (a1, arg_len, &q1, &r1) > > + && can_div_trunc_p (ae, arg_len, &qe, &re) > > + && q1 == qe)) > > + { > > + if (reason) > > + *reason = "crossed input vectors"; > > + return false; > > + } > > + > > Probably worth a comment above the following code too: > > /* Ensure that the stepped sequence always selects from the same > input pattern. */ Done. > > > + unsigned arg_npatterns > > + = ((q1 & 0) == 0) ? VECTOR_CST_NPATTERNS (arg0) > > + : VECTOR_CST_NPATTERNS (arg1); > > + > > + if (!multiple_p (S, arg_npatterns)) > > + { > > + if (reason) > > + *reason = "S is not multiple of npatterns"; > > + return false; > > + } > > + } > > + > > + return true; > > +} > > + > > +/* Try to fold permutation of ARG0 and ARG1 with SEL selector when > > + the input vectors are VECTOR_CST. Return NULL_TREE otherwise. > > + REASON and VERBOSE have same purpose as described in > > + valid_mask_for_fold_vec_perm_cst_p. > > + > > + (1) If SEL is a suitable mask as determined by > > + valid_mask_for_fold_vec_perm_cst_p, then: > > + res_npatterns = max of npatterns between ARG0, ARG1, and SEL > > + res_nelts_per_pattern = max of nelts_per_pattern between > > + ARG0, ARG1 and SEL. > > + (2) If SEL is not a suitable mask, and ARG0, ARG1 are VLS, > > + then: > > + res_npatterns = nelts in input vector. > > s/input vector/result vector/ Fixed, thanks. > > > + res_nelts_per_pattern = 1. > > + This exception is made so that VLS ARG0, ARG1 and SEL work as before. */ > > Guess this is personal preference, but (1) and (2) seem more like > implementation details, so I think they belong... > > > + > > +static tree > > +fold_vec_perm_cst (tree type, tree arg0, tree arg1, const vec_perm_indices &sel, > > + const char **reason = NULL, bool verbose = false) > > +{ > > + unsigned res_npatterns, res_nelts_per_pattern; > > + unsigned HOST_WIDE_INT res_nelts; > > + > > ...here instead. Done. > > > + if (valid_mask_for_fold_vec_perm_cst_p (arg0, arg1, sel, reason, verbose)) > > + { > > + res_npatterns > > + = std::max (VECTOR_CST_NPATTERNS (arg0), > > + std::max (VECTOR_CST_NPATTERNS (arg1), > > + sel.encoding ().npatterns ())); > > + > > + res_nelts_per_pattern > > + = std::max (VECTOR_CST_NELTS_PER_PATTERN (arg0), > > + std::max (VECTOR_CST_NELTS_PER_PATTERN (arg1), > > + sel.encoding ().nelts_per_pattern ())); > > + > > + res_nelts = res_npatterns * res_nelts_per_pattern; > > + } > > + else if (TYPE_VECTOR_SUBPARTS (type).is_constant (&res_nelts)) > > + { > > + res_npatterns = res_nelts; > > + res_nelts_per_pattern = 1; > > + } > > + else > > + return NULL_TREE; > > + > > + tree_vector_builder out_elts (type, res_npatterns, res_nelts_per_pattern); > > + for (unsigned i = 0; i < res_nelts; i++) > > + { > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + uint64_t q; > > + poly_uint64 r; > > + unsigned HOST_WIDE_INT index; > > + > > + unsigned HOST_WIDE_INT arg_nelts; > > + if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)).is_constant (&arg_nelts) > > + && known_ge (sel[i], poly_int64 (2 * arg_nelts))) > > + { > > + if (reason) > > + *reason = "out of bounds access"; > > + return NULL_TREE; > > + } > > I don't think this is needed. The selector indices wrap, and the code > below should handle the wrapping correctly. Removed, thanks. > > > + > > + /* Punt if sel[i] /trunc_div len cannot be determined, > > + because the input vector to be chosen will depend on > > + runtime vector length. > > + For example if len == 4 + 4x, and sel[i] == 4, > > + If len at runtime equals 4, we choose arg1[0]. > > + For any other value of len > 4 at runtime, we choose arg0[4]. > > + which makes the element choice dependent on runtime vector length. */ > > + if (!can_div_trunc_p (sel[i], len, &q, &r)) > > + { > > + if (reason) > > + *reason = "cannot divide selector element by arg len"; > > + return NULL_TREE; > > + } > > + > > + /* sel[i] % len will give the index of element in the chosen input > > + vector. For example if sel[i] == 5 + 4x and len == 4 + 4x, > > + we will choose arg1[1] since (5 + 4x) % (4 + 4x) == 1. */ > > + if (!r.is_constant (&index)) > > + { > > + if (reason) > > + *reason = "remainder is not constant"; > > + return NULL_TREE; > > + } > > + > > + tree arg = ((q & 1) == 0) ? arg0 : arg1; > > + tree elem = vector_cst_elt (arg, index); > > + out_elts.quick_push (elem); > > + } > > + > > + return out_elts.build (); > > +} > > + > > /* Attempt to fold vector permutation of ARG0 and ARG1 vectors using SEL > > selector. Return the folded VECTOR_CST or CONSTRUCTOR if successful, > > NULL_TREE otherwise. */ > > @@ -10529,43 +10713,40 @@ fold_vec_perm (tree type, tree arg0, tree arg1, const vec_perm_indices &sel) > > { > > unsigned int i; > > unsigned HOST_WIDE_INT nelts; > > - bool need_ctor = false; > > > > - if (!sel.length ().is_constant (&nelts)) > > - return NULL_TREE; > > - gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (type), nelts) > > - && known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)), nelts) > > - && known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)), nelts)); > > + gcc_assert (known_eq (TYPE_VECTOR_SUBPARTS (type), sel.length ()) > > + && known_eq (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)), > > + TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg1)))); > > + > > if (TREE_TYPE (TREE_TYPE (arg0)) != TREE_TYPE (type) > > || TREE_TYPE (TREE_TYPE (arg1)) != TREE_TYPE (type)) > > return NULL_TREE; > > > > + if (TREE_CODE (arg0) == VECTOR_CST > > + && TREE_CODE (arg1) == VECTOR_CST) > > + return fold_vec_perm_cst (type, arg0, arg1, sel); > > + > > + /* For fall back case, we want to ensure we have VLS vectors > > + with equal length. */ > > + if (!sel.length ().is_constant (&nelts)) > > + return NULL_TREE; > > + > > + gcc_assert (known_eq (sel.length (), TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)))); > > Nit: long line. Fixed, thanks. > > > tree *in_elts = XALLOCAVEC (tree, nelts * 2); > > if (!vec_cst_ctor_to_array (arg0, nelts, in_elts) > > || !vec_cst_ctor_to_array (arg1, nelts, in_elts + nelts)) > > return NULL_TREE; > > > > - tree_vector_builder out_elts (type, nelts, 1); > > + vec *v; > > + vec_alloc (v, nelts); > > for (i = 0; i < nelts; i++) > > { > > HOST_WIDE_INT index; > > if (!sel[i].is_constant (&index)) > > return NULL_TREE; > > - if (!CONSTANT_CLASS_P (in_elts[index])) > > - need_ctor = true; > > - out_elts.quick_push (unshare_expr (in_elts[index])); > > - } > > - > > - if (need_ctor) > > - { > > - vec *v; > > - vec_alloc (v, nelts); > > - for (i = 0; i < nelts; i++) > > - CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, out_elts[i]); > > - return build_constructor (type, v); > > + CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, in_elts[index]); > > } > > - else > > - return out_elts.build (); > > + return build_constructor (type, v); > > } > > > > /* Try to fold a pointer difference of type TYPE two address expressions of > > @@ -16892,6 +17073,508 @@ test_arithmetic_folding () > > x); > > } > > > > +namespace test_fold_vec_perm_cst { > > + > > +static tree > > +get_preferred_vectype (tree inner_type) > > +{ > > + scalar_int_mode int_mode = SCALAR_INT_TYPE_MODE (inner_type); > > + machine_mode vmode = targetm.vectorize.preferred_simd_mode (int_mode); > > + poly_uint64 nunits = GET_MODE_NUNITS (vmode); > > + return build_vector_type (inner_type, nunits); > > +} > > + > > +static tree > > +build_vec_cst_rand (tree inner_type, unsigned npatterns, > > + unsigned nelts_per_pattern, int S = 0, > > Similar comment about lowercase variable names here. > > > + tree vectype = NULL_TREE) > > +{ > > + if (!vectype) > > + vectype = get_preferred_vectype (inner_type); > > I'm not sure how portable this is. It looks like the tests rely on > the integer_type_node vectors being 4 + 4x, but that isn't necessarily > true on all VLA targets. > > Perhaps instead the tests could be classified based on the vector > lengths that they assume. Then we can iterate through the vector > modes and call the appropriate function based on GET_MODE_NUNITS > and GET_MODE_INNER. I tried this approach in the attached patch. Does it look OK ? > > > + tree_vector_builder builder (vectype, npatterns, nelts_per_pattern); > > + > > + // Fill a0 for each pattern > > + for (unsigned i = 0; i < npatterns; i++) > > + builder.quick_push (build_int_cst (inner_type, rand () % 100)); > > + > > + if (nelts_per_pattern == 1) > > + return builder.build (); > > + > > + // Fill a1 for each pattern > > + for (unsigned i = 0; i < npatterns; i++) > > + builder.quick_push (build_int_cst (inner_type, rand () % 100)); > > + > > + if (nelts_per_pattern == 2) > > + return builder.build (); > > + > > + for (unsigned i = npatterns * 2; i < npatterns * nelts_per_pattern; i++) > > + { > > + tree prev_elem = builder[i - npatterns]; > > + int prev_elem_val = TREE_INT_CST_LOW (prev_elem); > > + int val = prev_elem_val + S; > > + builder.quick_push (build_int_cst (inner_type, val)); > > + } > > + > > + return builder.build (); > > +} > > + > > +static void > > +validate_res (unsigned npatterns, unsigned nelts_per_pattern, > > + tree res, tree *expected_res) > > +{ > > + ASSERT_TRUE (VECTOR_CST_NPATTERNS (res) == npatterns); > > + ASSERT_TRUE (VECTOR_CST_NELTS_PER_PATTERN (res) == nelts_per_pattern); > > I don't think this is safe when the inputs are randomised. E.g. we > could by chance end up with a vector of all zeros, which would have > a single pattern and a single element per pattern, regardless of the > shapes of the inputs. > > Given the way that vector_builder::finalize > canonicalises the encoding, it should be safe to use: > > * VECTOR_CST_NPATTERNS (res) <= npatterns > * vector_cst_encoded_nelts (res) <= npatterns * nelts_per_pattern > > If we do that then... > > > + > > + for (unsigned i = 0; i < vector_cst_encoded_nelts (res); i++) > > ...this loop bound should be npatterns * nelts_per_pattern instead. Ah indeed. Fixed, thanks. > > > + ASSERT_TRUE (operand_equal_p (VECTOR_CST_ELT (res, i), expected_res[i], 0)); > > +} > > + > > +static void > > +validate_res_vls (tree res, tree *expected_res, unsigned expected_nelts) > > +{ > > + ASSERT_TRUE (known_eq (VECTOR_CST_NELTS (res), expected_nelts)); > > + for (unsigned i = 0; i < expected_nelts; i++) > > + ASSERT_TRUE (operand_equal_p (VECTOR_CST_ELT (res, i), expected_res[i], 0)); > > +} > > + > > +/* Verify VLA vec_perm folding. */ > > + > > +static void > > +test_stepped () > > +{ > > + /* Case 1: sel = {0, 1, 2, ...} > > + npatterns = 1, nelts_per_pattern = 3 > > + expected res: { arg0[0], arg0[1], arg0[2], ... } */ > > + { > > + tree arg0 = build_vec_cst_rand (integer_type_node, 1, 3, 2); > > + tree arg1 = build_vec_cst_rand (integer_type_node, 1, 3, 2); > > + poly_uint64 arg0_len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (arg0_len, 1, 3); > > + builder.quick_push (0); > > + builder.quick_push (1); > > + builder.quick_push (2); > > + > > + vec_perm_indices sel (builder, 2, arg0_len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + tree expected_res[] = { vector_cst_elt (arg0, 0), vector_cst_elt (arg0, 1), > > + vector_cst_elt (arg0, 2) }; > > + validate_res (1, 3, res, expected_res); > > + } > > + > > + /* Case 2: sel = {len, len + 1, len + 2, ... } > > + npatterns = 1, nelts_per_pattern = 3 > > + FIXME: This should return > > + expected res: { op1[0], op1[1], op1[2], ... } > > + however it returns NULL_TREE. */ > > Looks like the comment is out of date. Fixed, thanks. > > > + { > > + tree arg0 = build_vec_cst_rand (integer_type_node, 1, 3, 2); > > + tree arg1 = build_vec_cst_rand (integer_type_node, 1, 3, 2); > > + poly_uint64 arg0_len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (arg0_len, 1, 3); > > + builder.quick_push (arg0_len); > > + builder.quick_push (arg0_len + 1); > > + builder.quick_push (arg0_len + 2); > > + > > + vec_perm_indices sel (builder, 2, arg0_len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel, NULL, true); > > + tree expected_res[] = { vector_cst_elt (arg1, 0), vector_cst_elt (arg1, 1), > > + vector_cst_elt (arg1, 2) }; > > + validate_res (1, 3, res, expected_res); > > + } > > + > > + /* Case 3: Leading element of arg1, stepped sequence: pattern 0 of arg0. > > + sel = {len, 0, 0, 0, 2, 0, ...} > > + npatterns = 2, nelts_per_pattern = 3. > > + Use extra pattern {0, ...} to lower number of elements per pattern. */ > > + { > > + tree arg0 = build_vec_cst_rand (char_type_node, 1, 3, 2); > > + tree arg1 = build_vec_cst_rand (char_type_node, 1, 3, 2); > > + poly_uint64 arg0_len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (arg0_len, 2, 3); > > + builder.quick_push (arg0_len); > > + int mask_elems[] = { 0, 0, 0, 2, 0 }; > > + for (int i = 0; i < 5; i++) > > + builder.quick_push (mask_elems[i]); > > This leaves one of the elements unspecified. Sorry, I didn't understand. It first pushes len in: builder.quick_push (arg0_len) and then pushes the remaining indices in the loop: for (int i = 0; i < 5; i++) builder.quick_push (mask_elems[i]) So overall, builder will have 6 elements: {len, 0, 0, 0, 2, 0} > > > + > > + vec_perm_indices sel (builder, 2, arg0_len); > > + const char *reason; > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel, &reason); > > + > > + tree expected_res[] = { vector_cst_elt (arg1, 0), vector_cst_elt (arg0, 0), > > + vector_cst_elt (arg0, 0), vector_cst_elt (arg0, 0), > > + vector_cst_elt (arg0, 2), vector_cst_elt (arg0, 0) > > + }; > > + validate_res (2, 3, res, expected_res); > > + } > > + > > + /* Case 4: > > + sel = { len, 0, 2, ... } npatterns = 1, nelts_per_pattern = 3. > > + This should return NULL because we cross the input vectors. > > + Because, > > + arg0_len = 16 + 16x > > + a1 = 0 > > + S = 2 > > + esel = arg0_len / npatterns_sel = 16+16x/1 = 16 + 16x > > + ae = 0 + (esel - 2) * S > > + = 0 + (16 + 16x - 2) * 2 > > + = 28 + 32x > > + a1 / arg0_len = 0 /trunc (16 + 16x) = 0 > > + ae / arg0_len = (28 + 32x) /trunc (16 + 16x), which is not defined, > > + since 28/16 != 32/16. > > + So return NULL_TREE. */ > > The division should succeed now, so as the test says, the reason should > instead be that ae is in the second input. Fixed, thanks. > > > + { > > + tree arg0 = build_vec_cst_rand (char_type_node, 1, 3, 2); > > + tree arg1 = build_vec_cst_rand (char_type_node, 1, 3, 2); > > + poly_uint64 arg0_len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (arg0_len, 1, 3); > > + builder.quick_push (arg0_len); > > + builder.quick_push (0); > > + builder.quick_push (2); > > + > > + vec_perm_indices sel (builder, 2, arg0_len); > > + const char *reason; > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel, &reason, false); > > + gcc_assert (res == NULL_TREE); > > + gcc_assert (!strcmp (reason, "crossed input vectors")); > > The tests should use ASSERT_* macros rather than gcc_assert. Fixed, thanks. > > > + } > > + > > + /* Case 5: Select elements from different patterns. > > + Should return NULL. */ > > + { > > + tree op0 = build_vec_cst_rand (char_type_node, 2, 3, 2); > > + tree op1 = build_vec_cst_rand (char_type_node, 2, 3, 2); > > + poly_uint64 op0_len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (op0)); > > + > > + vec_perm_builder builder (op0_len, 2, 3); > > + builder.quick_push (op0_len); > > + int mask_elems[] = { 0, 0, 0, 1, 0 }; > > + for (int i = 0; i < 5; i++) > > + builder.quick_push (mask_elems[i]); > > Should be 6 elements here too. > > > + > > + vec_perm_indices sel (builder, 2, op0_len); > > + const char *reason; > > + tree res = fold_vec_perm_cst (TREE_TYPE (op0), op0, op1, sel, &reason, false); > > + gcc_assert (res == NULL_TREE); > > + gcc_assert (!strcmp (reason, "S is not multiple of npatterns")); > > + } > > + > > + /* Case 6: Select pattern 0 of op0 and dup of op0[0] > > + op0, op1, sel: npatterns = 2, nelts_per_pattern = 3 > > + sel = { 0, 0, 2, 0, 4, 0, ... }. > > + > > + For pattern {0, 2, 4, ...}: > > + a1 = 2 > > + len = 16 + 16x > > + S = 2 > > + esel = len / npatterns_sel = (16 + 16x) / 2 = (8 + 8x) > > + ae = a1 + (esel - 2) * S > > + = 2 + (8 + 8x - 2) * 2 > > + = 14 + 16x > > + a1 / arg0_len = 2 / (16 + 16x) = 0 > > + ae / arg0_len = (14 + 16x) / (16 + 16x) = 0 > > + So a1/arg0_len = ae/arg0_len = 0 > > + Hence we select from first vector op0 > > + S = 2, npatterns = 2. > > + Since S is multiple of npatterns(op0), we are selecting from > > + same pattern of op0. > > + > > + For pattern {0, ...}, we are choosing { op0[0] ... } > > + So res will be combination of above patterns: > > + res: { op0[0], op0[0], op0[2], op0[0], op0[4], op0[0], ... } > > + with npatterns = 2, nelts_per_pattern = 3. */ > > + { > > + tree op0 = build_vec_cst_rand (char_type_node, 2, 3, 2); > > + tree op1 = build_vec_cst_rand (char_type_node, 2, 3, 2); > > + poly_uint64 op0_len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (op0)); > > + > > + vec_perm_builder builder (op0_len, 2, 3); > > + int mask_elems[] = { 0, 0, 2, 0, 4, 0 }; > > + for (int i = 0; i < 6; i++) > > + builder.quick_push (mask_elems[i]); > > + > > + vec_perm_indices sel (builder, 2, op0_len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (op0), op0, op1, sel); > > + tree expected_res[] = { vector_cst_elt (op0, 0), vector_cst_elt (op0, 0), > > + vector_cst_elt (op0, 2), vector_cst_elt (op0, 0), > > + vector_cst_elt (op0, 4), vector_cst_elt (op0, 0) }; > > + validate_res (2, 3, res, expected_res); > > + } > > + > > + /* Case 7: sel_npatterns > op_npatterns; > > + op0, op1: npatterns = 2, nelts_per_pattern = 3 > > + sel: { 0, 0, 1, len, 2, 0, 3, len, 4, 0, 5, len, ...}, > > + with npatterns = 4, nelts_per_pattern = 3. */ > > + { > > + tree op0 = build_vec_cst_rand (char_type_node, 2, 3, 2); > > + tree op1 = build_vec_cst_rand (char_type_node, 2, 3, 2); > > + poly_uint64 op0_len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (op0)); > > + > > + vec_perm_builder builder(op0_len, 4, 3); > > + // -1 is used as place holder for poly_int_cst > > + int mask_elems[] = { 0, 0, 1, -1, 2, 0, 3, -1, 4, 0, 5, -1 }; > > + for (int i = 0; i < 12; i++) > > + builder.quick_push ((mask_elems[i] == -1) ? op0_len : mask_elems[i]); > > + > > + vec_perm_indices sel (builder, 2, op0_len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (op0), op0, op1, sel); > > + tree expected_res[] = { vector_cst_elt (op0, 0), vector_cst_elt (op0, 0), > > + vector_cst_elt (op0, 1), vector_cst_elt (op1, 0), > > + vector_cst_elt (op0, 2), vector_cst_elt (op0, 0), > > + vector_cst_elt (op0, 3), vector_cst_elt (op1, 0), > > + vector_cst_elt (op0, 4), vector_cst_elt (op0, 0), > > + vector_cst_elt (op0, 5), vector_cst_elt (op1, 0) }; > > + validate_res (4, 3, res, expected_res); > > + } > > +} > > + > > +static void > > +test_dup () > > +{ > > + /* Case 1: mask = {0, ...} */ > > + { > > + tree arg0 = build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + tree arg1 = build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 1, 1); > > + builder.quick_push (0); > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + > > + tree expected_res[] = { vector_cst_elt (res, 0) }; > > + validate_res (1, 1, res, expected_res); > > + } > > + > > + /* Case 2: mask = {len, ...} */ > > + { > > + tree arg0 = build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + tree arg1 = build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 1, 1); > > + builder.quick_push (len); > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + > > + tree expected_res[] = { vector_cst_elt (arg1, 0) }; > > + validate_res (1, 1, res, expected_res); > > + } > > + > > + /* Case 3: mask = { 0, len, ... } */ > > + { > > + tree arg0 = build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + tree arg1 = build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 2, 1); > > + builder.quick_push (0); > > + builder.quick_push (len); > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + > > + tree expected_res[] = { vector_cst_elt (arg0, 0), vector_cst_elt (arg1, 0) }; > > + validate_res (2, 1, res, expected_res); > > + } > > + > > + /* Case 4: mask = { 0, len, 1, len+1, ... } */ > > + { > > + tree arg0 = build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + tree arg1 = build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 2, 2); > > + builder.quick_push (0); > > + builder.quick_push (len); > > + builder.quick_push (1); > > + builder.quick_push (len + 1); > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + > > + tree expected_res[] = { vector_cst_elt (arg0, 0), vector_cst_elt (arg1, 0), > > + vector_cst_elt (arg0, 1), vector_cst_elt (arg1, 1) > > + }; > > + validate_res (2, 2, res, expected_res); > > + } > > + > > + /* Case 5: mask = { 0, len, 1, len+1, .... } > > + npatterns = 4, nelts_per_pattern = 1 */ > > + { > > + tree arg0 = build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + tree arg1 = build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 4, 1); > > + builder.quick_push (0); > > + builder.quick_push (len); > > + builder.quick_push (1); > > + builder.quick_push (len + 1); > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + > > + tree expected_res[] = { vector_cst_elt (arg0, 0), vector_cst_elt (arg1, 0), > > + vector_cst_elt (arg0, 1), vector_cst_elt (arg1, 1) > > + }; > > + validate_res (4, 1, res, expected_res); > > + } > > + > > + /* Case 6: mask = {0, 4, ...} > > + npatterns = 1, nelts_per_pattern = 2. > > + This should return NULL_TREE because the index 4 may choose > > + from either arg0 or arg1 depending on vector length. */ > > + { > > + tree arg0 = build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + tree arg1 = build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + poly_uint64 len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (len, 1, 2); > > + builder.quick_push (0); > > + builder.quick_push (4); > > + vec_perm_indices sel (builder, 2, len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + ASSERT_TRUE (res == NULL_TREE); > > + } > > + > > + /* Case 7: npatterns(arg0) = 4 > npatterns(sel) = 2 > > + mask = {0, len, 1, len + 1, ...} > > + sel_npatterns = 2, sel_nelts_per_pattern = 2. */ > > This is a good test to have, but it doesn't seem to match the > name of the containing function (test_dup). Well since the selector has nelts_per_pattern = 2, ie, dup of a1, I chose to put it in test_dup. Anyway, the functions are now re-classified based on vector length in the patch. > > > + { > > + tree arg0 = build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + tree arg1 = build_vec_cst_rand (integer_type_node, 2, 3, 1); > > + poly_uint64 arg0_len = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg0)); > > + > > + vec_perm_builder builder (arg0_len, 2, 2); > > + builder.quick_push (0); > > + builder.quick_push (arg0_len); > > + builder.quick_push (1); > > + builder.quick_push (arg0_len + 1); > > + vec_perm_indices sel (builder, 2, arg0_len); > > + tree res = fold_vec_perm_cst (TREE_TYPE (arg0), arg0, arg1, sel); > > + > > + tree expected_res[] = { vector_cst_elt (arg0, 0), vector_cst_elt (arg1, 0), > > + vector_cst_elt (arg0, 1), vector_cst_elt (arg1, 1) > > + }; > > + validate_res (2, 2, res, expected_res); > > + } > > +} > > + > > +static void > > +test_mixed () > > +{ > > + /* Case 1: op0, op1 -> VLS, sel -> VLA and selects from both input vectors. > > + In this case, we treat res_npatterns = nelts in input vector > > + and res_nelts_per_pattern = 1, and create a dup pattern. > > + sel = { 0, 4, 1, 5, ... } > > + res = { op0[0], op1[0], op0[1], op1[1], ...} // (4, 1) > > + res_npatterns = 4, res_nelts_per_pattern = 1. */ > > + { > > + tree arg_vectype = build_vector_type (integer_type_node, 4); > > + tree arg0 = build_vec_cst_rand (integer_type_node, 4, 1, 0, arg_vectype); > > + tree arg1 = build_vec_cst_rand (integer_type_node, 4, 1, 0, arg_vectype); > > + > > + tree res_type = get_preferred_vectype (integer_type_node); > > + poly_uint64 res_len = TYPE_VECTOR_SUBPARTS (res_type); > > + vec_perm_builder builder (res_len, 4, 1); > > + builder.quick_push (0); > > + builder.quick_push (4); > > + builder.quick_push (1); > > + builder.quick_push (5); > > + > > + vec_perm_indices sel (builder, 2, res_len); > > + tree res = fold_vec_perm_cst (res_type, arg0, arg1, sel); > > + tree expected_res[] = { vector_cst_elt (arg0, 0), vector_cst_elt (arg1, 0), > > + vector_cst_elt (arg0, 1), vector_cst_elt (arg1, 1) > > + }; > > + validate_res (4, 1, res, expected_res); > > + } > > + > > + /* Case 2: Same as Case 1, but sel contains an out of bounds index. > > + result should be NULL_TREE. */ > > + { > > + tree arg_vectype = build_vector_type (integer_type_node, 4); > > + tree arg0 = build_vec_cst_rand (integer_type_node, 4, 1, 0, arg_vectype); > > + tree arg1 = build_vec_cst_rand (integer_type_node, 4, 1, 0, arg_vectype); > > + > > + tree res_type = get_preferred_vectype (integer_type_node); > > + poly_uint64 res_len = TYPE_VECTOR_SUBPARTS (res_type); > > + vec_perm_builder builder (res_len, 4, 1); > > + builder.quick_push (0); > > + builder.quick_push (8); > > + builder.quick_push (1); > > + builder.quick_push (5); > > + > > + vec_perm_indices sel (builder, 2, res_len); > > + const char *reason; > > + tree res = fold_vec_perm_cst (res_type, arg0, arg1, sel, &reason); > > + gcc_assert (res == NULL_TREE); > > + gcc_assert (!strcmp (reason, "out of bounds access")); > > + } > > + > > + /* Case 3: op0, op1 are VLA and sel is VLS. > > + op0, op1: VNx16QI with shape (2, 3) > > + sel = V4SI with values {0, 2, 4, 6} > > + res: V4SI with values { op0[0], op0[2], op0[4], op0[6] }. */ > > + { > > + tree arg0 = build_vec_cst_rand (char_type_node, 2, 3, 2); > > + tree arg1 = build_vec_cst_rand (char_type_node, 2, 3, 2); > > + > > + poly_uint64 res_len = 4; > > + tree res_type = build_vector_type (char_type_node, res_len); > > + vec_perm_builder builder (res_len, 4, 1); > > + builder.quick_push (0); > > + builder.quick_push (2); > > + builder.quick_push (4); > > + builder.quick_push (6); > > + > > + vec_perm_indices sel (builder, 2, res_len); > > + tree res = fold_vec_perm_cst (res_type, arg0, arg1, sel); > > + > > + tree expected_res[] = { vector_cst_elt (arg0, 0), vector_cst_elt (arg0, 2), > > + vector_cst_elt (arg0, 4), vector_cst_elt (arg0, 6) > > + }; > > + validate_res_vls (res, expected_res, 4); > > + } > > + > > + /* Case 4: Same as case 4, but op0, op1 are VNx4SI with shape (2, 3) and step = 2 > > Same as case 3? Oops sorry, fixed. The attached patch passes bootstrap+test on aarch64-linux-gnu with and without SVE, and on x86_64-linux-gnu. Thanks, Prathamesh > > Thanks, > Richard > > > + sel = V4SI with values {0, 2, 4, 6} > > + In this case result should be NULL_TREE because we cross input vector > > + boundary at index 4. */ > > + { > > + tree arg0 = build_vec_cst_rand (integer_type_node, 2, 3, 2); > > + tree arg1 = build_vec_cst_rand (integer_type_node, 2, 3, 2); > > + > > + poly_uint64 res_len = 4; > > + tree res_type = build_vector_type (char_type_node, res_len); > > + vec_perm_builder builder (res_len, 4, 1); > > + builder.quick_push (0); > > + builder.quick_push (2); > > + builder.quick_push (4); > > + builder.quick_push (6); > > + > > + vec_perm_indices sel (builder, 2, res_len); > > + const char *reason; > > + tree res = fold_vec_perm_cst (res_type, arg0, arg1, sel, &reason); > > + gcc_assert (res == NULL_TREE); > > + gcc_assert (!strcmp (reason, "cannot divide selector element by arg len")); > > + } > > +} > > + > > +static void > > +test () > > +{ > > + tree vectype = get_preferred_vectype (integer_type_node); > > + if (TYPE_VECTOR_SUBPARTS (vectype).is_constant ()) > > + return; > > + > > + test_dup (); > > + test_stepped (); > > + test_mixed (); > > +} > > +}; > > + > > /* Verify that various binary operations on vectors are folded > > correctly. */ > > > > @@ -16943,6 +17626,7 @@ fold_const_cc_tests () > > test_arithmetic_folding (); > > test_vector_folding (); > > test_vec_duplicate_folding (); > > + test_fold_vec_perm_cst::test (); > > } > > > > } // namespace selftest --0000000000005664650602403c24 Content-Type: text/plain; charset="US-ASCII"; name="gnu-790-v2-13.txt" Content-Disposition: attachment; filename="gnu-790-v2-13.txt" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_lkzemj0z0 ZGlmZiAtLWdpdCBhL2djYy9mb2xkLWNvbnN0LmNjIGIvZ2NjL2ZvbGQtY29uc3QuY2MKaW5kZXgg N2U1NDk0ZGZkMzkuLjY0OGVmNWM2NDdlIDEwMDY0NAotLS0gYS9nY2MvZm9sZC1jb25zdC5jYwor KysgYi9nY2MvZm9sZC1jb25zdC5jYwpAQCAtNDAsNiArNDAsNyBAQCBhbG9uZyB3aXRoIEdDQzsg c2VlIHRoZSBmaWxlIENPUFlJTkczLiAgSWYgbm90IHNlZQogICAgZ2ltcGxlIGNvZGUsIHdlIG5l ZWQgdG8gaGFuZGxlIEdJTVBMRSB0dXBsZXMgYXMgd2VsbCBhcyB0aGVpcgogICAgY29ycmVzcG9u ZGluZyB0cmVlIGVxdWl2YWxlbnRzLiAgKi8KIAorI2RlZmluZSBJTkNMVURFX0FMR09SSVRITQog I2luY2x1ZGUgImNvbmZpZy5oIgogI2luY2x1ZGUgInN5c3RlbS5oIgogI2luY2x1ZGUgImNvcmV0 eXBlcy5oIgpAQCAtMTA0OTQsMTUgKzEwNDk1LDkgQEAgZm9sZF9tdWx0X3pjb25qeiAobG9jYXRp b25fdCBsb2MsIHRyZWUgdHlwZSwgdHJlZSBleHByKQogc3RhdGljIGJvb2wKIHZlY19jc3RfY3Rv cl90b19hcnJheSAodHJlZSBhcmcsIHVuc2lnbmVkIGludCBuZWx0cywgdHJlZSAqZWx0cykKIHsK LSAgdW5zaWduZWQgSE9TVF9XSURFX0lOVCBpLCBudW5pdHM7CisgIHVuc2lnbmVkIEhPU1RfV0lE RV9JTlQgaTsKIAotICBpZiAoVFJFRV9DT0RFIChhcmcpID09IFZFQ1RPUl9DU1QKLSAgICAgICYm IFZFQ1RPUl9DU1RfTkVMVFMgKGFyZykuaXNfY29uc3RhbnQgKCZudW5pdHMpKQotICAgIHsKLSAg ICAgIGZvciAoaSA9IDA7IGkgPCBudW5pdHM7ICsraSkKLQllbHRzW2ldID0gVkVDVE9SX0NTVF9F TFQgKGFyZywgaSk7Ci0gICAgfQotICBlbHNlIGlmIChUUkVFX0NPREUgKGFyZykgPT0gQ09OU1RS VUNUT1IpCisgIGlmIChUUkVFX0NPREUgKGFyZykgPT0gQ09OU1RSVUNUT1IpCiAgICAgewogICAg ICAgY29uc3RydWN0b3JfZWx0ICplbHQ7CiAKQEAgLTEwNTIwLDYgKzEwNTE1LDE4MiBAQCB2ZWNf Y3N0X2N0b3JfdG9fYXJyYXkgKHRyZWUgYXJnLCB1bnNpZ25lZCBpbnQgbmVsdHMsIHRyZWUgKmVs dHMpCiAgIHJldHVybiB0cnVlOwogfQogCisvKiBIZWxwZXIgcm91dGluZSBmb3IgZm9sZF92ZWNf cGVybV9jc3QgdG8gY2hlY2sgaWYgU0VMIGlzIGEgc3VpdGFibGUKKyAgIG1hc2sgZm9yIFZMQSB2 ZWNfcGVybSBmb2xkaW5nLgorICAgUkVBU09OIGlmIHNwZWNpZmllZCwgd2lsbCBjb250YWluIHRo ZSByZWFzb24gd2h5IFNFTCBpcyBub3Qgc3VpdGFibGUuCisgICBVc2VkIG9ubHkgZm9yIGRlYnVn Z2luZyBhbmQgdW5pdC10ZXN0aW5nLiAgKi8KKworc3RhdGljIGJvb2wKK3ZhbGlkX21hc2tfZm9y X2ZvbGRfdmVjX3Blcm1fY3N0X3AgKHRyZWUgYXJnMCwgdHJlZSBhcmcxLAorCQkJCSAgICBjb25z dCB2ZWNfcGVybV9pbmRpY2VzICZzZWwsCisJCQkJICAgIGNvbnN0IGNoYXIgKipyZWFzb24gPSBO VUxMKQoreworICB1bnNpZ25lZCBzZWxfbnBhdHRlcm5zID0gc2VsLmVuY29kaW5nICgpLm5wYXR0 ZXJucyAoKTsKKyAgdW5zaWduZWQgc2VsX25lbHRzX3Blcl9wYXR0ZXJuID0gc2VsLmVuY29kaW5n ICgpLm5lbHRzX3Blcl9wYXR0ZXJuICgpOworCisgIGlmICghKHBvdzJwX2h3aSAoc2VsX25wYXR0 ZXJucykKKwkmJiBwb3cycF9od2kgKFZFQ1RPUl9DU1RfTlBBVFRFUk5TIChhcmcwKSkKKwkmJiBw b3cycF9od2kgKFZFQ1RPUl9DU1RfTlBBVFRFUk5TIChhcmcxKSkpKQorICAgIHsKKyAgICAgIGlm IChyZWFzb24pCisJKnJlYXNvbiA9ICJucGF0dGVybnMgaXMgbm90IHBvd2VyIG9mIDIiOworICAg ICAgcmV0dXJuIGZhbHNlOworICAgIH0KKworICAvKiBXZSB3YW50IHRvIGF2b2lkIGNhc2VzIHdo ZXJlIHNlbC5sZW5ndGggaXMgbm90IGEgbXVsdGlwbGUgb2YgbnBhdHRlcm5zLgorICAgICBGb3Ig ZWc6IHNlbC5sZW5ndGggPSAyICsgMngsIGFuZCBzZWwgbnBhdHRlcm5zID0gNC4gICovCisgIHBv bHlfdWludDY0IGVzZWw7CisgIGlmICghbXVsdGlwbGVfcCAoc2VsLmxlbmd0aCAoKSwgc2VsX25w YXR0ZXJucywgJmVzZWwpKQorICAgIHsKKyAgICAgIGlmIChyZWFzb24pCisJKnJlYXNvbiA9ICJz ZWwubGVuZ3RoIGlzIG5vdCBtdWx0aXBsZSBvZiBzZWxfbnBhdHRlcm5zIjsKKyAgICAgIHJldHVy biBmYWxzZTsKKyAgICB9CisKKyAgaWYgKHNlbF9uZWx0c19wZXJfcGF0dGVybiA8IDMpCisgICAg cmV0dXJuIHRydWU7CisKKyAgZm9yICh1bnNpZ25lZCBwYXR0ZXJuID0gMDsgcGF0dGVybiA8IHNl bF9ucGF0dGVybnM7IHBhdHRlcm4rKykKKyAgICB7CisgICAgICBwb2x5X3VpbnQ2NCBhMSA9IHNl bFtwYXR0ZXJuICsgc2VsX25wYXR0ZXJuc107CisgICAgICBwb2x5X3VpbnQ2NCBhMiA9IHNlbFtw YXR0ZXJuICsgMiAqIHNlbF9ucGF0dGVybnNdOworICAgICAgSE9TVF9XSURFX0lOVCBzdGVwOwor ICAgICAgaWYgKCFwb2x5X2ludDY0IChhMiAtIGExKS5pc19jb25zdGFudCAoJnN0ZXApKQorCXsK KwkgIGlmIChyZWFzb24pCisJICAgICpyZWFzb24gPSAic3RlcCBpcyBub3QgY29uc3RhbnQiOwor CSAgcmV0dXJuIGZhbHNlOworCX0KKyAgICAgIC8vIEZJWE1FOiBQdW50IG9uIHN0ZXAgPCAwIGZv ciBub3csIHJldmlzaXQgbGF0ZXIuCisgICAgICBpZiAoc3RlcCA8IDApCisJcmV0dXJuIGZhbHNl OworICAgICAgaWYgKHN0ZXAgPT0gMCkKKwljb250aW51ZTsKKworICAgICAgaWYgKCFwb3cycF9o d2kgKHN0ZXApKQorCXsKKwkgIGlmIChyZWFzb24pCisJICAgICpyZWFzb24gPSAic3RlcCBpcyBu b3QgcG93ZXIgb2YgMiI7CisJICByZXR1cm4gZmFsc2U7CisJfQorCisgICAgICAvKiBFbnN1cmUg dGhhdCBzdGVwcGVkIHNlcXVlbmNlIG9mIHRoZSBwYXR0ZXJuIHNlbGVjdHMgZWxlbWVudHMKKwkg b25seSBmcm9tIHRoZSBzYW1lIGlucHV0IHZlY3Rvci4gICovCisgICAgICB1aW50NjRfdCBxMSwg cWU7CisgICAgICBwb2x5X3VpbnQ2NCByMSwgcmU7CisgICAgICBwb2x5X3VpbnQ2NCBhZSA9IGEx ICsgKGVzZWwgLSAyKSAqIHN0ZXA7CisgICAgICBwb2x5X3VpbnQ2NCBhcmdfbGVuID0gVFlQRV9W RUNUT1JfU1VCUEFSVFMgKFRSRUVfVFlQRSAoYXJnMCkpOworCisgICAgICBpZiAoIShjYW5fZGl2 X3RydW5jX3AgKGExLCBhcmdfbGVuLCAmcTEsICZyMSkKKwkgICAgJiYgY2FuX2Rpdl90cnVuY19w IChhZSwgYXJnX2xlbiwgJnFlLCAmcmUpCisJICAgICYmIHExID09IHFlKSkKKwl7CisJICBpZiAo cmVhc29uKQorCSAgICAqcmVhc29uID0gImNyb3NzZWQgaW5wdXQgdmVjdG9ycyI7CisJICByZXR1 cm4gZmFsc2U7CisJfQorCisgICAgICAvKiBFbnN1cmUgdGhhdCB0aGUgc3RlcHBlZCBzZXF1ZW5j ZSBhbHdheXMgc2VsZWN0cyBmcm9tIHRoZSBzYW1lCisJIGlucHV0IHBhdHRlcm4uICAqLworICAg ICAgdW5zaWduZWQgYXJnX25wYXR0ZXJucworCT0gKChxMSAmIDApID09IDApID8gVkVDVE9SX0NT VF9OUEFUVEVSTlMgKGFyZzApCisJCQkgIDogVkVDVE9SX0NTVF9OUEFUVEVSTlMgKGFyZzEpOwor CisgICAgICBpZiAoIW11bHRpcGxlX3AgKHN0ZXAsIGFyZ19ucGF0dGVybnMpKQorCXsKKwkgIGlm IChyZWFzb24pCisJICAgICpyZWFzb24gPSAic3RlcCBpcyBub3QgbXVsdGlwbGUgb2YgbnBhdHRl cm5zIjsKKwkgIHJldHVybiBmYWxzZTsKKwl9CisgICAgfQorCisgIHJldHVybiB0cnVlOworfQor CisvKiBUcnkgdG8gZm9sZCBwZXJtdXRhdGlvbiBvZiBBUkcwIGFuZCBBUkcxIHdpdGggU0VMIHNl bGVjdG9yIHdoZW4KKyAgIHRoZSBpbnB1dCB2ZWN0b3JzIGFyZSBWRUNUT1JfQ1NULiBSZXR1cm4g TlVMTF9UUkVFIG90aGVyd2lzZS4KKyAgIFJFQVNPTiBoYXMgc2FtZSBwdXJwb3NlIGFzIGRlc2Ny aWJlZCBpbgorICAgdmFsaWRfbWFza19mb3JfZm9sZF92ZWNfcGVybV9jc3RfcC4gICovCisKKwor c3RhdGljIHRyZWUKK2ZvbGRfdmVjX3Blcm1fY3N0ICh0cmVlIHR5cGUsIHRyZWUgYXJnMCwgdHJl ZSBhcmcxLCBjb25zdCB2ZWNfcGVybV9pbmRpY2VzICZzZWwsCisJCSAgIGNvbnN0IGNoYXIgKipy ZWFzb24gPSBOVUxMKQoreworICB1bnNpZ25lZCByZXNfbnBhdHRlcm5zLCByZXNfbmVsdHNfcGVy X3BhdHRlcm47CisgIHVuc2lnbmVkIEhPU1RfV0lERV9JTlQgcmVzX25lbHRzOworCisgIC8qICgx KSBJZiBTRUwgaXMgYSBzdWl0YWJsZSBtYXNrIGFzIGRldGVybWluZWQgYnkKKyAgICAgdmFsaWRf bWFza19mb3JfZm9sZF92ZWNfcGVybV9jc3RfcCwgdGhlbjoKKyAgICAgcmVzX25wYXR0ZXJucyA9 IG1heCBvZiBucGF0dGVybnMgYmV0d2VlbiBBUkcwLCBBUkcxLCBhbmQgU0VMCisgICAgIHJlc19u ZWx0c19wZXJfcGF0dGVybiA9IG1heCBvZiBuZWx0c19wZXJfcGF0dGVybiBiZXR3ZWVuCisJCQkg ICAgIEFSRzAsIEFSRzEgYW5kIFNFTC4KKyAgICAgKDIpIElmIFNFTCBpcyBub3QgYSBzdWl0YWJs ZSBtYXNrLCBhbmQgVFlQRSBpcyBWTFMgdGhlbjoKKyAgICAgcmVzX25wYXR0ZXJucyA9IG5lbHRz IGluIHJlc3VsdCB2ZWN0b3IuCisgICAgIHJlc19uZWx0c19wZXJfcGF0dGVybiA9IDEuCisgICAg IFRoaXMgZXhjZXB0aW9uIGlzIG1hZGUgc28gdGhhdCBWTFMgQVJHMCwgQVJHMSBhbmQgU0VMIHdv cmsgYXMgYmVmb3JlLiAgKi8KKyAgaWYgKHZhbGlkX21hc2tfZm9yX2ZvbGRfdmVjX3Blcm1fY3N0 X3AgKGFyZzAsIGFyZzEsIHNlbCwgcmVhc29uKSkKKyAgICB7CisgICAgICByZXNfbnBhdHRlcm5z CisJPSBzdGQ6Om1heCAoVkVDVE9SX0NTVF9OUEFUVEVSTlMgKGFyZzApLAorCQkgICAgc3RkOjpt YXggKFZFQ1RPUl9DU1RfTlBBVFRFUk5TIChhcmcxKSwKKwkJCSAgICAgIHNlbC5lbmNvZGluZyAo KS5ucGF0dGVybnMgKCkpKTsKKworICAgICAgcmVzX25lbHRzX3Blcl9wYXR0ZXJuCisJPSBzdGQ6 Om1heCAoVkVDVE9SX0NTVF9ORUxUU19QRVJfUEFUVEVSTiAoYXJnMCksCisJCSAgICBzdGQ6Om1h eCAoVkVDVE9SX0NTVF9ORUxUU19QRVJfUEFUVEVSTiAoYXJnMSksCisJCQkgICAgICBzZWwuZW5j b2RpbmcgKCkubmVsdHNfcGVyX3BhdHRlcm4gKCkpKTsKKworICAgICAgcmVzX25lbHRzID0gcmVz X25wYXR0ZXJucyAqIHJlc19uZWx0c19wZXJfcGF0dGVybjsKKyAgICB9CisgIGVsc2UgaWYgKFRZ UEVfVkVDVE9SX1NVQlBBUlRTICh0eXBlKS5pc19jb25zdGFudCAoJnJlc19uZWx0cykpCisgICAg eworICAgICAgcmVzX25wYXR0ZXJucyA9IHJlc19uZWx0czsKKyAgICAgIHJlc19uZWx0c19wZXJf cGF0dGVybiA9IDE7CisgICAgfQorICBlbHNlCisgICAgcmV0dXJuIE5VTExfVFJFRTsKKworICB0 cmVlX3ZlY3Rvcl9idWlsZGVyIG91dF9lbHRzICh0eXBlLCByZXNfbnBhdHRlcm5zLCByZXNfbmVs dHNfcGVyX3BhdHRlcm4pOworICBmb3IgKHVuc2lnbmVkIGkgPSAwOyBpIDwgcmVzX25lbHRzOyBp KyspCisgICAgeworICAgICAgcG9seV91aW50NjQgbGVuID0gVFlQRV9WRUNUT1JfU1VCUEFSVFMg KFRSRUVfVFlQRSAoYXJnMCkpOworICAgICAgdWludDY0X3QgcTsKKyAgICAgIHBvbHlfdWludDY0 IHI7CisgICAgICB1bnNpZ25lZCBIT1NUX1dJREVfSU5UIGluZGV4OworCisgICAgICAvKiBQdW50 IGlmIHNlbFtpXSAvdHJ1bmNfZGl2IGxlbiBjYW5ub3QgYmUgZGV0ZXJtaW5lZCwKKwkgYmVjYXVz ZSB0aGUgaW5wdXQgdmVjdG9yIHRvIGJlIGNob3NlbiB3aWxsIGRlcGVuZCBvbgorCSBydW50aW1l IHZlY3RvciBsZW5ndGguCisJIEZvciBleGFtcGxlIGlmIGxlbiA9PSA0ICsgNHgsIGFuZCBzZWxb aV0gPT0gNCwKKwkgSWYgbGVuIGF0IHJ1bnRpbWUgZXF1YWxzIDQsIHdlIGNob29zZSBhcmcxWzBd LgorCSBGb3IgYW55IG90aGVyIHZhbHVlIG9mIGxlbiA+IDQgYXQgcnVudGltZSwgd2UgY2hvb3Nl IGFyZzBbNF0uCisJIHdoaWNoIG1ha2VzIHRoZSBlbGVtZW50IGNob2ljZSBkZXBlbmRlbnQgb24g cnVudGltZSB2ZWN0b3IgbGVuZ3RoLiAgKi8KKyAgICAgIGlmICghY2FuX2Rpdl90cnVuY19wIChz ZWxbaV0sIGxlbiwgJnEsICZyKSkKKwl7CisJICBpZiAocmVhc29uKQorCSAgICAqcmVhc29uID0g ImNhbm5vdCBkaXZpZGUgc2VsZWN0b3IgZWxlbWVudCBieSBhcmcgbGVuIjsKKwkgIHJldHVybiBO VUxMX1RSRUU7CisJfQorCisgICAgICAvKiBzZWxbaV0gJSBsZW4gd2lsbCBnaXZlIHRoZSBpbmRl eCBvZiBlbGVtZW50IGluIHRoZSBjaG9zZW4gaW5wdXQKKwkgdmVjdG9yLiBGb3IgZXhhbXBsZSBp ZiBzZWxbaV0gPT0gNSArIDR4IGFuZCBsZW4gPT0gNCArIDR4LAorCSB3ZSB3aWxsIGNob29zZSBh cmcxWzFdIHNpbmNlICg1ICsgNHgpICUgKDQgKyA0eCkgPT0gMS4gICovCisgICAgICBpZiAoIXIu aXNfY29uc3RhbnQgKCZpbmRleCkpCisJeworCSAgaWYgKHJlYXNvbikKKwkgICAgKnJlYXNvbiA9 ICJyZW1haW5kZXIgaXMgbm90IGNvbnN0YW50IjsKKwkgIHJldHVybiBOVUxMX1RSRUU7CisJfQor CisgICAgICB0cmVlIGFyZyA9ICgocSAmIDEpID09IDApID8gYXJnMCA6IGFyZzE7CisgICAgICB0 cmVlIGVsZW0gPSB2ZWN0b3JfY3N0X2VsdCAoYXJnLCBpbmRleCk7CisgICAgICBvdXRfZWx0cy5x dWlja19wdXNoIChlbGVtKTsKKyAgICB9CisKKyAgcmV0dXJuIG91dF9lbHRzLmJ1aWxkICgpOwor fQorCiAvKiBBdHRlbXB0IHRvIGZvbGQgdmVjdG9yIHBlcm11dGF0aW9uIG9mIEFSRzAgYW5kIEFS RzEgdmVjdG9ycyB1c2luZyBTRUwKICAgIHNlbGVjdG9yLiAgUmV0dXJuIHRoZSBmb2xkZWQgVkVD VE9SX0NTVCBvciBDT05TVFJVQ1RPUiBpZiBzdWNjZXNzZnVsLAogICAgTlVMTF9UUkVFIG90aGVy d2lzZS4gICovCkBAIC0xMDUyOSw0MyArMTA3MDAsNDEgQEAgZm9sZF92ZWNfcGVybSAodHJlZSB0 eXBlLCB0cmVlIGFyZzAsIHRyZWUgYXJnMSwgY29uc3QgdmVjX3Blcm1faW5kaWNlcyAmc2VsKQog ewogICB1bnNpZ25lZCBpbnQgaTsKICAgdW5zaWduZWQgSE9TVF9XSURFX0lOVCBuZWx0czsKLSAg Ym9vbCBuZWVkX2N0b3IgPSBmYWxzZTsKIAotICBpZiAoIXNlbC5sZW5ndGggKCkuaXNfY29uc3Rh bnQgKCZuZWx0cykpCi0gICAgcmV0dXJuIE5VTExfVFJFRTsKLSAgZ2NjX2Fzc2VydCAoa25vd25f ZXEgKFRZUEVfVkVDVE9SX1NVQlBBUlRTICh0eXBlKSwgbmVsdHMpCi0JICAgICAgJiYga25vd25f ZXEgKFRZUEVfVkVDVE9SX1NVQlBBUlRTIChUUkVFX1RZUEUgKGFyZzApKSwgbmVsdHMpCi0JICAg ICAgJiYga25vd25fZXEgKFRZUEVfVkVDVE9SX1NVQlBBUlRTIChUUkVFX1RZUEUgKGFyZzEpKSwg bmVsdHMpKTsKKyAgZ2NjX2Fzc2VydCAoa25vd25fZXEgKFRZUEVfVkVDVE9SX1NVQlBBUlRTICh0 eXBlKSwgc2VsLmxlbmd0aCAoKSkKKwkgICAgICAmJiBrbm93bl9lcSAoVFlQRV9WRUNUT1JfU1VC UEFSVFMgKFRSRUVfVFlQRSAoYXJnMCkpLAorCQkJICAgVFlQRV9WRUNUT1JfU1VCUEFSVFMgKFRS RUVfVFlQRSAoYXJnMSkpKSk7CisKICAgaWYgKFRSRUVfVFlQRSAoVFJFRV9UWVBFIChhcmcwKSkg IT0gVFJFRV9UWVBFICh0eXBlKQogICAgICAgfHwgVFJFRV9UWVBFIChUUkVFX1RZUEUgKGFyZzEp KSAhPSBUUkVFX1RZUEUgKHR5cGUpKQogICAgIHJldHVybiBOVUxMX1RSRUU7CiAKKyAgaWYgKFRS RUVfQ09ERSAoYXJnMCkgPT0gVkVDVE9SX0NTVAorICAgICAgJiYgVFJFRV9DT0RFIChhcmcxKSA9 PSBWRUNUT1JfQ1NUKQorICAgIHJldHVybiBmb2xkX3ZlY19wZXJtX2NzdCAodHlwZSwgYXJnMCwg YXJnMSwgc2VsKTsKKworICAvKiBGb3IgZmFsbCBiYWNrIGNhc2UsIHdlIHdhbnQgdG8gZW5zdXJl IHdlIGhhdmUgVkxTIHZlY3RvcnMKKyAgICAgd2l0aCBlcXVhbCBsZW5ndGguICAqLworICBpZiAo IXNlbC5sZW5ndGggKCkuaXNfY29uc3RhbnQgKCZuZWx0cykpCisgICAgcmV0dXJuIE5VTExfVFJF RTsKKworICBnY2NfYXNzZXJ0IChrbm93bl9lcSAoc2VsLmxlbmd0aCAoKSwKKwkJCVRZUEVfVkVD VE9SX1NVQlBBUlRTIChUUkVFX1RZUEUgKGFyZzApKSkpOwogICB0cmVlICppbl9lbHRzID0gWEFM TE9DQVZFQyAodHJlZSwgbmVsdHMgKiAyKTsKICAgaWYgKCF2ZWNfY3N0X2N0b3JfdG9fYXJyYXkg KGFyZzAsIG5lbHRzLCBpbl9lbHRzKQogICAgICAgfHwgIXZlY19jc3RfY3Rvcl90b19hcnJheSAo YXJnMSwgbmVsdHMsIGluX2VsdHMgKyBuZWx0cykpCiAgICAgcmV0dXJuIE5VTExfVFJFRTsKIAot ICB0cmVlX3ZlY3Rvcl9idWlsZGVyIG91dF9lbHRzICh0eXBlLCBuZWx0cywgMSk7CisgIHZlYzxj b25zdHJ1Y3Rvcl9lbHQsIHZhX2djPiAqdjsKKyAgdmVjX2FsbG9jICh2LCBuZWx0cyk7CiAgIGZv ciAoaSA9IDA7IGkgPCBuZWx0czsgaSsrKQogICAgIHsKICAgICAgIEhPU1RfV0lERV9JTlQgaW5k ZXg7CiAgICAgICBpZiAoIXNlbFtpXS5pc19jb25zdGFudCAoJmluZGV4KSkKIAlyZXR1cm4gTlVM TF9UUkVFOwotICAgICAgaWYgKCFDT05TVEFOVF9DTEFTU19QIChpbl9lbHRzW2luZGV4XSkpCi0J bmVlZF9jdG9yID0gdHJ1ZTsKLSAgICAgIG91dF9lbHRzLnF1aWNrX3B1c2ggKHVuc2hhcmVfZXhw ciAoaW5fZWx0c1tpbmRleF0pKTsKLSAgICB9Ci0KLSAgaWYgKG5lZWRfY3RvcikKLSAgICB7Ci0g ICAgICB2ZWM8Y29uc3RydWN0b3JfZWx0LCB2YV9nYz4gKnY7Ci0gICAgICB2ZWNfYWxsb2MgKHYs IG5lbHRzKTsKLSAgICAgIGZvciAoaSA9IDA7IGkgPCBuZWx0czsgaSsrKQotCUNPTlNUUlVDVE9S X0FQUEVORF9FTFQgKHYsIE5VTExfVFJFRSwgb3V0X2VsdHNbaV0pOwotICAgICAgcmV0dXJuIGJ1 aWxkX2NvbnN0cnVjdG9yICh0eXBlLCB2KTsKKyAgICAgIENPTlNUUlVDVE9SX0FQUEVORF9FTFQg KHYsIE5VTExfVFJFRSwgaW5fZWx0c1tpbmRleF0pOwogICAgIH0KLSAgZWxzZQotICAgIHJldHVy biBvdXRfZWx0cy5idWlsZCAoKTsKKyAgcmV0dXJuIGJ1aWxkX2NvbnN0cnVjdG9yICh0eXBlLCB2 KTsKIH0KIAogLyogVHJ5IHRvIGZvbGQgYSBwb2ludGVyIGRpZmZlcmVuY2Ugb2YgdHlwZSBUWVBF IHR3byBhZGRyZXNzIGV4cHJlc3Npb25zIG9mCkBAIC0xNjg5Miw2ICsxNzA2MSw1NTQgQEAgdGVz dF9hcml0aG1ldGljX2ZvbGRpbmcgKCkKIAkJCQkgICB4KTsKIH0KIAorbmFtZXNwYWNlIHRlc3Rf Zm9sZF92ZWNfcGVybV9jc3QgeworCisvKiBCdWlsZCBhIFZFQ1RPUl9DU1QgY29ycmVzcG9uZGlu ZyB0byBWTU9ERSwgYW5kIGhhcworICAgZW5jb2RpbmcgZ2l2ZW4gYnkgTlBBVFRFUk5TLCBORUxU U19QRVJfUEFUVEVSTiBhbmQgU1RFUC4KKyAgIEZpbGwgaXQgd2l0aCByYW5kb21pemVkIGVsZW1l bnRzLCB1c2luZyByYW5kKCkgJSBUSFJFU0hPTEQuICAqLworCitzdGF0aWMgdHJlZQorYnVpbGRf dmVjX2NzdF9yYW5kIChtYWNoaW5lX21vZGUgdm1vZGUsIHVuc2lnbmVkIG5wYXR0ZXJucywKKwkJ ICAgIHVuc2lnbmVkIG5lbHRzX3Blcl9wYXR0ZXJuLAorCQkgICAgaW50IHN0ZXAgPSAwLCBpbnQg dGhyZXNob2xkID0gMTAwKQoreworICB0cmVlIGlubmVyX3R5cGUgPSBsYW5nX2hvb2tzLnR5cGVz LnR5cGVfZm9yX21vZGUgKEdFVF9NT0RFX0lOTkVSICh2bW9kZSksIDEpOworICB0cmVlIHZlY3R5 cGUgPSBidWlsZF92ZWN0b3JfdHlwZV9mb3JfbW9kZSAoaW5uZXJfdHlwZSwgdm1vZGUpOworICB0 cmVlX3ZlY3Rvcl9idWlsZGVyIGJ1aWxkZXIgKHZlY3R5cGUsIG5wYXR0ZXJucywgbmVsdHNfcGVy X3BhdHRlcm4pOworCisgIC8vIEZpbGwgYTAgZm9yIGVhY2ggcGF0dGVybgorICBmb3IgKHVuc2ln bmVkIGkgPSAwOyBpIDwgbnBhdHRlcm5zOyBpKyspCisgICAgYnVpbGRlci5xdWlja19wdXNoIChi dWlsZF9pbnRfY3N0IChpbm5lcl90eXBlLCByYW5kICgpICUgdGhyZXNob2xkKSk7CisKKyAgaWYg KG5lbHRzX3Blcl9wYXR0ZXJuID09IDEpCisgICAgcmV0dXJuIGJ1aWxkZXIuYnVpbGQgKCk7CisK KyAgLy8gRmlsbCBhMSBmb3IgZWFjaCBwYXR0ZXJuCisgIGZvciAodW5zaWduZWQgaSA9IDA7IGkg PCBucGF0dGVybnM7IGkrKykKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKGJ1aWxkX2ludF9jc3Qg KGlubmVyX3R5cGUsIHJhbmQgKCkgJSB0aHJlc2hvbGQpKTsKKworICBpZiAobmVsdHNfcGVyX3Bh dHRlcm4gPT0gMikKKyAgICByZXR1cm4gYnVpbGRlci5idWlsZCAoKTsKKworICBmb3IgKHVuc2ln bmVkIGkgPSBucGF0dGVybnMgKiAyOyBpIDwgbnBhdHRlcm5zICogbmVsdHNfcGVyX3BhdHRlcm47 IGkrKykKKyAgICB7CisgICAgICB0cmVlIHByZXZfZWxlbSA9IGJ1aWxkZXJbaSAtIG5wYXR0ZXJu c107CisgICAgICBpbnQgcHJldl9lbGVtX3ZhbCA9IFRSRUVfSU5UX0NTVF9MT1cgKHByZXZfZWxl bSk7CisgICAgICBpbnQgdmFsID0gcHJldl9lbGVtX3ZhbCArIHN0ZXA7CisgICAgICBidWlsZGVy LnF1aWNrX3B1c2ggKGJ1aWxkX2ludF9jc3QgKGlubmVyX3R5cGUsIHZhbCkpOworICAgIH0KKwor ICByZXR1cm4gYnVpbGRlci5idWlsZCAoKTsKK30KKworLyogVmFsaWRhdGUgcmVzdWx0IG9mIFZF Q19QRVJNX0VYUFIgZm9sZGluZyBmb3IgdGhlIHVuaXQtdGVzdHMgYmVsb3csCisgICB3aGVuIHJl c3VsdCBpcyBWTEEuICAqLworCitzdGF0aWMgdm9pZAordmFsaWRhdGVfcmVzICh1bnNpZ25lZCBu cGF0dGVybnMsIHVuc2lnbmVkIG5lbHRzX3Blcl9wYXR0ZXJuLAorCSAgICAgIHRyZWUgcmVzLCB0 cmVlICpleHBlY3RlZF9yZXMpCit7CisgIC8qIEFjdHVhbCBucGF0dGVybnMgLyBuZWx0c19wZXJf cGF0dGVybiBpbiByZXMgbWF5IGJlIGxlc3MgdGhhbiBleHBlY3RlZCBkdWUKKyAgICAgdG8gY2Fu b25pY2FsaXphdGlvbi4gICovCisgIEFTU0VSVF9UUlVFIChWRUNUT1JfQ1NUX05QQVRURVJOUyAo cmVzKSA8PSBucGF0dGVybnMpOworICBBU1NFUlRfVFJVRSAoVkVDVE9SX0NTVF9ORUxUU19QRVJf UEFUVEVSTiAocmVzKSA8PSBuZWx0c19wZXJfcGF0dGVybik7CisKKyAgZm9yICh1bnNpZ25lZCBp ID0gMDsgaSA8IG5wYXR0ZXJucyAqIG5lbHRzX3Blcl9wYXR0ZXJuOyBpKyspCisgICAgQVNTRVJU X1RSVUUgKG9wZXJhbmRfZXF1YWxfcCAoVkVDVE9SX0NTVF9FTFQgKHJlcywgaSksIGV4cGVjdGVk X3Jlc1tpXSwgMCkpOworfQorCisvKiBWYWxpZGF0ZSByZXN1bHQgb2YgVkVDX1BFUk1fRVhQUiBm b2xkaW5nIGZvciB0aGUgdW5pdC10ZXN0cyBiZWxvdywKKyAgIHdoZW4gdGhlIHJlc3VsdCBpcyBW TFMuICAqLworCitzdGF0aWMgdm9pZAordmFsaWRhdGVfcmVzX3ZscyAodHJlZSByZXMsIHRyZWUg KmV4cGVjdGVkX3JlcywgdW5zaWduZWQgZXhwZWN0ZWRfbmVsdHMpCit7CisgIEFTU0VSVF9UUlVF IChrbm93bl9lcSAoVkVDVE9SX0NTVF9ORUxUUyAocmVzKSwgZXhwZWN0ZWRfbmVsdHMpKTsKKyAg Zm9yICh1bnNpZ25lZCBpID0gMDsgaSA8IGV4cGVjdGVkX25lbHRzOyBpKyspCisgICAgQVNTRVJU X1RSVUUgKG9wZXJhbmRfZXF1YWxfcCAoVkVDVE9SX0NTVF9FTFQgKHJlcywgaSksIGV4cGVjdGVk X3Jlc1tpXSwgMCkpOworfQorCisvKiBUZXN0IGNhc2VzIHdoZXJlIHJlc3VsdCBhbmQgaW5wdXQg dmVjdG9ycyBhcmUgVk54NFNJICAqLworCitzdGF0aWMgdm9pZAordGVzdF92bng0c2kgKG1hY2hp bmVfbW9kZSB2bW9kZSkKK3sKKyAgLyogQ2FzZSAxOiBtYXNrID0gezAsIC4uLn0gKi8KKyAgewor ICAgIHRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDIsIDMsIDEpOworICAg IHRyZWUgYXJnMSA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDIsIDMsIDEpOworICAgIHBv bHlfdWludDY0IGxlbiA9IFRZUEVfVkVDVE9SX1NVQlBBUlRTIChUUkVFX1RZUEUgKGFyZzApKTsK KworICAgIHZlY19wZXJtX2J1aWxkZXIgYnVpbGRlciAobGVuLCAxLCAxKTsKKyAgICBidWlsZGVy LnF1aWNrX3B1c2ggKDApOworICAgIHZlY19wZXJtX2luZGljZXMgc2VsIChidWlsZGVyLCAyLCBs ZW4pOworICAgIHRyZWUgcmVzID0gZm9sZF92ZWNfcGVybV9jc3QgKFRSRUVfVFlQRSAoYXJnMCks IGFyZzAsIGFyZzEsIHNlbCk7CisKKyAgICB0cmVlIGV4cGVjdGVkX3Jlc1tdID0geyB2ZWN0b3Jf Y3N0X2VsdCAocmVzLCAwKSB9OworICAgIHZhbGlkYXRlX3JlcyAoMSwgMSwgcmVzLCBleHBlY3Rl ZF9yZXMpOworICB9CisKKyAgLyogQ2FzZSAyOiBtYXNrID0ge2xlbiwgLi4ufSAqLworICB7Cisg ICAgdHJlZSBhcmcwID0gYnVpbGRfdmVjX2NzdF9yYW5kICh2bW9kZSwgMiwgMywgMSk7CisgICAg dHJlZSBhcmcxID0gYnVpbGRfdmVjX2NzdF9yYW5kICh2bW9kZSwgMiwgMywgMSk7CisgICAgcG9s eV91aW50NjQgbGVuID0gVFlQRV9WRUNUT1JfU1VCUEFSVFMgKFRSRUVfVFlQRSAoYXJnMCkpOwor CisgICAgdmVjX3Blcm1fYnVpbGRlciBidWlsZGVyIChsZW4sIDEsIDEpOworICAgIGJ1aWxkZXIu cXVpY2tfcHVzaCAobGVuKTsKKyAgICB2ZWNfcGVybV9pbmRpY2VzIHNlbCAoYnVpbGRlciwgMiwg bGVuKTsKKyAgICB0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVFX1RZUEUgKGFyZzAp LCBhcmcwLCBhcmcxLCBzZWwpOworCisgICAgdHJlZSBleHBlY3RlZF9yZXNbXSA9IHsgdmVjdG9y X2NzdF9lbHQgKGFyZzEsIDApIH07CisgICAgdmFsaWRhdGVfcmVzICgxLCAxLCByZXMsIGV4cGVj dGVkX3Jlcyk7CisgIH0KKworICAvKiBDYXNlIDM6IG1hc2sgPSB7IDAsIGxlbiwgLi4uIH0gKi8K KyAgeworICAgIHRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDIsIDMsIDEp OworICAgIHRyZWUgYXJnMSA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDIsIDMsIDEpOwor ICAgIHBvbHlfdWludDY0IGxlbiA9IFRZUEVfVkVDVE9SX1NVQlBBUlRTIChUUkVFX1RZUEUgKGFy ZzApKTsKKworICAgIHZlY19wZXJtX2J1aWxkZXIgYnVpbGRlciAobGVuLCAyLCAxKTsKKyAgICBi dWlsZGVyLnF1aWNrX3B1c2ggKDApOworICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAobGVuKTsKKyAg ICB2ZWNfcGVybV9pbmRpY2VzIHNlbCAoYnVpbGRlciwgMiwgbGVuKTsKKyAgICB0cmVlIHJlcyA9 IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVFX1RZUEUgKGFyZzApLCBhcmcwLCBhcmcxLCBzZWwpOwor CisgICAgdHJlZSBleHBlY3RlZF9yZXNbXSA9IHsgdmVjdG9yX2NzdF9lbHQgKGFyZzAsIDApLCB2 ZWN0b3JfY3N0X2VsdCAoYXJnMSwgMCkgfTsKKyAgICB2YWxpZGF0ZV9yZXMgKDIsIDEsIHJlcywg ZXhwZWN0ZWRfcmVzKTsKKyAgfQorCisgIC8qIENhc2UgNDogbWFzayA9IHsgMCwgbGVuLCAxLCBs ZW4rMSwgLi4uIH0gKi8KKyAgeworICAgIHRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAo dm1vZGUsIDIsIDMsIDEpOworICAgIHRyZWUgYXJnMSA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1v ZGUsIDIsIDMsIDEpOworICAgIHBvbHlfdWludDY0IGxlbiA9IFRZUEVfVkVDVE9SX1NVQlBBUlRT IChUUkVFX1RZUEUgKGFyZzApKTsKKworICAgIHZlY19wZXJtX2J1aWxkZXIgYnVpbGRlciAobGVu LCAyLCAyKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKDApOworICAgIGJ1aWxkZXIucXVpY2tf cHVzaCAobGVuKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKDEpOworICAgIGJ1aWxkZXIucXVp Y2tfcHVzaCAobGVuICsgMSk7CisgICAgdmVjX3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIs IGxlbik7CisgICAgdHJlZSByZXMgPSBmb2xkX3ZlY19wZXJtX2NzdCAoVFJFRV9UWVBFIChhcmcw KSwgYXJnMCwgYXJnMSwgc2VsKTsKKworICAgIHRyZWUgZXhwZWN0ZWRfcmVzW10gPSB7IHZlY3Rv cl9jc3RfZWx0IChhcmcwLCAwKSwgdmVjdG9yX2NzdF9lbHQgKGFyZzEsIDApLAorCQkJICAgIHZl Y3Rvcl9jc3RfZWx0IChhcmcwLCAxKSwgdmVjdG9yX2NzdF9lbHQgKGFyZzEsIDEpCisJCQkgIH07 CisgICAgdmFsaWRhdGVfcmVzICgyLCAyLCByZXMsIGV4cGVjdGVkX3Jlcyk7CisgIH0KKworICAv KiBDYXNlIDU6IG1hc2sgPSB7IDAsIGxlbiwgMSwgbGVuKzEsIC4uLi4gfQorICAgICBucGF0dGVy bnMgPSA0LCBuZWx0c19wZXJfcGF0dGVybiA9IDEgKi8KKyAgeworICAgIHRyZWUgYXJnMCA9IGJ1 aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDIsIDMsIDEpOworICAgIHRyZWUgYXJnMSA9IGJ1aWxk X3ZlY19jc3RfcmFuZCAodm1vZGUsIDIsIDMsIDEpOworICAgIHBvbHlfdWludDY0IGxlbiA9IFRZ UEVfVkVDVE9SX1NVQlBBUlRTIChUUkVFX1RZUEUgKGFyZzApKTsKKworICAgIHZlY19wZXJtX2J1 aWxkZXIgYnVpbGRlciAobGVuLCA0LCAxKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKDApOwor ICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAobGVuKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKDEp OworICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAobGVuICsgMSk7CisgICAgdmVjX3Blcm1faW5kaWNl cyBzZWwgKGJ1aWxkZXIsIDIsIGxlbik7CisgICAgdHJlZSByZXMgPSBmb2xkX3ZlY19wZXJtX2Nz dCAoVFJFRV9UWVBFIChhcmcwKSwgYXJnMCwgYXJnMSwgc2VsKTsKKworICAgIHRyZWUgZXhwZWN0 ZWRfcmVzW10gPSB7IHZlY3Rvcl9jc3RfZWx0IChhcmcwLCAwKSwgdmVjdG9yX2NzdF9lbHQgKGFy ZzEsIDApLAorCQkJICAgIHZlY3Rvcl9jc3RfZWx0IChhcmcwLCAxKSwgdmVjdG9yX2NzdF9lbHQg KGFyZzEsIDEpCisJCQkgIH07CisgICAgdmFsaWRhdGVfcmVzICg0LCAxLCByZXMsIGV4cGVjdGVk X3Jlcyk7CisgIH0KKworICAvKiBDYXNlIDY6IG1hc2sgPSB7MCwgNCwgLi4ufQorICAgICBucGF0 dGVybnMgPSAxLCBuZWx0c19wZXJfcGF0dGVybiA9IDIuCisgICAgIFRoaXMgc2hvdWxkIHJldHVy biBOVUxMX1RSRUUgYmVjYXVzZSB0aGUgaW5kZXggNCBtYXkgY2hvb3NlCisgICAgIGZyb20gZWl0 aGVyIGFyZzAgb3IgYXJnMSBkZXBlbmRpbmcgb24gdmVjdG9yIGxlbmd0aC4gICovCisgIHsKKyAg ICB0cmVlIGFyZzAgPSBidWlsZF92ZWNfY3N0X3JhbmQgKHZtb2RlLCAyLCAzLCAxKTsKKyAgICB0 cmVlIGFyZzEgPSBidWlsZF92ZWNfY3N0X3JhbmQgKHZtb2RlLCAyLCAzLCAxKTsKKyAgICBwb2x5 X3VpbnQ2NCBsZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAoVFJFRV9UWVBFIChhcmcwKSk7CisK KyAgICB2ZWNfcGVybV9idWlsZGVyIGJ1aWxkZXIgKGxlbiwgMSwgMik7CisgICAgYnVpbGRlci5x dWlja19wdXNoICgwKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKDQpOworICAgIHZlY19wZXJt X2luZGljZXMgc2VsIChidWlsZGVyLCAyLCBsZW4pOworICAgIHRyZWUgcmVzID0gZm9sZF92ZWNf cGVybV9jc3QgKFRSRUVfVFlQRSAoYXJnMCksIGFyZzAsIGFyZzEsIHNlbCk7CisgICAgQVNTRVJU X1RSVUUgKHJlcyA9PSBOVUxMX1RSRUUpOworICB9CisKKyAgLyogQ2FzZSA3OiBucGF0dGVybnMo YXJnMCkgPSA0ID4gbnBhdHRlcm5zKHNlbCkgPSAyCisgICAgIG1hc2sgPSB7MCwgbGVuLCAxLCBs ZW4gKyAxLCAuLi59CisgICAgIHNlbF9ucGF0dGVybnMgPSAyLCBzZWxfbmVsdHNfcGVyX3BhdHRl cm4gPSAyLiAgKi8KKyAgeworICAgIHRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1v ZGUsIDIsIDMsIDEpOworICAgIHRyZWUgYXJnMSA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUs IDIsIDMsIDEpOworICAgIHBvbHlfdWludDY0IGFyZzBfbGVuID0gVFlQRV9WRUNUT1JfU1VCUEFS VFMgKFRSRUVfVFlQRSAoYXJnMCkpOworCisgICAgdmVjX3Blcm1fYnVpbGRlciBidWlsZGVyIChh cmcwX2xlbiwgMiwgMik7CisgICAgYnVpbGRlci5xdWlja19wdXNoICgwKTsKKyAgICBidWlsZGVy LnF1aWNrX3B1c2ggKGFyZzBfbGVuKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKDEpOworICAg IGJ1aWxkZXIucXVpY2tfcHVzaCAoYXJnMF9sZW4gKyAxKTsKKyAgICB2ZWNfcGVybV9pbmRpY2Vz IHNlbCAoYnVpbGRlciwgMiwgYXJnMF9sZW4pOworICAgIHRyZWUgcmVzID0gZm9sZF92ZWNfcGVy bV9jc3QgKFRSRUVfVFlQRSAoYXJnMCksIGFyZzAsIGFyZzEsIHNlbCk7CisKKyAgICB0cmVlIGV4 cGVjdGVkX3Jlc1tdID0geyB2ZWN0b3JfY3N0X2VsdCAoYXJnMCwgMCksIHZlY3Rvcl9jc3RfZWx0 IChhcmcxLCAwKSwKKwkJCSAgICB2ZWN0b3JfY3N0X2VsdCAoYXJnMCwgMSksIHZlY3Rvcl9jc3Rf ZWx0IChhcmcxLCAxKQorCQkJICB9OworICAgIHZhbGlkYXRlX3JlcyAoMiwgMiwgcmVzLCBleHBl Y3RlZF9yZXMpOworICB9CisKKyAgLyogQ2FzZSA4OiBzZWwgPSB7MCwgMSwgMiwgLi4ufQorICAg ICBucGF0dGVybnMgPSAxLCBuZWx0c19wZXJfcGF0dGVybiA9IDMKKyAgICAgZXhwZWN0ZWQgcmVz OiB7IGFyZzBbMF0sIGFyZzBbMV0sIGFyZzBbMl0sIC4uLiB9ICovCisgIHsKKyAgICB0cmVlIGFy ZzAgPSBidWlsZF92ZWNfY3N0X3JhbmQgKHZtb2RlLCAxLCAzLCAyKTsKKyAgICB0cmVlIGFyZzEg PSBidWlsZF92ZWNfY3N0X3JhbmQgKHZtb2RlLCAxLCAzLCAyKTsKKyAgICBwb2x5X3VpbnQ2NCBh cmcwX2xlbiA9IFRZUEVfVkVDVE9SX1NVQlBBUlRTIChUUkVFX1RZUEUgKGFyZzApKTsKKworICAg IHZlY19wZXJtX2J1aWxkZXIgYnVpbGRlciAoYXJnMF9sZW4sIDEsIDMpOworICAgIGJ1aWxkZXIu cXVpY2tfcHVzaCAoMCk7CisgICAgYnVpbGRlci5xdWlja19wdXNoICgxKTsKKyAgICBidWlsZGVy LnF1aWNrX3B1c2ggKDIpOworCisgICAgdmVjX3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIs IGFyZzBfbGVuKTsKKyAgICB0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVFX1RZUEUg KGFyZzApLCBhcmcwLCBhcmcxLCBzZWwpOworICAgIHRyZWUgZXhwZWN0ZWRfcmVzW10gPSB7IHZl Y3Rvcl9jc3RfZWx0IChhcmcwLCAwKSwgdmVjdG9yX2NzdF9lbHQgKGFyZzAsIDEpLAorCQkJICAg IHZlY3Rvcl9jc3RfZWx0IChhcmcwLCAyKSB9OworICAgIHZhbGlkYXRlX3JlcyAoMSwgMywgcmVz LCBleHBlY3RlZF9yZXMpOworICB9CisKKyAgLyogQ2FzZSA5OiBzZWwgPSB7bGVuLCBsZW4gKyAx LCBsZW4gKyAyLCAuLi4gfQorICAgICBucGF0dGVybnMgPSAxLCBuZWx0c19wZXJfcGF0dGVybiA9 IDMKKyAgICAgZXhwZWN0ZWQgcmVzOiB7IG9wMVswXSwgb3AxWzFdLCBvcDFbMl0sIC4uLiB9ICAq LworICB7CisgICAgdHJlZSBhcmcwID0gYnVpbGRfdmVjX2NzdF9yYW5kICh2bW9kZSwgMSwgMywg Mik7CisgICAgdHJlZSBhcmcxID0gYnVpbGRfdmVjX2NzdF9yYW5kICh2bW9kZSwgMSwgMywgMik7 CisgICAgcG9seV91aW50NjQgYXJnMF9sZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAoVFJFRV9U WVBFIChhcmcwKSk7CisKKyAgICB2ZWNfcGVybV9idWlsZGVyIGJ1aWxkZXIgKGFyZzBfbGVuLCAx LCAzKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKGFyZzBfbGVuKTsKKyAgICBidWlsZGVyLnF1 aWNrX3B1c2ggKGFyZzBfbGVuICsgMSk7CisgICAgYnVpbGRlci5xdWlja19wdXNoIChhcmcwX2xl biArIDIpOworCisgICAgdmVjX3Blcm1faW5kaWNlcyBzZWwgKGJ1aWxkZXIsIDIsIGFyZzBfbGVu KTsKKyAgICB0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVFX1RZUEUgKGFyZzApLCBh cmcwLCBhcmcxLCBzZWwsIE5VTEwpOworICAgIHRyZWUgZXhwZWN0ZWRfcmVzW10gPSB7IHZlY3Rv cl9jc3RfZWx0IChhcmcxLCAwKSwgdmVjdG9yX2NzdF9lbHQgKGFyZzEsIDEpLAorCQkJICAgIHZl Y3Rvcl9jc3RfZWx0IChhcmcxLCAyKSB9OworICAgIHZhbGlkYXRlX3JlcyAoMSwgMywgcmVzLCBl eHBlY3RlZF9yZXMpOworICB9Cit9CisKKy8qIFRlc3QgY2FzZXMgd2hlcmUgcmVzdWx0IGFuZCBp bnB1dCB2ZWN0b3JzIGFyZSBWTngxNlFJICAqLworCitzdGF0aWMgdm9pZAordGVzdF92bngxNnFp IChtYWNoaW5lX21vZGUgdm1vZGUpCit7CisgIC8qIENhc2UgMTogTGVhZGluZyBlbGVtZW50IG9m IGFyZzEsIHN0ZXBwZWQgc2VxdWVuY2U6IHBhdHRlcm4gMCBvZiBhcmcwLgorICAgICBzZWwgPSB7 bGVuLCAwLCAwLCAwLCAyLCAwLCAuLi59CisgICAgIG5wYXR0ZXJucyA9IDIsIG5lbHRzX3Blcl9w YXR0ZXJuID0gMy4KKyAgICAgVXNlIGV4dHJhIHBhdHRlcm4gezAsIC4uLn0gdG8gbG93ZXIgbnVt YmVyIG9mIGVsZW1lbnRzIHBlciBwYXR0ZXJuLiAgKi8KKyAgeworICAgIHRyZWUgYXJnMCA9IGJ1 aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDEsIDMsIDIpOworICAgIHRyZWUgYXJnMSA9IGJ1aWxk X3ZlY19jc3RfcmFuZCAodm1vZGUsIDEsIDMsIDIpOworICAgIHBvbHlfdWludDY0IGFyZzBfbGVu ID0gVFlQRV9WRUNUT1JfU1VCUEFSVFMgKFRSRUVfVFlQRSAoYXJnMCkpOworCisgICAgdmVjX3Bl cm1fYnVpbGRlciBidWlsZGVyIChhcmcwX2xlbiwgMiwgMyk7CisgICAgYnVpbGRlci5xdWlja19w dXNoIChhcmcwX2xlbik7CisgICAgaW50IG1hc2tfZWxlbXNbXSA9IHsgMCwgMCwgMCwgMiwgMCB9 OworICAgIGZvciAoaW50IGkgPSAwOyBpIDwgNTsgaSsrKQorICAgICAgYnVpbGRlci5xdWlja19w dXNoIChtYXNrX2VsZW1zW2ldKTsKKworICAgIHZlY19wZXJtX2luZGljZXMgc2VsIChidWlsZGVy LCAyLCBhcmcwX2xlbik7CisgICAgY29uc3QgY2hhciAqcmVhc29uOworICAgIHRyZWUgcmVzID0g Zm9sZF92ZWNfcGVybV9jc3QgKFRSRUVfVFlQRSAoYXJnMCksIGFyZzAsIGFyZzEsIHNlbCwgJnJl YXNvbik7CisKKyAgICB0cmVlIGV4cGVjdGVkX3Jlc1tdID0geyB2ZWN0b3JfY3N0X2VsdCAoYXJn MSwgMCksIHZlY3Rvcl9jc3RfZWx0IChhcmcwLCAwKSwKKwkJCSAgICB2ZWN0b3JfY3N0X2VsdCAo YXJnMCwgMCksIHZlY3Rvcl9jc3RfZWx0IChhcmcwLCAwKSwKKwkJCSAgICB2ZWN0b3JfY3N0X2Vs dCAoYXJnMCwgMiksIHZlY3Rvcl9jc3RfZWx0IChhcmcwLCAwKQorCQkJICB9OworICAgIHZhbGlk YXRlX3JlcyAoMiwgMywgcmVzLCBleHBlY3RlZF9yZXMpOworICB9CisKKyAgLyogQ2FzZSAyOgor ICAgICBzZWwgPSB7IGxlbiwgMCwgMiwgLi4uIH0gbnBhdHRlcm5zID0gMSwgbmVsdHNfcGVyX3Bh dHRlcm4gPSAzLgorICAgICBUaGlzIHNob3VsZCByZXR1cm4gTlVMTCBiZWNhdXNlIHdlIGNyb3Nz IHRoZSBpbnB1dCB2ZWN0b3JzLgorICAgICBCZWNhdXNlLAorICAgICBhcmcwX2xlbiA9IDE2ICsg MTZ4CisgICAgIGExID0gMAorICAgICBTID0gMgorICAgICBlc2VsID0gYXJnMF9sZW4gLyBucGF0 dGVybnNfc2VsID0gMTYrMTZ4LzEgPSAxNiArIDE2eAorICAgICBhZSA9IDAgKyAoZXNlbCAtIDIp ICogUworCT0gMCArICgxNiArIDE2eCAtIDIpICogMgorCT0gMjggKyAzMngKKyAgICAgTGV0IHEx ID0gYTEgLyBhcmcwX2xlbiA9IDAgL3RydW5jICgxNiArIDE2eCkgPSAwCisgICAgIExldCBxZSA9 IGFlIC8gYXJnMF9sZW4gPSAoMjggKyAzMngpIC90cnVuYyAoMTYgKyAxNngpID0gMS4KKyAgICAg U2luY2UgcTEgIT0gcWUsIHdlIGNyb3NzIGlucHV0IHZlY3RvcnMuCisgICAgIFNvIHJldHVybiBO VUxMX1RSRUUuICAqLworICB7CisgICAgdHJlZSBhcmcwID0gYnVpbGRfdmVjX2NzdF9yYW5kICh2 bW9kZSwgMSwgMywgMik7CisgICAgdHJlZSBhcmcxID0gYnVpbGRfdmVjX2NzdF9yYW5kICh2bW9k ZSwgMSwgMywgMik7CisgICAgcG9seV91aW50NjQgYXJnMF9sZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQ QVJUUyAoVFJFRV9UWVBFIChhcmcwKSk7CisKKyAgICB2ZWNfcGVybV9idWlsZGVyIGJ1aWxkZXIg KGFyZzBfbGVuLCAxLCAzKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKGFyZzBfbGVuKTsKKyAg ICBidWlsZGVyLnF1aWNrX3B1c2ggKDApOworICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAoMik7CisK KyAgICB2ZWNfcGVybV9pbmRpY2VzIHNlbCAoYnVpbGRlciwgMiwgYXJnMF9sZW4pOworICAgIGNv bnN0IGNoYXIgKnJlYXNvbjsKKyAgICB0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVF X1RZUEUgKGFyZzApLCBhcmcwLCBhcmcxLCBzZWwsICZyZWFzb24pOworICAgIEFTU0VSVF9UUlVF IChyZXMgPT0gTlVMTF9UUkVFKTsKKyAgICBBU1NFUlRfVFJVRSAoIXN0cmNtcCAocmVhc29uLCAi Y3Jvc3NlZCBpbnB1dCB2ZWN0b3JzIikpOworICB9CisKKyAgLyogQ2FzZSAzOiBTZWxlY3QgZWxl bWVudHMgZnJvbSBkaWZmZXJlbnQgcGF0dGVybnMuCisgICAgIFNob3VsZCByZXR1cm4gTlVMTC4g ICovCisgIHsKKyAgICB0cmVlIG9wMCA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDIsIDMs IDIpOworICAgIHRyZWUgb3AxID0gYnVpbGRfdmVjX2NzdF9yYW5kICh2bW9kZSwgMiwgMywgMik7 CisgICAgcG9seV91aW50NjQgb3AwX2xlbiA9IFRZUEVfVkVDVE9SX1NVQlBBUlRTIChUUkVFX1RZ UEUgKG9wMCkpOworCisgICAgdmVjX3Blcm1fYnVpbGRlciBidWlsZGVyIChvcDBfbGVuLCAyLCAz KTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKG9wMF9sZW4pOworICAgIGludCBtYXNrX2VsZW1z W10gPSB7IDAsIDAsIDAsIDEsIDAgfTsKKyAgICBmb3IgKGludCBpID0gMDsgaSA8IDU7IGkrKykK KyAgICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAobWFza19lbGVtc1tpXSk7CisKKyAgICB2ZWNfcGVy bV9pbmRpY2VzIHNlbCAoYnVpbGRlciwgMiwgb3AwX2xlbik7CisgICAgY29uc3QgY2hhciAqcmVh c29uOworICAgIHRyZWUgcmVzID0gZm9sZF92ZWNfcGVybV9jc3QgKFRSRUVfVFlQRSAob3AwKSwg b3AwLCBvcDEsIHNlbCwgJnJlYXNvbik7CisgICAgQVNTRVJUX1RSVUUgKHJlcyA9PSBOVUxMX1RS RUUpOworICAgIEFTU0VSVF9UUlVFICghc3RyY21wIChyZWFzb24sICJzdGVwIGlzIG5vdCBtdWx0 aXBsZSBvZiBucGF0dGVybnMiKSk7CisgIH0KKworICAvKiBDYXNlIDQ6IFNlbGVjdCBwYXR0ZXJu IDAgb2Ygb3AwIGFuZCBkdXAgb2Ygb3AwWzBdCisgICAgIG9wMCwgb3AxLCBzZWw6IG5wYXR0ZXJu cyA9IDIsIG5lbHRzX3Blcl9wYXR0ZXJuID0gMworICAgICBzZWwgPSB7IDAsIDAsIDIsIDAsIDQs IDAsIC4uLiB9LgorCisgICAgIEZvciBwYXR0ZXJuIHswLCAyLCA0LCAuLi59OgorICAgICBhMSA9 IDIKKyAgICAgbGVuID0gMTYgKyAxNngKKyAgICAgUyA9IDIKKyAgICAgZXNlbCA9IGxlbiAvIG5w YXR0ZXJuc19zZWwgPSAoMTYgKyAxNngpIC8gMiA9ICg4ICsgOHgpCisgICAgIGFlID0gYTEgKyAo ZXNlbCAtIDIpICogUworCT0gMiArICg4ICsgOHggLSAyKSAqIDIKKwk9IDE0ICsgMTZ4CisgICAg IGExIC8gYXJnMF9sZW4gPSAyIC8gKDE2ICsgMTZ4KSA9IDAKKyAgICAgYWUgLyBhcmcwX2xlbiA9 ICgxNCArIDE2eCkgLyAoMTYgKyAxNngpID0gMAorICAgICBTbyBhMS9hcmcwX2xlbiA9IGFlL2Fy ZzBfbGVuID0gMAorICAgICBIZW5jZSB3ZSBzZWxlY3QgZnJvbSBmaXJzdCB2ZWN0b3Igb3AwCisg ICAgIFMgPSAyLCBucGF0dGVybnMgPSAyLgorICAgICBTaW5jZSBTIGlzIG11bHRpcGxlIG9mIG5w YXR0ZXJucyhvcDApLCB3ZSBhcmUgc2VsZWN0aW5nIGZyb20KKyAgICAgc2FtZSBwYXR0ZXJuIG9m IG9wMC4KKworICAgICBGb3IgcGF0dGVybiB7MCwgLi4ufSwgd2UgYXJlIGNob29zaW5nIHsgb3Aw WzBdIC4uLiB9CisgICAgIFNvIHJlcyB3aWxsIGJlIGNvbWJpbmF0aW9uIG9mIGFib3ZlIHBhdHRl cm5zOgorICAgICByZXM6IHsgb3AwWzBdLCBvcDBbMF0sIG9wMFsyXSwgb3AwWzBdLCBvcDBbNF0s IG9wMFswXSwgLi4uIH0KKyAgICAgd2l0aCBucGF0dGVybnMgPSAyLCBuZWx0c19wZXJfcGF0dGVy biA9IDMuICAqLworICB7CisgICAgdHJlZSBvcDAgPSBidWlsZF92ZWNfY3N0X3JhbmQgKHZtb2Rl LCAyLCAzLCAyKTsKKyAgICB0cmVlIG9wMSA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodm1vZGUsIDIs IDMsIDIpOworICAgIHBvbHlfdWludDY0IG9wMF9sZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAo VFJFRV9UWVBFIChvcDApKTsKKworICAgIHZlY19wZXJtX2J1aWxkZXIgYnVpbGRlciAob3AwX2xl biwgMiwgMyk7CisgICAgaW50IG1hc2tfZWxlbXNbXSA9IHsgMCwgMCwgMiwgMCwgNCwgMCB9Owor ICAgIGZvciAoaW50IGkgPSAwOyBpIDwgNjsgaSsrKQorICAgICAgYnVpbGRlci5xdWlja19wdXNo IChtYXNrX2VsZW1zW2ldKTsKKworICAgIHZlY19wZXJtX2luZGljZXMgc2VsIChidWlsZGVyLCAy LCBvcDBfbGVuKTsKKyAgICB0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChUUkVFX1RZUEUg KG9wMCksIG9wMCwgb3AxLCBzZWwpOworICAgIHRyZWUgZXhwZWN0ZWRfcmVzW10gPSB7IHZlY3Rv cl9jc3RfZWx0IChvcDAsIDApLCB2ZWN0b3JfY3N0X2VsdCAob3AwLCAwKSwKKwkJCSAgICB2ZWN0 b3JfY3N0X2VsdCAob3AwLCAyKSwgdmVjdG9yX2NzdF9lbHQgKG9wMCwgMCksCisJCQkgICAgdmVj dG9yX2NzdF9lbHQgKG9wMCwgNCksIHZlY3Rvcl9jc3RfZWx0IChvcDAsIDApIH07CisgICAgdmFs aWRhdGVfcmVzICgyLCAzLCByZXMsIGV4cGVjdGVkX3Jlcyk7CisgIH0KKworICAvKiBDYXNlIDc6 IHNlbF9ucGF0dGVybnMgPiBvcF9ucGF0dGVybnM7CisgICAgIG9wMCwgb3AxOiBucGF0dGVybnMg PSAyLCBuZWx0c19wZXJfcGF0dGVybiA9IDMKKyAgICAgc2VsOiB7IDAsIDAsIDEsIGxlbiwgMiwg MCwgMywgbGVuLCA0LCAwLCA1LCBsZW4sIC4uLn0sCisgICAgIHdpdGggbnBhdHRlcm5zID0gNCwg bmVsdHNfcGVyX3BhdHRlcm4gPSAzLiAgKi8KKyAgeworICAgIHRyZWUgb3AwID0gYnVpbGRfdmVj X2NzdF9yYW5kICh2bW9kZSwgMiwgMywgMik7CisgICAgdHJlZSBvcDEgPSBidWlsZF92ZWNfY3N0 X3JhbmQgKHZtb2RlLCAyLCAzLCAyKTsKKyAgICBwb2x5X3VpbnQ2NCBvcDBfbGVuID0gVFlQRV9W RUNUT1JfU1VCUEFSVFMgKFRSRUVfVFlQRSAob3AwKSk7CisKKyAgICB2ZWNfcGVybV9idWlsZGVy IGJ1aWxkZXIob3AwX2xlbiwgNCwgMyk7CisgICAgLy8gLTEgaXMgdXNlZCBhcyBwbGFjZSBob2xk ZXIgZm9yIHBvbHlfaW50X2NzdAorICAgIGludCBtYXNrX2VsZW1zW10gPSB7IDAsIDAsIDEsIC0x LCAyLCAwLCAzLCAtMSwgNCwgMCwgNSwgLTEgfTsKKyAgICBmb3IgKGludCBpID0gMDsgaSA8IDEy OyBpKyspCisgICAgICBidWlsZGVyLnF1aWNrX3B1c2ggKChtYXNrX2VsZW1zW2ldID09IC0xKSA/ IG9wMF9sZW4gOiBtYXNrX2VsZW1zW2ldKTsKKworICAgIHZlY19wZXJtX2luZGljZXMgc2VsIChi dWlsZGVyLCAyLCBvcDBfbGVuKTsKKyAgICB0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChU UkVFX1RZUEUgKG9wMCksIG9wMCwgb3AxLCBzZWwpOworICAgIHRyZWUgZXhwZWN0ZWRfcmVzW10g PSB7IHZlY3Rvcl9jc3RfZWx0IChvcDAsIDApLCB2ZWN0b3JfY3N0X2VsdCAob3AwLCAwKSwKKwkJ CSAgICB2ZWN0b3JfY3N0X2VsdCAob3AwLCAxKSwgdmVjdG9yX2NzdF9lbHQgKG9wMSwgMCksCisJ CQkgICAgdmVjdG9yX2NzdF9lbHQgKG9wMCwgMiksIHZlY3Rvcl9jc3RfZWx0IChvcDAsIDApLAor CQkJICAgIHZlY3Rvcl9jc3RfZWx0IChvcDAsIDMpLCB2ZWN0b3JfY3N0X2VsdCAob3AxLCAwKSwK KwkJCSAgICB2ZWN0b3JfY3N0X2VsdCAob3AwLCA0KSwgdmVjdG9yX2NzdF9lbHQgKG9wMCwgMCks CisJCQkgICAgdmVjdG9yX2NzdF9lbHQgKG9wMCwgNSksIHZlY3Rvcl9jc3RfZWx0IChvcDEsIDAp IH07CisgICAgdmFsaWRhdGVfcmVzICg0LCAzLCByZXMsIGV4cGVjdGVkX3Jlcyk7CisgIH0KK30K KworLyogVGVzdCBjYXNlcyB3aGVyZSByZXN1bHQgaXMgVk54NFNJIGFuZCBpbnB1dCB2ZWN0b3Jz IGFyZSBWNFNJLiAgKi8KKworc3RhdGljIHZvaWQKK3Rlc3Rfdm54NHNpX3Y0c2kgKG1hY2hpbmVf bW9kZSB2bng0c2lfbW9kZSwgbWFjaGluZV9tb2RlIHY0c2lfbW9kZSkKK3sKKyAgLyogQ2FzZSAx OgorICAgICBzZWwgPSB7IDAsIDQsIDEsIDUsIC4uLiB9CisgICAgIHJlcyA9IHsgb3AwWzBdLCBv cDFbMF0sIG9wMFsxXSwgb3AxWzFdLCAuLi59IC8vICg0LCAxKSAgKi8KKyAgeworICAgIHRyZWUg YXJnMCA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodjRzaV9tb2RlLCA0LCAxLCAwKTsKKyAgICB0cmVl IGFyZzEgPSBidWlsZF92ZWNfY3N0X3JhbmQgKHY0c2lfbW9kZSwgNCwgMSwgMCk7CisKKyAgICB0 cmVlIGlubmVyX3R5cGUKKyAgICAgID0gbGFuZ19ob29rcy50eXBlcy50eXBlX2Zvcl9tb2RlIChH RVRfTU9ERV9JTk5FUiAodm54NHNpX21vZGUpLCAxKTsKKyAgICB0cmVlIHJlc190eXBlID0gYnVp bGRfdmVjdG9yX3R5cGVfZm9yX21vZGUgKGlubmVyX3R5cGUsIHZueDRzaV9tb2RlKTsKKworICAg IHBvbHlfdWludDY0IHJlc19sZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAocmVzX3R5cGUpOwor ICAgIHZlY19wZXJtX2J1aWxkZXIgYnVpbGRlciAocmVzX2xlbiwgNCwgMSk7CisgICAgYnVpbGRl ci5xdWlja19wdXNoICgwKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKDQpOworICAgIGJ1aWxk ZXIucXVpY2tfcHVzaCAoMSk7CisgICAgYnVpbGRlci5xdWlja19wdXNoICg1KTsKKworICAgIHZl Y19wZXJtX2luZGljZXMgc2VsIChidWlsZGVyLCAyLCByZXNfbGVuKTsKKyAgICB0cmVlIHJlcyA9 IGZvbGRfdmVjX3Blcm1fY3N0IChyZXNfdHlwZSwgYXJnMCwgYXJnMSwgc2VsKTsKKyAgICB0cmVl IGV4cGVjdGVkX3Jlc1tdID0geyB2ZWN0b3JfY3N0X2VsdCAoYXJnMCwgMCksIHZlY3Rvcl9jc3Rf ZWx0IChhcmcxLCAwKSwKKwkJCSAgICB2ZWN0b3JfY3N0X2VsdCAoYXJnMCwgMSksIHZlY3Rvcl9j c3RfZWx0IChhcmcxLCAxKQorCQkJICB9OworICAgIHZhbGlkYXRlX3JlcyAoNCwgMSwgcmVzLCBl eHBlY3RlZF9yZXMpOworICB9CisKKyAgLyogQ2FzZSAyOiBTYW1lIGFzIGNhc2UgMSwgYnV0IGNv bnRhaW5zIGFuIG91dCBvZiBib3VuZHMgYWNjZXNzIHdoaWNoCisgICAgIHNob3VsZCB3cmFwIGFy b3VuZC4KKyAgICAgc2VsID0gezAsIDgsIDQsIDEyLCAuLi59ICg0LCAxKQorICAgICByZXMgPSB7 IG9wMFswXSwgb3AwWzBdLCBvcDFbMF0sIG9wMVswXSwgLi4uIH0gKDQsIDEpLiAgKi8KKyAgewor ICAgIHRyZWUgYXJnMCA9IGJ1aWxkX3ZlY19jc3RfcmFuZCAodjRzaV9tb2RlLCA0LCAxLCAwKTsK KyAgICB0cmVlIGFyZzEgPSBidWlsZF92ZWNfY3N0X3JhbmQgKHY0c2lfbW9kZSwgNCwgMSwgMCk7 CisKKyAgICB0cmVlIGlubmVyX3R5cGUKKyAgICAgID0gbGFuZ19ob29rcy50eXBlcy50eXBlX2Zv cl9tb2RlIChHRVRfTU9ERV9JTk5FUiAodm54NHNpX21vZGUpLCAxKTsKKyAgICB0cmVlIHJlc190 eXBlID0gYnVpbGRfdmVjdG9yX3R5cGVfZm9yX21vZGUgKGlubmVyX3R5cGUsIHZueDRzaV9tb2Rl KTsKKworICAgIHBvbHlfdWludDY0IHJlc19sZW4gPSBUWVBFX1ZFQ1RPUl9TVUJQQVJUUyAocmVz X3R5cGUpOworICAgIHZlY19wZXJtX2J1aWxkZXIgYnVpbGRlciAocmVzX2xlbiwgNCwgMSk7Cisg ICAgYnVpbGRlci5xdWlja19wdXNoICgwKTsKKyAgICBidWlsZGVyLnF1aWNrX3B1c2ggKDgpOwor ICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAoNCk7CisgICAgYnVpbGRlci5xdWlja19wdXNoICgxMik7 CisKKyAgICB2ZWNfcGVybV9pbmRpY2VzIHNlbCAoYnVpbGRlciwgMiwgcmVzX2xlbik7CisgICAg dHJlZSByZXMgPSBmb2xkX3ZlY19wZXJtX2NzdCAocmVzX3R5cGUsIGFyZzAsIGFyZzEsIHNlbCk7 CisgICAgdHJlZSBleHBlY3RlZF9yZXNbXSA9IHsgdmVjdG9yX2NzdF9lbHQgKGFyZzAsIDApLCB2 ZWN0b3JfY3N0X2VsdCAoYXJnMCwgMCksCisJCQkgICAgdmVjdG9yX2NzdF9lbHQgKGFyZzEsIDAp LCB2ZWN0b3JfY3N0X2VsdCAoYXJnMSwgMCkKKwkJCSAgfTsKKyAgICB2YWxpZGF0ZV9yZXMgKDQs IDEsIHJlcywgZXhwZWN0ZWRfcmVzKTsKKyAgfQorfQorCisvKiBUZXN0IGNhc2VzIHdoZXJlIHJl c3VsdCBpcyBWNFNJIGFuZCBpbnB1dCB2ZWN0b3JzIGFyZSBWTng0U0kuICAqLworCitzdGF0aWMg dm9pZAordGVzdF92NHNpX3ZueDRzaSAobWFjaGluZV9tb2RlIHY0c2lfbW9kZSwgbWFjaGluZV9t b2RlIHZueDRzaV9tb2RlKQoreworICAvKiBDYXNlIDE6CisgICAgIHNlbCA9IHsgMCwgMSwgMiwg M30KKyAgICAgcmVzID0geyBvcDBbMF0sIG9wMFsxXSwgb3AwWzJdLCBvcDBbM10gfS4gICovCisg IHsKKyAgICB0cmVlIGFyZzAgPSBidWlsZF92ZWNfY3N0X3JhbmQgKHZueDRzaV9tb2RlLCA0LCAx KTsKKyAgICB0cmVlIGFyZzEgPSBidWlsZF92ZWNfY3N0X3JhbmQgKHZueDRzaV9tb2RlLCA0LCAx KTsKKworICAgIHRyZWUgaW5uZXJfdHlwZQorICAgICAgPSBsYW5nX2hvb2tzLnR5cGVzLnR5cGVf Zm9yX21vZGUgKEdFVF9NT0RFX0lOTkVSICh2NHNpX21vZGUpLCAxKTsKKyAgICB0cmVlIHJlc190 eXBlID0gYnVpbGRfdmVjdG9yX3R5cGVfZm9yX21vZGUgKGlubmVyX3R5cGUsIHY0c2lfbW9kZSk7 CisKKyAgICBwb2x5X3VpbnQ2NCByZXNfbGVuID0gVFlQRV9WRUNUT1JfU1VCUEFSVFMgKHJlc190 eXBlKTsKKyAgICB2ZWNfcGVybV9idWlsZGVyIGJ1aWxkZXIgKHJlc19sZW4sIDQsIDEpOworICAg IGZvciAoaW50IGkgPSAwOyBpIDwgNDsgaSsrKQorICAgICAgYnVpbGRlci5xdWlja19wdXNoIChp KTsKKworICAgIHZlY19wZXJtX2luZGljZXMgc2VsIChidWlsZGVyLCAyLCByZXNfbGVuKTsKKyAg ICB0cmVlIHJlcyA9IGZvbGRfdmVjX3Blcm1fY3N0IChyZXNfdHlwZSwgYXJnMCwgYXJnMSwgc2Vs KTsKKyAgICB0cmVlIGV4cGVjdGVkX3Jlc1tdID0geyB2ZWN0b3JfY3N0X2VsdCAoYXJnMCwgMCks IHZlY3Rvcl9jc3RfZWx0IChhcmcwLCAxKSwKKwkJCSAgICB2ZWN0b3JfY3N0X2VsdCAoYXJnMCwg MiksIHZlY3Rvcl9jc3RfZWx0IChhcmcwLCAzKSB9OworICAgIHZhbGlkYXRlX3Jlc192bHMgKHJl cywgZXhwZWN0ZWRfcmVzLCA0KTsKKyAgfQorCisgIC8qIENhc2UgMjogU2FtZSBhcyBDYXNlIDEs IGJ1dCBjcm9zc2luZyBpbnB1dCB2ZWN0b3IuCisgICAgIHNlbCA9IHswLCAyLCA0LCA2fQorICAg ICBJbiB0aGlzIGNhc2UsdGhlIGluZGV4IDQgaXMgYW1iaWd1b3VzIHNpbmNlIGxlbiA9IDQgKyA0 eC4KKyAgICAgSWYgeCA9IDAgYXQgcnVudGltZSwgd2UgY2hvb3NlIG9wMVswXQorICAgICBGb3Ig eCA+IDAgYXQgcnVudGltZSwgd2UgY2hvb3NlIG9wMFs0XQorICAgICBTaW5jZSB3ZSBjYW5ub3Qg ZGV0ZXJtaW5lLCB3aGljaCB2ZWN0b3IgdG8gY2hvb3NlIGZyb20gZHVyaW5nIGNvbXBpbGUgdGlt ZSwKKyAgICAgc2hvdWxkIHJldHVybiBOVUxMX1RSRUUuICAqLworICB7CisgICAgdHJlZSBhcmcw ID0gYnVpbGRfdmVjX2NzdF9yYW5kICh2bng0c2lfbW9kZSwgNCwgMSk7CisgICAgdHJlZSBhcmcx ID0gYnVpbGRfdmVjX2NzdF9yYW5kICh2bng0c2lfbW9kZSwgNCwgMSk7CisKKyAgICB0cmVlIGlu bmVyX3R5cGUKKyAgICAgID0gbGFuZ19ob29rcy50eXBlcy50eXBlX2Zvcl9tb2RlIChHRVRfTU9E RV9JTk5FUiAodjRzaV9tb2RlKSwgMSk7CisgICAgdHJlZSByZXNfdHlwZSA9IGJ1aWxkX3ZlY3Rv cl90eXBlX2Zvcl9tb2RlIChpbm5lcl90eXBlLCB2NHNpX21vZGUpOworCisgICAgcG9seV91aW50 NjQgcmVzX2xlbiA9IFRZUEVfVkVDVE9SX1NVQlBBUlRTIChyZXNfdHlwZSk7CisgICAgdmVjX3Bl cm1fYnVpbGRlciBidWlsZGVyIChyZXNfbGVuLCA0LCAxKTsKKyAgICBmb3IgKGludCBpID0gMDsg aSA8IDg7IGkgKz0gMikKKyAgICAgIGJ1aWxkZXIucXVpY2tfcHVzaCAoaSk7CisKKyAgICB2ZWNf cGVybV9pbmRpY2VzIHNlbCAoYnVpbGRlciwgMiwgcmVzX2xlbik7CisgICAgY29uc3QgY2hhciAq cmVhc29uOworICAgIHRyZWUgcmVzID0gZm9sZF92ZWNfcGVybV9jc3QgKHJlc190eXBlLCBhcmcw LCBhcmcxLCBzZWwsICZyZWFzb24pOworICAgIEFTU0VSVF9UUlVFIChyZXMgPT0gTlVMTF9UUkVF KTsKKyAgICBBU1NFUlRfVFJVRSAoIXN0cmNtcCAocmVhc29uLCAiY2Fubm90IGRpdmlkZSBzZWxl Y3RvciBlbGVtZW50IGJ5IGFyZyBsZW4iKSk7CisgIH0KK30KKworLyogSGVscGVyIGZ1bmN0aW9u IHRvIGdldCBhIHZlY3RvciBtb2RlIHRoYXQgaGFzIGVsZW1lbnQKKyAgIG1vZGUgYXMgSU5ORVJf TU9ERSBhbmQgR0VUX01PREVfTlVOSVRTIGVxdWFsIHRvIGxlbi4gICovCisKK3N0YXRpYyBtYWNo aW5lX21vZGUKK2dldF92bW9kZSAobWFjaGluZV9tb2RlIGlubmVyX21vZGUsIHBvbHlfdWludDY0 IGxlbikKK3sKKyAgbWFjaGluZV9tb2RlIHZtb2RlOworICBGT1JfRUFDSF9NT0RFX0lOX0NMQVNT ICh2bW9kZSwgTU9ERV9WRUNUT1JfSU5UKQorICAgIGlmIChHRVRfTU9ERV9JTk5FUiAodm1vZGUp ID09IGlubmVyX21vZGUKKwkmJiBrbm93bl9lcSAoR0VUX01PREVfTlVOSVRTICh2bW9kZSksIGxl bikpCisgICAgICByZXR1cm4gdm1vZGU7CisgIHJldHVybiBFX1ZPSURtb2RlOworfQorCisvKiBJ bnZva2UgdGVzdHMgZm9yIGZvbGRfdmVjX3Blcm1fY3N0LiAgKi8KKworc3RhdGljIHZvaWQKK3Rl c3QgKCkKK3sKKyAgLyogQ29uZGl0aW9uYWxseSBleGVjdXRlIGZvbGRfdmVjX3Blcm1fY3N0IHRl c3RzLCBpZiB0YXJnZXQgc3VwcG9ydHMKKyAgICAgVkxBIHZlY3RvcnMuIFVzZSBhIGNvbXBpbGUg dGltZSBjaGVjayBzbyB3ZSBhdm9pZCBpbnN0YW50aWF0aW5nCisgICAgIHBvbHlfdWludDY0IHdp dGggTiA+IDEgb24gdGFyZ2V0cyB0aGF0IGRvIG5vdCBzdXBwb3J0IFZMQSB2ZWN0b3JzLiAgKi8K KyAgaWYgY29uc3RleHByIChwb2x5X2ludF90cmFpdHM8cG9seV91aW50NjQ+OjpudW1fY29lZmZz ID4gMSkKKyAgICB7CisgICAgICBtYWNoaW5lX21vZGUgdm54NHNpX21vZGUgPSBnZXRfdm1vZGUg KFNJbW9kZSwgcG9seV91aW50NjQgKDQsIDQpKTsKKyAgICAgIGlmICh2bng0c2lfbW9kZSA9PSBF X1ZPSURtb2RlKQorCXJldHVybjsKKyAgICAgIG1hY2hpbmVfbW9kZSB2bngxNnFpX21vZGUgPSBn ZXRfdm1vZGUgKFFJbW9kZSwgcG9seV91aW50NjQgKDE2LCAxNikpOworICAgICAgaWYgKHZueDE2 cWlfbW9kZSA9PSBFX1ZPSURtb2RlKQorCXJldHVybjsKKyAgICAgIG1hY2hpbmVfbW9kZSB2NHNp X21vZGUgPSBnZXRfdm1vZGUgKFNJbW9kZSwgNCk7CisgICAgICBpZiAodjRzaV9tb2RlID09IEVf Vk9JRG1vZGUpCisJcmV0dXJuOworCisgICAgICB0ZXN0X3ZueDRzaSAodm54NHNpX21vZGUpOwor ICAgICAgdGVzdF92bngxNnFpICh2bngxNnFpX21vZGUpOworICAgICAgdGVzdF92bng0c2lfdjRz aSAodm54NHNpX21vZGUsIHY0c2lfbW9kZSk7CisgICAgICB0ZXN0X3Y0c2lfdm54NHNpICh2NHNp X21vZGUsIHZueDRzaV9tb2RlKTsKKyAgICB9Cit9Cit9OyAvLyBlbmQgb2YgdGVzdF9mb2xkX3Zl Y19wZXJtX2NzdCBuYW1lc3BhY2UKKwogLyogVmVyaWZ5IHRoYXQgdmFyaW91cyBiaW5hcnkgb3Bl cmF0aW9ucyBvbiB2ZWN0b3JzIGFyZSBmb2xkZWQKICAgIGNvcnJlY3RseS4gICovCiAKQEAgLTE2 OTQzLDYgKzE3NjYwLDcgQEAgZm9sZF9jb25zdF9jY190ZXN0cyAoKQogICB0ZXN0X2FyaXRobWV0 aWNfZm9sZGluZyAoKTsKICAgdGVzdF92ZWN0b3JfZm9sZGluZyAoKTsKICAgdGVzdF92ZWNfZHVw bGljYXRlX2ZvbGRpbmcgKCk7CisgIHRlc3RfZm9sZF92ZWNfcGVybV9jc3Q6OnRlc3QgKCk7CiB9 CiAKIH0gLy8gbmFtZXNwYWNlIHNlbGZ0ZXN0Cg== --0000000000005664650602403c24--