The 2.41 release!
[binutils-gdb.git] / gas / config / tc-bpf.c
blob3b86f9c89cb68857db27bdce15aaedbf84f1a2d1
1 /* tc-bpf.c -- Assembler for the Linux eBPF.
2 Copyright (C) 2019-2023 Free Software Foundation, Inc.
3 Contributed by Oracle, Inc.
5 This file is part of GAS, the GNU Assembler.
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to
19 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 #include "as.h"
23 #include "subsegs.h"
24 #include "symcat.h"
25 #include "opcodes/bpf-desc.h"
26 #include "opcodes/bpf-opc.h"
27 #include "cgen.h"
28 #include "elf/common.h"
29 #include "elf/bpf.h"
30 #include "dwarf2dbg.h"
31 #include <ctype.h>
33 const char comment_chars[] = ";";
34 const char line_comment_chars[] = "#";
35 const char line_separator_chars[] = "`";
36 const char EXP_CHARS[] = "eE";
37 const char FLT_CHARS[] = "fFdD";
39 static const char *invalid_expression;
40 static char pseudoc_lex[256];
41 static const char symbol_chars[] =
42 "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
44 static const char arithm_op[] = "+-/<>%&|^";
46 static void init_pseudoc_lex (void);
48 #define LEX_IS_SYMBOL_COMPONENT 1
49 #define LEX_IS_WHITESPACE 2
50 #define LEX_IS_NEWLINE 3
51 #define LEX_IS_ARITHM_OP 4
52 #define LEX_IS_STAR 6
53 #define LEX_IS_CLSE_BR 7
54 #define LEX_IS_OPEN_BR 8
55 #define LEX_IS_EQUAL 9
56 #define LEX_IS_EXCLA 10
58 #define ST_EOI 100
59 #define MAX_TOKEN_SZ 100
61 /* Like s_lcomm_internal in gas/read.c but the alignment string
62 is allowed to be optional. */
64 static symbolS *
65 pe_lcomm_internal (int needs_align, symbolS *symbolP, addressT size)
67 addressT align = 0;
69 SKIP_WHITESPACE ();
71 if (needs_align
72 && *input_line_pointer == ',')
74 align = parse_align (needs_align - 1);
76 if (align == (addressT) -1)
77 return NULL;
79 else
81 if (size >= 8)
82 align = 3;
83 else if (size >= 4)
84 align = 2;
85 else if (size >= 2)
86 align = 1;
87 else
88 align = 0;
91 bss_alloc (symbolP, size, align);
92 return symbolP;
95 static void
96 pe_lcomm (int needs_align)
98 s_comm_internal (needs_align * 2, pe_lcomm_internal);
101 /* The target specific pseudo-ops which we support. */
102 const pseudo_typeS md_pseudo_table[] =
104 { "half", cons, 2 },
105 { "word", cons, 4 },
106 { "dword", cons, 8 },
107 { "lcomm", pe_lcomm, 1 },
108 { NULL, NULL, 0 }
113 /* ISA handling. */
114 static CGEN_BITSET *bpf_isa;
118 /* Command-line options processing. */
120 enum options
122 OPTION_LITTLE_ENDIAN = OPTION_MD_BASE,
123 OPTION_BIG_ENDIAN,
124 OPTION_XBPF
127 struct option md_longopts[] =
129 { "EL", no_argument, NULL, OPTION_LITTLE_ENDIAN },
130 { "EB", no_argument, NULL, OPTION_BIG_ENDIAN },
131 { "mxbpf", no_argument, NULL, OPTION_XBPF },
132 { NULL, no_argument, NULL, 0 },
135 size_t md_longopts_size = sizeof (md_longopts);
137 const char * md_shortopts = "";
139 extern int target_big_endian;
141 /* Whether target_big_endian has been set while parsing command-line
142 arguments. */
143 static int set_target_endian = 0;
145 static int target_xbpf = 0;
147 static int set_xbpf = 0;
150 md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
152 switch (c)
154 case OPTION_BIG_ENDIAN:
155 set_target_endian = 1;
156 target_big_endian = 1;
157 break;
158 case OPTION_LITTLE_ENDIAN:
159 set_target_endian = 1;
160 target_big_endian = 0;
161 break;
162 case OPTION_XBPF:
163 set_xbpf = 1;
164 target_xbpf = 1;
165 break;
166 default:
167 return 0;
170 return 1;
173 void
174 md_show_usage (FILE * stream)
176 fprintf (stream, _("\nBPF options:\n"));
177 fprintf (stream, _("\
178 --EL generate code for a little endian machine\n\
179 --EB generate code for a big endian machine\n\
180 -mxbpf generate xBPF instructions\n"));
185 static void
186 init_pseudoc_lex (void)
188 const char *p;
190 for (p = symbol_chars; *p; ++p)
191 pseudoc_lex[(unsigned char) *p] = LEX_IS_SYMBOL_COMPONENT;
193 pseudoc_lex[' '] = LEX_IS_WHITESPACE;
194 pseudoc_lex['\t'] = LEX_IS_WHITESPACE;
195 pseudoc_lex['\r'] = LEX_IS_WHITESPACE;
196 pseudoc_lex['\n'] = LEX_IS_NEWLINE;
197 pseudoc_lex['*'] = LEX_IS_STAR;
198 pseudoc_lex[')'] = LEX_IS_CLSE_BR;
199 pseudoc_lex['('] = LEX_IS_OPEN_BR;
200 pseudoc_lex[']'] = LEX_IS_CLSE_BR;
201 pseudoc_lex['['] = LEX_IS_OPEN_BR;
203 for (p = arithm_op; *p; ++p)
204 pseudoc_lex[(unsigned char) *p] = LEX_IS_ARITHM_OP;
206 pseudoc_lex['='] = LEX_IS_EQUAL;
207 pseudoc_lex['!'] = LEX_IS_EXCLA;
210 void
211 md_begin (void)
213 /* Initialize the `cgen' interface. */
215 /* If not specified in the command line, use the host
216 endianness. */
217 if (!set_target_endian)
219 #ifdef WORDS_BIGENDIAN
220 target_big_endian = 1;
221 #else
222 target_big_endian = 0;
223 #endif
226 /* If not specified in the command line, use eBPF rather
227 than xBPF. */
228 if (!set_xbpf)
229 target_xbpf = 0;
231 /* Set the ISA, which depends on the target endianness. */
232 bpf_isa = cgen_bitset_create (ISA_MAX);
233 if (target_big_endian)
235 if (target_xbpf)
236 cgen_bitset_set (bpf_isa, ISA_XBPFBE);
237 else
238 cgen_bitset_set (bpf_isa, ISA_EBPFBE);
240 else
242 if (target_xbpf)
243 cgen_bitset_set (bpf_isa, ISA_XBPFLE);
244 else
245 cgen_bitset_set (bpf_isa, ISA_EBPFLE);
248 /* Ensure that lines can begin with '*' in BPF store pseudoc instruction. */
249 lex_type['*'] |= LEX_BEGIN_NAME;
251 /* Set the machine number and endian. */
252 gas_cgen_cpu_desc = bpf_cgen_cpu_open (CGEN_CPU_OPEN_ENDIAN,
253 target_big_endian ?
254 CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE,
255 CGEN_CPU_OPEN_INSN_ENDIAN,
256 CGEN_ENDIAN_LITTLE,
257 CGEN_CPU_OPEN_ISAS,
258 bpf_isa,
259 CGEN_CPU_OPEN_END);
260 bpf_cgen_init_asm (gas_cgen_cpu_desc);
262 /* This is a callback from cgen to gas to parse operands. */
263 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
265 /* Set the machine type. */
266 bfd_default_set_arch_mach (stdoutput, bfd_arch_bpf, bfd_mach_bpf);
267 init_pseudoc_lex();
270 valueT
271 md_section_align (segT segment, valueT size)
273 int align = bfd_section_alignment (segment);
275 return ((size + (1 << align) - 1) & -(1 << align));
279 /* Functions concerning relocs. */
281 /* The location from which a PC relative jump should be calculated,
282 given a PC relative reloc. */
284 long
285 md_pcrel_from_section (fixS *fixP, segT sec)
287 if (fixP->fx_addsy != (symbolS *) NULL
288 && (! S_IS_DEFINED (fixP->fx_addsy)
289 || (S_GET_SEGMENT (fixP->fx_addsy) != sec)
290 || S_IS_EXTERNAL (fixP->fx_addsy)
291 || S_IS_WEAK (fixP->fx_addsy)))
293 /* The symbol is undefined (or is defined but not in this section).
294 Let the linker figure it out. */
295 return 0;
298 return fixP->fx_where + fixP->fx_frag->fr_address;
301 /* Write a value out to the object file, using the appropriate endianness. */
303 void
304 md_number_to_chars (char * buf, valueT val, int n)
306 if (target_big_endian)
307 number_to_chars_bigendian (buf, val, n);
308 else
309 number_to_chars_littleendian (buf, val, n);
312 arelent *
313 tc_gen_reloc (asection *sec, fixS *fix)
315 return gas_cgen_tc_gen_reloc (sec, fix);
318 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP. This
319 is called when the operand is an expression that couldn't be fully
320 resolved. Returns BFD_RELOC_NONE if no reloc type can be found.
321 *FIXP may be modified if desired. */
323 bfd_reloc_code_real_type
324 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
325 const CGEN_OPERAND *operand,
326 fixS *fixP)
328 switch (operand->type)
330 case BPF_OPERAND_IMM64:
331 return BFD_RELOC_BPF_64;
332 case BPF_OPERAND_DISP32:
333 fixP->fx_pcrel = 1;
334 return BFD_RELOC_BPF_DISP32;
335 default:
336 break;
338 return BFD_RELOC_NONE;
341 /* *FRAGP has been relaxed to its final size, and now needs to have
342 the bytes inside it modified to conform to the new size.
344 Called after relaxation is finished.
345 fragP->fr_type == rs_machine_dependent.
346 fragP->fr_subtype is the subtype of what the address relaxed to. */
348 void
349 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
350 segT sec ATTRIBUTE_UNUSED,
351 fragS *fragP ATTRIBUTE_UNUSED)
353 as_fatal (_("convert_frag called"));
357 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
358 segT segment ATTRIBUTE_UNUSED)
360 as_fatal (_("estimate_size_before_relax called"));
361 return 0;
365 void
366 md_apply_fix (fixS *fixP, valueT *valP, segT seg)
368 /* Some fixups for instructions require special attention. This is
369 handled in the code block below. */
370 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
372 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
373 const CGEN_OPERAND *operand = cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
374 opindex);
375 char *where;
377 switch (operand->type)
379 case BPF_OPERAND_DISP32:
380 /* eBPF supports two kind of CALL instructions: the so
381 called pseudo calls ("bpf to bpf") and external calls
382 ("bpf to kernel").
384 Both kind of calls use the same instruction (CALL).
385 However, external calls are constructed by passing a
386 constant argument to the instruction, whereas pseudo
387 calls result from expressions involving symbols. In
388 practice, instructions requiring a fixup are interpreted
389 as pseudo-calls. If we are executing this code, this is
390 a pseudo call.
392 The kernel expects for pseudo-calls to be annotated by
393 having BPF_PSEUDO_CALL in the SRC field of the
394 instruction. But beware the infamous nibble-swapping of
395 eBPF and take endianness into account here.
397 Note that the CALL instruction has only one operand, so
398 this code is executed only once per instruction. */
399 where = fixP->fx_frag->fr_literal + fixP->fx_where + 1;
400 where[0] = target_big_endian ? 0x01 : 0x10;
401 /* Fallthrough. */
402 case BPF_OPERAND_DISP16:
403 /* The PC-relative displacement fields in jump instructions
404 shouldn't be in bytes. Instead, they hold the number of
405 64-bit words to the target, _minus one_. */
406 *valP = (((long) (*valP)) - 8) / 8;
407 break;
408 default:
409 break;
413 /* And now invoke CGEN's handler, which will eventually install
414 *valP into the corresponding operand. */
415 gas_cgen_md_apply_fix (fixP, valP, seg);
419 The BPF pseudo grammar:
421 instruction : bpf_alu_insn
422 | bpf_alu32_insn
423 | bpf_jump_insn
424 | bpf_load_store_insn
425 | bpf_load_store32_insn
426 | bpf_non_generic_load
427 | bpf_endianness_conv_insn
428 | bpf_64_imm_load_insn
429 | bpf_atomic_insn
432 bpf_alu_insn : BPF_REG bpf_alu_operator register_or_imm32
435 bpf_alu32_insn : BPF_REG32 bpf_alu_operator register32_or_imm32
438 bpf_jump_insn : BPF_JA offset
439 | IF BPF_REG bpf_jump_operator register_or_imm32 BPF_JA offset
440 | IF BPF_REG32 bpf_jump_operator register_or_imm32 BPF_JA offset
441 | BPF_CALL offset
442 | BPF_EXIT
445 bpf_load_store_insn : BPF_REG CHR_EQUAL bpf_size_cast BPF_CHR_OPEN_BR \
446 register_and_offset BPF_CHR_CLSE_BR
447 | bpf_size_cast register_and_offset CHR_EQUAL BPF_REG
450 bpf_load_store32_insn : BPF_REG CHR_EQUAL bpf_size_cast BPF_CHR_OPEN_BR \
451 register32_and_offset BPF_CHR_CLSE_BR
452 | bpf_size_cast register_and_offset CHR_EQUAL BPF_REG32
455 bpf_non_generic_load : BPF_REG_R0 CHR_EQUAL bpf_size_cast BPF_LD BPF_CHR_OPEN_BR \
456 imm32 BPF_CHR_CLSE_BR
459 bpf_endianness_conv_insn : BPF_REG_N bpf_endianness_mnem BPF_REG_N
462 bpf_64_imm_load_insn : BPF_REG imm64 BPF_LL
465 bpf_atomic_insn : BPF_LOCK bpf_size_cast_32_64 register_and_offset BPF_ADD BPF_REG
467 register_and_offset : BPF_CHR_OPEN_BR BPF_REG offset BPF_CHR_CLSE_BR
470 register32_and_offset : BPF_CHR_OPEN_BR BPF_REG32 offset BPF_CHR_CLSE_BR
473 bpf_size_cast : CHR_START BPF_CHR_OPEN_BR bpf_size CHR_START BPF_CHR_CLSE_BR
476 bpf_size_cast_32_64 : CHR_START BPF_CHR_OPEN_BR bpf_size_cast_32_64 CHR_STAR BPF_CHR_CLSE_BR
479 bpf_size_32_64 : BPF_CAST_U32
480 | BPF_CAST_U64
483 bpf_size : BPF_CAST_U8
484 | BPF_CAST_U16
485 | BPF_CAST_U32
486 | BPF_CAST_U64
489 bpf_jump_operator : BPF_JEQ
490 | BPF_JGT
491 | BPF_JGE
492 | BPF_JNE
493 | BPF_JSGT
494 | BPF_JSGE
495 | BPF_JLT
496 | BPF_JLE
497 | BPF_JSLT
498 | BPF_JSLE
501 bpf_alu_operator : BPF_ADD
502 | BPF_SUB
503 | BPF_MUL
504 | BPF_DIV
505 | BPF_OR
506 | BPF_AND
507 | BPF_LSH
508 | BPF_RSH
509 | BPF_NEG
510 | BPF_MOD
511 | BPF_XOR
512 | BPF_ARSH
513 | CHR_EQUAL
516 bpf_endianness_mnem : BPF_LE16
517 | BPF_LE32
518 | BPF_LE64
519 | BPF_BE16
520 | BPF_BE32
521 | BPF_BE64
524 offset : BPF_EXPR
525 | BPF_SYMBOL
528 register_or_imm32 : BPF_REG
529 | expression
532 register32_or_imm32 : BPF_REG32
533 | expression
536 imm32 : BPF_EXPR
537 | BPF_SYMBOL
540 imm64 : BPF_EXPR
541 | BPF_SYMBOL
544 register_or_expression : BPF_EXPR
545 | BPF_REG
548 BPF_EXPR : GAS_EXPR
552 enum bpf_token_type
554 /* Keep grouped to quickly access. */
555 BPF_ADD,
556 BPF_SUB,
557 BPF_MUL,
558 BPF_DIV,
559 BPF_OR,
560 BPF_AND,
561 BPF_LSH,
562 BPF_RSH,
563 BPF_MOD,
564 BPF_XOR,
565 BPF_MOV,
566 BPF_ARSH,
567 BPF_NEG,
569 BPF_REG,
571 BPF_IF,
572 BPF_GOTO,
574 /* Keep grouped to quickly access. */
575 BPF_JEQ,
576 BPF_JGT,
577 BPF_JGE,
578 BPF_JLT,
579 BPF_JLE,
580 BPF_JSET,
581 BPF_JNE,
582 BPF_JSGT,
583 BPF_JSGE,
584 BPF_JSLT,
585 BPF_JSLE,
587 BPF_SYMBOL,
588 BPF_CHR_CLSE_BR,
589 BPF_CHR_OPEN_BR,
591 /* Keep grouped to quickly access. */
592 BPF_CAST_U8,
593 BPF_CAST_U16,
594 BPF_CAST_U32,
595 BPF_CAST_U64,
597 /* Keep grouped to quickly access. */
598 BPF_LE16,
599 BPF_LE32,
600 BPF_LE64,
601 BPF_BE16,
602 BPF_BE32,
603 BPF_BE64,
605 BPF_LOCK,
607 BPF_IND_CALL,
608 BPF_LD,
609 BPF_LL,
610 BPF_EXPR,
611 BPF_UNKNOWN,
614 static int
615 valid_expr (const char *e, const char **end_expr)
617 invalid_expression = NULL;
618 char *hold = input_line_pointer;
619 expressionS exp;
621 input_line_pointer = (char *) e;
622 deferred_expression (&exp);
623 *end_expr = input_line_pointer;
624 input_line_pointer = hold;
626 return invalid_expression == NULL;
629 static char *
630 build_bpf_non_generic_load (char *src, enum bpf_token_type cast,
631 const char *imm32)
633 char *bpf_insn;
634 static const char *cast_rw[] = {"b", "h", "w", "dw"};
636 bpf_insn = xasprintf ("%s%s%s %s%s%s%s",
637 "ld",
638 src ? "ind" : "abs",
639 cast_rw[cast - BPF_CAST_U8],
640 src ? "%" : "",
641 src ? src : "",
642 src ? "," : "",
643 imm32);
644 return bpf_insn;
647 static char *
648 build_bpf_atomic_insn (char *dst, char *src,
649 enum bpf_token_type atomic_insn,
650 enum bpf_token_type cast,
651 const char *offset)
653 char *bpf_insn;
654 static const char *cast_rw[] = {"w", "dw"};
655 static const char *mnem[] = {"xadd"};
657 bpf_insn = xasprintf ("%s%s [%%%s%s%s],%%%s", mnem[atomic_insn - BPF_ADD],
658 cast_rw[cast - BPF_CAST_U32], dst,
659 *offset != '+' ? "+" : "",
660 offset, src);
661 return bpf_insn;
664 static char *
665 build_bpf_jmp_insn (char *dst, char *src,
666 char *imm32, enum bpf_token_type op,
667 const char *sym, const char *offset)
669 char *bpf_insn;
670 static const char *mnem[] =
672 "jeq", "jgt", "jge", "jlt",
673 "jle", "jset", "jne", "jsgt",
674 "jsge", "jslt", "jsle"
677 const char *in32 = (*dst == 'w' ? "32" : "");
679 *dst = 'r';
680 if (src)
681 *src = 'r';
683 bpf_insn = xasprintf ("%s%s %%%s,%s%s,%s",
684 mnem[op - BPF_JEQ], in32, dst,
685 src ? "%" : "",
686 src ? src : imm32,
687 offset ? offset : sym);
688 return bpf_insn;
691 static char *
692 build_bpf_arithm_insn (char *dst, char *src,
693 int load64, const char *imm32,
694 enum bpf_token_type type)
696 char *bpf_insn;
697 static const char *mnem[] =
699 "add", "sub", "mul", "div",
700 "or", "and", "lsh", "rsh",
701 "mod", "xor", "mov", "arsh",
702 "neg",
704 const char *in32 = (*dst == 'w' ? "32" : "");
706 *dst = 'r';
707 if (src)
708 *src = 'r';
710 if (type == BPF_NEG)
711 bpf_insn = xasprintf ("%s%s %%%s", mnem[type - BPF_ADD], in32, dst);
712 else if (load64)
713 bpf_insn = xasprintf ("%s %%%s,%s", "lddw", dst, imm32);
714 else
715 bpf_insn = xasprintf ("%s%s %%%s,%s%s", mnem[type - BPF_ADD],
716 in32, dst,
717 src ? "%" : "",
718 src ? src: imm32);
719 return bpf_insn;
722 static char *
723 build_bpf_endianness (char *dst, enum bpf_token_type endianness)
725 char *bpf_insn;
726 static const char *size[] = {"16", "32", "64"};
727 int be = 1;
729 if (endianness == BPF_LE16
730 || endianness == BPF_LE32
731 || endianness == BPF_LE64)
732 be = 0;
733 else
734 gas_assert (endianness == BPF_BE16 || endianness == BPF_BE32 || endianness == BPF_BE64);
736 bpf_insn = xasprintf ("%s %%%s,%s", be ? "endbe" : "endle",
737 dst, be ? size[endianness - BPF_BE16] : size[endianness - BPF_LE16]);
738 return bpf_insn;
741 static char *
742 build_bpf_load_store_insn (char *dst, char *src,
743 enum bpf_token_type cast,
744 const char *offset, int isload)
746 char *bpf_insn;
747 static const char *cast_rw[] = {"b", "h", "w", "dw"};
749 *dst = *src = 'r';
750 if (isload)
751 bpf_insn = xasprintf ("%s%s %%%s,[%%%s%s%s]", "ldx",
752 cast_rw[cast - BPF_CAST_U8], dst, src,
753 *offset != '+' ? "+" : "",
754 offset);
755 else
756 bpf_insn = xasprintf ("%s%s [%%%s%s%s],%%%s", "stx",
757 cast_rw[cast - BPF_CAST_U8], dst,
758 *offset != '+' ? "+" : "",
759 offset, src);
760 return bpf_insn;
763 static int
764 look_for_reserved_word (const char *token, enum bpf_token_type *type)
766 int i;
767 static struct
769 const char *name;
770 enum bpf_token_type type;
771 } reserved_words[] =
774 .name = "if",
775 .type = BPF_IF
778 .name = "goto",
779 .type = BPF_GOTO
782 .name = "le16",
783 .type = BPF_LE16
786 .name = "le32",
787 .type = BPF_LE32
790 .name = "le64",
791 .type = BPF_LE64
794 .name = "be16",
795 .type = BPF_BE16
798 .name = "be32",
799 .type = BPF_BE32
802 .name = "be64",
803 .type = BPF_BE64
806 .name = "lock",
807 .type = BPF_LOCK
810 .name = "callx",
811 .type = BPF_IND_CALL
814 .name = "skb",
815 .type = BPF_LD
818 .name = "ll",
819 .type = BPF_LL
822 .name = NULL,
826 for (i = 0; reserved_words[i].name; ++i)
827 if (*reserved_words[i].name == *token
828 && !strcmp (reserved_words[i].name, token))
830 *type = reserved_words[i].type;
831 return 1;
834 return 0;
837 static int
838 is_register (const char *token, int len)
840 if (token[0] == 'r' || token[0] == 'w')
841 if ((len == 2 && isdigit (token[1]))
842 || (len == 3 && token[1] == '1' && token[2] == '0'))
843 return 1;
845 return 0;
848 static enum bpf_token_type
849 is_cast (const char *token)
851 static const char *cast_rw[] = {"u8", "u16", "u32", "u64"};
852 unsigned int i;
854 for (i = 0; i < ARRAY_SIZE (cast_rw); ++i)
855 if (!strcmp (token, cast_rw[i]))
856 return BPF_CAST_U8 + i;
858 return BPF_UNKNOWN;
861 static enum bpf_token_type
862 get_token (const char **insn, char *token, size_t *tlen)
864 #define GET() \
865 (*str == '\0' \
866 ? EOF \
867 : *(unsigned char *)(str++))
869 #define UNGET() (--str)
871 #define START_EXPR() \
872 do \
874 if (expr == NULL) \
875 expr = str - 1; \
876 } while (0)
878 #define SCANNER_SKIP_WHITESPACE() \
879 do \
881 do \
882 ch = GET (); \
883 while (ch != EOF \
884 && ((ch) == ' ' || (ch) == '\t')); \
885 if (ch != EOF) \
886 UNGET (); \
887 } while (0)
889 const char *str = *insn;
890 int ch, ch2 = 0;
891 enum bpf_token_type ttype = BPF_UNKNOWN;
892 size_t len = 0;
893 const char *expr = NULL;
894 const char *end_expr = NULL;
895 int state = 0;
896 int return_token = 0;
898 while (1)
900 ch = GET ();
902 if (ch == EOF || len > MAX_TOKEN_SZ)
903 break;
905 switch (pseudoc_lex[(unsigned char) ch])
907 case LEX_IS_WHITESPACE:
908 SCANNER_SKIP_WHITESPACE ();
909 return_token = 1;
911 switch (state)
913 case 12: /* >' ' */
914 ttype = BPF_JGT;
915 break;
917 case 17: /* ==' ' */
918 ttype = BPF_JEQ;
919 break;
921 case 18: /* <' ' */
922 ttype = BPF_JLT;
923 break;
925 case 20: /* &' ' */
926 ttype = BPF_JSET;
927 break;
929 case 22: /* s<' '*/
930 ttype = BPF_JSLT;
931 break;
933 case 14: /* s> ' ' */
934 ttype = BPF_JSGT;
935 break;
937 case 16: /* =' ' */
938 ttype = BPF_MOV;
939 break;
941 default:
942 return_token = 0;
944 break;
946 case LEX_IS_EXCLA:
947 token[len++] = ch;
948 state = 21;
949 break;
951 case LEX_IS_ARITHM_OP:
952 if (state == 16)
954 /* ='-' is handle as '=' */
955 UNGET ();
956 ttype = BPF_MOV;
957 return_token = 1;
958 break;
961 START_EXPR();
962 token[len++] = ch;
963 switch (ch)
965 #define BPF_ARITHM_OP(op, type) \
966 case (op): \
967 state = 6; \
968 ttype = (type); \
969 break;
971 BPF_ARITHM_OP('+', BPF_ADD);
972 BPF_ARITHM_OP('-', BPF_SUB);
973 BPF_ARITHM_OP('*', BPF_MUL);
974 BPF_ARITHM_OP('/', BPF_DIV);
975 BPF_ARITHM_OP('|', BPF_OR);
976 BPF_ARITHM_OP('%', BPF_MOD);
977 BPF_ARITHM_OP('^', BPF_XOR);
979 case '&':
980 state = 20; /* '&' */
981 break;
983 case '<':
984 switch (state)
986 case 0:
987 state = 18; /* '<' */
988 break;
990 case 18:
991 state = 19; /* <'<' */
992 break;
994 case 8:
995 state = 22; /* s'<' */
996 break;
998 break;
1000 case '>':
1001 switch (state)
1003 case 0:
1004 state = 12; /* '>' */
1005 break;
1007 case 12:
1008 state = 13; /* >'>' */
1009 break;
1011 case 8:
1012 state = 14; /* s'>' */
1013 break;
1015 case 14:
1016 state = 15; /* s>'>' */
1017 break;
1019 break;
1021 break;
1023 case LEX_IS_STAR:
1024 switch (state)
1026 case 0:
1027 token[len++] = ch;
1028 START_EXPR ();
1029 state = 2; /* '*', It could be the fist cast char. */
1030 break;
1032 case 16: /* ='*' Not valid token. */
1033 ttype = BPF_MOV;
1034 return_token = 1;
1035 UNGET ();
1036 break;
1038 case 4: /* *(uXX'*' */
1039 token[len++] = ch;
1040 state = 5;
1041 break;
1043 break;
1045 case LEX_IS_OPEN_BR:
1046 START_EXPR ();
1047 token[len++] = ch;
1048 return_token = 1;
1050 switch (state)
1052 case 2:
1053 state = 3; /* *'(' second char of a cast or expr. */
1054 return_token = 0;
1055 break;
1057 case 6:
1058 if (valid_expr (expr, &end_expr))
1060 len = end_expr - expr;
1061 memcpy (token, expr, len);
1062 ttype = BPF_EXPR;
1063 str = end_expr;
1065 else
1067 len = 0;
1068 while (*invalid_expression)
1069 token[len++] = *invalid_expression++;
1071 token[len] = 0;
1072 ttype = BPF_UNKNOWN;
1074 break;
1076 default:
1077 ttype = BPF_CHR_OPEN_BR;
1078 SCANNER_SKIP_WHITESPACE ();
1079 ch2 = GET ();
1081 if ((isdigit (ch2) || ch2 == '(')
1082 && valid_expr (expr, &end_expr))
1084 len = end_expr - expr;
1085 memcpy (token, expr, len);
1086 ttype = BPF_EXPR;
1087 str = end_expr;
1089 else
1090 UNGET ();
1092 break;
1094 case LEX_IS_CLSE_BR:
1095 token[len++] = ch;
1097 if (state == 0)
1099 ttype = BPF_CHR_CLSE_BR;
1100 return_token = 1;
1102 else if (state == 5) /* *(uXX*')' */
1103 return_token = 1;
1104 break;
1106 case LEX_IS_EQUAL:
1107 token[len++] = ch;
1108 return_token = 1;
1110 switch (state)
1112 case 0:
1113 state = 16; /* '=' */
1114 return_token = 0;
1115 break;
1117 case 16:
1118 state = 17; /* ='=' */
1119 return_token = 0;
1120 break;
1122 case 2: /* *'=' */
1123 ttype = BPF_MUL;
1124 break;
1126 case 10: /* s>>'=' */
1127 ttype = BPF_ARSH;
1128 break;
1130 case 12: /* >'=' */
1131 ttype = BPF_JGE;
1132 break;
1134 case 13: /* >>'=' */
1135 ttype = BPF_RSH;
1136 break;
1138 case 14: /* s>'=' */
1139 ttype = BPF_JSGE;
1140 break;
1142 case 15: /* s>>'=' */
1143 ttype = BPF_ARSH;
1144 break;
1146 case 18: /* <'=' */
1147 ttype = BPF_JLE;
1148 break;
1150 case 19: /* <<'=' */
1151 ttype = BPF_LSH;
1152 break;
1154 case 20: /* &'=' */
1155 ttype = BPF_AND;
1156 break;
1158 case 21: /* !'=' */
1159 ttype = BPF_JNE;
1160 break;
1162 case 22: /* s<'=' */
1163 ttype = BPF_JSLE;
1164 break;
1166 break;
1168 case LEX_IS_SYMBOL_COMPONENT:
1169 return_token = 1;
1171 switch (state)
1173 case 17: /* =='sym' */
1174 ttype = BPF_JEQ;
1175 break;
1177 case 12: /* >'sym' */
1178 ttype = BPF_JGT;
1179 break;
1181 case 18: /* <'sym' */
1182 ttype = BPF_JLT;
1183 break;
1185 case 20: /* &'sym' */
1186 ttype = BPF_JSET;
1187 break;
1189 case 14: /*s>'sym' */
1190 ttype = BPF_JSGT;
1191 break;
1193 case 22: /* s<'sym' */
1194 ttype = BPF_JSLT;
1195 break;
1197 case 16: /* ='sym' */
1198 ttype = BPF_MOV;
1199 break;
1201 default:
1202 return_token = 0;
1205 if (return_token)
1207 UNGET ();
1208 break;
1211 START_EXPR ();
1212 token[len++] = ch;
1214 while ((ch2 = GET ()) != EOF)
1216 int type;
1218 type = pseudoc_lex[(unsigned char) ch2];
1219 if (type != LEX_IS_SYMBOL_COMPONENT)
1220 break;
1221 token[len++] = ch2;
1224 if (ch2 != EOF)
1225 UNGET ();
1227 if (state == 0)
1229 if (len == 1 && ch == 's')
1230 state = 8; /* signed instructions: 's' */
1231 else
1233 ttype = BPF_SYMBOL;
1234 if (is_register (token, len))
1235 ttype = BPF_REG;
1236 else if (look_for_reserved_word (token, &ttype))
1238 else if ((pseudoc_lex[(unsigned char) *token] == LEX_IS_ARITHM_OP
1239 || *token == '(' || isdigit(*token))
1240 && valid_expr (expr, &end_expr))
1242 len = end_expr - expr;
1243 token[len] = '\0';
1244 ttype = BPF_EXPR;
1245 str = end_expr;
1248 return_token = 1;
1251 else if (state == 3) /* *('sym' */
1253 if ((ttype = is_cast (&token[2])) != BPF_UNKNOWN)
1254 state = 4; /* *('uXX' */
1255 else
1257 ttype = BPF_EXPR;
1258 return_token = 1;
1261 else if (state == 6)
1263 if (ttype == BPF_SUB) /* neg */
1265 if (is_register (&token[1], len - 1))
1266 ttype = BPF_NEG;
1267 else if (valid_expr(expr, &end_expr))
1269 len = end_expr - expr;
1270 memcpy(token, expr, len);
1271 ttype = BPF_EXPR;
1272 str = end_expr;
1274 else
1276 len = 0;
1277 while (*invalid_expression)
1278 token[len++] = *invalid_expression++;
1279 token[len] = 0;
1280 ttype = BPF_UNKNOWN;
1283 else if (valid_expr (expr, &end_expr))
1285 len = end_expr - expr;
1286 memcpy(token, expr, len);
1287 ttype = BPF_EXPR;
1288 str = end_expr;
1290 else
1291 ttype = BPF_UNKNOWN;
1293 return_token = 1;
1295 break;
1298 if (return_token)
1300 *tlen = len;
1301 *insn = str;
1302 break;
1306 return ttype;
1308 #undef GET
1309 #undef UNGET
1310 #undef START_EXPR
1311 #undef SCANNER_SKIP_WHITESPACE
1312 #undef BPF_ARITHM_OP
1316 The parser represent a FSM for the grammar described above. So for example
1317 the following rule:
1319 ` bpf_alu_insn : BPF_REG bpf_alu_operator register_or_imm32'
1321 Is parser as follows:
1323 1. It starts in state 0.
1325 2. Consumes next token, e.g: `BPF_REG' and set `state' variable to a
1326 particular state to helps to identify, in this case, that a register
1327 token has been read, a comment surrounded by a single quote in the
1328 pseudo-c token is added along with the new `state' value to indicate
1329 what the scanner has read, e.g.:
1331 state = 6; // dst_reg = str_cast ( 'src_reg'
1333 So, in `state 6' the scanner has consumed: a destination register
1334 (BPF_REG), an equal character (BPF_MOV), a cast token (BPF_CAST), an
1335 open parenthesis (BPF_CHR_OPEN_BR) and the source register (BPF_REG).
1337 3. If the accumulated tokens represent a complete BPF pseudo-c syntax
1338 instruction then, a validation of the terms is made, for example: if
1339 the registers have the same sizes (32/64 bits), if a specific
1340 destination register must be used, etc., after that, a builder:
1341 build_bfp_{non_generic_load,atomic_insn,jmp_insn,arithm_insn,endianness,load_store_insn}
1342 is invoked, internally, it translates the BPF pseudo-c instruction to
1343 a BPF GAS instruction using the previous terms recollected by the
1344 scanner.
1346 4. If a successful build of BPF GAS instruction was done, a final
1347 state is set to `ST_EOI' (End Of Instruction) meaning that is not
1348 expecting for more tokens in such instruction. Otherwise if the
1349 conditions to calling builder are not satisfied an error is emitted
1350 and `parse_err' is set.
1353 static char *
1354 bpf_pseudoc_to_normal_syntax (const char *str, char **errmsg)
1356 #define syntax_err(format, ...) \
1357 do \
1359 if (! parse_err) \
1361 parse_err = 1; \
1362 errbuf = xasprintf (format, ##__VA_ARGS__); \
1364 } while (0)
1366 enum bpf_token_type ttype;
1367 enum bpf_token_type bpf_endianness = BPF_UNKNOWN,
1368 bpf_atomic_insn;
1369 enum bpf_token_type bpf_jmp_op = BPF_JEQ; /* Arbitrary. */
1370 enum bpf_token_type bpf_cast = BPF_CAST_U8; /* Arbitrary. */
1371 enum bpf_token_type bpf_arithm_op = BPF_ADD; /* Arbitrary. */
1372 char *bpf_insn = NULL;
1373 char *errbuf = NULL;
1374 char src_reg[3] = {0};
1375 char dst_reg[3] = {0};
1376 char str_imm32[40] = {0};
1377 char str_offset[40] = {0};
1378 char str_symbol[MAX_TOKEN_SZ] = {0};
1379 char token[MAX_TOKEN_SZ] = {0};
1380 int state = 0;
1381 int parse_err = 0;
1382 size_t tlen;
1384 while (*str)
1386 ttype = get_token (&str, token, &tlen);
1387 if (ttype == BPF_UNKNOWN || state == ST_EOI)
1389 syntax_err ("unexpected token: '%s'", token);
1390 break;
1393 switch (ttype)
1395 case BPF_UNKNOWN:
1396 case BPF_LL:
1397 break;
1399 case BPF_REG:
1400 switch (state)
1402 case 0:
1403 memcpy (dst_reg, token, tlen);
1404 state = 1; /* 'dst_reg' */
1405 break;
1407 case 3:
1408 /* dst_reg bpf_op 'src_reg' */
1409 memcpy (src_reg, token, tlen);
1410 if (*dst_reg == *src_reg)
1411 bpf_insn = build_bpf_arithm_insn (dst_reg, src_reg, 0,
1412 NULL, bpf_arithm_op);
1413 else
1415 syntax_err ("different register sizes: '%s', '%s'",
1416 dst_reg, src_reg);
1417 break;
1419 state = ST_EOI;
1420 break;
1422 case 5:
1423 memcpy (src_reg, token, tlen);
1424 state = 6; /* dst_reg = str_cast ( 'src_reg' */
1425 break;
1427 case 9:
1428 memcpy (dst_reg, token, tlen);
1429 state = 10; /* str_cast ( 'dst_reg' */
1430 break;
1432 case 11:
1433 /* str_cast ( dst_reg offset ) = 'src_reg' */
1434 memcpy (src_reg, token, tlen);
1435 bpf_insn = build_bpf_load_store_insn (dst_reg, src_reg,
1436 bpf_cast, str_offset, 0);
1437 state = ST_EOI;
1438 break;
1440 case 14:
1441 memcpy (dst_reg, token, tlen);
1442 state = 15; /* if 'dst_reg' */
1443 break;
1445 case 16:
1446 memcpy (src_reg, token, tlen);
1447 state = 17; /* if dst_reg jmp_op 'src_reg' */
1448 break;
1450 case 24:
1451 /* dst_reg = endianness src_reg */
1452 memcpy (src_reg, token, tlen);
1453 if (*dst_reg == 'r' && !strcmp (dst_reg, src_reg))
1454 bpf_insn = build_bpf_endianness (dst_reg, bpf_endianness);
1455 else
1456 syntax_err ("invalid operand for instruction: '%s'", token);
1458 state = ST_EOI;
1459 break;
1461 case 28:
1462 memcpy (dst_reg, token, tlen);
1463 state = 29; /* lock str_cast ( 'dst_reg' */
1464 break;
1466 case 32:
1468 /* lock str_cast ( dst_reg offset ) atomic_insn 'src_reg' */
1469 int with_offset = *str_offset != '\0';
1471 memcpy (src_reg, token, tlen);
1472 if ((bpf_cast != BPF_CAST_U32
1473 && bpf_cast != BPF_CAST_U64)
1474 || *dst_reg != 'r'
1475 || *src_reg != 'r')
1476 syntax_err ("invalid wide atomic instruction");
1477 else
1478 bpf_insn = build_bpf_atomic_insn (dst_reg, src_reg, bpf_atomic_insn,
1479 bpf_cast, with_offset ? str_offset : str_symbol);
1482 state = ST_EOI;
1483 break;
1485 case 33:
1486 /* callx 'dst_reg' */
1487 bpf_insn = xasprintf ("%s %%%s", "call", token);
1488 state = ST_EOI;
1489 break;
1491 case 35:
1492 memcpy (src_reg, token, tlen);
1493 state = 36; /* dst_reg = str_cast skb [ 'src_reg' */
1494 break;
1496 break;
1498 case BPF_MOV:
1499 case BPF_ADD:
1500 case BPF_SUB:
1501 case BPF_MUL:
1502 case BPF_DIV:
1503 case BPF_OR:
1504 case BPF_AND:
1505 case BPF_LSH:
1506 case BPF_RSH:
1507 case BPF_MOD:
1508 case BPF_XOR:
1509 case BPF_ARSH:
1510 case BPF_NEG:
1511 switch (state)
1513 case 1:
1514 state = 3; /* dst_reg 'arith_op' */
1515 bpf_arithm_op = ttype;
1516 break;
1518 case 3:
1519 if (ttype == BPF_NEG)
1521 /* reg = -reg */
1522 bpf_arithm_op = ttype;
1523 memcpy (src_reg, token + 1, tlen - 1);
1524 if (strcmp (dst_reg, src_reg))
1526 syntax_err ("found: '%s', expected: -%s", token, dst_reg);
1527 break;
1530 bpf_insn = build_bpf_arithm_insn (dst_reg, src_reg, 0,
1531 NULL, bpf_arithm_op);
1532 state = ST_EOI;
1534 break;
1536 case 23:
1537 memcpy (src_reg, token, tlen);
1538 state = 11; /* str_cast ( dst_reg offset ) '=' */
1539 break;
1541 case 12:
1542 if (ttype == BPF_MOV)
1543 state = 13; /* str_cast ( dst_reg offset ) '=' */
1544 break;
1546 case 31:
1547 bpf_atomic_insn = ttype;
1548 state = 32; /* lock str_cast ( dst_reg offset ) 'atomic_insn' */
1549 break;
1551 default:
1552 syntax_err ("unexpected '%s'", token);
1553 state = ST_EOI;
1555 break;
1557 case BPF_CAST_U8:
1558 case BPF_CAST_U16:
1559 case BPF_CAST_U32:
1560 case BPF_CAST_U64:
1561 bpf_cast = ttype;
1562 switch (state)
1564 case 3:
1565 state = 4; /* dst_reg = 'str_cast' */
1566 break;
1568 case 0:
1569 state = 8; /* 'str_cast' */
1570 break;
1572 case 26:
1573 state = 27; /* lock 'str_cast' */
1574 break;
1576 break;
1578 case BPF_CHR_OPEN_BR:
1579 switch (state)
1581 case 4:
1582 state = 5; /* dst_reg = str_cast '(' */
1583 break;
1585 case 8:
1586 state = 9; /* str_cast '(' */
1587 break;
1589 case 27:
1590 state = 28; /* lock str_cast '(' */
1591 break;
1593 case 34:
1594 state = 35; /* dst_reg = str_cast skb '[' */
1595 break;
1597 break;
1599 case BPF_CHR_CLSE_BR:
1600 switch (state)
1602 case 7:
1603 /* dst_reg = str_cast ( imm32 ')' */
1604 bpf_insn = build_bpf_load_store_insn (dst_reg, src_reg,
1605 bpf_cast, str_imm32, 1);
1606 state = ST_EOI;
1607 break;
1609 case 11:
1610 state = 12; /* str_cast ( dst_reg imm32 ')' */
1611 break;
1613 case 21:
1614 /* dst_reg = str_cast ( src_reg offset ')' */
1615 bpf_insn = build_bpf_load_store_insn (dst_reg, src_reg,
1616 bpf_cast, str_offset, 1);
1617 state = ST_EOI;
1618 break;
1620 case 22:
1621 state = 23; /* str_cast ( dst_reg offset ')' */
1622 break;
1624 case 30:
1625 state = 31; /* lock str_cast ( dst_reg offset ')' */
1626 break;
1628 case 37:
1629 /* dst_reg = str_cast skb [ src_reg imm32 ']' */
1630 if (*dst_reg != 'w' && !strcmp ("r0", dst_reg))
1631 bpf_insn = build_bpf_non_generic_load (*src_reg != '\0' ? src_reg : NULL,
1632 bpf_cast, str_imm32);
1633 else
1634 syntax_err ("invalid register operand: '%s'", dst_reg);
1636 state = ST_EOI;
1637 break;
1639 break;
1641 case BPF_EXPR:
1642 switch (state)
1644 case 3:
1646 /* dst_reg bpf_arithm_op 'imm32' */
1647 int load64 = 0;
1649 memcpy (str_imm32, token, tlen);
1650 memset (token, 0, tlen);
1652 if ((ttype = get_token (&str, token, &tlen)) == BPF_LL
1653 && bpf_arithm_op == BPF_MOV)
1654 load64 = 1;
1655 else if (ttype != BPF_UNKNOWN)
1656 syntax_err ("unexpected token: '%s'", token);
1658 if (load64 && *dst_reg == 'w')
1659 syntax_err ("unexpected register size: '%s'", dst_reg);
1661 if (! parse_err)
1662 bpf_insn = build_bpf_arithm_insn (dst_reg, NULL, load64,
1663 str_imm32, bpf_arithm_op);
1664 state = ST_EOI;
1666 break;
1668 case 18:
1670 /* if dst_reg jmp_op src_reg goto 'offset' */
1671 int with_src = *src_reg != '\0';
1673 memcpy (str_offset, token, tlen);
1674 if (with_src && *dst_reg != *src_reg)
1675 syntax_err ("different register size: '%s', '%s'",
1676 dst_reg, src_reg);
1677 else
1678 bpf_insn = build_bpf_jmp_insn (dst_reg, with_src ? src_reg : NULL,
1679 with_src ? NULL: str_imm32,
1680 bpf_jmp_op, NULL, str_offset);
1681 state = ST_EOI;
1683 break;
1685 case 19:
1686 /* goto 'offset' */
1687 memcpy (str_offset, token, tlen);
1688 bpf_insn = xasprintf ("%s %s", "ja", str_offset);
1689 state = ST_EOI;
1690 break;
1692 case 6:
1693 memcpy (str_offset, token, tlen);
1694 state = 21; /* dst_reg = str_cast ( src_reg 'offset' */
1695 break;
1697 case 10:
1698 memcpy (str_offset, token, tlen);
1699 state = 22; /* str_cast ( dst_reg 'offset' */
1700 break;
1702 case 16:
1703 memcpy (str_imm32, token, tlen);
1704 state = 25; /* if dst_reg jmp_op 'imm32' */
1705 break;
1707 case 29:
1708 memcpy (str_offset, token, tlen);
1709 state = 30; /* lock str_cast ( dst_reg 'offset' */
1710 break;
1712 case 34:
1713 /* dst_reg = str_cast skb 'imm32' */
1714 if (*dst_reg != 'w' && !strcmp ("r0", dst_reg))
1716 memcpy (str_imm32, token, tlen);
1717 bpf_insn = build_bpf_non_generic_load (*src_reg != '\0' ? src_reg : NULL,
1718 bpf_cast, str_imm32);
1720 else
1721 syntax_err ("invalid register operand: '%s'", dst_reg);
1723 state = ST_EOI;
1724 break;
1726 case 36:
1727 memcpy (str_imm32, token, tlen);
1728 state = 37; /* dst_reg = str_cast skb [ src_reg 'imm32' */
1729 break;
1731 break;
1733 case BPF_IF:
1734 if (state == 0)
1735 state = 14;
1736 break;
1738 case BPF_JSGT:
1739 case BPF_JSLT:
1740 case BPF_JSLE:
1741 case BPF_JSGE:
1742 case BPF_JGT:
1743 case BPF_JGE:
1744 case BPF_JLE:
1745 case BPF_JSET:
1746 case BPF_JNE:
1747 case BPF_JLT:
1748 case BPF_JEQ:
1749 if (state == 15)
1751 bpf_jmp_op = ttype;
1752 state = 16; /* if dst_reg 'jmp_op' */
1754 break;
1756 case BPF_GOTO:
1757 switch (state)
1759 case 17:
1760 case 25:
1761 state = 18; /* if dst_reg jmp_op src_reg|imm32 'goto' */
1762 break;
1764 case 0:
1765 state = 19;
1766 break;
1768 break;
1770 case BPF_SYMBOL:
1771 switch (state)
1773 case 18:
1775 /* if dst_reg jmp_op src_reg goto 'sym' */
1776 int with_src = *src_reg != '\0';
1778 memcpy (str_symbol, token, tlen);
1779 if (with_src && *dst_reg != *src_reg)
1780 syntax_err ("different register size: '%s', '%s'",
1781 dst_reg, src_reg);
1782 else
1783 bpf_insn = build_bpf_jmp_insn (dst_reg, with_src ? src_reg : NULL,
1784 with_src ? NULL: str_imm32,
1785 bpf_jmp_op, str_symbol, NULL);
1786 state = ST_EOI;
1788 break;
1790 case 19:
1791 /* goto 'sym' */
1792 memcpy (str_symbol, token, tlen);
1793 bpf_insn = xasprintf ("%s %s", "ja", str_symbol);
1794 state = ST_EOI;
1795 break;
1797 case 0:
1798 state = ST_EOI;
1799 break;
1801 case 3:
1803 /* dst_reg arithm_op 'sym' */
1804 int load64 = 0;
1806 memcpy (str_symbol, token, tlen);
1807 memset (token, 0, tlen);
1809 if ((ttype = get_token (&str, token, &tlen)) == BPF_LL
1810 && bpf_arithm_op == BPF_MOV)
1811 load64 = 1;
1812 else if (ttype != BPF_UNKNOWN)
1813 syntax_err ("unexpected token: '%s'", token);
1815 if (load64 && *dst_reg == 'w')
1816 syntax_err ("unexpected register size: '%s'", dst_reg);
1818 if (! parse_err)
1819 bpf_insn = build_bpf_arithm_insn (dst_reg, NULL, load64,
1820 str_symbol, bpf_arithm_op);
1821 state = ST_EOI;
1823 break;
1825 break;
1827 case BPF_LE16:
1828 case BPF_LE32:
1829 case BPF_LE64:
1830 case BPF_BE16:
1831 case BPF_BE32:
1832 case BPF_BE64:
1833 bpf_endianness = ttype;
1834 state = 24; /* dst_reg = 'endianness' */
1835 break;
1837 case BPF_LOCK:
1838 state = 26;
1839 break;
1841 case BPF_IND_CALL:
1842 state = 33;
1843 break;
1845 case BPF_LD:
1846 state = 34; /* dst_reg = str_cast 'skb' */
1847 break;
1850 memset (token, 0, tlen);
1853 if (state != ST_EOI)
1854 syntax_err ("incomplete instruction");
1856 *errmsg = errbuf;
1857 return bpf_insn;
1859 #undef syntax_err
1862 void
1863 md_assemble (char *str)
1865 const CGEN_INSN *insn;
1866 char *errmsg;
1867 char *a_errmsg;
1868 CGEN_FIELDS fields;
1869 char *normal;
1871 #if CGEN_INT_INSN_P
1872 CGEN_INSN_INT buffer[CGEN_MAX_INSN_SIZE / sizeof (CGEN_INT_INSN_P)];
1873 #else
1874 unsigned char buffer[CGEN_MAX_INSN_SIZE];
1875 #endif
1877 gas_cgen_init_parse ();
1878 insn = bpf_cgen_assemble_insn (gas_cgen_cpu_desc, str, &fields,
1879 buffer, &errmsg);
1880 if (insn == NULL)
1882 normal = bpf_pseudoc_to_normal_syntax (str, &a_errmsg);
1883 if (normal)
1885 insn = bpf_cgen_assemble_insn (gas_cgen_cpu_desc, normal, &fields,
1886 buffer, &a_errmsg);
1887 xfree (normal);
1890 if (insn == NULL)
1892 as_bad ("%s", errmsg);
1893 if (a_errmsg)
1895 as_bad ("%s", a_errmsg);
1896 xfree (a_errmsg);
1898 return;
1902 gas_cgen_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (&fields),
1903 0, /* zero to ban relaxable insns. */
1904 NULL); /* NULL so results not returned here. */
1907 void
1908 md_operand (expressionS *expressionP)
1910 invalid_expression = input_line_pointer - 1;
1911 gas_cgen_md_operand (expressionP);
1915 symbolS *
1916 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1918 return NULL;
1922 /* Turn a string in input_line_pointer into a floating point constant
1923 of type TYPE, and store the appropriate bytes in *LITP. The number
1924 of LITTLENUMS emitted is stored in *SIZEP. An error message is
1925 returned, or NULL on OK. */
1927 const char *
1928 md_atof (int type, char *litP, int *sizeP)
1930 return ieee_md_atof (type, litP, sizeP, false);