1/*
2 * Copyright (c) 2016, Intel Corporation
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * * Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of Intel Corporation nor the names of its contributors
13 * may be used to endorse or promote products derived from this software
14 * without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef VALIDATE_MASK_H
30#define VALIDATE_MASK_H
31
32#include "ue2common.h"
33#include "util/simd_utils.h"
34
35#if defined(DEBUG)
36static
37void validateMask32Print(const u8 *mask) {
38 int i;
39 for (i = 0; i < 32; i++) {
40 printf("%02x", mask[i]);
41 }
42 printf("\n");
43}
44#endif
45
46// check positive bytes in cmp_result.
47// return one if the check passed, zero otherwise.
48static really_inline
49int posValidateMask(const u64a cmp_result, const u64a pos_mask) {
50 return !(cmp_result & pos_mask);
51}
52
53/*
54 * check negative bytes in cmp_result.
55 * return one if any byte in cmp_result is not 0, zero otherwise.
56 * check lowest 7 bits and highest bit of every byte respectively.
57 */
58static really_inline
59int negValidateMask(const u64a cmp_result, const u64a neg_mask) {
60 const u64a count_mask = 0x7f7f7f7f7f7f7f7f;
61 // check lowest 7 bits of every byte.
62 // the highest bit should be 1 if check passed.
63 u64a check_low = (cmp_result & count_mask) + count_mask;
64 // check the highest bit of every byte.
65 // combine the highest bit and 0x7f to 0xff if check passes.
66 // flip all 0xff to 0x00 and 0x7f to 0x80.
67 u64a check_all = ~(check_low | cmp_result | count_mask);
68 return !(check_all & neg_mask);
69}
70
71static really_inline
72int validateMask(u64a data, u64a valid_data_mask, u64a and_mask,
73 u64a cmp_mask, u64a neg_mask) {
74 // skip some byte where valid_data_mask is 0x00 there.
75 and_mask &= valid_data_mask;
76 cmp_mask &= valid_data_mask;
77 neg_mask &= valid_data_mask;
78 u64a cmp_result = (data & and_mask) ^ cmp_mask;
79 /* do the positive check first since it's cheaper */
80 if (posValidateMask(cmp_result, ~neg_mask)
81 && negValidateMask(cmp_result, neg_mask)) {
82 return 1;
83 } else {
84 DEBUG_PRINTF("data %llx valid_data_mask(vdm) %llx\n",
85 data, valid_data_mask);
86 DEBUG_PRINTF("and_mask & vdm %llx cmp_mask & vdm %llx\n", and_mask,
87 cmp_mask);
88 DEBUG_PRINTF("cmp_result %llx neg_mask & vdm %llx\n",
89 cmp_result, neg_mask);
90 return 0;
91 }
92}
93
94static really_inline
95int validateMask32(const m256 data, const u32 valid_data_mask,
96 const m256 and_mask, const m256 cmp_mask,
97 const u32 neg_mask) {
98 m256 cmp_result_256 = eq256(and256(data, and_mask), cmp_mask);
99 u32 cmp_result = ~movemask256(cmp_result_256);
100#ifdef DEBUG
101 DEBUG_PRINTF("data\n");
102 validateMask32Print((const u8 *)&data);
103 DEBUG_PRINTF("cmp_result\n");
104 validateMask32Print((const u8 *)&cmp_result_256);
105#endif
106 DEBUG_PRINTF("cmp_result %08x neg_mask %08x\n", cmp_result, neg_mask);
107 DEBUG_PRINTF("valid_data_mask %08x\n", valid_data_mask);
108
109 if ((cmp_result & valid_data_mask) == (neg_mask & valid_data_mask)) {
110 DEBUG_PRINTF("checkCompareResult32 passed\n");
111 return 1;
112 } else {
113 DEBUG_PRINTF("checkCompareResult32 failed\n");
114 return 0;
115 }
116}
117
118#endif
119