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) |
36 | static |
37 | void 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. |
48 | static really_inline |
49 | int 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 | */ |
58 | static really_inline |
59 | int 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 | |
71 | static really_inline |
72 | int 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 | |
94 | static really_inline |
95 | int 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 | |