pipeline: fix emit instruction for invalid headers
[dpdk.git] / lib / pipeline / rte_swx_pipeline_internal.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2021 Intel Corporation
3  */
4 #ifndef __INCLUDE_RTE_SWX_PIPELINE_INTERNAL_H__
5 #define __INCLUDE_RTE_SWX_PIPELINE_INTERNAL_H__
6
7 #include <inttypes.h>
8 #include <string.h>
9 #include <sys/queue.h>
10
11 #include <rte_byteorder.h>
12 #include <rte_common.h>
13 #include <rte_cycles.h>
14 #include <rte_prefetch.h>
15 #include <rte_meter.h>
16
17 #include <rte_swx_table_selector.h>
18 #include <rte_swx_table_learner.h>
19 #include <rte_swx_pipeline.h>
20 #include <rte_swx_ctl.h>
21
22 #ifndef TRACE_LEVEL
23 #define TRACE_LEVEL 0
24 #endif
25
26 #if TRACE_LEVEL
27 #define TRACE(...) printf(__VA_ARGS__)
28 #else
29 #define TRACE(...)
30 #endif
31
32 /*
33  * Environment.
34  */
35 #define ntoh64(x) rte_be_to_cpu_64(x)
36 #define hton64(x) rte_cpu_to_be_64(x)
37
38 /*
39  * Struct.
40  */
41 struct field {
42         char name[RTE_SWX_NAME_SIZE];
43         uint32_t n_bits;
44         uint32_t offset;
45         int var_size;
46 };
47
48 struct struct_type {
49         TAILQ_ENTRY(struct_type) node;
50         char name[RTE_SWX_NAME_SIZE];
51         struct field *fields;
52         uint32_t n_fields;
53         uint32_t n_bits;
54         uint32_t n_bits_min;
55         int var_size;
56 };
57
58 TAILQ_HEAD(struct_type_tailq, struct_type);
59
60 /*
61  * Input port.
62  */
63 struct port_in_type {
64         TAILQ_ENTRY(port_in_type) node;
65         char name[RTE_SWX_NAME_SIZE];
66         struct rte_swx_port_in_ops ops;
67 };
68
69 TAILQ_HEAD(port_in_type_tailq, port_in_type);
70
71 struct port_in {
72         TAILQ_ENTRY(port_in) node;
73         struct port_in_type *type;
74         void *obj;
75         uint32_t id;
76 };
77
78 TAILQ_HEAD(port_in_tailq, port_in);
79
80 struct port_in_runtime {
81         rte_swx_port_in_pkt_rx_t pkt_rx;
82         void *obj;
83 };
84
85 /*
86  * Output port.
87  */
88 struct port_out_type {
89         TAILQ_ENTRY(port_out_type) node;
90         char name[RTE_SWX_NAME_SIZE];
91         struct rte_swx_port_out_ops ops;
92 };
93
94 TAILQ_HEAD(port_out_type_tailq, port_out_type);
95
96 struct port_out {
97         TAILQ_ENTRY(port_out) node;
98         struct port_out_type *type;
99         void *obj;
100         uint32_t id;
101 };
102
103 TAILQ_HEAD(port_out_tailq, port_out);
104
105 struct port_out_runtime {
106         rte_swx_port_out_pkt_tx_t pkt_tx;
107         rte_swx_port_out_flush_t flush;
108         void *obj;
109 };
110
111 /*
112  * Extern object.
113  */
114 struct extern_type_member_func {
115         TAILQ_ENTRY(extern_type_member_func) node;
116         char name[RTE_SWX_NAME_SIZE];
117         rte_swx_extern_type_member_func_t func;
118         uint32_t id;
119 };
120
121 TAILQ_HEAD(extern_type_member_func_tailq, extern_type_member_func);
122
123 struct extern_type {
124         TAILQ_ENTRY(extern_type) node;
125         char name[RTE_SWX_NAME_SIZE];
126         struct struct_type *mailbox_struct_type;
127         rte_swx_extern_type_constructor_t constructor;
128         rte_swx_extern_type_destructor_t destructor;
129         struct extern_type_member_func_tailq funcs;
130         uint32_t n_funcs;
131 };
132
133 TAILQ_HEAD(extern_type_tailq, extern_type);
134
135 struct extern_obj {
136         TAILQ_ENTRY(extern_obj) node;
137         char name[RTE_SWX_NAME_SIZE];
138         struct extern_type *type;
139         void *obj;
140         uint32_t struct_id;
141         uint32_t id;
142 };
143
144 TAILQ_HEAD(extern_obj_tailq, extern_obj);
145
146 #ifndef RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX
147 #define RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX 8
148 #endif
149
150 struct extern_obj_runtime {
151         void *obj;
152         uint8_t *mailbox;
153         rte_swx_extern_type_member_func_t funcs[RTE_SWX_EXTERN_TYPE_MEMBER_FUNCS_MAX];
154 };
155
156 /*
157  * Extern function.
158  */
159 struct extern_func {
160         TAILQ_ENTRY(extern_func) node;
161         char name[RTE_SWX_NAME_SIZE];
162         struct struct_type *mailbox_struct_type;
163         rte_swx_extern_func_t func;
164         uint32_t struct_id;
165         uint32_t id;
166 };
167
168 TAILQ_HEAD(extern_func_tailq, extern_func);
169
170 struct extern_func_runtime {
171         uint8_t *mailbox;
172         rte_swx_extern_func_t func;
173 };
174
175 /*
176  * Header.
177  */
178 struct header {
179         TAILQ_ENTRY(header) node;
180         char name[RTE_SWX_NAME_SIZE];
181         struct struct_type *st;
182         uint32_t struct_id;
183         uint32_t id;
184 };
185
186 TAILQ_HEAD(header_tailq, header);
187
188 struct header_runtime {
189         uint8_t *ptr0;
190         uint32_t n_bytes;
191 };
192
193 struct header_out_runtime {
194         uint8_t *ptr0;
195         uint8_t *ptr;
196         uint32_t n_bytes;
197 };
198
199 /*
200  * Instruction.
201  */
202
203 /* Packet headers are always in Network Byte Order (NBO), i.e. big endian.
204  * Packet meta-data fields are always assumed to be in Host Byte Order (HBO).
205  * Table entry fields can be in either NBO or HBO; they are assumed to be in HBO
206  * when transferred to packet meta-data and in NBO when transferred to packet
207  * headers.
208  */
209
210 /* Notation conventions:
211  *    -Header field: H = h.header.field (dst/src)
212  *    -Meta-data field: M = m.field (dst/src)
213  *    -Extern object mailbox field: E = e.field (dst/src)
214  *    -Extern function mailbox field: F = f.field (dst/src)
215  *    -Table action data field: T = t.field (src only)
216  *    -Immediate value: I = 32-bit unsigned value (src only)
217  */
218
219 enum instruction_type {
220         /* rx m.port_in */
221         INSTR_RX,
222
223         /* tx port_out
224          * port_out = MI
225          */
226         INSTR_TX,   /* port_out = M */
227         INSTR_TX_I, /* port_out = I */
228         INSTR_DROP,
229
230         /* extract h.header */
231         INSTR_HDR_EXTRACT,
232         INSTR_HDR_EXTRACT2,
233         INSTR_HDR_EXTRACT3,
234         INSTR_HDR_EXTRACT4,
235         INSTR_HDR_EXTRACT5,
236         INSTR_HDR_EXTRACT6,
237         INSTR_HDR_EXTRACT7,
238         INSTR_HDR_EXTRACT8,
239
240         /* extract h.header m.last_field_size */
241         INSTR_HDR_EXTRACT_M,
242
243         /* lookahead h.header */
244         INSTR_HDR_LOOKAHEAD,
245
246         /* emit h.header */
247         INSTR_HDR_EMIT,
248         INSTR_HDR_EMIT_TX,
249         INSTR_HDR_EMIT2_TX,
250         INSTR_HDR_EMIT3_TX,
251         INSTR_HDR_EMIT4_TX,
252         INSTR_HDR_EMIT5_TX,
253         INSTR_HDR_EMIT6_TX,
254         INSTR_HDR_EMIT7_TX,
255         INSTR_HDR_EMIT8_TX,
256
257         /* validate h.header */
258         INSTR_HDR_VALIDATE,
259
260         /* invalidate h.header */
261         INSTR_HDR_INVALIDATE,
262
263         /* mov dst src
264          * dst = src
265          * dst = HMEF, src = HMEFTI
266          */
267         INSTR_MOV,    /* dst = MEF, src = MEFT */
268         INSTR_MOV_MH, /* dst = MEF, src = H */
269         INSTR_MOV_HM, /* dst = H, src = MEFT */
270         INSTR_MOV_HH, /* dst = H, src = H */
271         INSTR_MOV_I,  /* dst = HMEF, src = I */
272
273         /* dma h.header t.field
274          * memcpy(h.header, t.field, sizeof(h.header))
275          */
276         INSTR_DMA_HT,
277         INSTR_DMA_HT2,
278         INSTR_DMA_HT3,
279         INSTR_DMA_HT4,
280         INSTR_DMA_HT5,
281         INSTR_DMA_HT6,
282         INSTR_DMA_HT7,
283         INSTR_DMA_HT8,
284
285         /* add dst src
286          * dst += src
287          * dst = HMEF, src = HMEFTI
288          */
289         INSTR_ALU_ADD,    /* dst = MEF, src = MEF */
290         INSTR_ALU_ADD_MH, /* dst = MEF, src = H */
291         INSTR_ALU_ADD_HM, /* dst = H, src = MEF */
292         INSTR_ALU_ADD_HH, /* dst = H, src = H */
293         INSTR_ALU_ADD_MI, /* dst = MEF, src = I */
294         INSTR_ALU_ADD_HI, /* dst = H, src = I */
295
296         /* sub dst src
297          * dst -= src
298          * dst = HMEF, src = HMEFTI
299          */
300         INSTR_ALU_SUB,    /* dst = MEF, src = MEF */
301         INSTR_ALU_SUB_MH, /* dst = MEF, src = H */
302         INSTR_ALU_SUB_HM, /* dst = H, src = MEF */
303         INSTR_ALU_SUB_HH, /* dst = H, src = H */
304         INSTR_ALU_SUB_MI, /* dst = MEF, src = I */
305         INSTR_ALU_SUB_HI, /* dst = H, src = I */
306
307         /* ckadd dst src
308          * dst = dst '+ src[0:1] '+ src[2:3] '+ ...
309          * dst = H, src = {H, h.header}, '+ = 1's complement addition operator
310          */
311         INSTR_ALU_CKADD_FIELD,    /* src = H */
312         INSTR_ALU_CKADD_STRUCT20, /* src = h.header, with sizeof(header) = 20 bytes. */
313         INSTR_ALU_CKADD_STRUCT,   /* src = h.header, with sizeof(header) any 4-byte multiple. */
314
315         /* cksub dst src
316          * dst = dst '- src
317          * dst = H, src = H, '- = 1's complement subtraction operator
318          */
319         INSTR_ALU_CKSUB_FIELD,
320
321         /* and dst src
322          * dst &= src
323          * dst = HMEF, src = HMEFTI
324          */
325         INSTR_ALU_AND,    /* dst = MEF, src = MEFT */
326         INSTR_ALU_AND_MH, /* dst = MEF, src = H */
327         INSTR_ALU_AND_HM, /* dst = H, src = MEFT */
328         INSTR_ALU_AND_HH, /* dst = H, src = H */
329         INSTR_ALU_AND_I,  /* dst = HMEF, src = I */
330
331         /* or dst src
332          * dst |= src
333          * dst = HMEF, src = HMEFTI
334          */
335         INSTR_ALU_OR,    /* dst = MEF, src = MEFT */
336         INSTR_ALU_OR_MH, /* dst = MEF, src = H */
337         INSTR_ALU_OR_HM, /* dst = H, src = MEFT */
338         INSTR_ALU_OR_HH, /* dst = H, src = H */
339         INSTR_ALU_OR_I,  /* dst = HMEF, src = I */
340
341         /* xor dst src
342          * dst ^= src
343          * dst = HMEF, src = HMEFTI
344          */
345         INSTR_ALU_XOR,    /* dst = MEF, src = MEFT */
346         INSTR_ALU_XOR_MH, /* dst = MEF, src = H */
347         INSTR_ALU_XOR_HM, /* dst = H, src = MEFT */
348         INSTR_ALU_XOR_HH, /* dst = H, src = H */
349         INSTR_ALU_XOR_I,  /* dst = HMEF, src = I */
350
351         /* shl dst src
352          * dst <<= src
353          * dst = HMEF, src = HMEFTI
354          */
355         INSTR_ALU_SHL,    /* dst = MEF, src = MEF */
356         INSTR_ALU_SHL_MH, /* dst = MEF, src = H */
357         INSTR_ALU_SHL_HM, /* dst = H, src = MEF */
358         INSTR_ALU_SHL_HH, /* dst = H, src = H */
359         INSTR_ALU_SHL_MI, /* dst = MEF, src = I */
360         INSTR_ALU_SHL_HI, /* dst = H, src = I */
361
362         /* shr dst src
363          * dst >>= src
364          * dst = HMEF, src = HMEFTI
365          */
366         INSTR_ALU_SHR,    /* dst = MEF, src = MEF */
367         INSTR_ALU_SHR_MH, /* dst = MEF, src = H */
368         INSTR_ALU_SHR_HM, /* dst = H, src = MEF */
369         INSTR_ALU_SHR_HH, /* dst = H, src = H */
370         INSTR_ALU_SHR_MI, /* dst = MEF, src = I */
371         INSTR_ALU_SHR_HI, /* dst = H, src = I */
372
373         /* regprefetch REGARRAY index
374          * prefetch REGARRAY[index]
375          * index = HMEFTI
376          */
377         INSTR_REGPREFETCH_RH, /* index = H */
378         INSTR_REGPREFETCH_RM, /* index = MEFT */
379         INSTR_REGPREFETCH_RI, /* index = I */
380
381         /* regrd dst REGARRAY index
382          * dst = REGARRAY[index]
383          * dst = HMEF, index = HMEFTI
384          */
385         INSTR_REGRD_HRH, /* dst = H, index = H */
386         INSTR_REGRD_HRM, /* dst = H, index = MEFT */
387         INSTR_REGRD_HRI, /* dst = H, index = I */
388         INSTR_REGRD_MRH, /* dst = MEF, index = H */
389         INSTR_REGRD_MRM, /* dst = MEF, index = MEFT */
390         INSTR_REGRD_MRI, /* dst = MEF, index = I */
391
392         /* regwr REGARRAY index src
393          * REGARRAY[index] = src
394          * index = HMEFTI, src = HMEFTI
395          */
396         INSTR_REGWR_RHH, /* index = H, src = H */
397         INSTR_REGWR_RHM, /* index = H, src = MEFT */
398         INSTR_REGWR_RHI, /* index = H, src = I */
399         INSTR_REGWR_RMH, /* index = MEFT, src = H */
400         INSTR_REGWR_RMM, /* index = MEFT, src = MEFT */
401         INSTR_REGWR_RMI, /* index = MEFT, src = I */
402         INSTR_REGWR_RIH, /* index = I, src = H */
403         INSTR_REGWR_RIM, /* index = I, src = MEFT */
404         INSTR_REGWR_RII, /* index = I, src = I */
405
406         /* regadd REGARRAY index src
407          * REGARRAY[index] += src
408          * index = HMEFTI, src = HMEFTI
409          */
410         INSTR_REGADD_RHH, /* index = H, src = H */
411         INSTR_REGADD_RHM, /* index = H, src = MEFT */
412         INSTR_REGADD_RHI, /* index = H, src = I */
413         INSTR_REGADD_RMH, /* index = MEFT, src = H */
414         INSTR_REGADD_RMM, /* index = MEFT, src = MEFT */
415         INSTR_REGADD_RMI, /* index = MEFT, src = I */
416         INSTR_REGADD_RIH, /* index = I, src = H */
417         INSTR_REGADD_RIM, /* index = I, src = MEFT */
418         INSTR_REGADD_RII, /* index = I, src = I */
419
420         /* metprefetch METARRAY index
421          * prefetch METARRAY[index]
422          * index = HMEFTI
423          */
424         INSTR_METPREFETCH_H, /* index = H */
425         INSTR_METPREFETCH_M, /* index = MEFT */
426         INSTR_METPREFETCH_I, /* index = I */
427
428         /* meter METARRAY index length color_in color_out
429          * color_out = meter(METARRAY[index], length, color_in)
430          * index = HMEFTI, length = HMEFT, color_in = MEFTI, color_out = MEF
431          */
432         INSTR_METER_HHM, /* index = H, length = H, color_in = MEFT */
433         INSTR_METER_HHI, /* index = H, length = H, color_in = I */
434         INSTR_METER_HMM, /* index = H, length = MEFT, color_in = MEFT */
435         INSTR_METER_HMI, /* index = H, length = MEFT, color_in = I */
436         INSTR_METER_MHM, /* index = MEFT, length = H, color_in = MEFT */
437         INSTR_METER_MHI, /* index = MEFT, length = H, color_in = I */
438         INSTR_METER_MMM, /* index = MEFT, length = MEFT, color_in = MEFT */
439         INSTR_METER_MMI, /* index = MEFT, length = MEFT, color_in = I */
440         INSTR_METER_IHM, /* index = I, length = H, color_in = MEFT */
441         INSTR_METER_IHI, /* index = I, length = H, color_in = I */
442         INSTR_METER_IMM, /* index = I, length = MEFT, color_in = MEFT */
443         INSTR_METER_IMI, /* index = I, length = MEFT, color_in = I */
444
445         /* table TABLE */
446         INSTR_TABLE,
447         INSTR_TABLE_AF,
448         INSTR_SELECTOR,
449         INSTR_LEARNER,
450         INSTR_LEARNER_AF,
451
452         /* learn LEARNER ACTION_NAME [ m.action_first_arg ] */
453         INSTR_LEARNER_LEARN,
454
455         /* forget */
456         INSTR_LEARNER_FORGET,
457
458         /* extern e.obj.func */
459         INSTR_EXTERN_OBJ,
460
461         /* extern f.func */
462         INSTR_EXTERN_FUNC,
463
464         /* jmp LABEL
465          * Unconditional jump
466          */
467         INSTR_JMP,
468
469         /* jmpv LABEL h.header
470          * Jump if header is valid
471          */
472         INSTR_JMP_VALID,
473
474         /* jmpnv LABEL h.header
475          * Jump if header is invalid
476          */
477         INSTR_JMP_INVALID,
478
479         /* jmph LABEL
480          * Jump if table lookup hit
481          */
482         INSTR_JMP_HIT,
483
484         /* jmpnh LABEL
485          * Jump if table lookup miss
486          */
487         INSTR_JMP_MISS,
488
489         /* jmpa LABEL ACTION
490          * Jump if action run
491          */
492         INSTR_JMP_ACTION_HIT,
493
494         /* jmpna LABEL ACTION
495          * Jump if action not run
496          */
497         INSTR_JMP_ACTION_MISS,
498
499         /* jmpeq LABEL a b
500          * Jump if a is equal to b
501          * a = HMEFT, b = HMEFTI
502          */
503         INSTR_JMP_EQ,    /* a = MEFT, b = MEFT */
504         INSTR_JMP_EQ_MH, /* a = MEFT, b = H */
505         INSTR_JMP_EQ_HM, /* a = H, b = MEFT */
506         INSTR_JMP_EQ_HH, /* a = H, b = H */
507         INSTR_JMP_EQ_I,  /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
508
509         /* jmpneq LABEL a b
510          * Jump if a is not equal to b
511          * a = HMEFT, b = HMEFTI
512          */
513         INSTR_JMP_NEQ,    /* a = MEFT, b = MEFT */
514         INSTR_JMP_NEQ_MH, /* a = MEFT, b = H */
515         INSTR_JMP_NEQ_HM, /* a = H, b = MEFT */
516         INSTR_JMP_NEQ_HH, /* a = H, b = H */
517         INSTR_JMP_NEQ_I,  /* (a, b) = (MEFT, I) or (a, b) = (H, I) */
518
519         /* jmplt LABEL a b
520          * Jump if a is less than b
521          * a = HMEFT, b = HMEFTI
522          */
523         INSTR_JMP_LT,    /* a = MEFT, b = MEFT */
524         INSTR_JMP_LT_MH, /* a = MEFT, b = H */
525         INSTR_JMP_LT_HM, /* a = H, b = MEFT */
526         INSTR_JMP_LT_HH, /* a = H, b = H */
527         INSTR_JMP_LT_MI, /* a = MEFT, b = I */
528         INSTR_JMP_LT_HI, /* a = H, b = I */
529
530         /* jmpgt LABEL a b
531          * Jump if a is greater than b
532          * a = HMEFT, b = HMEFTI
533          */
534         INSTR_JMP_GT,    /* a = MEFT, b = MEFT */
535         INSTR_JMP_GT_MH, /* a = MEFT, b = H */
536         INSTR_JMP_GT_HM, /* a = H, b = MEFT */
537         INSTR_JMP_GT_HH, /* a = H, b = H */
538         INSTR_JMP_GT_MI, /* a = MEFT, b = I */
539         INSTR_JMP_GT_HI, /* a = H, b = I */
540
541         /* return
542          * Return from action
543          */
544         INSTR_RETURN,
545
546         /* Start of custom instructions. */
547         INSTR_CUSTOM_0,
548 };
549
550 struct instr_operand {
551         uint8_t struct_id;
552         uint8_t n_bits;
553         uint8_t offset;
554         uint8_t pad;
555 };
556
557 struct instr_io {
558         struct {
559                 union {
560                         struct {
561                                 uint8_t offset;
562                                 uint8_t n_bits;
563                                 uint8_t pad[2];
564                         };
565
566                         uint32_t val;
567                 };
568         } io;
569
570         struct {
571                 uint8_t header_id[8];
572                 uint8_t struct_id[8];
573                 uint8_t n_bytes[8];
574         } hdr;
575 };
576
577 struct instr_hdr_validity {
578         uint8_t header_id;
579 };
580
581 struct instr_table {
582         uint8_t table_id;
583 };
584
585 struct instr_learn {
586         uint8_t action_id;
587         uint8_t mf_offset;
588 };
589
590 struct instr_extern_obj {
591         uint8_t ext_obj_id;
592         uint8_t func_id;
593 };
594
595 struct instr_extern_func {
596         uint8_t ext_func_id;
597 };
598
599 struct instr_dst_src {
600         struct instr_operand dst;
601         union {
602                 struct instr_operand src;
603                 uint64_t src_val;
604         };
605 };
606
607 struct instr_regarray {
608         uint8_t regarray_id;
609         uint8_t pad[3];
610
611         union {
612                 struct instr_operand idx;
613                 uint32_t idx_val;
614         };
615
616         union {
617                 struct instr_operand dstsrc;
618                 uint64_t dstsrc_val;
619         };
620 };
621
622 struct instr_meter {
623         uint8_t metarray_id;
624         uint8_t pad[3];
625
626         union {
627                 struct instr_operand idx;
628                 uint32_t idx_val;
629         };
630
631         struct instr_operand length;
632
633         union {
634                 struct instr_operand color_in;
635                 uint32_t color_in_val;
636         };
637
638         struct instr_operand color_out;
639 };
640
641 struct instr_dma {
642         struct {
643                 uint8_t header_id[8];
644                 uint8_t struct_id[8];
645         } dst;
646
647         struct {
648                 uint8_t offset[8];
649         } src;
650
651         uint16_t n_bytes[8];
652 };
653
654 struct instr_jmp {
655         struct instruction *ip;
656
657         union {
658                 struct instr_operand a;
659                 uint8_t header_id;
660                 uint8_t action_id;
661         };
662
663         union {
664                 struct instr_operand b;
665                 uint64_t b_val;
666         };
667 };
668
669 struct instruction {
670         enum instruction_type type;
671         union {
672                 struct instr_io io;
673                 struct instr_hdr_validity valid;
674                 struct instr_dst_src mov;
675                 struct instr_regarray regarray;
676                 struct instr_meter meter;
677                 struct instr_dma dma;
678                 struct instr_dst_src alu;
679                 struct instr_table table;
680                 struct instr_learn learn;
681                 struct instr_extern_obj ext_obj;
682                 struct instr_extern_func ext_func;
683                 struct instr_jmp jmp;
684         };
685 };
686
687 struct instruction_data {
688         char label[RTE_SWX_NAME_SIZE];
689         char jmp_label[RTE_SWX_NAME_SIZE];
690         uint32_t n_users; /* user = jmp instruction to this instruction. */
691         int invalid;
692 };
693
694 typedef void (*instr_exec_t)(struct rte_swx_pipeline *);
695
696 /*
697  * Action.
698  */
699 typedef void
700 (*action_func_t)(struct rte_swx_pipeline *p);
701
702 struct action {
703         TAILQ_ENTRY(action) node;
704         char name[RTE_SWX_NAME_SIZE];
705         struct struct_type *st;
706         int *args_endianness; /* 0 = Host Byte Order (HBO); 1 = Network Byte Order (NBO). */
707         struct instruction *instructions;
708         struct instruction_data *instruction_data;
709         uint32_t n_instructions;
710         uint32_t id;
711 };
712
713 TAILQ_HEAD(action_tailq, action);
714
715 /*
716  * Table.
717  */
718 struct table_type {
719         TAILQ_ENTRY(table_type) node;
720         char name[RTE_SWX_NAME_SIZE];
721         enum rte_swx_table_match_type match_type;
722         struct rte_swx_table_ops ops;
723 };
724
725 TAILQ_HEAD(table_type_tailq, table_type);
726
727 struct match_field {
728         enum rte_swx_table_match_type match_type;
729         struct field *field;
730 };
731
732 struct table {
733         TAILQ_ENTRY(table) node;
734         char name[RTE_SWX_NAME_SIZE];
735         char args[RTE_SWX_NAME_SIZE];
736         struct table_type *type; /* NULL when n_fields == 0. */
737
738         /* Match. */
739         struct match_field *fields;
740         uint32_t n_fields;
741         struct header *header; /* Only valid when n_fields > 0. */
742
743         /* Action. */
744         struct action **actions;
745         struct action *default_action;
746         uint8_t *default_action_data;
747         uint32_t n_actions;
748         int default_action_is_const;
749         uint32_t action_data_size_max;
750         int *action_is_for_table_entries;
751         int *action_is_for_default_entry;
752
753         uint32_t size;
754         uint32_t id;
755 };
756
757 TAILQ_HEAD(table_tailq, table);
758
759 struct table_runtime {
760         rte_swx_table_lookup_t func;
761         void *mailbox;
762         uint8_t **key;
763 };
764
765 struct table_statistics {
766         uint64_t n_pkts_hit[2]; /* 0 = Miss, 1 = Hit. */
767         uint64_t *n_pkts_action;
768 };
769
770 /*
771  * Selector.
772  */
773 struct selector {
774         TAILQ_ENTRY(selector) node;
775         char name[RTE_SWX_NAME_SIZE];
776
777         struct field *group_id_field;
778         struct field **selector_fields;
779         uint32_t n_selector_fields;
780         struct header *selector_header;
781         struct field *member_id_field;
782
783         uint32_t n_groups_max;
784         uint32_t n_members_per_group_max;
785
786         uint32_t id;
787 };
788
789 TAILQ_HEAD(selector_tailq, selector);
790
791 struct selector_runtime {
792         void *mailbox;
793         uint8_t **group_id_buffer;
794         uint8_t **selector_buffer;
795         uint8_t **member_id_buffer;
796 };
797
798 struct selector_statistics {
799         uint64_t n_pkts;
800 };
801
802 /*
803  * Learner table.
804  */
805 struct learner {
806         TAILQ_ENTRY(learner) node;
807         char name[RTE_SWX_NAME_SIZE];
808
809         /* Match. */
810         struct field **fields;
811         uint32_t n_fields;
812         struct header *header;
813
814         /* Action. */
815         struct action **actions;
816         struct action *default_action;
817         uint8_t *default_action_data;
818         uint32_t n_actions;
819         int default_action_is_const;
820         uint32_t action_data_size_max;
821         int *action_is_for_table_entries;
822         int *action_is_for_default_entry;
823
824         uint32_t size;
825         uint32_t timeout;
826         uint32_t id;
827 };
828
829 TAILQ_HEAD(learner_tailq, learner);
830
831 struct learner_runtime {
832         void *mailbox;
833         uint8_t **key;
834 };
835
836 struct learner_statistics {
837         uint64_t n_pkts_hit[2]; /* 0 = Miss, 1 = Hit. */
838         uint64_t n_pkts_learn[2]; /* 0 = Learn OK, 1 = Learn error. */
839         uint64_t n_pkts_forget;
840         uint64_t *n_pkts_action;
841 };
842
843 /*
844  * Register array.
845  */
846 struct regarray {
847         TAILQ_ENTRY(regarray) node;
848         char name[RTE_SWX_NAME_SIZE];
849         uint64_t init_val;
850         uint32_t size;
851         uint32_t id;
852 };
853
854 TAILQ_HEAD(regarray_tailq, regarray);
855
856 struct regarray_runtime {
857         uint64_t *regarray;
858         uint32_t size_mask;
859 };
860
861 /*
862  * Meter array.
863  */
864 struct meter_profile {
865         TAILQ_ENTRY(meter_profile) node;
866         char name[RTE_SWX_NAME_SIZE];
867         struct rte_meter_trtcm_params params;
868         struct rte_meter_trtcm_profile profile;
869         uint32_t n_users;
870 };
871
872 TAILQ_HEAD(meter_profile_tailq, meter_profile);
873
874 struct metarray {
875         TAILQ_ENTRY(metarray) node;
876         char name[RTE_SWX_NAME_SIZE];
877         uint32_t size;
878         uint32_t id;
879 };
880
881 TAILQ_HEAD(metarray_tailq, metarray);
882
883 struct meter {
884         struct rte_meter_trtcm m;
885         struct meter_profile *profile;
886         enum rte_color color_mask;
887         uint8_t pad[20];
888
889         uint64_t n_pkts[RTE_COLORS];
890         uint64_t n_bytes[RTE_COLORS];
891 };
892
893 struct metarray_runtime {
894         struct meter *metarray;
895         uint32_t size_mask;
896 };
897
898 /*
899  * Pipeline.
900  */
901 struct thread {
902         /* Packet. */
903         struct rte_swx_pkt pkt;
904         uint8_t *ptr;
905
906         /* Structures. */
907         uint8_t **structs;
908
909         /* Packet headers. */
910         struct header_runtime *headers; /* Extracted or generated headers. */
911         struct header_out_runtime *headers_out; /* Emitted headers. */
912         uint8_t *header_storage;
913         uint8_t *header_out_storage;
914         uint64_t valid_headers;
915         uint32_t n_headers_out;
916
917         /* Packet meta-data. */
918         uint8_t *metadata;
919
920         /* Tables. */
921         struct table_runtime *tables;
922         struct selector_runtime *selectors;
923         struct learner_runtime *learners;
924         struct rte_swx_table_state *table_state;
925         uint64_t action_id;
926         int hit; /* 0 = Miss, 1 = Hit. */
927         uint32_t learner_id;
928         uint64_t time;
929
930         /* Extern objects and functions. */
931         struct extern_obj_runtime *extern_objs;
932         struct extern_func_runtime *extern_funcs;
933
934         /* Instructions. */
935         struct instruction *ip;
936         struct instruction *ret;
937 };
938
939 #define MASK64_BIT_GET(mask, pos) ((mask) & (1LLU << (pos)))
940 #define MASK64_BIT_SET(mask, pos) ((mask) | (1LLU << (pos)))
941 #define MASK64_BIT_CLR(mask, pos) ((mask) & ~(1LLU << (pos)))
942
943 #define HEADER_VALID(thread, header_id) \
944         MASK64_BIT_GET((thread)->valid_headers, header_id)
945
946 static inline uint64_t
947 instr_operand_hbo(struct thread *t, const struct instr_operand *x)
948 {
949         uint8_t *x_struct = t->structs[x->struct_id];
950         uint64_t *x64_ptr = (uint64_t *)&x_struct[x->offset];
951         uint64_t x64 = *x64_ptr;
952         uint64_t x64_mask = UINT64_MAX >> (64 - x->n_bits);
953
954         return x64 & x64_mask;
955 }
956
957 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
958
959 static inline uint64_t
960 instr_operand_nbo(struct thread *t, const struct instr_operand *x)
961 {
962         uint8_t *x_struct = t->structs[x->struct_id];
963         uint64_t *x64_ptr = (uint64_t *)&x_struct[x->offset];
964         uint64_t x64 = *x64_ptr;
965
966         return ntoh64(x64) >> (64 - x->n_bits);
967 }
968
969 #else
970
971 #define instr_operand_nbo instr_operand_hbo
972
973 #endif
974
975 #define ALU(thread, ip, operator)  \
976 {                                                                              \
977         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];      \
978         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];   \
979         uint64_t dst64 = *dst64_ptr;                                           \
980         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);       \
981         uint64_t dst = dst64 & dst64_mask;                                     \
982                                                                                \
983         uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id];      \
984         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset];   \
985         uint64_t src64 = *src64_ptr;                                           \
986         uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits);       \
987         uint64_t src = src64 & src64_mask;                                     \
988                                                                                \
989         uint64_t result = dst operator src;                                    \
990                                                                                \
991         *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask);            \
992 }
993
994 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
995
996 #define ALU_MH(thread, ip, operator)  \
997 {                                                                              \
998         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];      \
999         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];   \
1000         uint64_t dst64 = *dst64_ptr;                                           \
1001         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);       \
1002         uint64_t dst = dst64 & dst64_mask;                                     \
1003                                                                                \
1004         uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id];      \
1005         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset];   \
1006         uint64_t src64 = *src64_ptr;                                           \
1007         uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits);           \
1008                                                                                \
1009         uint64_t result = dst operator src;                                    \
1010                                                                                \
1011         *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask);            \
1012 }
1013
1014 #define ALU_HM(thread, ip, operator)  \
1015 {                                                                              \
1016         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];      \
1017         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];   \
1018         uint64_t dst64 = *dst64_ptr;                                           \
1019         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);       \
1020         uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits);           \
1021                                                                                \
1022         uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id];      \
1023         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset];   \
1024         uint64_t src64 = *src64_ptr;                                           \
1025         uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits);       \
1026         uint64_t src = src64 & src64_mask;                                     \
1027                                                                                \
1028         uint64_t result = dst operator src;                                    \
1029         result = hton64(result << (64 - (ip)->alu.dst.n_bits));                \
1030                                                                                \
1031         *dst64_ptr = (dst64 & ~dst64_mask) | result;                           \
1032 }
1033
1034 #define ALU_HM_FAST(thread, ip, operator)  \
1035 {                                                                                 \
1036         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];         \
1037         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];      \
1038         uint64_t dst64 = *dst64_ptr;                                              \
1039         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);          \
1040         uint64_t dst = dst64 & dst64_mask;                                        \
1041                                                                                   \
1042         uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id];         \
1043         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset];      \
1044         uint64_t src64 = *src64_ptr;                                              \
1045         uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->alu.src.n_bits);          \
1046         uint64_t src = hton64(src64 & src64_mask) >> (64 - (ip)->alu.dst.n_bits); \
1047                                                                                   \
1048         uint64_t result = dst operator src;                                       \
1049                                                                                   \
1050         *dst64_ptr = (dst64 & ~dst64_mask) | result;                              \
1051 }
1052
1053 #define ALU_HH(thread, ip, operator)  \
1054 {                                                                              \
1055         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];      \
1056         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];   \
1057         uint64_t dst64 = *dst64_ptr;                                           \
1058         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);       \
1059         uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits);           \
1060                                                                                \
1061         uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id];      \
1062         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset];   \
1063         uint64_t src64 = *src64_ptr;                                           \
1064         uint64_t src = ntoh64(src64) >> (64 - (ip)->alu.src.n_bits);           \
1065                                                                                \
1066         uint64_t result = dst operator src;                                    \
1067         result = hton64(result << (64 - (ip)->alu.dst.n_bits));                \
1068                                                                                \
1069         *dst64_ptr = (dst64 & ~dst64_mask) | result;                           \
1070 }
1071
1072 #define ALU_HH_FAST(thread, ip, operator)  \
1073 {                                                                                             \
1074         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];                     \
1075         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];                  \
1076         uint64_t dst64 = *dst64_ptr;                                                          \
1077         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);                      \
1078         uint64_t dst = dst64 & dst64_mask;                                                    \
1079                                                                                               \
1080         uint8_t *src_struct = (thread)->structs[(ip)->alu.src.struct_id];                     \
1081         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->alu.src.offset];                  \
1082         uint64_t src64 = *src64_ptr;                                                          \
1083         uint64_t src = (src64 << (64 - (ip)->alu.src.n_bits)) >> (64 - (ip)->alu.dst.n_bits); \
1084                                                                                               \
1085         uint64_t result = dst operator src;                                                   \
1086                                                                                               \
1087         *dst64_ptr = (dst64 & ~dst64_mask) | result;                                          \
1088 }
1089
1090 #else
1091
1092 #define ALU_MH ALU
1093 #define ALU_HM ALU
1094 #define ALU_HM_FAST ALU
1095 #define ALU_HH ALU
1096 #define ALU_HH_FAST ALU
1097
1098 #endif
1099
1100 #define ALU_I(thread, ip, operator)  \
1101 {                                                                              \
1102         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];      \
1103         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];   \
1104         uint64_t dst64 = *dst64_ptr;                                           \
1105         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);       \
1106         uint64_t dst = dst64 & dst64_mask;                                     \
1107                                                                                \
1108         uint64_t src = (ip)->alu.src_val;                                      \
1109                                                                                \
1110         uint64_t result = dst operator src;                                    \
1111                                                                                \
1112         *dst64_ptr = (dst64 & ~dst64_mask) | (result & dst64_mask);            \
1113 }
1114
1115 #define ALU_MI ALU_I
1116
1117 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1118
1119 #define ALU_HI(thread, ip, operator)  \
1120 {                                                                              \
1121         uint8_t *dst_struct = (thread)->structs[(ip)->alu.dst.struct_id];      \
1122         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->alu.dst.offset];   \
1123         uint64_t dst64 = *dst64_ptr;                                           \
1124         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->alu.dst.n_bits);       \
1125         uint64_t dst = ntoh64(dst64) >> (64 - (ip)->alu.dst.n_bits);           \
1126                                                                                \
1127         uint64_t src = (ip)->alu.src_val;                                      \
1128                                                                                \
1129         uint64_t result = dst operator src;                                    \
1130         result = hton64(result << (64 - (ip)->alu.dst.n_bits));                \
1131                                                                                \
1132         *dst64_ptr = (dst64 & ~dst64_mask) | result;                           \
1133 }
1134
1135 #else
1136
1137 #define ALU_HI ALU_I
1138
1139 #endif
1140
1141 #define MOV(thread, ip)  \
1142 {                                                                              \
1143         uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id];      \
1144         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset];   \
1145         uint64_t dst64 = *dst64_ptr;                                           \
1146         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits);       \
1147                                                                                \
1148         uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id];      \
1149         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset];   \
1150         uint64_t src64 = *src64_ptr;                                           \
1151         uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->mov.src.n_bits);       \
1152         uint64_t src = src64 & src64_mask;                                     \
1153                                                                                \
1154         *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);               \
1155 }
1156
1157 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1158
1159 #define MOV_MH(thread, ip)  \
1160 {                                                                              \
1161         uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id];      \
1162         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset];   \
1163         uint64_t dst64 = *dst64_ptr;                                           \
1164         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits);       \
1165                                                                                \
1166         uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id];      \
1167         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset];   \
1168         uint64_t src64 = *src64_ptr;                                           \
1169         uint64_t src = ntoh64(src64) >> (64 - (ip)->mov.src.n_bits);           \
1170                                                                                \
1171         *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);               \
1172 }
1173
1174 #define MOV_HM(thread, ip)  \
1175 {                                                                              \
1176         uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id];      \
1177         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset];   \
1178         uint64_t dst64 = *dst64_ptr;                                           \
1179         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits);       \
1180                                                                                \
1181         uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id];      \
1182         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset];   \
1183         uint64_t src64 = *src64_ptr;                                           \
1184         uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->mov.src.n_bits);       \
1185         uint64_t src = src64 & src64_mask;                                     \
1186                                                                                \
1187         src = hton64(src) >> (64 - (ip)->mov.dst.n_bits);                      \
1188         *dst64_ptr = (dst64 & ~dst64_mask) | src;                              \
1189 }
1190
1191 #define MOV_HH(thread, ip)  \
1192 {                                                                              \
1193         uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id];      \
1194         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset];   \
1195         uint64_t dst64 = *dst64_ptr;                                           \
1196         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits);       \
1197                                                                                \
1198         uint8_t *src_struct = (thread)->structs[(ip)->mov.src.struct_id];      \
1199         uint64_t *src64_ptr = (uint64_t *)&src_struct[(ip)->mov.src.offset];   \
1200         uint64_t src64 = *src64_ptr;                                           \
1201                                                                                \
1202         uint64_t src = src64 << (64 - (ip)->mov.src.n_bits);                   \
1203         src = src >> (64 - (ip)->mov.dst.n_bits);                              \
1204         *dst64_ptr = (dst64 & ~dst64_mask) | src;                              \
1205 }
1206
1207 #else
1208
1209 #define MOV_MH MOV
1210 #define MOV_HM MOV
1211 #define MOV_HH MOV
1212
1213 #endif
1214
1215 #define MOV_I(thread, ip)  \
1216 {                                                                              \
1217         uint8_t *dst_struct = (thread)->structs[(ip)->mov.dst.struct_id];      \
1218         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[(ip)->mov.dst.offset];   \
1219         uint64_t dst64 = *dst64_ptr;                                           \
1220         uint64_t dst64_mask = UINT64_MAX >> (64 - (ip)->mov.dst.n_bits);       \
1221                                                                                \
1222         uint64_t src = (ip)->mov.src_val;                                      \
1223                                                                                \
1224         *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);               \
1225 }
1226
1227 #define JMP_CMP(thread, ip, operator)  \
1228 {                                                                              \
1229         uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id];          \
1230         uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset];         \
1231         uint64_t a64 = *a64_ptr;                                               \
1232         uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits);           \
1233         uint64_t a = a64 & a64_mask;                                           \
1234                                                                                \
1235         uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id];          \
1236         uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset];         \
1237         uint64_t b64 = *b64_ptr;                                               \
1238         uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits);           \
1239         uint64_t b = b64 & b64_mask;                                           \
1240                                                                                \
1241         (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1);     \
1242 }
1243
1244 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1245
1246 #define JMP_CMP_MH(thread, ip, operator)  \
1247 {                                                                              \
1248         uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id];          \
1249         uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset];         \
1250         uint64_t a64 = *a64_ptr;                                               \
1251         uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits);           \
1252         uint64_t a = a64 & a64_mask;                                           \
1253                                                                                \
1254         uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id];          \
1255         uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset];         \
1256         uint64_t b64 = *b64_ptr;                                               \
1257         uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits);                 \
1258                                                                                \
1259         (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1);     \
1260 }
1261
1262 #define JMP_CMP_HM(thread, ip, operator)  \
1263 {                                                                              \
1264         uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id];          \
1265         uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset];         \
1266         uint64_t a64 = *a64_ptr;                                               \
1267         uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits);                 \
1268                                                                                \
1269         uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id];          \
1270         uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset];         \
1271         uint64_t b64 = *b64_ptr;                                               \
1272         uint64_t b64_mask = UINT64_MAX >> (64 - (ip)->jmp.b.n_bits);           \
1273         uint64_t b = b64 & b64_mask;                                           \
1274                                                                                \
1275         (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1);     \
1276 }
1277
1278 #define JMP_CMP_HH(thread, ip, operator)  \
1279 {                                                                              \
1280         uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id];          \
1281         uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset];         \
1282         uint64_t a64 = *a64_ptr;                                               \
1283         uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits);                 \
1284                                                                                \
1285         uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id];          \
1286         uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset];         \
1287         uint64_t b64 = *b64_ptr;                                               \
1288         uint64_t b = ntoh64(b64) >> (64 - (ip)->jmp.b.n_bits);                 \
1289                                                                                \
1290         (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1);     \
1291 }
1292
1293 #define JMP_CMP_HH_FAST(thread, ip, operator)  \
1294 {                                                                              \
1295         uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id];          \
1296         uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset];         \
1297         uint64_t a64 = *a64_ptr;                                               \
1298         uint64_t a = a64 << (64 - (ip)->jmp.a.n_bits);                         \
1299                                                                                \
1300         uint8_t *b_struct = (thread)->structs[(ip)->jmp.b.struct_id];          \
1301         uint64_t *b64_ptr = (uint64_t *)&b_struct[(ip)->jmp.b.offset];         \
1302         uint64_t b64 = *b64_ptr;                                               \
1303         uint64_t b = b64 << (64 - (ip)->jmp.b.n_bits);                         \
1304                                                                                \
1305         (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1);     \
1306 }
1307
1308 #else
1309
1310 #define JMP_CMP_MH JMP_CMP
1311 #define JMP_CMP_HM JMP_CMP
1312 #define JMP_CMP_HH JMP_CMP
1313 #define JMP_CMP_HH_FAST JMP_CMP
1314
1315 #endif
1316
1317 #define JMP_CMP_I(thread, ip, operator)  \
1318 {                                                                              \
1319         uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id];          \
1320         uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset];         \
1321         uint64_t a64 = *a64_ptr;                                               \
1322         uint64_t a64_mask = UINT64_MAX >> (64 - (ip)->jmp.a.n_bits);           \
1323         uint64_t a = a64 & a64_mask;                                           \
1324                                                                                \
1325         uint64_t b = (ip)->jmp.b_val;                                          \
1326                                                                                \
1327         (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1);     \
1328 }
1329
1330 #define JMP_CMP_MI JMP_CMP_I
1331
1332 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
1333
1334 #define JMP_CMP_HI(thread, ip, operator)  \
1335 {                                                                              \
1336         uint8_t *a_struct = (thread)->structs[(ip)->jmp.a.struct_id];          \
1337         uint64_t *a64_ptr = (uint64_t *)&a_struct[(ip)->jmp.a.offset];         \
1338         uint64_t a64 = *a64_ptr;                                               \
1339         uint64_t a = ntoh64(a64) >> (64 - (ip)->jmp.a.n_bits);                 \
1340                                                                                \
1341         uint64_t b = (ip)->jmp.b_val;                                          \
1342                                                                                \
1343         (thread)->ip = (a operator b) ? (ip)->jmp.ip : ((thread)->ip + 1);     \
1344 }
1345
1346 #else
1347
1348 #define JMP_CMP_HI JMP_CMP_I
1349
1350 #endif
1351
1352 #define METADATA_READ(thread, offset, n_bits)                                  \
1353 ({                                                                             \
1354         uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset];           \
1355         uint64_t m64 = *m64_ptr;                                               \
1356         uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits));                     \
1357         (m64 & m64_mask);                                                      \
1358 })
1359
1360 #define METADATA_WRITE(thread, offset, n_bits, value)                          \
1361 {                                                                              \
1362         uint64_t *m64_ptr = (uint64_t *)&(thread)->metadata[offset];           \
1363         uint64_t m64 = *m64_ptr;                                               \
1364         uint64_t m64_mask = UINT64_MAX >> (64 - (n_bits));                     \
1365                                                                                \
1366         uint64_t m_new = value;                                                \
1367                                                                                \
1368         *m64_ptr = (m64 & ~m64_mask) | (m_new & m64_mask);                     \
1369 }
1370
1371 #ifndef RTE_SWX_PIPELINE_THREADS_MAX
1372 #define RTE_SWX_PIPELINE_THREADS_MAX 16
1373 #endif
1374
1375 #ifndef RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX
1376 #define RTE_SWX_PIPELINE_INSTRUCTION_TABLE_SIZE_MAX 256
1377 #endif
1378
1379 struct rte_swx_pipeline {
1380         struct struct_type_tailq struct_types;
1381         struct port_in_type_tailq port_in_types;
1382         struct port_in_tailq ports_in;
1383         struct port_out_type_tailq port_out_types;
1384         struct port_out_tailq ports_out;
1385         struct extern_type_tailq extern_types;
1386         struct extern_obj_tailq extern_objs;
1387         struct extern_func_tailq extern_funcs;
1388         struct header_tailq headers;
1389         struct struct_type *metadata_st;
1390         uint32_t metadata_struct_id;
1391         struct action_tailq actions;
1392         struct table_type_tailq table_types;
1393         struct table_tailq tables;
1394         struct selector_tailq selectors;
1395         struct learner_tailq learners;
1396         struct regarray_tailq regarrays;
1397         struct meter_profile_tailq meter_profiles;
1398         struct metarray_tailq metarrays;
1399
1400         struct port_in_runtime *in;
1401         struct port_out_runtime *out;
1402         struct instruction **action_instructions;
1403         action_func_t *action_funcs;
1404         struct rte_swx_table_state *table_state;
1405         struct table_statistics *table_stats;
1406         struct selector_statistics *selector_stats;
1407         struct learner_statistics *learner_stats;
1408         struct regarray_runtime *regarray_runtime;
1409         struct metarray_runtime *metarray_runtime;
1410         struct instruction *instructions;
1411         struct instruction_data *instruction_data;
1412         instr_exec_t *instruction_table;
1413         struct thread threads[RTE_SWX_PIPELINE_THREADS_MAX];
1414         void *lib;
1415
1416         uint32_t n_structs;
1417         uint32_t n_ports_in;
1418         uint32_t n_ports_out;
1419         uint32_t n_extern_objs;
1420         uint32_t n_extern_funcs;
1421         uint32_t n_actions;
1422         uint32_t n_tables;
1423         uint32_t n_selectors;
1424         uint32_t n_learners;
1425         uint32_t n_regarrays;
1426         uint32_t n_metarrays;
1427         uint32_t n_headers;
1428         uint32_t thread_id;
1429         uint32_t port_id;
1430         uint32_t n_instructions;
1431         int build_done;
1432         int numa_node;
1433 };
1434
1435 /*
1436  * Instruction.
1437  */
1438 static inline void
1439 pipeline_port_inc(struct rte_swx_pipeline *p)
1440 {
1441         p->port_id = (p->port_id + 1) & (p->n_ports_in - 1);
1442 }
1443
1444 static inline void
1445 thread_ip_reset(struct rte_swx_pipeline *p, struct thread *t)
1446 {
1447         t->ip = p->instructions;
1448 }
1449
1450 static inline void
1451 thread_ip_set(struct thread *t, struct instruction *ip)
1452 {
1453         t->ip = ip;
1454 }
1455
1456 static inline void
1457 thread_ip_action_call(struct rte_swx_pipeline *p,
1458                       struct thread *t,
1459                       uint32_t action_id)
1460 {
1461         t->ret = t->ip + 1;
1462         t->ip = p->action_instructions[action_id];
1463 }
1464
1465 static inline void
1466 thread_ip_inc(struct rte_swx_pipeline *p);
1467
1468 static inline void
1469 thread_ip_inc(struct rte_swx_pipeline *p)
1470 {
1471         struct thread *t = &p->threads[p->thread_id];
1472
1473         t->ip++;
1474 }
1475
1476 static inline void
1477 thread_ip_inc_cond(struct thread *t, int cond)
1478 {
1479         t->ip += cond;
1480 }
1481
1482 static inline void
1483 thread_yield(struct rte_swx_pipeline *p)
1484 {
1485         p->thread_id = (p->thread_id + 1) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
1486 }
1487
1488 static inline void
1489 thread_yield_cond(struct rte_swx_pipeline *p, int cond)
1490 {
1491         p->thread_id = (p->thread_id + cond) & (RTE_SWX_PIPELINE_THREADS_MAX - 1);
1492 }
1493
1494 /*
1495  * rx.
1496  */
1497 static inline int
1498 __instr_rx_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
1499 {
1500         struct port_in_runtime *port = &p->in[p->port_id];
1501         struct rte_swx_pkt *pkt = &t->pkt;
1502         int pkt_received;
1503
1504         /* Packet. */
1505         pkt_received = port->pkt_rx(port->obj, pkt);
1506         t->ptr = &pkt->pkt[pkt->offset];
1507         rte_prefetch0(t->ptr);
1508
1509         TRACE("[Thread %2u] rx %s from port %u\n",
1510               p->thread_id,
1511               pkt_received ? "1 pkt" : "0 pkts",
1512               p->port_id);
1513
1514         /* Headers. */
1515         t->valid_headers = 0;
1516         t->n_headers_out = 0;
1517
1518         /* Meta-data. */
1519         METADATA_WRITE(t, ip->io.io.offset, ip->io.io.n_bits, p->port_id);
1520
1521         /* Tables. */
1522         t->table_state = p->table_state;
1523
1524         /* Thread. */
1525         pipeline_port_inc(p);
1526
1527         return pkt_received;
1528 }
1529
1530 static inline void
1531 instr_rx_exec(struct rte_swx_pipeline *p)
1532 {
1533         struct thread *t = &p->threads[p->thread_id];
1534         struct instruction *ip = t->ip;
1535         int pkt_received;
1536
1537         /* Packet. */
1538         pkt_received = __instr_rx_exec(p, t, ip);
1539
1540         /* Thread. */
1541         thread_ip_inc_cond(t, pkt_received);
1542         thread_yield(p);
1543 }
1544
1545 /*
1546  * tx.
1547  */
1548 static inline void
1549 emit_handler(struct thread *t)
1550 {
1551         struct header_out_runtime *h0 = &t->headers_out[0];
1552         struct header_out_runtime *h1 = &t->headers_out[1];
1553         uint32_t offset = 0, i;
1554
1555         /* No header change or header decapsulation. */
1556         if ((t->n_headers_out == 1) &&
1557             (h0->ptr + h0->n_bytes == t->ptr)) {
1558                 TRACE("Emit handler: no header change or header decap.\n");
1559
1560                 t->pkt.offset -= h0->n_bytes;
1561                 t->pkt.length += h0->n_bytes;
1562
1563                 return;
1564         }
1565
1566         /* Header encapsulation (optionally, with prior header decapsulation). */
1567         if ((t->n_headers_out == 2) &&
1568             (h1->ptr + h1->n_bytes == t->ptr) &&
1569             (h0->ptr == h0->ptr0)) {
1570                 uint32_t offset;
1571
1572                 TRACE("Emit handler: header encapsulation.\n");
1573
1574                 offset = h0->n_bytes + h1->n_bytes;
1575                 memcpy(t->ptr - offset, h0->ptr, h0->n_bytes);
1576                 t->pkt.offset -= offset;
1577                 t->pkt.length += offset;
1578
1579                 return;
1580         }
1581
1582         /* For any other case. */
1583         TRACE("Emit handler: complex case.\n");
1584
1585         for (i = 0; i < t->n_headers_out; i++) {
1586                 struct header_out_runtime *h = &t->headers_out[i];
1587
1588                 memcpy(&t->header_out_storage[offset], h->ptr, h->n_bytes);
1589                 offset += h->n_bytes;
1590         }
1591
1592         if (offset) {
1593                 memcpy(t->ptr - offset, t->header_out_storage, offset);
1594                 t->pkt.offset -= offset;
1595                 t->pkt.length += offset;
1596         }
1597 }
1598
1599 static inline void
1600 __instr_tx_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
1601 {
1602         uint64_t port_id = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
1603         struct port_out_runtime *port = &p->out[port_id];
1604         struct rte_swx_pkt *pkt = &t->pkt;
1605
1606         TRACE("[Thread %2u]: tx 1 pkt to port %u\n",
1607               p->thread_id,
1608               (uint32_t)port_id);
1609
1610         /* Headers. */
1611         emit_handler(t);
1612
1613         /* Packet. */
1614         port->pkt_tx(port->obj, pkt);
1615 }
1616
1617 static inline void
1618 __instr_tx_i_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
1619 {
1620         uint64_t port_id = ip->io.io.val;
1621         struct port_out_runtime *port = &p->out[port_id];
1622         struct rte_swx_pkt *pkt = &t->pkt;
1623
1624         TRACE("[Thread %2u]: tx (i) 1 pkt to port %u\n",
1625               p->thread_id,
1626               (uint32_t)port_id);
1627
1628         /* Headers. */
1629         emit_handler(t);
1630
1631         /* Packet. */
1632         port->pkt_tx(port->obj, pkt);
1633 }
1634
1635 static inline void
1636 __instr_drop_exec(struct rte_swx_pipeline *p,
1637                   struct thread *t,
1638                   const struct instruction *ip __rte_unused)
1639 {
1640         uint64_t port_id = p->n_ports_out - 1;
1641         struct port_out_runtime *port = &p->out[port_id];
1642         struct rte_swx_pkt *pkt = &t->pkt;
1643
1644         TRACE("[Thread %2u]: drop 1 pkt\n",
1645               p->thread_id);
1646
1647         /* Headers. */
1648         emit_handler(t);
1649
1650         /* Packet. */
1651         port->pkt_tx(port->obj, pkt);
1652 }
1653
1654 /*
1655  * extract.
1656  */
1657 static inline void
1658 __instr_hdr_extract_many_exec(struct rte_swx_pipeline *p __rte_unused,
1659                               struct thread *t,
1660                               const struct instruction *ip,
1661                               uint32_t n_extract)
1662 {
1663         uint64_t valid_headers = t->valid_headers;
1664         uint8_t *ptr = t->ptr;
1665         uint32_t offset = t->pkt.offset;
1666         uint32_t length = t->pkt.length;
1667         uint32_t i;
1668
1669         for (i = 0; i < n_extract; i++) {
1670                 uint32_t header_id = ip->io.hdr.header_id[i];
1671                 uint32_t struct_id = ip->io.hdr.struct_id[i];
1672                 uint32_t n_bytes = ip->io.hdr.n_bytes[i];
1673
1674                 TRACE("[Thread %2u]: extract header %u (%u bytes)\n",
1675                       p->thread_id,
1676                       header_id,
1677                       n_bytes);
1678
1679                 /* Headers. */
1680                 t->structs[struct_id] = ptr;
1681                 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1682
1683                 /* Packet. */
1684                 offset += n_bytes;
1685                 length -= n_bytes;
1686                 ptr += n_bytes;
1687         }
1688
1689         /* Headers. */
1690         t->valid_headers = valid_headers;
1691
1692         /* Packet. */
1693         t->pkt.offset = offset;
1694         t->pkt.length = length;
1695         t->ptr = ptr;
1696 }
1697
1698 static inline void
1699 __instr_hdr_extract_exec(struct rte_swx_pipeline *p,
1700                          struct thread *t,
1701                          const struct instruction *ip)
1702 {
1703         __instr_hdr_extract_many_exec(p, t, ip, 1);
1704 }
1705
1706 static inline void
1707 __instr_hdr_extract2_exec(struct rte_swx_pipeline *p,
1708                           struct thread *t,
1709                           const struct instruction *ip)
1710 {
1711         TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
1712
1713         __instr_hdr_extract_many_exec(p, t, ip, 2);
1714 }
1715
1716 static inline void
1717 __instr_hdr_extract3_exec(struct rte_swx_pipeline *p,
1718                           struct thread *t,
1719                           const struct instruction *ip)
1720 {
1721         TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
1722
1723         __instr_hdr_extract_many_exec(p, t, ip, 3);
1724 }
1725
1726 static inline void
1727 __instr_hdr_extract4_exec(struct rte_swx_pipeline *p,
1728                           struct thread *t,
1729                           const struct instruction *ip)
1730 {
1731         TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
1732
1733         __instr_hdr_extract_many_exec(p, t, ip, 4);
1734 }
1735
1736 static inline void
1737 __instr_hdr_extract5_exec(struct rte_swx_pipeline *p,
1738                           struct thread *t,
1739                           const struct instruction *ip)
1740 {
1741         TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
1742
1743         __instr_hdr_extract_many_exec(p, t, ip, 5);
1744 }
1745
1746 static inline void
1747 __instr_hdr_extract6_exec(struct rte_swx_pipeline *p,
1748                           struct thread *t,
1749                           const struct instruction *ip)
1750 {
1751         TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
1752
1753         __instr_hdr_extract_many_exec(p, t, ip, 6);
1754 }
1755
1756 static inline void
1757 __instr_hdr_extract7_exec(struct rte_swx_pipeline *p,
1758                           struct thread *t,
1759                           const struct instruction *ip)
1760 {
1761         TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
1762
1763         __instr_hdr_extract_many_exec(p, t, ip, 7);
1764 }
1765
1766 static inline void
1767 __instr_hdr_extract8_exec(struct rte_swx_pipeline *p,
1768                           struct thread *t,
1769                           const struct instruction *ip)
1770 {
1771         TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
1772
1773         __instr_hdr_extract_many_exec(p, t, ip, 8);
1774 }
1775
1776 static inline void
1777 __instr_hdr_extract_m_exec(struct rte_swx_pipeline *p __rte_unused,
1778                            struct thread *t,
1779                            const struct instruction *ip)
1780 {
1781         uint64_t valid_headers = t->valid_headers;
1782         uint8_t *ptr = t->ptr;
1783         uint32_t offset = t->pkt.offset;
1784         uint32_t length = t->pkt.length;
1785
1786         uint32_t n_bytes_last = METADATA_READ(t, ip->io.io.offset, ip->io.io.n_bits);
1787         uint32_t header_id = ip->io.hdr.header_id[0];
1788         uint32_t struct_id = ip->io.hdr.struct_id[0];
1789         uint32_t n_bytes = ip->io.hdr.n_bytes[0];
1790
1791         struct header_runtime *h = &t->headers[header_id];
1792
1793         TRACE("[Thread %2u]: extract header %u (%u + %u bytes)\n",
1794               p->thread_id,
1795               header_id,
1796               n_bytes,
1797               n_bytes_last);
1798
1799         n_bytes += n_bytes_last;
1800
1801         /* Headers. */
1802         t->structs[struct_id] = ptr;
1803         t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1804         h->n_bytes = n_bytes;
1805
1806         /* Packet. */
1807         t->pkt.offset = offset + n_bytes;
1808         t->pkt.length = length - n_bytes;
1809         t->ptr = ptr + n_bytes;
1810 }
1811
1812 static inline void
1813 __instr_hdr_lookahead_exec(struct rte_swx_pipeline *p __rte_unused,
1814                            struct thread *t,
1815                            const struct instruction *ip)
1816 {
1817         uint64_t valid_headers = t->valid_headers;
1818         uint8_t *ptr = t->ptr;
1819
1820         uint32_t header_id = ip->io.hdr.header_id[0];
1821         uint32_t struct_id = ip->io.hdr.struct_id[0];
1822
1823         TRACE("[Thread %2u]: lookahead header %u\n",
1824               p->thread_id,
1825               header_id);
1826
1827         /* Headers. */
1828         t->structs[struct_id] = ptr;
1829         t->valid_headers = MASK64_BIT_SET(valid_headers, header_id);
1830 }
1831
1832 /*
1833  * emit.
1834  */
1835 static inline void
1836 __instr_hdr_emit_many_exec(struct rte_swx_pipeline *p __rte_unused,
1837                            struct thread *t,
1838                            const struct instruction *ip,
1839                            uint32_t n_emit)
1840 {
1841         uint64_t valid_headers = t->valid_headers;
1842         uint32_t n_headers_out = t->n_headers_out;
1843         struct header_out_runtime *ho = NULL;
1844         uint8_t *ho_ptr = NULL;
1845         uint32_t ho_nbytes = 0, i;
1846
1847         for (i = 0; i < n_emit; i++) {
1848                 uint32_t header_id = ip->io.hdr.header_id[i];
1849                 uint32_t struct_id = ip->io.hdr.struct_id[i];
1850
1851                 struct header_runtime *hi = &t->headers[header_id];
1852                 uint8_t *hi_ptr0 = hi->ptr0;
1853                 uint32_t n_bytes = hi->n_bytes;
1854
1855                 uint8_t *hi_ptr = t->structs[struct_id];
1856
1857                 if (!MASK64_BIT_GET(valid_headers, header_id)) {
1858                         TRACE("[Thread %2u]: emit header %u (invalid)\n",
1859                               p->thread_id,
1860                               header_id);
1861
1862                         continue;
1863                 }
1864
1865                 TRACE("[Thread %2u]: emit header %u (valid)\n",
1866                       p->thread_id,
1867                       header_id);
1868
1869                 /* Headers. */
1870                 if (!ho) {
1871                         if (!n_headers_out) {
1872                                 ho = &t->headers_out[0];
1873
1874                                 ho->ptr0 = hi_ptr0;
1875                                 ho->ptr = hi_ptr;
1876
1877                                 ho_ptr = hi_ptr;
1878                                 ho_nbytes = n_bytes;
1879
1880                                 n_headers_out = 1;
1881
1882                                 continue;
1883                         } else {
1884                                 ho = &t->headers_out[n_headers_out - 1];
1885
1886                                 ho_ptr = ho->ptr;
1887                                 ho_nbytes = ho->n_bytes;
1888                         }
1889                 }
1890
1891                 if (ho_ptr + ho_nbytes == hi_ptr) {
1892                         ho_nbytes += n_bytes;
1893                 } else {
1894                         ho->n_bytes = ho_nbytes;
1895
1896                         ho++;
1897                         ho->ptr0 = hi_ptr0;
1898                         ho->ptr = hi_ptr;
1899
1900                         ho_ptr = hi_ptr;
1901                         ho_nbytes = n_bytes;
1902
1903                         n_headers_out++;
1904                 }
1905         }
1906
1907         if (ho)
1908                 ho->n_bytes = ho_nbytes;
1909         t->n_headers_out = n_headers_out;
1910 }
1911
1912 static inline void
1913 __instr_hdr_emit_exec(struct rte_swx_pipeline *p,
1914                       struct thread *t,
1915                       const struct instruction *ip)
1916 {
1917         __instr_hdr_emit_many_exec(p, t, ip, 1);
1918 }
1919
1920 static inline void
1921 __instr_hdr_emit_tx_exec(struct rte_swx_pipeline *p,
1922                          struct thread *t,
1923                          const struct instruction *ip)
1924 {
1925         TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
1926
1927         __instr_hdr_emit_many_exec(p, t, ip, 1);
1928         __instr_tx_exec(p, t, ip);
1929 }
1930
1931 static inline void
1932 __instr_hdr_emit2_tx_exec(struct rte_swx_pipeline *p,
1933                           struct thread *t,
1934                           const struct instruction *ip)
1935 {
1936         TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
1937
1938         __instr_hdr_emit_many_exec(p, t, ip, 2);
1939         __instr_tx_exec(p, t, ip);
1940 }
1941
1942 static inline void
1943 __instr_hdr_emit3_tx_exec(struct rte_swx_pipeline *p,
1944                           struct thread *t,
1945                           const struct instruction *ip)
1946 {
1947         TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
1948
1949         __instr_hdr_emit_many_exec(p, t, ip, 3);
1950         __instr_tx_exec(p, t, ip);
1951 }
1952
1953 static inline void
1954 __instr_hdr_emit4_tx_exec(struct rte_swx_pipeline *p,
1955                           struct thread *t,
1956                           const struct instruction *ip)
1957 {
1958         TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
1959
1960         __instr_hdr_emit_many_exec(p, t, ip, 4);
1961         __instr_tx_exec(p, t, ip);
1962 }
1963
1964 static inline void
1965 __instr_hdr_emit5_tx_exec(struct rte_swx_pipeline *p,
1966                           struct thread *t,
1967                           const struct instruction *ip)
1968 {
1969         TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
1970
1971         __instr_hdr_emit_many_exec(p, t, ip, 5);
1972         __instr_tx_exec(p, t, ip);
1973 }
1974
1975 static inline void
1976 __instr_hdr_emit6_tx_exec(struct rte_swx_pipeline *p,
1977                           struct thread *t,
1978                           const struct instruction *ip)
1979 {
1980         TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
1981
1982         __instr_hdr_emit_many_exec(p, t, ip, 6);
1983         __instr_tx_exec(p, t, ip);
1984 }
1985
1986 static inline void
1987 __instr_hdr_emit7_tx_exec(struct rte_swx_pipeline *p,
1988                           struct thread *t,
1989                           const struct instruction *ip)
1990 {
1991         TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
1992
1993         __instr_hdr_emit_many_exec(p, t, ip, 7);
1994         __instr_tx_exec(p, t, ip);
1995 }
1996
1997 static inline void
1998 __instr_hdr_emit8_tx_exec(struct rte_swx_pipeline *p,
1999                           struct thread *t,
2000                           const struct instruction *ip)
2001 {
2002         TRACE("[Thread %2u] *** The next 9 instructions are fused. ***\n", p->thread_id);
2003
2004         __instr_hdr_emit_many_exec(p, t, ip, 8);
2005         __instr_tx_exec(p, t, ip);
2006 }
2007
2008 /*
2009  * validate.
2010  */
2011 static inline void
2012 __instr_hdr_validate_exec(struct rte_swx_pipeline *p __rte_unused,
2013                           struct thread *t,
2014                           const struct instruction *ip)
2015 {
2016         uint32_t header_id = ip->valid.header_id;
2017
2018         TRACE("[Thread %2u] validate header %u\n", p->thread_id, header_id);
2019
2020         /* Headers. */
2021         t->valid_headers = MASK64_BIT_SET(t->valid_headers, header_id);
2022 }
2023
2024 /*
2025  * invalidate.
2026  */
2027 static inline void
2028 __instr_hdr_invalidate_exec(struct rte_swx_pipeline *p __rte_unused,
2029                             struct thread *t,
2030                             const struct instruction *ip)
2031 {
2032         uint32_t header_id = ip->valid.header_id;
2033
2034         TRACE("[Thread %2u] invalidate header %u\n", p->thread_id, header_id);
2035
2036         /* Headers. */
2037         t->valid_headers = MASK64_BIT_CLR(t->valid_headers, header_id);
2038 }
2039
2040 /*
2041  * learn.
2042  */
2043 static inline void
2044 __instr_learn_exec(struct rte_swx_pipeline *p,
2045                    struct thread *t,
2046                    const struct instruction *ip)
2047 {
2048         uint64_t action_id = ip->learn.action_id;
2049         uint32_t mf_offset = ip->learn.mf_offset;
2050         uint32_t learner_id = t->learner_id;
2051         struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2052                 p->n_selectors + learner_id];
2053         struct learner_runtime *l = &t->learners[learner_id];
2054         struct learner_statistics *stats = &p->learner_stats[learner_id];
2055         uint32_t status;
2056
2057         /* Table. */
2058         status = rte_swx_table_learner_add(ts->obj,
2059                                            l->mailbox,
2060                                            t->time,
2061                                            action_id,
2062                                            &t->metadata[mf_offset]);
2063
2064         TRACE("[Thread %2u] learner %u learn %s\n",
2065               p->thread_id,
2066               learner_id,
2067               status ? "ok" : "error");
2068
2069         stats->n_pkts_learn[status] += 1;
2070 }
2071
2072 /*
2073  * forget.
2074  */
2075 static inline void
2076 __instr_forget_exec(struct rte_swx_pipeline *p,
2077                     struct thread *t,
2078                     const struct instruction *ip __rte_unused)
2079 {
2080         uint32_t learner_id = t->learner_id;
2081         struct rte_swx_table_state *ts = &t->table_state[p->n_tables +
2082                 p->n_selectors + learner_id];
2083         struct learner_runtime *l = &t->learners[learner_id];
2084         struct learner_statistics *stats = &p->learner_stats[learner_id];
2085
2086         /* Table. */
2087         rte_swx_table_learner_delete(ts->obj, l->mailbox);
2088
2089         TRACE("[Thread %2u] learner %u forget\n",
2090               p->thread_id,
2091               learner_id);
2092
2093         stats->n_pkts_forget += 1;
2094 }
2095
2096 /*
2097  * extern.
2098  */
2099 static inline uint32_t
2100 __instr_extern_obj_exec(struct rte_swx_pipeline *p __rte_unused,
2101                         struct thread *t,
2102                         const struct instruction *ip)
2103 {
2104         uint32_t obj_id = ip->ext_obj.ext_obj_id;
2105         uint32_t func_id = ip->ext_obj.func_id;
2106         struct extern_obj_runtime *obj = &t->extern_objs[obj_id];
2107         rte_swx_extern_type_member_func_t func = obj->funcs[func_id];
2108         uint32_t done;
2109
2110         TRACE("[Thread %2u] extern obj %u member func %u\n",
2111               p->thread_id,
2112               obj_id,
2113               func_id);
2114
2115         done = func(obj->obj, obj->mailbox);
2116
2117         return done;
2118 }
2119
2120 static inline uint32_t
2121 __instr_extern_func_exec(struct rte_swx_pipeline *p __rte_unused,
2122                          struct thread *t,
2123                          const struct instruction *ip)
2124 {
2125         uint32_t ext_func_id = ip->ext_func.ext_func_id;
2126         struct extern_func_runtime *ext_func = &t->extern_funcs[ext_func_id];
2127         rte_swx_extern_func_t func = ext_func->func;
2128         uint32_t done;
2129
2130         TRACE("[Thread %2u] extern func %u\n",
2131               p->thread_id,
2132               ext_func_id);
2133
2134         done = func(ext_func->mailbox);
2135
2136         return done;
2137 }
2138
2139 /*
2140  * mov.
2141  */
2142 static inline void
2143 __instr_mov_exec(struct rte_swx_pipeline *p __rte_unused,
2144                  struct thread *t,
2145                  const struct instruction *ip)
2146 {
2147         TRACE("[Thread %2u] mov\n", p->thread_id);
2148
2149         MOV(t, ip);
2150 }
2151
2152 static inline void
2153 __instr_mov_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2154                     struct thread *t,
2155                     const struct instruction *ip)
2156 {
2157         TRACE("[Thread %2u] mov (mh)\n", p->thread_id);
2158
2159         MOV_MH(t, ip);
2160 }
2161
2162 static inline void
2163 __instr_mov_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2164                     struct thread *t,
2165                     const struct instruction *ip)
2166 {
2167         TRACE("[Thread %2u] mov (hm)\n", p->thread_id);
2168
2169         MOV_HM(t, ip);
2170 }
2171
2172 static inline void
2173 __instr_mov_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2174                     struct thread *t,
2175                     const struct instruction *ip)
2176 {
2177         TRACE("[Thread %2u] mov (hh)\n", p->thread_id);
2178
2179         MOV_HH(t, ip);
2180 }
2181
2182 static inline void
2183 __instr_mov_i_exec(struct rte_swx_pipeline *p __rte_unused,
2184                    struct thread *t,
2185                    const struct instruction *ip)
2186 {
2187         TRACE("[Thread %2u] mov m.f %" PRIx64 "\n", p->thread_id, ip->mov.src_val);
2188
2189         MOV_I(t, ip);
2190 }
2191
2192 /*
2193  * dma.
2194  */
2195 static inline void
2196 __instr_dma_ht_many_exec(struct rte_swx_pipeline *p __rte_unused,
2197                          struct thread *t,
2198                          const struct instruction *ip,
2199                          uint32_t n_dma)
2200 {
2201         uint8_t *action_data = t->structs[0];
2202         uint64_t valid_headers = t->valid_headers;
2203         uint32_t i;
2204
2205         for (i = 0; i < n_dma; i++) {
2206                 uint32_t header_id = ip->dma.dst.header_id[i];
2207                 uint32_t struct_id = ip->dma.dst.struct_id[i];
2208                 uint32_t offset = ip->dma.src.offset[i];
2209                 uint32_t n_bytes = ip->dma.n_bytes[i];
2210
2211                 struct header_runtime *h = &t->headers[header_id];
2212                 uint8_t *h_ptr0 = h->ptr0;
2213                 uint8_t *h_ptr = t->structs[struct_id];
2214
2215                 void *dst = MASK64_BIT_GET(valid_headers, header_id) ?
2216                         h_ptr : h_ptr0;
2217                 void *src = &action_data[offset];
2218
2219                 TRACE("[Thread %2u] dma h.s t.f\n", p->thread_id);
2220
2221                 /* Headers. */
2222                 memcpy(dst, src, n_bytes);
2223                 t->structs[struct_id] = dst;
2224                 valid_headers = MASK64_BIT_SET(valid_headers, header_id);
2225         }
2226
2227         t->valid_headers = valid_headers;
2228 }
2229
2230 static inline void
2231 __instr_dma_ht_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2232 {
2233         __instr_dma_ht_many_exec(p, t, ip, 1);
2234 }
2235
2236 static inline void
2237 __instr_dma_ht2_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2238 {
2239         TRACE("[Thread %2u] *** The next 2 instructions are fused. ***\n", p->thread_id);
2240
2241         __instr_dma_ht_many_exec(p, t, ip, 2);
2242 }
2243
2244 static inline void
2245 __instr_dma_ht3_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2246 {
2247         TRACE("[Thread %2u] *** The next 3 instructions are fused. ***\n", p->thread_id);
2248
2249         __instr_dma_ht_many_exec(p, t, ip, 3);
2250 }
2251
2252 static inline void
2253 __instr_dma_ht4_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2254 {
2255         TRACE("[Thread %2u] *** The next 4 instructions are fused. ***\n", p->thread_id);
2256
2257         __instr_dma_ht_many_exec(p, t, ip, 4);
2258 }
2259
2260 static inline void
2261 __instr_dma_ht5_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2262 {
2263         TRACE("[Thread %2u] *** The next 5 instructions are fused. ***\n", p->thread_id);
2264
2265         __instr_dma_ht_many_exec(p, t, ip, 5);
2266 }
2267
2268 static inline void
2269 __instr_dma_ht6_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2270 {
2271         TRACE("[Thread %2u] *** The next 6 instructions are fused. ***\n", p->thread_id);
2272
2273         __instr_dma_ht_many_exec(p, t, ip, 6);
2274 }
2275
2276 static inline void
2277 __instr_dma_ht7_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2278 {
2279         TRACE("[Thread %2u] *** The next 7 instructions are fused. ***\n", p->thread_id);
2280
2281         __instr_dma_ht_many_exec(p, t, ip, 7);
2282 }
2283
2284 static inline void
2285 __instr_dma_ht8_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2286 {
2287         TRACE("[Thread %2u] *** The next 8 instructions are fused. ***\n", p->thread_id);
2288
2289         __instr_dma_ht_many_exec(p, t, ip, 8);
2290 }
2291
2292 /*
2293  * alu.
2294  */
2295 static inline void
2296 __instr_alu_add_exec(struct rte_swx_pipeline *p __rte_unused,
2297                      struct thread *t,
2298                      const struct instruction *ip)
2299 {
2300         TRACE("[Thread %2u] add\n", p->thread_id);
2301
2302         ALU(t, ip, +);
2303 }
2304
2305 static inline void
2306 __instr_alu_add_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2307                         struct thread *t,
2308                         const struct instruction *ip)
2309 {
2310         TRACE("[Thread %2u] add (mh)\n", p->thread_id);
2311
2312         ALU_MH(t, ip, +);
2313 }
2314
2315 static inline void
2316 __instr_alu_add_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2317                         struct thread *t,
2318                         const struct instruction *ip)
2319 {
2320         TRACE("[Thread %2u] add (hm)\n", p->thread_id);
2321
2322         ALU_HM(t, ip, +);
2323 }
2324
2325 static inline void
2326 __instr_alu_add_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2327                         struct thread *t,
2328                         const struct instruction *ip)
2329 {
2330         TRACE("[Thread %2u] add (hh)\n", p->thread_id);
2331
2332         ALU_HH(t, ip, +);
2333 }
2334
2335 static inline void
2336 __instr_alu_add_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2337                         struct thread *t,
2338                         const struct instruction *ip)
2339 {
2340         TRACE("[Thread %2u] add (mi)\n", p->thread_id);
2341
2342         ALU_MI(t, ip, +);
2343 }
2344
2345 static inline void
2346 __instr_alu_add_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2347                         struct thread *t,
2348                         const struct instruction *ip)
2349 {
2350         TRACE("[Thread %2u] add (hi)\n", p->thread_id);
2351
2352         ALU_HI(t, ip, +);
2353 }
2354
2355 static inline void
2356 __instr_alu_sub_exec(struct rte_swx_pipeline *p __rte_unused,
2357                      struct thread *t,
2358                      const struct instruction *ip)
2359 {
2360         TRACE("[Thread %2u] sub\n", p->thread_id);
2361
2362         ALU(t, ip, -);
2363 }
2364
2365 static inline void
2366 __instr_alu_sub_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2367                         struct thread *t,
2368                         const struct instruction *ip)
2369 {
2370         TRACE("[Thread %2u] sub (mh)\n", p->thread_id);
2371
2372         ALU_MH(t, ip, -);
2373 }
2374
2375 static inline void
2376 __instr_alu_sub_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2377                         struct thread *t,
2378                         const struct instruction *ip)
2379 {
2380         TRACE("[Thread %2u] sub (hm)\n", p->thread_id);
2381
2382         ALU_HM(t, ip, -);
2383 }
2384
2385 static inline void
2386 __instr_alu_sub_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2387                         struct thread *t,
2388                         const struct instruction *ip)
2389 {
2390         TRACE("[Thread %2u] sub (hh)\n", p->thread_id);
2391
2392         ALU_HH(t, ip, -);
2393 }
2394
2395 static inline void
2396 __instr_alu_sub_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2397                         struct thread *t,
2398                         const struct instruction *ip)
2399 {
2400         TRACE("[Thread %2u] sub (mi)\n", p->thread_id);
2401
2402         ALU_MI(t, ip, -);
2403 }
2404
2405 static inline void
2406 __instr_alu_sub_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2407                         struct thread *t,
2408                         const struct instruction *ip)
2409 {
2410         TRACE("[Thread %2u] sub (hi)\n", p->thread_id);
2411
2412         ALU_HI(t, ip, -);
2413 }
2414
2415 static inline void
2416 __instr_alu_shl_exec(struct rte_swx_pipeline *p __rte_unused,
2417                      struct thread *t,
2418                      const struct instruction *ip)
2419 {
2420         TRACE("[Thread %2u] shl\n", p->thread_id);
2421
2422         ALU(t, ip, <<);
2423 }
2424
2425 static inline void
2426 __instr_alu_shl_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2427                         struct thread *t,
2428                         const struct instruction *ip)
2429 {
2430         TRACE("[Thread %2u] shl (mh)\n", p->thread_id);
2431
2432         ALU_MH(t, ip, <<);
2433 }
2434
2435 static inline void
2436 __instr_alu_shl_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2437                         struct thread *t,
2438                         const struct instruction *ip)
2439 {
2440         TRACE("[Thread %2u] shl (hm)\n", p->thread_id);
2441
2442         ALU_HM(t, ip, <<);
2443 }
2444
2445 static inline void
2446 __instr_alu_shl_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2447                         struct thread *t,
2448                         const struct instruction *ip)
2449 {
2450         TRACE("[Thread %2u] shl (hh)\n", p->thread_id);
2451
2452         ALU_HH(t, ip, <<);
2453 }
2454
2455 static inline void
2456 __instr_alu_shl_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2457                         struct thread *t,
2458                         const struct instruction *ip)
2459 {
2460         TRACE("[Thread %2u] shl (mi)\n", p->thread_id);
2461
2462         ALU_MI(t, ip, <<);
2463 }
2464
2465 static inline void
2466 __instr_alu_shl_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2467                         struct thread *t,
2468                         const struct instruction *ip)
2469 {
2470         TRACE("[Thread %2u] shl (hi)\n", p->thread_id);
2471
2472         ALU_HI(t, ip, <<);
2473 }
2474
2475 static inline void
2476 __instr_alu_shr_exec(struct rte_swx_pipeline *p __rte_unused,
2477                      struct thread *t,
2478                      const struct instruction *ip)
2479 {
2480         TRACE("[Thread %2u] shr\n", p->thread_id);
2481
2482         ALU(t, ip, >>);
2483 }
2484
2485 static inline void
2486 __instr_alu_shr_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2487                         struct thread *t,
2488                         const struct instruction *ip)
2489 {
2490         TRACE("[Thread %2u] shr (mh)\n", p->thread_id);
2491
2492         ALU_MH(t, ip, >>);
2493 }
2494
2495 static inline void
2496 __instr_alu_shr_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2497                         struct thread *t,
2498                         const struct instruction *ip)
2499 {
2500         TRACE("[Thread %2u] shr (hm)\n", p->thread_id);
2501
2502         ALU_HM(t, ip, >>);
2503 }
2504
2505 static inline void
2506 __instr_alu_shr_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2507                         struct thread *t,
2508                         const struct instruction *ip)
2509 {
2510         TRACE("[Thread %2u] shr (hh)\n", p->thread_id);
2511
2512         ALU_HH(t, ip, >>);
2513 }
2514
2515 static inline void
2516 __instr_alu_shr_mi_exec(struct rte_swx_pipeline *p __rte_unused,
2517                         struct thread *t,
2518                         const struct instruction *ip)
2519 {
2520         TRACE("[Thread %2u] shr (mi)\n", p->thread_id);
2521
2522         /* Structs. */
2523         ALU_MI(t, ip, >>);
2524 }
2525
2526 static inline void
2527 __instr_alu_shr_hi_exec(struct rte_swx_pipeline *p __rte_unused,
2528                         struct thread *t,
2529                         const struct instruction *ip)
2530 {
2531         TRACE("[Thread %2u] shr (hi)\n", p->thread_id);
2532
2533         ALU_HI(t, ip, >>);
2534 }
2535
2536 static inline void
2537 __instr_alu_and_exec(struct rte_swx_pipeline *p __rte_unused,
2538                      struct thread *t,
2539                      const struct instruction *ip)
2540 {
2541         TRACE("[Thread %2u] and\n", p->thread_id);
2542
2543         ALU(t, ip, &);
2544 }
2545
2546 static inline void
2547 __instr_alu_and_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2548                         struct thread *t,
2549                         const struct instruction *ip)
2550 {
2551         TRACE("[Thread %2u] and (mh)\n", p->thread_id);
2552
2553         ALU_MH(t, ip, &);
2554 }
2555
2556 static inline void
2557 __instr_alu_and_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2558                         struct thread *t,
2559                         const struct instruction *ip)
2560 {
2561         TRACE("[Thread %2u] and (hm)\n", p->thread_id);
2562
2563         ALU_HM_FAST(t, ip, &);
2564 }
2565
2566 static inline void
2567 __instr_alu_and_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2568                         struct thread *t,
2569                         const struct instruction *ip)
2570 {
2571         TRACE("[Thread %2u] and (hh)\n", p->thread_id);
2572
2573         ALU_HH_FAST(t, ip, &);
2574 }
2575
2576 static inline void
2577 __instr_alu_and_i_exec(struct rte_swx_pipeline *p __rte_unused,
2578                        struct thread *t,
2579                        const struct instruction *ip)
2580 {
2581         TRACE("[Thread %2u] and (i)\n", p->thread_id);
2582
2583         ALU_I(t, ip, &);
2584 }
2585
2586 static inline void
2587 __instr_alu_or_exec(struct rte_swx_pipeline *p __rte_unused,
2588                     struct thread *t,
2589                     const struct instruction *ip)
2590 {
2591         TRACE("[Thread %2u] or\n", p->thread_id);
2592
2593         ALU(t, ip, |);
2594 }
2595
2596 static inline void
2597 __instr_alu_or_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2598                        struct thread *t,
2599                        const struct instruction *ip)
2600 {
2601         TRACE("[Thread %2u] or (mh)\n", p->thread_id);
2602
2603         ALU_MH(t, ip, |);
2604 }
2605
2606 static inline void
2607 __instr_alu_or_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2608                        struct thread *t,
2609                        const struct instruction *ip)
2610 {
2611         TRACE("[Thread %2u] or (hm)\n", p->thread_id);
2612
2613         ALU_HM_FAST(t, ip, |);
2614 }
2615
2616 static inline void
2617 __instr_alu_or_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2618                        struct thread *t,
2619                        const struct instruction *ip)
2620 {
2621         TRACE("[Thread %2u] or (hh)\n", p->thread_id);
2622
2623         ALU_HH_FAST(t, ip, |);
2624 }
2625
2626 static inline void
2627 __instr_alu_or_i_exec(struct rte_swx_pipeline *p __rte_unused,
2628                       struct thread *t,
2629                       const struct instruction *ip)
2630 {
2631         TRACE("[Thread %2u] or (i)\n", p->thread_id);
2632
2633         ALU_I(t, ip, |);
2634 }
2635
2636 static inline void
2637 __instr_alu_xor_exec(struct rte_swx_pipeline *p __rte_unused,
2638                      struct thread *t,
2639                      const struct instruction *ip)
2640 {
2641         TRACE("[Thread %2u] xor\n", p->thread_id);
2642
2643         ALU(t, ip, ^);
2644 }
2645
2646 static inline void
2647 __instr_alu_xor_mh_exec(struct rte_swx_pipeline *p __rte_unused,
2648                         struct thread *t,
2649                         const struct instruction *ip)
2650 {
2651         TRACE("[Thread %2u] xor (mh)\n", p->thread_id);
2652
2653         ALU_MH(t, ip, ^);
2654 }
2655
2656 static inline void
2657 __instr_alu_xor_hm_exec(struct rte_swx_pipeline *p __rte_unused,
2658                         struct thread *t,
2659                         const struct instruction *ip)
2660 {
2661         TRACE("[Thread %2u] xor (hm)\n", p->thread_id);
2662
2663         ALU_HM_FAST(t, ip, ^);
2664 }
2665
2666 static inline void
2667 __instr_alu_xor_hh_exec(struct rte_swx_pipeline *p __rte_unused,
2668                         struct thread *t,
2669                         const struct instruction *ip)
2670 {
2671         TRACE("[Thread %2u] xor (hh)\n", p->thread_id);
2672
2673         ALU_HH_FAST(t, ip, ^);
2674 }
2675
2676 static inline void
2677 __instr_alu_xor_i_exec(struct rte_swx_pipeline *p __rte_unused,
2678                        struct thread *t,
2679                        const struct instruction *ip)
2680 {
2681         TRACE("[Thread %2u] xor (i)\n", p->thread_id);
2682
2683         ALU_I(t, ip, ^);
2684 }
2685
2686 static inline void
2687 __instr_alu_ckadd_field_exec(struct rte_swx_pipeline *p __rte_unused,
2688                              struct thread *t,
2689                              const struct instruction *ip)
2690 {
2691         uint8_t *dst_struct, *src_struct;
2692         uint16_t *dst16_ptr, dst;
2693         uint64_t *src64_ptr, src64, src64_mask, src;
2694         uint64_t r;
2695
2696         TRACE("[Thread %2u] ckadd (field)\n", p->thread_id);
2697
2698         /* Structs. */
2699         dst_struct = t->structs[ip->alu.dst.struct_id];
2700         dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2701         dst = *dst16_ptr;
2702
2703         src_struct = t->structs[ip->alu.src.struct_id];
2704         src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
2705         src64 = *src64_ptr;
2706         src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
2707         src = src64 & src64_mask;
2708
2709         /* Initialize the result with destination 1's complement. */
2710         r = dst;
2711         r = ~r & 0xFFFF;
2712
2713         /* The first input (r) is a 16-bit number. The second and the third
2714          * inputs are 32-bit numbers. In the worst case scenario, the sum of the
2715          * three numbers (output r) is a 34-bit number.
2716          */
2717         r += (src >> 32) + (src & 0xFFFFFFFF);
2718
2719         /* The first input is a 16-bit number. The second input is an 18-bit
2720          * number. In the worst case scenario, the sum of the two numbers is a
2721          * 19-bit number.
2722          */
2723         r = (r & 0xFFFF) + (r >> 16);
2724
2725         /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2726          * a 3-bit number (0 .. 7). Their sum is a 17-bit number (0 .. 0x10006).
2727          */
2728         r = (r & 0xFFFF) + (r >> 16);
2729
2730         /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2731          * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2732          * 0x10006), the output r is (0 .. 7). So no carry bit can be generated,
2733          * therefore the output r is always a 16-bit number.
2734          */
2735         r = (r & 0xFFFF) + (r >> 16);
2736
2737         /* Apply 1's complement to the result. */
2738         r = ~r & 0xFFFF;
2739         r = r ? r : 0xFFFF;
2740
2741         *dst16_ptr = (uint16_t)r;
2742 }
2743
2744 static inline void
2745 __instr_alu_cksub_field_exec(struct rte_swx_pipeline *p __rte_unused,
2746                              struct thread *t,
2747                              const struct instruction *ip)
2748 {
2749         uint8_t *dst_struct, *src_struct;
2750         uint16_t *dst16_ptr, dst;
2751         uint64_t *src64_ptr, src64, src64_mask, src;
2752         uint64_t r;
2753
2754         TRACE("[Thread %2u] cksub (field)\n", p->thread_id);
2755
2756         /* Structs. */
2757         dst_struct = t->structs[ip->alu.dst.struct_id];
2758         dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2759         dst = *dst16_ptr;
2760
2761         src_struct = t->structs[ip->alu.src.struct_id];
2762         src64_ptr = (uint64_t *)&src_struct[ip->alu.src.offset];
2763         src64 = *src64_ptr;
2764         src64_mask = UINT64_MAX >> (64 - ip->alu.src.n_bits);
2765         src = src64 & src64_mask;
2766
2767         /* Initialize the result with destination 1's complement. */
2768         r = dst;
2769         r = ~r & 0xFFFF;
2770
2771         /* Subtraction in 1's complement arithmetic (i.e. a '- b) is the same as
2772          * the following sequence of operations in 2's complement arithmetic:
2773          *    a '- b = (a - b) % 0xFFFF.
2774          *
2775          * In order to prevent an underflow for the below subtraction, in which
2776          * a 33-bit number (the subtrahend) is taken out of a 16-bit number (the
2777          * minuend), we first add a multiple of the 0xFFFF modulus to the
2778          * minuend. The number we add to the minuend needs to be a 34-bit number
2779          * or higher, so for readability reasons we picked the 36-bit multiple.
2780          * We are effectively turning the 16-bit minuend into a 36-bit number:
2781          *    (a - b) % 0xFFFF = (a + 0xFFFF00000 - b) % 0xFFFF.
2782          */
2783         r += 0xFFFF00000ULL; /* The output r is a 36-bit number. */
2784
2785         /* A 33-bit number is subtracted from a 36-bit number (the input r). The
2786          * result (the output r) is a 36-bit number.
2787          */
2788         r -= (src >> 32) + (src & 0xFFFFFFFF);
2789
2790         /* The first input is a 16-bit number. The second input is a 20-bit
2791          * number. Their sum is a 21-bit number.
2792          */
2793         r = (r & 0xFFFF) + (r >> 16);
2794
2795         /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2796          * a 5-bit number (0 .. 31). The sum is a 17-bit number (0 .. 0x1001E).
2797          */
2798         r = (r & 0xFFFF) + (r >> 16);
2799
2800         /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2801          * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2802          * 0x1001E), the output r is (0 .. 31). So no carry bit can be
2803          * generated, therefore the output r is always a 16-bit number.
2804          */
2805         r = (r & 0xFFFF) + (r >> 16);
2806
2807         /* Apply 1's complement to the result. */
2808         r = ~r & 0xFFFF;
2809         r = r ? r : 0xFFFF;
2810
2811         *dst16_ptr = (uint16_t)r;
2812 }
2813
2814 static inline void
2815 __instr_alu_ckadd_struct20_exec(struct rte_swx_pipeline *p __rte_unused,
2816                                 struct thread *t,
2817                                 const struct instruction *ip)
2818 {
2819         uint8_t *dst_struct, *src_struct;
2820         uint16_t *dst16_ptr, dst;
2821         uint32_t *src32_ptr;
2822         uint64_t r0, r1;
2823
2824         TRACE("[Thread %2u] ckadd (struct of 20 bytes)\n", p->thread_id);
2825
2826         /* Structs. */
2827         dst_struct = t->structs[ip->alu.dst.struct_id];
2828         dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2829         dst = *dst16_ptr;
2830
2831         src_struct = t->structs[ip->alu.src.struct_id];
2832         src32_ptr = (uint32_t *)&src_struct[0];
2833
2834         /* Initialize the result with destination 1's complement. */
2835         r0 = dst;
2836         r0 = ~r0 & 0xFFFF;
2837
2838         r0 += src32_ptr[0]; /* The output r0 is a 33-bit number. */
2839         r1 = src32_ptr[1]; /* r1 is a 32-bit number. */
2840         r0 += src32_ptr[2]; /* The output r0 is a 34-bit number. */
2841         r1 += src32_ptr[3]; /* The output r1 is a 33-bit number. */
2842         r0 += r1 + src32_ptr[4]; /* The output r0 is a 35-bit number. */
2843
2844         /* The first input is a 16-bit number. The second input is a 19-bit
2845          * number. Their sum is a 20-bit number.
2846          */
2847         r0 = (r0 & 0xFFFF) + (r0 >> 16);
2848
2849         /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2850          * a 4-bit number (0 .. 15). The sum is a 17-bit number (0 .. 0x1000E).
2851          */
2852         r0 = (r0 & 0xFFFF) + (r0 >> 16);
2853
2854         /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2855          * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2856          * 0x1000E), the output r is (0 .. 15). So no carry bit can be
2857          * generated, therefore the output r is always a 16-bit number.
2858          */
2859         r0 = (r0 & 0xFFFF) + (r0 >> 16);
2860
2861         /* Apply 1's complement to the result. */
2862         r0 = ~r0 & 0xFFFF;
2863         r0 = r0 ? r0 : 0xFFFF;
2864
2865         *dst16_ptr = (uint16_t)r0;
2866 }
2867
2868 static inline void
2869 __instr_alu_ckadd_struct_exec(struct rte_swx_pipeline *p __rte_unused,
2870                               struct thread *t,
2871                               const struct instruction *ip)
2872 {
2873         uint32_t src_header_id = ip->alu.src.n_bits; /* The src header ID is stored here. */
2874         uint32_t n_src_header_bytes = t->headers[src_header_id].n_bytes;
2875         uint8_t *dst_struct, *src_struct;
2876         uint16_t *dst16_ptr, dst;
2877         uint32_t *src32_ptr;
2878         uint64_t r;
2879         uint32_t i;
2880
2881         if (n_src_header_bytes == 20) {
2882                 __instr_alu_ckadd_struct20_exec(p, t, ip);
2883                 return;
2884         }
2885
2886         TRACE("[Thread %2u] ckadd (struct)\n", p->thread_id);
2887
2888         /* Structs. */
2889         dst_struct = t->structs[ip->alu.dst.struct_id];
2890         dst16_ptr = (uint16_t *)&dst_struct[ip->alu.dst.offset];
2891         dst = *dst16_ptr;
2892
2893         src_struct = t->structs[ip->alu.src.struct_id];
2894         src32_ptr = (uint32_t *)&src_struct[0];
2895
2896         /* Initialize the result with destination 1's complement. */
2897         r = dst;
2898         r = ~r & 0xFFFF;
2899
2900         /* The max number of 32-bit words in a 32K-byte header is 2^13.
2901          * Therefore, in the worst case scenario, a 45-bit number is added to a
2902          * 16-bit number (the input r), so the output r is 46-bit number.
2903          */
2904         for (i = 0; i < n_src_header_bytes / 4; i++, src32_ptr++)
2905                 r += *src32_ptr;
2906
2907         /* The first input is a 16-bit number. The second input is a 30-bit
2908          * number. Their sum is a 31-bit number.
2909          */
2910         r = (r & 0xFFFF) + (r >> 16);
2911
2912         /* The first input is a 16-bit number (0 .. 0xFFFF). The second input is
2913          * a 15-bit number (0 .. 0x7FFF). The sum is a 17-bit number (0 .. 0x17FFE).
2914          */
2915         r = (r & 0xFFFF) + (r >> 16);
2916
2917         /* When the input r is (0 .. 0xFFFF), the output r is equal to the input
2918          * r, so the output is (0 .. 0xFFFF). When the input r is (0x10000 ..
2919          * 0x17FFE), the output r is (0 .. 0x7FFF). So no carry bit can be
2920          * generated, therefore the output r is always a 16-bit number.
2921          */
2922         r = (r & 0xFFFF) + (r >> 16);
2923
2924         /* Apply 1's complement to the result. */
2925         r = ~r & 0xFFFF;
2926         r = r ? r : 0xFFFF;
2927
2928         *dst16_ptr = (uint16_t)r;
2929 }
2930
2931 /*
2932  * Register array.
2933  */
2934 static inline uint64_t *
2935 instr_regarray_regarray(struct rte_swx_pipeline *p, const struct instruction *ip)
2936 {
2937         struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2938         return r->regarray;
2939 }
2940
2941 static inline uint64_t
2942 instr_regarray_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2943 {
2944         struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2945
2946         uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
2947         uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
2948         uint64_t idx64 = *idx64_ptr;
2949         uint64_t idx64_mask = UINT64_MAX >> (64 - ip->regarray.idx.n_bits);
2950         uint64_t idx = idx64 & idx64_mask & r->size_mask;
2951
2952         return idx;
2953 }
2954
2955 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
2956
2957 static inline uint64_t
2958 instr_regarray_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
2959 {
2960         struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2961
2962         uint8_t *idx_struct = t->structs[ip->regarray.idx.struct_id];
2963         uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->regarray.idx.offset];
2964         uint64_t idx64 = *idx64_ptr;
2965         uint64_t idx = (ntoh64(idx64) >> (64 - ip->regarray.idx.n_bits)) & r->size_mask;
2966
2967         return idx;
2968 }
2969
2970 #else
2971
2972 #define instr_regarray_idx_nbo instr_regarray_idx_hbo
2973
2974 #endif
2975
2976 static inline uint64_t
2977 instr_regarray_idx_imm(struct rte_swx_pipeline *p, const struct instruction *ip)
2978 {
2979         struct regarray_runtime *r = &p->regarray_runtime[ip->regarray.regarray_id];
2980
2981         uint64_t idx = ip->regarray.idx_val & r->size_mask;
2982
2983         return idx;
2984 }
2985
2986 static inline uint64_t
2987 instr_regarray_src_hbo(struct thread *t, const struct instruction *ip)
2988 {
2989         uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
2990         uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
2991         uint64_t src64 = *src64_ptr;
2992         uint64_t src64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
2993         uint64_t src = src64 & src64_mask;
2994
2995         return src;
2996 }
2997
2998 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
2999
3000 static inline uint64_t
3001 instr_regarray_src_nbo(struct thread *t, const struct instruction *ip)
3002 {
3003         uint8_t *src_struct = t->structs[ip->regarray.dstsrc.struct_id];
3004         uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->regarray.dstsrc.offset];
3005         uint64_t src64 = *src64_ptr;
3006         uint64_t src = ntoh64(src64) >> (64 - ip->regarray.dstsrc.n_bits);
3007
3008         return src;
3009 }
3010
3011 #else
3012
3013 #define instr_regarray_src_nbo instr_regarray_src_hbo
3014
3015 #endif
3016
3017 static inline void
3018 instr_regarray_dst_hbo_src_hbo_set(struct thread *t, const struct instruction *ip, uint64_t src)
3019 {
3020         uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
3021         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
3022         uint64_t dst64 = *dst64_ptr;
3023         uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
3024
3025         *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3026
3027 }
3028
3029 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3030
3031 static inline void
3032 instr_regarray_dst_nbo_src_hbo_set(struct thread *t, const struct instruction *ip, uint64_t src)
3033 {
3034         uint8_t *dst_struct = t->structs[ip->regarray.dstsrc.struct_id];
3035         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->regarray.dstsrc.offset];
3036         uint64_t dst64 = *dst64_ptr;
3037         uint64_t dst64_mask = UINT64_MAX >> (64 - ip->regarray.dstsrc.n_bits);
3038
3039         src = hton64(src) >> (64 - ip->regarray.dstsrc.n_bits);
3040         *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3041 }
3042
3043 #else
3044
3045 #define instr_regarray_dst_nbo_src_hbo_set instr_regarray_dst_hbo_src_hbo_set
3046
3047 #endif
3048
3049 static inline void
3050 __instr_regprefetch_rh_exec(struct rte_swx_pipeline *p,
3051                             struct thread *t,
3052                             const struct instruction *ip)
3053 {
3054         uint64_t *regarray, idx;
3055
3056         TRACE("[Thread %2u] regprefetch (r[h])\n", p->thread_id);
3057
3058         regarray = instr_regarray_regarray(p, ip);
3059         idx = instr_regarray_idx_nbo(p, t, ip);
3060         rte_prefetch0(&regarray[idx]);
3061 }
3062
3063 static inline void
3064 __instr_regprefetch_rm_exec(struct rte_swx_pipeline *p,
3065                             struct thread *t,
3066                             const struct instruction *ip)
3067 {
3068         uint64_t *regarray, idx;
3069
3070         TRACE("[Thread %2u] regprefetch (r[m])\n", p->thread_id);
3071
3072         regarray = instr_regarray_regarray(p, ip);
3073         idx = instr_regarray_idx_hbo(p, t, ip);
3074         rte_prefetch0(&regarray[idx]);
3075 }
3076
3077 static inline void
3078 __instr_regprefetch_ri_exec(struct rte_swx_pipeline *p,
3079                             struct thread *t __rte_unused,
3080                             const struct instruction *ip)
3081 {
3082         uint64_t *regarray, idx;
3083
3084         TRACE("[Thread %2u] regprefetch (r[i])\n", p->thread_id);
3085
3086         regarray = instr_regarray_regarray(p, ip);
3087         idx = instr_regarray_idx_imm(p, ip);
3088         rte_prefetch0(&regarray[idx]);
3089 }
3090
3091 static inline void
3092 __instr_regrd_hrh_exec(struct rte_swx_pipeline *p,
3093                        struct thread *t,
3094                        const struct instruction *ip)
3095 {
3096         uint64_t *regarray, idx;
3097
3098         TRACE("[Thread %2u] regrd (h = r[h])\n", p->thread_id);
3099
3100         regarray = instr_regarray_regarray(p, ip);
3101         idx = instr_regarray_idx_nbo(p, t, ip);
3102         instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3103 }
3104
3105 static inline void
3106 __instr_regrd_hrm_exec(struct rte_swx_pipeline *p,
3107                        struct thread *t,
3108                        const struct instruction *ip)
3109 {
3110         uint64_t *regarray, idx;
3111
3112         TRACE("[Thread %2u] regrd (h = r[m])\n", p->thread_id);
3113
3114         /* Structs. */
3115         regarray = instr_regarray_regarray(p, ip);
3116         idx = instr_regarray_idx_hbo(p, t, ip);
3117         instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3118 }
3119
3120 static inline void
3121 __instr_regrd_mrh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3122 {
3123         uint64_t *regarray, idx;
3124
3125         TRACE("[Thread %2u] regrd (m = r[h])\n", p->thread_id);
3126
3127         regarray = instr_regarray_regarray(p, ip);
3128         idx = instr_regarray_idx_nbo(p, t, ip);
3129         instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3130 }
3131
3132 static inline void
3133 __instr_regrd_mrm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3134 {
3135         uint64_t *regarray, idx;
3136
3137         TRACE("[Thread %2u] regrd (m = r[m])\n", p->thread_id);
3138
3139         regarray = instr_regarray_regarray(p, ip);
3140         idx = instr_regarray_idx_hbo(p, t, ip);
3141         instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3142 }
3143
3144 static inline void
3145 __instr_regrd_hri_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3146 {
3147         uint64_t *regarray, idx;
3148
3149         TRACE("[Thread %2u] regrd (h = r[i])\n", p->thread_id);
3150
3151         regarray = instr_regarray_regarray(p, ip);
3152         idx = instr_regarray_idx_imm(p, ip);
3153         instr_regarray_dst_nbo_src_hbo_set(t, ip, regarray[idx]);
3154 }
3155
3156 static inline void
3157 __instr_regrd_mri_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3158 {
3159         uint64_t *regarray, idx;
3160
3161         TRACE("[Thread %2u] regrd (m = r[i])\n", p->thread_id);
3162
3163         regarray = instr_regarray_regarray(p, ip);
3164         idx = instr_regarray_idx_imm(p, ip);
3165         instr_regarray_dst_hbo_src_hbo_set(t, ip, regarray[idx]);
3166 }
3167
3168 static inline void
3169 __instr_regwr_rhh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3170 {
3171         uint64_t *regarray, idx, src;
3172
3173         TRACE("[Thread %2u] regwr (r[h] = h)\n", p->thread_id);
3174
3175         regarray = instr_regarray_regarray(p, ip);
3176         idx = instr_regarray_idx_nbo(p, t, ip);
3177         src = instr_regarray_src_nbo(t, ip);
3178         regarray[idx] = src;
3179 }
3180
3181 static inline void
3182 __instr_regwr_rhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3183 {
3184         uint64_t *regarray, idx, src;
3185
3186         TRACE("[Thread %2u] regwr (r[h] = m)\n", p->thread_id);
3187
3188         regarray = instr_regarray_regarray(p, ip);
3189         idx = instr_regarray_idx_nbo(p, t, ip);
3190         src = instr_regarray_src_hbo(t, ip);
3191         regarray[idx] = src;
3192 }
3193
3194 static inline void
3195 __instr_regwr_rmh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3196 {
3197         uint64_t *regarray, idx, src;
3198
3199         TRACE("[Thread %2u] regwr (r[m] = h)\n", p->thread_id);
3200
3201         regarray = instr_regarray_regarray(p, ip);
3202         idx = instr_regarray_idx_hbo(p, t, ip);
3203         src = instr_regarray_src_nbo(t, ip);
3204         regarray[idx] = src;
3205 }
3206
3207 static inline void
3208 __instr_regwr_rmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3209 {
3210         uint64_t *regarray, idx, src;
3211
3212         TRACE("[Thread %2u] regwr (r[m] = m)\n", p->thread_id);
3213
3214         regarray = instr_regarray_regarray(p, ip);
3215         idx = instr_regarray_idx_hbo(p, t, ip);
3216         src = instr_regarray_src_hbo(t, ip);
3217         regarray[idx] = src;
3218 }
3219
3220 static inline void
3221 __instr_regwr_rhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3222 {
3223         uint64_t *regarray, idx, src;
3224
3225         TRACE("[Thread %2u] regwr (r[h] = i)\n", p->thread_id);
3226
3227         regarray = instr_regarray_regarray(p, ip);
3228         idx = instr_regarray_idx_nbo(p, t, ip);
3229         src = ip->regarray.dstsrc_val;
3230         regarray[idx] = src;
3231 }
3232
3233 static inline void
3234 __instr_regwr_rmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3235 {
3236         uint64_t *regarray, idx, src;
3237
3238         TRACE("[Thread %2u] regwr (r[m] = i)\n", p->thread_id);
3239
3240         regarray = instr_regarray_regarray(p, ip);
3241         idx = instr_regarray_idx_hbo(p, t, ip);
3242         src = ip->regarray.dstsrc_val;
3243         regarray[idx] = src;
3244 }
3245
3246 static inline void
3247 __instr_regwr_rih_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3248 {
3249         uint64_t *regarray, idx, src;
3250
3251         TRACE("[Thread %2u] regwr (r[i] = h)\n", p->thread_id);
3252
3253         regarray = instr_regarray_regarray(p, ip);
3254         idx = instr_regarray_idx_imm(p, ip);
3255         src = instr_regarray_src_nbo(t, ip);
3256         regarray[idx] = src;
3257 }
3258
3259 static inline void
3260 __instr_regwr_rim_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3261 {
3262         uint64_t *regarray, idx, src;
3263
3264         TRACE("[Thread %2u] regwr (r[i] = m)\n", p->thread_id);
3265
3266         regarray = instr_regarray_regarray(p, ip);
3267         idx = instr_regarray_idx_imm(p, ip);
3268         src = instr_regarray_src_hbo(t, ip);
3269         regarray[idx] = src;
3270 }
3271
3272 static inline void
3273 __instr_regwr_rii_exec(struct rte_swx_pipeline *p,
3274                        struct thread *t __rte_unused,
3275                        const struct instruction *ip)
3276 {
3277         uint64_t *regarray, idx, src;
3278
3279         TRACE("[Thread %2u] regwr (r[i] = i)\n", p->thread_id);
3280
3281         regarray = instr_regarray_regarray(p, ip);
3282         idx = instr_regarray_idx_imm(p, ip);
3283         src = ip->regarray.dstsrc_val;
3284         regarray[idx] = src;
3285 }
3286
3287 static inline void
3288 __instr_regadd_rhh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3289 {
3290         uint64_t *regarray, idx, src;
3291
3292         TRACE("[Thread %2u] regadd (r[h] += h)\n", p->thread_id);
3293
3294         regarray = instr_regarray_regarray(p, ip);
3295         idx = instr_regarray_idx_nbo(p, t, ip);
3296         src = instr_regarray_src_nbo(t, ip);
3297         regarray[idx] += src;
3298 }
3299
3300 static inline void
3301 __instr_regadd_rhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3302 {
3303         uint64_t *regarray, idx, src;
3304
3305         TRACE("[Thread %2u] regadd (r[h] += m)\n", p->thread_id);
3306
3307         regarray = instr_regarray_regarray(p, ip);
3308         idx = instr_regarray_idx_nbo(p, t, ip);
3309         src = instr_regarray_src_hbo(t, ip);
3310         regarray[idx] += src;
3311 }
3312
3313 static inline void
3314 __instr_regadd_rmh_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3315 {
3316         uint64_t *regarray, idx, src;
3317
3318         TRACE("[Thread %2u] regadd (r[m] += h)\n", p->thread_id);
3319
3320         regarray = instr_regarray_regarray(p, ip);
3321         idx = instr_regarray_idx_hbo(p, t, ip);
3322         src = instr_regarray_src_nbo(t, ip);
3323         regarray[idx] += src;
3324 }
3325
3326 static inline void
3327 __instr_regadd_rmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3328 {
3329         uint64_t *regarray, idx, src;
3330
3331         TRACE("[Thread %2u] regadd (r[m] += m)\n", p->thread_id);
3332
3333         regarray = instr_regarray_regarray(p, ip);
3334         idx = instr_regarray_idx_hbo(p, t, ip);
3335         src = instr_regarray_src_hbo(t, ip);
3336         regarray[idx] += src;
3337 }
3338
3339 static inline void
3340 __instr_regadd_rhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3341 {
3342         uint64_t *regarray, idx, src;
3343
3344         TRACE("[Thread %2u] regadd (r[h] += i)\n", p->thread_id);
3345
3346         regarray = instr_regarray_regarray(p, ip);
3347         idx = instr_regarray_idx_nbo(p, t, ip);
3348         src = ip->regarray.dstsrc_val;
3349         regarray[idx] += src;
3350 }
3351
3352 static inline void
3353 __instr_regadd_rmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3354 {
3355         uint64_t *regarray, idx, src;
3356
3357         TRACE("[Thread %2u] regadd (r[m] += i)\n", p->thread_id);
3358
3359         regarray = instr_regarray_regarray(p, ip);
3360         idx = instr_regarray_idx_hbo(p, t, ip);
3361         src = ip->regarray.dstsrc_val;
3362         regarray[idx] += src;
3363 }
3364
3365 static inline void
3366 __instr_regadd_rih_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3367 {
3368         uint64_t *regarray, idx, src;
3369
3370         TRACE("[Thread %2u] regadd (r[i] += h)\n", p->thread_id);
3371
3372         regarray = instr_regarray_regarray(p, ip);
3373         idx = instr_regarray_idx_imm(p, ip);
3374         src = instr_regarray_src_nbo(t, ip);
3375         regarray[idx] += src;
3376 }
3377
3378 static inline void
3379 __instr_regadd_rim_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3380 {
3381         uint64_t *regarray, idx, src;
3382
3383         TRACE("[Thread %2u] regadd (r[i] += m)\n", p->thread_id);
3384
3385         regarray = instr_regarray_regarray(p, ip);
3386         idx = instr_regarray_idx_imm(p, ip);
3387         src = instr_regarray_src_hbo(t, ip);
3388         regarray[idx] += src;
3389 }
3390
3391 static inline void
3392 __instr_regadd_rii_exec(struct rte_swx_pipeline *p,
3393                         struct thread *t __rte_unused,
3394                         const struct instruction *ip)
3395 {
3396         uint64_t *regarray, idx, src;
3397
3398         TRACE("[Thread %2u] regadd (r[i] += i)\n", p->thread_id);
3399
3400         regarray = instr_regarray_regarray(p, ip);
3401         idx = instr_regarray_idx_imm(p, ip);
3402         src = ip->regarray.dstsrc_val;
3403         regarray[idx] += src;
3404 }
3405
3406 /*
3407  * metarray.
3408  */
3409 static inline struct meter *
3410 instr_meter_idx_hbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3411 {
3412         struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3413
3414         uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
3415         uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
3416         uint64_t idx64 = *idx64_ptr;
3417         uint64_t idx64_mask = UINT64_MAX >> (64 - (ip)->meter.idx.n_bits);
3418         uint64_t idx = idx64 & idx64_mask & r->size_mask;
3419
3420         return &r->metarray[idx];
3421 }
3422
3423 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3424
3425 static inline struct meter *
3426 instr_meter_idx_nbo(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3427 {
3428         struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3429
3430         uint8_t *idx_struct = t->structs[ip->meter.idx.struct_id];
3431         uint64_t *idx64_ptr = (uint64_t *)&idx_struct[ip->meter.idx.offset];
3432         uint64_t idx64 = *idx64_ptr;
3433         uint64_t idx = (ntoh64(idx64) >> (64 - ip->meter.idx.n_bits)) & r->size_mask;
3434
3435         return &r->metarray[idx];
3436 }
3437
3438 #else
3439
3440 #define instr_meter_idx_nbo instr_meter_idx_hbo
3441
3442 #endif
3443
3444 static inline struct meter *
3445 instr_meter_idx_imm(struct rte_swx_pipeline *p, const struct instruction *ip)
3446 {
3447         struct metarray_runtime *r = &p->metarray_runtime[ip->meter.metarray_id];
3448
3449         uint64_t idx =  ip->meter.idx_val & r->size_mask;
3450
3451         return &r->metarray[idx];
3452 }
3453
3454 static inline uint32_t
3455 instr_meter_length_hbo(struct thread *t, const struct instruction *ip)
3456 {
3457         uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
3458         uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
3459         uint64_t src64 = *src64_ptr;
3460         uint64_t src64_mask = UINT64_MAX >> (64 - (ip)->meter.length.n_bits);
3461         uint64_t src = src64 & src64_mask;
3462
3463         return (uint32_t)src;
3464 }
3465
3466 #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN
3467
3468 static inline uint32_t
3469 instr_meter_length_nbo(struct thread *t, const struct instruction *ip)
3470 {
3471         uint8_t *src_struct = t->structs[ip->meter.length.struct_id];
3472         uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.length.offset];
3473         uint64_t src64 = *src64_ptr;
3474         uint64_t src = ntoh64(src64) >> (64 - ip->meter.length.n_bits);
3475
3476         return (uint32_t)src;
3477 }
3478
3479 #else
3480
3481 #define instr_meter_length_nbo instr_meter_length_hbo
3482
3483 #endif
3484
3485 static inline enum rte_color
3486 instr_meter_color_in_hbo(struct thread *t, const struct instruction *ip)
3487 {
3488         uint8_t *src_struct = t->structs[ip->meter.color_in.struct_id];
3489         uint64_t *src64_ptr = (uint64_t *)&src_struct[ip->meter.color_in.offset];
3490         uint64_t src64 = *src64_ptr;
3491         uint64_t src64_mask = UINT64_MAX >> (64 - ip->meter.color_in.n_bits);
3492         uint64_t src = src64 & src64_mask;
3493
3494         return (enum rte_color)src;
3495 }
3496
3497 static inline void
3498 instr_meter_color_out_hbo_set(struct thread *t,
3499                               const struct instruction *ip,
3500                               enum rte_color color_out)
3501 {
3502         uint8_t *dst_struct = t->structs[ip->meter.color_out.struct_id];
3503         uint64_t *dst64_ptr = (uint64_t *)&dst_struct[ip->meter.color_out.offset];
3504         uint64_t dst64 = *dst64_ptr;
3505         uint64_t dst64_mask = UINT64_MAX >> (64 - ip->meter.color_out.n_bits);
3506
3507         uint64_t src = (uint64_t)color_out;
3508
3509         *dst64_ptr = (dst64 & ~dst64_mask) | (src & dst64_mask);
3510 }
3511
3512 static inline void
3513 __instr_metprefetch_h_exec(struct rte_swx_pipeline *p,
3514                            struct thread *t,
3515                            const struct instruction *ip)
3516 {
3517         struct meter *m;
3518
3519         TRACE("[Thread %2u] metprefetch (h)\n", p->thread_id);
3520
3521         m = instr_meter_idx_nbo(p, t, ip);
3522         rte_prefetch0(m);
3523 }
3524
3525 static inline void
3526 __instr_metprefetch_m_exec(struct rte_swx_pipeline *p,
3527                            struct thread *t,
3528                            const struct instruction *ip)
3529 {
3530         struct meter *m;
3531
3532         TRACE("[Thread %2u] metprefetch (m)\n", p->thread_id);
3533
3534         m = instr_meter_idx_hbo(p, t, ip);
3535         rte_prefetch0(m);
3536 }
3537
3538 static inline void
3539 __instr_metprefetch_i_exec(struct rte_swx_pipeline *p,
3540                            struct thread *t __rte_unused,
3541                            const struct instruction *ip)
3542 {
3543         struct meter *m;
3544
3545         TRACE("[Thread %2u] metprefetch (i)\n", p->thread_id);
3546
3547         m = instr_meter_idx_imm(p, ip);
3548         rte_prefetch0(m);
3549 }
3550
3551 static inline void
3552 __instr_meter_hhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3553 {
3554         struct meter *m;
3555         uint64_t time, n_pkts, n_bytes;
3556         uint32_t length;
3557         enum rte_color color_in, color_out;
3558
3559         TRACE("[Thread %2u] meter (hhm)\n", p->thread_id);
3560
3561         m = instr_meter_idx_nbo(p, t, ip);
3562         rte_prefetch0(m->n_pkts);
3563         time = rte_get_tsc_cycles();
3564         length = instr_meter_length_nbo(t, ip);
3565         color_in = instr_meter_color_in_hbo(t, ip);
3566
3567         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3568                 &m->profile->profile,
3569                 time,
3570                 length,
3571                 color_in);
3572
3573         color_out &= m->color_mask;
3574
3575         n_pkts = m->n_pkts[color_out];
3576         n_bytes = m->n_bytes[color_out];
3577
3578         instr_meter_color_out_hbo_set(t, ip, color_out);
3579
3580         m->n_pkts[color_out] = n_pkts + 1;
3581         m->n_bytes[color_out] = n_bytes + length;
3582 }
3583
3584 static inline void
3585 __instr_meter_hhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3586 {
3587         struct meter *m;
3588         uint64_t time, n_pkts, n_bytes;
3589         uint32_t length;
3590         enum rte_color color_in, color_out;
3591
3592         TRACE("[Thread %2u] meter (hhi)\n", p->thread_id);
3593
3594         m = instr_meter_idx_nbo(p, t, ip);
3595         rte_prefetch0(m->n_pkts);
3596         time = rte_get_tsc_cycles();
3597         length = instr_meter_length_nbo(t, ip);
3598         color_in = (enum rte_color)ip->meter.color_in_val;
3599
3600         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3601                 &m->profile->profile,
3602                 time,
3603                 length,
3604                 color_in);
3605
3606         color_out &= m->color_mask;
3607
3608         n_pkts = m->n_pkts[color_out];
3609         n_bytes = m->n_bytes[color_out];
3610
3611         instr_meter_color_out_hbo_set(t, ip, color_out);
3612
3613         m->n_pkts[color_out] = n_pkts + 1;
3614         m->n_bytes[color_out] = n_bytes + length;
3615 }
3616
3617 static inline void
3618 __instr_meter_hmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3619 {
3620         struct meter *m;
3621         uint64_t time, n_pkts, n_bytes;
3622         uint32_t length;
3623         enum rte_color color_in, color_out;
3624
3625         TRACE("[Thread %2u] meter (hmm)\n", p->thread_id);
3626
3627         m = instr_meter_idx_nbo(p, t, ip);
3628         rte_prefetch0(m->n_pkts);
3629         time = rte_get_tsc_cycles();
3630         length = instr_meter_length_hbo(t, ip);
3631         color_in = instr_meter_color_in_hbo(t, ip);
3632
3633         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3634                 &m->profile->profile,
3635                 time,
3636                 length,
3637                 color_in);
3638
3639         color_out &= m->color_mask;
3640
3641         n_pkts = m->n_pkts[color_out];
3642         n_bytes = m->n_bytes[color_out];
3643
3644         instr_meter_color_out_hbo_set(t, ip, color_out);
3645
3646         m->n_pkts[color_out] = n_pkts + 1;
3647         m->n_bytes[color_out] = n_bytes + length;
3648 }
3649
3650 static inline void
3651 __instr_meter_hmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3652 {
3653         struct meter *m;
3654         uint64_t time, n_pkts, n_bytes;
3655         uint32_t length;
3656         enum rte_color color_in, color_out;
3657
3658         TRACE("[Thread %2u] meter (hmi)\n", p->thread_id);
3659
3660         m = instr_meter_idx_nbo(p, t, ip);
3661         rte_prefetch0(m->n_pkts);
3662         time = rte_get_tsc_cycles();
3663         length = instr_meter_length_hbo(t, ip);
3664         color_in = (enum rte_color)ip->meter.color_in_val;
3665
3666         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3667                 &m->profile->profile,
3668                 time,
3669                 length,
3670                 color_in);
3671
3672         color_out &= m->color_mask;
3673
3674         n_pkts = m->n_pkts[color_out];
3675         n_bytes = m->n_bytes[color_out];
3676
3677         instr_meter_color_out_hbo_set(t, ip, color_out);
3678
3679         m->n_pkts[color_out] = n_pkts + 1;
3680         m->n_bytes[color_out] = n_bytes + length;
3681 }
3682
3683 static inline void
3684 __instr_meter_mhm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3685 {
3686         struct meter *m;
3687         uint64_t time, n_pkts, n_bytes;
3688         uint32_t length;
3689         enum rte_color color_in, color_out;
3690
3691         TRACE("[Thread %2u] meter (mhm)\n", p->thread_id);
3692
3693         m = instr_meter_idx_hbo(p, t, ip);
3694         rte_prefetch0(m->n_pkts);
3695         time = rte_get_tsc_cycles();
3696         length = instr_meter_length_nbo(t, ip);
3697         color_in = instr_meter_color_in_hbo(t, ip);
3698
3699         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3700                 &m->profile->profile,
3701                 time,
3702                 length,
3703                 color_in);
3704
3705         color_out &= m->color_mask;
3706
3707         n_pkts = m->n_pkts[color_out];
3708         n_bytes = m->n_bytes[color_out];
3709
3710         instr_meter_color_out_hbo_set(t, ip, color_out);
3711
3712         m->n_pkts[color_out] = n_pkts + 1;
3713         m->n_bytes[color_out] = n_bytes + length;
3714 }
3715
3716 static inline void
3717 __instr_meter_mhi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3718 {
3719         struct meter *m;
3720         uint64_t time, n_pkts, n_bytes;
3721         uint32_t length;
3722         enum rte_color color_in, color_out;
3723
3724         TRACE("[Thread %2u] meter (mhi)\n", p->thread_id);
3725
3726         m = instr_meter_idx_hbo(p, t, ip);
3727         rte_prefetch0(m->n_pkts);
3728         time = rte_get_tsc_cycles();
3729         length = instr_meter_length_nbo(t, ip);
3730         color_in = (enum rte_color)ip->meter.color_in_val;
3731
3732         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3733                 &m->profile->profile,
3734                 time,
3735                 length,
3736                 color_in);
3737
3738         color_out &= m->color_mask;
3739
3740         n_pkts = m->n_pkts[color_out];
3741         n_bytes = m->n_bytes[color_out];
3742
3743         instr_meter_color_out_hbo_set(t, ip, color_out);
3744
3745         m->n_pkts[color_out] = n_pkts + 1;
3746         m->n_bytes[color_out] = n_bytes + length;
3747 }
3748
3749 static inline void
3750 __instr_meter_mmm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3751 {
3752         struct meter *m;
3753         uint64_t time, n_pkts, n_bytes;
3754         uint32_t length;
3755         enum rte_color color_in, color_out;
3756
3757         TRACE("[Thread %2u] meter (mmm)\n", p->thread_id);
3758
3759         m = instr_meter_idx_hbo(p, t, ip);
3760         rte_prefetch0(m->n_pkts);
3761         time = rte_get_tsc_cycles();
3762         length = instr_meter_length_hbo(t, ip);
3763         color_in = instr_meter_color_in_hbo(t, ip);
3764
3765         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3766                 &m->profile->profile,
3767                 time,
3768                 length,
3769                 color_in);
3770
3771         color_out &= m->color_mask;
3772
3773         n_pkts = m->n_pkts[color_out];
3774         n_bytes = m->n_bytes[color_out];
3775
3776         instr_meter_color_out_hbo_set(t, ip, color_out);
3777
3778         m->n_pkts[color_out] = n_pkts + 1;
3779         m->n_bytes[color_out] = n_bytes + length;
3780 }
3781
3782 static inline void
3783 __instr_meter_mmi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3784 {
3785         struct meter *m;
3786         uint64_t time, n_pkts, n_bytes;
3787         uint32_t length;
3788         enum rte_color color_in, color_out;
3789
3790         TRACE("[Thread %2u] meter (mmi)\n", p->thread_id);
3791
3792         m = instr_meter_idx_hbo(p, t, ip);
3793         rte_prefetch0(m->n_pkts);
3794         time = rte_get_tsc_cycles();
3795         length = instr_meter_length_hbo(t, ip);
3796         color_in = (enum rte_color)ip->meter.color_in_val;
3797
3798         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3799                 &m->profile->profile,
3800                 time,
3801                 length,
3802                 color_in);
3803
3804         color_out &= m->color_mask;
3805
3806         n_pkts = m->n_pkts[color_out];
3807         n_bytes = m->n_bytes[color_out];
3808
3809         instr_meter_color_out_hbo_set(t, ip, color_out);
3810
3811         m->n_pkts[color_out] = n_pkts + 1;
3812         m->n_bytes[color_out] = n_bytes + length;
3813 }
3814
3815 static inline void
3816 __instr_meter_ihm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3817 {
3818         struct meter *m;
3819         uint64_t time, n_pkts, n_bytes;
3820         uint32_t length;
3821         enum rte_color color_in, color_out;
3822
3823         TRACE("[Thread %2u] meter (ihm)\n", p->thread_id);
3824
3825         m = instr_meter_idx_imm(p, ip);
3826         rte_prefetch0(m->n_pkts);
3827         time = rte_get_tsc_cycles();
3828         length = instr_meter_length_nbo(t, ip);
3829         color_in = instr_meter_color_in_hbo(t, ip);
3830
3831         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3832                 &m->profile->profile,
3833                 time,
3834                 length,
3835                 color_in);
3836
3837         color_out &= m->color_mask;
3838
3839         n_pkts = m->n_pkts[color_out];
3840         n_bytes = m->n_bytes[color_out];
3841
3842         instr_meter_color_out_hbo_set(t, ip, color_out);
3843
3844         m->n_pkts[color_out] = n_pkts + 1;
3845         m->n_bytes[color_out] = n_bytes + length;
3846 }
3847
3848 static inline void
3849 __instr_meter_ihi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3850 {
3851         struct meter *m;
3852         uint64_t time, n_pkts, n_bytes;
3853         uint32_t length;
3854         enum rte_color color_in, color_out;
3855
3856         TRACE("[Thread %2u] meter (ihi)\n", p->thread_id);
3857
3858         m = instr_meter_idx_imm(p, ip);
3859         rte_prefetch0(m->n_pkts);
3860         time = rte_get_tsc_cycles();
3861         length = instr_meter_length_nbo(t, ip);
3862         color_in = (enum rte_color)ip->meter.color_in_val;
3863
3864         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3865                 &m->profile->profile,
3866                 time,
3867                 length,
3868                 color_in);
3869
3870         color_out &= m->color_mask;
3871
3872         n_pkts = m->n_pkts[color_out];
3873         n_bytes = m->n_bytes[color_out];
3874
3875         instr_meter_color_out_hbo_set(t, ip, color_out);
3876
3877         m->n_pkts[color_out] = n_pkts + 1;
3878         m->n_bytes[color_out] = n_bytes + length;
3879 }
3880
3881 static inline void
3882 __instr_meter_imm_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3883 {
3884         struct meter *m;
3885         uint64_t time, n_pkts, n_bytes;
3886         uint32_t length;
3887         enum rte_color color_in, color_out;
3888
3889         TRACE("[Thread %2u] meter (imm)\n", p->thread_id);
3890
3891         m = instr_meter_idx_imm(p, ip);
3892         rte_prefetch0(m->n_pkts);
3893         time = rte_get_tsc_cycles();
3894         length = instr_meter_length_hbo(t, ip);
3895         color_in = instr_meter_color_in_hbo(t, ip);
3896
3897         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3898                 &m->profile->profile,
3899                 time,
3900                 length,
3901                 color_in);
3902
3903         color_out &= m->color_mask;
3904
3905         n_pkts = m->n_pkts[color_out];
3906         n_bytes = m->n_bytes[color_out];
3907
3908         instr_meter_color_out_hbo_set(t, ip, color_out);
3909
3910         m->n_pkts[color_out] = n_pkts + 1;
3911         m->n_bytes[color_out] = n_bytes + length;
3912 }
3913
3914 static inline void
3915 __instr_meter_imi_exec(struct rte_swx_pipeline *p, struct thread *t, const struct instruction *ip)
3916 {
3917         struct meter *m;
3918         uint64_t time, n_pkts, n_bytes;
3919         uint32_t length;
3920         enum rte_color color_in, color_out;
3921
3922         TRACE("[Thread %2u] meter (imi)\n", p->thread_id);
3923
3924         m = instr_meter_idx_imm(p, ip);
3925         rte_prefetch0(m->n_pkts);
3926         time = rte_get_tsc_cycles();
3927         length = instr_meter_length_hbo(t, ip);
3928         color_in = (enum rte_color)ip->meter.color_in_val;
3929
3930         color_out = rte_meter_trtcm_color_aware_check(&m->m,
3931                 &m->profile->profile,
3932                 time,
3933                 length,
3934                 color_in);
3935
3936         color_out &= m->color_mask;
3937
3938         n_pkts = m->n_pkts[color_out];
3939         n_bytes = m->n_bytes[color_out];
3940
3941         instr_meter_color_out_hbo_set(t, ip, color_out);
3942
3943         m->n_pkts[color_out] = n_pkts + 1;
3944         m->n_bytes[color_out] = n_bytes + length;
3945 }
3946
3947 #endif