]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gas/config/tc-pru.c
gdb: Avoid compilation warning in gcore.c.
[thirdparty/binutils-gdb.git] / gas / config / tc-pru.c
CommitLineData
93f11b16 1/* TI PRU assembler.
fd67aa11 2 Copyright (C) 2014-2024 Free Software Foundation, Inc.
93f11b16
DD
3 Contributed by Dimitar Dimitrov <dimitar@dinux.eu>
4 Based on tc-nios2.c
5
6 This file is part of GAS, the GNU Assembler.
7
8 GAS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GAS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GAS; see the file COPYING. If not, write to the Free
20 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21 02110-1301, USA. */
22
23#include "as.h"
3dfb1b6d 24#include <stdint.h>
93f11b16
DD
25#include "opcode/pru.h"
26#include "elf/pru.h"
27#include "tc-pru.h"
28#include "bfd.h"
29#include "dwarf2dbg.h"
30#include "subsegs.h"
31#include "safe-ctype.h"
32#include "dw2gencfi.h"
33
34#ifndef OBJ_ELF
35/* We are not supporting any other target so we throw a compile time error. */
36 #error "OBJ_ELF not defined"
37#endif
38
39/* This array holds the chars that always start a comment. If the
40 pre-processor is disabled, these aren't very useful. */
41const char comment_chars[] = "#;";
42
43/* This array holds the chars that only start a comment at the beginning of
44 a line. If the line seems to have the form '# 123 filename'
45 .line and .file directives will appear in the pre-processed output. */
46/* Note that input_file.c hand checks for '#' at the beginning of the
47 first line of the input file. This is because the compiler outputs
48 #NO_APP at the beginning of its output. */
49/* Also note that C style comments are always supported. */
50const char line_comment_chars[] = "#;*";
51
52/* This array holds machine specific line separator characters. */
53const char line_separator_chars[] = "";
54
55/* Chars that can be used to separate mant from exp in floating point nums. */
56const char EXP_CHARS[] = "eE";
57
58/* Chars that mean this number is a floating point constant.
59 As in 0f12.456
60 or 0d1.2345e12 */
61const char FLT_CHARS[] = "rRsSfFdDxXpP";
62
63/* Machine-dependent command-line options. */
64
65struct pru_opt_s
66{
67 /* -mno-link-relax / -mlink-relax: generate (or not)
68 relocations for linker relaxation. */
5b7c81bd 69 bool link_relax;
93f11b16
DD
70
71 /* -mno-warn-regname-label: do not output a warning that a label name
72 matches a register name. */
5b7c81bd 73 bool warn_regname_label;
93f11b16
DD
74};
75
5b7c81bd 76static struct pru_opt_s pru_opt = { true, true };
93f11b16
DD
77
78const char *md_shortopts = "r";
79
80enum options
81{
82 OPTION_LINK_RELAX = OPTION_MD_BASE + 1,
83 OPTION_NO_LINK_RELAX,
84 OPTION_NO_WARN_REGNAME_LABEL,
85};
86
87struct option md_longopts[] = {
88 { "mlink-relax", no_argument, NULL, OPTION_LINK_RELAX },
89 { "mno-link-relax", no_argument, NULL, OPTION_NO_LINK_RELAX },
90 { "mno-warn-regname-label", no_argument, NULL,
91 OPTION_NO_WARN_REGNAME_LABEL },
92 { NULL, no_argument, NULL, 0 }
93};
94
95size_t md_longopts_size = sizeof (md_longopts);
96
97typedef struct pru_insn_reloc
98{
99 /* Any expression in the instruction is parsed into this field,
100 which is passed to fix_new_exp () to generate a fixup. */
101 expressionS reloc_expression;
102
103 /* The type of the relocation to be applied. */
104 bfd_reloc_code_real_type reloc_type;
105
106 /* PC-relative. */
107 unsigned int reloc_pcrel;
108
109 /* The next relocation to be applied to the instruction. */
110 struct pru_insn_reloc *reloc_next;
111} pru_insn_relocS;
112
113/* This struct is used to hold state when assembling instructions. */
114typedef struct pru_insn_info
115{
116 /* Assembled instruction. */
117 unsigned long insn_code;
118 /* Used for assembling LDI32. */
119 unsigned long ldi32_imm32;
120
121 /* Pointer to the relevant bit of the opcode table. */
122 const struct pru_opcode *insn_pru_opcode;
123 /* After parsing ptrs to the tokens in the instruction fill this array
124 it is terminated with a null pointer (hence the first +1).
125 The second +1 is because in some parts of the code the opcode
126 is not counted as a token, but still placed in this array. */
127 const char *insn_tokens[PRU_MAX_INSN_TOKENS + 1 + 1];
128
129 /* This holds information used to generate fixups
130 and eventually relocations if it is not null. */
131 pru_insn_relocS *insn_reloc;
132} pru_insn_infoS;
133
134/* Opcode hash table. */
629310ab 135static htab_t pru_opcode_hash = NULL;
93f11b16 136#define pru_opcode_lookup(NAME) \
629310ab 137 ((struct pru_opcode *) str_hash_find (pru_opcode_hash, (NAME)))
93f11b16
DD
138
139/* Register hash table. */
629310ab 140static htab_t pru_reg_hash = NULL;
93f11b16 141#define pru_reg_lookup(NAME) \
629310ab 142 ((struct pru_reg *) str_hash_find (pru_reg_hash, (NAME)))
93f11b16
DD
143
144/* The known current alignment of the current section. */
145static int pru_current_align;
146static segT pru_current_align_seg;
147
148static int pru_auto_align_on = 1;
149
150/* The last seen label in the current section. This is used to auto-align
33eaf5de 151 labels preceding instructions. */
93f11b16
DD
152static symbolS *pru_last_label;
153
154\f
155/** Utility routines. */
156/* Function md_chars_to_number takes the sequence of
157 bytes in buf and returns the corresponding value
158 in an int. n must be 1, 2, 4 or 8. */
159static uint64_t
160md_chars_to_number (char *buf, int n)
161{
162 int i;
163 uint64_t val;
164
165 gas_assert (n == 1 || n == 2 || n == 4 || n == 8);
166
167 val = 0;
168 for (i = 0; i < n; ++i)
169 val = val | ((buf[i] & 0xff) << 8 * i);
170 return val;
171}
172
173
174/* This function turns a C long int, short int or char
175 into the series of bytes that represent the number
176 on the target machine. */
177void
ddb2c6fd 178md_number_to_chars (char *buf, valueT val, int n)
93f11b16
DD
179{
180 gas_assert (n == 1 || n == 2 || n == 4 || n == 8);
181 number_to_chars_littleendian (buf, val, n);
182}
183
184/* Turn a string in input_line_pointer into a floating point constant
185 of type TYPE, and store the appropriate bytes in *LITP. The number
186 of LITTLENUMS emitted is stored in *SIZEP. An error message is
187 returned, or NULL on OK. */
188const char *
189md_atof (int type, char *litP, int *sizeP)
190{
5b7c81bd 191 return ieee_md_atof (type, litP, sizeP, false);
93f11b16
DD
192}
193
194/* Return true if STR starts with PREFIX, which should be a string literal. */
195#define strprefix(STR, PREFIX) \
196 (strncmp ((STR), PREFIX, strlen (PREFIX)) == 0)
197
198/* nop fill pattern for text section. */
199static char const nop[4] = { 0xe0, 0xe0, 0xe0, 0x12 };
200
201/* Handles all machine-dependent alignment needs. */
202static void
203pru_align (int log_size, const char *pfill, symbolS *label)
204{
205 int align;
206 long max_alignment = 15;
207
208 /* The front end is prone to changing segments out from under us
209 temporarily when -g is in effect. */
210 int switched_seg_p = (pru_current_align_seg != now_seg);
211
212 align = log_size;
213 if (align > max_alignment)
214 {
215 align = max_alignment;
216 as_bad (_("Alignment too large: %d assumed"), align);
217 }
218 else if (align < 0)
219 {
220 as_warn (_("Alignment negative: 0 assumed"));
221 align = 0;
222 }
223
224 if (align != 0)
225 {
226 if (subseg_text_p (now_seg) && align >= 2)
227 {
228 /* First, make sure we're on a four-byte boundary, in case
229 someone has been putting .byte values the text section. */
230 if (pru_current_align < 2 || switched_seg_p)
231 frag_align (2, 0, 0);
232
233 /* Now fill in the alignment pattern. */
234 if (pfill != NULL)
235 frag_align_pattern (align, pfill, sizeof nop, 0);
236 else
237 frag_align (align, 0, 0);
238 }
239 else
240 frag_align (align, 0, 0);
241
242 if (!switched_seg_p)
243 pru_current_align = align;
244
245 /* If the last label was in a different section we can't align it. */
246 if (label != NULL && !switched_seg_p)
247 {
248 symbolS *sym;
5b7c81bd 249 int label_seen = false;
93f11b16
DD
250 struct frag *old_frag;
251 valueT old_value;
252 valueT new_value;
253
254 gas_assert (S_GET_SEGMENT (label) == now_seg);
255
256 old_frag = symbol_get_frag (label);
257 old_value = S_GET_VALUE (label);
258 new_value = (valueT) frag_now_fix ();
259
260 /* It is possible to have more than one label at a particular
261 address, especially if debugging is enabled, so we must
262 take care to adjust all the labels at this address in this
263 fragment. To save time we search from the end of the symbol
264 list, backwards, since the symbols we are interested in are
265 almost certainly the ones that were most recently added.
266 Also to save time we stop searching once we have seen at least
267 one matching label, and we encounter a label that is no longer
268 in the target fragment. Note, this search is guaranteed to
269 find at least one match when sym == label, so no special case
270 code is necessary. */
271 for (sym = symbol_lastP; sym != NULL; sym = symbol_previous (sym))
272 if (symbol_get_frag (sym) == old_frag
273 && S_GET_VALUE (sym) == old_value)
274 {
5b7c81bd 275 label_seen = true;
93f11b16
DD
276 symbol_set_frag (sym, frag_now);
277 S_SET_VALUE (sym, new_value);
278 }
279 else if (label_seen && symbol_get_frag (sym) != old_frag)
280 break;
281 }
282 record_alignment (now_seg, align);
283 }
284}
285
286\f
287/** Support for self-check mode. */
288
289/* Mode of the assembler. */
290typedef enum
291{
292 PRU_MODE_ASSEMBLE, /* Ordinary operation. */
293 PRU_MODE_TEST /* Hidden mode used for self testing. */
294} PRU_MODE;
295
296static PRU_MODE pru_mode = PRU_MODE_ASSEMBLE;
297
298/* This function is used to in self-checking mode
0bae9e9e
NC
299 to check the assembled instruction.
300 OPCODE should be the assembled opcode, and exp_opcode
93f11b16 301 the parsed string representing the expected opcode. */
0bae9e9e 302
93f11b16
DD
303static void
304pru_check_assembly (unsigned int opcode, const char *exp_opcode)
305{
306 if (pru_mode == PRU_MODE_TEST)
307 {
308 if (exp_opcode == NULL)
309 as_bad (_("expecting opcode string in self test mode"));
310 else if (opcode != strtoul (exp_opcode, NULL, 16))
311 as_bad (_("assembly 0x%08x, expected %s"), opcode, exp_opcode);
312 }
313}
314
315\f
316/** Support for machine-dependent assembler directives. */
317/* Handle the .align pseudo-op. This aligns to a power of two. It
318 also adjusts any current instruction label. We treat this the same
319 way the MIPS port does: .align 0 turns off auto alignment. */
320static void
321s_pru_align (int ignore ATTRIBUTE_UNUSED)
322{
323 int align;
324 char fill;
325 const char *pfill = NULL;
326 long max_alignment = 15;
327
328 align = get_absolute_expression ();
329 if (align > max_alignment)
330 {
331 align = max_alignment;
332 as_bad (_("Alignment too large: %d assumed"), align);
333 }
334 else if (align < 0)
335 {
336 as_warn (_("Alignment negative: 0 assumed"));
337 align = 0;
338 }
339
340 if (*input_line_pointer == ',')
341 {
342 input_line_pointer++;
343 fill = get_absolute_expression ();
344 pfill = (const char *) &fill;
345 }
346 else if (subseg_text_p (now_seg))
347 pfill = (const char *) &nop;
348 else
349 {
350 pfill = NULL;
351 pru_last_label = NULL;
352 }
353
354 if (align != 0)
355 {
356 pru_auto_align_on = 1;
357 pru_align (align, pfill, pru_last_label);
358 pru_last_label = NULL;
359 }
360 else
361 pru_auto_align_on = 0;
362
363 demand_empty_rest_of_line ();
364}
365
366/* Handle the .text pseudo-op. This is like the usual one, but it
367 clears the saved last label and resets known alignment. */
368static void
369s_pru_text (int i)
370{
8fc8d7cd 371 obj_elf_text (i);
93f11b16
DD
372 pru_last_label = NULL;
373 pru_current_align = 0;
374 pru_current_align_seg = now_seg;
375}
376
377/* Handle the .data pseudo-op. This is like the usual one, but it
378 clears the saved last label and resets known alignment. */
379static void
380s_pru_data (int i)
381{
8fc8d7cd 382 obj_elf_data (i);
93f11b16
DD
383 pru_last_label = NULL;
384 pru_current_align = 0;
385 pru_current_align_seg = now_seg;
386}
387
388/* Handle the .section pseudo-op. This is like the usual one, but it
389 clears the saved last label and resets known alignment. */
390static void
391s_pru_section (int ignore)
392{
393 obj_elf_section (ignore);
394 pru_last_label = NULL;
395 pru_current_align = 0;
396 pru_current_align_seg = now_seg;
397}
398
399/* Explicitly unaligned cons. */
400static void
401s_pru_ucons (int nbytes)
402{
403 int hold;
404 hold = pru_auto_align_on;
405 pru_auto_align_on = 0;
406 cons (nbytes);
407 pru_auto_align_on = hold;
408}
409
410/* .set sets assembler options. */
411static void
412s_pru_set (int equiv)
413{
414 char *save = input_line_pointer;
415 char *directive;
416 char delim = get_symbol_name (&directive);
417 char *endline = input_line_pointer;
418
419 (void) restore_line_pointer (delim);
420
421 /* We only want to handle ".set XXX" if the
422 user has tried ".set XXX, YYY" they are not
423 trying a directive. This prevents
424 us from polluting the name space. */
425 SKIP_WHITESPACE ();
426 if (is_end_of_line[(unsigned char) *input_line_pointer])
427 {
5b7c81bd 428 bool done = true;
93f11b16
DD
429 *endline = 0;
430
431 if (!strcmp (directive, "no_warn_regname_label"))
5b7c81bd 432 pru_opt.warn_regname_label = false;
93f11b16 433 else
5b7c81bd 434 done = false;
93f11b16
DD
435
436 if (done)
437 {
438 *endline = delim;
439 demand_empty_rest_of_line ();
440 return;
441 }
442 }
443
444 /* If we fall through to here, either we have ".set XXX, YYY"
445 or we have ".set XXX" where XXX is unknown or we have
446 a syntax error. */
447 input_line_pointer = save;
448 s_set (equiv);
449}
450
451/* Machine-dependent assembler directives.
452 Format of each entry is:
453 { "directive", handler_func, param } */
454const pseudo_typeS md_pseudo_table[] = {
455 {"align", s_pru_align, 0},
456 {"text", s_pru_text, 0},
457 {"data", s_pru_data, 0},
458 {"section", s_pru_section, 0},
459 {"section.s", s_pru_section, 0},
460 {"sect", s_pru_section, 0},
461 {"sect.s", s_pru_section, 0},
462 /* .dword and .half are included for compatibility with MIPS. */
463 {"dword", cons, 8},
464 {"half", cons, 2},
465 /* PRU native word size is 4 bytes, so we override
466 the GAS default of 2. */
467 {"word", cons, 4},
468 /* Explicitly unaligned directives. */
469 {"2byte", s_pru_ucons, 2},
470 {"4byte", s_pru_ucons, 4},
471 {"8byte", s_pru_ucons, 8},
472 {"16byte", s_pru_ucons, 16},
473 {"set", s_pru_set, 0},
474 {NULL, NULL, 0}
475};
476
477\f
478int
479md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
480 asection *seg ATTRIBUTE_UNUSED)
481{
482 abort ();
483 return 0;
484}
485
486void
487md_convert_frag (bfd *headers ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED,
488 fragS *fragp ATTRIBUTE_UNUSED)
489{
490 abort ();
491}
492
493\f
5b7c81bd 494static bool
93f11b16
DD
495relaxable_section (asection *sec)
496{
497 return ((sec->flags & SEC_DEBUGGING) == 0
498 && (sec->flags & SEC_CODE) != 0
499 && (sec->flags & SEC_ALLOC) != 0);
500}
501
502/* Does whatever the xtensa port does. */
503int
504pru_validate_fix_sub (fixS *fix)
505{
506 segT add_symbol_segment, sub_symbol_segment;
507
508 /* The difference of two symbols should be resolved by the assembler when
509 linkrelax is not set. If the linker may relax the section containing
510 the symbols, then an Xtensa DIFF relocation must be generated so that
511 the linker knows to adjust the difference value. */
512 if (!linkrelax || fix->fx_addsy == NULL)
513 return 0;
514
515 /* Make sure both symbols are in the same segment, and that segment is
516 "normal" and relaxable. If the segment is not "normal", then the
517 fix is not valid. If the segment is not "relaxable", then the fix
518 should have been handled earlier. */
519 add_symbol_segment = S_GET_SEGMENT (fix->fx_addsy);
520 if (! SEG_NORMAL (add_symbol_segment)
521 || ! relaxable_section (add_symbol_segment))
522 return 0;
523
524 sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
525 return (sub_symbol_segment == add_symbol_segment);
526}
527
528/* TC_FORCE_RELOCATION hook. */
529
530/* If linkrelax is turned on, and the symbol to relocate
531 against is in a relaxable segment, don't compute the value -
532 generate a relocation instead. */
533int
534pru_force_relocation (fixS *fix)
535{
536 if (linkrelax && fix->fx_addsy
537 && relaxable_section (S_GET_SEGMENT (fix->fx_addsy)))
538 return 1;
539
540 return generic_force_reloc (fix);
541}
542
543
544\f
545/** Fixups and overflow checking. */
546
547/* Check a fixup for overflow. */
548static bfd_reloc_status_type
549pru_check_overflow (valueT fixup, reloc_howto_type *howto)
550{
551 bfd_reloc_status_type ret;
552
553 ret = bfd_check_overflow (howto->complain_on_overflow,
554 howto->bitsize,
555 howto->rightshift,
556 bfd_get_reloc_size (howto) * 8,
557 fixup);
558
559 return ret;
560}
561
562/* Emit diagnostic for fixup overflow. */
563static void
564pru_diagnose_overflow (valueT fixup, reloc_howto_type *howto,
565 fixS *fixP, valueT value)
566{
567 if (fixP->fx_r_type == BFD_RELOC_8
568 || fixP->fx_r_type == BFD_RELOC_16
569 || fixP->fx_r_type == BFD_RELOC_32)
570 /* These relocs are against data, not instructions. */
571 as_bad_where (fixP->fx_file, fixP->fx_line,
572 _("immediate value 0x%x truncated to 0x%x"),
573 (unsigned int) fixup,
574 (unsigned int) (~(~(valueT) 0 << howto->bitsize) & fixup));
575 else
576 {
577 /* What opcode is the instruction? This will determine
578 whether we check for overflow in immediate values
579 and what error message we get. */
580 const struct pru_opcode *opcode;
581 enum overflow_type overflow_msg_type;
582 unsigned int range_min;
583 unsigned int range_max;
584 unsigned int address;
585 gas_assert (fixP->fx_size == 4);
586 opcode = pru_find_opcode (value);
587 gas_assert (opcode);
588 overflow_msg_type = opcode->overflow_msg;
589 switch (overflow_msg_type)
590 {
591 case call_target_overflow:
592 range_min
593 = ((fixP->fx_frag->fr_address + fixP->fx_where) & 0xf0000000);
594 range_max = range_min + 0x0fffffff;
595 address = fixup | range_min;
596
597 as_bad_where (fixP->fx_file, fixP->fx_line,
598 _("call target address 0x%08x out of range 0x%08x to 0x%08x"),
599 address, range_min, range_max);
600 break;
601 case qbranch_target_overflow:
602 as_bad_where (fixP->fx_file, fixP->fx_line,
603 _("quick branch offset %d out of range %d to %d"),
604 (int)fixup, -((1<<9) * 4), (1 << 9) * 4);
605 break;
606 case address_offset_overflow:
607 as_bad_where (fixP->fx_file, fixP->fx_line,
608 _("%s offset %d out of range %d to %d"),
609 opcode->name, (int)fixup, -32768, 32767);
610 break;
611 case signed_immed16_overflow:
612 as_bad_where (fixP->fx_file, fixP->fx_line,
613 _("immediate value %d out of range %d to %d"),
614 (int)fixup, -32768, 32767);
615 break;
616 case unsigned_immed32_overflow:
617 as_bad_where (fixP->fx_file, fixP->fx_line,
618 _("immediate value %llu out of range %u to %lu"),
619 (unsigned long long)fixup, 0, 0xfffffffflu);
620 break;
621 case unsigned_immed16_overflow:
622 as_bad_where (fixP->fx_file, fixP->fx_line,
623 _("immediate value %u out of range %u to %u"),
624 (unsigned int)fixup, 0, 65535);
625 break;
626 case unsigned_immed5_overflow:
627 as_bad_where (fixP->fx_file, fixP->fx_line,
628 _("immediate value %u out of range %u to %u"),
629 (unsigned int)fixup, 0, 31);
630 break;
631 default:
632 as_bad_where (fixP->fx_file, fixP->fx_line,
633 _("overflow in immediate argument"));
634 break;
635 }
636 }
637}
638
639/* Apply a fixup to the object file. */
640void
641md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
642{
643 unsigned char *where;
644 valueT value = *valP;
93f11b16
DD
645
646 /* Assert that the fixup is one we can handle. */
647 gas_assert (fixP != NULL && valP != NULL
648 && (fixP->fx_r_type == BFD_RELOC_8
649 || fixP->fx_r_type == BFD_RELOC_16
650 || fixP->fx_r_type == BFD_RELOC_32
651 || fixP->fx_r_type == BFD_RELOC_64
652 || fixP->fx_r_type == BFD_RELOC_PRU_LDI32
653 || fixP->fx_r_type == BFD_RELOC_PRU_U16
654 || fixP->fx_r_type == BFD_RELOC_PRU_U16_PMEMIMM
655 || fixP->fx_r_type == BFD_RELOC_PRU_S10_PCREL
656 || fixP->fx_r_type == BFD_RELOC_PRU_U8_PCREL
657 || fixP->fx_r_type == BFD_RELOC_PRU_32_PMEM
658 || fixP->fx_r_type == BFD_RELOC_PRU_16_PMEM
659 /* Add other relocs here as we generate them. */
660 ));
661
662 if (fixP->fx_r_type == BFD_RELOC_64)
663 {
664 /* We may reach here due to .8byte directives, but we never output
665 BFD_RELOC_64; it must be resolved. */
666 if (fixP->fx_addsy != NULL)
667 as_bad_where (fixP->fx_file, fixP->fx_line,
668 _("cannot create 64-bit relocation"));
669 else
670 {
671 md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
672 *valP, 8);
673 fixP->fx_done = 1;
674 }
675 return;
676 }
677
678 /* gas_assert (had_errors () || !fixP->fx_subsy); */
679
680 /* In general, fix instructions with immediate
681 constants. But leave LDI32 for the linker,
682 which is prepared to shorten insns. */
683 if (fixP->fx_addsy == (symbolS *) NULL
684 && fixP->fx_r_type != BFD_RELOC_PRU_LDI32)
685 fixP->fx_done = 1;
686
687 else if (fixP->fx_pcrel)
688 {
689 segT s = S_GET_SEGMENT (fixP->fx_addsy);
690
691 if (s == seg || s == absolute_section)
692 {
693 /* Blindly copied from AVR, but I don't understand why
694 this is needed in the first place. Fail hard to catch
695 when this curious code snippet is utilized. */
696 as_bad_where (fixP->fx_file, fixP->fx_line,
697 _("unexpected PC relative expression"));
698 value += S_GET_VALUE (fixP->fx_addsy);
699 fixP->fx_done = 1;
700 }
701 }
702 else if (linkrelax && fixP->fx_subsy)
703 {
704 /* For a subtraction relocation expression, generate one
705 of the DIFF relocs, with the value being the difference.
706 Note that a sym1 - sym2 expression is adjusted into a
707 section_start_sym + sym4_offset_from_section_start - sym1
708 expression. fixP->fx_addsy holds the section start symbol,
709 fixP->fx_offset holds sym2's offset, and fixP->fx_subsy
710 holds sym1. Calculate the current difference and write value,
711 but leave fx_offset as is - during relaxation,
712 fx_offset - value gives sym1's value. */
713
714 offsetT diffval; /* valueT is unsigned, so use offsetT. */
715
716 diffval = S_GET_VALUE (fixP->fx_addsy)
717 + fixP->fx_offset - S_GET_VALUE (fixP->fx_subsy);
718
719 switch (fixP->fx_r_type)
720 {
721 case BFD_RELOC_8:
722 fixP->fx_r_type = BFD_RELOC_PRU_GNU_DIFF8;
723 break;
724 case BFD_RELOC_16:
725 fixP->fx_r_type = BFD_RELOC_PRU_GNU_DIFF16;
726 break;
727 case BFD_RELOC_32:
728 fixP->fx_r_type = BFD_RELOC_PRU_GNU_DIFF32;
729 break;
730 case BFD_RELOC_PRU_16_PMEM:
731 fixP->fx_r_type = BFD_RELOC_PRU_GNU_DIFF16_PMEM;
732 if (diffval % 4)
733 as_bad_where (fixP->fx_file, fixP->fx_line,
734 _("residual low bits in pmem diff relocation"));
735 diffval /= 4;
736 break;
737 case BFD_RELOC_PRU_32_PMEM:
738 fixP->fx_r_type = BFD_RELOC_PRU_GNU_DIFF32_PMEM;
739 if (diffval % 4)
740 as_bad_where (fixP->fx_file, fixP->fx_line,
741 _("residual low bits in pmem diff relocation"));
742 diffval /= 4;
743 break;
744 default:
4bf09429 745 as_bad_subtract (fixP);
93f11b16
DD
746 break;
747 }
748
749 value = *valP = diffval;
750
751 fixP->fx_subsy = NULL;
752 }
753 /* We don't actually support subtracting a symbol. */
754 if (fixP->fx_subsy != (symbolS *) NULL)
4bf09429 755 as_bad_subtract (fixP);
93f11b16
DD
756
757 /* For the DIFF relocs, write the value into the object file while still
758 keeping fx_done FALSE, as both the difference (recorded in the object file)
759 and the sym offset (part of fixP) are needed at link relax time. */
760 where = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
761 switch (fixP->fx_r_type)
762 {
763 case BFD_RELOC_PRU_GNU_DIFF8:
764 *where = value;
765 break;
766 case BFD_RELOC_PRU_GNU_DIFF16:
767 case BFD_RELOC_PRU_GNU_DIFF16_PMEM:
768 bfd_putl16 ((bfd_vma) value, where);
769 break;
770 case BFD_RELOC_PRU_GNU_DIFF32:
771 case BFD_RELOC_PRU_GNU_DIFF32_PMEM:
772 bfd_putl32 ((bfd_vma) value, where);
773 break;
774 default:
775 break;
776 }
777
778 if (fixP->fx_done)
779 /* Fully resolved fixup. */
780 {
781 reloc_howto_type *howto
782 = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
783
784 if (howto == NULL)
785 as_bad_where (fixP->fx_file, fixP->fx_line,
786 _("relocation is not supported"));
787 else
788 {
789 valueT fixup = value;
790 uint64_t insn;
791 char *buf;
792
793 /* Get the instruction or data to be fixed up. */
794 buf = fixP->fx_frag->fr_literal + fixP->fx_where;
795 insn = md_chars_to_number (buf, fixP->fx_size);
796
797 /* Check for overflow, emitting a diagnostic if necessary. */
798 if (pru_check_overflow (fixup, howto) != bfd_reloc_ok)
799 pru_diagnose_overflow (fixup, howto, fixP, insn);
800
801 /* Apply the right shift. */
4f7cc141 802 fixup = (offsetT) fixup >> howto->rightshift;
93f11b16
DD
803
804 /* Truncate the fixup to right size. */
4f7cc141
AM
805 if (howto->bitsize == 0)
806 fixup = 0;
807 else
808 fixup &= ((valueT) 2 << (howto->bitsize - 1)) - 1;
93f11b16
DD
809
810 /* Fix up the instruction. Non-contiguous bitfields need
811 special handling. */
ddb2c6fd 812 if (fixP->fx_r_type == BFD_RELOC_PRU_LDI32)
93f11b16
DD
813 {
814 /* As the only 64-bit "insn", LDI32 needs special handling. */
815 uint32_t insn1 = insn & 0xffffffff;
816 uint32_t insn2 = insn >> 32;
493ffac5
DD
817 SET_INSN_FIELD (IMM16, insn1, fixup >> 16);
818 SET_INSN_FIELD (IMM16, insn2, fixup & 0xffff);
819
820 SET_INSN_FIELD (RDSEL, insn1, RSEL_31_16);
821 SET_INSN_FIELD (RDSEL, insn2, RSEL_15_0);
ddb2c6fd
DD
822
823 md_number_to_chars (buf, insn1, 4);
824 md_number_to_chars (buf + 4, insn2, 4);
93f11b16
DD
825 }
826 else
ddb2c6fd
DD
827 {
828 if (fixP->fx_r_type == BFD_RELOC_PRU_S10_PCREL)
829 SET_BROFF_URAW (insn, fixup);
830 else
831 insn = (insn & ~howto->dst_mask) | (fixup << howto->bitpos);
832 md_number_to_chars (buf, insn, fixP->fx_size);
833 }
93f11b16
DD
834 }
835
836 fixP->fx_done = 1;
837 }
838
839 if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT)
840 {
841 fixP->fx_done = 0;
842 if (fixP->fx_addsy
843 && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
844 S_SET_WEAK (fixP->fx_addsy);
845 }
846 else if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
847 fixP->fx_done = 0;
848}
849
850
851\f
852/** Instruction parsing support. */
853
854/* Creates a new pru_insn_relocS and returns a pointer to it. */
855static pru_insn_relocS *
856pru_insn_reloc_new (bfd_reloc_code_real_type reloc_type, unsigned int pcrel)
857{
858 pru_insn_relocS *retval;
859 retval = XNEW (pru_insn_relocS);
860 if (retval == NULL)
861 {
862 as_bad (_("can't create relocation"));
863 abort ();
864 }
865
866 /* Fill out the fields with default values. */
867 retval->reloc_next = NULL;
868 retval->reloc_type = reloc_type;
869 retval->reloc_pcrel = pcrel;
870 return retval;
871}
872
873/* Frees up memory previously allocated by pru_insn_reloc_new (). */
874static void
875pru_insn_reloc_destroy (pru_insn_relocS *reloc)
876{
877 pru_insn_relocS *next;
878
879 while (reloc)
880 {
881 next = reloc->reloc_next;
882 free (reloc);
883 reloc = next;
884 }
885}
886
887/* The various pru_assemble_* functions call this
888 function to generate an expression from a string representing an expression.
889 It then tries to evaluate the expression, and if it can, returns its value.
890 If not, it creates a new pru_insn_relocS and stores the expression and
891 reloc_type for future use. */
892static unsigned long
893pru_assemble_expression (const char *exprstr,
894 pru_insn_infoS *insn,
895 pru_insn_relocS *prev_reloc,
896 bfd_reloc_code_real_type reloc_type,
897 unsigned int pcrel)
898{
899 expressionS *ep;
900 pru_insn_relocS *reloc;
901 char *saved_line_ptr;
902 unsigned short value;
903
904 gas_assert (exprstr != NULL);
905 gas_assert (insn != NULL);
906
907 /* We use this blank keyword to distinguish register from
908 label operands. */
909 if (strstr (exprstr, "%label") != NULL)
910 {
911 exprstr += strlen ("%label") + 1;
912 }
913
914 /* Check for pmem relocation operator.
915 Change the relocation type and advance the ptr to the start of
916 the expression proper. */
917 if (strstr (exprstr, "%pmem") != NULL)
918 {
919 reloc_type = BFD_RELOC_PRU_U16_PMEMIMM;
920 exprstr += strlen ("%pmem") + 1;
921 }
922
923 /* We potentially have a relocation. */
924 reloc = pru_insn_reloc_new (reloc_type, pcrel);
925 if (prev_reloc != NULL)
926 prev_reloc->reloc_next = reloc;
927 else
928 insn->insn_reloc = reloc;
929
930 /* Parse the expression string. */
931 ep = &reloc->reloc_expression;
932 saved_line_ptr = input_line_pointer;
933 input_line_pointer = (char *) exprstr;
934 SKIP_WHITESPACE ();
935 expression (ep);
936 SKIP_WHITESPACE ();
937 if (*input_line_pointer)
938 as_bad (_("trailing garbage after expression: %s"), input_line_pointer);
939 input_line_pointer = saved_line_ptr;
940
941
942 if (ep->X_op == O_illegal || ep->X_op == O_absent)
943 as_bad (_("expected expression, got %s"), exprstr);
944
945 /* This is redundant as the fixup will put this into
946 the instruction, but it is included here so that
947 self-test mode (-r) works. */
948 value = 0;
949 if (pru_mode == PRU_MODE_TEST && ep->X_op == O_constant)
950 value = ep->X_add_number;
951
952 return (unsigned long) value;
953}
954
955/* Try to parse a non-relocatable expression. */
956static unsigned long
957pru_assemble_noreloc_expression (const char *exprstr)
958{
959 expressionS exp;
960 char *saved_line_ptr;
961 unsigned long val;
962
963 gas_assert (exprstr != NULL);
964
965 saved_line_ptr = input_line_pointer;
966 input_line_pointer = (char *) exprstr;
967 SKIP_WHITESPACE ();
968 expression (&exp);
969 SKIP_WHITESPACE ();
970 if (*input_line_pointer)
971 as_bad (_("trailing garbage after expression: %s"), input_line_pointer);
972 input_line_pointer = saved_line_ptr;
973
974 val = 0;
975 if (exp.X_op != O_constant)
976 as_bad (_("expected constant expression, got %s"), exprstr);
977 else
978 val = exp.X_add_number;
979
980 return val;
981}
982
983/* Argument assemble functions.
984 All take an instruction argument string, and a pointer
985 to an instruction opcode. Upon return the insn_opcode
986 has the relevant fields filled in to represent the arg
987 string. The return value is NULL if successful, or
988 an error message if an error was detected. */
989
990static void
991pru_assemble_arg_d (pru_insn_infoS *insn_info, const char *argstr)
992{
993 struct pru_reg *dst = pru_reg_lookup (argstr);
994
995 if (dst == NULL)
996 as_bad (_("unknown register %s"), argstr);
997 else
998 {
999 SET_INSN_FIELD (RD, insn_info->insn_code, dst->index);
1000 SET_INSN_FIELD (RDSEL, insn_info->insn_code, dst->regsel);
1001 }
1002}
1003
1004static void
1005pru_assemble_arg_D (pru_insn_infoS *insn_info, const char *argstr)
1006{
1007 struct pru_reg *dst;
1008
1009 /* The leading & before an address register is optional. */
1010 if (*argstr == '&')
1011 argstr++;
1012
1013 dst = pru_reg_lookup (argstr);
1014
1015 if (dst == NULL)
1016 as_bad (_("unknown register %s"), argstr);
1017 else
1018 {
1019 unsigned long rxb = 0;
1020
1021 switch (dst->regsel)
1022 {
1023 case RSEL_31_0: rxb = 0; break; /* whole register defaults to .b0 */
1024 case RSEL_7_0: rxb = 0; break;
1025 case RSEL_15_8: rxb = 1; break;
1026 case RSEL_23_16: rxb = 2; break;
1027 case RSEL_31_24: rxb = 3; break;
1028 default:
1029 as_bad (_("data transfer register cannot be halfword"));
1030 }
1031
1032 SET_INSN_FIELD (RD, insn_info->insn_code, dst->index);
1033 SET_INSN_FIELD (RDB, insn_info->insn_code, rxb);
1034 }
1035}
1036
1037static void
1038pru_assemble_arg_R (pru_insn_infoS *insn_info, const char *argstr)
1039{
1040 struct pru_reg *dst = pru_reg_lookup (argstr);
1041
1042 if (dst == NULL)
1043 as_bad (_("unknown register %s"), argstr);
1044 else
1045 {
1046 if (dst->regsel != RSEL_31_0)
1047 {
1048 as_bad (_("destination register must be full-word"));
1049 }
1050
1051 SET_INSN_FIELD (RD, insn_info->insn_code, dst->index);
1052 SET_INSN_FIELD (RDSEL, insn_info->insn_code, dst->regsel);
1053 }
1054}
1055
1056static void
1057pru_assemble_arg_s (pru_insn_infoS *insn_info, const char *argstr)
1058{
1059 struct pru_reg *src1 = pru_reg_lookup (argstr);
1060
1061 if (src1 == NULL)
1062 as_bad (_("unknown register %s"), argstr);
1063 else
1064 {
1065 SET_INSN_FIELD (RS1, insn_info->insn_code, src1->index);
1066 SET_INSN_FIELD (RS1SEL, insn_info->insn_code, src1->regsel);
1067 }
1068}
1069
1070static void
1071pru_assemble_arg_S (pru_insn_infoS *insn_info, const char *argstr)
1072{
1073 struct pru_reg *src1 = pru_reg_lookup (argstr);
1074
1075 if (src1 == NULL)
1076 as_bad (_("unknown register %s"), argstr);
1077 else
1078 {
1079 if (src1->regsel != RSEL_31_0)
1080 as_bad (_("cannot use partial register %s for addressing"), argstr);
1081 SET_INSN_FIELD (RS1, insn_info->insn_code, src1->index);
1082 }
1083}
1084
1085static void
1086pru_assemble_arg_b (pru_insn_infoS *insn_info, const char *argstr)
1087{
1088 struct pru_reg *src2 = pru_reg_lookup (argstr);
1089 if (src2 == NULL)
1090 {
1091 unsigned long imm8 = pru_assemble_noreloc_expression (argstr);
493ffac5
DD
1092 if (imm8 >= 0x100)
1093 as_bad (_("value %lu is too large for a byte operand"), imm8);
93f11b16
DD
1094 SET_INSN_FIELD (IMM8, insn_info->insn_code, imm8);
1095 SET_INSN_FIELD (IO, insn_info->insn_code, 1);
1096 }
1097 else
1098 {
1099 SET_INSN_FIELD (IO, insn_info->insn_code, 0);
1100 SET_INSN_FIELD (RS2, insn_info->insn_code, src2->index);
1101 SET_INSN_FIELD (RS2SEL, insn_info->insn_code, src2->regsel);
1102 }
1103
1104}
1105
1106static void
1107pru_assemble_arg_B (pru_insn_infoS *insn_info, const char *argstr)
1108{
1109 struct pru_reg *src2 = pru_reg_lookup (argstr);
1110 if (src2 == NULL)
1111 {
1112 unsigned long imm8;
1113 imm8 = pru_assemble_noreloc_expression (argstr);
1114 if (!imm8 || imm8 > 0xff)
1115 as_bad (_("loop count constant %ld is out of range [1..%d]"),
1116 imm8, 0xff);
1117 /* Note: HW expects the immediate loop count field
1118 to be one less than the actual loop count. */
1119 SET_INSN_FIELD (IMM8, insn_info->insn_code, imm8 - 1);
1120 SET_INSN_FIELD (IO, insn_info->insn_code, 1);
1121 }
1122 else
1123 {
1124 SET_INSN_FIELD (IO, insn_info->insn_code, 0);
1125 SET_INSN_FIELD (RS2, insn_info->insn_code, src2->index);
1126 SET_INSN_FIELD (RS2SEL, insn_info->insn_code, src2->regsel);
1127 }
1128}
1129
1130static void
1131pru_assemble_arg_i (pru_insn_infoS *insn_info, const char *argstr)
1132{
1133 unsigned long imm32;
1134
1135 /* We must not generate PRU_LDI32 relocation if relaxation is disabled in
1136 GAS. Consider the following scenario: GAS relaxation is disabled, so
1137 DIFF* expressions are fixed and not emitted as relocations. Then if LD
1138 has relaxation enabled, it may shorten LDI32 but will not update
1139 accordingly the DIFF expressions. */
1140 if (pru_opt.link_relax)
1141 imm32 = pru_assemble_expression (argstr, insn_info,
1142 insn_info->insn_reloc,
1143 BFD_RELOC_PRU_LDI32, 0);
1144 else
1145 imm32 = pru_assemble_noreloc_expression (argstr);
1146
1147 /* QUIRK: LDI must clear IO bit high, even though it has immediate arg. */
1148 SET_INSN_FIELD (IO, insn_info->insn_code, 0);
493ffac5
DD
1149 SET_INSN_FIELD (RDSEL, insn_info->insn_code, RSEL_31_16);
1150 SET_INSN_FIELD (IMM16, insn_info->insn_code, imm32 >> 16);
93f11b16
DD
1151 insn_info->ldi32_imm32 = imm32;
1152}
1153
1154static void
1155pru_assemble_arg_j (pru_insn_infoS *insn_info, const char *argstr)
1156{
1157 struct pru_reg *src2 = pru_reg_lookup (argstr);
1158
1159 if (src2 == NULL)
1160 {
1161 unsigned long imm16 = pru_assemble_expression (argstr, insn_info,
1162 insn_info->insn_reloc,
1163 BFD_RELOC_PRU_U16_PMEMIMM,
1164 0);
1165 SET_INSN_FIELD (IMM16, insn_info->insn_code, imm16);
1166 SET_INSN_FIELD (IO, insn_info->insn_code, 1);
1167 }
1168 else
1169 {
1170 SET_INSN_FIELD (IO, insn_info->insn_code, 0);
1171 SET_INSN_FIELD (RS2, insn_info->insn_code, src2->index);
1172 SET_INSN_FIELD (RS2SEL, insn_info->insn_code, src2->regsel);
1173 }
1174}
1175
1176static void
1177pru_assemble_arg_W (pru_insn_infoS *insn_info, const char *argstr)
1178{
1179 unsigned long imm16 = pru_assemble_expression (argstr, insn_info,
1180 insn_info->insn_reloc,
1181 BFD_RELOC_PRU_U16, 0);
1182 /* QUIRK: LDI must clear IO bit high, even though it has immediate arg. */
1183 SET_INSN_FIELD (IO, insn_info->insn_code, 0);
1184 SET_INSN_FIELD (IMM16, insn_info->insn_code, imm16);
1185}
1186
1187static void
1188pru_assemble_arg_o (pru_insn_infoS *insn_info, const char *argstr)
1189{
1190 unsigned long imm10 = pru_assemble_expression (argstr, insn_info,
1191 insn_info->insn_reloc,
1192 BFD_RELOC_PRU_S10_PCREL, 1);
1193 SET_BROFF_URAW (insn_info->insn_code, imm10);
1194}
1195
1196static void
1197pru_assemble_arg_O (pru_insn_infoS *insn_info, const char *argstr)
1198{
1199 unsigned long imm8 = pru_assemble_expression (argstr, insn_info,
1200 insn_info->insn_reloc,
1201 BFD_RELOC_PRU_U8_PCREL, 1);
1202 SET_INSN_FIELD (LOOP_JMPOFFS, insn_info->insn_code, imm8);
1203}
1204
1205static void
1206pru_assemble_arg_l (pru_insn_infoS *insn_info, const char *argstr)
1207{
1208 unsigned long burstlen = 0;
1209 struct pru_reg *blreg = pru_reg_lookup (argstr);
1210
1211 if (blreg == NULL)
1212 {
1213 burstlen = pru_assemble_noreloc_expression (argstr);
1214 if (!burstlen || burstlen > LSSBBO_BYTECOUNT_R0_BITS7_0)
1215 as_bad (_("byte count constant %ld is out of range [1..%d]"),
1216 burstlen, LSSBBO_BYTECOUNT_R0_BITS7_0);
1217 burstlen--;
1218 }
1219 else
1220 {
1221 if (blreg->index != 0)
1222 as_bad (_("only r0 can be used as byte count register"));
1223 else if (blreg->regsel > RSEL_31_24)
1224 as_bad (_("only r0.bX byte fields of r0 can be used as byte count"));
1225 else
1226 burstlen = LSSBBO_BYTECOUNT_R0_BITS7_0 + blreg->regsel;
1227 }
1228 SET_BURSTLEN (insn_info->insn_code, burstlen);
1229}
1230
1231static void
1232pru_assemble_arg_n (pru_insn_infoS *insn_info, const char *argstr)
1233{
1234 unsigned long burstlen = 0;
1235 struct pru_reg *blreg = pru_reg_lookup (argstr);
1236
1237 if (blreg == NULL)
1238 {
1239 burstlen = pru_assemble_noreloc_expression (argstr);
1240 if (!burstlen || burstlen > LSSBBO_BYTECOUNT_R0_BITS7_0)
1241 as_bad (_("byte count constant %ld is out of range [1..%d]"),
1242 burstlen, LSSBBO_BYTECOUNT_R0_BITS7_0);
1243 burstlen--;
1244 }
1245 else
1246 {
1247 if (blreg->index != 0)
1248 as_bad (_("only r0 can be used as byte count register"));
1249 else if (blreg->regsel > RSEL_31_24)
1250 as_bad (_("only r0.bX byte fields of r0 can be used as byte count"));
1251 else
1252 burstlen = LSSBBO_BYTECOUNT_R0_BITS7_0 + blreg->regsel;
1253 }
1254 SET_INSN_FIELD (XFR_LENGTH, insn_info->insn_code, burstlen);
1255}
1256
1257static void
1258pru_assemble_arg_c (pru_insn_infoS *insn_info, const char *argstr)
1259{
1260 unsigned long cb = pru_assemble_noreloc_expression (argstr);
1261
1262 if (cb > 31)
1263 as_bad (_("invalid constant table offset %ld"), cb);
1264 else
1265 SET_INSN_FIELD (CB, insn_info->insn_code, cb);
1266}
1267
1268static void
1269pru_assemble_arg_w (pru_insn_infoS *insn_info, const char *argstr)
1270{
1271 unsigned long wk = pru_assemble_noreloc_expression (argstr);
1272
1273 if (wk != 0 && wk != 1)
1274 as_bad (_("invalid WakeOnStatus %ld"), wk);
1275 else
1276 SET_INSN_FIELD (WAKEONSTATUS, insn_info->insn_code, wk);
1277}
1278
1279static void
1280pru_assemble_arg_x (pru_insn_infoS *insn_info, const char *argstr)
1281{
1282 unsigned long wba = pru_assemble_noreloc_expression (argstr);
1283
1284 if (wba > 255)
1285 as_bad (_("invalid XFR WideBus Address %ld"), wba);
1286 else
1287 SET_INSN_FIELD (XFR_WBA, insn_info->insn_code, wba);
1288}
1289
1290/* The function consume_arg takes a pointer into a string
1291 of instruction tokens (args) and a pointer into a string
1292 representing the expected sequence of tokens and separators.
1293 It checks whether the first argument in argstr is of the
1294 expected type, throwing an error if it is not, and returns
1295 the pointer argstr. */
1296static char *
1297pru_consume_arg (char *argstr, const char *parsestr)
1298{
1299 char *temp;
1300
1301 switch (*parsestr)
1302 {
1303 case 'W':
1304 if (*argstr == '%')
1305 {
1306 if (strprefix (argstr, "%pmem") || strprefix (argstr, "%label"))
1307 {
1308 /* We zap the parentheses because we don't want them confused
1309 with separators. */
1310 temp = strchr (argstr, '(');
1311 if (temp != NULL)
1312 *temp = ' ';
1313 temp = strchr (argstr, ')');
1314 if (temp != NULL)
1315 *temp = ' ';
1316 }
1317 else
1318 as_bad (_("badly formed expression near %s"), argstr);
1319 }
1320 break;
1321
1322 case 'j':
1323 case 'o':
1324 case 'O':
1325 if (*argstr == '%')
1326 {
1327 /* Only 'j' really requires %label for distinguishing registers
1328 from labels, but we include 'o' and 'O' here to avoid
1329 confusing assembler programmers. Thus for completeness all
1330 jump operands can be prefixed with %label. */
1331 if (strprefix (argstr, "%label"))
1332 {
1333 /* We zap the parentheses because we don't want them confused
1334 with separators. */
1335 temp = strchr (argstr, '(');
1336 if (temp != NULL)
1337 *temp = ' ';
1338 temp = strchr (argstr, ')');
1339 if (temp != NULL)
1340 *temp = ' ';
1341 }
1342 else
1343 as_bad (_("badly formed expression near %s"), argstr);
1344 }
1345 break;
1346
1347 case 'b':
1348 case 'B':
1349 case 'c':
1350 case 'd':
1351 case 'D':
1352 case 'E':
1353 case 'i':
1354 case 's':
1355 case 'S':
1356 case 'l':
1357 case 'n':
1358 case 'R':
1359 case 'w':
1360 case 'x':
1361 /* We can't have %pmem here. */
1362 if (*argstr == '%')
1363 as_bad (_("badly formed expression near %s"), argstr);
1364 break;
1365 default:
1366 BAD_CASE (*parsestr);
1367 break;
1368 }
1369
1370 return argstr;
1371}
1372
1373/* The function consume_separator takes a pointer into a string
1374 of instruction tokens (args) and a pointer into a string representing
1375 the expected sequence of tokens and separators. It finds the first
1376 instance of the character pointed to by separator in argstr, and
1377 returns a pointer to the next element of argstr, which is the
1378 following token in the sequence. */
1379static char *
1380pru_consume_separator (char *argstr, const char *separator)
1381{
1382 char *p;
1383
1384 p = strchr (argstr, *separator);
1385
1386 if (p != NULL)
1387 *p++ = 0;
1388 else
1389 as_bad (_("expecting %c near %s"), *separator, argstr);
1390 return p;
1391}
1392
1393
1394/* The principal argument parsing function which takes a string argstr
1395 representing the instruction arguments for insn, and extracts the argument
1396 tokens matching parsestr into parsed_args. */
1397static void
1398pru_parse_args (pru_insn_infoS *insn ATTRIBUTE_UNUSED, char *argstr,
1399 const char *parsestr, char **parsed_args)
1400{
1401 char *p;
1402 char *end = NULL;
1403 int i;
1404 p = argstr;
1405 i = 0;
5b7c81bd 1406 bool terminate = false;
93f11b16
DD
1407
1408 /* This rest of this function is it too fragile and it mostly works,
1409 therefore special case this one. */
1410 if (*parsestr == 0 && argstr != 0)
1411 {
1412 as_bad (_("too many arguments"));
1413 parsed_args[0] = NULL;
1414 return;
1415 }
1416
1417 while (p != NULL && !terminate && i < PRU_MAX_INSN_TOKENS)
1418 {
1419 parsed_args[i] = pru_consume_arg (p, parsestr);
1420 ++parsestr;
1421 if (*parsestr != '\0')
1422 {
1423 p = pru_consume_separator (p, parsestr);
1424 ++parsestr;
1425 }
1426 else
1427 {
1428 /* Check that the argument string has no trailing arguments. */
1429 /* If we've got a %pmem relocation, we've zapped the parens with
1430 spaces. */
1431 if (strprefix (p, "%pmem") || strprefix (p, "%label"))
1432 end = strpbrk (p, ",");
1433 else
1434 end = strpbrk (p, " ,");
1435
1436 if (end != NULL)
1437 as_bad (_("too many arguments"));
1438 }
1439
1440 if (*parsestr == '\0' || (p != NULL && *p == '\0'))
5b7c81bd 1441 terminate = true;
93f11b16
DD
1442 ++i;
1443 }
1444
1445 parsed_args[i] = NULL;
1446
1447 /* There are no instructions with optional arguments; complain. */
1448 if (*parsestr != '\0')
1449 as_bad (_("missing argument"));
1450}
1451
1452\f
1453/** Assembler output support. */
1454
1455/* Output a normal instruction. */
1456static void
1457output_insn (pru_insn_infoS *insn)
1458{
1459 char *f;
1460 pru_insn_relocS *reloc;
1461
1462 f = frag_more (4);
1463 /* This allocates enough space for the instruction
1464 and puts it in the current frag. */
1465 md_number_to_chars (f, insn->insn_code, 4);
1466 /* Emit debug info. */
1467 dwarf2_emit_insn (4);
1468 /* Create any fixups to be acted on later. */
1469 for (reloc = insn->insn_reloc; reloc != NULL; reloc = reloc->reloc_next)
1470 fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
1471 &reloc->reloc_expression, reloc->reloc_pcrel,
1472 reloc->reloc_type);
1473}
1474
1475/* Output two LDI instructions from LDI32 macro */
1476static void
1477output_insn_ldi32 (pru_insn_infoS *insn)
1478{
1479 char *f;
1480 pru_insn_relocS *reloc;
1481 unsigned long insn2;
1482
1483 f = frag_more (8);
493ffac5
DD
1484 SET_INSN_FIELD (IMM16, insn->insn_code, insn->ldi32_imm32 >> 16);
1485 SET_INSN_FIELD (RDSEL, insn->insn_code, RSEL_31_16);
93f11b16
DD
1486 md_number_to_chars (f, insn->insn_code, 4);
1487
1488 insn2 = insn->insn_code;
493ffac5
DD
1489 SET_INSN_FIELD (IMM16, insn2, insn->ldi32_imm32 & 0xffff);
1490 SET_INSN_FIELD (RDSEL, insn2, RSEL_15_0);
93f11b16
DD
1491 md_number_to_chars (f + 4, insn2, 4);
1492
1493 /* Emit debug info. */
1494 dwarf2_emit_insn (8);
1495
1496 /* Create any fixups to be acted on later. */
1497 for (reloc = insn->insn_reloc; reloc != NULL; reloc = reloc->reloc_next)
1498 fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
1499 &reloc->reloc_expression, reloc->reloc_pcrel,
1500 reloc->reloc_type);
1501}
1502
1503\f
1504/** External interfaces. */
1505
1506/* The following functions are called by machine-independent parts of
1507 the assembler. */
1508int
1509md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
1510{
1511 switch (c)
1512 {
1513 case 'r':
1514 /* Hidden option for self-test mode. */
1515 pru_mode = PRU_MODE_TEST;
1516 break;
1517 case OPTION_LINK_RELAX:
5b7c81bd 1518 pru_opt.link_relax = true;
93f11b16
DD
1519 break;
1520 case OPTION_NO_LINK_RELAX:
5b7c81bd 1521 pru_opt.link_relax = false;
93f11b16
DD
1522 break;
1523 case OPTION_NO_WARN_REGNAME_LABEL:
5b7c81bd 1524 pru_opt.warn_regname_label = false;
93f11b16
DD
1525 break;
1526 default:
1527 return 0;
1528 break;
1529 }
1530
1531 return 1;
1532}
1533
1534const char *
1535pru_target_format (void)
1536{
1537 return "elf32-pru";
1538}
1539
1540/* Machine-dependent usage message. */
1541void
1542md_show_usage (FILE *stream)
1543{
1544 fprintf (stream,
1545 _("PRU options:\n"
1546 " -mlink-relax generate relocations for linker relaxation (default).\n"
1547 " -mno-link-relax don't generate relocations for linker relaxation.\n"
1548 ));
1549
1550}
1551
1552/* This function is called once, at assembler startup time.
1553 It should set up all the tables, etc. that the MD part of the
1554 assembler will need. */
1555void
1556md_begin (void)
1557{
1558 int i;
93f11b16
DD
1559
1560 /* Create and fill a hashtable for the PRU opcodes, registers and
1561 arguments. */
629310ab
ML
1562 pru_opcode_hash = str_htab_create ();
1563 pru_reg_hash = str_htab_create ();
93f11b16
DD
1564
1565 for (i = 0; i < NUMOPCODES; ++i)
fe0e921f
AM
1566 if (str_hash_insert (pru_opcode_hash, pru_opcodes[i].name,
1567 &pru_opcodes[i], 0) != NULL)
1568 as_fatal (_("duplicate %s"), pru_opcodes[i].name);
93f11b16
DD
1569
1570 for (i = 0; i < pru_num_regs; ++i)
fe0e921f
AM
1571 if (str_hash_insert (pru_reg_hash, pru_regs[i].name, &pru_regs[i], 0))
1572 as_fatal (_("duplicate %s"), pru_regs[i].name);
93f11b16
DD
1573
1574 linkrelax = pru_opt.link_relax;
1575 /* Initialize the alignment data. */
1576 pru_current_align_seg = now_seg;
1577 pru_last_label = NULL;
1578 pru_current_align = 0;
1579}
1580
1581
1582/* Assembles a single line of PRU assembly language. */
1583void
1584md_assemble (char *op_str)
1585{
1586 char *argstr;
1587 char *op_strdup = NULL;
1588 pru_insn_infoS thisinsn;
1589 pru_insn_infoS *insn = &thisinsn;
1590
1591 /* Make sure we are aligned on a 4-byte boundary. */
1592 if (pru_current_align < 2)
1593 pru_align (2, NULL, pru_last_label);
1594 else if (pru_current_align > 2)
1595 pru_current_align = 2;
1596 pru_last_label = NULL;
1597
1598 /* We don't want to clobber to op_str
1599 because we want to be able to use it in messages. */
1600 op_strdup = strdup (op_str);
1601 insn->insn_tokens[0] = strtok (op_strdup, " ");
1602 argstr = strtok (NULL, "");
1603
1604 /* Assemble the opcode. */
1605 insn->insn_pru_opcode = pru_opcode_lookup (insn->insn_tokens[0]);
1606 insn->insn_reloc = NULL;
1607
1608 if (insn->insn_pru_opcode != NULL)
1609 {
1610 const char *argsfmt = insn->insn_pru_opcode->args;
1611 const char **argtk = &insn->insn_tokens[1];
1612 const char *argp;
1613
1614 /* Set the opcode for the instruction. */
1615 insn->insn_code = insn->insn_pru_opcode->match;
1616
1617 if (pru_mode == PRU_MODE_TEST)
1618 {
1619 /* Add the "expected" instruction parameter used for validation. */
1620 argsfmt = malloc (strlen (argsfmt) + 3);
1621 sprintf ((char *)argsfmt, "%s,E", insn->insn_pru_opcode->args);
1622 }
1623 pru_parse_args (insn, argstr, argsfmt,
1624 (char **) &insn->insn_tokens[1]);
1625
1626 for (argp = argsfmt; !had_errors () && *argp && *argtk; ++argp)
1627 {
1628 gas_assert (argtk <= &insn->insn_tokens[PRU_MAX_INSN_TOKENS]);
1629
1630 switch (*argp)
1631 {
1632 case ',':
1633 continue;
1634
1635 case 'd':
1636 pru_assemble_arg_d (insn, *argtk++);
1637 continue;
1638 case 'D':
1639 pru_assemble_arg_D (insn, *argtk++);
1640 continue;
1641 case 'R':
1642 pru_assemble_arg_R (insn, *argtk++);
1643 continue;
1644 case 's':
1645 pru_assemble_arg_s (insn, *argtk++);
1646 continue;
1647 case 'S':
1648 pru_assemble_arg_S (insn, *argtk++);
1649 continue;
1650 case 'b':
1651 pru_assemble_arg_b (insn, *argtk++);
1652 continue;
1653 case 'B':
1654 pru_assemble_arg_B (insn, *argtk++);
1655 continue;
1656 case 'i':
1657 pru_assemble_arg_i (insn, *argtk++);
1658 continue;
1659 case 'j':
1660 pru_assemble_arg_j (insn, *argtk++);
1661 continue;
1662 case 'W':
1663 pru_assemble_arg_W (insn, *argtk++);
1664 continue;
1665 case 'o':
1666 pru_assemble_arg_o (insn, *argtk++);
1667 continue;
1668 case 'O':
1669 pru_assemble_arg_O (insn, *argtk++);
1670 continue;
1671 case 'l':
1672 pru_assemble_arg_l (insn, *argtk++);
1673 continue;
1674 case 'n':
1675 pru_assemble_arg_n (insn, *argtk++);
1676 continue;
1677 case 'c':
1678 pru_assemble_arg_c (insn, *argtk++);
1679 continue;
1680 case 'w':
1681 pru_assemble_arg_w (insn, *argtk++);
1682 continue;
1683 case 'x':
1684 pru_assemble_arg_x (insn, *argtk++);
1685 continue;
1686
1687 case 'E':
1688 pru_check_assembly (insn->insn_code, *argtk++);
0bae9e9e
NC
1689 continue;
1690
93f11b16
DD
1691 default:
1692 BAD_CASE (*argp);
1693 }
1694 }
1695
1696 if (*argp && !had_errors ())
1697 as_bad (_("missing argument"));
1698
1699 if (!had_errors ())
1700 {
1701 if (insn->insn_pru_opcode->pinfo & PRU_INSN_LDI32)
1702 {
1703 output_insn_ldi32 (insn);
1704 }
1705 else
1706 {
1707 output_insn (insn);
1708 }
1709 }
1710
1711 if (pru_mode == PRU_MODE_TEST)
1712 free ((char *)argsfmt);
1713 }
1714 else
1715 /* Unrecognised instruction - error. */
1716 as_bad (_("unrecognised instruction %s"), insn->insn_tokens[0]);
1717
1718 /* Don't leak memory. */
1719 pru_insn_reloc_destroy (insn->insn_reloc);
1720 free (op_strdup);
1721}
1722
1723/* Round up section size. */
1724valueT
1725md_section_align (asection *seg, valueT addr)
1726{
fd361982 1727 int align = bfd_section_alignment (seg);
93f11b16
DD
1728 return ((addr + (1 << align) - 1) & (-((valueT) 1 << align)));
1729}
1730
1731/* Implement tc_fix_adjustable. */
1732int
1733pru_fix_adjustable (fixS *fixp)
1734{
1735 if (fixp->fx_addsy == NULL)
1736 return 1;
1737
1738 /* Prevent all adjustments to global symbols. */
1739 if (OUTPUT_FLAVOR == bfd_target_elf_flavour
1740 && (S_IS_EXTERNAL (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy)))
1741 return 0;
1742
1743 if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
1744 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1745 return 0;
1746
1747 /* Preserve relocations against symbols with function type. */
1748 if (symbol_get_bfdsym (fixp->fx_addsy)->flags & BSF_FUNCTION)
1749 return 0;
1750
1751 return 1;
1752}
1753
1754/* The function tc_gen_reloc creates a relocation structure for the
1755 fixup fixp, and returns a pointer to it. This structure is passed
1756 to bfd_install_relocation so that it can be written to the object
1757 file for linking. */
1758arelent *
1759tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
1760{
1761 arelent *reloc = XNEW (arelent);
1762 reloc->sym_ptr_ptr = XNEW (asymbol *);
1763 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
1764
1765 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
1766 reloc->addend = fixp->fx_offset; /* fixp->fx_addnumber; */
1767
1768 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
1769 if (reloc->howto == NULL)
1770 {
1771 as_bad_where (fixp->fx_file, fixp->fx_line,
1772 _("can't represent relocation type %s"),
1773 bfd_get_reloc_code_name (fixp->fx_r_type));
1774
1775 /* Set howto to a garbage value so that we can keep going. */
1776 reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
1777 gas_assert (reloc->howto != NULL);
1778 }
1779 return reloc;
1780}
1781
1782long
1783md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
1784{
1785 return fixP->fx_where + fixP->fx_frag->fr_address;
1786}
1787
1788/* Called just before the assembler exits. */
1789void
ed2917de 1790pru_md_end (void)
93f11b16 1791{
629310ab
ML
1792 htab_delete (pru_opcode_hash);
1793 htab_delete (pru_reg_hash);
93f11b16
DD
1794}
1795
1796symbolS *
1797md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1798{
1799 return NULL;
1800}
1801
1802/* Implement tc_frob_label. */
1803void
1804pru_frob_label (symbolS *lab)
1805{
1806 /* Emit dwarf information. */
1807 dwarf2_emit_label (lab);
1808
1809 /* Update the label's address with the current output pointer. */
1810 symbol_set_frag (lab, frag_now);
1811 S_SET_VALUE (lab, (valueT) frag_now_fix ());
1812
1813 /* Record this label for future adjustment after we find out what
1814 kind of data it references, and the required alignment therewith. */
1815 pru_last_label = lab;
1816
1817 if (pru_opt.warn_regname_label && pru_reg_lookup (S_GET_NAME (lab)))
1818 as_warn (_("Label \"%s\" matches a CPU register name"), S_GET_NAME (lab));
1819}
1820
1821static inline char *
1822skip_space (char *s)
1823{
1824 while (*s == ' ' || *s == '\t')
1825 ++s;
1826 return s;
1827}
1828
1829/* Parse special CONS expression: pmem (expression). Idea from AVR.
1830
1831 Used to catch and mark code (program memory) in constant expression
1832 relocations. Return non-zero for program memory. */
1833
1834int
1835pru_parse_cons_expression (expressionS *exp, int nbytes)
1836{
5b7c81bd 1837 int is_pmem = false;
93f11b16
DD
1838 char *tmp;
1839
1840 tmp = input_line_pointer = skip_space (input_line_pointer);
1841
1842 if (nbytes == 4 || nbytes == 2)
1843 {
1844 const char *pmem_str = "%pmem";
1845 int len = strlen (pmem_str);
1846
1847 if (strncasecmp (input_line_pointer, pmem_str, len) == 0)
1848 {
1849 input_line_pointer = skip_space (input_line_pointer + len);
1850
1851 if (*input_line_pointer == '(')
1852 {
1853 input_line_pointer = skip_space (input_line_pointer + 1);
5b7c81bd 1854 is_pmem = true;
93f11b16
DD
1855 expression (exp);
1856
1857 if (*input_line_pointer == ')')
1858 ++input_line_pointer;
1859 else
1860 {
1861 as_bad (_("`)' required"));
5b7c81bd 1862 is_pmem = false;
93f11b16
DD
1863 }
1864
1865 return is_pmem;
1866 }
1867
1868 input_line_pointer = tmp;
1869 }
1870 }
1871
1872 expression (exp);
1873
1874 return is_pmem;
1875}
1876
1877/* Implement TC_CONS_FIX_NEW. */
1878void
1879pru_cons_fix_new (fragS *frag, int where, unsigned int nbytes,
1880 expressionS *exp, const int is_pmem)
1881{
1882 bfd_reloc_code_real_type r;
1883
1884 switch (nbytes | (!!is_pmem << 8))
1885 {
1886 case 1 | (0 << 8): r = BFD_RELOC_8; break;
1887 case 2 | (0 << 8): r = BFD_RELOC_16; break;
1888 case 4 | (0 << 8): r = BFD_RELOC_32; break;
1889 case 8 | (0 << 8): r = BFD_RELOC_64; break;
1890 case 2 | (1 << 8): r = BFD_RELOC_PRU_16_PMEM; break;
1891 case 4 | (1 << 8): r = BFD_RELOC_PRU_32_PMEM; break;
1892 default:
1893 as_bad (_("illegal %s relocation size: %d"),
1894 is_pmem ? "text" : "data", nbytes);
1895 return;
1896 }
1897
1898 fix_new_exp (frag, where, (int) nbytes, exp, 0, r);
1899}
1900
1901/* Implement tc_regname_to_dw2regnum, to convert REGNAME to a DWARF-2
2688aab2
DD
1902 register number. Return the starting HW byte-register number. */
1903
93f11b16
DD
1904int
1905pru_regname_to_dw2regnum (char *regname)
1906{
2688aab2
DD
1907 static const unsigned int regstart[RSEL_NUM_ITEMS] =
1908 {
1909 [RSEL_7_0] = 0,
1910 [RSEL_15_8] = 1,
1911 [RSEL_23_16] = 2,
1912 [RSEL_31_24] = 3,
1913 [RSEL_15_0] = 0,
1914 [RSEL_23_8] = 1,
1915 [RSEL_31_16] = 2,
1916 [RSEL_31_0] = 0,
1917 };
1918
93f11b16 1919 struct pru_reg *r = pru_reg_lookup (regname);
2688aab2
DD
1920
1921 if (r == NULL || r->regsel >= RSEL_NUM_ITEMS)
93f11b16 1922 return -1;
2688aab2 1923 return r->index * 4 + regstart[r->regsel];
93f11b16
DD
1924}
1925
1926/* Implement tc_cfi_frame_initial_instructions, to initialize the DWARF-2
1927 unwind information for this procedure. */
1928void
1929pru_frame_initial_instructions (void)
1930{
2688aab2 1931 const unsigned fp_regno = 4 * 4;
93f11b16
DD
1932 cfi_add_CFA_def_cfa (fp_regno, 0);
1933}
1934
5b7c81bd 1935bool
93f11b16
DD
1936pru_allow_local_subtract (expressionS * left,
1937 expressionS * right,
1938 segT section)
1939{
1940 /* If we are not in relaxation mode, subtraction is OK. */
1941 if (!linkrelax)
5b7c81bd 1942 return true;
93f11b16
DD
1943
1944 /* If the symbols are not in a code section then they are OK. */
1945 if ((section->flags & SEC_CODE) == 0)
5b7c81bd 1946 return true;
93f11b16
DD
1947
1948 if (left->X_add_symbol == right->X_add_symbol)
5b7c81bd 1949 return true;
93f11b16
DD
1950
1951 /* We have to assume that there may be instructions between the
1952 two symbols and that relaxation may increase the distance between
1953 them. */
5b7c81bd 1954 return false;
93f11b16 1955}