OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [gas/] [config/] [tc-tic54x.c] - Blame information for rev 16

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.