xref: /openbsd-src/gnu/usr.bin/binutils/gas/config/tc-arc.c (revision cf2f2c5620d6d9a4fd01930983c4b9a1f76d7aa3)
1f7cc78ecSespie /* tc-arc.c -- Assembler for the ARC
2d2201f2fSdrahn    Copyright 1994, 1995, 1997, 1999, 2000, 2001, 2002
35f210c2aSfgsch    Free Software Foundation, Inc.
4f7cc78ecSespie    Contributed by Doug Evans (dje@cygnus.com).
5f7cc78ecSespie 
6f7cc78ecSespie    This file is part of GAS, the GNU Assembler.
7f7cc78ecSespie 
8f7cc78ecSespie    GAS is free software; you can redistribute it and/or modify
9f7cc78ecSespie    it under the terms of the GNU General Public License as published by
10f7cc78ecSespie    the Free Software Foundation; either version 2, or (at your option)
11f7cc78ecSespie    any later version.
12f7cc78ecSespie 
13f7cc78ecSespie    GAS is distributed in the hope that it will be useful,
14f7cc78ecSespie    but WITHOUT ANY WARRANTY; without even the implied warranty of
15f7cc78ecSespie    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16f7cc78ecSespie    GNU General Public License for more details.
17f7cc78ecSespie 
18f7cc78ecSespie    You should have received a copy of the GNU General Public License
19f7cc78ecSespie    along with GAS; see the file COPYING.  If not, write to the Free
20f7cc78ecSespie    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21f7cc78ecSespie    02111-1307, USA.  */
22f7cc78ecSespie 
23f7cc78ecSespie #include <stdio.h>
245f210c2aSfgsch #include "libiberty.h"
25f7cc78ecSespie #include "as.h"
26d2201f2fSdrahn #include "struc-symbol.h"
27d2201f2fSdrahn #include "safe-ctype.h"
28f7cc78ecSespie #include "subsegs.h"
29f7cc78ecSespie #include "opcode/arc.h"
305f210c2aSfgsch #include "../opcodes/arc-ext.h"
31f7cc78ecSespie #include "elf/arc.h"
325f210c2aSfgsch #include "dwarf2dbg.h"
33f7cc78ecSespie 
34f7cc78ecSespie extern int arc_get_mach PARAMS ((char *));
355f210c2aSfgsch extern int arc_operand_type PARAMS ((int));
365f210c2aSfgsch extern int arc_insn_not_jl PARAMS ((arc_insn));
375f210c2aSfgsch extern int arc_limm_fixup_adjust PARAMS ((arc_insn));
385f210c2aSfgsch extern int arc_get_noshortcut_flag PARAMS ((void));
395f210c2aSfgsch extern int arc_set_ext_seg PARAMS ((void));
405f210c2aSfgsch extern void arc_code_symbol PARAMS ((expressionS *));
41f7cc78ecSespie 
42f7cc78ecSespie static arc_insn arc_insert_operand PARAMS ((arc_insn,
43f7cc78ecSespie 					    const struct arc_operand *, int,
44f7cc78ecSespie 					    const struct arc_operand_value *,
45f7cc78ecSespie 					    offsetT, char *, unsigned int));
46f7cc78ecSespie static void arc_common PARAMS ((int));
475f210c2aSfgsch static void arc_extinst PARAMS ((int));
485f210c2aSfgsch static void arc_extoper PARAMS ((int));
495f210c2aSfgsch static void arc_option PARAMS ((int));
50f7cc78ecSespie static int  get_arc_exp_reloc_type PARAMS ((int, int, expressionS *,
51f7cc78ecSespie 					   expressionS *));
52f7cc78ecSespie 
53d2201f2fSdrahn static void init_opcode_tables PARAMS ((int));
54d2201f2fSdrahn 
555f210c2aSfgsch const struct suffix_classes {
565f210c2aSfgsch   char *name;
575f210c2aSfgsch   int  len;
585f210c2aSfgsch } suffixclass[] = {
595f210c2aSfgsch   { "SUFFIX_COND|SUFFIX_FLAG",23 },
605f210c2aSfgsch   { "SUFFIX_FLAG", 11 },
615f210c2aSfgsch   { "SUFFIX_COND", 11 },
625f210c2aSfgsch   { "SUFFIX_NONE", 11 }
635f210c2aSfgsch };
645f210c2aSfgsch 
655f210c2aSfgsch #define MAXSUFFIXCLASS (sizeof (suffixclass) / sizeof (struct suffix_classes))
665f210c2aSfgsch 
675f210c2aSfgsch const struct syntax_classes {
685f210c2aSfgsch   char *name;
695f210c2aSfgsch   int  len;
705f210c2aSfgsch   int  class;
715f210c2aSfgsch } syntaxclass[] = {
725f210c2aSfgsch   { "SYNTAX_3OP|OP1_MUST_BE_IMM", 26, SYNTAX_3OP|OP1_MUST_BE_IMM|SYNTAX_VALID },
735f210c2aSfgsch   { "OP1_MUST_BE_IMM|SYNTAX_3OP", 26, OP1_MUST_BE_IMM|SYNTAX_3OP|SYNTAX_VALID },
745f210c2aSfgsch   { "SYNTAX_2OP|OP1_IMM_IMPLIED", 26, SYNTAX_2OP|OP1_IMM_IMPLIED|SYNTAX_VALID },
755f210c2aSfgsch   { "OP1_IMM_IMPLIED|SYNTAX_2OP", 26, OP1_IMM_IMPLIED|SYNTAX_2OP|SYNTAX_VALID },
765f210c2aSfgsch   { "SYNTAX_3OP",                 10, SYNTAX_3OP|SYNTAX_VALID },
775f210c2aSfgsch   { "SYNTAX_2OP",                 10, SYNTAX_2OP|SYNTAX_VALID }
785f210c2aSfgsch };
795f210c2aSfgsch 
805f210c2aSfgsch #define MAXSYNTAXCLASS (sizeof (syntaxclass) / sizeof (struct syntax_classes))
815f210c2aSfgsch 
825f210c2aSfgsch const pseudo_typeS md_pseudo_table[] = {
835f210c2aSfgsch   { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0).  */
845f210c2aSfgsch   { "comm", arc_common, 0 },
85f7cc78ecSespie   { "common", arc_common, 0 },
865f210c2aSfgsch   { "lcomm", arc_common, 1 },
875f210c2aSfgsch   { "lcommon", arc_common, 1 },
885f210c2aSfgsch   { "2byte", cons, 2 },
895f210c2aSfgsch   { "half", cons, 2 },
905f210c2aSfgsch   { "short", cons, 2 },
915f210c2aSfgsch   { "3byte", cons, 3 },
925f210c2aSfgsch   { "4byte", cons, 4 },
93f7cc78ecSespie   { "word", cons, 4 },
945f210c2aSfgsch   { "option", arc_option, 0 },
955f210c2aSfgsch   { "cpu", arc_option, 0 },
965f210c2aSfgsch   { "block", s_space, 0 },
975f210c2aSfgsch   { "extcondcode", arc_extoper, 0 },
985f210c2aSfgsch   { "extcoreregister", arc_extoper, 1 },
995f210c2aSfgsch   { "extauxregister", arc_extoper, 2 },
1005f210c2aSfgsch   { "extinstruction", arc_extinst, 0 },
101f7cc78ecSespie   { NULL, 0, 0 },
102f7cc78ecSespie };
103f7cc78ecSespie 
104f7cc78ecSespie /* This array holds the chars that always start a comment.  If the
1055f210c2aSfgsch    pre-processor is disabled, these aren't very useful.  */
106f7cc78ecSespie const char comment_chars[] = "#;";
107f7cc78ecSespie 
108f7cc78ecSespie /* This array holds the chars that only start a comment at the beginning of
109f7cc78ecSespie    a line.  If the line seems to have the form '# 123 filename'
110f7cc78ecSespie    .line and .file directives will appear in the pre-processed output */
111f7cc78ecSespie /* Note that input_file.c hand checks for '#' at the beginning of the
112f7cc78ecSespie    first line of the input file.  This is because the compiler outputs
113f7cc78ecSespie    #NO_APP at the beginning of its output.  */
114f7cc78ecSespie /* Also note that comments started like this one will always
115f7cc78ecSespie    work if '/' isn't otherwise defined.  */
116f7cc78ecSespie const char line_comment_chars[] = "#";
117f7cc78ecSespie 
118f7cc78ecSespie const char line_separator_chars[] = "";
119f7cc78ecSespie 
1205f210c2aSfgsch /* Chars that can be used to separate mant from exp in floating point nums.  */
121f7cc78ecSespie const char EXP_CHARS[] = "eE";
122f7cc78ecSespie 
1235f210c2aSfgsch /* Chars that mean this number is a floating point constant
1245f210c2aSfgsch    As in 0f12.456 or 0d1.2345e12.  */
125f7cc78ecSespie const char FLT_CHARS[] = "rRsSfFdD";
126f7cc78ecSespie 
127f7cc78ecSespie /* Byte order.  */
128f7cc78ecSespie extern int target_big_endian;
129f7cc78ecSespie const char *arc_target_format = DEFAULT_TARGET_FORMAT;
130f7cc78ecSespie static int byte_order = DEFAULT_BYTE_ORDER;
131f7cc78ecSespie 
1325f210c2aSfgsch static segT arcext_section;
1335f210c2aSfgsch 
1345f210c2aSfgsch /* One of bfd_mach_arc_n.  */
1355f210c2aSfgsch static int arc_mach_type = bfd_mach_arc_6;
136f7cc78ecSespie 
137f7cc78ecSespie /* Non-zero if the cpu type has been explicitly specified.  */
138f7cc78ecSespie static int mach_type_specified_p = 0;
139f7cc78ecSespie 
140f7cc78ecSespie /* Non-zero if opcode tables have been initialized.
1415f210c2aSfgsch    A .option command must appear before any instructions.  */
142f7cc78ecSespie static int cpu_tables_init_p = 0;
143f7cc78ecSespie 
144f7cc78ecSespie static struct hash_control *arc_suffix_hash = NULL;
145f7cc78ecSespie 
146f7cc78ecSespie const char *md_shortopts = "";
1475f210c2aSfgsch struct option md_longopts[] = {
148f7cc78ecSespie #define OPTION_EB (OPTION_MD_BASE + 0)
149f7cc78ecSespie   { "EB", no_argument, NULL, OPTION_EB },
150f7cc78ecSespie #define OPTION_EL (OPTION_MD_BASE + 1)
151f7cc78ecSespie   { "EL", no_argument, NULL, OPTION_EL },
1525f210c2aSfgsch #define OPTION_ARC5 (OPTION_MD_BASE + 2)
1535f210c2aSfgsch   { "marc5", no_argument, NULL, OPTION_ARC5 },
1545f210c2aSfgsch   { "pre-v6", no_argument, NULL, OPTION_ARC5 },
1555f210c2aSfgsch #define OPTION_ARC6 (OPTION_MD_BASE + 3)
1565f210c2aSfgsch   { "marc6", no_argument, NULL, OPTION_ARC6 },
1575f210c2aSfgsch #define OPTION_ARC7 (OPTION_MD_BASE + 4)
1585f210c2aSfgsch   { "marc7", no_argument, NULL, OPTION_ARC7 },
1595f210c2aSfgsch #define OPTION_ARC8 (OPTION_MD_BASE + 5)
1605f210c2aSfgsch   { "marc8", no_argument, NULL, OPTION_ARC8 },
1615f210c2aSfgsch #define OPTION_ARC (OPTION_MD_BASE + 6)
1625f210c2aSfgsch   { "marc", no_argument, NULL, OPTION_ARC },
163f7cc78ecSespie   { NULL, no_argument, NULL, 0 }
164f7cc78ecSespie };
165f7cc78ecSespie size_t md_longopts_size = sizeof (md_longopts);
166f7cc78ecSespie 
1675f210c2aSfgsch #define IS_SYMBOL_OPERAND(o) \
1685f210c2aSfgsch  ((o) == 'b' || (o) == 'c' || (o) == 's' || (o) == 'o' || (o) == 'O')
1695f210c2aSfgsch 
1705f210c2aSfgsch struct arc_operand_value *get_ext_suffix (char *s);
1715f210c2aSfgsch 
1725f210c2aSfgsch /* Invocation line includes a switch not recognized by the base assembler.
1735f210c2aSfgsch    See if it's a processor-specific option.  */
174f7cc78ecSespie 
175f7cc78ecSespie int
md_parse_option(c,arg)176f7cc78ecSespie md_parse_option (c, arg)
177f7cc78ecSespie      int c;
1785f210c2aSfgsch      char *arg ATTRIBUTE_UNUSED;
179f7cc78ecSespie {
180f7cc78ecSespie   switch (c)
181f7cc78ecSespie     {
1825f210c2aSfgsch     case OPTION_ARC5:
1835f210c2aSfgsch       arc_mach_type = bfd_mach_arc_5;
1845f210c2aSfgsch       break;
1855f210c2aSfgsch     case OPTION_ARC:
1865f210c2aSfgsch     case OPTION_ARC6:
1875f210c2aSfgsch       arc_mach_type = bfd_mach_arc_6;
1885f210c2aSfgsch       break;
1895f210c2aSfgsch     case OPTION_ARC7:
1905f210c2aSfgsch       arc_mach_type = bfd_mach_arc_7;
1915f210c2aSfgsch       break;
1925f210c2aSfgsch     case OPTION_ARC8:
1935f210c2aSfgsch       arc_mach_type = bfd_mach_arc_8;
1945f210c2aSfgsch       break;
195f7cc78ecSespie     case OPTION_EB:
196f7cc78ecSespie       byte_order = BIG_ENDIAN;
197f7cc78ecSespie       arc_target_format = "elf32-bigarc";
198f7cc78ecSespie       break;
199f7cc78ecSespie     case OPTION_EL:
200f7cc78ecSespie       byte_order = LITTLE_ENDIAN;
201f7cc78ecSespie       arc_target_format = "elf32-littlearc";
202f7cc78ecSespie       break;
203f7cc78ecSespie     default:
204f7cc78ecSespie       return 0;
205f7cc78ecSespie     }
206f7cc78ecSespie   return 1;
207f7cc78ecSespie }
208f7cc78ecSespie 
209f7cc78ecSespie void
md_show_usage(stream)210f7cc78ecSespie md_show_usage (stream)
211f7cc78ecSespie      FILE *stream;
212f7cc78ecSespie {
2135f210c2aSfgsch   fprintf (stream, "\
2145f210c2aSfgsch ARC Options:\n\
2155f210c2aSfgsch   -marc[5|6|7|8]          select processor variant (default arc%d)\n\
2165f210c2aSfgsch   -EB                     assemble code for a big endian cpu\n\
2175f210c2aSfgsch   -EL                     assemble code for a little endian cpu\n", arc_mach_type + 5);
218f7cc78ecSespie }
219f7cc78ecSespie 
220f7cc78ecSespie /* This function is called once, at assembler startup time.  It should
221f7cc78ecSespie    set up all the tables, etc. that the MD part of the assembler will need.
2225f210c2aSfgsch    Opcode selection is deferred until later because we might see a .option
223f7cc78ecSespie    command.  */
224f7cc78ecSespie 
225f7cc78ecSespie void
md_begin()226f7cc78ecSespie md_begin ()
227f7cc78ecSespie {
228f7cc78ecSespie   /* The endianness can be chosen "at the factory".  */
229f7cc78ecSespie   target_big_endian = byte_order == BIG_ENDIAN;
230f7cc78ecSespie 
231f7cc78ecSespie   if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, arc_mach_type))
2325f210c2aSfgsch     as_warn ("could not set architecture and machine");
233f7cc78ecSespie 
2345f210c2aSfgsch   /* This call is necessary because we need to initialize `arc_operand_map'
2355f210c2aSfgsch      which may be needed before we see the first insn.  */
2365f210c2aSfgsch   arc_opcode_init_tables (arc_get_opcode_mach (arc_mach_type,
237f7cc78ecSespie 					       target_big_endian));
238f7cc78ecSespie }
239f7cc78ecSespie 
240f7cc78ecSespie /* Initialize the various opcode and operand tables.
241f7cc78ecSespie    MACH is one of bfd_mach_arc_xxx.  */
242f7cc78ecSespie static void
init_opcode_tables(mach)243f7cc78ecSespie init_opcode_tables (mach)
244f7cc78ecSespie      int mach;
245f7cc78ecSespie {
2465f210c2aSfgsch   int i;
247f7cc78ecSespie   char *last;
248f7cc78ecSespie 
249f7cc78ecSespie   if ((arc_suffix_hash = hash_new ()) == NULL)
2505f210c2aSfgsch     as_fatal ("virtual memory exhausted");
251f7cc78ecSespie 
252f7cc78ecSespie   if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach))
2535f210c2aSfgsch     as_warn ("could not set architecture and machine");
254f7cc78ecSespie 
255f7cc78ecSespie   /* This initializes a few things in arc-opc.c that we need.
256f7cc78ecSespie      This must be called before the various arc_xxx_supported fns.  */
257f7cc78ecSespie   arc_opcode_init_tables (arc_get_opcode_mach (mach, target_big_endian));
258f7cc78ecSespie 
259f7cc78ecSespie   /* Only put the first entry of each equivalently named suffix in the
260f7cc78ecSespie      table.  */
261f7cc78ecSespie   last = "";
262f7cc78ecSespie   for (i = 0; i < arc_suffixes_count; i++)
263f7cc78ecSespie     {
264f7cc78ecSespie       if (strcmp (arc_suffixes[i].name, last) != 0)
265f7cc78ecSespie 	hash_insert (arc_suffix_hash, arc_suffixes[i].name, (PTR) (arc_suffixes + i));
266f7cc78ecSespie       last = arc_suffixes[i].name;
267f7cc78ecSespie     }
268f7cc78ecSespie 
269f7cc78ecSespie   /* Since registers don't have a prefix, we put them in the symbol table so
270f7cc78ecSespie      they can't be used as symbols.  This also simplifies argument parsing as
271f7cc78ecSespie      we can let gas parse registers for us.  The recorded register number is
2725f210c2aSfgsch      the address of the register's entry in arc_reg_names.
2735f210c2aSfgsch 
2745f210c2aSfgsch      If the register name is already in the table, then the existing
2755f210c2aSfgsch      definition is assumed to be from an .ExtCoreRegister pseudo-op.  */
2765f210c2aSfgsch 
277f7cc78ecSespie   for (i = 0; i < arc_reg_names_count; i++)
278f7cc78ecSespie     {
2795f210c2aSfgsch       if (symbol_find (arc_reg_names[i].name))
280f7cc78ecSespie 	continue;
281f7cc78ecSespie       /* Use symbol_create here instead of symbol_new so we don't try to
282f7cc78ecSespie 	 output registers into the object file's symbol table.  */
2835f210c2aSfgsch       symbol_table_insert (symbol_create (arc_reg_names[i].name,
2845f210c2aSfgsch 					  reg_section,
2855f210c2aSfgsch 					  (int) &arc_reg_names[i],
2865f210c2aSfgsch 					  &zero_address_frag));
287f7cc78ecSespie     }
288f7cc78ecSespie 
2895f210c2aSfgsch   /* Tell `.option' it's too late.  */
290f7cc78ecSespie   cpu_tables_init_p = 1;
291f7cc78ecSespie }
292f7cc78ecSespie 
293f7cc78ecSespie /* Insert an operand value into an instruction.
294f7cc78ecSespie    If REG is non-NULL, it is a register number and ignore VAL.  */
295f7cc78ecSespie 
296f7cc78ecSespie static arc_insn
arc_insert_operand(insn,operand,mods,reg,val,file,line)297f7cc78ecSespie arc_insert_operand (insn, operand, mods, reg, val, file, line)
298f7cc78ecSespie      arc_insn insn;
299f7cc78ecSespie      const struct arc_operand *operand;
300f7cc78ecSespie      int mods;
301f7cc78ecSespie      const struct arc_operand_value *reg;
302f7cc78ecSespie      offsetT val;
303f7cc78ecSespie      char *file;
304f7cc78ecSespie      unsigned int line;
305f7cc78ecSespie {
306f7cc78ecSespie   if (operand->bits != 32)
307f7cc78ecSespie     {
308f7cc78ecSespie       long min, max;
309f7cc78ecSespie       offsetT test;
310f7cc78ecSespie 
311f7cc78ecSespie       if ((operand->flags & ARC_OPERAND_SIGNED) != 0)
312f7cc78ecSespie 	{
313f7cc78ecSespie 	  if ((operand->flags & ARC_OPERAND_SIGNOPT) != 0)
314f7cc78ecSespie 	    max = (1 << operand->bits) - 1;
315f7cc78ecSespie 	  else
316f7cc78ecSespie 	    max = (1 << (operand->bits - 1)) - 1;
317f7cc78ecSespie 	  min = - (1 << (operand->bits - 1));
318f7cc78ecSespie 	}
319f7cc78ecSespie       else
320f7cc78ecSespie 	{
321f7cc78ecSespie 	  max = (1 << operand->bits) - 1;
322f7cc78ecSespie 	  min = 0;
323f7cc78ecSespie 	}
324f7cc78ecSespie 
325f7cc78ecSespie       if ((operand->flags & ARC_OPERAND_NEGATIVE) != 0)
326f7cc78ecSespie 	test = - val;
327f7cc78ecSespie       else
328f7cc78ecSespie 	test = val;
329f7cc78ecSespie 
330f7cc78ecSespie       if (test < (offsetT) min || test > (offsetT) max)
331f7cc78ecSespie 	{
332f7cc78ecSespie 	  const char *err =
3335f210c2aSfgsch 	    "operand out of range (%s not between %ld and %ld)";
334f7cc78ecSespie 	  char buf[100];
335f7cc78ecSespie 
336f7cc78ecSespie 	  sprint_value (buf, test);
337f7cc78ecSespie 	  if (file == (char *) NULL)
338f7cc78ecSespie 	    as_warn (err, buf, min, max);
339f7cc78ecSespie 	  else
340f7cc78ecSespie 	    as_warn_where (file, line, err, buf, min, max);
341f7cc78ecSespie 	}
342f7cc78ecSespie     }
343f7cc78ecSespie 
344f7cc78ecSespie   if (operand->insert)
345f7cc78ecSespie     {
346f7cc78ecSespie       const char *errmsg;
347f7cc78ecSespie 
348f7cc78ecSespie       errmsg = NULL;
349f7cc78ecSespie       insn = (*operand->insert) (insn, operand, mods, reg, (long) val, &errmsg);
350f7cc78ecSespie       if (errmsg != (const char *) NULL)
351f7cc78ecSespie 	as_warn (errmsg);
352f7cc78ecSespie     }
353f7cc78ecSespie   else
354f7cc78ecSespie     insn |= (((long) val & ((1 << operand->bits) - 1))
355f7cc78ecSespie 	     << operand->shift);
356f7cc78ecSespie 
357f7cc78ecSespie   return insn;
358f7cc78ecSespie }
359f7cc78ecSespie 
360f7cc78ecSespie /* We need to keep a list of fixups.  We can't simply generate them as
361f7cc78ecSespie    we go, because that would require us to first create the frag, and
362f7cc78ecSespie    that would screw up references to ``.''.  */
363f7cc78ecSespie 
3645f210c2aSfgsch struct arc_fixup {
365f7cc78ecSespie   /* index into `arc_operands'  */
366f7cc78ecSespie   int opindex;
367f7cc78ecSespie   expressionS exp;
368f7cc78ecSespie };
369f7cc78ecSespie 
370f7cc78ecSespie #define MAX_FIXUPS 5
371f7cc78ecSespie 
372f7cc78ecSespie #define MAX_SUFFIXES 5
373f7cc78ecSespie 
374f7cc78ecSespie /* This routine is called for each instruction to be assembled.  */
375f7cc78ecSespie 
376f7cc78ecSespie void
md_assemble(str)377f7cc78ecSespie md_assemble (str)
378f7cc78ecSespie      char *str;
379f7cc78ecSespie {
380f7cc78ecSespie   const struct arc_opcode *opcode;
3815f210c2aSfgsch   const struct arc_opcode *std_opcode;
3825f210c2aSfgsch   struct arc_opcode *ext_opcode;
383f7cc78ecSespie   char *start;
3845f210c2aSfgsch   const char *last_errmsg = 0;
385f7cc78ecSespie   arc_insn insn;
386f7cc78ecSespie   static int init_tables_p = 0;
387f7cc78ecSespie 
388f7cc78ecSespie   /* Opcode table initialization is deferred until here because we have to
3895f210c2aSfgsch      wait for a possible .option command.  */
390f7cc78ecSespie   if (!init_tables_p)
391f7cc78ecSespie     {
392f7cc78ecSespie       init_opcode_tables (arc_mach_type);
393f7cc78ecSespie       init_tables_p = 1;
394f7cc78ecSespie     }
395f7cc78ecSespie 
396f7cc78ecSespie   /* Skip leading white space.  */
397d2201f2fSdrahn   while (ISSPACE (*str))
398f7cc78ecSespie     str++;
399f7cc78ecSespie 
400f7cc78ecSespie   /* The instructions are stored in lists hashed by the first letter (though
401f7cc78ecSespie      we needn't care how they're hashed).  Get the first in the list.  */
402f7cc78ecSespie 
4035f210c2aSfgsch   ext_opcode = arc_ext_opcodes;
4045f210c2aSfgsch   std_opcode = arc_opcode_lookup_asm (str);
405f7cc78ecSespie 
406f7cc78ecSespie   /* Keep looking until we find a match.  */
407f7cc78ecSespie 
408f7cc78ecSespie   start = str;
4095f210c2aSfgsch   for (opcode = (ext_opcode ? ext_opcode : std_opcode);
4105f210c2aSfgsch        opcode != NULL;
4115f210c2aSfgsch        opcode = (ARC_OPCODE_NEXT_ASM (opcode)
4125f210c2aSfgsch 		 ? ARC_OPCODE_NEXT_ASM (opcode)
4135f210c2aSfgsch 		 : (ext_opcode ? ext_opcode = NULL, std_opcode : NULL)))
414f7cc78ecSespie     {
415f7cc78ecSespie       int past_opcode_p, fc, num_suffixes;
4165f210c2aSfgsch       int fix_up_at = 0;
417f7cc78ecSespie       char *syn;
418f7cc78ecSespie       struct arc_fixup fixups[MAX_FIXUPS];
419f7cc78ecSespie       /* Used as a sanity check.  If we need a limm reloc, make sure we ask
420f7cc78ecSespie 	 for an extra 4 bytes from frag_more.  */
421f7cc78ecSespie       int limm_reloc_p;
4225f210c2aSfgsch       int ext_suffix_p;
423f7cc78ecSespie       const struct arc_operand_value *insn_suffixes[MAX_SUFFIXES];
424f7cc78ecSespie 
425f7cc78ecSespie       /* Is this opcode supported by the selected cpu?  */
426f7cc78ecSespie       if (! arc_opcode_supported (opcode))
427f7cc78ecSespie 	continue;
428f7cc78ecSespie 
429f7cc78ecSespie       /* Scan the syntax string.  If it doesn't match, try the next one.  */
430f7cc78ecSespie 
431f7cc78ecSespie       arc_opcode_init_insert ();
432f7cc78ecSespie       insn = opcode->value;
433f7cc78ecSespie       fc = 0;
434f7cc78ecSespie       past_opcode_p = 0;
435f7cc78ecSespie       num_suffixes = 0;
436f7cc78ecSespie       limm_reloc_p = 0;
4375f210c2aSfgsch       ext_suffix_p = 0;
438f7cc78ecSespie 
439f7cc78ecSespie       /* We don't check for (*str != '\0') here because we want to parse
440f7cc78ecSespie 	 any trailing fake arguments in the syntax string.  */
441f7cc78ecSespie       for (str = start, syn = opcode->syntax; *syn != '\0';)
442f7cc78ecSespie 	{
443f7cc78ecSespie 	  int mods;
444f7cc78ecSespie 	  const struct arc_operand *operand;
445f7cc78ecSespie 
446f7cc78ecSespie 	  /* Non operand chars must match exactly.  */
447f7cc78ecSespie 	  if (*syn != '%' || *++syn == '%')
448f7cc78ecSespie 	    {
449f7cc78ecSespie 	      /* Handle '+' specially as we want to allow "ld r0,[sp-4]".  */
450f7cc78ecSespie 	      /* ??? The syntax has changed to [sp,-4].  */
451f7cc78ecSespie 	      if (0 && *syn == '+' && *str == '-')
452f7cc78ecSespie 		{
453f7cc78ecSespie 		  /* Skip over syn's +, but leave str's - alone.
454f7cc78ecSespie 		     That makes the case identical to "ld r0,[sp+-4]".  */
455f7cc78ecSespie 		  ++syn;
456f7cc78ecSespie 		}
457f7cc78ecSespie 	      else if (*str == *syn)
458f7cc78ecSespie 		{
459f7cc78ecSespie 		  if (*syn == ' ')
460f7cc78ecSespie 		    past_opcode_p = 1;
461f7cc78ecSespie 		  ++syn;
462f7cc78ecSespie 		  ++str;
463f7cc78ecSespie 		}
464f7cc78ecSespie 	      else
465f7cc78ecSespie 		break;
466f7cc78ecSespie 	      continue;
467f7cc78ecSespie 	    }
468f7cc78ecSespie 
469f7cc78ecSespie 	  /* We have an operand.  Pick out any modifiers.  */
470f7cc78ecSespie 	  mods = 0;
4715f210c2aSfgsch 	  while (ARC_MOD_P (arc_operands[arc_operand_map[(int) *syn]].flags))
472f7cc78ecSespie 	    {
4735f210c2aSfgsch 	      mods |= arc_operands[arc_operand_map[(int) *syn]].flags & ARC_MOD_BITS;
474f7cc78ecSespie 	      ++syn;
475f7cc78ecSespie 	    }
4765f210c2aSfgsch 	  operand = arc_operands + arc_operand_map[(int) *syn];
477f7cc78ecSespie 	  if (operand->fmt == 0)
4785f210c2aSfgsch 	    as_fatal ("unknown syntax format character `%c'", *syn);
479f7cc78ecSespie 
480f7cc78ecSespie 	  if (operand->flags & ARC_OPERAND_FAKE)
481f7cc78ecSespie 	    {
482f7cc78ecSespie 	      const char *errmsg = NULL;
483f7cc78ecSespie 	      if (operand->insert)
484f7cc78ecSespie 		{
485f7cc78ecSespie 		  insn = (*operand->insert) (insn, operand, mods, NULL, 0, &errmsg);
4865f210c2aSfgsch 		  if (errmsg != (const char *) NULL)
4875f210c2aSfgsch 		    {
4885f210c2aSfgsch 		      last_errmsg = errmsg;
4895f210c2aSfgsch 		      if (operand->flags & ARC_OPERAND_ERROR)
4905f210c2aSfgsch 			{
4915f210c2aSfgsch 			  as_bad (errmsg);
4925f210c2aSfgsch 			  return;
4935f210c2aSfgsch 			}
4945f210c2aSfgsch 		      else if (operand->flags & ARC_OPERAND_WARN)
4955f210c2aSfgsch 			as_warn (errmsg);
496f7cc78ecSespie 		      break;
497f7cc78ecSespie 		    }
4985f210c2aSfgsch 		  if (limm_reloc_p
4995f210c2aSfgsch 		      && (operand->flags && operand->flags & ARC_OPERAND_LIMM)
5005f210c2aSfgsch 		      && (operand->flags &
5015f210c2aSfgsch 			  (ARC_OPERAND_ABSOLUTE_BRANCH | ARC_OPERAND_ADDRESS)))
5025f210c2aSfgsch 		    {
5035f210c2aSfgsch 		      fixups[fix_up_at].opindex = arc_operand_map[operand->fmt];
5045f210c2aSfgsch 		    }
5055f210c2aSfgsch 		}
506f7cc78ecSespie 	      ++syn;
507f7cc78ecSespie 	    }
508f7cc78ecSespie 	  /* Are we finished with suffixes?  */
509f7cc78ecSespie 	  else if (!past_opcode_p)
510f7cc78ecSespie 	    {
511f7cc78ecSespie 	      int found;
512f7cc78ecSespie 	      char c;
513f7cc78ecSespie 	      char *s, *t;
5145f210c2aSfgsch 	      const struct arc_operand_value *suf, *suffix_end;
5155f210c2aSfgsch 	      const struct arc_operand_value *suffix = NULL;
516f7cc78ecSespie 
517f7cc78ecSespie 	      if (!(operand->flags & ARC_OPERAND_SUFFIX))
518f7cc78ecSespie 		abort ();
519f7cc78ecSespie 
520f7cc78ecSespie 	      /* If we're at a space in the input string, we want to skip the
521f7cc78ecSespie 		 remaining suffixes.  There may be some fake ones though, so
522f7cc78ecSespie 		 just go on to try the next one.  */
523f7cc78ecSespie 	      if (*str == ' ')
524f7cc78ecSespie 		{
525f7cc78ecSespie 		  ++syn;
526f7cc78ecSespie 		  continue;
527f7cc78ecSespie 		}
528f7cc78ecSespie 
529f7cc78ecSespie 	      s = str;
530f7cc78ecSespie 	      if (mods & ARC_MOD_DOT)
531f7cc78ecSespie 		{
532f7cc78ecSespie 		  if (*s != '.')
533f7cc78ecSespie 		    break;
534f7cc78ecSespie 		  ++s;
535f7cc78ecSespie 		}
536f7cc78ecSespie 	      else
537f7cc78ecSespie 		{
538f7cc78ecSespie 		  /* This can happen in "b.nd foo" and we're currently looking
539f7cc78ecSespie 		     for "%q" (ie: a condition code suffix).  */
540f7cc78ecSespie 		  if (*s == '.')
541f7cc78ecSespie 		    {
542f7cc78ecSespie 		      ++syn;
543f7cc78ecSespie 		      continue;
544f7cc78ecSespie 		    }
545f7cc78ecSespie 		}
546f7cc78ecSespie 
547f7cc78ecSespie 	      /* Pick the suffix out and look it up via the hash table.  */
548d2201f2fSdrahn 	      for (t = s; *t && ISALNUM (*t); ++t)
549f7cc78ecSespie 		continue;
550f7cc78ecSespie 	      c = *t;
551f7cc78ecSespie 	      *t = '\0';
5525f210c2aSfgsch 	      if ((suf = get_ext_suffix (s)))
5535f210c2aSfgsch 		ext_suffix_p = 1;
5545f210c2aSfgsch 	      else
555f7cc78ecSespie 		suf = hash_find (arc_suffix_hash, s);
556f7cc78ecSespie 	      if (!suf)
557f7cc78ecSespie 		{
558f7cc78ecSespie 		  /* This can happen in "blle foo" and we're currently using
559f7cc78ecSespie 		     the template "b%q%.n %j".  The "bl" insn occurs later in
560f7cc78ecSespie 		     the table so "lle" isn't an illegal suffix.  */
5615f210c2aSfgsch 		  *t = c;
562f7cc78ecSespie 		  break;
563f7cc78ecSespie 		}
564f7cc78ecSespie 
565f7cc78ecSespie 	      /* Is it the right type?  Note that the same character is used
566f7cc78ecSespie 		 several times, so we have to examine all of them.  This is
567f7cc78ecSespie 		 relatively efficient as equivalent entries are kept
568f7cc78ecSespie 		 together.  If it's not the right type, don't increment `str'
569f7cc78ecSespie 		 so we try the next one in the series.  */
570f7cc78ecSespie 	      found = 0;
5715f210c2aSfgsch 	      if (ext_suffix_p && arc_operands[suf->type].fmt == *syn)
5725f210c2aSfgsch 		{
5735f210c2aSfgsch 		  /* Insert the suffix's value into the insn.  */
5745f210c2aSfgsch 		  *t = c;
5755f210c2aSfgsch 		  if (operand->insert)
5765f210c2aSfgsch 		    insn = (*operand->insert) (insn, operand,
5775f210c2aSfgsch 					       mods, NULL, suf->value,
5785f210c2aSfgsch 					       NULL);
5795f210c2aSfgsch 		  else
5805f210c2aSfgsch 		    insn |= suf->value << operand->shift;
5815f210c2aSfgsch 
5825f210c2aSfgsch 		  str = t;
5835f210c2aSfgsch 		  found = 1;
5845f210c2aSfgsch 		}
5855f210c2aSfgsch 	      else
5865f210c2aSfgsch 		{
5875f210c2aSfgsch 		  *t = c;
588f7cc78ecSespie 		  suffix_end = arc_suffixes + arc_suffixes_count;
589f7cc78ecSespie 		  for (suffix = suf;
590f7cc78ecSespie 		       suffix < suffix_end && strcmp (suffix->name, suf->name) == 0;
591f7cc78ecSespie 		       ++suffix)
592f7cc78ecSespie 		    {
593f7cc78ecSespie 		      if (arc_operands[suffix->type].fmt == *syn)
594f7cc78ecSespie 			{
595f7cc78ecSespie 			  /* Insert the suffix's value into the insn.  */
596f7cc78ecSespie 			  if (operand->insert)
597f7cc78ecSespie 			    insn = (*operand->insert) (insn, operand,
598f7cc78ecSespie 						       mods, NULL, suffix->value,
599f7cc78ecSespie 						       NULL);
600f7cc78ecSespie 			  else
601f7cc78ecSespie 			    insn |= suffix->value << operand->shift;
602f7cc78ecSespie 
603f7cc78ecSespie 			  str = t;
604f7cc78ecSespie 			  found = 1;
605f7cc78ecSespie 			  break;
606f7cc78ecSespie 			}
607f7cc78ecSespie 		    }
6085f210c2aSfgsch 		}
609f7cc78ecSespie 	      ++syn;
610f7cc78ecSespie 	      if (!found)
6115f210c2aSfgsch 		/* Wrong type.  Just go on to try next insn entry.  */
6125f210c2aSfgsch 		;
613f7cc78ecSespie 	      else
614f7cc78ecSespie 		{
615f7cc78ecSespie 		  if (num_suffixes == MAX_SUFFIXES)
6165f210c2aSfgsch 		    as_bad ("too many suffixes");
617f7cc78ecSespie 		  else
618f7cc78ecSespie 		    insn_suffixes[num_suffixes++] = suffix;
619f7cc78ecSespie 		}
620f7cc78ecSespie 	    }
621f7cc78ecSespie 	  else
622f7cc78ecSespie 	    /* This is either a register or an expression of some kind.  */
623f7cc78ecSespie 	    {
624f7cc78ecSespie 	      char *hold;
625f7cc78ecSespie 	      const struct arc_operand_value *reg = NULL;
626f7cc78ecSespie 	      long value = 0;
627f7cc78ecSespie 	      expressionS exp;
628f7cc78ecSespie 
629f7cc78ecSespie 	      if (operand->flags & ARC_OPERAND_SUFFIX)
630f7cc78ecSespie 		abort ();
631f7cc78ecSespie 
632f7cc78ecSespie 	      /* Is there anything left to parse?
633f7cc78ecSespie 		 We don't check for this at the top because we want to parse
634f7cc78ecSespie 		 any trailing fake arguments in the syntax string.  */
6355f210c2aSfgsch 	      if (is_end_of_line[(unsigned char) *str])
636f7cc78ecSespie 		break;
637f7cc78ecSespie 
638f7cc78ecSespie 	      /* Parse the operand.  */
639f7cc78ecSespie 	      hold = input_line_pointer;
640f7cc78ecSespie 	      input_line_pointer = str;
641f7cc78ecSespie 	      expression (&exp);
642f7cc78ecSespie 	      str = input_line_pointer;
643f7cc78ecSespie 	      input_line_pointer = hold;
644f7cc78ecSespie 
645f7cc78ecSespie 	      if (exp.X_op == O_illegal)
6465f210c2aSfgsch 		as_bad ("illegal operand");
647f7cc78ecSespie 	      else if (exp.X_op == O_absent)
6485f210c2aSfgsch 		as_bad ("missing operand");
649f7cc78ecSespie 	      else if (exp.X_op == O_constant)
650f7cc78ecSespie 		{
651f7cc78ecSespie 		  value = exp.X_add_number;
652f7cc78ecSespie 		}
653f7cc78ecSespie 	      else if (exp.X_op == O_register)
654f7cc78ecSespie 		{
6555f210c2aSfgsch 		  reg = (struct arc_operand_value *) exp.X_add_number;
656f7cc78ecSespie 		}
6575f210c2aSfgsch #define IS_REG_DEST_OPERAND(o) ((o) == 'a')
6585f210c2aSfgsch 	      else if (IS_REG_DEST_OPERAND (*syn))
6595f210c2aSfgsch 		as_bad ("symbol as destination register");
660f7cc78ecSespie 	      else
661f7cc78ecSespie 		{
6625f210c2aSfgsch 		  if (!strncmp (str, "@h30", 4))
6635f210c2aSfgsch 		    {
6645f210c2aSfgsch 		      arc_code_symbol (&exp);
6655f210c2aSfgsch 		      str += 4;
6665f210c2aSfgsch 		    }
667f7cc78ecSespie 		  /* We need to generate a fixup for this expression.  */
668f7cc78ecSespie 		  if (fc >= MAX_FIXUPS)
6695f210c2aSfgsch 		    as_fatal ("too many fixups");
670f7cc78ecSespie 		  fixups[fc].exp = exp;
6715f210c2aSfgsch 		  /* We don't support shimm relocs. break here to force
6725f210c2aSfgsch 		     the assembler to output a limm.  */
6735f210c2aSfgsch #define IS_REG_SHIMM_OFFSET(o) ((o) == 'd')
6745f210c2aSfgsch 		  if (IS_REG_SHIMM_OFFSET (*syn))
6755f210c2aSfgsch 		    break;
676f7cc78ecSespie 		  /* If this is a register constant (IE: one whose
677f7cc78ecSespie 		     register value gets stored as 61-63) then this
6785f210c2aSfgsch 		     must be a limm.  */
679f7cc78ecSespie 		  /* ??? This bit could use some cleaning up.
680f7cc78ecSespie 		     Referencing the format chars like this goes
681f7cc78ecSespie 		     against style.  */
6825f210c2aSfgsch 		  if (IS_SYMBOL_OPERAND (*syn))
683f7cc78ecSespie 		    {
684f7cc78ecSespie 		      const char *junk;
685f7cc78ecSespie 		      limm_reloc_p = 1;
6865f210c2aSfgsch 		      /* Save this, we don't yet know what reloc to use.  */
6875f210c2aSfgsch 		      fix_up_at = fc;
688f7cc78ecSespie 		      /* Tell insert_reg we need a limm.  This is
689f7cc78ecSespie 			 needed because the value at this point is
690f7cc78ecSespie 			 zero, a shimm.  */
691f7cc78ecSespie 		      /* ??? We need a cleaner interface than this.  */
692f7cc78ecSespie 		      (*arc_operands[arc_operand_map['Q']].insert)
693f7cc78ecSespie 			(insn, operand, mods, reg, 0L, &junk);
694f7cc78ecSespie 		    }
695f7cc78ecSespie 		  else
6965f210c2aSfgsch 		    fixups[fc].opindex = arc_operand_map[(int) *syn];
697f7cc78ecSespie 		  ++fc;
698f7cc78ecSespie 		  value = 0;
699f7cc78ecSespie 		}
700f7cc78ecSespie 
701f7cc78ecSespie 	      /* Insert the register or expression into the instruction.  */
702f7cc78ecSespie 	      if (operand->insert)
703f7cc78ecSespie 		{
704f7cc78ecSespie 		  const char *errmsg = NULL;
705f7cc78ecSespie 		  insn = (*operand->insert) (insn, operand, mods,
706f7cc78ecSespie 					     reg, (long) value, &errmsg);
707f7cc78ecSespie 		  if (errmsg != (const char *) NULL)
7085f210c2aSfgsch 		    {
7095f210c2aSfgsch 		      last_errmsg = errmsg;
7105f210c2aSfgsch 		      if (operand->flags & ARC_OPERAND_ERROR)
7115f210c2aSfgsch 			{
7125f210c2aSfgsch 			  as_bad (errmsg);
7135f210c2aSfgsch 			  return;
7145f210c2aSfgsch 			}
7155f210c2aSfgsch 		      else if (operand->flags & ARC_OPERAND_WARN)
716f7cc78ecSespie 			as_warn (errmsg);
717f7cc78ecSespie 		      break;
718f7cc78ecSespie 		    }
7195f210c2aSfgsch 		}
720f7cc78ecSespie 	      else
721f7cc78ecSespie 		insn |= (value & ((1 << operand->bits) - 1)) << operand->shift;
722f7cc78ecSespie 
723f7cc78ecSespie 	      ++syn;
724f7cc78ecSespie 	    }
725f7cc78ecSespie 	}
726f7cc78ecSespie 
727f7cc78ecSespie       /* If we're at the end of the syntax string, we're done.  */
728f7cc78ecSespie       /* FIXME: try to move this to a separate function.  */
729f7cc78ecSespie       if (*syn == '\0')
730f7cc78ecSespie 	{
731f7cc78ecSespie 	  int i;
732f7cc78ecSespie 	  char *f;
733f7cc78ecSespie 	  long limm, limm_p;
734f7cc78ecSespie 
735f7cc78ecSespie 	  /* For the moment we assume a valid `str' can only contain blanks
736f7cc78ecSespie 	     now.  IE: We needn't try again with a longer version of the
737f7cc78ecSespie 	     insn and it is assumed that longer versions of insns appear
738f7cc78ecSespie 	     before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
739f7cc78ecSespie 
740d2201f2fSdrahn 	  while (ISSPACE (*str))
741f7cc78ecSespie 	    ++str;
742f7cc78ecSespie 
7435f210c2aSfgsch 	  if (!is_end_of_line[(unsigned char) *str])
7445f210c2aSfgsch 	    as_bad ("junk at end of line: `%s'", str);
745f7cc78ecSespie 
746f7cc78ecSespie 	  /* Is there a limm value?  */
747f7cc78ecSespie 	  limm_p = arc_opcode_limm_p (&limm);
748f7cc78ecSespie 
749f7cc78ecSespie 	  /* Perform various error and warning tests.  */
750f7cc78ecSespie 
751f7cc78ecSespie 	  {
752f7cc78ecSespie 	    static int in_delay_slot_p = 0;
753f7cc78ecSespie 	    static int prev_insn_needs_cc_nop_p = 0;
754f7cc78ecSespie 	    /* delay slot type seen */
755f7cc78ecSespie 	    int delay_slot_type = ARC_DELAY_NONE;
756f7cc78ecSespie 	    /* conditional execution flag seen */
757f7cc78ecSespie 	    int conditional = 0;
758f7cc78ecSespie 	    /* 1 if condition codes are being set */
759f7cc78ecSespie 	    int cc_set_p = 0;
760f7cc78ecSespie 	    /* 1 if conditional branch, including `b' "branch always" */
761f7cc78ecSespie 	    int cond_branch_p = opcode->flags & ARC_OPCODE_COND_BRANCH;
762f7cc78ecSespie 
763f7cc78ecSespie 	    for (i = 0; i < num_suffixes; ++i)
764f7cc78ecSespie 	      {
765f7cc78ecSespie 		switch (arc_operands[insn_suffixes[i]->type].fmt)
766f7cc78ecSespie 		  {
767f7cc78ecSespie 		  case 'n':
768f7cc78ecSespie 		    delay_slot_type = insn_suffixes[i]->value;
769f7cc78ecSespie 		    break;
770f7cc78ecSespie 		  case 'q':
771f7cc78ecSespie 		    conditional = insn_suffixes[i]->value;
772f7cc78ecSespie 		    break;
773f7cc78ecSespie 		  case 'f':
774f7cc78ecSespie 		    cc_set_p = 1;
775f7cc78ecSespie 		    break;
776f7cc78ecSespie 		  }
777f7cc78ecSespie 	      }
778f7cc78ecSespie 
779f7cc78ecSespie 	    /* Putting an insn with a limm value in a delay slot is supposed to
780f7cc78ecSespie 	       be legal, but let's warn the user anyway.  Ditto for 8 byte
781f7cc78ecSespie 	       jumps with delay slots.  */
782f7cc78ecSespie 	    if (in_delay_slot_p && limm_p)
7835f210c2aSfgsch 	      as_warn ("8 byte instruction in delay slot");
7845f210c2aSfgsch 	    if (delay_slot_type != ARC_DELAY_NONE
7855f210c2aSfgsch 		&& limm_p && arc_insn_not_jl (insn)) /* except for jl  addr */
7865f210c2aSfgsch 	      as_warn ("8 byte jump instruction with delay slot");
787f7cc78ecSespie 	    in_delay_slot_p = (delay_slot_type != ARC_DELAY_NONE) && !limm_p;
788f7cc78ecSespie 
789f7cc78ecSespie 	    /* Warn when a conditional branch immediately follows a set of
790f7cc78ecSespie 	       the condition codes.  Note that this needn't be done if the
791f7cc78ecSespie 	       insn that sets the condition codes uses a limm.  */
792f7cc78ecSespie 	    if (cond_branch_p && conditional != 0 /* 0 = "always" */
7935f210c2aSfgsch 		&& prev_insn_needs_cc_nop_p && arc_mach_type == bfd_mach_arc_5)
7945f210c2aSfgsch 	      as_warn ("conditional branch follows set of flags");
7955f210c2aSfgsch 	    prev_insn_needs_cc_nop_p =
7965f210c2aSfgsch 	      /* FIXME: ??? not required:
7975f210c2aSfgsch 		 (delay_slot_type != ARC_DELAY_NONE) &&  */
7985f210c2aSfgsch 	      cc_set_p && !limm_p;
799f7cc78ecSespie 	  }
800f7cc78ecSespie 
801f7cc78ecSespie 	  /* Write out the instruction.
802f7cc78ecSespie 	     It is important to fetch enough space in one call to `frag_more'.
803f7cc78ecSespie 	     We use (f - frag_now->fr_literal) to compute where we are and we
804f7cc78ecSespie 	     don't want frag_now to change between calls.  */
805f7cc78ecSespie 	  if (limm_p)
806f7cc78ecSespie 	    {
807f7cc78ecSespie 	      f = frag_more (8);
808f7cc78ecSespie 	      md_number_to_chars (f, insn, 4);
809f7cc78ecSespie 	      md_number_to_chars (f + 4, limm, 4);
8105f210c2aSfgsch 	      dwarf2_emit_insn (8);
811f7cc78ecSespie 	    }
812f7cc78ecSespie 	  else if (limm_reloc_p)
813f7cc78ecSespie 	    {
814f7cc78ecSespie 	      /* We need a limm reloc, but the tables think we don't.  */
815f7cc78ecSespie 	      abort ();
816f7cc78ecSespie 	    }
817f7cc78ecSespie 	  else
818f7cc78ecSespie 	    {
819f7cc78ecSespie 	      f = frag_more (4);
820f7cc78ecSespie 	      md_number_to_chars (f, insn, 4);
8215f210c2aSfgsch 	      dwarf2_emit_insn (4);
822f7cc78ecSespie 	    }
823f7cc78ecSespie 
824f7cc78ecSespie 	  /* Create any fixups.  */
825f7cc78ecSespie 	  for (i = 0; i < fc; ++i)
826f7cc78ecSespie 	    {
827f7cc78ecSespie 	      int op_type, reloc_type;
828f7cc78ecSespie 	      expressionS exptmp;
829f7cc78ecSespie 	      const struct arc_operand *operand;
830f7cc78ecSespie 
831f7cc78ecSespie 	      /* Create a fixup for this operand.
832f7cc78ecSespie 		 At this point we do not use a bfd_reloc_code_real_type for
833f7cc78ecSespie 		 operands residing in the insn, but instead just use the
834f7cc78ecSespie 		 operand index.  This lets us easily handle fixups for any
835f7cc78ecSespie 		 operand type, although that is admittedly not a very exciting
836d2201f2fSdrahn 		 feature.  We pick a BFD reloc type in md_apply_fix3.
837f7cc78ecSespie 
838f7cc78ecSespie 		 Limm values (4 byte immediate "constants") must be treated
839f7cc78ecSespie 		 normally because they're not part of the actual insn word
840f7cc78ecSespie 		 and thus the insertion routines don't handle them.  */
841f7cc78ecSespie 
842f7cc78ecSespie 	      if (arc_operands[fixups[i].opindex].flags & ARC_OPERAND_LIMM)
843f7cc78ecSespie 		{
8445f210c2aSfgsch 		  /* Modify the fixup addend as required by the cpu.  */
8455f210c2aSfgsch 		  fixups[i].exp.X_add_number += arc_limm_fixup_adjust (insn);
846f7cc78ecSespie 		  op_type = fixups[i].opindex;
847f7cc78ecSespie 		  /* FIXME: can we add this data to the operand table?  */
8485f210c2aSfgsch 		  if (op_type == arc_operand_map['L']
8495f210c2aSfgsch 		      || op_type == arc_operand_map['s']
8505f210c2aSfgsch 		      || op_type == arc_operand_map['o']
8515f210c2aSfgsch 		      || op_type == arc_operand_map['O'])
852f7cc78ecSespie 		    reloc_type = BFD_RELOC_32;
853f7cc78ecSespie 		  else if (op_type == arc_operand_map['J'])
854f7cc78ecSespie 		    reloc_type = BFD_RELOC_ARC_B26;
855f7cc78ecSespie 		  else
856f7cc78ecSespie 		    abort ();
857f7cc78ecSespie 		  reloc_type = get_arc_exp_reloc_type (1, reloc_type,
858f7cc78ecSespie 						       &fixups[i].exp,
859f7cc78ecSespie 						       &exptmp);
860f7cc78ecSespie 		}
861f7cc78ecSespie 	      else
862f7cc78ecSespie 		{
863f7cc78ecSespie 		  op_type = get_arc_exp_reloc_type (0, fixups[i].opindex,
864f7cc78ecSespie 						    &fixups[i].exp, &exptmp);
865f7cc78ecSespie 		  reloc_type = op_type + (int) BFD_RELOC_UNUSED;
866f7cc78ecSespie 		}
867f7cc78ecSespie 	      operand = &arc_operands[op_type];
868f7cc78ecSespie 	      fix_new_exp (frag_now,
869f7cc78ecSespie 			   ((f - frag_now->fr_literal)
870f7cc78ecSespie 			    + (operand->flags & ARC_OPERAND_LIMM ? 4 : 0)), 4,
871f7cc78ecSespie 			   &exptmp,
872f7cc78ecSespie 			   (operand->flags & ARC_OPERAND_RELATIVE_BRANCH) != 0,
873f7cc78ecSespie 			   (bfd_reloc_code_real_type) reloc_type);
874f7cc78ecSespie 	    }
875f7cc78ecSespie 
876f7cc78ecSespie 	  /* All done.  */
877f7cc78ecSespie 	  return;
878f7cc78ecSespie 	}
879f7cc78ecSespie 
880f7cc78ecSespie       /* Try the next entry.  */
881f7cc78ecSespie     }
882f7cc78ecSespie 
8835f210c2aSfgsch   if (NULL == last_errmsg)
8845f210c2aSfgsch     as_bad ("bad instruction `%s'", start);
8855f210c2aSfgsch   else
8865f210c2aSfgsch     as_bad (last_errmsg);
887f7cc78ecSespie }
888f7cc78ecSespie 
8895f210c2aSfgsch static void
arc_extoper(opertype)8905f210c2aSfgsch arc_extoper (opertype)
8915f210c2aSfgsch      int opertype;
8925f210c2aSfgsch {
8935f210c2aSfgsch   char *name;
8945f210c2aSfgsch   char *mode;
8955f210c2aSfgsch   char c;
8965f210c2aSfgsch   char *p;
8975f210c2aSfgsch   int imode = 0;
8985f210c2aSfgsch   int number;
8995f210c2aSfgsch   struct arc_ext_operand_value *ext_oper;
9005f210c2aSfgsch   symbolS *symbolP;
9015f210c2aSfgsch 
9025f210c2aSfgsch   segT old_sec;
9035f210c2aSfgsch   int old_subsec;
9045f210c2aSfgsch 
9055f210c2aSfgsch   name = input_line_pointer;
9065f210c2aSfgsch   c = get_symbol_end ();
9075f210c2aSfgsch   name = xstrdup (name);
9085f210c2aSfgsch 
9095f210c2aSfgsch   p = name;
9105f210c2aSfgsch   while (*p)
9115f210c2aSfgsch     {
912d2201f2fSdrahn       *p = TOLOWER (*p);
9135f210c2aSfgsch       p++;
9145f210c2aSfgsch     }
9155f210c2aSfgsch 
9165f210c2aSfgsch   /* just after name is now '\0'  */
9175f210c2aSfgsch   p = input_line_pointer;
9185f210c2aSfgsch   *p = c;
9195f210c2aSfgsch   SKIP_WHITESPACE ();
9205f210c2aSfgsch 
9215f210c2aSfgsch   if (*input_line_pointer != ',')
9225f210c2aSfgsch     {
9235f210c2aSfgsch       as_bad ("expected comma after operand name");
9245f210c2aSfgsch       ignore_rest_of_line ();
9255f210c2aSfgsch       free (name);
9265f210c2aSfgsch       return;
9275f210c2aSfgsch     }
9285f210c2aSfgsch 
9295f210c2aSfgsch   input_line_pointer++;		/* skip ','  */
9305f210c2aSfgsch   number = get_absolute_expression ();
9315f210c2aSfgsch 
9325f210c2aSfgsch   if (number < 0)
9335f210c2aSfgsch     {
9345f210c2aSfgsch       as_bad ("negative operand number %d", number);
9355f210c2aSfgsch       ignore_rest_of_line ();
9365f210c2aSfgsch       free (name);
9375f210c2aSfgsch       return;
9385f210c2aSfgsch     }
9395f210c2aSfgsch 
9405f210c2aSfgsch   if (opertype)
9415f210c2aSfgsch     {
9425f210c2aSfgsch       SKIP_WHITESPACE ();
9435f210c2aSfgsch 
9445f210c2aSfgsch       if (*input_line_pointer != ',')
9455f210c2aSfgsch 	{
9465f210c2aSfgsch 	  as_bad ("expected comma after register-number");
9475f210c2aSfgsch 	  ignore_rest_of_line ();
9485f210c2aSfgsch 	  free (name);
9495f210c2aSfgsch 	  return;
9505f210c2aSfgsch 	}
9515f210c2aSfgsch 
9525f210c2aSfgsch       input_line_pointer++;		/* skip ','  */
9535f210c2aSfgsch       mode = input_line_pointer;
9545f210c2aSfgsch 
9555f210c2aSfgsch       if (!strncmp (mode, "r|w", 3))
9565f210c2aSfgsch 	{
9575f210c2aSfgsch 	  imode = 0;
9585f210c2aSfgsch 	  input_line_pointer += 3;
9595f210c2aSfgsch 	}
9605f210c2aSfgsch       else
9615f210c2aSfgsch 	{
9625f210c2aSfgsch 	  if (!strncmp (mode, "r", 1))
9635f210c2aSfgsch 	    {
9645f210c2aSfgsch 	      imode = ARC_REGISTER_READONLY;
9655f210c2aSfgsch 	      input_line_pointer += 1;
9665f210c2aSfgsch 	    }
9675f210c2aSfgsch 	  else
9685f210c2aSfgsch 	    {
9695f210c2aSfgsch 	      if (strncmp (mode, "w", 1))
9705f210c2aSfgsch 		{
9715f210c2aSfgsch 		  as_bad ("invalid mode");
9725f210c2aSfgsch 		  ignore_rest_of_line ();
9735f210c2aSfgsch 		  free (name);
9745f210c2aSfgsch 		  return;
9755f210c2aSfgsch 		}
9765f210c2aSfgsch 	      else
9775f210c2aSfgsch 		{
9785f210c2aSfgsch 		  imode = ARC_REGISTER_WRITEONLY;
9795f210c2aSfgsch 		  input_line_pointer += 1;
9805f210c2aSfgsch 		}
9815f210c2aSfgsch 	    }
9825f210c2aSfgsch 	}
9835f210c2aSfgsch       SKIP_WHITESPACE ();
9845f210c2aSfgsch       if (1 == opertype)
9855f210c2aSfgsch 	{
9865f210c2aSfgsch 	  if (*input_line_pointer != ',')
9875f210c2aSfgsch 	    {
9885f210c2aSfgsch 	      as_bad ("expected comma after register-mode");
9895f210c2aSfgsch 	      ignore_rest_of_line ();
9905f210c2aSfgsch 	      free (name);
9915f210c2aSfgsch 	      return;
9925f210c2aSfgsch 	    }
9935f210c2aSfgsch 
9945f210c2aSfgsch 	  input_line_pointer++;		/* skip ','  */
9955f210c2aSfgsch 
9965f210c2aSfgsch 	  if (!strncmp (input_line_pointer, "cannot_shortcut", 15))
9975f210c2aSfgsch 	    {
9985f210c2aSfgsch 	      imode |= arc_get_noshortcut_flag ();
9995f210c2aSfgsch 	      input_line_pointer += 15;
10005f210c2aSfgsch 	    }
10015f210c2aSfgsch 	  else
10025f210c2aSfgsch 	    {
10035f210c2aSfgsch 	      if (strncmp (input_line_pointer, "can_shortcut", 12))
10045f210c2aSfgsch 		{
10055f210c2aSfgsch 		  as_bad ("shortcut designator invalid");
10065f210c2aSfgsch 		  ignore_rest_of_line ();
10075f210c2aSfgsch 		  free (name);
10085f210c2aSfgsch 		  return;
10095f210c2aSfgsch 		}
10105f210c2aSfgsch 	      else
10115f210c2aSfgsch 		{
10125f210c2aSfgsch 		  input_line_pointer += 12;
10135f210c2aSfgsch 		}
10145f210c2aSfgsch 	    }
10155f210c2aSfgsch 	}
10165f210c2aSfgsch     }
10175f210c2aSfgsch 
10185f210c2aSfgsch   if ((opertype == 1) && number > 60)
10195f210c2aSfgsch     {
10205f210c2aSfgsch       as_bad ("core register value (%d) too large", number);
10215f210c2aSfgsch       ignore_rest_of_line ();
10225f210c2aSfgsch       free (name);
10235f210c2aSfgsch       return;
10245f210c2aSfgsch     }
10255f210c2aSfgsch 
10265f210c2aSfgsch   if ((opertype == 0) && number > 31)
10275f210c2aSfgsch     {
10285f210c2aSfgsch       as_bad ("condition code value (%d) too large", number);
10295f210c2aSfgsch       ignore_rest_of_line ();
10305f210c2aSfgsch       free (name);
10315f210c2aSfgsch       return;
10325f210c2aSfgsch     }
10335f210c2aSfgsch 
10345f210c2aSfgsch   ext_oper = (struct arc_ext_operand_value *) \
10355f210c2aSfgsch     xmalloc (sizeof (struct arc_ext_operand_value));
10365f210c2aSfgsch 
10375f210c2aSfgsch   if (opertype)
10385f210c2aSfgsch     {
10395f210c2aSfgsch       /* If the symbol already exists, point it at the new definition.  */
10405f210c2aSfgsch       if ((symbolP = symbol_find (name)))
10415f210c2aSfgsch 	{
10425f210c2aSfgsch 	  if (S_GET_SEGMENT (symbolP) == reg_section)
10435f210c2aSfgsch 	    S_SET_VALUE (symbolP, (int) &ext_oper->operand);
10445f210c2aSfgsch 	  else
10455f210c2aSfgsch 	    {
10465f210c2aSfgsch 	      as_bad ("attempt to override symbol: %s", name);
10475f210c2aSfgsch 	      ignore_rest_of_line ();
10485f210c2aSfgsch 	      free (name);
10495f210c2aSfgsch 	      free (ext_oper);
10505f210c2aSfgsch 	      return;
10515f210c2aSfgsch 	    }
10525f210c2aSfgsch 	}
10535f210c2aSfgsch       else
10545f210c2aSfgsch 	{
10555f210c2aSfgsch 	  /* If its not there, add it.  */
10565f210c2aSfgsch 	  symbol_table_insert (symbol_create (name, reg_section,
10575f210c2aSfgsch 					      (int) &ext_oper->operand, &zero_address_frag));
10585f210c2aSfgsch 	}
10595f210c2aSfgsch     }
10605f210c2aSfgsch 
10615f210c2aSfgsch   ext_oper->operand.name  = name;
10625f210c2aSfgsch   ext_oper->operand.value = number;
10635f210c2aSfgsch   ext_oper->operand.type  = arc_operand_type (opertype);
10645f210c2aSfgsch   ext_oper->operand.flags = imode;
10655f210c2aSfgsch 
10665f210c2aSfgsch   ext_oper->next = arc_ext_operands;
10675f210c2aSfgsch   arc_ext_operands = ext_oper;
10685f210c2aSfgsch 
10695f210c2aSfgsch   /* OK, now that we know what this operand is, put a description in
10705f210c2aSfgsch      the arc extension section of the output file.  */
10715f210c2aSfgsch 
10725f210c2aSfgsch   old_sec    = now_seg;
10735f210c2aSfgsch   old_subsec = now_subseg;
10745f210c2aSfgsch 
10755f210c2aSfgsch   arc_set_ext_seg ();
10765f210c2aSfgsch 
10775f210c2aSfgsch   switch (opertype)
10785f210c2aSfgsch     {
10795f210c2aSfgsch     case 0:
10805f210c2aSfgsch       p = frag_more (1);
10815f210c2aSfgsch       *p = 3 + strlen (name) + 1;
10825f210c2aSfgsch       p = frag_more (1);
10835f210c2aSfgsch       *p = EXT_COND_CODE;
10845f210c2aSfgsch       p = frag_more (1);
10855f210c2aSfgsch       *p = number;
10865f210c2aSfgsch       p = frag_more (strlen (name) + 1);
10875f210c2aSfgsch       strcpy (p, name);
10885f210c2aSfgsch       break;
10895f210c2aSfgsch     case 1:
10905f210c2aSfgsch       p = frag_more (1);
10915f210c2aSfgsch       *p = 3 + strlen (name) + 1;
10925f210c2aSfgsch       p = frag_more (1);
10935f210c2aSfgsch       *p = EXT_CORE_REGISTER;
10945f210c2aSfgsch       p = frag_more (1);
10955f210c2aSfgsch       *p = number;
10965f210c2aSfgsch       p = frag_more (strlen (name) + 1);
10975f210c2aSfgsch       strcpy (p, name);
10985f210c2aSfgsch       break;
10995f210c2aSfgsch     case 2:
11005f210c2aSfgsch       p = frag_more (1);
11015f210c2aSfgsch       *p = 6 + strlen (name) + 1;
11025f210c2aSfgsch       p = frag_more (1);
11035f210c2aSfgsch       *p = EXT_AUX_REGISTER;
11045f210c2aSfgsch       p = frag_more (1);
11055f210c2aSfgsch       *p = number >> 24 & 0xff;
11065f210c2aSfgsch       p = frag_more (1);
11075f210c2aSfgsch       *p = number >> 16 & 0xff;
11085f210c2aSfgsch       p = frag_more (1);
11095f210c2aSfgsch       *p = number >>  8 & 0xff;
11105f210c2aSfgsch       p = frag_more (1);
11115f210c2aSfgsch       *p = number       & 0xff;
11125f210c2aSfgsch       p = frag_more (strlen (name) + 1);
11135f210c2aSfgsch       strcpy (p, name);
11145f210c2aSfgsch       break;
11155f210c2aSfgsch     default:
11165f210c2aSfgsch       as_bad ("invalid opertype");
11175f210c2aSfgsch       ignore_rest_of_line ();
11185f210c2aSfgsch       free (name);
11195f210c2aSfgsch       return;
11205f210c2aSfgsch       break;
11215f210c2aSfgsch     }
11225f210c2aSfgsch 
11235f210c2aSfgsch   subseg_set (old_sec, old_subsec);
11245f210c2aSfgsch 
11255f210c2aSfgsch   /* Enter all registers into the symbol table.  */
11265f210c2aSfgsch 
11275f210c2aSfgsch   demand_empty_rest_of_line ();
11285f210c2aSfgsch }
1129f7cc78ecSespie 
1130f7cc78ecSespie static void
arc_extinst(ignore)11315f210c2aSfgsch arc_extinst (ignore)
11325f210c2aSfgsch      int ignore ATTRIBUTE_UNUSED;
11335f210c2aSfgsch {
11345f210c2aSfgsch   unsigned char syntax[129];
11355f210c2aSfgsch   char *name;
11365f210c2aSfgsch   char *p;
11375f210c2aSfgsch   char c;
11385f210c2aSfgsch   int suffixcode = -1;
11395f210c2aSfgsch   int opcode, subopcode;
11405f210c2aSfgsch   int i;
11415f210c2aSfgsch   int class = 0;
11425f210c2aSfgsch   int name_len;
11435f210c2aSfgsch   struct arc_opcode *ext_op;
11445f210c2aSfgsch 
11455f210c2aSfgsch   segT old_sec;
11465f210c2aSfgsch   int old_subsec;
11475f210c2aSfgsch 
11485f210c2aSfgsch   name = input_line_pointer;
11495f210c2aSfgsch   c = get_symbol_end ();
11505f210c2aSfgsch   name = xstrdup (name);
11515f210c2aSfgsch   strcpy (syntax, name);
11525f210c2aSfgsch   name_len = strlen (name);
11535f210c2aSfgsch 
11545f210c2aSfgsch   /* just after name is now '\0'  */
11555f210c2aSfgsch   p = input_line_pointer;
11565f210c2aSfgsch   *p = c;
11575f210c2aSfgsch 
11585f210c2aSfgsch   SKIP_WHITESPACE ();
11595f210c2aSfgsch 
11605f210c2aSfgsch   if (*input_line_pointer != ',')
11615f210c2aSfgsch     {
11625f210c2aSfgsch       as_bad ("expected comma after operand name");
11635f210c2aSfgsch       ignore_rest_of_line ();
11645f210c2aSfgsch       return;
11655f210c2aSfgsch     }
11665f210c2aSfgsch 
11675f210c2aSfgsch   input_line_pointer++;		/* skip ','  */
11685f210c2aSfgsch   opcode = get_absolute_expression ();
11695f210c2aSfgsch 
11705f210c2aSfgsch   SKIP_WHITESPACE ();
11715f210c2aSfgsch 
11725f210c2aSfgsch   if (*input_line_pointer != ',')
11735f210c2aSfgsch     {
11745f210c2aSfgsch       as_bad ("expected comma after opcode");
11755f210c2aSfgsch       ignore_rest_of_line ();
11765f210c2aSfgsch       return;
11775f210c2aSfgsch     }
11785f210c2aSfgsch 
11795f210c2aSfgsch   input_line_pointer++;		/* skip ','  */
11805f210c2aSfgsch   subopcode = get_absolute_expression ();
11815f210c2aSfgsch 
11825f210c2aSfgsch   if (subopcode < 0)
11835f210c2aSfgsch     {
11845f210c2aSfgsch       as_bad ("negative subopcode %d", subopcode);
11855f210c2aSfgsch       ignore_rest_of_line ();
11865f210c2aSfgsch       return;
11875f210c2aSfgsch     }
11885f210c2aSfgsch 
11895f210c2aSfgsch   if (subopcode)
11905f210c2aSfgsch     {
11915f210c2aSfgsch       if (3 != opcode)
11925f210c2aSfgsch 	{
11935f210c2aSfgsch 	  as_bad ("subcode value found when opcode not equal 0x03");
11945f210c2aSfgsch 	  ignore_rest_of_line ();
11955f210c2aSfgsch 	  return;
11965f210c2aSfgsch 	}
11975f210c2aSfgsch       else
11985f210c2aSfgsch 	{
11995f210c2aSfgsch 	  if (subopcode < 0x09 || subopcode == 0x3f)
12005f210c2aSfgsch 	    {
12015f210c2aSfgsch 	      as_bad ("invalid subopcode %d", subopcode);
12025f210c2aSfgsch 	      ignore_rest_of_line ();
12035f210c2aSfgsch 	      return;
12045f210c2aSfgsch 	    }
12055f210c2aSfgsch 	}
12065f210c2aSfgsch     }
12075f210c2aSfgsch 
12085f210c2aSfgsch   SKIP_WHITESPACE ();
12095f210c2aSfgsch 
12105f210c2aSfgsch   if (*input_line_pointer != ',')
12115f210c2aSfgsch     {
12125f210c2aSfgsch       as_bad ("expected comma after subopcode");
12135f210c2aSfgsch       ignore_rest_of_line ();
12145f210c2aSfgsch       return;
12155f210c2aSfgsch     }
12165f210c2aSfgsch 
12175f210c2aSfgsch   input_line_pointer++;		/* skip ','  */
12185f210c2aSfgsch 
12195f210c2aSfgsch   for (i = 0; i < (int) MAXSUFFIXCLASS; i++)
12205f210c2aSfgsch     {
12215f210c2aSfgsch       if (!strncmp (suffixclass[i].name,input_line_pointer, suffixclass[i].len))
12225f210c2aSfgsch 	{
12235f210c2aSfgsch 	  suffixcode = i;
12245f210c2aSfgsch 	  input_line_pointer += suffixclass[i].len;
12255f210c2aSfgsch 	  break;
12265f210c2aSfgsch 	}
12275f210c2aSfgsch     }
12285f210c2aSfgsch 
12295f210c2aSfgsch   if (-1 == suffixcode)
12305f210c2aSfgsch     {
12315f210c2aSfgsch       as_bad ("invalid suffix class");
12325f210c2aSfgsch       ignore_rest_of_line ();
12335f210c2aSfgsch       return;
12345f210c2aSfgsch     }
12355f210c2aSfgsch 
12365f210c2aSfgsch   SKIP_WHITESPACE ();
12375f210c2aSfgsch 
12385f210c2aSfgsch   if (*input_line_pointer != ',')
12395f210c2aSfgsch     {
12405f210c2aSfgsch       as_bad ("expected comma after suffix class");
12415f210c2aSfgsch       ignore_rest_of_line ();
12425f210c2aSfgsch       return;
12435f210c2aSfgsch     }
12445f210c2aSfgsch 
12455f210c2aSfgsch   input_line_pointer++;		/* skip ','  */
12465f210c2aSfgsch 
12475f210c2aSfgsch   for (i = 0; i < (int) MAXSYNTAXCLASS; i++)
12485f210c2aSfgsch     {
12495f210c2aSfgsch       if (!strncmp (syntaxclass[i].name,input_line_pointer, syntaxclass[i].len))
12505f210c2aSfgsch 	{
12515f210c2aSfgsch 	  class = syntaxclass[i].class;
12525f210c2aSfgsch 	  input_line_pointer += syntaxclass[i].len;
12535f210c2aSfgsch 	  break;
12545f210c2aSfgsch 	}
12555f210c2aSfgsch     }
12565f210c2aSfgsch 
12575f210c2aSfgsch   if (0 == (SYNTAX_VALID & class))
12585f210c2aSfgsch     {
12595f210c2aSfgsch       as_bad ("invalid syntax class");
12605f210c2aSfgsch       ignore_rest_of_line ();
12615f210c2aSfgsch       return;
12625f210c2aSfgsch     }
12635f210c2aSfgsch 
12645f210c2aSfgsch   if ((0x3 == opcode) & (class & SYNTAX_3OP))
12655f210c2aSfgsch     {
12665f210c2aSfgsch       as_bad ("opcode 0x3 and SYNTAX_3OP invalid");
12675f210c2aSfgsch       ignore_rest_of_line ();
12685f210c2aSfgsch       return;
12695f210c2aSfgsch     }
12705f210c2aSfgsch 
12715f210c2aSfgsch   switch (suffixcode)
12725f210c2aSfgsch     {
12735f210c2aSfgsch     case 0:
12745f210c2aSfgsch       strcat (syntax, "%.q%.f ");
12755f210c2aSfgsch       break;
12765f210c2aSfgsch     case 1:
12775f210c2aSfgsch       strcat (syntax, "%.f ");
12785f210c2aSfgsch       break;
12795f210c2aSfgsch     case 2:
12805f210c2aSfgsch       strcat (syntax, "%.q ");
12815f210c2aSfgsch       break;
12825f210c2aSfgsch     case 3:
12835f210c2aSfgsch       strcat (syntax, " ");
12845f210c2aSfgsch       break;
12855f210c2aSfgsch     default:
12865f210c2aSfgsch       as_bad ("unknown suffix class");
12875f210c2aSfgsch       ignore_rest_of_line ();
12885f210c2aSfgsch       return;
12895f210c2aSfgsch       break;
12905f210c2aSfgsch     };
12915f210c2aSfgsch 
12925f210c2aSfgsch   strcat (syntax, ((opcode == 0x3) ? "%a,%b" : ((class & SYNTAX_3OP) ? "%a,%b,%c" : "%b,%c")));
12935f210c2aSfgsch   if (suffixcode < 2)
12945f210c2aSfgsch     strcat (syntax, "%F");
12955f210c2aSfgsch   strcat (syntax, "%S%L");
12965f210c2aSfgsch 
12975f210c2aSfgsch   ext_op = (struct arc_opcode *) xmalloc (sizeof (struct arc_opcode));
12985f210c2aSfgsch   ext_op->syntax = xstrdup (syntax);
12995f210c2aSfgsch 
13005f210c2aSfgsch   ext_op->mask  = I (-1) | ((0x3 == opcode) ? C (-1) : 0);
13015f210c2aSfgsch   ext_op->value = I (opcode) | ((0x3 == opcode) ? C (subopcode) : 0);
13025f210c2aSfgsch   ext_op->flags = class;
13035f210c2aSfgsch   ext_op->next_asm = arc_ext_opcodes;
13045f210c2aSfgsch   ext_op->next_dis = arc_ext_opcodes;
13055f210c2aSfgsch   arc_ext_opcodes = ext_op;
13065f210c2aSfgsch 
13075f210c2aSfgsch   /* OK, now that we know what this inst is, put a description in the
13085f210c2aSfgsch      arc extension section of the output file.  */
13095f210c2aSfgsch 
13105f210c2aSfgsch   old_sec    = now_seg;
13115f210c2aSfgsch   old_subsec = now_subseg;
13125f210c2aSfgsch 
13135f210c2aSfgsch   arc_set_ext_seg ();
13145f210c2aSfgsch 
13155f210c2aSfgsch   p = frag_more (1);
13165f210c2aSfgsch   *p = 5 + name_len + 1;
13175f210c2aSfgsch   p = frag_more (1);
13185f210c2aSfgsch   *p = EXT_INSTRUCTION;
13195f210c2aSfgsch   p = frag_more (1);
13205f210c2aSfgsch   *p = opcode;
13215f210c2aSfgsch   p = frag_more (1);
13225f210c2aSfgsch   *p = subopcode;
13235f210c2aSfgsch   p = frag_more (1);
13245f210c2aSfgsch   *p = (class & (OP1_MUST_BE_IMM | OP1_IMM_IMPLIED) ? IGNORE_FIRST_OPD : 0);
13255f210c2aSfgsch   p = frag_more (name_len);
13265f210c2aSfgsch   strncpy (p, syntax, name_len);
13275f210c2aSfgsch   p = frag_more (1);
13285f210c2aSfgsch   *p = '\0';
13295f210c2aSfgsch 
13305f210c2aSfgsch   subseg_set (old_sec, old_subsec);
13315f210c2aSfgsch 
13325f210c2aSfgsch   demand_empty_rest_of_line ();
13335f210c2aSfgsch }
13345f210c2aSfgsch 
13355f210c2aSfgsch int
arc_set_ext_seg()13365f210c2aSfgsch arc_set_ext_seg ()
13375f210c2aSfgsch {
13385f210c2aSfgsch   if (!arcext_section)
13395f210c2aSfgsch     {
13405f210c2aSfgsch       arcext_section = subseg_new (".arcextmap", 0);
13415f210c2aSfgsch       bfd_set_section_flags (stdoutput, arcext_section,
13425f210c2aSfgsch 			     SEC_READONLY | SEC_HAS_CONTENTS);
13435f210c2aSfgsch     }
13445f210c2aSfgsch   else
13455f210c2aSfgsch     subseg_set (arcext_section, 0);
13465f210c2aSfgsch   return 1;
13475f210c2aSfgsch }
13485f210c2aSfgsch 
13495f210c2aSfgsch static void
arc_common(localScope)13505f210c2aSfgsch arc_common (localScope)
13515f210c2aSfgsch      int localScope;
1352f7cc78ecSespie {
1353f7cc78ecSespie   char *name;
1354f7cc78ecSespie   char c;
1355f7cc78ecSespie   char *p;
13565f210c2aSfgsch   int align, size;
1357f7cc78ecSespie   symbolS *symbolP;
1358f7cc78ecSespie 
1359f7cc78ecSespie   name = input_line_pointer;
1360f7cc78ecSespie   c = get_symbol_end ();
1361f7cc78ecSespie   /* just after name is now '\0'  */
1362f7cc78ecSespie   p = input_line_pointer;
1363f7cc78ecSespie   *p = c;
1364f7cc78ecSespie   SKIP_WHITESPACE ();
13655f210c2aSfgsch 
1366f7cc78ecSespie   if (*input_line_pointer != ',')
1367f7cc78ecSespie     {
13685f210c2aSfgsch       as_bad ("expected comma after symbol name");
1369f7cc78ecSespie       ignore_rest_of_line ();
1370f7cc78ecSespie       return;
1371f7cc78ecSespie     }
13725f210c2aSfgsch 
1373f7cc78ecSespie   input_line_pointer++;		/* skip ','  */
13745f210c2aSfgsch   size = get_absolute_expression ();
13755f210c2aSfgsch 
13765f210c2aSfgsch   if (size < 0)
1377f7cc78ecSespie     {
13785f210c2aSfgsch       as_bad ("negative symbol length");
1379f7cc78ecSespie       ignore_rest_of_line ();
1380f7cc78ecSespie       return;
1381f7cc78ecSespie     }
13825f210c2aSfgsch 
1383f7cc78ecSespie   *p = 0;
1384f7cc78ecSespie   symbolP = symbol_find_or_make (name);
1385f7cc78ecSespie   *p = c;
13865f210c2aSfgsch 
1387f7cc78ecSespie   if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
1388f7cc78ecSespie     {
13895f210c2aSfgsch       as_bad ("ignoring attempt to re-define symbol");
1390f7cc78ecSespie       ignore_rest_of_line ();
1391f7cc78ecSespie       return;
1392f7cc78ecSespie     }
13935f210c2aSfgsch   if (((int) S_GET_VALUE (symbolP) != 0) \
13945f210c2aSfgsch       && ((int) S_GET_VALUE (symbolP) != size))
1395f7cc78ecSespie     {
13965f210c2aSfgsch       as_warn ("length of symbol \"%s\" already %ld, ignoring %d",
1397f7cc78ecSespie 	       S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
1398f7cc78ecSespie     }
13995f210c2aSfgsch   assert (symbolP->sy_frag == &zero_address_frag);
14005f210c2aSfgsch 
14015f210c2aSfgsch   /* Now parse the alignment field.  This field is optional for
14025f210c2aSfgsch      local and global symbols. Default alignment is zero.  */
14035f210c2aSfgsch   if (*input_line_pointer == ',')
1404f7cc78ecSespie     {
1405f7cc78ecSespie       input_line_pointer++;
14065f210c2aSfgsch       align = get_absolute_expression ();
14075f210c2aSfgsch       if (align < 0)
1408f7cc78ecSespie 	{
14095f210c2aSfgsch 	  align = 0;
14105f210c2aSfgsch 	  as_warn ("assuming symbol alignment of zero");
1411f7cc78ecSespie 	}
14125f210c2aSfgsch     }
14135f210c2aSfgsch   else
14145f210c2aSfgsch     align = 0;
14155f210c2aSfgsch 
14165f210c2aSfgsch   if (localScope != 0)
1417f7cc78ecSespie     {
1418f7cc78ecSespie       segT old_sec;
1419f7cc78ecSespie       int old_subsec;
14205f210c2aSfgsch       char *pfrag;
1421f7cc78ecSespie 
1422f7cc78ecSespie       old_sec    = now_seg;
1423f7cc78ecSespie       old_subsec = now_subseg;
1424f7cc78ecSespie       record_alignment (bss_section, align);
14255f210c2aSfgsch       subseg_set (bss_section, 0);  /* ??? subseg_set (bss_section, 1); ???  */
14265f210c2aSfgsch 
1427f7cc78ecSespie       if (align)
14285f210c2aSfgsch 	/* Do alignment.  */
1429f7cc78ecSespie 	frag_align (align, 0, 0);
14305f210c2aSfgsch 
14315f210c2aSfgsch       /* Detach from old frag.  */
1432f7cc78ecSespie       if (S_GET_SEGMENT (symbolP) == bss_section)
14335f210c2aSfgsch 	symbolP->sy_frag->fr_symbol = NULL;
14345f210c2aSfgsch 
14355f210c2aSfgsch       symbolP->sy_frag = frag_now;
14365f210c2aSfgsch       pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
1437f7cc78ecSespie 			(offsetT) size, (char *) 0);
14385f210c2aSfgsch       *pfrag = 0;
14395f210c2aSfgsch 
14405f210c2aSfgsch       S_SET_SIZE       (symbolP, size);
1441f7cc78ecSespie       S_SET_SEGMENT    (symbolP, bss_section);
1442f7cc78ecSespie       S_CLEAR_EXTERNAL (symbolP);
14435f210c2aSfgsch       symbolP->local = 1;
1444f7cc78ecSespie       subseg_set (old_sec, old_subsec);
1445f7cc78ecSespie     }
1446f7cc78ecSespie   else
1447f7cc78ecSespie     {
1448f7cc78ecSespie       S_SET_VALUE    (symbolP, (valueT) size);
14495f210c2aSfgsch       S_SET_ALIGN    (symbolP, align);
1450f7cc78ecSespie       S_SET_EXTERNAL (symbolP);
1451f7cc78ecSespie       S_SET_SEGMENT  (symbolP, bfd_com_section_ptr);
1452f7cc78ecSespie     }
14535f210c2aSfgsch 
14545f210c2aSfgsch   symbolP->bsym->flags |= BSF_OBJECT;
14555f210c2aSfgsch 
1456f7cc78ecSespie   demand_empty_rest_of_line ();
1457f7cc78ecSespie }
14585f210c2aSfgsch 
1459f7cc78ecSespie /* Select the cpu we're assembling for.  */
1460f7cc78ecSespie 
1461f7cc78ecSespie static void
arc_option(ignore)14625f210c2aSfgsch arc_option (ignore)
14635f210c2aSfgsch      int ignore ATTRIBUTE_UNUSED;
1464f7cc78ecSespie {
1465f7cc78ecSespie   int mach;
1466f7cc78ecSespie   char c;
1467f7cc78ecSespie   char *cpu;
1468f7cc78ecSespie 
1469f7cc78ecSespie   cpu = input_line_pointer;
1470f7cc78ecSespie   c = get_symbol_end ();
1471f7cc78ecSespie   mach = arc_get_mach (cpu);
1472f7cc78ecSespie   *input_line_pointer = c;
14735f210c2aSfgsch 
14745f210c2aSfgsch   /* If an instruction has already been seen, it's too late.  */
14755f210c2aSfgsch   if (cpu_tables_init_p)
14765f210c2aSfgsch     {
14775f210c2aSfgsch       as_bad ("\".option\" directive must appear before any instructions");
14785f210c2aSfgsch       ignore_rest_of_line ();
14795f210c2aSfgsch       return;
14805f210c2aSfgsch     }
14815f210c2aSfgsch 
1482f7cc78ecSespie   if (mach == -1)
1483f7cc78ecSespie     goto bad_cpu;
1484f7cc78ecSespie 
1485f7cc78ecSespie   if (mach_type_specified_p && mach != arc_mach_type)
14865f210c2aSfgsch     {
14875f210c2aSfgsch       as_bad ("\".option\" directive conflicts with initial definition");
14885f210c2aSfgsch       ignore_rest_of_line ();
14895f210c2aSfgsch       return;
14905f210c2aSfgsch     }
1491f7cc78ecSespie   else
1492f7cc78ecSespie     {
14935f210c2aSfgsch       /* The cpu may have been selected on the command line.  */
14945f210c2aSfgsch       if (mach != arc_mach_type)
14955f210c2aSfgsch 	as_warn ("\".option\" directive overrides command-line (default) value");
1496f7cc78ecSespie       arc_mach_type = mach;
1497f7cc78ecSespie       if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach))
14985f210c2aSfgsch 	as_fatal ("could not set architecture and machine");
14995f210c2aSfgsch       mach_type_specified_p = 1;
1500f7cc78ecSespie     }
15015f210c2aSfgsch   demand_empty_rest_of_line ();
1502f7cc78ecSespie   return;
1503f7cc78ecSespie 
1504f7cc78ecSespie  bad_cpu:
15055f210c2aSfgsch   as_bad ("invalid identifier for \".option\"");
1506f7cc78ecSespie   ignore_rest_of_line ();
1507f7cc78ecSespie }
1508f7cc78ecSespie 
15095f210c2aSfgsch /* Turn a string in input_line_pointer into a floating point constant
15105f210c2aSfgsch    of type TYPE, and store the appropriate bytes in *LITP.  The number
15115f210c2aSfgsch    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
15125f210c2aSfgsch    returned, or NULL on OK.  */
1513f7cc78ecSespie 
1514f7cc78ecSespie /* Equal to MAX_PRECISION in atof-ieee.c  */
1515f7cc78ecSespie #define MAX_LITTLENUMS 6
1516f7cc78ecSespie 
1517f7cc78ecSespie char *
md_atof(type,litP,sizeP)1518f7cc78ecSespie md_atof (type, litP, sizeP)
1519d2201f2fSdrahn      int type;
1520f7cc78ecSespie      char *litP;
1521f7cc78ecSespie      int *sizeP;
1522f7cc78ecSespie {
1523f7cc78ecSespie   int prec;
1524f7cc78ecSespie   LITTLENUM_TYPE words[MAX_LITTLENUMS];
1525f7cc78ecSespie   LITTLENUM_TYPE *wordP;
1526f7cc78ecSespie   char *t;
1527f7cc78ecSespie 
1528f7cc78ecSespie   switch (type)
1529f7cc78ecSespie     {
1530f7cc78ecSespie     case 'f':
1531f7cc78ecSespie     case 'F':
1532f7cc78ecSespie       prec = 2;
1533f7cc78ecSespie       break;
1534f7cc78ecSespie 
1535f7cc78ecSespie     case 'd':
1536f7cc78ecSespie     case 'D':
1537f7cc78ecSespie       prec = 4;
1538f7cc78ecSespie       break;
1539f7cc78ecSespie 
1540f7cc78ecSespie     default:
1541f7cc78ecSespie       *sizeP = 0;
15425f210c2aSfgsch       return "bad call to md_atof";
1543f7cc78ecSespie     }
1544f7cc78ecSespie 
1545f7cc78ecSespie   t = atof_ieee (input_line_pointer, type, words);
1546f7cc78ecSespie   if (t)
1547f7cc78ecSespie     input_line_pointer = t;
1548f7cc78ecSespie   *sizeP = prec * sizeof (LITTLENUM_TYPE);
1549f7cc78ecSespie   for (wordP = words; prec--;)
1550f7cc78ecSespie     {
1551f7cc78ecSespie       md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
1552f7cc78ecSespie       litP += sizeof (LITTLENUM_TYPE);
1553f7cc78ecSespie     }
1554f7cc78ecSespie 
1555f7cc78ecSespie   return NULL;
1556f7cc78ecSespie }
1557f7cc78ecSespie 
1558f7cc78ecSespie /* Write a value out to the object file, using the appropriate
1559f7cc78ecSespie    endianness.  */
1560f7cc78ecSespie 
1561f7cc78ecSespie void
md_number_to_chars(buf,val,n)1562f7cc78ecSespie md_number_to_chars (buf, val, n)
1563f7cc78ecSespie      char *buf;
1564f7cc78ecSespie      valueT val;
1565f7cc78ecSespie      int n;
1566f7cc78ecSespie {
1567f7cc78ecSespie   if (target_big_endian)
1568f7cc78ecSespie     number_to_chars_bigendian (buf, val, n);
1569f7cc78ecSespie   else
1570f7cc78ecSespie     number_to_chars_littleendian (buf, val, n);
1571f7cc78ecSespie }
1572f7cc78ecSespie 
1573f7cc78ecSespie /* Round up a section size to the appropriate boundary.  */
1574f7cc78ecSespie 
1575f7cc78ecSespie valueT
md_section_align(segment,size)1576f7cc78ecSespie md_section_align (segment, size)
1577f7cc78ecSespie      segT segment;
1578f7cc78ecSespie      valueT size;
1579f7cc78ecSespie {
1580f7cc78ecSespie   int align = bfd_get_section_alignment (stdoutput, segment);
1581f7cc78ecSespie 
1582f7cc78ecSespie   return ((size + (1 << align) - 1) & (-1 << align));
1583f7cc78ecSespie }
1584f7cc78ecSespie 
1585f7cc78ecSespie /* We don't have any form of relaxing.  */
1586f7cc78ecSespie 
1587f7cc78ecSespie int
md_estimate_size_before_relax(fragp,seg)1588f7cc78ecSespie md_estimate_size_before_relax (fragp, seg)
15895f210c2aSfgsch      fragS *fragp ATTRIBUTE_UNUSED;
15905f210c2aSfgsch      asection *seg ATTRIBUTE_UNUSED;
1591f7cc78ecSespie {
15925f210c2aSfgsch   as_fatal (_("md_estimate_size_before_relax\n"));
15935f210c2aSfgsch   return 1;
1594f7cc78ecSespie }
1595f7cc78ecSespie 
1596f7cc78ecSespie /* Convert a machine dependent frag.  We never generate these.  */
1597f7cc78ecSespie 
1598f7cc78ecSespie void
md_convert_frag(abfd,sec,fragp)1599f7cc78ecSespie md_convert_frag (abfd, sec, fragp)
16005f210c2aSfgsch      bfd *abfd ATTRIBUTE_UNUSED;
16015f210c2aSfgsch      asection *sec ATTRIBUTE_UNUSED;
16025f210c2aSfgsch      fragS *fragp ATTRIBUTE_UNUSED;
1603f7cc78ecSespie {
16045f210c2aSfgsch   as_fatal (_("md_convert_frag\n"));
16055f210c2aSfgsch }
16065f210c2aSfgsch 
16075f210c2aSfgsch void
arc_code_symbol(expressionP)16085f210c2aSfgsch arc_code_symbol (expressionP)
16095f210c2aSfgsch      expressionS *expressionP;
16105f210c2aSfgsch {
1611d2201f2fSdrahn   if (expressionP->X_op == O_symbol && expressionP->X_add_number == 0)
16125f210c2aSfgsch     {
16135f210c2aSfgsch       expressionS two;
16145f210c2aSfgsch       expressionP->X_op = O_right_shift;
16155f210c2aSfgsch       expressionP->X_add_symbol->sy_value.X_op = O_constant;
16165f210c2aSfgsch       two.X_op = O_constant;
16175f210c2aSfgsch       two.X_add_symbol = two.X_op_symbol = NULL;
16185f210c2aSfgsch       two.X_add_number = 2;
16195f210c2aSfgsch       expressionP->X_op_symbol = make_expr_symbol (&two);
16205f210c2aSfgsch     }
16215f210c2aSfgsch   /* Allow %st(sym1-sym2)  */
16225f210c2aSfgsch   else if (expressionP->X_op == O_subtract
16235f210c2aSfgsch 	   && expressionP->X_add_symbol != NULL
16245f210c2aSfgsch 	   && expressionP->X_op_symbol != NULL
16255f210c2aSfgsch 	   && expressionP->X_add_number == 0)
16265f210c2aSfgsch     {
16275f210c2aSfgsch       expressionS two;
16285f210c2aSfgsch       expressionP->X_add_symbol = make_expr_symbol (expressionP);
16295f210c2aSfgsch       expressionP->X_op = O_right_shift;
16305f210c2aSfgsch       two.X_op = O_constant;
16315f210c2aSfgsch       two.X_add_symbol = two.X_op_symbol = NULL;
16325f210c2aSfgsch       two.X_add_number = 2;
16335f210c2aSfgsch       expressionP->X_op_symbol = make_expr_symbol (&two);
16345f210c2aSfgsch     }
16355f210c2aSfgsch   else
16365f210c2aSfgsch     {
16375f210c2aSfgsch       as_bad ("expression too complex code symbol");
16385f210c2aSfgsch       return;
16395f210c2aSfgsch     }
1640f7cc78ecSespie }
1641f7cc78ecSespie 
1642f7cc78ecSespie /* Parse an operand that is machine-specific.
1643f7cc78ecSespie 
1644f7cc78ecSespie    The ARC has a special %-op to adjust addresses so they're usable in
1645f7cc78ecSespie    branches.  The "st" is short for the STatus register.
1646f7cc78ecSespie    ??? Later expand this to take a flags value too.
1647f7cc78ecSespie 
1648f7cc78ecSespie    ??? We can't create new expression types so we map the %-op's onto the
1649f7cc78ecSespie    existing syntax.  This means that the user could use the chosen syntax
16505f210c2aSfgsch    to achieve the same effect.  */
1651f7cc78ecSespie 
1652f7cc78ecSespie void
md_operand(expressionP)1653f7cc78ecSespie md_operand (expressionP)
1654f7cc78ecSespie      expressionS *expressionP;
1655f7cc78ecSespie {
1656f7cc78ecSespie   char *p = input_line_pointer;
1657f7cc78ecSespie 
16585f210c2aSfgsch   if (*p == '%')
16595f210c2aSfgsch     if (strncmp (p, "%st(", 4) == 0)
1660f7cc78ecSespie       {
1661f7cc78ecSespie 	input_line_pointer += 4;
1662f7cc78ecSespie 	expression (expressionP);
1663f7cc78ecSespie 	if (*input_line_pointer != ')')
1664f7cc78ecSespie 	  {
16655f210c2aSfgsch 	    as_bad ("missing ')' in %%-op");
1666f7cc78ecSespie 	    return;
1667f7cc78ecSespie 	  }
1668f7cc78ecSespie 	++input_line_pointer;
16695f210c2aSfgsch 	arc_code_symbol (expressionP);
1670f7cc78ecSespie       }
1671f7cc78ecSespie     else
1672f7cc78ecSespie       {
16735f210c2aSfgsch 	/* It could be a register.  */
16745f210c2aSfgsch 	int i, l;
16755f210c2aSfgsch 	struct arc_ext_operand_value *ext_oper = arc_ext_operands;
16765f210c2aSfgsch 	p++;
16775f210c2aSfgsch 
16785f210c2aSfgsch 	while (ext_oper)
16795f210c2aSfgsch 	  {
16805f210c2aSfgsch 	    l = strlen (ext_oper->operand.name);
1681d2201f2fSdrahn 	    if (!strncmp (p, ext_oper->operand.name, l) && !ISALNUM (*(p + l)))
16825f210c2aSfgsch 	      {
16835f210c2aSfgsch 		input_line_pointer += l + 1;
16845f210c2aSfgsch 		expressionP->X_op = O_register;
16855f210c2aSfgsch 		expressionP->X_add_number = (int) &ext_oper->operand;
1686f7cc78ecSespie 		return;
1687f7cc78ecSespie 	      }
16885f210c2aSfgsch 	    ext_oper = ext_oper->next;
16895f210c2aSfgsch 	  }
16905f210c2aSfgsch 	for (i = 0; i < arc_reg_names_count; i++)
16915f210c2aSfgsch 	  {
16925f210c2aSfgsch 	    l = strlen (arc_reg_names[i].name);
1693d2201f2fSdrahn 	    if (!strncmp (p, arc_reg_names[i].name, l) && !ISALNUM (*(p + l)))
16945f210c2aSfgsch 	      {
16955f210c2aSfgsch 		input_line_pointer += l + 1;
16965f210c2aSfgsch 		expressionP->X_op = O_register;
16975f210c2aSfgsch 		expressionP->X_add_number = (int) &arc_reg_names[i];
16985f210c2aSfgsch 		break;
16995f210c2aSfgsch 	      }
17005f210c2aSfgsch 	  }
1701f7cc78ecSespie       }
1702f7cc78ecSespie }
1703f7cc78ecSespie 
1704f7cc78ecSespie /* We have no need to default values of symbols.
1705f7cc78ecSespie    We could catch register names here, but that is handled by inserting
1706f7cc78ecSespie    them all in the symbol table to begin with.  */
1707f7cc78ecSespie 
1708f7cc78ecSespie symbolS *
md_undefined_symbol(name)1709f7cc78ecSespie md_undefined_symbol (name)
17105f210c2aSfgsch      char *name ATTRIBUTE_UNUSED;
1711f7cc78ecSespie {
1712f7cc78ecSespie   return 0;
1713f7cc78ecSespie }
1714f7cc78ecSespie 
1715f7cc78ecSespie /* Functions concerning expressions.  */
1716f7cc78ecSespie 
1717f7cc78ecSespie /* Parse a .byte, .word, etc. expression.
1718f7cc78ecSespie 
1719f7cc78ecSespie    Values for the status register are specified with %st(label).
1720f7cc78ecSespie    `label' will be right shifted by 2.  */
1721f7cc78ecSespie 
1722f7cc78ecSespie void
arc_parse_cons_expression(exp,nbytes)1723f7cc78ecSespie arc_parse_cons_expression (exp, nbytes)
1724f7cc78ecSespie      expressionS *exp;
17255f210c2aSfgsch      unsigned int nbytes ATTRIBUTE_UNUSED;
1726f7cc78ecSespie {
17275f210c2aSfgsch   char *p = input_line_pointer;
17285f210c2aSfgsch   int code_symbol_fix = 0;
17295f210c2aSfgsch 
17305f210c2aSfgsch   for (; ! is_end_of_line[(unsigned char) *p]; p++)
17315f210c2aSfgsch     if (*p == '@' && !strncmp (p, "@h30", 4))
17325f210c2aSfgsch       {
17335f210c2aSfgsch 	code_symbol_fix = 1;
17345f210c2aSfgsch 	strcpy (p, ";   ");
17355f210c2aSfgsch       }
1736f7cc78ecSespie   expr (0, exp);
17375f210c2aSfgsch   if (code_symbol_fix)
17385f210c2aSfgsch     {
17395f210c2aSfgsch       arc_code_symbol (exp);
17405f210c2aSfgsch       input_line_pointer = p;
17415f210c2aSfgsch     }
1742f7cc78ecSespie }
1743f7cc78ecSespie 
1744f7cc78ecSespie /* Record a fixup for a cons expression.  */
1745f7cc78ecSespie 
1746f7cc78ecSespie void
arc_cons_fix_new(frag,where,nbytes,exp)1747f7cc78ecSespie arc_cons_fix_new (frag, where, nbytes, exp)
1748f7cc78ecSespie      fragS *frag;
1749f7cc78ecSespie      int where;
1750f7cc78ecSespie      int nbytes;
1751f7cc78ecSespie      expressionS *exp;
1752f7cc78ecSespie {
1753f7cc78ecSespie   if (nbytes == 4)
1754f7cc78ecSespie     {
1755f7cc78ecSespie       int reloc_type;
1756f7cc78ecSespie       expressionS exptmp;
1757f7cc78ecSespie 
1758f7cc78ecSespie       /* This may be a special ARC reloc (eg: %st()).  */
1759f7cc78ecSespie       reloc_type = get_arc_exp_reloc_type (1, BFD_RELOC_32, exp, &exptmp);
1760f7cc78ecSespie       fix_new_exp (frag, where, nbytes, &exptmp, 0, reloc_type);
1761f7cc78ecSespie     }
1762f7cc78ecSespie   else
1763f7cc78ecSespie     {
1764f7cc78ecSespie       fix_new_exp (frag, where, nbytes, exp, 0,
1765f7cc78ecSespie 		   nbytes == 2 ? BFD_RELOC_16
1766f7cc78ecSespie 		   : nbytes == 8 ? BFD_RELOC_64
1767f7cc78ecSespie 		   : BFD_RELOC_32);
1768f7cc78ecSespie     }
1769f7cc78ecSespie }
1770f7cc78ecSespie 
1771f7cc78ecSespie /* Functions concerning relocs.  */
1772f7cc78ecSespie 
1773f7cc78ecSespie /* The location from which a PC relative jump should be calculated,
1774f7cc78ecSespie    given a PC relative reloc.  */
1775f7cc78ecSespie 
1776f7cc78ecSespie long
md_pcrel_from(fixP)1777f7cc78ecSespie md_pcrel_from (fixP)
1778f7cc78ecSespie      fixS *fixP;
1779f7cc78ecSespie {
1780f7cc78ecSespie   /* Return the address of the delay slot.  */
1781f7cc78ecSespie   return fixP->fx_frag->fr_address + fixP->fx_where + fixP->fx_size;
1782f7cc78ecSespie }
1783f7cc78ecSespie 
1784f7cc78ecSespie /* Compute the reloc type of an expression.
1785f7cc78ecSespie    The possibly modified expression is stored in EXPNEW.
1786f7cc78ecSespie 
1787f7cc78ecSespie    This is used to convert the expressions generated by the %-op's into
1788f7cc78ecSespie    the appropriate operand type.  It is called for both data in instructions
1789f7cc78ecSespie    (operands) and data outside instructions (variables, debugging info, etc.).
1790f7cc78ecSespie 
1791f7cc78ecSespie    Currently supported %-ops:
1792f7cc78ecSespie 
1793f7cc78ecSespie    %st(symbol): represented as "symbol >> 2"
1794f7cc78ecSespie                 "st" is short for STatus as in the status register (pc)
1795f7cc78ecSespie 
1796f7cc78ecSespie    DEFAULT_TYPE is the type to use if no special processing is required.
1797f7cc78ecSespie 
1798f7cc78ecSespie    DATA_P is non-zero for data or limm values, zero for insn operands.
1799f7cc78ecSespie    Remember that the opcode "insertion fns" cannot be used on data, they're
1800f7cc78ecSespie    only for inserting operands into insns.  They also can't be used for limm
1801f7cc78ecSespie    values as the insertion routines don't handle limm values.  When called for
1802f7cc78ecSespie    insns we return fudged reloc types (real_value - BFD_RELOC_UNUSED).  When
1803f7cc78ecSespie    called for data or limm values we use real reloc types.  */
1804f7cc78ecSespie 
1805f7cc78ecSespie static int
get_arc_exp_reloc_type(data_p,default_type,exp,expnew)1806f7cc78ecSespie get_arc_exp_reloc_type (data_p, default_type, exp, expnew)
1807f7cc78ecSespie      int data_p;
1808f7cc78ecSespie      int default_type;
1809f7cc78ecSespie      expressionS *exp;
1810f7cc78ecSespie      expressionS *expnew;
1811f7cc78ecSespie {
1812f7cc78ecSespie   /* If the expression is "symbol >> 2" we must change it to just "symbol",
1813*cf2f2c56Smiod      as fix_new_exp can't handle it.  Similarly for (symbol - symbol) >> 2.
1814f7cc78ecSespie      That's ok though.  What's really going on here is that we're using
1815f7cc78ecSespie      ">> 2" as a special syntax for specifying BFD_RELOC_ARC_B26.  */
1816f7cc78ecSespie 
1817f7cc78ecSespie   if (exp->X_op == O_right_shift
1818f7cc78ecSespie       && exp->X_op_symbol != NULL
18195f210c2aSfgsch       && exp->X_op_symbol->sy_value.X_op == O_constant
18205f210c2aSfgsch       && exp->X_op_symbol->sy_value.X_add_number == 2
1821f7cc78ecSespie       && exp->X_add_number == 0)
1822f7cc78ecSespie     {
1823f7cc78ecSespie       if (exp->X_add_symbol != NULL
18245f210c2aSfgsch 	  && (exp->X_add_symbol->sy_value.X_op == O_constant
18255f210c2aSfgsch 	      || exp->X_add_symbol->sy_value.X_op == O_symbol))
1826f7cc78ecSespie 	{
1827f7cc78ecSespie 	  *expnew = *exp;
1828f7cc78ecSespie 	  expnew->X_op = O_symbol;
1829f7cc78ecSespie 	  expnew->X_op_symbol = NULL;
1830f7cc78ecSespie 	  return data_p ? BFD_RELOC_ARC_B26 : arc_operand_map['J'];
1831f7cc78ecSespie 	}
1832f7cc78ecSespie       else if (exp->X_add_symbol != NULL
18335f210c2aSfgsch 	       && exp->X_add_symbol->sy_value.X_op == O_subtract)
1834f7cc78ecSespie 	{
18355f210c2aSfgsch 	  *expnew = exp->X_add_symbol->sy_value;
1836f7cc78ecSespie 	  return data_p ? BFD_RELOC_ARC_B26 : arc_operand_map['J'];
1837f7cc78ecSespie 	}
1838f7cc78ecSespie     }
1839f7cc78ecSespie 
1840f7cc78ecSespie   *expnew = *exp;
1841f7cc78ecSespie   return default_type;
1842f7cc78ecSespie }
1843f7cc78ecSespie 
1844f7cc78ecSespie /* Apply a fixup to the object code.  This is called for all the
1845f7cc78ecSespie    fixups we generated by the call to fix_new_exp, above.  In the call
1846f7cc78ecSespie    above we used a reloc code which was the largest legal reloc code
1847f7cc78ecSespie    plus the operand index.  Here we undo that to recover the operand
1848f7cc78ecSespie    index.  At this point all symbol values should be fully resolved,
1849f7cc78ecSespie    and we attempt to completely resolve the reloc.  If we can not do
1850f7cc78ecSespie    that, we determine the correct reloc code and put it back in the fixup.  */
1851f7cc78ecSespie 
1852d2201f2fSdrahn void
md_apply_fix3(fixP,valP,seg)1853d2201f2fSdrahn md_apply_fix3 (fixP, valP, seg)
1854f7cc78ecSespie      fixS *fixP;
1855d2201f2fSdrahn      valueT * valP;
1856f7cc78ecSespie      segT seg;
1857f7cc78ecSespie {
18585f210c2aSfgsch #if 0
18595f210c2aSfgsch   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
18605f210c2aSfgsch #endif
1861d2201f2fSdrahn   valueT value = * valP;
1862f7cc78ecSespie 
1863f7cc78ecSespie   if (fixP->fx_addsy == (symbolS *) NULL)
1864f7cc78ecSespie     fixP->fx_done = 1;
1865d2201f2fSdrahn 
1866f7cc78ecSespie   else if (fixP->fx_pcrel)
1867f7cc78ecSespie     {
1868d2201f2fSdrahn       /* Hack around bfd_install_relocation brain damage.  */
1869d2201f2fSdrahn       if (S_GET_SEGMENT (fixP->fx_addsy) != seg)
1870f7cc78ecSespie 	value += md_pcrel_from (fixP);
1871f7cc78ecSespie     }
1872d2201f2fSdrahn 
1873f7cc78ecSespie   /* We can't actually support subtracting a symbol.  */
1874d2201f2fSdrahn   if (fixP->fx_subsy != NULL)
1875d2201f2fSdrahn     as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
1876f7cc78ecSespie 
1877f7cc78ecSespie   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1878f7cc78ecSespie     {
1879f7cc78ecSespie       int opindex;
1880f7cc78ecSespie       const struct arc_operand *operand;
1881f7cc78ecSespie       char *where;
1882f7cc78ecSespie       arc_insn insn;
1883f7cc78ecSespie 
1884f7cc78ecSespie       opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1885f7cc78ecSespie 
1886f7cc78ecSespie       operand = &arc_operands[opindex];
1887f7cc78ecSespie 
1888f7cc78ecSespie       /* Fetch the instruction, insert the fully resolved operand
1889f7cc78ecSespie 	 value, and stuff the instruction back again.  */
1890f7cc78ecSespie       where = fixP->fx_frag->fr_literal + fixP->fx_where;
1891f7cc78ecSespie       if (target_big_endian)
1892f7cc78ecSespie 	insn = bfd_getb32 ((unsigned char *) where);
1893f7cc78ecSespie       else
1894f7cc78ecSespie 	insn = bfd_getl32 ((unsigned char *) where);
1895f7cc78ecSespie       insn = arc_insert_operand (insn, operand, -1, NULL, (offsetT) value,
1896f7cc78ecSespie 				 fixP->fx_file, fixP->fx_line);
1897f7cc78ecSespie       if (target_big_endian)
1898f7cc78ecSespie 	bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
1899f7cc78ecSespie       else
1900f7cc78ecSespie 	bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
1901f7cc78ecSespie 
1902f7cc78ecSespie       if (fixP->fx_done)
1903f7cc78ecSespie 	{
1904f7cc78ecSespie 	  /* Nothing else to do here.  */
1905d2201f2fSdrahn 	  return;
1906f7cc78ecSespie 	}
1907f7cc78ecSespie 
1908f7cc78ecSespie       /* Determine a BFD reloc value based on the operand information.
1909f7cc78ecSespie 	 We are only prepared to turn a few of the operands into relocs.
1910f7cc78ecSespie 	 !!! Note that we can't handle limm values here.  Since we're using
1911f7cc78ecSespie 	 implicit addends the addend must be inserted into the instruction,
1912f7cc78ecSespie 	 however, the opcode insertion routines currently do nothing with
1913f7cc78ecSespie 	 limm values.  */
1914f7cc78ecSespie       if (operand->fmt == 'B')
1915f7cc78ecSespie 	{
1916f7cc78ecSespie 	  assert ((operand->flags & ARC_OPERAND_RELATIVE_BRANCH) != 0
1917f7cc78ecSespie 		  && operand->bits == 20
1918f7cc78ecSespie 		  && operand->shift == 7);
1919f7cc78ecSespie 	  fixP->fx_r_type = BFD_RELOC_ARC_B22_PCREL;
1920f7cc78ecSespie 	}
19215f210c2aSfgsch       else if (operand->fmt == 'J')
1922f7cc78ecSespie 	{
1923f7cc78ecSespie 	  assert ((operand->flags & ARC_OPERAND_ABSOLUTE_BRANCH) != 0
1924f7cc78ecSespie 		  && operand->bits == 24
1925f7cc78ecSespie 		  && operand->shift == 32);
1926f7cc78ecSespie 	  fixP->fx_r_type = BFD_RELOC_ARC_B26;
1927f7cc78ecSespie 	}
19285f210c2aSfgsch       else if (operand->fmt == 'L')
1929f7cc78ecSespie 	{
1930f7cc78ecSespie 	  assert ((operand->flags & ARC_OPERAND_LIMM) != 0
1931f7cc78ecSespie 		  && operand->bits == 32
1932f7cc78ecSespie 		  && operand->shift == 32);
1933f7cc78ecSespie 	  fixP->fx_r_type = BFD_RELOC_32;
1934f7cc78ecSespie 	}
1935f7cc78ecSespie       else
1936f7cc78ecSespie 	{
1937f7cc78ecSespie 	  as_bad_where (fixP->fx_file, fixP->fx_line,
19385f210c2aSfgsch 			"unresolved expression that must be resolved");
1939f7cc78ecSespie 	  fixP->fx_done = 1;
1940d2201f2fSdrahn 	  return;
1941f7cc78ecSespie 	}
1942f7cc78ecSespie     }
1943f7cc78ecSespie   else
1944f7cc78ecSespie     {
1945f7cc78ecSespie       switch (fixP->fx_r_type)
1946f7cc78ecSespie 	{
1947f7cc78ecSespie 	case BFD_RELOC_8:
1948f7cc78ecSespie 	  md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
1949f7cc78ecSespie 			      value, 1);
1950f7cc78ecSespie 	  break;
1951f7cc78ecSespie 	case BFD_RELOC_16:
1952f7cc78ecSespie 	  md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
1953f7cc78ecSespie 			      value, 2);
1954f7cc78ecSespie 	  break;
1955f7cc78ecSespie 	case BFD_RELOC_32:
1956f7cc78ecSespie 	  md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
1957f7cc78ecSespie 			      value, 4);
1958f7cc78ecSespie 	  break;
1959f7cc78ecSespie #if 0
1960f7cc78ecSespie 	case BFD_RELOC_64:
1961f7cc78ecSespie 	  md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
1962f7cc78ecSespie 			      value, 8);
1963f7cc78ecSespie 	  break;
1964f7cc78ecSespie #endif
1965f7cc78ecSespie 	case BFD_RELOC_ARC_B26:
1966f7cc78ecSespie 	  /* If !fixP->fx_done then `value' is an implicit addend.
1967f7cc78ecSespie 	     We must shift it right by 2 in this case as well because the
1968f7cc78ecSespie 	     linker performs the relocation and then adds this in (as opposed
1969f7cc78ecSespie 	     to adding this in and then shifting right by 2).  */
1970f7cc78ecSespie 	  value >>= 2;
1971f7cc78ecSespie 	  md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
1972f7cc78ecSespie 			      value, 4);
1973f7cc78ecSespie 	  break;
1974f7cc78ecSespie 	default:
1975f7cc78ecSespie 	  abort ();
1976f7cc78ecSespie 	}
1977f7cc78ecSespie     }
1978f7cc78ecSespie }
1979f7cc78ecSespie 
1980f7cc78ecSespie /* Translate internal representation of relocation info to BFD target
1981f7cc78ecSespie    format.  */
1982f7cc78ecSespie 
1983f7cc78ecSespie arelent *
tc_gen_reloc(section,fixP)1984f7cc78ecSespie tc_gen_reloc (section, fixP)
19855f210c2aSfgsch      asection *section ATTRIBUTE_UNUSED;
1986f7cc78ecSespie      fixS *fixP;
1987f7cc78ecSespie {
1988f7cc78ecSespie   arelent *reloc;
1989f7cc78ecSespie 
1990f7cc78ecSespie   reloc = (arelent *) xmalloc (sizeof (arelent));
1991f7cc78ecSespie 
19925f210c2aSfgsch   reloc->sym_ptr_ptr = &fixP->fx_addsy->bsym;
1993f7cc78ecSespie   reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
1994f7cc78ecSespie   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
1995f7cc78ecSespie   if (reloc->howto == (reloc_howto_type *) NULL)
1996f7cc78ecSespie     {
1997f7cc78ecSespie       as_bad_where (fixP->fx_file, fixP->fx_line,
19985f210c2aSfgsch 		    "internal error: can't export reloc type %d (`%s')",
19995f210c2aSfgsch 		    fixP->fx_r_type,
20005f210c2aSfgsch 		    bfd_get_reloc_code_name (fixP->fx_r_type));
2001f7cc78ecSespie       return NULL;
2002f7cc78ecSespie     }
2003f7cc78ecSespie 
2004f7cc78ecSespie   assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
2005f7cc78ecSespie 
20065f210c2aSfgsch   /* Set addend to account for PC being advanced one insn before the
2007d2201f2fSdrahn      target address is computed.  */
20085f210c2aSfgsch 
20095f210c2aSfgsch   reloc->addend = (fixP->fx_pcrel ? -4 : 0);
2010f7cc78ecSespie 
2011f7cc78ecSespie   return reloc;
2012f7cc78ecSespie }
2013