1 /* tc-tic54x.c -- Assembly code for the Texas Instruments TMS320C54X
2 Copyright (C) 1999-2022 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 htab_t subsym_recurse_hash
; /* Prevent infinite recurse. */
185 /* Allow maximum levels of macro nesting; level 0 is the main substitution
186 symbol table. The other assembler only does 32 levels, so there! */
187 #define MAX_SUBSYM_HASH 100
188 static htab_t subsym_hash
[MAX_SUBSYM_HASH
];
194 int (*s
) (char *, char *);
195 float (*f
) (float, float);
196 int (*i
) (float, float);
205 const subsym_proc_entry
*p
;
207 unsigned int freekey
: 1;
208 unsigned int freeval
: 1;
209 unsigned int isproc
: 1;
210 unsigned int ismath
: 1;
214 /* Keep track of local labels so we can substitute them before GAS sees them
215 since macros use their own 'namespace' for local labels, use a separate hash
217 We do our own local label handling 'cuz it's subtly different from the
220 We use our own macro nesting counter, since GAS overloads it when expanding
221 other things (like conditionals and repeat loops). */
222 static int macro_level
= 0;
223 static htab_t local_label_hash
[MAX_SUBSYM_HASH
];
224 /* Keep track of struct/union tags. */
225 static htab_t stag_hash
;
226 static htab_t op_hash
;
227 static htab_t parop_hash
;
228 static htab_t reg_hash
;
229 static htab_t mmreg_hash
;
230 static htab_t cc_hash
;
231 static htab_t cc2_hash
;
232 static htab_t cc3_hash
;
233 static htab_t sbit_hash
;
234 static htab_t misc_symbol_hash
;
236 /* Only word (et al.), align, or conditionals are allowed within
238 #define ILLEGAL_WITHIN_STRUCT() \
240 if (current_stag != NULL) \
242 as_bad (_("pseudo-op illegal within .struct/.union")); \
248 static void subsym_create_or_replace (char *, char *);
249 static subsym_ent_t
*subsym_lookup (char *, int);
250 static char *subsym_substitute (char *, int);
254 md_show_usage (FILE *stream
)
256 fprintf (stream
, _("C54x-specific command line options:\n"));
257 fprintf (stream
, _("-mfar-mode | -mf Use extended addressing\n"));
258 fprintf (stream
, _("-mcpu=<CPU version> Specify the CPU version\n"));
259 fprintf (stream
, _("-merrors-to-file <filename>\n"));
260 fprintf (stream
, _("-me <filename> Redirect errors to a file\n"));
263 /* Output a single character (upper octet is zero). */
266 tic54x_emit_char (char c
)
270 expn
.X_op
= O_constant
;
271 expn
.X_add_number
= c
;
272 emit_expr (&expn
, 2);
275 /* Walk backwards in the frag chain. */
278 frag_prev (fragS
*frag
, segT seg
)
280 segment_info_type
*seginfo
= seg_info (seg
);
283 for (fragp
= seginfo
->frchainP
->frch_root
; fragp
; fragp
= fragp
->fr_next
)
284 if (fragp
->fr_next
== frag
)
291 bit_offset_frag (fragS
*frag
, segT seg
)
295 if (frag
->fr_fix
== 0
296 && frag
->fr_opcode
== NULL
297 && frag
->tc_frag_data
== 0)
298 frag
= frag_prev (frag
, seg
);
305 /* Return the number of bits allocated in the most recent word, or zero if
306 none. .field/.space/.bes may leave words partially allocated. */
309 frag_bit_offset (fragS
*frag
, segT seg
)
311 frag
= bit_offset_frag (frag
, seg
);
314 return frag
->fr_opcode
!= NULL
? -1 : frag
->tc_frag_data
;
319 /* Read an expression from a C string; returns a pointer past the end of the
323 parse_expression (char *str
, expressionS
*expn
)
328 tmp
= input_line_pointer
; /* Save line pointer. */
329 input_line_pointer
= str
;
331 s
= input_line_pointer
;
332 input_line_pointer
= tmp
; /* Restore line pointer. */
333 return s
; /* Return pointer to where parsing stopped. */
336 /* .asg "character-string"|character-string, symbol
338 .eval is the only pseudo-op allowed to perform arithmetic on substitution
339 symbols. all other use of symbols defined with .asg are currently
343 tic54x_asg (int x ATTRIBUTE_UNUSED
)
348 int quoted
= *input_line_pointer
== '"';
350 ILLEGAL_WITHIN_STRUCT ();
355 str
= demand_copy_C_string (&len
);
356 c
= *input_line_pointer
;
361 str
= input_line_pointer
;
362 while ((c
= *input_line_pointer
) != ',')
364 if (is_end_of_line
[(unsigned char) c
])
366 ++input_line_pointer
;
368 len
= input_line_pointer
- str
;
369 str
= notes_memdup (str
, len
, len
+ 1);
373 as_bad (_("Comma and symbol expected for '.asg STRING, SYMBOL'"));
375 ignore_rest_of_line ();
379 ++input_line_pointer
;
380 c
= get_symbol_name (&name
); /* Get terminator. */
381 name
= notes_strdup (name
);
382 (void) restore_line_pointer (c
);
383 if (!ISALPHA (*name
))
385 as_bad (_("symbols assigned with .asg must begin with a letter"));
387 ignore_rest_of_line ();
391 subsym_create_or_replace (name
, str
);
392 demand_empty_rest_of_line ();
395 /* .eval expression, symbol
396 There's something screwy about this. The other assembler sometimes does and
397 sometimes doesn't substitute symbols defined with .eval.
398 We'll put the symbols into the subsym table as well as the normal symbol
399 table, since that's what works best. */
402 tic54x_eval (int x ATTRIBUTE_UNUSED
)
408 char valuestr
[32], *tmp
;
411 ILLEGAL_WITHIN_STRUCT ();
415 quoted
= *input_line_pointer
== '"';
417 ++input_line_pointer
;
418 value
= get_absolute_expression ();
421 if (*input_line_pointer
!= '"')
423 as_bad (_("Unterminated string after absolute expression"));
424 ignore_rest_of_line ();
427 ++input_line_pointer
;
429 if (*input_line_pointer
++ != ',')
431 as_bad (_("Comma and symbol expected for '.eval EXPR, SYMBOL'"));
432 ignore_rest_of_line ();
435 c
= get_symbol_name (&name
); /* Get terminator. */
437 if (!ISALPHA (*name
))
439 as_bad (_("symbols assigned with .eval must begin with a letter"));
440 (void) restore_line_pointer (c
);
441 ignore_rest_of_line ();
444 name
= notes_strdup (name
);
445 (void) restore_line_pointer (c
);
447 symbolP
= symbol_new (name
, absolute_section
, &zero_address_frag
, value
);
448 SF_SET_LOCAL (symbolP
);
449 symbol_table_insert (symbolP
);
451 /* The "other" assembler sometimes doesn't put .eval's in the subsym table
452 But since there's not written rule as to when, don't even bother trying
453 to match their behavior. */
454 sprintf (valuestr
, "%d", value
);
455 tmp
= notes_strdup (valuestr
);
456 subsym_create_or_replace (name
, tmp
);
458 demand_empty_rest_of_line ();
461 /* .bss symbol, size [, [blocking flag] [, alignment flag]
463 alignment is to a longword boundary; blocking is to 128-word boundary.
465 1) if there is a hole in memory, this directive should attempt to fill it
466 (not yet implemented).
468 2) if the blocking flag is not set, allocate at the current SPC
469 otherwise, check to see if the current SPC plus the space to be
470 allocated crosses the page boundary (128 words).
471 if there's not enough space, create a hole and align with the next page
473 (not yet implemented). */
476 tic54x_bss (int x ATTRIBUTE_UNUSED
)
483 subsegT current_subseg
;
488 ILLEGAL_WITHIN_STRUCT ();
490 current_seg
= now_seg
; /* Save current seg. */
491 current_subseg
= now_subseg
; /* Save current subseg. */
493 c
= get_symbol_name (&name
); /* Get terminator. */
495 c
= * ++ input_line_pointer
;
498 as_bad (_(".bss size argument missing\n"));
499 ignore_rest_of_line ();
503 ++input_line_pointer
;
504 words
= get_absolute_expression ();
507 as_bad (_(".bss size %d < 0!"), words
);
508 ignore_rest_of_line ();
512 if (*input_line_pointer
== ',')
514 /* The blocking flag may be missing. */
515 ++input_line_pointer
;
516 if (*input_line_pointer
!= ',')
517 block
= get_absolute_expression ();
521 if (*input_line_pointer
== ',')
523 ++input_line_pointer
;
524 align
= get_absolute_expression ();
532 subseg_set (bss_section
, 0);
533 symbolP
= symbol_find_or_make (name
);
535 if (S_GET_SEGMENT (symbolP
) == bss_section
)
536 symbol_get_frag (symbolP
)->fr_symbol
= (symbolS
*) NULL
;
538 symbol_set_frag (symbolP
, frag_now
);
539 p
= frag_var (rs_org
, 1, 1, (relax_substateT
) 0, symbolP
,
540 (offsetT
) (words
* OCTETS_PER_BYTE
), (char *) 0);
541 *p
= 0; /* Fill char. */
543 S_SET_SEGMENT (symbolP
, bss_section
);
545 /* The symbol may already have been created with a preceding
546 ".globl" directive -- be careful not to step on storage class
547 in that case. Otherwise, set it to static. */
548 if (S_GET_STORAGE_CLASS (symbolP
) != C_EXT
)
549 S_SET_STORAGE_CLASS (symbolP
, C_STAT
);
553 /* s_align eats end of line; restore it */
555 --input_line_pointer
;
559 bss_section
->flags
|= SEC_TIC54X_BLOCK
;
561 subseg_set (current_seg
, current_subseg
); /* Restore current seg. */
562 demand_empty_rest_of_line ();
566 stag_add_field_symbols (struct stag
*stag
,
570 const char *root_stag_name
)
573 struct stag_field
*field
= stag
->field
;
575 /* Construct a symbol for every field contained within this structure
576 including fields within structure fields. */
577 prefix
= concat (path
, *path
? "." : "", NULL
);
579 while (field
!= NULL
)
581 char *name
= concat (prefix
, field
->name
, NULL
);
582 char *freename
= name
;
587 sym
= symbol_new (name
, absolute_section
, &zero_address_frag
,
588 (field
->stag
? field
->offset
589 : base_offset
+ field
->offset
));
591 symbol_table_insert (sym
);
595 subsym_ent_t
*ent
= xmalloc (sizeof (*ent
));
596 ent
->u
.s
= concat (S_GET_NAME (rootsym
), "+", root_stag_name
,
597 name
+ strlen (S_GET_NAME (rootsym
)), NULL
);
602 str_hash_insert (subsym_hash
[0], name
, ent
, 0);
606 /* Recurse if the field is a structure.
607 Note the field offset is relative to the outermost struct. */
608 if (field
->stag
!= NULL
)
609 stag_add_field_symbols (field
->stag
, name
,
611 rootsym
, root_stag_name
);
618 /* Keep track of stag fields so that when structures are nested we can add the
619 complete dereferencing symbols to the symbol table. */
622 stag_add_field (struct stag
*parent
,
627 struct stag_field
*sfield
= XCNEW (struct stag_field
);
629 sfield
->name
= xstrdup (name
);
630 sfield
->offset
= offset
;
631 sfield
->bitfield_offset
= parent
->current_bitfield_offset
;
633 if (parent
->field
== NULL
)
634 parent
->field
= sfield
;
637 struct stag_field
*sf
= parent
->field
;
638 while (sf
->next
!= NULL
)
642 /* Only create a symbol for this field if the parent has no name. */
643 if (startswith (parent
->name
, ".fake"))
645 symbolS
*sym
= symbol_new (name
, absolute_section
, &zero_address_frag
,
648 symbol_table_insert (sym
);
652 /* [STAG] .struct [OFFSET]
653 Start defining structure offsets (symbols in absolute section). */
656 tic54x_struct (int arg
)
658 int start_offset
= 0;
663 /* Starting a new struct, switch to absolute section. */
664 stag_saved_seg
= now_seg
;
665 stag_saved_subseg
= now_subseg
;
666 subseg_set (absolute_section
, 0);
668 /* Align the current pointer. */
669 else if (current_stag
->current_bitfield_offset
!= 0)
671 ++abs_section_offset
;
672 current_stag
->current_bitfield_offset
= 0;
675 /* Offset expression is only meaningful for global .structs. */
678 /* Offset is ignored in inner structs. */
680 if (!is_end_of_line
[(unsigned char) *input_line_pointer
])
681 start_offset
= get_absolute_expression ();
688 /* Nesting, link to outer one. */
689 current_stag
->inner
= XCNEW (struct stag
);
690 current_stag
->inner
->outer
= current_stag
;
691 current_stag
= current_stag
->inner
;
693 as_warn (_("Offset on nested structures is ignored"));
694 start_offset
= abs_section_offset
;
698 current_stag
= XCNEW (struct stag
);
699 abs_section_offset
= start_offset
;
701 current_stag
->is_union
= is_union
;
703 if (line_label
== NULL
)
705 static int struct_count
= 0;
706 char fake
[] = ".fake_stagNNNNNNN";
707 sprintf (fake
, ".fake_stag%d", struct_count
++);
708 current_stag
->sym
= symbol_new (fake
, absolute_section
,
714 char * label
= xstrdup (S_GET_NAME (line_label
));
715 current_stag
->sym
= symbol_new (label
,
721 current_stag
->name
= S_GET_NAME (current_stag
->sym
);
722 SF_SET_LOCAL (current_stag
->sym
);
723 /* Nested .structs don't go into the symbol table. */
724 if (current_stag
->outer
== NULL
)
725 symbol_table_insert (current_stag
->sym
);
730 /* [LABEL] .endstruct
731 finish defining structure offsets; optional LABEL's value will be the size
735 tic54x_endstruct (int is_union
)
739 startswith (current_stag
->name
, ".fake") ? "" : current_stag
->name
;
741 if (!current_stag
|| current_stag
->is_union
!= is_union
)
743 as_bad (_(".end%s without preceding .%s"),
744 is_union
? "union" : "struct",
745 is_union
? "union" : "struct");
746 ignore_rest_of_line ();
750 /* Align end of structures. */
751 if (current_stag
->current_bitfield_offset
)
753 ++abs_section_offset
;
754 current_stag
->current_bitfield_offset
= 0;
757 if (current_stag
->is_union
)
758 size
= current_stag
->size
;
760 size
= abs_section_offset
- S_GET_VALUE (current_stag
->sym
);
761 if (line_label
!= NULL
)
763 S_SET_VALUE (line_label
, size
);
764 symbol_table_insert (line_label
);
768 /* Union size has already been calculated. */
769 if (!current_stag
->is_union
)
770 current_stag
->size
= size
;
771 /* Nested .structs don't get put in the stag table. */
772 if (current_stag
->outer
== NULL
)
774 str_hash_insert (stag_hash
, current_stag
->name
, current_stag
, 0);
775 stag_add_field_symbols (current_stag
, path
,
776 S_GET_VALUE (current_stag
->sym
),
779 current_stag
= current_stag
->outer
;
781 /* If this is a nested .struct/.union, add it as a field to the enclosing
782 one. otherwise, restore the section we were in. */
783 if (current_stag
!= NULL
)
785 stag_add_field (current_stag
, current_stag
->inner
->name
,
786 S_GET_VALUE (current_stag
->inner
->sym
),
787 current_stag
->inner
);
790 subseg_set (stag_saved_seg
, stag_saved_subseg
);
794 Reference a structure within a structure, as a sized field with an optional
796 If used outside of a .struct/.endstruct, overlays the given structure
797 format on the existing allocated space. */
800 tic54x_tag (int ignore ATTRIBUTE_UNUSED
)
803 int c
= get_symbol_name (&name
);
804 struct stag
*stag
= (struct stag
*) str_hash_find (stag_hash
, name
);
809 as_bad (_("Unrecognized struct/union tag '%s'"), name
);
811 as_bad (_(".tag requires a structure tag"));
812 ignore_rest_of_line ();
815 if (line_label
== NULL
)
817 as_bad (_("Label required for .tag"));
818 ignore_rest_of_line ();
825 label
= xstrdup (S_GET_NAME (line_label
));
826 if (current_stag
!= NULL
)
827 stag_add_field (current_stag
, label
,
828 abs_section_offset
- S_GET_VALUE (current_stag
->sym
),
832 symbolS
*sym
= symbol_find (label
);
836 as_bad (_(".tag target '%s' undefined"), label
);
837 ignore_rest_of_line ();
841 stag_add_field_symbols (stag
, S_GET_NAME (sym
),
842 S_GET_VALUE (stag
->sym
), sym
, stag
->name
);
847 /* Bump by the struct size, but only if we're within a .struct section. */
848 if (current_stag
!= NULL
&& !current_stag
->is_union
)
849 abs_section_offset
+= stag
->size
;
851 (void) restore_line_pointer (c
);
852 demand_empty_rest_of_line ();
856 /* Handle all .byte, .char, .double, .field, .float, .half, .int, .long,
857 .short, .string, .ubyte, .uchar, .uhalf, .uint, .ulong, .ushort, .uword,
861 tic54x_struct_field (int type
)
865 int new_bitfield_offset
= 0;
866 int field_align
= current_stag
->current_bitfield_offset
!= 0;
867 int longword_align
= 0;
870 if (!is_end_of_line
[(unsigned char) *input_line_pointer
])
871 count
= get_absolute_expression ();
887 case '*': /* String. */
896 case '.': /* Bitfield. */
898 if (count
< 1 || count
> 32)
900 as_bad (_(".field count '%d' out of range (1 <= X <= 32)"), count
);
901 ignore_rest_of_line ();
904 if (current_stag
->current_bitfield_offset
+ count
> 16)
906 /* Set the appropriate size and new field offset. */
916 new_bitfield_offset
= count
- 16;
919 new_bitfield_offset
= count
;
924 new_bitfield_offset
= current_stag
->current_bitfield_offset
+ count
;
928 as_bad (_("Unrecognized field type '%c'"), type
);
929 ignore_rest_of_line ();
935 /* Align to the actual starting position of the field. */
936 current_stag
->current_bitfield_offset
= 0;
937 ++abs_section_offset
;
939 /* Align to longword boundary. */
940 if (longword_align
&& (abs_section_offset
& 0x1))
941 ++abs_section_offset
;
943 if (line_label
== NULL
)
945 static int fieldno
= 0;
946 char fake
[] = ".fake_fieldNNNNN";
948 sprintf (fake
, ".fake_field%d", fieldno
++);
949 stag_add_field (current_stag
, fake
,
950 abs_section_offset
- S_GET_VALUE (current_stag
->sym
),
957 label
= xstrdup (S_GET_NAME (line_label
));
958 stag_add_field (current_stag
, label
,
959 abs_section_offset
- S_GET_VALUE (current_stag
->sym
),
964 if (current_stag
->is_union
)
966 /* Note we treat the element as if it were an array of COUNT. */
967 if (current_stag
->size
< (unsigned) size
* count
)
968 current_stag
->size
= size
* count
;
972 abs_section_offset
+= (unsigned) size
* count
;
973 current_stag
->current_bitfield_offset
= new_bitfield_offset
;
978 /* Handle .byte, .word. .int, .long and all variants. */
981 tic54x_cons (int type
)
986 /* If we're within a .struct construct, don't actually allocate space. */
987 if (current_stag
!= NULL
)
989 tic54x_struct_field (type
);
993 #ifdef md_flush_pending_output
994 md_flush_pending_output ();
997 generate_lineno_debug ();
999 /* Align long words to long word boundaries (4 octets). */
1000 if (type
== 'l' || type
== 'L')
1002 frag_align (2, 0, 2);
1003 /* If there's a label, assign it to the first allocated word. */
1004 if (line_label
!= NULL
)
1006 symbol_set_frag (line_label
, frag_now
);
1007 S_SET_VALUE (line_label
, frag_now_fix ());
1031 if (*input_line_pointer
== '"')
1033 input_line_pointer
++;
1034 while (is_a_char (c
= next_char_of_string ()))
1035 tic54x_emit_char (c
);
1036 know (input_line_pointer
[-1] == '\"');
1042 input_line_pointer
= parse_expression (input_line_pointer
, &expn
);
1043 if (expn
.X_op
== O_constant
)
1045 offsetT value
= expn
.X_add_number
;
1046 /* Truncate overflows. */
1050 if ((value
> 0 && value
> 0xFF)
1051 || (value
< 0 && value
< - 0x100))
1052 as_warn (_("Overflow in expression, truncated to 8 bits"));
1055 if ((value
> 0 && value
> 0xFFFF)
1056 || (value
< 0 && value
< - 0x10000))
1057 as_warn (_("Overflow in expression, truncated to 16 bits"));
1061 if (expn
.X_op
!= O_constant
&& octets
< 2)
1063 /* Disallow .byte with a non constant expression that will
1064 require relocation. */
1065 as_bad (_("Relocatable values require at least WORD storage"));
1066 ignore_rest_of_line ();
1070 if (expn
.X_op
!= O_constant
1074 /* FIXME -- at one point TI tools used to output REL16
1075 relocations, but I don't think the latest tools do at all
1076 The current tools output extended relocations regardless of
1077 the addressing mode (I actually think that ".c_mode" is
1078 totally ignored in the latest tools). */
1081 emit_expr (&expn
, 4);
1087 emitting_long
= octets
== 4;
1088 emit_expr (&expn
, (octets
== 1) ? 2 : octets
);
1093 while (*input_line_pointer
++ == ',');
1095 input_line_pointer
--; /* Put terminator back into stream. */
1096 demand_empty_rest_of_line ();
1099 /* .global <symbol>[,...,<symbolN>]
1100 .def <symbol>[,...,<symbolN>]
1101 .ref <symbol>[,...,<symbolN>]
1103 These all identify global symbols.
1105 .def means the symbol is defined in the current module and can be accessed
1106 by other files. The symbol should be placed in the symbol table.
1108 .ref means the symbol is used in the current module but defined in another
1109 module. The linker is to resolve this symbol's definition at link time.
1111 .global should act as a .ref or .def, as needed.
1113 global, def and ref all have symbol storage classes of C_EXT.
1115 I can't identify any difference in how the "other" c54x assembler treats
1116 these, so we ignore the type here. */
1119 tic54x_global (int type
)
1126 as_warn (_("Use of .def/.ref is deprecated. Use .global instead"));
1128 ILLEGAL_WITHIN_STRUCT ();
1132 c
= get_symbol_name (&name
);
1133 symbolP
= symbol_find_or_make (name
);
1134 c
= restore_line_pointer (c
);
1136 S_SET_STORAGE_CLASS (symbolP
, C_EXT
);
1139 input_line_pointer
++;
1140 if (is_end_of_line
[(unsigned char) *input_line_pointer
])
1141 c
= *input_line_pointer
;
1146 demand_empty_rest_of_line ();
1150 free_subsym_ent (void *ent
)
1152 string_tuple_t
*tuple
= (string_tuple_t
*) ent
;
1153 subsym_ent_t
*val
= (void *) tuple
->value
;
1155 free ((void *) tuple
->key
);
1163 subsym_htab_create (void)
1165 return htab_create_alloc (16, hash_string_tuple
, eq_string_tuple
,
1166 free_subsym_ent
, xcalloc
, free
);
1170 free_local_label_ent (void *ent
)
1172 string_tuple_t
*tuple
= (string_tuple_t
*) ent
;
1173 free ((void *) tuple
->key
);
1174 free ((void *) tuple
->value
);
1179 local_label_htab_create (void)
1181 return htab_create_alloc (16, hash_string_tuple
, eq_string_tuple
,
1182 free_local_label_ent
, xcalloc
, free
);
1185 /* Reset all local labels. */
1188 tic54x_clear_local_labels (int ignored ATTRIBUTE_UNUSED
)
1190 htab_empty (local_label_hash
[macro_level
]);
1195 .sect "section name"
1198 make sure local labels get cleared when changing sections
1200 ARG is 't' for text, 'd' for data, or '*' for a named section
1202 For compatibility, '*' sections are SEC_CODE if instructions are
1203 encountered, or SEC_DATA if not.
1207 tic54x_sect (int arg
)
1209 ILLEGAL_WITHIN_STRUCT ();
1211 /* Local labels are cleared when changing sections. */
1212 tic54x_clear_local_labels (0);
1216 else if (arg
== 'd')
1222 /* Make sure all named initialized sections flagged properly. If we
1223 encounter instructions, we'll flag it with SEC_CODE as well. */
1224 const char *flags
= ",\"w\"\n";
1226 /* If there are quotes, remove them. */
1227 if (*input_line_pointer
== '"')
1229 name
= demand_copy_C_string (&len
);
1230 demand_empty_rest_of_line ();
1231 name
= concat (name
, flags
, (char *) NULL
);
1237 c
= get_symbol_name (&name
);
1238 name
= concat (name
, flags
, (char *) NULL
);
1239 (void) restore_line_pointer (c
);
1240 demand_empty_rest_of_line ();
1243 input_scrub_insert_line (name
);
1244 obj_coff_section (0);
1246 /* If there was a line label, make sure that it gets assigned the proper
1247 section. This is for compatibility, even though the actual behavior
1248 is not explicitly defined. For consistency, we make .sect behave
1249 like .usect, since that is probably what people expect. */
1250 if (line_label
!= NULL
)
1252 S_SET_SEGMENT (line_label
, now_seg
);
1253 symbol_set_frag (line_label
, frag_now
);
1254 S_SET_VALUE (line_label
, frag_now_fix ());
1255 if (S_GET_STORAGE_CLASS (line_label
) != C_EXT
)
1256 S_SET_STORAGE_CLASS (line_label
, C_LABEL
);
1261 /* [symbol] .space space_in_bits
1262 [symbol] .bes space_in_bits
1263 BES puts the symbol at the *last* word allocated
1265 cribbed from s_space. */
1268 tic54x_space (int arg
)
1274 int bits_per_byte
= (OCTETS_PER_BYTE
* 8);
1276 symbolS
*label
= line_label
;
1279 ILLEGAL_WITHIN_STRUCT ();
1281 #ifdef md_flush_pending_output
1282 md_flush_pending_output ();
1285 /* Read the bit count. */
1288 /* Some expressions are unresolvable until later in the assembly pass;
1289 postpone until relaxation/fixup. we also have to postpone if a previous
1290 partial allocation has not been completed yet. */
1291 if (expn
.X_op
!= O_constant
|| frag_bit_offset (frag_now
, now_seg
) == -1)
1293 struct bit_info
*bi
= XNEW (struct bit_info
);
1298 p
= frag_var (rs_machine_dependent
,
1299 65536 * 2, 1, (relax_substateT
) 0,
1300 make_expr_symbol (&expn
), (offsetT
) 0,
1308 /* Reduce the required size by any bit offsets currently left over
1309 from a previous .space/.bes/.field directive. */
1310 bit_offset
= frag_now
->tc_frag_data
;
1311 if (bit_offset
!= 0 && bit_offset
< 16)
1313 int spare_bits
= bits_per_byte
- bit_offset
;
1315 if (spare_bits
>= expn
.X_add_number
)
1317 /* Don't have to do anything; sufficient bits have already been
1318 allocated; just point the label to the right place. */
1321 symbol_set_frag (label
, frag_now
);
1322 S_SET_VALUE (label
, frag_now_fix () - 1);
1325 frag_now
->tc_frag_data
+= expn
.X_add_number
;
1328 expn
.X_add_number
-= spare_bits
;
1329 /* Set the label to point to the first word allocated, which in this
1330 case is the previous word, which was only partially filled. */
1331 if (!bes
&& label
!= NULL
)
1333 symbol_set_frag (label
, frag_now
);
1334 S_SET_VALUE (label
, frag_now_fix () - 1);
1338 /* Convert bits to bytes/words and octets, rounding up. */
1339 words
= ((expn
.X_add_number
+ bits_per_byte
- 1) / bits_per_byte
);
1340 /* How many do we have left over? */
1341 bit_offset
= expn
.X_add_number
% bits_per_byte
;
1342 octets
= words
* OCTETS_PER_BYTE
;
1345 as_warn (_(".space/.bes repeat count is negative, ignored"));
1348 else if (octets
== 0)
1350 as_warn (_(".space/.bes repeat count is zero, ignored"));
1354 /* If we are in the absolute section, just bump the offset. */
1355 if (now_seg
== absolute_section
)
1357 abs_section_offset
+= words
;
1358 if (bes
&& label
!= NULL
)
1359 S_SET_VALUE (label
, abs_section_offset
- 1);
1360 frag_now
->tc_frag_data
= bit_offset
;
1365 p
= frag_var (rs_fill
, 1, 1,
1366 (relax_substateT
) 0, (symbolS
*) 0,
1367 (offsetT
) octets
, (char *) 0);
1369 /* Make note of how many bits of this word we've allocated so far. */
1370 frag_now
->tc_frag_data
= bit_offset
;
1372 /* .bes puts label at *last* word allocated. */
1373 if (bes
&& label
!= NULL
)
1375 symbol_set_frag (label
, frag_now
);
1376 S_SET_VALUE (label
, frag_now_fix () - 1);
1384 demand_empty_rest_of_line ();
1387 /* [symbol] .usect "section-name", size-in-words
1388 [, [blocking-flag] [, alignment-flag]]
1390 Uninitialized section.
1391 Non-zero blocking means that if the section would cross a page (128-word)
1392 boundary, it will be page-aligned.
1393 Non-zero alignment aligns on a longword boundary.
1395 Has no effect on the current section. */
1398 tic54x_usect (int x ATTRIBUTE_UNUSED
)
1405 int size
, blocking_flag
, alignment_flag
;
1407 subsegT current_subseg
;
1410 ILLEGAL_WITHIN_STRUCT ();
1412 current_seg
= now_seg
; /* Save current seg. */
1413 current_subseg
= now_subseg
; /* Save current subseg. */
1415 c
= get_symbol_name (§ion_name
); /* Get terminator. */
1416 name
= xstrdup (section_name
);
1417 c
= restore_line_pointer (c
);
1420 ++input_line_pointer
;
1423 as_bad (_("Missing size argument"));
1424 ignore_rest_of_line ();
1428 size
= get_absolute_expression ();
1430 /* Read a possibly present third argument (blocking flag). */
1431 if (*input_line_pointer
== ',')
1433 ++input_line_pointer
;
1434 if (*input_line_pointer
!= ',')
1435 blocking_flag
= get_absolute_expression ();
1439 /* Read a possibly present fourth argument (alignment flag). */
1440 if (*input_line_pointer
== ',')
1442 ++input_line_pointer
;
1443 alignment_flag
= get_absolute_expression ();
1449 blocking_flag
= alignment_flag
= 0;
1451 seg
= subseg_new (name
, 0);
1452 flags
= bfd_section_flags (seg
) | SEC_ALLOC
;
1456 /* s_align eats end of line; restore it. */
1458 --input_line_pointer
;
1461 if (line_label
!= NULL
)
1463 S_SET_SEGMENT (line_label
, seg
);
1464 symbol_set_frag (line_label
, frag_now
);
1465 S_SET_VALUE (line_label
, frag_now_fix ());
1466 /* Set scl to label, since that's what TI does. */
1467 if (S_GET_STORAGE_CLASS (line_label
) != C_EXT
)
1468 S_SET_STORAGE_CLASS (line_label
, C_LABEL
);
1471 seg_info (seg
)->bss
= 1; /* Uninitialized data. */
1473 p
= frag_var (rs_fill
, 1, 1,
1474 (relax_substateT
) 0, (symbolS
*) line_label
,
1475 size
* OCTETS_PER_BYTE
, (char *) 0);
1479 flags
|= SEC_TIC54X_BLOCK
;
1481 if (!bfd_set_section_flags (seg
, flags
))
1482 as_warn (_("Error setting flags for \"%s\": %s"), name
,
1483 bfd_errmsg (bfd_get_error ()));
1485 subseg_set (current_seg
, current_subseg
); /* Restore current seg. */
1486 demand_empty_rest_of_line ();
1489 static enum cpu_version
1490 lookup_version (const char *ver
)
1492 enum cpu_version version
= VNONE
;
1494 if (ver
[0] == '5' && ver
[1] == '4')
1496 if (strlen (ver
) == 3
1497 && (ver
[2] == '1' || ver
[2] == '2' || ver
[2] == '3'
1498 || ver
[2] == '5' || ver
[2] == '8' || ver
[2] == '9'))
1499 version
= ver
[2] - '0';
1500 else if (strlen (ver
) == 5
1501 && TOUPPER (ver
[3]) == 'L'
1502 && TOUPPER (ver
[4]) == 'P'
1503 && (ver
[2] == '5' || ver
[2] == '6'))
1504 version
= ver
[2] - '0' + 10;
1511 set_cpu (enum cpu_version version
)
1514 if (version
== V545LP
|| version
== V546LP
)
1516 symbolS
*symbolP
= symbol_new ("__allow_lp", absolute_section
,
1517 &zero_address_frag
, 1);
1518 SF_SET_LOCAL (symbolP
);
1519 symbol_table_insert (symbolP
);
1523 /* .version cpu-version
1524 cpu-version may be one of the following:
1534 This is for compatibility only. It currently has no affect on assembly. */
1535 static int cpu_needs_set
= 1;
1538 tic54x_version (int x ATTRIBUTE_UNUSED
)
1540 enum cpu_version version
= VNONE
;
1541 enum cpu_version old_version
= cpu
;
1545 ILLEGAL_WITHIN_STRUCT ();
1548 ver
= input_line_pointer
;
1549 while (!is_end_of_line
[(unsigned char) *input_line_pointer
])
1550 ++input_line_pointer
;
1551 c
= *input_line_pointer
;
1552 *input_line_pointer
= 0;
1554 version
= lookup_version (ver
);
1556 if (cpu
!= VNONE
&& cpu
!= version
)
1557 as_warn (_("CPU version has already been set"));
1559 if (version
== VNONE
)
1561 as_bad (_("Unrecognized version '%s'"), ver
);
1562 ignore_rest_of_line ();
1565 else if (assembly_begun
&& version
!= old_version
)
1567 as_bad (_("Changing of CPU version on the fly not supported"));
1568 ignore_rest_of_line ();
1574 *input_line_pointer
= c
;
1575 demand_empty_rest_of_line ();
1578 /* 'f' = float, 'x' = xfloat, 'd' = double, 'l' = ldouble. */
1581 tic54x_float_cons (int type
)
1583 if (current_stag
!= 0)
1584 tic54x_struct_field ('f');
1586 #ifdef md_flush_pending_output
1587 md_flush_pending_output ();
1590 /* Align to long word boundary (4 octets) unless it's ".xfloat". */
1593 frag_align (2, 0, 2);
1594 /* If there's a label, assign it to the first allocated word. */
1595 if (line_label
!= NULL
)
1597 symbol_set_frag (line_label
, frag_now
);
1598 S_SET_VALUE (line_label
, frag_now_fix ());
1605 /* The argument is capitalized if it should be zero-terminated
1606 's' is normal string with upper 8-bits zero-filled, 'p' is packed.
1607 Code copied from stringer, and slightly modified so that strings are packed
1608 and encoded into the correct octets. */
1611 tic54x_stringer (int type
)
1614 int append_zero
= type
== 'S' || type
== 'P';
1615 int packed
= type
== 'p' || type
== 'P';
1616 int last_char
= -1; /* Packed strings need two bytes at a time to encode. */
1618 if (current_stag
!= NULL
)
1620 tic54x_struct_field ('*');
1624 #ifdef md_flush_pending_output
1625 md_flush_pending_output ();
1628 c
= ','; /* Do loop. */
1632 switch (*input_line_pointer
)
1636 unsigned short value
= get_absolute_expression ();
1637 FRAG_APPEND_1_CHAR ( value
& 0xFF);
1638 FRAG_APPEND_1_CHAR ((value
>> 8) & 0xFF);
1642 ++input_line_pointer
; /* -> 1st char of string. */
1643 while (is_a_char (c
= next_char_of_string ()))
1647 FRAG_APPEND_1_CHAR (c
);
1648 FRAG_APPEND_1_CHAR (0);
1652 /* Packed strings are filled MS octet first. */
1653 if (last_char
== -1)
1657 FRAG_APPEND_1_CHAR (c
);
1658 FRAG_APPEND_1_CHAR (last_char
);
1665 if (packed
&& last_char
!= -1)
1667 FRAG_APPEND_1_CHAR (0);
1668 FRAG_APPEND_1_CHAR (last_char
);
1673 FRAG_APPEND_1_CHAR (0);
1674 FRAG_APPEND_1_CHAR (0);
1677 know (input_line_pointer
[-1] == '\"');
1681 c
= *input_line_pointer
;
1682 if (!is_end_of_line
[c
])
1683 ++input_line_pointer
;
1686 /* Finish up any leftover packed string. */
1687 if (packed
&& last_char
!= -1)
1689 FRAG_APPEND_1_CHAR (0);
1690 FRAG_APPEND_1_CHAR (last_char
);
1692 demand_empty_rest_of_line ();
1696 tic54x_p2align (int arg ATTRIBUTE_UNUSED
)
1698 as_bad (_("p2align not supported on this target"));
1702 tic54x_align_words (int arg
)
1704 /* Only ".align" with no argument is allowed within .struct/.union. */
1707 if (!is_end_of_line
[(unsigned char) *input_line_pointer
])
1710 as_warn (_("Argument to .even ignored"));
1712 count
= get_absolute_expression ();
1715 if (current_stag
!= NULL
&& arg
== 128)
1717 if (current_stag
->current_bitfield_offset
!= 0)
1719 current_stag
->current_bitfield_offset
= 0;
1720 ++abs_section_offset
;
1722 demand_empty_rest_of_line ();
1726 ILLEGAL_WITHIN_STRUCT ();
1728 s_align_bytes (count
<< 1);
1731 /* Initialize multiple-bit fields within a single word of memory. */
1734 tic54x_field (int ignore ATTRIBUTE_UNUSED
)
1740 symbolS
*label
= line_label
;
1742 if (current_stag
!= NULL
)
1744 tic54x_struct_field ('.');
1748 input_line_pointer
= parse_expression (input_line_pointer
, &expn
);
1750 if (*input_line_pointer
== ',')
1752 ++input_line_pointer
;
1753 size
= get_absolute_expression ();
1754 if (size
< 1 || size
> 32)
1756 as_bad (_("Invalid field size, must be from 1 to 32"));
1757 ignore_rest_of_line ();
1762 /* Truncate values to the field width. */
1763 if (expn
.X_op
!= O_constant
)
1765 /* If the expression value is relocatable, the field size *must*
1769 as_bad (_("field size must be 16 when value is relocatable"));
1770 ignore_rest_of_line ();
1774 frag_now
->tc_frag_data
= 0;
1775 emit_expr (&expn
, 2);
1779 unsigned long fmask
= (size
== 32) ? 0xFFFFFFFF : (1ul << size
) - 1;
1781 value
= expn
.X_add_number
;
1782 expn
.X_add_number
&= fmask
;
1783 if (value
!= (valueT
) expn
.X_add_number
)
1784 as_warn (_("field value truncated"));
1785 value
= expn
.X_add_number
;
1786 /* Bits are stored MS first. */
1789 frag_now
->tc_frag_data
= 0;
1791 md_number_to_chars (p
, (value
>> (size
- 16)) & 0xFFFF, 2);
1796 int bit_offset
= frag_bit_offset (frag_now
, now_seg
);
1798 fragS
*alloc_frag
= bit_offset_frag (frag_now
, now_seg
);
1799 if (bit_offset
== -1)
1801 struct bit_info
*bi
= XNEW (struct bit_info
);
1802 /* We don't know the previous offset at this time, so store the
1803 info we need and figure it out later. */
1804 expressionS size_exp
;
1806 size_exp
.X_op
= O_constant
;
1807 size_exp
.X_add_number
= size
;
1809 bi
->type
= TYPE_FIELD
;
1811 p
= frag_var (rs_machine_dependent
,
1812 4, 1, (relax_substateT
) 0,
1813 make_expr_symbol (&size_exp
), (offsetT
) 0,
1817 else if (bit_offset
== 0 || bit_offset
+ size
> 16)
1819 /* Align a new field. */
1821 frag_now
->tc_frag_data
= 0;
1822 alloc_frag
= frag_now
;
1826 /* Put the new value entirely within the existing one. */
1827 p
= alloc_frag
== frag_now
?
1828 frag_now
->fr_literal
+ frag_now_fix_octets () - 2 :
1829 alloc_frag
->fr_literal
;
1832 symbol_set_frag (label
, alloc_frag
);
1833 if (alloc_frag
== frag_now
)
1834 S_SET_VALUE (label
, frag_now_fix () - 1);
1838 value
<<= 16 - alloc_frag
->tc_frag_data
- size
;
1840 /* OR in existing value. */
1841 if (alloc_frag
->tc_frag_data
)
1842 value
|= ((unsigned short) p
[1] << 8) | p
[0];
1843 md_number_to_chars (p
, value
, 2);
1844 alloc_frag
->tc_frag_data
+= size
;
1845 if (alloc_frag
->tc_frag_data
== 16)
1846 alloc_frag
->tc_frag_data
= 0;
1850 demand_empty_rest_of_line ();
1853 /* Ideally, we want to check SEC_LOAD and SEC_HAS_CONTENTS, but those aren't
1854 available yet. seg_info ()->bss is the next best thing. */
1857 tic54x_initialized_section (segT seg
)
1859 return !seg_info (seg
)->bss
;
1862 /* .clink ["section name"]
1864 Marks the section as conditionally linked (link only if contents are
1865 referenced elsewhere.
1866 Without a name, refers to the current initialized section.
1867 Name is required for uninitialized sections. */
1870 tic54x_clink (int ignored ATTRIBUTE_UNUSED
)
1874 ILLEGAL_WITHIN_STRUCT ();
1876 if (*input_line_pointer
== '\"')
1878 char *section_name
= ++input_line_pointer
;
1881 while (is_a_char (next_char_of_string ()))
1883 know (input_line_pointer
[-1] == '\"');
1884 input_line_pointer
[-1] = 0;
1885 name
= xstrdup (section_name
);
1887 seg
= bfd_get_section_by_name (stdoutput
, name
);
1890 as_bad (_("Unrecognized section '%s'"), section_name
);
1891 ignore_rest_of_line ();
1897 if (!tic54x_initialized_section (seg
))
1899 as_bad (_("Current section is uninitialized, "
1900 "section name required for .clink"));
1901 ignore_rest_of_line ();
1906 seg
->flags
|= SEC_TIC54X_CLINK
;
1908 demand_empty_rest_of_line ();
1911 /* Change the default include directory to be the current source file's
1912 directory, instead of the current working directory. If DOT is non-zero,
1913 set to "." instead. */
1916 tic54x_set_default_include (void)
1918 char *dir
, *tmp
= NULL
;
1919 const char *curfile
;
1922 curfile
= as_where (&lineno
);
1923 dir
= xstrdup (curfile
);
1924 tmp
= strrchr (dir
, '/');
1931 if (include_dir_count
== 0)
1933 include_dirs
= XNEWVEC (const char *, 1);
1934 include_dir_count
= 1;
1936 include_dirs
[0] = dir
;
1937 if (len
> include_dir_maxlen
)
1938 include_dir_maxlen
= len
;
1940 else if (include_dirs
!= NULL
)
1941 include_dirs
[0] = ".";
1944 /* .include "filename" | filename
1945 .copy "filename" | filename
1947 FIXME 'include' file should be omitted from any output listing,
1948 'copy' should be included in any output listing
1949 FIXME -- prevent any included files from changing listing (compat only)
1950 FIXME -- need to include source file directory in search path; what's a
1951 good way to do this?
1953 Entering/exiting included/copied file clears all local labels. */
1956 tic54x_include (int ignored ATTRIBUTE_UNUSED
)
1958 char newblock
[] = " .newblock\n";
1963 ILLEGAL_WITHIN_STRUCT ();
1967 if (*input_line_pointer
== '"')
1969 filename
= demand_copy_C_string (&len
);
1970 demand_empty_rest_of_line ();
1974 filename
= input_line_pointer
;
1975 while (!is_end_of_line
[(unsigned char) *input_line_pointer
])
1976 ++input_line_pointer
;
1977 c
= *input_line_pointer
;
1978 *input_line_pointer
= '\0';
1979 filename
= xstrdup (filename
);
1980 *input_line_pointer
= c
;
1981 demand_empty_rest_of_line ();
1983 /* Insert a partial line with the filename (for the sake of s_include)
1985 The included file will be inserted before the newblock, so that the
1986 newblock is executed after the included file is processed. */
1987 input
= concat ("\"", filename
, "\"\n", newblock
, (char *) NULL
);
1988 input_scrub_insert_line (input
);
1990 tic54x_clear_local_labels (0);
1992 tic54x_set_default_include ();
1998 tic54x_message (int type
)
2004 ILLEGAL_WITHIN_STRUCT ();
2006 if (*input_line_pointer
== '"')
2007 msg
= demand_copy_C_string (&len
);
2010 msg
= input_line_pointer
;
2011 while (!is_end_of_line
[(unsigned char) *input_line_pointer
])
2012 ++input_line_pointer
;
2013 c
= *input_line_pointer
;
2014 *input_line_pointer
= 0;
2015 msg
= xstrdup (msg
);
2016 *input_line_pointer
= c
;
2022 as_tsktsk ("%s", msg
);
2025 as_warn ("%s", msg
);
2032 demand_empty_rest_of_line ();
2036 Define a special symbol that refers to the loadtime address rather than the
2037 runtime address within the current section.
2039 This symbol gets a special storage class so that when it is resolved, it is
2040 resolved relative to the load address (lma) of the section rather than the
2041 run address (vma). */
2044 tic54x_label (int ignored ATTRIBUTE_UNUSED
)
2050 ILLEGAL_WITHIN_STRUCT ();
2052 c
= get_symbol_name (&name
);
2053 symbolP
= colon (name
);
2054 S_SET_STORAGE_CLASS (symbolP
, C_STATLAB
);
2056 (void) restore_line_pointer (c
);
2057 demand_empty_rest_of_line ();
2061 Install all memory-mapped register names into the symbol table as
2062 absolute local symbols. */
2065 tic54x_register_mmregs (int ignored ATTRIBUTE_UNUSED
)
2067 const tic54x_symbol
*sym
;
2069 ILLEGAL_WITHIN_STRUCT ();
2071 for (sym
= tic54x_mmregs
; sym
->name
; sym
++)
2073 symbolS
*symbolP
= symbol_new (sym
->name
, absolute_section
,
2074 &zero_address_frag
, sym
->value
);
2075 SF_SET_LOCAL (symbolP
);
2076 symbol_table_insert (symbolP
);
2081 Count defaults to 1024. */
2084 tic54x_loop (int count
)
2086 ILLEGAL_WITHIN_STRUCT ();
2089 if (!is_end_of_line
[(unsigned char) *input_line_pointer
])
2090 count
= get_absolute_expression ();
2092 do_repeat ((size_t) count
, "LOOP", "ENDLOOP", NULL
);
2095 /* Normally, endloop gets eaten by the preceding loop. */
2098 tic54x_endloop (int ignore ATTRIBUTE_UNUSED
)
2100 as_bad (_("ENDLOOP without corresponding LOOP"));
2101 ignore_rest_of_line ();
2104 /* .break [condition]. */
2107 tic54x_break (int ignore ATTRIBUTE_UNUSED
)
2111 ILLEGAL_WITHIN_STRUCT ();
2114 if (!is_end_of_line
[(unsigned char) *input_line_pointer
])
2115 cond
= get_absolute_expression ();
2118 end_repeat (substitution_line
? 1 : 0);
2122 set_address_mode (int mode
)
2125 if (mode
== far_mode
)
2127 symbolS
*symbolP
= symbol_new ("__allow_far", absolute_section
,
2128 &zero_address_frag
, 1);
2129 SF_SET_LOCAL (symbolP
);
2130 symbol_table_insert (symbolP
);
2134 static int address_mode_needs_set
= 1;
2137 tic54x_address_mode (int mode
)
2139 if (assembly_begun
&& amode
!= (unsigned) mode
)
2141 as_bad (_("Mixing of normal and extended addressing not supported"));
2142 ignore_rest_of_line ();
2145 if (mode
== far_mode
&& cpu
!= VNONE
&& cpu
!= V548
&& cpu
!= V549
)
2147 as_bad (_("Extended addressing not supported on the specified CPU"));
2148 ignore_rest_of_line ();
2152 set_address_mode (mode
);
2153 demand_empty_rest_of_line ();
2156 /* .sblock "section"|section [,...,"section"|section]
2157 Designate initialized sections for blocking. */
2160 tic54x_sblock (int ignore ATTRIBUTE_UNUSED
)
2164 ILLEGAL_WITHIN_STRUCT ();
2171 if (*input_line_pointer
== '"')
2175 name
= demand_copy_C_string (&len
);
2181 c
= get_symbol_name (§ion_name
);
2182 name
= xstrdup (section_name
);
2183 (void) restore_line_pointer (c
);
2186 seg
= bfd_get_section_by_name (stdoutput
, name
);
2189 as_bad (_("Unrecognized section '%s'"), name
);
2190 ignore_rest_of_line ();
2193 else if (!tic54x_initialized_section (seg
))
2195 as_bad (_(".sblock may be used for initialized sections only"));
2196 ignore_rest_of_line ();
2199 seg
->flags
|= SEC_TIC54X_BLOCK
;
2201 c
= *input_line_pointer
;
2202 if (!is_end_of_line
[(unsigned char) c
])
2203 ++input_line_pointer
;
2206 demand_empty_rest_of_line ();
2209 /* symbol .set value
2212 value must be defined externals; no forward-referencing allowed
2213 symbols assigned with .set/.equ may not be redefined. */
2216 tic54x_set (int ignore ATTRIBUTE_UNUSED
)
2221 ILLEGAL_WITHIN_STRUCT ();
2225 as_bad (_("Symbol missing for .set/.equ"));
2226 ignore_rest_of_line ();
2229 name
= xstrdup (S_GET_NAME (line_label
));
2231 if ((symbolP
= symbol_find (name
)) == NULL
2232 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
2234 symbolP
= symbol_new (name
, absolute_section
, &zero_address_frag
, 0);
2235 S_SET_STORAGE_CLASS (symbolP
, C_STAT
);
2238 S_SET_DATA_TYPE (symbolP
, T_INT
);
2239 S_SET_SEGMENT (symbolP
, absolute_section
);
2240 symbol_table_insert (symbolP
);
2241 pseudo_set (symbolP
);
2242 demand_empty_rest_of_line ();
2247 List false conditional blocks. */
2250 tic54x_fclist (int show
)
2253 listing
&= ~LISTING_NOCOND
;
2255 listing
|= LISTING_NOCOND
;
2256 demand_empty_rest_of_line ();
2260 tic54x_sslist (int show
)
2262 ILLEGAL_WITHIN_STRUCT ();
2264 listing_sslist
= show
;
2267 /* .var SYM[,...,SYMN]
2268 Define a substitution string to be local to a macro. */
2271 tic54x_var (int ignore ATTRIBUTE_UNUSED
)
2276 ILLEGAL_WITHIN_STRUCT ();
2278 if (macro_level
== 0)
2280 as_bad (_(".var may only be used within a macro definition"));
2281 ignore_rest_of_line ();
2286 if (!ISALPHA (*input_line_pointer
))
2288 as_bad (_("Substitution symbols must begin with a letter"));
2289 ignore_rest_of_line ();
2292 c
= get_symbol_name (&name
);
2293 name
= xstrdup (name
);
2294 c
= restore_line_pointer (c
);
2296 /* .var symbols start out with a null string. */
2297 subsym_ent_t
*ent
= xmalloc (sizeof (*ent
));
2298 ent
->u
.s
= (char *) "";
2303 str_hash_insert (subsym_hash
[macro_level
], name
, ent
, 0);
2306 ++input_line_pointer
;
2307 if (is_end_of_line
[(unsigned char) *input_line_pointer
])
2308 c
= *input_line_pointer
;
2313 demand_empty_rest_of_line ();
2316 /* .mlib <macro library filename>
2318 Macro libraries are archived (standard AR-format) text macro definitions
2319 Expand the file and include it.
2321 FIXME need to try the source file directory as well. */
2324 tic54x_mlib (int ignore ATTRIBUTE_UNUSED
)
2331 ILLEGAL_WITHIN_STRUCT ();
2333 /* Parse the filename. */
2334 if (*input_line_pointer
== '"')
2336 if ((filename
= demand_copy_C_string (&len
)) == NULL
)
2343 while (!is_end_of_line
[(unsigned char) *input_line_pointer
]
2344 && !ISSPACE (*input_line_pointer
))
2346 obstack_1grow (¬es
, *input_line_pointer
);
2347 ++input_line_pointer
;
2350 obstack_1grow (¬es
, '\0');
2351 filename
= obstack_finish (¬es
);
2353 demand_empty_rest_of_line ();
2355 tic54x_set_default_include ();
2356 path
= XNEWVEC (char, (unsigned long) len
+ include_dir_maxlen
+ 5);
2358 for (i
= 0; i
< include_dir_count
; i
++)
2362 strcpy (path
, include_dirs
[i
]);
2364 strcat (path
, filename
);
2365 if ((try = fopen (path
, "r")) != NULL
)
2372 if (i
>= include_dir_count
)
2378 /* FIXME: if path is found, malloc'd storage is not freed. Of course, this
2379 happens all over the place, and since the assembler doesn't usually keep
2380 running for a very long time, it really doesn't matter. */
2381 register_dependency (path
);
2383 /* Expand all archive entries to temporary files and include them. */
2384 abfd
= bfd_openr (path
, NULL
);
2387 as_bad (_("can't open macro library file '%s' for reading: %s"),
2388 path
, bfd_errmsg (bfd_get_error ()));
2389 ignore_rest_of_line ();
2392 if (!bfd_check_format (abfd
, bfd_archive
))
2394 as_bad (_("File '%s' not in macro archive format"), path
);
2395 ignore_rest_of_line ();
2399 /* Open each BFD as binary (it should be straight ASCII text). */
2400 for (mbfd
= bfd_openr_next_archived_file (abfd
, NULL
);
2401 mbfd
!= NULL
; mbfd
= bfd_openr_next_archived_file (abfd
, mbfd
))
2403 /* Get a size at least as big as the archive member. */
2404 bfd_size_type size
= bfd_get_size (mbfd
);
2405 char *buf
= XNEWVEC (char, size
);
2406 char *fname
= tmpnam (NULL
);
2409 /* We're not sure how big it is, but it will be smaller than "size". */
2410 size
= bfd_bread (buf
, size
, mbfd
);
2412 /* Write to a temporary file, then use s_include to include it
2414 ftmp
= fopen (fname
, "w+b");
2415 fwrite ((void *) buf
, size
, 1, ftmp
);
2416 if (size
== 0 || buf
[size
- 1] != '\n')
2417 fwrite ("\n", 1, 1, ftmp
);
2420 input_scrub_insert_file (fname
);
2425 const pseudo_typeS md_pseudo_table
[] =
2427 { "algebraic", s_ignore
, 0 },
2428 { "align" , tic54x_align_words
, 128 },
2429 { "ascii" , tic54x_stringer
, 'p' },
2430 { "asciz" , tic54x_stringer
, 'P' },
2431 { "even" , tic54x_align_words
, 2 },
2432 { "asg" , tic54x_asg
, 0 },
2433 { "eval" , tic54x_eval
, 0 },
2434 { "bss" , tic54x_bss
, 0 },
2435 { "byte" , tic54x_cons
, 'b' },
2436 { "ubyte" , tic54x_cons
, 'B' },
2437 { "char" , tic54x_cons
, 'c' },
2438 { "uchar" , tic54x_cons
, 'C' },
2439 { "clink" , tic54x_clink
, 0 },
2440 { "c_mode" , tic54x_address_mode
, c_mode
},
2441 { "copy" , tic54x_include
, 'c' },
2442 { "include" , tic54x_include
, 'i' },
2443 { "data" , tic54x_sect
, 'd' },
2444 { "double" , tic54x_float_cons
, 'd' },
2445 { "ldouble" , tic54x_float_cons
, 'l' },
2446 { "drlist" , s_ignore
, 0 },
2447 { "drnolist" , s_ignore
, 0 },
2448 { "emsg" , tic54x_message
, 'e' },
2449 { "mmsg" , tic54x_message
, 'm' },
2450 { "wmsg" , tic54x_message
, 'w' },
2451 { "far_mode" , tic54x_address_mode
, far_mode
},
2452 { "fclist" , tic54x_fclist
, 1 },
2453 { "fcnolist" , tic54x_fclist
, 0 },
2454 { "field" , tic54x_field
, -1 },
2455 { "float" , tic54x_float_cons
, 'f' },
2456 { "xfloat" , tic54x_float_cons
, 'x' },
2457 { "global" , tic54x_global
, 'g' },
2458 { "def" , tic54x_global
, 'd' },
2459 { "ref" , tic54x_global
, 'r' },
2460 { "half" , tic54x_cons
, 'h' },
2461 { "uhalf" , tic54x_cons
, 'H' },
2462 { "short" , tic54x_cons
, 's' },
2463 { "ushort" , tic54x_cons
, 'S' },
2464 { "if" , s_if
, (int) O_ne
},
2465 { "elseif" , s_elseif
, (int) O_ne
},
2466 { "else" , s_else
, 0 },
2467 { "endif" , s_endif
, 0 },
2468 { "int" , tic54x_cons
, 'i' },
2469 { "uint" , tic54x_cons
, 'I' },
2470 { "word" , tic54x_cons
, 'w' },
2471 { "uword" , tic54x_cons
, 'W' },
2472 { "label" , tic54x_label
, 0 }, /* Loadtime
2474 { "length" , s_ignore
, 0 },
2475 { "width" , s_ignore
, 0 },
2476 { "long" , tic54x_cons
, 'l' },
2477 { "ulong" , tic54x_cons
, 'L' },
2478 { "xlong" , tic54x_cons
, 'x' },
2479 { "loop" , tic54x_loop
, 1024 },
2480 { "break" , tic54x_break
, 0 },
2481 { "endloop" , tic54x_endloop
, 0 },
2482 { "mlib" , tic54x_mlib
, 0 },
2483 { "mlist" , s_ignore
, 0 },
2484 { "mnolist" , s_ignore
, 0 },
2485 { "mmregs" , tic54x_register_mmregs
, 0 },
2486 { "newblock" , tic54x_clear_local_labels
, 0 },
2487 { "option" , s_ignore
, 0 },
2488 { "p2align" , tic54x_p2align
, 0 },
2489 { "sblock" , tic54x_sblock
, 0 },
2490 { "sect" , tic54x_sect
, '*' },
2491 { "set" , tic54x_set
, 0 },
2492 { "equ" , tic54x_set
, 0 },
2493 { "space" , tic54x_space
, 0 },
2494 { "bes" , tic54x_space
, 1 },
2495 { "sslist" , tic54x_sslist
, 1 },
2496 { "ssnolist" , tic54x_sslist
, 0 },
2497 { "string" , tic54x_stringer
, 's' },
2498 { "pstring" , tic54x_stringer
, 'p' },
2499 { "struct" , tic54x_struct
, 0 },
2500 { "tag" , tic54x_tag
, 0 },
2501 { "endstruct", tic54x_endstruct
, 0 },
2502 { "tab" , s_ignore
, 0 },
2503 { "text" , tic54x_sect
, 't' },
2504 { "union" , tic54x_struct
, 1 },
2505 { "endunion" , tic54x_endstruct
, 1 },
2506 { "usect" , tic54x_usect
, 0 },
2507 { "var" , tic54x_var
, 0 },
2508 { "version" , tic54x_version
, 0 },
2513 md_parse_option (int c
, const char *arg
)
2519 case OPTION_COFF_VERSION
:
2521 int version
= atoi (arg
);
2523 if (version
!= 0 && version
!= 1 && version
!= 2)
2524 as_fatal (_("Bad COFF version '%s'"), arg
);
2525 /* FIXME -- not yet implemented. */
2528 case OPTION_CPU_VERSION
:
2530 cpu
= lookup_version (arg
);
2533 as_fatal (_("Bad CPU version '%s'"), arg
);
2536 case OPTION_ADDRESS_MODE
:
2538 address_mode_needs_set
= 1;
2540 case OPTION_STDERR_TO_FILE
:
2542 const char *filename
= arg
;
2543 FILE *fp
= fopen (filename
, "w+");
2546 as_fatal (_("Can't redirect stderr to the file '%s'"), filename
);
2548 if ((fp
= freopen (filename
, "w+", stderr
)) == NULL
)
2549 as_fatal (_("Can't redirect stderr to the file '%s'"), filename
);
2557 /* Create a "local" substitution string hash table for a new macro level
2558 Some docs imply that macros have to use .newblock in order to be able
2559 to re-use a local label. We effectively do an automatic .newblock by
2560 deleting the local label hash between macro invocations. */
2563 tic54x_macro_start (void)
2565 if (++macro_level
>= MAX_SUBSYM_HASH
)
2568 as_fatal (_("Macro nesting is too deep"));
2571 subsym_hash
[macro_level
] = subsym_htab_create ();
2572 local_label_hash
[macro_level
] = local_label_htab_create ();
2576 tic54x_macro_info (const macro_entry
*macro
)
2578 const formal_entry
*entry
;
2580 /* Put the formal args into the substitution symbol table. */
2581 for (entry
= macro
->formals
; entry
; entry
= entry
->next
)
2583 char *name
= xstrndup (entry
->name
.ptr
, entry
->name
.len
);
2584 subsym_ent_t
*ent
= xmalloc (sizeof (*ent
));
2586 ent
->u
.s
= xstrndup (entry
->actual
.ptr
, entry
->actual
.len
);
2591 str_hash_insert (subsym_hash
[macro_level
], name
, ent
, 0);
2595 /* Get rid of this macro's .var's, arguments, and local labels. */
2598 tic54x_macro_end (void)
2600 htab_delete (subsym_hash
[macro_level
]);
2601 subsym_hash
[macro_level
] = NULL
;
2602 htab_delete (local_label_hash
[macro_level
]);
2603 local_label_hash
[macro_level
] = NULL
;
2608 subsym_symlen (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2613 /* Compare symbol A to string B. */
2616 subsym_symcmp (char *a
, char *b
)
2618 return strcmp (a
, b
);
2621 /* Return the index of the first occurrence of B in A, or zero if none
2622 assumes b is an integer char value as a string. Index is one-based. */
2625 subsym_firstch (char *a
, char *b
)
2628 char *tmp
= strchr (a
, val
);
2630 return tmp
? tmp
- a
+ 1 : 0;
2633 /* Similar to firstch, but returns index of last occurrence of B in A. */
2636 subsym_lastch (char *a
, char *b
)
2639 char *tmp
= strrchr (a
, val
);
2641 return tmp
? tmp
- a
+ 1 : 0;
2644 /* Returns 1 if string A is defined in the symbol table (NOT the substitution
2648 subsym_isdefed (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2650 symbolS
*symbolP
= symbol_find (a
);
2652 return symbolP
!= NULL
;
2655 /* Assign first member of comma-separated list B (e.g. "1,2,3") to the symbol
2656 A, or zero if B is a null string. Both arguments *must* be substitution
2657 symbols, unsubstituted. */
2660 subsym_ismember (char *sym
, char *list
)
2663 subsym_ent_t
*listv
;
2668 listv
= subsym_lookup (list
, macro_level
);
2669 if (!listv
|| listv
->isproc
)
2671 as_bad (_("Undefined substitution symbol '%s'"), list
);
2672 ignore_rest_of_line ();
2676 ptr
= elem
= notes_strdup (listv
->u
.s
);
2677 while (*ptr
&& *ptr
!= ',')
2681 subsym_create_or_replace (sym
, elem
);
2683 /* Reassign the list. */
2684 subsym_create_or_replace (list
, ptr
);
2686 /* Assume this value, docs aren't clear. */
2690 /* Return zero if not a constant; otherwise:
2698 subsym_iscons (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2702 parse_expression (a
, &expn
);
2704 if (expn
.X_op
== O_constant
)
2706 int len
= strlen (a
);
2708 switch (TOUPPER (a
[len
- 1]))
2721 /* No suffix; either octal, hex, or decimal. */
2722 if (*a
== '0' && len
> 1)
2724 if (TOUPPER (a
[1]) == 'X')
2734 /* Return 1 if A is a valid symbol name. Expects string input. */
2737 subsym_isname (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2739 if (!is_name_beginner (*a
))
2743 if (!is_part_of_name (*a
))
2750 /* Return whether the string is a register; accepts ar0-7, unless .mmregs has
2751 been seen; if so, recognize any memory-mapped register.
2752 Note this does not recognize "A" or "B" accumulators. */
2755 subsym_isreg (char *a
, char *ignore ATTRIBUTE_UNUSED
)
2757 if (str_hash_find (reg_hash
, a
))
2759 if (str_hash_find (mmreg_hash
, a
))
2764 /* Return the structure size, given the stag. */
2767 subsym_structsz (char *name
, char *ignore ATTRIBUTE_UNUSED
)
2769 struct stag
*stag
= (struct stag
*) str_hash_find (stag_hash
, name
);
2777 /* If anybody actually uses this, they can fix it :)
2778 FIXME I'm not sure what the "reference point" of a structure is. It might
2779 be either the initial offset given .struct, or it may be the offset of the
2780 structure within another structure, or it might be something else
2781 altogether. since the TI assembler doesn't seem to ever do anything but
2782 return zero, we punt and return zero. */
2785 subsym_structacc (char *stag_name ATTRIBUTE_UNUSED
,
2786 char *ignore ATTRIBUTE_UNUSED
)
2792 math_ceil (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2794 return (float) ceil (arg1
);
2798 math_cvi (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2804 math_floor (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2806 return (float) floor (arg1
);
2810 math_fmod (float arg1
, float arg2
)
2812 return (int) arg1
% (int) arg2
;
2816 math_int (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2818 return arg1
== (float) (int) arg1
;
2822 math_round (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2824 return arg1
> 0 ? (int) (arg1
+ 0.5) : (int) (arg1
- 0.5);
2828 math_sgn (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2830 return arg1
< 0.0f
? -1 : arg1
!= 0.0f
? 1 : 0;
2834 math_trunc (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2840 math_acos (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2842 return (float) acos (arg1
);
2846 math_asin (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2848 return (float) asin (arg1
);
2852 math_atan (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2854 return (float) atan (arg1
);
2858 math_atan2 (float arg1
, float arg2
)
2860 return (float) atan2 (arg1
, arg2
);
2864 math_cosh (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2866 return (float) cosh (arg1
);
2870 math_cos (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2872 return (float) cos (arg1
);
2876 math_cvf (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2878 return (float) arg1
;
2882 math_exp (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2884 return (float) exp (arg1
);
2888 math_fabs (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2890 return (float) fabs (arg1
);
2893 /* expr1 * 2^expr2. */
2896 math_ldexp (float arg1
, float arg2
)
2898 return arg1
* (float) pow (2.0, arg2
);
2902 math_log10 (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2904 return (float) log10 (arg1
);
2908 math_log (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2910 return (float) log (arg1
);
2914 math_max (float arg1
, float arg2
)
2916 return (arg1
> arg2
) ? arg1
: arg2
;
2920 math_min (float arg1
, float arg2
)
2922 return (arg1
< arg2
) ? arg1
: arg2
;
2926 math_pow (float arg1
, float arg2
)
2928 return (float) pow (arg1
, arg2
);
2932 math_sin (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2934 return (float) sin (arg1
);
2938 math_sinh (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2940 return (float) sinh (arg1
);
2944 math_sqrt (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2946 return (float) sqrt (arg1
);
2950 math_tan (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2952 return (float) tan (arg1
);
2956 math_tanh (float arg1
, float ignore ATTRIBUTE_UNUSED
)
2958 return (float) tanh (arg1
);
2961 /* Built-in substitution symbol functions and math functions. */
2962 static const subsym_proc_entry subsym_procs
[] =
2964 /* Assembler built-in string substitution functions. */
2965 { "$symlen", { .s
= subsym_symlen
}, 1, 0 },
2966 { "$symcmp", { .s
= subsym_symcmp
}, 2, 0 },
2967 { "$firstch", { .s
= subsym_firstch
}, 2, 0 },
2968 { "$lastch", { .s
= subsym_lastch
}, 2, 0 },
2969 { "$isdefed", { .s
= subsym_isdefed
}, 1, 0 },
2970 { "$ismember", { .s
= subsym_ismember
}, 2, 0 },
2971 { "$iscons", { .s
= subsym_iscons
}, 1, 0 },
2972 { "$isname", { .s
= subsym_isname
}, 1, 0 },
2973 { "$isreg", { .s
= subsym_isreg
}, 1, 0 },
2974 { "$structsz", { .s
= subsym_structsz
}, 1, 0 },
2975 { "$structacc", { .s
= subsym_structacc
}, 1, 0 },
2977 /* Integer-returning built-in math functions. */
2978 { "$cvi", { .i
= math_cvi
}, 1, 2 },
2979 { "$int", { .i
= math_int
}, 1, 2 },
2980 { "$sgn", { .i
= math_sgn
}, 1, 2 },
2982 /* Float-returning built-in math functions. */
2983 { "$acos", { .f
= math_acos
}, 1, 1 },
2984 { "$asin", { .f
= math_asin
}, 1, 1 },
2985 { "$atan", { .f
= math_atan
}, 1, 1 },
2986 { "$atan2", { .f
= math_atan2
}, 2, 1 },
2987 { "$ceil", { .f
= math_ceil
}, 1, 1 },
2988 { "$cosh", { .f
= math_cosh
}, 1, 1 },
2989 { "$cos", { .f
= math_cos
}, 1, 1 },
2990 { "$cvf", { .f
= math_cvf
}, 1, 1 },
2991 { "$exp", { .f
= math_exp
}, 1, 1 },
2992 { "$fabs", { .f
= math_fabs
}, 1, 1 },
2993 { "$floor", { .f
= math_floor
}, 1, 1 },
2994 { "$fmod", { .f
= math_fmod
}, 2, 1 },
2995 { "$ldexp", { .f
= math_ldexp
}, 2, 1 },
2996 { "$log10", { .f
= math_log10
}, 1, 1 },
2997 { "$log", { .f
= math_log
}, 1, 1 },
2998 { "$max", { .f
= math_max
}, 2, 1 },
2999 { "$min", { .f
= math_min
}, 2, 1 },
3000 { "$pow", { .f
= math_pow
}, 2, 1 },
3001 { "$round", { .f
= math_round
}, 1, 1 },
3002 { "$sin", { .f
= math_sin
}, 1, 1 },
3003 { "$sinh", { .f
= math_sinh
}, 1, 1 },
3004 { "$sqrt", { .f
= math_sqrt
}, 1, 1 },
3005 { "$tan", { .f
= math_tan
}, 1, 1 },
3006 { "$tanh", { .f
= math_tanh
}, 1, 1 },
3007 { "$trunc", { .f
= math_trunc
}, 1, 1 },
3008 { NULL
, { NULL
}, 0, 0 },
3015 const tic54x_symbol
*sym
;
3016 const subsym_proc_entry
*subsym_proc
;
3017 const char **symname
;
3018 char *TIC54X_DIR
= getenv ("TIC54X_DIR");
3019 char *A_DIR
= TIC54X_DIR
? TIC54X_DIR
: getenv ("A_DIR");
3023 /* Look for A_DIR and add it to the include list. */
3026 char *tmp
= xstrdup (A_DIR
);
3030 char *next
= strchr (tmp
, ';');
3034 add_include_dir (tmp
);
3037 while (tmp
!= NULL
);
3040 op_hash
= str_htab_create ();
3041 for (tm
= (insn_template
*) tic54x_optab
; tm
->name
; tm
++)
3042 str_hash_insert (op_hash
, tm
->name
, tm
, 0);
3044 parop_hash
= str_htab_create ();
3045 for (tm
= (insn_template
*) tic54x_paroptab
; tm
->name
; tm
++)
3046 str_hash_insert (parop_hash
, tm
->name
, tm
, 0);
3048 reg_hash
= str_htab_create ();
3049 for (sym
= tic54x_regs
; sym
->name
; sym
++)
3051 /* Add basic registers to the symbol table. */
3052 symbolS
*symbolP
= symbol_new (sym
->name
, absolute_section
,
3053 &zero_address_frag
, sym
->value
);
3054 SF_SET_LOCAL (symbolP
);
3055 symbol_table_insert (symbolP
);
3056 str_hash_insert (reg_hash
, sym
->name
, sym
, 0);
3058 for (sym
= tic54x_mmregs
; sym
->name
; sym
++)
3059 str_hash_insert (reg_hash
, sym
->name
, sym
, 0);
3060 mmreg_hash
= str_htab_create ();
3061 for (sym
= tic54x_mmregs
; sym
->name
; sym
++)
3062 str_hash_insert (mmreg_hash
, sym
->name
, sym
, 0);
3064 cc_hash
= str_htab_create ();
3065 for (sym
= tic54x_condition_codes
; sym
->name
; sym
++)
3066 str_hash_insert (cc_hash
, sym
->name
, sym
, 0);
3068 cc2_hash
= str_htab_create ();
3069 for (sym
= tic54x_cc2_codes
; sym
->name
; sym
++)
3070 str_hash_insert (cc2_hash
, sym
->name
, sym
, 0);
3072 cc3_hash
= str_htab_create ();
3073 for (sym
= tic54x_cc3_codes
; sym
->name
; sym
++)
3074 str_hash_insert (cc3_hash
, sym
->name
, sym
, 0);
3076 sbit_hash
= str_htab_create ();
3077 for (sym
= tic54x_status_bits
; sym
->name
; sym
++)
3078 str_hash_insert (sbit_hash
, sym
->name
, sym
, 0);
3080 misc_symbol_hash
= str_htab_create ();
3081 for (symname
= tic54x_misc_symbols
; *symname
; symname
++)
3082 str_hash_insert (misc_symbol_hash
, *symname
, *symname
, 0);
3084 /* Only the base substitution table and local label table are initialized;
3085 the others (for local macro substitution) get instantiated as needed. */
3086 local_label_hash
[0] = local_label_htab_create ();
3087 subsym_hash
[0] = subsym_htab_create ();
3088 for (subsym_proc
= subsym_procs
; subsym_proc
->name
; subsym_proc
++)
3090 subsym_ent_t
*ent
= xmalloc (sizeof (*ent
));
3091 ent
->u
.p
= subsym_proc
;
3095 ent
->ismath
= subsym_proc
->type
!= 0;
3096 str_hash_insert (subsym_hash
[0], subsym_proc
->name
, ent
, 0);
3098 subsym_recurse_hash
= str_htab_create ();
3099 stag_hash
= str_htab_create ();
3103 tic54x_md_end (void)
3105 htab_delete (stag_hash
);
3106 htab_delete (subsym_recurse_hash
);
3107 while (macro_level
!= -1)
3108 tic54x_macro_end ();
3110 htab_delete (misc_symbol_hash
);
3111 htab_delete (sbit_hash
);
3112 htab_delete (cc3_hash
);
3113 htab_delete (cc2_hash
);
3114 htab_delete (cc_hash
);
3115 htab_delete (mmreg_hash
);
3116 htab_delete (reg_hash
);
3117 htab_delete (parop_hash
);
3118 htab_delete (op_hash
);
3122 is_accumulator (struct opstruct
*operand
)
3124 return strcasecmp (operand
->buf
, "a") == 0
3125 || strcasecmp (operand
->buf
, "b") == 0;
3128 /* Return the number of operands found, or -1 on error, copying the
3129 operands into the given array and the accompanying expressions into
3133 get_operands (struct opstruct operands
[], char *line
)
3137 int expecting_operand
= 0;
3140 while (numexp
< MAX_OPERANDS
&& !is_end_of_line
[(unsigned char) *lptr
])
3142 int paren_not_balanced
= 0;
3143 char *op_start
, *op_end
;
3145 while (*lptr
&& ISSPACE (*lptr
))
3148 while (paren_not_balanced
|| *lptr
!= ',')
3152 if (paren_not_balanced
)
3154 as_bad (_("Unbalanced parenthesis in operand %d"), numexp
);
3161 ++paren_not_balanced
;
3162 else if (*lptr
== ')')
3163 --paren_not_balanced
;
3167 if (op_end
!= op_start
)
3169 int len
= op_end
- op_start
;
3171 strncpy (operands
[numexp
].buf
, op_start
, len
);
3172 operands
[numexp
].buf
[len
] = 0;
3173 /* Trim trailing spaces; while the preprocessor gets rid of most,
3174 there are weird usage patterns that can introduce them
3175 (i.e. using strings for macro args). */
3176 while (len
> 0 && ISSPACE (operands
[numexp
].buf
[len
- 1]))
3177 operands
[numexp
].buf
[--len
] = 0;
3183 if (expecting_operand
|| *lptr
== ',')
3185 as_bad (_("Expecting operand after ','"));
3191 if (*++lptr
== '\0')
3193 as_bad (_("Expecting operand after ','"));
3196 expecting_operand
= 1;
3200 while (*lptr
&& ISSPACE (*lptr
++))
3202 if (!is_end_of_line
[(unsigned char) *lptr
])
3204 as_bad (_("Extra junk on line"));
3208 /* OK, now parse them into expressions. */
3209 for (i
= 0; i
< numexp
; i
++)
3211 memset (&operands
[i
].exp
, 0, sizeof (operands
[i
].exp
));
3212 if (operands
[i
].buf
[0] == '#')
3215 parse_expression (operands
[i
].buf
+ 1, &operands
[i
].exp
);
3217 else if (operands
[i
].buf
[0] == '@')
3219 /* Direct notation. */
3220 parse_expression (operands
[i
].buf
+ 1, &operands
[i
].exp
);
3222 else if (operands
[i
].buf
[0] == '*')
3225 char *paren
= strchr (operands
[i
].buf
, '(');
3227 /* Allow immediate syntax in the inner expression. */
3228 if (paren
&& paren
[1] == '#')
3231 /* Pull out the lk expression or SP offset, if present. */
3234 int len
= strlen (paren
);
3235 char *end
= paren
+ len
;
3238 while (end
[-1] != ')')
3241 as_bad (_("Badly formed address expression"));
3246 parse_expression (paren
, &operands
[i
].exp
);
3250 operands
[i
].exp
.X_op
= O_absent
;
3253 parse_expression (operands
[i
].buf
, &operands
[i
].exp
);
3259 /* Predicates for different operand types. */
3262 is_immediate (struct opstruct
*operand
)
3264 return *operand
->buf
== '#';
3267 /* This is distinguished from immediate because some numbers must be constants
3268 and must *not* have the '#' prefix. */
3271 is_absolute (struct opstruct
*operand
)
3273 return operand
->exp
.X_op
== O_constant
&& !is_immediate (operand
);
3276 /* Is this an indirect operand? */
3279 is_indirect (struct opstruct
*operand
)
3281 return operand
->buf
[0] == '*';
3284 /* Is this a valid dual-memory operand? */
3287 is_dual (struct opstruct
*operand
)
3289 if (is_indirect (operand
) && strncasecmp (operand
->buf
, "*ar", 3) == 0)
3291 char *tmp
= operand
->buf
+ 3;
3296 /* Only allow *ARx, *ARx-, *ARx+, or *ARx+0%. */
3297 valid_mod
= *tmp
== '\0' ||
3298 strcasecmp (tmp
, "-") == 0 ||
3299 strcasecmp (tmp
, "+") == 0 ||
3300 strcasecmp (tmp
, "+0%") == 0;
3301 return arf
>= 2 && arf
<= 5 && valid_mod
;
3307 is_mmreg (struct opstruct
*operand
)
3309 return (is_absolute (operand
)
3310 || is_immediate (operand
)
3311 || str_hash_find (mmreg_hash
, operand
->buf
) != 0);
3315 is_type (struct opstruct
*operand
, enum optype type
)
3320 return operand
->buf
[0] == 0;
3323 return is_dual (operand
);
3325 return is_indirect (operand
);
3327 /* This one *must* be immediate. */
3328 return is_immediate (operand
);
3337 /* Address may be a numeric, indirect, or an expression. */
3338 return !is_immediate (operand
);
3341 return is_mmreg (operand
);
3346 return is_accumulator (operand
);
3348 return is_accumulator (operand
) && TOUPPER (operand
->buf
[0]) == 'B';
3350 return is_accumulator (operand
) && TOUPPER (operand
->buf
[0]) == 'A';
3352 return strncasecmp ("ar", operand
->buf
, 2) == 0
3353 && ISDIGIT (operand
->buf
[2]);
3355 return str_hash_find (sbit_hash
, operand
->buf
) != 0 || is_absolute (operand
);
3357 return str_hash_find (cc_hash
, operand
->buf
) != 0;
3359 return str_hash_find (cc2_hash
, operand
->buf
) != 0;
3361 return str_hash_find (cc3_hash
, operand
->buf
) != 0
3362 || is_immediate (operand
) || is_absolute (operand
);
3364 return (is_immediate (operand
) || is_absolute (operand
))
3365 && operand
->exp
.X_add_number
== 16;
3367 /* Allow st0 or st1 instead of a numeric. */
3368 return is_absolute (operand
) || is_immediate (operand
) ||
3369 strcasecmp ("st0", operand
->buf
) == 0 ||
3370 strcasecmp ("st1", operand
->buf
) == 0;
3373 return is_absolute (operand
) || is_immediate (operand
);
3375 return (is_immediate (operand
) || is_absolute (operand
))
3376 && operand
->exp
.X_add_number
>= 0 && operand
->exp
.X_add_number
< 16;
3378 /* Let this one catch out-of-range values. */
3379 return (is_immediate (operand
) || is_absolute (operand
))
3380 && operand
->exp
.X_add_number
!= 16;
3384 return is_absolute (operand
) || is_immediate (operand
);
3386 return is_immediate (operand
)
3387 && operand
->exp
.X_op
== O_constant
3388 && operand
->exp
.X_add_number
>= 0
3389 && operand
->exp
.X_add_number
< 256;
3392 /* Allow anything; assumes opcodes are ordered with Smem operands
3398 /* Just make sure it's an integer; check range later. */
3399 return is_immediate (operand
);
3401 return strcasecmp ("t", operand
->buf
) == 0 ||
3402 strcasecmp ("treg", operand
->buf
) == 0;
3404 return strcasecmp ("ts", operand
->buf
) == 0;
3406 return strcasecmp ("asm", operand
->buf
) == 0;
3408 return strcasecmp ("trn", operand
->buf
) == 0;
3410 return strcasecmp ("dp", operand
->buf
) == 0;
3412 return strcasecmp ("arp", operand
->buf
) == 0;
3419 operands_match (tic54x_insn
*insn
,
3420 struct opstruct
*operands
,
3422 const enum optype
*refoptype
,
3426 int op
= 0, refop
= 0;
3428 if (opcount
== 0 && minops
== 0)
3431 while (op
<= maxops
&& refop
<= maxops
)
3433 while (!is_type (&operands
[op
], OPTYPE (refoptype
[refop
])))
3435 /* Skip an optional template operand if it doesn't agree
3436 with the current operand. */
3437 if (refoptype
[refop
] & OPT
)
3448 /* Save the actual operand type for later use. */
3449 operands
[op
].type
= OPTYPE (refoptype
[refop
]);
3452 /* Have we matched them all yet? */
3457 /* If a later operand is *not* optional, no match. */
3458 if ((refoptype
[refop
] & OPT
) == 0)
3460 /* Flag any implicit default OP_DST operands so we know to add
3461 them explicitly when encoding the operand later. */
3462 if (OPTYPE (refoptype
[refop
]) == OP_DST
)
3463 insn
->using_default_dst
= 1;
3475 /* 16-bit direct memory address
3476 Explicit dmad operands are always in last word of insn (usually second
3477 word, but bumped to third if lk addressing is used)
3479 We allow *(dmad) notation because the TI assembler allows it.
3482 0 for 16-bit addresses
3483 1 for full 23-bit addresses
3484 2 for the upper 7 bits of a 23-bit address (LDX). */
3487 encode_dmad (tic54x_insn
*insn
, struct opstruct
*operand
, int xpc_code
)
3489 int op
= 1 + insn
->is_lkaddr
;
3491 /* Only allow *(dmad) expressions; all others are invalid. */
3492 if (is_indirect (operand
) && operand
->buf
[strlen (operand
->buf
) - 1] != ')')
3494 as_bad (_("Invalid dmad syntax '%s'"), operand
->buf
);
3498 insn
->opcode
[op
].addr_expr
= operand
->exp
;
3500 if (insn
->opcode
[op
].addr_expr
.X_op
== O_constant
)
3502 valueT value
= insn
->opcode
[op
].addr_expr
.X_add_number
;
3506 insn
->opcode
[0].word
&= 0xFF80;
3507 insn
->opcode
[0].word
|= (value
>> 16) & 0x7F;
3508 insn
->opcode
[1].word
= value
& 0xFFFF;
3510 else if (xpc_code
== 2)
3511 insn
->opcode
[op
].word
= (value
>> 16) & 0xFFFF;
3513 insn
->opcode
[op
].word
= value
;
3517 /* Do the fixup later; just store the expression. */
3518 insn
->opcode
[op
].word
= 0;
3519 insn
->opcode
[op
].r_nchars
= 2;
3521 if (amode
== c_mode
)
3522 insn
->opcode
[op
].r_type
= BFD_RELOC_TIC54X_16_OF_23
;
3523 else if (xpc_code
== 1)
3525 /* This relocation spans two words, so adjust accordingly. */
3526 insn
->opcode
[0].addr_expr
= operand
->exp
;
3527 insn
->opcode
[0].r_type
= BFD_RELOC_TIC54X_23
;
3528 insn
->opcode
[0].r_nchars
= 4;
3529 insn
->opcode
[0].unresolved
= 1;
3530 /* It's really 2 words, but we want to stop encoding after the
3531 first, since we must encode both words at once. */
3534 else if (xpc_code
== 2)
3535 insn
->opcode
[op
].r_type
= BFD_RELOC_TIC54X_MS7_OF_23
;
3537 insn
->opcode
[op
].r_type
= BFD_RELOC_TIC54X_16_OF_23
;
3539 insn
->opcode
[op
].unresolved
= 1;
3545 /* 7-bit direct address encoding. */
3548 encode_address (tic54x_insn
*insn
, struct opstruct
*operand
)
3550 /* Assumes that dma addresses are *always* in word 0 of the opcode. */
3551 insn
->opcode
[0].addr_expr
= operand
->exp
;
3553 if (operand
->exp
.X_op
== O_constant
)
3554 insn
->opcode
[0].word
|= (operand
->exp
.X_add_number
& 0x7F);
3557 if (operand
->exp
.X_op
== O_register
)
3558 as_bad (_("Use the .mmregs directive to use memory-mapped register names such as '%s'"), operand
->buf
);
3559 /* Do the fixup later; just store the expression. */
3560 insn
->opcode
[0].r_nchars
= 1;
3561 insn
->opcode
[0].r_type
= BFD_RELOC_TIC54X_PARTLS7
;
3562 insn
->opcode
[0].unresolved
= 1;
3569 encode_indirect (tic54x_insn
*insn
, struct opstruct
*operand
)
3574 if (insn
->is_lkaddr
)
3576 /* lk addresses always go in the second insn word. */
3577 mod
= ((TOUPPER (operand
->buf
[1]) == 'A') ? 12 :
3578 (operand
->buf
[1] == '(') ? 15 :
3579 (strchr (operand
->buf
, '%') != NULL
) ? 14 : 13);
3580 arf
= ((mod
== 12) ? operand
->buf
[3] - '0' :
3581 (mod
== 15) ? 0 : operand
->buf
[4] - '0');
3583 insn
->opcode
[1].addr_expr
= operand
->exp
;
3585 if (operand
->exp
.X_op
== O_constant
)
3586 insn
->opcode
[1].word
= operand
->exp
.X_add_number
;
3589 insn
->opcode
[1].word
= 0;
3590 insn
->opcode
[1].r_nchars
= 2;
3591 insn
->opcode
[1].r_type
= BFD_RELOC_TIC54X_16_OF_23
;
3592 insn
->opcode
[1].unresolved
= 1;
3595 else if (strncasecmp (operand
->buf
, "*sp (", 4) == 0)
3597 /* Stack offsets look the same as 7-bit direct addressing. */
3598 return encode_address (insn
, operand
);
3602 arf
= (TOUPPER (operand
->buf
[1]) == 'A' ?
3603 operand
->buf
[3] : operand
->buf
[4]) - '0';
3605 if (operand
->buf
[1] == '+')
3607 mod
= 3; /* *+ARx */
3608 if (insn
->tm
->flags
& FL_SMR
)
3609 as_warn (_("Address mode *+ARx is write-only. "
3610 "Results of reading are undefined."));
3612 else if (operand
->buf
[4] == '\0')
3614 else if (operand
->buf
[5] == '\0')
3615 mod
= (operand
->buf
[4] == '-' ? 1 : 2); /* *ARx+ / *ARx- */
3616 else if (operand
->buf
[6] == '\0')
3618 if (operand
->buf
[5] == '0')
3619 mod
= (operand
->buf
[4] == '-' ? 5 : 6); /* *ARx+0 / *ARx-0 */
3621 mod
= (operand
->buf
[4] == '-' ? 8 : 10);/* *ARx+% / *ARx-% */
3623 else if (TOUPPER (operand
->buf
[6]) == 'B')
3624 mod
= (operand
->buf
[4] == '-' ? 4 : 7); /* ARx+0B / *ARx-0B */
3625 else if (TOUPPER (operand
->buf
[6]) == '%')
3626 mod
= (operand
->buf
[4] == '-' ? 9 : 11); /* ARx+0% / *ARx - 0% */
3629 as_bad (_("Unrecognized indirect address format \"%s\""),
3635 insn
->opcode
[0].word
|= 0x80 | (mod
<< 3) | arf
;
3641 encode_integer (tic54x_insn
*insn
,
3642 struct opstruct
*operand
,
3646 unsigned short mask
)
3648 long parse
, integer
;
3650 insn
->opcode
[which
].addr_expr
= operand
->exp
;
3652 if (operand
->exp
.X_op
== O_constant
)
3654 parse
= operand
->exp
.X_add_number
;
3655 /* Hack -- fixup for 16-bit hex quantities that get converted positive
3656 instead of negative. */
3657 if ((parse
& 0x8000) && min
== -32768 && max
== 32767)
3658 integer
= (short) parse
;
3662 if (integer
>= min
&& integer
<= max
)
3664 insn
->opcode
[which
].word
|= (integer
& mask
);
3667 as_bad (_("Operand '%s' out of range (%d <= x <= %d)"),
3668 operand
->buf
, min
, max
);
3672 if (insn
->opcode
[which
].addr_expr
.X_op
== O_constant
)
3674 insn
->opcode
[which
].word
|=
3675 insn
->opcode
[which
].addr_expr
.X_add_number
& mask
;
3679 /* Do the fixup later; just store the expression. */
3680 bfd_reloc_code_real_type rtype
=
3681 (mask
== 0x1FF ? BFD_RELOC_TIC54X_PARTMS9
:
3682 mask
== 0xFFFF ? BFD_RELOC_TIC54X_16_OF_23
:
3683 mask
== 0x7F ? BFD_RELOC_TIC54X_PARTLS7
: BFD_RELOC_8
);
3684 int size
= (mask
== 0x1FF || mask
== 0xFFFF) ? 2 : 1;
3686 if (rtype
== BFD_RELOC_8
)
3687 as_bad (_("Error in relocation handling"));
3689 insn
->opcode
[which
].r_nchars
= size
;
3690 insn
->opcode
[which
].r_type
= rtype
;
3691 insn
->opcode
[which
].unresolved
= 1;
3701 encode_condition (tic54x_insn
*insn
, struct opstruct
*operand
)
3703 tic54x_symbol
*cc
= (tic54x_symbol
*) str_hash_find (cc_hash
, operand
->buf
);
3706 as_bad (_("Unrecognized condition code \"%s\""), operand
->buf
);
3709 #define CC_GROUP 0x40
3711 #define CATG_A1 0x07
3712 #define CATG_B1 0x30
3713 #define CATG_A2 0x30
3714 #define CATG_B2 0x0C
3715 #define CATG_C2 0x03
3716 /* Disallow group 1 conditions mixed with group 2 conditions
3717 if group 1, allow only one category A and one category B
3718 if group 2, allow only one each of category A, B, and C. */
3719 if (((insn
->opcode
[0].word
& 0xFF) != 0))
3721 if ((insn
->opcode
[0].word
& CC_GROUP
) != (cc
->value
& CC_GROUP
))
3723 as_bad (_("Condition \"%s\" does not match preceding group"),
3727 if (insn
->opcode
[0].word
& CC_GROUP
)
3729 if ((insn
->opcode
[0].word
& CC_ACC
) != (cc
->value
& CC_ACC
))
3731 as_bad (_("Condition \"%s\" uses a different accumulator from "
3732 "a preceding condition"),
3736 if ((insn
->opcode
[0].word
& CATG_A1
) && (cc
->value
& CATG_A1
))
3738 as_bad (_("Only one comparison conditional allowed"));
3741 if ((insn
->opcode
[0].word
& CATG_B1
) && (cc
->value
& CATG_B1
))
3743 as_bad (_("Only one overflow conditional allowed"));
3747 else if ( ((insn
->opcode
[0].word
& CATG_A2
) && (cc
->value
& CATG_A2
))
3748 || ((insn
->opcode
[0].word
& CATG_B2
) && (cc
->value
& CATG_B2
))
3749 || ((insn
->opcode
[0].word
& CATG_C2
) && (cc
->value
& CATG_C2
)))
3751 as_bad (_("Duplicate %s conditional"), operand
->buf
);
3756 insn
->opcode
[0].word
|= cc
->value
;
3761 encode_cc3 (tic54x_insn
*insn
, struct opstruct
*operand
)
3763 tic54x_symbol
*cc3
= (tic54x_symbol
*) str_hash_find (cc3_hash
, operand
->buf
);
3764 int value
= cc3
? cc3
->value
: operand
->exp
.X_add_number
<< 8;
3766 if ((value
& 0x0300) != value
)
3768 as_bad (_("Unrecognized condition code \"%s\""), operand
->buf
);
3771 insn
->opcode
[0].word
|= value
;
3776 encode_arx (tic54x_insn
*insn
, struct opstruct
*operand
)
3778 int arf
= strlen (operand
->buf
) >= 3 ? operand
->buf
[2] - '0' : -1;
3780 if (strncasecmp ("ar", operand
->buf
, 2) || arf
< 0 || arf
> 7)
3782 as_bad (_("Invalid auxiliary register (use AR0-AR7)"));
3785 insn
->opcode
[0].word
|= arf
;
3790 encode_cc2 (tic54x_insn
*insn
, struct opstruct
*operand
)
3792 tic54x_symbol
*cc2
= (tic54x_symbol
*) str_hash_find (cc2_hash
, operand
->buf
);
3796 as_bad (_("Unrecognized condition code \"%s\""), operand
->buf
);
3799 insn
->opcode
[0].word
|= cc2
->value
;
3804 encode_operand (tic54x_insn
*insn
, enum optype type
, struct opstruct
*operand
)
3806 int ext
= (insn
->tm
->flags
& FL_EXT
) != 0;
3808 if (type
== OP_MMR
&& operand
->exp
.X_op
!= O_constant
)
3810 /* Disallow long-constant addressing for memory-mapped addressing. */
3811 if (insn
->is_lkaddr
)
3813 as_bad (_("lk addressing modes are invalid for memory-mapped "
3814 "register addressing"));
3818 /* Warn about *+ARx when used with MMR operands. */
3819 if (strncasecmp (operand
->buf
, "*+ar", 4) == 0)
3821 as_warn (_("Address mode *+ARx is not allowed in memory-mapped "
3822 "register addressing. Resulting behavior is "
3832 /* 16-bit immediate value. */
3833 return encode_dmad (insn
, operand
, 0);
3835 if (TOUPPER (*operand
->buf
) == 'B')
3837 insn
->opcode
[ext
? (1 + insn
->is_lkaddr
) : 0].word
|= (1 << 9);
3838 if (insn
->using_default_dst
)
3839 insn
->opcode
[ext
? (1 + insn
->is_lkaddr
) : 0].word
|= (1 << 8);
3843 /* Make sure this agrees with the OP_DST operand. */
3844 if (!((TOUPPER (operand
->buf
[0]) == 'B') ^
3845 ((insn
->opcode
[0].word
& (1 << 8)) != 0)))
3847 as_bad (_("Destination accumulator for each part of this parallel "
3848 "instruction must be different"));
3854 if (TOUPPER (operand
->buf
[0]) == 'B')
3855 insn
->opcode
[ext
? (1 + insn
->is_lkaddr
) : 0].word
|= (1 << 8);
3860 int mod
= (operand
->buf
[4] == '\0' ? 0 : /* *arx */
3861 operand
->buf
[4] == '-' ? 1 : /* *arx- */
3862 operand
->buf
[5] == '\0' ? 2 : 3); /* *arx+, *arx+0% */
3863 int arf
= operand
->buf
[3] - '0' - 2;
3864 int code
= (mod
<< 2) | arf
;
3865 insn
->opcode
[0].word
|= (code
<< (type
== OP_Xmem
? 4 : 0));
3870 if (!is_indirect (operand
))
3871 return encode_address (insn
, operand
);
3874 return encode_indirect (insn
, operand
);
3876 return encode_dmad (insn
, operand
, 2);
3878 return encode_dmad (insn
, operand
, 1);
3881 return encode_dmad (insn
, operand
, 0);
3883 return encode_arx (insn
, operand
);
3888 int value
= operand
->exp
.X_add_number
;
3891 insn
->opcode
[0].word
|= value
;
3894 if (value
< 16 || value
> 24)
3896 as_bad (_("Memory mapped register \"%s\" out of range"),
3900 if (type
== OP_MMRX
)
3901 insn
->opcode
[0].word
|= (value
- 16) << 4;
3903 insn
->opcode
[0].word
|= (value
- 16);
3911 return encode_integer (insn
, operand
, ext
+ insn
->is_lkaddr
,
3914 return encode_integer (insn
, operand
, ext
+ insn
->is_lkaddr
,
3917 return encode_integer (insn
, operand
, 1 + insn
->is_lkaddr
,
3918 -32768, 32767, 0xFFFF);
3920 return encode_condition (insn
, operand
);
3922 return encode_cc2 (insn
, operand
);
3924 return encode_cc3 (insn
, operand
);
3926 return encode_integer (insn
, operand
, 0, 0, 15, 0xF);
3928 return encode_integer (insn
, operand
, 0, -128, 127, 0xFF);
3931 int value
= operand
->exp
.X_add_number
;
3933 if (value
< 1 || value
> 3)
3935 as_bad (_("Invalid operand (use 1, 2, or 3)"));
3938 code
= value
== 1 ? 0 : value
== 2 ? 0x2 : 0x1;
3939 insn
->opcode
[0].word
|= (code
<< 8);
3943 return encode_integer (insn
, operand
, 0, 0, 31, 0x1F);
3945 return encode_integer (insn
, operand
, 0, 0, 255, 0xFF);
3947 return encode_integer (insn
, operand
, 1 + insn
->is_lkaddr
,
3951 tic54x_symbol
*sbit
= (tic54x_symbol
*)
3952 str_hash_find (sbit_hash
, operand
->buf
);
3953 int value
= is_absolute (operand
) ?
3954 operand
->exp
.X_add_number
: (sbit
? sbit
->value
: -1);
3957 if (insn
->opcount
== 1)
3961 as_bad (_("A status register or status bit name is required"));
3964 /* Guess the register based on the status bit; "ovb" is the last
3965 status bit defined for st0. */
3966 if (sbit
> (tic54x_symbol
*) str_hash_find (sbit_hash
, "ovb"))
3971 as_bad (_("Unrecognized status bit \"%s\""), operand
->buf
);
3974 insn
->opcode
[0].word
|= value
;
3975 insn
->opcode
[0].word
|= (reg
<< 9);
3979 if (strcasecmp (operand
->buf
, "st0") == 0
3980 || strcasecmp (operand
->buf
, "st1") == 0)
3982 insn
->opcode
[0].word
|=
3983 ((unsigned short) (operand
->buf
[2] - '0')) << 9;
3986 else if (operand
->exp
.X_op
== O_constant
3987 && (operand
->exp
.X_add_number
== 0
3988 || operand
->exp
.X_add_number
== 1))
3990 insn
->opcode
[0].word
|=
3991 ((unsigned short) (operand
->exp
.X_add_number
)) << 9;
3994 as_bad (_("Invalid status register \"%s\""), operand
->buf
);
3997 return encode_integer (insn
, operand
, 0, -16, 15, 0x1F);
3999 return encode_integer (insn
, operand
, 0, 0, 7, 0x7);
4001 return encode_integer (insn
, operand
, 0, 0, 0x1FF, 0x1FF);
4003 if (operand
->exp
.X_add_number
!= 1
4004 && operand
->exp
.X_add_number
!= 2)
4006 as_bad (_("Operand \"%s\" out of range (use 1 or 2)"), operand
->buf
);
4009 insn
->opcode
[0].word
|= (operand
->exp
.X_add_number
- 1) << 9;
4018 /* No encoding necessary. */
4028 emit_insn (tic54x_insn
*insn
)
4031 flagword oldflags
= bfd_section_flags (now_seg
);
4032 flagword flags
= oldflags
| SEC_CODE
;
4034 if (!bfd_set_section_flags (now_seg
, flags
))
4035 as_warn (_("error setting flags for \"%s\": %s"),
4036 bfd_section_name (now_seg
),
4037 bfd_errmsg (bfd_get_error ()));
4039 for (i
= 0; i
< insn
->words
; i
++)
4041 int size
= (insn
->opcode
[i
].unresolved
4042 && insn
->opcode
[i
].r_type
== BFD_RELOC_TIC54X_23
) ? 4 : 2;
4043 char *p
= frag_more (size
);
4046 md_number_to_chars (p
, (valueT
) insn
->opcode
[i
].word
, 2);
4048 md_number_to_chars (p
, (valueT
) insn
->opcode
[i
].word
<< 16, 4);
4050 if (insn
->opcode
[i
].unresolved
)
4051 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
,
4052 insn
->opcode
[i
].r_nchars
, &insn
->opcode
[i
].addr_expr
,
4053 false, insn
->opcode
[i
].r_type
);
4057 /* Convert the operand strings into appropriate opcode values
4058 return the total number of words used by the instruction. */
4061 build_insn (tic54x_insn
*insn
)
4065 /* Only non-parallel instructions support lk addressing. */
4066 if (!(insn
->tm
->flags
& FL_PAR
))
4068 for (i
= 0; i
< insn
->opcount
; i
++)
4070 if ((OPTYPE (insn
->operands
[i
].type
) == OP_Smem
4071 || OPTYPE (insn
->operands
[i
].type
) == OP_Lmem
4072 || OPTYPE (insn
->operands
[i
].type
) == OP_Sind
)
4073 && strchr (insn
->operands
[i
].buf
, '(')
4074 /* Don't mistake stack-relative addressing for lk addressing. */
4075 && strncasecmp (insn
->operands
[i
].buf
, "*sp (", 4) != 0)
4077 insn
->is_lkaddr
= 1;
4078 insn
->lkoperand
= i
;
4083 insn
->words
= insn
->tm
->words
+ insn
->is_lkaddr
;
4085 insn
->opcode
[0].word
= insn
->tm
->opcode
;
4086 if (insn
->tm
->flags
& FL_EXT
)
4087 insn
->opcode
[1 + insn
->is_lkaddr
].word
= insn
->tm
->opcode2
;
4089 for (i
= 0; i
< insn
->opcount
; i
++)
4091 enum optype type
= insn
->operands
[i
].type
;
4093 if (!encode_operand (insn
, type
, &insn
->operands
[i
]))
4096 if (insn
->tm
->flags
& FL_PAR
)
4097 for (i
= 0; i
< insn
->paropcount
; i
++)
4099 enum optype partype
= insn
->paroperands
[i
].type
;
4101 if (!encode_operand (insn
, partype
, &insn
->paroperands
[i
]))
4111 optimize_insn (tic54x_insn
*insn
)
4113 /* Optimize some instructions, helping out the brain-dead programmer. */
4114 #define is_zero(op) ((op).exp.X_op == O_constant && (op).exp.X_add_number == 0)
4115 if (strcasecmp (insn
->tm
->name
, "add") == 0)
4117 if (insn
->opcount
> 1
4118 && is_accumulator (&insn
->operands
[insn
->opcount
- 2])
4119 && is_accumulator (&insn
->operands
[insn
->opcount
- 1])
4120 && strcasecmp (insn
->operands
[insn
->opcount
- 2].buf
,
4121 insn
->operands
[insn
->opcount
- 1].buf
) == 0)
4124 insn
->using_default_dst
= 1;
4128 /* Try to collapse if Xmem and shift count is zero. */
4129 if ((OPTYPE (insn
->tm
->operand_types
[0]) == OP_Xmem
4130 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
4131 && is_zero (insn
->operands
[1]))
4132 /* Or if Smem, shift is zero or absent, and SRC == DST. */
4133 || (OPTYPE (insn
->tm
->operand_types
[0]) == OP_Smem
4134 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
4135 && is_type (&insn
->operands
[1], OP_SHIFT
)
4136 && is_zero (insn
->operands
[1]) && insn
->opcount
== 3))
4138 insn
->operands
[1] = insn
->operands
[2];
4143 else if (strcasecmp (insn
->tm
->name
, "ld") == 0)
4145 if (insn
->opcount
== 3 && insn
->operands
[0].type
!= OP_SRC
)
4147 if ((OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
4148 || OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
)
4149 && is_zero (insn
->operands
[1])
4150 && (OPTYPE (insn
->tm
->operand_types
[0]) != OP_lk
4151 || (insn
->operands
[0].exp
.X_op
== O_constant
4152 && insn
->operands
[0].exp
.X_add_number
<= 255
4153 && insn
->operands
[0].exp
.X_add_number
>= 0)))
4155 insn
->operands
[1] = insn
->operands
[2];
4161 else if (strcasecmp (insn
->tm
->name
, "sth") == 0
4162 || strcasecmp (insn
->tm
->name
, "stl") == 0)
4164 if ((OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
4165 || OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
)
4166 && is_zero (insn
->operands
[1]))
4168 insn
->operands
[1] = insn
->operands
[2];
4173 else if (strcasecmp (insn
->tm
->name
, "sub") == 0)
4175 if (insn
->opcount
> 1
4176 && is_accumulator (&insn
->operands
[insn
->opcount
- 2])
4177 && is_accumulator (&insn
->operands
[insn
->opcount
- 1])
4178 && strcasecmp (insn
->operands
[insn
->opcount
- 2].buf
,
4179 insn
->operands
[insn
->opcount
- 1].buf
) == 0)
4182 insn
->using_default_dst
= 1;
4186 if ( ((OPTYPE (insn
->tm
->operand_types
[0]) == OP_Smem
4187 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
)
4188 || (OPTYPE (insn
->tm
->operand_types
[0]) == OP_Xmem
4189 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
))
4190 && is_zero (insn
->operands
[1])
4191 && insn
->opcount
== 3)
4193 insn
->operands
[1] = insn
->operands
[2];
4201 /* Find a matching template if possible, and get the operand strings. */
4204 tic54x_parse_insn (tic54x_insn
*insn
, char *line
)
4206 insn
->tm
= (insn_template
*) str_hash_find (op_hash
, insn
->mnemonic
);
4209 as_bad (_("Unrecognized instruction \"%s\""), insn
->mnemonic
);
4213 insn
->opcount
= get_operands (insn
->operands
, line
);
4214 if (insn
->opcount
< 0)
4217 /* Check each variation of operands for this mnemonic. */
4218 while (insn
->tm
->name
&& strcasecmp (insn
->tm
->name
, insn
->mnemonic
) == 0)
4220 if (insn
->opcount
>= insn
->tm
->minops
4221 && insn
->opcount
<= insn
->tm
->maxops
4222 && operands_match (insn
, &insn
->operands
[0], insn
->opcount
,
4223 insn
->tm
->operand_types
,
4224 insn
->tm
->minops
, insn
->tm
->maxops
))
4226 /* SUCCESS! now try some optimizations. */
4227 if (optimize_insn (insn
))
4229 insn
->tm
= (insn_template
*) str_hash_find (op_hash
,
4238 as_bad (_("Unrecognized operand list '%s' for instruction '%s'"),
4239 line
, insn
->mnemonic
);
4243 /* We set this in start_line_hook, 'cause if we do a line replacement, we
4244 won't be able to see the next line. */
4245 static int parallel_on_next_line_hint
= 0;
4247 /* See if this is part of a parallel instruction
4248 Look for a subsequent line starting with "||". */
4251 next_line_shows_parallel (char *next_line
)
4253 /* Look for the second half. */
4254 while (*next_line
!= 0 && ISSPACE (*next_line
))
4257 return (next_line
[0] == PARALLEL_SEPARATOR
4258 && next_line
[1] == PARALLEL_SEPARATOR
);
4262 tic54x_parse_parallel_insn_firstline (tic54x_insn
*insn
, char *line
)
4264 insn
->tm
= (insn_template
*) str_hash_find (parop_hash
, insn
->mnemonic
);
4267 as_bad (_("Unrecognized parallel instruction \"%s\""),
4272 while (insn
->tm
->name
&& strcasecmp (insn
->tm
->name
,
4273 insn
->mnemonic
) == 0)
4275 insn
->opcount
= get_operands (insn
->operands
, line
);
4276 if (insn
->opcount
< 0)
4278 if (insn
->opcount
== 2
4279 && operands_match (insn
, &insn
->operands
[0], insn
->opcount
,
4280 insn
->tm
->operand_types
, 2, 2))
4286 /* Didn't find a matching parallel; try for a normal insn. */
4290 /* Parse the second line of a two-line parallel instruction. */
4293 tic54x_parse_parallel_insn_lastline (tic54x_insn
*insn
, char *line
)
4295 int valid_mnemonic
= 0;
4297 insn
->paropcount
= get_operands (insn
->paroperands
, line
);
4298 while (insn
->tm
->name
&& strcasecmp (insn
->tm
->name
,
4299 insn
->mnemonic
) == 0)
4301 if (strcasecmp (insn
->tm
->parname
, insn
->parmnemonic
) == 0)
4305 if (insn
->paropcount
>= insn
->tm
->minops
4306 && insn
->paropcount
<= insn
->tm
->maxops
4307 && operands_match (insn
, insn
->paroperands
,
4309 insn
->tm
->paroperand_types
,
4310 insn
->tm
->minops
, insn
->tm
->maxops
))
4316 as_bad (_("Invalid operand (s) for parallel instruction \"%s\""),
4319 as_bad (_("Unrecognized parallel instruction combination \"%s || %s\""),
4320 insn
->mnemonic
, insn
->parmnemonic
);
4325 /* If quotes found, return copy of line up to closing quote;
4326 otherwise up until terminator.
4327 If it's a string, pass as-is; otherwise attempt substitution symbol
4328 replacement on the value. */
4331 subsym_get_arg (char *line
, const char *terminators
, char **str
, int nosub
)
4335 int is_string
= *line
== '"';
4336 int is_char
= ISDIGIT (*line
);
4340 while (ISDIGIT (*ptr
))
4343 *str
= xmemdup0 (line
, ptr
- line
);
4347 char *savedp
= input_line_pointer
;
4350 input_line_pointer
= ptr
;
4351 *str
= demand_copy_C_string (&len
);
4352 endp
= input_line_pointer
;
4353 input_line_pointer
= savedp
;
4355 /* Do forced substitutions if requested. */
4356 if (!nosub
&& **str
== ':')
4357 *str
= subsym_substitute (*str
, 1);
4361 const char *term
= terminators
;
4363 while (*ptr
&& *ptr
!= *term
)
4374 *str
= xmemdup0 (line
, ptr
- line
);
4375 /* Do simple substitution, if available. */
4378 subsym_ent_t
*ent
= subsym_lookup (*str
, macro_level
);
4379 if (ent
&& !ent
->isproc
)
4387 /* Replace the given substitution string.
4388 We start at the innermost macro level, so that existing locals remain local
4389 Note: we're treating macro args identically to .var's; I don't know if
4390 that's compatible w/TI's assembler. */
4393 subsym_create_or_replace (char *name
, char *value
)
4396 subsym_ent_t
*ent
= xmalloc (sizeof (*ent
));
4403 for (i
= macro_level
; i
> 0; i
--)
4404 if (str_hash_find (subsym_hash
[i
], name
))
4406 str_hash_insert (subsym_hash
[i
], name
, ent
, 1);
4409 str_hash_insert (subsym_hash
[0], name
, ent
, 1);
4412 /* Look up the substitution string replacement for the given symbol.
4413 Start with the innermost macro substitution table given and work
4416 static subsym_ent_t
*
4417 subsym_lookup (char *name
, int nest_level
)
4419 void *value
= str_hash_find (subsym_hash
[nest_level
], name
);
4421 if (value
|| nest_level
== 0)
4424 return subsym_lookup (name
, nest_level
- 1);
4427 /* Do substitution-symbol replacement on the given line (recursively).
4428 return the argument if no substitution was done
4430 Also look for built-in functions ($func (arg)) and local labels.
4432 If FORCED is set, look for forced substitutions of the form ':SYMBOL:'. */
4435 subsym_substitute (char *line
, int forced
)
4437 /* For each apparent symbol, see if it's a substitution symbol, and if so,
4438 replace it in the input. */
4439 char *replacement
; /* current replacement for LINE. */
4440 char *head
; /* Start of line. */
4441 char *ptr
; /* Current examination point. */
4442 int changed
= 0; /* Did we make a substitution? */
4443 int eval_line
= 0; /* Is this line a .eval/.asg statement? */
4444 int eval_symbol
= 0; /* Are we in the middle of the symbol for
4446 char *eval_end
= NULL
;
4448 int line_conditional
= 0;
4450 unsigned char current_char
;
4452 /* Flag lines where we might need to replace a single '=' with two;
4453 GAS uses single '=' to assign macro args values, and possibly other
4454 places, so limit what we replace. */
4455 if (strstr (line
, ".if")
4456 || strstr (line
, ".elseif")
4457 || strstr (line
, ".break"))
4458 line_conditional
= 1;
4460 /* Watch out for .eval, so that we avoid doing substitution on the
4461 symbol being assigned a value. */
4462 if (strstr (line
, ".eval") || strstr (line
, ".asg"))
4465 /* If it's a macro definition, don't do substitution on the argument
4467 if (strstr (line
, ".macro"))
4470 /* Work with a copy of the input line. */
4471 replacement
= xstrdup (line
);
4472 ptr
= head
= replacement
;
4474 while (!is_end_of_line
[(current_char
= * (unsigned char *) ptr
)])
4476 /* Need to update this since LINE may have been modified. */
4478 eval_end
= strrchr (ptr
, ',');
4480 /* Replace triple double quotes with bounding quote/escapes. */
4481 if (current_char
== '"' && ptr
[1] == '"' && ptr
[2] == '"')
4484 tmp
= strstr (ptr
+ 2, "\"\"\"");
4490 /* Replace a single '=' with a '==';
4491 for compatibility with older code only. */
4492 if (line_conditional
&& current_char
== '=')
4500 tmp
= concat (head
, "==", ptr
, (char *) NULL
);
4501 /* Continue examining after the '=='. */
4502 ptr
= tmp
+ strlen (head
) + 2;
4504 head
= replacement
= tmp
;
4508 /* Flag when we've reached the symbol part of .eval/.asg. */
4509 if (eval_line
&& ptr
>= eval_end
)
4512 /* For each apparent symbol, see if it's a substitution symbol, and if
4513 so, replace it in the input. */
4514 if ((forced
&& current_char
== ':')
4515 || (!forced
&& is_name_beginner (current_char
)))
4517 char *name
; /* Symbol to be replaced. */
4518 char *savedp
= input_line_pointer
;
4520 subsym_ent_t
*ent
= NULL
;
4522 char *tail
; /* Rest of line after symbol. */
4524 /* Skip the colon. */
4528 input_line_pointer
= ptr
;
4529 c
= get_symbol_name (&name
);
4530 /* '?' is not normally part of a symbol, but it IS part of a local
4534 *input_line_pointer
++ = c
;
4535 c
= *input_line_pointer
;
4536 *input_line_pointer
= '\0';
4538 /* Avoid infinite recursion; if a symbol shows up a second time for
4539 substitution, leave it as is. */
4540 if (str_hash_find (subsym_recurse_hash
, name
) == NULL
)
4542 ent
= subsym_lookup (name
, macro_level
);
4543 if (ent
&& !ent
->isproc
)
4547 as_warn (_("%s symbol recursion stopped at "
4548 "second appearance of '%s'"),
4549 forced
? "Forced substitution" : "Substitution", name
);
4550 ptr
= tail
= input_line_pointer
;
4551 input_line_pointer
= savedp
;
4553 /* Check for local labels; replace them with the appropriate
4555 if ((*name
== '$' && ISDIGIT (name
[1]) && name
[2] == '\0')
4556 || name
[strlen (name
) - 1] == '?')
4558 /* Use an existing identifier for that label if, available, or
4559 create a new, unique identifier. */
4560 value
= str_hash_find (local_label_hash
[macro_level
], name
);
4564 char *namecopy
= xstrdup (name
);
4566 value
= strcpy (xmalloc (strlen (name
) + sizeof (digit
) + 1),
4569 value
[strlen (value
) - 1] = '\0';
4570 sprintf (digit
, ".%d", local_label_id
++);
4571 strcat (value
, digit
);
4572 str_hash_insert (local_label_hash
[macro_level
],
4573 namecopy
, value
, 0);
4575 /* Indicate where to continue looking for substitutions. */
4578 /* Check for built-in subsym and math functions. */
4579 else if (ent
!= NULL
&& *name
== '$')
4581 const subsym_proc_entry
*entry
= ent
->u
.p
;
4582 char *arg1
, *arg2
= NULL
;
4587 as_bad (_("Unrecognized substitution symbol function"));
4590 else if (*ptr
!= '(')
4592 as_bad (_("Missing '(' after substitution symbol function"));
4598 float farg1
, farg2
= 0;
4600 farg1
= (float) strtod (ptr
, &ptr
);
4601 if (entry
->nargs
== 2)
4605 as_bad (_("Expecting second argument"));
4608 farg2
= (float) strtod (ptr
, &ptr
);
4610 value
= XNEWVEC (char, 128);
4611 if (entry
->type
== 2)
4613 int result
= (*entry
->proc
.i
) (farg1
, farg2
);
4614 sprintf (value
, "%d", result
);
4618 float result
= (*entry
->proc
.f
) (farg1
, farg2
);
4619 sprintf (value
, "%f", result
);
4623 as_bad (_("Extra junk in function call, expecting ')'"));
4626 /* Don't bother recursing; the replacement isn't a
4633 int arg_type
[2] = { *ptr
== '"' , 0 };
4634 int ismember
= !strcmp (entry
->name
, "$ismember");
4636 /* Parse one or two args, which must be a substitution
4637 symbol, string or a character-string constant. */
4638 /* For all functions, a string or substitution symbol may be
4639 used, with the following exceptions:
4640 firstch/lastch: 2nd arg must be character constant
4641 ismember: both args must be substitution symbols. */
4642 ptr
= subsym_get_arg (ptr
, ",)", &arg1
, ismember
);
4645 if (entry
->nargs
== 2)
4649 as_bad (_("Function expects two arguments"));
4652 /* Character constants are converted to numerics
4653 by the preprocessor. */
4654 arg_type
[1] = (ISDIGIT (*ptr
)) ? 2 : (*ptr
== '"');
4655 ptr
= subsym_get_arg (ptr
, ")", &arg2
, ismember
);
4657 /* Args checking. */
4658 if ((!strcmp (entry
->name
, "$firstch")
4659 || !strcmp (entry
->name
, "$lastch"))
4660 && arg_type
[1] != 2)
4662 as_bad (_("Expecting character constant argument"));
4666 && (arg_type
[0] != 0 || arg_type
[1] != 0))
4668 as_bad (_("Both arguments must be substitution symbols"));
4673 as_bad (_("Extra junk in function call, expecting ')'"));
4676 val
= (*entry
->proc
.s
) (arg1
, arg2
);
4677 value
= XNEWVEC (char, 64);
4678 sprintf (value
, "%d", val
);
4680 /* Fix things up to replace the entire expression, not just the
4686 if (value
!= NULL
&& !eval_symbol
)
4688 /* Replace the symbol with its string replacement and
4689 continue. Recursively replace VALUE until either no
4690 substitutions are performed, or a substitution that has been
4691 previously made is encountered again.
4693 Put the symbol into the recursion hash table so we only
4694 try to replace a symbol once. */
4697 str_hash_insert (subsym_recurse_hash
, name
, name
, 0);
4698 value
= subsym_substitute (value
, macro_level
> 0);
4699 str_hash_delete (subsym_recurse_hash
, name
);
4702 /* Temporarily zero-terminate where the symbol started. */
4708 /* Subscripted substitution symbol -- use just the
4709 indicated portion of the string; the description
4710 kinda indicates that forced substitution is not
4711 supposed to be recursive, but I'm not sure. */
4712 unsigned beg
, len
= 1; /* default to a single char */
4713 char *newval
= xstrdup (value
);
4715 savedp
= input_line_pointer
;
4716 input_line_pointer
= tail
+ 1;
4717 beg
= get_absolute_expression ();
4720 as_bad (_("Invalid subscript (use 1 to %d)"),
4721 (int) strlen (value
));
4724 if (*input_line_pointer
== ',')
4726 ++input_line_pointer
;
4727 len
= get_absolute_expression ();
4728 if (beg
+ len
> strlen (value
))
4730 as_bad (_("Invalid length (use 0 to %d)"),
4731 (int) strlen (value
) - beg
);
4737 tail
= input_line_pointer
;
4740 as_bad (_("Missing ')' in subscripted substitution "
4741 "symbol expression"));
4745 input_line_pointer
= savedp
;
4751 tmp
= xmalloc (strlen (head
) + strlen (value
) +
4752 strlen (tail
+ 1) + 2);
4754 strcat (tmp
, value
);
4755 /* Make sure forced substitutions are properly terminated. */
4760 as_bad (_("Missing forced substitution terminator ':'"));
4766 /* Restore the character after the symbol end. */
4769 /* Continue examining after the replacement value. */
4770 ptr
= tmp
+ strlen (head
) + strlen (value
);
4772 head
= replacement
= tmp
;
4791 /* We use this to handle substitution symbols
4792 hijack input_line_pointer, replacing it with our substituted string.
4794 .sslist should enable listing the line after replacements are made...
4796 returns the new buffer limit. */
4799 tic54x_start_line_hook (void)
4802 char *replacement
= NULL
;
4804 /* Work with a copy of the input line, including EOL char. */
4805 for (endp
= input_line_pointer
; *endp
!= 0; )
4806 if (is_end_of_line
[(unsigned char) *endp
++])
4809 line
= xmemdup0 (input_line_pointer
, endp
- input_line_pointer
);
4811 /* Scan ahead for parallel insns. */
4812 parallel_on_next_line_hint
= next_line_shows_parallel (endp
);
4814 /* If within a macro, first process forced replacements. */
4815 if (macro_level
> 0)
4816 replacement
= subsym_substitute (line
, 1);
4819 replacement
= subsym_substitute (replacement
, 0);
4821 if (replacement
!= line
)
4823 char *tmp
= replacement
;
4824 char *comment
= strchr (replacement
, ';');
4825 char endc
= replacement
[strlen (replacement
) - 1];
4827 /* Clean up the replacement; we'd prefer to have this done by the
4828 standard preprocessing equipment (maybe do_scrub_chars?)
4829 but for now, do a quick-and-dirty. */
4830 if (comment
!= NULL
)
4837 comment
= replacement
+ strlen (replacement
) - 1;
4839 /* Trim trailing whitespace. */
4840 while (ISSPACE (*comment
))
4847 /* Compact leading whitespace. */
4848 while (ISSPACE (tmp
[0]) && ISSPACE (tmp
[1]))
4851 input_line_pointer
= endp
;
4852 input_scrub_insert_line (tmp
);
4855 /* Keep track of whether we've done a substitution. */
4856 substitution_line
= 1;
4862 substitution_line
= 0;
4866 /* This is the guts of the machine-dependent assembler. STR points to a
4867 machine dependent instruction. This function is supposed to emit
4868 the frags/bytes it assembles to. */
4870 md_assemble (char *line
)
4872 static int repeat_slot
= 0;
4873 static int delay_slots
= 0; /* How many delay slots left to fill? */
4874 static int is_parallel
= 0;
4875 static tic54x_insn insn
;
4877 char *savedp
= input_line_pointer
;
4880 input_line_pointer
= line
;
4881 c
= get_symbol_name (&line
);
4885 if (address_mode_needs_set
)
4887 set_address_mode (amode
);
4888 address_mode_needs_set
= 0;
4901 strcpy (insn
.parmnemonic
, line
);
4902 lptr
= input_line_pointer
;
4904 input_line_pointer
= savedp
;
4906 if (tic54x_parse_parallel_insn_lastline (&insn
, lptr
))
4908 int words
= build_insn (&insn
);
4910 if (delay_slots
!= 0)
4912 if (words
> delay_slots
)
4914 as_bad (ngettext ("Instruction does not fit in available "
4915 "delay slots (%d-word insn, %d slot left)",
4916 "Instruction does not fit in available "
4917 "delay slots (%d-word insn, %d slots left)",
4919 words
, delay_slots
);
4923 delay_slots
-= words
;
4929 memset (&insn
, 0, sizeof (insn
));
4930 strcpy (insn
.mnemonic
, line
);
4931 lptr
= input_line_pointer
;
4933 input_line_pointer
= savedp
;
4935 /* See if this line is part of a parallel instruction; if so, either this
4936 line or the next line will have the "||" specifier preceding the
4937 mnemonic, and we look for it in the parallel insn hash table. */
4938 if (strstr (line
, "||") != NULL
|| parallel_on_next_line_hint
)
4940 char *tmp
= strstr (line
, "||");
4944 if (tic54x_parse_parallel_insn_firstline (&insn
, lptr
))
4947 /* If the parallel part is on the same line, process it now,
4948 otherwise let the assembler pick up the next line for us. */
4951 while (ISSPACE (tmp
[2]))
4953 md_assemble (tmp
+ 2);
4958 as_bad (_("Unrecognized parallel instruction '%s'"), line
);
4963 if (tic54x_parse_insn (&insn
, lptr
))
4967 if ((insn
.tm
->flags
& FL_LP
)
4968 && cpu
!= V545LP
&& cpu
!= V546LP
)
4970 as_bad (_("Instruction '%s' requires an LP cpu version"),
4974 if ((insn
.tm
->flags
& FL_FAR
)
4975 && amode
!= far_mode
)
4977 as_bad (_("Instruction '%s' requires far mode addressing"),
4982 words
= build_insn (&insn
);
4984 /* Is this instruction in a delay slot? */
4987 if (words
> delay_slots
)
4989 as_warn (ngettext ("Instruction does not fit in available "
4990 "delay slots (%d-word insn, %d slot left). "
4991 "Resulting behavior is undefined.",
4992 "Instruction does not fit in available "
4993 "delay slots (%d-word insn, %d slots left). "
4994 "Resulting behavior is undefined.",
4996 words
, delay_slots
);
5000 /* Branches in delay slots are not allowed. */
5001 if (insn
.tm
->flags
& FL_BMASK
)
5003 as_warn (_("Instructions which cause PC discontinuity are not "
5004 "allowed in a delay slot. "
5005 "Resulting behavior is undefined."));
5007 delay_slots
-= words
;
5010 /* Is this instruction the target of a repeat? */
5013 if (insn
.tm
->flags
& FL_NR
)
5014 as_warn (_("'%s' is not repeatable. "
5015 "Resulting behavior is undefined."),
5017 else if (insn
.is_lkaddr
)
5018 as_warn (_("Instructions using long offset modifiers or absolute "
5019 "addresses are not repeatable. "
5020 "Resulting behavior is undefined."));
5024 /* Make sure we check the target of a repeat instruction. */
5025 if (insn
.tm
->flags
& B_REPEAT
)
5028 /* FIXME -- warn if repeat_slot == 1 at EOF. */
5030 /* Make sure we check our delay slots for validity. */
5031 if (insn
.tm
->flags
& FL_DELAY
)
5034 /* FIXME -- warn if delay_slots != 0 at EOF. */
5039 /* Do a final adjustment on the symbol table; in this case, make sure we have
5040 a ".file" symbol. */
5043 tic54x_adjust_symtab (void)
5045 if (symbol_rootP
== NULL
5046 || S_GET_STORAGE_CLASS (symbol_rootP
) != C_FILE
)
5049 const char * filename
= as_where (&lineno
);
5050 c_dot_file_symbol (filename
);
5054 /* In order to get gas to ignore any | chars at the start of a line,
5055 this function returns true if a | is found in a line.
5056 This lets us process parallel instructions, which span two lines. */
5059 tic54x_unrecognized_line (int c
)
5061 return c
== PARALLEL_SEPARATOR
;
5064 /* Watch for local labels of the form $[0-9] and [_a-zA-Z][_a-zA-Z0-9]*?
5065 Encode their names so that only we see them and can map them to the
5067 FIXME -- obviously this isn't done yet. These locals still show up in the
5070 tic54x_define_label (symbolS
*sym
)
5072 /* Just in case we need this later; note that this is not necessarily the
5073 same thing as line_label...
5074 When aligning or assigning labels to fields, sometimes the label is
5075 assigned other than the address at which the label appears.
5076 FIXME -- is this really needed? I think all the proper label assignment
5077 is done in tic54x_cons. */
5078 last_label_seen
= sym
;
5081 /* Try to parse something that normal parsing failed at. */
5084 tic54x_undefined_symbol (char *name
)
5088 /* Not sure how to handle predefined symbols. */
5089 if ((sym
= (tic54x_symbol
*) str_hash_find (cc_hash
, name
)) != NULL
5090 || (sym
= (tic54x_symbol
*) str_hash_find (cc2_hash
, name
)) != NULL
5091 || (sym
= (tic54x_symbol
*) str_hash_find (cc3_hash
, name
)) != NULL
5092 || str_hash_find (misc_symbol_hash
, name
) != NULL
5093 || (sym
= (tic54x_symbol
*) str_hash_find (sbit_hash
, name
)) != NULL
5094 || (sym
= (tic54x_symbol
*) str_hash_find (reg_hash
, name
)) != NULL
5095 || (sym
= (tic54x_symbol
*) str_hash_find (mmreg_hash
, name
)) != NULL
5096 || !strcasecmp (name
, "a")
5097 || !strcasecmp (name
, "b"))
5099 return symbol_new (name
, reg_section
, &zero_address_frag
,
5100 sym
? sym
->value
: 0);
5106 /* Parse a name in an expression before the expression parser takes a stab at
5110 tic54x_parse_name (char *name ATTRIBUTE_UNUSED
,
5111 expressionS
*expn ATTRIBUTE_UNUSED
)
5117 md_atof (int type
, char *literalP
, int *sizeP
)
5119 /* Target data is little-endian, but floats are stored
5120 big-"word"ian. ugh. */
5121 return ieee_md_atof (type
, literalP
, sizeP
, true);
5125 tc_gen_reloc (asection
*section
, fixS
*fixP
)
5128 bfd_reloc_code_real_type code
= fixP
->fx_r_type
;
5129 asymbol
*sym
= symbol_get_bfdsym (fixP
->fx_addsy
);
5131 rel
= XNEW (arelent
);
5132 rel
->sym_ptr_ptr
= XNEW (asymbol
*);
5133 *rel
->sym_ptr_ptr
= sym
;
5134 /* We assume that all rel->address are host byte offsets. */
5135 rel
->address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
5136 rel
->address
/= OCTETS_PER_BYTE
;
5137 rel
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
5138 if (!strcmp (sym
->name
, section
->name
))
5139 rel
->howto
+= HOWTO_BANK
;
5143 const char *name
= S_GET_NAME (fixP
->fx_addsy
);
5146 as_fatal ("Cannot generate relocation type for symbol %s, code %s",
5147 name
, bfd_get_reloc_code_name (code
));
5153 /* Handle cons expressions. */
5156 tic54x_cons_fix_new (fragS
*frag
, int where
, int octets
, expressionS
*expn
,
5157 bfd_reloc_code_real_type r
)
5162 as_bad (_("Unsupported relocation size %d"), octets
);
5163 r
= BFD_RELOC_TIC54X_16_OF_23
;
5166 r
= BFD_RELOC_TIC54X_16_OF_23
;
5169 /* TI assembler always uses this, regardless of addressing mode. */
5171 r
= BFD_RELOC_TIC54X_23
;
5173 /* We never want to directly generate this; this is provided for
5174 stabs support only. */
5178 fix_new_exp (frag
, where
, octets
, expn
, 0, r
);
5181 /* Attempt to simplify or even eliminate a fixup.
5182 To indicate that a fixup has been eliminated, set fixP->fx_done.
5184 If fixp->fx_addsy is non-NULL, we'll have to generate a reloc entry. */
5187 md_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg ATTRIBUTE_UNUSED
)
5189 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
5190 valueT val
= * valP
;
5192 switch (fixP
->fx_r_type
)
5195 as_fatal ("Bad relocation type: 0x%02x", fixP
->fx_r_type
);
5197 case BFD_RELOC_TIC54X_MS7_OF_23
:
5198 val
= (val
>> 16) & 0x7F;
5200 case BFD_RELOC_TIC54X_16_OF_23
:
5202 bfd_put_16 (stdoutput
, val
, buf
);
5203 /* Indicate what we're actually writing, so that we don't get warnings
5204 about exceeding available space. */
5205 *valP
= val
& 0xFFFF;
5207 case BFD_RELOC_TIC54X_PARTLS7
:
5208 bfd_put_16 (stdoutput
,
5209 (bfd_get_16 (stdoutput
, buf
) & 0xFF80) | (val
& 0x7F),
5211 /* Indicate what we're actually writing, so that we don't get warnings
5212 about exceeding available space. */
5215 case BFD_RELOC_TIC54X_PARTMS9
:
5216 /* TI assembler doesn't shift its encoding for relocatable files, and is
5217 thus incompatible with this implementation's relocatable files. */
5218 bfd_put_16 (stdoutput
,
5219 (bfd_get_16 (stdoutput
, buf
) & 0xFE00) | (val
>> 7),
5223 case BFD_RELOC_TIC54X_23
:
5224 bfd_put_32 (stdoutput
,
5225 (bfd_get_32 (stdoutput
, buf
) & 0xFF800000) | val
,
5230 if (fixP
->fx_addsy
== NULL
&& fixP
->fx_pcrel
== 0)
5234 /* This is our chance to record section alignment
5235 don't need to do anything here, since BFD does the proper encoding. */
5238 md_section_align (segT segment ATTRIBUTE_UNUSED
, valueT section_size
)
5240 return section_size
;
5244 md_pcrel_from (fixS
*fixP ATTRIBUTE_UNUSED
)
5249 /* Mostly little-endian, but longwords (4 octets) get MS word stored
5253 tic54x_number_to_chars (char *buf
, valueT val
, int n
)
5256 number_to_chars_littleendian (buf
, val
, n
);
5259 number_to_chars_littleendian (buf
, val
>> 16 , 2);
5260 number_to_chars_littleendian (buf
+ 2, val
& 0xFFFF, 2);
5265 tic54x_estimate_size_before_relax (fragS
*frag ATTRIBUTE_UNUSED
,
5266 segT seg ATTRIBUTE_UNUSED
)
5271 /* We use this to handle bit allocations which we couldn't handle before due
5272 to symbols being in different frags. return number of octets added. */
5275 tic54x_relax_frag (fragS
*frag
, long stretch ATTRIBUTE_UNUSED
)
5277 symbolS
*sym
= frag
->fr_symbol
;
5283 struct bit_info
*bi
= (struct bit_info
*) frag
->fr_opcode
;
5284 int bit_offset
= frag_bit_offset (frag_prev (frag
, bi
->seg
), bi
->seg
);
5285 int size
= S_GET_VALUE (sym
);
5286 fragS
*prev_frag
= bit_offset_frag (frag_prev (frag
, bi
->seg
), bi
->seg
);
5287 int available
= 16 - bit_offset
;
5289 if (symbol_get_frag (sym
) != &zero_address_frag
5290 || S_IS_COMMON (sym
)
5291 || !S_IS_DEFINED (sym
))
5292 as_bad_where (frag
->fr_file
, frag
->fr_line
,
5293 _("non-absolute value used with .space/.bes"));
5297 as_warn (_("negative value ignored in %s"),
5298 bi
->type
== TYPE_SPACE
? ".space" :
5299 bi
->type
== TYPE_BES
? ".bes" : ".field");
5301 frag
->tc_frag_data
= frag
->fr_fix
= 0;
5305 if (bi
->type
== TYPE_FIELD
)
5307 /* Bit fields of 16 or larger will have already been handled. */
5308 if (bit_offset
!= 0 && available
>= size
)
5310 char *p
= prev_frag
->fr_literal
;
5312 valueT value
= bi
->value
;
5313 value
<<= available
- size
;
5314 value
|= ((unsigned short) p
[1] << 8) | p
[0];
5315 md_number_to_chars (p
, value
, 2);
5316 if ((prev_frag
->tc_frag_data
+= size
) == 16)
5317 prev_frag
->tc_frag_data
= 0;
5319 symbol_set_frag (bi
->sym
, prev_frag
);
5320 /* This frag is no longer used. */
5321 growth
= -frag
->fr_fix
;
5323 frag
->tc_frag_data
= 0;
5327 char *p
= frag
->fr_literal
;
5329 valueT value
= bi
->value
<< (16 - size
);
5330 md_number_to_chars (p
, value
, 2);
5331 if ((frag
->tc_frag_data
= size
) == 16)
5332 frag
->tc_frag_data
= 0;
5338 if (bit_offset
!= 0 && bit_offset
< 16)
5340 if (available
>= size
)
5342 if ((prev_frag
->tc_frag_data
+= size
) == 16)
5343 prev_frag
->tc_frag_data
= 0;
5345 symbol_set_frag (bi
->sym
, prev_frag
);
5346 /* This frag is no longer used. */
5347 growth
= -frag
->fr_fix
;
5349 frag
->tc_frag_data
= 0;
5352 if (bi
->type
== TYPE_SPACE
&& bi
->sym
)
5353 symbol_set_frag (bi
->sym
, prev_frag
);
5356 growth
= (size
+ 15) / 16 * OCTETS_PER_BYTE
- frag
->fr_fix
;
5357 for (i
= 0; i
< growth
; i
++)
5358 frag
->fr_literal
[i
] = 0;
5359 frag
->fr_fix
= growth
;
5360 frag
->tc_frag_data
= size
% 16;
5361 /* Make sure any BES label points to the LAST word allocated. */
5362 if (bi
->type
== TYPE_BES
&& bi
->sym
)
5363 S_SET_VALUE (bi
->sym
, frag
->fr_fix
/ OCTETS_PER_BYTE
- 1);
5366 frag
->fr_symbol
= 0;
5367 frag
->fr_opcode
= 0;
5374 tic54x_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
,
5375 segT seg ATTRIBUTE_UNUSED
,
5378 /* Offset is in bytes. */
5379 frag
->fr_offset
= (frag
->fr_next
->fr_address
5381 - frag
->fr_fix
) / frag
->fr_var
;
5382 if (frag
->fr_offset
< 0)
5384 as_bad_where (frag
->fr_file
, frag
->fr_line
,
5385 _("attempt to .space/.bes backwards? (%ld)"),
5386 (long) frag
->fr_offset
);
5388 frag
->fr_type
= rs_space
;
5391 /* We need to avoid having labels defined for certain directives/pseudo-ops
5392 since once the label is defined, it's in the symbol table for good. TI
5393 syntax puts the symbol *before* the pseudo (which is kinda like MRI syntax,
5394 I guess, except I've never seen a definition of MRI syntax).
5396 Don't allow labels to start with '.' */
5399 tic54x_start_label (char * label_start
, int nul_char
, int next_char
)
5403 /* If within .struct/.union, no auto line labels, please. */
5404 if (current_stag
!= NULL
)
5407 /* Disallow labels starting with "." */
5408 if (next_char
!= ':')
5410 if (*label_start
== '.')
5412 as_bad (_("Invalid label '%s'"), label_start
);
5417 if (is_end_of_line
[(unsigned char) next_char
])
5420 rest
= input_line_pointer
;
5421 if (nul_char
== '"')
5423 while (ISSPACE (next_char
))
5424 next_char
= *++rest
;
5425 if (next_char
!= '.')
5428 /* Don't let colon () define a label for any of these... */
5429 return ((strncasecmp (rest
, ".tag", 4) != 0 || !ISSPACE (rest
[4]))
5430 && (strncasecmp (rest
, ".struct", 7) != 0 || !ISSPACE (rest
[7]))
5431 && (strncasecmp (rest
, ".union", 6) != 0 || !ISSPACE (rest
[6]))
5432 && (strncasecmp (rest
, ".macro", 6) != 0 || !ISSPACE (rest
[6]))
5433 && (strncasecmp (rest
, ".set", 4) != 0 || !ISSPACE (rest
[4]))
5434 && (strncasecmp (rest
, ".equ", 4) != 0 || !ISSPACE (rest
[4])));