* config/tc-arc.c (md_pseudo_table): Add .cpu.
[external/binutils.git] / gas / config / tc-arc.c
1 /* tc-arc.c -- Assembler for the ARC
2    Copyright (C) 1994, 1995 Free Software Foundation, Inc.
3    Contributed by Doug Evans (dje@cygnus.com).
4
5    This file is part of GAS, the GNU Assembler.
6
7    GAS is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2, or (at your option)
10    any later version.
11
12    GAS is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GAS; see the file COPYING.  If not, write to
19    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
20
21 #include <stdio.h>
22 #include <ctype.h>
23 #include "as.h"
24 #include "subsegs.h"
25 #include "opcode/arc.h"
26 #include "elf/arc.h"
27
28 extern int target_big_endian;
29 extern int arc_get_mach PARAMS ((char *));
30
31 static arc_insn arc_insert_operand PARAMS ((arc_insn insn,
32                                             const struct arc_operand *operand,
33                                             int mods,
34                                             const struct arc_operand_value *reg,
35                                             offsetT val,
36                                             char *file, unsigned int line));
37
38 static void arc_common PARAMS ((int));
39 static void arc_cpu PARAMS ((int));
40 /*static void arc_rename PARAMS ((int));*/
41
42 static int find_mach PARAMS ((char *));
43
44 const pseudo_typeS md_pseudo_table[] =
45 {
46   { "align", s_align_bytes, 0 },        /* Defaulting is invalid (0) */
47   { "common", arc_common, 0 },
48 /*{ "hword", cons, 2 }, - already exists */
49   { "word", cons, 4 },
50   { "xword", cons, 8 },
51   { "cpu", arc_cpu, 0 },
52 /*{ "rename", arc_rename, 0 },*/
53   { NULL, 0, 0 },
54 };
55
56 const int md_short_jump_size = 4;
57 const int md_long_jump_size = 4;
58 const int md_reloc_size = 12;   /* Size of relocation record */
59
60 /* This array holds the chars that always start a comment.  If the
61    pre-processor is disabled, these aren't very useful */
62 const char comment_chars[] = "#;";
63
64 /* This array holds the chars that only start a comment at the beginning of
65    a line.  If the line seems to have the form '# 123 filename'
66    .line and .file directives will appear in the pre-processed output */
67 /* Note that input_file.c hand checks for '#' at the beginning of the
68    first line of the input file.  This is because the compiler outputs
69    #NO_APP at the beginning of its output. */
70 /* Also note that comments started like this one will always
71    work if '/' isn't otherwise defined. */
72 const char line_comment_chars[] = "#";
73
74 const char line_separator_chars[] = "";
75
76 /* Chars that can be used to separate mant from exp in floating point nums */
77 const char EXP_CHARS[] = "eE";
78
79 /* Chars that mean this number is a floating point constant */
80 /* As in 0f12.456 */
81 /* or    0d1.2345e12 */
82 const char FLT_CHARS[] = "rRsSfFdDxXpP";
83
84 /* One of bfd_mach_arc_xxx.  */
85 static int arc_mach_type = bfd_mach_arc_base;
86
87 /* Non-zero if the cpu type was specified on the command line.  */
88 static int mach_type_specified = 0;
89
90 /* Non-zero if opcode tables have been initialized.
91    A .cpu command must appear before any instructions.  */
92 static int cpu_tables_init_p = 0;
93
94 static const char *arc_condition_codes[] =
95 {
96   "al", "eq", "ne", "p", "n", "c", "nc", "v",
97   "nv", "gt", "ge", "lt", "le", "hi", "ls", "pnz"
98 };
99
100 static struct hash_control *arc_ops_hash = NULL;
101 static struct hash_control *arc_suffix_hash = NULL;
102 static struct hash_control *arc_reg_hash = NULL;
103 \f
104 const char *md_shortopts = "m:";
105 struct option md_longopts[] =
106 {
107   { NULL, no_argument, NULL, 0 }
108 };
109 size_t md_longopts_size = sizeof (md_longopts);
110
111 /*
112  * md_parse_option
113  *
114  * Invocation line includes a switch not recognized by the base assembler.
115  * See if it's a processor-specific option.
116  */
117
118 int
119 md_parse_option (c, arg)
120      int c;
121      char *arg;
122 {
123   switch (c)
124     {
125     case 'm':
126       if (strncmp (arg, "cpu=", 4) == 0)
127         {
128           int mach = arc_get_mach (arg + 4);
129
130           if (mach != -1)
131             {
132               arc_mach_type = mach;
133               mach_type_specified = 1;
134               break;
135             }
136         }
137       as_bad ("invalid architecture -m%s", arg);
138       return 0;
139
140     default:
141       return 0;
142     }
143
144  return 1;
145 }
146
147 void
148 md_show_usage (stream)
149      FILE *stream;
150 {
151   fprintf (stream, "\
152 ARC options:\n\
153 -mcpu={base,host,graphics,audio}        select cpu type\n");
154 }
155
156 /* This function is called once, at assembler startup time.  It should
157    set up all the tables, etc. that the MD part of the assembler will need.
158    Opcode selection is defered until later because we might see a .cpu
159    command.  */
160
161 void
162 md_begin ()
163 {
164   /* The endianness can be chosen "at the factory".  One day we may have
165      to be bi-endian.  */
166   target_big_endian = 0;
167
168   if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, arc_mach_type))
169     as_warn ("could not set architecture and machine");
170 }
171
172 /* Initialize the various opcode and operand tables.
173    MACH is one of bfd_mach_arc_xxx.  */
174
175 static void
176 init_opcode_tables (mach)
177      int mach;
178 {
179   register unsigned int i;
180   char *last;
181   /* Indexed by bfd_mach_arc_xxx.  */
182   static int cpu_type_map[] =
183     {
184       ARC_CPU_BASE,
185       ARC_CPU_HOST,
186       ARC_CPU_GRAPHICS,
187       ARC_CPU_AUDIO,
188     };
189
190   if ((arc_ops_hash = hash_new ()) == NULL
191       || (arc_suffix_hash = hash_new ()) == NULL
192       || (arc_reg_hash = hash_new ()) == NULL)
193     as_fatal ("Virtual memory exhausted");
194
195   if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach))
196     as_warn ("could not set architecture and machine");
197
198   /* This initializes a few things in arc-opc.c that we need.
199      This must be called before the various arc_xxx_supported fns.  */
200   arc_opcode_init_tables (cpu_type_map[mach]);
201
202 #if 0
203   for (i = 0; i < arc_opcodes_count; i++)
204     hash_insert (arc_ops_hash, arc_opcodes[i].name, (PTR) (arc_opcodes + i));
205 #endif
206
207   /* Only put the first entry of each equivalently named suffix in the
208      table.  */
209   last = "";
210   for (i = 0; i < arc_suffixes_count; i++)
211     {
212       if (! arc_opval_supported (&arc_suffixes[i]))
213         continue;
214       if (strcmp (arc_suffixes[i].name, last) != 0)
215         hash_insert (arc_suffix_hash, arc_suffixes[i].name, (PTR) (arc_suffixes + i));
216       last = arc_suffixes[i].name;
217     }
218
219   /* ??? This is the simple version.  See tc-arm.c for something snazzier.  */
220   for (i = 0; i < arc_reg_names_count; i++)
221     {
222       if (! arc_opval_supported (&arc_reg_names[i]))
223         continue;
224       hash_insert (arc_reg_hash, arc_reg_names[i].name, (PTR) (arc_reg_names + i));
225     }
226
227   /* Tell `s_cpu' it's too late.  */
228   cpu_tables_init_p = 1;
229 }
230 \f
231 /* Insert an operand value into an instruction.
232    If REG is non-NULL, it is a register number and ignore VAL.  */
233
234 static arc_insn
235 arc_insert_operand (insn, operand, mods, reg, val, file, line)
236      arc_insn insn;
237      const struct arc_operand *operand;
238      int mods;
239      const struct arc_operand_value *reg;
240      offsetT val;
241      char *file;
242      unsigned int line;
243 {
244   if (operand->bits != 32)
245     {
246       long min, max;
247       offsetT test;
248
249       if ((operand->flags & ARC_OPERAND_SIGNED) != 0)
250         {
251           if ((operand->flags & ARC_OPERAND_SIGNOPT) != 0)
252             max = (1 << operand->bits) - 1;
253           else
254             max = (1 << (operand->bits - 1)) - 1;
255           min = - (1 << (operand->bits - 1));
256         }
257       else
258         {
259           max = (1 << operand->bits) - 1;
260           min = 0;
261         }
262
263       if ((operand->flags & ARC_OPERAND_NEGATIVE) != 0)
264         test = - val;
265       else
266         test = val;
267
268       if (test < (offsetT) min || test > (offsetT) max)
269         {
270           const char *err =
271             "operand out of range (%s not between %ld and %ld)";
272           char buf[100];
273
274           sprint_value (buf, test);
275           if (file == (char *) NULL)
276             as_warn (err, buf, min, max);
277           else
278             as_warn_where (file, line, err, buf, min, max);
279         }
280     }
281
282   if (operand->insert)
283     {
284       const char *errmsg;
285
286       errmsg = NULL;
287       insn = (*operand->insert) (insn, operand, mods, reg, (long) val, &errmsg);
288       if (errmsg != (const char *) NULL)
289         as_warn (errmsg);
290     }
291   else
292     insn |= (((long) val & ((1 << operand->bits) - 1))
293              << operand->shift);
294
295   return insn;
296 }
297
298 /* We need to keep a list of fixups.  We can't simply generate them as
299    we go, because that would require us to first create the frag, and
300    that would screw up references to ``.''.  */
301
302 struct arc_fixup
303 {
304   expressionS exp;
305   /* index into `arc_operands' */
306   int opindex;
307 };
308
309 #define MAX_INSN_FIXUPS 5
310
311 /* This routine is called for each instruction to be assembled.  */
312
313 void
314 md_assemble (str)
315      char *str;
316 {
317   const struct arc_opcode *opcode,*opcode_end;
318   char *start;
319   arc_insn insn;
320   bfd_reloc_code_real_type reloc;
321   static int init_tables_p = 0;
322
323   /* Opcode table initialization is deferred until here because we have to
324      wait for a possible .cpu command.  */
325   if (!init_tables_p)
326     {
327       init_opcode_tables (arc_mach_type);
328       init_tables_p = 1;
329     }
330
331   /* Skip leading white space.  */
332   while (isspace (*str))
333     str++;
334
335   /* The instructions are sorted by the first letter.  Scan the opcode table
336      until we find the right one.  */
337   opcode_end = arc_opcodes + arc_opcodes_count;
338   for (opcode = arc_opcodes; opcode < opcode_end; opcode++)
339     if (*opcode->syntax == *str)
340       break;
341   if (opcode == opcode_end)
342     {
343       as_bad ("bad instruction `%s'", str);
344       return;
345     }
346
347   /* Keep looking until we find a match.  If we haven't found a match, and the
348      first character no longer matches, we needn't look any further.  */
349
350   start = str;
351   for ( ; opcode < opcode_end && *opcode->syntax == *start; ++opcode)
352     {
353       int past_opcode_p;
354       char *syn;
355       struct arc_fixup fixups[MAX_INSN_FIXUPS];
356       int fc,limm_reloc_p;
357
358       /* Is this opcode supported by the selected cpu?  */
359       if (! arc_opcode_supported (opcode))
360         continue;
361
362       /* Scan the syntax string.  If it doesn't match, try the next one.  */
363
364       arc_opcode_init_insert ();
365       insn = opcode->value;
366       reloc = BFD_RELOC_NONE;
367       fc = 0;
368       past_opcode_p = 0;
369
370       /* Used as a sanity check.  If we need a limm reloc, make sure we ask
371          for an extra 4 bytes from frag_more.  */
372       limm_reloc_p = 0;
373
374       /* We don't check for (*str != '\0') here because we want to parse
375          any trailing fake arguments in the syntax string.  */
376       for (str = start, syn = opcode->syntax; *syn != '\0'; )
377         {
378           int mods;
379           const struct arc_operand *operand;
380
381           /* Non operand chars must match exactly.  */
382           if (*syn != '%' || *++syn == '%')
383             {
384               /* Handle '+' specially as we want to allow "ld r0,[sp-4]".  */
385               if (*syn == '+' && *str == '-')
386                 {
387                   /* Skip over syn's +, but leave str's - alone.
388                      That makes the case identical to "ld r0,[sp+-4]".  */
389                   ++syn;
390                 }
391               else if (*str != *syn)
392                 break;
393               else
394                 {
395                   if (*syn == ' ')
396                     past_opcode_p = 1;
397                   ++syn;
398                   ++str;
399                 }
400               continue;
401             }
402
403           /* We have an operand.  Pick out any modifiers.  */
404           mods = 0;
405           while (ARC_MOD_P (arc_operands[arc_operand_map[*syn]].flags))
406             {
407               mods |= arc_operands[arc_operand_map[*syn]].flags & ARC_MOD_BITS;
408               ++syn;
409             }
410           operand = arc_operands + arc_operand_map[*syn];
411           if (operand->fmt == 0)
412             as_fatal ("unknown syntax format character `%c'", *syn);
413
414           if (operand->flags & ARC_OPERAND_FAKE)
415             {
416               const char *errmsg = NULL;
417               if (operand->insert)
418                 {
419                   insn = (*operand->insert) (insn, operand, mods, NULL, 0, &errmsg);
420                   /* If we get an error, go on to try the next insn.  */
421                   if (errmsg)
422                     break;
423                 }
424               ++syn;
425             }
426           /* Are we finished with suffixes?  */
427           else if (!past_opcode_p)
428             {
429               int found;
430               char c;
431               char *s,*t;
432               const struct arc_operand_value *suf,*suffix,*suffix_end;
433
434               if (!(operand->flags & ARC_OPERAND_SUFFIX))
435                 abort ();
436
437               /* If we're at a space in the input string, we want to skip the
438                  remaining suffixes.  There may be some fake ones though, so
439                  just go on to try the next one.  */
440               if (*str == ' ')
441                 {
442                   ++syn;
443                   continue;
444                 }
445
446               s = str;
447               if (mods & ARC_MOD_DOT)
448                 {
449                   if (*s != '.')
450                     break;
451                   ++s;
452                 }
453               else
454                 {
455                   /* This can happen in "b.nd foo" and we're currently looking
456                      for "%q" (ie: a condition code suffix).  */
457                   if (*s == '.')
458                     {
459                       ++syn;
460                       continue;
461                     }
462                 }
463
464               /* Pick the suffix out and look it up via the hash table.  */
465               for (t = s; *t && isalpha (*t); ++t)
466                 continue;
467               c = *t;
468               *t = '\0';
469               suf = hash_find (arc_suffix_hash, s);
470               *t = c;
471               if (!suf)
472                 {
473                   /* This can happen in "blle foo" and we're currently using
474                      the template "b%q%.n %j".  The "bl" insn occurs later in
475                      the table so "lle" isn't an illegal suffix.  */
476                   break;
477                 }
478
479               /* Is it the right type?  Note that the same character is used
480                  several times, so we have to examine all of them.  This is
481                  relatively efficient as equivalent entries are kept
482                  together.  If it's not the right type, don't increment `str'
483                  so we try the next one in the series.  */
484               found = 0;
485               suffix_end = arc_suffixes + arc_suffixes_count;
486               for (suffix = suf;
487                    suffix < suffix_end && strcmp (suffix->name, suf->name) == 0;
488                    suffix++)
489                 {
490                   if (arc_operands[suffix->type].fmt == *syn)
491                     {
492                       /* Insert the suffix's value into the insn.  */
493                       if (operand->insert)
494                         insn = (*operand->insert) (insn, operand,
495                                                    mods, NULL, suffix->value,
496                                                    NULL);
497                       else
498                         insn |= suffix->value << operand->shift;
499
500                       str = t;
501                       found = 1;
502                       break;
503                     }
504                 }
505               ++syn;
506               if (!found)
507                 /* There's nothing to do except, go on to try the next one.
508                    ??? This test can be deleted when we're done.  */
509                 ;
510             }
511           else
512             /* This is either a register or an expression of some kind.  */
513             {
514               char c;
515               char *hold;
516               const struct arc_operand_value *reg;
517               long value;
518               expressionS ex;
519
520               if (operand->flags & ARC_OPERAND_SUFFIX)
521                 abort ();
522
523               /* Is there anything left to parse?
524                  We don't check for this at the top because we want to parse
525                  any trailing fake arguments in the syntax string.  */
526               if (*str == '\0')
527                 break;
528
529               /* Is this a syntax character?  Eg: is there a '[' present when
530                  there shouldn't be?  */
531               if (!isalnum (*str)
532                   /* '.' as in ".LLC0" */
533                   && *str != '.'
534                   /* '_' as in "_print" */
535                   && *str != '_'
536                   /* '-' as in "[fp-4]" */
537                   && *str != '-')
538                 break;
539
540               /* Is it a register?  */
541               value = 0;
542               hold = str;
543               while (*str && (isalnum (*str) || *str == '_'))
544                 ++str;
545               c = *str;
546               *str = '\0';
547               reg = hash_find (arc_reg_hash, hold);
548               *str = c;
549               if (!reg)
550                 {
551                   /* Restore `str', it wasn't a register.  */
552                   str = hold;
553
554                   /* Gather the operand.  */
555                   hold = input_line_pointer;
556                   input_line_pointer = str;
557                   expression (&ex);
558                   str = input_line_pointer;
559                   input_line_pointer = hold;
560
561                   if (ex.X_op == O_illegal)
562                     as_bad ("illegal operand");
563                   else if (ex.X_op == O_absent)
564                     as_bad ("missing operand");
565                   else if (ex.X_op == O_constant)
566                     {
567                       value = ex.X_add_number;
568                     }
569                   else
570                     {
571                       /* We need to generate a fixup for this expression.
572                          If this is a register constant (IE: one whose register
573                          value gets stored as 61-63) then this must be a limm.
574                          We don't support shimm relocs.  */
575                       if (fc >= MAX_INSN_FIXUPS)
576                         as_fatal ("too many fixups");
577                       fixups[fc].exp = ex;
578
579                       /* ??? This bit could use some cleaning up.  Referencing
580                          the format chars like this goes against style.  */
581 #define IS_REG_OPERAND(o) ((o) == 'a' || (o) == 'b' || (o) == 'c')
582                       if (IS_REG_OPERAND (*syn))
583                         {
584                           const char *junk;
585                           fixups[fc].opindex = arc_operand_map['L'];
586                           limm_reloc_p = 1;
587                           /* Tell insert_reg we need a limm.  This is needed
588                              because the value at this point is zero, a shimm.
589                              ??? Hack city.  */
590                           (*arc_operands[arc_operand_map['Q']].insert)
591                             (insn, operand, mods, reg, 0L, &junk);
592                         }
593                       else
594                         fixups[fc].opindex = arc_operand_map[*syn];
595                       ++fc;
596                       value = 0;
597                     }
598                 }
599
600               /* Insert the register or expression into the instruction.  */
601               if (operand->insert)
602                 {
603                   const char *errmsg = NULL;
604                   insn = (*operand->insert) (insn, operand, mods,
605                                              reg, (long) value, &errmsg);
606 #if 0
607                   if (errmsg != (const char *) NULL)
608                     as_warn (errmsg);
609 #endif
610                   /* FIXME: We want to try shimm insns for limm ones.  But if
611                      the constant won't fit, we must go on to try the next
612                      possibility.  Where do we issue warnings for constants
613                      that are too big then?  At present, we'll flag the insn
614                      as unrecognizable!  Maybe have the "bad instruction"
615                      error message include our `errmsg'?  */
616                   if (errmsg != (const char *) NULL)
617                     break;
618                 }
619               else
620                 insn |= (value & ((1 << operand->bits) - 1)) << operand->shift;
621
622               ++syn;
623             }
624         }
625
626       if (*syn == '\0')
627         {
628           int i;
629           char *f;
630           long limm;
631
632           /* We've found a matching insn.
633              ??? For the moment we assume a valid `str' can only contain blanks
634              now.  IE: We needn't try again with a longer version of the
635              insn.  */
636
637           while (isspace (*str))
638             ++str;
639
640           if (*str != '\0')
641             as_bad ("junk at end of line: `%s'", str);
642
643           /* Write out the instruction.
644              It is important to fetch enough space in one call to `frag_more'.
645              We use (f - frag_now->fr_literal) to compute where we are and we
646              don't want frag_now to change between calls.  */
647           if (arc_opcode_limm_p (&limm))
648             {
649               f = frag_more (8);
650               md_number_to_chars (f, insn, 4);
651               md_number_to_chars (f + 4, limm, 4);
652             }
653           else if (limm_reloc_p)
654             {
655               /* We need a limm reloc, but the tables think we don't.  */
656               abort ();
657             }
658           else
659             {
660               f = frag_more (4);
661               md_number_to_chars (f, insn, 4);
662             }
663
664           /* Create any fixups.  At this point we do not use a
665              bfd_reloc_code_real_type, but instead just use the operand index.
666              This lets us easily handle fixups for any operand type, although
667              that is admittedly not a very exciting feature.  We pick a BFD
668              reloc type in md_apply_fix.  */
669           for (i = 0; i < fc; i++)
670             {
671               const struct arc_operand *operand;
672
673               operand = &arc_operands[fixups[i].opindex];
674               fix_new_exp (frag_now,
675                            ((f - frag_now->fr_literal)
676                             + (operand->fmt == 'L' ? 4 : 0)), 4,
677                            &fixups[i].exp,
678                            (operand->flags & ARC_OPERAND_RELATIVE) != 0,
679                            ((bfd_reloc_code_real_type)
680                             (fixups[i].opindex + (int) BFD_RELOC_UNUSED)));
681             }
682
683           /* All done.  */
684           return;
685         }
686
687       /* Try the next entry.  */
688     }
689
690   as_bad ("bad instruction `%s'", start);
691 }
692 \f
693 static void
694 arc_common (ignore)
695      int ignore;
696 {
697   char *name;
698   char c;
699   char *p;
700   int temp, size;
701   symbolS *symbolP;
702
703   name = input_line_pointer;
704   c = get_symbol_end ();
705   /* just after name is now '\0' */
706   p = input_line_pointer;
707   *p = c;
708   SKIP_WHITESPACE ();
709   if (*input_line_pointer != ',')
710     {
711       as_bad ("expected comma after symbol-name");
712       ignore_rest_of_line ();
713       return;
714     }
715   input_line_pointer++;         /* skip ',' */
716   if ((temp = get_absolute_expression ()) < 0)
717     {
718       as_bad (".COMMon length (%d.) <0! Ignored.", temp);
719       ignore_rest_of_line ();
720       return;
721     }
722   size = temp;
723   *p = 0;
724   symbolP = symbol_find_or_make (name);
725   *p = c;
726   if (S_IS_DEFINED (symbolP))
727     {
728       as_bad ("ignoring attempt to re-define symbol");
729       ignore_rest_of_line ();
730       return;
731     }
732   if (S_GET_VALUE (symbolP) != 0)
733     {
734       if (S_GET_VALUE (symbolP) != size)
735         {
736           as_warn ("Length of .comm \"%s\" is already %ld. Not changed to %d.",
737                    S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
738         }
739     }
740   else
741     {
742 #ifndef OBJ_ELF
743       S_SET_VALUE (symbolP, (valueT) size);
744       S_SET_EXTERNAL (symbolP);
745 #endif
746     }
747   assert (symbolP->sy_frag == &zero_address_frag);
748   if (*input_line_pointer != ',')
749     {
750       as_bad ("expected comma after common length");
751       ignore_rest_of_line ();
752       return;
753     }
754   input_line_pointer++;
755   SKIP_WHITESPACE ();
756   if (*input_line_pointer != '"')
757     {
758       temp = get_absolute_expression ();
759 #ifndef OBJ_ELF
760       if (temp > max_alignment)
761         {
762           temp = max_alignment;
763           as_warn ("Common alignment too large: %d. assumed", temp);
764         }
765 #endif
766       if (temp < 0)
767         {
768           temp = 0;
769           as_warn ("Common alignment negative; 0 assumed");
770         }
771 #ifdef OBJ_ELF
772       if (symbolP->local)
773         {
774           segT old_sec;
775           int old_subsec;
776           char *p;
777           int align;
778
779         allocate_bss:
780           old_sec = now_seg;
781           old_subsec = now_subseg;
782           align = temp;
783           record_alignment (bss_section, align);
784           subseg_set (bss_section, 0);
785           if (align)
786             frag_align (align, 0);
787           if (S_GET_SEGMENT (symbolP) == bss_section)
788             symbolP->sy_frag->fr_symbol = 0;
789           symbolP->sy_frag = frag_now;
790           p = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, size,
791                         (char *) 0);
792           *p = 0;
793           S_SET_SEGMENT (symbolP, bss_section);
794           S_CLEAR_EXTERNAL (symbolP);
795           subseg_set (old_sec, old_subsec);
796         }
797       else
798 #endif
799         {
800         allocate_common:
801           S_SET_VALUE (symbolP, (valueT) size);
802 #ifdef OBJ_ELF
803           S_SET_ALIGN (symbolP, temp);
804 #endif
805           S_SET_EXTERNAL (symbolP);
806           /* should be common, but this is how gas does it for now */
807           S_SET_SEGMENT (symbolP, bfd_und_section_ptr);
808         }
809     }
810   else
811     {
812       input_line_pointer++;
813       /* @@ Some use the dot, some don't.  Can we get some consistency??  */
814       if (*input_line_pointer == '.')
815         input_line_pointer++;
816       /* @@ Some say data, some say bss.  */
817       if (strncmp (input_line_pointer, "bss\"", 4)
818           && strncmp (input_line_pointer, "data\"", 5))
819         {
820           while (*--input_line_pointer != '"')
821             ;
822           input_line_pointer--;
823           goto bad_common_segment;
824         }
825       while (*input_line_pointer++ != '"')
826         ;
827       goto allocate_common;
828     }
829   demand_empty_rest_of_line ();
830   return;
831
832   {
833   bad_common_segment:
834     p = input_line_pointer;
835     while (*p && *p != '\n')
836       p++;
837     c = *p;
838     *p = '\0';
839     as_bad ("bad .common segment %s", input_line_pointer + 1);
840     *p = c;
841     input_line_pointer = p;
842     ignore_rest_of_line ();
843     return;
844   }
845 }
846
847 /* Select the cpu we're assembling for.  */
848
849 static void
850 arc_cpu (ignore)
851      int ignore;
852 {
853   int mach;
854   char c;
855   char *cpu;
856   static int seen_p = 0;
857
858   /* Allow only one .cpu.  */
859   if (seen_p)
860     {
861       as_bad ("only one .cpu command allowed");
862       ignore_rest_of_line ();
863       return;
864     }
865   seen_p = 1;
866
867   /* If an instruction has already been seen, it's too late.  */
868   if (cpu_tables_init_p)
869     {
870       as_bad (".cpu command must appear before any instructions");
871       ignore_rest_of_line ();
872       return;
873     }
874
875   cpu = input_line_pointer;
876   c = get_symbol_end ();
877   mach = arc_get_mach (cpu);
878   *input_line_pointer = c;
879   if (mach == -1)
880     goto bad_cpu;
881
882   /* Kind of overkill but what the heck.  */
883   demand_empty_rest_of_line ();
884
885   /* The cpu may have been selected on the command line.
886      The choices must match.  */
887   if (mach_type_specified && mach != arc_mach_type)
888     as_bad (".cpu conflicts with -mcpu flag");
889   else
890     {
891       arc_mach_type = mach;
892       if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach))
893         as_warn ("could not set architecture and machine");
894     }
895   return;
896
897  bad_cpu:
898   as_bad ("bad .cpu op");
899   ignore_rest_of_line ();
900 }
901
902 #if 0
903 /* The .rename pseudo-op.  This is used by gcc to implement
904    -mmangle-cpu-libgcc.  */
905
906 static void
907 arc_rename (ignore)
908      int ignore;
909 {
910   char *name,*new;
911   char c;
912   symbolS *sym;
913   int len;
914
915   name = input_line_pointer;
916   c = get_symbol_end ();
917   sym = symbol_find_or_make (name);
918   *input_line_pointer = c;
919
920   if (*input_line_pointer != ',')
921     {
922       as_bad ("missing rename string");
923       ignore_rest_of_line ();
924       return;
925     }
926   ++input_line_pointer;
927   SKIP_WHITESPACE ();
928
929   name = input_line_pointer;
930   c = get_symbol_end ();
931   if (*name == '\0')
932     {
933       *input_line_pointer = c;
934       as_bad ("invalid symbol to rename to");
935       ignore_rest_of_line ();
936       return;
937     }
938   new = (char *) xmalloc (strlen (name) + 1);
939   strcpy (new, name);
940   *input_line_pointer = c;
941   sym->sy_tc.real_name = new;
942
943   demand_empty_rest_of_line ();
944 }
945 #endif
946 \f
947 /* Turn a string in input_line_pointer into a floating point constant of type
948    type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
949    emitted is stored in *sizeP.
950    An error message is returned, or NULL on OK.  */
951
952 /* Equal to MAX_PRECISION in atof-ieee.c */
953 #define MAX_LITTLENUMS 6
954
955 char *
956 md_atof (type, litP, sizeP)
957      char type;
958      char *litP;
959      int *sizeP;
960 {
961   int prec;
962   LITTLENUM_TYPE words[MAX_LITTLENUMS];
963   LITTLENUM_TYPE *wordP;
964   char *t;
965   char *atof_ieee ();
966
967   switch (type)
968     {
969     case 'f':
970     case 'F':
971       prec = 2;
972       break;
973
974     case 'd':
975     case 'D':
976       prec = 4;
977       break;
978
979     default:
980       *sizeP = 0;
981       return "bad call to md_atof";
982     }
983
984   t = atof_ieee (input_line_pointer, type, words);
985   if (t)
986     input_line_pointer = t;
987   *sizeP = prec * sizeof (LITTLENUM_TYPE);
988   for (wordP = words; prec--;)
989     {
990       md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
991       litP += sizeof (LITTLENUM_TYPE);
992     }
993
994   return NULL;
995 }
996
997 /* Write a value out to the object file, using the appropriate
998    endianness.  */
999
1000 void
1001 md_number_to_chars (buf, val, n)
1002      char *buf;
1003      valueT val;
1004      int n;
1005 {
1006   /* The ARC isn't bi-endian.  Yet.  */
1007   if (target_big_endian)
1008     number_to_chars_bigendian (buf, val, n);
1009   else
1010     number_to_chars_littleendian (buf, val, n);
1011 }
1012
1013 /* Round up a section size to the appropriate boundary. */
1014
1015 valueT
1016 md_section_align (segment, size)
1017      segT segment;
1018      valueT size;
1019 {
1020   int align = bfd_get_section_alignment (stdoutput, segment);
1021
1022   return ((size + (1 << align) - 1) & (-1 << align));
1023 }
1024
1025 /* We don't have any form of relaxing.  */
1026
1027 int
1028 md_estimate_size_before_relax (fragp, seg)
1029      fragS *fragp;
1030      asection *seg;
1031 {
1032   abort ();
1033 }
1034
1035 const relax_typeS md_relax_table[] =
1036 {
1037   { 0 }
1038 };
1039
1040 /* Convert a machine dependent frag.  We never generate these.  */
1041
1042 void
1043 md_convert_frag (abfd, sec, fragp)
1044      bfd *abfd;
1045      asection *sec;
1046      fragS *fragp;
1047 {
1048   abort ();
1049 }
1050
1051 /* Parse an operand that is machine-specific.
1052    We just return without modifying the expression if we have nothing to do. */
1053
1054 /* ARGSUSED */
1055 void 
1056 md_operand (expressionP)
1057      expressionS *expressionP;
1058 {
1059 }
1060
1061 /* We have no need to default values of symbols. */
1062
1063 /* ARGSUSED */
1064 symbolS *
1065 md_undefined_symbol (name)
1066      char *name;
1067 {
1068   return 0;
1069 }                               /* md_undefined_symbol() */
1070 \f
1071 /* Functions concerning relocs.  */
1072
1073 /* The location from which a PC relative jump should be calculated,
1074    given a PC relative reloc.  */
1075
1076 long 
1077 md_pcrel_from (fixP)
1078      fixS *fixP;
1079 {
1080   if (fixP->fx_addsy != (symbolS *) NULL
1081       && ! S_IS_DEFINED (fixP->fx_addsy))
1082     /* Return offset from PC to delay slot.  Offsets are from there.  */
1083     return 4;
1084
1085   /* Return the address of the delay slot.  */
1086   return fixP->fx_frag->fr_address + fixP->fx_where + fixP->fx_size;
1087 }
1088
1089 /* Apply a fixup to the object code.  This is called for all the
1090    fixups we generated by the call to fix_new_exp, above.  In the call
1091    above we used a reloc code which was the largest legal reloc code
1092    plus the operand index.  Here we undo that to recover the operand
1093    index.  At this point all symbol values should be fully resolved,
1094    and we attempt to completely resolve the reloc.  If we can not do
1095    that, we determine the correct reloc code and put it back in the
1096    fixup.  */
1097
1098 int
1099 md_apply_fix (fixP, valueP)
1100      fixS *fixP;
1101      valueT *valueP;
1102 {
1103   /*char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;*/
1104   valueT value;
1105
1106   /* FIXME FIXME FIXME: The value we are passed in *valueP includes
1107      the symbol values.  Since we are using BFD_ASSEMBLER, if we are
1108      doing this relocation the code in write.c is going to call
1109      bfd_perform_relocation, which is also going to use the symbol
1110      value.  That means that if the reloc is fully resolved we want to
1111      use *valueP since bfd_perform_relocation is not being used.
1112      However, if the reloc is not fully resolved we do not want to use
1113      *valueP, and must use fx_offset instead.  However, if the reloc
1114      is PC relative, we do want to use *valueP since it includes the
1115      result of md_pcrel_from.  This is confusing.  */
1116
1117   if (fixP->fx_addsy == (symbolS *) NULL)
1118     {
1119       value = *valueP;
1120       fixP->fx_done = 1;
1121     }
1122   else if (fixP->fx_pcrel)
1123     value = *valueP;
1124   else
1125     {
1126       value = fixP->fx_offset;
1127       if (fixP->fx_subsy != (symbolS *) NULL)
1128         {
1129           if (S_GET_SEGMENT (fixP->fx_subsy) == absolute_section)
1130             value -= S_GET_VALUE (fixP->fx_subsy);
1131           else
1132             {
1133               /* We can't actually support subtracting a symbol.  */
1134               as_bad_where (fixP->fx_file, fixP->fx_line,
1135                             "expression too complex");
1136             }
1137         }
1138     }
1139
1140   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1141     {
1142       int opindex;
1143       const struct arc_operand *operand;
1144       char *where;
1145       arc_insn insn;
1146
1147       opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1148
1149       operand = &arc_operands[opindex];
1150
1151       /* Fetch the instruction, insert the fully resolved operand
1152          value, and stuff the instruction back again.  */
1153       where = fixP->fx_frag->fr_literal + fixP->fx_where;
1154       if (target_big_endian)
1155         insn = bfd_getb32 ((unsigned char *) where);
1156       else
1157         insn = bfd_getl32 ((unsigned char *) where);
1158       insn = arc_insert_operand (insn, operand, -1, NULL, (offsetT) value,
1159                                  fixP->fx_file, fixP->fx_line);
1160       if (target_big_endian)
1161         bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
1162       else
1163         bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
1164
1165       if (fixP->fx_done)
1166         {
1167           /* Nothing else to do here.  */
1168           return 1;
1169         }
1170
1171       /* Determine a BFD reloc value based on the operand information.
1172          We are only prepared to turn a few of the operands into relocs.
1173          FIXME: Selecting the reloc type is a bit haphazard; perhaps
1174          there should be a new field in the operand table.  */
1175       if ((operand->flags & ARC_OPERAND_RELATIVE) != 0
1176           && operand->bits == 20
1177           && operand->shift == 7)
1178         fixP->fx_r_type = BFD_RELOC_ARC_B22_PCREL;
1179       else if ((operand->flags & ARC_OPERAND_ABSOLUTE) != 0
1180                && operand->bits == 32
1181                && operand->shift == 32)
1182         fixP->fx_r_type = BFD_RELOC_32;
1183       else
1184         {
1185           as_bad_where (fixP->fx_file, fixP->fx_line,
1186                         "unresolved expression that must be resolved");
1187           fixP->fx_done = 1;
1188           return 1;
1189         }
1190     }
1191   else
1192     {
1193       switch (fixP->fx_r_type)
1194         {
1195         case BFD_RELOC_32:
1196           md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
1197                               value, 4);
1198           break;
1199         case BFD_RELOC_16:
1200           md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
1201                               value, 2);
1202           break;
1203         case BFD_RELOC_8:
1204           md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
1205                               value, 1);
1206           break;
1207         default:
1208           abort ();
1209         }
1210     }
1211
1212 #ifdef OBJ_ELF
1213   fixP->fx_addnumber = value;
1214 #else
1215   fixP->fx_addnumber = 0;
1216 #endif
1217
1218   return 1;
1219 }
1220
1221 /* Translate internal representation of relocation info to BFD target
1222    format.  */
1223
1224 arelent *
1225 tc_gen_reloc (section, fixP)
1226      asection *section;
1227      fixS *fixP;
1228 {
1229   arelent *reloc;
1230
1231   reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
1232
1233   reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym;
1234   reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
1235   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
1236   if (reloc->howto == (reloc_howto_type *) NULL)
1237     {
1238       as_bad_where (fixP->fx_file, fixP->fx_line,
1239                     "internal error: can't export reloc type %d (`%s')",
1240                     fixP->fx_r_type, bfd_get_reloc_code_name (fixP->fx_r_type));
1241       return NULL;
1242     }
1243   reloc->addend = fixP->fx_addnumber;
1244
1245   assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
1246
1247   return reloc;
1248 }
1249 \f
1250 /* Frobbers.  */
1251
1252 #if 0
1253 /* Set the real name if the .rename pseudo-op was used.
1254    Return 1 if the symbol should not be included in the symbol table.  */
1255
1256 int
1257 arc_frob_symbol (sym)
1258      symbolS *sym;
1259 {
1260   if (sym->sy_tc.real_name != (char *) NULL)
1261     S_SET_NAME (sym, sym->sy_tc.real_name);
1262
1263   return 0;
1264 }
1265 #endif