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