1 | /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ |
2 | /* Copyright (C) 2016-2018 Netronome Systems, Inc. */ |
3 | |
4 | #ifndef __NFP_ASM_H__ |
5 | #define __NFP_ASM_H__ 1 |
6 | |
7 | #include <linux/bitfield.h> |
8 | #include <linux/bug.h> |
9 | #include <linux/types.h> |
10 | |
11 | #define REG_NONE 0 |
12 | #define REG_WIDTH 4 |
13 | |
14 | #define RE_REG_NO_DST 0x020 |
15 | #define RE_REG_IMM 0x020 |
16 | #define RE_REG_IMM_encode(x) \ |
17 | (RE_REG_IMM | ((x) & 0x1f) | (((x) & 0x60) << 1)) |
18 | #define RE_REG_IMM_MAX 0x07fULL |
19 | #define RE_REG_LM 0x050 |
20 | #define RE_REG_LM_IDX 0x008 |
21 | #define RE_REG_LM_IDX_MAX 0x7 |
22 | #define RE_REG_XFR 0x080 |
23 | |
24 | #define UR_REG_XFR 0x180 |
25 | #define UR_REG_LM 0x200 |
26 | #define UR_REG_LM_IDX 0x020 |
27 | #define UR_REG_LM_POST_MOD 0x010 |
28 | #define UR_REG_LM_POST_MOD_DEC 0x001 |
29 | #define UR_REG_LM_IDX_MAX 0xf |
30 | #define UR_REG_NN 0x280 |
31 | #define UR_REG_NO_DST 0x300 |
32 | #define UR_REG_IMM UR_REG_NO_DST |
33 | #define UR_REG_IMM_encode(x) (UR_REG_IMM | (x)) |
34 | #define UR_REG_IMM_MAX 0x0ffULL |
35 | |
36 | #define OP_BR_BASE 0x0d800000020ULL |
37 | #define OP_BR_BASE_MASK 0x0f8000c3ce0ULL |
38 | #define OP_BR_MASK 0x0000000001fULL |
39 | #define OP_BR_EV_PIP 0x00000000300ULL |
40 | #define OP_BR_CSS 0x0000003c000ULL |
41 | #define OP_BR_DEFBR 0x00000300000ULL |
42 | #define OP_BR_ADDR_LO 0x007ffc00000ULL |
43 | #define OP_BR_ADDR_HI 0x10000000000ULL |
44 | |
45 | #define OP_BR_BIT_BASE 0x0d000000000ULL |
46 | #define OP_BR_BIT_BASE_MASK 0x0f800080300ULL |
47 | #define OP_BR_BIT_A_SRC 0x000000000ffULL |
48 | #define OP_BR_BIT_B_SRC 0x0000003fc00ULL |
49 | #define OP_BR_BIT_BV 0x00000040000ULL |
50 | #define OP_BR_BIT_SRC_LMEXTN 0x40000000000ULL |
51 | #define OP_BR_BIT_DEFBR OP_BR_DEFBR |
52 | #define OP_BR_BIT_ADDR_LO OP_BR_ADDR_LO |
53 | #define OP_BR_BIT_ADDR_HI OP_BR_ADDR_HI |
54 | |
55 | #define OP_BR_ALU_BASE 0x0e800000000ULL |
56 | #define OP_BR_ALU_BASE_MASK 0x0ff80000000ULL |
57 | #define OP_BR_ALU_A_SRC 0x000000003ffULL |
58 | #define OP_BR_ALU_B_SRC 0x000000ffc00ULL |
59 | #define OP_BR_ALU_DEFBR 0x00000300000ULL |
60 | #define OP_BR_ALU_IMM_HI 0x0007fc00000ULL |
61 | #define OP_BR_ALU_SRC_LMEXTN 0x40000000000ULL |
62 | #define OP_BR_ALU_DST_LMEXTN 0x80000000000ULL |
63 | |
64 | static inline bool nfp_is_br(u64 insn) |
65 | { |
66 | return (insn & OP_BR_BASE_MASK) == OP_BR_BASE || |
67 | (insn & OP_BR_BIT_BASE_MASK) == OP_BR_BIT_BASE; |
68 | } |
69 | |
70 | enum br_mask { |
71 | BR_BEQ = 0x00, |
72 | BR_BNE = 0x01, |
73 | BR_BMI = 0x02, |
74 | BR_BHS = 0x04, |
75 | BR_BCC = 0x05, |
76 | BR_BLO = 0x05, |
77 | BR_BGE = 0x08, |
78 | BR_BLT = 0x09, |
79 | BR_UNC = 0x18, |
80 | }; |
81 | |
82 | enum br_ev_pip { |
83 | BR_EV_PIP_UNCOND = 0, |
84 | BR_EV_PIP_COND = 1, |
85 | }; |
86 | |
87 | enum br_ctx_signal_state { |
88 | BR_CSS_NONE = 2, |
89 | }; |
90 | |
91 | u16 br_get_offset(u64 instr); |
92 | void br_set_offset(u64 *instr, u16 offset); |
93 | void br_add_offset(u64 *instr, u16 offset); |
94 | |
95 | #define OP_BBYTE_BASE 0x0c800000000ULL |
96 | #define OP_BB_A_SRC 0x000000000ffULL |
97 | #define OP_BB_BYTE 0x00000000300ULL |
98 | #define OP_BB_B_SRC 0x0000003fc00ULL |
99 | #define OP_BB_I8 0x00000040000ULL |
100 | #define OP_BB_EQ 0x00000080000ULL |
101 | #define OP_BB_DEFBR 0x00000300000ULL |
102 | #define OP_BB_ADDR_LO 0x007ffc00000ULL |
103 | #define OP_BB_ADDR_HI 0x10000000000ULL |
104 | #define OP_BB_SRC_LMEXTN 0x40000000000ULL |
105 | |
106 | #define OP_BALU_BASE 0x0e800000000ULL |
107 | #define OP_BA_A_SRC 0x000000003ffULL |
108 | #define OP_BA_B_SRC 0x000000ffc00ULL |
109 | #define OP_BA_DEFBR 0x00000300000ULL |
110 | #define OP_BA_ADDR_HI 0x0007fc00000ULL |
111 | |
112 | #define OP_IMMED_A_SRC 0x000000003ffULL |
113 | #define OP_IMMED_B_SRC 0x000000ffc00ULL |
114 | #define OP_IMMED_IMM 0x0000ff00000ULL |
115 | #define OP_IMMED_WIDTH 0x00060000000ULL |
116 | #define OP_IMMED_INV 0x00080000000ULL |
117 | #define OP_IMMED_SHIFT 0x00600000000ULL |
118 | #define OP_IMMED_BASE 0x0f000000000ULL |
119 | #define OP_IMMED_WR_AB 0x20000000000ULL |
120 | #define OP_IMMED_SRC_LMEXTN 0x40000000000ULL |
121 | #define OP_IMMED_DST_LMEXTN 0x80000000000ULL |
122 | |
123 | enum immed_width { |
124 | IMMED_WIDTH_ALL = 0, |
125 | IMMED_WIDTH_BYTE = 1, |
126 | IMMED_WIDTH_WORD = 2, |
127 | }; |
128 | |
129 | enum immed_shift { |
130 | IMMED_SHIFT_0B = 0, |
131 | IMMED_SHIFT_1B = 1, |
132 | IMMED_SHIFT_2B = 2, |
133 | }; |
134 | |
135 | u16 immed_get_value(u64 instr); |
136 | void immed_set_value(u64 *instr, u16 immed); |
137 | void immed_add_value(u64 *instr, u16 offset); |
138 | |
139 | #define OP_SHF_BASE 0x08000000000ULL |
140 | #define OP_SHF_A_SRC 0x000000000ffULL |
141 | #define OP_SHF_SC 0x00000000300ULL |
142 | #define OP_SHF_B_SRC 0x0000003fc00ULL |
143 | #define OP_SHF_I8 0x00000040000ULL |
144 | #define OP_SHF_SW 0x00000080000ULL |
145 | #define OP_SHF_DST 0x0000ff00000ULL |
146 | #define OP_SHF_SHIFT 0x001f0000000ULL |
147 | #define OP_SHF_OP 0x00e00000000ULL |
148 | #define OP_SHF_DST_AB 0x01000000000ULL |
149 | #define OP_SHF_WR_AB 0x20000000000ULL |
150 | #define OP_SHF_SRC_LMEXTN 0x40000000000ULL |
151 | #define OP_SHF_DST_LMEXTN 0x80000000000ULL |
152 | |
153 | enum shf_op { |
154 | SHF_OP_NONE = 0, |
155 | SHF_OP_AND = 2, |
156 | SHF_OP_OR = 5, |
157 | SHF_OP_ASHR = 6, |
158 | }; |
159 | |
160 | enum shf_sc { |
161 | SHF_SC_R_ROT = 0, |
162 | SHF_SC_NONE = SHF_SC_R_ROT, |
163 | SHF_SC_R_SHF = 1, |
164 | SHF_SC_L_SHF = 2, |
165 | SHF_SC_R_DSHF = 3, |
166 | }; |
167 | |
168 | #define OP_ALU_A_SRC 0x000000003ffULL |
169 | #define OP_ALU_B_SRC 0x000000ffc00ULL |
170 | #define OP_ALU_DST 0x0003ff00000ULL |
171 | #define OP_ALU_SW 0x00040000000ULL |
172 | #define OP_ALU_OP 0x00f80000000ULL |
173 | #define OP_ALU_DST_AB 0x01000000000ULL |
174 | #define OP_ALU_BASE 0x0a000000000ULL |
175 | #define OP_ALU_WR_AB 0x20000000000ULL |
176 | #define OP_ALU_SRC_LMEXTN 0x40000000000ULL |
177 | #define OP_ALU_DST_LMEXTN 0x80000000000ULL |
178 | |
179 | enum alu_op { |
180 | ALU_OP_NONE = 0x00, |
181 | ALU_OP_ADD = 0x01, |
182 | ALU_OP_NOT = 0x04, |
183 | ALU_OP_ADD_2B = 0x05, |
184 | ALU_OP_AND = 0x08, |
185 | ALU_OP_AND_NOT_A = 0x0c, |
186 | ALU_OP_SUB_C = 0x0d, |
187 | ALU_OP_AND_NOT_B = 0x10, |
188 | ALU_OP_ADD_C = 0x11, |
189 | ALU_OP_OR = 0x14, |
190 | ALU_OP_SUB = 0x15, |
191 | ALU_OP_XOR = 0x18, |
192 | }; |
193 | |
194 | enum alu_dst_ab { |
195 | ALU_DST_A = 0, |
196 | ALU_DST_B = 1, |
197 | }; |
198 | |
199 | #define OP_LDF_BASE 0x0c000000000ULL |
200 | #define OP_LDF_A_SRC 0x000000000ffULL |
201 | #define OP_LDF_SC 0x00000000300ULL |
202 | #define OP_LDF_B_SRC 0x0000003fc00ULL |
203 | #define OP_LDF_I8 0x00000040000ULL |
204 | #define OP_LDF_SW 0x00000080000ULL |
205 | #define OP_LDF_ZF 0x00000100000ULL |
206 | #define OP_LDF_BMASK 0x0000f000000ULL |
207 | #define OP_LDF_SHF 0x001f0000000ULL |
208 | #define OP_LDF_WR_AB 0x20000000000ULL |
209 | #define OP_LDF_SRC_LMEXTN 0x40000000000ULL |
210 | #define OP_LDF_DST_LMEXTN 0x80000000000ULL |
211 | |
212 | #define OP_CMD_A_SRC 0x000000000ffULL |
213 | #define OP_CMD_CTX 0x00000000300ULL |
214 | #define OP_CMD_B_SRC 0x0000003fc00ULL |
215 | #define OP_CMD_TOKEN 0x000000c0000ULL |
216 | #define OP_CMD_XFER 0x00001f00000ULL |
217 | #define OP_CMD_CNT 0x0000e000000ULL |
218 | #define OP_CMD_SIG 0x000f0000000ULL |
219 | #define OP_CMD_TGT_CMD 0x07f00000000ULL |
220 | #define OP_CMD_INDIR 0x20000000000ULL |
221 | #define OP_CMD_MODE 0x1c0000000000ULL |
222 | |
223 | struct cmd_tgt_act { |
224 | u8 token; |
225 | u8 tgt_cmd; |
226 | }; |
227 | |
228 | enum cmd_tgt_map { |
229 | CMD_TGT_READ8, |
230 | CMD_TGT_WRITE8_SWAP, |
231 | CMD_TGT_WRITE32_SWAP, |
232 | CMD_TGT_READ32, |
233 | CMD_TGT_READ32_LE, |
234 | CMD_TGT_READ32_SWAP, |
235 | CMD_TGT_READ_LE, |
236 | CMD_TGT_READ_SWAP_LE, |
237 | CMD_TGT_ADD, |
238 | CMD_TGT_ADD_IMM, |
239 | __CMD_TGT_MAP_SIZE, |
240 | }; |
241 | |
242 | extern const struct cmd_tgt_act cmd_tgt_act[__CMD_TGT_MAP_SIZE]; |
243 | |
244 | enum cmd_mode { |
245 | CMD_MODE_40b_AB = 0, |
246 | CMD_MODE_40b_BA = 1, |
247 | CMD_MODE_32b = 4, |
248 | }; |
249 | |
250 | enum cmd_ctx_swap { |
251 | CMD_CTX_SWAP = 0, |
252 | CMD_CTX_SWAP_DEFER1 = 1, |
253 | CMD_CTX_SWAP_DEFER2 = 2, |
254 | CMD_CTX_NO_SWAP = 3, |
255 | }; |
256 | |
257 | #define CMD_OVE_DATA GENMASK(5, 3) |
258 | #define CMD_OVE_LEN BIT(7) |
259 | #define CMD_OV_LEN GENMASK(12, 8) |
260 | |
261 | #define OP_LCSR_BASE 0x0fc00000000ULL |
262 | #define OP_LCSR_A_SRC 0x000000003ffULL |
263 | #define OP_LCSR_B_SRC 0x000000ffc00ULL |
264 | #define OP_LCSR_WRITE 0x00000200000ULL |
265 | #define OP_LCSR_ADDR 0x001ffc00000ULL |
266 | #define OP_LCSR_SRC_LMEXTN 0x40000000000ULL |
267 | #define OP_LCSR_DST_LMEXTN 0x80000000000ULL |
268 | |
269 | enum lcsr_wr_src { |
270 | LCSR_WR_AREG, |
271 | LCSR_WR_BREG, |
272 | LCSR_WR_IMM, |
273 | }; |
274 | |
275 | #define OP_CARB_BASE 0x0e000000000ULL |
276 | #define OP_CARB_OR 0x00000010000ULL |
277 | |
278 | #define NFP_CSR_CTX_PTR 0x20 |
279 | #define NFP_CSR_ACT_LM_ADDR0 0x64 |
280 | #define NFP_CSR_ACT_LM_ADDR1 0x6c |
281 | #define NFP_CSR_ACT_LM_ADDR2 0x94 |
282 | #define NFP_CSR_ACT_LM_ADDR3 0x9c |
283 | #define NFP_CSR_PSEUDO_RND_NUM 0x148 |
284 | |
285 | /* Software register representation, independent of operand type */ |
286 | #define NN_REG_TYPE GENMASK(31, 24) |
287 | #define NN_REG_LM_IDX GENMASK(23, 22) |
288 | #define NN_REG_LM_IDX_HI BIT(23) |
289 | #define NN_REG_LM_IDX_LO BIT(22) |
290 | #define NN_REG_LM_MOD GENMASK(21, 20) |
291 | #define NN_REG_VAL GENMASK(7, 0) |
292 | |
293 | enum nfp_bpf_reg_type { |
294 | NN_REG_GPR_A = BIT(0), |
295 | NN_REG_GPR_B = BIT(1), |
296 | NN_REG_GPR_BOTH = NN_REG_GPR_A | NN_REG_GPR_B, |
297 | NN_REG_NNR = BIT(2), |
298 | NN_REG_XFER = BIT(3), |
299 | NN_REG_IMM = BIT(4), |
300 | NN_REG_NONE = BIT(5), |
301 | NN_REG_LMEM = BIT(6), |
302 | }; |
303 | |
304 | enum nfp_bpf_lm_mode { |
305 | NN_LM_MOD_NONE = 0, |
306 | NN_LM_MOD_INC, |
307 | NN_LM_MOD_DEC, |
308 | }; |
309 | |
310 | #define reg_both(x) __enc_swreg((x), NN_REG_GPR_BOTH) |
311 | #define reg_a(x) __enc_swreg((x), NN_REG_GPR_A) |
312 | #define reg_b(x) __enc_swreg((x), NN_REG_GPR_B) |
313 | #define reg_nnr(x) __enc_swreg((x), NN_REG_NNR) |
314 | #define reg_xfer(x) __enc_swreg((x), NN_REG_XFER) |
315 | #define reg_imm(x) __enc_swreg((x), NN_REG_IMM) |
316 | #define reg_none() __enc_swreg(0, NN_REG_NONE) |
317 | #define reg_lm(x, off) __enc_swreg_lm((x), NN_LM_MOD_NONE, (off)) |
318 | #define reg_lm_inc(x) __enc_swreg_lm((x), NN_LM_MOD_INC, 0) |
319 | #define reg_lm_dec(x) __enc_swreg_lm((x), NN_LM_MOD_DEC, 0) |
320 | #define __reg_lm(x, mod, off) __enc_swreg_lm((x), (mod), (off)) |
321 | |
322 | typedef __u32 __bitwise swreg; |
323 | |
324 | static inline swreg __enc_swreg(u16 id, u8 type) |
325 | { |
326 | return (__force swreg)(id | FIELD_PREP(NN_REG_TYPE, type)); |
327 | } |
328 | |
329 | static inline swreg __enc_swreg_lm(u8 id, enum nfp_bpf_lm_mode mode, u8 off) |
330 | { |
331 | WARN_ON(id > 3 || (off && mode != NN_LM_MOD_NONE)); |
332 | |
333 | return (__force swreg)(FIELD_PREP(NN_REG_TYPE, NN_REG_LMEM) | |
334 | FIELD_PREP(NN_REG_LM_IDX, id) | |
335 | FIELD_PREP(NN_REG_LM_MOD, mode) | |
336 | off); |
337 | } |
338 | |
339 | static inline u32 swreg_raw(swreg reg) |
340 | { |
341 | return (__force u32)reg; |
342 | } |
343 | |
344 | static inline enum nfp_bpf_reg_type swreg_type(swreg reg) |
345 | { |
346 | return FIELD_GET(NN_REG_TYPE, swreg_raw(reg)); |
347 | } |
348 | |
349 | static inline u16 swreg_value(swreg reg) |
350 | { |
351 | return FIELD_GET(NN_REG_VAL, swreg_raw(reg)); |
352 | } |
353 | |
354 | static inline bool swreg_lm_idx(swreg reg) |
355 | { |
356 | return FIELD_GET(NN_REG_LM_IDX_LO, swreg_raw(reg)); |
357 | } |
358 | |
359 | static inline bool swreg_lmextn(swreg reg) |
360 | { |
361 | return FIELD_GET(NN_REG_LM_IDX_HI, swreg_raw(reg)); |
362 | } |
363 | |
364 | static inline enum nfp_bpf_lm_mode swreg_lm_mode(swreg reg) |
365 | { |
366 | return FIELD_GET(NN_REG_LM_MOD, swreg_raw(reg)); |
367 | } |
368 | |
369 | struct nfp_insn_ur_regs { |
370 | enum alu_dst_ab dst_ab; |
371 | u16 dst; |
372 | u16 areg, breg; |
373 | bool swap; |
374 | bool wr_both; |
375 | bool dst_lmextn; |
376 | bool src_lmextn; |
377 | }; |
378 | |
379 | struct nfp_insn_re_regs { |
380 | enum alu_dst_ab dst_ab; |
381 | u8 dst; |
382 | u8 areg, breg; |
383 | bool swap; |
384 | bool wr_both; |
385 | bool i8; |
386 | bool dst_lmextn; |
387 | bool src_lmextn; |
388 | }; |
389 | |
390 | int swreg_to_unrestricted(swreg dst, swreg lreg, swreg rreg, |
391 | struct nfp_insn_ur_regs *reg); |
392 | int swreg_to_restricted(swreg dst, swreg lreg, swreg rreg, |
393 | struct nfp_insn_re_regs *reg, bool has_imm8); |
394 | |
395 | #define NFP_USTORE_PREFETCH_WINDOW 8 |
396 | |
397 | int nfp_ustore_check_valid_no_ecc(u64 insn); |
398 | u64 nfp_ustore_calc_ecc_insn(u64 insn); |
399 | |
400 | #define NFP_IND_ME_REFL_WR_SIG_INIT 3 |
401 | #define NFP_IND_ME_CTX_PTR_BASE_MASK GENMASK(9, 0) |
402 | #define NFP_IND_NUM_CONTEXTS 8 |
403 | |
404 | static inline u32 nfp_get_ind_csr_ctx_ptr_offs(u32 read_offset) |
405 | { |
406 | return (read_offset & ~NFP_IND_ME_CTX_PTR_BASE_MASK) | NFP_CSR_CTX_PTR; |
407 | } |
408 | |
409 | enum mul_type { |
410 | MUL_TYPE_START = 0x00, |
411 | MUL_TYPE_STEP_24x8 = 0x01, |
412 | MUL_TYPE_STEP_16x16 = 0x02, |
413 | MUL_TYPE_STEP_32x32 = 0x03, |
414 | }; |
415 | |
416 | enum mul_step { |
417 | MUL_STEP_1 = 0x00, |
418 | MUL_STEP_NONE = MUL_STEP_1, |
419 | MUL_STEP_2 = 0x01, |
420 | MUL_STEP_3 = 0x02, |
421 | MUL_STEP_4 = 0x03, |
422 | MUL_LAST = 0x04, |
423 | MUL_LAST_2 = 0x05, |
424 | }; |
425 | |
426 | #define OP_MUL_BASE 0x0f800000000ULL |
427 | #define OP_MUL_A_SRC 0x000000003ffULL |
428 | #define OP_MUL_B_SRC 0x000000ffc00ULL |
429 | #define OP_MUL_STEP 0x00000700000ULL |
430 | #define OP_MUL_DST_AB 0x00000800000ULL |
431 | #define OP_MUL_SW 0x00040000000ULL |
432 | #define OP_MUL_TYPE 0x00180000000ULL |
433 | #define OP_MUL_WR_AB 0x20000000000ULL |
434 | #define OP_MUL_SRC_LMEXTN 0x40000000000ULL |
435 | #define OP_MUL_DST_LMEXTN 0x80000000000ULL |
436 | |
437 | #endif |
438 | |