]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-bpf.c
bpf: accept # as an inline comment char
[thirdparty/binutils-gdb.git] / gas / config / tc-bpf.c
CommitLineData
f8861f5d 1/* tc-bpf.c -- Assembler for the Linux eBPF.
d87bef3a 2 Copyright (C) 2019-2023 Free Software Foundation, Inc.
f8861f5d
JM
3 Contributed by Oracle, Inc.
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to
19 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20 Boston, MA 02110-1301, USA. */
21
22#include "as.h"
23#include "subsegs.h"
24#include "symcat.h"
d218e7fe 25#include "opcode/bpf.h"
f8861f5d
JM
26#include "elf/common.h"
27#include "elf/bpf.h"
28#include "dwarf2dbg.h"
d218e7fe 29#include "libiberty.h"
ff5a51b3 30#include <ctype.h>
f8861f5d 31
d218e7fe
JM
32/* Data structure representing a parsed BPF instruction. */
33
34struct bpf_insn
35{
c2ca88d7 36 enum bpf_insn_id id;
d218e7fe
JM
37 int size; /* Instruction size in bytes. */
38 bpf_insn_word opcode;
39 uint8_t dst;
40 uint8_t src;
41 expressionS offset16;
42 expressionS imm32;
43 expressionS imm64;
44 expressionS disp16;
45 expressionS disp32;
46
47 unsigned int has_dst : 1;
48 unsigned int has_src : 1;
49 unsigned int has_offset16 : 1;
50 unsigned int has_disp16 : 1;
51 unsigned int has_disp32 : 1;
52 unsigned int has_imm32 : 1;
53 unsigned int has_imm64 : 1;
54};
55
9d1e07bd 56const char comment_chars[] = ";#";
ff5a51b3 57const char line_comment_chars[] = "#";
f8861f5d
JM
58const char line_separator_chars[] = "`";
59const char EXP_CHARS[] = "eE";
60const char FLT_CHARS[] = "fFdD";
61
1802aae8
JM
62/* Like s_lcomm_internal in gas/read.c but the alignment string
63 is allowed to be optional. */
64
65static symbolS *
66pe_lcomm_internal (int needs_align, symbolS *symbolP, addressT size)
67{
68 addressT align = 0;
69
70 SKIP_WHITESPACE ();
71
72 if (needs_align
73 && *input_line_pointer == ',')
74 {
75 align = parse_align (needs_align - 1);
76
77 if (align == (addressT) -1)
78 return NULL;
79 }
80 else
81 {
82 if (size >= 8)
83 align = 3;
84 else if (size >= 4)
85 align = 2;
86 else if (size >= 2)
87 align = 1;
88 else
89 align = 0;
90 }
91
92 bss_alloc (symbolP, size, align);
93 return symbolP;
94}
95
96static void
97pe_lcomm (int needs_align)
98{
99 s_comm_internal (needs_align * 2, pe_lcomm_internal);
100}
101
f8861f5d
JM
102/* The target specific pseudo-ops which we support. */
103const pseudo_typeS md_pseudo_table[] =
104{
e0b989a6
JM
105 { "half", cons, 2 },
106 { "word", cons, 4 },
107 { "dword", cons, 8 },
1802aae8 108 { "lcomm", pe_lcomm, 1 },
d0044bac 109 { NULL, NULL, 0 }
f8861f5d
JM
110};
111
1802aae8
JM
112\f
113
f8861f5d
JM
114/* Command-line options processing. */
115
116enum options
117{
118 OPTION_LITTLE_ENDIAN = OPTION_MD_BASE,
4449c81a 119 OPTION_BIG_ENDIAN,
d218e7fe
JM
120 OPTION_XBPF,
121 OPTION_DIALECT,
122 OPTION_ISA_SPEC,
f8861f5d
JM
123};
124
125struct option md_longopts[] =
126{
127 { "EL", no_argument, NULL, OPTION_LITTLE_ENDIAN },
128 { "EB", no_argument, NULL, OPTION_BIG_ENDIAN },
4449c81a 129 { "mxbpf", no_argument, NULL, OPTION_XBPF },
d218e7fe
JM
130 { "mdialect", required_argument, NULL, OPTION_DIALECT},
131 { "misa-spec", required_argument, NULL, OPTION_ISA_SPEC},
f8861f5d
JM
132 { NULL, no_argument, NULL, 0 },
133};
134
135size_t md_longopts_size = sizeof (md_longopts);
136
137const char * md_shortopts = "";
138
d218e7fe
JM
139/* BPF supports little-endian and big-endian variants. The following
140 global records what endianness to use. It can be configured using
141 command-line options. It defaults to the host endianness
142 initialized in md_begin. */
f8861f5d 143
f8861f5d 144static int set_target_endian = 0;
d218e7fe
JM
145extern int target_big_endian;
146
147/* The ISA specification can be one of BPF_V1, BPF_V2, BPF_V3, BPF_V4
148 or BPF_XPBF. The ISA spec to use can be configured using
149 command-line options. It defaults to the latest BPF spec. */
150
151static int isa_spec = BPF_V4;
f8861f5d 152
d218e7fe
JM
153/* The assembler supports two different dialects: "normal" syntax and
154 "pseudoc" syntax. The dialect to use can be configured using
155 command-line options. */
4449c81a 156
d218e7fe
JM
157enum target_asm_dialect
158{
159 DIALECT_NORMAL,
160 DIALECT_PSEUDOC
161};
162
163static int asm_dialect = DIALECT_NORMAL;
4449c81a 164
f8861f5d 165int
d218e7fe 166md_parse_option (int c, const char * arg)
f8861f5d
JM
167{
168 switch (c)
169 {
170 case OPTION_BIG_ENDIAN:
171 set_target_endian = 1;
172 target_big_endian = 1;
173 break;
174 case OPTION_LITTLE_ENDIAN:
d218e7fe 175 set_target_endian = 0;
f8861f5d
JM
176 target_big_endian = 0;
177 break;
d218e7fe
JM
178 case OPTION_DIALECT:
179 if (strcmp (arg, "normal") == 0)
180 asm_dialect = DIALECT_NORMAL;
181 else if (strcmp (arg, "pseudoc") == 0)
182 asm_dialect = DIALECT_PSEUDOC;
183 else
184 as_fatal (_("-mdialect=%s is not valid. Expected normal or pseudoc"),
185 arg);
186 break;
187 case OPTION_ISA_SPEC:
188 if (strcmp (arg, "v1") == 0)
189 isa_spec = BPF_V1;
190 else if (strcmp (arg, "v2") == 0)
191 isa_spec = BPF_V2;
192 else if (strcmp (arg, "v3") == 0)
193 isa_spec = BPF_V3;
194 else if (strcmp (arg, "v4") == 0)
195 isa_spec = BPF_V4;
196 else if (strcmp (arg, "xbpf") == 0)
197 isa_spec = BPF_XBPF;
198 else
199 as_fatal (_("-misa-spec=%s is not valid. Expected v1, v2, v3, v4 o xbpf"),
200 arg);
201 break;
4449c81a 202 case OPTION_XBPF:
d218e7fe
JM
203 /* This is an alias for -misa-spec=xbpf. */
204 isa_spec = BPF_XBPF;
4449c81a 205 break;
f8861f5d
JM
206 default:
207 return 0;
208 }
209
210 return 1;
211}
212
213void
214md_show_usage (FILE * stream)
215{
216 fprintf (stream, _("\nBPF options:\n"));
217 fprintf (stream, _("\
d218e7fe
JM
218BPF options:\n\
219 -EL generate code for a little endian machine\n\
220 -EB generate code for a big endian machine\n\
221 -mdialect=DIALECT set the assembly dialect (normal, pseudoc)\n\
222 -misa-spec set the BPF ISA spec (v1, v2, v3, v4, xbpf)\n\
223 -mxbpf alias for -misa-spec=xbpf\n"));
f8861f5d
JM
224}
225
226\f
d218e7fe
JM
227/* This function is called once, at assembler startup time. This
228 should set up all the tables, etc that the MD part of the assembler
229 needs. */
ff5a51b3 230
f8861f5d
JM
231void
232md_begin (void)
233{
f8861f5d
JM
234 /* If not specified in the command line, use the host
235 endianness. */
236 if (!set_target_endian)
237 {
238#ifdef WORDS_BIGENDIAN
239 target_big_endian = 1;
240#else
241 target_big_endian = 0;
242#endif
243 }
244
ff5a51b3
GM
245 /* Ensure that lines can begin with '*' in BPF store pseudoc instruction. */
246 lex_type['*'] |= LEX_BEGIN_NAME;
247
f8861f5d
JM
248 /* Set the machine type. */
249 bfd_default_set_arch_mach (stdoutput, bfd_arch_bpf, bfd_mach_bpf);
250}
251
d218e7fe
JM
252/* Round up a section size to the appropriate boundary. */
253
f8861f5d
JM
254valueT
255md_section_align (segT segment, valueT size)
256{
fd361982 257 int align = bfd_section_alignment (segment);
f8861f5d
JM
258
259 return ((size + (1 << align) - 1) & -(1 << align));
260}
261
262\f
263/* Functions concerning relocs. */
264
265/* The location from which a PC relative jump should be calculated,
266 given a PC relative reloc. */
267
268long
269md_pcrel_from_section (fixS *fixP, segT sec)
270{
271 if (fixP->fx_addsy != (symbolS *) NULL
272 && (! S_IS_DEFINED (fixP->fx_addsy)
273 || (S_GET_SEGMENT (fixP->fx_addsy) != sec)
274 || S_IS_EXTERNAL (fixP->fx_addsy)
275 || S_IS_WEAK (fixP->fx_addsy)))
276 {
277 /* The symbol is undefined (or is defined but not in this section).
278 Let the linker figure it out. */
279 return 0;
280 }
281
282 return fixP->fx_where + fixP->fx_frag->fr_address;
283}
284
285/* Write a value out to the object file, using the appropriate endianness. */
286
287void
288md_number_to_chars (char * buf, valueT val, int n)
289{
290 if (target_big_endian)
291 number_to_chars_bigendian (buf, val, n);
292 else
293 number_to_chars_littleendian (buf, val, n);
294}
295
296arelent *
d218e7fe 297tc_gen_reloc (asection *sec ATTRIBUTE_UNUSED, fixS *fixP)
f8861f5d 298{
d218e7fe
JM
299 bfd_reloc_code_real_type r_type = fixP->fx_r_type;
300 arelent *reloc;
f8861f5d 301
d218e7fe 302 reloc = XNEW (arelent);
f8861f5d 303
d218e7fe
JM
304 if (fixP->fx_pcrel)
305 {
306 r_type = (r_type == BFD_RELOC_8 ? BFD_RELOC_8_PCREL
307 : r_type == BFD_RELOC_16 ? BFD_RELOC_16_PCREL
308 : r_type == BFD_RELOC_24 ? BFD_RELOC_24_PCREL
309 : r_type == BFD_RELOC_32 ? BFD_RELOC_32_PCREL
310 : r_type == BFD_RELOC_64 ? BFD_RELOC_64_PCREL
311 : r_type);
312 }
313
314 reloc->howto = bfd_reloc_type_lookup (stdoutput, r_type);
315
316 if (reloc->howto == (reloc_howto_type *) NULL)
f8861f5d 317 {
d218e7fe
JM
318 as_bad_where (fixP->fx_file, fixP->fx_line,
319 _("relocation is not supported"));
320 return NULL;
f8861f5d 321 }
d218e7fe
JM
322
323 //XXX gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
324
325 reloc->sym_ptr_ptr = XNEW (asymbol *);
326 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
327
328 /* Use fx_offset for these cases. */
329 if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
330 || fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT)
331 reloc->addend = fixP->fx_offset;
332 else
333 reloc->addend = fixP->fx_addnumber;
334
335 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
336 return reloc;
f8861f5d 337}
d218e7fe 338
f8861f5d
JM
339\f
340/* *FRAGP has been relaxed to its final size, and now needs to have
341 the bytes inside it modified to conform to the new size.
342
343 Called after relaxation is finished.
344 fragP->fr_type == rs_machine_dependent.
345 fragP->fr_subtype is the subtype of what the address relaxed to. */
346
347void
348md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
349 segT sec ATTRIBUTE_UNUSED,
350 fragS *fragP ATTRIBUTE_UNUSED)
351{
352 as_fatal (_("convert_frag called"));
353}
354
355int
356md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
357 segT segment ATTRIBUTE_UNUSED)
358{
359 as_fatal (_("estimate_size_before_relax called"));
360 return 0;
361}
362
363\f
d218e7fe
JM
364/* Apply a fixS (fixup of an instruction or data that we didn't have
365 enough info to complete immediately) to the data in a frag. */
366
f8861f5d 367void
d218e7fe 368md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
f8861f5d 369{
d218e7fe
JM
370 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
371
372 switch (fixP->fx_r_type)
f8861f5d 373 {
d218e7fe
JM
374 case BFD_RELOC_BPF_DISP16:
375 /* Convert from bytes to number of 64-bit words to the target,
376 minus one. */
377 *valP = (((long) (*valP)) - 8) / 8;
378 break;
c2ca88d7 379 case BFD_RELOC_BPF_DISPCALL32:
d218e7fe 380 case BFD_RELOC_BPF_DISP32:
d218e7fe
JM
381 /* Convert from bytes to number of 64-bit words to the target,
382 minus one. */
383 *valP = (((long) (*valP)) - 8) / 8;
c2ca88d7
JM
384
385 if (fixP->fx_r_type == BFD_RELOC_BPF_DISPCALL32)
386 {
387 /* eBPF supports two kind of CALL instructions: the so
388 called pseudo calls ("bpf to bpf") and external calls
389 ("bpf to kernel").
390
391 Both kind of calls use the same instruction (CALL).
392 However, external calls are constructed by passing a
393 constant argument to the instruction, whereas pseudo
394 calls result from expressions involving symbols. In
395 practice, instructions requiring a fixup are interpreted
396 as pseudo-calls. If we are executing this code, this is
397 a pseudo call.
398
399 The kernel expects for pseudo-calls to be annotated by
400 having BPF_PSEUDO_CALL in the SRC field of the
401 instruction. But beware the infamous nibble-swapping of
402 eBPF and take endianness into account here.
403
404 Note that the CALL instruction has only one operand, so
405 this code is executed only once per instruction. */
406 md_number_to_chars (where + 1, target_big_endian ? 0x01 : 0x10, 1);
407 }
d218e7fe
JM
408 break;
409 case BFD_RELOC_16_PCREL:
410 /* Convert from bytes to number of 64-bit words to the target,
411 minus one. */
412 *valP = (((long) (*valP)) - 8) / 8;
413 break;
414 default:
415 break;
416 }
f8861f5d 417
d218e7fe
JM
418 if (fixP->fx_addsy == (symbolS *) NULL)
419 fixP->fx_done = 1;
420
421 if (fixP->fx_done)
422 {
423 /* We're finished with this fixup. Install it because
424 bfd_install_relocation won't be called to do it. */
425 switch (fixP->fx_r_type)
426 {
427 case BFD_RELOC_8:
428 md_number_to_chars (where, *valP, 1);
429 break;
430 case BFD_RELOC_16:
431 md_number_to_chars (where, *valP, 2);
432 break;
433 case BFD_RELOC_32:
434 md_number_to_chars (where, *valP, 4);
435 break;
436 case BFD_RELOC_64:
437 md_number_to_chars (where, *valP, 8);
438 break;
439 case BFD_RELOC_BPF_DISP16:
440 md_number_to_chars (where + 2, (uint16_t) *valP, 2);
f8861f5d 441 break;
d218e7fe 442 case BFD_RELOC_BPF_DISP32:
c2ca88d7 443 case BFD_RELOC_BPF_DISPCALL32:
d218e7fe 444 md_number_to_chars (where + 4, (uint32_t) *valP, 4);
f8861f5d 445 break;
d218e7fe
JM
446 case BFD_RELOC_16_PCREL:
447 md_number_to_chars (where + 2, (uint32_t) *valP, 2);
448 break;
449 default:
450 as_bad_where (fixP->fx_file, fixP->fx_line,
451 _("internal error: can't install fix for reloc type %d (`%s')"),
452 fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
453 break;
454 }
f8861f5d
JM
455 }
456
d218e7fe
JM
457 /* Tuck `value' away for use by tc_gen_reloc.
458 See the comment describing fx_addnumber in write.h.
459 This field is misnamed (or misused :-). */
460 fixP->fx_addnumber = *valP;
f8861f5d
JM
461}
462
d218e7fe
JM
463/* Parse an operand expression. Returns the first character that is
464 not part of the expression, or NULL in case of parse error.
ff5a51b3 465
d218e7fe 466 See md_operand below to see how exp_parse_failed is used. */
ff5a51b3 467
d218e7fe 468static int exp_parse_failed = 0;
ff5a51b3
GM
469
470static char *
d218e7fe 471parse_expression (char *s, expressionS *exp)
ff5a51b3 472{
d218e7fe
JM
473 char *saved_input_line_pointer = input_line_pointer;
474 char *saved_s = s;
ff5a51b3 475
d218e7fe
JM
476 exp_parse_failed = 0;
477 input_line_pointer = s;
478 expression (exp);
479 s = input_line_pointer;
480 input_line_pointer = saved_input_line_pointer;
ff5a51b3 481
d218e7fe
JM
482 switch (exp->X_op == O_absent || exp_parse_failed)
483 return NULL;
ff5a51b3 484
d218e7fe
JM
485 /* The expression parser may consume trailing whitespaces. We have
486 to undo that since the instruction templates may be expecting
487 these whitespaces. */
488 {
489 char *p;
490 for (p = s - 1; p >= saved_s && *p == ' '; --p)
491 --s;
492 }
ff5a51b3 493
d218e7fe 494 return s;
ff5a51b3
GM
495}
496
d218e7fe
JM
497/* Parse a BPF register name and return the corresponding register
498 number. Return NULL in case of parse error, or a pointer to the
499 first character in S that is not part of the register name. */
ff5a51b3 500
d218e7fe
JM
501static char *
502parse_bpf_register (char *s, char rw, uint8_t *regno)
ff5a51b3 503{
d218e7fe 504 if (asm_dialect == DIALECT_NORMAL)
ff5a51b3 505 {
d218e7fe
JM
506 rw = 'r';
507 if (*s != '%')
508 return NULL;
509 s += 1;
ff5a51b3 510
d218e7fe
JM
511 if (*s == 'f' && *(s + 1) == 'p')
512 {
513 *regno = 10;
514 s += 2;
515 return s;
516 }
517 }
ff5a51b3 518
d218e7fe
JM
519 if (*s != rw)
520 return NULL;
521 s += 1;
ff5a51b3 522
d218e7fe
JM
523 if (*s == '1')
524 {
525 if (*(s + 1) == '0')
526 {
527 *regno = 10;
528 s += 2;
529 }
530 else
531 {
532 *regno = 1;
533 s += 1;
534 }
535 }
536 else if (*s >= '0' && *s <= '9')
537 {
538 *regno = *s - '0';
539 s += 1;
540 }
ff5a51b3 541
d218e7fe 542 return s;
ff5a51b3
GM
543}
544
d218e7fe 545/* Collect a parse error message. */
ff5a51b3 546
d218e7fe
JM
547static int partial_match_length = 0;
548static char *errmsg = NULL;
ff5a51b3 549
d218e7fe
JM
550static void
551parse_error (int length, const char *fmt, ...)
ff5a51b3 552{
d218e7fe 553 if (length > partial_match_length)
ff5a51b3 554 {
d218e7fe 555 va_list args;
ff5a51b3 556
d218e7fe
JM
557 free (errmsg);
558 va_start (args, fmt);
559 errmsg = xvasprintf (fmt, args);
560 va_end (args);
561 partial_match_length = length;
ff5a51b3 562 }
ff5a51b3
GM
563}
564
d218e7fe
JM
565/* Assemble a machine instruction in STR and emit the frags/bytes it
566 assembles to. */
ff5a51b3 567
d218e7fe
JM
568void
569md_assemble (char *str ATTRIBUTE_UNUSED)
ff5a51b3 570{
d218e7fe
JM
571 /* There are two different syntaxes that can be used to write BPF
572 instructions. One is very conventional and like any other
573 assembly language where each instruction is conformed by an
574 instruction mnemonic followed by its operands. This is what we
575 call the "normal" syntax. The other syntax tries to look like C
576 statements. We have to support both syntaxes in this assembler.
577
578 One of the many nuisances introduced by this eccentricity is that
579 in the pseudo-c syntax it is not possible to hash the opcodes
580 table by instruction mnemonic, because there is none. So we have
581 no other choice than to try to parse all instruction opcodes
582 until one matches. This is slow.
583
584 Another problem is that emitting detailed diagnostics becomes
585 tricky, since the lack of mnemonic means it is not clear what
586 instruction was intended by the user, and we cannot emit
587 diagnostics for every attempted template. So if an instruction
588 is not parsed, we report the diagnostic corresponding to the
589 partially parsed instruction that was matched further. */
590
591 unsigned int idx = 0;
592 struct bpf_insn insn;
593 const struct bpf_opcode *opcode;
594
595 /* Initialize the global diagnostic variables. See the parse_error
596 function above. */
597 partial_match_length = 0;
598 errmsg = NULL;
599
600#define PARSE_ERROR(...) parse_error (s - str, __VA_ARGS__)
601
602 while ((opcode = bpf_get_opcode (idx++)) != NULL)
ff5a51b3 603 {
d218e7fe
JM
604 const char *p;
605 char *s;
606 const char *template
607 = (asm_dialect == DIALECT_PSEUDOC ? opcode->pseudoc : opcode->normal);
608
609 /* Do not try to match opcodes with a higher version than the
610 selected ISA spec. */
611 if (opcode->version > isa_spec)
612 continue;
613
614 memset (&insn, 0, sizeof (struct bpf_insn));
615 insn.size = 8;
616 for (s = str, p = template; *p != '\0';)
617 {
618 if (*p == ' ')
619 {
620 /* Expect zero or more spaces. */
621 while (*s != '\0' && (*s == ' ' || *s == '\t'))
622 s += 1;
623 p += 1;
624 }
625 else if (*p == '%')
626 {
627 if (*(p + 1) == '%')
628 {
629 if (*s != '%')
630 {
631 PARSE_ERROR ("expected '%%'");
632 break;
633 }
634 p += 2;
635 s += 1;
636 }
637 else if (*(p + 1) == 'w')
638 {
639 /* Expect zero or more spaces. */
640 while (*s != '\0' && (*s == ' ' || *s == '\t'))
641 s += 1;
642 p += 2;
643 }
644 else if (*(p + 1) == 'W')
645 {
646 /* Expect one or more spaces. */
647 if (*s != ' ' && *s != '\t')
648 {
649 PARSE_ERROR ("expected white space, got '%s'",
650 s);
651 break;
652 }
653 while (*s != '\0' && (*s == ' ' || *s == '\t'))
654 s += 1;
655 p += 2;
656 }
657 else if (strncmp (p, "%dr", 3) == 0)
658 {
659 uint8_t regno;
660 char *news = parse_bpf_register (s, 'r', &regno);
661
662 if (news == NULL || (insn.has_dst && regno != insn.dst))
663 {
664 if (news != NULL)
665 PARSE_ERROR ("expected register r%d, got r%d",
666 insn.dst, regno);
667 else
668 PARSE_ERROR ("expected register name, got '%s'", s);
669 break;
670 }
671 s = news;
672 insn.dst = regno;
673 insn.has_dst = 1;
674 p += 3;
675 }
676 else if (strncmp (p, "%sr", 3) == 0)
677 {
678 uint8_t regno;
679 char *news = parse_bpf_register (s, 'r', &regno);
680
681 if (news == NULL || (insn.has_src && regno != insn.src))
682 {
683 if (news != NULL)
684 PARSE_ERROR ("expected register r%d, got r%d",
685 insn.dst, regno);
686 else
687 PARSE_ERROR ("expected register name, got '%s'", s);
688 break;
689 }
690 s = news;
691 insn.src = regno;
692 insn.has_src = 1;
693 p += 3;
694 }
695 else if (strncmp (p, "%dw", 3) == 0)
696 {
697 uint8_t regno;
698 char *news = parse_bpf_register (s, 'w', &regno);
699
700 if (news == NULL || (insn.has_dst && regno != insn.dst))
701 {
702 if (news != NULL)
703 PARSE_ERROR ("expected register r%d, got r%d",
704 insn.dst, regno);
705 else
706 PARSE_ERROR ("expected register name, got '%s'", s);
707 break;
708 }
709 s = news;
710 insn.dst = regno;
711 insn.has_dst = 1;
712 p += 3;
713 }
714 else if (strncmp (p, "%sw", 3) == 0)
715 {
716 uint8_t regno;
717 char *news = parse_bpf_register (s, 'w', &regno);
718
719 if (news == NULL || (insn.has_src && regno != insn.src))
720 {
721 if (news != NULL)
722 PARSE_ERROR ("expected register r%d, got r%d",
723 insn.dst, regno);
724 else
725 PARSE_ERROR ("expected register name, got '%s'", s);
726 break;
727 }
728 s = news;
729 insn.src = regno;
730 insn.has_src = 1;
731 p += 3;
732 }
733 else if (strncmp (p, "%i32", 4) == 0
734 || strncmp (p, "%I32", 4) == 0)
735 {
736 if (p[1] == 'I')
737 {
738 while (*s == ' ' || *s == '\t')
739 s += 1;
740 if (*s != '+' && *s != '-')
741 {
742 PARSE_ERROR ("expected `+' or `-', got `%c'", *s);
743 break;
744 }
745 }
746
747 s = parse_expression (s, &insn.imm32);
748 if (s == NULL)
749 {
750 PARSE_ERROR ("expected signed 32-bit immediate");
751 break;
752 }
753 insn.has_imm32 = 1;
754 p += 4;
755 }
756 else if (strncmp (p, "%o16", 4) == 0)
757 {
758 while (*s == ' ' || *s == '\t')
759 s += 1;
760 if (*s != '+' && *s != '-')
761 {
762 PARSE_ERROR ("expected `+' or `-', got `%c'", *s);
763 break;
764 }
765
766 s = parse_expression (s, &insn.offset16);
767 if (s == NULL)
768 {
769 PARSE_ERROR ("expected signed 16-bit offset");
770 break;
771 }
772 insn.has_offset16 = 1;
773 p += 4;
774 }
775 else if (strncmp (p, "%d16", 4) == 0)
776 {
777 s = parse_expression (s, &insn.disp16);
778 if (s == NULL)
779 {
780 PARSE_ERROR ("expected signed 16-bit displacement");
781 break;
782 }
783 insn.has_disp16 = 1;
784 p += 4;
785 }
786 else if (strncmp (p, "%d32", 4) == 0)
787 {
788 s = parse_expression (s, &insn.disp32);
789 if (s == NULL)
790 {
791 PARSE_ERROR ("expected signed 32-bit displacement");
792 break;
793 }
794 insn.has_disp32 = 1;
795 p += 4;
796 }
797 else if (strncmp (p, "%i64", 4) == 0)
798 {
799 s = parse_expression (s, &insn.imm64);
800 if (s == NULL)
801 {
802 PARSE_ERROR ("expected signed 64-bit immediate");
803 break;
804 }
805 insn.has_imm64 = 1;
806 insn.size = 16;
807 p += 4;
808 }
809 else
810 as_fatal (_("invalid %%-tag in BPF opcode '%s'\n"), template);
811 }
812 else
813 {
814 /* Match a literal character. */
815 if (*s != *p)
816 {
817 if (*s == '\0')
818 PARSE_ERROR ("expected '%c'", *p);
819 else if (*s == '%')
820 {
821 /* This is to workaround a bug in as_bad. */
822 char tmp[3];
823
824 tmp[0] = '%';
825 tmp[1] = '%';
826 tmp[2] = '\0';
827
828 PARSE_ERROR ("expected '%c', got '%s'", *p, tmp);
829 }
830 else
831 PARSE_ERROR ("expected '%c', got '%c'", *p, *s);
832 break;
833 }
834 p += 1;
835 s += 1;
836 }
837 }
ff5a51b3 838
d218e7fe
JM
839 if (*p == '\0')
840 {
841 /* Allow white spaces at the end of the line. */
842 while (*s != '\0' && (*s == ' ' || *s == '\t'))
843 s += 1;
844 if (*s == '\0')
845 /* We parsed an instruction successfully. */
846 break;
847 PARSE_ERROR ("extra junk at end of line");
848 }
849 }
ff5a51b3 850
d218e7fe
JM
851 if (opcode == NULL)
852 {
853 as_bad (_("unrecognized instruction `%s'"), str);
854 if (errmsg != NULL)
855 {
fafcbd14 856 as_bad ("%s", errmsg);
d218e7fe
JM
857 free (errmsg);
858 }
ff5a51b3 859
d218e7fe
JM
860 return;
861 }
c2ca88d7 862 insn.id = opcode->id;
d218e7fe 863 insn.opcode = opcode->opcode;
ff5a51b3 864
d218e7fe 865#undef PARSE_ERROR
ff5a51b3 866
d218e7fe
JM
867 /* Generate the frags and fixups for the parsed instruction. */
868 {
869 char *this_frag = frag_more (insn.size);
870 char bytes[16];
871 uint8_t src, dst;
872 int i;
873
874 /* Zero all the bytes. */
875 memset (bytes, 0, 16);
876
877 /* First encode the opcodes. Note that we have to handle the
878 endianness groups of the BPF instructions: 8 | 4 | 4 | 16 |
879 32. */
880 if (target_big_endian)
881 {
882 /* code */
883 bytes[0] = (insn.opcode >> 56) & 0xff;
884 /* regs */
885 bytes[1] = (insn.opcode >> 48) & 0xff;
886 /* offset16 */
887 bytes[2] = (insn.opcode >> 40) & 0xff;
888 bytes[3] = (insn.opcode >> 32) & 0xff;
889 /* imm32 */
890 bytes[4] = (insn.opcode >> 24) & 0xff;
891 bytes[5] = (insn.opcode >> 16) & 0xff;
892 bytes[6] = (insn.opcode >> 8) & 0xff;
893 bytes[7] = insn.opcode & 0xff;
894 }
895 else
896 {
897 /* code */
898 bytes[0] = (insn.opcode >> 56) & 0xff;
899 /* regs */
900 bytes[1] = (((((insn.opcode >> 48) & 0xff) & 0xf) << 4)
901 | (((insn.opcode >> 48) & 0xff) & 0xf));
902 /* offset16 */
903 bytes[3] = (insn.opcode >> 40) & 0xff;
904 bytes[2] = (insn.opcode >> 32) & 0xff;
905 /* imm32 */
906 bytes[7] = (insn.opcode >> 24) & 0xff;
907 bytes[6] = (insn.opcode >> 16) & 0xff;
908 bytes[5] = (insn.opcode >> 8) & 0xff;
909 bytes[4] = insn.opcode & 0xff;
910 }
ff5a51b3 911
d218e7fe
JM
912 /* Now the registers. */
913 src = insn.has_src ? insn.src : 0;
914 dst = insn.has_dst ? insn.dst : 0;
ff5a51b3 915
d218e7fe
JM
916 if (target_big_endian)
917 bytes[1] = ((dst & 0xf) << 4) | (src & 0xf);
918 else
919 bytes[1] = ((src & 0xf) << 4) | (dst & 0xf);
ff5a51b3 920
d218e7fe
JM
921 /* Now the immediates. */
922 if (insn.has_imm64)
923 {
924 switch (insn.imm64.X_op)
925 {
926 case O_constant:
927 {
928 uint64_t imm64 = insn.imm64.X_add_number;
929
930 if (target_big_endian)
931 {
932 bytes[12] = (imm64 >> 56) & 0xff;
933 bytes[13] = (imm64 >> 48) & 0xff;
934 bytes[14] = (imm64 >> 40) & 0xff;
935 bytes[15] = (imm64 >> 32) & 0xff;
936 bytes[4] = (imm64 >> 24) & 0xff;
937 bytes[5] = (imm64 >> 16) & 0xff;
938 bytes[6] = (imm64 >> 8) & 0xff;
939 bytes[7] = imm64 & 0xff;
940 }
941 else
942 {
943 bytes[15] = (imm64 >> 56) & 0xff;
944 bytes[14] = (imm64 >> 48) & 0xff;
945 bytes[13] = (imm64 >> 40) & 0xff;
946 bytes[12] = (imm64 >> 32) & 0xff;
947 bytes[7] = (imm64 >> 24) & 0xff;
948 bytes[6] = (imm64 >> 16) & 0xff;
949 bytes[5] = (imm64 >> 8) & 0xff;
950 bytes[4] = imm64 & 0xff;
951 }
952 break;
953 }
954 case O_symbol:
955 case O_subtract:
956 case O_add:
957 {
958 reloc_howto_type *reloc_howto;
959 int size;
960
961 reloc_howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_BPF_64);
962 if (!reloc_howto)
963 abort ();
964
965 size = bfd_get_reloc_size (reloc_howto);
966
967 fix_new_exp (frag_now, this_frag - frag_now->fr_literal,
968 size, &insn.imm64, reloc_howto->pc_relative,
969 BFD_RELOC_BPF_64);
970 break;
971 }
972 default:
973 abort ();
974 }
975 }
ff5a51b3 976
d218e7fe
JM
977 if (insn.has_imm32)
978 {
979 switch (insn.imm32.X_op)
980 {
981 case O_constant:
982 {
983 uint32_t imm32 = insn.imm32.X_add_number;
984
985 if (target_big_endian)
986 {
987 bytes[4] = (imm32 >> 24) & 0xff;
988 bytes[5] = (imm32 >> 16) & 0xff;
989 bytes[6] = (imm32 >> 8) & 0xff;
990 bytes[7] = imm32 & 0xff;
991 }
992 else
993 {
994 bytes[7] = (imm32 >> 24) & 0xff;
995 bytes[6] = (imm32 >> 16) & 0xff;
996 bytes[5] = (imm32 >> 8) & 0xff;
997 bytes[4] = imm32 & 0xff;
998 }
999 break;
1000 }
1001 case O_symbol:
1002 case O_subtract:
1003 case O_add:
1004 case O_uminus:
1005 {
1006 reloc_howto_type *reloc_howto;
1007 int size;
1008
1009 reloc_howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
1010 if (!reloc_howto)
1011 abort ();
1012
1013 size = bfd_get_reloc_size (reloc_howto);
1014
1015 fix_new_exp (frag_now, this_frag - frag_now->fr_literal + 4,
1016 size, &insn.imm32, reloc_howto->pc_relative,
1017 BFD_RELOC_32);
1018 break;
1019 }
1020 default:
1021 abort ();
1022 }
1023 }
ff5a51b3 1024
d218e7fe
JM
1025 if (insn.has_disp32)
1026 {
1027 switch (insn.disp32.X_op)
1028 {
1029 case O_constant:
1030 {
1031 uint32_t disp32 = insn.disp32.X_add_number;
1032
1033 if (target_big_endian)
1034 {
1035 bytes[4] = (disp32 >> 24) & 0xff;
1036 bytes[5] = (disp32 >> 16) & 0xff;
1037 bytes[6] = (disp32 >> 8) & 0xff;
1038 bytes[7] = disp32 & 0xff;
1039 }
1040 else
1041 {
1042 bytes[7] = (disp32 >> 24) & 0xff;
1043 bytes[6] = (disp32 >> 16) & 0xff;
1044 bytes[5] = (disp32 >> 8) & 0xff;
1045 bytes[4] = disp32 & 0xff;
1046 }
1047 break;
1048 }
1049 case O_symbol:
1050 case O_subtract:
1051 case O_add:
1052 {
1053 reloc_howto_type *reloc_howto;
1054 int size;
c2ca88d7
JM
1055 unsigned int bfd_reloc
1056 = (insn.id == BPF_INSN_CALL
1057 ? BFD_RELOC_BPF_DISPCALL32
1058 : BFD_RELOC_BPF_DISP32);
d218e7fe 1059
c2ca88d7 1060 reloc_howto = bfd_reloc_type_lookup (stdoutput, bfd_reloc);
d218e7fe
JM
1061 if (!reloc_howto)
1062 abort ();
1063
1064 size = bfd_get_reloc_size (reloc_howto);
1065
1066 fix_new_exp (frag_now, this_frag - frag_now->fr_literal,
1067 size, &insn.disp32, reloc_howto->pc_relative,
c2ca88d7 1068 bfd_reloc);
d218e7fe
JM
1069 break;
1070 }
1071 default:
1072 abort ();
1073 }
1074 }
ff5a51b3 1075
d218e7fe
JM
1076 if (insn.has_offset16)
1077 {
1078 switch (insn.offset16.X_op)
1079 {
1080 case O_constant:
1081 {
1082 uint32_t offset16 = insn.offset16.X_add_number;
1083
1084 if (target_big_endian)
1085 {
1086 bytes[2] = (offset16 >> 8) & 0xff;
1087 bytes[3] = offset16 & 0xff;
1088 }
1089 else
1090 {
1091 bytes[3] = (offset16 >> 8) & 0xff;
1092 bytes[2] = offset16 & 0xff;
1093 }
1094 break;
1095 }
1096 case O_symbol:
1097 case O_subtract:
1098 case O_add:
1099 {
1100 reloc_howto_type *reloc_howto;
1101 int size;
1102
1103 reloc_howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_BPF_DISP16);
1104 if (!reloc_howto)
1105 abort ();
1106
1107 size = bfd_get_reloc_size (reloc_howto);
1108
1109 fix_new_exp (frag_now, this_frag - frag_now->fr_literal,
1110 size, &insn.offset16, reloc_howto->pc_relative,
1111 BFD_RELOC_BPF_DISP16);
1112 break;
1113 }
1114 default:
1115 abort ();
1116 }
1117 }
ff5a51b3 1118
d218e7fe
JM
1119 if (insn.has_disp16)
1120 {
1121 switch (insn.disp16.X_op)
1122 {
1123 case O_constant:
1124 {
1125 uint32_t disp16 = insn.disp16.X_add_number;
1126
1127 if (target_big_endian)
1128 {
1129 bytes[2] = (disp16 >> 8) & 0xff;
1130 bytes[3] = disp16 & 0xff;
1131 }
1132 else
1133 {
1134 bytes[3] = (disp16 >> 8) & 0xff;
1135 bytes[2] = disp16 & 0xff;
1136 }
1137 break;
1138 }
1139 case O_symbol:
1140 case O_subtract:
1141 case O_add:
1142 {
1143 reloc_howto_type *reloc_howto;
1144 int size;
1145
1146 reloc_howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_BPF_DISP16);
1147 if (!reloc_howto)
1148 abort ();
1149
1150 size = bfd_get_reloc_size (reloc_howto);
1151
1152 fix_new_exp (frag_now, this_frag - frag_now->fr_literal,
1153 size, &insn.disp16, reloc_howto->pc_relative,
1154 BFD_RELOC_BPF_DISP16);
1155 break;
1156 }
1157 default:
1158 abort ();
1159 }
1160 }
ff5a51b3 1161
d218e7fe
JM
1162 /* Emit bytes. */
1163 for (i = 0; i < insn.size; ++i)
1164 {
1165 md_number_to_chars (this_frag, (valueT) bytes[i], 1);
1166 this_frag += 1;
1167 }
1168 }
ff5a51b3 1169
d218e7fe
JM
1170 /* Emit DWARF2 debugging information. */
1171 dwarf2_emit_insn (insn.size);
ff5a51b3
GM
1172}
1173
d218e7fe 1174/* Parse an operand that is machine-specific. */
f8861f5d
JM
1175
1176void
1177md_operand (expressionS *expressionP)
1178{
d218e7fe
JM
1179 /* If this hook is invoked it means GAS failed to parse a generic
1180 expression. We should inhibit the as_bad in expr.c, so we can fail
1181 while parsing instruction alternatives. To do that, we change the
1182 expression to not have an O_absent. But then we also need to set
1183 exp_parse_failed to parse_expression above does the right thing. */
1184 ++input_line_pointer;
1185 expressionP->X_op = O_constant;
1186 expressionP->X_add_number = 0;
1187 exp_parse_failed = 1;
f8861f5d
JM
1188}
1189
f8861f5d
JM
1190symbolS *
1191md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1192{
1193 return NULL;
1194}
1195
1196\f
1197/* Turn a string in input_line_pointer into a floating point constant
1198 of type TYPE, and store the appropriate bytes in *LITP. The number
1199 of LITTLENUMS emitted is stored in *SIZEP. An error message is
1200 returned, or NULL on OK. */
1201
1202const char *
1203md_atof (int type, char *litP, int *sizeP)
1204{
5b7c81bd 1205 return ieee_md_atof (type, litP, sizeP, false);
f8861f5d 1206}
d218e7fe
JM
1207
1208\f
1209/* Determine whether the equal sign in the given string corresponds to
1210 a BPF instruction, i.e. when it is not to be considered a symbol
1211 assignment. */
1212
1213bool
1214bpf_tc_equal_in_insn (int c ATTRIBUTE_UNUSED, char *str ATTRIBUTE_UNUSED)
1215{
1216 uint8_t regno;
1217
1218 /* Only pseudo-c instructions can have equal signs, and of these,
1219 all that could be confused with a symbol assignment all start
1220 with a register name. */
1221 if (asm_dialect == DIALECT_PSEUDOC)
1222 {
1223 char *w = parse_bpf_register (str, 'w', &regno);
1224 char *r = parse_bpf_register (str, 'r', &regno);
1225
1226 if ((w != NULL && *w == '\0')
1227 || (r != NULL && *r == '\0'))
1228 return 1;
1229 }
1230
1231 return 0;
1232}