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