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