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