xref: /netbsd-src/external/gpl3/binutils/dist/gas/config/tc-arc.c (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
1 /* tc-arc.c -- Assembler for the ARC
2    Copyright (C) 1994-2024 Free Software Foundation, Inc.
3 
4    Contributor: Claudiu Zissulescu <claziss@synopsys.com>
5 
6    This file is part of GAS, the GNU Assembler.
7 
8    GAS is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3, or (at your option)
11    any later version.
12 
13    GAS is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with GAS; see the file COPYING.  If not, write to the Free
20    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21    02110-1301, USA.  */
22 
23 #include "as.h"
24 #include "subsegs.h"
25 #include "dwarf2dbg.h"
26 #include "dw2gencfi.h"
27 #include "safe-ctype.h"
28 
29 #include "opcode/arc.h"
30 #include "opcode/arc-attrs.h"
31 #include "elf/arc.h"
32 #include "../opcodes/arc-ext.h"
33 
34 /* Defines section.  */
35 
36 #define MAX_INSN_FIXUPS      2
37 #define MAX_CONSTR_STR       20
38 #define FRAG_MAX_GROWTH      8
39 
40 #ifdef DEBUG
41 # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
42 #else
43 # define pr_debug(fmt, args...)
44 #endif
45 
46 #define MAJOR_OPCODE(x)  (((x) & 0xF8000000) >> 27)
47 #define SUB_OPCODE(x)	 (((x) & 0x003F0000) >> 16)
48 #define LP_INSN(x)	 ((MAJOR_OPCODE (x) == 0x4) \
49 			  && (SUB_OPCODE (x) == 0x28))
50 
51 #ifndef TARGET_WITH_CPU
52 #define TARGET_WITH_CPU "hs38_linux"
53 #endif /* TARGET_WITH_CPU */
54 
55 #define ARC_GET_FLAG(s)   	(*symbol_get_tc (s))
56 #define ARC_SET_FLAG(s,v) 	(*symbol_get_tc (s) |= (v))
57 #define streq(a, b)	      (strcmp (a, b) == 0)
58 
59 /* Enum used to enumerate the relaxable ins operands.  */
60 enum rlx_operand_type
61 {
62   EMPTY = 0,
63   REGISTER,
64   REGISTER_S,     /* Register for short instruction(s).  */
65   REGISTER_NO_GP, /* Is a register but not gp register specifically.  */
66   REGISTER_DUP,   /* Duplication of previous operand of type register.  */
67   IMMEDIATE,
68   BRACKET
69 };
70 
71 enum arc_rlx_types
72 {
73   ARC_RLX_NONE = 0,
74   ARC_RLX_BL_S,
75   ARC_RLX_BL,
76   ARC_RLX_B_S,
77   ARC_RLX_B,
78   ARC_RLX_ADD_U3,
79   ARC_RLX_ADD_U6,
80   ARC_RLX_ADD_LIMM,
81   ARC_RLX_LD_U7,
82   ARC_RLX_LD_S9,
83   ARC_RLX_LD_LIMM,
84   ARC_RLX_MOV_U8,
85   ARC_RLX_MOV_S12,
86   ARC_RLX_MOV_LIMM,
87   ARC_RLX_SUB_U3,
88   ARC_RLX_SUB_U6,
89   ARC_RLX_SUB_LIMM,
90   ARC_RLX_MPY_U6,
91   ARC_RLX_MPY_LIMM,
92   ARC_RLX_MOV_RU6,
93   ARC_RLX_MOV_RLIMM,
94   ARC_RLX_ADD_RRU6,
95   ARC_RLX_ADD_RRLIMM,
96 };
97 
98 /* Macros section.  */
99 
100 #define regno(x)		((x) & 0x3F)
101 #define is_ir_num(x)		(((x) & ~0x3F) == 0)
102 #define is_code_density_p(sc)   (((sc) == CD1 || (sc) == CD2))
103 #define is_spfp_p(op)           (((sc) == SPX))
104 #define is_dpfp_p(op)           (((sc) == DPX))
105 #define is_fpuda_p(op)          (((sc) == DPA))
106 #define is_br_jmp_insn_p(op)    (((op)->insn_class == BRANCH		\
107 				  || (op)->insn_class == JUMP		\
108 				  || (op)->insn_class == BRCC		\
109 				  || (op)->insn_class == BBIT0		\
110 				  || (op)->insn_class == BBIT1		\
111 				  || (op)->insn_class == BI		\
112 				  || (op)->insn_class == EI		\
113 				  || (op)->insn_class == ENTER		\
114 				  || (op)->insn_class == JLI		\
115 				  || (op)->insn_class == LOOP		\
116 				  || (op)->insn_class == LEAVE		\
117 				  ))
118 #define is_kernel_insn_p(op)    (((op)->insn_class == KERNEL))
119 #define is_nps400_p(op)         (((sc) == NPS400))
120 
121 /* Generic assembler global variables which must be defined by all
122    targets.  */
123 
124 /* Characters which always start a comment.  */
125 const char comment_chars[] = "#;";
126 
127 /* Characters which start a comment at the beginning of a line.  */
128 const char line_comment_chars[] = "#";
129 
130 /* Characters which may be used to separate multiple commands on a
131    single line.  */
132 const char line_separator_chars[] = "`";
133 
134 /* Characters which are used to indicate an exponent in a floating
135    point number.  */
136 const char EXP_CHARS[] = "eE";
137 
138 /* Chars that mean this number is a floating point constant
139    As in 0f12.456 or 0d1.2345e12.  */
140 const char FLT_CHARS[] = "rRsSfFdD";
141 
142 /* Byte order.  */
143 extern int target_big_endian;
144 const char *arc_target_format = DEFAULT_TARGET_FORMAT;
145 static int byte_order = DEFAULT_BYTE_ORDER;
146 
147 /* Arc extension section.  */
148 static segT arcext_section;
149 
150 /* By default relaxation is disabled.  */
151 static int relaxation_state = 0;
152 
153 extern int arc_get_mach (char *);
154 
155 /* Forward declarations.  */
156 static void arc_lcomm (int);
157 static void arc_option (int);
158 static void arc_extra_reloc (int);
159 static void arc_extinsn (int);
160 static void arc_extcorereg (int);
161 static void arc_attribute (int);
162 
163 const pseudo_typeS md_pseudo_table[] =
164 {
165   /* Make sure that .word is 32 bits.  */
166   { "word", cons, 4 },
167 
168   { "align",   s_align_bytes, 0 }, /* Defaulting is invalid (0).  */
169   { "lcomm",   arc_lcomm, 0 },
170   { "lcommon", arc_lcomm, 0 },
171   { "cpu",     arc_option, 0 },
172 
173   { "arc_attribute",   arc_attribute, 0 },
174   { "extinstruction",  arc_extinsn, 0 },
175   { "extcoreregister", arc_extcorereg, EXT_CORE_REGISTER },
176   { "extauxregister",  arc_extcorereg, EXT_AUX_REGISTER },
177   { "extcondcode",     arc_extcorereg, EXT_COND_CODE },
178 
179   { "tls_gd_ld",   arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_LD },
180   { "tls_gd_call", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_CALL },
181 
182   { NULL, NULL, 0 }
183 };
184 
185 const char *md_shortopts = "";
186 
187 enum options
188 {
189   OPTION_EB = OPTION_MD_BASE,
190   OPTION_EL,
191 
192   OPTION_ARC600,
193   OPTION_ARC601,
194   OPTION_ARC700,
195   OPTION_ARCEM,
196   OPTION_ARCHS,
197 
198   OPTION_MCPU,
199   OPTION_CD,
200   OPTION_RELAX,
201   OPTION_NPS400,
202 
203   OPTION_SPFP,
204   OPTION_DPFP,
205   OPTION_FPUDA,
206 
207   /* The following options are deprecated and provided here only for
208      compatibility reasons.  */
209   OPTION_USER_MODE,
210   OPTION_LD_EXT_MASK,
211   OPTION_SWAP,
212   OPTION_NORM,
213   OPTION_BARREL_SHIFT,
214   OPTION_MIN_MAX,
215   OPTION_NO_MPY,
216   OPTION_EA,
217   OPTION_MUL64,
218   OPTION_SIMD,
219   OPTION_XMAC_D16,
220   OPTION_XMAC_24,
221   OPTION_DSP_PACKA,
222   OPTION_CRC,
223   OPTION_DVBF,
224   OPTION_TELEPHONY,
225   OPTION_XYMEMORY,
226   OPTION_LOCK,
227   OPTION_SWAPE,
228   OPTION_RTSC
229 };
230 
231 struct option md_longopts[] =
232 {
233   { "EB",		no_argument,	   NULL, OPTION_EB },
234   { "EL",		no_argument,	   NULL, OPTION_EL },
235   { "mcpu",		required_argument, NULL, OPTION_MCPU },
236   { "mA6",		no_argument,	   NULL, OPTION_ARC600 },
237   { "mARC600",		no_argument,	   NULL, OPTION_ARC600 },
238   { "mARC601",		no_argument,	   NULL, OPTION_ARC601 },
239   { "mARC700",		no_argument,	   NULL, OPTION_ARC700 },
240   { "mA7",		no_argument,	   NULL, OPTION_ARC700 },
241   { "mEM",		no_argument,	   NULL, OPTION_ARCEM },
242   { "mHS",		no_argument,	   NULL, OPTION_ARCHS },
243   { "mcode-density",	no_argument,	   NULL, OPTION_CD },
244   { "mrelax",           no_argument,       NULL, OPTION_RELAX },
245   { "mnps400",          no_argument,       NULL, OPTION_NPS400 },
246 
247   /* Floating point options */
248   { "mspfp", no_argument, NULL, OPTION_SPFP},
249   { "mspfp-compact", no_argument, NULL, OPTION_SPFP},
250   { "mspfp_compact", no_argument, NULL, OPTION_SPFP},
251   { "mspfp-fast", no_argument, NULL, OPTION_SPFP},
252   { "mspfp_fast", no_argument, NULL, OPTION_SPFP},
253   { "mdpfp", no_argument, NULL, OPTION_DPFP},
254   { "mdpfp-compact", no_argument, NULL, OPTION_DPFP},
255   { "mdpfp_compact", no_argument, NULL, OPTION_DPFP},
256   { "mdpfp-fast", no_argument, NULL, OPTION_DPFP},
257   { "mdpfp_fast", no_argument, NULL, OPTION_DPFP},
258   { "mfpuda", no_argument, NULL, OPTION_FPUDA},
259 
260   /* The following options are deprecated and provided here only for
261      compatibility reasons.  */
262   { "mav2em", no_argument, NULL, OPTION_ARCEM },
263   { "mav2hs", no_argument, NULL, OPTION_ARCHS },
264   { "muser-mode-only", no_argument, NULL, OPTION_USER_MODE },
265   { "mld-extension-reg-mask", required_argument, NULL, OPTION_LD_EXT_MASK },
266   { "mswap", no_argument, NULL, OPTION_SWAP },
267   { "mnorm", no_argument, NULL, OPTION_NORM },
268   { "mbarrel-shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
269   { "mbarrel_shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
270   { "mmin-max", no_argument, NULL, OPTION_MIN_MAX },
271   { "mmin_max", no_argument, NULL, OPTION_MIN_MAX },
272   { "mno-mpy", no_argument, NULL, OPTION_NO_MPY },
273   { "mea", no_argument, NULL, OPTION_EA },
274   { "mEA", no_argument, NULL, OPTION_EA },
275   { "mmul64", no_argument, NULL, OPTION_MUL64 },
276   { "msimd", no_argument, NULL, OPTION_SIMD},
277   { "mmac-d16", no_argument, NULL, OPTION_XMAC_D16},
278   { "mmac_d16", no_argument, NULL, OPTION_XMAC_D16},
279   { "mmac-24", no_argument, NULL, OPTION_XMAC_24},
280   { "mmac_24", no_argument, NULL, OPTION_XMAC_24},
281   { "mdsp-packa", no_argument, NULL, OPTION_DSP_PACKA},
282   { "mdsp_packa", no_argument, NULL, OPTION_DSP_PACKA},
283   { "mcrc", no_argument, NULL, OPTION_CRC},
284   { "mdvbf", no_argument, NULL, OPTION_DVBF},
285   { "mtelephony", no_argument, NULL, OPTION_TELEPHONY},
286   { "mxy", no_argument, NULL, OPTION_XYMEMORY},
287   { "mlock", no_argument, NULL, OPTION_LOCK},
288   { "mswape", no_argument, NULL, OPTION_SWAPE},
289   { "mrtsc", no_argument, NULL, OPTION_RTSC},
290 
291   { NULL,		no_argument, NULL, 0 }
292 };
293 
294 size_t md_longopts_size = sizeof (md_longopts);
295 
296 /* Local data and data types.  */
297 
298 /* Used since new relocation types are introduced in this
299    file (DUMMY_RELOC_LITUSE_*).  */
300 typedef int extended_bfd_reloc_code_real_type;
301 
302 struct arc_fixup
303 {
304   expressionS exp;
305 
306   extended_bfd_reloc_code_real_type reloc;
307 
308   /* index into arc_operands.  */
309   unsigned int opindex;
310 
311   /* PC-relative, used by internals fixups.  */
312   unsigned char pcrel;
313 
314   /* TRUE if this fixup is for LIMM operand.  */
315   bool islong;
316 };
317 
318 struct arc_insn
319 {
320   unsigned long long int insn;
321   int nfixups;
322   struct arc_fixup fixups[MAX_INSN_FIXUPS];
323   long limm;
324   unsigned int len;     /* Length of instruction in bytes.  */
325   bool has_limm;	/* Boolean value: TRUE if limm field is valid.  */
326   bool relax;		/* Boolean value: TRUE if needs relaxation.  */
327 };
328 
329 /* Structure to hold any last two instructions.  */
330 static struct arc_last_insn
331 {
332   /* Saved instruction opcode.  */
333   const struct arc_opcode *opcode;
334 
335   /* Boolean value: TRUE if current insn is short.  */
336   bool has_limm;
337 
338   /* Boolean value: TRUE if current insn has delay slot.  */
339   bool has_delay_slot;
340 } arc_last_insns[2];
341 
342 /* Extension instruction suffix classes.  */
343 typedef struct
344 {
345   const char *name;
346   int  len;
347   int  attr_class;
348 } attributes_t;
349 
350 static const attributes_t suffixclass[] =
351 {
352   { "SUFFIX_FLAG", 11, ARC_SUFFIX_FLAG },
353   { "SUFFIX_COND", 11, ARC_SUFFIX_COND },
354   { "SUFFIX_NONE", 11, ARC_SUFFIX_NONE }
355 };
356 
357 /* Extension instruction syntax classes.  */
358 static const attributes_t syntaxclass[] =
359 {
360   { "SYNTAX_3OP", 10, ARC_SYNTAX_3OP },
361   { "SYNTAX_2OP", 10, ARC_SYNTAX_2OP },
362   { "SYNTAX_1OP", 10, ARC_SYNTAX_1OP },
363   { "SYNTAX_NOP", 10, ARC_SYNTAX_NOP }
364 };
365 
366 /* Extension instruction syntax classes modifiers.  */
367 static const attributes_t syntaxclassmod[] =
368 {
369   { "OP1_IMM_IMPLIED" , 15, ARC_OP1_IMM_IMPLIED },
370   { "OP1_MUST_BE_IMM" , 15, ARC_OP1_MUST_BE_IMM }
371 };
372 
373 /* Extension register type.  */
374 typedef struct
375 {
376   char *name;
377   int  number;
378   int  imode;
379 } extRegister_t;
380 
381 /* A structure to hold the additional conditional codes.  */
382 static struct
383 {
384   struct arc_flag_operand *arc_ext_condcode;
385   int size;
386 } ext_condcode = { NULL, 0 };
387 
388 /* Structure to hold an entry in ARC_OPCODE_HASH.  */
389 struct arc_opcode_hash_entry
390 {
391   /* The number of pointers in the OPCODE list.  */
392   size_t count;
393 
394   /* Points to a list of opcode pointers.  */
395   const struct arc_opcode **opcode;
396 };
397 
398 /* Structure used for iterating through an arc_opcode_hash_entry.  */
399 struct arc_opcode_hash_entry_iterator
400 {
401   /* Index into the OPCODE element of the arc_opcode_hash_entry.  */
402   size_t index;
403 
404   /* The specific ARC_OPCODE from the ARC_OPCODES table that was last
405      returned by this iterator.  */
406   const struct arc_opcode *opcode;
407 };
408 
409 /* Forward declaration.  */
410 static void assemble_insn
411   (const struct arc_opcode *, const expressionS *, int,
412    const struct arc_flags *, int, struct arc_insn *);
413 
414 /* The selection of the machine type can come from different sources.  This
415    enum is used to track how the selection was made in order to perform
416    error checks.  */
417 enum mach_selection_type
418   {
419     MACH_SELECTION_NONE,
420     MACH_SELECTION_FROM_DEFAULT,
421     MACH_SELECTION_FROM_CPU_DIRECTIVE,
422     MACH_SELECTION_FROM_COMMAND_LINE
423   };
424 
425 /* How the current machine type was selected.  */
426 static enum mach_selection_type mach_selection_mode = MACH_SELECTION_NONE;
427 
428 /* The hash table of instruction opcodes.  */
429 static htab_t arc_opcode_hash;
430 
431 /* The hash table of register symbols.  */
432 static htab_t arc_reg_hash;
433 
434 /* The hash table of aux register symbols.  */
435 static htab_t arc_aux_hash;
436 
437 /* The hash table of address types.  */
438 static htab_t arc_addrtype_hash;
439 
440 #define ARC_CPU_TYPE_A6xx(NAME,EXTRA)			\
441   { #NAME, ARC_OPCODE_ARC600, bfd_mach_arc_arc600,	\
442       E_ARC_MACH_ARC600, EXTRA}
443 #define ARC_CPU_TYPE_A7xx(NAME,EXTRA)			\
444   { #NAME, ARC_OPCODE_ARC700,  bfd_mach_arc_arc700,	\
445       E_ARC_MACH_ARC700, EXTRA}
446 #define ARC_CPU_TYPE_AV2EM(NAME,EXTRA)			\
447   { #NAME,  ARC_OPCODE_ARCv2EM, bfd_mach_arc_arcv2,	\
448       EF_ARC_CPU_ARCV2EM, EXTRA}
449 #define ARC_CPU_TYPE_AV2HS(NAME,EXTRA)			\
450   { #NAME,  ARC_OPCODE_ARCv2HS, bfd_mach_arc_arcv2,	\
451       EF_ARC_CPU_ARCV2HS, EXTRA}
452 #define ARC_CPU_TYPE_NONE				\
453   { 0, 0, 0, 0, 0 }
454 
455 /* A table of CPU names and opcode sets.  */
456 static const struct cpu_type
457 {
458   const char *name;
459   unsigned flags;
460   int mach;
461   unsigned eflags;
462   unsigned features;
463 }
464   cpu_types[] =
465 {
466   #include "elf/arc-cpu.def"
467 };
468 
469 /* Information about the cpu/variant we're assembling for.  */
470 static struct cpu_type selected_cpu = { 0, 0, 0, E_ARC_OSABI_CURRENT, 0 };
471 
472 /* TRUE if current assembly code uses RF16 only registers.  */
473 static bool rf16_only = true;
474 
475 /* MPY option.  */
476 static unsigned mpy_option = 0;
477 
478 /* Use PIC. */
479 static unsigned pic_option = 0;
480 
481 /* Use small data.  */
482 static unsigned sda_option = 0;
483 
484 /* Use TLS.  */
485 static unsigned tls_option = 0;
486 
487 /* Command line given features.  */
488 static unsigned cl_features = 0;
489 
490 /* Used by the arc_reloc_op table.  Order is important.  */
491 #define O_gotoff  O_md1     /* @gotoff relocation.  */
492 #define O_gotpc   O_md2     /* @gotpc relocation.  */
493 #define O_plt     O_md3     /* @plt relocation.  */
494 #define O_sda     O_md4     /* @sda relocation.  */
495 #define O_pcl     O_md5     /* @pcl relocation.  */
496 #define O_tlsgd   O_md6     /* @tlsgd relocation.  */
497 #define O_tlsie   O_md7     /* @tlsie relocation.  */
498 #define O_tpoff9  O_md8     /* @tpoff9 relocation.  */
499 #define O_tpoff   O_md9     /* @tpoff relocation.  */
500 #define O_dtpoff9 O_md10    /* @dtpoff9 relocation.  */
501 #define O_dtpoff  O_md11    /* @dtpoff relocation.  */
502 #define O_last    O_dtpoff
503 
504 /* Used to define a bracket as operand in tokens.  */
505 #define O_bracket O_md32
506 
507 /* Used to define a colon as an operand in tokens.  */
508 #define O_colon O_md31
509 
510 /* Used to define address types in nps400.  */
511 #define O_addrtype O_md30
512 
513 /* Dummy relocation, to be sorted out.  */
514 #define DUMMY_RELOC_ARC_ENTRY     (BFD_RELOC_UNUSED + 1)
515 
516 #define USER_RELOC_P(R) ((R) >= O_gotoff && (R) <= O_last)
517 
518 /* A table to map the spelling of a relocation operand into an appropriate
519    bfd_reloc_code_real_type type.  The table is assumed to be ordered such
520    that op-O_literal indexes into it.  */
521 #define ARC_RELOC_TABLE(op)				\
522   (&arc_reloc_op[ ((!USER_RELOC_P (op))			\
523 		   ? (abort (), 0)			\
524 		   : (int) (op) - (int) O_gotoff) ])
525 
526 #define DEF(NAME, RELOC, REQ)				\
527   { #NAME, sizeof (#NAME)-1, O_##NAME, RELOC, REQ}
528 
529 static const struct arc_reloc_op_tag
530 {
531   /* String to lookup.  */
532   const char *name;
533   /* Size of the string.  */
534   size_t length;
535   /* Which operator to use.  */
536   operatorT op;
537   extended_bfd_reloc_code_real_type reloc;
538   /* Allows complex relocation expression like identifier@reloc +
539      const.  */
540   unsigned int complex_expr : 1;
541 }
542   arc_reloc_op[] =
543 {
544   DEF (gotoff,  BFD_RELOC_ARC_GOTOFF,		1),
545   DEF (gotpc,   BFD_RELOC_ARC_GOTPC32,		0),
546   DEF (plt,	BFD_RELOC_ARC_PLT32,		0),
547   DEF (sda,	DUMMY_RELOC_ARC_ENTRY,		1),
548   DEF (pcl,	BFD_RELOC_ARC_PC32,		1),
549   DEF (tlsgd,   BFD_RELOC_ARC_TLS_GD_GOT,	0),
550   DEF (tlsie,   BFD_RELOC_ARC_TLS_IE_GOT,	0),
551   DEF (tpoff9,  BFD_RELOC_ARC_TLS_LE_S9,	0),
552   DEF (tpoff,   BFD_RELOC_ARC_TLS_LE_32,	1),
553   DEF (dtpoff9, BFD_RELOC_ARC_TLS_DTPOFF_S9,	0),
554   DEF (dtpoff,  BFD_RELOC_ARC_TLS_DTPOFF,	1),
555 };
556 
557 static const int arc_num_reloc_op
558 = sizeof (arc_reloc_op) / sizeof (*arc_reloc_op);
559 
560 /* Structure for relaxable instruction that have to be swapped with a
561    smaller alternative instruction.  */
562 struct arc_relaxable_ins
563 {
564   /* Mnemonic that should be checked.  */
565   const char *mnemonic_r;
566 
567   /* Operands that should be checked.
568      Indexes of operands from operand array.  */
569   enum rlx_operand_type operands[6];
570 
571   /* Flags that should be checked.  */
572   unsigned flag_classes[5];
573 
574   /* Mnemonic (smaller) alternative to be used later for relaxation.  */
575   const char *mnemonic_alt;
576 
577   /* Index of operand that generic relaxation has to check.  */
578   unsigned opcheckidx;
579 
580   /* Base subtype index used.  */
581   enum arc_rlx_types subtype;
582 };
583 
584 #define RELAX_TABLE_ENTRY(BITS, ISSIGNED, SIZE, NEXT)			\
585   { (ISSIGNED) ? ((1 << ((BITS) - 1)) - 1) : ((1 << (BITS)) - 1),	\
586       (ISSIGNED) ? -(1 << ((BITS) - 1)) : 0,				\
587       (SIZE),								\
588       (NEXT) }								\
589 
590 #define RELAX_TABLE_ENTRY_MAX(ISSIGNED, SIZE, NEXT)	\
591   { (ISSIGNED) ? 0x7FFFFFFF : 0xFFFFFFFF,		\
592       (ISSIGNED) ? -(0x7FFFFFFF) : 0,                   \
593       (SIZE),                                           \
594       (NEXT) }                                          \
595 
596 
597 /* ARC relaxation table.  */
598 const relax_typeS md_relax_table[] =
599 {
600   /* Fake entry.  */
601   {0, 0, 0, 0},
602 
603   /* BL_S s13 ->
604      BL s25.  */
605   RELAX_TABLE_ENTRY (13, 1, 2, ARC_RLX_BL),
606   RELAX_TABLE_ENTRY (25, 1, 4, ARC_RLX_NONE),
607 
608   /* B_S s10 ->
609      B s25.  */
610   RELAX_TABLE_ENTRY (10, 1, 2, ARC_RLX_B),
611   RELAX_TABLE_ENTRY (25, 1, 4, ARC_RLX_NONE),
612 
613   /* ADD_S c,b, u3 ->
614      ADD<.f> a,b,u6 ->
615      ADD<.f> a,b,limm.  */
616   RELAX_TABLE_ENTRY (3, 0, 2, ARC_RLX_ADD_U6),
617   RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_ADD_LIMM),
618   RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
619 
620   /* LD_S a, [b, u7] ->
621      LD<zz><.x><.aa><.di> a, [b, s9] ->
622      LD<zz><.x><.aa><.di> a, [b, limm] */
623   RELAX_TABLE_ENTRY (7, 0, 2, ARC_RLX_LD_S9),
624   RELAX_TABLE_ENTRY (9, 1, 4, ARC_RLX_LD_LIMM),
625   RELAX_TABLE_ENTRY_MAX (1, 8, ARC_RLX_NONE),
626 
627   /* MOV_S b, u8 ->
628      MOV<.f> b, s12 ->
629      MOV<.f> b, limm.  */
630   RELAX_TABLE_ENTRY (8, 0, 2, ARC_RLX_MOV_S12),
631   RELAX_TABLE_ENTRY (8, 0, 4, ARC_RLX_MOV_LIMM),
632   RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
633 
634   /* SUB_S c, b, u3 ->
635      SUB<.f> a, b, u6 ->
636      SUB<.f> a, b, limm.  */
637   RELAX_TABLE_ENTRY (3, 0, 2, ARC_RLX_SUB_U6),
638   RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_SUB_LIMM),
639   RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
640 
641   /* MPY<.f> a, b, u6 ->
642      MPY<.f> a, b, limm.  */
643   RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_MPY_LIMM),
644   RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
645 
646   /* MOV<.f><.cc> b, u6 ->
647      MOV<.f><.cc> b, limm.  */
648   RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_MOV_RLIMM),
649   RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
650 
651   /* ADD<.f><.cc> b, b, u6 ->
652      ADD<.f><.cc> b, b, limm.  */
653   RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_ADD_RRLIMM),
654   RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
655 };
656 
657 /* Order of this table's entries matters!  */
658 const struct arc_relaxable_ins arc_relaxable_insns[] =
659 {
660   { "bl", { IMMEDIATE }, { 0 }, "bl_s", 0, ARC_RLX_BL_S },
661   { "b", { IMMEDIATE }, { 0 }, "b_s", 0, ARC_RLX_B_S },
662   { "add", { REGISTER, REGISTER_DUP, IMMEDIATE }, { 5, 1, 0 }, "add",
663     2, ARC_RLX_ADD_RRU6},
664   { "add", { REGISTER_S, REGISTER_S, IMMEDIATE }, { 0 }, "add_s", 2,
665     ARC_RLX_ADD_U3 },
666   { "add", { REGISTER, REGISTER, IMMEDIATE }, { 5, 0 }, "add", 2,
667     ARC_RLX_ADD_U6 },
668   { "ld", { REGISTER_S, BRACKET, REGISTER_S, IMMEDIATE, BRACKET },
669     { 0 }, "ld_s", 3, ARC_RLX_LD_U7 },
670   { "ld", { REGISTER, BRACKET, REGISTER_NO_GP, IMMEDIATE, BRACKET },
671     { 11, 4, 14, 17, 0 }, "ld", 3, ARC_RLX_LD_S9 },
672   { "mov", { REGISTER_S, IMMEDIATE }, { 0 }, "mov_s", 1, ARC_RLX_MOV_U8 },
673   { "mov", { REGISTER, IMMEDIATE }, { 5, 0 }, "mov", 1, ARC_RLX_MOV_S12 },
674   { "mov", { REGISTER, IMMEDIATE }, { 5, 1, 0 },"mov", 1, ARC_RLX_MOV_RU6 },
675   { "sub", { REGISTER_S, REGISTER_S, IMMEDIATE }, { 0 }, "sub_s", 2,
676     ARC_RLX_SUB_U3 },
677   { "sub", { REGISTER, REGISTER, IMMEDIATE }, { 5, 0 }, "sub", 2,
678     ARC_RLX_SUB_U6 },
679   { "mpy", { REGISTER, REGISTER, IMMEDIATE }, { 5, 0 }, "mpy", 2,
680     ARC_RLX_MPY_U6 },
681 };
682 
683 const unsigned arc_num_relaxable_ins = ARRAY_SIZE (arc_relaxable_insns);
684 
685 /* Pre-defined "_GLOBAL_OFFSET_TABLE_".  */
686 symbolS * GOT_symbol = 0;
687 
688 /* Set to TRUE when we assemble instructions.  */
689 static bool assembling_insn = false;
690 
691 /* List with attributes set explicitly.  */
692 static bool attributes_set_explicitly[NUM_KNOWN_OBJ_ATTRIBUTES];
693 
694 /* Functions implementation.  */
695 
696 /* Return a pointer to ARC_OPCODE_HASH_ENTRY that identifies all
697    ARC_OPCODE entries in ARC_OPCODE_HASH that match NAME, or NULL if there
698    are no matching entries in ARC_OPCODE_HASH.  */
699 
700 static const struct arc_opcode_hash_entry *
arc_find_opcode(const char * name)701 arc_find_opcode (const char *name)
702 {
703   const struct arc_opcode_hash_entry *entry;
704 
705   entry = str_hash_find (arc_opcode_hash, name);
706   return entry;
707 }
708 
709 /* Initialise the iterator ITER.  */
710 
711 static void
arc_opcode_hash_entry_iterator_init(struct arc_opcode_hash_entry_iterator * iter)712 arc_opcode_hash_entry_iterator_init (struct arc_opcode_hash_entry_iterator *iter)
713 {
714   iter->index = 0;
715   iter->opcode = NULL;
716 }
717 
718 /* Return the next ARC_OPCODE from ENTRY, using ITER to hold state between
719    calls to this function.  Return NULL when all ARC_OPCODE entries have
720    been returned.  */
721 
722 static const struct arc_opcode *
arc_opcode_hash_entry_iterator_next(const struct arc_opcode_hash_entry * entry,struct arc_opcode_hash_entry_iterator * iter)723 arc_opcode_hash_entry_iterator_next (const struct arc_opcode_hash_entry *entry,
724 				     struct arc_opcode_hash_entry_iterator *iter)
725 {
726   if (iter->opcode == NULL && iter->index == 0)
727     {
728       gas_assert (entry->count > 0);
729       iter->opcode = entry->opcode[iter->index];
730     }
731   else if (iter->opcode != NULL)
732     {
733       const char *old_name = iter->opcode->name;
734 
735       iter->opcode++;
736       if (iter->opcode->name == NULL
737 	  || strcmp (old_name, iter->opcode->name) != 0)
738 	{
739 	  iter->index++;
740 	  if (iter->index == entry->count)
741 	    iter->opcode = NULL;
742 	  else
743 	    iter->opcode = entry->opcode[iter->index];
744 	}
745     }
746 
747   return iter->opcode;
748 }
749 
750 /* Insert an opcode into opcode hash structure.  */
751 
752 static void
arc_insert_opcode(const struct arc_opcode * opcode)753 arc_insert_opcode (const struct arc_opcode *opcode)
754 {
755   const char *name;
756   struct arc_opcode_hash_entry *entry;
757   name = opcode->name;
758 
759   entry = str_hash_find (arc_opcode_hash, name);
760   if (entry == NULL)
761     {
762       entry = XNEW (struct arc_opcode_hash_entry);
763       entry->count = 0;
764       entry->opcode = NULL;
765 
766       if (str_hash_insert (arc_opcode_hash, name, entry, 0) != NULL)
767 	as_fatal (_("duplicate %s"), name);
768     }
769 
770   entry->opcode = XRESIZEVEC (const struct arc_opcode *, entry->opcode,
771 			      entry->count + 1);
772 
773   entry->opcode[entry->count] = opcode;
774   entry->count++;
775 }
776 
777 static void
arc_opcode_free(void * elt)778 arc_opcode_free (void *elt)
779 {
780   string_tuple_t *tuple = (string_tuple_t *) elt;
781   struct arc_opcode_hash_entry *entry = (void *) tuple->value;
782   free (entry->opcode);
783   free (entry);
784   free (tuple);
785 }
786 
787 /* Like md_number_to_chars but for middle-endian values.  The 4-byte limm
788    value, is encoded as 'middle-endian' for a little-endian target.  This
789    function is used for regular 4, 6, and 8 byte instructions as well.  */
790 
791 static void
md_number_to_chars_midend(char * buf,unsigned long long val,int n)792 md_number_to_chars_midend (char *buf, unsigned long long val, int n)
793 {
794   switch (n)
795     {
796     case 2:
797       md_number_to_chars (buf, val, n);
798       break;
799     case 6:
800       md_number_to_chars (buf, (val & 0xffff00000000ull) >> 32, 2);
801       md_number_to_chars_midend (buf + 2, (val & 0xffffffff), 4);
802       break;
803     case 4:
804       md_number_to_chars (buf,     (val & 0xffff0000) >> 16, 2);
805       md_number_to_chars (buf + 2, (val & 0xffff), 2);
806       break;
807     case 8:
808       md_number_to_chars_midend (buf, (val & 0xffffffff00000000ull) >> 32, 4);
809       md_number_to_chars_midend (buf + 4, (val & 0xffffffff), 4);
810       break;
811     default:
812       abort ();
813     }
814 }
815 
816 /* Check if a feature is allowed for a specific CPU.  */
817 
818 static void
arc_check_feature(void)819 arc_check_feature (void)
820 {
821   unsigned i;
822 
823   if (!selected_cpu.features
824       || !selected_cpu.name)
825     return;
826 
827   for (i = 0; i < ARRAY_SIZE (feature_list); i++)
828     if ((selected_cpu.features & feature_list[i].feature)
829 	&& !(selected_cpu.flags & feature_list[i].cpus))
830       as_bad (_("invalid %s option for %s cpu"), feature_list[i].name,
831 	      selected_cpu.name);
832 
833   for (i = 0; i < ARRAY_SIZE (conflict_list); i++)
834     if ((selected_cpu.features & conflict_list[i]) == conflict_list[i])
835       as_bad(_("conflicting ISA extension attributes."));
836 }
837 
838 /* Select an appropriate entry from CPU_TYPES based on ARG and initialise
839    the relevant static global variables.  Parameter SEL describes where
840    this selection originated from.  */
841 
842 static void
arc_select_cpu(const char * arg,enum mach_selection_type sel)843 arc_select_cpu (const char *arg, enum mach_selection_type sel)
844 {
845   int i;
846   static struct cpu_type old_cpu = { 0, 0, 0, E_ARC_OSABI_CURRENT, 0 };
847 
848   /* We should only set a default if we've not made a selection from some
849      other source.  */
850   gas_assert (sel != MACH_SELECTION_FROM_DEFAULT
851               || mach_selection_mode == MACH_SELECTION_NONE);
852 
853   if ((mach_selection_mode == MACH_SELECTION_FROM_CPU_DIRECTIVE)
854       && (sel == MACH_SELECTION_FROM_CPU_DIRECTIVE))
855     as_bad (_("Multiple .cpu directives found"));
856 
857   /* Look for a matching entry in CPU_TYPES array.  */
858   for (i = 0; cpu_types[i].name; ++i)
859     {
860       if (!strcasecmp (cpu_types[i].name, arg))
861         {
862           /* If a previous selection was made on the command line, then we
863              allow later selections on the command line to override earlier
864              ones.  However, a selection from a '.cpu NAME' directive must
865              match the command line selection, or we give a warning.  */
866           if (mach_selection_mode == MACH_SELECTION_FROM_COMMAND_LINE)
867             {
868               gas_assert (sel == MACH_SELECTION_FROM_COMMAND_LINE
869                           || sel == MACH_SELECTION_FROM_CPU_DIRECTIVE);
870               if (sel == MACH_SELECTION_FROM_CPU_DIRECTIVE
871                   && selected_cpu.mach != cpu_types[i].mach)
872                 {
873                   as_warn (_("Command-line value overrides \".cpu\" directive"));
874                 }
875 	      return;
876             }
877 	  /* Initialise static global data about selected machine type.  */
878 	  selected_cpu.flags = cpu_types[i].flags;
879 	  selected_cpu.name = cpu_types[i].name;
880 	  selected_cpu.features = cpu_types[i].features | cl_features;
881 	  selected_cpu.mach = cpu_types[i].mach;
882 	  selected_cpu.eflags = ((selected_cpu.eflags & ~EF_ARC_MACH_MSK)
883 				 | cpu_types[i].eflags);
884           break;
885         }
886     }
887 
888   if (!cpu_types[i].name)
889     as_fatal (_("unknown architecture: %s\n"), arg);
890 
891   /* Check if set features are compatible with the chosen CPU.  */
892   arc_check_feature ();
893 
894   /* If we change the CPU, we need to re-init the bfd.  */
895   if (mach_selection_mode != MACH_SELECTION_NONE
896       && (old_cpu.mach != selected_cpu.mach))
897     {
898       bfd_find_target (arc_target_format, stdoutput);
899       if (! bfd_set_arch_mach (stdoutput, bfd_arch_arc, selected_cpu.mach))
900 	as_warn (_("Could not set architecture and machine"));
901     }
902 
903   mach_selection_mode = sel;
904   old_cpu = selected_cpu;
905 }
906 
907 /* Here ends all the ARCompact extension instruction assembling
908    stuff.  */
909 
910 static void
arc_extra_reloc(int r_type)911 arc_extra_reloc (int r_type)
912 {
913   char *sym_name, c;
914   symbolS *sym, *lab = NULL;
915 
916   if (*input_line_pointer == '@')
917     input_line_pointer++;
918   c = get_symbol_name (&sym_name);
919   sym = symbol_find_or_make (sym_name);
920   restore_line_pointer (c);
921   if (c == ',' && r_type == BFD_RELOC_ARC_TLS_GD_LD)
922     {
923       ++input_line_pointer;
924       char *lab_name;
925       c = get_symbol_name (&lab_name);
926       lab = symbol_find_or_make (lab_name);
927       restore_line_pointer (c);
928     }
929 
930   /* These relocations exist as a mechanism for the compiler to tell the
931      linker how to patch the code if the tls model is optimised.  However,
932      the relocation itself does not require any space within the assembler
933      fragment, and so we pass a size of 0.
934 
935      The lines that generate these relocations look like this:
936 
937          .tls_gd_ld @.tdata`bl __tls_get_addr@plt
938 
939      The '.tls_gd_ld @.tdata' is processed first and generates the
940      additional relocation, while the 'bl __tls_get_addr@plt' is processed
941      second and generates the additional branch.
942 
943      It is possible that the additional relocation generated by the
944      '.tls_gd_ld @.tdata' will be attached at the very end of one fragment,
945      while the 'bl __tls_get_addr@plt' will be generated as the first thing
946      in the next fragment.  This will be fine; both relocations will still
947      appear to be at the same address in the generated object file.
948      However, this only works as the additional relocation is generated
949      with size of 0 bytes.  */
950   fixS *fixP
951     = fix_new (frag_now,	/* Which frag?  */
952 	       frag_now_fix (),	/* Where in that frag?  */
953 	       0,		/* size: 1, 2, or 4 usually.  */
954 	       sym,		/* X_add_symbol.  */
955 	       0,		/* X_add_number.  */
956 	       false,		/* TRUE if PC-relative relocation.  */
957 	       r_type		/* Relocation type.  */);
958   fixP->fx_subsy = lab;
959 }
960 
961 static symbolS *
arc_lcomm_internal(int ignore ATTRIBUTE_UNUSED,symbolS * symbolP,addressT size)962 arc_lcomm_internal (int ignore ATTRIBUTE_UNUSED,
963 		    symbolS *symbolP, addressT size)
964 {
965   addressT align = 0;
966   SKIP_WHITESPACE ();
967 
968   if (*input_line_pointer == ',')
969     {
970       align = parse_align (1);
971 
972       if (align == (addressT) -1)
973 	return NULL;
974     }
975   else
976     {
977       if (size >= 8)
978 	align = 3;
979       else if (size >= 4)
980 	align = 2;
981       else if (size >= 2)
982 	align = 1;
983       else
984 	align = 0;
985     }
986 
987   bss_alloc (symbolP, size, align);
988   S_CLEAR_EXTERNAL (symbolP);
989 
990   return symbolP;
991 }
992 
993 static void
arc_lcomm(int ignore)994 arc_lcomm (int ignore)
995 {
996   symbolS *symbolP = s_comm_internal (ignore, arc_lcomm_internal);
997 
998   if (symbolP)
999     symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
1000 }
1001 
1002 /* Select the cpu we're assembling for.  */
1003 
1004 static void
arc_option(int ignore ATTRIBUTE_UNUSED)1005 arc_option (int ignore ATTRIBUTE_UNUSED)
1006 {
1007   char c;
1008   char *cpu;
1009   const char *cpu_name;
1010 
1011   c = get_symbol_name (&cpu);
1012 
1013   cpu_name = cpu;
1014   if ((!strcmp ("ARC600", cpu))
1015       || (!strcmp ("ARC601", cpu))
1016       || (!strcmp ("A6", cpu)))
1017     cpu_name = "arc600";
1018   else if ((!strcmp ("ARC700", cpu))
1019            || (!strcmp ("A7", cpu)))
1020     cpu_name = "arc700";
1021   else if (!strcmp ("EM", cpu))
1022     cpu_name = "arcem";
1023   else if (!strcmp ("HS", cpu))
1024     cpu_name = "archs";
1025   else if (!strcmp ("NPS400", cpu))
1026     cpu_name = "nps400";
1027 
1028   arc_select_cpu (cpu_name, MACH_SELECTION_FROM_CPU_DIRECTIVE);
1029 
1030   restore_line_pointer (c);
1031   demand_empty_rest_of_line ();
1032 }
1033 
1034 /* Smartly print an expression.  */
1035 
1036 static void
debug_exp(expressionS * t)1037 debug_exp (expressionS *t)
1038 {
1039   const char *name ATTRIBUTE_UNUSED;
1040   const char *namemd ATTRIBUTE_UNUSED;
1041 
1042   pr_debug ("debug_exp: ");
1043 
1044   switch (t->X_op)
1045     {
1046     default:			name = "unknown";		break;
1047     case O_illegal:		name = "O_illegal";		break;
1048     case O_absent:		name = "O_absent";		break;
1049     case O_constant:		name = "O_constant";		break;
1050     case O_symbol:		name = "O_symbol";		break;
1051     case O_symbol_rva:		name = "O_symbol_rva";		break;
1052     case O_register:		name = "O_register";		break;
1053     case O_big:			name = "O_big";			break;
1054     case O_uminus:		name = "O_uminus";		break;
1055     case O_bit_not:		name = "O_bit_not";		break;
1056     case O_logical_not:		name = "O_logical_not";		break;
1057     case O_multiply:		name = "O_multiply";		break;
1058     case O_divide:		name = "O_divide";		break;
1059     case O_modulus:		name = "O_modulus";		break;
1060     case O_left_shift:		name = "O_left_shift";		break;
1061     case O_right_shift:		name = "O_right_shift";		break;
1062     case O_bit_inclusive_or:	name = "O_bit_inclusive_or";	break;
1063     case O_bit_or_not:		name = "O_bit_or_not";		break;
1064     case O_bit_exclusive_or:	name = "O_bit_exclusive_or";	break;
1065     case O_bit_and:		name = "O_bit_and";		break;
1066     case O_add:			name = "O_add";			break;
1067     case O_subtract:		name = "O_subtract";		break;
1068     case O_eq:			name = "O_eq";			break;
1069     case O_ne:			name = "O_ne";			break;
1070     case O_lt:			name = "O_lt";			break;
1071     case O_le:			name = "O_le";			break;
1072     case O_ge:			name = "O_ge";			break;
1073     case O_gt:			name = "O_gt";			break;
1074     case O_logical_and:		name = "O_logical_and";		break;
1075     case O_logical_or:		name = "O_logical_or";		break;
1076     case O_index:		name = "O_index";		break;
1077     case O_bracket:		name = "O_bracket";		break;
1078     case O_colon:		name = "O_colon";               break;
1079     case O_addrtype:		name = "O_addrtype";            break;
1080     }
1081 
1082   switch (t->X_md)
1083     {
1084     default:			namemd = "unknown";		break;
1085     case O_gotoff:		namemd = "O_gotoff";		break;
1086     case O_gotpc:		namemd = "O_gotpc";		break;
1087     case O_plt:			namemd = "O_plt";		break;
1088     case O_sda:			namemd = "O_sda";		break;
1089     case O_pcl:			namemd = "O_pcl";		break;
1090     case O_tlsgd:		namemd = "O_tlsgd";		break;
1091     case O_tlsie:		namemd = "O_tlsie";		break;
1092     case O_tpoff9:		namemd = "O_tpoff9";		break;
1093     case O_tpoff:		namemd = "O_tpoff";		break;
1094     case O_dtpoff9:		namemd = "O_dtpoff9";		break;
1095     case O_dtpoff:		namemd = "O_dtpoff";		break;
1096     }
1097 
1098   pr_debug ("%s (%s, %s, %d, %s)", name,
1099 	    (t->X_add_symbol) ? S_GET_NAME (t->X_add_symbol) : "--",
1100 	    (t->X_op_symbol) ? S_GET_NAME (t->X_op_symbol) : "--",
1101 	    (int) t->X_add_number,
1102 	    (t->X_md) ? namemd : "--");
1103   pr_debug ("\n");
1104   fflush (stderr);
1105 }
1106 
1107 /* Helper for parsing an argument, used for sorting out the relocation
1108    type.  */
1109 
1110 static void
parse_reloc_symbol(expressionS * resultP)1111 parse_reloc_symbol (expressionS *resultP)
1112 {
1113   char *reloc_name, c, *sym_name;
1114   size_t len;
1115   int i;
1116   const struct arc_reloc_op_tag *r;
1117   expressionS right;
1118   symbolS *base;
1119 
1120   /* A relocation operand has the following form
1121      @identifier@relocation_type.  The identifier is already in
1122      tok!  */
1123   if (resultP->X_op != O_symbol)
1124     {
1125       as_bad (_("No valid label relocation operand"));
1126       resultP->X_op = O_illegal;
1127       return;
1128     }
1129 
1130   /* Parse @relocation_type.  */
1131   input_line_pointer++;
1132   c = get_symbol_name (&reloc_name);
1133   len = input_line_pointer - reloc_name;
1134   if (len == 0)
1135     {
1136       as_bad (_("No relocation operand"));
1137       resultP->X_op = O_illegal;
1138       return;
1139     }
1140 
1141   /* Go through known relocation and try to find a match.  */
1142   r = &arc_reloc_op[0];
1143   for (i = arc_num_reloc_op - 1; i >= 0; i--, r++)
1144     if (len == r->length
1145 	&& memcmp (reloc_name, r->name, len) == 0)
1146       break;
1147   if (i < 0)
1148     {
1149       as_bad (_("Unknown relocation operand: @%s"), reloc_name);
1150       resultP->X_op = O_illegal;
1151       return;
1152     }
1153 
1154   *input_line_pointer = c;
1155   SKIP_WHITESPACE_AFTER_NAME ();
1156   /* Extra check for TLS: base.  */
1157   if (*input_line_pointer == '@')
1158     {
1159       if (resultP->X_op_symbol != NULL
1160 	  || resultP->X_op != O_symbol)
1161 	{
1162 	  as_bad (_("Unable to parse TLS base: %s"),
1163 		  input_line_pointer);
1164 	  resultP->X_op = O_illegal;
1165 	  return;
1166 	}
1167       input_line_pointer++;
1168       c = get_symbol_name (&sym_name);
1169       base = symbol_find_or_make (sym_name);
1170       resultP->X_op = O_subtract;
1171       resultP->X_op_symbol = base;
1172       restore_line_pointer (c);
1173       right.X_add_number = 0;
1174     }
1175 
1176   if ((*input_line_pointer != '+')
1177       && (*input_line_pointer != '-'))
1178     right.X_add_number = 0;
1179   else
1180     {
1181       /* Parse the constant of a complex relocation expression
1182 	 like @identifier@reloc +/- const.  */
1183       if (! r->complex_expr)
1184 	{
1185 	  as_bad (_("@%s is not a complex relocation."), r->name);
1186 	  resultP->X_op = O_illegal;
1187 	  return;
1188 	}
1189       expression (&right);
1190       if (right.X_op != O_constant)
1191 	{
1192 	  as_bad (_("Bad expression: @%s + %s."),
1193 		  r->name, input_line_pointer);
1194 	  resultP->X_op = O_illegal;
1195 	  return;
1196 	}
1197     }
1198 
1199   resultP->X_md = r->op;
1200   resultP->X_add_number = right.X_add_number;
1201 }
1202 
1203 /* Parse the arguments to an opcode.  */
1204 
1205 static int
tokenize_arguments(char * str,expressionS * tok,int ntok)1206 tokenize_arguments (char *str,
1207 		    expressionS *tok,
1208 		    int ntok)
1209 {
1210   char *old_input_line_pointer;
1211   bool saw_comma = false;
1212   bool saw_arg = false;
1213   int brk_lvl = 0;
1214   int num_args = 0;
1215 
1216   memset (tok, 0, sizeof (*tok) * ntok);
1217 
1218   /* Save and restore input_line_pointer around this function.  */
1219   old_input_line_pointer = input_line_pointer;
1220   input_line_pointer = str;
1221 
1222   while (*input_line_pointer)
1223     {
1224       SKIP_WHITESPACE ();
1225       switch (*input_line_pointer)
1226 	{
1227 	case '\0':
1228 	  goto fini;
1229 
1230 	case ',':
1231 	  input_line_pointer++;
1232 	  if (saw_comma || !saw_arg)
1233 	    goto err;
1234 	  saw_comma = true;
1235 	  break;
1236 
1237 	case '}':
1238 	case ']':
1239 	  ++input_line_pointer;
1240 	  --brk_lvl;
1241 	  if (!saw_arg || num_args == ntok)
1242 	    goto err;
1243 	  tok->X_op = O_bracket;
1244 	  ++tok;
1245 	  ++num_args;
1246 	  break;
1247 
1248 	case '{':
1249 	case '[':
1250 	  input_line_pointer++;
1251 	  if (brk_lvl || num_args == ntok)
1252 	    goto err;
1253 	  ++brk_lvl;
1254 	  tok->X_op = O_bracket;
1255 	  ++tok;
1256 	  ++num_args;
1257 	  break;
1258 
1259         case ':':
1260           input_line_pointer++;
1261           if (!saw_arg || num_args == ntok)
1262             goto err;
1263           tok->X_op = O_colon;
1264           saw_arg = false;
1265           ++tok;
1266           ++num_args;
1267           break;
1268 
1269 	case '@':
1270 	  /* We have labels, function names and relocations, all
1271 	     starting with @ symbol.  Sort them out.  */
1272 	  if ((saw_arg && !saw_comma) || num_args == ntok)
1273 	    goto err;
1274 
1275 	  /* Parse @label.  */
1276 	  input_line_pointer++;
1277 	  tok->X_op = O_symbol;
1278 	  tok->X_md = O_absent;
1279 	  expression (tok);
1280 
1281 	  if (*input_line_pointer == '@')
1282 	    parse_reloc_symbol (tok);
1283 
1284 	  debug_exp (tok);
1285 
1286 	  if (tok->X_op == O_illegal
1287               || tok->X_op == O_absent
1288               || num_args == ntok)
1289 	    goto err;
1290 
1291 	  saw_comma = false;
1292 	  saw_arg = true;
1293 	  tok++;
1294 	  num_args++;
1295 	  break;
1296 
1297 	case '%':
1298 	  /* Can be a register.  */
1299 	  ++input_line_pointer;
1300 	  /* Fall through.  */
1301 	default:
1302 
1303 	  if ((saw_arg && !saw_comma) || num_args == ntok)
1304 	    goto err;
1305 
1306 	  tok->X_op = O_absent;
1307 	  tok->X_md = O_absent;
1308 	  expression (tok);
1309 
1310 	  /* Legacy: There are cases when we have
1311 	     identifier@relocation_type, if it is the case parse the
1312 	     relocation type as well.  */
1313 	  if (*input_line_pointer == '@')
1314 	    parse_reloc_symbol (tok);
1315 	  else
1316 	    resolve_register (tok);
1317 
1318 	  debug_exp (tok);
1319 
1320 	  if (tok->X_op == O_illegal
1321               || tok->X_op == O_absent
1322               || num_args == ntok)
1323 	    goto err;
1324 
1325 	  saw_comma = false;
1326 	  saw_arg = true;
1327 	  tok++;
1328 	  num_args++;
1329 	  break;
1330 	}
1331     }
1332 
1333  fini:
1334   if (saw_comma || brk_lvl)
1335     goto err;
1336   input_line_pointer = old_input_line_pointer;
1337 
1338   return num_args;
1339 
1340  err:
1341   if (brk_lvl)
1342     as_bad (_("Brackets in operand field incorrect"));
1343   else if (saw_comma)
1344     as_bad (_("extra comma"));
1345   else if (!saw_arg)
1346     as_bad (_("missing argument"));
1347   else
1348     as_bad (_("missing comma or colon"));
1349   input_line_pointer = old_input_line_pointer;
1350   return -1;
1351 }
1352 
1353 /* Parse the flags to a structure.  */
1354 
1355 static int
tokenize_flags(const char * str,struct arc_flags flags[],int nflg)1356 tokenize_flags (const char *str,
1357 		struct arc_flags flags[],
1358 		int nflg)
1359 {
1360   char *old_input_line_pointer;
1361   bool saw_flg = false;
1362   bool saw_dot = false;
1363   int num_flags  = 0;
1364   size_t flgnamelen;
1365 
1366   memset (flags, 0, sizeof (*flags) * nflg);
1367 
1368   /* Save and restore input_line_pointer around this function.  */
1369   old_input_line_pointer = input_line_pointer;
1370   input_line_pointer = (char *) str;
1371 
1372   while (*input_line_pointer)
1373     {
1374       switch (*input_line_pointer)
1375 	{
1376 	case ' ':
1377 	case '\0':
1378 	  goto fini;
1379 
1380 	case '.':
1381 	  input_line_pointer++;
1382 	  if (saw_dot)
1383 	    goto err;
1384 	  saw_dot = true;
1385 	  saw_flg = false;
1386 	  break;
1387 
1388 	default:
1389 	  if (saw_flg && !saw_dot)
1390 	    goto err;
1391 
1392 	  if (num_flags >= nflg)
1393 	    goto err;
1394 
1395 	  flgnamelen = strspn (input_line_pointer,
1396 			       "abcdefghijklmnopqrstuvwxyz0123456789");
1397 	  if (flgnamelen > MAX_FLAG_NAME_LENGTH)
1398 	    goto err;
1399 
1400 	  memcpy (flags->name, input_line_pointer, flgnamelen);
1401 
1402 	  input_line_pointer += flgnamelen;
1403 	  flags++;
1404 	  saw_dot = false;
1405 	  saw_flg = true;
1406 	  num_flags++;
1407 	  break;
1408 	}
1409     }
1410 
1411  fini:
1412   input_line_pointer = old_input_line_pointer;
1413   return num_flags;
1414 
1415  err:
1416   if (saw_dot)
1417     as_bad (_("extra dot"));
1418   else if (!saw_flg)
1419     as_bad (_("unrecognized flag"));
1420   else
1421     as_bad (_("failed to parse flags"));
1422   input_line_pointer = old_input_line_pointer;
1423   return -1;
1424 }
1425 
1426 /* Apply the fixups in order.  */
1427 
1428 static void
apply_fixups(struct arc_insn * insn,fragS * fragP,int fix)1429 apply_fixups (struct arc_insn *insn, fragS *fragP, int fix)
1430 {
1431   int i;
1432 
1433   for (i = 0; i < insn->nfixups; i++)
1434     {
1435       struct arc_fixup *fixup = &insn->fixups[i];
1436       int size, pcrel, offset = 0;
1437 
1438       /* FIXME! the reloc size is wrong in the BFD file.
1439 	 When it is fixed please delete me.  */
1440       size = ((insn->len == 2) && !fixup->islong) ? 2 : 4;
1441 
1442       if (fixup->islong)
1443 	offset = insn->len;
1444 
1445       /* Some fixups are only used internally, thus no howto.  */
1446       if ((int) fixup->reloc == 0)
1447 	as_fatal (_("Unhandled reloc type"));
1448 
1449       if ((int) fixup->reloc < 0)
1450 	{
1451 	  /* FIXME! the reloc size is wrong in the BFD file.
1452 	     When it is fixed please enable me.
1453 	     size = ((insn->len == 2 && !fixup->islong) ? 2 : 4; */
1454 	  pcrel = fixup->pcrel;
1455 	}
1456       else
1457 	{
1458 	  reloc_howto_type *reloc_howto =
1459 	    bfd_reloc_type_lookup (stdoutput,
1460 				   (bfd_reloc_code_real_type) fixup->reloc);
1461 	  gas_assert (reloc_howto);
1462 
1463 	  /* FIXME! the reloc size is wrong in the BFD file.
1464 	     When it is fixed please enable me.
1465 	     size = bfd_get_reloc_size (reloc_howto); */
1466 	  pcrel = reloc_howto->pc_relative;
1467 	}
1468 
1469       pr_debug ("%s:%d: apply_fixups: new %s fixup (PCrel:%s) of size %d @ \
1470 offset %d + %d\n",
1471 		fragP->fr_file, fragP->fr_line,
1472 		(fixup->reloc < 0) ? "Internal" :
1473 		bfd_get_reloc_code_name (fixup->reloc),
1474 		pcrel ? "Y" : "N",
1475 		size, fix, offset);
1476       fix_new_exp (fragP, fix + offset,
1477 		   size, &fixup->exp, pcrel, fixup->reloc);
1478 
1479       /* Check for ZOLs, and update symbol info if any.  */
1480       if (LP_INSN (insn->insn))
1481 	{
1482 	  gas_assert (fixup->exp.X_add_symbol);
1483 	  ARC_SET_FLAG (fixup->exp.X_add_symbol, ARC_FLAG_ZOL);
1484 	}
1485     }
1486 }
1487 
1488 /* Actually output an instruction with its fixup.  */
1489 
1490 static void
emit_insn0(struct arc_insn * insn,char * where,bool relax)1491 emit_insn0 (struct arc_insn *insn, char *where, bool relax)
1492 {
1493   char *f = where;
1494   size_t total_len;
1495 
1496   pr_debug ("Emit insn : 0x%llx\n", insn->insn);
1497   pr_debug ("\tLength  : %d\n", insn->len);
1498   pr_debug ("\tLong imm: 0x%lx\n", insn->limm);
1499 
1500   /* Write out the instruction.  */
1501   total_len = insn->len + (insn->has_limm ? 4 : 0);
1502   if (!relax)
1503     f = frag_more (total_len);
1504 
1505   md_number_to_chars_midend(f, insn->insn, insn->len);
1506 
1507   if (insn->has_limm)
1508     md_number_to_chars_midend (f + insn->len, insn->limm, 4);
1509   dwarf2_emit_insn (total_len);
1510 
1511   if (!relax)
1512     apply_fixups (insn, frag_now, (f - frag_now->fr_literal));
1513 }
1514 
1515 static void
emit_insn1(struct arc_insn * insn)1516 emit_insn1 (struct arc_insn *insn)
1517 {
1518   /* How frag_var's args are currently configured:
1519      - rs_machine_dependent, to dictate it's a relaxation frag.
1520      - FRAG_MAX_GROWTH, maximum size of instruction
1521      - 0, variable size that might grow...unused by generic relaxation.
1522      - frag_now->fr_subtype, fr_subtype starting value, set previously.
1523      - s, opand expression.
1524      - 0, offset but it's unused.
1525      - 0, opcode but it's unused.  */
1526   symbolS *s = make_expr_symbol (&insn->fixups[0].exp);
1527   frag_now->tc_frag_data.pcrel = insn->fixups[0].pcrel;
1528 
1529   if (frag_room () < FRAG_MAX_GROWTH)
1530     {
1531       /* Handle differently when frag literal memory is exhausted.
1532 	 This is used because when there's not enough memory left in
1533 	 the current frag, a new frag is created and the information
1534 	 we put into frag_now->tc_frag_data is disregarded.  */
1535 
1536       struct arc_relax_type relax_info_copy;
1537       relax_substateT subtype = frag_now->fr_subtype;
1538 
1539       memcpy (&relax_info_copy, &frag_now->tc_frag_data,
1540 	      sizeof (struct arc_relax_type));
1541 
1542       frag_wane (frag_now);
1543       frag_grow (FRAG_MAX_GROWTH);
1544 
1545       memcpy (&frag_now->tc_frag_data, &relax_info_copy,
1546 	      sizeof (struct arc_relax_type));
1547 
1548       frag_var (rs_machine_dependent, FRAG_MAX_GROWTH, 0,
1549 		subtype, s, 0, 0);
1550     }
1551   else
1552     frag_var (rs_machine_dependent, FRAG_MAX_GROWTH, 0,
1553 	      frag_now->fr_subtype, s, 0, 0);
1554 }
1555 
1556 static void
emit_insn(struct arc_insn * insn)1557 emit_insn (struct arc_insn *insn)
1558 {
1559   if (insn->relax)
1560     emit_insn1 (insn);
1561   else
1562     emit_insn0 (insn, NULL, false);
1563 }
1564 
1565 /* Check whether a symbol involves a register.  */
1566 
1567 static bool
contains_register(symbolS * sym)1568 contains_register (symbolS *sym)
1569 {
1570   if (sym)
1571     {
1572       expressionS *ex = symbol_get_value_expression (sym);
1573 
1574       return ((O_register == ex->X_op)
1575 	      && !contains_register (ex->X_add_symbol)
1576 	      && !contains_register (ex->X_op_symbol));
1577     }
1578 
1579   return false;
1580 }
1581 
1582 /* Returns the register number within a symbol.  */
1583 
1584 static int
get_register(symbolS * sym)1585 get_register (symbolS *sym)
1586 {
1587   if (!contains_register (sym))
1588     return -1;
1589 
1590   expressionS *ex = symbol_get_value_expression (sym);
1591   return regno (ex->X_add_number);
1592 }
1593 
1594 /* Return true if a RELOC is generic.  A generic reloc is PC-rel of a
1595    simple ME relocation (e.g. RELOC_ARC_32_ME, BFD_RELOC_ARC_PC32.  */
1596 
1597 static bool
generic_reloc_p(extended_bfd_reloc_code_real_type reloc)1598 generic_reloc_p (extended_bfd_reloc_code_real_type reloc)
1599 {
1600   if (!reloc)
1601     return false;
1602 
1603   switch (reloc)
1604     {
1605     case BFD_RELOC_ARC_SDA_LDST:
1606     case BFD_RELOC_ARC_SDA_LDST1:
1607     case BFD_RELOC_ARC_SDA_LDST2:
1608     case BFD_RELOC_ARC_SDA16_LD:
1609     case BFD_RELOC_ARC_SDA16_LD1:
1610     case BFD_RELOC_ARC_SDA16_LD2:
1611     case BFD_RELOC_ARC_SDA16_ST2:
1612     case BFD_RELOC_ARC_SDA32_ME:
1613       return false;
1614     default:
1615       return true;
1616     }
1617 }
1618 
1619 /* Allocates a tok entry.  */
1620 
1621 static int
allocate_tok(expressionS * tok,int ntok,int cidx)1622 allocate_tok (expressionS *tok, int ntok, int cidx)
1623 {
1624   if (ntok > MAX_INSN_ARGS - 2)
1625     return 0; /* No space left.  */
1626 
1627   if (cidx > ntok)
1628     return 0; /* Incorrect args.  */
1629 
1630   memcpy (&tok[ntok+1], &tok[ntok], sizeof (*tok));
1631 
1632   if (cidx == ntok)
1633     return 1; /* Success.  */
1634   return allocate_tok (tok, ntok - 1, cidx);
1635 }
1636 
1637 /* Check if an particular ARC feature is enabled.  */
1638 
1639 static bool
check_cpu_feature(insn_subclass_t sc)1640 check_cpu_feature (insn_subclass_t sc)
1641 {
1642   if (is_code_density_p (sc) && !(selected_cpu.features & CD))
1643     return false;
1644 
1645   if (is_spfp_p (sc) && !(selected_cpu.features & SPX))
1646     return false;
1647 
1648   if (is_dpfp_p (sc) && !(selected_cpu.features & DPX))
1649     return false;
1650 
1651   if (is_fpuda_p (sc) && !(selected_cpu.features & DPA))
1652     return false;
1653 
1654   if (is_nps400_p (sc) && !(selected_cpu.features & NPS400))
1655     return false;
1656 
1657   return true;
1658 }
1659 
1660 /* Parse the flags described by FIRST_PFLAG and NFLGS against the flag
1661    operands in OPCODE.  Stores the matching OPCODES into the FIRST_PFLAG
1662    array and returns TRUE if the flag operands all match, otherwise,
1663    returns FALSE, in which case the FIRST_PFLAG array may have been
1664    modified.  */
1665 
1666 static bool
parse_opcode_flags(const struct arc_opcode * opcode,int nflgs,struct arc_flags * first_pflag)1667 parse_opcode_flags (const struct arc_opcode *opcode,
1668                     int nflgs,
1669                     struct arc_flags *first_pflag)
1670 {
1671   int lnflg, i;
1672   const unsigned char *flgidx;
1673 
1674   lnflg = nflgs;
1675   for (i = 0; i < nflgs; i++)
1676     first_pflag[i].flgp = NULL;
1677 
1678   /* Check the flags.  Iterate over the valid flag classes.  */
1679   for (flgidx = opcode->flags; *flgidx; ++flgidx)
1680     {
1681       /* Get a valid flag class.  */
1682       const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
1683       const unsigned *flgopridx;
1684       int cl_matches = 0;
1685       struct arc_flags *pflag = NULL;
1686 
1687       /* Check if opcode has implicit flag classes.  */
1688       if (cl_flags->flag_class & F_CLASS_IMPLICIT)
1689 	continue;
1690 
1691       /* Check for extension conditional codes.  */
1692       if (ext_condcode.arc_ext_condcode
1693           && cl_flags->flag_class & F_CLASS_EXTEND)
1694         {
1695           struct arc_flag_operand *pf = ext_condcode.arc_ext_condcode;
1696           while (pf->name)
1697             {
1698               pflag = first_pflag;
1699               for (i = 0; i < nflgs; i++, pflag++)
1700                 {
1701                   if (!strcmp (pf->name, pflag->name))
1702                     {
1703                       if (pflag->flgp != NULL)
1704                         return false;
1705                       /* Found it.  */
1706                       cl_matches++;
1707                       pflag->flgp = pf;
1708                       lnflg--;
1709                       break;
1710                     }
1711                 }
1712               pf++;
1713             }
1714         }
1715 
1716       for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
1717         {
1718           const struct arc_flag_operand *flg_operand;
1719 
1720           pflag = first_pflag;
1721           flg_operand = &arc_flag_operands[*flgopridx];
1722           for (i = 0; i < nflgs; i++, pflag++)
1723             {
1724               /* Match against the parsed flags.  */
1725               if (!strcmp (flg_operand->name, pflag->name))
1726                 {
1727                   if (pflag->flgp != NULL)
1728                     return false;
1729                   cl_matches++;
1730                   pflag->flgp = flg_operand;
1731                   lnflg--;
1732                   break; /* goto next flag class and parsed flag.  */
1733                 }
1734             }
1735         }
1736 
1737       if ((cl_flags->flag_class & F_CLASS_REQUIRED) && cl_matches == 0)
1738         return false;
1739       if ((cl_flags->flag_class & F_CLASS_OPTIONAL) && cl_matches > 1)
1740         return false;
1741     }
1742 
1743   /* Did I check all the parsed flags?  */
1744   return lnflg == 0;
1745 }
1746 
1747 
1748 /* Search forward through all variants of an opcode looking for a
1749    syntax match.  */
1750 
1751 static const struct arc_opcode *
find_opcode_match(const struct arc_opcode_hash_entry * entry,expressionS * tok,int * pntok,struct arc_flags * first_pflag,int nflgs,int * pcpumatch,const char ** errmsg)1752 find_opcode_match (const struct arc_opcode_hash_entry *entry,
1753 		   expressionS *tok,
1754 		   int *pntok,
1755 		   struct arc_flags *first_pflag,
1756 		   int nflgs,
1757 		   int *pcpumatch,
1758 		   const char **errmsg)
1759 {
1760   const struct arc_opcode *opcode;
1761   struct arc_opcode_hash_entry_iterator iter;
1762   int ntok = *pntok;
1763   int got_cpu_match = 0;
1764   expressionS bktok[MAX_INSN_ARGS];
1765   int bkntok, maxerridx = 0;
1766   expressionS emptyE;
1767   const char *tmpmsg = NULL;
1768 
1769   arc_opcode_hash_entry_iterator_init (&iter);
1770   memset (&emptyE, 0, sizeof (emptyE));
1771   memcpy (bktok, tok, MAX_INSN_ARGS * sizeof (*tok));
1772   bkntok = ntok;
1773 
1774   for (opcode = arc_opcode_hash_entry_iterator_next (entry, &iter);
1775        opcode != NULL;
1776        opcode = arc_opcode_hash_entry_iterator_next (entry, &iter))
1777     {
1778       const unsigned char *opidx;
1779       int tokidx = 0;
1780       const expressionS *t = &emptyE;
1781 
1782       pr_debug ("%s:%d: find_opcode_match: trying opcode 0x%08llX ",
1783 		frag_now->fr_file, frag_now->fr_line, opcode->opcode);
1784 
1785       /* Don't match opcodes that don't exist on this
1786 	 architecture.  */
1787       if (!(opcode->cpu & selected_cpu.flags))
1788 	goto match_failed;
1789 
1790       if (!check_cpu_feature (opcode->subclass))
1791 	goto match_failed;
1792 
1793       got_cpu_match = 1;
1794       pr_debug ("cpu ");
1795 
1796       /* Check the operands.  */
1797       for (opidx = opcode->operands; *opidx; ++opidx)
1798 	{
1799 	  const struct arc_operand *operand = &arc_operands[*opidx];
1800 
1801 	  /* Only take input from real operands.  */
1802 	  if (ARC_OPERAND_IS_FAKE (operand))
1803 	    continue;
1804 
1805 	  /* When we expect input, make sure we have it.  */
1806 	  if (tokidx >= ntok)
1807 	    goto match_failed;
1808 
1809 	  /* Match operand type with expression type.  */
1810 	  switch (operand->flags & ARC_OPERAND_TYPECHECK_MASK)
1811 	    {
1812             case ARC_OPERAND_ADDRTYPE:
1813 	      {
1814 		tmpmsg = NULL;
1815 
1816 		/* Check to be an address type.  */
1817 		if (tok[tokidx].X_op != O_addrtype)
1818 		  goto match_failed;
1819 
1820 		/* All address type operands need to have an insert
1821 		   method in order to check that we have the correct
1822 		   address type.  */
1823 		gas_assert (operand->insert != NULL);
1824 		(*operand->insert) (0, tok[tokidx].X_add_number,
1825 				    &tmpmsg);
1826 		if (tmpmsg != NULL)
1827 		  goto match_failed;
1828 	      }
1829               break;
1830 
1831 	    case ARC_OPERAND_IR:
1832 	      /* Check to be a register.  */
1833 	      if ((tok[tokidx].X_op != O_register
1834 		   || !is_ir_num (tok[tokidx].X_add_number))
1835 		  && !(operand->flags & ARC_OPERAND_IGNORE))
1836 		goto match_failed;
1837 
1838 	      /* If expect duplicate, make sure it is duplicate.  */
1839 	      if (operand->flags & ARC_OPERAND_DUPLICATE)
1840 		{
1841 		  /* Check for duplicate.  */
1842 		  if (t->X_op != O_register
1843 		      || !is_ir_num (t->X_add_number)
1844 		      || (regno (t->X_add_number) !=
1845 			  regno (tok[tokidx].X_add_number)))
1846 		    goto match_failed;
1847 		}
1848 
1849 	      /* Special handling?  */
1850 	      if (operand->insert)
1851 		{
1852 		  tmpmsg = NULL;
1853 		  (*operand->insert)(0,
1854 				     regno (tok[tokidx].X_add_number),
1855 				     &tmpmsg);
1856 		  if (tmpmsg)
1857 		    {
1858 		      if (operand->flags & ARC_OPERAND_IGNORE)
1859 			{
1860 			  /* Missing argument, create one.  */
1861 			  if (!allocate_tok (tok, ntok - 1, tokidx))
1862 			    goto match_failed;
1863 
1864 			  tok[tokidx].X_op = O_absent;
1865 			  ++ntok;
1866 			}
1867 		      else
1868 			goto match_failed;
1869 		    }
1870 		}
1871 
1872 	      t = &tok[tokidx];
1873 	      break;
1874 
1875 	    case ARC_OPERAND_BRAKET:
1876 	      /* Check if bracket is also in opcode table as
1877 		 operand.  */
1878 	      if (tok[tokidx].X_op != O_bracket)
1879 		goto match_failed;
1880 	      break;
1881 
1882             case ARC_OPERAND_COLON:
1883               /* Check if colon is also in opcode table as operand.  */
1884               if (tok[tokidx].X_op != O_colon)
1885                 goto match_failed;
1886               break;
1887 
1888 	    case ARC_OPERAND_LIMM:
1889 	    case ARC_OPERAND_SIGNED:
1890 	    case ARC_OPERAND_UNSIGNED:
1891 	      switch (tok[tokidx].X_op)
1892 		{
1893 		case O_illegal:
1894 		case O_absent:
1895 		case O_register:
1896 		  goto match_failed;
1897 
1898 		case O_bracket:
1899 		  /* Got an (too) early bracket, check if it is an
1900 		     ignored operand.  N.B. This procedure works only
1901 		     when bracket is the last operand!  */
1902 		  if (!(operand->flags & ARC_OPERAND_IGNORE))
1903 		    goto match_failed;
1904 		  /* Insert the missing operand.  */
1905 		  if (!allocate_tok (tok, ntok - 1, tokidx))
1906 		    goto match_failed;
1907 
1908 		  tok[tokidx].X_op = O_absent;
1909 		  ++ntok;
1910 		  break;
1911 
1912 		case O_symbol:
1913 		  {
1914 		    const char *p;
1915 		    char *tmpp, *pp;
1916 		    const struct arc_aux_reg *auxr;
1917 
1918 		    if (opcode->insn_class != AUXREG)
1919 		      goto de_fault;
1920 		    p = S_GET_NAME (tok[tokidx].X_add_symbol);
1921 
1922 		    /* For compatibility reasons, an aux register can
1923 		       be spelled with upper or lower case
1924 		       letters.  */
1925 		    tmpp = strdup (p);
1926 		    for (pp = tmpp; *pp; ++pp) *pp = TOLOWER (*pp);
1927 
1928 		    auxr = str_hash_find (arc_aux_hash, tmpp);
1929 		    if (auxr)
1930 		      {
1931 			/* We modify the token array here, safe in the
1932 			   knowledge, that if this was the wrong
1933 			   choice then the original contents will be
1934 			   restored from BKTOK.  */
1935 			tok[tokidx].X_op = O_constant;
1936 			tok[tokidx].X_add_number = auxr->address;
1937 			ARC_SET_FLAG (tok[tokidx].X_add_symbol, ARC_FLAG_AUX);
1938 		      }
1939 		    free (tmpp);
1940 
1941 		    if (tok[tokidx].X_op != O_constant)
1942 		      goto de_fault;
1943 		  }
1944 		  /* Fall through.  */
1945 		case O_constant:
1946 		  /* Check the range.  */
1947 		  if (operand->bits != 32
1948 		      && !(operand->flags & ARC_OPERAND_NCHK))
1949 		    {
1950 		      offsetT min, max, val;
1951 		      val = tok[tokidx].X_add_number;
1952 
1953 		      if (operand->flags & ARC_OPERAND_SIGNED)
1954 			{
1955 			  max = (1 << (operand->bits - 1)) - 1;
1956 			  min = -(1 << (operand->bits - 1));
1957 			}
1958 		      else
1959 			{
1960 			  max = (1 << operand->bits) - 1;
1961 			  min = 0;
1962 			}
1963 
1964 		      if (val < min || val > max)
1965 			{
1966 			  tmpmsg = _("immediate is out of bounds");
1967 			  goto match_failed;
1968 			}
1969 
1970 		      /* Check alignments.  */
1971 		      if ((operand->flags & ARC_OPERAND_ALIGNED32)
1972 			  && (val & 0x03))
1973 			{
1974 			  tmpmsg = _("immediate is not 32bit aligned");
1975 			  goto match_failed;
1976 			}
1977 
1978 		      if ((operand->flags & ARC_OPERAND_ALIGNED16)
1979 			  && (val & 0x01))
1980 			{
1981 			  tmpmsg = _("immediate is not 16bit aligned");
1982 			  goto match_failed;
1983 			}
1984 		    }
1985 		  else if (operand->flags & ARC_OPERAND_NCHK)
1986 		    {
1987 		      if (operand->insert)
1988 			{
1989 			  tmpmsg = NULL;
1990 			  (*operand->insert)(0,
1991 					     tok[tokidx].X_add_number,
1992 					     &tmpmsg);
1993 			  if (tmpmsg)
1994 			    goto match_failed;
1995 			}
1996 		      else if (!(operand->flags & ARC_OPERAND_IGNORE))
1997 			goto match_failed;
1998 		    }
1999 		  break;
2000 
2001 		case O_subtract:
2002 		  /* Check if it is register range.  */
2003 		  if ((tok[tokidx].X_add_number == 0)
2004 		      && contains_register (tok[tokidx].X_add_symbol)
2005 		      && contains_register (tok[tokidx].X_op_symbol))
2006 		    {
2007 		      int regs;
2008 
2009 		      regs = get_register (tok[tokidx].X_add_symbol);
2010 		      regs <<= 16;
2011 		      regs |= get_register (tok[tokidx].X_op_symbol);
2012 		      if (operand->insert)
2013 			{
2014 			  tmpmsg = NULL;
2015 			  (*operand->insert)(0,
2016 					     regs,
2017 					     &tmpmsg);
2018 			  if (tmpmsg)
2019 			    goto match_failed;
2020 			}
2021 		      else
2022 			goto match_failed;
2023 		      break;
2024 		    }
2025 		  /* Fall through.  */
2026 		default:
2027 		de_fault:
2028 		  if (operand->default_reloc == 0)
2029 		    goto match_failed; /* The operand needs relocation.  */
2030 
2031 		  /* Relocs requiring long immediate.  FIXME! make it
2032 		     generic and move it to a function.  */
2033 		  switch (tok[tokidx].X_md)
2034 		    {
2035 		    case O_gotoff:
2036 		    case O_gotpc:
2037 		    case O_pcl:
2038 		    case O_tpoff:
2039 		    case O_dtpoff:
2040 		    case O_tlsgd:
2041 		    case O_tlsie:
2042 		      if (!(operand->flags & ARC_OPERAND_LIMM))
2043 			goto match_failed;
2044 		      /* Fall through.  */
2045 		    case O_absent:
2046 		      if (!generic_reloc_p (operand->default_reloc))
2047 			goto match_failed;
2048 		      break;
2049 		    default:
2050 		      break;
2051 		    }
2052 		  break;
2053 		}
2054 	      /* If expect duplicate, make sure it is duplicate.  */
2055 	      if (operand->flags & ARC_OPERAND_DUPLICATE)
2056 		{
2057 		  if (t->X_op == O_illegal
2058 		      || t->X_op == O_absent
2059 		      || t->X_op == O_register
2060 		      || (t->X_add_number != tok[tokidx].X_add_number))
2061 		    {
2062 		      tmpmsg = _("operand is not duplicate of the "
2063 				 "previous one");
2064 		      goto match_failed;
2065 		    }
2066 		}
2067 	      t = &tok[tokidx];
2068 	      break;
2069 
2070 	    default:
2071 	      /* Everything else should have been fake.  */
2072 	      abort ();
2073 	    }
2074 
2075 	  ++tokidx;
2076 	}
2077       pr_debug ("opr ");
2078 
2079       /* Setup ready for flag parsing.  */
2080       if (!parse_opcode_flags (opcode, nflgs, first_pflag))
2081 	{
2082 	  tmpmsg = _("flag mismatch");
2083 	  goto match_failed;
2084 	}
2085 
2086       pr_debug ("flg");
2087       /* Possible match -- did we use all of our input?  */
2088       if (tokidx == ntok)
2089 	{
2090 	  *pntok = ntok;
2091 	  pr_debug ("\n");
2092 	  return opcode;
2093 	}
2094       tmpmsg = _("too many arguments");
2095 
2096     match_failed:;
2097       pr_debug ("\n");
2098       /* Restore the original parameters.  */
2099       memcpy (tok, bktok, MAX_INSN_ARGS * sizeof (*tok));
2100       ntok = bkntok;
2101       if (tokidx >= maxerridx
2102 	  && tmpmsg)
2103 	{
2104 	  maxerridx = tokidx;
2105 	  *errmsg = tmpmsg;
2106 	}
2107     }
2108 
2109   if (*pcpumatch)
2110     *pcpumatch = got_cpu_match;
2111 
2112   return NULL;
2113 }
2114 
2115 /* Swap operand tokens.  */
2116 
2117 static void
swap_operand(expressionS * operand_array,unsigned source,unsigned destination)2118 swap_operand (expressionS *operand_array,
2119 	      unsigned source,
2120 	      unsigned destination)
2121 {
2122   expressionS cpy_operand;
2123   expressionS *src_operand;
2124   expressionS *dst_operand;
2125   size_t size;
2126 
2127   if (source == destination)
2128     return;
2129 
2130   src_operand = &operand_array[source];
2131   dst_operand = &operand_array[destination];
2132   size = sizeof (expressionS);
2133 
2134   /* Make copy of operand to swap with and swap.  */
2135   memcpy (&cpy_operand, dst_operand, size);
2136   memcpy (dst_operand, src_operand, size);
2137   memcpy (src_operand, &cpy_operand, size);
2138 }
2139 
2140 /* Check if *op matches *tok type.
2141    Returns FALSE if they don't match, TRUE if they match.  */
2142 
2143 static bool
pseudo_operand_match(const expressionS * tok,const struct arc_operand_operation * op)2144 pseudo_operand_match (const expressionS *tok,
2145 		      const struct arc_operand_operation *op)
2146 {
2147   offsetT min, max, val;
2148   bool ret;
2149   const struct arc_operand *operand_real = &arc_operands[op->operand_idx];
2150 
2151   ret = false;
2152   switch (tok->X_op)
2153     {
2154     case O_constant:
2155       if (operand_real->bits == 32 && (operand_real->flags & ARC_OPERAND_LIMM))
2156 	ret = 1;
2157       else if (!(operand_real->flags & ARC_OPERAND_IR))
2158 	{
2159 	  val = tok->X_add_number + op->count;
2160 	  if (operand_real->flags & ARC_OPERAND_SIGNED)
2161 	    {
2162 	      max = (1 << (operand_real->bits - 1)) - 1;
2163 	      min = -(1 << (operand_real->bits - 1));
2164 	    }
2165 	  else
2166 	    {
2167 	      max = (1 << operand_real->bits) - 1;
2168 	      min = 0;
2169 	    }
2170 	  if (min <= val && val <= max)
2171 	    ret = true;
2172 	}
2173       break;
2174 
2175     case O_symbol:
2176       /* Handle all symbols as long immediates or signed 9.  */
2177       if (operand_real->flags & ARC_OPERAND_LIMM
2178 	  || ((operand_real->flags & ARC_OPERAND_SIGNED)
2179 	      && operand_real->bits == 9))
2180 	ret = true;
2181       break;
2182 
2183     case O_register:
2184       if (operand_real->flags & ARC_OPERAND_IR)
2185 	ret = true;
2186       break;
2187 
2188     case O_bracket:
2189       if (operand_real->flags & ARC_OPERAND_BRAKET)
2190 	ret = true;
2191       break;
2192 
2193     default:
2194       /* Unknown.  */
2195       break;
2196     }
2197   return ret;
2198 }
2199 
2200 /* Find pseudo instruction in array.  */
2201 
2202 static const struct arc_pseudo_insn *
find_pseudo_insn(const char * opname,int ntok,const expressionS * tok)2203 find_pseudo_insn (const char *opname,
2204 		  int ntok,
2205 		  const expressionS *tok)
2206 {
2207   const struct arc_pseudo_insn *pseudo_insn = NULL;
2208   const struct arc_operand_operation *op;
2209   unsigned int i;
2210   int j;
2211 
2212   for (i = 0; i < arc_num_pseudo_insn; ++i)
2213     {
2214       pseudo_insn = &arc_pseudo_insns[i];
2215       if (strcmp (pseudo_insn->mnemonic_p, opname) == 0)
2216 	{
2217 	  op = pseudo_insn->operand;
2218 	  for (j = 0; j < ntok; ++j)
2219 	    if (!pseudo_operand_match (&tok[j], &op[j]))
2220 	      break;
2221 
2222 	  /* Found the right instruction.  */
2223 	  if (j == ntok)
2224 	    return pseudo_insn;
2225 	}
2226     }
2227   return NULL;
2228 }
2229 
2230 /* Assumes the expressionS *tok is of sufficient size.  */
2231 
2232 static const struct arc_opcode_hash_entry *
find_special_case_pseudo(const char * opname,int * ntok,expressionS * tok,int * nflgs,struct arc_flags * pflags)2233 find_special_case_pseudo (const char *opname,
2234 			  int *ntok,
2235 			  expressionS *tok,
2236 			  int *nflgs,
2237 			  struct arc_flags *pflags)
2238 {
2239   const struct arc_pseudo_insn *pseudo_insn = NULL;
2240   const struct arc_operand_operation *operand_pseudo;
2241   const struct arc_operand *operand_real;
2242   unsigned i;
2243   char construct_operand[MAX_CONSTR_STR];
2244 
2245   /* Find whether opname is in pseudo instruction array.  */
2246   pseudo_insn = find_pseudo_insn (opname, *ntok, tok);
2247 
2248   if (pseudo_insn == NULL)
2249     return NULL;
2250 
2251   /* Handle flag, Limited to one flag at the moment.  */
2252   if (pseudo_insn->flag_r != NULL)
2253     *nflgs += tokenize_flags (pseudo_insn->flag_r, &pflags[*nflgs],
2254 			      MAX_INSN_FLGS - *nflgs);
2255 
2256   /* Handle operand operations.  */
2257   for (i = 0; i < pseudo_insn->operand_cnt; ++i)
2258     {
2259       operand_pseudo = &pseudo_insn->operand[i];
2260       operand_real = &arc_operands[operand_pseudo->operand_idx];
2261 
2262       if (operand_real->flags & ARC_OPERAND_BRAKET
2263 	  && !operand_pseudo->needs_insert)
2264 	continue;
2265 
2266       /* Has to be inserted (i.e. this token does not exist yet).  */
2267       if (operand_pseudo->needs_insert)
2268 	{
2269 	  if (operand_real->flags & ARC_OPERAND_BRAKET)
2270 	    {
2271 	      tok[i].X_op = O_bracket;
2272 	      ++(*ntok);
2273 	      continue;
2274 	    }
2275 
2276 	  /* Check if operand is a register or constant and handle it
2277 	     by type.  */
2278 	  if (operand_real->flags & ARC_OPERAND_IR)
2279 	    snprintf (construct_operand, MAX_CONSTR_STR, "r%d",
2280 		      operand_pseudo->count);
2281 	  else
2282 	    snprintf (construct_operand, MAX_CONSTR_STR, "%d",
2283 		      operand_pseudo->count);
2284 
2285 	  tokenize_arguments (construct_operand, &tok[i], 1);
2286 	  ++(*ntok);
2287 	}
2288 
2289       else if (operand_pseudo->count)
2290 	{
2291 	  /* Operand number has to be adjusted accordingly (by operand
2292 	     type).  */
2293 	  switch (tok[i].X_op)
2294 	    {
2295 	    case O_constant:
2296 	      tok[i].X_add_number += operand_pseudo->count;
2297 	      break;
2298 
2299 	    case O_symbol:
2300 	      break;
2301 
2302 	    default:
2303 	      /* Ignored.  */
2304 	      break;
2305 	    }
2306 	}
2307     }
2308 
2309   /* Swap operands if necessary.  Only supports one swap at the
2310      moment.  */
2311   for (i = 0; i < pseudo_insn->operand_cnt; ++i)
2312     {
2313       operand_pseudo = &pseudo_insn->operand[i];
2314 
2315       if (operand_pseudo->swap_operand_idx == i)
2316 	continue;
2317 
2318       swap_operand (tok, i, operand_pseudo->swap_operand_idx);
2319 
2320       /* Prevent a swap back later by breaking out.  */
2321       break;
2322     }
2323 
2324   return arc_find_opcode (pseudo_insn->mnemonic_r);
2325 }
2326 
2327 static const struct arc_opcode_hash_entry *
find_special_case_flag(const char * opname,int * nflgs,struct arc_flags * pflags)2328 find_special_case_flag (const char *opname,
2329 			int *nflgs,
2330 			struct arc_flags *pflags)
2331 {
2332   unsigned int i;
2333   const char *flagnm;
2334   unsigned flag_idx, flag_arr_idx;
2335   size_t flaglen, oplen;
2336   const struct arc_flag_special *arc_flag_special_opcode;
2337   const struct arc_opcode_hash_entry *entry;
2338 
2339   /* Search for special case instruction.  */
2340   for (i = 0; i < arc_num_flag_special; i++)
2341     {
2342       arc_flag_special_opcode = &arc_flag_special_cases[i];
2343       oplen = strlen (arc_flag_special_opcode->name);
2344 
2345       if (strncmp (opname, arc_flag_special_opcode->name, oplen) != 0)
2346 	continue;
2347 
2348       /* Found a potential special case instruction, now test for
2349 	 flags.  */
2350       for (flag_arr_idx = 0;; ++flag_arr_idx)
2351 	{
2352 	  flag_idx = arc_flag_special_opcode->flags[flag_arr_idx];
2353 	  if (flag_idx == 0)
2354 	    break;  /* End of array, nothing found.  */
2355 
2356 	  flagnm = arc_flag_operands[flag_idx].name;
2357 	  flaglen = strlen (flagnm);
2358 	  if (strcmp (opname + oplen, flagnm) == 0)
2359 	    {
2360               entry = arc_find_opcode (arc_flag_special_opcode->name);
2361 
2362 	      if (*nflgs + 1 > MAX_INSN_FLGS)
2363 		break;
2364 	      memcpy (pflags[*nflgs].name, flagnm, flaglen);
2365 	      pflags[*nflgs].name[flaglen] = '\0';
2366 	      (*nflgs)++;
2367 	      return entry;
2368 	    }
2369 	}
2370     }
2371   return NULL;
2372 }
2373 
2374 /* Used to find special case opcode.  */
2375 
2376 static const struct arc_opcode_hash_entry *
find_special_case(const char * opname,int * nflgs,struct arc_flags * pflags,expressionS * tok,int * ntok)2377 find_special_case (const char *opname,
2378 		   int *nflgs,
2379 		   struct arc_flags *pflags,
2380 		   expressionS *tok,
2381 		   int *ntok)
2382 {
2383   const struct arc_opcode_hash_entry *entry;
2384 
2385   entry = find_special_case_pseudo (opname, ntok, tok, nflgs, pflags);
2386 
2387   if (entry == NULL)
2388     entry = find_special_case_flag (opname, nflgs, pflags);
2389 
2390   return entry;
2391 }
2392 
2393 /* Autodetect cpu attribute list.  */
2394 
2395 static void
autodetect_attributes(const struct arc_opcode * opcode,const expressionS * tok,int ntok)2396 autodetect_attributes (const struct arc_opcode *opcode,
2397 			 const expressionS *tok,
2398 			 int ntok)
2399 {
2400   unsigned i;
2401   struct mpy_type
2402   {
2403     unsigned feature;
2404     unsigned encoding;
2405   } mpy_list[] = {{ MPY1E, 1 }, { MPY6E, 6 }, { MPY7E, 7 }, { MPY8E, 8 },
2406 		 { MPY9E, 9 }};
2407 
2408   for (i = 0; i < ARRAY_SIZE (feature_list); i++)
2409     if (opcode->subclass == feature_list[i].feature)
2410       selected_cpu.features |= feature_list[i].feature;
2411 
2412   for (i = 0; i < ARRAY_SIZE (mpy_list); i++)
2413     if (opcode->subclass == mpy_list[i].feature)
2414       mpy_option = mpy_list[i].encoding;
2415 
2416   for (i = 0; i < (unsigned) ntok; i++)
2417     {
2418       switch (tok[i].X_md)
2419 	{
2420 	case O_gotoff:
2421 	case O_gotpc:
2422 	case O_plt:
2423 	  pic_option = 2;
2424 	  break;
2425 	case O_sda:
2426 	  sda_option = 2;
2427 	  break;
2428 	case O_tlsgd:
2429 	case O_tlsie:
2430 	case O_tpoff9:
2431 	case O_tpoff:
2432 	case O_dtpoff9:
2433 	case O_dtpoff:
2434 	  tls_option = 1;
2435 	  break;
2436 	default:
2437 	  break;
2438 	}
2439 
2440       switch (tok[i].X_op)
2441 	{
2442 	case O_register:
2443 	  if ((tok[i].X_add_number >= 4 && tok[i].X_add_number <= 9)
2444 	      || (tok[i].X_add_number >= 16 && tok[i].X_add_number <= 25))
2445 	    rf16_only = false;
2446 	  break;
2447 	default:
2448 	  break;
2449 	}
2450     }
2451 }
2452 
2453 /* Given an opcode name, pre-tockenized set of argumenst and the
2454    opcode flags, take it all the way through emission.  */
2455 
2456 static void
assemble_tokens(const char * opname,expressionS * tok,int ntok,struct arc_flags * pflags,int nflgs)2457 assemble_tokens (const char *opname,
2458 		 expressionS *tok,
2459 		 int ntok,
2460 		 struct arc_flags *pflags,
2461 		 int nflgs)
2462 {
2463   bool found_something = false;
2464   const struct arc_opcode_hash_entry *entry;
2465   int cpumatch = 1;
2466   const char *errmsg = NULL;
2467 
2468   /* Search opcodes.  */
2469   entry = arc_find_opcode (opname);
2470 
2471   /* Couldn't find opcode conventional way, try special cases.  */
2472   if (entry == NULL)
2473     entry = find_special_case (opname, &nflgs, pflags, tok, &ntok);
2474 
2475   if (entry != NULL)
2476     {
2477       const struct arc_opcode *opcode;
2478 
2479       pr_debug ("%s:%d: assemble_tokens: %s\n",
2480 		frag_now->fr_file, frag_now->fr_line, opname);
2481       found_something = true;
2482       opcode = find_opcode_match (entry, tok, &ntok, pflags,
2483 				  nflgs, &cpumatch, &errmsg);
2484       if (opcode != NULL)
2485 	{
2486 	  struct arc_insn insn;
2487 
2488 	  autodetect_attributes (opcode,  tok, ntok);
2489 	  assemble_insn (opcode, tok, ntok, pflags, nflgs, &insn);
2490 	  emit_insn (&insn);
2491 	  return;
2492 	}
2493     }
2494 
2495   if (found_something)
2496     {
2497       if (cpumatch)
2498 	if (errmsg)
2499 	  as_bad (_("%s for instruction '%s'"), errmsg, opname);
2500 	else
2501 	  as_bad (_("inappropriate arguments for opcode '%s'"), opname);
2502       else
2503 	as_bad (_("opcode '%s' not supported for target %s"), opname,
2504 		selected_cpu.name);
2505     }
2506   else
2507     as_bad (_("unknown opcode '%s'"), opname);
2508 }
2509 
2510 /* The public interface to the instruction assembler.  */
2511 
2512 void
md_assemble(char * str)2513 md_assemble (char *str)
2514 {
2515   char *opname;
2516   expressionS tok[MAX_INSN_ARGS];
2517   int ntok, nflg;
2518   size_t opnamelen;
2519   struct arc_flags flags[MAX_INSN_FLGS];
2520 
2521   /* Split off the opcode.  */
2522   opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_0123456789");
2523   opname = xmemdup0 (str, opnamelen);
2524 
2525   /* Signalize we are assembling the instructions.  */
2526   assembling_insn = true;
2527 
2528   /* Tokenize the flags.  */
2529   if ((nflg = tokenize_flags (str + opnamelen, flags, MAX_INSN_FLGS)) == -1)
2530     {
2531       as_bad (_("syntax error"));
2532       return;
2533     }
2534 
2535   /* Scan up to the end of the mnemonic which must end in space or end
2536      of string.  */
2537   str += opnamelen;
2538   for (; *str != '\0'; str++)
2539     if (*str == ' ')
2540       break;
2541 
2542   /* Tokenize the rest of the line.  */
2543   if ((ntok = tokenize_arguments (str, tok, MAX_INSN_ARGS)) < 0)
2544     {
2545       as_bad (_("syntax error"));
2546       return;
2547     }
2548 
2549   /* Finish it off.  */
2550   assemble_tokens (opname, tok, ntok, flags, nflg);
2551   assembling_insn = false;
2552 }
2553 
2554 /* Callback to insert a register into the hash table.  */
2555 
2556 static void
declare_register(const char * name,int number)2557 declare_register (const char *name, int number)
2558 {
2559   symbolS *regS = symbol_create (name, reg_section,
2560 				 &zero_address_frag, number);
2561 
2562   if (str_hash_insert (arc_reg_hash, S_GET_NAME (regS), regS, 0) != NULL)
2563     as_fatal (_("duplicate %s"), name);
2564 }
2565 
2566 /* Construct symbols for each of the general registers.  */
2567 
2568 static void
declare_register_set(void)2569 declare_register_set (void)
2570 {
2571   int i;
2572   for (i = 0; i < 64; ++i)
2573     {
2574       char name[32];
2575 
2576       sprintf (name, "r%d", i);
2577       declare_register (name, i);
2578       if ((i & 0x01) == 0)
2579 	{
2580 	  sprintf (name, "r%dr%d", i, i+1);
2581 	  declare_register (name, i);
2582 	}
2583     }
2584 }
2585 
2586 /* Construct a symbol for an address type.  */
2587 
2588 static void
declare_addrtype(const char * name,int number)2589 declare_addrtype (const char *name, int number)
2590 {
2591   symbolS *addrtypeS = symbol_create (name, undefined_section,
2592 				      &zero_address_frag, number);
2593 
2594   if (str_hash_insert (arc_addrtype_hash, S_GET_NAME (addrtypeS), addrtypeS, 0))
2595     as_fatal (_("duplicate %s"), name);
2596 }
2597 
2598 /* Port-specific assembler initialization.  This function is called
2599    once, at assembler startup time.  */
2600 
2601 void
md_begin(void)2602 md_begin (void)
2603 {
2604   const struct arc_opcode *opcode = arc_opcodes;
2605 
2606   if (mach_selection_mode == MACH_SELECTION_NONE)
2607     arc_select_cpu (TARGET_WITH_CPU, MACH_SELECTION_FROM_DEFAULT);
2608 
2609   /* The endianness can be chosen "at the factory".  */
2610   target_big_endian = byte_order == BIG_ENDIAN;
2611 
2612   if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, selected_cpu.mach))
2613     as_warn (_("could not set architecture and machine"));
2614 
2615   /* Set elf header flags.  */
2616   bfd_set_private_flags (stdoutput, selected_cpu.eflags);
2617 
2618   /* Set up a hash table for the instructions.  */
2619   arc_opcode_hash = htab_create_alloc (16, hash_string_tuple, eq_string_tuple,
2620 				       arc_opcode_free, xcalloc, free);
2621 
2622   /* Initialize the hash table with the insns.  */
2623   do
2624     {
2625       const char *name = opcode->name;
2626 
2627       arc_insert_opcode (opcode);
2628 
2629       while (++opcode && opcode->name
2630 	     && (opcode->name == name
2631 		 || !strcmp (opcode->name, name)))
2632 	continue;
2633     }while (opcode->name);
2634 
2635   /* Register declaration.  */
2636   arc_reg_hash = str_htab_create ();
2637 
2638   declare_register_set ();
2639   declare_register ("gp", 26);
2640   declare_register ("fp", 27);
2641   declare_register ("sp", 28);
2642   declare_register ("ilink", 29);
2643   declare_register ("ilink1", 29);
2644   declare_register ("ilink2", 30);
2645   declare_register ("blink", 31);
2646 
2647   /* XY memory registers.  */
2648   declare_register ("x0_u0", 32);
2649   declare_register ("x0_u1", 33);
2650   declare_register ("x1_u0", 34);
2651   declare_register ("x1_u1", 35);
2652   declare_register ("x2_u0", 36);
2653   declare_register ("x2_u1", 37);
2654   declare_register ("x3_u0", 38);
2655   declare_register ("x3_u1", 39);
2656   declare_register ("y0_u0", 40);
2657   declare_register ("y0_u1", 41);
2658   declare_register ("y1_u0", 42);
2659   declare_register ("y1_u1", 43);
2660   declare_register ("y2_u0", 44);
2661   declare_register ("y2_u1", 45);
2662   declare_register ("y3_u0", 46);
2663   declare_register ("y3_u1", 47);
2664   declare_register ("x0_nu", 48);
2665   declare_register ("x1_nu", 49);
2666   declare_register ("x2_nu", 50);
2667   declare_register ("x3_nu", 51);
2668   declare_register ("y0_nu", 52);
2669   declare_register ("y1_nu", 53);
2670   declare_register ("y2_nu", 54);
2671   declare_register ("y3_nu", 55);
2672 
2673   declare_register ("mlo", 57);
2674   declare_register ("mmid", 58);
2675   declare_register ("mhi", 59);
2676 
2677   declare_register ("acc1", 56);
2678   declare_register ("acc2", 57);
2679 
2680   declare_register ("lp_count", 60);
2681   declare_register ("pcl", 63);
2682 
2683   /* Initialize the last instructions.  */
2684   memset (&arc_last_insns[0], 0, sizeof (arc_last_insns));
2685 
2686   /* Aux register declaration.  */
2687   arc_aux_hash = str_htab_create ();
2688 
2689   const struct arc_aux_reg *auxr = &arc_aux_regs[0];
2690   unsigned int i;
2691   for (i = 0; i < arc_num_aux_regs; i++, auxr++)
2692     {
2693       if (!(auxr->cpu & selected_cpu.flags))
2694 	continue;
2695 
2696       if ((auxr->subclass != NONE)
2697 	  && !check_cpu_feature (auxr->subclass))
2698 	continue;
2699 
2700       if (str_hash_insert (arc_aux_hash, auxr->name, auxr, 0) != 0)
2701 	as_fatal (_("duplicate %s"), auxr->name);
2702     }
2703 
2704   /* Address type declaration.  */
2705   arc_addrtype_hash = str_htab_create ();
2706 
2707   declare_addrtype ("bd", ARC_NPS400_ADDRTYPE_BD);
2708   declare_addrtype ("jid", ARC_NPS400_ADDRTYPE_JID);
2709   declare_addrtype ("lbd", ARC_NPS400_ADDRTYPE_LBD);
2710   declare_addrtype ("mbd", ARC_NPS400_ADDRTYPE_MBD);
2711   declare_addrtype ("sd", ARC_NPS400_ADDRTYPE_SD);
2712   declare_addrtype ("sm", ARC_NPS400_ADDRTYPE_SM);
2713   declare_addrtype ("xa", ARC_NPS400_ADDRTYPE_XA);
2714   declare_addrtype ("xd", ARC_NPS400_ADDRTYPE_XD);
2715   declare_addrtype ("cd", ARC_NPS400_ADDRTYPE_CD);
2716   declare_addrtype ("cbd", ARC_NPS400_ADDRTYPE_CBD);
2717   declare_addrtype ("cjid", ARC_NPS400_ADDRTYPE_CJID);
2718   declare_addrtype ("clbd", ARC_NPS400_ADDRTYPE_CLBD);
2719   declare_addrtype ("cm", ARC_NPS400_ADDRTYPE_CM);
2720   declare_addrtype ("csd", ARC_NPS400_ADDRTYPE_CSD);
2721   declare_addrtype ("cxa", ARC_NPS400_ADDRTYPE_CXA);
2722   declare_addrtype ("cxd", ARC_NPS400_ADDRTYPE_CXD);
2723 }
2724 
2725 void
arc_md_end(void)2726 arc_md_end (void)
2727 {
2728   htab_delete (arc_opcode_hash);
2729   htab_delete (arc_reg_hash);
2730   htab_delete (arc_aux_hash);
2731   htab_delete (arc_addrtype_hash);
2732 }
2733 
2734 /* Write a value out to the object file, using the appropriate
2735    endianness.  */
2736 
2737 void
md_number_to_chars(char * buf,valueT val,int n)2738 md_number_to_chars (char *buf,
2739 		    valueT val,
2740 		    int n)
2741 {
2742   if (target_big_endian)
2743     number_to_chars_bigendian (buf, val, n);
2744   else
2745     number_to_chars_littleendian (buf, val, n);
2746 }
2747 
2748 /* Round up a section size to the appropriate boundary.  */
2749 
2750 valueT
md_section_align(segT segment,valueT size)2751 md_section_align (segT segment,
2752 		  valueT size)
2753 {
2754   int align = bfd_section_alignment (segment);
2755 
2756   return ((size + (1 << align) - 1) & (-((valueT) 1 << align)));
2757 }
2758 
2759 /* The location from which a PC relative jump should be calculated,
2760    given a PC relative reloc.  */
2761 
2762 long
md_pcrel_from_section(fixS * fixP,segT sec)2763 md_pcrel_from_section (fixS *fixP,
2764 		       segT sec)
2765 {
2766   offsetT base = fixP->fx_where + fixP->fx_frag->fr_address;
2767 
2768   pr_debug ("pcrel_from_section, fx_offset = %d\n", (int) fixP->fx_offset);
2769 
2770   if (fixP->fx_addsy != (symbolS *) NULL
2771       && (!S_IS_DEFINED (fixP->fx_addsy)
2772 	  || S_GET_SEGMENT (fixP->fx_addsy) != sec))
2773     {
2774       pr_debug ("Unknown pcrel symbol: %s\n", S_GET_NAME (fixP->fx_addsy));
2775 
2776       /* The symbol is undefined (or is defined but not in this section).
2777 	 Let the linker figure it out.  */
2778       return 0;
2779     }
2780 
2781   if ((int) fixP->fx_r_type < 0)
2782     {
2783       /* These are the "internal" relocations.  Align them to
2784 	 32 bit boundary (PCL), for the moment.  */
2785       base &= ~3;
2786     }
2787   else
2788     {
2789       switch (fixP->fx_r_type)
2790 	{
2791 	case BFD_RELOC_ARC_PC32:
2792 	  /* The hardware calculates relative to the start of the
2793 	     insn, but this relocation is relative to location of the
2794 	     LIMM, compensate.  The base always needs to be
2795 	     subtracted by 4 as we do not support this type of PCrel
2796 	     relocation for short instructions.  */
2797 	  base -= 4;
2798 	  /* Fall through.  */
2799 	case BFD_RELOC_ARC_PLT32:
2800 	case BFD_RELOC_ARC_S25H_PCREL_PLT:
2801 	case BFD_RELOC_ARC_S21H_PCREL_PLT:
2802 	case BFD_RELOC_ARC_S25W_PCREL_PLT:
2803 	case BFD_RELOC_ARC_S21W_PCREL_PLT:
2804 
2805 	case BFD_RELOC_ARC_S21H_PCREL:
2806 	case BFD_RELOC_ARC_S25H_PCREL:
2807 	case BFD_RELOC_ARC_S13_PCREL:
2808 	case BFD_RELOC_ARC_S21W_PCREL:
2809 	case BFD_RELOC_ARC_S25W_PCREL:
2810 	  base &= ~3;
2811 	  break;
2812 	default:
2813 	  as_bad_where (fixP->fx_file, fixP->fx_line,
2814 			_("unhandled reloc %s in md_pcrel_from_section"),
2815 		  bfd_get_reloc_code_name (fixP->fx_r_type));
2816 	  break;
2817 	}
2818     }
2819 
2820   pr_debug ("pcrel from %" PRIx64 " + %lx = %" PRIx64 ", "
2821 	    "symbol: %s (%" PRIx64 ")\n",
2822 	    (uint64_t) fixP->fx_frag->fr_address, fixP->fx_where, (uint64_t) base,
2823 	    fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "(null)",
2824 	    fixP->fx_addsy ? (uint64_t) S_GET_VALUE (fixP->fx_addsy) : (uint64_t) 0);
2825 
2826   return base;
2827 }
2828 
2829 /* Given a BFD relocation find the corresponding operand.  */
2830 
2831 static const struct arc_operand *
find_operand_for_reloc(extended_bfd_reloc_code_real_type reloc)2832 find_operand_for_reloc (extended_bfd_reloc_code_real_type reloc)
2833 {
2834   unsigned i;
2835 
2836   for (i = 0; i < arc_num_operands; i++)
2837     if (arc_operands[i].default_reloc == reloc)
2838       return  &arc_operands[i];
2839   return NULL;
2840 }
2841 
2842 /* Insert an operand value into an instruction.  */
2843 
2844 static unsigned long long
insert_operand(unsigned long long insn,const struct arc_operand * operand,long long val,const char * file,unsigned line)2845 insert_operand (unsigned long long insn,
2846 		const struct arc_operand *operand,
2847 		long long val,
2848 		const char *file,
2849 		unsigned line)
2850 {
2851   offsetT min = 0, max = 0;
2852 
2853   if (operand->bits != 32
2854       && !(operand->flags & ARC_OPERAND_NCHK)
2855       && !(operand->flags & ARC_OPERAND_FAKE))
2856     {
2857       if (operand->flags & ARC_OPERAND_SIGNED)
2858 	{
2859 	  max = (1 << (operand->bits - 1)) - 1;
2860 	  min = -(1 << (operand->bits - 1));
2861 	}
2862       else
2863 	{
2864 	  max = (1 << operand->bits) - 1;
2865 	  min = 0;
2866 	}
2867 
2868       if (val < min || val > max)
2869 	as_bad_value_out_of_range (_("operand"),
2870 				   val, min, max, file, line);
2871     }
2872 
2873   pr_debug ("insert field: %ld <= %lld <= %ld in 0x%08llx\n",
2874 	    min, val, max, insn);
2875 
2876   if ((operand->flags & ARC_OPERAND_ALIGNED32)
2877       && (val & 0x03))
2878     as_bad_where (file, line,
2879 		  _("Unaligned operand. Needs to be 32bit aligned"));
2880 
2881   if ((operand->flags & ARC_OPERAND_ALIGNED16)
2882       && (val & 0x01))
2883     as_bad_where (file, line,
2884 		  _("Unaligned operand. Needs to be 16bit aligned"));
2885 
2886   if (operand->insert)
2887     {
2888       const char *errmsg = NULL;
2889 
2890       insn = (*operand->insert) (insn, val, &errmsg);
2891       if (errmsg)
2892 	as_warn_where (file, line, "%s", errmsg);
2893     }
2894   else
2895     {
2896       if (operand->flags & ARC_OPERAND_TRUNCATE)
2897 	{
2898 	  if (operand->flags & ARC_OPERAND_ALIGNED32)
2899 	    val >>= 2;
2900 	  if (operand->flags & ARC_OPERAND_ALIGNED16)
2901 	    val >>= 1;
2902 	}
2903       insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift);
2904     }
2905   return insn;
2906 }
2907 
2908 /* Apply a fixup to the object code.  At this point all symbol values
2909    should be fully resolved, and we attempt to completely resolve the
2910    reloc.  If we can not do that, we determine the correct reloc code
2911    and put it back in the fixup.  To indicate that a fixup has been
2912    eliminated, set fixP->fx_done.  */
2913 
2914 void
md_apply_fix(fixS * fixP,valueT * valP,segT seg)2915 md_apply_fix (fixS *fixP,
2916 	      valueT *valP,
2917 	      segT seg)
2918 {
2919   char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
2920   valueT value = *valP;
2921   unsigned insn = 0;
2922   symbolS *fx_addsy, *fx_subsy;
2923   offsetT fx_offset;
2924   segT add_symbol_segment = absolute_section;
2925   segT sub_symbol_segment = absolute_section;
2926   const struct arc_operand *operand = NULL;
2927   extended_bfd_reloc_code_real_type reloc;
2928 
2929   pr_debug ("%s:%u: apply_fix: r_type=%d (%s) value=0x%lX offset=0x%lX\n",
2930 	    fixP->fx_file, fixP->fx_line, fixP->fx_r_type,
2931 	    ((int) fixP->fx_r_type < 0) ? "Internal":
2932 	    bfd_get_reloc_code_name (fixP->fx_r_type), value,
2933 	    fixP->fx_offset);
2934 
2935   fx_addsy = fixP->fx_addsy;
2936   fx_subsy = fixP->fx_subsy;
2937   fx_offset = 0;
2938 
2939   if (fx_addsy)
2940     {
2941       add_symbol_segment = S_GET_SEGMENT (fx_addsy);
2942     }
2943 
2944   if (fx_subsy
2945       && fixP->fx_r_type != BFD_RELOC_ARC_TLS_DTPOFF
2946       && fixP->fx_r_type != BFD_RELOC_ARC_TLS_DTPOFF_S9
2947       && fixP->fx_r_type != BFD_RELOC_ARC_TLS_GD_LD)
2948     {
2949       resolve_symbol_value (fx_subsy);
2950       sub_symbol_segment = S_GET_SEGMENT (fx_subsy);
2951 
2952       if (sub_symbol_segment == absolute_section)
2953 	{
2954 	  /* The symbol is really a constant.  */
2955 	  fx_offset -= S_GET_VALUE (fx_subsy);
2956 	  fx_subsy = NULL;
2957 	}
2958       else
2959 	{
2960 	  as_bad_subtract (fixP);
2961 	  return;
2962 	}
2963     }
2964 
2965   if (fx_addsy
2966       && !S_IS_WEAK (fx_addsy))
2967     {
2968       if (add_symbol_segment == seg
2969 	  && fixP->fx_pcrel)
2970 	{
2971 	  value += S_GET_VALUE (fx_addsy);
2972 	  value -= md_pcrel_from_section (fixP, seg);
2973 	  fx_addsy = NULL;
2974 	  fixP->fx_pcrel = false;
2975 	}
2976       else if (add_symbol_segment == absolute_section)
2977 	{
2978 	  value = fixP->fx_offset;
2979 	  fx_offset += S_GET_VALUE (fixP->fx_addsy);
2980 	  fx_addsy = NULL;
2981 	  fixP->fx_pcrel = false;
2982 	}
2983     }
2984 
2985   if (!fx_addsy)
2986     fixP->fx_done = true;
2987 
2988   if (fixP->fx_pcrel)
2989     {
2990       if (fx_addsy
2991 	  && ((S_IS_DEFINED (fx_addsy)
2992 	       && S_GET_SEGMENT (fx_addsy) != seg)
2993 	      || S_IS_WEAK (fx_addsy)))
2994 	value += md_pcrel_from_section (fixP, seg);
2995 
2996       switch (fixP->fx_r_type)
2997 	{
2998 	case BFD_RELOC_ARC_32_ME:
2999 	  /* This is a pc-relative value in a LIMM.  Adjust it to the
3000 	     address of the instruction not to the address of the
3001 	     LIMM.  Note: it is not any longer valid this affirmation as
3002 	     the linker consider ARC_PC32 a fixup to entire 64 bit
3003 	     insn.  */
3004 	  fixP->fx_offset += fixP->fx_frag->fr_address;
3005 	  /* Fall through.  */
3006 	case BFD_RELOC_32:
3007 	  fixP->fx_r_type = BFD_RELOC_ARC_PC32;
3008 	  /* Fall through.  */
3009 	case BFD_RELOC_ARC_PC32:
3010 	  /* fixP->fx_offset += fixP->fx_where - fixP->fx_dot_value; */
3011 	  break;
3012 	default:
3013 	  if ((int) fixP->fx_r_type < 0)
3014 	    as_bad_where (fixP->fx_file, fixP->fx_line,
3015 			  _("PC relative relocation not allowed for (internal)"
3016 			    " type %d"),
3017 			  fixP->fx_r_type);
3018 	  break;
3019 	}
3020     }
3021 
3022   pr_debug ("%s:%u: apply_fix: r_type=%d (%s) value=0x%lX offset=0x%lX\n",
3023 	    fixP->fx_file, fixP->fx_line, fixP->fx_r_type,
3024 	    ((int) fixP->fx_r_type < 0) ? "Internal":
3025 	    bfd_get_reloc_code_name (fixP->fx_r_type), value,
3026 	    fixP->fx_offset);
3027 
3028 
3029   /* Now check for TLS relocations.  */
3030   reloc = fixP->fx_r_type;
3031   switch (reloc)
3032     {
3033     case BFD_RELOC_ARC_TLS_DTPOFF:
3034     case BFD_RELOC_ARC_TLS_LE_32:
3035       if (fixP->fx_done)
3036 	break;
3037       /* Fall through.  */
3038     case BFD_RELOC_ARC_TLS_GD_GOT:
3039     case BFD_RELOC_ARC_TLS_IE_GOT:
3040       S_SET_THREAD_LOCAL (fixP->fx_addsy);
3041       break;
3042 
3043     case BFD_RELOC_ARC_TLS_GD_LD:
3044       gas_assert (!fixP->fx_offset);
3045       if (fixP->fx_subsy)
3046 	fixP->fx_offset
3047 	  = (S_GET_VALUE (fixP->fx_subsy)
3048 	     - fixP->fx_frag->fr_address- fixP->fx_where);
3049       fixP->fx_subsy = NULL;
3050       /* Fall through.  */
3051     case BFD_RELOC_ARC_TLS_GD_CALL:
3052       /* These two relocs are there just to allow ld to change the tls
3053 	 model for this symbol, by patching the code.  The offset -
3054 	 and scale, if any - will be installed by the linker.  */
3055       S_SET_THREAD_LOCAL (fixP->fx_addsy);
3056       break;
3057 
3058     case BFD_RELOC_ARC_TLS_LE_S9:
3059     case BFD_RELOC_ARC_TLS_DTPOFF_S9:
3060       as_bad (_("TLS_*_S9 relocs are not supported yet"));
3061       break;
3062 
3063     default:
3064       break;
3065     }
3066 
3067   if (!fixP->fx_done)
3068     {
3069       return;
3070     }
3071 
3072   /* Adjust the value if we have a constant.  */
3073   value += fx_offset;
3074 
3075   /* For hosts with longs bigger than 32-bits make sure that the top
3076      bits of a 32-bit negative value read in by the parser are set,
3077      so that the correct comparisons are made.  */
3078   if (value & 0x80000000)
3079     value |= (-1UL << 31);
3080 
3081   reloc = fixP->fx_r_type;
3082   switch (reloc)
3083     {
3084     case BFD_RELOC_8:
3085     case BFD_RELOC_16:
3086     case BFD_RELOC_24:
3087     case BFD_RELOC_32:
3088     case BFD_RELOC_64:
3089     case BFD_RELOC_ARC_32_PCREL:
3090       md_number_to_chars (fixpos, value, fixP->fx_size);
3091       return;
3092 
3093     case BFD_RELOC_ARC_GOTPC32:
3094       /* I cannot fix an GOTPC relocation because I need to relax it
3095 	 from ld rx,[pcl,@sym@gotpc] to add rx,pcl,@sym@gotpc.  */
3096       as_bad (_("Unsupported operation on reloc"));
3097       return;
3098 
3099     case BFD_RELOC_ARC_TLS_DTPOFF:
3100     case BFD_RELOC_ARC_TLS_LE_32:
3101       gas_assert (!fixP->fx_addsy);
3102       gas_assert (!fixP->fx_subsy);
3103       /* Fall through.  */
3104 
3105     case BFD_RELOC_ARC_GOTOFF:
3106     case BFD_RELOC_ARC_32_ME:
3107     case BFD_RELOC_ARC_PC32:
3108       md_number_to_chars_midend (fixpos, value, fixP->fx_size);
3109       return;
3110 
3111     case BFD_RELOC_ARC_PLT32:
3112       md_number_to_chars_midend (fixpos, value, fixP->fx_size);
3113       return;
3114 
3115     case BFD_RELOC_ARC_S25H_PCREL_PLT:
3116       reloc = BFD_RELOC_ARC_S25W_PCREL;
3117       goto solve_plt;
3118 
3119     case BFD_RELOC_ARC_S21H_PCREL_PLT:
3120       reloc = BFD_RELOC_ARC_S21H_PCREL;
3121       goto solve_plt;
3122 
3123     case BFD_RELOC_ARC_S25W_PCREL_PLT:
3124       reloc = BFD_RELOC_ARC_S25W_PCREL;
3125       goto solve_plt;
3126 
3127     case BFD_RELOC_ARC_S21W_PCREL_PLT:
3128       reloc = BFD_RELOC_ARC_S21W_PCREL;
3129       /* Fall through.  */
3130 
3131     case BFD_RELOC_ARC_S25W_PCREL:
3132     case BFD_RELOC_ARC_S21W_PCREL:
3133     case BFD_RELOC_ARC_S21H_PCREL:
3134     case BFD_RELOC_ARC_S25H_PCREL:
3135     case BFD_RELOC_ARC_S13_PCREL:
3136     solve_plt:
3137       operand = find_operand_for_reloc (reloc);
3138       gas_assert (operand);
3139       break;
3140 
3141     default:
3142       {
3143 	if ((int) fixP->fx_r_type >= 0)
3144 	  as_fatal (_("unhandled relocation type %s"),
3145 		    bfd_get_reloc_code_name (fixP->fx_r_type));
3146 
3147 	/* The rest of these fixups needs to be completely resolved as
3148 	   constants.  */
3149 	if (fixP->fx_addsy != 0
3150 	    && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
3151 	  as_bad_where (fixP->fx_file, fixP->fx_line,
3152 			_("non-absolute expression in constant field"));
3153 
3154 	gas_assert (-(int) fixP->fx_r_type < (int) arc_num_operands);
3155 	operand = &arc_operands[-(int) fixP->fx_r_type];
3156 	break;
3157       }
3158     }
3159 
3160   if (target_big_endian)
3161     {
3162       switch (fixP->fx_size)
3163 	{
3164 	case 4:
3165 	  insn = bfd_getb32 (fixpos);
3166 	  break;
3167 	case 2:
3168 	  insn = bfd_getb16 (fixpos);
3169 	  break;
3170 	default:
3171 	  as_bad_where (fixP->fx_file, fixP->fx_line,
3172 			_("unknown fixup size"));
3173 	}
3174     }
3175   else
3176     {
3177       insn = 0;
3178       switch (fixP->fx_size)
3179 	{
3180 	case 4:
3181 	  insn = bfd_getl16 (fixpos) << 16 | bfd_getl16 (fixpos + 2);
3182 	  break;
3183 	case 2:
3184 	  insn = bfd_getl16 (fixpos);
3185 	  break;
3186 	default:
3187 	  as_bad_where (fixP->fx_file, fixP->fx_line,
3188 			_("unknown fixup size"));
3189 	}
3190     }
3191 
3192   insn = insert_operand (insn, operand, (offsetT) value,
3193 			 fixP->fx_file, fixP->fx_line);
3194 
3195   md_number_to_chars_midend (fixpos, insn, fixP->fx_size);
3196 }
3197 
3198 /* Prepare machine-dependent frags for relaxation.
3199 
3200    Called just before relaxation starts.  Any symbol that is now undefined
3201    will not become defined.
3202 
3203    Return the correct fr_subtype in the frag.
3204 
3205    Return the initial "guess for fr_var" to caller.  The guess for fr_var
3206    is *actually* the growth beyond fr_fix.  Whatever we do to grow fr_fix
3207    or fr_var contributes to our returned value.
3208 
3209    Although it may not be explicit in the frag, pretend
3210    fr_var starts with a value.  */
3211 
3212 int
md_estimate_size_before_relax(fragS * fragP,segT segment)3213 md_estimate_size_before_relax (fragS *fragP,
3214 			       segT segment)
3215 {
3216   int growth;
3217 
3218   /* If the symbol is not located within the same section AND it's not
3219      an absolute section, use the maximum.  OR if the symbol is a
3220      constant AND the insn is by nature not pc-rel, use the maximum.
3221      OR if the symbol is being equated against another symbol, use the
3222      maximum.  OR if the symbol is weak use the maximum.  */
3223   if ((S_GET_SEGMENT (fragP->fr_symbol) != segment
3224        && S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
3225       || (symbol_constant_p (fragP->fr_symbol)
3226 	  && !fragP->tc_frag_data.pcrel)
3227       || symbol_equated_p (fragP->fr_symbol)
3228       || S_IS_WEAK (fragP->fr_symbol))
3229     {
3230       while (md_relax_table[fragP->fr_subtype].rlx_more != ARC_RLX_NONE)
3231 	++fragP->fr_subtype;
3232     }
3233 
3234   growth = md_relax_table[fragP->fr_subtype].rlx_length;
3235   fragP->fr_var = growth;
3236 
3237   pr_debug ("%s:%d: md_estimate_size_before_relax: %d\n",
3238 	   fragP->fr_file, fragP->fr_line, growth);
3239 
3240   return growth;
3241 }
3242 
3243 /* Translate internal representation of relocation info to BFD target
3244    format.  */
3245 
3246 arelent *
tc_gen_reloc(asection * section ATTRIBUTE_UNUSED,fixS * fixP)3247 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
3248 	      fixS *fixP)
3249 {
3250   arelent *reloc;
3251   bfd_reloc_code_real_type code;
3252 
3253   reloc = XNEW (arelent);
3254   reloc->sym_ptr_ptr = XNEW (asymbol *);
3255   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
3256   reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
3257 
3258   /* Make sure none of our internal relocations make it this far.
3259      They'd better have been fully resolved by this point.  */
3260   gas_assert ((int) fixP->fx_r_type > 0);
3261 
3262   code = fixP->fx_r_type;
3263 
3264   /* if we have something like add gp, pcl,
3265      _GLOBAL_OFFSET_TABLE_@gotpc.  */
3266   if (code == BFD_RELOC_ARC_GOTPC32
3267       && GOT_symbol
3268       && fixP->fx_addsy == GOT_symbol)
3269     code = BFD_RELOC_ARC_GOTPC;
3270 
3271   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
3272   if (reloc->howto == NULL)
3273     {
3274       as_bad_where (fixP->fx_file, fixP->fx_line,
3275 		    _("cannot represent `%s' relocation in object file"),
3276 		    bfd_get_reloc_code_name (code));
3277       return NULL;
3278     }
3279 
3280   if (!fixP->fx_pcrel != !reloc->howto->pc_relative)
3281     as_fatal (_("internal error? cannot generate `%s' relocation"),
3282 	      bfd_get_reloc_code_name (code));
3283 
3284   gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
3285 
3286   reloc->addend = fixP->fx_offset;
3287 
3288   return reloc;
3289 }
3290 
3291 /* Perform post-processing of machine-dependent frags after relaxation.
3292    Called after relaxation is finished.
3293    In:	Address of frag.
3294    fr_type == rs_machine_dependent.
3295    fr_subtype is what the address relaxed to.
3296 
3297    Out: Any fixS:s and constants are set up.  */
3298 
3299 void
md_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,segT segment ATTRIBUTE_UNUSED,fragS * fragP)3300 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
3301 		 segT segment ATTRIBUTE_UNUSED,
3302 		 fragS *fragP)
3303 {
3304   const relax_typeS *table_entry;
3305   char *dest;
3306   const struct arc_opcode *opcode;
3307   struct arc_insn insn;
3308   int size, fix;
3309   struct arc_relax_type *relax_arg = &fragP->tc_frag_data;
3310 
3311   fix = fragP->fr_fix;
3312   dest = fragP->fr_literal + fix;
3313   table_entry = TC_GENERIC_RELAX_TABLE + fragP->fr_subtype;
3314 
3315   pr_debug ("%s:%d: md_convert_frag, subtype: %d, fix: %d, "
3316 	    "var: %" PRId64 "\n",
3317 	    fragP->fr_file, fragP->fr_line,
3318 	    fragP->fr_subtype, fix, (int64_t) fragP->fr_var);
3319 
3320   if (fragP->fr_subtype <= 0
3321       && fragP->fr_subtype >= arc_num_relax_opcodes)
3322     as_fatal (_("no relaxation found for this instruction."));
3323 
3324   opcode = &arc_relax_opcodes[fragP->fr_subtype];
3325 
3326   assemble_insn (opcode, relax_arg->tok, relax_arg->ntok, relax_arg->pflags,
3327 	relax_arg->nflg, &insn);
3328 
3329   apply_fixups (&insn, fragP, fix);
3330 
3331   size = insn.len + (insn.has_limm ? 4 : 0);
3332   gas_assert (table_entry->rlx_length == size);
3333   emit_insn0 (&insn, dest, true);
3334 
3335   fragP->fr_fix += table_entry->rlx_length;
3336   fragP->fr_var = 0;
3337 }
3338 
3339 /* We have no need to default values of symbols.  We could catch
3340    register names here, but that is handled by inserting them all in
3341    the symbol table to begin with.  */
3342 
3343 symbolS *
md_undefined_symbol(char * name)3344 md_undefined_symbol (char *name)
3345 {
3346   /* The arc abi demands that a GOT[0] should be referencible as
3347      [pc+_DYNAMIC@gotpc].  Hence we convert a _DYNAMIC@gotpc to a
3348      GOTPC reference to _GLOBAL_OFFSET_TABLE_.  */
3349   if (((*name == '_')
3350        && (*(name+1) == 'G')
3351        && (strcmp (name, GLOBAL_OFFSET_TABLE_NAME) == 0)))
3352     {
3353       if (!GOT_symbol)
3354 	{
3355 	  if (symbol_find (name))
3356 	    as_bad ("GOT already in symbol table");
3357 
3358 	  GOT_symbol = symbol_new (GLOBAL_OFFSET_TABLE_NAME, undefined_section,
3359 				   &zero_address_frag, 0);
3360 	};
3361       return GOT_symbol;
3362     }
3363   return NULL;
3364 }
3365 
3366 /* Turn a string in input_line_pointer into a floating point constant
3367    of type type, and store the appropriate bytes in *litP.  The number
3368    of LITTLENUMS emitted is stored in *sizeP.  An error message is
3369    returned, or NULL on OK.  */
3370 
3371 const char *
md_atof(int type,char * litP,int * sizeP)3372 md_atof (int type, char *litP, int *sizeP)
3373 {
3374   return ieee_md_atof (type, litP, sizeP, target_big_endian);
3375 }
3376 
3377 /* Called for any expression that can not be recognized.  When the
3378    function is called, `input_line_pointer' will point to the start of
3379    the expression.  We use it when we have complex operations like
3380    @label1 - @label2.  */
3381 
3382 void
md_operand(expressionS * expressionP)3383 md_operand (expressionS *expressionP)
3384 {
3385   char *p = input_line_pointer;
3386   if (*p == '@')
3387     {
3388       input_line_pointer++;
3389       expressionP->X_op = O_symbol;
3390       expressionP->X_md = O_absent;
3391       expression (expressionP);
3392     }
3393 }
3394 
3395 /* This function is called from the function 'expression', it attempts
3396    to parse special names (in our case register names).  It fills in
3397    the expression with the identified register.  It returns TRUE if
3398    it is a register and FALSE otherwise.  */
3399 
3400 bool
arc_parse_name(const char * name,struct expressionS * e)3401 arc_parse_name (const char *name,
3402 		struct expressionS *e)
3403 {
3404   struct symbol *sym;
3405 
3406   if (!assembling_insn)
3407     return false;
3408 
3409   if (e->X_op == O_symbol
3410       && e->X_md == O_absent)
3411     return false;
3412 
3413   sym = str_hash_find (arc_reg_hash, name);
3414   if (sym)
3415     {
3416       e->X_op = O_register;
3417       e->X_add_number = S_GET_VALUE (sym);
3418       return true;
3419     }
3420 
3421   sym = str_hash_find (arc_addrtype_hash, name);
3422   if (sym)
3423     {
3424       e->X_op = O_addrtype;
3425       e->X_add_number = S_GET_VALUE (sym);
3426       return true;
3427     }
3428 
3429   return false;
3430 }
3431 
3432 /* md_parse_option
3433    Invocation line includes a switch not recognized by the base assembler.
3434    See if it's a processor-specific option.
3435 
3436    New options (supported) are:
3437 
3438    -mcpu=<cpu name>		 Assemble for selected processor
3439    -EB/-mbig-endian		 Big-endian
3440    -EL/-mlittle-endian		 Little-endian
3441    -mrelax                       Enable relaxation
3442 
3443    The following CPU names are recognized:
3444    arc600, arc700, arcem, archs, nps400.  */
3445 
3446 int
md_parse_option(int c,const char * arg ATTRIBUTE_UNUSED)3447 md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
3448 {
3449   switch (c)
3450     {
3451     case OPTION_ARC600:
3452     case OPTION_ARC601:
3453       return md_parse_option (OPTION_MCPU, "arc600");
3454 
3455     case OPTION_ARC700:
3456       return md_parse_option (OPTION_MCPU, "arc700");
3457 
3458     case OPTION_ARCEM:
3459       return md_parse_option (OPTION_MCPU, "arcem");
3460 
3461     case OPTION_ARCHS:
3462       return md_parse_option (OPTION_MCPU, "archs");
3463 
3464     case OPTION_MCPU:
3465       {
3466         arc_select_cpu (arg, MACH_SELECTION_FROM_COMMAND_LINE);
3467 	break;
3468       }
3469 
3470     case OPTION_EB:
3471       arc_target_format = "elf32-bigarc";
3472       byte_order = BIG_ENDIAN;
3473       break;
3474 
3475     case OPTION_EL:
3476       arc_target_format = "elf32-littlearc";
3477       byte_order = LITTLE_ENDIAN;
3478       break;
3479 
3480     case OPTION_CD:
3481       selected_cpu.features |= CD;
3482       cl_features |= CD;
3483       arc_check_feature ();
3484       break;
3485 
3486     case OPTION_RELAX:
3487       relaxation_state = 1;
3488       break;
3489 
3490     case OPTION_NPS400:
3491       selected_cpu.features |= NPS400;
3492       cl_features |= NPS400;
3493       arc_check_feature ();
3494       break;
3495 
3496     case OPTION_SPFP:
3497       selected_cpu.features |= SPX;
3498       cl_features |= SPX;
3499       arc_check_feature ();
3500       break;
3501 
3502     case OPTION_DPFP:
3503       selected_cpu.features |= DPX;
3504       cl_features |= DPX;
3505       arc_check_feature ();
3506       break;
3507 
3508     case OPTION_FPUDA:
3509       selected_cpu.features |= DPA;
3510       cl_features |= DPA;
3511       arc_check_feature ();
3512       break;
3513 
3514     /* Dummy options are accepted but have no effect.  */
3515     case OPTION_USER_MODE:
3516     case OPTION_LD_EXT_MASK:
3517     case OPTION_SWAP:
3518     case OPTION_NORM:
3519     case OPTION_BARREL_SHIFT:
3520     case OPTION_MIN_MAX:
3521     case OPTION_NO_MPY:
3522     case OPTION_EA:
3523     case OPTION_MUL64:
3524     case OPTION_SIMD:
3525     case OPTION_XMAC_D16:
3526     case OPTION_XMAC_24:
3527     case OPTION_DSP_PACKA:
3528     case OPTION_CRC:
3529     case OPTION_DVBF:
3530     case OPTION_TELEPHONY:
3531     case OPTION_XYMEMORY:
3532     case OPTION_LOCK:
3533     case OPTION_SWAPE:
3534     case OPTION_RTSC:
3535       break;
3536 
3537     default:
3538       return 0;
3539     }
3540 
3541   return 1;
3542 }
3543 
3544 /* Display the list of cpu names for use in the help text.  */
3545 
3546 static void
arc_show_cpu_list(FILE * stream)3547 arc_show_cpu_list (FILE *stream)
3548 {
3549   int i, offset;
3550   static const char *space_buf = "                          ";
3551 
3552   fprintf (stream, "%s", space_buf);
3553   offset = strlen (space_buf);
3554   for (i = 0; cpu_types[i].name != NULL; ++i)
3555     {
3556       bool last = (cpu_types[i + 1].name == NULL);
3557 
3558       /* If displaying the new cpu name string, and the ', ' (for all
3559          but the last one) will take us past a target width of 80
3560          characters, then it's time for a new line.  */
3561       if (offset + strlen (cpu_types[i].name) + (last ? 0 : 2) > 80)
3562         {
3563           fprintf (stream, "\n%s", space_buf);
3564           offset = strlen (space_buf);
3565         }
3566 
3567       fprintf (stream, "%s%s", cpu_types[i].name, (last ? "\n" : ", "));
3568       offset += strlen (cpu_types [i].name) + (last ? 0 : 2);
3569     }
3570 }
3571 
3572 void
md_show_usage(FILE * stream)3573 md_show_usage (FILE *stream)
3574 {
3575   fprintf (stream, _("ARC-specific assembler options:\n"));
3576 
3577   fprintf (stream, "  -mcpu=<cpu name>\t  (default: %s), assemble for"
3578            " CPU <cpu name>, one of:\n", TARGET_WITH_CPU);
3579   arc_show_cpu_list (stream);
3580   fprintf (stream, "\n");
3581   fprintf (stream, "  -mA6/-mARC600/-mARC601  same as -mcpu=arc600\n");
3582   fprintf (stream, "  -mA7/-mARC700\t\t  same as -mcpu=arc700\n");
3583   fprintf (stream, "  -mEM\t\t\t  same as -mcpu=arcem\n");
3584   fprintf (stream, "  -mHS\t\t\t  same as -mcpu=archs\n");
3585 
3586   fprintf (stream, "  -mnps400\t\t  enable NPS-400 extended instructions\n");
3587   fprintf (stream, "  -mspfp\t\t  enable single-precision floating point"
3588 	   " instructions\n");
3589   fprintf (stream, "  -mdpfp\t\t  enable double-precision floating point"
3590 	   " instructions\n");
3591   fprintf (stream, "  -mfpuda\t\t  enable double-precision assist floating "
3592                    "point\n\t\t\t  instructions for ARC EM\n");
3593 
3594   fprintf (stream,
3595 	   "  -mcode-density\t  enable code density option for ARC EM\n");
3596 
3597   fprintf (stream, _("\
3598   -EB                     assemble code for a big-endian cpu\n"));
3599   fprintf (stream, _("\
3600   -EL                     assemble code for a little-endian cpu\n"));
3601   fprintf (stream, _("\
3602   -mrelax                 enable relaxation\n"));
3603 
3604   fprintf (stream, _("The following ARC-specific assembler options are "
3605                      "deprecated and are accepted\nfor compatibility only:\n"));
3606 
3607   fprintf (stream, _("  -mEA\n"
3608                      "  -mbarrel-shifter\n"
3609                      "  -mbarrel_shifter\n"
3610                      "  -mcrc\n"
3611                      "  -mdsp-packa\n"
3612                      "  -mdsp_packa\n"
3613                      "  -mdvbf\n"
3614                      "  -mld-extension-reg-mask\n"
3615                      "  -mlock\n"
3616                      "  -mmac-24\n"
3617                      "  -mmac-d16\n"
3618                      "  -mmac_24\n"
3619                      "  -mmac_d16\n"
3620                      "  -mmin-max\n"
3621                      "  -mmin_max\n"
3622                      "  -mmul64\n"
3623                      "  -mno-mpy\n"
3624                      "  -mnorm\n"
3625                      "  -mrtsc\n"
3626                      "  -msimd\n"
3627                      "  -mswap\n"
3628                      "  -mswape\n"
3629                      "  -mtelephony\n"
3630 		     "  -muser-mode-only\n"
3631                      "  -mxy\n"));
3632 }
3633 
3634 /* Find the proper relocation for the given opcode.  */
3635 
3636 static extended_bfd_reloc_code_real_type
find_reloc(const char * name,const char * opcodename,const struct arc_flags * pflags,int nflg,extended_bfd_reloc_code_real_type reloc)3637 find_reloc (const char *name,
3638 	    const char *opcodename,
3639 	    const struct arc_flags *pflags,
3640 	    int nflg,
3641 	    extended_bfd_reloc_code_real_type reloc)
3642 {
3643   unsigned int i;
3644   int j;
3645   bool found_flag, tmp;
3646   extended_bfd_reloc_code_real_type ret = BFD_RELOC_UNUSED;
3647 
3648   for (i = 0; i < arc_num_equiv_tab; i++)
3649     {
3650       const struct arc_reloc_equiv_tab *r = &arc_reloc_equiv[i];
3651 
3652       /* Find the entry.  */
3653       if (strcmp (name, r->name))
3654 	continue;
3655       if (r->mnemonic && (strcmp (r->mnemonic, opcodename)))
3656 	continue;
3657       if (r->flags[0])
3658 	{
3659 	  if (!nflg)
3660 	    continue;
3661 	  found_flag = false;
3662 	  unsigned * psflg = (unsigned *)r->flags;
3663 	  do
3664 	    {
3665 	      tmp = false;
3666 	      for (j = 0; j < nflg; j++)
3667 		if (!strcmp (pflags[j].name,
3668 			     arc_flag_operands[*psflg].name))
3669 		  {
3670 		    tmp = true;
3671 		    break;
3672 		  }
3673 	      if (!tmp)
3674 		{
3675 		  found_flag = false;
3676 		  break;
3677 		}
3678 	      else
3679 		{
3680 		  found_flag = true;
3681 		}
3682 	      ++ psflg;
3683 	    } while (*psflg);
3684 
3685 	  if (!found_flag)
3686 	    continue;
3687 	}
3688 
3689       if (reloc != r->oldreloc)
3690 	continue;
3691       /* Found it.  */
3692       ret = r->newreloc;
3693       break;
3694     }
3695 
3696   if (ret == BFD_RELOC_UNUSED)
3697     as_bad (_("Unable to find %s relocation for instruction %s"),
3698 	    name, opcodename);
3699   return ret;
3700 }
3701 
3702 /* All the symbol types that are allowed to be used for
3703    relaxation.  */
3704 
3705 static bool
may_relax_expr(expressionS tok)3706 may_relax_expr (expressionS tok)
3707 {
3708   /* Check if we have unrelaxable relocs.  */
3709   switch (tok.X_md)
3710     {
3711     default:
3712       break;
3713     case O_plt:
3714       return false;
3715     }
3716 
3717   switch (tok.X_op)
3718     {
3719     case O_symbol:
3720     case O_multiply:
3721     case O_divide:
3722     case O_modulus:
3723     case O_add:
3724     case O_subtract:
3725       break;
3726 
3727     default:
3728       return false;
3729     }
3730   return true;
3731 }
3732 
3733 /* Checks if flags are in line with relaxable insn.  */
3734 
3735 static bool
relaxable_flag(const struct arc_relaxable_ins * ins,const struct arc_flags * pflags,int nflgs)3736 relaxable_flag (const struct arc_relaxable_ins *ins,
3737 		const struct arc_flags *pflags,
3738 		int nflgs)
3739 {
3740   unsigned flag_class,
3741     flag,
3742     flag_class_idx = 0,
3743     flag_idx = 0;
3744 
3745   const struct arc_flag_operand *flag_opand;
3746   int i, counttrue = 0;
3747 
3748   /* Iterate through flags classes.  */
3749   while ((flag_class = ins->flag_classes[flag_class_idx]) != 0)
3750     {
3751       /* Iterate through flags in flag class.  */
3752       while ((flag = arc_flag_classes[flag_class].flags[flag_idx])
3753 	     != 0)
3754 	{
3755 	  flag_opand = &arc_flag_operands[flag];
3756 	  /* Iterate through flags in ins to compare.  */
3757 	  for (i = 0; i < nflgs; ++i)
3758 	    {
3759 	      if (strcmp (flag_opand->name, pflags[i].name) == 0)
3760 		++counttrue;
3761 	    }
3762 
3763 	  ++flag_idx;
3764 	}
3765 
3766       ++flag_class_idx;
3767       flag_idx = 0;
3768     }
3769 
3770   /* If counttrue == nflgs, then all flags have been found.  */
3771   return counttrue == nflgs;
3772 }
3773 
3774 /* Checks if operands are in line with relaxable insn.  */
3775 
3776 static bool
relaxable_operand(const struct arc_relaxable_ins * ins,const expressionS * tok,int ntok)3777 relaxable_operand (const struct arc_relaxable_ins *ins,
3778 		   const expressionS *tok,
3779 		   int ntok)
3780 {
3781   const enum rlx_operand_type *operand = &ins->operands[0];
3782   int i = 0;
3783 
3784   while (*operand != EMPTY)
3785     {
3786       const expressionS *epr = &tok[i];
3787 
3788       if (i != 0 && i >= ntok)
3789 	return false;
3790 
3791       switch (*operand)
3792 	{
3793 	case IMMEDIATE:
3794 	  if (!(epr->X_op == O_multiply
3795 		|| epr->X_op == O_divide
3796 		|| epr->X_op == O_modulus
3797 		|| epr->X_op == O_add
3798 		|| epr->X_op == O_subtract
3799 		|| epr->X_op == O_symbol))
3800 	    return false;
3801 	  break;
3802 
3803 	case REGISTER_DUP:
3804 	  if ((i <= 0)
3805 	      || (epr->X_add_number != tok[i - 1].X_add_number))
3806 	    return false;
3807 	  /* Fall through.  */
3808 	case REGISTER:
3809 	  if (epr->X_op != O_register)
3810 	    return false;
3811 	  break;
3812 
3813 	case REGISTER_S:
3814 	  if (epr->X_op != O_register)
3815 	    return false;
3816 
3817 	  switch (epr->X_add_number)
3818 	    {
3819 	    case 0: case 1: case 2: case 3:
3820 	    case 12: case 13: case 14: case 15:
3821 	      break;
3822 	    default:
3823 	      return false;
3824 	    }
3825 	  break;
3826 
3827 	case REGISTER_NO_GP:
3828 	  if ((epr->X_op != O_register)
3829 	      || (epr->X_add_number == 26)) /* 26 is the gp register.  */
3830 	    return false;
3831 	  break;
3832 
3833 	case BRACKET:
3834 	  if (epr->X_op != O_bracket)
3835 	    return false;
3836 	  break;
3837 
3838 	default:
3839 	  /* Don't understand, bail out.  */
3840 	  return false;
3841 	  break;
3842 	}
3843 
3844       ++i;
3845       operand = &ins->operands[i];
3846     }
3847 
3848   return i == ntok;
3849 }
3850 
3851 /* Return TRUE if this OPDCODE is a candidate for relaxation.  */
3852 
3853 static bool
relax_insn_p(const struct arc_opcode * opcode,const expressionS * tok,int ntok,const struct arc_flags * pflags,int nflg)3854 relax_insn_p (const struct arc_opcode *opcode,
3855 	      const expressionS *tok,
3856 	      int ntok,
3857 	      const struct arc_flags *pflags,
3858 	      int nflg)
3859 {
3860   unsigned i;
3861   bool rv = false;
3862 
3863   /* Check the relaxation table.  */
3864   for (i = 0; i < arc_num_relaxable_ins && relaxation_state; ++i)
3865     {
3866       const struct arc_relaxable_ins *arc_rlx_ins = &arc_relaxable_insns[i];
3867 
3868       if ((strcmp (opcode->name, arc_rlx_ins->mnemonic_r) == 0)
3869 	  && may_relax_expr (tok[arc_rlx_ins->opcheckidx])
3870 	  && relaxable_operand (arc_rlx_ins, tok, ntok)
3871 	  && relaxable_flag (arc_rlx_ins, pflags, nflg))
3872 	{
3873 	  rv = true;
3874 	  frag_now->fr_subtype = arc_relaxable_insns[i].subtype;
3875 	  memcpy (&frag_now->tc_frag_data.tok, tok,
3876 		sizeof (expressionS) * ntok);
3877 	  memcpy (&frag_now->tc_frag_data.pflags, pflags,
3878 		sizeof (struct arc_flags) * nflg);
3879 	  frag_now->tc_frag_data.nflg = nflg;
3880 	  frag_now->tc_frag_data.ntok = ntok;
3881 	  break;
3882 	}
3883     }
3884 
3885   return rv;
3886 }
3887 
3888 /* Turn an opcode description and a set of arguments into
3889    an instruction and a fixup.  */
3890 
3891 static void
assemble_insn(const struct arc_opcode * opcode,const expressionS * tok,int ntok,const struct arc_flags * pflags,int nflg,struct arc_insn * insn)3892 assemble_insn (const struct arc_opcode *opcode,
3893 	       const expressionS *tok,
3894 	       int ntok,
3895 	       const struct arc_flags *pflags,
3896 	       int nflg,
3897 	       struct arc_insn *insn)
3898 {
3899   const expressionS *reloc_exp = NULL;
3900   unsigned long long image;
3901   const unsigned char *argidx;
3902   int i;
3903   int tokidx = 0;
3904   unsigned char pcrel = 0;
3905   bool needGOTSymbol;
3906   bool has_delay_slot = false;
3907   extended_bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
3908 
3909   memset (insn, 0, sizeof (*insn));
3910   image = opcode->opcode;
3911 
3912   pr_debug ("%s:%d: assemble_insn: %s using opcode %llx\n",
3913 	    frag_now->fr_file, frag_now->fr_line, opcode->name,
3914 	    opcode->opcode);
3915 
3916   /* Handle operands.  */
3917   for (argidx = opcode->operands; *argidx; ++argidx)
3918     {
3919       const struct arc_operand *operand = &arc_operands[*argidx];
3920       const expressionS *t = (const expressionS *) 0;
3921 
3922       if (ARC_OPERAND_IS_FAKE (operand))
3923 	continue;
3924 
3925       if (operand->flags & ARC_OPERAND_DUPLICATE)
3926 	{
3927 	  /* Duplicate operand, already inserted.  */
3928 	  tokidx ++;
3929 	  continue;
3930 	}
3931 
3932       if (tokidx >= ntok)
3933 	{
3934 	  abort ();
3935 	}
3936       else
3937 	t = &tok[tokidx++];
3938 
3939       /* Regardless if we have a reloc or not mark the instruction
3940 	 limm if it is the case.  */
3941       if (operand->flags & ARC_OPERAND_LIMM)
3942 	insn->has_limm = true;
3943 
3944       switch (t->X_op)
3945 	{
3946 	case O_register:
3947 	  image = insert_operand (image, operand, regno (t->X_add_number),
3948 				  NULL, 0);
3949 	  break;
3950 
3951 	case O_constant:
3952 	  image = insert_operand (image, operand, t->X_add_number, NULL, 0);
3953 	  reloc_exp = t;
3954 	  if (operand->flags & ARC_OPERAND_LIMM)
3955 	    insn->limm = t->X_add_number;
3956 	  break;
3957 
3958 	case O_bracket:
3959         case O_colon:
3960         case O_addrtype:
3961 	  /* Ignore brackets, colons, and address types.  */
3962 	  break;
3963 
3964 	case O_absent:
3965 	  gas_assert (operand->flags & ARC_OPERAND_IGNORE);
3966 	  break;
3967 
3968 	case O_subtract:
3969 	  /* Maybe register range.  */
3970 	  if ((t->X_add_number == 0)
3971 	      && contains_register (t->X_add_symbol)
3972 	      && contains_register (t->X_op_symbol))
3973 	    {
3974 	      int regs;
3975 
3976 	      regs = get_register (t->X_add_symbol);
3977 	      regs <<= 16;
3978 	      regs |= get_register (t->X_op_symbol);
3979 	      image = insert_operand (image, operand, regs, NULL, 0);
3980 	      break;
3981 	    }
3982 	  /* Fall through.  */
3983 
3984 	default:
3985 	  /* This operand needs a relocation.  */
3986 	  needGOTSymbol = false;
3987 
3988 	  switch (t->X_md)
3989 	    {
3990 	    case O_plt:
3991 	      if (opcode->insn_class == JUMP)
3992 		as_bad (_("Unable to use @plt relocation for insn %s"),
3993 			opcode->name);
3994 	      needGOTSymbol = true;
3995 	      reloc = find_reloc ("plt", opcode->name,
3996 				  pflags, nflg,
3997 				  operand->default_reloc);
3998 	      break;
3999 
4000 	    case O_gotoff:
4001 	    case O_gotpc:
4002 	      needGOTSymbol = true;
4003 	      reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
4004 	      break;
4005 	    case O_pcl:
4006 	      if (operand->flags & ARC_OPERAND_LIMM)
4007 		{
4008 		  reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
4009 		  if (arc_opcode_len (opcode) == 2
4010 		      || opcode->insn_class == JUMP)
4011 		    as_bad (_("Unable to use @pcl relocation for insn %s"),
4012 			    opcode->name);
4013 		}
4014 	      else
4015 		{
4016 		  /* This is a relaxed operand which initially was
4017 		     limm, choose whatever we have defined in the
4018 		     opcode as reloc.  */
4019 		  reloc = operand->default_reloc;
4020 		}
4021 	      break;
4022 	    case O_sda:
4023 	      reloc = find_reloc ("sda", opcode->name,
4024 				  pflags, nflg,
4025 				  operand->default_reloc);
4026 	      break;
4027 	    case O_tlsgd:
4028 	    case O_tlsie:
4029 	      needGOTSymbol = true;
4030 	      /* Fall-through.  */
4031 
4032 	    case O_tpoff:
4033 	    case O_dtpoff:
4034 	      reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
4035 	      break;
4036 
4037 	    case O_tpoff9: /*FIXME! Check for the conditionality of
4038 			     the insn.  */
4039 	    case O_dtpoff9: /*FIXME! Check for the conditionality of
4040 			      the insn.  */
4041 	      as_bad (_("TLS_*_S9 relocs are not supported yet"));
4042 	      break;
4043 
4044 	    default:
4045 	      /* Just consider the default relocation.  */
4046 	      reloc = operand->default_reloc;
4047 	      break;
4048 	    }
4049 
4050 	  if (needGOTSymbol && (GOT_symbol == NULL))
4051 	    GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
4052 
4053 	  reloc_exp = t;
4054 
4055 #if 0
4056 	  if (reloc > 0)
4057 	    {
4058 	      /* sanity checks.  */
4059 	      reloc_howto_type *reloc_howto
4060 		= bfd_reloc_type_lookup (stdoutput,
4061 					 (bfd_reloc_code_real_type) reloc);
4062 	      unsigned reloc_bitsize = reloc_howto->bitsize;
4063 	      if (reloc_howto->rightshift)
4064 		reloc_bitsize -= reloc_howto->rightshift;
4065 	      if (reloc_bitsize != operand->bits)
4066 		{
4067 		  as_bad (_("invalid relocation %s for field"),
4068 			  bfd_get_reloc_code_name (reloc));
4069 		  return;
4070 		}
4071 	    }
4072 #endif
4073 	  if (insn->nfixups >= MAX_INSN_FIXUPS)
4074 	    as_fatal (_("too many fixups"));
4075 
4076 	  struct arc_fixup *fixup;
4077 	  fixup = &insn->fixups[insn->nfixups++];
4078 	  fixup->exp = *t;
4079 	  fixup->reloc = reloc;
4080 	  if ((int) reloc < 0)
4081 	    pcrel = (operand->flags & ARC_OPERAND_PCREL) ? 1 : 0;
4082 	  else
4083 	    {
4084 	      reloc_howto_type *reloc_howto =
4085 		bfd_reloc_type_lookup (stdoutput,
4086 				       (bfd_reloc_code_real_type) fixup->reloc);
4087 	      pcrel = reloc_howto->pc_relative;
4088 	    }
4089 	  fixup->pcrel = pcrel;
4090 	  fixup->islong = (operand->flags & ARC_OPERAND_LIMM) != 0;
4091 	  break;
4092 	}
4093     }
4094 
4095   /* Handle flags.  */
4096   for (i = 0; i < nflg; i++)
4097     {
4098       const struct arc_flag_operand *flg_operand = pflags[i].flgp;
4099 
4100       /* Check if the instruction has a delay slot.  */
4101       if (!strcmp (flg_operand->name, "d"))
4102 	has_delay_slot = true;
4103 
4104       /* There is an exceptional case when we cannot insert a flag just as
4105 	 it is.  On ARCv2 the '.t' and '.nt' flags must be handled in
4106 	 relation with the relative address.  Unfortunately, some of the
4107 	 ARC700 extensions (NPS400) also have a '.nt' flag that should be
4108 	 handled in the normal way.
4109 
4110 	 Flag operands don't have an architecture field, so we can't
4111 	 directly validate that FLAG_OPERAND is valid for the current
4112 	 architecture, what we do instead is just validate that we're
4113 	 assembling for an ARCv2 architecture.  */
4114       if ((selected_cpu.flags & ARC_OPCODE_ARCV2)
4115 	  && (!strcmp (flg_operand->name, "t")
4116 	      || !strcmp (flg_operand->name, "nt")))
4117 	{
4118 	  unsigned bitYoperand = 0;
4119 	  /* FIXME! move selection bbit/brcc in arc-opc.c.  */
4120 	  if (!strcmp (flg_operand->name, "t"))
4121 	    if (!strcmp (opcode->name, "bbit0")
4122 		|| !strcmp (opcode->name, "bbit1"))
4123 	      bitYoperand = arc_NToperand;
4124 	    else
4125 	      bitYoperand = arc_Toperand;
4126 	  else
4127 	    if (!strcmp (opcode->name, "bbit0")
4128 		|| !strcmp (opcode->name, "bbit1"))
4129 	      bitYoperand = arc_Toperand;
4130 	    else
4131 	      bitYoperand = arc_NToperand;
4132 
4133 	  gas_assert (reloc_exp != NULL);
4134 	  if (reloc_exp->X_op == O_constant)
4135 	    {
4136 	      /* Check if we have a constant and solved it
4137 		 immediately.  */
4138 	      offsetT val = reloc_exp->X_add_number;
4139 	      image |= insert_operand (image, &arc_operands[bitYoperand],
4140 				       val, NULL, 0);
4141 	    }
4142 	  else
4143 	    {
4144 	      struct arc_fixup *fixup;
4145 
4146 	      if (insn->nfixups >= MAX_INSN_FIXUPS)
4147 		as_fatal (_("too many fixups"));
4148 
4149 	      fixup = &insn->fixups[insn->nfixups++];
4150 	      fixup->exp = *reloc_exp;
4151 	      fixup->reloc = -bitYoperand;
4152 	      fixup->pcrel = pcrel;
4153 	      fixup->islong = false;
4154 	    }
4155 	}
4156       else
4157 	image |= (flg_operand->code & ((1 << flg_operand->bits) - 1))
4158 	  << flg_operand->shift;
4159     }
4160 
4161   insn->relax = relax_insn_p (opcode, tok, ntok, pflags, nflg);
4162 
4163   /* Instruction length.  */
4164   insn->len = arc_opcode_len (opcode);
4165 
4166   insn->insn = image;
4167 
4168   /* Update last insn status.  */
4169   arc_last_insns[1]		   = arc_last_insns[0];
4170   arc_last_insns[0].opcode	   = opcode;
4171   arc_last_insns[0].has_limm	   = insn->has_limm;
4172   arc_last_insns[0].has_delay_slot = has_delay_slot;
4173 
4174   /* Check if the current instruction is legally used.  */
4175   if (arc_last_insns[1].has_delay_slot
4176       && is_br_jmp_insn_p (arc_last_insns[0].opcode))
4177     as_bad (_("Insn %s has a jump/branch instruction %s in its delay slot."),
4178 	    arc_last_insns[1].opcode->name,
4179 	    arc_last_insns[0].opcode->name);
4180   if (arc_last_insns[1].has_delay_slot
4181       && arc_last_insns[0].has_limm)
4182     as_bad (_("Insn %s has an instruction %s with limm in its delay slot."),
4183 	    arc_last_insns[1].opcode->name,
4184 	    arc_last_insns[0].opcode->name);
4185 }
4186 
4187 void
arc_handle_align(fragS * fragP)4188 arc_handle_align (fragS* fragP)
4189 {
4190   if ((fragP)->fr_type == rs_align_code)
4191     {
4192       char *dest = (fragP)->fr_literal + (fragP)->fr_fix;
4193       valueT count = ((fragP)->fr_next->fr_address
4194 		      - (fragP)->fr_address - (fragP)->fr_fix);
4195 
4196       (fragP)->fr_var = 2;
4197 
4198       if (count & 1)/* Padding in the gap till the next 2-byte
4199 		       boundary with 0s.  */
4200 	{
4201 	  (fragP)->fr_fix++;
4202 	  *dest++ = 0;
4203 	}
4204       /* Writing nop_s.  */
4205       md_number_to_chars (dest, NOP_OPCODE_S, 2);
4206     }
4207 }
4208 
4209 /* Here we decide which fixups can be adjusted to make them relative
4210    to the beginning of the section instead of the symbol.  Basically
4211    we need to make sure that the dynamic relocations are done
4212    correctly, so in some cases we force the original symbol to be
4213    used.  */
4214 
4215 int
tc_arc_fix_adjustable(fixS * fixP)4216 tc_arc_fix_adjustable (fixS *fixP)
4217 {
4218 
4219   /* Prevent all adjustments to global symbols.  */
4220   if (S_IS_EXTERNAL (fixP->fx_addsy))
4221     return 0;
4222   if (S_IS_WEAK (fixP->fx_addsy))
4223     return 0;
4224 
4225   /* Adjust_reloc_syms doesn't know about the GOT.  */
4226   switch (fixP->fx_r_type)
4227     {
4228     case BFD_RELOC_ARC_GOTPC32:
4229     case BFD_RELOC_ARC_PLT32:
4230     case BFD_RELOC_ARC_S25H_PCREL_PLT:
4231     case BFD_RELOC_ARC_S21H_PCREL_PLT:
4232     case BFD_RELOC_ARC_S25W_PCREL_PLT:
4233     case BFD_RELOC_ARC_S21W_PCREL_PLT:
4234       return 0;
4235 
4236     default:
4237       break;
4238     }
4239 
4240   return 1;
4241 }
4242 
4243 /* Compute the reloc type of an expression EXP.  */
4244 
4245 static void
arc_check_reloc(expressionS * exp,bfd_reloc_code_real_type * r_type_p)4246 arc_check_reloc (expressionS *exp,
4247 		 bfd_reloc_code_real_type *r_type_p)
4248 {
4249   if (*r_type_p == BFD_RELOC_32
4250       && exp->X_op == O_subtract
4251       && exp->X_op_symbol != NULL
4252       && S_GET_SEGMENT (exp->X_op_symbol) == now_seg)
4253     *r_type_p = BFD_RELOC_ARC_32_PCREL;
4254 }
4255 
4256 
4257 /* Add expression EXP of SIZE bytes to offset OFF of fragment FRAG.  */
4258 
4259 void
arc_cons_fix_new(fragS * frag,int off,int size,expressionS * exp,bfd_reloc_code_real_type r_type)4260 arc_cons_fix_new (fragS *frag,
4261 		  int off,
4262 		  int size,
4263 		  expressionS *exp,
4264 		  bfd_reloc_code_real_type r_type)
4265 {
4266   r_type = BFD_RELOC_UNUSED;
4267 
4268   switch (size)
4269     {
4270     case 1:
4271       r_type = BFD_RELOC_8;
4272       break;
4273 
4274     case 2:
4275       r_type = BFD_RELOC_16;
4276       break;
4277 
4278     case 3:
4279       r_type = BFD_RELOC_24;
4280       break;
4281 
4282     case 4:
4283       r_type = BFD_RELOC_32;
4284       arc_check_reloc (exp, &r_type);
4285       break;
4286 
4287     case 8:
4288       r_type = BFD_RELOC_64;
4289       break;
4290 
4291     default:
4292       as_bad (_("unsupported BFD relocation size %u"), size);
4293       r_type = BFD_RELOC_UNUSED;
4294     }
4295 
4296   fix_new_exp (frag, off, size, exp, 0, r_type);
4297 }
4298 
4299 /* The actual routine that checks the ZOL conditions.  */
4300 
4301 static void
check_zol(symbolS * s)4302 check_zol (symbolS *s)
4303 {
4304   switch (selected_cpu.mach)
4305     {
4306     case bfd_mach_arc_arcv2:
4307       if (selected_cpu.flags & ARC_OPCODE_ARCv2EM)
4308 	return;
4309 
4310       if (is_br_jmp_insn_p (arc_last_insns[0].opcode)
4311 	  || arc_last_insns[1].has_delay_slot)
4312 	as_bad (_("Jump/Branch instruction detected at the end of the ZOL label @%s"),
4313 		S_GET_NAME (s));
4314 
4315       break;
4316     case bfd_mach_arc_arc600:
4317 
4318       if (is_kernel_insn_p (arc_last_insns[0].opcode))
4319 	as_bad (_("Kernel instruction detected at the end of the ZOL label @%s"),
4320 		S_GET_NAME (s));
4321 
4322       if (arc_last_insns[0].has_limm
4323 	  && is_br_jmp_insn_p (arc_last_insns[0].opcode))
4324 	as_bad (_("A jump instruction with long immediate detected at the \
4325 end of the ZOL label @%s"), S_GET_NAME (s));
4326 
4327       /* Fall through.  */
4328     case bfd_mach_arc_arc700:
4329       if (arc_last_insns[0].has_delay_slot)
4330 	as_bad (_("An illegal use of delay slot detected at the end of the ZOL label @%s"),
4331 		S_GET_NAME (s));
4332 
4333       break;
4334     default:
4335       break;
4336     }
4337 }
4338 
4339 /* If ZOL end check the last two instruction for illegals.  */
4340 void
arc_frob_label(symbolS * sym)4341 arc_frob_label (symbolS * sym)
4342 {
4343   if (ARC_GET_FLAG (sym) & ARC_FLAG_ZOL)
4344     check_zol (sym);
4345 
4346   dwarf2_emit_label (sym);
4347 }
4348 
4349 /* Used because generic relaxation assumes a pc-rel value whilst we
4350    also relax instructions that use an absolute value resolved out of
4351    relative values (if that makes any sense).  An example: 'add r1,
4352    r2, @.L2 - .'  The symbols . and @.L2 are relative to the section
4353    but if they're in the same section we can subtract the section
4354    offset relocation which ends up in a resolved value.  So if @.L2 is
4355    .text + 0x50 and . is .text + 0x10, we can say that .text + 0x50 -
4356    .text + 0x40 = 0x10.  */
4357 int
arc_pcrel_adjust(fragS * fragP)4358 arc_pcrel_adjust (fragS *fragP)
4359 {
4360   pr_debug ("arc_pcrel_adjust: address=%ld, fix=%ld, PCrel %s\n",
4361 	    fragP->fr_address, fragP->fr_fix,
4362 	    fragP->tc_frag_data.pcrel ? "Y" : "N");
4363 
4364   if (!fragP->tc_frag_data.pcrel)
4365     return fragP->fr_address + fragP->fr_fix;
4366 
4367   /* Take into account the PCL rounding.  */
4368   return (fragP->fr_address + fragP->fr_fix) & 0x03;
4369 }
4370 
4371 /* Initialize the DWARF-2 unwind information for this procedure.  */
4372 
4373 void
tc_arc_frame_initial_instructions(void)4374 tc_arc_frame_initial_instructions (void)
4375 {
4376   /* Stack pointer is register 28.  */
4377   cfi_add_CFA_def_cfa (28, 0);
4378 }
4379 
4380 int
tc_arc_regname_to_dw2regnum(char * regname)4381 tc_arc_regname_to_dw2regnum (char *regname)
4382 {
4383   struct symbol *sym;
4384 
4385   sym = str_hash_find (arc_reg_hash, regname);
4386   if (sym)
4387     return S_GET_VALUE (sym);
4388 
4389   return -1;
4390 }
4391 
4392 /* Adjust the symbol table.  Delete found AUX register symbols.  */
4393 
4394 void
arc_adjust_symtab(void)4395 arc_adjust_symtab (void)
4396 {
4397   symbolS * sym;
4398 
4399   for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
4400     {
4401       /* I've created a symbol during parsing process.  Now, remove
4402 	 the symbol as it is found to be an AUX register.  */
4403       if (ARC_GET_FLAG (sym) & ARC_FLAG_AUX)
4404 	symbol_remove (sym, &symbol_rootP, &symbol_lastP);
4405     }
4406 
4407   /* Now do generic ELF adjustments.  */
4408   elf_adjust_symtab ();
4409 }
4410 
4411 static void
tokenize_extinsn(extInstruction_t * einsn)4412 tokenize_extinsn (extInstruction_t *einsn)
4413 {
4414   char *p, c;
4415   char *insn_name;
4416   unsigned char major_opcode;
4417   unsigned char sub_opcode;
4418   unsigned char syntax_class = 0;
4419   unsigned char syntax_class_modifiers = 0;
4420   unsigned char suffix_class = 0;
4421   unsigned int i;
4422 
4423   SKIP_WHITESPACE ();
4424 
4425   /* 1st: get instruction name.  */
4426   p = input_line_pointer;
4427   c = get_symbol_name (&p);
4428 
4429   insn_name = xstrdup (p);
4430   restore_line_pointer (c);
4431 
4432   /* Convert to lower case.  */
4433   for (p = insn_name; *p; ++p)
4434     *p = TOLOWER (*p);
4435 
4436   /* 2nd: get major opcode.  */
4437   if (*input_line_pointer != ',')
4438     {
4439       as_bad (_("expected comma after instruction name"));
4440       ignore_rest_of_line ();
4441       return;
4442     }
4443   input_line_pointer++;
4444   major_opcode = get_absolute_expression ();
4445 
4446   /* 3rd: get sub-opcode.  */
4447   SKIP_WHITESPACE ();
4448 
4449   if (*input_line_pointer != ',')
4450     {
4451       as_bad (_("expected comma after major opcode"));
4452       ignore_rest_of_line ();
4453       return;
4454     }
4455   input_line_pointer++;
4456   sub_opcode = get_absolute_expression ();
4457 
4458   /* 4th: get suffix class.  */
4459   SKIP_WHITESPACE ();
4460 
4461   if (*input_line_pointer != ',')
4462     {
4463       as_bad ("expected comma after sub opcode");
4464       ignore_rest_of_line ();
4465       return;
4466     }
4467   input_line_pointer++;
4468 
4469   while (1)
4470     {
4471       SKIP_WHITESPACE ();
4472 
4473       for (i = 0; i < ARRAY_SIZE (suffixclass); i++)
4474 	{
4475 	  if (!strncmp (suffixclass[i].name, input_line_pointer,
4476 			suffixclass[i].len))
4477 	    {
4478 	      suffix_class |= suffixclass[i].attr_class;
4479 	      input_line_pointer += suffixclass[i].len;
4480 	      break;
4481 	    }
4482 	}
4483 
4484       if (i == ARRAY_SIZE (suffixclass))
4485 	{
4486 	  as_bad ("invalid suffix class");
4487 	  ignore_rest_of_line ();
4488 	  return;
4489 	}
4490 
4491       SKIP_WHITESPACE ();
4492 
4493       if (*input_line_pointer == '|')
4494 	input_line_pointer++;
4495       else
4496 	break;
4497     }
4498 
4499   /* 5th: get syntax class and syntax class modifiers.  */
4500   if (*input_line_pointer != ',')
4501     {
4502       as_bad ("expected comma after suffix class");
4503       ignore_rest_of_line ();
4504       return;
4505     }
4506   input_line_pointer++;
4507 
4508   while (1)
4509     {
4510       SKIP_WHITESPACE ();
4511 
4512       for (i = 0; i < ARRAY_SIZE (syntaxclassmod); i++)
4513 	{
4514 	  if (!strncmp (syntaxclassmod[i].name,
4515 			input_line_pointer,
4516 			syntaxclassmod[i].len))
4517 	    {
4518 	      syntax_class_modifiers |= syntaxclassmod[i].attr_class;
4519 	      input_line_pointer += syntaxclassmod[i].len;
4520 	      break;
4521 	    }
4522 	}
4523 
4524       if (i == ARRAY_SIZE (syntaxclassmod))
4525 	{
4526 	  for (i = 0; i < ARRAY_SIZE (syntaxclass); i++)
4527 	    {
4528 	      if (!strncmp (syntaxclass[i].name,
4529 			    input_line_pointer,
4530 			    syntaxclass[i].len))
4531 		{
4532 		  syntax_class |= syntaxclass[i].attr_class;
4533 		  input_line_pointer += syntaxclass[i].len;
4534 		  break;
4535 		}
4536 	    }
4537 
4538 	  if (i == ARRAY_SIZE (syntaxclass))
4539 	    {
4540 	      as_bad ("missing syntax class");
4541 	      ignore_rest_of_line ();
4542 	      return;
4543 	    }
4544 	}
4545 
4546       SKIP_WHITESPACE ();
4547 
4548       if (*input_line_pointer == '|')
4549 	input_line_pointer++;
4550       else
4551 	break;
4552     }
4553 
4554   demand_empty_rest_of_line ();
4555 
4556   einsn->name   = insn_name;
4557   einsn->major  = major_opcode;
4558   einsn->minor  = sub_opcode;
4559   einsn->syntax = syntax_class;
4560   einsn->modsyn = syntax_class_modifiers;
4561   einsn->suffix = suffix_class;
4562   einsn->flags  = syntax_class
4563     | (syntax_class_modifiers & ARC_OP1_IMM_IMPLIED ? 0x10 : 0);
4564 }
4565 
4566 /* Generate an extension section.  */
4567 
4568 static int
arc_set_ext_seg(void)4569 arc_set_ext_seg (void)
4570 {
4571   if (!arcext_section)
4572     {
4573       arcext_section = subseg_new (".arcextmap", 0);
4574       bfd_set_section_flags (arcext_section, SEC_READONLY | SEC_HAS_CONTENTS);
4575     }
4576   else
4577     subseg_set (arcext_section, 0);
4578   return 1;
4579 }
4580 
4581 /* Create an extension instruction description in the arc extension
4582    section of the output file.
4583    The structure for an instruction is like this:
4584    [0]: Length of the record.
4585    [1]: Type of the record.
4586 
4587    [2]: Major opcode.
4588    [3]: Sub-opcode.
4589    [4]: Syntax (flags).
4590    [5]+ Name instruction.
4591 
4592    The sequence is terminated by an empty entry.  */
4593 
4594 static void
create_extinst_section(extInstruction_t * einsn)4595 create_extinst_section (extInstruction_t *einsn)
4596 {
4597 
4598   segT old_sec    = now_seg;
4599   int old_subsec  = now_subseg;
4600   char *p;
4601   int name_len    = strlen (einsn->name);
4602 
4603   arc_set_ext_seg ();
4604 
4605   p = frag_more (1);
4606   *p = 5 + name_len + 1;
4607   p = frag_more (1);
4608   *p = EXT_INSTRUCTION;
4609   p = frag_more (1);
4610   *p = einsn->major;
4611   p = frag_more (1);
4612   *p = einsn->minor;
4613   p = frag_more (1);
4614   *p = einsn->flags;
4615   p = frag_more (name_len + 1);
4616   strcpy (p, einsn->name);
4617 
4618   subseg_set (old_sec, old_subsec);
4619 }
4620 
4621 /* Handler .extinstruction pseudo-op.  */
4622 
4623 static void
arc_extinsn(int ignore ATTRIBUTE_UNUSED)4624 arc_extinsn (int ignore ATTRIBUTE_UNUSED)
4625 {
4626   extInstruction_t einsn;
4627   struct arc_opcode *arc_ext_opcodes;
4628   const char *errmsg = NULL;
4629   unsigned char moplow, mophigh;
4630 
4631   memset (&einsn, 0, sizeof (einsn));
4632   tokenize_extinsn (&einsn);
4633 
4634   /* Check if the name is already used.  */
4635   if (arc_find_opcode (einsn.name))
4636     as_warn (_("Pseudocode already used %s"), einsn.name);
4637 
4638   /* Check the opcode ranges.  */
4639   moplow = 0x05;
4640   mophigh = (selected_cpu.flags & (ARC_OPCODE_ARCv2EM
4641                                    | ARC_OPCODE_ARCv2HS)) ? 0x07 : 0x0a;
4642 
4643   if ((einsn.major > mophigh) || (einsn.major < moplow))
4644     as_fatal (_("major opcode not in range [0x%02x - 0x%02x]"), moplow, mophigh);
4645 
4646   if ((einsn.minor > 0x3f) && (einsn.major != 0x0a)
4647       && (einsn.major != 5) && (einsn.major != 9))
4648     as_fatal (_("minor opcode not in range [0x00 - 0x3f]"));
4649 
4650   switch (einsn.syntax & ARC_SYNTAX_MASK)
4651     {
4652     case ARC_SYNTAX_3OP:
4653       if (einsn.modsyn & ARC_OP1_IMM_IMPLIED)
4654 	as_fatal (_("Improper use of OP1_IMM_IMPLIED"));
4655       break;
4656     case ARC_SYNTAX_2OP:
4657     case ARC_SYNTAX_1OP:
4658     case ARC_SYNTAX_NOP:
4659       if (einsn.modsyn & ARC_OP1_MUST_BE_IMM)
4660 	as_fatal (_("Improper use of OP1_MUST_BE_IMM"));
4661       break;
4662     default:
4663       break;
4664     }
4665 
4666   arc_ext_opcodes = arcExtMap_genOpcode (&einsn, selected_cpu.flags, &errmsg);
4667   if (arc_ext_opcodes == NULL)
4668     {
4669       if (errmsg)
4670 	as_fatal ("%s", errmsg);
4671       else
4672 	as_fatal (_("Couldn't generate extension instruction opcodes"));
4673     }
4674   else if (errmsg)
4675     as_warn ("%s", errmsg);
4676 
4677   /* Insert the extension instruction.  */
4678   arc_insert_opcode ((const struct arc_opcode *) arc_ext_opcodes);
4679 
4680   create_extinst_section (&einsn);
4681 }
4682 
4683 static bool
tokenize_extregister(extRegister_t * ereg,int opertype)4684 tokenize_extregister (extRegister_t *ereg, int opertype)
4685 {
4686   char *name;
4687   char *mode;
4688   char c;
4689   char *p;
4690   int number, imode = 0;
4691   bool isCore_p = opertype == EXT_CORE_REGISTER;
4692   bool isReg_p = opertype == EXT_CORE_REGISTER || opertype == EXT_AUX_REGISTER;
4693 
4694   /* 1st: get register name.  */
4695   SKIP_WHITESPACE ();
4696   p = input_line_pointer;
4697   c = get_symbol_name (&p);
4698 
4699   name = xstrdup (p);
4700   restore_line_pointer (c);
4701 
4702   /* 2nd: get register number.  */
4703   SKIP_WHITESPACE ();
4704 
4705   if (*input_line_pointer != ',')
4706     {
4707       as_bad (_("expected comma after name"));
4708       ignore_rest_of_line ();
4709       free (name);
4710       return false;
4711     }
4712   input_line_pointer++;
4713   number = get_absolute_expression ();
4714 
4715   if ((number < 0)
4716       && (opertype != EXT_AUX_REGISTER))
4717     {
4718       as_bad (_("%s second argument cannot be a negative number %d"),
4719 	      isCore_p ? "extCoreRegister's" : "extCondCode's",
4720 	      number);
4721       ignore_rest_of_line ();
4722       free (name);
4723       return false;
4724     }
4725 
4726   if (isReg_p)
4727     {
4728       /* 3rd: get register mode.  */
4729       SKIP_WHITESPACE ();
4730 
4731       if (*input_line_pointer != ',')
4732 	{
4733 	  as_bad (_("expected comma after register number"));
4734 	  ignore_rest_of_line ();
4735 	  free (name);
4736 	  return false;
4737 	}
4738 
4739       input_line_pointer++;
4740       mode = input_line_pointer;
4741 
4742       if (startswith (mode, "r|w"))
4743 	{
4744 	  imode = 0;
4745 	  input_line_pointer += 3;
4746 	}
4747       else if (startswith (mode, "r"))
4748 	{
4749 	  imode = ARC_REGISTER_READONLY;
4750 	  input_line_pointer += 1;
4751 	}
4752       else if (!startswith (mode, "w"))
4753 	{
4754 	  as_bad (_("invalid mode"));
4755 	  ignore_rest_of_line ();
4756 	  free (name);
4757 	  return false;
4758 	}
4759       else
4760 	{
4761 	  imode = ARC_REGISTER_WRITEONLY;
4762 	  input_line_pointer += 1;
4763 	}
4764     }
4765 
4766   if (isCore_p)
4767     {
4768       /* 4th: get core register shortcut.  */
4769       SKIP_WHITESPACE ();
4770       if (*input_line_pointer != ',')
4771 	{
4772 	  as_bad (_("expected comma after register mode"));
4773 	  ignore_rest_of_line ();
4774 	  free (name);
4775 	  return false;
4776 	}
4777 
4778       input_line_pointer++;
4779 
4780       if (startswith (input_line_pointer, "cannot_shortcut"))
4781 	{
4782 	  imode |= ARC_REGISTER_NOSHORT_CUT;
4783 	  input_line_pointer += 15;
4784 	}
4785       else if (!startswith (input_line_pointer, "can_shortcut"))
4786 	{
4787 	  as_bad (_("shortcut designator invalid"));
4788 	  ignore_rest_of_line ();
4789 	  free (name);
4790 	  return false;
4791 	}
4792       else
4793 	{
4794 	  input_line_pointer += 12;
4795 	}
4796     }
4797   demand_empty_rest_of_line ();
4798 
4799   ereg->name = name;
4800   ereg->number = number;
4801   ereg->imode  = imode;
4802   return true;
4803 }
4804 
4805 /* Create an extension register/condition description in the arc
4806    extension section of the output file.
4807 
4808    The structure for an instruction is like this:
4809    [0]: Length of the record.
4810    [1]: Type of the record.
4811 
4812    For core regs and condition codes:
4813    [2]: Value.
4814    [3]+ Name.
4815 
4816    For auxiliary registers:
4817    [2..5]: Value.
4818    [6]+ Name
4819 
4820    The sequence is terminated by an empty entry.  */
4821 
4822 static void
create_extcore_section(extRegister_t * ereg,int opertype)4823 create_extcore_section (extRegister_t *ereg, int opertype)
4824 {
4825   segT old_sec   = now_seg;
4826   int old_subsec = now_subseg;
4827   char *p;
4828   int name_len   = strlen (ereg->name);
4829 
4830   arc_set_ext_seg ();
4831 
4832   switch (opertype)
4833     {
4834     case EXT_COND_CODE:
4835     case EXT_CORE_REGISTER:
4836       p = frag_more (1);
4837       *p = 3 + name_len + 1;
4838       p = frag_more (1);
4839       *p = opertype;
4840       p = frag_more (1);
4841       *p = ereg->number;
4842       break;
4843     case EXT_AUX_REGISTER:
4844       p = frag_more (1);
4845       *p = 6 + name_len + 1;
4846       p = frag_more (1);
4847       *p = EXT_AUX_REGISTER;
4848       p = frag_more (1);
4849       *p = (ereg->number >> 24) & 0xff;
4850       p = frag_more (1);
4851       *p = (ereg->number >> 16) & 0xff;
4852       p = frag_more (1);
4853       *p = (ereg->number >>  8) & 0xff;
4854       p = frag_more (1);
4855       *p = (ereg->number)       & 0xff;
4856       break;
4857     default:
4858       break;
4859     }
4860 
4861   p = frag_more (name_len + 1);
4862   strcpy (p, ereg->name);
4863 
4864   subseg_set (old_sec, old_subsec);
4865 }
4866 
4867 /* Handler .extCoreRegister pseudo-op.  */
4868 
4869 static void
arc_extcorereg(int opertype)4870 arc_extcorereg (int opertype)
4871 {
4872   extRegister_t ereg;
4873   struct arc_aux_reg *auxr;
4874   struct arc_flag_operand *ccode;
4875 
4876   memset (&ereg, 0, sizeof (ereg));
4877   if (!tokenize_extregister (&ereg, opertype))
4878     return;
4879 
4880   switch (opertype)
4881     {
4882     case EXT_CORE_REGISTER:
4883       /* Core register.  */
4884       if (ereg.number > 60)
4885 	as_bad (_("core register %s value (%d) too large"), ereg.name,
4886 		ereg.number);
4887       declare_register (ereg.name, ereg.number);
4888       break;
4889     case EXT_AUX_REGISTER:
4890       /* Auxiliary register.  */
4891       auxr = XNEW (struct arc_aux_reg);
4892       auxr->name = ereg.name;
4893       auxr->cpu = selected_cpu.flags;
4894       auxr->subclass = NONE;
4895       auxr->address = ereg.number;
4896       if (str_hash_insert (arc_aux_hash, auxr->name, auxr, 0) != NULL)
4897 	as_bad (_("duplicate aux register %s"), auxr->name);
4898       break;
4899     case EXT_COND_CODE:
4900       /* Condition code.  */
4901       if (ereg.number > 31)
4902 	as_bad (_("condition code %s value (%d) too large"), ereg.name,
4903 		ereg.number);
4904       ext_condcode.size ++;
4905       ext_condcode.arc_ext_condcode =
4906 	XRESIZEVEC (struct arc_flag_operand, ext_condcode.arc_ext_condcode,
4907 		    ext_condcode.size + 1);
4908 
4909       ccode = ext_condcode.arc_ext_condcode + ext_condcode.size - 1;
4910       ccode->name   = ereg.name;
4911       ccode->code   = ereg.number;
4912       ccode->bits   = 5;
4913       ccode->shift  = 0;
4914       ccode->favail = 0; /* not used.  */
4915       ccode++;
4916       memset (ccode, 0, sizeof (struct arc_flag_operand));
4917       break;
4918     default:
4919       as_bad (_("Unknown extension"));
4920       break;
4921     }
4922   create_extcore_section (&ereg, opertype);
4923 }
4924 
4925 /* Parse a .arc_attribute directive.  */
4926 
4927 static void
arc_attribute(int ignored ATTRIBUTE_UNUSED)4928 arc_attribute (int ignored ATTRIBUTE_UNUSED)
4929 {
4930   int tag = obj_elf_vendor_attribute (OBJ_ATTR_PROC);
4931 
4932   if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
4933     attributes_set_explicitly[tag] = true;
4934 }
4935 
4936 /* Set an attribute if it has not already been set by the user.  */
4937 
4938 static void
arc_set_attribute_int(int tag,int value)4939 arc_set_attribute_int (int tag, int value)
4940 {
4941   if (tag < 1
4942       || tag >= NUM_KNOWN_OBJ_ATTRIBUTES
4943       || !attributes_set_explicitly[tag])
4944     if (!bfd_elf_add_proc_attr_int (stdoutput, tag, value))
4945       as_fatal (_("error adding attribute: %s"),
4946 		bfd_errmsg (bfd_get_error ()));
4947 }
4948 
4949 static void
arc_set_attribute_string(int tag,const char * value)4950 arc_set_attribute_string (int tag, const char *value)
4951 {
4952   if (tag < 1
4953       || tag >= NUM_KNOWN_OBJ_ATTRIBUTES
4954       || !attributes_set_explicitly[tag])
4955     if (!bfd_elf_add_proc_attr_string (stdoutput, tag, value))
4956       as_fatal (_("error adding attribute: %s"),
4957 		bfd_errmsg (bfd_get_error ()));
4958 }
4959 
4960 /* Allocate and concatenate two strings.  s1 can be NULL but not
4961    s2.  s1 pointer is freed at end of this procedure.  */
4962 
4963 static char *
arc_stralloc(char * s1,const char * s2)4964 arc_stralloc (char * s1, const char * s2)
4965 {
4966   char * p;
4967   int len = 0;
4968 
4969   if (s1)
4970     len = strlen (s1) + 1;
4971 
4972   /* Only s1 can be null.  */
4973   gas_assert (s2);
4974   len += strlen (s2) + 1;
4975 
4976   p = (char *) xmalloc (len);
4977 
4978   if (s1)
4979     {
4980       strcpy (p, s1);
4981       strcat (p, ",");
4982       strcat (p, s2);
4983       free (s1);
4984     }
4985   else
4986     strcpy (p, s2);
4987 
4988   return p;
4989 }
4990 
4991 /* Set the public ARC object attributes.  */
4992 
4993 static void
arc_set_public_attributes(void)4994 arc_set_public_attributes (void)
4995 {
4996   int base = 0;
4997   char *s = NULL;
4998   unsigned int i;
4999 
5000   /* Tag_ARC_CPU_name.  */
5001   arc_set_attribute_string (Tag_ARC_CPU_name, selected_cpu.name);
5002 
5003   /* Tag_ARC_CPU_base.  */
5004   switch (selected_cpu.eflags & EF_ARC_MACH_MSK)
5005     {
5006     case E_ARC_MACH_ARC600:
5007     case E_ARC_MACH_ARC601:
5008       base = TAG_CPU_ARC6xx;
5009       break;
5010     case E_ARC_MACH_ARC700:
5011       base = TAG_CPU_ARC7xx;
5012       break;
5013     case EF_ARC_CPU_ARCV2EM:
5014       base = TAG_CPU_ARCEM;
5015       break;
5016     case EF_ARC_CPU_ARCV2HS:
5017       base = TAG_CPU_ARCHS;
5018       break;
5019     default:
5020       base = 0;
5021       break;
5022     }
5023   if (attributes_set_explicitly[Tag_ARC_CPU_base]
5024       && (base != bfd_elf_get_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
5025 					    Tag_ARC_CPU_base)))
5026     as_warn (_("Overwrite explicitly set Tag_ARC_CPU_base"));
5027   if (!bfd_elf_add_proc_attr_int (stdoutput, Tag_ARC_CPU_base, base))
5028     as_fatal (_("error adding attribute: %s"),
5029 	      bfd_errmsg (bfd_get_error ()));
5030 
5031   /* Tag_ARC_ABI_osver.  */
5032   if (attributes_set_explicitly[Tag_ARC_ABI_osver])
5033     {
5034       int val = bfd_elf_get_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
5035 					  Tag_ARC_ABI_osver);
5036 
5037       selected_cpu.eflags = ((selected_cpu.eflags & ~EF_ARC_OSABI_MSK)
5038 			     | (val & 0x0f << 8));
5039     }
5040   else
5041     {
5042       arc_set_attribute_int (Tag_ARC_ABI_osver, E_ARC_OSABI_CURRENT >> 8);
5043     }
5044 
5045   /* Tag_ARC_ISA_config.  */
5046   arc_check_feature();
5047 
5048   for (i = 0; i < ARRAY_SIZE (feature_list); i++)
5049     if (selected_cpu.features & feature_list[i].feature)
5050       s = arc_stralloc (s, feature_list[i].attr);
5051 
5052   if (s)
5053     arc_set_attribute_string (Tag_ARC_ISA_config, s);
5054 
5055   /* Tag_ARC_ISA_mpy_option.  */
5056   arc_set_attribute_int (Tag_ARC_ISA_mpy_option, mpy_option);
5057 
5058   /* Tag_ARC_ABI_pic.  */
5059   arc_set_attribute_int (Tag_ARC_ABI_pic, pic_option);
5060 
5061   /* Tag_ARC_ABI_sda.  */
5062   arc_set_attribute_int (Tag_ARC_ABI_sda, sda_option);
5063 
5064   /* Tag_ARC_ABI_tls.  */
5065   arc_set_attribute_int (Tag_ARC_ABI_tls, tls_option);
5066 
5067   /* Tag_ARC_ATR_version.  */
5068   arc_set_attribute_int (Tag_ARC_ATR_version, 1);
5069 
5070   /* Tag_ARC_ABI_rf16.  */
5071   if (attributes_set_explicitly[Tag_ARC_ABI_rf16]
5072       && bfd_elf_get_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
5073 				   Tag_ARC_ABI_rf16)
5074       && !rf16_only)
5075     {
5076       as_warn (_("Overwrite explicitly set Tag_ARC_ABI_rf16 to full "
5077 		 "register file"));
5078       if (!bfd_elf_add_proc_attr_int (stdoutput, Tag_ARC_ABI_rf16, 0))
5079 	as_fatal (_("error adding attribute: %s"),
5080 		  bfd_errmsg (bfd_get_error ()));
5081     }
5082 }
5083 
5084 /* Add the default contents for the .ARC.attributes section.  */
5085 
5086 void
arc_md_finish(void)5087 arc_md_finish (void)
5088 {
5089   arc_set_public_attributes ();
5090 
5091   if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, selected_cpu.mach))
5092     as_fatal (_("could not set architecture and machine"));
5093 
5094   bfd_set_private_flags (stdoutput, selected_cpu.eflags);
5095 }
5096 
arc_copy_symbol_attributes(symbolS * dest,symbolS * src)5097 void arc_copy_symbol_attributes (symbolS *dest, symbolS *src)
5098 {
5099   ARC_GET_FLAG (dest) = ARC_GET_FLAG (src);
5100 }
5101 
arc_convert_symbolic_attribute(const char * name)5102 int arc_convert_symbolic_attribute (const char *name)
5103 {
5104   static const struct
5105   {
5106     const char * name;
5107     const int    tag;
5108   }
5109   attribute_table[] =
5110     {
5111 #define T(tag) {#tag, tag}
5112   T (Tag_ARC_PCS_config),
5113   T (Tag_ARC_CPU_base),
5114   T (Tag_ARC_CPU_variation),
5115   T (Tag_ARC_CPU_name),
5116   T (Tag_ARC_ABI_rf16),
5117   T (Tag_ARC_ABI_osver),
5118   T (Tag_ARC_ABI_sda),
5119   T (Tag_ARC_ABI_pic),
5120   T (Tag_ARC_ABI_tls),
5121   T (Tag_ARC_ABI_enumsize),
5122   T (Tag_ARC_ABI_exceptions),
5123   T (Tag_ARC_ABI_double_size),
5124   T (Tag_ARC_ISA_config),
5125   T (Tag_ARC_ISA_apex),
5126   T (Tag_ARC_ISA_mpy_option),
5127   T (Tag_ARC_ATR_version)
5128 #undef T
5129     };
5130   unsigned int i;
5131 
5132   if (name == NULL)
5133     return -1;
5134 
5135   for (i = 0; i < ARRAY_SIZE (attribute_table); i++)
5136     if (streq (name, attribute_table[i].name))
5137       return attribute_table[i].tag;
5138 
5139   return -1;
5140 }
5141 
5142 /* Local variables:
5143    eval: (c-set-style "gnu")
5144    indent-tabs-mode: t
5145    End:  */
5146