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