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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [binutils-2.20.1/] [gas/] [config/] [tc-tic54x.c] - Blame information for rev 237

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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