xref: /netbsd-src/external/gpl3/binutils.old/dist/gas/config/tc-tic54x.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
1 /* tc-tic54x.c -- Assembly code for the Texas Instruments TMS320C54X
2    Copyright (C) 1999-2022 Free Software Foundation, Inc.
3    Contributed by Timothy Wall (twall@cygnus.com)
4 
5    This file is part of GAS, the GNU Assembler.
6 
7    GAS is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3, or (at your option)
10    any later version.
11 
12    GAS is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with GAS; see the file COPYING.  If not, write to the Free
19    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20    02110-1301, USA.  */
21 
22 /* Texas Instruments TMS320C54X machine specific gas.
23    Written by Timothy Wall (twall@alum.mit.edu).
24 
25    Valuable things to do:
26    Pipeline conflict warnings
27    We encode/decode "ld #_label, dp" differently in relocatable files
28      This means we're not compatible with TI output containing those
29      expressions.  We store the upper nine bits; TI stores the lower nine
30      bits.  How they recover the original upper nine bits is beyond me.
31 
32    Tests to add to expect testsuite:
33      '=' and '==' with .if, .elseif, and .break
34 
35    Incompatibilities (mostly trivial):
36    We don't allow '''
37    We fill text section with zeroes instead of "nop"s
38    We don't convert '' or "" to a single instance
39    We don't convert '' to '\0'
40    We don't allow strings with .byte/.half/.short/.long
41    Probably details of the subsym stuff are different
42    TI sets labels to be data type 4 (T_INT); GAS uses T_NULL.
43 
44    COFF1 limits section names to 8 characters.
45    Some of the default behavior changed from COFF1 to COFF2.  */
46 
47 #include "as.h"
48 #include <limits.h>
49 #include "safe-ctype.h"
50 #include "sb.h"
51 #include "macro.h"
52 #include "subsegs.h"
53 #include "opcode/tic54x.h"
54 #include "obj-coff.h"
55 #include <math.h>
56 
57 
58 static struct stag
59 {
60   symbolS *sym;		        /* Symbol for this stag; value is offset.  */
61   const char *name;		/* Shortcut to symbol name.  */
62   bfd_vma size;		        /* Size of struct/union.  */
63   int current_bitfield_offset;  /* Temporary for tracking fields.  */
64   int is_union;
65   struct stag_field		/* List of fields.  */
66   {
67     const char *name;
68     bfd_vma offset;		/* Of start of this field.  */
69     int bitfield_offset;	/* Of start of this field.  */
70     struct stag *stag;	        /* If field is struct/union.  */
71     struct stag_field *next;
72   } *field;
73   /* For nesting; used only in stag construction.  */
74   struct stag *inner;	        /* Enclosed .struct.  */
75   struct stag *outer;	        /* Enclosing .struct.  */
76 } *current_stag = NULL;
77 
78 #define MAX_LINE 256 /* Lines longer than this are truncated by TI's asm.  */
79 
80 typedef struct _tic54x_insn
81 {
82   const insn_template *tm;	/* Opcode template.  */
83 
84   char mnemonic[MAX_LINE];	/* Opcode name/mnemonic.  */
85   char parmnemonic[MAX_LINE];   /* 2nd mnemonic of parallel insn.  */
86 
87   int opcount;
88   struct opstruct
89   {
90     char buf[MAX_LINE];
91     enum optype type;
92     expressionS exp;
93   } operands[MAX_OPERANDS];
94 
95   int paropcount;
96   struct opstruct paroperands[MAX_OPERANDS];
97 
98   int is_lkaddr;
99   int lkoperand;
100   int words;			/* Size of insn in 16-bit words.  */
101   int using_default_dst;	/* Do we need to explicitly set an
102 				   omitted OP_DST operand?  */
103   struct
104   {
105     unsigned short word;	     /* Final encoded opcode data.  */
106     int unresolved;
107     int r_nchars;		     /* Relocation size.  */
108     bfd_reloc_code_real_type r_type; /* Relocation type.  */
109     expressionS addr_expr;	     /* Storage for unresolved expressions.  */
110   } opcode[3];
111 } tic54x_insn;
112 
113 enum cpu_version
114 {
115   VNONE = 0, V541 = 1, V542 = 2, V543 = 3, V545 = 5, V548 = 8, V549 = 9,
116   V545LP = 15, V546LP = 16
117 };
118 
119 enum address_mode
120 {
121   c_mode,   /* 16-bit addresses.  */
122   far_mode  /* >16-bit addresses.  */
123 };
124 
125 static segT stag_saved_seg;
126 static subsegT stag_saved_subseg;
127 
128 const char comment_chars[] = ";";
129 const char line_comment_chars[] = ";*#"; /* At column zero only.  */
130 const char line_separator_chars[] = ""; /* Not permitted.  */
131 
132 int emitting_long = 0;
133 
134 /* Characters which indicate that this is a floating point constant.  */
135 const char FLT_CHARS[] = "fF";
136 
137 /* Characters that can be used to separate mantissa from exp in FP
138    nums.  */
139 const char EXP_CHARS[] = "eE";
140 
141 const char *md_shortopts = "";
142 
143 #define OPTION_ADDRESS_MODE     (OPTION_MD_BASE)
144 #define OPTION_CPU_VERSION      (OPTION_ADDRESS_MODE + 1)
145 #define OPTION_COFF_VERSION     (OPTION_CPU_VERSION + 1)
146 #define OPTION_STDERR_TO_FILE   (OPTION_COFF_VERSION + 1)
147 
148 struct option md_longopts[] =
149 {
150   { "mfar-mode",       no_argument,	    NULL, OPTION_ADDRESS_MODE },
151   { "mf",	       no_argument,	    NULL, OPTION_ADDRESS_MODE },
152   { "mcpu",	       required_argument,   NULL, OPTION_CPU_VERSION },
153   { "merrors-to-file", required_argument,   NULL, OPTION_STDERR_TO_FILE },
154   { "me",	       required_argument,   NULL, OPTION_STDERR_TO_FILE },
155   { NULL,              no_argument,         NULL, 0},
156 };
157 
158 size_t md_longopts_size = sizeof (md_longopts);
159 
160 static int assembly_begun = 0;
161 /* Addressing mode is not entirely implemented; the latest rev of the Other
162    assembler doesn't seem to make any distinction whatsoever; all relocations
163    are stored as extended relocations.  Older versions used REL16 vs RELEXT16,
164    but now it seems all relocations are RELEXT16.  We use all RELEXT16.
165 
166    The cpu version is kind of a waste of time as well.  There is one
167    instruction (RND) for LP devices only, and several for devices with
168    extended addressing only.  We include it for compatibility.  */
169 static enum address_mode amode = c_mode;
170 static enum cpu_version cpu = VNONE;
171 
172 /* Include string substitutions in listing?  */
173 static int listing_sslist = 0;
174 
175 /* Did we do subsym substitutions on the line?  */
176 static int substitution_line = 0;
177 
178 /* Last label seen.  */
179 static symbolS *last_label_seen = NULL;
180 
181 /* This ensures that all new labels are unique.  */
182 static int local_label_id;
183 
184 static htab_t subsym_recurse_hash; /* Prevent infinite recurse.  */
185 static htab_t math_hash; /* Built-in math functions.  */
186 /* Allow maximum levels of macro nesting; level 0 is the main substitution
187    symbol table.  The other assembler only does 32 levels, so there!  */
188 #define MAX_SUBSYM_HASH 100
189 static htab_t subsym_hash[MAX_SUBSYM_HASH];
190 
191 /* Keep track of local labels so we can substitute them before GAS sees them
192    since macros use their own 'namespace' for local labels, use a separate hash
193 
194    We do our own local label handling 'cuz it's subtly different from the
195    stock GAS handling.
196 
197    We use our own macro nesting counter, since GAS overloads it when expanding
198    other things (like conditionals and repeat loops).  */
199 static int macro_level = 0;
200 static htab_t local_label_hash[100];
201 /* Keep track of struct/union tags.  */
202 static htab_t stag_hash;
203 static htab_t op_hash;
204 static htab_t parop_hash;
205 static htab_t reg_hash;
206 static htab_t mmreg_hash;
207 static htab_t cc_hash;
208 static htab_t cc2_hash;
209 static htab_t cc3_hash;
210 static htab_t sbit_hash;
211 static htab_t misc_symbol_hash;
212 
213 /* Only word (et al.), align, or conditionals are allowed within
214    .struct/.union.  */
215 #define ILLEGAL_WITHIN_STRUCT()					\
216   do								\
217     if (current_stag != NULL)					\
218       { 							\
219 	as_bad (_("pseudo-op illegal within .struct/.union"));	\
220 	return;							\
221       }								\
222   while (0)
223 
224 
225 static void subsym_create_or_replace (char *, char *);
226 static char *subsym_lookup (char *, int);
227 static char *subsym_substitute (char *, int);
228 
229 
230 void
md_show_usage(FILE * stream)231 md_show_usage (FILE *stream)
232 {
233   fprintf (stream, _("C54x-specific command line options:\n"));
234   fprintf (stream, _("-mfar-mode | -mf          Use extended addressing\n"));
235   fprintf (stream, _("-mcpu=<CPU version>       Specify the CPU version\n"));
236   fprintf (stream, _("-merrors-to-file <filename>\n"));
237   fprintf (stream, _("-me <filename>            Redirect errors to a file\n"));
238 }
239 
240 /* Output a single character (upper octet is zero).  */
241 
242 static void
tic54x_emit_char(char c)243 tic54x_emit_char (char c)
244 {
245   expressionS expn;
246 
247   expn.X_op = O_constant;
248   expn.X_add_number = c;
249   emit_expr (&expn, 2);
250 }
251 
252 /* Walk backwards in the frag chain.  */
253 
254 static fragS *
frag_prev(fragS * frag,segT seg)255 frag_prev (fragS *frag, segT seg)
256 {
257   segment_info_type *seginfo = seg_info (seg);
258   fragS *fragp;
259 
260   for (fragp = seginfo->frchainP->frch_root; fragp; fragp = fragp->fr_next)
261     if (fragp->fr_next == frag)
262       return fragp;
263 
264   return NULL;
265 }
266 
267 static fragS *
bit_offset_frag(fragS * frag,segT seg)268 bit_offset_frag (fragS *frag, segT seg)
269 {
270   while (frag != NULL)
271     {
272       if (frag->fr_fix == 0
273 	  && frag->fr_opcode == NULL
274 	  && frag->tc_frag_data == 0)
275 	frag = frag_prev (frag, seg);
276       else
277 	return frag;
278     }
279   return NULL;
280 }
281 
282 /* Return the number of bits allocated in the most recent word, or zero if
283    none. .field/.space/.bes may leave words partially allocated.  */
284 
285 static int
frag_bit_offset(fragS * frag,segT seg)286 frag_bit_offset (fragS *frag, segT seg)
287 {
288   frag = bit_offset_frag (frag, seg);
289 
290   if (frag)
291     return frag->fr_opcode != NULL ? -1 : frag->tc_frag_data;
292 
293   return 0;
294 }
295 
296 /* Read an expression from a C string; returns a pointer past the end of the
297    expression.  */
298 
299 static char *
parse_expression(char * str,expressionS * expn)300 parse_expression (char *str, expressionS *expn)
301 {
302   char *s;
303   char *tmp;
304 
305   tmp = input_line_pointer;	/* Save line pointer.  */
306   input_line_pointer = str;
307   expression (expn);
308   s = input_line_pointer;
309   input_line_pointer = tmp;	/* Restore line pointer.  */
310   return s;			/* Return pointer to where parsing stopped.  */
311 }
312 
313 /* .asg "character-string"|character-string, symbol
314 
315    .eval is the only pseudo-op allowed to perform arithmetic on substitution
316    symbols.  all other use of symbols defined with .asg are currently
317    unsupported.  */
318 
319 static void
tic54x_asg(int x ATTRIBUTE_UNUSED)320 tic54x_asg (int x ATTRIBUTE_UNUSED)
321 {
322   int c;
323   char *name;
324   char *str;
325   int quoted = *input_line_pointer == '"';
326 
327   ILLEGAL_WITHIN_STRUCT ();
328 
329   if (quoted)
330     {
331       int len;
332       str = demand_copy_C_string (&len);
333       c = *input_line_pointer;
334     }
335   else
336     {
337       str = input_line_pointer;
338       while ((c = *input_line_pointer) != ',')
339 	{
340 	  if (is_end_of_line[(unsigned char) c])
341 	    break;
342 	  ++input_line_pointer;
343 	}
344       *input_line_pointer = 0;
345     }
346   if (c != ',')
347     {
348       as_bad (_("Comma and symbol expected for '.asg STRING, SYMBOL'"));
349       ignore_rest_of_line ();
350       return;
351     }
352 
353   ++input_line_pointer;
354   c = get_symbol_name (&name);	/* Get terminator.  */
355   if (!ISALPHA (*name))
356     {
357       as_bad (_("symbols assigned with .asg must begin with a letter"));
358       ignore_rest_of_line ();
359       return;
360     }
361 
362   str = xstrdup (str);
363   name = xstrdup (name);
364   subsym_create_or_replace (name, str);
365   (void) restore_line_pointer (c);
366   demand_empty_rest_of_line ();
367 }
368 
369 /* .eval expression, symbol
370    There's something screwy about this.  The other assembler sometimes does and
371    sometimes doesn't substitute symbols defined with .eval.
372    We'll put the symbols into the subsym table as well as the normal symbol
373    table, since that's what works best.  */
374 
375 static void
tic54x_eval(int x ATTRIBUTE_UNUSED)376 tic54x_eval (int x ATTRIBUTE_UNUSED)
377 {
378   char c;
379   int value;
380   char *name;
381   symbolS *symbolP;
382   char valuestr[32], *tmp;
383   int quoted;
384 
385   ILLEGAL_WITHIN_STRUCT ();
386 
387   SKIP_WHITESPACE ();
388 
389   quoted = *input_line_pointer == '"';
390   if (quoted)
391     ++input_line_pointer;
392   value = get_absolute_expression ();
393   if (quoted)
394     {
395       if (*input_line_pointer != '"')
396 	{
397 	  as_bad (_("Unterminated string after absolute expression"));
398 	  ignore_rest_of_line ();
399 	  return;
400 	}
401       ++input_line_pointer;
402     }
403   if (*input_line_pointer++ != ',')
404     {
405       as_bad (_("Comma and symbol expected for '.eval EXPR, SYMBOL'"));
406       ignore_rest_of_line ();
407       return;
408     }
409   c = get_symbol_name (&name);	/* Get terminator.  */
410   name = xstrdup (name);
411   (void) restore_line_pointer (c);
412 
413   if (!ISALPHA (*name))
414     {
415       as_bad (_("symbols assigned with .eval must begin with a letter"));
416       ignore_rest_of_line ();
417       return;
418     }
419   symbolP = symbol_new (name, absolute_section, &zero_address_frag, value);
420   SF_SET_LOCAL (symbolP);
421   symbol_table_insert (symbolP);
422 
423   /* The "other" assembler sometimes doesn't put .eval's in the subsym table
424      But since there's not written rule as to when, don't even bother trying
425      to match their behavior.  */
426   sprintf (valuestr, "%d", value);
427   tmp = xstrdup (valuestr);
428   subsym_create_or_replace (name, tmp);
429 
430   demand_empty_rest_of_line ();
431 }
432 
433 /* .bss symbol, size [, [blocking flag] [, alignment flag]
434 
435    alignment is to a longword boundary; blocking is to 128-word boundary.
436 
437    1) if there is a hole in memory, this directive should attempt to fill it
438       (not yet implemented).
439 
440    2) if the blocking flag is not set, allocate at the current SPC
441       otherwise, check to see if the current SPC plus the space to be
442       allocated crosses the page boundary (128 words).
443       if there's not enough space, create a hole and align with the next page
444       boundary.
445       (not yet implemented).  */
446 
447 static void
tic54x_bss(int x ATTRIBUTE_UNUSED)448 tic54x_bss (int x ATTRIBUTE_UNUSED)
449 {
450   char c;
451   char *name;
452   char *p;
453   int words;
454   segT current_seg;
455   subsegT current_subseg;
456   symbolS *symbolP;
457   int block = 0;
458   int align = 0;
459 
460   ILLEGAL_WITHIN_STRUCT ();
461 
462   current_seg = now_seg;	/* Save current seg.  */
463   current_subseg = now_subseg;	/* Save current subseg.  */
464 
465   c = get_symbol_name (&name);	/* Get terminator.  */
466   if (c == '"')
467     c = * ++ input_line_pointer;
468   if (c != ',')
469     {
470       as_bad (_(".bss size argument missing\n"));
471       ignore_rest_of_line ();
472       return;
473     }
474 
475   ++input_line_pointer;
476   words = get_absolute_expression ();
477   if (words < 0)
478     {
479       as_bad (_(".bss size %d < 0!"), words);
480       ignore_rest_of_line ();
481       return;
482     }
483 
484   if (*input_line_pointer == ',')
485     {
486       /* The blocking flag may be missing.  */
487       ++input_line_pointer;
488       if (*input_line_pointer != ',')
489 	block = get_absolute_expression ();
490       else
491 	block = 0;
492 
493       if (*input_line_pointer == ',')
494 	{
495 	  ++input_line_pointer;
496 	  align = get_absolute_expression ();
497 	}
498       else
499 	align = 0;
500     }
501   else
502     block = align = 0;
503 
504   subseg_set (bss_section, 0);
505   symbolP = symbol_find_or_make (name);
506 
507   if (S_GET_SEGMENT (symbolP) == bss_section)
508     symbol_get_frag (symbolP)->fr_symbol = (symbolS *) NULL;
509 
510   symbol_set_frag (symbolP, frag_now);
511   p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
512 		(offsetT) (words * OCTETS_PER_BYTE), (char *) 0);
513   *p = 0;			/* Fill char.  */
514 
515   S_SET_SEGMENT (symbolP, bss_section);
516 
517   /* The symbol may already have been created with a preceding
518      ".globl" directive -- be careful not to step on storage class
519      in that case.  Otherwise, set it to static.  */
520   if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
521     S_SET_STORAGE_CLASS (symbolP, C_STAT);
522 
523   if (align)
524     {
525       /* s_align eats end of line; restore it */
526       s_align_bytes (4);
527       --input_line_pointer;
528     }
529 
530   if (block)
531     bss_section->flags |= SEC_TIC54X_BLOCK;
532 
533   subseg_set (current_seg, current_subseg);	/* Restore current seg.  */
534   demand_empty_rest_of_line ();
535 }
536 
537 static void
stag_add_field_symbols(struct stag * stag,const char * path,bfd_vma base_offset,symbolS * rootsym,const char * root_stag_name)538 stag_add_field_symbols (struct stag *stag,
539 			const char *path,
540 			bfd_vma base_offset,
541 			symbolS *rootsym,
542 			const char *root_stag_name)
543 {
544   char * prefix;
545   struct stag_field *field = stag->field;
546 
547   /* Construct a symbol for every field contained within this structure
548      including fields within structure fields.  */
549   prefix = concat (path, *path ? "." : "", NULL);
550 
551   while (field != NULL)
552     {
553       char *name = concat (prefix, field->name, NULL);
554       char *freename = name;
555 
556       if (rootsym == NULL)
557 	{
558 	  symbolS *sym;
559 	  sym = symbol_new (name, absolute_section, &zero_address_frag,
560 			    (field->stag ? field->offset
561 			     : base_offset + field->offset));
562 	  SF_SET_LOCAL (sym);
563 	  symbol_table_insert (sym);
564 	}
565       else
566 	{
567 	  char *replacement;
568 
569 	  replacement = concat (S_GET_NAME (rootsym), "+", root_stag_name,
570 				name + strlen (S_GET_NAME (rootsym)), NULL);
571 	  str_hash_insert (subsym_hash[0], name, replacement, 0);
572 	  freename = NULL;
573 	}
574 
575       /* Recurse if the field is a structure.
576 	 Note the field offset is relative to the outermost struct.  */
577       if (field->stag != NULL)
578 	stag_add_field_symbols (field->stag, name,
579 				field->offset,
580 				rootsym, root_stag_name);
581       field = field->next;
582       free (freename);
583     }
584   free (prefix);
585 }
586 
587 /* Keep track of stag fields so that when structures are nested we can add the
588    complete dereferencing symbols to the symbol table.  */
589 
590 static void
stag_add_field(struct stag * parent,const char * name,bfd_vma offset,struct stag * stag)591 stag_add_field (struct stag *parent,
592 		const char *name,
593 		bfd_vma offset,
594 		struct stag *stag)
595 {
596   struct stag_field *sfield = XCNEW (struct stag_field);
597 
598   sfield->name = xstrdup (name);
599   sfield->offset = offset;
600   sfield->bitfield_offset = parent->current_bitfield_offset;
601   sfield->stag = stag;
602   if (parent->field == NULL)
603     parent->field = sfield;
604   else
605     {
606       struct stag_field *sf = parent->field;
607       while (sf->next != NULL)
608 	sf = sf->next;
609       sf->next = sfield;
610     }
611   /* Only create a symbol for this field if the parent has no name.  */
612   if (startswith (parent->name, ".fake"))
613     {
614       symbolS *sym = symbol_new (name, absolute_section, &zero_address_frag,
615 				 offset);
616       SF_SET_LOCAL (sym);
617       symbol_table_insert (sym);
618     }
619 }
620 
621 /* [STAG] .struct       [OFFSET]
622    Start defining structure offsets (symbols in absolute section).  */
623 
624 static void
tic54x_struct(int arg)625 tic54x_struct (int arg)
626 {
627   int start_offset = 0;
628   int is_union = arg;
629 
630   if (!current_stag)
631     {
632       /* Starting a new struct, switch to absolute section.  */
633       stag_saved_seg = now_seg;
634       stag_saved_subseg = now_subseg;
635       subseg_set (absolute_section, 0);
636     }
637   /* Align the current pointer.  */
638   else if (current_stag->current_bitfield_offset != 0)
639     {
640       ++abs_section_offset;
641       current_stag->current_bitfield_offset = 0;
642     }
643 
644   /* Offset expression is only meaningful for global .structs.  */
645   if (!is_union)
646     {
647       /* Offset is ignored in inner structs.  */
648       SKIP_WHITESPACE ();
649       if (!is_end_of_line[(unsigned char) *input_line_pointer])
650 	start_offset = get_absolute_expression ();
651       else
652 	start_offset = 0;
653     }
654 
655   if (current_stag)
656     {
657       /* Nesting, link to outer one.  */
658       current_stag->inner = XCNEW (struct stag);
659       current_stag->inner->outer = current_stag;
660       current_stag = current_stag->inner;
661       if (start_offset)
662 	as_warn (_("Offset on nested structures is ignored"));
663       start_offset = abs_section_offset;
664     }
665   else
666     {
667       current_stag = XCNEW (struct stag);
668       abs_section_offset = start_offset;
669     }
670   current_stag->is_union = is_union;
671 
672   if (line_label == NULL)
673     {
674       static int struct_count = 0;
675       char fake[] = ".fake_stagNNNNNNN";
676       sprintf (fake, ".fake_stag%d", struct_count++);
677       current_stag->sym = symbol_new (fake, absolute_section,
678 				      &zero_address_frag,
679 				      abs_section_offset);
680     }
681   else
682     {
683       char * label = xstrdup (S_GET_NAME (line_label));
684       current_stag->sym = symbol_new (label,
685 				      absolute_section,
686 				      &zero_address_frag,
687 				      abs_section_offset);
688       free (label);
689     }
690   current_stag->name = S_GET_NAME (current_stag->sym);
691   SF_SET_LOCAL (current_stag->sym);
692   /* Nested .structs don't go into the symbol table.  */
693   if (current_stag->outer == NULL)
694     symbol_table_insert (current_stag->sym);
695 
696   line_label = NULL;
697 }
698 
699 /* [LABEL] .endstruct
700    finish defining structure offsets; optional LABEL's value will be the size
701    of the structure.  */
702 
703 static void
tic54x_endstruct(int is_union)704 tic54x_endstruct (int is_union)
705 {
706   int size;
707   const char *path =
708     startswith (current_stag->name, ".fake") ? "" : current_stag->name;
709 
710   if (!current_stag || current_stag->is_union != is_union)
711     {
712       as_bad (_(".end%s without preceding .%s"),
713 	      is_union ? "union" : "struct",
714 	      is_union ? "union" : "struct");
715       ignore_rest_of_line ();
716       return;
717     }
718 
719   /* Align end of structures.  */
720   if (current_stag->current_bitfield_offset)
721     {
722       ++abs_section_offset;
723       current_stag->current_bitfield_offset = 0;
724     }
725 
726   if (current_stag->is_union)
727     size = current_stag->size;
728   else
729     size = abs_section_offset - S_GET_VALUE (current_stag->sym);
730   if (line_label != NULL)
731     {
732       S_SET_VALUE (line_label, size);
733       symbol_table_insert (line_label);
734       line_label = NULL;
735     }
736 
737   /* Union size has already been calculated.  */
738   if (!current_stag->is_union)
739     current_stag->size = size;
740   /* Nested .structs don't get put in the stag table.  */
741   if (current_stag->outer == NULL)
742     {
743       str_hash_insert (stag_hash, current_stag->name, current_stag, 0);
744       stag_add_field_symbols (current_stag, path,
745 			      S_GET_VALUE (current_stag->sym),
746 			      NULL, NULL);
747     }
748   current_stag = current_stag->outer;
749 
750   /* If this is a nested .struct/.union, add it as a field to the enclosing
751      one.  otherwise, restore the section we were in.  */
752   if (current_stag != NULL)
753     {
754       stag_add_field (current_stag, current_stag->inner->name,
755 		      S_GET_VALUE (current_stag->inner->sym),
756 		      current_stag->inner);
757     }
758   else
759     subseg_set (stag_saved_seg, stag_saved_subseg);
760 }
761 
762 /* [LABEL]      .tag    STAG
763    Reference a structure within a structure, as a sized field with an optional
764    label.
765    If used outside of a .struct/.endstruct, overlays the given structure
766    format on the existing allocated space.  */
767 
768 static void
tic54x_tag(int ignore ATTRIBUTE_UNUSED)769 tic54x_tag (int ignore ATTRIBUTE_UNUSED)
770 {
771   char *name;
772   int c = get_symbol_name (&name);
773   struct stag *stag = (struct stag *) str_hash_find (stag_hash, name);
774 
775   if (!stag)
776     {
777       if (*name)
778 	as_bad (_("Unrecognized struct/union tag '%s'"), name);
779       else
780 	as_bad (_(".tag requires a structure tag"));
781       ignore_rest_of_line ();
782       return;
783     }
784   if (line_label == NULL)
785     {
786       as_bad (_("Label required for .tag"));
787       ignore_rest_of_line ();
788       return;
789     }
790   else
791     {
792       char * label;
793 
794       label = xstrdup (S_GET_NAME (line_label));
795       if (current_stag != NULL)
796 	stag_add_field (current_stag, label,
797 			abs_section_offset - S_GET_VALUE (current_stag->sym),
798 			stag);
799       else
800 	{
801 	  symbolS *sym = symbol_find (label);
802 
803 	  if (!sym)
804 	    {
805 	      as_bad (_(".tag target '%s' undefined"), label);
806 	      ignore_rest_of_line ();
807 	      free (label);
808 	      return;
809 	    }
810 	  stag_add_field_symbols (stag, S_GET_NAME (sym),
811 				  S_GET_VALUE (stag->sym), sym, stag->name);
812 	}
813       free (label);
814     }
815 
816   /* Bump by the struct size, but only if we're within a .struct section.  */
817   if (current_stag != NULL && !current_stag->is_union)
818     abs_section_offset += stag->size;
819 
820   (void) restore_line_pointer (c);
821   demand_empty_rest_of_line ();
822   line_label = NULL;
823 }
824 
825 /* Handle all .byte, .char, .double, .field, .float, .half, .int, .long,
826    .short, .string, .ubyte, .uchar, .uhalf, .uint, .ulong, .ushort, .uword,
827    and .word.  */
828 
829 static void
tic54x_struct_field(int type)830 tic54x_struct_field (int type)
831 {
832   int size;
833   int count = 1;
834   int new_bitfield_offset = 0;
835   int field_align = current_stag->current_bitfield_offset != 0;
836   int longword_align = 0;
837 
838   SKIP_WHITESPACE ();
839   if (!is_end_of_line[(unsigned char) *input_line_pointer])
840     count = get_absolute_expression ();
841 
842   switch (type)
843     {
844     case 'b':
845     case 'B':
846     case 'c':
847     case 'C':
848     case 'h':
849     case 'H':
850     case 'i':
851     case 'I':
852     case 's':
853     case 'S':
854     case 'w':
855     case 'W':
856     case '*': /* String.  */
857       size = 1;
858       break;
859     case 'f':
860     case 'l':
861     case 'L':
862       longword_align = 1;
863       size = 2;
864       break;
865     case '.': /* Bitfield.  */
866       size = 0;
867       if (count < 1 || count > 32)
868 	{
869 	  as_bad (_(".field count '%d' out of range (1 <= X <= 32)"), count);
870 	  ignore_rest_of_line ();
871 	  return;
872 	}
873       if (current_stag->current_bitfield_offset + count > 16)
874 	{
875 	  /* Set the appropriate size and new field offset.  */
876 	  if (count == 32)
877 	    {
878 	      size = 2;
879 	      count = 1;
880 	    }
881 	  else if (count > 16)
882 	    {
883 	      size = 1;
884 	      count = 1;
885 	      new_bitfield_offset = count - 16;
886 	    }
887 	  else
888 	    new_bitfield_offset = count;
889 	}
890       else
891 	{
892 	  field_align = 0;
893 	  new_bitfield_offset = current_stag->current_bitfield_offset + count;
894 	}
895       break;
896     default:
897       as_bad (_("Unrecognized field type '%c'"), type);
898       ignore_rest_of_line ();
899       return;
900     }
901 
902   if (field_align)
903     {
904       /* Align to the actual starting position of the field.  */
905       current_stag->current_bitfield_offset = 0;
906       ++abs_section_offset;
907     }
908   /* Align to longword boundary.  */
909   if (longword_align && (abs_section_offset & 0x1))
910     ++abs_section_offset;
911 
912   if (line_label == NULL)
913     {
914       static int fieldno = 0;
915       char fake[] = ".fake_fieldNNNNN";
916 
917       sprintf (fake, ".fake_field%d", fieldno++);
918       stag_add_field (current_stag, fake,
919 		      abs_section_offset - S_GET_VALUE (current_stag->sym),
920 		      NULL);
921     }
922   else
923     {
924       char * label;
925 
926       label = xstrdup (S_GET_NAME (line_label));
927       stag_add_field (current_stag, label,
928 		      abs_section_offset - S_GET_VALUE (current_stag->sym),
929 		      NULL);
930       free (label);
931     }
932 
933   if (current_stag->is_union)
934     {
935       /* Note we treat the element as if it were an array of COUNT.  */
936       if (current_stag->size < (unsigned) size * count)
937 	current_stag->size = size * count;
938     }
939   else
940     {
941       abs_section_offset += (unsigned) size * count;
942       current_stag->current_bitfield_offset = new_bitfield_offset;
943     }
944   line_label = NULL;
945 }
946 
947 /* Handle .byte, .word. .int, .long and all variants.  */
948 
949 static void
tic54x_cons(int type)950 tic54x_cons (int type)
951 {
952   unsigned int c;
953   int octets;
954 
955   /* If we're within a .struct construct, don't actually allocate space.  */
956   if (current_stag != NULL)
957     {
958       tic54x_struct_field (type);
959       return;
960     }
961 
962 #ifdef md_flush_pending_output
963   md_flush_pending_output ();
964 #endif
965 
966   generate_lineno_debug ();
967 
968   /* Align long words to long word boundaries (4 octets).  */
969   if (type == 'l' || type == 'L')
970     {
971       frag_align (2, 0, 2);
972       /* If there's a label, assign it to the first allocated word.  */
973       if (line_label != NULL)
974 	{
975 	  symbol_set_frag (line_label, frag_now);
976 	  S_SET_VALUE (line_label, frag_now_fix ());
977 	}
978     }
979 
980   switch (type)
981     {
982     case 'l':
983     case 'L':
984     case 'x':
985       octets = 4;
986       break;
987     case 'b':
988     case 'B':
989     case 'c':
990     case 'C':
991       octets = 1;
992       break;
993     default:
994       octets = 2;
995       break;
996     }
997 
998   do
999     {
1000       if (*input_line_pointer == '"')
1001 	{
1002 	  input_line_pointer++;
1003 	  while (is_a_char (c = next_char_of_string ()))
1004 	    tic54x_emit_char (c);
1005 	  know (input_line_pointer[-1] == '\"');
1006 	}
1007       else
1008 	{
1009 	  expressionS expn;
1010 
1011 	  input_line_pointer = parse_expression (input_line_pointer, &expn);
1012 	  if (expn.X_op == O_constant)
1013 	    {
1014 	      offsetT value = expn.X_add_number;
1015 	      /* Truncate overflows.  */
1016 	      switch (octets)
1017 		{
1018 		case 1:
1019 		  if ((value > 0 && value > 0xFF)
1020 		      || (value < 0 && value < - 0x100))
1021 		    as_warn (_("Overflow in expression, truncated to 8 bits"));
1022 		  break;
1023 		case 2:
1024 		  if ((value > 0 && value > 0xFFFF)
1025 		      || (value < 0 && value < - 0x10000))
1026 		    as_warn (_("Overflow in expression, truncated to 16 bits"));
1027 		  break;
1028 		}
1029 	    }
1030 	  if (expn.X_op != O_constant && octets < 2)
1031 	    {
1032 	      /* Disallow .byte with a non constant expression that will
1033 		 require relocation.  */
1034 	      as_bad (_("Relocatable values require at least WORD storage"));
1035 	      ignore_rest_of_line ();
1036 	      return;
1037 	    }
1038 
1039 	  if (expn.X_op != O_constant
1040 	      && amode == c_mode
1041 	      && octets == 4)
1042 	    {
1043 	      /* FIXME -- at one point TI tools used to output REL16
1044 		 relocations, but I don't think the latest tools do at all
1045 		 The current tools output extended relocations regardless of
1046 		 the addressing mode (I actually think that ".c_mode" is
1047 		 totally ignored in the latest tools).  */
1048 	      amode = far_mode;
1049 	      emitting_long = 1;
1050 	      emit_expr (&expn, 4);
1051 	      emitting_long = 0;
1052 	      amode = c_mode;
1053 	    }
1054 	  else
1055 	    {
1056 	      emitting_long = octets == 4;
1057 	      emit_expr (&expn, (octets == 1) ? 2 : octets);
1058 	      emitting_long = 0;
1059 	    }
1060 	}
1061     }
1062   while (*input_line_pointer++ == ',');
1063 
1064   input_line_pointer--;		/* Put terminator back into stream.  */
1065   demand_empty_rest_of_line ();
1066 }
1067 
1068 /* .global <symbol>[,...,<symbolN>]
1069    .def    <symbol>[,...,<symbolN>]
1070    .ref    <symbol>[,...,<symbolN>]
1071 
1072    These all identify global symbols.
1073 
1074    .def means the symbol is defined in the current module and can be accessed
1075    by other files.  The symbol should be placed in the symbol table.
1076 
1077    .ref means the symbol is used in the current module but defined in another
1078    module.  The linker is to resolve this symbol's definition at link time.
1079 
1080    .global should act as a .ref or .def, as needed.
1081 
1082    global, def and ref all have symbol storage classes of C_EXT.
1083 
1084    I can't identify any difference in how the "other" c54x assembler treats
1085    these, so we ignore the type here.  */
1086 
1087 void
tic54x_global(int type)1088 tic54x_global (int type)
1089 {
1090   char *name;
1091   int c;
1092   symbolS *symbolP;
1093 
1094   if (type == 'r')
1095     as_warn (_("Use of .def/.ref is deprecated.  Use .global instead"));
1096 
1097   ILLEGAL_WITHIN_STRUCT ();
1098 
1099   do
1100     {
1101       c = get_symbol_name (&name);
1102       symbolP = symbol_find_or_make (name);
1103       c = restore_line_pointer (c);
1104 
1105       S_SET_STORAGE_CLASS (symbolP, C_EXT);
1106       if (c == ',')
1107 	{
1108 	  input_line_pointer++;
1109 	  if (is_end_of_line[(unsigned char) *input_line_pointer])
1110 	    c = *input_line_pointer;
1111 	}
1112     }
1113   while (c == ',');
1114 
1115   demand_empty_rest_of_line ();
1116 }
1117 
1118 /* Remove the symbol from the local label hash lookup.  */
1119 
1120 static int
tic54x_remove_local_label(void ** slot,void * arg ATTRIBUTE_UNUSED)1121 tic54x_remove_local_label (void **slot, void *arg ATTRIBUTE_UNUSED)
1122 {
1123   string_tuple_t *tuple = *((string_tuple_t **) slot);
1124   void *elem = str_hash_find (local_label_hash[macro_level], tuple->key);
1125   str_hash_delete (local_label_hash[macro_level], tuple->key);
1126   free (elem);
1127   return 0;
1128 }
1129 
1130 /* Reset all local labels.  */
1131 
1132 static void
tic54x_clear_local_labels(int ignored ATTRIBUTE_UNUSED)1133 tic54x_clear_local_labels (int ignored ATTRIBUTE_UNUSED)
1134 {
1135   htab_traverse (local_label_hash[macro_level], tic54x_remove_local_label, NULL);
1136 }
1137 
1138 /* .text
1139    .data
1140    .sect "section name"
1141 
1142    Initialized section
1143    make sure local labels get cleared when changing sections
1144 
1145    ARG is 't' for text, 'd' for data, or '*' for a named section
1146 
1147    For compatibility, '*' sections are SEC_CODE if instructions are
1148    encountered, or SEC_DATA if not.
1149 */
1150 
1151 static void
tic54x_sect(int arg)1152 tic54x_sect (int arg)
1153 {
1154   ILLEGAL_WITHIN_STRUCT ();
1155 
1156   /* Local labels are cleared when changing sections.  */
1157   tic54x_clear_local_labels (0);
1158 
1159   if (arg == 't')
1160     s_text (0);
1161   else if (arg == 'd')
1162     s_data (0);
1163   else
1164     {
1165       char *name = NULL;
1166       int len;
1167       /* Make sure all named initialized sections flagged properly.  If we
1168          encounter instructions, we'll flag it with SEC_CODE as well.  */
1169       const char *flags = ",\"w\"\n";
1170 
1171       /* If there are quotes, remove them.  */
1172       if (*input_line_pointer == '"')
1173 	{
1174 	  name = demand_copy_C_string (&len);
1175 	  demand_empty_rest_of_line ();
1176 	  name = concat (name, flags, (char *) NULL);
1177 	}
1178       else
1179 	{
1180 	  int c;
1181 
1182 	  c = get_symbol_name (&name);
1183 	  name = concat (name, flags, (char *) NULL);
1184 	  (void) restore_line_pointer (c);
1185 	  demand_empty_rest_of_line ();
1186 	}
1187 
1188       input_scrub_insert_line (name);
1189       obj_coff_section (0);
1190 
1191       /* If there was a line label, make sure that it gets assigned the proper
1192 	 section.  This is for compatibility, even though the actual behavior
1193 	 is not explicitly defined.  For consistency, we make .sect behave
1194 	 like .usect, since that is probably what people expect.  */
1195       if (line_label != NULL)
1196 	{
1197 	  S_SET_SEGMENT (line_label, now_seg);
1198 	  symbol_set_frag (line_label, frag_now);
1199 	  S_SET_VALUE (line_label, frag_now_fix ());
1200 	  if (S_GET_STORAGE_CLASS (line_label) != C_EXT)
1201 	    S_SET_STORAGE_CLASS (line_label, C_LABEL);
1202 	}
1203     }
1204 }
1205 
1206 /* [symbol] .space space_in_bits
1207    [symbol] .bes space_in_bits
1208    BES puts the symbol at the *last* word allocated
1209 
1210    cribbed from s_space.  */
1211 
1212 static void
tic54x_space(int arg)1213 tic54x_space (int arg)
1214 {
1215   expressionS expn;
1216   char *p = 0;
1217   int octets = 0;
1218   long words;
1219   int bits_per_byte = (OCTETS_PER_BYTE * 8);
1220   int bit_offset = 0;
1221   symbolS *label = line_label;
1222   int bes = arg;
1223 
1224   ILLEGAL_WITHIN_STRUCT ();
1225 
1226 #ifdef md_flush_pending_output
1227   md_flush_pending_output ();
1228 #endif
1229 
1230   /* Read the bit count.  */
1231   expression (&expn);
1232 
1233   /* Some expressions are unresolvable until later in the assembly pass;
1234      postpone until relaxation/fixup.  we also have to postpone if a previous
1235      partial allocation has not been completed yet.  */
1236   if (expn.X_op != O_constant || frag_bit_offset (frag_now, now_seg) == -1)
1237     {
1238       struct bit_info *bi = XNEW (struct bit_info);
1239 
1240       bi->seg = now_seg;
1241       bi->type = bes;
1242       bi->sym = label;
1243       p = frag_var (rs_machine_dependent,
1244 		    65536 * 2, 1, (relax_substateT) 0,
1245 		    make_expr_symbol (&expn), (offsetT) 0,
1246 		    (char *) bi);
1247       if (p)
1248 	*p = 0;
1249 
1250       return;
1251     }
1252 
1253   /* Reduce the required size by any bit offsets currently left over
1254      from a previous .space/.bes/.field directive.  */
1255   bit_offset = frag_now->tc_frag_data;
1256   if (bit_offset != 0 && bit_offset < 16)
1257     {
1258       int spare_bits = bits_per_byte - bit_offset;
1259 
1260       if (spare_bits >= expn.X_add_number)
1261 	{
1262 	  /* Don't have to do anything; sufficient bits have already been
1263 	     allocated; just point the label to the right place.  */
1264 	  if (label != NULL)
1265 	    {
1266 	      symbol_set_frag (label, frag_now);
1267 	      S_SET_VALUE (label, frag_now_fix () - 1);
1268 	      label = NULL;
1269 	    }
1270 	  frag_now->tc_frag_data += expn.X_add_number;
1271 	  goto getout;
1272 	}
1273       expn.X_add_number -= spare_bits;
1274       /* Set the label to point to the first word allocated, which in this
1275 	 case is the previous word, which was only partially filled.  */
1276       if (!bes && label != NULL)
1277 	{
1278 	  symbol_set_frag (label, frag_now);
1279 	  S_SET_VALUE (label, frag_now_fix () - 1);
1280 	  label = NULL;
1281 	}
1282     }
1283   /* Convert bits to bytes/words and octets, rounding up.  */
1284   words = ((expn.X_add_number + bits_per_byte - 1) / bits_per_byte);
1285   /* How many do we have left over?  */
1286   bit_offset = expn.X_add_number % bits_per_byte;
1287   octets = words * OCTETS_PER_BYTE;
1288   if (octets < 0)
1289     {
1290       as_warn (_(".space/.bes repeat count is negative, ignored"));
1291       goto getout;
1292     }
1293   else if (octets == 0)
1294     {
1295       as_warn (_(".space/.bes repeat count is zero, ignored"));
1296       goto getout;
1297     }
1298 
1299   /* If we are in the absolute section, just bump the offset.  */
1300   if (now_seg == absolute_section)
1301     {
1302       abs_section_offset += words;
1303       if (bes && label != NULL)
1304 	S_SET_VALUE (label, abs_section_offset - 1);
1305       frag_now->tc_frag_data = bit_offset;
1306       goto getout;
1307     }
1308 
1309   if (!need_pass_2)
1310     p = frag_var (rs_fill, 1, 1,
1311 		  (relax_substateT) 0, (symbolS *) 0,
1312 		  (offsetT) octets, (char *) 0);
1313 
1314   /* Make note of how many bits of this word we've allocated so far.  */
1315   frag_now->tc_frag_data = bit_offset;
1316 
1317   /* .bes puts label at *last* word allocated.  */
1318   if (bes && label != NULL)
1319     {
1320       symbol_set_frag (label, frag_now);
1321       S_SET_VALUE (label, frag_now_fix () - 1);
1322     }
1323 
1324   if (p)
1325     *p = 0;
1326 
1327  getout:
1328 
1329   demand_empty_rest_of_line ();
1330 }
1331 
1332 /* [symbol] .usect "section-name", size-in-words
1333 		   [, [blocking-flag] [, alignment-flag]]
1334 
1335    Uninitialized section.
1336    Non-zero blocking means that if the section would cross a page (128-word)
1337    boundary, it will be page-aligned.
1338    Non-zero alignment aligns on a longword boundary.
1339 
1340    Has no effect on the current section.  */
1341 
1342 static void
tic54x_usect(int x ATTRIBUTE_UNUSED)1343 tic54x_usect (int x ATTRIBUTE_UNUSED)
1344 {
1345   char c;
1346   char *name;
1347   char *section_name;
1348   char *p;
1349   segT seg;
1350   int size, blocking_flag, alignment_flag;
1351   segT current_seg;
1352   subsegT current_subseg;
1353   flagword flags;
1354 
1355   ILLEGAL_WITHIN_STRUCT ();
1356 
1357   current_seg = now_seg;	/* Save current seg.  */
1358   current_subseg = now_subseg;	/* Save current subseg.  */
1359 
1360   c = get_symbol_name (&section_name);	/* Get terminator.  */
1361   name = xstrdup (section_name);
1362   c = restore_line_pointer (c);
1363 
1364   if (c == ',')
1365     ++input_line_pointer;
1366   else
1367     {
1368       as_bad (_("Missing size argument"));
1369       ignore_rest_of_line ();
1370       return;
1371     }
1372 
1373   size = get_absolute_expression ();
1374 
1375   /* Read a possibly present third argument (blocking flag).  */
1376   if (*input_line_pointer == ',')
1377     {
1378       ++input_line_pointer;
1379       if (*input_line_pointer != ',')
1380 	blocking_flag = get_absolute_expression ();
1381       else
1382 	blocking_flag = 0;
1383 
1384       /* Read a possibly present fourth argument (alignment flag).  */
1385       if (*input_line_pointer == ',')
1386 	{
1387 	  ++input_line_pointer;
1388 	  alignment_flag = get_absolute_expression ();
1389 	}
1390       else
1391 	alignment_flag = 0;
1392     }
1393   else
1394     blocking_flag = alignment_flag = 0;
1395 
1396   seg = subseg_new (name, 0);
1397   flags = bfd_section_flags (seg) | SEC_ALLOC;
1398 
1399   if (alignment_flag)
1400     {
1401       /* s_align eats end of line; restore it.  */
1402       s_align_bytes (4);
1403       --input_line_pointer;
1404     }
1405 
1406   if (line_label != NULL)
1407     {
1408       S_SET_SEGMENT (line_label, seg);
1409       symbol_set_frag (line_label, frag_now);
1410       S_SET_VALUE (line_label, frag_now_fix ());
1411       /* Set scl to label, since that's what TI does.  */
1412       if (S_GET_STORAGE_CLASS (line_label) != C_EXT)
1413 	S_SET_STORAGE_CLASS (line_label, C_LABEL);
1414     }
1415 
1416   seg_info (seg)->bss = 1;	/* Uninitialized data.  */
1417 
1418   p = frag_var (rs_fill, 1, 1,
1419 		(relax_substateT) 0, (symbolS *) line_label,
1420 		size * OCTETS_PER_BYTE, (char *) 0);
1421   *p = 0;
1422 
1423   if (blocking_flag)
1424     flags |= SEC_TIC54X_BLOCK;
1425 
1426   if (!bfd_set_section_flags (seg, flags))
1427     as_warn (_("Error setting flags for \"%s\": %s"), name,
1428 	     bfd_errmsg (bfd_get_error ()));
1429 
1430   subseg_set (current_seg, current_subseg);	/* Restore current seg.  */
1431   demand_empty_rest_of_line ();
1432 }
1433 
1434 static enum cpu_version
lookup_version(const char * ver)1435 lookup_version (const char *ver)
1436 {
1437   enum cpu_version version = VNONE;
1438 
1439   if (ver[0] == '5' && ver[1] == '4')
1440     {
1441       if (strlen (ver) == 3
1442 	  && (ver[2] == '1' || ver[2] == '2' || ver[2] == '3'
1443 	      || ver[2] == '5' || ver[2] == '8' || ver[2] == '9'))
1444 	version = ver[2] - '0';
1445       else if (strlen (ver) == 5
1446 	       && TOUPPER (ver[3]) == 'L'
1447 	       && TOUPPER (ver[4]) == 'P'
1448 	       && (ver[2] == '5' || ver[2] == '6'))
1449 	version = ver[2] - '0' + 10;
1450     }
1451 
1452   return version;
1453 }
1454 
1455 static void
set_cpu(enum cpu_version version)1456 set_cpu (enum cpu_version version)
1457 {
1458   cpu = version;
1459   if (version == V545LP || version == V546LP)
1460     {
1461       symbolS *symbolP = symbol_new ("__allow_lp", absolute_section,
1462 				     &zero_address_frag, 1);
1463       SF_SET_LOCAL (symbolP);
1464       symbol_table_insert (symbolP);
1465     }
1466 }
1467 
1468 /* .version cpu-version
1469    cpu-version may be one of the following:
1470    541
1471    542
1472    543
1473    545
1474    545LP
1475    546LP
1476    548
1477    549
1478 
1479    This is for compatibility only.  It currently has no affect on assembly.  */
1480 static int cpu_needs_set = 1;
1481 
1482 static void
tic54x_version(int x ATTRIBUTE_UNUSED)1483 tic54x_version (int x ATTRIBUTE_UNUSED)
1484 {
1485   enum cpu_version version = VNONE;
1486   enum cpu_version old_version = cpu;
1487   int c;
1488   char *ver;
1489 
1490   ILLEGAL_WITHIN_STRUCT ();
1491 
1492   SKIP_WHITESPACE ();
1493   ver = input_line_pointer;
1494   while (!is_end_of_line[(unsigned char) *input_line_pointer])
1495     ++input_line_pointer;
1496   c = *input_line_pointer;
1497   *input_line_pointer = 0;
1498 
1499   version = lookup_version (ver);
1500 
1501   if (cpu != VNONE && cpu != version)
1502     as_warn (_("CPU version has already been set"));
1503 
1504   if (version == VNONE)
1505     {
1506       as_bad (_("Unrecognized version '%s'"), ver);
1507       ignore_rest_of_line ();
1508       return;
1509     }
1510   else if (assembly_begun && version != old_version)
1511     {
1512       as_bad (_("Changing of CPU version on the fly not supported"));
1513       ignore_rest_of_line ();
1514       return;
1515     }
1516 
1517   set_cpu (version);
1518 
1519   *input_line_pointer = c;
1520   demand_empty_rest_of_line ();
1521 }
1522 
1523 /* 'f' = float, 'x' = xfloat, 'd' = double, 'l' = ldouble.  */
1524 
1525 static void
tic54x_float_cons(int type)1526 tic54x_float_cons (int type)
1527 {
1528   if (current_stag != 0)
1529     tic54x_struct_field ('f');
1530 
1531 #ifdef md_flush_pending_output
1532   md_flush_pending_output ();
1533 #endif
1534 
1535   /* Align to long word boundary (4 octets) unless it's ".xfloat".  */
1536   if (type != 'x')
1537     {
1538       frag_align (2, 0, 2);
1539       /* If there's a label, assign it to the first allocated word.  */
1540       if (line_label != NULL)
1541 	{
1542 	  symbol_set_frag (line_label, frag_now);
1543 	  S_SET_VALUE (line_label, frag_now_fix ());
1544 	}
1545     }
1546 
1547   float_cons ('f');
1548 }
1549 
1550 /* The argument is capitalized if it should be zero-terminated
1551    's' is normal string with upper 8-bits zero-filled, 'p' is packed.
1552    Code copied from stringer, and slightly modified so that strings are packed
1553    and encoded into the correct octets.  */
1554 
1555 static void
tic54x_stringer(int type)1556 tic54x_stringer (int type)
1557 {
1558   unsigned int c;
1559   int append_zero = type == 'S' || type == 'P';
1560   int packed = type == 'p' || type == 'P';
1561   int last_char = -1; /* Packed strings need two bytes at a time to encode.  */
1562 
1563   if (current_stag != NULL)
1564     {
1565       tic54x_struct_field ('*');
1566       return;
1567     }
1568 
1569 #ifdef md_flush_pending_output
1570   md_flush_pending_output ();
1571 #endif
1572 
1573   c = ',';			/* Do loop.  */
1574   while (c == ',')
1575     {
1576       SKIP_WHITESPACE ();
1577       switch (*input_line_pointer)
1578 	{
1579 	default:
1580 	  {
1581 	    unsigned short value = get_absolute_expression ();
1582 	    FRAG_APPEND_1_CHAR ( value       & 0xFF);
1583 	    FRAG_APPEND_1_CHAR ((value >> 8) & 0xFF);
1584 	    break;
1585 	  }
1586 	case '\"':
1587 	  ++input_line_pointer;	/* -> 1st char of string.  */
1588 	  while (is_a_char (c = next_char_of_string ()))
1589 	    {
1590 	      if (!packed)
1591 		{
1592 		  FRAG_APPEND_1_CHAR (c);
1593 		  FRAG_APPEND_1_CHAR (0);
1594 		}
1595 	      else
1596 		{
1597 		  /* Packed strings are filled MS octet first.  */
1598 		  if (last_char == -1)
1599 		    last_char = c;
1600 		  else
1601 		    {
1602 		      FRAG_APPEND_1_CHAR (c);
1603 		      FRAG_APPEND_1_CHAR (last_char);
1604 		      last_char = -1;
1605 		    }
1606 		}
1607 	    }
1608 	  if (append_zero)
1609 	    {
1610 	      if (packed && last_char != -1)
1611 		{
1612 		  FRAG_APPEND_1_CHAR (0);
1613 		  FRAG_APPEND_1_CHAR (last_char);
1614 		  last_char = -1;
1615 		}
1616 	      else
1617 		{
1618 		  FRAG_APPEND_1_CHAR (0);
1619 		  FRAG_APPEND_1_CHAR (0);
1620 		}
1621 	    }
1622 	  know (input_line_pointer[-1] == '\"');
1623 	  break;
1624 	}
1625       SKIP_WHITESPACE ();
1626       c = *input_line_pointer;
1627       if (!is_end_of_line[c])
1628 	++input_line_pointer;
1629     }
1630 
1631   /* Finish up any leftover packed string.  */
1632   if (packed && last_char != -1)
1633     {
1634       FRAG_APPEND_1_CHAR (0);
1635       FRAG_APPEND_1_CHAR (last_char);
1636     }
1637   demand_empty_rest_of_line ();
1638 }
1639 
1640 static void
tic54x_p2align(int arg ATTRIBUTE_UNUSED)1641 tic54x_p2align (int arg ATTRIBUTE_UNUSED)
1642 {
1643   as_bad (_("p2align not supported on this target"));
1644 }
1645 
1646 static void
tic54x_align_words(int arg)1647 tic54x_align_words (int arg)
1648 {
1649   /* Only ".align" with no argument is allowed within .struct/.union.  */
1650   int count = arg;
1651 
1652   if (!is_end_of_line[(unsigned char) *input_line_pointer])
1653     {
1654       if (arg == 2)
1655 	as_warn (_("Argument to .even ignored"));
1656       else
1657 	count = get_absolute_expression ();
1658     }
1659 
1660   if (current_stag != NULL && arg == 128)
1661     {
1662       if (current_stag->current_bitfield_offset != 0)
1663 	{
1664 	  current_stag->current_bitfield_offset = 0;
1665 	  ++abs_section_offset;
1666 	}
1667       demand_empty_rest_of_line ();
1668       return;
1669     }
1670 
1671   ILLEGAL_WITHIN_STRUCT ();
1672 
1673   s_align_bytes (count << 1);
1674 }
1675 
1676 /* Initialize multiple-bit fields within a single word of memory.  */
1677 
1678 static void
tic54x_field(int ignore ATTRIBUTE_UNUSED)1679 tic54x_field (int ignore ATTRIBUTE_UNUSED)
1680 {
1681   expressionS expn;
1682   int size = 16;
1683   char *p;
1684   valueT value;
1685   symbolS *label = line_label;
1686 
1687   if (current_stag != NULL)
1688     {
1689       tic54x_struct_field ('.');
1690       return;
1691     }
1692 
1693   input_line_pointer = parse_expression (input_line_pointer, &expn);
1694 
1695   if (*input_line_pointer == ',')
1696     {
1697       ++input_line_pointer;
1698       size = get_absolute_expression ();
1699       if (size < 1 || size > 32)
1700 	{
1701 	  as_bad (_("Invalid field size, must be from 1 to 32"));
1702 	  ignore_rest_of_line ();
1703 	  return;
1704 	}
1705     }
1706 
1707   /* Truncate values to the field width.  */
1708   if (expn.X_op != O_constant)
1709     {
1710       /* If the expression value is relocatable, the field size *must*
1711          be 16.  */
1712       if (size != 16)
1713 	{
1714 	  as_bad (_("field size must be 16 when value is relocatable"));
1715 	  ignore_rest_of_line ();
1716 	  return;
1717 	}
1718 
1719       frag_now->tc_frag_data = 0;
1720       emit_expr (&expn, 2);
1721     }
1722   else
1723     {
1724       unsigned long fmask = (size == 32) ? 0xFFFFFFFF : (1ul << size) - 1;
1725 
1726       value = expn.X_add_number;
1727       expn.X_add_number &= fmask;
1728       if (value != (valueT) expn.X_add_number)
1729 	as_warn (_("field value truncated"));
1730       value = expn.X_add_number;
1731       /* Bits are stored MS first.  */
1732       while (size >= 16)
1733 	{
1734 	  frag_now->tc_frag_data = 0;
1735 	  p = frag_more (2);
1736 	  md_number_to_chars (p, (value >> (size - 16)) & 0xFFFF, 2);
1737 	  size -= 16;
1738 	}
1739       if (size > 0)
1740 	{
1741 	  int bit_offset = frag_bit_offset (frag_now, now_seg);
1742 
1743 	  fragS *alloc_frag = bit_offset_frag (frag_now, now_seg);
1744 	  if (bit_offset == -1)
1745 	    {
1746 	      struct bit_info *bi = XNEW (struct bit_info);
1747 	      /* We don't know the previous offset at this time, so store the
1748 		 info we need and figure it out later.  */
1749 	      expressionS size_exp;
1750 
1751 	      size_exp.X_op = O_constant;
1752 	      size_exp.X_add_number = size;
1753 	      bi->seg = now_seg;
1754 	      bi->type = TYPE_FIELD;
1755 	      bi->value = value;
1756 	      p = frag_var (rs_machine_dependent,
1757 			    4, 1, (relax_substateT) 0,
1758 			    make_expr_symbol (&size_exp), (offsetT) 0,
1759 			    (char *) bi);
1760 	      goto getout;
1761 	    }
1762 	  else if (bit_offset == 0 || bit_offset + size > 16)
1763 	    {
1764 	      /* Align a new field.  */
1765 	      p = frag_more (2);
1766 	      frag_now->tc_frag_data = 0;
1767 	      alloc_frag = frag_now;
1768 	    }
1769 	  else
1770 	    {
1771 	      /* Put the new value entirely within the existing one.  */
1772 	      p = alloc_frag == frag_now ?
1773 		frag_now->fr_literal + frag_now_fix_octets () - 2 :
1774 		alloc_frag->fr_literal;
1775 	      if (label != NULL)
1776 		{
1777 		  symbol_set_frag (label, alloc_frag);
1778 		  if (alloc_frag == frag_now)
1779 		    S_SET_VALUE (label, frag_now_fix () - 1);
1780 		  label = NULL;
1781 		}
1782 	    }
1783 	  value <<= 16 - alloc_frag->tc_frag_data - size;
1784 
1785 	  /* OR in existing value.  */
1786 	  if (alloc_frag->tc_frag_data)
1787 	    value |= ((unsigned short) p[1] << 8) | p[0];
1788 	  md_number_to_chars (p, value, 2);
1789 	  alloc_frag->tc_frag_data += size;
1790 	  if (alloc_frag->tc_frag_data == 16)
1791 	    alloc_frag->tc_frag_data = 0;
1792 	}
1793     }
1794  getout:
1795   demand_empty_rest_of_line ();
1796 }
1797 
1798 /* Ideally, we want to check SEC_LOAD and SEC_HAS_CONTENTS, but those aren't
1799    available yet.  seg_info ()->bss is the next best thing.  */
1800 
1801 static int
tic54x_initialized_section(segT seg)1802 tic54x_initialized_section (segT seg)
1803 {
1804   return !seg_info (seg)->bss;
1805 }
1806 
1807 /* .clink ["section name"]
1808 
1809    Marks the section as conditionally linked (link only if contents are
1810    referenced elsewhere.
1811    Without a name, refers to the current initialized section.
1812    Name is required for uninitialized sections.  */
1813 
1814 static void
tic54x_clink(int ignored ATTRIBUTE_UNUSED)1815 tic54x_clink (int ignored ATTRIBUTE_UNUSED)
1816 {
1817   segT seg = now_seg;
1818 
1819   ILLEGAL_WITHIN_STRUCT ();
1820 
1821   if (*input_line_pointer == '\"')
1822     {
1823       char *section_name = ++input_line_pointer;
1824       char *name;
1825 
1826       while (is_a_char (next_char_of_string ()))
1827 	;
1828       know (input_line_pointer[-1] == '\"');
1829       input_line_pointer[-1] = 0;
1830       name = xstrdup (section_name);
1831 
1832       seg = bfd_get_section_by_name (stdoutput, name);
1833       if (seg == NULL)
1834 	{
1835 	  as_bad (_("Unrecognized section '%s'"), section_name);
1836 	  ignore_rest_of_line ();
1837 	  return;
1838 	}
1839     }
1840   else
1841     {
1842       if (!tic54x_initialized_section (seg))
1843 	{
1844 	  as_bad (_("Current section is uninitialized, "
1845 		    "section name required for .clink"));
1846 	  ignore_rest_of_line ();
1847 	  return;
1848 	}
1849     }
1850 
1851   seg->flags |= SEC_TIC54X_CLINK;
1852 
1853   demand_empty_rest_of_line ();
1854 }
1855 
1856 /* Change the default include directory to be the current source file's
1857    directory, instead of the current working directory.  If DOT is non-zero,
1858    set to "." instead.  */
1859 
1860 static void
tic54x_set_default_include(void)1861 tic54x_set_default_include (void)
1862 {
1863   char *dir, *tmp = NULL;
1864   const char *curfile;
1865   unsigned lineno;
1866 
1867   curfile = as_where (&lineno);
1868   dir = xstrdup (curfile);
1869   tmp = strrchr (dir, '/');
1870   if (tmp != NULL)
1871     {
1872       int len;
1873 
1874       *tmp = '\0';
1875       len = strlen (dir);
1876       if (include_dir_count == 0)
1877 	{
1878 	  include_dirs = XNEWVEC (const char *, 1);
1879 	  include_dir_count = 1;
1880 	}
1881       include_dirs[0] = dir;
1882       if (len > include_dir_maxlen)
1883 	include_dir_maxlen = len;
1884     }
1885   else if (include_dirs != NULL)
1886     include_dirs[0] = ".";
1887 }
1888 
1889 /* .include "filename" | filename
1890    .copy    "filename" | filename
1891 
1892    FIXME 'include' file should be omitted from any output listing,
1893      'copy' should be included in any output listing
1894    FIXME -- prevent any included files from changing listing (compat only)
1895    FIXME -- need to include source file directory in search path; what's a
1896       good way to do this?
1897 
1898    Entering/exiting included/copied file clears all local labels.  */
1899 
1900 static void
tic54x_include(int ignored ATTRIBUTE_UNUSED)1901 tic54x_include (int ignored ATTRIBUTE_UNUSED)
1902 {
1903   char newblock[] = " .newblock\n";
1904   char *filename;
1905   char *input;
1906   int len, c = -1;
1907 
1908   ILLEGAL_WITHIN_STRUCT ();
1909 
1910   SKIP_WHITESPACE ();
1911 
1912   if (*input_line_pointer == '"')
1913     {
1914       filename = demand_copy_C_string (&len);
1915       demand_empty_rest_of_line ();
1916     }
1917   else
1918     {
1919       filename = input_line_pointer;
1920       while (!is_end_of_line[(unsigned char) *input_line_pointer])
1921 	++input_line_pointer;
1922       c = *input_line_pointer;
1923       *input_line_pointer = '\0';
1924       filename = xstrdup (filename);
1925       *input_line_pointer = c;
1926       demand_empty_rest_of_line ();
1927     }
1928   /* Insert a partial line with the filename (for the sake of s_include)
1929      and a .newblock.
1930      The included file will be inserted before the newblock, so that the
1931      newblock is executed after the included file is processed.  */
1932   input = concat ("\"", filename, "\"\n", newblock, (char *) NULL);
1933   input_scrub_insert_line (input);
1934 
1935   tic54x_clear_local_labels (0);
1936 
1937   tic54x_set_default_include ();
1938 
1939   s_include (0);
1940 }
1941 
1942 static void
tic54x_message(int type)1943 tic54x_message (int type)
1944 {
1945   char *msg;
1946   char c;
1947   int len;
1948 
1949   ILLEGAL_WITHIN_STRUCT ();
1950 
1951   if (*input_line_pointer == '"')
1952     msg = demand_copy_C_string (&len);
1953   else
1954     {
1955       msg = input_line_pointer;
1956       while (!is_end_of_line[(unsigned char) *input_line_pointer])
1957 	++input_line_pointer;
1958       c = *input_line_pointer;
1959       *input_line_pointer = 0;
1960       msg = xstrdup (msg);
1961       *input_line_pointer = c;
1962     }
1963 
1964   switch (type)
1965     {
1966     case 'm':
1967       as_tsktsk ("%s", msg);
1968       break;
1969     case 'w':
1970       as_warn ("%s", msg);
1971       break;
1972     case 'e':
1973       as_bad ("%s", msg);
1974       break;
1975     }
1976 
1977   demand_empty_rest_of_line ();
1978 }
1979 
1980 /* .label <symbol>
1981    Define a special symbol that refers to the loadtime address rather than the
1982    runtime address within the current section.
1983 
1984    This symbol gets a special storage class so that when it is resolved, it is
1985    resolved relative to the load address (lma) of the section rather than the
1986    run address (vma).  */
1987 
1988 static void
tic54x_label(int ignored ATTRIBUTE_UNUSED)1989 tic54x_label (int ignored ATTRIBUTE_UNUSED)
1990 {
1991   char *name;
1992   symbolS *symbolP;
1993   int c;
1994 
1995   ILLEGAL_WITHIN_STRUCT ();
1996 
1997   c = get_symbol_name (&name);
1998   symbolP = colon (name);
1999   S_SET_STORAGE_CLASS (symbolP, C_STATLAB);
2000 
2001   (void) restore_line_pointer (c);
2002   demand_empty_rest_of_line ();
2003 }
2004 
2005 /* .mmregs
2006    Install all memory-mapped register names into the symbol table as
2007    absolute local symbols.  */
2008 
2009 static void
tic54x_register_mmregs(int ignored ATTRIBUTE_UNUSED)2010 tic54x_register_mmregs (int ignored ATTRIBUTE_UNUSED)
2011 {
2012   const tic54x_symbol *sym;
2013 
2014   ILLEGAL_WITHIN_STRUCT ();
2015 
2016   for (sym = tic54x_mmregs; sym->name; sym++)
2017     {
2018       symbolS *symbolP = symbol_new (sym->name, absolute_section,
2019 				     &zero_address_frag, sym->value);
2020       SF_SET_LOCAL (symbolP);
2021       symbol_table_insert (symbolP);
2022     }
2023 }
2024 
2025 /* .loop [count]
2026    Count defaults to 1024.  */
2027 
2028 static void
tic54x_loop(int count)2029 tic54x_loop (int count)
2030 {
2031   ILLEGAL_WITHIN_STRUCT ();
2032 
2033   SKIP_WHITESPACE ();
2034   if (!is_end_of_line[(unsigned char) *input_line_pointer])
2035     count = get_absolute_expression ();
2036 
2037   do_repeat ((size_t) count, "LOOP", "ENDLOOP", NULL);
2038 }
2039 
2040 /* Normally, endloop gets eaten by the preceding loop.  */
2041 
2042 static void
tic54x_endloop(int ignore ATTRIBUTE_UNUSED)2043 tic54x_endloop (int ignore ATTRIBUTE_UNUSED)
2044 {
2045   as_bad (_("ENDLOOP without corresponding LOOP"));
2046   ignore_rest_of_line ();
2047 }
2048 
2049 /* .break [condition].  */
2050 
2051 static void
tic54x_break(int ignore ATTRIBUTE_UNUSED)2052 tic54x_break (int ignore ATTRIBUTE_UNUSED)
2053 {
2054   int cond = 1;
2055 
2056   ILLEGAL_WITHIN_STRUCT ();
2057 
2058   SKIP_WHITESPACE ();
2059   if (!is_end_of_line[(unsigned char) *input_line_pointer])
2060     cond = get_absolute_expression ();
2061 
2062   if (cond)
2063     end_repeat (substitution_line ? 1 : 0);
2064 }
2065 
2066 static void
set_address_mode(int mode)2067 set_address_mode (int mode)
2068 {
2069   amode = mode;
2070   if (mode == far_mode)
2071     {
2072       symbolS *symbolP = symbol_new ("__allow_far", absolute_section,
2073 				     &zero_address_frag, 1);
2074       SF_SET_LOCAL (symbolP);
2075       symbol_table_insert (symbolP);
2076     }
2077 }
2078 
2079 static int address_mode_needs_set = 1;
2080 
2081 static void
tic54x_address_mode(int mode)2082 tic54x_address_mode (int mode)
2083 {
2084   if (assembly_begun && amode != (unsigned) mode)
2085     {
2086       as_bad (_("Mixing of normal and extended addressing not supported"));
2087       ignore_rest_of_line ();
2088       return;
2089     }
2090   if (mode == far_mode && cpu != VNONE && cpu != V548 && cpu != V549)
2091     {
2092       as_bad (_("Extended addressing not supported on the specified CPU"));
2093       ignore_rest_of_line ();
2094       return;
2095     }
2096 
2097   set_address_mode (mode);
2098   demand_empty_rest_of_line ();
2099 }
2100 
2101 /* .sblock "section"|section [,...,"section"|section]
2102    Designate initialized sections for blocking.  */
2103 
2104 static void
tic54x_sblock(int ignore ATTRIBUTE_UNUSED)2105 tic54x_sblock (int ignore ATTRIBUTE_UNUSED)
2106 {
2107   int c = ',';
2108 
2109   ILLEGAL_WITHIN_STRUCT ();
2110 
2111   while (c == ',')
2112     {
2113       segT seg;
2114       char *name;
2115 
2116       if (*input_line_pointer == '"')
2117 	{
2118 	  int len;
2119 
2120 	  name = demand_copy_C_string (&len);
2121 	}
2122       else
2123 	{
2124 	  char *section_name;
2125 
2126 	  c = get_symbol_name (&section_name);
2127 	  name = xstrdup (section_name);
2128 	  (void) restore_line_pointer (c);
2129 	}
2130 
2131       seg = bfd_get_section_by_name (stdoutput, name);
2132       if (seg == NULL)
2133 	{
2134 	  as_bad (_("Unrecognized section '%s'"), name);
2135 	  ignore_rest_of_line ();
2136 	  return;
2137 	}
2138       else if (!tic54x_initialized_section (seg))
2139 	{
2140 	  as_bad (_(".sblock may be used for initialized sections only"));
2141 	  ignore_rest_of_line ();
2142 	  return;
2143 	}
2144       seg->flags |= SEC_TIC54X_BLOCK;
2145 
2146       c = *input_line_pointer;
2147       if (!is_end_of_line[(unsigned char) c])
2148 	++input_line_pointer;
2149     }
2150 
2151   demand_empty_rest_of_line ();
2152 }
2153 
2154 /* symbol .set value
2155    symbol .equ value
2156 
2157    value must be defined externals; no forward-referencing allowed
2158    symbols assigned with .set/.equ may not be redefined.  */
2159 
2160 static void
tic54x_set(int ignore ATTRIBUTE_UNUSED)2161 tic54x_set (int ignore ATTRIBUTE_UNUSED)
2162 {
2163   symbolS *symbolP;
2164   char *name;
2165 
2166   ILLEGAL_WITHIN_STRUCT ();
2167 
2168   if (!line_label)
2169     {
2170       as_bad (_("Symbol missing for .set/.equ"));
2171       ignore_rest_of_line ();
2172       return;
2173     }
2174   name = xstrdup (S_GET_NAME (line_label));
2175   line_label = NULL;
2176   if ((symbolP = symbol_find (name)) == NULL
2177       && (symbolP = md_undefined_symbol (name)) == NULL)
2178     {
2179       symbolP = symbol_new (name, absolute_section, &zero_address_frag, 0);
2180       S_SET_STORAGE_CLASS (symbolP, C_STAT);
2181     }
2182   free (name);
2183   S_SET_DATA_TYPE (symbolP, T_INT);
2184   S_SET_SEGMENT (symbolP, absolute_section);
2185   symbol_table_insert (symbolP);
2186   pseudo_set (symbolP);
2187   demand_empty_rest_of_line ();
2188 }
2189 
2190 /* .fclist
2191    .fcnolist
2192    List false conditional blocks.  */
2193 
2194 static void
tic54x_fclist(int show)2195 tic54x_fclist (int show)
2196 {
2197   if (show)
2198     listing &= ~LISTING_NOCOND;
2199   else
2200     listing |= LISTING_NOCOND;
2201   demand_empty_rest_of_line ();
2202 }
2203 
2204 static void
tic54x_sslist(int show)2205 tic54x_sslist (int show)
2206 {
2207   ILLEGAL_WITHIN_STRUCT ();
2208 
2209   listing_sslist = show;
2210 }
2211 
2212 /* .var SYM[,...,SYMN]
2213    Define a substitution string to be local to a macro.  */
2214 
2215 static void
tic54x_var(int ignore ATTRIBUTE_UNUSED)2216 tic54x_var (int ignore ATTRIBUTE_UNUSED)
2217 {
2218   static char empty[] = "";
2219   char *name;
2220   int c;
2221 
2222   ILLEGAL_WITHIN_STRUCT ();
2223 
2224   if (macro_level == 0)
2225     {
2226       as_bad (_(".var may only be used within a macro definition"));
2227       ignore_rest_of_line ();
2228       return;
2229     }
2230   do
2231     {
2232       if (!ISALPHA (*input_line_pointer))
2233 	{
2234 	  as_bad (_("Substitution symbols must begin with a letter"));
2235 	  ignore_rest_of_line ();
2236 	  return;
2237 	}
2238       c = get_symbol_name (&name);
2239       /* .var symbols start out with a null string.  */
2240       name = xstrdup (name);
2241       str_hash_insert (subsym_hash[macro_level], name, empty, 0);
2242       c = restore_line_pointer (c);
2243       if (c == ',')
2244 	{
2245 	  ++input_line_pointer;
2246 	  if (is_end_of_line[(unsigned char) *input_line_pointer])
2247 	    c = *input_line_pointer;
2248 	}
2249     }
2250   while (c == ',');
2251 
2252   demand_empty_rest_of_line ();
2253 }
2254 
2255 /* .mlib <macro library filename>
2256 
2257    Macro libraries are archived (standard AR-format) text macro definitions
2258    Expand the file and include it.
2259 
2260    FIXME need to try the source file directory as well.  */
2261 
2262 static void
tic54x_mlib(int ignore ATTRIBUTE_UNUSED)2263 tic54x_mlib (int ignore ATTRIBUTE_UNUSED)
2264 {
2265   char *filename;
2266   char *path;
2267   int len, i;
2268   bfd *abfd, *mbfd;
2269 
2270   ILLEGAL_WITHIN_STRUCT ();
2271 
2272   /* Parse the filename.  */
2273   if (*input_line_pointer == '"')
2274     {
2275       if ((filename = demand_copy_C_string (&len)) == NULL)
2276 	return;
2277     }
2278   else
2279     {
2280       SKIP_WHITESPACE ();
2281       len = 0;
2282       while (!is_end_of_line[(unsigned char) *input_line_pointer]
2283 	     && !ISSPACE (*input_line_pointer))
2284 	{
2285 	  obstack_1grow (&notes, *input_line_pointer);
2286 	  ++input_line_pointer;
2287 	  ++len;
2288 	}
2289       obstack_1grow (&notes, '\0');
2290       filename = obstack_finish (&notes);
2291     }
2292   demand_empty_rest_of_line ();
2293 
2294   tic54x_set_default_include ();
2295   path = XNEWVEC (char, (unsigned long) len + include_dir_maxlen + 5);
2296 
2297   for (i = 0; i < include_dir_count; i++)
2298     {
2299       FILE *try;
2300 
2301       strcpy (path, include_dirs[i]);
2302       strcat (path, "/");
2303       strcat (path, filename);
2304       if ((try = fopen (path, "r")) != NULL)
2305 	{
2306 	  fclose (try);
2307 	  break;
2308 	}
2309     }
2310 
2311   if (i >= include_dir_count)
2312     {
2313       free (path);
2314       path = filename;
2315     }
2316 
2317   /* FIXME: if path is found, malloc'd storage is not freed.  Of course, this
2318      happens all over the place, and since the assembler doesn't usually keep
2319      running for a very long time, it really doesn't matter.  */
2320   register_dependency (path);
2321 
2322   /* Expand all archive entries to temporary files and include them.  */
2323   abfd = bfd_openr (path, NULL);
2324   if (!abfd)
2325     {
2326       as_bad (_("can't open macro library file '%s' for reading: %s"),
2327 	      path, bfd_errmsg (bfd_get_error ()));
2328       ignore_rest_of_line ();
2329       return;
2330     }
2331   if (!bfd_check_format (abfd, bfd_archive))
2332     {
2333       as_bad (_("File '%s' not in macro archive format"), path);
2334       ignore_rest_of_line ();
2335       return;
2336     }
2337 
2338   /* Open each BFD as binary (it should be straight ASCII text).  */
2339   for (mbfd = bfd_openr_next_archived_file (abfd, NULL);
2340        mbfd != NULL; mbfd = bfd_openr_next_archived_file (abfd, mbfd))
2341     {
2342       /* Get a size at least as big as the archive member.  */
2343       bfd_size_type size = bfd_get_size (mbfd);
2344       char *buf = XNEWVEC (char, size);
2345       char *fname = tmpnam (NULL);
2346       FILE *ftmp;
2347 
2348       /* We're not sure how big it is, but it will be smaller than "size".  */
2349       size = bfd_bread (buf, size, mbfd);
2350 
2351       /* Write to a temporary file, then use s_include to include it
2352 	 a bit of a hack.  */
2353       ftmp = fopen (fname, "w+b");
2354       fwrite ((void *) buf, size, 1, ftmp);
2355       if (size == 0 || buf[size - 1] != '\n')
2356 	fwrite ("\n", 1, 1, ftmp);
2357       fclose (ftmp);
2358       free (buf);
2359       input_scrub_insert_file (fname);
2360       remove (fname);
2361     }
2362 }
2363 
2364 const pseudo_typeS md_pseudo_table[] =
2365 {
2366   { "algebraic", s_ignore                 ,          0 },
2367   { "align"    , tic54x_align_words       ,        128 },
2368   { "ascii"    , tic54x_stringer          ,        'p' },
2369   { "asciz"    , tic54x_stringer          ,        'P' },
2370   { "even"     , tic54x_align_words       ,          2 },
2371   { "asg"      , tic54x_asg               ,          0 },
2372   { "eval"     , tic54x_eval              ,          0 },
2373   { "bss"      , tic54x_bss               ,          0 },
2374   { "byte"     , tic54x_cons              ,        'b' },
2375   { "ubyte"    , tic54x_cons              ,        'B' },
2376   { "char"     , tic54x_cons              ,        'c' },
2377   { "uchar"    , tic54x_cons              ,        'C' },
2378   { "clink"    , tic54x_clink             ,          0 },
2379   { "c_mode"   , tic54x_address_mode      ,     c_mode },
2380   { "copy"     , tic54x_include           ,        'c' },
2381   { "include"  , tic54x_include           ,        'i' },
2382   { "data"     , tic54x_sect              ,        'd' },
2383   { "double"   , tic54x_float_cons        ,        'd' },
2384   { "ldouble"  , tic54x_float_cons        ,        'l' },
2385   { "drlist"   , s_ignore                 ,          0 },
2386   { "drnolist" , s_ignore                 ,          0 },
2387   { "emsg"     , tic54x_message           ,        'e' },
2388   { "mmsg"     , tic54x_message           ,        'm' },
2389   { "wmsg"     , tic54x_message           ,        'w' },
2390   { "far_mode" , tic54x_address_mode      ,   far_mode },
2391   { "fclist"   , tic54x_fclist            ,          1 },
2392   { "fcnolist" , tic54x_fclist            ,          0 },
2393   { "field"    , tic54x_field             ,         -1 },
2394   { "float"    , tic54x_float_cons        ,        'f' },
2395   { "xfloat"   , tic54x_float_cons        ,        'x' },
2396   { "global"   , tic54x_global            ,        'g' },
2397   { "def"      , tic54x_global            ,        'd' },
2398   { "ref"      , tic54x_global            ,        'r' },
2399   { "half"     , tic54x_cons              ,        'h' },
2400   { "uhalf"    , tic54x_cons              ,        'H' },
2401   { "short"    , tic54x_cons              ,        's' },
2402   { "ushort"   , tic54x_cons              ,        'S' },
2403   { "if"       , s_if                     , (int) O_ne },
2404   { "elseif"   , s_elseif                 , (int) O_ne },
2405   { "else"     , s_else                   ,          0 },
2406   { "endif"    , s_endif                  ,          0 },
2407   { "int"      , tic54x_cons              ,        'i' },
2408   { "uint"     , tic54x_cons              ,        'I' },
2409   { "word"     , tic54x_cons              ,        'w' },
2410   { "uword"    , tic54x_cons              ,        'W' },
2411   { "label"    , tic54x_label             ,          0 }, /* Loadtime
2412                                                              address.  */
2413   { "length"   , s_ignore                 ,          0 },
2414   { "width"    , s_ignore                 ,          0 },
2415   { "long"     , tic54x_cons              ,        'l' },
2416   { "ulong"    , tic54x_cons              ,        'L' },
2417   { "xlong"    , tic54x_cons              ,        'x' },
2418   { "loop"     , tic54x_loop              ,       1024 },
2419   { "break"    , tic54x_break             ,          0 },
2420   { "endloop"  , tic54x_endloop           ,          0 },
2421   { "mlib"     , tic54x_mlib              ,          0 },
2422   { "mlist"    , s_ignore                 ,          0 },
2423   { "mnolist"  , s_ignore                 ,          0 },
2424   { "mmregs"   , tic54x_register_mmregs   ,          0 },
2425   { "newblock" , tic54x_clear_local_labels,          0 },
2426   { "option"   , s_ignore                 ,          0 },
2427   { "p2align"  , tic54x_p2align           ,          0 },
2428   { "sblock"   , tic54x_sblock            ,          0 },
2429   { "sect"     , tic54x_sect              ,        '*' },
2430   { "set"      , tic54x_set               ,          0 },
2431   { "equ"      , tic54x_set               ,          0 },
2432   { "space"    , tic54x_space             ,          0 },
2433   { "bes"      , tic54x_space             ,          1 },
2434   { "sslist"   , tic54x_sslist            ,          1 },
2435   { "ssnolist" , tic54x_sslist            ,          0 },
2436   { "string"   , tic54x_stringer          ,        's' },
2437   { "pstring"  , tic54x_stringer          ,        'p' },
2438   { "struct"   , tic54x_struct            ,          0 },
2439   { "tag"      , tic54x_tag               ,          0 },
2440   { "endstruct", tic54x_endstruct         ,          0 },
2441   { "tab"      , s_ignore                 ,          0 },
2442   { "text"     , tic54x_sect              ,        't' },
2443   { "union"    , tic54x_struct            ,          1 },
2444   { "endunion" , tic54x_endstruct         ,          1 },
2445   { "usect"    , tic54x_usect             ,          0 },
2446   { "var"      , tic54x_var               ,          0 },
2447   { "version"  , tic54x_version           ,          0 },
2448   {0           , 0                        ,          0 }
2449 };
2450 
2451 int
md_parse_option(int c,const char * arg)2452 md_parse_option (int c, const char *arg)
2453 {
2454   switch (c)
2455     {
2456     default:
2457       return 0;
2458     case OPTION_COFF_VERSION:
2459       {
2460 	int version = atoi (arg);
2461 
2462 	if (version != 0 && version != 1 && version != 2)
2463 	  as_fatal (_("Bad COFF version '%s'"), arg);
2464 	/* FIXME -- not yet implemented.  */
2465 	break;
2466       }
2467     case OPTION_CPU_VERSION:
2468       {
2469 	cpu = lookup_version (arg);
2470 	cpu_needs_set = 1;
2471 	if (cpu == VNONE)
2472 	  as_fatal (_("Bad CPU version '%s'"), arg);
2473 	break;
2474       }
2475     case OPTION_ADDRESS_MODE:
2476       amode = far_mode;
2477       address_mode_needs_set = 1;
2478       break;
2479     case OPTION_STDERR_TO_FILE:
2480       {
2481 	const char *filename = arg;
2482 	FILE *fp = fopen (filename, "w+");
2483 
2484 	if (fp == NULL)
2485 	  as_fatal (_("Can't redirect stderr to the file '%s'"), filename);
2486 	fclose (fp);
2487 	if ((fp = freopen (filename, "w+", stderr)) == NULL)
2488 	  as_fatal (_("Can't redirect stderr to the file '%s'"), filename);
2489 	break;
2490       }
2491     }
2492 
2493   return 1;
2494 }
2495 
2496 /* Create a "local" substitution string hash table for a new macro level
2497    Some docs imply that macros have to use .newblock in order to be able
2498    to re-use a local label.  We effectively do an automatic .newblock by
2499    deleting the local label hash between macro invocations.  */
2500 
2501 void
tic54x_macro_start(void)2502 tic54x_macro_start (void)
2503 {
2504   if (++macro_level >= MAX_SUBSYM_HASH)
2505     {
2506       as_fatal (_("Macro nesting is too deep"));
2507       return;
2508     }
2509   subsym_hash[macro_level] = str_htab_create ();
2510   local_label_hash[macro_level] = str_htab_create ();
2511 }
2512 
2513 void
tic54x_macro_info(const macro_entry * macro)2514 tic54x_macro_info (const macro_entry *macro)
2515 {
2516   const formal_entry *entry;
2517 
2518   /* Put the formal args into the substitution symbol table.  */
2519   for (entry = macro->formals; entry; entry = entry->next)
2520     {
2521       char *name = xstrndup (entry->name.ptr, entry->name.len);
2522       char *value = xstrndup (entry->actual.ptr, entry->actual.len);
2523 
2524       name[entry->name.len] = '\0';
2525       value[entry->actual.len] = '\0';
2526       str_hash_insert (subsym_hash[macro_level], name, value, 0);
2527     }
2528 }
2529 
2530 /* Get rid of this macro's .var's, arguments, and local labels.  */
2531 
2532 void
tic54x_macro_end(void)2533 tic54x_macro_end (void)
2534 {
2535   htab_delete (subsym_hash[macro_level]);
2536   subsym_hash[macro_level] = NULL;
2537   htab_delete (local_label_hash[macro_level]);
2538   local_label_hash[macro_level] = NULL;
2539   --macro_level;
2540 }
2541 
2542 static int
subsym_symlen(char * a,char * ignore ATTRIBUTE_UNUSED)2543 subsym_symlen (char *a, char *ignore ATTRIBUTE_UNUSED)
2544 {
2545   return strlen (a);
2546 }
2547 
2548 /* Compare symbol A to string B.  */
2549 
2550 static int
subsym_symcmp(char * a,char * b)2551 subsym_symcmp (char *a, char *b)
2552 {
2553   return strcmp (a, b);
2554 }
2555 
2556 /* Return the index of the first occurrence of B in A, or zero if none
2557    assumes b is an integer char value as a string.  Index is one-based.  */
2558 
2559 static int
subsym_firstch(char * a,char * b)2560 subsym_firstch (char *a, char *b)
2561 {
2562   int val = atoi (b);
2563   char *tmp = strchr (a, val);
2564 
2565   return tmp ? tmp - a + 1 : 0;
2566 }
2567 
2568 /* Similar to firstch, but returns index of last occurrence of B in A.  */
2569 
2570 static int
subsym_lastch(char * a,char * b)2571 subsym_lastch (char *a, char *b)
2572 {
2573   int val = atoi (b);
2574   char *tmp = strrchr (a, val);
2575 
2576   return tmp ? tmp - a + 1 : 0;
2577 }
2578 
2579 /* Returns 1 if string A is defined in the symbol table (NOT the substitution
2580    symbol table).  */
2581 
2582 static int
subsym_isdefed(char * a,char * ignore ATTRIBUTE_UNUSED)2583 subsym_isdefed (char *a, char *ignore ATTRIBUTE_UNUSED)
2584 {
2585   symbolS *symbolP = symbol_find (a);
2586 
2587   return symbolP != NULL;
2588 }
2589 
2590 /* Assign first member of comma-separated list B (e.g. "1,2,3") to the symbol
2591    A, or zero if B is a null string.  Both arguments *must* be substitution
2592    symbols, unsubstituted.  */
2593 
2594 static int
subsym_ismember(char * sym,char * list)2595 subsym_ismember (char *sym, char *list)
2596 {
2597   char *elem, *ptr, *listv;
2598 
2599   if (!list)
2600     return 0;
2601 
2602   listv = subsym_lookup (list, macro_level);
2603   if (!listv)
2604     {
2605       as_bad (_("Undefined substitution symbol '%s'"), list);
2606       ignore_rest_of_line ();
2607       return 0;
2608     }
2609 
2610   ptr = elem = xstrdup (listv);
2611   while (*ptr && *ptr != ',')
2612     ++ptr;
2613   *ptr++ = 0;
2614 
2615   subsym_create_or_replace (sym, elem);
2616 
2617   /* Reassign the list.  */
2618   subsym_create_or_replace (list, ptr);
2619 
2620   /* Assume this value, docs aren't clear.  */
2621   return *list != 0;
2622 }
2623 
2624 /* Return zero if not a constant; otherwise:
2625    1 if binary
2626    2 if octal
2627    3 if hexadecimal
2628    4 if character
2629    5 if decimal.  */
2630 
2631 static int
subsym_iscons(char * a,char * ignore ATTRIBUTE_UNUSED)2632 subsym_iscons (char *a, char *ignore ATTRIBUTE_UNUSED)
2633 {
2634   expressionS expn;
2635 
2636   parse_expression (a, &expn);
2637 
2638   if (expn.X_op == O_constant)
2639     {
2640       int len = strlen (a);
2641 
2642       switch (TOUPPER (a[len - 1]))
2643 	{
2644 	case 'B':
2645 	  return 1;
2646 	case 'Q':
2647 	  return 2;
2648 	case 'H':
2649 	  return 3;
2650 	case '\'':
2651 	  return 4;
2652 	default:
2653 	  break;
2654 	}
2655       /* No suffix; either octal, hex, or decimal.  */
2656       if (*a == '0' && len > 1)
2657 	{
2658 	  if (TOUPPER (a[1]) == 'X')
2659 	    return 3;
2660 	  return 2;
2661 	}
2662       return 5;
2663     }
2664 
2665   return 0;
2666 }
2667 
2668 /* Return 1 if A is a valid symbol name.  Expects string input.   */
2669 
2670 static int
subsym_isname(char * a,char * ignore ATTRIBUTE_UNUSED)2671 subsym_isname (char *a, char *ignore ATTRIBUTE_UNUSED)
2672 {
2673   if (!is_name_beginner (*a))
2674     return 0;
2675   while (*a)
2676     {
2677       if (!is_part_of_name (*a))
2678 	return 0;
2679       ++a;
2680     }
2681   return 1;
2682 }
2683 
2684 /* Return whether the string is a register; accepts ar0-7, unless .mmregs has
2685    been seen; if so, recognize any memory-mapped register.
2686    Note this does not recognize "A" or "B" accumulators.  */
2687 
2688 static int
subsym_isreg(char * a,char * ignore ATTRIBUTE_UNUSED)2689 subsym_isreg (char *a, char *ignore ATTRIBUTE_UNUSED)
2690 {
2691   if (str_hash_find (reg_hash, a))
2692     return 1;
2693   if (str_hash_find (mmreg_hash, a))
2694     return 1;
2695   return 0;
2696 }
2697 
2698 /* Return the structure size, given the stag.  */
2699 
2700 static int
subsym_structsz(char * name,char * ignore ATTRIBUTE_UNUSED)2701 subsym_structsz (char *name, char *ignore ATTRIBUTE_UNUSED)
2702 {
2703   struct stag *stag = (struct stag *) str_hash_find (stag_hash, name);
2704 
2705   if (stag)
2706     return stag->size;
2707 
2708   return 0;
2709 }
2710 
2711 /* If anybody actually uses this, they can fix it :)
2712    FIXME I'm not sure what the "reference point" of a structure is.  It might
2713    be either the initial offset given .struct, or it may be the offset of the
2714    structure within another structure, or it might be something else
2715    altogether.  since the TI assembler doesn't seem to ever do anything but
2716    return zero, we punt and return zero.  */
2717 
2718 static int
subsym_structacc(char * stag_name ATTRIBUTE_UNUSED,char * ignore ATTRIBUTE_UNUSED)2719 subsym_structacc (char *stag_name ATTRIBUTE_UNUSED,
2720 		  char *ignore ATTRIBUTE_UNUSED)
2721 {
2722   return 0;
2723 }
2724 
2725 static float
math_ceil(float arg1,float ignore ATTRIBUTE_UNUSED)2726 math_ceil (float arg1, float ignore ATTRIBUTE_UNUSED)
2727 {
2728   return (float) ceil (arg1);
2729 }
2730 
2731 static float
math_cvi(float arg1,float ignore ATTRIBUTE_UNUSED)2732 math_cvi (float arg1, float ignore ATTRIBUTE_UNUSED)
2733 {
2734   return (int) arg1;
2735 }
2736 
2737 static float
math_floor(float arg1,float ignore ATTRIBUTE_UNUSED)2738 math_floor (float arg1, float ignore ATTRIBUTE_UNUSED)
2739 {
2740   return (float) floor (arg1);
2741 }
2742 
2743 static float
math_fmod(float arg1,float arg2)2744 math_fmod (float arg1, float arg2)
2745 {
2746   return (int) arg1 % (int) arg2;
2747 }
2748 
2749 static float
math_int(float arg1,float ignore ATTRIBUTE_UNUSED)2750 math_int (float arg1, float ignore ATTRIBUTE_UNUSED)
2751 {
2752   return ((float) ((int) arg1)) == arg1;
2753 }
2754 
2755 static float
math_round(float arg1,float ignore ATTRIBUTE_UNUSED)2756 math_round (float arg1, float ignore ATTRIBUTE_UNUSED)
2757 {
2758   return arg1 > 0 ? (int) (arg1 + 0.5) : (int) (arg1 - 0.5);
2759 }
2760 
2761 static float
math_sgn(float arg1,float ignore ATTRIBUTE_UNUSED)2762 math_sgn (float arg1, float ignore ATTRIBUTE_UNUSED)
2763 {
2764   return (arg1 < 0) ? -1 : (arg1 ? 1 : 0);
2765 }
2766 
2767 static float
math_trunc(float arg1,float ignore ATTRIBUTE_UNUSED)2768 math_trunc (float arg1, float ignore ATTRIBUTE_UNUSED)
2769 {
2770   return (int) arg1;
2771 }
2772 
2773 static float
math_acos(float arg1,float ignore ATTRIBUTE_UNUSED)2774 math_acos (float arg1, float ignore ATTRIBUTE_UNUSED)
2775 {
2776   return (float) acos (arg1);
2777 }
2778 
2779 static float
math_asin(float arg1,float ignore ATTRIBUTE_UNUSED)2780 math_asin (float arg1, float ignore ATTRIBUTE_UNUSED)
2781 {
2782   return (float) asin (arg1);
2783 }
2784 
2785 static float
math_atan(float arg1,float ignore ATTRIBUTE_UNUSED)2786 math_atan (float arg1, float ignore ATTRIBUTE_UNUSED)
2787 {
2788   return (float) atan (arg1);
2789 }
2790 
2791 static float
math_atan2(float arg1,float arg2)2792 math_atan2 (float arg1, float arg2)
2793 {
2794   return (float) atan2 (arg1, arg2);
2795 }
2796 
2797 static float
math_cosh(float arg1,float ignore ATTRIBUTE_UNUSED)2798 math_cosh (float arg1, float ignore ATTRIBUTE_UNUSED)
2799 {
2800   return (float) cosh (arg1);
2801 }
2802 
2803 static float
math_cos(float arg1,float ignore ATTRIBUTE_UNUSED)2804 math_cos (float arg1, float ignore ATTRIBUTE_UNUSED)
2805 {
2806   return (float) cos (arg1);
2807 }
2808 
2809 static float
math_cvf(float arg1,float ignore ATTRIBUTE_UNUSED)2810 math_cvf (float arg1, float ignore ATTRIBUTE_UNUSED)
2811 {
2812   return (float) arg1;
2813 }
2814 
2815 static float
math_exp(float arg1,float ignore ATTRIBUTE_UNUSED)2816 math_exp (float arg1, float ignore ATTRIBUTE_UNUSED)
2817 {
2818   return (float) exp (arg1);
2819 }
2820 
2821 static float
math_fabs(float arg1,float ignore ATTRIBUTE_UNUSED)2822 math_fabs (float arg1, float ignore ATTRIBUTE_UNUSED)
2823 {
2824   return (float) fabs (arg1);
2825 }
2826 
2827 /* expr1 * 2^expr2.  */
2828 
2829 static float
math_ldexp(float arg1,float arg2)2830 math_ldexp (float arg1, float arg2)
2831 {
2832   return arg1 * (float) pow (2.0, arg2);
2833 }
2834 
2835 static float
math_log10(float arg1,float ignore ATTRIBUTE_UNUSED)2836 math_log10 (float arg1, float ignore ATTRIBUTE_UNUSED)
2837 {
2838   return (float) log10 (arg1);
2839 }
2840 
2841 static float
math_log(float arg1,float ignore ATTRIBUTE_UNUSED)2842 math_log (float arg1, float ignore ATTRIBUTE_UNUSED)
2843 {
2844   return (float) log (arg1);
2845 }
2846 
2847 static float
math_max(float arg1,float arg2)2848 math_max (float arg1, float arg2)
2849 {
2850   return (arg1 > arg2) ? arg1 : arg2;
2851 }
2852 
2853 static float
math_min(float arg1,float arg2)2854 math_min (float arg1, float arg2)
2855 {
2856   return (arg1 < arg2) ? arg1 : arg2;
2857 }
2858 
2859 static float
math_pow(float arg1,float arg2)2860 math_pow (float arg1, float arg2)
2861 {
2862   return (float) pow (arg1, arg2);
2863 }
2864 
2865 static float
math_sin(float arg1,float ignore ATTRIBUTE_UNUSED)2866 math_sin (float arg1, float ignore ATTRIBUTE_UNUSED)
2867 {
2868   return (float) sin (arg1);
2869 }
2870 
2871 static float
math_sinh(float arg1,float ignore ATTRIBUTE_UNUSED)2872 math_sinh (float arg1, float ignore ATTRIBUTE_UNUSED)
2873 {
2874   return (float) sinh (arg1);
2875 }
2876 
2877 static float
math_sqrt(float arg1,float ignore ATTRIBUTE_UNUSED)2878 math_sqrt (float arg1, float ignore ATTRIBUTE_UNUSED)
2879 {
2880   return (float) sqrt (arg1);
2881 }
2882 
2883 static float
math_tan(float arg1,float ignore ATTRIBUTE_UNUSED)2884 math_tan (float arg1, float ignore ATTRIBUTE_UNUSED)
2885 {
2886   return (float) tan (arg1);
2887 }
2888 
2889 static float
math_tanh(float arg1,float ignore ATTRIBUTE_UNUSED)2890 math_tanh (float arg1, float ignore ATTRIBUTE_UNUSED)
2891 {
2892   return (float) tanh (arg1);
2893 }
2894 
2895 /* Built-in substitution symbol functions and math functions.  */
2896 typedef struct
2897 {
2898   const char *name;
2899   int (*proc) (char *, char *);
2900   int nargs;
2901 } subsym_proc_entry;
2902 
2903 static const subsym_proc_entry subsym_procs[] =
2904 {
2905   /* Assembler built-in string substitution functions.  */
2906   { "$symlen", subsym_symlen, 1,  },
2907   { "$symcmp", subsym_symcmp, 2,  },
2908   { "$firstch", subsym_firstch, 2,  },
2909   { "$lastch", subsym_lastch, 2,  },
2910   { "$isdefed", subsym_isdefed, 1,  },
2911   { "$ismember", subsym_ismember, 2,  },
2912   { "$iscons", subsym_iscons, 1,  },
2913   { "$isname", subsym_isname, 1,  },
2914   { "$isreg", subsym_isreg, 1,  },
2915   { "$structsz", subsym_structsz, 1,  },
2916   { "$structacc", subsym_structacc, 1,  },
2917   { NULL, NULL, 0 },
2918 };
2919 
2920 typedef struct
2921 {
2922   const char *name;
2923   float (*proc) (float, float);
2924   int nargs;
2925   int int_return;
2926 } math_proc_entry;
2927 
2928 static const math_proc_entry math_procs[] =
2929 {
2930   /* Integer-returning built-in math functions.  */
2931   { "$cvi", math_cvi, 1, 1 },
2932   { "$int", math_int, 1, 1 },
2933   { "$sgn", math_sgn, 1, 1 },
2934 
2935   /* Float-returning built-in math functions.  */
2936   { "$acos", math_acos, 1, 0 },
2937   { "$asin", math_asin, 1, 0 },
2938   { "$atan", math_atan, 1, 0 },
2939   { "$atan2", math_atan2, 2, 0 },
2940   { "$ceil", math_ceil, 1, 0 },
2941   { "$cosh", math_cosh, 1, 0 },
2942   { "$cos", math_cos, 1, 0 },
2943   { "$cvf", math_cvf, 1, 0 },
2944   { "$exp", math_exp, 1, 0 },
2945   { "$fabs", math_fabs, 1, 0 },
2946   { "$floor", math_floor, 1, 0 },
2947   { "$fmod", math_fmod, 2, 0 },
2948   { "$ldexp", math_ldexp, 2, 0 },
2949   { "$log10", math_log10, 1, 0 },
2950   { "$log", math_log, 1, 0 },
2951   { "$max", math_max, 2, 0 },
2952   { "$min", math_min, 2, 0 },
2953   { "$pow", math_pow, 2, 0 },
2954   { "$round", math_round, 1, 0 },
2955   { "$sin", math_sin, 1, 0 },
2956   { "$sinh", math_sinh, 1, 0 },
2957   { "$sqrt", math_sqrt, 1, 0 },
2958   { "$tan", math_tan, 1, 0 },
2959   { "$tanh", math_tanh, 1, 0 },
2960   { "$trunc", math_trunc, 1, 0 },
2961   { NULL, NULL, 0, 0 },
2962 };
2963 
2964 void
md_begin(void)2965 md_begin (void)
2966 {
2967   insn_template *tm;
2968   const tic54x_symbol *sym;
2969   const subsym_proc_entry *subsym_proc;
2970   const math_proc_entry *math_proc;
2971   const char **symname;
2972   char *TIC54X_DIR = getenv ("TIC54X_DIR");
2973   char *A_DIR = TIC54X_DIR ? TIC54X_DIR : getenv ("A_DIR");
2974 
2975   local_label_id = 0;
2976 
2977   /* Look for A_DIR and add it to the include list.  */
2978   if (A_DIR != NULL)
2979     {
2980       char *tmp = xstrdup (A_DIR);
2981 
2982       do
2983 	{
2984 	  char *next = strchr (tmp, ';');
2985 
2986 	  if (next)
2987 	    *next++ = '\0';
2988 	  add_include_dir (tmp);
2989 	  tmp = next;
2990 	}
2991       while (tmp != NULL);
2992     }
2993 
2994   op_hash = str_htab_create ();
2995   for (tm = (insn_template *) tic54x_optab; tm->name; tm++)
2996     str_hash_insert (op_hash, tm->name, tm, 0);
2997 
2998   parop_hash = str_htab_create ();
2999   for (tm = (insn_template *) tic54x_paroptab; tm->name; tm++)
3000     str_hash_insert (parop_hash, tm->name, tm, 0);
3001 
3002   reg_hash = str_htab_create ();
3003   for (sym = tic54x_regs; sym->name; sym++)
3004     {
3005       /* Add basic registers to the symbol table.  */
3006       symbolS *symbolP = symbol_new (sym->name, absolute_section,
3007 				     &zero_address_frag, sym->value);
3008       SF_SET_LOCAL (symbolP);
3009       symbol_table_insert (symbolP);
3010       str_hash_insert (reg_hash, sym->name, sym, 0);
3011     }
3012   for (sym = tic54x_mmregs; sym->name; sym++)
3013     str_hash_insert (reg_hash, sym->name, sym, 0);
3014   mmreg_hash = str_htab_create ();
3015   for (sym = tic54x_mmregs; sym->name; sym++)
3016     str_hash_insert (mmreg_hash, sym->name, sym, 0);
3017 
3018   cc_hash = str_htab_create ();
3019   for (sym = tic54x_condition_codes; sym->name; sym++)
3020     str_hash_insert (cc_hash, sym->name, sym, 0);
3021 
3022   cc2_hash = str_htab_create ();
3023   for (sym = tic54x_cc2_codes; sym->name; sym++)
3024     str_hash_insert (cc2_hash, sym->name, sym, 0);
3025 
3026   cc3_hash = str_htab_create ();
3027   for (sym = tic54x_cc3_codes; sym->name; sym++)
3028     str_hash_insert (cc3_hash, sym->name, sym, 0);
3029 
3030   sbit_hash = str_htab_create ();
3031   for (sym = tic54x_status_bits; sym->name; sym++)
3032     str_hash_insert (sbit_hash, sym->name, sym, 0);
3033 
3034   misc_symbol_hash = str_htab_create ();
3035   for (symname = tic54x_misc_symbols; *symname; symname++)
3036     str_hash_insert (misc_symbol_hash, *symname, *symname, 0);
3037 
3038   /* Only the base substitution table and local label table are initialized;
3039      the others (for local macro substitution) get instantiated as needed.  */
3040   local_label_hash[0] = str_htab_create ();
3041   subsym_hash[0] = str_htab_create ();
3042   for (subsym_proc = subsym_procs; subsym_proc->name; subsym_proc++)
3043     str_hash_insert (subsym_hash[0], subsym_proc->name, subsym_proc, 0);
3044 
3045   math_hash = str_htab_create ();
3046   for (math_proc = math_procs; math_proc->name; math_proc++)
3047     {
3048       /* Insert into the main subsym hash for recognition; insert into
3049 	 the math hash to actually store information.  */
3050       str_hash_insert (subsym_hash[0], math_proc->name, math_proc, 0);
3051       str_hash_insert (math_hash, math_proc->name, math_proc, 0);
3052     }
3053   subsym_recurse_hash = str_htab_create ();
3054   stag_hash = str_htab_create ();
3055 }
3056 
3057 static int
is_accumulator(struct opstruct * operand)3058 is_accumulator (struct opstruct *operand)
3059 {
3060   return strcasecmp (operand->buf, "a") == 0
3061     || strcasecmp (operand->buf, "b") == 0;
3062 }
3063 
3064 /* Return the number of operands found, or -1 on error, copying the
3065    operands into the given array and the accompanying expressions into
3066    the next array.  */
3067 
3068 static int
get_operands(struct opstruct operands[],char * line)3069 get_operands (struct opstruct operands[], char *line)
3070 {
3071   char *lptr = line;
3072   int numexp = 0;
3073   int expecting_operand = 0;
3074   int i;
3075 
3076   while (numexp < MAX_OPERANDS && !is_end_of_line[(unsigned char) *lptr])
3077     {
3078       int paren_not_balanced = 0;
3079       char *op_start, *op_end;
3080 
3081       while (*lptr && ISSPACE (*lptr))
3082 	++lptr;
3083       op_start = lptr;
3084       while (paren_not_balanced || *lptr != ',')
3085 	{
3086 	  if (*lptr == '\0')
3087 	    {
3088 	      if (paren_not_balanced)
3089 		{
3090 		  as_bad (_("Unbalanced parenthesis in operand %d"), numexp);
3091 		  return -1;
3092 		}
3093 	      else
3094 		break;
3095 	    }
3096 	  if (*lptr == '(')
3097 	    ++paren_not_balanced;
3098 	  else if (*lptr == ')')
3099 	    --paren_not_balanced;
3100 	  ++lptr;
3101 	}
3102       op_end = lptr;
3103       if (op_end != op_start)
3104 	{
3105 	  int len = op_end - op_start;
3106 
3107 	  strncpy (operands[numexp].buf, op_start, len);
3108 	  operands[numexp].buf[len] = 0;
3109 	  /* Trim trailing spaces; while the preprocessor gets rid of most,
3110 	     there are weird usage patterns that can introduce them
3111 	     (i.e. using strings for macro args).  */
3112 	  while (len > 0 && ISSPACE (operands[numexp].buf[len - 1]))
3113 	    operands[numexp].buf[--len] = 0;
3114 	  lptr = op_end;
3115 	  ++numexp;
3116 	}
3117       else
3118 	{
3119 	  if (expecting_operand || *lptr == ',')
3120 	    {
3121 	      as_bad (_("Expecting operand after ','"));
3122 	      return -1;
3123 	    }
3124 	}
3125       if (*lptr == ',')
3126 	{
3127 	  if (*++lptr == '\0')
3128 	    {
3129 	      as_bad (_("Expecting operand after ','"));
3130 	      return -1;
3131 	    }
3132 	  expecting_operand = 1;
3133 	}
3134     }
3135 
3136   while (*lptr && ISSPACE (*lptr++))
3137     ;
3138   if (!is_end_of_line[(unsigned char) *lptr])
3139     {
3140       as_bad (_("Extra junk on line"));
3141       return -1;
3142     }
3143 
3144   /* OK, now parse them into expressions.  */
3145   for (i = 0; i < numexp; i++)
3146     {
3147       memset (&operands[i].exp, 0, sizeof (operands[i].exp));
3148       if (operands[i].buf[0] == '#')
3149 	{
3150 	  /* Immediate.  */
3151 	  parse_expression (operands[i].buf + 1, &operands[i].exp);
3152 	}
3153       else if (operands[i].buf[0] == '@')
3154 	{
3155 	  /* Direct notation.  */
3156 	  parse_expression (operands[i].buf + 1, &operands[i].exp);
3157 	}
3158       else if (operands[i].buf[0] == '*')
3159 	{
3160 	  /* Indirect.  */
3161 	  char *paren = strchr (operands[i].buf, '(');
3162 
3163 	  /* Allow immediate syntax in the inner expression.  */
3164 	  if (paren && paren[1] == '#')
3165 	    *++paren = '(';
3166 
3167 	  /* Pull out the lk expression or SP offset, if present.  */
3168 	  if (paren != NULL)
3169 	    {
3170 	      int len = strlen (paren);
3171 	      char *end = paren + len;
3172 	      int c;
3173 
3174 	      while (end[-1] != ')')
3175 		if (--end <= paren)
3176 		  {
3177 		    as_bad (_("Badly formed address expression"));
3178 		    return -1;
3179 		  }
3180 	      c = *end;
3181 	      *end = '\0';
3182 	      parse_expression (paren, &operands[i].exp);
3183 	      *end = c;
3184 	    }
3185 	  else
3186 	    operands[i].exp.X_op = O_absent;
3187 	}
3188       else
3189 	parse_expression (operands[i].buf, &operands[i].exp);
3190     }
3191 
3192   return numexp;
3193 }
3194 
3195 /* Predicates for different operand types.  */
3196 
3197 static int
is_immediate(struct opstruct * operand)3198 is_immediate (struct opstruct *operand)
3199 {
3200   return *operand->buf == '#';
3201 }
3202 
3203 /* This is distinguished from immediate because some numbers must be constants
3204    and must *not* have the '#' prefix.  */
3205 
3206 static int
is_absolute(struct opstruct * operand)3207 is_absolute (struct opstruct *operand)
3208 {
3209   return operand->exp.X_op == O_constant && !is_immediate (operand);
3210 }
3211 
3212 /* Is this an indirect operand?  */
3213 
3214 static int
is_indirect(struct opstruct * operand)3215 is_indirect (struct opstruct *operand)
3216 {
3217   return operand->buf[0] == '*';
3218 }
3219 
3220 /* Is this a valid dual-memory operand?  */
3221 
3222 static int
is_dual(struct opstruct * operand)3223 is_dual (struct opstruct *operand)
3224 {
3225   if (is_indirect (operand) && strncasecmp (operand->buf, "*ar", 3) == 0)
3226     {
3227       char *tmp = operand->buf + 3;
3228       int arf;
3229       int valid_mod;
3230 
3231       arf = *tmp++ - '0';
3232       /* Only allow *ARx, *ARx-, *ARx+, or *ARx+0%.  */
3233       valid_mod = *tmp == '\0' ||
3234 	strcasecmp (tmp, "-") == 0 ||
3235 	strcasecmp (tmp, "+") == 0 ||
3236 	strcasecmp (tmp, "+0%") == 0;
3237       return arf >= 2 && arf <= 5 && valid_mod;
3238     }
3239   return 0;
3240 }
3241 
3242 static int
is_mmreg(struct opstruct * operand)3243 is_mmreg (struct opstruct *operand)
3244 {
3245   return (is_absolute (operand)
3246 	  || is_immediate (operand)
3247 	  || str_hash_find (mmreg_hash, operand->buf) != 0);
3248 }
3249 
3250 static int
is_type(struct opstruct * operand,enum optype type)3251 is_type (struct opstruct *operand, enum optype type)
3252 {
3253   switch (type)
3254     {
3255     case OP_None:
3256       return operand->buf[0] == 0;
3257     case OP_Xmem:
3258     case OP_Ymem:
3259       return is_dual (operand);
3260     case OP_Sind:
3261       return is_indirect (operand);
3262     case OP_xpmad_ms7:
3263       /* This one *must* be immediate.  */
3264       return is_immediate (operand);
3265     case OP_xpmad:
3266     case OP_pmad:
3267     case OP_PA:
3268     case OP_dmad:
3269     case OP_Lmem:
3270     case OP_MMR:
3271       return 1;
3272     case OP_Smem:
3273       /* Address may be a numeric, indirect, or an expression.  */
3274       return !is_immediate (operand);
3275     case OP_MMRY:
3276     case OP_MMRX:
3277       return is_mmreg (operand);
3278     case OP_SRC:
3279     case OP_SRC1:
3280     case OP_RND:
3281     case OP_DST:
3282       return is_accumulator (operand);
3283     case OP_B:
3284       return is_accumulator (operand) && TOUPPER (operand->buf[0]) == 'B';
3285     case OP_A:
3286       return is_accumulator (operand) && TOUPPER (operand->buf[0]) == 'A';
3287     case OP_ARX:
3288       return strncasecmp ("ar", operand->buf, 2) == 0
3289 	&& ISDIGIT (operand->buf[2]);
3290     case OP_SBIT:
3291       return str_hash_find (sbit_hash, operand->buf) != 0 || is_absolute (operand);
3292     case OP_CC:
3293       return str_hash_find (cc_hash, operand->buf) != 0;
3294     case OP_CC2:
3295       return str_hash_find (cc2_hash, operand->buf) != 0;
3296     case OP_CC3:
3297       return str_hash_find (cc3_hash, operand->buf) != 0
3298 	|| is_immediate (operand) || is_absolute (operand);
3299     case OP_16:
3300       return (is_immediate (operand) || is_absolute (operand))
3301 	&& operand->exp.X_add_number == 16;
3302     case OP_N:
3303       /* Allow st0 or st1 instead of a numeric.  */
3304       return is_absolute (operand) || is_immediate (operand) ||
3305 	strcasecmp ("st0", operand->buf) == 0 ||
3306 	strcasecmp ("st1", operand->buf) == 0;
3307     case OP_12:
3308     case OP_123:
3309       return is_absolute (operand) || is_immediate (operand);
3310     case OP_SHFT:
3311       return (is_immediate (operand) || is_absolute (operand))
3312 	&& operand->exp.X_add_number >= 0 && operand->exp.X_add_number < 16;
3313     case OP_SHIFT:
3314       /* Let this one catch out-of-range values.  */
3315       return (is_immediate (operand) || is_absolute (operand))
3316 	&& operand->exp.X_add_number != 16;
3317     case OP_BITC:
3318     case OP_031:
3319     case OP_k8:
3320       return is_absolute (operand) || is_immediate (operand);
3321     case OP_k8u:
3322       return is_immediate (operand)
3323 	&& operand->exp.X_op == O_constant
3324 	&& operand->exp.X_add_number >= 0
3325 	&& operand->exp.X_add_number < 256;
3326     case OP_lk:
3327     case OP_lku:
3328       /* Allow anything; assumes opcodes are ordered with Smem operands
3329 	 versions first.  */
3330       return 1;
3331     case OP_k5:
3332     case OP_k3:
3333     case OP_k9:
3334       /* Just make sure it's an integer; check range later.  */
3335       return is_immediate (operand);
3336     case OP_T:
3337       return strcasecmp ("t", operand->buf) == 0 ||
3338 	strcasecmp ("treg", operand->buf) == 0;
3339     case OP_TS:
3340       return strcasecmp ("ts", operand->buf) == 0;
3341     case OP_ASM:
3342       return strcasecmp ("asm", operand->buf) == 0;
3343     case OP_TRN:
3344       return strcasecmp ("trn", operand->buf) == 0;
3345     case OP_DP:
3346       return strcasecmp ("dp", operand->buf) == 0;
3347     case OP_ARP:
3348       return strcasecmp ("arp", operand->buf) == 0;
3349     default:
3350       return 0;
3351     }
3352 }
3353 
3354 static int
operands_match(tic54x_insn * insn,struct opstruct * operands,int opcount,const enum optype * refoptype,int minops,int maxops)3355 operands_match (tic54x_insn *insn,
3356 		struct opstruct *operands,
3357 		int opcount,
3358 		const enum optype *refoptype,
3359 		int minops,
3360 		int maxops)
3361 {
3362   int op = 0, refop = 0;
3363 
3364   if (opcount == 0 && minops == 0)
3365     return 1;
3366 
3367   while (op <= maxops && refop <= maxops)
3368     {
3369       while (!is_type (&operands[op], OPTYPE (refoptype[refop])))
3370 	{
3371 	  /* Skip an optional template operand if it doesn't agree
3372 	     with the current operand.  */
3373 	  if (refoptype[refop] & OPT)
3374 	    {
3375 	      ++refop;
3376 	      --maxops;
3377 	      if (refop > maxops)
3378 		return 0;
3379 	    }
3380 	  else
3381 	    return 0;
3382 	}
3383 
3384       /* Save the actual operand type for later use.  */
3385       operands[op].type = OPTYPE (refoptype[refop]);
3386       ++refop;
3387       ++op;
3388       /* Have we matched them all yet?  */
3389       if (op == opcount)
3390 	{
3391 	  while (op < maxops)
3392 	    {
3393 	      /* If a later operand is *not* optional, no match.  */
3394 	      if ((refoptype[refop] & OPT) == 0)
3395 		return 0;
3396 	      /* Flag any implicit default OP_DST operands so we know to add
3397 		 them explicitly when encoding the operand later.  */
3398 	      if (OPTYPE (refoptype[refop]) == OP_DST)
3399 		insn->using_default_dst = 1;
3400 	      ++refop;
3401 	      ++op;
3402 	    }
3403 
3404 	  return 1;
3405 	}
3406     }
3407 
3408   return 0;
3409 }
3410 
3411 /* 16-bit direct memory address
3412    Explicit dmad operands are always in last word of insn (usually second
3413    word, but bumped to third if lk addressing is used)
3414 
3415    We allow *(dmad) notation because the TI assembler allows it.
3416 
3417    XPC_CODE:
3418    0 for 16-bit addresses
3419    1 for full 23-bit addresses
3420    2 for the upper 7 bits of a 23-bit address (LDX).  */
3421 
3422 static int
encode_dmad(tic54x_insn * insn,struct opstruct * operand,int xpc_code)3423 encode_dmad (tic54x_insn *insn, struct opstruct *operand, int xpc_code)
3424 {
3425   int op = 1 + insn->is_lkaddr;
3426 
3427   /* Only allow *(dmad) expressions; all others are invalid.  */
3428   if (is_indirect (operand) && operand->buf[strlen (operand->buf) - 1] != ')')
3429     {
3430       as_bad (_("Invalid dmad syntax '%s'"), operand->buf);
3431       return 0;
3432     }
3433 
3434   insn->opcode[op].addr_expr = operand->exp;
3435 
3436   if (insn->opcode[op].addr_expr.X_op == O_constant)
3437     {
3438       valueT value = insn->opcode[op].addr_expr.X_add_number;
3439 
3440       if (xpc_code == 1)
3441 	{
3442 	  insn->opcode[0].word &= 0xFF80;
3443 	  insn->opcode[0].word |= (value >> 16) & 0x7F;
3444 	  insn->opcode[1].word = value & 0xFFFF;
3445 	}
3446       else if (xpc_code == 2)
3447 	insn->opcode[op].word = (value >> 16) & 0xFFFF;
3448       else
3449 	insn->opcode[op].word = value;
3450     }
3451   else
3452     {
3453       /* Do the fixup later; just store the expression.  */
3454       insn->opcode[op].word = 0;
3455       insn->opcode[op].r_nchars = 2;
3456 
3457       if (amode == c_mode)
3458 	insn->opcode[op].r_type = BFD_RELOC_TIC54X_16_OF_23;
3459       else if (xpc_code == 1)
3460 	{
3461 	  /* This relocation spans two words, so adjust accordingly.  */
3462 	  insn->opcode[0].addr_expr = operand->exp;
3463 	  insn->opcode[0].r_type = BFD_RELOC_TIC54X_23;
3464 	  insn->opcode[0].r_nchars = 4;
3465 	  insn->opcode[0].unresolved = 1;
3466 	  /* It's really 2 words, but we want to stop encoding after the
3467 	     first, since we must encode both words at once.  */
3468 	  insn->words = 1;
3469 	}
3470       else if (xpc_code == 2)
3471 	insn->opcode[op].r_type = BFD_RELOC_TIC54X_MS7_OF_23;
3472       else
3473 	insn->opcode[op].r_type = BFD_RELOC_TIC54X_16_OF_23;
3474 
3475       insn->opcode[op].unresolved = 1;
3476     }
3477 
3478   return 1;
3479 }
3480 
3481 /* 7-bit direct address encoding.  */
3482 
3483 static int
encode_address(tic54x_insn * insn,struct opstruct * operand)3484 encode_address (tic54x_insn *insn, struct opstruct *operand)
3485 {
3486   /* Assumes that dma addresses are *always* in word 0 of the opcode.  */
3487   insn->opcode[0].addr_expr = operand->exp;
3488 
3489   if (operand->exp.X_op == O_constant)
3490     insn->opcode[0].word |= (operand->exp.X_add_number & 0x7F);
3491   else
3492     {
3493       if (operand->exp.X_op == O_register)
3494         as_bad (_("Use the .mmregs directive to use memory-mapped register names such as '%s'"), operand->buf);
3495       /* Do the fixup later; just store the expression.  */
3496       insn->opcode[0].r_nchars = 1;
3497       insn->opcode[0].r_type = BFD_RELOC_TIC54X_PARTLS7;
3498       insn->opcode[0].unresolved = 1;
3499     }
3500 
3501   return 1;
3502 }
3503 
3504 static int
encode_indirect(tic54x_insn * insn,struct opstruct * operand)3505 encode_indirect (tic54x_insn *insn, struct opstruct *operand)
3506 {
3507   int arf;
3508   int mod;
3509 
3510   if (insn->is_lkaddr)
3511     {
3512       /* lk addresses always go in the second insn word.  */
3513       mod = ((TOUPPER (operand->buf[1]) == 'A') ? 12 :
3514 	     (operand->buf[1] == '(') ? 15 :
3515 	     (strchr (operand->buf, '%') != NULL) ? 14 : 13);
3516       arf = ((mod == 12) ? operand->buf[3] - '0' :
3517 	     (mod == 15) ? 0 : operand->buf[4] - '0');
3518 
3519       insn->opcode[1].addr_expr = operand->exp;
3520 
3521       if (operand->exp.X_op == O_constant)
3522 	insn->opcode[1].word = operand->exp.X_add_number;
3523       else
3524 	{
3525 	  insn->opcode[1].word = 0;
3526 	  insn->opcode[1].r_nchars = 2;
3527 	  insn->opcode[1].r_type = BFD_RELOC_TIC54X_16_OF_23;
3528 	  insn->opcode[1].unresolved = 1;
3529 	}
3530     }
3531   else if (strncasecmp (operand->buf, "*sp (", 4) == 0)
3532     {
3533       /* Stack offsets look the same as 7-bit direct addressing.  */
3534       return encode_address (insn, operand);
3535     }
3536   else
3537     {
3538       arf = (TOUPPER (operand->buf[1]) == 'A' ?
3539 	     operand->buf[3] : operand->buf[4]) - '0';
3540 
3541       if (operand->buf[1] == '+')
3542 	{
3543 	  mod = 3;		    /* *+ARx  */
3544 	  if (insn->tm->flags & FL_SMR)
3545 	    as_warn (_("Address mode *+ARx is write-only. "
3546 		       "Results of reading are undefined."));
3547 	}
3548       else if (operand->buf[4] == '\0')
3549 	mod = 0;		    /* *ARx  */
3550       else if (operand->buf[5] == '\0')
3551 	mod = (operand->buf[4] == '-' ? 1 : 2); /* *ARx+ / *ARx-  */
3552       else if (operand->buf[6] == '\0')
3553 	{
3554 	  if (operand->buf[5] == '0')
3555 	    mod = (operand->buf[4] == '-' ? 5 : 6); /* *ARx+0 / *ARx-0  */
3556 	  else
3557 	    mod = (operand->buf[4] == '-' ? 8 : 10);/* *ARx+% / *ARx-%  */
3558 	}
3559       else if (TOUPPER (operand->buf[6]) == 'B')
3560 	mod = (operand->buf[4] == '-' ? 4 : 7); /* ARx+0B / *ARx-0B  */
3561       else if (TOUPPER (operand->buf[6]) == '%')
3562 	mod = (operand->buf[4] == '-' ? 9 : 11); /* ARx+0% / *ARx - 0%  */
3563       else
3564 	{
3565 	  as_bad (_("Unrecognized indirect address format \"%s\""),
3566 		  operand->buf);
3567 	  return 0;
3568 	}
3569     }
3570 
3571   insn->opcode[0].word |= 0x80 | (mod << 3) | arf;
3572 
3573   return 1;
3574 }
3575 
3576 static int
encode_integer(tic54x_insn * insn,struct opstruct * operand,int which,int min,int max,unsigned short mask)3577 encode_integer (tic54x_insn *insn,
3578 		struct opstruct *operand,
3579 		int which,
3580 		int min,
3581 		int max,
3582 		unsigned short mask)
3583 {
3584   long parse, integer;
3585 
3586   insn->opcode[which].addr_expr = operand->exp;
3587 
3588   if (operand->exp.X_op == O_constant)
3589     {
3590       parse = operand->exp.X_add_number;
3591       /* Hack -- fixup for 16-bit hex quantities that get converted positive
3592 	 instead of negative.  */
3593       if ((parse & 0x8000) && min == -32768 && max == 32767)
3594 	integer = (short) parse;
3595       else
3596 	integer = parse;
3597 
3598       if (integer >= min && integer <= max)
3599 	{
3600 	  insn->opcode[which].word |= (integer & mask);
3601 	  return 1;
3602 	}
3603       as_bad (_("Operand '%s' out of range (%d <= x <= %d)"),
3604 	      operand->buf, min, max);
3605     }
3606   else
3607     {
3608       if (insn->opcode[which].addr_expr.X_op == O_constant)
3609 	{
3610 	  insn->opcode[which].word |=
3611 	    insn->opcode[which].addr_expr.X_add_number & mask;
3612 	}
3613       else
3614 	{
3615 	  /* Do the fixup later; just store the expression.  */
3616 	  bfd_reloc_code_real_type rtype =
3617 	    (mask == 0x1FF ? BFD_RELOC_TIC54X_PARTMS9 :
3618 	     mask == 0xFFFF ? BFD_RELOC_TIC54X_16_OF_23 :
3619 	     mask == 0x7F ? BFD_RELOC_TIC54X_PARTLS7 : BFD_RELOC_8);
3620 	  int size = (mask == 0x1FF || mask == 0xFFFF) ? 2 : 1;
3621 
3622 	  if (rtype == BFD_RELOC_8)
3623 	    as_bad (_("Error in relocation handling"));
3624 
3625 	  insn->opcode[which].r_nchars = size;
3626 	  insn->opcode[which].r_type = rtype;
3627 	  insn->opcode[which].unresolved = 1;
3628 	}
3629 
3630       return 1;
3631     }
3632 
3633   return 0;
3634 }
3635 
3636 static int
encode_condition(tic54x_insn * insn,struct opstruct * operand)3637 encode_condition (tic54x_insn *insn, struct opstruct *operand)
3638 {
3639   tic54x_symbol *cc = (tic54x_symbol *) str_hash_find (cc_hash, operand->buf);
3640   if (!cc)
3641     {
3642       as_bad (_("Unrecognized condition code \"%s\""), operand->buf);
3643       return 0;
3644     }
3645 #define CC_GROUP 0x40
3646 #define CC_ACC   0x08
3647 #define CATG_A1  0x07
3648 #define CATG_B1  0x30
3649 #define CATG_A2  0x30
3650 #define CATG_B2  0x0C
3651 #define CATG_C2  0x03
3652   /* Disallow group 1 conditions mixed with group 2 conditions
3653      if group 1, allow only one category A and one category B
3654      if group 2, allow only one each of category A, B, and C.  */
3655   if (((insn->opcode[0].word & 0xFF) != 0))
3656     {
3657       if ((insn->opcode[0].word & CC_GROUP) != (cc->value & CC_GROUP))
3658 	{
3659 	  as_bad (_("Condition \"%s\" does not match preceding group"),
3660 		  operand->buf);
3661 	  return 0;
3662 	}
3663       if (insn->opcode[0].word & CC_GROUP)
3664 	{
3665 	  if ((insn->opcode[0].word & CC_ACC) != (cc->value & CC_ACC))
3666 	    {
3667 	      as_bad (_("Condition \"%s\" uses a different accumulator from "
3668 			"a preceding condition"),
3669 		      operand->buf);
3670 	      return 0;
3671 	    }
3672 	  if ((insn->opcode[0].word & CATG_A1) && (cc->value & CATG_A1))
3673 	    {
3674 	      as_bad (_("Only one comparison conditional allowed"));
3675 	      return 0;
3676 	    }
3677 	  if ((insn->opcode[0].word & CATG_B1) && (cc->value & CATG_B1))
3678 	    {
3679 	      as_bad (_("Only one overflow conditional allowed"));
3680 	      return 0;
3681 	    }
3682 	}
3683       else if (   ((insn->opcode[0].word & CATG_A2) && (cc->value & CATG_A2))
3684 	       || ((insn->opcode[0].word & CATG_B2) && (cc->value & CATG_B2))
3685 	       || ((insn->opcode[0].word & CATG_C2) && (cc->value & CATG_C2)))
3686 	{
3687 	  as_bad (_("Duplicate %s conditional"), operand->buf);
3688 	  return 0;
3689 	}
3690     }
3691 
3692   insn->opcode[0].word |= cc->value;
3693   return 1;
3694 }
3695 
3696 static int
encode_cc3(tic54x_insn * insn,struct opstruct * operand)3697 encode_cc3 (tic54x_insn *insn, struct opstruct *operand)
3698 {
3699   tic54x_symbol *cc3 = (tic54x_symbol *) str_hash_find (cc3_hash, operand->buf);
3700   int value = cc3 ? cc3->value : operand->exp.X_add_number << 8;
3701 
3702   if ((value & 0x0300) != value)
3703     {
3704       as_bad (_("Unrecognized condition code \"%s\""), operand->buf);
3705       return 0;
3706     }
3707   insn->opcode[0].word |= value;
3708   return 1;
3709 }
3710 
3711 static int
encode_arx(tic54x_insn * insn,struct opstruct * operand)3712 encode_arx (tic54x_insn *insn, struct opstruct *operand)
3713 {
3714   int arf = strlen (operand->buf) >= 3 ? operand->buf[2] - '0' : -1;
3715 
3716   if (strncasecmp ("ar", operand->buf, 2) || arf < 0 || arf > 7)
3717     {
3718       as_bad (_("Invalid auxiliary register (use AR0-AR7)"));
3719       return 0;
3720     }
3721   insn->opcode[0].word |= arf;
3722   return 1;
3723 }
3724 
3725 static int
encode_cc2(tic54x_insn * insn,struct opstruct * operand)3726 encode_cc2 (tic54x_insn *insn, struct opstruct *operand)
3727 {
3728   tic54x_symbol *cc2 = (tic54x_symbol *) str_hash_find (cc2_hash, operand->buf);
3729 
3730   if (!cc2)
3731     {
3732       as_bad (_("Unrecognized condition code \"%s\""), operand->buf);
3733       return 0;
3734     }
3735   insn->opcode[0].word |= cc2->value;
3736   return 1;
3737 }
3738 
3739 static int
encode_operand(tic54x_insn * insn,enum optype type,struct opstruct * operand)3740 encode_operand (tic54x_insn *insn, enum optype type, struct opstruct *operand)
3741 {
3742   int ext = (insn->tm->flags & FL_EXT) != 0;
3743 
3744   if (type == OP_MMR && operand->exp.X_op != O_constant)
3745     {
3746       /* Disallow long-constant addressing for memory-mapped addressing.  */
3747       if (insn->is_lkaddr)
3748 	{
3749 	  as_bad (_("lk addressing modes are invalid for memory-mapped "
3750 		    "register addressing"));
3751 	  return 0;
3752 	}
3753       type = OP_Smem;
3754       /* Warn about *+ARx when used with MMR operands.  */
3755       if (strncasecmp (operand->buf, "*+ar", 4) == 0)
3756 	{
3757 	  as_warn (_("Address mode *+ARx is not allowed in memory-mapped "
3758 		     "register addressing.  Resulting behavior is "
3759 		     "undefined."));
3760 	}
3761     }
3762 
3763   switch (type)
3764     {
3765     case OP_None:
3766       return 1;
3767     case OP_dmad:
3768       /* 16-bit immediate value.  */
3769       return encode_dmad (insn, operand, 0);
3770     case OP_SRC:
3771       if (TOUPPER (*operand->buf) == 'B')
3772 	{
3773 	  insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1 << 9);
3774 	  if (insn->using_default_dst)
3775 	    insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1 << 8);
3776 	}
3777       return 1;
3778     case OP_RND:
3779       /* Make sure this agrees with the OP_DST operand.  */
3780       if (!((TOUPPER (operand->buf[0]) == 'B') ^
3781 	    ((insn->opcode[0].word & (1 << 8)) != 0)))
3782 	{
3783 	  as_bad (_("Destination accumulator for each part of this parallel "
3784 		    "instruction must be different"));
3785 	  return 0;
3786 	}
3787       return 1;
3788     case OP_SRC1:
3789     case OP_DST:
3790       if (TOUPPER (operand->buf[0]) == 'B')
3791 	insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1 << 8);
3792       return 1;
3793     case OP_Xmem:
3794     case OP_Ymem:
3795       {
3796 	int mod = (operand->buf[4] == '\0' ? 0 : /* *arx  */
3797 		   operand->buf[4] == '-' ? 1 : /* *arx-  */
3798 		   operand->buf[5] == '\0' ? 2 : 3); /* *arx+, *arx+0%  */
3799 	int arf = operand->buf[3] - '0' - 2;
3800 	int code = (mod << 2) | arf;
3801 	insn->opcode[0].word |= (code << (type == OP_Xmem ? 4 : 0));
3802 	return 1;
3803       }
3804     case OP_Lmem:
3805     case OP_Smem:
3806       if (!is_indirect (operand))
3807 	return encode_address (insn, operand);
3808       /* Fall through.  */
3809     case OP_Sind:
3810       return encode_indirect (insn, operand);
3811     case OP_xpmad_ms7:
3812       return encode_dmad (insn, operand, 2);
3813     case OP_xpmad:
3814       return encode_dmad (insn, operand, 1);
3815     case OP_PA:
3816     case OP_pmad:
3817       return encode_dmad (insn, operand, 0);
3818     case OP_ARX:
3819       return encode_arx (insn, operand);
3820     case OP_MMRX:
3821     case OP_MMRY:
3822     case OP_MMR:
3823       {
3824 	int value = operand->exp.X_add_number;
3825 
3826 	if (type == OP_MMR)
3827 	  insn->opcode[0].word |= value;
3828 	else
3829 	  {
3830 	    if (value < 16 || value > 24)
3831 	      {
3832 		as_bad (_("Memory mapped register \"%s\" out of range"),
3833 			operand->buf);
3834 		return 0;
3835 	      }
3836 	    if (type == OP_MMRX)
3837 	      insn->opcode[0].word |= (value - 16) << 4;
3838 	    else
3839 	      insn->opcode[0].word |= (value - 16);
3840 	  }
3841 	return 1;
3842       }
3843     case OP_B:
3844     case OP_A:
3845       return 1;
3846     case OP_SHFT:
3847       return encode_integer (insn, operand, ext + insn->is_lkaddr,
3848 			     0, 15, 0xF);
3849     case OP_SHIFT:
3850       return encode_integer (insn, operand, ext + insn->is_lkaddr,
3851 			     -16, 15, 0x1F);
3852     case OP_lk:
3853       return encode_integer (insn, operand, 1 + insn->is_lkaddr,
3854 			     -32768, 32767, 0xFFFF);
3855     case OP_CC:
3856       return encode_condition (insn, operand);
3857     case OP_CC2:
3858       return encode_cc2 (insn, operand);
3859     case OP_CC3:
3860       return encode_cc3 (insn, operand);
3861     case OP_BITC:
3862       return encode_integer (insn, operand, 0, 0, 15, 0xF);
3863     case OP_k8:
3864       return encode_integer (insn, operand, 0, -128, 127, 0xFF);
3865     case OP_123:
3866       {
3867 	int value = operand->exp.X_add_number;
3868 	int code;
3869 	if (value < 1 || value > 3)
3870 	  {
3871 	    as_bad (_("Invalid operand (use 1, 2, or 3)"));
3872 	    return 0;
3873 	  }
3874 	code = value == 1 ? 0 : value == 2 ? 0x2 : 0x1;
3875 	insn->opcode[0].word |= (code << 8);
3876 	return 1;
3877       }
3878     case OP_031:
3879       return encode_integer (insn, operand, 0, 0, 31, 0x1F);
3880     case OP_k8u:
3881       return encode_integer (insn, operand, 0, 0, 255, 0xFF);
3882     case OP_lku:
3883       return encode_integer (insn, operand, 1 + insn->is_lkaddr,
3884 			     0, 65535, 0xFFFF);
3885     case OP_SBIT:
3886       {
3887 	tic54x_symbol *sbit = (tic54x_symbol *)
3888 	  str_hash_find (sbit_hash, operand->buf);
3889 	int value = is_absolute (operand) ?
3890 	  operand->exp.X_add_number : (sbit ? sbit->value : -1);
3891 	int reg = 0;
3892 
3893 	if (insn->opcount == 1)
3894 	  {
3895 	    if (!sbit)
3896 	      {
3897 		as_bad (_("A status register or status bit name is required"));
3898 		return 0;
3899 	      }
3900 	    /* Guess the register based on the status bit; "ovb" is the last
3901 	       status bit defined for st0.  */
3902 	    if (sbit > (tic54x_symbol *) str_hash_find (sbit_hash, "ovb"))
3903 	      reg = 1;
3904 	  }
3905 	if (value == -1)
3906 	  {
3907 	    as_bad (_("Unrecognized status bit \"%s\""), operand->buf);
3908 	    return 0;
3909 	  }
3910 	insn->opcode[0].word |= value;
3911 	insn->opcode[0].word |= (reg << 9);
3912 	return 1;
3913       }
3914     case OP_N:
3915       if (strcasecmp (operand->buf, "st0") == 0
3916 	  || strcasecmp (operand->buf, "st1") == 0)
3917 	{
3918 	  insn->opcode[0].word |=
3919 	    ((unsigned short) (operand->buf[2] - '0')) << 9;
3920 	  return 1;
3921 	}
3922       else if (operand->exp.X_op == O_constant
3923 	       && (operand->exp.X_add_number == 0
3924 		   || operand->exp.X_add_number == 1))
3925 	{
3926 	  insn->opcode[0].word |=
3927 	    ((unsigned short) (operand->exp.X_add_number)) << 9;
3928 	  return 1;
3929 	}
3930       as_bad (_("Invalid status register \"%s\""), operand->buf);
3931       return 0;
3932     case OP_k5:
3933       return encode_integer (insn, operand, 0, -16, 15, 0x1F);
3934     case OP_k3:
3935       return encode_integer (insn, operand, 0, 0, 7, 0x7);
3936     case OP_k9:
3937       return encode_integer (insn, operand, 0, 0, 0x1FF, 0x1FF);
3938     case OP_12:
3939       if (operand->exp.X_add_number != 1
3940 	  && operand->exp.X_add_number != 2)
3941 	{
3942 	  as_bad (_("Operand \"%s\" out of range (use 1 or 2)"), operand->buf);
3943 	  return 0;
3944 	}
3945       insn->opcode[0].word |= (operand->exp.X_add_number - 1) << 9;
3946       return 1;
3947     case OP_16:
3948     case OP_T:
3949     case OP_TS:
3950     case OP_ASM:
3951     case OP_TRN:
3952     case OP_DP:
3953     case OP_ARP:
3954       /* No encoding necessary.  */
3955       return 1;
3956     default:
3957       return 0;
3958     }
3959 
3960   return 1;
3961 }
3962 
3963 static void
emit_insn(tic54x_insn * insn)3964 emit_insn (tic54x_insn *insn)
3965 {
3966   int i;
3967   flagword oldflags = bfd_section_flags (now_seg);
3968   flagword flags = oldflags | SEC_CODE;
3969 
3970   if (!bfd_set_section_flags (now_seg, flags))
3971         as_warn (_("error setting flags for \"%s\": %s"),
3972                  bfd_section_name (now_seg),
3973                  bfd_errmsg (bfd_get_error ()));
3974 
3975   for (i = 0; i < insn->words; i++)
3976     {
3977       int size = (insn->opcode[i].unresolved
3978 		  && insn->opcode[i].r_type == BFD_RELOC_TIC54X_23) ? 4 : 2;
3979       char *p = frag_more (size);
3980 
3981       if (size == 2)
3982 	md_number_to_chars (p, (valueT) insn->opcode[i].word, 2);
3983       else
3984 	md_number_to_chars (p, (valueT) insn->opcode[i].word << 16, 4);
3985 
3986       if (insn->opcode[i].unresolved)
3987 	fix_new_exp (frag_now, p - frag_now->fr_literal,
3988 		     insn->opcode[i].r_nchars, &insn->opcode[i].addr_expr,
3989 		     false, insn->opcode[i].r_type);
3990     }
3991 }
3992 
3993 /* Convert the operand strings into appropriate opcode values
3994    return the total number of words used by the instruction.  */
3995 
3996 static int
build_insn(tic54x_insn * insn)3997 build_insn (tic54x_insn *insn)
3998 {
3999   int i;
4000 
4001   /* Only non-parallel instructions support lk addressing.  */
4002   if (!(insn->tm->flags & FL_PAR))
4003     {
4004       for (i = 0; i < insn->opcount; i++)
4005 	{
4006 	  if ((OPTYPE (insn->operands[i].type) == OP_Smem
4007 	       || OPTYPE (insn->operands[i].type) == OP_Lmem
4008 	       || OPTYPE (insn->operands[i].type) == OP_Sind)
4009 	      && strchr (insn->operands[i].buf, '(')
4010 	      /* Don't mistake stack-relative addressing for lk addressing.  */
4011 	      && strncasecmp (insn->operands[i].buf, "*sp (", 4) != 0)
4012 	    {
4013 	      insn->is_lkaddr = 1;
4014 	      insn->lkoperand = i;
4015 	      break;
4016 	    }
4017 	}
4018     }
4019   insn->words = insn->tm->words + insn->is_lkaddr;
4020 
4021   insn->opcode[0].word = insn->tm->opcode;
4022   if (insn->tm->flags & FL_EXT)
4023     insn->opcode[1 + insn->is_lkaddr].word = insn->tm->opcode2;
4024 
4025   for (i = 0; i < insn->opcount; i++)
4026     {
4027       enum optype type = insn->operands[i].type;
4028 
4029       if (!encode_operand (insn, type, &insn->operands[i]))
4030 	return 0;
4031     }
4032   if (insn->tm->flags & FL_PAR)
4033     for (i = 0; i < insn->paropcount; i++)
4034       {
4035 	enum optype partype = insn->paroperands[i].type;
4036 
4037 	if (!encode_operand (insn, partype, &insn->paroperands[i]))
4038 	  return 0;
4039       }
4040 
4041   emit_insn (insn);
4042 
4043   return insn->words;
4044 }
4045 
4046 static int
optimize_insn(tic54x_insn * insn)4047 optimize_insn (tic54x_insn *insn)
4048 {
4049   /* Optimize some instructions, helping out the brain-dead programmer.  */
4050 #define is_zero(op) ((op).exp.X_op == O_constant && (op).exp.X_add_number == 0)
4051   if (strcasecmp (insn->tm->name, "add") == 0)
4052     {
4053       if (insn->opcount > 1
4054 	  && is_accumulator (&insn->operands[insn->opcount - 2])
4055 	  && is_accumulator (&insn->operands[insn->opcount - 1])
4056 	  && strcasecmp (insn->operands[insn->opcount - 2].buf,
4057 			 insn->operands[insn->opcount - 1].buf) == 0)
4058 	{
4059 	  --insn->opcount;
4060 	  insn->using_default_dst = 1;
4061 	  return 1;
4062 	}
4063 
4064       /* Try to collapse if Xmem and shift count is zero.  */
4065       if ((OPTYPE (insn->tm->operand_types[0]) == OP_Xmem
4066 	   && OPTYPE (insn->tm->operand_types[1]) == OP_SHFT
4067 	   && is_zero (insn->operands[1]))
4068 	  /* Or if Smem, shift is zero or absent, and SRC == DST.  */
4069 	  || (OPTYPE (insn->tm->operand_types[0]) == OP_Smem
4070 	      && OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT
4071 	      && is_type (&insn->operands[1], OP_SHIFT)
4072 	      && is_zero (insn->operands[1]) && insn->opcount == 3))
4073 	{
4074 	  insn->operands[1] = insn->operands[2];
4075 	  insn->opcount = 2;
4076 	  return 1;
4077 	}
4078     }
4079   else if (strcasecmp (insn->tm->name, "ld") == 0)
4080     {
4081       if (insn->opcount == 3 && insn->operands[0].type != OP_SRC)
4082 	{
4083 	  if ((OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT
4084 	       || OPTYPE (insn->tm->operand_types[1]) == OP_SHFT)
4085 	      && is_zero (insn->operands[1])
4086 	      && (OPTYPE (insn->tm->operand_types[0]) != OP_lk
4087 		  || (insn->operands[0].exp.X_op == O_constant
4088 		      && insn->operands[0].exp.X_add_number <= 255
4089 		      && insn->operands[0].exp.X_add_number >= 0)))
4090 	    {
4091 	      insn->operands[1] = insn->operands[2];
4092 	      insn->opcount = 2;
4093 	      return 1;
4094 	    }
4095 	}
4096     }
4097   else if (strcasecmp (insn->tm->name, "sth") == 0
4098 	   || strcasecmp (insn->tm->name, "stl") == 0)
4099     {
4100       if ((OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT
4101 	   || OPTYPE (insn->tm->operand_types[1]) == OP_SHFT)
4102 	  && is_zero (insn->operands[1]))
4103 	{
4104 	  insn->operands[1] = insn->operands[2];
4105 	  insn->opcount = 2;
4106 	  return 1;
4107 	}
4108     }
4109   else if (strcasecmp (insn->tm->name, "sub") == 0)
4110     {
4111       if (insn->opcount > 1
4112 	  && is_accumulator (&insn->operands[insn->opcount - 2])
4113 	  && is_accumulator (&insn->operands[insn->opcount - 1])
4114 	  && strcasecmp (insn->operands[insn->opcount - 2].buf,
4115 			 insn->operands[insn->opcount - 1].buf) == 0)
4116 	{
4117 	  --insn->opcount;
4118 	  insn->using_default_dst = 1;
4119 	  return 1;
4120 	}
4121 
4122       if (   ((OPTYPE (insn->tm->operand_types[0]) == OP_Smem
4123 	    && OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT)
4124 	   || (OPTYPE (insn->tm->operand_types[0]) == OP_Xmem
4125 	    && OPTYPE (insn->tm->operand_types[1]) == OP_SHFT))
4126 	  && is_zero (insn->operands[1])
4127 	  && insn->opcount == 3)
4128 	{
4129 	  insn->operands[1] = insn->operands[2];
4130 	  insn->opcount = 2;
4131 	  return 1;
4132 	}
4133     }
4134   return 0;
4135 }
4136 
4137 /* Find a matching template if possible, and get the operand strings.  */
4138 
4139 static int
tic54x_parse_insn(tic54x_insn * insn,char * line)4140 tic54x_parse_insn (tic54x_insn *insn, char *line)
4141 {
4142   insn->tm = (insn_template *) str_hash_find (op_hash, insn->mnemonic);
4143   if (!insn->tm)
4144     {
4145       as_bad (_("Unrecognized instruction \"%s\""), insn->mnemonic);
4146       return 0;
4147     }
4148 
4149   insn->opcount = get_operands (insn->operands, line);
4150   if (insn->opcount < 0)
4151     return 0;
4152 
4153   /* Check each variation of operands for this mnemonic.  */
4154   while (insn->tm->name && strcasecmp (insn->tm->name, insn->mnemonic) == 0)
4155     {
4156       if (insn->opcount >= insn->tm->minops
4157 	  && insn->opcount <= insn->tm->maxops
4158 	  && operands_match (insn, &insn->operands[0], insn->opcount,
4159 			     insn->tm->operand_types,
4160 			     insn->tm->minops, insn->tm->maxops))
4161 	{
4162 	  /* SUCCESS! now try some optimizations.  */
4163 	  if (optimize_insn (insn))
4164 	    {
4165 	      insn->tm = (insn_template *) str_hash_find (op_hash,
4166 							  insn->mnemonic);
4167 	      continue;
4168 	    }
4169 
4170 	  return 1;
4171 	}
4172       ++(insn->tm);
4173     }
4174   as_bad (_("Unrecognized operand list '%s' for instruction '%s'"),
4175 	  line, insn->mnemonic);
4176   return 0;
4177 }
4178 
4179 /* We set this in start_line_hook, 'cause if we do a line replacement, we
4180    won't be able to see the next line.  */
4181 static int parallel_on_next_line_hint = 0;
4182 
4183 /* See if this is part of a parallel instruction
4184    Look for a subsequent line starting with "||".  */
4185 
4186 static int
next_line_shows_parallel(char * next_line)4187 next_line_shows_parallel (char *next_line)
4188 {
4189   /* Look for the second half.  */
4190   while (*next_line != 0 && ISSPACE (*next_line))
4191     ++next_line;
4192 
4193   return (next_line[0] == PARALLEL_SEPARATOR
4194 	  && next_line[1] == PARALLEL_SEPARATOR);
4195 }
4196 
4197 static int
tic54x_parse_parallel_insn_firstline(tic54x_insn * insn,char * line)4198 tic54x_parse_parallel_insn_firstline (tic54x_insn *insn, char *line)
4199 {
4200   insn->tm = (insn_template *) str_hash_find (parop_hash, insn->mnemonic);
4201   if (!insn->tm)
4202     {
4203       as_bad (_("Unrecognized parallel instruction \"%s\""),
4204 	      insn->mnemonic);
4205       return 0;
4206     }
4207 
4208   while (insn->tm->name && strcasecmp (insn->tm->name,
4209                                        insn->mnemonic) == 0)
4210     {
4211       insn->opcount = get_operands (insn->operands, line);
4212       if (insn->opcount < 0)
4213 	return 0;
4214       if (insn->opcount == 2
4215 	  && operands_match (insn, &insn->operands[0], insn->opcount,
4216 			     insn->tm->operand_types, 2, 2))
4217 	{
4218 	  return 1;
4219 	}
4220       ++(insn->tm);
4221     }
4222   /* Didn't find a matching parallel; try for a normal insn.  */
4223   return 0;
4224 }
4225 
4226 /* Parse the second line of a two-line parallel instruction.  */
4227 
4228 static int
tic54x_parse_parallel_insn_lastline(tic54x_insn * insn,char * line)4229 tic54x_parse_parallel_insn_lastline (tic54x_insn *insn, char *line)
4230 {
4231   int valid_mnemonic = 0;
4232 
4233   insn->paropcount = get_operands (insn->paroperands, line);
4234   while (insn->tm->name && strcasecmp (insn->tm->name,
4235 				       insn->mnemonic) == 0)
4236     {
4237       if (strcasecmp (insn->tm->parname, insn->parmnemonic) == 0)
4238 	{
4239 	  valid_mnemonic = 1;
4240 
4241 	  if (insn->paropcount >= insn->tm->minops
4242 	      && insn->paropcount <= insn->tm->maxops
4243 	      && operands_match (insn, insn->paroperands,
4244 				 insn->paropcount,
4245 				 insn->tm->paroperand_types,
4246 				 insn->tm->minops, insn->tm->maxops))
4247 	    return 1;
4248 	}
4249       ++(insn->tm);
4250     }
4251   if (valid_mnemonic)
4252     as_bad (_("Invalid operand (s) for parallel instruction \"%s\""),
4253 	    insn->parmnemonic);
4254   else
4255     as_bad (_("Unrecognized parallel instruction combination \"%s || %s\""),
4256 	    insn->mnemonic, insn->parmnemonic);
4257 
4258   return 0;
4259 }
4260 
4261 /* If quotes found, return copy of line up to closing quote;
4262    otherwise up until terminator.
4263    If it's a string, pass as-is; otherwise attempt substitution symbol
4264    replacement on the value.  */
4265 
4266 static char *
subsym_get_arg(char * line,const char * terminators,char ** str,int nosub)4267 subsym_get_arg (char *line, const char *terminators, char **str, int nosub)
4268 {
4269   char *ptr = line;
4270   char *endp;
4271   int is_string = *line == '"';
4272   int is_char = ISDIGIT (*line);
4273 
4274   if (is_char)
4275     {
4276       while (ISDIGIT (*ptr))
4277 	++ptr;
4278       endp = ptr;
4279       *str = xmemdup0 (line, ptr - line);
4280     }
4281   else if (is_string)
4282     {
4283       char *savedp = input_line_pointer;
4284       int len;
4285 
4286       input_line_pointer = ptr;
4287       *str = demand_copy_C_string (&len);
4288       endp = input_line_pointer;
4289       input_line_pointer = savedp;
4290 
4291       /* Do forced substitutions if requested.  */
4292       if (!nosub && **str == ':')
4293 	*str = subsym_substitute (*str, 1);
4294     }
4295   else
4296     {
4297       const char *term = terminators;
4298       char *value = NULL;
4299 
4300       while (*ptr && *ptr != *term)
4301 	{
4302 	  if (!*term)
4303 	    {
4304 	      term = terminators;
4305 	      ++ptr;
4306 	    }
4307 	  else
4308 	    ++term;
4309 	}
4310       endp = ptr;
4311       *str = xmemdup0 (line, ptr - line);
4312       /* Do simple substitution, if available.  */
4313       if (!nosub && (value = subsym_lookup (*str, macro_level)) != NULL)
4314 	*str = value;
4315     }
4316 
4317   return endp;
4318 }
4319 
4320 /* Replace the given substitution string.
4321    We start at the innermost macro level, so that existing locals remain local
4322    Note: we're treating macro args identically to .var's; I don't know if
4323    that's compatible w/TI's assembler.  */
4324 
4325 static void
subsym_create_or_replace(char * name,char * value)4326 subsym_create_or_replace (char *name, char *value)
4327 {
4328   int i;
4329 
4330   for (i = macro_level; i > 0; i--)
4331     if (str_hash_find (subsym_hash[i], name))
4332       {
4333 	str_hash_insert (subsym_hash[i], name, value, 1);
4334 	return;
4335       }
4336   str_hash_insert (subsym_hash[0], name, value, 1);
4337 }
4338 
4339 /* Look up the substitution string replacement for the given symbol.
4340    Start with the innermost macro substitution table given and work
4341    outwards.  */
4342 
4343 static char *
subsym_lookup(char * name,int nest_level)4344 subsym_lookup (char *name, int nest_level)
4345 {
4346   char *value = str_hash_find (subsym_hash[nest_level], name);
4347 
4348   if (value || nest_level == 0)
4349     return value;
4350 
4351   return subsym_lookup (name, nest_level - 1);
4352 }
4353 
4354 /* Do substitution-symbol replacement on the given line (recursively).
4355    return the argument if no substitution was done
4356 
4357    Also look for built-in functions ($func (arg)) and local labels.
4358 
4359    If FORCED is set, look for forced substitutions of the form ':SYMBOL:'.  */
4360 
4361 static char *
subsym_substitute(char * line,int forced)4362 subsym_substitute (char *line, int forced)
4363 {
4364   /* For each apparent symbol, see if it's a substitution symbol, and if so,
4365      replace it in the input.  */
4366   char *replacement; /* current replacement for LINE.  */
4367   char *head; /* Start of line.  */
4368   char *ptr; /* Current examination point.  */
4369   int changed = 0; /* Did we make a substitution?  */
4370   int eval_line = 0; /* Is this line a .eval/.asg statement?  */
4371   int eval_symbol = 0; /* Are we in the middle of the symbol for
4372                           .eval/.asg?  */
4373   char *eval_end = NULL;
4374   int recurse = 1;
4375   int line_conditional = 0;
4376   char *tmp;
4377 
4378   /* Work with a copy of the input line.  */
4379   replacement = xstrdup (line);
4380 
4381   ptr = head = replacement;
4382 
4383   /* Flag lines where we might need to replace a single '=' with two;
4384      GAS uses single '=' to assign macro args values, and possibly other
4385      places, so limit what we replace.  */
4386   if (strstr (line, ".if")
4387       || strstr (line, ".elseif")
4388       || strstr (line, ".break"))
4389     line_conditional = 1;
4390 
4391   /* Watch out for .eval, so that we avoid doing substitution on the
4392      symbol being assigned a value.  */
4393   if (strstr (line, ".eval") || strstr (line, ".asg"))
4394     eval_line = 1;
4395 
4396   /* If it's a macro definition, don't do substitution on the argument
4397      names.  */
4398   if (strstr (line, ".macro"))
4399     return line;
4400 
4401   unsigned char current_char;
4402   while (!is_end_of_line[(current_char = * (unsigned char *) ptr)])
4403     {
4404       /* Need to update this since LINE may have been modified.  */
4405       if (eval_line)
4406 	eval_end = strrchr (ptr, ',');
4407 
4408       /* Replace triple double quotes with bounding quote/escapes.  */
4409       if (current_char == '"' && ptr[1] == '"' && ptr[2] == '"')
4410 	{
4411 	  ptr[1] = '\\';
4412 	  tmp = strstr (ptr + 2, "\"\"\"");
4413 	  if (tmp)
4414 	    tmp[0] = '\\';
4415 	  changed = 1;
4416 	}
4417 
4418       /* Replace a single '=' with a '==';
4419 	 for compatibility with older code only.  */
4420       if (line_conditional && current_char == '=')
4421 	{
4422 	  if (ptr[1] == '=')
4423 	    {
4424 	      ptr += 2;
4425 	      continue;
4426 	    }
4427 	  *ptr++ = '\0';
4428 	  tmp = concat (head, "==", ptr, (char *) NULL);
4429 	  /* Continue examining after the '=='.  */
4430 	  ptr = tmp + strlen (head) + 2;
4431 	  free (replacement);
4432 	  head = replacement = tmp;
4433 	  changed = 1;
4434 	}
4435 
4436       /* Flag when we've reached the symbol part of .eval/.asg.  */
4437       if (eval_line && ptr >= eval_end)
4438 	eval_symbol = 1;
4439 
4440       /* For each apparent symbol, see if it's a substitution symbol, and if
4441 	 so, replace it in the input.  */
4442       if ((forced && current_char == ':')
4443 	  || (!forced && is_name_beginner (current_char)))
4444 	{
4445 	  char *name; /* Symbol to be replaced.  */
4446 	  char *savedp = input_line_pointer;
4447 	  int c;
4448 	  char *value = NULL;
4449 	  char *tail; /* Rest of line after symbol.  */
4450 
4451 	  /* Skip the colon.  */
4452 	  if (forced)
4453 	    ++ptr;
4454 
4455 	  input_line_pointer = ptr;
4456 	  c = get_symbol_name (&name);
4457 	  /* '?' is not normally part of a symbol, but it IS part of a local
4458 	     label.  */
4459 	  if (c == '?')
4460 	    {
4461 	      *input_line_pointer++ = c;
4462 	      c = *input_line_pointer;
4463 	      *input_line_pointer = '\0';
4464 	    }
4465 	  /* Avoid infinite recursion; if a symbol shows up a second time for
4466 	     substitution, leave it as is.  */
4467 	  if (str_hash_find (subsym_recurse_hash, name) == NULL)
4468 	    value = subsym_lookup (name, macro_level);
4469 	  else
4470 	    as_warn (_("%s symbol recursion stopped at "
4471 		       "second appearance of '%s'"),
4472 		     forced ? "Forced substitution" : "Substitution", name);
4473 	  ptr = tail = input_line_pointer;
4474 	  input_line_pointer = savedp;
4475 
4476 	  /* Check for local labels; replace them with the appropriate
4477 	     substitution.  */
4478 	  if ((*name == '$' && ISDIGIT (name[1]) && name[2] == '\0')
4479 	      || name[strlen (name) - 1] == '?')
4480 	    {
4481 	      /* Use an existing identifier for that label if, available, or
4482 		 create a new, unique identifier.  */
4483 	      value = str_hash_find (local_label_hash[macro_level], name);
4484 	      if (value == NULL)
4485 		{
4486 		  char digit[11];
4487 		  char *namecopy = xstrdup (name);
4488 
4489 		  value = strcpy (xmalloc (strlen (name) + sizeof (digit) + 1),
4490 				  name);
4491 		  if (*value != '$')
4492 		    value[strlen (value) - 1] = '\0';
4493 		  sprintf (digit, ".%d", local_label_id++);
4494 		  strcat (value, digit);
4495 		  str_hash_insert (local_label_hash[macro_level],
4496 				   namecopy, value, 0);
4497 		}
4498 	      /* Indicate where to continue looking for substitutions.  */
4499 	      ptr = tail;
4500 	    }
4501 	  /* Check for built-in subsym and math functions.  */
4502 	  else if (value != NULL && *name == '$')
4503 	    {
4504 	      subsym_proc_entry *entry = (subsym_proc_entry *) value;
4505 	      math_proc_entry *math_entry = str_hash_find (math_hash, name);
4506 	      char *arg1, *arg2 = NULL;
4507 
4508 	      *ptr = c;
4509 	      if (entry == NULL)
4510 		{
4511 		  as_bad (_("Unrecognized substitution symbol function"));
4512 		  break;
4513 		}
4514 	      else if (*ptr != '(')
4515 		{
4516 		  as_bad (_("Missing '(' after substitution symbol function"));
4517 		  break;
4518 		}
4519 	      ++ptr;
4520 	      if (math_entry != NULL)
4521 		{
4522 		  float farg1, farg2 = 0;
4523 		  volatile float fresult;
4524 
4525 		  farg1 = (float) strtod (ptr, &ptr);
4526 		  if (math_entry->nargs == 2)
4527 		    {
4528 		      if (*ptr++ != ',')
4529 			{
4530 			  as_bad (_("Expecting second argument"));
4531 			  break;
4532 			}
4533 		      farg2 = (float) strtod (ptr, &ptr);
4534 		    }
4535 		  fresult = (*math_entry->proc) (farg1, farg2);
4536 		  value = XNEWVEC (char, 128);
4537 		  if (math_entry->int_return)
4538 		    sprintf (value, "%d", (int) fresult);
4539 		  else
4540 		    sprintf (value, "%f", fresult);
4541 		  if (*ptr++ != ')')
4542 		    {
4543 		      as_bad (_("Extra junk in function call, expecting ')'"));
4544 		      break;
4545 		    }
4546 		  /* Don't bother recursing; the replacement isn't a
4547                      symbol.  */
4548 		  recurse = 0;
4549 		}
4550 	      else
4551 		{
4552 		  int val;
4553 		  int arg_type[2] = { *ptr == '"' , 0 };
4554 		  int ismember = !strcmp (entry->name, "$ismember");
4555 
4556 		  /* Parse one or two args, which must be a substitution
4557 		     symbol, string or a character-string constant.  */
4558 		  /* For all functions, a string or substitution symbol may be
4559 		     used, with the following exceptions:
4560 		     firstch/lastch: 2nd arg must be character constant
4561 		     ismember: both args must be substitution symbols.  */
4562 		  ptr = subsym_get_arg (ptr, ",)", &arg1, ismember);
4563 		  if (!arg1)
4564 		    break;
4565 		  if (entry->nargs == 2)
4566 		    {
4567 		      if (*ptr++ != ',')
4568 			{
4569 			  as_bad (_("Function expects two arguments"));
4570 			  break;
4571 			}
4572 		      /* Character constants are converted to numerics
4573 			 by the preprocessor.  */
4574 		      arg_type[1] = (ISDIGIT (*ptr)) ? 2 : (*ptr == '"');
4575 		      ptr = subsym_get_arg (ptr, ")", &arg2, ismember);
4576 		    }
4577 		  /* Args checking.  */
4578 		  if ((!strcmp (entry->name, "$firstch")
4579 		       || !strcmp (entry->name, "$lastch"))
4580 		      && arg_type[1] != 2)
4581 		    {
4582 		      as_bad (_("Expecting character constant argument"));
4583 		      break;
4584 		    }
4585 		  if (ismember
4586 		      && (arg_type[0] != 0 || arg_type[1] != 0))
4587 		    {
4588 		      as_bad (_("Both arguments must be substitution symbols"));
4589 		      break;
4590 		    }
4591 		  if (*ptr++ != ')')
4592 		    {
4593 		      as_bad (_("Extra junk in function call, expecting ')'"));
4594 		      break;
4595 		    }
4596 		  val = (*entry->proc) (arg1, arg2);
4597 		  value = XNEWVEC (char, 64);
4598 		  sprintf (value, "%d", val);
4599 		}
4600 	      /* Fix things up to replace the entire expression, not just the
4601 		 function name.  */
4602 	      tail = ptr;
4603 	      c = *tail;
4604 	    }
4605 
4606 	  if (value != NULL && !eval_symbol)
4607 	    {
4608 	      /* Replace the symbol with its string replacement and
4609 		 continue.  Recursively replace VALUE until either no
4610 		 substitutions are performed, or a substitution that has been
4611 		 previously made is encountered again.
4612 
4613 		 Put the symbol into the recursion hash table so we only
4614 		 try to replace a symbol once.  */
4615 	      if (recurse)
4616 		{
4617 		  str_hash_insert (subsym_recurse_hash, name, name, 0);
4618 		  value = subsym_substitute (value, macro_level > 0);
4619 		  str_hash_delete (subsym_recurse_hash, name);
4620 		}
4621 
4622 	      /* Temporarily zero-terminate where the symbol started.  */
4623 	      *name = 0;
4624 	      if (forced)
4625 		{
4626 		  if (c == '(')
4627 		    {
4628 		      /* Subscripted substitution symbol -- use just the
4629 			 indicated portion of the string; the description
4630 			 kinda indicates that forced substitution is not
4631 			 supposed to be recursive, but I'm not sure.  */
4632 		      unsigned beg, len = 1; /* default to a single char */
4633 		      char *newval = xstrdup (value);
4634 
4635 		      savedp = input_line_pointer;
4636 		      input_line_pointer = tail + 1;
4637 		      beg = get_absolute_expression ();
4638 		      if (beg < 1)
4639 			{
4640 			  as_bad (_("Invalid subscript (use 1 to %d)"),
4641 				  (int) strlen (value));
4642 			  break;
4643 			}
4644 		      if (*input_line_pointer == ',')
4645 			{
4646 			  ++input_line_pointer;
4647 			  len = get_absolute_expression ();
4648 			  if (beg + len > strlen (value))
4649 			    {
4650 			      as_bad (_("Invalid length (use 0 to %d)"),
4651 				      (int) strlen (value) - beg);
4652 			      break;
4653 			    }
4654 			}
4655 		      newval += beg - 1;
4656 		      newval[len] = 0;
4657 		      tail = input_line_pointer;
4658 		      if (*tail++ != ')')
4659 			{
4660 			  as_bad (_("Missing ')' in subscripted substitution "
4661 				    "symbol expression"));
4662 			  break;
4663 			}
4664 		      c = *tail;
4665 		      input_line_pointer = savedp;
4666 
4667 		      value = newval;
4668 		    }
4669 		  name[-1] = 0;
4670 		}
4671 	      tmp = xmalloc (strlen (head) + strlen (value) +
4672 			     strlen (tail + 1) + 2);
4673 	      strcpy (tmp, head);
4674 	      strcat (tmp, value);
4675 	      /* Make sure forced substitutions are properly terminated.  */
4676 	      if (forced)
4677 		{
4678 		  if (c != ':')
4679 		    {
4680 		      as_bad (_("Missing forced substitution terminator ':'"));
4681 		      break;
4682 		    }
4683 		  ++tail;
4684 		}
4685 	      else
4686 		/* Restore the character after the symbol end.  */
4687 		*tail = c;
4688 	      strcat (tmp, tail);
4689 	      /* Continue examining after the replacement value.  */
4690 	      ptr = tmp + strlen (head) + strlen (value);
4691 	      free (replacement);
4692 	      head = replacement = tmp;
4693 	      changed = 1;
4694 	    }
4695 	  else
4696 	    *ptr = c;
4697 	}
4698       else
4699 	{
4700 	  ++ptr;
4701 	}
4702     }
4703 
4704   if (changed)
4705     return replacement;
4706   else
4707     return line;
4708 }
4709 
4710 /* We use this to handle substitution symbols
4711    hijack input_line_pointer, replacing it with our substituted string.
4712 
4713    .sslist should enable listing the line after replacements are made...
4714 
4715    returns the new buffer limit.  */
4716 
4717 void
tic54x_start_line_hook(void)4718 tic54x_start_line_hook (void)
4719 {
4720   char *line, *endp;
4721   char *replacement = NULL;
4722 
4723   /* Work with a copy of the input line, including EOL char.  */
4724   for (endp = input_line_pointer; *endp != 0; )
4725     if (is_end_of_line[(unsigned char) *endp++])
4726       break;
4727 
4728   line = xmemdup0 (input_line_pointer, endp - input_line_pointer);
4729 
4730   /* Scan ahead for parallel insns.  */
4731   parallel_on_next_line_hint = next_line_shows_parallel (endp);
4732 
4733   /* If within a macro, first process forced replacements.  */
4734   if (macro_level > 0)
4735     replacement = subsym_substitute (line, 1);
4736   else
4737     replacement = line;
4738   replacement = subsym_substitute (replacement, 0);
4739 
4740   if (replacement != line)
4741     {
4742       char *tmp = replacement;
4743       char *comment = strchr (replacement, ';');
4744       char endc = replacement[strlen (replacement) - 1];
4745 
4746       /* Clean up the replacement; we'd prefer to have this done by the
4747 	 standard preprocessing equipment (maybe do_scrub_chars?)
4748 	 but for now, do a quick-and-dirty.  */
4749       if (comment != NULL)
4750 	{
4751 	  comment[0] = endc;
4752 	  comment[1] = 0;
4753 	  --comment;
4754 	}
4755       else
4756 	comment = replacement + strlen (replacement) - 1;
4757 
4758       /* Trim trailing whitespace.  */
4759       while (ISSPACE (*comment))
4760 	{
4761 	  comment[0] = endc;
4762 	  comment[1] = 0;
4763 	  --comment;
4764 	}
4765 
4766       /* Compact leading whitespace.  */
4767       while (ISSPACE (tmp[0]) && ISSPACE (tmp[1]))
4768 	++tmp;
4769 
4770       input_line_pointer = endp;
4771       input_scrub_insert_line (tmp);
4772       free (replacement);
4773       free (line);
4774       /* Keep track of whether we've done a substitution.  */
4775       substitution_line = 1;
4776     }
4777   else
4778     {
4779       /* No change.  */
4780       free (line);
4781       substitution_line = 0;
4782     }
4783 }
4784 
4785 /* This is the guts of the machine-dependent assembler.  STR points to a
4786    machine dependent instruction.  This function is supposed to emit
4787    the frags/bytes it assembles to.  */
4788 void
md_assemble(char * line)4789 md_assemble (char *line)
4790 {
4791   static int repeat_slot = 0;
4792   static int delay_slots = 0; /* How many delay slots left to fill?  */
4793   static int is_parallel = 0;
4794   static tic54x_insn insn;
4795   char *lptr;
4796   char *savedp = input_line_pointer;
4797   int c;
4798 
4799   input_line_pointer = line;
4800   c = get_symbol_name (&line);
4801 
4802   if (cpu == VNONE)
4803     cpu = V542;
4804   if (address_mode_needs_set)
4805     {
4806       set_address_mode (amode);
4807       address_mode_needs_set = 0;
4808     }
4809   if (cpu_needs_set)
4810     {
4811       set_cpu (cpu);
4812       cpu_needs_set = 0;
4813     }
4814   assembly_begun = 1;
4815 
4816   if (is_parallel)
4817     {
4818       is_parallel = 0;
4819 
4820       strcpy (insn.parmnemonic, line);
4821       lptr = input_line_pointer;
4822       *lptr = c;
4823       input_line_pointer = savedp;
4824 
4825       if (tic54x_parse_parallel_insn_lastline (&insn, lptr))
4826 	{
4827 	  int words = build_insn (&insn);
4828 
4829 	  if (delay_slots != 0)
4830 	    {
4831 	      if (words > delay_slots)
4832 		{
4833 		  as_bad (ngettext ("Instruction does not fit in available "
4834 				    "delay slots (%d-word insn, %d slot left)",
4835 				    "Instruction does not fit in available "
4836 				    "delay slots (%d-word insn, %d slots left)",
4837 				    delay_slots),
4838 			  words, delay_slots);
4839 		  delay_slots = 0;
4840 		  return;
4841 		}
4842 	      delay_slots -= words;
4843 	    }
4844 	}
4845       return;
4846     }
4847 
4848   memset (&insn, 0, sizeof (insn));
4849   strcpy (insn.mnemonic, line);
4850   lptr = input_line_pointer;
4851   *lptr = c;
4852   input_line_pointer = savedp;
4853 
4854   /* See if this line is part of a parallel instruction; if so, either this
4855      line or the next line will have the "||" specifier preceding the
4856      mnemonic, and we look for it in the parallel insn hash table.  */
4857   if (strstr (line, "||") != NULL || parallel_on_next_line_hint)
4858     {
4859       char *tmp = strstr (line, "||");
4860       if (tmp != NULL)
4861 	*tmp = '\0';
4862 
4863       if (tic54x_parse_parallel_insn_firstline (&insn, lptr))
4864 	{
4865 	  is_parallel = 1;
4866 	  /* If the parallel part is on the same line, process it now,
4867 	     otherwise let the assembler pick up the next line for us.  */
4868 	  if (tmp != NULL)
4869 	    {
4870 	      while (ISSPACE (tmp[2]))
4871 		++tmp;
4872 	      md_assemble (tmp + 2);
4873 	    }
4874 	}
4875       else
4876 	{
4877 	  as_bad (_("Unrecognized parallel instruction '%s'"), line);
4878 	}
4879       return;
4880     }
4881 
4882   if (tic54x_parse_insn (&insn, lptr))
4883     {
4884       int words;
4885 
4886       if ((insn.tm->flags & FL_LP)
4887 	  && cpu != V545LP && cpu != V546LP)
4888 	{
4889 	  as_bad (_("Instruction '%s' requires an LP cpu version"),
4890 		  insn.tm->name);
4891 	  return;
4892 	}
4893       if ((insn.tm->flags & FL_FAR)
4894 	  && amode != far_mode)
4895 	{
4896 	  as_bad (_("Instruction '%s' requires far mode addressing"),
4897 		  insn.tm->name);
4898 	  return;
4899 	}
4900 
4901       words = build_insn (&insn);
4902 
4903       /* Is this instruction in a delay slot?  */
4904       if (delay_slots)
4905 	{
4906 	  if (words > delay_slots)
4907 	    {
4908 	      as_warn (ngettext ("Instruction does not fit in available "
4909 				 "delay slots (%d-word insn, %d slot left). "
4910 				 "Resulting behavior is undefined.",
4911 				 "Instruction does not fit in available "
4912 				 "delay slots (%d-word insn, %d slots left). "
4913 				 "Resulting behavior is undefined.",
4914 				 delay_slots),
4915 		       words, delay_slots);
4916 	      delay_slots = 0;
4917 	      return;
4918 	    }
4919 	  /* Branches in delay slots are not allowed.  */
4920 	  if (insn.tm->flags & FL_BMASK)
4921 	    {
4922 	      as_warn (_("Instructions which cause PC discontinuity are not "
4923 			 "allowed in a delay slot. "
4924 			 "Resulting behavior is undefined."));
4925 	    }
4926 	  delay_slots -= words;
4927 	}
4928 
4929       /* Is this instruction the target of a repeat?  */
4930       if (repeat_slot)
4931 	{
4932 	  if (insn.tm->flags & FL_NR)
4933 	    as_warn (_("'%s' is not repeatable. "
4934 		       "Resulting behavior is undefined."),
4935 		     insn.tm->name);
4936 	  else if (insn.is_lkaddr)
4937 	    as_warn (_("Instructions using long offset modifiers or absolute "
4938 		       "addresses are not repeatable. "
4939 		       "Resulting behavior is undefined."));
4940 	  repeat_slot = 0;
4941 	}
4942 
4943       /* Make sure we check the target of a repeat instruction.  */
4944       if (insn.tm->flags & B_REPEAT)
4945 	{
4946 	  repeat_slot = 1;
4947 	  /* FIXME -- warn if repeat_slot == 1 at EOF.  */
4948 	}
4949       /* Make sure we check our delay slots for validity.  */
4950       if (insn.tm->flags & FL_DELAY)
4951 	{
4952 	  delay_slots = 2;
4953 	  /* FIXME -- warn if delay_slots != 0 at EOF.  */
4954 	}
4955     }
4956 }
4957 
4958 /* Do a final adjustment on the symbol table; in this case, make sure we have
4959    a ".file" symbol.  */
4960 
4961 void
tic54x_adjust_symtab(void)4962 tic54x_adjust_symtab (void)
4963 {
4964   if (symbol_rootP == NULL
4965       || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
4966     {
4967       unsigned lineno;
4968       const char * filename = as_where (&lineno);
4969       c_dot_file_symbol (filename);
4970     }
4971 }
4972 
4973 /* In order to get gas to ignore any | chars at the start of a line,
4974    this function returns true if a | is found in a line.
4975    This lets us process parallel instructions, which span two lines.  */
4976 
4977 int
tic54x_unrecognized_line(int c)4978 tic54x_unrecognized_line (int c)
4979 {
4980   return c == PARALLEL_SEPARATOR;
4981 }
4982 
4983 /* Watch for local labels of the form $[0-9] and [_a-zA-Z][_a-zA-Z0-9]*?
4984    Encode their names so that only we see them and can map them to the
4985    appropriate places.
4986    FIXME -- obviously this isn't done yet.  These locals still show up in the
4987    symbol table.  */
4988 void
tic54x_define_label(symbolS * sym)4989 tic54x_define_label (symbolS *sym)
4990 {
4991   /* Just in case we need this later; note that this is not necessarily the
4992      same thing as line_label...
4993      When aligning or assigning labels to fields, sometimes the label is
4994      assigned other than the address at which the label appears.
4995      FIXME -- is this really needed? I think all the proper label assignment
4996      is done in tic54x_cons.  */
4997   last_label_seen = sym;
4998 }
4999 
5000 /* Try to parse something that normal parsing failed at.  */
5001 
5002 symbolS *
tic54x_undefined_symbol(char * name)5003 tic54x_undefined_symbol (char *name)
5004 {
5005   tic54x_symbol *sym;
5006 
5007   /* Not sure how to handle predefined symbols.  */
5008   if ((sym = (tic54x_symbol *) str_hash_find (cc_hash, name)) != NULL
5009       || (sym = (tic54x_symbol *) str_hash_find (cc2_hash, name)) != NULL
5010       || (sym = (tic54x_symbol *) str_hash_find (cc3_hash, name)) != NULL
5011       || str_hash_find (misc_symbol_hash, name) != NULL
5012       || (sym = (tic54x_symbol *) str_hash_find (sbit_hash, name)) != NULL
5013       || (sym = (tic54x_symbol *) str_hash_find (reg_hash, name)) != NULL
5014       || (sym = (tic54x_symbol *) str_hash_find (mmreg_hash, name)) != NULL
5015       || !strcasecmp (name, "a")
5016       || !strcasecmp (name, "b"))
5017     {
5018       return symbol_new (name, reg_section, &zero_address_frag,
5019 			 sym ? sym->value : 0);
5020     }
5021 
5022   return NULL;
5023 }
5024 
5025 /* Parse a name in an expression before the expression parser takes a stab at
5026    it.  */
5027 
5028 int
tic54x_parse_name(char * name ATTRIBUTE_UNUSED,expressionS * expn ATTRIBUTE_UNUSED)5029 tic54x_parse_name (char *name ATTRIBUTE_UNUSED,
5030 		   expressionS *expn ATTRIBUTE_UNUSED)
5031 {
5032   return 0;
5033 }
5034 
5035 const char *
md_atof(int type,char * literalP,int * sizeP)5036 md_atof (int type, char *literalP, int *sizeP)
5037 {
5038   /* Target data is little-endian, but floats are stored
5039      big-"word"ian.  ugh.  */
5040   return ieee_md_atof (type, literalP, sizeP, true);
5041 }
5042 
5043 arelent *
tc_gen_reloc(asection * section,fixS * fixP)5044 tc_gen_reloc (asection *section, fixS *fixP)
5045 {
5046   arelent *rel;
5047   bfd_reloc_code_real_type code = fixP->fx_r_type;
5048   asymbol *sym = symbol_get_bfdsym (fixP->fx_addsy);
5049 
5050   rel = XNEW (arelent);
5051   rel->sym_ptr_ptr = XNEW (asymbol *);
5052   *rel->sym_ptr_ptr = sym;
5053   /* We assume that all rel->address are host byte offsets.  */
5054   rel->address = fixP->fx_frag->fr_address + fixP->fx_where;
5055   rel->address /= OCTETS_PER_BYTE;
5056   rel->howto = bfd_reloc_type_lookup (stdoutput, code);
5057   if (!strcmp (sym->name, section->name))
5058     rel->howto += HOWTO_BANK;
5059 
5060   if (!rel->howto)
5061     {
5062       const char *name = S_GET_NAME (fixP->fx_addsy);
5063       if (name == NULL)
5064 	name = "<unknown>";
5065       as_fatal ("Cannot generate relocation type for symbol %s, code %s",
5066 		name, bfd_get_reloc_code_name (code));
5067       return NULL;
5068     }
5069   return rel;
5070 }
5071 
5072 /* Handle cons expressions.  */
5073 
5074 void
tic54x_cons_fix_new(fragS * frag,int where,int octets,expressionS * expn,bfd_reloc_code_real_type r)5075 tic54x_cons_fix_new (fragS *frag, int where, int octets, expressionS *expn,
5076 		     bfd_reloc_code_real_type r)
5077 {
5078   switch (octets)
5079     {
5080     default:
5081       as_bad (_("Unsupported relocation size %d"), octets);
5082       r = BFD_RELOC_TIC54X_16_OF_23;
5083       break;
5084     case 2:
5085       r = BFD_RELOC_TIC54X_16_OF_23;
5086       break;
5087     case 4:
5088       /* TI assembler always uses this, regardless of addressing mode.  */
5089       if (emitting_long)
5090 	r = BFD_RELOC_TIC54X_23;
5091       else
5092 	/* We never want to directly generate this; this is provided for
5093 	   stabs support only.  */
5094 	r = BFD_RELOC_32;
5095       break;
5096     }
5097   fix_new_exp (frag, where, octets, expn, 0, r);
5098 }
5099 
5100 /* Attempt to simplify or even eliminate a fixup.
5101    To indicate that a fixup has been eliminated, set fixP->fx_done.
5102 
5103    If fixp->fx_addsy is non-NULL, we'll have to generate a reloc entry.   */
5104 
5105 void
md_apply_fix(fixS * fixP,valueT * valP,segT seg ATTRIBUTE_UNUSED)5106 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
5107 {
5108   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
5109   valueT val = * valP;
5110 
5111   switch (fixP->fx_r_type)
5112     {
5113     default:
5114       as_fatal ("Bad relocation type: 0x%02x", fixP->fx_r_type);
5115       return;
5116     case BFD_RELOC_TIC54X_MS7_OF_23:
5117       val = (val >> 16) & 0x7F;
5118       /* Fall through.  */
5119     case BFD_RELOC_TIC54X_16_OF_23:
5120     case BFD_RELOC_16:
5121       bfd_put_16 (stdoutput, val, buf);
5122       /* Indicate what we're actually writing, so that we don't get warnings
5123 	 about exceeding available space.  */
5124       *valP = val & 0xFFFF;
5125       break;
5126     case BFD_RELOC_TIC54X_PARTLS7:
5127       bfd_put_16 (stdoutput,
5128 		  (bfd_get_16 (stdoutput, buf) & 0xFF80) | (val & 0x7F),
5129 		  buf);
5130       /* Indicate what we're actually writing, so that we don't get warnings
5131 	 about exceeding available space.  */
5132       *valP = val & 0x7F;
5133       break;
5134     case BFD_RELOC_TIC54X_PARTMS9:
5135       /* TI assembler doesn't shift its encoding for relocatable files, and is
5136 	 thus incompatible with this implementation's relocatable files.  */
5137       bfd_put_16 (stdoutput,
5138 		  (bfd_get_16 (stdoutput, buf) & 0xFE00) | (val >> 7),
5139 		  buf);
5140       break;
5141     case BFD_RELOC_32:
5142     case BFD_RELOC_TIC54X_23:
5143       bfd_put_32 (stdoutput,
5144 		  (bfd_get_32 (stdoutput, buf) & 0xFF800000) | val,
5145 		  buf);
5146       break;
5147     }
5148 
5149   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
5150     fixP->fx_done = 1;
5151 }
5152 
5153 /* This is our chance to record section alignment
5154    don't need to do anything here, since BFD does the proper encoding.  */
5155 
5156 valueT
md_section_align(segT segment ATTRIBUTE_UNUSED,valueT section_size)5157 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT section_size)
5158 {
5159   return section_size;
5160 }
5161 
5162 long
md_pcrel_from(fixS * fixP ATTRIBUTE_UNUSED)5163 md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
5164 {
5165   return 0;
5166 }
5167 
5168 /* Mostly little-endian, but longwords (4 octets) get MS word stored
5169    first.  */
5170 
5171 void
tic54x_number_to_chars(char * buf,valueT val,int n)5172 tic54x_number_to_chars (char *buf, valueT val, int n)
5173 {
5174   if (n != 4)
5175     number_to_chars_littleendian (buf, val, n);
5176   else
5177     {
5178       number_to_chars_littleendian (buf    , val >> 16   , 2);
5179       number_to_chars_littleendian (buf + 2, val & 0xFFFF, 2);
5180     }
5181 }
5182 
5183 int
tic54x_estimate_size_before_relax(fragS * frag ATTRIBUTE_UNUSED,segT seg ATTRIBUTE_UNUSED)5184 tic54x_estimate_size_before_relax (fragS *frag ATTRIBUTE_UNUSED,
5185 				   segT seg ATTRIBUTE_UNUSED)
5186 {
5187   return 0;
5188 }
5189 
5190 /* We use this to handle bit allocations which we couldn't handle before due
5191    to symbols being in different frags.  return number of octets added.  */
5192 
5193 int
tic54x_relax_frag(fragS * frag,long stretch ATTRIBUTE_UNUSED)5194 tic54x_relax_frag (fragS *frag, long stretch ATTRIBUTE_UNUSED)
5195 {
5196   symbolS *sym = frag->fr_symbol;
5197   int growth = 0;
5198   int i;
5199 
5200   if (sym != NULL)
5201     {
5202       struct bit_info *bi = (struct bit_info *) frag->fr_opcode;
5203       int bit_offset = frag_bit_offset (frag_prev (frag, bi->seg), bi->seg);
5204       int size = S_GET_VALUE (sym);
5205       fragS *prev_frag = bit_offset_frag (frag_prev (frag, bi->seg), bi->seg);
5206       int available = 16 - bit_offset;
5207 
5208       if (symbol_get_frag (sym) != &zero_address_frag
5209 	  || S_IS_COMMON (sym)
5210 	  || !S_IS_DEFINED (sym))
5211 	as_bad_where (frag->fr_file, frag->fr_line,
5212 		      _("non-absolute value used with .space/.bes"));
5213 
5214       if (size < 0)
5215 	{
5216 	  as_warn (_("negative value ignored in %s"),
5217 		   bi->type == TYPE_SPACE ? ".space" :
5218 		   bi->type == TYPE_BES ? ".bes" : ".field");
5219 	  growth = 0;
5220 	  frag->tc_frag_data = frag->fr_fix = 0;
5221 	  return 0;
5222 	}
5223 
5224       if (bi->type == TYPE_FIELD)
5225 	{
5226 	  /* Bit fields of 16 or larger will have already been handled.  */
5227 	  if (bit_offset != 0 && available >= size)
5228 	    {
5229 	      char *p = prev_frag->fr_literal;
5230 
5231 	      valueT value = bi->value;
5232 	      value <<= available - size;
5233 	      value |= ((unsigned short) p[1] << 8) | p[0];
5234 	      md_number_to_chars (p, value, 2);
5235 	      if ((prev_frag->tc_frag_data += size) == 16)
5236 		prev_frag->tc_frag_data = 0;
5237 	      if (bi->sym)
5238 		symbol_set_frag (bi->sym, prev_frag);
5239 	      /* This frag is no longer used.  */
5240 	      growth = -frag->fr_fix;
5241 	      frag->fr_fix = 0;
5242 	      frag->tc_frag_data = 0;
5243 	    }
5244 	  else
5245 	    {
5246 	      char *p = frag->fr_literal;
5247 
5248 	      valueT value = bi->value << (16 - size);
5249 	      md_number_to_chars (p, value, 2);
5250 	      if ((frag->tc_frag_data = size) == 16)
5251 		frag->tc_frag_data = 0;
5252 	      growth = 0;
5253 	    }
5254 	}
5255       else
5256 	{
5257 	  if (bit_offset != 0 && bit_offset < 16)
5258 	    {
5259 	      if (available >= size)
5260 		{
5261 		  if ((prev_frag->tc_frag_data += size) == 16)
5262 		    prev_frag->tc_frag_data = 0;
5263 		  if (bi->sym)
5264 		    symbol_set_frag (bi->sym, prev_frag);
5265 		  /* This frag is no longer used.  */
5266 		  growth = -frag->fr_fix;
5267 		  frag->fr_fix = 0;
5268 		  frag->tc_frag_data = 0;
5269 		  goto getout;
5270 		}
5271 	      if (bi->type == TYPE_SPACE && bi->sym)
5272 		symbol_set_frag (bi->sym, prev_frag);
5273 	      size -= available;
5274 	    }
5275 	  growth = (size + 15) / 16 * OCTETS_PER_BYTE - frag->fr_fix;
5276 	  for (i = 0; i < growth; i++)
5277 	    frag->fr_literal[i] = 0;
5278 	  frag->fr_fix = growth;
5279 	  frag->tc_frag_data = size % 16;
5280 	  /* Make sure any BES label points to the LAST word allocated.  */
5281 	  if (bi->type == TYPE_BES && bi->sym)
5282 	    S_SET_VALUE (bi->sym, frag->fr_fix / OCTETS_PER_BYTE - 1);
5283 	}
5284     getout:
5285       frag->fr_symbol = 0;
5286       frag->fr_opcode = 0;
5287       free ((void *) bi);
5288     }
5289   return growth;
5290 }
5291 
5292 void
tic54x_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,segT seg ATTRIBUTE_UNUSED,fragS * frag)5293 tic54x_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
5294 		     segT seg ATTRIBUTE_UNUSED,
5295 		     fragS *frag)
5296 {
5297   /* Offset is in bytes.  */
5298   frag->fr_offset = (frag->fr_next->fr_address
5299 		     - frag->fr_address
5300 		     - frag->fr_fix) / frag->fr_var;
5301   if (frag->fr_offset < 0)
5302     {
5303       as_bad_where (frag->fr_file, frag->fr_line,
5304 		    _("attempt to .space/.bes backwards? (%ld)"),
5305 		    (long) frag->fr_offset);
5306     }
5307   frag->fr_type = rs_space;
5308 }
5309 
5310 /* We need to avoid having labels defined for certain directives/pseudo-ops
5311    since once the label is defined, it's in the symbol table for good.  TI
5312    syntax puts the symbol *before* the pseudo (which is kinda like MRI syntax,
5313    I guess, except I've never seen a definition of MRI syntax).
5314 
5315    Don't allow labels to start with '.'  */
5316 
5317 int
tic54x_start_label(char * label_start,int nul_char,int next_char)5318 tic54x_start_label (char * label_start, int nul_char, int next_char)
5319 {
5320   char *rest;
5321 
5322   /* If within .struct/.union, no auto line labels, please.  */
5323   if (current_stag != NULL)
5324     return 0;
5325 
5326   /* Disallow labels starting with "."  */
5327   if (next_char != ':')
5328     {
5329       if (*label_start == '.')
5330 	{
5331 	  as_bad (_("Invalid label '%s'"), label_start);
5332 	  return 0;
5333 	}
5334     }
5335 
5336   if (is_end_of_line[(unsigned char) next_char])
5337     return 1;
5338 
5339   rest = input_line_pointer;
5340   if (nul_char == '"')
5341     ++rest;
5342   while (ISSPACE (next_char))
5343     next_char = *++rest;
5344   if (next_char != '.')
5345     return 1;
5346 
5347   /* Don't let colon () define a label for any of these...  */
5348   return ((strncasecmp (rest, ".tag", 4) != 0 || !ISSPACE (rest[4]))
5349 	  && (strncasecmp (rest, ".struct", 7) != 0 || !ISSPACE (rest[7]))
5350 	  && (strncasecmp (rest, ".union", 6) != 0 || !ISSPACE (rest[6]))
5351 	  && (strncasecmp (rest, ".macro", 6) != 0 || !ISSPACE (rest[6]))
5352 	  && (strncasecmp (rest, ".set", 4) != 0 || !ISSPACE (rest[4]))
5353 	  && (strncasecmp (rest, ".equ", 4) != 0 || !ISSPACE (rest[4])));
5354 }
5355