1 /* tc-tic54x.c -- Assembly code for the Texas Instruments TMS320C54X
2 Copyright (C) 1999, 2000 Free Software Foundation.
3 Contributed by Timothy Wall (twall@cygnus.com)
5 This file is part of GAS, the GNU Assembler.
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 Texas Instruments TMS320C54X machine specific gas.
24 Written by Timothy Wall (twall@alum.mit.edu).
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.
33 Tests to add to expect testsuite:
34 '=' and '==' with .if, .elseif, and .break
36 Incompatibilities (mostly trivial):
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
53 #include "struc-symbol.h"
54 #include "opcode/tic54x.h"
58 #define MAX_LINE 256 /* lines longer than this are truncated by TI's asm */
60 const char comment_chars[] = ";";
61 const char line_comment_chars[] = ";*#"; /* at column zero only */
62 const char line_separator_chars[] = "";/* not permitted */
64 /* characters which indicate that this is a floating point constant */
65 const char FLT_CHARS[] = "fF";
66 /* Characters that can be used to separate mantissa from exp in FP nums */
67 const char EXP_CHARS[] = "eE";
69 /* only word (et al.), align, or conditionals are allowed within
71 #define ILLEGAL_WITHIN_STRUCT() \
72 do if (current_stag != NULL){ \
73 as_bad (_("pseudo-op illegal within .struct/.union"));return; } while (0)
76 md_show_usage (stream)
79 fprintf (stream, _("C54x-specific command line options:\n"));
80 fprintf (stream, _("-mfar-mode | -mf Use extended addressing\n"));
81 fprintf (stream, _("-mcpu=<CPU version> Specify the CPU version\n"));
82 /* fprintf (stream, _("-mcoff-version={0|1|2} Select COFF version\n"));*/
83 fprintf (stream, _("-merrors-to-file <filename>\n"));
84 fprintf (stream, _("-me <filename> Redirect errors to a file\n"));
87 const char *md_shortopts = "";
89 VNONE = 0, V541 = 1, V542 = 2, V543 = 3, V545 = 5, V548 = 8, V549 = 9,
90 V545LP = 15, V546LP = 16
94 c_mode, /* 16-bit addresses */
95 far_mode /* >16-bit addresses */
98 #define OPTION_ADDRESS_MODE (OPTION_MD_BASE)
99 #define OPTION_CPU_VERSION (OPTION_ADDRESS_MODE+1)
100 #define OPTION_COFF_VERSION (OPTION_CPU_VERSION+1)
101 #define OPTION_STDERR_TO_FILE (OPTION_COFF_VERSION+1)
103 struct option md_longopts[] =
105 { "mfar-mode", no_argument, NULL, OPTION_ADDRESS_MODE },
106 { "mf", no_argument, NULL, OPTION_ADDRESS_MODE },
107 { "mcpu", required_argument, NULL, OPTION_CPU_VERSION },
108 /* { "mcoff-version", required_argument, NULL, OPTION_COFF_VERSION },*/
109 { "merrors-to-file", required_argument, NULL, OPTION_STDERR_TO_FILE },
110 { "me", required_argument, NULL, OPTION_STDERR_TO_FILE },
111 { NULL, no_argument, NULL, 0},
114 size_t md_longopts_size = sizeof (md_longopts);
116 static int assembly_begun = 0;
117 /* Addressing mode is not entirely implemented; the latest rev of the Other
118 assembler doesn't seem to make any distinction whatsoever; all relocations
119 are stored as extended relocatiosn. Older versions used REL16 vs RELEXT16,
120 but now it seems all relocations are RELEXT16. We use all RELEXT16.
122 The cpu version is kind of a waste of time as well. There is one
123 instruction (RND) for LP devices only, and several for devices with
124 extended addressing only. We include it for compatibility.
126 static enum address_mode amode = c_mode;
127 static enum cpu_version cpu = VNONE;
129 /* include string substitutions in listing? */
130 static int listing_sslist = 0;
131 /* did we do subsym substitutions on the line? */
132 static int substitution_line = 0;
133 /* last label seen */
134 static symbolS *last_label_seen = NULL;
135 /* this ensures that all new labels are unique */
136 static int local_label_id;
138 static struct hash_control *subsym_recurse_hash; /* prevent infinite recurse */
139 static struct hash_control *math_hash; /* built-in math functions */
140 /* allow maximum levels of macro nesting; level 0 is the main substitution
141 symbol table. The other assembler only does 32 levels, so there! */
142 static struct hash_control *subsym_hash[100];
143 /* keep track of local labels so we can substitute them before GAS sees them
144 since macros use their own 'namespace' for local labels, use a separate hash
146 We do our own local label handling 'cuz it's subtly different from the
149 We use our own macro nesting counter, since GAS overloads it when expanding
150 other things (like conditionals and repeat loops).
152 static int macro_level = 0;
153 static struct hash_control *local_label_hash[100];
154 /* keep track of struct/union tags */
155 static struct hash_control *stag_hash;
156 static struct hash_control *op_hash;
157 static struct hash_control *parop_hash;
158 static struct hash_control *reg_hash;
159 static struct hash_control *mmreg_hash;
160 static struct hash_control *cc_hash;
161 static struct hash_control *cc2_hash;
162 static struct hash_control *cc3_hash;
163 static struct hash_control *sbit_hash;
164 static struct hash_control *misc_symbol_hash;
166 static char *subsym_substitute PARAMS ((char *line, int forced));
167 static char *subsym_lookup PARAMS ((char *name, int nest_level));
168 static void subsym_create_or_replace PARAMS ((char *name, char *value));
169 static float math_ceil PARAMS ((float, float));
170 static float math_cvi PARAMS ((float, float));
171 static float math_floor PARAMS ((float, float));
172 static float math_fmod PARAMS ((float, float));
173 static float math_int PARAMS ((float, float));
174 static float math_round PARAMS ((float, float));
175 static float math_sgn PARAMS ((float, float));
176 static float math_trunc PARAMS ((float, float));
177 static float math_acos PARAMS ((float, float));
178 static float math_asin PARAMS ((float, float));
179 static float math_atan PARAMS ((float, float));
180 static float math_atan2 PARAMS ((float, float));
181 static float math_cosh PARAMS ((float, float));
182 static float math_cos PARAMS ((float, float));
183 static float math_cvf PARAMS ((float, float));
184 static float math_exp PARAMS ((float, float));
185 static float math_fabs PARAMS ((float, float));
186 static float math_ldexp PARAMS ((float, float));
187 static float math_log10 PARAMS ((float, float));
188 static float math_log PARAMS ((float, float));
189 static float math_max PARAMS ((float, float));
190 static float math_pow PARAMS ((float, float));
191 static float math_sin PARAMS ((float, float));
192 static float math_sinh PARAMS ((float, float));
193 static float math_sqrt PARAMS ((float, float));
194 static float math_tan PARAMS ((float, float));
195 static float math_tanh PARAMS ((float, float));
198 symbolS *sym; /* symbol for this stag; value is offset */
199 const char *name; /* shortcut to symbol name */
200 bfd_vma size; /* size of struct/union */
201 int current_bitfield_offset; /* temporary for tracking fields */
203 struct stag_field { /* list of fields */
205 bfd_vma offset; /* of start of this field */
206 int bitfield_offset; /* of start of this field */
207 struct stag *stag; /* if field is struct/union */
208 struct stag_field *next;
210 /* for nesting; used only in stag construction */
211 struct stag *inner; /* enclosed .struct */
212 struct stag *outer; /* enclosing .struct */
213 } *current_stag = NULL;
215 static segT stag_saved_seg;
216 static subsegT stag_saved_subseg;
218 /* output a single character (upper octect is zero) */
220 tic54x_emit_char (char c)
224 exp.X_op = O_constant;
225 exp.X_add_number = c;
229 /* walk backwards in the frag chain */
231 frag_prev (frag, seg)
235 segment_info_type *seginfo = seg_info (seg);
238 for (fragp = seginfo->frchainP->frch_root;fragp;fragp = fragp->fr_next)
239 if (fragp->fr_next == frag)
245 bit_offset_frag (frag, seg)
251 if (frag->fr_fix == 0
252 && frag->fr_opcode == NULL
253 && frag->tc_frag_data == 0)
254 frag = frag_prev (frag, seg);
261 /* return the number of bits allocated in the most recent word, or zero if
262 none. .field/.space/.bes may leave words partially allocated */
264 frag_bit_offset (frag, seg)
268 frag = bit_offset_frag (frag, seg);
271 return frag->fr_opcode != NULL ? -1 : frag->tc_frag_data;
276 /* read an expression from a C string; returns a pointer past the end of the
279 parse_expression (char *str, expressionS * exp)
284 tmp = input_line_pointer; /* Save line pointer. */
285 input_line_pointer = str;
287 s = input_line_pointer;
288 input_line_pointer = tmp; /* Restore line pointer. */
289 return s; /* Return pointer to where parsing stopped. */
292 /* .asg "character-string"|character-string, symbol
294 .eval is the only pseudo-op allowed to perform arithmetic on substitution
295 symbols. all other use of symbols defined with .asg are currently
300 int x ATTRIBUTE_UNUSED;
306 int quoted = *input_line_pointer == '"';
308 ILLEGAL_WITHIN_STRUCT ();
313 str = demand_copy_C_string (&len);
314 c = *input_line_pointer;
318 str = input_line_pointer;
319 while ((c = *input_line_pointer) != ',')
321 if (is_end_of_line[(int)*input_line_pointer])
323 ++input_line_pointer;
325 *input_line_pointer = 0;
329 as_bad (_("Comma and symbol expected for '.asg STRING, SYMBOL'"));
330 ignore_rest_of_line ();
334 name = ++input_line_pointer;
335 c = get_symbol_end (); /* Get terminator. */
336 if (!isalpha (*name))
338 as_bad ("symbols assigned with .asg must begin with a letter");
339 ignore_rest_of_line ();
343 tmp = xmalloc (strlen (str) + 1);
346 tmp = xmalloc (strlen (name) + 1);
349 subsym_create_or_replace (name, str);
350 *input_line_pointer = c;
351 demand_empty_rest_of_line ();
354 /* .eval expression, symbol
355 There's something screwy about this. The other assembler sometimes does and
356 sometimes doesn't substitute symbols defined with .eval.
357 We'll put the symbols into the subsym table as well as the normal symbol
358 table, since that's what works best.
362 int x ATTRIBUTE_UNUSED;
368 char valuestr[32], *tmp;
371 ILLEGAL_WITHIN_STRUCT ();
375 quoted = *input_line_pointer == '"';
377 ++input_line_pointer;
378 value = get_absolute_expression ();
381 if (*input_line_pointer != '"')
383 as_bad (_("Unterminated string after absolute expression"));
384 ignore_rest_of_line ();
387 ++input_line_pointer;
389 if (*input_line_pointer++ != ',')
391 as_bad (_("Comma and symbol expected for '.eval EXPR, SYMBOL'"));
392 ignore_rest_of_line ();
395 name = input_line_pointer;
396 c = get_symbol_end (); /* Get terminator. */
397 tmp = xmalloc (strlen (name)+1);
398 name = strcpy (tmp, name);
399 *input_line_pointer = c;
401 if (!isalpha (*name))
403 as_bad (_("symbols assigned with .eval must begin with a letter"));
404 ignore_rest_of_line ();
407 symbolP = symbol_new (name, absolute_section,
408 (valueT) value, &zero_address_frag);
409 SF_SET_LOCAL (symbolP);
410 symbol_table_insert (symbolP);
412 /* The "other" assembler sometimes doesn't put .eval's in the subsym table
413 But since there's not written rule as to when, don't even bother trying
414 to match their behavior */
415 sprintf (valuestr, "%d", value);
416 tmp = xmalloc (strlen (valuestr) + 1);
417 strcpy (tmp, valuestr);
418 subsym_create_or_replace (name, tmp);
420 demand_empty_rest_of_line ();
423 /* .bss symbol, size [, [blocking flag] [, alignment flag]
425 alignment is to a longword boundary; blocking is to 128-word boundary.
427 1) if there is a hole in memory, this directive should attempt to fill it
428 (not yet implemented).
430 2) if the blocking flag is not set, allocate at the current SPC
431 otherwise, check to see if the current SPC plus the space to be
432 allocated crosses the page boundary (128 words).
433 if there's not enough space, create a hole and align with the next page
435 (not yet implemented)
440 int x ATTRIBUTE_UNUSED;
447 subsegT current_subseg;
452 ILLEGAL_WITHIN_STRUCT ();
454 current_seg = now_seg; /* save current seg. */
455 current_subseg = now_subseg; /* save current subseg. */
457 name = input_line_pointer;
458 c = get_symbol_end (); /* Get terminator. */
461 as_bad (".bss size argument missing\n");
462 ignore_rest_of_line ();
466 ++input_line_pointer;
467 words = get_absolute_expression ();
470 as_bad (".bss size %d < 0!", words);
471 ignore_rest_of_line ();
475 if (*input_line_pointer == ',')
477 /* the blocking flag may be missing */
478 ++input_line_pointer;
479 if (*input_line_pointer != ',')
480 block = get_absolute_expression ();
484 if (*input_line_pointer == ',')
486 ++input_line_pointer;
487 align = get_absolute_expression ();
495 subseg_set (bss_section, 0);
496 symbolP = symbol_find_or_make (name);
498 if (S_GET_SEGMENT (symbolP) == bss_section)
499 symbolP->sy_frag->fr_symbol = (symbolS *) NULL;
501 symbol_set_frag (symbolP, frag_now);
502 p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
503 (offsetT)(words << 1), (char *) 0);
504 *p = 0; /* fill char. */
506 S_SET_SEGMENT (symbolP, bss_section);
508 /* The symbol may already have been created with a preceding
509 ".globl" directive -- be careful not to step on storage class
510 in that case. Otherwise, set it to static. */
511 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
512 S_SET_STORAGE_CLASS (symbolP, C_STAT);
516 /* s_align eats end of line; restore it */
518 --input_line_pointer;
522 bss_section->flags |= SEC_BLOCK;
524 subseg_set (current_seg, current_subseg); /* restore current seg. */
525 demand_empty_rest_of_line ();
529 stag_add_field_symbols (struct stag *stag,
533 const char *root_stag_name)
535 char prefix[strlen (path) + 2];
536 struct stag_field *field = stag->field;
538 /* construct a symbol for every field contained within this structure
539 including fields within structure fields
541 strcpy (prefix, path);
543 strcat (prefix, ".");
545 while (field != NULL)
547 int len = strlen (prefix) + strlen (field->name) + 2;
548 char *name = xmalloc (len);
549 strcpy (name, prefix);
550 strcat (name, field->name);
555 sym = symbol_new (name, absolute_section,
556 (field->stag ? field->offset :
557 (valueT)(base_offset + field->offset)),
560 symbol_table_insert (sym);
564 char *replacement = xmalloc (strlen (name) + strlen (stag->name) + 2);
565 strcpy (replacement, S_GET_NAME (rootsym));
566 strcat (replacement, "+");
567 strcat (replacement, root_stag_name);
568 strcat (replacement, name + strlen (S_GET_NAME (rootsym)));
569 hash_insert (subsym_hash[0], name, replacement);
572 /* recurse if the field is a structure
573 note the field offset is relative to the outermost struct
575 if (field->stag != NULL)
576 stag_add_field_symbols (field->stag, name,
578 rootsym, root_stag_name);
583 /* keep track of stag fields so that when structures are nested we can add the
584 complete dereferencing symbols to the symbol table */
586 stag_add_field (struct stag *parent, const char *name, bfd_vma offset,
589 struct stag_field *sfield = xmalloc (sizeof (struct stag_field));
591 memset (sfield, 0, sizeof (*sfield));
592 sfield->name = strcpy (xmalloc (strlen (name)+1), name);
593 sfield->offset = offset;
594 sfield->bitfield_offset = parent->current_bitfield_offset;
596 if (parent->field == NULL)
597 parent->field = sfield;
599 struct stag_field *sf = parent->field;
600 while (sf->next != NULL)
604 /* only create a symbol for this field if the parent has no name */
605 if (!strncmp (".fake", parent->name, 5))
607 symbolS *sym = symbol_new (name, absolute_section,
608 (valueT)offset, &zero_address_frag);
610 symbol_table_insert (sym);
614 /* [STAG] .struct [OFFSET]
615 start defining structure offsets (symbols in absolute section)
619 tic54x_struct (int arg)
621 int start_offset = 0;
626 /* starting a new struct, switch to absolute section */
627 stag_saved_seg = now_seg;
628 stag_saved_subseg = now_subseg;
629 subseg_set (absolute_section, 0);
631 /* align the current pointer */
632 else if (current_stag->current_bitfield_offset != 0)
634 ++abs_section_offset;
635 current_stag->current_bitfield_offset = 0;
638 /* offset expression is only meaningful for global .structs */
641 /* offset is ignored in inner structs */
643 if (!is_end_of_line[(int)*input_line_pointer])
644 start_offset = get_absolute_expression ();
651 /* nesting, link to outer one */
652 current_stag->inner = (struct stag *)xmalloc (sizeof (struct stag));
653 memset (current_stag->inner, 0, sizeof (struct stag));
654 current_stag->inner->outer = current_stag;
655 current_stag = current_stag->inner;
657 as_warn (_("Offset on nested structures is ignored"));
658 start_offset = abs_section_offset;
662 current_stag = (struct stag *)xmalloc (sizeof (struct stag));
663 memset (current_stag, 0, sizeof (struct stag));
664 abs_section_offset = start_offset;
666 current_stag->is_union = is_union;
668 if (line_label == NULL)
670 static int struct_count = 0;
671 char fake[] = ".fake_stagNNNNNNN";
672 sprintf (fake, ".fake_stag%d", struct_count++);
673 current_stag->sym = symbol_new (fake, absolute_section,
674 (valueT)abs_section_offset,
679 char label[strlen (S_GET_NAME (line_label)) + 1];
680 strcpy (label, S_GET_NAME (line_label));
681 current_stag->sym = symbol_new (label, absolute_section,
682 (valueT)abs_section_offset,
685 current_stag->name = S_GET_NAME (current_stag->sym);
686 SF_SET_LOCAL (current_stag->sym);
687 /* nested .structs don't go into the symbol table */
688 if (current_stag->outer == NULL)
689 symbol_table_insert (current_stag->sym);
694 /* [LABEL] .endstruct
695 finish defining structure offsets; optional LABEL's value will be the size
699 tic54x_endstruct (int is_union)
703 !strncmp (current_stag->name, ".fake", 5) ? "" : current_stag->name;
704 if (!current_stag || current_stag->is_union != is_union)
706 as_bad (_(".end%s without preceding .%s"),
707 is_union ? "union" : "struct",
708 is_union ? "union" : "struct");
709 ignore_rest_of_line ();
713 /* align end of structures */
714 if (current_stag->current_bitfield_offset)
716 ++abs_section_offset;
717 current_stag->current_bitfield_offset = 0;
720 if (current_stag->is_union)
721 size = current_stag->size;
723 size = abs_section_offset - S_GET_VALUE (current_stag->sym);
724 if (line_label != NULL)
726 S_SET_VALUE (line_label, size);
727 symbol_table_insert (line_label);
731 /* union size has already been calculated */
732 if (!current_stag->is_union)
733 current_stag->size = size;
734 /* nested .structs don't get put in the stag table */
735 if (current_stag->outer == NULL)
737 hash_insert (stag_hash, current_stag->name, current_stag);
738 stag_add_field_symbols (current_stag, path,
739 S_GET_VALUE (current_stag->sym),
742 current_stag = current_stag->outer;
744 /* if this is a nested .struct/.union, add it as a field to the enclosing
745 one. otherwise, restore the section we were in */
746 if (current_stag != NULL)
748 stag_add_field (current_stag, current_stag->inner->name,
749 S_GET_VALUE (current_stag->inner->sym),
750 current_stag->inner);
753 subseg_set (stag_saved_seg, stag_saved_subseg);
757 Reference a structure within a structure, as a sized field with an optional
759 If used outside of a .struct/.endstruct, overlays the given structure
760 format on the existing allocated space.
764 int ignore ATTRIBUTE_UNUSED;
766 char *name = input_line_pointer;
767 int c = get_symbol_end ();
768 struct stag *stag = (struct stag *)hash_find (stag_hash, name);
773 as_bad (_("Unrecognized struct/union tag '%s'"), name);
775 as_bad (_(".tag requires a structure tag"));
776 ignore_rest_of_line ();
779 if (line_label == NULL)
781 as_bad (_("Label required for .tag"));
782 ignore_rest_of_line ();
787 char label[strlen (S_GET_NAME (line_label))+1];
788 strcpy (label, S_GET_NAME (line_label));
789 if (current_stag != NULL)
790 stag_add_field (current_stag, label,
791 abs_section_offset - S_GET_VALUE (current_stag->sym),
795 symbolS *sym = symbol_find (label);
798 as_bad (_(".tag target '%s' undefined"), label);
799 ignore_rest_of_line ();
802 stag_add_field_symbols (stag, S_GET_NAME (sym),
803 S_GET_VALUE (stag->sym), sym, stag->name);
807 /* bump by the struct size, but only if we're within a .struct section */
808 if (current_stag != NULL && !current_stag->is_union)
809 abs_section_offset += stag->size;
811 *input_line_pointer = c;
812 demand_empty_rest_of_line ();
816 /* handle all .byte, .char, .double, .field, .float, .half, .int, .long,
817 .short, .string, .ubyte, .uchar, .uhalf, .uint, .ulong, .ushort, .uword,
821 tic54x_struct_field (int type)
825 int new_bitfield_offset = 0;
826 int field_align = current_stag->current_bitfield_offset != 0;
827 int longword_align = 0;
830 if (!is_end_of_line[(int)*input_line_pointer])
831 count = get_absolute_expression ();
847 case '*': /* string */
856 case '.': /* bitfield */
858 if (count < 1 || count > 32)
860 as_bad (_(".field count '%d' out of range (1 <= X <= 32)"), count);
861 ignore_rest_of_line ();
864 if (current_stag->current_bitfield_offset + count > 16)
866 /* set the appropriate size and new field offset */
874 new_bitfield_offset = count - 16;
878 new_bitfield_offset = count;
884 new_bitfield_offset = current_stag->current_bitfield_offset + count;
888 as_bad (_("Unrecognized field type '%c'"), type);
889 ignore_rest_of_line ();
895 /* align to the actual starting position of the field */
896 current_stag->current_bitfield_offset = 0;
897 ++abs_section_offset;
899 /* align to longword boundary */
900 if (longword_align && (abs_section_offset & 0x1))
901 ++abs_section_offset;
903 if (line_label == NULL)
905 static int fieldno = 0;
906 char fake[] = ".fake_fieldNNNNN";
907 sprintf (fake, ".fake_field%d", fieldno++);
908 stag_add_field (current_stag, fake,
909 abs_section_offset - S_GET_VALUE (current_stag->sym),
914 char label[strlen (S_GET_NAME (line_label) + 1)];
915 strcpy (label, S_GET_NAME (line_label));
916 stag_add_field (current_stag, label,
917 abs_section_offset - S_GET_VALUE (current_stag->sym),
921 if (current_stag->is_union)
923 /* Note we treat the element as if it were an array of COUNT */
924 if (current_stag->size < (unsigned)size * count)
925 current_stag->size = size * count;
929 abs_section_offset += (unsigned)size * count;
930 current_stag->current_bitfield_offset = new_bitfield_offset;
935 /* Handle .byte, .word. .int, .long and all variants */
936 int emitting_long = 0;
938 tic54x_cons (int type)
940 register unsigned int c;
943 /* if we're within a .struct construct, don't actually allocate space */
944 if (current_stag != NULL)
946 tic54x_struct_field (type);
950 #ifdef md_flush_pending_output
951 md_flush_pending_output ();
954 generate_lineno_debug ();
956 /* align long words to long word boundaries (4 octets) */
957 if (type == 'l' || type == 'L')
959 frag_align (2, 0, 2);
960 /* if there's a label, assign it to the first allocated word */
961 if (line_label != NULL)
963 symbol_set_frag (line_label, frag_now);
964 S_SET_VALUE (line_label, frag_now_fix ());
988 if (*input_line_pointer == '"')
990 input_line_pointer++;
991 while (is_a_char (c = next_char_of_string ()))
992 tic54x_emit_char (c);
993 know (input_line_pointer[-1] == '\"');
999 input_line_pointer = parse_expression (input_line_pointer, &exp);
1000 if (exp.X_op == O_constant)
1002 offsetT value = exp.X_add_number;
1003 /* truncate overflows */
1007 if ((value > 0 && value > 0xFF)
1008 || (value < 0 && value < - 0x100))
1009 as_warn ("Overflow in expression, truncated to 8 bits");
1012 if ((value > 0 && value > 0xFFFF)
1013 || (value < 0 && value < - 0x10000))
1014 as_warn ("Overflow in expression, truncated to 16 bits");
1018 if (exp.X_op != O_constant && octets < 2)
1020 /* Disallow .byte with a non constant expression that will
1021 require relocation. */
1022 as_bad (_("Relocatable values require at least WORD storage"));
1023 ignore_rest_of_line ();
1027 if (exp.X_op != O_constant
1031 /* FIXME -- at one point TI tools used to output REL16
1032 relocations, but I don't think the latest tools do at all
1033 The current tools output extended relocations regardless of
1034 the addresing mode (I actually think that ".c_mode" is
1035 totally ignored in the latest tools) */
1038 emit_expr (&exp, 4);
1044 emitting_long = octets == 4;
1045 emit_expr (&exp, (octets == 1) ? 2 : octets);
1050 while (*input_line_pointer++ == ',');
1052 input_line_pointer--; /* Put terminator back into stream. */
1053 demand_empty_rest_of_line ();
1056 /* .global <symbol>[,...,<symbolN>]
1057 .def <symbol>[,...,<symbolN>]
1058 .ref <symbol>[,...,<symbolN>]
1060 These all identify global symbols.
1062 .def means the symbol is defined in the current module and can be accessed
1063 by other files. The symbol should be placed in the symbol table.
1065 .ref means the symbol is used in the current module but defined in another
1066 module. The linker is to resolve this symbol's definition at link time.
1068 .global should act as a .ref or .def, as needed.
1070 global, def and ref all have symbol storage classes of C_EXT.
1072 I can't identify any difference in how the "other" c54x assembler treats
1073 these, so we ignore the type here.
1076 tic54x_global (type)
1084 as_warn (_("Use of .def/.ref is deprecated. Use .global instead"));
1086 ILLEGAL_WITHIN_STRUCT ();
1090 name = input_line_pointer;
1091 c = get_symbol_end ();
1092 symbolP = symbol_find_or_make (name);
1094 *input_line_pointer = c;
1095 S_SET_STORAGE_CLASS (symbolP, C_EXT);
1098 input_line_pointer++;
1099 if (is_end_of_line[(int)*input_line_pointer])
1100 c = *input_line_pointer;
1105 demand_empty_rest_of_line ();
1108 /* remove the symbol from the local label hash lookup */
1110 tic54x_remove_local_label (key, value)
1112 PTR value ATTRIBUTE_UNUSED;
1114 PTR *elem = hash_delete (local_label_hash[macro_level], key);
1118 /* Reset all local labels */
1120 tic54x_clear_local_labels (ignored)
1121 int ignored ATTRIBUTE_UNUSED;
1123 hash_traverse (local_label_hash[macro_level], tic54x_remove_local_label);
1129 .sect "section name"
1132 make sure local labels get cleared when changing sections
1134 ARG is 't' for text, 'd' for data, or '*' for a named section
1136 For compatibility, '*' sections have SEC_DATA set instead of SEC_CODE
1139 tic54x_sect (int arg)
1141 ILLEGAL_WITHIN_STRUCT ();
1143 /* local labels are cleared when changing sections */
1144 tic54x_clear_local_labels (0);
1148 else if (arg == 'd')
1154 /* if there are quotes, remove them */
1155 if (*input_line_pointer == '"')
1157 name = demand_copy_C_string (&len);
1158 demand_empty_rest_of_line ();
1159 name = strcpy (xmalloc (len+10), name);
1164 name = input_line_pointer;
1165 c = get_symbol_end ();
1166 name = strcpy (xmalloc (len+10), name);
1167 *input_line_pointer = c;
1168 demand_empty_rest_of_line ();
1170 /* make sure all named initialized sections are SEC_DATA */
1171 strcat (name, ",\"w\"\n");
1172 input_scrub_insert_line (name);
1173 obj_coff_section (0);
1175 /* if there was a line label, make sure that it gets assigned the proper
1176 section. This is for compatibility, even though the actual behavior
1177 is not explicitly defined. For consistency, we make .sect behave
1178 like .usect, since that is probably what people expect */
1179 if (line_label != NULL)
1181 S_SET_SEGMENT (line_label, now_seg);
1182 symbol_set_frag (line_label, frag_now);
1183 S_SET_VALUE (line_label, frag_now_fix ());
1184 if (S_GET_STORAGE_CLASS (line_label) != C_EXT)
1185 S_SET_STORAGE_CLASS (line_label, C_LABEL);
1190 /* [symbol] .space space_in_bits
1191 [symbol] .bes space_in_bits
1192 BES puts the symbol at the *last* word allocated
1194 cribbed from s_space
1197 tic54x_space (int arg)
1203 int bits_per_byte = (OCTETS_PER_BYTE * 8);
1205 symbolS *label = line_label;
1208 ILLEGAL_WITHIN_STRUCT ();
1210 #ifdef md_flush_pending_output
1211 md_flush_pending_output ();
1214 /* read the bit count */
1217 /* some expressions are unresolvable until later in the assembly pass;
1218 postpone until relaxation/fixup. we also have to postpone if a previous
1219 partial allocation has not been completed yet.
1221 if (exp.X_op != O_constant || frag_bit_offset (frag_now, now_seg) == -1)
1223 struct bit_info *bi = xmalloc (sizeof (struct bit_info));
1229 p = frag_var (rs_machine_dependent,
1230 65536*2, 1, (relax_substateT) 0,
1231 make_expr_symbol (&exp), (offsetT) 0,
1239 /* reduce the required size by any bit offsets currently left over
1240 from a previous .space/.bes/.field directive */
1241 bit_offset = frag_now->tc_frag_data;
1242 if (bit_offset != 0 && bit_offset < 16)
1244 int spare_bits = bits_per_byte - bit_offset;
1245 if (spare_bits >= exp.X_add_number)
1247 /* don't have to do anything; sufficient bits have already been
1248 allocated; just point the label to the right place */
1251 symbol_set_frag (label, frag_now);
1252 S_SET_VALUE (label, frag_now_fix () - 1);
1255 frag_now->tc_frag_data += exp.X_add_number;
1258 exp.X_add_number -= spare_bits;
1259 /* set the label to point to the first word allocated, which in this
1260 case is the previous word, which was only partially filled */
1261 if (!bes && label != NULL)
1263 symbol_set_frag (label, frag_now);
1264 S_SET_VALUE (label, frag_now_fix () - 1);
1268 /* convert bits to bytes/words and octets, rounding up */
1269 words = ((exp.X_add_number + bits_per_byte - 1) / bits_per_byte);
1270 /* how many do we have left over? */
1271 bit_offset = exp.X_add_number % bits_per_byte;
1272 octets = words * OCTETS_PER_BYTE;
1275 as_warn (_(".space/.bes repeat count is negative, ignored"));
1278 else if (octets == 0)
1280 as_warn (_(".space/.bes repeat count is zero, ignored"));
1284 /* If we are in the absolute section, just bump the offset. */
1285 if (now_seg == absolute_section)
1287 abs_section_offset += words;
1288 if (bes && label != NULL)
1289 S_SET_VALUE (label, abs_section_offset - 1);
1290 frag_now->tc_frag_data = bit_offset;
1295 p = frag_var (rs_fill, 1, 1,
1296 (relax_substateT) 0, (symbolS *) 0,
1297 (offsetT) octets, (char *) 0);
1299 /* make note of how many bits of this word we've allocated so far */
1300 frag_now->tc_frag_data = bit_offset;
1302 /* .bes puts label at *last* word allocated */
1303 if (bes && label != NULL)
1305 symbol_set_frag (label, frag_now);
1306 S_SET_VALUE (label, frag_now_fix ()-1);
1314 demand_empty_rest_of_line ();
1317 /* [symbol] .usect "section-name", size-in-words
1318 [, [blocking-flag] [, alignment-flag]]
1320 Unitialized section.
1321 Non-zero blocking means that if the section would cross a page (128-word)
1322 boundary, it will be page-aligned.
1323 Non-zero alignment aligns on a longword boundary.
1325 Has no effect on the current section.
1329 int x ATTRIBUTE_UNUSED;
1336 int size, blocking_flag, alignment_flag;
1338 subsegT current_subseg;
1341 ILLEGAL_WITHIN_STRUCT ();
1343 current_seg = now_seg; /* save current seg. */
1344 current_subseg = now_subseg; /* save current subseg. */
1346 if (*input_line_pointer == '"')
1347 input_line_pointer++;
1348 section_name = input_line_pointer;
1349 c = get_symbol_end (); /* Get terminator. */
1350 input_line_pointer++; /* Skip null symbol terminator. */
1351 name = xmalloc (input_line_pointer - section_name + 1);
1352 strcpy (name, section_name);
1354 if (*input_line_pointer == ',')
1355 ++input_line_pointer;
1358 as_bad (_("Missing size argument"));
1359 ignore_rest_of_line ();
1363 size = get_absolute_expression ();
1365 /* read a possibly present third argument (blocking flag) */
1366 if (*input_line_pointer == ',')
1368 ++input_line_pointer;
1369 if (*input_line_pointer != ',')
1370 blocking_flag = get_absolute_expression ();
1374 /* read a possibly present fourth argument (alignment flag) */
1375 if (*input_line_pointer == ',')
1377 ++input_line_pointer;
1378 alignment_flag = get_absolute_expression ();
1384 blocking_flag = alignment_flag = 0;
1386 seg = subseg_new (name, 0);
1387 flags = bfd_get_section_flags (stdoutput, seg) | SEC_ALLOC;
1391 /* s_align eats end of line; restore it */
1393 --input_line_pointer;
1396 if (line_label != NULL)
1398 S_SET_SEGMENT (line_label, seg);
1399 symbol_set_frag (line_label, frag_now);
1400 S_SET_VALUE (line_label, frag_now_fix ());
1401 /* set scl to label, since that's what TI does */
1402 if (S_GET_STORAGE_CLASS (line_label) != C_EXT)
1403 S_SET_STORAGE_CLASS (line_label, C_LABEL);
1406 seg_info (seg)->bss = 1; /* Uninitialized data. */
1408 p = frag_var (rs_fill, 1, 1,
1409 (relax_substateT) 0, (symbolS *) line_label,
1410 size * OCTETS_PER_BYTE, (char *) 0);
1416 if (!bfd_set_section_flags (stdoutput, seg, flags))
1417 as_warn ("Error setting flags for \"%s\": %s", name,
1418 bfd_errmsg (bfd_get_error ()));
1420 subseg_set (current_seg, current_subseg); /* Restore current seg. */
1421 demand_empty_rest_of_line ();
1424 static enum cpu_version
1425 lookup_version (const char *ver)
1427 enum cpu_version version = VNONE;
1428 if (ver[0] == '5' && ver[1] == '4')
1430 if (strlen (ver) == 3 &&
1431 (ver[2] == '1' || ver[2] == '2' || ver[2] == '3' ||
1432 ver[2] == '5' || ver[2] == '8' || ver[2] == '9'))
1433 version = ver[2] - '0';
1434 else if (strlen (ver) == 5 &&
1435 toupper (ver[3]) == 'L' &&
1436 toupper (ver[4]) == 'P' &&
1437 (ver[2] == '5' || ver[2] == '6'))
1438 version = ver[2] - '0' + 10;
1445 set_cpu (enum cpu_version version)
1448 if (version == V545LP || version == V546LP)
1450 symbolS *symbolP = symbol_new ("__allow_lp", absolute_section,
1451 (valueT)1, &zero_address_frag);
1452 SF_SET_LOCAL (symbolP);
1453 symbol_table_insert (symbolP);
1457 /* .version cpu-version
1458 cpu-version may be one of the following:
1468 This is for compatibility only. It currently has no affect on assembly.
1471 static int cpu_needs_set = 1;
1474 int x ATTRIBUTE_UNUSED;
1476 enum cpu_version version = VNONE;
1477 enum cpu_version old_version = cpu;
1481 ILLEGAL_WITHIN_STRUCT ();
1484 ver = input_line_pointer;
1485 while (!is_end_of_line[(int)*input_line_pointer])
1486 ++input_line_pointer;
1487 c = *input_line_pointer;
1488 *input_line_pointer = 0;
1490 version = lookup_version (ver);
1492 if (cpu != VNONE && cpu != version)
1493 as_warn (_("CPU version has already been set"));
1495 if (version == VNONE)
1497 as_bad (_("Unrecognized version '%s'"), ver);
1498 ignore_rest_of_line ();
1501 else if (assembly_begun && version != old_version)
1503 as_bad (_("Changing of CPU version on the fly not supported"));
1504 ignore_rest_of_line ();
1510 *input_line_pointer = c;
1511 demand_empty_rest_of_line ();
1514 /* 'f' = float, 'x' = xfloat, 'd' = double, 'l' = ldouble */
1516 tic54x_float_cons (int type)
1518 if (current_stag != 0)
1520 tic54x_struct_field ('f');
1523 #ifdef md_flush_pending_output
1524 md_flush_pending_output ();
1526 /* align to long word boundary (4 octets) unless it's ".xfloat" */
1529 frag_align (2, 0, 2);
1530 /* if there's a label, assign it to the first allocated word */
1531 if (line_label != NULL)
1533 symbol_set_frag (line_label, frag_now);
1534 S_SET_VALUE (line_label, frag_now_fix ());
1541 /* The argument is capitalized if it should be zero-terminated
1542 's' is normal string with upper 8-bits zero-filled, 'p' is packed.
1543 Code copied from read.c, and slightly modified so that strings are packed
1544 and encoded into the correct octets.
1547 tic54x_stringer (int type)
1549 register unsigned int c;
1551 int append_zero = type == 'S' || type == 'P';
1552 int packed = type == 'p' || type == 'P';
1553 int last_char = -1; /* packed strings need two bytes at a time to encode */
1555 if (current_stag != NULL)
1557 tic54x_struct_field ('*');
1561 #ifdef md_flush_pending_output
1562 md_flush_pending_output ();
1565 c = ','; /* Do loop. */
1569 switch (*input_line_pointer)
1573 unsigned short value = get_absolute_expression ();
1574 FRAG_APPEND_1_CHAR (value&0xFF);
1575 FRAG_APPEND_1_CHAR ((value>>8)&0xFF);
1579 ++input_line_pointer; /*->1st char of string. */
1580 start = input_line_pointer;
1581 while (is_a_char (c = next_char_of_string ()))
1585 FRAG_APPEND_1_CHAR (c);
1586 FRAG_APPEND_1_CHAR (0);
1590 /* packed strings are filled MS octet first */
1591 if (last_char == -1)
1595 FRAG_APPEND_1_CHAR (c);
1596 FRAG_APPEND_1_CHAR (last_char);
1603 if (packed && last_char != -1)
1605 FRAG_APPEND_1_CHAR (0);
1606 FRAG_APPEND_1_CHAR (last_char);
1611 FRAG_APPEND_1_CHAR (0);
1612 FRAG_APPEND_1_CHAR (0);
1615 know (input_line_pointer[-1] == '\"');
1619 c = *input_line_pointer;
1620 if (!is_end_of_line[c])
1621 ++input_line_pointer;
1624 /* finish up any leftover packed string */
1625 if (packed && last_char != -1)
1627 FRAG_APPEND_1_CHAR (0);
1628 FRAG_APPEND_1_CHAR (last_char);
1630 demand_empty_rest_of_line ();
1634 tic54x_p2align (arg)
1635 int arg ATTRIBUTE_UNUSED;
1637 as_bad (_("p2align not supported on this target"));
1641 tic54x_align_words (int arg)
1643 /* only ".align" with no argument is allowed within .struct/.union */
1646 if (!is_end_of_line[(int)*input_line_pointer])
1649 as_warn (_("Argument to .even ignored"));
1651 count = get_absolute_expression ();
1654 if (current_stag != NULL && arg == 128)
1656 if (current_stag->current_bitfield_offset != 0)
1658 current_stag->current_bitfield_offset = 0;
1659 ++abs_section_offset;
1661 demand_empty_rest_of_line ();
1665 ILLEGAL_WITHIN_STRUCT ();
1667 s_align_bytes (count << 1);
1670 /* initialize multiple-bit fields withing a single word of memory
1673 tic54x_field (ignore)
1674 int ignore ATTRIBUTE_UNUSED;
1680 symbolS *label = line_label;
1682 if (current_stag != NULL)
1684 tic54x_struct_field ('.');
1688 input_line_pointer = parse_expression (input_line_pointer, &exp);
1690 if (*input_line_pointer == ',')
1692 ++input_line_pointer;
1693 size = get_absolute_expression ();
1694 if (size < 1 || size > 32)
1696 as_bad (_("Invalid field size, must be from 1 to 32"));
1697 ignore_rest_of_line ();
1702 /* truncate values to the field width */
1703 if (exp.X_op != O_constant)
1705 /* if the expression value is relocatable, the field size *must* be 16 */
1708 as_bad (_("field size must be 16 when value is relocatable"));
1709 ignore_rest_of_line ();
1713 frag_now->tc_frag_data = 0;
1714 emit_expr (&exp, 2);
1718 unsigned long fmask = (size == 32) ? 0xFFFFFFFF : (1ul << size) - 1;
1719 value = exp.X_add_number;
1720 exp.X_add_number &= fmask;
1721 if (value != (valueT)exp.X_add_number)
1722 as_warn (_("field value truncated"));
1723 value = exp.X_add_number;
1724 /* bits are stored MS first */
1727 frag_now->tc_frag_data = 0;
1729 md_number_to_chars (p, (value >> (size - 16)) & 0xFFFF, 2);
1734 int bit_offset = frag_bit_offset (frag_now, now_seg);
1735 fragS *alloc_frag = bit_offset_frag (frag_now, now_seg);
1736 if (bit_offset == -1)
1738 struct bit_info *bi = xmalloc (sizeof (struct bit_info));
1739 /* we don't know the previous offset at this time, so store the
1740 info we need and figure it out later */
1741 expressionS size_exp;
1742 size_exp.X_op = O_constant;
1743 size_exp.X_add_number = size;
1745 bi->type = TYPE_FIELD;
1747 p = frag_var (rs_machine_dependent,
1748 4, 1, (relax_substateT) 0,
1749 make_expr_symbol (&size_exp), (offsetT) 0,
1753 else if (bit_offset == 0 || bit_offset + size > 16)
1755 /* align a new field */
1757 frag_now->tc_frag_data = 0;
1758 alloc_frag = frag_now;
1762 /* put the new value entirely within the existing one */
1763 p = alloc_frag == frag_now ?
1764 frag_now->fr_literal + frag_now_fix_octets () - 2 :
1765 alloc_frag->fr_literal;
1768 symbol_set_frag (label, alloc_frag);
1769 if (alloc_frag == frag_now)
1770 S_SET_VALUE (label, frag_now_fix () - 1);
1774 value <<= 16 - alloc_frag->tc_frag_data - size;
1776 /* OR in existing value */
1777 if (alloc_frag->tc_frag_data)
1778 value |= ((unsigned short)p[1]<<8) | p[0];
1779 md_number_to_chars (p, value, 2);
1780 alloc_frag->tc_frag_data += size;
1781 if (alloc_frag->tc_frag_data == 16)
1782 alloc_frag->tc_frag_data = 0;
1786 demand_empty_rest_of_line ();
1789 /* Ideally, we want to check SEC_LOAD and SEC_HAS_CONTENTS, but those aren't
1790 available yet. seg_info ()->bss is the next best thing */
1792 tic54x_initialized_section (seg)
1795 return !seg_info (seg)->bss;
1798 /* .clink ["section name"]
1800 Marks the section as conditionally linked (link only if contents are
1801 referenced elsewhere.
1802 Without a name, refers to the current initialized section.
1803 Name is required for uninitialized sections.
1807 tic54x_clink (ignored)
1808 int ignored ATTRIBUTE_UNUSED;
1812 ILLEGAL_WITHIN_STRUCT ();
1814 if (*input_line_pointer == '\"')
1816 char *section_name = ++input_line_pointer;
1818 while (is_a_char (next_char_of_string ()))
1820 know (input_line_pointer[-1] == '\"');
1821 input_line_pointer[-1] = 0;
1822 name = xmalloc (input_line_pointer - section_name + 1);
1823 strcpy (name, section_name);
1825 seg = bfd_get_section_by_name (stdoutput, name);
1828 as_bad (_("Unrecognized section '%s'"), section_name);
1829 ignore_rest_of_line ();
1835 if (!tic54x_initialized_section (seg))
1837 as_bad (_("Current section is unitialized, "
1838 "section name required for .clink"));
1839 ignore_rest_of_line ();
1844 seg->flags |= SEC_CLINK;
1846 demand_empty_rest_of_line ();
1849 /* change the default include directory to be the current source file's
1850 directory, instead of the current working directory. If DOT is non-zero,
1851 set to "." instead */
1853 tic54x_set_default_include (dot)
1864 as_where (&curfile, &lineno);
1865 dir = strcpy (xmalloc (strlen (curfile)+1), curfile);
1866 tmp = strrchr (dir, '/');
1873 if (include_dir_count == 0)
1875 include_dirs = (char **) xmalloc (sizeof (*include_dirs));
1876 include_dir_count = 1;
1878 include_dirs[0] = dir;
1879 if (len > include_dir_maxlen)
1880 include_dir_maxlen = len;
1882 else if (include_dirs != NULL)
1883 include_dirs[0] = ".";
1887 .include "filename" | filename
1888 .copy "filename" | filename
1890 FIXME 'include' file should be omitted from any output listing,
1891 'copy' should be included in any output listing
1892 FIXME -- prevent any included files from changing listing (compat only)
1893 FIXME -- need to include source file directory in search path; what's a
1894 good way to do this?
1896 Entering/exiting included/copied file clears all local labels
1899 tic54x_include (ignored)
1900 int ignored ATTRIBUTE_UNUSED;
1902 char newblock[] = " .newblock\n";
1907 ILLEGAL_WITHIN_STRUCT ();
1911 if (*input_line_pointer == '"')
1913 filename = demand_copy_C_string (&len);
1914 demand_empty_rest_of_line ();
1918 filename = input_line_pointer;
1919 while (!is_end_of_line[(int)*input_line_pointer])
1920 ++input_line_pointer;
1921 c = *input_line_pointer;
1922 *input_line_pointer = '\0';
1923 filename = strcpy (xmalloc (strlen (filename)+1), filename);
1924 *input_line_pointer = c;
1925 demand_empty_rest_of_line ();
1927 /* Insert a partial line with the filename (for the sake of s_include)
1929 The included file will be inserted before the newblock, so that the
1930 newblock is executed after the included file is processed */
1931 input = xmalloc (sizeof (newblock) + strlen (filename) + 4);
1932 sprintf (input, "\"%s\"\n%s", filename, newblock);
1933 input_scrub_insert_line (input);
1935 tic54x_clear_local_labels (0);
1937 tic54x_set_default_include (0);
1943 tic54x_message (int type)
1949 ILLEGAL_WITHIN_STRUCT ();
1951 if (*input_line_pointer == '"')
1952 msg = demand_copy_C_string (&len);
1955 msg = input_line_pointer;
1956 while (! is_end_of_line[(int)*input_line_pointer])
1957 ++input_line_pointer;
1958 c = *input_line_pointer;
1959 *input_line_pointer = 0;
1960 msg = strcpy (xmalloc (strlen (msg) + 1), msg);
1961 *input_line_pointer = c;
1967 as_tsktsk ("%s", msg);
1970 as_warn ("%s", msg);
1977 demand_empty_rest_of_line ();
1981 define a special symbol that refers to the loadtime address rather than the
1982 runtime address within the current section.
1984 This symbol gets a special storage class so that when it is resolved, it is
1985 resolved relative to the load address (lma) of the section rather than the
1989 tic54x_label (ignored)
1990 int ignored ATTRIBUTE_UNUSED;
1992 char *name = input_line_pointer;
1996 ILLEGAL_WITHIN_STRUCT ();
1998 c = get_symbol_end ();
1999 symbolP = colon (name);
2000 S_SET_STORAGE_CLASS (symbolP, C_STATLAB);
2002 *input_line_pointer = c;
2003 demand_empty_rest_of_line ();
2008 install all memory-mapped register names into the symbol table as absolute
2012 tic54x_mmregs (ignored)
2013 int ignored ATTRIBUTE_UNUSED;
2017 ILLEGAL_WITHIN_STRUCT ();
2019 for (sym = (symbol *)mmregs; sym->name; sym++)
2021 symbolS *symbolP = symbol_new (sym->name, absolute_section,
2022 (valueT) sym->value, &zero_address_frag);
2023 SF_SET_LOCAL (symbolP);
2024 symbol_table_insert (symbolP);
2030 count defaults to 1024
2033 tic54x_loop (int count)
2035 ILLEGAL_WITHIN_STRUCT ();
2038 if (!is_end_of_line[(int)*input_line_pointer])
2039 count = get_absolute_expression ();
2041 do_repeat (count, "LOOP", "ENDLOOP");
2044 /* normally, endloop gets eaten by the preceding loop */
2046 tic54x_endloop (ignore)
2047 int ignore ATTRIBUTE_UNUSED;
2049 as_bad (_("ENDLOOP without corresponding LOOP"));
2050 ignore_rest_of_line ();
2057 tic54x_break (ignore)
2058 int ignore ATTRIBUTE_UNUSED;
2062 ILLEGAL_WITHIN_STRUCT ();
2065 if (!is_end_of_line[(int)*input_line_pointer])
2067 cond = get_absolute_expression ();
2071 end_repeat (substitution_line ? 1 : 0);
2076 set_address_mode (mode)
2080 if (mode == far_mode)
2082 symbolS *symbolP = symbol_new ("__allow_far", absolute_section,
2083 (valueT)1, &zero_address_frag);
2084 SF_SET_LOCAL (symbolP);
2085 symbol_table_insert (symbolP);
2089 static int address_mode_needs_set = 1;
2091 tic54x_address_mode (mode)
2094 if (assembly_begun && amode != (unsigned)mode)
2096 as_bad (_("Mixing of normal and extended addressing not supported"));
2097 ignore_rest_of_line ();
2100 if (mode == far_mode && cpu != VNONE && cpu != V548 && cpu != V549)
2102 as_bad (_("Extended addressing not supported on the specified CPU"));
2103 ignore_rest_of_line ();
2107 set_address_mode (mode);
2108 demand_empty_rest_of_line ();
2111 /* .sblock "section"|section [,...,"section"|section]
2112 designate initialized sections for blocking
2115 tic54x_sblock (ignore)
2116 int ignore ATTRIBUTE_UNUSED;
2120 ILLEGAL_WITHIN_STRUCT ();
2127 if (*input_line_pointer == '"')
2130 name = demand_copy_C_string (&len);
2134 char *section_name = input_line_pointer;
2135 c = get_symbol_end ();
2136 name = xmalloc (strlen (section_name)+1);
2137 strcpy (name, section_name);
2138 *input_line_pointer = c;
2141 seg = bfd_get_section_by_name (stdoutput, name);
2144 as_bad (_("Unrecognized section '%s'"), name);
2145 ignore_rest_of_line ();
2148 else if (!tic54x_initialized_section (seg))
2150 as_bad (_(".sblock may be used for initialized sections only"));
2151 ignore_rest_of_line ();
2154 seg->flags |= SEC_BLOCK;
2156 c = *input_line_pointer;
2157 if (!is_end_of_line[(int)c])
2158 ++input_line_pointer;
2161 demand_empty_rest_of_line ();
2164 /* symbol .set value
2167 value must be defined externals; no forward-referencing allowed
2168 symbols assigned with .set/.equ may not be redefined
2172 int ignore ATTRIBUTE_UNUSED;
2177 ILLEGAL_WITHIN_STRUCT ();
2181 as_bad (_("Symbol missing for .set/.equ"));
2182 ignore_rest_of_line ();
2185 name = xstrdup (S_GET_NAME (line_label));
2187 if ((symbolP = symbol_find (name)) == NULL
2188 && (symbolP = md_undefined_symbol (name)) == NULL)
2190 symbolP = symbol_new (name, absolute_section, 0, &zero_address_frag);
2191 S_SET_STORAGE_CLASS (symbolP, C_STAT);
2194 S_SET_DATA_TYPE (symbolP, T_INT);
2195 S_SET_SEGMENT (symbolP, absolute_section);
2196 symbol_table_insert (symbolP);
2197 pseudo_set (symbolP);
2198 demand_empty_rest_of_line ();
2203 list false conditional blocks
2206 tic54x_fclist (int show)
2209 listing &= ~LISTING_NOCOND;
2211 listing |= LISTING_NOCOND;
2212 demand_empty_rest_of_line ();
2216 tic54x_sslist (int show)
2218 ILLEGAL_WITHIN_STRUCT ();
2220 listing_sslist = show;
2223 /* .var SYM[,...,SYMN]
2224 define a substitution string to be local to a macro
2228 int ignore ATTRIBUTE_UNUSED;
2230 static char empty[] = "";
2234 ILLEGAL_WITHIN_STRUCT ();
2236 if (macro_level == 0)
2238 as_bad (_(".var may only be used within a macro definition"));
2239 ignore_rest_of_line ();
2244 if (!isalpha (*input_line_pointer))
2246 as_bad (_("Substitution symbols must begin with a letter"));
2247 ignore_rest_of_line ();
2250 name = input_line_pointer;
2251 c = get_symbol_end ();
2252 /* .var symbols start out with a null string */
2253 name = strcpy (xmalloc (strlen (name)+1), name);
2254 hash_insert (subsym_hash[macro_level], name, empty);
2255 *input_line_pointer = c;
2258 ++input_line_pointer;
2259 if (is_end_of_line[(int)*input_line_pointer])
2260 c = *input_line_pointer;
2265 demand_empty_rest_of_line ();
2268 /* .mlib <macro library filename>
2270 Macro libraries are archived (standard AR-format) text macro definitions
2271 Expand the file and include it.
2273 FIXME need to try the source file directory as well
2276 tic54x_mlib (ignore)
2277 int ignore ATTRIBUTE_UNUSED;
2284 ILLEGAL_WITHIN_STRUCT ();
2286 /* parse the filename */
2287 if (*input_line_pointer == '"')
2289 if ((filename = demand_copy_C_string (&len)) == NULL)
2296 while (! is_end_of_line[(int)*input_line_pointer]
2297 && !isspace (*input_line_pointer))
2299 obstack_1grow (¬es, *input_line_pointer);
2300 ++input_line_pointer;
2303 obstack_1grow (¬es, '\0');
2304 filename = obstack_finish (¬es);
2306 demand_empty_rest_of_line ();
2308 tic54x_set_default_include (0);
2309 path = xmalloc ((unsigned long) len + include_dir_maxlen + 5);
2310 for (i=0;i < include_dir_count; i++)
2313 strcpy (path, include_dirs[i]);
2315 strcat (path, filename);
2316 if ((try = fopen (path, "r")) != NULL)
2322 if (i >= include_dir_count)
2328 /* FIXME: if path is found, malloc'd storage is not freed. Of course, this
2329 happens all over the place, and since the assembler doesn't usually keep
2330 running for a very long time, it really doesn't matter... */
2331 register_dependency (path);
2333 /* expand all archive entries to temporary files and include them */
2334 abfd = bfd_openr (path, NULL);
2337 as_bad (_("Can't open macro library file '%s' for reading."), path);
2338 as_perror ("%s", path);
2339 ignore_rest_of_line ();
2342 if (!bfd_check_format (abfd, bfd_archive))
2344 as_bad (_("File '%s' not in macro archive format"), path);
2345 ignore_rest_of_line ();
2349 /* open each BFD as binary (it should be straight ASCII text) */
2350 for (mbfd = bfd_openr_next_archived_file (abfd, NULL);
2351 mbfd != NULL; mbfd = bfd_openr_next_archived_file (abfd, mbfd))
2353 /* get a size at least as big as the archive member */
2354 bfd_size_type size = bfd_get_size (mbfd);
2355 char *buf = xmalloc (size);
2356 char *fname = tmpnam (NULL);
2359 /* we're not sure how big it is, but it will be smaller than "size" */
2360 bfd_read (buf, size, 1, mbfd);
2362 /* write to a temporary file, then use s_include to include it
2365 ftmp = fopen (fname, "w+b");
2366 fwrite ((void *)buf, size, 1, ftmp);
2367 if (buf[size-1] != '\n')
2368 fwrite ("\n", 1, 1, ftmp);
2371 input_scrub_insert_file (fname);
2376 const pseudo_typeS md_pseudo_table[] =
2378 { "algebraic", s_ignore, 0 },
2379 { "align", tic54x_align_words, 128 },
2380 { "even", tic54x_align_words, 2 },
2381 { "asg", tic54x_asg, 0 },
2382 { "eval", tic54x_eval, 0 },
2383 { "bss", tic54x_bss, 0 },
2384 { "byte", tic54x_cons, 'b' },
2385 { "ubyte", tic54x_cons, 'B' },
2386 { "char", tic54x_cons, 'c' },
2387 { "uchar", tic54x_cons, 'C' },
2388 { "clink", tic54x_clink, 0 },
2389 { "c_mode", tic54x_address_mode, c_mode },
2390 { "copy", tic54x_include, 'c' },
2391 { "include", tic54x_include, 'i' },
2392 { "data", tic54x_sect, 'd' },
2393 { "double", tic54x_float_cons, 'd' },
2394 { "ldouble", tic54x_float_cons, 'l' },
2395 { "drlist", s_ignore, 0 },
2396 { "drnolist", s_ignore, 0 },
2397 { "emsg", tic54x_message, 'e' },
2398 { "mmsg", tic54x_message, 'm' },
2399 { "wmsg", tic54x_message, 'w' },
2400 /*{ "end", s_end, 0 }, */
2401 { "far_mode", tic54x_address_mode, far_mode },
2402 { "fclist", tic54x_fclist, 1 },
2403 { "fcnolist", tic54x_fclist, 0 },
2404 { "field", tic54x_field, -1 },
2405 { "float", tic54x_float_cons, 'f' },
2406 { "xfloat", tic54x_float_cons, 'x' },
2407 { "global", tic54x_global, 'g' },
2408 { "def", tic54x_global, 'd' },
2409 { "ref", tic54x_global, 'r' },
2410 { "half", tic54x_cons, 'h' },
2411 { "uhalf", tic54x_cons, 'H' },
2412 { "short", tic54x_cons, 's' },
2413 { "ushort", tic54x_cons, 'S' },
2414 { "if", s_if, (int)O_ne },
2415 { "elseif", s_elseif, (int)O_ne },
2416 { "else", s_else, 0 },
2417 { "endif", s_endif, 0 },
2418 { "int", tic54x_cons, 'i' },
2419 { "uint", tic54x_cons, 'I' },
2420 { "word", tic54x_cons, 'w' },
2421 { "uword", tic54x_cons, 'W' },
2422 { "label", tic54x_label, 0 }, /* loadtime address */
2423 { "length", s_ignore, 0 },
2424 { "width", s_ignore, 0 },
2425 /*{ "list", listing_list, 1 }, */
2426 /*{ "nolist", listing_list, 0 }, */
2427 { "long", tic54x_cons, 'l' },
2428 { "ulong", tic54x_cons, 'L' },
2429 { "xlong", tic54x_cons, 'x' },
2430 { "loop", tic54x_loop, 1024 },
2431 { "break", tic54x_break, 0 },
2432 { "endloop", tic54x_endloop, 0 },
2433 { "mlib", tic54x_mlib, 0 },
2434 { "mlist", s_ignore, 0 },
2435 { "mnolist", s_ignore, 0 },
2436 { "mmregs", tic54x_mmregs, 0 },
2437 { "newblock", tic54x_clear_local_labels, 0 },
2438 { "option", s_ignore, 0 },
2439 { "p2align", tic54x_p2align, 0 },
2440 /*{ "page", listing_eject, 0 }, */
2441 { "sblock", tic54x_sblock, 0 },
2442 { "sect", tic54x_sect, '*' },
2443 { "set", tic54x_set, 0 },
2444 { "equ", tic54x_set, 0 },
2445 { "space", tic54x_space, 0 },
2446 { "bes", tic54x_space, 1 },
2447 { "sslist", tic54x_sslist, 1 },
2448 { "ssnolist", tic54x_sslist, 0 },
2449 { "string", tic54x_stringer, 's' },
2450 { "pstring", tic54x_stringer, 'p' },
2451 { "struct", tic54x_struct, 0 },
2452 { "tag", tic54x_tag, 0 },
2453 { "endstruct", tic54x_endstruct, 0 },
2454 { "tab", s_ignore, 0 },
2455 { "text", tic54x_sect, 't' },
2456 /*{ "title", listing_title, 0 }, */
2457 { "union", tic54x_struct, 1 },
2458 { "endunion", tic54x_endstruct, 1 },
2459 { "usect", tic54x_usect, 0 },
2460 { "var", tic54x_var, 0 },
2461 { "version", tic54x_version, 0 },
2465 /* for debugging, strings for each operand type */
2467 static const char *optypes[] =
2469 "none", "Xmem", "Ymem", "pmad", "dmad", "Smem", "Lmem", "MMR", "PA",
2470 "Sind", "xpmad", "xpmad+", "MMRX", "MMRY",
2471 "SRC1", "SRC", "RND", "DST",
2474 "B", "A", "lk", "TS", "k8", "16", "BITC", "CC", "CC2", "CC3", "123", "031",
2475 "k5", "k8u", "ASM", "T", "DP", "ARP", "k3", "lku", "N", "SBIT", "12",
2481 md_parse_option (c, arg)
2489 case OPTION_COFF_VERSION:
2491 int version = atoi (arg);
2492 if (version != 0 && version != 1 && version != 2)
2493 as_fatal (_("Bad COFF version '%s'"), arg);
2494 /* FIXME -- not yet implemented */
2497 case OPTION_CPU_VERSION:
2499 cpu = lookup_version (arg);
2502 as_fatal (_("Bad CPU version '%s'"), arg);
2505 case OPTION_ADDRESS_MODE:
2507 address_mode_needs_set = 1;
2509 case OPTION_STDERR_TO_FILE:
2511 char *filename = arg;
2512 FILE *fp = fopen (filename, "w+");
2514 as_fatal (_("Can't redirect stderr to the file '%s'"), filename);
2516 if ((fp = freopen (filename, "w+", stderr)) == NULL)
2517 as_fatal (_("Can't redirect stderr to the file '%s'"), filename);
2525 /* create a "local" substitution string hash table for a new macro level
2526 Some docs imply that macros have to use .newblock in order to be able
2527 to re-use a local label. We effectively do an automatic .newblock by
2528 deleting the local label hash between macro invocations.
2531 tic54x_macro_start ()
2534 subsym_hash[macro_level] = hash_new ();
2535 local_label_hash[macro_level] = hash_new ();
2539 tic54x_macro_info (void *info)
2541 struct formal_struct
2543 struct formal_struct *next; /* next formal in list */
2544 sb name; /* name of the formal */
2545 sb def; /* the default value */
2546 sb actual; /* the actual argument (changed on each expansion) */
2547 int index; /* the index of the formal 0..formal_count-1 */
2551 sb sub; /* substitution text. */
2552 int formal_count; /* number of formal args. */
2553 struct formal_struct *formals; /* pointer to list of formal_structs */
2554 struct hash_control *formal_hash; /* hash table of formals. */
2557 macro = (struct macro_struct *)info;
2559 /* put the formal args into the substitution symbol table */
2560 for (entry = macro->formals; entry; entry = entry->next)
2562 char *name = strncpy (xmalloc (entry->name.len + 1),
2563 entry->name.ptr, entry->name.len);
2564 char *value = strncpy (xmalloc (entry->actual.len + 1),
2565 entry->actual.ptr, entry->actual.len);
2566 name[entry->name.len] = '\0';
2567 value[entry->actual.len] = '\0';
2568 hash_insert (subsym_hash[macro_level], name, value);
2572 /* get rid of this macro's .var's, arguments, and local labels */
2576 hash_die (subsym_hash[macro_level]);
2577 subsym_hash[macro_level] = NULL;
2578 hash_die (local_label_hash[macro_level]);
2579 local_label_hash[macro_level] = NULL;
2584 subsym_symlen (a, ignore)
2586 char *ignore ATTRIBUTE_UNUSED;
2591 /* compare symbol A to string B */
2593 subsym_symcmp (char *a, char *b)
2595 return strcmp (a, b);
2598 /* return the index of the first occurence of B in A, or zero if none
2599 assumes b is an integer char value as a string. index is one-based */
2601 subsym_firstch (char *a, char *b)
2604 char *tmp = strchr (a, val);
2606 return tmp ? tmp - a + 1 : 0;
2609 /* similar to firstch, but returns index of last occurrence of B in A */
2611 subsym_lastch (a, b)
2616 char *tmp = strrchr (a, val);
2618 return tmp ? tmp - a + 1 : 0;
2621 /* returns 1 if string A is defined in the symbol table (NOT the substitution
2624 subsym_isdefed (a, ignore)
2626 char *ignore ATTRIBUTE_UNUSED;
2628 symbolS *symbolP = symbol_find (a);
2630 return symbolP != NULL;
2633 /* assign first member of comma-separated list B (e.g. "1,2,3") to the symbol
2634 A, or zero if B is a null string. Both arguments *must* be substitution
2635 symbols, unsubstituted */
2637 subsym_ismember (char *symbol, char *list)
2639 char *elem, *ptr, *listv;
2644 listv = subsym_lookup (list, macro_level);
2647 as_bad (_("Undefined substitution symbol '%s'"), list);
2648 ignore_rest_of_line ();
2652 ptr = elem = xmalloc (strlen (listv)+1);
2653 strcpy (elem, listv);
2654 while (*ptr && *ptr != ',')
2658 subsym_create_or_replace (symbol, elem);
2660 /* reassign the list */
2661 subsym_create_or_replace (list, ptr);
2663 /* assume this value, docs aren't clear */
2667 /* return zero if not a constant; otherwise:
2675 subsym_iscons (a, ignore)
2677 char *ignore ATTRIBUTE_UNUSED;
2681 parse_expression (a, &exp);
2683 if (exp.X_op == O_constant)
2685 int len = strlen (a);
2687 switch (toupper (a[len-1]))
2700 /* no suffix; either octal, hex, or decimal */
2701 if (*a == '0' && len > 1)
2703 if (toupper (a[1]) == 'X')
2713 /* return 1 if A is a valid symbol name. Expects string input */
2715 subsym_isname (a, ignore)
2717 char *ignore ATTRIBUTE_UNUSED;
2719 if (!is_name_beginner (*a))
2723 if (!is_part_of_name (*a))
2730 /* return whether the string is a register; accepts ar0-7, unless .mmregs has
2731 been seen; if so, recognize any memory-mapped register.
2732 Note this does not recognize "A" or "B" accumulators */
2734 subsym_isreg (a, ignore)
2736 char *ignore ATTRIBUTE_UNUSED;
2738 if (hash_find (reg_hash, a))
2740 if (hash_find (mmreg_hash, a))
2745 /* Return the structrure size, given the stag */
2747 subsym_structsz (name, ignore)
2749 char *ignore ATTRIBUTE_UNUSED;
2751 struct stag *stag = (struct stag *)hash_find (stag_hash, name);
2758 /* If anybody actually uses this, they can fix it :)
2759 FIXME I'm not sure what the "reference point" of a structure is. It might
2760 be either the initial offset given .struct, or it may be the offset of the
2761 structure within another structure, or it might be something else
2762 altogether. since the TI assembler doesn't seem to ever do anything but
2763 return zero, we punt and return zero.
2766 subsym_structacc (stag_name, ignore)
2767 char *stag_name ATTRIBUTE_UNUSED;
2768 char *ignore ATTRIBUTE_UNUSED;
2774 math_ceil (arg1, ignore)
2776 float ignore ATTRIBUTE_UNUSED;
2778 return (float)ceil (arg1);
2781 math_cvi (arg1, ignore)
2783 float ignore ATTRIBUTE_UNUSED;
2788 math_floor (arg1, ignore)
2790 float ignore ATTRIBUTE_UNUSED;
2792 return (float)floor (arg1);
2795 math_fmod (float arg1, float arg2)
2797 return (int)arg1 % (int)arg2;
2800 math_int (arg1, ignore)
2802 float ignore ATTRIBUTE_UNUSED;
2804 return ((float)((int)arg1)) == arg1;
2807 math_round (arg1, ignore)
2809 float ignore ATTRIBUTE_UNUSED;
2811 return arg1 > 0 ? (int)(arg1 + 0.5) : (int)(arg1 - 0.5);
2814 math_sgn (arg1, ignore)
2816 float ignore ATTRIBUTE_UNUSED;
2818 return (arg1 < 0) ? -1 : (arg1 ? 1 : 0);
2821 math_trunc (arg1, ignore)
2823 float ignore ATTRIBUTE_UNUSED;
2829 math_acos (arg1, ignore)
2831 float ignore ATTRIBUTE_UNUSED;
2833 return (float)acos (arg1);
2836 math_asin (arg1, ignore)
2838 float ignore ATTRIBUTE_UNUSED;
2840 return (float)asin (arg1);
2843 math_atan (arg1, ignore)
2845 float ignore ATTRIBUTE_UNUSED;
2847 return (float)atan (arg1);
2850 math_atan2(float arg1, float arg2)
2852 return (float)atan2 (arg1, arg2);
2855 math_cosh (arg1, ignore)
2857 float ignore ATTRIBUTE_UNUSED;
2859 return (float)cosh (arg1);
2862 math_cos (arg1, ignore)
2864 float ignore ATTRIBUTE_UNUSED;
2866 return (float)cos (arg1);
2869 math_cvf (arg1, ignore)
2871 float ignore ATTRIBUTE_UNUSED;
2876 math_exp (arg1, ignore)
2878 float ignore ATTRIBUTE_UNUSED;
2880 return (float)exp (arg1);
2883 math_fabs (arg1, ignore)
2885 float ignore ATTRIBUTE_UNUSED;
2887 return (float)fabs (arg1);
2889 /* expr1 * 2^expr2 */
2891 math_ldexp (float arg1, float arg2)
2893 return arg1 * (float)pow (2.0, arg2);
2896 math_log10 (arg1, ignore)
2898 float ignore ATTRIBUTE_UNUSED;
2900 return (float)log10 (arg1);
2903 math_log (arg1, ignore)
2905 float ignore ATTRIBUTE_UNUSED;
2907 return (float)log (arg1);
2910 math_max (float arg1, float arg2)
2912 return (arg1 > arg2) ? arg1 : arg2;
2915 math_min (float arg1, float arg2)
2917 return (arg1 < arg2) ? arg1 : arg2;
2920 math_pow (float arg1, float arg2)
2922 return (float)pow (arg1, arg2);
2925 math_sin (arg1, ignore)
2927 float ignore ATTRIBUTE_UNUSED;
2929 return (float)sin (arg1);
2932 math_sinh (arg1, ignore)
2934 float ignore ATTRIBUTE_UNUSED;
2936 return (float)sinh (arg1);
2939 math_sqrt (arg1, ignore)
2941 float ignore ATTRIBUTE_UNUSED;
2943 return (float)sqrt (arg1);
2946 math_tan (arg1, ignore)
2948 float ignore ATTRIBUTE_UNUSED;
2950 return (float)tan (arg1);
2953 math_tanh (arg1, ignore)
2955 float ignore ATTRIBUTE_UNUSED;
2957 return (float)tanh (arg1);
2960 /* built-in substitution symbol functions and math functions */
2964 int (*proc)(char *, char *);
2966 } subsym_proc_entry;
2968 static const subsym_proc_entry subsym_procs[] = {
2969 /* assembler built-in string substitution functions */
2970 { "$symlen", subsym_symlen, 1, },
2971 { "$symcmp", subsym_symcmp, 2, },
2972 { "$firstch", subsym_firstch, 2, },
2973 { "$lastch", subsym_lastch, 2, },
2974 { "$isdefed", subsym_isdefed, 1, },
2975 { "$ismember", subsym_ismember, 2, },
2976 { "$iscons", subsym_iscons, 1, },
2977 { "$isname", subsym_isname, 1, },
2978 { "$isreg", subsym_isreg, 1, },
2979 { "$structsz", subsym_structsz, 1, },
2980 { "$structacc", subsym_structacc, 1, },
2987 float (*proc)(float, float);
2992 static const math_proc_entry math_procs[] = {
2993 /* integer-returning built-in math functions */
2994 { "$cvi", math_cvi, 1, 1 },
2995 { "$int", math_int, 1, 1 },
2996 { "$sgn", math_sgn, 1, 1 },
2998 /* float-returning built-in math functions */
2999 { "$acos", math_acos, 1, 0 },
3000 { "$asin", math_asin, 1, 0 },
3001 { "$atan", math_atan, 1, 0 },
3002 { "$atan2", math_atan2, 2, 0 },
3003 { "$ceil", math_ceil, 1, 0 },
3004 { "$cosh", math_cosh, 1, 0 },
3005 { "$cos", math_cos, 1, 0 },
3006 { "$cvf", math_cvf, 1, 0 },
3007 { "$exp", math_exp, 1, 0 },
3008 { "$fabs", math_fabs, 1, 0 },
3009 { "$floor", math_floor, 1, 0 },
3010 { "$fmod", math_fmod, 2, 0 },
3011 { "$ldexp", math_ldexp, 2, 0 },
3012 { "$log10", math_log10, 1, 0 },
3013 { "$log", math_log, 1, 0 },
3014 { "$max", math_max, 2, 0 },
3015 { "$min", math_min, 2, 0 },
3016 { "$pow", math_pow, 2, 0 },
3017 { "$round", math_round, 1, 0 },
3018 { "$sin", math_sin, 1, 0 },
3019 { "$sinh", math_sinh, 1, 0 },
3020 { "$sqrt", math_sqrt, 1, 0 },
3021 { "$tan", math_tan, 1, 0 },
3022 { "$tanh", math_tanh, 1, 0 },
3023 { "$trunc", math_trunc, 1, 0 },
3024 { NULL, NULL, 0, 0 },
3031 partemplate *paropcode;
3033 const subsym_proc_entry *subsym_proc;
3034 const math_proc_entry *math_proc;
3035 const char *hash_err;
3037 char *TIC54X_DIR = getenv ("TIC54X_DIR");
3038 char *A_DIR = TIC54X_DIR ? TIC54X_DIR : getenv ("A_DIR");
3042 /* look for A_DIR and add it to the include list */
3045 char *tmp = xstrdup (A_DIR);
3047 char *next = strchr (tmp, ';');
3050 add_include_dir (tmp);
3052 } while (tmp != NULL);
3055 op_hash = hash_new ();
3056 for (opcode=(template *)tic54x_optab; opcode->name; opcode++)
3058 if (hash_find (op_hash, opcode->name))
3060 hash_err = hash_insert (op_hash, opcode->name, (char *)opcode);
3062 as_fatal ("Internal Error: Can't hash %s: %s",
3063 opcode->name, hash_err);
3065 parop_hash = hash_new ();
3066 for (paropcode=(partemplate *)tic54x_paroptab; paropcode->name; paropcode++)
3068 if (hash_find (parop_hash, paropcode->name))
3070 hash_err = hash_insert (parop_hash, paropcode->name, (char *)paropcode);
3072 as_fatal ("Internal Error: Can't hash %s: %s",
3073 paropcode->name, hash_err);
3075 reg_hash = hash_new ();
3076 for (sym = (symbol *)regs; sym->name; sym++)
3078 /* add basic registers to the symbol table */
3079 symbolS *symbolP = symbol_new (sym->name, absolute_section,
3080 (valueT)sym->value, &zero_address_frag);
3081 SF_SET_LOCAL (symbolP);
3082 symbol_table_insert (symbolP);
3083 hash_err = hash_insert (reg_hash, sym->name, (char *)sym);
3085 for (sym = (symbol *)mmregs; sym->name; sym++)
3086 hash_err = hash_insert (reg_hash, sym->name, (char *)sym);
3087 mmreg_hash = hash_new ();
3088 for (sym = (symbol *)mmregs; sym->name; sym++)
3090 hash_err = hash_insert (mmreg_hash, sym->name, (char *)sym);
3092 cc_hash = hash_new ();
3093 for (sym = (symbol *)condition_codes; sym->name; sym++)
3095 hash_err = hash_insert (cc_hash, sym->name, (char *)sym);
3097 cc2_hash = hash_new ();
3098 for (sym = (symbol *)cc2_codes; sym->name; sym++)
3100 hash_err = hash_insert (cc2_hash, sym->name, (char *)sym);
3102 cc3_hash = hash_new ();
3103 for (sym = (symbol *)cc3_codes; sym->name; sym++)
3105 hash_err = hash_insert (cc3_hash, sym->name, (char *)sym);
3107 sbit_hash = hash_new ();
3108 for (sym = (symbol *)status_bits; sym->name; sym++)
3110 hash_err = hash_insert (sbit_hash, sym->name, (char *)sym);
3112 misc_symbol_hash = hash_new ();
3113 for (symname = (char **)misc_symbols; *symname; symname++)
3115 hash_err = hash_insert (misc_symbol_hash, *symname, *symname);
3117 /* only the base substitution table and local label table are initialized;
3118 the others (for local macro substitution) get instantiated as needed */
3119 local_label_hash[0] = hash_new ();
3120 subsym_hash[0] = hash_new ();
3121 for (subsym_proc = subsym_procs; subsym_proc->name; subsym_proc++)
3123 hash_err = hash_insert (subsym_hash[0], subsym_proc->name,
3124 (char *)subsym_proc);
3126 math_hash = hash_new ();
3127 for (math_proc = math_procs; math_proc->name; math_proc++)
3129 /* insert into the main subsym hash for recognition; insert into
3130 the math hash to actually store information */
3131 hash_err = hash_insert (subsym_hash[0], math_proc->name,
3133 hash_err = hash_insert (math_hash, math_proc->name,
3136 subsym_recurse_hash = hash_new ();
3137 stag_hash = hash_new ();
3140 typedef struct _tic54x_insn {
3141 const template *tm; /* opcode template */
3142 const partemplate *ptm; /* parallel opcode template */
3144 char mnemonic[MAX_LINE]; /* opcode name/mnemonic */
3145 char parmnemonic[MAX_LINE]; /* 2nd mnemonic of parallel insn */
3152 } operands[MAX_OPERANDS];
3155 struct opstruct paroperands[MAX_OPERANDS];
3159 int words; /* size of insn in 16-bit words */
3160 int using_default_dst; /* do we need to explicitly set an
3161 omitted OP_DST operand? */
3163 unsigned short word; /* final encoded opcode data */
3165 int r_nchars; /* relocation size */
3166 bfd_reloc_code_real_type r_type; /* relocation type */
3167 expressionS addr_expr; /* storage for unresolved expressions */
3171 static int encode_operand (tic54x_insn *, enum optype, struct opstruct *);
3172 static int encode_dmad (tic54x_insn *, struct opstruct *, int);
3173 static int operands_match (tic54x_insn *, struct opstruct *, int,
3174 const enum optype *, int, int);
3175 static int encode_address (tic54x_insn *, struct opstruct *);
3178 is_accumulator (struct opstruct *operand)
3180 return strcasecmp (operand->buf, "a") == 0
3181 || strcasecmp (operand->buf, "b") == 0;
3184 /* return the number of operands found, or -1 on error, copying the operands
3185 into the given array and the accompanying expressions into the next array */
3187 get_operands (operands, line)
3188 struct opstruct operands[];
3193 int expecting_operand = 0;
3196 while (numexp < MAX_OPERANDS && !is_end_of_line[(int)*lptr])
3198 int paren_not_balanced = 0;
3199 char *op_start, *op_end;
3200 while (*lptr && isspace (*lptr))
3203 while (paren_not_balanced || *lptr != ',')
3207 if (paren_not_balanced)
3209 as_bad ("Unbalanced parenthesis in operand %d", numexp);
3216 ++paren_not_balanced;
3217 else if (*lptr == ')')
3218 --paren_not_balanced;
3222 if (op_end != op_start)
3224 int len = op_end - op_start;
3225 strncpy (operands[numexp].buf, op_start, len);
3226 operands[numexp].buf[len] = 0;
3227 /* trim trailing spaces; while the preprocessor gets rid of most,
3228 there are weird usage patterns that can introduce them
3229 (i.e. using strings for macro args) */
3230 while (len > 0 && isspace (operands[numexp].buf[len-1]))
3231 operands[numexp].buf[--len] = 0;
3237 if (expecting_operand || *lptr == ',')
3239 as_bad ("Expecting operand after ','");
3245 if (*++lptr == '\0')
3247 as_bad ("Expecting operand after ','");
3250 expecting_operand = 1;
3254 while (*lptr && isspace (*lptr++))
3256 if (!is_end_of_line[(int)*lptr])
3258 as_bad ("Extra junk on line");
3262 /* ok, now parse them into expressions */
3263 for (i=0;i < numexp;i++)
3265 memset (&operands[i].exp, 0, sizeof (operands[i].exp));
3266 if (operands[i].buf[0] == '#')
3269 parse_expression (operands[i].buf + 1, &operands[i].exp);
3271 else if (operands[i].buf[0] == '@')
3273 /* direct notation */
3274 parse_expression (operands[i].buf + 1, &operands[i].exp);
3276 else if (operands[i].buf[0] == '*')
3279 char *paren = strchr (operands[i].buf, '(');
3280 /* allow immediate syntax in the inner expression */
3281 if (paren && paren[1] == '#')
3284 /* pull out the lk expression or SP offset, if present */
3287 int len = strlen (paren);
3288 char *end = paren + len;
3290 while (end[-1] != ')')
3293 as_bad (_("Badly formed address expression"));
3298 parse_expression (paren, &operands[i].exp);
3302 operands[i].exp.X_op = O_absent;
3306 parse_expression (operands[i].buf, &operands[i].exp);
3314 * Predicates for different operand types
3317 is_immediate (struct opstruct *operand)
3319 return *operand->buf == '#';
3322 /* This is distinguished from immediate because some numbers must be constants
3323 and must *not* have the '#' prefix */
3325 is_absolute (struct opstruct *operand)
3327 return operand->exp.X_op == O_constant && !is_immediate (operand);
3330 /* is this an indirect operand? */
3332 is_indirect (struct opstruct *operand)
3334 return operand->buf[0] == '*';
3337 /* is this a valid dual-memory operand? */
3339 is_dual (struct opstruct *operand)
3341 if (is_indirect (operand) && strncasecmp (operand->buf, "*ar", 3) == 0)
3343 char *tmp = operand->buf + 3;
3347 /* only allow *ARx, *ARx-, *ARx+, or *ARx+0% */
3348 valid_mod = *tmp == '\0' ||
3349 strcasecmp (tmp, "-") == 0 ||
3350 strcasecmp (tmp, "+") == 0 ||
3351 strcasecmp (tmp, "+0%") == 0;
3352 return arf >= 2 && arf <= 5 && valid_mod;
3358 is_mmreg (struct opstruct *operand)
3360 return is_absolute (operand) || is_immediate (operand)
3361 || hash_find (mmreg_hash, operand->buf) != 0;
3365 is_type (operand, type)
3366 struct opstruct *operand;
3372 return operand->buf[0] == 0;
3375 return is_dual (operand);
3377 return is_indirect (operand);
3379 /* this one *must* be immediate */
3380 return is_immediate (operand);
3389 /* address may be a numeric, indirect, or an expression */
3390 return !is_immediate (operand);
3393 return is_mmreg (operand);
3398 return is_accumulator (operand);
3400 return is_accumulator (operand) && toupper (operand->buf[0]) == 'B';
3402 return is_accumulator (operand) && toupper (operand->buf[0]) == 'A';
3404 return strncasecmp ("ar", operand->buf, 2) == 0
3405 && isdigit (operand->buf[2]);
3407 return hash_find (sbit_hash, operand->buf) != 0 || is_absolute (operand);
3409 return hash_find (cc_hash, operand->buf) != 0;
3411 return hash_find (cc2_hash, operand->buf) != 0;
3413 return hash_find (cc3_hash, operand->buf) != 0
3414 || is_immediate (operand) || is_absolute (operand);
3416 return (is_immediate (operand) || is_absolute (operand))
3417 && operand->exp.X_add_number == 16;
3419 /* allow st0 or st1 instead of a numeric */
3420 return is_absolute (operand) || is_immediate (operand) ||
3421 strcasecmp ("st0", operand->buf) == 0 ||
3422 strcasecmp ("st1", operand->buf) == 0;
3425 return is_absolute (operand) || is_immediate (operand);
3427 return (is_immediate (operand) || is_absolute (operand))
3428 && operand->exp.X_add_number >= 0 && operand->exp.X_add_number < 16;
3430 /* let this one catch out-of-range values */
3431 return (is_immediate (operand) || is_absolute (operand))
3432 && operand->exp.X_add_number != 16;
3436 return is_absolute (operand) || is_immediate (operand);
3438 return is_immediate (operand)
3439 && operand->exp.X_op == O_constant
3440 && operand->exp.X_add_number >= 0
3441 && operand->exp.X_add_number < 256;
3444 /* allow anything; assumes opcodes are ordered with Smem operands
3450 /* just make sure it's an integer; check range later */
3451 return is_immediate (operand);
3453 return strcasecmp ("t", operand->buf) == 0 ||
3454 strcasecmp ("treg", operand->buf) == 0;
3456 return strcasecmp ("ts", operand->buf) == 0;
3458 return strcasecmp ("asm", operand->buf) == 0;
3460 return strcasecmp ("trn", operand->buf) == 0;
3462 return strcasecmp ("dp", operand->buf) == 0;
3464 return strcasecmp ("arp", operand->buf) == 0;
3471 operands_match (insn, operands, opcount, refoptype, minops, maxops)
3473 struct opstruct *operands;
3475 const enum optype *refoptype;
3478 int op = 0, refop = 0;
3480 if (opcount == 0 && minops == 0)
3485 while (op <= maxops && refop <= maxops)
3487 while (!is_type (&operands[op], OPTYPE (refoptype[refop])))
3489 /* skip an optional template operand if it doesn't agree
3490 with the current operand
3492 if (refoptype[refop] & OPT)
3503 /* save the actual operand type for later use */
3504 operands[op].type = OPTYPE (refoptype[refop]);
3507 /* have we matched them all yet? */
3512 /* if a later operand is *not* optional, no match */
3513 if ((refoptype[refop] & OPT) == 0)
3515 /* flag any implicit default OP_DST operands so we know to add
3516 them explicitly when encoding the operand later */
3517 if (OPTYPE (refoptype[refop]) == OP_DST)
3518 insn->using_default_dst = 1;
3530 /* 16-bit direct memory address
3531 Explicit dmad operands are always in last word of insn (usually second
3532 word, but bumped to third if lk addressing is used)
3534 We allow *(dmad) notation because the TI assembler allows it.
3537 0 for 16-bit addresses
3538 1 for full 23-bit addresses
3539 2 for the upper 7 bits of a 23-bit address (LDX)
3542 encode_dmad (insn, operand, xpc_code)
3544 struct opstruct *operand;
3547 int op = 1 + insn->is_lkaddr;
3549 /* only allow *(dmad) expressions; all others are invalid */
3550 if (is_indirect (operand) && operand->buf[strlen (operand->buf)-1] != ')')
3552 as_bad (_("Invalid dmad syntax '%s'"), operand->buf);
3556 insn->opcode[op].addr_expr = operand->exp;
3558 if (insn->opcode[op].addr_expr.X_op == O_constant)
3560 valueT value = insn->opcode[op].addr_expr.X_add_number;
3563 insn->opcode[0].word &= 0xFF80;
3564 insn->opcode[0].word |= (value >> 16) & 0x7F;
3565 insn->opcode[1].word = value & 0xFFFF;
3567 else if (xpc_code == 2)
3568 insn->opcode[op].word = (value >> 16) & 0xFFFF;
3570 insn->opcode[op].word = value;
3574 /* do the fixup later; just store the expression */
3575 insn->opcode[op].word = 0;
3576 insn->opcode[op].r_nchars = 2;
3578 if (amode == c_mode)
3579 insn->opcode[op].r_type = BFD_RELOC_TIC54X_16_OF_23;
3580 else if (xpc_code == 1)
3582 /* this relocation spans two words, so adjust accordingly */
3583 insn->opcode[0].addr_expr = operand->exp;
3584 insn->opcode[0].r_type = BFD_RELOC_TIC54X_23;
3585 insn->opcode[0].r_nchars = 4;
3586 insn->opcode[0].unresolved = 1;
3587 /* it's really 2 words, but we want to stop encoding after the
3588 first, since we must encode both words at once */
3591 else if (xpc_code == 2)
3592 insn->opcode[op].r_type = BFD_RELOC_TIC54X_MS7_OF_23;
3594 insn->opcode[op].r_type = BFD_RELOC_TIC54X_16_OF_23;
3596 insn->opcode[op].unresolved = 1;
3603 /* 7-bit direct address encoding */
3605 encode_address (insn, operand)
3607 struct opstruct *operand;
3609 /* Assumes that dma addresses are *always* in word 0 of the opcode */
3610 insn->opcode[0].addr_expr = operand->exp;
3612 if (operand->exp.X_op == O_constant)
3613 insn->opcode[0].word |= (operand->exp.X_add_number & 0x7F);
3616 /* do the fixup later; just store the expression */
3617 insn->opcode[0].r_nchars = 1;
3618 insn->opcode[0].r_type = BFD_RELOC_TIC54X_PARTLS7;
3619 insn->opcode[0].unresolved = 1;
3626 encode_indirect (insn, operand)
3628 struct opstruct *operand;
3633 if (insn->is_lkaddr)
3635 /* lk addresses always go in the second insn word */
3636 mod = ((toupper (operand->buf[1]) == 'A') ? 12 :
3637 (operand->buf[1] == '(') ? 15 :
3638 (strchr (operand->buf, '%') != NULL) ? 14 : 13);
3639 arf = ((mod == 12) ? operand->buf[3] - '0' :
3640 (mod == 15) ? 0 : operand->buf[4] - '0');
3642 insn->opcode[1].addr_expr = operand->exp;
3644 if (operand->exp.X_op == O_constant)
3645 insn->opcode[1].word = operand->exp.X_add_number;
3648 insn->opcode[1].word = 0;
3649 insn->opcode[1].r_nchars = 2;
3650 insn->opcode[1].r_type = BFD_RELOC_TIC54X_16_OF_23;
3651 insn->opcode[1].unresolved = 1;
3654 else if (strncasecmp (operand->buf, "*sp (", 4) == 0)
3656 /* stack offsets look the same as 7-bit direct addressing */
3657 return encode_address (insn, operand);
3661 arf = (toupper (operand->buf[1]) == 'A' ?
3662 operand->buf[3] : operand->buf[4]) - '0';
3664 if (operand->buf[1] == '+')
3666 mod = 3; /* *+ARx */
3667 if (insn->tm->flags & FL_SMR)
3668 as_warn (_("Address mode *+ARx is write-only. "
3669 "Results of reading are undefined."));
3671 else if (operand->buf[4] == '\0')
3673 else if (operand->buf[5] == '\0')
3674 mod = (operand->buf[4] == '-' ? 1 : 2); /* *ARx+ / *ARx- */
3675 else if (operand->buf[6] == '\0')
3677 if (operand->buf[5] == '0')
3678 mod = (operand->buf[4] == '-' ? 5 : 6); /* *ARx+0 / *ARx-0 */
3680 mod = (operand->buf[4] == '-' ? 8 : 10);/* *ARx+% / *ARx-% */
3682 else if (toupper (operand->buf[6]) == 'B')
3683 mod = (operand->buf[4] == '-' ? 4 : 7); /* ARx+0B / *ARx-0B */
3684 else if (toupper (operand->buf[6]) == '%')
3685 mod = (operand->buf[4] == '-' ? 9 : 11); /* ARx+0% / *ARx - 0% */
3688 as_bad (_("Unrecognized indirect address format \"%s\""),
3694 insn->opcode[0].word |= 0x80 | (mod<<3) | arf;
3700 encode_integer (insn, operand, which, min, max, mask)
3702 struct opstruct *operand;
3703 int which, min, max;
3704 unsigned short mask;
3706 long parse, integer;
3708 insn->opcode[which].addr_expr = operand->exp;
3710 if (operand->exp.X_op == O_constant)
3712 parse = operand->exp.X_add_number;
3713 /* hack -- fixup for 16-bit hex quantities that get converted positive
3714 instead of negative */
3715 if ((parse & 0x8000) && min == -32768 && max == 32767)
3716 integer = (short)parse;
3720 if (integer >= min && integer <= max)
3722 insn->opcode[which].word |= (integer & mask);
3725 as_bad (_("Operand '%s' out of range (%d <= x <= %d)"),
3726 operand->buf, min, max);
3730 if (insn->opcode[which].addr_expr.X_op == O_constant)
3732 insn->opcode[which].word |=
3733 insn->opcode[which].addr_expr.X_add_number & mask;
3737 /* do the fixup later; just store the expression */
3738 bfd_reloc_code_real_type rtype =
3739 (mask == 0x1FF ? BFD_RELOC_TIC54X_PARTMS9 :
3740 mask == 0xFFFF ? BFD_RELOC_TIC54X_16_OF_23 :
3741 mask == 0x7F ? BFD_RELOC_TIC54X_PARTLS7 : BFD_RELOC_8);
3742 int size = (mask == 0x1FF || mask == 0xFFFF) ? 2 : 1;
3744 if (rtype == BFD_RELOC_8)
3745 as_bad (_("Error in relocation handling"));
3747 insn->opcode[which].r_nchars = size;
3748 insn->opcode[which].r_type = rtype;
3749 insn->opcode[which].unresolved = 1;
3759 encode_condition (insn, operand)
3761 struct opstruct *operand;
3763 symbol *cc = (symbol *)hash_find (cc_hash, operand->buf);
3766 as_bad (_("Unrecognized condition code \"%s\""), operand->buf);
3769 #define CC_GROUP 0x40
3771 #define CATG_A1 0x07
3772 #define CATG_B1 0x30
3773 #define CATG_A2 0x30
3774 #define CATG_B2 0x0C
3775 #define CATG_C2 0x03
3776 /* disallow group 1 conditions mixed with group 2 conditions
3777 if group 1, allow only one category A and one category B
3778 if group 2, allow only one each of category A, B, and C
3780 if (((insn->opcode[0].word & 0xFF) != 0))
3782 if ((insn->opcode[0].word & CC_GROUP) != (cc->value & CC_GROUP))
3784 as_bad (_("Condition \"%s\" does not match preceding group"),
3788 if (insn->opcode[0].word & CC_GROUP)
3790 if ((insn->opcode[0].word & CC_ACC) != (cc->value & CC_ACC))
3792 as_bad (_("Condition \"%s\" uses a different accumulator from "
3793 "a preceding condition"),
3797 if ((insn->opcode[0].word & CATG_A1) && (cc->value & CATG_A1))
3799 as_bad (_("Only one comparison conditional allowed"));
3802 if ((insn->opcode[0].word & CATG_B1) && (cc->value & CATG_B1))
3804 as_bad (_("Only one overflow conditional allowed"));
3808 else if (((insn->opcode[0].word & CATG_A2) && (cc->value & CATG_A2)) ||
3809 ((insn->opcode[0].word & CATG_B2) && (cc->value & CATG_B2)) ||
3810 ((insn->opcode[0].word & CATG_C2) && (cc->value & CATG_C2)))
3812 as_bad (_("Duplicate %s conditional"), operand->buf);
3817 insn->opcode[0].word |= cc->value;
3822 encode_cc3 (insn, operand)
3824 struct opstruct *operand;
3826 symbol *cc3 = (symbol *)hash_find (cc3_hash, operand->buf);
3827 int value = cc3 ? cc3->value : operand->exp.X_add_number << 8;
3829 if ((value & 0x0300) != value)
3831 as_bad (_("Unrecognized condition code \"%s\""), operand->buf);
3834 insn->opcode[0].word |= value;
3839 encode_arx (insn, operand)
3841 struct opstruct *operand;
3843 int arf = strlen (operand->buf) >= 3 ? operand->buf[2] - '0' : -1;
3844 if (strncasecmp ("ar", operand->buf, 2) || arf < 0 || arf > 7)
3846 as_bad (_("Invalid auxiliary register (use AR0-AR7)"));
3849 insn->opcode[0].word |= arf;
3854 encode_cc2 (insn, operand)
3856 struct opstruct *operand;
3858 symbol *cc2 = (symbol *)hash_find (cc2_hash, operand->buf);
3861 as_bad (_("Unrecognized condition code \"%s\""), operand->buf);
3864 insn->opcode[0].word |= cc2->value;
3869 encode_operand (insn, type, operand)
3872 struct opstruct *operand;
3874 int ext = insn->tm && ((insn->tm->flags & FL_EXT) != 0);
3876 if (type == OP_MMR && operand->exp.X_op != O_constant)
3878 /* disallow long-constant addressing for memory-mapped addressing */
3879 if (insn->is_lkaddr)
3881 as_bad (_("lk addressing modes are invalid for memory-mapped "
3882 "register addressing"));
3886 /* warn about *+ARx when used with MMR operands */
3887 if (strncasecmp (operand->buf, "*+ar", 4) == 0)
3889 as_warn (_("Address mode *+ARx is not allowed in memory-mapped "
3890 "register addressing. Resulting behavior is "
3900 /* 16-bit immediate value */
3901 return encode_dmad (insn, operand, 0);
3903 if (toupper (*operand->buf) == 'B')
3905 insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1<<9);
3906 if (insn->using_default_dst)
3907 insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1<<8);
3911 /* make sure this agrees with with the OP_DST operand */
3912 if (!((toupper (operand->buf[0]) == 'B') ^
3913 ((insn->opcode[0].word & (1<<8)) != 0)))
3915 as_bad (_("Destination accumulator for each part of this parallel "
3916 "instruction must be different"));
3922 if (toupper (operand->buf[0]) == 'B')
3923 insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1<<8);
3928 int mod = (operand->buf[4] == '\0' ? 0 : /* *arx */
3929 operand->buf[4] == '-' ? 1 : /* *arx- */
3930 operand->buf[5] == '\0' ? 2 : 3); /* *arx+, *arx+0% */
3931 int arf = operand->buf[3] - '0' - 2;
3932 int code = (mod << 2)|arf;
3933 insn->opcode[0].word |= (code << (type == OP_Xmem ? 4 : 0));
3938 if (!is_indirect (operand))
3939 return encode_address (insn, operand);
3942 return encode_indirect (insn, operand);
3944 return encode_dmad (insn, operand, 2);
3946 return encode_dmad (insn, operand, 1);
3949 return encode_dmad (insn, operand, 0);
3951 return encode_arx (insn, operand);
3956 int value = operand->exp.X_add_number;
3958 insn->opcode[0].word |= value;
3960 if (value < 16 || value > 24)
3962 as_bad (_("Memory mapped register \"%s\" out of range"),
3966 if (type == OP_MMRX)
3967 insn->opcode[0].word |= (value - 16) << 4;
3969 insn->opcode[0].word |= (value - 16);
3977 return encode_integer (insn, operand, ext + insn->is_lkaddr,
3980 return encode_integer (insn, operand, ext + insn->is_lkaddr,
3983 return encode_integer (insn, operand, 1 + insn->is_lkaddr,
3984 -32768, 32767, 0xFFFF);
3986 return encode_condition (insn, operand);
3988 return encode_cc2 (insn, operand);
3990 return encode_cc3 (insn, operand);
3992 return encode_integer (insn, operand, 0, 0, 15, 0xF);
3994 return encode_integer (insn, operand, 0, -128, 127, 0xFF);
3997 int value = operand->exp.X_add_number;
3999 if (value < 1 || value > 3)
4001 as_bad (_("Invalid operand (use 1, 2, or 3)"));
4004 code = value == 1 ? 0 : value == 2 ? 0x2 : 0x1;
4005 insn->opcode[0].word |= (code << 8);
4009 return encode_integer (insn, operand, 0, 0, 31, 0x1F);
4011 return encode_integer (insn, operand, 0, 0, 255, 0xFF);
4013 return encode_integer (insn, operand, 1 + insn->is_lkaddr,
4017 symbol *sbit = (symbol *)hash_find (sbit_hash, operand->buf);
4018 int value = is_absolute (operand) ?
4019 operand->exp.X_add_number : (sbit ? sbit->value : -1);
4022 if (insn->opcount == 1)
4026 as_bad (_("A status register or status bit name is required"));
4029 /* guess the register based on the status bit; "ovb" is the last
4030 status bit defined for st0 */
4031 if (sbit > (symbol *)hash_find (sbit_hash, "ovb"))
4036 as_bad (_("Unrecognized status bit \"%s\""), operand->buf);
4039 insn->opcode[0].word |= value;
4040 insn->opcode[0].word |= (reg << 9);
4044 if (strcasecmp (operand->buf, "st0") == 0
4045 || strcasecmp (operand->buf, "st1") == 0)
4047 insn->opcode[0].word |= ((unsigned short)(operand->buf[2] - '0'))<<9;
4050 else if (operand->exp.X_op == O_constant
4051 && (operand->exp.X_add_number == 0
4052 || operand->exp.X_add_number == 1))
4054 insn->opcode[0].word |= ((unsigned short)
4055 (operand->exp.X_add_number))<<9;
4058 as_bad (_("Invalid status register \"%s\""), operand->buf);
4061 return encode_integer (insn, operand, 0, -16, 15, 0x1F);
4063 return encode_integer (insn, operand, 0, 0, 7, 0x7);
4065 return encode_integer (insn, operand, 0, 0, 0x1FF, 0x1FF);
4067 if (operand->exp.X_add_number != 1
4068 && operand->exp.X_add_number != 2)
4070 as_bad (_("Operand \"%s\" out of range (use 1 or 2)"), operand->buf);
4073 insn->opcode[0].word |= (operand->exp.X_add_number - 1) << 9;
4082 /* no encoding necessary */
4096 for (i=0;i < insn->words;i++)
4098 int size = (insn->opcode[i].unresolved
4099 && insn->opcode[i].r_type == BFD_RELOC_TIC54X_23) ? 4 : 2;
4100 char *p = frag_more (size);
4103 md_number_to_chars (p, (valueT)insn->opcode[i].word, 2);
4105 md_number_to_chars (p, (valueT)insn->opcode[i].word << 16, 4);
4107 if (insn->opcode[i].unresolved)
4108 fix_new_exp (frag_now, p - frag_now->fr_literal,
4109 insn->opcode[i].r_nchars, &insn->opcode[i].addr_expr,
4110 false, insn->opcode[i].r_type);
4114 /* convert the operand strings into appropriate opcode values
4115 return the total number of words used by the instruction
4123 /* only non-parallel instructions support lk addressing */
4126 for (i=0; i < insn->opcount; i++)
4128 if ((OPTYPE (insn->operands[i].type) == OP_Smem ||
4129 OPTYPE (insn->operands[i].type) == OP_Lmem ||
4130 OPTYPE (insn->operands[i].type) == OP_Sind) &&
4131 strchr (insn->operands[i].buf, '(') &&
4132 /* don't mistake stack-relative addressing for lk addressing */
4133 strncasecmp (insn->operands[i].buf, "*sp (", 4) != 0)
4135 insn->is_lkaddr = 1;
4136 insn->lkoperand = i;
4142 (insn->tm ? insn->tm->words : insn->ptm->words) + insn->is_lkaddr;
4144 insn->opcode[0].word = insn->tm ? insn->tm->opcode : insn->ptm->opcode;
4145 if (insn->tm && (insn->tm->flags & FL_EXT))
4146 insn->opcode[1 + insn->is_lkaddr].word = insn->tm->opcode2;
4148 for (i=0; i < insn->opcount; i++)
4150 enum optype type = insn->operands[i].type;
4151 if (!encode_operand (insn, type, &insn->operands[i]))
4154 if (insn->ptm) for (i=0; i < insn->paropcount; i++)
4156 enum optype partype = insn->paroperands[i].type;
4157 if (!encode_operand (insn, partype, &insn->paroperands[i]))
4167 optimize_insn (insn)
4170 /* optimize some instructions, helping out the brain-dead programmer
4172 #define is_zero(op) ((op).exp.X_op == O_constant && (op).exp.X_add_number == 0)
4173 if (strcasecmp (insn->tm->name, "add") == 0)
4175 if (insn->opcount > 1 &&
4176 is_accumulator (&insn->operands[insn->opcount-2]) &&
4177 is_accumulator (&insn->operands[insn->opcount-1]) &&
4178 strcasecmp (insn->operands[insn->opcount-2].buf,
4179 insn->operands[insn->opcount-1].buf) == 0)
4182 insn->using_default_dst = 1;
4186 /* try to collapse if Xmem and shift count is zero */
4187 if ((OPTYPE (insn->tm->operand_types[0]) == OP_Xmem &&
4188 OPTYPE (insn->tm->operand_types[1]) == OP_SHFT &&
4189 is_zero (insn->operands[1])) ||
4190 /* Or if Smem, shift is zero or absent, and SRC == DST */
4191 (OPTYPE (insn->tm->operand_types[0]) == OP_Smem &&
4192 OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT &&
4193 is_type (&insn->operands[1], OP_SHIFT) &&
4194 is_zero (insn->operands[1]) && insn->opcount == 3))
4196 insn->operands[1] = insn->operands[2];
4201 else if (strcasecmp (insn->tm->name, "ld") == 0)
4203 if (insn->opcount == 3 && insn->operands[0].type != OP_SRC)
4205 if ((OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT ||
4206 OPTYPE (insn->tm->operand_types[1]) == OP_SHFT) &&
4207 is_zero (insn->operands[1]) &&
4208 (OPTYPE (insn->tm->operand_types[0]) != OP_lk ||
4209 (insn->operands[0].exp.X_op == O_constant &&
4210 insn->operands[0].exp.X_add_number <= 255 &&
4211 insn->operands[0].exp.X_add_number >= 0)))
4213 insn->operands[1] = insn->operands[2];
4219 else if (strcasecmp (insn->tm->name, "sth") == 0 ||
4220 strcasecmp (insn->tm->name, "stl") == 0)
4222 if ((OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT ||
4223 OPTYPE (insn->tm->operand_types[1]) == OP_SHFT) &&
4224 is_zero (insn->operands[1]))
4226 insn->operands[1] = insn->operands[2];
4231 else if (strcasecmp (insn->tm->name, "sub") == 0)
4233 if (insn->opcount > 1 &&
4234 is_accumulator (&insn->operands[insn->opcount-2]) &&
4235 is_accumulator (&insn->operands[insn->opcount-1]) &&
4236 strcasecmp (insn->operands[insn->opcount-2].buf,
4237 insn->operands[insn->opcount-1].buf) == 0)
4240 insn->using_default_dst = 1;
4244 if (((OPTYPE (insn->tm->operand_types[0]) == OP_Smem &&
4245 OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT) ||
4246 (OPTYPE (insn->tm->operand_types[0]) == OP_Xmem &&
4247 OPTYPE (insn->tm->operand_types[1]) == OP_SHFT)) &&
4248 is_zero (insn->operands[1]) &&
4251 insn->operands[1] = insn->operands[2];
4259 /* Find a matching template if possible, and get the operand strings */
4261 tic54x_parse_insn (insn, line)
4265 insn->tm = (template *)hash_find (op_hash, insn->mnemonic);
4268 as_bad (_("Unrecognized instruction \"%s\""), insn->mnemonic);
4272 insn->opcount = get_operands (insn->operands, line);
4273 if (insn->opcount < 0)
4276 /* check each variation of operands for this mnemonic */
4277 while (insn->tm->name && strcasecmp (insn->tm->name, insn->mnemonic) == 0)
4279 if (insn->opcount >= insn->tm->minops &&
4280 insn->opcount <= insn->tm->maxops &&
4281 operands_match (insn, &insn->operands[0], insn->opcount,
4282 insn->tm->operand_types,
4283 insn->tm->minops, insn->tm->maxops))
4285 /* SUCCESS! now try some optimizations */
4286 if (optimize_insn (insn))
4288 insn->tm = (template *)hash_find (op_hash,
4297 as_bad (_("Unrecognized operand list '%s' for instruction '%s'"),
4298 line, insn->mnemonic);
4302 /* we set this in start_line_hook, 'cause if we do a line replacement, we
4303 won't be able to see the next line */
4304 static int parallel_on_next_line_hint = 0;
4305 /* See if this is part of a parallel instruction
4306 Look for a subsequent line starting with "||"
4309 next_line_shows_parallel (next_line)
4312 /* look for the second half */
4313 while (isspace (*next_line))
4316 return (next_line[0] == PARALLEL_SEPARATOR &&
4317 next_line[1] == PARALLEL_SEPARATOR);
4321 tic54x_parse_parallel_insn_firstline (insn, line)
4325 insn->ptm = (partemplate *)hash_find (parop_hash, insn->mnemonic);
4328 as_bad (_("Unrecognized parallel instruction \"%s\""),
4333 while (insn->ptm->name && strcasecmp (insn->ptm->name,
4334 insn->mnemonic) == 0)
4336 insn->opcount = get_operands (insn->operands, line);
4337 if (insn->opcount < 0)
4339 if (insn->opcount == 2 &&
4340 operands_match (insn, &insn->operands[0], insn->opcount,
4341 insn->ptm->operand_types, 2, 2))
4347 /* didn't find a matching parallel; try for a normal insn */
4351 /* parse the second line of a two-line parallel instruction */
4353 tic54x_parse_parallel_insn_lastline (insn, line)
4357 int valid_mnemonic = 0;
4359 insn->paropcount = get_operands (insn->paroperands, line);
4360 while (insn->ptm->name && strcasecmp (insn->ptm->name,
4361 insn->mnemonic) == 0)
4363 if (strcasecmp (insn->ptm->parname, insn->parmnemonic) == 0)
4366 if (insn->paropcount >= insn->ptm->minops &&
4367 insn->paropcount <= insn->ptm->maxops &&
4368 operands_match (insn, insn->paroperands,
4370 insn->ptm->paroperand_types,
4371 insn->ptm->minops, insn->ptm->maxops))
4379 as_bad (_("Invalid operand (s) for parallel instruction \"%s\""),
4382 as_bad (_("Unrecognized parallel instruction combination \"%s || %s\""),
4383 insn->mnemonic, insn->parmnemonic);
4388 /* if quotes found, return copy of line up to closing quote;
4389 otherwise up until terminator
4390 if it's a string, pass as-is; otherwise attempt substitution symbol
4391 replacement on the value
4394 subsym_get_arg (char *line, char *terminators, char **str, int nosub)
4398 int is_string = *line == '"';
4399 int is_char = isdigit (*line);
4403 while (isdigit (*ptr))
4406 *str = xmalloc (ptr - line + 1);
4407 strncpy (*str, line, ptr - line);
4408 (*str)[ptr - line] = 0;
4412 char *savedp = input_line_pointer;
4414 input_line_pointer = ptr;
4415 *str = demand_copy_C_string (&len);
4416 endp = input_line_pointer;
4417 input_line_pointer = savedp;
4419 /* do forced substitutions if requested */
4420 if (!nosub && **str == ':')
4421 *str = subsym_substitute (*str, 1);
4425 char *term = terminators;
4428 while (*ptr && *ptr != *term)
4439 *str = xmalloc (ptr - line + 1);
4440 strncpy (*str, line, ptr - line);
4441 (*str)[ptr - line] = 0;
4442 /* do simple substitution, if available */
4443 if (!nosub && (value = subsym_lookup (*str, macro_level)) != NULL)
4450 /* replace the given substitution string.
4451 We start at the innermost macro level, so that existing locals remain local
4452 Note: we're treating macro args identically to .var's; I don't know if
4453 that's compatible w/TI's assembler.
4456 subsym_create_or_replace (char *name, char *value)
4460 for (i=macro_level;i > 0;i--)
4462 if (hash_find (subsym_hash[i], name))
4464 hash_replace (subsym_hash[i], name, value);
4468 if (hash_find (subsym_hash[0], name))
4469 hash_replace (subsym_hash[0], name, value);
4471 hash_insert (subsym_hash[0], name, value);
4474 /* look up the substitution string replacement for the given symbol
4475 start with the innermost macro substituion table given and work outwards */
4477 subsym_lookup (char *name, int nest_level)
4479 char *value = hash_find (subsym_hash[nest_level], name);
4481 if (value || nest_level == 0)
4484 return subsym_lookup (name, nest_level-1);
4487 /* do substitution-symbol replacement on the given line (recursively).
4488 return the argument if no substitution was done
4490 Also look for built-in functions ($func (arg)) and local labels.
4492 if FORCED is set, look for forced substitutions of the form ':SYMBOL:'.
4495 subsym_substitute (char *line, int forced)
4497 /* for each apparent symbol, see if it's a substitution symbol, and if so,
4498 replace it in the input */
4499 char *replacement; /* current replacement for LINE */
4500 char *head; /* start of line */
4501 char *ptr; /* current examination point */
4502 int changed = 0; /* did we make a substitution? */
4503 int eval_line = 0; /* is this line a .eval/.asg statement? */
4504 int eval_symbol = 0; /* are we in the middle of the symbol for .eval/.asg? */
4505 char *eval_end = NULL;
4507 int line_conditional = 0;
4510 /* work with a copy of the input line */
4511 replacement = xmalloc (strlen (line) + 1);
4512 strcpy (replacement, line);
4514 ptr = head = replacement;
4516 /* flag lines where we might need to replace a single '=' with two;
4517 GAS uses single '=' to assign macro args values, and possibly other
4518 places, so limit what we replace */
4519 if (strstr (line, ".if")
4520 || strstr (line, ".elseif")
4521 || strstr (line, ".break"))
4523 line_conditional = 1;
4526 /* watch out for .eval, so that we avoid doing substitution on the
4527 symbol being assigned a value */
4528 if (strstr (line, ".eval") || strstr (line, ".asg"))
4531 /* if it's a macro definition, don't do substitution on the argument names */
4532 if (strstr (line, ".macro"))
4535 while (!is_end_of_line[(int)*ptr])
4537 int current_char = *ptr;
4539 /* need to update this since LINE may have been modified */
4541 eval_end = strrchr (ptr, ',');
4543 /* replace triple double quotes with bounding quote/escapes */
4544 if (current_char == '"' && ptr[1] == '"' && ptr[2] == '"')
4547 tmp = strstr (ptr+2, "\"\"\"");
4553 /* replace a single '=' with a '==';
4554 for compatibility with older code only */
4555 if (line_conditional && current_char == '=')
4563 tmp = xmalloc (strlen (head) + 2 + strlen (ptr) + 1);
4564 sprintf (tmp, "%s==%s", head, ptr);
4565 /* continue examining after the '==' */
4566 ptr = tmp + strlen (head) + 2;
4568 head = replacement = tmp;
4572 /* flag when we've reached the symbol part of .eval/.asg */
4573 if (eval_line && ptr >= eval_end)
4576 /* for each apparent symbol, see if it's a substitution symbol, and if
4577 so, replace it in the input
4579 if ((forced && current_char == ':')
4580 || (!forced && is_name_beginner (current_char)))
4582 char *name; /* symbol to be replaced */
4583 char *savedp = input_line_pointer;
4586 char *tail; /* rest of line after symbol */
4588 /* skip the colon */
4592 name = input_line_pointer = ptr;
4593 c = get_symbol_end ();
4594 /* '?' is not normally part of a symbol, but it IS part of a local
4599 *input_line_pointer++ = c;
4600 c = *input_line_pointer;
4601 *input_line_pointer = '\0';
4603 /* avoid infinite recursion; if a symbol shows up a second time for
4604 substitution, leave it as is */
4605 if (hash_find (subsym_recurse_hash, name) == NULL)
4606 value = subsym_lookup (name, macro_level);
4608 as_warn (_("%s symbol recursion stopped at "
4609 "second appearance of '%s'"),
4610 forced ? "Forced substitution": "Substitution", name);
4611 ptr = tail = input_line_pointer;
4612 input_line_pointer = savedp;
4614 /* check for local labels; replace them with the appropriate
4616 if ((*name == '$' && isdigit (name[1]) && name[2] == '\0')
4617 || name[strlen (name)-1] == '?')
4619 /* use an existing identifier for that label if, available, or
4620 create a new, unique identifier */
4621 value = hash_find (local_label_hash[macro_level], name);
4625 char *namecopy = strcpy (xmalloc (strlen (name) + 1), name);
4626 value = strcpy (xmalloc (strlen (name) + sizeof (digit) + 1),
4629 value[strlen (value)-1] = '\0';
4630 sprintf (digit, ".%d", local_label_id++);
4631 strcat (value, digit);
4632 hash_insert (local_label_hash[macro_level], namecopy, value);
4634 /* indicate where to continue looking for substitutions */
4637 /* check for built-in subsym and math functions */
4638 else if (value != NULL && *name == '$')
4640 subsym_proc_entry *entry = (subsym_proc_entry *)value;
4641 math_proc_entry *math_entry = hash_find (math_hash, name);
4642 char *arg1, *arg2 = NULL;
4647 as_bad (_("Unrecognized substitution symbol function"));
4650 else if (*ptr != '(')
4652 as_bad (_("Missing '(' after substitution symbol function"));
4656 if (math_entry != NULL)
4658 float arg1, arg2 = 0;
4659 volatile float fresult;
4661 arg1 = (float)strtod (ptr, &ptr);
4662 if (math_entry->nargs == 2)
4666 as_bad (_("Expecting second argument"));
4669 arg2 = (float)strtod (ptr, &ptr);
4671 fresult = (*math_entry->proc)(arg1, arg2);
4672 value = xmalloc (128);
4673 if (math_entry->int_return)
4674 sprintf (value, "%d", (int)fresult);
4676 sprintf (value, "%f", fresult);
4679 as_bad (_("Extra junk in function call, expecting ')'"));
4682 /* don't bother recursing; the replacement isn't a symbol */
4688 int arg_type[2] = {*ptr == '"',0};
4689 int ismember = !strcmp (entry->name, "$ismember");
4690 /* parse one or two args, which must be a substitution
4691 symbol, string or a character-string constant */
4692 /* for all functions, a string or substitution symbol may be
4693 used, with the following exceptions:
4694 firstch/lastch: 2nd arg must be character constant
4695 ismember: both args must be substitution symbols
4697 ptr = subsym_get_arg (ptr, ",)", &arg1, ismember);
4700 if (entry->nargs == 2)
4704 as_bad (_("Function expects two arguments"));
4707 /* character constants are converted to numerics
4708 by the preprocessor */
4709 arg_type[1] = (isdigit (*ptr)) ? 2 : (*ptr == '"');
4710 ptr = subsym_get_arg (ptr, ")", &arg2, ismember);
4713 if ((!strcmp (entry->name, "$firstch")
4714 || !strcmp (entry->name, "$lastch"))
4715 && arg_type[1] != 2)
4717 as_bad (_("Expecting character constant argument"));
4721 && (arg_type[0] != 0 || arg_type[1] != 0))
4723 as_bad (_("Both arguments must be substitution symbols"));
4728 as_bad (_("Extra junk in function call, expecting ')'"));
4731 val = (*entry->proc)(arg1, arg2);
4732 value = xmalloc (64);
4733 sprintf (value, "%d", val);
4735 /* fix things up to replace the entire expression, not just the
4741 if (value != NULL && !eval_symbol)
4743 /* Replace the symbol with its string replacement and
4744 continue. Recursively replace VALUE until either no
4745 substitutions are performed, or a substitution that has been
4746 previously made is encountered again.
4748 put the symbol into the recursion hash table so we only
4749 try to replace a symbol once
4753 hash_insert (subsym_recurse_hash, name, name);
4754 value = subsym_substitute (value, macro_level > 0);
4755 hash_delete (subsym_recurse_hash, name);
4758 /* temporarily zero-terminate where the symbol started */
4764 /* subscripted substitution symbol -- use just the
4765 indicated portion of the string; the description
4766 kinda indicates that forced substituion is not
4767 supposed to be recursive, but I'm not sure.
4769 unsigned beg, len = 1; /* default to a single char */
4770 char *newval = strcpy (xmalloc (strlen (value)+1), value);
4772 savedp = input_line_pointer;
4773 input_line_pointer = tail + 1;
4774 beg = get_absolute_expression ();
4777 as_bad (_("Invalid subscript (use 1 to %d)"),
4781 if (*input_line_pointer == ',')
4783 ++input_line_pointer;
4784 len = get_absolute_expression ();
4785 if (beg + len > strlen (value))
4787 as_bad (_("Invalid length (use 0 to %d"),
4788 strlen (value) - beg);
4794 tail = input_line_pointer;
4797 as_bad (_("Missing ')' in subscripted substitution "
4798 "symbol expression"));
4802 input_line_pointer = savedp;
4808 tmp = xmalloc (strlen (head) + strlen (value) +
4809 strlen (tail+1) + 2);
4811 strcat (tmp, value);
4812 /* Make sure forced substitutions are properly terminated */
4817 as_bad (_("Missing forced substitution terminator ':'"));
4822 /* Try to replace required whitespace
4823 eliminated by the preprocessor; technically, a forced
4824 substitution could come anywhere, even mid-symbol,
4825 e.g. if x is "0", 'sym:x:end' should result in 'sym0end',
4826 but 'sym:x: end' should result in 'sym0 end'.
4827 FIXME -- this should really be fixed in the preprocessor,
4828 but would require several new states;
4829 KEEP_WHITE_AROUND_COLON does part of the job, but isn't
4832 if ((is_part_of_name (tail[1])
4835 || tail[1] == '\0' || tail[1] == ',' || tail[1] == '"')
4842 /* restore the character after the symbol end */
4845 /* continue examining after the replacement value */
4846 ptr = tmp + strlen (head) + strlen (value);
4848 head = replacement = tmp;
4866 /* we use this to handle substitution symbols
4867 hijack input_line_pointer, replacing it with our substituted string.
4869 .sslist should enable listing the line after replacements are made...
4871 returns the new buffer limit
4874 tic54x_start_line_hook ()
4877 char *replacement = NULL;
4879 /* work with a copy of the input line, including EOL char */
4880 endp = input_line_pointer;
4881 while (!is_end_of_line[(int)*endp++])
4883 line = xmalloc (endp - input_line_pointer + 1);
4884 strncpy (line, input_line_pointer, endp - input_line_pointer + 1);
4885 line[endp - input_line_pointer] = 0;
4887 /* scan ahead for parallel insns */
4888 parallel_on_next_line_hint = next_line_shows_parallel (endp + 1);
4890 /* if within a macro, first process forced replacements */
4891 if (macro_level > 0)
4892 replacement = subsym_substitute (line, 1);
4895 replacement = subsym_substitute (replacement, 0);
4897 if (replacement != line)
4899 char *tmp = replacement;
4900 char *comment = strchr (replacement,';');
4901 char endc = replacement[strlen (replacement)-1];
4903 /* clean up the replacement; we'd prefer to have this done by the
4904 standard preprocessing equipment (maybe do_scrub_chars?)
4905 but for now, do a quick-and-dirty
4907 if (comment != NULL)
4914 comment = replacement + strlen (replacement) - 1;
4916 /* trim trailing whitespace */
4917 while (isspace (*comment))
4924 /* compact leading whitespace */
4925 while (isspace (tmp[0]) && isspace (tmp[1]))
4928 input_line_pointer = endp;
4929 input_scrub_insert_line (tmp);
4932 /* keep track of whether we've done a substitution */
4933 substitution_line = 1;
4939 substitution_line = 0;
4943 /* This is the guts of the machine-dependent assembler. STR points to a
4944 machine dependent instruction. This function is supposed to emit
4945 the frags/bytes it assembles to.
4951 static int repeat_slot = 0;
4952 static int delay_slots = 0; /* how many delay slots left to fill? */
4953 static int is_parallel = 0;
4954 static tic54x_insn insn;
4956 char *savedp = input_line_pointer;
4959 input_line_pointer = line;
4960 c = get_symbol_end ();
4964 if (address_mode_needs_set)
4966 set_address_mode (amode);
4967 address_mode_needs_set = 0;
4980 strcpy (insn.parmnemonic, line);
4981 lptr = input_line_pointer;
4983 input_line_pointer = savedp;
4985 if (tic54x_parse_parallel_insn_lastline (&insn, lptr))
4987 int words = build_insn (&insn);
4989 if (delay_slots != 0)
4991 if (words > delay_slots)
4993 as_bad (_("Instruction does not fit in available delay "
4994 "slots (%d-word insn, %d slots left)"),
4995 words, delay_slots);
4999 delay_slots -= words;
5005 memset (&insn, 0, sizeof (insn));
5006 strcpy (insn.mnemonic, line);
5007 lptr = input_line_pointer;
5009 input_line_pointer = savedp;
5011 /* See if this line is part of a parallel instruction; if so, either this
5012 line or the next line will have the "||" specifier preceding the
5013 mnemonic, and we look for it in the parallel insn hash table */
5014 if (strstr (line, "||") != NULL || parallel_on_next_line_hint)
5016 char *tmp = strstr (line, "||");
5020 if (tic54x_parse_parallel_insn_firstline (&insn, lptr))
5023 /* if the parallel part is on the same line, process it now,
5024 otherwise let the assembler pick up the next line for us */
5027 while (isspace (tmp[2]))
5029 md_assemble (tmp+2);
5034 as_bad (_("Unrecognized parallel instruction '%s'"), line);
5039 if (tic54x_parse_insn (&insn, lptr))
5043 if ((insn.tm->flags & FL_LP)
5044 && cpu != V545LP && cpu != V546LP)
5046 as_bad (_("Instruction '%s' requires an LP cpu version"),
5050 if ((insn.tm->flags & FL_FAR)
5051 && amode != far_mode)
5053 as_bad (_("Instruction '%s' requires far mode addressing"),
5058 words = build_insn (&insn);
5060 /* Is this instruction in a delay slot? */
5063 if (words > delay_slots)
5065 as_warn (_("Instruction does not fit in available delay "
5066 "slots (%d-word insn, %d slots left). "
5067 "Resulting behavior is undefined."),
5068 words, delay_slots);
5072 /* branches in delay slots are not allowed */
5073 if (insn.tm->flags & FL_BMASK)
5075 as_warn (_("Instructions which cause PC discontinuity are not "
5076 "allowed in a delay slot. "
5077 "Resulting behavior is undefined."));
5079 delay_slots -= words;
5081 /* Is this instruction the target of a repeat? */
5084 if (insn.tm->flags & FL_NR)
5085 as_warn (_("'%s' is not repeatable. "
5086 "Resulting behavior is undefined."),
5088 else if (insn.is_lkaddr)
5089 as_warn (_("Instructions using long offset modifiers or absolute "
5090 "addresses are not repeatable. "
5091 "Resulting behavior is undefined."));
5095 /* make sure we check the target of a repeat instruction */
5096 if (insn.tm->flags & B_REPEAT)
5099 /* FIXME -- warn if repeat_slot == 1 at EOF */
5101 /* make sure we check our delay slots for validity */
5102 if (insn.tm->flags & FL_DELAY)
5105 /* FIXME -- warn if delay_slots != 0 at EOF */
5110 /* Do a final adjustment on the symbol table; in this case, make sure we have
5113 tic54x_adjust_symtab ()
5115 if (symbol_rootP == NULL
5116 || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
5120 as_where (&filename, &lineno);
5121 c_dot_file_symbol (filename);
5125 /* In order to get gas to ignore any | chars at the start of a line,
5126 this function returns true if a | is found in a line.
5127 This lets us process parallel instructions, which span two lines
5130 tic54x_unrecognized_line (int c)
5132 return c == PARALLEL_SEPARATOR;
5135 /* Watch for local labels of the form $[0-9] and [_a-zA-Z][_a-zA-Z0-9]*?
5136 Encode their names so that only we see them and can map them to the
5138 FIXME -- obviously this isn't done yet. These locals still show up in the
5142 tic54x_define_label (symbolS *sym)
5144 /*static int local_label_count = 0;*/
5145 /*const char *name = S_GET_NAME (sym);*/
5147 /* just in case we need this later; note that this is not necessarily the
5148 same thing as line_label...
5149 When aligning or assigning labels to fields, sometimes the label is
5150 assigned other than the address at which the label appears.
5151 FIXME -- is this really needed? I think all the proper label assignment
5152 is done in tic54x_cons.
5154 last_label_seen = sym;
5157 /* Try to parse something that normal parsing failed at. */
5159 tic54x_undefined_symbol (name)
5164 /* not sure how to handle predefined symbols */
5165 if ((sym = (symbol *)hash_find (cc_hash, name)) != NULL ||
5166 (sym = (symbol *)hash_find (cc2_hash, name)) != NULL ||
5167 (sym = (symbol *)hash_find (cc3_hash, name)) != NULL ||
5168 (sym = (symbol *)hash_find (misc_symbol_hash, name)) != NULL ||
5169 (sym = (symbol *)hash_find (sbit_hash, name)) != NULL)
5171 return symbol_new (name, reg_section,
5172 (valueT) sym->value,
5173 &zero_address_frag);
5176 if ((sym = (symbol *)hash_find (reg_hash, name)) != NULL ||
5177 (sym = (symbol *)hash_find (mmreg_hash, name)) != NULL ||
5178 !strcasecmp (name, "a") || !strcasecmp (name, "b"))
5180 return symbol_new (name, reg_section,
5181 (valueT) sym ? sym->value : 0,
5182 &zero_address_frag);
5188 /* parse a name in an expression before the expression parser takes a stab at
5191 tic54x_parse_name (name, exp)
5192 char *name ATTRIBUTE_UNUSED;
5193 expressionS *exp ATTRIBUTE_UNUSED;
5196 symbol *sym = (symbol *)hash_find (mmreg_hash, name);
5197 /* if it's a MMREG, replace it with its constant value */
5200 exp->X_op = O_constant;
5201 exp->X_add_number = sym->value;
5209 md_atof (type, literalP, sizeP)
5214 #define MAX_LITTLENUMS 2
5215 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5216 LITTLENUM_TYPE *word;
5217 /* only one precision on the c54x */
5219 char *t = atof_ieee (input_line_pointer, type, words);
5221 input_line_pointer = t;
5224 /* target data is little-endian, but floats are stored big-"word"ian. ugh */
5225 for (word = words; prec--;)
5227 md_number_to_chars (literalP, (long)(*word++), sizeof (LITTLENUM_TYPE));
5228 literalP += sizeof (LITTLENUM_TYPE);
5235 tc_gen_reloc (section, fixP)
5240 bfd_reloc_code_real_type code = fixP->fx_r_type;
5241 asymbol *sym = symbol_get_bfdsym (fixP->fx_addsy);
5243 rel = (arelent *) xmalloc (sizeof (arelent));
5244 rel->sym_ptr_ptr = (asymbol **)xmalloc (sizeof (asymbol *));
5245 *rel->sym_ptr_ptr = sym;
5246 /* We assume that all rel->address are host byte offsets */
5247 rel->address = fixP->fx_frag->fr_address + fixP->fx_where;
5248 rel->address /= OCTETS_PER_BYTE;
5249 rel->howto = bfd_reloc_type_lookup (stdoutput, code);
5250 if (!strcmp (sym->name, section->name))
5251 rel->howto += HOWTO_BANK;
5255 const char *name = S_GET_NAME (fixP->fx_addsy);
5258 as_fatal ("Cannot generate relocation type for symbol %s, code %s",
5259 name, bfd_get_reloc_code_name (code));
5265 /* handle cons expressions */
5267 tic54x_cons_fix_new (fragS *frag, int where, int octets, expressionS *exp)
5269 bfd_reloc_code_real_type r;
5273 as_bad (_("Unsupported relocation size %d"), octets);
5274 r = BFD_RELOC_TIC54X_16_OF_23;
5277 r = BFD_RELOC_TIC54X_16_OF_23;
5280 /* TI assembler always uses this, regardless of addressing mode */
5282 r = BFD_RELOC_TIC54X_23;
5284 /* we never want to directly generate this; this is provided for
5285 stabs support only */
5289 fix_new_exp (frag, where, octets, exp, 0, r);
5292 /* Attempt to simplify or even eliminate a fixup.
5293 To indicate that a fixup has been eliminated, set fixP->fx_done.
5295 If fixp->fx_addsy is non-NULL, we'll have to generate a reloc entry.
5298 md_apply_fix (fixP, valP)
5302 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
5305 switch (fixP->fx_r_type)
5308 as_fatal ("Bad relocation type: 0x%02x", fixP->fx_r_type);
5310 case BFD_RELOC_TIC54X_MS7_OF_23:
5311 val = (val >> 16) & 0x7F;
5313 case BFD_RELOC_TIC54X_16_OF_23:
5315 bfd_put_16 (stdoutput, val, buf);
5316 /* indicate what we're actually writing, so that we don't get warnings
5317 about exceeding available space */
5318 *valP = val & 0xFFFF;
5320 case BFD_RELOC_TIC54X_PARTLS7:
5321 bfd_put_16 (stdoutput,
5322 (bfd_get_16 (stdoutput, buf) & 0xFF80) | (val & 0x7F),
5324 /* indicate what we're actually writing, so that we don't get warnings
5325 about exceeding available space */
5328 case BFD_RELOC_TIC54X_PARTMS9:
5329 /* TI assembler doesn't shift its encoding for relocatable files, and is
5330 thus incompatible with this implementation's relocatable files */
5331 bfd_put_16 (stdoutput,
5332 (bfd_get_16 (stdoutput, buf) & 0xFE00) | (val >> 7),
5336 case BFD_RELOC_TIC54X_23:
5337 bfd_put_32 (stdoutput,
5338 (bfd_get_32 (stdoutput, buf) & 0xFF800000) | val,
5343 return 0; /* return value is ignored */
5346 /* this is our chance to record section alignment
5347 don't need to do anything here, since BFD does the proper encoding
5350 md_section_align (segment, section_size)
5351 segT segment ATTRIBUTE_UNUSED;
5352 valueT section_size;
5354 return section_size;
5358 md_pcrel_from (fixP)
5359 fixS *fixP ATTRIBUTE_UNUSED;
5364 #if defined OBJ_COFF
5367 tc_coff_fix2rtype (fixP)
5370 return (fixP->fx_r_type);
5373 #endif /* OBJ_COFF */
5375 /* mostly little-endian, but longwords (4 octets) get MS word stored first */
5377 tic54x_number_to_chars (buf, val, n)
5383 number_to_chars_littleendian (buf, val, n);
5386 number_to_chars_littleendian (buf, val>>16, 2);
5387 number_to_chars_littleendian (buf+2, val&0xFFFF, 2);
5392 tic54x_estimate_size_before_relax (frag, seg)
5393 fragS *frag ATTRIBUTE_UNUSED;
5394 segT seg ATTRIBUTE_UNUSED;
5399 /* we use this to handle bit allocations which we couldn't handle before due
5400 to symbols being in different frags. return number of octets added. */
5402 tic54x_relax_frag (frag, stretch)
5404 long stretch ATTRIBUTE_UNUSED;
5406 symbolS *sym = frag->fr_symbol;
5412 struct bit_info *bi = (struct bit_info *)frag->fr_opcode;
5413 int bit_offset = frag_bit_offset (frag_prev (frag, bi->seg), bi->seg);
5414 int size = S_GET_VALUE (sym);
5415 fragS *prev_frag = bit_offset_frag (frag_prev (frag, bi->seg), bi->seg);
5416 int available = 16 - bit_offset;
5418 if (symbol_get_frag (sym) != &zero_address_frag
5419 || S_IS_COMMON (sym)
5420 || !S_IS_DEFINED (sym))
5421 as_bad_where (frag->fr_file, frag->fr_line,
5422 _("non-absolute value used with .space/.bes"));
5426 as_warn (_("negative value ignored in %s"),
5427 bi->type == TYPE_SPACE ? ".space" :
5428 bi->type == TYPE_BES ? ".bes" : ".field");
5430 frag->tc_frag_data = frag->fr_fix = 0;
5434 if (bi->type == TYPE_FIELD)
5436 /* bit fields of 16 or larger will have already been handled */
5437 if (bit_offset != 0 && available >= size)
5439 char *p = prev_frag->fr_literal;
5440 valueT value = bi->value;
5441 value <<= available - size;
5442 value |= ((unsigned short)p[1]<<8) | p[0];
5443 md_number_to_chars (p, value, 2);
5444 if ((prev_frag->tc_frag_data += size) == 16)
5445 prev_frag->tc_frag_data = 0;
5447 symbol_set_frag (bi->sym, prev_frag);
5448 /* this frag is no longer used */
5449 growth = -frag->fr_fix;
5451 frag->tc_frag_data = 0;
5455 char *p = frag->fr_literal;
5456 valueT value = bi->value << (16 - size);
5457 md_number_to_chars (p, value, 2);
5458 if ((frag->tc_frag_data = size) == 16)
5459 frag->tc_frag_data = 0;
5465 if (bit_offset != 0 && bit_offset < 16)
5467 if (available >= size)
5469 if ((prev_frag->tc_frag_data += size) == 16)
5470 prev_frag->tc_frag_data = 0;
5472 symbol_set_frag (bi->sym, prev_frag);
5473 /* this frag is no longer used */
5474 growth = -frag->fr_fix;
5476 frag->tc_frag_data = 0;
5479 if (bi->type == TYPE_SPACE && bi->sym)
5480 symbol_set_frag (bi->sym, prev_frag);
5483 growth = (size + 15) / 16 * OCTETS_PER_BYTE - frag->fr_fix;
5484 for (i=0;i < growth;i++)
5485 frag->fr_literal[i] = 0;
5486 frag->fr_fix = growth;
5487 frag->tc_frag_data = size % 16;
5488 /* make sure any BES label points to the LAST word allocated */
5489 if (bi->type == TYPE_BES && bi->sym)
5490 S_SET_VALUE (bi->sym, frag->fr_fix / OCTETS_PER_BYTE - 1);
5493 frag->fr_symbol = 0;
5494 frag->fr_opcode = 0;
5501 tic54x_convert_frag (abfd, seg, frag)
5502 bfd *abfd ATTRIBUTE_UNUSED;
5503 segT seg ATTRIBUTE_UNUSED;
5506 /* offset is in bytes */
5507 frag->fr_offset = (frag->fr_next->fr_address
5509 - frag->fr_fix) / frag->fr_var;
5510 if (frag->fr_offset < 0)
5512 as_bad_where (frag->fr_file, frag->fr_line,
5513 _("attempt to .space/.bes backwards? (%ld)"),
5514 (long) frag->fr_offset);
5516 frag->fr_type = rs_space;
5519 /* we need to avoid having labels defined for certain directives/pseudo-ops
5520 since once the label is defined, it's in the symbol table for good. TI
5521 syntax puts the symbol *before* the pseudo (which is kinda like MRI syntax,
5522 I guess, except I've never seen a definition of MRI syntax).
5524 C is the character that used to be at *REST, which points to the end of the
5527 Don't allow labels to start with '.'
5530 tic54x_start_label (c, rest)
5534 /* if within .struct/.union, no auto line labels, please */
5535 if (current_stag != NULL)
5538 /* disallow labels starting with "." */
5542 while (!is_end_of_line[(int)label[-1]])
5546 as_bad (_("Invalid label '%s'"), label);
5551 if (is_end_of_line[(int)c])
5555 while (isspace (c = *++rest))
5559 /* don't let colon () define a label for any of these... */
5560 return (strncasecmp (rest, ".tag", 4) != 0 || !isspace (rest[4]))
5561 && (strncasecmp (rest, ".struct", 7) != 0 || !isspace (rest[7]))
5562 && (strncasecmp (rest, ".union", 6) != 0 || !isspace (rest[6]))
5563 && (strncasecmp (rest, ".macro", 6) != 0 || !isspace (rest[6]))
5564 && (strncasecmp (rest, ".set", 4) != 0 || !isspace (rest[4]))
5565 && (strncasecmp (rest, ".equ", 4) != 0 || !isspace (rest[4]));