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