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