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)
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
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):
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. */
49 #include "safe-ctype.h"
53 #include "opcode/tic54x.h"
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. */
65 struct stag_field
/* List of fields. */
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
;
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. */
93 } operands
[MAX_OPERANDS
];
96 struct opstruct paroperands
[MAX_OPERANDS
];
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? */
105 unsigned short word
; /* Final encoded opcode data. */
107 int r_nchars
; /* Relocation size. */
108 bfd_reloc_code_real_type r_type
; /* Relocation type. */
109 expressionS addr_expr
; /* Storage for unresolved expressions. */
115 VNONE
= 0, V541
= 1, V542
= 2, V543
= 3, V545
= 5, V548
= 8, V549
= 9,
116 V545LP
= 15, V546LP
= 16
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
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
];
194 int (*s
) (char *, char *);
195 float (*f
) (float, float);
196 int (*i
) (float, float);
205 const subsym_proc_entry
*p
;
207 unsigned int freekey
: 1;
208 unsigned int freeval
: 1;
209 unsigned int isproc
: 1;
210 unsigned int ismath
: 1;
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
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
238 #define ILLEGAL_WITHIN_STRUCT() \
240 if (current_stag != NULL) \
242 as_bad (_("pseudo-op illegal within .struct/.union")); \
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);
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). */
266 tic54x_emit_char (char c
)
270 expn
.X_op
= O_constant
;
271 expn
.X_add_number
= c
;
272 emit_expr (&expn
, 2);
275 /* Walk backwards in the frag chain. */
278 frag_prev (fragS
*frag
, segT seg
)
280 segment_info_type
*seginfo
= seg_info (seg
);
283 for (fragp
= seginfo
->frchainP
->frch_root
; fragp
; fragp
= fragp
->fr_next
)
284 if (fragp
->fr_next
== frag
)
291 bit_offset_frag (fragS
*frag
, segT seg
)
295 if (frag
->fr_fix
== 0
296 && frag
->fr_opcode
== NULL
297 && frag
->tc_frag_data
== 0)
298 frag
= frag_prev (frag
, seg
);
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. */
309 frag_bit_offset (fragS
*frag
, segT seg
)
311 frag
= bit_offset_frag (frag
, seg
);
314 return frag
->fr_opcode
!= NULL
? -1 : frag
->tc_frag_data
;
319 /* Read an expression from a C string; returns a pointer past the end of the
323 parse_expression (char *str
, expressionS
*expn
)
328 tmp
= input_line_pointer
; /* Save line pointer. */
329 input_line_pointer
= str
;
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
343 tic54x_asg (int x ATTRIBUTE_UNUSED
)
348 int quoted
= *input_line_pointer
== '"';
350 ILLEGAL_WITHIN_STRUCT ();
355 str
= demand_copy_C_string (&len
);
356 c
= *input_line_pointer
;
361 str
= input_line_pointer
;
362 while ((c
= *input_line_pointer
) != ',')
364 if (is_end_of_line
[(unsigned char) c
])
366 ++input_line_pointer
;
368 len
= input_line_pointer
- str
;
369 str
= notes_memdup (str
, len
, len
+ 1);
373 as_bad (_("Comma and symbol expected for '.asg STRING, SYMBOL'"));
375 ignore_rest_of_line ();
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"));
387 ignore_rest_of_line ();
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. */
402 tic54x_eval (int x ATTRIBUTE_UNUSED
)
408 char valuestr
[32], *tmp
;
411 ILLEGAL_WITHIN_STRUCT ();
415 quoted
= *input_line_pointer
== '"';
417 ++input_line_pointer
;
418 value
= get_absolute_expression ();
421 if (*input_line_pointer
!= '"')
423 as_bad (_("Unterminated string after absolute expression"));
424 ignore_rest_of_line ();
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 ();
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 ();
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
473 (not yet implemented). */
476 tic54x_bss (int x ATTRIBUTE_UNUSED
)
483 subsegT current_subseg
;
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. */
495 c
= * ++ input_line_pointer
;
498 as_bad (_(".bss size argument missing\n"));
499 ignore_rest_of_line ();
503 ++input_line_pointer
;
504 words
= get_absolute_expression ();
507 as_bad (_(".bss size %d < 0!"), words
);
508 ignore_rest_of_line ();
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 ();
521 if (*input_line_pointer
== ',')
523 ++input_line_pointer
;
524 align
= get_absolute_expression ();
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
);
553 /* s_align eats end of line; restore it */
555 --input_line_pointer
;
559 bss_section
->flags
|= SEC_TIC54X_BLOCK
;
561 subseg_set (current_seg
, current_subseg
); /* Restore current seg. */
562 demand_empty_rest_of_line ();
566 stag_add_field_symbols (struct stag
*stag
,
570 const char *root_stag_name
)
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
;
587 sym
= symbol_new (name
, absolute_section
, &zero_address_frag
,
588 (field
->stag
? field
->offset
589 : base_offset
+ field
->offset
));
591 symbol_table_insert (sym
);
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
);
602 str_hash_insert (subsym_hash
[0], name
, ent
, 0);
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
,
611 rootsym
, root_stag_name
);
618 /* Keep track of stag fields so that when structures are nested we can add the
619 complete dereferencing symbols to the symbol table. */
622 stag_add_field (struct stag
*parent
,
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
;
633 if (parent
->field
== NULL
)
634 parent
->field
= sfield
;
637 struct stag_field
*sf
= parent
->field
;
638 while (sf
->next
!= NULL
)
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
,
648 symbol_table_insert (sym
);
652 /* [STAG] .struct [OFFSET]
653 Start defining structure offsets (symbols in absolute section). */
656 tic54x_struct (int arg
)
658 int start_offset
= 0;
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. */
678 /* Offset is ignored in inner structs. */
680 if (!is_end_of_line
[(unsigned char) *input_line_pointer
])
681 start_offset
= get_absolute_expression ();
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
;
693 as_warn (_("Offset on nested structures is ignored"));
694 start_offset
= abs_section_offset
;
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
,
714 char * label
= xstrdup (S_GET_NAME (line_label
));
715 current_stag
->sym
= symbol_new (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
);
730 /* [LABEL] .endstruct
731 finish defining structure offsets; optional LABEL's value will be the size
735 tic54x_endstruct (int is_union
)
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 ();
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
;
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
);
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
),
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
);
790 subseg_set (stag_saved_seg
, stag_saved_subseg
);
794 Reference a structure within a structure, as a sized field with an optional
796 If used outside of a .struct/.endstruct, overlays the given structure
797 format on the existing allocated space. */
800 tic54x_tag (int ignore ATTRIBUTE_UNUSED
)
803 int c
= get_symbol_name (&name
);
804 struct stag
*stag
= (struct stag
*) str_hash_find (stag_hash
, name
);
809 as_bad (_("Unrecognized struct/union tag '%s'"), name
);
811 as_bad (_(".tag requires a structure tag"));
812 ignore_rest_of_line ();
815 if (line_label
== NULL
)
817 as_bad (_("Label required for .tag"));
818 ignore_rest_of_line ();
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
),
832 symbolS
*sym
= symbol_find (label
);
836 as_bad (_(".tag target '%s' undefined"), label
);
837 ignore_rest_of_line ();
841 stag_add_field_symbols (stag
, S_GET_NAME (sym
),
842 S_GET_VALUE (stag
->sym
), sym
, stag
->name
);
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 ();
856 /* Handle all .byte, .char, .double, .field, .float, .half, .int, .long,
857 .short, .string, .ubyte, .uchar, .uhalf, .uint, .ulong, .ushort, .uword,
861 tic54x_struct_field (int type
)
865 int new_bitfield_offset
= 0;
866 int field_align
= current_stag
->current_bitfield_offset
!= 0;
867 int longword_align
= 0;
870 if (!is_end_of_line
[(unsigned char) *input_line_pointer
])
871 count
= get_absolute_expression ();
887 case '*': /* String. */
896 case '.': /* Bitfield. */
898 if (count
< 1 || count
> 32)
900 as_bad (_(".field count '%d' out of range (1 <= X <= 32)"), count
);
901 ignore_rest_of_line ();
904 if (current_stag
->current_bitfield_offset
+ count
> 16)
906 /* Set the appropriate size and new field offset. */
916 new_bitfield_offset
= count
- 16;
919 new_bitfield_offset
= count
;
924 new_bitfield_offset
= current_stag
->current_bitfield_offset
+ count
;
928 as_bad (_("Unrecognized field type '%c'"), type
);
929 ignore_rest_of_line ();
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
),
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
),
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
;
972 abs_section_offset
+= (unsigned) size
* count
;
973 current_stag
->current_bitfield_offset
= new_bitfield_offset
;
978 /* Handle .byte, .word. .int, .long and all variants. */
981 tic54x_cons (int type
)
986 /* If we're within a .struct construct, don't actually allocate space. */
987 if (current_stag
!= NULL
)
989 tic54x_struct_field (type
);
993 #ifdef md_flush_pending_output
994 md_flush_pending_output ();
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 ());
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] == '\"');
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. */
1050 if ((value
> 0 && value
> 0xFF)
1051 || (value
< 0 && value
< - 0x100))
1052 as_warn (_("Overflow in expression, truncated to 8 bits"));
1055 if ((value
> 0 && value
> 0xFFFF)
1056 || (value
< 0 && value
< - 0x10000))
1057 as_warn (_("Overflow in expression, truncated to 16 bits"));
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 ();
1070 if (expn
.X_op
!= O_constant
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). */
1081 emit_expr (&expn
, 4);
1087 emitting_long
= octets
== 4;
1088 emit_expr (&expn
, (octets
== 1) ? 2 : octets
);
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. */
1119 tic54x_global (int type
)
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
);
1139 input_line_pointer
++;
1140 if (is_end_of_line
[(unsigned char) *input_line_pointer
])
1141 c
= *input_line_pointer
;
1146 demand_empty_rest_of_line ();
1150 free_subsym_ent (void *ent
)
1152 string_tuple_t
*tuple
= (string_tuple_t
*) ent
;
1153 subsym_ent_t
*val
= (void *) tuple
->value
;
1155 free ((void *) tuple
->key
);
1163 subsym_htab_create (void)
1165 return htab_create_alloc (16, hash_string_tuple
, eq_string_tuple
,
1166 free_subsym_ent
, xcalloc
, free
);
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
);
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. */
1188 tic54x_clear_local_labels (int ignored ATTRIBUTE_UNUSED
)
1190 htab_empty (local_label_hash
[macro_level
]);
1195 .sect "section name"
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.
1207 tic54x_sect (int arg
)
1209 ILLEGAL_WITHIN_STRUCT ();
1211 /* Local labels are cleared when changing sections. */
1212 tic54x_clear_local_labels (0);
1216 else if (arg
== 'd')
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
);
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. */
1268 tic54x_space (int arg
)
1274 int bits_per_byte
= (OCTETS_PER_BYTE
* 8);
1276 symbolS
*label
= line_label
;
1279 ILLEGAL_WITHIN_STRUCT ();
1281 #ifdef md_flush_pending_output
1282 md_flush_pending_output ();
1285 /* Read the bit count. */
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
);
1298 p
= frag_var (rs_machine_dependent
,
1299 65536 * 2, 1, (relax_substateT
) 0,
1300 make_expr_symbol (&expn
), (offsetT
) 0,
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. */
1321 symbol_set_frag (label
, frag_now
);
1322 S_SET_VALUE (label
, frag_now_fix () - 1);
1325 frag_now
->tc_frag_data
+= expn
.X_add_number
;
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);
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
;
1345 as_warn (_(".space/.bes repeat count is negative, ignored"));
1348 else if (octets
== 0)
1350 as_warn (_(".space/.bes repeat count is zero, ignored"));
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
;
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);
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. */
1398 tic54x_usect (int x ATTRIBUTE_UNUSED
)
1405 int size
, blocking_flag
, alignment_flag
;
1407 subsegT current_subseg
;
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 (§ion_name
); /* Get terminator. */
1416 name
= xstrdup (section_name
);
1417 c
= restore_line_pointer (c
);
1420 ++input_line_pointer
;
1423 as_bad (_("Missing size argument"));
1424 ignore_rest_of_line ();
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 ();
1439 /* Read a possibly present fourth argument (alignment flag). */
1440 if (*input_line_pointer
== ',')
1442 ++input_line_pointer
;
1443 alignment_flag
= get_absolute_expression ();
1449 blocking_flag
= alignment_flag
= 0;
1451 seg
= subseg_new (name
, 0);
1452 flags
= bfd_section_flags (seg
) | SEC_ALLOC
;
1456 /* s_align eats end of line; restore it. */
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);
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;
1511 set_cpu (enum cpu_version 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:
1534 This is for compatibility only. It currently has no affect on assembly. */
1535 static int cpu_needs_set
= 1;
1538 tic54x_version (int x ATTRIBUTE_UNUSED
)
1540 enum cpu_version version
= VNONE
;
1541 enum cpu_version old_version
= cpu
;
1545 ILLEGAL_WITHIN_STRUCT ();
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 ();
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 ();
1574 *input_line_pointer
= c
;
1575 demand_empty_rest_of_line ();
1578 /* 'f' = float, 'x' = xfloat, 'd' = double, 'l' = ldouble. */
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 ();
1590 /* Align to long word boundary (4 octets) unless it's ".xfloat". */
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 ());
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. */
1611 tic54x_stringer (int type
)
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 ('*');
1624 #ifdef md_flush_pending_output
1625 md_flush_pending_output ();
1628 c
= ','; /* Do loop. */
1632 switch (*input_line_pointer
)
1636 unsigned short value
= get_absolute_expression ();
1637 FRAG_APPEND_1_CHAR ( value
& 0xFF);
1638 FRAG_APPEND_1_CHAR ((value
>> 8) & 0xFF);
1642 ++input_line_pointer
; /* -> 1st char of string. */
1643 while (is_a_char (c
= next_char_of_string ()))
1647 FRAG_APPEND_1_CHAR (c
);
1648 FRAG_APPEND_1_CHAR (0);
1652 /* Packed strings are filled MS octet first. */
1653 if (last_char
== -1)
1657 FRAG_APPEND_1_CHAR (c
);
1658 FRAG_APPEND_1_CHAR (last_char
);
1665 if (packed
&& last_char
!= -1)
1667 FRAG_APPEND_1_CHAR (0);
1668 FRAG_APPEND_1_CHAR (last_char
);
1673 FRAG_APPEND_1_CHAR (0);
1674 FRAG_APPEND_1_CHAR (0);
1677 know (input_line_pointer
[-1] == '\"');
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 ();
1696 tic54x_p2align (int arg ATTRIBUTE_UNUSED
)
1698 as_bad (_("p2align not supported on this target"));
1702 tic54x_align_words (int arg
)
1704 /* Only ".align" with no argument is allowed within .struct/.union. */
1707 if (!is_end_of_line
[(unsigned char) *input_line_pointer
])
1710 as_warn (_("Argument to .even ignored"));
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 ();
1726 ILLEGAL_WITHIN_STRUCT ();
1728 s_align_bytes (count
<< 1);
1731 /* Initialize multiple-bit fields within a single word of memory. */
1734 tic54x_field (int ignore ATTRIBUTE_UNUSED
)
1740 symbolS
*label
= line_label
;
1742 if (current_stag
!= NULL
)
1744 tic54x_struct_field ('.');
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 ();
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*
1769 as_bad (_("field size must be 16 when value is relocatable"));
1770 ignore_rest_of_line ();
1774 frag_now
->tc_frag_data
= 0;
1775 emit_expr (&expn
, 2);
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. */
1789 frag_now
->tc_frag_data
= 0;
1791 md_number_to_chars (p
, (value
>> (size
- 16)) & 0xFFFF, 2);
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
;
1809 bi
->type
= TYPE_FIELD
;
1811 p
= frag_var (rs_machine_dependent
,
1812 4, 1, (relax_substateT
) 0,
1813 make_expr_symbol (&size_exp
), (offsetT
) 0,
1817 else if (bit_offset
== 0 || bit_offset
+ size
> 16)
1819 /* Align a new field. */
1821 frag_now
->tc_frag_data
= 0;
1822 alloc_frag
= frag_now
;
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
;
1832 symbol_set_frag (label
, alloc_frag
);
1833 if (alloc_frag
== frag_now
)
1834 S_SET_VALUE (label
, frag_now_fix () - 1);
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;
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. */
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. */
1870 tic54x_clink (int ignored ATTRIBUTE_UNUSED
)
1874 ILLEGAL_WITHIN_STRUCT ();
1876 if (*input_line_pointer
== '\"')
1878 char *section_name
= ++input_line_pointer
;
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
);
1890 as_bad (_("Unrecognized section '%s'"), section_name
);
1891 ignore_rest_of_line ();
1897 if (!tic54x_initialized_section (seg
))
1899 as_bad (_("Current section is uninitialized, "
1900 "section name required for .clink"));
1901 ignore_rest_of_line ();
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
1915 tic54x_set_default_include (void)
1918 const char *curfile
= as_where (&lineno
);
1919 const char *tmp
= strrchr (curfile
, '/');
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);
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. */
1943 tic54x_include (int ignored ATTRIBUTE_UNUSED
)
1945 char newblock
[] = " .newblock\n";
1950 ILLEGAL_WITHIN_STRUCT ();
1954 if (*input_line_pointer
== '"')
1956 filename
= demand_copy_C_string (&len
);
1957 demand_empty_rest_of_line ();
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)
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 ();
1985 tic54x_message (int type
)
1991 ILLEGAL_WITHIN_STRUCT ();
1993 if (*input_line_pointer
== '"')
1994 msg
= demand_copy_C_string (&len
);
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
;
2009 as_tsktsk ("%s", msg
);
2012 as_warn ("%s", msg
);
2019 demand_empty_rest_of_line ();
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). */
2031 tic54x_label (int ignored ATTRIBUTE_UNUSED
)
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 ();
2048 Install all memory-mapped register names into the symbol table as
2049 absolute local symbols. */
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
);
2068 Count defaults to 1024. */
2071 tic54x_loop (int count
)
2073 ILLEGAL_WITHIN_STRUCT ();
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. */
2085 tic54x_endloop (int ignore ATTRIBUTE_UNUSED
)
2087 as_bad (_("ENDLOOP without corresponding LOOP"));
2088 ignore_rest_of_line ();
2091 /* .break [condition]. */
2094 tic54x_break (int ignore ATTRIBUTE_UNUSED
)
2098 ILLEGAL_WITHIN_STRUCT ();
2101 if (!is_end_of_line
[(unsigned char) *input_line_pointer
])
2102 cond
= get_absolute_expression ();
2105 end_repeat (substitution_line
? 1 : 0);
2109 set_address_mode (int 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;
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 ();
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 ();
2139 set_address_mode (mode
);
2140 demand_empty_rest_of_line ();
2143 /* .sblock "section"|section [,...,"section"|section]
2144 Designate initialized sections for blocking. */
2147 tic54x_sblock (int ignore ATTRIBUTE_UNUSED
)
2151 ILLEGAL_WITHIN_STRUCT ();
2158 if (*input_line_pointer
== '"')
2162 name
= demand_copy_C_string (&len
);
2168 c
= get_symbol_name (§ion_name
);
2169 name
= xstrdup (section_name
);
2170 (void) restore_line_pointer (c
);
2173 seg
= bfd_get_section_by_name (stdoutput
, name
);
2176 as_bad (_("Unrecognized section '%s'"), name
);
2177 ignore_rest_of_line ();
2180 else if (!tic54x_initialized_section (seg
))
2182 as_bad (_(".sblock may be used for initialized sections only"));
2183 ignore_rest_of_line ();
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
2199 value must be defined externals; no forward-referencing allowed
2200 symbols assigned with .set/.equ may not be redefined. */
2203 tic54x_set (int ignore ATTRIBUTE_UNUSED
)
2208 ILLEGAL_WITHIN_STRUCT ();
2212 as_bad (_("Symbol missing for .set/.equ"));
2213 ignore_rest_of_line ();
2216 name
= xstrdup (S_GET_NAME (line_label
));
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
);
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 ();
2234 List false conditional blocks. */
2237 tic54x_fclist (int show
)
2240 listing
&= ~LISTING_NOCOND
;
2242 listing
|= LISTING_NOCOND
;
2243 demand_empty_rest_of_line ();
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. */
2258 tic54x_var (int ignore ATTRIBUTE_UNUSED
)
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 ();
2273 if (!ISALPHA (*input_line_pointer
))
2275 as_bad (_("Substitution symbols must begin with a letter"));
2276 ignore_rest_of_line ();
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 *) "";
2290 str_hash_insert (subsym_hash
[macro_level
], name
, ent
, 0);
2293 ++input_line_pointer
;
2294 if (is_end_of_line
[(unsigned char) *input_line_pointer
])
2295 c
= *input_line_pointer
;
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. */
2311 tic54x_mlib (int ignore ATTRIBUTE_UNUSED
)
2318 ILLEGAL_WITHIN_STRUCT ();
2320 /* Parse the filename. */
2321 if (*input_line_pointer
== '"')
2323 if ((filename
= demand_copy_C_string (&len
)) == NULL
)
2330 while (!is_end_of_line
[(unsigned char) *input_line_pointer
]
2331 && !ISSPACE (*input_line_pointer
))
2333 obstack_1grow (¬es
, *input_line_pointer
);
2334 ++input_line_pointer
;
2337 obstack_1grow (¬es
, '\0');
2338 filename
= obstack_finish (¬es
);
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
);
2348 register_dependency (path
);
2350 /* Expand all archive entries to temporary files and include them. */
2351 abfd
= bfd_openr (path
, NULL
);
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 ();
2359 if (!bfd_check_format (abfd
, bfd_archive
))
2361 as_bad (_("File '%s' not in macro archive format"), path
);
2362 ignore_rest_of_line ();
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
);
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
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
);
2387 input_scrub_insert_file (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
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 },
2480 md_parse_option (int c
, const char *arg
)
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. */
2495 case OPTION_CPU_VERSION
:
2497 cpu
= lookup_version (arg
);
2500 as_fatal (_("Bad CPU version '%s'"), arg
);
2503 case OPTION_ADDRESS_MODE
:
2505 address_mode_needs_set
= 1;
2507 case OPTION_STDERR_TO_FILE
:
2509 const char *filename
= arg
;
2510 FILE *fp
= fopen (filename
, "w+");
2513 as_fatal (_("Can't redirect stderr to the file '%s'"), filename
);
2515 if ((fp
= freopen (filename
, "w+", stderr
)) == NULL
)
2516 as_fatal (_("Can't redirect stderr to the file '%s'"), filename
);
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. */
2530 tic54x_macro_start (void)
2532 if (++macro_level
>= MAX_SUBSYM_HASH
)
2535 as_fatal (_("Macro nesting is too deep"));
2538 subsym_hash
[macro_level
] = subsym_htab_create ();
2539 local_label_hash
[macro_level
] = local_label_htab_create ();
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
);
2558 str_hash_insert (subsym_hash
[macro_level
], name
, ent
, 0);
2562 /* Get rid of this macro's .var's, arguments, and local labels. */
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
;
2575 subsym_symlen (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2580 /* Compare symbol A to string B. */
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. */
2592 subsym_firstch (char *a
, char *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. */
2603 subsym_lastch (char *a
, char *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
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. */
2627 subsym_ismember (char *sym
, char *list
)
2630 subsym_ent_t
*listv
;
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 ();
2643 ptr
= elem
= notes_strdup (listv
->u
.s
);
2644 while (*ptr
&& *ptr
!= ',')
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. */
2657 /* Return zero if not a constant; otherwise:
2665 subsym_iscons (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2669 parse_expression (a
, &expn
);
2671 if (expn
.X_op
== O_constant
)
2673 int len
= strlen (a
);
2675 switch (TOUPPER (a
[len
- 1]))
2688 /* No suffix; either octal, hex, or decimal. */
2689 if (*a
== '0' && len
> 1)
2691 if (TOUPPER (a
[1]) == 'X')
2701 /* Return 1 if A is a valid symbol name. Expects string input. */
2704 subsym_isname (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2706 if (!is_name_beginner (*a
))
2710 if (!is_part_of_name (*a
))
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. */
2722 subsym_isreg (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2724 if (str_hash_find (reg_hash
, a
))
2726 if (str_hash_find (mmreg_hash
, a
))
2731 /* Return the structure size, given the stag. */
2734 subsym_structsz (char *name
, char *ignore ATTRIBUTE_UNUSED
)
2736 struct stag
*stag
= (struct stag
*) str_hash_find (stag_hash
, name
);
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. */
2752 subsym_structacc (char *stag_name ATTRIBUTE_UNUSED
,
2753 char *ignore ATTRIBUTE_UNUSED
)
2759 math_ceil (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2761 return (float) ceil (arg1
);
2765 math_cvi (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2771 math_floor (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2773 return (float) floor (arg1
);
2777 math_fmod (float arg1
, float arg2
)
2779 return (int) arg1
% (int) arg2
;
2783 math_int (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2785 return arg1
== (float) (int) arg1
;
2789 math_round (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2791 return arg1
> 0 ? (int) (arg1
+ 0.5) : (int) (arg1
- 0.5);
2795 math_sgn (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2797 return arg1
< 0.0f
? -1 : arg1
!= 0.0f
? 1 : 0;
2801 math_trunc (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2807 math_acos (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2809 return (float) acos (arg1
);
2813 math_asin (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2815 return (float) asin (arg1
);
2819 math_atan (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2821 return (float) atan (arg1
);
2825 math_atan2 (float arg1
, float arg2
)
2827 return (float) atan2 (arg1
, arg2
);
2831 math_cosh (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2833 return (float) cosh (arg1
);
2837 math_cos (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2839 return (float) cos (arg1
);
2843 math_cvf (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2845 return (float) arg1
;
2849 math_exp (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2851 return (float) exp (arg1
);
2855 math_fabs (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2857 return (float) fabs (arg1
);
2860 /* expr1 * 2^expr2. */
2863 math_ldexp (float arg1
, float arg2
)
2865 return arg1
* (float) pow (2.0, arg2
);
2869 math_log10 (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2871 return (float) log10 (arg1
);
2875 math_log (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2877 return (float) log (arg1
);
2881 math_max (float arg1
, float arg2
)
2883 return (arg1
> arg2
) ? arg1
: arg2
;
2887 math_min (float arg1
, float arg2
)
2889 return (arg1
< arg2
) ? arg1
: arg2
;
2893 math_pow (float arg1
, float arg2
)
2895 return (float) pow (arg1
, arg2
);
2899 math_sin (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2901 return (float) sin (arg1
);
2905 math_sinh (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2907 return (float) sinh (arg1
);
2911 math_sqrt (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2913 return (float) sqrt (arg1
);
2917 math_tan (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2919 return (float) tan (arg1
);
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 },
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");
2990 /* Look for A_DIR and add it to the include list. */
2993 char *tmp
= xstrdup (A_DIR
);
2997 char *next
= strchr (tmp
, ';');
3001 add_include_dir (tmp
);
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
;
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 ();
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 ();
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
);
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
3100 get_operands (struct opstruct operands
[], char *line
)
3104 int expecting_operand
= 0;
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
))
3115 while (paren_not_balanced
|| *lptr
!= ',')
3119 if (paren_not_balanced
)
3121 as_bad (_("Unbalanced parenthesis in operand %d"), numexp
);
3128 ++paren_not_balanced
;
3129 else if (*lptr
== ')')
3130 --paren_not_balanced
;
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;
3150 if (expecting_operand
|| *lptr
== ',')
3152 as_bad (_("Expecting operand after ','"));
3158 if (*++lptr
== '\0')
3160 as_bad (_("Expecting operand after ','"));
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"));
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] == '#')
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] == '*')
3192 char *paren
= strchr (operands
[i
].buf
, '(');
3194 /* Allow immediate syntax in the inner expression. */
3195 if (paren
&& paren
[1] == '#')
3198 /* Pull out the lk expression or SP offset, if present. */
3201 int len
= strlen (paren
);
3202 char *end
= paren
+ len
;
3205 while (end
[-1] != ')')
3208 as_bad (_("Badly formed address expression"));
3213 parse_expression (paren
, &operands
[i
].exp
);
3217 operands
[i
].exp
.X_op
= O_absent
;
3220 parse_expression (operands
[i
].buf
, &operands
[i
].exp
);
3226 /* Predicates for different operand types. */
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. */
3238 is_absolute (struct opstruct
*operand
)
3240 return operand
->exp
.X_op
== O_constant
&& !is_immediate (operand
);
3243 /* Is this an indirect operand? */
3246 is_indirect (struct opstruct
*operand
)
3248 return operand
->buf
[0] == '*';
3251 /* Is this a valid dual-memory operand? */
3254 is_dual (struct opstruct
*operand
)
3256 if (is_indirect (operand
) && strncasecmp (operand
->buf
, "*ar", 3) == 0)
3258 char *tmp
= operand
->buf
+ 3;
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
;
3274 is_mmreg (struct opstruct
*operand
)
3276 return (is_absolute (operand
)
3277 || is_immediate (operand
)
3278 || str_hash_find (mmreg_hash
, operand
->buf
) != 0);
3282 is_type (struct opstruct
*operand
, enum optype type
)
3287 return operand
->buf
[0] == 0;
3290 return is_dual (operand
);
3292 return is_indirect (operand
);
3294 /* This one *must* be immediate. */
3295 return is_immediate (operand
);
3304 /* Address may be a numeric, indirect, or an expression. */
3305 return !is_immediate (operand
);
3308 return is_mmreg (operand
);
3313 return is_accumulator (operand
);
3315 return is_accumulator (operand
) && TOUPPER (operand
->buf
[0]) == 'B';
3317 return is_accumulator (operand
) && TOUPPER (operand
->buf
[0]) == 'A';
3319 return strncasecmp ("ar", operand
->buf
, 2) == 0
3320 && ISDIGIT (operand
->buf
[2]);
3322 return str_hash_find (sbit_hash
, operand
->buf
) != 0 || is_absolute (operand
);
3324 return str_hash_find (cc_hash
, operand
->buf
) != 0;
3326 return str_hash_find (cc2_hash
, operand
->buf
) != 0;
3328 return str_hash_find (cc3_hash
, operand
->buf
) != 0
3329 || is_immediate (operand
) || is_absolute (operand
);
3331 return (is_immediate (operand
) || is_absolute (operand
))
3332 && operand
->exp
.X_add_number
== 16;
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;
3340 return is_absolute (operand
) || is_immediate (operand
);
3342 return (is_immediate (operand
) || is_absolute (operand
))
3343 && operand
->exp
.X_add_number
>= 0 && operand
->exp
.X_add_number
< 16;
3345 /* Let this one catch out-of-range values. */
3346 return (is_immediate (operand
) || is_absolute (operand
))
3347 && operand
->exp
.X_add_number
!= 16;
3351 return is_absolute (operand
) || is_immediate (operand
);
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;
3359 /* Allow anything; assumes opcodes are ordered with Smem operands
3365 /* Just make sure it's an integer; check range later. */
3366 return is_immediate (operand
);
3368 return strcasecmp ("t", operand
->buf
) == 0 ||
3369 strcasecmp ("treg", operand
->buf
) == 0;
3371 return strcasecmp ("ts", operand
->buf
) == 0;
3373 return strcasecmp ("asm", operand
->buf
) == 0;
3375 return strcasecmp ("trn", operand
->buf
) == 0;
3377 return strcasecmp ("dp", operand
->buf
) == 0;
3379 return strcasecmp ("arp", operand
->buf
) == 0;
3386 operands_match (tic54x_insn
*insn
,
3387 struct opstruct
*operands
,
3389 const enum optype
*refoptype
,
3393 int op
= 0, refop
= 0;
3395 if (opcount
== 0 && minops
== 0)
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
)
3415 /* Save the actual operand type for later use. */
3416 operands
[op
].type
= OPTYPE (refoptype
[refop
]);
3419 /* Have we matched them all yet? */
3424 /* If a later operand is *not* optional, no match. */
3425 if ((refoptype
[refop
] & OPT
) == 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;
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.
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). */
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
);
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
;
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;
3480 insn
->opcode
[op
].word
= value
;
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. */
3501 else if (xpc_code
== 2)
3502 insn
->opcode
[op
].r_type
= BFD_RELOC_TIC54X_MS7_OF_23
;
3504 insn
->opcode
[op
].r_type
= BFD_RELOC_TIC54X_16_OF_23
;
3506 insn
->opcode
[op
].unresolved
= 1;
3512 /* 7-bit direct address encoding. */
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);
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;
3536 encode_indirect (tic54x_insn
*insn
, struct opstruct
*operand
)
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
;
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
);
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')
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 */
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% */
3596 as_bad (_("Unrecognized indirect address format \"%s\""),
3602 insn
->opcode
[0].word
|= 0x80 | (mod
<< 3) | arf
;
3608 encode_integer (tic54x_insn
*insn
,
3609 struct opstruct
*operand
,
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
;
3629 if (integer
>= min
&& integer
<= max
)
3631 insn
->opcode
[which
].word
|= (integer
& mask
);
3634 as_bad (_("Operand '%s' out of range (%d <= x <= %d)"),
3635 operand
->buf
, min
, max
);
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
;
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;
3668 encode_condition (tic54x_insn
*insn
, struct opstruct
*operand
)
3670 tic54x_symbol
*cc
= (tic54x_symbol
*) str_hash_find (cc_hash
, operand
->buf
);
3673 as_bad (_("Unrecognized condition code \"%s\""), operand
->buf
);
3676 #define CC_GROUP 0x40
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"),
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"),
3703 if ((insn
->opcode
[0].word
& CATG_A1
) && (cc
->value
& CATG_A1
))
3705 as_bad (_("Only one comparison conditional allowed"));
3708 if ((insn
->opcode
[0].word
& CATG_B1
) && (cc
->value
& CATG_B1
))
3710 as_bad (_("Only one overflow conditional allowed"));
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
);
3723 insn
->opcode
[0].word
|= cc
->value
;
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
);
3738 insn
->opcode
[0].word
|= value
;
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)"));
3752 insn
->opcode
[0].word
|= arf
;
3757 encode_cc2 (tic54x_insn
*insn
, struct opstruct
*operand
)
3759 tic54x_symbol
*cc2
= (tic54x_symbol
*) str_hash_find (cc2_hash
, operand
->buf
);
3763 as_bad (_("Unrecognized condition code \"%s\""), operand
->buf
);
3766 insn
->opcode
[0].word
|= cc2
->value
;
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"));
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 "
3799 /* 16-bit immediate value. */
3800 return encode_dmad (insn
, operand
, 0);
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);
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"));
3821 if (TOUPPER (operand
->buf
[0]) == 'B')
3822 insn
->opcode
[ext
? (1 + insn
->is_lkaddr
) : 0].word
|= (1 << 8);
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));
3837 if (!is_indirect (operand
))
3838 return encode_address (insn
, operand
);
3841 return encode_indirect (insn
, operand
);
3843 return encode_dmad (insn
, operand
, 2);
3845 return encode_dmad (insn
, operand
, 1);
3848 return encode_dmad (insn
, operand
, 0);
3850 return encode_arx (insn
, operand
);
3855 int value
= operand
->exp
.X_add_number
;
3858 insn
->opcode
[0].word
|= value
;
3861 if (value
< 16 || value
> 24)
3863 as_bad (_("Memory mapped register \"%s\" out of range"),
3867 if (type
== OP_MMRX
)
3868 insn
->opcode
[0].word
|= (value
- 16) << 4;
3870 insn
->opcode
[0].word
|= (value
- 16);
3878 return encode_integer (insn
, operand
, ext
+ insn
->is_lkaddr
,
3881 return encode_integer (insn
, operand
, ext
+ insn
->is_lkaddr
,
3884 return encode_integer (insn
, operand
, 1 + insn
->is_lkaddr
,
3885 -32768, 32767, 0xFFFF);
3887 return encode_condition (insn
, operand
);
3889 return encode_cc2 (insn
, operand
);
3891 return encode_cc3 (insn
, operand
);
3893 return encode_integer (insn
, operand
, 0, 0, 15, 0xF);
3895 return encode_integer (insn
, operand
, 0, -128, 127, 0xFF);
3898 int value
= operand
->exp
.X_add_number
;
3900 if (value
< 1 || value
> 3)
3902 as_bad (_("Invalid operand (use 1, 2, or 3)"));
3905 code
= value
== 1 ? 0 : value
== 2 ? 0x2 : 0x1;
3906 insn
->opcode
[0].word
|= (code
<< 8);
3910 return encode_integer (insn
, operand
, 0, 0, 31, 0x1F);
3912 return encode_integer (insn
, operand
, 0, 0, 255, 0xFF);
3914 return encode_integer (insn
, operand
, 1 + insn
->is_lkaddr
,
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);
3924 if (insn
->opcount
== 1)
3928 as_bad (_("A status register or status bit name is required"));
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"))
3938 as_bad (_("Unrecognized status bit \"%s\""), operand
->buf
);
3941 insn
->opcode
[0].word
|= value
;
3942 insn
->opcode
[0].word
|= (reg
<< 9);
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;
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;
3961 as_bad (_("Invalid status register \"%s\""), operand
->buf
);
3964 return encode_integer (insn
, operand
, 0, -16, 15, 0x1F);
3966 return encode_integer (insn
, operand
, 0, 0, 7, 0x7);
3968 return encode_integer (insn
, operand
, 0, 0, 0x1FF, 0x1FF);
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
);
3976 insn
->opcode
[0].word
|= (operand
->exp
.X_add_number
- 1) << 9;
3985 /* No encoding necessary. */
3995 emit_insn (tic54x_insn
*insn
)
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
);
4013 md_number_to_chars (p
, (valueT
) insn
->opcode
[i
].word
, 2);
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. */
4028 build_insn (tic54x_insn
*insn
)
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
;
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
]))
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
]))
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)
4091 insn
->using_default_dst
= 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];
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];
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];
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)
4149 insn
->using_default_dst
= 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];
4168 /* Find a matching template if possible, and get the operand strings. */
4171 tic54x_parse_insn (tic54x_insn
*insn
, char *line
)
4173 insn
->tm
= (insn_template
*) str_hash_find (op_hash
, insn
->mnemonic
);
4176 as_bad (_("Unrecognized instruction \"%s\""), insn
->mnemonic
);
4180 insn
->opcount
= get_operands (insn
->operands
, line
);
4181 if (insn
->opcount
< 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
,
4205 as_bad (_("Unrecognized operand list '%s' for instruction '%s'"),
4206 line
, insn
->mnemonic
);
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 "||". */
4218 next_line_shows_parallel (char *next_line
)
4220 /* Look for the second half. */
4221 while (*next_line
!= 0 && ISSPACE (*next_line
))
4224 return (next_line
[0] == PARALLEL_SEPARATOR
4225 && next_line
[1] == PARALLEL_SEPARATOR
);
4229 tic54x_parse_parallel_insn_firstline (tic54x_insn
*insn
, char *line
)
4231 insn
->tm
= (insn_template
*) str_hash_find (parop_hash
, insn
->mnemonic
);
4234 as_bad (_("Unrecognized parallel instruction \"%s\""),
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)
4245 if (insn
->opcount
== 2
4246 && operands_match (insn
, &insn
->operands
[0], insn
->opcount
,
4247 insn
->tm
->operand_types
, 2, 2))
4253 /* Didn't find a matching parallel; try for a normal insn. */
4257 /* Parse the second line of a two-line parallel instruction. */
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)
4272 if (insn
->paropcount
>= insn
->tm
->minops
4273 && insn
->paropcount
<= insn
->tm
->maxops
4274 && operands_match (insn
, insn
->paroperands
,
4276 insn
->tm
->paroperand_types
,
4277 insn
->tm
->minops
, insn
->tm
->maxops
))
4283 as_bad (_("Invalid operand (s) for parallel instruction \"%s\""),
4286 as_bad (_("Unrecognized parallel instruction combination \"%s || %s\""),
4287 insn
->mnemonic
, insn
->parmnemonic
);
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. */
4298 subsym_get_arg (char *line
, const char *terminators
, char **str
, int nosub
)
4302 int is_string
= *line
== '"';
4303 int is_char
= ISDIGIT (*line
);
4307 while (ISDIGIT (*ptr
))
4310 *str
= xmemdup0 (line
, ptr
- line
);
4314 char *savedp
= input_line_pointer
;
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);
4328 const char *term
= terminators
;
4330 while (*ptr
&& *ptr
!= *term
)
4341 *str
= xmemdup0 (line
, ptr
- line
);
4342 /* Do simple substitution, if available. */
4345 subsym_ent_t
*ent
= subsym_lookup (*str
, macro_level
);
4346 if (ent
&& !ent
->isproc
)
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. */
4360 subsym_create_or_replace (char *name
, char *value
)
4363 subsym_ent_t
*ent
= xmalloc (sizeof (*ent
));
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);
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
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)
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:'. */
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
4413 char *eval_end
= NULL
;
4415 int line_conditional
= 0;
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"))
4432 /* If it's a macro definition, don't do substitution on the argument
4434 if (strstr (line
, ".macro"))
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. */
4445 eval_end
= strrchr (ptr
, ',');
4447 /* Replace triple double quotes with bounding quote/escapes. */
4448 if (current_char
== '"' && ptr
[1] == '"' && ptr
[2] == '"')
4451 tmp
= strstr (ptr
+ 2, "\"\"\"");
4457 /* Replace a single '=' with a '==';
4458 for compatibility with older code only. */
4459 if (line_conditional
&& current_char
== '=')
4467 tmp
= concat (head
, "==", ptr
, (char *) NULL
);
4468 /* Continue examining after the '=='. */
4469 ptr
= tmp
+ strlen (head
) + 2;
4471 head
= replacement
= tmp
;
4475 /* Flag when we've reached the symbol part of .eval/.asg. */
4476 if (eval_line
&& ptr
>= eval_end
)
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
;
4487 subsym_ent_t
*ent
= NULL
;
4489 char *tail
; /* Rest of line after symbol. */
4491 /* Skip the colon. */
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
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
)
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
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
);
4531 char *namecopy
= xstrdup (name
);
4533 value
= strcpy (xmalloc (strlen (name
) + sizeof (digit
) + 1),
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. */
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
;
4554 as_bad (_("Unrecognized substitution symbol function"));
4557 else if (*ptr
!= '(')
4559 as_bad (_("Missing '(' after substitution symbol function"));
4565 float farg1
, farg2
= 0;
4567 farg1
= (float) strtod (ptr
, &ptr
);
4568 if (entry
->nargs
== 2)
4572 as_bad (_("Expecting second argument"));
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
);
4585 float result
= (*entry
->proc
.f
) (farg1
, farg2
);
4586 sprintf (value
, "%f", result
);
4590 as_bad (_("Extra junk in function call, expecting ')'"));
4593 /* Don't bother recursing; the replacement isn't a
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
);
4612 if (entry
->nargs
== 2)
4616 as_bad (_("Function expects two arguments"));
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"));
4633 && (arg_type
[0] != 0 || arg_type
[1] != 0))
4635 as_bad (_("Both arguments must be substitution symbols"));
4640 as_bad (_("Extra junk in function call, expecting ')'"));
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
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. */
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. */
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 ();
4687 as_bad (_("Invalid subscript (use 1 to %d)"),
4688 (int) strlen (value
));
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
);
4704 tail
= input_line_pointer
;
4707 as_bad (_("Missing ')' in subscripted substitution "
4708 "symbol expression"));
4712 input_line_pointer
= savedp
;
4718 tmp
= xmalloc (strlen (head
) + strlen (value
) +
4719 strlen (tail
+ 1) + 2);
4721 strcat (tmp
, value
);
4722 /* Make sure forced substitutions are properly terminated. */
4727 as_bad (_("Missing forced substitution terminator ':'"));
4733 /* Restore the character after the symbol end. */
4736 /* Continue examining after the replacement value. */
4737 ptr
= tmp
+ strlen (head
) + strlen (value
);
4739 head
= replacement
= tmp
;
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. */
4766 tic54x_start_line_hook (void)
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
++])
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);
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
)
4804 comment
= replacement
+ strlen (replacement
) - 1;
4806 /* Trim trailing whitespace. */
4807 while (ISSPACE (*comment
))
4814 /* Compact leading whitespace. */
4815 while (ISSPACE (tmp
[0]) && ISSPACE (tmp
[1]))
4818 input_line_pointer
= endp
;
4819 input_scrub_insert_line (tmp
);
4822 /* Keep track of whether we've done a substitution. */
4823 substitution_line
= 1;
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. */
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
;
4844 char *savedp
= input_line_pointer
;
4847 input_line_pointer
= line
;
4848 c
= get_symbol_name (&line
);
4852 if (address_mode_needs_set
)
4854 set_address_mode (amode
);
4855 address_mode_needs_set
= 0;
4868 strcpy (insn
.parmnemonic
, line
);
4869 lptr
= input_line_pointer
;
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)",
4886 words
, delay_slots
);
4890 delay_slots
-= words
;
4896 memset (&insn
, 0, sizeof (insn
));
4897 strcpy (insn
.mnemonic
, line
);
4898 lptr
= input_line_pointer
;
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
, "||");
4911 if (tic54x_parse_parallel_insn_firstline (&insn
, lptr
))
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. */
4918 while (ISSPACE (tmp
[2]))
4920 md_assemble (tmp
+ 2);
4925 as_bad (_("Unrecognized parallel instruction '%s'"), line
);
4930 if (tic54x_parse_insn (&insn
, lptr
))
4934 if ((insn
.tm
->flags
& FL_LP
)
4935 && cpu
!= V545LP
&& cpu
!= V546LP
)
4937 as_bad (_("Instruction '%s' requires an LP cpu version"),
4941 if ((insn
.tm
->flags
& FL_FAR
)
4942 && amode
!= far_mode
)
4944 as_bad (_("Instruction '%s' requires far mode addressing"),
4949 words
= build_insn (&insn
);
4951 /* Is this instruction in a delay slot? */
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.",
4963 words
, delay_slots
);
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? */
4980 if (insn
.tm
->flags
& FL_NR
)
4981 as_warn (_("'%s' is not repeatable. "
4982 "Resulting behavior is undefined."),
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."));
4991 /* Make sure we check the target of a repeat instruction. */
4992 if (insn
.tm
->flags
& B_REPEAT
)
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
)
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. */
5010 tic54x_adjust_symtab (void)
5012 if (symbol_rootP
== NULL
5013 || S_GET_STORAGE_CLASS (symbol_rootP
) != C_FILE
)
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
5034 FIXME -- obviously this isn't done yet. These locals still show up in the
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. */
5051 tic54x_undefined_symbol (char *name
)
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);
5073 /* Parse a name in an expression before the expression parser takes a stab at
5077 tic54x_parse_name (char *name ATTRIBUTE_UNUSED
,
5078 expressionS
*expn ATTRIBUTE_UNUSED
)
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);
5092 tc_gen_reloc (asection
*section
, fixS
*fixP
)
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
;
5110 const char *name
= S_GET_NAME (fixP
->fx_addsy
);
5113 as_fatal ("Cannot generate relocation type for symbol %s, code %s",
5114 name
, bfd_get_reloc_code_name (code
));
5120 /* Handle cons expressions. */
5123 tic54x_cons_fix_new (fragS
*frag
, int where
, int octets
, expressionS
*expn
,
5124 bfd_reloc_code_real_type r
)
5129 as_bad (_("Unsupported relocation size %d"), octets
);
5130 r
= BFD_RELOC_TIC54X_16_OF_23
;
5133 r
= BFD_RELOC_TIC54X_16_OF_23
;
5136 /* TI assembler always uses this, regardless of addressing mode. */
5138 r
= BFD_RELOC_TIC54X_23
;
5140 /* We never want to directly generate this; this is provided for
5141 stabs support only. */
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. */
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
)
5162 as_fatal ("Bad relocation type: 0x%02x", fixP
->fx_r_type
);
5164 case BFD_RELOC_TIC54X_MS7_OF_23
:
5165 val
= (val
>> 16) & 0x7F;
5167 case BFD_RELOC_TIC54X_16_OF_23
:
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;
5174 case BFD_RELOC_TIC54X_PARTLS7
:
5175 bfd_put_16 (stdoutput
,
5176 (bfd_get_16 (stdoutput
, buf
) & 0xFF80) | (val
& 0x7F),
5178 /* Indicate what we're actually writing, so that we don't get warnings
5179 about exceeding available space. */
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),
5190 case BFD_RELOC_TIC54X_23
:
5191 bfd_put_32 (stdoutput
,
5192 (bfd_get_32 (stdoutput
, buf
) & 0xFF800000) | val
,
5197 if (fixP
->fx_addsy
== NULL
&& fixP
->fx_pcrel
== 0)
5201 /* This is our chance to record section alignment
5202 don't need to do anything here, since BFD does the proper encoding. */
5205 md_section_align (segT segment ATTRIBUTE_UNUSED
, valueT section_size
)
5207 return section_size
;
5211 md_pcrel_from (fixS
*fixP ATTRIBUTE_UNUSED
)
5216 /* Mostly little-endian, but longwords (4 octets) get MS word stored
5220 tic54x_number_to_chars (char *buf
, valueT val
, int n
)
5223 number_to_chars_littleendian (buf
, val
, n
);
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
)
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
;
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"));
5264 as_warn (_("negative value ignored in %s"),
5265 bi
->type
== TYPE_SPACE
? ".space" :
5266 bi
->type
== TYPE_BES
? ".bes" : ".field");
5268 frag
->tc_frag_data
= frag
->fr_fix
= 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;
5286 symbol_set_frag (bi
->sym
, prev_frag
);
5287 /* This frag is no longer used. */
5288 growth
= -frag
->fr_fix
;
5290 frag
->tc_frag_data
= 0;
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;
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;
5312 symbol_set_frag (bi
->sym
, prev_frag
);
5313 /* This frag is no longer used. */
5314 growth
= -frag
->fr_fix
;
5316 frag
->tc_frag_data
= 0;
5319 if (bi
->type
== TYPE_SPACE
&& bi
->sym
)
5320 symbol_set_frag (bi
->sym
, prev_frag
);
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);
5333 frag
->fr_symbol
= 0;
5334 frag
->fr_opcode
= 0;
5341 tic54x_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
,
5342 segT seg ATTRIBUTE_UNUSED
,
5345 /* Offset is in bytes. */
5346 frag
->fr_offset
= (frag
->fr_next
->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
)
5370 /* If within .struct/.union, no auto line labels, please. */
5371 if (current_stag
!= NULL
)
5374 /* Disallow labels starting with "." */
5375 if (next_char
!= ':')
5377 if (*label_start
== '.')
5379 as_bad (_("Invalid label '%s'"), label_start
);
5384 if (is_end_of_line
[(unsigned char) next_char
])
5387 rest
= input_line_pointer
;
5388 if (nul_char
== '"')
5390 while (ISSPACE (next_char
))
5391 next_char
= *++rest
;
5392 if (next_char
!= '.')
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])));