xref: /netbsd-src/external/gpl3/binutils/dist/gas/config/tc-pru.c (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
1 /* TI PRU assembler.
2    Copyright (C) 2014-2024 Free Software Foundation, Inc.
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"
24 #include <stdint.h>
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.  */
41 const 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.  */
50 const char line_comment_chars[] = "#;*";
51 
52 /* This array holds machine specific line separator characters.  */
53 const char line_separator_chars[] = "";
54 
55 /* Chars that can be used to separate mant from exp in floating point nums.  */
56 const 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  */
61 const char FLT_CHARS[] = "rRsSfFdDxXpP";
62 
63 /* Machine-dependent command-line options.  */
64 
65 struct pru_opt_s
66 {
67   /* -mno-link-relax / -mlink-relax: generate (or not)
68      relocations for linker relaxation.  */
69   bool link_relax;
70 
71   /* -mno-warn-regname-label: do not output a warning that a label name
72      matches a register name.  */
73   bool warn_regname_label;
74 };
75 
76 static struct pru_opt_s pru_opt = { true, true };
77 
78 const char *md_shortopts = "r";
79 
80 enum options
81 {
82   OPTION_LINK_RELAX = OPTION_MD_BASE + 1,
83   OPTION_NO_LINK_RELAX,
84   OPTION_NO_WARN_REGNAME_LABEL,
85 };
86 
87 struct 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 
95 size_t md_longopts_size = sizeof (md_longopts);
96 
97 typedef 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.  */
114 typedef 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.  */
135 static htab_t pru_opcode_hash = NULL;
136 #define pru_opcode_lookup(NAME) \
137   ((struct pru_opcode *) str_hash_find (pru_opcode_hash, (NAME)))
138 
139 /* Register hash table.  */
140 static htab_t pru_reg_hash = NULL;
141 #define pru_reg_lookup(NAME) \
142   ((struct pru_reg *) str_hash_find (pru_reg_hash, (NAME)))
143 
144 /* The known current alignment of the current section.  */
145 static int pru_current_align;
146 static segT pru_current_align_seg;
147 
148 static int pru_auto_align_on = 1;
149 
150 /* The last seen label in the current section.  This is used to auto-align
151    labels preceding instructions.  */
152 static symbolS *pru_last_label;
153 
154 
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.  */
159 static uint64_t
md_chars_to_number(char * buf,int n)160 md_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.  */
177 void
md_number_to_chars(char * buf,valueT val,int n)178 md_number_to_chars (char *buf, valueT val, int n)
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.  */
188 const char *
md_atof(int type,char * litP,int * sizeP)189 md_atof (int type, char *litP, int *sizeP)
190 {
191   return ieee_md_atof (type, litP, sizeP, false);
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.  */
199 static char const nop[4] = { 0xe0, 0xe0, 0xe0, 0x12 };
200 
201 /* Handles all machine-dependent alignment needs.  */
202 static void
pru_align(int log_size,const char * pfill,symbolS * label)203 pru_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;
249 	  int label_seen = false;
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 	      {
275 		label_seen = true;
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 
287 /** Support for self-check mode.  */
288 
289 /* Mode of the assembler.  */
290 typedef enum
291 {
292   PRU_MODE_ASSEMBLE,		/* Ordinary operation.  */
293   PRU_MODE_TEST		/* Hidden mode used for self testing.  */
294 } PRU_MODE;
295 
296 static PRU_MODE pru_mode = PRU_MODE_ASSEMBLE;
297 
298 /* This function is used to in self-checking mode
299    to check the assembled instruction.
300    OPCODE should be the assembled opcode, and exp_opcode
301    the parsed string representing the expected opcode.  */
302 
303 static void
pru_check_assembly(unsigned int opcode,const char * exp_opcode)304 pru_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 
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.  */
320 static void
s_pru_align(int ignore ATTRIBUTE_UNUSED)321 s_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.  */
368 static void
s_pru_text(int i)369 s_pru_text (int i)
370 {
371   obj_elf_text (i);
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.  */
379 static void
s_pru_data(int i)380 s_pru_data (int i)
381 {
382   obj_elf_data (i);
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.  */
390 static void
s_pru_section(int ignore)391 s_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.  */
400 static void
s_pru_ucons(int nbytes)401 s_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.  */
411 static void
s_pru_set(int equiv)412 s_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     {
428       bool done = true;
429       *endline = 0;
430 
431       if (!strcmp (directive, "no_warn_regname_label"))
432 	  pru_opt.warn_regname_label = false;
433       else
434 	done = false;
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 }	 */
454 const 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 
478 int
md_estimate_size_before_relax(fragS * fragp ATTRIBUTE_UNUSED,asection * seg ATTRIBUTE_UNUSED)479 md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
480 			       asection *seg ATTRIBUTE_UNUSED)
481 {
482   abort ();
483   return 0;
484 }
485 
486 void
md_convert_frag(bfd * headers ATTRIBUTE_UNUSED,segT segment ATTRIBUTE_UNUSED,fragS * fragp ATTRIBUTE_UNUSED)487 md_convert_frag (bfd *headers ATTRIBUTE_UNUSED, segT segment ATTRIBUTE_UNUSED,
488 		 fragS *fragp ATTRIBUTE_UNUSED)
489 {
490   abort ();
491 }
492 
493 
494 static bool
relaxable_section(asection * sec)495 relaxable_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.  */
503 int
pru_validate_fix_sub(fixS * fix)504 pru_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.  */
533 int
pru_force_relocation(fixS * fix)534 pru_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 
545 /** Fixups and overflow checking.  */
546 
547 /* Check a fixup for overflow.  */
548 static bfd_reloc_status_type
pru_check_overflow(valueT fixup,reloc_howto_type * howto)549 pru_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.  */
563 static void
pru_diagnose_overflow(valueT fixup,reloc_howto_type * howto,fixS * fixP,valueT value)564 pru_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.  */
640 void
md_apply_fix(fixS * fixP,valueT * valP,segT seg ATTRIBUTE_UNUSED)641 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
642 {
643   unsigned char *where;
644   valueT value = *valP;
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:
745 	  as_bad_subtract (fixP);
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)
755     as_bad_subtract (fixP);
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.  */
802 	  fixup = (offsetT) fixup >> howto->rightshift;
803 
804 	  /* Truncate the fixup to right size.  */
805 	  if (howto->bitsize == 0)
806 	    fixup = 0;
807 	  else
808 	    fixup &= ((valueT) 2 << (howto->bitsize - 1)) - 1;
809 
810 	  /* Fix up the instruction.  Non-contiguous bitfields need
811 	     special handling.  */
812 	  if (fixP->fx_r_type == BFD_RELOC_PRU_LDI32)
813 	    {
814 	      /* As the only 64-bit "insn", LDI32 needs special handling. */
815 	      uint32_t insn1 = insn & 0xffffffff;
816 	      uint32_t insn2 = insn >> 32;
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);
822 
823 	      md_number_to_chars (buf, insn1, 4);
824 	      md_number_to_chars (buf + 4, insn2, 4);
825 	    }
826 	  else
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 	    }
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 
852 /** Instruction parsing support.  */
853 
854 /* Creates a new pru_insn_relocS and returns a pointer to it.  */
855 static pru_insn_relocS *
pru_insn_reloc_new(bfd_reloc_code_real_type reloc_type,unsigned int pcrel)856 pru_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 ().  */
874 static void
pru_insn_reloc_destroy(pru_insn_relocS * reloc)875 pru_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.  */
892 static unsigned long
pru_assemble_expression(const char * exprstr,pru_insn_infoS * insn,pru_insn_relocS * prev_reloc,bfd_reloc_code_real_type reloc_type,unsigned int pcrel)893 pru_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.  */
956 static unsigned long
pru_assemble_noreloc_expression(const char * exprstr)957 pru_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 
990 static void
pru_assemble_arg_d(pru_insn_infoS * insn_info,const char * argstr)991 pru_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 
1004 static void
pru_assemble_arg_D(pru_insn_infoS * insn_info,const char * argstr)1005 pru_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 
1037 static void
pru_assemble_arg_R(pru_insn_infoS * insn_info,const char * argstr)1038 pru_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 
1056 static void
pru_assemble_arg_s(pru_insn_infoS * insn_info,const char * argstr)1057 pru_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 
1070 static void
pru_assemble_arg_S(pru_insn_infoS * insn_info,const char * argstr)1071 pru_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 
1085 static void
pru_assemble_arg_b(pru_insn_infoS * insn_info,const char * argstr)1086 pru_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);
1092       if (imm8 >= 0x100)
1093 	as_bad (_("value %lu is too large for a byte operand"), imm8);
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 
1106 static void
pru_assemble_arg_B(pru_insn_infoS * insn_info,const char * argstr)1107 pru_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 
1130 static void
pru_assemble_arg_i(pru_insn_infoS * insn_info,const char * argstr)1131 pru_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);
1149   SET_INSN_FIELD (RDSEL, insn_info->insn_code, RSEL_31_16);
1150   SET_INSN_FIELD (IMM16, insn_info->insn_code, imm32 >> 16);
1151   insn_info->ldi32_imm32 = imm32;
1152 }
1153 
1154 static void
pru_assemble_arg_j(pru_insn_infoS * insn_info,const char * argstr)1155 pru_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 
1176 static void
pru_assemble_arg_W(pru_insn_infoS * insn_info,const char * argstr)1177 pru_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 
1187 static void
pru_assemble_arg_o(pru_insn_infoS * insn_info,const char * argstr)1188 pru_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 
1196 static void
pru_assemble_arg_O(pru_insn_infoS * insn_info,const char * argstr)1197 pru_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 
1205 static void
pru_assemble_arg_l(pru_insn_infoS * insn_info,const char * argstr)1206 pru_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 
1231 static void
pru_assemble_arg_n(pru_insn_infoS * insn_info,const char * argstr)1232 pru_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 
1257 static void
pru_assemble_arg_c(pru_insn_infoS * insn_info,const char * argstr)1258 pru_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 
1268 static void
pru_assemble_arg_w(pru_insn_infoS * insn_info,const char * argstr)1269 pru_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 
1279 static void
pru_assemble_arg_x(pru_insn_infoS * insn_info,const char * argstr)1280 pru_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.  */
1296 static char *
pru_consume_arg(char * argstr,const char * parsestr)1297 pru_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.  */
1379 static char *
pru_consume_separator(char * argstr,const char * separator)1380 pru_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.  */
1397 static void
pru_parse_args(pru_insn_infoS * insn ATTRIBUTE_UNUSED,char * argstr,const char * parsestr,char ** parsed_args)1398 pru_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;
1406   bool terminate = false;
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'))
1441 	terminate = true;
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 
1453 /** Assembler output support.  */
1454 
1455 /* Output a normal instruction.  */
1456 static void
output_insn(pru_insn_infoS * insn)1457 output_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 */
1476 static void
output_insn_ldi32(pru_insn_infoS * insn)1477 output_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);
1484   SET_INSN_FIELD (IMM16, insn->insn_code, insn->ldi32_imm32 >> 16);
1485   SET_INSN_FIELD (RDSEL, insn->insn_code, RSEL_31_16);
1486   md_number_to_chars (f, insn->insn_code, 4);
1487 
1488   insn2 = insn->insn_code;
1489   SET_INSN_FIELD (IMM16, insn2, insn->ldi32_imm32 & 0xffff);
1490   SET_INSN_FIELD (RDSEL, insn2, RSEL_15_0);
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 
1504 /** External interfaces.  */
1505 
1506 /* The following functions are called by machine-independent parts of
1507    the assembler.  */
1508 int
md_parse_option(int c,const char * arg ATTRIBUTE_UNUSED)1509 md_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:
1518       pru_opt.link_relax = true;
1519       break;
1520     case OPTION_NO_LINK_RELAX:
1521       pru_opt.link_relax = false;
1522       break;
1523     case OPTION_NO_WARN_REGNAME_LABEL:
1524       pru_opt.warn_regname_label = false;
1525       break;
1526     default:
1527       return 0;
1528       break;
1529     }
1530 
1531   return 1;
1532 }
1533 
1534 const char *
pru_target_format(void)1535 pru_target_format (void)
1536 {
1537   return "elf32-pru";
1538 }
1539 
1540 /* Machine-dependent usage message.  */
1541 void
md_show_usage(FILE * stream)1542 md_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.  */
1555 void
md_begin(void)1556 md_begin (void)
1557 {
1558   int i;
1559 
1560   /* Create and fill a hashtable for the PRU opcodes, registers and
1561      arguments.  */
1562   pru_opcode_hash = str_htab_create ();
1563   pru_reg_hash = str_htab_create ();
1564 
1565   for (i = 0; i < NUMOPCODES; ++i)
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);
1569 
1570   for (i = 0; i < pru_num_regs; ++i)
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);
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.  */
1583 void
md_assemble(char * op_str)1584 md_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++);
1689 	      continue;
1690 
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.  */
1724 valueT
md_section_align(asection * seg,valueT addr)1725 md_section_align (asection *seg, valueT addr)
1726 {
1727   int align = bfd_section_alignment (seg);
1728   return ((addr + (1 << align) - 1) & (-((valueT) 1 << align)));
1729 }
1730 
1731 /* Implement tc_fix_adjustable.  */
1732 int
pru_fix_adjustable(fixS * fixp)1733 pru_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.  */
1758 arelent *
tc_gen_reloc(asection * section ATTRIBUTE_UNUSED,fixS * fixp)1759 tc_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 
1782 long
md_pcrel_from(fixS * fixP ATTRIBUTE_UNUSED)1783 md_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.  */
1789 void
pru_md_end(void)1790 pru_md_end (void)
1791 {
1792   htab_delete (pru_opcode_hash);
1793   htab_delete (pru_reg_hash);
1794 }
1795 
1796 symbolS *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)1797 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1798 {
1799   return NULL;
1800 }
1801 
1802 /* Implement tc_frob_label.  */
1803 void
pru_frob_label(symbolS * lab)1804 pru_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 
1821 static inline char *
skip_space(char * s)1822 skip_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 
1834 int
pru_parse_cons_expression(expressionS * exp,int nbytes)1835 pru_parse_cons_expression (expressionS *exp, int nbytes)
1836 {
1837   int is_pmem = false;
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);
1854 	      is_pmem = true;
1855 	      expression (exp);
1856 
1857 	      if (*input_line_pointer == ')')
1858 		++input_line_pointer;
1859 	      else
1860 		{
1861 		  as_bad (_("`)' required"));
1862 		  is_pmem = false;
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.  */
1878 void
pru_cons_fix_new(fragS * frag,int where,unsigned int nbytes,expressionS * exp,const int is_pmem)1879 pru_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
1902    register number.  Return the starting HW byte-register number.  */
1903 
1904 int
pru_regname_to_dw2regnum(char * regname)1905 pru_regname_to_dw2regnum (char *regname)
1906 {
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 
1919   struct pru_reg *r = pru_reg_lookup (regname);
1920 
1921   if (r == NULL || r->regsel >= RSEL_NUM_ITEMS)
1922     return -1;
1923   return r->index * 4 + regstart[r->regsel];
1924 }
1925 
1926 /* Implement tc_cfi_frame_initial_instructions, to initialize the DWARF-2
1927    unwind information for this procedure.  */
1928 void
pru_frame_initial_instructions(void)1929 pru_frame_initial_instructions (void)
1930 {
1931   const unsigned fp_regno = 4 * 4;
1932   cfi_add_CFA_def_cfa (fp_regno, 0);
1933 }
1934 
1935 bool
pru_allow_local_subtract(expressionS * left,expressionS * right,segT section)1936 pru_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)
1942     return true;
1943 
1944   /* If the symbols are not in a code section then they are OK.  */
1945   if ((section->flags & SEC_CODE) == 0)
1946     return true;
1947 
1948   if (left->X_add_symbol == right->X_add_symbol)
1949     return true;
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.  */
1954   return false;
1955 }
1956