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_JUMP_CMD_H__
8 #define __RTA_JUMP_CMD_H__
9
10 static const uint32_t jump_test_cond[][2] = {
11 { NIFP, JUMP_COND_NIFP },
12 { NIP, JUMP_COND_NIP },
13 { NOP, JUMP_COND_NOP },
14 { NCP, JUMP_COND_NCP },
15 { CALM, JUMP_COND_CALM },
16 { SELF, JUMP_COND_SELF },
17 { SHRD, JUMP_COND_SHRD },
18 { JQP, JUMP_COND_JQP },
19 { MATH_Z, JUMP_COND_MATH_Z },
20 { MATH_N, JUMP_COND_MATH_N },
21 { MATH_NV, JUMP_COND_MATH_NV },
22 { MATH_C, JUMP_COND_MATH_C },
23 { PK_0, JUMP_COND_PK_0 },
24 { PK_GCD_1, JUMP_COND_PK_GCD_1 },
25 { PK_PRIME, JUMP_COND_PK_PRIME },
26 { CLASS1, JUMP_CLASS_CLASS1 },
27 { CLASS2, JUMP_CLASS_CLASS2 },
28 { BOTH, JUMP_CLASS_BOTH }
29 };
30
31 static const uint32_t jump_test_math_cond[][2] = {
32 { MATH_Z, JUMP_COND_MATH_Z },
33 { MATH_N, JUMP_COND_MATH_N },
34 { MATH_NV, JUMP_COND_MATH_NV },
35 { MATH_C, JUMP_COND_MATH_C }
36 };
37
38 static const uint32_t jump_src_dst[][2] = {
39 { MATH0, JUMP_SRC_DST_MATH0 },
40 { MATH1, JUMP_SRC_DST_MATH1 },
41 { MATH2, JUMP_SRC_DST_MATH2 },
42 { MATH3, JUMP_SRC_DST_MATH3 },
43 { DPOVRD, JUMP_SRC_DST_DPOVRD },
44 { SEQINSZ, JUMP_SRC_DST_SEQINLEN },
45 { SEQOUTSZ, JUMP_SRC_DST_SEQOUTLEN },
46 { VSEQINSZ, JUMP_SRC_DST_VARSEQINLEN },
47 { VSEQOUTSZ, JUMP_SRC_DST_VARSEQOUTLEN }
48 };
49
50 static inline int
rta_jump(struct program * program,uint64_t address,enum rta_jump_type jump_type,enum rta_jump_cond test_type,uint32_t test_condition,uint32_t src_dst)51 rta_jump(struct program *program, uint64_t address,
52 enum rta_jump_type jump_type,
53 enum rta_jump_cond test_type,
54 uint32_t test_condition, uint32_t src_dst)
55 {
56 uint32_t opcode = CMD_JUMP;
57 unsigned int start_pc = program->current_pc;
58 int ret = -EINVAL;
59
60 switch (jump_type) {
61 case (LOCAL_JUMP):
62 /*
63 * opcode |= JUMP_TYPE_LOCAL;
64 * JUMP_TYPE_LOCAL is 0
65 */
66 break;
67 case (HALT):
68 opcode |= JUMP_TYPE_HALT;
69 break;
70 case (HALT_STATUS):
71 opcode |= JUMP_TYPE_HALT_USER;
72 break;
73 case (FAR_JUMP):
74 opcode |= JUMP_TYPE_NONLOCAL;
75 break;
76 case (GOSUB):
77 opcode |= JUMP_TYPE_GOSUB;
78 break;
79 case (RETURN):
80 opcode |= JUMP_TYPE_RETURN;
81 break;
82 case (LOCAL_JUMP_INC):
83 opcode |= JUMP_TYPE_LOCAL_INC;
84 break;
85 case (LOCAL_JUMP_DEC):
86 opcode |= JUMP_TYPE_LOCAL_DEC;
87 break;
88 default:
89 pr_err("JUMP: Invalid jump type. SEC Program Line: %d\n",
90 program->current_pc);
91 goto err;
92 }
93
94 switch (test_type) {
95 case (ALL_TRUE):
96 /*
97 * opcode |= JUMP_TEST_ALL;
98 * JUMP_TEST_ALL is 0
99 */
100 break;
101 case (ALL_FALSE):
102 opcode |= JUMP_TEST_INVALL;
103 break;
104 case (ANY_TRUE):
105 opcode |= JUMP_TEST_ANY;
106 break;
107 case (ANY_FALSE):
108 opcode |= JUMP_TEST_INVANY;
109 break;
110 default:
111 pr_err("JUMP: test type not supported. SEC Program Line: %d\n",
112 program->current_pc);
113 goto err;
114 }
115
116 /* write test condition field */
117 if ((jump_type != LOCAL_JUMP_INC) && (jump_type != LOCAL_JUMP_DEC)) {
118 __rta_map_flags(test_condition, jump_test_cond,
119 ARRAY_SIZE(jump_test_cond), &opcode);
120 } else {
121 uint32_t val = 0;
122
123 ret = __rta_map_opcode(src_dst, jump_src_dst,
124 ARRAY_SIZE(jump_src_dst), &val);
125 if (ret < 0) {
126 pr_err("JUMP_INCDEC: SRC_DST not supported. SEC PC: %d; Instr: %d\n",
127 program->current_pc,
128 program->current_instruction);
129 goto err;
130 }
131 opcode |= val;
132
133 __rta_map_flags(test_condition, jump_test_math_cond,
134 ARRAY_SIZE(jump_test_math_cond), &opcode);
135 }
136
137 /* write local offset field for local jumps and user-defined halt */
138 if ((jump_type == LOCAL_JUMP) || (jump_type == LOCAL_JUMP_INC) ||
139 (jump_type == LOCAL_JUMP_DEC) || (jump_type == GOSUB) ||
140 (jump_type == HALT_STATUS))
141 opcode |= (uint32_t)(address & JUMP_OFFSET_MASK);
142
143 __rta_out32(program, opcode);
144 program->current_instruction++;
145
146 if (jump_type == FAR_JUMP)
147 __rta_out64(program, program->ps, address);
148
149 return (int)start_pc;
150
151 err:
152 program->first_error_pc = start_pc;
153 program->current_instruction++;
154 return ret;
155 }
156
157 #endif /* __RTA_JUMP_CMD_H__ */
158