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