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