1 /* tc-tic54x.c -- Assembly code for the Texas Instruments TMS320C54X
2 Copyright (C) 1999-2016 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 "struc-symbol.h"
54 #include "opcode/tic54x.h"
61 symbolS
*sym
; /* Symbol for this stag; value is offset. */
62 const char *name
; /* Shortcut to symbol name. */
63 bfd_vma size
; /* Size of struct/union. */
64 int current_bitfield_offset
; /* Temporary for tracking fields. */
66 struct stag_field
/* List of fields. */
69 bfd_vma offset
; /* Of start of this field. */
70 int bitfield_offset
; /* Of start of this field. */
71 struct stag
*stag
; /* If field is struct/union. */
72 struct stag_field
*next
;
74 /* For nesting; used only in stag construction. */
75 struct stag
*inner
; /* Enclosed .struct. */
76 struct stag
*outer
; /* Enclosing .struct. */
77 } *current_stag
= NULL
;
79 #define MAX_LINE 256 /* Lines longer than this are truncated by TI's asm. */
81 typedef struct _tic54x_insn
83 const insn_template
*tm
; /* Opcode template. */
85 char mnemonic
[MAX_LINE
]; /* Opcode name/mnemonic. */
86 char parmnemonic
[MAX_LINE
]; /* 2nd mnemonic of parallel insn. */
94 } operands
[MAX_OPERANDS
];
97 struct opstruct paroperands
[MAX_OPERANDS
];
101 int words
; /* Size of insn in 16-bit words. */
102 int using_default_dst
; /* Do we need to explicitly set an
103 omitted OP_DST operand? */
106 unsigned short word
; /* Final encoded opcode data. */
108 int r_nchars
; /* Relocation size. */
109 bfd_reloc_code_real_type r_type
; /* Relocation type. */
110 expressionS addr_expr
; /* Storage for unresolved expressions. */
116 VNONE
= 0, V541
= 1, V542
= 2, V543
= 3, V545
= 5, V548
= 8, V549
= 9,
117 V545LP
= 15, V546LP
= 16
122 c_mode
, /* 16-bit addresses. */
123 far_mode
/* >16-bit addresses. */
126 static segT stag_saved_seg
;
127 static subsegT stag_saved_subseg
;
129 const char comment_chars
[] = ";";
130 const char line_comment_chars
[] = ";*#"; /* At column zero only. */
131 const char line_separator_chars
[] = ""; /* Not permitted. */
133 int emitting_long
= 0;
135 /* Characters which indicate that this is a floating point constant. */
136 const char FLT_CHARS
[] = "fF";
138 /* Characters that can be used to separate mantissa from exp in FP
140 const char EXP_CHARS
[] = "eE";
142 const char *md_shortopts
= "";
144 #define OPTION_ADDRESS_MODE (OPTION_MD_BASE)
145 #define OPTION_CPU_VERSION (OPTION_ADDRESS_MODE + 1)
146 #define OPTION_COFF_VERSION (OPTION_CPU_VERSION + 1)
147 #define OPTION_STDERR_TO_FILE (OPTION_COFF_VERSION + 1)
149 struct option md_longopts
[] =
151 { "mfar-mode", no_argument
, NULL
, OPTION_ADDRESS_MODE
},
152 { "mf", no_argument
, NULL
, OPTION_ADDRESS_MODE
},
153 { "mcpu", required_argument
, NULL
, OPTION_CPU_VERSION
},
154 { "merrors-to-file", required_argument
, NULL
, OPTION_STDERR_TO_FILE
},
155 { "me", required_argument
, NULL
, OPTION_STDERR_TO_FILE
},
156 { NULL
, no_argument
, NULL
, 0},
159 size_t md_longopts_size
= sizeof (md_longopts
);
161 static int assembly_begun
= 0;
162 /* Addressing mode is not entirely implemented; the latest rev of the Other
163 assembler doesn't seem to make any distinction whatsoever; all relocations
164 are stored as extended relocatiosn. Older versions used REL16 vs RELEXT16,
165 but now it seems all relocations are RELEXT16. We use all RELEXT16.
167 The cpu version is kind of a waste of time as well. There is one
168 instruction (RND) for LP devices only, and several for devices with
169 extended addressing only. We include it for compatibility. */
170 static enum address_mode amode
= c_mode
;
171 static enum cpu_version cpu
= VNONE
;
173 /* Include string substitutions in listing? */
174 static int listing_sslist
= 0;
176 /* Did we do subsym substitutions on the line? */
177 static int substitution_line
= 0;
179 /* Last label seen. */
180 static symbolS
*last_label_seen
= NULL
;
182 /* This ensures that all new labels are unique. */
183 static int local_label_id
;
185 static struct hash_control
*subsym_recurse_hash
; /* Prevent infinite recurse. */
186 static struct hash_control
*math_hash
; /* Built-in math functions. */
187 /* Allow maximum levels of macro nesting; level 0 is the main substitution
188 symbol table. The other assembler only does 32 levels, so there! */
189 static struct hash_control
*subsym_hash
[100];
191 /* Keep track of local labels so we can substitute them before GAS sees them
192 since macros use their own 'namespace' for local labels, use a separate hash
194 We do our own local label handling 'cuz it's subtly different from the
197 We use our own macro nesting counter, since GAS overloads it when expanding
198 other things (like conditionals and repeat loops). */
199 static int macro_level
= 0;
200 static struct hash_control
*local_label_hash
[100];
201 /* Keep track of struct/union tags. */
202 static struct hash_control
*stag_hash
;
203 static struct hash_control
*op_hash
;
204 static struct hash_control
*parop_hash
;
205 static struct hash_control
*reg_hash
;
206 static struct hash_control
*mmreg_hash
;
207 static struct hash_control
*cc_hash
;
208 static struct hash_control
*cc2_hash
;
209 static struct hash_control
*cc3_hash
;
210 static struct hash_control
*sbit_hash
;
211 static struct hash_control
*misc_symbol_hash
;
213 /* Only word (et al.), align, or conditionals are allowed within
215 #define ILLEGAL_WITHIN_STRUCT() \
217 if (current_stag != NULL) \
219 as_bad (_("pseudo-op illegal within .struct/.union")); \
225 static void subsym_create_or_replace (char *, char *);
226 static char *subsym_lookup (char *, int);
227 static char *subsym_substitute (char *, int);
231 md_show_usage (FILE *stream
)
233 fprintf (stream
, _("C54x-specific command line options:\n"));
234 fprintf (stream
, _("-mfar-mode | -mf Use extended addressing\n"));
235 fprintf (stream
, _("-mcpu=<CPU version> Specify the CPU version\n"));
236 fprintf (stream
, _("-merrors-to-file <filename>\n"));
237 fprintf (stream
, _("-me <filename> Redirect errors to a file\n"));
240 /* Output a single character (upper octect is zero). */
243 tic54x_emit_char (char c
)
247 expn
.X_op
= O_constant
;
248 expn
.X_add_number
= c
;
249 emit_expr (&expn
, 2);
252 /* Walk backwards in the frag chain. */
255 frag_prev (fragS
*frag
, segT seg
)
257 segment_info_type
*seginfo
= seg_info (seg
);
260 for (fragp
= seginfo
->frchainP
->frch_root
; fragp
; fragp
= fragp
->fr_next
)
261 if (fragp
->fr_next
== frag
)
268 bit_offset_frag (fragS
*frag
, segT seg
)
272 if (frag
->fr_fix
== 0
273 && frag
->fr_opcode
== NULL
274 && frag
->tc_frag_data
== 0)
275 frag
= frag_prev (frag
, seg
);
282 /* Return the number of bits allocated in the most recent word, or zero if
283 none. .field/.space/.bes may leave words partially allocated. */
286 frag_bit_offset (fragS
*frag
, segT seg
)
288 frag
= bit_offset_frag (frag
, seg
);
291 return frag
->fr_opcode
!= NULL
? -1 : frag
->tc_frag_data
;
296 /* Read an expression from a C string; returns a pointer past the end of the
300 parse_expression (char *str
, expressionS
*expn
)
305 tmp
= input_line_pointer
; /* Save line pointer. */
306 input_line_pointer
= str
;
308 s
= input_line_pointer
;
309 input_line_pointer
= tmp
; /* Restore line pointer. */
310 return s
; /* Return pointer to where parsing stopped. */
313 /* .asg "character-string"|character-string, symbol
315 .eval is the only pseudo-op allowed to perform arithmetic on substitution
316 symbols. all other use of symbols defined with .asg are currently
320 tic54x_asg (int x ATTRIBUTE_UNUSED
)
325 int quoted
= *input_line_pointer
== '"';
327 ILLEGAL_WITHIN_STRUCT ();
332 str
= demand_copy_C_string (&len
);
333 c
= *input_line_pointer
;
337 str
= input_line_pointer
;
338 while ((c
= *input_line_pointer
) != ',')
340 if (is_end_of_line
[(int) *input_line_pointer
])
342 ++input_line_pointer
;
344 *input_line_pointer
= 0;
348 as_bad (_("Comma and symbol expected for '.asg STRING, SYMBOL'"));
349 ignore_rest_of_line ();
353 ++input_line_pointer
;
354 c
= get_symbol_name (&name
); /* Get terminator. */
355 if (!ISALPHA (*name
))
357 as_bad (_("symbols assigned with .asg must begin with a letter"));
358 ignore_rest_of_line ();
363 name
= xstrdup (name
);
364 subsym_create_or_replace (name
, str
);
365 (void) restore_line_pointer (c
);
366 demand_empty_rest_of_line ();
369 /* .eval expression, symbol
370 There's something screwy about this. The other assembler sometimes does and
371 sometimes doesn't substitute symbols defined with .eval.
372 We'll put the symbols into the subsym table as well as the normal symbol
373 table, since that's what works best. */
376 tic54x_eval (int x ATTRIBUTE_UNUSED
)
382 char valuestr
[32], *tmp
;
385 ILLEGAL_WITHIN_STRUCT ();
389 quoted
= *input_line_pointer
== '"';
391 ++input_line_pointer
;
392 value
= get_absolute_expression ();
395 if (*input_line_pointer
!= '"')
397 as_bad (_("Unterminated string after absolute expression"));
398 ignore_rest_of_line ();
401 ++input_line_pointer
;
403 if (*input_line_pointer
++ != ',')
405 as_bad (_("Comma and symbol expected for '.eval EXPR, SYMBOL'"));
406 ignore_rest_of_line ();
409 c
= get_symbol_name (&name
); /* Get terminator. */
410 name
= xstrdup (name
);
411 (void) restore_line_pointer (c
);
413 if (!ISALPHA (*name
))
415 as_bad (_("symbols assigned with .eval must begin with a letter"));
416 ignore_rest_of_line ();
419 symbolP
= symbol_new (name
, absolute_section
,
420 (valueT
) value
, &zero_address_frag
);
421 SF_SET_LOCAL (symbolP
);
422 symbol_table_insert (symbolP
);
424 /* The "other" assembler sometimes doesn't put .eval's in the subsym table
425 But since there's not written rule as to when, don't even bother trying
426 to match their behavior. */
427 sprintf (valuestr
, "%d", value
);
428 tmp
= xstrdup (valuestr
);
429 subsym_create_or_replace (name
, tmp
);
431 demand_empty_rest_of_line ();
434 /* .bss symbol, size [, [blocking flag] [, alignment flag]
436 alignment is to a longword boundary; blocking is to 128-word boundary.
438 1) if there is a hole in memory, this directive should attempt to fill it
439 (not yet implemented).
441 2) if the blocking flag is not set, allocate at the current SPC
442 otherwise, check to see if the current SPC plus the space to be
443 allocated crosses the page boundary (128 words).
444 if there's not enough space, create a hole and align with the next page
446 (not yet implemented). */
449 tic54x_bss (int x ATTRIBUTE_UNUSED
)
456 subsegT current_subseg
;
461 ILLEGAL_WITHIN_STRUCT ();
463 current_seg
= now_seg
; /* Save current seg. */
464 current_subseg
= now_subseg
; /* Save current subseg. */
466 c
= get_symbol_name (&name
); /* Get terminator. */
468 c
= * ++ input_line_pointer
;
471 as_bad (_(".bss size argument missing\n"));
472 ignore_rest_of_line ();
476 ++input_line_pointer
;
477 words
= get_absolute_expression ();
480 as_bad (_(".bss size %d < 0!"), words
);
481 ignore_rest_of_line ();
485 if (*input_line_pointer
== ',')
487 /* The blocking flag may be missing. */
488 ++input_line_pointer
;
489 if (*input_line_pointer
!= ',')
490 block
= get_absolute_expression ();
494 if (*input_line_pointer
== ',')
496 ++input_line_pointer
;
497 align
= get_absolute_expression ();
505 subseg_set (bss_section
, 0);
506 symbolP
= symbol_find_or_make (name
);
508 if (S_GET_SEGMENT (symbolP
) == bss_section
)
509 symbolP
->sy_frag
->fr_symbol
= (symbolS
*) NULL
;
511 symbol_set_frag (symbolP
, frag_now
);
512 p
= frag_var (rs_org
, 1, 1, (relax_substateT
) 0, symbolP
,
513 (offsetT
) (words
* OCTETS_PER_BYTE
), (char *) 0);
514 *p
= 0; /* Fill char. */
516 S_SET_SEGMENT (symbolP
, bss_section
);
518 /* The symbol may already have been created with a preceding
519 ".globl" directive -- be careful not to step on storage class
520 in that case. Otherwise, set it to static. */
521 if (S_GET_STORAGE_CLASS (symbolP
) != C_EXT
)
522 S_SET_STORAGE_CLASS (symbolP
, C_STAT
);
526 /* s_align eats end of line; restore it */
528 --input_line_pointer
;
532 bss_section
->flags
|= SEC_TIC54X_BLOCK
;
534 subseg_set (current_seg
, current_subseg
); /* Restore current seg. */
535 demand_empty_rest_of_line ();
539 stag_add_field_symbols (struct stag
*stag
,
543 const char *root_stag_name
)
546 struct stag_field
*field
= stag
->field
;
548 /* Construct a symbol for every field contained within this structure
549 including fields within structure fields. */
550 prefix
= concat (path
, *path
? "." : "", NULL
);
552 while (field
!= NULL
)
554 char *name
= concat (prefix
, field
->name
, NULL
);
559 sym
= symbol_new (name
, absolute_section
,
560 (field
->stag
? field
->offset
:
561 (valueT
) (base_offset
+ field
->offset
)),
564 symbol_table_insert (sym
);
570 replacement
= concat (S_GET_NAME (rootsym
), "+", root_stag_name
,
571 name
+ strlen (S_GET_NAME (rootsym
)), NULL
);
572 hash_insert (subsym_hash
[0], name
, replacement
);
575 /* Recurse if the field is a structure.
576 Note the field offset is relative to the outermost struct. */
577 if (field
->stag
!= NULL
)
578 stag_add_field_symbols (field
->stag
, name
,
580 rootsym
, root_stag_name
);
587 /* Keep track of stag fields so that when structures are nested we can add the
588 complete dereferencing symbols to the symbol table. */
591 stag_add_field (struct stag
*parent
,
596 struct stag_field
*sfield
= xmalloc (sizeof (struct stag_field
));
598 memset (sfield
, 0, sizeof (*sfield
));
599 sfield
->name
= xstrdup (name
);
600 sfield
->offset
= offset
;
601 sfield
->bitfield_offset
= parent
->current_bitfield_offset
;
603 if (parent
->field
== NULL
)
604 parent
->field
= sfield
;
607 struct stag_field
*sf
= parent
->field
;
608 while (sf
->next
!= NULL
)
612 /* Only create a symbol for this field if the parent has no name. */
613 if (!strncmp (".fake", parent
->name
, 5))
615 symbolS
*sym
= symbol_new (name
, absolute_section
,
616 (valueT
) offset
, &zero_address_frag
);
618 symbol_table_insert (sym
);
622 /* [STAG] .struct [OFFSET]
623 Start defining structure offsets (symbols in absolute section). */
626 tic54x_struct (int arg
)
628 int start_offset
= 0;
633 /* Starting a new struct, switch to absolute section. */
634 stag_saved_seg
= now_seg
;
635 stag_saved_subseg
= now_subseg
;
636 subseg_set (absolute_section
, 0);
638 /* Align the current pointer. */
639 else if (current_stag
->current_bitfield_offset
!= 0)
641 ++abs_section_offset
;
642 current_stag
->current_bitfield_offset
= 0;
645 /* Offset expression is only meaningful for global .structs. */
648 /* Offset is ignored in inner structs. */
650 if (!is_end_of_line
[(int) *input_line_pointer
])
651 start_offset
= get_absolute_expression ();
658 /* Nesting, link to outer one. */
659 current_stag
->inner
= (struct stag
*) xmalloc (sizeof (struct stag
));
660 memset (current_stag
->inner
, 0, sizeof (struct stag
));
661 current_stag
->inner
->outer
= current_stag
;
662 current_stag
= current_stag
->inner
;
664 as_warn (_("Offset on nested structures is ignored"));
665 start_offset
= abs_section_offset
;
669 current_stag
= (struct stag
*) xmalloc (sizeof (struct stag
));
670 memset (current_stag
, 0, sizeof (struct stag
));
671 abs_section_offset
= start_offset
;
673 current_stag
->is_union
= is_union
;
675 if (line_label
== NULL
)
677 static int struct_count
= 0;
678 char fake
[] = ".fake_stagNNNNNNN";
679 sprintf (fake
, ".fake_stag%d", struct_count
++);
680 current_stag
->sym
= symbol_new (fake
, absolute_section
,
681 (valueT
) abs_section_offset
,
686 char * label
= xstrdup (S_GET_NAME (line_label
));
687 current_stag
->sym
= symbol_new (label
,
689 (valueT
) abs_section_offset
,
693 current_stag
->name
= S_GET_NAME (current_stag
->sym
);
694 SF_SET_LOCAL (current_stag
->sym
);
695 /* Nested .structs don't go into the symbol table. */
696 if (current_stag
->outer
== NULL
)
697 symbol_table_insert (current_stag
->sym
);
702 /* [LABEL] .endstruct
703 finish defining structure offsets; optional LABEL's value will be the size
707 tic54x_endstruct (int is_union
)
711 !strncmp (current_stag
->name
, ".fake", 5) ? "" : current_stag
->name
;
713 if (!current_stag
|| current_stag
->is_union
!= is_union
)
715 as_bad (_(".end%s without preceding .%s"),
716 is_union
? "union" : "struct",
717 is_union
? "union" : "struct");
718 ignore_rest_of_line ();
722 /* Align end of structures. */
723 if (current_stag
->current_bitfield_offset
)
725 ++abs_section_offset
;
726 current_stag
->current_bitfield_offset
= 0;
729 if (current_stag
->is_union
)
730 size
= current_stag
->size
;
732 size
= abs_section_offset
- S_GET_VALUE (current_stag
->sym
);
733 if (line_label
!= NULL
)
735 S_SET_VALUE (line_label
, size
);
736 symbol_table_insert (line_label
);
740 /* Union size has already been calculated. */
741 if (!current_stag
->is_union
)
742 current_stag
->size
= size
;
743 /* Nested .structs don't get put in the stag table. */
744 if (current_stag
->outer
== NULL
)
746 hash_insert (stag_hash
, current_stag
->name
, current_stag
);
747 stag_add_field_symbols (current_stag
, path
,
748 S_GET_VALUE (current_stag
->sym
),
751 current_stag
= current_stag
->outer
;
753 /* If this is a nested .struct/.union, add it as a field to the enclosing
754 one. otherwise, restore the section we were in. */
755 if (current_stag
!= NULL
)
757 stag_add_field (current_stag
, current_stag
->inner
->name
,
758 S_GET_VALUE (current_stag
->inner
->sym
),
759 current_stag
->inner
);
762 subseg_set (stag_saved_seg
, stag_saved_subseg
);
766 Reference a structure within a structure, as a sized field with an optional
768 If used outside of a .struct/.endstruct, overlays the given structure
769 format on the existing allocated space. */
772 tic54x_tag (int ignore ATTRIBUTE_UNUSED
)
775 int c
= get_symbol_name (&name
);
776 struct stag
*stag
= (struct stag
*) hash_find (stag_hash
, name
);
781 as_bad (_("Unrecognized struct/union tag '%s'"), name
);
783 as_bad (_(".tag requires a structure tag"));
784 ignore_rest_of_line ();
787 if (line_label
== NULL
)
789 as_bad (_("Label required for .tag"));
790 ignore_rest_of_line ();
797 label
= xstrdup (S_GET_NAME (line_label
));
798 if (current_stag
!= NULL
)
799 stag_add_field (current_stag
, label
,
800 abs_section_offset
- S_GET_VALUE (current_stag
->sym
),
804 symbolS
*sym
= symbol_find (label
);
808 as_bad (_(".tag target '%s' undefined"), label
);
809 ignore_rest_of_line ();
813 stag_add_field_symbols (stag
, S_GET_NAME (sym
),
814 S_GET_VALUE (stag
->sym
), sym
, stag
->name
);
819 /* Bump by the struct size, but only if we're within a .struct section. */
820 if (current_stag
!= NULL
&& !current_stag
->is_union
)
821 abs_section_offset
+= stag
->size
;
823 (void) restore_line_pointer (c
);
824 demand_empty_rest_of_line ();
828 /* Handle all .byte, .char, .double, .field, .float, .half, .int, .long,
829 .short, .string, .ubyte, .uchar, .uhalf, .uint, .ulong, .ushort, .uword,
833 tic54x_struct_field (int type
)
837 int new_bitfield_offset
= 0;
838 int field_align
= current_stag
->current_bitfield_offset
!= 0;
839 int longword_align
= 0;
842 if (!is_end_of_line
[(int) *input_line_pointer
])
843 count
= get_absolute_expression ();
859 case '*': /* String. */
868 case '.': /* Bitfield. */
870 if (count
< 1 || count
> 32)
872 as_bad (_(".field count '%d' out of range (1 <= X <= 32)"), count
);
873 ignore_rest_of_line ();
876 if (current_stag
->current_bitfield_offset
+ count
> 16)
878 /* Set the appropriate size and new field offset. */
888 new_bitfield_offset
= count
- 16;
891 new_bitfield_offset
= count
;
896 new_bitfield_offset
= current_stag
->current_bitfield_offset
+ count
;
900 as_bad (_("Unrecognized field type '%c'"), type
);
901 ignore_rest_of_line ();
907 /* Align to the actual starting position of the field. */
908 current_stag
->current_bitfield_offset
= 0;
909 ++abs_section_offset
;
911 /* Align to longword boundary. */
912 if (longword_align
&& (abs_section_offset
& 0x1))
913 ++abs_section_offset
;
915 if (line_label
== NULL
)
917 static int fieldno
= 0;
918 char fake
[] = ".fake_fieldNNNNN";
920 sprintf (fake
, ".fake_field%d", fieldno
++);
921 stag_add_field (current_stag
, fake
,
922 abs_section_offset
- S_GET_VALUE (current_stag
->sym
),
929 label
= xstrdup (S_GET_NAME (line_label
));
930 stag_add_field (current_stag
, label
,
931 abs_section_offset
- S_GET_VALUE (current_stag
->sym
),
936 if (current_stag
->is_union
)
938 /* Note we treat the element as if it were an array of COUNT. */
939 if (current_stag
->size
< (unsigned) size
* count
)
940 current_stag
->size
= size
* count
;
944 abs_section_offset
+= (unsigned) size
* count
;
945 current_stag
->current_bitfield_offset
= new_bitfield_offset
;
950 /* Handle .byte, .word. .int, .long and all variants. */
953 tic54x_cons (int type
)
958 /* If we're within a .struct construct, don't actually allocate space. */
959 if (current_stag
!= NULL
)
961 tic54x_struct_field (type
);
965 #ifdef md_flush_pending_output
966 md_flush_pending_output ();
969 generate_lineno_debug ();
971 /* Align long words to long word boundaries (4 octets). */
972 if (type
== 'l' || type
== 'L')
974 frag_align (2, 0, 2);
975 /* If there's a label, assign it to the first allocated word. */
976 if (line_label
!= NULL
)
978 symbol_set_frag (line_label
, frag_now
);
979 S_SET_VALUE (line_label
, frag_now_fix ());
1003 if (*input_line_pointer
== '"')
1005 input_line_pointer
++;
1006 while (is_a_char (c
= next_char_of_string ()))
1007 tic54x_emit_char (c
);
1008 know (input_line_pointer
[-1] == '\"');
1014 input_line_pointer
= parse_expression (input_line_pointer
, &expn
);
1015 if (expn
.X_op
== O_constant
)
1017 offsetT value
= expn
.X_add_number
;
1018 /* Truncate overflows. */
1022 if ((value
> 0 && value
> 0xFF)
1023 || (value
< 0 && value
< - 0x100))
1024 as_warn (_("Overflow in expression, truncated to 8 bits"));
1027 if ((value
> 0 && value
> 0xFFFF)
1028 || (value
< 0 && value
< - 0x10000))
1029 as_warn (_("Overflow in expression, truncated to 16 bits"));
1033 if (expn
.X_op
!= O_constant
&& octets
< 2)
1035 /* Disallow .byte with a non constant expression that will
1036 require relocation. */
1037 as_bad (_("Relocatable values require at least WORD storage"));
1038 ignore_rest_of_line ();
1042 if (expn
.X_op
!= O_constant
1046 /* FIXME -- at one point TI tools used to output REL16
1047 relocations, but I don't think the latest tools do at all
1048 The current tools output extended relocations regardless of
1049 the addressing mode (I actually think that ".c_mode" is
1050 totally ignored in the latest tools). */
1053 emit_expr (&expn
, 4);
1059 emitting_long
= octets
== 4;
1060 emit_expr (&expn
, (octets
== 1) ? 2 : octets
);
1065 while (*input_line_pointer
++ == ',');
1067 input_line_pointer
--; /* Put terminator back into stream. */
1068 demand_empty_rest_of_line ();
1071 /* .global <symbol>[,...,<symbolN>]
1072 .def <symbol>[,...,<symbolN>]
1073 .ref <symbol>[,...,<symbolN>]
1075 These all identify global symbols.
1077 .def means the symbol is defined in the current module and can be accessed
1078 by other files. The symbol should be placed in the symbol table.
1080 .ref means the symbol is used in the current module but defined in another
1081 module. The linker is to resolve this symbol's definition at link time.
1083 .global should act as a .ref or .def, as needed.
1085 global, def and ref all have symbol storage classes of C_EXT.
1087 I can't identify any difference in how the "other" c54x assembler treats
1088 these, so we ignore the type here. */
1091 tic54x_global (int type
)
1098 as_warn (_("Use of .def/.ref is deprecated. Use .global instead"));
1100 ILLEGAL_WITHIN_STRUCT ();
1104 c
= get_symbol_name (&name
);
1105 symbolP
= symbol_find_or_make (name
);
1106 c
= restore_line_pointer (c
);
1108 S_SET_STORAGE_CLASS (symbolP
, C_EXT
);
1111 input_line_pointer
++;
1112 if (is_end_of_line
[(int) *input_line_pointer
])
1113 c
= *input_line_pointer
;
1118 demand_empty_rest_of_line ();
1121 /* Remove the symbol from the local label hash lookup. */
1124 tic54x_remove_local_label (const char *key
, void *value ATTRIBUTE_UNUSED
)
1126 void *elem
= hash_delete (local_label_hash
[macro_level
], key
, FALSE
);
1130 /* Reset all local labels. */
1133 tic54x_clear_local_labels (int ignored ATTRIBUTE_UNUSED
)
1135 hash_traverse (local_label_hash
[macro_level
], tic54x_remove_local_label
);
1140 .sect "section name"
1143 make sure local labels get cleared when changing sections
1145 ARG is 't' for text, 'd' for data, or '*' for a named section
1147 For compatibility, '*' sections are SEC_CODE if instructions are
1148 encountered, or SEC_DATA if not.
1152 tic54x_sect (int arg
)
1154 ILLEGAL_WITHIN_STRUCT ();
1156 /* Local labels are cleared when changing sections. */
1157 tic54x_clear_local_labels (0);
1161 else if (arg
== 'd')
1168 /* If there are quotes, remove them. */
1169 if (*input_line_pointer
== '"')
1171 name
= demand_copy_C_string (&len
);
1172 demand_empty_rest_of_line ();
1173 name
= strcpy (xmalloc (len
+ 10), name
);
1179 c
= get_symbol_name (&name
);
1181 name
= strcpy (xmalloc (len
+ 10), name
);
1182 (void) restore_line_pointer (c
);
1183 demand_empty_rest_of_line ();
1186 /* Make sure all named initialized sections flagged properly. If we
1187 encounter instructions, we'll flag it with SEC_CODE as well. */
1188 strcat (name
, ",\"w\"\n");
1189 input_scrub_insert_line (name
);
1190 obj_coff_section (0);
1192 /* If there was a line label, make sure that it gets assigned the proper
1193 section. This is for compatibility, even though the actual behavior
1194 is not explicitly defined. For consistency, we make .sect behave
1195 like .usect, since that is probably what people expect. */
1196 if (line_label
!= NULL
)
1198 S_SET_SEGMENT (line_label
, now_seg
);
1199 symbol_set_frag (line_label
, frag_now
);
1200 S_SET_VALUE (line_label
, frag_now_fix ());
1201 if (S_GET_STORAGE_CLASS (line_label
) != C_EXT
)
1202 S_SET_STORAGE_CLASS (line_label
, C_LABEL
);
1207 /* [symbol] .space space_in_bits
1208 [symbol] .bes space_in_bits
1209 BES puts the symbol at the *last* word allocated
1211 cribbed from s_space. */
1214 tic54x_space (int arg
)
1220 int bits_per_byte
= (OCTETS_PER_BYTE
* 8);
1222 symbolS
*label
= line_label
;
1225 ILLEGAL_WITHIN_STRUCT ();
1227 #ifdef md_flush_pending_output
1228 md_flush_pending_output ();
1231 /* Read the bit count. */
1234 /* Some expressions are unresolvable until later in the assembly pass;
1235 postpone until relaxation/fixup. we also have to postpone if a previous
1236 partial allocation has not been completed yet. */
1237 if (expn
.X_op
!= O_constant
|| frag_bit_offset (frag_now
, now_seg
) == -1)
1239 struct bit_info
*bi
= xmalloc (sizeof (struct bit_info
));
1244 p
= frag_var (rs_machine_dependent
,
1245 65536 * 2, 1, (relax_substateT
) 0,
1246 make_expr_symbol (&expn
), (offsetT
) 0,
1254 /* Reduce the required size by any bit offsets currently left over
1255 from a previous .space/.bes/.field directive. */
1256 bit_offset
= frag_now
->tc_frag_data
;
1257 if (bit_offset
!= 0 && bit_offset
< 16)
1259 int spare_bits
= bits_per_byte
- bit_offset
;
1261 if (spare_bits
>= expn
.X_add_number
)
1263 /* Don't have to do anything; sufficient bits have already been
1264 allocated; just point the label to the right place. */
1267 symbol_set_frag (label
, frag_now
);
1268 S_SET_VALUE (label
, frag_now_fix () - 1);
1271 frag_now
->tc_frag_data
+= expn
.X_add_number
;
1274 expn
.X_add_number
-= spare_bits
;
1275 /* Set the label to point to the first word allocated, which in this
1276 case is the previous word, which was only partially filled. */
1277 if (!bes
&& label
!= NULL
)
1279 symbol_set_frag (label
, frag_now
);
1280 S_SET_VALUE (label
, frag_now_fix () - 1);
1284 /* Convert bits to bytes/words and octets, rounding up. */
1285 words
= ((expn
.X_add_number
+ bits_per_byte
- 1) / bits_per_byte
);
1286 /* How many do we have left over? */
1287 bit_offset
= expn
.X_add_number
% bits_per_byte
;
1288 octets
= words
* OCTETS_PER_BYTE
;
1291 as_warn (_(".space/.bes repeat count is negative, ignored"));
1294 else if (octets
== 0)
1296 as_warn (_(".space/.bes repeat count is zero, ignored"));
1300 /* If we are in the absolute section, just bump the offset. */
1301 if (now_seg
== absolute_section
)
1303 abs_section_offset
+= words
;
1304 if (bes
&& label
!= NULL
)
1305 S_SET_VALUE (label
, abs_section_offset
- 1);
1306 frag_now
->tc_frag_data
= bit_offset
;
1311 p
= frag_var (rs_fill
, 1, 1,
1312 (relax_substateT
) 0, (symbolS
*) 0,
1313 (offsetT
) octets
, (char *) 0);
1315 /* Make note of how many bits of this word we've allocated so far. */
1316 frag_now
->tc_frag_data
= bit_offset
;
1318 /* .bes puts label at *last* word allocated. */
1319 if (bes
&& label
!= NULL
)
1321 symbol_set_frag (label
, frag_now
);
1322 S_SET_VALUE (label
, frag_now_fix () - 1);
1330 demand_empty_rest_of_line ();
1333 /* [symbol] .usect "section-name", size-in-words
1334 [, [blocking-flag] [, alignment-flag]]
1336 Uninitialized section.
1337 Non-zero blocking means that if the section would cross a page (128-word)
1338 boundary, it will be page-aligned.
1339 Non-zero alignment aligns on a longword boundary.
1341 Has no effect on the current section. */
1344 tic54x_usect (int x ATTRIBUTE_UNUSED
)
1351 int size
, blocking_flag
, alignment_flag
;
1353 subsegT current_subseg
;
1356 ILLEGAL_WITHIN_STRUCT ();
1358 current_seg
= now_seg
; /* Save current seg. */
1359 current_subseg
= now_subseg
; /* Save current subseg. */
1361 c
= get_symbol_name (§ion_name
); /* Get terminator. */
1362 name
= xstrdup (section_name
);
1363 c
= restore_line_pointer (c
);
1366 ++input_line_pointer
;
1369 as_bad (_("Missing size argument"));
1370 ignore_rest_of_line ();
1374 size
= get_absolute_expression ();
1376 /* Read a possibly present third argument (blocking flag). */
1377 if (*input_line_pointer
== ',')
1379 ++input_line_pointer
;
1380 if (*input_line_pointer
!= ',')
1381 blocking_flag
= get_absolute_expression ();
1385 /* Read a possibly present fourth argument (alignment flag). */
1386 if (*input_line_pointer
== ',')
1388 ++input_line_pointer
;
1389 alignment_flag
= get_absolute_expression ();
1395 blocking_flag
= alignment_flag
= 0;
1397 seg
= subseg_new (name
, 0);
1398 flags
= bfd_get_section_flags (stdoutput
, seg
) | SEC_ALLOC
;
1402 /* s_align eats end of line; restore it. */
1404 --input_line_pointer
;
1407 if (line_label
!= NULL
)
1409 S_SET_SEGMENT (line_label
, seg
);
1410 symbol_set_frag (line_label
, frag_now
);
1411 S_SET_VALUE (line_label
, frag_now_fix ());
1412 /* Set scl to label, since that's what TI does. */
1413 if (S_GET_STORAGE_CLASS (line_label
) != C_EXT
)
1414 S_SET_STORAGE_CLASS (line_label
, C_LABEL
);
1417 seg_info (seg
)->bss
= 1; /* Uninitialized data. */
1419 p
= frag_var (rs_fill
, 1, 1,
1420 (relax_substateT
) 0, (symbolS
*) line_label
,
1421 size
* OCTETS_PER_BYTE
, (char *) 0);
1425 flags
|= SEC_TIC54X_BLOCK
;
1427 if (!bfd_set_section_flags (stdoutput
, seg
, flags
))
1428 as_warn (_("Error setting flags for \"%s\": %s"), name
,
1429 bfd_errmsg (bfd_get_error ()));
1431 subseg_set (current_seg
, current_subseg
); /* Restore current seg. */
1432 demand_empty_rest_of_line ();
1435 static enum cpu_version
1436 lookup_version (const char *ver
)
1438 enum cpu_version version
= VNONE
;
1440 if (ver
[0] == '5' && ver
[1] == '4')
1442 if (strlen (ver
) == 3
1443 && (ver
[2] == '1' || ver
[2] == '2' || ver
[2] == '3'
1444 || ver
[2] == '5' || ver
[2] == '8' || ver
[2] == '9'))
1445 version
= ver
[2] - '0';
1446 else if (strlen (ver
) == 5
1447 && TOUPPER (ver
[3]) == 'L'
1448 && TOUPPER (ver
[4]) == 'P'
1449 && (ver
[2] == '5' || ver
[2] == '6'))
1450 version
= ver
[2] - '0' + 10;
1457 set_cpu (enum cpu_version version
)
1460 if (version
== V545LP
|| version
== V546LP
)
1462 symbolS
*symbolP
= symbol_new ("__allow_lp", absolute_section
,
1463 (valueT
) 1, &zero_address_frag
);
1464 SF_SET_LOCAL (symbolP
);
1465 symbol_table_insert (symbolP
);
1469 /* .version cpu-version
1470 cpu-version may be one of the following:
1480 This is for compatibility only. It currently has no affect on assembly. */
1481 static int cpu_needs_set
= 1;
1484 tic54x_version (int x ATTRIBUTE_UNUSED
)
1486 enum cpu_version version
= VNONE
;
1487 enum cpu_version old_version
= cpu
;
1491 ILLEGAL_WITHIN_STRUCT ();
1494 ver
= input_line_pointer
;
1495 while (!is_end_of_line
[(int) *input_line_pointer
])
1496 ++input_line_pointer
;
1497 c
= *input_line_pointer
;
1498 *input_line_pointer
= 0;
1500 version
= lookup_version (ver
);
1502 if (cpu
!= VNONE
&& cpu
!= version
)
1503 as_warn (_("CPU version has already been set"));
1505 if (version
== VNONE
)
1507 as_bad (_("Unrecognized version '%s'"), ver
);
1508 ignore_rest_of_line ();
1511 else if (assembly_begun
&& version
!= old_version
)
1513 as_bad (_("Changing of CPU version on the fly not supported"));
1514 ignore_rest_of_line ();
1520 *input_line_pointer
= c
;
1521 demand_empty_rest_of_line ();
1524 /* 'f' = float, 'x' = xfloat, 'd' = double, 'l' = ldouble. */
1527 tic54x_float_cons (int type
)
1529 if (current_stag
!= 0)
1530 tic54x_struct_field ('f');
1532 #ifdef md_flush_pending_output
1533 md_flush_pending_output ();
1536 /* Align to long word boundary (4 octets) unless it's ".xfloat". */
1539 frag_align (2, 0, 2);
1540 /* If there's a label, assign it to the first allocated word. */
1541 if (line_label
!= NULL
)
1543 symbol_set_frag (line_label
, frag_now
);
1544 S_SET_VALUE (line_label
, frag_now_fix ());
1551 /* The argument is capitalized if it should be zero-terminated
1552 's' is normal string with upper 8-bits zero-filled, 'p' is packed.
1553 Code copied from stringer, and slightly modified so that strings are packed
1554 and encoded into the correct octets. */
1557 tic54x_stringer (int type
)
1560 int append_zero
= type
== 'S' || type
== 'P';
1561 int packed
= type
== 'p' || type
== 'P';
1562 int last_char
= -1; /* Packed strings need two bytes at a time to encode. */
1564 if (current_stag
!= NULL
)
1566 tic54x_struct_field ('*');
1570 #ifdef md_flush_pending_output
1571 md_flush_pending_output ();
1574 c
= ','; /* Do loop. */
1578 switch (*input_line_pointer
)
1582 unsigned short value
= get_absolute_expression ();
1583 FRAG_APPEND_1_CHAR ( value
& 0xFF);
1584 FRAG_APPEND_1_CHAR ((value
>> 8) & 0xFF);
1588 ++input_line_pointer
; /* -> 1st char of string. */
1589 while (is_a_char (c
= next_char_of_string ()))
1593 FRAG_APPEND_1_CHAR (c
);
1594 FRAG_APPEND_1_CHAR (0);
1598 /* Packed strings are filled MS octet first. */
1599 if (last_char
== -1)
1603 FRAG_APPEND_1_CHAR (c
);
1604 FRAG_APPEND_1_CHAR (last_char
);
1611 if (packed
&& last_char
!= -1)
1613 FRAG_APPEND_1_CHAR (0);
1614 FRAG_APPEND_1_CHAR (last_char
);
1619 FRAG_APPEND_1_CHAR (0);
1620 FRAG_APPEND_1_CHAR (0);
1623 know (input_line_pointer
[-1] == '\"');
1627 c
= *input_line_pointer
;
1628 if (!is_end_of_line
[c
])
1629 ++input_line_pointer
;
1632 /* Finish up any leftover packed string. */
1633 if (packed
&& last_char
!= -1)
1635 FRAG_APPEND_1_CHAR (0);
1636 FRAG_APPEND_1_CHAR (last_char
);
1638 demand_empty_rest_of_line ();
1642 tic54x_p2align (int arg ATTRIBUTE_UNUSED
)
1644 as_bad (_("p2align not supported on this target"));
1648 tic54x_align_words (int arg
)
1650 /* Only ".align" with no argument is allowed within .struct/.union. */
1653 if (!is_end_of_line
[(int) *input_line_pointer
])
1656 as_warn (_("Argument to .even ignored"));
1658 count
= get_absolute_expression ();
1661 if (current_stag
!= NULL
&& arg
== 128)
1663 if (current_stag
->current_bitfield_offset
!= 0)
1665 current_stag
->current_bitfield_offset
= 0;
1666 ++abs_section_offset
;
1668 demand_empty_rest_of_line ();
1672 ILLEGAL_WITHIN_STRUCT ();
1674 s_align_bytes (count
<< 1);
1677 /* Initialize multiple-bit fields withing a single word of memory. */
1680 tic54x_field (int ignore ATTRIBUTE_UNUSED
)
1686 symbolS
*label
= line_label
;
1688 if (current_stag
!= NULL
)
1690 tic54x_struct_field ('.');
1694 input_line_pointer
= parse_expression (input_line_pointer
, &expn
);
1696 if (*input_line_pointer
== ',')
1698 ++input_line_pointer
;
1699 size
= get_absolute_expression ();
1700 if (size
< 1 || size
> 32)
1702 as_bad (_("Invalid field size, must be from 1 to 32"));
1703 ignore_rest_of_line ();
1708 /* Truncate values to the field width. */
1709 if (expn
.X_op
!= O_constant
)
1711 /* If the expression value is relocatable, the field size *must*
1715 as_bad (_("field size must be 16 when value is relocatable"));
1716 ignore_rest_of_line ();
1720 frag_now
->tc_frag_data
= 0;
1721 emit_expr (&expn
, 2);
1725 unsigned long fmask
= (size
== 32) ? 0xFFFFFFFF : (1ul << size
) - 1;
1727 value
= expn
.X_add_number
;
1728 expn
.X_add_number
&= fmask
;
1729 if (value
!= (valueT
) expn
.X_add_number
)
1730 as_warn (_("field value truncated"));
1731 value
= expn
.X_add_number
;
1732 /* Bits are stored MS first. */
1735 frag_now
->tc_frag_data
= 0;
1737 md_number_to_chars (p
, (value
>> (size
- 16)) & 0xFFFF, 2);
1742 int bit_offset
= frag_bit_offset (frag_now
, now_seg
);
1744 fragS
*alloc_frag
= bit_offset_frag (frag_now
, now_seg
);
1745 if (bit_offset
== -1)
1747 struct bit_info
*bi
= xmalloc (sizeof (struct bit_info
));
1748 /* We don't know the previous offset at this time, so store the
1749 info we need and figure it out later. */
1750 expressionS size_exp
;
1752 size_exp
.X_op
= O_constant
;
1753 size_exp
.X_add_number
= size
;
1755 bi
->type
= TYPE_FIELD
;
1757 p
= frag_var (rs_machine_dependent
,
1758 4, 1, (relax_substateT
) 0,
1759 make_expr_symbol (&size_exp
), (offsetT
) 0,
1763 else if (bit_offset
== 0 || bit_offset
+ size
> 16)
1765 /* Align a new field. */
1767 frag_now
->tc_frag_data
= 0;
1768 alloc_frag
= frag_now
;
1772 /* Put the new value entirely within the existing one. */
1773 p
= alloc_frag
== frag_now
?
1774 frag_now
->fr_literal
+ frag_now_fix_octets () - 2 :
1775 alloc_frag
->fr_literal
;
1778 symbol_set_frag (label
, alloc_frag
);
1779 if (alloc_frag
== frag_now
)
1780 S_SET_VALUE (label
, frag_now_fix () - 1);
1784 value
<<= 16 - alloc_frag
->tc_frag_data
- size
;
1786 /* OR in existing value. */
1787 if (alloc_frag
->tc_frag_data
)
1788 value
|= ((unsigned short) p
[1] << 8) | p
[0];
1789 md_number_to_chars (p
, value
, 2);
1790 alloc_frag
->tc_frag_data
+= size
;
1791 if (alloc_frag
->tc_frag_data
== 16)
1792 alloc_frag
->tc_frag_data
= 0;
1796 demand_empty_rest_of_line ();
1799 /* Ideally, we want to check SEC_LOAD and SEC_HAS_CONTENTS, but those aren't
1800 available yet. seg_info ()->bss is the next best thing. */
1803 tic54x_initialized_section (segT seg
)
1805 return !seg_info (seg
)->bss
;
1808 /* .clink ["section name"]
1810 Marks the section as conditionally linked (link only if contents are
1811 referenced elsewhere.
1812 Without a name, refers to the current initialized section.
1813 Name is required for uninitialized sections. */
1816 tic54x_clink (int ignored ATTRIBUTE_UNUSED
)
1820 ILLEGAL_WITHIN_STRUCT ();
1822 if (*input_line_pointer
== '\"')
1824 char *section_name
= ++input_line_pointer
;
1827 while (is_a_char (next_char_of_string ()))
1829 know (input_line_pointer
[-1] == '\"');
1830 input_line_pointer
[-1] = 0;
1831 name
= xstrdup (section_name
);
1833 seg
= bfd_get_section_by_name (stdoutput
, name
);
1836 as_bad (_("Unrecognized section '%s'"), section_name
);
1837 ignore_rest_of_line ();
1843 if (!tic54x_initialized_section (seg
))
1845 as_bad (_("Current section is unitialized, "
1846 "section name required for .clink"));
1847 ignore_rest_of_line ();
1852 seg
->flags
|= SEC_TIC54X_CLINK
;
1854 demand_empty_rest_of_line ();
1857 /* Change the default include directory to be the current source file's
1858 directory, instead of the current working directory. If DOT is non-zero,
1859 set to "." instead. */
1862 tic54x_set_default_include (int dot
)
1864 const char *dir
= ".";
1869 const char *curfile
;
1872 curfile
= as_where (&lineno
);
1873 dir
= xstrdup (curfile
);
1874 tmp
= strrchr (dir
, '/');
1882 if (include_dir_count
== 0)
1884 include_dirs
= XNEWVEC (const char *, 1);
1885 include_dir_count
= 1;
1887 include_dirs
[0] = dir
;
1888 if (len
> include_dir_maxlen
)
1889 include_dir_maxlen
= len
;
1891 else if (include_dirs
!= NULL
)
1892 include_dirs
[0] = ".";
1895 /* .include "filename" | filename
1896 .copy "filename" | filename
1898 FIXME 'include' file should be omitted from any output listing,
1899 'copy' should be included in any output listing
1900 FIXME -- prevent any included files from changing listing (compat only)
1901 FIXME -- need to include source file directory in search path; what's a
1902 good way to do this?
1904 Entering/exiting included/copied file clears all local labels. */
1907 tic54x_include (int ignored ATTRIBUTE_UNUSED
)
1909 char newblock
[] = " .newblock\n";
1914 ILLEGAL_WITHIN_STRUCT ();
1918 if (*input_line_pointer
== '"')
1920 filename
= demand_copy_C_string (&len
);
1921 demand_empty_rest_of_line ();
1925 filename
= input_line_pointer
;
1926 while (!is_end_of_line
[(int) *input_line_pointer
])
1927 ++input_line_pointer
;
1928 c
= *input_line_pointer
;
1929 *input_line_pointer
= '\0';
1930 filename
= xstrdup (filename
);
1931 *input_line_pointer
= c
;
1932 demand_empty_rest_of_line ();
1934 /* Insert a partial line with the filename (for the sake of s_include)
1936 The included file will be inserted before the newblock, so that the
1937 newblock is executed after the included file is processed. */
1938 input
= xmalloc (sizeof (newblock
) + strlen (filename
) + 4);
1939 sprintf (input
, "\"%s\"\n%s", filename
, newblock
);
1940 input_scrub_insert_line (input
);
1942 tic54x_clear_local_labels (0);
1944 tic54x_set_default_include (0);
1950 tic54x_message (int type
)
1956 ILLEGAL_WITHIN_STRUCT ();
1958 if (*input_line_pointer
== '"')
1959 msg
= demand_copy_C_string (&len
);
1962 msg
= input_line_pointer
;
1963 while (!is_end_of_line
[(int) *input_line_pointer
])
1964 ++input_line_pointer
;
1965 c
= *input_line_pointer
;
1966 *input_line_pointer
= 0;
1967 msg
= xstrdup (msg
);
1968 *input_line_pointer
= c
;
1974 as_tsktsk ("%s", msg
);
1977 as_warn ("%s", msg
);
1984 demand_empty_rest_of_line ();
1988 Define a special symbol that refers to the loadtime address rather than the
1989 runtime address within the current section.
1991 This symbol gets a special storage class so that when it is resolved, it is
1992 resolved relative to the load address (lma) of the section rather than the
1993 run address (vma). */
1996 tic54x_label (int ignored ATTRIBUTE_UNUSED
)
2002 ILLEGAL_WITHIN_STRUCT ();
2004 c
= get_symbol_name (&name
);
2005 symbolP
= colon (name
);
2006 S_SET_STORAGE_CLASS (symbolP
, C_STATLAB
);
2008 (void) restore_line_pointer (c
);
2009 demand_empty_rest_of_line ();
2013 Install all memory-mapped register names into the symbol table as
2014 absolute local symbols. */
2017 tic54x_mmregs (int ignored ATTRIBUTE_UNUSED
)
2021 ILLEGAL_WITHIN_STRUCT ();
2023 for (sym
= (symbol
*) mmregs
; sym
->name
; sym
++)
2025 symbolS
*symbolP
= symbol_new (sym
->name
, absolute_section
,
2026 (valueT
) sym
->value
, &zero_address_frag
);
2027 SF_SET_LOCAL (symbolP
);
2028 symbol_table_insert (symbolP
);
2033 Count defaults to 1024. */
2036 tic54x_loop (int count
)
2038 ILLEGAL_WITHIN_STRUCT ();
2041 if (!is_end_of_line
[(int) *input_line_pointer
])
2042 count
= get_absolute_expression ();
2044 do_repeat (count
, "LOOP", "ENDLOOP");
2047 /* Normally, endloop gets eaten by the preceding loop. */
2050 tic54x_endloop (int ignore ATTRIBUTE_UNUSED
)
2052 as_bad (_("ENDLOOP without corresponding LOOP"));
2053 ignore_rest_of_line ();
2056 /* .break [condition]. */
2059 tic54x_break (int ignore ATTRIBUTE_UNUSED
)
2063 ILLEGAL_WITHIN_STRUCT ();
2066 if (!is_end_of_line
[(int) *input_line_pointer
])
2067 cond
= get_absolute_expression ();
2070 end_repeat (substitution_line
? 1 : 0);
2074 set_address_mode (int mode
)
2077 if (mode
== far_mode
)
2079 symbolS
*symbolP
= symbol_new ("__allow_far", absolute_section
,
2080 (valueT
) 1, &zero_address_frag
);
2081 SF_SET_LOCAL (symbolP
);
2082 symbol_table_insert (symbolP
);
2086 static int address_mode_needs_set
= 1;
2089 tic54x_address_mode (int mode
)
2091 if (assembly_begun
&& amode
!= (unsigned) mode
)
2093 as_bad (_("Mixing of normal and extended addressing not supported"));
2094 ignore_rest_of_line ();
2097 if (mode
== far_mode
&& cpu
!= VNONE
&& cpu
!= V548
&& cpu
!= V549
)
2099 as_bad (_("Extended addressing not supported on the specified CPU"));
2100 ignore_rest_of_line ();
2104 set_address_mode (mode
);
2105 demand_empty_rest_of_line ();
2108 /* .sblock "section"|section [,...,"section"|section]
2109 Designate initialized sections for blocking. */
2112 tic54x_sblock (int ignore ATTRIBUTE_UNUSED
)
2116 ILLEGAL_WITHIN_STRUCT ();
2123 if (*input_line_pointer
== '"')
2127 name
= demand_copy_C_string (&len
);
2133 c
= get_symbol_name (§ion_name
);
2134 name
= xstrdup (section_name
);
2135 (void) restore_line_pointer (c
);
2138 seg
= bfd_get_section_by_name (stdoutput
, name
);
2141 as_bad (_("Unrecognized section '%s'"), name
);
2142 ignore_rest_of_line ();
2145 else if (!tic54x_initialized_section (seg
))
2147 as_bad (_(".sblock may be used for initialized sections only"));
2148 ignore_rest_of_line ();
2151 seg
->flags
|= SEC_TIC54X_BLOCK
;
2153 c
= *input_line_pointer
;
2154 if (!is_end_of_line
[(int) c
])
2155 ++input_line_pointer
;
2158 demand_empty_rest_of_line ();
2161 /* symbol .set value
2164 value must be defined externals; no forward-referencing allowed
2165 symbols assigned with .set/.equ may not be redefined. */
2168 tic54x_set (int ignore ATTRIBUTE_UNUSED
)
2173 ILLEGAL_WITHIN_STRUCT ();
2177 as_bad (_("Symbol missing for .set/.equ"));
2178 ignore_rest_of_line ();
2181 name
= xstrdup (S_GET_NAME (line_label
));
2183 if ((symbolP
= symbol_find (name
)) == NULL
2184 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
2186 symbolP
= symbol_new (name
, absolute_section
, 0, &zero_address_frag
);
2187 S_SET_STORAGE_CLASS (symbolP
, C_STAT
);
2190 S_SET_DATA_TYPE (symbolP
, T_INT
);
2191 S_SET_SEGMENT (symbolP
, absolute_section
);
2192 symbol_table_insert (symbolP
);
2193 pseudo_set (symbolP
);
2194 demand_empty_rest_of_line ();
2199 List false conditional blocks. */
2202 tic54x_fclist (int show
)
2205 listing
&= ~LISTING_NOCOND
;
2207 listing
|= LISTING_NOCOND
;
2208 demand_empty_rest_of_line ();
2212 tic54x_sslist (int show
)
2214 ILLEGAL_WITHIN_STRUCT ();
2216 listing_sslist
= show
;
2219 /* .var SYM[,...,SYMN]
2220 Define a substitution string to be local to a macro. */
2223 tic54x_var (int ignore ATTRIBUTE_UNUSED
)
2225 static char empty
[] = "";
2229 ILLEGAL_WITHIN_STRUCT ();
2231 if (macro_level
== 0)
2233 as_bad (_(".var may only be used within a macro definition"));
2234 ignore_rest_of_line ();
2239 if (!ISALPHA (*input_line_pointer
))
2241 as_bad (_("Substitution symbols must begin with a letter"));
2242 ignore_rest_of_line ();
2245 c
= get_symbol_name (&name
);
2246 /* .var symbols start out with a null string. */
2247 name
= xstrdup (name
);
2248 hash_insert (subsym_hash
[macro_level
], name
, empty
);
2249 c
= restore_line_pointer (c
);
2252 ++input_line_pointer
;
2253 if (is_end_of_line
[(int) *input_line_pointer
])
2254 c
= *input_line_pointer
;
2259 demand_empty_rest_of_line ();
2262 /* .mlib <macro library filename>
2264 Macro libraries are archived (standard AR-format) text macro definitions
2265 Expand the file and include it.
2267 FIXME need to try the source file directory as well. */
2270 tic54x_mlib (int ignore ATTRIBUTE_UNUSED
)
2277 ILLEGAL_WITHIN_STRUCT ();
2279 /* Parse the filename. */
2280 if (*input_line_pointer
== '"')
2282 if ((filename
= demand_copy_C_string (&len
)) == NULL
)
2289 while (!is_end_of_line
[(int) *input_line_pointer
]
2290 && !ISSPACE (*input_line_pointer
))
2292 obstack_1grow (¬es
, *input_line_pointer
);
2293 ++input_line_pointer
;
2296 obstack_1grow (¬es
, '\0');
2297 filename
= obstack_finish (¬es
);
2299 demand_empty_rest_of_line ();
2301 tic54x_set_default_include (0);
2302 path
= xmalloc ((unsigned long) len
+ include_dir_maxlen
+ 5);
2304 for (i
= 0; i
< include_dir_count
; i
++)
2308 strcpy (path
, include_dirs
[i
]);
2310 strcat (path
, filename
);
2311 if ((try = fopen (path
, "r")) != NULL
)
2318 if (i
>= include_dir_count
)
2324 /* FIXME: if path is found, malloc'd storage is not freed. Of course, this
2325 happens all over the place, and since the assembler doesn't usually keep
2326 running for a very long time, it really doesn't matter. */
2327 register_dependency (path
);
2329 /* Expand all archive entries to temporary files and include them. */
2330 abfd
= bfd_openr (path
, NULL
);
2333 as_bad (_("can't open macro library file '%s' for reading: %s"),
2334 path
, bfd_errmsg (bfd_get_error ()));
2335 ignore_rest_of_line ();
2338 if (!bfd_check_format (abfd
, bfd_archive
))
2340 as_bad (_("File '%s' not in macro archive format"), path
);
2341 ignore_rest_of_line ();
2345 /* Open each BFD as binary (it should be straight ASCII text). */
2346 for (mbfd
= bfd_openr_next_archived_file (abfd
, NULL
);
2347 mbfd
!= NULL
; mbfd
= bfd_openr_next_archived_file (abfd
, mbfd
))
2349 /* Get a size at least as big as the archive member. */
2350 bfd_size_type size
= bfd_get_size (mbfd
);
2351 char *buf
= xmalloc (size
);
2352 char *fname
= tmpnam (NULL
);
2355 /* We're not sure how big it is, but it will be smaller than "size". */
2356 size
= bfd_bread (buf
, size
, mbfd
);
2358 /* Write to a temporary file, then use s_include to include it
2360 ftmp
= fopen (fname
, "w+b");
2361 fwrite ((void *) buf
, size
, 1, ftmp
);
2362 if (size
== 0 || buf
[size
- 1] != '\n')
2363 fwrite ("\n", 1, 1, ftmp
);
2366 input_scrub_insert_file (fname
);
2371 const pseudo_typeS md_pseudo_table
[] =
2373 { "algebraic", s_ignore
, 0 },
2374 { "align" , tic54x_align_words
, 128 },
2375 { "ascii" , tic54x_stringer
, 'p' },
2376 { "asciz" , tic54x_stringer
, 'P' },
2377 { "even" , tic54x_align_words
, 2 },
2378 { "asg" , tic54x_asg
, 0 },
2379 { "eval" , tic54x_eval
, 0 },
2380 { "bss" , tic54x_bss
, 0 },
2381 { "byte" , tic54x_cons
, 'b' },
2382 { "ubyte" , tic54x_cons
, 'B' },
2383 { "char" , tic54x_cons
, 'c' },
2384 { "uchar" , tic54x_cons
, 'C' },
2385 { "clink" , tic54x_clink
, 0 },
2386 { "c_mode" , tic54x_address_mode
, c_mode
},
2387 { "copy" , tic54x_include
, 'c' },
2388 { "include" , tic54x_include
, 'i' },
2389 { "data" , tic54x_sect
, 'd' },
2390 { "double" , tic54x_float_cons
, 'd' },
2391 { "ldouble" , tic54x_float_cons
, 'l' },
2392 { "drlist" , s_ignore
, 0 },
2393 { "drnolist" , s_ignore
, 0 },
2394 { "emsg" , tic54x_message
, 'e' },
2395 { "mmsg" , tic54x_message
, 'm' },
2396 { "wmsg" , tic54x_message
, 'w' },
2397 { "far_mode" , tic54x_address_mode
, far_mode
},
2398 { "fclist" , tic54x_fclist
, 1 },
2399 { "fcnolist" , tic54x_fclist
, 0 },
2400 { "field" , tic54x_field
, -1 },
2401 { "float" , tic54x_float_cons
, 'f' },
2402 { "xfloat" , tic54x_float_cons
, 'x' },
2403 { "global" , tic54x_global
, 'g' },
2404 { "def" , tic54x_global
, 'd' },
2405 { "ref" , tic54x_global
, 'r' },
2406 { "half" , tic54x_cons
, 'h' },
2407 { "uhalf" , tic54x_cons
, 'H' },
2408 { "short" , tic54x_cons
, 's' },
2409 { "ushort" , tic54x_cons
, 'S' },
2410 { "if" , s_if
, (int) O_ne
},
2411 { "elseif" , s_elseif
, (int) O_ne
},
2412 { "else" , s_else
, 0 },
2413 { "endif" , s_endif
, 0 },
2414 { "int" , tic54x_cons
, 'i' },
2415 { "uint" , tic54x_cons
, 'I' },
2416 { "word" , tic54x_cons
, 'w' },
2417 { "uword" , tic54x_cons
, 'W' },
2418 { "label" , tic54x_label
, 0 }, /* Loadtime
2420 { "length" , s_ignore
, 0 },
2421 { "width" , s_ignore
, 0 },
2422 { "long" , tic54x_cons
, 'l' },
2423 { "ulong" , tic54x_cons
, 'L' },
2424 { "xlong" , tic54x_cons
, 'x' },
2425 { "loop" , tic54x_loop
, 1024 },
2426 { "break" , tic54x_break
, 0 },
2427 { "endloop" , tic54x_endloop
, 0 },
2428 { "mlib" , tic54x_mlib
, 0 },
2429 { "mlist" , s_ignore
, 0 },
2430 { "mnolist" , s_ignore
, 0 },
2431 { "mmregs" , tic54x_mmregs
, 0 },
2432 { "newblock" , tic54x_clear_local_labels
, 0 },
2433 { "option" , s_ignore
, 0 },
2434 { "p2align" , tic54x_p2align
, 0 },
2435 { "sblock" , tic54x_sblock
, 0 },
2436 { "sect" , tic54x_sect
, '*' },
2437 { "set" , tic54x_set
, 0 },
2438 { "equ" , tic54x_set
, 0 },
2439 { "space" , tic54x_space
, 0 },
2440 { "bes" , tic54x_space
, 1 },
2441 { "sslist" , tic54x_sslist
, 1 },
2442 { "ssnolist" , tic54x_sslist
, 0 },
2443 { "string" , tic54x_stringer
, 's' },
2444 { "pstring" , tic54x_stringer
, 'p' },
2445 { "struct" , tic54x_struct
, 0 },
2446 { "tag" , tic54x_tag
, 0 },
2447 { "endstruct", tic54x_endstruct
, 0 },
2448 { "tab" , s_ignore
, 0 },
2449 { "text" , tic54x_sect
, 't' },
2450 { "union" , tic54x_struct
, 1 },
2451 { "endunion" , tic54x_endstruct
, 1 },
2452 { "usect" , tic54x_usect
, 0 },
2453 { "var" , tic54x_var
, 0 },
2454 { "version" , tic54x_version
, 0 },
2459 md_parse_option (int c
, const char *arg
)
2465 case OPTION_COFF_VERSION
:
2467 int version
= atoi (arg
);
2469 if (version
!= 0 && version
!= 1 && version
!= 2)
2470 as_fatal (_("Bad COFF version '%s'"), arg
);
2471 /* FIXME -- not yet implemented. */
2474 case OPTION_CPU_VERSION
:
2476 cpu
= lookup_version (arg
);
2479 as_fatal (_("Bad CPU version '%s'"), arg
);
2482 case OPTION_ADDRESS_MODE
:
2484 address_mode_needs_set
= 1;
2486 case OPTION_STDERR_TO_FILE
:
2488 const char *filename
= arg
;
2489 FILE *fp
= fopen (filename
, "w+");
2492 as_fatal (_("Can't redirect stderr to the file '%s'"), filename
);
2494 if ((fp
= freopen (filename
, "w+", stderr
)) == NULL
)
2495 as_fatal (_("Can't redirect stderr to the file '%s'"), filename
);
2503 /* Create a "local" substitution string hash table for a new macro level
2504 Some docs imply that macros have to use .newblock in order to be able
2505 to re-use a local label. We effectively do an automatic .newblock by
2506 deleting the local label hash between macro invocations. */
2509 tic54x_macro_start (void)
2512 subsym_hash
[macro_level
] = hash_new ();
2513 local_label_hash
[macro_level
] = hash_new ();
2517 tic54x_macro_info (const macro_entry
*macro
)
2519 const formal_entry
*entry
;
2521 /* Put the formal args into the substitution symbol table. */
2522 for (entry
= macro
->formals
; entry
; entry
= entry
->next
)
2524 char *name
= strncpy (xmalloc (entry
->name
.len
+ 1),
2525 entry
->name
.ptr
, entry
->name
.len
);
2526 char *value
= strncpy (xmalloc (entry
->actual
.len
+ 1),
2527 entry
->actual
.ptr
, entry
->actual
.len
);
2529 name
[entry
->name
.len
] = '\0';
2530 value
[entry
->actual
.len
] = '\0';
2531 hash_insert (subsym_hash
[macro_level
], name
, value
);
2535 /* Get rid of this macro's .var's, arguments, and local labels. */
2538 tic54x_macro_end (void)
2540 hash_die (subsym_hash
[macro_level
]);
2541 subsym_hash
[macro_level
] = NULL
;
2542 hash_die (local_label_hash
[macro_level
]);
2543 local_label_hash
[macro_level
] = NULL
;
2548 subsym_symlen (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2553 /* Compare symbol A to string B. */
2556 subsym_symcmp (char *a
, char *b
)
2558 return strcmp (a
, b
);
2561 /* Return the index of the first occurrence of B in A, or zero if none
2562 assumes b is an integer char value as a string. Index is one-based. */
2565 subsym_firstch (char *a
, char *b
)
2568 char *tmp
= strchr (a
, val
);
2570 return tmp
? tmp
- a
+ 1 : 0;
2573 /* Similar to firstch, but returns index of last occurrence of B in A. */
2576 subsym_lastch (char *a
, char *b
)
2579 char *tmp
= strrchr (a
, val
);
2581 return tmp
? tmp
- a
+ 1 : 0;
2584 /* Returns 1 if string A is defined in the symbol table (NOT the substitution
2588 subsym_isdefed (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2590 symbolS
*symbolP
= symbol_find (a
);
2592 return symbolP
!= NULL
;
2595 /* Assign first member of comma-separated list B (e.g. "1,2,3") to the symbol
2596 A, or zero if B is a null string. Both arguments *must* be substitution
2597 symbols, unsubstituted. */
2600 subsym_ismember (char *sym
, char *list
)
2602 char *elem
, *ptr
, *listv
;
2607 listv
= subsym_lookup (list
, macro_level
);
2610 as_bad (_("Undefined substitution symbol '%s'"), list
);
2611 ignore_rest_of_line ();
2615 ptr
= elem
= xstrdup (listv
);
2616 while (*ptr
&& *ptr
!= ',')
2620 subsym_create_or_replace (sym
, elem
);
2622 /* Reassign the list. */
2623 subsym_create_or_replace (list
, ptr
);
2625 /* Assume this value, docs aren't clear. */
2629 /* Return zero if not a constant; otherwise:
2637 subsym_iscons (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2641 parse_expression (a
, &expn
);
2643 if (expn
.X_op
== O_constant
)
2645 int len
= strlen (a
);
2647 switch (TOUPPER (a
[len
- 1]))
2660 /* No suffix; either octal, hex, or decimal. */
2661 if (*a
== '0' && len
> 1)
2663 if (TOUPPER (a
[1]) == 'X')
2673 /* Return 1 if A is a valid symbol name. Expects string input. */
2676 subsym_isname (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2678 if (!is_name_beginner (*a
))
2682 if (!is_part_of_name (*a
))
2689 /* Return whether the string is a register; accepts ar0-7, unless .mmregs has
2690 been seen; if so, recognize any memory-mapped register.
2691 Note this does not recognize "A" or "B" accumulators. */
2694 subsym_isreg (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2696 if (hash_find (reg_hash
, a
))
2698 if (hash_find (mmreg_hash
, a
))
2703 /* Return the structure size, given the stag. */
2706 subsym_structsz (char *name
, char *ignore ATTRIBUTE_UNUSED
)
2708 struct stag
*stag
= (struct stag
*) hash_find (stag_hash
, name
);
2716 /* If anybody actually uses this, they can fix it :)
2717 FIXME I'm not sure what the "reference point" of a structure is. It might
2718 be either the initial offset given .struct, or it may be the offset of the
2719 structure within another structure, or it might be something else
2720 altogether. since the TI assembler doesn't seem to ever do anything but
2721 return zero, we punt and return zero. */
2724 subsym_structacc (char *stag_name ATTRIBUTE_UNUSED
,
2725 char *ignore ATTRIBUTE_UNUSED
)
2731 math_ceil (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2733 return (float) ceil (arg1
);
2737 math_cvi (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2743 math_floor (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2745 return (float) floor (arg1
);
2749 math_fmod (float arg1
, float arg2
)
2751 return (int) arg1
% (int) arg2
;
2755 math_int (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2757 return ((float) ((int) arg1
)) == arg1
;
2761 math_round (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2763 return arg1
> 0 ? (int) (arg1
+ 0.5) : (int) (arg1
- 0.5);
2767 math_sgn (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2769 return (arg1
< 0) ? -1 : (arg1
? 1 : 0);
2773 math_trunc (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2779 math_acos (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2781 return (float) acos (arg1
);
2785 math_asin (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2787 return (float) asin (arg1
);
2791 math_atan (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2793 return (float) atan (arg1
);
2797 math_atan2 (float arg1
, float arg2
)
2799 return (float) atan2 (arg1
, arg2
);
2803 math_cosh (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2805 return (float) cosh (arg1
);
2809 math_cos (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2811 return (float) cos (arg1
);
2815 math_cvf (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2817 return (float) arg1
;
2821 math_exp (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2823 return (float) exp (arg1
);
2827 math_fabs (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2829 return (float) fabs (arg1
);
2832 /* expr1 * 2^expr2. */
2835 math_ldexp (float arg1
, float arg2
)
2837 return arg1
* (float) pow (2.0, arg2
);
2841 math_log10 (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2843 return (float) log10 (arg1
);
2847 math_log (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2849 return (float) log (arg1
);
2853 math_max (float arg1
, float arg2
)
2855 return (arg1
> arg2
) ? arg1
: arg2
;
2859 math_min (float arg1
, float arg2
)
2861 return (arg1
< arg2
) ? arg1
: arg2
;
2865 math_pow (float arg1
, float arg2
)
2867 return (float) pow (arg1
, arg2
);
2871 math_sin (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2873 return (float) sin (arg1
);
2877 math_sinh (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2879 return (float) sinh (arg1
);
2883 math_sqrt (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2885 return (float) sqrt (arg1
);
2889 math_tan (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2891 return (float) tan (arg1
);
2895 math_tanh (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2897 return (float) tanh (arg1
);
2900 /* Built-in substitution symbol functions and math functions. */
2904 int (*proc
) (char *, char *);
2906 } subsym_proc_entry
;
2908 static const subsym_proc_entry subsym_procs
[] =
2910 /* Assembler built-in string substitution functions. */
2911 { "$symlen", subsym_symlen
, 1, },
2912 { "$symcmp", subsym_symcmp
, 2, },
2913 { "$firstch", subsym_firstch
, 2, },
2914 { "$lastch", subsym_lastch
, 2, },
2915 { "$isdefed", subsym_isdefed
, 1, },
2916 { "$ismember", subsym_ismember
, 2, },
2917 { "$iscons", subsym_iscons
, 1, },
2918 { "$isname", subsym_isname
, 1, },
2919 { "$isreg", subsym_isreg
, 1, },
2920 { "$structsz", subsym_structsz
, 1, },
2921 { "$structacc", subsym_structacc
, 1, },
2928 float (*proc
) (float, float);
2933 static const math_proc_entry math_procs
[] =
2935 /* Integer-returning built-in math functions. */
2936 { "$cvi", math_cvi
, 1, 1 },
2937 { "$int", math_int
, 1, 1 },
2938 { "$sgn", math_sgn
, 1, 1 },
2940 /* Float-returning built-in math functions. */
2941 { "$acos", math_acos
, 1, 0 },
2942 { "$asin", math_asin
, 1, 0 },
2943 { "$atan", math_atan
, 1, 0 },
2944 { "$atan2", math_atan2
, 2, 0 },
2945 { "$ceil", math_ceil
, 1, 0 },
2946 { "$cosh", math_cosh
, 1, 0 },
2947 { "$cos", math_cos
, 1, 0 },
2948 { "$cvf", math_cvf
, 1, 0 },
2949 { "$exp", math_exp
, 1, 0 },
2950 { "$fabs", math_fabs
, 1, 0 },
2951 { "$floor", math_floor
, 1, 0 },
2952 { "$fmod", math_fmod
, 2, 0 },
2953 { "$ldexp", math_ldexp
, 2, 0 },
2954 { "$log10", math_log10
, 1, 0 },
2955 { "$log", math_log
, 1, 0 },
2956 { "$max", math_max
, 2, 0 },
2957 { "$min", math_min
, 2, 0 },
2958 { "$pow", math_pow
, 2, 0 },
2959 { "$round", math_round
, 1, 0 },
2960 { "$sin", math_sin
, 1, 0 },
2961 { "$sinh", math_sinh
, 1, 0 },
2962 { "$sqrt", math_sqrt
, 1, 0 },
2963 { "$tan", math_tan
, 1, 0 },
2964 { "$tanh", math_tanh
, 1, 0 },
2965 { "$trunc", math_trunc
, 1, 0 },
2966 { NULL
, NULL
, 0, 0 },
2974 const subsym_proc_entry
*subsym_proc
;
2975 const math_proc_entry
*math_proc
;
2976 const char *hash_err
;
2978 char *TIC54X_DIR
= getenv ("TIC54X_DIR");
2979 char *A_DIR
= TIC54X_DIR
? TIC54X_DIR
: getenv ("A_DIR");
2983 /* Look for A_DIR and add it to the include list. */
2986 char *tmp
= xstrdup (A_DIR
);
2990 char *next
= strchr (tmp
, ';');
2994 add_include_dir (tmp
);
2997 while (tmp
!= NULL
);
3000 op_hash
= hash_new ();
3001 for (tm
= (insn_template
*) tic54x_optab
; tm
->name
; tm
++)
3003 if (hash_find (op_hash
, tm
->name
))
3005 hash_err
= hash_insert (op_hash
, tm
->name
, (char *) tm
);
3007 as_fatal ("Internal Error: Can't hash %s: %s",
3008 tm
->name
, hash_err
);
3010 parop_hash
= hash_new ();
3011 for (tm
= (insn_template
*) tic54x_paroptab
; tm
->name
; tm
++)
3013 if (hash_find (parop_hash
, tm
->name
))
3015 hash_err
= hash_insert (parop_hash
, tm
->name
, (char *) tm
);
3017 as_fatal ("Internal Error: Can't hash %s: %s",
3018 tm
->name
, hash_err
);
3020 reg_hash
= hash_new ();
3021 for (sym
= (symbol
*) regs
; sym
->name
; sym
++)
3023 /* Add basic registers to the symbol table. */
3024 symbolS
*symbolP
= symbol_new (sym
->name
, absolute_section
,
3025 (valueT
) sym
->value
, &zero_address_frag
);
3026 SF_SET_LOCAL (symbolP
);
3027 symbol_table_insert (symbolP
);
3028 hash_err
= hash_insert (reg_hash
, sym
->name
, (char *) sym
);
3030 for (sym
= (symbol
*) mmregs
; sym
->name
; sym
++)
3031 hash_err
= hash_insert (reg_hash
, sym
->name
, (char *) sym
);
3032 mmreg_hash
= hash_new ();
3033 for (sym
= (symbol
*) mmregs
; sym
->name
; sym
++)
3034 hash_err
= hash_insert (mmreg_hash
, sym
->name
, (char *) sym
);
3036 cc_hash
= hash_new ();
3037 for (sym
= (symbol
*) condition_codes
; sym
->name
; sym
++)
3038 hash_err
= hash_insert (cc_hash
, sym
->name
, (char *) sym
);
3040 cc2_hash
= hash_new ();
3041 for (sym
= (symbol
*) cc2_codes
; sym
->name
; sym
++)
3042 hash_err
= hash_insert (cc2_hash
, sym
->name
, (char *) sym
);
3044 cc3_hash
= hash_new ();
3045 for (sym
= (symbol
*) cc3_codes
; sym
->name
; sym
++)
3046 hash_err
= hash_insert (cc3_hash
, sym
->name
, (char *) sym
);
3048 sbit_hash
= hash_new ();
3049 for (sym
= (symbol
*) status_bits
; sym
->name
; sym
++)
3050 hash_err
= hash_insert (sbit_hash
, sym
->name
, (char *) sym
);
3052 misc_symbol_hash
= hash_new ();
3053 for (symname
= (char **) misc_symbols
; *symname
; symname
++)
3054 hash_err
= hash_insert (misc_symbol_hash
, *symname
, *symname
);
3056 /* Only the base substitution table and local label table are initialized;
3057 the others (for local macro substitution) get instantiated as needed. */
3058 local_label_hash
[0] = hash_new ();
3059 subsym_hash
[0] = hash_new ();
3060 for (subsym_proc
= subsym_procs
; subsym_proc
->name
; subsym_proc
++)
3061 hash_err
= hash_insert (subsym_hash
[0], subsym_proc
->name
,
3062 (char *) subsym_proc
);
3064 math_hash
= hash_new ();
3065 for (math_proc
= math_procs
; math_proc
->name
; math_proc
++)
3067 /* Insert into the main subsym hash for recognition; insert into
3068 the math hash to actually store information. */
3069 hash_err
= hash_insert (subsym_hash
[0], math_proc
->name
,
3070 (char *) math_proc
);
3071 hash_err
= hash_insert (math_hash
, math_proc
->name
,
3072 (char *) math_proc
);
3074 subsym_recurse_hash
= hash_new ();
3075 stag_hash
= hash_new ();
3079 is_accumulator (struct opstruct
*operand
)
3081 return strcasecmp (operand
->buf
, "a") == 0
3082 || strcasecmp (operand
->buf
, "b") == 0;
3085 /* Return the number of operands found, or -1 on error, copying the
3086 operands into the given array and the accompanying expressions into
3090 get_operands (struct opstruct operands
[], char *line
)
3094 int expecting_operand
= 0;
3097 while (numexp
< MAX_OPERANDS
&& !is_end_of_line
[(int) *lptr
])
3099 int paren_not_balanced
= 0;
3100 char *op_start
, *op_end
;
3102 while (*lptr
&& ISSPACE (*lptr
))
3105 while (paren_not_balanced
|| *lptr
!= ',')
3109 if (paren_not_balanced
)
3111 as_bad (_("Unbalanced parenthesis in operand %d"), numexp
);
3118 ++paren_not_balanced
;
3119 else if (*lptr
== ')')
3120 --paren_not_balanced
;
3124 if (op_end
!= op_start
)
3126 int len
= op_end
- op_start
;
3128 strncpy (operands
[numexp
].buf
, op_start
, len
);
3129 operands
[numexp
].buf
[len
] = 0;
3130 /* Trim trailing spaces; while the preprocessor gets rid of most,
3131 there are weird usage patterns that can introduce them
3132 (i.e. using strings for macro args). */
3133 while (len
> 0 && ISSPACE (operands
[numexp
].buf
[len
- 1]))
3134 operands
[numexp
].buf
[--len
] = 0;
3140 if (expecting_operand
|| *lptr
== ',')
3142 as_bad (_("Expecting operand after ','"));
3148 if (*++lptr
== '\0')
3150 as_bad (_("Expecting operand after ','"));
3153 expecting_operand
= 1;
3157 while (*lptr
&& ISSPACE (*lptr
++))
3159 if (!is_end_of_line
[(int) *lptr
])
3161 as_bad (_("Extra junk on line"));
3165 /* OK, now parse them into expressions. */
3166 for (i
= 0; i
< numexp
; i
++)
3168 memset (&operands
[i
].exp
, 0, sizeof (operands
[i
].exp
));
3169 if (operands
[i
].buf
[0] == '#')
3172 parse_expression (operands
[i
].buf
+ 1, &operands
[i
].exp
);
3174 else if (operands
[i
].buf
[0] == '@')
3176 /* Direct notation. */
3177 parse_expression (operands
[i
].buf
+ 1, &operands
[i
].exp
);
3179 else if (operands
[i
].buf
[0] == '*')
3182 char *paren
= strchr (operands
[i
].buf
, '(');
3184 /* Allow immediate syntax in the inner expression. */
3185 if (paren
&& paren
[1] == '#')
3188 /* Pull out the lk expression or SP offset, if present. */
3191 int len
= strlen (paren
);
3192 char *end
= paren
+ len
;
3195 while (end
[-1] != ')')
3198 as_bad (_("Badly formed address expression"));
3203 parse_expression (paren
, &operands
[i
].exp
);
3207 operands
[i
].exp
.X_op
= O_absent
;
3210 parse_expression (operands
[i
].buf
, &operands
[i
].exp
);
3216 /* Predicates for different operand types. */
3219 is_immediate (struct opstruct
*operand
)
3221 return *operand
->buf
== '#';
3224 /* This is distinguished from immediate because some numbers must be constants
3225 and must *not* have the '#' prefix. */
3228 is_absolute (struct opstruct
*operand
)
3230 return operand
->exp
.X_op
== O_constant
&& !is_immediate (operand
);
3233 /* Is this an indirect operand? */
3236 is_indirect (struct opstruct
*operand
)
3238 return operand
->buf
[0] == '*';
3241 /* Is this a valid dual-memory operand? */
3244 is_dual (struct opstruct
*operand
)
3246 if (is_indirect (operand
) && strncasecmp (operand
->buf
, "*ar", 3) == 0)
3248 char *tmp
= operand
->buf
+ 3;
3253 /* Only allow *ARx, *ARx-, *ARx+, or *ARx+0%. */
3254 valid_mod
= *tmp
== '\0' ||
3255 strcasecmp (tmp
, "-") == 0 ||
3256 strcasecmp (tmp
, "+") == 0 ||
3257 strcasecmp (tmp
, "+0%") == 0;
3258 return arf
>= 2 && arf
<= 5 && valid_mod
;
3264 is_mmreg (struct opstruct
*operand
)
3266 return (is_absolute (operand
)
3267 || is_immediate (operand
)
3268 || hash_find (mmreg_hash
, operand
->buf
) != 0);
3272 is_type (struct opstruct
*operand
, enum optype type
)
3277 return operand
->buf
[0] == 0;
3280 return is_dual (operand
);
3282 return is_indirect (operand
);
3284 /* This one *must* be immediate. */
3285 return is_immediate (operand
);
3294 /* Address may be a numeric, indirect, or an expression. */
3295 return !is_immediate (operand
);
3298 return is_mmreg (operand
);
3303 return is_accumulator (operand
);
3305 return is_accumulator (operand
) && TOUPPER (operand
->buf
[0]) == 'B';
3307 return is_accumulator (operand
) && TOUPPER (operand
->buf
[0]) == 'A';
3309 return strncasecmp ("ar", operand
->buf
, 2) == 0
3310 && ISDIGIT (operand
->buf
[2]);
3312 return hash_find (sbit_hash
, operand
->buf
) != 0 || is_absolute (operand
);
3314 return hash_find (cc_hash
, operand
->buf
) != 0;
3316 return hash_find (cc2_hash
, operand
->buf
) != 0;
3318 return hash_find (cc3_hash
, operand
->buf
) != 0
3319 || is_immediate (operand
) || is_absolute (operand
);
3321 return (is_immediate (operand
) || is_absolute (operand
))
3322 && operand
->exp
.X_add_number
== 16;
3324 /* Allow st0 or st1 instead of a numeric. */
3325 return is_absolute (operand
) || is_immediate (operand
) ||
3326 strcasecmp ("st0", operand
->buf
) == 0 ||
3327 strcasecmp ("st1", operand
->buf
) == 0;
3330 return is_absolute (operand
) || is_immediate (operand
);
3332 return (is_immediate (operand
) || is_absolute (operand
))
3333 && operand
->exp
.X_add_number
>= 0 && operand
->exp
.X_add_number
< 16;
3335 /* Let this one catch out-of-range values. */
3336 return (is_immediate (operand
) || is_absolute (operand
))
3337 && operand
->exp
.X_add_number
!= 16;
3341 return is_absolute (operand
) || is_immediate (operand
);
3343 return is_immediate (operand
)
3344 && operand
->exp
.X_op
== O_constant
3345 && operand
->exp
.X_add_number
>= 0
3346 && operand
->exp
.X_add_number
< 256;
3349 /* Allow anything; assumes opcodes are ordered with Smem operands
3355 /* Just make sure it's an integer; check range later. */
3356 return is_immediate (operand
);
3358 return strcasecmp ("t", operand
->buf
) == 0 ||
3359 strcasecmp ("treg", operand
->buf
) == 0;
3361 return strcasecmp ("ts", operand
->buf
) == 0;
3363 return strcasecmp ("asm", operand
->buf
) == 0;
3365 return strcasecmp ("trn", operand
->buf
) == 0;
3367 return strcasecmp ("dp", operand
->buf
) == 0;
3369 return strcasecmp ("arp", operand
->buf
) == 0;
3376 operands_match (tic54x_insn
*insn
,
3377 struct opstruct
*operands
,
3379 const enum optype
*refoptype
,
3383 int op
= 0, refop
= 0;
3385 if (opcount
== 0 && minops
== 0)
3388 while (op
<= maxops
&& refop
<= maxops
)
3390 while (!is_type (&operands
[op
], OPTYPE (refoptype
[refop
])))
3392 /* Skip an optional template operand if it doesn't agree
3393 with the current operand. */
3394 if (refoptype
[refop
] & OPT
)
3405 /* Save the actual operand type for later use. */
3406 operands
[op
].type
= OPTYPE (refoptype
[refop
]);
3409 /* Have we matched them all yet? */
3414 /* If a later operand is *not* optional, no match. */
3415 if ((refoptype
[refop
] & OPT
) == 0)
3417 /* Flag any implicit default OP_DST operands so we know to add
3418 them explicitly when encoding the operand later. */
3419 if (OPTYPE (refoptype
[refop
]) == OP_DST
)
3420 insn
->using_default_dst
= 1;
3432 /* 16-bit direct memory address
3433 Explicit dmad operands are always in last word of insn (usually second
3434 word, but bumped to third if lk addressing is used)
3436 We allow *(dmad) notation because the TI assembler allows it.
3439 0 for 16-bit addresses
3440 1 for full 23-bit addresses
3441 2 for the upper 7 bits of a 23-bit address (LDX). */
3444 encode_dmad (tic54x_insn
*insn
, struct opstruct
*operand
, int xpc_code
)
3446 int op
= 1 + insn
->is_lkaddr
;
3448 /* Only allow *(dmad) expressions; all others are invalid. */
3449 if (is_indirect (operand
) && operand
->buf
[strlen (operand
->buf
) - 1] != ')')
3451 as_bad (_("Invalid dmad syntax '%s'"), operand
->buf
);
3455 insn
->opcode
[op
].addr_expr
= operand
->exp
;
3457 if (insn
->opcode
[op
].addr_expr
.X_op
== O_constant
)
3459 valueT value
= insn
->opcode
[op
].addr_expr
.X_add_number
;
3463 insn
->opcode
[0].word
&= 0xFF80;
3464 insn
->opcode
[0].word
|= (value
>> 16) & 0x7F;
3465 insn
->opcode
[1].word
= value
& 0xFFFF;
3467 else if (xpc_code
== 2)
3468 insn
->opcode
[op
].word
= (value
>> 16) & 0xFFFF;
3470 insn
->opcode
[op
].word
= value
;
3474 /* Do the fixup later; just store the expression. */
3475 insn
->opcode
[op
].word
= 0;
3476 insn
->opcode
[op
].r_nchars
= 2;
3478 if (amode
== c_mode
)
3479 insn
->opcode
[op
].r_type
= BFD_RELOC_TIC54X_16_OF_23
;
3480 else if (xpc_code
== 1)
3482 /* This relocation spans two words, so adjust accordingly. */
3483 insn
->opcode
[0].addr_expr
= operand
->exp
;
3484 insn
->opcode
[0].r_type
= BFD_RELOC_TIC54X_23
;
3485 insn
->opcode
[0].r_nchars
= 4;
3486 insn
->opcode
[0].unresolved
= 1;
3487 /* It's really 2 words, but we want to stop encoding after the
3488 first, since we must encode both words at once. */
3491 else if (xpc_code
== 2)
3492 insn
->opcode
[op
].r_type
= BFD_RELOC_TIC54X_MS7_OF_23
;
3494 insn
->opcode
[op
].r_type
= BFD_RELOC_TIC54X_16_OF_23
;
3496 insn
->opcode
[op
].unresolved
= 1;
3502 /* 7-bit direct address encoding. */
3505 encode_address (tic54x_insn
*insn
, struct opstruct
*operand
)
3507 /* Assumes that dma addresses are *always* in word 0 of the opcode. */
3508 insn
->opcode
[0].addr_expr
= operand
->exp
;
3510 if (operand
->exp
.X_op
== O_constant
)
3511 insn
->opcode
[0].word
|= (operand
->exp
.X_add_number
& 0x7F);
3514 if (operand
->exp
.X_op
== O_register
)
3515 as_bad (_("Use the .mmregs directive to use memory-mapped register names such as '%s'"), operand
->buf
);
3516 /* Do the fixup later; just store the expression. */
3517 insn
->opcode
[0].r_nchars
= 1;
3518 insn
->opcode
[0].r_type
= BFD_RELOC_TIC54X_PARTLS7
;
3519 insn
->opcode
[0].unresolved
= 1;
3526 encode_indirect (tic54x_insn
*insn
, struct opstruct
*operand
)
3531 if (insn
->is_lkaddr
)
3533 /* lk addresses always go in the second insn word. */
3534 mod
= ((TOUPPER (operand
->buf
[1]) == 'A') ? 12 :
3535 (operand
->buf
[1] == '(') ? 15 :
3536 (strchr (operand
->buf
, '%') != NULL
) ? 14 : 13);
3537 arf
= ((mod
== 12) ? operand
->buf
[3] - '0' :
3538 (mod
== 15) ? 0 : operand
->buf
[4] - '0');
3540 insn
->opcode
[1].addr_expr
= operand
->exp
;
3542 if (operand
->exp
.X_op
== O_constant
)
3543 insn
->opcode
[1].word
= operand
->exp
.X_add_number
;
3546 insn
->opcode
[1].word
= 0;
3547 insn
->opcode
[1].r_nchars
= 2;
3548 insn
->opcode
[1].r_type
= BFD_RELOC_TIC54X_16_OF_23
;
3549 insn
->opcode
[1].unresolved
= 1;
3552 else if (strncasecmp (operand
->buf
, "*sp (", 4) == 0)
3554 /* Stack offsets look the same as 7-bit direct addressing. */
3555 return encode_address (insn
, operand
);
3559 arf
= (TOUPPER (operand
->buf
[1]) == 'A' ?
3560 operand
->buf
[3] : operand
->buf
[4]) - '0';
3562 if (operand
->buf
[1] == '+')
3564 mod
= 3; /* *+ARx */
3565 if (insn
->tm
->flags
& FL_SMR
)
3566 as_warn (_("Address mode *+ARx is write-only. "
3567 "Results of reading are undefined."));
3569 else if (operand
->buf
[4] == '\0')
3571 else if (operand
->buf
[5] == '\0')
3572 mod
= (operand
->buf
[4] == '-' ? 1 : 2); /* *ARx+ / *ARx- */
3573 else if (operand
->buf
[6] == '\0')
3575 if (operand
->buf
[5] == '0')
3576 mod
= (operand
->buf
[4] == '-' ? 5 : 6); /* *ARx+0 / *ARx-0 */
3578 mod
= (operand
->buf
[4] == '-' ? 8 : 10);/* *ARx+% / *ARx-% */
3580 else if (TOUPPER (operand
->buf
[6]) == 'B')
3581 mod
= (operand
->buf
[4] == '-' ? 4 : 7); /* ARx+0B / *ARx-0B */
3582 else if (TOUPPER (operand
->buf
[6]) == '%')
3583 mod
= (operand
->buf
[4] == '-' ? 9 : 11); /* ARx+0% / *ARx - 0% */
3586 as_bad (_("Unrecognized indirect address format \"%s\""),
3592 insn
->opcode
[0].word
|= 0x80 | (mod
<< 3) | arf
;
3598 encode_integer (tic54x_insn
*insn
,
3599 struct opstruct
*operand
,
3603 unsigned short mask
)
3605 long parse
, integer
;
3607 insn
->opcode
[which
].addr_expr
= operand
->exp
;
3609 if (operand
->exp
.X_op
== O_constant
)
3611 parse
= operand
->exp
.X_add_number
;
3612 /* Hack -- fixup for 16-bit hex quantities that get converted positive
3613 instead of negative. */
3614 if ((parse
& 0x8000) && min
== -32768 && max
== 32767)
3615 integer
= (short) parse
;
3619 if (integer
>= min
&& integer
<= max
)
3621 insn
->opcode
[which
].word
|= (integer
& mask
);
3624 as_bad (_("Operand '%s' out of range (%d <= x <= %d)"),
3625 operand
->buf
, min
, max
);
3629 if (insn
->opcode
[which
].addr_expr
.X_op
== O_constant
)
3631 insn
->opcode
[which
].word
|=
3632 insn
->opcode
[which
].addr_expr
.X_add_number
& mask
;
3636 /* Do the fixup later; just store the expression. */
3637 bfd_reloc_code_real_type rtype
=
3638 (mask
== 0x1FF ? BFD_RELOC_TIC54X_PARTMS9
:
3639 mask
== 0xFFFF ? BFD_RELOC_TIC54X_16_OF_23
:
3640 mask
== 0x7F ? BFD_RELOC_TIC54X_PARTLS7
: BFD_RELOC_8
);
3641 int size
= (mask
== 0x1FF || mask
== 0xFFFF) ? 2 : 1;
3643 if (rtype
== BFD_RELOC_8
)
3644 as_bad (_("Error in relocation handling"));
3646 insn
->opcode
[which
].r_nchars
= size
;
3647 insn
->opcode
[which
].r_type
= rtype
;
3648 insn
->opcode
[which
].unresolved
= 1;
3658 encode_condition (tic54x_insn
*insn
, struct opstruct
*operand
)
3660 symbol
*cc
= (symbol
*) hash_find (cc_hash
, operand
->buf
);
3663 as_bad (_("Unrecognized condition code \"%s\""), operand
->buf
);
3666 #define CC_GROUP 0x40
3668 #define CATG_A1 0x07
3669 #define CATG_B1 0x30
3670 #define CATG_A2 0x30
3671 #define CATG_B2 0x0C
3672 #define CATG_C2 0x03
3673 /* Disallow group 1 conditions mixed with group 2 conditions
3674 if group 1, allow only one category A and one category B
3675 if group 2, allow only one each of category A, B, and C. */
3676 if (((insn
->opcode
[0].word
& 0xFF) != 0))
3678 if ((insn
->opcode
[0].word
& CC_GROUP
) != (cc
->value
& CC_GROUP
))
3680 as_bad (_("Condition \"%s\" does not match preceding group"),
3684 if (insn
->opcode
[0].word
& CC_GROUP
)
3686 if ((insn
->opcode
[0].word
& CC_ACC
) != (cc
->value
& CC_ACC
))
3688 as_bad (_("Condition \"%s\" uses a different accumulator from "
3689 "a preceding condition"),
3693 if ((insn
->opcode
[0].word
& CATG_A1
) && (cc
->value
& CATG_A1
))
3695 as_bad (_("Only one comparison conditional allowed"));
3698 if ((insn
->opcode
[0].word
& CATG_B1
) && (cc
->value
& CATG_B1
))
3700 as_bad (_("Only one overflow conditional allowed"));
3704 else if ( ((insn
->opcode
[0].word
& CATG_A2
) && (cc
->value
& CATG_A2
))
3705 || ((insn
->opcode
[0].word
& CATG_B2
) && (cc
->value
& CATG_B2
))
3706 || ((insn
->opcode
[0].word
& CATG_C2
) && (cc
->value
& CATG_C2
)))
3708 as_bad (_("Duplicate %s conditional"), operand
->buf
);
3713 insn
->opcode
[0].word
|= cc
->value
;
3718 encode_cc3 (tic54x_insn
*insn
, struct opstruct
*operand
)
3720 symbol
*cc3
= (symbol
*) hash_find (cc3_hash
, operand
->buf
);
3721 int value
= cc3
? cc3
->value
: operand
->exp
.X_add_number
<< 8;
3723 if ((value
& 0x0300) != value
)
3725 as_bad (_("Unrecognized condition code \"%s\""), operand
->buf
);
3728 insn
->opcode
[0].word
|= value
;
3733 encode_arx (tic54x_insn
*insn
, struct opstruct
*operand
)
3735 int arf
= strlen (operand
->buf
) >= 3 ? operand
->buf
[2] - '0' : -1;
3737 if (strncasecmp ("ar", operand
->buf
, 2) || arf
< 0 || arf
> 7)
3739 as_bad (_("Invalid auxiliary register (use AR0-AR7)"));
3742 insn
->opcode
[0].word
|= arf
;
3747 encode_cc2 (tic54x_insn
*insn
, struct opstruct
*operand
)
3749 symbol
*cc2
= (symbol
*) hash_find (cc2_hash
, operand
->buf
);
3753 as_bad (_("Unrecognized condition code \"%s\""), operand
->buf
);
3756 insn
->opcode
[0].word
|= cc2
->value
;
3761 encode_operand (tic54x_insn
*insn
, enum optype type
, struct opstruct
*operand
)
3763 int ext
= (insn
->tm
->flags
& FL_EXT
) != 0;
3765 if (type
== OP_MMR
&& operand
->exp
.X_op
!= O_constant
)
3767 /* Disallow long-constant addressing for memory-mapped addressing. */
3768 if (insn
->is_lkaddr
)
3770 as_bad (_("lk addressing modes are invalid for memory-mapped "
3771 "register addressing"));
3775 /* Warn about *+ARx when used with MMR operands. */
3776 if (strncasecmp (operand
->buf
, "*+ar", 4) == 0)
3778 as_warn (_("Address mode *+ARx is not allowed in memory-mapped "
3779 "register addressing. Resulting behavior is "
3789 /* 16-bit immediate value. */
3790 return encode_dmad (insn
, operand
, 0);
3792 if (TOUPPER (*operand
->buf
) == 'B')
3794 insn
->opcode
[ext
? (1 + insn
->is_lkaddr
) : 0].word
|= (1 << 9);
3795 if (insn
->using_default_dst
)
3796 insn
->opcode
[ext
? (1 + insn
->is_lkaddr
) : 0].word
|= (1 << 8);
3800 /* Make sure this agrees with the OP_DST operand. */
3801 if (!((TOUPPER (operand
->buf
[0]) == 'B') ^
3802 ((insn
->opcode
[0].word
& (1 << 8)) != 0)))
3804 as_bad (_("Destination accumulator for each part of this parallel "
3805 "instruction must be different"));
3811 if (TOUPPER (operand
->buf
[0]) == 'B')
3812 insn
->opcode
[ext
? (1 + insn
->is_lkaddr
) : 0].word
|= (1 << 8);
3817 int mod
= (operand
->buf
[4] == '\0' ? 0 : /* *arx */
3818 operand
->buf
[4] == '-' ? 1 : /* *arx- */
3819 operand
->buf
[5] == '\0' ? 2 : 3); /* *arx+, *arx+0% */
3820 int arf
= operand
->buf
[3] - '0' - 2;
3821 int code
= (mod
<< 2) | arf
;
3822 insn
->opcode
[0].word
|= (code
<< (type
== OP_Xmem
? 4 : 0));
3827 if (!is_indirect (operand
))
3828 return encode_address (insn
, operand
);
3831 return encode_indirect (insn
, operand
);
3833 return encode_dmad (insn
, operand
, 2);
3835 return encode_dmad (insn
, operand
, 1);
3838 return encode_dmad (insn
, operand
, 0);
3840 return encode_arx (insn
, operand
);
3845 int value
= operand
->exp
.X_add_number
;
3848 insn
->opcode
[0].word
|= value
;
3851 if (value
< 16 || value
> 24)
3853 as_bad (_("Memory mapped register \"%s\" out of range"),
3857 if (type
== OP_MMRX
)
3858 insn
->opcode
[0].word
|= (value
- 16) << 4;
3860 insn
->opcode
[0].word
|= (value
- 16);
3868 return encode_integer (insn
, operand
, ext
+ insn
->is_lkaddr
,
3871 return encode_integer (insn
, operand
, ext
+ insn
->is_lkaddr
,
3874 return encode_integer (insn
, operand
, 1 + insn
->is_lkaddr
,
3875 -32768, 32767, 0xFFFF);
3877 return encode_condition (insn
, operand
);
3879 return encode_cc2 (insn
, operand
);
3881 return encode_cc3 (insn
, operand
);
3883 return encode_integer (insn
, operand
, 0, 0, 15, 0xF);
3885 return encode_integer (insn
, operand
, 0, -128, 127, 0xFF);
3888 int value
= operand
->exp
.X_add_number
;
3890 if (value
< 1 || value
> 3)
3892 as_bad (_("Invalid operand (use 1, 2, or 3)"));
3895 code
= value
== 1 ? 0 : value
== 2 ? 0x2 : 0x1;
3896 insn
->opcode
[0].word
|= (code
<< 8);
3900 return encode_integer (insn
, operand
, 0, 0, 31, 0x1F);
3902 return encode_integer (insn
, operand
, 0, 0, 255, 0xFF);
3904 return encode_integer (insn
, operand
, 1 + insn
->is_lkaddr
,
3908 symbol
*sbit
= (symbol
*) hash_find (sbit_hash
, operand
->buf
);
3909 int value
= is_absolute (operand
) ?
3910 operand
->exp
.X_add_number
: (sbit
? sbit
->value
: -1);
3913 if (insn
->opcount
== 1)
3917 as_bad (_("A status register or status bit name is required"));
3920 /* Guess the register based on the status bit; "ovb" is the last
3921 status bit defined for st0. */
3922 if (sbit
> (symbol
*) hash_find (sbit_hash
, "ovb"))
3927 as_bad (_("Unrecognized status bit \"%s\""), operand
->buf
);
3930 insn
->opcode
[0].word
|= value
;
3931 insn
->opcode
[0].word
|= (reg
<< 9);
3935 if (strcasecmp (operand
->buf
, "st0") == 0
3936 || strcasecmp (operand
->buf
, "st1") == 0)
3938 insn
->opcode
[0].word
|=
3939 ((unsigned short) (operand
->buf
[2] - '0')) << 9;
3942 else if (operand
->exp
.X_op
== O_constant
3943 && (operand
->exp
.X_add_number
== 0
3944 || operand
->exp
.X_add_number
== 1))
3946 insn
->opcode
[0].word
|=
3947 ((unsigned short) (operand
->exp
.X_add_number
)) << 9;
3950 as_bad (_("Invalid status register \"%s\""), operand
->buf
);
3953 return encode_integer (insn
, operand
, 0, -16, 15, 0x1F);
3955 return encode_integer (insn
, operand
, 0, 0, 7, 0x7);
3957 return encode_integer (insn
, operand
, 0, 0, 0x1FF, 0x1FF);
3959 if (operand
->exp
.X_add_number
!= 1
3960 && operand
->exp
.X_add_number
!= 2)
3962 as_bad (_("Operand \"%s\" out of range (use 1 or 2)"), operand
->buf
);
3965 insn
->opcode
[0].word
|= (operand
->exp
.X_add_number
- 1) << 9;
3974 /* No encoding necessary. */
3984 emit_insn (tic54x_insn
*insn
)
3987 flagword oldflags
= bfd_get_section_flags (stdoutput
, now_seg
);
3988 flagword flags
= oldflags
| SEC_CODE
;
3990 if (! bfd_set_section_flags (stdoutput
, now_seg
, flags
))
3991 as_warn (_("error setting flags for \"%s\": %s"),
3992 bfd_section_name (stdoutput
, now_seg
),
3993 bfd_errmsg (bfd_get_error ()));
3995 for (i
= 0; i
< insn
->words
; i
++)
3997 int size
= (insn
->opcode
[i
].unresolved
3998 && insn
->opcode
[i
].r_type
== BFD_RELOC_TIC54X_23
) ? 4 : 2;
3999 char *p
= frag_more (size
);
4002 md_number_to_chars (p
, (valueT
) insn
->opcode
[i
].word
, 2);
4004 md_number_to_chars (p
, (valueT
) insn
->opcode
[i
].word
<< 16, 4);
4006 if (insn
->opcode
[i
].unresolved
)
4007 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
,
4008 insn
->opcode
[i
].r_nchars
, &insn
->opcode
[i
].addr_expr
,
4009 FALSE
, insn
->opcode
[i
].r_type
);
4013 /* Convert the operand strings into appropriate opcode values
4014 return the total number of words used by the instruction. */
4017 build_insn (tic54x_insn
*insn
)
4021 /* Only non-parallel instructions support lk addressing. */
4022 if (!(insn
->tm
->flags
& FL_PAR
))
4024 for (i
= 0; i
< insn
->opcount
; i
++)
4026 if ((OPTYPE (insn
->operands
[i
].type
) == OP_Smem
4027 || OPTYPE (insn
->operands
[i
].type
) == OP_Lmem
4028 || OPTYPE (insn
->operands
[i
].type
) == OP_Sind
)
4029 && strchr (insn
->operands
[i
].buf
, '(')
4030 /* Don't mistake stack-relative addressing for lk addressing. */
4031 && strncasecmp (insn
->operands
[i
].buf
, "*sp (", 4) != 0)
4033 insn
->is_lkaddr
= 1;
4034 insn
->lkoperand
= i
;
4039 insn
->words
= insn
->tm
->words
+ insn
->is_lkaddr
;
4041 insn
->opcode
[0].word
= insn
->tm
->opcode
;
4042 if (insn
->tm
->flags
& FL_EXT
)
4043 insn
->opcode
[1 + insn
->is_lkaddr
].word
= insn
->tm
->opcode2
;
4045 for (i
= 0; i
< insn
->opcount
; i
++)
4047 enum optype type
= insn
->operands
[i
].type
;
4049 if (!encode_operand (insn
, type
, &insn
->operands
[i
]))
4052 if (insn
->tm
->flags
& FL_PAR
)
4053 for (i
= 0; i
< insn
->paropcount
; i
++)
4055 enum optype partype
= insn
->paroperands
[i
].type
;
4057 if (!encode_operand (insn
, partype
, &insn
->paroperands
[i
]))
4067 optimize_insn (tic54x_insn
*insn
)
4069 /* Optimize some instructions, helping out the brain-dead programmer. */
4070 #define is_zero(op) ((op).exp.X_op == O_constant && (op).exp.X_add_number == 0)
4071 if (strcasecmp (insn
->tm
->name
, "add") == 0)
4073 if (insn
->opcount
> 1
4074 && is_accumulator (&insn
->operands
[insn
->opcount
- 2])
4075 && is_accumulator (&insn
->operands
[insn
->opcount
- 1])
4076 && strcasecmp (insn
->operands
[insn
->opcount
- 2].buf
,
4077 insn
->operands
[insn
->opcount
- 1].buf
) == 0)
4080 insn
->using_default_dst
= 1;
4084 /* Try to collapse if Xmem and shift count is zero. */
4085 if ((OPTYPE (insn
->tm
->operand_types
[0]) == OP_Xmem
4086 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
4087 && is_zero (insn
->operands
[1]))
4088 /* Or if Smem, shift is zero or absent, and SRC == DST. */
4089 || (OPTYPE (insn
->tm
->operand_types
[0]) == OP_Smem
4090 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
4091 && is_type (&insn
->operands
[1], OP_SHIFT
)
4092 && is_zero (insn
->operands
[1]) && insn
->opcount
== 3))
4094 insn
->operands
[1] = insn
->operands
[2];
4099 else if (strcasecmp (insn
->tm
->name
, "ld") == 0)
4101 if (insn
->opcount
== 3 && insn
->operands
[0].type
!= OP_SRC
)
4103 if ((OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
4104 || OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
)
4105 && is_zero (insn
->operands
[1])
4106 && (OPTYPE (insn
->tm
->operand_types
[0]) != OP_lk
4107 || (insn
->operands
[0].exp
.X_op
== O_constant
4108 && insn
->operands
[0].exp
.X_add_number
<= 255
4109 && insn
->operands
[0].exp
.X_add_number
>= 0)))
4111 insn
->operands
[1] = insn
->operands
[2];
4117 else if (strcasecmp (insn
->tm
->name
, "sth") == 0
4118 || strcasecmp (insn
->tm
->name
, "stl") == 0)
4120 if ((OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
4121 || OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
)
4122 && is_zero (insn
->operands
[1]))
4124 insn
->operands
[1] = insn
->operands
[2];
4129 else if (strcasecmp (insn
->tm
->name
, "sub") == 0)
4131 if (insn
->opcount
> 1
4132 && is_accumulator (&insn
->operands
[insn
->opcount
- 2])
4133 && is_accumulator (&insn
->operands
[insn
->opcount
- 1])
4134 && strcasecmp (insn
->operands
[insn
->opcount
- 2].buf
,
4135 insn
->operands
[insn
->opcount
- 1].buf
) == 0)
4138 insn
->using_default_dst
= 1;
4142 if ( ((OPTYPE (insn
->tm
->operand_types
[0]) == OP_Smem
4143 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
)
4144 || (OPTYPE (insn
->tm
->operand_types
[0]) == OP_Xmem
4145 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
))
4146 && is_zero (insn
->operands
[1])
4147 && insn
->opcount
== 3)
4149 insn
->operands
[1] = insn
->operands
[2];
4157 /* Find a matching template if possible, and get the operand strings. */
4160 tic54x_parse_insn (tic54x_insn
*insn
, char *line
)
4162 insn
->tm
= (insn_template
*) hash_find (op_hash
, insn
->mnemonic
);
4165 as_bad (_("Unrecognized instruction \"%s\""), insn
->mnemonic
);
4169 insn
->opcount
= get_operands (insn
->operands
, line
);
4170 if (insn
->opcount
< 0)
4173 /* Check each variation of operands for this mnemonic. */
4174 while (insn
->tm
->name
&& strcasecmp (insn
->tm
->name
, insn
->mnemonic
) == 0)
4176 if (insn
->opcount
>= insn
->tm
->minops
4177 && insn
->opcount
<= insn
->tm
->maxops
4178 && operands_match (insn
, &insn
->operands
[0], insn
->opcount
,
4179 insn
->tm
->operand_types
,
4180 insn
->tm
->minops
, insn
->tm
->maxops
))
4182 /* SUCCESS! now try some optimizations. */
4183 if (optimize_insn (insn
))
4185 insn
->tm
= (insn_template
*) hash_find (op_hash
,
4194 as_bad (_("Unrecognized operand list '%s' for instruction '%s'"),
4195 line
, insn
->mnemonic
);
4199 /* We set this in start_line_hook, 'cause if we do a line replacement, we
4200 won't be able to see the next line. */
4201 static int parallel_on_next_line_hint
= 0;
4203 /* See if this is part of a parallel instruction
4204 Look for a subsequent line starting with "||". */
4207 next_line_shows_parallel (char *next_line
)
4209 /* Look for the second half. */
4210 while (ISSPACE (*next_line
))
4213 return (next_line
[0] == PARALLEL_SEPARATOR
4214 && next_line
[1] == PARALLEL_SEPARATOR
);
4218 tic54x_parse_parallel_insn_firstline (tic54x_insn
*insn
, char *line
)
4220 insn
->tm
= (insn_template
*) hash_find (parop_hash
, insn
->mnemonic
);
4223 as_bad (_("Unrecognized parallel instruction \"%s\""),
4228 while (insn
->tm
->name
&& strcasecmp (insn
->tm
->name
,
4229 insn
->mnemonic
) == 0)
4231 insn
->opcount
= get_operands (insn
->operands
, line
);
4232 if (insn
->opcount
< 0)
4234 if (insn
->opcount
== 2
4235 && operands_match (insn
, &insn
->operands
[0], insn
->opcount
,
4236 insn
->tm
->operand_types
, 2, 2))
4242 /* Didn't find a matching parallel; try for a normal insn. */
4246 /* Parse the second line of a two-line parallel instruction. */
4249 tic54x_parse_parallel_insn_lastline (tic54x_insn
*insn
, char *line
)
4251 int valid_mnemonic
= 0;
4253 insn
->paropcount
= get_operands (insn
->paroperands
, line
);
4254 while (insn
->tm
->name
&& strcasecmp (insn
->tm
->name
,
4255 insn
->mnemonic
) == 0)
4257 if (strcasecmp (insn
->tm
->parname
, insn
->parmnemonic
) == 0)
4261 if (insn
->paropcount
>= insn
->tm
->minops
4262 && insn
->paropcount
<= insn
->tm
->maxops
4263 && operands_match (insn
, insn
->paroperands
,
4265 insn
->tm
->paroperand_types
,
4266 insn
->tm
->minops
, insn
->tm
->maxops
))
4272 as_bad (_("Invalid operand (s) for parallel instruction \"%s\""),
4275 as_bad (_("Unrecognized parallel instruction combination \"%s || %s\""),
4276 insn
->mnemonic
, insn
->parmnemonic
);
4281 /* If quotes found, return copy of line up to closing quote;
4282 otherwise up until terminator.
4283 If it's a string, pass as-is; otherwise attempt substitution symbol
4284 replacement on the value. */
4287 subsym_get_arg (char *line
, const char *terminators
, char **str
, int nosub
)
4291 int is_string
= *line
== '"';
4292 int is_char
= ISDIGIT (*line
);
4296 while (ISDIGIT (*ptr
))
4299 *str
= xmalloc (ptr
- line
+ 1);
4300 strncpy (*str
, line
, ptr
- line
);
4301 (*str
)[ptr
- line
] = 0;
4305 char *savedp
= input_line_pointer
;
4308 input_line_pointer
= ptr
;
4309 *str
= demand_copy_C_string (&len
);
4310 endp
= input_line_pointer
;
4311 input_line_pointer
= savedp
;
4313 /* Do forced substitutions if requested. */
4314 if (!nosub
&& **str
== ':')
4315 *str
= subsym_substitute (*str
, 1);
4319 const char *term
= terminators
;
4322 while (*ptr
&& *ptr
!= *term
)
4333 *str
= xmalloc (ptr
- line
+ 1);
4334 strncpy (*str
, line
, ptr
- line
);
4335 (*str
)[ptr
- line
] = 0;
4336 /* Do simple substitution, if available. */
4337 if (!nosub
&& (value
= subsym_lookup (*str
, macro_level
)) != NULL
)
4344 /* Replace the given substitution string.
4345 We start at the innermost macro level, so that existing locals remain local
4346 Note: we're treating macro args identically to .var's; I don't know if
4347 that's compatible w/TI's assembler. */
4350 subsym_create_or_replace (char *name
, char *value
)
4354 for (i
= macro_level
; i
> 0; i
--)
4356 if (hash_find (subsym_hash
[i
], name
))
4358 hash_replace (subsym_hash
[i
], name
, value
);
4362 if (hash_find (subsym_hash
[0], name
))
4363 hash_replace (subsym_hash
[0], name
, value
);
4365 hash_insert (subsym_hash
[0], name
, value
);
4368 /* Look up the substitution string replacement for the given symbol.
4369 Start with the innermost macro substitution table given and work
4373 subsym_lookup (char *name
, int nest_level
)
4375 char *value
= hash_find (subsym_hash
[nest_level
], name
);
4377 if (value
|| nest_level
== 0)
4380 return subsym_lookup (name
, nest_level
- 1);
4383 /* Do substitution-symbol replacement on the given line (recursively).
4384 return the argument if no substitution was done
4386 Also look for built-in functions ($func (arg)) and local labels.
4388 If FORCED is set, look for forced substitutions of the form ':SYMBOL:'. */
4391 subsym_substitute (char *line
, int forced
)
4393 /* For each apparent symbol, see if it's a substitution symbol, and if so,
4394 replace it in the input. */
4395 char *replacement
; /* current replacement for LINE. */
4396 char *head
; /* Start of line. */
4397 char *ptr
; /* Current examination point. */
4398 int changed
= 0; /* Did we make a substitution? */
4399 int eval_line
= 0; /* Is this line a .eval/.asg statement? */
4400 int eval_symbol
= 0; /* Are we in the middle of the symbol for
4402 char *eval_end
= NULL
;
4404 int line_conditional
= 0;
4407 /* Work with a copy of the input line. */
4408 replacement
= xstrdup (line
);
4410 ptr
= head
= replacement
;
4412 /* Flag lines where we might need to replace a single '=' with two;
4413 GAS uses single '=' to assign macro args values, and possibly other
4414 places, so limit what we replace. */
4415 if (strstr (line
, ".if")
4416 || strstr (line
, ".elseif")
4417 || strstr (line
, ".break"))
4418 line_conditional
= 1;
4420 /* Watch out for .eval, so that we avoid doing substitution on the
4421 symbol being assigned a value. */
4422 if (strstr (line
, ".eval") || strstr (line
, ".asg"))
4425 /* If it's a macro definition, don't do substitution on the argument
4427 if (strstr (line
, ".macro"))
4430 while (!is_end_of_line
[(int) *ptr
])
4432 int current_char
= *ptr
;
4434 /* Need to update this since LINE may have been modified. */
4436 eval_end
= strrchr (ptr
, ',');
4438 /* Replace triple double quotes with bounding quote/escapes. */
4439 if (current_char
== '"' && ptr
[1] == '"' && ptr
[2] == '"')
4442 tmp
= strstr (ptr
+ 2, "\"\"\"");
4448 /* Replace a single '=' with a '==';
4449 for compatibility with older code only. */
4450 if (line_conditional
&& current_char
== '=')
4458 tmp
= xmalloc (strlen (head
) + 2 + strlen (ptr
) + 1);
4459 sprintf (tmp
, "%s==%s", head
, ptr
);
4460 /* Continue examining after the '=='. */
4461 ptr
= tmp
+ strlen (head
) + 2;
4463 head
= replacement
= tmp
;
4467 /* Flag when we've reached the symbol part of .eval/.asg. */
4468 if (eval_line
&& ptr
>= eval_end
)
4471 /* For each apparent symbol, see if it's a substitution symbol, and if
4472 so, replace it in the input. */
4473 if ((forced
&& current_char
== ':')
4474 || (!forced
&& is_name_beginner (current_char
)))
4476 char *name
; /* Symbol to be replaced. */
4477 char *savedp
= input_line_pointer
;
4480 char *tail
; /* Rest of line after symbol. */
4482 /* Skip the colon. */
4486 input_line_pointer
= ptr
;
4487 c
= get_symbol_name (&name
);
4488 /* '?' is not normally part of a symbol, but it IS part of a local
4492 *input_line_pointer
++ = c
;
4493 c
= *input_line_pointer
;
4494 *input_line_pointer
= '\0';
4496 /* Avoid infinite recursion; if a symbol shows up a second time for
4497 substitution, leave it as is. */
4498 if (hash_find (subsym_recurse_hash
, name
) == NULL
)
4499 value
= subsym_lookup (name
, macro_level
);
4501 as_warn (_("%s symbol recursion stopped at "
4502 "second appearance of '%s'"),
4503 forced
? "Forced substitution" : "Substitution", name
);
4504 ptr
= tail
= input_line_pointer
;
4505 input_line_pointer
= savedp
;
4507 /* Check for local labels; replace them with the appropriate
4509 if ((*name
== '$' && ISDIGIT (name
[1]) && name
[2] == '\0')
4510 || name
[strlen (name
) - 1] == '?')
4512 /* Use an existing identifier for that label if, available, or
4513 create a new, unique identifier. */
4514 value
= hash_find (local_label_hash
[macro_level
], name
);
4518 char *namecopy
= xstrdup (name
);
4520 value
= strcpy (xmalloc (strlen (name
) + sizeof (digit
) + 1),
4523 value
[strlen (value
) - 1] = '\0';
4524 sprintf (digit
, ".%d", local_label_id
++);
4525 strcat (value
, digit
);
4526 hash_insert (local_label_hash
[macro_level
], namecopy
, value
);
4528 /* Indicate where to continue looking for substitutions. */
4531 /* Check for built-in subsym and math functions. */
4532 else if (value
!= NULL
&& *name
== '$')
4534 subsym_proc_entry
*entry
= (subsym_proc_entry
*) value
;
4535 math_proc_entry
*math_entry
= hash_find (math_hash
, name
);
4536 char *arg1
, *arg2
= NULL
;
4541 as_bad (_("Unrecognized substitution symbol function"));
4544 else if (*ptr
!= '(')
4546 as_bad (_("Missing '(' after substitution symbol function"));
4550 if (math_entry
!= NULL
)
4552 float farg1
, farg2
= 0;
4553 volatile float fresult
;
4555 farg1
= (float) strtod (ptr
, &ptr
);
4556 if (math_entry
->nargs
== 2)
4560 as_bad (_("Expecting second argument"));
4563 farg2
= (float) strtod (ptr
, &ptr
);
4565 fresult
= (*math_entry
->proc
) (farg1
, farg2
);
4566 value
= xmalloc (128);
4567 if (math_entry
->int_return
)
4568 sprintf (value
, "%d", (int) fresult
);
4570 sprintf (value
, "%f", fresult
);
4573 as_bad (_("Extra junk in function call, expecting ')'"));
4576 /* Don't bother recursing; the replacement isn't a
4583 int arg_type
[2] = { *ptr
== '"' , 0 };
4584 int ismember
= !strcmp (entry
->name
, "$ismember");
4586 /* Parse one or two args, which must be a substitution
4587 symbol, string or a character-string constant. */
4588 /* For all functions, a string or substitution symbol may be
4589 used, with the following exceptions:
4590 firstch/lastch: 2nd arg must be character constant
4591 ismember: both args must be substitution symbols. */
4592 ptr
= subsym_get_arg (ptr
, ",)", &arg1
, ismember
);
4595 if (entry
->nargs
== 2)
4599 as_bad (_("Function expects two arguments"));
4602 /* Character constants are converted to numerics
4603 by the preprocessor. */
4604 arg_type
[1] = (ISDIGIT (*ptr
)) ? 2 : (*ptr
== '"');
4605 ptr
= subsym_get_arg (ptr
, ")", &arg2
, ismember
);
4607 /* Args checking. */
4608 if ((!strcmp (entry
->name
, "$firstch")
4609 || !strcmp (entry
->name
, "$lastch"))
4610 && arg_type
[1] != 2)
4612 as_bad (_("Expecting character constant argument"));
4616 && (arg_type
[0] != 0 || arg_type
[1] != 0))
4618 as_bad (_("Both arguments must be substitution symbols"));
4623 as_bad (_("Extra junk in function call, expecting ')'"));
4626 val
= (*entry
->proc
) (arg1
, arg2
);
4627 value
= xmalloc (64);
4628 sprintf (value
, "%d", val
);
4630 /* Fix things up to replace the entire expression, not just the
4636 if (value
!= NULL
&& !eval_symbol
)
4638 /* Replace the symbol with its string replacement and
4639 continue. Recursively replace VALUE until either no
4640 substitutions are performed, or a substitution that has been
4641 previously made is encountered again.
4643 Put the symbol into the recursion hash table so we only
4644 try to replace a symbol once. */
4647 hash_insert (subsym_recurse_hash
, name
, name
);
4648 value
= subsym_substitute (value
, macro_level
> 0);
4649 hash_delete (subsym_recurse_hash
, name
, FALSE
);
4652 /* Temporarily zero-terminate where the symbol started. */
4658 /* Subscripted substitution symbol -- use just the
4659 indicated portion of the string; the description
4660 kinda indicates that forced substitution is not
4661 supposed to be recursive, but I'm not sure. */
4662 unsigned beg
, len
= 1; /* default to a single char */
4663 char *newval
= xstrdup (value
);
4665 savedp
= input_line_pointer
;
4666 input_line_pointer
= tail
+ 1;
4667 beg
= get_absolute_expression ();
4670 as_bad (_("Invalid subscript (use 1 to %d)"),
4671 (int) strlen (value
));
4674 if (*input_line_pointer
== ',')
4676 ++input_line_pointer
;
4677 len
= get_absolute_expression ();
4678 if (beg
+ len
> strlen (value
))
4680 as_bad (_("Invalid length (use 0 to %d"),
4681 (int) strlen (value
) - beg
);
4687 tail
= input_line_pointer
;
4690 as_bad (_("Missing ')' in subscripted substitution "
4691 "symbol expression"));
4695 input_line_pointer
= savedp
;
4701 tmp
= xmalloc (strlen (head
) + strlen (value
) +
4702 strlen (tail
+ 1) + 2);
4704 strcat (tmp
, value
);
4705 /* Make sure forced substitutions are properly terminated. */
4710 as_bad (_("Missing forced substitution terminator ':'"));
4716 /* Restore the character after the symbol end. */
4719 /* Continue examining after the replacement value. */
4720 ptr
= tmp
+ strlen (head
) + strlen (value
);
4722 head
= replacement
= tmp
;
4740 /* We use this to handle substitution symbols
4741 hijack input_line_pointer, replacing it with our substituted string.
4743 .sslist should enable listing the line after replacements are made...
4745 returns the new buffer limit. */
4748 tic54x_start_line_hook (void)
4751 char *replacement
= NULL
;
4753 /* Work with a copy of the input line, including EOL char. */
4754 endp
= input_line_pointer
;
4755 while (!is_end_of_line
[(int) *endp
++])
4757 line
= xmalloc (endp
- input_line_pointer
+ 1);
4758 strncpy (line
, input_line_pointer
, endp
- input_line_pointer
+ 1);
4759 line
[endp
- input_line_pointer
] = 0;
4761 /* Scan ahead for parallel insns. */
4762 parallel_on_next_line_hint
= next_line_shows_parallel (endp
);
4764 /* If within a macro, first process forced replacements. */
4765 if (macro_level
> 0)
4766 replacement
= subsym_substitute (line
, 1);
4769 replacement
= subsym_substitute (replacement
, 0);
4771 if (replacement
!= line
)
4773 char *tmp
= replacement
;
4774 char *comment
= strchr (replacement
, ';');
4775 char endc
= replacement
[strlen (replacement
) - 1];
4777 /* Clean up the replacement; we'd prefer to have this done by the
4778 standard preprocessing equipment (maybe do_scrub_chars?)
4779 but for now, do a quick-and-dirty. */
4780 if (comment
!= NULL
)
4787 comment
= replacement
+ strlen (replacement
) - 1;
4789 /* Trim trailing whitespace. */
4790 while (ISSPACE (*comment
))
4797 /* Compact leading whitespace. */
4798 while (ISSPACE (tmp
[0]) && ISSPACE (tmp
[1]))
4801 input_line_pointer
= endp
;
4802 input_scrub_insert_line (tmp
);
4805 /* Keep track of whether we've done a substitution. */
4806 substitution_line
= 1;
4812 substitution_line
= 0;
4816 /* This is the guts of the machine-dependent assembler. STR points to a
4817 machine dependent instruction. This function is supposed to emit
4818 the frags/bytes it assembles to. */
4820 md_assemble (char *line
)
4822 static int repeat_slot
= 0;
4823 static int delay_slots
= 0; /* How many delay slots left to fill? */
4824 static int is_parallel
= 0;
4825 static tic54x_insn insn
;
4827 char *savedp
= input_line_pointer
;
4830 input_line_pointer
= line
;
4831 c
= get_symbol_name (&line
);
4835 if (address_mode_needs_set
)
4837 set_address_mode (amode
);
4838 address_mode_needs_set
= 0;
4851 strcpy (insn
.parmnemonic
, line
);
4852 lptr
= input_line_pointer
;
4854 input_line_pointer
= savedp
;
4856 if (tic54x_parse_parallel_insn_lastline (&insn
, lptr
))
4858 int words
= build_insn (&insn
);
4860 if (delay_slots
!= 0)
4862 if (words
> delay_slots
)
4864 as_bad (_("Instruction does not fit in available delay "
4865 "slots (%d-word insn, %d slots left)"),
4866 words
, delay_slots
);
4870 delay_slots
-= words
;
4876 memset (&insn
, 0, sizeof (insn
));
4877 strcpy (insn
.mnemonic
, line
);
4878 lptr
= input_line_pointer
;
4880 input_line_pointer
= savedp
;
4882 /* See if this line is part of a parallel instruction; if so, either this
4883 line or the next line will have the "||" specifier preceding the
4884 mnemonic, and we look for it in the parallel insn hash table. */
4885 if (strstr (line
, "||") != NULL
|| parallel_on_next_line_hint
)
4887 char *tmp
= strstr (line
, "||");
4891 if (tic54x_parse_parallel_insn_firstline (&insn
, lptr
))
4894 /* If the parallel part is on the same line, process it now,
4895 otherwise let the assembler pick up the next line for us. */
4898 while (ISSPACE (tmp
[2]))
4900 md_assemble (tmp
+ 2);
4905 as_bad (_("Unrecognized parallel instruction '%s'"), line
);
4910 if (tic54x_parse_insn (&insn
, lptr
))
4914 if ((insn
.tm
->flags
& FL_LP
)
4915 && cpu
!= V545LP
&& cpu
!= V546LP
)
4917 as_bad (_("Instruction '%s' requires an LP cpu version"),
4921 if ((insn
.tm
->flags
& FL_FAR
)
4922 && amode
!= far_mode
)
4924 as_bad (_("Instruction '%s' requires far mode addressing"),
4929 words
= build_insn (&insn
);
4931 /* Is this instruction in a delay slot? */
4934 if (words
> delay_slots
)
4936 as_warn (_("Instruction does not fit in available delay "
4937 "slots (%d-word insn, %d slots left). "
4938 "Resulting behavior is undefined."),
4939 words
, delay_slots
);
4943 /* Branches in delay slots are not allowed. */
4944 if (insn
.tm
->flags
& FL_BMASK
)
4946 as_warn (_("Instructions which cause PC discontinuity are not "
4947 "allowed in a delay slot. "
4948 "Resulting behavior is undefined."));
4950 delay_slots
-= words
;
4953 /* Is this instruction the target of a repeat? */
4956 if (insn
.tm
->flags
& FL_NR
)
4957 as_warn (_("'%s' is not repeatable. "
4958 "Resulting behavior is undefined."),
4960 else if (insn
.is_lkaddr
)
4961 as_warn (_("Instructions using long offset modifiers or absolute "
4962 "addresses are not repeatable. "
4963 "Resulting behavior is undefined."));
4967 /* Make sure we check the target of a repeat instruction. */
4968 if (insn
.tm
->flags
& B_REPEAT
)
4971 /* FIXME -- warn if repeat_slot == 1 at EOF. */
4973 /* Make sure we check our delay slots for validity. */
4974 if (insn
.tm
->flags
& FL_DELAY
)
4977 /* FIXME -- warn if delay_slots != 0 at EOF. */
4982 /* Do a final adjustment on the symbol table; in this case, make sure we have
4983 a ".file" symbol. */
4986 tic54x_adjust_symtab (void)
4988 if (symbol_rootP
== NULL
4989 || S_GET_STORAGE_CLASS (symbol_rootP
) != C_FILE
)
4992 const char * filename
= as_where (&lineno
);
4993 c_dot_file_symbol (filename
, 0);
4997 /* In order to get gas to ignore any | chars at the start of a line,
4998 this function returns true if a | is found in a line.
4999 This lets us process parallel instructions, which span two lines. */
5002 tic54x_unrecognized_line (int c
)
5004 return c
== PARALLEL_SEPARATOR
;
5007 /* Watch for local labels of the form $[0-9] and [_a-zA-Z][_a-zA-Z0-9]*?
5008 Encode their names so that only we see them and can map them to the
5010 FIXME -- obviously this isn't done yet. These locals still show up in the
5013 tic54x_define_label (symbolS
*sym
)
5015 /* Just in case we need this later; note that this is not necessarily the
5016 same thing as line_label...
5017 When aligning or assigning labels to fields, sometimes the label is
5018 assigned other than the address at which the label appears.
5019 FIXME -- is this really needed? I think all the proper label assignment
5020 is done in tic54x_cons. */
5021 last_label_seen
= sym
;
5024 /* Try to parse something that normal parsing failed at. */
5027 tic54x_undefined_symbol (char *name
)
5031 /* Not sure how to handle predefined symbols. */
5032 if ((sym
= (symbol
*) hash_find (cc_hash
, name
)) != NULL
||
5033 (sym
= (symbol
*) hash_find (cc2_hash
, name
)) != NULL
||
5034 (sym
= (symbol
*) hash_find (cc3_hash
, name
)) != NULL
||
5035 (sym
= (symbol
*) hash_find (misc_symbol_hash
, name
)) != NULL
||
5036 (sym
= (symbol
*) hash_find (sbit_hash
, name
)) != NULL
)
5038 return symbol_new (name
, reg_section
,
5039 (valueT
) sym
->value
,
5040 &zero_address_frag
);
5043 if ((sym
= (symbol
*) hash_find (reg_hash
, name
)) != NULL
||
5044 (sym
= (symbol
*) hash_find (mmreg_hash
, name
)) != NULL
||
5045 !strcasecmp (name
, "a") || !strcasecmp (name
, "b"))
5047 return symbol_new (name
, reg_section
,
5048 (valueT
) sym
? sym
->value
: 0,
5049 &zero_address_frag
);
5055 /* Parse a name in an expression before the expression parser takes a stab at
5059 tic54x_parse_name (char *name ATTRIBUTE_UNUSED
,
5060 expressionS
*expn ATTRIBUTE_UNUSED
)
5066 md_atof (int type
, char *literalP
, int *sizeP
)
5068 /* Target data is little-endian, but floats are stored
5069 big-"word"ian. ugh. */
5070 return ieee_md_atof (type
, literalP
, sizeP
, TRUE
);
5074 tc_gen_reloc (asection
*section
, fixS
*fixP
)
5077 bfd_reloc_code_real_type code
= fixP
->fx_r_type
;
5078 asymbol
*sym
= symbol_get_bfdsym (fixP
->fx_addsy
);
5080 rel
= (arelent
*) xmalloc (sizeof (arelent
));
5081 rel
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
5082 *rel
->sym_ptr_ptr
= sym
;
5083 /* We assume that all rel->address are host byte offsets. */
5084 rel
->address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
5085 rel
->address
/= OCTETS_PER_BYTE
;
5086 rel
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
5087 if (!strcmp (sym
->name
, section
->name
))
5088 rel
->howto
+= HOWTO_BANK
;
5092 const char *name
= S_GET_NAME (fixP
->fx_addsy
);
5095 as_fatal ("Cannot generate relocation type for symbol %s, code %s",
5096 name
, bfd_get_reloc_code_name (code
));
5102 /* Handle cons expressions. */
5105 tic54x_cons_fix_new (fragS
*frag
, int where
, int octets
, expressionS
*expn
,
5106 bfd_reloc_code_real_type r
)
5111 as_bad (_("Unsupported relocation size %d"), octets
);
5112 r
= BFD_RELOC_TIC54X_16_OF_23
;
5115 r
= BFD_RELOC_TIC54X_16_OF_23
;
5118 /* TI assembler always uses this, regardless of addressing mode. */
5120 r
= BFD_RELOC_TIC54X_23
;
5122 /* We never want to directly generate this; this is provided for
5123 stabs support only. */
5127 fix_new_exp (frag
, where
, octets
, expn
, 0, r
);
5130 /* Attempt to simplify or even eliminate a fixup.
5131 To indicate that a fixup has been eliminated, set fixP->fx_done.
5133 If fixp->fx_addsy is non-NULL, we'll have to generate a reloc entry. */
5136 md_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg ATTRIBUTE_UNUSED
)
5138 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
5139 valueT val
= * valP
;
5141 switch (fixP
->fx_r_type
)
5144 as_fatal ("Bad relocation type: 0x%02x", fixP
->fx_r_type
);
5146 case BFD_RELOC_TIC54X_MS7_OF_23
:
5147 val
= (val
>> 16) & 0x7F;
5149 case BFD_RELOC_TIC54X_16_OF_23
:
5151 bfd_put_16 (stdoutput
, val
, buf
);
5152 /* Indicate what we're actually writing, so that we don't get warnings
5153 about exceeding available space. */
5154 *valP
= val
& 0xFFFF;
5156 case BFD_RELOC_TIC54X_PARTLS7
:
5157 bfd_put_16 (stdoutput
,
5158 (bfd_get_16 (stdoutput
, buf
) & 0xFF80) | (val
& 0x7F),
5160 /* Indicate what we're actually writing, so that we don't get warnings
5161 about exceeding available space. */
5164 case BFD_RELOC_TIC54X_PARTMS9
:
5165 /* TI assembler doesn't shift its encoding for relocatable files, and is
5166 thus incompatible with this implementation's relocatable files. */
5167 bfd_put_16 (stdoutput
,
5168 (bfd_get_16 (stdoutput
, buf
) & 0xFE00) | (val
>> 7),
5172 case BFD_RELOC_TIC54X_23
:
5173 bfd_put_32 (stdoutput
,
5174 (bfd_get_32 (stdoutput
, buf
) & 0xFF800000) | val
,
5179 if (fixP
->fx_addsy
== NULL
&& fixP
->fx_pcrel
== 0)
5183 /* This is our chance to record section alignment
5184 don't need to do anything here, since BFD does the proper encoding. */
5187 md_section_align (segT segment ATTRIBUTE_UNUSED
, valueT section_size
)
5189 return section_size
;
5193 md_pcrel_from (fixS
*fixP ATTRIBUTE_UNUSED
)
5198 /* Mostly little-endian, but longwords (4 octets) get MS word stored
5202 tic54x_number_to_chars (char *buf
, valueT val
, int n
)
5205 number_to_chars_littleendian (buf
, val
, n
);
5208 number_to_chars_littleendian (buf
, val
>> 16 , 2);
5209 number_to_chars_littleendian (buf
+ 2, val
& 0xFFFF, 2);
5214 tic54x_estimate_size_before_relax (fragS
*frag ATTRIBUTE_UNUSED
,
5215 segT seg ATTRIBUTE_UNUSED
)
5220 /* We use this to handle bit allocations which we couldn't handle before due
5221 to symbols being in different frags. return number of octets added. */
5224 tic54x_relax_frag (fragS
*frag
, long stretch ATTRIBUTE_UNUSED
)
5226 symbolS
*sym
= frag
->fr_symbol
;
5232 struct bit_info
*bi
= (struct bit_info
*) frag
->fr_opcode
;
5233 int bit_offset
= frag_bit_offset (frag_prev (frag
, bi
->seg
), bi
->seg
);
5234 int size
= S_GET_VALUE (sym
);
5235 fragS
*prev_frag
= bit_offset_frag (frag_prev (frag
, bi
->seg
), bi
->seg
);
5236 int available
= 16 - bit_offset
;
5238 if (symbol_get_frag (sym
) != &zero_address_frag
5239 || S_IS_COMMON (sym
)
5240 || !S_IS_DEFINED (sym
))
5241 as_bad_where (frag
->fr_file
, frag
->fr_line
,
5242 _("non-absolute value used with .space/.bes"));
5246 as_warn (_("negative value ignored in %s"),
5247 bi
->type
== TYPE_SPACE
? ".space" :
5248 bi
->type
== TYPE_BES
? ".bes" : ".field");
5250 frag
->tc_frag_data
= frag
->fr_fix
= 0;
5254 if (bi
->type
== TYPE_FIELD
)
5256 /* Bit fields of 16 or larger will have already been handled. */
5257 if (bit_offset
!= 0 && available
>= size
)
5259 char *p
= prev_frag
->fr_literal
;
5261 valueT value
= bi
->value
;
5262 value
<<= available
- size
;
5263 value
|= ((unsigned short) p
[1] << 8) | p
[0];
5264 md_number_to_chars (p
, value
, 2);
5265 if ((prev_frag
->tc_frag_data
+= size
) == 16)
5266 prev_frag
->tc_frag_data
= 0;
5268 symbol_set_frag (bi
->sym
, prev_frag
);
5269 /* This frag is no longer used. */
5270 growth
= -frag
->fr_fix
;
5272 frag
->tc_frag_data
= 0;
5276 char *p
= frag
->fr_literal
;
5278 valueT value
= bi
->value
<< (16 - size
);
5279 md_number_to_chars (p
, value
, 2);
5280 if ((frag
->tc_frag_data
= size
) == 16)
5281 frag
->tc_frag_data
= 0;
5287 if (bit_offset
!= 0 && bit_offset
< 16)
5289 if (available
>= size
)
5291 if ((prev_frag
->tc_frag_data
+= size
) == 16)
5292 prev_frag
->tc_frag_data
= 0;
5294 symbol_set_frag (bi
->sym
, prev_frag
);
5295 /* This frag is no longer used. */
5296 growth
= -frag
->fr_fix
;
5298 frag
->tc_frag_data
= 0;
5301 if (bi
->type
== TYPE_SPACE
&& bi
->sym
)
5302 symbol_set_frag (bi
->sym
, prev_frag
);
5305 growth
= (size
+ 15) / 16 * OCTETS_PER_BYTE
- frag
->fr_fix
;
5306 for (i
= 0; i
< growth
; i
++)
5307 frag
->fr_literal
[i
] = 0;
5308 frag
->fr_fix
= growth
;
5309 frag
->tc_frag_data
= size
% 16;
5310 /* Make sure any BES label points to the LAST word allocated. */
5311 if (bi
->type
== TYPE_BES
&& bi
->sym
)
5312 S_SET_VALUE (bi
->sym
, frag
->fr_fix
/ OCTETS_PER_BYTE
- 1);
5315 frag
->fr_symbol
= 0;
5316 frag
->fr_opcode
= 0;
5323 tic54x_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
,
5324 segT seg ATTRIBUTE_UNUSED
,
5327 /* Offset is in bytes. */
5328 frag
->fr_offset
= (frag
->fr_next
->fr_address
5330 - frag
->fr_fix
) / frag
->fr_var
;
5331 if (frag
->fr_offset
< 0)
5333 as_bad_where (frag
->fr_file
, frag
->fr_line
,
5334 _("attempt to .space/.bes backwards? (%ld)"),
5335 (long) frag
->fr_offset
);
5337 frag
->fr_type
= rs_space
;
5340 /* We need to avoid having labels defined for certain directives/pseudo-ops
5341 since once the label is defined, it's in the symbol table for good. TI
5342 syntax puts the symbol *before* the pseudo (which is kinda like MRI syntax,
5343 I guess, except I've never seen a definition of MRI syntax).
5345 Don't allow labels to start with '.' */
5348 tic54x_start_label (int nul_char
, int next_char
)
5352 /* If within .struct/.union, no auto line labels, please. */
5353 if (current_stag
!= NULL
)
5356 /* Disallow labels starting with "." */
5357 if (next_char
!= ':')
5359 char *label
= input_line_pointer
;
5361 while (!is_end_of_line
[(int) label
[-1]])
5365 as_bad (_("Invalid label '%s'"), label
);
5370 if (is_end_of_line
[(int) next_char
])
5373 rest
= input_line_pointer
;
5374 if (nul_char
== '"')
5376 while (ISSPACE (next_char
))
5377 next_char
= *++rest
;
5378 if (next_char
!= '.')
5381 /* Don't let colon () define a label for any of these... */
5382 return ((strncasecmp (rest
, ".tag", 4) != 0 || !ISSPACE (rest
[4]))
5383 && (strncasecmp (rest
, ".struct", 7) != 0 || !ISSPACE (rest
[7]))
5384 && (strncasecmp (rest
, ".union", 6) != 0 || !ISSPACE (rest
[6]))
5385 && (strncasecmp (rest
, ".macro", 6) != 0 || !ISSPACE (rest
[6]))
5386 && (strncasecmp (rest
, ".set", 4) != 0 || !ISSPACE (rest
[4]))
5387 && (strncasecmp (rest
, ".equ", 4) != 0 || !ISSPACE (rest
[4])));