1 /* tc-tic54x.c -- Assembly code for the Texas Instruments TMS320C54X
2 Copyright (C) 1999-2019 Free Software Foundation, Inc.
3 Contributed by Timothy Wall (twall@cygnus.com)
5 This file is part of GAS, the GNU Assembler.
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
22 /* Texas Instruments TMS320C54X machine specific gas.
23 Written by Timothy Wall (twall@alum.mit.edu).
25 Valuable things to do:
26 Pipeline conflict warnings
27 We encode/decode "ld #_label, dp" differently in relocatable files
28 This means we're not compatible with TI output containing those
29 expressions. We store the upper nine bits; TI stores the lower nine
30 bits. How they recover the original upper nine bits is beyond me.
32 Tests to add to expect testsuite:
33 '=' and '==' with .if, .elseif, and .break
35 Incompatibilities (mostly trivial):
37 We fill text section with zeroes instead of "nop"s
38 We don't convert '' or "" to a single instance
39 We don't convert '' to '\0'
40 We don't allow strings with .byte/.half/.short/.long
41 Probably details of the subsym stuff are different
42 TI sets labels to be data type 4 (T_INT); GAS uses T_NULL.
44 COFF1 limits section names to 8 characters.
45 Some of the default behavior changed from COFF1 to COFF2. */
49 #include "safe-ctype.h"
53 #include "opcode/tic54x.h"
60 symbolS
*sym
; /* Symbol for this stag; value is offset. */
61 const char *name
; /* Shortcut to symbol name. */
62 bfd_vma size
; /* Size of struct/union. */
63 int current_bitfield_offset
; /* Temporary for tracking fields. */
65 struct stag_field
/* List of fields. */
68 bfd_vma offset
; /* Of start of this field. */
69 int bitfield_offset
; /* Of start of this field. */
70 struct stag
*stag
; /* If field is struct/union. */
71 struct stag_field
*next
;
73 /* For nesting; used only in stag construction. */
74 struct stag
*inner
; /* Enclosed .struct. */
75 struct stag
*outer
; /* Enclosing .struct. */
76 } *current_stag
= NULL
;
78 #define MAX_LINE 256 /* Lines longer than this are truncated by TI's asm. */
80 typedef struct _tic54x_insn
82 const insn_template
*tm
; /* Opcode template. */
84 char mnemonic
[MAX_LINE
]; /* Opcode name/mnemonic. */
85 char parmnemonic
[MAX_LINE
]; /* 2nd mnemonic of parallel insn. */
93 } operands
[MAX_OPERANDS
];
96 struct opstruct paroperands
[MAX_OPERANDS
];
100 int words
; /* Size of insn in 16-bit words. */
101 int using_default_dst
; /* Do we need to explicitly set an
102 omitted OP_DST operand? */
105 unsigned short word
; /* Final encoded opcode data. */
107 int r_nchars
; /* Relocation size. */
108 bfd_reloc_code_real_type r_type
; /* Relocation type. */
109 expressionS addr_expr
; /* Storage for unresolved expressions. */
115 VNONE
= 0, V541
= 1, V542
= 2, V543
= 3, V545
= 5, V548
= 8, V549
= 9,
116 V545LP
= 15, V546LP
= 16
121 c_mode
, /* 16-bit addresses. */
122 far_mode
/* >16-bit addresses. */
125 static segT stag_saved_seg
;
126 static subsegT stag_saved_subseg
;
128 const char comment_chars
[] = ";";
129 const char line_comment_chars
[] = ";*#"; /* At column zero only. */
130 const char line_separator_chars
[] = ""; /* Not permitted. */
132 int emitting_long
= 0;
134 /* Characters which indicate that this is a floating point constant. */
135 const char FLT_CHARS
[] = "fF";
137 /* Characters that can be used to separate mantissa from exp in FP
139 const char EXP_CHARS
[] = "eE";
141 const char *md_shortopts
= "";
143 #define OPTION_ADDRESS_MODE (OPTION_MD_BASE)
144 #define OPTION_CPU_VERSION (OPTION_ADDRESS_MODE + 1)
145 #define OPTION_COFF_VERSION (OPTION_CPU_VERSION + 1)
146 #define OPTION_STDERR_TO_FILE (OPTION_COFF_VERSION + 1)
148 struct option md_longopts
[] =
150 { "mfar-mode", no_argument
, NULL
, OPTION_ADDRESS_MODE
},
151 { "mf", no_argument
, NULL
, OPTION_ADDRESS_MODE
},
152 { "mcpu", required_argument
, NULL
, OPTION_CPU_VERSION
},
153 { "merrors-to-file", required_argument
, NULL
, OPTION_STDERR_TO_FILE
},
154 { "me", required_argument
, NULL
, OPTION_STDERR_TO_FILE
},
155 { NULL
, no_argument
, NULL
, 0},
158 size_t md_longopts_size
= sizeof (md_longopts
);
160 static int assembly_begun
= 0;
161 /* Addressing mode is not entirely implemented; the latest rev of the Other
162 assembler doesn't seem to make any distinction whatsoever; all relocations
163 are stored as extended relocations. Older versions used REL16 vs RELEXT16,
164 but now it seems all relocations are RELEXT16. We use all RELEXT16.
166 The cpu version is kind of a waste of time as well. There is one
167 instruction (RND) for LP devices only, and several for devices with
168 extended addressing only. We include it for compatibility. */
169 static enum address_mode amode
= c_mode
;
170 static enum cpu_version cpu
= VNONE
;
172 /* Include string substitutions in listing? */
173 static int listing_sslist
= 0;
175 /* Did we do subsym substitutions on the line? */
176 static int substitution_line
= 0;
178 /* Last label seen. */
179 static symbolS
*last_label_seen
= NULL
;
181 /* This ensures that all new labels are unique. */
182 static int local_label_id
;
184 static struct hash_control
*subsym_recurse_hash
; /* Prevent infinite recurse. */
185 static struct hash_control
*math_hash
; /* Built-in math functions. */
186 /* Allow maximum levels of macro nesting; level 0 is the main substitution
187 symbol table. The other assembler only does 32 levels, so there! */
188 static struct hash_control
*subsym_hash
[100];
190 /* Keep track of local labels so we can substitute them before GAS sees them
191 since macros use their own 'namespace' for local labels, use a separate hash
193 We do our own local label handling 'cuz it's subtly different from the
196 We use our own macro nesting counter, since GAS overloads it when expanding
197 other things (like conditionals and repeat loops). */
198 static int macro_level
= 0;
199 static struct hash_control
*local_label_hash
[100];
200 /* Keep track of struct/union tags. */
201 static struct hash_control
*stag_hash
;
202 static struct hash_control
*op_hash
;
203 static struct hash_control
*parop_hash
;
204 static struct hash_control
*reg_hash
;
205 static struct hash_control
*mmreg_hash
;
206 static struct hash_control
*cc_hash
;
207 static struct hash_control
*cc2_hash
;
208 static struct hash_control
*cc3_hash
;
209 static struct hash_control
*sbit_hash
;
210 static struct hash_control
*misc_symbol_hash
;
212 /* Only word (et al.), align, or conditionals are allowed within
214 #define ILLEGAL_WITHIN_STRUCT() \
216 if (current_stag != NULL) \
218 as_bad (_("pseudo-op illegal within .struct/.union")); \
224 static void subsym_create_or_replace (char *, char *);
225 static char *subsym_lookup (char *, int);
226 static char *subsym_substitute (char *, int);
230 md_show_usage (FILE *stream
)
232 fprintf (stream
, _("C54x-specific command line options:\n"));
233 fprintf (stream
, _("-mfar-mode | -mf Use extended addressing\n"));
234 fprintf (stream
, _("-mcpu=<CPU version> Specify the CPU version\n"));
235 fprintf (stream
, _("-merrors-to-file <filename>\n"));
236 fprintf (stream
, _("-me <filename> Redirect errors to a file\n"));
239 /* Output a single character (upper octet is zero). */
242 tic54x_emit_char (char c
)
246 expn
.X_op
= O_constant
;
247 expn
.X_add_number
= c
;
248 emit_expr (&expn
, 2);
251 /* Walk backwards in the frag chain. */
254 frag_prev (fragS
*frag
, segT seg
)
256 segment_info_type
*seginfo
= seg_info (seg
);
259 for (fragp
= seginfo
->frchainP
->frch_root
; fragp
; fragp
= fragp
->fr_next
)
260 if (fragp
->fr_next
== frag
)
267 bit_offset_frag (fragS
*frag
, segT seg
)
271 if (frag
->fr_fix
== 0
272 && frag
->fr_opcode
== NULL
273 && frag
->tc_frag_data
== 0)
274 frag
= frag_prev (frag
, seg
);
281 /* Return the number of bits allocated in the most recent word, or zero if
282 none. .field/.space/.bes may leave words partially allocated. */
285 frag_bit_offset (fragS
*frag
, segT seg
)
287 frag
= bit_offset_frag (frag
, seg
);
290 return frag
->fr_opcode
!= NULL
? -1 : frag
->tc_frag_data
;
295 /* Read an expression from a C string; returns a pointer past the end of the
299 parse_expression (char *str
, expressionS
*expn
)
304 tmp
= input_line_pointer
; /* Save line pointer. */
305 input_line_pointer
= str
;
307 s
= input_line_pointer
;
308 input_line_pointer
= tmp
; /* Restore line pointer. */
309 return s
; /* Return pointer to where parsing stopped. */
312 /* .asg "character-string"|character-string, symbol
314 .eval is the only pseudo-op allowed to perform arithmetic on substitution
315 symbols. all other use of symbols defined with .asg are currently
319 tic54x_asg (int x ATTRIBUTE_UNUSED
)
324 int quoted
= *input_line_pointer
== '"';
326 ILLEGAL_WITHIN_STRUCT ();
331 str
= demand_copy_C_string (&len
);
332 c
= *input_line_pointer
;
336 str
= input_line_pointer
;
337 while ((c
= *input_line_pointer
) != ',')
339 if (is_end_of_line
[(int) *input_line_pointer
])
341 ++input_line_pointer
;
343 *input_line_pointer
= 0;
347 as_bad (_("Comma and symbol expected for '.asg STRING, SYMBOL'"));
348 ignore_rest_of_line ();
352 ++input_line_pointer
;
353 c
= get_symbol_name (&name
); /* Get terminator. */
354 if (!ISALPHA (*name
))
356 as_bad (_("symbols assigned with .asg must begin with a letter"));
357 ignore_rest_of_line ();
362 name
= xstrdup (name
);
363 subsym_create_or_replace (name
, str
);
364 (void) restore_line_pointer (c
);
365 demand_empty_rest_of_line ();
368 /* .eval expression, symbol
369 There's something screwy about this. The other assembler sometimes does and
370 sometimes doesn't substitute symbols defined with .eval.
371 We'll put the symbols into the subsym table as well as the normal symbol
372 table, since that's what works best. */
375 tic54x_eval (int x ATTRIBUTE_UNUSED
)
381 char valuestr
[32], *tmp
;
384 ILLEGAL_WITHIN_STRUCT ();
388 quoted
= *input_line_pointer
== '"';
390 ++input_line_pointer
;
391 value
= get_absolute_expression ();
394 if (*input_line_pointer
!= '"')
396 as_bad (_("Unterminated string after absolute expression"));
397 ignore_rest_of_line ();
400 ++input_line_pointer
;
402 if (*input_line_pointer
++ != ',')
404 as_bad (_("Comma and symbol expected for '.eval EXPR, SYMBOL'"));
405 ignore_rest_of_line ();
408 c
= get_symbol_name (&name
); /* Get terminator. */
409 name
= xstrdup (name
);
410 (void) restore_line_pointer (c
);
412 if (!ISALPHA (*name
))
414 as_bad (_("symbols assigned with .eval must begin with a letter"));
415 ignore_rest_of_line ();
418 symbolP
= symbol_new (name
, absolute_section
,
419 (valueT
) value
, &zero_address_frag
);
420 SF_SET_LOCAL (symbolP
);
421 symbol_table_insert (symbolP
);
423 /* The "other" assembler sometimes doesn't put .eval's in the subsym table
424 But since there's not written rule as to when, don't even bother trying
425 to match their behavior. */
426 sprintf (valuestr
, "%d", value
);
427 tmp
= xstrdup (valuestr
);
428 subsym_create_or_replace (name
, tmp
);
430 demand_empty_rest_of_line ();
433 /* .bss symbol, size [, [blocking flag] [, alignment flag]
435 alignment is to a longword boundary; blocking is to 128-word boundary.
437 1) if there is a hole in memory, this directive should attempt to fill it
438 (not yet implemented).
440 2) if the blocking flag is not set, allocate at the current SPC
441 otherwise, check to see if the current SPC plus the space to be
442 allocated crosses the page boundary (128 words).
443 if there's not enough space, create a hole and align with the next page
445 (not yet implemented). */
448 tic54x_bss (int x ATTRIBUTE_UNUSED
)
455 subsegT current_subseg
;
460 ILLEGAL_WITHIN_STRUCT ();
462 current_seg
= now_seg
; /* Save current seg. */
463 current_subseg
= now_subseg
; /* Save current subseg. */
465 c
= get_symbol_name (&name
); /* Get terminator. */
467 c
= * ++ input_line_pointer
;
470 as_bad (_(".bss size argument missing\n"));
471 ignore_rest_of_line ();
475 ++input_line_pointer
;
476 words
= get_absolute_expression ();
479 as_bad (_(".bss size %d < 0!"), words
);
480 ignore_rest_of_line ();
484 if (*input_line_pointer
== ',')
486 /* The blocking flag may be missing. */
487 ++input_line_pointer
;
488 if (*input_line_pointer
!= ',')
489 block
= get_absolute_expression ();
493 if (*input_line_pointer
== ',')
495 ++input_line_pointer
;
496 align
= get_absolute_expression ();
504 subseg_set (bss_section
, 0);
505 symbolP
= symbol_find_or_make (name
);
507 if (S_GET_SEGMENT (symbolP
) == bss_section
)
508 symbol_get_frag (symbolP
)->fr_symbol
= (symbolS
*) NULL
;
510 symbol_set_frag (symbolP
, frag_now
);
511 p
= frag_var (rs_org
, 1, 1, (relax_substateT
) 0, symbolP
,
512 (offsetT
) (words
* OCTETS_PER_BYTE
), (char *) 0);
513 *p
= 0; /* Fill char. */
515 S_SET_SEGMENT (symbolP
, bss_section
);
517 /* The symbol may already have been created with a preceding
518 ".globl" directive -- be careful not to step on storage class
519 in that case. Otherwise, set it to static. */
520 if (S_GET_STORAGE_CLASS (symbolP
) != C_EXT
)
521 S_SET_STORAGE_CLASS (symbolP
, C_STAT
);
525 /* s_align eats end of line; restore it */
527 --input_line_pointer
;
531 bss_section
->flags
|= SEC_TIC54X_BLOCK
;
533 subseg_set (current_seg
, current_subseg
); /* Restore current seg. */
534 demand_empty_rest_of_line ();
538 stag_add_field_symbols (struct stag
*stag
,
542 const char *root_stag_name
)
545 struct stag_field
*field
= stag
->field
;
547 /* Construct a symbol for every field contained within this structure
548 including fields within structure fields. */
549 prefix
= concat (path
, *path
? "." : "", NULL
);
551 while (field
!= NULL
)
553 char *name
= concat (prefix
, field
->name
, NULL
);
558 sym
= symbol_new (name
, absolute_section
,
559 (field
->stag
? field
->offset
:
560 (valueT
) (base_offset
+ field
->offset
)),
563 symbol_table_insert (sym
);
569 replacement
= concat (S_GET_NAME (rootsym
), "+", root_stag_name
,
570 name
+ strlen (S_GET_NAME (rootsym
)), NULL
);
571 hash_insert (subsym_hash
[0], name
, replacement
);
574 /* Recurse if the field is a structure.
575 Note the field offset is relative to the outermost struct. */
576 if (field
->stag
!= NULL
)
577 stag_add_field_symbols (field
->stag
, name
,
579 rootsym
, root_stag_name
);
586 /* Keep track of stag fields so that when structures are nested we can add the
587 complete dereferencing symbols to the symbol table. */
590 stag_add_field (struct stag
*parent
,
595 struct stag_field
*sfield
= XCNEW (struct stag_field
);
597 sfield
->name
= xstrdup (name
);
598 sfield
->offset
= offset
;
599 sfield
->bitfield_offset
= parent
->current_bitfield_offset
;
601 if (parent
->field
== NULL
)
602 parent
->field
= sfield
;
605 struct stag_field
*sf
= parent
->field
;
606 while (sf
->next
!= NULL
)
610 /* Only create a symbol for this field if the parent has no name. */
611 if (!strncmp (".fake", parent
->name
, 5))
613 symbolS
*sym
= symbol_new (name
, absolute_section
,
614 (valueT
) offset
, &zero_address_frag
);
616 symbol_table_insert (sym
);
620 /* [STAG] .struct [OFFSET]
621 Start defining structure offsets (symbols in absolute section). */
624 tic54x_struct (int arg
)
626 int start_offset
= 0;
631 /* Starting a new struct, switch to absolute section. */
632 stag_saved_seg
= now_seg
;
633 stag_saved_subseg
= now_subseg
;
634 subseg_set (absolute_section
, 0);
636 /* Align the current pointer. */
637 else if (current_stag
->current_bitfield_offset
!= 0)
639 ++abs_section_offset
;
640 current_stag
->current_bitfield_offset
= 0;
643 /* Offset expression is only meaningful for global .structs. */
646 /* Offset is ignored in inner structs. */
648 if (!is_end_of_line
[(int) *input_line_pointer
])
649 start_offset
= get_absolute_expression ();
656 /* Nesting, link to outer one. */
657 current_stag
->inner
= XCNEW (struct stag
);
658 current_stag
->inner
->outer
= current_stag
;
659 current_stag
= current_stag
->inner
;
661 as_warn (_("Offset on nested structures is ignored"));
662 start_offset
= abs_section_offset
;
666 current_stag
= XCNEW (struct stag
);
667 abs_section_offset
= start_offset
;
669 current_stag
->is_union
= is_union
;
671 if (line_label
== NULL
)
673 static int struct_count
= 0;
674 char fake
[] = ".fake_stagNNNNNNN";
675 sprintf (fake
, ".fake_stag%d", struct_count
++);
676 current_stag
->sym
= symbol_new (fake
, absolute_section
,
677 (valueT
) abs_section_offset
,
682 char * label
= xstrdup (S_GET_NAME (line_label
));
683 current_stag
->sym
= symbol_new (label
,
685 (valueT
) abs_section_offset
,
689 current_stag
->name
= S_GET_NAME (current_stag
->sym
);
690 SF_SET_LOCAL (current_stag
->sym
);
691 /* Nested .structs don't go into the symbol table. */
692 if (current_stag
->outer
== NULL
)
693 symbol_table_insert (current_stag
->sym
);
698 /* [LABEL] .endstruct
699 finish defining structure offsets; optional LABEL's value will be the size
703 tic54x_endstruct (int is_union
)
707 !strncmp (current_stag
->name
, ".fake", 5) ? "" : current_stag
->name
;
709 if (!current_stag
|| current_stag
->is_union
!= is_union
)
711 as_bad (_(".end%s without preceding .%s"),
712 is_union
? "union" : "struct",
713 is_union
? "union" : "struct");
714 ignore_rest_of_line ();
718 /* Align end of structures. */
719 if (current_stag
->current_bitfield_offset
)
721 ++abs_section_offset
;
722 current_stag
->current_bitfield_offset
= 0;
725 if (current_stag
->is_union
)
726 size
= current_stag
->size
;
728 size
= abs_section_offset
- S_GET_VALUE (current_stag
->sym
);
729 if (line_label
!= NULL
)
731 S_SET_VALUE (line_label
, size
);
732 symbol_table_insert (line_label
);
736 /* Union size has already been calculated. */
737 if (!current_stag
->is_union
)
738 current_stag
->size
= size
;
739 /* Nested .structs don't get put in the stag table. */
740 if (current_stag
->outer
== NULL
)
742 hash_insert (stag_hash
, current_stag
->name
, current_stag
);
743 stag_add_field_symbols (current_stag
, path
,
744 S_GET_VALUE (current_stag
->sym
),
747 current_stag
= current_stag
->outer
;
749 /* If this is a nested .struct/.union, add it as a field to the enclosing
750 one. otherwise, restore the section we were in. */
751 if (current_stag
!= NULL
)
753 stag_add_field (current_stag
, current_stag
->inner
->name
,
754 S_GET_VALUE (current_stag
->inner
->sym
),
755 current_stag
->inner
);
758 subseg_set (stag_saved_seg
, stag_saved_subseg
);
762 Reference a structure within a structure, as a sized field with an optional
764 If used outside of a .struct/.endstruct, overlays the given structure
765 format on the existing allocated space. */
768 tic54x_tag (int ignore ATTRIBUTE_UNUSED
)
771 int c
= get_symbol_name (&name
);
772 struct stag
*stag
= (struct stag
*) hash_find (stag_hash
, name
);
777 as_bad (_("Unrecognized struct/union tag '%s'"), name
);
779 as_bad (_(".tag requires a structure tag"));
780 ignore_rest_of_line ();
783 if (line_label
== NULL
)
785 as_bad (_("Label required for .tag"));
786 ignore_rest_of_line ();
793 label
= xstrdup (S_GET_NAME (line_label
));
794 if (current_stag
!= NULL
)
795 stag_add_field (current_stag
, label
,
796 abs_section_offset
- S_GET_VALUE (current_stag
->sym
),
800 symbolS
*sym
= symbol_find (label
);
804 as_bad (_(".tag target '%s' undefined"), label
);
805 ignore_rest_of_line ();
809 stag_add_field_symbols (stag
, S_GET_NAME (sym
),
810 S_GET_VALUE (stag
->sym
), sym
, stag
->name
);
815 /* Bump by the struct size, but only if we're within a .struct section. */
816 if (current_stag
!= NULL
&& !current_stag
->is_union
)
817 abs_section_offset
+= stag
->size
;
819 (void) restore_line_pointer (c
);
820 demand_empty_rest_of_line ();
824 /* Handle all .byte, .char, .double, .field, .float, .half, .int, .long,
825 .short, .string, .ubyte, .uchar, .uhalf, .uint, .ulong, .ushort, .uword,
829 tic54x_struct_field (int type
)
833 int new_bitfield_offset
= 0;
834 int field_align
= current_stag
->current_bitfield_offset
!= 0;
835 int longword_align
= 0;
838 if (!is_end_of_line
[(int) *input_line_pointer
])
839 count
= get_absolute_expression ();
855 case '*': /* String. */
864 case '.': /* Bitfield. */
866 if (count
< 1 || count
> 32)
868 as_bad (_(".field count '%d' out of range (1 <= X <= 32)"), count
);
869 ignore_rest_of_line ();
872 if (current_stag
->current_bitfield_offset
+ count
> 16)
874 /* Set the appropriate size and new field offset. */
884 new_bitfield_offset
= count
- 16;
887 new_bitfield_offset
= count
;
892 new_bitfield_offset
= current_stag
->current_bitfield_offset
+ count
;
896 as_bad (_("Unrecognized field type '%c'"), type
);
897 ignore_rest_of_line ();
903 /* Align to the actual starting position of the field. */
904 current_stag
->current_bitfield_offset
= 0;
905 ++abs_section_offset
;
907 /* Align to longword boundary. */
908 if (longword_align
&& (abs_section_offset
& 0x1))
909 ++abs_section_offset
;
911 if (line_label
== NULL
)
913 static int fieldno
= 0;
914 char fake
[] = ".fake_fieldNNNNN";
916 sprintf (fake
, ".fake_field%d", fieldno
++);
917 stag_add_field (current_stag
, fake
,
918 abs_section_offset
- S_GET_VALUE (current_stag
->sym
),
925 label
= xstrdup (S_GET_NAME (line_label
));
926 stag_add_field (current_stag
, label
,
927 abs_section_offset
- S_GET_VALUE (current_stag
->sym
),
932 if (current_stag
->is_union
)
934 /* Note we treat the element as if it were an array of COUNT. */
935 if (current_stag
->size
< (unsigned) size
* count
)
936 current_stag
->size
= size
* count
;
940 abs_section_offset
+= (unsigned) size
* count
;
941 current_stag
->current_bitfield_offset
= new_bitfield_offset
;
946 /* Handle .byte, .word. .int, .long and all variants. */
949 tic54x_cons (int type
)
954 /* If we're within a .struct construct, don't actually allocate space. */
955 if (current_stag
!= NULL
)
957 tic54x_struct_field (type
);
961 #ifdef md_flush_pending_output
962 md_flush_pending_output ();
965 generate_lineno_debug ();
967 /* Align long words to long word boundaries (4 octets). */
968 if (type
== 'l' || type
== 'L')
970 frag_align (2, 0, 2);
971 /* If there's a label, assign it to the first allocated word. */
972 if (line_label
!= NULL
)
974 symbol_set_frag (line_label
, frag_now
);
975 S_SET_VALUE (line_label
, frag_now_fix ());
999 if (*input_line_pointer
== '"')
1001 input_line_pointer
++;
1002 while (is_a_char (c
= next_char_of_string ()))
1003 tic54x_emit_char (c
);
1004 know (input_line_pointer
[-1] == '\"');
1010 input_line_pointer
= parse_expression (input_line_pointer
, &expn
);
1011 if (expn
.X_op
== O_constant
)
1013 offsetT value
= expn
.X_add_number
;
1014 /* Truncate overflows. */
1018 if ((value
> 0 && value
> 0xFF)
1019 || (value
< 0 && value
< - 0x100))
1020 as_warn (_("Overflow in expression, truncated to 8 bits"));
1023 if ((value
> 0 && value
> 0xFFFF)
1024 || (value
< 0 && value
< - 0x10000))
1025 as_warn (_("Overflow in expression, truncated to 16 bits"));
1029 if (expn
.X_op
!= O_constant
&& octets
< 2)
1031 /* Disallow .byte with a non constant expression that will
1032 require relocation. */
1033 as_bad (_("Relocatable values require at least WORD storage"));
1034 ignore_rest_of_line ();
1038 if (expn
.X_op
!= O_constant
1042 /* FIXME -- at one point TI tools used to output REL16
1043 relocations, but I don't think the latest tools do at all
1044 The current tools output extended relocations regardless of
1045 the addressing mode (I actually think that ".c_mode" is
1046 totally ignored in the latest tools). */
1049 emit_expr (&expn
, 4);
1055 emitting_long
= octets
== 4;
1056 emit_expr (&expn
, (octets
== 1) ? 2 : octets
);
1061 while (*input_line_pointer
++ == ',');
1063 input_line_pointer
--; /* Put terminator back into stream. */
1064 demand_empty_rest_of_line ();
1067 /* .global <symbol>[,...,<symbolN>]
1068 .def <symbol>[,...,<symbolN>]
1069 .ref <symbol>[,...,<symbolN>]
1071 These all identify global symbols.
1073 .def means the symbol is defined in the current module and can be accessed
1074 by other files. The symbol should be placed in the symbol table.
1076 .ref means the symbol is used in the current module but defined in another
1077 module. The linker is to resolve this symbol's definition at link time.
1079 .global should act as a .ref or .def, as needed.
1081 global, def and ref all have symbol storage classes of C_EXT.
1083 I can't identify any difference in how the "other" c54x assembler treats
1084 these, so we ignore the type here. */
1087 tic54x_global (int type
)
1094 as_warn (_("Use of .def/.ref is deprecated. Use .global instead"));
1096 ILLEGAL_WITHIN_STRUCT ();
1100 c
= get_symbol_name (&name
);
1101 symbolP
= symbol_find_or_make (name
);
1102 c
= restore_line_pointer (c
);
1104 S_SET_STORAGE_CLASS (symbolP
, C_EXT
);
1107 input_line_pointer
++;
1108 if (is_end_of_line
[(int) *input_line_pointer
])
1109 c
= *input_line_pointer
;
1114 demand_empty_rest_of_line ();
1117 /* Remove the symbol from the local label hash lookup. */
1120 tic54x_remove_local_label (const char *key
, void *value ATTRIBUTE_UNUSED
)
1122 void *elem
= hash_delete (local_label_hash
[macro_level
], key
, FALSE
);
1126 /* Reset all local labels. */
1129 tic54x_clear_local_labels (int ignored ATTRIBUTE_UNUSED
)
1131 hash_traverse (local_label_hash
[macro_level
], tic54x_remove_local_label
);
1136 .sect "section name"
1139 make sure local labels get cleared when changing sections
1141 ARG is 't' for text, 'd' for data, or '*' for a named section
1143 For compatibility, '*' sections are SEC_CODE if instructions are
1144 encountered, or SEC_DATA if not.
1148 tic54x_sect (int arg
)
1150 ILLEGAL_WITHIN_STRUCT ();
1152 /* Local labels are cleared when changing sections. */
1153 tic54x_clear_local_labels (0);
1157 else if (arg
== 'd')
1163 /* Make sure all named initialized sections flagged properly. If we
1164 encounter instructions, we'll flag it with SEC_CODE as well. */
1165 const char *flags
= ",\"w\"\n";
1167 /* If there are quotes, remove them. */
1168 if (*input_line_pointer
== '"')
1170 name
= demand_copy_C_string (&len
);
1171 demand_empty_rest_of_line ();
1172 name
= concat (name
, flags
, (char *) NULL
);
1178 c
= get_symbol_name (&name
);
1179 name
= concat (name
, flags
, (char *) NULL
);
1180 (void) restore_line_pointer (c
);
1181 demand_empty_rest_of_line ();
1184 input_scrub_insert_line (name
);
1185 obj_coff_section (0);
1187 /* If there was a line label, make sure that it gets assigned the proper
1188 section. This is for compatibility, even though the actual behavior
1189 is not explicitly defined. For consistency, we make .sect behave
1190 like .usect, since that is probably what people expect. */
1191 if (line_label
!= NULL
)
1193 S_SET_SEGMENT (line_label
, now_seg
);
1194 symbol_set_frag (line_label
, frag_now
);
1195 S_SET_VALUE (line_label
, frag_now_fix ());
1196 if (S_GET_STORAGE_CLASS (line_label
) != C_EXT
)
1197 S_SET_STORAGE_CLASS (line_label
, C_LABEL
);
1202 /* [symbol] .space space_in_bits
1203 [symbol] .bes space_in_bits
1204 BES puts the symbol at the *last* word allocated
1206 cribbed from s_space. */
1209 tic54x_space (int arg
)
1215 int bits_per_byte
= (OCTETS_PER_BYTE
* 8);
1217 symbolS
*label
= line_label
;
1220 ILLEGAL_WITHIN_STRUCT ();
1222 #ifdef md_flush_pending_output
1223 md_flush_pending_output ();
1226 /* Read the bit count. */
1229 /* Some expressions are unresolvable until later in the assembly pass;
1230 postpone until relaxation/fixup. we also have to postpone if a previous
1231 partial allocation has not been completed yet. */
1232 if (expn
.X_op
!= O_constant
|| frag_bit_offset (frag_now
, now_seg
) == -1)
1234 struct bit_info
*bi
= XNEW (struct bit_info
);
1239 p
= frag_var (rs_machine_dependent
,
1240 65536 * 2, 1, (relax_substateT
) 0,
1241 make_expr_symbol (&expn
), (offsetT
) 0,
1249 /* Reduce the required size by any bit offsets currently left over
1250 from a previous .space/.bes/.field directive. */
1251 bit_offset
= frag_now
->tc_frag_data
;
1252 if (bit_offset
!= 0 && bit_offset
< 16)
1254 int spare_bits
= bits_per_byte
- bit_offset
;
1256 if (spare_bits
>= expn
.X_add_number
)
1258 /* Don't have to do anything; sufficient bits have already been
1259 allocated; just point the label to the right place. */
1262 symbol_set_frag (label
, frag_now
);
1263 S_SET_VALUE (label
, frag_now_fix () - 1);
1266 frag_now
->tc_frag_data
+= expn
.X_add_number
;
1269 expn
.X_add_number
-= spare_bits
;
1270 /* Set the label to point to the first word allocated, which in this
1271 case is the previous word, which was only partially filled. */
1272 if (!bes
&& label
!= NULL
)
1274 symbol_set_frag (label
, frag_now
);
1275 S_SET_VALUE (label
, frag_now_fix () - 1);
1279 /* Convert bits to bytes/words and octets, rounding up. */
1280 words
= ((expn
.X_add_number
+ bits_per_byte
- 1) / bits_per_byte
);
1281 /* How many do we have left over? */
1282 bit_offset
= expn
.X_add_number
% bits_per_byte
;
1283 octets
= words
* OCTETS_PER_BYTE
;
1286 as_warn (_(".space/.bes repeat count is negative, ignored"));
1289 else if (octets
== 0)
1291 as_warn (_(".space/.bes repeat count is zero, ignored"));
1295 /* If we are in the absolute section, just bump the offset. */
1296 if (now_seg
== absolute_section
)
1298 abs_section_offset
+= words
;
1299 if (bes
&& label
!= NULL
)
1300 S_SET_VALUE (label
, abs_section_offset
- 1);
1301 frag_now
->tc_frag_data
= bit_offset
;
1306 p
= frag_var (rs_fill
, 1, 1,
1307 (relax_substateT
) 0, (symbolS
*) 0,
1308 (offsetT
) octets
, (char *) 0);
1310 /* Make note of how many bits of this word we've allocated so far. */
1311 frag_now
->tc_frag_data
= bit_offset
;
1313 /* .bes puts label at *last* word allocated. */
1314 if (bes
&& label
!= NULL
)
1316 symbol_set_frag (label
, frag_now
);
1317 S_SET_VALUE (label
, frag_now_fix () - 1);
1325 demand_empty_rest_of_line ();
1328 /* [symbol] .usect "section-name", size-in-words
1329 [, [blocking-flag] [, alignment-flag]]
1331 Uninitialized section.
1332 Non-zero blocking means that if the section would cross a page (128-word)
1333 boundary, it will be page-aligned.
1334 Non-zero alignment aligns on a longword boundary.
1336 Has no effect on the current section. */
1339 tic54x_usect (int x ATTRIBUTE_UNUSED
)
1346 int size
, blocking_flag
, alignment_flag
;
1348 subsegT current_subseg
;
1351 ILLEGAL_WITHIN_STRUCT ();
1353 current_seg
= now_seg
; /* Save current seg. */
1354 current_subseg
= now_subseg
; /* Save current subseg. */
1356 c
= get_symbol_name (§ion_name
); /* Get terminator. */
1357 name
= xstrdup (section_name
);
1358 c
= restore_line_pointer (c
);
1361 ++input_line_pointer
;
1364 as_bad (_("Missing size argument"));
1365 ignore_rest_of_line ();
1369 size
= get_absolute_expression ();
1371 /* Read a possibly present third argument (blocking flag). */
1372 if (*input_line_pointer
== ',')
1374 ++input_line_pointer
;
1375 if (*input_line_pointer
!= ',')
1376 blocking_flag
= get_absolute_expression ();
1380 /* Read a possibly present fourth argument (alignment flag). */
1381 if (*input_line_pointer
== ',')
1383 ++input_line_pointer
;
1384 alignment_flag
= get_absolute_expression ();
1390 blocking_flag
= alignment_flag
= 0;
1392 seg
= subseg_new (name
, 0);
1393 flags
= bfd_get_section_flags (stdoutput
, seg
) | SEC_ALLOC
;
1397 /* s_align eats end of line; restore it. */
1399 --input_line_pointer
;
1402 if (line_label
!= NULL
)
1404 S_SET_SEGMENT (line_label
, seg
);
1405 symbol_set_frag (line_label
, frag_now
);
1406 S_SET_VALUE (line_label
, frag_now_fix ());
1407 /* Set scl to label, since that's what TI does. */
1408 if (S_GET_STORAGE_CLASS (line_label
) != C_EXT
)
1409 S_SET_STORAGE_CLASS (line_label
, C_LABEL
);
1412 seg_info (seg
)->bss
= 1; /* Uninitialized data. */
1414 p
= frag_var (rs_fill
, 1, 1,
1415 (relax_substateT
) 0, (symbolS
*) line_label
,
1416 size
* OCTETS_PER_BYTE
, (char *) 0);
1420 flags
|= SEC_TIC54X_BLOCK
;
1422 if (!bfd_set_section_flags (stdoutput
, seg
, flags
))
1423 as_warn (_("Error setting flags for \"%s\": %s"), name
,
1424 bfd_errmsg (bfd_get_error ()));
1426 subseg_set (current_seg
, current_subseg
); /* Restore current seg. */
1427 demand_empty_rest_of_line ();
1430 static enum cpu_version
1431 lookup_version (const char *ver
)
1433 enum cpu_version version
= VNONE
;
1435 if (ver
[0] == '5' && ver
[1] == '4')
1437 if (strlen (ver
) == 3
1438 && (ver
[2] == '1' || ver
[2] == '2' || ver
[2] == '3'
1439 || ver
[2] == '5' || ver
[2] == '8' || ver
[2] == '9'))
1440 version
= ver
[2] - '0';
1441 else if (strlen (ver
) == 5
1442 && TOUPPER (ver
[3]) == 'L'
1443 && TOUPPER (ver
[4]) == 'P'
1444 && (ver
[2] == '5' || ver
[2] == '6'))
1445 version
= ver
[2] - '0' + 10;
1452 set_cpu (enum cpu_version version
)
1455 if (version
== V545LP
|| version
== V546LP
)
1457 symbolS
*symbolP
= symbol_new ("__allow_lp", absolute_section
,
1458 (valueT
) 1, &zero_address_frag
);
1459 SF_SET_LOCAL (symbolP
);
1460 symbol_table_insert (symbolP
);
1464 /* .version cpu-version
1465 cpu-version may be one of the following:
1475 This is for compatibility only. It currently has no affect on assembly. */
1476 static int cpu_needs_set
= 1;
1479 tic54x_version (int x ATTRIBUTE_UNUSED
)
1481 enum cpu_version version
= VNONE
;
1482 enum cpu_version old_version
= cpu
;
1486 ILLEGAL_WITHIN_STRUCT ();
1489 ver
= input_line_pointer
;
1490 while (!is_end_of_line
[(int) *input_line_pointer
])
1491 ++input_line_pointer
;
1492 c
= *input_line_pointer
;
1493 *input_line_pointer
= 0;
1495 version
= lookup_version (ver
);
1497 if (cpu
!= VNONE
&& cpu
!= version
)
1498 as_warn (_("CPU version has already been set"));
1500 if (version
== VNONE
)
1502 as_bad (_("Unrecognized version '%s'"), ver
);
1503 ignore_rest_of_line ();
1506 else if (assembly_begun
&& version
!= old_version
)
1508 as_bad (_("Changing of CPU version on the fly not supported"));
1509 ignore_rest_of_line ();
1515 *input_line_pointer
= c
;
1516 demand_empty_rest_of_line ();
1519 /* 'f' = float, 'x' = xfloat, 'd' = double, 'l' = ldouble. */
1522 tic54x_float_cons (int type
)
1524 if (current_stag
!= 0)
1525 tic54x_struct_field ('f');
1527 #ifdef md_flush_pending_output
1528 md_flush_pending_output ();
1531 /* Align to long word boundary (4 octets) unless it's ".xfloat". */
1534 frag_align (2, 0, 2);
1535 /* If there's a label, assign it to the first allocated word. */
1536 if (line_label
!= NULL
)
1538 symbol_set_frag (line_label
, frag_now
);
1539 S_SET_VALUE (line_label
, frag_now_fix ());
1546 /* The argument is capitalized if it should be zero-terminated
1547 's' is normal string with upper 8-bits zero-filled, 'p' is packed.
1548 Code copied from stringer, and slightly modified so that strings are packed
1549 and encoded into the correct octets. */
1552 tic54x_stringer (int type
)
1555 int append_zero
= type
== 'S' || type
== 'P';
1556 int packed
= type
== 'p' || type
== 'P';
1557 int last_char
= -1; /* Packed strings need two bytes at a time to encode. */
1559 if (current_stag
!= NULL
)
1561 tic54x_struct_field ('*');
1565 #ifdef md_flush_pending_output
1566 md_flush_pending_output ();
1569 c
= ','; /* Do loop. */
1573 switch (*input_line_pointer
)
1577 unsigned short value
= get_absolute_expression ();
1578 FRAG_APPEND_1_CHAR ( value
& 0xFF);
1579 FRAG_APPEND_1_CHAR ((value
>> 8) & 0xFF);
1583 ++input_line_pointer
; /* -> 1st char of string. */
1584 while (is_a_char (c
= next_char_of_string ()))
1588 FRAG_APPEND_1_CHAR (c
);
1589 FRAG_APPEND_1_CHAR (0);
1593 /* Packed strings are filled MS octet first. */
1594 if (last_char
== -1)
1598 FRAG_APPEND_1_CHAR (c
);
1599 FRAG_APPEND_1_CHAR (last_char
);
1606 if (packed
&& last_char
!= -1)
1608 FRAG_APPEND_1_CHAR (0);
1609 FRAG_APPEND_1_CHAR (last_char
);
1614 FRAG_APPEND_1_CHAR (0);
1615 FRAG_APPEND_1_CHAR (0);
1618 know (input_line_pointer
[-1] == '\"');
1622 c
= *input_line_pointer
;
1623 if (!is_end_of_line
[c
])
1624 ++input_line_pointer
;
1627 /* Finish up any leftover packed string. */
1628 if (packed
&& last_char
!= -1)
1630 FRAG_APPEND_1_CHAR (0);
1631 FRAG_APPEND_1_CHAR (last_char
);
1633 demand_empty_rest_of_line ();
1637 tic54x_p2align (int arg ATTRIBUTE_UNUSED
)
1639 as_bad (_("p2align not supported on this target"));
1643 tic54x_align_words (int arg
)
1645 /* Only ".align" with no argument is allowed within .struct/.union. */
1648 if (!is_end_of_line
[(int) *input_line_pointer
])
1651 as_warn (_("Argument to .even ignored"));
1653 count
= get_absolute_expression ();
1656 if (current_stag
!= NULL
&& arg
== 128)
1658 if (current_stag
->current_bitfield_offset
!= 0)
1660 current_stag
->current_bitfield_offset
= 0;
1661 ++abs_section_offset
;
1663 demand_empty_rest_of_line ();
1667 ILLEGAL_WITHIN_STRUCT ();
1669 s_align_bytes (count
<< 1);
1672 /* Initialize multiple-bit fields within a single word of memory. */
1675 tic54x_field (int ignore ATTRIBUTE_UNUSED
)
1681 symbolS
*label
= line_label
;
1683 if (current_stag
!= NULL
)
1685 tic54x_struct_field ('.');
1689 input_line_pointer
= parse_expression (input_line_pointer
, &expn
);
1691 if (*input_line_pointer
== ',')
1693 ++input_line_pointer
;
1694 size
= get_absolute_expression ();
1695 if (size
< 1 || size
> 32)
1697 as_bad (_("Invalid field size, must be from 1 to 32"));
1698 ignore_rest_of_line ();
1703 /* Truncate values to the field width. */
1704 if (expn
.X_op
!= O_constant
)
1706 /* If the expression value is relocatable, the field size *must*
1710 as_bad (_("field size must be 16 when value is relocatable"));
1711 ignore_rest_of_line ();
1715 frag_now
->tc_frag_data
= 0;
1716 emit_expr (&expn
, 2);
1720 unsigned long fmask
= (size
== 32) ? 0xFFFFFFFF : (1ul << size
) - 1;
1722 value
= expn
.X_add_number
;
1723 expn
.X_add_number
&= fmask
;
1724 if (value
!= (valueT
) expn
.X_add_number
)
1725 as_warn (_("field value truncated"));
1726 value
= expn
.X_add_number
;
1727 /* Bits are stored MS first. */
1730 frag_now
->tc_frag_data
= 0;
1732 md_number_to_chars (p
, (value
>> (size
- 16)) & 0xFFFF, 2);
1737 int bit_offset
= frag_bit_offset (frag_now
, now_seg
);
1739 fragS
*alloc_frag
= bit_offset_frag (frag_now
, now_seg
);
1740 if (bit_offset
== -1)
1742 struct bit_info
*bi
= XNEW (struct bit_info
);
1743 /* We don't know the previous offset at this time, so store the
1744 info we need and figure it out later. */
1745 expressionS size_exp
;
1747 size_exp
.X_op
= O_constant
;
1748 size_exp
.X_add_number
= size
;
1750 bi
->type
= TYPE_FIELD
;
1752 p
= frag_var (rs_machine_dependent
,
1753 4, 1, (relax_substateT
) 0,
1754 make_expr_symbol (&size_exp
), (offsetT
) 0,
1758 else if (bit_offset
== 0 || bit_offset
+ size
> 16)
1760 /* Align a new field. */
1762 frag_now
->tc_frag_data
= 0;
1763 alloc_frag
= frag_now
;
1767 /* Put the new value entirely within the existing one. */
1768 p
= alloc_frag
== frag_now
?
1769 frag_now
->fr_literal
+ frag_now_fix_octets () - 2 :
1770 alloc_frag
->fr_literal
;
1773 symbol_set_frag (label
, alloc_frag
);
1774 if (alloc_frag
== frag_now
)
1775 S_SET_VALUE (label
, frag_now_fix () - 1);
1779 value
<<= 16 - alloc_frag
->tc_frag_data
- size
;
1781 /* OR in existing value. */
1782 if (alloc_frag
->tc_frag_data
)
1783 value
|= ((unsigned short) p
[1] << 8) | p
[0];
1784 md_number_to_chars (p
, value
, 2);
1785 alloc_frag
->tc_frag_data
+= size
;
1786 if (alloc_frag
->tc_frag_data
== 16)
1787 alloc_frag
->tc_frag_data
= 0;
1791 demand_empty_rest_of_line ();
1794 /* Ideally, we want to check SEC_LOAD and SEC_HAS_CONTENTS, but those aren't
1795 available yet. seg_info ()->bss is the next best thing. */
1798 tic54x_initialized_section (segT seg
)
1800 return !seg_info (seg
)->bss
;
1803 /* .clink ["section name"]
1805 Marks the section as conditionally linked (link only if contents are
1806 referenced elsewhere.
1807 Without a name, refers to the current initialized section.
1808 Name is required for uninitialized sections. */
1811 tic54x_clink (int ignored ATTRIBUTE_UNUSED
)
1815 ILLEGAL_WITHIN_STRUCT ();
1817 if (*input_line_pointer
== '\"')
1819 char *section_name
= ++input_line_pointer
;
1822 while (is_a_char (next_char_of_string ()))
1824 know (input_line_pointer
[-1] == '\"');
1825 input_line_pointer
[-1] = 0;
1826 name
= xstrdup (section_name
);
1828 seg
= bfd_get_section_by_name (stdoutput
, name
);
1831 as_bad (_("Unrecognized section '%s'"), section_name
);
1832 ignore_rest_of_line ();
1838 if (!tic54x_initialized_section (seg
))
1840 as_bad (_("Current section is uninitialized, "
1841 "section name required for .clink"));
1842 ignore_rest_of_line ();
1847 seg
->flags
|= SEC_TIC54X_CLINK
;
1849 demand_empty_rest_of_line ();
1852 /* Change the default include directory to be the current source file's
1853 directory, instead of the current working directory. If DOT is non-zero,
1854 set to "." instead. */
1857 tic54x_set_default_include (void)
1859 char *dir
, *tmp
= NULL
;
1860 const char *curfile
;
1863 curfile
= as_where (&lineno
);
1864 dir
= xstrdup (curfile
);
1865 tmp
= strrchr (dir
, '/');
1872 if (include_dir_count
== 0)
1874 include_dirs
= XNEWVEC (const char *, 1);
1875 include_dir_count
= 1;
1877 include_dirs
[0] = dir
;
1878 if (len
> include_dir_maxlen
)
1879 include_dir_maxlen
= len
;
1881 else if (include_dirs
!= NULL
)
1882 include_dirs
[0] = ".";
1885 /* .include "filename" | filename
1886 .copy "filename" | filename
1888 FIXME 'include' file should be omitted from any output listing,
1889 'copy' should be included in any output listing
1890 FIXME -- prevent any included files from changing listing (compat only)
1891 FIXME -- need to include source file directory in search path; what's a
1892 good way to do this?
1894 Entering/exiting included/copied file clears all local labels. */
1897 tic54x_include (int ignored ATTRIBUTE_UNUSED
)
1899 char newblock
[] = " .newblock\n";
1904 ILLEGAL_WITHIN_STRUCT ();
1908 if (*input_line_pointer
== '"')
1910 filename
= demand_copy_C_string (&len
);
1911 demand_empty_rest_of_line ();
1915 filename
= input_line_pointer
;
1916 while (!is_end_of_line
[(int) *input_line_pointer
])
1917 ++input_line_pointer
;
1918 c
= *input_line_pointer
;
1919 *input_line_pointer
= '\0';
1920 filename
= xstrdup (filename
);
1921 *input_line_pointer
= c
;
1922 demand_empty_rest_of_line ();
1924 /* Insert a partial line with the filename (for the sake of s_include)
1926 The included file will be inserted before the newblock, so that the
1927 newblock is executed after the included file is processed. */
1928 input
= concat ("\"", filename
, "\"\n", newblock
, (char *) NULL
);
1929 input_scrub_insert_line (input
);
1931 tic54x_clear_local_labels (0);
1933 tic54x_set_default_include ();
1939 tic54x_message (int type
)
1945 ILLEGAL_WITHIN_STRUCT ();
1947 if (*input_line_pointer
== '"')
1948 msg
= demand_copy_C_string (&len
);
1951 msg
= input_line_pointer
;
1952 while (!is_end_of_line
[(int) *input_line_pointer
])
1953 ++input_line_pointer
;
1954 c
= *input_line_pointer
;
1955 *input_line_pointer
= 0;
1956 msg
= xstrdup (msg
);
1957 *input_line_pointer
= c
;
1963 as_tsktsk ("%s", msg
);
1966 as_warn ("%s", msg
);
1973 demand_empty_rest_of_line ();
1977 Define a special symbol that refers to the loadtime address rather than the
1978 runtime address within the current section.
1980 This symbol gets a special storage class so that when it is resolved, it is
1981 resolved relative to the load address (lma) of the section rather than the
1982 run address (vma). */
1985 tic54x_label (int ignored ATTRIBUTE_UNUSED
)
1991 ILLEGAL_WITHIN_STRUCT ();
1993 c
= get_symbol_name (&name
);
1994 symbolP
= colon (name
);
1995 S_SET_STORAGE_CLASS (symbolP
, C_STATLAB
);
1997 (void) restore_line_pointer (c
);
1998 demand_empty_rest_of_line ();
2002 Install all memory-mapped register names into the symbol table as
2003 absolute local symbols. */
2006 tic54x_mmregs (int ignored ATTRIBUTE_UNUSED
)
2010 ILLEGAL_WITHIN_STRUCT ();
2012 for (sym
= (tic54x_symbol
*) mmregs
; sym
->name
; sym
++)
2014 symbolS
*symbolP
= symbol_new (sym
->name
, absolute_section
,
2015 (valueT
) sym
->value
, &zero_address_frag
);
2016 SF_SET_LOCAL (symbolP
);
2017 symbol_table_insert (symbolP
);
2022 Count defaults to 1024. */
2025 tic54x_loop (int count
)
2027 ILLEGAL_WITHIN_STRUCT ();
2030 if (!is_end_of_line
[(int) *input_line_pointer
])
2031 count
= get_absolute_expression ();
2033 do_repeat ((size_t) count
, "LOOP", "ENDLOOP");
2036 /* Normally, endloop gets eaten by the preceding loop. */
2039 tic54x_endloop (int ignore ATTRIBUTE_UNUSED
)
2041 as_bad (_("ENDLOOP without corresponding LOOP"));
2042 ignore_rest_of_line ();
2045 /* .break [condition]. */
2048 tic54x_break (int ignore ATTRIBUTE_UNUSED
)
2052 ILLEGAL_WITHIN_STRUCT ();
2055 if (!is_end_of_line
[(int) *input_line_pointer
])
2056 cond
= get_absolute_expression ();
2059 end_repeat (substitution_line
? 1 : 0);
2063 set_address_mode (int mode
)
2066 if (mode
== far_mode
)
2068 symbolS
*symbolP
= symbol_new ("__allow_far", absolute_section
,
2069 (valueT
) 1, &zero_address_frag
);
2070 SF_SET_LOCAL (symbolP
);
2071 symbol_table_insert (symbolP
);
2075 static int address_mode_needs_set
= 1;
2078 tic54x_address_mode (int mode
)
2080 if (assembly_begun
&& amode
!= (unsigned) mode
)
2082 as_bad (_("Mixing of normal and extended addressing not supported"));
2083 ignore_rest_of_line ();
2086 if (mode
== far_mode
&& cpu
!= VNONE
&& cpu
!= V548
&& cpu
!= V549
)
2088 as_bad (_("Extended addressing not supported on the specified CPU"));
2089 ignore_rest_of_line ();
2093 set_address_mode (mode
);
2094 demand_empty_rest_of_line ();
2097 /* .sblock "section"|section [,...,"section"|section]
2098 Designate initialized sections for blocking. */
2101 tic54x_sblock (int ignore ATTRIBUTE_UNUSED
)
2105 ILLEGAL_WITHIN_STRUCT ();
2112 if (*input_line_pointer
== '"')
2116 name
= demand_copy_C_string (&len
);
2122 c
= get_symbol_name (§ion_name
);
2123 name
= xstrdup (section_name
);
2124 (void) restore_line_pointer (c
);
2127 seg
= bfd_get_section_by_name (stdoutput
, name
);
2130 as_bad (_("Unrecognized section '%s'"), name
);
2131 ignore_rest_of_line ();
2134 else if (!tic54x_initialized_section (seg
))
2136 as_bad (_(".sblock may be used for initialized sections only"));
2137 ignore_rest_of_line ();
2140 seg
->flags
|= SEC_TIC54X_BLOCK
;
2142 c
= *input_line_pointer
;
2143 if (!is_end_of_line
[(int) c
])
2144 ++input_line_pointer
;
2147 demand_empty_rest_of_line ();
2150 /* symbol .set value
2153 value must be defined externals; no forward-referencing allowed
2154 symbols assigned with .set/.equ may not be redefined. */
2157 tic54x_set (int ignore ATTRIBUTE_UNUSED
)
2162 ILLEGAL_WITHIN_STRUCT ();
2166 as_bad (_("Symbol missing for .set/.equ"));
2167 ignore_rest_of_line ();
2170 name
= xstrdup (S_GET_NAME (line_label
));
2172 if ((symbolP
= symbol_find (name
)) == NULL
2173 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
2175 symbolP
= symbol_new (name
, absolute_section
, 0, &zero_address_frag
);
2176 S_SET_STORAGE_CLASS (symbolP
, C_STAT
);
2179 S_SET_DATA_TYPE (symbolP
, T_INT
);
2180 S_SET_SEGMENT (symbolP
, absolute_section
);
2181 symbol_table_insert (symbolP
);
2182 pseudo_set (symbolP
);
2183 demand_empty_rest_of_line ();
2188 List false conditional blocks. */
2191 tic54x_fclist (int show
)
2194 listing
&= ~LISTING_NOCOND
;
2196 listing
|= LISTING_NOCOND
;
2197 demand_empty_rest_of_line ();
2201 tic54x_sslist (int show
)
2203 ILLEGAL_WITHIN_STRUCT ();
2205 listing_sslist
= show
;
2208 /* .var SYM[,...,SYMN]
2209 Define a substitution string to be local to a macro. */
2212 tic54x_var (int ignore ATTRIBUTE_UNUSED
)
2214 static char empty
[] = "";
2218 ILLEGAL_WITHIN_STRUCT ();
2220 if (macro_level
== 0)
2222 as_bad (_(".var may only be used within a macro definition"));
2223 ignore_rest_of_line ();
2228 if (!ISALPHA (*input_line_pointer
))
2230 as_bad (_("Substitution symbols must begin with a letter"));
2231 ignore_rest_of_line ();
2234 c
= get_symbol_name (&name
);
2235 /* .var symbols start out with a null string. */
2236 name
= xstrdup (name
);
2237 hash_insert (subsym_hash
[macro_level
], name
, empty
);
2238 c
= restore_line_pointer (c
);
2241 ++input_line_pointer
;
2242 if (is_end_of_line
[(int) *input_line_pointer
])
2243 c
= *input_line_pointer
;
2248 demand_empty_rest_of_line ();
2251 /* .mlib <macro library filename>
2253 Macro libraries are archived (standard AR-format) text macro definitions
2254 Expand the file and include it.
2256 FIXME need to try the source file directory as well. */
2259 tic54x_mlib (int ignore ATTRIBUTE_UNUSED
)
2266 ILLEGAL_WITHIN_STRUCT ();
2268 /* Parse the filename. */
2269 if (*input_line_pointer
== '"')
2271 if ((filename
= demand_copy_C_string (&len
)) == NULL
)
2278 while (!is_end_of_line
[(int) *input_line_pointer
]
2279 && !ISSPACE (*input_line_pointer
))
2281 obstack_1grow (¬es
, *input_line_pointer
);
2282 ++input_line_pointer
;
2285 obstack_1grow (¬es
, '\0');
2286 filename
= obstack_finish (¬es
);
2288 demand_empty_rest_of_line ();
2290 tic54x_set_default_include ();
2291 path
= XNEWVEC (char, (unsigned long) len
+ include_dir_maxlen
+ 5);
2293 for (i
= 0; i
< include_dir_count
; i
++)
2297 strcpy (path
, include_dirs
[i
]);
2299 strcat (path
, filename
);
2300 if ((try = fopen (path
, "r")) != NULL
)
2307 if (i
>= include_dir_count
)
2313 /* FIXME: if path is found, malloc'd storage is not freed. Of course, this
2314 happens all over the place, and since the assembler doesn't usually keep
2315 running for a very long time, it really doesn't matter. */
2316 register_dependency (path
);
2318 /* Expand all archive entries to temporary files and include them. */
2319 abfd
= bfd_openr (path
, NULL
);
2322 as_bad (_("can't open macro library file '%s' for reading: %s"),
2323 path
, bfd_errmsg (bfd_get_error ()));
2324 ignore_rest_of_line ();
2327 if (!bfd_check_format (abfd
, bfd_archive
))
2329 as_bad (_("File '%s' not in macro archive format"), path
);
2330 ignore_rest_of_line ();
2334 /* Open each BFD as binary (it should be straight ASCII text). */
2335 for (mbfd
= bfd_openr_next_archived_file (abfd
, NULL
);
2336 mbfd
!= NULL
; mbfd
= bfd_openr_next_archived_file (abfd
, mbfd
))
2338 /* Get a size at least as big as the archive member. */
2339 bfd_size_type size
= bfd_get_size (mbfd
);
2340 char *buf
= XNEWVEC (char, size
);
2341 char *fname
= tmpnam (NULL
);
2344 /* We're not sure how big it is, but it will be smaller than "size". */
2345 size
= bfd_bread (buf
, size
, mbfd
);
2347 /* Write to a temporary file, then use s_include to include it
2349 ftmp
= fopen (fname
, "w+b");
2350 fwrite ((void *) buf
, size
, 1, ftmp
);
2351 if (size
== 0 || buf
[size
- 1] != '\n')
2352 fwrite ("\n", 1, 1, ftmp
);
2355 input_scrub_insert_file (fname
);
2360 const pseudo_typeS md_pseudo_table
[] =
2362 { "algebraic", s_ignore
, 0 },
2363 { "align" , tic54x_align_words
, 128 },
2364 { "ascii" , tic54x_stringer
, 'p' },
2365 { "asciz" , tic54x_stringer
, 'P' },
2366 { "even" , tic54x_align_words
, 2 },
2367 { "asg" , tic54x_asg
, 0 },
2368 { "eval" , tic54x_eval
, 0 },
2369 { "bss" , tic54x_bss
, 0 },
2370 { "byte" , tic54x_cons
, 'b' },
2371 { "ubyte" , tic54x_cons
, 'B' },
2372 { "char" , tic54x_cons
, 'c' },
2373 { "uchar" , tic54x_cons
, 'C' },
2374 { "clink" , tic54x_clink
, 0 },
2375 { "c_mode" , tic54x_address_mode
, c_mode
},
2376 { "copy" , tic54x_include
, 'c' },
2377 { "include" , tic54x_include
, 'i' },
2378 { "data" , tic54x_sect
, 'd' },
2379 { "double" , tic54x_float_cons
, 'd' },
2380 { "ldouble" , tic54x_float_cons
, 'l' },
2381 { "drlist" , s_ignore
, 0 },
2382 { "drnolist" , s_ignore
, 0 },
2383 { "emsg" , tic54x_message
, 'e' },
2384 { "mmsg" , tic54x_message
, 'm' },
2385 { "wmsg" , tic54x_message
, 'w' },
2386 { "far_mode" , tic54x_address_mode
, far_mode
},
2387 { "fclist" , tic54x_fclist
, 1 },
2388 { "fcnolist" , tic54x_fclist
, 0 },
2389 { "field" , tic54x_field
, -1 },
2390 { "float" , tic54x_float_cons
, 'f' },
2391 { "xfloat" , tic54x_float_cons
, 'x' },
2392 { "global" , tic54x_global
, 'g' },
2393 { "def" , tic54x_global
, 'd' },
2394 { "ref" , tic54x_global
, 'r' },
2395 { "half" , tic54x_cons
, 'h' },
2396 { "uhalf" , tic54x_cons
, 'H' },
2397 { "short" , tic54x_cons
, 's' },
2398 { "ushort" , tic54x_cons
, 'S' },
2399 { "if" , s_if
, (int) O_ne
},
2400 { "elseif" , s_elseif
, (int) O_ne
},
2401 { "else" , s_else
, 0 },
2402 { "endif" , s_endif
, 0 },
2403 { "int" , tic54x_cons
, 'i' },
2404 { "uint" , tic54x_cons
, 'I' },
2405 { "word" , tic54x_cons
, 'w' },
2406 { "uword" , tic54x_cons
, 'W' },
2407 { "label" , tic54x_label
, 0 }, /* Loadtime
2409 { "length" , s_ignore
, 0 },
2410 { "width" , s_ignore
, 0 },
2411 { "long" , tic54x_cons
, 'l' },
2412 { "ulong" , tic54x_cons
, 'L' },
2413 { "xlong" , tic54x_cons
, 'x' },
2414 { "loop" , tic54x_loop
, 1024 },
2415 { "break" , tic54x_break
, 0 },
2416 { "endloop" , tic54x_endloop
, 0 },
2417 { "mlib" , tic54x_mlib
, 0 },
2418 { "mlist" , s_ignore
, 0 },
2419 { "mnolist" , s_ignore
, 0 },
2420 { "mmregs" , tic54x_mmregs
, 0 },
2421 { "newblock" , tic54x_clear_local_labels
, 0 },
2422 { "option" , s_ignore
, 0 },
2423 { "p2align" , tic54x_p2align
, 0 },
2424 { "sblock" , tic54x_sblock
, 0 },
2425 { "sect" , tic54x_sect
, '*' },
2426 { "set" , tic54x_set
, 0 },
2427 { "equ" , tic54x_set
, 0 },
2428 { "space" , tic54x_space
, 0 },
2429 { "bes" , tic54x_space
, 1 },
2430 { "sslist" , tic54x_sslist
, 1 },
2431 { "ssnolist" , tic54x_sslist
, 0 },
2432 { "string" , tic54x_stringer
, 's' },
2433 { "pstring" , tic54x_stringer
, 'p' },
2434 { "struct" , tic54x_struct
, 0 },
2435 { "tag" , tic54x_tag
, 0 },
2436 { "endstruct", tic54x_endstruct
, 0 },
2437 { "tab" , s_ignore
, 0 },
2438 { "text" , tic54x_sect
, 't' },
2439 { "union" , tic54x_struct
, 1 },
2440 { "endunion" , tic54x_endstruct
, 1 },
2441 { "usect" , tic54x_usect
, 0 },
2442 { "var" , tic54x_var
, 0 },
2443 { "version" , tic54x_version
, 0 },
2448 md_parse_option (int c
, const char *arg
)
2454 case OPTION_COFF_VERSION
:
2456 int version
= atoi (arg
);
2458 if (version
!= 0 && version
!= 1 && version
!= 2)
2459 as_fatal (_("Bad COFF version '%s'"), arg
);
2460 /* FIXME -- not yet implemented. */
2463 case OPTION_CPU_VERSION
:
2465 cpu
= lookup_version (arg
);
2468 as_fatal (_("Bad CPU version '%s'"), arg
);
2471 case OPTION_ADDRESS_MODE
:
2473 address_mode_needs_set
= 1;
2475 case OPTION_STDERR_TO_FILE
:
2477 const char *filename
= arg
;
2478 FILE *fp
= fopen (filename
, "w+");
2481 as_fatal (_("Can't redirect stderr to the file '%s'"), filename
);
2483 if ((fp
= freopen (filename
, "w+", stderr
)) == NULL
)
2484 as_fatal (_("Can't redirect stderr to the file '%s'"), filename
);
2492 /* Create a "local" substitution string hash table for a new macro level
2493 Some docs imply that macros have to use .newblock in order to be able
2494 to re-use a local label. We effectively do an automatic .newblock by
2495 deleting the local label hash between macro invocations. */
2498 tic54x_macro_start (void)
2501 subsym_hash
[macro_level
] = hash_new ();
2502 local_label_hash
[macro_level
] = hash_new ();
2506 tic54x_macro_info (const macro_entry
*macro
)
2508 const formal_entry
*entry
;
2510 /* Put the formal args into the substitution symbol table. */
2511 for (entry
= macro
->formals
; entry
; entry
= entry
->next
)
2513 char *name
= xstrndup (entry
->name
.ptr
, entry
->name
.len
);
2514 char *value
= xstrndup (entry
->actual
.ptr
, entry
->actual
.len
);
2516 name
[entry
->name
.len
] = '\0';
2517 value
[entry
->actual
.len
] = '\0';
2518 hash_insert (subsym_hash
[macro_level
], name
, value
);
2522 /* Get rid of this macro's .var's, arguments, and local labels. */
2525 tic54x_macro_end (void)
2527 hash_die (subsym_hash
[macro_level
]);
2528 subsym_hash
[macro_level
] = NULL
;
2529 hash_die (local_label_hash
[macro_level
]);
2530 local_label_hash
[macro_level
] = NULL
;
2535 subsym_symlen (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2540 /* Compare symbol A to string B. */
2543 subsym_symcmp (char *a
, char *b
)
2545 return strcmp (a
, b
);
2548 /* Return the index of the first occurrence of B in A, or zero if none
2549 assumes b is an integer char value as a string. Index is one-based. */
2552 subsym_firstch (char *a
, char *b
)
2555 char *tmp
= strchr (a
, val
);
2557 return tmp
? tmp
- a
+ 1 : 0;
2560 /* Similar to firstch, but returns index of last occurrence of B in A. */
2563 subsym_lastch (char *a
, char *b
)
2566 char *tmp
= strrchr (a
, val
);
2568 return tmp
? tmp
- a
+ 1 : 0;
2571 /* Returns 1 if string A is defined in the symbol table (NOT the substitution
2575 subsym_isdefed (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2577 symbolS
*symbolP
= symbol_find (a
);
2579 return symbolP
!= NULL
;
2582 /* Assign first member of comma-separated list B (e.g. "1,2,3") to the symbol
2583 A, or zero if B is a null string. Both arguments *must* be substitution
2584 symbols, unsubstituted. */
2587 subsym_ismember (char *sym
, char *list
)
2589 char *elem
, *ptr
, *listv
;
2594 listv
= subsym_lookup (list
, macro_level
);
2597 as_bad (_("Undefined substitution symbol '%s'"), list
);
2598 ignore_rest_of_line ();
2602 ptr
= elem
= xstrdup (listv
);
2603 while (*ptr
&& *ptr
!= ',')
2607 subsym_create_or_replace (sym
, elem
);
2609 /* Reassign the list. */
2610 subsym_create_or_replace (list
, ptr
);
2612 /* Assume this value, docs aren't clear. */
2616 /* Return zero if not a constant; otherwise:
2624 subsym_iscons (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2628 parse_expression (a
, &expn
);
2630 if (expn
.X_op
== O_constant
)
2632 int len
= strlen (a
);
2634 switch (TOUPPER (a
[len
- 1]))
2647 /* No suffix; either octal, hex, or decimal. */
2648 if (*a
== '0' && len
> 1)
2650 if (TOUPPER (a
[1]) == 'X')
2660 /* Return 1 if A is a valid symbol name. Expects string input. */
2663 subsym_isname (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2665 if (!is_name_beginner (*a
))
2669 if (!is_part_of_name (*a
))
2676 /* Return whether the string is a register; accepts ar0-7, unless .mmregs has
2677 been seen; if so, recognize any memory-mapped register.
2678 Note this does not recognize "A" or "B" accumulators. */
2681 subsym_isreg (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2683 if (hash_find (reg_hash
, a
))
2685 if (hash_find (mmreg_hash
, a
))
2690 /* Return the structure size, given the stag. */
2693 subsym_structsz (char *name
, char *ignore ATTRIBUTE_UNUSED
)
2695 struct stag
*stag
= (struct stag
*) hash_find (stag_hash
, name
);
2703 /* If anybody actually uses this, they can fix it :)
2704 FIXME I'm not sure what the "reference point" of a structure is. It might
2705 be either the initial offset given .struct, or it may be the offset of the
2706 structure within another structure, or it might be something else
2707 altogether. since the TI assembler doesn't seem to ever do anything but
2708 return zero, we punt and return zero. */
2711 subsym_structacc (char *stag_name ATTRIBUTE_UNUSED
,
2712 char *ignore ATTRIBUTE_UNUSED
)
2718 math_ceil (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2720 return (float) ceil (arg1
);
2724 math_cvi (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2730 math_floor (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2732 return (float) floor (arg1
);
2736 math_fmod (float arg1
, float arg2
)
2738 return (int) arg1
% (int) arg2
;
2742 math_int (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2744 return ((float) ((int) arg1
)) == arg1
;
2748 math_round (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2750 return arg1
> 0 ? (int) (arg1
+ 0.5) : (int) (arg1
- 0.5);
2754 math_sgn (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2756 return (arg1
< 0) ? -1 : (arg1
? 1 : 0);
2760 math_trunc (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2766 math_acos (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2768 return (float) acos (arg1
);
2772 math_asin (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2774 return (float) asin (arg1
);
2778 math_atan (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2780 return (float) atan (arg1
);
2784 math_atan2 (float arg1
, float arg2
)
2786 return (float) atan2 (arg1
, arg2
);
2790 math_cosh (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2792 return (float) cosh (arg1
);
2796 math_cos (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2798 return (float) cos (arg1
);
2802 math_cvf (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2804 return (float) arg1
;
2808 math_exp (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2810 return (float) exp (arg1
);
2814 math_fabs (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2816 return (float) fabs (arg1
);
2819 /* expr1 * 2^expr2. */
2822 math_ldexp (float arg1
, float arg2
)
2824 return arg1
* (float) pow (2.0, arg2
);
2828 math_log10 (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2830 return (float) log10 (arg1
);
2834 math_log (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2836 return (float) log (arg1
);
2840 math_max (float arg1
, float arg2
)
2842 return (arg1
> arg2
) ? arg1
: arg2
;
2846 math_min (float arg1
, float arg2
)
2848 return (arg1
< arg2
) ? arg1
: arg2
;
2852 math_pow (float arg1
, float arg2
)
2854 return (float) pow (arg1
, arg2
);
2858 math_sin (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2860 return (float) sin (arg1
);
2864 math_sinh (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2866 return (float) sinh (arg1
);
2870 math_sqrt (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2872 return (float) sqrt (arg1
);
2876 math_tan (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2878 return (float) tan (arg1
);
2882 math_tanh (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2884 return (float) tanh (arg1
);
2887 /* Built-in substitution symbol functions and math functions. */
2891 int (*proc
) (char *, char *);
2893 } subsym_proc_entry
;
2895 static const subsym_proc_entry subsym_procs
[] =
2897 /* Assembler built-in string substitution functions. */
2898 { "$symlen", subsym_symlen
, 1, },
2899 { "$symcmp", subsym_symcmp
, 2, },
2900 { "$firstch", subsym_firstch
, 2, },
2901 { "$lastch", subsym_lastch
, 2, },
2902 { "$isdefed", subsym_isdefed
, 1, },
2903 { "$ismember", subsym_ismember
, 2, },
2904 { "$iscons", subsym_iscons
, 1, },
2905 { "$isname", subsym_isname
, 1, },
2906 { "$isreg", subsym_isreg
, 1, },
2907 { "$structsz", subsym_structsz
, 1, },
2908 { "$structacc", subsym_structacc
, 1, },
2915 float (*proc
) (float, float);
2920 static const math_proc_entry math_procs
[] =
2922 /* Integer-returning built-in math functions. */
2923 { "$cvi", math_cvi
, 1, 1 },
2924 { "$int", math_int
, 1, 1 },
2925 { "$sgn", math_sgn
, 1, 1 },
2927 /* Float-returning built-in math functions. */
2928 { "$acos", math_acos
, 1, 0 },
2929 { "$asin", math_asin
, 1, 0 },
2930 { "$atan", math_atan
, 1, 0 },
2931 { "$atan2", math_atan2
, 2, 0 },
2932 { "$ceil", math_ceil
, 1, 0 },
2933 { "$cosh", math_cosh
, 1, 0 },
2934 { "$cos", math_cos
, 1, 0 },
2935 { "$cvf", math_cvf
, 1, 0 },
2936 { "$exp", math_exp
, 1, 0 },
2937 { "$fabs", math_fabs
, 1, 0 },
2938 { "$floor", math_floor
, 1, 0 },
2939 { "$fmod", math_fmod
, 2, 0 },
2940 { "$ldexp", math_ldexp
, 2, 0 },
2941 { "$log10", math_log10
, 1, 0 },
2942 { "$log", math_log
, 1, 0 },
2943 { "$max", math_max
, 2, 0 },
2944 { "$min", math_min
, 2, 0 },
2945 { "$pow", math_pow
, 2, 0 },
2946 { "$round", math_round
, 1, 0 },
2947 { "$sin", math_sin
, 1, 0 },
2948 { "$sinh", math_sinh
, 1, 0 },
2949 { "$sqrt", math_sqrt
, 1, 0 },
2950 { "$tan", math_tan
, 1, 0 },
2951 { "$tanh", math_tanh
, 1, 0 },
2952 { "$trunc", math_trunc
, 1, 0 },
2953 { NULL
, NULL
, 0, 0 },
2961 const subsym_proc_entry
*subsym_proc
;
2962 const math_proc_entry
*math_proc
;
2963 const char *hash_err
;
2965 char *TIC54X_DIR
= getenv ("TIC54X_DIR");
2966 char *A_DIR
= TIC54X_DIR
? TIC54X_DIR
: getenv ("A_DIR");
2970 /* Look for A_DIR and add it to the include list. */
2973 char *tmp
= xstrdup (A_DIR
);
2977 char *next
= strchr (tmp
, ';');
2981 add_include_dir (tmp
);
2984 while (tmp
!= NULL
);
2987 op_hash
= hash_new ();
2988 for (tm
= (insn_template
*) tic54x_optab
; tm
->name
; tm
++)
2990 if (hash_find (op_hash
, tm
->name
))
2992 hash_err
= hash_insert (op_hash
, tm
->name
, (char *) tm
);
2994 as_fatal ("Internal Error: Can't hash %s: %s",
2995 tm
->name
, hash_err
);
2997 parop_hash
= hash_new ();
2998 for (tm
= (insn_template
*) tic54x_paroptab
; tm
->name
; tm
++)
3000 if (hash_find (parop_hash
, tm
->name
))
3002 hash_err
= hash_insert (parop_hash
, tm
->name
, (char *) tm
);
3004 as_fatal ("Internal Error: Can't hash %s: %s",
3005 tm
->name
, hash_err
);
3007 reg_hash
= hash_new ();
3008 for (sym
= (tic54x_symbol
*) regs
; sym
->name
; sym
++)
3010 /* Add basic registers to the symbol table. */
3011 symbolS
*symbolP
= symbol_new (sym
->name
, absolute_section
,
3012 (valueT
) sym
->value
, &zero_address_frag
);
3013 SF_SET_LOCAL (symbolP
);
3014 symbol_table_insert (symbolP
);
3015 hash_err
= hash_insert (reg_hash
, sym
->name
, (char *) sym
);
3017 for (sym
= (tic54x_symbol
*) mmregs
; sym
->name
; sym
++)
3018 hash_err
= hash_insert (reg_hash
, sym
->name
, (char *) sym
);
3019 mmreg_hash
= hash_new ();
3020 for (sym
= (tic54x_symbol
*) mmregs
; sym
->name
; sym
++)
3021 hash_err
= hash_insert (mmreg_hash
, sym
->name
, (char *) sym
);
3023 cc_hash
= hash_new ();
3024 for (sym
= (tic54x_symbol
*) condition_codes
; sym
->name
; sym
++)
3025 hash_err
= hash_insert (cc_hash
, sym
->name
, (char *) sym
);
3027 cc2_hash
= hash_new ();
3028 for (sym
= (tic54x_symbol
*) cc2_codes
; sym
->name
; sym
++)
3029 hash_err
= hash_insert (cc2_hash
, sym
->name
, (char *) sym
);
3031 cc3_hash
= hash_new ();
3032 for (sym
= (tic54x_symbol
*) cc3_codes
; sym
->name
; sym
++)
3033 hash_err
= hash_insert (cc3_hash
, sym
->name
, (char *) sym
);
3035 sbit_hash
= hash_new ();
3036 for (sym
= (tic54x_symbol
*) status_bits
; sym
->name
; sym
++)
3037 hash_err
= hash_insert (sbit_hash
, sym
->name
, (char *) sym
);
3039 misc_symbol_hash
= hash_new ();
3040 for (symname
= (char **) misc_symbols
; *symname
; symname
++)
3041 hash_err
= hash_insert (misc_symbol_hash
, *symname
, *symname
);
3043 /* Only the base substitution table and local label table are initialized;
3044 the others (for local macro substitution) get instantiated as needed. */
3045 local_label_hash
[0] = hash_new ();
3046 subsym_hash
[0] = hash_new ();
3047 for (subsym_proc
= subsym_procs
; subsym_proc
->name
; subsym_proc
++)
3048 hash_err
= hash_insert (subsym_hash
[0], subsym_proc
->name
,
3049 (char *) subsym_proc
);
3051 math_hash
= hash_new ();
3052 for (math_proc
= math_procs
; math_proc
->name
; math_proc
++)
3054 /* Insert into the main subsym hash for recognition; insert into
3055 the math hash to actually store information. */
3056 hash_err
= hash_insert (subsym_hash
[0], math_proc
->name
,
3057 (char *) math_proc
);
3058 hash_err
= hash_insert (math_hash
, math_proc
->name
,
3059 (char *) math_proc
);
3061 subsym_recurse_hash
= hash_new ();
3062 stag_hash
= hash_new ();
3066 is_accumulator (struct opstruct
*operand
)
3068 return strcasecmp (operand
->buf
, "a") == 0
3069 || strcasecmp (operand
->buf
, "b") == 0;
3072 /* Return the number of operands found, or -1 on error, copying the
3073 operands into the given array and the accompanying expressions into
3077 get_operands (struct opstruct operands
[], char *line
)
3081 int expecting_operand
= 0;
3084 while (numexp
< MAX_OPERANDS
&& !is_end_of_line
[(int) *lptr
])
3086 int paren_not_balanced
= 0;
3087 char *op_start
, *op_end
;
3089 while (*lptr
&& ISSPACE (*lptr
))
3092 while (paren_not_balanced
|| *lptr
!= ',')
3096 if (paren_not_balanced
)
3098 as_bad (_("Unbalanced parenthesis in operand %d"), numexp
);
3105 ++paren_not_balanced
;
3106 else if (*lptr
== ')')
3107 --paren_not_balanced
;
3111 if (op_end
!= op_start
)
3113 int len
= op_end
- op_start
;
3115 strncpy (operands
[numexp
].buf
, op_start
, len
);
3116 operands
[numexp
].buf
[len
] = 0;
3117 /* Trim trailing spaces; while the preprocessor gets rid of most,
3118 there are weird usage patterns that can introduce them
3119 (i.e. using strings for macro args). */
3120 while (len
> 0 && ISSPACE (operands
[numexp
].buf
[len
- 1]))
3121 operands
[numexp
].buf
[--len
] = 0;
3127 if (expecting_operand
|| *lptr
== ',')
3129 as_bad (_("Expecting operand after ','"));
3135 if (*++lptr
== '\0')
3137 as_bad (_("Expecting operand after ','"));
3140 expecting_operand
= 1;
3144 while (*lptr
&& ISSPACE (*lptr
++))
3146 if (!is_end_of_line
[(int) *lptr
])
3148 as_bad (_("Extra junk on line"));
3152 /* OK, now parse them into expressions. */
3153 for (i
= 0; i
< numexp
; i
++)
3155 memset (&operands
[i
].exp
, 0, sizeof (operands
[i
].exp
));
3156 if (operands
[i
].buf
[0] == '#')
3159 parse_expression (operands
[i
].buf
+ 1, &operands
[i
].exp
);
3161 else if (operands
[i
].buf
[0] == '@')
3163 /* Direct notation. */
3164 parse_expression (operands
[i
].buf
+ 1, &operands
[i
].exp
);
3166 else if (operands
[i
].buf
[0] == '*')
3169 char *paren
= strchr (operands
[i
].buf
, '(');
3171 /* Allow immediate syntax in the inner expression. */
3172 if (paren
&& paren
[1] == '#')
3175 /* Pull out the lk expression or SP offset, if present. */
3178 int len
= strlen (paren
);
3179 char *end
= paren
+ len
;
3182 while (end
[-1] != ')')
3185 as_bad (_("Badly formed address expression"));
3190 parse_expression (paren
, &operands
[i
].exp
);
3194 operands
[i
].exp
.X_op
= O_absent
;
3197 parse_expression (operands
[i
].buf
, &operands
[i
].exp
);
3203 /* Predicates for different operand types. */
3206 is_immediate (struct opstruct
*operand
)
3208 return *operand
->buf
== '#';
3211 /* This is distinguished from immediate because some numbers must be constants
3212 and must *not* have the '#' prefix. */
3215 is_absolute (struct opstruct
*operand
)
3217 return operand
->exp
.X_op
== O_constant
&& !is_immediate (operand
);
3220 /* Is this an indirect operand? */
3223 is_indirect (struct opstruct
*operand
)
3225 return operand
->buf
[0] == '*';
3228 /* Is this a valid dual-memory operand? */
3231 is_dual (struct opstruct
*operand
)
3233 if (is_indirect (operand
) && strncasecmp (operand
->buf
, "*ar", 3) == 0)
3235 char *tmp
= operand
->buf
+ 3;
3240 /* Only allow *ARx, *ARx-, *ARx+, or *ARx+0%. */
3241 valid_mod
= *tmp
== '\0' ||
3242 strcasecmp (tmp
, "-") == 0 ||
3243 strcasecmp (tmp
, "+") == 0 ||
3244 strcasecmp (tmp
, "+0%") == 0;
3245 return arf
>= 2 && arf
<= 5 && valid_mod
;
3251 is_mmreg (struct opstruct
*operand
)
3253 return (is_absolute (operand
)
3254 || is_immediate (operand
)
3255 || hash_find (mmreg_hash
, operand
->buf
) != 0);
3259 is_type (struct opstruct
*operand
, enum optype type
)
3264 return operand
->buf
[0] == 0;
3267 return is_dual (operand
);
3269 return is_indirect (operand
);
3271 /* This one *must* be immediate. */
3272 return is_immediate (operand
);
3281 /* Address may be a numeric, indirect, or an expression. */
3282 return !is_immediate (operand
);
3285 return is_mmreg (operand
);
3290 return is_accumulator (operand
);
3292 return is_accumulator (operand
) && TOUPPER (operand
->buf
[0]) == 'B';
3294 return is_accumulator (operand
) && TOUPPER (operand
->buf
[0]) == 'A';
3296 return strncasecmp ("ar", operand
->buf
, 2) == 0
3297 && ISDIGIT (operand
->buf
[2]);
3299 return hash_find (sbit_hash
, operand
->buf
) != 0 || is_absolute (operand
);
3301 return hash_find (cc_hash
, operand
->buf
) != 0;
3303 return hash_find (cc2_hash
, operand
->buf
) != 0;
3305 return hash_find (cc3_hash
, operand
->buf
) != 0
3306 || is_immediate (operand
) || is_absolute (operand
);
3308 return (is_immediate (operand
) || is_absolute (operand
))
3309 && operand
->exp
.X_add_number
== 16;
3311 /* Allow st0 or st1 instead of a numeric. */
3312 return is_absolute (operand
) || is_immediate (operand
) ||
3313 strcasecmp ("st0", operand
->buf
) == 0 ||
3314 strcasecmp ("st1", operand
->buf
) == 0;
3317 return is_absolute (operand
) || is_immediate (operand
);
3319 return (is_immediate (operand
) || is_absolute (operand
))
3320 && operand
->exp
.X_add_number
>= 0 && operand
->exp
.X_add_number
< 16;
3322 /* Let this one catch out-of-range values. */
3323 return (is_immediate (operand
) || is_absolute (operand
))
3324 && operand
->exp
.X_add_number
!= 16;
3328 return is_absolute (operand
) || is_immediate (operand
);
3330 return is_immediate (operand
)
3331 && operand
->exp
.X_op
== O_constant
3332 && operand
->exp
.X_add_number
>= 0
3333 && operand
->exp
.X_add_number
< 256;
3336 /* Allow anything; assumes opcodes are ordered with Smem operands
3342 /* Just make sure it's an integer; check range later. */
3343 return is_immediate (operand
);
3345 return strcasecmp ("t", operand
->buf
) == 0 ||
3346 strcasecmp ("treg", operand
->buf
) == 0;
3348 return strcasecmp ("ts", operand
->buf
) == 0;
3350 return strcasecmp ("asm", operand
->buf
) == 0;
3352 return strcasecmp ("trn", operand
->buf
) == 0;
3354 return strcasecmp ("dp", operand
->buf
) == 0;
3356 return strcasecmp ("arp", operand
->buf
) == 0;
3363 operands_match (tic54x_insn
*insn
,
3364 struct opstruct
*operands
,
3366 const enum optype
*refoptype
,
3370 int op
= 0, refop
= 0;
3372 if (opcount
== 0 && minops
== 0)
3375 while (op
<= maxops
&& refop
<= maxops
)
3377 while (!is_type (&operands
[op
], OPTYPE (refoptype
[refop
])))
3379 /* Skip an optional template operand if it doesn't agree
3380 with the current operand. */
3381 if (refoptype
[refop
] & OPT
)
3392 /* Save the actual operand type for later use. */
3393 operands
[op
].type
= OPTYPE (refoptype
[refop
]);
3396 /* Have we matched them all yet? */
3401 /* If a later operand is *not* optional, no match. */
3402 if ((refoptype
[refop
] & OPT
) == 0)
3404 /* Flag any implicit default OP_DST operands so we know to add
3405 them explicitly when encoding the operand later. */
3406 if (OPTYPE (refoptype
[refop
]) == OP_DST
)
3407 insn
->using_default_dst
= 1;
3419 /* 16-bit direct memory address
3420 Explicit dmad operands are always in last word of insn (usually second
3421 word, but bumped to third if lk addressing is used)
3423 We allow *(dmad) notation because the TI assembler allows it.
3426 0 for 16-bit addresses
3427 1 for full 23-bit addresses
3428 2 for the upper 7 bits of a 23-bit address (LDX). */
3431 encode_dmad (tic54x_insn
*insn
, struct opstruct
*operand
, int xpc_code
)
3433 int op
= 1 + insn
->is_lkaddr
;
3435 /* Only allow *(dmad) expressions; all others are invalid. */
3436 if (is_indirect (operand
) && operand
->buf
[strlen (operand
->buf
) - 1] != ')')
3438 as_bad (_("Invalid dmad syntax '%s'"), operand
->buf
);
3442 insn
->opcode
[op
].addr_expr
= operand
->exp
;
3444 if (insn
->opcode
[op
].addr_expr
.X_op
== O_constant
)
3446 valueT value
= insn
->opcode
[op
].addr_expr
.X_add_number
;
3450 insn
->opcode
[0].word
&= 0xFF80;
3451 insn
->opcode
[0].word
|= (value
>> 16) & 0x7F;
3452 insn
->opcode
[1].word
= value
& 0xFFFF;
3454 else if (xpc_code
== 2)
3455 insn
->opcode
[op
].word
= (value
>> 16) & 0xFFFF;
3457 insn
->opcode
[op
].word
= value
;
3461 /* Do the fixup later; just store the expression. */
3462 insn
->opcode
[op
].word
= 0;
3463 insn
->opcode
[op
].r_nchars
= 2;
3465 if (amode
== c_mode
)
3466 insn
->opcode
[op
].r_type
= BFD_RELOC_TIC54X_16_OF_23
;
3467 else if (xpc_code
== 1)
3469 /* This relocation spans two words, so adjust accordingly. */
3470 insn
->opcode
[0].addr_expr
= operand
->exp
;
3471 insn
->opcode
[0].r_type
= BFD_RELOC_TIC54X_23
;
3472 insn
->opcode
[0].r_nchars
= 4;
3473 insn
->opcode
[0].unresolved
= 1;
3474 /* It's really 2 words, but we want to stop encoding after the
3475 first, since we must encode both words at once. */
3478 else if (xpc_code
== 2)
3479 insn
->opcode
[op
].r_type
= BFD_RELOC_TIC54X_MS7_OF_23
;
3481 insn
->opcode
[op
].r_type
= BFD_RELOC_TIC54X_16_OF_23
;
3483 insn
->opcode
[op
].unresolved
= 1;
3489 /* 7-bit direct address encoding. */
3492 encode_address (tic54x_insn
*insn
, struct opstruct
*operand
)
3494 /* Assumes that dma addresses are *always* in word 0 of the opcode. */
3495 insn
->opcode
[0].addr_expr
= operand
->exp
;
3497 if (operand
->exp
.X_op
== O_constant
)
3498 insn
->opcode
[0].word
|= (operand
->exp
.X_add_number
& 0x7F);
3501 if (operand
->exp
.X_op
== O_register
)
3502 as_bad (_("Use the .mmregs directive to use memory-mapped register names such as '%s'"), operand
->buf
);
3503 /* Do the fixup later; just store the expression. */
3504 insn
->opcode
[0].r_nchars
= 1;
3505 insn
->opcode
[0].r_type
= BFD_RELOC_TIC54X_PARTLS7
;
3506 insn
->opcode
[0].unresolved
= 1;
3513 encode_indirect (tic54x_insn
*insn
, struct opstruct
*operand
)
3518 if (insn
->is_lkaddr
)
3520 /* lk addresses always go in the second insn word. */
3521 mod
= ((TOUPPER (operand
->buf
[1]) == 'A') ? 12 :
3522 (operand
->buf
[1] == '(') ? 15 :
3523 (strchr (operand
->buf
, '%') != NULL
) ? 14 : 13);
3524 arf
= ((mod
== 12) ? operand
->buf
[3] - '0' :
3525 (mod
== 15) ? 0 : operand
->buf
[4] - '0');
3527 insn
->opcode
[1].addr_expr
= operand
->exp
;
3529 if (operand
->exp
.X_op
== O_constant
)
3530 insn
->opcode
[1].word
= operand
->exp
.X_add_number
;
3533 insn
->opcode
[1].word
= 0;
3534 insn
->opcode
[1].r_nchars
= 2;
3535 insn
->opcode
[1].r_type
= BFD_RELOC_TIC54X_16_OF_23
;
3536 insn
->opcode
[1].unresolved
= 1;
3539 else if (strncasecmp (operand
->buf
, "*sp (", 4) == 0)
3541 /* Stack offsets look the same as 7-bit direct addressing. */
3542 return encode_address (insn
, operand
);
3546 arf
= (TOUPPER (operand
->buf
[1]) == 'A' ?
3547 operand
->buf
[3] : operand
->buf
[4]) - '0';
3549 if (operand
->buf
[1] == '+')
3551 mod
= 3; /* *+ARx */
3552 if (insn
->tm
->flags
& FL_SMR
)
3553 as_warn (_("Address mode *+ARx is write-only. "
3554 "Results of reading are undefined."));
3556 else if (operand
->buf
[4] == '\0')
3558 else if (operand
->buf
[5] == '\0')
3559 mod
= (operand
->buf
[4] == '-' ? 1 : 2); /* *ARx+ / *ARx- */
3560 else if (operand
->buf
[6] == '\0')
3562 if (operand
->buf
[5] == '0')
3563 mod
= (operand
->buf
[4] == '-' ? 5 : 6); /* *ARx+0 / *ARx-0 */
3565 mod
= (operand
->buf
[4] == '-' ? 8 : 10);/* *ARx+% / *ARx-% */
3567 else if (TOUPPER (operand
->buf
[6]) == 'B')
3568 mod
= (operand
->buf
[4] == '-' ? 4 : 7); /* ARx+0B / *ARx-0B */
3569 else if (TOUPPER (operand
->buf
[6]) == '%')
3570 mod
= (operand
->buf
[4] == '-' ? 9 : 11); /* ARx+0% / *ARx - 0% */
3573 as_bad (_("Unrecognized indirect address format \"%s\""),
3579 insn
->opcode
[0].word
|= 0x80 | (mod
<< 3) | arf
;
3585 encode_integer (tic54x_insn
*insn
,
3586 struct opstruct
*operand
,
3590 unsigned short mask
)
3592 long parse
, integer
;
3594 insn
->opcode
[which
].addr_expr
= operand
->exp
;
3596 if (operand
->exp
.X_op
== O_constant
)
3598 parse
= operand
->exp
.X_add_number
;
3599 /* Hack -- fixup for 16-bit hex quantities that get converted positive
3600 instead of negative. */
3601 if ((parse
& 0x8000) && min
== -32768 && max
== 32767)
3602 integer
= (short) parse
;
3606 if (integer
>= min
&& integer
<= max
)
3608 insn
->opcode
[which
].word
|= (integer
& mask
);
3611 as_bad (_("Operand '%s' out of range (%d <= x <= %d)"),
3612 operand
->buf
, min
, max
);
3616 if (insn
->opcode
[which
].addr_expr
.X_op
== O_constant
)
3618 insn
->opcode
[which
].word
|=
3619 insn
->opcode
[which
].addr_expr
.X_add_number
& mask
;
3623 /* Do the fixup later; just store the expression. */
3624 bfd_reloc_code_real_type rtype
=
3625 (mask
== 0x1FF ? BFD_RELOC_TIC54X_PARTMS9
:
3626 mask
== 0xFFFF ? BFD_RELOC_TIC54X_16_OF_23
:
3627 mask
== 0x7F ? BFD_RELOC_TIC54X_PARTLS7
: BFD_RELOC_8
);
3628 int size
= (mask
== 0x1FF || mask
== 0xFFFF) ? 2 : 1;
3630 if (rtype
== BFD_RELOC_8
)
3631 as_bad (_("Error in relocation handling"));
3633 insn
->opcode
[which
].r_nchars
= size
;
3634 insn
->opcode
[which
].r_type
= rtype
;
3635 insn
->opcode
[which
].unresolved
= 1;
3645 encode_condition (tic54x_insn
*insn
, struct opstruct
*operand
)
3647 tic54x_symbol
*cc
= (tic54x_symbol
*) hash_find (cc_hash
, operand
->buf
);
3650 as_bad (_("Unrecognized condition code \"%s\""), operand
->buf
);
3653 #define CC_GROUP 0x40
3655 #define CATG_A1 0x07
3656 #define CATG_B1 0x30
3657 #define CATG_A2 0x30
3658 #define CATG_B2 0x0C
3659 #define CATG_C2 0x03
3660 /* Disallow group 1 conditions mixed with group 2 conditions
3661 if group 1, allow only one category A and one category B
3662 if group 2, allow only one each of category A, B, and C. */
3663 if (((insn
->opcode
[0].word
& 0xFF) != 0))
3665 if ((insn
->opcode
[0].word
& CC_GROUP
) != (cc
->value
& CC_GROUP
))
3667 as_bad (_("Condition \"%s\" does not match preceding group"),
3671 if (insn
->opcode
[0].word
& CC_GROUP
)
3673 if ((insn
->opcode
[0].word
& CC_ACC
) != (cc
->value
& CC_ACC
))
3675 as_bad (_("Condition \"%s\" uses a different accumulator from "
3676 "a preceding condition"),
3680 if ((insn
->opcode
[0].word
& CATG_A1
) && (cc
->value
& CATG_A1
))
3682 as_bad (_("Only one comparison conditional allowed"));
3685 if ((insn
->opcode
[0].word
& CATG_B1
) && (cc
->value
& CATG_B1
))
3687 as_bad (_("Only one overflow conditional allowed"));
3691 else if ( ((insn
->opcode
[0].word
& CATG_A2
) && (cc
->value
& CATG_A2
))
3692 || ((insn
->opcode
[0].word
& CATG_B2
) && (cc
->value
& CATG_B2
))
3693 || ((insn
->opcode
[0].word
& CATG_C2
) && (cc
->value
& CATG_C2
)))
3695 as_bad (_("Duplicate %s conditional"), operand
->buf
);
3700 insn
->opcode
[0].word
|= cc
->value
;
3705 encode_cc3 (tic54x_insn
*insn
, struct opstruct
*operand
)
3707 tic54x_symbol
*cc3
= (tic54x_symbol
*) hash_find (cc3_hash
, operand
->buf
);
3708 int value
= cc3
? cc3
->value
: operand
->exp
.X_add_number
<< 8;
3710 if ((value
& 0x0300) != value
)
3712 as_bad (_("Unrecognized condition code \"%s\""), operand
->buf
);
3715 insn
->opcode
[0].word
|= value
;
3720 encode_arx (tic54x_insn
*insn
, struct opstruct
*operand
)
3722 int arf
= strlen (operand
->buf
) >= 3 ? operand
->buf
[2] - '0' : -1;
3724 if (strncasecmp ("ar", operand
->buf
, 2) || arf
< 0 || arf
> 7)
3726 as_bad (_("Invalid auxiliary register (use AR0-AR7)"));
3729 insn
->opcode
[0].word
|= arf
;
3734 encode_cc2 (tic54x_insn
*insn
, struct opstruct
*operand
)
3736 tic54x_symbol
*cc2
= (tic54x_symbol
*) hash_find (cc2_hash
, operand
->buf
);
3740 as_bad (_("Unrecognized condition code \"%s\""), operand
->buf
);
3743 insn
->opcode
[0].word
|= cc2
->value
;
3748 encode_operand (tic54x_insn
*insn
, enum optype type
, struct opstruct
*operand
)
3750 int ext
= (insn
->tm
->flags
& FL_EXT
) != 0;
3752 if (type
== OP_MMR
&& operand
->exp
.X_op
!= O_constant
)
3754 /* Disallow long-constant addressing for memory-mapped addressing. */
3755 if (insn
->is_lkaddr
)
3757 as_bad (_("lk addressing modes are invalid for memory-mapped "
3758 "register addressing"));
3762 /* Warn about *+ARx when used with MMR operands. */
3763 if (strncasecmp (operand
->buf
, "*+ar", 4) == 0)
3765 as_warn (_("Address mode *+ARx is not allowed in memory-mapped "
3766 "register addressing. Resulting behavior is "
3776 /* 16-bit immediate value. */
3777 return encode_dmad (insn
, operand
, 0);
3779 if (TOUPPER (*operand
->buf
) == 'B')
3781 insn
->opcode
[ext
? (1 + insn
->is_lkaddr
) : 0].word
|= (1 << 9);
3782 if (insn
->using_default_dst
)
3783 insn
->opcode
[ext
? (1 + insn
->is_lkaddr
) : 0].word
|= (1 << 8);
3787 /* Make sure this agrees with the OP_DST operand. */
3788 if (!((TOUPPER (operand
->buf
[0]) == 'B') ^
3789 ((insn
->opcode
[0].word
& (1 << 8)) != 0)))
3791 as_bad (_("Destination accumulator for each part of this parallel "
3792 "instruction must be different"));
3798 if (TOUPPER (operand
->buf
[0]) == 'B')
3799 insn
->opcode
[ext
? (1 + insn
->is_lkaddr
) : 0].word
|= (1 << 8);
3804 int mod
= (operand
->buf
[4] == '\0' ? 0 : /* *arx */
3805 operand
->buf
[4] == '-' ? 1 : /* *arx- */
3806 operand
->buf
[5] == '\0' ? 2 : 3); /* *arx+, *arx+0% */
3807 int arf
= operand
->buf
[3] - '0' - 2;
3808 int code
= (mod
<< 2) | arf
;
3809 insn
->opcode
[0].word
|= (code
<< (type
== OP_Xmem
? 4 : 0));
3814 if (!is_indirect (operand
))
3815 return encode_address (insn
, operand
);
3818 return encode_indirect (insn
, operand
);
3820 return encode_dmad (insn
, operand
, 2);
3822 return encode_dmad (insn
, operand
, 1);
3825 return encode_dmad (insn
, operand
, 0);
3827 return encode_arx (insn
, operand
);
3832 int value
= operand
->exp
.X_add_number
;
3835 insn
->opcode
[0].word
|= value
;
3838 if (value
< 16 || value
> 24)
3840 as_bad (_("Memory mapped register \"%s\" out of range"),
3844 if (type
== OP_MMRX
)
3845 insn
->opcode
[0].word
|= (value
- 16) << 4;
3847 insn
->opcode
[0].word
|= (value
- 16);
3855 return encode_integer (insn
, operand
, ext
+ insn
->is_lkaddr
,
3858 return encode_integer (insn
, operand
, ext
+ insn
->is_lkaddr
,
3861 return encode_integer (insn
, operand
, 1 + insn
->is_lkaddr
,
3862 -32768, 32767, 0xFFFF);
3864 return encode_condition (insn
, operand
);
3866 return encode_cc2 (insn
, operand
);
3868 return encode_cc3 (insn
, operand
);
3870 return encode_integer (insn
, operand
, 0, 0, 15, 0xF);
3872 return encode_integer (insn
, operand
, 0, -128, 127, 0xFF);
3875 int value
= operand
->exp
.X_add_number
;
3877 if (value
< 1 || value
> 3)
3879 as_bad (_("Invalid operand (use 1, 2, or 3)"));
3882 code
= value
== 1 ? 0 : value
== 2 ? 0x2 : 0x1;
3883 insn
->opcode
[0].word
|= (code
<< 8);
3887 return encode_integer (insn
, operand
, 0, 0, 31, 0x1F);
3889 return encode_integer (insn
, operand
, 0, 0, 255, 0xFF);
3891 return encode_integer (insn
, operand
, 1 + insn
->is_lkaddr
,
3895 tic54x_symbol
*sbit
= (tic54x_symbol
*)
3896 hash_find (sbit_hash
, operand
->buf
);
3897 int value
= is_absolute (operand
) ?
3898 operand
->exp
.X_add_number
: (sbit
? sbit
->value
: -1);
3901 if (insn
->opcount
== 1)
3905 as_bad (_("A status register or status bit name is required"));
3908 /* Guess the register based on the status bit; "ovb" is the last
3909 status bit defined for st0. */
3910 if (sbit
> (tic54x_symbol
*) hash_find (sbit_hash
, "ovb"))
3915 as_bad (_("Unrecognized status bit \"%s\""), operand
->buf
);
3918 insn
->opcode
[0].word
|= value
;
3919 insn
->opcode
[0].word
|= (reg
<< 9);
3923 if (strcasecmp (operand
->buf
, "st0") == 0
3924 || strcasecmp (operand
->buf
, "st1") == 0)
3926 insn
->opcode
[0].word
|=
3927 ((unsigned short) (operand
->buf
[2] - '0')) << 9;
3930 else if (operand
->exp
.X_op
== O_constant
3931 && (operand
->exp
.X_add_number
== 0
3932 || operand
->exp
.X_add_number
== 1))
3934 insn
->opcode
[0].word
|=
3935 ((unsigned short) (operand
->exp
.X_add_number
)) << 9;
3938 as_bad (_("Invalid status register \"%s\""), operand
->buf
);
3941 return encode_integer (insn
, operand
, 0, -16, 15, 0x1F);
3943 return encode_integer (insn
, operand
, 0, 0, 7, 0x7);
3945 return encode_integer (insn
, operand
, 0, 0, 0x1FF, 0x1FF);
3947 if (operand
->exp
.X_add_number
!= 1
3948 && operand
->exp
.X_add_number
!= 2)
3950 as_bad (_("Operand \"%s\" out of range (use 1 or 2)"), operand
->buf
);
3953 insn
->opcode
[0].word
|= (operand
->exp
.X_add_number
- 1) << 9;
3962 /* No encoding necessary. */
3972 emit_insn (tic54x_insn
*insn
)
3975 flagword oldflags
= bfd_get_section_flags (stdoutput
, now_seg
);
3976 flagword flags
= oldflags
| SEC_CODE
;
3978 if (! bfd_set_section_flags (stdoutput
, now_seg
, flags
))
3979 as_warn (_("error setting flags for \"%s\": %s"),
3980 bfd_section_name (stdoutput
, now_seg
),
3981 bfd_errmsg (bfd_get_error ()));
3983 for (i
= 0; i
< insn
->words
; i
++)
3985 int size
= (insn
->opcode
[i
].unresolved
3986 && insn
->opcode
[i
].r_type
== BFD_RELOC_TIC54X_23
) ? 4 : 2;
3987 char *p
= frag_more (size
);
3990 md_number_to_chars (p
, (valueT
) insn
->opcode
[i
].word
, 2);
3992 md_number_to_chars (p
, (valueT
) insn
->opcode
[i
].word
<< 16, 4);
3994 if (insn
->opcode
[i
].unresolved
)
3995 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
,
3996 insn
->opcode
[i
].r_nchars
, &insn
->opcode
[i
].addr_expr
,
3997 FALSE
, insn
->opcode
[i
].r_type
);
4001 /* Convert the operand strings into appropriate opcode values
4002 return the total number of words used by the instruction. */
4005 build_insn (tic54x_insn
*insn
)
4009 /* Only non-parallel instructions support lk addressing. */
4010 if (!(insn
->tm
->flags
& FL_PAR
))
4012 for (i
= 0; i
< insn
->opcount
; i
++)
4014 if ((OPTYPE (insn
->operands
[i
].type
) == OP_Smem
4015 || OPTYPE (insn
->operands
[i
].type
) == OP_Lmem
4016 || OPTYPE (insn
->operands
[i
].type
) == OP_Sind
)
4017 && strchr (insn
->operands
[i
].buf
, '(')
4018 /* Don't mistake stack-relative addressing for lk addressing. */
4019 && strncasecmp (insn
->operands
[i
].buf
, "*sp (", 4) != 0)
4021 insn
->is_lkaddr
= 1;
4022 insn
->lkoperand
= i
;
4027 insn
->words
= insn
->tm
->words
+ insn
->is_lkaddr
;
4029 insn
->opcode
[0].word
= insn
->tm
->opcode
;
4030 if (insn
->tm
->flags
& FL_EXT
)
4031 insn
->opcode
[1 + insn
->is_lkaddr
].word
= insn
->tm
->opcode2
;
4033 for (i
= 0; i
< insn
->opcount
; i
++)
4035 enum optype type
= insn
->operands
[i
].type
;
4037 if (!encode_operand (insn
, type
, &insn
->operands
[i
]))
4040 if (insn
->tm
->flags
& FL_PAR
)
4041 for (i
= 0; i
< insn
->paropcount
; i
++)
4043 enum optype partype
= insn
->paroperands
[i
].type
;
4045 if (!encode_operand (insn
, partype
, &insn
->paroperands
[i
]))
4055 optimize_insn (tic54x_insn
*insn
)
4057 /* Optimize some instructions, helping out the brain-dead programmer. */
4058 #define is_zero(op) ((op).exp.X_op == O_constant && (op).exp.X_add_number == 0)
4059 if (strcasecmp (insn
->tm
->name
, "add") == 0)
4061 if (insn
->opcount
> 1
4062 && is_accumulator (&insn
->operands
[insn
->opcount
- 2])
4063 && is_accumulator (&insn
->operands
[insn
->opcount
- 1])
4064 && strcasecmp (insn
->operands
[insn
->opcount
- 2].buf
,
4065 insn
->operands
[insn
->opcount
- 1].buf
) == 0)
4068 insn
->using_default_dst
= 1;
4072 /* Try to collapse if Xmem and shift count is zero. */
4073 if ((OPTYPE (insn
->tm
->operand_types
[0]) == OP_Xmem
4074 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
4075 && is_zero (insn
->operands
[1]))
4076 /* Or if Smem, shift is zero or absent, and SRC == DST. */
4077 || (OPTYPE (insn
->tm
->operand_types
[0]) == OP_Smem
4078 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
4079 && is_type (&insn
->operands
[1], OP_SHIFT
)
4080 && is_zero (insn
->operands
[1]) && insn
->opcount
== 3))
4082 insn
->operands
[1] = insn
->operands
[2];
4087 else if (strcasecmp (insn
->tm
->name
, "ld") == 0)
4089 if (insn
->opcount
== 3 && insn
->operands
[0].type
!= OP_SRC
)
4091 if ((OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
4092 || OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
)
4093 && is_zero (insn
->operands
[1])
4094 && (OPTYPE (insn
->tm
->operand_types
[0]) != OP_lk
4095 || (insn
->operands
[0].exp
.X_op
== O_constant
4096 && insn
->operands
[0].exp
.X_add_number
<= 255
4097 && insn
->operands
[0].exp
.X_add_number
>= 0)))
4099 insn
->operands
[1] = insn
->operands
[2];
4105 else if (strcasecmp (insn
->tm
->name
, "sth") == 0
4106 || strcasecmp (insn
->tm
->name
, "stl") == 0)
4108 if ((OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
4109 || OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
)
4110 && is_zero (insn
->operands
[1]))
4112 insn
->operands
[1] = insn
->operands
[2];
4117 else if (strcasecmp (insn
->tm
->name
, "sub") == 0)
4119 if (insn
->opcount
> 1
4120 && is_accumulator (&insn
->operands
[insn
->opcount
- 2])
4121 && is_accumulator (&insn
->operands
[insn
->opcount
- 1])
4122 && strcasecmp (insn
->operands
[insn
->opcount
- 2].buf
,
4123 insn
->operands
[insn
->opcount
- 1].buf
) == 0)
4126 insn
->using_default_dst
= 1;
4130 if ( ((OPTYPE (insn
->tm
->operand_types
[0]) == OP_Smem
4131 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
)
4132 || (OPTYPE (insn
->tm
->operand_types
[0]) == OP_Xmem
4133 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
))
4134 && is_zero (insn
->operands
[1])
4135 && insn
->opcount
== 3)
4137 insn
->operands
[1] = insn
->operands
[2];
4145 /* Find a matching template if possible, and get the operand strings. */
4148 tic54x_parse_insn (tic54x_insn
*insn
, char *line
)
4150 insn
->tm
= (insn_template
*) hash_find (op_hash
, insn
->mnemonic
);
4153 as_bad (_("Unrecognized instruction \"%s\""), insn
->mnemonic
);
4157 insn
->opcount
= get_operands (insn
->operands
, line
);
4158 if (insn
->opcount
< 0)
4161 /* Check each variation of operands for this mnemonic. */
4162 while (insn
->tm
->name
&& strcasecmp (insn
->tm
->name
, insn
->mnemonic
) == 0)
4164 if (insn
->opcount
>= insn
->tm
->minops
4165 && insn
->opcount
<= insn
->tm
->maxops
4166 && operands_match (insn
, &insn
->operands
[0], insn
->opcount
,
4167 insn
->tm
->operand_types
,
4168 insn
->tm
->minops
, insn
->tm
->maxops
))
4170 /* SUCCESS! now try some optimizations. */
4171 if (optimize_insn (insn
))
4173 insn
->tm
= (insn_template
*) hash_find (op_hash
,
4182 as_bad (_("Unrecognized operand list '%s' for instruction '%s'"),
4183 line
, insn
->mnemonic
);
4187 /* We set this in start_line_hook, 'cause if we do a line replacement, we
4188 won't be able to see the next line. */
4189 static int parallel_on_next_line_hint
= 0;
4191 /* See if this is part of a parallel instruction
4192 Look for a subsequent line starting with "||". */
4195 next_line_shows_parallel (char *next_line
)
4197 /* Look for the second half. */
4198 while (ISSPACE (*next_line
))
4201 return (next_line
[0] == PARALLEL_SEPARATOR
4202 && next_line
[1] == PARALLEL_SEPARATOR
);
4206 tic54x_parse_parallel_insn_firstline (tic54x_insn
*insn
, char *line
)
4208 insn
->tm
= (insn_template
*) hash_find (parop_hash
, insn
->mnemonic
);
4211 as_bad (_("Unrecognized parallel instruction \"%s\""),
4216 while (insn
->tm
->name
&& strcasecmp (insn
->tm
->name
,
4217 insn
->mnemonic
) == 0)
4219 insn
->opcount
= get_operands (insn
->operands
, line
);
4220 if (insn
->opcount
< 0)
4222 if (insn
->opcount
== 2
4223 && operands_match (insn
, &insn
->operands
[0], insn
->opcount
,
4224 insn
->tm
->operand_types
, 2, 2))
4230 /* Didn't find a matching parallel; try for a normal insn. */
4234 /* Parse the second line of a two-line parallel instruction. */
4237 tic54x_parse_parallel_insn_lastline (tic54x_insn
*insn
, char *line
)
4239 int valid_mnemonic
= 0;
4241 insn
->paropcount
= get_operands (insn
->paroperands
, line
);
4242 while (insn
->tm
->name
&& strcasecmp (insn
->tm
->name
,
4243 insn
->mnemonic
) == 0)
4245 if (strcasecmp (insn
->tm
->parname
, insn
->parmnemonic
) == 0)
4249 if (insn
->paropcount
>= insn
->tm
->minops
4250 && insn
->paropcount
<= insn
->tm
->maxops
4251 && operands_match (insn
, insn
->paroperands
,
4253 insn
->tm
->paroperand_types
,
4254 insn
->tm
->minops
, insn
->tm
->maxops
))
4260 as_bad (_("Invalid operand (s) for parallel instruction \"%s\""),
4263 as_bad (_("Unrecognized parallel instruction combination \"%s || %s\""),
4264 insn
->mnemonic
, insn
->parmnemonic
);
4269 /* If quotes found, return copy of line up to closing quote;
4270 otherwise up until terminator.
4271 If it's a string, pass as-is; otherwise attempt substitution symbol
4272 replacement on the value. */
4275 subsym_get_arg (char *line
, const char *terminators
, char **str
, int nosub
)
4279 int is_string
= *line
== '"';
4280 int is_char
= ISDIGIT (*line
);
4284 while (ISDIGIT (*ptr
))
4287 *str
= xmemdup0 (line
, ptr
- line
);
4291 char *savedp
= input_line_pointer
;
4294 input_line_pointer
= ptr
;
4295 *str
= demand_copy_C_string (&len
);
4296 endp
= input_line_pointer
;
4297 input_line_pointer
= savedp
;
4299 /* Do forced substitutions if requested. */
4300 if (!nosub
&& **str
== ':')
4301 *str
= subsym_substitute (*str
, 1);
4305 const char *term
= terminators
;
4308 while (*ptr
&& *ptr
!= *term
)
4319 *str
= xmemdup0 (line
, ptr
- line
);
4320 /* Do simple substitution, if available. */
4321 if (!nosub
&& (value
= subsym_lookup (*str
, macro_level
)) != NULL
)
4328 /* Replace the given substitution string.
4329 We start at the innermost macro level, so that existing locals remain local
4330 Note: we're treating macro args identically to .var's; I don't know if
4331 that's compatible w/TI's assembler. */
4334 subsym_create_or_replace (char *name
, char *value
)
4338 for (i
= macro_level
; i
> 0; i
--)
4340 if (hash_find (subsym_hash
[i
], name
))
4342 hash_replace (subsym_hash
[i
], name
, value
);
4346 if (hash_find (subsym_hash
[0], name
))
4347 hash_replace (subsym_hash
[0], name
, value
);
4349 hash_insert (subsym_hash
[0], name
, value
);
4352 /* Look up the substitution string replacement for the given symbol.
4353 Start with the innermost macro substitution table given and work
4357 subsym_lookup (char *name
, int nest_level
)
4359 char *value
= hash_find (subsym_hash
[nest_level
], name
);
4361 if (value
|| nest_level
== 0)
4364 return subsym_lookup (name
, nest_level
- 1);
4367 /* Do substitution-symbol replacement on the given line (recursively).
4368 return the argument if no substitution was done
4370 Also look for built-in functions ($func (arg)) and local labels.
4372 If FORCED is set, look for forced substitutions of the form ':SYMBOL:'. */
4375 subsym_substitute (char *line
, int forced
)
4377 /* For each apparent symbol, see if it's a substitution symbol, and if so,
4378 replace it in the input. */
4379 char *replacement
; /* current replacement for LINE. */
4380 char *head
; /* Start of line. */
4381 char *ptr
; /* Current examination point. */
4382 int changed
= 0; /* Did we make a substitution? */
4383 int eval_line
= 0; /* Is this line a .eval/.asg statement? */
4384 int eval_symbol
= 0; /* Are we in the middle of the symbol for
4386 char *eval_end
= NULL
;
4388 int line_conditional
= 0;
4391 /* Work with a copy of the input line. */
4392 replacement
= xstrdup (line
);
4394 ptr
= head
= replacement
;
4396 /* Flag lines where we might need to replace a single '=' with two;
4397 GAS uses single '=' to assign macro args values, and possibly other
4398 places, so limit what we replace. */
4399 if (strstr (line
, ".if")
4400 || strstr (line
, ".elseif")
4401 || strstr (line
, ".break"))
4402 line_conditional
= 1;
4404 /* Watch out for .eval, so that we avoid doing substitution on the
4405 symbol being assigned a value. */
4406 if (strstr (line
, ".eval") || strstr (line
, ".asg"))
4409 /* If it's a macro definition, don't do substitution on the argument
4411 if (strstr (line
, ".macro"))
4414 while (!is_end_of_line
[(int) *ptr
])
4416 int current_char
= *ptr
;
4418 /* Need to update this since LINE may have been modified. */
4420 eval_end
= strrchr (ptr
, ',');
4422 /* Replace triple double quotes with bounding quote/escapes. */
4423 if (current_char
== '"' && ptr
[1] == '"' && ptr
[2] == '"')
4426 tmp
= strstr (ptr
+ 2, "\"\"\"");
4432 /* Replace a single '=' with a '==';
4433 for compatibility with older code only. */
4434 if (line_conditional
&& current_char
== '=')
4442 tmp
= concat (head
, "==", ptr
, (char *) NULL
);
4443 /* Continue examining after the '=='. */
4444 ptr
= tmp
+ strlen (head
) + 2;
4446 head
= replacement
= tmp
;
4450 /* Flag when we've reached the symbol part of .eval/.asg. */
4451 if (eval_line
&& ptr
>= eval_end
)
4454 /* For each apparent symbol, see if it's a substitution symbol, and if
4455 so, replace it in the input. */
4456 if ((forced
&& current_char
== ':')
4457 || (!forced
&& is_name_beginner (current_char
)))
4459 char *name
; /* Symbol to be replaced. */
4460 char *savedp
= input_line_pointer
;
4463 char *tail
; /* Rest of line after symbol. */
4465 /* Skip the colon. */
4469 input_line_pointer
= ptr
;
4470 c
= get_symbol_name (&name
);
4471 /* '?' is not normally part of a symbol, but it IS part of a local
4475 *input_line_pointer
++ = c
;
4476 c
= *input_line_pointer
;
4477 *input_line_pointer
= '\0';
4479 /* Avoid infinite recursion; if a symbol shows up a second time for
4480 substitution, leave it as is. */
4481 if (hash_find (subsym_recurse_hash
, name
) == NULL
)
4482 value
= subsym_lookup (name
, macro_level
);
4484 as_warn (_("%s symbol recursion stopped at "
4485 "second appearance of '%s'"),
4486 forced
? "Forced substitution" : "Substitution", name
);
4487 ptr
= tail
= input_line_pointer
;
4488 input_line_pointer
= savedp
;
4490 /* Check for local labels; replace them with the appropriate
4492 if ((*name
== '$' && ISDIGIT (name
[1]) && name
[2] == '\0')
4493 || name
[strlen (name
) - 1] == '?')
4495 /* Use an existing identifier for that label if, available, or
4496 create a new, unique identifier. */
4497 value
= hash_find (local_label_hash
[macro_level
], name
);
4501 char *namecopy
= xstrdup (name
);
4503 value
= strcpy (xmalloc (strlen (name
) + sizeof (digit
) + 1),
4506 value
[strlen (value
) - 1] = '\0';
4507 sprintf (digit
, ".%d", local_label_id
++);
4508 strcat (value
, digit
);
4509 hash_insert (local_label_hash
[macro_level
], namecopy
, value
);
4511 /* Indicate where to continue looking for substitutions. */
4514 /* Check for built-in subsym and math functions. */
4515 else if (value
!= NULL
&& *name
== '$')
4517 subsym_proc_entry
*entry
= (subsym_proc_entry
*) value
;
4518 math_proc_entry
*math_entry
= hash_find (math_hash
, name
);
4519 char *arg1
, *arg2
= NULL
;
4524 as_bad (_("Unrecognized substitution symbol function"));
4527 else if (*ptr
!= '(')
4529 as_bad (_("Missing '(' after substitution symbol function"));
4533 if (math_entry
!= NULL
)
4535 float farg1
, farg2
= 0;
4536 volatile float fresult
;
4538 farg1
= (float) strtod (ptr
, &ptr
);
4539 if (math_entry
->nargs
== 2)
4543 as_bad (_("Expecting second argument"));
4546 farg2
= (float) strtod (ptr
, &ptr
);
4548 fresult
= (*math_entry
->proc
) (farg1
, farg2
);
4549 value
= XNEWVEC (char, 128);
4550 if (math_entry
->int_return
)
4551 sprintf (value
, "%d", (int) fresult
);
4553 sprintf (value
, "%f", fresult
);
4556 as_bad (_("Extra junk in function call, expecting ')'"));
4559 /* Don't bother recursing; the replacement isn't a
4566 int arg_type
[2] = { *ptr
== '"' , 0 };
4567 int ismember
= !strcmp (entry
->name
, "$ismember");
4569 /* Parse one or two args, which must be a substitution
4570 symbol, string or a character-string constant. */
4571 /* For all functions, a string or substitution symbol may be
4572 used, with the following exceptions:
4573 firstch/lastch: 2nd arg must be character constant
4574 ismember: both args must be substitution symbols. */
4575 ptr
= subsym_get_arg (ptr
, ",)", &arg1
, ismember
);
4578 if (entry
->nargs
== 2)
4582 as_bad (_("Function expects two arguments"));
4585 /* Character constants are converted to numerics
4586 by the preprocessor. */
4587 arg_type
[1] = (ISDIGIT (*ptr
)) ? 2 : (*ptr
== '"');
4588 ptr
= subsym_get_arg (ptr
, ")", &arg2
, ismember
);
4590 /* Args checking. */
4591 if ((!strcmp (entry
->name
, "$firstch")
4592 || !strcmp (entry
->name
, "$lastch"))
4593 && arg_type
[1] != 2)
4595 as_bad (_("Expecting character constant argument"));
4599 && (arg_type
[0] != 0 || arg_type
[1] != 0))
4601 as_bad (_("Both arguments must be substitution symbols"));
4606 as_bad (_("Extra junk in function call, expecting ')'"));
4609 val
= (*entry
->proc
) (arg1
, arg2
);
4610 value
= XNEWVEC (char, 64);
4611 sprintf (value
, "%d", val
);
4613 /* Fix things up to replace the entire expression, not just the
4619 if (value
!= NULL
&& !eval_symbol
)
4621 /* Replace the symbol with its string replacement and
4622 continue. Recursively replace VALUE until either no
4623 substitutions are performed, or a substitution that has been
4624 previously made is encountered again.
4626 Put the symbol into the recursion hash table so we only
4627 try to replace a symbol once. */
4630 hash_insert (subsym_recurse_hash
, name
, name
);
4631 value
= subsym_substitute (value
, macro_level
> 0);
4632 hash_delete (subsym_recurse_hash
, name
, FALSE
);
4635 /* Temporarily zero-terminate where the symbol started. */
4641 /* Subscripted substitution symbol -- use just the
4642 indicated portion of the string; the description
4643 kinda indicates that forced substitution is not
4644 supposed to be recursive, but I'm not sure. */
4645 unsigned beg
, len
= 1; /* default to a single char */
4646 char *newval
= xstrdup (value
);
4648 savedp
= input_line_pointer
;
4649 input_line_pointer
= tail
+ 1;
4650 beg
= get_absolute_expression ();
4653 as_bad (_("Invalid subscript (use 1 to %d)"),
4654 (int) strlen (value
));
4657 if (*input_line_pointer
== ',')
4659 ++input_line_pointer
;
4660 len
= get_absolute_expression ();
4661 if (beg
+ len
> strlen (value
))
4663 as_bad (_("Invalid length (use 0 to %d)"),
4664 (int) strlen (value
) - beg
);
4670 tail
= input_line_pointer
;
4673 as_bad (_("Missing ')' in subscripted substitution "
4674 "symbol expression"));
4678 input_line_pointer
= savedp
;
4684 tmp
= xmalloc (strlen (head
) + strlen (value
) +
4685 strlen (tail
+ 1) + 2);
4687 strcat (tmp
, value
);
4688 /* Make sure forced substitutions are properly terminated. */
4693 as_bad (_("Missing forced substitution terminator ':'"));
4699 /* Restore the character after the symbol end. */
4702 /* Continue examining after the replacement value. */
4703 ptr
= tmp
+ strlen (head
) + strlen (value
);
4705 head
= replacement
= tmp
;
4723 /* We use this to handle substitution symbols
4724 hijack input_line_pointer, replacing it with our substituted string.
4726 .sslist should enable listing the line after replacements are made...
4728 returns the new buffer limit. */
4731 tic54x_start_line_hook (void)
4734 char *replacement
= NULL
;
4736 /* Work with a copy of the input line, including EOL char. */
4737 endp
= input_line_pointer
;
4738 while (!is_end_of_line
[(int) *endp
++])
4740 line
= xmemdup0 (input_line_pointer
, endp
- input_line_pointer
);
4742 /* Scan ahead for parallel insns. */
4743 parallel_on_next_line_hint
= next_line_shows_parallel (endp
);
4745 /* If within a macro, first process forced replacements. */
4746 if (macro_level
> 0)
4747 replacement
= subsym_substitute (line
, 1);
4750 replacement
= subsym_substitute (replacement
, 0);
4752 if (replacement
!= line
)
4754 char *tmp
= replacement
;
4755 char *comment
= strchr (replacement
, ';');
4756 char endc
= replacement
[strlen (replacement
) - 1];
4758 /* Clean up the replacement; we'd prefer to have this done by the
4759 standard preprocessing equipment (maybe do_scrub_chars?)
4760 but for now, do a quick-and-dirty. */
4761 if (comment
!= NULL
)
4768 comment
= replacement
+ strlen (replacement
) - 1;
4770 /* Trim trailing whitespace. */
4771 while (ISSPACE (*comment
))
4778 /* Compact leading whitespace. */
4779 while (ISSPACE (tmp
[0]) && ISSPACE (tmp
[1]))
4782 input_line_pointer
= endp
;
4783 input_scrub_insert_line (tmp
);
4786 /* Keep track of whether we've done a substitution. */
4787 substitution_line
= 1;
4793 substitution_line
= 0;
4797 /* This is the guts of the machine-dependent assembler. STR points to a
4798 machine dependent instruction. This function is supposed to emit
4799 the frags/bytes it assembles to. */
4801 md_assemble (char *line
)
4803 static int repeat_slot
= 0;
4804 static int delay_slots
= 0; /* How many delay slots left to fill? */
4805 static int is_parallel
= 0;
4806 static tic54x_insn insn
;
4808 char *savedp
= input_line_pointer
;
4811 input_line_pointer
= line
;
4812 c
= get_symbol_name (&line
);
4816 if (address_mode_needs_set
)
4818 set_address_mode (amode
);
4819 address_mode_needs_set
= 0;
4832 strcpy (insn
.parmnemonic
, line
);
4833 lptr
= input_line_pointer
;
4835 input_line_pointer
= savedp
;
4837 if (tic54x_parse_parallel_insn_lastline (&insn
, lptr
))
4839 int words
= build_insn (&insn
);
4841 if (delay_slots
!= 0)
4843 if (words
> delay_slots
)
4845 as_bad (ngettext ("Instruction does not fit in available "
4846 "delay slots (%d-word insn, %d slot left)",
4847 "Instruction does not fit in available "
4848 "delay slots (%d-word insn, %d slots left)",
4850 words
, delay_slots
);
4854 delay_slots
-= words
;
4860 memset (&insn
, 0, sizeof (insn
));
4861 strcpy (insn
.mnemonic
, line
);
4862 lptr
= input_line_pointer
;
4864 input_line_pointer
= savedp
;
4866 /* See if this line is part of a parallel instruction; if so, either this
4867 line or the next line will have the "||" specifier preceding the
4868 mnemonic, and we look for it in the parallel insn hash table. */
4869 if (strstr (line
, "||") != NULL
|| parallel_on_next_line_hint
)
4871 char *tmp
= strstr (line
, "||");
4875 if (tic54x_parse_parallel_insn_firstline (&insn
, lptr
))
4878 /* If the parallel part is on the same line, process it now,
4879 otherwise let the assembler pick up the next line for us. */
4882 while (ISSPACE (tmp
[2]))
4884 md_assemble (tmp
+ 2);
4889 as_bad (_("Unrecognized parallel instruction '%s'"), line
);
4894 if (tic54x_parse_insn (&insn
, lptr
))
4898 if ((insn
.tm
->flags
& FL_LP
)
4899 && cpu
!= V545LP
&& cpu
!= V546LP
)
4901 as_bad (_("Instruction '%s' requires an LP cpu version"),
4905 if ((insn
.tm
->flags
& FL_FAR
)
4906 && amode
!= far_mode
)
4908 as_bad (_("Instruction '%s' requires far mode addressing"),
4913 words
= build_insn (&insn
);
4915 /* Is this instruction in a delay slot? */
4918 if (words
> delay_slots
)
4920 as_warn (ngettext ("Instruction does not fit in available "
4921 "delay slots (%d-word insn, %d slot left). "
4922 "Resulting behavior is undefined.",
4923 "Instruction does not fit in available "
4924 "delay slots (%d-word insn, %d slots left). "
4925 "Resulting behavior is undefined.",
4927 words
, delay_slots
);
4931 /* Branches in delay slots are not allowed. */
4932 if (insn
.tm
->flags
& FL_BMASK
)
4934 as_warn (_("Instructions which cause PC discontinuity are not "
4935 "allowed in a delay slot. "
4936 "Resulting behavior is undefined."));
4938 delay_slots
-= words
;
4941 /* Is this instruction the target of a repeat? */
4944 if (insn
.tm
->flags
& FL_NR
)
4945 as_warn (_("'%s' is not repeatable. "
4946 "Resulting behavior is undefined."),
4948 else if (insn
.is_lkaddr
)
4949 as_warn (_("Instructions using long offset modifiers or absolute "
4950 "addresses are not repeatable. "
4951 "Resulting behavior is undefined."));
4955 /* Make sure we check the target of a repeat instruction. */
4956 if (insn
.tm
->flags
& B_REPEAT
)
4959 /* FIXME -- warn if repeat_slot == 1 at EOF. */
4961 /* Make sure we check our delay slots for validity. */
4962 if (insn
.tm
->flags
& FL_DELAY
)
4965 /* FIXME -- warn if delay_slots != 0 at EOF. */
4970 /* Do a final adjustment on the symbol table; in this case, make sure we have
4971 a ".file" symbol. */
4974 tic54x_adjust_symtab (void)
4976 if (symbol_rootP
== NULL
4977 || S_GET_STORAGE_CLASS (symbol_rootP
) != C_FILE
)
4980 const char * filename
= as_where (&lineno
);
4981 c_dot_file_symbol (filename
, 0);
4985 /* In order to get gas to ignore any | chars at the start of a line,
4986 this function returns true if a | is found in a line.
4987 This lets us process parallel instructions, which span two lines. */
4990 tic54x_unrecognized_line (int c
)
4992 return c
== PARALLEL_SEPARATOR
;
4995 /* Watch for local labels of the form $[0-9] and [_a-zA-Z][_a-zA-Z0-9]*?
4996 Encode their names so that only we see them and can map them to the
4998 FIXME -- obviously this isn't done yet. These locals still show up in the
5001 tic54x_define_label (symbolS
*sym
)
5003 /* Just in case we need this later; note that this is not necessarily the
5004 same thing as line_label...
5005 When aligning or assigning labels to fields, sometimes the label is
5006 assigned other than the address at which the label appears.
5007 FIXME -- is this really needed? I think all the proper label assignment
5008 is done in tic54x_cons. */
5009 last_label_seen
= sym
;
5012 /* Try to parse something that normal parsing failed at. */
5015 tic54x_undefined_symbol (char *name
)
5019 /* Not sure how to handle predefined symbols. */
5020 if ((sym
= (tic54x_symbol
*) hash_find (cc_hash
, name
)) != NULL
||
5021 (sym
= (tic54x_symbol
*) hash_find (cc2_hash
, name
)) != NULL
||
5022 (sym
= (tic54x_symbol
*) hash_find (cc3_hash
, name
)) != NULL
||
5023 (sym
= (tic54x_symbol
*) hash_find (misc_symbol_hash
, name
)) != NULL
||
5024 (sym
= (tic54x_symbol
*) hash_find (sbit_hash
, name
)) != NULL
)
5026 return symbol_new (name
, reg_section
,
5027 (valueT
) sym
->value
,
5028 &zero_address_frag
);
5031 if ((sym
= (tic54x_symbol
*) hash_find (reg_hash
, name
)) != NULL
||
5032 (sym
= (tic54x_symbol
*) hash_find (mmreg_hash
, name
)) != NULL
||
5033 !strcasecmp (name
, "a") || !strcasecmp (name
, "b"))
5035 return symbol_new (name
, reg_section
,
5036 (valueT
) sym
? sym
->value
: 0,
5037 &zero_address_frag
);
5043 /* Parse a name in an expression before the expression parser takes a stab at
5047 tic54x_parse_name (char *name ATTRIBUTE_UNUSED
,
5048 expressionS
*expn ATTRIBUTE_UNUSED
)
5054 md_atof (int type
, char *literalP
, int *sizeP
)
5056 /* Target data is little-endian, but floats are stored
5057 big-"word"ian. ugh. */
5058 return ieee_md_atof (type
, literalP
, sizeP
, TRUE
);
5062 tc_gen_reloc (asection
*section
, fixS
*fixP
)
5065 bfd_reloc_code_real_type code
= fixP
->fx_r_type
;
5066 asymbol
*sym
= symbol_get_bfdsym (fixP
->fx_addsy
);
5068 rel
= XNEW (arelent
);
5069 rel
->sym_ptr_ptr
= XNEW (asymbol
*);
5070 *rel
->sym_ptr_ptr
= sym
;
5071 /* We assume that all rel->address are host byte offsets. */
5072 rel
->address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
5073 rel
->address
/= OCTETS_PER_BYTE
;
5074 rel
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
5075 if (!strcmp (sym
->name
, section
->name
))
5076 rel
->howto
+= HOWTO_BANK
;
5080 const char *name
= S_GET_NAME (fixP
->fx_addsy
);
5083 as_fatal ("Cannot generate relocation type for symbol %s, code %s",
5084 name
, bfd_get_reloc_code_name (code
));
5090 /* Handle cons expressions. */
5093 tic54x_cons_fix_new (fragS
*frag
, int where
, int octets
, expressionS
*expn
,
5094 bfd_reloc_code_real_type r
)
5099 as_bad (_("Unsupported relocation size %d"), octets
);
5100 r
= BFD_RELOC_TIC54X_16_OF_23
;
5103 r
= BFD_RELOC_TIC54X_16_OF_23
;
5106 /* TI assembler always uses this, regardless of addressing mode. */
5108 r
= BFD_RELOC_TIC54X_23
;
5110 /* We never want to directly generate this; this is provided for
5111 stabs support only. */
5115 fix_new_exp (frag
, where
, octets
, expn
, 0, r
);
5118 /* Attempt to simplify or even eliminate a fixup.
5119 To indicate that a fixup has been eliminated, set fixP->fx_done.
5121 If fixp->fx_addsy is non-NULL, we'll have to generate a reloc entry. */
5124 md_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg ATTRIBUTE_UNUSED
)
5126 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
5127 valueT val
= * valP
;
5129 switch (fixP
->fx_r_type
)
5132 as_fatal ("Bad relocation type: 0x%02x", fixP
->fx_r_type
);
5134 case BFD_RELOC_TIC54X_MS7_OF_23
:
5135 val
= (val
>> 16) & 0x7F;
5137 case BFD_RELOC_TIC54X_16_OF_23
:
5139 bfd_put_16 (stdoutput
, val
, buf
);
5140 /* Indicate what we're actually writing, so that we don't get warnings
5141 about exceeding available space. */
5142 *valP
= val
& 0xFFFF;
5144 case BFD_RELOC_TIC54X_PARTLS7
:
5145 bfd_put_16 (stdoutput
,
5146 (bfd_get_16 (stdoutput
, buf
) & 0xFF80) | (val
& 0x7F),
5148 /* Indicate what we're actually writing, so that we don't get warnings
5149 about exceeding available space. */
5152 case BFD_RELOC_TIC54X_PARTMS9
:
5153 /* TI assembler doesn't shift its encoding for relocatable files, and is
5154 thus incompatible with this implementation's relocatable files. */
5155 bfd_put_16 (stdoutput
,
5156 (bfd_get_16 (stdoutput
, buf
) & 0xFE00) | (val
>> 7),
5160 case BFD_RELOC_TIC54X_23
:
5161 bfd_put_32 (stdoutput
,
5162 (bfd_get_32 (stdoutput
, buf
) & 0xFF800000) | val
,
5167 if (fixP
->fx_addsy
== NULL
&& fixP
->fx_pcrel
== 0)
5171 /* This is our chance to record section alignment
5172 don't need to do anything here, since BFD does the proper encoding. */
5175 md_section_align (segT segment ATTRIBUTE_UNUSED
, valueT section_size
)
5177 return section_size
;
5181 md_pcrel_from (fixS
*fixP ATTRIBUTE_UNUSED
)
5186 /* Mostly little-endian, but longwords (4 octets) get MS word stored
5190 tic54x_number_to_chars (char *buf
, valueT val
, int n
)
5193 number_to_chars_littleendian (buf
, val
, n
);
5196 number_to_chars_littleendian (buf
, val
>> 16 , 2);
5197 number_to_chars_littleendian (buf
+ 2, val
& 0xFFFF, 2);
5202 tic54x_estimate_size_before_relax (fragS
*frag ATTRIBUTE_UNUSED
,
5203 segT seg ATTRIBUTE_UNUSED
)
5208 /* We use this to handle bit allocations which we couldn't handle before due
5209 to symbols being in different frags. return number of octets added. */
5212 tic54x_relax_frag (fragS
*frag
, long stretch ATTRIBUTE_UNUSED
)
5214 symbolS
*sym
= frag
->fr_symbol
;
5220 struct bit_info
*bi
= (struct bit_info
*) frag
->fr_opcode
;
5221 int bit_offset
= frag_bit_offset (frag_prev (frag
, bi
->seg
), bi
->seg
);
5222 int size
= S_GET_VALUE (sym
);
5223 fragS
*prev_frag
= bit_offset_frag (frag_prev (frag
, bi
->seg
), bi
->seg
);
5224 int available
= 16 - bit_offset
;
5226 if (symbol_get_frag (sym
) != &zero_address_frag
5227 || S_IS_COMMON (sym
)
5228 || !S_IS_DEFINED (sym
))
5229 as_bad_where (frag
->fr_file
, frag
->fr_line
,
5230 _("non-absolute value used with .space/.bes"));
5234 as_warn (_("negative value ignored in %s"),
5235 bi
->type
== TYPE_SPACE
? ".space" :
5236 bi
->type
== TYPE_BES
? ".bes" : ".field");
5238 frag
->tc_frag_data
= frag
->fr_fix
= 0;
5242 if (bi
->type
== TYPE_FIELD
)
5244 /* Bit fields of 16 or larger will have already been handled. */
5245 if (bit_offset
!= 0 && available
>= size
)
5247 char *p
= prev_frag
->fr_literal
;
5249 valueT value
= bi
->value
;
5250 value
<<= available
- size
;
5251 value
|= ((unsigned short) p
[1] << 8) | p
[0];
5252 md_number_to_chars (p
, value
, 2);
5253 if ((prev_frag
->tc_frag_data
+= size
) == 16)
5254 prev_frag
->tc_frag_data
= 0;
5256 symbol_set_frag (bi
->sym
, prev_frag
);
5257 /* This frag is no longer used. */
5258 growth
= -frag
->fr_fix
;
5260 frag
->tc_frag_data
= 0;
5264 char *p
= frag
->fr_literal
;
5266 valueT value
= bi
->value
<< (16 - size
);
5267 md_number_to_chars (p
, value
, 2);
5268 if ((frag
->tc_frag_data
= size
) == 16)
5269 frag
->tc_frag_data
= 0;
5275 if (bit_offset
!= 0 && bit_offset
< 16)
5277 if (available
>= size
)
5279 if ((prev_frag
->tc_frag_data
+= size
) == 16)
5280 prev_frag
->tc_frag_data
= 0;
5282 symbol_set_frag (bi
->sym
, prev_frag
);
5283 /* This frag is no longer used. */
5284 growth
= -frag
->fr_fix
;
5286 frag
->tc_frag_data
= 0;
5289 if (bi
->type
== TYPE_SPACE
&& bi
->sym
)
5290 symbol_set_frag (bi
->sym
, prev_frag
);
5293 growth
= (size
+ 15) / 16 * OCTETS_PER_BYTE
- frag
->fr_fix
;
5294 for (i
= 0; i
< growth
; i
++)
5295 frag
->fr_literal
[i
] = 0;
5296 frag
->fr_fix
= growth
;
5297 frag
->tc_frag_data
= size
% 16;
5298 /* Make sure any BES label points to the LAST word allocated. */
5299 if (bi
->type
== TYPE_BES
&& bi
->sym
)
5300 S_SET_VALUE (bi
->sym
, frag
->fr_fix
/ OCTETS_PER_BYTE
- 1);
5303 frag
->fr_symbol
= 0;
5304 frag
->fr_opcode
= 0;
5311 tic54x_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
,
5312 segT seg ATTRIBUTE_UNUSED
,
5315 /* Offset is in bytes. */
5316 frag
->fr_offset
= (frag
->fr_next
->fr_address
5318 - frag
->fr_fix
) / frag
->fr_var
;
5319 if (frag
->fr_offset
< 0)
5321 as_bad_where (frag
->fr_file
, frag
->fr_line
,
5322 _("attempt to .space/.bes backwards? (%ld)"),
5323 (long) frag
->fr_offset
);
5325 frag
->fr_type
= rs_space
;
5328 /* We need to avoid having labels defined for certain directives/pseudo-ops
5329 since once the label is defined, it's in the symbol table for good. TI
5330 syntax puts the symbol *before* the pseudo (which is kinda like MRI syntax,
5331 I guess, except I've never seen a definition of MRI syntax).
5333 Don't allow labels to start with '.' */
5336 tic54x_start_label (int nul_char
, int next_char
)
5340 /* If within .struct/.union, no auto line labels, please. */
5341 if (current_stag
!= NULL
)
5344 /* Disallow labels starting with "." */
5345 if (next_char
!= ':')
5347 char *label
= input_line_pointer
;
5349 while (!is_end_of_line
[(int) label
[-1]])
5353 as_bad (_("Invalid label '%s'"), label
);
5358 if (is_end_of_line
[(int) next_char
])
5361 rest
= input_line_pointer
;
5362 if (nul_char
== '"')
5364 while (ISSPACE (next_char
))
5365 next_char
= *++rest
;
5366 if (next_char
!= '.')
5369 /* Don't let colon () define a label for any of these... */
5370 return ((strncasecmp (rest
, ".tag", 4) != 0 || !ISSPACE (rest
[4]))
5371 && (strncasecmp (rest
, ".struct", 7) != 0 || !ISSPACE (rest
[7]))
5372 && (strncasecmp (rest
, ".union", 6) != 0 || !ISSPACE (rest
[6]))
5373 && (strncasecmp (rest
, ".macro", 6) != 0 || !ISSPACE (rest
[6]))
5374 && (strncasecmp (rest
, ".set", 4) != 0 || !ISSPACE (rest
[4]))
5375 && (strncasecmp (rest
, ".equ", 4) != 0 || !ISSPACE (rest
[4])));