1/*
2 * Copyright (c) 2015-2017, 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#include "accel.h"
30#include "shufti.h"
31#include "truffle.h"
32#include "vermicelli.h"
33#include "ue2common.h"
34
35const u8 *run_accel(const union AccelAux *accel, const u8 *c, const u8 *c_end) {
36 assert(ISALIGNED_N(accel, alignof(union AccelAux)));
37 const u8 *rv;
38
39 switch (accel->accel_type) {
40 case ACCEL_NONE:
41 DEBUG_PRINTF("accel none %p %p\n", c, c_end);
42 return c;
43
44 case ACCEL_VERM:
45 DEBUG_PRINTF("accel verm %p %p\n", c, c_end);
46 if (c + 15 >= c_end) {
47 return c;
48 }
49
50 rv = vermicelliExec(accel->verm.c, 0, c, c_end);
51 break;
52
53 case ACCEL_VERM_NOCASE:
54 DEBUG_PRINTF("accel verm nc %p %p\n", c, c_end);
55 if (c + 15 >= c_end) {
56 return c;
57 }
58
59 rv = vermicelliExec(accel->verm.c, 1, c, c_end);
60 break;
61
62 case ACCEL_DVERM:
63 DEBUG_PRINTF("accel dverm %p %p\n", c, c_end);
64 if (c + 16 + 1 >= c_end) {
65 return c;
66 }
67
68 /* need to stop one early to get an accurate end state */
69 rv = vermicelliDoubleExec(accel->dverm.c1, accel->dverm.c2, 0, c,
70 c_end - 1);
71 break;
72
73 case ACCEL_DVERM_NOCASE:
74 DEBUG_PRINTF("accel dverm nc %p %p\n", c, c_end);
75 if (c + 16 + 1 >= c_end) {
76 return c;
77 }
78
79 /* need to stop one early to get an accurate end state */
80 rv = vermicelliDoubleExec(accel->dverm.c1, accel->dverm.c2, 1, c,
81 c_end - 1);
82 break;
83
84 case ACCEL_DVERM_MASKED:
85 DEBUG_PRINTF("accel dverm masked %p %p\n", c, c_end);
86 if (c + 16 + 1 >= c_end) {
87 return c;
88 }
89
90 /* need to stop one early to get an accurate end state */
91 rv = vermicelliDoubleMaskedExec(accel->dverm.c1, accel->dverm.c2,
92 accel->dverm.m1, accel->dverm.m2,
93 c, c_end - 1);
94 break;
95
96 case ACCEL_SHUFTI:
97 DEBUG_PRINTF("accel shufti %p %p\n", c, c_end);
98 if (c + 15 >= c_end) {
99 return c;
100 }
101
102 rv = shuftiExec(accel->shufti.lo, accel->shufti.hi, c, c_end);
103 break;
104
105 case ACCEL_TRUFFLE:
106 DEBUG_PRINTF("accel Truffle %p %p\n", c, c_end);
107 if (c + 15 >= c_end) {
108 return c;
109 }
110
111 rv = truffleExec(accel->truffle.mask1, accel->truffle.mask2, c, c_end);
112 break;
113
114 case ACCEL_DSHUFTI:
115 DEBUG_PRINTF("accel dshufti %p %p\n", c, c_end);
116 if (c + 15 + 1 >= c_end) {
117 return c;
118 }
119
120 /* need to stop one early to get an accurate end state */
121 rv = shuftiDoubleExec(accel->dshufti.lo1,
122 accel->dshufti.hi1,
123 accel->dshufti.lo2,
124 accel->dshufti.hi2, c, c_end - 1);
125 break;
126
127 case ACCEL_RED_TAPE:
128 DEBUG_PRINTF("accel red tape %p %p\n", c, c_end);
129 rv = c_end;
130 break;
131
132
133 default:
134 assert(!"not here");
135 return c;
136 }
137
138 DEBUG_PRINTF("adjusting for offset %u\n", accel->generic.offset);
139 /* adjust offset to take into account the offset */
140 rv = MAX(c + accel->generic.offset, rv);
141 rv -= accel->generic.offset;
142
143 DEBUG_PRINTF("advanced %zd\n", rv - c);
144
145 return rv;
146}
147