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