Automatic date update in version.in
[binutils-gdb.git] / gas / config / tc-tic54x.c
blobb60b1a7777ba69ffa9dde8972f8fabd67c331dcd
1 /* tc-tic54x.c -- Assembly code for the Texas Instruments TMS320C54X
2 Copyright (C) 1999-2024 Free Software Foundation, Inc.
3 Contributed by Timothy Wall (twall@cygnus.com)
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 3, or (at your option)
10 any later version.
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, 51 Franklin Street - Fifth Floor, Boston, MA
20 02110-1301, USA. */
22 /* Texas Instruments TMS320C54X machine specific gas.
23 Written by Timothy Wall (twall@alum.mit.edu).
25 Valuable things to do:
26 Pipeline conflict warnings
27 We encode/decode "ld #_label, dp" differently in relocatable files
28 This means we're not compatible with TI output containing those
29 expressions. We store the upper nine bits; TI stores the lower nine
30 bits. How they recover the original upper nine bits is beyond me.
32 Tests to add to expect testsuite:
33 '=' and '==' with .if, .elseif, and .break
35 Incompatibilities (mostly trivial):
36 We don't allow '''
37 We fill text section with zeroes instead of "nop"s
38 We don't convert '' or "" to a single instance
39 We don't convert '' to '\0'
40 We don't allow strings with .byte/.half/.short/.long
41 Probably details of the subsym stuff are different
42 TI sets labels to be data type 4 (T_INT); GAS uses T_NULL.
44 COFF1 limits section names to 8 characters.
45 Some of the default behavior changed from COFF1 to COFF2. */
47 #include "as.h"
48 #include <limits.h>
49 #include "safe-ctype.h"
50 #include "sb.h"
51 #include "macro.h"
52 #include "subsegs.h"
53 #include "opcode/tic54x.h"
54 #include "obj-coff.h"
55 #include <math.h>
58 static struct stag
60 symbolS *sym; /* Symbol for this stag; value is offset. */
61 const char *name; /* Shortcut to symbol name. */
62 bfd_vma size; /* Size of struct/union. */
63 int current_bitfield_offset; /* Temporary for tracking fields. */
64 int is_union;
65 struct stag_field /* List of fields. */
67 const char *name;
68 bfd_vma offset; /* Of start of this field. */
69 int bitfield_offset; /* Of start of this field. */
70 struct stag *stag; /* If field is struct/union. */
71 struct stag_field *next;
72 } *field;
73 /* For nesting; used only in stag construction. */
74 struct stag *inner; /* Enclosed .struct. */
75 struct stag *outer; /* Enclosing .struct. */
76 } *current_stag = NULL;
78 #define MAX_LINE 256 /* Lines longer than this are truncated by TI's asm. */
80 typedef struct _tic54x_insn
82 const insn_template *tm; /* Opcode template. */
84 char mnemonic[MAX_LINE]; /* Opcode name/mnemonic. */
85 char parmnemonic[MAX_LINE]; /* 2nd mnemonic of parallel insn. */
87 int opcount;
88 struct opstruct
90 char buf[MAX_LINE];
91 enum optype type;
92 expressionS exp;
93 } operands[MAX_OPERANDS];
95 int paropcount;
96 struct opstruct paroperands[MAX_OPERANDS];
98 int is_lkaddr;
99 int lkoperand;
100 int words; /* Size of insn in 16-bit words. */
101 int using_default_dst; /* Do we need to explicitly set an
102 omitted OP_DST operand? */
103 struct
105 unsigned short word; /* Final encoded opcode data. */
106 int unresolved;
107 int r_nchars; /* Relocation size. */
108 bfd_reloc_code_real_type r_type; /* Relocation type. */
109 expressionS addr_expr; /* Storage for unresolved expressions. */
110 } opcode[3];
111 } tic54x_insn;
113 enum cpu_version
115 VNONE = 0, V541 = 1, V542 = 2, V543 = 3, V545 = 5, V548 = 8, V549 = 9,
116 V545LP = 15, V546LP = 16
119 enum address_mode
121 c_mode, /* 16-bit addresses. */
122 far_mode /* >16-bit addresses. */
125 static segT stag_saved_seg;
126 static subsegT stag_saved_subseg;
128 const char comment_chars[] = ";";
129 const char line_comment_chars[] = ";*#"; /* At column zero only. */
130 const char line_separator_chars[] = ""; /* Not permitted. */
132 int emitting_long = 0;
134 /* Characters which indicate that this is a floating point constant. */
135 const char FLT_CHARS[] = "fF";
137 /* Characters that can be used to separate mantissa from exp in FP
138 nums. */
139 const char EXP_CHARS[] = "eE";
141 const char md_shortopts[] = "";
143 #define OPTION_ADDRESS_MODE (OPTION_MD_BASE)
144 #define OPTION_CPU_VERSION (OPTION_ADDRESS_MODE + 1)
145 #define OPTION_COFF_VERSION (OPTION_CPU_VERSION + 1)
146 #define OPTION_STDERR_TO_FILE (OPTION_COFF_VERSION + 1)
148 const struct option md_longopts[] =
150 { "mfar-mode", no_argument, NULL, OPTION_ADDRESS_MODE },
151 { "mf", no_argument, NULL, OPTION_ADDRESS_MODE },
152 { "mcpu", required_argument, NULL, OPTION_CPU_VERSION },
153 { "merrors-to-file", required_argument, NULL, OPTION_STDERR_TO_FILE },
154 { "me", required_argument, NULL, OPTION_STDERR_TO_FILE },
155 { NULL, no_argument, NULL, 0},
158 const size_t md_longopts_size = sizeof (md_longopts);
160 static int assembly_begun = 0;
161 /* Addressing mode is not entirely implemented; the latest rev of the Other
162 assembler doesn't seem to make any distinction whatsoever; all relocations
163 are stored as extended relocations. Older versions used REL16 vs RELEXT16,
164 but now it seems all relocations are RELEXT16. We use all RELEXT16.
166 The cpu version is kind of a waste of time as well. There is one
167 instruction (RND) for LP devices only, and several for devices with
168 extended addressing only. We include it for compatibility. */
169 static enum address_mode amode = c_mode;
170 static enum cpu_version cpu = VNONE;
172 /* Include string substitutions in listing? */
173 static int listing_sslist = 0;
175 /* Did we do subsym substitutions on the line? */
176 static int substitution_line = 0;
178 /* Last label seen. */
179 static symbolS *last_label_seen = NULL;
181 /* This ensures that all new labels are unique. */
182 static int local_label_id;
184 static htab_t subsym_recurse_hash; /* Prevent infinite recurse. */
185 /* Allow maximum levels of macro nesting; level 0 is the main substitution
186 symbol table. The other assembler only does 32 levels, so there! */
187 #define MAX_SUBSYM_HASH 100
188 static htab_t subsym_hash[MAX_SUBSYM_HASH];
190 typedef struct
192 const char *name;
193 union {
194 int (*s) (char *, char *);
195 float (*f) (float, float);
196 int (*i) (float, float);
197 } proc;
198 int nargs;
199 int type;
200 } subsym_proc_entry;
202 typedef struct {
203 union {
204 char *s;
205 const subsym_proc_entry *p;
206 } u;
207 unsigned int freekey : 1;
208 unsigned int freeval : 1;
209 unsigned int isproc : 1;
210 unsigned int ismath : 1;
211 } subsym_ent_t;
214 /* Keep track of local labels so we can substitute them before GAS sees them
215 since macros use their own 'namespace' for local labels, use a separate hash
217 We do our own local label handling 'cuz it's subtly different from the
218 stock GAS handling.
220 We use our own macro nesting counter, since GAS overloads it when expanding
221 other things (like conditionals and repeat loops). */
222 static int macro_level = 0;
223 static htab_t local_label_hash[MAX_SUBSYM_HASH];
224 /* Keep track of struct/union tags. */
225 static htab_t stag_hash;
226 static htab_t op_hash;
227 static htab_t parop_hash;
228 static htab_t reg_hash;
229 static htab_t mmreg_hash;
230 static htab_t cc_hash;
231 static htab_t cc2_hash;
232 static htab_t cc3_hash;
233 static htab_t sbit_hash;
234 static htab_t misc_symbol_hash;
236 /* Only word (et al.), align, or conditionals are allowed within
237 .struct/.union. */
238 #define ILLEGAL_WITHIN_STRUCT() \
239 do \
240 if (current_stag != NULL) \
242 as_bad (_("pseudo-op illegal within .struct/.union")); \
243 return; \
245 while (0)
248 static void subsym_create_or_replace (char *, char *);
249 static subsym_ent_t *subsym_lookup (char *, int);
250 static char *subsym_substitute (char *, int);
253 void
254 md_show_usage (FILE *stream)
256 fprintf (stream, _("C54x-specific command line options:\n"));
257 fprintf (stream, _("-mfar-mode | -mf Use extended addressing\n"));
258 fprintf (stream, _("-mcpu=<CPU version> Specify the CPU version\n"));
259 fprintf (stream, _("-merrors-to-file <filename>\n"));
260 fprintf (stream, _("-me <filename> Redirect errors to a file\n"));
263 /* Output a single character (upper octet is zero). */
265 static void
266 tic54x_emit_char (char c)
268 expressionS expn;
270 expn.X_op = O_constant;
271 expn.X_add_number = c;
272 emit_expr (&expn, 2);
275 /* Walk backwards in the frag chain. */
277 static fragS *
278 frag_prev (fragS *frag, segT seg)
280 segment_info_type *seginfo = seg_info (seg);
281 fragS *fragp;
283 for (fragp = seginfo->frchainP->frch_root; fragp; fragp = fragp->fr_next)
284 if (fragp->fr_next == frag)
285 return fragp;
287 return NULL;
290 static fragS *
291 bit_offset_frag (fragS *frag, segT seg)
293 while (frag != NULL)
295 if (frag->fr_fix == 0
296 && frag->fr_opcode == NULL
297 && frag->tc_frag_data == 0)
298 frag = frag_prev (frag, seg);
299 else
300 return frag;
302 return NULL;
305 /* Return the number of bits allocated in the most recent word, or zero if
306 none. .field/.space/.bes may leave words partially allocated. */
308 static int
309 frag_bit_offset (fragS *frag, segT seg)
311 frag = bit_offset_frag (frag, seg);
313 if (frag)
314 return frag->fr_opcode != NULL ? -1 : frag->tc_frag_data;
316 return 0;
319 /* Read an expression from a C string; returns a pointer past the end of the
320 expression. */
322 static char *
323 parse_expression (char *str, expressionS *expn)
325 char *s;
326 char *tmp;
328 tmp = input_line_pointer; /* Save line pointer. */
329 input_line_pointer = str;
330 expression (expn);
331 s = input_line_pointer;
332 input_line_pointer = tmp; /* Restore line pointer. */
333 return s; /* Return pointer to where parsing stopped. */
336 /* .asg "character-string"|character-string, symbol
338 .eval is the only pseudo-op allowed to perform arithmetic on substitution
339 symbols. all other use of symbols defined with .asg are currently
340 unsupported. */
342 static void
343 tic54x_asg (int x ATTRIBUTE_UNUSED)
345 int c;
346 char *name;
347 char *str;
348 int quoted = *input_line_pointer == '"';
350 ILLEGAL_WITHIN_STRUCT ();
352 if (quoted)
354 int len;
355 str = demand_copy_C_string (&len);
356 c = *input_line_pointer;
358 else
360 size_t len;
361 str = input_line_pointer;
362 while ((c = *input_line_pointer) != ',')
364 if (is_end_of_line[(unsigned char) c])
365 break;
366 ++input_line_pointer;
368 len = input_line_pointer - str;
369 str = notes_memdup (str, len, len + 1);
371 if (c != ',')
373 as_bad (_("Comma and symbol expected for '.asg STRING, SYMBOL'"));
374 notes_free (str);
375 ignore_rest_of_line ();
376 return;
379 ++input_line_pointer;
380 c = get_symbol_name (&name); /* Get terminator. */
381 name = notes_strdup (name);
382 (void) restore_line_pointer (c);
383 if (!ISALPHA (*name))
385 as_bad (_("symbols assigned with .asg must begin with a letter"));
386 notes_free (str);
387 ignore_rest_of_line ();
388 return;
391 subsym_create_or_replace (name, str);
392 demand_empty_rest_of_line ();
395 /* .eval expression, symbol
396 There's something screwy about this. The other assembler sometimes does and
397 sometimes doesn't substitute symbols defined with .eval.
398 We'll put the symbols into the subsym table as well as the normal symbol
399 table, since that's what works best. */
401 static void
402 tic54x_eval (int x ATTRIBUTE_UNUSED)
404 char c;
405 int value;
406 char *name;
407 symbolS *symbolP;
408 char valuestr[32], *tmp;
409 int quoted;
411 ILLEGAL_WITHIN_STRUCT ();
413 SKIP_WHITESPACE ();
415 quoted = *input_line_pointer == '"';
416 if (quoted)
417 ++input_line_pointer;
418 value = get_absolute_expression ();
419 if (quoted)
421 if (*input_line_pointer != '"')
423 as_bad (_("Unterminated string after absolute expression"));
424 ignore_rest_of_line ();
425 return;
427 ++input_line_pointer;
429 if (*input_line_pointer++ != ',')
431 as_bad (_("Comma and symbol expected for '.eval EXPR, SYMBOL'"));
432 ignore_rest_of_line ();
433 return;
435 c = get_symbol_name (&name); /* Get terminator. */
437 if (!ISALPHA (*name))
439 as_bad (_("symbols assigned with .eval must begin with a letter"));
440 (void) restore_line_pointer (c);
441 ignore_rest_of_line ();
442 return;
444 name = notes_strdup (name);
445 (void) restore_line_pointer (c);
447 symbolP = symbol_new (name, absolute_section, &zero_address_frag, value);
448 SF_SET_LOCAL (symbolP);
449 symbol_table_insert (symbolP);
451 /* The "other" assembler sometimes doesn't put .eval's in the subsym table
452 But since there's not written rule as to when, don't even bother trying
453 to match their behavior. */
454 sprintf (valuestr, "%d", value);
455 tmp = notes_strdup (valuestr);
456 subsym_create_or_replace (name, tmp);
458 demand_empty_rest_of_line ();
461 /* .bss symbol, size [, [blocking flag] [, alignment flag]
463 alignment is to a longword boundary; blocking is to 128-word boundary.
465 1) if there is a hole in memory, this directive should attempt to fill it
466 (not yet implemented).
468 2) if the blocking flag is not set, allocate at the current SPC
469 otherwise, check to see if the current SPC plus the space to be
470 allocated crosses the page boundary (128 words).
471 if there's not enough space, create a hole and align with the next page
472 boundary.
473 (not yet implemented). */
475 static void
476 tic54x_bss (int x ATTRIBUTE_UNUSED)
478 char c;
479 char *name;
480 char *p;
481 int words;
482 segT current_seg;
483 subsegT current_subseg;
484 symbolS *symbolP;
485 int block = 0;
486 int align = 0;
488 ILLEGAL_WITHIN_STRUCT ();
490 current_seg = now_seg; /* Save current seg. */
491 current_subseg = now_subseg; /* Save current subseg. */
493 c = get_symbol_name (&name); /* Get terminator. */
494 if (c == '"')
495 c = * ++ input_line_pointer;
496 if (c != ',')
498 as_bad (_(".bss size argument missing\n"));
499 ignore_rest_of_line ();
500 return;
503 ++input_line_pointer;
504 words = get_absolute_expression ();
505 if (words < 0)
507 as_bad (_(".bss size %d < 0!"), words);
508 ignore_rest_of_line ();
509 return;
512 if (*input_line_pointer == ',')
514 /* The blocking flag may be missing. */
515 ++input_line_pointer;
516 if (*input_line_pointer != ',')
517 block = get_absolute_expression ();
518 else
519 block = 0;
521 if (*input_line_pointer == ',')
523 ++input_line_pointer;
524 align = get_absolute_expression ();
526 else
527 align = 0;
529 else
530 block = align = 0;
532 subseg_set (bss_section, 0);
533 symbolP = symbol_find_or_make (name);
535 if (S_GET_SEGMENT (symbolP) == bss_section)
536 symbol_get_frag (symbolP)->fr_symbol = (symbolS *) NULL;
538 symbol_set_frag (symbolP, frag_now);
539 p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
540 (offsetT) (words * OCTETS_PER_BYTE), (char *) 0);
541 *p = 0; /* Fill char. */
543 S_SET_SEGMENT (symbolP, bss_section);
545 /* The symbol may already have been created with a preceding
546 ".globl" directive -- be careful not to step on storage class
547 in that case. Otherwise, set it to static. */
548 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
549 S_SET_STORAGE_CLASS (symbolP, C_STAT);
551 if (align)
553 /* s_align eats end of line; restore it */
554 s_align_bytes (4);
555 --input_line_pointer;
558 if (block)
559 bss_section->flags |= SEC_TIC54X_BLOCK;
561 subseg_set (current_seg, current_subseg); /* Restore current seg. */
562 demand_empty_rest_of_line ();
565 static void
566 stag_add_field_symbols (struct stag *stag,
567 const char *path,
568 bfd_vma base_offset,
569 symbolS *rootsym,
570 const char *root_stag_name)
572 char * prefix;
573 struct stag_field *field = stag->field;
575 /* Construct a symbol for every field contained within this structure
576 including fields within structure fields. */
577 prefix = concat (path, *path ? "." : "", NULL);
579 while (field != NULL)
581 char *name = concat (prefix, field->name, NULL);
582 char *freename = name;
584 if (rootsym == NULL)
586 symbolS *sym;
587 sym = symbol_new (name, absolute_section, &zero_address_frag,
588 (field->stag ? field->offset
589 : base_offset + field->offset));
590 SF_SET_LOCAL (sym);
591 symbol_table_insert (sym);
593 else
595 subsym_ent_t *ent = xmalloc (sizeof (*ent));
596 ent->u.s = concat (S_GET_NAME (rootsym), "+", root_stag_name,
597 name + strlen (S_GET_NAME (rootsym)), NULL);
598 ent->freekey = 1;
599 ent->freeval = 1;
600 ent->isproc = 0;
601 ent->ismath = 0;
602 str_hash_insert (subsym_hash[0], name, ent, 0);
603 freename = NULL;
606 /* Recurse if the field is a structure.
607 Note the field offset is relative to the outermost struct. */
608 if (field->stag != NULL)
609 stag_add_field_symbols (field->stag, name,
610 field->offset,
611 rootsym, root_stag_name);
612 field = field->next;
613 free (freename);
615 free (prefix);
618 /* Keep track of stag fields so that when structures are nested we can add the
619 complete dereferencing symbols to the symbol table. */
621 static void
622 stag_add_field (struct stag *parent,
623 const char *name,
624 bfd_vma offset,
625 struct stag *stag)
627 struct stag_field *sfield = XCNEW (struct stag_field);
629 sfield->name = xstrdup (name);
630 sfield->offset = offset;
631 sfield->bitfield_offset = parent->current_bitfield_offset;
632 sfield->stag = stag;
633 if (parent->field == NULL)
634 parent->field = sfield;
635 else
637 struct stag_field *sf = parent->field;
638 while (sf->next != NULL)
639 sf = sf->next;
640 sf->next = sfield;
642 /* Only create a symbol for this field if the parent has no name. */
643 if (startswith (parent->name, ".fake"))
645 symbolS *sym = symbol_new (name, absolute_section, &zero_address_frag,
646 offset);
647 SF_SET_LOCAL (sym);
648 symbol_table_insert (sym);
652 /* [STAG] .struct [OFFSET]
653 Start defining structure offsets (symbols in absolute section). */
655 static void
656 tic54x_struct (int arg)
658 int start_offset = 0;
659 int is_union = arg;
661 if (!current_stag)
663 /* Starting a new struct, switch to absolute section. */
664 stag_saved_seg = now_seg;
665 stag_saved_subseg = now_subseg;
666 subseg_set (absolute_section, 0);
668 /* Align the current pointer. */
669 else if (current_stag->current_bitfield_offset != 0)
671 ++abs_section_offset;
672 current_stag->current_bitfield_offset = 0;
675 /* Offset expression is only meaningful for global .structs. */
676 if (!is_union)
678 /* Offset is ignored in inner structs. */
679 SKIP_WHITESPACE ();
680 if (!is_end_of_line[(unsigned char) *input_line_pointer])
681 start_offset = get_absolute_expression ();
682 else
683 start_offset = 0;
686 if (current_stag)
688 /* Nesting, link to outer one. */
689 current_stag->inner = XCNEW (struct stag);
690 current_stag->inner->outer = current_stag;
691 current_stag = current_stag->inner;
692 if (start_offset)
693 as_warn (_("Offset on nested structures is ignored"));
694 start_offset = abs_section_offset;
696 else
698 current_stag = XCNEW (struct stag);
699 abs_section_offset = start_offset;
701 current_stag->is_union = is_union;
703 if (line_label == NULL)
705 static int struct_count = 0;
706 char fake[] = ".fake_stagNNNNNNN";
707 sprintf (fake, ".fake_stag%d", struct_count++);
708 current_stag->sym = symbol_new (fake, absolute_section,
709 &zero_address_frag,
710 abs_section_offset);
712 else
714 char * label = xstrdup (S_GET_NAME (line_label));
715 current_stag->sym = symbol_new (label,
716 absolute_section,
717 &zero_address_frag,
718 abs_section_offset);
719 free (label);
721 current_stag->name = S_GET_NAME (current_stag->sym);
722 SF_SET_LOCAL (current_stag->sym);
723 /* Nested .structs don't go into the symbol table. */
724 if (current_stag->outer == NULL)
725 symbol_table_insert (current_stag->sym);
727 line_label = NULL;
730 /* [LABEL] .endstruct
731 finish defining structure offsets; optional LABEL's value will be the size
732 of the structure. */
734 static void
735 tic54x_endstruct (int is_union)
737 int size;
738 const char *path =
739 startswith (current_stag->name, ".fake") ? "" : current_stag->name;
741 if (!current_stag || current_stag->is_union != is_union)
743 as_bad (_(".end%s without preceding .%s"),
744 is_union ? "union" : "struct",
745 is_union ? "union" : "struct");
746 ignore_rest_of_line ();
747 return;
750 /* Align end of structures. */
751 if (current_stag->current_bitfield_offset)
753 ++abs_section_offset;
754 current_stag->current_bitfield_offset = 0;
757 if (current_stag->is_union)
758 size = current_stag->size;
759 else
760 size = abs_section_offset - S_GET_VALUE (current_stag->sym);
761 if (line_label != NULL)
763 S_SET_VALUE (line_label, size);
764 symbol_table_insert (line_label);
765 line_label = NULL;
768 /* Union size has already been calculated. */
769 if (!current_stag->is_union)
770 current_stag->size = size;
771 /* Nested .structs don't get put in the stag table. */
772 if (current_stag->outer == NULL)
774 str_hash_insert (stag_hash, current_stag->name, current_stag, 0);
775 stag_add_field_symbols (current_stag, path,
776 S_GET_VALUE (current_stag->sym),
777 NULL, NULL);
779 current_stag = current_stag->outer;
781 /* If this is a nested .struct/.union, add it as a field to the enclosing
782 one. otherwise, restore the section we were in. */
783 if (current_stag != NULL)
785 stag_add_field (current_stag, current_stag->inner->name,
786 S_GET_VALUE (current_stag->inner->sym),
787 current_stag->inner);
789 else
790 subseg_set (stag_saved_seg, stag_saved_subseg);
793 /* [LABEL] .tag STAG
794 Reference a structure within a structure, as a sized field with an optional
795 label.
796 If used outside of a .struct/.endstruct, overlays the given structure
797 format on the existing allocated space. */
799 static void
800 tic54x_tag (int ignore ATTRIBUTE_UNUSED)
802 char *name;
803 int c = get_symbol_name (&name);
804 struct stag *stag = (struct stag *) str_hash_find (stag_hash, name);
806 if (!stag)
808 if (*name)
809 as_bad (_("Unrecognized struct/union tag '%s'"), name);
810 else
811 as_bad (_(".tag requires a structure tag"));
812 ignore_rest_of_line ();
813 return;
815 if (line_label == NULL)
817 as_bad (_("Label required for .tag"));
818 ignore_rest_of_line ();
819 return;
821 else
823 char * label;
825 label = xstrdup (S_GET_NAME (line_label));
826 if (current_stag != NULL)
827 stag_add_field (current_stag, label,
828 abs_section_offset - S_GET_VALUE (current_stag->sym),
829 stag);
830 else
832 symbolS *sym = symbol_find (label);
834 if (!sym)
836 as_bad (_(".tag target '%s' undefined"), label);
837 ignore_rest_of_line ();
838 free (label);
839 return;
841 stag_add_field_symbols (stag, S_GET_NAME (sym),
842 S_GET_VALUE (stag->sym), sym, stag->name);
844 free (label);
847 /* Bump by the struct size, but only if we're within a .struct section. */
848 if (current_stag != NULL && !current_stag->is_union)
849 abs_section_offset += stag->size;
851 (void) restore_line_pointer (c);
852 demand_empty_rest_of_line ();
853 line_label = NULL;
856 /* Handle all .byte, .char, .double, .field, .float, .half, .int, .long,
857 .short, .string, .ubyte, .uchar, .uhalf, .uint, .ulong, .ushort, .uword,
858 and .word. */
860 static void
861 tic54x_struct_field (int type)
863 int size;
864 int count = 1;
865 int new_bitfield_offset = 0;
866 int field_align = current_stag->current_bitfield_offset != 0;
867 int longword_align = 0;
869 SKIP_WHITESPACE ();
870 if (!is_end_of_line[(unsigned char) *input_line_pointer])
871 count = get_absolute_expression ();
873 switch (type)
875 case 'b':
876 case 'B':
877 case 'c':
878 case 'C':
879 case 'h':
880 case 'H':
881 case 'i':
882 case 'I':
883 case 's':
884 case 'S':
885 case 'w':
886 case 'W':
887 case '*': /* String. */
888 size = 1;
889 break;
890 case 'f':
891 case 'l':
892 case 'L':
893 longword_align = 1;
894 size = 2;
895 break;
896 case '.': /* Bitfield. */
897 size = 0;
898 if (count < 1 || count > 32)
900 as_bad (_(".field count '%d' out of range (1 <= X <= 32)"), count);
901 ignore_rest_of_line ();
902 return;
904 if (current_stag->current_bitfield_offset + count > 16)
906 /* Set the appropriate size and new field offset. */
907 if (count == 32)
909 size = 2;
910 count = 1;
912 else if (count > 16)
914 size = 1;
915 count = 1;
916 new_bitfield_offset = count - 16;
918 else
919 new_bitfield_offset = count;
921 else
923 field_align = 0;
924 new_bitfield_offset = current_stag->current_bitfield_offset + count;
926 break;
927 default:
928 as_bad (_("Unrecognized field type '%c'"), type);
929 ignore_rest_of_line ();
930 return;
933 if (field_align)
935 /* Align to the actual starting position of the field. */
936 current_stag->current_bitfield_offset = 0;
937 ++abs_section_offset;
939 /* Align to longword boundary. */
940 if (longword_align && (abs_section_offset & 0x1))
941 ++abs_section_offset;
943 if (line_label == NULL)
945 static int fieldno = 0;
946 char fake[] = ".fake_fieldNNNNN";
948 sprintf (fake, ".fake_field%d", fieldno++);
949 stag_add_field (current_stag, fake,
950 abs_section_offset - S_GET_VALUE (current_stag->sym),
951 NULL);
953 else
955 char * label;
957 label = xstrdup (S_GET_NAME (line_label));
958 stag_add_field (current_stag, label,
959 abs_section_offset - S_GET_VALUE (current_stag->sym),
960 NULL);
961 free (label);
964 if (current_stag->is_union)
966 /* Note we treat the element as if it were an array of COUNT. */
967 if (current_stag->size < (unsigned) size * count)
968 current_stag->size = size * count;
970 else
972 abs_section_offset += (unsigned) size * count;
973 current_stag->current_bitfield_offset = new_bitfield_offset;
975 line_label = NULL;
978 /* Handle .byte, .word. .int, .long and all variants. */
980 static void
981 tic54x_cons (int type)
983 unsigned int c;
984 int octets;
986 /* If we're within a .struct construct, don't actually allocate space. */
987 if (current_stag != NULL)
989 tic54x_struct_field (type);
990 return;
993 #ifdef md_flush_pending_output
994 md_flush_pending_output ();
995 #endif
997 generate_lineno_debug ();
999 /* Align long words to long word boundaries (4 octets). */
1000 if (type == 'l' || type == 'L')
1002 frag_align (2, 0, 2);
1003 /* If there's a label, assign it to the first allocated word. */
1004 if (line_label != NULL)
1006 symbol_set_frag (line_label, frag_now);
1007 S_SET_VALUE (line_label, frag_now_fix ());
1011 switch (type)
1013 case 'l':
1014 case 'L':
1015 case 'x':
1016 octets = 4;
1017 break;
1018 case 'b':
1019 case 'B':
1020 case 'c':
1021 case 'C':
1022 octets = 1;
1023 break;
1024 default:
1025 octets = 2;
1026 break;
1031 if (*input_line_pointer == '"')
1033 input_line_pointer++;
1034 while (is_a_char (c = next_char_of_string ()))
1035 tic54x_emit_char (c);
1036 know (input_line_pointer[-1] == '\"');
1038 else
1040 expressionS expn;
1042 input_line_pointer = parse_expression (input_line_pointer, &expn);
1043 if (expn.X_op == O_constant)
1045 offsetT value = expn.X_add_number;
1046 /* Truncate overflows. */
1047 switch (octets)
1049 case 1:
1050 if ((value > 0 && value > 0xFF)
1051 || (value < 0 && value < - 0x100))
1052 as_warn (_("Overflow in expression, truncated to 8 bits"));
1053 break;
1054 case 2:
1055 if ((value > 0 && value > 0xFFFF)
1056 || (value < 0 && value < - 0x10000))
1057 as_warn (_("Overflow in expression, truncated to 16 bits"));
1058 break;
1061 if (expn.X_op != O_constant && octets < 2)
1063 /* Disallow .byte with a non constant expression that will
1064 require relocation. */
1065 as_bad (_("Relocatable values require at least WORD storage"));
1066 ignore_rest_of_line ();
1067 return;
1070 if (expn.X_op != O_constant
1071 && amode == c_mode
1072 && octets == 4)
1074 /* FIXME -- at one point TI tools used to output REL16
1075 relocations, but I don't think the latest tools do at all
1076 The current tools output extended relocations regardless of
1077 the addressing mode (I actually think that ".c_mode" is
1078 totally ignored in the latest tools). */
1079 amode = far_mode;
1080 emitting_long = 1;
1081 emit_expr (&expn, 4);
1082 emitting_long = 0;
1083 amode = c_mode;
1085 else
1087 emitting_long = octets == 4;
1088 emit_expr (&expn, (octets == 1) ? 2 : octets);
1089 emitting_long = 0;
1093 while (*input_line_pointer++ == ',');
1095 input_line_pointer--; /* Put terminator back into stream. */
1096 demand_empty_rest_of_line ();
1099 /* .global <symbol>[,...,<symbolN>]
1100 .def <symbol>[,...,<symbolN>]
1101 .ref <symbol>[,...,<symbolN>]
1103 These all identify global symbols.
1105 .def means the symbol is defined in the current module and can be accessed
1106 by other files. The symbol should be placed in the symbol table.
1108 .ref means the symbol is used in the current module but defined in another
1109 module. The linker is to resolve this symbol's definition at link time.
1111 .global should act as a .ref or .def, as needed.
1113 global, def and ref all have symbol storage classes of C_EXT.
1115 I can't identify any difference in how the "other" c54x assembler treats
1116 these, so we ignore the type here. */
1118 void
1119 tic54x_global (int type)
1121 char *name;
1122 int c;
1123 symbolS *symbolP;
1125 if (type == 'r')
1126 as_warn (_("Use of .def/.ref is deprecated. Use .global instead"));
1128 ILLEGAL_WITHIN_STRUCT ();
1132 c = get_symbol_name (&name);
1133 symbolP = symbol_find_or_make (name);
1134 c = restore_line_pointer (c);
1136 S_SET_STORAGE_CLASS (symbolP, C_EXT);
1137 if (c == ',')
1139 input_line_pointer++;
1140 if (is_end_of_line[(unsigned char) *input_line_pointer])
1141 c = *input_line_pointer;
1144 while (c == ',');
1146 demand_empty_rest_of_line ();
1149 static void
1150 free_subsym_ent (void *ent)
1152 string_tuple_t *tuple = (string_tuple_t *) ent;
1153 subsym_ent_t *val = (void *) tuple->value;
1154 if (val->freekey)
1155 free ((void *) tuple->key);
1156 if (val->freeval)
1157 free (val->u.s);
1158 free (val);
1159 free (ent);
1162 static htab_t
1163 subsym_htab_create (void)
1165 return htab_create_alloc (16, hash_string_tuple, eq_string_tuple,
1166 free_subsym_ent, xcalloc, free);
1169 static void
1170 free_local_label_ent (void *ent)
1172 string_tuple_t *tuple = (string_tuple_t *) ent;
1173 free ((void *) tuple->key);
1174 free ((void *) tuple->value);
1175 free (ent);
1178 static htab_t
1179 local_label_htab_create (void)
1181 return htab_create_alloc (16, hash_string_tuple, eq_string_tuple,
1182 free_local_label_ent, xcalloc, free);
1185 /* Reset all local labels. */
1187 static void
1188 tic54x_clear_local_labels (int ignored ATTRIBUTE_UNUSED)
1190 htab_empty (local_label_hash[macro_level]);
1193 /* .text
1194 .data
1195 .sect "section name"
1197 Initialized section
1198 make sure local labels get cleared when changing sections
1200 ARG is 't' for text, 'd' for data, or '*' for a named section
1202 For compatibility, '*' sections are SEC_CODE if instructions are
1203 encountered, or SEC_DATA if not.
1206 static void
1207 tic54x_sect (int arg)
1209 ILLEGAL_WITHIN_STRUCT ();
1211 /* Local labels are cleared when changing sections. */
1212 tic54x_clear_local_labels (0);
1214 if (arg == 't')
1215 s_text (0);
1216 else if (arg == 'd')
1217 s_data (0);
1218 else
1220 char *name = NULL;
1221 int len;
1222 /* Make sure all named initialized sections flagged properly. If we
1223 encounter instructions, we'll flag it with SEC_CODE as well. */
1224 const char *flags = ",\"w\"\n";
1226 /* If there are quotes, remove them. */
1227 if (*input_line_pointer == '"')
1229 name = demand_copy_C_string (&len);
1230 demand_empty_rest_of_line ();
1231 name = concat (name, flags, (char *) NULL);
1233 else
1235 int c;
1237 c = get_symbol_name (&name);
1238 name = concat (name, flags, (char *) NULL);
1239 (void) restore_line_pointer (c);
1240 demand_empty_rest_of_line ();
1243 input_scrub_insert_line (name);
1244 obj_coff_section (0);
1246 /* If there was a line label, make sure that it gets assigned the proper
1247 section. This is for compatibility, even though the actual behavior
1248 is not explicitly defined. For consistency, we make .sect behave
1249 like .usect, since that is probably what people expect. */
1250 if (line_label != NULL)
1252 S_SET_SEGMENT (line_label, now_seg);
1253 symbol_set_frag (line_label, frag_now);
1254 S_SET_VALUE (line_label, frag_now_fix ());
1255 if (S_GET_STORAGE_CLASS (line_label) != C_EXT)
1256 S_SET_STORAGE_CLASS (line_label, C_LABEL);
1261 /* [symbol] .space space_in_bits
1262 [symbol] .bes space_in_bits
1263 BES puts the symbol at the *last* word allocated
1265 cribbed from s_space. */
1267 static void
1268 tic54x_space (int arg)
1270 expressionS expn;
1271 char *p = 0;
1272 int octets = 0;
1273 long words;
1274 int bits_per_byte = (OCTETS_PER_BYTE * 8);
1275 int bit_offset = 0;
1276 symbolS *label = line_label;
1277 int bes = arg;
1279 ILLEGAL_WITHIN_STRUCT ();
1281 #ifdef md_flush_pending_output
1282 md_flush_pending_output ();
1283 #endif
1285 /* Read the bit count. */
1286 expression (&expn);
1288 /* Some expressions are unresolvable until later in the assembly pass;
1289 postpone until relaxation/fixup. we also have to postpone if a previous
1290 partial allocation has not been completed yet. */
1291 if (expn.X_op != O_constant || frag_bit_offset (frag_now, now_seg) == -1)
1293 struct bit_info *bi = XNEW (struct bit_info);
1295 bi->seg = now_seg;
1296 bi->type = bes;
1297 bi->sym = label;
1298 p = frag_var (rs_machine_dependent,
1299 65536 * 2, 1, (relax_substateT) 0,
1300 make_expr_symbol (&expn), (offsetT) 0,
1301 (char *) bi);
1302 if (p)
1303 *p = 0;
1305 return;
1308 /* Reduce the required size by any bit offsets currently left over
1309 from a previous .space/.bes/.field directive. */
1310 bit_offset = frag_now->tc_frag_data;
1311 if (bit_offset != 0 && bit_offset < 16)
1313 int spare_bits = bits_per_byte - bit_offset;
1315 if (spare_bits >= expn.X_add_number)
1317 /* Don't have to do anything; sufficient bits have already been
1318 allocated; just point the label to the right place. */
1319 if (label != NULL)
1321 symbol_set_frag (label, frag_now);
1322 S_SET_VALUE (label, frag_now_fix () - 1);
1323 label = NULL;
1325 frag_now->tc_frag_data += expn.X_add_number;
1326 goto getout;
1328 expn.X_add_number -= spare_bits;
1329 /* Set the label to point to the first word allocated, which in this
1330 case is the previous word, which was only partially filled. */
1331 if (!bes && label != NULL)
1333 symbol_set_frag (label, frag_now);
1334 S_SET_VALUE (label, frag_now_fix () - 1);
1335 label = NULL;
1338 /* Convert bits to bytes/words and octets, rounding up. */
1339 words = ((expn.X_add_number + bits_per_byte - 1) / bits_per_byte);
1340 /* How many do we have left over? */
1341 bit_offset = expn.X_add_number % bits_per_byte;
1342 octets = words * OCTETS_PER_BYTE;
1343 if (octets < 0)
1345 as_warn (_(".space/.bes repeat count is negative, ignored"));
1346 goto getout;
1348 else if (octets == 0)
1350 as_warn (_(".space/.bes repeat count is zero, ignored"));
1351 goto getout;
1354 /* If we are in the absolute section, just bump the offset. */
1355 if (now_seg == absolute_section)
1357 abs_section_offset += words;
1358 if (bes && label != NULL)
1359 S_SET_VALUE (label, abs_section_offset - 1);
1360 frag_now->tc_frag_data = bit_offset;
1361 goto getout;
1364 if (!need_pass_2)
1365 p = frag_var (rs_fill, 1, 1,
1366 (relax_substateT) 0, (symbolS *) 0,
1367 (offsetT) octets, (char *) 0);
1369 /* Make note of how many bits of this word we've allocated so far. */
1370 frag_now->tc_frag_data = bit_offset;
1372 /* .bes puts label at *last* word allocated. */
1373 if (bes && label != NULL)
1375 symbol_set_frag (label, frag_now);
1376 S_SET_VALUE (label, frag_now_fix () - 1);
1379 if (p)
1380 *p = 0;
1382 getout:
1384 demand_empty_rest_of_line ();
1387 /* [symbol] .usect "section-name", size-in-words
1388 [, [blocking-flag] [, alignment-flag]]
1390 Uninitialized section.
1391 Non-zero blocking means that if the section would cross a page (128-word)
1392 boundary, it will be page-aligned.
1393 Non-zero alignment aligns on a longword boundary.
1395 Has no effect on the current section. */
1397 static void
1398 tic54x_usect (int x ATTRIBUTE_UNUSED)
1400 char c;
1401 char *name;
1402 char *section_name;
1403 char *p;
1404 segT seg;
1405 int size, blocking_flag, alignment_flag;
1406 segT current_seg;
1407 subsegT current_subseg;
1408 flagword flags;
1410 ILLEGAL_WITHIN_STRUCT ();
1412 current_seg = now_seg; /* Save current seg. */
1413 current_subseg = now_subseg; /* Save current subseg. */
1415 c = get_symbol_name (&section_name); /* Get terminator. */
1416 name = xstrdup (section_name);
1417 c = restore_line_pointer (c);
1419 if (c == ',')
1420 ++input_line_pointer;
1421 else
1423 as_bad (_("Missing size argument"));
1424 ignore_rest_of_line ();
1425 return;
1428 size = get_absolute_expression ();
1430 /* Read a possibly present third argument (blocking flag). */
1431 if (*input_line_pointer == ',')
1433 ++input_line_pointer;
1434 if (*input_line_pointer != ',')
1435 blocking_flag = get_absolute_expression ();
1436 else
1437 blocking_flag = 0;
1439 /* Read a possibly present fourth argument (alignment flag). */
1440 if (*input_line_pointer == ',')
1442 ++input_line_pointer;
1443 alignment_flag = get_absolute_expression ();
1445 else
1446 alignment_flag = 0;
1448 else
1449 blocking_flag = alignment_flag = 0;
1451 seg = subseg_new (name, 0);
1452 flags = bfd_section_flags (seg) | SEC_ALLOC;
1454 if (alignment_flag)
1456 /* s_align eats end of line; restore it. */
1457 s_align_bytes (4);
1458 --input_line_pointer;
1461 if (line_label != NULL)
1463 S_SET_SEGMENT (line_label, seg);
1464 symbol_set_frag (line_label, frag_now);
1465 S_SET_VALUE (line_label, frag_now_fix ());
1466 /* Set scl to label, since that's what TI does. */
1467 if (S_GET_STORAGE_CLASS (line_label) != C_EXT)
1468 S_SET_STORAGE_CLASS (line_label, C_LABEL);
1471 seg_info (seg)->bss = 1; /* Uninitialized data. */
1473 p = frag_var (rs_fill, 1, 1,
1474 (relax_substateT) 0, (symbolS *) line_label,
1475 size * OCTETS_PER_BYTE, (char *) 0);
1476 *p = 0;
1478 if (blocking_flag)
1479 flags |= SEC_TIC54X_BLOCK;
1481 if (!bfd_set_section_flags (seg, flags))
1482 as_warn (_("Error setting flags for \"%s\": %s"), name,
1483 bfd_errmsg (bfd_get_error ()));
1485 subseg_set (current_seg, current_subseg); /* Restore current seg. */
1486 demand_empty_rest_of_line ();
1489 static enum cpu_version
1490 lookup_version (const char *ver)
1492 enum cpu_version version = VNONE;
1494 if (ver[0] == '5' && ver[1] == '4')
1496 if (strlen (ver) == 3
1497 && (ver[2] == '1' || ver[2] == '2' || ver[2] == '3'
1498 || ver[2] == '5' || ver[2] == '8' || ver[2] == '9'))
1499 version = ver[2] - '0';
1500 else if (strlen (ver) == 5
1501 && TOUPPER (ver[3]) == 'L'
1502 && TOUPPER (ver[4]) == 'P'
1503 && (ver[2] == '5' || ver[2] == '6'))
1504 version = ver[2] - '0' + 10;
1507 return version;
1510 static void
1511 set_cpu (enum cpu_version version)
1513 cpu = version;
1514 if (version == V545LP || version == V546LP)
1516 symbolS *symbolP = symbol_new ("__allow_lp", absolute_section,
1517 &zero_address_frag, 1);
1518 SF_SET_LOCAL (symbolP);
1519 symbol_table_insert (symbolP);
1523 /* .version cpu-version
1524 cpu-version may be one of the following:
1529 545LP
1530 546LP
1534 This is for compatibility only. It currently has no affect on assembly. */
1535 static int cpu_needs_set = 1;
1537 static void
1538 tic54x_version (int x ATTRIBUTE_UNUSED)
1540 enum cpu_version version = VNONE;
1541 enum cpu_version old_version = cpu;
1542 int c;
1543 char *ver;
1545 ILLEGAL_WITHIN_STRUCT ();
1547 SKIP_WHITESPACE ();
1548 ver = input_line_pointer;
1549 while (!is_end_of_line[(unsigned char) *input_line_pointer])
1550 ++input_line_pointer;
1551 c = *input_line_pointer;
1552 *input_line_pointer = 0;
1554 version = lookup_version (ver);
1556 if (cpu != VNONE && cpu != version)
1557 as_warn (_("CPU version has already been set"));
1559 if (version == VNONE)
1561 as_bad (_("Unrecognized version '%s'"), ver);
1562 ignore_rest_of_line ();
1563 return;
1565 else if (assembly_begun && version != old_version)
1567 as_bad (_("Changing of CPU version on the fly not supported"));
1568 ignore_rest_of_line ();
1569 return;
1572 set_cpu (version);
1574 *input_line_pointer = c;
1575 demand_empty_rest_of_line ();
1578 /* 'f' = float, 'x' = xfloat, 'd' = double, 'l' = ldouble. */
1580 static void
1581 tic54x_float_cons (int type)
1583 if (current_stag != 0)
1584 tic54x_struct_field ('f');
1586 #ifdef md_flush_pending_output
1587 md_flush_pending_output ();
1588 #endif
1590 /* Align to long word boundary (4 octets) unless it's ".xfloat". */
1591 if (type != 'x')
1593 frag_align (2, 0, 2);
1594 /* If there's a label, assign it to the first allocated word. */
1595 if (line_label != NULL)
1597 symbol_set_frag (line_label, frag_now);
1598 S_SET_VALUE (line_label, frag_now_fix ());
1602 float_cons ('f');
1605 /* The argument is capitalized if it should be zero-terminated
1606 's' is normal string with upper 8-bits zero-filled, 'p' is packed.
1607 Code copied from stringer, and slightly modified so that strings are packed
1608 and encoded into the correct octets. */
1610 static void
1611 tic54x_stringer (int type)
1613 unsigned int c;
1614 int append_zero = type == 'S' || type == 'P';
1615 int packed = type == 'p' || type == 'P';
1616 int last_char = -1; /* Packed strings need two bytes at a time to encode. */
1618 if (current_stag != NULL)
1620 tic54x_struct_field ('*');
1621 return;
1624 #ifdef md_flush_pending_output
1625 md_flush_pending_output ();
1626 #endif
1628 c = ','; /* Do loop. */
1629 while (c == ',')
1631 SKIP_WHITESPACE ();
1632 switch (*input_line_pointer)
1634 default:
1636 unsigned short value = get_absolute_expression ();
1637 FRAG_APPEND_1_CHAR ( value & 0xFF);
1638 FRAG_APPEND_1_CHAR ((value >> 8) & 0xFF);
1639 break;
1641 case '\"':
1642 ++input_line_pointer; /* -> 1st char of string. */
1643 while (is_a_char (c = next_char_of_string ()))
1645 if (!packed)
1647 FRAG_APPEND_1_CHAR (c);
1648 FRAG_APPEND_1_CHAR (0);
1650 else
1652 /* Packed strings are filled MS octet first. */
1653 if (last_char == -1)
1654 last_char = c;
1655 else
1657 FRAG_APPEND_1_CHAR (c);
1658 FRAG_APPEND_1_CHAR (last_char);
1659 last_char = -1;
1663 if (append_zero)
1665 if (packed && last_char != -1)
1667 FRAG_APPEND_1_CHAR (0);
1668 FRAG_APPEND_1_CHAR (last_char);
1669 last_char = -1;
1671 else
1673 FRAG_APPEND_1_CHAR (0);
1674 FRAG_APPEND_1_CHAR (0);
1677 know (input_line_pointer[-1] == '\"');
1678 break;
1680 SKIP_WHITESPACE ();
1681 c = *input_line_pointer;
1682 if (!is_end_of_line[c])
1683 ++input_line_pointer;
1686 /* Finish up any leftover packed string. */
1687 if (packed && last_char != -1)
1689 FRAG_APPEND_1_CHAR (0);
1690 FRAG_APPEND_1_CHAR (last_char);
1692 demand_empty_rest_of_line ();
1695 static void
1696 tic54x_p2align (int arg ATTRIBUTE_UNUSED)
1698 as_bad (_("p2align not supported on this target"));
1701 static void
1702 tic54x_align_words (int arg)
1704 /* Only ".align" with no argument is allowed within .struct/.union. */
1705 int count = arg;
1707 if (!is_end_of_line[(unsigned char) *input_line_pointer])
1709 if (arg == 2)
1710 as_warn (_("Argument to .even ignored"));
1711 else
1712 count = get_absolute_expression ();
1715 if (current_stag != NULL && arg == 128)
1717 if (current_stag->current_bitfield_offset != 0)
1719 current_stag->current_bitfield_offset = 0;
1720 ++abs_section_offset;
1722 demand_empty_rest_of_line ();
1723 return;
1726 ILLEGAL_WITHIN_STRUCT ();
1728 s_align_bytes (count << 1);
1731 /* Initialize multiple-bit fields within a single word of memory. */
1733 static void
1734 tic54x_field (int ignore ATTRIBUTE_UNUSED)
1736 expressionS expn;
1737 int size = 16;
1738 char *p;
1739 valueT value;
1740 symbolS *label = line_label;
1742 if (current_stag != NULL)
1744 tic54x_struct_field ('.');
1745 return;
1748 input_line_pointer = parse_expression (input_line_pointer, &expn);
1750 if (*input_line_pointer == ',')
1752 ++input_line_pointer;
1753 size = get_absolute_expression ();
1754 if (size < 1 || size > 32)
1756 as_bad (_("Invalid field size, must be from 1 to 32"));
1757 ignore_rest_of_line ();
1758 return;
1762 /* Truncate values to the field width. */
1763 if (expn.X_op != O_constant)
1765 /* If the expression value is relocatable, the field size *must*
1766 be 16. */
1767 if (size != 16)
1769 as_bad (_("field size must be 16 when value is relocatable"));
1770 ignore_rest_of_line ();
1771 return;
1774 frag_now->tc_frag_data = 0;
1775 emit_expr (&expn, 2);
1777 else
1779 unsigned long fmask = (size == 32) ? 0xFFFFFFFF : (1ul << size) - 1;
1781 value = expn.X_add_number;
1782 expn.X_add_number &= fmask;
1783 if (value != (valueT) expn.X_add_number)
1784 as_warn (_("field value truncated"));
1785 value = expn.X_add_number;
1786 /* Bits are stored MS first. */
1787 while (size >= 16)
1789 frag_now->tc_frag_data = 0;
1790 p = frag_more (2);
1791 md_number_to_chars (p, (value >> (size - 16)) & 0xFFFF, 2);
1792 size -= 16;
1794 if (size > 0)
1796 int bit_offset = frag_bit_offset (frag_now, now_seg);
1798 fragS *alloc_frag = bit_offset_frag (frag_now, now_seg);
1799 if (bit_offset == -1)
1801 struct bit_info *bi = XNEW (struct bit_info);
1802 /* We don't know the previous offset at this time, so store the
1803 info we need and figure it out later. */
1804 expressionS size_exp;
1806 size_exp.X_op = O_constant;
1807 size_exp.X_add_number = size;
1808 bi->seg = now_seg;
1809 bi->type = TYPE_FIELD;
1810 bi->value = value;
1811 p = frag_var (rs_machine_dependent,
1812 4, 1, (relax_substateT) 0,
1813 make_expr_symbol (&size_exp), (offsetT) 0,
1814 (char *) bi);
1815 goto getout;
1817 else if (bit_offset == 0 || bit_offset + size > 16)
1819 /* Align a new field. */
1820 p = frag_more (2);
1821 frag_now->tc_frag_data = 0;
1822 alloc_frag = frag_now;
1824 else
1826 /* Put the new value entirely within the existing one. */
1827 p = alloc_frag == frag_now ?
1828 frag_now->fr_literal + frag_now_fix_octets () - 2 :
1829 alloc_frag->fr_literal;
1830 if (label != NULL)
1832 symbol_set_frag (label, alloc_frag);
1833 if (alloc_frag == frag_now)
1834 S_SET_VALUE (label, frag_now_fix () - 1);
1835 label = NULL;
1838 value <<= 16 - alloc_frag->tc_frag_data - size;
1840 /* OR in existing value. */
1841 if (alloc_frag->tc_frag_data)
1842 value |= ((unsigned short) p[1] << 8) | p[0];
1843 md_number_to_chars (p, value, 2);
1844 alloc_frag->tc_frag_data += size;
1845 if (alloc_frag->tc_frag_data == 16)
1846 alloc_frag->tc_frag_data = 0;
1849 getout:
1850 demand_empty_rest_of_line ();
1853 /* Ideally, we want to check SEC_LOAD and SEC_HAS_CONTENTS, but those aren't
1854 available yet. seg_info ()->bss is the next best thing. */
1856 static int
1857 tic54x_initialized_section (segT seg)
1859 return !seg_info (seg)->bss;
1862 /* .clink ["section name"]
1864 Marks the section as conditionally linked (link only if contents are
1865 referenced elsewhere.
1866 Without a name, refers to the current initialized section.
1867 Name is required for uninitialized sections. */
1869 static void
1870 tic54x_clink (int ignored ATTRIBUTE_UNUSED)
1872 segT seg = now_seg;
1874 ILLEGAL_WITHIN_STRUCT ();
1876 if (*input_line_pointer == '\"')
1878 char *section_name = ++input_line_pointer;
1879 char *name;
1881 while (is_a_char (next_char_of_string ()))
1883 know (input_line_pointer[-1] == '\"');
1884 input_line_pointer[-1] = 0;
1885 name = xstrdup (section_name);
1887 seg = bfd_get_section_by_name (stdoutput, name);
1888 if (seg == NULL)
1890 as_bad (_("Unrecognized section '%s'"), section_name);
1891 ignore_rest_of_line ();
1892 return;
1895 else
1897 if (!tic54x_initialized_section (seg))
1899 as_bad (_("Current section is uninitialized, "
1900 "section name required for .clink"));
1901 ignore_rest_of_line ();
1902 return;
1906 seg->flags |= SEC_TIC54X_CLINK;
1908 demand_empty_rest_of_line ();
1911 /* Change the default include directory to be the current source file's
1912 directory. */
1914 static void
1915 tic54x_set_default_include (void)
1917 unsigned lineno;
1918 const char *curfile = as_where (&lineno);
1919 const char *tmp = strrchr (curfile, '/');
1920 if (tmp != NULL)
1922 size_t len = tmp - curfile;
1923 if (len > include_dir_maxlen)
1924 include_dir_maxlen = len;
1925 include_dirs[0] = notes_memdup (curfile, len, len + 1);
1927 else
1928 include_dirs[0] = ".";
1931 /* .include "filename" | filename
1932 .copy "filename" | filename
1934 FIXME 'include' file should be omitted from any output listing,
1935 'copy' should be included in any output listing
1936 FIXME -- prevent any included files from changing listing (compat only)
1937 FIXME -- need to include source file directory in search path; what's a
1938 good way to do this?
1940 Entering/exiting included/copied file clears all local labels. */
1942 static void
1943 tic54x_include (int ignored ATTRIBUTE_UNUSED)
1945 char newblock[] = " .newblock\n";
1946 char *filename;
1947 char *input;
1948 int len, c = -1;
1950 ILLEGAL_WITHIN_STRUCT ();
1952 SKIP_WHITESPACE ();
1954 if (*input_line_pointer == '"')
1956 filename = demand_copy_C_string (&len);
1957 demand_empty_rest_of_line ();
1959 else
1961 filename = input_line_pointer;
1962 while (!is_end_of_line[(unsigned char) *input_line_pointer])
1963 ++input_line_pointer;
1964 c = *input_line_pointer;
1965 *input_line_pointer = '\0';
1966 filename = xstrdup (filename);
1967 *input_line_pointer = c;
1968 demand_empty_rest_of_line ();
1970 /* Insert a partial line with the filename (for the sake of s_include)
1971 and a .newblock.
1972 The included file will be inserted before the newblock, so that the
1973 newblock is executed after the included file is processed. */
1974 input = concat ("\"", filename, "\"\n", newblock, (char *) NULL);
1975 input_scrub_insert_line (input);
1977 tic54x_clear_local_labels (0);
1979 tic54x_set_default_include ();
1981 s_include (0);
1984 static void
1985 tic54x_message (int type)
1987 char *msg;
1988 char c;
1989 int len;
1991 ILLEGAL_WITHIN_STRUCT ();
1993 if (*input_line_pointer == '"')
1994 msg = demand_copy_C_string (&len);
1995 else
1997 msg = input_line_pointer;
1998 while (!is_end_of_line[(unsigned char) *input_line_pointer])
1999 ++input_line_pointer;
2000 c = *input_line_pointer;
2001 *input_line_pointer = 0;
2002 msg = xstrdup (msg);
2003 *input_line_pointer = c;
2006 switch (type)
2008 case 'm':
2009 as_tsktsk ("%s", msg);
2010 break;
2011 case 'w':
2012 as_warn ("%s", msg);
2013 break;
2014 case 'e':
2015 as_bad ("%s", msg);
2016 break;
2019 demand_empty_rest_of_line ();
2022 /* .label <symbol>
2023 Define a special symbol that refers to the loadtime address rather than the
2024 runtime address within the current section.
2026 This symbol gets a special storage class so that when it is resolved, it is
2027 resolved relative to the load address (lma) of the section rather than the
2028 run address (vma). */
2030 static void
2031 tic54x_label (int ignored ATTRIBUTE_UNUSED)
2033 char *name;
2034 symbolS *symbolP;
2035 int c;
2037 ILLEGAL_WITHIN_STRUCT ();
2039 c = get_symbol_name (&name);
2040 symbolP = colon (name);
2041 S_SET_STORAGE_CLASS (symbolP, C_STATLAB);
2043 (void) restore_line_pointer (c);
2044 demand_empty_rest_of_line ();
2047 /* .mmregs
2048 Install all memory-mapped register names into the symbol table as
2049 absolute local symbols. */
2051 static void
2052 tic54x_register_mmregs (int ignored ATTRIBUTE_UNUSED)
2054 const tic54x_symbol *sym;
2056 ILLEGAL_WITHIN_STRUCT ();
2058 for (sym = tic54x_mmregs; sym->name; sym++)
2060 symbolS *symbolP = symbol_new (sym->name, absolute_section,
2061 &zero_address_frag, sym->value);
2062 SF_SET_LOCAL (symbolP);
2063 symbol_table_insert (symbolP);
2067 /* .loop [count]
2068 Count defaults to 1024. */
2070 static void
2071 tic54x_loop (int count)
2073 ILLEGAL_WITHIN_STRUCT ();
2075 SKIP_WHITESPACE ();
2076 if (!is_end_of_line[(unsigned char) *input_line_pointer])
2077 count = get_absolute_expression ();
2079 do_repeat ((size_t) count, "LOOP", "ENDLOOP", NULL);
2082 /* Normally, endloop gets eaten by the preceding loop. */
2084 static void
2085 tic54x_endloop (int ignore ATTRIBUTE_UNUSED)
2087 as_bad (_("ENDLOOP without corresponding LOOP"));
2088 ignore_rest_of_line ();
2091 /* .break [condition]. */
2093 static void
2094 tic54x_break (int ignore ATTRIBUTE_UNUSED)
2096 int cond = 1;
2098 ILLEGAL_WITHIN_STRUCT ();
2100 SKIP_WHITESPACE ();
2101 if (!is_end_of_line[(unsigned char) *input_line_pointer])
2102 cond = get_absolute_expression ();
2104 if (cond)
2105 end_repeat (substitution_line ? 1 : 0);
2108 static void
2109 set_address_mode (int mode)
2111 amode = mode;
2112 if (mode == far_mode)
2114 symbolS *symbolP = symbol_new ("__allow_far", absolute_section,
2115 &zero_address_frag, 1);
2116 SF_SET_LOCAL (symbolP);
2117 symbol_table_insert (symbolP);
2121 static int address_mode_needs_set = 1;
2123 static void
2124 tic54x_address_mode (int mode)
2126 if (assembly_begun && amode != (unsigned) mode)
2128 as_bad (_("Mixing of normal and extended addressing not supported"));
2129 ignore_rest_of_line ();
2130 return;
2132 if (mode == far_mode && cpu != VNONE && cpu != V548 && cpu != V549)
2134 as_bad (_("Extended addressing not supported on the specified CPU"));
2135 ignore_rest_of_line ();
2136 return;
2139 set_address_mode (mode);
2140 demand_empty_rest_of_line ();
2143 /* .sblock "section"|section [,...,"section"|section]
2144 Designate initialized sections for blocking. */
2146 static void
2147 tic54x_sblock (int ignore ATTRIBUTE_UNUSED)
2149 int c = ',';
2151 ILLEGAL_WITHIN_STRUCT ();
2153 while (c == ',')
2155 segT seg;
2156 char *name;
2158 if (*input_line_pointer == '"')
2160 int len;
2162 name = demand_copy_C_string (&len);
2164 else
2166 char *section_name;
2168 c = get_symbol_name (&section_name);
2169 name = xstrdup (section_name);
2170 (void) restore_line_pointer (c);
2173 seg = bfd_get_section_by_name (stdoutput, name);
2174 if (seg == NULL)
2176 as_bad (_("Unrecognized section '%s'"), name);
2177 ignore_rest_of_line ();
2178 return;
2180 else if (!tic54x_initialized_section (seg))
2182 as_bad (_(".sblock may be used for initialized sections only"));
2183 ignore_rest_of_line ();
2184 return;
2186 seg->flags |= SEC_TIC54X_BLOCK;
2188 c = *input_line_pointer;
2189 if (!is_end_of_line[(unsigned char) c])
2190 ++input_line_pointer;
2193 demand_empty_rest_of_line ();
2196 /* symbol .set value
2197 symbol .equ value
2199 value must be defined externals; no forward-referencing allowed
2200 symbols assigned with .set/.equ may not be redefined. */
2202 static void
2203 tic54x_set (int ignore ATTRIBUTE_UNUSED)
2205 symbolS *symbolP;
2206 char *name;
2208 ILLEGAL_WITHIN_STRUCT ();
2210 if (!line_label)
2212 as_bad (_("Symbol missing for .set/.equ"));
2213 ignore_rest_of_line ();
2214 return;
2216 name = xstrdup (S_GET_NAME (line_label));
2217 line_label = NULL;
2218 if ((symbolP = symbol_find (name)) == NULL
2219 && (symbolP = md_undefined_symbol (name)) == NULL)
2221 symbolP = symbol_new (name, absolute_section, &zero_address_frag, 0);
2222 S_SET_STORAGE_CLASS (symbolP, C_STAT);
2224 free (name);
2225 S_SET_DATA_TYPE (symbolP, T_INT);
2226 S_SET_SEGMENT (symbolP, absolute_section);
2227 symbol_table_insert (symbolP);
2228 pseudo_set (symbolP);
2229 demand_empty_rest_of_line ();
2232 /* .fclist
2233 .fcnolist
2234 List false conditional blocks. */
2236 static void
2237 tic54x_fclist (int show)
2239 if (show)
2240 listing &= ~LISTING_NOCOND;
2241 else
2242 listing |= LISTING_NOCOND;
2243 demand_empty_rest_of_line ();
2246 static void
2247 tic54x_sslist (int show)
2249 ILLEGAL_WITHIN_STRUCT ();
2251 listing_sslist = show;
2254 /* .var SYM[,...,SYMN]
2255 Define a substitution string to be local to a macro. */
2257 static void
2258 tic54x_var (int ignore ATTRIBUTE_UNUSED)
2260 char *name;
2261 int c;
2263 ILLEGAL_WITHIN_STRUCT ();
2265 if (macro_level == 0)
2267 as_bad (_(".var may only be used within a macro definition"));
2268 ignore_rest_of_line ();
2269 return;
2273 if (!ISALPHA (*input_line_pointer))
2275 as_bad (_("Substitution symbols must begin with a letter"));
2276 ignore_rest_of_line ();
2277 return;
2279 c = get_symbol_name (&name);
2280 name = xstrdup (name);
2281 c = restore_line_pointer (c);
2283 /* .var symbols start out with a null string. */
2284 subsym_ent_t *ent = xmalloc (sizeof (*ent));
2285 ent->u.s = (char *) "";
2286 ent->freekey = 1;
2287 ent->freeval = 0;
2288 ent->isproc = 0;
2289 ent->ismath = 0;
2290 str_hash_insert (subsym_hash[macro_level], name, ent, 0);
2291 if (c == ',')
2293 ++input_line_pointer;
2294 if (is_end_of_line[(unsigned char) *input_line_pointer])
2295 c = *input_line_pointer;
2298 while (c == ',');
2300 demand_empty_rest_of_line ();
2303 /* .mlib <macro library filename>
2305 Macro libraries are archived (standard AR-format) text macro definitions
2306 Expand the file and include it.
2308 FIXME need to try the source file directory as well. */
2310 static void
2311 tic54x_mlib (int ignore ATTRIBUTE_UNUSED)
2313 char *filename;
2314 char *path;
2315 int len;
2316 bfd *abfd, *mbfd;
2318 ILLEGAL_WITHIN_STRUCT ();
2320 /* Parse the filename. */
2321 if (*input_line_pointer == '"')
2323 if ((filename = demand_copy_C_string (&len)) == NULL)
2324 return;
2326 else
2328 SKIP_WHITESPACE ();
2329 len = 0;
2330 while (!is_end_of_line[(unsigned char) *input_line_pointer]
2331 && !ISSPACE (*input_line_pointer))
2333 obstack_1grow (&notes, *input_line_pointer);
2334 ++input_line_pointer;
2335 ++len;
2337 obstack_1grow (&notes, '\0');
2338 filename = obstack_finish (&notes);
2340 demand_empty_rest_of_line ();
2342 tic54x_set_default_include ();
2343 path = notes_alloc (len + include_dir_maxlen + 2);
2344 FILE *try = search_and_open (filename, path);
2345 if (try)
2346 fclose (try);
2348 register_dependency (path);
2350 /* Expand all archive entries to temporary files and include them. */
2351 abfd = bfd_openr (path, NULL);
2352 if (!abfd)
2354 as_bad (_("can't open macro library file '%s' for reading: %s"),
2355 path, bfd_errmsg (bfd_get_error ()));
2356 ignore_rest_of_line ();
2357 return;
2359 if (!bfd_check_format (abfd, bfd_archive))
2361 as_bad (_("File '%s' not in macro archive format"), path);
2362 ignore_rest_of_line ();
2363 return;
2366 /* Open each BFD as binary (it should be straight ASCII text). */
2367 for (mbfd = bfd_openr_next_archived_file (abfd, NULL);
2368 mbfd != NULL; mbfd = bfd_openr_next_archived_file (abfd, mbfd))
2370 /* Get a size at least as big as the archive member. */
2371 bfd_size_type size = bfd_get_size (mbfd);
2372 char *buf = XNEWVEC (char, size);
2373 char *fname = tmpnam (NULL);
2374 FILE *ftmp;
2376 /* We're not sure how big it is, but it will be smaller than "size". */
2377 size = bfd_read (buf, size, mbfd);
2379 /* Write to a temporary file, then use s_include to include it
2380 a bit of a hack. */
2381 ftmp = fopen (fname, "w+b");
2382 fwrite ((void *) buf, size, 1, ftmp);
2383 if (size == 0 || buf[size - 1] != '\n')
2384 fwrite ("\n", 1, 1, ftmp);
2385 fclose (ftmp);
2386 free (buf);
2387 input_scrub_insert_file (fname);
2388 remove (fname);
2392 const pseudo_typeS md_pseudo_table[] =
2394 { "algebraic", s_ignore , 0 },
2395 { "align" , tic54x_align_words , 128 },
2396 { "ascii" , tic54x_stringer , 'p' },
2397 { "asciz" , tic54x_stringer , 'P' },
2398 { "even" , tic54x_align_words , 2 },
2399 { "asg" , tic54x_asg , 0 },
2400 { "eval" , tic54x_eval , 0 },
2401 { "bss" , tic54x_bss , 0 },
2402 { "byte" , tic54x_cons , 'b' },
2403 { "ubyte" , tic54x_cons , 'B' },
2404 { "char" , tic54x_cons , 'c' },
2405 { "uchar" , tic54x_cons , 'C' },
2406 { "clink" , tic54x_clink , 0 },
2407 { "c_mode" , tic54x_address_mode , c_mode },
2408 { "copy" , tic54x_include , 'c' },
2409 { "include" , tic54x_include , 'i' },
2410 { "data" , tic54x_sect , 'd' },
2411 { "double" , tic54x_float_cons , 'd' },
2412 { "ldouble" , tic54x_float_cons , 'l' },
2413 { "drlist" , s_ignore , 0 },
2414 { "drnolist" , s_ignore , 0 },
2415 { "emsg" , tic54x_message , 'e' },
2416 { "mmsg" , tic54x_message , 'm' },
2417 { "wmsg" , tic54x_message , 'w' },
2418 { "far_mode" , tic54x_address_mode , far_mode },
2419 { "fclist" , tic54x_fclist , 1 },
2420 { "fcnolist" , tic54x_fclist , 0 },
2421 { "field" , tic54x_field , -1 },
2422 { "float" , tic54x_float_cons , 'f' },
2423 { "xfloat" , tic54x_float_cons , 'x' },
2424 { "global" , tic54x_global , 'g' },
2425 { "def" , tic54x_global , 'd' },
2426 { "ref" , tic54x_global , 'r' },
2427 { "half" , tic54x_cons , 'h' },
2428 { "uhalf" , tic54x_cons , 'H' },
2429 { "short" , tic54x_cons , 's' },
2430 { "ushort" , tic54x_cons , 'S' },
2431 { "if" , s_if , (int) O_ne },
2432 { "elseif" , s_elseif , (int) O_ne },
2433 { "else" , s_else , 0 },
2434 { "endif" , s_endif , 0 },
2435 { "int" , tic54x_cons , 'i' },
2436 { "uint" , tic54x_cons , 'I' },
2437 { "word" , tic54x_cons , 'w' },
2438 { "uword" , tic54x_cons , 'W' },
2439 { "label" , tic54x_label , 0 }, /* Loadtime
2440 address. */
2441 { "length" , s_ignore , 0 },
2442 { "width" , s_ignore , 0 },
2443 { "long" , tic54x_cons , 'l' },
2444 { "ulong" , tic54x_cons , 'L' },
2445 { "xlong" , tic54x_cons , 'x' },
2446 { "loop" , tic54x_loop , 1024 },
2447 { "break" , tic54x_break , 0 },
2448 { "endloop" , tic54x_endloop , 0 },
2449 { "mlib" , tic54x_mlib , 0 },
2450 { "mlist" , s_ignore , 0 },
2451 { "mnolist" , s_ignore , 0 },
2452 { "mmregs" , tic54x_register_mmregs , 0 },
2453 { "newblock" , tic54x_clear_local_labels, 0 },
2454 { "option" , s_ignore , 0 },
2455 { "p2align" , tic54x_p2align , 0 },
2456 { "sblock" , tic54x_sblock , 0 },
2457 { "sect" , tic54x_sect , '*' },
2458 { "set" , tic54x_set , 0 },
2459 { "equ" , tic54x_set , 0 },
2460 { "space" , tic54x_space , 0 },
2461 { "bes" , tic54x_space , 1 },
2462 { "sslist" , tic54x_sslist , 1 },
2463 { "ssnolist" , tic54x_sslist , 0 },
2464 { "string" , tic54x_stringer , 's' },
2465 { "pstring" , tic54x_stringer , 'p' },
2466 { "struct" , tic54x_struct , 0 },
2467 { "tag" , tic54x_tag , 0 },
2468 { "endstruct", tic54x_endstruct , 0 },
2469 { "tab" , s_ignore , 0 },
2470 { "text" , tic54x_sect , 't' },
2471 { "union" , tic54x_struct , 1 },
2472 { "endunion" , tic54x_endstruct , 1 },
2473 { "usect" , tic54x_usect , 0 },
2474 { "var" , tic54x_var , 0 },
2475 { "version" , tic54x_version , 0 },
2476 {0 , 0 , 0 }
2480 md_parse_option (int c, const char *arg)
2482 switch (c)
2484 default:
2485 return 0;
2486 case OPTION_COFF_VERSION:
2488 int version = atoi (arg);
2490 if (version != 0 && version != 1 && version != 2)
2491 as_fatal (_("Bad COFF version '%s'"), arg);
2492 /* FIXME -- not yet implemented. */
2493 break;
2495 case OPTION_CPU_VERSION:
2497 cpu = lookup_version (arg);
2498 cpu_needs_set = 1;
2499 if (cpu == VNONE)
2500 as_fatal (_("Bad CPU version '%s'"), arg);
2501 break;
2503 case OPTION_ADDRESS_MODE:
2504 amode = far_mode;
2505 address_mode_needs_set = 1;
2506 break;
2507 case OPTION_STDERR_TO_FILE:
2509 const char *filename = arg;
2510 FILE *fp = fopen (filename, "w+");
2512 if (fp == NULL)
2513 as_fatal (_("Can't redirect stderr to the file '%s'"), filename);
2514 fclose (fp);
2515 if ((fp = freopen (filename, "w+", stderr)) == NULL)
2516 as_fatal (_("Can't redirect stderr to the file '%s'"), filename);
2517 break;
2521 return 1;
2524 /* Create a "local" substitution string hash table for a new macro level
2525 Some docs imply that macros have to use .newblock in order to be able
2526 to re-use a local label. We effectively do an automatic .newblock by
2527 deleting the local label hash between macro invocations. */
2529 void
2530 tic54x_macro_start (void)
2532 if (++macro_level >= MAX_SUBSYM_HASH)
2534 --macro_level;
2535 as_fatal (_("Macro nesting is too deep"));
2536 return;
2538 subsym_hash[macro_level] = subsym_htab_create ();
2539 local_label_hash[macro_level] = local_label_htab_create ();
2542 void
2543 tic54x_macro_info (const macro_entry *macro)
2545 const formal_entry *entry;
2547 /* Put the formal args into the substitution symbol table. */
2548 for (entry = macro->formals; entry; entry = entry->next)
2550 char *name = xstrndup (entry->name.ptr, entry->name.len);
2551 subsym_ent_t *ent = xmalloc (sizeof (*ent));
2553 ent->u.s = xstrndup (entry->actual.ptr, entry->actual.len);
2554 ent->freekey = 1;
2555 ent->freeval = 1;
2556 ent->isproc = 0;
2557 ent->ismath = 0;
2558 str_hash_insert (subsym_hash[macro_level], name, ent, 0);
2562 /* Get rid of this macro's .var's, arguments, and local labels. */
2564 void
2565 tic54x_macro_end (void)
2567 htab_delete (subsym_hash[macro_level]);
2568 subsym_hash[macro_level] = NULL;
2569 htab_delete (local_label_hash[macro_level]);
2570 local_label_hash[macro_level] = NULL;
2571 --macro_level;
2574 static int
2575 subsym_symlen (char *a, char *ignore ATTRIBUTE_UNUSED)
2577 return strlen (a);
2580 /* Compare symbol A to string B. */
2582 static int
2583 subsym_symcmp (char *a, char *b)
2585 return strcmp (a, b);
2588 /* Return the index of the first occurrence of B in A, or zero if none
2589 assumes b is an integer char value as a string. Index is one-based. */
2591 static int
2592 subsym_firstch (char *a, char *b)
2594 int val = atoi (b);
2595 char *tmp = strchr (a, val);
2597 return tmp ? tmp - a + 1 : 0;
2600 /* Similar to firstch, but returns index of last occurrence of B in A. */
2602 static int
2603 subsym_lastch (char *a, char *b)
2605 int val = atoi (b);
2606 char *tmp = strrchr (a, val);
2608 return tmp ? tmp - a + 1 : 0;
2611 /* Returns 1 if string A is defined in the symbol table (NOT the substitution
2612 symbol table). */
2614 static int
2615 subsym_isdefed (char *a, char *ignore ATTRIBUTE_UNUSED)
2617 symbolS *symbolP = symbol_find (a);
2619 return symbolP != NULL;
2622 /* Assign first member of comma-separated list B (e.g. "1,2,3") to the symbol
2623 A, or zero if B is a null string. Both arguments *must* be substitution
2624 symbols, unsubstituted. */
2626 static int
2627 subsym_ismember (char *sym, char *list)
2629 char *elem, *ptr;
2630 subsym_ent_t *listv;
2632 if (!list)
2633 return 0;
2635 listv = subsym_lookup (list, macro_level);
2636 if (!listv || listv->isproc)
2638 as_bad (_("Undefined substitution symbol '%s'"), list);
2639 ignore_rest_of_line ();
2640 return 0;
2643 ptr = elem = notes_strdup (listv->u.s);
2644 while (*ptr && *ptr != ',')
2645 ++ptr;
2646 *ptr++ = 0;
2648 subsym_create_or_replace (sym, elem);
2650 /* Reassign the list. */
2651 subsym_create_or_replace (list, ptr);
2653 /* Assume this value, docs aren't clear. */
2654 return *list != 0;
2657 /* Return zero if not a constant; otherwise:
2658 1 if binary
2659 2 if octal
2660 3 if hexadecimal
2661 4 if character
2662 5 if decimal. */
2664 static int
2665 subsym_iscons (char *a, char *ignore ATTRIBUTE_UNUSED)
2667 expressionS expn;
2669 parse_expression (a, &expn);
2671 if (expn.X_op == O_constant)
2673 int len = strlen (a);
2675 switch (TOUPPER (a[len - 1]))
2677 case 'B':
2678 return 1;
2679 case 'Q':
2680 return 2;
2681 case 'H':
2682 return 3;
2683 case '\'':
2684 return 4;
2685 default:
2686 break;
2688 /* No suffix; either octal, hex, or decimal. */
2689 if (*a == '0' && len > 1)
2691 if (TOUPPER (a[1]) == 'X')
2692 return 3;
2693 return 2;
2695 return 5;
2698 return 0;
2701 /* Return 1 if A is a valid symbol name. Expects string input. */
2703 static int
2704 subsym_isname (char *a, char *ignore ATTRIBUTE_UNUSED)
2706 if (!is_name_beginner (*a))
2707 return 0;
2708 while (*a)
2710 if (!is_part_of_name (*a))
2711 return 0;
2712 ++a;
2714 return 1;
2717 /* Return whether the string is a register; accepts ar0-7, unless .mmregs has
2718 been seen; if so, recognize any memory-mapped register.
2719 Note this does not recognize "A" or "B" accumulators. */
2721 static int
2722 subsym_isreg (char *a, char *ignore ATTRIBUTE_UNUSED)
2724 if (str_hash_find (reg_hash, a))
2725 return 1;
2726 if (str_hash_find (mmreg_hash, a))
2727 return 1;
2728 return 0;
2731 /* Return the structure size, given the stag. */
2733 static int
2734 subsym_structsz (char *name, char *ignore ATTRIBUTE_UNUSED)
2736 struct stag *stag = (struct stag *) str_hash_find (stag_hash, name);
2738 if (stag)
2739 return stag->size;
2741 return 0;
2744 /* If anybody actually uses this, they can fix it :)
2745 FIXME I'm not sure what the "reference point" of a structure is. It might
2746 be either the initial offset given .struct, or it may be the offset of the
2747 structure within another structure, or it might be something else
2748 altogether. since the TI assembler doesn't seem to ever do anything but
2749 return zero, we punt and return zero. */
2751 static int
2752 subsym_structacc (char *stag_name ATTRIBUTE_UNUSED,
2753 char *ignore ATTRIBUTE_UNUSED)
2755 return 0;
2758 static float
2759 math_ceil (float arg1, float ignore ATTRIBUTE_UNUSED)
2761 return (float) ceil (arg1);
2764 static int
2765 math_cvi (float arg1, float ignore ATTRIBUTE_UNUSED)
2767 return (int) arg1;
2770 static float
2771 math_floor (float arg1, float ignore ATTRIBUTE_UNUSED)
2773 return (float) floor (arg1);
2776 static float
2777 math_fmod (float arg1, float arg2)
2779 return (int) arg1 % (int) arg2;
2782 static int
2783 math_int (float arg1, float ignore ATTRIBUTE_UNUSED)
2785 return arg1 == (float) (int) arg1;
2788 static float
2789 math_round (float arg1, float ignore ATTRIBUTE_UNUSED)
2791 return arg1 > 0 ? (int) (arg1 + 0.5) : (int) (arg1 - 0.5);
2794 static int
2795 math_sgn (float arg1, float ignore ATTRIBUTE_UNUSED)
2797 return arg1 < 0.0f ? -1 : arg1 != 0.0f ? 1 : 0;
2800 static float
2801 math_trunc (float arg1, float ignore ATTRIBUTE_UNUSED)
2803 return (int) arg1;
2806 static float
2807 math_acos (float arg1, float ignore ATTRIBUTE_UNUSED)
2809 return (float) acos (arg1);
2812 static float
2813 math_asin (float arg1, float ignore ATTRIBUTE_UNUSED)
2815 return (float) asin (arg1);
2818 static float
2819 math_atan (float arg1, float ignore ATTRIBUTE_UNUSED)
2821 return (float) atan (arg1);
2824 static float
2825 math_atan2 (float arg1, float arg2)
2827 return (float) atan2 (arg1, arg2);
2830 static float
2831 math_cosh (float arg1, float ignore ATTRIBUTE_UNUSED)
2833 return (float) cosh (arg1);
2836 static float
2837 math_cos (float arg1, float ignore ATTRIBUTE_UNUSED)
2839 return (float) cos (arg1);
2842 static float
2843 math_cvf (float arg1, float ignore ATTRIBUTE_UNUSED)
2845 return (float) arg1;
2848 static float
2849 math_exp (float arg1, float ignore ATTRIBUTE_UNUSED)
2851 return (float) exp (arg1);
2854 static float
2855 math_fabs (float arg1, float ignore ATTRIBUTE_UNUSED)
2857 return (float) fabs (arg1);
2860 /* expr1 * 2^expr2. */
2862 static float
2863 math_ldexp (float arg1, float arg2)
2865 return arg1 * (float) pow (2.0, arg2);
2868 static float
2869 math_log10 (float arg1, float ignore ATTRIBUTE_UNUSED)
2871 return (float) log10 (arg1);
2874 static float
2875 math_log (float arg1, float ignore ATTRIBUTE_UNUSED)
2877 return (float) log (arg1);
2880 static float
2881 math_max (float arg1, float arg2)
2883 return (arg1 > arg2) ? arg1 : arg2;
2886 static float
2887 math_min (float arg1, float arg2)
2889 return (arg1 < arg2) ? arg1 : arg2;
2892 static float
2893 math_pow (float arg1, float arg2)
2895 return (float) pow (arg1, arg2);
2898 static float
2899 math_sin (float arg1, float ignore ATTRIBUTE_UNUSED)
2901 return (float) sin (arg1);
2904 static float
2905 math_sinh (float arg1, float ignore ATTRIBUTE_UNUSED)
2907 return (float) sinh (arg1);
2910 static float
2911 math_sqrt (float arg1, float ignore ATTRIBUTE_UNUSED)
2913 return (float) sqrt (arg1);
2916 static float
2917 math_tan (float arg1, float ignore ATTRIBUTE_UNUSED)
2919 return (float) tan (arg1);
2922 static float
2923 math_tanh (float arg1, float ignore ATTRIBUTE_UNUSED)
2925 return (float) tanh (arg1);
2928 /* Built-in substitution symbol functions and math functions. */
2929 static const subsym_proc_entry subsym_procs[] =
2931 /* Assembler built-in string substitution functions. */
2932 { "$symlen", { .s = subsym_symlen }, 1, 0 },
2933 { "$symcmp", { .s = subsym_symcmp }, 2, 0 },
2934 { "$firstch", { .s = subsym_firstch }, 2, 0 },
2935 { "$lastch", { .s = subsym_lastch }, 2, 0 },
2936 { "$isdefed", { .s = subsym_isdefed }, 1, 0 },
2937 { "$ismember", { .s = subsym_ismember }, 2, 0 },
2938 { "$iscons", { .s = subsym_iscons }, 1, 0 },
2939 { "$isname", { .s = subsym_isname }, 1, 0 },
2940 { "$isreg", { .s = subsym_isreg }, 1, 0 },
2941 { "$structsz", { .s = subsym_structsz }, 1, 0 },
2942 { "$structacc", { .s = subsym_structacc }, 1, 0 },
2944 /* Integer-returning built-in math functions. */
2945 { "$cvi", { .i = math_cvi }, 1, 2 },
2946 { "$int", { .i = math_int }, 1, 2 },
2947 { "$sgn", { .i = math_sgn }, 1, 2 },
2949 /* Float-returning built-in math functions. */
2950 { "$acos", { .f = math_acos }, 1, 1 },
2951 { "$asin", { .f = math_asin }, 1, 1 },
2952 { "$atan", { .f = math_atan }, 1, 1 },
2953 { "$atan2", { .f = math_atan2 }, 2, 1 },
2954 { "$ceil", { .f = math_ceil }, 1, 1 },
2955 { "$cosh", { .f = math_cosh }, 1, 1 },
2956 { "$cos", { .f = math_cos }, 1, 1 },
2957 { "$cvf", { .f = math_cvf }, 1, 1 },
2958 { "$exp", { .f = math_exp }, 1, 1 },
2959 { "$fabs", { .f = math_fabs }, 1, 1 },
2960 { "$floor", { .f = math_floor }, 1, 1 },
2961 { "$fmod", { .f = math_fmod }, 2, 1 },
2962 { "$ldexp", { .f = math_ldexp }, 2, 1 },
2963 { "$log10", { .f = math_log10 }, 1, 1 },
2964 { "$log", { .f = math_log }, 1, 1 },
2965 { "$max", { .f = math_max }, 2, 1 },
2966 { "$min", { .f = math_min }, 2, 1 },
2967 { "$pow", { .f = math_pow }, 2, 1 },
2968 { "$round", { .f = math_round }, 1, 1 },
2969 { "$sin", { .f = math_sin }, 1, 1 },
2970 { "$sinh", { .f = math_sinh }, 1, 1 },
2971 { "$sqrt", { .f = math_sqrt }, 1, 1 },
2972 { "$tan", { .f = math_tan }, 1, 1 },
2973 { "$tanh", { .f = math_tanh }, 1, 1 },
2974 { "$trunc", { .f = math_trunc }, 1, 1 },
2975 { NULL, { NULL }, 0, 0 },
2978 void
2979 md_begin (void)
2981 insn_template *tm;
2982 const tic54x_symbol *sym;
2983 const subsym_proc_entry *subsym_proc;
2984 const char **symname;
2985 char *TIC54X_DIR = getenv ("TIC54X_DIR");
2986 char *A_DIR = TIC54X_DIR ? TIC54X_DIR : getenv ("A_DIR");
2988 local_label_id = 0;
2990 /* Look for A_DIR and add it to the include list. */
2991 if (A_DIR != NULL)
2993 char *tmp = xstrdup (A_DIR);
2997 char *next = strchr (tmp, ';');
2999 if (next)
3000 *next++ = '\0';
3001 add_include_dir (tmp);
3002 tmp = next;
3004 while (tmp != NULL);
3007 op_hash = str_htab_create ();
3008 for (tm = (insn_template *) tic54x_optab; tm->name; tm++)
3009 str_hash_insert (op_hash, tm->name, tm, 0);
3011 parop_hash = str_htab_create ();
3012 for (tm = (insn_template *) tic54x_paroptab; tm->name; tm++)
3013 str_hash_insert (parop_hash, tm->name, tm, 0);
3015 reg_hash = str_htab_create ();
3016 for (sym = tic54x_regs; sym->name; sym++)
3018 /* Add basic registers to the symbol table. */
3019 symbolS *symbolP = symbol_new (sym->name, absolute_section,
3020 &zero_address_frag, sym->value);
3021 SF_SET_LOCAL (symbolP);
3022 symbol_table_insert (symbolP);
3023 str_hash_insert (reg_hash, sym->name, sym, 0);
3025 for (sym = tic54x_mmregs; sym->name; sym++)
3026 str_hash_insert (reg_hash, sym->name, sym, 0);
3027 mmreg_hash = str_htab_create ();
3028 for (sym = tic54x_mmregs; sym->name; sym++)
3029 str_hash_insert (mmreg_hash, sym->name, sym, 0);
3031 cc_hash = str_htab_create ();
3032 for (sym = tic54x_condition_codes; sym->name; sym++)
3033 str_hash_insert (cc_hash, sym->name, sym, 0);
3035 cc2_hash = str_htab_create ();
3036 for (sym = tic54x_cc2_codes; sym->name; sym++)
3037 str_hash_insert (cc2_hash, sym->name, sym, 0);
3039 cc3_hash = str_htab_create ();
3040 for (sym = tic54x_cc3_codes; sym->name; sym++)
3041 str_hash_insert (cc3_hash, sym->name, sym, 0);
3043 sbit_hash = str_htab_create ();
3044 for (sym = tic54x_status_bits; sym->name; sym++)
3045 str_hash_insert (sbit_hash, sym->name, sym, 0);
3047 misc_symbol_hash = str_htab_create ();
3048 for (symname = tic54x_misc_symbols; *symname; symname++)
3049 str_hash_insert (misc_symbol_hash, *symname, *symname, 0);
3051 /* Only the base substitution table and local label table are initialized;
3052 the others (for local macro substitution) get instantiated as needed. */
3053 local_label_hash[0] = local_label_htab_create ();
3054 subsym_hash[0] = subsym_htab_create ();
3055 for (subsym_proc = subsym_procs; subsym_proc->name; subsym_proc++)
3057 subsym_ent_t *ent = xmalloc (sizeof (*ent));
3058 ent->u.p = subsym_proc;
3059 ent->freekey = 0;
3060 ent->freeval = 0;
3061 ent->isproc = 1;
3062 ent->ismath = subsym_proc->type != 0;
3063 str_hash_insert (subsym_hash[0], subsym_proc->name, ent, 0);
3065 subsym_recurse_hash = str_htab_create ();
3066 stag_hash = str_htab_create ();
3069 void
3070 tic54x_md_end (void)
3072 htab_delete (stag_hash);
3073 htab_delete (subsym_recurse_hash);
3074 while (macro_level != -1)
3075 tic54x_macro_end ();
3076 macro_level = 0;
3077 htab_delete (misc_symbol_hash);
3078 htab_delete (sbit_hash);
3079 htab_delete (cc3_hash);
3080 htab_delete (cc2_hash);
3081 htab_delete (cc_hash);
3082 htab_delete (mmreg_hash);
3083 htab_delete (reg_hash);
3084 htab_delete (parop_hash);
3085 htab_delete (op_hash);
3088 static int
3089 is_accumulator (struct opstruct *operand)
3091 return strcasecmp (operand->buf, "a") == 0
3092 || strcasecmp (operand->buf, "b") == 0;
3095 /* Return the number of operands found, or -1 on error, copying the
3096 operands into the given array and the accompanying expressions into
3097 the next array. */
3099 static int
3100 get_operands (struct opstruct operands[], char *line)
3102 char *lptr = line;
3103 int numexp = 0;
3104 int expecting_operand = 0;
3105 int i;
3107 while (numexp < MAX_OPERANDS && !is_end_of_line[(unsigned char) *lptr])
3109 int paren_not_balanced = 0;
3110 char *op_start, *op_end;
3112 while (*lptr && ISSPACE (*lptr))
3113 ++lptr;
3114 op_start = lptr;
3115 while (paren_not_balanced || *lptr != ',')
3117 if (*lptr == '\0')
3119 if (paren_not_balanced)
3121 as_bad (_("Unbalanced parenthesis in operand %d"), numexp);
3122 return -1;
3124 else
3125 break;
3127 if (*lptr == '(')
3128 ++paren_not_balanced;
3129 else if (*lptr == ')')
3130 --paren_not_balanced;
3131 ++lptr;
3133 op_end = lptr;
3134 if (op_end != op_start)
3136 int len = op_end - op_start;
3138 strncpy (operands[numexp].buf, op_start, len);
3139 operands[numexp].buf[len] = 0;
3140 /* Trim trailing spaces; while the preprocessor gets rid of most,
3141 there are weird usage patterns that can introduce them
3142 (i.e. using strings for macro args). */
3143 while (len > 0 && ISSPACE (operands[numexp].buf[len - 1]))
3144 operands[numexp].buf[--len] = 0;
3145 lptr = op_end;
3146 ++numexp;
3148 else
3150 if (expecting_operand || *lptr == ',')
3152 as_bad (_("Expecting operand after ','"));
3153 return -1;
3156 if (*lptr == ',')
3158 if (*++lptr == '\0')
3160 as_bad (_("Expecting operand after ','"));
3161 return -1;
3163 expecting_operand = 1;
3167 while (*lptr && ISSPACE (*lptr++))
3169 if (!is_end_of_line[(unsigned char) *lptr])
3171 as_bad (_("Extra junk on line"));
3172 return -1;
3175 /* OK, now parse them into expressions. */
3176 for (i = 0; i < numexp; i++)
3178 memset (&operands[i].exp, 0, sizeof (operands[i].exp));
3179 if (operands[i].buf[0] == '#')
3181 /* Immediate. */
3182 parse_expression (operands[i].buf + 1, &operands[i].exp);
3184 else if (operands[i].buf[0] == '@')
3186 /* Direct notation. */
3187 parse_expression (operands[i].buf + 1, &operands[i].exp);
3189 else if (operands[i].buf[0] == '*')
3191 /* Indirect. */
3192 char *paren = strchr (operands[i].buf, '(');
3194 /* Allow immediate syntax in the inner expression. */
3195 if (paren && paren[1] == '#')
3196 *++paren = '(';
3198 /* Pull out the lk expression or SP offset, if present. */
3199 if (paren != NULL)
3201 int len = strlen (paren);
3202 char *end = paren + len;
3203 int c;
3205 while (end[-1] != ')')
3206 if (--end <= paren)
3208 as_bad (_("Badly formed address expression"));
3209 return -1;
3211 c = *end;
3212 *end = '\0';
3213 parse_expression (paren, &operands[i].exp);
3214 *end = c;
3216 else
3217 operands[i].exp.X_op = O_absent;
3219 else
3220 parse_expression (operands[i].buf, &operands[i].exp);
3223 return numexp;
3226 /* Predicates for different operand types. */
3228 static int
3229 is_immediate (struct opstruct *operand)
3231 return *operand->buf == '#';
3234 /* This is distinguished from immediate because some numbers must be constants
3235 and must *not* have the '#' prefix. */
3237 static int
3238 is_absolute (struct opstruct *operand)
3240 return operand->exp.X_op == O_constant && !is_immediate (operand);
3243 /* Is this an indirect operand? */
3245 static int
3246 is_indirect (struct opstruct *operand)
3248 return operand->buf[0] == '*';
3251 /* Is this a valid dual-memory operand? */
3253 static int
3254 is_dual (struct opstruct *operand)
3256 if (is_indirect (operand) && strncasecmp (operand->buf, "*ar", 3) == 0)
3258 char *tmp = operand->buf + 3;
3259 int arf;
3260 int valid_mod;
3262 arf = *tmp++ - '0';
3263 /* Only allow *ARx, *ARx-, *ARx+, or *ARx+0%. */
3264 valid_mod = *tmp == '\0' ||
3265 strcasecmp (tmp, "-") == 0 ||
3266 strcasecmp (tmp, "+") == 0 ||
3267 strcasecmp (tmp, "+0%") == 0;
3268 return arf >= 2 && arf <= 5 && valid_mod;
3270 return 0;
3273 static int
3274 is_mmreg (struct opstruct *operand)
3276 return (is_absolute (operand)
3277 || is_immediate (operand)
3278 || str_hash_find (mmreg_hash, operand->buf) != 0);
3281 static int
3282 is_type (struct opstruct *operand, enum optype type)
3284 switch (type)
3286 case OP_None:
3287 return operand->buf[0] == 0;
3288 case OP_Xmem:
3289 case OP_Ymem:
3290 return is_dual (operand);
3291 case OP_Sind:
3292 return is_indirect (operand);
3293 case OP_xpmad_ms7:
3294 /* This one *must* be immediate. */
3295 return is_immediate (operand);
3296 case OP_xpmad:
3297 case OP_pmad:
3298 case OP_PA:
3299 case OP_dmad:
3300 case OP_Lmem:
3301 case OP_MMR:
3302 return 1;
3303 case OP_Smem:
3304 /* Address may be a numeric, indirect, or an expression. */
3305 return !is_immediate (operand);
3306 case OP_MMRY:
3307 case OP_MMRX:
3308 return is_mmreg (operand);
3309 case OP_SRC:
3310 case OP_SRC1:
3311 case OP_RND:
3312 case OP_DST:
3313 return is_accumulator (operand);
3314 case OP_B:
3315 return is_accumulator (operand) && TOUPPER (operand->buf[0]) == 'B';
3316 case OP_A:
3317 return is_accumulator (operand) && TOUPPER (operand->buf[0]) == 'A';
3318 case OP_ARX:
3319 return strncasecmp ("ar", operand->buf, 2) == 0
3320 && ISDIGIT (operand->buf[2]);
3321 case OP_SBIT:
3322 return str_hash_find (sbit_hash, operand->buf) != 0 || is_absolute (operand);
3323 case OP_CC:
3324 return str_hash_find (cc_hash, operand->buf) != 0;
3325 case OP_CC2:
3326 return str_hash_find (cc2_hash, operand->buf) != 0;
3327 case OP_CC3:
3328 return str_hash_find (cc3_hash, operand->buf) != 0
3329 || is_immediate (operand) || is_absolute (operand);
3330 case OP_16:
3331 return (is_immediate (operand) || is_absolute (operand))
3332 && operand->exp.X_add_number == 16;
3333 case OP_N:
3334 /* Allow st0 or st1 instead of a numeric. */
3335 return is_absolute (operand) || is_immediate (operand) ||
3336 strcasecmp ("st0", operand->buf) == 0 ||
3337 strcasecmp ("st1", operand->buf) == 0;
3338 case OP_12:
3339 case OP_123:
3340 return is_absolute (operand) || is_immediate (operand);
3341 case OP_SHFT:
3342 return (is_immediate (operand) || is_absolute (operand))
3343 && operand->exp.X_add_number >= 0 && operand->exp.X_add_number < 16;
3344 case OP_SHIFT:
3345 /* Let this one catch out-of-range values. */
3346 return (is_immediate (operand) || is_absolute (operand))
3347 && operand->exp.X_add_number != 16;
3348 case OP_BITC:
3349 case OP_031:
3350 case OP_k8:
3351 return is_absolute (operand) || is_immediate (operand);
3352 case OP_k8u:
3353 return is_immediate (operand)
3354 && operand->exp.X_op == O_constant
3355 && operand->exp.X_add_number >= 0
3356 && operand->exp.X_add_number < 256;
3357 case OP_lk:
3358 case OP_lku:
3359 /* Allow anything; assumes opcodes are ordered with Smem operands
3360 versions first. */
3361 return 1;
3362 case OP_k5:
3363 case OP_k3:
3364 case OP_k9:
3365 /* Just make sure it's an integer; check range later. */
3366 return is_immediate (operand);
3367 case OP_T:
3368 return strcasecmp ("t", operand->buf) == 0 ||
3369 strcasecmp ("treg", operand->buf) == 0;
3370 case OP_TS:
3371 return strcasecmp ("ts", operand->buf) == 0;
3372 case OP_ASM:
3373 return strcasecmp ("asm", operand->buf) == 0;
3374 case OP_TRN:
3375 return strcasecmp ("trn", operand->buf) == 0;
3376 case OP_DP:
3377 return strcasecmp ("dp", operand->buf) == 0;
3378 case OP_ARP:
3379 return strcasecmp ("arp", operand->buf) == 0;
3380 default:
3381 return 0;
3385 static int
3386 operands_match (tic54x_insn *insn,
3387 struct opstruct *operands,
3388 int opcount,
3389 const enum optype *refoptype,
3390 int minops,
3391 int maxops)
3393 int op = 0, refop = 0;
3395 if (opcount == 0 && minops == 0)
3396 return 1;
3398 while (op <= maxops && refop <= maxops)
3400 while (!is_type (&operands[op], OPTYPE (refoptype[refop])))
3402 /* Skip an optional template operand if it doesn't agree
3403 with the current operand. */
3404 if (refoptype[refop] & OPT)
3406 ++refop;
3407 --maxops;
3408 if (refop > maxops)
3409 return 0;
3411 else
3412 return 0;
3415 /* Save the actual operand type for later use. */
3416 operands[op].type = OPTYPE (refoptype[refop]);
3417 ++refop;
3418 ++op;
3419 /* Have we matched them all yet? */
3420 if (op == opcount)
3422 while (op < maxops)
3424 /* If a later operand is *not* optional, no match. */
3425 if ((refoptype[refop] & OPT) == 0)
3426 return 0;
3427 /* Flag any implicit default OP_DST operands so we know to add
3428 them explicitly when encoding the operand later. */
3429 if (OPTYPE (refoptype[refop]) == OP_DST)
3430 insn->using_default_dst = 1;
3431 ++refop;
3432 ++op;
3435 return 1;
3439 return 0;
3442 /* 16-bit direct memory address
3443 Explicit dmad operands are always in last word of insn (usually second
3444 word, but bumped to third if lk addressing is used)
3446 We allow *(dmad) notation because the TI assembler allows it.
3448 XPC_CODE:
3449 0 for 16-bit addresses
3450 1 for full 23-bit addresses
3451 2 for the upper 7 bits of a 23-bit address (LDX). */
3453 static int
3454 encode_dmad (tic54x_insn *insn, struct opstruct *operand, int xpc_code)
3456 int op = 1 + insn->is_lkaddr;
3458 /* Only allow *(dmad) expressions; all others are invalid. */
3459 if (is_indirect (operand) && operand->buf[strlen (operand->buf) - 1] != ')')
3461 as_bad (_("Invalid dmad syntax '%s'"), operand->buf);
3462 return 0;
3465 insn->opcode[op].addr_expr = operand->exp;
3467 if (insn->opcode[op].addr_expr.X_op == O_constant)
3469 valueT value = insn->opcode[op].addr_expr.X_add_number;
3471 if (xpc_code == 1)
3473 insn->opcode[0].word &= 0xFF80;
3474 insn->opcode[0].word |= (value >> 16) & 0x7F;
3475 insn->opcode[1].word = value & 0xFFFF;
3477 else if (xpc_code == 2)
3478 insn->opcode[op].word = (value >> 16) & 0xFFFF;
3479 else
3480 insn->opcode[op].word = value;
3482 else
3484 /* Do the fixup later; just store the expression. */
3485 insn->opcode[op].word = 0;
3486 insn->opcode[op].r_nchars = 2;
3488 if (amode == c_mode)
3489 insn->opcode[op].r_type = BFD_RELOC_TIC54X_16_OF_23;
3490 else if (xpc_code == 1)
3492 /* This relocation spans two words, so adjust accordingly. */
3493 insn->opcode[0].addr_expr = operand->exp;
3494 insn->opcode[0].r_type = BFD_RELOC_TIC54X_23;
3495 insn->opcode[0].r_nchars = 4;
3496 insn->opcode[0].unresolved = 1;
3497 /* It's really 2 words, but we want to stop encoding after the
3498 first, since we must encode both words at once. */
3499 insn->words = 1;
3501 else if (xpc_code == 2)
3502 insn->opcode[op].r_type = BFD_RELOC_TIC54X_MS7_OF_23;
3503 else
3504 insn->opcode[op].r_type = BFD_RELOC_TIC54X_16_OF_23;
3506 insn->opcode[op].unresolved = 1;
3509 return 1;
3512 /* 7-bit direct address encoding. */
3514 static int
3515 encode_address (tic54x_insn *insn, struct opstruct *operand)
3517 /* Assumes that dma addresses are *always* in word 0 of the opcode. */
3518 insn->opcode[0].addr_expr = operand->exp;
3520 if (operand->exp.X_op == O_constant)
3521 insn->opcode[0].word |= (operand->exp.X_add_number & 0x7F);
3522 else
3524 if (operand->exp.X_op == O_register)
3525 as_bad (_("Use the .mmregs directive to use memory-mapped register names such as '%s'"), operand->buf);
3526 /* Do the fixup later; just store the expression. */
3527 insn->opcode[0].r_nchars = 1;
3528 insn->opcode[0].r_type = BFD_RELOC_TIC54X_PARTLS7;
3529 insn->opcode[0].unresolved = 1;
3532 return 1;
3535 static int
3536 encode_indirect (tic54x_insn *insn, struct opstruct *operand)
3538 int arf;
3539 int mod;
3541 if (insn->is_lkaddr)
3543 /* lk addresses always go in the second insn word. */
3544 mod = ((TOUPPER (operand->buf[1]) == 'A') ? 12 :
3545 (operand->buf[1] == '(') ? 15 :
3546 (strchr (operand->buf, '%') != NULL) ? 14 : 13);
3547 arf = ((mod == 12) ? operand->buf[3] - '0' :
3548 (mod == 15) ? 0 : operand->buf[4] - '0');
3550 insn->opcode[1].addr_expr = operand->exp;
3552 if (operand->exp.X_op == O_constant)
3553 insn->opcode[1].word = operand->exp.X_add_number;
3554 else
3556 insn->opcode[1].word = 0;
3557 insn->opcode[1].r_nchars = 2;
3558 insn->opcode[1].r_type = BFD_RELOC_TIC54X_16_OF_23;
3559 insn->opcode[1].unresolved = 1;
3562 else if (strncasecmp (operand->buf, "*sp (", 4) == 0)
3564 /* Stack offsets look the same as 7-bit direct addressing. */
3565 return encode_address (insn, operand);
3567 else
3569 arf = (TOUPPER (operand->buf[1]) == 'A' ?
3570 operand->buf[3] : operand->buf[4]) - '0';
3572 if (operand->buf[1] == '+')
3574 mod = 3; /* *+ARx */
3575 if (insn->tm->flags & FL_SMR)
3576 as_warn (_("Address mode *+ARx is write-only. "
3577 "Results of reading are undefined."));
3579 else if (operand->buf[4] == '\0')
3580 mod = 0; /* *ARx */
3581 else if (operand->buf[5] == '\0')
3582 mod = (operand->buf[4] == '-' ? 1 : 2); /* *ARx+ / *ARx- */
3583 else if (operand->buf[6] == '\0')
3585 if (operand->buf[5] == '0')
3586 mod = (operand->buf[4] == '-' ? 5 : 6); /* *ARx+0 / *ARx-0 */
3587 else
3588 mod = (operand->buf[4] == '-' ? 8 : 10);/* *ARx+% / *ARx-% */
3590 else if (TOUPPER (operand->buf[6]) == 'B')
3591 mod = (operand->buf[4] == '-' ? 4 : 7); /* ARx+0B / *ARx-0B */
3592 else if (TOUPPER (operand->buf[6]) == '%')
3593 mod = (operand->buf[4] == '-' ? 9 : 11); /* ARx+0% / *ARx - 0% */
3594 else
3596 as_bad (_("Unrecognized indirect address format \"%s\""),
3597 operand->buf);
3598 return 0;
3602 insn->opcode[0].word |= 0x80 | (mod << 3) | arf;
3604 return 1;
3607 static int
3608 encode_integer (tic54x_insn *insn,
3609 struct opstruct *operand,
3610 int which,
3611 int min,
3612 int max,
3613 unsigned short mask)
3615 long parse, integer;
3617 insn->opcode[which].addr_expr = operand->exp;
3619 if (operand->exp.X_op == O_constant)
3621 parse = operand->exp.X_add_number;
3622 /* Hack -- fixup for 16-bit hex quantities that get converted positive
3623 instead of negative. */
3624 if ((parse & 0x8000) && min == -32768 && max == 32767)
3625 integer = (short) parse;
3626 else
3627 integer = parse;
3629 if (integer >= min && integer <= max)
3631 insn->opcode[which].word |= (integer & mask);
3632 return 1;
3634 as_bad (_("Operand '%s' out of range (%d <= x <= %d)"),
3635 operand->buf, min, max);
3637 else
3639 if (insn->opcode[which].addr_expr.X_op == O_constant)
3641 insn->opcode[which].word |=
3642 insn->opcode[which].addr_expr.X_add_number & mask;
3644 else
3646 /* Do the fixup later; just store the expression. */
3647 bfd_reloc_code_real_type rtype =
3648 (mask == 0x1FF ? BFD_RELOC_TIC54X_PARTMS9 :
3649 mask == 0xFFFF ? BFD_RELOC_TIC54X_16_OF_23 :
3650 mask == 0x7F ? BFD_RELOC_TIC54X_PARTLS7 : BFD_RELOC_8);
3651 int size = (mask == 0x1FF || mask == 0xFFFF) ? 2 : 1;
3653 if (rtype == BFD_RELOC_8)
3654 as_bad (_("Error in relocation handling"));
3656 insn->opcode[which].r_nchars = size;
3657 insn->opcode[which].r_type = rtype;
3658 insn->opcode[which].unresolved = 1;
3661 return 1;
3664 return 0;
3667 static int
3668 encode_condition (tic54x_insn *insn, struct opstruct *operand)
3670 tic54x_symbol *cc = (tic54x_symbol *) str_hash_find (cc_hash, operand->buf);
3671 if (!cc)
3673 as_bad (_("Unrecognized condition code \"%s\""), operand->buf);
3674 return 0;
3676 #define CC_GROUP 0x40
3677 #define CC_ACC 0x08
3678 #define CATG_A1 0x07
3679 #define CATG_B1 0x30
3680 #define CATG_A2 0x30
3681 #define CATG_B2 0x0C
3682 #define CATG_C2 0x03
3683 /* Disallow group 1 conditions mixed with group 2 conditions
3684 if group 1, allow only one category A and one category B
3685 if group 2, allow only one each of category A, B, and C. */
3686 if (((insn->opcode[0].word & 0xFF) != 0))
3688 if ((insn->opcode[0].word & CC_GROUP) != (cc->value & CC_GROUP))
3690 as_bad (_("Condition \"%s\" does not match preceding group"),
3691 operand->buf);
3692 return 0;
3694 if (insn->opcode[0].word & CC_GROUP)
3696 if ((insn->opcode[0].word & CC_ACC) != (cc->value & CC_ACC))
3698 as_bad (_("Condition \"%s\" uses a different accumulator from "
3699 "a preceding condition"),
3700 operand->buf);
3701 return 0;
3703 if ((insn->opcode[0].word & CATG_A1) && (cc->value & CATG_A1))
3705 as_bad (_("Only one comparison conditional allowed"));
3706 return 0;
3708 if ((insn->opcode[0].word & CATG_B1) && (cc->value & CATG_B1))
3710 as_bad (_("Only one overflow conditional allowed"));
3711 return 0;
3714 else if ( ((insn->opcode[0].word & CATG_A2) && (cc->value & CATG_A2))
3715 || ((insn->opcode[0].word & CATG_B2) && (cc->value & CATG_B2))
3716 || ((insn->opcode[0].word & CATG_C2) && (cc->value & CATG_C2)))
3718 as_bad (_("Duplicate %s conditional"), operand->buf);
3719 return 0;
3723 insn->opcode[0].word |= cc->value;
3724 return 1;
3727 static int
3728 encode_cc3 (tic54x_insn *insn, struct opstruct *operand)
3730 tic54x_symbol *cc3 = (tic54x_symbol *) str_hash_find (cc3_hash, operand->buf);
3731 int value = cc3 ? cc3->value : operand->exp.X_add_number << 8;
3733 if ((value & 0x0300) != value)
3735 as_bad (_("Unrecognized condition code \"%s\""), operand->buf);
3736 return 0;
3738 insn->opcode[0].word |= value;
3739 return 1;
3742 static int
3743 encode_arx (tic54x_insn *insn, struct opstruct *operand)
3745 int arf = strlen (operand->buf) >= 3 ? operand->buf[2] - '0' : -1;
3747 if (strncasecmp ("ar", operand->buf, 2) || arf < 0 || arf > 7)
3749 as_bad (_("Invalid auxiliary register (use AR0-AR7)"));
3750 return 0;
3752 insn->opcode[0].word |= arf;
3753 return 1;
3756 static int
3757 encode_cc2 (tic54x_insn *insn, struct opstruct *operand)
3759 tic54x_symbol *cc2 = (tic54x_symbol *) str_hash_find (cc2_hash, operand->buf);
3761 if (!cc2)
3763 as_bad (_("Unrecognized condition code \"%s\""), operand->buf);
3764 return 0;
3766 insn->opcode[0].word |= cc2->value;
3767 return 1;
3770 static int
3771 encode_operand (tic54x_insn *insn, enum optype type, struct opstruct *operand)
3773 int ext = (insn->tm->flags & FL_EXT) != 0;
3775 if (type == OP_MMR && operand->exp.X_op != O_constant)
3777 /* Disallow long-constant addressing for memory-mapped addressing. */
3778 if (insn->is_lkaddr)
3780 as_bad (_("lk addressing modes are invalid for memory-mapped "
3781 "register addressing"));
3782 return 0;
3784 type = OP_Smem;
3785 /* Warn about *+ARx when used with MMR operands. */
3786 if (strncasecmp (operand->buf, "*+ar", 4) == 0)
3788 as_warn (_("Address mode *+ARx is not allowed in memory-mapped "
3789 "register addressing. Resulting behavior is "
3790 "undefined."));
3794 switch (type)
3796 case OP_None:
3797 return 1;
3798 case OP_dmad:
3799 /* 16-bit immediate value. */
3800 return encode_dmad (insn, operand, 0);
3801 case OP_SRC:
3802 if (TOUPPER (*operand->buf) == 'B')
3804 insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1 << 9);
3805 if (insn->using_default_dst)
3806 insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1 << 8);
3808 return 1;
3809 case OP_RND:
3810 /* Make sure this agrees with the OP_DST operand. */
3811 if (!((TOUPPER (operand->buf[0]) == 'B') ^
3812 ((insn->opcode[0].word & (1 << 8)) != 0)))
3814 as_bad (_("Destination accumulator for each part of this parallel "
3815 "instruction must be different"));
3816 return 0;
3818 return 1;
3819 case OP_SRC1:
3820 case OP_DST:
3821 if (TOUPPER (operand->buf[0]) == 'B')
3822 insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1 << 8);
3823 return 1;
3824 case OP_Xmem:
3825 case OP_Ymem:
3827 int mod = (operand->buf[4] == '\0' ? 0 : /* *arx */
3828 operand->buf[4] == '-' ? 1 : /* *arx- */
3829 operand->buf[5] == '\0' ? 2 : 3); /* *arx+, *arx+0% */
3830 int arf = operand->buf[3] - '0' - 2;
3831 int code = (mod << 2) | arf;
3832 insn->opcode[0].word |= (code << (type == OP_Xmem ? 4 : 0));
3833 return 1;
3835 case OP_Lmem:
3836 case OP_Smem:
3837 if (!is_indirect (operand))
3838 return encode_address (insn, operand);
3839 /* Fall through. */
3840 case OP_Sind:
3841 return encode_indirect (insn, operand);
3842 case OP_xpmad_ms7:
3843 return encode_dmad (insn, operand, 2);
3844 case OP_xpmad:
3845 return encode_dmad (insn, operand, 1);
3846 case OP_PA:
3847 case OP_pmad:
3848 return encode_dmad (insn, operand, 0);
3849 case OP_ARX:
3850 return encode_arx (insn, operand);
3851 case OP_MMRX:
3852 case OP_MMRY:
3853 case OP_MMR:
3855 int value = operand->exp.X_add_number;
3857 if (type == OP_MMR)
3858 insn->opcode[0].word |= value;
3859 else
3861 if (value < 16 || value > 24)
3863 as_bad (_("Memory mapped register \"%s\" out of range"),
3864 operand->buf);
3865 return 0;
3867 if (type == OP_MMRX)
3868 insn->opcode[0].word |= (value - 16) << 4;
3869 else
3870 insn->opcode[0].word |= (value - 16);
3872 return 1;
3874 case OP_B:
3875 case OP_A:
3876 return 1;
3877 case OP_SHFT:
3878 return encode_integer (insn, operand, ext + insn->is_lkaddr,
3879 0, 15, 0xF);
3880 case OP_SHIFT:
3881 return encode_integer (insn, operand, ext + insn->is_lkaddr,
3882 -16, 15, 0x1F);
3883 case OP_lk:
3884 return encode_integer (insn, operand, 1 + insn->is_lkaddr,
3885 -32768, 32767, 0xFFFF);
3886 case OP_CC:
3887 return encode_condition (insn, operand);
3888 case OP_CC2:
3889 return encode_cc2 (insn, operand);
3890 case OP_CC3:
3891 return encode_cc3 (insn, operand);
3892 case OP_BITC:
3893 return encode_integer (insn, operand, 0, 0, 15, 0xF);
3894 case OP_k8:
3895 return encode_integer (insn, operand, 0, -128, 127, 0xFF);
3896 case OP_123:
3898 int value = operand->exp.X_add_number;
3899 int code;
3900 if (value < 1 || value > 3)
3902 as_bad (_("Invalid operand (use 1, 2, or 3)"));
3903 return 0;
3905 code = value == 1 ? 0 : value == 2 ? 0x2 : 0x1;
3906 insn->opcode[0].word |= (code << 8);
3907 return 1;
3909 case OP_031:
3910 return encode_integer (insn, operand, 0, 0, 31, 0x1F);
3911 case OP_k8u:
3912 return encode_integer (insn, operand, 0, 0, 255, 0xFF);
3913 case OP_lku:
3914 return encode_integer (insn, operand, 1 + insn->is_lkaddr,
3915 0, 65535, 0xFFFF);
3916 case OP_SBIT:
3918 tic54x_symbol *sbit = (tic54x_symbol *)
3919 str_hash_find (sbit_hash, operand->buf);
3920 int value = is_absolute (operand) ?
3921 operand->exp.X_add_number : (sbit ? sbit->value : -1);
3922 int reg = 0;
3924 if (insn->opcount == 1)
3926 if (!sbit)
3928 as_bad (_("A status register or status bit name is required"));
3929 return 0;
3931 /* Guess the register based on the status bit; "ovb" is the last
3932 status bit defined for st0. */
3933 if (sbit > (tic54x_symbol *) str_hash_find (sbit_hash, "ovb"))
3934 reg = 1;
3936 if (value == -1)
3938 as_bad (_("Unrecognized status bit \"%s\""), operand->buf);
3939 return 0;
3941 insn->opcode[0].word |= value;
3942 insn->opcode[0].word |= (reg << 9);
3943 return 1;
3945 case OP_N:
3946 if (strcasecmp (operand->buf, "st0") == 0
3947 || strcasecmp (operand->buf, "st1") == 0)
3949 insn->opcode[0].word |=
3950 ((unsigned short) (operand->buf[2] - '0')) << 9;
3951 return 1;
3953 else if (operand->exp.X_op == O_constant
3954 && (operand->exp.X_add_number == 0
3955 || operand->exp.X_add_number == 1))
3957 insn->opcode[0].word |=
3958 ((unsigned short) (operand->exp.X_add_number)) << 9;
3959 return 1;
3961 as_bad (_("Invalid status register \"%s\""), operand->buf);
3962 return 0;
3963 case OP_k5:
3964 return encode_integer (insn, operand, 0, -16, 15, 0x1F);
3965 case OP_k3:
3966 return encode_integer (insn, operand, 0, 0, 7, 0x7);
3967 case OP_k9:
3968 return encode_integer (insn, operand, 0, 0, 0x1FF, 0x1FF);
3969 case OP_12:
3970 if (operand->exp.X_add_number != 1
3971 && operand->exp.X_add_number != 2)
3973 as_bad (_("Operand \"%s\" out of range (use 1 or 2)"), operand->buf);
3974 return 0;
3976 insn->opcode[0].word |= (operand->exp.X_add_number - 1) << 9;
3977 return 1;
3978 case OP_16:
3979 case OP_T:
3980 case OP_TS:
3981 case OP_ASM:
3982 case OP_TRN:
3983 case OP_DP:
3984 case OP_ARP:
3985 /* No encoding necessary. */
3986 return 1;
3987 default:
3988 return 0;
3991 return 1;
3994 static void
3995 emit_insn (tic54x_insn *insn)
3997 int i;
3998 flagword oldflags = bfd_section_flags (now_seg);
3999 flagword flags = oldflags | SEC_CODE;
4001 if (!bfd_set_section_flags (now_seg, flags))
4002 as_warn (_("error setting flags for \"%s\": %s"),
4003 bfd_section_name (now_seg),
4004 bfd_errmsg (bfd_get_error ()));
4006 for (i = 0; i < insn->words; i++)
4008 int size = (insn->opcode[i].unresolved
4009 && insn->opcode[i].r_type == BFD_RELOC_TIC54X_23) ? 4 : 2;
4010 char *p = frag_more (size);
4012 if (size == 2)
4013 md_number_to_chars (p, (valueT) insn->opcode[i].word, 2);
4014 else
4015 md_number_to_chars (p, (valueT) insn->opcode[i].word << 16, 4);
4017 if (insn->opcode[i].unresolved)
4018 fix_new_exp (frag_now, p - frag_now->fr_literal,
4019 insn->opcode[i].r_nchars, &insn->opcode[i].addr_expr,
4020 false, insn->opcode[i].r_type);
4024 /* Convert the operand strings into appropriate opcode values
4025 return the total number of words used by the instruction. */
4027 static int
4028 build_insn (tic54x_insn *insn)
4030 int i;
4032 /* Only non-parallel instructions support lk addressing. */
4033 if (!(insn->tm->flags & FL_PAR))
4035 for (i = 0; i < insn->opcount; i++)
4037 if ((OPTYPE (insn->operands[i].type) == OP_Smem
4038 || OPTYPE (insn->operands[i].type) == OP_Lmem
4039 || OPTYPE (insn->operands[i].type) == OP_Sind)
4040 && strchr (insn->operands[i].buf, '(')
4041 /* Don't mistake stack-relative addressing for lk addressing. */
4042 && strncasecmp (insn->operands[i].buf, "*sp (", 4) != 0)
4044 insn->is_lkaddr = 1;
4045 insn->lkoperand = i;
4046 break;
4050 insn->words = insn->tm->words + insn->is_lkaddr;
4052 insn->opcode[0].word = insn->tm->opcode;
4053 if (insn->tm->flags & FL_EXT)
4054 insn->opcode[1 + insn->is_lkaddr].word = insn->tm->opcode2;
4056 for (i = 0; i < insn->opcount; i++)
4058 enum optype type = insn->operands[i].type;
4060 if (!encode_operand (insn, type, &insn->operands[i]))
4061 return 0;
4063 if (insn->tm->flags & FL_PAR)
4064 for (i = 0; i < insn->paropcount; i++)
4066 enum optype partype = insn->paroperands[i].type;
4068 if (!encode_operand (insn, partype, &insn->paroperands[i]))
4069 return 0;
4072 emit_insn (insn);
4074 return insn->words;
4077 static int
4078 optimize_insn (tic54x_insn *insn)
4080 /* Optimize some instructions, helping out the brain-dead programmer. */
4081 #define is_zero(op) ((op).exp.X_op == O_constant && (op).exp.X_add_number == 0)
4082 if (strcasecmp (insn->tm->name, "add") == 0)
4084 if (insn->opcount > 1
4085 && is_accumulator (&insn->operands[insn->opcount - 2])
4086 && is_accumulator (&insn->operands[insn->opcount - 1])
4087 && strcasecmp (insn->operands[insn->opcount - 2].buf,
4088 insn->operands[insn->opcount - 1].buf) == 0)
4090 --insn->opcount;
4091 insn->using_default_dst = 1;
4092 return 1;
4095 /* Try to collapse if Xmem and shift count is zero. */
4096 if ((OPTYPE (insn->tm->operand_types[0]) == OP_Xmem
4097 && OPTYPE (insn->tm->operand_types[1]) == OP_SHFT
4098 && is_zero (insn->operands[1]))
4099 /* Or if Smem, shift is zero or absent, and SRC == DST. */
4100 || (OPTYPE (insn->tm->operand_types[0]) == OP_Smem
4101 && OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT
4102 && is_type (&insn->operands[1], OP_SHIFT)
4103 && is_zero (insn->operands[1]) && insn->opcount == 3))
4105 insn->operands[1] = insn->operands[2];
4106 insn->opcount = 2;
4107 return 1;
4110 else if (strcasecmp (insn->tm->name, "ld") == 0)
4112 if (insn->opcount == 3 && insn->operands[0].type != OP_SRC)
4114 if ((OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT
4115 || OPTYPE (insn->tm->operand_types[1]) == OP_SHFT)
4116 && is_zero (insn->operands[1])
4117 && (OPTYPE (insn->tm->operand_types[0]) != OP_lk
4118 || (insn->operands[0].exp.X_op == O_constant
4119 && insn->operands[0].exp.X_add_number <= 255
4120 && insn->operands[0].exp.X_add_number >= 0)))
4122 insn->operands[1] = insn->operands[2];
4123 insn->opcount = 2;
4124 return 1;
4128 else if (strcasecmp (insn->tm->name, "sth") == 0
4129 || strcasecmp (insn->tm->name, "stl") == 0)
4131 if ((OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT
4132 || OPTYPE (insn->tm->operand_types[1]) == OP_SHFT)
4133 && is_zero (insn->operands[1]))
4135 insn->operands[1] = insn->operands[2];
4136 insn->opcount = 2;
4137 return 1;
4140 else if (strcasecmp (insn->tm->name, "sub") == 0)
4142 if (insn->opcount > 1
4143 && is_accumulator (&insn->operands[insn->opcount - 2])
4144 && is_accumulator (&insn->operands[insn->opcount - 1])
4145 && strcasecmp (insn->operands[insn->opcount - 2].buf,
4146 insn->operands[insn->opcount - 1].buf) == 0)
4148 --insn->opcount;
4149 insn->using_default_dst = 1;
4150 return 1;
4153 if ( ((OPTYPE (insn->tm->operand_types[0]) == OP_Smem
4154 && OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT)
4155 || (OPTYPE (insn->tm->operand_types[0]) == OP_Xmem
4156 && OPTYPE (insn->tm->operand_types[1]) == OP_SHFT))
4157 && is_zero (insn->operands[1])
4158 && insn->opcount == 3)
4160 insn->operands[1] = insn->operands[2];
4161 insn->opcount = 2;
4162 return 1;
4165 return 0;
4168 /* Find a matching template if possible, and get the operand strings. */
4170 static int
4171 tic54x_parse_insn (tic54x_insn *insn, char *line)
4173 insn->tm = (insn_template *) str_hash_find (op_hash, insn->mnemonic);
4174 if (!insn->tm)
4176 as_bad (_("Unrecognized instruction \"%s\""), insn->mnemonic);
4177 return 0;
4180 insn->opcount = get_operands (insn->operands, line);
4181 if (insn->opcount < 0)
4182 return 0;
4184 /* Check each variation of operands for this mnemonic. */
4185 while (insn->tm->name && strcasecmp (insn->tm->name, insn->mnemonic) == 0)
4187 if (insn->opcount >= insn->tm->minops
4188 && insn->opcount <= insn->tm->maxops
4189 && operands_match (insn, &insn->operands[0], insn->opcount,
4190 insn->tm->operand_types,
4191 insn->tm->minops, insn->tm->maxops))
4193 /* SUCCESS! now try some optimizations. */
4194 if (optimize_insn (insn))
4196 insn->tm = (insn_template *) str_hash_find (op_hash,
4197 insn->mnemonic);
4198 continue;
4201 return 1;
4203 ++(insn->tm);
4205 as_bad (_("Unrecognized operand list '%s' for instruction '%s'"),
4206 line, insn->mnemonic);
4207 return 0;
4210 /* We set this in start_line_hook, 'cause if we do a line replacement, we
4211 won't be able to see the next line. */
4212 static int parallel_on_next_line_hint = 0;
4214 /* See if this is part of a parallel instruction
4215 Look for a subsequent line starting with "||". */
4217 static int
4218 next_line_shows_parallel (char *next_line)
4220 /* Look for the second half. */
4221 while (*next_line != 0 && ISSPACE (*next_line))
4222 ++next_line;
4224 return (next_line[0] == PARALLEL_SEPARATOR
4225 && next_line[1] == PARALLEL_SEPARATOR);
4228 static int
4229 tic54x_parse_parallel_insn_firstline (tic54x_insn *insn, char *line)
4231 insn->tm = (insn_template *) str_hash_find (parop_hash, insn->mnemonic);
4232 if (!insn->tm)
4234 as_bad (_("Unrecognized parallel instruction \"%s\""),
4235 insn->mnemonic);
4236 return 0;
4239 while (insn->tm->name && strcasecmp (insn->tm->name,
4240 insn->mnemonic) == 0)
4242 insn->opcount = get_operands (insn->operands, line);
4243 if (insn->opcount < 0)
4244 return 0;
4245 if (insn->opcount == 2
4246 && operands_match (insn, &insn->operands[0], insn->opcount,
4247 insn->tm->operand_types, 2, 2))
4249 return 1;
4251 ++(insn->tm);
4253 /* Didn't find a matching parallel; try for a normal insn. */
4254 return 0;
4257 /* Parse the second line of a two-line parallel instruction. */
4259 static int
4260 tic54x_parse_parallel_insn_lastline (tic54x_insn *insn, char *line)
4262 int valid_mnemonic = 0;
4264 insn->paropcount = get_operands (insn->paroperands, line);
4265 while (insn->tm->name && strcasecmp (insn->tm->name,
4266 insn->mnemonic) == 0)
4268 if (strcasecmp (insn->tm->parname, insn->parmnemonic) == 0)
4270 valid_mnemonic = 1;
4272 if (insn->paropcount >= insn->tm->minops
4273 && insn->paropcount <= insn->tm->maxops
4274 && operands_match (insn, insn->paroperands,
4275 insn->paropcount,
4276 insn->tm->paroperand_types,
4277 insn->tm->minops, insn->tm->maxops))
4278 return 1;
4280 ++(insn->tm);
4282 if (valid_mnemonic)
4283 as_bad (_("Invalid operand (s) for parallel instruction \"%s\""),
4284 insn->parmnemonic);
4285 else
4286 as_bad (_("Unrecognized parallel instruction combination \"%s || %s\""),
4287 insn->mnemonic, insn->parmnemonic);
4289 return 0;
4292 /* If quotes found, return copy of line up to closing quote;
4293 otherwise up until terminator.
4294 If it's a string, pass as-is; otherwise attempt substitution symbol
4295 replacement on the value. */
4297 static char *
4298 subsym_get_arg (char *line, const char *terminators, char **str, int nosub)
4300 char *ptr = line;
4301 char *endp;
4302 int is_string = *line == '"';
4303 int is_char = ISDIGIT (*line);
4305 if (is_char)
4307 while (ISDIGIT (*ptr))
4308 ++ptr;
4309 endp = ptr;
4310 *str = xmemdup0 (line, ptr - line);
4312 else if (is_string)
4314 char *savedp = input_line_pointer;
4315 int len;
4317 input_line_pointer = ptr;
4318 *str = demand_copy_C_string (&len);
4319 endp = input_line_pointer;
4320 input_line_pointer = savedp;
4322 /* Do forced substitutions if requested. */
4323 if (!nosub && **str == ':')
4324 *str = subsym_substitute (*str, 1);
4326 else
4328 const char *term = terminators;
4330 while (*ptr && *ptr != *term)
4332 if (!*term)
4334 term = terminators;
4335 ++ptr;
4337 else
4338 ++term;
4340 endp = ptr;
4341 *str = xmemdup0 (line, ptr - line);
4342 /* Do simple substitution, if available. */
4343 if (!nosub)
4345 subsym_ent_t *ent = subsym_lookup (*str, macro_level);
4346 if (ent && !ent->isproc)
4347 *str = ent->u.s;
4351 return endp;
4354 /* Replace the given substitution string.
4355 We start at the innermost macro level, so that existing locals remain local
4356 Note: we're treating macro args identically to .var's; I don't know if
4357 that's compatible w/TI's assembler. */
4359 static void
4360 subsym_create_or_replace (char *name, char *value)
4362 int i;
4363 subsym_ent_t *ent = xmalloc (sizeof (*ent));
4364 ent->u.s = value;
4365 ent->freekey = 0;
4366 ent->freeval = 0;
4367 ent->isproc = 0;
4368 ent->ismath = 0;
4370 for (i = macro_level; i > 0; i--)
4371 if (str_hash_find (subsym_hash[i], name))
4373 str_hash_insert (subsym_hash[i], name, ent, 1);
4374 return;
4376 str_hash_insert (subsym_hash[0], name, ent, 1);
4379 /* Look up the substitution string replacement for the given symbol.
4380 Start with the innermost macro substitution table given and work
4381 outwards. */
4383 static subsym_ent_t *
4384 subsym_lookup (char *name, int nest_level)
4386 void *value = str_hash_find (subsym_hash[nest_level], name);
4388 if (value || nest_level == 0)
4389 return value;
4391 return subsym_lookup (name, nest_level - 1);
4394 /* Do substitution-symbol replacement on the given line (recursively).
4395 return the argument if no substitution was done
4397 Also look for built-in functions ($func (arg)) and local labels.
4399 If FORCED is set, look for forced substitutions of the form ':SYMBOL:'. */
4401 static char *
4402 subsym_substitute (char *line, int forced)
4404 /* For each apparent symbol, see if it's a substitution symbol, and if so,
4405 replace it in the input. */
4406 char *replacement; /* current replacement for LINE. */
4407 char *head; /* Start of line. */
4408 char *ptr; /* Current examination point. */
4409 int changed = 0; /* Did we make a substitution? */
4410 int eval_line = 0; /* Is this line a .eval/.asg statement? */
4411 int eval_symbol = 0; /* Are we in the middle of the symbol for
4412 .eval/.asg? */
4413 char *eval_end = NULL;
4414 int recurse = 1;
4415 int line_conditional = 0;
4416 char *tmp;
4417 unsigned char current_char;
4419 /* Flag lines where we might need to replace a single '=' with two;
4420 GAS uses single '=' to assign macro args values, and possibly other
4421 places, so limit what we replace. */
4422 if (strstr (line, ".if")
4423 || strstr (line, ".elseif")
4424 || strstr (line, ".break"))
4425 line_conditional = 1;
4427 /* Watch out for .eval, so that we avoid doing substitution on the
4428 symbol being assigned a value. */
4429 if (strstr (line, ".eval") || strstr (line, ".asg"))
4430 eval_line = 1;
4432 /* If it's a macro definition, don't do substitution on the argument
4433 names. */
4434 if (strstr (line, ".macro"))
4435 return line;
4437 /* Work with a copy of the input line. */
4438 replacement = xstrdup (line);
4439 ptr = head = replacement;
4441 while (!is_end_of_line[(current_char = * (unsigned char *) ptr)])
4443 /* Need to update this since LINE may have been modified. */
4444 if (eval_line)
4445 eval_end = strrchr (ptr, ',');
4447 /* Replace triple double quotes with bounding quote/escapes. */
4448 if (current_char == '"' && ptr[1] == '"' && ptr[2] == '"')
4450 ptr[1] = '\\';
4451 tmp = strstr (ptr + 2, "\"\"\"");
4452 if (tmp)
4453 tmp[0] = '\\';
4454 changed = 1;
4457 /* Replace a single '=' with a '==';
4458 for compatibility with older code only. */
4459 if (line_conditional && current_char == '=')
4461 if (ptr[1] == '=')
4463 ptr += 2;
4464 continue;
4466 *ptr++ = '\0';
4467 tmp = concat (head, "==", ptr, (char *) NULL);
4468 /* Continue examining after the '=='. */
4469 ptr = tmp + strlen (head) + 2;
4470 free (replacement);
4471 head = replacement = tmp;
4472 changed = 1;
4475 /* Flag when we've reached the symbol part of .eval/.asg. */
4476 if (eval_line && ptr >= eval_end)
4477 eval_symbol = 1;
4479 /* For each apparent symbol, see if it's a substitution symbol, and if
4480 so, replace it in the input. */
4481 if ((forced && current_char == ':')
4482 || (!forced && is_name_beginner (current_char)))
4484 char *name; /* Symbol to be replaced. */
4485 char *savedp = input_line_pointer;
4486 int c;
4487 subsym_ent_t *ent = NULL;
4488 char *value = NULL;
4489 char *tail; /* Rest of line after symbol. */
4491 /* Skip the colon. */
4492 if (forced)
4493 ++ptr;
4495 input_line_pointer = ptr;
4496 c = get_symbol_name (&name);
4497 /* '?' is not normally part of a symbol, but it IS part of a local
4498 label. */
4499 if (c == '?')
4501 *input_line_pointer++ = c;
4502 c = *input_line_pointer;
4503 *input_line_pointer = '\0';
4505 /* Avoid infinite recursion; if a symbol shows up a second time for
4506 substitution, leave it as is. */
4507 if (str_hash_find (subsym_recurse_hash, name) == NULL)
4509 ent = subsym_lookup (name, macro_level);
4510 if (ent && !ent->isproc)
4511 value = ent->u.s;
4513 else
4514 as_warn (_("%s symbol recursion stopped at "
4515 "second appearance of '%s'"),
4516 forced ? "Forced substitution" : "Substitution", name);
4517 ptr = tail = input_line_pointer;
4518 input_line_pointer = savedp;
4520 /* Check for local labels; replace them with the appropriate
4521 substitution. */
4522 if ((*name == '$' && ISDIGIT (name[1]) && name[2] == '\0')
4523 || name[strlen (name) - 1] == '?')
4525 /* Use an existing identifier for that label if, available, or
4526 create a new, unique identifier. */
4527 value = str_hash_find (local_label_hash[macro_level], name);
4528 if (value == NULL)
4530 char digit[11];
4531 char *namecopy = xstrdup (name);
4533 value = strcpy (xmalloc (strlen (name) + sizeof (digit) + 1),
4534 name);
4535 if (*value != '$')
4536 value[strlen (value) - 1] = '\0';
4537 sprintf (digit, ".%d", local_label_id++);
4538 strcat (value, digit);
4539 str_hash_insert (local_label_hash[macro_level],
4540 namecopy, value, 0);
4542 /* Indicate where to continue looking for substitutions. */
4543 ptr = tail;
4545 /* Check for built-in subsym and math functions. */
4546 else if (ent != NULL && *name == '$')
4548 const subsym_proc_entry *entry = ent->u.p;
4549 char *arg1, *arg2 = NULL;
4551 *ptr = c;
4552 if (!ent->isproc)
4554 as_bad (_("Unrecognized substitution symbol function"));
4555 break;
4557 else if (*ptr != '(')
4559 as_bad (_("Missing '(' after substitution symbol function"));
4560 break;
4562 ++ptr;
4563 if (ent->ismath)
4565 float farg1, farg2 = 0;
4567 farg1 = (float) strtod (ptr, &ptr);
4568 if (entry->nargs == 2)
4570 if (*ptr++ != ',')
4572 as_bad (_("Expecting second argument"));
4573 break;
4575 farg2 = (float) strtod (ptr, &ptr);
4577 value = XNEWVEC (char, 128);
4578 if (entry->type == 2)
4580 int result = (*entry->proc.i) (farg1, farg2);
4581 sprintf (value, "%d", result);
4583 else
4585 float result = (*entry->proc.f) (farg1, farg2);
4586 sprintf (value, "%f", result);
4588 if (*ptr++ != ')')
4590 as_bad (_("Extra junk in function call, expecting ')'"));
4591 break;
4593 /* Don't bother recursing; the replacement isn't a
4594 symbol. */
4595 recurse = 0;
4597 else
4599 int val;
4600 int arg_type[2] = { *ptr == '"' , 0 };
4601 int ismember = !strcmp (entry->name, "$ismember");
4603 /* Parse one or two args, which must be a substitution
4604 symbol, string or a character-string constant. */
4605 /* For all functions, a string or substitution symbol may be
4606 used, with the following exceptions:
4607 firstch/lastch: 2nd arg must be character constant
4608 ismember: both args must be substitution symbols. */
4609 ptr = subsym_get_arg (ptr, ",)", &arg1, ismember);
4610 if (!arg1)
4611 break;
4612 if (entry->nargs == 2)
4614 if (*ptr++ != ',')
4616 as_bad (_("Function expects two arguments"));
4617 break;
4619 /* Character constants are converted to numerics
4620 by the preprocessor. */
4621 arg_type[1] = (ISDIGIT (*ptr)) ? 2 : (*ptr == '"');
4622 ptr = subsym_get_arg (ptr, ")", &arg2, ismember);
4624 /* Args checking. */
4625 if ((!strcmp (entry->name, "$firstch")
4626 || !strcmp (entry->name, "$lastch"))
4627 && arg_type[1] != 2)
4629 as_bad (_("Expecting character constant argument"));
4630 break;
4632 if (ismember
4633 && (arg_type[0] != 0 || arg_type[1] != 0))
4635 as_bad (_("Both arguments must be substitution symbols"));
4636 break;
4638 if (*ptr++ != ')')
4640 as_bad (_("Extra junk in function call, expecting ')'"));
4641 break;
4643 val = (*entry->proc.s) (arg1, arg2);
4644 value = XNEWVEC (char, 64);
4645 sprintf (value, "%d", val);
4647 /* Fix things up to replace the entire expression, not just the
4648 function name. */
4649 tail = ptr;
4650 c = *tail;
4653 if (value != NULL && !eval_symbol)
4655 /* Replace the symbol with its string replacement and
4656 continue. Recursively replace VALUE until either no
4657 substitutions are performed, or a substitution that has been
4658 previously made is encountered again.
4660 Put the symbol into the recursion hash table so we only
4661 try to replace a symbol once. */
4662 if (recurse)
4664 str_hash_insert (subsym_recurse_hash, name, name, 0);
4665 value = subsym_substitute (value, macro_level > 0);
4666 str_hash_delete (subsym_recurse_hash, name);
4669 /* Temporarily zero-terminate where the symbol started. */
4670 *name = 0;
4671 if (forced)
4673 if (c == '(')
4675 /* Subscripted substitution symbol -- use just the
4676 indicated portion of the string; the description
4677 kinda indicates that forced substitution is not
4678 supposed to be recursive, but I'm not sure. */
4679 unsigned beg, len = 1; /* default to a single char */
4680 char *newval = xstrdup (value);
4682 savedp = input_line_pointer;
4683 input_line_pointer = tail + 1;
4684 beg = get_absolute_expression ();
4685 if (beg < 1)
4687 as_bad (_("Invalid subscript (use 1 to %d)"),
4688 (int) strlen (value));
4689 break;
4691 if (*input_line_pointer == ',')
4693 ++input_line_pointer;
4694 len = get_absolute_expression ();
4695 if (beg + len > strlen (value))
4697 as_bad (_("Invalid length (use 0 to %d)"),
4698 (int) strlen (value) - beg);
4699 break;
4702 newval += beg - 1;
4703 newval[len] = 0;
4704 tail = input_line_pointer;
4705 if (*tail++ != ')')
4707 as_bad (_("Missing ')' in subscripted substitution "
4708 "symbol expression"));
4709 break;
4711 c = *tail;
4712 input_line_pointer = savedp;
4714 value = newval;
4716 name[-1] = 0;
4718 tmp = xmalloc (strlen (head) + strlen (value) +
4719 strlen (tail + 1) + 2);
4720 strcpy (tmp, head);
4721 strcat (tmp, value);
4722 /* Make sure forced substitutions are properly terminated. */
4723 if (forced)
4725 if (c != ':')
4727 as_bad (_("Missing forced substitution terminator ':'"));
4728 break;
4730 ++tail;
4732 else
4733 /* Restore the character after the symbol end. */
4734 *tail = c;
4735 strcat (tmp, tail);
4736 /* Continue examining after the replacement value. */
4737 ptr = tmp + strlen (head) + strlen (value);
4738 free (replacement);
4739 head = replacement = tmp;
4740 changed = 1;
4742 else
4743 *ptr = c;
4745 else
4747 ++ptr;
4751 if (changed)
4752 return replacement;
4754 free (replacement);
4755 return line;
4758 /* We use this to handle substitution symbols
4759 hijack input_line_pointer, replacing it with our substituted string.
4761 .sslist should enable listing the line after replacements are made...
4763 returns the new buffer limit. */
4765 void
4766 tic54x_start_line_hook (void)
4768 char *line, *endp;
4769 char *replacement = NULL;
4771 /* Work with a copy of the input line, including EOL char. */
4772 for (endp = input_line_pointer; *endp != 0; )
4773 if (is_end_of_line[(unsigned char) *endp++])
4774 break;
4776 line = xmemdup0 (input_line_pointer, endp - input_line_pointer);
4778 /* Scan ahead for parallel insns. */
4779 parallel_on_next_line_hint = next_line_shows_parallel (endp);
4781 /* If within a macro, first process forced replacements. */
4782 if (macro_level > 0)
4783 replacement = subsym_substitute (line, 1);
4784 else
4785 replacement = line;
4786 replacement = subsym_substitute (replacement, 0);
4788 if (replacement != line)
4790 char *tmp = replacement;
4791 char *comment = strchr (replacement, ';');
4792 char endc = replacement[strlen (replacement) - 1];
4794 /* Clean up the replacement; we'd prefer to have this done by the
4795 standard preprocessing equipment (maybe do_scrub_chars?)
4796 but for now, do a quick-and-dirty. */
4797 if (comment != NULL)
4799 comment[0] = endc;
4800 comment[1] = 0;
4801 --comment;
4803 else
4804 comment = replacement + strlen (replacement) - 1;
4806 /* Trim trailing whitespace. */
4807 while (ISSPACE (*comment))
4809 comment[0] = endc;
4810 comment[1] = 0;
4811 --comment;
4814 /* Compact leading whitespace. */
4815 while (ISSPACE (tmp[0]) && ISSPACE (tmp[1]))
4816 ++tmp;
4818 input_line_pointer = endp;
4819 input_scrub_insert_line (tmp);
4820 free (replacement);
4821 free (line);
4822 /* Keep track of whether we've done a substitution. */
4823 substitution_line = 1;
4825 else
4827 /* No change. */
4828 free (line);
4829 substitution_line = 0;
4833 /* This is the guts of the machine-dependent assembler. STR points to a
4834 machine dependent instruction. This function is supposed to emit
4835 the frags/bytes it assembles to. */
4836 void
4837 md_assemble (char *line)
4839 static int repeat_slot = 0;
4840 static int delay_slots = 0; /* How many delay slots left to fill? */
4841 static int is_parallel = 0;
4842 static tic54x_insn insn;
4843 char *lptr;
4844 char *savedp = input_line_pointer;
4845 int c;
4847 input_line_pointer = line;
4848 c = get_symbol_name (&line);
4850 if (cpu == VNONE)
4851 cpu = V542;
4852 if (address_mode_needs_set)
4854 set_address_mode (amode);
4855 address_mode_needs_set = 0;
4857 if (cpu_needs_set)
4859 set_cpu (cpu);
4860 cpu_needs_set = 0;
4862 assembly_begun = 1;
4864 if (is_parallel)
4866 is_parallel = 0;
4868 strcpy (insn.parmnemonic, line);
4869 lptr = input_line_pointer;
4870 *lptr = c;
4871 input_line_pointer = savedp;
4873 if (tic54x_parse_parallel_insn_lastline (&insn, lptr))
4875 int words = build_insn (&insn);
4877 if (delay_slots != 0)
4879 if (words > delay_slots)
4881 as_bad (ngettext ("Instruction does not fit in available "
4882 "delay slots (%d-word insn, %d slot left)",
4883 "Instruction does not fit in available "
4884 "delay slots (%d-word insn, %d slots left)",
4885 delay_slots),
4886 words, delay_slots);
4887 delay_slots = 0;
4888 return;
4890 delay_slots -= words;
4893 return;
4896 memset (&insn, 0, sizeof (insn));
4897 strcpy (insn.mnemonic, line);
4898 lptr = input_line_pointer;
4899 *lptr = c;
4900 input_line_pointer = savedp;
4902 /* See if this line is part of a parallel instruction; if so, either this
4903 line or the next line will have the "||" specifier preceding the
4904 mnemonic, and we look for it in the parallel insn hash table. */
4905 if (strstr (line, "||") != NULL || parallel_on_next_line_hint)
4907 char *tmp = strstr (line, "||");
4908 if (tmp != NULL)
4909 *tmp = '\0';
4911 if (tic54x_parse_parallel_insn_firstline (&insn, lptr))
4913 is_parallel = 1;
4914 /* If the parallel part is on the same line, process it now,
4915 otherwise let the assembler pick up the next line for us. */
4916 if (tmp != NULL)
4918 while (ISSPACE (tmp[2]))
4919 ++tmp;
4920 md_assemble (tmp + 2);
4923 else
4925 as_bad (_("Unrecognized parallel instruction '%s'"), line);
4927 return;
4930 if (tic54x_parse_insn (&insn, lptr))
4932 int words;
4934 if ((insn.tm->flags & FL_LP)
4935 && cpu != V545LP && cpu != V546LP)
4937 as_bad (_("Instruction '%s' requires an LP cpu version"),
4938 insn.tm->name);
4939 return;
4941 if ((insn.tm->flags & FL_FAR)
4942 && amode != far_mode)
4944 as_bad (_("Instruction '%s' requires far mode addressing"),
4945 insn.tm->name);
4946 return;
4949 words = build_insn (&insn);
4951 /* Is this instruction in a delay slot? */
4952 if (delay_slots)
4954 if (words > delay_slots)
4956 as_warn (ngettext ("Instruction does not fit in available "
4957 "delay slots (%d-word insn, %d slot left). "
4958 "Resulting behavior is undefined.",
4959 "Instruction does not fit in available "
4960 "delay slots (%d-word insn, %d slots left). "
4961 "Resulting behavior is undefined.",
4962 delay_slots),
4963 words, delay_slots);
4964 delay_slots = 0;
4965 return;
4967 /* Branches in delay slots are not allowed. */
4968 if (insn.tm->flags & FL_BMASK)
4970 as_warn (_("Instructions which cause PC discontinuity are not "
4971 "allowed in a delay slot. "
4972 "Resulting behavior is undefined."));
4974 delay_slots -= words;
4977 /* Is this instruction the target of a repeat? */
4978 if (repeat_slot)
4980 if (insn.tm->flags & FL_NR)
4981 as_warn (_("'%s' is not repeatable. "
4982 "Resulting behavior is undefined."),
4983 insn.tm->name);
4984 else if (insn.is_lkaddr)
4985 as_warn (_("Instructions using long offset modifiers or absolute "
4986 "addresses are not repeatable. "
4987 "Resulting behavior is undefined."));
4988 repeat_slot = 0;
4991 /* Make sure we check the target of a repeat instruction. */
4992 if (insn.tm->flags & B_REPEAT)
4994 repeat_slot = 1;
4995 /* FIXME -- warn if repeat_slot == 1 at EOF. */
4997 /* Make sure we check our delay slots for validity. */
4998 if (insn.tm->flags & FL_DELAY)
5000 delay_slots = 2;
5001 /* FIXME -- warn if delay_slots != 0 at EOF. */
5006 /* Do a final adjustment on the symbol table; in this case, make sure we have
5007 a ".file" symbol. */
5009 void
5010 tic54x_adjust_symtab (void)
5012 if (symbol_rootP == NULL
5013 || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
5015 unsigned lineno;
5016 const char * filename = as_where (&lineno);
5017 c_dot_file_symbol (filename);
5021 /* In order to get gas to ignore any | chars at the start of a line,
5022 this function returns true if a | is found in a line.
5023 This lets us process parallel instructions, which span two lines. */
5026 tic54x_unrecognized_line (int c)
5028 return c == PARALLEL_SEPARATOR;
5031 /* Watch for local labels of the form $[0-9] and [_a-zA-Z][_a-zA-Z0-9]*?
5032 Encode their names so that only we see them and can map them to the
5033 appropriate places.
5034 FIXME -- obviously this isn't done yet. These locals still show up in the
5035 symbol table. */
5036 void
5037 tic54x_define_label (symbolS *sym)
5039 /* Just in case we need this later; note that this is not necessarily the
5040 same thing as line_label...
5041 When aligning or assigning labels to fields, sometimes the label is
5042 assigned other than the address at which the label appears.
5043 FIXME -- is this really needed? I think all the proper label assignment
5044 is done in tic54x_cons. */
5045 last_label_seen = sym;
5048 /* Try to parse something that normal parsing failed at. */
5050 symbolS *
5051 tic54x_undefined_symbol (char *name)
5053 tic54x_symbol *sym;
5055 /* Not sure how to handle predefined symbols. */
5056 if ((sym = (tic54x_symbol *) str_hash_find (cc_hash, name)) != NULL
5057 || (sym = (tic54x_symbol *) str_hash_find (cc2_hash, name)) != NULL
5058 || (sym = (tic54x_symbol *) str_hash_find (cc3_hash, name)) != NULL
5059 || str_hash_find (misc_symbol_hash, name) != NULL
5060 || (sym = (tic54x_symbol *) str_hash_find (sbit_hash, name)) != NULL
5061 || (sym = (tic54x_symbol *) str_hash_find (reg_hash, name)) != NULL
5062 || (sym = (tic54x_symbol *) str_hash_find (mmreg_hash, name)) != NULL
5063 || !strcasecmp (name, "a")
5064 || !strcasecmp (name, "b"))
5066 return symbol_new (name, reg_section, &zero_address_frag,
5067 sym ? sym->value : 0);
5070 return NULL;
5073 /* Parse a name in an expression before the expression parser takes a stab at
5074 it. */
5077 tic54x_parse_name (char *name ATTRIBUTE_UNUSED,
5078 expressionS *expn ATTRIBUTE_UNUSED)
5080 return 0;
5083 const char *
5084 md_atof (int type, char *literalP, int *sizeP)
5086 /* Target data is little-endian, but floats are stored
5087 big-"word"ian. ugh. */
5088 return ieee_md_atof (type, literalP, sizeP, true);
5091 arelent *
5092 tc_gen_reloc (asection *section, fixS *fixP)
5094 arelent *rel;
5095 bfd_reloc_code_real_type code = fixP->fx_r_type;
5096 asymbol *sym = symbol_get_bfdsym (fixP->fx_addsy);
5098 rel = XNEW (arelent);
5099 rel->sym_ptr_ptr = XNEW (asymbol *);
5100 *rel->sym_ptr_ptr = sym;
5101 /* We assume that all rel->address are host byte offsets. */
5102 rel->address = fixP->fx_frag->fr_address + fixP->fx_where;
5103 rel->address /= OCTETS_PER_BYTE;
5104 rel->howto = bfd_reloc_type_lookup (stdoutput, code);
5105 if (!strcmp (sym->name, section->name))
5106 rel->howto += HOWTO_BANK;
5108 if (!rel->howto)
5110 const char *name = S_GET_NAME (fixP->fx_addsy);
5111 if (name == NULL)
5112 name = "<unknown>";
5113 as_fatal ("Cannot generate relocation type for symbol %s, code %s",
5114 name, bfd_get_reloc_code_name (code));
5115 return NULL;
5117 return rel;
5120 /* Handle cons expressions. */
5122 void
5123 tic54x_cons_fix_new (fragS *frag, int where, int octets, expressionS *expn,
5124 bfd_reloc_code_real_type r)
5126 switch (octets)
5128 default:
5129 as_bad (_("Unsupported relocation size %d"), octets);
5130 r = BFD_RELOC_TIC54X_16_OF_23;
5131 break;
5132 case 2:
5133 r = BFD_RELOC_TIC54X_16_OF_23;
5134 break;
5135 case 4:
5136 /* TI assembler always uses this, regardless of addressing mode. */
5137 if (emitting_long)
5138 r = BFD_RELOC_TIC54X_23;
5139 else
5140 /* We never want to directly generate this; this is provided for
5141 stabs support only. */
5142 r = BFD_RELOC_32;
5143 break;
5145 fix_new_exp (frag, where, octets, expn, 0, r);
5148 /* Attempt to simplify or even eliminate a fixup.
5149 To indicate that a fixup has been eliminated, set fixP->fx_done.
5151 If fixp->fx_addsy is non-NULL, we'll have to generate a reloc entry. */
5153 void
5154 md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
5156 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
5157 valueT val = * valP;
5159 switch (fixP->fx_r_type)
5161 default:
5162 as_fatal ("Bad relocation type: 0x%02x", fixP->fx_r_type);
5163 return;
5164 case BFD_RELOC_TIC54X_MS7_OF_23:
5165 val = (val >> 16) & 0x7F;
5166 /* Fall through. */
5167 case BFD_RELOC_TIC54X_16_OF_23:
5168 case BFD_RELOC_16:
5169 bfd_put_16 (stdoutput, val, buf);
5170 /* Indicate what we're actually writing, so that we don't get warnings
5171 about exceeding available space. */
5172 *valP = val & 0xFFFF;
5173 break;
5174 case BFD_RELOC_TIC54X_PARTLS7:
5175 bfd_put_16 (stdoutput,
5176 (bfd_get_16 (stdoutput, buf) & 0xFF80) | (val & 0x7F),
5177 buf);
5178 /* Indicate what we're actually writing, so that we don't get warnings
5179 about exceeding available space. */
5180 *valP = val & 0x7F;
5181 break;
5182 case BFD_RELOC_TIC54X_PARTMS9:
5183 /* TI assembler doesn't shift its encoding for relocatable files, and is
5184 thus incompatible with this implementation's relocatable files. */
5185 bfd_put_16 (stdoutput,
5186 (bfd_get_16 (stdoutput, buf) & 0xFE00) | (val >> 7),
5187 buf);
5188 break;
5189 case BFD_RELOC_32:
5190 case BFD_RELOC_TIC54X_23:
5191 bfd_put_32 (stdoutput,
5192 (bfd_get_32 (stdoutput, buf) & 0xFF800000) | val,
5193 buf);
5194 break;
5197 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
5198 fixP->fx_done = 1;
5201 /* This is our chance to record section alignment
5202 don't need to do anything here, since BFD does the proper encoding. */
5204 valueT
5205 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT section_size)
5207 return section_size;
5210 long
5211 md_pcrel_from (fixS *fixP ATTRIBUTE_UNUSED)
5213 return 0;
5216 /* Mostly little-endian, but longwords (4 octets) get MS word stored
5217 first. */
5219 void
5220 tic54x_number_to_chars (char *buf, valueT val, int n)
5222 if (n != 4)
5223 number_to_chars_littleendian (buf, val, n);
5224 else
5226 number_to_chars_littleendian (buf , val >> 16 , 2);
5227 number_to_chars_littleendian (buf + 2, val & 0xFFFF, 2);
5232 tic54x_estimate_size_before_relax (fragS *frag ATTRIBUTE_UNUSED,
5233 segT seg ATTRIBUTE_UNUSED)
5235 return 0;
5238 /* We use this to handle bit allocations which we couldn't handle before due
5239 to symbols being in different frags. return number of octets added. */
5242 tic54x_relax_frag (fragS *frag, long stretch ATTRIBUTE_UNUSED)
5244 symbolS *sym = frag->fr_symbol;
5245 int growth = 0;
5246 int i;
5248 if (sym != NULL)
5250 struct bit_info *bi = (struct bit_info *) frag->fr_opcode;
5251 int bit_offset = frag_bit_offset (frag_prev (frag, bi->seg), bi->seg);
5252 int size = S_GET_VALUE (sym);
5253 fragS *prev_frag = bit_offset_frag (frag_prev (frag, bi->seg), bi->seg);
5254 int available = 16 - bit_offset;
5256 if (symbol_get_frag (sym) != &zero_address_frag
5257 || S_IS_COMMON (sym)
5258 || !S_IS_DEFINED (sym))
5259 as_bad_where (frag->fr_file, frag->fr_line,
5260 _("non-absolute value used with .space/.bes"));
5262 if (size < 0)
5264 as_warn (_("negative value ignored in %s"),
5265 bi->type == TYPE_SPACE ? ".space" :
5266 bi->type == TYPE_BES ? ".bes" : ".field");
5267 growth = 0;
5268 frag->tc_frag_data = frag->fr_fix = 0;
5269 return 0;
5272 if (bi->type == TYPE_FIELD)
5274 /* Bit fields of 16 or larger will have already been handled. */
5275 if (bit_offset != 0 && available >= size)
5277 char *p = prev_frag->fr_literal;
5279 valueT value = bi->value;
5280 value <<= available - size;
5281 value |= ((unsigned short) p[1] << 8) | p[0];
5282 md_number_to_chars (p, value, 2);
5283 if ((prev_frag->tc_frag_data += size) == 16)
5284 prev_frag->tc_frag_data = 0;
5285 if (bi->sym)
5286 symbol_set_frag (bi->sym, prev_frag);
5287 /* This frag is no longer used. */
5288 growth = -frag->fr_fix;
5289 frag->fr_fix = 0;
5290 frag->tc_frag_data = 0;
5292 else
5294 char *p = frag->fr_literal;
5296 valueT value = bi->value << (16 - size);
5297 md_number_to_chars (p, value, 2);
5298 if ((frag->tc_frag_data = size) == 16)
5299 frag->tc_frag_data = 0;
5300 growth = 0;
5303 else
5305 if (bit_offset != 0 && bit_offset < 16)
5307 if (available >= size)
5309 if ((prev_frag->tc_frag_data += size) == 16)
5310 prev_frag->tc_frag_data = 0;
5311 if (bi->sym)
5312 symbol_set_frag (bi->sym, prev_frag);
5313 /* This frag is no longer used. */
5314 growth = -frag->fr_fix;
5315 frag->fr_fix = 0;
5316 frag->tc_frag_data = 0;
5317 goto getout;
5319 if (bi->type == TYPE_SPACE && bi->sym)
5320 symbol_set_frag (bi->sym, prev_frag);
5321 size -= available;
5323 growth = (size + 15) / 16 * OCTETS_PER_BYTE - frag->fr_fix;
5324 for (i = 0; i < growth; i++)
5325 frag->fr_literal[i] = 0;
5326 frag->fr_fix = growth;
5327 frag->tc_frag_data = size % 16;
5328 /* Make sure any BES label points to the LAST word allocated. */
5329 if (bi->type == TYPE_BES && bi->sym)
5330 S_SET_VALUE (bi->sym, frag->fr_fix / OCTETS_PER_BYTE - 1);
5332 getout:
5333 frag->fr_symbol = 0;
5334 frag->fr_opcode = 0;
5335 free ((void *) bi);
5337 return growth;
5340 void
5341 tic54x_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
5342 segT seg ATTRIBUTE_UNUSED,
5343 fragS *frag)
5345 /* Offset is in bytes. */
5346 frag->fr_offset = (frag->fr_next->fr_address
5347 - frag->fr_address
5348 - frag->fr_fix) / frag->fr_var;
5349 if (frag->fr_offset < 0)
5351 as_bad_where (frag->fr_file, frag->fr_line,
5352 _("attempt to .space/.bes backwards? (%ld)"),
5353 (long) frag->fr_offset);
5355 frag->fr_type = rs_space;
5358 /* We need to avoid having labels defined for certain directives/pseudo-ops
5359 since once the label is defined, it's in the symbol table for good. TI
5360 syntax puts the symbol *before* the pseudo (which is kinda like MRI syntax,
5361 I guess, except I've never seen a definition of MRI syntax).
5363 Don't allow labels to start with '.' */
5366 tic54x_start_label (char * label_start, int nul_char, int next_char)
5368 char *rest;
5370 /* If within .struct/.union, no auto line labels, please. */
5371 if (current_stag != NULL)
5372 return 0;
5374 /* Disallow labels starting with "." */
5375 if (next_char != ':')
5377 if (*label_start == '.')
5379 as_bad (_("Invalid label '%s'"), label_start);
5380 return 0;
5384 if (is_end_of_line[(unsigned char) next_char])
5385 return 1;
5387 rest = input_line_pointer;
5388 if (nul_char == '"')
5389 ++rest;
5390 while (ISSPACE (next_char))
5391 next_char = *++rest;
5392 if (next_char != '.')
5393 return 1;
5395 /* Don't let colon () define a label for any of these... */
5396 return ((strncasecmp (rest, ".tag", 4) != 0 || !ISSPACE (rest[4]))
5397 && (strncasecmp (rest, ".struct", 7) != 0 || !ISSPACE (rest[7]))
5398 && (strncasecmp (rest, ".union", 6) != 0 || !ISSPACE (rest[6]))
5399 && (strncasecmp (rest, ".macro", 6) != 0 || !ISSPACE (rest[6]))
5400 && (strncasecmp (rest, ".set", 4) != 0 || !ISSPACE (rest[4]))
5401 && (strncasecmp (rest, ".equ", 4) != 0 || !ISSPACE (rest[4])));