1
2
3
4
5
6
7#ifndef __RTA_MATH_CMD_H__
8#define __RTA_MATH_CMD_H__
9
10extern enum rta_sec_era rta_sec_era;
11
12static const uint32_t math_op1[][2] = {
13 { 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 { NONE, 0 },
23 { DPOVRD, MATH_SRC0_DPOVRD },
24 { ONE, MATH_SRC0_ONE }
25};
26
27
28
29
30
31static const unsigned int math_op1_sz[] = {10, 10, 12, 12, 12, 12,
32 12, 12, 12, 12};
33
34static const uint32_t math_op2[][2] = {
35 { 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 { NONE, 0 },
43 { JOBSRC, MATH_SRC1_JOBSOURCE },
44 { DPOVRD, MATH_SRC1_DPOVRD },
45 { VSEQINSZ, MATH_SRC1_VARSEQINLEN },
46 { VSEQOUTSZ, MATH_SRC1_VARSEQOUTLEN },
47 { ZERO, MATH_SRC1_ZERO }
48};
49
50
51
52
53
54static const unsigned int math_op2_sz[] = {8, 9, 13, 13, 13, 13, 13, 13,
55 13, 13};
56
57static const uint32_t math_result[][2] = {
58 { 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 { NONE, MATH_DEST_NONE },
67 { DPOVRD, MATH_DEST_DPOVRD }
68};
69
70
71
72
73
74
75static const unsigned int math_result_sz[] = {9, 9, 10, 10, 10, 10, 10, 10,
76 10, 10};
77
78static inline int
79rta_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 unsigned int start_pc = program->current_pc;
87
88 if (((op == MATH_FUN_BSWAP) && (rta_sec_era < RTA_SEC_ERA_4)) ||
89 ((op == MATH_FUN_ZBYT) && (rta_sec_era < RTA_SEC_ERA_2))) {
90 pr_err("MATH: operation not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
91 USER_SEC_ERA(rta_sec_era), program->current_pc,
92 program->current_instruction);
93 goto err;
94 }
95
96 if (options & SWP) {
97 if (rta_sec_era < RTA_SEC_ERA_7) {
98 pr_err("MATH: operation not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
99 USER_SEC_ERA(rta_sec_era), program->current_pc,
100 program->current_instruction);
101 goto err;
102 }
103
104 if ((options & IFB) ||
105 (!(options & IMMED) && !(options & IMMED2)) ||
106 ((options & IMMED) && (options & IMMED2))) {
107 pr_err("MATH: SWP - invalid configuration. SEC PC: %d; Instr: %d\n",
108 program->current_pc,
109 program->current_instruction);
110 goto err;
111 }
112 }
113
114
115
116
117
118
119 if ((op != MATH_FUN_SHLD) && ((operand1 == NONE) ||
120 (operand2 == SEQINSZ))) {
121 pr_err("MATH: Invalid operand. SEC PC: %d; Instr: %d\n",
122 program->current_pc, program->current_instruction);
123 goto err;
124 }
125
126
127
128
129
130 if (((op == MATH_FUN_ZBYT) || (op == MATH_FUN_BSWAP)) &&
131 (operand2 != NONE)) {
132 pr_err("MATH: Invalid operand2. SEC PC: %d; Instr: %d\n",
133 program->current_pc, program->current_instruction);
134 goto err;
135 }
136
137
138 if (options & IMMED) {
139 opcode |= MATH_SRC0_IMM;
140 } else {
141 ret = __rta_map_opcode((uint32_t)operand1, math_op1,
142 math_op1_sz[rta_sec_era], &val);
143 if (ret < 0) {
144 pr_err("MATH: operand1 not supported. SEC PC: %d; Instr: %d\n",
145 program->current_pc,
146 program->current_instruction);
147 goto err;
148 }
149 opcode |= val;
150 }
151
152
153 if (options & IMMED2) {
154 opcode |= MATH_SRC1_IMM;
155 } else {
156 ret = __rta_map_opcode((uint32_t)operand2, math_op2,
157 math_op2_sz[rta_sec_era], &val);
158 if (ret < 0) {
159 pr_err("MATH: operand2 not supported. SEC PC: %d; Instr: %d\n",
160 program->current_pc,
161 program->current_instruction);
162 goto err;
163 }
164 opcode |= val;
165 }
166
167
168 ret = __rta_map_opcode(result, math_result, math_result_sz[rta_sec_era],
169 &val);
170 if (ret < 0) {
171 pr_err("MATH: result not supported. SEC PC: %d; Instr: %d\n",
172 program->current_pc, program->current_instruction);
173 goto err;
174 }
175 opcode |= val;
176
177
178
179
180
181 switch (op) {
182
183 case (MATH_FUN_ADD):
184 case (MATH_FUN_ADDC):
185 case (MATH_FUN_SUB):
186 case (MATH_FUN_SUBB):
187 case (MATH_FUN_OR):
188 case (MATH_FUN_AND):
189 case (MATH_FUN_XOR):
190 case (MATH_FUN_LSHIFT):
191 case (MATH_FUN_RSHIFT):
192 case (MATH_FUN_SHLD):
193
194 case (MATH_FUN_ZBYT):
195 case (MATH_FUN_BSWAP):
196 opcode |= op;
197 break;
198 default:
199 pr_err("MATH: operator is not supported. SEC PC: %d; Instr: %d\n",
200 program->current_pc, program->current_instruction);
201 ret = -EINVAL;
202 goto err;
203 }
204
205 opcode |= (options & ~(IMMED | IMMED2));
206
207
208 switch (length) {
209 case (1):
210 opcode |= MATH_LEN_1BYTE;
211 break;
212 case (2):
213 opcode |= MATH_LEN_2BYTE;
214 break;
215 case (4):
216 opcode |= MATH_LEN_4BYTE;
217 break;
218 case (8):
219 opcode |= MATH_LEN_8BYTE;
220 break;
221 default:
222 pr_err("MATH: length is not supported. SEC PC: %d; Instr: %d\n",
223 program->current_pc, program->current_instruction);
224 ret = -EINVAL;
225 goto err;
226 }
227
228 __rta_out32(program, opcode);
229 program->current_instruction++;
230
231
232 if ((options & IMMED) && !(options & IMMED2)) {
233 __rta_out64(program, (length > 4) && !(options & IFB),
234 operand1);
235 } else if ((options & IMMED2) && !(options & IMMED)) {
236 __rta_out64(program, (length > 4) && !(options & IFB),
237 operand2);
238 } else if ((options & IMMED) && (options & IMMED2)) {
239 __rta_out32(program, lower_32_bits(operand1));
240 __rta_out32(program, lower_32_bits(operand2));
241 }
242
243 return (int)start_pc;
244
245 err:
246 program->first_error_pc = start_pc;
247 program->current_instruction++;
248 return ret;
249}
250
251static inline int
252rta_mathi(struct program *program, uint64_t operand,
253 uint32_t op, uint8_t imm, uint32_t result,
254 int length, uint32_t options)
255{
256 uint32_t opcode = CMD_MATHI;
257 uint32_t val = 0;
258 int ret = -EINVAL;
259 unsigned int start_pc = program->current_pc;
260
261 if (rta_sec_era < RTA_SEC_ERA_6) {
262 pr_err("MATHI: Command not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
263 USER_SEC_ERA(rta_sec_era), program->current_pc,
264 program->current_instruction);
265 goto err;
266 }
267
268 if (((op == MATH_FUN_FBYT) && (options & SSEL))) {
269 pr_err("MATHI: Illegal combination - FBYT and SSEL. SEC PC: %d; Instr: %d\n",
270 program->current_pc, program->current_instruction);
271 goto err;
272 }
273
274 if ((options & SWP) && (rta_sec_era < RTA_SEC_ERA_7)) {
275 pr_err("MATHI: SWP not supported by SEC Era %d. SEC PC: %d; Instr: %d\n",
276 USER_SEC_ERA(rta_sec_era), program->current_pc,
277 program->current_instruction);
278 goto err;
279 }
280
281
282 if (!(options & SSEL))
283 ret = __rta_map_opcode((uint32_t)operand, math_op1,
284 math_op1_sz[rta_sec_era], &val);
285 else
286 ret = __rta_map_opcode((uint32_t)operand, math_op2,
287 math_op2_sz[rta_sec_era], &val);
288 if (ret < 0) {
289 pr_err("MATHI: operand not supported. SEC PC: %d; Instr: %d\n",
290 program->current_pc, program->current_instruction);
291 goto err;
292 }
293
294 if (!(options & SSEL))
295 opcode |= val;
296 else
297 opcode |= (val << (MATHI_SRC1_SHIFT - MATH_SRC1_SHIFT));
298
299
300 opcode |= (imm << MATHI_IMM_SHIFT);
301
302
303 ret = __rta_map_opcode(result, math_result, math_result_sz[rta_sec_era],
304 &val);
305 if (ret < 0) {
306 pr_err("MATHI: result not supported. SEC PC: %d; Instr: %d\n",
307 program->current_pc, program->current_instruction);
308 goto err;
309 }
310 opcode |= (val << (MATHI_DEST_SHIFT - MATH_DEST_SHIFT));
311
312
313
314
315
316 switch (op) {
317 case (MATH_FUN_ADD):
318 case (MATH_FUN_ADDC):
319 case (MATH_FUN_SUB):
320 case (MATH_FUN_SUBB):
321 case (MATH_FUN_OR):
322 case (MATH_FUN_AND):
323 case (MATH_FUN_XOR):
324 case (MATH_FUN_LSHIFT):
325 case (MATH_FUN_RSHIFT):
326 case (MATH_FUN_FBYT):
327 opcode |= op;
328 break;
329 default:
330 pr_err("MATHI: operator not supported. SEC PC: %d; Instr: %d\n",
331 program->current_pc, program->current_instruction);
332 ret = -EINVAL;
333 goto err;
334 }
335
336 opcode |= options;
337
338
339 switch (length) {
340 case (1):
341 opcode |= MATH_LEN_1BYTE;
342 break;
343 case (2):
344 opcode |= MATH_LEN_2BYTE;
345 break;
346 case (4):
347 opcode |= MATH_LEN_4BYTE;
348 break;
349 case (8):
350 opcode |= MATH_LEN_8BYTE;
351 break;
352 default:
353 pr_err("MATHI: length %d not supported. SEC PC: %d; Instr: %d\n",
354 length, program->current_pc,
355 program->current_instruction);
356 ret = -EINVAL;
357 goto err;
358 }
359
360 __rta_out32(program, opcode);
361 program->current_instruction++;
362
363 return (int)start_pc;
364
365 err:
366 program->first_error_pc = start_pc;
367 program->current_instruction++;
368 return ret;
369}
370
371#endif
372