cpu,gas,opcodes: remove no longer needed workaround from the BPF port
[deliverable/binutils-gdb.git] / gas / config / tc-bpf.c
1 /* tc-bpf.c -- Assembler for the Linux eBPF.
2 Copyright (C) 2019-2020 Free Software Foundation, Inc.
3 Contributed by Oracle, Inc.
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to
19 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20 Boston, MA 02110-1301, USA. */
21
22 #include "as.h"
23 #include "subsegs.h"
24 #include "symcat.h"
25 #include "opcodes/bpf-desc.h"
26 #include "opcodes/bpf-opc.h"
27 #include "cgen.h"
28 #include "elf/common.h"
29 #include "elf/bpf.h"
30 #include "dwarf2dbg.h"
31
32 const char comment_chars[] = ";";
33 const char line_comment_chars[] = "#";
34 const char line_separator_chars[] = "`";
35 const char EXP_CHARS[] = "eE";
36 const char FLT_CHARS[] = "fFdD";
37
38 /* Like s_lcomm_internal in gas/read.c but the alignment string
39 is allowed to be optional. */
40
41 static symbolS *
42 pe_lcomm_internal (int needs_align, symbolS *symbolP, addressT size)
43 {
44 addressT align = 0;
45
46 SKIP_WHITESPACE ();
47
48 if (needs_align
49 && *input_line_pointer == ',')
50 {
51 align = parse_align (needs_align - 1);
52
53 if (align == (addressT) -1)
54 return NULL;
55 }
56 else
57 {
58 if (size >= 8)
59 align = 3;
60 else if (size >= 4)
61 align = 2;
62 else if (size >= 2)
63 align = 1;
64 else
65 align = 0;
66 }
67
68 bss_alloc (symbolP, size, align);
69 return symbolP;
70 }
71
72 static void
73 pe_lcomm (int needs_align)
74 {
75 s_comm_internal (needs_align * 2, pe_lcomm_internal);
76 }
77
78 /* The target specific pseudo-ops which we support. */
79 const pseudo_typeS md_pseudo_table[] =
80 {
81 { "half", cons, 2 },
82 { "word", cons, 4 },
83 { "dword", cons, 8 },
84 { "lcomm", pe_lcomm, 1 },
85 { NULL, NULL, 0 }
86 };
87
88 \f
89
90 /* ISA handling. */
91 static CGEN_BITSET *bpf_isa;
92
93 \f
94
95 /* Command-line options processing. */
96
97 enum options
98 {
99 OPTION_LITTLE_ENDIAN = OPTION_MD_BASE,
100 OPTION_BIG_ENDIAN
101 };
102
103 struct option md_longopts[] =
104 {
105 { "EL", no_argument, NULL, OPTION_LITTLE_ENDIAN },
106 { "EB", no_argument, NULL, OPTION_BIG_ENDIAN },
107 { NULL, no_argument, NULL, 0 },
108 };
109
110 size_t md_longopts_size = sizeof (md_longopts);
111
112 const char * md_shortopts = "";
113
114 extern int target_big_endian;
115
116 /* Whether target_big_endian has been set while parsing command-line
117 arguments. */
118 static int set_target_endian = 0;
119
120 int
121 md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
122 {
123 switch (c)
124 {
125 case OPTION_BIG_ENDIAN:
126 set_target_endian = 1;
127 target_big_endian = 1;
128 break;
129 case OPTION_LITTLE_ENDIAN:
130 set_target_endian = 1;
131 target_big_endian = 0;
132 break;
133 default:
134 return 0;
135 }
136
137 return 1;
138 }
139
140 void
141 md_show_usage (FILE * stream)
142 {
143 fprintf (stream, _("\nBPF options:\n"));
144 fprintf (stream, _("\
145 --EL generate code for a little endian machine\n\
146 --EB generate code for a big endian machine\n"));
147 }
148
149 \f
150 void
151 md_begin (void)
152 {
153 /* Initialize the `cgen' interface. */
154
155 /* If not specified in the command line, use the host
156 endianness. */
157 if (!set_target_endian)
158 {
159 #ifdef WORDS_BIGENDIAN
160 target_big_endian = 1;
161 #else
162 target_big_endian = 0;
163 #endif
164 }
165
166 /* Set the ISA, which depends on the target endianness. */
167 bpf_isa = cgen_bitset_create (ISA_MAX);
168 if (target_big_endian)
169 cgen_bitset_set (bpf_isa, ISA_EBPFBE);
170 else
171 cgen_bitset_set (bpf_isa, ISA_EBPFLE);
172
173 /* Set the machine number and endian. */
174 gas_cgen_cpu_desc = bpf_cgen_cpu_open (CGEN_CPU_OPEN_ENDIAN,
175 target_big_endian ?
176 CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE,
177 CGEN_CPU_OPEN_INSN_ENDIAN,
178 CGEN_ENDIAN_LITTLE,
179 CGEN_CPU_OPEN_ISAS,
180 bpf_isa,
181 CGEN_CPU_OPEN_END);
182 bpf_cgen_init_asm (gas_cgen_cpu_desc);
183
184 /* This is a callback from cgen to gas to parse operands. */
185 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
186
187 /* Set the machine type. */
188 bfd_default_set_arch_mach (stdoutput, bfd_arch_bpf, bfd_mach_bpf);
189 }
190
191 valueT
192 md_section_align (segT segment, valueT size)
193 {
194 int align = bfd_section_alignment (segment);
195
196 return ((size + (1 << align) - 1) & -(1 << align));
197 }
198
199 \f
200 /* Functions concerning relocs. */
201
202 /* The location from which a PC relative jump should be calculated,
203 given a PC relative reloc. */
204
205 long
206 md_pcrel_from_section (fixS *fixP, segT sec)
207 {
208 if (fixP->fx_addsy != (symbolS *) NULL
209 && (! S_IS_DEFINED (fixP->fx_addsy)
210 || (S_GET_SEGMENT (fixP->fx_addsy) != sec)
211 || S_IS_EXTERNAL (fixP->fx_addsy)
212 || S_IS_WEAK (fixP->fx_addsy)))
213 {
214 /* The symbol is undefined (or is defined but not in this section).
215 Let the linker figure it out. */
216 return 0;
217 }
218
219 return fixP->fx_where + fixP->fx_frag->fr_address;
220 }
221
222 /* Write a value out to the object file, using the appropriate endianness. */
223
224 void
225 md_number_to_chars (char * buf, valueT val, int n)
226 {
227 if (target_big_endian)
228 number_to_chars_bigendian (buf, val, n);
229 else
230 number_to_chars_littleendian (buf, val, n);
231 }
232
233 arelent *
234 tc_gen_reloc (asection *sec, fixS *fix)
235 {
236 return gas_cgen_tc_gen_reloc (sec, fix);
237 }
238
239 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP. This
240 is called when the operand is an expression that couldn't be fully
241 resolved. Returns BFD_RELOC_NONE if no reloc type can be found.
242 *FIXP may be modified if desired. */
243
244 bfd_reloc_code_real_type
245 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
246 const CGEN_OPERAND *operand,
247 fixS *fixP)
248 {
249 switch (operand->type)
250 {
251 case BPF_OPERAND_OFFSET16:
252 return BFD_RELOC_BPF_16;
253 case BPF_OPERAND_IMM32:
254 return BFD_RELOC_BPF_32;
255 case BPF_OPERAND_IMM64:
256 return BFD_RELOC_BPF_64;
257 case BPF_OPERAND_DISP16:
258 fixP->fx_pcrel = 1;
259 return BFD_RELOC_BPF_DISP16;
260 case BPF_OPERAND_DISP32:
261 fixP->fx_pcrel = 1;
262 return BFD_RELOC_BPF_DISP32;
263 default:
264 break;
265 }
266 return BFD_RELOC_NONE;
267 }
268 \f
269 /* *FRAGP has been relaxed to its final size, and now needs to have
270 the bytes inside it modified to conform to the new size.
271
272 Called after relaxation is finished.
273 fragP->fr_type == rs_machine_dependent.
274 fragP->fr_subtype is the subtype of what the address relaxed to. */
275
276 void
277 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
278 segT sec ATTRIBUTE_UNUSED,
279 fragS *fragP ATTRIBUTE_UNUSED)
280 {
281 as_fatal (_("convert_frag called"));
282 }
283
284 int
285 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
286 segT segment ATTRIBUTE_UNUSED)
287 {
288 as_fatal (_("estimate_size_before_relax called"));
289 return 0;
290 }
291
292 \f
293 void
294 md_apply_fix (fixS *fixP, valueT *valP, segT seg)
295 {
296 /* Some fixups for instructions require special attention. This is
297 handled in the code block below. */
298 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
299 {
300 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
301 const CGEN_OPERAND *operand = cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
302 opindex);
303 char *where;
304
305 switch (operand->type)
306 {
307 case BPF_OPERAND_DISP32:
308 /* eBPF supports two kind of CALL instructions: the so
309 called pseudo calls ("bpf to bpf") and external calls
310 ("bpf to kernel").
311
312 Both kind of calls use the same instruction (CALL).
313 However, external calls are constructed by passing a
314 constant argument to the instruction, whereas pseudo
315 calls result from expressions involving symbols. In
316 practice, instructions requiring a fixup are interpreted
317 as pseudo-calls. If we are executing this code, this is
318 a pseudo call.
319
320 The kernel expects for pseudo-calls to be annotated by
321 having BPF_PSEUDO_CALL in the SRC field of the
322 instruction. But beware the infamous nibble-swapping of
323 eBPF and take endianness into account here.
324
325 Note that the CALL instruction has only one operand, so
326 this code is executed only once per instruction. */
327 where = fixP->fx_frag->fr_literal + fixP->fx_where;
328 cgen_put_insn_value (gas_cgen_cpu_desc, (unsigned char *) where + 1, 8,
329 target_big_endian ? 0x01 : 0x10,
330 gas_cgen_cpu_desc->endian);
331 /* Fallthrough. */
332 case BPF_OPERAND_DISP16:
333 /* The PC-relative displacement fields in jump instructions
334 shouldn't be in bytes. Instead, they hold the number of
335 64-bit words to the target, _minus one_. */
336 *valP = (((long) (*valP)) - 8) / 8;
337 break;
338 default:
339 break;
340 }
341 }
342
343 /* And now invoke CGEN's handler, which will eventually install
344 *valP into the corresponding operand. */
345 gas_cgen_md_apply_fix (fixP, valP, seg);
346 }
347
348 void
349 md_assemble (char *str)
350 {
351 const CGEN_INSN *insn;
352 char *errmsg;
353 CGEN_FIELDS fields;
354
355 #if CGEN_INT_INSN_P
356 CGEN_INSN_INT buffer[CGEN_MAX_INSN_SIZE / sizeof (CGEN_INT_INSN_P)];
357 #else
358 unsigned char buffer[CGEN_MAX_INSN_SIZE];
359 #endif
360
361 gas_cgen_init_parse ();
362 insn = bpf_cgen_assemble_insn (gas_cgen_cpu_desc, str, &fields,
363 buffer, &errmsg);
364
365 if (insn == NULL)
366 {
367 as_bad ("%s", errmsg);
368 return;
369 }
370
371 gas_cgen_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (&fields),
372 0, /* zero to ban relaxable insns. */
373 NULL); /* NULL so results not returned here. */
374 }
375
376 void
377 md_operand (expressionS *expressionP)
378 {
379 gas_cgen_md_operand (expressionP);
380 }
381
382
383 symbolS *
384 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
385 {
386 return NULL;
387 }
388
389 \f
390 /* Turn a string in input_line_pointer into a floating point constant
391 of type TYPE, and store the appropriate bytes in *LITP. The number
392 of LITTLENUMS emitted is stored in *SIZEP. An error message is
393 returned, or NULL on OK. */
394
395 const char *
396 md_atof (int type, char *litP, int *sizeP)
397 {
398 return ieee_md_atof (type, litP, sizeP, FALSE);
399 }
This page took 0.037567 seconds and 5 git commands to generate.