1 /* TI PRU assembler.
2    Copyright (C) 2014-2021 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   s_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   s_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_where (fixP->fx_file, fixP->fx_line,
746 			_("expression too complex"));
747 	  break;
748 	}
749 
750       value = *valP = diffval;
751 
752       fixP->fx_subsy = NULL;
753   }
754   /* We don't actually support subtracting a symbol.  */
755   if (fixP->fx_subsy != (symbolS *) NULL)
756     as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
757 
758   /* For the DIFF relocs, write the value into the object file while still
759      keeping fx_done FALSE, as both the difference (recorded in the object file)
760      and the sym offset (part of fixP) are needed at link relax time.  */
761   where = (unsigned char *) fixP->fx_frag->fr_literal + fixP->fx_where;
762   switch (fixP->fx_r_type)
763     {
764     case BFD_RELOC_PRU_GNU_DIFF8:
765       *where = value;
766       break;
767     case BFD_RELOC_PRU_GNU_DIFF16:
768     case BFD_RELOC_PRU_GNU_DIFF16_PMEM:
769       bfd_putl16 ((bfd_vma) value, where);
770       break;
771     case BFD_RELOC_PRU_GNU_DIFF32:
772     case BFD_RELOC_PRU_GNU_DIFF32_PMEM:
773       bfd_putl32 ((bfd_vma) value, where);
774       break;
775     default:
776       break;
777     }
778 
779   if (fixP->fx_done)
780     /* Fully resolved fixup.  */
781     {
782       reloc_howto_type *howto
783 	= bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
784 
785       if (howto == NULL)
786 	as_bad_where (fixP->fx_file, fixP->fx_line,
787 		      _("relocation is not supported"));
788       else
789 	{
790 	  valueT fixup = value;
791 	  uint64_t insn;
792 	  char *buf;
793 
794 	  /* Get the instruction or data to be fixed up.  */
795 	  buf = fixP->fx_frag->fr_literal + fixP->fx_where;
796 	  insn = md_chars_to_number (buf, fixP->fx_size);
797 
798 	  /* Check for overflow, emitting a diagnostic if necessary.  */
799 	  if (pru_check_overflow (fixup, howto) != bfd_reloc_ok)
800 	    pru_diagnose_overflow (fixup, howto, fixP, insn);
801 
802 	  /* Apply the right shift.  */
803 	  fixup = (offsetT) fixup >> howto->rightshift;
804 
805 	  /* Truncate the fixup to right size.  */
806 	  if (howto->bitsize == 0)
807 	    fixup = 0;
808 	  else
809 	    fixup &= ((valueT) 2 << (howto->bitsize - 1)) - 1;
810 
811 	  /* Fix up the instruction.  Non-contiguous bitfields need
812 	     special handling.  */
813 	  if (fixP->fx_r_type == BFD_RELOC_PRU_LDI32)
814 	    {
815 	      /* As the only 64-bit "insn", LDI32 needs special handling. */
816 	      uint32_t insn1 = insn & 0xffffffff;
817 	      uint32_t insn2 = insn >> 32;
818 	      SET_INSN_FIELD (IMM16, insn1, fixup >> 16);
819 	      SET_INSN_FIELD (IMM16, insn2, fixup & 0xffff);
820 
821 	      SET_INSN_FIELD (RDSEL, insn1, RSEL_31_16);
822 	      SET_INSN_FIELD (RDSEL, insn2, RSEL_15_0);
823 
824 	      md_number_to_chars (buf, insn1, 4);
825 	      md_number_to_chars (buf + 4, insn2, 4);
826 	    }
827 	  else
828 	    {
829 	      if (fixP->fx_r_type == BFD_RELOC_PRU_S10_PCREL)
830 		SET_BROFF_URAW (insn, fixup);
831 	      else
832 		insn = (insn & ~howto->dst_mask) | (fixup << howto->bitpos);
833 	      md_number_to_chars (buf, insn, fixP->fx_size);
834 	    }
835 	}
836 
837       fixP->fx_done = 1;
838     }
839 
840   if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT)
841     {
842       fixP->fx_done = 0;
843       if (fixP->fx_addsy
844 	  && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
845 	S_SET_WEAK (fixP->fx_addsy);
846     }
847   else if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
848     fixP->fx_done = 0;
849 }
850 
851 
852 
853 /** Instruction parsing support.  */
854 
855 /* Creates a new pru_insn_relocS and returns a pointer to it.  */
856 static pru_insn_relocS *
pru_insn_reloc_new(bfd_reloc_code_real_type reloc_type,unsigned int pcrel)857 pru_insn_reloc_new (bfd_reloc_code_real_type reloc_type, unsigned int pcrel)
858 {
859   pru_insn_relocS *retval;
860   retval = XNEW (pru_insn_relocS);
861   if (retval == NULL)
862     {
863       as_bad (_("can't create relocation"));
864       abort ();
865     }
866 
867   /* Fill out the fields with default values.  */
868   retval->reloc_next = NULL;
869   retval->reloc_type = reloc_type;
870   retval->reloc_pcrel = pcrel;
871   return retval;
872 }
873 
874 /* Frees up memory previously allocated by pru_insn_reloc_new ().  */
875 static void
pru_insn_reloc_destroy(pru_insn_relocS * reloc)876 pru_insn_reloc_destroy (pru_insn_relocS *reloc)
877 {
878   pru_insn_relocS *next;
879 
880   while (reloc)
881     {
882       next = reloc->reloc_next;
883       free (reloc);
884       reloc = next;
885     }
886 }
887 
888 /* The various pru_assemble_* functions call this
889    function to generate an expression from a string representing an expression.
890    It then tries to evaluate the expression, and if it can, returns its value.
891    If not, it creates a new pru_insn_relocS and stores the expression and
892    reloc_type for future use.  */
893 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)894 pru_assemble_expression (const char *exprstr,
895 			   pru_insn_infoS *insn,
896 			   pru_insn_relocS *prev_reloc,
897 			   bfd_reloc_code_real_type reloc_type,
898 			   unsigned int pcrel)
899 {
900   expressionS *ep;
901   pru_insn_relocS *reloc;
902   char *saved_line_ptr;
903   unsigned short value;
904 
905   gas_assert (exprstr != NULL);
906   gas_assert (insn != NULL);
907 
908   /* We use this blank keyword to distinguish register from
909      label operands.  */
910   if (strstr (exprstr, "%label") != NULL)
911     {
912       exprstr += strlen ("%label") + 1;
913     }
914 
915   /* Check for pmem relocation operator.
916      Change the relocation type and advance the ptr to the start of
917      the expression proper.  */
918   if (strstr (exprstr, "%pmem") != NULL)
919     {
920       reloc_type = BFD_RELOC_PRU_U16_PMEMIMM;
921       exprstr += strlen ("%pmem") + 1;
922     }
923 
924   /* We potentially have a relocation.  */
925   reloc = pru_insn_reloc_new (reloc_type, pcrel);
926   if (prev_reloc != NULL)
927     prev_reloc->reloc_next = reloc;
928   else
929     insn->insn_reloc = reloc;
930 
931   /* Parse the expression string.  */
932   ep = &reloc->reloc_expression;
933   saved_line_ptr = input_line_pointer;
934   input_line_pointer = (char *) exprstr;
935   SKIP_WHITESPACE ();
936   expression (ep);
937   SKIP_WHITESPACE ();
938   if (*input_line_pointer)
939     as_bad (_("trailing garbage after expression: %s"), input_line_pointer);
940   input_line_pointer = saved_line_ptr;
941 
942 
943   if (ep->X_op == O_illegal || ep->X_op == O_absent)
944     as_bad (_("expected expression, got %s"), exprstr);
945 
946   /* This is redundant as the fixup will put this into
947      the instruction, but it is included here so that
948      self-test mode (-r) works.  */
949   value = 0;
950   if (pru_mode == PRU_MODE_TEST && ep->X_op == O_constant)
951     value = ep->X_add_number;
952 
953   return (unsigned long) value;
954 }
955 
956 /* Try to parse a non-relocatable expression.  */
957 static unsigned long
pru_assemble_noreloc_expression(const char * exprstr)958 pru_assemble_noreloc_expression (const char *exprstr)
959 {
960   expressionS exp;
961   char *saved_line_ptr;
962   unsigned long val;
963 
964   gas_assert (exprstr != NULL);
965 
966   saved_line_ptr = input_line_pointer;
967   input_line_pointer = (char *) exprstr;
968   SKIP_WHITESPACE ();
969   expression (&exp);
970   SKIP_WHITESPACE ();
971   if (*input_line_pointer)
972     as_bad (_("trailing garbage after expression: %s"), input_line_pointer);
973   input_line_pointer = saved_line_ptr;
974 
975   val = 0;
976   if (exp.X_op != O_constant)
977     as_bad (_("expected constant expression, got %s"), exprstr);
978   else
979     val = exp.X_add_number;
980 
981   return val;
982 }
983 
984 /* Argument assemble functions.
985    All take an instruction argument string, and a pointer
986    to an instruction opcode.  Upon return the insn_opcode
987    has the relevant fields filled in to represent the arg
988    string.  The return value is NULL if successful, or
989    an error message if an error was detected.  */
990 
991 static void
pru_assemble_arg_d(pru_insn_infoS * insn_info,const char * argstr)992 pru_assemble_arg_d (pru_insn_infoS *insn_info, const char *argstr)
993 {
994   struct pru_reg *dst = pru_reg_lookup (argstr);
995 
996   if (dst == NULL)
997     as_bad (_("unknown register %s"), argstr);
998   else
999     {
1000       SET_INSN_FIELD (RD, insn_info->insn_code, dst->index);
1001       SET_INSN_FIELD (RDSEL, insn_info->insn_code, dst->regsel);
1002     }
1003 }
1004 
1005 static void
pru_assemble_arg_D(pru_insn_infoS * insn_info,const char * argstr)1006 pru_assemble_arg_D (pru_insn_infoS *insn_info, const char *argstr)
1007 {
1008   struct pru_reg *dst;
1009 
1010   /* The leading & before an address register is optional.  */
1011   if (*argstr == '&')
1012     argstr++;
1013 
1014   dst = pru_reg_lookup (argstr);
1015 
1016   if (dst == NULL)
1017     as_bad (_("unknown register %s"), argstr);
1018   else
1019     {
1020       unsigned long rxb = 0;
1021 
1022       switch (dst->regsel)
1023 	{
1024 	case RSEL_31_0: rxb = 0; break;	/* whole register defaults to .b0  */
1025 	case RSEL_7_0: rxb = 0; break;
1026 	case RSEL_15_8: rxb = 1; break;
1027 	case RSEL_23_16: rxb = 2; break;
1028 	case RSEL_31_24: rxb = 3; break;
1029 	default:
1030 	  as_bad (_("data transfer register cannot be halfword"));
1031 	}
1032 
1033       SET_INSN_FIELD (RD, insn_info->insn_code, dst->index);
1034       SET_INSN_FIELD (RDB, insn_info->insn_code, rxb);
1035     }
1036 }
1037 
1038 static void
pru_assemble_arg_R(pru_insn_infoS * insn_info,const char * argstr)1039 pru_assemble_arg_R (pru_insn_infoS *insn_info, const char *argstr)
1040 {
1041   struct pru_reg *dst = pru_reg_lookup (argstr);
1042 
1043   if (dst == NULL)
1044     as_bad (_("unknown register %s"), argstr);
1045   else
1046     {
1047       if (dst->regsel != RSEL_31_0)
1048 	{
1049 	  as_bad (_("destination register must be full-word"));
1050 	}
1051 
1052       SET_INSN_FIELD (RD, insn_info->insn_code, dst->index);
1053       SET_INSN_FIELD (RDSEL, insn_info->insn_code, dst->regsel);
1054     }
1055 }
1056 
1057 static void
pru_assemble_arg_s(pru_insn_infoS * insn_info,const char * argstr)1058 pru_assemble_arg_s (pru_insn_infoS *insn_info, const char *argstr)
1059 {
1060   struct pru_reg *src1 = pru_reg_lookup (argstr);
1061 
1062   if (src1 == NULL)
1063     as_bad (_("unknown register %s"), argstr);
1064   else
1065     {
1066       SET_INSN_FIELD (RS1, insn_info->insn_code, src1->index);
1067       SET_INSN_FIELD (RS1SEL, insn_info->insn_code, src1->regsel);
1068     }
1069 }
1070 
1071 static void
pru_assemble_arg_S(pru_insn_infoS * insn_info,const char * argstr)1072 pru_assemble_arg_S (pru_insn_infoS *insn_info, const char *argstr)
1073 {
1074   struct pru_reg *src1 = pru_reg_lookup (argstr);
1075 
1076   if (src1 == NULL)
1077     as_bad (_("unknown register %s"), argstr);
1078   else
1079     {
1080       if (src1->regsel != RSEL_31_0)
1081 	as_bad (_("cannot use partial register %s for addressing"), argstr);
1082       SET_INSN_FIELD (RS1, insn_info->insn_code, src1->index);
1083     }
1084 }
1085 
1086 static void
pru_assemble_arg_b(pru_insn_infoS * insn_info,const char * argstr)1087 pru_assemble_arg_b (pru_insn_infoS *insn_info, const char *argstr)
1088 {
1089   struct pru_reg *src2 = pru_reg_lookup (argstr);
1090   if (src2 == NULL)
1091     {
1092       unsigned long imm8 = pru_assemble_noreloc_expression (argstr);
1093       if (imm8 >= 0x100)
1094 	as_bad (_("value %lu is too large for a byte operand"), imm8);
1095       SET_INSN_FIELD (IMM8, insn_info->insn_code, imm8);
1096       SET_INSN_FIELD (IO, insn_info->insn_code, 1);
1097     }
1098   else
1099     {
1100       SET_INSN_FIELD (IO, insn_info->insn_code, 0);
1101       SET_INSN_FIELD (RS2, insn_info->insn_code, src2->index);
1102       SET_INSN_FIELD (RS2SEL, insn_info->insn_code, src2->regsel);
1103     }
1104 
1105 }
1106 
1107 static void
pru_assemble_arg_B(pru_insn_infoS * insn_info,const char * argstr)1108 pru_assemble_arg_B (pru_insn_infoS *insn_info, const char *argstr)
1109 {
1110   struct pru_reg *src2 = pru_reg_lookup (argstr);
1111   if (src2 == NULL)
1112     {
1113       unsigned long imm8;
1114       imm8 = pru_assemble_noreloc_expression (argstr);
1115       if (!imm8 || imm8 > 0xff)
1116 	as_bad (_("loop count constant %ld is out of range [1..%d]"),
1117 		imm8, 0xff);
1118       /* Note: HW expects the immediate loop count field
1119 	 to be one less than the actual loop count.  */
1120       SET_INSN_FIELD (IMM8, insn_info->insn_code, imm8 - 1);
1121       SET_INSN_FIELD (IO, insn_info->insn_code, 1);
1122     }
1123   else
1124     {
1125       SET_INSN_FIELD (IO, insn_info->insn_code, 0);
1126       SET_INSN_FIELD (RS2, insn_info->insn_code, src2->index);
1127       SET_INSN_FIELD (RS2SEL, insn_info->insn_code, src2->regsel);
1128     }
1129 }
1130 
1131 static void
pru_assemble_arg_i(pru_insn_infoS * insn_info,const char * argstr)1132 pru_assemble_arg_i (pru_insn_infoS *insn_info, const char *argstr)
1133 {
1134   unsigned long imm32;
1135 
1136   /* We must not generate PRU_LDI32 relocation if relaxation is disabled in
1137      GAS. Consider the following scenario: GAS relaxation is disabled, so
1138      DIFF* expressions are fixed and not emitted as relocations. Then if LD
1139      has relaxation enabled, it may shorten LDI32 but will not update
1140      accordingly the DIFF expressions.  */
1141   if (pru_opt.link_relax)
1142     imm32 = pru_assemble_expression (argstr, insn_info,
1143 				     insn_info->insn_reloc,
1144 				     BFD_RELOC_PRU_LDI32, 0);
1145   else
1146     imm32 = pru_assemble_noreloc_expression (argstr);
1147 
1148   /* QUIRK: LDI must clear IO bit high, even though it has immediate arg. */
1149   SET_INSN_FIELD (IO, insn_info->insn_code, 0);
1150   SET_INSN_FIELD (RDSEL, insn_info->insn_code, RSEL_31_16);
1151   SET_INSN_FIELD (IMM16, insn_info->insn_code, imm32 >> 16);
1152   insn_info->ldi32_imm32 = imm32;
1153 }
1154 
1155 static void
pru_assemble_arg_j(pru_insn_infoS * insn_info,const char * argstr)1156 pru_assemble_arg_j (pru_insn_infoS *insn_info, const char *argstr)
1157 {
1158   struct pru_reg *src2 = pru_reg_lookup (argstr);
1159 
1160   if (src2 == NULL)
1161     {
1162       unsigned long imm16 = pru_assemble_expression (argstr, insn_info,
1163 						     insn_info->insn_reloc,
1164 						     BFD_RELOC_PRU_U16_PMEMIMM,
1165 						     0);
1166       SET_INSN_FIELD (IMM16, insn_info->insn_code, imm16);
1167       SET_INSN_FIELD (IO, insn_info->insn_code, 1);
1168     }
1169   else
1170     {
1171       SET_INSN_FIELD (IO, insn_info->insn_code, 0);
1172       SET_INSN_FIELD (RS2, insn_info->insn_code, src2->index);
1173       SET_INSN_FIELD (RS2SEL, insn_info->insn_code, src2->regsel);
1174     }
1175 }
1176 
1177 static void
pru_assemble_arg_W(pru_insn_infoS * insn_info,const char * argstr)1178 pru_assemble_arg_W (pru_insn_infoS *insn_info, const char *argstr)
1179 {
1180   unsigned long imm16 = pru_assemble_expression (argstr, insn_info,
1181 						 insn_info->insn_reloc,
1182 						 BFD_RELOC_PRU_U16, 0);
1183   /* QUIRK: LDI must clear IO bit high, even though it has immediate arg.  */
1184   SET_INSN_FIELD (IO, insn_info->insn_code, 0);
1185   SET_INSN_FIELD (IMM16, insn_info->insn_code, imm16);
1186 }
1187 
1188 static void
pru_assemble_arg_o(pru_insn_infoS * insn_info,const char * argstr)1189 pru_assemble_arg_o (pru_insn_infoS *insn_info, const char *argstr)
1190 {
1191   unsigned long imm10 = pru_assemble_expression (argstr, insn_info,
1192 						 insn_info->insn_reloc,
1193 						 BFD_RELOC_PRU_S10_PCREL, 1);
1194   SET_BROFF_URAW (insn_info->insn_code, imm10);
1195 }
1196 
1197 static void
pru_assemble_arg_O(pru_insn_infoS * insn_info,const char * argstr)1198 pru_assemble_arg_O (pru_insn_infoS *insn_info, const char *argstr)
1199 {
1200   unsigned long imm8 = pru_assemble_expression (argstr, insn_info,
1201 						insn_info->insn_reloc,
1202 						BFD_RELOC_PRU_U8_PCREL, 1);
1203   SET_INSN_FIELD (LOOP_JMPOFFS, insn_info->insn_code, imm8);
1204 }
1205 
1206 static void
pru_assemble_arg_l(pru_insn_infoS * insn_info,const char * argstr)1207 pru_assemble_arg_l (pru_insn_infoS *insn_info, const char *argstr)
1208 {
1209   unsigned long burstlen = 0;
1210   struct pru_reg *blreg = pru_reg_lookup (argstr);
1211 
1212   if (blreg == NULL)
1213     {
1214       burstlen = pru_assemble_noreloc_expression (argstr);
1215       if (!burstlen || burstlen > LSSBBO_BYTECOUNT_R0_BITS7_0)
1216 	as_bad (_("byte count constant %ld is out of range [1..%d]"),
1217 		burstlen, LSSBBO_BYTECOUNT_R0_BITS7_0);
1218       burstlen--;
1219     }
1220   else
1221     {
1222       if (blreg->index != 0)
1223 	as_bad (_("only r0 can be used as byte count register"));
1224       else if (blreg->regsel > RSEL_31_24)
1225 	as_bad (_("only r0.bX byte fields of r0 can be used as byte count"));
1226       else
1227 	burstlen = LSSBBO_BYTECOUNT_R0_BITS7_0 + blreg->regsel;
1228     }
1229     SET_BURSTLEN (insn_info->insn_code, burstlen);
1230 }
1231 
1232 static void
pru_assemble_arg_n(pru_insn_infoS * insn_info,const char * argstr)1233 pru_assemble_arg_n (pru_insn_infoS *insn_info, const char *argstr)
1234 {
1235   unsigned long burstlen = 0;
1236   struct pru_reg *blreg = pru_reg_lookup (argstr);
1237 
1238   if (blreg == NULL)
1239     {
1240       burstlen = pru_assemble_noreloc_expression (argstr);
1241       if (!burstlen || burstlen > LSSBBO_BYTECOUNT_R0_BITS7_0)
1242 	as_bad (_("byte count constant %ld is out of range [1..%d]"),
1243 		burstlen, LSSBBO_BYTECOUNT_R0_BITS7_0);
1244       burstlen--;
1245     }
1246   else
1247     {
1248       if (blreg->index != 0)
1249 	as_bad (_("only r0 can be used as byte count register"));
1250       else if (blreg->regsel > RSEL_31_24)
1251 	as_bad (_("only r0.bX byte fields of r0 can be used as byte count"));
1252       else
1253 	burstlen = LSSBBO_BYTECOUNT_R0_BITS7_0 + blreg->regsel;
1254     }
1255     SET_INSN_FIELD (XFR_LENGTH, insn_info->insn_code, burstlen);
1256 }
1257 
1258 static void
pru_assemble_arg_c(pru_insn_infoS * insn_info,const char * argstr)1259 pru_assemble_arg_c (pru_insn_infoS *insn_info, const char *argstr)
1260 {
1261   unsigned long cb = pru_assemble_noreloc_expression (argstr);
1262 
1263   if (cb > 31)
1264     as_bad (_("invalid constant table offset %ld"), cb);
1265   else
1266     SET_INSN_FIELD (CB, insn_info->insn_code, cb);
1267 }
1268 
1269 static void
pru_assemble_arg_w(pru_insn_infoS * insn_info,const char * argstr)1270 pru_assemble_arg_w (pru_insn_infoS *insn_info, const char *argstr)
1271 {
1272   unsigned long wk = pru_assemble_noreloc_expression (argstr);
1273 
1274   if (wk != 0 && wk != 1)
1275     as_bad (_("invalid WakeOnStatus %ld"), wk);
1276   else
1277     SET_INSN_FIELD (WAKEONSTATUS, insn_info->insn_code, wk);
1278 }
1279 
1280 static void
pru_assemble_arg_x(pru_insn_infoS * insn_info,const char * argstr)1281 pru_assemble_arg_x (pru_insn_infoS *insn_info, const char *argstr)
1282 {
1283   unsigned long wba = pru_assemble_noreloc_expression (argstr);
1284 
1285   if (wba > 255)
1286     as_bad (_("invalid XFR WideBus Address %ld"), wba);
1287   else
1288     SET_INSN_FIELD (XFR_WBA, insn_info->insn_code, wba);
1289 }
1290 
1291 /* The function consume_arg takes a pointer into a string
1292    of instruction tokens (args) and a pointer into a string
1293    representing the expected sequence of tokens and separators.
1294    It checks whether the first argument in argstr is of the
1295    expected type, throwing an error if it is not, and returns
1296    the pointer argstr.  */
1297 static char *
pru_consume_arg(char * argstr,const char * parsestr)1298 pru_consume_arg (char *argstr, const char *parsestr)
1299 {
1300   char *temp;
1301 
1302   switch (*parsestr)
1303     {
1304     case 'W':
1305       if (*argstr == '%')
1306 	{
1307 	  if (strprefix (argstr, "%pmem") || strprefix (argstr, "%label"))
1308 	    {
1309 	      /* We zap the parentheses because we don't want them confused
1310 		 with separators.  */
1311 	      temp = strchr (argstr, '(');
1312 	      if (temp != NULL)
1313 		*temp = ' ';
1314 	      temp = strchr (argstr, ')');
1315 	      if (temp != NULL)
1316 		*temp = ' ';
1317 	    }
1318 	  else
1319 	    as_bad (_("badly formed expression near %s"), argstr);
1320 	}
1321       break;
1322 
1323     case 'j':
1324     case 'o':
1325     case 'O':
1326       if (*argstr == '%')
1327 	{
1328 	  /* Only 'j' really requires %label for distinguishing registers
1329 	     from labels, but we include 'o' and 'O' here to avoid
1330 	     confusing assembler programmers. Thus for completeness all
1331 	     jump operands can be prefixed with %label.  */
1332 	  if (strprefix (argstr, "%label"))
1333 	    {
1334 	      /* We zap the parentheses because we don't want them confused
1335 		 with separators.  */
1336 	      temp = strchr (argstr, '(');
1337 	      if (temp != NULL)
1338 		*temp = ' ';
1339 	      temp = strchr (argstr, ')');
1340 	      if (temp != NULL)
1341 		*temp = ' ';
1342 	    }
1343 	  else
1344 	    as_bad (_("badly formed expression near %s"), argstr);
1345 	}
1346       break;
1347 
1348     case 'b':
1349     case 'B':
1350     case 'c':
1351     case 'd':
1352     case 'D':
1353     case 'E':
1354     case 'i':
1355     case 's':
1356     case 'S':
1357     case 'l':
1358     case 'n':
1359     case 'R':
1360     case 'w':
1361     case 'x':
1362       /* We can't have %pmem here.  */
1363       if (*argstr == '%')
1364 	as_bad (_("badly formed expression near %s"), argstr);
1365       break;
1366     default:
1367       BAD_CASE (*parsestr);
1368       break;
1369     }
1370 
1371   return argstr;
1372 }
1373 
1374 /* The function consume_separator takes a pointer into a string
1375    of instruction tokens (args) and a pointer into a string representing
1376    the expected sequence of tokens and separators.  It finds the first
1377    instance of the character pointed to by separator in argstr, and
1378    returns a pointer to the next element of argstr, which is the
1379    following token in the sequence.  */
1380 static char *
pru_consume_separator(char * argstr,const char * separator)1381 pru_consume_separator (char *argstr, const char *separator)
1382 {
1383   char *p;
1384 
1385   p = strchr (argstr, *separator);
1386 
1387   if (p != NULL)
1388     *p++ = 0;
1389   else
1390     as_bad (_("expecting %c near %s"), *separator, argstr);
1391   return p;
1392 }
1393 
1394 
1395 /* The principal argument parsing function which takes a string argstr
1396    representing the instruction arguments for insn, and extracts the argument
1397    tokens matching parsestr into parsed_args.  */
1398 static void
pru_parse_args(pru_insn_infoS * insn ATTRIBUTE_UNUSED,char * argstr,const char * parsestr,char ** parsed_args)1399 pru_parse_args (pru_insn_infoS *insn ATTRIBUTE_UNUSED, char *argstr,
1400 		  const char *parsestr, char **parsed_args)
1401 {
1402   char *p;
1403   char *end = NULL;
1404   int i;
1405   p = argstr;
1406   i = 0;
1407   bool terminate = false;
1408 
1409   /* This rest of this function is it too fragile and it mostly works,
1410      therefore special case this one.  */
1411   if (*parsestr == 0 && argstr != 0)
1412     {
1413       as_bad (_("too many arguments"));
1414       parsed_args[0] = NULL;
1415       return;
1416     }
1417 
1418   while (p != NULL && !terminate && i < PRU_MAX_INSN_TOKENS)
1419     {
1420       parsed_args[i] = pru_consume_arg (p, parsestr);
1421       ++parsestr;
1422       if (*parsestr != '\0')
1423 	{
1424 	  p = pru_consume_separator (p, parsestr);
1425 	  ++parsestr;
1426 	}
1427       else
1428 	{
1429 	  /* Check that the argument string has no trailing arguments.  */
1430 	  /* If we've got a %pmem relocation, we've zapped the parens with
1431 	     spaces.  */
1432 	  if (strprefix (p, "%pmem") || strprefix (p, "%label"))
1433 	    end = strpbrk (p, ",");
1434 	  else
1435 	    end = strpbrk (p, " ,");
1436 
1437 	  if (end != NULL)
1438 	    as_bad (_("too many arguments"));
1439 	}
1440 
1441       if (*parsestr == '\0' || (p != NULL && *p == '\0'))
1442 	terminate = true;
1443       ++i;
1444     }
1445 
1446   parsed_args[i] = NULL;
1447 
1448   /* There are no instructions with optional arguments; complain.  */
1449   if (*parsestr != '\0')
1450     as_bad (_("missing argument"));
1451 }
1452 
1453 
1454 /** Assembler output support.  */
1455 
1456 /* Output a normal instruction.  */
1457 static void
output_insn(pru_insn_infoS * insn)1458 output_insn (pru_insn_infoS *insn)
1459 {
1460   char *f;
1461   pru_insn_relocS *reloc;
1462 
1463   f = frag_more (4);
1464   /* This allocates enough space for the instruction
1465      and puts it in the current frag.  */
1466   md_number_to_chars (f, insn->insn_code, 4);
1467   /* Emit debug info.  */
1468   dwarf2_emit_insn (4);
1469   /* Create any fixups to be acted on later.  */
1470   for (reloc = insn->insn_reloc; reloc != NULL; reloc = reloc->reloc_next)
1471     fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
1472 		 &reloc->reloc_expression, reloc->reloc_pcrel,
1473 		 reloc->reloc_type);
1474 }
1475 
1476 /* Output two LDI instructions from LDI32 macro */
1477 static void
output_insn_ldi32(pru_insn_infoS * insn)1478 output_insn_ldi32 (pru_insn_infoS *insn)
1479 {
1480   char *f;
1481   pru_insn_relocS *reloc;
1482   unsigned long insn2;
1483 
1484   f = frag_more (8);
1485   SET_INSN_FIELD (IMM16, insn->insn_code, insn->ldi32_imm32 >> 16);
1486   SET_INSN_FIELD (RDSEL, insn->insn_code, RSEL_31_16);
1487   md_number_to_chars (f, insn->insn_code, 4);
1488 
1489   insn2 = insn->insn_code;
1490   SET_INSN_FIELD (IMM16, insn2, insn->ldi32_imm32 & 0xffff);
1491   SET_INSN_FIELD (RDSEL, insn2, RSEL_15_0);
1492   md_number_to_chars (f + 4, insn2, 4);
1493 
1494   /* Emit debug info.  */
1495   dwarf2_emit_insn (8);
1496 
1497   /* Create any fixups to be acted on later.  */
1498   for (reloc = insn->insn_reloc; reloc != NULL; reloc = reloc->reloc_next)
1499     fix_new_exp (frag_now, f - frag_now->fr_literal, 4,
1500 		 &reloc->reloc_expression, reloc->reloc_pcrel,
1501 		 reloc->reloc_type);
1502 }
1503 
1504 
1505 /** External interfaces.  */
1506 
1507 /* The following functions are called by machine-independent parts of
1508    the assembler.  */
1509 int
md_parse_option(int c,const char * arg ATTRIBUTE_UNUSED)1510 md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
1511 {
1512   switch (c)
1513     {
1514     case 'r':
1515       /* Hidden option for self-test mode.  */
1516       pru_mode = PRU_MODE_TEST;
1517       break;
1518     case OPTION_LINK_RELAX:
1519       pru_opt.link_relax = true;
1520       break;
1521     case OPTION_NO_LINK_RELAX:
1522       pru_opt.link_relax = false;
1523       break;
1524     case OPTION_NO_WARN_REGNAME_LABEL:
1525       pru_opt.warn_regname_label = false;
1526       break;
1527     default:
1528       return 0;
1529       break;
1530     }
1531 
1532   return 1;
1533 }
1534 
1535 const char *
pru_target_format(void)1536 pru_target_format (void)
1537 {
1538   return "elf32-pru";
1539 }
1540 
1541 /* Machine-dependent usage message.  */
1542 void
md_show_usage(FILE * stream)1543 md_show_usage (FILE *stream)
1544 {
1545   fprintf (stream,
1546     _("PRU options:\n"
1547       "  -mlink-relax     generate relocations for linker relaxation (default).\n"
1548       "  -mno-link-relax  don't generate relocations for linker relaxation.\n"
1549     ));
1550 
1551 }
1552 
1553 /* This function is called once, at assembler startup time.
1554    It should set up all the tables, etc.  that the MD part of the
1555    assembler will need.  */
1556 void
md_begin(void)1557 md_begin (void)
1558 {
1559   int i;
1560 
1561   /* Create and fill a hashtable for the PRU opcodes, registers and
1562      arguments.  */
1563   pru_opcode_hash = str_htab_create ();
1564   pru_reg_hash = str_htab_create ();
1565 
1566   for (i = 0; i < NUMOPCODES; ++i)
1567     if (str_hash_insert (pru_opcode_hash, pru_opcodes[i].name,
1568 			 &pru_opcodes[i], 0) != NULL)
1569       as_fatal (_("duplicate %s"), pru_opcodes[i].name);
1570 
1571   for (i = 0; i < pru_num_regs; ++i)
1572     if (str_hash_insert (pru_reg_hash, pru_regs[i].name, &pru_regs[i], 0))
1573       as_fatal (_("duplicate %s"), pru_regs[i].name);
1574 
1575   linkrelax = pru_opt.link_relax;
1576   /* Initialize the alignment data.  */
1577   pru_current_align_seg = now_seg;
1578   pru_last_label = NULL;
1579   pru_current_align = 0;
1580 }
1581 
1582 
1583 /* Assembles a single line of PRU assembly language.  */
1584 void
md_assemble(char * op_str)1585 md_assemble (char *op_str)
1586 {
1587   char *argstr;
1588   char *op_strdup = NULL;
1589   pru_insn_infoS thisinsn;
1590   pru_insn_infoS *insn = &thisinsn;
1591 
1592   /* Make sure we are aligned on a 4-byte boundary.  */
1593   if (pru_current_align < 2)
1594     pru_align (2, NULL, pru_last_label);
1595   else if (pru_current_align > 2)
1596     pru_current_align = 2;
1597   pru_last_label = NULL;
1598 
1599   /* We don't want to clobber to op_str
1600      because we want to be able to use it in messages.  */
1601   op_strdup = strdup (op_str);
1602   insn->insn_tokens[0] = strtok (op_strdup, " ");
1603   argstr = strtok (NULL, "");
1604 
1605   /* Assemble the opcode.  */
1606   insn->insn_pru_opcode = pru_opcode_lookup (insn->insn_tokens[0]);
1607   insn->insn_reloc = NULL;
1608 
1609   if (insn->insn_pru_opcode != NULL)
1610     {
1611       const char *argsfmt = insn->insn_pru_opcode->args;
1612       const char **argtk = &insn->insn_tokens[1];
1613       const char *argp;
1614 
1615       /* Set the opcode for the instruction.  */
1616       insn->insn_code = insn->insn_pru_opcode->match;
1617 
1618       if (pru_mode == PRU_MODE_TEST)
1619 	{
1620 	  /* Add the "expected" instruction parameter used for validation.  */
1621 	  argsfmt = malloc (strlen (argsfmt) + 3);
1622 	  sprintf ((char *)argsfmt, "%s,E", insn->insn_pru_opcode->args);
1623 	}
1624       pru_parse_args (insn, argstr, argsfmt,
1625 		      (char **) &insn->insn_tokens[1]);
1626 
1627       for (argp = argsfmt; !had_errors () && *argp && *argtk; ++argp)
1628 	{
1629 	  gas_assert (argtk <= &insn->insn_tokens[PRU_MAX_INSN_TOKENS]);
1630 
1631 	  switch (*argp)
1632 	    {
1633 	    case ',':
1634 	      continue;
1635 
1636 	    case 'd':
1637 	      pru_assemble_arg_d (insn, *argtk++);
1638 	      continue;
1639 	    case 'D':
1640 	      pru_assemble_arg_D (insn, *argtk++);
1641 	      continue;
1642 	    case 'R':
1643 	      pru_assemble_arg_R (insn, *argtk++);
1644 	      continue;
1645 	    case 's':
1646 	      pru_assemble_arg_s (insn, *argtk++);
1647 	      continue;
1648 	    case 'S':
1649 	      pru_assemble_arg_S (insn, *argtk++);
1650 	      continue;
1651 	    case 'b':
1652 	      pru_assemble_arg_b (insn, *argtk++);
1653 	      continue;
1654 	    case 'B':
1655 	      pru_assemble_arg_B (insn, *argtk++);
1656 	      continue;
1657 	    case 'i':
1658 	      pru_assemble_arg_i (insn, *argtk++);
1659 	      continue;
1660 	    case 'j':
1661 	      pru_assemble_arg_j (insn, *argtk++);
1662 	      continue;
1663 	    case 'W':
1664 	      pru_assemble_arg_W (insn, *argtk++);
1665 	      continue;
1666 	    case 'o':
1667 	      pru_assemble_arg_o (insn, *argtk++);
1668 	      continue;
1669 	    case 'O':
1670 	      pru_assemble_arg_O (insn, *argtk++);
1671 	      continue;
1672 	    case 'l':
1673 	      pru_assemble_arg_l (insn, *argtk++);
1674 	      continue;
1675 	    case 'n':
1676 	      pru_assemble_arg_n (insn, *argtk++);
1677 	      continue;
1678 	    case 'c':
1679 	      pru_assemble_arg_c (insn, *argtk++);
1680 	      continue;
1681 	    case 'w':
1682 	      pru_assemble_arg_w (insn, *argtk++);
1683 	      continue;
1684 	    case 'x':
1685 	      pru_assemble_arg_x (insn, *argtk++);
1686 	      continue;
1687 
1688 	    case 'E':
1689 	      pru_check_assembly (insn->insn_code, *argtk++);
1690 	      continue;
1691 
1692 	    default:
1693 	      BAD_CASE (*argp);
1694 	    }
1695 	}
1696 
1697       if (*argp && !had_errors ())
1698 	as_bad (_("missing argument"));
1699 
1700       if (!had_errors ())
1701 	{
1702 	  if (insn->insn_pru_opcode->pinfo & PRU_INSN_LDI32)
1703 	    {
1704 	      output_insn_ldi32 (insn);
1705 	    }
1706 	  else
1707 	    {
1708 	      output_insn (insn);
1709 	    }
1710 	}
1711 
1712       if (pru_mode == PRU_MODE_TEST)
1713 	free ((char *)argsfmt);
1714     }
1715   else
1716     /* Unrecognised instruction - error.  */
1717     as_bad (_("unrecognised instruction %s"), insn->insn_tokens[0]);
1718 
1719   /* Don't leak memory.  */
1720   pru_insn_reloc_destroy (insn->insn_reloc);
1721   free (op_strdup);
1722 }
1723 
1724 /* Round up section size.  */
1725 valueT
md_section_align(asection * seg,valueT addr)1726 md_section_align (asection *seg, valueT addr)
1727 {
1728   int align = bfd_section_alignment (seg);
1729   return ((addr + (1 << align) - 1) & (-((valueT) 1 << align)));
1730 }
1731 
1732 /* Implement tc_fix_adjustable.  */
1733 int
pru_fix_adjustable(fixS * fixp)1734 pru_fix_adjustable (fixS *fixp)
1735 {
1736   if (fixp->fx_addsy == NULL)
1737     return 1;
1738 
1739   /* Prevent all adjustments to global symbols.  */
1740   if (OUTPUT_FLAVOR == bfd_target_elf_flavour
1741       && (S_IS_EXTERNAL (fixp->fx_addsy) || S_IS_WEAK (fixp->fx_addsy)))
1742     return 0;
1743 
1744   if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
1745       || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1746     return 0;
1747 
1748   /* Preserve relocations against symbols with function type.  */
1749   if (symbol_get_bfdsym (fixp->fx_addsy)->flags & BSF_FUNCTION)
1750     return 0;
1751 
1752   return 1;
1753 }
1754 
1755 /* The function tc_gen_reloc creates a relocation structure for the
1756    fixup fixp, and returns a pointer to it.  This structure is passed
1757    to bfd_install_relocation so that it can be written to the object
1758    file for linking.  */
1759 arelent *
tc_gen_reloc(asection * section ATTRIBUTE_UNUSED,fixS * fixp)1760 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
1761 {
1762   arelent *reloc = XNEW (arelent);
1763   reloc->sym_ptr_ptr = XNEW (asymbol *);
1764   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
1765 
1766   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
1767   reloc->addend = fixp->fx_offset;  /* fixp->fx_addnumber; */
1768 
1769   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
1770   if (reloc->howto == NULL)
1771     {
1772       as_bad_where (fixp->fx_file, fixp->fx_line,
1773 		    _("can't represent relocation type %s"),
1774 		    bfd_get_reloc_code_name (fixp->fx_r_type));
1775 
1776       /* Set howto to a garbage value so that we can keep going.  */
1777       reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_32);
1778       gas_assert (reloc->howto != NULL);
1779     }
1780   return reloc;
1781 }
1782 
1783 long
md_pcrel_from(fixS * fixP ATTRIBUTE_UNUSED)1784 md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
1785 {
1786   return fixP->fx_where + fixP->fx_frag->fr_address;
1787 }
1788 
1789 /* Called just before the assembler exits.  */
1790 void
md_end(void)1791 md_end (void)
1792 {
1793   htab_delete (pru_opcode_hash);
1794   htab_delete (pru_reg_hash);
1795 }
1796 
1797 symbolS *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)1798 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1799 {
1800   return NULL;
1801 }
1802 
1803 /* Implement tc_frob_label.  */
1804 void
pru_frob_label(symbolS * lab)1805 pru_frob_label (symbolS *lab)
1806 {
1807   /* Emit dwarf information.  */
1808   dwarf2_emit_label (lab);
1809 
1810   /* Update the label's address with the current output pointer.  */
1811   symbol_set_frag (lab, frag_now);
1812   S_SET_VALUE (lab, (valueT) frag_now_fix ());
1813 
1814   /* Record this label for future adjustment after we find out what
1815      kind of data it references, and the required alignment therewith.  */
1816   pru_last_label = lab;
1817 
1818   if (pru_opt.warn_regname_label && pru_reg_lookup (S_GET_NAME (lab)))
1819     as_warn (_("Label \"%s\" matches a CPU register name"), S_GET_NAME (lab));
1820 }
1821 
1822 static inline char *
skip_space(char * s)1823 skip_space (char *s)
1824 {
1825   while (*s == ' ' || *s == '\t')
1826     ++s;
1827   return s;
1828 }
1829 
1830 /* Parse special CONS expression: pmem (expression).  Idea from AVR.
1831 
1832    Used to catch and mark code (program memory) in constant expression
1833    relocations.  Return non-zero for program memory.  */
1834 
1835 int
pru_parse_cons_expression(expressionS * exp,int nbytes)1836 pru_parse_cons_expression (expressionS *exp, int nbytes)
1837 {
1838   int is_pmem = false;
1839   char *tmp;
1840 
1841   tmp = input_line_pointer = skip_space (input_line_pointer);
1842 
1843   if (nbytes == 4 || nbytes == 2)
1844     {
1845       const char *pmem_str = "%pmem";
1846       int len = strlen (pmem_str);
1847 
1848       if (strncasecmp (input_line_pointer, pmem_str, len) == 0)
1849 	{
1850 	  input_line_pointer = skip_space (input_line_pointer + len);
1851 
1852 	  if (*input_line_pointer == '(')
1853 	    {
1854 	      input_line_pointer = skip_space (input_line_pointer + 1);
1855 	      is_pmem = true;
1856 	      expression (exp);
1857 
1858 	      if (*input_line_pointer == ')')
1859 		++input_line_pointer;
1860 	      else
1861 		{
1862 		  as_bad (_("`)' required"));
1863 		  is_pmem = false;
1864 		}
1865 
1866 	      return is_pmem;
1867 	    }
1868 
1869 	  input_line_pointer = tmp;
1870 	}
1871     }
1872 
1873   expression (exp);
1874 
1875   return is_pmem;
1876 }
1877 
1878 /* Implement TC_CONS_FIX_NEW.  */
1879 void
pru_cons_fix_new(fragS * frag,int where,unsigned int nbytes,expressionS * exp,const int is_pmem)1880 pru_cons_fix_new (fragS *frag, int where, unsigned int nbytes,
1881 		    expressionS *exp, const int is_pmem)
1882 {
1883   bfd_reloc_code_real_type r;
1884 
1885   switch (nbytes | (!!is_pmem << 8))
1886     {
1887     case 1 | (0 << 8): r = BFD_RELOC_8; break;
1888     case 2 | (0 << 8): r = BFD_RELOC_16; break;
1889     case 4 | (0 << 8): r = BFD_RELOC_32; break;
1890     case 8 | (0 << 8): r = BFD_RELOC_64; break;
1891     case 2 | (1 << 8): r = BFD_RELOC_PRU_16_PMEM; break;
1892     case 4 | (1 << 8): r = BFD_RELOC_PRU_32_PMEM; break;
1893     default:
1894       as_bad (_("illegal %s relocation size: %d"),
1895 	      is_pmem ? "text" : "data", nbytes);
1896       return;
1897     }
1898 
1899   fix_new_exp (frag, where, (int) nbytes, exp, 0, r);
1900 }
1901 
1902 /* Implement tc_regname_to_dw2regnum, to convert REGNAME to a DWARF-2
1903    register number.  Return the starting HW byte-register number.  */
1904 
1905 int
pru_regname_to_dw2regnum(char * regname)1906 pru_regname_to_dw2regnum (char *regname)
1907 {
1908   static const unsigned int regstart[RSEL_NUM_ITEMS] =
1909     {
1910      [RSEL_7_0]	  = 0,
1911      [RSEL_15_8]  = 1,
1912      [RSEL_23_16] = 2,
1913      [RSEL_31_24] = 3,
1914      [RSEL_15_0]  = 0,
1915      [RSEL_23_8]  = 1,
1916      [RSEL_31_16] = 2,
1917      [RSEL_31_0]  = 0,
1918     };
1919 
1920   struct pru_reg *r = pru_reg_lookup (regname);
1921 
1922   if (r == NULL || r->regsel >= RSEL_NUM_ITEMS)
1923     return -1;
1924   return r->index * 4 + regstart[r->regsel];
1925 }
1926 
1927 /* Implement tc_cfi_frame_initial_instructions, to initialize the DWARF-2
1928    unwind information for this procedure.  */
1929 void
pru_frame_initial_instructions(void)1930 pru_frame_initial_instructions (void)
1931 {
1932   const unsigned fp_regno = 4 * 4;
1933   cfi_add_CFA_def_cfa (fp_regno, 0);
1934 }
1935 
1936 bool
pru_allow_local_subtract(expressionS * left,expressionS * right,segT section)1937 pru_allow_local_subtract (expressionS * left,
1938 			     expressionS * right,
1939 			     segT section)
1940 {
1941   /* If we are not in relaxation mode, subtraction is OK.  */
1942   if (!linkrelax)
1943     return true;
1944 
1945   /* If the symbols are not in a code section then they are OK.  */
1946   if ((section->flags & SEC_CODE) == 0)
1947     return true;
1948 
1949   if (left->X_add_symbol == right->X_add_symbol)
1950     return true;
1951 
1952   /* We have to assume that there may be instructions between the
1953      two symbols and that relaxation may increase the distance between
1954      them.  */
1955   return false;
1956 }
1957