Branch data Line data Source code
1 : : /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2 : : *
3 : : * Copyright 2008-2016 Freescale Semiconductor Inc.
4 : : * Copyright 2016,2019 NXP
5 : : */
6 : :
7 : : #ifndef __RTA_MATH_CMD_H__
8 : : #define __RTA_MATH_CMD_H__
9 : :
10 : : extern enum rta_sec_era rta_sec_era;
11 : :
12 : : static const uint32_t math_op1[][2] = {
13 : : /*1*/ { MATH0, MATH_SRC0_REG0 },
14 : : { MATH1, MATH_SRC0_REG1 },
15 : : { MATH2, MATH_SRC0_REG2 },
16 : : { MATH3, MATH_SRC0_REG3 },
17 : : { SEQINSZ, MATH_SRC0_SEQINLEN },
18 : : { SEQOUTSZ, MATH_SRC0_SEQOUTLEN },
19 : : { VSEQINSZ, MATH_SRC0_VARSEQINLEN },
20 : : { VSEQOUTSZ, MATH_SRC0_VARSEQOUTLEN },
21 : : { ZERO, MATH_SRC0_ZERO },
22 : : /*10*/ { NONE, 0 }, /* dummy value */
23 : : { DPOVRD, MATH_SRC0_DPOVRD },
24 : : { ONE, MATH_SRC0_ONE }
25 : : };
26 : :
27 : : /*
28 : : * Allowed MATH op1 sources for each SEC Era.
29 : : * Values represent the number of entries from math_op1[] that are supported.
30 : : */
31 : : static const unsigned int math_op1_sz[] = {10, 10, 12, 12, 12, 12,
32 : : 12, 12, 12, 12};
33 : :
34 : : static const uint32_t math_op2[][2] = {
35 : : /*1*/ { MATH0, MATH_SRC1_REG0 },
36 : : { MATH1, MATH_SRC1_REG1 },
37 : : { MATH2, MATH_SRC1_REG2 },
38 : : { MATH3, MATH_SRC1_REG3 },
39 : : { ABD, MATH_SRC1_INFIFO },
40 : : { OFIFO, MATH_SRC1_OUTFIFO },
41 : : { ONE, MATH_SRC1_ONE },
42 : : /*8*/ { NONE, 0 }, /* dummy value */
43 : : { JOBSRC, MATH_SRC1_JOBSOURCE },
44 : : { DPOVRD, MATH_SRC1_DPOVRD },
45 : : { VSEQINSZ, MATH_SRC1_VARSEQINLEN },
46 : : { VSEQOUTSZ, MATH_SRC1_VARSEQOUTLEN },
47 : : /*13*/ { ZERO, MATH_SRC1_ZERO }
48 : : };
49 : :
50 : : /*
51 : : * Allowed MATH op2 sources for each SEC Era.
52 : : * Values represent the number of entries from math_op2[] that are supported.
53 : : */
54 : : static const unsigned int math_op2_sz[] = {8, 9, 13, 13, 13, 13, 13, 13,
55 : : 13, 13};
56 : :
57 : : static const uint32_t math_result[][2] = {
58 : : /*1*/ { MATH0, MATH_DEST_REG0 },
59 : : { MATH1, MATH_DEST_REG1 },
60 : : { MATH2, MATH_DEST_REG2 },
61 : : { MATH3, MATH_DEST_REG3 },
62 : : { SEQINSZ, MATH_DEST_SEQINLEN },
63 : : { SEQOUTSZ, MATH_DEST_SEQOUTLEN },
64 : : { VSEQINSZ, MATH_DEST_VARSEQINLEN },
65 : : { VSEQOUTSZ, MATH_DEST_VARSEQOUTLEN },
66 : : /*9*/ { NONE, MATH_DEST_NONE },
67 : : { DPOVRD, MATH_DEST_DPOVRD }
68 : : };
69 : :
70 : : /*
71 : : * Allowed MATH result destinations for each SEC Era.
72 : : * Values represent the number of entries from math_result[] that are
73 : : * supported.
74 : : */
75 : : static const unsigned int math_result_sz[] = {9, 9, 10, 10, 10, 10, 10, 10,
76 : : 10, 10};
77 : :
78 : : static inline int
79 : 0 : rta_math(struct program *program, uint64_t operand1,
80 : : uint32_t op, uint64_t operand2, uint32_t result,
81 : : int length, uint32_t options)
82 : : {
83 : : uint32_t opcode = CMD_MATH;
84 : : uint32_t val = 0;
85 : : int ret = -EINVAL;
86 : 0 : unsigned int start_pc = program->current_pc;
87 : :
88 [ # # ]: 0 : if (options & SWP) {
89 [ # # # # ]: 0 : if ((options & IFB) ||
90 [ # # # # ]: 0 : (!(options & IMMED) && !(options & IMMED2)) ||
91 [ # # ]: 0 : ((options & IMMED) && (options & IMMED2))) {
92 : 0 : pr_err("MATH: SWP - invalid configuration. SEC PC: %d; Instr: %d\n",
93 : : program->current_pc,
94 : : program->current_instruction);
95 : 0 : goto err;
96 : : }
97 : : }
98 : :
99 : : /*
100 : : * SHLD operation is different from others and we
101 : : * assume that we can have _NONE as first operand
102 : : * or _SEQINSZ as second operand
103 : : */
104 [ # # ]: 0 : if ((op != MATH_FUN_SHLD) && ((operand1 == NONE) ||
105 [ # # ]: 0 : (operand2 == SEQINSZ))) {
106 : 0 : pr_err("MATH: Invalid operand. SEC PC: %d; Instr: %d\n",
107 : : program->current_pc, program->current_instruction);
108 : 0 : goto err;
109 : : }
110 : :
111 : : /*
112 : : * We first check if it is unary operation. In that
113 : : * case second operand must be _NONE
114 : : */
115 [ # # # # ]: 0 : if (((op == MATH_FUN_ZBYT) || (op == MATH_FUN_BSWAP)) &&
116 : : (operand2 != NONE)) {
117 : 0 : pr_err("MATH: Invalid operand2. SEC PC: %d; Instr: %d\n",
118 : : program->current_pc, program->current_instruction);
119 : 0 : goto err;
120 : : }
121 : :
122 : : /* Write first operand field */
123 [ # # ]: 0 : if (options & IMMED) {
124 : : opcode |= MATH_SRC0_IMM;
125 : : } else {
126 : 0 : ret = __rta_map_opcode((uint32_t)operand1, math_op1,
127 : 0 : math_op1_sz[rta_sec_era], &val);
128 : : if (ret < 0) {
129 : 0 : pr_err("MATH: operand1 not supported. SEC PC: %d; Instr: %d\n",
130 : : program->current_pc,
131 : : program->current_instruction);
132 : 0 : goto err;
133 : : }
134 : 0 : opcode |= val;
135 : : }
136 : :
137 : : /* Write second operand field */
138 [ # # ]: 0 : if (options & IMMED2) {
139 : 0 : opcode |= MATH_SRC1_IMM;
140 : : } else {
141 : 0 : ret = __rta_map_opcode((uint32_t)operand2, math_op2,
142 : 0 : math_op2_sz[rta_sec_era], &val);
143 : : if (ret < 0) {
144 : 0 : pr_err("MATH: operand2 not supported. SEC PC: %d; Instr: %d\n",
145 : : program->current_pc,
146 : : program->current_instruction);
147 : 0 : goto err;
148 : : }
149 : 0 : opcode |= val;
150 : : }
151 : :
152 : : /* Write result field */
153 : 0 : ret = __rta_map_opcode(result, math_result, math_result_sz[rta_sec_era],
154 : : &val);
155 : : if (ret < 0) {
156 : 0 : pr_err("MATH: result not supported. SEC PC: %d; Instr: %d\n",
157 : : program->current_pc, program->current_instruction);
158 : 0 : goto err;
159 : : }
160 : 0 : opcode |= val;
161 : :
162 : : /*
163 : : * as we encode operations with their "real" values, we do not
164 : : * to translate but we do need to validate the value
165 : : */
166 [ # # ]: 0 : switch (op) {
167 : : /*Binary operators */
168 : 0 : case (MATH_FUN_ADD):
169 : : case (MATH_FUN_ADDC):
170 : : case (MATH_FUN_SUB):
171 : : case (MATH_FUN_SUBB):
172 : : case (MATH_FUN_OR):
173 : : case (MATH_FUN_AND):
174 : : case (MATH_FUN_XOR):
175 : : case (MATH_FUN_LSHIFT):
176 : : case (MATH_FUN_RSHIFT):
177 : : case (MATH_FUN_SHLD):
178 : : /* Unary operators */
179 : : case (MATH_FUN_ZBYT):
180 : : case (MATH_FUN_BSWAP):
181 : 0 : opcode |= op;
182 : : break;
183 : 0 : default:
184 : 0 : pr_err("MATH: operator is not supported. SEC PC: %d; Instr: %d\n",
185 : : program->current_pc, program->current_instruction);
186 : : ret = -EINVAL;
187 : 0 : goto err;
188 : : }
189 : :
190 : 0 : opcode |= (options & ~(IMMED | IMMED2));
191 : :
192 : : /* Verify length */
193 [ # # # # : 0 : switch (length) {
# ]
194 : 0 : case (1):
195 : 0 : opcode |= MATH_LEN_1BYTE;
196 : 0 : break;
197 : 0 : case (2):
198 : 0 : opcode |= MATH_LEN_2BYTE;
199 : 0 : break;
200 : 0 : case (4):
201 : 0 : opcode |= MATH_LEN_4BYTE;
202 : 0 : break;
203 : 0 : case (8):
204 : 0 : opcode |= MATH_LEN_8BYTE;
205 : 0 : break;
206 : 0 : default:
207 : 0 : pr_err("MATH: length is not supported. SEC PC: %d; Instr: %d\n",
208 : : program->current_pc, program->current_instruction);
209 : : ret = -EINVAL;
210 : 0 : goto err;
211 : : }
212 : :
213 : 0 : __rta_out32(program, opcode);
214 : 0 : program->current_instruction++;
215 : :
216 : : /* Write immediate value */
217 [ # # # # ]: 0 : if ((options & IMMED) && !(options & IMMED2)) {
218 [ # # # # ]: 0 : __rta_out64(program, (length > 4) && !(options & IFB),
219 : : operand1);
220 [ # # # # ]: 0 : } else if ((options & IMMED2) && !(options & IMMED)) {
221 [ # # # # ]: 0 : __rta_out64(program, (length > 4) && !(options & IFB),
222 : : operand2);
223 [ # # # # ]: 0 : } else if ((options & IMMED) && (options & IMMED2)) {
224 : 0 : __rta_out32(program, lower_32_bits(operand1));
225 : 0 : __rta_out32(program, lower_32_bits(operand2));
226 : : }
227 : :
228 : 0 : return (int)start_pc;
229 : :
230 : 0 : err:
231 : 0 : program->first_error_pc = start_pc;
232 : 0 : program->current_instruction++;
233 : 0 : return ret;
234 : : }
235 : :
236 : : static inline int
237 : 0 : rta_mathi(struct program *program, uint64_t operand,
238 : : uint32_t op, uint8_t imm, uint32_t result,
239 : : int length, uint32_t options)
240 : : {
241 : : uint32_t opcode = CMD_MATHI;
242 : : uint32_t val = 0;
243 : : int ret = -EINVAL;
244 : 0 : unsigned int start_pc = program->current_pc;
245 : :
246 [ # # # # ]: 0 : if (((op == MATH_FUN_FBYT) && (options & SSEL))) {
247 : 0 : pr_err("MATHI: Illegal combination - FBYT and SSEL. SEC PC: %d; Instr: %d\n",
248 : : program->current_pc, program->current_instruction);
249 : 0 : goto err;
250 : : }
251 : :
252 : : /* Write first operand field */
253 [ # # ]: 0 : if (!(options & SSEL))
254 : 0 : ret = __rta_map_opcode((uint32_t)operand, math_op1,
255 : 0 : math_op1_sz[rta_sec_era], &val);
256 : : else
257 : 0 : ret = __rta_map_opcode((uint32_t)operand, math_op2,
258 : 0 : math_op2_sz[rta_sec_era], &val);
259 [ # # ]: 0 : if (ret < 0) {
260 : 0 : pr_err("MATHI: operand not supported. SEC PC: %d; Instr: %d\n",
261 : : program->current_pc, program->current_instruction);
262 : 0 : goto err;
263 : : }
264 : :
265 [ # # ]: 0 : if (!(options & SSEL))
266 : 0 : opcode |= val;
267 : : else
268 : 0 : opcode |= (val << (MATHI_SRC1_SHIFT - MATH_SRC1_SHIFT));
269 : :
270 : : /* Write second operand field */
271 : 0 : opcode |= (imm << MATHI_IMM_SHIFT);
272 : :
273 : : /* Write result field */
274 : 0 : ret = __rta_map_opcode(result, math_result, math_result_sz[rta_sec_era],
275 : : &val);
276 : : if (ret < 0) {
277 : 0 : pr_err("MATHI: result not supported. SEC PC: %d; Instr: %d\n",
278 : : program->current_pc, program->current_instruction);
279 : 0 : goto err;
280 : : }
281 : 0 : opcode |= (val << (MATHI_DEST_SHIFT - MATH_DEST_SHIFT));
282 : :
283 : : /*
284 : : * as we encode operations with their "real" values, we do not have to
285 : : * translate but we do need to validate the value
286 : : */
287 [ # # ]: 0 : switch (op) {
288 : 0 : case (MATH_FUN_ADD):
289 : : case (MATH_FUN_ADDC):
290 : : case (MATH_FUN_SUB):
291 : : case (MATH_FUN_SUBB):
292 : : case (MATH_FUN_OR):
293 : : case (MATH_FUN_AND):
294 : : case (MATH_FUN_XOR):
295 : : case (MATH_FUN_LSHIFT):
296 : : case (MATH_FUN_RSHIFT):
297 : : case (MATH_FUN_FBYT):
298 : 0 : opcode |= op;
299 : : break;
300 : 0 : default:
301 : 0 : pr_err("MATHI: operator not supported. SEC PC: %d; Instr: %d\n",
302 : : program->current_pc, program->current_instruction);
303 : : ret = -EINVAL;
304 : 0 : goto err;
305 : : }
306 : :
307 : 0 : opcode |= options;
308 : :
309 : : /* Verify length */
310 [ # # # # : 0 : switch (length) {
# ]
311 : 0 : case (1):
312 : 0 : opcode |= MATH_LEN_1BYTE;
313 : 0 : break;
314 : 0 : case (2):
315 : 0 : opcode |= MATH_LEN_2BYTE;
316 : 0 : break;
317 : 0 : case (4):
318 : 0 : opcode |= MATH_LEN_4BYTE;
319 : 0 : break;
320 : 0 : case (8):
321 : 0 : opcode |= MATH_LEN_8BYTE;
322 : 0 : break;
323 : 0 : default:
324 : 0 : pr_err("MATHI: length %d not supported. SEC PC: %d; Instr: %d\n",
325 : : length, program->current_pc,
326 : : program->current_instruction);
327 : : ret = -EINVAL;
328 : 0 : goto err;
329 : : }
330 : :
331 : 0 : __rta_out32(program, opcode);
332 : 0 : program->current_instruction++;
333 : :
334 : 0 : return (int)start_pc;
335 : :
336 : 0 : err:
337 : 0 : program->first_error_pc = start_pc;
338 : 0 : program->current_instruction++;
339 : 0 : return ret;
340 : : }
341 : :
342 : : #endif /* __RTA_MATH_CMD_H__ */
|