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