xref: /openbsd-src/gnu/usr.bin/binutils-2.17/gas/config/tc-arc.c (revision 3d8817e467ea46cf4772788d6804dd293abfb01a)
1*3d8817e4Smiod /* tc-arc.c -- Assembler for the ARC
2*3d8817e4Smiod    Copyright 1994, 1995, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3*3d8817e4Smiod    2006  Free Software Foundation, Inc.
4*3d8817e4Smiod    Contributed by Doug Evans (dje@cygnus.com).
5*3d8817e4Smiod 
6*3d8817e4Smiod    This file is part of GAS, the GNU Assembler.
7*3d8817e4Smiod 
8*3d8817e4Smiod    GAS is free software; you can redistribute it and/or modify
9*3d8817e4Smiod    it under the terms of the GNU General Public License as published by
10*3d8817e4Smiod    the Free Software Foundation; either version 2, or (at your option)
11*3d8817e4Smiod    any later version.
12*3d8817e4Smiod 
13*3d8817e4Smiod    GAS is distributed in the hope that it will be useful,
14*3d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
15*3d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*3d8817e4Smiod    GNU General Public License for more details.
17*3d8817e4Smiod 
18*3d8817e4Smiod    You should have received a copy of the GNU General Public License
19*3d8817e4Smiod    along with GAS; see the file COPYING.  If not, write to the Free
20*3d8817e4Smiod    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21*3d8817e4Smiod    02110-1301, USA.  */
22*3d8817e4Smiod 
23*3d8817e4Smiod #include <stdio.h>
24*3d8817e4Smiod #include "libiberty.h"
25*3d8817e4Smiod #include "as.h"
26*3d8817e4Smiod #include "struc-symbol.h"
27*3d8817e4Smiod #include "safe-ctype.h"
28*3d8817e4Smiod #include "subsegs.h"
29*3d8817e4Smiod #include "opcode/arc.h"
30*3d8817e4Smiod #include "../opcodes/arc-ext.h"
31*3d8817e4Smiod #include "elf/arc.h"
32*3d8817e4Smiod #include "dwarf2dbg.h"
33*3d8817e4Smiod 
34*3d8817e4Smiod const struct suffix_classes
35*3d8817e4Smiod {
36*3d8817e4Smiod   char *name;
37*3d8817e4Smiod   int  len;
38*3d8817e4Smiod } suffixclass[] =
39*3d8817e4Smiod {
40*3d8817e4Smiod   { "SUFFIX_COND|SUFFIX_FLAG",23 },
41*3d8817e4Smiod   { "SUFFIX_FLAG", 11 },
42*3d8817e4Smiod   { "SUFFIX_COND", 11 },
43*3d8817e4Smiod   { "SUFFIX_NONE", 11 }
44*3d8817e4Smiod };
45*3d8817e4Smiod 
46*3d8817e4Smiod #define MAXSUFFIXCLASS (sizeof (suffixclass) / sizeof (struct suffix_classes))
47*3d8817e4Smiod 
48*3d8817e4Smiod const struct syntax_classes
49*3d8817e4Smiod {
50*3d8817e4Smiod   char *name;
51*3d8817e4Smiod   int  len;
52*3d8817e4Smiod   int  class;
53*3d8817e4Smiod } syntaxclass[] =
54*3d8817e4Smiod {
55*3d8817e4Smiod   { "SYNTAX_3OP|OP1_MUST_BE_IMM", 26, SYNTAX_3OP|OP1_MUST_BE_IMM|SYNTAX_VALID },
56*3d8817e4Smiod   { "OP1_MUST_BE_IMM|SYNTAX_3OP", 26, OP1_MUST_BE_IMM|SYNTAX_3OP|SYNTAX_VALID },
57*3d8817e4Smiod   { "SYNTAX_2OP|OP1_IMM_IMPLIED", 26, SYNTAX_2OP|OP1_IMM_IMPLIED|SYNTAX_VALID },
58*3d8817e4Smiod   { "OP1_IMM_IMPLIED|SYNTAX_2OP", 26, OP1_IMM_IMPLIED|SYNTAX_2OP|SYNTAX_VALID },
59*3d8817e4Smiod   { "SYNTAX_3OP",                 10, SYNTAX_3OP|SYNTAX_VALID },
60*3d8817e4Smiod   { "SYNTAX_2OP",                 10, SYNTAX_2OP|SYNTAX_VALID }
61*3d8817e4Smiod };
62*3d8817e4Smiod 
63*3d8817e4Smiod #define MAXSYNTAXCLASS (sizeof (syntaxclass) / sizeof (struct syntax_classes))
64*3d8817e4Smiod 
65*3d8817e4Smiod /* This array holds the chars that always start a comment.  If the
66*3d8817e4Smiod    pre-processor is disabled, these aren't very useful.  */
67*3d8817e4Smiod const char comment_chars[] = "#;";
68*3d8817e4Smiod 
69*3d8817e4Smiod /* This array holds the chars that only start a comment at the beginning of
70*3d8817e4Smiod    a line.  If the line seems to have the form '# 123 filename'
71*3d8817e4Smiod    .line and .file directives will appear in the pre-processed output */
72*3d8817e4Smiod /* Note that input_file.c hand checks for '#' at the beginning of the
73*3d8817e4Smiod    first line of the input file.  This is because the compiler outputs
74*3d8817e4Smiod    #NO_APP at the beginning of its output.  */
75*3d8817e4Smiod /* Also note that comments started like this one will always
76*3d8817e4Smiod    work if '/' isn't otherwise defined.  */
77*3d8817e4Smiod const char line_comment_chars[] = "#";
78*3d8817e4Smiod 
79*3d8817e4Smiod const char line_separator_chars[] = "";
80*3d8817e4Smiod 
81*3d8817e4Smiod /* Chars that can be used to separate mant from exp in floating point nums.  */
82*3d8817e4Smiod const char EXP_CHARS[] = "eE";
83*3d8817e4Smiod 
84*3d8817e4Smiod /* Chars that mean this number is a floating point constant
85*3d8817e4Smiod    As in 0f12.456 or 0d1.2345e12.  */
86*3d8817e4Smiod const char FLT_CHARS[] = "rRsSfFdD";
87*3d8817e4Smiod 
88*3d8817e4Smiod /* Byte order.  */
89*3d8817e4Smiod extern int target_big_endian;
90*3d8817e4Smiod const char *arc_target_format = DEFAULT_TARGET_FORMAT;
91*3d8817e4Smiod static int byte_order = DEFAULT_BYTE_ORDER;
92*3d8817e4Smiod 
93*3d8817e4Smiod static segT arcext_section;
94*3d8817e4Smiod 
95*3d8817e4Smiod /* One of bfd_mach_arc_n.  */
96*3d8817e4Smiod static int arc_mach_type = bfd_mach_arc_6;
97*3d8817e4Smiod 
98*3d8817e4Smiod /* Non-zero if the cpu type has been explicitly specified.  */
99*3d8817e4Smiod static int mach_type_specified_p = 0;
100*3d8817e4Smiod 
101*3d8817e4Smiod /* Non-zero if opcode tables have been initialized.
102*3d8817e4Smiod    A .option command must appear before any instructions.  */
103*3d8817e4Smiod static int cpu_tables_init_p = 0;
104*3d8817e4Smiod 
105*3d8817e4Smiod static struct hash_control *arc_suffix_hash = NULL;
106*3d8817e4Smiod 
107*3d8817e4Smiod const char *md_shortopts = "";
108*3d8817e4Smiod 
109*3d8817e4Smiod enum options
110*3d8817e4Smiod {
111*3d8817e4Smiod   OPTION_EB = OPTION_MD_BASE,
112*3d8817e4Smiod   OPTION_EL,
113*3d8817e4Smiod   OPTION_ARC5,
114*3d8817e4Smiod   OPTION_ARC6,
115*3d8817e4Smiod   OPTION_ARC7,
116*3d8817e4Smiod   OPTION_ARC8,
117*3d8817e4Smiod   OPTION_ARC
118*3d8817e4Smiod };
119*3d8817e4Smiod 
120*3d8817e4Smiod struct option md_longopts[] =
121*3d8817e4Smiod {
122*3d8817e4Smiod   { "EB", no_argument, NULL, OPTION_EB },
123*3d8817e4Smiod   { "EL", no_argument, NULL, OPTION_EL },
124*3d8817e4Smiod   { "marc5", no_argument, NULL, OPTION_ARC5 },
125*3d8817e4Smiod   { "pre-v6", no_argument, NULL, OPTION_ARC5 },
126*3d8817e4Smiod   { "marc6", no_argument, NULL, OPTION_ARC6 },
127*3d8817e4Smiod   { "marc7", no_argument, NULL, OPTION_ARC7 },
128*3d8817e4Smiod   { "marc8", no_argument, NULL, OPTION_ARC8 },
129*3d8817e4Smiod   { "marc", no_argument, NULL, OPTION_ARC },
130*3d8817e4Smiod   { NULL, no_argument, NULL, 0 }
131*3d8817e4Smiod };
132*3d8817e4Smiod size_t md_longopts_size = sizeof (md_longopts);
133*3d8817e4Smiod 
134*3d8817e4Smiod #define IS_SYMBOL_OPERAND(o) \
135*3d8817e4Smiod  ((o) == 'b' || (o) == 'c' || (o) == 's' || (o) == 'o' || (o) == 'O')
136*3d8817e4Smiod 
137*3d8817e4Smiod struct arc_operand_value *get_ext_suffix (char *s);
138*3d8817e4Smiod 
139*3d8817e4Smiod /* Invocation line includes a switch not recognized by the base assembler.
140*3d8817e4Smiod    See if it's a processor-specific option.  */
141*3d8817e4Smiod 
142*3d8817e4Smiod int
md_parse_option(int c,char * arg ATTRIBUTE_UNUSED)143*3d8817e4Smiod md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
144*3d8817e4Smiod {
145*3d8817e4Smiod   switch (c)
146*3d8817e4Smiod     {
147*3d8817e4Smiod     case OPTION_ARC5:
148*3d8817e4Smiod       arc_mach_type = bfd_mach_arc_5;
149*3d8817e4Smiod       break;
150*3d8817e4Smiod     case OPTION_ARC:
151*3d8817e4Smiod     case OPTION_ARC6:
152*3d8817e4Smiod       arc_mach_type = bfd_mach_arc_6;
153*3d8817e4Smiod       break;
154*3d8817e4Smiod     case OPTION_ARC7:
155*3d8817e4Smiod       arc_mach_type = bfd_mach_arc_7;
156*3d8817e4Smiod       break;
157*3d8817e4Smiod     case OPTION_ARC8:
158*3d8817e4Smiod       arc_mach_type = bfd_mach_arc_8;
159*3d8817e4Smiod       break;
160*3d8817e4Smiod     case OPTION_EB:
161*3d8817e4Smiod       byte_order = BIG_ENDIAN;
162*3d8817e4Smiod       arc_target_format = "elf32-bigarc";
163*3d8817e4Smiod       break;
164*3d8817e4Smiod     case OPTION_EL:
165*3d8817e4Smiod       byte_order = LITTLE_ENDIAN;
166*3d8817e4Smiod       arc_target_format = "elf32-littlearc";
167*3d8817e4Smiod       break;
168*3d8817e4Smiod     default:
169*3d8817e4Smiod       return 0;
170*3d8817e4Smiod     }
171*3d8817e4Smiod   return 1;
172*3d8817e4Smiod }
173*3d8817e4Smiod 
174*3d8817e4Smiod void
md_show_usage(FILE * stream)175*3d8817e4Smiod md_show_usage (FILE *stream)
176*3d8817e4Smiod {
177*3d8817e4Smiod   fprintf (stream, "\
178*3d8817e4Smiod ARC Options:\n\
179*3d8817e4Smiod   -marc[5|6|7|8]          select processor variant (default arc%d)\n\
180*3d8817e4Smiod   -EB                     assemble code for a big endian cpu\n\
181*3d8817e4Smiod   -EL                     assemble code for a little endian cpu\n", arc_mach_type + 5);
182*3d8817e4Smiod }
183*3d8817e4Smiod 
184*3d8817e4Smiod /* This function is called once, at assembler startup time.  It should
185*3d8817e4Smiod    set up all the tables, etc. that the MD part of the assembler will need.
186*3d8817e4Smiod    Opcode selection is deferred until later because we might see a .option
187*3d8817e4Smiod    command.  */
188*3d8817e4Smiod 
189*3d8817e4Smiod void
md_begin(void)190*3d8817e4Smiod md_begin (void)
191*3d8817e4Smiod {
192*3d8817e4Smiod   /* The endianness can be chosen "at the factory".  */
193*3d8817e4Smiod   target_big_endian = byte_order == BIG_ENDIAN;
194*3d8817e4Smiod 
195*3d8817e4Smiod   if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, arc_mach_type))
196*3d8817e4Smiod     as_warn ("could not set architecture and machine");
197*3d8817e4Smiod 
198*3d8817e4Smiod   /* This call is necessary because we need to initialize `arc_operand_map'
199*3d8817e4Smiod      which may be needed before we see the first insn.  */
200*3d8817e4Smiod   arc_opcode_init_tables (arc_get_opcode_mach (arc_mach_type,
201*3d8817e4Smiod 					       target_big_endian));
202*3d8817e4Smiod }
203*3d8817e4Smiod 
204*3d8817e4Smiod /* Initialize the various opcode and operand tables.
205*3d8817e4Smiod    MACH is one of bfd_mach_arc_xxx.  */
206*3d8817e4Smiod 
207*3d8817e4Smiod static void
init_opcode_tables(int mach)208*3d8817e4Smiod init_opcode_tables (int mach)
209*3d8817e4Smiod {
210*3d8817e4Smiod   int i;
211*3d8817e4Smiod   char *last;
212*3d8817e4Smiod 
213*3d8817e4Smiod   if ((arc_suffix_hash = hash_new ()) == NULL)
214*3d8817e4Smiod     as_fatal ("virtual memory exhausted");
215*3d8817e4Smiod 
216*3d8817e4Smiod   if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach))
217*3d8817e4Smiod     as_warn ("could not set architecture and machine");
218*3d8817e4Smiod 
219*3d8817e4Smiod   /* This initializes a few things in arc-opc.c that we need.
220*3d8817e4Smiod      This must be called before the various arc_xxx_supported fns.  */
221*3d8817e4Smiod   arc_opcode_init_tables (arc_get_opcode_mach (mach, target_big_endian));
222*3d8817e4Smiod 
223*3d8817e4Smiod   /* Only put the first entry of each equivalently named suffix in the
224*3d8817e4Smiod      table.  */
225*3d8817e4Smiod   last = "";
226*3d8817e4Smiod   for (i = 0; i < arc_suffixes_count; i++)
227*3d8817e4Smiod     {
228*3d8817e4Smiod       if (strcmp (arc_suffixes[i].name, last) != 0)
229*3d8817e4Smiod 	hash_insert (arc_suffix_hash, arc_suffixes[i].name, (void *) (arc_suffixes + i));
230*3d8817e4Smiod       last = arc_suffixes[i].name;
231*3d8817e4Smiod     }
232*3d8817e4Smiod 
233*3d8817e4Smiod   /* Since registers don't have a prefix, we put them in the symbol table so
234*3d8817e4Smiod      they can't be used as symbols.  This also simplifies argument parsing as
235*3d8817e4Smiod      we can let gas parse registers for us.  The recorded register number is
236*3d8817e4Smiod      the address of the register's entry in arc_reg_names.
237*3d8817e4Smiod 
238*3d8817e4Smiod      If the register name is already in the table, then the existing
239*3d8817e4Smiod      definition is assumed to be from an .ExtCoreRegister pseudo-op.  */
240*3d8817e4Smiod 
241*3d8817e4Smiod   for (i = 0; i < arc_reg_names_count; i++)
242*3d8817e4Smiod     {
243*3d8817e4Smiod       if (symbol_find (arc_reg_names[i].name))
244*3d8817e4Smiod 	continue;
245*3d8817e4Smiod       /* Use symbol_create here instead of symbol_new so we don't try to
246*3d8817e4Smiod 	 output registers into the object file's symbol table.  */
247*3d8817e4Smiod       symbol_table_insert (symbol_create (arc_reg_names[i].name,
248*3d8817e4Smiod 					  reg_section,
249*3d8817e4Smiod 					  (valueT) &arc_reg_names[i],
250*3d8817e4Smiod 					  &zero_address_frag));
251*3d8817e4Smiod     }
252*3d8817e4Smiod 
253*3d8817e4Smiod   /* Tell `.option' it's too late.  */
254*3d8817e4Smiod   cpu_tables_init_p = 1;
255*3d8817e4Smiod }
256*3d8817e4Smiod 
257*3d8817e4Smiod /* Insert an operand value into an instruction.
258*3d8817e4Smiod    If REG is non-NULL, it is a register number and ignore VAL.  */
259*3d8817e4Smiod 
260*3d8817e4Smiod static arc_insn
arc_insert_operand(arc_insn insn,const struct arc_operand * operand,int mods,const struct arc_operand_value * reg,offsetT val,char * file,unsigned int line)261*3d8817e4Smiod arc_insert_operand (arc_insn insn,
262*3d8817e4Smiod 		    const struct arc_operand *operand,
263*3d8817e4Smiod 		    int mods,
264*3d8817e4Smiod 		    const struct arc_operand_value *reg,
265*3d8817e4Smiod 		    offsetT val,
266*3d8817e4Smiod 		    char *file,
267*3d8817e4Smiod 		    unsigned int line)
268*3d8817e4Smiod {
269*3d8817e4Smiod   if (operand->bits != 32)
270*3d8817e4Smiod     {
271*3d8817e4Smiod       long min, max;
272*3d8817e4Smiod       offsetT test;
273*3d8817e4Smiod 
274*3d8817e4Smiod       if ((operand->flags & ARC_OPERAND_SIGNED) != 0)
275*3d8817e4Smiod 	{
276*3d8817e4Smiod 	  if ((operand->flags & ARC_OPERAND_SIGNOPT) != 0)
277*3d8817e4Smiod 	    max = (1 << operand->bits) - 1;
278*3d8817e4Smiod 	  else
279*3d8817e4Smiod 	    max = (1 << (operand->bits - 1)) - 1;
280*3d8817e4Smiod 	  min = - (1 << (operand->bits - 1));
281*3d8817e4Smiod 	}
282*3d8817e4Smiod       else
283*3d8817e4Smiod 	{
284*3d8817e4Smiod 	  max = (1 << operand->bits) - 1;
285*3d8817e4Smiod 	  min = 0;
286*3d8817e4Smiod 	}
287*3d8817e4Smiod 
288*3d8817e4Smiod       if ((operand->flags & ARC_OPERAND_NEGATIVE) != 0)
289*3d8817e4Smiod 	test = - val;
290*3d8817e4Smiod       else
291*3d8817e4Smiod 	test = val;
292*3d8817e4Smiod 
293*3d8817e4Smiod       if (test < (offsetT) min || test > (offsetT) max)
294*3d8817e4Smiod 	as_warn_value_out_of_range (_("operand"), test, (offsetT) min, (offsetT) max, file, line);
295*3d8817e4Smiod     }
296*3d8817e4Smiod 
297*3d8817e4Smiod   if (operand->insert)
298*3d8817e4Smiod     {
299*3d8817e4Smiod       const char *errmsg;
300*3d8817e4Smiod 
301*3d8817e4Smiod       errmsg = NULL;
302*3d8817e4Smiod       insn = (*operand->insert) (insn, operand, mods, reg, (long) val, &errmsg);
303*3d8817e4Smiod       if (errmsg != (const char *) NULL)
304*3d8817e4Smiod 	as_warn (errmsg);
305*3d8817e4Smiod     }
306*3d8817e4Smiod   else
307*3d8817e4Smiod     insn |= (((long) val & ((1 << operand->bits) - 1))
308*3d8817e4Smiod 	     << operand->shift);
309*3d8817e4Smiod 
310*3d8817e4Smiod   return insn;
311*3d8817e4Smiod }
312*3d8817e4Smiod 
313*3d8817e4Smiod /* We need to keep a list of fixups.  We can't simply generate them as
314*3d8817e4Smiod    we go, because that would require us to first create the frag, and
315*3d8817e4Smiod    that would screw up references to ``.''.  */
316*3d8817e4Smiod 
317*3d8817e4Smiod struct arc_fixup
318*3d8817e4Smiod {
319*3d8817e4Smiod   /* index into `arc_operands'  */
320*3d8817e4Smiod   int opindex;
321*3d8817e4Smiod   expressionS exp;
322*3d8817e4Smiod };
323*3d8817e4Smiod 
324*3d8817e4Smiod #define MAX_FIXUPS 5
325*3d8817e4Smiod 
326*3d8817e4Smiod #define MAX_SUFFIXES 5
327*3d8817e4Smiod 
328*3d8817e4Smiod /* Compute the reloc type of an expression.
329*3d8817e4Smiod    The possibly modified expression is stored in EXPNEW.
330*3d8817e4Smiod 
331*3d8817e4Smiod    This is used to convert the expressions generated by the %-op's into
332*3d8817e4Smiod    the appropriate operand type.  It is called for both data in instructions
333*3d8817e4Smiod    (operands) and data outside instructions (variables, debugging info, etc.).
334*3d8817e4Smiod 
335*3d8817e4Smiod    Currently supported %-ops:
336*3d8817e4Smiod 
337*3d8817e4Smiod    %st(symbol): represented as "symbol >> 2"
338*3d8817e4Smiod                 "st" is short for STatus as in the status register (pc)
339*3d8817e4Smiod 
340*3d8817e4Smiod    DEFAULT_TYPE is the type to use if no special processing is required.
341*3d8817e4Smiod 
342*3d8817e4Smiod    DATA_P is non-zero for data or limm values, zero for insn operands.
343*3d8817e4Smiod    Remember that the opcode "insertion fns" cannot be used on data, they're
344*3d8817e4Smiod    only for inserting operands into insns.  They also can't be used for limm
345*3d8817e4Smiod    values as the insertion routines don't handle limm values.  When called for
346*3d8817e4Smiod    insns we return fudged reloc types (real_value - BFD_RELOC_UNUSED).  When
347*3d8817e4Smiod    called for data or limm values we use real reloc types.  */
348*3d8817e4Smiod 
349*3d8817e4Smiod static int
get_arc_exp_reloc_type(int data_p,int default_type,expressionS * exp,expressionS * expnew)350*3d8817e4Smiod get_arc_exp_reloc_type (int data_p,
351*3d8817e4Smiod 			int default_type,
352*3d8817e4Smiod 			expressionS *exp,
353*3d8817e4Smiod 			expressionS *expnew)
354*3d8817e4Smiod {
355*3d8817e4Smiod   /* If the expression is "symbol >> 2" we must change it to just "symbol",
356*3d8817e4Smiod      as fix_new_exp can't handle it.  Similarly for (symbol - symbol) >> 2.
357*3d8817e4Smiod      That's ok though.  What's really going on here is that we're using
358*3d8817e4Smiod      ">> 2" as a special syntax for specifying BFD_RELOC_ARC_B26.  */
359*3d8817e4Smiod 
360*3d8817e4Smiod   if (exp->X_op == O_right_shift
361*3d8817e4Smiod       && exp->X_op_symbol != NULL
362*3d8817e4Smiod       && exp->X_op_symbol->sy_value.X_op == O_constant
363*3d8817e4Smiod       && exp->X_op_symbol->sy_value.X_add_number == 2
364*3d8817e4Smiod       && exp->X_add_number == 0)
365*3d8817e4Smiod     {
366*3d8817e4Smiod       if (exp->X_add_symbol != NULL
367*3d8817e4Smiod 	  && (exp->X_add_symbol->sy_value.X_op == O_constant
368*3d8817e4Smiod 	      || exp->X_add_symbol->sy_value.X_op == O_symbol))
369*3d8817e4Smiod 	{
370*3d8817e4Smiod 	  *expnew = *exp;
371*3d8817e4Smiod 	  expnew->X_op = O_symbol;
372*3d8817e4Smiod 	  expnew->X_op_symbol = NULL;
373*3d8817e4Smiod 	  return data_p ? BFD_RELOC_ARC_B26 : arc_operand_map['J'];
374*3d8817e4Smiod 	}
375*3d8817e4Smiod       else if (exp->X_add_symbol != NULL
376*3d8817e4Smiod 	       && exp->X_add_symbol->sy_value.X_op == O_subtract)
377*3d8817e4Smiod 	{
378*3d8817e4Smiod 	  *expnew = exp->X_add_symbol->sy_value;
379*3d8817e4Smiod 	  return data_p ? BFD_RELOC_ARC_B26 : arc_operand_map['J'];
380*3d8817e4Smiod 	}
381*3d8817e4Smiod     }
382*3d8817e4Smiod 
383*3d8817e4Smiod   *expnew = *exp;
384*3d8817e4Smiod   return default_type;
385*3d8817e4Smiod }
386*3d8817e4Smiod 
387*3d8817e4Smiod static int
arc_set_ext_seg(void)388*3d8817e4Smiod arc_set_ext_seg (void)
389*3d8817e4Smiod {
390*3d8817e4Smiod   if (!arcext_section)
391*3d8817e4Smiod     {
392*3d8817e4Smiod       arcext_section = subseg_new (".arcextmap", 0);
393*3d8817e4Smiod       bfd_set_section_flags (stdoutput, arcext_section,
394*3d8817e4Smiod 			     SEC_READONLY | SEC_HAS_CONTENTS);
395*3d8817e4Smiod     }
396*3d8817e4Smiod   else
397*3d8817e4Smiod     subseg_set (arcext_section, 0);
398*3d8817e4Smiod   return 1;
399*3d8817e4Smiod }
400*3d8817e4Smiod 
401*3d8817e4Smiod static void
arc_extoper(int opertype)402*3d8817e4Smiod arc_extoper (int opertype)
403*3d8817e4Smiod {
404*3d8817e4Smiod   char *name;
405*3d8817e4Smiod   char *mode;
406*3d8817e4Smiod   char c;
407*3d8817e4Smiod   char *p;
408*3d8817e4Smiod   int imode = 0;
409*3d8817e4Smiod   int number;
410*3d8817e4Smiod   struct arc_ext_operand_value *ext_oper;
411*3d8817e4Smiod   symbolS *symbolP;
412*3d8817e4Smiod 
413*3d8817e4Smiod   segT old_sec;
414*3d8817e4Smiod   int old_subsec;
415*3d8817e4Smiod 
416*3d8817e4Smiod   name = input_line_pointer;
417*3d8817e4Smiod   c = get_symbol_end ();
418*3d8817e4Smiod   name = xstrdup (name);
419*3d8817e4Smiod 
420*3d8817e4Smiod   p = name;
421*3d8817e4Smiod   while (*p)
422*3d8817e4Smiod     {
423*3d8817e4Smiod       *p = TOLOWER (*p);
424*3d8817e4Smiod       p++;
425*3d8817e4Smiod     }
426*3d8817e4Smiod 
427*3d8817e4Smiod   /* just after name is now '\0'  */
428*3d8817e4Smiod   p = input_line_pointer;
429*3d8817e4Smiod   *p = c;
430*3d8817e4Smiod   SKIP_WHITESPACE ();
431*3d8817e4Smiod 
432*3d8817e4Smiod   if (*input_line_pointer != ',')
433*3d8817e4Smiod     {
434*3d8817e4Smiod       as_bad ("expected comma after operand name");
435*3d8817e4Smiod       ignore_rest_of_line ();
436*3d8817e4Smiod       free (name);
437*3d8817e4Smiod       return;
438*3d8817e4Smiod     }
439*3d8817e4Smiod 
440*3d8817e4Smiod   input_line_pointer++;		/* skip ','  */
441*3d8817e4Smiod   number = get_absolute_expression ();
442*3d8817e4Smiod 
443*3d8817e4Smiod   if (number < 0)
444*3d8817e4Smiod     {
445*3d8817e4Smiod       as_bad ("negative operand number %d", number);
446*3d8817e4Smiod       ignore_rest_of_line ();
447*3d8817e4Smiod       free (name);
448*3d8817e4Smiod       return;
449*3d8817e4Smiod     }
450*3d8817e4Smiod 
451*3d8817e4Smiod   if (opertype)
452*3d8817e4Smiod     {
453*3d8817e4Smiod       SKIP_WHITESPACE ();
454*3d8817e4Smiod 
455*3d8817e4Smiod       if (*input_line_pointer != ',')
456*3d8817e4Smiod 	{
457*3d8817e4Smiod 	  as_bad ("expected comma after register-number");
458*3d8817e4Smiod 	  ignore_rest_of_line ();
459*3d8817e4Smiod 	  free (name);
460*3d8817e4Smiod 	  return;
461*3d8817e4Smiod 	}
462*3d8817e4Smiod 
463*3d8817e4Smiod       input_line_pointer++;		/* skip ','  */
464*3d8817e4Smiod       mode = input_line_pointer;
465*3d8817e4Smiod 
466*3d8817e4Smiod       if (!strncmp (mode, "r|w", 3))
467*3d8817e4Smiod 	{
468*3d8817e4Smiod 	  imode = 0;
469*3d8817e4Smiod 	  input_line_pointer += 3;
470*3d8817e4Smiod 	}
471*3d8817e4Smiod       else
472*3d8817e4Smiod 	{
473*3d8817e4Smiod 	  if (!strncmp (mode, "r", 1))
474*3d8817e4Smiod 	    {
475*3d8817e4Smiod 	      imode = ARC_REGISTER_READONLY;
476*3d8817e4Smiod 	      input_line_pointer += 1;
477*3d8817e4Smiod 	    }
478*3d8817e4Smiod 	  else
479*3d8817e4Smiod 	    {
480*3d8817e4Smiod 	      if (strncmp (mode, "w", 1))
481*3d8817e4Smiod 		{
482*3d8817e4Smiod 		  as_bad ("invalid mode");
483*3d8817e4Smiod 		  ignore_rest_of_line ();
484*3d8817e4Smiod 		  free (name);
485*3d8817e4Smiod 		  return;
486*3d8817e4Smiod 		}
487*3d8817e4Smiod 	      else
488*3d8817e4Smiod 		{
489*3d8817e4Smiod 		  imode = ARC_REGISTER_WRITEONLY;
490*3d8817e4Smiod 		  input_line_pointer += 1;
491*3d8817e4Smiod 		}
492*3d8817e4Smiod 	    }
493*3d8817e4Smiod 	}
494*3d8817e4Smiod       SKIP_WHITESPACE ();
495*3d8817e4Smiod       if (1 == opertype)
496*3d8817e4Smiod 	{
497*3d8817e4Smiod 	  if (*input_line_pointer != ',')
498*3d8817e4Smiod 	    {
499*3d8817e4Smiod 	      as_bad ("expected comma after register-mode");
500*3d8817e4Smiod 	      ignore_rest_of_line ();
501*3d8817e4Smiod 	      free (name);
502*3d8817e4Smiod 	      return;
503*3d8817e4Smiod 	    }
504*3d8817e4Smiod 
505*3d8817e4Smiod 	  input_line_pointer++;		/* skip ','  */
506*3d8817e4Smiod 
507*3d8817e4Smiod 	  if (!strncmp (input_line_pointer, "cannot_shortcut", 15))
508*3d8817e4Smiod 	    {
509*3d8817e4Smiod 	      imode |= arc_get_noshortcut_flag ();
510*3d8817e4Smiod 	      input_line_pointer += 15;
511*3d8817e4Smiod 	    }
512*3d8817e4Smiod 	  else
513*3d8817e4Smiod 	    {
514*3d8817e4Smiod 	      if (strncmp (input_line_pointer, "can_shortcut", 12))
515*3d8817e4Smiod 		{
516*3d8817e4Smiod 		  as_bad ("shortcut designator invalid");
517*3d8817e4Smiod 		  ignore_rest_of_line ();
518*3d8817e4Smiod 		  free (name);
519*3d8817e4Smiod 		  return;
520*3d8817e4Smiod 		}
521*3d8817e4Smiod 	      else
522*3d8817e4Smiod 		{
523*3d8817e4Smiod 		  input_line_pointer += 12;
524*3d8817e4Smiod 		}
525*3d8817e4Smiod 	    }
526*3d8817e4Smiod 	}
527*3d8817e4Smiod     }
528*3d8817e4Smiod 
529*3d8817e4Smiod   if ((opertype == 1) && number > 60)
530*3d8817e4Smiod     {
531*3d8817e4Smiod       as_bad ("core register value (%d) too large", number);
532*3d8817e4Smiod       ignore_rest_of_line ();
533*3d8817e4Smiod       free (name);
534*3d8817e4Smiod       return;
535*3d8817e4Smiod     }
536*3d8817e4Smiod 
537*3d8817e4Smiod   if ((opertype == 0) && number > 31)
538*3d8817e4Smiod     {
539*3d8817e4Smiod       as_bad ("condition code value (%d) too large", number);
540*3d8817e4Smiod       ignore_rest_of_line ();
541*3d8817e4Smiod       free (name);
542*3d8817e4Smiod       return;
543*3d8817e4Smiod     }
544*3d8817e4Smiod 
545*3d8817e4Smiod   ext_oper = xmalloc (sizeof (struct arc_ext_operand_value));
546*3d8817e4Smiod 
547*3d8817e4Smiod   if (opertype)
548*3d8817e4Smiod     {
549*3d8817e4Smiod       /* If the symbol already exists, point it at the new definition.  */
550*3d8817e4Smiod       if ((symbolP = symbol_find (name)))
551*3d8817e4Smiod 	{
552*3d8817e4Smiod 	  if (S_GET_SEGMENT (symbolP) == reg_section)
553*3d8817e4Smiod 	    S_SET_VALUE (symbolP, (valueT) &ext_oper->operand);
554*3d8817e4Smiod 	  else
555*3d8817e4Smiod 	    {
556*3d8817e4Smiod 	      as_bad ("attempt to override symbol: %s", name);
557*3d8817e4Smiod 	      ignore_rest_of_line ();
558*3d8817e4Smiod 	      free (name);
559*3d8817e4Smiod 	      free (ext_oper);
560*3d8817e4Smiod 	      return;
561*3d8817e4Smiod 	    }
562*3d8817e4Smiod 	}
563*3d8817e4Smiod       else
564*3d8817e4Smiod 	{
565*3d8817e4Smiod 	  /* If its not there, add it.  */
566*3d8817e4Smiod 	  symbol_table_insert (symbol_create (name, reg_section,
567*3d8817e4Smiod 					      (valueT) &ext_oper->operand,
568*3d8817e4Smiod 					      &zero_address_frag));
569*3d8817e4Smiod 	}
570*3d8817e4Smiod     }
571*3d8817e4Smiod 
572*3d8817e4Smiod   ext_oper->operand.name  = name;
573*3d8817e4Smiod   ext_oper->operand.value = number;
574*3d8817e4Smiod   ext_oper->operand.type  = arc_operand_type (opertype);
575*3d8817e4Smiod   ext_oper->operand.flags = imode;
576*3d8817e4Smiod 
577*3d8817e4Smiod   ext_oper->next = arc_ext_operands;
578*3d8817e4Smiod   arc_ext_operands = ext_oper;
579*3d8817e4Smiod 
580*3d8817e4Smiod   /* OK, now that we know what this operand is, put a description in
581*3d8817e4Smiod      the arc extension section of the output file.  */
582*3d8817e4Smiod 
583*3d8817e4Smiod   old_sec    = now_seg;
584*3d8817e4Smiod   old_subsec = now_subseg;
585*3d8817e4Smiod 
586*3d8817e4Smiod   arc_set_ext_seg ();
587*3d8817e4Smiod 
588*3d8817e4Smiod   switch (opertype)
589*3d8817e4Smiod     {
590*3d8817e4Smiod     case 0:
591*3d8817e4Smiod       p = frag_more (1);
592*3d8817e4Smiod       *p = 3 + strlen (name) + 1;
593*3d8817e4Smiod       p = frag_more (1);
594*3d8817e4Smiod       *p = EXT_COND_CODE;
595*3d8817e4Smiod       p = frag_more (1);
596*3d8817e4Smiod       *p = number;
597*3d8817e4Smiod       p = frag_more (strlen (name) + 1);
598*3d8817e4Smiod       strcpy (p, name);
599*3d8817e4Smiod       break;
600*3d8817e4Smiod     case 1:
601*3d8817e4Smiod       p = frag_more (1);
602*3d8817e4Smiod       *p = 3 + strlen (name) + 1;
603*3d8817e4Smiod       p = frag_more (1);
604*3d8817e4Smiod       *p = EXT_CORE_REGISTER;
605*3d8817e4Smiod       p = frag_more (1);
606*3d8817e4Smiod       *p = number;
607*3d8817e4Smiod       p = frag_more (strlen (name) + 1);
608*3d8817e4Smiod       strcpy (p, name);
609*3d8817e4Smiod       break;
610*3d8817e4Smiod     case 2:
611*3d8817e4Smiod       p = frag_more (1);
612*3d8817e4Smiod       *p = 6 + strlen (name) + 1;
613*3d8817e4Smiod       p = frag_more (1);
614*3d8817e4Smiod       *p = EXT_AUX_REGISTER;
615*3d8817e4Smiod       p = frag_more (1);
616*3d8817e4Smiod       *p = number >> 24 & 0xff;
617*3d8817e4Smiod       p = frag_more (1);
618*3d8817e4Smiod       *p = number >> 16 & 0xff;
619*3d8817e4Smiod       p = frag_more (1);
620*3d8817e4Smiod       *p = number >>  8 & 0xff;
621*3d8817e4Smiod       p = frag_more (1);
622*3d8817e4Smiod       *p = number       & 0xff;
623*3d8817e4Smiod       p = frag_more (strlen (name) + 1);
624*3d8817e4Smiod       strcpy (p, name);
625*3d8817e4Smiod       break;
626*3d8817e4Smiod     default:
627*3d8817e4Smiod       as_bad ("invalid opertype");
628*3d8817e4Smiod       ignore_rest_of_line ();
629*3d8817e4Smiod       free (name);
630*3d8817e4Smiod       return;
631*3d8817e4Smiod       break;
632*3d8817e4Smiod     }
633*3d8817e4Smiod 
634*3d8817e4Smiod   subseg_set (old_sec, old_subsec);
635*3d8817e4Smiod 
636*3d8817e4Smiod   /* Enter all registers into the symbol table.  */
637*3d8817e4Smiod 
638*3d8817e4Smiod   demand_empty_rest_of_line ();
639*3d8817e4Smiod }
640*3d8817e4Smiod 
641*3d8817e4Smiod static void
arc_extinst(int ignore ATTRIBUTE_UNUSED)642*3d8817e4Smiod arc_extinst (int ignore ATTRIBUTE_UNUSED)
643*3d8817e4Smiod {
644*3d8817e4Smiod   char syntax[129];
645*3d8817e4Smiod   char *name;
646*3d8817e4Smiod   char *p;
647*3d8817e4Smiod   char c;
648*3d8817e4Smiod   int suffixcode = -1;
649*3d8817e4Smiod   int opcode, subopcode;
650*3d8817e4Smiod   int i;
651*3d8817e4Smiod   int class = 0;
652*3d8817e4Smiod   int name_len;
653*3d8817e4Smiod   struct arc_opcode *ext_op;
654*3d8817e4Smiod 
655*3d8817e4Smiod   segT old_sec;
656*3d8817e4Smiod   int old_subsec;
657*3d8817e4Smiod 
658*3d8817e4Smiod   name = input_line_pointer;
659*3d8817e4Smiod   c = get_symbol_end ();
660*3d8817e4Smiod   name = xstrdup (name);
661*3d8817e4Smiod   strcpy (syntax, name);
662*3d8817e4Smiod   name_len = strlen (name);
663*3d8817e4Smiod 
664*3d8817e4Smiod   /* just after name is now '\0'  */
665*3d8817e4Smiod   p = input_line_pointer;
666*3d8817e4Smiod   *p = c;
667*3d8817e4Smiod 
668*3d8817e4Smiod   SKIP_WHITESPACE ();
669*3d8817e4Smiod 
670*3d8817e4Smiod   if (*input_line_pointer != ',')
671*3d8817e4Smiod     {
672*3d8817e4Smiod       as_bad ("expected comma after operand name");
673*3d8817e4Smiod       ignore_rest_of_line ();
674*3d8817e4Smiod       return;
675*3d8817e4Smiod     }
676*3d8817e4Smiod 
677*3d8817e4Smiod   input_line_pointer++;		/* skip ','  */
678*3d8817e4Smiod   opcode = get_absolute_expression ();
679*3d8817e4Smiod 
680*3d8817e4Smiod   SKIP_WHITESPACE ();
681*3d8817e4Smiod 
682*3d8817e4Smiod   if (*input_line_pointer != ',')
683*3d8817e4Smiod     {
684*3d8817e4Smiod       as_bad ("expected comma after opcode");
685*3d8817e4Smiod       ignore_rest_of_line ();
686*3d8817e4Smiod       return;
687*3d8817e4Smiod     }
688*3d8817e4Smiod 
689*3d8817e4Smiod   input_line_pointer++;		/* skip ','  */
690*3d8817e4Smiod   subopcode = get_absolute_expression ();
691*3d8817e4Smiod 
692*3d8817e4Smiod   if (subopcode < 0)
693*3d8817e4Smiod     {
694*3d8817e4Smiod       as_bad ("negative subopcode %d", subopcode);
695*3d8817e4Smiod       ignore_rest_of_line ();
696*3d8817e4Smiod       return;
697*3d8817e4Smiod     }
698*3d8817e4Smiod 
699*3d8817e4Smiod   if (subopcode)
700*3d8817e4Smiod     {
701*3d8817e4Smiod       if (3 != opcode)
702*3d8817e4Smiod 	{
703*3d8817e4Smiod 	  as_bad ("subcode value found when opcode not equal 0x03");
704*3d8817e4Smiod 	  ignore_rest_of_line ();
705*3d8817e4Smiod 	  return;
706*3d8817e4Smiod 	}
707*3d8817e4Smiod       else
708*3d8817e4Smiod 	{
709*3d8817e4Smiod 	  if (subopcode < 0x09 || subopcode == 0x3f)
710*3d8817e4Smiod 	    {
711*3d8817e4Smiod 	      as_bad ("invalid subopcode %d", subopcode);
712*3d8817e4Smiod 	      ignore_rest_of_line ();
713*3d8817e4Smiod 	      return;
714*3d8817e4Smiod 	    }
715*3d8817e4Smiod 	}
716*3d8817e4Smiod     }
717*3d8817e4Smiod 
718*3d8817e4Smiod   SKIP_WHITESPACE ();
719*3d8817e4Smiod 
720*3d8817e4Smiod   if (*input_line_pointer != ',')
721*3d8817e4Smiod     {
722*3d8817e4Smiod       as_bad ("expected comma after subopcode");
723*3d8817e4Smiod       ignore_rest_of_line ();
724*3d8817e4Smiod       return;
725*3d8817e4Smiod     }
726*3d8817e4Smiod 
727*3d8817e4Smiod   input_line_pointer++;		/* skip ','  */
728*3d8817e4Smiod 
729*3d8817e4Smiod   for (i = 0; i < (int) MAXSUFFIXCLASS; i++)
730*3d8817e4Smiod     {
731*3d8817e4Smiod       if (!strncmp (suffixclass[i].name,input_line_pointer, suffixclass[i].len))
732*3d8817e4Smiod 	{
733*3d8817e4Smiod 	  suffixcode = i;
734*3d8817e4Smiod 	  input_line_pointer += suffixclass[i].len;
735*3d8817e4Smiod 	  break;
736*3d8817e4Smiod 	}
737*3d8817e4Smiod     }
738*3d8817e4Smiod 
739*3d8817e4Smiod   if (-1 == suffixcode)
740*3d8817e4Smiod     {
741*3d8817e4Smiod       as_bad ("invalid suffix class");
742*3d8817e4Smiod       ignore_rest_of_line ();
743*3d8817e4Smiod       return;
744*3d8817e4Smiod     }
745*3d8817e4Smiod 
746*3d8817e4Smiod   SKIP_WHITESPACE ();
747*3d8817e4Smiod 
748*3d8817e4Smiod   if (*input_line_pointer != ',')
749*3d8817e4Smiod     {
750*3d8817e4Smiod       as_bad ("expected comma after suffix class");
751*3d8817e4Smiod       ignore_rest_of_line ();
752*3d8817e4Smiod       return;
753*3d8817e4Smiod     }
754*3d8817e4Smiod 
755*3d8817e4Smiod   input_line_pointer++;		/* skip ','  */
756*3d8817e4Smiod 
757*3d8817e4Smiod   for (i = 0; i < (int) MAXSYNTAXCLASS; i++)
758*3d8817e4Smiod     {
759*3d8817e4Smiod       if (!strncmp (syntaxclass[i].name,input_line_pointer, syntaxclass[i].len))
760*3d8817e4Smiod 	{
761*3d8817e4Smiod 	  class = syntaxclass[i].class;
762*3d8817e4Smiod 	  input_line_pointer += syntaxclass[i].len;
763*3d8817e4Smiod 	  break;
764*3d8817e4Smiod 	}
765*3d8817e4Smiod     }
766*3d8817e4Smiod 
767*3d8817e4Smiod   if (0 == (SYNTAX_VALID & class))
768*3d8817e4Smiod     {
769*3d8817e4Smiod       as_bad ("invalid syntax class");
770*3d8817e4Smiod       ignore_rest_of_line ();
771*3d8817e4Smiod       return;
772*3d8817e4Smiod     }
773*3d8817e4Smiod 
774*3d8817e4Smiod   if ((0x3 == opcode) & (class & SYNTAX_3OP))
775*3d8817e4Smiod     {
776*3d8817e4Smiod       as_bad ("opcode 0x3 and SYNTAX_3OP invalid");
777*3d8817e4Smiod       ignore_rest_of_line ();
778*3d8817e4Smiod       return;
779*3d8817e4Smiod     }
780*3d8817e4Smiod 
781*3d8817e4Smiod   switch (suffixcode)
782*3d8817e4Smiod     {
783*3d8817e4Smiod     case 0:
784*3d8817e4Smiod       strcat (syntax, "%.q%.f ");
785*3d8817e4Smiod       break;
786*3d8817e4Smiod     case 1:
787*3d8817e4Smiod       strcat (syntax, "%.f ");
788*3d8817e4Smiod       break;
789*3d8817e4Smiod     case 2:
790*3d8817e4Smiod       strcat (syntax, "%.q ");
791*3d8817e4Smiod       break;
792*3d8817e4Smiod     case 3:
793*3d8817e4Smiod       strcat (syntax, " ");
794*3d8817e4Smiod       break;
795*3d8817e4Smiod     default:
796*3d8817e4Smiod       as_bad ("unknown suffix class");
797*3d8817e4Smiod       ignore_rest_of_line ();
798*3d8817e4Smiod       return;
799*3d8817e4Smiod       break;
800*3d8817e4Smiod     };
801*3d8817e4Smiod 
802*3d8817e4Smiod   strcat (syntax, ((opcode == 0x3) ? "%a,%b" : ((class & SYNTAX_3OP) ? "%a,%b,%c" : "%b,%c")));
803*3d8817e4Smiod   if (suffixcode < 2)
804*3d8817e4Smiod     strcat (syntax, "%F");
805*3d8817e4Smiod   strcat (syntax, "%S%L");
806*3d8817e4Smiod 
807*3d8817e4Smiod   ext_op = xmalloc (sizeof (struct arc_opcode));
808*3d8817e4Smiod   ext_op->syntax = xstrdup (syntax);
809*3d8817e4Smiod 
810*3d8817e4Smiod   ext_op->mask  = I (-1) | ((0x3 == opcode) ? C (-1) : 0);
811*3d8817e4Smiod   ext_op->value = I (opcode) | ((0x3 == opcode) ? C (subopcode) : 0);
812*3d8817e4Smiod   ext_op->flags = class;
813*3d8817e4Smiod   ext_op->next_asm = arc_ext_opcodes;
814*3d8817e4Smiod   ext_op->next_dis = arc_ext_opcodes;
815*3d8817e4Smiod   arc_ext_opcodes = ext_op;
816*3d8817e4Smiod 
817*3d8817e4Smiod   /* OK, now that we know what this inst is, put a description in the
818*3d8817e4Smiod      arc extension section of the output file.  */
819*3d8817e4Smiod 
820*3d8817e4Smiod   old_sec    = now_seg;
821*3d8817e4Smiod   old_subsec = now_subseg;
822*3d8817e4Smiod 
823*3d8817e4Smiod   arc_set_ext_seg ();
824*3d8817e4Smiod 
825*3d8817e4Smiod   p = frag_more (1);
826*3d8817e4Smiod   *p = 5 + name_len + 1;
827*3d8817e4Smiod   p = frag_more (1);
828*3d8817e4Smiod   *p = EXT_INSTRUCTION;
829*3d8817e4Smiod   p = frag_more (1);
830*3d8817e4Smiod   *p = opcode;
831*3d8817e4Smiod   p = frag_more (1);
832*3d8817e4Smiod   *p = subopcode;
833*3d8817e4Smiod   p = frag_more (1);
834*3d8817e4Smiod   *p = (class & (OP1_MUST_BE_IMM | OP1_IMM_IMPLIED) ? IGNORE_FIRST_OPD : 0);
835*3d8817e4Smiod   p = frag_more (name_len);
836*3d8817e4Smiod   strncpy (p, syntax, name_len);
837*3d8817e4Smiod   p = frag_more (1);
838*3d8817e4Smiod   *p = '\0';
839*3d8817e4Smiod 
840*3d8817e4Smiod   subseg_set (old_sec, old_subsec);
841*3d8817e4Smiod 
842*3d8817e4Smiod   demand_empty_rest_of_line ();
843*3d8817e4Smiod }
844*3d8817e4Smiod 
845*3d8817e4Smiod static void
arc_common(int localScope)846*3d8817e4Smiod arc_common (int localScope)
847*3d8817e4Smiod {
848*3d8817e4Smiod   char *name;
849*3d8817e4Smiod   char c;
850*3d8817e4Smiod   char *p;
851*3d8817e4Smiod   int align, size;
852*3d8817e4Smiod   symbolS *symbolP;
853*3d8817e4Smiod 
854*3d8817e4Smiod   name = input_line_pointer;
855*3d8817e4Smiod   c = get_symbol_end ();
856*3d8817e4Smiod   /* just after name is now '\0'  */
857*3d8817e4Smiod   p = input_line_pointer;
858*3d8817e4Smiod   *p = c;
859*3d8817e4Smiod   SKIP_WHITESPACE ();
860*3d8817e4Smiod 
861*3d8817e4Smiod   if (*input_line_pointer != ',')
862*3d8817e4Smiod     {
863*3d8817e4Smiod       as_bad ("expected comma after symbol name");
864*3d8817e4Smiod       ignore_rest_of_line ();
865*3d8817e4Smiod       return;
866*3d8817e4Smiod     }
867*3d8817e4Smiod 
868*3d8817e4Smiod   input_line_pointer++;		/* skip ','  */
869*3d8817e4Smiod   size = get_absolute_expression ();
870*3d8817e4Smiod 
871*3d8817e4Smiod   if (size < 0)
872*3d8817e4Smiod     {
873*3d8817e4Smiod       as_bad ("negative symbol length");
874*3d8817e4Smiod       ignore_rest_of_line ();
875*3d8817e4Smiod       return;
876*3d8817e4Smiod     }
877*3d8817e4Smiod 
878*3d8817e4Smiod   *p = 0;
879*3d8817e4Smiod   symbolP = symbol_find_or_make (name);
880*3d8817e4Smiod   *p = c;
881*3d8817e4Smiod 
882*3d8817e4Smiod   if (S_IS_DEFINED (symbolP) && ! S_IS_COMMON (symbolP))
883*3d8817e4Smiod     {
884*3d8817e4Smiod       as_bad ("ignoring attempt to re-define symbol");
885*3d8817e4Smiod       ignore_rest_of_line ();
886*3d8817e4Smiod       return;
887*3d8817e4Smiod     }
888*3d8817e4Smiod   if (((int) S_GET_VALUE (symbolP) != 0) \
889*3d8817e4Smiod       && ((int) S_GET_VALUE (symbolP) != size))
890*3d8817e4Smiod     {
891*3d8817e4Smiod       as_warn ("length of symbol \"%s\" already %ld, ignoring %d",
892*3d8817e4Smiod 	       S_GET_NAME (symbolP), (long) S_GET_VALUE (symbolP), size);
893*3d8817e4Smiod     }
894*3d8817e4Smiod   assert (symbolP->sy_frag == &zero_address_frag);
895*3d8817e4Smiod 
896*3d8817e4Smiod   /* Now parse the alignment field.  This field is optional for
897*3d8817e4Smiod      local and global symbols. Default alignment is zero.  */
898*3d8817e4Smiod   if (*input_line_pointer == ',')
899*3d8817e4Smiod     {
900*3d8817e4Smiod       input_line_pointer++;
901*3d8817e4Smiod       align = get_absolute_expression ();
902*3d8817e4Smiod       if (align < 0)
903*3d8817e4Smiod 	{
904*3d8817e4Smiod 	  align = 0;
905*3d8817e4Smiod 	  as_warn ("assuming symbol alignment of zero");
906*3d8817e4Smiod 	}
907*3d8817e4Smiod     }
908*3d8817e4Smiod   else
909*3d8817e4Smiod     align = 0;
910*3d8817e4Smiod 
911*3d8817e4Smiod   if (localScope != 0)
912*3d8817e4Smiod     {
913*3d8817e4Smiod       segT old_sec;
914*3d8817e4Smiod       int old_subsec;
915*3d8817e4Smiod       char *pfrag;
916*3d8817e4Smiod 
917*3d8817e4Smiod       old_sec    = now_seg;
918*3d8817e4Smiod       old_subsec = now_subseg;
919*3d8817e4Smiod       record_alignment (bss_section, align);
920*3d8817e4Smiod       subseg_set (bss_section, 0);  /* ??? subseg_set (bss_section, 1); ???  */
921*3d8817e4Smiod 
922*3d8817e4Smiod       if (align)
923*3d8817e4Smiod 	/* Do alignment.  */
924*3d8817e4Smiod 	frag_align (align, 0, 0);
925*3d8817e4Smiod 
926*3d8817e4Smiod       /* Detach from old frag.  */
927*3d8817e4Smiod       if (S_GET_SEGMENT (symbolP) == bss_section)
928*3d8817e4Smiod 	symbolP->sy_frag->fr_symbol = NULL;
929*3d8817e4Smiod 
930*3d8817e4Smiod       symbolP->sy_frag = frag_now;
931*3d8817e4Smiod       pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP,
932*3d8817e4Smiod 			(offsetT) size, (char *) 0);
933*3d8817e4Smiod       *pfrag = 0;
934*3d8817e4Smiod 
935*3d8817e4Smiod       S_SET_SIZE       (symbolP, size);
936*3d8817e4Smiod       S_SET_SEGMENT    (symbolP, bss_section);
937*3d8817e4Smiod       S_CLEAR_EXTERNAL (symbolP);
938*3d8817e4Smiod       symbolP->local = 1;
939*3d8817e4Smiod       subseg_set (old_sec, old_subsec);
940*3d8817e4Smiod     }
941*3d8817e4Smiod   else
942*3d8817e4Smiod     {
943*3d8817e4Smiod       S_SET_VALUE    (symbolP, (valueT) size);
944*3d8817e4Smiod       S_SET_ALIGN    (symbolP, align);
945*3d8817e4Smiod       S_SET_EXTERNAL (symbolP);
946*3d8817e4Smiod       S_SET_SEGMENT  (symbolP, bfd_com_section_ptr);
947*3d8817e4Smiod     }
948*3d8817e4Smiod 
949*3d8817e4Smiod   symbolP->bsym->flags |= BSF_OBJECT;
950*3d8817e4Smiod 
951*3d8817e4Smiod   demand_empty_rest_of_line ();
952*3d8817e4Smiod }
953*3d8817e4Smiod 
954*3d8817e4Smiod /* Select the cpu we're assembling for.  */
955*3d8817e4Smiod 
956*3d8817e4Smiod static void
arc_option(int ignore ATTRIBUTE_UNUSED)957*3d8817e4Smiod arc_option (int ignore ATTRIBUTE_UNUSED)
958*3d8817e4Smiod {
959*3d8817e4Smiod   extern int arc_get_mach (char *);
960*3d8817e4Smiod   int mach;
961*3d8817e4Smiod   char c;
962*3d8817e4Smiod   char *cpu;
963*3d8817e4Smiod 
964*3d8817e4Smiod   cpu = input_line_pointer;
965*3d8817e4Smiod   c = get_symbol_end ();
966*3d8817e4Smiod   mach = arc_get_mach (cpu);
967*3d8817e4Smiod   *input_line_pointer = c;
968*3d8817e4Smiod 
969*3d8817e4Smiod   /* If an instruction has already been seen, it's too late.  */
970*3d8817e4Smiod   if (cpu_tables_init_p)
971*3d8817e4Smiod     {
972*3d8817e4Smiod       as_bad ("\".option\" directive must appear before any instructions");
973*3d8817e4Smiod       ignore_rest_of_line ();
974*3d8817e4Smiod       return;
975*3d8817e4Smiod     }
976*3d8817e4Smiod 
977*3d8817e4Smiod   if (mach == -1)
978*3d8817e4Smiod     goto bad_cpu;
979*3d8817e4Smiod 
980*3d8817e4Smiod   if (mach_type_specified_p && mach != arc_mach_type)
981*3d8817e4Smiod     {
982*3d8817e4Smiod       as_bad ("\".option\" directive conflicts with initial definition");
983*3d8817e4Smiod       ignore_rest_of_line ();
984*3d8817e4Smiod       return;
985*3d8817e4Smiod     }
986*3d8817e4Smiod   else
987*3d8817e4Smiod     {
988*3d8817e4Smiod       /* The cpu may have been selected on the command line.  */
989*3d8817e4Smiod       if (mach != arc_mach_type)
990*3d8817e4Smiod 	as_warn ("\".option\" directive overrides command-line (default) value");
991*3d8817e4Smiod       arc_mach_type = mach;
992*3d8817e4Smiod       if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach))
993*3d8817e4Smiod 	as_fatal ("could not set architecture and machine");
994*3d8817e4Smiod       mach_type_specified_p = 1;
995*3d8817e4Smiod     }
996*3d8817e4Smiod   demand_empty_rest_of_line ();
997*3d8817e4Smiod   return;
998*3d8817e4Smiod 
999*3d8817e4Smiod  bad_cpu:
1000*3d8817e4Smiod   as_bad ("invalid identifier for \".option\"");
1001*3d8817e4Smiod   ignore_rest_of_line ();
1002*3d8817e4Smiod }
1003*3d8817e4Smiod 
1004*3d8817e4Smiod /* Turn a string in input_line_pointer into a floating point constant
1005*3d8817e4Smiod    of type TYPE, and store the appropriate bytes in *LITP.  The number
1006*3d8817e4Smiod    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
1007*3d8817e4Smiod    returned, or NULL on OK.  */
1008*3d8817e4Smiod 
1009*3d8817e4Smiod /* Equal to MAX_PRECISION in atof-ieee.c  */
1010*3d8817e4Smiod #define MAX_LITTLENUMS 6
1011*3d8817e4Smiod 
1012*3d8817e4Smiod char *
md_atof(int type,char * litP,int * sizeP)1013*3d8817e4Smiod md_atof (int type, char *litP, int *sizeP)
1014*3d8817e4Smiod {
1015*3d8817e4Smiod   int prec;
1016*3d8817e4Smiod   LITTLENUM_TYPE words[MAX_LITTLENUMS];
1017*3d8817e4Smiod   LITTLENUM_TYPE *wordP;
1018*3d8817e4Smiod   char *t;
1019*3d8817e4Smiod 
1020*3d8817e4Smiod   switch (type)
1021*3d8817e4Smiod     {
1022*3d8817e4Smiod     case 'f':
1023*3d8817e4Smiod     case 'F':
1024*3d8817e4Smiod       prec = 2;
1025*3d8817e4Smiod       break;
1026*3d8817e4Smiod 
1027*3d8817e4Smiod     case 'd':
1028*3d8817e4Smiod     case 'D':
1029*3d8817e4Smiod       prec = 4;
1030*3d8817e4Smiod       break;
1031*3d8817e4Smiod 
1032*3d8817e4Smiod     default:
1033*3d8817e4Smiod       *sizeP = 0;
1034*3d8817e4Smiod       return "bad call to md_atof";
1035*3d8817e4Smiod     }
1036*3d8817e4Smiod 
1037*3d8817e4Smiod   t = atof_ieee (input_line_pointer, type, words);
1038*3d8817e4Smiod   if (t)
1039*3d8817e4Smiod     input_line_pointer = t;
1040*3d8817e4Smiod   *sizeP = prec * sizeof (LITTLENUM_TYPE);
1041*3d8817e4Smiod   for (wordP = words; prec--;)
1042*3d8817e4Smiod     {
1043*3d8817e4Smiod       md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
1044*3d8817e4Smiod       litP += sizeof (LITTLENUM_TYPE);
1045*3d8817e4Smiod     }
1046*3d8817e4Smiod 
1047*3d8817e4Smiod   return NULL;
1048*3d8817e4Smiod }
1049*3d8817e4Smiod 
1050*3d8817e4Smiod /* Write a value out to the object file, using the appropriate
1051*3d8817e4Smiod    endianness.  */
1052*3d8817e4Smiod 
1053*3d8817e4Smiod void
md_number_to_chars(char * buf,valueT val,int n)1054*3d8817e4Smiod md_number_to_chars (char *buf, valueT val, int n)
1055*3d8817e4Smiod {
1056*3d8817e4Smiod   if (target_big_endian)
1057*3d8817e4Smiod     number_to_chars_bigendian (buf, val, n);
1058*3d8817e4Smiod   else
1059*3d8817e4Smiod     number_to_chars_littleendian (buf, val, n);
1060*3d8817e4Smiod }
1061*3d8817e4Smiod 
1062*3d8817e4Smiod /* Round up a section size to the appropriate boundary.  */
1063*3d8817e4Smiod 
1064*3d8817e4Smiod valueT
md_section_align(segT segment,valueT size)1065*3d8817e4Smiod md_section_align (segT segment, valueT size)
1066*3d8817e4Smiod {
1067*3d8817e4Smiod   int align = bfd_get_section_alignment (stdoutput, segment);
1068*3d8817e4Smiod 
1069*3d8817e4Smiod   return ((size + (1 << align) - 1) & (-1 << align));
1070*3d8817e4Smiod }
1071*3d8817e4Smiod 
1072*3d8817e4Smiod /* We don't have any form of relaxing.  */
1073*3d8817e4Smiod 
1074*3d8817e4Smiod int
md_estimate_size_before_relax(fragS * fragp ATTRIBUTE_UNUSED,asection * seg ATTRIBUTE_UNUSED)1075*3d8817e4Smiod md_estimate_size_before_relax (fragS *fragp ATTRIBUTE_UNUSED,
1076*3d8817e4Smiod 			       asection *seg ATTRIBUTE_UNUSED)
1077*3d8817e4Smiod {
1078*3d8817e4Smiod   as_fatal (_("md_estimate_size_before_relax\n"));
1079*3d8817e4Smiod   return 1;
1080*3d8817e4Smiod }
1081*3d8817e4Smiod 
1082*3d8817e4Smiod /* Convert a machine dependent frag.  We never generate these.  */
1083*3d8817e4Smiod 
1084*3d8817e4Smiod void
md_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,asection * sec ATTRIBUTE_UNUSED,fragS * fragp ATTRIBUTE_UNUSED)1085*3d8817e4Smiod md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
1086*3d8817e4Smiod 		 asection *sec ATTRIBUTE_UNUSED,
1087*3d8817e4Smiod 		 fragS *fragp ATTRIBUTE_UNUSED)
1088*3d8817e4Smiod {
1089*3d8817e4Smiod   as_fatal (_("md_convert_frag\n"));
1090*3d8817e4Smiod }
1091*3d8817e4Smiod 
1092*3d8817e4Smiod static void
arc_code_symbol(expressionS * expressionP)1093*3d8817e4Smiod arc_code_symbol (expressionS *expressionP)
1094*3d8817e4Smiod {
1095*3d8817e4Smiod   if (expressionP->X_op == O_symbol && expressionP->X_add_number == 0)
1096*3d8817e4Smiod     {
1097*3d8817e4Smiod       expressionS two;
1098*3d8817e4Smiod 
1099*3d8817e4Smiod       expressionP->X_op = O_right_shift;
1100*3d8817e4Smiod       expressionP->X_add_symbol->sy_value.X_op = O_constant;
1101*3d8817e4Smiod       two.X_op = O_constant;
1102*3d8817e4Smiod       two.X_add_symbol = two.X_op_symbol = NULL;
1103*3d8817e4Smiod       two.X_add_number = 2;
1104*3d8817e4Smiod       expressionP->X_op_symbol = make_expr_symbol (&two);
1105*3d8817e4Smiod     }
1106*3d8817e4Smiod   /* Allow %st(sym1-sym2)  */
1107*3d8817e4Smiod   else if (expressionP->X_op == O_subtract
1108*3d8817e4Smiod 	   && expressionP->X_add_symbol != NULL
1109*3d8817e4Smiod 	   && expressionP->X_op_symbol != NULL
1110*3d8817e4Smiod 	   && expressionP->X_add_number == 0)
1111*3d8817e4Smiod     {
1112*3d8817e4Smiod       expressionS two;
1113*3d8817e4Smiod 
1114*3d8817e4Smiod       expressionP->X_add_symbol = make_expr_symbol (expressionP);
1115*3d8817e4Smiod       expressionP->X_op = O_right_shift;
1116*3d8817e4Smiod       two.X_op = O_constant;
1117*3d8817e4Smiod       two.X_add_symbol = two.X_op_symbol = NULL;
1118*3d8817e4Smiod       two.X_add_number = 2;
1119*3d8817e4Smiod       expressionP->X_op_symbol = make_expr_symbol (&two);
1120*3d8817e4Smiod     }
1121*3d8817e4Smiod   else
1122*3d8817e4Smiod     as_bad ("expression too complex code symbol");
1123*3d8817e4Smiod }
1124*3d8817e4Smiod 
1125*3d8817e4Smiod /* Parse an operand that is machine-specific.
1126*3d8817e4Smiod 
1127*3d8817e4Smiod    The ARC has a special %-op to adjust addresses so they're usable in
1128*3d8817e4Smiod    branches.  The "st" is short for the STatus register.
1129*3d8817e4Smiod    ??? Later expand this to take a flags value too.
1130*3d8817e4Smiod 
1131*3d8817e4Smiod    ??? We can't create new expression types so we map the %-op's onto the
1132*3d8817e4Smiod    existing syntax.  This means that the user could use the chosen syntax
1133*3d8817e4Smiod    to achieve the same effect.  */
1134*3d8817e4Smiod 
1135*3d8817e4Smiod void
md_operand(expressionS * expressionP)1136*3d8817e4Smiod md_operand (expressionS *expressionP)
1137*3d8817e4Smiod {
1138*3d8817e4Smiod   char *p = input_line_pointer;
1139*3d8817e4Smiod 
1140*3d8817e4Smiod   if (*p != '%')
1141*3d8817e4Smiod     return;
1142*3d8817e4Smiod 
1143*3d8817e4Smiod   if (strncmp (p, "%st(", 4) == 0)
1144*3d8817e4Smiod     {
1145*3d8817e4Smiod       input_line_pointer += 4;
1146*3d8817e4Smiod       expression (expressionP);
1147*3d8817e4Smiod       if (*input_line_pointer != ')')
1148*3d8817e4Smiod 	{
1149*3d8817e4Smiod 	  as_bad ("missing ')' in %%-op");
1150*3d8817e4Smiod 	  return;
1151*3d8817e4Smiod 	}
1152*3d8817e4Smiod       ++input_line_pointer;
1153*3d8817e4Smiod       arc_code_symbol (expressionP);
1154*3d8817e4Smiod     }
1155*3d8817e4Smiod   else
1156*3d8817e4Smiod     {
1157*3d8817e4Smiod       /* It could be a register.  */
1158*3d8817e4Smiod       int i, l;
1159*3d8817e4Smiod       struct arc_ext_operand_value *ext_oper = arc_ext_operands;
1160*3d8817e4Smiod       p++;
1161*3d8817e4Smiod 
1162*3d8817e4Smiod       while (ext_oper)
1163*3d8817e4Smiod 	{
1164*3d8817e4Smiod 	  l = strlen (ext_oper->operand.name);
1165*3d8817e4Smiod 	  if (!strncmp (p, ext_oper->operand.name, l) && !ISALNUM (*(p + l)))
1166*3d8817e4Smiod 	    {
1167*3d8817e4Smiod 	      input_line_pointer += l + 1;
1168*3d8817e4Smiod 	      expressionP->X_op = O_register;
1169*3d8817e4Smiod 	      expressionP->X_add_number = (offsetT) &ext_oper->operand;
1170*3d8817e4Smiod 	      return;
1171*3d8817e4Smiod 	    }
1172*3d8817e4Smiod 	  ext_oper = ext_oper->next;
1173*3d8817e4Smiod 	}
1174*3d8817e4Smiod       for (i = 0; i < arc_reg_names_count; i++)
1175*3d8817e4Smiod 	{
1176*3d8817e4Smiod 	  l = strlen (arc_reg_names[i].name);
1177*3d8817e4Smiod 	  if (!strncmp (p, arc_reg_names[i].name, l) && !ISALNUM (*(p + l)))
1178*3d8817e4Smiod 	    {
1179*3d8817e4Smiod 	      input_line_pointer += l + 1;
1180*3d8817e4Smiod 	      expressionP->X_op = O_register;
1181*3d8817e4Smiod 	      expressionP->X_add_number = (offsetT) &arc_reg_names[i];
1182*3d8817e4Smiod 	      break;
1183*3d8817e4Smiod 	    }
1184*3d8817e4Smiod 	}
1185*3d8817e4Smiod     }
1186*3d8817e4Smiod }
1187*3d8817e4Smiod 
1188*3d8817e4Smiod /* We have no need to default values of symbols.
1189*3d8817e4Smiod    We could catch register names here, but that is handled by inserting
1190*3d8817e4Smiod    them all in the symbol table to begin with.  */
1191*3d8817e4Smiod 
1192*3d8817e4Smiod symbolS *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)1193*3d8817e4Smiod md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1194*3d8817e4Smiod {
1195*3d8817e4Smiod   return 0;
1196*3d8817e4Smiod }
1197*3d8817e4Smiod 
1198*3d8817e4Smiod /* Functions concerning expressions.  */
1199*3d8817e4Smiod 
1200*3d8817e4Smiod /* Parse a .byte, .word, etc. expression.
1201*3d8817e4Smiod 
1202*3d8817e4Smiod    Values for the status register are specified with %st(label).
1203*3d8817e4Smiod    `label' will be right shifted by 2.  */
1204*3d8817e4Smiod 
1205*3d8817e4Smiod void
arc_parse_cons_expression(expressionS * exp,unsigned int nbytes ATTRIBUTE_UNUSED)1206*3d8817e4Smiod arc_parse_cons_expression (expressionS *exp,
1207*3d8817e4Smiod 			   unsigned int nbytes ATTRIBUTE_UNUSED)
1208*3d8817e4Smiod {
1209*3d8817e4Smiod   char *p = input_line_pointer;
1210*3d8817e4Smiod   int code_symbol_fix = 0;
1211*3d8817e4Smiod 
1212*3d8817e4Smiod   for (; ! is_end_of_line[(unsigned char) *p]; p++)
1213*3d8817e4Smiod     if (*p == '@' && !strncmp (p, "@h30", 4))
1214*3d8817e4Smiod       {
1215*3d8817e4Smiod 	code_symbol_fix = 1;
1216*3d8817e4Smiod 	strcpy (p, ";   ");
1217*3d8817e4Smiod       }
1218*3d8817e4Smiod   expression_and_evaluate (exp);
1219*3d8817e4Smiod   if (code_symbol_fix)
1220*3d8817e4Smiod     {
1221*3d8817e4Smiod       arc_code_symbol (exp);
1222*3d8817e4Smiod       input_line_pointer = p;
1223*3d8817e4Smiod     }
1224*3d8817e4Smiod }
1225*3d8817e4Smiod 
1226*3d8817e4Smiod /* Record a fixup for a cons expression.  */
1227*3d8817e4Smiod 
1228*3d8817e4Smiod void
arc_cons_fix_new(fragS * frag,int where,int nbytes,expressionS * exp)1229*3d8817e4Smiod arc_cons_fix_new (fragS *frag,
1230*3d8817e4Smiod 		  int where,
1231*3d8817e4Smiod 		  int nbytes,
1232*3d8817e4Smiod 		  expressionS *exp)
1233*3d8817e4Smiod {
1234*3d8817e4Smiod   if (nbytes == 4)
1235*3d8817e4Smiod     {
1236*3d8817e4Smiod       int reloc_type;
1237*3d8817e4Smiod       expressionS exptmp;
1238*3d8817e4Smiod 
1239*3d8817e4Smiod       /* This may be a special ARC reloc (eg: %st()).  */
1240*3d8817e4Smiod       reloc_type = get_arc_exp_reloc_type (1, BFD_RELOC_32, exp, &exptmp);
1241*3d8817e4Smiod       fix_new_exp (frag, where, nbytes, &exptmp, 0, reloc_type);
1242*3d8817e4Smiod     }
1243*3d8817e4Smiod   else
1244*3d8817e4Smiod     {
1245*3d8817e4Smiod       fix_new_exp (frag, where, nbytes, exp, 0,
1246*3d8817e4Smiod 		   nbytes == 2 ? BFD_RELOC_16
1247*3d8817e4Smiod 		   : nbytes == 8 ? BFD_RELOC_64
1248*3d8817e4Smiod 		   : BFD_RELOC_32);
1249*3d8817e4Smiod     }
1250*3d8817e4Smiod }
1251*3d8817e4Smiod 
1252*3d8817e4Smiod /* Functions concerning relocs.  */
1253*3d8817e4Smiod 
1254*3d8817e4Smiod /* The location from which a PC relative jump should be calculated,
1255*3d8817e4Smiod    given a PC relative reloc.  */
1256*3d8817e4Smiod 
1257*3d8817e4Smiod long
md_pcrel_from(fixS * fixP)1258*3d8817e4Smiod md_pcrel_from (fixS *fixP)
1259*3d8817e4Smiod {
1260*3d8817e4Smiod   /* Return the address of the delay slot.  */
1261*3d8817e4Smiod   return fixP->fx_frag->fr_address + fixP->fx_where + fixP->fx_size;
1262*3d8817e4Smiod }
1263*3d8817e4Smiod 
1264*3d8817e4Smiod /* Apply a fixup to the object code.  This is called for all the
1265*3d8817e4Smiod    fixups we generated by the call to fix_new_exp, above.  In the call
1266*3d8817e4Smiod    above we used a reloc code which was the largest legal reloc code
1267*3d8817e4Smiod    plus the operand index.  Here we undo that to recover the operand
1268*3d8817e4Smiod    index.  At this point all symbol values should be fully resolved,
1269*3d8817e4Smiod    and we attempt to completely resolve the reloc.  If we can not do
1270*3d8817e4Smiod    that, we determine the correct reloc code and put it back in the fixup.  */
1271*3d8817e4Smiod 
1272*3d8817e4Smiod void
md_apply_fix(fixS * fixP,valueT * valP,segT seg)1273*3d8817e4Smiod md_apply_fix (fixS *fixP, valueT * valP, segT seg)
1274*3d8817e4Smiod {
1275*3d8817e4Smiod   valueT value = * valP;
1276*3d8817e4Smiod 
1277*3d8817e4Smiod   if (fixP->fx_addsy == (symbolS *) NULL)
1278*3d8817e4Smiod     fixP->fx_done = 1;
1279*3d8817e4Smiod 
1280*3d8817e4Smiod   else if (fixP->fx_pcrel)
1281*3d8817e4Smiod     {
1282*3d8817e4Smiod       /* Hack around bfd_install_relocation brain damage.  */
1283*3d8817e4Smiod       if (S_GET_SEGMENT (fixP->fx_addsy) != seg)
1284*3d8817e4Smiod 	value += md_pcrel_from (fixP);
1285*3d8817e4Smiod     }
1286*3d8817e4Smiod 
1287*3d8817e4Smiod   /* We can't actually support subtracting a symbol.  */
1288*3d8817e4Smiod   if (fixP->fx_subsy != NULL)
1289*3d8817e4Smiod     as_bad_where (fixP->fx_file, fixP->fx_line, _("expression too complex"));
1290*3d8817e4Smiod 
1291*3d8817e4Smiod   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1292*3d8817e4Smiod     {
1293*3d8817e4Smiod       int opindex;
1294*3d8817e4Smiod       const struct arc_operand *operand;
1295*3d8817e4Smiod       char *where;
1296*3d8817e4Smiod       arc_insn insn;
1297*3d8817e4Smiod 
1298*3d8817e4Smiod       opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1299*3d8817e4Smiod 
1300*3d8817e4Smiod       operand = &arc_operands[opindex];
1301*3d8817e4Smiod 
1302*3d8817e4Smiod       /* Fetch the instruction, insert the fully resolved operand
1303*3d8817e4Smiod 	 value, and stuff the instruction back again.  */
1304*3d8817e4Smiod       where = fixP->fx_frag->fr_literal + fixP->fx_where;
1305*3d8817e4Smiod       if (target_big_endian)
1306*3d8817e4Smiod 	insn = bfd_getb32 ((unsigned char *) where);
1307*3d8817e4Smiod       else
1308*3d8817e4Smiod 	insn = bfd_getl32 ((unsigned char *) where);
1309*3d8817e4Smiod       insn = arc_insert_operand (insn, operand, -1, NULL, (offsetT) value,
1310*3d8817e4Smiod 				 fixP->fx_file, fixP->fx_line);
1311*3d8817e4Smiod       if (target_big_endian)
1312*3d8817e4Smiod 	bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
1313*3d8817e4Smiod       else
1314*3d8817e4Smiod 	bfd_putl32 ((bfd_vma) insn, (unsigned char *) where);
1315*3d8817e4Smiod 
1316*3d8817e4Smiod       if (fixP->fx_done)
1317*3d8817e4Smiod 	/* Nothing else to do here.  */
1318*3d8817e4Smiod 	return;
1319*3d8817e4Smiod 
1320*3d8817e4Smiod       /* Determine a BFD reloc value based on the operand information.
1321*3d8817e4Smiod 	 We are only prepared to turn a few of the operands into relocs.
1322*3d8817e4Smiod 	 !!! Note that we can't handle limm values here.  Since we're using
1323*3d8817e4Smiod 	 implicit addends the addend must be inserted into the instruction,
1324*3d8817e4Smiod 	 however, the opcode insertion routines currently do nothing with
1325*3d8817e4Smiod 	 limm values.  */
1326*3d8817e4Smiod       if (operand->fmt == 'B')
1327*3d8817e4Smiod 	{
1328*3d8817e4Smiod 	  assert ((operand->flags & ARC_OPERAND_RELATIVE_BRANCH) != 0
1329*3d8817e4Smiod 		  && operand->bits == 20
1330*3d8817e4Smiod 		  && operand->shift == 7);
1331*3d8817e4Smiod 	  fixP->fx_r_type = BFD_RELOC_ARC_B22_PCREL;
1332*3d8817e4Smiod 	}
1333*3d8817e4Smiod       else if (operand->fmt == 'J')
1334*3d8817e4Smiod 	{
1335*3d8817e4Smiod 	  assert ((operand->flags & ARC_OPERAND_ABSOLUTE_BRANCH) != 0
1336*3d8817e4Smiod 		  && operand->bits == 24
1337*3d8817e4Smiod 		  && operand->shift == 32);
1338*3d8817e4Smiod 	  fixP->fx_r_type = BFD_RELOC_ARC_B26;
1339*3d8817e4Smiod 	}
1340*3d8817e4Smiod       else if (operand->fmt == 'L')
1341*3d8817e4Smiod 	{
1342*3d8817e4Smiod 	  assert ((operand->flags & ARC_OPERAND_LIMM) != 0
1343*3d8817e4Smiod 		  && operand->bits == 32
1344*3d8817e4Smiod 		  && operand->shift == 32);
1345*3d8817e4Smiod 	  fixP->fx_r_type = BFD_RELOC_32;
1346*3d8817e4Smiod 	}
1347*3d8817e4Smiod       else
1348*3d8817e4Smiod 	{
1349*3d8817e4Smiod 	  as_bad_where (fixP->fx_file, fixP->fx_line,
1350*3d8817e4Smiod 			"unresolved expression that must be resolved");
1351*3d8817e4Smiod 	  fixP->fx_done = 1;
1352*3d8817e4Smiod 	  return;
1353*3d8817e4Smiod 	}
1354*3d8817e4Smiod     }
1355*3d8817e4Smiod   else
1356*3d8817e4Smiod     {
1357*3d8817e4Smiod       switch (fixP->fx_r_type)
1358*3d8817e4Smiod 	{
1359*3d8817e4Smiod 	case BFD_RELOC_8:
1360*3d8817e4Smiod 	  md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
1361*3d8817e4Smiod 			      value, 1);
1362*3d8817e4Smiod 	  break;
1363*3d8817e4Smiod 	case BFD_RELOC_16:
1364*3d8817e4Smiod 	  md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
1365*3d8817e4Smiod 			      value, 2);
1366*3d8817e4Smiod 	  break;
1367*3d8817e4Smiod 	case BFD_RELOC_32:
1368*3d8817e4Smiod 	  md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
1369*3d8817e4Smiod 			      value, 4);
1370*3d8817e4Smiod 	  break;
1371*3d8817e4Smiod 	case BFD_RELOC_ARC_B26:
1372*3d8817e4Smiod 	  /* If !fixP->fx_done then `value' is an implicit addend.
1373*3d8817e4Smiod 	     We must shift it right by 2 in this case as well because the
1374*3d8817e4Smiod 	     linker performs the relocation and then adds this in (as opposed
1375*3d8817e4Smiod 	     to adding this in and then shifting right by 2).  */
1376*3d8817e4Smiod 	  value >>= 2;
1377*3d8817e4Smiod 	  md_number_to_chars (fixP->fx_frag->fr_literal + fixP->fx_where,
1378*3d8817e4Smiod 			      value, 4);
1379*3d8817e4Smiod 	  break;
1380*3d8817e4Smiod 	default:
1381*3d8817e4Smiod 	  abort ();
1382*3d8817e4Smiod 	}
1383*3d8817e4Smiod     }
1384*3d8817e4Smiod }
1385*3d8817e4Smiod 
1386*3d8817e4Smiod /* Translate internal representation of relocation info to BFD target
1387*3d8817e4Smiod    format.  */
1388*3d8817e4Smiod 
1389*3d8817e4Smiod arelent *
tc_gen_reloc(asection * section ATTRIBUTE_UNUSED,fixS * fixP)1390*3d8817e4Smiod tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
1391*3d8817e4Smiod 	      fixS *fixP)
1392*3d8817e4Smiod {
1393*3d8817e4Smiod   arelent *reloc;
1394*3d8817e4Smiod 
1395*3d8817e4Smiod   reloc = xmalloc (sizeof (arelent));
1396*3d8817e4Smiod   reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
1397*3d8817e4Smiod 
1398*3d8817e4Smiod   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
1399*3d8817e4Smiod   reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
1400*3d8817e4Smiod   reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
1401*3d8817e4Smiod   if (reloc->howto == (reloc_howto_type *) NULL)
1402*3d8817e4Smiod     {
1403*3d8817e4Smiod       as_bad_where (fixP->fx_file, fixP->fx_line,
1404*3d8817e4Smiod 		    "internal error: can't export reloc type %d (`%s')",
1405*3d8817e4Smiod 		    fixP->fx_r_type,
1406*3d8817e4Smiod 		    bfd_get_reloc_code_name (fixP->fx_r_type));
1407*3d8817e4Smiod       return NULL;
1408*3d8817e4Smiod     }
1409*3d8817e4Smiod 
1410*3d8817e4Smiod   assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
1411*3d8817e4Smiod 
1412*3d8817e4Smiod   /* Set addend to account for PC being advanced one insn before the
1413*3d8817e4Smiod      target address is computed.  */
1414*3d8817e4Smiod 
1415*3d8817e4Smiod   reloc->addend = (fixP->fx_pcrel ? -4 : 0);
1416*3d8817e4Smiod 
1417*3d8817e4Smiod   return reloc;
1418*3d8817e4Smiod }
1419*3d8817e4Smiod 
1420*3d8817e4Smiod const pseudo_typeS md_pseudo_table[] =
1421*3d8817e4Smiod {
1422*3d8817e4Smiod   { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0).  */
1423*3d8817e4Smiod   { "comm", arc_common, 0 },
1424*3d8817e4Smiod   { "common", arc_common, 0 },
1425*3d8817e4Smiod   { "lcomm", arc_common, 1 },
1426*3d8817e4Smiod   { "lcommon", arc_common, 1 },
1427*3d8817e4Smiod   { "2byte", cons, 2 },
1428*3d8817e4Smiod   { "half", cons, 2 },
1429*3d8817e4Smiod   { "short", cons, 2 },
1430*3d8817e4Smiod   { "3byte", cons, 3 },
1431*3d8817e4Smiod   { "4byte", cons, 4 },
1432*3d8817e4Smiod   { "word", cons, 4 },
1433*3d8817e4Smiod   { "option", arc_option, 0 },
1434*3d8817e4Smiod   { "cpu", arc_option, 0 },
1435*3d8817e4Smiod   { "block", s_space, 0 },
1436*3d8817e4Smiod   { "extcondcode", arc_extoper, 0 },
1437*3d8817e4Smiod   { "extcoreregister", arc_extoper, 1 },
1438*3d8817e4Smiod   { "extauxregister", arc_extoper, 2 },
1439*3d8817e4Smiod   { "extinstruction", arc_extinst, 0 },
1440*3d8817e4Smiod   { NULL, 0, 0 },
1441*3d8817e4Smiod };
1442*3d8817e4Smiod 
1443*3d8817e4Smiod /* This routine is called for each instruction to be assembled.  */
1444*3d8817e4Smiod 
1445*3d8817e4Smiod void
md_assemble(char * str)1446*3d8817e4Smiod md_assemble (char *str)
1447*3d8817e4Smiod {
1448*3d8817e4Smiod   const struct arc_opcode *opcode;
1449*3d8817e4Smiod   const struct arc_opcode *std_opcode;
1450*3d8817e4Smiod   struct arc_opcode *ext_opcode;
1451*3d8817e4Smiod   char *start;
1452*3d8817e4Smiod   const char *last_errmsg = 0;
1453*3d8817e4Smiod   arc_insn insn;
1454*3d8817e4Smiod   static int init_tables_p = 0;
1455*3d8817e4Smiod 
1456*3d8817e4Smiod   /* Opcode table initialization is deferred until here because we have to
1457*3d8817e4Smiod      wait for a possible .option command.  */
1458*3d8817e4Smiod   if (!init_tables_p)
1459*3d8817e4Smiod     {
1460*3d8817e4Smiod       init_opcode_tables (arc_mach_type);
1461*3d8817e4Smiod       init_tables_p = 1;
1462*3d8817e4Smiod     }
1463*3d8817e4Smiod 
1464*3d8817e4Smiod   /* Skip leading white space.  */
1465*3d8817e4Smiod   while (ISSPACE (*str))
1466*3d8817e4Smiod     str++;
1467*3d8817e4Smiod 
1468*3d8817e4Smiod   /* The instructions are stored in lists hashed by the first letter (though
1469*3d8817e4Smiod      we needn't care how they're hashed).  Get the first in the list.  */
1470*3d8817e4Smiod 
1471*3d8817e4Smiod   ext_opcode = arc_ext_opcodes;
1472*3d8817e4Smiod   std_opcode = arc_opcode_lookup_asm (str);
1473*3d8817e4Smiod 
1474*3d8817e4Smiod   /* Keep looking until we find a match.  */
1475*3d8817e4Smiod   start = str;
1476*3d8817e4Smiod   for (opcode = (ext_opcode ? ext_opcode : std_opcode);
1477*3d8817e4Smiod        opcode != NULL;
1478*3d8817e4Smiod        opcode = (ARC_OPCODE_NEXT_ASM (opcode)
1479*3d8817e4Smiod 		 ? ARC_OPCODE_NEXT_ASM (opcode)
1480*3d8817e4Smiod 		 : (ext_opcode ? ext_opcode = NULL, std_opcode : NULL)))
1481*3d8817e4Smiod     {
1482*3d8817e4Smiod       int past_opcode_p, fc, num_suffixes;
1483*3d8817e4Smiod       int fix_up_at = 0;
1484*3d8817e4Smiod       char *syn;
1485*3d8817e4Smiod       struct arc_fixup fixups[MAX_FIXUPS];
1486*3d8817e4Smiod       /* Used as a sanity check.  If we need a limm reloc, make sure we ask
1487*3d8817e4Smiod 	 for an extra 4 bytes from frag_more.  */
1488*3d8817e4Smiod       int limm_reloc_p;
1489*3d8817e4Smiod       int ext_suffix_p;
1490*3d8817e4Smiod       const struct arc_operand_value *insn_suffixes[MAX_SUFFIXES];
1491*3d8817e4Smiod 
1492*3d8817e4Smiod       /* Is this opcode supported by the selected cpu?  */
1493*3d8817e4Smiod       if (! arc_opcode_supported (opcode))
1494*3d8817e4Smiod 	continue;
1495*3d8817e4Smiod 
1496*3d8817e4Smiod       /* Scan the syntax string.  If it doesn't match, try the next one.  */
1497*3d8817e4Smiod       arc_opcode_init_insert ();
1498*3d8817e4Smiod       insn = opcode->value;
1499*3d8817e4Smiod       fc = 0;
1500*3d8817e4Smiod       past_opcode_p = 0;
1501*3d8817e4Smiod       num_suffixes = 0;
1502*3d8817e4Smiod       limm_reloc_p = 0;
1503*3d8817e4Smiod       ext_suffix_p = 0;
1504*3d8817e4Smiod 
1505*3d8817e4Smiod       /* We don't check for (*str != '\0') here because we want to parse
1506*3d8817e4Smiod 	 any trailing fake arguments in the syntax string.  */
1507*3d8817e4Smiod       for (str = start, syn = opcode->syntax; *syn != '\0';)
1508*3d8817e4Smiod 	{
1509*3d8817e4Smiod 	  int mods;
1510*3d8817e4Smiod 	  const struct arc_operand *operand;
1511*3d8817e4Smiod 
1512*3d8817e4Smiod 	  /* Non operand chars must match exactly.  */
1513*3d8817e4Smiod 	  if (*syn != '%' || *++syn == '%')
1514*3d8817e4Smiod 	    {
1515*3d8817e4Smiod 	     if (*str == *syn)
1516*3d8817e4Smiod 		{
1517*3d8817e4Smiod 		  if (*syn == ' ')
1518*3d8817e4Smiod 		    past_opcode_p = 1;
1519*3d8817e4Smiod 		  ++syn;
1520*3d8817e4Smiod 		  ++str;
1521*3d8817e4Smiod 		}
1522*3d8817e4Smiod 	      else
1523*3d8817e4Smiod 		break;
1524*3d8817e4Smiod 	      continue;
1525*3d8817e4Smiod 	    }
1526*3d8817e4Smiod 
1527*3d8817e4Smiod 	  /* We have an operand.  Pick out any modifiers.  */
1528*3d8817e4Smiod 	  mods = 0;
1529*3d8817e4Smiod 	  while (ARC_MOD_P (arc_operands[arc_operand_map[(int) *syn]].flags))
1530*3d8817e4Smiod 	    {
1531*3d8817e4Smiod 	      mods |= arc_operands[arc_operand_map[(int) *syn]].flags & ARC_MOD_BITS;
1532*3d8817e4Smiod 	      ++syn;
1533*3d8817e4Smiod 	    }
1534*3d8817e4Smiod 	  operand = arc_operands + arc_operand_map[(int) *syn];
1535*3d8817e4Smiod 	  if (operand->fmt == 0)
1536*3d8817e4Smiod 	    as_fatal ("unknown syntax format character `%c'", *syn);
1537*3d8817e4Smiod 
1538*3d8817e4Smiod 	  if (operand->flags & ARC_OPERAND_FAKE)
1539*3d8817e4Smiod 	    {
1540*3d8817e4Smiod 	      const char *errmsg = NULL;
1541*3d8817e4Smiod 	      if (operand->insert)
1542*3d8817e4Smiod 		{
1543*3d8817e4Smiod 		  insn = (*operand->insert) (insn, operand, mods, NULL, 0, &errmsg);
1544*3d8817e4Smiod 		  if (errmsg != (const char *) NULL)
1545*3d8817e4Smiod 		    {
1546*3d8817e4Smiod 		      last_errmsg = errmsg;
1547*3d8817e4Smiod 		      if (operand->flags & ARC_OPERAND_ERROR)
1548*3d8817e4Smiod 			{
1549*3d8817e4Smiod 			  as_bad (errmsg);
1550*3d8817e4Smiod 			  return;
1551*3d8817e4Smiod 			}
1552*3d8817e4Smiod 		      else if (operand->flags & ARC_OPERAND_WARN)
1553*3d8817e4Smiod 			as_warn (errmsg);
1554*3d8817e4Smiod 		      break;
1555*3d8817e4Smiod 		    }
1556*3d8817e4Smiod 		  if (limm_reloc_p
1557*3d8817e4Smiod 		      && (operand->flags && operand->flags & ARC_OPERAND_LIMM)
1558*3d8817e4Smiod 		      && (operand->flags &
1559*3d8817e4Smiod 			  (ARC_OPERAND_ABSOLUTE_BRANCH | ARC_OPERAND_ADDRESS)))
1560*3d8817e4Smiod 		    {
1561*3d8817e4Smiod 		      fixups[fix_up_at].opindex = arc_operand_map[operand->fmt];
1562*3d8817e4Smiod 		    }
1563*3d8817e4Smiod 		}
1564*3d8817e4Smiod 	      ++syn;
1565*3d8817e4Smiod 	    }
1566*3d8817e4Smiod 	  /* Are we finished with suffixes?  */
1567*3d8817e4Smiod 	  else if (!past_opcode_p)
1568*3d8817e4Smiod 	    {
1569*3d8817e4Smiod 	      int found;
1570*3d8817e4Smiod 	      char c;
1571*3d8817e4Smiod 	      char *s, *t;
1572*3d8817e4Smiod 	      const struct arc_operand_value *suf, *suffix_end;
1573*3d8817e4Smiod 	      const struct arc_operand_value *suffix = NULL;
1574*3d8817e4Smiod 
1575*3d8817e4Smiod 	      if (!(operand->flags & ARC_OPERAND_SUFFIX))
1576*3d8817e4Smiod 		abort ();
1577*3d8817e4Smiod 
1578*3d8817e4Smiod 	      /* If we're at a space in the input string, we want to skip the
1579*3d8817e4Smiod 		 remaining suffixes.  There may be some fake ones though, so
1580*3d8817e4Smiod 		 just go on to try the next one.  */
1581*3d8817e4Smiod 	      if (*str == ' ')
1582*3d8817e4Smiod 		{
1583*3d8817e4Smiod 		  ++syn;
1584*3d8817e4Smiod 		  continue;
1585*3d8817e4Smiod 		}
1586*3d8817e4Smiod 
1587*3d8817e4Smiod 	      s = str;
1588*3d8817e4Smiod 	      if (mods & ARC_MOD_DOT)
1589*3d8817e4Smiod 		{
1590*3d8817e4Smiod 		  if (*s != '.')
1591*3d8817e4Smiod 		    break;
1592*3d8817e4Smiod 		  ++s;
1593*3d8817e4Smiod 		}
1594*3d8817e4Smiod 	      else
1595*3d8817e4Smiod 		{
1596*3d8817e4Smiod 		  /* This can happen in "b.nd foo" and we're currently looking
1597*3d8817e4Smiod 		     for "%q" (ie: a condition code suffix).  */
1598*3d8817e4Smiod 		  if (*s == '.')
1599*3d8817e4Smiod 		    {
1600*3d8817e4Smiod 		      ++syn;
1601*3d8817e4Smiod 		      continue;
1602*3d8817e4Smiod 		    }
1603*3d8817e4Smiod 		}
1604*3d8817e4Smiod 
1605*3d8817e4Smiod 	      /* Pick the suffix out and look it up via the hash table.  */
1606*3d8817e4Smiod 	      for (t = s; *t && ISALNUM (*t); ++t)
1607*3d8817e4Smiod 		continue;
1608*3d8817e4Smiod 	      c = *t;
1609*3d8817e4Smiod 	      *t = '\0';
1610*3d8817e4Smiod 	      if ((suf = get_ext_suffix (s)))
1611*3d8817e4Smiod 		ext_suffix_p = 1;
1612*3d8817e4Smiod 	      else
1613*3d8817e4Smiod 		suf = hash_find (arc_suffix_hash, s);
1614*3d8817e4Smiod 	      if (!suf)
1615*3d8817e4Smiod 		{
1616*3d8817e4Smiod 		  /* This can happen in "blle foo" and we're currently using
1617*3d8817e4Smiod 		     the template "b%q%.n %j".  The "bl" insn occurs later in
1618*3d8817e4Smiod 		     the table so "lle" isn't an illegal suffix.  */
1619*3d8817e4Smiod 		  *t = c;
1620*3d8817e4Smiod 		  break;
1621*3d8817e4Smiod 		}
1622*3d8817e4Smiod 
1623*3d8817e4Smiod 	      /* Is it the right type?  Note that the same character is used
1624*3d8817e4Smiod 		 several times, so we have to examine all of them.  This is
1625*3d8817e4Smiod 		 relatively efficient as equivalent entries are kept
1626*3d8817e4Smiod 		 together.  If it's not the right type, don't increment `str'
1627*3d8817e4Smiod 		 so we try the next one in the series.  */
1628*3d8817e4Smiod 	      found = 0;
1629*3d8817e4Smiod 	      if (ext_suffix_p && arc_operands[suf->type].fmt == *syn)
1630*3d8817e4Smiod 		{
1631*3d8817e4Smiod 		  /* Insert the suffix's value into the insn.  */
1632*3d8817e4Smiod 		  *t = c;
1633*3d8817e4Smiod 		  if (operand->insert)
1634*3d8817e4Smiod 		    insn = (*operand->insert) (insn, operand,
1635*3d8817e4Smiod 					       mods, NULL, suf->value,
1636*3d8817e4Smiod 					       NULL);
1637*3d8817e4Smiod 		  else
1638*3d8817e4Smiod 		    insn |= suf->value << operand->shift;
1639*3d8817e4Smiod 		  suffix = suf;
1640*3d8817e4Smiod 		  str = t;
1641*3d8817e4Smiod 		  found = 1;
1642*3d8817e4Smiod 		}
1643*3d8817e4Smiod 	      else
1644*3d8817e4Smiod 		{
1645*3d8817e4Smiod 		  *t = c;
1646*3d8817e4Smiod 		  suffix_end = arc_suffixes + arc_suffixes_count;
1647*3d8817e4Smiod 		  for (suffix = suf;
1648*3d8817e4Smiod 		       suffix < suffix_end && strcmp (suffix->name, suf->name) == 0;
1649*3d8817e4Smiod 		       ++suffix)
1650*3d8817e4Smiod 		    {
1651*3d8817e4Smiod 		      if (arc_operands[suffix->type].fmt == *syn)
1652*3d8817e4Smiod 			{
1653*3d8817e4Smiod 			  /* Insert the suffix's value into the insn.  */
1654*3d8817e4Smiod 			  if (operand->insert)
1655*3d8817e4Smiod 			    insn = (*operand->insert) (insn, operand,
1656*3d8817e4Smiod 						       mods, NULL, suffix->value,
1657*3d8817e4Smiod 						       NULL);
1658*3d8817e4Smiod 			  else
1659*3d8817e4Smiod 			    insn |= suffix->value << operand->shift;
1660*3d8817e4Smiod 
1661*3d8817e4Smiod 			  str = t;
1662*3d8817e4Smiod 			  found = 1;
1663*3d8817e4Smiod 			  break;
1664*3d8817e4Smiod 			}
1665*3d8817e4Smiod 		    }
1666*3d8817e4Smiod 		}
1667*3d8817e4Smiod 	      ++syn;
1668*3d8817e4Smiod 	      if (!found)
1669*3d8817e4Smiod 		/* Wrong type.  Just go on to try next insn entry.  */
1670*3d8817e4Smiod 		;
1671*3d8817e4Smiod 	      else
1672*3d8817e4Smiod 		{
1673*3d8817e4Smiod 		  if (num_suffixes == MAX_SUFFIXES)
1674*3d8817e4Smiod 		    as_bad ("too many suffixes");
1675*3d8817e4Smiod 		  else
1676*3d8817e4Smiod 		    insn_suffixes[num_suffixes++] = suffix;
1677*3d8817e4Smiod 		}
1678*3d8817e4Smiod 	    }
1679*3d8817e4Smiod 	  else
1680*3d8817e4Smiod 	    /* This is either a register or an expression of some kind.  */
1681*3d8817e4Smiod 	    {
1682*3d8817e4Smiod 	      char *hold;
1683*3d8817e4Smiod 	      const struct arc_operand_value *reg = NULL;
1684*3d8817e4Smiod 	      long value = 0;
1685*3d8817e4Smiod 	      expressionS exp;
1686*3d8817e4Smiod 
1687*3d8817e4Smiod 	      if (operand->flags & ARC_OPERAND_SUFFIX)
1688*3d8817e4Smiod 		abort ();
1689*3d8817e4Smiod 
1690*3d8817e4Smiod 	      /* Is there anything left to parse?
1691*3d8817e4Smiod 		 We don't check for this at the top because we want to parse
1692*3d8817e4Smiod 		 any trailing fake arguments in the syntax string.  */
1693*3d8817e4Smiod 	      if (is_end_of_line[(unsigned char) *str])
1694*3d8817e4Smiod 		break;
1695*3d8817e4Smiod 
1696*3d8817e4Smiod 	      /* Parse the operand.  */
1697*3d8817e4Smiod 	      hold = input_line_pointer;
1698*3d8817e4Smiod 	      input_line_pointer = str;
1699*3d8817e4Smiod 	      expression (&exp);
1700*3d8817e4Smiod 	      str = input_line_pointer;
1701*3d8817e4Smiod 	      input_line_pointer = hold;
1702*3d8817e4Smiod 
1703*3d8817e4Smiod 	      if (exp.X_op == O_illegal)
1704*3d8817e4Smiod 		as_bad ("illegal operand");
1705*3d8817e4Smiod 	      else if (exp.X_op == O_absent)
1706*3d8817e4Smiod 		as_bad ("missing operand");
1707*3d8817e4Smiod 	      else if (exp.X_op == O_constant)
1708*3d8817e4Smiod 		value = exp.X_add_number;
1709*3d8817e4Smiod 	      else if (exp.X_op == O_register)
1710*3d8817e4Smiod 		reg = (struct arc_operand_value *) exp.X_add_number;
1711*3d8817e4Smiod #define IS_REG_DEST_OPERAND(o) ((o) == 'a')
1712*3d8817e4Smiod 	      else if (IS_REG_DEST_OPERAND (*syn))
1713*3d8817e4Smiod 		as_bad ("symbol as destination register");
1714*3d8817e4Smiod 	      else
1715*3d8817e4Smiod 		{
1716*3d8817e4Smiod 		  if (!strncmp (str, "@h30", 4))
1717*3d8817e4Smiod 		    {
1718*3d8817e4Smiod 		      arc_code_symbol (&exp);
1719*3d8817e4Smiod 		      str += 4;
1720*3d8817e4Smiod 		    }
1721*3d8817e4Smiod 		  /* We need to generate a fixup for this expression.  */
1722*3d8817e4Smiod 		  if (fc >= MAX_FIXUPS)
1723*3d8817e4Smiod 		    as_fatal ("too many fixups");
1724*3d8817e4Smiod 		  fixups[fc].exp = exp;
1725*3d8817e4Smiod 		  /* We don't support shimm relocs. break here to force
1726*3d8817e4Smiod 		     the assembler to output a limm.  */
1727*3d8817e4Smiod #define IS_REG_SHIMM_OFFSET(o) ((o) == 'd')
1728*3d8817e4Smiod 		  if (IS_REG_SHIMM_OFFSET (*syn))
1729*3d8817e4Smiod 		    break;
1730*3d8817e4Smiod 		  /* If this is a register constant (IE: one whose
1731*3d8817e4Smiod 		     register value gets stored as 61-63) then this
1732*3d8817e4Smiod 		     must be a limm.  */
1733*3d8817e4Smiod 		  /* ??? This bit could use some cleaning up.
1734*3d8817e4Smiod 		     Referencing the format chars like this goes
1735*3d8817e4Smiod 		     against style.  */
1736*3d8817e4Smiod 		  if (IS_SYMBOL_OPERAND (*syn))
1737*3d8817e4Smiod 		    {
1738*3d8817e4Smiod 		      const char *junk;
1739*3d8817e4Smiod 		      limm_reloc_p = 1;
1740*3d8817e4Smiod 		      /* Save this, we don't yet know what reloc to use.  */
1741*3d8817e4Smiod 		      fix_up_at = fc;
1742*3d8817e4Smiod 		      /* Tell insert_reg we need a limm.  This is
1743*3d8817e4Smiod 			 needed because the value at this point is
1744*3d8817e4Smiod 			 zero, a shimm.  */
1745*3d8817e4Smiod 		      /* ??? We need a cleaner interface than this.  */
1746*3d8817e4Smiod 		      (*arc_operands[arc_operand_map['Q']].insert)
1747*3d8817e4Smiod 			(insn, operand, mods, reg, 0L, &junk);
1748*3d8817e4Smiod 		    }
1749*3d8817e4Smiod 		  else
1750*3d8817e4Smiod 		    fixups[fc].opindex = arc_operand_map[(int) *syn];
1751*3d8817e4Smiod 		  ++fc;
1752*3d8817e4Smiod 		  value = 0;
1753*3d8817e4Smiod 		}
1754*3d8817e4Smiod 
1755*3d8817e4Smiod 	      /* Insert the register or expression into the instruction.  */
1756*3d8817e4Smiod 	      if (operand->insert)
1757*3d8817e4Smiod 		{
1758*3d8817e4Smiod 		  const char *errmsg = NULL;
1759*3d8817e4Smiod 		  insn = (*operand->insert) (insn, operand, mods,
1760*3d8817e4Smiod 					     reg, (long) value, &errmsg);
1761*3d8817e4Smiod 		  if (errmsg != (const char *) NULL)
1762*3d8817e4Smiod 		    {
1763*3d8817e4Smiod 		      last_errmsg = errmsg;
1764*3d8817e4Smiod 		      if (operand->flags & ARC_OPERAND_ERROR)
1765*3d8817e4Smiod 			{
1766*3d8817e4Smiod 			  as_bad (errmsg);
1767*3d8817e4Smiod 			  return;
1768*3d8817e4Smiod 			}
1769*3d8817e4Smiod 		      else if (operand->flags & ARC_OPERAND_WARN)
1770*3d8817e4Smiod 			as_warn (errmsg);
1771*3d8817e4Smiod 		      break;
1772*3d8817e4Smiod 		    }
1773*3d8817e4Smiod 		}
1774*3d8817e4Smiod 	      else
1775*3d8817e4Smiod 		insn |= (value & ((1 << operand->bits) - 1)) << operand->shift;
1776*3d8817e4Smiod 
1777*3d8817e4Smiod 	      ++syn;
1778*3d8817e4Smiod 	    }
1779*3d8817e4Smiod 	}
1780*3d8817e4Smiod 
1781*3d8817e4Smiod       /* If we're at the end of the syntax string, we're done.  */
1782*3d8817e4Smiod       /* FIXME: try to move this to a separate function.  */
1783*3d8817e4Smiod       if (*syn == '\0')
1784*3d8817e4Smiod 	{
1785*3d8817e4Smiod 	  int i;
1786*3d8817e4Smiod 	  char *f;
1787*3d8817e4Smiod 	  long limm, limm_p;
1788*3d8817e4Smiod 
1789*3d8817e4Smiod 	  /* For the moment we assume a valid `str' can only contain blanks
1790*3d8817e4Smiod 	     now.  IE: We needn't try again with a longer version of the
1791*3d8817e4Smiod 	     insn and it is assumed that longer versions of insns appear
1792*3d8817e4Smiod 	     before shorter ones (eg: lsr r2,r3,1 vs lsr r2,r3).  */
1793*3d8817e4Smiod 
1794*3d8817e4Smiod 	  while (ISSPACE (*str))
1795*3d8817e4Smiod 	    ++str;
1796*3d8817e4Smiod 
1797*3d8817e4Smiod 	  if (!is_end_of_line[(unsigned char) *str])
1798*3d8817e4Smiod 	    as_bad ("junk at end of line: `%s'", str);
1799*3d8817e4Smiod 
1800*3d8817e4Smiod 	  /* Is there a limm value?  */
1801*3d8817e4Smiod 	  limm_p = arc_opcode_limm_p (&limm);
1802*3d8817e4Smiod 
1803*3d8817e4Smiod 	  /* Perform various error and warning tests.  */
1804*3d8817e4Smiod 
1805*3d8817e4Smiod 	  {
1806*3d8817e4Smiod 	    static int in_delay_slot_p = 0;
1807*3d8817e4Smiod 	    static int prev_insn_needs_cc_nop_p = 0;
1808*3d8817e4Smiod 	    /* delay slot type seen */
1809*3d8817e4Smiod 	    int delay_slot_type = ARC_DELAY_NONE;
1810*3d8817e4Smiod 	    /* conditional execution flag seen */
1811*3d8817e4Smiod 	    int conditional = 0;
1812*3d8817e4Smiod 	    /* 1 if condition codes are being set */
1813*3d8817e4Smiod 	    int cc_set_p = 0;
1814*3d8817e4Smiod 	    /* 1 if conditional branch, including `b' "branch always" */
1815*3d8817e4Smiod 	    int cond_branch_p = opcode->flags & ARC_OPCODE_COND_BRANCH;
1816*3d8817e4Smiod 
1817*3d8817e4Smiod 	    for (i = 0; i < num_suffixes; ++i)
1818*3d8817e4Smiod 	      {
1819*3d8817e4Smiod 		switch (arc_operands[insn_suffixes[i]->type].fmt)
1820*3d8817e4Smiod 		  {
1821*3d8817e4Smiod 		  case 'n':
1822*3d8817e4Smiod 		    delay_slot_type = insn_suffixes[i]->value;
1823*3d8817e4Smiod 		    break;
1824*3d8817e4Smiod 		  case 'q':
1825*3d8817e4Smiod 		    conditional = insn_suffixes[i]->value;
1826*3d8817e4Smiod 		    break;
1827*3d8817e4Smiod 		  case 'f':
1828*3d8817e4Smiod 		    cc_set_p = 1;
1829*3d8817e4Smiod 		    break;
1830*3d8817e4Smiod 		  }
1831*3d8817e4Smiod 	      }
1832*3d8817e4Smiod 
1833*3d8817e4Smiod 	    /* Putting an insn with a limm value in a delay slot is supposed to
1834*3d8817e4Smiod 	       be legal, but let's warn the user anyway.  Ditto for 8 byte
1835*3d8817e4Smiod 	       jumps with delay slots.  */
1836*3d8817e4Smiod 	    if (in_delay_slot_p && limm_p)
1837*3d8817e4Smiod 	      as_warn ("8 byte instruction in delay slot");
1838*3d8817e4Smiod 	    if (delay_slot_type != ARC_DELAY_NONE
1839*3d8817e4Smiod 		&& limm_p && arc_insn_not_jl (insn)) /* except for jl  addr */
1840*3d8817e4Smiod 	      as_warn ("8 byte jump instruction with delay slot");
1841*3d8817e4Smiod 	    in_delay_slot_p = (delay_slot_type != ARC_DELAY_NONE) && !limm_p;
1842*3d8817e4Smiod 
1843*3d8817e4Smiod 	    /* Warn when a conditional branch immediately follows a set of
1844*3d8817e4Smiod 	       the condition codes.  Note that this needn't be done if the
1845*3d8817e4Smiod 	       insn that sets the condition codes uses a limm.  */
1846*3d8817e4Smiod 	    if (cond_branch_p && conditional != 0 /* 0 = "always" */
1847*3d8817e4Smiod 		&& prev_insn_needs_cc_nop_p && arc_mach_type == bfd_mach_arc_5)
1848*3d8817e4Smiod 	      as_warn ("conditional branch follows set of flags");
1849*3d8817e4Smiod 	    prev_insn_needs_cc_nop_p =
1850*3d8817e4Smiod 	      /* FIXME: ??? not required:
1851*3d8817e4Smiod 		 (delay_slot_type != ARC_DELAY_NONE) &&  */
1852*3d8817e4Smiod 	      cc_set_p && !limm_p;
1853*3d8817e4Smiod 	  }
1854*3d8817e4Smiod 
1855*3d8817e4Smiod 	  /* Write out the instruction.
1856*3d8817e4Smiod 	     It is important to fetch enough space in one call to `frag_more'.
1857*3d8817e4Smiod 	     We use (f - frag_now->fr_literal) to compute where we are and we
1858*3d8817e4Smiod 	     don't want frag_now to change between calls.  */
1859*3d8817e4Smiod 	  if (limm_p)
1860*3d8817e4Smiod 	    {
1861*3d8817e4Smiod 	      f = frag_more (8);
1862*3d8817e4Smiod 	      md_number_to_chars (f, insn, 4);
1863*3d8817e4Smiod 	      md_number_to_chars (f + 4, limm, 4);
1864*3d8817e4Smiod 	      dwarf2_emit_insn (8);
1865*3d8817e4Smiod 	    }
1866*3d8817e4Smiod 	  else if (limm_reloc_p)
1867*3d8817e4Smiod 	    /* We need a limm reloc, but the tables think we don't.  */
1868*3d8817e4Smiod 	    abort ();
1869*3d8817e4Smiod 	  else
1870*3d8817e4Smiod 	    {
1871*3d8817e4Smiod 	      f = frag_more (4);
1872*3d8817e4Smiod 	      md_number_to_chars (f, insn, 4);
1873*3d8817e4Smiod 	      dwarf2_emit_insn (4);
1874*3d8817e4Smiod 	    }
1875*3d8817e4Smiod 
1876*3d8817e4Smiod 	  /* Create any fixups.  */
1877*3d8817e4Smiod 	  for (i = 0; i < fc; ++i)
1878*3d8817e4Smiod 	    {
1879*3d8817e4Smiod 	      int op_type, reloc_type;
1880*3d8817e4Smiod 	      expressionS exptmp;
1881*3d8817e4Smiod 	      const struct arc_operand *operand;
1882*3d8817e4Smiod 
1883*3d8817e4Smiod 	      /* Create a fixup for this operand.
1884*3d8817e4Smiod 		 At this point we do not use a bfd_reloc_code_real_type for
1885*3d8817e4Smiod 		 operands residing in the insn, but instead just use the
1886*3d8817e4Smiod 		 operand index.  This lets us easily handle fixups for any
1887*3d8817e4Smiod 		 operand type, although that is admittedly not a very exciting
1888*3d8817e4Smiod 		 feature.  We pick a BFD reloc type in md_apply_fix.
1889*3d8817e4Smiod 
1890*3d8817e4Smiod 		 Limm values (4 byte immediate "constants") must be treated
1891*3d8817e4Smiod 		 normally because they're not part of the actual insn word
1892*3d8817e4Smiod 		 and thus the insertion routines don't handle them.  */
1893*3d8817e4Smiod 
1894*3d8817e4Smiod 	      if (arc_operands[fixups[i].opindex].flags & ARC_OPERAND_LIMM)
1895*3d8817e4Smiod 		{
1896*3d8817e4Smiod 		  /* Modify the fixup addend as required by the cpu.  */
1897*3d8817e4Smiod 		  fixups[i].exp.X_add_number += arc_limm_fixup_adjust (insn);
1898*3d8817e4Smiod 		  op_type = fixups[i].opindex;
1899*3d8817e4Smiod 		  /* FIXME: can we add this data to the operand table?  */
1900*3d8817e4Smiod 		  if (op_type == arc_operand_map['L']
1901*3d8817e4Smiod 		      || op_type == arc_operand_map['s']
1902*3d8817e4Smiod 		      || op_type == arc_operand_map['o']
1903*3d8817e4Smiod 		      || op_type == arc_operand_map['O'])
1904*3d8817e4Smiod 		    reloc_type = BFD_RELOC_32;
1905*3d8817e4Smiod 		  else if (op_type == arc_operand_map['J'])
1906*3d8817e4Smiod 		    reloc_type = BFD_RELOC_ARC_B26;
1907*3d8817e4Smiod 		  else
1908*3d8817e4Smiod 		    abort ();
1909*3d8817e4Smiod 		  reloc_type = get_arc_exp_reloc_type (1, reloc_type,
1910*3d8817e4Smiod 						       &fixups[i].exp,
1911*3d8817e4Smiod 						       &exptmp);
1912*3d8817e4Smiod 		}
1913*3d8817e4Smiod 	      else
1914*3d8817e4Smiod 		{
1915*3d8817e4Smiod 		  op_type = get_arc_exp_reloc_type (0, fixups[i].opindex,
1916*3d8817e4Smiod 						    &fixups[i].exp, &exptmp);
1917*3d8817e4Smiod 		  reloc_type = op_type + (int) BFD_RELOC_UNUSED;
1918*3d8817e4Smiod 		}
1919*3d8817e4Smiod 	      operand = &arc_operands[op_type];
1920*3d8817e4Smiod 	      fix_new_exp (frag_now,
1921*3d8817e4Smiod 			   ((f - frag_now->fr_literal)
1922*3d8817e4Smiod 			    + (operand->flags & ARC_OPERAND_LIMM ? 4 : 0)), 4,
1923*3d8817e4Smiod 			   &exptmp,
1924*3d8817e4Smiod 			   (operand->flags & ARC_OPERAND_RELATIVE_BRANCH) != 0,
1925*3d8817e4Smiod 			   (bfd_reloc_code_real_type) reloc_type);
1926*3d8817e4Smiod 	    }
1927*3d8817e4Smiod 	  return;
1928*3d8817e4Smiod 	}
1929*3d8817e4Smiod     }
1930*3d8817e4Smiod 
1931*3d8817e4Smiod   if (NULL == last_errmsg)
1932*3d8817e4Smiod     as_bad ("bad instruction `%s'", start);
1933*3d8817e4Smiod   else
1934*3d8817e4Smiod     as_bad (last_errmsg);
1935*3d8817e4Smiod }
1936