(root)/
binutils-2.41/
gas/
config/
tc-bpf.c
       1  /* tc-bpf.c -- Assembler for the Linux eBPF.
       2     Copyright (C) 2019-2023 Free Software Foundation, Inc.
       3     Contributed by Oracle, Inc.
       4  
       5     This file is part of GAS, the GNU Assembler.
       6  
       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.
      11  
      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.
      16  
      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.  */
      21  
      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>
      32  
      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";
      38  
      39  static const char *invalid_expression;
      40  static char pseudoc_lex[256];
      41  static const char symbol_chars[] =
      42  "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
      43  
      44  static const char arithm_op[] = "+-/<>%&|^";
      45  
      46  static void init_pseudoc_lex (void);
      47  
      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
      57  
      58  #define ST_EOI        100
      59  #define MAX_TOKEN_SZ  100
      60  
      61  /* Like s_lcomm_internal in gas/read.c but the alignment string
      62     is allowed to be optional.  */
      63  
      64  static symbolS *
      65  pe_lcomm_internal (int needs_align, symbolS *symbolP, addressT size)
      66  {
      67    addressT align = 0;
      68  
      69    SKIP_WHITESPACE ();
      70  
      71    if (needs_align
      72        && *input_line_pointer == ',')
      73      {
      74        align = parse_align (needs_align - 1);
      75  
      76        if (align == (addressT) -1)
      77  	return NULL;
      78      }
      79    else
      80      {
      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;
      89      }
      90  
      91    bss_alloc (symbolP, size, align);
      92    return symbolP;
      93  }
      94  
      95  static void
      96  pe_lcomm (int needs_align)
      97  {
      98    s_comm_internal (needs_align * 2, pe_lcomm_internal);
      99  }
     100  
     101  /* The target specific pseudo-ops which we support.  */
     102  const pseudo_typeS md_pseudo_table[] =
     103  {
     104      { "half",      cons,              2 },
     105      { "word",      cons,              4 },
     106      { "dword",     cons,              8 },
     107      { "lcomm",	   pe_lcomm,	      1 },
     108      { NULL,        NULL,              0 }
     109  };
     110  
     111  
     112  
     113  /* ISA handling.  */
     114  static CGEN_BITSET *bpf_isa;
     115  
     116  
     117  
     118  /* Command-line options processing.  */
     119  
     120  enum options
     121  {
     122    OPTION_LITTLE_ENDIAN = OPTION_MD_BASE,
     123    OPTION_BIG_ENDIAN,
     124    OPTION_XBPF
     125  };
     126  
     127  struct option md_longopts[] =
     128  {
     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 },
     133  };
     134  
     135  size_t md_longopts_size = sizeof (md_longopts);
     136  
     137  const char * md_shortopts = "";
     138  
     139  extern int target_big_endian;
     140  
     141  /* Whether target_big_endian has been set while parsing command-line
     142     arguments.  */
     143  static int set_target_endian = 0;
     144  
     145  static int target_xbpf = 0;
     146  
     147  static int set_xbpf = 0;
     148  
     149  int
     150  md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
     151  {
     152    switch (c)
     153      {
     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;
     168      }
     169  
     170    return 1;
     171  }
     172  
     173  void
     174  md_show_usage (FILE * stream)
     175  {
     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"));
     181  }
     182  
     183  
     184  
     185  static void
     186  init_pseudoc_lex (void)
     187  {
     188    const char *p;
     189  
     190    for (p = symbol_chars; *p; ++p)
     191      pseudoc_lex[(unsigned char) *p] = LEX_IS_SYMBOL_COMPONENT;
     192  
     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;
     202  
     203    for (p = arithm_op; *p; ++p)
     204      pseudoc_lex[(unsigned char) *p] = LEX_IS_ARITHM_OP;
     205  
     206    pseudoc_lex['='] = LEX_IS_EQUAL;
     207    pseudoc_lex['!'] = LEX_IS_EXCLA;
     208  }
     209  
     210  void
     211  md_begin (void)
     212  {
     213    /* Initialize the `cgen' interface.  */
     214  
     215    /* If not specified in the command line, use the host
     216       endianness.  */
     217    if (!set_target_endian)
     218      {
     219  #ifdef WORDS_BIGENDIAN
     220        target_big_endian = 1;
     221  #else
     222        target_big_endian = 0;
     223  #endif
     224      }
     225  
     226    /* If not specified in the command line, use eBPF rather
     227       than xBPF.  */
     228    if (!set_xbpf)
     229        target_xbpf = 0;
     230  
     231    /* Set the ISA, which depends on the target endianness. */
     232    bpf_isa = cgen_bitset_create (ISA_MAX);
     233    if (target_big_endian)
     234      {
     235        if (target_xbpf)
     236  	cgen_bitset_set (bpf_isa, ISA_XBPFBE);
     237        else
     238  	cgen_bitset_set (bpf_isa, ISA_EBPFBE);
     239      }
     240    else
     241      {
     242        if (target_xbpf)
     243  	cgen_bitset_set (bpf_isa, ISA_XBPFLE);
     244        else
     245  	cgen_bitset_set (bpf_isa, ISA_EBPFLE);
     246      }
     247  
     248    /* Ensure that lines can begin with '*' in BPF store pseudoc instruction.  */
     249    lex_type['*'] |= LEX_BEGIN_NAME;
     250  
     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);
     261  
     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);
     264  
     265    /* Set the machine type. */
     266    bfd_default_set_arch_mach (stdoutput, bfd_arch_bpf, bfd_mach_bpf);
     267    init_pseudoc_lex();
     268  }
     269  
     270  valueT
     271  md_section_align (segT segment, valueT size)
     272  {
     273    int align = bfd_section_alignment (segment);
     274  
     275    return ((size + (1 << align) - 1) & -(1 << align));
     276  }
     277  
     278  
     279  /* Functions concerning relocs.  */
     280  
     281  /* The location from which a PC relative jump should be calculated,
     282     given a PC relative reloc.  */
     283  
     284  long
     285  md_pcrel_from_section (fixS *fixP, segT sec)
     286  {
     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)))
     292      {
     293          /* The symbol is undefined (or is defined but not in this section).
     294           Let the linker figure it out.  */
     295        return 0;
     296      }
     297  
     298    return fixP->fx_where + fixP->fx_frag->fr_address;
     299  }
     300  
     301  /* Write a value out to the object file, using the appropriate endianness.  */
     302  
     303  void
     304  md_number_to_chars (char * buf, valueT val, int n)
     305  {
     306    if (target_big_endian)
     307      number_to_chars_bigendian (buf, val, n);
     308    else
     309      number_to_chars_littleendian (buf, val, n);
     310  }
     311  
     312  arelent *
     313  tc_gen_reloc (asection *sec, fixS *fix)
     314  {
     315    return gas_cgen_tc_gen_reloc (sec, fix);
     316  }
     317  
     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.  */
     322  
     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)
     327  {
     328    switch (operand->type)
     329      {
     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;
     337      }
     338    return BFD_RELOC_NONE;
     339  }
     340  
     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.
     343  
     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.  */
     347  
     348  void
     349  md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
     350  		 segT sec ATTRIBUTE_UNUSED,
     351  		 fragS *fragP ATTRIBUTE_UNUSED)
     352  {
     353    as_fatal (_("convert_frag called"));
     354  }
     355  
     356  int
     357  md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
     358                                 segT segment ATTRIBUTE_UNUSED)
     359  {
     360    as_fatal (_("estimate_size_before_relax called"));
     361    return 0;
     362  }
     363  
     364  
     365  void
     366  md_apply_fix (fixS *fixP, valueT *valP, segT seg)
     367  {
     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)
     371      {
     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;
     376  
     377        switch (operand->type)
     378          {
     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").
     383  
     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.
     391  
     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.
     396  
     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;
     410          }
     411      }
     412  
     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);
     416  }
     417  
     418  /*
     419    The BPF pseudo grammar:
     420  
     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
     430  		     ;
     431  
     432  	bpf_alu_insn : BPF_REG bpf_alu_operator register_or_imm32
     433  		     ;
     434  
     435  	bpf_alu32_insn : BPF_REG32 bpf_alu_operator register32_or_imm32
     436  		       ;
     437  
     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
     443  		       ;
     444  
     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
     448  			     ;
     449  
     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
     453  			     ;
     454  
     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
     457  			     ;
     458  
     459  	bpf_endianness_conv_insn : BPF_REG_N bpf_endianness_mnem BPF_REG_N
     460  				 ;
     461  
     462  	bpf_64_imm_load_insn : BPF_REG imm64 BPF_LL
     463  			     ;
     464  
     465  	bpf_atomic_insn : BPF_LOCK bpf_size_cast_32_64 register_and_offset BPF_ADD BPF_REG
     466  
     467  	register_and_offset : BPF_CHR_OPEN_BR BPF_REG offset BPF_CHR_CLSE_BR
     468  			    ;
     469  
     470  	register32_and_offset : BPF_CHR_OPEN_BR BPF_REG32 offset BPF_CHR_CLSE_BR
     471  			      ;
     472  
     473  	bpf_size_cast : CHR_START BPF_CHR_OPEN_BR bpf_size CHR_START BPF_CHR_CLSE_BR
     474  		      ;
     475  
     476  	bpf_size_cast_32_64 : CHR_START BPF_CHR_OPEN_BR bpf_size_cast_32_64 CHR_STAR BPF_CHR_CLSE_BR
     477  			    ;
     478  
     479  	bpf_size_32_64 : BPF_CAST_U32
     480  		       | BPF_CAST_U64
     481  		       ;
     482  
     483  	bpf_size  : BPF_CAST_U8
     484  		  | BPF_CAST_U16
     485  		  | BPF_CAST_U32
     486  		  | BPF_CAST_U64
     487  		  ;
     488  
     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
     499  			  ;
     500  
     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
     514  			 ;
     515  
     516  	bpf_endianness_mnem : BPF_LE16
     517  			    | BPF_LE32
     518  			    | BPF_LE64
     519  			    | BPF_BE16
     520  			    | BPF_BE32
     521  			    | BPF_BE64
     522  			    ;
     523  
     524  	offset : BPF_EXPR
     525  	       | BPF_SYMBOL
     526  	       ;
     527  
     528  	register_or_imm32 : BPF_REG
     529  			  | expression
     530  			  ;
     531  
     532  	register32_or_imm32 : BPF_REG32
     533  			    | expression
     534  			    ;
     535  
     536  	imm32 : BPF_EXPR
     537  	      | BPF_SYMBOL
     538  	      ;
     539  
     540  	imm64 : BPF_EXPR
     541  	      | BPF_SYMBOL
     542  	      ;
     543  
     544  	register_or_expression : BPF_EXPR
     545  			       | BPF_REG
     546  			       ;
     547  
     548  	BPF_EXPR : GAS_EXPR
     549  
     550  */
     551  
     552  enum bpf_token_type
     553    {
     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,
     568  
     569      BPF_REG,
     570  
     571      BPF_IF,
     572      BPF_GOTO,
     573  
     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,
     586  
     587      BPF_SYMBOL,
     588      BPF_CHR_CLSE_BR,
     589      BPF_CHR_OPEN_BR,
     590  
     591      /* Keep grouped to quickly access.  */
     592      BPF_CAST_U8,
     593      BPF_CAST_U16,
     594      BPF_CAST_U32,
     595      BPF_CAST_U64,
     596  
     597      /* Keep grouped to quickly access.  */
     598      BPF_LE16,
     599      BPF_LE32,
     600      BPF_LE64,
     601      BPF_BE16,
     602      BPF_BE32,
     603      BPF_BE64,
     604  
     605      BPF_LOCK,
     606  
     607      BPF_IND_CALL,
     608      BPF_LD,
     609      BPF_LL,
     610      BPF_EXPR,
     611      BPF_UNKNOWN,
     612    };
     613  
     614  static int
     615  valid_expr (const char *e, const char **end_expr)
     616  {
     617    invalid_expression = NULL;
     618    char *hold = input_line_pointer;
     619    expressionS exp;
     620  
     621    input_line_pointer = (char *) e;
     622    deferred_expression  (&exp);
     623    *end_expr = input_line_pointer;
     624    input_line_pointer = hold;
     625  
     626    return invalid_expression == NULL;
     627  }
     628  
     629  static char *
     630  build_bpf_non_generic_load (char *src, enum bpf_token_type cast,
     631  			    const char *imm32)
     632  {
     633    char *bpf_insn;
     634    static const char *cast_rw[] = {"b", "h", "w", "dw"};
     635  
     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;
     645  }
     646  
     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)
     652  {
     653    char *bpf_insn;
     654    static const char *cast_rw[] = {"w", "dw"};
     655    static const char *mnem[] = {"xadd"};
     656  
     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;
     662  }
     663  
     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)
     668  {
     669    char *bpf_insn;
     670    static const char *mnem[] =
     671      {
     672        "jeq", "jgt", "jge", "jlt",
     673        "jle", "jset", "jne", "jsgt",
     674        "jsge", "jslt", "jsle"
     675      };
     676  
     677    const char *in32 = (*dst == 'w' ? "32" : "");
     678  
     679    *dst = 'r';
     680    if (src)
     681      *src = 'r';
     682  
     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;
     689  }
     690  
     691  static char *
     692  build_bpf_arithm_insn (char *dst, char *src,
     693  		       int load64, const char *imm32,
     694  		       enum bpf_token_type type)
     695  {
     696    char *bpf_insn;
     697    static const char *mnem[] =
     698      {
     699        "add", "sub", "mul", "div",
     700        "or", "and", "lsh", "rsh",
     701        "mod", "xor", "mov", "arsh",
     702        "neg",
     703      };
     704    const char *in32 = (*dst == 'w' ? "32" : "");
     705  
     706    *dst = 'r';
     707    if (src)
     708      *src = 'r';
     709  
     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;
     720  }
     721  
     722  static char *
     723  build_bpf_endianness (char *dst, enum bpf_token_type endianness)
     724  {
     725    char *bpf_insn;
     726    static const char *size[] = {"16", "32", "64"};
     727    int be = 1;
     728  
     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);
     735  
     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;
     739  }
     740  
     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)
     745  {
     746    char *bpf_insn;
     747    static const char *cast_rw[] = {"b", "h", "w", "dw"};
     748  
     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;
     761  }
     762  
     763  static int
     764  look_for_reserved_word (const char *token, enum bpf_token_type *type)
     765  {
     766    int i;
     767    static struct
     768    {
     769      const char *name;
     770      enum bpf_token_type type;
     771    } reserved_words[] =
     772      {
     773        {
     774  	.name = "if",
     775  	.type = BPF_IF
     776        },
     777        {
     778  	.name = "goto",
     779  	.type = BPF_GOTO
     780        },
     781        {
     782  	.name = "le16",
     783  	.type = BPF_LE16
     784        },
     785        {
     786  	.name = "le32",
     787  	.type = BPF_LE32
     788        },
     789        {
     790  	.name = "le64",
     791  	.type = BPF_LE64
     792        },
     793        {
     794  	.name = "be16",
     795  	.type = BPF_BE16
     796        },
     797        {
     798  	.name = "be32",
     799  	.type = BPF_BE32
     800        },
     801        {
     802  	.name = "be64",
     803  	.type = BPF_BE64
     804  	},
     805        {
     806  	.name = "lock",
     807  	.type = BPF_LOCK
     808        },
     809        {
     810  	.name = "callx",
     811  	.type = BPF_IND_CALL
     812        },
     813        {
     814  	.name = "skb",
     815  	.type = BPF_LD
     816        },
     817        {
     818  	.name = "ll",
     819  	.type = BPF_LL
     820        },
     821        {
     822  	.name = NULL,
     823        }
     824      };
     825  
     826    for (i = 0; reserved_words[i].name; ++i)
     827      if (*reserved_words[i].name == *token
     828  	&& !strcmp (reserved_words[i].name, token))
     829        {
     830  	*type = reserved_words[i].type;
     831  	return 1;
     832        }
     833  
     834    return 0;
     835  }
     836  
     837  static int
     838  is_register (const char *token, int len)
     839  {
     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;
     844  
     845    return 0;
     846  }
     847  
     848  static enum bpf_token_type
     849  is_cast (const char *token)
     850  {
     851    static const char *cast_rw[] = {"u8", "u16", "u32", "u64"};
     852    unsigned int i;
     853  
     854    for (i = 0; i < ARRAY_SIZE (cast_rw); ++i)
     855      if (!strcmp (token, cast_rw[i]))
     856        return BPF_CAST_U8 + i;
     857  
     858    return BPF_UNKNOWN;
     859  }
     860  
     861  static enum bpf_token_type
     862  get_token (const char **insn, char *token, size_t *tlen)
     863  {
     864  #define GET()					\
     865    (*str == '\0'					\
     866     ? EOF					\
     867     : *(unsigned char *)(str++))
     868  
     869  #define UNGET() (--str)
     870  
     871  #define START_EXPR()			       \
     872    do					       \
     873      {					       \
     874        if (expr == NULL)			       \
     875  	expr = str - 1;			       \
     876      } while (0)
     877  
     878  #define SCANNER_SKIP_WHITESPACE()		\
     879    do						\
     880      {						\
     881        do					\
     882  	ch = GET ();				\
     883        while (ch != EOF				\
     884  	     && ((ch) == ' ' || (ch) == '\t'));	\
     885        if (ch != EOF)				\
     886  	UNGET ();				\
     887      } while (0)
     888  
     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;
     897  
     898    while (1)
     899      {
     900        ch = GET ();
     901  
     902        if (ch == EOF || len > MAX_TOKEN_SZ)
     903  	break;
     904  
     905        switch (pseudoc_lex[(unsigned char) ch])
     906  	{
     907  	case LEX_IS_WHITESPACE:
     908  	  SCANNER_SKIP_WHITESPACE ();
     909  	  return_token = 1;
     910  
     911  	  switch (state)
     912  	    {
     913  	    case 12: /* >' ' */
     914  	      ttype = BPF_JGT;
     915  	      break;
     916  
     917  	    case 17: /* ==' ' */
     918  	      ttype = BPF_JEQ;
     919  	      break;
     920  
     921  	    case 18: /* <' ' */
     922  	      ttype = BPF_JLT;
     923  	      break;
     924  
     925  	    case 20: /* &' ' */
     926  	      ttype = BPF_JSET;
     927  	      break;
     928  
     929  	    case 22:  /* s<' '*/
     930  	      ttype = BPF_JSLT;
     931  	      break;
     932  
     933  	    case 14: /* s> ' ' */
     934  	      ttype = BPF_JSGT;
     935  	      break;
     936  
     937  	    case 16: /* =' ' */
     938  	      ttype = BPF_MOV;
     939  	      break;
     940  
     941  	    default:
     942  	      return_token = 0;
     943  	    }
     944  	  break;
     945  
     946  	case LEX_IS_EXCLA:
     947  	  token[len++] = ch;
     948  	  state = 21;
     949  	  break;
     950  
     951  	case LEX_IS_ARITHM_OP:
     952  	  if (state == 16)
     953  	    {
     954  	      /* ='-' is handle as '=' */
     955  	      UNGET ();
     956  	      ttype = BPF_MOV;
     957  	      return_token = 1;
     958  	      break;
     959  	    }
     960  
     961  	  START_EXPR();
     962  	  token[len++] = ch;
     963  	  switch (ch)
     964  	    {
     965  #define BPF_ARITHM_OP(op, type)			\
     966  	      case (op):			\
     967  		state = 6;			\
     968  		ttype = (type);			\
     969  		break;
     970  
     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);
     978  
     979  	    case '&':
     980  	      state = 20; /* '&' */
     981  	      break;
     982  
     983  	    case '<':
     984  	      switch (state)
     985  		{
     986  		case 0:
     987  		  state = 18; /* '<' */
     988  		  break;
     989  
     990  		case 18:
     991  		  state = 19; /* <'<' */
     992  		  break;
     993  
     994  		case 8:
     995  		  state = 22; /* s'<' */
     996  		  break;
     997  		}
     998  	      break;
     999  
    1000  	    case '>':
    1001  	      switch (state)
    1002  		{
    1003  		case 0:
    1004  		  state = 12; /* '>' */
    1005  		  break;
    1006  
    1007  		case 12:
    1008  		  state = 13; /* >'>' */
    1009  		  break;
    1010  
    1011  		case 8:
    1012  		  state = 14; /* s'>' */
    1013  		  break;
    1014  
    1015  		case 14:
    1016  		  state = 15; /* s>'>' */
    1017  		  break;
    1018  		}
    1019  	      break;
    1020  	    }
    1021  	  break;
    1022  
    1023  	case LEX_IS_STAR:
    1024  	  switch (state)
    1025  	    {
    1026  	    case 0:
    1027  	      token[len++] = ch;
    1028  	      START_EXPR ();
    1029  	      state = 2; /* '*', It could be the fist cast char.  */
    1030  	      break;
    1031  
    1032  	    case 16: /* ='*' Not valid token.  */
    1033  	      ttype = BPF_MOV;
    1034  	      return_token = 1;
    1035  	      UNGET ();
    1036  	      break;
    1037  
    1038  	    case 4: /* *(uXX'*' */
    1039  	      token[len++] = ch;
    1040  	      state = 5;
    1041  	      break;
    1042  	    }
    1043  	  break;
    1044  
    1045  	case LEX_IS_OPEN_BR:
    1046  	  START_EXPR ();
    1047  	  token[len++] = ch;
    1048  	  return_token = 1;
    1049  
    1050  	  switch (state)
    1051  	    {
    1052  	    case 2:
    1053  	      state = 3; /* *'(' second char of a cast or expr.  */
    1054  	      return_token = 0;
    1055  	      break;
    1056  
    1057  	    case 6:
    1058  	      if (valid_expr (expr, &end_expr))
    1059  		{
    1060  		  len = end_expr - expr;
    1061  		  memcpy (token, expr, len);
    1062  		  ttype = BPF_EXPR;
    1063  		  str = end_expr;
    1064  		}
    1065  	      else
    1066  		{
    1067  		  len = 0;
    1068  		  while (*invalid_expression)
    1069  		    token[len++] = *invalid_expression++;
    1070  
    1071  		  token[len] = 0;
    1072  		  ttype = BPF_UNKNOWN;
    1073  		}
    1074  	      break;
    1075  
    1076  	    default:
    1077  	      ttype = BPF_CHR_OPEN_BR;
    1078  	      SCANNER_SKIP_WHITESPACE ();
    1079  	      ch2 = GET ();
    1080  
    1081  	      if ((isdigit (ch2) || ch2 == '(')
    1082  		  && valid_expr (expr, &end_expr))
    1083  		{
    1084  		  len = end_expr - expr;
    1085  		  memcpy (token, expr, len);
    1086  		  ttype = BPF_EXPR;
    1087  		  str = end_expr;
    1088  		}
    1089  	      else
    1090  		UNGET ();
    1091  	    }
    1092  	  break;
    1093  
    1094  	case LEX_IS_CLSE_BR:
    1095  	  token[len++] = ch;
    1096  
    1097  	  if (state == 0)
    1098  	    {
    1099  	      ttype = BPF_CHR_CLSE_BR;
    1100  	      return_token = 1;
    1101  	    }
    1102  	  else if (state == 5) /* *(uXX*')'  */
    1103  	    return_token = 1;
    1104  	  break;
    1105  
    1106  	case LEX_IS_EQUAL:
    1107  	  token[len++] = ch;
    1108  	  return_token = 1;
    1109  
    1110  	  switch (state)
    1111  	    {
    1112  	    case 0:
    1113  	      state = 16; /* '=' */
    1114  	      return_token = 0;
    1115  	      break;
    1116  
    1117  	    case 16:
    1118  	      state = 17; /* ='=' */
    1119  	      return_token = 0;
    1120  	      break;
    1121  
    1122  	    case 2: /* *'=' */
    1123  	      ttype = BPF_MUL;
    1124  	      break;
    1125  
    1126  	    case 10: /* s>>'=' */
    1127  	      ttype = BPF_ARSH;
    1128  	      break;
    1129  
    1130  	    case 12: /* >'=' */
    1131  	      ttype = BPF_JGE;
    1132  	      break;
    1133  
    1134  	    case 13: /* >>'=' */
    1135  	      ttype = BPF_RSH;
    1136  	      break;
    1137  
    1138  	    case 14: /* s>'=' */
    1139  	      ttype = BPF_JSGE;
    1140  	      break;
    1141  
    1142  	    case 15: /* s>>'=' */
    1143  	      ttype = BPF_ARSH;
    1144  	      break;
    1145  
    1146  	    case 18: /* <'=' */
    1147  	      ttype = BPF_JLE;
    1148  	      break;
    1149  
    1150  	    case 19: /* <<'=' */
    1151  	      ttype = BPF_LSH;
    1152  	      break;
    1153  
    1154  	    case 20: /* &'=' */
    1155  	      ttype = BPF_AND;
    1156  	      break;
    1157  
    1158  	    case 21: /* !'=' */
    1159  	      ttype = BPF_JNE;
    1160  	      break;
    1161  
    1162  	    case 22: /* s<'=' */
    1163  	      ttype = BPF_JSLE;
    1164  	      break;
    1165  	    }
    1166  	  break;
    1167  
    1168  	case LEX_IS_SYMBOL_COMPONENT:
    1169  	  return_token = 1;
    1170  
    1171  	  switch (state)
    1172  	    {
    1173  	    case 17: /* =='sym' */
    1174  	      ttype = BPF_JEQ;
    1175  	      break;
    1176  
    1177  	    case 12: /* >'sym' */
    1178  	      ttype = BPF_JGT;
    1179  	      break;
    1180  
    1181  	    case 18: /* <'sym' */
    1182  	      ttype = BPF_JLT;
    1183  	      break;
    1184  
    1185  	    case 20: /* &'sym' */
    1186  	      ttype = BPF_JSET;
    1187  	      break;
    1188  
    1189  	    case 14: /*s>'sym' */
    1190  	      ttype = BPF_JSGT;
    1191  	      break;
    1192  
    1193  	    case 22:  /* s<'sym' */
    1194  	      ttype = BPF_JSLT;
    1195  	      break;
    1196  
    1197  	    case 16: /* ='sym' */
    1198  	      ttype = BPF_MOV;
    1199  	      break;
    1200  
    1201  	    default:
    1202  	      return_token = 0;
    1203  	    }
    1204  
    1205  	  if (return_token)
    1206  	    {
    1207  	      UNGET ();
    1208  	      break;
    1209  	    }
    1210  
    1211  	  START_EXPR ();
    1212  	  token[len++] = ch;
    1213  
    1214  	  while ((ch2 = GET ()) != EOF)
    1215  	    {
    1216  	      int type;
    1217  
    1218  	      type = pseudoc_lex[(unsigned char) ch2];
    1219  	      if (type != LEX_IS_SYMBOL_COMPONENT)
    1220  		break;
    1221  	      token[len++] = ch2;
    1222  	    }
    1223  
    1224  	  if (ch2 != EOF)
    1225  	    UNGET ();
    1226  
    1227  	  if (state == 0)
    1228  	    {
    1229  	      if (len == 1 && ch == 's')
    1230  		state = 8; /* signed instructions: 's' */
    1231  	      else
    1232  		{
    1233  		  ttype = BPF_SYMBOL;
    1234  		  if (is_register (token, len))
    1235  		    ttype = BPF_REG;
    1236  		  else if (look_for_reserved_word (token, &ttype))
    1237  		    ;
    1238  		  else if ((pseudoc_lex[(unsigned char) *token] == LEX_IS_ARITHM_OP
    1239  			    || *token == '(' || isdigit(*token))
    1240  			   && valid_expr (expr, &end_expr))
    1241  		    {
    1242  		      len = end_expr - expr;
    1243  		      token[len] = '\0';
    1244  		      ttype = BPF_EXPR;
    1245  		      str = end_expr;
    1246  		    }
    1247  
    1248  		  return_token = 1;
    1249  		}
    1250  	    }
    1251  	  else if (state == 3) /* *('sym' */
    1252  	    {
    1253  	      if ((ttype = is_cast (&token[2])) != BPF_UNKNOWN)
    1254  		state = 4; /* *('uXX' */
    1255  	      else
    1256  		{
    1257  		  ttype = BPF_EXPR;
    1258  		  return_token = 1;
    1259  		}
    1260  	    }
    1261  	  else if (state == 6)
    1262  	    {
    1263  	      if (ttype == BPF_SUB) /* neg */
    1264  		{
    1265  		  if (is_register (&token[1], len - 1))
    1266  		    ttype =  BPF_NEG;
    1267  		  else if (valid_expr(expr, &end_expr))
    1268  		    {
    1269  		      len = end_expr - expr;
    1270  		      memcpy(token, expr, len);
    1271  		      ttype = BPF_EXPR;
    1272  		      str = end_expr;
    1273  		    }
    1274  		  else
    1275  		    {
    1276  		      len = 0;
    1277  		      while (*invalid_expression)
    1278  			token[len++] = *invalid_expression++;
    1279  		      token[len] = 0;
    1280  		      ttype = BPF_UNKNOWN;
    1281  		    }
    1282  		}
    1283  	      else if (valid_expr (expr, &end_expr))
    1284  		{
    1285  		  len = end_expr - expr;
    1286  		  memcpy(token, expr, len);
    1287  		  ttype = BPF_EXPR;
    1288  		  str = end_expr;
    1289  		}
    1290  	      else
    1291  		ttype = BPF_UNKNOWN;
    1292  
    1293  	      return_token = 1;
    1294  	    }
    1295  	  break;
    1296  	}
    1297  
    1298        if (return_token)
    1299  	{
    1300  	  *tlen = len;
    1301  	  *insn = str;
    1302  	  break;
    1303  	}
    1304      }
    1305  
    1306    return ttype;
    1307  
    1308  #undef GET
    1309  #undef UNGET
    1310  #undef START_EXPR
    1311  #undef SCANNER_SKIP_WHITESPACE
    1312  #undef BPF_ARITHM_OP
    1313  }
    1314  
    1315  /*
    1316    The parser represent a FSM for the grammar described above. So for example
    1317    the following rule:
    1318  
    1319       ` bpf_alu_insn : BPF_REG bpf_alu_operator register_or_imm32'
    1320  
    1321    Is parser as follows:
    1322  
    1323        1. It starts in state 0.
    1324  
    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.:
    1330  
    1331            state = 6; // dst_reg = str_cast ( 'src_reg'
    1332  
    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).
    1336  
    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.
    1345  
    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.
    1351  */
    1352  
    1353  static char *
    1354  bpf_pseudoc_to_normal_syntax (const char *str, char **errmsg)
    1355  {
    1356  #define syntax_err(format, ...)						\
    1357    do									\
    1358      {									\
    1359        if (! parse_err)							\
    1360  	{								\
    1361  	  parse_err = 1;						\
    1362  	  errbuf = xasprintf (format, ##__VA_ARGS__);			\
    1363  	}								\
    1364      } while (0)
    1365  
    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;
    1383  
    1384    while (*str)
    1385      {
    1386        ttype = get_token (&str, token, &tlen);
    1387        if (ttype == BPF_UNKNOWN || state == ST_EOI)
    1388  	{
    1389  	  syntax_err ("unexpected token: '%s'", token);
    1390  	  break;
    1391  	}
    1392  
    1393        switch (ttype)
    1394  	{
    1395  	case BPF_UNKNOWN:
    1396  	case BPF_LL:
    1397  	  break;
    1398  
    1399  	case BPF_REG:
    1400  	  switch (state)
    1401  	    {
    1402  	    case 0:
    1403  	      memcpy (dst_reg, token, tlen);
    1404  	      state = 1; /* 'dst_reg' */
    1405  	      break;
    1406  
    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
    1414  		{
    1415  		  syntax_err ("different register sizes: '%s', '%s'",
    1416  			      dst_reg, src_reg);
    1417  		  break;
    1418  		}
    1419  	      state = ST_EOI;
    1420  	      break;
    1421  
    1422  	    case 5:
    1423  	      memcpy (src_reg, token, tlen);
    1424  	      state = 6; /* dst_reg = str_cast ( 'src_reg' */
    1425  	      break;
    1426  
    1427  	    case 9:
    1428  	      memcpy (dst_reg, token, tlen);
    1429  	      state = 10; /* str_cast ( 'dst_reg' */
    1430  	      break;
    1431  
    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;
    1439  
    1440  	    case 14:
    1441  	      memcpy (dst_reg, token, tlen);
    1442  	      state = 15; /* if 'dst_reg' */
    1443  	      break;
    1444  
    1445  	    case 16:
    1446  	      memcpy (src_reg, token, tlen);
    1447  	      state = 17; /* if dst_reg jmp_op 'src_reg' */
    1448  	      break;
    1449  
    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);
    1457  
    1458  	      state = ST_EOI;
    1459  	      break;
    1460  
    1461  	    case 28:
    1462  	      memcpy (dst_reg, token, tlen);
    1463  	      state = 29; /* lock str_cast ( 'dst_reg'  */
    1464  	      break;
    1465  
    1466  	    case 32:
    1467  	      {
    1468  		/* lock str_cast ( dst_reg offset ) atomic_insn 'src_reg' */
    1469  		int with_offset = *str_offset != '\0';
    1470  
    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);
    1480  	      }
    1481  
    1482  	      state = ST_EOI;
    1483  	      break;
    1484  
    1485  	    case 33:
    1486  	      /* callx 'dst_reg' */
    1487  	      bpf_insn = xasprintf ("%s %%%s", "call", token);
    1488  	      state = ST_EOI;
    1489  	      break;
    1490  
    1491  	    case 35:
    1492  	      memcpy (src_reg, token, tlen);
    1493  	      state = 36; /* dst_reg = str_cast skb [ 'src_reg' */
    1494  	      break;
    1495  	    }
    1496  	  break;
    1497  
    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)
    1512  	    {
    1513  	    case 1:
    1514  	      state = 3;  /* dst_reg 'arith_op' */
    1515  	      bpf_arithm_op = ttype;
    1516  	      break;
    1517  
    1518  	    case 3:
    1519  	      if (ttype == BPF_NEG)
    1520  		{
    1521  		  /* reg = -reg */
    1522  		  bpf_arithm_op = ttype;
    1523  		  memcpy (src_reg, token + 1, tlen - 1);
    1524  		  if (strcmp (dst_reg, src_reg))
    1525  		    {
    1526  		      syntax_err ("found: '%s', expected: -%s", token, dst_reg);
    1527  		      break;
    1528  		    }
    1529  
    1530  		  bpf_insn = build_bpf_arithm_insn (dst_reg, src_reg, 0,
    1531  						    NULL, bpf_arithm_op);
    1532  		  state = ST_EOI;
    1533  		}
    1534  	      break;
    1535  
    1536  	    case 23:
    1537  	      memcpy (src_reg, token, tlen);
    1538  	      state = 11; /* str_cast ( dst_reg offset ) '=' */
    1539  	      break;
    1540  
    1541  	    case 12:
    1542  	      if (ttype == BPF_MOV)
    1543  		state = 13; /* str_cast ( dst_reg offset ) '=' */
    1544  	      break;
    1545  
    1546  	    case 31:
    1547  	      bpf_atomic_insn = ttype;
    1548  	      state = 32; /* lock str_cast ( dst_reg offset ) 'atomic_insn' */
    1549  	      break;
    1550  
    1551  	    default:
    1552  	      syntax_err ("unexpected '%s'", token);
    1553  	      state = ST_EOI;
    1554  	    }
    1555  	  break;
    1556  
    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)
    1563  	    {
    1564  	    case 3:
    1565  	      state = 4; /* dst_reg = 'str_cast' */
    1566  	      break;
    1567  
    1568  	    case 0:
    1569  	      state = 8;  /* 'str_cast' */
    1570  	      break;
    1571  
    1572  	    case 26:
    1573  	      state = 27; /* lock 'str_cast' */
    1574  	      break;
    1575  	    }
    1576  	  break;
    1577  
    1578  	case BPF_CHR_OPEN_BR:
    1579  	  switch (state)
    1580  	    {
    1581  	    case 4:
    1582  	      state = 5; /* dst_reg = str_cast '(' */
    1583  	      break;
    1584  
    1585  	    case 8:
    1586  	      state = 9; /* str_cast '(' */
    1587  	      break;
    1588  
    1589  	    case 27:
    1590  	      state = 28; /* lock str_cast '(' */
    1591  	      break;
    1592  
    1593  	    case 34:
    1594  	      state = 35; /* dst_reg = str_cast skb '[' */
    1595  	      break;
    1596  	    }
    1597  	  break;
    1598  
    1599  	case BPF_CHR_CLSE_BR:
    1600  	  switch (state)
    1601  	    {
    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;
    1608  
    1609  	    case 11:
    1610  	      state = 12; /* str_cast ( dst_reg imm32 ')' */
    1611  	      break;
    1612  
    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;
    1619  
    1620  	    case 22:
    1621  	      state = 23; /* str_cast ( dst_reg offset ')' */
    1622  	      break;
    1623  
    1624  	    case 30:
    1625  	      state = 31; /* lock str_cast ( dst_reg offset ')' */
    1626  	      break;
    1627  
    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);
    1635  
    1636  	      state = ST_EOI;
    1637  	      break;
    1638  	    }
    1639  	  break;
    1640  
    1641  	case BPF_EXPR:
    1642  	  switch (state)
    1643  	    {
    1644  	    case 3:
    1645  	      {
    1646  		/* dst_reg bpf_arithm_op 'imm32' */
    1647  		int load64 = 0;
    1648  
    1649  		memcpy (str_imm32, token, tlen);
    1650  		memset (token, 0, tlen);
    1651  
    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);
    1657  
    1658  		if (load64 && *dst_reg == 'w')
    1659  		  syntax_err ("unexpected register size: '%s'", dst_reg);
    1660  
    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;
    1665  	      }
    1666  	      break;
    1667  
    1668  	    case 18:
    1669  	      {
    1670  		/* if dst_reg jmp_op src_reg goto 'offset' */
    1671  		int with_src = *src_reg != '\0';
    1672  
    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;
    1682  	      }
    1683  	      break;
    1684  
    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;
    1691  
    1692  	    case 6:
    1693  	      memcpy (str_offset, token, tlen);
    1694  	      state = 21; /* dst_reg = str_cast ( src_reg  'offset' */
    1695  	      break;
    1696  
    1697  	    case 10:
    1698  	      memcpy (str_offset, token, tlen);
    1699  	      state = 22; /* str_cast ( dst_reg 'offset' */
    1700  	      break;
    1701  
    1702  	    case 16:
    1703  	      memcpy (str_imm32, token, tlen);
    1704  	      state = 25; /* if dst_reg jmp_op 'imm32' */
    1705  	      break;
    1706  
    1707  	    case 29:
    1708  	      memcpy (str_offset, token, tlen);
    1709  	      state = 30; /* lock str_cast ( dst_reg 'offset' */
    1710  	      break;
    1711  
    1712  	    case 34:
    1713  	      /* dst_reg = str_cast skb 'imm32' */
    1714  	      if (*dst_reg != 'w' && !strcmp ("r0", dst_reg))
    1715  		{
    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);
    1719  		}
    1720  	      else
    1721  		syntax_err ("invalid register operand: '%s'", dst_reg);
    1722  
    1723  	      state = ST_EOI;
    1724  	      break;
    1725  
    1726  	    case 36:
    1727  	      memcpy (str_imm32, token, tlen);
    1728  	      state = 37; /* dst_reg = str_cast skb [ src_reg 'imm32' */
    1729  	      break;
    1730  	    }
    1731  	  break;
    1732  
    1733  	case BPF_IF:
    1734  	  if (state == 0)
    1735  	    state = 14;
    1736  	  break;
    1737  
    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)
    1750  	    {
    1751  	      bpf_jmp_op = ttype;
    1752  	      state = 16; /* if dst_reg 'jmp_op' */
    1753  	    }
    1754  	  break;
    1755  
    1756  	case BPF_GOTO:
    1757  	  switch (state)
    1758  	    {
    1759  	    case 17:
    1760  	    case 25:
    1761  	      state = 18; /* if dst_reg jmp_op src_reg|imm32 'goto' */
    1762  	      break;
    1763  
    1764  	    case 0:
    1765  	      state = 19;
    1766  	      break;
    1767  	    }
    1768  	  break;
    1769  
    1770  	case BPF_SYMBOL:
    1771  	  switch (state)
    1772  	    {
    1773  	    case 18:
    1774  	      {
    1775  		/* if dst_reg jmp_op src_reg goto 'sym' */
    1776  		int with_src = *src_reg != '\0';
    1777  
    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;
    1787  	      }
    1788  	      break;
    1789  
    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;
    1796  
    1797  	    case 0:
    1798  	      state = ST_EOI;
    1799  	      break;
    1800  
    1801  	    case 3:
    1802  	      {
    1803  		/* dst_reg arithm_op 'sym' */
    1804  		int load64 = 0;
    1805  		
    1806  		memcpy (str_symbol, token, tlen);
    1807  		memset (token, 0, tlen);
    1808  
    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);
    1814  
    1815  		if (load64 && *dst_reg == 'w')
    1816  		  syntax_err ("unexpected register size: '%s'", dst_reg);
    1817  
    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;
    1822  	      }
    1823  	      break;
    1824  	    }
    1825  	  break;
    1826  
    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;
    1836  
    1837  	case BPF_LOCK:
    1838  	  state = 26;
    1839  	  break;
    1840  
    1841  	case BPF_IND_CALL:
    1842  	  state = 33;
    1843  	  break;
    1844  
    1845  	case BPF_LD:
    1846  	  state = 34; /* dst_reg = str_cast 'skb' */
    1847  	  break;
    1848  	}
    1849  
    1850        memset (token, 0, tlen);
    1851      }
    1852  
    1853    if (state != ST_EOI)
    1854      syntax_err ("incomplete instruction");
    1855  
    1856    *errmsg = errbuf;
    1857    return bpf_insn;
    1858  
    1859  #undef syntax_err
    1860  }
    1861  
    1862  void
    1863  md_assemble (char *str)
    1864  {
    1865    const CGEN_INSN *insn;
    1866    char *errmsg;
    1867    char *a_errmsg;
    1868    CGEN_FIELDS fields;
    1869    char *normal;
    1870  
    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
    1876  
    1877    gas_cgen_init_parse ();
    1878    insn = bpf_cgen_assemble_insn (gas_cgen_cpu_desc, str, &fields,
    1879                                    buffer, &errmsg);
    1880    if (insn == NULL)
    1881      {
    1882        normal = bpf_pseudoc_to_normal_syntax (str, &a_errmsg);
    1883        if (normal)
    1884  	{
    1885  	  insn = bpf_cgen_assemble_insn (gas_cgen_cpu_desc, normal, &fields,
    1886  					 buffer, &a_errmsg);
    1887  	  xfree (normal);
    1888  	}
    1889  
    1890        if (insn == NULL)
    1891  	{
    1892  	  as_bad ("%s", errmsg);
    1893  	  if (a_errmsg)
    1894  	    {
    1895  	      as_bad ("%s", a_errmsg);
    1896  	      xfree (a_errmsg);
    1897  	    }
    1898  	  return;
    1899  	}
    1900      }
    1901  
    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.  */
    1905  }
    1906  
    1907  void
    1908  md_operand (expressionS *expressionP)
    1909  {
    1910    invalid_expression = input_line_pointer - 1;
    1911    gas_cgen_md_operand (expressionP);
    1912  }
    1913  
    1914  
    1915  symbolS *
    1916  md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
    1917  {
    1918    return NULL;
    1919  }
    1920  
    1921  
    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.  */
    1926  
    1927  const char *
    1928  md_atof (int type, char *litP, int *sizeP)
    1929  {
    1930    return ieee_md_atof (type, litP, sizeP, false);
    1931  }