Fix formatting.
[deliverable/binutils-gdb.git] / gas / config / tc-tic54x.c
CommitLineData
39bec121
TW
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
d0313fb7 22/* Texas Instruments TMS320C54X machine specific gas.
39bec121
TW
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
d0313fb7 42 TI sets labels to be data type 4 (T_INT); GAS uses T_NULL. */
39bec121
TW
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
d0313fb7 56#define MAX_LINE 256 /* Lines longer than this are truncated by TI's asm. */
39bec121
TW
57
58const char comment_chars[] = ";";
59const char line_comment_chars[] = ";*#"; /* at column zero only */
d0313fb7 60const char line_separator_chars[] = ""; /* not permitted */
39bec121 61
d0313fb7
NC
62/* Characters which indicate that this is a floating point constant. */
63const char FLT_CHARS[] = "fF";
64/* Characters that can be used to separate mantissa from exp in FP
65 nums. */
39bec121
TW
66const char EXP_CHARS[] = "eE";
67
d0313fb7
NC
68/* Only word (et al.), align, or conditionals are allowed within
69 .struct/.union. */
39bec121
TW
70#define ILLEGAL_WITHIN_STRUCT() \
71do if (current_stag != NULL){ \
72as_bad (_("pseudo-op illegal within .struct/.union"));return; } while (0)
73
74void
75md_show_usage (stream)
d0313fb7 76 FILE *stream;
39bec121
TW
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"));
d0313fb7
NC
81#if 0
82 fprintf (stream, _("-mcoff-version={0|1|2} Select COFF version\n"));
83#endif
39bec121
TW
84 fprintf (stream, _("-merrors-to-file <filename>\n"));
85 fprintf (stream, _("-me <filename> Redirect errors to a file\n"));
86}
87
88const char *md_shortopts = "";
d0313fb7
NC
89
90enum cpu_version
91{
39bec121
TW
92 VNONE = 0, V541 = 1, V542 = 2, V543 = 3, V545 = 5, V548 = 8, V549 = 9,
93 V545LP = 15, V546LP = 16
94};
95
d0313fb7
NC
96enum address_mode
97{
98 c_mode, /* 16-bit addresses */
39bec121
TW
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
107struct 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
118size_t md_longopts_size = sizeof (md_longopts);
119
d0313fb7 120static int assembly_begun = 0;
39bec121
TW
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
d0313fb7 128 extended addressing only. We include it for compatibility. */
39bec121 129static enum address_mode amode = c_mode;
d0313fb7 130static enum cpu_version cpu = VNONE;
39bec121 131
d0313fb7 132/* Include string substitutions in listing? */
39bec121 133static int listing_sslist = 0;
d0313fb7 134/* Did we do subsym substitutions on the line? */
39bec121 135static int substitution_line = 0;
d0313fb7 136/* Last label seen. */
39bec121 137static symbolS *last_label_seen = NULL;
d0313fb7 138/* This ensures that all new labels are unique. */
39bec121
TW
139static int local_label_id;
140
141static struct hash_control *subsym_recurse_hash; /* prevent infinite recurse */
142static struct hash_control *math_hash; /* built-in math functions */
d0313fb7
NC
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! */
39bec121 145static struct hash_control *subsym_hash[100];
d0313fb7 146/* Keep track of local labels so we can substitute them before GAS sees them
39bec121
TW
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
d0313fb7 153 other things (like conditionals and repeat loops). */
39bec121
TW
154static int macro_level = 0;
155static struct hash_control *local_label_hash[100];
d0313fb7 156/* Keep track of struct/union tags. */
39bec121
TW
157static struct hash_control *stag_hash;
158static struct hash_control *op_hash;
159static struct hash_control *parop_hash;
160static struct hash_control *reg_hash;
161static struct hash_control *mmreg_hash;
162static struct hash_control *cc_hash;
163static struct hash_control *cc2_hash;
164static struct hash_control *cc3_hash;
165static struct hash_control *sbit_hash;
166static struct hash_control *misc_symbol_hash;
167
168static char *subsym_substitute PARAMS ((char *line, int forced));
169static char *subsym_lookup PARAMS ((char *name, int nest_level));
170static void subsym_create_or_replace PARAMS ((char *name, char *value));
171static float math_ceil PARAMS ((float, float));
172static float math_cvi PARAMS ((float, float));
173static float math_floor PARAMS ((float, float));
174static float math_fmod PARAMS ((float, float));
175static float math_int PARAMS ((float, float));
176static float math_round PARAMS ((float, float));
177static float math_sgn PARAMS ((float, float));
178static float math_trunc PARAMS ((float, float));
179static float math_acos PARAMS ((float, float));
180static float math_asin PARAMS ((float, float));
181static float math_atan PARAMS ((float, float));
182static float math_atan2 PARAMS ((float, float));
183static float math_cosh PARAMS ((float, float));
184static float math_cos PARAMS ((float, float));
185static float math_cvf PARAMS ((float, float));
186static float math_exp PARAMS ((float, float));
187static float math_fabs PARAMS ((float, float));
188static float math_ldexp PARAMS ((float, float));
189static float math_log10 PARAMS ((float, float));
190static float math_log PARAMS ((float, float));
191static float math_max PARAMS ((float, float));
192static float math_pow PARAMS ((float, float));
193static float math_sin PARAMS ((float, float));
194static float math_sinh PARAMS ((float, float));
195static float math_sqrt PARAMS ((float, float));
196static float math_tan PARAMS ((float, float));
197static float math_tanh PARAMS ((float, float));
198
d0313fb7
NC
199static struct stag
200{
39bec121
TW
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;
d0313fb7
NC
206 struct stag_field /* list of fields */
207 {
39bec121
TW
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
219static segT stag_saved_seg;
220static subsegT stag_saved_subseg;
221
d0313fb7
NC
222/* Output a single character (upper octect is zero). */
223static void
224tic54x_emit_char (c)
225 char c;
39bec121
TW
226{
227 expressionS exp;
228
229 exp.X_op = O_constant;
230 exp.X_add_number = c;
231 emit_expr (&exp, 2);
232}
233
d0313fb7 234/* Walk backwards in the frag chain. */
39bec121
TW
235static fragS *
236frag_prev (frag, seg)
d0313fb7
NC
237 fragS *frag;
238 segT seg;
39bec121
TW
239{
240 segment_info_type *seginfo = seg_info (seg);
241 fragS *fragp;
242
d0313fb7 243 for (fragp = seginfo->frchainP->frch_root; fragp; fragp = fragp->fr_next)
39bec121
TW
244 if (fragp->fr_next == frag)
245 return fragp;
d0313fb7 246
39bec121
TW
247 return NULL;
248}
249
250static fragS *
251bit_offset_frag (frag, seg)
d0313fb7
NC
252 fragS *frag;
253 segT seg;
39bec121
TW
254{
255 while (frag != NULL)
256 {
d0313fb7
NC
257 if (frag->fr_fix == 0
258 && frag->fr_opcode == NULL
259 && frag->tc_frag_data == 0)
260 frag = frag_prev (frag, seg);
39bec121 261 else
d0313fb7 262 return frag;
39bec121
TW
263 }
264 return NULL;
265}
266
d0313fb7
NC
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. */
39bec121
TW
269static int
270frag_bit_offset (frag, seg)
d0313fb7
NC
271 fragS *frag;
272 segT seg;
39bec121
TW
273{
274 frag = bit_offset_frag (frag, seg);
d0313fb7 275
39bec121 276 if (frag)
d0313fb7
NC
277 return frag->fr_opcode != NULL ? -1 : frag->tc_frag_data;
278
39bec121
TW
279 return 0;
280}
281
d0313fb7
NC
282/* Read an expression from a C string; returns a pointer past the end of the
283 expression. */
39bec121
TW
284static char *
285parse_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
d0313fb7
NC
302 unsupported. */
303static void
39bec121 304tic54x_asg (x)
d0313fb7 305 int x ATTRIBUTE_UNUSED;
39bec121
TW
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) != ',')
d0313fb7
NC
325 {
326 if (is_end_of_line[(int) *input_line_pointer])
327 break;
328 ++input_line_pointer;
329 }
39bec121
TW
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
d0313fb7
NC
363 table, since that's what works best. */
364static void
39bec121 365tic54x_eval (x)
d0313fb7 366 int x ATTRIBUTE_UNUSED;
39bec121
TW
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 != '"')
d0313fb7
NC
386 {
387 as_bad (_("Unterminated string after absolute expression"));
388 ignore_rest_of_line ();
389 return;
390 }
39bec121
TW
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. */
d0313fb7 401 tmp = xmalloc (strlen (name) + 1);
39bec121
TW
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
d0313fb7 418 to match their behavior. */
39bec121
TW
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.
d0313fb7
NC
439 (not yet implemented). */
440static void
39bec121 441tic54x_bss (x)
d0313fb7 442 int x ATTRIBUTE_UNUSED;
39bec121
TW
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
d0313fb7
NC
456 current_seg = now_seg; /* Save current seg. */
457 current_subseg = now_subseg; /* Save current subseg. */
39bec121
TW
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 != ',')
d0313fb7 482 block = get_absolute_expression ();
39bec121 483 else
d0313fb7 484 block = 0;
39bec121
TW
485
486 if (*input_line_pointer == ',')
d0313fb7
NC
487 {
488 ++input_line_pointer;
489 align = get_absolute_expression ();
490 }
39bec121 491 else
d0313fb7 492 align = 0;
39bec121
TW
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,
d0313fb7 505 (offsetT) (words << 1), (char *) 0);
39bec121
TW
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
530static void
d0313fb7
NC
531stag_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;
39bec121
TW
537{
538 char prefix[strlen (path) + 2];
539 struct stag_field *field = stag->field;
540
d0313fb7
NC
541 /* Construct a symbol for every field contained within this structure
542 including fields within structure fields. */
39bec121
TW
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
d0313fb7
NC
574 /* Recurse if the field is a structure.
575 Note the field offset is relative to the outermost struct. */
39bec121
TW
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
d0313fb7
NC
584/* Keep track of stag fields so that when structures are nested we can add the
585 complete dereferencing symbols to the symbol table. */
39bec121 586static void
d0313fb7
NC
587stag_add_field (parent, name, offset, stag)
588 struct stag *parent;
589 const char *name;
590 bfd_vma offset;
591 struct stag *stag;
39bec121
TW
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 }
d0313fb7 608 /* Only create a symbol for this field if the parent has no name. */
39bec121
TW
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]
d0313fb7 619 start defining structure offsets (symbols in absolute section). */
39bec121
TW
620static void
621tic54x_struct (int arg)
622{
623 int start_offset = 0;
624 int is_union = arg;
625
626 if (!current_stag)
627 {
d0313fb7 628 /* Starting a new struct, switch to absolute section. */
39bec121
TW
629 stag_saved_seg = now_seg;
630 stag_saved_subseg = now_subseg;
631 subseg_set (absolute_section, 0);
632 }
d0313fb7 633 /* Align the current pointer. */
39bec121
TW
634 else if (current_stag->current_bitfield_offset != 0)
635 {
636 ++abs_section_offset;
637 current_stag->current_bitfield_offset = 0;
638 }
639
d0313fb7 640 /* Offset expression is only meaningful for global .structs. */
39bec121
TW
641 if (!is_union)
642 {
d0313fb7 643 /* Offset is ignored in inner structs. */
39bec121
TW
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 {
d0313fb7 653 /* Nesting, link to outer one. */
39bec121
TW
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);
d0313fb7 689 /* Nested .structs don't go into the symbol table. */
39bec121
TW
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
d0313fb7 698 of the structure. */
39bec121
TW
699static void
700tic54x_endstruct (int is_union)
701{
702 int size;
703 const char *path =
704 !strncmp (current_stag->name, ".fake", 5) ? "" : current_stag->name;
d0313fb7 705
39bec121
TW
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
d0313fb7 715 /* Align end of structures. */
39bec121
TW
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
d0313fb7 733 /* Union size has already been calculated. */
39bec121
TW
734 if (!current_stag->is_union)
735 current_stag->size = size;
d0313fb7 736 /* Nested .structs don't get put in the stag table. */
39bec121
TW
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
d0313fb7
NC
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. */
39bec121
TW
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
d0313fb7 762 format on the existing allocated space. */
39bec121
TW
763static void
764tic54x_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
d0313fb7 808 /* Bump by the struct size, but only if we're within a .struct section. */
39bec121
TW
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
d0313fb7 817/* Handle all .byte, .char, .double, .field, .float, .half, .int, .long,
39bec121 818 .short, .string, .ubyte, .uchar, .uhalf, .uint, .ulong, .ushort, .uword,
d0313fb7 819 and .word. */
39bec121
TW
820static void
821tic54x_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 {
d0313fb7 866 /* Set the appropriate size and new field offset. */
39bec121
TW
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 {
d0313fb7 895 /* Align to the actual starting position of the field. */
39bec121
TW
896 current_stag->current_bitfield_offset = 0;
897 ++abs_section_offset;
898 }
d0313fb7 899 /* Align to longword boundary. */
39bec121
TW
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 {
d0313fb7 923 /* Note we treat the element as if it were an array of COUNT. */
39bec121
TW
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
d0313fb7 935/* Handle .byte, .word. .int, .long and all variants. */
39bec121
TW
936int emitting_long = 0;
937static void
938tic54x_cons (int type)
939{
940 register unsigned int c;
941 int octets;
942
d0313fb7 943 /* If we're within a .struct construct, don't actually allocate space. */
39bec121
TW
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
d0313fb7 956 /* Align long words to long word boundaries (4 octets). */
39bec121
TW
957 if (type == 'l' || type == 'L')
958 {
959 frag_align (2, 0, 2);
d0313fb7 960 /* If there's a label, assign it to the first allocated word. */
39bec121
TW
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;
d0313fb7 1003 /* Truncate overflows. */
39bec121
TW
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
d0313fb7 1035 totally ignored in the latest tools). */
39bec121
TW
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
d0313fb7 1073 these, so we ignore the type here. */
39bec121
TW
1074void
1075tic54x_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
d0313fb7 1107/* Remove the symbol from the local label hash lookup. */
39bec121
TW
1108static void
1109tic54x_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
d0313fb7 1117/* Reset all local labels. */
39bec121
TW
1118static void
1119tic54x_clear_local_labels (ignored)
1120 int ignored ATTRIBUTE_UNUSED;
1121{
1122 hash_traverse (local_label_hash[macro_level], tic54x_remove_local_label);
1123}
1124
d0313fb7 1125/* .text
39bec121
TW
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
d0313fb7 1134 For compatibility, '*' sections have SEC_DATA set instead of SEC_CODE. */
39bec121
TW
1135static void
1136tic54x_sect (int arg)
1137{
1138 ILLEGAL_WITHIN_STRUCT ();
1139
d0313fb7 1140 /* Local labels are cleared when changing sections. */
39bec121
TW
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;
d0313fb7 1151 /* If there are quotes, remove them. */
39bec121
TW
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 }
d0313fb7 1167 /* Make sure all named initialized sections are SEC_DATA. */
39bec121
TW
1168 strcat (name, ",\"w\"\n");
1169 input_scrub_insert_line (name);
1170 obj_coff_section (0);
1171
d0313fb7 1172 /* If there was a line label, make sure that it gets assigned the proper
39bec121
TW
1173 section. This is for compatibility, even though the actual behavior
1174 is not explicitly defined. For consistency, we make .sect behave
d0313fb7 1175 like .usect, since that is probably what people expect. */
39bec121
TW
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
d0313fb7 1191 cribbed from s_space. */
39bec121
TW
1192static void
1193tic54x_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
d0313fb7 1210 /* Read the bit count. */
39bec121
TW
1211 expression (&exp);
1212
d0313fb7 1213 /* Some expressions are unresolvable until later in the assembly pass;
39bec121 1214 postpone until relaxation/fixup. we also have to postpone if a previous
d0313fb7 1215 partial allocation has not been completed yet. */
39bec121
TW
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
d0313fb7
NC
1234 /* Reduce the required size by any bit offsets currently left over
1235 from a previous .space/.bes/.field directive. */
39bec121
TW
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 {
d0313fb7
NC
1242 /* Don't have to do anything; sufficient bits have already been
1243 allocated; just point the label to the right place. */
39bec121
TW
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;
d0313fb7
NC
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. */
39bec121
TW
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 }
d0313fb7 1263 /* Convert bits to bytes/words and octets, rounding up. */
39bec121 1264 words = ((exp.X_add_number + bits_per_byte - 1) / bits_per_byte);
d0313fb7 1265 /* How many do we have left over? */
39bec121
TW
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
d0313fb7 1294 /* Make note of how many bits of this word we've allocated so far. */
39bec121
TW
1295 frag_now->tc_frag_data = bit_offset;
1296
d0313fb7 1297 /* .bes puts label at *last* word allocated. */
39bec121
TW
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
d0313fb7 1320 Has no effect on the current section. */
39bec121
TW
1321static void
1322tic54x_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
d0313fb7 1359 /* Read a possibly present third argument (blocking flag). */
39bec121
TW
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
d0313fb7 1368 /* Read a possibly present fourth argument (alignment flag). */
39bec121
TW
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 {
d0313fb7 1385 /* s_align eats end of line; restore it. */
39bec121
TW
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
1418static enum cpu_version
d0313fb7
NC
1419lookup_version (ver)
1420 const char *ver;
39bec121
TW
1421{
1422 enum cpu_version version = VNONE;
d0313fb7 1423
39bec121
TW
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
1440static void
d0313fb7
NC
1441set_cpu (version)
1442 enum cpu_version version;
39bec121
TW
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
d0313fb7 1465 This is for compatibility only. It currently has no affect on assembly. */
39bec121 1466static int cpu_needs_set = 1;
d0313fb7 1467
39bec121
TW
1468static void
1469tic54x_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
d0313fb7 1510/* 'f' = float, 'x' = xfloat, 'd' = double, 'l' = ldouble. */
39bec121
TW
1511static void
1512tic54x_float_cons (int type)
1513{
1514 if (current_stag != 0)
d0313fb7 1515 tic54x_struct_field ('f');
39bec121
TW
1516
1517#ifdef md_flush_pending_output
1518 md_flush_pending_output ();
1519#endif
d0313fb7
NC
1520
1521 /* Align to long word boundary (4 octets) unless it's ".xfloat". */
39bec121
TW
1522 if (type != 'x')
1523 {
1524 frag_align (2, 0, 2);
d0313fb7 1525 /* If there's a label, assign it to the first allocated word. */
39bec121
TW
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
d0313fb7 1539 and encoded into the correct octets. */
39bec121 1540static void
d0313fb7
NC
1541tic54x_stringer (type)
1542 int type;
39bec121
TW
1543{
1544 register unsigned int c;
1545 char *start;
1546 int append_zero = type == 'S' || type == 'P';
1547 int packed = type == 'p' || type == 'P';
d0313fb7 1548 int last_char = -1; /* Packed strings need two bytes at a time to encode. */
39bec121
TW
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 {
d0313fb7 1585 /* Packed strings are filled MS octet first. */
39bec121
TW
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
d0313fb7 1619 /* Finish up any leftover packed string. */
39bec121
TW
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
1628static void
1629tic54x_p2align (arg)
1630 int arg ATTRIBUTE_UNUSED;
1631{
1632 as_bad (_("p2align not supported on this target"));
1633}
1634
1635static void
d0313fb7
NC
1636tic54x_align_words (arg)
1637 int arg;
39bec121 1638{
d0313fb7 1639 /* Only ".align" with no argument is allowed within .struct/.union. */
39bec121
TW
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
d0313fb7 1666/* Initialize multiple-bit fields withing a single word of memory. */
39bec121
TW
1667static void
1668tic54x_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
d0313fb7 1697 /* Truncate values to the field width. */
39bec121
TW
1698 if (exp.X_op != O_constant)
1699 {
d0313fb7 1700 /* If the expression value is relocatable, the field size *must* be 16. */
39bec121
TW
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;
d0313fb7 1719 /* Bits are stored MS first. */
39bec121
TW
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));
d0313fb7
NC
1734 /* We don't know the previous offset at this time, so store the
1735 info we need and figure it out later. */
39bec121
TW
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 {
d0313fb7 1750 /* Align a new field. */
39bec121
TW
1751 p = frag_more (2);
1752 frag_now->tc_frag_data = 0;
1753 alloc_frag = frag_now;
1754 }
1755 else
1756 {
d0313fb7 1757 /* Put the new value entirely within the existing one. */
39bec121
TW
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
d0313fb7 1771 /* OR in existing value. */
39bec121
TW
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
d0313fb7 1785 available yet. seg_info ()->bss is the next best thing. */
39bec121
TW
1786static int
1787tic54x_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.
d0313fb7 1798 Name is required for uninitialized sections. */
39bec121
TW
1799static void
1800tic54x_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
d0313fb7 1842/* Change the default include directory to be the current source file's
39bec121 1843 directory, instead of the current working directory. If DOT is non-zero,
d0313fb7 1844 set to "." instead. */
39bec121
TW
1845static void
1846tic54x_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
d0313fb7 1879/* .include "filename" | filename
39bec121
TW
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
d0313fb7 1888 Entering/exiting included/copied file clears all local labels. */
39bec121
TW
1889static void
1890tic54x_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
d0313fb7 1921 newblock is executed after the included file is processed. */
39bec121
TW
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
1933static void
d0313fb7
NC
1934tic54x_message (type)
1935 int type;
39bec121
TW
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
d0313fb7 1978 run address (vma). */
39bec121
TW
1979static void
1980tic54x_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
d0313fb7
NC
1997/* .mmregs
1998 install all memory-mapped register names into the symbol table as absolute
1999 local symbols. */
39bec121
TW
2000static void
2001tic54x_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
d0313fb7
NC
2017/* .loop [count]
2018 count defaults to 1024. */
39bec121
TW
2019static void
2020tic54x_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
d0313fb7 2031/* Normally, endloop gets eaten by the preceding loop. */
39bec121
TW
2032static void
2033tic54x_endloop (ignore)
2034 int ignore ATTRIBUTE_UNUSED;
2035{
2036 as_bad (_("ENDLOOP without corresponding LOOP"));
2037 ignore_rest_of_line ();
2038}
2039
d0313fb7 2040/* .break [condition]. */
39bec121
TW
2041static void
2042tic54x_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
2060static void
2061set_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
2074static int address_mode_needs_set = 1;
2075static void
2076tic54x_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]
d0313fb7 2097 designate initialized sections for blocking. */
39bec121
TW
2098static void
2099tic54x_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
d0313fb7 2152 symbols assigned with .set/.equ may not be redefined. */
39bec121
TW
2153static void
2154tic54x_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
d0313fb7 2186 list false conditional blocks. */
39bec121
TW
2187static void
2188tic54x_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
2197static void
2198tic54x_sslist (int show)
2199{
2200 ILLEGAL_WITHIN_STRUCT ();
2201
2202 listing_sslist = show;
2203}
2204
2205/* .var SYM[,...,SYMN]
d0313fb7 2206 define a substitution string to be local to a macro. */
39bec121
TW
2207static void
2208tic54x_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
d0313fb7 2254 FIXME need to try the source file directory as well. */
39bec121
TW
2255static void
2256tic54x_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
d0313fb7 2310 running for a very long time, it really doesn't matter... */
39bec121
TW
2311 register_dependency (path);
2312
d0313fb7 2313 /* Expand all archive entries to temporary files and include them. */
39bec121
TW
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
d0313fb7 2329 /* Open each BFD as binary (it should be straight ASCII text). */
39bec121
TW
2330 for (mbfd = bfd_openr_next_archived_file (abfd, NULL);
2331 mbfd != NULL; mbfd = bfd_openr_next_archived_file (abfd, mbfd))
2332 {
d0313fb7 2333 /* Get a size at least as big as the archive member. */
39bec121
TW
2334 bfd_size_type size = bfd_get_size (mbfd);
2335 char *buf = xmalloc (size);
2336 char *fname = tmpnam (NULL);
2337 FILE *ftmp;
2338
d0313fb7 2339 /* We're not sure how big it is, but it will be smaller than "size". */
39bec121
TW
2340 bfd_read (buf, size, 1, mbfd);
2341
d0313fb7
NC
2342 /* Write to a temporary file, then use s_include to include it
2343 a bit of a hack... */
39bec121
TW
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
2355const 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
39bec121 2444#if 0
d0313fb7 2445/* For debugging, strings for each operand type. */
39bec121
TW
2446static 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
2459int
2460md_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
d0313fb7 2504/* Create a "local" substitution string hash table for a new macro level
39bec121
TW
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
d0313fb7 2507 deleting the local label hash between macro invocations. */
39bec121
TW
2508void
2509tic54x_macro_start ()
2510{
2511 ++macro_level;
2512 subsym_hash[macro_level] = hash_new ();
2513 local_label_hash[macro_level] = hash_new ();
2514}
2515
2516void
d0313fb7
NC
2517tic54x_macro_info (info)
2518 void *info;
39bec121
TW
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
d0313fb7 2538 /* Put the formal args into the substitution symbol table. */
39bec121
TW
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
d0313fb7 2551/* Get rid of this macro's .var's, arguments, and local labels. */
39bec121
TW
2552void
2553tic54x_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
2562static int
2563subsym_symlen (a, ignore)
2564 char *a;
2565 char *ignore ATTRIBUTE_UNUSED;
2566{
2567 return strlen (a);
2568}
2569
d0313fb7 2570/* Compare symbol A to string B. */
39bec121 2571static int
d0313fb7
NC
2572subsym_symcmp (a, b)
2573 char *a;
2574 char *b;
39bec121
TW
2575{
2576 return strcmp (a, b);
2577}
2578
d0313fb7
NC
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. */
39bec121 2581static int
d0313fb7
NC
2582subsym_firstch (a, b)
2583 char *a;
2584 char *b;
39bec121
TW
2585{
2586 int val = atoi (b);
2587 char *tmp = strchr (a, val);
2588
2589 return tmp ? tmp - a + 1 : 0;
2590}
2591
d0313fb7 2592/* Similar to firstch, but returns index of last occurrence of B in A. */
39bec121
TW
2593static int
2594subsym_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
d0313fb7
NC
2604/* Returns 1 if string A is defined in the symbol table (NOT the substitution
2605 symbol table). */
39bec121
TW
2606static int
2607subsym_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
d0313fb7 2616/* Assign first member of comma-separated list B (e.g. "1,2,3") to the symbol
39bec121 2617 A, or zero if B is a null string. Both arguments *must* be substitution
d0313fb7 2618 symbols, unsubstituted. */
39bec121 2619static int
d0313fb7
NC
2620subsym_ismember (sym, list)
2621 char *sym;
2622 char *list;
39bec121
TW
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
d0313fb7 2643 subsym_create_or_replace (sym, elem);
39bec121 2644
d0313fb7 2645 /* Reassign the list. */
39bec121
TW
2646 subsym_create_or_replace (list, ptr);
2647
d0313fb7 2648 /* Assume this value, docs aren't clear. */
39bec121
TW
2649 return *list != 0;
2650}
2651
d0313fb7 2652/* Return zero if not a constant; otherwise:
39bec121
TW
2653 1 if binary
2654 2 if octal
2655 3 if hexadecimal
2656 4 if character
d0313fb7 2657 5 if decimal. */
39bec121
TW
2658static int
2659subsym_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 }
d0313fb7 2684 /* No suffix; either octal, hex, or decimal. */
39bec121
TW
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
d0313fb7 2697/* Return 1 if A is a valid symbol name. Expects string input. */
39bec121
TW
2698static int
2699subsym_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
d0313fb7 2714/* Return whether the string is a register; accepts ar0-7, unless .mmregs has
39bec121 2715 been seen; if so, recognize any memory-mapped register.
d0313fb7 2716 Note this does not recognize "A" or "B" accumulators. */
39bec121
TW
2717static int
2718subsym_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
d0313fb7 2729/* Return the structrure size, given the stag. */
39bec121
TW
2730static int
2731subsym_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
d0313fb7 2747 return zero, we punt and return zero. */
39bec121
TW
2748static int
2749subsym_structacc (stag_name, ignore)
2750 char *stag_name ATTRIBUTE_UNUSED;
2751 char *ignore ATTRIBUTE_UNUSED;
2752{
2753 return 0;
2754}
2755
2756static float
2757math_ceil (arg1, ignore)
2758 float arg1;
2759 float ignore ATTRIBUTE_UNUSED;
2760{
2761 return (float)ceil (arg1);
2762}
d0313fb7 2763
39bec121
TW
2764static float
2765math_cvi (arg1, ignore)
2766 float arg1;
2767 float ignore ATTRIBUTE_UNUSED;
2768{
2769 return (int)arg1;
2770}
d0313fb7 2771
39bec121
TW
2772static float
2773math_floor (arg1, ignore)
2774 float arg1;
2775 float ignore ATTRIBUTE_UNUSED;
2776{
2777 return (float)floor (arg1);
2778}
d0313fb7 2779
39bec121
TW
2780static float
2781math_fmod (float arg1, float arg2)
2782{
2783 return (int)arg1 % (int)arg2;
2784}
d0313fb7 2785
39bec121
TW
2786static float
2787math_int (arg1, ignore)
2788 float arg1;
2789 float ignore ATTRIBUTE_UNUSED;
2790{
2791 return ((float)((int)arg1)) == arg1;
2792}
d0313fb7 2793
39bec121
TW
2794static float
2795math_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}
d0313fb7 2801
39bec121
TW
2802static float
2803math_sgn (arg1, ignore)
2804 float arg1;
2805 float ignore ATTRIBUTE_UNUSED;
2806{
2807 return (arg1 < 0) ? -1 : (arg1 ? 1 : 0);
2808}
d0313fb7 2809
39bec121
TW
2810static float
2811math_trunc (arg1, ignore)
2812 float arg1;
2813 float ignore ATTRIBUTE_UNUSED;
2814{
2815 return (int)arg1;
2816}
2817
2818static float
2819math_acos (arg1, ignore)
2820 float arg1;
2821 float ignore ATTRIBUTE_UNUSED;
2822{
2823 return (float)acos (arg1);
2824}
d0313fb7 2825
39bec121
TW
2826static float
2827math_asin (arg1, ignore)
2828 float arg1;
2829 float ignore ATTRIBUTE_UNUSED;
2830{
2831 return (float)asin (arg1);
2832}
d0313fb7 2833
39bec121
TW
2834static float
2835math_atan (arg1, ignore)
2836 float arg1;
2837 float ignore ATTRIBUTE_UNUSED;
2838{
2839 return (float)atan (arg1);
2840}
d0313fb7 2841
39bec121
TW
2842static float
2843math_atan2(float arg1, float arg2)
2844{
2845 return (float)atan2 (arg1, arg2);
2846}
d0313fb7 2847
39bec121
TW
2848static float
2849math_cosh (arg1, ignore)
2850 float arg1;
2851 float ignore ATTRIBUTE_UNUSED;
2852{
2853 return (float)cosh (arg1);
2854}
d0313fb7 2855
39bec121
TW
2856static float
2857math_cos (arg1, ignore)
2858 float arg1;
2859 float ignore ATTRIBUTE_UNUSED;
2860{
2861 return (float)cos (arg1);
2862}
d0313fb7 2863
39bec121
TW
2864static float
2865math_cvf (arg1, ignore)
2866 float arg1;
2867 float ignore ATTRIBUTE_UNUSED;
2868{
2869 return (float)arg1;
2870}
d0313fb7 2871
39bec121
TW
2872static float
2873math_exp (arg1, ignore)
2874 float arg1;
2875 float ignore ATTRIBUTE_UNUSED;
2876{
2877 return (float)exp (arg1);
2878}
d0313fb7 2879
39bec121
TW
2880static float
2881math_fabs (arg1, ignore)
2882 float arg1;
2883 float ignore ATTRIBUTE_UNUSED;
2884{
2885 return (float)fabs (arg1);
2886}
d0313fb7
NC
2887
2888/* expr1 * 2^expr2. */
39bec121
TW
2889static float
2890math_ldexp (float arg1, float arg2)
2891{
2892 return arg1 * (float)pow (2.0, arg2);
2893}
d0313fb7 2894
39bec121
TW
2895static float
2896math_log10 (arg1, ignore)
2897 float arg1;
2898 float ignore ATTRIBUTE_UNUSED;
2899{
2900 return (float)log10 (arg1);
2901}
d0313fb7 2902
39bec121
TW
2903static float
2904math_log (arg1, ignore)
2905 float arg1;
2906 float ignore ATTRIBUTE_UNUSED;
2907{
2908 return (float)log (arg1);
2909}
d0313fb7 2910
39bec121
TW
2911static float
2912math_max (float arg1, float arg2)
2913{
2914 return (arg1 > arg2) ? arg1 : arg2;
2915}
d0313fb7 2916
39bec121
TW
2917static float
2918math_min (float arg1, float arg2)
2919{
2920 return (arg1 < arg2) ? arg1 : arg2;
2921}
d0313fb7 2922
39bec121
TW
2923static float
2924math_pow (float arg1, float arg2)
2925{
2926 return (float)pow (arg1, arg2);
2927}
d0313fb7 2928
39bec121
TW
2929static float
2930math_sin (arg1, ignore)
2931 float arg1;
2932 float ignore ATTRIBUTE_UNUSED;
2933{
2934 return (float)sin (arg1);
2935}
d0313fb7 2936
39bec121
TW
2937static float
2938math_sinh (arg1, ignore)
2939 float arg1;
2940 float ignore ATTRIBUTE_UNUSED;
2941{
2942 return (float)sinh (arg1);
2943}
d0313fb7 2944
39bec121
TW
2945static float
2946math_sqrt (arg1, ignore)
2947 float arg1;
2948 float ignore ATTRIBUTE_UNUSED;
2949{
2950 return (float)sqrt (arg1);
2951}
d0313fb7 2952
39bec121
TW
2953static float
2954math_tan (arg1, ignore)
2955 float arg1;
2956 float ignore ATTRIBUTE_UNUSED;
2957{
2958 return (float)tan (arg1);
2959}
d0313fb7 2960
39bec121
TW
2961static float
2962math_tanh (arg1, ignore)
2963 float arg1;
2964 float ignore ATTRIBUTE_UNUSED;
2965{
2966 return (float)tanh (arg1);
2967}
2968
d0313fb7 2969/* Built-in substitution symbol functions and math functions. */
39bec121
TW
2970typedef struct
2971{
2972 char *name;
2973 int (*proc)(char *, char *);
2974 int nargs;
2975} subsym_proc_entry;
2976
d0313fb7
NC
2977static const subsym_proc_entry subsym_procs[] =
2978{
2979 /* Assembler built-in string substitution functions. */
39bec121
TW
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
2994typedef struct
2995{
2996 char *name;
2997 float (*proc)(float, float);
2998 int nargs;
2999 int int_return;
3000} math_proc_entry;
3001
d0313fb7
NC
3002static const math_proc_entry math_procs[] =
3003{
3004 /* Integer-returning built-in math functions. */
39bec121
TW
3005 { "$cvi", math_cvi, 1, 1 },
3006 { "$int", math_int, 1, 1 },
3007 { "$sgn", math_sgn, 1, 1 },
3008
d0313fb7 3009 /* Float-returning built-in math functions. */
39bec121
TW
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
3038void
3039md_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
d0313fb7 3053 /* Look for A_DIR and add it to the include list. a */
39bec121
TW
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 {
d0313fb7 3089 /* Add basic registers to the symbol table. */
39bec121
TW
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 }
d0313fb7
NC
3128 /* Only the base substitution table and local label table are initialized;
3129 the others (for local macro substitution) get instantiated as needed. */
39bec121
TW
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 {
d0313fb7
NC
3140 /* Insert into the main subsym hash for recognition; insert into
3141 the math hash to actually store information. */
39bec121
TW
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
d0313fb7
NC
3151typedef struct _tic54x_insn
3152{
39bec121
TW
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;
d0313fb7
NC
3160 struct opstruct
3161 {
39bec121
TW
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? */
d0313fb7
NC
3175 struct
3176 {
39bec121
TW
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
3185static int encode_operand (tic54x_insn *, enum optype, struct opstruct *);
3186static int encode_dmad (tic54x_insn *, struct opstruct *, int);
3187static int operands_match (tic54x_insn *, struct opstruct *, int,
3188 const enum optype *, int, int);
3189static int encode_address (tic54x_insn *, struct opstruct *);
3190
3191static int
d0313fb7
NC
3192is_accumulator (operand)
3193 struct opstruct *operand;
39bec121
TW
3194{
3195 return strcasecmp (operand->buf, "a") == 0
3196 || strcasecmp (operand->buf, "b") == 0;
3197}
3198
d0313fb7
NC
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. */
39bec121
TW
3201static int
3202get_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;
d0313fb7 3242 /* Trim trailing spaces; while the preprocessor gets rid of most,
39bec121 3243 there are weird usage patterns that can introduce them
d0313fb7 3244 (i.e. using strings for macro args). */
39bec121
TW
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
d0313fb7 3277 /* OK, now parse them into expressions. */
39bec121
TW
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, '(');
d0313fb7 3295 /* Allow immediate syntax in the inner expression. */
39bec121
TW
3296 if (paren && paren[1] == '#')
3297 *++paren = '(';
3298
d0313fb7 3299 /* Pull out the lk expression or SP offset, if present. */
39bec121
TW
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
d0313fb7 3328/* Predicates for different operand types. */
39bec121 3329static int
d0313fb7
NC
3330is_immediate (operand)
3331 struct opstruct *operand;
39bec121
TW
3332{
3333 return *operand->buf == '#';
3334}
3335
3336/* This is distinguished from immediate because some numbers must be constants
d0313fb7 3337 and must *not* have the '#' prefix. */
39bec121 3338static int
d0313fb7
NC
3339is_absolute (operand)
3340 struct opstruct *operand;
39bec121
TW
3341{
3342 return operand->exp.X_op == O_constant && !is_immediate (operand);
3343}
3344
d0313fb7 3345/* Is this an indirect operand? */
39bec121 3346static int
d0313fb7
NC
3347is_indirect (operand)
3348 struct opstruct *operand;
39bec121
TW
3349{
3350 return operand->buf[0] == '*';
3351}
3352
d0313fb7 3353/* Is this a valid dual-memory operand? */
39bec121 3354static int
d0313fb7
NC
3355is_dual (operand)
3356 struct opstruct *operand;
39bec121
TW
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;
d0313fb7 3363
39bec121 3364 arf = *tmp++ - '0';
d0313fb7 3365 /* Only allow *ARx, *ARx-, *ARx+, or *ARx+0%. */
39bec121
TW
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
3375static int
d0313fb7
NC
3376is_mmreg (operand)
3377 struct opstruct *operand;
39bec121
TW
3378{
3379 return is_absolute (operand) || is_immediate (operand)
3380 || hash_find (mmreg_hash, operand->buf) != 0;
3381}
3382
3383static int
3384is_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:
d0313fb7 3398 /* This one *must* be immediate. */
39bec121
TW
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:
d0313fb7 3408 /* Address may be a numeric, indirect, or an expression. */
39bec121
TW
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:
d0313fb7 3438 /* Allow st0 or st1 instead of a numeric. */
39bec121
TW
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:
d0313fb7 3449 /* Let this one catch out-of-range values. */
39bec121
TW
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:
d0313fb7
NC
3463 /* Allow anything; assumes opcodes are ordered with Smem operands
3464 versions first. */
39bec121
TW
3465 return 1;
3466 case OP_k5:
3467 case OP_k3:
3468 case OP_k9:
d0313fb7 3469 /* Just make sure it's an integer; check range later. */
39bec121
TW
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
3489static int
3490operands_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 {
d0313fb7
NC
3508 /* Skip an optional template operand if it doesn't agree
3509 with the current operand. */
39bec121
TW
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
d0313fb7 3521 /* Save the actual operand type for later use. */
39bec121
TW
3522 operands[op].type = OPTYPE (refoptype[refop]);
3523 ++refop;
3524 ++op;
d0313fb7 3525 /* Have we matched them all yet? */
39bec121
TW
3526 if (op == opcount)
3527 {
3528 while (op < maxops)
3529 {
d0313fb7 3530 /* If a later operand is *not* optional, no match. */
39bec121
TW
3531 if ((refoptype[refop] & OPT) == 0)
3532 return 0;
d0313fb7
NC
3533 /* Flag any implicit default OP_DST operands so we know to add
3534 them explicitly when encoding the operand later. */
39bec121
TW
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
d0313fb7 3557 2 for the upper 7 bits of a 23-bit address (LDX). */
39bec121
TW
3558static int
3559encode_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
d0313fb7 3566 /* Only allow *(dmad) expressions; all others are invalid. */
39bec121
TW
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 {
d0313fb7 3591 /* Do the fixup later; just store the expression. */
39bec121
TW
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 {
d0313fb7 3599 /* This relocation spans two words, so adjust accordingly. */
39bec121
TW
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;
d0313fb7
NC
3604 /* It's really 2 words, but we want to stop encoding after the
3605 first, since we must encode both words at once. */
39bec121
TW
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
d0313fb7 3620/* 7-bit direct address encoding. */
39bec121
TW
3621static int
3622encode_address (insn, operand)
3623 tic54x_insn *insn;
3624 struct opstruct *operand;
3625{
d0313fb7 3626 /* Assumes that dma addresses are *always* in word 0 of the opcode. */
39bec121
TW
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 {
d0313fb7 3633 /* Do the fixup later; just store the expression. */
39bec121
TW
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
3642static int
3643encode_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 {
d0313fb7 3652 /* lk addresses always go in the second insn word. */
39bec121
TW
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 {
d0313fb7 3673 /* Stack offsets look the same as 7-bit direct addressing. */
39bec121
TW
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
3716static int
3717encode_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;
d0313fb7
NC
3730 /* Hack -- fixup for 16-bit hex quantities that get converted positive
3731 instead of negative. */
39bec121
TW
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 {
d0313fb7 3754 /* Do the fixup later; just store the expression. */
39bec121
TW
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
3775static int
3776encode_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
d0313fb7 3793 /* Disallow group 1 conditions mixed with group 2 conditions
39bec121 3794 if group 1, allow only one category A and one category B
d0313fb7 3795 if group 2, allow only one each of category A, B, and C. */
39bec121
TW
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
3837static int
3838encode_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
3854static int
3855encode_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
3869static int
3870encode_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
3884static int
3885encode_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 {
d0313fb7 3894 /* Disallow long-constant addressing for memory-mapped addressing. */
39bec121
TW
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;
d0313fb7 3902 /* Warn about *+ARx when used with MMR operands. */
39bec121
TW
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:
d0313fb7 3916 /* 16-bit immediate value. */
39bec121
TW
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:
d0313fb7 3927 /* Make sure this agrees with with the OP_DST operand. */
39bec121
TW
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 }
d0313fb7
NC
4045 /* Guess the register based on the status bit; "ovb" is the last
4046 status bit defined for st0. */
39bec121
TW
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:
d0313fb7 4098 /* No encoding necessary. */
39bec121
TW
4099 return 1;
4100 default:
4101 return 0;
4102 }
4103
4104 return 1;
4105}
4106
4107static void
4108emit_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
d0313fb7
NC
4130/* Convert the operand strings into appropriate opcode values
4131 return the total number of words used by the instruction. */
39bec121
TW
4132static int
4133build_insn (insn)
4134 tic54x_insn *insn;
4135{
4136 int i;
4137
d0313fb7 4138 /* Only non-parallel instructions support lk addressing. */
39bec121
TW
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, '(') &&
d0313fb7 4147 /* Don't mistake stack-relative addressing for lk addressing. */
39bec121
TW
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
4181static int
4182optimize_insn (insn)
4183 tic54x_insn *insn;
4184{
d0313fb7 4185 /* Optimize some instructions, helping out the brain-dead programmer. */
39bec121
TW
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
d0313fb7 4200 /* Try to collapse if Xmem and shift count is zero. */
39bec121
TW
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])) ||
d0313fb7 4204 /* Or if Smem, shift is zero or absent, and SRC == DST. */
39bec121
TW
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
d0313fb7 4273/* Find a matching template if possible, and get the operand strings. */
39bec121
TW
4274static int
4275tic54x_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
d0313fb7 4290 /* Check each variation of operands for this mnemonic. */
39bec121
TW
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 {
d0313fb7 4299 /* SUCCESS! now try some optimizations. */
39bec121
TW
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
d0313fb7
NC
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. */
39bec121
TW
4318static int parallel_on_next_line_hint = 0;
4319/* See if this is part of a parallel instruction
d0313fb7 4320 Look for a subsequent line starting with "||". */
39bec121
TW
4321static int
4322next_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
4333static int
4334tic54x_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 }
d0313fb7 4360 /* Didn't find a matching parallel; try for a normal insn. */
39bec121
TW
4361 return 0;
4362}
4363
d0313fb7 4364/* Parse the second line of a two-line parallel instruction. */
39bec121
TW
4365static int
4366tic54x_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
d0313fb7 4401/* If quotes found, return copy of line up to closing quote;
39bec121
TW
4402 otherwise up until terminator
4403 if it's a string, pass as-is; otherwise attempt substitution symbol
d0313fb7 4404 replacement on the value. */
39bec121
TW
4405static char *
4406subsym_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
d0313fb7 4431 /* Do forced substitutions if requested. */
39bec121
TW
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;
d0313fb7 4454 /* Do simple substitution, if available. */
39bec121
TW
4455 if (!nosub && (value = subsym_lookup (*str, macro_level)) != NULL)
4456 *str = value;
4457 }
4458
4459 return endp;
4460}
4461
d0313fb7 4462/* Replace the given substitution string.
39bec121
TW
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
d0313fb7 4465 that's compatible w/TI's assembler. */
39bec121 4466static void
d0313fb7
NC
4467subsym_create_or_replace (name, value)
4468 char *name;
4469 char *value;
39bec121
TW
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
d0313fb7
NC
4487/* Look up the substitution string replacement for the given symbol
4488 start with the innermost macro substituion table given and work outwards. */
39bec121 4489static char *
d0313fb7
NC
4490subsym_lookup (name, nest_level)
4491 char *name;
4492 int nest_level;
39bec121
TW
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
d0313fb7 4502/* Do substitution-symbol replacement on the given line (recursively).
39bec121
TW
4503 return the argument if no substitution was done
4504
4505 Also look for built-in functions ($func (arg)) and local labels.
4506
d0313fb7 4507 If FORCED is set, look for forced substitutions of the form ':SYMBOL:'. */
39bec121
TW
4508static char *
4509subsym_substitute (char *line, int forced)
4510{
d0313fb7
NC
4511 /* For each apparent symbol, see if it's a substitution symbol, and if so,
4512 replace it in the input. */
39bec121
TW
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
d0313fb7 4524 /* Work with a copy of the input line. */
39bec121
TW
4525 replacement = xmalloc (strlen (line) + 1);
4526 strcpy (replacement, line);
4527
4528 ptr = head = replacement;
4529
d0313fb7 4530 /* Flag lines where we might need to replace a single '=' with two;
39bec121 4531 GAS uses single '=' to assign macro args values, and possibly other
d0313fb7 4532 places, so limit what we replace. */
39bec121
TW
4533 if (strstr (line, ".if")
4534 || strstr (line, ".elseif")
4535 || strstr (line, ".break"))
4536 {
4537 line_conditional = 1;
4538 }
4539
d0313fb7
NC
4540 /* Watch out for .eval, so that we avoid doing substitution on the
4541 symbol being assigned a value. */
39bec121
TW
4542 if (strstr (line, ".eval") || strstr (line, ".asg"))
4543 eval_line = 1;
4544
d0313fb7 4545 /* If it's a macro definition, don't do substitution on the argument names. */
39bec121
TW
4546 if (strstr (line, ".macro"))
4547 return line;
4548
4549 while (!is_end_of_line[(int)*ptr])
4550 {
4551 int current_char = *ptr;
4552
d0313fb7 4553 /* Need to update this since LINE may have been modified. */
39bec121
TW
4554 if (eval_line)
4555 eval_end = strrchr (ptr, ',');
4556
d0313fb7 4557 /* Replace triple double quotes with bounding quote/escapes. */
39bec121
TW
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
d0313fb7
NC
4567 /* Replace a single '=' with a '==';
4568 for compatibility with older code only. */
39bec121
TW
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);
d0313fb7 4579 /* Continue examining after the '=='. */
39bec121
TW
4580 ptr = tmp + strlen (head) + 2;
4581 free (replacement);
4582 head = replacement = tmp;
4583 changed = 1;
4584 }
4585
d0313fb7 4586 /* Flag when we've reached the symbol part of .eval/.asg. */
39bec121
TW
4587 if (eval_line && ptr >= eval_end)
4588 eval_symbol = 1;
4589
d0313fb7
NC
4590 /* For each apparent symbol, see if it's a substitution symbol, and if
4591 so, replace it in the input. */
39bec121
TW
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
d0313fb7 4601 /* Skip the colon. */
39bec121
TW
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
d0313fb7 4608 label. */
39bec121
TW
4609 if (c == '?')
4610 {
4611 *input_line_pointer++ = c;
4612 c = *input_line_pointer;
4613 *input_line_pointer = '\0';
4614 }
d0313fb7
NC
4615 /* Avoid infinite recursion; if a symbol shows up a second time for
4616 substitution, leave it as is. */
39bec121
TW
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
d0313fb7
NC
4626 /* Check for local labels; replace them with the appropriate
4627 substitution. */
39bec121
TW
4628 if ((*name == '$' && isdigit (name[1]) && name[2] == '\0')
4629 || name[strlen (name)-1] == '?')
4630 {
d0313fb7
NC
4631 /* Use an existing identifier for that label if, available, or
4632 create a new, unique identifier. */
39bec121
TW
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 }
d0313fb7 4646 /* Indicate where to continue looking for substitutions. */
39bec121
TW
4647 ptr = tail;
4648 }
d0313fb7 4649 /* Check for built-in subsym and math functions. */
39bec121
TW
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 }
d0313fb7 4694 /* Don't bother recursing; the replacement isn't a symbol. */
39bec121
TW
4695 recurse = 0;
4696 }
4697 else
4698 {
4699 int val;
4700 int arg_type[2] = {*ptr == '"',0};
4701 int ismember = !strcmp (entry->name, "$ismember");
d0313fb7
NC
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
39bec121
TW
4705 used, with the following exceptions:
4706 firstch/lastch: 2nd arg must be character constant
d0313fb7 4707 ismember: both args must be substitution symbols. */
39bec121
TW
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 }
d0313fb7
NC
4718 /* Character constants are converted to numerics
4719 by the preprocessor. */
39bec121
TW
4720 arg_type[1] = (isdigit (*ptr)) ? 2 : (*ptr == '"');
4721 ptr = subsym_get_arg (ptr, ")", &arg2, ismember);
4722 }
d0313fb7 4723 /* Args checking. */
39bec121
TW
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 }
d0313fb7
NC
4746 /* Fix things up to replace the entire expression, not just the
4747 function name. */
39bec121
TW
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
d0313fb7 4760 try to replace a symbol once. */
39bec121
TW
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
d0313fb7 4768 /* Temporarily zero-terminate where the symbol started. */
39bec121
TW
4769 *name = 0;
4770 if (forced)
4771 {
4772 if (c == '(')
4773 {
d0313fb7 4774 /* Subscripted substitution symbol -- use just the
39bec121
TW
4775 indicated portion of the string; the description
4776 kinda indicates that forced substituion is not
d0313fb7 4777 supposed to be recursive, but I'm not sure. */
39bec121
TW
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);
d0313fb7 4821 /* Make sure forced substitutions are properly terminated. */
39bec121
TW
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
d0313fb7 4839 complete. */
39bec121
TW
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
d0313fb7 4850 /* Restore the character after the symbol end. */
39bec121
TW
4851 *tail = c;
4852 strcat (tmp, tail);
d0313fb7 4853 /* Continue examining after the replacement value. */
39bec121
TW
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
d0313fb7 4874/* We use this to handle substitution symbols
39bec121
TW
4875 hijack input_line_pointer, replacing it with our substituted string.
4876
4877 .sslist should enable listing the line after replacements are made...
4878
d0313fb7 4879 returns the new buffer limit. */
39bec121
TW
4880void
4881tic54x_start_line_hook ()
4882{
4883 char *line, *endp;
4884 char *replacement = NULL;
4885
d0313fb7 4886 /* Work with a copy of the input line, including EOL char. */
39bec121
TW
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
d0313fb7 4894 /* Scan ahead for parallel insns. */
39bec121
TW
4895 parallel_on_next_line_hint = next_line_shows_parallel (endp + 1);
4896
d0313fb7 4897 /* If within a macro, first process forced replacements. */
39bec121
TW
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
d0313fb7 4910 /* Clean up the replacement; we'd prefer to have this done by the
39bec121 4911 standard preprocessing equipment (maybe do_scrub_chars?)
d0313fb7 4912 but for now, do a quick-and-dirty. */
39bec121
TW
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
d0313fb7 4922 /* Trim trailing whitespace. */
39bec121
TW
4923 while (isspace (*comment))
4924 {
4925 comment[0] = endc;
4926 comment[1] = 0;
4927 --comment;
4928 }
4929
d0313fb7 4930 /* Compact leading whitespace. */
39bec121
TW
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);
d0313fb7 4938 /* Keep track of whether we've done a substitution. */
39bec121
TW
4939 substitution_line = 1;
4940 }
4941 else
4942 {
d0313fb7 4943 /* No change. */
39bec121
TW
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
d0313fb7 4951 the frags/bytes it assembles to. */
39bec121
TW
4952void
4953md_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
d0313fb7 5018 mnemonic, and we look for it in the parallel insn hash table. */
39bec121
TW
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;
d0313fb7
NC
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. */
39bec121
TW
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
d0313fb7 5065 /* Is this instruction in a delay slot? */
39bec121
TW
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 }
d0313fb7 5077 /* Branches in delay slots are not allowed. */
39bec121
TW
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 }
d0313fb7 5086
39bec121
TW
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
d0313fb7 5101 /* Make sure we check the target of a repeat instruction. */
39bec121
TW
5102 if (insn.tm->flags & B_REPEAT)
5103 {
5104 repeat_slot = 1;
d0313fb7 5105 /* FIXME -- warn if repeat_slot == 1 at EOF. */
39bec121 5106 }
d0313fb7 5107 /* Make sure we check our delay slots for validity. */
39bec121
TW
5108 if (insn.tm->flags & FL_DELAY)
5109 {
5110 delay_slots = 2;
d0313fb7 5111 /* FIXME -- warn if delay_slots != 0 at EOF. */
39bec121
TW
5112 }
5113 }
5114}
5115
5116/* Do a final adjustment on the symbol table; in this case, make sure we have
d0313fb7 5117 a ".file" symbol. */
39bec121
TW
5118void
5119tic54x_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.
d0313fb7 5133 This lets us process parallel instructions, which span two lines. */
39bec121
TW
5134int
5135tic54x_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
d0313fb7 5144 symbol table. */
39bec121 5145void
d0313fb7
NC
5146tic54x_define_label (sym)
5147 symbolS *sym;
39bec121
TW
5148{
5149 /*static int local_label_count = 0;*/
5150 /*const char *name = S_GET_NAME (sym);*/
5151
d0313fb7 5152 /* Just in case we need this later; note that this is not necessarily the
39bec121
TW
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
d0313fb7 5157 is done in tic54x_cons. */
39bec121
TW
5158 last_label_seen = sym;
5159}
5160
d0313fb7 5161/* Try to parse something that normal parsing failed at. */
39bec121
TW
5162symbolS *
5163tic54x_undefined_symbol (name)
5164 char *name;
5165{
5166 symbol *sym;
5167
d0313fb7 5168 /* Not sure how to handle predefined symbols. */
39bec121
TW
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
d0313fb7
NC
5192/* Parse a name in an expression before the expression parser takes a stab at
5193 it. */
39bec121
TW
5194int
5195tic54x_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);
d0313fb7 5201 /* If it's a MMREG, replace it with its constant value. */
39bec121
TW
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
5212char *
5213md_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
d0313fb7 5228 /* Target data is little-endian, but floats are stored big-"word"ian. ugh. */
39bec121
TW
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
5238arelent *
5239tc_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
d0313fb7 5269/* Handle cons expressions. */
39bec121
TW
5270void
5271tic54x_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:
d0313fb7 5284 /* TI assembler always uses this, regardless of addressing mode. */
39bec121
TW
5285 if (emitting_long)
5286 r = BFD_RELOC_TIC54X_23;
5287 else
d0313fb7
NC
5288 /* We never want to directly generate this; this is provided for
5289 stabs support only. */
39bec121
TW
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
d0313fb7 5299 If fixp->fx_addsy is non-NULL, we'll have to generate a reloc entry. */
39bec121
TW
5300int
5301md_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;
d0313fb7 5315 /* Fall through. */
39bec121
TW
5316 case BFD_RELOC_TIC54X_16_OF_23:
5317 case BFD_RELOC_16:
5318 bfd_put_16 (stdoutput, val, buf);
d0313fb7
NC
5319 /* Indicate what we're actually writing, so that we don't get warnings
5320 about exceeding available space. */
39bec121
TW
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);
d0313fb7
NC
5327 /* Indicate what we're actually writing, so that we don't get warnings
5328 about exceeding available space. */
39bec121
TW
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
d0313fb7 5333 thus incompatible with this implementation's relocatable files. */
39bec121
TW
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
d0313fb7 5346 return 0; /* Return value is ignored. */
39bec121
TW
5347}
5348
d0313fb7
NC
5349/* This is our chance to record section alignment
5350 don't need to do anything here, since BFD does the proper encoding. */
39bec121
TW
5351valueT
5352md_section_align (segment, section_size)
5353 segT segment ATTRIBUTE_UNUSED;
5354 valueT section_size;
5355{
5356 return section_size;
5357}
5358
5359long
5360md_pcrel_from (fixP)
5361 fixS *fixP ATTRIBUTE_UNUSED;
5362{
5363 return 0;
5364}
5365
5366#if defined OBJ_COFF
5367
5368short
5369tc_coff_fix2rtype (fixP)
5370 fixS *fixP;
5371{
5372 return (fixP->fx_r_type);
5373}
5374
5375#endif /* OBJ_COFF */
5376
d0313fb7 5377/* Mostly little-endian, but longwords (4 octets) get MS word stored first. */
39bec121
TW
5378void
5379tic54x_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
5393int
5394tic54x_estimate_size_before_relax (frag, seg)
5395 fragS *frag ATTRIBUTE_UNUSED;
5396 segT seg ATTRIBUTE_UNUSED;
5397{
5398 return 0;
5399}
5400
d0313fb7
NC
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. */
39bec121
TW
5403int
5404tic54x_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 {
d0313fb7 5438 /* Bit fields of 16 or larger will have already been handled. */
39bec121
TW
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);
d0313fb7 5450 /* This frag is no longer used. */
39bec121
TW
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;
d0313fb7 5490 /* Make sure any BES label points to the LAST word allocated. */
39bec121
TW
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
5502void
5503tic54x_convert_frag (abfd, seg, frag)
5504 bfd *abfd ATTRIBUTE_UNUSED;
5505 segT seg ATTRIBUTE_UNUSED;
5506 fragS *frag;
5507{
d0313fb7 5508 /* Offset is in bytes. */
39bec121
TW
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
d0313fb7 5521/* We need to avoid having labels defined for certain directives/pseudo-ops
39bec121
TW
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
d0313fb7 5529 Don't allow labels to start with '.' */
39bec121
TW
5530int
5531tic54x_start_label (c, rest)
5532 int c;
5533 char *rest;
5534{
d0313fb7 5535 /* If within .struct/.union, no auto line labels, please. */
39bec121
TW
5536 if (current_stag != NULL)
5537 return 0;
5538
d0313fb7 5539 /* Disallow labels starting with "." */
39bec121
TW
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 {
d0313fb7 5560 /* Don't let colon () define a label for any of these... */
39bec121
TW
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}
This page took 0.261234 seconds and 4 git commands to generate.