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