github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/ebpf/asm.go (about)

     1  package ebpf
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/alecthomas/participle/v2"
    10  	"github.com/alecthomas/participle/v2/lexer/stateful"
    11  )
    12  
    13  var (
    14  	ebpfLexer = stateful.MustSimple([]stateful.Rule{
    15  		{Name: "Comment", Pattern: `(?:#)[^\n]*`, Action: nil},
    16  		{Name: "Register32", Pattern: `w[0-9]{1,2}`, Action: nil},
    17  		{Name: "Register64", Pattern: `r[0-9]{1,2}`, Action: nil},
    18  		// https://golang.org/pkg/strconv/#ParseInt
    19  		{Name: "Number", Pattern: `(0x[0-9a-fA-F]+)|(0b[01]+)|(0o?[0-7]+)|\d+`, Action: nil},
    20  		{Name: "Nop", Pattern: `nop`, Action: nil},
    21  		{Name: "Ident", Pattern: `[a-zA-Z0-9_]+`, Action: nil},
    22  		{Name: "LabelEnd", Pattern: `:`, Action: nil},
    23  		{Name: "Punct", Pattern: `[-[!@#$%^&*()+_={}\\\|;'"<,>.?/]|]`, Action: nil},
    24  		{Name: "Whitespace", Pattern: `[ \t\r]+`, Action: nil},
    25  		{Name: "Newline", Pattern: `\n`, Action: nil},
    26  	})
    27  	ebpfParser = participle.MustBuild(&asmFile{},
    28  		participle.Lexer(ebpfLexer),
    29  		participle.Elide("Comment", "Whitespace", "Nop"),
    30  		participle.UseLookahead(100),
    31  	)
    32  )
    33  
    34  // TODO make a AssemblyToProgram function, since we can technically reconstruct the whole ELF(Program, Maps, license)
    35  // from the assembly
    36  
    37  // AssemblyToInstructions takes in a reader and the name of the file which is used in error messages. This function
    38  // attempts to parse the contents of the file as a super set of clang/LLVM eBPF assembly code. Meaning that
    39  // we support the output of clang with the -S option and some additional features since clang/LLVM doesn't
    40  // generate or assemble all instructions in the eBPF specification.
    41  func AssemblyToInstructions(filename string, reader io.Reader) ([]Instruction, error) {
    42  	ast := &asmFile{}
    43  	err := ebpfParser.Parse(filename, reader, ast)
    44  	if err != nil {
    45  		return nil, fmt.Errorf("error while parsing: %w", err)
    46  	}
    47  
    48  	var instructions []Instruction
    49  
    50  	ctx := assembleContext{
    51  		Labels: make(map[string]int),
    52  		Maps:   make(map[string]struct{}),
    53  	}
    54  
    55  	instCnt := 0
    56  	for _, entry := range ast.Entries {
    57  		if entry.Label != "" {
    58  			if _, found := ctx.Labels[entry.Label]; found {
    59  				return nil, fmt.Errorf("duplicate label '%s' found, labels must be unique", entry.Label)
    60  			}
    61  
    62  			ctx.Labels[entry.Label] = instCnt
    63  			continue
    64  		}
    65  
    66  		if entry.Instruction != nil {
    67  			// Since the LoadConstant64bit is the only instruction to produce 2 instructions, we have to account for
    68  			// that when counting
    69  			if entry.Instruction.LoadConstant64bit != nil {
    70  				instCnt++
    71  			}
    72  
    73  			instCnt++
    74  			continue
    75  		}
    76  
    77  		if entry.Directive != nil {
    78  			if typ := entry.Directive.Type; typ != nil {
    79  				// object type declarations are maps(as far as I can tell, we may need to check size,
    80  				// and section as well in future)
    81  				if typ.Type == "object" {
    82  					if _, found := ctx.Maps[typ.Name]; found {
    83  						return nil, fmt.Errorf("duplicate map definition '%s'", typ.Name)
    84  					}
    85  
    86  					ctx.Maps[typ.Name] = struct{}{}
    87  				}
    88  			}
    89  
    90  			continue
    91  		}
    92  	}
    93  
    94  	instCnt = 0
    95  	for _, entry := range ast.Entries {
    96  		if entry.Instruction != nil {
    97  			insts, err := entry.Instruction.ToInst(instCnt, &ctx)
    98  			if err != nil {
    99  				return nil, err
   100  			}
   101  
   102  			instructions = append(instructions, insts...)
   103  			instCnt++
   104  
   105  			// Since the LoadConstant64bit is the only instruction to produce 2 instructions, we have to account for
   106  			// that when counting
   107  			if entry.Instruction.LoadConstant64bit != nil {
   108  				instCnt++
   109  			}
   110  		}
   111  	}
   112  
   113  	return instructions, nil
   114  }
   115  
   116  type assembleContext struct {
   117  	Labels map[string]int
   118  	Maps   map[string]struct{} // TODO add actual parsed map definition in the future?
   119  }
   120  
   121  type asmFile struct {
   122  	Entries []*entry `parser:"@@*"`
   123  }
   124  
   125  type entry struct {
   126  	Label       string       `parser:"( @(Ident|Number|Punct)+ LabelEnd"`
   127  	Directive   *directive   `parser:"| @@"`
   128  	Instruction *instruction `parser:"| @@ )? Newline*"`
   129  }
   130  
   131  func (r *Register) Capture(values []string) error {
   132  	// Join all values, and strip the leading r
   133  	i, err := strconv.Atoi(strings.Join(values, "")[1:])
   134  	if err != nil {
   135  		return err
   136  	}
   137  
   138  	*r = Register(i)
   139  
   140  	return nil
   141  }
   142  
   143  func (s *Size) Capture(values []string) error {
   144  	switch strings.Join(values, "") {
   145  	case "u8", "w8":
   146  		*s = BPF_B
   147  	case "u16", "w16":
   148  		*s = BPF_H
   149  	case "u32", "w32":
   150  		*s = BPF_W
   151  	case "u64", "w64":
   152  		*s = BPF_DW
   153  	default:
   154  		return fmt.Errorf("'%s' is not a valid variable Size", strings.Join(values, ""))
   155  	}
   156  
   157  	return nil
   158  }
   159  
   160  type directive struct {
   161  	Type    *typeDirective    `parser:"  @@"`
   162  	Generic *genericDirective `parser:"| @@"`
   163  }
   164  
   165  // https://sourceware.org/binutils/docs/as/Type.html
   166  type typeDirective struct {
   167  	Name string `parser:"'.' 'type' @Ident"`
   168  	Type string `parser:"','? ('@'|'%')? @Ident"`
   169  }
   170  
   171  type genericDirective struct {
   172  	Name  string `parser:"'.' @Ident"`
   173  	Value string `parser:"(@Ident | @Number | @Punct)*"`
   174  }
   175  
   176  type instruction struct {
   177  	ARSH32                                 *arsh32                                 `parser:"  @@"`
   178  	ARSH32Register                         *arsh32Register                         `parser:"| @@"`
   179  	ARSH64                                 *arsh64                                 `parser:"| @@"`
   180  	ARSH64Register                         *arsh64Register                         `parser:"| @@"`
   181  	Add32                                  *add32                                  `parser:"| @@"`
   182  	Add32Register                          *add32Register                          `parser:"| @@"`
   183  	Add64                                  *add64                                  `parser:"| @@"`
   184  	Add64Register                          *add64Register                          `parser:"| @@"`
   185  	And32                                  *and32                                  `parser:"| @@"`
   186  	And32Register                          *and32Register                          `parser:"| @@"`
   187  	And64                                  *and64                                  `parser:"| @@"`
   188  	And64Register                          *and64Register                          `parser:"| @@"`
   189  	AtomicAdd32                            *atomicAdd32                            `parser:"| @@"`
   190  	AtomicAdd64                            *atomicAdd64                            `parser:"| @@"`
   191  	AtomicSub32                            *atomicSub32                            `parser:"| @@"`
   192  	AtomicSub64                            *atomicSub64                            `parser:"| @@"`
   193  	AtomicAnd32                            *atomicAnd32                            `parser:"| @@"`
   194  	AtomicAnd64                            *atomicAnd64                            `parser:"| @@"`
   195  	AtomicCompareAndExchange32             *atomicCompareAndExchange32             `parser:"| @@"`
   196  	AtomicCompareAndExchange64             *atomicCompareAndExchange64             `parser:"| @@"`
   197  	AtomicExchange32                       *atomicExchange32                       `parser:"| @@"`
   198  	AtomicExchange64                       *atomicExchange64                       `parser:"| @@"`
   199  	AtomicOr32                             *atomicOr32                             `parser:"| @@"`
   200  	AtomicOr64                             *atomicOr64                             `parser:"| @@"`
   201  	AtomicXor32                            *atomicXor32                            `parser:"| @@"`
   202  	AtomicXor64                            *atomicXor64                            `parser:"| @@"`
   203  	Call                                   *call                                   `parser:"| @@"`
   204  	Div32                                  *div32                                  `parser:"| @@"`
   205  	Div32Register                          *div32Register                          `parser:"| @@"`
   206  	Div64                                  *div64                                  `parser:"| @@"`
   207  	Div64Register                          *div64Register                          `parser:"| @@"`
   208  	End16ToBE                              *end16ToBE                              `parser:"| @@"`
   209  	End16ToLE                              *end16ToLE                              `parser:"| @@"`
   210  	End32ToBE                              *end32ToBE                              `parser:"| @@"`
   211  	End32ToLE                              *end32ToLE                              `parser:"| @@"`
   212  	End64ToBE                              *end64ToBE                              `parser:"| @@"`
   213  	End64ToLE                              *end64ToLE                              `parser:"| @@"`
   214  	Exit                                   *exit                                   `parser:"| @@"`
   215  	Jump                                   *jump                                   `parser:"| @@"`
   216  	JumpEqual                              *jumpEqual                              `parser:"| @@"`
   217  	JumpEqual32                            *jumpEqual32                            `parser:"| @@"`
   218  	JumpEqualRegister                      *jumpEqualRegister                      `parser:"| @@"`
   219  	JumpEqualRegister32                    *jumpEqualRegister32                    `parser:"| @@"`
   220  	JumpGreaterThan                        *jumpGreaterThan                        `parser:"| @@"`
   221  	JumpGreaterThan32                      *jumpGreaterThan32                      `parser:"| @@"`
   222  	JumpGreaterThanRegister                *jumpGreaterThanRegister                `parser:"| @@"`
   223  	JumpGreaterThanRegister32              *jumpGreaterThanRegister32              `parser:"| @@"`
   224  	JumpGreaterThanEqual                   *jumpGreaterThanEqual                   `parser:"| @@"`
   225  	JumpGreaterThanEqual32                 *jumpGreaterThanEqual32                 `parser:"| @@"`
   226  	JumpGreaterThanEqualRegister           *jumpGreaterThanEqualRegister           `parser:"| @@"`
   227  	JumpGreaterThanEqualRegister32         *jumpGreaterThanEqualRegister32         `parser:"| @@"`
   228  	JumpIfAnd                              *jumpIfAnd                              `parser:"| @@"`
   229  	JumpIfAnd32                            *jumpIfAnd32                            `parser:"| @@"`
   230  	JumpIfAndRegister                      *jumpIfAndRegister                      `parser:"| @@"`
   231  	JumpIfAndRegister32                    *jumpIfAndRegister32                    `parser:"| @@"`
   232  	JumpIfNotEqual                         *jumpIfNotEqual                         `parser:"| @@"`
   233  	JumpIfNotEqual32                       *jumpIfNotEqual32                       `parser:"| @@"`
   234  	JumpIfNotEqualRegister                 *jumpIfNotEqualRegister                 `parser:"| @@"`
   235  	JumpIfNotEqualRegister32               *jumpIfNotEqualRegister32               `parser:"| @@"`
   236  	JumpSignedGreaterThan                  *jumpSignedGreaterThan                  `parser:"| @@"`
   237  	JumpSignedGreaterThan32                *jumpSignedGreaterThan32                `parser:"| @@"`
   238  	JumpSignedGreaterThanRegister          *jumpSignedGreaterThanRegister          `parser:"| @@"`
   239  	JumpSignedGreaterThanRegister32        *jumpSignedGreaterThanRegister32        `parser:"| @@"`
   240  	JumpSignedGreaterThanOrEqual           *jumpSignedGreaterThanOrEqual           `parser:"| @@"`
   241  	JumpSignedGreaterThanOrEqual32         *jumpSignedGreaterThanOrEqual32         `parser:"| @@"`
   242  	JumpSignedGreaterThanOrEqualRegister   *jumpSignedGreaterThanOrEqualRegister   `parser:"| @@"`
   243  	JumpSignedGreaterThanOrEqualRegister32 *jumpSignedGreaterThanOrEqualRegister32 `parser:"| @@"`
   244  	JumpSignedSmallerThan                  *jumpSignedSmallerThan                  `parser:"| @@"`
   245  	JumpSignedSmallerThan32                *jumpSignedSmallerThan32                `parser:"| @@"`
   246  	JumpSignedSmallerThanRegister          *jumpSignedSmallerThanRegister          `parser:"| @@"`
   247  	JumpSignedSmallerThanRegister32        *jumpSignedSmallerThanRegister32        `parser:"| @@"`
   248  	JumpSignedSmallerThanOrEqual           *jumpSignedSmallerThanOrEqual           `parser:"| @@"`
   249  	JumpSignedSmallerThanOrEqual32         *jumpSignedSmallerThanOrEqual32         `parser:"| @@"`
   250  	JumpSignedSmallerThanOrEqualRegister   *jumpSignedSmallerThanOrEqualRegister   `parser:"| @@"`
   251  	JumpSignedSmallerThanOrEqualRegister32 *jumpSignedSmallerThanOrEqualRegister32 `parser:"| @@"`
   252  	JumpSmallerThan                        *jumpSmallerThan                        `parser:"| @@"`
   253  	JumpSmallerThan32                      *jumpSmallerThan32                      `parser:"| @@"`
   254  	JumpSmallerThanRegister                *jumpSmallerThanRegister                `parser:"| @@"`
   255  	JumpSmallerThanRegister32              *jumpSmallerThanRegister32              `parser:"| @@"`
   256  	JumpSmallerThanEqual                   *jumpSmallerThanEqual                   `parser:"| @@"`
   257  	JumpSmallerThanEqual32                 *jumpSmallerThanEqual32                 `parser:"| @@"`
   258  	JumpSmallerThanEqualRegister           *jumpSmallerThanEqualRegister           `parser:"| @@"`
   259  	JumpSmallerThanEqualRegister32         *jumpSmallerThanEqualRegister32         `parser:"| @@"`
   260  	LoadConstant64bit                      *loadConstant64bit                      `parser:"| @@"`
   261  	LoadMemory                             *loadMemory                             `parser:"| @@"`
   262  	LoadSocketBuf                          *loadSocketBuf                          `parser:"| @@"`
   263  	LoadSocketBufConstant                  *loadSocketBufConstant                  `parser:"| @@"`
   264  	Lsh32                                  *lsh32                                  `parser:"| @@"`
   265  	Lsh32Register                          *lsh32Register                          `parser:"| @@"`
   266  	Lsh64                                  *lsh64                                  `parser:"| @@"`
   267  	Lsh64Register                          *lsh64Register                          `parser:"| @@"`
   268  	Mod32                                  *mod32                                  `parser:"| @@"`
   269  	Mod32Register                          *mod32Register                          `parser:"| @@"`
   270  	Mod64                                  *mod64                                  `parser:"| @@"`
   271  	Mod64Register                          *mod64Register                          `parser:"| @@"`
   272  	Mov32                                  *mov32                                  `parser:"| @@"`
   273  	Mov32Register                          *mov32Register                          `parser:"| @@"`
   274  	Mov64                                  *mov64                                  `parser:"| @@"`
   275  	Mov64Register                          *mov64Register                          `parser:"| @@"`
   276  	Mul32                                  *mul32                                  `parser:"| @@"`
   277  	Mul32Register                          *mul32Register                          `parser:"| @@"`
   278  	Mul64                                  *mul64                                  `parser:"| @@"`
   279  	Mul64Register                          *mul64Register                          `parser:"| @@"`
   280  	Neg32                                  *neg32                                  `parser:"| @@"`
   281  	Neg64                                  *neg64                                  `parser:"| @@"`
   282  	Or32                                   *or32                                   `parser:"| @@"`
   283  	Or32Register                           *or32Register                           `parser:"| @@"`
   284  	Or64                                   *or64                                   `parser:"| @@"`
   285  	Or64Register                           *or64Register                           `parser:"| @@"`
   286  	Rsh32                                  *rsh32                                  `parser:"| @@"`
   287  	Rsh32Register                          *rsh32Register                          `parser:"| @@"`
   288  	Rsh64                                  *rsh64                                  `parser:"| @@"`
   289  	Rsh64Register                          *rsh64Register                          `parser:"| @@"`
   290  	StoreMemoryConstant                    *storeMemoryConstant                    `parser:"| @@"`
   291  	StoreMemoryRegister                    *storeMemoryRegister                    `parser:"| @@"`
   292  	Sub32                                  *sub32                                  `parser:"| @@"`
   293  	Sub32Register                          *sub32Register                          `parser:"| @@"`
   294  	Sub64                                  *sub64                                  `parser:"| @@"`
   295  	Sub64Register                          *sub64Register                          `parser:"| @@"`
   296  	Xor32                                  *xor32                                  `parser:"| @@"`
   297  	Xor32Register                          *xor32Register                          `parser:"| @@"`
   298  	Xor64                                  *xor64                                  `parser:"| @@"`
   299  	Xor64Register                          *xor64Register                          `parser:"| @@"`
   300  }
   301  
   302  func (i *instruction) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   303  	if i.ARSH32 != nil {
   304  		return i.ARSH32.ToInst(index, ctx)
   305  	}
   306  
   307  	if i.ARSH32Register != nil {
   308  		return i.ARSH32Register.ToInst(index, ctx)
   309  	}
   310  
   311  	if i.ARSH64 != nil {
   312  		return i.ARSH64.ToInst(index, ctx)
   313  	}
   314  
   315  	if i.ARSH64Register != nil {
   316  		return i.ARSH64Register.ToInst(index, ctx)
   317  	}
   318  
   319  	if i.Add32 != nil {
   320  		return i.Add32.ToInst(index, ctx)
   321  	}
   322  
   323  	if i.Add32Register != nil {
   324  		return i.Add32Register.ToInst(index, ctx)
   325  	}
   326  
   327  	if i.Add64 != nil {
   328  		return i.Add64.ToInst(index, ctx)
   329  	}
   330  
   331  	if i.Add64Register != nil {
   332  		return i.Add64Register.ToInst(index, ctx)
   333  	}
   334  
   335  	if i.And32 != nil {
   336  		return i.And32.ToInst(index, ctx)
   337  	}
   338  
   339  	if i.And32Register != nil {
   340  		return i.And32Register.ToInst(index, ctx)
   341  	}
   342  
   343  	if i.And64 != nil {
   344  		return i.And64.ToInst(index, ctx)
   345  	}
   346  
   347  	if i.And64Register != nil {
   348  		return i.And64Register.ToInst(index, ctx)
   349  	}
   350  
   351  	if i.AtomicAdd32 != nil {
   352  		return i.AtomicAdd32.ToInst(index, ctx)
   353  	}
   354  
   355  	if i.AtomicAdd64 != nil {
   356  		return i.AtomicAdd64.ToInst(index, ctx)
   357  	}
   358  
   359  	if i.AtomicSub32 != nil {
   360  		return i.AtomicSub32.ToInst(index, ctx)
   361  	}
   362  
   363  	if i.AtomicSub64 != nil {
   364  		return i.AtomicSub64.ToInst(index, ctx)
   365  	}
   366  
   367  	if i.AtomicAnd32 != nil {
   368  		return i.AtomicAnd32.ToInst(index, ctx)
   369  	}
   370  
   371  	if i.AtomicAnd64 != nil {
   372  		return i.AtomicAnd64.ToInst(index, ctx)
   373  	}
   374  
   375  	if i.AtomicCompareAndExchange32 != nil {
   376  		return i.AtomicCompareAndExchange32.ToInst(index, ctx)
   377  	}
   378  
   379  	if i.AtomicCompareAndExchange64 != nil {
   380  		return i.AtomicCompareAndExchange64.ToInst(index, ctx)
   381  	}
   382  
   383  	if i.AtomicExchange32 != nil {
   384  		return i.AtomicExchange32.ToInst(index, ctx)
   385  	}
   386  
   387  	if i.AtomicExchange64 != nil {
   388  		return i.AtomicExchange64.ToInst(index, ctx)
   389  	}
   390  
   391  	if i.AtomicOr32 != nil {
   392  		return i.AtomicOr32.ToInst(index, ctx)
   393  	}
   394  
   395  	if i.AtomicOr64 != nil {
   396  		return i.AtomicOr64.ToInst(index, ctx)
   397  	}
   398  
   399  	if i.AtomicXor32 != nil {
   400  		return i.AtomicXor32.ToInst(index, ctx)
   401  	}
   402  
   403  	if i.AtomicXor64 != nil {
   404  		return i.AtomicXor64.ToInst(index, ctx)
   405  	}
   406  
   407  	if i.Call != nil {
   408  		return i.Call.ToInst(index, ctx)
   409  	}
   410  
   411  	if i.Div32 != nil {
   412  		return i.Div32.ToInst(index, ctx)
   413  	}
   414  
   415  	if i.Div32Register != nil {
   416  		return i.Div32Register.ToInst(index, ctx)
   417  	}
   418  
   419  	if i.Div64 != nil {
   420  		return i.Div64.ToInst(index, ctx)
   421  	}
   422  
   423  	if i.Div64Register != nil {
   424  		return i.Div64Register.ToInst(index, ctx)
   425  	}
   426  
   427  	if i.End16ToBE != nil {
   428  		return i.End16ToBE.ToInst(index, ctx)
   429  	}
   430  
   431  	if i.End16ToLE != nil {
   432  		return i.End16ToLE.ToInst(index, ctx)
   433  	}
   434  
   435  	if i.End32ToBE != nil {
   436  		return i.End32ToBE.ToInst(index, ctx)
   437  	}
   438  
   439  	if i.End32ToLE != nil {
   440  		return i.End32ToLE.ToInst(index, ctx)
   441  	}
   442  
   443  	if i.End64ToBE != nil {
   444  		return i.End64ToBE.ToInst(index, ctx)
   445  	}
   446  
   447  	if i.End64ToLE != nil {
   448  		return i.End64ToLE.ToInst(index, ctx)
   449  	}
   450  
   451  	if i.Exit != nil {
   452  		return i.Exit.ToInst(index, ctx)
   453  	}
   454  
   455  	if i.Jump != nil {
   456  		return i.Jump.ToInst(index, ctx)
   457  	}
   458  
   459  	if i.JumpEqual != nil {
   460  		return i.JumpEqual.ToInst(index, ctx)
   461  	}
   462  
   463  	if i.JumpEqual32 != nil {
   464  		return i.JumpEqual32.ToInst(index, ctx)
   465  	}
   466  
   467  	if i.JumpEqualRegister != nil {
   468  		return i.JumpEqualRegister.ToInst(index, ctx)
   469  	}
   470  
   471  	if i.JumpEqualRegister32 != nil {
   472  		return i.JumpEqualRegister32.ToInst(index, ctx)
   473  	}
   474  
   475  	if i.JumpGreaterThan != nil {
   476  		return i.JumpGreaterThan.ToInst(index, ctx)
   477  	}
   478  
   479  	if i.JumpGreaterThan32 != nil {
   480  		return i.JumpGreaterThan32.ToInst(index, ctx)
   481  	}
   482  
   483  	if i.JumpGreaterThanRegister != nil {
   484  		return i.JumpGreaterThanRegister.ToInst(index, ctx)
   485  	}
   486  
   487  	if i.JumpGreaterThanRegister32 != nil {
   488  		return i.JumpGreaterThanRegister32.ToInst(index, ctx)
   489  	}
   490  
   491  	if i.JumpGreaterThanEqual != nil {
   492  		return i.JumpGreaterThanEqual.ToInst(index, ctx)
   493  	}
   494  
   495  	if i.JumpGreaterThanEqual32 != nil {
   496  		return i.JumpGreaterThanEqual32.ToInst(index, ctx)
   497  	}
   498  
   499  	if i.JumpGreaterThanEqualRegister != nil {
   500  		return i.JumpGreaterThanEqualRegister.ToInst(index, ctx)
   501  	}
   502  
   503  	if i.JumpGreaterThanEqualRegister32 != nil {
   504  		return i.JumpGreaterThanEqualRegister32.ToInst(index, ctx)
   505  	}
   506  
   507  	if i.JumpIfAnd != nil {
   508  		return i.JumpIfAnd.ToInst(index, ctx)
   509  	}
   510  
   511  	if i.JumpIfAnd32 != nil {
   512  		return i.JumpIfAnd32.ToInst(index, ctx)
   513  	}
   514  
   515  	if i.JumpIfAndRegister != nil {
   516  		return i.JumpIfAndRegister.ToInst(index, ctx)
   517  	}
   518  
   519  	if i.JumpIfAndRegister32 != nil {
   520  		return i.JumpIfAndRegister32.ToInst(index, ctx)
   521  	}
   522  
   523  	if i.JumpIfNotEqual != nil {
   524  		return i.JumpIfNotEqual.ToInst(index, ctx)
   525  	}
   526  
   527  	if i.JumpIfNotEqual32 != nil {
   528  		return i.JumpIfNotEqual32.ToInst(index, ctx)
   529  	}
   530  
   531  	if i.JumpIfNotEqualRegister != nil {
   532  		return i.JumpIfNotEqualRegister.ToInst(index, ctx)
   533  	}
   534  
   535  	if i.JumpIfNotEqualRegister32 != nil {
   536  		return i.JumpIfNotEqualRegister32.ToInst(index, ctx)
   537  	}
   538  
   539  	if i.JumpSignedGreaterThan != nil {
   540  		return i.JumpSignedGreaterThan.ToInst(index, ctx)
   541  	}
   542  
   543  	if i.JumpSignedGreaterThan32 != nil {
   544  		return i.JumpSignedGreaterThan32.ToInst(index, ctx)
   545  	}
   546  
   547  	if i.JumpSignedGreaterThanRegister != nil {
   548  		return i.JumpSignedGreaterThanRegister.ToInst(index, ctx)
   549  	}
   550  
   551  	if i.JumpSignedGreaterThanRegister32 != nil {
   552  		return i.JumpSignedGreaterThanRegister32.ToInst(index, ctx)
   553  	}
   554  
   555  	if i.JumpSignedGreaterThanOrEqual != nil {
   556  		return i.JumpSignedGreaterThanOrEqual.ToInst(index, ctx)
   557  	}
   558  
   559  	if i.JumpSignedGreaterThanOrEqual32 != nil {
   560  		return i.JumpSignedGreaterThanOrEqual32.ToInst(index, ctx)
   561  	}
   562  
   563  	if i.JumpSignedGreaterThanOrEqualRegister != nil {
   564  		return i.JumpSignedGreaterThanOrEqualRegister.ToInst(index, ctx)
   565  	}
   566  
   567  	if i.JumpSignedGreaterThanOrEqualRegister32 != nil {
   568  		return i.JumpSignedGreaterThanOrEqualRegister32.ToInst(index, ctx)
   569  	}
   570  
   571  	if i.JumpSignedSmallerThan != nil {
   572  		return i.JumpSignedSmallerThan.ToInst(index, ctx)
   573  	}
   574  
   575  	if i.JumpSignedSmallerThan32 != nil {
   576  		return i.JumpSignedSmallerThan32.ToInst(index, ctx)
   577  	}
   578  
   579  	if i.JumpSignedSmallerThanRegister != nil {
   580  		return i.JumpSignedSmallerThanRegister.ToInst(index, ctx)
   581  	}
   582  
   583  	if i.JumpSignedSmallerThanRegister32 != nil {
   584  		return i.JumpSignedSmallerThanRegister32.ToInst(index, ctx)
   585  	}
   586  
   587  	if i.JumpSignedSmallerThanOrEqual != nil {
   588  		return i.JumpSignedSmallerThanOrEqual.ToInst(index, ctx)
   589  	}
   590  
   591  	if i.JumpSignedSmallerThanOrEqual32 != nil {
   592  		return i.JumpSignedSmallerThanOrEqual32.ToInst(index, ctx)
   593  	}
   594  
   595  	if i.JumpSignedSmallerThanOrEqualRegister != nil {
   596  		return i.JumpSignedSmallerThanOrEqualRegister.ToInst(index, ctx)
   597  	}
   598  
   599  	if i.JumpSignedSmallerThanOrEqualRegister32 != nil {
   600  		return i.JumpSignedSmallerThanOrEqualRegister32.ToInst(index, ctx)
   601  	}
   602  
   603  	if i.JumpSmallerThan != nil {
   604  		return i.JumpSmallerThan.ToInst(index, ctx)
   605  	}
   606  
   607  	if i.JumpSmallerThan32 != nil {
   608  		return i.JumpSmallerThan32.ToInst(index, ctx)
   609  	}
   610  
   611  	if i.JumpSmallerThanRegister != nil {
   612  		return i.JumpSmallerThanRegister.ToInst(index, ctx)
   613  	}
   614  
   615  	if i.JumpSmallerThanRegister32 != nil {
   616  		return i.JumpSmallerThanRegister32.ToInst(index, ctx)
   617  	}
   618  
   619  	if i.JumpSmallerThanEqual != nil {
   620  		return i.JumpSmallerThanEqual.ToInst(index, ctx)
   621  	}
   622  
   623  	if i.JumpSmallerThanEqual32 != nil {
   624  		return i.JumpSmallerThanEqual32.ToInst(index, ctx)
   625  	}
   626  
   627  	if i.JumpSmallerThanEqualRegister != nil {
   628  		return i.JumpSmallerThanEqualRegister.ToInst(index, ctx)
   629  	}
   630  
   631  	if i.JumpSmallerThanEqualRegister32 != nil {
   632  		return i.JumpSmallerThanEqualRegister32.ToInst(index, ctx)
   633  	}
   634  
   635  	if i.LoadConstant64bit != nil {
   636  		return i.LoadConstant64bit.ToInst(index, ctx)
   637  	}
   638  
   639  	if i.LoadMemory != nil {
   640  		return i.LoadMemory.ToInst(index, ctx)
   641  	}
   642  
   643  	if i.LoadSocketBuf != nil {
   644  		return i.LoadSocketBuf.ToInst(index, ctx)
   645  	}
   646  
   647  	if i.LoadSocketBufConstant != nil {
   648  		return i.LoadSocketBufConstant.ToInst(index, ctx)
   649  	}
   650  
   651  	if i.Lsh32 != nil {
   652  		return i.Lsh32.ToInst(index, ctx)
   653  	}
   654  
   655  	if i.Lsh32Register != nil {
   656  		return i.Lsh32Register.ToInst(index, ctx)
   657  	}
   658  
   659  	if i.Lsh64 != nil {
   660  		return i.Lsh64.ToInst(index, ctx)
   661  	}
   662  
   663  	if i.Lsh64Register != nil {
   664  		return i.Lsh64Register.ToInst(index, ctx)
   665  	}
   666  
   667  	if i.Mod32 != nil {
   668  		return i.Mod32.ToInst(index, ctx)
   669  	}
   670  
   671  	if i.Mod32Register != nil {
   672  		return i.Mod32Register.ToInst(index, ctx)
   673  	}
   674  
   675  	if i.Mod64 != nil {
   676  		return i.Mod64.ToInst(index, ctx)
   677  	}
   678  
   679  	if i.Mod64Register != nil {
   680  		return i.Mod64Register.ToInst(index, ctx)
   681  	}
   682  
   683  	if i.Mov32 != nil {
   684  		return i.Mov32.ToInst(index, ctx)
   685  	}
   686  
   687  	if i.Mov32Register != nil {
   688  		return i.Mov32Register.ToInst(index, ctx)
   689  	}
   690  
   691  	if i.Mov64 != nil {
   692  		return i.Mov64.ToInst(index, ctx)
   693  	}
   694  
   695  	if i.Mov64Register != nil {
   696  		return i.Mov64Register.ToInst(index, ctx)
   697  	}
   698  
   699  	if i.Mul32 != nil {
   700  		return i.Mul32.ToInst(index, ctx)
   701  	}
   702  
   703  	if i.Mul32Register != nil {
   704  		return i.Mul32Register.ToInst(index, ctx)
   705  	}
   706  
   707  	if i.Mul64 != nil {
   708  		return i.Mul64.ToInst(index, ctx)
   709  	}
   710  
   711  	if i.Mul64Register != nil {
   712  		return i.Mul64Register.ToInst(index, ctx)
   713  	}
   714  
   715  	if i.Neg32 != nil {
   716  		return i.Neg32.ToInst(index, ctx)
   717  	}
   718  
   719  	if i.Neg64 != nil {
   720  		return i.Neg64.ToInst(index, ctx)
   721  	}
   722  
   723  	if i.Or32 != nil {
   724  		return i.Or32.ToInst(index, ctx)
   725  	}
   726  
   727  	if i.Or32Register != nil {
   728  		return i.Or32Register.ToInst(index, ctx)
   729  	}
   730  
   731  	if i.Or64 != nil {
   732  		return i.Or64.ToInst(index, ctx)
   733  	}
   734  
   735  	if i.Or64Register != nil {
   736  		return i.Or64Register.ToInst(index, ctx)
   737  	}
   738  
   739  	if i.Rsh32 != nil {
   740  		return i.Rsh32.ToInst(index, ctx)
   741  	}
   742  
   743  	if i.Rsh32Register != nil {
   744  		return i.Rsh32Register.ToInst(index, ctx)
   745  	}
   746  
   747  	if i.Rsh64 != nil {
   748  		return i.Rsh64.ToInst(index, ctx)
   749  	}
   750  
   751  	if i.Rsh64Register != nil {
   752  		return i.Rsh64Register.ToInst(index, ctx)
   753  	}
   754  
   755  	if i.StoreMemoryConstant != nil {
   756  		return i.StoreMemoryConstant.ToInst(index, ctx)
   757  	}
   758  
   759  	if i.StoreMemoryRegister != nil {
   760  		return i.StoreMemoryRegister.ToInst(index, ctx)
   761  	}
   762  
   763  	if i.Sub32 != nil {
   764  		return i.Sub32.ToInst(index, ctx)
   765  	}
   766  
   767  	if i.Sub32Register != nil {
   768  		return i.Sub32Register.ToInst(index, ctx)
   769  	}
   770  
   771  	if i.Sub64 != nil {
   772  		return i.Sub64.ToInst(index, ctx)
   773  	}
   774  
   775  	if i.Sub64Register != nil {
   776  		return i.Sub64Register.ToInst(index, ctx)
   777  	}
   778  
   779  	if i.Xor32 != nil {
   780  		return i.Xor32.ToInst(index, ctx)
   781  	}
   782  
   783  	if i.Xor32Register != nil {
   784  		return i.Xor32Register.ToInst(index, ctx)
   785  	}
   786  
   787  	if i.Xor64 != nil {
   788  		return i.Xor64.ToInst(index, ctx)
   789  	}
   790  
   791  	if i.Xor64Register != nil {
   792  		return i.Xor64Register.ToInst(index, ctx)
   793  	}
   794  
   795  	return nil, nil
   796  }
   797  
   798  type arsh32 struct {
   799  	Dst   Register `parser:"@Register32 's' '>' '>' '='"`
   800  	Value int32    `parser:"@(('+'|'-')? Number)"`
   801  }
   802  
   803  func (i *arsh32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   804  	return []Instruction{&ARSH32{
   805  		Dest:  i.Dst,
   806  		Value: i.Value,
   807  	}}, nil
   808  }
   809  
   810  type arsh32Register struct {
   811  	Dst Register `parser:"@Register32 's' '>' '>' '='"`
   812  	Src Register `parser:"@Register32"`
   813  }
   814  
   815  func (i *arsh32Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   816  	return []Instruction{
   817  		&ARSH32Register{
   818  			Dest: i.Dst,
   819  			Src:  i.Src,
   820  		},
   821  	}, nil
   822  }
   823  
   824  type arsh64 struct {
   825  	Dst   Register `parser:"@Register64 's' '>' '>' '='"`
   826  	Value int32    `parser:"@(('+'|'-')? Number)"`
   827  }
   828  
   829  func (i *arsh64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   830  	return []Instruction{&ARSH64{
   831  		Dest:  i.Dst,
   832  		Value: i.Value,
   833  	}}, nil
   834  }
   835  
   836  type arsh64Register struct {
   837  	Dst Register `parser:"@Register64 's' '>' '>' '='"`
   838  	Src Register `parser:"@Register64"`
   839  }
   840  
   841  func (i *arsh64Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   842  	return []Instruction{&ARSH64Register{
   843  		Dest: i.Dst,
   844  		Src:  i.Src,
   845  	}}, nil
   846  }
   847  
   848  type add32 struct {
   849  	Dst   Register `parser:"@Register32 '+' '='"`
   850  	Value int32    `parser:"@(('+'|'-')? Number)"`
   851  }
   852  
   853  func (i *add32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   854  	return []Instruction{&Add32{
   855  		Dest:  i.Dst,
   856  		Value: i.Value,
   857  	}}, nil
   858  }
   859  
   860  type add32Register struct {
   861  	Dst Register `parser:"@Register32 '+' '='"`
   862  	Src Register `parser:"@Register32"`
   863  }
   864  
   865  func (i *add32Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   866  	return []Instruction{&Add32Register{
   867  		Dest: i.Dst,
   868  		Src:  i.Src,
   869  	}}, nil
   870  }
   871  
   872  type add64 struct {
   873  	Dst   Register `parser:"@Register64 '+' '='"`
   874  	Value int32    `parser:"@(('+'|'-')? Number)"`
   875  }
   876  
   877  func (i *add64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   878  	return []Instruction{&Add64{
   879  		Dest:  i.Dst,
   880  		Value: i.Value,
   881  	}}, nil
   882  }
   883  
   884  type add64Register struct {
   885  	Dst Register `parser:"@Register64 '+' '='"`
   886  	Src Register `parser:"@Register64"`
   887  }
   888  
   889  func (i *add64Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   890  	return []Instruction{&Add64Register{
   891  		Dest: i.Dst,
   892  		Src:  i.Src,
   893  	}}, nil
   894  }
   895  
   896  type and32 struct {
   897  	Dst   Register `parser:"@Register32 '&' '='"`
   898  	Value int32    `parser:"@(('+'|'-')? Number)"`
   899  }
   900  
   901  func (i *and32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   902  	return []Instruction{&And32{
   903  		Dest:  i.Dst,
   904  		Value: i.Value,
   905  	}}, nil
   906  }
   907  
   908  type and32Register struct {
   909  	Dst Register `parser:"@Register32 '&' '='"`
   910  	Src Register `parser:"@Register32"`
   911  }
   912  
   913  func (i *and32Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   914  	return []Instruction{&And32Register{
   915  		Dest: i.Dst,
   916  		Src:  i.Src,
   917  	}}, nil
   918  }
   919  
   920  type and64 struct {
   921  	Dst   Register `parser:"@Register64 '&' '='"`
   922  	Value int32    `parser:"@(('+'|'-')? Number)"`
   923  }
   924  
   925  func (i *and64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   926  	return []Instruction{&And64{
   927  		Dest:  i.Dst,
   928  		Value: i.Value,
   929  	}}, nil
   930  }
   931  
   932  type and64Register struct {
   933  	Dst Register `parser:"@Register64 '&' '='"`
   934  	Src Register `parser:"@Register64"`
   935  }
   936  
   937  func (i *and64Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   938  	return []Instruction{&And64Register{
   939  		Dest: i.Dst,
   940  		Src:  i.Src,
   941  	}}, nil
   942  }
   943  
   944  type atomicAdd32 struct {
   945  	Dst    Register `parser:"'lock' '*' '(' 'u32' '*' ')' '(' @Register64"`
   946  	Offset int32    `parser:"@(('+'|'-') Number) ')' '+' '='"`
   947  	Src    Register `parser:"@Register32"`
   948  }
   949  
   950  func (i *atomicAdd32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   951  	return []Instruction{&AtomicAdd{
   952  		Dest:   i.Dst,
   953  		Src:    i.Src,
   954  		Size:   BPF_W,
   955  		Offset: int16(i.Offset),
   956  		Fetch:  false, // TODO make a special instruction for the fetch flag?
   957  	}}, nil
   958  }
   959  
   960  type atomicAdd64 struct {
   961  	Dst    Register `parser:"'lock' '*' '(' 'u64' '*' ')' '(' @Register64"`
   962  	Offset int32    `parser:"@(('+'|'-') Number) ')' '+' '='"`
   963  	Src    Register `parser:"@Register64"`
   964  }
   965  
   966  func (i *atomicAdd64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   967  	return []Instruction{&AtomicAdd{
   968  		Dest:   i.Dst,
   969  		Src:    i.Src,
   970  		Size:   BPF_DW,
   971  		Offset: int16(i.Offset),
   972  		Fetch:  false, // TODO make a special instruction for the fetch flag?
   973  	}}, nil
   974  }
   975  
   976  type atomicSub32 struct {
   977  	Dst    Register `parser:"'lock' '*' '(' 'u32' '*' ')' '(' @Register64"`
   978  	Offset int32    `parser:"@(('+'|'-') Number) ')' '-' '='"`
   979  	Src    Register `parser:"@Register32"`
   980  }
   981  
   982  func (i *atomicSub32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   983  	return []Instruction{&AtomicSub{
   984  		Dest:   i.Dst,
   985  		Src:    i.Src,
   986  		Size:   BPF_W,
   987  		Offset: int16(i.Offset),
   988  		Fetch:  false, // TODO make a special instruction for the fetch flag?
   989  	}}, nil
   990  }
   991  
   992  type atomicSub64 struct {
   993  	Dst    Register `parser:"'lock' '*' '(' 'u64' '*' ')' '(' @Register64"`
   994  	Offset int32    `parser:"@(('+'|'-') Number) ')' '-' '='"`
   995  	Src    Register `parser:"@Register64"`
   996  }
   997  
   998  func (i *atomicSub64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
   999  	return []Instruction{&AtomicSub{
  1000  		Dest:   i.Dst,
  1001  		Src:    i.Src,
  1002  		Size:   BPF_DW,
  1003  		Offset: int16(i.Offset),
  1004  		Fetch:  false, // TODO make a special instruction for the fetch flag?
  1005  	}}, nil
  1006  }
  1007  
  1008  type atomicAnd32 struct {
  1009  	Dst    Register `parser:"'lock' '*' '(' 'u32' '*' ')' '(' @Register64"`
  1010  	Offset int32    `parser:"@(('+'|'-') Number) ')' '&' '='"`
  1011  	Src    Register `parser:"@Register32"`
  1012  }
  1013  
  1014  func (i *atomicAnd32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1015  	return []Instruction{&AtomicAnd{
  1016  		Dest:   i.Dst,
  1017  		Src:    i.Src,
  1018  		Size:   BPF_W,
  1019  		Offset: int16(i.Offset),
  1020  		Fetch:  false, // TODO make a special instruction for the fetch flag?
  1021  	}}, nil
  1022  }
  1023  
  1024  type atomicAnd64 struct {
  1025  	Dst    Register `parser:"'lock' '*' '(' 'u64' '*' ')' '(' @Register64"`
  1026  	Offset int32    `parser:"@(('+'|'-') Number) ')' '&' '='"`
  1027  	Src    Register `parser:"@Register64"`
  1028  }
  1029  
  1030  func (i *atomicAnd64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1031  	return []Instruction{&AtomicAnd{
  1032  		Dest:   i.Dst,
  1033  		Src:    i.Src,
  1034  		Size:   BPF_DW,
  1035  		Offset: int16(i.Offset),
  1036  		Fetch:  false, // TODO make a special instruction for the fetch flag?
  1037  	}}, nil
  1038  }
  1039  
  1040  // w0 = cmpxchg(r3 + 456, w0, w2)
  1041  type atomicCompareAndExchange32 struct {
  1042  	Dst    Register `parser:"'w0' '=' 'cmpxchg' '(' @Register64"`
  1043  	Offset int32    `parser:"@(('+'|'-') Number) ',' 'w0' ','"`
  1044  	Src    Register `parser:"@Register32 ')'"`
  1045  }
  1046  
  1047  func (i *atomicCompareAndExchange32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1048  	return []Instruction{&AtomicCompareAndExchange{
  1049  		Dest:   i.Dst,
  1050  		Src:    i.Src,
  1051  		Size:   BPF_W,
  1052  		Offset: int16(i.Offset),
  1053  	}}, nil
  1054  }
  1055  
  1056  // r0 = cmpxchg(r3 + 456, r0, r2)
  1057  type atomicCompareAndExchange64 struct {
  1058  	Dst    Register `parser:"'r0' '=' 'cmpxchg' '(' @Register64"`
  1059  	Offset int32    `parser:"@(('+'|'-') Number) ',' 'r0' ','"`
  1060  	Src    Register `parser:"@Register64 ')'"`
  1061  }
  1062  
  1063  func (i *atomicCompareAndExchange64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1064  	return []Instruction{&AtomicCompareAndExchange{
  1065  		Dest:   i.Dst,
  1066  		Src:    i.Src,
  1067  		Size:   BPF_DW,
  1068  		Offset: int16(i.Offset),
  1069  	}}, nil
  1070  }
  1071  
  1072  // w1 = xchg(r3 + 456, w1)
  1073  type atomicExchange32 struct {
  1074  	Src    Register `parser:"@Register32 '=' 'xchg' '('"`
  1075  	Dst    Register `parser:"@Register64"`
  1076  	Offset int32    `parser:"@(('+'|'-') Number) ',' Register32 ')'"`
  1077  }
  1078  
  1079  func (i *atomicExchange32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1080  	return []Instruction{&AtomicExchange{
  1081  		Dest:   i.Dst,
  1082  		Src:    i.Src,
  1083  		Size:   BPF_W,
  1084  		Offset: int16(i.Offset),
  1085  	}}, nil
  1086  }
  1087  
  1088  // r1 = xchg(r3 + 456, r1)
  1089  type atomicExchange64 struct {
  1090  	Src    Register `parser:"@Register64 '=' 'xchg' '('"`
  1091  	Dst    Register `parser:"@Register64"`
  1092  	Offset int32    `parser:"@(('+'|'-') Number) ',' Register64 ')'"`
  1093  }
  1094  
  1095  func (i *atomicExchange64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1096  	return []Instruction{&AtomicExchange{
  1097  		Dest:   i.Dst,
  1098  		Src:    i.Src,
  1099  		Size:   BPF_DW,
  1100  		Offset: int16(i.Offset),
  1101  	}}, nil
  1102  }
  1103  
  1104  type atomicOr32 struct {
  1105  	Dst    Register `parser:"'lock' '*' '(' 'u32' '*' ')' '(' @Register64"`
  1106  	Offset int32    `parser:"@(('+'|'-') Number) ')' '|' '='"`
  1107  	Src    Register `parser:"@Register32"`
  1108  }
  1109  
  1110  func (i *atomicOr32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1111  	return []Instruction{&AtomicOr{
  1112  		Dest:   i.Dst,
  1113  		Src:    i.Src,
  1114  		Size:   BPF_W,
  1115  		Offset: int16(i.Offset),
  1116  		Fetch:  false, // TODO make a special instruction for the fetch flag?
  1117  	}}, nil
  1118  }
  1119  
  1120  type atomicOr64 struct {
  1121  	Dst    Register `parser:"'lock' '*' '(' 'u64' '*' ')' '(' @Register64"`
  1122  	Offset int32    `parser:"@(('+'|'-') Number) ')' '|' '='"`
  1123  	Src    Register `parser:"@Register64"`
  1124  }
  1125  
  1126  func (i *atomicOr64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1127  	return []Instruction{&AtomicOr{
  1128  		Dest:   i.Dst,
  1129  		Src:    i.Src,
  1130  		Size:   BPF_DW,
  1131  		Offset: int16(i.Offset),
  1132  		Fetch:  false, // TODO make a special instruction for the fetch flag?
  1133  	}}, nil
  1134  }
  1135  
  1136  type atomicXor32 struct {
  1137  	Dst    Register `parser:"'lock' '*' '(' 'u32' '*' ')' '(' @Register64"`
  1138  	Offset int32    `parser:"@(('+'|'-') Number) ')' '^' '='"`
  1139  	Src    Register `parser:"@Register32"`
  1140  }
  1141  
  1142  func (i *atomicXor32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1143  	return []Instruction{&AtomicXor{
  1144  		Dest:   i.Dst,
  1145  		Src:    i.Src,
  1146  		Size:   BPF_W,
  1147  		Offset: int16(i.Offset),
  1148  		Fetch:  false, // TODO make a special instruction for the fetch flag?
  1149  	}}, nil
  1150  }
  1151  
  1152  type atomicXor64 struct {
  1153  	Dst    Register `parser:"'lock' '*' '(' 'u64' '*' ')' '(' @Register64"`
  1154  	Offset int32    `parser:"@(('+'|'-') Number) ')' '^' '='"`
  1155  	Src    Register `parser:"@Register64"`
  1156  }
  1157  
  1158  func (i *atomicXor64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1159  	return []Instruction{&AtomicXor{
  1160  		Dest:   i.Dst,
  1161  		Src:    i.Src,
  1162  		Size:   BPF_DW,
  1163  		Offset: int16(i.Offset),
  1164  		Fetch:  false, // TODO make a special instruction for the fetch flag?
  1165  	}}, nil
  1166  }
  1167  
  1168  // Call is both for BPF-to-BPF and helper funcs, but since
  1169  type call struct {
  1170  	Ident     *string `parser:"'call' (@Ident |"`
  1171  	Offset    *int32  `parser:"@(('+'|'-') Number) |"`
  1172  	HelperNum *int32  `parser:"@Number)"`
  1173  }
  1174  
  1175  func (i *call) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1176  	if i.Ident != nil {
  1177  		pos, found := ctx.Labels[*i.Ident]
  1178  		if !found {
  1179  			// TODO check if the ident matches a known helper function
  1180  
  1181  			return nil, fmt.Errorf("undefined label '%s'", *i.Ident)
  1182  		}
  1183  
  1184  		off := int32(pos-index) - 1
  1185  		i.Offset = &off
  1186  	}
  1187  
  1188  	if i.Offset != nil {
  1189  		return []Instruction{&CallBPF{
  1190  			Offset: *i.Offset,
  1191  		}}, nil
  1192  	}
  1193  
  1194  	if i.HelperNum != nil {
  1195  		return []Instruction{&CallHelper{
  1196  			Function: *i.HelperNum,
  1197  		}}, nil
  1198  	}
  1199  
  1200  	return nil, nil
  1201  }
  1202  
  1203  type div32 struct {
  1204  	Dst   Register `parser:"@Register32 '/' '='"`
  1205  	Value int32    `parser:"@(('+'|'-')? Number)"`
  1206  }
  1207  
  1208  func (i *div32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1209  	return []Instruction{&Div32{
  1210  		Dest:  i.Dst,
  1211  		Value: i.Value,
  1212  	}}, nil
  1213  }
  1214  
  1215  type div32Register struct {
  1216  	Dst Register `parser:"@Register32 '/' '='"`
  1217  	Src Register `parser:"@Register32"`
  1218  }
  1219  
  1220  func (i *div32Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1221  	return []Instruction{&Div32Register{
  1222  		Dest: i.Dst,
  1223  		Src:  i.Src,
  1224  	}}, nil
  1225  }
  1226  
  1227  type div64 struct {
  1228  	Dst   Register `parser:"@Register64 '/' '='"`
  1229  	Value int32    `parser:"@(('+'|'-')? Number)"`
  1230  }
  1231  
  1232  func (i *div64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1233  	return []Instruction{&Div64{
  1234  		Dest:  i.Dst,
  1235  		Value: i.Value,
  1236  	}}, nil
  1237  }
  1238  
  1239  type div64Register struct {
  1240  	Dst Register `parser:"@Register64 '/' '='"`
  1241  	Src Register `parser:"@Register64"`
  1242  }
  1243  
  1244  func (i *div64Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1245  	return []Instruction{&Div64Register{
  1246  		Dest: i.Dst,
  1247  		Src:  i.Src,
  1248  	}}, nil
  1249  }
  1250  
  1251  type end16ToBE struct {
  1252  	Dst Register `parser:"@Register64 '=' 'be16' Register64"`
  1253  }
  1254  
  1255  func (i *end16ToBE) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1256  	return []Instruction{&End16ToBE{
  1257  		Dest: i.Dst,
  1258  	}}, nil
  1259  }
  1260  
  1261  type end16ToLE struct {
  1262  	Dst Register `parser:"@Register64 '=' 'le16' Register64"`
  1263  }
  1264  
  1265  func (i *end16ToLE) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1266  	return []Instruction{&End16ToLE{
  1267  		Dest: i.Dst,
  1268  	}}, nil
  1269  }
  1270  
  1271  type end32ToBE struct {
  1272  	Dst Register `parser:"@Register64 '=' 'be32' Register64"`
  1273  }
  1274  
  1275  func (i *end32ToBE) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1276  	return []Instruction{&End32ToBE{
  1277  		Dest: i.Dst,
  1278  	}}, nil
  1279  }
  1280  
  1281  type end32ToLE struct {
  1282  	Dst Register `parser:"@Register64 '=' 'le32' Register64"`
  1283  }
  1284  
  1285  func (i *end32ToLE) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1286  	return []Instruction{&End32ToLE{
  1287  		Dest: i.Dst,
  1288  	}}, nil
  1289  }
  1290  
  1291  type end64ToBE struct {
  1292  	Dst Register `parser:"@Register64 '=' 'be64' Register64"`
  1293  }
  1294  
  1295  func (i *end64ToBE) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1296  	return []Instruction{&End64ToBE{
  1297  		Dest: i.Dst,
  1298  	}}, nil
  1299  }
  1300  
  1301  type end64ToLE struct {
  1302  	Dst Register `parser:"@Register64 '=' 'le64' Register64"`
  1303  }
  1304  
  1305  func (i *end64ToLE) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1306  	return []Instruction{&End64ToLE{
  1307  		Dest: i.Dst,
  1308  	}}, nil
  1309  }
  1310  
  1311  type exit struct {
  1312  	Exit struct{} `parser:"'exit'"`
  1313  }
  1314  
  1315  func (i *exit) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1316  	return []Instruction{&Exit{}}, nil
  1317  }
  1318  
  1319  type jump struct {
  1320  	Offset *int16  `parser:"'goto' (@(('+'|'-')? Number) |"`
  1321  	Label  *string `parser:"@Ident )"`
  1322  }
  1323  
  1324  func (i *jump) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1325  	inst := &Jump{}
  1326  
  1327  	if i.Label != nil {
  1328  		target, found := ctx.Labels[*i.Label]
  1329  		if !found {
  1330  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1331  		}
  1332  
  1333  		// Get diff between current instruction and the target, -1 since a offset of 0 will jump
  1334  		// to the next instruction (inherent pc+1)
  1335  		inst.Offset = int16(target-index) - 1
  1336  	}
  1337  
  1338  	if i.Offset != nil {
  1339  		inst.Offset = *i.Offset
  1340  	}
  1341  
  1342  	return []Instruction{inst}, nil
  1343  }
  1344  
  1345  type jumpEqual struct {
  1346  	Dest   Register `parser:"'if' @Register64 '=' '=' "`
  1347  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  1348  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1349  	Label  *string  `parser:"@Ident )"`
  1350  }
  1351  
  1352  func (i *jumpEqual) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1353  	inst := &JumpEqual{
  1354  		Dest:  i.Dest,
  1355  		Value: i.Value,
  1356  	}
  1357  
  1358  	if i.Label != nil {
  1359  		target, found := ctx.Labels[*i.Label]
  1360  		if !found {
  1361  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1362  		}
  1363  
  1364  		// Get diff between current instruction and the target
  1365  		inst.Offset = int16(target-index) - 1
  1366  	}
  1367  
  1368  	if i.Offset != nil {
  1369  		inst.Offset = *i.Offset
  1370  	}
  1371  
  1372  	return []Instruction{inst}, nil
  1373  }
  1374  
  1375  type jumpEqual32 struct {
  1376  	Dest   Register `parser:"'if' @Register32 '=' '=' "`
  1377  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  1378  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1379  	Label  *string  `parser:"@Ident )"`
  1380  }
  1381  
  1382  func (i *jumpEqual32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1383  	inst := &JumpEqual32{
  1384  		Dest:  i.Dest,
  1385  		Value: i.Value,
  1386  	}
  1387  
  1388  	if i.Label != nil {
  1389  		target, found := ctx.Labels[*i.Label]
  1390  		if !found {
  1391  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1392  		}
  1393  
  1394  		// Get diff between current instruction and the target
  1395  		inst.Offset = int16(target-index) - 1
  1396  	}
  1397  
  1398  	if i.Offset != nil {
  1399  		inst.Offset = *i.Offset
  1400  	}
  1401  
  1402  	return []Instruction{inst}, nil
  1403  }
  1404  
  1405  type jumpEqualRegister struct {
  1406  	Dest   Register `parser:"'if' @Register64 '=' '=' "`
  1407  	Src    Register `parser:"@Register64"`
  1408  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1409  	Label  *string  `parser:"@Ident )"`
  1410  }
  1411  
  1412  func (i *jumpEqualRegister) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1413  	inst := &JumpEqualRegister{
  1414  		Dest: i.Dest,
  1415  		Src:  i.Src,
  1416  	}
  1417  
  1418  	if i.Label != nil {
  1419  		target, found := ctx.Labels[*i.Label]
  1420  		if !found {
  1421  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1422  		}
  1423  
  1424  		// Get diff between current instruction and the target
  1425  		inst.Offset = int16(target-index) - 1
  1426  	}
  1427  
  1428  	if i.Offset != nil {
  1429  		inst.Offset = *i.Offset
  1430  	}
  1431  
  1432  	return []Instruction{inst}, nil
  1433  }
  1434  
  1435  type jumpEqualRegister32 struct {
  1436  	Dest   Register `parser:"'if' @Register32 '=' '=' "`
  1437  	Src    Register `parser:"@Register32"`
  1438  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1439  	Label  *string  `parser:"@Ident )"`
  1440  }
  1441  
  1442  func (i *jumpEqualRegister32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1443  	inst := &JumpEqualRegister32{
  1444  		Dest: i.Dest,
  1445  		Src:  i.Src,
  1446  	}
  1447  
  1448  	if i.Label != nil {
  1449  		target, found := ctx.Labels[*i.Label]
  1450  		if !found {
  1451  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1452  		}
  1453  
  1454  		// Get diff between current instruction and the target
  1455  		inst.Offset = int16(target-index) - 1
  1456  	}
  1457  
  1458  	if i.Offset != nil {
  1459  		inst.Offset = *i.Offset
  1460  	}
  1461  
  1462  	return []Instruction{inst}, nil
  1463  }
  1464  
  1465  type jumpGreaterThan struct {
  1466  	Dest   Register `parser:"'if' @Register64 '>' "`
  1467  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  1468  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1469  	Label  *string  `parser:"@Ident )"`
  1470  }
  1471  
  1472  func (i *jumpGreaterThan) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1473  	inst := &JumpGreaterThan{
  1474  		Dest:  i.Dest,
  1475  		Value: i.Value,
  1476  	}
  1477  
  1478  	if i.Label != nil {
  1479  		target, found := ctx.Labels[*i.Label]
  1480  		if !found {
  1481  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1482  		}
  1483  
  1484  		// Get diff between current instruction and the target
  1485  		inst.Offset = int16(target-index) - 1
  1486  	}
  1487  
  1488  	if i.Offset != nil {
  1489  		inst.Offset = *i.Offset
  1490  	}
  1491  
  1492  	return []Instruction{inst}, nil
  1493  }
  1494  
  1495  type jumpGreaterThan32 struct {
  1496  	Dest   Register `parser:"'if' @Register32 '>' "`
  1497  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  1498  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1499  	Label  *string  `parser:"@Ident )"`
  1500  }
  1501  
  1502  func (i *jumpGreaterThan32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1503  	inst := &JumpGreaterThan32{
  1504  		Dest:  i.Dest,
  1505  		Value: i.Value,
  1506  	}
  1507  
  1508  	if i.Label != nil {
  1509  		target, found := ctx.Labels[*i.Label]
  1510  		if !found {
  1511  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1512  		}
  1513  
  1514  		// Get diff between current instruction and the target
  1515  		inst.Offset = int16(target-index) - 1
  1516  	}
  1517  
  1518  	if i.Offset != nil {
  1519  		inst.Offset = *i.Offset
  1520  	}
  1521  
  1522  	return []Instruction{inst}, nil
  1523  }
  1524  
  1525  type jumpGreaterThanRegister struct {
  1526  	Dest   Register `parser:"'if' @Register64 '>' "`
  1527  	Src    Register `parser:"@Register64"`
  1528  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1529  	Label  *string  `parser:"@Ident )"`
  1530  }
  1531  
  1532  func (i *jumpGreaterThanRegister) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1533  	inst := &JumpGreaterThanRegister{
  1534  		Dest: i.Dest,
  1535  		Src:  i.Src,
  1536  	}
  1537  
  1538  	if i.Label != nil {
  1539  		target, found := ctx.Labels[*i.Label]
  1540  		if !found {
  1541  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1542  		}
  1543  
  1544  		// Get diff between current instruction and the target
  1545  		inst.Offset = int16(target-index) - 1
  1546  	}
  1547  
  1548  	if i.Offset != nil {
  1549  		inst.Offset = *i.Offset
  1550  	}
  1551  
  1552  	return []Instruction{inst}, nil
  1553  }
  1554  
  1555  type jumpGreaterThanRegister32 struct {
  1556  	Dest   Register `parser:"'if' @Register32 '>' "`
  1557  	Src    Register `parser:"@Register32"`
  1558  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1559  	Label  *string  `parser:"@Ident )"`
  1560  }
  1561  
  1562  func (i *jumpGreaterThanRegister32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1563  	inst := &JumpGreaterThanRegister32{
  1564  		Dest: i.Dest,
  1565  		Src:  i.Src,
  1566  	}
  1567  
  1568  	if i.Label != nil {
  1569  		target, found := ctx.Labels[*i.Label]
  1570  		if !found {
  1571  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1572  		}
  1573  
  1574  		// Get diff between current instruction and the target
  1575  		inst.Offset = int16(target-index) - 1
  1576  	}
  1577  
  1578  	if i.Offset != nil {
  1579  		inst.Offset = *i.Offset
  1580  	}
  1581  
  1582  	return []Instruction{inst}, nil
  1583  }
  1584  
  1585  type jumpGreaterThanEqual struct {
  1586  	Dest   Register `parser:"'if' @Register64 '>' '='"`
  1587  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  1588  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1589  	Label  *string  `parser:"@Ident )"`
  1590  }
  1591  
  1592  func (i *jumpGreaterThanEqual) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1593  	inst := &JumpGreaterThanEqual{
  1594  		Dest:  i.Dest,
  1595  		Value: i.Value,
  1596  	}
  1597  
  1598  	if i.Label != nil {
  1599  		target, found := ctx.Labels[*i.Label]
  1600  		if !found {
  1601  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1602  		}
  1603  
  1604  		// Get diff between current instruction and the target
  1605  		inst.Offset = int16(target-index) - 1
  1606  	}
  1607  
  1608  	if i.Offset != nil {
  1609  		inst.Offset = *i.Offset
  1610  	}
  1611  
  1612  	return []Instruction{inst}, nil
  1613  }
  1614  
  1615  type jumpGreaterThanEqual32 struct {
  1616  	Dest   Register `parser:"'if' @Register32 '>' '='"`
  1617  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  1618  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1619  	Label  *string  `parser:"@Ident )"`
  1620  }
  1621  
  1622  func (i *jumpGreaterThanEqual32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1623  	inst := &JumpGreaterThanEqual32{
  1624  		Dest:  i.Dest,
  1625  		Value: i.Value,
  1626  	}
  1627  
  1628  	if i.Label != nil {
  1629  		target, found := ctx.Labels[*i.Label]
  1630  		if !found {
  1631  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1632  		}
  1633  
  1634  		// Get diff between current instruction and the target
  1635  		inst.Offset = int16(target-index) - 1
  1636  	}
  1637  
  1638  	if i.Offset != nil {
  1639  		inst.Offset = *i.Offset
  1640  	}
  1641  
  1642  	return []Instruction{inst}, nil
  1643  }
  1644  
  1645  type jumpGreaterThanEqualRegister struct {
  1646  	Dest   Register `parser:"'if' @Register64 '>' '='"`
  1647  	Src    Register `parser:"@Register64"`
  1648  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1649  	Label  *string  `parser:"@Ident )"`
  1650  }
  1651  
  1652  func (i *jumpGreaterThanEqualRegister) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1653  	inst := &JumpGreaterThanEqualRegister{
  1654  		Dest: i.Dest,
  1655  		Src:  i.Src,
  1656  	}
  1657  
  1658  	if i.Label != nil {
  1659  		target, found := ctx.Labels[*i.Label]
  1660  		if !found {
  1661  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1662  		}
  1663  
  1664  		// Get diff between current instruction and the target
  1665  		inst.Offset = int16(target-index) - 1
  1666  	}
  1667  
  1668  	if i.Offset != nil {
  1669  		inst.Offset = *i.Offset
  1670  	}
  1671  
  1672  	return []Instruction{inst}, nil
  1673  }
  1674  
  1675  type jumpGreaterThanEqualRegister32 struct {
  1676  	Dest   Register `parser:"'if' @Register32 '>' '=' "`
  1677  	Src    Register `parser:"@Register32"`
  1678  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1679  	Label  *string  `parser:"@Ident )"`
  1680  }
  1681  
  1682  func (i *jumpGreaterThanEqualRegister32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1683  	inst := &JumpGreaterThanEqualRegister32{
  1684  		Dest: i.Dest,
  1685  		Src:  i.Src,
  1686  	}
  1687  
  1688  	if i.Label != nil {
  1689  		target, found := ctx.Labels[*i.Label]
  1690  		if !found {
  1691  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1692  		}
  1693  
  1694  		// Get diff between current instruction and the target
  1695  		inst.Offset = int16(target-index) - 1
  1696  	}
  1697  
  1698  	if i.Offset != nil {
  1699  		inst.Offset = *i.Offset
  1700  	}
  1701  
  1702  	return []Instruction{inst}, nil
  1703  }
  1704  
  1705  type jumpIfAnd struct {
  1706  	Dest   Register `parser:"'if' @Register64 '&' "`
  1707  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  1708  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1709  	Label  *string  `parser:"@Ident )"`
  1710  }
  1711  
  1712  func (i *jumpIfAnd) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1713  	inst := &JumpAnd{
  1714  		Dest:  i.Dest,
  1715  		Value: i.Value,
  1716  	}
  1717  
  1718  	if i.Label != nil {
  1719  		target, found := ctx.Labels[*i.Label]
  1720  		if !found {
  1721  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1722  		}
  1723  
  1724  		// Get diff between current instruction and the target
  1725  		inst.Offset = int16(target-index) - 1
  1726  	}
  1727  
  1728  	if i.Offset != nil {
  1729  		inst.Offset = *i.Offset
  1730  	}
  1731  
  1732  	return []Instruction{inst}, nil
  1733  }
  1734  
  1735  type jumpIfAnd32 struct {
  1736  	Dest   Register `parser:"'if' @Register32 '&' "`
  1737  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  1738  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1739  	Label  *string  `parser:"@Ident )"`
  1740  }
  1741  
  1742  func (i *jumpIfAnd32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1743  	inst := &JumpAnd32{
  1744  		Dest:  i.Dest,
  1745  		Value: i.Value,
  1746  	}
  1747  
  1748  	if i.Label != nil {
  1749  		target, found := ctx.Labels[*i.Label]
  1750  		if !found {
  1751  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1752  		}
  1753  
  1754  		// Get diff between current instruction and the target
  1755  		inst.Offset = int16(target-index) - 1
  1756  	}
  1757  
  1758  	if i.Offset != nil {
  1759  		inst.Offset = *i.Offset
  1760  	}
  1761  
  1762  	return []Instruction{inst}, nil
  1763  }
  1764  
  1765  type jumpIfAndRegister struct {
  1766  	Dest   Register `parser:"'if' @Register64 '&' "`
  1767  	Src    Register `parser:"@Register64"`
  1768  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1769  	Label  *string  `parser:"@Ident )"`
  1770  }
  1771  
  1772  func (i *jumpIfAndRegister) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1773  	inst := &JumpAndRegister{
  1774  		Dest: i.Dest,
  1775  		Src:  i.Src,
  1776  	}
  1777  
  1778  	if i.Label != nil {
  1779  		target, found := ctx.Labels[*i.Label]
  1780  		if !found {
  1781  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1782  		}
  1783  
  1784  		// Get diff between current instruction and the target
  1785  		inst.Offset = int16(target-index) - 1
  1786  	}
  1787  
  1788  	if i.Offset != nil {
  1789  		inst.Offset = *i.Offset
  1790  	}
  1791  
  1792  	return []Instruction{inst}, nil
  1793  }
  1794  
  1795  type jumpIfAndRegister32 struct {
  1796  	Dest   Register `parser:"'if' @Register32 '&' "`
  1797  	Src    Register `parser:"@Register32"`
  1798  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1799  	Label  *string  `parser:"@Ident )"`
  1800  }
  1801  
  1802  func (i *jumpIfAndRegister32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1803  	inst := &JumpAndRegister32{
  1804  		Dest: i.Dest,
  1805  		Src:  i.Src,
  1806  	}
  1807  
  1808  	if i.Label != nil {
  1809  		target, found := ctx.Labels[*i.Label]
  1810  		if !found {
  1811  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1812  		}
  1813  
  1814  		// Get diff between current instruction and the target
  1815  		inst.Offset = int16(target-index) - 1
  1816  	}
  1817  
  1818  	if i.Offset != nil {
  1819  		inst.Offset = *i.Offset
  1820  	}
  1821  
  1822  	return []Instruction{inst}, nil
  1823  }
  1824  
  1825  type jumpIfNotEqual struct {
  1826  	Dest   Register `parser:"'if' @Register64 '!' '=' "`
  1827  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  1828  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1829  	Label  *string  `parser:"@Ident )"`
  1830  }
  1831  
  1832  func (i *jumpIfNotEqual) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1833  	inst := &JumpNotEqual{
  1834  		Dest:  i.Dest,
  1835  		Value: i.Value,
  1836  	}
  1837  
  1838  	if i.Label != nil {
  1839  		target, found := ctx.Labels[*i.Label]
  1840  		if !found {
  1841  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1842  		}
  1843  
  1844  		// Get diff between current instruction and the target
  1845  		inst.Offset = int16(target-index) - 1
  1846  	}
  1847  
  1848  	if i.Offset != nil {
  1849  		inst.Offset = *i.Offset
  1850  	}
  1851  
  1852  	return []Instruction{inst}, nil
  1853  }
  1854  
  1855  type jumpIfNotEqual32 struct {
  1856  	Dest   Register `parser:"'if' @Register32 '!' '=' "`
  1857  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  1858  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1859  	Label  *string  `parser:"@Ident )"`
  1860  }
  1861  
  1862  func (i *jumpIfNotEqual32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1863  	inst := &JumpNotEqual32{
  1864  		Dest:  i.Dest,
  1865  		Value: i.Value,
  1866  	}
  1867  
  1868  	if i.Label != nil {
  1869  		target, found := ctx.Labels[*i.Label]
  1870  		if !found {
  1871  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1872  		}
  1873  
  1874  		// Get diff between current instruction and the target
  1875  		inst.Offset = int16(target-index) - 1
  1876  	}
  1877  
  1878  	if i.Offset != nil {
  1879  		inst.Offset = *i.Offset
  1880  	}
  1881  
  1882  	return []Instruction{inst}, nil
  1883  }
  1884  
  1885  type jumpIfNotEqualRegister struct {
  1886  	Dest   Register `parser:"'if' @Register64 '!' '=' "`
  1887  	Src    Register `parser:"@Register64"`
  1888  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1889  	Label  *string  `parser:"@Ident )"`
  1890  }
  1891  
  1892  func (i *jumpIfNotEqualRegister) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1893  	inst := &JumpNotEqualRegister{
  1894  		Dest: i.Dest,
  1895  		Src:  i.Src,
  1896  	}
  1897  
  1898  	if i.Label != nil {
  1899  		target, found := ctx.Labels[*i.Label]
  1900  		if !found {
  1901  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1902  		}
  1903  
  1904  		// Get diff between current instruction and the target
  1905  		inst.Offset = int16(target-index) - 1
  1906  	}
  1907  
  1908  	if i.Offset != nil {
  1909  		inst.Offset = *i.Offset
  1910  	}
  1911  
  1912  	return []Instruction{inst}, nil
  1913  }
  1914  
  1915  type jumpIfNotEqualRegister32 struct {
  1916  	Dest   Register `parser:"'if' @Register32 '!' '=' "`
  1917  	Src    Register `parser:"@Register32"`
  1918  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1919  	Label  *string  `parser:"@Ident )"`
  1920  }
  1921  
  1922  func (i *jumpIfNotEqualRegister32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1923  	inst := &JumpNotEqualRegister32{
  1924  		Dest: i.Dest,
  1925  		Src:  i.Src,
  1926  	}
  1927  
  1928  	if i.Label != nil {
  1929  		target, found := ctx.Labels[*i.Label]
  1930  		if !found {
  1931  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1932  		}
  1933  
  1934  		// Get diff between current instruction and the target
  1935  		inst.Offset = int16(target-index) - 1
  1936  	}
  1937  
  1938  	if i.Offset != nil {
  1939  		inst.Offset = *i.Offset
  1940  	}
  1941  
  1942  	return []Instruction{inst}, nil
  1943  }
  1944  
  1945  type jumpSignedGreaterThan struct {
  1946  	Dest   Register `parser:"'if' @Register64 's' '>' "`
  1947  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  1948  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1949  	Label  *string  `parser:"@Ident )"`
  1950  }
  1951  
  1952  func (i *jumpSignedGreaterThan) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1953  	inst := &JumpSignedGreaterThan{
  1954  		Dest:  i.Dest,
  1955  		Value: i.Value,
  1956  	}
  1957  
  1958  	if i.Label != nil {
  1959  		target, found := ctx.Labels[*i.Label]
  1960  		if !found {
  1961  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1962  		}
  1963  
  1964  		// Get diff between current instruction and the target
  1965  		inst.Offset = int16(target-index) - 1
  1966  	}
  1967  
  1968  	if i.Offset != nil {
  1969  		inst.Offset = *i.Offset
  1970  	}
  1971  
  1972  	return []Instruction{inst}, nil
  1973  }
  1974  
  1975  type jumpSignedGreaterThan32 struct {
  1976  	Dest   Register `parser:"'if' @Register32 's' '>' "`
  1977  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  1978  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  1979  	Label  *string  `parser:"@Ident )"`
  1980  }
  1981  
  1982  func (i *jumpSignedGreaterThan32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  1983  	inst := &JumpSignedGreaterThan32{
  1984  		Dest:  i.Dest,
  1985  		Value: i.Value,
  1986  	}
  1987  
  1988  	if i.Label != nil {
  1989  		target, found := ctx.Labels[*i.Label]
  1990  		if !found {
  1991  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  1992  		}
  1993  
  1994  		// Get diff between current instruction and the target
  1995  		inst.Offset = int16(target-index) - 1
  1996  	}
  1997  
  1998  	if i.Offset != nil {
  1999  		inst.Offset = *i.Offset
  2000  	}
  2001  
  2002  	return []Instruction{inst}, nil
  2003  }
  2004  
  2005  type jumpSignedGreaterThanRegister struct {
  2006  	Dest   Register `parser:"'if' @Register64 's' '>' "`
  2007  	Src    Register `parser:"@Register64"`
  2008  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2009  	Label  *string  `parser:"@Ident )"`
  2010  }
  2011  
  2012  func (i *jumpSignedGreaterThanRegister) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2013  	inst := &JumpSignedGreaterThanRegister{
  2014  		Dest: i.Dest,
  2015  		Src:  i.Src,
  2016  	}
  2017  
  2018  	if i.Label != nil {
  2019  		target, found := ctx.Labels[*i.Label]
  2020  		if !found {
  2021  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2022  		}
  2023  
  2024  		// Get diff between current instruction and the target
  2025  		inst.Offset = int16(target-index) - 1
  2026  	}
  2027  
  2028  	if i.Offset != nil {
  2029  		inst.Offset = *i.Offset
  2030  	}
  2031  
  2032  	return []Instruction{inst}, nil
  2033  }
  2034  
  2035  type jumpSignedGreaterThanRegister32 struct {
  2036  	Dest   Register `parser:"'if' @Register32 's' '>' "`
  2037  	Src    Register `parser:"@Register32"`
  2038  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2039  	Label  *string  `parser:"@Ident )"`
  2040  }
  2041  
  2042  func (i *jumpSignedGreaterThanRegister32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2043  	inst := &JumpSignedGreaterThanRegister32{
  2044  		Dest: i.Dest,
  2045  		Src:  i.Src,
  2046  	}
  2047  
  2048  	if i.Label != nil {
  2049  		target, found := ctx.Labels[*i.Label]
  2050  		if !found {
  2051  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2052  		}
  2053  
  2054  		// Get diff between current instruction and the target
  2055  		inst.Offset = int16(target-index) - 1
  2056  	}
  2057  
  2058  	if i.Offset != nil {
  2059  		inst.Offset = *i.Offset
  2060  	}
  2061  
  2062  	return []Instruction{inst}, nil
  2063  }
  2064  
  2065  type jumpSignedGreaterThanOrEqual struct {
  2066  	Dest   Register `parser:"'if' @Register64 's' '>' '='"`
  2067  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  2068  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2069  	Label  *string  `parser:"@Ident )"`
  2070  }
  2071  
  2072  func (i *jumpSignedGreaterThanOrEqual) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2073  	inst := &JumpSignedGreaterThanOrEqual{
  2074  		Dest:  i.Dest,
  2075  		Value: i.Value,
  2076  	}
  2077  
  2078  	if i.Label != nil {
  2079  		target, found := ctx.Labels[*i.Label]
  2080  		if !found {
  2081  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2082  		}
  2083  
  2084  		// Get diff between current instruction and the target
  2085  		inst.Offset = int16(target-index) - 1
  2086  	}
  2087  
  2088  	if i.Offset != nil {
  2089  		inst.Offset = *i.Offset
  2090  	}
  2091  
  2092  	return []Instruction{inst}, nil
  2093  }
  2094  
  2095  type jumpSignedGreaterThanOrEqual32 struct {
  2096  	Dest   Register `parser:"'if' @Register32 's' '>' '='"`
  2097  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  2098  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2099  	Label  *string  `parser:"@Ident )"`
  2100  }
  2101  
  2102  func (i *jumpSignedGreaterThanOrEqual32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2103  	inst := &JumpSignedGreaterThanOrEqual32{
  2104  		Dest:  i.Dest,
  2105  		Value: i.Value,
  2106  	}
  2107  
  2108  	if i.Label != nil {
  2109  		target, found := ctx.Labels[*i.Label]
  2110  		if !found {
  2111  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2112  		}
  2113  
  2114  		// Get diff between current instruction and the target
  2115  		inst.Offset = int16(target-index) - 1
  2116  	}
  2117  
  2118  	if i.Offset != nil {
  2119  		inst.Offset = *i.Offset
  2120  	}
  2121  
  2122  	return []Instruction{inst}, nil
  2123  }
  2124  
  2125  type jumpSignedGreaterThanOrEqualRegister struct {
  2126  	Dest   Register `parser:"'if' @Register64 's' '>' '='"`
  2127  	Src    Register `parser:"@Register64"`
  2128  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2129  	Label  *string  `parser:"@Ident )"`
  2130  }
  2131  
  2132  func (i *jumpSignedGreaterThanOrEqualRegister) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2133  	inst := &JumpSignedGreaterThanOrEqualRegister{
  2134  		Dest: i.Dest,
  2135  		Src:  i.Src,
  2136  	}
  2137  
  2138  	if i.Label != nil {
  2139  		target, found := ctx.Labels[*i.Label]
  2140  		if !found {
  2141  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2142  		}
  2143  
  2144  		// Get diff between current instruction and the target
  2145  		inst.Offset = int16(target-index) - 1
  2146  	}
  2147  
  2148  	if i.Offset != nil {
  2149  		inst.Offset = *i.Offset
  2150  	}
  2151  
  2152  	return []Instruction{inst}, nil
  2153  }
  2154  
  2155  type jumpSignedGreaterThanOrEqualRegister32 struct {
  2156  	Dest   Register `parser:"'if' @Register32 's' '>' '=' "`
  2157  	Src    Register `parser:"@Register32"`
  2158  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2159  	Label  *string  `parser:"@Ident )"`
  2160  }
  2161  
  2162  func (i *jumpSignedGreaterThanOrEqualRegister32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2163  	inst := &JumpSignedGreaterThanOrEqualRegister32{
  2164  		Dest: i.Dest,
  2165  		Src:  i.Src,
  2166  	}
  2167  
  2168  	if i.Label != nil {
  2169  		target, found := ctx.Labels[*i.Label]
  2170  		if !found {
  2171  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2172  		}
  2173  
  2174  		// Get diff between current instruction and the target
  2175  		inst.Offset = int16(target-index) - 1
  2176  	}
  2177  
  2178  	if i.Offset != nil {
  2179  		inst.Offset = *i.Offset
  2180  	}
  2181  
  2182  	return []Instruction{inst}, nil
  2183  }
  2184  
  2185  type jumpSignedSmallerThan struct {
  2186  	Dest   Register `parser:"'if' @Register64 's' '<' "`
  2187  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  2188  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2189  	Label  *string  `parser:"@Ident )"`
  2190  }
  2191  
  2192  func (i *jumpSignedSmallerThan) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2193  	inst := &JumpSignedSmallerThan{
  2194  		Dest:  i.Dest,
  2195  		Value: i.Value,
  2196  	}
  2197  
  2198  	if i.Label != nil {
  2199  		target, found := ctx.Labels[*i.Label]
  2200  		if !found {
  2201  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2202  		}
  2203  
  2204  		// Get diff between current instruction and the target
  2205  		inst.Offset = int16(target-index) - 1
  2206  	}
  2207  
  2208  	if i.Offset != nil {
  2209  		inst.Offset = *i.Offset
  2210  	}
  2211  
  2212  	return []Instruction{inst}, nil
  2213  }
  2214  
  2215  type jumpSignedSmallerThan32 struct {
  2216  	Dest   Register `parser:"'if' @Register32 's' '<' "`
  2217  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  2218  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2219  	Label  *string  `parser:"@Ident )"`
  2220  }
  2221  
  2222  func (i *jumpSignedSmallerThan32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2223  	inst := &JumpSignedSmallerThan32{
  2224  		Dest:  i.Dest,
  2225  		Value: i.Value,
  2226  	}
  2227  
  2228  	if i.Label != nil {
  2229  		target, found := ctx.Labels[*i.Label]
  2230  		if !found {
  2231  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2232  		}
  2233  
  2234  		// Get diff between current instruction and the target
  2235  		inst.Offset = int16(target-index) - 1
  2236  	}
  2237  
  2238  	if i.Offset != nil {
  2239  		inst.Offset = *i.Offset
  2240  	}
  2241  
  2242  	return []Instruction{inst}, nil
  2243  }
  2244  
  2245  type jumpSignedSmallerThanRegister struct {
  2246  	Dest   Register `parser:"'if' @Register64 's' '<' "`
  2247  	Src    Register `parser:"@Register64"`
  2248  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2249  	Label  *string  `parser:"@Ident )"`
  2250  }
  2251  
  2252  func (i *jumpSignedSmallerThanRegister) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2253  	inst := &JumpSignedSmallerThanRegister{
  2254  		Dest: i.Dest,
  2255  		Src:  i.Src,
  2256  	}
  2257  
  2258  	if i.Label != nil {
  2259  		target, found := ctx.Labels[*i.Label]
  2260  		if !found {
  2261  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2262  		}
  2263  
  2264  		// Get diff between current instruction and the target
  2265  		inst.Offset = int16(target-index) - 1
  2266  	}
  2267  
  2268  	if i.Offset != nil {
  2269  		inst.Offset = *i.Offset
  2270  	}
  2271  
  2272  	return []Instruction{inst}, nil
  2273  }
  2274  
  2275  type jumpSignedSmallerThanRegister32 struct {
  2276  	Dest   Register `parser:"'if' @Register32 's' '<' "`
  2277  	Src    Register `parser:"@Register32"`
  2278  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2279  	Label  *string  `parser:"@Ident )"`
  2280  }
  2281  
  2282  func (i *jumpSignedSmallerThanRegister32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2283  	inst := &JumpSignedSmallerThanRegister32{
  2284  		Dest: i.Dest,
  2285  		Src:  i.Src,
  2286  	}
  2287  
  2288  	if i.Label != nil {
  2289  		target, found := ctx.Labels[*i.Label]
  2290  		if !found {
  2291  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2292  		}
  2293  
  2294  		// Get diff between current instruction and the target
  2295  		inst.Offset = int16(target-index) - 1
  2296  	}
  2297  
  2298  	if i.Offset != nil {
  2299  		inst.Offset = *i.Offset
  2300  	}
  2301  
  2302  	return []Instruction{inst}, nil
  2303  }
  2304  
  2305  type jumpSignedSmallerThanOrEqual struct {
  2306  	Dest   Register `parser:"'if' @Register64 's' '<' '='"`
  2307  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  2308  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2309  	Label  *string  `parser:"@Ident )"`
  2310  }
  2311  
  2312  func (i *jumpSignedSmallerThanOrEqual) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2313  	inst := &JumpSignedSmallerThanOrEqual{
  2314  		Dest:  i.Dest,
  2315  		Value: i.Value,
  2316  	}
  2317  
  2318  	if i.Label != nil {
  2319  		target, found := ctx.Labels[*i.Label]
  2320  		if !found {
  2321  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2322  		}
  2323  
  2324  		// Get diff between current instruction and the target
  2325  		inst.Offset = int16(target-index) - 1
  2326  	}
  2327  
  2328  	if i.Offset != nil {
  2329  		inst.Offset = *i.Offset
  2330  	}
  2331  
  2332  	return []Instruction{inst}, nil
  2333  }
  2334  
  2335  type jumpSignedSmallerThanOrEqual32 struct {
  2336  	Dest   Register `parser:"'if' @Register32 's' '<' '='"`
  2337  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  2338  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2339  	Label  *string  `parser:"@Ident )"`
  2340  }
  2341  
  2342  func (i *jumpSignedSmallerThanOrEqual32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2343  	inst := &JumpSignedSmallerThanOrEqual32{
  2344  		Dest:  i.Dest,
  2345  		Value: i.Value,
  2346  	}
  2347  
  2348  	if i.Label != nil {
  2349  		target, found := ctx.Labels[*i.Label]
  2350  		if !found {
  2351  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2352  		}
  2353  
  2354  		// Get diff between current instruction and the target
  2355  		inst.Offset = int16(target-index) - 1
  2356  	}
  2357  
  2358  	if i.Offset != nil {
  2359  		inst.Offset = *i.Offset
  2360  	}
  2361  
  2362  	return []Instruction{inst}, nil
  2363  }
  2364  
  2365  type jumpSignedSmallerThanOrEqualRegister struct {
  2366  	Dest   Register `parser:"'if' @Register64 's' '<' '='"`
  2367  	Src    Register `parser:"@Register64"`
  2368  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2369  	Label  *string  `parser:"@Ident )"`
  2370  }
  2371  
  2372  func (i *jumpSignedSmallerThanOrEqualRegister) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2373  	inst := &JumpSignedSmallerThanOrEqualRegister{
  2374  		Dest: i.Dest,
  2375  		Src:  i.Src,
  2376  	}
  2377  
  2378  	if i.Label != nil {
  2379  		target, found := ctx.Labels[*i.Label]
  2380  		if !found {
  2381  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2382  		}
  2383  
  2384  		// Get diff between current instruction and the target
  2385  		inst.Offset = int16(target-index) - 1
  2386  	}
  2387  
  2388  	if i.Offset != nil {
  2389  		inst.Offset = *i.Offset
  2390  	}
  2391  
  2392  	return []Instruction{inst}, nil
  2393  }
  2394  
  2395  type jumpSignedSmallerThanOrEqualRegister32 struct {
  2396  	Dest   Register `parser:"'if' @Register32 's' '<' '=' "`
  2397  	Src    Register `parser:"@Register32"`
  2398  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2399  	Label  *string  `parser:"@Ident )"`
  2400  }
  2401  
  2402  func (i *jumpSignedSmallerThanOrEqualRegister32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2403  	inst := &JumpSignedSmallerThanOrEqualRegister32{
  2404  		Dest: i.Dest,
  2405  		Src:  i.Src,
  2406  	}
  2407  
  2408  	if i.Label != nil {
  2409  		target, found := ctx.Labels[*i.Label]
  2410  		if !found {
  2411  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2412  		}
  2413  
  2414  		// Get diff between current instruction and the target
  2415  		inst.Offset = int16(target-index) - 1
  2416  	}
  2417  
  2418  	if i.Offset != nil {
  2419  		inst.Offset = *i.Offset
  2420  	}
  2421  
  2422  	return []Instruction{inst}, nil
  2423  }
  2424  
  2425  type jumpSmallerThan struct {
  2426  	Dest   Register `parser:"'if' @Register64 '<' "`
  2427  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  2428  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2429  	Label  *string  `parser:"@Ident )"`
  2430  }
  2431  
  2432  func (i *jumpSmallerThan) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2433  	inst := &JumpSmallerThan{
  2434  		Dest:  i.Dest,
  2435  		Value: i.Value,
  2436  	}
  2437  
  2438  	if i.Label != nil {
  2439  		target, found := ctx.Labels[*i.Label]
  2440  		if !found {
  2441  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2442  		}
  2443  
  2444  		// Get diff between current instruction and the target
  2445  		inst.Offset = int16(target-index) - 1
  2446  	}
  2447  
  2448  	if i.Offset != nil {
  2449  		inst.Offset = *i.Offset
  2450  	}
  2451  
  2452  	return []Instruction{inst}, nil
  2453  }
  2454  
  2455  type jumpSmallerThan32 struct {
  2456  	Dest   Register `parser:"'if' @Register32 '<' "`
  2457  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  2458  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2459  	Label  *string  `parser:"@Ident )"`
  2460  }
  2461  
  2462  func (i *jumpSmallerThan32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2463  	inst := &JumpSmallerThan32{
  2464  		Dest:  i.Dest,
  2465  		Value: i.Value,
  2466  	}
  2467  
  2468  	if i.Label != nil {
  2469  		target, found := ctx.Labels[*i.Label]
  2470  		if !found {
  2471  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2472  		}
  2473  
  2474  		// Get diff between current instruction and the target
  2475  		inst.Offset = int16(target-index) - 1
  2476  	}
  2477  
  2478  	if i.Offset != nil {
  2479  		inst.Offset = *i.Offset
  2480  	}
  2481  
  2482  	return []Instruction{inst}, nil
  2483  }
  2484  
  2485  type jumpSmallerThanRegister struct {
  2486  	Dest   Register `parser:"'if' @Register64 '<' "`
  2487  	Src    Register `parser:"@Register64"`
  2488  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2489  	Label  *string  `parser:"@Ident )"`
  2490  }
  2491  
  2492  func (i *jumpSmallerThanRegister) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2493  	inst := &JumpSmallerThanRegister{
  2494  		Dest: i.Dest,
  2495  		Src:  i.Src,
  2496  	}
  2497  
  2498  	if i.Label != nil {
  2499  		target, found := ctx.Labels[*i.Label]
  2500  		if !found {
  2501  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2502  		}
  2503  
  2504  		// Get diff between current instruction and the target
  2505  		inst.Offset = int16(target-index) - 1
  2506  	}
  2507  
  2508  	if i.Offset != nil {
  2509  		inst.Offset = *i.Offset
  2510  	}
  2511  
  2512  	return []Instruction{inst}, nil
  2513  }
  2514  
  2515  type jumpSmallerThanRegister32 struct {
  2516  	Dest   Register `parser:"'if' @Register32 '<' "`
  2517  	Src    Register `parser:"@Register32"`
  2518  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2519  	Label  *string  `parser:"@Ident )"`
  2520  }
  2521  
  2522  func (i *jumpSmallerThanRegister32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2523  	inst := &JumpSmallerThanRegister32{
  2524  		Dest: i.Dest,
  2525  		Src:  i.Src,
  2526  	}
  2527  
  2528  	if i.Label != nil {
  2529  		target, found := ctx.Labels[*i.Label]
  2530  		if !found {
  2531  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2532  		}
  2533  
  2534  		// Get diff between current instruction and the target
  2535  		inst.Offset = int16(target-index) - 1
  2536  	}
  2537  
  2538  	if i.Offset != nil {
  2539  		inst.Offset = *i.Offset
  2540  	}
  2541  
  2542  	return []Instruction{inst}, nil
  2543  }
  2544  
  2545  type jumpSmallerThanEqual struct {
  2546  	Dest   Register `parser:"'if' @Register64 '<' '='"`
  2547  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  2548  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2549  	Label  *string  `parser:"@Ident )"`
  2550  }
  2551  
  2552  func (i *jumpSmallerThanEqual) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2553  	inst := &JumpSmallerThanEqual{
  2554  		Dest:  i.Dest,
  2555  		Value: i.Value,
  2556  	}
  2557  
  2558  	if i.Label != nil {
  2559  		target, found := ctx.Labels[*i.Label]
  2560  		if !found {
  2561  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2562  		}
  2563  
  2564  		// Get diff between current instruction and the target
  2565  		inst.Offset = int16(target-index) - 1
  2566  	}
  2567  
  2568  	if i.Offset != nil {
  2569  		inst.Offset = *i.Offset
  2570  	}
  2571  
  2572  	return []Instruction{inst}, nil
  2573  }
  2574  
  2575  type jumpSmallerThanEqual32 struct {
  2576  	Dest   Register `parser:"'if' @Register32 '<' '='"`
  2577  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  2578  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2579  	Label  *string  `parser:"@Ident )"`
  2580  }
  2581  
  2582  func (i *jumpSmallerThanEqual32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2583  	inst := &JumpSmallerThanEqual32{
  2584  		Dest:  i.Dest,
  2585  		Value: i.Value,
  2586  	}
  2587  
  2588  	if i.Label != nil {
  2589  		target, found := ctx.Labels[*i.Label]
  2590  		if !found {
  2591  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2592  		}
  2593  
  2594  		// Get diff between current instruction and the target
  2595  		inst.Offset = int16(target-index) - 1
  2596  	}
  2597  
  2598  	if i.Offset != nil {
  2599  		inst.Offset = *i.Offset
  2600  	}
  2601  
  2602  	return []Instruction{inst}, nil
  2603  }
  2604  
  2605  type jumpSmallerThanEqualRegister struct {
  2606  	Dest   Register `parser:"'if' @Register64 '<' '='"`
  2607  	Src    Register `parser:"@Register64"`
  2608  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2609  	Label  *string  `parser:"@Ident )"`
  2610  }
  2611  
  2612  func (i *jumpSmallerThanEqualRegister) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2613  	inst := &JumpSmallerThanEqualRegister{
  2614  		Dest: i.Dest,
  2615  		Src:  i.Src,
  2616  	}
  2617  
  2618  	if i.Label != nil {
  2619  		target, found := ctx.Labels[*i.Label]
  2620  		if !found {
  2621  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2622  		}
  2623  
  2624  		// Get diff between current instruction and the target
  2625  		inst.Offset = int16(target-index) - 1
  2626  	}
  2627  
  2628  	if i.Offset != nil {
  2629  		inst.Offset = *i.Offset
  2630  	}
  2631  
  2632  	return []Instruction{inst}, nil
  2633  }
  2634  
  2635  type jumpSmallerThanEqualRegister32 struct {
  2636  	Dest   Register `parser:"'if' @Register32 '<' '=' "`
  2637  	Src    Register `parser:"@Register32"`
  2638  	Offset *int16   `parser:"'goto' (@(('+'|'-')? Number) |"`
  2639  	Label  *string  `parser:"@Ident )"`
  2640  }
  2641  
  2642  func (i *jumpSmallerThanEqualRegister32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2643  	inst := &JumpSmallerThanEqualRegister32{
  2644  		Dest: i.Dest,
  2645  		Src:  i.Src,
  2646  	}
  2647  
  2648  	if i.Label != nil {
  2649  		target, found := ctx.Labels[*i.Label]
  2650  		if !found {
  2651  			return nil, fmt.Errorf("invalid label '%s' at instruction %d", *i.Label, index)
  2652  		}
  2653  
  2654  		// Get diff between current instruction and the target
  2655  		inst.Offset = int16(target-index) - 1
  2656  	}
  2657  
  2658  	if i.Offset != nil {
  2659  		inst.Offset = *i.Offset
  2660  	}
  2661  
  2662  	return []Instruction{inst}, nil
  2663  }
  2664  
  2665  type loadConstant64bit struct {
  2666  	Dest  Register `parser:"@Register64 '='"`
  2667  	Label *string  `parser:"(@Ident |"`
  2668  	Value *int64   `parser:"@Number) 'll'"`
  2669  }
  2670  
  2671  func (i *loadConstant64bit) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2672  	ld := &LoadConstant64bit{
  2673  		Dest: i.Dest,
  2674  	}
  2675  
  2676  	if i.Value != nil {
  2677  		val := uint64(*i.Value)
  2678  		ld.Val2 = uint32((val >> 32) & 0xFFFFFFFF)
  2679  		ld.Val1 = uint32(val & 0xFFFFFFFF)
  2680  	}
  2681  
  2682  	// Since the LD instruction will generate 2 eBPF instructions, we also create the Nop instructions
  2683  	// which will generate no eBPF instructions. So the amount of Instructions and eBPF instructions
  2684  	// stay the same, makes live easier while calclulating offsets and such.
  2685  	return []Instruction{ld, &Nop{}}, nil
  2686  }
  2687  
  2688  type loadMemory struct {
  2689  	Dst    Register `parser:"@Register64 '='"`
  2690  	Size   Size     `parser:"'*' '(' @Ident '*' ')' '('"`
  2691  	Src    Register `parser:"@Register64"`
  2692  	Offset int16    `parser:"@(('+'|'-') Number) ')'"`
  2693  }
  2694  
  2695  func (i *loadMemory) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2696  	return []Instruction{&LoadMemory{
  2697  		Dest:   i.Dst,
  2698  		Size:   i.Size,
  2699  		Src:    i.Src,
  2700  		Offset: i.Offset,
  2701  	}}, nil
  2702  }
  2703  
  2704  // r0 = ntohl((u8) (((struct sk_buff *) r6)->data[r1]))
  2705  type loadSocketBuf struct {
  2706  	// nolint:lll // can't multi-line struct tags
  2707  	Size   Size     `parser:"'r0' '=' 'ntohl' '(' '(' @Ident ')' '(' '(' '(' 'struct' 'sk_buff' '*' ')' 'r6' ')' '-' '>' 'data' '['"`
  2708  	Src    Register `parser:"@Register64"`
  2709  	Offset int32    `parser:"@(('+'|'-') Number) ']' ')' ')'"`
  2710  }
  2711  
  2712  func (i *loadSocketBuf) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2713  	return []Instruction{&LoadSocketBuf{
  2714  		Size:   i.Size,
  2715  		Src:    i.Src,
  2716  		Offset: i.Offset,
  2717  	}}, nil
  2718  }
  2719  
  2720  // r0 = ntohl((u8) (((struct sk_buff *) r6)->data[456]))
  2721  type loadSocketBufConstant struct {
  2722  	// nolint:lll // can't multi-line struct tags
  2723  	Size  Size  `parser:"'r0' '=' 'ntohl' '(' '(' @Ident ')' '(' '(' '(' 'struct' 'sk_buff' '*' ')' 'r6' ')' '-' '>' 'data' '['"`
  2724  	Value int32 `parser:"@Number ']' ')' ')'"`
  2725  }
  2726  
  2727  func (i *loadSocketBufConstant) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2728  	return []Instruction{&LoadSocketBufConstant{
  2729  		Size:  i.Size,
  2730  		Value: i.Value,
  2731  	}}, nil
  2732  }
  2733  
  2734  type lsh32 struct {
  2735  	Dst   Register `parser:"@Register32 '<' '<' '='"`
  2736  	Value int32    `parser:"@(('+'|'-')? Number)"`
  2737  }
  2738  
  2739  func (i *lsh32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2740  	return []Instruction{&Lsh32{
  2741  		Dest:  i.Dst,
  2742  		Value: i.Value,
  2743  	}}, nil
  2744  }
  2745  
  2746  type lsh32Register struct {
  2747  	Dst Register `parser:"@Register32 '<' '<' '='"`
  2748  	Src Register `parser:"@Register32"`
  2749  }
  2750  
  2751  func (i *lsh32Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2752  	return []Instruction{&Lsh32Register{
  2753  		Dest: i.Dst,
  2754  		Src:  i.Src,
  2755  	}}, nil
  2756  }
  2757  
  2758  type lsh64 struct {
  2759  	Dst   Register `parser:"@Register64 '<' '<' '='"`
  2760  	Value int32    `parser:"@(('+'|'-')? Number)"`
  2761  }
  2762  
  2763  func (i *lsh64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2764  	return []Instruction{&Lsh64{
  2765  		Dest:  i.Dst,
  2766  		Value: i.Value,
  2767  	}}, nil
  2768  }
  2769  
  2770  type lsh64Register struct {
  2771  	Dst Register `parser:"@Register64 '<' '<' '='"`
  2772  	Src Register `parser:"@Register64"`
  2773  }
  2774  
  2775  func (i *lsh64Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2776  	return []Instruction{&Lsh64Register{
  2777  		Dest: i.Dst,
  2778  		Src:  i.Src,
  2779  	}}, nil
  2780  }
  2781  
  2782  type mod32 struct {
  2783  	Dst   Register `parser:"@Register32 '%' '='"`
  2784  	Value int32    `parser:"@(('+'|'-')? Number)"`
  2785  }
  2786  
  2787  func (i *mod32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2788  	return []Instruction{&Mod32{
  2789  		Dest:  i.Dst,
  2790  		Value: i.Value,
  2791  	}}, nil
  2792  }
  2793  
  2794  type mod32Register struct {
  2795  	Dst Register `parser:"@Register32 '%' '='"`
  2796  	Src Register `parser:"@Register32"`
  2797  }
  2798  
  2799  func (i *mod32Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2800  	return []Instruction{&Mod32Register{
  2801  		Dest: i.Dst,
  2802  		Src:  i.Src,
  2803  	}}, nil
  2804  }
  2805  
  2806  type mod64 struct {
  2807  	Dst   Register `parser:"@Register64 '%' '='"`
  2808  	Value int32    `parser:"@(('+'|'-')? Number)"`
  2809  }
  2810  
  2811  func (i *mod64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2812  	return []Instruction{&Mod64{
  2813  		Dest:  i.Dst,
  2814  		Value: i.Value,
  2815  	}}, nil
  2816  }
  2817  
  2818  type mod64Register struct {
  2819  	Dst Register `parser:"@Register64 '%' '='"`
  2820  	Src Register `parser:"@Register64"`
  2821  }
  2822  
  2823  func (i *mod64Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2824  	return []Instruction{&Mod64Register{
  2825  		Dest: i.Dst,
  2826  		Src:  i.Src,
  2827  	}}, nil
  2828  }
  2829  
  2830  type mov32 struct {
  2831  	Dst   Register `parser:"@Register32 '='"`
  2832  	Value int32    `parser:"@(('+'|'-')? Number)"`
  2833  }
  2834  
  2835  func (i *mov32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2836  	return []Instruction{&Mov32{
  2837  		Dest:  i.Dst,
  2838  		Value: i.Value,
  2839  	}}, nil
  2840  }
  2841  
  2842  type mov32Register struct {
  2843  	Dst Register `parser:"@Register32 '='"`
  2844  	Src Register `parser:"@Register32"`
  2845  }
  2846  
  2847  func (i *mov32Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2848  	return []Instruction{&Mov32Register{
  2849  		Dest: i.Dst,
  2850  		Src:  i.Src,
  2851  	}}, nil
  2852  }
  2853  
  2854  type mov64 struct {
  2855  	Dst   Register `parser:"@Register64 '='"`
  2856  	Value int32    `parser:"@(('+'|'-')? Number)"`
  2857  }
  2858  
  2859  func (i *mov64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2860  	return []Instruction{&Mov64{
  2861  		Dest:  i.Dst,
  2862  		Value: i.Value,
  2863  	}}, nil
  2864  }
  2865  
  2866  type mov64Register struct {
  2867  	Dst Register `parser:"@Register64 '='"`
  2868  	Src Register `parser:"@Register64"`
  2869  }
  2870  
  2871  func (i *mov64Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2872  	return []Instruction{&Mov64Register{
  2873  		Dest: i.Dst,
  2874  		Src:  i.Src,
  2875  	}}, nil
  2876  }
  2877  
  2878  type mul32 struct {
  2879  	Dst   Register `parser:"@Register32 '*' '='"`
  2880  	Value int32    `parser:"@(('+'|'-')? Number)"`
  2881  }
  2882  
  2883  func (i *mul32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2884  	return []Instruction{&Mul32{
  2885  		Dest:  i.Dst,
  2886  		Value: i.Value,
  2887  	}}, nil
  2888  }
  2889  
  2890  type mul32Register struct {
  2891  	Dst Register `parser:"@Register32 '*' '='"`
  2892  	Src Register `parser:"@Register32"`
  2893  }
  2894  
  2895  func (i *mul32Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2896  	return []Instruction{&Mul32Register{
  2897  		Dest: i.Dst,
  2898  		Src:  i.Src,
  2899  	}}, nil
  2900  }
  2901  
  2902  type mul64 struct {
  2903  	Dst   Register `parser:"@Register64 '*' '='"`
  2904  	Value int32    `parser:"@(('+'|'-')? Number)"`
  2905  }
  2906  
  2907  func (i *mul64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2908  	return []Instruction{&Mul64{
  2909  		Dest:  i.Dst,
  2910  		Value: i.Value,
  2911  	}}, nil
  2912  }
  2913  
  2914  type mul64Register struct {
  2915  	Dst Register `parser:"@Register64 '*' '='"`
  2916  	Src Register `parser:"@Register64"`
  2917  }
  2918  
  2919  func (i *mul64Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2920  	return []Instruction{&Mul64Register{
  2921  		Dest: i.Dst,
  2922  		Src:  i.Src,
  2923  	}}, nil
  2924  }
  2925  
  2926  type neg32 struct {
  2927  	Dst Register `parser:"@Register32 '=' '-' Register32"`
  2928  }
  2929  
  2930  func (i *neg32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2931  	return []Instruction{&Neg32{
  2932  		Dest: i.Dst,
  2933  	}}, nil
  2934  }
  2935  
  2936  type neg64 struct {
  2937  	Dst Register `parser:"@Register64 '=' '-' Register64"`
  2938  }
  2939  
  2940  func (i *neg64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2941  	return []Instruction{&Neg64{
  2942  		Dest: i.Dst,
  2943  	}}, nil
  2944  }
  2945  
  2946  type or32 struct {
  2947  	Dst   Register `parser:"@Register32 '|' '='"`
  2948  	Value int32    `parser:"@(('+'|'-')? Number)"`
  2949  }
  2950  
  2951  func (i *or32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2952  	return []Instruction{&Or32{
  2953  		Dest:  i.Dst,
  2954  		Value: i.Value,
  2955  	}}, nil
  2956  }
  2957  
  2958  type or32Register struct {
  2959  	Dst Register `parser:"@Register32 '|' '='"`
  2960  	Src Register `parser:"@Register32"`
  2961  }
  2962  
  2963  func (i *or32Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2964  	return []Instruction{&Or32Register{
  2965  		Dest: i.Dst,
  2966  		Src:  i.Src,
  2967  	}}, nil
  2968  }
  2969  
  2970  type or64 struct {
  2971  	Dst   Register `parser:"@Register64 '|' '='"`
  2972  	Value int32    `parser:"@(('+'|'-')? Number)"`
  2973  }
  2974  
  2975  func (i *or64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2976  	return []Instruction{&Or64{
  2977  		Dest:  i.Dst,
  2978  		Value: i.Value,
  2979  	}}, nil
  2980  }
  2981  
  2982  type or64Register struct {
  2983  	Dst Register `parser:"@Register64 '|' '='"`
  2984  	Src Register `parser:"@Register64"`
  2985  }
  2986  
  2987  func (i *or64Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  2988  	return []Instruction{&Or64Register{
  2989  		Dest: i.Dst,
  2990  		Src:  i.Src,
  2991  	}}, nil
  2992  }
  2993  
  2994  type rsh32 struct {
  2995  	Dst   Register `parser:"@Register32 '>' '>' '='"`
  2996  	Value int32    `parser:"@(('+'|'-')? Number)"`
  2997  }
  2998  
  2999  func (i *rsh32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  3000  	return []Instruction{&Rsh32{
  3001  		Dest:  i.Dst,
  3002  		Value: i.Value,
  3003  	}}, nil
  3004  }
  3005  
  3006  type rsh32Register struct {
  3007  	Dst Register `parser:"@Register32 '>' '>' '='"`
  3008  	Src Register `parser:"@Register32"`
  3009  }
  3010  
  3011  func (i *rsh32Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  3012  	return []Instruction{&Rsh32Register{
  3013  		Dest: i.Dst,
  3014  		Src:  i.Src,
  3015  	}}, nil
  3016  }
  3017  
  3018  type rsh64 struct {
  3019  	Dst   Register `parser:"@Register64 '>' '>' '='"`
  3020  	Value int32    `parser:"@(('+'|'-')? Number)"`
  3021  }
  3022  
  3023  func (i *rsh64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  3024  	return []Instruction{&Rsh64{
  3025  		Dest:  i.Dst,
  3026  		Value: i.Value,
  3027  	}}, nil
  3028  }
  3029  
  3030  type rsh64Register struct {
  3031  	Dst Register `parser:"@Register64 '>' '>' '='"`
  3032  	Src Register `parser:"@Register64"`
  3033  }
  3034  
  3035  func (i *rsh64Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  3036  	return []Instruction{&Rsh64Register{
  3037  		Dest: i.Dst,
  3038  		Src:  i.Src,
  3039  	}}, nil
  3040  }
  3041  
  3042  // *(u8 *)(r3 + 456) = 123
  3043  type storeMemoryConstant struct {
  3044  	Size   Size     `parser:"'*' '(' @Ident '*' ')' '('"`
  3045  	Dst    Register `parser:"@Register64"`
  3046  	Offset int16    `parser:"@(('+'|'-') Number) ')' '='"`
  3047  	Value  int32    `parser:"@(('+'|'-')? Number)"`
  3048  }
  3049  
  3050  func (i *storeMemoryConstant) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  3051  	return []Instruction{&StoreMemoryConstant{
  3052  		Size:   i.Size,
  3053  		Dest:   i.Dst,
  3054  		Offset: i.Offset,
  3055  		Value:  i.Value,
  3056  	}}, nil
  3057  }
  3058  
  3059  // *(u8 *)(r3 + 456) = r1
  3060  type storeMemoryRegister struct {
  3061  	Size   Size     `parser:"'*' '(' @Ident '*' ')' '('"`
  3062  	Dst    Register `parser:"@Register64"`
  3063  	Offset int16    `parser:"@(('+'|'-') Number) ')' '='"`
  3064  	Src    Register `parser:"@Register64"`
  3065  }
  3066  
  3067  func (i *storeMemoryRegister) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  3068  	return []Instruction{&StoreMemoryRegister{
  3069  		Size:   i.Size,
  3070  		Dest:   i.Dst,
  3071  		Offset: i.Offset,
  3072  		Src:    i.Src,
  3073  	}}, nil
  3074  }
  3075  
  3076  type sub32 struct {
  3077  	Dst   Register `parser:"@Register32 '-' '='"`
  3078  	Value int32    `parser:"@(('+'|'-')? Number)"`
  3079  }
  3080  
  3081  func (i *sub32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  3082  	return []Instruction{&Sub32{
  3083  		Dest:  i.Dst,
  3084  		Value: i.Value,
  3085  	}}, nil
  3086  }
  3087  
  3088  type sub32Register struct {
  3089  	Dst Register `parser:"@Register32 '-' '='"`
  3090  	Src Register `parser:"@Register32"`
  3091  }
  3092  
  3093  func (i *sub32Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  3094  	return []Instruction{&Sub32Register{
  3095  		Dest: i.Dst,
  3096  		Src:  i.Src,
  3097  	}}, nil
  3098  }
  3099  
  3100  type sub64 struct {
  3101  	Dst   Register `parser:"@Register64 '-' '='"`
  3102  	Value int32    `parser:"@(('+'|'-')? Number)"`
  3103  }
  3104  
  3105  func (i *sub64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  3106  	return []Instruction{&Sub64{
  3107  		Dest:  i.Dst,
  3108  		Value: i.Value,
  3109  	}}, nil
  3110  }
  3111  
  3112  type sub64Register struct {
  3113  	Dst Register `parser:"@Register64 '-' '='"`
  3114  	Src Register `parser:"@Register64"`
  3115  }
  3116  
  3117  func (i *sub64Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  3118  	return []Instruction{&Sub64Register{
  3119  		Dest: i.Dst,
  3120  		Src:  i.Src,
  3121  	}}, nil
  3122  }
  3123  
  3124  type xor32 struct {
  3125  	Dst   Register `parser:"@Register32 '^' '='"`
  3126  	Value int32    `parser:"@(('+'|'-')? Number)"`
  3127  }
  3128  
  3129  func (i *xor32) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  3130  	return []Instruction{&Xor32{
  3131  		Dest:  i.Dst,
  3132  		Value: i.Value,
  3133  	}}, nil
  3134  }
  3135  
  3136  type xor32Register struct {
  3137  	Dst Register `parser:"@Register32 '^' '='"`
  3138  	Src Register `parser:"@Register32"`
  3139  }
  3140  
  3141  func (i *xor32Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  3142  	return []Instruction{&Xor32Register{
  3143  		Dest: i.Dst,
  3144  		Src:  i.Src,
  3145  	}}, nil
  3146  }
  3147  
  3148  type xor64 struct {
  3149  	Dst   Register `parser:"@Register64 '^' '='"`
  3150  	Value int32    `parser:"@(('+'|'-')? Number)"`
  3151  }
  3152  
  3153  func (i *xor64) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  3154  	return []Instruction{&Xor64{
  3155  		Dest:  i.Dst,
  3156  		Value: i.Value,
  3157  	}}, nil
  3158  }
  3159  
  3160  type xor64Register struct {
  3161  	Dst Register `parser:"@Register64 '^' '='"`
  3162  	Src Register `parser:"@Register64"`
  3163  }
  3164  
  3165  func (i *xor64Register) ToInst(index int, ctx *assembleContext) ([]Instruction, error) {
  3166  	return []Instruction{&Xor64Register{
  3167  		Dest: i.Dst,
  3168  		Src:  i.Src,
  3169  	}}, nil
  3170  }