* elf64-sh64.c (sh_elf64_relocate_section): Fix a typo from my
[deliverable/binutils-gdb.git] / gas / config / tc-tic54x.c
... / ...
CommitLineData
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)
4
5 This file is part of GAS, the GNU Assembler.
6
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)
10 any later version.
11
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.
16
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
20 02111-1307, USA. */
21
22/* Texas Instruments TMS320C54X machine specific gas.
23 Written by Timothy Wall (twall@alum.mit.edu).
24
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.
31
32 Tests to add to expect testsuite:
33 '=' and '==' with .if, .elseif, and .break
34
35 Incompatibilities (mostly trivial):
36 We don't allow '''
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.
43
44 COFF1 limits section names to 8 characters.
45 Some of the default behavior changed from COFF1 to COFF2.
46*/
47
48#include <stdlib.h>
49#include <limits.h>
50#include <errno.h>
51#include "as.h"
52#include "safe-ctype.h"
53#include "sb.h"
54#include "macro.h"
55#include "subsegs.h"
56#include "struc-symbol.h"
57#include "opcode/tic54x.h"
58#include "obj-coff.h"
59#include <math.h>
60
61#define MAX_LINE 256 /* Lines longer than this are truncated by TI's asm. */
62
63const char comment_chars[] = ";";
64const char line_comment_chars[] = ";*#"; /* At column zero only. */
65const char line_separator_chars[] = ""; /* Not permitted. */
66
67/* Characters which indicate that this is a floating point constant. */
68const char FLT_CHARS[] = "fF";
69
70/* Characters that can be used to separate mantissa from exp in FP
71 nums. */
72const char EXP_CHARS[] = "eE";
73
74/* Only word (et al.), align, or conditionals are allowed within
75 .struct/.union. */
76#define ILLEGAL_WITHIN_STRUCT() \
77 do \
78 if (current_stag != NULL) \
79 { \
80 as_bad (_("pseudo-op illegal within .struct/.union")); \
81 return; \
82 } \
83 while (0)
84
85void
86md_show_usage (stream)
87 FILE *stream;
88{
89 fprintf (stream, _("C54x-specific command line options:\n"));
90 fprintf (stream, _("-mfar-mode | -mf Use extended addressing\n"));
91 fprintf (stream, _("-mcpu=<CPU version> Specify the CPU version\n"));
92#if 0
93 fprintf (stream, _("-mcoff-version={0|1|2} Select COFF version\n"));
94#endif
95 fprintf (stream, _("-merrors-to-file <filename>\n"));
96 fprintf (stream, _("-me <filename> Redirect errors to a file\n"));
97}
98
99const char *md_shortopts = "";
100
101enum cpu_version
102{
103 VNONE = 0, V541 = 1, V542 = 2, V543 = 3, V545 = 5, V548 = 8, V549 = 9,
104 V545LP = 15, V546LP = 16
105};
106
107enum address_mode
108{
109 c_mode, /* 16-bit addresses. */
110 far_mode /* >16-bit addresses. */
111};
112
113#define OPTION_ADDRESS_MODE (OPTION_MD_BASE)
114#define OPTION_CPU_VERSION (OPTION_ADDRESS_MODE + 1)
115#define OPTION_COFF_VERSION (OPTION_CPU_VERSION + 1)
116#define OPTION_STDERR_TO_FILE (OPTION_COFF_VERSION + 1)
117
118struct option md_longopts[] =
119{
120 { "mfar-mode", no_argument, NULL, OPTION_ADDRESS_MODE },
121 { "mf", no_argument, NULL, OPTION_ADDRESS_MODE },
122 { "mcpu", required_argument, NULL, OPTION_CPU_VERSION },
123#if 0
124 { "mcoff-version", required_argument, NULL, OPTION_COFF_VERSION },
125#endif
126 { "merrors-to-file", required_argument, NULL, OPTION_STDERR_TO_FILE },
127 { "me", required_argument, NULL, OPTION_STDERR_TO_FILE },
128 { NULL, no_argument, NULL, 0},
129};
130
131size_t md_longopts_size = sizeof (md_longopts);
132
133static int assembly_begun = 0;
134/* Addressing mode is not entirely implemented; the latest rev of the Other
135 assembler doesn't seem to make any distinction whatsoever; all relocations
136 are stored as extended relocatiosn. Older versions used REL16 vs RELEXT16,
137 but now it seems all relocations are RELEXT16. We use all RELEXT16.
138
139 The cpu version is kind of a waste of time as well. There is one
140 instruction (RND) for LP devices only, and several for devices with
141 extended addressing only. We include it for compatibility. */
142static enum address_mode amode = c_mode;
143static enum cpu_version cpu = VNONE;
144
145/* Include string substitutions in listing? */
146static int listing_sslist = 0;
147
148/* Did we do subsym substitutions on the line? */
149static int substitution_line = 0;
150
151/* Last label seen. */
152static symbolS *last_label_seen = NULL;
153
154/* This ensures that all new labels are unique. */
155static int local_label_id;
156
157static struct hash_control *subsym_recurse_hash; /* Prevent infinite recurse. */
158static struct hash_control *math_hash; /* Built-in math functions. */
159/* Allow maximum levels of macro nesting; level 0 is the main substitution
160 symbol table. The other assembler only does 32 levels, so there! */
161static struct hash_control *subsym_hash[100];
162
163/* Keep track of local labels so we can substitute them before GAS sees them
164 since macros use their own 'namespace' for local labels, use a separate hash
165
166 We do our own local label handling 'cuz it's subtly different from the
167 stock GAS handling.
168
169 We use our own macro nesting counter, since GAS overloads it when expanding
170 other things (like conditionals and repeat loops). */
171static int macro_level = 0;
172static struct hash_control *local_label_hash[100];
173/* Keep track of struct/union tags. */
174static struct hash_control *stag_hash;
175static struct hash_control *op_hash;
176static struct hash_control *parop_hash;
177static struct hash_control *reg_hash;
178static struct hash_control *mmreg_hash;
179static struct hash_control *cc_hash;
180static struct hash_control *cc2_hash;
181static struct hash_control *cc3_hash;
182static struct hash_control *sbit_hash;
183static struct hash_control *misc_symbol_hash;
184
185static char *subsym_substitute PARAMS ((char *line, int forced));
186static char *subsym_lookup PARAMS ((char *name, int nest_level));
187static void subsym_create_or_replace PARAMS ((char *name, char *value));
188static float math_ceil PARAMS ((float, float));
189static float math_cvi PARAMS ((float, float));
190static float math_floor PARAMS ((float, float));
191static float math_fmod PARAMS ((float, float));
192static float math_int PARAMS ((float, float));
193static float math_round PARAMS ((float, float));
194static float math_sgn PARAMS ((float, float));
195static float math_trunc PARAMS ((float, float));
196static float math_acos PARAMS ((float, float));
197static float math_asin PARAMS ((float, float));
198static float math_atan PARAMS ((float, float));
199static float math_atan2 PARAMS ((float, float));
200static float math_cosh PARAMS ((float, float));
201static float math_cos PARAMS ((float, float));
202static float math_cvf PARAMS ((float, float));
203static float math_exp PARAMS ((float, float));
204static float math_fabs PARAMS ((float, float));
205static float math_ldexp PARAMS ((float, float));
206static float math_log10 PARAMS ((float, float));
207static float math_log PARAMS ((float, float));
208static float math_max PARAMS ((float, float));
209static float math_pow PARAMS ((float, float));
210static float math_sin PARAMS ((float, float));
211static float math_sinh PARAMS ((float, float));
212static float math_sqrt PARAMS ((float, float));
213static float math_tan PARAMS ((float, float));
214static float math_tanh PARAMS ((float, float));
215
216static struct stag
217{
218 symbolS *sym; /* Symbol for this stag; value is offset. */
219 const char *name; /* Shortcut to symbol name. */
220 bfd_vma size; /* Size of struct/union. */
221 int current_bitfield_offset; /* Temporary for tracking fields. */
222 int is_union;
223 struct stag_field /* List of fields. */
224 {
225 const char *name;
226 bfd_vma offset; /* Of start of this field. */
227 int bitfield_offset; /* Of start of this field. */
228 struct stag *stag; /* If field is struct/union. */
229 struct stag_field *next;
230 } *field;
231 /* For nesting; used only in stag construction. */
232 struct stag *inner; /* Enclosed .struct. */
233 struct stag *outer; /* Enclosing .struct. */
234} *current_stag = NULL;
235
236static segT stag_saved_seg;
237static subsegT stag_saved_subseg;
238
239/* Output a single character (upper octect is zero). */
240
241static void
242tic54x_emit_char (char c)
243{
244 expressionS exp;
245
246 exp.X_op = O_constant;
247 exp.X_add_number = c;
248 emit_expr (&exp, 2);
249}
250
251/* Walk backwards in the frag chain. */
252
253static fragS *
254frag_prev (fragS *frag, segT seg)
255{
256 segment_info_type *seginfo = seg_info (seg);
257 fragS *fragp;
258
259 for (fragp = seginfo->frchainP->frch_root; fragp; fragp = fragp->fr_next)
260 if (fragp->fr_next == frag)
261 return fragp;
262
263 return NULL;
264}
265
266static fragS *
267bit_offset_frag (fragS *frag, segT seg)
268{
269 while (frag != NULL)
270 {
271 if (frag->fr_fix == 0
272 && frag->fr_opcode == NULL
273 && frag->tc_frag_data == 0)
274 frag = frag_prev (frag, seg);
275 else
276 return frag;
277 }
278 return NULL;
279}
280
281/* Return the number of bits allocated in the most recent word, or zero if
282 none. .field/.space/.bes may leave words partially allocated. */
283
284static int
285frag_bit_offset (fragS *frag, segT seg)
286{
287 frag = bit_offset_frag (frag, seg);
288
289 if (frag)
290 return frag->fr_opcode != NULL ? -1 : frag->tc_frag_data;
291
292 return 0;
293}
294
295/* Read an expression from a C string; returns a pointer past the end of the
296 expression. */
297
298static char *
299parse_expression (char *str, expressionS * exp)
300{
301 char *s;
302 char *tmp;
303
304 tmp = input_line_pointer; /* Save line pointer. */
305 input_line_pointer = str;
306 expression (exp);
307 s = input_line_pointer;
308 input_line_pointer = tmp; /* Restore line pointer. */
309 return s; /* Return pointer to where parsing stopped. */
310}
311
312/* .asg "character-string"|character-string, symbol
313
314 .eval is the only pseudo-op allowed to perform arithmetic on substitution
315 symbols. all other use of symbols defined with .asg are currently
316 unsupported. */
317
318static void
319tic54x_asg (int x ATTRIBUTE_UNUSED)
320{
321 int c;
322 char *name;
323 char *str;
324 char *tmp;
325 int quoted = *input_line_pointer == '"';
326
327 ILLEGAL_WITHIN_STRUCT ();
328
329 if (quoted)
330 {
331 int len;
332 str = demand_copy_C_string (&len);
333 c = *input_line_pointer;
334 }
335 else
336 {
337 str = input_line_pointer;
338 while ((c = *input_line_pointer) != ',')
339 {
340 if (is_end_of_line[(int) *input_line_pointer])
341 break;
342 ++input_line_pointer;
343 }
344 *input_line_pointer = 0;
345 }
346 if (c != ',')
347 {
348 as_bad (_("Comma and symbol expected for '.asg STRING, SYMBOL'"));
349 ignore_rest_of_line ();
350 return;
351 }
352
353 name = ++input_line_pointer;
354 c = get_symbol_end (); /* Get terminator. */
355 if (!ISALPHA (*name))
356 {
357 as_bad ("symbols assigned with .asg must begin with a letter");
358 ignore_rest_of_line ();
359 return;
360 }
361
362 tmp = xmalloc (strlen (str) + 1);
363 strcpy (tmp, str);
364 str = tmp;
365 tmp = xmalloc (strlen (name) + 1);
366 strcpy (tmp, name);
367 name = tmp;
368 subsym_create_or_replace (name, str);
369 *input_line_pointer = c;
370 demand_empty_rest_of_line ();
371}
372
373/* .eval expression, symbol
374 There's something screwy about this. The other assembler sometimes does and
375 sometimes doesn't substitute symbols defined with .eval.
376 We'll put the symbols into the subsym table as well as the normal symbol
377 table, since that's what works best. */
378
379static void
380tic54x_eval (int x ATTRIBUTE_UNUSED)
381{
382 char c;
383 int value;
384 char *name;
385 symbolS *symbolP;
386 char valuestr[32], *tmp;
387 int quoted;
388
389 ILLEGAL_WITHIN_STRUCT ();
390
391 SKIP_WHITESPACE ();
392
393 quoted = *input_line_pointer == '"';
394 if (quoted)
395 ++input_line_pointer;
396 value = get_absolute_expression ();
397 if (quoted)
398 {
399 if (*input_line_pointer != '"')
400 {
401 as_bad (_("Unterminated string after absolute expression"));
402 ignore_rest_of_line ();
403 return;
404 }
405 ++input_line_pointer;
406 }
407 if (*input_line_pointer++ != ',')
408 {
409 as_bad (_("Comma and symbol expected for '.eval EXPR, SYMBOL'"));
410 ignore_rest_of_line ();
411 return;
412 }
413 name = input_line_pointer;
414 c = get_symbol_end (); /* Get terminator. */
415 tmp = xmalloc (strlen (name) + 1);
416 name = strcpy (tmp, name);
417 *input_line_pointer = c;
418
419 if (!ISALPHA (*name))
420 {
421 as_bad (_("symbols assigned with .eval must begin with a letter"));
422 ignore_rest_of_line ();
423 return;
424 }
425 symbolP = symbol_new (name, absolute_section,
426 (valueT) value, &zero_address_frag);
427 SF_SET_LOCAL (symbolP);
428 symbol_table_insert (symbolP);
429
430 /* The "other" assembler sometimes doesn't put .eval's in the subsym table
431 But since there's not written rule as to when, don't even bother trying
432 to match their behavior. */
433 sprintf (valuestr, "%d", value);
434 tmp = xmalloc (strlen (valuestr) + 1);
435 strcpy (tmp, valuestr);
436 subsym_create_or_replace (name, tmp);
437
438 demand_empty_rest_of_line ();
439}
440
441/* .bss symbol, size [, [blocking flag] [, alignment flag]
442
443 alignment is to a longword boundary; blocking is to 128-word boundary.
444
445 1) if there is a hole in memory, this directive should attempt to fill it
446 (not yet implemented).
447
448 2) if the blocking flag is not set, allocate at the current SPC
449 otherwise, check to see if the current SPC plus the space to be
450 allocated crosses the page boundary (128 words).
451 if there's not enough space, create a hole and align with the next page
452 boundary.
453 (not yet implemented). */
454
455static void
456tic54x_bss (int x ATTRIBUTE_UNUSED)
457{
458 char c;
459 char *name;
460 char *p;
461 int words;
462 segT current_seg;
463 subsegT current_subseg;
464 symbolS *symbolP;
465 int block = 0;
466 int align = 0;
467
468 ILLEGAL_WITHIN_STRUCT ();
469
470 current_seg = now_seg; /* Save current seg. */
471 current_subseg = now_subseg; /* Save current subseg. */
472
473 name = input_line_pointer;
474 c = get_symbol_end (); /* Get terminator. */
475 if (c != ',')
476 {
477 as_bad (".bss size argument missing\n");
478 ignore_rest_of_line ();
479 return;
480 }
481
482 ++input_line_pointer;
483 words = get_absolute_expression ();
484 if (words < 0)
485 {
486 as_bad (".bss size %d < 0!", words);
487 ignore_rest_of_line ();
488 return;
489 }
490
491 if (*input_line_pointer == ',')
492 {
493 /* The blocking flag may be missing. */
494 ++input_line_pointer;
495 if (*input_line_pointer != ',')
496 block = get_absolute_expression ();
497 else
498 block = 0;
499
500 if (*input_line_pointer == ',')
501 {
502 ++input_line_pointer;
503 align = get_absolute_expression ();
504 }
505 else
506 align = 0;
507 }
508 else
509 block = align = 0;
510
511 subseg_set (bss_section, 0);
512 symbolP = symbol_find_or_make (name);
513
514 if (S_GET_SEGMENT (symbolP) == bss_section)
515 symbolP->sy_frag->fr_symbol = (symbolS *) NULL;
516
517 symbol_set_frag (symbolP, frag_now);
518 p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
519 (offsetT) (words * OCTETS_PER_BYTE), (char *) 0);
520 *p = 0; /* Fill char. */
521
522 S_SET_SEGMENT (symbolP, bss_section);
523
524 /* The symbol may already have been created with a preceding
525 ".globl" directive -- be careful not to step on storage class
526 in that case. Otherwise, set it to static. */
527 if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
528 S_SET_STORAGE_CLASS (symbolP, C_STAT);
529
530 if (align)
531 {
532 /* s_align eats end of line; restore it */
533 s_align_bytes (4);
534 --input_line_pointer;
535 }
536
537 if (block)
538 bss_section->flags |= SEC_BLOCK;
539
540 subseg_set (current_seg, current_subseg); /* Restore current seg. */
541 demand_empty_rest_of_line ();
542}
543
544static void
545stag_add_field_symbols (struct stag *stag,
546 const char *path,
547 bfd_vma base_offset,
548 symbolS *rootsym,
549 const char *root_stag_name)
550{
551 char prefix[strlen (path) + 2];
552 struct stag_field *field = stag->field;
553
554 /* Construct a symbol for every field contained within this structure
555 including fields within structure fields. */
556 strcpy (prefix, path);
557 if (*path)
558 strcat (prefix, ".");
559
560 while (field != NULL)
561 {
562 int len = strlen (prefix) + strlen (field->name) + 2;
563 char *name = xmalloc (len);
564 strcpy (name, prefix);
565 strcat (name, field->name);
566
567 if (rootsym == NULL)
568 {
569 symbolS *sym;
570 sym = symbol_new (name, absolute_section,
571 (field->stag ? field->offset :
572 (valueT) (base_offset + field->offset)),
573 &zero_address_frag);
574 SF_SET_LOCAL (sym);
575 symbol_table_insert (sym);
576 }
577 else
578 {
579 char *replacement = xmalloc (strlen (name)
580 + strlen (stag->name) + 2);
581 strcpy (replacement, S_GET_NAME (rootsym));
582 strcat (replacement, "+");
583 strcat (replacement, root_stag_name);
584 strcat (replacement, name + strlen (S_GET_NAME (rootsym)));
585 hash_insert (subsym_hash[0], name, replacement);
586 }
587
588 /* Recurse if the field is a structure.
589 Note the field offset is relative to the outermost struct. */
590 if (field->stag != NULL)
591 stag_add_field_symbols (field->stag, name,
592 field->offset,
593 rootsym, root_stag_name);
594 field = field->next;
595 }
596}
597
598/* Keep track of stag fields so that when structures are nested we can add the
599 complete dereferencing symbols to the symbol table. */
600
601static void
602stag_add_field (struct stag *parent,
603 const char *name,
604 bfd_vma offset,
605 struct stag *stag)
606{
607 struct stag_field *sfield = xmalloc (sizeof (struct stag_field));
608
609 memset (sfield, 0, sizeof (*sfield));
610 sfield->name = strcpy (xmalloc (strlen (name) + 1), name);
611 sfield->offset = offset;
612 sfield->bitfield_offset = parent->current_bitfield_offset;
613 sfield->stag = stag;
614 if (parent->field == NULL)
615 parent->field = sfield;
616 else
617 {
618 struct stag_field *sf = parent->field;
619 while (sf->next != NULL)
620 sf = sf->next;
621 sf->next = sfield;
622 }
623 /* Only create a symbol for this field if the parent has no name. */
624 if (!strncmp (".fake", parent->name, 5))
625 {
626 symbolS *sym = symbol_new (name, absolute_section,
627 (valueT) offset, &zero_address_frag);
628 SF_SET_LOCAL (sym);
629 symbol_table_insert (sym);
630 }
631}
632
633/* [STAG] .struct [OFFSET]
634 Start defining structure offsets (symbols in absolute section). */
635
636static void
637tic54x_struct (int arg)
638{
639 int start_offset = 0;
640 int is_union = arg;
641
642 if (!current_stag)
643 {
644 /* Starting a new struct, switch to absolute section. */
645 stag_saved_seg = now_seg;
646 stag_saved_subseg = now_subseg;
647 subseg_set (absolute_section, 0);
648 }
649 /* Align the current pointer. */
650 else if (current_stag->current_bitfield_offset != 0)
651 {
652 ++abs_section_offset;
653 current_stag->current_bitfield_offset = 0;
654 }
655
656 /* Offset expression is only meaningful for global .structs. */
657 if (!is_union)
658 {
659 /* Offset is ignored in inner structs. */
660 SKIP_WHITESPACE ();
661 if (!is_end_of_line[(int) *input_line_pointer])
662 start_offset = get_absolute_expression ();
663 else
664 start_offset = 0;
665 }
666
667 if (current_stag)
668 {
669 /* Nesting, link to outer one. */
670 current_stag->inner = (struct stag *) xmalloc (sizeof (struct stag));
671 memset (current_stag->inner, 0, sizeof (struct stag));
672 current_stag->inner->outer = current_stag;
673 current_stag = current_stag->inner;
674 if (start_offset)
675 as_warn (_("Offset on nested structures is ignored"));
676 start_offset = abs_section_offset;
677 }
678 else
679 {
680 current_stag = (struct stag *) xmalloc (sizeof (struct stag));
681 memset (current_stag, 0, sizeof (struct stag));
682 abs_section_offset = start_offset;
683 }
684 current_stag->is_union = is_union;
685
686 if (line_label == NULL)
687 {
688 static int struct_count = 0;
689 char fake[] = ".fake_stagNNNNNNN";
690 sprintf (fake, ".fake_stag%d", struct_count++);
691 current_stag->sym = symbol_new (fake, absolute_section,
692 (valueT) abs_section_offset,
693 &zero_address_frag);
694 }
695 else
696 {
697 char label[strlen (S_GET_NAME (line_label)) + 1];
698 strcpy (label, S_GET_NAME (line_label));
699 current_stag->sym = symbol_new (label, absolute_section,
700 (valueT) abs_section_offset,
701 &zero_address_frag);
702 }
703 current_stag->name = S_GET_NAME (current_stag->sym);
704 SF_SET_LOCAL (current_stag->sym);
705 /* Nested .structs don't go into the symbol table. */
706 if (current_stag->outer == NULL)
707 symbol_table_insert (current_stag->sym);
708
709 line_label = NULL;
710}
711
712/* [LABEL] .endstruct
713 finish defining structure offsets; optional LABEL's value will be the size
714 of the structure. */
715
716static void
717tic54x_endstruct (int is_union)
718{
719 int size;
720 const char *path =
721 !strncmp (current_stag->name, ".fake", 5) ? "" : current_stag->name;
722
723 if (!current_stag || current_stag->is_union != is_union)
724 {
725 as_bad (_(".end%s without preceding .%s"),
726 is_union ? "union" : "struct",
727 is_union ? "union" : "struct");
728 ignore_rest_of_line ();
729 return;
730 }
731
732 /* Align end of structures. */
733 if (current_stag->current_bitfield_offset)
734 {
735 ++abs_section_offset;
736 current_stag->current_bitfield_offset = 0;
737 }
738
739 if (current_stag->is_union)
740 size = current_stag->size;
741 else
742 size = abs_section_offset - S_GET_VALUE (current_stag->sym);
743 if (line_label != NULL)
744 {
745 S_SET_VALUE (line_label, size);
746 symbol_table_insert (line_label);
747 line_label = NULL;
748 }
749
750 /* Union size has already been calculated. */
751 if (!current_stag->is_union)
752 current_stag->size = size;
753 /* Nested .structs don't get put in the stag table. */
754 if (current_stag->outer == NULL)
755 {
756 hash_insert (stag_hash, current_stag->name, current_stag);
757 stag_add_field_symbols (current_stag, path,
758 S_GET_VALUE (current_stag->sym),
759 NULL, NULL);
760 }
761 current_stag = current_stag->outer;
762
763 /* If this is a nested .struct/.union, add it as a field to the enclosing
764 one. otherwise, restore the section we were in. */
765 if (current_stag != NULL)
766 {
767 stag_add_field (current_stag, current_stag->inner->name,
768 S_GET_VALUE (current_stag->inner->sym),
769 current_stag->inner);
770 }
771 else
772 subseg_set (stag_saved_seg, stag_saved_subseg);
773}
774
775/* [LABEL] .tag STAG
776 Reference a structure within a structure, as a sized field with an optional
777 label.
778 If used outside of a .struct/.endstruct, overlays the given structure
779 format on the existing allocated space. */
780
781static void
782tic54x_tag (int ignore ATTRIBUTE_UNUSED)
783{
784 char *name = input_line_pointer;
785 int c = get_symbol_end ();
786 struct stag *stag = (struct stag *) hash_find (stag_hash, name);
787
788 if (!stag)
789 {
790 if (*name)
791 as_bad (_("Unrecognized struct/union tag '%s'"), name);
792 else
793 as_bad (_(".tag requires a structure tag"));
794 ignore_rest_of_line ();
795 return;
796 }
797 if (line_label == NULL)
798 {
799 as_bad (_("Label required for .tag"));
800 ignore_rest_of_line ();
801 return;
802 }
803 else
804 {
805 char label[strlen (S_GET_NAME (line_label)) + 1];
806
807 strcpy (label, S_GET_NAME (line_label));
808 if (current_stag != NULL)
809 stag_add_field (current_stag, label,
810 abs_section_offset - S_GET_VALUE (current_stag->sym),
811 stag);
812 else
813 {
814 symbolS *sym = symbol_find (label);
815 if (!sym)
816 {
817 as_bad (_(".tag target '%s' undefined"), label);
818 ignore_rest_of_line ();
819 return;
820 }
821 stag_add_field_symbols (stag, S_GET_NAME (sym),
822 S_GET_VALUE (stag->sym), sym, stag->name);
823 }
824 }
825
826 /* Bump by the struct size, but only if we're within a .struct section. */
827 if (current_stag != NULL && !current_stag->is_union)
828 abs_section_offset += stag->size;
829
830 *input_line_pointer = c;
831 demand_empty_rest_of_line ();
832 line_label = NULL;
833}
834
835/* Handle all .byte, .char, .double, .field, .float, .half, .int, .long,
836 .short, .string, .ubyte, .uchar, .uhalf, .uint, .ulong, .ushort, .uword,
837 and .word. */
838
839static void
840tic54x_struct_field (int type)
841{
842 int size;
843 int count = 1;
844 int new_bitfield_offset = 0;
845 int field_align = current_stag->current_bitfield_offset != 0;
846 int longword_align = 0;
847
848 SKIP_WHITESPACE ();
849 if (!is_end_of_line[(int) *input_line_pointer])
850 count = get_absolute_expression ();
851
852 switch (type)
853 {
854 case 'b':
855 case 'B':
856 case 'c':
857 case 'C':
858 case 'h':
859 case 'H':
860 case 'i':
861 case 'I':
862 case 's':
863 case 'S':
864 case 'w':
865 case 'W':
866 case '*': /* String. */
867 size = 1;
868 break;
869 case 'f':
870 case 'l':
871 case 'L':
872 longword_align = 1;
873 size = 2;
874 break;
875 case '.': /* Bitfield. */
876 size = 0;
877 if (count < 1 || count > 32)
878 {
879 as_bad (_(".field count '%d' out of range (1 <= X <= 32)"), count);
880 ignore_rest_of_line ();
881 return;
882 }
883 if (current_stag->current_bitfield_offset + count > 16)
884 {
885 /* Set the appropriate size and new field offset. */
886 if (count == 32)
887 {
888 size = 2;
889 count = 1;
890 }
891 else if (count > 16)
892 {
893 size = 1;
894 count = 1;
895 new_bitfield_offset = count - 16;
896 }
897 else
898 {
899 new_bitfield_offset = count;
900 }
901 }
902 else
903 {
904 field_align = 0;
905 new_bitfield_offset = current_stag->current_bitfield_offset + count;
906 }
907 break;
908 default:
909 as_bad (_("Unrecognized field type '%c'"), type);
910 ignore_rest_of_line ();
911 return;
912 }
913
914 if (field_align)
915 {
916 /* Align to the actual starting position of the field. */
917 current_stag->current_bitfield_offset = 0;
918 ++abs_section_offset;
919 }
920 /* Align to longword boundary. */
921 if (longword_align && (abs_section_offset & 0x1))
922 ++abs_section_offset;
923
924 if (line_label == NULL)
925 {
926 static int fieldno = 0;
927 char fake[] = ".fake_fieldNNNNN";
928 sprintf (fake, ".fake_field%d", fieldno++);
929 stag_add_field (current_stag, fake,
930 abs_section_offset - S_GET_VALUE (current_stag->sym),
931 NULL);
932 }
933 else
934 {
935 char label[strlen (S_GET_NAME (line_label) + 1)];
936 strcpy (label, S_GET_NAME (line_label));
937 stag_add_field (current_stag, label,
938 abs_section_offset - S_GET_VALUE (current_stag->sym),
939 NULL);
940 }
941
942 if (current_stag->is_union)
943 {
944 /* Note we treat the element as if it were an array of COUNT. */
945 if (current_stag->size < (unsigned) size * count)
946 current_stag->size = size * count;
947 }
948 else
949 {
950 abs_section_offset += (unsigned) size * count;
951 current_stag->current_bitfield_offset = new_bitfield_offset;
952 }
953 line_label = NULL;
954}
955
956/* Handle .byte, .word. .int, .long and all variants. */
957
958int emitting_long = 0;
959static void
960tic54x_cons (int type)
961{
962 register unsigned int c;
963 int octets;
964
965 /* If we're within a .struct construct, don't actually allocate space. */
966 if (current_stag != NULL)
967 {
968 tic54x_struct_field (type);
969 return;
970 }
971
972#ifdef md_flush_pending_output
973 md_flush_pending_output ();
974#endif
975
976 generate_lineno_debug ();
977
978 /* Align long words to long word boundaries (4 octets). */
979 if (type == 'l' || type == 'L')
980 {
981 frag_align (2, 0, 2);
982 /* If there's a label, assign it to the first allocated word. */
983 if (line_label != NULL)
984 {
985 symbol_set_frag (line_label, frag_now);
986 S_SET_VALUE (line_label, frag_now_fix ());
987 }
988 }
989
990 switch (type)
991 {
992 case 'l':
993 case 'L':
994 case 'x':
995 octets = 4;
996 break;
997 case 'b':
998 case 'B':
999 case 'c':
1000 case 'C':
1001 octets = 1;
1002 break;
1003 default:
1004 octets = 2;
1005 break;
1006 }
1007
1008 do
1009 {
1010 if (*input_line_pointer == '"')
1011 {
1012 input_line_pointer++;
1013 while (is_a_char (c = next_char_of_string ()))
1014 tic54x_emit_char (c);
1015 know (input_line_pointer[-1] == '\"');
1016 }
1017 else
1018 {
1019 expressionS exp;
1020
1021 input_line_pointer = parse_expression (input_line_pointer, &exp);
1022 if (exp.X_op == O_constant)
1023 {
1024 offsetT value = exp.X_add_number;
1025 /* Truncate overflows. */
1026 switch (octets)
1027 {
1028 case 1:
1029 if ((value > 0 && value > 0xFF)
1030 || (value < 0 && value < - 0x100))
1031 as_warn ("Overflow in expression, truncated to 8 bits");
1032 break;
1033 case 2:
1034 if ((value > 0 && value > 0xFFFF)
1035 || (value < 0 && value < - 0x10000))
1036 as_warn ("Overflow in expression, truncated to 16 bits");
1037 break;
1038 }
1039 }
1040 if (exp.X_op != O_constant && octets < 2)
1041 {
1042 /* Disallow .byte with a non constant expression that will
1043 require relocation. */
1044 as_bad (_("Relocatable values require at least WORD storage"));
1045 ignore_rest_of_line ();
1046 return;
1047 }
1048
1049 if (exp.X_op != O_constant
1050 && amode == c_mode
1051 && octets == 4)
1052 {
1053 /* FIXME -- at one point TI tools used to output REL16
1054 relocations, but I don't think the latest tools do at all
1055 The current tools output extended relocations regardless of
1056 the addresing mode (I actually think that ".c_mode" is
1057 totally ignored in the latest tools). */
1058 amode = far_mode;
1059 emitting_long = 1;
1060 emit_expr (&exp, 4);
1061 emitting_long = 0;
1062 amode = c_mode;
1063 }
1064 else
1065 {
1066 emitting_long = octets == 4;
1067 emit_expr (&exp, (octets == 1) ? 2 : octets);
1068 emitting_long = 0;
1069 }
1070 }
1071 }
1072 while (*input_line_pointer++ == ',');
1073
1074 input_line_pointer--; /* Put terminator back into stream. */
1075 demand_empty_rest_of_line ();
1076}
1077
1078/* .global <symbol>[,...,<symbolN>]
1079 .def <symbol>[,...,<symbolN>]
1080 .ref <symbol>[,...,<symbolN>]
1081
1082 These all identify global symbols.
1083
1084 .def means the symbol is defined in the current module and can be accessed
1085 by other files. The symbol should be placed in the symbol table.
1086
1087 .ref means the symbol is used in the current module but defined in another
1088 module. The linker is to resolve this symbol's definition at link time.
1089
1090 .global should act as a .ref or .def, as needed.
1091
1092 global, def and ref all have symbol storage classes of C_EXT.
1093
1094 I can't identify any difference in how the "other" c54x assembler treats
1095 these, so we ignore the type here. */
1096
1097void
1098tic54x_global (int type)
1099{
1100 char *name;
1101 int c;
1102 symbolS *symbolP;
1103
1104 if (type == 'r')
1105 as_warn (_("Use of .def/.ref is deprecated. Use .global instead"));
1106
1107 ILLEGAL_WITHIN_STRUCT ();
1108
1109 do
1110 {
1111 name = input_line_pointer;
1112 c = get_symbol_end ();
1113 symbolP = symbol_find_or_make (name);
1114
1115 *input_line_pointer = c;
1116 S_SET_STORAGE_CLASS (symbolP, C_EXT);
1117 if (c == ',')
1118 {
1119 input_line_pointer++;
1120 if (is_end_of_line[(int) *input_line_pointer])
1121 c = *input_line_pointer;
1122 }
1123 }
1124 while (c == ',');
1125
1126 demand_empty_rest_of_line ();
1127}
1128
1129/* Remove the symbol from the local label hash lookup. */
1130
1131static void
1132tic54x_remove_local_label (const char *key,
1133 PTR value ATTRIBUTE_UNUSED)
1134{
1135 PTR *elem = hash_delete (local_label_hash[macro_level], key);
1136 free (elem);
1137}
1138
1139/* Reset all local labels. */
1140
1141static void
1142tic54x_clear_local_labels (int ignored ATTRIBUTE_UNUSED)
1143{
1144 hash_traverse (local_label_hash[macro_level], tic54x_remove_local_label);
1145}
1146
1147/* .text
1148 .data
1149 .sect "section name"
1150
1151 Initialized section
1152 make sure local labels get cleared when changing sections
1153
1154 ARG is 't' for text, 'd' for data, or '*' for a named section
1155
1156 For compatibility, '*' sections are SEC_CODE if instructions are
1157 encountered, or SEC_DATA if not.
1158*/
1159
1160static void
1161tic54x_sect (int arg)
1162{
1163 ILLEGAL_WITHIN_STRUCT ();
1164
1165 /* Local labels are cleared when changing sections. */
1166 tic54x_clear_local_labels (0);
1167
1168 if (arg == 't')
1169 s_text (0);
1170 else if (arg == 'd')
1171 s_data (0);
1172 else
1173 {
1174 char *name = NULL;
1175 int len;
1176 /* If there are quotes, remove them. */
1177 if (*input_line_pointer == '"')
1178 {
1179 name = demand_copy_C_string (&len);
1180 demand_empty_rest_of_line ();
1181 name = strcpy (xmalloc (len + 10), name);
1182 }
1183 else
1184 {
1185 int c;
1186 name = input_line_pointer;
1187 c = get_symbol_end ();
1188 len = strlen(name);
1189 name = strcpy (xmalloc (len + 10), name);
1190 *input_line_pointer = c;
1191 demand_empty_rest_of_line ();
1192 }
1193 /* Make sure all named initialized sections flagged properly. If we
1194 encounter instructions, we'll flag it with SEC_CODE as well. */
1195 strcat (name, ",\"w\"\n");
1196 input_scrub_insert_line (name);
1197 obj_coff_section (0);
1198
1199 /* If there was a line label, make sure that it gets assigned the proper
1200 section. This is for compatibility, even though the actual behavior
1201 is not explicitly defined. For consistency, we make .sect behave
1202 like .usect, since that is probably what people expect. */
1203 if (line_label != NULL)
1204 {
1205 S_SET_SEGMENT (line_label, now_seg);
1206 symbol_set_frag (line_label, frag_now);
1207 S_SET_VALUE (line_label, frag_now_fix ());
1208 if (S_GET_STORAGE_CLASS (line_label) != C_EXT)
1209 S_SET_STORAGE_CLASS (line_label, C_LABEL);
1210 }
1211 }
1212}
1213
1214/* [symbol] .space space_in_bits
1215 [symbol] .bes space_in_bits
1216 BES puts the symbol at the *last* word allocated
1217
1218 cribbed from s_space. */
1219
1220static void
1221tic54x_space (int arg)
1222{
1223 expressionS exp;
1224 char *p = 0;
1225 int octets = 0;
1226 long words;
1227 int bits_per_byte = (OCTETS_PER_BYTE * 8);
1228 int bit_offset = 0;
1229 symbolS *label = line_label;
1230 int bes = arg;
1231
1232 ILLEGAL_WITHIN_STRUCT ();
1233
1234#ifdef md_flush_pending_output
1235 md_flush_pending_output ();
1236#endif
1237
1238 /* Read the bit count. */
1239 expression (&exp);
1240
1241 /* Some expressions are unresolvable until later in the assembly pass;
1242 postpone until relaxation/fixup. we also have to postpone if a previous
1243 partial allocation has not been completed yet. */
1244 if (exp.X_op != O_constant || frag_bit_offset (frag_now, now_seg) == -1)
1245 {
1246 struct bit_info *bi = xmalloc (sizeof (struct bit_info));
1247 char *p;
1248
1249 bi->seg = now_seg;
1250 bi->type = bes;
1251 bi->sym = label;
1252 p = frag_var (rs_machine_dependent,
1253 65536 * 2, 1, (relax_substateT) 0,
1254 make_expr_symbol (&exp), (offsetT) 0,
1255 (char *) bi);
1256 if (p)
1257 *p = 0;
1258
1259 return;
1260 }
1261
1262 /* Reduce the required size by any bit offsets currently left over
1263 from a previous .space/.bes/.field directive. */
1264 bit_offset = frag_now->tc_frag_data;
1265 if (bit_offset != 0 && bit_offset < 16)
1266 {
1267 int spare_bits = bits_per_byte - bit_offset;
1268 if (spare_bits >= exp.X_add_number)
1269 {
1270 /* Don't have to do anything; sufficient bits have already been
1271 allocated; just point the label to the right place. */
1272 if (label != NULL)
1273 {
1274 symbol_set_frag (label, frag_now);
1275 S_SET_VALUE (label, frag_now_fix () - 1);
1276 label = NULL;
1277 }
1278 frag_now->tc_frag_data += exp.X_add_number;
1279 goto getout;
1280 }
1281 exp.X_add_number -= spare_bits;
1282 /* Set the label to point to the first word allocated, which in this
1283 case is the previous word, which was only partially filled. */
1284 if (!bes && label != NULL)
1285 {
1286 symbol_set_frag (label, frag_now);
1287 S_SET_VALUE (label, frag_now_fix () - 1);
1288 label = NULL;
1289 }
1290 }
1291 /* Convert bits to bytes/words and octets, rounding up. */
1292 words = ((exp.X_add_number + bits_per_byte - 1) / bits_per_byte);
1293 /* How many do we have left over? */
1294 bit_offset = exp.X_add_number % bits_per_byte;
1295 octets = words * OCTETS_PER_BYTE;
1296 if (octets < 0)
1297 {
1298 as_warn (_(".space/.bes repeat count is negative, ignored"));
1299 goto getout;
1300 }
1301 else if (octets == 0)
1302 {
1303 as_warn (_(".space/.bes repeat count is zero, ignored"));
1304 goto getout;
1305 }
1306
1307 /* If we are in the absolute section, just bump the offset. */
1308 if (now_seg == absolute_section)
1309 {
1310 abs_section_offset += words;
1311 if (bes && label != NULL)
1312 S_SET_VALUE (label, abs_section_offset - 1);
1313 frag_now->tc_frag_data = bit_offset;
1314 goto getout;
1315 }
1316
1317 if (!need_pass_2)
1318 p = frag_var (rs_fill, 1, 1,
1319 (relax_substateT) 0, (symbolS *) 0,
1320 (offsetT) octets, (char *) 0);
1321
1322 /* Make note of how many bits of this word we've allocated so far. */
1323 frag_now->tc_frag_data = bit_offset;
1324
1325 /* .bes puts label at *last* word allocated. */
1326 if (bes && label != NULL)
1327 {
1328 symbol_set_frag (label, frag_now);
1329 S_SET_VALUE (label, frag_now_fix () - 1);
1330 }
1331
1332 if (p)
1333 *p = 0;
1334
1335 getout:
1336
1337 demand_empty_rest_of_line ();
1338}
1339
1340/* [symbol] .usect "section-name", size-in-words
1341 [, [blocking-flag] [, alignment-flag]]
1342
1343 Unitialized section.
1344 Non-zero blocking means that if the section would cross a page (128-word)
1345 boundary, it will be page-aligned.
1346 Non-zero alignment aligns on a longword boundary.
1347
1348 Has no effect on the current section. */
1349
1350static void
1351tic54x_usect (int x ATTRIBUTE_UNUSED)
1352{
1353 char c;
1354 char *name;
1355 char *section_name;
1356 char *p;
1357 segT seg;
1358 int size, blocking_flag, alignment_flag;
1359 segT current_seg;
1360 subsegT current_subseg;
1361 flagword flags;
1362
1363 ILLEGAL_WITHIN_STRUCT ();
1364
1365 current_seg = now_seg; /* Save current seg. */
1366 current_subseg = now_subseg; /* Save current subseg. */
1367
1368 if (*input_line_pointer == '"')
1369 input_line_pointer++;
1370 section_name = input_line_pointer;
1371 c = get_symbol_end (); /* Get terminator. */
1372 input_line_pointer++; /* Skip null symbol terminator. */
1373 name = xmalloc (input_line_pointer - section_name + 1);
1374 strcpy (name, section_name);
1375
1376 if (*input_line_pointer == ',')
1377 ++input_line_pointer;
1378 else if (c != ',')
1379 {
1380 as_bad (_("Missing size argument"));
1381 ignore_rest_of_line ();
1382 return;
1383 }
1384
1385 size = get_absolute_expression ();
1386
1387 /* Read a possibly present third argument (blocking flag). */
1388 if (*input_line_pointer == ',')
1389 {
1390 ++input_line_pointer;
1391 if (*input_line_pointer != ',')
1392 blocking_flag = get_absolute_expression ();
1393 else
1394 blocking_flag = 0;
1395
1396 /* Read a possibly present fourth argument (alignment flag). */
1397 if (*input_line_pointer == ',')
1398 {
1399 ++input_line_pointer;
1400 alignment_flag = get_absolute_expression ();
1401 }
1402 else
1403 alignment_flag = 0;
1404 }
1405 else
1406 blocking_flag = alignment_flag = 0;
1407
1408 seg = subseg_new (name, 0);
1409 flags = bfd_get_section_flags (stdoutput, seg) | SEC_ALLOC;
1410
1411 if (alignment_flag)
1412 {
1413 /* s_align eats end of line; restore it. */
1414 s_align_bytes (4);
1415 --input_line_pointer;
1416 }
1417
1418 if (line_label != NULL)
1419 {
1420 S_SET_SEGMENT (line_label, seg);
1421 symbol_set_frag (line_label, frag_now);
1422 S_SET_VALUE (line_label, frag_now_fix ());
1423 /* Set scl to label, since that's what TI does. */
1424 if (S_GET_STORAGE_CLASS (line_label) != C_EXT)
1425 S_SET_STORAGE_CLASS (line_label, C_LABEL);
1426 }
1427
1428 seg_info (seg)->bss = 1; /* Uninitialized data. */
1429
1430 p = frag_var (rs_fill, 1, 1,
1431 (relax_substateT) 0, (symbolS *) line_label,
1432 size * OCTETS_PER_BYTE, (char *) 0);
1433 *p = 0;
1434
1435 if (blocking_flag)
1436 flags |= SEC_BLOCK;
1437
1438 if (!bfd_set_section_flags (stdoutput, seg, flags))
1439 as_warn ("Error setting flags for \"%s\": %s", name,
1440 bfd_errmsg (bfd_get_error ()));
1441
1442 subseg_set (current_seg, current_subseg); /* Restore current seg. */
1443 demand_empty_rest_of_line ();
1444}
1445
1446static enum cpu_version
1447lookup_version (const char *ver)
1448{
1449 enum cpu_version version = VNONE;
1450
1451 if (ver[0] == '5' && ver[1] == '4')
1452 {
1453 if (strlen (ver) == 3
1454 && (ver[2] == '1' || ver[2] == '2' || ver[2] == '3'
1455 || ver[2] == '5' || ver[2] == '8' || ver[2] == '9'))
1456 version = ver[2] - '0';
1457 else if (strlen (ver) == 5
1458 && TOUPPER (ver[3]) == 'L'
1459 && TOUPPER (ver[4]) == 'P'
1460 && (ver[2] == '5' || ver[2] == '6'))
1461 version = ver[2] - '0' + 10;
1462 }
1463
1464 return version;
1465}
1466
1467static void
1468set_cpu (enum cpu_version version)
1469{
1470 cpu = version;
1471 if (version == V545LP || version == V546LP)
1472 {
1473 symbolS *symbolP = symbol_new ("__allow_lp", absolute_section,
1474 (valueT) 1, &zero_address_frag);
1475 SF_SET_LOCAL (symbolP);
1476 symbol_table_insert (symbolP);
1477 }
1478}
1479
1480/* .version cpu-version
1481 cpu-version may be one of the following:
1482 541
1483 542
1484 543
1485 545
1486 545LP
1487 546LP
1488 548
1489 549
1490
1491 This is for compatibility only. It currently has no affect on assembly. */
1492static int cpu_needs_set = 1;
1493
1494static void
1495tic54x_version (int x ATTRIBUTE_UNUSED)
1496{
1497 enum cpu_version version = VNONE;
1498 enum cpu_version old_version = cpu;
1499 int c;
1500 char *ver;
1501
1502 ILLEGAL_WITHIN_STRUCT ();
1503
1504 SKIP_WHITESPACE ();
1505 ver = input_line_pointer;
1506 while (!is_end_of_line[(int) *input_line_pointer])
1507 ++input_line_pointer;
1508 c = *input_line_pointer;
1509 *input_line_pointer = 0;
1510
1511 version = lookup_version (ver);
1512
1513 if (cpu != VNONE && cpu != version)
1514 as_warn (_("CPU version has already been set"));
1515
1516 if (version == VNONE)
1517 {
1518 as_bad (_("Unrecognized version '%s'"), ver);
1519 ignore_rest_of_line ();
1520 return;
1521 }
1522 else if (assembly_begun && version != old_version)
1523 {
1524 as_bad (_("Changing of CPU version on the fly not supported"));
1525 ignore_rest_of_line ();
1526 return;
1527 }
1528
1529 set_cpu (version);
1530
1531 *input_line_pointer = c;
1532 demand_empty_rest_of_line ();
1533}
1534
1535/* 'f' = float, 'x' = xfloat, 'd' = double, 'l' = ldouble. */
1536
1537static void
1538tic54x_float_cons (int type)
1539{
1540 if (current_stag != 0)
1541 tic54x_struct_field ('f');
1542
1543#ifdef md_flush_pending_output
1544 md_flush_pending_output ();
1545#endif
1546
1547 /* Align to long word boundary (4 octets) unless it's ".xfloat". */
1548 if (type != 'x')
1549 {
1550 frag_align (2, 0, 2);
1551 /* If there's a label, assign it to the first allocated word. */
1552 if (line_label != NULL)
1553 {
1554 symbol_set_frag (line_label, frag_now);
1555 S_SET_VALUE (line_label, frag_now_fix ());
1556 }
1557 }
1558
1559 float_cons ('f');
1560}
1561
1562/* The argument is capitalized if it should be zero-terminated
1563 's' is normal string with upper 8-bits zero-filled, 'p' is packed.
1564 Code copied from stringer, and slightly modified so that strings are packed
1565 and encoded into the correct octets. */
1566
1567static void
1568tic54x_stringer (int type)
1569{
1570 register unsigned int c;
1571 char *start;
1572 int append_zero = type == 'S' || type == 'P';
1573 int packed = type == 'p' || type == 'P';
1574 int last_char = -1; /* Packed strings need two bytes at a time to encode. */
1575
1576 if (current_stag != NULL)
1577 {
1578 tic54x_struct_field ('*');
1579 return;
1580 }
1581
1582#ifdef md_flush_pending_output
1583 md_flush_pending_output ();
1584#endif
1585
1586 c = ','; /* Do loop. */
1587 while (c == ',')
1588 {
1589 SKIP_WHITESPACE ();
1590 switch (*input_line_pointer)
1591 {
1592 default:
1593 {
1594 unsigned short value = get_absolute_expression ();
1595 FRAG_APPEND_1_CHAR ( value & 0xFF);
1596 FRAG_APPEND_1_CHAR ((value >> 8) & 0xFF);
1597 break;
1598 }
1599 case '\"':
1600 ++input_line_pointer; /* -> 1st char of string. */
1601 start = input_line_pointer;
1602 while (is_a_char (c = next_char_of_string ()))
1603 {
1604 if (!packed)
1605 {
1606 FRAG_APPEND_1_CHAR (c);
1607 FRAG_APPEND_1_CHAR (0);
1608 }
1609 else
1610 {
1611 /* Packed strings are filled MS octet first. */
1612 if (last_char == -1)
1613 last_char = c;
1614 else
1615 {
1616 FRAG_APPEND_1_CHAR (c);
1617 FRAG_APPEND_1_CHAR (last_char);
1618 last_char = -1;
1619 }
1620 }
1621 }
1622 if (append_zero)
1623 {
1624 if (packed && last_char != -1)
1625 {
1626 FRAG_APPEND_1_CHAR (0);
1627 FRAG_APPEND_1_CHAR (last_char);
1628 last_char = -1;
1629 }
1630 else
1631 {
1632 FRAG_APPEND_1_CHAR (0);
1633 FRAG_APPEND_1_CHAR (0);
1634 }
1635 }
1636 know (input_line_pointer[-1] == '\"');
1637 break;
1638 }
1639 SKIP_WHITESPACE ();
1640 c = *input_line_pointer;
1641 if (!is_end_of_line[c])
1642 ++input_line_pointer;
1643 }
1644
1645 /* Finish up any leftover packed string. */
1646 if (packed && last_char != -1)
1647 {
1648 FRAG_APPEND_1_CHAR (0);
1649 FRAG_APPEND_1_CHAR (last_char);
1650 }
1651 demand_empty_rest_of_line ();
1652}
1653
1654static void
1655tic54x_p2align (int arg ATTRIBUTE_UNUSED)
1656{
1657 as_bad (_("p2align not supported on this target"));
1658}
1659
1660static void
1661tic54x_align_words (int arg)
1662{
1663 /* Only ".align" with no argument is allowed within .struct/.union. */
1664 int count = arg;
1665
1666 if (!is_end_of_line[(int) *input_line_pointer])
1667 {
1668 if (arg == 2)
1669 as_warn (_("Argument to .even ignored"));
1670 else
1671 count = get_absolute_expression ();
1672 }
1673
1674 if (current_stag != NULL && arg == 128)
1675 {
1676 if (current_stag->current_bitfield_offset != 0)
1677 {
1678 current_stag->current_bitfield_offset = 0;
1679 ++abs_section_offset;
1680 }
1681 demand_empty_rest_of_line ();
1682 return;
1683 }
1684
1685 ILLEGAL_WITHIN_STRUCT ();
1686
1687 s_align_bytes (count << 1);
1688}
1689
1690/* Initialize multiple-bit fields withing a single word of memory. */
1691
1692static void
1693tic54x_field (int ignore ATTRIBUTE_UNUSED)
1694{
1695 expressionS exp;
1696 int size = 16;
1697 char *p;
1698 valueT value;
1699 symbolS *label = line_label;
1700
1701 if (current_stag != NULL)
1702 {
1703 tic54x_struct_field ('.');
1704 return;
1705 }
1706
1707 input_line_pointer = parse_expression (input_line_pointer, &exp);
1708
1709 if (*input_line_pointer == ',')
1710 {
1711 ++input_line_pointer;
1712 size = get_absolute_expression ();
1713 if (size < 1 || size > 32)
1714 {
1715 as_bad (_("Invalid field size, must be from 1 to 32"));
1716 ignore_rest_of_line ();
1717 return;
1718 }
1719 }
1720
1721 /* Truncate values to the field width. */
1722 if (exp.X_op != O_constant)
1723 {
1724 /* If the expression value is relocatable, the field size *must*
1725 be 16. */
1726 if (size != 16)
1727 {
1728 as_bad (_("field size must be 16 when value is relocatable"));
1729 ignore_rest_of_line ();
1730 return;
1731 }
1732
1733 frag_now->tc_frag_data = 0;
1734 emit_expr (&exp, 2);
1735 }
1736 else
1737 {
1738 unsigned long fmask = (size == 32) ? 0xFFFFFFFF : (1ul << size) - 1;
1739 value = exp.X_add_number;
1740 exp.X_add_number &= fmask;
1741 if (value != (valueT) exp.X_add_number)
1742 as_warn (_("field value truncated"));
1743 value = exp.X_add_number;
1744 /* Bits are stored MS first. */
1745 while (size >= 16)
1746 {
1747 frag_now->tc_frag_data = 0;
1748 p = frag_more (2);
1749 md_number_to_chars (p, (value >> (size - 16)) & 0xFFFF, 2);
1750 size -= 16;
1751 }
1752 if (size > 0)
1753 {
1754 int bit_offset = frag_bit_offset (frag_now, now_seg);
1755 fragS *alloc_frag = bit_offset_frag (frag_now, now_seg);
1756 if (bit_offset == -1)
1757 {
1758 struct bit_info *bi = xmalloc (sizeof (struct bit_info));
1759 /* We don't know the previous offset at this time, so store the
1760 info we need and figure it out later. */
1761 expressionS size_exp;
1762 size_exp.X_op = O_constant;
1763 size_exp.X_add_number = size;
1764 bi->seg = now_seg;
1765 bi->type = TYPE_FIELD;
1766 bi->value = value;
1767 p = frag_var (rs_machine_dependent,
1768 4, 1, (relax_substateT) 0,
1769 make_expr_symbol (&size_exp), (offsetT) 0,
1770 (char *) bi);
1771 goto getout;
1772 }
1773 else if (bit_offset == 0 || bit_offset + size > 16)
1774 {
1775 /* Align a new field. */
1776 p = frag_more (2);
1777 frag_now->tc_frag_data = 0;
1778 alloc_frag = frag_now;
1779 }
1780 else
1781 {
1782 /* Put the new value entirely within the existing one. */
1783 p = alloc_frag == frag_now ?
1784 frag_now->fr_literal + frag_now_fix_octets () - 2 :
1785 alloc_frag->fr_literal;
1786 if (label != NULL)
1787 {
1788 symbol_set_frag (label, alloc_frag);
1789 if (alloc_frag == frag_now)
1790 S_SET_VALUE (label, frag_now_fix () - 1);
1791 label = NULL;
1792 }
1793 }
1794 value <<= 16 - alloc_frag->tc_frag_data - size;
1795
1796 /* OR in existing value. */
1797 if (alloc_frag->tc_frag_data)
1798 value |= ((unsigned short) p[1] << 8) | p[0];
1799 md_number_to_chars (p, value, 2);
1800 alloc_frag->tc_frag_data += size;
1801 if (alloc_frag->tc_frag_data == 16)
1802 alloc_frag->tc_frag_data = 0;
1803 }
1804 }
1805 getout:
1806 demand_empty_rest_of_line ();
1807}
1808
1809/* Ideally, we want to check SEC_LOAD and SEC_HAS_CONTENTS, but those aren't
1810 available yet. seg_info ()->bss is the next best thing. */
1811
1812static int
1813tic54x_initialized_section (segT seg)
1814{
1815 return !seg_info (seg)->bss;
1816}
1817
1818/* .clink ["section name"]
1819
1820 Marks the section as conditionally linked (link only if contents are
1821 referenced elsewhere.
1822 Without a name, refers to the current initialized section.
1823 Name is required for uninitialized sections. */
1824
1825static void
1826tic54x_clink (int ignored ATTRIBUTE_UNUSED)
1827{
1828 segT seg = now_seg;
1829
1830 ILLEGAL_WITHIN_STRUCT ();
1831
1832 if (*input_line_pointer == '\"')
1833 {
1834 char *section_name = ++input_line_pointer;
1835 char *name;
1836 while (is_a_char (next_char_of_string ()))
1837 ;
1838 know (input_line_pointer[-1] == '\"');
1839 input_line_pointer[-1] = 0;
1840 name = xmalloc (input_line_pointer - section_name + 1);
1841 strcpy (name, section_name);
1842
1843 seg = bfd_get_section_by_name (stdoutput, name);
1844 if (seg == NULL)
1845 {
1846 as_bad (_("Unrecognized section '%s'"), section_name);
1847 ignore_rest_of_line ();
1848 return;
1849 }
1850 }
1851 else
1852 {
1853 if (!tic54x_initialized_section (seg))
1854 {
1855 as_bad (_("Current section is unitialized, "
1856 "section name required for .clink"));
1857 ignore_rest_of_line ();
1858 return;
1859 }
1860 }
1861
1862 seg->flags |= SEC_CLINK;
1863
1864 demand_empty_rest_of_line ();
1865}
1866
1867/* Change the default include directory to be the current source file's
1868 directory, instead of the current working directory. If DOT is non-zero,
1869 set to "." instead. */
1870
1871static void
1872tic54x_set_default_include (int dot)
1873{
1874 char *dir = ".";
1875 char *tmp = NULL;
1876
1877 if (!dot)
1878 {
1879 char *curfile;
1880 unsigned lineno;
1881
1882 as_where (&curfile, &lineno);
1883 dir = strcpy (xmalloc (strlen (curfile) + 1), curfile);
1884 tmp = strrchr (dir, '/');
1885 }
1886 if (tmp != NULL)
1887 {
1888 int len;
1889 *tmp = '\0';
1890 len = strlen (dir);
1891 if (include_dir_count == 0)
1892 {
1893 include_dirs = (char **) xmalloc (sizeof (*include_dirs));
1894 include_dir_count = 1;
1895 }
1896 include_dirs[0] = dir;
1897 if (len > include_dir_maxlen)
1898 include_dir_maxlen = len;
1899 }
1900 else if (include_dirs != NULL)
1901 include_dirs[0] = ".";
1902}
1903
1904/* .include "filename" | filename
1905 .copy "filename" | filename
1906
1907 FIXME 'include' file should be omitted from any output listing,
1908 'copy' should be included in any output listing
1909 FIXME -- prevent any included files from changing listing (compat only)
1910 FIXME -- need to include source file directory in search path; what's a
1911 good way to do this?
1912
1913 Entering/exiting included/copied file clears all local labels. */
1914
1915static void
1916tic54x_include (int ignored ATTRIBUTE_UNUSED)
1917{
1918 char newblock[] = " .newblock\n";
1919 char *filename;
1920 char *input;
1921 int len, c = -1;
1922
1923 ILLEGAL_WITHIN_STRUCT ();
1924
1925 SKIP_WHITESPACE ();
1926
1927 if (*input_line_pointer == '"')
1928 {
1929 filename = demand_copy_C_string (&len);
1930 demand_empty_rest_of_line ();
1931 }
1932 else
1933 {
1934 filename = input_line_pointer;
1935 while (!is_end_of_line[(int) *input_line_pointer])
1936 ++input_line_pointer;
1937 c = *input_line_pointer;
1938 *input_line_pointer = '\0';
1939 filename = strcpy (xmalloc (strlen (filename) + 1), filename);
1940 *input_line_pointer = c;
1941 demand_empty_rest_of_line ();
1942 }
1943 /* Insert a partial line with the filename (for the sake of s_include)
1944 and a .newblock.
1945 The included file will be inserted before the newblock, so that the
1946 newblock is executed after the included file is processed. */
1947 input = xmalloc (sizeof (newblock) + strlen (filename) + 4);
1948 sprintf (input, "\"%s\"\n%s", filename, newblock);
1949 input_scrub_insert_line (input);
1950
1951 tic54x_clear_local_labels (0);
1952
1953 tic54x_set_default_include (0);
1954
1955 s_include (0);
1956}
1957
1958static void
1959tic54x_message (int type)
1960{
1961 char *msg;
1962 char c;
1963 int len;
1964
1965 ILLEGAL_WITHIN_STRUCT ();
1966
1967 if (*input_line_pointer == '"')
1968 msg = demand_copy_C_string (&len);
1969 else
1970 {
1971 msg = input_line_pointer;
1972 while (!is_end_of_line[(int) *input_line_pointer])
1973 ++input_line_pointer;
1974 c = *input_line_pointer;
1975 *input_line_pointer = 0;
1976 msg = strcpy (xmalloc (strlen (msg) + 1), msg);
1977 *input_line_pointer = c;
1978 }
1979
1980 switch (type)
1981 {
1982 case 'm':
1983 as_tsktsk ("%s", msg);
1984 break;
1985 case 'w':
1986 as_warn ("%s", msg);
1987 break;
1988 case 'e':
1989 as_bad ("%s", msg);
1990 break;
1991 }
1992
1993 demand_empty_rest_of_line ();
1994}
1995
1996/* .label <symbol>
1997 Define a special symbol that refers to the loadtime address rather than the
1998 runtime address within the current section.
1999
2000 This symbol gets a special storage class so that when it is resolved, it is
2001 resolved relative to the load address (lma) of the section rather than the
2002 run address (vma). */
2003
2004static void
2005tic54x_label (int ignored ATTRIBUTE_UNUSED)
2006{
2007 char *name = input_line_pointer;
2008 symbolS *symbolP;
2009 int c;
2010
2011 ILLEGAL_WITHIN_STRUCT ();
2012
2013 c = get_symbol_end ();
2014 symbolP = colon (name);
2015 S_SET_STORAGE_CLASS (symbolP, C_STATLAB);
2016
2017 *input_line_pointer = c;
2018 demand_empty_rest_of_line ();
2019}
2020
2021/* .mmregs
2022 Install all memory-mapped register names into the symbol table as
2023 absolute local symbols. */
2024
2025static void
2026tic54x_mmregs (int ignored ATTRIBUTE_UNUSED)
2027{
2028 symbol *sym;
2029
2030 ILLEGAL_WITHIN_STRUCT ();
2031
2032 for (sym = (symbol *) mmregs; sym->name; sym++)
2033 {
2034 symbolS *symbolP = symbol_new (sym->name, absolute_section,
2035 (valueT) sym->value, &zero_address_frag);
2036 SF_SET_LOCAL (symbolP);
2037 symbol_table_insert (symbolP);
2038 }
2039}
2040
2041/* .loop [count]
2042 Count defaults to 1024. */
2043
2044static void
2045tic54x_loop (int count)
2046{
2047 ILLEGAL_WITHIN_STRUCT ();
2048
2049 SKIP_WHITESPACE ();
2050 if (!is_end_of_line[(int) *input_line_pointer])
2051 count = get_absolute_expression ();
2052
2053 do_repeat (count, "LOOP", "ENDLOOP");
2054}
2055
2056/* Normally, endloop gets eaten by the preceding loop. */
2057
2058static void
2059tic54x_endloop (int ignore ATTRIBUTE_UNUSED)
2060{
2061 as_bad (_("ENDLOOP without corresponding LOOP"));
2062 ignore_rest_of_line ();
2063}
2064
2065/* .break [condition]. */
2066
2067static void
2068tic54x_break (int ignore ATTRIBUTE_UNUSED)
2069{
2070 int cond = 1;
2071
2072 ILLEGAL_WITHIN_STRUCT ();
2073
2074 SKIP_WHITESPACE ();
2075 if (!is_end_of_line[(int) *input_line_pointer])
2076 cond = get_absolute_expression ();
2077
2078 if (cond)
2079 end_repeat (substitution_line ? 1 : 0);
2080}
2081
2082static void
2083set_address_mode (int mode)
2084{
2085 amode = mode;
2086 if (mode == far_mode)
2087 {
2088 symbolS *symbolP = symbol_new ("__allow_far", absolute_section,
2089 (valueT) 1, &zero_address_frag);
2090 SF_SET_LOCAL (symbolP);
2091 symbol_table_insert (symbolP);
2092 }
2093}
2094
2095static int address_mode_needs_set = 1;
2096static void
2097tic54x_address_mode (int mode)
2098{
2099 if (assembly_begun && amode != (unsigned) mode)
2100 {
2101 as_bad (_("Mixing of normal and extended addressing not supported"));
2102 ignore_rest_of_line ();
2103 return;
2104 }
2105 if (mode == far_mode && cpu != VNONE && cpu != V548 && cpu != V549)
2106 {
2107 as_bad (_("Extended addressing not supported on the specified CPU"));
2108 ignore_rest_of_line ();
2109 return;
2110 }
2111
2112 set_address_mode (mode);
2113 demand_empty_rest_of_line ();
2114}
2115
2116/* .sblock "section"|section [,...,"section"|section]
2117 Designate initialized sections for blocking. */
2118
2119static void
2120tic54x_sblock (int ignore ATTRIBUTE_UNUSED)
2121{
2122 int c = ',';
2123
2124 ILLEGAL_WITHIN_STRUCT ();
2125
2126 while (c == ',')
2127 {
2128 segT seg;
2129 char *name;
2130
2131 if (*input_line_pointer == '"')
2132 {
2133 int len;
2134 name = demand_copy_C_string (&len);
2135 }
2136 else
2137 {
2138 char *section_name = input_line_pointer;
2139 c = get_symbol_end ();
2140 name = xmalloc (strlen (section_name) + 1);
2141 strcpy (name, section_name);
2142 *input_line_pointer = c;
2143 }
2144
2145 seg = bfd_get_section_by_name (stdoutput, name);
2146 if (seg == NULL)
2147 {
2148 as_bad (_("Unrecognized section '%s'"), name);
2149 ignore_rest_of_line ();
2150 return;
2151 }
2152 else if (!tic54x_initialized_section (seg))
2153 {
2154 as_bad (_(".sblock may be used for initialized sections only"));
2155 ignore_rest_of_line ();
2156 return;
2157 }
2158 seg->flags |= SEC_BLOCK;
2159
2160 c = *input_line_pointer;
2161 if (!is_end_of_line[(int) c])
2162 ++input_line_pointer;
2163 }
2164
2165 demand_empty_rest_of_line ();
2166}
2167
2168/* symbol .set value
2169 symbol .equ value
2170
2171 value must be defined externals; no forward-referencing allowed
2172 symbols assigned with .set/.equ may not be redefined. */
2173
2174static void
2175tic54x_set (int ignore ATTRIBUTE_UNUSED)
2176{
2177 symbolS *symbolP;
2178 char *name;
2179
2180 ILLEGAL_WITHIN_STRUCT ();
2181
2182 if (!line_label)
2183 {
2184 as_bad (_("Symbol missing for .set/.equ"));
2185 ignore_rest_of_line ();
2186 return;
2187 }
2188 name = xstrdup (S_GET_NAME (line_label));
2189 line_label = NULL;
2190 if ((symbolP = symbol_find (name)) == NULL
2191 && (symbolP = md_undefined_symbol (name)) == NULL)
2192 {
2193 symbolP = symbol_new (name, absolute_section, 0, &zero_address_frag);
2194 S_SET_STORAGE_CLASS (symbolP, C_STAT);
2195 }
2196 free (name);
2197 S_SET_DATA_TYPE (symbolP, T_INT);
2198 S_SET_SEGMENT (symbolP, absolute_section);
2199 symbol_table_insert (symbolP);
2200 pseudo_set (symbolP);
2201 demand_empty_rest_of_line ();
2202}
2203
2204/* .fclist
2205 .fcnolist
2206 List false conditional blocks. */
2207
2208static void
2209tic54x_fclist (int show)
2210{
2211 if (show)
2212 listing &= ~LISTING_NOCOND;
2213 else
2214 listing |= LISTING_NOCOND;
2215 demand_empty_rest_of_line ();
2216}
2217
2218static void
2219tic54x_sslist (int show)
2220{
2221 ILLEGAL_WITHIN_STRUCT ();
2222
2223 listing_sslist = show;
2224}
2225
2226/* .var SYM[,...,SYMN]
2227 Define a substitution string to be local to a macro. */
2228
2229static void
2230tic54x_var (int ignore ATTRIBUTE_UNUSED)
2231{
2232 static char empty[] = "";
2233 char *name;
2234 int c;
2235
2236 ILLEGAL_WITHIN_STRUCT ();
2237
2238 if (macro_level == 0)
2239 {
2240 as_bad (_(".var may only be used within a macro definition"));
2241 ignore_rest_of_line ();
2242 return;
2243 }
2244 do
2245 {
2246 if (!ISALPHA (*input_line_pointer))
2247 {
2248 as_bad (_("Substitution symbols must begin with a letter"));
2249 ignore_rest_of_line ();
2250 return;
2251 }
2252 name = input_line_pointer;
2253 c = get_symbol_end ();
2254 /* .var symbols start out with a null string. */
2255 name = strcpy (xmalloc (strlen (name) + 1), name);
2256 hash_insert (subsym_hash[macro_level], name, empty);
2257 *input_line_pointer = c;
2258 if (c == ',')
2259 {
2260 ++input_line_pointer;
2261 if (is_end_of_line[(int) *input_line_pointer])
2262 c = *input_line_pointer;
2263 }
2264 }
2265 while (c == ',');
2266
2267 demand_empty_rest_of_line ();
2268}
2269
2270/* .mlib <macro library filename>
2271
2272 Macro libraries are archived (standard AR-format) text macro definitions
2273 Expand the file and include it.
2274
2275 FIXME need to try the source file directory as well. */
2276
2277static void
2278tic54x_mlib (int ignore ATTRIBUTE_UNUSED)
2279{
2280 char *filename;
2281 char *path;
2282 int len, i;
2283 bfd *abfd, *mbfd;
2284
2285 ILLEGAL_WITHIN_STRUCT ();
2286
2287 /* Parse the filename. */
2288 if (*input_line_pointer == '"')
2289 {
2290 if ((filename = demand_copy_C_string (&len)) == NULL)
2291 return;
2292 }
2293 else
2294 {
2295 SKIP_WHITESPACE ();
2296 len = 0;
2297 while (!is_end_of_line[(int) *input_line_pointer]
2298 && !ISSPACE (*input_line_pointer))
2299 {
2300 obstack_1grow (&notes, *input_line_pointer);
2301 ++input_line_pointer;
2302 ++len;
2303 }
2304 obstack_1grow (&notes, '\0');
2305 filename = obstack_finish (&notes);
2306 }
2307 demand_empty_rest_of_line ();
2308
2309 tic54x_set_default_include (0);
2310 path = xmalloc ((unsigned long) len + include_dir_maxlen + 5);
2311 for (i = 0; i < include_dir_count; i++)
2312 {
2313 FILE *try;
2314 strcpy (path, include_dirs[i]);
2315 strcat (path, "/");
2316 strcat (path, filename);
2317 if ((try = fopen (path, "r")) != NULL)
2318 {
2319 fclose (try);
2320 break;
2321 }
2322 }
2323 if (i >= include_dir_count)
2324 {
2325 free (path);
2326 path = filename;
2327 }
2328
2329 /* FIXME: if path is found, malloc'd storage is not freed. Of course, this
2330 happens all over the place, and since the assembler doesn't usually keep
2331 running for a very long time, it really doesn't matter. */
2332 register_dependency (path);
2333
2334 /* Expand all archive entries to temporary files and include them. */
2335 abfd = bfd_openr (path, NULL);
2336 if (!abfd)
2337 {
2338 as_bad (_("Can't open macro library file '%s' for reading."), path);
2339 as_perror ("%s", path);
2340 ignore_rest_of_line ();
2341 return;
2342 }
2343 if (!bfd_check_format (abfd, bfd_archive))
2344 {
2345 as_bad (_("File '%s' not in macro archive format"), path);
2346 ignore_rest_of_line ();
2347 return;
2348 }
2349
2350 /* Open each BFD as binary (it should be straight ASCII text). */
2351 for (mbfd = bfd_openr_next_archived_file (abfd, NULL);
2352 mbfd != NULL; mbfd = bfd_openr_next_archived_file (abfd, mbfd))
2353 {
2354 /* Get a size at least as big as the archive member. */
2355 bfd_size_type size = bfd_get_size (mbfd);
2356 char *buf = xmalloc (size);
2357 char *fname = tmpnam (NULL);
2358 FILE *ftmp;
2359
2360 /* We're not sure how big it is, but it will be smaller than "size". */
2361 bfd_bread (buf, size, mbfd);
2362
2363 /* Write to a temporary file, then use s_include to include it
2364 a bit of a hack. */
2365 ftmp = fopen (fname, "w+b");
2366 fwrite ((void *) buf, size, 1, ftmp);
2367 if (buf[size - 1] != '\n')
2368 fwrite ("\n", 1, 1, ftmp);
2369 fclose (ftmp);
2370 free (buf);
2371 input_scrub_insert_file (fname);
2372 unlink (fname);
2373 }
2374}
2375
2376const pseudo_typeS md_pseudo_table[] =
2377{
2378 { "algebraic", s_ignore , 0 },
2379 { "align" , tic54x_align_words , 128 },
2380 { "ascii" , tic54x_stringer , 'p' },
2381 { "asciz" , tic54x_stringer , 'P' },
2382 { "even" , tic54x_align_words , 2 },
2383 { "asg" , tic54x_asg , 0 },
2384 { "eval" , tic54x_eval , 0 },
2385 { "bss" , tic54x_bss , 0 },
2386 { "byte" , tic54x_cons , 'b' },
2387 { "ubyte" , tic54x_cons , 'B' },
2388 { "char" , tic54x_cons , 'c' },
2389 { "uchar" , tic54x_cons , 'C' },
2390 { "clink" , tic54x_clink , 0 },
2391 { "c_mode" , tic54x_address_mode , c_mode },
2392 { "copy" , tic54x_include , 'c' },
2393 { "include" , tic54x_include , 'i' },
2394 { "data" , tic54x_sect , 'd' },
2395 { "double" , tic54x_float_cons , 'd' },
2396 { "ldouble" , tic54x_float_cons , 'l' },
2397 { "drlist" , s_ignore , 0 },
2398 { "drnolist" , s_ignore , 0 },
2399 { "emsg" , tic54x_message , 'e' },
2400 { "mmsg" , tic54x_message , 'm' },
2401 { "wmsg" , tic54x_message , 'w' },
2402#if 0
2403 { "end" , s_end , 0 },
2404#endif
2405 { "far_mode" , tic54x_address_mode , far_mode },
2406 { "fclist" , tic54x_fclist , 1 },
2407 { "fcnolist" , tic54x_fclist , 0 },
2408 { "field" , tic54x_field , -1 },
2409 { "float" , tic54x_float_cons , 'f' },
2410 { "xfloat" , tic54x_float_cons , 'x' },
2411 { "global" , tic54x_global , 'g' },
2412 { "def" , tic54x_global , 'd' },
2413 { "ref" , tic54x_global , 'r' },
2414 { "half" , tic54x_cons , 'h' },
2415 { "uhalf" , tic54x_cons , 'H' },
2416 { "short" , tic54x_cons , 's' },
2417 { "ushort" , tic54x_cons , 'S' },
2418 { "if" , s_if , (int) O_ne },
2419 { "elseif" , s_elseif , (int) O_ne },
2420 { "else" , s_else , 0 },
2421 { "endif" , s_endif , 0 },
2422 { "int" , tic54x_cons , 'i' },
2423 { "uint" , tic54x_cons , 'I' },
2424 { "word" , tic54x_cons , 'w' },
2425 { "uword" , tic54x_cons , 'W' },
2426 { "label" , tic54x_label , 0 }, /* Loadtime
2427 address. */
2428 { "length" , s_ignore , 0 },
2429 { "width" , s_ignore , 0 },
2430#if 0
2431 { "list" , listing_list , 1 },
2432 { "nolist" , listing_list , 0 },
2433#endif
2434 { "long" , tic54x_cons , 'l' },
2435 { "ulong" , tic54x_cons , 'L' },
2436 { "xlong" , tic54x_cons , 'x' },
2437 { "loop" , tic54x_loop , 1024 },
2438 { "break" , tic54x_break , 0 },
2439 { "endloop" , tic54x_endloop , 0 },
2440 { "mlib" , tic54x_mlib , 0 },
2441 { "mlist" , s_ignore , 0 },
2442 { "mnolist" , s_ignore , 0 },
2443 { "mmregs" , tic54x_mmregs , 0 },
2444 { "newblock" , tic54x_clear_local_labels, 0 },
2445 { "option" , s_ignore , 0 },
2446 { "p2align" , tic54x_p2align , 0 },
2447#if 0
2448 { "page" , listing_eject , 0 },
2449#endif
2450 { "sblock" , tic54x_sblock , 0 },
2451 { "sect" , tic54x_sect , '*' },
2452 { "set" , tic54x_set , 0 },
2453 { "equ" , tic54x_set , 0 },
2454 { "space" , tic54x_space , 0 },
2455 { "bes" , tic54x_space , 1 },
2456 { "sslist" , tic54x_sslist , 1 },
2457 { "ssnolist" , tic54x_sslist , 0 },
2458 { "string" , tic54x_stringer , 's' },
2459 { "pstring" , tic54x_stringer , 'p' },
2460 { "struct" , tic54x_struct , 0 },
2461 { "tag" , tic54x_tag , 0 },
2462 { "endstruct", tic54x_endstruct , 0 },
2463 { "tab" , s_ignore , 0 },
2464 { "text" , tic54x_sect , 't' },
2465#if 0
2466 { "title" , listing_title , 0 },
2467#endif
2468 { "union" , tic54x_struct , 1 },
2469 { "endunion" , tic54x_endstruct , 1 },
2470 { "usect" , tic54x_usect , 0 },
2471 { "var" , tic54x_var , 0 },
2472 { "version" , tic54x_version , 0 },
2473 {0 , 0 , 0 }
2474};
2475
2476#if 0
2477/* For debugging, strings for each operand type. */
2478static const char *optypes[] =
2479{
2480 "none", "Xmem", "Ymem", "pmad", "dmad", "Smem", "Lmem", "MMR", "PA",
2481 "Sind", "xpmad", "xpmad+", "MMRX", "MMRY",
2482 "SRC1", "SRC", "RND", "DST",
2483 "ARX",
2484 "SHIFT", "SHFT",
2485 "B", "A", "lk", "TS", "k8", "16", "BITC", "CC", "CC2", "CC3", "123", "031",
2486 "k5", "k8u", "ASM", "T", "DP", "ARP", "k3", "lku", "N", "SBIT", "12",
2487 "k9", "TRN",
2488};
2489#endif
2490
2491int
2492md_parse_option (c, arg)
2493 int c;
2494 char *arg;
2495{
2496 switch (c)
2497 {
2498 default:
2499 return 0;
2500 case OPTION_COFF_VERSION:
2501 {
2502 int version = atoi (arg);
2503 if (version != 0 && version != 1 && version != 2)
2504 as_fatal (_("Bad COFF version '%s'"), arg);
2505 /* FIXME -- not yet implemented. */
2506 break;
2507 }
2508 case OPTION_CPU_VERSION:
2509 {
2510 cpu = lookup_version (arg);
2511 cpu_needs_set = 1;
2512 if (cpu == VNONE)
2513 as_fatal (_("Bad CPU version '%s'"), arg);
2514 break;
2515 }
2516 case OPTION_ADDRESS_MODE:
2517 amode = far_mode;
2518 address_mode_needs_set = 1;
2519 break;
2520 case OPTION_STDERR_TO_FILE:
2521 {
2522 char *filename = arg;
2523 FILE *fp = fopen (filename, "w+");
2524 if (fp == NULL)
2525 as_fatal (_("Can't redirect stderr to the file '%s'"), filename);
2526 fclose (fp);
2527 if ((fp = freopen (filename, "w+", stderr)) == NULL)
2528 as_fatal (_("Can't redirect stderr to the file '%s'"), filename);
2529 break;
2530 }
2531 }
2532
2533 return 1;
2534}
2535
2536/* Create a "local" substitution string hash table for a new macro level
2537 Some docs imply that macros have to use .newblock in order to be able
2538 to re-use a local label. We effectively do an automatic .newblock by
2539 deleting the local label hash between macro invocations. */
2540
2541void
2542tic54x_macro_start ()
2543{
2544 ++macro_level;
2545 subsym_hash[macro_level] = hash_new ();
2546 local_label_hash[macro_level] = hash_new ();
2547}
2548
2549void
2550tic54x_macro_info (info)
2551 void *info;
2552{
2553 struct formal_struct
2554 {
2555 struct formal_struct *next; /* Next formal in list */
2556 sb name; /* Name of the formal */
2557 sb def; /* The default value */
2558 sb actual; /* The actual argument (changed on
2559 each expansion) */
2560 int index; /* The index of the formal
2561 0 .. formal_count - 1 */
2562 } *entry;
2563 struct macro_struct
2564 {
2565 sb sub; /* Substitution text. */
2566 int formal_count; /* Number of formal args. */
2567 struct formal_struct *formals; /* Pointer to list of
2568 formal_structs. */
2569 struct hash_control *formal_hash; /* Hash table of formals. */
2570 } *macro;
2571
2572 macro = (struct macro_struct *) info;
2573
2574 /* Put the formal args into the substitution symbol table. */
2575 for (entry = macro->formals; entry; entry = entry->next)
2576 {
2577 char *name = strncpy (xmalloc (entry->name.len + 1),
2578 entry->name.ptr, entry->name.len);
2579 char *value = strncpy (xmalloc (entry->actual.len + 1),
2580 entry->actual.ptr, entry->actual.len);
2581 name[entry->name.len] = '\0';
2582 value[entry->actual.len] = '\0';
2583 hash_insert (subsym_hash[macro_level], name, value);
2584 }
2585}
2586
2587/* Get rid of this macro's .var's, arguments, and local labels. */
2588
2589void
2590tic54x_macro_end ()
2591{
2592 hash_die (subsym_hash[macro_level]);
2593 subsym_hash[macro_level] = NULL;
2594 hash_die (local_label_hash[macro_level]);
2595 local_label_hash[macro_level] = NULL;
2596 --macro_level;
2597}
2598
2599static int
2600subsym_symlen (char *a, char *ignore ATTRIBUTE_UNUSED)
2601{
2602 return strlen (a);
2603}
2604
2605/* Compare symbol A to string B. */
2606
2607static int
2608subsym_symcmp (char *a, char *b)
2609{
2610 return strcmp (a, b);
2611}
2612
2613/* Return the index of the first occurence of B in A, or zero if none
2614 assumes b is an integer char value as a string. Index is one-based. */
2615
2616static int
2617subsym_firstch (char *a, char *b)
2618{
2619 int val = atoi (b);
2620 char *tmp = strchr (a, val);
2621
2622 return tmp ? tmp - a + 1 : 0;
2623}
2624
2625/* Similar to firstch, but returns index of last occurrence of B in A. */
2626
2627static int
2628subsym_lastch (char *a, char *b)
2629{
2630 int val = atoi (b);
2631 char *tmp = strrchr (a, val);
2632
2633 return tmp ? tmp - a + 1 : 0;
2634}
2635
2636/* Returns 1 if string A is defined in the symbol table (NOT the substitution
2637 symbol table). */
2638
2639static int
2640subsym_isdefed (char *a, char *ignore ATTRIBUTE_UNUSED)
2641{
2642 symbolS *symbolP = symbol_find (a);
2643
2644 return symbolP != NULL;
2645}
2646
2647/* Assign first member of comma-separated list B (e.g. "1,2,3") to the symbol
2648 A, or zero if B is a null string. Both arguments *must* be substitution
2649 symbols, unsubstituted. */
2650
2651static int
2652subsym_ismember (char *sym, char *list)
2653{
2654 char *elem, *ptr, *listv;
2655
2656 if (!list)
2657 return 0;
2658
2659 listv = subsym_lookup (list, macro_level);
2660 if (!listv)
2661 {
2662 as_bad (_("Undefined substitution symbol '%s'"), list);
2663 ignore_rest_of_line ();
2664 return 0;
2665 }
2666
2667 ptr = elem = xmalloc (strlen (listv) + 1);
2668 strcpy (elem, listv);
2669 while (*ptr && *ptr != ',')
2670 ++ptr;
2671 *ptr++ = 0;
2672
2673 subsym_create_or_replace (sym, elem);
2674
2675 /* Reassign the list. */
2676 subsym_create_or_replace (list, ptr);
2677
2678 /* Assume this value, docs aren't clear. */
2679 return *list != 0;
2680}
2681
2682/* Return zero if not a constant; otherwise:
2683 1 if binary
2684 2 if octal
2685 3 if hexadecimal
2686 4 if character
2687 5 if decimal. */
2688
2689static int
2690subsym_iscons (char *a, char *ignore ATTRIBUTE_UNUSED)
2691{
2692 expressionS exp;
2693
2694 parse_expression (a, &exp);
2695
2696 if (exp.X_op == O_constant)
2697 {
2698 int len = strlen (a);
2699
2700 switch (TOUPPER (a[len - 1]))
2701 {
2702 case 'B':
2703 return 1;
2704 case 'Q':
2705 return 2;
2706 case 'H':
2707 return 3;
2708 case '\'':
2709 return 4;
2710 default:
2711 break;
2712 }
2713 /* No suffix; either octal, hex, or decimal. */
2714 if (*a == '0' && len > 1)
2715 {
2716 if (TOUPPER (a[1]) == 'X')
2717 return 3;
2718 return 2;
2719 }
2720 return 5;
2721 }
2722
2723 return 0;
2724}
2725
2726/* Return 1 if A is a valid symbol name. Expects string input. */
2727
2728static int
2729subsym_isname (char *a, char *ignore ATTRIBUTE_UNUSED)
2730{
2731 if (!is_name_beginner (*a))
2732 return 0;
2733 while (*a)
2734 {
2735 if (!is_part_of_name (*a))
2736 return 0;
2737 ++a;
2738 }
2739 return 1;
2740}
2741
2742/* Return whether the string is a register; accepts ar0-7, unless .mmregs has
2743 been seen; if so, recognize any memory-mapped register.
2744 Note this does not recognize "A" or "B" accumulators. */
2745
2746static int
2747subsym_isreg (char *a, char *ignore ATTRIBUTE_UNUSED)
2748{
2749 if (hash_find (reg_hash, a))
2750 return 1;
2751 if (hash_find (mmreg_hash, a))
2752 return 1;
2753 return 0;
2754}
2755
2756/* Return the structrure size, given the stag. */
2757
2758static int
2759subsym_structsz (char *name, char *ignore ATTRIBUTE_UNUSED)
2760{
2761 struct stag *stag = (struct stag *) hash_find (stag_hash, name);
2762 if (stag)
2763 return stag->size;
2764
2765 return 0;
2766}
2767
2768/* If anybody actually uses this, they can fix it :)
2769 FIXME I'm not sure what the "reference point" of a structure is. It might
2770 be either the initial offset given .struct, or it may be the offset of the
2771 structure within another structure, or it might be something else
2772 altogether. since the TI assembler doesn't seem to ever do anything but
2773 return zero, we punt and return zero. */
2774
2775static int
2776subsym_structacc (char *stag_name ATTRIBUTE_UNUSED,
2777 char *ignore ATTRIBUTE_UNUSED)
2778{
2779 return 0;
2780}
2781
2782static float
2783math_ceil (arg1, ignore)
2784 float arg1;
2785 float ignore ATTRIBUTE_UNUSED;
2786{
2787 return (float) ceil (arg1);
2788}
2789
2790static float
2791math_cvi (arg1, ignore)
2792 float arg1;
2793 float ignore ATTRIBUTE_UNUSED;
2794{
2795 return (int) arg1;
2796}
2797
2798static float
2799math_floor (arg1, ignore)
2800 float arg1;
2801 float ignore ATTRIBUTE_UNUSED;
2802{
2803 return (float) floor (arg1);
2804}
2805
2806static float
2807math_fmod (float arg1, float arg2)
2808{
2809 return (int) arg1 % (int) arg2;
2810}
2811
2812static float
2813math_int (arg1, ignore)
2814 float arg1;
2815 float ignore ATTRIBUTE_UNUSED;
2816{
2817 return ((float) ((int) arg1)) == arg1;
2818}
2819
2820static float
2821math_round (arg1, ignore)
2822 float arg1;
2823 float ignore ATTRIBUTE_UNUSED;
2824{
2825 return arg1 > 0 ? (int) (arg1 + 0.5) : (int) (arg1 - 0.5);
2826}
2827
2828static float
2829math_sgn (arg1, ignore)
2830 float arg1;
2831 float ignore ATTRIBUTE_UNUSED;
2832{
2833 return (arg1 < 0) ? -1 : (arg1 ? 1 : 0);
2834}
2835
2836static float
2837math_trunc (arg1, ignore)
2838 float arg1;
2839 float ignore ATTRIBUTE_UNUSED;
2840{
2841 return (int) arg1;
2842}
2843
2844static float
2845math_acos (arg1, ignore)
2846 float arg1;
2847 float ignore ATTRIBUTE_UNUSED;
2848{
2849 return (float) acos (arg1);
2850}
2851
2852static float
2853math_asin (arg1, ignore)
2854 float arg1;
2855 float ignore ATTRIBUTE_UNUSED;
2856{
2857 return (float) asin (arg1);
2858}
2859
2860static float
2861math_atan (arg1, ignore)
2862 float arg1;
2863 float ignore ATTRIBUTE_UNUSED;
2864{
2865 return (float) atan (arg1);
2866}
2867
2868static float
2869math_atan2 (float arg1, float arg2)
2870{
2871 return (float) atan2 (arg1, arg2);
2872}
2873
2874static float
2875math_cosh (arg1, ignore)
2876 float arg1;
2877 float ignore ATTRIBUTE_UNUSED;
2878{
2879 return (float) cosh (arg1);
2880}
2881
2882static float
2883math_cos (arg1, ignore)
2884 float arg1;
2885 float ignore ATTRIBUTE_UNUSED;
2886{
2887 return (float) cos (arg1);
2888}
2889
2890static float
2891math_cvf (arg1, ignore)
2892 float arg1;
2893 float ignore ATTRIBUTE_UNUSED;
2894{
2895 return (float) arg1;
2896}
2897
2898static float
2899math_exp (arg1, ignore)
2900 float arg1;
2901 float ignore ATTRIBUTE_UNUSED;
2902{
2903 return (float) exp (arg1);
2904}
2905
2906static float
2907math_fabs (arg1, ignore)
2908 float arg1;
2909 float ignore ATTRIBUTE_UNUSED;
2910{
2911 return (float) fabs (arg1);
2912}
2913
2914/* expr1 * 2^expr2. */
2915
2916static float
2917math_ldexp (float arg1, float arg2)
2918{
2919 return arg1 * (float) pow (2.0, arg2);
2920}
2921
2922static float
2923math_log10 (arg1, ignore)
2924 float arg1;
2925 float ignore ATTRIBUTE_UNUSED;
2926{
2927 return (float) log10 (arg1);
2928}
2929
2930static float
2931math_log (arg1, ignore)
2932 float arg1;
2933 float ignore ATTRIBUTE_UNUSED;
2934{
2935 return (float) log (arg1);
2936}
2937
2938static float
2939math_max (float arg1, float arg2)
2940{
2941 return (arg1 > arg2) ? arg1 : arg2;
2942}
2943
2944static float
2945math_min (float arg1, float arg2)
2946{
2947 return (arg1 < arg2) ? arg1 : arg2;
2948}
2949
2950static float
2951math_pow (float arg1, float arg2)
2952{
2953 return (float) pow (arg1, arg2);
2954}
2955
2956static float
2957math_sin (arg1, ignore)
2958 float arg1;
2959 float ignore ATTRIBUTE_UNUSED;
2960{
2961 return (float) sin (arg1);
2962}
2963
2964static float
2965math_sinh (arg1, ignore)
2966 float arg1;
2967 float ignore ATTRIBUTE_UNUSED;
2968{
2969 return (float) sinh (arg1);
2970}
2971
2972static float
2973math_sqrt (arg1, ignore)
2974 float arg1;
2975 float ignore ATTRIBUTE_UNUSED;
2976{
2977 return (float) sqrt (arg1);
2978}
2979
2980static float
2981math_tan (arg1, ignore)
2982 float arg1;
2983 float ignore ATTRIBUTE_UNUSED;
2984{
2985 return (float) tan (arg1);
2986}
2987
2988static float
2989math_tanh (arg1, ignore)
2990 float arg1;
2991 float ignore ATTRIBUTE_UNUSED;
2992{
2993 return (float) tanh (arg1);
2994}
2995
2996/* Built-in substitution symbol functions and math functions. */
2997typedef struct
2998{
2999 char *name;
3000 int (*proc) (char *, char *);
3001 int nargs;
3002} subsym_proc_entry;
3003
3004static const subsym_proc_entry subsym_procs[] =
3005{
3006 /* Assembler built-in string substitution functions. */
3007 { "$symlen", subsym_symlen, 1, },
3008 { "$symcmp", subsym_symcmp, 2, },
3009 { "$firstch", subsym_firstch, 2, },
3010 { "$lastch", subsym_lastch, 2, },
3011 { "$isdefed", subsym_isdefed, 1, },
3012 { "$ismember", subsym_ismember, 2, },
3013 { "$iscons", subsym_iscons, 1, },
3014 { "$isname", subsym_isname, 1, },
3015 { "$isreg", subsym_isreg, 1, },
3016 { "$structsz", subsym_structsz, 1, },
3017 { "$structacc", subsym_structacc, 1, },
3018 { NULL, NULL, 0 },
3019};
3020
3021typedef struct
3022{
3023 char *name;
3024 float (*proc) (float, float);
3025 int nargs;
3026 int int_return;
3027} math_proc_entry;
3028
3029static const math_proc_entry math_procs[] =
3030{
3031 /* Integer-returning built-in math functions. */
3032 { "$cvi", math_cvi, 1, 1 },
3033 { "$int", math_int, 1, 1 },
3034 { "$sgn", math_sgn, 1, 1 },
3035
3036 /* Float-returning built-in math functions. */
3037 { "$acos", math_acos, 1, 0 },
3038 { "$asin", math_asin, 1, 0 },
3039 { "$atan", math_atan, 1, 0 },
3040 { "$atan2", math_atan2, 2, 0 },
3041 { "$ceil", math_ceil, 1, 0 },
3042 { "$cosh", math_cosh, 1, 0 },
3043 { "$cos", math_cos, 1, 0 },
3044 { "$cvf", math_cvf, 1, 0 },
3045 { "$exp", math_exp, 1, 0 },
3046 { "$fabs", math_fabs, 1, 0 },
3047 { "$floor", math_floor, 1, 0 },
3048 { "$fmod", math_fmod, 2, 0 },
3049 { "$ldexp", math_ldexp, 2, 0 },
3050 { "$log10", math_log10, 1, 0 },
3051 { "$log", math_log, 1, 0 },
3052 { "$max", math_max, 2, 0 },
3053 { "$min", math_min, 2, 0 },
3054 { "$pow", math_pow, 2, 0 },
3055 { "$round", math_round, 1, 0 },
3056 { "$sin", math_sin, 1, 0 },
3057 { "$sinh", math_sinh, 1, 0 },
3058 { "$sqrt", math_sqrt, 1, 0 },
3059 { "$tan", math_tan, 1, 0 },
3060 { "$tanh", math_tanh, 1, 0 },
3061 { "$trunc", math_trunc, 1, 0 },
3062 { NULL, NULL, 0, 0 },
3063};
3064
3065void
3066md_begin ()
3067{
3068 template *tm;
3069 symbol *sym;
3070 const subsym_proc_entry *subsym_proc;
3071 const math_proc_entry *math_proc;
3072 const char *hash_err;
3073 char **symname;
3074 char *TIC54X_DIR = getenv ("TIC54X_DIR");
3075 char *A_DIR = TIC54X_DIR ? TIC54X_DIR : getenv ("A_DIR");
3076
3077 local_label_id = 0;
3078
3079 /* Look for A_DIR and add it to the include list. a */
3080 if (A_DIR != NULL)
3081 {
3082 char *tmp = xstrdup (A_DIR);
3083 do
3084 {
3085 char *next = strchr (tmp, ';');
3086 if (next)
3087 *next++ = '\0';
3088 add_include_dir (tmp);
3089 tmp = next;
3090 }
3091 while (tmp != NULL);
3092 }
3093
3094 op_hash = hash_new ();
3095 for (tm = (template *) tic54x_optab; tm->name; tm++)
3096 {
3097 if (hash_find (op_hash, tm->name))
3098 continue;
3099 hash_err = hash_insert (op_hash, tm->name, (char *) tm);
3100 if (hash_err)
3101 as_fatal ("Internal Error: Can't hash %s: %s",
3102 tm->name, hash_err);
3103 }
3104 parop_hash = hash_new ();
3105 for (tm = (template *) tic54x_paroptab; tm->name; tm++)
3106 {
3107 if (hash_find (parop_hash, tm->name))
3108 continue;
3109 hash_err = hash_insert (parop_hash, tm->name, (char *) tm);
3110 if (hash_err)
3111 as_fatal ("Internal Error: Can't hash %s: %s",
3112 tm->name, hash_err);
3113 }
3114 reg_hash = hash_new ();
3115 for (sym = (symbol *) regs; sym->name; sym++)
3116 {
3117 /* Add basic registers to the symbol table. */
3118 symbolS *symbolP = symbol_new (sym->name, absolute_section,
3119 (valueT) sym->value, &zero_address_frag);
3120 SF_SET_LOCAL (symbolP);
3121 symbol_table_insert (symbolP);
3122 hash_err = hash_insert (reg_hash, sym->name, (char *) sym);
3123 }
3124 for (sym = (symbol *) mmregs; sym->name; sym++)
3125 hash_err = hash_insert (reg_hash, sym->name, (char *) sym);
3126 mmreg_hash = hash_new ();
3127 for (sym = (symbol *) mmregs; sym->name; sym++)
3128 {
3129 hash_err = hash_insert (mmreg_hash, sym->name, (char *) sym);
3130 }
3131 cc_hash = hash_new ();
3132 for (sym = (symbol *) condition_codes; sym->name; sym++)
3133 {
3134 hash_err = hash_insert (cc_hash, sym->name, (char *) sym);
3135 }
3136 cc2_hash = hash_new ();
3137 for (sym = (symbol *) cc2_codes; sym->name; sym++)
3138 {
3139 hash_err = hash_insert (cc2_hash, sym->name, (char *) sym);
3140 }
3141 cc3_hash = hash_new ();
3142 for (sym = (symbol *) cc3_codes; sym->name; sym++)
3143 {
3144 hash_err = hash_insert (cc3_hash, sym->name, (char *) sym);
3145 }
3146 sbit_hash = hash_new ();
3147 for (sym = (symbol *) status_bits; sym->name; sym++)
3148 {
3149 hash_err = hash_insert (sbit_hash, sym->name, (char *) sym);
3150 }
3151 misc_symbol_hash = hash_new ();
3152 for (symname = (char **) misc_symbols; *symname; symname++)
3153 {
3154 hash_err = hash_insert (misc_symbol_hash, *symname, *symname);
3155 }
3156 /* Only the base substitution table and local label table are initialized;
3157 the others (for local macro substitution) get instantiated as needed. */
3158 local_label_hash[0] = hash_new ();
3159 subsym_hash[0] = hash_new ();
3160 for (subsym_proc = subsym_procs; subsym_proc->name; subsym_proc++)
3161 {
3162 hash_err = hash_insert (subsym_hash[0], subsym_proc->name,
3163 (char *) subsym_proc);
3164 }
3165 math_hash = hash_new ();
3166 for (math_proc = math_procs; math_proc->name; math_proc++)
3167 {
3168 /* Insert into the main subsym hash for recognition; insert into
3169 the math hash to actually store information. */
3170 hash_err = hash_insert (subsym_hash[0], math_proc->name,
3171 (char *) math_proc);
3172 hash_err = hash_insert (math_hash, math_proc->name,
3173 (char *) math_proc);
3174 }
3175 subsym_recurse_hash = hash_new ();
3176 stag_hash = hash_new ();
3177}
3178
3179typedef struct _tic54x_insn
3180{
3181 const template *tm; /* Opcode template. */
3182
3183 char mnemonic[MAX_LINE]; /* Opcode name/mnemonic. */
3184 char parmnemonic[MAX_LINE]; /* 2nd mnemonic of parallel insn. */
3185
3186 int opcount;
3187 struct opstruct
3188 {
3189 char buf[MAX_LINE];
3190 enum optype type;
3191 expressionS exp;
3192 } operands[MAX_OPERANDS];
3193
3194 int paropcount;
3195 struct opstruct paroperands[MAX_OPERANDS];
3196
3197 int is_lkaddr;
3198 int lkoperand;
3199 int words; /* Size of insn in 16-bit words. */
3200 int using_default_dst; /* Do we need to explicitly set an
3201 omitted OP_DST operand? */
3202 struct
3203 {
3204 unsigned short word; /* Final encoded opcode data. */
3205 int unresolved;
3206 int r_nchars; /* Relocation size. */
3207 bfd_reloc_code_real_type r_type; /* Relocation type. */
3208 expressionS addr_expr; /* Storage for unresolved expressions. */
3209 } opcode[3];
3210} tic54x_insn;
3211
3212static int encode_operand (tic54x_insn *, enum optype, struct opstruct *);
3213static int encode_dmad (tic54x_insn *, struct opstruct *, int);
3214static int operands_match (tic54x_insn *, struct opstruct *, int,
3215 const enum optype *, int, int);
3216static int encode_address (tic54x_insn *, struct opstruct *);
3217static int is_accumulator (struct opstruct *);
3218
3219static int
3220is_accumulator (struct opstruct *operand)
3221{
3222 return strcasecmp (operand->buf, "a") == 0
3223 || strcasecmp (operand->buf, "b") == 0;
3224}
3225
3226/* Return the number of operands found, or -1 on error, copying the
3227 operands into the given array and the accompanying expressions into
3228 the next array. */
3229
3230static int
3231get_operands (struct opstruct operands[], char *line)
3232{
3233 char *lptr = line;
3234 int numexp = 0;
3235 int expecting_operand = 0;
3236 int i;
3237
3238 while (numexp < MAX_OPERANDS && !is_end_of_line[(int) *lptr])
3239 {
3240 int paren_not_balanced = 0;
3241 char *op_start, *op_end;
3242 while (*lptr && ISSPACE (*lptr))
3243 ++lptr;
3244 op_start = lptr;
3245 while (paren_not_balanced || *lptr != ',')
3246 {
3247 if (*lptr == '\0')
3248 {
3249 if (paren_not_balanced)
3250 {
3251 as_bad ("Unbalanced parenthesis in operand %d", numexp);
3252 return -1;
3253 }
3254 else
3255 break;
3256 }
3257 if (*lptr == '(')
3258 ++paren_not_balanced;
3259 else if (*lptr == ')')
3260 --paren_not_balanced;
3261 ++lptr;
3262 }
3263 op_end = lptr;
3264 if (op_end != op_start)
3265 {
3266 int len = op_end - op_start;
3267 strncpy (operands[numexp].buf, op_start, len);
3268 operands[numexp].buf[len] = 0;
3269 /* Trim trailing spaces; while the preprocessor gets rid of most,
3270 there are weird usage patterns that can introduce them
3271 (i.e. using strings for macro args). */
3272 while (len > 0 && ISSPACE (operands[numexp].buf[len - 1]))
3273 operands[numexp].buf[--len] = 0;
3274 lptr = op_end;
3275 ++numexp;
3276 }
3277 else
3278 {
3279 if (expecting_operand || *lptr == ',')
3280 {
3281 as_bad ("Expecting operand after ','");
3282 return -1;
3283 }
3284 }
3285 if (*lptr == ',')
3286 {
3287 if (*++lptr == '\0')
3288 {
3289 as_bad ("Expecting operand after ','");
3290 return -1;
3291 }
3292 expecting_operand = 1;
3293 }
3294 }
3295
3296 while (*lptr && ISSPACE (*lptr++))
3297 ;
3298 if (!is_end_of_line[(int) *lptr])
3299 {
3300 as_bad ("Extra junk on line");
3301 return -1;
3302 }
3303
3304 /* OK, now parse them into expressions. */
3305 for (i = 0; i < numexp; i++)
3306 {
3307 memset (&operands[i].exp, 0, sizeof (operands[i].exp));
3308 if (operands[i].buf[0] == '#')
3309 {
3310 /* Immediate. */
3311 parse_expression (operands[i].buf + 1, &operands[i].exp);
3312 }
3313 else if (operands[i].buf[0] == '@')
3314 {
3315 /* Direct notation. */
3316 parse_expression (operands[i].buf + 1, &operands[i].exp);
3317 }
3318 else if (operands[i].buf[0] == '*')
3319 {
3320 /* Indirect. */
3321 char *paren = strchr (operands[i].buf, '(');
3322 /* Allow immediate syntax in the inner expression. */
3323 if (paren && paren[1] == '#')
3324 *++paren = '(';
3325
3326 /* Pull out the lk expression or SP offset, if present. */
3327 if (paren != NULL)
3328 {
3329 int len = strlen (paren);
3330 char *end = paren + len;
3331 int c;
3332 while (end[-1] != ')')
3333 if (--end <= paren)
3334 {
3335 as_bad (_("Badly formed address expression"));
3336 return -1;
3337 }
3338 c = *end;
3339 *end = '\0';
3340 parse_expression (paren, &operands[i].exp);
3341 *end = c;
3342 }
3343 else
3344 operands[i].exp.X_op = O_absent;
3345 }
3346 else
3347 parse_expression (operands[i].buf, &operands[i].exp);
3348 }
3349
3350 return numexp;
3351}
3352
3353/* Predicates for different operand types. */
3354
3355static int
3356is_immediate (struct opstruct *operand)
3357{
3358 return *operand->buf == '#';
3359}
3360
3361/* This is distinguished from immediate because some numbers must be constants
3362 and must *not* have the '#' prefix. */
3363
3364static int
3365is_absolute (struct opstruct *operand)
3366{
3367 return operand->exp.X_op == O_constant && !is_immediate (operand);
3368}
3369
3370/* Is this an indirect operand? */
3371
3372static int
3373is_indirect (struct opstruct *operand)
3374{
3375 return operand->buf[0] == '*';
3376}
3377
3378/* Is this a valid dual-memory operand? */
3379
3380static int
3381is_dual (struct opstruct *operand)
3382{
3383 if (is_indirect (operand) && strncasecmp (operand->buf, "*ar", 3) == 0)
3384 {
3385 char *tmp = operand->buf + 3;
3386 int arf;
3387 int valid_mod;
3388
3389 arf = *tmp++ - '0';
3390 /* Only allow *ARx, *ARx-, *ARx+, or *ARx+0%. */
3391 valid_mod = *tmp == '\0' ||
3392 strcasecmp (tmp, "-") == 0 ||
3393 strcasecmp (tmp, "+") == 0 ||
3394 strcasecmp (tmp, "+0%") == 0;
3395 return arf >= 2 && arf <= 5 && valid_mod;
3396 }
3397 return 0;
3398}
3399
3400static int
3401is_mmreg (struct opstruct *operand)
3402{
3403 return (is_absolute (operand)
3404 || is_immediate (operand)
3405 || hash_find (mmreg_hash, operand->buf) != 0);
3406}
3407
3408static int
3409is_type (struct opstruct *operand, enum optype type)
3410{
3411 switch (type)
3412 {
3413 case OP_None:
3414 return operand->buf[0] == 0;
3415 case OP_Xmem:
3416 case OP_Ymem:
3417 return is_dual (operand);
3418 case OP_Sind:
3419 return is_indirect (operand);
3420 case OP_xpmad_ms7:
3421 /* This one *must* be immediate. */
3422 return is_immediate (operand);
3423 case OP_xpmad:
3424 case OP_pmad:
3425 case OP_PA:
3426 case OP_dmad:
3427 case OP_Lmem:
3428 case OP_MMR:
3429 return 1;
3430 case OP_Smem:
3431 /* Address may be a numeric, indirect, or an expression. */
3432 return !is_immediate (operand);
3433 case OP_MMRY:
3434 case OP_MMRX:
3435 return is_mmreg (operand);
3436 case OP_SRC:
3437 case OP_SRC1:
3438 case OP_RND:
3439 case OP_DST:
3440 return is_accumulator (operand);
3441 case OP_B:
3442 return is_accumulator (operand) && TOUPPER (operand->buf[0]) == 'B';
3443 case OP_A:
3444 return is_accumulator (operand) && TOUPPER (operand->buf[0]) == 'A';
3445 case OP_ARX:
3446 return strncasecmp ("ar", operand->buf, 2) == 0
3447 && ISDIGIT (operand->buf[2]);
3448 case OP_SBIT:
3449 return hash_find (sbit_hash, operand->buf) != 0 || is_absolute (operand);
3450 case OP_CC:
3451 return hash_find (cc_hash, operand->buf) != 0;
3452 case OP_CC2:
3453 return hash_find (cc2_hash, operand->buf) != 0;
3454 case OP_CC3:
3455 return hash_find (cc3_hash, operand->buf) != 0
3456 || is_immediate (operand) || is_absolute (operand);
3457 case OP_16:
3458 return (is_immediate (operand) || is_absolute (operand))
3459 && operand->exp.X_add_number == 16;
3460 case OP_N:
3461 /* Allow st0 or st1 instead of a numeric. */
3462 return is_absolute (operand) || is_immediate (operand) ||
3463 strcasecmp ("st0", operand->buf) == 0 ||
3464 strcasecmp ("st1", operand->buf) == 0;
3465 case OP_12:
3466 case OP_123:
3467 return is_absolute (operand) || is_immediate (operand);
3468 case OP_SHFT:
3469 return (is_immediate (operand) || is_absolute (operand))
3470 && operand->exp.X_add_number >= 0 && operand->exp.X_add_number < 16;
3471 case OP_SHIFT:
3472 /* Let this one catch out-of-range values. */
3473 return (is_immediate (operand) || is_absolute (operand))
3474 && operand->exp.X_add_number != 16;
3475 case OP_BITC:
3476 case OP_031:
3477 case OP_k8:
3478 return is_absolute (operand) || is_immediate (operand);
3479 case OP_k8u:
3480 return is_immediate (operand)
3481 && operand->exp.X_op == O_constant
3482 && operand->exp.X_add_number >= 0
3483 && operand->exp.X_add_number < 256;
3484 case OP_lk:
3485 case OP_lku:
3486 /* Allow anything; assumes opcodes are ordered with Smem operands
3487 versions first. */
3488 return 1;
3489 case OP_k5:
3490 case OP_k3:
3491 case OP_k9:
3492 /* Just make sure it's an integer; check range later. */
3493 return is_immediate (operand);
3494 case OP_T:
3495 return strcasecmp ("t", operand->buf) == 0 ||
3496 strcasecmp ("treg", operand->buf) == 0;
3497 case OP_TS:
3498 return strcasecmp ("ts", operand->buf) == 0;
3499 case OP_ASM:
3500 return strcasecmp ("asm", operand->buf) == 0;
3501 case OP_TRN:
3502 return strcasecmp ("trn", operand->buf) == 0;
3503 case OP_DP:
3504 return strcasecmp ("dp", operand->buf) == 0;
3505 case OP_ARP:
3506 return strcasecmp ("arp", operand->buf) == 0;
3507 default:
3508 return 0;
3509 }
3510}
3511
3512static int
3513operands_match (insn, operands, opcount, refoptype, minops, maxops)
3514 tic54x_insn *insn;
3515 struct opstruct *operands;
3516 int opcount;
3517 const enum optype *refoptype;
3518 int minops, maxops;
3519{
3520 int op = 0, refop = 0;
3521
3522 if (opcount == 0 && minops == 0)
3523 {
3524 return 1;
3525 }
3526
3527 while (op <= maxops && refop <= maxops)
3528 {
3529 while (!is_type (&operands[op], OPTYPE (refoptype[refop])))
3530 {
3531 /* Skip an optional template operand if it doesn't agree
3532 with the current operand. */
3533 if (refoptype[refop] & OPT)
3534 {
3535 ++refop;
3536 --maxops;
3537 if (refop > maxops)
3538 return 0;
3539 }
3540 else
3541 return 0;
3542 }
3543
3544 /* Save the actual operand type for later use. */
3545 operands[op].type = OPTYPE (refoptype[refop]);
3546 ++refop;
3547 ++op;
3548 /* Have we matched them all yet? */
3549 if (op == opcount)
3550 {
3551 while (op < maxops)
3552 {
3553 /* If a later operand is *not* optional, no match. */
3554 if ((refoptype[refop] & OPT) == 0)
3555 return 0;
3556 /* Flag any implicit default OP_DST operands so we know to add
3557 them explicitly when encoding the operand later. */
3558 if (OPTYPE (refoptype[refop]) == OP_DST)
3559 insn->using_default_dst = 1;
3560 ++refop;
3561 ++op;
3562 }
3563
3564 return 1;
3565 }
3566 }
3567
3568 return 0;
3569}
3570
3571/* 16-bit direct memory address
3572 Explicit dmad operands are always in last word of insn (usually second
3573 word, but bumped to third if lk addressing is used)
3574
3575 We allow *(dmad) notation because the TI assembler allows it.
3576
3577 XPC_CODE:
3578 0 for 16-bit addresses
3579 1 for full 23-bit addresses
3580 2 for the upper 7 bits of a 23-bit address (LDX). */
3581
3582static int
3583encode_dmad (insn, operand, xpc_code)
3584 tic54x_insn *insn;
3585 struct opstruct *operand;
3586 int xpc_code;
3587{
3588 int op = 1 + insn->is_lkaddr;
3589
3590 /* Only allow *(dmad) expressions; all others are invalid. */
3591 if (is_indirect (operand) && operand->buf[strlen (operand->buf) - 1] != ')')
3592 {
3593 as_bad (_("Invalid dmad syntax '%s'"), operand->buf);
3594 return 0;
3595 }
3596
3597 insn->opcode[op].addr_expr = operand->exp;
3598
3599 if (insn->opcode[op].addr_expr.X_op == O_constant)
3600 {
3601 valueT value = insn->opcode[op].addr_expr.X_add_number;
3602 if (xpc_code == 1)
3603 {
3604 insn->opcode[0].word &= 0xFF80;
3605 insn->opcode[0].word |= (value >> 16) & 0x7F;
3606 insn->opcode[1].word = value & 0xFFFF;
3607 }
3608 else if (xpc_code == 2)
3609 insn->opcode[op].word = (value >> 16) & 0xFFFF;
3610 else
3611 insn->opcode[op].word = value;
3612 }
3613 else
3614 {
3615 /* Do the fixup later; just store the expression. */
3616 insn->opcode[op].word = 0;
3617 insn->opcode[op].r_nchars = 2;
3618
3619 if (amode == c_mode)
3620 insn->opcode[op].r_type = BFD_RELOC_TIC54X_16_OF_23;
3621 else if (xpc_code == 1)
3622 {
3623 /* This relocation spans two words, so adjust accordingly. */
3624 insn->opcode[0].addr_expr = operand->exp;
3625 insn->opcode[0].r_type = BFD_RELOC_TIC54X_23;
3626 insn->opcode[0].r_nchars = 4;
3627 insn->opcode[0].unresolved = 1;
3628 /* It's really 2 words, but we want to stop encoding after the
3629 first, since we must encode both words at once. */
3630 insn->words = 1;
3631 }
3632 else if (xpc_code == 2)
3633 insn->opcode[op].r_type = BFD_RELOC_TIC54X_MS7_OF_23;
3634 else
3635 insn->opcode[op].r_type = BFD_RELOC_TIC54X_16_OF_23;
3636
3637 insn->opcode[op].unresolved = 1;
3638 }
3639
3640 return 1;
3641}
3642
3643/* 7-bit direct address encoding. */
3644
3645static int
3646encode_address (insn, operand)
3647 tic54x_insn *insn;
3648 struct opstruct *operand;
3649{
3650 /* Assumes that dma addresses are *always* in word 0 of the opcode. */
3651 insn->opcode[0].addr_expr = operand->exp;
3652
3653 if (operand->exp.X_op == O_constant)
3654 insn->opcode[0].word |= (operand->exp.X_add_number & 0x7F);
3655 else
3656 {
3657 if (operand->exp.X_op == O_register) {
3658 as_bad(_("Use the .mmregs directive to use memory-mapped register names such as '%s'"), operand->buf);
3659 }
3660 /* Do the fixup later; just store the expression. */
3661 insn->opcode[0].r_nchars = 1;
3662 insn->opcode[0].r_type = BFD_RELOC_TIC54X_PARTLS7;
3663 insn->opcode[0].unresolved = 1;
3664 }
3665
3666 return 1;
3667}
3668
3669static int
3670encode_indirect (tic54x_insn *insn, struct opstruct *operand)
3671{
3672 int arf;
3673 int mod;
3674
3675 if (insn->is_lkaddr)
3676 {
3677 /* lk addresses always go in the second insn word. */
3678 mod = ((TOUPPER (operand->buf[1]) == 'A') ? 12 :
3679 (operand->buf[1] == '(') ? 15 :
3680 (strchr (operand->buf, '%') != NULL) ? 14 : 13);
3681 arf = ((mod == 12) ? operand->buf[3] - '0' :
3682 (mod == 15) ? 0 : operand->buf[4] - '0');
3683
3684 insn->opcode[1].addr_expr = operand->exp;
3685
3686 if (operand->exp.X_op == O_constant)
3687 insn->opcode[1].word = operand->exp.X_add_number;
3688 else
3689 {
3690 insn->opcode[1].word = 0;
3691 insn->opcode[1].r_nchars = 2;
3692 insn->opcode[1].r_type = BFD_RELOC_TIC54X_16_OF_23;
3693 insn->opcode[1].unresolved = 1;
3694 }
3695 }
3696 else if (strncasecmp (operand->buf, "*sp (", 4) == 0)
3697 {
3698 /* Stack offsets look the same as 7-bit direct addressing. */
3699 return encode_address (insn, operand);
3700 }
3701 else
3702 {
3703 arf = (TOUPPER (operand->buf[1]) == 'A' ?
3704 operand->buf[3] : operand->buf[4]) - '0';
3705
3706 if (operand->buf[1] == '+')
3707 {
3708 mod = 3; /* *+ARx */
3709 if (insn->tm->flags & FL_SMR)
3710 as_warn (_("Address mode *+ARx is write-only. "
3711 "Results of reading are undefined."));
3712 }
3713 else if (operand->buf[4] == '\0')
3714 mod = 0; /* *ARx */
3715 else if (operand->buf[5] == '\0')
3716 mod = (operand->buf[4] == '-' ? 1 : 2); /* *ARx+ / *ARx- */
3717 else if (operand->buf[6] == '\0')
3718 {
3719 if (operand->buf[5] == '0')
3720 mod = (operand->buf[4] == '-' ? 5 : 6); /* *ARx+0 / *ARx-0 */
3721 else
3722 mod = (operand->buf[4] == '-' ? 8 : 10);/* *ARx+% / *ARx-% */
3723 }
3724 else if (TOUPPER (operand->buf[6]) == 'B')
3725 mod = (operand->buf[4] == '-' ? 4 : 7); /* ARx+0B / *ARx-0B */
3726 else if (TOUPPER (operand->buf[6]) == '%')
3727 mod = (operand->buf[4] == '-' ? 9 : 11); /* ARx+0% / *ARx - 0% */
3728 else
3729 {
3730 as_bad (_("Unrecognized indirect address format \"%s\""),
3731 operand->buf);
3732 return 0;
3733 }
3734 }
3735
3736 insn->opcode[0].word |= 0x80 | (mod << 3) | arf;
3737
3738 return 1;
3739}
3740
3741static int
3742encode_integer (tic54x_insn *insn,
3743 struct opstruct *operand,
3744 int which, int min, int max, unsigned short mask)
3745{
3746 long parse, integer;
3747
3748 insn->opcode[which].addr_expr = operand->exp;
3749
3750 if (operand->exp.X_op == O_constant)
3751 {
3752 parse = operand->exp.X_add_number;
3753 /* Hack -- fixup for 16-bit hex quantities that get converted positive
3754 instead of negative. */
3755 if ((parse & 0x8000) && min == -32768 && max == 32767)
3756 integer = (short) parse;
3757 else
3758 integer = parse;
3759
3760 if (integer >= min && integer <= max)
3761 {
3762 insn->opcode[which].word |= (integer & mask);
3763 return 1;
3764 }
3765 as_bad (_("Operand '%s' out of range (%d <= x <= %d)"),
3766 operand->buf, min, max);
3767 }
3768 else
3769 {
3770 if (insn->opcode[which].addr_expr.X_op == O_constant)
3771 {
3772 insn->opcode[which].word |=
3773 insn->opcode[which].addr_expr.X_add_number & mask;
3774 }
3775 else
3776 {
3777 /* Do the fixup later; just store the expression. */
3778 bfd_reloc_code_real_type rtype =
3779 (mask == 0x1FF ? BFD_RELOC_TIC54X_PARTMS9 :
3780 mask == 0xFFFF ? BFD_RELOC_TIC54X_16_OF_23 :
3781 mask == 0x7F ? BFD_RELOC_TIC54X_PARTLS7 : BFD_RELOC_8);
3782 int size = (mask == 0x1FF || mask == 0xFFFF) ? 2 : 1;
3783
3784 if (rtype == BFD_RELOC_8)
3785 as_bad (_("Error in relocation handling"));
3786
3787 insn->opcode[which].r_nchars = size;
3788 insn->opcode[which].r_type = rtype;
3789 insn->opcode[which].unresolved = 1;
3790 }
3791
3792 return 1;
3793 }
3794
3795 return 0;
3796}
3797
3798static int
3799encode_condition (tic54x_insn *insn, struct opstruct *operand)
3800{
3801 symbol *cc = (symbol *) hash_find (cc_hash, operand->buf);
3802 if (!cc)
3803 {
3804 as_bad (_("Unrecognized condition code \"%s\""), operand->buf);
3805 return 0;
3806 }
3807#define CC_GROUP 0x40
3808#define CC_ACC 0x08
3809#define CATG_A1 0x07
3810#define CATG_B1 0x30
3811#define CATG_A2 0x30
3812#define CATG_B2 0x0C
3813#define CATG_C2 0x03
3814 /* Disallow group 1 conditions mixed with group 2 conditions
3815 if group 1, allow only one category A and one category B
3816 if group 2, allow only one each of category A, B, and C. */
3817 if (((insn->opcode[0].word & 0xFF) != 0))
3818 {
3819 if ((insn->opcode[0].word & CC_GROUP) != (cc->value & CC_GROUP))
3820 {
3821 as_bad (_("Condition \"%s\" does not match preceding group"),
3822 operand->buf);
3823 return 0;
3824 }
3825 if (insn->opcode[0].word & CC_GROUP)
3826 {
3827 if ((insn->opcode[0].word & CC_ACC) != (cc->value & CC_ACC))
3828 {
3829 as_bad (_("Condition \"%s\" uses a different accumulator from "
3830 "a preceding condition"),
3831 operand->buf);
3832 return 0;
3833 }
3834 if ((insn->opcode[0].word & CATG_A1) && (cc->value & CATG_A1))
3835 {
3836 as_bad (_("Only one comparison conditional allowed"));
3837 return 0;
3838 }
3839 if ((insn->opcode[0].word & CATG_B1) && (cc->value & CATG_B1))
3840 {
3841 as_bad (_("Only one overflow conditional allowed"));
3842 return 0;
3843 }
3844 }
3845 else if (((insn->opcode[0].word & CATG_A2) && (cc->value & CATG_A2)) ||
3846 ((insn->opcode[0].word & CATG_B2) && (cc->value & CATG_B2)) ||
3847 ((insn->opcode[0].word & CATG_C2) && (cc->value & CATG_C2)))
3848 {
3849 as_bad (_("Duplicate %s conditional"), operand->buf);
3850 return 0;
3851 }
3852 }
3853
3854 insn->opcode[0].word |= cc->value;
3855 return 1;
3856}
3857
3858static int
3859encode_cc3 (tic54x_insn *insn, struct opstruct *operand)
3860{
3861 symbol *cc3 = (symbol *) hash_find (cc3_hash, operand->buf);
3862 int value = cc3 ? cc3->value : operand->exp.X_add_number << 8;
3863
3864 if ((value & 0x0300) != value)
3865 {
3866 as_bad (_("Unrecognized condition code \"%s\""), operand->buf);
3867 return 0;
3868 }
3869 insn->opcode[0].word |= value;
3870 return 1;
3871}
3872
3873static int
3874encode_arx (tic54x_insn *insn, struct opstruct *operand)
3875{
3876 int arf = strlen (operand->buf) >= 3 ? operand->buf[2] - '0' : -1;
3877 if (strncasecmp ("ar", operand->buf, 2) || arf < 0 || arf > 7)
3878 {
3879 as_bad (_("Invalid auxiliary register (use AR0-AR7)"));
3880 return 0;
3881 }
3882 insn->opcode[0].word |= arf;
3883 return 1;
3884}
3885
3886static int
3887encode_cc2 (tic54x_insn *insn, struct opstruct *operand)
3888{
3889 symbol *cc2 = (symbol *) hash_find (cc2_hash, operand->buf);
3890 if (!cc2)
3891 {
3892 as_bad (_("Unrecognized condition code \"%s\""), operand->buf);
3893 return 0;
3894 }
3895 insn->opcode[0].word |= cc2->value;
3896 return 1;
3897}
3898
3899static int
3900encode_operand (insn, type, operand)
3901 tic54x_insn *insn;
3902 enum optype type;
3903 struct opstruct *operand;
3904{
3905 int ext = (insn->tm->flags & FL_EXT) != 0;
3906
3907 if (type == OP_MMR && operand->exp.X_op != O_constant)
3908 {
3909 /* Disallow long-constant addressing for memory-mapped addressing. */
3910 if (insn->is_lkaddr)
3911 {
3912 as_bad (_("lk addressing modes are invalid for memory-mapped "
3913 "register addressing"));
3914 return 0;
3915 }
3916 type = OP_Smem;
3917 /* Warn about *+ARx when used with MMR operands. */
3918 if (strncasecmp (operand->buf, "*+ar", 4) == 0)
3919 {
3920 as_warn (_("Address mode *+ARx is not allowed in memory-mapped "
3921 "register addressing. Resulting behavior is "
3922 "undefined."));
3923 }
3924 }
3925
3926 switch (type)
3927 {
3928 case OP_None:
3929 return 1;
3930 case OP_dmad:
3931 /* 16-bit immediate value. */
3932 return encode_dmad (insn, operand, 0);
3933 case OP_SRC:
3934 if (TOUPPER (*operand->buf) == 'B')
3935 {
3936 insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1 << 9);
3937 if (insn->using_default_dst)
3938 insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1 << 8);
3939 }
3940 return 1;
3941 case OP_RND:
3942 /* Make sure this agrees with with the OP_DST operand. */
3943 if (!((TOUPPER (operand->buf[0]) == 'B') ^
3944 ((insn->opcode[0].word & (1 << 8)) != 0)))
3945 {
3946 as_bad (_("Destination accumulator for each part of this parallel "
3947 "instruction must be different"));
3948 return 0;
3949 }
3950 return 1;
3951 case OP_SRC1:
3952 case OP_DST:
3953 if (TOUPPER (operand->buf[0]) == 'B')
3954 insn->opcode[ext ? (1 + insn->is_lkaddr) : 0].word |= (1 << 8);
3955 return 1;
3956 case OP_Xmem:
3957 case OP_Ymem:
3958 {
3959 int mod = (operand->buf[4] == '\0' ? 0 : /* *arx */
3960 operand->buf[4] == '-' ? 1 : /* *arx- */
3961 operand->buf[5] == '\0' ? 2 : 3); /* *arx+, *arx+0% */
3962 int arf = operand->buf[3] - '0' - 2;
3963 int code = (mod << 2) | arf;
3964 insn->opcode[0].word |= (code << (type == OP_Xmem ? 4 : 0));
3965 return 1;
3966 }
3967 case OP_Lmem:
3968 case OP_Smem:
3969 if (!is_indirect (operand))
3970 return encode_address (insn, operand);
3971 /* Fall through. */
3972 case OP_Sind:
3973 return encode_indirect (insn, operand);
3974 case OP_xpmad_ms7:
3975 return encode_dmad (insn, operand, 2);
3976 case OP_xpmad:
3977 return encode_dmad (insn, operand, 1);
3978 case OP_PA:
3979 case OP_pmad:
3980 return encode_dmad (insn, operand, 0);
3981 case OP_ARX:
3982 return encode_arx (insn, operand);
3983 case OP_MMRX:
3984 case OP_MMRY:
3985 case OP_MMR:
3986 {
3987 int value = operand->exp.X_add_number;
3988
3989 if (type == OP_MMR)
3990 insn->opcode[0].word |= value;
3991 else
3992 {
3993 if (value < 16 || value > 24)
3994 {
3995 as_bad (_("Memory mapped register \"%s\" out of range"),
3996 operand->buf);
3997 return 0;
3998 }
3999 if (type == OP_MMRX)
4000 insn->opcode[0].word |= (value - 16) << 4;
4001 else
4002 insn->opcode[0].word |= (value - 16);
4003 }
4004 return 1;
4005 }
4006 case OP_B:
4007 case OP_A:
4008 return 1;
4009 case OP_SHFT:
4010 return encode_integer (insn, operand, ext + insn->is_lkaddr,
4011 0, 15, 0xF);
4012 case OP_SHIFT:
4013 return encode_integer (insn, operand, ext + insn->is_lkaddr,
4014 -16, 15, 0x1F);
4015 case OP_lk:
4016 return encode_integer (insn, operand, 1 + insn->is_lkaddr,
4017 -32768, 32767, 0xFFFF);
4018 case OP_CC:
4019 return encode_condition (insn, operand);
4020 case OP_CC2:
4021 return encode_cc2 (insn, operand);
4022 case OP_CC3:
4023 return encode_cc3 (insn, operand);
4024 case OP_BITC:
4025 return encode_integer (insn, operand, 0, 0, 15, 0xF);
4026 case OP_k8:
4027 return encode_integer (insn, operand, 0, -128, 127, 0xFF);
4028 case OP_123:
4029 {
4030 int value = operand->exp.X_add_number;
4031 int code;
4032 if (value < 1 || value > 3)
4033 {
4034 as_bad (_("Invalid operand (use 1, 2, or 3)"));
4035 return 0;
4036 }
4037 code = value == 1 ? 0 : value == 2 ? 0x2 : 0x1;
4038 insn->opcode[0].word |= (code << 8);
4039 return 1;
4040 }
4041 case OP_031:
4042 return encode_integer (insn, operand, 0, 0, 31, 0x1F);
4043 case OP_k8u:
4044 return encode_integer (insn, operand, 0, 0, 255, 0xFF);
4045 case OP_lku:
4046 return encode_integer (insn, operand, 1 + insn->is_lkaddr,
4047 0, 65535, 0xFFFF);
4048 case OP_SBIT:
4049 {
4050 symbol *sbit = (symbol *) hash_find (sbit_hash, operand->buf);
4051 int value = is_absolute (operand) ?
4052 operand->exp.X_add_number : (sbit ? sbit->value : -1);
4053 int reg = 0;
4054
4055 if (insn->opcount == 1)
4056 {
4057 if (!sbit)
4058 {
4059 as_bad (_("A status register or status bit name is required"));
4060 return 0;
4061 }
4062 /* Guess the register based on the status bit; "ovb" is the last
4063 status bit defined for st0. */
4064 if (sbit > (symbol *) hash_find (sbit_hash, "ovb"))
4065 reg = 1;
4066 }
4067 if (value == -1)
4068 {
4069 as_bad (_("Unrecognized status bit \"%s\""), operand->buf);
4070 return 0;
4071 }
4072 insn->opcode[0].word |= value;
4073 insn->opcode[0].word |= (reg << 9);
4074 return 1;
4075 }
4076 case OP_N:
4077 if (strcasecmp (operand->buf, "st0") == 0
4078 || strcasecmp (operand->buf, "st1") == 0)
4079 {
4080 insn->opcode[0].word |=
4081 ((unsigned short) (operand->buf[2] - '0')) << 9;
4082 return 1;
4083 }
4084 else if (operand->exp.X_op == O_constant
4085 && (operand->exp.X_add_number == 0
4086 || operand->exp.X_add_number == 1))
4087 {
4088 insn->opcode[0].word |=
4089 ((unsigned short) (operand->exp.X_add_number)) << 9;
4090 return 1;
4091 }
4092 as_bad (_("Invalid status register \"%s\""), operand->buf);
4093 return 0;
4094 case OP_k5:
4095 return encode_integer (insn, operand, 0, -16, 15, 0x1F);
4096 case OP_k3:
4097 return encode_integer (insn, operand, 0, 0, 7, 0x7);
4098 case OP_k9:
4099 return encode_integer (insn, operand, 0, 0, 0x1FF, 0x1FF);
4100 case OP_12:
4101 if (operand->exp.X_add_number != 1
4102 && operand->exp.X_add_number != 2)
4103 {
4104 as_bad (_("Operand \"%s\" out of range (use 1 or 2)"), operand->buf);
4105 return 0;
4106 }
4107 insn->opcode[0].word |= (operand->exp.X_add_number - 1) << 9;
4108 return 1;
4109 case OP_16:
4110 case OP_T:
4111 case OP_TS:
4112 case OP_ASM:
4113 case OP_TRN:
4114 case OP_DP:
4115 case OP_ARP:
4116 /* No encoding necessary. */
4117 return 1;
4118 default:
4119 return 0;
4120 }
4121
4122 return 1;
4123}
4124
4125static void
4126emit_insn (tic54x_insn *insn)
4127{
4128 int i;
4129 flagword oldflags = bfd_get_section_flags (stdoutput, now_seg);
4130 flagword flags = oldflags | SEC_CODE;
4131
4132 if (! bfd_set_section_flags (stdoutput, now_seg, flags))
4133 as_warn (_("error setting flags for \"%s\": %s"),
4134 bfd_section_name (stdoutput, now_seg),
4135 bfd_errmsg (bfd_get_error ()));
4136
4137 for (i = 0; i < insn->words; i++)
4138 {
4139 int size = (insn->opcode[i].unresolved
4140 && insn->opcode[i].r_type == BFD_RELOC_TIC54X_23) ? 4 : 2;
4141 char *p = frag_more (size);
4142
4143 if (size == 2)
4144 md_number_to_chars (p, (valueT) insn->opcode[i].word, 2);
4145 else
4146 md_number_to_chars (p, (valueT) insn->opcode[i].word << 16, 4);
4147
4148 if (insn->opcode[i].unresolved)
4149 fix_new_exp (frag_now, p - frag_now->fr_literal,
4150 insn->opcode[i].r_nchars, &insn->opcode[i].addr_expr,
4151 false, insn->opcode[i].r_type);
4152 }
4153}
4154
4155/* Convert the operand strings into appropriate opcode values
4156 return the total number of words used by the instruction. */
4157
4158static int
4159build_insn (tic54x_insn *insn)
4160{
4161 int i;
4162
4163 /* Only non-parallel instructions support lk addressing. */
4164 if (!(insn->tm->flags & FL_PAR))
4165 {
4166 for (i = 0; i < insn->opcount; i++)
4167 {
4168 if ((OPTYPE (insn->operands[i].type) == OP_Smem
4169 || OPTYPE (insn->operands[i].type) == OP_Lmem
4170 || OPTYPE (insn->operands[i].type) == OP_Sind)
4171 && strchr (insn->operands[i].buf, '(')
4172 /* Don't mistake stack-relative addressing for lk addressing. */
4173 && strncasecmp (insn->operands[i].buf, "*sp (", 4) != 0)
4174 {
4175 insn->is_lkaddr = 1;
4176 insn->lkoperand = i;
4177 break;
4178 }
4179 }
4180 }
4181 insn->words = insn->tm->words + insn->is_lkaddr;
4182
4183 insn->opcode[0].word = insn->tm->opcode;
4184 if (insn->tm->flags & FL_EXT)
4185 insn->opcode[1 + insn->is_lkaddr].word = insn->tm->opcode2;
4186
4187 for (i = 0; i < insn->opcount; i++)
4188 {
4189 enum optype type = insn->operands[i].type;
4190 if (!encode_operand (insn, type, &insn->operands[i]))
4191 return 0;
4192 }
4193 if (insn->tm->flags & FL_PAR)
4194 for (i = 0; i < insn->paropcount; i++)
4195 {
4196 enum optype partype = insn->paroperands[i].type;
4197 if (!encode_operand (insn, partype, &insn->paroperands[i]))
4198 return 0;
4199 }
4200
4201 emit_insn (insn);
4202
4203 return insn->words;
4204}
4205
4206static int
4207optimize_insn (tic54x_insn *insn)
4208{
4209 /* Optimize some instructions, helping out the brain-dead programmer. */
4210#define is_zero(op) ((op).exp.X_op == O_constant && (op).exp.X_add_number == 0)
4211 if (strcasecmp (insn->tm->name, "add") == 0)
4212 {
4213 if (insn->opcount > 1
4214 && is_accumulator (&insn->operands[insn->opcount - 2])
4215 && is_accumulator (&insn->operands[insn->opcount - 1])
4216 && strcasecmp (insn->operands[insn->opcount - 2].buf,
4217 insn->operands[insn->opcount - 1].buf) == 0)
4218 {
4219 --insn->opcount;
4220 insn->using_default_dst = 1;
4221 return 1;
4222 }
4223
4224 /* Try to collapse if Xmem and shift count is zero. */
4225 if ((OPTYPE (insn->tm->operand_types[0]) == OP_Xmem
4226 && OPTYPE (insn->tm->operand_types[1]) == OP_SHFT
4227 && is_zero (insn->operands[1]))
4228 /* Or if Smem, shift is zero or absent, and SRC == DST. */
4229 || (OPTYPE (insn->tm->operand_types[0]) == OP_Smem
4230 && OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT
4231 && is_type (&insn->operands[1], OP_SHIFT)
4232 && is_zero (insn->operands[1]) && insn->opcount == 3))
4233 {
4234 insn->operands[1] = insn->operands[2];
4235 insn->opcount = 2;
4236 return 1;
4237 }
4238 }
4239 else if (strcasecmp (insn->tm->name, "ld") == 0)
4240 {
4241 if (insn->opcount == 3 && insn->operands[0].type != OP_SRC)
4242 {
4243 if ((OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT
4244 || OPTYPE (insn->tm->operand_types[1]) == OP_SHFT)
4245 && is_zero (insn->operands[1])
4246 && (OPTYPE (insn->tm->operand_types[0]) != OP_lk
4247 || (insn->operands[0].exp.X_op == O_constant
4248 && insn->operands[0].exp.X_add_number <= 255
4249 && insn->operands[0].exp.X_add_number >= 0)))
4250 {
4251 insn->operands[1] = insn->operands[2];
4252 insn->opcount = 2;
4253 return 1;
4254 }
4255 }
4256 }
4257 else if (strcasecmp (insn->tm->name, "sth") == 0
4258 || strcasecmp (insn->tm->name, "stl") == 0)
4259 {
4260 if ((OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT
4261 || OPTYPE (insn->tm->operand_types[1]) == OP_SHFT)
4262 && is_zero (insn->operands[1]))
4263 {
4264 insn->operands[1] = insn->operands[2];
4265 insn->opcount = 2;
4266 return 1;
4267 }
4268 }
4269 else if (strcasecmp (insn->tm->name, "sub") == 0)
4270 {
4271 if (insn->opcount > 1
4272 && is_accumulator (&insn->operands[insn->opcount - 2])
4273 && is_accumulator (&insn->operands[insn->opcount - 1])
4274 && strcasecmp (insn->operands[insn->opcount - 2].buf,
4275 insn->operands[insn->opcount - 1].buf) == 0)
4276 {
4277 --insn->opcount;
4278 insn->using_default_dst = 1;
4279 return 1;
4280 }
4281
4282 if (((OPTYPE (insn->tm->operand_types[0]) == OP_Smem
4283 && OPTYPE (insn->tm->operand_types[1]) == OP_SHIFT)
4284 || (OPTYPE (insn->tm->operand_types[0]) == OP_Xmem
4285 && OPTYPE (insn->tm->operand_types[1]) == OP_SHFT))
4286 && is_zero (insn->operands[1])
4287 && insn->opcount == 3)
4288 {
4289 insn->operands[1] = insn->operands[2];
4290 insn->opcount = 2;
4291 return 1;
4292 }
4293 }
4294 return 0;
4295}
4296
4297/* Find a matching template if possible, and get the operand strings. */
4298
4299static int
4300tic54x_parse_insn (tic54x_insn *insn, char *line)
4301{
4302 insn->tm = (template *) hash_find (op_hash, insn->mnemonic);
4303 if (!insn->tm)
4304 {
4305 as_bad (_("Unrecognized instruction \"%s\""), insn->mnemonic);
4306 return 0;
4307 }
4308
4309 insn->opcount = get_operands (insn->operands, line);
4310 if (insn->opcount < 0)
4311 return 0;
4312
4313 /* Check each variation of operands for this mnemonic. */
4314 while (insn->tm->name && strcasecmp (insn->tm->name, insn->mnemonic) == 0)
4315 {
4316 if (insn->opcount >= insn->tm->minops
4317 && insn->opcount <= insn->tm->maxops
4318 && operands_match (insn, &insn->operands[0], insn->opcount,
4319 insn->tm->operand_types,
4320 insn->tm->minops, insn->tm->maxops))
4321 {
4322 /* SUCCESS! now try some optimizations. */
4323 if (optimize_insn (insn))
4324 {
4325 insn->tm = (template *) hash_find (op_hash,
4326 insn->mnemonic);
4327 continue;
4328 }
4329
4330 return 1;
4331 }
4332 ++(insn->tm);
4333 }
4334 as_bad (_("Unrecognized operand list '%s' for instruction '%s'"),
4335 line, insn->mnemonic);
4336 return 0;
4337}
4338
4339/* We set this in start_line_hook, 'cause if we do a line replacement, we
4340 won't be able to see the next line. */
4341static int parallel_on_next_line_hint = 0;
4342
4343/* See if this is part of a parallel instruction
4344 Look for a subsequent line starting with "||". */
4345
4346static int
4347next_line_shows_parallel (char *next_line)
4348{
4349 /* Look for the second half. */
4350 while (ISSPACE (*next_line))
4351 ++next_line;
4352
4353 return (next_line[0] == PARALLEL_SEPARATOR
4354 && next_line[1] == PARALLEL_SEPARATOR);
4355}
4356
4357static int
4358tic54x_parse_parallel_insn_firstline (tic54x_insn *insn, char *line)
4359{
4360 insn->tm = (template *) hash_find (parop_hash, insn->mnemonic);
4361 if (!insn->tm)
4362 {
4363 as_bad (_("Unrecognized parallel instruction \"%s\""),
4364 insn->mnemonic);
4365 return 0;
4366 }
4367
4368 while (insn->tm->name && strcasecmp (insn->tm->name,
4369 insn->mnemonic) == 0)
4370 {
4371 insn->opcount = get_operands (insn->operands, line);
4372 if (insn->opcount < 0)
4373 return 0;
4374 if (insn->opcount == 2
4375 && operands_match (insn, &insn->operands[0], insn->opcount,
4376 insn->tm->operand_types, 2, 2))
4377 {
4378 return 1;
4379 }
4380 ++(insn->tm);
4381 }
4382 /* Didn't find a matching parallel; try for a normal insn. */
4383 return 0;
4384}
4385
4386/* Parse the second line of a two-line parallel instruction. */
4387
4388static int
4389tic54x_parse_parallel_insn_lastline (tic54x_insn *insn, char *line)
4390{
4391 int valid_mnemonic = 0;
4392
4393 insn->paropcount = get_operands (insn->paroperands, line);
4394 while (insn->tm->name && strcasecmp (insn->tm->name,
4395 insn->mnemonic) == 0)
4396 {
4397 if (strcasecmp (insn->tm->parname, insn->parmnemonic) == 0)
4398 {
4399 valid_mnemonic = 1;
4400 if (insn->paropcount >= insn->tm->minops
4401 && insn->paropcount <= insn->tm->maxops
4402 && operands_match (insn, insn->paroperands,
4403 insn->paropcount,
4404 insn->tm->paroperand_types,
4405 insn->tm->minops, insn->tm->maxops))
4406 {
4407 return 1;
4408 }
4409 }
4410 ++(insn->tm);
4411 }
4412 if (valid_mnemonic)
4413 as_bad (_("Invalid operand (s) for parallel instruction \"%s\""),
4414 insn->parmnemonic);
4415 else
4416 as_bad (_("Unrecognized parallel instruction combination \"%s || %s\""),
4417 insn->mnemonic, insn->parmnemonic);
4418
4419 return 0;
4420}
4421
4422/* If quotes found, return copy of line up to closing quote;
4423 otherwise up until terminator.
4424 If it's a string, pass as-is; otherwise attempt substitution symbol
4425 replacement on the value. */
4426
4427static char *
4428subsym_get_arg (char *line, char *terminators, char **str, int nosub)
4429{
4430 char *ptr = line;
4431 char *endp;
4432 int is_string = *line == '"';
4433 int is_char = ISDIGIT (*line);
4434
4435 if (is_char)
4436 {
4437 while (ISDIGIT (*ptr))
4438 ++ptr;
4439 endp = ptr;
4440 *str = xmalloc (ptr - line + 1);
4441 strncpy (*str, line, ptr - line);
4442 (*str)[ptr - line] = 0;
4443 }
4444 else if (is_string)
4445 {
4446 char *savedp = input_line_pointer;
4447 int len;
4448 input_line_pointer = ptr;
4449 *str = demand_copy_C_string (&len);
4450 endp = input_line_pointer;
4451 input_line_pointer = savedp;
4452
4453 /* Do forced substitutions if requested. */
4454 if (!nosub && **str == ':')
4455 *str = subsym_substitute (*str, 1);
4456 }
4457 else
4458 {
4459 char *term = terminators;
4460 char *value = NULL;
4461
4462 while (*ptr && *ptr != *term)
4463 {
4464 if (!*term)
4465 {
4466 term = terminators;
4467 ++ptr;
4468 }
4469 else
4470 ++term;
4471 }
4472 endp = ptr;
4473 *str = xmalloc (ptr - line + 1);
4474 strncpy (*str, line, ptr - line);
4475 (*str)[ptr - line] = 0;
4476 /* Do simple substitution, if available. */
4477 if (!nosub && (value = subsym_lookup (*str, macro_level)) != NULL)
4478 *str = value;
4479 }
4480
4481 return endp;
4482}
4483
4484/* Replace the given substitution string.
4485 We start at the innermost macro level, so that existing locals remain local
4486 Note: we're treating macro args identically to .var's; I don't know if
4487 that's compatible w/TI's assembler. */
4488
4489static void
4490subsym_create_or_replace (name, value)
4491 char *name;
4492 char *value;
4493{
4494 int i;
4495
4496 for (i = macro_level; i > 0; i--)
4497 {
4498 if (hash_find (subsym_hash[i], name))
4499 {
4500 hash_replace (subsym_hash[i], name, value);
4501 return;
4502 }
4503 }
4504 if (hash_find (subsym_hash[0], name))
4505 hash_replace (subsym_hash[0], name, value);
4506 else
4507 hash_insert (subsym_hash[0], name, value);
4508}
4509
4510/* Look up the substitution string replacement for the given symbol.
4511 Start with the innermost macro substituion table given and work
4512 outwards. */
4513
4514static char *
4515subsym_lookup (name, nest_level)
4516 char *name;
4517 int nest_level;
4518{
4519 char *value = hash_find (subsym_hash[nest_level], name);
4520
4521 if (value || nest_level == 0)
4522 return value;
4523
4524 return subsym_lookup (name, nest_level - 1);
4525}
4526
4527/* Do substitution-symbol replacement on the given line (recursively).
4528 return the argument if no substitution was done
4529
4530 Also look for built-in functions ($func (arg)) and local labels.
4531
4532 If FORCED is set, look for forced substitutions of the form ':SYMBOL:'. */
4533
4534static char *
4535subsym_substitute (char *line, int forced)
4536{
4537 /* For each apparent symbol, see if it's a substitution symbol, and if so,
4538 replace it in the input. */
4539 char *replacement; /* current replacement for LINE. */
4540 char *head; /* Start of line. */
4541 char *ptr; /* Current examination point. */
4542 int changed = 0; /* Did we make a substitution? */
4543 int eval_line = 0; /* Is this line a .eval/.asg statement? */
4544 int eval_symbol = 0; /* Are we in the middle of the symbol for
4545 .eval/.asg? */
4546 char *eval_end = NULL;
4547 int recurse = 1;
4548 int line_conditional = 0;
4549 char *tmp;
4550
4551 /* Work with a copy of the input line. */
4552 replacement = xmalloc (strlen (line) + 1);
4553 strcpy (replacement, line);
4554
4555 ptr = head = replacement;
4556
4557 /* Flag lines where we might need to replace a single '=' with two;
4558 GAS uses single '=' to assign macro args values, and possibly other
4559 places, so limit what we replace. */
4560 if (strstr (line, ".if")
4561 || strstr (line, ".elseif")
4562 || strstr (line, ".break"))
4563 {
4564 line_conditional = 1;
4565 }
4566
4567 /* Watch out for .eval, so that we avoid doing substitution on the
4568 symbol being assigned a value. */
4569 if (strstr (line, ".eval") || strstr (line, ".asg"))
4570 eval_line = 1;
4571
4572 /* If it's a macro definition, don't do substitution on the argument
4573 names. */
4574 if (strstr (line, ".macro"))
4575 return line;
4576
4577 while (!is_end_of_line[(int) *ptr])
4578 {
4579 int current_char = *ptr;
4580
4581 /* Need to update this since LINE may have been modified. */
4582 if (eval_line)
4583 eval_end = strrchr (ptr, ',');
4584
4585 /* Replace triple double quotes with bounding quote/escapes. */
4586 if (current_char == '"' && ptr[1] == '"' && ptr[2] == '"')
4587 {
4588 ptr[1] = '\\';
4589 tmp = strstr (ptr + 2, "\"\"\"");
4590 if (tmp)
4591 tmp[0] = '\\';
4592 changed = 1;
4593 }
4594
4595 /* Replace a single '=' with a '==';
4596 for compatibility with older code only. */
4597 if (line_conditional && current_char == '=')
4598 {
4599 if (ptr[1] == '=')
4600 {
4601 ptr += 2;
4602 continue;
4603 }
4604 *ptr++ = '\0';
4605 tmp = xmalloc (strlen (head) + 2 + strlen (ptr) + 1);
4606 sprintf (tmp, "%s==%s", head, ptr);
4607 /* Continue examining after the '=='. */
4608 ptr = tmp + strlen (head) + 2;
4609 free (replacement);
4610 head = replacement = tmp;
4611 changed = 1;
4612 }
4613
4614 /* Flag when we've reached the symbol part of .eval/.asg. */
4615 if (eval_line && ptr >= eval_end)
4616 eval_symbol = 1;
4617
4618 /* For each apparent symbol, see if it's a substitution symbol, and if
4619 so, replace it in the input. */
4620 if ((forced && current_char == ':')
4621 || (!forced && is_name_beginner (current_char)))
4622 {
4623 char *name; /* Symbol to be replaced. */
4624 char *savedp = input_line_pointer;
4625 int c;
4626 char *value = NULL;
4627 char *tail; /* Rest of line after symbol. */
4628
4629 /* Skip the colon. */
4630 if (forced)
4631 ++ptr;
4632
4633 name = input_line_pointer = ptr;
4634 c = get_symbol_end ();
4635 /* '?' is not normally part of a symbol, but it IS part of a local
4636 label. */
4637 if (c == '?')
4638 {
4639 *input_line_pointer++ = c;
4640 c = *input_line_pointer;
4641 *input_line_pointer = '\0';
4642 }
4643 /* Avoid infinite recursion; if a symbol shows up a second time for
4644 substitution, leave it as is. */
4645 if (hash_find (subsym_recurse_hash, name) == NULL)
4646 value = subsym_lookup (name, macro_level);
4647 else
4648 as_warn (_("%s symbol recursion stopped at "
4649 "second appearance of '%s'"),
4650 forced ? "Forced substitution" : "Substitution", name);
4651 ptr = tail = input_line_pointer;
4652 input_line_pointer = savedp;
4653
4654 /* Check for local labels; replace them with the appropriate
4655 substitution. */
4656 if ((*name == '$' && ISDIGIT (name[1]) && name[2] == '\0')
4657 || name[strlen (name) - 1] == '?')
4658 {
4659 /* Use an existing identifier for that label if, available, or
4660 create a new, unique identifier. */
4661 value = hash_find (local_label_hash[macro_level], name);
4662 if (value == NULL)
4663 {
4664 char digit[11];
4665 char *namecopy = strcpy (xmalloc (strlen (name) + 1), name);
4666 value = strcpy (xmalloc (strlen (name) + sizeof (digit) + 1),
4667 name);
4668 if (*value != '$')
4669 value[strlen (value) - 1] = '\0';
4670 sprintf (digit, ".%d", local_label_id++);
4671 strcat (value, digit);
4672 hash_insert (local_label_hash[macro_level], namecopy, value);
4673 }
4674 /* Indicate where to continue looking for substitutions. */
4675 ptr = tail;
4676 }
4677 /* Check for built-in subsym and math functions. */
4678 else if (value != NULL && *name == '$')
4679 {
4680 subsym_proc_entry *entry = (subsym_proc_entry *) value;
4681 math_proc_entry *math_entry = hash_find (math_hash, name);
4682 char *arg1, *arg2 = NULL;
4683
4684 *ptr = c;
4685 if (entry == NULL)
4686 {
4687 as_bad (_("Unrecognized substitution symbol function"));
4688 break;
4689 }
4690 else if (*ptr != '(')
4691 {
4692 as_bad (_("Missing '(' after substitution symbol function"));
4693 break;
4694 }
4695 ++ptr;
4696 if (math_entry != NULL)
4697 {
4698 float arg1, arg2 = 0;
4699 volatile float fresult;
4700
4701 arg1 = (float) strtod (ptr, &ptr);
4702 if (math_entry->nargs == 2)
4703 {
4704 if (*ptr++ != ',')
4705 {
4706 as_bad (_("Expecting second argument"));
4707 break;
4708 }
4709 arg2 = (float) strtod (ptr, &ptr);
4710 }
4711 fresult = (*math_entry->proc) (arg1, arg2);
4712 value = xmalloc (128);
4713 if (math_entry->int_return)
4714 sprintf (value, "%d", (int) fresult);
4715 else
4716 sprintf (value, "%f", fresult);
4717 if (*ptr++ != ')')
4718 {
4719 as_bad (_("Extra junk in function call, expecting ')'"));
4720 break;
4721 }
4722 /* Don't bother recursing; the replacement isn't a
4723 symbol. */
4724 recurse = 0;
4725 }
4726 else
4727 {
4728 int val;
4729 int arg_type[2] = { *ptr == '"' , 0 };
4730 int ismember = !strcmp (entry->name, "$ismember");
4731 /* Parse one or two args, which must be a substitution
4732 symbol, string or a character-string constant. */
4733 /* For all functions, a string or substitution symbol may be
4734 used, with the following exceptions:
4735 firstch/lastch: 2nd arg must be character constant
4736 ismember: both args must be substitution symbols. */
4737 ptr = subsym_get_arg (ptr, ",)", &arg1, ismember);
4738 if (!arg1)
4739 break;
4740 if (entry->nargs == 2)
4741 {
4742 if (*ptr++ != ',')
4743 {
4744 as_bad (_("Function expects two arguments"));
4745 break;
4746 }
4747 /* Character constants are converted to numerics
4748 by the preprocessor. */
4749 arg_type[1] = (ISDIGIT (*ptr)) ? 2 : (*ptr == '"');
4750 ptr = subsym_get_arg (ptr, ")", &arg2, ismember);
4751 }
4752 /* Args checking. */
4753 if ((!strcmp (entry->name, "$firstch")
4754 || !strcmp (entry->name, "$lastch"))
4755 && arg_type[1] != 2)
4756 {
4757 as_bad (_("Expecting character constant argument"));
4758 break;
4759 }
4760 if (ismember
4761 && (arg_type[0] != 0 || arg_type[1] != 0))
4762 {
4763 as_bad (_("Both arguments must be substitution symbols"));
4764 break;
4765 }
4766 if (*ptr++ != ')')
4767 {
4768 as_bad (_("Extra junk in function call, expecting ')'"));
4769 break;
4770 }
4771 val = (*entry->proc) (arg1, arg2);
4772 value = xmalloc (64);
4773 sprintf (value, "%d", val);
4774 }
4775 /* Fix things up to replace the entire expression, not just the
4776 function name. */
4777 tail = ptr;
4778 c = *tail;
4779 }
4780
4781 if (value != NULL && !eval_symbol)
4782 {
4783 /* Replace the symbol with its string replacement and
4784 continue. Recursively replace VALUE until either no
4785 substitutions are performed, or a substitution that has been
4786 previously made is encountered again.
4787
4788 put the symbol into the recursion hash table so we only
4789 try to replace a symbol once. */
4790 if (recurse)
4791 {
4792 hash_insert (subsym_recurse_hash, name, name);
4793 value = subsym_substitute (value, macro_level > 0);
4794 hash_delete (subsym_recurse_hash, name);
4795 }
4796
4797 /* Temporarily zero-terminate where the symbol started. */
4798 *name = 0;
4799 if (forced)
4800 {
4801 if (c == '(')
4802 {
4803 /* Subscripted substitution symbol -- use just the
4804 indicated portion of the string; the description
4805 kinda indicates that forced substituion is not
4806 supposed to be recursive, but I'm not sure. */
4807 unsigned beg, len = 1; /* default to a single char */
4808 char *newval = strcpy (xmalloc (strlen (value) + 1),
4809 value);
4810
4811 savedp = input_line_pointer;
4812 input_line_pointer = tail + 1;
4813 beg = get_absolute_expression ();
4814 if (beg < 1)
4815 {
4816 as_bad (_("Invalid subscript (use 1 to %d)"),
4817 strlen (value));
4818 break;
4819 }
4820 if (*input_line_pointer == ',')
4821 {
4822 ++input_line_pointer;
4823 len = get_absolute_expression ();
4824 if (beg + len > strlen (value))
4825 {
4826 as_bad (_("Invalid length (use 0 to %d"),
4827 strlen (value) - beg);
4828 break;
4829 }
4830 }
4831 newval += beg - 1;
4832 newval[len] = 0;
4833 tail = input_line_pointer;
4834 if (*tail++ != ')')
4835 {
4836 as_bad (_("Missing ')' in subscripted substitution "
4837 "symbol expression"));
4838 break;
4839 }
4840 c = *tail;
4841 input_line_pointer = savedp;
4842
4843 value = newval;
4844 }
4845 name[-1] = 0;
4846 }
4847 tmp = xmalloc (strlen (head) + strlen (value) +
4848 strlen (tail + 1) + 2);
4849 strcpy (tmp, head);
4850 strcat (tmp, value);
4851 /* Make sure forced substitutions are properly terminated. */
4852 if (forced)
4853 {
4854 if (c != ':')
4855 {
4856 as_bad (_("Missing forced substitution terminator ':'"));
4857 break;
4858 }
4859 ++tail;
4860#if 0
4861 /* Try to replace required whitespace
4862 eliminated by the preprocessor; technically, a forced
4863 substitution could come anywhere, even mid-symbol,
4864 e.g. if x is "0", 'sym:x:end' should result in 'sym0end',
4865 but 'sym:x: end' should result in 'sym0 end'.
4866 FIXME -- this should really be fixed in the preprocessor,
4867 but would require several new states;
4868 KEEP_WHITE_AROUND_COLON does part of the job, but isn't
4869 complete. */
4870 if ((is_part_of_name (tail[1])
4871 && tail[1] != '.'
4872 && tail[1] != '$')
4873 || tail[1] == '\0' || tail[1] == ',' || tail[1] == '"')
4874 ++tail;
4875 else
4876 *tail = ' ';
4877#endif
4878 }
4879 else
4880 /* Restore the character after the symbol end. */
4881 *tail = c;
4882 strcat (tmp, tail);
4883 /* Continue examining after the replacement value. */
4884 ptr = tmp + strlen (head) + strlen (value);
4885 free (replacement);
4886 head = replacement = tmp;
4887 changed = 1;
4888 }
4889 else
4890 *ptr = c;
4891 }
4892 else
4893 {
4894 ++ptr;
4895 }
4896 }
4897
4898 if (changed)
4899 return replacement;
4900 else
4901 return line;
4902}
4903
4904/* We use this to handle substitution symbols
4905 hijack input_line_pointer, replacing it with our substituted string.
4906
4907 .sslist should enable listing the line after replacements are made...
4908
4909 returns the new buffer limit. */
4910
4911void
4912tic54x_start_line_hook ()
4913{
4914 char *line, *endp;
4915 char *replacement = NULL;
4916
4917 /* Work with a copy of the input line, including EOL char. */
4918 endp = input_line_pointer;
4919 while (!is_end_of_line[(int) *endp++])
4920 ;
4921 line = xmalloc (endp - input_line_pointer + 1);
4922 strncpy (line, input_line_pointer, endp - input_line_pointer + 1);
4923 line[endp - input_line_pointer] = 0;
4924
4925 /* Scan ahead for parallel insns. */
4926 parallel_on_next_line_hint = next_line_shows_parallel (endp + 1);
4927
4928 /* If within a macro, first process forced replacements. */
4929 if (macro_level > 0)
4930 replacement = subsym_substitute (line, 1);
4931 else
4932 replacement = line;
4933 replacement = subsym_substitute (replacement, 0);
4934
4935 if (replacement != line)
4936 {
4937 char *tmp = replacement;
4938 char *comment = strchr (replacement, ';');
4939 char endc = replacement[strlen (replacement) - 1];
4940
4941 /* Clean up the replacement; we'd prefer to have this done by the
4942 standard preprocessing equipment (maybe do_scrub_chars?)
4943 but for now, do a quick-and-dirty. */
4944 if (comment != NULL)
4945 {
4946 comment[0] = endc;
4947 comment[1] = 0;
4948 --comment;
4949 }
4950 else
4951 comment = replacement + strlen (replacement) - 1;
4952
4953 /* Trim trailing whitespace. */
4954 while (ISSPACE (*comment))
4955 {
4956 comment[0] = endc;
4957 comment[1] = 0;
4958 --comment;
4959 }
4960
4961 /* Compact leading whitespace. */
4962 while (ISSPACE (tmp[0]) && ISSPACE (tmp[1]))
4963 ++tmp;
4964
4965 input_line_pointer = endp;
4966 input_scrub_insert_line (tmp);
4967 free (replacement);
4968 free (line);
4969 /* Keep track of whether we've done a substitution. */
4970 substitution_line = 1;
4971 }
4972 else
4973 {
4974 /* No change. */
4975 free (line);
4976 substitution_line = 0;
4977 }
4978}
4979
4980/* This is the guts of the machine-dependent assembler. STR points to a
4981 machine dependent instruction. This function is supposed to emit
4982 the frags/bytes it assembles to. */
4983void
4984md_assemble (line)
4985 char *line;
4986{
4987 static int repeat_slot = 0;
4988 static int delay_slots = 0; /* How many delay slots left to fill? */
4989 static int is_parallel = 0;
4990 static tic54x_insn insn;
4991 char *lptr;
4992 char *savedp = input_line_pointer;
4993 int c;
4994
4995 input_line_pointer = line;
4996 c = get_symbol_end ();
4997
4998 if (cpu == VNONE)
4999 cpu = V542;
5000 if (address_mode_needs_set)
5001 {
5002 set_address_mode (amode);
5003 address_mode_needs_set = 0;
5004 }
5005 if (cpu_needs_set)
5006 {
5007 set_cpu (cpu);
5008 cpu_needs_set = 0;
5009 }
5010 assembly_begun = 1;
5011
5012 if (is_parallel)
5013 {
5014 is_parallel = 0;
5015
5016 strcpy (insn.parmnemonic, line);
5017 lptr = input_line_pointer;
5018 *lptr = c;
5019 input_line_pointer = savedp;
5020
5021 if (tic54x_parse_parallel_insn_lastline (&insn, lptr))
5022 {
5023 int words = build_insn (&insn);
5024
5025 if (delay_slots != 0)
5026 {
5027 if (words > delay_slots)
5028 {
5029 as_bad (_("Instruction does not fit in available delay "
5030 "slots (%d-word insn, %d slots left)"),
5031 words, delay_slots);
5032 delay_slots = 0;
5033 return;
5034 }
5035 delay_slots -= words;
5036 }
5037 }
5038 return;
5039 }
5040
5041 memset (&insn, 0, sizeof (insn));
5042 strcpy (insn.mnemonic, line);
5043 lptr = input_line_pointer;
5044 *lptr = c;
5045 input_line_pointer = savedp;
5046
5047 /* See if this line is part of a parallel instruction; if so, either this
5048 line or the next line will have the "||" specifier preceding the
5049 mnemonic, and we look for it in the parallel insn hash table. */
5050 if (strstr (line, "||") != NULL || parallel_on_next_line_hint)
5051 {
5052 char *tmp = strstr (line, "||");
5053 if (tmp != NULL)
5054 *tmp = '\0';
5055
5056 if (tic54x_parse_parallel_insn_firstline (&insn, lptr))
5057 {
5058 is_parallel = 1;
5059 /* If the parallel part is on the same line, process it now,
5060 otherwise let the assembler pick up the next line for us. */
5061 if (tmp != NULL)
5062 {
5063 while (ISSPACE (tmp[2]))
5064 ++tmp;
5065 md_assemble (tmp + 2);
5066 }
5067 }
5068 else
5069 {
5070 as_bad (_("Unrecognized parallel instruction '%s'"), line);
5071 }
5072 return;
5073 }
5074
5075 if (tic54x_parse_insn (&insn, lptr))
5076 {
5077 int words;
5078
5079 if ((insn.tm->flags & FL_LP)
5080 && cpu != V545LP && cpu != V546LP)
5081 {
5082 as_bad (_("Instruction '%s' requires an LP cpu version"),
5083 insn.tm->name);
5084 return;
5085 }
5086 if ((insn.tm->flags & FL_FAR)
5087 && amode != far_mode)
5088 {
5089 as_bad (_("Instruction '%s' requires far mode addressing"),
5090 insn.tm->name);
5091 return;
5092 }
5093
5094 words = build_insn (&insn);
5095
5096 /* Is this instruction in a delay slot? */
5097 if (delay_slots)
5098 {
5099 if (words > delay_slots)
5100 {
5101 as_warn (_("Instruction does not fit in available delay "
5102 "slots (%d-word insn, %d slots left). "
5103 "Resulting behavior is undefined."),
5104 words, delay_slots);
5105 delay_slots = 0;
5106 return;
5107 }
5108 /* Branches in delay slots are not allowed. */
5109 if (insn.tm->flags & FL_BMASK)
5110 {
5111 as_warn (_("Instructions which cause PC discontinuity are not "
5112 "allowed in a delay slot. "
5113 "Resulting behavior is undefined."));
5114 }
5115 delay_slots -= words;
5116 }
5117
5118 /* Is this instruction the target of a repeat? */
5119 if (repeat_slot)
5120 {
5121 if (insn.tm->flags & FL_NR)
5122 as_warn (_("'%s' is not repeatable. "
5123 "Resulting behavior is undefined."),
5124 insn.tm->name);
5125 else if (insn.is_lkaddr)
5126 as_warn (_("Instructions using long offset modifiers or absolute "
5127 "addresses are not repeatable. "
5128 "Resulting behavior is undefined."));
5129 repeat_slot = 0;
5130 }
5131
5132 /* Make sure we check the target of a repeat instruction. */
5133 if (insn.tm->flags & B_REPEAT)
5134 {
5135 repeat_slot = 1;
5136 /* FIXME -- warn if repeat_slot == 1 at EOF. */
5137 }
5138 /* Make sure we check our delay slots for validity. */
5139 if (insn.tm->flags & FL_DELAY)
5140 {
5141 delay_slots = 2;
5142 /* FIXME -- warn if delay_slots != 0 at EOF. */
5143 }
5144 }
5145}
5146
5147/* Do a final adjustment on the symbol table; in this case, make sure we have
5148 a ".file" symbol. */
5149
5150void
5151tic54x_adjust_symtab ()
5152{
5153 if (symbol_rootP == NULL
5154 || S_GET_STORAGE_CLASS (symbol_rootP) != C_FILE)
5155 {
5156 char *filename;
5157 unsigned lineno;
5158 as_where (&filename, &lineno);
5159 c_dot_file_symbol (filename);
5160 }
5161}
5162
5163/* In order to get gas to ignore any | chars at the start of a line,
5164 this function returns true if a | is found in a line.
5165 This lets us process parallel instructions, which span two lines. */
5166
5167int
5168tic54x_unrecognized_line (int c)
5169{
5170 return c == PARALLEL_SEPARATOR;
5171}
5172
5173/* Watch for local labels of the form $[0-9] and [_a-zA-Z][_a-zA-Z0-9]*?
5174 Encode their names so that only we see them and can map them to the
5175 appropriate places.
5176 FIXME -- obviously this isn't done yet. These locals still show up in the
5177 symbol table. */
5178void
5179tic54x_define_label (sym)
5180 symbolS *sym;
5181{
5182#if 0
5183 static int local_label_count = 0;
5184 const char *name = S_GET_NAME (sym);
5185#endif
5186
5187 /* Just in case we need this later; note that this is not necessarily the
5188 same thing as line_label...
5189 When aligning or assigning labels to fields, sometimes the label is
5190 assigned other than the address at which the label appears.
5191 FIXME -- is this really needed? I think all the proper label assignment
5192 is done in tic54x_cons. */
5193 last_label_seen = sym;
5194}
5195
5196/* Try to parse something that normal parsing failed at. */
5197
5198symbolS *
5199tic54x_undefined_symbol (name)
5200 char *name;
5201{
5202 symbol *sym;
5203
5204 /* Not sure how to handle predefined symbols. */
5205 if ((sym = (symbol *) hash_find (cc_hash, name)) != NULL ||
5206 (sym = (symbol *) hash_find (cc2_hash, name)) != NULL ||
5207 (sym = (symbol *) hash_find (cc3_hash, name)) != NULL ||
5208 (sym = (symbol *) hash_find (misc_symbol_hash, name)) != NULL ||
5209 (sym = (symbol *) hash_find (sbit_hash, name)) != NULL)
5210 {
5211 return symbol_new (name, reg_section,
5212 (valueT) sym->value,
5213 &zero_address_frag);
5214 }
5215
5216 if ((sym = (symbol *) hash_find (reg_hash, name)) != NULL ||
5217 (sym = (symbol *) hash_find (mmreg_hash, name)) != NULL ||
5218 !strcasecmp (name, "a") || !strcasecmp (name, "b"))
5219 {
5220 return symbol_new (name, reg_section,
5221 (valueT) sym ? sym->value : 0,
5222 &zero_address_frag);
5223 }
5224
5225 return NULL;
5226}
5227
5228/* Parse a name in an expression before the expression parser takes a stab at
5229 it. */
5230
5231int
5232tic54x_parse_name (name, exp)
5233 char *name ATTRIBUTE_UNUSED;
5234 expressionS *exp ATTRIBUTE_UNUSED;
5235{
5236#if 0
5237 symbol *sym = (symbol *) hash_find (mmreg_hash, name);
5238
5239 /* If it's a MMREG, replace it with its constant value. */
5240 if (sym)
5241 {
5242 exp->X_op = O_constant;
5243 exp->X_add_number = sym->value;
5244 return 1;
5245 }
5246#endif
5247 return 0;
5248}
5249
5250char *
5251md_atof (type, literalP, sizeP)
5252 int type;
5253 char *literalP;
5254 int *sizeP;
5255{
5256#define MAX_LITTLENUMS 2
5257 LITTLENUM_TYPE words[MAX_LITTLENUMS];
5258 LITTLENUM_TYPE *word;
5259 /* Only one precision on the c54x. */
5260 int prec = 2;
5261 char *t = atof_ieee (input_line_pointer, type, words);
5262 if (t)
5263 input_line_pointer = t;
5264 *sizeP = 4;
5265
5266 /* Target data is little-endian, but floats are stored
5267 big-"word"ian. ugh. */
5268 for (word = words; prec--;)
5269 {
5270 md_number_to_chars (literalP, (long) (*word++), sizeof (LITTLENUM_TYPE));
5271 literalP += sizeof (LITTLENUM_TYPE);
5272 }
5273
5274 return 0;
5275}
5276
5277arelent *
5278tc_gen_reloc (section, fixP)
5279 asection *section;
5280 fixS *fixP;
5281{
5282 arelent *rel;
5283 bfd_reloc_code_real_type code = fixP->fx_r_type;
5284 asymbol *sym = symbol_get_bfdsym (fixP->fx_addsy);
5285
5286 rel = (arelent *) xmalloc (sizeof (arelent));
5287 rel->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
5288 *rel->sym_ptr_ptr = sym;
5289 /* We assume that all rel->address are host byte offsets. */
5290 rel->address = fixP->fx_frag->fr_address + fixP->fx_where;
5291 rel->address /= OCTETS_PER_BYTE;
5292 rel->howto = bfd_reloc_type_lookup (stdoutput, code);
5293 if (!strcmp (sym->name, section->name))
5294 rel->howto += HOWTO_BANK;
5295
5296 if (!rel->howto)
5297 {
5298 const char *name = S_GET_NAME (fixP->fx_addsy);
5299 if (name == NULL)
5300 name = "<unknown>";
5301 as_fatal ("Cannot generate relocation type for symbol %s, code %s",
5302 name, bfd_get_reloc_code_name (code));
5303 return NULL;
5304 }
5305 return rel;
5306}
5307
5308/* Handle cons expressions. */
5309
5310void
5311tic54x_cons_fix_new (fragS *frag, int where, int octets, expressionS *exp)
5312{
5313 bfd_reloc_code_real_type r;
5314 switch (octets)
5315 {
5316 default:
5317 as_bad (_("Unsupported relocation size %d"), octets);
5318 r = BFD_RELOC_TIC54X_16_OF_23;
5319 break;
5320 case 2:
5321 r = BFD_RELOC_TIC54X_16_OF_23;
5322 break;
5323 case 4:
5324 /* TI assembler always uses this, regardless of addressing mode. */
5325 if (emitting_long)
5326 r = BFD_RELOC_TIC54X_23;
5327 else
5328 /* We never want to directly generate this; this is provided for
5329 stabs support only. */
5330 r = BFD_RELOC_32;
5331 break;
5332 }
5333 fix_new_exp (frag, where, octets, exp, 0, r);
5334}
5335
5336/* Attempt to simplify or even eliminate a fixup.
5337 To indicate that a fixup has been eliminated, set fixP->fx_done.
5338
5339 If fixp->fx_addsy is non-NULL, we'll have to generate a reloc entry. */
5340
5341void
5342md_apply_fix3 (fixP, valP, seg)
5343 fixS *fixP;
5344 valueT * valP;
5345 segT seg ATTRIBUTE_UNUSED;
5346{
5347 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
5348 valueT val = * valP;
5349
5350 switch (fixP->fx_r_type)
5351 {
5352 default:
5353 as_fatal ("Bad relocation type: 0x%02x", fixP->fx_r_type);
5354 return;
5355 case BFD_RELOC_TIC54X_MS7_OF_23:
5356 val = (val >> 16) & 0x7F;
5357 /* Fall through. */
5358 case BFD_RELOC_TIC54X_16_OF_23:
5359 case BFD_RELOC_16:
5360 bfd_put_16 (stdoutput, val, buf);
5361 /* Indicate what we're actually writing, so that we don't get warnings
5362 about exceeding available space. */
5363 *valP = val & 0xFFFF;
5364 break;
5365 case BFD_RELOC_TIC54X_PARTLS7:
5366 bfd_put_16 (stdoutput,
5367 (bfd_get_16 (stdoutput, buf) & 0xFF80) | (val & 0x7F),
5368 buf);
5369 /* Indicate what we're actually writing, so that we don't get warnings
5370 about exceeding available space. */
5371 *valP = val & 0x7F;
5372 break;
5373 case BFD_RELOC_TIC54X_PARTMS9:
5374 /* TI assembler doesn't shift its encoding for relocatable files, and is
5375 thus incompatible with this implementation's relocatable files. */
5376 bfd_put_16 (stdoutput,
5377 (bfd_get_16 (stdoutput, buf) & 0xFE00) | (val >> 7),
5378 buf);
5379 break;
5380 case BFD_RELOC_32:
5381 case BFD_RELOC_TIC54X_23:
5382 bfd_put_32 (stdoutput,
5383 (bfd_get_32 (stdoutput, buf) & 0xFF800000) | val,
5384 buf);
5385 break;
5386 }
5387
5388 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
5389 fixP->fx_done = 1;
5390}
5391
5392/* This is our chance to record section alignment
5393 don't need to do anything here, since BFD does the proper encoding. */
5394
5395valueT
5396md_section_align (segment, section_size)
5397 segT segment ATTRIBUTE_UNUSED;
5398 valueT section_size;
5399{
5400 return section_size;
5401}
5402
5403long
5404md_pcrel_from (fixP)
5405 fixS *fixP ATTRIBUTE_UNUSED;
5406{
5407 return 0;
5408}
5409
5410#if defined OBJ_COFF
5411
5412short
5413tc_coff_fix2rtype (fixP)
5414 fixS *fixP;
5415{
5416 return (fixP->fx_r_type);
5417}
5418
5419#endif /* OBJ_COFF */
5420
5421/* Mostly little-endian, but longwords (4 octets) get MS word stored
5422 first. */
5423
5424void
5425tic54x_number_to_chars (buf, val, n)
5426 char *buf;
5427 valueT val;
5428 int n;
5429{
5430 if (n != 4)
5431 number_to_chars_littleendian (buf, val, n);
5432 else
5433 {
5434 number_to_chars_littleendian (buf , val >> 16 , 2);
5435 number_to_chars_littleendian (buf + 2, val & 0xFFFF, 2);
5436 }
5437}
5438
5439int
5440tic54x_estimate_size_before_relax (frag, seg)
5441 fragS *frag ATTRIBUTE_UNUSED;
5442 segT seg ATTRIBUTE_UNUSED;
5443{
5444 return 0;
5445}
5446
5447/* We use this to handle bit allocations which we couldn't handle before due
5448 to symbols being in different frags. return number of octets added. */
5449
5450int
5451tic54x_relax_frag (frag, stretch)
5452 fragS *frag;
5453 long stretch ATTRIBUTE_UNUSED;
5454{
5455 symbolS *sym = frag->fr_symbol;
5456 int growth = 0;
5457 int i;
5458
5459 if (sym != NULL)
5460 {
5461 struct bit_info *bi = (struct bit_info *) frag->fr_opcode;
5462 int bit_offset = frag_bit_offset (frag_prev (frag, bi->seg), bi->seg);
5463 int size = S_GET_VALUE (sym);
5464 fragS *prev_frag = bit_offset_frag (frag_prev (frag, bi->seg), bi->seg);
5465 int available = 16 - bit_offset;
5466
5467 if (symbol_get_frag (sym) != &zero_address_frag
5468 || S_IS_COMMON (sym)
5469 || !S_IS_DEFINED (sym))
5470 as_bad_where (frag->fr_file, frag->fr_line,
5471 _("non-absolute value used with .space/.bes"));
5472
5473 if (size < 0)
5474 {
5475 as_warn (_("negative value ignored in %s"),
5476 bi->type == TYPE_SPACE ? ".space" :
5477 bi->type == TYPE_BES ? ".bes" : ".field");
5478 growth = 0;
5479 frag->tc_frag_data = frag->fr_fix = 0;
5480 return 0;
5481 }
5482
5483 if (bi->type == TYPE_FIELD)
5484 {
5485 /* Bit fields of 16 or larger will have already been handled. */
5486 if (bit_offset != 0 && available >= size)
5487 {
5488 char *p = prev_frag->fr_literal;
5489 valueT value = bi->value;
5490 value <<= available - size;
5491 value |= ((unsigned short) p[1] << 8) | p[0];
5492 md_number_to_chars (p, value, 2);
5493 if ((prev_frag->tc_frag_data += size) == 16)
5494 prev_frag->tc_frag_data = 0;
5495 if (bi->sym)
5496 symbol_set_frag (bi->sym, prev_frag);
5497 /* This frag is no longer used. */
5498 growth = -frag->fr_fix;
5499 frag->fr_fix = 0;
5500 frag->tc_frag_data = 0;
5501 }
5502 else
5503 {
5504 char *p = frag->fr_literal;
5505 valueT value = bi->value << (16 - size);
5506 md_number_to_chars (p, value, 2);
5507 if ((frag->tc_frag_data = size) == 16)
5508 frag->tc_frag_data = 0;
5509 growth = 0;
5510 }
5511 }
5512 else
5513 {
5514 if (bit_offset != 0 && bit_offset < 16)
5515 {
5516 if (available >= size)
5517 {
5518 if ((prev_frag->tc_frag_data += size) == 16)
5519 prev_frag->tc_frag_data = 0;
5520 if (bi->sym)
5521 symbol_set_frag (bi->sym, prev_frag);
5522 /* This frag is no longer used. */
5523 growth = -frag->fr_fix;
5524 frag->fr_fix = 0;
5525 frag->tc_frag_data = 0;
5526 goto getout;
5527 }
5528 if (bi->type == TYPE_SPACE && bi->sym)
5529 symbol_set_frag (bi->sym, prev_frag);
5530 size -= available;
5531 }
5532 growth = (size + 15) / 16 * OCTETS_PER_BYTE - frag->fr_fix;
5533 for (i = 0; i < growth; i++)
5534 frag->fr_literal[i] = 0;
5535 frag->fr_fix = growth;
5536 frag->tc_frag_data = size % 16;
5537 /* Make sure any BES label points to the LAST word allocated. */
5538 if (bi->type == TYPE_BES && bi->sym)
5539 S_SET_VALUE (bi->sym, frag->fr_fix / OCTETS_PER_BYTE - 1);
5540 }
5541 getout:
5542 frag->fr_symbol = 0;
5543 frag->fr_opcode = 0;
5544 free ((void *) bi);
5545 }
5546 return growth;
5547}
5548
5549void
5550tic54x_convert_frag (abfd, seg, frag)
5551 bfd *abfd ATTRIBUTE_UNUSED;
5552 segT seg ATTRIBUTE_UNUSED;
5553 fragS *frag;
5554{
5555 /* Offset is in bytes. */
5556 frag->fr_offset = (frag->fr_next->fr_address
5557 - frag->fr_address
5558 - frag->fr_fix) / frag->fr_var;
5559 if (frag->fr_offset < 0)
5560 {
5561 as_bad_where (frag->fr_file, frag->fr_line,
5562 _("attempt to .space/.bes backwards? (%ld)"),
5563 (long) frag->fr_offset);
5564 }
5565 frag->fr_type = rs_space;
5566}
5567
5568/* We need to avoid having labels defined for certain directives/pseudo-ops
5569 since once the label is defined, it's in the symbol table for good. TI
5570 syntax puts the symbol *before* the pseudo (which is kinda like MRI syntax,
5571 I guess, except I've never seen a definition of MRI syntax).
5572
5573 C is the character that used to be at *REST, which points to the end of the
5574 label.
5575
5576 Don't allow labels to start with '.' */
5577
5578int
5579tic54x_start_label (c, rest)
5580 int c;
5581 char *rest;
5582{
5583 /* If within .struct/.union, no auto line labels, please. */
5584 if (current_stag != NULL)
5585 return 0;
5586
5587 /* Disallow labels starting with "." */
5588 if (c != ':')
5589 {
5590 char *label = rest;
5591 while (!is_end_of_line[(int) label[-1]])
5592 --label;
5593 if (*label == '.')
5594 {
5595 as_bad (_("Invalid label '%s'"), label);
5596 return 0;
5597 }
5598 }
5599
5600 if (is_end_of_line[(int) c])
5601 return 1;
5602
5603 if (ISSPACE (c))
5604 while (ISSPACE (c = *++rest))
5605 ;
5606 if (c == '.')
5607 {
5608 /* Don't let colon () define a label for any of these... */
5609 return (strncasecmp (rest, ".tag", 4) != 0 || !ISSPACE (rest[4]))
5610 && (strncasecmp (rest, ".struct", 7) != 0 || !ISSPACE (rest[7]))
5611 && (strncasecmp (rest, ".union", 6) != 0 || !ISSPACE (rest[6]))
5612 && (strncasecmp (rest, ".macro", 6) != 0 || !ISSPACE (rest[6]))
5613 && (strncasecmp (rest, ".set", 4) != 0 || !ISSPACE (rest[4]))
5614 && (strncasecmp (rest, ".equ", 4) != 0 || !ISSPACE (rest[4]));
5615 }
5616
5617 return 1;
5618}
This page took 0.040509 seconds and 4 git commands to generate.