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