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