1 /* tc-tic54x.c -- Assembly code for the Texas Instruments TMS320C54X
2 Copyright 1999, 2000, 2001 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 2, 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, 59 Temple Place - Suite 330, 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. */
48 #include "safe-ctype.h"
52 #include "struc-symbol.h"
53 #include "opcode/tic54x.h"
57 #define MAX_LINE 256 /* Lines longer than this are truncated by TI's asm. */
59 const char comment_chars
[] = ";";
60 const char line_comment_chars
[] = ";*#"; /* At column zero only. */
61 const char line_separator_chars
[] = ""; /* Not permitted. */
63 /* Characters which indicate that this is a floating point constant. */
64 const char FLT_CHARS
[] = "fF";
66 /* Characters that can be used to separate mantissa from exp in FP
68 const char EXP_CHARS
[] = "eE";
70 /* Only word (et al.), align, or conditionals are allowed within
72 #define ILLEGAL_WITHIN_STRUCT() \
74 if (current_stag != NULL) \
76 as_bad (_("pseudo-op illegal within .struct/.union")); \
82 md_show_usage (stream
)
85 fprintf (stream
, _("C54x-specific command line options:\n"));
86 fprintf (stream
, _("-mfar-mode | -mf Use extended addressing\n"));
87 fprintf (stream
, _("-mcpu=<CPU version> Specify the CPU version\n"));
89 fprintf (stream
, _("-mcoff-version={0|1|2} Select COFF version\n"));
91 fprintf (stream
, _("-merrors-to-file <filename>\n"));
92 fprintf (stream
, _("-me <filename> Redirect errors to a file\n"));
95 const char *md_shortopts
= "";
99 VNONE
= 0, V541
= 1, V542
= 2, V543
= 3, V545
= 5, V548
= 8, V549
= 9,
100 V545LP
= 15, V546LP
= 16
105 c_mode
, /* 16-bit addresses. */
106 far_mode
/* >16-bit addresses. */
109 #define OPTION_ADDRESS_MODE (OPTION_MD_BASE)
110 #define OPTION_CPU_VERSION (OPTION_ADDRESS_MODE + 1)
111 #define OPTION_COFF_VERSION (OPTION_CPU_VERSION + 1)
112 #define OPTION_STDERR_TO_FILE (OPTION_COFF_VERSION + 1)
114 struct option md_longopts
[] =
116 { "mfar-mode", no_argument
, NULL
, OPTION_ADDRESS_MODE
},
117 { "mf", no_argument
, NULL
, OPTION_ADDRESS_MODE
},
118 { "mcpu", required_argument
, NULL
, OPTION_CPU_VERSION
},
120 { "mcoff-version", required_argument
, NULL
, OPTION_COFF_VERSION
},
122 { "merrors-to-file", required_argument
, NULL
, OPTION_STDERR_TO_FILE
},
123 { "me", required_argument
, NULL
, OPTION_STDERR_TO_FILE
},
124 { NULL
, no_argument
, NULL
, 0},
127 size_t md_longopts_size
= sizeof (md_longopts
);
129 static int assembly_begun
= 0;
130 /* Addressing mode is not entirely implemented; the latest rev of the Other
131 assembler doesn't seem to make any distinction whatsoever; all relocations
132 are stored as extended relocatiosn. Older versions used REL16 vs RELEXT16,
133 but now it seems all relocations are RELEXT16. We use all RELEXT16.
135 The cpu version is kind of a waste of time as well. There is one
136 instruction (RND) for LP devices only, and several for devices with
137 extended addressing only. We include it for compatibility. */
138 static enum address_mode amode
= c_mode
;
139 static enum cpu_version cpu
= VNONE
;
141 /* Include string substitutions in listing? */
142 static int listing_sslist
= 0;
144 /* Did we do subsym substitutions on the line? */
145 static int substitution_line
= 0;
147 /* Last label seen. */
148 static symbolS
*last_label_seen
= NULL
;
150 /* This ensures that all new labels are unique. */
151 static int local_label_id
;
153 static struct hash_control
*subsym_recurse_hash
; /* Prevent infinite recurse. */
154 static struct hash_control
*math_hash
; /* Built-in math functions. */
155 /* Allow maximum levels of macro nesting; level 0 is the main substitution
156 symbol table. The other assembler only does 32 levels, so there! */
157 static struct hash_control
*subsym_hash
[100];
159 /* Keep track of local labels so we can substitute them before GAS sees them
160 since macros use their own 'namespace' for local labels, use a separate hash
162 We do our own local label handling 'cuz it's subtly different from the
165 We use our own macro nesting counter, since GAS overloads it when expanding
166 other things (like conditionals and repeat loops). */
167 static int macro_level
= 0;
168 static struct hash_control
*local_label_hash
[100];
169 /* Keep track of struct/union tags. */
170 static struct hash_control
*stag_hash
;
171 static struct hash_control
*op_hash
;
172 static struct hash_control
*parop_hash
;
173 static struct hash_control
*reg_hash
;
174 static struct hash_control
*mmreg_hash
;
175 static struct hash_control
*cc_hash
;
176 static struct hash_control
*cc2_hash
;
177 static struct hash_control
*cc3_hash
;
178 static struct hash_control
*sbit_hash
;
179 static struct hash_control
*misc_symbol_hash
;
181 static char *subsym_substitute
PARAMS ((char *line
, int forced
));
182 static char *subsym_lookup
PARAMS ((char *name
, int nest_level
));
183 static void subsym_create_or_replace
PARAMS ((char *name
, char *value
));
184 static float math_ceil
PARAMS ((float, float));
185 static float math_cvi
PARAMS ((float, float));
186 static float math_floor
PARAMS ((float, float));
187 static float math_fmod
PARAMS ((float, float));
188 static float math_int
PARAMS ((float, float));
189 static float math_round
PARAMS ((float, float));
190 static float math_sgn
PARAMS ((float, float));
191 static float math_trunc
PARAMS ((float, float));
192 static float math_acos
PARAMS ((float, float));
193 static float math_asin
PARAMS ((float, float));
194 static float math_atan
PARAMS ((float, float));
195 static float math_atan2
PARAMS ((float, float));
196 static float math_cosh
PARAMS ((float, float));
197 static float math_cos
PARAMS ((float, float));
198 static float math_cvf
PARAMS ((float, float));
199 static float math_exp
PARAMS ((float, float));
200 static float math_fabs
PARAMS ((float, float));
201 static float math_ldexp
PARAMS ((float, float));
202 static float math_log10
PARAMS ((float, float));
203 static float math_log
PARAMS ((float, float));
204 static float math_max
PARAMS ((float, float));
205 static float math_pow
PARAMS ((float, float));
206 static float math_sin
PARAMS ((float, float));
207 static float math_sinh
PARAMS ((float, float));
208 static float math_sqrt
PARAMS ((float, float));
209 static float math_tan
PARAMS ((float, float));
210 static float math_tanh
PARAMS ((float, float));
214 symbolS
*sym
; /* Symbol for this stag; value is offset. */
215 const char *name
; /* Shortcut to symbol name. */
216 bfd_vma size
; /* Size of struct/union. */
217 int current_bitfield_offset
; /* Temporary for tracking fields. */
219 struct stag_field
/* List of fields. */
222 bfd_vma offset
; /* Of start of this field. */
223 int bitfield_offset
; /* Of start of this field. */
224 struct stag
*stag
; /* If field is struct/union. */
225 struct stag_field
*next
;
227 /* For nesting; used only in stag construction. */
228 struct stag
*inner
; /* Enclosed .struct. */
229 struct stag
*outer
; /* Enclosing .struct. */
230 } *current_stag
= NULL
;
232 static segT stag_saved_seg
;
233 static subsegT stag_saved_subseg
;
235 /* Output a single character (upper octect is zero). */
243 exp
.X_op
= O_constant
;
244 exp
.X_add_number
= c
;
248 /* Walk backwards in the frag chain. */
251 frag_prev (frag
, seg
)
255 segment_info_type
*seginfo
= seg_info (seg
);
258 for (fragp
= seginfo
->frchainP
->frch_root
; fragp
; fragp
= fragp
->fr_next
)
259 if (fragp
->fr_next
== frag
)
266 bit_offset_frag (frag
, seg
)
272 if (frag
->fr_fix
== 0
273 && frag
->fr_opcode
== NULL
274 && frag
->tc_frag_data
== 0)
275 frag
= frag_prev (frag
, seg
);
282 /* Return the number of bits allocated in the most recent word, or zero if
283 none. .field/.space/.bes may leave words partially allocated. */
286 frag_bit_offset (frag
, seg
)
290 frag
= bit_offset_frag (frag
, seg
);
293 return frag
->fr_opcode
!= NULL
? -1 : frag
->tc_frag_data
;
298 /* Read an expression from a C string; returns a pointer past the end of the
302 parse_expression (char *str
, expressionS
* exp
)
307 tmp
= input_line_pointer
; /* Save line pointer. */
308 input_line_pointer
= str
;
310 s
= input_line_pointer
;
311 input_line_pointer
= tmp
; /* Restore line pointer. */
312 return s
; /* Return pointer to where parsing stopped. */
315 /* .asg "character-string"|character-string, symbol
317 .eval is the only pseudo-op allowed to perform arithmetic on substitution
318 symbols. all other use of symbols defined with .asg are currently
323 int x ATTRIBUTE_UNUSED
;
329 int quoted
= *input_line_pointer
== '"';
331 ILLEGAL_WITHIN_STRUCT ();
336 str
= demand_copy_C_string (&len
);
337 c
= *input_line_pointer
;
341 str
= input_line_pointer
;
342 while ((c
= *input_line_pointer
) != ',')
344 if (is_end_of_line
[(int) *input_line_pointer
])
346 ++input_line_pointer
;
348 *input_line_pointer
= 0;
352 as_bad (_("Comma and symbol expected for '.asg STRING, SYMBOL'"));
353 ignore_rest_of_line ();
357 name
= ++input_line_pointer
;
358 c
= get_symbol_end (); /* Get terminator. */
359 if (!ISALPHA (*name
))
361 as_bad ("symbols assigned with .asg must begin with a letter");
362 ignore_rest_of_line ();
366 tmp
= xmalloc (strlen (str
) + 1);
369 tmp
= xmalloc (strlen (name
) + 1);
372 subsym_create_or_replace (name
, str
);
373 *input_line_pointer
= c
;
374 demand_empty_rest_of_line ();
377 /* .eval expression, symbol
378 There's something screwy about this. The other assembler sometimes does and
379 sometimes doesn't substitute symbols defined with .eval.
380 We'll put the symbols into the subsym table as well as the normal symbol
381 table, since that's what works best. */
385 int x ATTRIBUTE_UNUSED
;
391 char valuestr
[32], *tmp
;
394 ILLEGAL_WITHIN_STRUCT ();
398 quoted
= *input_line_pointer
== '"';
400 ++input_line_pointer
;
401 value
= get_absolute_expression ();
404 if (*input_line_pointer
!= '"')
406 as_bad (_("Unterminated string after absolute expression"));
407 ignore_rest_of_line ();
410 ++input_line_pointer
;
412 if (*input_line_pointer
++ != ',')
414 as_bad (_("Comma and symbol expected for '.eval EXPR, SYMBOL'"));
415 ignore_rest_of_line ();
418 name
= input_line_pointer
;
419 c
= get_symbol_end (); /* Get terminator. */
420 tmp
= xmalloc (strlen (name
) + 1);
421 name
= strcpy (tmp
, name
);
422 *input_line_pointer
= c
;
424 if (!ISALPHA (*name
))
426 as_bad (_("symbols assigned with .eval must begin with a letter"));
427 ignore_rest_of_line ();
430 symbolP
= symbol_new (name
, absolute_section
,
431 (valueT
) value
, &zero_address_frag
);
432 SF_SET_LOCAL (symbolP
);
433 symbol_table_insert (symbolP
);
435 /* The "other" assembler sometimes doesn't put .eval's in the subsym table
436 But since there's not written rule as to when, don't even bother trying
437 to match their behavior. */
438 sprintf (valuestr
, "%d", value
);
439 tmp
= xmalloc (strlen (valuestr
) + 1);
440 strcpy (tmp
, valuestr
);
441 subsym_create_or_replace (name
, tmp
);
443 demand_empty_rest_of_line ();
446 /* .bss symbol, size [, [blocking flag] [, alignment flag]
448 alignment is to a longword boundary; blocking is to 128-word boundary.
450 1) if there is a hole in memory, this directive should attempt to fill it
451 (not yet implemented).
453 2) if the blocking flag is not set, allocate at the current SPC
454 otherwise, check to see if the current SPC plus the space to be
455 allocated crosses the page boundary (128 words).
456 if there's not enough space, create a hole and align with the next page
458 (not yet implemented). */
462 int x ATTRIBUTE_UNUSED
;
469 subsegT current_subseg
;
474 ILLEGAL_WITHIN_STRUCT ();
476 current_seg
= now_seg
; /* Save current seg. */
477 current_subseg
= now_subseg
; /* Save current subseg. */
479 name
= input_line_pointer
;
480 c
= get_symbol_end (); /* Get terminator. */
483 as_bad (".bss size argument missing\n");
484 ignore_rest_of_line ();
488 ++input_line_pointer
;
489 words
= get_absolute_expression ();
492 as_bad (".bss size %d < 0!", words
);
493 ignore_rest_of_line ();
497 if (*input_line_pointer
== ',')
499 /* The blocking flag may be missing. */
500 ++input_line_pointer
;
501 if (*input_line_pointer
!= ',')
502 block
= get_absolute_expression ();
506 if (*input_line_pointer
== ',')
508 ++input_line_pointer
;
509 align
= get_absolute_expression ();
517 subseg_set (bss_section
, 0);
518 symbolP
= symbol_find_or_make (name
);
520 if (S_GET_SEGMENT (symbolP
) == bss_section
)
521 symbolP
->sy_frag
->fr_symbol
= (symbolS
*) NULL
;
523 symbol_set_frag (symbolP
, frag_now
);
524 p
= frag_var (rs_org
, 1, 1, (relax_substateT
) 0, symbolP
,
525 (offsetT
) (words
<< 1), (char *) 0);
526 *p
= 0; /* Fill char. */
528 S_SET_SEGMENT (symbolP
, bss_section
);
530 /* The symbol may already have been created with a preceding
531 ".globl" directive -- be careful not to step on storage class
532 in that case. Otherwise, set it to static. */
533 if (S_GET_STORAGE_CLASS (symbolP
) != C_EXT
)
534 S_SET_STORAGE_CLASS (symbolP
, C_STAT
);
538 /* s_align eats end of line; restore it */
540 --input_line_pointer
;
544 bss_section
->flags
|= SEC_BLOCK
;
546 subseg_set (current_seg
, current_subseg
); /* Restore current seg. */
547 demand_empty_rest_of_line ();
551 stag_add_field_symbols (stag
, path
, base_offset
, rootsym
, root_stag_name
)
556 const char *root_stag_name
;
558 char prefix
[strlen (path
) + 2];
559 struct stag_field
*field
= stag
->field
;
561 /* Construct a symbol for every field contained within this structure
562 including fields within structure fields. */
563 strcpy (prefix
, path
);
565 strcat (prefix
, ".");
567 while (field
!= NULL
)
569 int len
= strlen (prefix
) + strlen (field
->name
) + 2;
570 char *name
= xmalloc (len
);
571 strcpy (name
, prefix
);
572 strcat (name
, field
->name
);
577 sym
= symbol_new (name
, absolute_section
,
578 (field
->stag
? field
->offset
:
579 (valueT
) (base_offset
+ field
->offset
)),
582 symbol_table_insert (sym
);
586 char *replacement
= xmalloc (strlen (name
)
587 + strlen (stag
->name
) + 2);
588 strcpy (replacement
, S_GET_NAME (rootsym
));
589 strcat (replacement
, "+");
590 strcat (replacement
, root_stag_name
);
591 strcat (replacement
, name
+ strlen (S_GET_NAME (rootsym
)));
592 hash_insert (subsym_hash
[0], name
, replacement
);
595 /* Recurse if the field is a structure.
596 Note the field offset is relative to the outermost struct. */
597 if (field
->stag
!= NULL
)
598 stag_add_field_symbols (field
->stag
, name
,
600 rootsym
, root_stag_name
);
605 /* Keep track of stag fields so that when structures are nested we can add the
606 complete dereferencing symbols to the symbol table. */
609 stag_add_field (parent
, name
, offset
, stag
)
615 struct stag_field
*sfield
= xmalloc (sizeof (struct stag_field
));
617 memset (sfield
, 0, sizeof (*sfield
));
618 sfield
->name
= strcpy (xmalloc (strlen (name
) + 1), name
);
619 sfield
->offset
= offset
;
620 sfield
->bitfield_offset
= parent
->current_bitfield_offset
;
622 if (parent
->field
== NULL
)
623 parent
->field
= sfield
;
626 struct stag_field
*sf
= parent
->field
;
627 while (sf
->next
!= NULL
)
631 /* Only create a symbol for this field if the parent has no name. */
632 if (!strncmp (".fake", parent
->name
, 5))
634 symbolS
*sym
= symbol_new (name
, absolute_section
,
635 (valueT
) offset
, &zero_address_frag
);
637 symbol_table_insert (sym
);
641 /* [STAG] .struct [OFFSET]
642 Start defining structure offsets (symbols in absolute section). */
645 tic54x_struct (int arg
)
647 int start_offset
= 0;
652 /* Starting a new struct, switch to absolute section. */
653 stag_saved_seg
= now_seg
;
654 stag_saved_subseg
= now_subseg
;
655 subseg_set (absolute_section
, 0);
657 /* Align the current pointer. */
658 else if (current_stag
->current_bitfield_offset
!= 0)
660 ++abs_section_offset
;
661 current_stag
->current_bitfield_offset
= 0;
664 /* Offset expression is only meaningful for global .structs. */
667 /* Offset is ignored in inner structs. */
669 if (!is_end_of_line
[(int) *input_line_pointer
])
670 start_offset
= get_absolute_expression ();
677 /* Nesting, link to outer one. */
678 current_stag
->inner
= (struct stag
*) xmalloc (sizeof (struct stag
));
679 memset (current_stag
->inner
, 0, sizeof (struct stag
));
680 current_stag
->inner
->outer
= current_stag
;
681 current_stag
= current_stag
->inner
;
683 as_warn (_("Offset on nested structures is ignored"));
684 start_offset
= abs_section_offset
;
688 current_stag
= (struct stag
*) xmalloc (sizeof (struct stag
));
689 memset (current_stag
, 0, sizeof (struct stag
));
690 abs_section_offset
= start_offset
;
692 current_stag
->is_union
= is_union
;
694 if (line_label
== NULL
)
696 static int struct_count
= 0;
697 char fake
[] = ".fake_stagNNNNNNN";
698 sprintf (fake
, ".fake_stag%d", struct_count
++);
699 current_stag
->sym
= symbol_new (fake
, absolute_section
,
700 (valueT
) abs_section_offset
,
705 char label
[strlen (S_GET_NAME (line_label
)) + 1];
706 strcpy (label
, S_GET_NAME (line_label
));
707 current_stag
->sym
= symbol_new (label
, absolute_section
,
708 (valueT
) abs_section_offset
,
711 current_stag
->name
= S_GET_NAME (current_stag
->sym
);
712 SF_SET_LOCAL (current_stag
->sym
);
713 /* Nested .structs don't go into the symbol table. */
714 if (current_stag
->outer
== NULL
)
715 symbol_table_insert (current_stag
->sym
);
720 /* [LABEL] .endstruct
721 finish defining structure offsets; optional LABEL's value will be the size
725 tic54x_endstruct (int is_union
)
729 !strncmp (current_stag
->name
, ".fake", 5) ? "" : current_stag
->name
;
731 if (!current_stag
|| current_stag
->is_union
!= is_union
)
733 as_bad (_(".end%s without preceding .%s"),
734 is_union
? "union" : "struct",
735 is_union
? "union" : "struct");
736 ignore_rest_of_line ();
740 /* Align end of structures. */
741 if (current_stag
->current_bitfield_offset
)
743 ++abs_section_offset
;
744 current_stag
->current_bitfield_offset
= 0;
747 if (current_stag
->is_union
)
748 size
= current_stag
->size
;
750 size
= abs_section_offset
- S_GET_VALUE (current_stag
->sym
);
751 if (line_label
!= NULL
)
753 S_SET_VALUE (line_label
, size
);
754 symbol_table_insert (line_label
);
758 /* Union size has already been calculated. */
759 if (!current_stag
->is_union
)
760 current_stag
->size
= size
;
761 /* Nested .structs don't get put in the stag table. */
762 if (current_stag
->outer
== NULL
)
764 hash_insert (stag_hash
, current_stag
->name
, current_stag
);
765 stag_add_field_symbols (current_stag
, path
,
766 S_GET_VALUE (current_stag
->sym
),
769 current_stag
= current_stag
->outer
;
771 /* If this is a nested .struct/.union, add it as a field to the enclosing
772 one. otherwise, restore the section we were in. */
773 if (current_stag
!= NULL
)
775 stag_add_field (current_stag
, current_stag
->inner
->name
,
776 S_GET_VALUE (current_stag
->inner
->sym
),
777 current_stag
->inner
);
780 subseg_set (stag_saved_seg
, stag_saved_subseg
);
784 Reference a structure within a structure, as a sized field with an optional
786 If used outside of a .struct/.endstruct, overlays the given structure
787 format on the existing allocated space. */
791 int ignore ATTRIBUTE_UNUSED
;
793 char *name
= input_line_pointer
;
794 int c
= get_symbol_end ();
795 struct stag
*stag
= (struct stag
*) hash_find (stag_hash
, name
);
800 as_bad (_("Unrecognized struct/union tag '%s'"), name
);
802 as_bad (_(".tag requires a structure tag"));
803 ignore_rest_of_line ();
806 if (line_label
== NULL
)
808 as_bad (_("Label required for .tag"));
809 ignore_rest_of_line ();
814 char label
[strlen (S_GET_NAME (line_label
)) + 1];
816 strcpy (label
, S_GET_NAME (line_label
));
817 if (current_stag
!= NULL
)
818 stag_add_field (current_stag
, label
,
819 abs_section_offset
- S_GET_VALUE (current_stag
->sym
),
823 symbolS
*sym
= symbol_find (label
);
826 as_bad (_(".tag target '%s' undefined"), label
);
827 ignore_rest_of_line ();
830 stag_add_field_symbols (stag
, S_GET_NAME (sym
),
831 S_GET_VALUE (stag
->sym
), sym
, stag
->name
);
835 /* Bump by the struct size, but only if we're within a .struct section. */
836 if (current_stag
!= NULL
&& !current_stag
->is_union
)
837 abs_section_offset
+= stag
->size
;
839 *input_line_pointer
= c
;
840 demand_empty_rest_of_line ();
844 /* Handle all .byte, .char, .double, .field, .float, .half, .int, .long,
845 .short, .string, .ubyte, .uchar, .uhalf, .uint, .ulong, .ushort, .uword,
849 tic54x_struct_field (int type
)
853 int new_bitfield_offset
= 0;
854 int field_align
= current_stag
->current_bitfield_offset
!= 0;
855 int longword_align
= 0;
858 if (!is_end_of_line
[(int) *input_line_pointer
])
859 count
= get_absolute_expression ();
875 case '*': /* String. */
884 case '.': /* Bitfield. */
886 if (count
< 1 || count
> 32)
888 as_bad (_(".field count '%d' out of range (1 <= X <= 32)"), count
);
889 ignore_rest_of_line ();
892 if (current_stag
->current_bitfield_offset
+ count
> 16)
894 /* Set the appropriate size and new field offset. */
904 new_bitfield_offset
= count
- 16;
908 new_bitfield_offset
= count
;
914 new_bitfield_offset
= current_stag
->current_bitfield_offset
+ count
;
918 as_bad (_("Unrecognized field type '%c'"), type
);
919 ignore_rest_of_line ();
925 /* Align to the actual starting position of the field. */
926 current_stag
->current_bitfield_offset
= 0;
927 ++abs_section_offset
;
929 /* Align to longword boundary. */
930 if (longword_align
&& (abs_section_offset
& 0x1))
931 ++abs_section_offset
;
933 if (line_label
== NULL
)
935 static int fieldno
= 0;
936 char fake
[] = ".fake_fieldNNNNN";
937 sprintf (fake
, ".fake_field%d", fieldno
++);
938 stag_add_field (current_stag
, fake
,
939 abs_section_offset
- S_GET_VALUE (current_stag
->sym
),
944 char label
[strlen (S_GET_NAME (line_label
) + 1)];
945 strcpy (label
, S_GET_NAME (line_label
));
946 stag_add_field (current_stag
, label
,
947 abs_section_offset
- S_GET_VALUE (current_stag
->sym
),
951 if (current_stag
->is_union
)
953 /* Note we treat the element as if it were an array of COUNT. */
954 if (current_stag
->size
< (unsigned) size
* count
)
955 current_stag
->size
= size
* count
;
959 abs_section_offset
+= (unsigned) size
* count
;
960 current_stag
->current_bitfield_offset
= new_bitfield_offset
;
965 /* Handle .byte, .word. .int, .long and all variants. */
967 int emitting_long
= 0;
969 tic54x_cons (int type
)
971 register unsigned int c
;
974 /* If we're within a .struct construct, don't actually allocate space. */
975 if (current_stag
!= NULL
)
977 tic54x_struct_field (type
);
981 #ifdef md_flush_pending_output
982 md_flush_pending_output ();
985 generate_lineno_debug ();
987 /* Align long words to long word boundaries (4 octets). */
988 if (type
== 'l' || type
== 'L')
990 frag_align (2, 0, 2);
991 /* If there's a label, assign it to the first allocated word. */
992 if (line_label
!= NULL
)
994 symbol_set_frag (line_label
, frag_now
);
995 S_SET_VALUE (line_label
, frag_now_fix ());
1019 if (*input_line_pointer
== '"')
1021 input_line_pointer
++;
1022 while (is_a_char (c
= next_char_of_string ()))
1023 tic54x_emit_char (c
);
1024 know (input_line_pointer
[-1] == '\"');
1030 input_line_pointer
= parse_expression (input_line_pointer
, &exp
);
1031 if (exp
.X_op
== O_constant
)
1033 offsetT value
= exp
.X_add_number
;
1034 /* Truncate overflows. */
1038 if ((value
> 0 && value
> 0xFF)
1039 || (value
< 0 && value
< - 0x100))
1040 as_warn ("Overflow in expression, truncated to 8 bits");
1043 if ((value
> 0 && value
> 0xFFFF)
1044 || (value
< 0 && value
< - 0x10000))
1045 as_warn ("Overflow in expression, truncated to 16 bits");
1049 if (exp
.X_op
!= O_constant
&& octets
< 2)
1051 /* Disallow .byte with a non constant expression that will
1052 require relocation. */
1053 as_bad (_("Relocatable values require at least WORD storage"));
1054 ignore_rest_of_line ();
1058 if (exp
.X_op
!= O_constant
1062 /* FIXME -- at one point TI tools used to output REL16
1063 relocations, but I don't think the latest tools do at all
1064 The current tools output extended relocations regardless of
1065 the addresing mode (I actually think that ".c_mode" is
1066 totally ignored in the latest tools). */
1069 emit_expr (&exp
, 4);
1075 emitting_long
= octets
== 4;
1076 emit_expr (&exp
, (octets
== 1) ? 2 : octets
);
1081 while (*input_line_pointer
++ == ',');
1083 input_line_pointer
--; /* Put terminator back into stream. */
1084 demand_empty_rest_of_line ();
1087 /* .global <symbol>[,...,<symbolN>]
1088 .def <symbol>[,...,<symbolN>]
1089 .ref <symbol>[,...,<symbolN>]
1091 These all identify global symbols.
1093 .def means the symbol is defined in the current module and can be accessed
1094 by other files. The symbol should be placed in the symbol table.
1096 .ref means the symbol is used in the current module but defined in another
1097 module. The linker is to resolve this symbol's definition at link time.
1099 .global should act as a .ref or .def, as needed.
1101 global, def and ref all have symbol storage classes of C_EXT.
1103 I can't identify any difference in how the "other" c54x assembler treats
1104 these, so we ignore the type here. */
1107 tic54x_global (type
)
1115 as_warn (_("Use of .def/.ref is deprecated. Use .global instead"));
1117 ILLEGAL_WITHIN_STRUCT ();
1121 name
= input_line_pointer
;
1122 c
= get_symbol_end ();
1123 symbolP
= symbol_find_or_make (name
);
1125 *input_line_pointer
= c
;
1126 S_SET_STORAGE_CLASS (symbolP
, C_EXT
);
1129 input_line_pointer
++;
1130 if (is_end_of_line
[(int) *input_line_pointer
])
1131 c
= *input_line_pointer
;
1136 demand_empty_rest_of_line ();
1139 /* Remove the symbol from the local label hash lookup. */
1142 tic54x_remove_local_label (key
, value
)
1144 PTR value ATTRIBUTE_UNUSED
;
1146 PTR
*elem
= hash_delete (local_label_hash
[macro_level
], key
);
1150 /* Reset all local labels. */
1153 tic54x_clear_local_labels (ignored
)
1154 int ignored ATTRIBUTE_UNUSED
;
1156 hash_traverse (local_label_hash
[macro_level
], tic54x_remove_local_label
);
1161 .sect "section name"
1164 make sure local labels get cleared when changing sections
1166 ARG is 't' for text, 'd' for data, or '*' for a named section
1168 For compatibility, '*' sections have SEC_DATA set instead of SEC_CODE. */
1171 tic54x_sect (int arg
)
1173 ILLEGAL_WITHIN_STRUCT ();
1175 /* Local labels are cleared when changing sections. */
1176 tic54x_clear_local_labels (0);
1180 else if (arg
== 'd')
1186 /* If there are quotes, remove them. */
1187 if (*input_line_pointer
== '"')
1189 name
= demand_copy_C_string (&len
);
1190 demand_empty_rest_of_line ();
1191 name
= strcpy (xmalloc (len
+ 10), name
);
1196 name
= input_line_pointer
;
1197 c
= get_symbol_end ();
1198 name
= strcpy (xmalloc (len
+ 10), name
);
1199 *input_line_pointer
= c
;
1200 demand_empty_rest_of_line ();
1202 /* Make sure all named initialized sections are SEC_DATA. */
1203 strcat (name
, ",\"w\"\n");
1204 input_scrub_insert_line (name
);
1205 obj_coff_section (0);
1207 /* If there was a line label, make sure that it gets assigned the proper
1208 section. This is for compatibility, even though the actual behavior
1209 is not explicitly defined. For consistency, we make .sect behave
1210 like .usect, since that is probably what people expect. */
1211 if (line_label
!= NULL
)
1213 S_SET_SEGMENT (line_label
, now_seg
);
1214 symbol_set_frag (line_label
, frag_now
);
1215 S_SET_VALUE (line_label
, frag_now_fix ());
1216 if (S_GET_STORAGE_CLASS (line_label
) != C_EXT
)
1217 S_SET_STORAGE_CLASS (line_label
, C_LABEL
);
1222 /* [symbol] .space space_in_bits
1223 [symbol] .bes space_in_bits
1224 BES puts the symbol at the *last* word allocated
1226 cribbed from s_space. */
1229 tic54x_space (int arg
)
1235 int bits_per_byte
= (OCTETS_PER_BYTE
* 8);
1237 symbolS
*label
= line_label
;
1240 ILLEGAL_WITHIN_STRUCT ();
1242 #ifdef md_flush_pending_output
1243 md_flush_pending_output ();
1246 /* Read the bit count. */
1249 /* Some expressions are unresolvable until later in the assembly pass;
1250 postpone until relaxation/fixup. we also have to postpone if a previous
1251 partial allocation has not been completed yet. */
1252 if (exp
.X_op
!= O_constant
|| frag_bit_offset (frag_now
, now_seg
) == -1)
1254 struct bit_info
*bi
= xmalloc (sizeof (struct bit_info
));
1260 p
= frag_var (rs_machine_dependent
,
1261 65536 * 2, 1, (relax_substateT
) 0,
1262 make_expr_symbol (&exp
), (offsetT
) 0,
1270 /* Reduce the required size by any bit offsets currently left over
1271 from a previous .space/.bes/.field directive. */
1272 bit_offset
= frag_now
->tc_frag_data
;
1273 if (bit_offset
!= 0 && bit_offset
< 16)
1275 int spare_bits
= bits_per_byte
- bit_offset
;
1276 if (spare_bits
>= exp
.X_add_number
)
1278 /* Don't have to do anything; sufficient bits have already been
1279 allocated; just point the label to the right place. */
1282 symbol_set_frag (label
, frag_now
);
1283 S_SET_VALUE (label
, frag_now_fix () - 1);
1286 frag_now
->tc_frag_data
+= exp
.X_add_number
;
1289 exp
.X_add_number
-= spare_bits
;
1290 /* Set the label to point to the first word allocated, which in this
1291 case is the previous word, which was only partially filled. */
1292 if (!bes
&& label
!= NULL
)
1294 symbol_set_frag (label
, frag_now
);
1295 S_SET_VALUE (label
, frag_now_fix () - 1);
1299 /* Convert bits to bytes/words and octets, rounding up. */
1300 words
= ((exp
.X_add_number
+ bits_per_byte
- 1) / bits_per_byte
);
1301 /* How many do we have left over? */
1302 bit_offset
= exp
.X_add_number
% bits_per_byte
;
1303 octets
= words
* OCTETS_PER_BYTE
;
1306 as_warn (_(".space/.bes repeat count is negative, ignored"));
1309 else if (octets
== 0)
1311 as_warn (_(".space/.bes repeat count is zero, ignored"));
1315 /* If we are in the absolute section, just bump the offset. */
1316 if (now_seg
== absolute_section
)
1318 abs_section_offset
+= words
;
1319 if (bes
&& label
!= NULL
)
1320 S_SET_VALUE (label
, abs_section_offset
- 1);
1321 frag_now
->tc_frag_data
= bit_offset
;
1326 p
= frag_var (rs_fill
, 1, 1,
1327 (relax_substateT
) 0, (symbolS
*) 0,
1328 (offsetT
) octets
, (char *) 0);
1330 /* Make note of how many bits of this word we've allocated so far. */
1331 frag_now
->tc_frag_data
= bit_offset
;
1333 /* .bes puts label at *last* word allocated. */
1334 if (bes
&& label
!= NULL
)
1336 symbol_set_frag (label
, frag_now
);
1337 S_SET_VALUE (label
, frag_now_fix () - 1);
1345 demand_empty_rest_of_line ();
1348 /* [symbol] .usect "section-name", size-in-words
1349 [, [blocking-flag] [, alignment-flag]]
1351 Unitialized section.
1352 Non-zero blocking means that if the section would cross a page (128-word)
1353 boundary, it will be page-aligned.
1354 Non-zero alignment aligns on a longword boundary.
1356 Has no effect on the current section. */
1360 int x ATTRIBUTE_UNUSED
;
1367 int size
, blocking_flag
, alignment_flag
;
1369 subsegT current_subseg
;
1372 ILLEGAL_WITHIN_STRUCT ();
1374 current_seg
= now_seg
; /* Save current seg. */
1375 current_subseg
= now_subseg
; /* Save current subseg. */
1377 if (*input_line_pointer
== '"')
1378 input_line_pointer
++;
1379 section_name
= input_line_pointer
;
1380 c
= get_symbol_end (); /* Get terminator. */
1381 input_line_pointer
++; /* Skip null symbol terminator. */
1382 name
= xmalloc (input_line_pointer
- section_name
+ 1);
1383 strcpy (name
, section_name
);
1385 if (*input_line_pointer
== ',')
1386 ++input_line_pointer
;
1389 as_bad (_("Missing size argument"));
1390 ignore_rest_of_line ();
1394 size
= get_absolute_expression ();
1396 /* Read a possibly present third argument (blocking flag). */
1397 if (*input_line_pointer
== ',')
1399 ++input_line_pointer
;
1400 if (*input_line_pointer
!= ',')
1401 blocking_flag
= get_absolute_expression ();
1405 /* Read a possibly present fourth argument (alignment flag). */
1406 if (*input_line_pointer
== ',')
1408 ++input_line_pointer
;
1409 alignment_flag
= get_absolute_expression ();
1415 blocking_flag
= alignment_flag
= 0;
1417 seg
= subseg_new (name
, 0);
1418 flags
= bfd_get_section_flags (stdoutput
, seg
) | SEC_ALLOC
;
1422 /* s_align eats end of line; restore it. */
1424 --input_line_pointer
;
1427 if (line_label
!= NULL
)
1429 S_SET_SEGMENT (line_label
, seg
);
1430 symbol_set_frag (line_label
, frag_now
);
1431 S_SET_VALUE (line_label
, frag_now_fix ());
1432 /* Set scl to label, since that's what TI does. */
1433 if (S_GET_STORAGE_CLASS (line_label
) != C_EXT
)
1434 S_SET_STORAGE_CLASS (line_label
, C_LABEL
);
1437 seg_info (seg
)->bss
= 1; /* Uninitialized data. */
1439 p
= frag_var (rs_fill
, 1, 1,
1440 (relax_substateT
) 0, (symbolS
*) line_label
,
1441 size
* OCTETS_PER_BYTE
, (char *) 0);
1447 if (!bfd_set_section_flags (stdoutput
, seg
, flags
))
1448 as_warn ("Error setting flags for \"%s\": %s", name
,
1449 bfd_errmsg (bfd_get_error ()));
1451 subseg_set (current_seg
, current_subseg
); /* Restore current seg. */
1452 demand_empty_rest_of_line ();
1455 static enum cpu_version
1456 lookup_version (ver
)
1459 enum cpu_version version
= VNONE
;
1461 if (ver
[0] == '5' && ver
[1] == '4')
1463 if (strlen (ver
) == 3
1464 && (ver
[2] == '1' || ver
[2] == '2' || ver
[2] == '3'
1465 || ver
[2] == '5' || ver
[2] == '8' || ver
[2] == '9'))
1466 version
= ver
[2] - '0';
1467 else if (strlen (ver
) == 5
1468 && TOUPPER (ver
[3]) == 'L'
1469 && TOUPPER (ver
[4]) == 'P'
1470 && (ver
[2] == '5' || ver
[2] == '6'))
1471 version
= ver
[2] - '0' + 10;
1479 enum cpu_version version
;
1482 if (version
== V545LP
|| version
== V546LP
)
1484 symbolS
*symbolP
= symbol_new ("__allow_lp", absolute_section
,
1485 (valueT
) 1, &zero_address_frag
);
1486 SF_SET_LOCAL (symbolP
);
1487 symbol_table_insert (symbolP
);
1491 /* .version cpu-version
1492 cpu-version may be one of the following:
1502 This is for compatibility only. It currently has no affect on assembly. */
1503 static int cpu_needs_set
= 1;
1507 int x ATTRIBUTE_UNUSED
;
1509 enum cpu_version version
= VNONE
;
1510 enum cpu_version old_version
= cpu
;
1514 ILLEGAL_WITHIN_STRUCT ();
1517 ver
= input_line_pointer
;
1518 while (!is_end_of_line
[(int) *input_line_pointer
])
1519 ++input_line_pointer
;
1520 c
= *input_line_pointer
;
1521 *input_line_pointer
= 0;
1523 version
= lookup_version (ver
);
1525 if (cpu
!= VNONE
&& cpu
!= version
)
1526 as_warn (_("CPU version has already been set"));
1528 if (version
== VNONE
)
1530 as_bad (_("Unrecognized version '%s'"), ver
);
1531 ignore_rest_of_line ();
1534 else if (assembly_begun
&& version
!= old_version
)
1536 as_bad (_("Changing of CPU version on the fly not supported"));
1537 ignore_rest_of_line ();
1543 *input_line_pointer
= c
;
1544 demand_empty_rest_of_line ();
1547 /* 'f' = float, 'x' = xfloat, 'd' = double, 'l' = ldouble. */
1550 tic54x_float_cons (int type
)
1552 if (current_stag
!= 0)
1553 tic54x_struct_field ('f');
1555 #ifdef md_flush_pending_output
1556 md_flush_pending_output ();
1559 /* Align to long word boundary (4 octets) unless it's ".xfloat". */
1562 frag_align (2, 0, 2);
1563 /* If there's a label, assign it to the first allocated word. */
1564 if (line_label
!= NULL
)
1566 symbol_set_frag (line_label
, frag_now
);
1567 S_SET_VALUE (line_label
, frag_now_fix ());
1574 /* The argument is capitalized if it should be zero-terminated
1575 's' is normal string with upper 8-bits zero-filled, 'p' is packed.
1576 Code copied from read.c, and slightly modified so that strings are packed
1577 and encoded into the correct octets. */
1580 tic54x_stringer (type
)
1583 register unsigned int c
;
1585 int append_zero
= type
== 'S' || type
== 'P';
1586 int packed
= type
== 'p' || type
== 'P';
1587 int last_char
= -1; /* Packed strings need two bytes at a time to encode. */
1589 if (current_stag
!= NULL
)
1591 tic54x_struct_field ('*');
1595 #ifdef md_flush_pending_output
1596 md_flush_pending_output ();
1599 c
= ','; /* Do loop. */
1603 switch (*input_line_pointer
)
1607 unsigned short value
= get_absolute_expression ();
1608 FRAG_APPEND_1_CHAR ( value
& 0xFF);
1609 FRAG_APPEND_1_CHAR ((value
>> 8) & 0xFF);
1613 ++input_line_pointer
; /* -> 1st char of string. */
1614 start
= input_line_pointer
;
1615 while (is_a_char (c
= next_char_of_string ()))
1619 FRAG_APPEND_1_CHAR (c
);
1620 FRAG_APPEND_1_CHAR (0);
1624 /* Packed strings are filled MS octet first. */
1625 if (last_char
== -1)
1629 FRAG_APPEND_1_CHAR (c
);
1630 FRAG_APPEND_1_CHAR (last_char
);
1637 if (packed
&& last_char
!= -1)
1639 FRAG_APPEND_1_CHAR (0);
1640 FRAG_APPEND_1_CHAR (last_char
);
1645 FRAG_APPEND_1_CHAR (0);
1646 FRAG_APPEND_1_CHAR (0);
1649 know (input_line_pointer
[-1] == '\"');
1653 c
= *input_line_pointer
;
1654 if (!is_end_of_line
[c
])
1655 ++input_line_pointer
;
1658 /* Finish up any leftover packed string. */
1659 if (packed
&& last_char
!= -1)
1661 FRAG_APPEND_1_CHAR (0);
1662 FRAG_APPEND_1_CHAR (last_char
);
1664 demand_empty_rest_of_line ();
1668 tic54x_p2align (arg
)
1669 int arg ATTRIBUTE_UNUSED
;
1671 as_bad (_("p2align not supported on this target"));
1675 tic54x_align_words (arg
)
1678 /* Only ".align" with no argument is allowed within .struct/.union. */
1681 if (!is_end_of_line
[(int) *input_line_pointer
])
1684 as_warn (_("Argument to .even ignored"));
1686 count
= get_absolute_expression ();
1689 if (current_stag
!= NULL
&& arg
== 128)
1691 if (current_stag
->current_bitfield_offset
!= 0)
1693 current_stag
->current_bitfield_offset
= 0;
1694 ++abs_section_offset
;
1696 demand_empty_rest_of_line ();
1700 ILLEGAL_WITHIN_STRUCT ();
1702 s_align_bytes (count
<< 1);
1705 /* Initialize multiple-bit fields withing a single word of memory. */
1708 tic54x_field (ignore
)
1709 int ignore ATTRIBUTE_UNUSED
;
1715 symbolS
*label
= line_label
;
1717 if (current_stag
!= NULL
)
1719 tic54x_struct_field ('.');
1723 input_line_pointer
= parse_expression (input_line_pointer
, &exp
);
1725 if (*input_line_pointer
== ',')
1727 ++input_line_pointer
;
1728 size
= get_absolute_expression ();
1729 if (size
< 1 || size
> 32)
1731 as_bad (_("Invalid field size, must be from 1 to 32"));
1732 ignore_rest_of_line ();
1737 /* Truncate values to the field width. */
1738 if (exp
.X_op
!= O_constant
)
1740 /* If the expression value is relocatable, the field size *must*
1744 as_bad (_("field size must be 16 when value is relocatable"));
1745 ignore_rest_of_line ();
1749 frag_now
->tc_frag_data
= 0;
1750 emit_expr (&exp
, 2);
1754 unsigned long fmask
= (size
== 32) ? 0xFFFFFFFF : (1ul << size
) - 1;
1755 value
= exp
.X_add_number
;
1756 exp
.X_add_number
&= fmask
;
1757 if (value
!= (valueT
) exp
.X_add_number
)
1758 as_warn (_("field value truncated"));
1759 value
= exp
.X_add_number
;
1760 /* Bits are stored MS first. */
1763 frag_now
->tc_frag_data
= 0;
1765 md_number_to_chars (p
, (value
>> (size
- 16)) & 0xFFFF, 2);
1770 int bit_offset
= frag_bit_offset (frag_now
, now_seg
);
1771 fragS
*alloc_frag
= bit_offset_frag (frag_now
, now_seg
);
1772 if (bit_offset
== -1)
1774 struct bit_info
*bi
= xmalloc (sizeof (struct bit_info
));
1775 /* We don't know the previous offset at this time, so store the
1776 info we need and figure it out later. */
1777 expressionS size_exp
;
1778 size_exp
.X_op
= O_constant
;
1779 size_exp
.X_add_number
= size
;
1781 bi
->type
= TYPE_FIELD
;
1783 p
= frag_var (rs_machine_dependent
,
1784 4, 1, (relax_substateT
) 0,
1785 make_expr_symbol (&size_exp
), (offsetT
) 0,
1789 else if (bit_offset
== 0 || bit_offset
+ size
> 16)
1791 /* Align a new field. */
1793 frag_now
->tc_frag_data
= 0;
1794 alloc_frag
= frag_now
;
1798 /* Put the new value entirely within the existing one. */
1799 p
= alloc_frag
== frag_now
?
1800 frag_now
->fr_literal
+ frag_now_fix_octets () - 2 :
1801 alloc_frag
->fr_literal
;
1804 symbol_set_frag (label
, alloc_frag
);
1805 if (alloc_frag
== frag_now
)
1806 S_SET_VALUE (label
, frag_now_fix () - 1);
1810 value
<<= 16 - alloc_frag
->tc_frag_data
- size
;
1812 /* OR in existing value. */
1813 if (alloc_frag
->tc_frag_data
)
1814 value
|= ((unsigned short) p
[1] << 8) | p
[0];
1815 md_number_to_chars (p
, value
, 2);
1816 alloc_frag
->tc_frag_data
+= size
;
1817 if (alloc_frag
->tc_frag_data
== 16)
1818 alloc_frag
->tc_frag_data
= 0;
1822 demand_empty_rest_of_line ();
1825 /* Ideally, we want to check SEC_LOAD and SEC_HAS_CONTENTS, but those aren't
1826 available yet. seg_info ()->bss is the next best thing. */
1829 tic54x_initialized_section (seg
)
1832 return !seg_info (seg
)->bss
;
1835 /* .clink ["section name"]
1837 Marks the section as conditionally linked (link only if contents are
1838 referenced elsewhere.
1839 Without a name, refers to the current initialized section.
1840 Name is required for uninitialized sections. */
1843 tic54x_clink (ignored
)
1844 int ignored ATTRIBUTE_UNUSED
;
1848 ILLEGAL_WITHIN_STRUCT ();
1850 if (*input_line_pointer
== '\"')
1852 char *section_name
= ++input_line_pointer
;
1854 while (is_a_char (next_char_of_string ()))
1856 know (input_line_pointer
[-1] == '\"');
1857 input_line_pointer
[-1] = 0;
1858 name
= xmalloc (input_line_pointer
- section_name
+ 1);
1859 strcpy (name
, section_name
);
1861 seg
= bfd_get_section_by_name (stdoutput
, name
);
1864 as_bad (_("Unrecognized section '%s'"), section_name
);
1865 ignore_rest_of_line ();
1871 if (!tic54x_initialized_section (seg
))
1873 as_bad (_("Current section is unitialized, "
1874 "section name required for .clink"));
1875 ignore_rest_of_line ();
1880 seg
->flags
|= SEC_CLINK
;
1882 demand_empty_rest_of_line ();
1885 /* Change the default include directory to be the current source file's
1886 directory, instead of the current working directory. If DOT is non-zero,
1887 set to "." instead. */
1890 tic54x_set_default_include (dot
)
1901 as_where (&curfile
, &lineno
);
1902 dir
= strcpy (xmalloc (strlen (curfile
) + 1), curfile
);
1903 tmp
= strrchr (dir
, '/');
1910 if (include_dir_count
== 0)
1912 include_dirs
= (char **) xmalloc (sizeof (*include_dirs
));
1913 include_dir_count
= 1;
1915 include_dirs
[0] = dir
;
1916 if (len
> include_dir_maxlen
)
1917 include_dir_maxlen
= len
;
1919 else if (include_dirs
!= NULL
)
1920 include_dirs
[0] = ".";
1923 /* .include "filename" | filename
1924 .copy "filename" | filename
1926 FIXME 'include' file should be omitted from any output listing,
1927 'copy' should be included in any output listing
1928 FIXME -- prevent any included files from changing listing (compat only)
1929 FIXME -- need to include source file directory in search path; what's a
1930 good way to do this?
1932 Entering/exiting included/copied file clears all local labels. */
1935 tic54x_include (ignored
)
1936 int ignored ATTRIBUTE_UNUSED
;
1938 char newblock
[] = " .newblock\n";
1943 ILLEGAL_WITHIN_STRUCT ();
1947 if (*input_line_pointer
== '"')
1949 filename
= demand_copy_C_string (&len
);
1950 demand_empty_rest_of_line ();
1954 filename
= input_line_pointer
;
1955 while (!is_end_of_line
[(int) *input_line_pointer
])
1956 ++input_line_pointer
;
1957 c
= *input_line_pointer
;
1958 *input_line_pointer
= '\0';
1959 filename
= strcpy (xmalloc (strlen (filename
) + 1), filename
);
1960 *input_line_pointer
= c
;
1961 demand_empty_rest_of_line ();
1963 /* Insert a partial line with the filename (for the sake of s_include)
1965 The included file will be inserted before the newblock, so that the
1966 newblock is executed after the included file is processed. */
1967 input
= xmalloc (sizeof (newblock
) + strlen (filename
) + 4);
1968 sprintf (input
, "\"%s\"\n%s", filename
, newblock
);
1969 input_scrub_insert_line (input
);
1971 tic54x_clear_local_labels (0);
1973 tic54x_set_default_include (0);
1979 tic54x_message (type
)
1986 ILLEGAL_WITHIN_STRUCT ();
1988 if (*input_line_pointer
== '"')
1989 msg
= demand_copy_C_string (&len
);
1992 msg
= input_line_pointer
;
1993 while (!is_end_of_line
[(int) *input_line_pointer
])
1994 ++input_line_pointer
;
1995 c
= *input_line_pointer
;
1996 *input_line_pointer
= 0;
1997 msg
= strcpy (xmalloc (strlen (msg
) + 1), msg
);
1998 *input_line_pointer
= c
;
2004 as_tsktsk ("%s", msg
);
2007 as_warn ("%s", msg
);
2014 demand_empty_rest_of_line ();
2018 Define a special symbol that refers to the loadtime address rather than the
2019 runtime address within the current section.
2021 This symbol gets a special storage class so that when it is resolved, it is
2022 resolved relative to the load address (lma) of the section rather than the
2023 run address (vma). */
2026 tic54x_label (ignored
)
2027 int ignored ATTRIBUTE_UNUSED
;
2029 char *name
= input_line_pointer
;
2033 ILLEGAL_WITHIN_STRUCT ();
2035 c
= get_symbol_end ();
2036 symbolP
= colon (name
);
2037 S_SET_STORAGE_CLASS (symbolP
, C_STATLAB
);
2039 *input_line_pointer
= c
;
2040 demand_empty_rest_of_line ();
2044 Install all memory-mapped register names into the symbol table as
2045 absolute local symbols. */
2048 tic54x_mmregs (ignored
)
2049 int ignored ATTRIBUTE_UNUSED
;
2053 ILLEGAL_WITHIN_STRUCT ();
2055 for (sym
= (symbol
*) mmregs
; sym
->name
; sym
++)
2057 symbolS
*symbolP
= symbol_new (sym
->name
, absolute_section
,
2058 (valueT
) sym
->value
, &zero_address_frag
);
2059 SF_SET_LOCAL (symbolP
);
2060 symbol_table_insert (symbolP
);
2065 Count defaults to 1024. */
2068 tic54x_loop (int count
)
2070 ILLEGAL_WITHIN_STRUCT ();
2073 if (!is_end_of_line
[(int) *input_line_pointer
])
2074 count
= get_absolute_expression ();
2076 do_repeat (count
, "LOOP", "ENDLOOP");
2079 /* Normally, endloop gets eaten by the preceding loop. */
2082 tic54x_endloop (ignore
)
2083 int ignore ATTRIBUTE_UNUSED
;
2085 as_bad (_("ENDLOOP without corresponding LOOP"));
2086 ignore_rest_of_line ();
2089 /* .break [condition]. */
2092 tic54x_break (ignore
)
2093 int ignore ATTRIBUTE_UNUSED
;
2097 ILLEGAL_WITHIN_STRUCT ();
2100 if (!is_end_of_line
[(int) *input_line_pointer
])
2101 cond
= get_absolute_expression ();
2104 end_repeat (substitution_line
? 1 : 0);
2108 set_address_mode (mode
)
2112 if (mode
== far_mode
)
2114 symbolS
*symbolP
= symbol_new ("__allow_far", absolute_section
,
2115 (valueT
) 1, &zero_address_frag
);
2116 SF_SET_LOCAL (symbolP
);
2117 symbol_table_insert (symbolP
);
2121 static int address_mode_needs_set
= 1;
2123 tic54x_address_mode (mode
)
2126 if (assembly_begun
&& amode
!= (unsigned) mode
)
2128 as_bad (_("Mixing of normal and extended addressing not supported"));
2129 ignore_rest_of_line ();
2132 if (mode
== far_mode
&& cpu
!= VNONE
&& cpu
!= V548
&& cpu
!= V549
)
2134 as_bad (_("Extended addressing not supported on the specified CPU"));
2135 ignore_rest_of_line ();
2139 set_address_mode (mode
);
2140 demand_empty_rest_of_line ();
2143 /* .sblock "section"|section [,...,"section"|section]
2144 Designate initialized sections for blocking. */
2147 tic54x_sblock (ignore
)
2148 int ignore ATTRIBUTE_UNUSED
;
2152 ILLEGAL_WITHIN_STRUCT ();
2159 if (*input_line_pointer
== '"')
2162 name
= demand_copy_C_string (&len
);
2166 char *section_name
= input_line_pointer
;
2167 c
= get_symbol_end ();
2168 name
= xmalloc (strlen (section_name
) + 1);
2169 strcpy (name
, section_name
);
2170 *input_line_pointer
= c
;
2173 seg
= bfd_get_section_by_name (stdoutput
, name
);
2176 as_bad (_("Unrecognized section '%s'"), name
);
2177 ignore_rest_of_line ();
2180 else if (!tic54x_initialized_section (seg
))
2182 as_bad (_(".sblock may be used for initialized sections only"));
2183 ignore_rest_of_line ();
2186 seg
->flags
|= SEC_BLOCK
;
2188 c
= *input_line_pointer
;
2189 if (!is_end_of_line
[(int) c
])
2190 ++input_line_pointer
;
2193 demand_empty_rest_of_line ();
2196 /* symbol .set value
2199 value must be defined externals; no forward-referencing allowed
2200 symbols assigned with .set/.equ may not be redefined. */
2204 int ignore ATTRIBUTE_UNUSED
;
2209 ILLEGAL_WITHIN_STRUCT ();
2213 as_bad (_("Symbol missing for .set/.equ"));
2214 ignore_rest_of_line ();
2217 name
= xstrdup (S_GET_NAME (line_label
));
2219 if ((symbolP
= symbol_find (name
)) == NULL
2220 && (symbolP
= md_undefined_symbol (name
)) == NULL
)
2222 symbolP
= symbol_new (name
, absolute_section
, 0, &zero_address_frag
);
2223 S_SET_STORAGE_CLASS (symbolP
, C_STAT
);
2226 S_SET_DATA_TYPE (symbolP
, T_INT
);
2227 S_SET_SEGMENT (symbolP
, absolute_section
);
2228 symbol_table_insert (symbolP
);
2229 pseudo_set (symbolP
);
2230 demand_empty_rest_of_line ();
2235 List false conditional blocks. */
2238 tic54x_fclist (int show
)
2241 listing
&= ~LISTING_NOCOND
;
2243 listing
|= LISTING_NOCOND
;
2244 demand_empty_rest_of_line ();
2248 tic54x_sslist (int show
)
2250 ILLEGAL_WITHIN_STRUCT ();
2252 listing_sslist
= show
;
2255 /* .var SYM[,...,SYMN]
2256 Define a substitution string to be local to a macro. */
2260 int ignore ATTRIBUTE_UNUSED
;
2262 static char empty
[] = "";
2266 ILLEGAL_WITHIN_STRUCT ();
2268 if (macro_level
== 0)
2270 as_bad (_(".var may only be used within a macro definition"));
2271 ignore_rest_of_line ();
2276 if (!ISALPHA (*input_line_pointer
))
2278 as_bad (_("Substitution symbols must begin with a letter"));
2279 ignore_rest_of_line ();
2282 name
= input_line_pointer
;
2283 c
= get_symbol_end ();
2284 /* .var symbols start out with a null string. */
2285 name
= strcpy (xmalloc (strlen (name
) + 1), name
);
2286 hash_insert (subsym_hash
[macro_level
], name
, empty
);
2287 *input_line_pointer
= c
;
2290 ++input_line_pointer
;
2291 if (is_end_of_line
[(int) *input_line_pointer
])
2292 c
= *input_line_pointer
;
2297 demand_empty_rest_of_line ();
2300 /* .mlib <macro library filename>
2302 Macro libraries are archived (standard AR-format) text macro definitions
2303 Expand the file and include it.
2305 FIXME need to try the source file directory as well. */
2308 tic54x_mlib (ignore
)
2309 int ignore ATTRIBUTE_UNUSED
;
2316 ILLEGAL_WITHIN_STRUCT ();
2318 /* Parse the filename. */
2319 if (*input_line_pointer
== '"')
2321 if ((filename
= demand_copy_C_string (&len
)) == NULL
)
2328 while (!is_end_of_line
[(int) *input_line_pointer
]
2329 && !ISSPACE (*input_line_pointer
))
2331 obstack_1grow (¬es
, *input_line_pointer
);
2332 ++input_line_pointer
;
2335 obstack_1grow (¬es
, '\0');
2336 filename
= obstack_finish (¬es
);
2338 demand_empty_rest_of_line ();
2340 tic54x_set_default_include (0);
2341 path
= xmalloc ((unsigned long) len
+ include_dir_maxlen
+ 5);
2342 for (i
= 0; i
< include_dir_count
; i
++)
2345 strcpy (path
, include_dirs
[i
]);
2347 strcat (path
, filename
);
2348 if ((try = fopen (path
, "r")) != NULL
)
2354 if (i
>= include_dir_count
)
2360 /* FIXME: if path is found, malloc'd storage is not freed. Of course, this
2361 happens all over the place, and since the assembler doesn't usually keep
2362 running for a very long time, it really doesn't matter. */
2363 register_dependency (path
);
2365 /* Expand all archive entries to temporary files and include them. */
2366 abfd
= bfd_openr (path
, NULL
);
2369 as_bad (_("Can't open macro library file '%s' for reading."), path
);
2370 as_perror ("%s", path
);
2371 ignore_rest_of_line ();
2374 if (!bfd_check_format (abfd
, bfd_archive
))
2376 as_bad (_("File '%s' not in macro archive format"), path
);
2377 ignore_rest_of_line ();
2381 /* Open each BFD as binary (it should be straight ASCII text). */
2382 for (mbfd
= bfd_openr_next_archived_file (abfd
, NULL
);
2383 mbfd
!= NULL
; mbfd
= bfd_openr_next_archived_file (abfd
, mbfd
))
2385 /* Get a size at least as big as the archive member. */
2386 bfd_size_type size
= bfd_get_size (mbfd
);
2387 char *buf
= xmalloc (size
);
2388 char *fname
= tmpnam (NULL
);
2391 /* We're not sure how big it is, but it will be smaller than "size". */
2392 bfd_bread (buf
, size
, mbfd
);
2394 /* Write to a temporary file, then use s_include to include it
2396 ftmp
= fopen (fname
, "w+b");
2397 fwrite ((void *) buf
, size
, 1, ftmp
);
2398 if (buf
[size
- 1] != '\n')
2399 fwrite ("\n", 1, 1, ftmp
);
2402 input_scrub_insert_file (fname
);
2407 const pseudo_typeS md_pseudo_table
[] =
2409 { "algebraic", s_ignore
, 0 },
2410 { "align" , tic54x_align_words
, 128 },
2411 { "even" , tic54x_align_words
, 2 },
2412 { "asg" , tic54x_asg
, 0 },
2413 { "eval" , tic54x_eval
, 0 },
2414 { "bss" , tic54x_bss
, 0 },
2415 { "byte" , tic54x_cons
, 'b' },
2416 { "ubyte" , tic54x_cons
, 'B' },
2417 { "char" , tic54x_cons
, 'c' },
2418 { "uchar" , tic54x_cons
, 'C' },
2419 { "clink" , tic54x_clink
, 0 },
2420 { "c_mode" , tic54x_address_mode
, c_mode
},
2421 { "copy" , tic54x_include
, 'c' },
2422 { "include" , tic54x_include
, 'i' },
2423 { "data" , tic54x_sect
, 'd' },
2424 { "double" , tic54x_float_cons
, 'd' },
2425 { "ldouble" , tic54x_float_cons
, 'l' },
2426 { "drlist" , s_ignore
, 0 },
2427 { "drnolist" , s_ignore
, 0 },
2428 { "emsg" , tic54x_message
, 'e' },
2429 { "mmsg" , tic54x_message
, 'm' },
2430 { "wmsg" , tic54x_message
, 'w' },
2432 { "end" , s_end
, 0 },
2434 { "far_mode" , tic54x_address_mode
, far_mode
},
2435 { "fclist" , tic54x_fclist
, 1 },
2436 { "fcnolist" , tic54x_fclist
, 0 },
2437 { "field" , tic54x_field
, -1 },
2438 { "float" , tic54x_float_cons
, 'f' },
2439 { "xfloat" , tic54x_float_cons
, 'x' },
2440 { "global" , tic54x_global
, 'g' },
2441 { "def" , tic54x_global
, 'd' },
2442 { "ref" , tic54x_global
, 'r' },
2443 { "half" , tic54x_cons
, 'h' },
2444 { "uhalf" , tic54x_cons
, 'H' },
2445 { "short" , tic54x_cons
, 's' },
2446 { "ushort" , tic54x_cons
, 'S' },
2447 { "if" , s_if
, (int) O_ne
},
2448 { "elseif" , s_elseif
, (int) O_ne
},
2449 { "else" , s_else
, 0 },
2450 { "endif" , s_endif
, 0 },
2451 { "int" , tic54x_cons
, 'i' },
2452 { "uint" , tic54x_cons
, 'I' },
2453 { "word" , tic54x_cons
, 'w' },
2454 { "uword" , tic54x_cons
, 'W' },
2455 { "label" , tic54x_label
, 0 }, /* Loadtime
2457 { "length" , s_ignore
, 0 },
2458 { "width" , s_ignore
, 0 },
2460 { "list" , listing_list
, 1 },
2461 { "nolist" , listing_list
, 0 },
2463 { "long" , tic54x_cons
, 'l' },
2464 { "ulong" , tic54x_cons
, 'L' },
2465 { "xlong" , tic54x_cons
, 'x' },
2466 { "loop" , tic54x_loop
, 1024 },
2467 { "break" , tic54x_break
, 0 },
2468 { "endloop" , tic54x_endloop
, 0 },
2469 { "mlib" , tic54x_mlib
, 0 },
2470 { "mlist" , s_ignore
, 0 },
2471 { "mnolist" , s_ignore
, 0 },
2472 { "mmregs" , tic54x_mmregs
, 0 },
2473 { "newblock" , tic54x_clear_local_labels
, 0 },
2474 { "option" , s_ignore
, 0 },
2475 { "p2align" , tic54x_p2align
, 0 },
2477 { "page" , listing_eject
, 0 },
2479 { "sblock" , tic54x_sblock
, 0 },
2480 { "sect" , tic54x_sect
, '*' },
2481 { "set" , tic54x_set
, 0 },
2482 { "equ" , tic54x_set
, 0 },
2483 { "space" , tic54x_space
, 0 },
2484 { "bes" , tic54x_space
, 1 },
2485 { "sslist" , tic54x_sslist
, 1 },
2486 { "ssnolist" , tic54x_sslist
, 0 },
2487 { "string" , tic54x_stringer
, 's' },
2488 { "pstring" , tic54x_stringer
, 'p' },
2489 { "struct" , tic54x_struct
, 0 },
2490 { "tag" , tic54x_tag
, 0 },
2491 { "endstruct", tic54x_endstruct
, 0 },
2492 { "tab" , s_ignore
, 0 },
2493 { "text" , tic54x_sect
, 't' },
2495 { "title" , listing_title
, 0 },
2497 { "union" , tic54x_struct
, 1 },
2498 { "endunion" , tic54x_endstruct
, 1 },
2499 { "usect" , tic54x_usect
, 0 },
2500 { "var" , tic54x_var
, 0 },
2501 { "version" , tic54x_version
, 0 },
2506 /* For debugging, strings for each operand type. */
2507 static const char *optypes
[] =
2509 "none", "Xmem", "Ymem", "pmad", "dmad", "Smem", "Lmem", "MMR", "PA",
2510 "Sind", "xpmad", "xpmad+", "MMRX", "MMRY",
2511 "SRC1", "SRC", "RND", "DST",
2514 "B", "A", "lk", "TS", "k8", "16", "BITC", "CC", "CC2", "CC3", "123", "031",
2515 "k5", "k8u", "ASM", "T", "DP", "ARP", "k3", "lku", "N", "SBIT", "12",
2521 md_parse_option (c
, arg
)
2529 case OPTION_COFF_VERSION
:
2531 int version
= atoi (arg
);
2532 if (version
!= 0 && version
!= 1 && version
!= 2)
2533 as_fatal (_("Bad COFF version '%s'"), arg
);
2534 /* FIXME -- not yet implemented. */
2537 case OPTION_CPU_VERSION
:
2539 cpu
= lookup_version (arg
);
2542 as_fatal (_("Bad CPU version '%s'"), arg
);
2545 case OPTION_ADDRESS_MODE
:
2547 address_mode_needs_set
= 1;
2549 case OPTION_STDERR_TO_FILE
:
2551 char *filename
= arg
;
2552 FILE *fp
= fopen (filename
, "w+");
2554 as_fatal (_("Can't redirect stderr to the file '%s'"), filename
);
2556 if ((fp
= freopen (filename
, "w+", stderr
)) == NULL
)
2557 as_fatal (_("Can't redirect stderr to the file '%s'"), filename
);
2565 /* Create a "local" substitution string hash table for a new macro level
2566 Some docs imply that macros have to use .newblock in order to be able
2567 to re-use a local label. We effectively do an automatic .newblock by
2568 deleting the local label hash between macro invocations. */
2571 tic54x_macro_start ()
2574 subsym_hash
[macro_level
] = hash_new ();
2575 local_label_hash
[macro_level
] = hash_new ();
2579 tic54x_macro_info (info
)
2582 struct formal_struct
2584 struct formal_struct
*next
; /* Next formal in list */
2585 sb name
; /* Name of the formal */
2586 sb def
; /* The default value */
2587 sb actual
; /* The actual argument (changed on
2589 int index
; /* The index of the formal
2590 0 .. formal_count - 1 */
2594 sb sub
; /* Substitution text. */
2595 int formal_count
; /* Number of formal args. */
2596 struct formal_struct
*formals
; /* Pointer to list of
2598 struct hash_control
*formal_hash
; /* Hash table of formals. */
2601 macro
= (struct macro_struct
*) info
;
2603 /* Put the formal args into the substitution symbol table. */
2604 for (entry
= macro
->formals
; entry
; entry
= entry
->next
)
2606 char *name
= strncpy (xmalloc (entry
->name
.len
+ 1),
2607 entry
->name
.ptr
, entry
->name
.len
);
2608 char *value
= strncpy (xmalloc (entry
->actual
.len
+ 1),
2609 entry
->actual
.ptr
, entry
->actual
.len
);
2610 name
[entry
->name
.len
] = '\0';
2611 value
[entry
->actual
.len
] = '\0';
2612 hash_insert (subsym_hash
[macro_level
], name
, value
);
2616 /* Get rid of this macro's .var's, arguments, and local labels. */
2621 hash_die (subsym_hash
[macro_level
]);
2622 subsym_hash
[macro_level
] = NULL
;
2623 hash_die (local_label_hash
[macro_level
]);
2624 local_label_hash
[macro_level
] = NULL
;
2629 subsym_symlen (a
, ignore
)
2631 char *ignore ATTRIBUTE_UNUSED
;
2636 /* Compare symbol A to string B. */
2639 subsym_symcmp (a
, b
)
2643 return strcmp (a
, b
);
2646 /* Return the index of the first occurence of B in A, or zero if none
2647 assumes b is an integer char value as a string. Index is one-based. */
2650 subsym_firstch (a
, b
)
2655 char *tmp
= strchr (a
, val
);
2657 return tmp
? tmp
- a
+ 1 : 0;
2660 /* Similar to firstch, but returns index of last occurrence of B in A. */
2663 subsym_lastch (a
, b
)
2668 char *tmp
= strrchr (a
, val
);
2670 return tmp
? tmp
- a
+ 1 : 0;
2673 /* Returns 1 if string A is defined in the symbol table (NOT the substitution
2677 subsym_isdefed (a
, ignore
)
2679 char *ignore ATTRIBUTE_UNUSED
;
2681 symbolS
*symbolP
= symbol_find (a
);
2683 return symbolP
!= NULL
;
2686 /* Assign first member of comma-separated list B (e.g. "1,2,3") to the symbol
2687 A, or zero if B is a null string. Both arguments *must* be substitution
2688 symbols, unsubstituted. */
2691 subsym_ismember (sym
, list
)
2695 char *elem
, *ptr
, *listv
;
2700 listv
= subsym_lookup (list
, macro_level
);
2703 as_bad (_("Undefined substitution symbol '%s'"), list
);
2704 ignore_rest_of_line ();
2708 ptr
= elem
= xmalloc (strlen (listv
) + 1);
2709 strcpy (elem
, listv
);
2710 while (*ptr
&& *ptr
!= ',')
2714 subsym_create_or_replace (sym
, elem
);
2716 /* Reassign the list. */
2717 subsym_create_or_replace (list
, ptr
);
2719 /* Assume this value, docs aren't clear. */
2723 /* Return zero if not a constant; otherwise:
2731 subsym_iscons (a
, ignore
)
2733 char *ignore ATTRIBUTE_UNUSED
;
2737 parse_expression (a
, &exp
);
2739 if (exp
.X_op
== O_constant
)
2741 int len
= strlen (a
);
2743 switch (TOUPPER (a
[len
- 1]))
2756 /* No suffix; either octal, hex, or decimal. */
2757 if (*a
== '0' && len
> 1)
2759 if (TOUPPER (a
[1]) == 'X')
2769 /* Return 1 if A is a valid symbol name. Expects string input. */
2772 subsym_isname (a
, ignore
)
2774 char *ignore ATTRIBUTE_UNUSED
;
2776 if (!is_name_beginner (*a
))
2780 if (!is_part_of_name (*a
))
2787 /* Return whether the string is a register; accepts ar0-7, unless .mmregs has
2788 been seen; if so, recognize any memory-mapped register.
2789 Note this does not recognize "A" or "B" accumulators. */
2792 subsym_isreg (a
, ignore
)
2794 char *ignore ATTRIBUTE_UNUSED
;
2796 if (hash_find (reg_hash
, a
))
2798 if (hash_find (mmreg_hash
, a
))
2803 /* Return the structrure size, given the stag. */
2806 subsym_structsz (name
, ignore
)
2808 char *ignore ATTRIBUTE_UNUSED
;
2810 struct stag
*stag
= (struct stag
*) hash_find (stag_hash
, name
);
2817 /* If anybody actually uses this, they can fix it :)
2818 FIXME I'm not sure what the "reference point" of a structure is. It might
2819 be either the initial offset given .struct, or it may be the offset of the
2820 structure within another structure, or it might be something else
2821 altogether. since the TI assembler doesn't seem to ever do anything but
2822 return zero, we punt and return zero. */
2825 subsym_structacc (stag_name
, ignore
)
2826 char *stag_name ATTRIBUTE_UNUSED
;
2827 char *ignore ATTRIBUTE_UNUSED
;
2833 math_ceil (arg1
, ignore
)
2835 float ignore ATTRIBUTE_UNUSED
;
2837 return (float) ceil (arg1
);
2841 math_cvi (arg1
, ignore
)
2843 float ignore ATTRIBUTE_UNUSED
;
2849 math_floor (arg1
, ignore
)
2851 float ignore ATTRIBUTE_UNUSED
;
2853 return (float) floor (arg1
);
2857 math_fmod (float arg1
, float arg2
)
2859 return (int) arg1
% (int) arg2
;
2863 math_int (arg1
, ignore
)
2865 float ignore ATTRIBUTE_UNUSED
;
2867 return ((float) ((int) arg1
)) == arg1
;
2871 math_round (arg1
, ignore
)
2873 float ignore ATTRIBUTE_UNUSED
;
2875 return arg1
> 0 ? (int) (arg1
+ 0.5) : (int) (arg1
- 0.5);
2879 math_sgn (arg1
, ignore
)
2881 float ignore ATTRIBUTE_UNUSED
;
2883 return (arg1
< 0) ? -1 : (arg1
? 1 : 0);
2887 math_trunc (arg1
, ignore
)
2889 float ignore ATTRIBUTE_UNUSED
;
2895 math_acos (arg1
, ignore
)
2897 float ignore ATTRIBUTE_UNUSED
;
2899 return (float) acos (arg1
);
2903 math_asin (arg1
, ignore
)
2905 float ignore ATTRIBUTE_UNUSED
;
2907 return (float) asin (arg1
);
2911 math_atan (arg1
, ignore
)
2913 float ignore ATTRIBUTE_UNUSED
;
2915 return (float) atan (arg1
);
2919 math_atan2 (float arg1
, float arg2
)
2921 return (float) atan2 (arg1
, arg2
);
2925 math_cosh (arg1
, ignore
)
2927 float ignore ATTRIBUTE_UNUSED
;
2929 return (float) cosh (arg1
);
2933 math_cos (arg1
, ignore
)
2935 float ignore ATTRIBUTE_UNUSED
;
2937 return (float) cos (arg1
);
2941 math_cvf (arg1
, ignore
)
2943 float ignore ATTRIBUTE_UNUSED
;
2945 return (float) arg1
;
2949 math_exp (arg1
, ignore
)
2951 float ignore ATTRIBUTE_UNUSED
;
2953 return (float) exp (arg1
);
2957 math_fabs (arg1
, ignore
)
2959 float ignore ATTRIBUTE_UNUSED
;
2961 return (float) fabs (arg1
);
2964 /* expr1 * 2^expr2. */
2967 math_ldexp (float arg1
, float arg2
)
2969 return arg1
* (float) pow (2.0, arg2
);
2973 math_log10 (arg1
, ignore
)
2975 float ignore ATTRIBUTE_UNUSED
;
2977 return (float) log10 (arg1
);
2981 math_log (arg1
, ignore
)
2983 float ignore ATTRIBUTE_UNUSED
;
2985 return (float) log (arg1
);
2989 math_max (float arg1
, float arg2
)
2991 return (arg1
> arg2
) ? arg1
: arg2
;
2995 math_min (float arg1
, float arg2
)
2997 return (arg1
< arg2
) ? arg1
: arg2
;
3001 math_pow (float arg1
, float arg2
)
3003 return (float) pow (arg1
, arg2
);
3007 math_sin (arg1
, ignore
)
3009 float ignore ATTRIBUTE_UNUSED
;
3011 return (float) sin (arg1
);
3015 math_sinh (arg1
, ignore
)
3017 float ignore ATTRIBUTE_UNUSED
;
3019 return (float) sinh (arg1
);
3023 math_sqrt (arg1
, ignore
)
3025 float ignore ATTRIBUTE_UNUSED
;
3027 return (float) sqrt (arg1
);
3031 math_tan (arg1
, ignore
)
3033 float ignore ATTRIBUTE_UNUSED
;
3035 return (float) tan (arg1
);
3039 math_tanh (arg1
, ignore
)
3041 float ignore ATTRIBUTE_UNUSED
;
3043 return (float) tanh (arg1
);
3046 /* Built-in substitution symbol functions and math functions. */
3050 int (*proc
) (char *, char *);
3052 } subsym_proc_entry
;
3054 static const subsym_proc_entry subsym_procs
[] =
3056 /* Assembler built-in string substitution functions. */
3057 { "$symlen", subsym_symlen
, 1, },
3058 { "$symcmp", subsym_symcmp
, 2, },
3059 { "$firstch", subsym_firstch
, 2, },
3060 { "$lastch", subsym_lastch
, 2, },
3061 { "$isdefed", subsym_isdefed
, 1, },
3062 { "$ismember", subsym_ismember
, 2, },
3063 { "$iscons", subsym_iscons
, 1, },
3064 { "$isname", subsym_isname
, 1, },
3065 { "$isreg", subsym_isreg
, 1, },
3066 { "$structsz", subsym_structsz
, 1, },
3067 { "$structacc", subsym_structacc
, 1, },
3074 float (*proc
) (float, float);
3079 static const math_proc_entry math_procs
[] =
3081 /* Integer-returning built-in math functions. */
3082 { "$cvi", math_cvi
, 1, 1 },
3083 { "$int", math_int
, 1, 1 },
3084 { "$sgn", math_sgn
, 1, 1 },
3086 /* Float-returning built-in math functions. */
3087 { "$acos", math_acos
, 1, 0 },
3088 { "$asin", math_asin
, 1, 0 },
3089 { "$atan", math_atan
, 1, 0 },
3090 { "$atan2", math_atan2
, 2, 0 },
3091 { "$ceil", math_ceil
, 1, 0 },
3092 { "$cosh", math_cosh
, 1, 0 },
3093 { "$cos", math_cos
, 1, 0 },
3094 { "$cvf", math_cvf
, 1, 0 },
3095 { "$exp", math_exp
, 1, 0 },
3096 { "$fabs", math_fabs
, 1, 0 },
3097 { "$floor", math_floor
, 1, 0 },
3098 { "$fmod", math_fmod
, 2, 0 },
3099 { "$ldexp", math_ldexp
, 2, 0 },
3100 { "$log10", math_log10
, 1, 0 },
3101 { "$log", math_log
, 1, 0 },
3102 { "$max", math_max
, 2, 0 },
3103 { "$min", math_min
, 2, 0 },
3104 { "$pow", math_pow
, 2, 0 },
3105 { "$round", math_round
, 1, 0 },
3106 { "$sin", math_sin
, 1, 0 },
3107 { "$sinh", math_sinh
, 1, 0 },
3108 { "$sqrt", math_sqrt
, 1, 0 },
3109 { "$tan", math_tan
, 1, 0 },
3110 { "$tanh", math_tanh
, 1, 0 },
3111 { "$trunc", math_trunc
, 1, 0 },
3112 { NULL
, NULL
, 0, 0 },
3119 partemplate
*paropcode
;
3121 const subsym_proc_entry
*subsym_proc
;
3122 const math_proc_entry
*math_proc
;
3123 const char *hash_err
;
3125 char *TIC54X_DIR
= getenv ("TIC54X_DIR");
3126 char *A_DIR
= TIC54X_DIR
? TIC54X_DIR
: getenv ("A_DIR");
3130 /* Look for A_DIR and add it to the include list. a */
3133 char *tmp
= xstrdup (A_DIR
);
3136 char *next
= strchr (tmp
, ';');
3139 add_include_dir (tmp
);
3142 while (tmp
!= NULL
);
3145 op_hash
= hash_new ();
3146 for (opcode
= (template *) tic54x_optab
; opcode
->name
; opcode
++)
3148 if (hash_find (op_hash
, opcode
->name
))
3150 hash_err
= hash_insert (op_hash
, opcode
->name
, (char *) opcode
);
3152 as_fatal ("Internal Error: Can't hash %s: %s",
3153 opcode
->name
, hash_err
);
3155 parop_hash
= hash_new ();
3156 for (paropcode
= (partemplate
*) tic54x_paroptab
;
3160 if (hash_find (parop_hash
, paropcode
->name
))
3162 hash_err
= hash_insert (parop_hash
, paropcode
->name
, (char *) paropcode
);
3164 as_fatal ("Internal Error: Can't hash %s: %s",
3165 paropcode
->name
, hash_err
);
3167 reg_hash
= hash_new ();
3168 for (sym
= (symbol
*) regs
; sym
->name
; sym
++)
3170 /* Add basic registers to the symbol table. */
3171 symbolS
*symbolP
= symbol_new (sym
->name
, absolute_section
,
3172 (valueT
) sym
->value
, &zero_address_frag
);
3173 SF_SET_LOCAL (symbolP
);
3174 symbol_table_insert (symbolP
);
3175 hash_err
= hash_insert (reg_hash
, sym
->name
, (char *) sym
);
3177 for (sym
= (symbol
*) mmregs
; sym
->name
; sym
++)
3178 hash_err
= hash_insert (reg_hash
, sym
->name
, (char *) sym
);
3179 mmreg_hash
= hash_new ();
3180 for (sym
= (symbol
*) mmregs
; sym
->name
; sym
++)
3182 hash_err
= hash_insert (mmreg_hash
, sym
->name
, (char *) sym
);
3184 cc_hash
= hash_new ();
3185 for (sym
= (symbol
*) condition_codes
; sym
->name
; sym
++)
3187 hash_err
= hash_insert (cc_hash
, sym
->name
, (char *) sym
);
3189 cc2_hash
= hash_new ();
3190 for (sym
= (symbol
*) cc2_codes
; sym
->name
; sym
++)
3192 hash_err
= hash_insert (cc2_hash
, sym
->name
, (char *) sym
);
3194 cc3_hash
= hash_new ();
3195 for (sym
= (symbol
*) cc3_codes
; sym
->name
; sym
++)
3197 hash_err
= hash_insert (cc3_hash
, sym
->name
, (char *) sym
);
3199 sbit_hash
= hash_new ();
3200 for (sym
= (symbol
*) status_bits
; sym
->name
; sym
++)
3202 hash_err
= hash_insert (sbit_hash
, sym
->name
, (char *) sym
);
3204 misc_symbol_hash
= hash_new ();
3205 for (symname
= (char **) misc_symbols
; *symname
; symname
++)
3207 hash_err
= hash_insert (misc_symbol_hash
, *symname
, *symname
);
3209 /* Only the base substitution table and local label table are initialized;
3210 the others (for local macro substitution) get instantiated as needed. */
3211 local_label_hash
[0] = hash_new ();
3212 subsym_hash
[0] = hash_new ();
3213 for (subsym_proc
= subsym_procs
; subsym_proc
->name
; subsym_proc
++)
3215 hash_err
= hash_insert (subsym_hash
[0], subsym_proc
->name
,
3216 (char *) subsym_proc
);
3218 math_hash
= hash_new ();
3219 for (math_proc
= math_procs
; math_proc
->name
; math_proc
++)
3221 /* Insert into the main subsym hash for recognition; insert into
3222 the math hash to actually store information. */
3223 hash_err
= hash_insert (subsym_hash
[0], math_proc
->name
,
3224 (char *) math_proc
);
3225 hash_err
= hash_insert (math_hash
, math_proc
->name
,
3226 (char *) math_proc
);
3228 subsym_recurse_hash
= hash_new ();
3229 stag_hash
= hash_new ();
3232 typedef struct _tic54x_insn
3234 const template *tm
; /* Opcode template. */
3235 const partemplate
*ptm
; /* Parallel opcode template. */
3237 char mnemonic
[MAX_LINE
]; /* Opcode name/mnemonic. */
3238 char parmnemonic
[MAX_LINE
]; /* 2nd mnemonic of parallel insn. */
3246 } operands
[MAX_OPERANDS
];
3249 struct opstruct paroperands
[MAX_OPERANDS
];
3253 int words
; /* Size of insn in 16-bit words. */
3254 int using_default_dst
; /* Do we need to explicitly set an
3255 omitted OP_DST operand? */
3258 unsigned short word
; /* Final encoded opcode data. */
3260 int r_nchars
; /* Relocation size. */
3261 bfd_reloc_code_real_type r_type
; /* Relocation type. */
3262 expressionS addr_expr
; /* Storage for unresolved expressions. */
3266 static int encode_operand (tic54x_insn
*, enum optype
, struct opstruct
*);
3267 static int encode_dmad (tic54x_insn
*, struct opstruct
*, int);
3268 static int operands_match (tic54x_insn
*, struct opstruct
*, int,
3269 const enum optype
*, int, int);
3270 static int encode_address (tic54x_insn
*, struct opstruct
*);
3273 is_accumulator (operand
)
3274 struct opstruct
*operand
;
3276 return strcasecmp (operand
->buf
, "a") == 0
3277 || strcasecmp (operand
->buf
, "b") == 0;
3280 /* Return the number of operands found, or -1 on error, copying the
3281 operands into the given array and the accompanying expressions into
3285 get_operands (operands
, line
)
3286 struct opstruct operands
[];
3291 int expecting_operand
= 0;
3294 while (numexp
< MAX_OPERANDS
&& !is_end_of_line
[(int) *lptr
])
3296 int paren_not_balanced
= 0;
3297 char *op_start
, *op_end
;
3298 while (*lptr
&& ISSPACE (*lptr
))
3301 while (paren_not_balanced
|| *lptr
!= ',')
3305 if (paren_not_balanced
)
3307 as_bad ("Unbalanced parenthesis in operand %d", numexp
);
3314 ++paren_not_balanced
;
3315 else if (*lptr
== ')')
3316 --paren_not_balanced
;
3320 if (op_end
!= op_start
)
3322 int len
= op_end
- op_start
;
3323 strncpy (operands
[numexp
].buf
, op_start
, len
);
3324 operands
[numexp
].buf
[len
] = 0;
3325 /* Trim trailing spaces; while the preprocessor gets rid of most,
3326 there are weird usage patterns that can introduce them
3327 (i.e. using strings for macro args). */
3328 while (len
> 0 && ISSPACE (operands
[numexp
].buf
[len
- 1]))
3329 operands
[numexp
].buf
[--len
] = 0;
3335 if (expecting_operand
|| *lptr
== ',')
3337 as_bad ("Expecting operand after ','");
3343 if (*++lptr
== '\0')
3345 as_bad ("Expecting operand after ','");
3348 expecting_operand
= 1;
3352 while (*lptr
&& ISSPACE (*lptr
++))
3354 if (!is_end_of_line
[(int) *lptr
])
3356 as_bad ("Extra junk on line");
3360 /* OK, now parse them into expressions. */
3361 for (i
= 0; i
< numexp
; i
++)
3363 memset (&operands
[i
].exp
, 0, sizeof (operands
[i
].exp
));
3364 if (operands
[i
].buf
[0] == '#')
3367 parse_expression (operands
[i
].buf
+ 1, &operands
[i
].exp
);
3369 else if (operands
[i
].buf
[0] == '@')
3371 /* Direct notation. */
3372 parse_expression (operands
[i
].buf
+ 1, &operands
[i
].exp
);
3374 else if (operands
[i
].buf
[0] == '*')
3377 char *paren
= strchr (operands
[i
].buf
, '(');
3378 /* Allow immediate syntax in the inner expression. */
3379 if (paren
&& paren
[1] == '#')
3382 /* Pull out the lk expression or SP offset, if present. */
3385 int len
= strlen (paren
);
3386 char *end
= paren
+ len
;
3388 while (end
[-1] != ')')
3391 as_bad (_("Badly formed address expression"));
3396 parse_expression (paren
, &operands
[i
].exp
);
3400 operands
[i
].exp
.X_op
= O_absent
;
3403 parse_expression (operands
[i
].buf
, &operands
[i
].exp
);
3409 /* Predicates for different operand types. */
3412 is_immediate (operand
)
3413 struct opstruct
*operand
;
3415 return *operand
->buf
== '#';
3418 /* This is distinguished from immediate because some numbers must be constants
3419 and must *not* have the '#' prefix. */
3422 is_absolute (operand
)
3423 struct opstruct
*operand
;
3425 return operand
->exp
.X_op
== O_constant
&& !is_immediate (operand
);
3428 /* Is this an indirect operand? */
3431 is_indirect (operand
)
3432 struct opstruct
*operand
;
3434 return operand
->buf
[0] == '*';
3437 /* Is this a valid dual-memory operand? */
3441 struct opstruct
*operand
;
3443 if (is_indirect (operand
) && strncasecmp (operand
->buf
, "*ar", 3) == 0)
3445 char *tmp
= operand
->buf
+ 3;
3450 /* Only allow *ARx, *ARx-, *ARx+, or *ARx+0%. */
3451 valid_mod
= *tmp
== '\0' ||
3452 strcasecmp (tmp
, "-") == 0 ||
3453 strcasecmp (tmp
, "+") == 0 ||
3454 strcasecmp (tmp
, "+0%") == 0;
3455 return arf
>= 2 && arf
<= 5 && valid_mod
;
3462 struct opstruct
*operand
;
3464 return (is_absolute (operand
)
3465 || is_immediate (operand
)
3466 || hash_find (mmreg_hash
, operand
->buf
) != 0);
3470 is_type (operand
, type
)
3471 struct opstruct
*operand
;
3477 return operand
->buf
[0] == 0;
3480 return is_dual (operand
);
3482 return is_indirect (operand
);
3484 /* This one *must* be immediate. */
3485 return is_immediate (operand
);
3494 /* Address may be a numeric, indirect, or an expression. */
3495 return !is_immediate (operand
);
3498 return is_mmreg (operand
);
3503 return is_accumulator (operand
);
3505 return is_accumulator (operand
) && TOUPPER (operand
->buf
[0]) == 'B';
3507 return is_accumulator (operand
) && TOUPPER (operand
->buf
[0]) == 'A';
3509 return strncasecmp ("ar", operand
->buf
, 2) == 0
3510 && ISDIGIT (operand
->buf
[2]);
3512 return hash_find (sbit_hash
, operand
->buf
) != 0 || is_absolute (operand
);
3514 return hash_find (cc_hash
, operand
->buf
) != 0;
3516 return hash_find (cc2_hash
, operand
->buf
) != 0;
3518 return hash_find (cc3_hash
, operand
->buf
) != 0
3519 || is_immediate (operand
) || is_absolute (operand
);
3521 return (is_immediate (operand
) || is_absolute (operand
))
3522 && operand
->exp
.X_add_number
== 16;
3524 /* Allow st0 or st1 instead of a numeric. */
3525 return is_absolute (operand
) || is_immediate (operand
) ||
3526 strcasecmp ("st0", operand
->buf
) == 0 ||
3527 strcasecmp ("st1", operand
->buf
) == 0;
3530 return is_absolute (operand
) || is_immediate (operand
);
3532 return (is_immediate (operand
) || is_absolute (operand
))
3533 && operand
->exp
.X_add_number
>= 0 && operand
->exp
.X_add_number
< 16;
3535 /* Let this one catch out-of-range values. */
3536 return (is_immediate (operand
) || is_absolute (operand
))
3537 && operand
->exp
.X_add_number
!= 16;
3541 return is_absolute (operand
) || is_immediate (operand
);
3543 return is_immediate (operand
)
3544 && operand
->exp
.X_op
== O_constant
3545 && operand
->exp
.X_add_number
>= 0
3546 && operand
->exp
.X_add_number
< 256;
3549 /* Allow anything; assumes opcodes are ordered with Smem operands
3555 /* Just make sure it's an integer; check range later. */
3556 return is_immediate (operand
);
3558 return strcasecmp ("t", operand
->buf
) == 0 ||
3559 strcasecmp ("treg", operand
->buf
) == 0;
3561 return strcasecmp ("ts", operand
->buf
) == 0;
3563 return strcasecmp ("asm", operand
->buf
) == 0;
3565 return strcasecmp ("trn", operand
->buf
) == 0;
3567 return strcasecmp ("dp", operand
->buf
) == 0;
3569 return strcasecmp ("arp", operand
->buf
) == 0;
3576 operands_match (insn
, operands
, opcount
, refoptype
, minops
, maxops
)
3578 struct opstruct
*operands
;
3580 const enum optype
*refoptype
;
3583 int op
= 0, refop
= 0;
3585 if (opcount
== 0 && minops
== 0)
3590 while (op
<= maxops
&& refop
<= maxops
)
3592 while (!is_type (&operands
[op
], OPTYPE (refoptype
[refop
])))
3594 /* Skip an optional template operand if it doesn't agree
3595 with the current operand. */
3596 if (refoptype
[refop
] & OPT
)
3607 /* Save the actual operand type for later use. */
3608 operands
[op
].type
= OPTYPE (refoptype
[refop
]);
3611 /* Have we matched them all yet? */
3616 /* If a later operand is *not* optional, no match. */
3617 if ((refoptype
[refop
] & OPT
) == 0)
3619 /* Flag any implicit default OP_DST operands so we know to add
3620 them explicitly when encoding the operand later. */
3621 if (OPTYPE (refoptype
[refop
]) == OP_DST
)
3622 insn
->using_default_dst
= 1;
3634 /* 16-bit direct memory address
3635 Explicit dmad operands are always in last word of insn (usually second
3636 word, but bumped to third if lk addressing is used)
3638 We allow *(dmad) notation because the TI assembler allows it.
3641 0 for 16-bit addresses
3642 1 for full 23-bit addresses
3643 2 for the upper 7 bits of a 23-bit address (LDX). */
3646 encode_dmad (insn
, operand
, xpc_code
)
3648 struct opstruct
*operand
;
3651 int op
= 1 + insn
->is_lkaddr
;
3653 /* Only allow *(dmad) expressions; all others are invalid. */
3654 if (is_indirect (operand
) && operand
->buf
[strlen (operand
->buf
) - 1] != ')')
3656 as_bad (_("Invalid dmad syntax '%s'"), operand
->buf
);
3660 insn
->opcode
[op
].addr_expr
= operand
->exp
;
3662 if (insn
->opcode
[op
].addr_expr
.X_op
== O_constant
)
3664 valueT value
= insn
->opcode
[op
].addr_expr
.X_add_number
;
3667 insn
->opcode
[0].word
&= 0xFF80;
3668 insn
->opcode
[0].word
|= (value
>> 16) & 0x7F;
3669 insn
->opcode
[1].word
= value
& 0xFFFF;
3671 else if (xpc_code
== 2)
3672 insn
->opcode
[op
].word
= (value
>> 16) & 0xFFFF;
3674 insn
->opcode
[op
].word
= value
;
3678 /* Do the fixup later; just store the expression. */
3679 insn
->opcode
[op
].word
= 0;
3680 insn
->opcode
[op
].r_nchars
= 2;
3682 if (amode
== c_mode
)
3683 insn
->opcode
[op
].r_type
= BFD_RELOC_TIC54X_16_OF_23
;
3684 else if (xpc_code
== 1)
3686 /* This relocation spans two words, so adjust accordingly. */
3687 insn
->opcode
[0].addr_expr
= operand
->exp
;
3688 insn
->opcode
[0].r_type
= BFD_RELOC_TIC54X_23
;
3689 insn
->opcode
[0].r_nchars
= 4;
3690 insn
->opcode
[0].unresolved
= 1;
3691 /* It's really 2 words, but we want to stop encoding after the
3692 first, since we must encode both words at once. */
3695 else if (xpc_code
== 2)
3696 insn
->opcode
[op
].r_type
= BFD_RELOC_TIC54X_MS7_OF_23
;
3698 insn
->opcode
[op
].r_type
= BFD_RELOC_TIC54X_16_OF_23
;
3700 insn
->opcode
[op
].unresolved
= 1;
3706 /* 7-bit direct address encoding. */
3709 encode_address (insn
, operand
)
3711 struct opstruct
*operand
;
3713 /* Assumes that dma addresses are *always* in word 0 of the opcode. */
3714 insn
->opcode
[0].addr_expr
= operand
->exp
;
3716 if (operand
->exp
.X_op
== O_constant
)
3717 insn
->opcode
[0].word
|= (operand
->exp
.X_add_number
& 0x7F);
3720 /* Do the fixup later; just store the expression. */
3721 insn
->opcode
[0].r_nchars
= 1;
3722 insn
->opcode
[0].r_type
= BFD_RELOC_TIC54X_PARTLS7
;
3723 insn
->opcode
[0].unresolved
= 1;
3730 encode_indirect (insn
, operand
)
3732 struct opstruct
*operand
;
3737 if (insn
->is_lkaddr
)
3739 /* lk addresses always go in the second insn word. */
3740 mod
= ((TOUPPER (operand
->buf
[1]) == 'A') ? 12 :
3741 (operand
->buf
[1] == '(') ? 15 :
3742 (strchr (operand
->buf
, '%') != NULL
) ? 14 : 13);
3743 arf
= ((mod
== 12) ? operand
->buf
[3] - '0' :
3744 (mod
== 15) ? 0 : operand
->buf
[4] - '0');
3746 insn
->opcode
[1].addr_expr
= operand
->exp
;
3748 if (operand
->exp
.X_op
== O_constant
)
3749 insn
->opcode
[1].word
= operand
->exp
.X_add_number
;
3752 insn
->opcode
[1].word
= 0;
3753 insn
->opcode
[1].r_nchars
= 2;
3754 insn
->opcode
[1].r_type
= BFD_RELOC_TIC54X_16_OF_23
;
3755 insn
->opcode
[1].unresolved
= 1;
3758 else if (strncasecmp (operand
->buf
, "*sp (", 4) == 0)
3760 /* Stack offsets look the same as 7-bit direct addressing. */
3761 return encode_address (insn
, operand
);
3765 arf
= (TOUPPER (operand
->buf
[1]) == 'A' ?
3766 operand
->buf
[3] : operand
->buf
[4]) - '0';
3768 if (operand
->buf
[1] == '+')
3770 mod
= 3; /* *+ARx */
3771 if (insn
->tm
->flags
& FL_SMR
)
3772 as_warn (_("Address mode *+ARx is write-only. "
3773 "Results of reading are undefined."));
3775 else if (operand
->buf
[4] == '\0')
3777 else if (operand
->buf
[5] == '\0')
3778 mod
= (operand
->buf
[4] == '-' ? 1 : 2); /* *ARx+ / *ARx- */
3779 else if (operand
->buf
[6] == '\0')
3781 if (operand
->buf
[5] == '0')
3782 mod
= (operand
->buf
[4] == '-' ? 5 : 6); /* *ARx+0 / *ARx-0 */
3784 mod
= (operand
->buf
[4] == '-' ? 8 : 10);/* *ARx+% / *ARx-% */
3786 else if (TOUPPER (operand
->buf
[6]) == 'B')
3787 mod
= (operand
->buf
[4] == '-' ? 4 : 7); /* ARx+0B / *ARx-0B */
3788 else if (TOUPPER (operand
->buf
[6]) == '%')
3789 mod
= (operand
->buf
[4] == '-' ? 9 : 11); /* ARx+0% / *ARx - 0% */
3792 as_bad (_("Unrecognized indirect address format \"%s\""),
3798 insn
->opcode
[0].word
|= 0x80 | (mod
<< 3) | arf
;
3804 encode_integer (insn
, operand
, which
, min
, max
, mask
)
3806 struct opstruct
*operand
;
3807 int which
, min
, max
;
3808 unsigned short mask
;
3810 long parse
, integer
;
3812 insn
->opcode
[which
].addr_expr
= operand
->exp
;
3814 if (operand
->exp
.X_op
== O_constant
)
3816 parse
= operand
->exp
.X_add_number
;
3817 /* Hack -- fixup for 16-bit hex quantities that get converted positive
3818 instead of negative. */
3819 if ((parse
& 0x8000) && min
== -32768 && max
== 32767)
3820 integer
= (short) parse
;
3824 if (integer
>= min
&& integer
<= max
)
3826 insn
->opcode
[which
].word
|= (integer
& mask
);
3829 as_bad (_("Operand '%s' out of range (%d <= x <= %d)"),
3830 operand
->buf
, min
, max
);
3834 if (insn
->opcode
[which
].addr_expr
.X_op
== O_constant
)
3836 insn
->opcode
[which
].word
|=
3837 insn
->opcode
[which
].addr_expr
.X_add_number
& mask
;
3841 /* Do the fixup later; just store the expression. */
3842 bfd_reloc_code_real_type rtype
=
3843 (mask
== 0x1FF ? BFD_RELOC_TIC54X_PARTMS9
:
3844 mask
== 0xFFFF ? BFD_RELOC_TIC54X_16_OF_23
:
3845 mask
== 0x7F ? BFD_RELOC_TIC54X_PARTLS7
: BFD_RELOC_8
);
3846 int size
= (mask
== 0x1FF || mask
== 0xFFFF) ? 2 : 1;
3848 if (rtype
== BFD_RELOC_8
)
3849 as_bad (_("Error in relocation handling"));
3851 insn
->opcode
[which
].r_nchars
= size
;
3852 insn
->opcode
[which
].r_type
= rtype
;
3853 insn
->opcode
[which
].unresolved
= 1;
3863 encode_condition (insn
, operand
)
3865 struct opstruct
*operand
;
3867 symbol
*cc
= (symbol
*) hash_find (cc_hash
, operand
->buf
);
3870 as_bad (_("Unrecognized condition code \"%s\""), operand
->buf
);
3873 #define CC_GROUP 0x40
3875 #define CATG_A1 0x07
3876 #define CATG_B1 0x30
3877 #define CATG_A2 0x30
3878 #define CATG_B2 0x0C
3879 #define CATG_C2 0x03
3880 /* Disallow group 1 conditions mixed with group 2 conditions
3881 if group 1, allow only one category A and one category B
3882 if group 2, allow only one each of category A, B, and C. */
3883 if (((insn
->opcode
[0].word
& 0xFF) != 0))
3885 if ((insn
->opcode
[0].word
& CC_GROUP
) != (cc
->value
& CC_GROUP
))
3887 as_bad (_("Condition \"%s\" does not match preceding group"),
3891 if (insn
->opcode
[0].word
& CC_GROUP
)
3893 if ((insn
->opcode
[0].word
& CC_ACC
) != (cc
->value
& CC_ACC
))
3895 as_bad (_("Condition \"%s\" uses a different accumulator from "
3896 "a preceding condition"),
3900 if ((insn
->opcode
[0].word
& CATG_A1
) && (cc
->value
& CATG_A1
))
3902 as_bad (_("Only one comparison conditional allowed"));
3905 if ((insn
->opcode
[0].word
& CATG_B1
) && (cc
->value
& CATG_B1
))
3907 as_bad (_("Only one overflow conditional allowed"));
3911 else if (((insn
->opcode
[0].word
& CATG_A2
) && (cc
->value
& CATG_A2
)) ||
3912 ((insn
->opcode
[0].word
& CATG_B2
) && (cc
->value
& CATG_B2
)) ||
3913 ((insn
->opcode
[0].word
& CATG_C2
) && (cc
->value
& CATG_C2
)))
3915 as_bad (_("Duplicate %s conditional"), operand
->buf
);
3920 insn
->opcode
[0].word
|= cc
->value
;
3925 encode_cc3 (insn
, operand
)
3927 struct opstruct
*operand
;
3929 symbol
*cc3
= (symbol
*) hash_find (cc3_hash
, operand
->buf
);
3930 int value
= cc3
? cc3
->value
: operand
->exp
.X_add_number
<< 8;
3932 if ((value
& 0x0300) != value
)
3934 as_bad (_("Unrecognized condition code \"%s\""), operand
->buf
);
3937 insn
->opcode
[0].word
|= value
;
3942 encode_arx (insn
, operand
)
3944 struct opstruct
*operand
;
3946 int arf
= strlen (operand
->buf
) >= 3 ? operand
->buf
[2] - '0' : -1;
3947 if (strncasecmp ("ar", operand
->buf
, 2) || arf
< 0 || arf
> 7)
3949 as_bad (_("Invalid auxiliary register (use AR0-AR7)"));
3952 insn
->opcode
[0].word
|= arf
;
3957 encode_cc2 (insn
, operand
)
3959 struct opstruct
*operand
;
3961 symbol
*cc2
= (symbol
*) hash_find (cc2_hash
, operand
->buf
);
3964 as_bad (_("Unrecognized condition code \"%s\""), operand
->buf
);
3967 insn
->opcode
[0].word
|= cc2
->value
;
3972 encode_operand (insn
, type
, operand
)
3975 struct opstruct
*operand
;
3977 int ext
= insn
->tm
&& ((insn
->tm
->flags
& FL_EXT
) != 0);
3979 if (type
== OP_MMR
&& operand
->exp
.X_op
!= O_constant
)
3981 /* Disallow long-constant addressing for memory-mapped addressing. */
3982 if (insn
->is_lkaddr
)
3984 as_bad (_("lk addressing modes are invalid for memory-mapped "
3985 "register addressing"));
3989 /* Warn about *+ARx when used with MMR operands. */
3990 if (strncasecmp (operand
->buf
, "*+ar", 4) == 0)
3992 as_warn (_("Address mode *+ARx is not allowed in memory-mapped "
3993 "register addressing. Resulting behavior is "
4003 /* 16-bit immediate value. */
4004 return encode_dmad (insn
, operand
, 0);
4006 if (TOUPPER (*operand
->buf
) == 'B')
4008 insn
->opcode
[ext
? (1 + insn
->is_lkaddr
) : 0].word
|= (1 << 9);
4009 if (insn
->using_default_dst
)
4010 insn
->opcode
[ext
? (1 + insn
->is_lkaddr
) : 0].word
|= (1 << 8);
4014 /* Make sure this agrees with with the OP_DST operand. */
4015 if (!((TOUPPER (operand
->buf
[0]) == 'B') ^
4016 ((insn
->opcode
[0].word
& (1 << 8)) != 0)))
4018 as_bad (_("Destination accumulator for each part of this parallel "
4019 "instruction must be different"));
4025 if (TOUPPER (operand
->buf
[0]) == 'B')
4026 insn
->opcode
[ext
? (1 + insn
->is_lkaddr
) : 0].word
|= (1 << 8);
4031 int mod
= (operand
->buf
[4] == '\0' ? 0 : /* *arx */
4032 operand
->buf
[4] == '-' ? 1 : /* *arx- */
4033 operand
->buf
[5] == '\0' ? 2 : 3); /* *arx+, *arx+0% */
4034 int arf
= operand
->buf
[3] - '0' - 2;
4035 int code
= (mod
<< 2) | arf
;
4036 insn
->opcode
[0].word
|= (code
<< (type
== OP_Xmem
? 4 : 0));
4041 if (!is_indirect (operand
))
4042 return encode_address (insn
, operand
);
4045 return encode_indirect (insn
, operand
);
4047 return encode_dmad (insn
, operand
, 2);
4049 return encode_dmad (insn
, operand
, 1);
4052 return encode_dmad (insn
, operand
, 0);
4054 return encode_arx (insn
, operand
);
4059 int value
= operand
->exp
.X_add_number
;
4062 insn
->opcode
[0].word
|= value
;
4065 if (value
< 16 || value
> 24)
4067 as_bad (_("Memory mapped register \"%s\" out of range"),
4071 if (type
== OP_MMRX
)
4072 insn
->opcode
[0].word
|= (value
- 16) << 4;
4074 insn
->opcode
[0].word
|= (value
- 16);
4082 return encode_integer (insn
, operand
, ext
+ insn
->is_lkaddr
,
4085 return encode_integer (insn
, operand
, ext
+ insn
->is_lkaddr
,
4088 return encode_integer (insn
, operand
, 1 + insn
->is_lkaddr
,
4089 -32768, 32767, 0xFFFF);
4091 return encode_condition (insn
, operand
);
4093 return encode_cc2 (insn
, operand
);
4095 return encode_cc3 (insn
, operand
);
4097 return encode_integer (insn
, operand
, 0, 0, 15, 0xF);
4099 return encode_integer (insn
, operand
, 0, -128, 127, 0xFF);
4102 int value
= operand
->exp
.X_add_number
;
4104 if (value
< 1 || value
> 3)
4106 as_bad (_("Invalid operand (use 1, 2, or 3)"));
4109 code
= value
== 1 ? 0 : value
== 2 ? 0x2 : 0x1;
4110 insn
->opcode
[0].word
|= (code
<< 8);
4114 return encode_integer (insn
, operand
, 0, 0, 31, 0x1F);
4116 return encode_integer (insn
, operand
, 0, 0, 255, 0xFF);
4118 return encode_integer (insn
, operand
, 1 + insn
->is_lkaddr
,
4122 symbol
*sbit
= (symbol
*) hash_find (sbit_hash
, operand
->buf
);
4123 int value
= is_absolute (operand
) ?
4124 operand
->exp
.X_add_number
: (sbit
? sbit
->value
: -1);
4127 if (insn
->opcount
== 1)
4131 as_bad (_("A status register or status bit name is required"));
4134 /* Guess the register based on the status bit; "ovb" is the last
4135 status bit defined for st0. */
4136 if (sbit
> (symbol
*) hash_find (sbit_hash
, "ovb"))
4141 as_bad (_("Unrecognized status bit \"%s\""), operand
->buf
);
4144 insn
->opcode
[0].word
|= value
;
4145 insn
->opcode
[0].word
|= (reg
<< 9);
4149 if (strcasecmp (operand
->buf
, "st0") == 0
4150 || strcasecmp (operand
->buf
, "st1") == 0)
4152 insn
->opcode
[0].word
|=
4153 ((unsigned short) (operand
->buf
[2] - '0')) << 9;
4156 else if (operand
->exp
.X_op
== O_constant
4157 && (operand
->exp
.X_add_number
== 0
4158 || operand
->exp
.X_add_number
== 1))
4160 insn
->opcode
[0].word
|=
4161 ((unsigned short) (operand
->exp
.X_add_number
)) << 9;
4164 as_bad (_("Invalid status register \"%s\""), operand
->buf
);
4167 return encode_integer (insn
, operand
, 0, -16, 15, 0x1F);
4169 return encode_integer (insn
, operand
, 0, 0, 7, 0x7);
4171 return encode_integer (insn
, operand
, 0, 0, 0x1FF, 0x1FF);
4173 if (operand
->exp
.X_add_number
!= 1
4174 && operand
->exp
.X_add_number
!= 2)
4176 as_bad (_("Operand \"%s\" out of range (use 1 or 2)"), operand
->buf
);
4179 insn
->opcode
[0].word
|= (operand
->exp
.X_add_number
- 1) << 9;
4188 /* No encoding necessary. */
4203 for (i
= 0; i
< insn
->words
; i
++)
4205 int size
= (insn
->opcode
[i
].unresolved
4206 && insn
->opcode
[i
].r_type
== BFD_RELOC_TIC54X_23
) ? 4 : 2;
4207 char *p
= frag_more (size
);
4210 md_number_to_chars (p
, (valueT
) insn
->opcode
[i
].word
, 2);
4212 md_number_to_chars (p
, (valueT
) insn
->opcode
[i
].word
<< 16, 4);
4214 if (insn
->opcode
[i
].unresolved
)
4215 fix_new_exp (frag_now
, p
- frag_now
->fr_literal
,
4216 insn
->opcode
[i
].r_nchars
, &insn
->opcode
[i
].addr_expr
,
4217 false, insn
->opcode
[i
].r_type
);
4221 /* Convert the operand strings into appropriate opcode values
4222 return the total number of words used by the instruction. */
4230 /* Only non-parallel instructions support lk addressing. */
4233 for (i
= 0; i
< insn
->opcount
; i
++)
4235 if ((OPTYPE (insn
->operands
[i
].type
) == OP_Smem
4236 || OPTYPE (insn
->operands
[i
].type
) == OP_Lmem
4237 || OPTYPE (insn
->operands
[i
].type
) == OP_Sind
)
4238 && strchr (insn
->operands
[i
].buf
, '(')
4239 /* Don't mistake stack-relative addressing for lk addressing. */
4240 && strncasecmp (insn
->operands
[i
].buf
, "*sp (", 4) != 0)
4242 insn
->is_lkaddr
= 1;
4243 insn
->lkoperand
= i
;
4249 (insn
->tm
? insn
->tm
->words
: insn
->ptm
->words
) + insn
->is_lkaddr
;
4251 insn
->opcode
[0].word
= insn
->tm
? insn
->tm
->opcode
: insn
->ptm
->opcode
;
4252 if (insn
->tm
&& (insn
->tm
->flags
& FL_EXT
))
4253 insn
->opcode
[1 + insn
->is_lkaddr
].word
= insn
->tm
->opcode2
;
4255 for (i
= 0; i
< insn
->opcount
; i
++)
4257 enum optype type
= insn
->operands
[i
].type
;
4258 if (!encode_operand (insn
, type
, &insn
->operands
[i
]))
4262 for (i
= 0; i
< insn
->paropcount
; i
++)
4264 enum optype partype
= insn
->paroperands
[i
].type
;
4265 if (!encode_operand (insn
, partype
, &insn
->paroperands
[i
]))
4275 optimize_insn (insn
)
4278 /* Optimize some instructions, helping out the brain-dead programmer. */
4279 #define is_zero(op) ((op).exp.X_op == O_constant && (op).exp.X_add_number == 0)
4280 if (strcasecmp (insn
->tm
->name
, "add") == 0)
4282 if (insn
->opcount
> 1
4283 && is_accumulator (&insn
->operands
[insn
->opcount
- 2])
4284 && is_accumulator (&insn
->operands
[insn
->opcount
- 1])
4285 && strcasecmp (insn
->operands
[insn
->opcount
- 2].buf
,
4286 insn
->operands
[insn
->opcount
- 1].buf
) == 0)
4289 insn
->using_default_dst
= 1;
4293 /* Try to collapse if Xmem and shift count is zero. */
4294 if ((OPTYPE (insn
->tm
->operand_types
[0]) == OP_Xmem
4295 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
4296 && is_zero (insn
->operands
[1]))
4297 /* Or if Smem, shift is zero or absent, and SRC == DST. */
4298 || (OPTYPE (insn
->tm
->operand_types
[0]) == OP_Smem
4299 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
4300 && is_type (&insn
->operands
[1], OP_SHIFT
)
4301 && is_zero (insn
->operands
[1]) && insn
->opcount
== 3))
4303 insn
->operands
[1] = insn
->operands
[2];
4308 else if (strcasecmp (insn
->tm
->name
, "ld") == 0)
4310 if (insn
->opcount
== 3 && insn
->operands
[0].type
!= OP_SRC
)
4312 if ((OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
4313 || OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
)
4314 && is_zero (insn
->operands
[1])
4315 && (OPTYPE (insn
->tm
->operand_types
[0]) != OP_lk
4316 || (insn
->operands
[0].exp
.X_op
== O_constant
4317 && insn
->operands
[0].exp
.X_add_number
<= 255
4318 && insn
->operands
[0].exp
.X_add_number
>= 0)))
4320 insn
->operands
[1] = insn
->operands
[2];
4326 else if (strcasecmp (insn
->tm
->name
, "sth") == 0
4327 || strcasecmp (insn
->tm
->name
, "stl") == 0)
4329 if ((OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
4330 || OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
)
4331 && is_zero (insn
->operands
[1]))
4333 insn
->operands
[1] = insn
->operands
[2];
4338 else if (strcasecmp (insn
->tm
->name
, "sub") == 0)
4340 if (insn
->opcount
> 1
4341 && is_accumulator (&insn
->operands
[insn
->opcount
- 2])
4342 && is_accumulator (&insn
->operands
[insn
->opcount
- 1])
4343 && strcasecmp (insn
->operands
[insn
->opcount
- 2].buf
,
4344 insn
->operands
[insn
->opcount
- 1].buf
) == 0)
4347 insn
->using_default_dst
= 1;
4351 if (((OPTYPE (insn
->tm
->operand_types
[0]) == OP_Smem
4352 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHIFT
)
4353 || (OPTYPE (insn
->tm
->operand_types
[0]) == OP_Xmem
4354 && OPTYPE (insn
->tm
->operand_types
[1]) == OP_SHFT
))
4355 && is_zero (insn
->operands
[1])
4356 && insn
->opcount
== 3)
4358 insn
->operands
[1] = insn
->operands
[2];
4366 /* Find a matching template if possible, and get the operand strings. */
4369 tic54x_parse_insn (insn
, line
)
4373 insn
->tm
= (template *) hash_find (op_hash
, insn
->mnemonic
);
4376 as_bad (_("Unrecognized instruction \"%s\""), insn
->mnemonic
);
4380 insn
->opcount
= get_operands (insn
->operands
, line
);
4381 if (insn
->opcount
< 0)
4384 /* Check each variation of operands for this mnemonic. */
4385 while (insn
->tm
->name
&& strcasecmp (insn
->tm
->name
, insn
->mnemonic
) == 0)
4387 if (insn
->opcount
>= insn
->tm
->minops
4388 && insn
->opcount
<= insn
->tm
->maxops
4389 && operands_match (insn
, &insn
->operands
[0], insn
->opcount
,
4390 insn
->tm
->operand_types
,
4391 insn
->tm
->minops
, insn
->tm
->maxops
))
4393 /* SUCCESS! now try some optimizations. */
4394 if (optimize_insn (insn
))
4396 insn
->tm
= (template *) hash_find (op_hash
,
4405 as_bad (_("Unrecognized operand list '%s' for instruction '%s'"),
4406 line
, insn
->mnemonic
);
4410 /* We set this in start_line_hook, 'cause if we do a line replacement, we
4411 won't be able to see the next line. */
4412 static int parallel_on_next_line_hint
= 0;
4414 /* See if this is part of a parallel instruction
4415 Look for a subsequent line starting with "||". */
4418 next_line_shows_parallel (next_line
)
4421 /* Look for the second half. */
4422 while (ISSPACE (*next_line
))
4425 return (next_line
[0] == PARALLEL_SEPARATOR
4426 && next_line
[1] == PARALLEL_SEPARATOR
);
4430 tic54x_parse_parallel_insn_firstline (insn
, line
)
4434 insn
->ptm
= (partemplate
*) hash_find (parop_hash
, insn
->mnemonic
);
4437 as_bad (_("Unrecognized parallel instruction \"%s\""),
4442 while (insn
->ptm
->name
&& strcasecmp (insn
->ptm
->name
,
4443 insn
->mnemonic
) == 0)
4445 insn
->opcount
= get_operands (insn
->operands
, line
);
4446 if (insn
->opcount
< 0)
4448 if (insn
->opcount
== 2
4449 && operands_match (insn
, &insn
->operands
[0], insn
->opcount
,
4450 insn
->ptm
->operand_types
, 2, 2))
4456 /* Didn't find a matching parallel; try for a normal insn. */
4460 /* Parse the second line of a two-line parallel instruction. */
4463 tic54x_parse_parallel_insn_lastline (insn
, line
)
4467 int valid_mnemonic
= 0;
4469 insn
->paropcount
= get_operands (insn
->paroperands
, line
);
4470 while (insn
->ptm
->name
&& strcasecmp (insn
->ptm
->name
,
4471 insn
->mnemonic
) == 0)
4473 if (strcasecmp (insn
->ptm
->parname
, insn
->parmnemonic
) == 0)
4476 if (insn
->paropcount
>= insn
->ptm
->minops
4477 && insn
->paropcount
<= insn
->ptm
->maxops
4478 && operands_match (insn
, insn
->paroperands
,
4480 insn
->ptm
->paroperand_types
,
4481 insn
->ptm
->minops
, insn
->ptm
->maxops
))
4489 as_bad (_("Invalid operand (s) for parallel instruction \"%s\""),
4492 as_bad (_("Unrecognized parallel instruction combination \"%s || %s\""),
4493 insn
->mnemonic
, insn
->parmnemonic
);
4498 /* If quotes found, return copy of line up to closing quote;
4499 otherwise up until terminator.
4500 If it's a string, pass as-is; otherwise attempt substitution symbol
4501 replacement on the value. */
4504 subsym_get_arg (char *line
, char *terminators
, char **str
, int nosub
)
4508 int is_string
= *line
== '"';
4509 int is_char
= ISDIGIT (*line
);
4513 while (ISDIGIT (*ptr
))
4516 *str
= xmalloc (ptr
- line
+ 1);
4517 strncpy (*str
, line
, ptr
- line
);
4518 (*str
)[ptr
- line
] = 0;
4522 char *savedp
= input_line_pointer
;
4524 input_line_pointer
= ptr
;
4525 *str
= demand_copy_C_string (&len
);
4526 endp
= input_line_pointer
;
4527 input_line_pointer
= savedp
;
4529 /* Do forced substitutions if requested. */
4530 if (!nosub
&& **str
== ':')
4531 *str
= subsym_substitute (*str
, 1);
4535 char *term
= terminators
;
4538 while (*ptr
&& *ptr
!= *term
)
4549 *str
= xmalloc (ptr
- line
+ 1);
4550 strncpy (*str
, line
, ptr
- line
);
4551 (*str
)[ptr
- line
] = 0;
4552 /* Do simple substitution, if available. */
4553 if (!nosub
&& (value
= subsym_lookup (*str
, macro_level
)) != NULL
)
4560 /* Replace the given substitution string.
4561 We start at the innermost macro level, so that existing locals remain local
4562 Note: we're treating macro args identically to .var's; I don't know if
4563 that's compatible w/TI's assembler. */
4566 subsym_create_or_replace (name
, value
)
4572 for (i
= macro_level
; i
> 0; i
--)
4574 if (hash_find (subsym_hash
[i
], name
))
4576 hash_replace (subsym_hash
[i
], name
, value
);
4580 if (hash_find (subsym_hash
[0], name
))
4581 hash_replace (subsym_hash
[0], name
, value
);
4583 hash_insert (subsym_hash
[0], name
, value
);
4586 /* Look up the substitution string replacement for the given symbol.
4587 Start with the innermost macro substituion table given and work
4591 subsym_lookup (name
, nest_level
)
4595 char *value
= hash_find (subsym_hash
[nest_level
], name
);
4597 if (value
|| nest_level
== 0)
4600 return subsym_lookup (name
, nest_level
- 1);
4603 /* Do substitution-symbol replacement on the given line (recursively).
4604 return the argument if no substitution was done
4606 Also look for built-in functions ($func (arg)) and local labels.
4608 If FORCED is set, look for forced substitutions of the form ':SYMBOL:'. */
4611 subsym_substitute (char *line
, int forced
)
4613 /* For each apparent symbol, see if it's a substitution symbol, and if so,
4614 replace it in the input. */
4615 char *replacement
; /* current replacement for LINE. */
4616 char *head
; /* Start of line. */
4617 char *ptr
; /* Current examination point. */
4618 int changed
= 0; /* Did we make a substitution? */
4619 int eval_line
= 0; /* Is this line a .eval/.asg statement? */
4620 int eval_symbol
= 0; /* Are we in the middle of the symbol for
4622 char *eval_end
= NULL
;
4624 int line_conditional
= 0;
4627 /* Work with a copy of the input line. */
4628 replacement
= xmalloc (strlen (line
) + 1);
4629 strcpy (replacement
, line
);
4631 ptr
= head
= replacement
;
4633 /* Flag lines where we might need to replace a single '=' with two;
4634 GAS uses single '=' to assign macro args values, and possibly other
4635 places, so limit what we replace. */
4636 if (strstr (line
, ".if")
4637 || strstr (line
, ".elseif")
4638 || strstr (line
, ".break"))
4640 line_conditional
= 1;
4643 /* Watch out for .eval, so that we avoid doing substitution on the
4644 symbol being assigned a value. */
4645 if (strstr (line
, ".eval") || strstr (line
, ".asg"))
4648 /* If it's a macro definition, don't do substitution on the argument
4650 if (strstr (line
, ".macro"))
4653 while (!is_end_of_line
[(int) *ptr
])
4655 int current_char
= *ptr
;
4657 /* Need to update this since LINE may have been modified. */
4659 eval_end
= strrchr (ptr
, ',');
4661 /* Replace triple double quotes with bounding quote/escapes. */
4662 if (current_char
== '"' && ptr
[1] == '"' && ptr
[2] == '"')
4665 tmp
= strstr (ptr
+ 2, "\"\"\"");
4671 /* Replace a single '=' with a '==';
4672 for compatibility with older code only. */
4673 if (line_conditional
&& current_char
== '=')
4681 tmp
= xmalloc (strlen (head
) + 2 + strlen (ptr
) + 1);
4682 sprintf (tmp
, "%s==%s", head
, ptr
);
4683 /* Continue examining after the '=='. */
4684 ptr
= tmp
+ strlen (head
) + 2;
4686 head
= replacement
= tmp
;
4690 /* Flag when we've reached the symbol part of .eval/.asg. */
4691 if (eval_line
&& ptr
>= eval_end
)
4694 /* For each apparent symbol, see if it's a substitution symbol, and if
4695 so, replace it in the input. */
4696 if ((forced
&& current_char
== ':')
4697 || (!forced
&& is_name_beginner (current_char
)))
4699 char *name
; /* Symbol to be replaced. */
4700 char *savedp
= input_line_pointer
;
4703 char *tail
; /* Rest of line after symbol. */
4705 /* Skip the colon. */
4709 name
= input_line_pointer
= ptr
;
4710 c
= get_symbol_end ();
4711 /* '?' is not normally part of a symbol, but it IS part of a local
4715 *input_line_pointer
++ = c
;
4716 c
= *input_line_pointer
;
4717 *input_line_pointer
= '\0';
4719 /* Avoid infinite recursion; if a symbol shows up a second time for
4720 substitution, leave it as is. */
4721 if (hash_find (subsym_recurse_hash
, name
) == NULL
)
4722 value
= subsym_lookup (name
, macro_level
);
4724 as_warn (_("%s symbol recursion stopped at "
4725 "second appearance of '%s'"),
4726 forced
? "Forced substitution" : "Substitution", name
);
4727 ptr
= tail
= input_line_pointer
;
4728 input_line_pointer
= savedp
;
4730 /* Check for local labels; replace them with the appropriate
4732 if ((*name
== '$' && ISDIGIT (name
[1]) && name
[2] == '\0')
4733 || name
[strlen (name
) - 1] == '?')
4735 /* Use an existing identifier for that label if, available, or
4736 create a new, unique identifier. */
4737 value
= hash_find (local_label_hash
[macro_level
], name
);
4741 char *namecopy
= strcpy (xmalloc (strlen (name
) + 1), name
);
4742 value
= strcpy (xmalloc (strlen (name
) + sizeof (digit
) + 1),
4745 value
[strlen (value
) - 1] = '\0';
4746 sprintf (digit
, ".%d", local_label_id
++);
4747 strcat (value
, digit
);
4748 hash_insert (local_label_hash
[macro_level
], namecopy
, value
);
4750 /* Indicate where to continue looking for substitutions. */
4753 /* Check for built-in subsym and math functions. */
4754 else if (value
!= NULL
&& *name
== '$')
4756 subsym_proc_entry
*entry
= (subsym_proc_entry
*) value
;
4757 math_proc_entry
*math_entry
= hash_find (math_hash
, name
);
4758 char *arg1
, *arg2
= NULL
;
4763 as_bad (_("Unrecognized substitution symbol function"));
4766 else if (*ptr
!= '(')
4768 as_bad (_("Missing '(' after substitution symbol function"));
4772 if (math_entry
!= NULL
)
4774 float arg1
, arg2
= 0;
4775 volatile float fresult
;
4777 arg1
= (float) strtod (ptr
, &ptr
);
4778 if (math_entry
->nargs
== 2)
4782 as_bad (_("Expecting second argument"));
4785 arg2
= (float) strtod (ptr
, &ptr
);
4787 fresult
= (*math_entry
->proc
) (arg1
, arg2
);
4788 value
= xmalloc (128);
4789 if (math_entry
->int_return
)
4790 sprintf (value
, "%d", (int) fresult
);
4792 sprintf (value
, "%f", fresult
);
4795 as_bad (_("Extra junk in function call, expecting ')'"));
4798 /* Don't bother recursing; the replacement isn't a
4805 int arg_type
[2] = { *ptr
== '"' , 0 };
4806 int ismember
= !strcmp (entry
->name
, "$ismember");
4807 /* Parse one or two args, which must be a substitution
4808 symbol, string or a character-string constant. */
4809 /* For all functions, a string or substitution symbol may be
4810 used, with the following exceptions:
4811 firstch/lastch: 2nd arg must be character constant
4812 ismember: both args must be substitution symbols. */
4813 ptr
= subsym_get_arg (ptr
, ",)", &arg1
, ismember
);
4816 if (entry
->nargs
== 2)
4820 as_bad (_("Function expects two arguments"));
4823 /* Character constants are converted to numerics
4824 by the preprocessor. */
4825 arg_type
[1] = (ISDIGIT (*ptr
)) ? 2 : (*ptr
== '"');
4826 ptr
= subsym_get_arg (ptr
, ")", &arg2
, ismember
);
4828 /* Args checking. */
4829 if ((!strcmp (entry
->name
, "$firstch")
4830 || !strcmp (entry
->name
, "$lastch"))
4831 && arg_type
[1] != 2)
4833 as_bad (_("Expecting character constant argument"));
4837 && (arg_type
[0] != 0 || arg_type
[1] != 0))
4839 as_bad (_("Both arguments must be substitution symbols"));
4844 as_bad (_("Extra junk in function call, expecting ')'"));
4847 val
= (*entry
->proc
) (arg1
, arg2
);
4848 value
= xmalloc (64);
4849 sprintf (value
, "%d", val
);
4851 /* Fix things up to replace the entire expression, not just the
4857 if (value
!= NULL
&& !eval_symbol
)
4859 /* Replace the symbol with its string replacement and
4860 continue. Recursively replace VALUE until either no
4861 substitutions are performed, or a substitution that has been
4862 previously made is encountered again.
4864 put the symbol into the recursion hash table so we only
4865 try to replace a symbol once. */
4868 hash_insert (subsym_recurse_hash
, name
, name
);
4869 value
= subsym_substitute (value
, macro_level
> 0);
4870 hash_delete (subsym_recurse_hash
, name
);
4873 /* Temporarily zero-terminate where the symbol started. */
4879 /* Subscripted substitution symbol -- use just the
4880 indicated portion of the string; the description
4881 kinda indicates that forced substituion is not
4882 supposed to be recursive, but I'm not sure. */
4883 unsigned beg
, len
= 1; /* default to a single char */
4884 char *newval
= strcpy (xmalloc (strlen (value
) + 1),
4887 savedp
= input_line_pointer
;
4888 input_line_pointer
= tail
+ 1;
4889 beg
= get_absolute_expression ();
4892 as_bad (_("Invalid subscript (use 1 to %d)"),
4896 if (*input_line_pointer
== ',')
4898 ++input_line_pointer
;
4899 len
= get_absolute_expression ();
4900 if (beg
+ len
> strlen (value
))
4902 as_bad (_("Invalid length (use 0 to %d"),
4903 strlen (value
) - beg
);
4909 tail
= input_line_pointer
;
4912 as_bad (_("Missing ')' in subscripted substitution "
4913 "symbol expression"));
4917 input_line_pointer
= savedp
;
4923 tmp
= xmalloc (strlen (head
) + strlen (value
) +
4924 strlen (tail
+ 1) + 2);
4926 strcat (tmp
, value
);
4927 /* Make sure forced substitutions are properly terminated. */
4932 as_bad (_("Missing forced substitution terminator ':'"));
4937 /* Try to replace required whitespace
4938 eliminated by the preprocessor; technically, a forced
4939 substitution could come anywhere, even mid-symbol,
4940 e.g. if x is "0", 'sym:x:end' should result in 'sym0end',
4941 but 'sym:x: end' should result in 'sym0 end'.
4942 FIXME -- this should really be fixed in the preprocessor,
4943 but would require several new states;
4944 KEEP_WHITE_AROUND_COLON does part of the job, but isn't
4946 if ((is_part_of_name (tail
[1])
4949 || tail
[1] == '\0' || tail
[1] == ',' || tail
[1] == '"')
4956 /* Restore the character after the symbol end. */
4959 /* Continue examining after the replacement value. */
4960 ptr
= tmp
+ strlen (head
) + strlen (value
);
4962 head
= replacement
= tmp
;
4980 /* We use this to handle substitution symbols
4981 hijack input_line_pointer, replacing it with our substituted string.
4983 .sslist should enable listing the line after replacements are made...
4985 returns the new buffer limit. */
4988 tic54x_start_line_hook ()
4991 char *replacement
= NULL
;
4993 /* Work with a copy of the input line, including EOL char. */
4994 endp
= input_line_pointer
;
4995 while (!is_end_of_line
[(int) *endp
++])
4997 line
= xmalloc (endp
- input_line_pointer
+ 1);
4998 strncpy (line
, input_line_pointer
, endp
- input_line_pointer
+ 1);
4999 line
[endp
- input_line_pointer
] = 0;
5001 /* Scan ahead for parallel insns. */
5002 parallel_on_next_line_hint
= next_line_shows_parallel (endp
+ 1);
5004 /* If within a macro, first process forced replacements. */
5005 if (macro_level
> 0)
5006 replacement
= subsym_substitute (line
, 1);
5009 replacement
= subsym_substitute (replacement
, 0);
5011 if (replacement
!= line
)
5013 char *tmp
= replacement
;
5014 char *comment
= strchr (replacement
, ';');
5015 char endc
= replacement
[strlen (replacement
) - 1];
5017 /* Clean up the replacement; we'd prefer to have this done by the
5018 standard preprocessing equipment (maybe do_scrub_chars?)
5019 but for now, do a quick-and-dirty. */
5020 if (comment
!= NULL
)
5027 comment
= replacement
+ strlen (replacement
) - 1;
5029 /* Trim trailing whitespace. */
5030 while (ISSPACE (*comment
))
5037 /* Compact leading whitespace. */
5038 while (ISSPACE (tmp
[0]) && ISSPACE (tmp
[1]))
5041 input_line_pointer
= endp
;
5042 input_scrub_insert_line (tmp
);
5045 /* Keep track of whether we've done a substitution. */
5046 substitution_line
= 1;
5052 substitution_line
= 0;
5056 /* This is the guts of the machine-dependent assembler. STR points to a
5057 machine dependent instruction. This function is supposed to emit
5058 the frags/bytes it assembles to. */
5063 static int repeat_slot
= 0;
5064 static int delay_slots
= 0; /* How many delay slots left to fill? */
5065 static int is_parallel
= 0;
5066 static tic54x_insn insn
;
5068 char *savedp
= input_line_pointer
;
5071 input_line_pointer
= line
;
5072 c
= get_symbol_end ();
5076 if (address_mode_needs_set
)
5078 set_address_mode (amode
);
5079 address_mode_needs_set
= 0;
5092 strcpy (insn
.parmnemonic
, line
);
5093 lptr
= input_line_pointer
;
5095 input_line_pointer
= savedp
;
5097 if (tic54x_parse_parallel_insn_lastline (&insn
, lptr
))
5099 int words
= build_insn (&insn
);
5101 if (delay_slots
!= 0)
5103 if (words
> delay_slots
)
5105 as_bad (_("Instruction does not fit in available delay "
5106 "slots (%d-word insn, %d slots left)"),
5107 words
, delay_slots
);
5111 delay_slots
-= words
;
5117 memset (&insn
, 0, sizeof (insn
));
5118 strcpy (insn
.mnemonic
, line
);
5119 lptr
= input_line_pointer
;
5121 input_line_pointer
= savedp
;
5123 /* See if this line is part of a parallel instruction; if so, either this
5124 line or the next line will have the "||" specifier preceding the
5125 mnemonic, and we look for it in the parallel insn hash table. */
5126 if (strstr (line
, "||") != NULL
|| parallel_on_next_line_hint
)
5128 char *tmp
= strstr (line
, "||");
5132 if (tic54x_parse_parallel_insn_firstline (&insn
, lptr
))
5135 /* If the parallel part is on the same line, process it now,
5136 otherwise let the assembler pick up the next line for us. */
5139 while (ISSPACE (tmp
[2]))
5141 md_assemble (tmp
+ 2);
5146 as_bad (_("Unrecognized parallel instruction '%s'"), line
);
5151 if (tic54x_parse_insn (&insn
, lptr
))
5155 if ((insn
.tm
->flags
& FL_LP
)
5156 && cpu
!= V545LP
&& cpu
!= V546LP
)
5158 as_bad (_("Instruction '%s' requires an LP cpu version"),
5162 if ((insn
.tm
->flags
& FL_FAR
)
5163 && amode
!= far_mode
)
5165 as_bad (_("Instruction '%s' requires far mode addressing"),
5170 words
= build_insn (&insn
);
5172 /* Is this instruction in a delay slot? */
5175 if (words
> delay_slots
)
5177 as_warn (_("Instruction does not fit in available delay "
5178 "slots (%d-word insn, %d slots left). "
5179 "Resulting behavior is undefined."),
5180 words
, delay_slots
);
5184 /* Branches in delay slots are not allowed. */
5185 if (insn
.tm
->flags
& FL_BMASK
)
5187 as_warn (_("Instructions which cause PC discontinuity are not "
5188 "allowed in a delay slot. "
5189 "Resulting behavior is undefined."));
5191 delay_slots
-= words
;
5194 /* Is this instruction the target of a repeat? */
5197 if (insn
.tm
->flags
& FL_NR
)
5198 as_warn (_("'%s' is not repeatable. "
5199 "Resulting behavior is undefined."),
5201 else if (insn
.is_lkaddr
)
5202 as_warn (_("Instructions using long offset modifiers or absolute "
5203 "addresses are not repeatable. "
5204 "Resulting behavior is undefined."));
5208 /* Make sure we check the target of a repeat instruction. */
5209 if (insn
.tm
->flags
& B_REPEAT
)
5212 /* FIXME -- warn if repeat_slot == 1 at EOF. */
5214 /* Make sure we check our delay slots for validity. */
5215 if (insn
.tm
->flags
& FL_DELAY
)
5218 /* FIXME -- warn if delay_slots != 0 at EOF. */
5223 /* Do a final adjustment on the symbol table; in this case, make sure we have
5224 a ".file" symbol. */
5227 tic54x_adjust_symtab ()
5229 if (symbol_rootP
== NULL
5230 || S_GET_STORAGE_CLASS (symbol_rootP
) != C_FILE
)
5234 as_where (&filename
, &lineno
);
5235 c_dot_file_symbol (filename
);
5239 /* In order to get gas to ignore any | chars at the start of a line,
5240 this function returns true if a | is found in a line.
5241 This lets us process parallel instructions, which span two lines. */
5244 tic54x_unrecognized_line (int c
)
5246 return c
== PARALLEL_SEPARATOR
;
5249 /* Watch for local labels of the form $[0-9] and [_a-zA-Z][_a-zA-Z0-9]*?
5250 Encode their names so that only we see them and can map them to the
5252 FIXME -- obviously this isn't done yet. These locals still show up in the
5255 tic54x_define_label (sym
)
5259 static int local_label_count
= 0;
5260 const char *name
= S_GET_NAME (sym
);
5263 /* Just in case we need this later; note that this is not necessarily the
5264 same thing as line_label...
5265 When aligning or assigning labels to fields, sometimes the label is
5266 assigned other than the address at which the label appears.
5267 FIXME -- is this really needed? I think all the proper label assignment
5268 is done in tic54x_cons. */
5269 last_label_seen
= sym
;
5272 /* Try to parse something that normal parsing failed at. */
5275 tic54x_undefined_symbol (name
)
5280 /* Not sure how to handle predefined symbols. */
5281 if ((sym
= (symbol
*) hash_find (cc_hash
, name
)) != NULL
||
5282 (sym
= (symbol
*) hash_find (cc2_hash
, name
)) != NULL
||
5283 (sym
= (symbol
*) hash_find (cc3_hash
, name
)) != NULL
||
5284 (sym
= (symbol
*) hash_find (misc_symbol_hash
, name
)) != NULL
||
5285 (sym
= (symbol
*) hash_find (sbit_hash
, name
)) != NULL
)
5287 return symbol_new (name
, reg_section
,
5288 (valueT
) sym
->value
,
5289 &zero_address_frag
);
5292 if ((sym
= (symbol
*) hash_find (reg_hash
, name
)) != NULL
||
5293 (sym
= (symbol
*) hash_find (mmreg_hash
, name
)) != NULL
||
5294 !strcasecmp (name
, "a") || !strcasecmp (name
, "b"))
5296 return symbol_new (name
, reg_section
,
5297 (valueT
) sym
? sym
->value
: 0,
5298 &zero_address_frag
);
5304 /* Parse a name in an expression before the expression parser takes a stab at
5308 tic54x_parse_name (name
, exp
)
5309 char *name ATTRIBUTE_UNUSED
;
5310 expressionS
*exp ATTRIBUTE_UNUSED
;
5313 symbol
*sym
= (symbol
*) hash_find (mmreg_hash
, name
);
5315 /* If it's a MMREG, replace it with its constant value. */
5318 exp
->X_op
= O_constant
;
5319 exp
->X_add_number
= sym
->value
;
5327 md_atof (type
, literalP
, sizeP
)
5332 #define MAX_LITTLENUMS 2
5333 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5334 LITTLENUM_TYPE
*word
;
5335 /* Only one precision on the c54x. */
5337 char *t
= atof_ieee (input_line_pointer
, type
, words
);
5339 input_line_pointer
= t
;
5342 /* Target data is little-endian, but floats are stored
5343 big-"word"ian. ugh. */
5344 for (word
= words
; prec
--;)
5346 md_number_to_chars (literalP
, (long) (*word
++), sizeof (LITTLENUM_TYPE
));
5347 literalP
+= sizeof (LITTLENUM_TYPE
);
5354 tc_gen_reloc (section
, fixP
)
5359 bfd_reloc_code_real_type code
= fixP
->fx_r_type
;
5360 asymbol
*sym
= symbol_get_bfdsym (fixP
->fx_addsy
);
5362 rel
= (arelent
*) xmalloc (sizeof (arelent
));
5363 rel
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
5364 *rel
->sym_ptr_ptr
= sym
;
5365 /* We assume that all rel->address are host byte offsets. */
5366 rel
->address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
5367 rel
->address
/= OCTETS_PER_BYTE
;
5368 rel
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
5369 if (!strcmp (sym
->name
, section
->name
))
5370 rel
->howto
+= HOWTO_BANK
;
5374 const char *name
= S_GET_NAME (fixP
->fx_addsy
);
5377 as_fatal ("Cannot generate relocation type for symbol %s, code %s",
5378 name
, bfd_get_reloc_code_name (code
));
5384 /* Handle cons expressions. */
5387 tic54x_cons_fix_new (fragS
*frag
, int where
, int octets
, expressionS
*exp
)
5389 bfd_reloc_code_real_type r
;
5393 as_bad (_("Unsupported relocation size %d"), octets
);
5394 r
= BFD_RELOC_TIC54X_16_OF_23
;
5397 r
= BFD_RELOC_TIC54X_16_OF_23
;
5400 /* TI assembler always uses this, regardless of addressing mode. */
5402 r
= BFD_RELOC_TIC54X_23
;
5404 /* We never want to directly generate this; this is provided for
5405 stabs support only. */
5409 fix_new_exp (frag
, where
, octets
, exp
, 0, r
);
5412 /* Attempt to simplify or even eliminate a fixup.
5413 To indicate that a fixup has been eliminated, set fixP->fx_done.
5415 If fixp->fx_addsy is non-NULL, we'll have to generate a reloc entry. */
5418 md_apply_fix (fixP
, valP
)
5422 char *buf
= fixP
->fx_where
+ fixP
->fx_frag
->fr_literal
;
5425 switch (fixP
->fx_r_type
)
5428 as_fatal ("Bad relocation type: 0x%02x", fixP
->fx_r_type
);
5430 case BFD_RELOC_TIC54X_MS7_OF_23
:
5431 val
= (val
>> 16) & 0x7F;
5433 case BFD_RELOC_TIC54X_16_OF_23
:
5435 bfd_put_16 (stdoutput
, val
, buf
);
5436 /* Indicate what we're actually writing, so that we don't get warnings
5437 about exceeding available space. */
5438 *valP
= val
& 0xFFFF;
5440 case BFD_RELOC_TIC54X_PARTLS7
:
5441 bfd_put_16 (stdoutput
,
5442 (bfd_get_16 (stdoutput
, buf
) & 0xFF80) | (val
& 0x7F),
5444 /* Indicate what we're actually writing, so that we don't get warnings
5445 about exceeding available space. */
5448 case BFD_RELOC_TIC54X_PARTMS9
:
5449 /* TI assembler doesn't shift its encoding for relocatable files, and is
5450 thus incompatible with this implementation's relocatable files. */
5451 bfd_put_16 (stdoutput
,
5452 (bfd_get_16 (stdoutput
, buf
) & 0xFE00) | (val
>> 7),
5456 case BFD_RELOC_TIC54X_23
:
5457 bfd_put_32 (stdoutput
,
5458 (bfd_get_32 (stdoutput
, buf
) & 0xFF800000) | val
,
5463 return 0; /* Return value is ignored. */
5466 /* This is our chance to record section alignment
5467 don't need to do anything here, since BFD does the proper encoding. */
5470 md_section_align (segment
, section_size
)
5471 segT segment ATTRIBUTE_UNUSED
;
5472 valueT section_size
;
5474 return section_size
;
5478 md_pcrel_from (fixP
)
5479 fixS
*fixP ATTRIBUTE_UNUSED
;
5484 #if defined OBJ_COFF
5487 tc_coff_fix2rtype (fixP
)
5490 return (fixP
->fx_r_type
);
5493 #endif /* OBJ_COFF */
5495 /* Mostly little-endian, but longwords (4 octets) get MS word stored
5499 tic54x_number_to_chars (buf
, val
, n
)
5505 number_to_chars_littleendian (buf
, val
, n
);
5508 number_to_chars_littleendian (buf
, val
>> 16 , 2);
5509 number_to_chars_littleendian (buf
+ 2, val
& 0xFFFF, 2);
5514 tic54x_estimate_size_before_relax (frag
, seg
)
5515 fragS
*frag ATTRIBUTE_UNUSED
;
5516 segT seg ATTRIBUTE_UNUSED
;
5521 /* We use this to handle bit allocations which we couldn't handle before due
5522 to symbols being in different frags. return number of octets added. */
5525 tic54x_relax_frag (frag
, stretch
)
5527 long stretch ATTRIBUTE_UNUSED
;
5529 symbolS
*sym
= frag
->fr_symbol
;
5535 struct bit_info
*bi
= (struct bit_info
*) frag
->fr_opcode
;
5536 int bit_offset
= frag_bit_offset (frag_prev (frag
, bi
->seg
), bi
->seg
);
5537 int size
= S_GET_VALUE (sym
);
5538 fragS
*prev_frag
= bit_offset_frag (frag_prev (frag
, bi
->seg
), bi
->seg
);
5539 int available
= 16 - bit_offset
;
5541 if (symbol_get_frag (sym
) != &zero_address_frag
5542 || S_IS_COMMON (sym
)
5543 || !S_IS_DEFINED (sym
))
5544 as_bad_where (frag
->fr_file
, frag
->fr_line
,
5545 _("non-absolute value used with .space/.bes"));
5549 as_warn (_("negative value ignored in %s"),
5550 bi
->type
== TYPE_SPACE
? ".space" :
5551 bi
->type
== TYPE_BES
? ".bes" : ".field");
5553 frag
->tc_frag_data
= frag
->fr_fix
= 0;
5557 if (bi
->type
== TYPE_FIELD
)
5559 /* Bit fields of 16 or larger will have already been handled. */
5560 if (bit_offset
!= 0 && available
>= size
)
5562 char *p
= prev_frag
->fr_literal
;
5563 valueT value
= bi
->value
;
5564 value
<<= available
- size
;
5565 value
|= ((unsigned short) p
[1] << 8) | p
[0];
5566 md_number_to_chars (p
, value
, 2);
5567 if ((prev_frag
->tc_frag_data
+= size
) == 16)
5568 prev_frag
->tc_frag_data
= 0;
5570 symbol_set_frag (bi
->sym
, prev_frag
);
5571 /* This frag is no longer used. */
5572 growth
= -frag
->fr_fix
;
5574 frag
->tc_frag_data
= 0;
5578 char *p
= frag
->fr_literal
;
5579 valueT value
= bi
->value
<< (16 - size
);
5580 md_number_to_chars (p
, value
, 2);
5581 if ((frag
->tc_frag_data
= size
) == 16)
5582 frag
->tc_frag_data
= 0;
5588 if (bit_offset
!= 0 && bit_offset
< 16)
5590 if (available
>= size
)
5592 if ((prev_frag
->tc_frag_data
+= size
) == 16)
5593 prev_frag
->tc_frag_data
= 0;
5595 symbol_set_frag (bi
->sym
, prev_frag
);
5596 /* This frag is no longer used. */
5597 growth
= -frag
->fr_fix
;
5599 frag
->tc_frag_data
= 0;
5602 if (bi
->type
== TYPE_SPACE
&& bi
->sym
)
5603 symbol_set_frag (bi
->sym
, prev_frag
);
5606 growth
= (size
+ 15) / 16 * OCTETS_PER_BYTE
- frag
->fr_fix
;
5607 for (i
= 0; i
< growth
; i
++)
5608 frag
->fr_literal
[i
] = 0;
5609 frag
->fr_fix
= growth
;
5610 frag
->tc_frag_data
= size
% 16;
5611 /* Make sure any BES label points to the LAST word allocated. */
5612 if (bi
->type
== TYPE_BES
&& bi
->sym
)
5613 S_SET_VALUE (bi
->sym
, frag
->fr_fix
/ OCTETS_PER_BYTE
- 1);
5616 frag
->fr_symbol
= 0;
5617 frag
->fr_opcode
= 0;
5624 tic54x_convert_frag (abfd
, seg
, frag
)
5625 bfd
*abfd ATTRIBUTE_UNUSED
;
5626 segT seg ATTRIBUTE_UNUSED
;
5629 /* Offset is in bytes. */
5630 frag
->fr_offset
= (frag
->fr_next
->fr_address
5632 - frag
->fr_fix
) / frag
->fr_var
;
5633 if (frag
->fr_offset
< 0)
5635 as_bad_where (frag
->fr_file
, frag
->fr_line
,
5636 _("attempt to .space/.bes backwards? (%ld)"),
5637 (long) frag
->fr_offset
);
5639 frag
->fr_type
= rs_space
;
5642 /* We need to avoid having labels defined for certain directives/pseudo-ops
5643 since once the label is defined, it's in the symbol table for good. TI
5644 syntax puts the symbol *before* the pseudo (which is kinda like MRI syntax,
5645 I guess, except I've never seen a definition of MRI syntax).
5647 C is the character that used to be at *REST, which points to the end of the
5650 Don't allow labels to start with '.' */
5653 tic54x_start_label (c
, rest
)
5657 /* If within .struct/.union, no auto line labels, please. */
5658 if (current_stag
!= NULL
)
5661 /* Disallow labels starting with "." */
5665 while (!is_end_of_line
[(int) label
[-1]])
5669 as_bad (_("Invalid label '%s'"), label
);
5674 if (is_end_of_line
[(int) c
])
5678 while (ISSPACE (c
= *++rest
))
5682 /* Don't let colon () define a label for any of these... */
5683 return (strncasecmp (rest
, ".tag", 4) != 0 || !ISSPACE (rest
[4]))
5684 && (strncasecmp (rest
, ".struct", 7) != 0 || !ISSPACE (rest
[7]))
5685 && (strncasecmp (rest
, ".union", 6) != 0 || !ISSPACE (rest
[6]))
5686 && (strncasecmp (rest
, ".macro", 6) != 0 || !ISSPACE (rest
[6]))
5687 && (strncasecmp (rest
, ".set", 4) != 0 || !ISSPACE (rest
[4]))
5688 && (strncasecmp (rest
, ".equ", 4) != 0 || !ISSPACE (rest
[4]));