Extend objdump's --show-all-symbols option so that it also shows the extra symbols...
[binutils-gdb.git] / gas / config / tc-arc.c
blobf7d8e8938ce02d96d54a037f91d9346627e339ab
1 /* tc-arc.c -- Assembler for the ARC
2 Copyright (C) 1994-2024 Free Software Foundation, Inc.
4 Contributor: Claudiu Zissulescu <claziss@synopsys.com>
6 This file is part of GAS, the GNU Assembler.
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.
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.
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. */
23 #include "as.h"
24 #include "subsegs.h"
25 #include "dwarf2dbg.h"
26 #include "dw2gencfi.h"
27 #include "safe-ctype.h"
29 #include "opcode/arc.h"
30 #include "opcode/arc-attrs.h"
31 #include "elf/arc.h"
32 #include "../opcodes/arc-ext.h"
34 /* Defines section. */
36 #define MAX_INSN_FIXUPS 2
37 #define MAX_CONSTR_STR 20
38 #define FRAG_MAX_GROWTH 8
40 #ifdef DEBUG
41 # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
42 #else
43 # define pr_debug(fmt, args...)
44 #endif
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))
51 #ifndef TARGET_WITH_CPU
52 #define TARGET_WITH_CPU "hs38_linux"
53 #endif /* TARGET_WITH_CPU */
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)
59 /* Enum used to enumerate the relaxable ins operands. */
60 enum rlx_operand_type
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
71 enum arc_rlx_types
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,
98 /* Macros section. */
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 == DBNZ \
113 || (op)->insn_class == EI \
114 || (op)->insn_class == ENTER \
115 || (op)->insn_class == JLI \
116 || (op)->insn_class == LOOP \
117 || (op)->insn_class == LEAVE \
119 #define is_kernel_insn_p(op) (((op)->insn_class == KERNEL))
120 #define is_nps400_p(op) (((sc) == NPS400))
122 /* Generic assembler global variables which must be defined by all
123 targets. */
125 /* Characters which always start a comment. */
126 const char comment_chars[] = "#;";
128 /* Characters which start a comment at the beginning of a line. */
129 const char line_comment_chars[] = "#";
131 /* Characters which may be used to separate multiple commands on a
132 single line. */
133 const char line_separator_chars[] = "`";
135 /* Characters which are used to indicate an exponent in a floating
136 point number. */
137 const char EXP_CHARS[] = "eE";
139 /* Chars that mean this number is a floating point constant
140 As in 0f12.456 or 0d1.2345e12. */
141 const char FLT_CHARS[] = "rRsSfFdD";
143 /* Byte order. */
144 extern int target_big_endian;
145 const char *arc_target_format = DEFAULT_TARGET_FORMAT;
146 static int byte_order = DEFAULT_BYTE_ORDER;
148 /* Arc extension section. */
149 static segT arcext_section;
151 /* By default relaxation is disabled. */
152 static int relaxation_state = 0;
154 extern int arc_get_mach (char *);
156 /* Forward declarations. */
157 static void arc_lcomm (int);
158 static void arc_option (int);
159 static void arc_extra_reloc (int);
160 static void arc_extinsn (int);
161 static void arc_extcorereg (int);
162 static void arc_attribute (int);
164 const pseudo_typeS md_pseudo_table[] =
166 /* Make sure that .word is 32 bits. */
167 { "word", cons, 4 },
169 { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0). */
170 { "lcomm", arc_lcomm, 0 },
171 { "lcommon", arc_lcomm, 0 },
172 { "cpu", arc_option, 0 },
174 { "arc_attribute", arc_attribute, 0 },
175 { "extinstruction", arc_extinsn, 0 },
176 { "extcoreregister", arc_extcorereg, EXT_CORE_REGISTER },
177 { "extauxregister", arc_extcorereg, EXT_AUX_REGISTER },
178 { "extcondcode", arc_extcorereg, EXT_COND_CODE },
180 { "tls_gd_ld", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_LD },
181 { "tls_gd_call", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_CALL },
183 { NULL, NULL, 0 }
186 const char *md_shortopts = "";
188 enum options
190 OPTION_EB = OPTION_MD_BASE,
191 OPTION_EL,
193 OPTION_ARC600,
194 OPTION_ARC601,
195 OPTION_ARC700,
196 OPTION_ARCEM,
197 OPTION_ARCHS,
199 OPTION_MCPU,
200 OPTION_CD,
201 OPTION_RELAX,
202 OPTION_NPS400,
204 OPTION_SPFP,
205 OPTION_DPFP,
206 OPTION_FPUDA,
208 /* The following options are deprecated and provided here only for
209 compatibility reasons. */
210 OPTION_USER_MODE,
211 OPTION_LD_EXT_MASK,
212 OPTION_SWAP,
213 OPTION_NORM,
214 OPTION_BARREL_SHIFT,
215 OPTION_MIN_MAX,
216 OPTION_NO_MPY,
217 OPTION_EA,
218 OPTION_MUL64,
219 OPTION_SIMD,
220 OPTION_XMAC_D16,
221 OPTION_XMAC_24,
222 OPTION_DSP_PACKA,
223 OPTION_CRC,
224 OPTION_DVBF,
225 OPTION_TELEPHONY,
226 OPTION_XYMEMORY,
227 OPTION_LOCK,
228 OPTION_SWAPE,
229 OPTION_RTSC
232 struct option md_longopts[] =
234 { "EB", no_argument, NULL, OPTION_EB },
235 { "EL", no_argument, NULL, OPTION_EL },
236 { "mcpu", required_argument, NULL, OPTION_MCPU },
237 { "mA6", no_argument, NULL, OPTION_ARC600 },
238 { "mARC600", no_argument, NULL, OPTION_ARC600 },
239 { "mARC601", no_argument, NULL, OPTION_ARC601 },
240 { "mARC700", no_argument, NULL, OPTION_ARC700 },
241 { "mA7", no_argument, NULL, OPTION_ARC700 },
242 { "mEM", no_argument, NULL, OPTION_ARCEM },
243 { "mHS", no_argument, NULL, OPTION_ARCHS },
244 { "mcode-density", no_argument, NULL, OPTION_CD },
245 { "mrelax", no_argument, NULL, OPTION_RELAX },
246 { "mnps400", no_argument, NULL, OPTION_NPS400 },
248 /* Floating point options */
249 { "mspfp", no_argument, NULL, OPTION_SPFP},
250 { "mspfp-compact", no_argument, NULL, OPTION_SPFP},
251 { "mspfp_compact", no_argument, NULL, OPTION_SPFP},
252 { "mspfp-fast", no_argument, NULL, OPTION_SPFP},
253 { "mspfp_fast", no_argument, NULL, OPTION_SPFP},
254 { "mdpfp", no_argument, NULL, OPTION_DPFP},
255 { "mdpfp-compact", no_argument, NULL, OPTION_DPFP},
256 { "mdpfp_compact", no_argument, NULL, OPTION_DPFP},
257 { "mdpfp-fast", no_argument, NULL, OPTION_DPFP},
258 { "mdpfp_fast", no_argument, NULL, OPTION_DPFP},
259 { "mfpuda", no_argument, NULL, OPTION_FPUDA},
261 /* The following options are deprecated and provided here only for
262 compatibility reasons. */
263 { "mav2em", no_argument, NULL, OPTION_ARCEM },
264 { "mav2hs", no_argument, NULL, OPTION_ARCHS },
265 { "muser-mode-only", no_argument, NULL, OPTION_USER_MODE },
266 { "mld-extension-reg-mask", required_argument, NULL, OPTION_LD_EXT_MASK },
267 { "mswap", no_argument, NULL, OPTION_SWAP },
268 { "mnorm", no_argument, NULL, OPTION_NORM },
269 { "mbarrel-shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
270 { "mbarrel_shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
271 { "mmin-max", no_argument, NULL, OPTION_MIN_MAX },
272 { "mmin_max", no_argument, NULL, OPTION_MIN_MAX },
273 { "mno-mpy", no_argument, NULL, OPTION_NO_MPY },
274 { "mea", no_argument, NULL, OPTION_EA },
275 { "mEA", no_argument, NULL, OPTION_EA },
276 { "mmul64", no_argument, NULL, OPTION_MUL64 },
277 { "msimd", no_argument, NULL, OPTION_SIMD},
278 { "mmac-d16", no_argument, NULL, OPTION_XMAC_D16},
279 { "mmac_d16", no_argument, NULL, OPTION_XMAC_D16},
280 { "mmac-24", no_argument, NULL, OPTION_XMAC_24},
281 { "mmac_24", no_argument, NULL, OPTION_XMAC_24},
282 { "mdsp-packa", no_argument, NULL, OPTION_DSP_PACKA},
283 { "mdsp_packa", no_argument, NULL, OPTION_DSP_PACKA},
284 { "mcrc", no_argument, NULL, OPTION_CRC},
285 { "mdvbf", no_argument, NULL, OPTION_DVBF},
286 { "mtelephony", no_argument, NULL, OPTION_TELEPHONY},
287 { "mxy", no_argument, NULL, OPTION_XYMEMORY},
288 { "mlock", no_argument, NULL, OPTION_LOCK},
289 { "mswape", no_argument, NULL, OPTION_SWAPE},
290 { "mrtsc", no_argument, NULL, OPTION_RTSC},
292 { NULL, no_argument, NULL, 0 }
295 size_t md_longopts_size = sizeof (md_longopts);
297 /* Local data and data types. */
299 /* Used since new relocation types are introduced in this
300 file (DUMMY_RELOC_LITUSE_*). */
301 typedef int extended_bfd_reloc_code_real_type;
303 struct arc_fixup
305 expressionS exp;
307 extended_bfd_reloc_code_real_type reloc;
309 /* index into arc_operands. */
310 unsigned int opindex;
312 /* PC-relative, used by internals fixups. */
313 unsigned char pcrel;
315 /* TRUE if this fixup is for LIMM operand. */
316 bool islong;
319 struct arc_insn
321 unsigned long long int insn;
322 int nfixups;
323 struct arc_fixup fixups[MAX_INSN_FIXUPS];
324 long limm;
325 unsigned int len; /* Length of instruction in bytes. */
326 bool has_limm; /* Boolean value: TRUE if limm field is valid. */
327 bool relax; /* Boolean value: TRUE if needs relaxation. */
330 /* Structure to hold any last two instructions. */
331 static struct arc_last_insn
333 /* Saved instruction opcode. */
334 const struct arc_opcode *opcode;
336 /* Boolean value: TRUE if current insn is short. */
337 bool has_limm;
339 /* Boolean value: TRUE if current insn has delay slot. */
340 bool has_delay_slot;
341 } arc_last_insns[2];
343 /* Extension instruction suffix classes. */
344 typedef struct
346 const char *name;
347 int len;
348 int attr_class;
349 } attributes_t;
351 static const attributes_t suffixclass[] =
353 { "SUFFIX_FLAG", 11, ARC_SUFFIX_FLAG },
354 { "SUFFIX_COND", 11, ARC_SUFFIX_COND },
355 { "SUFFIX_NONE", 11, ARC_SUFFIX_NONE }
358 /* Extension instruction syntax classes. */
359 static const attributes_t syntaxclass[] =
361 { "SYNTAX_3OP", 10, ARC_SYNTAX_3OP },
362 { "SYNTAX_2OP", 10, ARC_SYNTAX_2OP },
363 { "SYNTAX_1OP", 10, ARC_SYNTAX_1OP },
364 { "SYNTAX_NOP", 10, ARC_SYNTAX_NOP }
367 /* Extension instruction syntax classes modifiers. */
368 static const attributes_t syntaxclassmod[] =
370 { "OP1_IMM_IMPLIED" , 15, ARC_OP1_IMM_IMPLIED },
371 { "OP1_MUST_BE_IMM" , 15, ARC_OP1_MUST_BE_IMM }
374 /* Extension register type. */
375 typedef struct
377 char *name;
378 int number;
379 int imode;
380 } extRegister_t;
382 /* A structure to hold the additional conditional codes. */
383 static struct
385 struct arc_flag_operand *arc_ext_condcode;
386 int size;
387 } ext_condcode = { NULL, 0 };
389 /* Structure to hold an entry in ARC_OPCODE_HASH. */
390 struct arc_opcode_hash_entry
392 /* The number of pointers in the OPCODE list. */
393 size_t count;
395 /* Points to a list of opcode pointers. */
396 const struct arc_opcode **opcode;
399 /* Structure used for iterating through an arc_opcode_hash_entry. */
400 struct arc_opcode_hash_entry_iterator
402 /* Index into the OPCODE element of the arc_opcode_hash_entry. */
403 size_t index;
405 /* The specific ARC_OPCODE from the ARC_OPCODES table that was last
406 returned by this iterator. */
407 const struct arc_opcode *opcode;
410 /* Forward declaration. */
411 static void assemble_insn
412 (const struct arc_opcode *, const expressionS *, int,
413 const struct arc_flags *, int, struct arc_insn *);
415 /* The selection of the machine type can come from different sources. This
416 enum is used to track how the selection was made in order to perform
417 error checks. */
418 enum mach_selection_type
420 MACH_SELECTION_NONE,
421 MACH_SELECTION_FROM_DEFAULT,
422 MACH_SELECTION_FROM_CPU_DIRECTIVE,
423 MACH_SELECTION_FROM_COMMAND_LINE
426 /* How the current machine type was selected. */
427 static enum mach_selection_type mach_selection_mode = MACH_SELECTION_NONE;
429 /* The hash table of instruction opcodes. */
430 static htab_t arc_opcode_hash;
432 /* The hash table of register symbols. */
433 static htab_t arc_reg_hash;
435 /* The hash table of aux register symbols. */
436 static htab_t arc_aux_hash;
438 /* The hash table of address types. */
439 static htab_t arc_addrtype_hash;
441 #define ARC_CPU_TYPE_A6xx(NAME,EXTRA) \
442 { #NAME, ARC_OPCODE_ARC600, bfd_mach_arc_arc600, \
443 E_ARC_MACH_ARC600, EXTRA}
444 #define ARC_CPU_TYPE_A7xx(NAME,EXTRA) \
445 { #NAME, ARC_OPCODE_ARC700, bfd_mach_arc_arc700, \
446 E_ARC_MACH_ARC700, EXTRA}
447 #define ARC_CPU_TYPE_AV2EM(NAME,EXTRA) \
448 { #NAME, ARC_OPCODE_ARCv2EM, bfd_mach_arc_arcv2, \
449 EF_ARC_CPU_ARCV2EM, EXTRA}
450 #define ARC_CPU_TYPE_AV2HS(NAME,EXTRA) \
451 { #NAME, ARC_OPCODE_ARCv2HS, bfd_mach_arc_arcv2, \
452 EF_ARC_CPU_ARCV2HS, EXTRA}
453 #define ARC_CPU_TYPE_NONE \
454 { 0, 0, 0, 0, 0 }
456 /* A table of CPU names and opcode sets. */
457 static const struct cpu_type
459 const char *name;
460 unsigned flags;
461 int mach;
462 unsigned eflags;
463 unsigned features;
465 cpu_types[] =
467 #include "elf/arc-cpu.def"
470 /* Information about the cpu/variant we're assembling for. */
471 static struct cpu_type selected_cpu = { 0, 0, 0, E_ARC_OSABI_CURRENT, 0 };
473 /* TRUE if current assembly code uses RF16 only registers. */
474 static bool rf16_only = true;
476 /* MPY option. */
477 static unsigned mpy_option = 0;
479 /* Use PIC. */
480 static unsigned pic_option = 0;
482 /* Use small data. */
483 static unsigned sda_option = 0;
485 /* Use TLS. */
486 static unsigned tls_option = 0;
488 /* Command line given features. */
489 static unsigned cl_features = 0;
491 /* Used by the arc_reloc_op table. Order is important. */
492 #define O_gotoff O_md1 /* @gotoff relocation. */
493 #define O_gotpc O_md2 /* @gotpc relocation. */
494 #define O_plt O_md3 /* @plt relocation. */
495 #define O_sda O_md4 /* @sda relocation. */
496 #define O_pcl O_md5 /* @pcl relocation. */
497 #define O_tlsgd O_md6 /* @tlsgd relocation. */
498 #define O_tlsie O_md7 /* @tlsie relocation. */
499 #define O_tpoff9 O_md8 /* @tpoff9 relocation. */
500 #define O_tpoff O_md9 /* @tpoff relocation. */
501 #define O_dtpoff9 O_md10 /* @dtpoff9 relocation. */
502 #define O_dtpoff O_md11 /* @dtpoff relocation. */
503 #define O_last O_dtpoff
505 /* Used to define a bracket as operand in tokens. */
506 #define O_bracket O_md32
508 /* Used to define a colon as an operand in tokens. */
509 #define O_colon O_md31
511 /* Used to define address types in nps400. */
512 #define O_addrtype O_md30
514 /* Dummy relocation, to be sorted out. */
515 #define DUMMY_RELOC_ARC_ENTRY (BFD_RELOC_UNUSED + 1)
517 #define USER_RELOC_P(R) ((R) >= O_gotoff && (R) <= O_last)
519 /* A table to map the spelling of a relocation operand into an appropriate
520 bfd_reloc_code_real_type type. The table is assumed to be ordered such
521 that op-O_literal indexes into it. */
522 #define ARC_RELOC_TABLE(op) \
523 (&arc_reloc_op[ ((!USER_RELOC_P (op)) \
524 ? (abort (), 0) \
525 : (int) (op) - (int) O_gotoff) ])
527 #define DEF(NAME, RELOC, REQ) \
528 { #NAME, sizeof (#NAME)-1, O_##NAME, RELOC, REQ}
530 static const struct arc_reloc_op_tag
532 /* String to lookup. */
533 const char *name;
534 /* Size of the string. */
535 size_t length;
536 /* Which operator to use. */
537 operatorT op;
538 extended_bfd_reloc_code_real_type reloc;
539 /* Allows complex relocation expression like identifier@reloc +
540 const. */
541 unsigned int complex_expr : 1;
543 arc_reloc_op[] =
545 DEF (gotoff, BFD_RELOC_ARC_GOTOFF, 1),
546 DEF (gotpc, BFD_RELOC_ARC_GOTPC32, 0),
547 DEF (plt, BFD_RELOC_ARC_PLT32, 0),
548 DEF (sda, DUMMY_RELOC_ARC_ENTRY, 1),
549 DEF (pcl, BFD_RELOC_ARC_PC32, 1),
550 DEF (tlsgd, BFD_RELOC_ARC_TLS_GD_GOT, 0),
551 DEF (tlsie, BFD_RELOC_ARC_TLS_IE_GOT, 0),
552 DEF (tpoff9, BFD_RELOC_ARC_TLS_LE_S9, 0),
553 DEF (tpoff, BFD_RELOC_ARC_TLS_LE_32, 1),
554 DEF (dtpoff9, BFD_RELOC_ARC_TLS_DTPOFF_S9, 0),
555 DEF (dtpoff, BFD_RELOC_ARC_TLS_DTPOFF, 1),
558 static const int arc_num_reloc_op
559 = sizeof (arc_reloc_op) / sizeof (*arc_reloc_op);
561 /* Structure for relaxable instruction that have to be swapped with a
562 smaller alternative instruction. */
563 struct arc_relaxable_ins
565 /* Mnemonic that should be checked. */
566 const char *mnemonic_r;
568 /* Operands that should be checked.
569 Indexes of operands from operand array. */
570 enum rlx_operand_type operands[6];
572 /* Flags that should be checked. */
573 unsigned flag_classes[5];
575 /* Mnemonic (smaller) alternative to be used later for relaxation. */
576 const char *mnemonic_alt;
578 /* Index of operand that generic relaxation has to check. */
579 unsigned opcheckidx;
581 /* Base subtype index used. */
582 enum arc_rlx_types subtype;
585 #define RELAX_TABLE_ENTRY(BITS, ISSIGNED, SIZE, NEXT) \
586 { (ISSIGNED) ? ((1 << ((BITS) - 1)) - 1) : ((1 << (BITS)) - 1), \
587 (ISSIGNED) ? -(1 << ((BITS) - 1)) : 0, \
588 (SIZE), \
589 (NEXT) } \
591 #define RELAX_TABLE_ENTRY_MAX(ISSIGNED, SIZE, NEXT) \
592 { (ISSIGNED) ? 0x7FFFFFFF : 0xFFFFFFFF, \
593 (ISSIGNED) ? -(0x7FFFFFFF) : 0, \
594 (SIZE), \
595 (NEXT) } \
598 /* ARC relaxation table. */
599 const relax_typeS md_relax_table[] =
601 /* Fake entry. */
602 {0, 0, 0, 0},
604 /* BL_S s13 ->
605 BL s25. */
606 RELAX_TABLE_ENTRY (13, 1, 2, ARC_RLX_BL),
607 RELAX_TABLE_ENTRY (25, 1, 4, ARC_RLX_NONE),
609 /* B_S s10 ->
610 B s25. */
611 RELAX_TABLE_ENTRY (10, 1, 2, ARC_RLX_B),
612 RELAX_TABLE_ENTRY (25, 1, 4, ARC_RLX_NONE),
614 /* ADD_S c,b, u3 ->
615 ADD<.f> a,b,u6 ->
616 ADD<.f> a,b,limm. */
617 RELAX_TABLE_ENTRY (3, 0, 2, ARC_RLX_ADD_U6),
618 RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_ADD_LIMM),
619 RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
621 /* LD_S a, [b, u7] ->
622 LD<zz><.x><.aa><.di> a, [b, s9] ->
623 LD<zz><.x><.aa><.di> a, [b, limm] */
624 RELAX_TABLE_ENTRY (7, 0, 2, ARC_RLX_LD_S9),
625 RELAX_TABLE_ENTRY (9, 1, 4, ARC_RLX_LD_LIMM),
626 RELAX_TABLE_ENTRY_MAX (1, 8, ARC_RLX_NONE),
628 /* MOV_S b, u8 ->
629 MOV<.f> b, s12 ->
630 MOV<.f> b, limm. */
631 RELAX_TABLE_ENTRY (8, 0, 2, ARC_RLX_MOV_S12),
632 RELAX_TABLE_ENTRY (8, 0, 4, ARC_RLX_MOV_LIMM),
633 RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
635 /* SUB_S c, b, u3 ->
636 SUB<.f> a, b, u6 ->
637 SUB<.f> a, b, limm. */
638 RELAX_TABLE_ENTRY (3, 0, 2, ARC_RLX_SUB_U6),
639 RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_SUB_LIMM),
640 RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
642 /* MPY<.f> a, b, u6 ->
643 MPY<.f> a, b, limm. */
644 RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_MPY_LIMM),
645 RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
647 /* MOV<.f><.cc> b, u6 ->
648 MOV<.f><.cc> b, limm. */
649 RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_MOV_RLIMM),
650 RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
652 /* ADD<.f><.cc> b, b, u6 ->
653 ADD<.f><.cc> b, b, limm. */
654 RELAX_TABLE_ENTRY (6, 0, 4, ARC_RLX_ADD_RRLIMM),
655 RELAX_TABLE_ENTRY_MAX (0, 8, ARC_RLX_NONE),
658 /* Order of this table's entries matters! */
659 const struct arc_relaxable_ins arc_relaxable_insns[] =
661 { "bl", { IMMEDIATE }, { 0 }, "bl_s", 0, ARC_RLX_BL_S },
662 { "b", { IMMEDIATE }, { 0 }, "b_s", 0, ARC_RLX_B_S },
663 { "add", { REGISTER, REGISTER_DUP, IMMEDIATE }, { 5, 1, 0 }, "add",
664 2, ARC_RLX_ADD_RRU6},
665 { "add", { REGISTER_S, REGISTER_S, IMMEDIATE }, { 0 }, "add_s", 2,
666 ARC_RLX_ADD_U3 },
667 { "add", { REGISTER, REGISTER, IMMEDIATE }, { 5, 0 }, "add", 2,
668 ARC_RLX_ADD_U6 },
669 { "ld", { REGISTER_S, BRACKET, REGISTER_S, IMMEDIATE, BRACKET },
670 { 0 }, "ld_s", 3, ARC_RLX_LD_U7 },
671 { "ld", { REGISTER, BRACKET, REGISTER_NO_GP, IMMEDIATE, BRACKET },
672 { 11, 4, 14, 17, 0 }, "ld", 3, ARC_RLX_LD_S9 },
673 { "mov", { REGISTER_S, IMMEDIATE }, { 0 }, "mov_s", 1, ARC_RLX_MOV_U8 },
674 { "mov", { REGISTER, IMMEDIATE }, { 5, 0 }, "mov", 1, ARC_RLX_MOV_S12 },
675 { "mov", { REGISTER, IMMEDIATE }, { 5, 1, 0 },"mov", 1, ARC_RLX_MOV_RU6 },
676 { "sub", { REGISTER_S, REGISTER_S, IMMEDIATE }, { 0 }, "sub_s", 2,
677 ARC_RLX_SUB_U3 },
678 { "sub", { REGISTER, REGISTER, IMMEDIATE }, { 5, 0 }, "sub", 2,
679 ARC_RLX_SUB_U6 },
680 { "mpy", { REGISTER, REGISTER, IMMEDIATE }, { 5, 0 }, "mpy", 2,
681 ARC_RLX_MPY_U6 },
684 const unsigned arc_num_relaxable_ins = ARRAY_SIZE (arc_relaxable_insns);
686 /* Pre-defined "_GLOBAL_OFFSET_TABLE_". */
687 symbolS * GOT_symbol = 0;
689 /* Set to TRUE when we assemble instructions. */
690 static bool assembling_insn = false;
692 /* List with attributes set explicitly. */
693 static bool attributes_set_explicitly[NUM_KNOWN_OBJ_ATTRIBUTES];
695 /* Functions implementation. */
697 /* Return a pointer to ARC_OPCODE_HASH_ENTRY that identifies all
698 ARC_OPCODE entries in ARC_OPCODE_HASH that match NAME, or NULL if there
699 are no matching entries in ARC_OPCODE_HASH. */
701 static const struct arc_opcode_hash_entry *
702 arc_find_opcode (const char *name)
704 const struct arc_opcode_hash_entry *entry;
706 entry = str_hash_find (arc_opcode_hash, name);
707 return entry;
710 /* Initialise the iterator ITER. */
712 static void
713 arc_opcode_hash_entry_iterator_init (struct arc_opcode_hash_entry_iterator *iter)
715 iter->index = 0;
716 iter->opcode = NULL;
719 /* Return the next ARC_OPCODE from ENTRY, using ITER to hold state between
720 calls to this function. Return NULL when all ARC_OPCODE entries have
721 been returned. */
723 static const struct arc_opcode *
724 arc_opcode_hash_entry_iterator_next (const struct arc_opcode_hash_entry *entry,
725 struct arc_opcode_hash_entry_iterator *iter)
727 if (iter->opcode == NULL && iter->index == 0)
729 gas_assert (entry->count > 0);
730 iter->opcode = entry->opcode[iter->index];
732 else if (iter->opcode != NULL)
734 const char *old_name = iter->opcode->name;
736 iter->opcode++;
737 if (iter->opcode->name == NULL
738 || strcmp (old_name, iter->opcode->name) != 0)
740 iter->index++;
741 if (iter->index == entry->count)
742 iter->opcode = NULL;
743 else
744 iter->opcode = entry->opcode[iter->index];
748 return iter->opcode;
751 /* Insert an opcode into opcode hash structure. */
753 static void
754 arc_insert_opcode (const struct arc_opcode *opcode)
756 const char *name;
757 struct arc_opcode_hash_entry *entry;
758 name = opcode->name;
760 entry = str_hash_find (arc_opcode_hash, name);
761 if (entry == NULL)
763 entry = XNEW (struct arc_opcode_hash_entry);
764 entry->count = 0;
765 entry->opcode = NULL;
767 if (str_hash_insert (arc_opcode_hash, name, entry, 0) != NULL)
768 as_fatal (_("duplicate %s"), name);
771 entry->opcode = XRESIZEVEC (const struct arc_opcode *, entry->opcode,
772 entry->count + 1);
774 entry->opcode[entry->count] = opcode;
775 entry->count++;
778 static void
779 arc_opcode_free (void *elt)
781 string_tuple_t *tuple = (string_tuple_t *) elt;
782 struct arc_opcode_hash_entry *entry = (void *) tuple->value;
783 free (entry->opcode);
784 free (entry);
785 free (tuple);
788 /* Like md_number_to_chars but for middle-endian values. The 4-byte limm
789 value, is encoded as 'middle-endian' for a little-endian target. This
790 function is used for regular 4, 6, and 8 byte instructions as well. */
792 static void
793 md_number_to_chars_midend (char *buf, unsigned long long val, int n)
795 switch (n)
797 case 2:
798 md_number_to_chars (buf, val, n);
799 break;
800 case 6:
801 md_number_to_chars (buf, (val & 0xffff00000000ull) >> 32, 2);
802 md_number_to_chars_midend (buf + 2, (val & 0xffffffff), 4);
803 break;
804 case 4:
805 md_number_to_chars (buf, (val & 0xffff0000) >> 16, 2);
806 md_number_to_chars (buf + 2, (val & 0xffff), 2);
807 break;
808 case 8:
809 md_number_to_chars_midend (buf, (val & 0xffffffff00000000ull) >> 32, 4);
810 md_number_to_chars_midend (buf + 4, (val & 0xffffffff), 4);
811 break;
812 default:
813 abort ();
817 /* Check if a feature is allowed for a specific CPU. */
819 static void
820 arc_check_feature (void)
822 unsigned i;
824 if (!selected_cpu.features
825 || !selected_cpu.name)
826 return;
828 for (i = 0; i < ARRAY_SIZE (feature_list); i++)
829 if ((selected_cpu.features & feature_list[i].feature)
830 && !(selected_cpu.flags & feature_list[i].cpus))
831 as_bad (_("invalid %s option for %s cpu"), feature_list[i].name,
832 selected_cpu.name);
834 for (i = 0; i < ARRAY_SIZE (conflict_list); i++)
835 if ((selected_cpu.features & conflict_list[i]) == conflict_list[i])
836 as_bad(_("conflicting ISA extension attributes."));
839 /* Select an appropriate entry from CPU_TYPES based on ARG and initialise
840 the relevant static global variables. Parameter SEL describes where
841 this selection originated from. */
843 static void
844 arc_select_cpu (const char *arg, enum mach_selection_type sel)
846 int i;
847 static struct cpu_type old_cpu = { 0, 0, 0, E_ARC_OSABI_CURRENT, 0 };
849 /* We should only set a default if we've not made a selection from some
850 other source. */
851 gas_assert (sel != MACH_SELECTION_FROM_DEFAULT
852 || mach_selection_mode == MACH_SELECTION_NONE);
854 if ((mach_selection_mode == MACH_SELECTION_FROM_CPU_DIRECTIVE)
855 && (sel == MACH_SELECTION_FROM_CPU_DIRECTIVE))
856 as_bad (_("Multiple .cpu directives found"));
858 /* Look for a matching entry in CPU_TYPES array. */
859 for (i = 0; cpu_types[i].name; ++i)
861 if (!strcasecmp (cpu_types[i].name, arg))
863 /* If a previous selection was made on the command line, then we
864 allow later selections on the command line to override earlier
865 ones. However, a selection from a '.cpu NAME' directive must
866 match the command line selection, or we give a warning. */
867 if (mach_selection_mode == MACH_SELECTION_FROM_COMMAND_LINE)
869 gas_assert (sel == MACH_SELECTION_FROM_COMMAND_LINE
870 || sel == MACH_SELECTION_FROM_CPU_DIRECTIVE);
871 if (sel == MACH_SELECTION_FROM_CPU_DIRECTIVE
872 && selected_cpu.mach != cpu_types[i].mach)
874 as_warn (_("Command-line value overrides \".cpu\" directive"));
876 return;
878 /* Initialise static global data about selected machine type. */
879 selected_cpu.flags = cpu_types[i].flags;
880 selected_cpu.name = cpu_types[i].name;
881 selected_cpu.features = cpu_types[i].features | cl_features;
882 selected_cpu.mach = cpu_types[i].mach;
883 selected_cpu.eflags = ((selected_cpu.eflags & ~EF_ARC_MACH_MSK)
884 | cpu_types[i].eflags);
885 break;
889 if (!cpu_types[i].name)
890 as_fatal (_("unknown architecture: %s\n"), arg);
892 /* Check if set features are compatible with the chosen CPU. */
893 arc_check_feature ();
895 /* If we change the CPU, we need to re-init the bfd. */
896 if (mach_selection_mode != MACH_SELECTION_NONE
897 && (old_cpu.mach != selected_cpu.mach))
899 bfd_find_target (arc_target_format, stdoutput);
900 if (! bfd_set_arch_mach (stdoutput, bfd_arch_arc, selected_cpu.mach))
901 as_warn (_("Could not set architecture and machine"));
904 mach_selection_mode = sel;
905 old_cpu = selected_cpu;
908 /* Here ends all the ARCompact extension instruction assembling
909 stuff. */
911 static void
912 arc_extra_reloc (int r_type)
914 char *sym_name, c;
915 symbolS *sym, *lab = NULL;
917 if (*input_line_pointer == '@')
918 input_line_pointer++;
919 c = get_symbol_name (&sym_name);
920 sym = symbol_find_or_make (sym_name);
921 restore_line_pointer (c);
922 if (c == ',' && r_type == BFD_RELOC_ARC_TLS_GD_LD)
924 ++input_line_pointer;
925 char *lab_name;
926 c = get_symbol_name (&lab_name);
927 lab = symbol_find_or_make (lab_name);
928 restore_line_pointer (c);
931 /* These relocations exist as a mechanism for the compiler to tell the
932 linker how to patch the code if the tls model is optimised. However,
933 the relocation itself does not require any space within the assembler
934 fragment, and so we pass a size of 0.
936 The lines that generate these relocations look like this:
938 .tls_gd_ld @.tdata`bl __tls_get_addr@plt
940 The '.tls_gd_ld @.tdata' is processed first and generates the
941 additional relocation, while the 'bl __tls_get_addr@plt' is processed
942 second and generates the additional branch.
944 It is possible that the additional relocation generated by the
945 '.tls_gd_ld @.tdata' will be attached at the very end of one fragment,
946 while the 'bl __tls_get_addr@plt' will be generated as the first thing
947 in the next fragment. This will be fine; both relocations will still
948 appear to be at the same address in the generated object file.
949 However, this only works as the additional relocation is generated
950 with size of 0 bytes. */
951 fixS *fixP
952 = fix_new (frag_now, /* Which frag? */
953 frag_now_fix (), /* Where in that frag? */
954 0, /* size: 1, 2, or 4 usually. */
955 sym, /* X_add_symbol. */
956 0, /* X_add_number. */
957 false, /* TRUE if PC-relative relocation. */
958 r_type /* Relocation type. */);
959 fixP->fx_subsy = lab;
962 static symbolS *
963 arc_lcomm_internal (int ignore ATTRIBUTE_UNUSED,
964 symbolS *symbolP, addressT size)
966 addressT align = 0;
967 SKIP_WHITESPACE ();
969 if (*input_line_pointer == ',')
971 align = parse_align (1);
973 if (align == (addressT) -1)
974 return NULL;
976 else
978 if (size >= 8)
979 align = 3;
980 else if (size >= 4)
981 align = 2;
982 else if (size >= 2)
983 align = 1;
984 else
985 align = 0;
988 bss_alloc (symbolP, size, align);
989 S_CLEAR_EXTERNAL (symbolP);
991 return symbolP;
994 static void
995 arc_lcomm (int ignore)
997 symbolS *symbolP = s_comm_internal (ignore, arc_lcomm_internal);
999 if (symbolP)
1000 symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
1003 /* Select the cpu we're assembling for. */
1005 static void
1006 arc_option (int ignore ATTRIBUTE_UNUSED)
1008 char c;
1009 char *cpu;
1010 const char *cpu_name;
1012 c = get_symbol_name (&cpu);
1014 cpu_name = cpu;
1015 if ((!strcmp ("ARC600", cpu))
1016 || (!strcmp ("ARC601", cpu))
1017 || (!strcmp ("A6", cpu)))
1018 cpu_name = "arc600";
1019 else if ((!strcmp ("ARC700", cpu))
1020 || (!strcmp ("A7", cpu)))
1021 cpu_name = "arc700";
1022 else if (!strcmp ("EM", cpu))
1023 cpu_name = "arcem";
1024 else if (!strcmp ("HS", cpu))
1025 cpu_name = "archs";
1026 else if (!strcmp ("NPS400", cpu))
1027 cpu_name = "nps400";
1029 arc_select_cpu (cpu_name, MACH_SELECTION_FROM_CPU_DIRECTIVE);
1031 restore_line_pointer (c);
1032 demand_empty_rest_of_line ();
1035 /* Smartly print an expression. */
1037 static void
1038 debug_exp (expressionS *t)
1040 const char *name ATTRIBUTE_UNUSED;
1041 const char *namemd ATTRIBUTE_UNUSED;
1043 pr_debug ("debug_exp: ");
1045 switch (t->X_op)
1047 default: name = "unknown"; break;
1048 case O_illegal: name = "O_illegal"; break;
1049 case O_absent: name = "O_absent"; break;
1050 case O_constant: name = "O_constant"; break;
1051 case O_symbol: name = "O_symbol"; break;
1052 case O_symbol_rva: name = "O_symbol_rva"; break;
1053 case O_register: name = "O_register"; break;
1054 case O_big: name = "O_big"; break;
1055 case O_uminus: name = "O_uminus"; break;
1056 case O_bit_not: name = "O_bit_not"; break;
1057 case O_logical_not: name = "O_logical_not"; break;
1058 case O_multiply: name = "O_multiply"; break;
1059 case O_divide: name = "O_divide"; break;
1060 case O_modulus: name = "O_modulus"; break;
1061 case O_left_shift: name = "O_left_shift"; break;
1062 case O_right_shift: name = "O_right_shift"; break;
1063 case O_bit_inclusive_or: name = "O_bit_inclusive_or"; break;
1064 case O_bit_or_not: name = "O_bit_or_not"; break;
1065 case O_bit_exclusive_or: name = "O_bit_exclusive_or"; break;
1066 case O_bit_and: name = "O_bit_and"; break;
1067 case O_add: name = "O_add"; break;
1068 case O_subtract: name = "O_subtract"; break;
1069 case O_eq: name = "O_eq"; break;
1070 case O_ne: name = "O_ne"; break;
1071 case O_lt: name = "O_lt"; break;
1072 case O_le: name = "O_le"; break;
1073 case O_ge: name = "O_ge"; break;
1074 case O_gt: name = "O_gt"; break;
1075 case O_logical_and: name = "O_logical_and"; break;
1076 case O_logical_or: name = "O_logical_or"; break;
1077 case O_index: name = "O_index"; break;
1078 case O_bracket: name = "O_bracket"; break;
1079 case O_colon: name = "O_colon"; break;
1080 case O_addrtype: name = "O_addrtype"; break;
1083 switch (t->X_md)
1085 default: namemd = "unknown"; break;
1086 case O_gotoff: namemd = "O_gotoff"; break;
1087 case O_gotpc: namemd = "O_gotpc"; break;
1088 case O_plt: namemd = "O_plt"; break;
1089 case O_sda: namemd = "O_sda"; break;
1090 case O_pcl: namemd = "O_pcl"; break;
1091 case O_tlsgd: namemd = "O_tlsgd"; break;
1092 case O_tlsie: namemd = "O_tlsie"; break;
1093 case O_tpoff9: namemd = "O_tpoff9"; break;
1094 case O_tpoff: namemd = "O_tpoff"; break;
1095 case O_dtpoff9: namemd = "O_dtpoff9"; break;
1096 case O_dtpoff: namemd = "O_dtpoff"; break;
1099 pr_debug ("%s (%s, %s, %d, %s)", name,
1100 (t->X_add_symbol) ? S_GET_NAME (t->X_add_symbol) : "--",
1101 (t->X_op_symbol) ? S_GET_NAME (t->X_op_symbol) : "--",
1102 (int) t->X_add_number,
1103 (t->X_md) ? namemd : "--");
1104 pr_debug ("\n");
1105 fflush (stderr);
1108 /* Helper for parsing an argument, used for sorting out the relocation
1109 type. */
1111 static void
1112 parse_reloc_symbol (expressionS *resultP)
1114 char *reloc_name, c, *sym_name;
1115 size_t len;
1116 int i;
1117 const struct arc_reloc_op_tag *r;
1118 expressionS right;
1119 symbolS *base;
1121 /* A relocation operand has the following form
1122 @identifier@relocation_type. The identifier is already in
1123 tok! */
1124 if (resultP->X_op != O_symbol)
1126 as_bad (_("No valid label relocation operand"));
1127 resultP->X_op = O_illegal;
1128 return;
1131 /* Parse @relocation_type. */
1132 input_line_pointer++;
1133 c = get_symbol_name (&reloc_name);
1134 len = input_line_pointer - reloc_name;
1135 if (len == 0)
1137 as_bad (_("No relocation operand"));
1138 resultP->X_op = O_illegal;
1139 return;
1142 /* Go through known relocation and try to find a match. */
1143 r = &arc_reloc_op[0];
1144 for (i = arc_num_reloc_op - 1; i >= 0; i--, r++)
1145 if (len == r->length
1146 && memcmp (reloc_name, r->name, len) == 0)
1147 break;
1148 if (i < 0)
1150 as_bad (_("Unknown relocation operand: @%s"), reloc_name);
1151 resultP->X_op = O_illegal;
1152 return;
1155 *input_line_pointer = c;
1156 SKIP_WHITESPACE_AFTER_NAME ();
1157 /* Extra check for TLS: base. */
1158 if (*input_line_pointer == '@')
1160 if (resultP->X_op_symbol != NULL
1161 || resultP->X_op != O_symbol)
1163 as_bad (_("Unable to parse TLS base: %s"),
1164 input_line_pointer);
1165 resultP->X_op = O_illegal;
1166 return;
1168 input_line_pointer++;
1169 c = get_symbol_name (&sym_name);
1170 base = symbol_find_or_make (sym_name);
1171 resultP->X_op = O_subtract;
1172 resultP->X_op_symbol = base;
1173 restore_line_pointer (c);
1174 right.X_add_number = 0;
1177 if ((*input_line_pointer != '+')
1178 && (*input_line_pointer != '-'))
1179 right.X_add_number = 0;
1180 else
1182 /* Parse the constant of a complex relocation expression
1183 like @identifier@reloc +/- const. */
1184 if (! r->complex_expr)
1186 as_bad (_("@%s is not a complex relocation."), r->name);
1187 resultP->X_op = O_illegal;
1188 return;
1190 expression (&right);
1191 if (right.X_op != O_constant)
1193 as_bad (_("Bad expression: @%s + %s."),
1194 r->name, input_line_pointer);
1195 resultP->X_op = O_illegal;
1196 return;
1200 resultP->X_md = r->op;
1201 resultP->X_add_number = right.X_add_number;
1204 /* Parse the arguments to an opcode. */
1206 static int
1207 tokenize_arguments (char *str,
1208 expressionS *tok,
1209 int ntok)
1211 char *old_input_line_pointer;
1212 bool saw_comma = false;
1213 bool saw_arg = false;
1214 int brk_lvl = 0;
1215 int num_args = 0;
1217 memset (tok, 0, sizeof (*tok) * ntok);
1219 /* Save and restore input_line_pointer around this function. */
1220 old_input_line_pointer = input_line_pointer;
1221 input_line_pointer = str;
1223 while (*input_line_pointer)
1225 SKIP_WHITESPACE ();
1226 switch (*input_line_pointer)
1228 case '\0':
1229 goto fini;
1231 case ',':
1232 input_line_pointer++;
1233 if (saw_comma || !saw_arg)
1234 goto err;
1235 saw_comma = true;
1236 break;
1238 case '}':
1239 case ']':
1240 ++input_line_pointer;
1241 --brk_lvl;
1242 if (!saw_arg || num_args == ntok)
1243 goto err;
1244 tok->X_op = O_bracket;
1245 ++tok;
1246 ++num_args;
1247 break;
1249 case '{':
1250 case '[':
1251 input_line_pointer++;
1252 if (brk_lvl || num_args == ntok)
1253 goto err;
1254 ++brk_lvl;
1255 tok->X_op = O_bracket;
1256 ++tok;
1257 ++num_args;
1258 break;
1260 case ':':
1261 input_line_pointer++;
1262 if (!saw_arg || num_args == ntok)
1263 goto err;
1264 tok->X_op = O_colon;
1265 saw_arg = false;
1266 ++tok;
1267 ++num_args;
1268 break;
1270 case '@':
1271 /* We have labels, function names and relocations, all
1272 starting with @ symbol. Sort them out. */
1273 if ((saw_arg && !saw_comma) || num_args == ntok)
1274 goto err;
1276 /* Parse @label. */
1277 input_line_pointer++;
1278 tok->X_op = O_symbol;
1279 tok->X_md = O_absent;
1280 expression (tok);
1282 if (*input_line_pointer == '@')
1283 parse_reloc_symbol (tok);
1285 debug_exp (tok);
1287 if (tok->X_op == O_illegal
1288 || tok->X_op == O_absent
1289 || num_args == ntok)
1290 goto err;
1292 saw_comma = false;
1293 saw_arg = true;
1294 tok++;
1295 num_args++;
1296 break;
1298 case '%':
1299 /* Can be a register. */
1300 ++input_line_pointer;
1301 /* Fall through. */
1302 default:
1304 if ((saw_arg && !saw_comma) || num_args == ntok)
1305 goto err;
1307 tok->X_op = O_absent;
1308 tok->X_md = O_absent;
1309 expression (tok);
1311 /* Legacy: There are cases when we have
1312 identifier@relocation_type, if it is the case parse the
1313 relocation type as well. */
1314 if (*input_line_pointer == '@')
1315 parse_reloc_symbol (tok);
1316 else
1317 resolve_register (tok);
1319 debug_exp (tok);
1321 if (tok->X_op == O_illegal
1322 || tok->X_op == O_absent
1323 || num_args == ntok)
1324 goto err;
1326 saw_comma = false;
1327 saw_arg = true;
1328 tok++;
1329 num_args++;
1330 break;
1334 fini:
1335 if (saw_comma || brk_lvl)
1336 goto err;
1337 input_line_pointer = old_input_line_pointer;
1339 return num_args;
1341 err:
1342 if (brk_lvl)
1343 as_bad (_("Brackets in operand field incorrect"));
1344 else if (saw_comma)
1345 as_bad (_("extra comma"));
1346 else if (!saw_arg)
1347 as_bad (_("missing argument"));
1348 else
1349 as_bad (_("missing comma or colon"));
1350 input_line_pointer = old_input_line_pointer;
1351 return -1;
1354 /* Parse the flags to a structure. */
1356 static int
1357 tokenize_flags (const char *str,
1358 struct arc_flags flags[],
1359 int nflg)
1361 char *old_input_line_pointer;
1362 bool saw_flg = false;
1363 bool saw_dot = false;
1364 int num_flags = 0;
1365 size_t flgnamelen;
1367 memset (flags, 0, sizeof (*flags) * nflg);
1369 /* Save and restore input_line_pointer around this function. */
1370 old_input_line_pointer = input_line_pointer;
1371 input_line_pointer = (char *) str;
1373 while (*input_line_pointer)
1375 switch (*input_line_pointer)
1377 case ' ':
1378 case '\0':
1379 goto fini;
1381 case '.':
1382 input_line_pointer++;
1383 if (saw_dot)
1384 goto err;
1385 saw_dot = true;
1386 saw_flg = false;
1387 break;
1389 default:
1390 if (saw_flg && !saw_dot)
1391 goto err;
1393 if (num_flags >= nflg)
1394 goto err;
1396 flgnamelen = strspn (input_line_pointer,
1397 "abcdefghijklmnopqrstuvwxyz0123456789");
1398 if (flgnamelen > MAX_FLAG_NAME_LENGTH)
1399 goto err;
1401 memcpy (flags->name, input_line_pointer, flgnamelen);
1403 input_line_pointer += flgnamelen;
1404 flags++;
1405 saw_dot = false;
1406 saw_flg = true;
1407 num_flags++;
1408 break;
1412 fini:
1413 input_line_pointer = old_input_line_pointer;
1414 return num_flags;
1416 err:
1417 if (saw_dot)
1418 as_bad (_("extra dot"));
1419 else if (!saw_flg)
1420 as_bad (_("unrecognized flag"));
1421 else
1422 as_bad (_("failed to parse flags"));
1423 input_line_pointer = old_input_line_pointer;
1424 return -1;
1427 /* Apply the fixups in order. */
1429 static void
1430 apply_fixups (struct arc_insn *insn, fragS *fragP, int fix)
1432 int i;
1434 for (i = 0; i < insn->nfixups; i++)
1436 struct arc_fixup *fixup = &insn->fixups[i];
1437 int size, pcrel, offset = 0;
1439 /* FIXME! the reloc size is wrong in the BFD file.
1440 When it is fixed please delete me. */
1441 size = ((insn->len == 2) && !fixup->islong) ? 2 : 4;
1443 if (fixup->islong)
1444 offset = insn->len;
1446 /* Some fixups are only used internally, thus no howto. */
1447 if ((int) fixup->reloc == 0)
1448 as_fatal (_("Unhandled reloc type"));
1450 if ((int) fixup->reloc < 0)
1452 /* FIXME! the reloc size is wrong in the BFD file.
1453 When it is fixed please enable me.
1454 size = ((insn->len == 2 && !fixup->islong) ? 2 : 4; */
1455 pcrel = fixup->pcrel;
1457 else
1459 reloc_howto_type *reloc_howto =
1460 bfd_reloc_type_lookup (stdoutput,
1461 (bfd_reloc_code_real_type) fixup->reloc);
1462 gas_assert (reloc_howto);
1464 /* FIXME! the reloc size is wrong in the BFD file.
1465 When it is fixed please enable me.
1466 size = bfd_get_reloc_size (reloc_howto); */
1467 pcrel = reloc_howto->pc_relative;
1470 pr_debug ("%s:%d: apply_fixups: new %s fixup (PCrel:%s) of size %d @ \
1471 offset %d + %d\n",
1472 fragP->fr_file, fragP->fr_line,
1473 (fixup->reloc < 0) ? "Internal" :
1474 bfd_get_reloc_code_name (fixup->reloc),
1475 pcrel ? "Y" : "N",
1476 size, fix, offset);
1477 fix_new_exp (fragP, fix + offset,
1478 size, &fixup->exp, pcrel, fixup->reloc);
1480 /* Check for ZOLs, and update symbol info if any. */
1481 if (LP_INSN (insn->insn))
1483 gas_assert (fixup->exp.X_add_symbol);
1484 ARC_SET_FLAG (fixup->exp.X_add_symbol, ARC_FLAG_ZOL);
1489 /* Actually output an instruction with its fixup. */
1491 static void
1492 emit_insn0 (struct arc_insn *insn, char *where, bool relax)
1494 char *f = where;
1495 size_t total_len;
1497 pr_debug ("Emit insn : 0x%llx\n", insn->insn);
1498 pr_debug ("\tLength : %d\n", insn->len);
1499 pr_debug ("\tLong imm: 0x%lx\n", insn->limm);
1501 /* Write out the instruction. */
1502 total_len = insn->len + (insn->has_limm ? 4 : 0);
1503 if (!relax)
1504 f = frag_more (total_len);
1506 md_number_to_chars_midend(f, insn->insn, insn->len);
1508 if (insn->has_limm)
1509 md_number_to_chars_midend (f + insn->len, insn->limm, 4);
1510 dwarf2_emit_insn (total_len);
1512 if (!relax)
1513 apply_fixups (insn, frag_now, (f - frag_now->fr_literal));
1516 static void
1517 emit_insn1 (struct arc_insn *insn)
1519 /* How frag_var's args are currently configured:
1520 - rs_machine_dependent, to dictate it's a relaxation frag.
1521 - FRAG_MAX_GROWTH, maximum size of instruction
1522 - 0, variable size that might grow...unused by generic relaxation.
1523 - frag_now->fr_subtype, fr_subtype starting value, set previously.
1524 - s, opand expression.
1525 - 0, offset but it's unused.
1526 - 0, opcode but it's unused. */
1527 symbolS *s = make_expr_symbol (&insn->fixups[0].exp);
1528 frag_now->tc_frag_data.pcrel = insn->fixups[0].pcrel;
1530 if (frag_room () < FRAG_MAX_GROWTH)
1532 /* Handle differently when frag literal memory is exhausted.
1533 This is used because when there's not enough memory left in
1534 the current frag, a new frag is created and the information
1535 we put into frag_now->tc_frag_data is disregarded. */
1537 struct arc_relax_type relax_info_copy;
1538 relax_substateT subtype = frag_now->fr_subtype;
1540 memcpy (&relax_info_copy, &frag_now->tc_frag_data,
1541 sizeof (struct arc_relax_type));
1543 frag_wane (frag_now);
1544 frag_grow (FRAG_MAX_GROWTH);
1546 memcpy (&frag_now->tc_frag_data, &relax_info_copy,
1547 sizeof (struct arc_relax_type));
1549 frag_var (rs_machine_dependent, FRAG_MAX_GROWTH, 0,
1550 subtype, s, 0, 0);
1552 else
1553 frag_var (rs_machine_dependent, FRAG_MAX_GROWTH, 0,
1554 frag_now->fr_subtype, s, 0, 0);
1557 static void
1558 emit_insn (struct arc_insn *insn)
1560 if (insn->relax)
1561 emit_insn1 (insn);
1562 else
1563 emit_insn0 (insn, NULL, false);
1566 /* Check whether a symbol involves a register. */
1568 static bool
1569 contains_register (symbolS *sym)
1571 if (sym)
1573 expressionS *ex = symbol_get_value_expression (sym);
1575 return ((O_register == ex->X_op)
1576 && !contains_register (ex->X_add_symbol)
1577 && !contains_register (ex->X_op_symbol));
1580 return false;
1583 /* Returns the register number within a symbol. */
1585 static int
1586 get_register (symbolS *sym)
1588 if (!contains_register (sym))
1589 return -1;
1591 expressionS *ex = symbol_get_value_expression (sym);
1592 return regno (ex->X_add_number);
1595 /* Return true if a RELOC is generic. A generic reloc is PC-rel of a
1596 simple ME relocation (e.g. RELOC_ARC_32_ME, BFD_RELOC_ARC_PC32. */
1598 static bool
1599 generic_reloc_p (extended_bfd_reloc_code_real_type reloc)
1601 if (!reloc)
1602 return false;
1604 switch (reloc)
1606 case BFD_RELOC_ARC_SDA_LDST:
1607 case BFD_RELOC_ARC_SDA_LDST1:
1608 case BFD_RELOC_ARC_SDA_LDST2:
1609 case BFD_RELOC_ARC_SDA16_LD:
1610 case BFD_RELOC_ARC_SDA16_LD1:
1611 case BFD_RELOC_ARC_SDA16_LD2:
1612 case BFD_RELOC_ARC_SDA16_ST2:
1613 case BFD_RELOC_ARC_SDA32_ME:
1614 return false;
1615 default:
1616 return true;
1620 /* Allocates a tok entry. */
1622 static int
1623 allocate_tok (expressionS *tok, int ntok, int cidx)
1625 if (ntok > MAX_INSN_ARGS - 2)
1626 return 0; /* No space left. */
1628 if (cidx > ntok)
1629 return 0; /* Incorrect args. */
1631 memcpy (&tok[ntok+1], &tok[ntok], sizeof (*tok));
1633 if (cidx == ntok)
1634 return 1; /* Success. */
1635 return allocate_tok (tok, ntok - 1, cidx);
1638 /* Check if an particular ARC feature is enabled. */
1640 static bool
1641 check_cpu_feature (insn_subclass_t sc)
1643 if (is_code_density_p (sc) && !(selected_cpu.features & CD))
1644 return false;
1646 if (is_spfp_p (sc) && !(selected_cpu.features & SPX))
1647 return false;
1649 if (is_dpfp_p (sc) && !(selected_cpu.features & DPX))
1650 return false;
1652 if (is_fpuda_p (sc) && !(selected_cpu.features & DPA))
1653 return false;
1655 if (is_nps400_p (sc) && !(selected_cpu.features & NPS400))
1656 return false;
1658 return true;
1661 /* Parse the flags described by FIRST_PFLAG and NFLGS against the flag
1662 operands in OPCODE. Stores the matching OPCODES into the FIRST_PFLAG
1663 array and returns TRUE if the flag operands all match, otherwise,
1664 returns FALSE, in which case the FIRST_PFLAG array may have been
1665 modified. */
1667 static bool
1668 parse_opcode_flags (const struct arc_opcode *opcode,
1669 int nflgs,
1670 struct arc_flags *first_pflag)
1672 int lnflg, i;
1673 const unsigned char *flgidx;
1675 lnflg = nflgs;
1676 for (i = 0; i < nflgs; i++)
1677 first_pflag[i].flgp = NULL;
1679 /* Check the flags. Iterate over the valid flag classes. */
1680 for (flgidx = opcode->flags; *flgidx; ++flgidx)
1682 /* Get a valid flag class. */
1683 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
1684 const unsigned *flgopridx;
1685 int cl_matches = 0;
1686 struct arc_flags *pflag = NULL;
1688 /* Check if opcode has implicit flag classes. */
1689 if (cl_flags->flag_class & F_CLASS_IMPLICIT)
1690 continue;
1692 /* Check for extension conditional codes. */
1693 if (ext_condcode.arc_ext_condcode
1694 && cl_flags->flag_class & F_CLASS_EXTEND)
1696 struct arc_flag_operand *pf = ext_condcode.arc_ext_condcode;
1697 while (pf->name)
1699 pflag = first_pflag;
1700 for (i = 0; i < nflgs; i++, pflag++)
1702 if (!strcmp (pf->name, pflag->name))
1704 if (pflag->flgp != NULL)
1705 return false;
1706 /* Found it. */
1707 cl_matches++;
1708 pflag->flgp = pf;
1709 lnflg--;
1710 break;
1713 pf++;
1717 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
1719 const struct arc_flag_operand *flg_operand;
1721 pflag = first_pflag;
1722 flg_operand = &arc_flag_operands[*flgopridx];
1723 for (i = 0; i < nflgs; i++, pflag++)
1725 /* Match against the parsed flags. */
1726 if (!strcmp (flg_operand->name, pflag->name))
1728 if (pflag->flgp != NULL)
1729 return false;
1730 cl_matches++;
1731 pflag->flgp = flg_operand;
1732 lnflg--;
1733 break; /* goto next flag class and parsed flag. */
1738 if ((cl_flags->flag_class & F_CLASS_REQUIRED) && cl_matches == 0)
1739 return false;
1740 if ((cl_flags->flag_class & F_CLASS_OPTIONAL) && cl_matches > 1)
1741 return false;
1744 /* Did I check all the parsed flags? */
1745 return lnflg == 0;
1749 /* Search forward through all variants of an opcode looking for a
1750 syntax match. */
1752 static const struct arc_opcode *
1753 find_opcode_match (const struct arc_opcode_hash_entry *entry,
1754 expressionS *tok,
1755 int *pntok,
1756 struct arc_flags *first_pflag,
1757 int nflgs,
1758 int *pcpumatch,
1759 const char **errmsg)
1761 const struct arc_opcode *opcode;
1762 struct arc_opcode_hash_entry_iterator iter;
1763 int ntok = *pntok;
1764 int got_cpu_match = 0;
1765 expressionS bktok[MAX_INSN_ARGS];
1766 int bkntok, maxerridx = 0;
1767 expressionS emptyE;
1768 const char *tmpmsg = NULL;
1770 arc_opcode_hash_entry_iterator_init (&iter);
1771 memset (&emptyE, 0, sizeof (emptyE));
1772 memcpy (bktok, tok, MAX_INSN_ARGS * sizeof (*tok));
1773 bkntok = ntok;
1775 for (opcode = arc_opcode_hash_entry_iterator_next (entry, &iter);
1776 opcode != NULL;
1777 opcode = arc_opcode_hash_entry_iterator_next (entry, &iter))
1779 const unsigned char *opidx;
1780 int tokidx = 0;
1781 const expressionS *t = &emptyE;
1783 pr_debug ("%s:%d: find_opcode_match: trying opcode 0x%08llX ",
1784 frag_now->fr_file, frag_now->fr_line, opcode->opcode);
1786 /* Don't match opcodes that don't exist on this
1787 architecture. */
1788 if (!(opcode->cpu & selected_cpu.flags))
1789 goto match_failed;
1791 if (!check_cpu_feature (opcode->subclass))
1792 goto match_failed;
1794 got_cpu_match = 1;
1795 pr_debug ("cpu ");
1797 /* Check the operands. */
1798 for (opidx = opcode->operands; *opidx; ++opidx)
1800 const struct arc_operand *operand = &arc_operands[*opidx];
1802 /* Only take input from real operands. */
1803 if (ARC_OPERAND_IS_FAKE (operand))
1804 continue;
1806 /* When we expect input, make sure we have it. */
1807 if (tokidx >= ntok)
1808 goto match_failed;
1810 /* Match operand type with expression type. */
1811 switch (operand->flags & ARC_OPERAND_TYPECHECK_MASK)
1813 case ARC_OPERAND_ADDRTYPE:
1815 tmpmsg = NULL;
1817 /* Check to be an address type. */
1818 if (tok[tokidx].X_op != O_addrtype)
1819 goto match_failed;
1821 /* All address type operands need to have an insert
1822 method in order to check that we have the correct
1823 address type. */
1824 gas_assert (operand->insert != NULL);
1825 (*operand->insert) (0, tok[tokidx].X_add_number,
1826 &tmpmsg);
1827 if (tmpmsg != NULL)
1828 goto match_failed;
1830 break;
1832 case ARC_OPERAND_IR:
1833 /* Check to be a register. */
1834 if ((tok[tokidx].X_op != O_register
1835 || !is_ir_num (tok[tokidx].X_add_number))
1836 && !(operand->flags & ARC_OPERAND_IGNORE))
1837 goto match_failed;
1839 /* If expect duplicate, make sure it is duplicate. */
1840 if (operand->flags & ARC_OPERAND_DUPLICATE)
1842 /* Check for duplicate. */
1843 if (t->X_op != O_register
1844 || !is_ir_num (t->X_add_number)
1845 || (regno (t->X_add_number) !=
1846 regno (tok[tokidx].X_add_number)))
1847 goto match_failed;
1850 /* Special handling? */
1851 if (operand->insert)
1853 tmpmsg = NULL;
1854 (*operand->insert)(0,
1855 regno (tok[tokidx].X_add_number),
1856 &tmpmsg);
1857 if (tmpmsg)
1859 if (operand->flags & ARC_OPERAND_IGNORE)
1861 /* Missing argument, create one. */
1862 if (!allocate_tok (tok, ntok - 1, tokidx))
1863 goto match_failed;
1865 tok[tokidx].X_op = O_absent;
1866 ++ntok;
1868 else
1869 goto match_failed;
1873 t = &tok[tokidx];
1874 break;
1876 case ARC_OPERAND_BRAKET:
1877 /* Check if bracket is also in opcode table as
1878 operand. */
1879 if (tok[tokidx].X_op != O_bracket)
1880 goto match_failed;
1881 break;
1883 case ARC_OPERAND_COLON:
1884 /* Check if colon is also in opcode table as operand. */
1885 if (tok[tokidx].X_op != O_colon)
1886 goto match_failed;
1887 break;
1889 case ARC_OPERAND_LIMM:
1890 case ARC_OPERAND_SIGNED:
1891 case ARC_OPERAND_UNSIGNED:
1892 switch (tok[tokidx].X_op)
1894 case O_illegal:
1895 case O_absent:
1896 case O_register:
1897 goto match_failed;
1899 case O_bracket:
1900 /* Got an (too) early bracket, check if it is an
1901 ignored operand. N.B. This procedure works only
1902 when bracket is the last operand! */
1903 if (!(operand->flags & ARC_OPERAND_IGNORE))
1904 goto match_failed;
1905 /* Insert the missing operand. */
1906 if (!allocate_tok (tok, ntok - 1, tokidx))
1907 goto match_failed;
1909 tok[tokidx].X_op = O_absent;
1910 ++ntok;
1911 break;
1913 case O_symbol:
1915 const char *p;
1916 char *tmpp, *pp;
1917 const struct arc_aux_reg *auxr;
1919 if (opcode->insn_class != AUXREG)
1920 goto de_fault;
1921 p = S_GET_NAME (tok[tokidx].X_add_symbol);
1923 /* For compatibility reasons, an aux register can
1924 be spelled with upper or lower case
1925 letters. */
1926 tmpp = strdup (p);
1927 for (pp = tmpp; *pp; ++pp) *pp = TOLOWER (*pp);
1929 auxr = str_hash_find (arc_aux_hash, tmpp);
1930 if (auxr)
1932 /* We modify the token array here, safe in the
1933 knowledge, that if this was the wrong
1934 choice then the original contents will be
1935 restored from BKTOK. */
1936 tok[tokidx].X_op = O_constant;
1937 tok[tokidx].X_add_number = auxr->address;
1938 ARC_SET_FLAG (tok[tokidx].X_add_symbol, ARC_FLAG_AUX);
1940 free (tmpp);
1942 if (tok[tokidx].X_op != O_constant)
1943 goto de_fault;
1945 /* Fall through. */
1946 case O_constant:
1947 /* Check the range. */
1948 if (operand->bits != 32
1949 && !(operand->flags & ARC_OPERAND_NCHK))
1951 offsetT min, max, val;
1952 val = tok[tokidx].X_add_number;
1954 if (operand->flags & ARC_OPERAND_SIGNED)
1956 max = (1 << (operand->bits - 1)) - 1;
1957 min = -(1 << (operand->bits - 1));
1959 else
1961 max = (1 << operand->bits) - 1;
1962 min = 0;
1965 if (val < min || val > max)
1967 tmpmsg = _("immediate is out of bounds");
1968 goto match_failed;
1971 /* Check alignments. */
1972 if ((operand->flags & ARC_OPERAND_ALIGNED32)
1973 && (val & 0x03))
1975 tmpmsg = _("immediate is not 32bit aligned");
1976 goto match_failed;
1979 if ((operand->flags & ARC_OPERAND_ALIGNED16)
1980 && (val & 0x01))
1982 tmpmsg = _("immediate is not 16bit aligned");
1983 goto match_failed;
1986 else if (operand->flags & ARC_OPERAND_NCHK)
1988 if (operand->insert)
1990 tmpmsg = NULL;
1991 (*operand->insert)(0,
1992 tok[tokidx].X_add_number,
1993 &tmpmsg);
1994 if (tmpmsg)
1995 goto match_failed;
1997 else if (!(operand->flags & ARC_OPERAND_IGNORE))
1998 goto match_failed;
2000 break;
2002 case O_subtract:
2003 /* Check if it is register range. */
2004 if ((tok[tokidx].X_add_number == 0)
2005 && contains_register (tok[tokidx].X_add_symbol)
2006 && contains_register (tok[tokidx].X_op_symbol))
2008 int regs;
2010 regs = get_register (tok[tokidx].X_add_symbol);
2011 regs <<= 16;
2012 regs |= get_register (tok[tokidx].X_op_symbol);
2013 if (operand->insert)
2015 tmpmsg = NULL;
2016 (*operand->insert)(0,
2017 regs,
2018 &tmpmsg);
2019 if (tmpmsg)
2020 goto match_failed;
2022 else
2023 goto match_failed;
2024 break;
2026 /* Fall through. */
2027 default:
2028 de_fault:
2029 if (operand->default_reloc == 0)
2030 goto match_failed; /* The operand needs relocation. */
2032 /* Relocs requiring long immediate. FIXME! make it
2033 generic and move it to a function. */
2034 switch (tok[tokidx].X_md)
2036 case O_gotoff:
2037 case O_gotpc:
2038 case O_pcl:
2039 case O_tpoff:
2040 case O_dtpoff:
2041 case O_tlsgd:
2042 case O_tlsie:
2043 if (!(operand->flags & ARC_OPERAND_LIMM))
2044 goto match_failed;
2045 /* Fall through. */
2046 case O_absent:
2047 if (!generic_reloc_p (operand->default_reloc))
2048 goto match_failed;
2049 break;
2050 default:
2051 break;
2053 break;
2055 /* If expect duplicate, make sure it is duplicate. */
2056 if (operand->flags & ARC_OPERAND_DUPLICATE)
2058 if (t->X_op == O_illegal
2059 || t->X_op == O_absent
2060 || t->X_op == O_register
2061 || (t->X_add_number != tok[tokidx].X_add_number))
2063 tmpmsg = _("operand is not duplicate of the "
2064 "previous one");
2065 goto match_failed;
2068 t = &tok[tokidx];
2069 break;
2071 default:
2072 /* Everything else should have been fake. */
2073 abort ();
2076 ++tokidx;
2078 pr_debug ("opr ");
2080 /* Setup ready for flag parsing. */
2081 if (!parse_opcode_flags (opcode, nflgs, first_pflag))
2083 tmpmsg = _("flag mismatch");
2084 goto match_failed;
2087 pr_debug ("flg");
2088 /* Possible match -- did we use all of our input? */
2089 if (tokidx == ntok)
2091 *pntok = ntok;
2092 pr_debug ("\n");
2093 return opcode;
2095 tmpmsg = _("too many arguments");
2097 match_failed:;
2098 pr_debug ("\n");
2099 /* Restore the original parameters. */
2100 memcpy (tok, bktok, MAX_INSN_ARGS * sizeof (*tok));
2101 ntok = bkntok;
2102 if (tokidx >= maxerridx
2103 && tmpmsg)
2105 maxerridx = tokidx;
2106 *errmsg = tmpmsg;
2110 if (*pcpumatch)
2111 *pcpumatch = got_cpu_match;
2113 return NULL;
2116 /* Swap operand tokens. */
2118 static void
2119 swap_operand (expressionS *operand_array,
2120 unsigned source,
2121 unsigned destination)
2123 expressionS cpy_operand;
2124 expressionS *src_operand;
2125 expressionS *dst_operand;
2126 size_t size;
2128 if (source == destination)
2129 return;
2131 src_operand = &operand_array[source];
2132 dst_operand = &operand_array[destination];
2133 size = sizeof (expressionS);
2135 /* Make copy of operand to swap with and swap. */
2136 memcpy (&cpy_operand, dst_operand, size);
2137 memcpy (dst_operand, src_operand, size);
2138 memcpy (src_operand, &cpy_operand, size);
2141 /* Check if *op matches *tok type.
2142 Returns FALSE if they don't match, TRUE if they match. */
2144 static bool
2145 pseudo_operand_match (const expressionS *tok,
2146 const struct arc_operand_operation *op)
2148 offsetT min, max, val;
2149 bool ret;
2150 const struct arc_operand *operand_real = &arc_operands[op->operand_idx];
2152 ret = false;
2153 switch (tok->X_op)
2155 case O_constant:
2156 if (operand_real->bits == 32 && (operand_real->flags & ARC_OPERAND_LIMM))
2157 ret = 1;
2158 else if (!(operand_real->flags & ARC_OPERAND_IR))
2160 val = tok->X_add_number + op->count;
2161 if (operand_real->flags & ARC_OPERAND_SIGNED)
2163 max = (1 << (operand_real->bits - 1)) - 1;
2164 min = -(1 << (operand_real->bits - 1));
2166 else
2168 max = (1 << operand_real->bits) - 1;
2169 min = 0;
2171 if (min <= val && val <= max)
2172 ret = true;
2174 break;
2176 case O_symbol:
2177 /* Handle all symbols as long immediates or signed 9. */
2178 if (operand_real->flags & ARC_OPERAND_LIMM
2179 || ((operand_real->flags & ARC_OPERAND_SIGNED)
2180 && operand_real->bits == 9))
2181 ret = true;
2182 break;
2184 case O_register:
2185 if (operand_real->flags & ARC_OPERAND_IR)
2186 ret = true;
2187 break;
2189 case O_bracket:
2190 if (operand_real->flags & ARC_OPERAND_BRAKET)
2191 ret = true;
2192 break;
2194 default:
2195 /* Unknown. */
2196 break;
2198 return ret;
2201 /* Find pseudo instruction in array. */
2203 static const struct arc_pseudo_insn *
2204 find_pseudo_insn (const char *opname,
2205 int ntok,
2206 const expressionS *tok)
2208 const struct arc_pseudo_insn *pseudo_insn = NULL;
2209 const struct arc_operand_operation *op;
2210 unsigned int i;
2211 int j;
2213 for (i = 0; i < arc_num_pseudo_insn; ++i)
2215 pseudo_insn = &arc_pseudo_insns[i];
2216 if (strcmp (pseudo_insn->mnemonic_p, opname) == 0)
2218 op = pseudo_insn->operand;
2219 for (j = 0; j < ntok; ++j)
2220 if (!pseudo_operand_match (&tok[j], &op[j]))
2221 break;
2223 /* Found the right instruction. */
2224 if (j == ntok)
2225 return pseudo_insn;
2228 return NULL;
2231 /* Assumes the expressionS *tok is of sufficient size. */
2233 static const struct arc_opcode_hash_entry *
2234 find_special_case_pseudo (const char *opname,
2235 int *ntok,
2236 expressionS *tok,
2237 int *nflgs,
2238 struct arc_flags *pflags)
2240 const struct arc_pseudo_insn *pseudo_insn = NULL;
2241 const struct arc_operand_operation *operand_pseudo;
2242 const struct arc_operand *operand_real;
2243 unsigned i;
2244 char construct_operand[MAX_CONSTR_STR];
2246 /* Find whether opname is in pseudo instruction array. */
2247 pseudo_insn = find_pseudo_insn (opname, *ntok, tok);
2249 if (pseudo_insn == NULL)
2250 return NULL;
2252 /* Handle flag, Limited to one flag at the moment. */
2253 if (pseudo_insn->flag_r != NULL)
2254 *nflgs += tokenize_flags (pseudo_insn->flag_r, &pflags[*nflgs],
2255 MAX_INSN_FLGS - *nflgs);
2257 /* Handle operand operations. */
2258 for (i = 0; i < pseudo_insn->operand_cnt; ++i)
2260 operand_pseudo = &pseudo_insn->operand[i];
2261 operand_real = &arc_operands[operand_pseudo->operand_idx];
2263 if (operand_real->flags & ARC_OPERAND_BRAKET
2264 && !operand_pseudo->needs_insert)
2265 continue;
2267 /* Has to be inserted (i.e. this token does not exist yet). */
2268 if (operand_pseudo->needs_insert)
2270 if (operand_real->flags & ARC_OPERAND_BRAKET)
2272 tok[i].X_op = O_bracket;
2273 ++(*ntok);
2274 continue;
2277 /* Check if operand is a register or constant and handle it
2278 by type. */
2279 if (operand_real->flags & ARC_OPERAND_IR)
2280 snprintf (construct_operand, MAX_CONSTR_STR, "r%d",
2281 operand_pseudo->count);
2282 else
2283 snprintf (construct_operand, MAX_CONSTR_STR, "%d",
2284 operand_pseudo->count);
2286 tokenize_arguments (construct_operand, &tok[i], 1);
2287 ++(*ntok);
2290 else if (operand_pseudo->count)
2292 /* Operand number has to be adjusted accordingly (by operand
2293 type). */
2294 switch (tok[i].X_op)
2296 case O_constant:
2297 tok[i].X_add_number += operand_pseudo->count;
2298 break;
2300 case O_symbol:
2301 break;
2303 default:
2304 /* Ignored. */
2305 break;
2310 /* Swap operands if necessary. Only supports one swap at the
2311 moment. */
2312 for (i = 0; i < pseudo_insn->operand_cnt; ++i)
2314 operand_pseudo = &pseudo_insn->operand[i];
2316 if (operand_pseudo->swap_operand_idx == i)
2317 continue;
2319 swap_operand (tok, i, operand_pseudo->swap_operand_idx);
2321 /* Prevent a swap back later by breaking out. */
2322 break;
2325 return arc_find_opcode (pseudo_insn->mnemonic_r);
2328 static const struct arc_opcode_hash_entry *
2329 find_special_case_flag (const char *opname,
2330 int *nflgs,
2331 struct arc_flags *pflags)
2333 unsigned int i;
2334 const char *flagnm;
2335 unsigned flag_idx, flag_arr_idx;
2336 size_t flaglen, oplen;
2337 const struct arc_flag_special *arc_flag_special_opcode;
2338 const struct arc_opcode_hash_entry *entry;
2340 /* Search for special case instruction. */
2341 for (i = 0; i < arc_num_flag_special; i++)
2343 arc_flag_special_opcode = &arc_flag_special_cases[i];
2344 oplen = strlen (arc_flag_special_opcode->name);
2346 if (strncmp (opname, arc_flag_special_opcode->name, oplen) != 0)
2347 continue;
2349 /* Found a potential special case instruction, now test for
2350 flags. */
2351 for (flag_arr_idx = 0;; ++flag_arr_idx)
2353 flag_idx = arc_flag_special_opcode->flags[flag_arr_idx];
2354 if (flag_idx == 0)
2355 break; /* End of array, nothing found. */
2357 flagnm = arc_flag_operands[flag_idx].name;
2358 flaglen = strlen (flagnm);
2359 if (strcmp (opname + oplen, flagnm) == 0)
2361 entry = arc_find_opcode (arc_flag_special_opcode->name);
2363 if (*nflgs + 1 > MAX_INSN_FLGS)
2364 break;
2365 memcpy (pflags[*nflgs].name, flagnm, flaglen);
2366 pflags[*nflgs].name[flaglen] = '\0';
2367 (*nflgs)++;
2368 return entry;
2372 return NULL;
2375 /* Used to find special case opcode. */
2377 static const struct arc_opcode_hash_entry *
2378 find_special_case (const char *opname,
2379 int *nflgs,
2380 struct arc_flags *pflags,
2381 expressionS *tok,
2382 int *ntok)
2384 const struct arc_opcode_hash_entry *entry;
2386 entry = find_special_case_pseudo (opname, ntok, tok, nflgs, pflags);
2388 if (entry == NULL)
2389 entry = find_special_case_flag (opname, nflgs, pflags);
2391 return entry;
2394 /* Autodetect cpu attribute list. */
2396 static void
2397 autodetect_attributes (const struct arc_opcode *opcode,
2398 const expressionS *tok,
2399 int ntok)
2401 unsigned i;
2402 struct mpy_type
2404 unsigned feature;
2405 unsigned encoding;
2406 } mpy_list[] = {{ MPY1E, 1 }, { MPY6E, 6 }, { MPY7E, 7 }, { MPY8E, 8 },
2407 { MPY9E, 9 }};
2409 for (i = 0; i < ARRAY_SIZE (feature_list); i++)
2410 if (opcode->subclass == feature_list[i].feature)
2411 selected_cpu.features |= feature_list[i].feature;
2413 for (i = 0; i < ARRAY_SIZE (mpy_list); i++)
2414 if (opcode->subclass == mpy_list[i].feature)
2415 mpy_option = mpy_list[i].encoding;
2417 for (i = 0; i < (unsigned) ntok; i++)
2419 switch (tok[i].X_md)
2421 case O_gotoff:
2422 case O_gotpc:
2423 case O_plt:
2424 pic_option = 2;
2425 break;
2426 case O_sda:
2427 sda_option = 2;
2428 break;
2429 case O_tlsgd:
2430 case O_tlsie:
2431 case O_tpoff9:
2432 case O_tpoff:
2433 case O_dtpoff9:
2434 case O_dtpoff:
2435 tls_option = 1;
2436 break;
2437 default:
2438 break;
2441 switch (tok[i].X_op)
2443 case O_register:
2444 if ((tok[i].X_add_number >= 4 && tok[i].X_add_number <= 9)
2445 || (tok[i].X_add_number >= 16 && tok[i].X_add_number <= 25))
2446 rf16_only = false;
2447 break;
2448 default:
2449 break;
2454 /* Given an opcode name, pre-tockenized set of argumenst and the
2455 opcode flags, take it all the way through emission. */
2457 static void
2458 assemble_tokens (const char *opname,
2459 expressionS *tok,
2460 int ntok,
2461 struct arc_flags *pflags,
2462 int nflgs)
2464 bool found_something = false;
2465 const struct arc_opcode_hash_entry *entry;
2466 int cpumatch = 1;
2467 const char *errmsg = NULL;
2469 /* Search opcodes. */
2470 entry = arc_find_opcode (opname);
2472 /* Couldn't find opcode conventional way, try special cases. */
2473 if (entry == NULL)
2474 entry = find_special_case (opname, &nflgs, pflags, tok, &ntok);
2476 if (entry != NULL)
2478 const struct arc_opcode *opcode;
2480 pr_debug ("%s:%d: assemble_tokens: %s\n",
2481 frag_now->fr_file, frag_now->fr_line, opname);
2482 found_something = true;
2483 opcode = find_opcode_match (entry, tok, &ntok, pflags,
2484 nflgs, &cpumatch, &errmsg);
2485 if (opcode != NULL)
2487 struct arc_insn insn;
2489 autodetect_attributes (opcode, tok, ntok);
2490 assemble_insn (opcode, tok, ntok, pflags, nflgs, &insn);
2491 emit_insn (&insn);
2492 return;
2496 if (found_something)
2498 if (cpumatch)
2499 if (errmsg)
2500 as_bad (_("%s for instruction '%s'"), errmsg, opname);
2501 else
2502 as_bad (_("inappropriate arguments for opcode '%s'"), opname);
2503 else
2504 as_bad (_("opcode '%s' not supported for target %s"), opname,
2505 selected_cpu.name);
2507 else
2508 as_bad (_("unknown opcode '%s'"), opname);
2511 /* The public interface to the instruction assembler. */
2513 void
2514 md_assemble (char *str)
2516 char *opname;
2517 expressionS tok[MAX_INSN_ARGS];
2518 int ntok, nflg;
2519 size_t opnamelen;
2520 struct arc_flags flags[MAX_INSN_FLGS];
2522 /* Split off the opcode. */
2523 opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_0123456789");
2524 opname = xmemdup0 (str, opnamelen);
2526 /* Signalize we are assembling the instructions. */
2527 assembling_insn = true;
2529 /* Tokenize the flags. */
2530 if ((nflg = tokenize_flags (str + opnamelen, flags, MAX_INSN_FLGS)) == -1)
2532 as_bad (_("syntax error"));
2533 return;
2536 /* Scan up to the end of the mnemonic which must end in space or end
2537 of string. */
2538 str += opnamelen;
2539 for (; *str != '\0'; str++)
2540 if (*str == ' ')
2541 break;
2543 /* Tokenize the rest of the line. */
2544 if ((ntok = tokenize_arguments (str, tok, MAX_INSN_ARGS)) < 0)
2546 as_bad (_("syntax error"));
2547 return;
2550 /* Finish it off. */
2551 assemble_tokens (opname, tok, ntok, flags, nflg);
2552 assembling_insn = false;
2555 /* Callback to insert a register into the hash table. */
2557 static void
2558 declare_register (const char *name, int number)
2560 symbolS *regS = symbol_create (name, reg_section,
2561 &zero_address_frag, number);
2563 if (str_hash_insert (arc_reg_hash, S_GET_NAME (regS), regS, 0) != NULL)
2564 as_fatal (_("duplicate %s"), name);
2567 /* Construct symbols for each of the general registers. */
2569 static void
2570 declare_register_set (void)
2572 int i;
2573 for (i = 0; i < 64; ++i)
2575 char name[32];
2577 sprintf (name, "r%d", i);
2578 declare_register (name, i);
2579 if ((i & 0x01) == 0)
2581 sprintf (name, "r%dr%d", i, i+1);
2582 declare_register (name, i);
2587 /* Construct a symbol for an address type. */
2589 static void
2590 declare_addrtype (const char *name, int number)
2592 symbolS *addrtypeS = symbol_create (name, undefined_section,
2593 &zero_address_frag, number);
2595 if (str_hash_insert (arc_addrtype_hash, S_GET_NAME (addrtypeS), addrtypeS, 0))
2596 as_fatal (_("duplicate %s"), name);
2599 /* Port-specific assembler initialization. This function is called
2600 once, at assembler startup time. */
2602 void
2603 md_begin (void)
2605 const struct arc_opcode *opcode = arc_opcodes;
2607 if (mach_selection_mode == MACH_SELECTION_NONE)
2608 arc_select_cpu (TARGET_WITH_CPU, MACH_SELECTION_FROM_DEFAULT);
2610 /* The endianness can be chosen "at the factory". */
2611 target_big_endian = byte_order == BIG_ENDIAN;
2613 if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, selected_cpu.mach))
2614 as_warn (_("could not set architecture and machine"));
2616 /* Set elf header flags. */
2617 bfd_set_private_flags (stdoutput, selected_cpu.eflags);
2619 /* Set up a hash table for the instructions. */
2620 arc_opcode_hash = htab_create_alloc (16, hash_string_tuple, eq_string_tuple,
2621 arc_opcode_free, xcalloc, free);
2623 /* Initialize the hash table with the insns. */
2626 const char *name = opcode->name;
2628 arc_insert_opcode (opcode);
2630 while (++opcode && opcode->name
2631 && (opcode->name == name
2632 || !strcmp (opcode->name, name)))
2633 continue;
2634 }while (opcode->name);
2636 /* Register declaration. */
2637 arc_reg_hash = str_htab_create ();
2639 declare_register_set ();
2640 declare_register ("gp", 26);
2641 declare_register ("fp", 27);
2642 declare_register ("sp", 28);
2643 declare_register ("ilink", 29);
2644 declare_register ("ilink1", 29);
2645 declare_register ("ilink2", 30);
2646 declare_register ("blink", 31);
2648 /* XY memory registers. */
2649 declare_register ("x0_u0", 32);
2650 declare_register ("x0_u1", 33);
2651 declare_register ("x1_u0", 34);
2652 declare_register ("x1_u1", 35);
2653 declare_register ("x2_u0", 36);
2654 declare_register ("x2_u1", 37);
2655 declare_register ("x3_u0", 38);
2656 declare_register ("x3_u1", 39);
2657 declare_register ("y0_u0", 40);
2658 declare_register ("y0_u1", 41);
2659 declare_register ("y1_u0", 42);
2660 declare_register ("y1_u1", 43);
2661 declare_register ("y2_u0", 44);
2662 declare_register ("y2_u1", 45);
2663 declare_register ("y3_u0", 46);
2664 declare_register ("y3_u1", 47);
2665 declare_register ("x0_nu", 48);
2666 declare_register ("x1_nu", 49);
2667 declare_register ("x2_nu", 50);
2668 declare_register ("x3_nu", 51);
2669 declare_register ("y0_nu", 52);
2670 declare_register ("y1_nu", 53);
2671 declare_register ("y2_nu", 54);
2672 declare_register ("y3_nu", 55);
2674 declare_register ("mlo", 57);
2675 declare_register ("mmid", 58);
2676 declare_register ("mhi", 59);
2678 declare_register ("acc1", 56);
2679 declare_register ("acc2", 57);
2681 declare_register ("lp_count", 60);
2682 declare_register ("pcl", 63);
2684 /* Initialize the last instructions. */
2685 memset (&arc_last_insns[0], 0, sizeof (arc_last_insns));
2687 /* Aux register declaration. */
2688 arc_aux_hash = str_htab_create ();
2690 const struct arc_aux_reg *auxr = &arc_aux_regs[0];
2691 unsigned int i;
2692 for (i = 0; i < arc_num_aux_regs; i++, auxr++)
2694 if (!(auxr->cpu & selected_cpu.flags))
2695 continue;
2697 if ((auxr->subclass != NONE)
2698 && !check_cpu_feature (auxr->subclass))
2699 continue;
2701 if (str_hash_insert (arc_aux_hash, auxr->name, auxr, 0) != 0)
2702 as_fatal (_("duplicate %s"), auxr->name);
2705 /* Address type declaration. */
2706 arc_addrtype_hash = str_htab_create ();
2708 declare_addrtype ("bd", ARC_NPS400_ADDRTYPE_BD);
2709 declare_addrtype ("jid", ARC_NPS400_ADDRTYPE_JID);
2710 declare_addrtype ("lbd", ARC_NPS400_ADDRTYPE_LBD);
2711 declare_addrtype ("mbd", ARC_NPS400_ADDRTYPE_MBD);
2712 declare_addrtype ("sd", ARC_NPS400_ADDRTYPE_SD);
2713 declare_addrtype ("sm", ARC_NPS400_ADDRTYPE_SM);
2714 declare_addrtype ("xa", ARC_NPS400_ADDRTYPE_XA);
2715 declare_addrtype ("xd", ARC_NPS400_ADDRTYPE_XD);
2716 declare_addrtype ("cd", ARC_NPS400_ADDRTYPE_CD);
2717 declare_addrtype ("cbd", ARC_NPS400_ADDRTYPE_CBD);
2718 declare_addrtype ("cjid", ARC_NPS400_ADDRTYPE_CJID);
2719 declare_addrtype ("clbd", ARC_NPS400_ADDRTYPE_CLBD);
2720 declare_addrtype ("cm", ARC_NPS400_ADDRTYPE_CM);
2721 declare_addrtype ("csd", ARC_NPS400_ADDRTYPE_CSD);
2722 declare_addrtype ("cxa", ARC_NPS400_ADDRTYPE_CXA);
2723 declare_addrtype ("cxd", ARC_NPS400_ADDRTYPE_CXD);
2726 void
2727 arc_md_end (void)
2729 htab_delete (arc_opcode_hash);
2730 htab_delete (arc_reg_hash);
2731 htab_delete (arc_aux_hash);
2732 htab_delete (arc_addrtype_hash);
2735 /* Write a value out to the object file, using the appropriate
2736 endianness. */
2738 void
2739 md_number_to_chars (char *buf,
2740 valueT val,
2741 int n)
2743 if (target_big_endian)
2744 number_to_chars_bigendian (buf, val, n);
2745 else
2746 number_to_chars_littleendian (buf, val, n);
2749 /* Round up a section size to the appropriate boundary. */
2751 valueT
2752 md_section_align (segT segment,
2753 valueT size)
2755 int align = bfd_section_alignment (segment);
2757 return ((size + (1 << align) - 1) & (-((valueT) 1 << align)));
2760 /* The location from which a PC relative jump should be calculated,
2761 given a PC relative reloc. */
2763 long
2764 md_pcrel_from_section (fixS *fixP,
2765 segT sec)
2767 offsetT base = fixP->fx_where + fixP->fx_frag->fr_address;
2769 pr_debug ("pcrel_from_section, fx_offset = %d\n", (int) fixP->fx_offset);
2771 if (fixP->fx_addsy != (symbolS *) NULL
2772 && (!S_IS_DEFINED (fixP->fx_addsy)
2773 || S_GET_SEGMENT (fixP->fx_addsy) != sec))
2775 pr_debug ("Unknown pcrel symbol: %s\n", S_GET_NAME (fixP->fx_addsy));
2777 /* The symbol is undefined (or is defined but not in this section).
2778 Let the linker figure it out. */
2779 return 0;
2782 if ((int) fixP->fx_r_type < 0)
2784 /* These are the "internal" relocations. Align them to
2785 32 bit boundary (PCL), for the moment. */
2786 base &= ~3;
2788 else
2790 switch (fixP->fx_r_type)
2792 case BFD_RELOC_ARC_PC32:
2793 /* The hardware calculates relative to the start of the
2794 insn, but this relocation is relative to location of the
2795 LIMM, compensate. The base always needs to be
2796 subtracted by 4 as we do not support this type of PCrel
2797 relocation for short instructions. */
2798 base -= 4;
2799 /* Fall through. */
2800 case BFD_RELOC_ARC_PLT32:
2801 case BFD_RELOC_ARC_S25H_PCREL_PLT:
2802 case BFD_RELOC_ARC_S21H_PCREL_PLT:
2803 case BFD_RELOC_ARC_S25W_PCREL_PLT:
2804 case BFD_RELOC_ARC_S21W_PCREL_PLT:
2806 case BFD_RELOC_ARC_S21H_PCREL:
2807 case BFD_RELOC_ARC_S25H_PCREL:
2808 case BFD_RELOC_ARC_S13_PCREL:
2809 case BFD_RELOC_ARC_S21W_PCREL:
2810 case BFD_RELOC_ARC_S25W_PCREL:
2811 base &= ~3;
2812 break;
2813 default:
2814 as_bad_where (fixP->fx_file, fixP->fx_line,
2815 _("unhandled reloc %s in md_pcrel_from_section"),
2816 bfd_get_reloc_code_name (fixP->fx_r_type));
2817 break;
2821 pr_debug ("pcrel from %" PRIx64 " + %lx = %" PRIx64 ", "
2822 "symbol: %s (%" PRIx64 ")\n",
2823 (uint64_t) fixP->fx_frag->fr_address, fixP->fx_where, (uint64_t) base,
2824 fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "(null)",
2825 fixP->fx_addsy ? (uint64_t) S_GET_VALUE (fixP->fx_addsy) : (uint64_t) 0);
2827 return base;
2830 /* Given a BFD relocation find the corresponding operand. */
2832 static const struct arc_operand *
2833 find_operand_for_reloc (extended_bfd_reloc_code_real_type reloc)
2835 unsigned i;
2837 for (i = 0; i < arc_num_operands; i++)
2838 if (arc_operands[i].default_reloc == reloc)
2839 return &arc_operands[i];
2840 return NULL;
2843 /* Insert an operand value into an instruction. */
2845 static unsigned long long
2846 insert_operand (unsigned long long insn,
2847 const struct arc_operand *operand,
2848 long long val,
2849 const char *file,
2850 unsigned line)
2852 offsetT min = 0, max = 0;
2854 if (operand->bits != 32
2855 && !(operand->flags & ARC_OPERAND_NCHK)
2856 && !(operand->flags & ARC_OPERAND_FAKE))
2858 if (operand->flags & ARC_OPERAND_SIGNED)
2860 max = (1 << (operand->bits - 1)) - 1;
2861 min = -(1 << (operand->bits - 1));
2863 else
2865 max = (1 << operand->bits) - 1;
2866 min = 0;
2869 if (val < min || val > max)
2870 as_bad_value_out_of_range (_("operand"),
2871 val, min, max, file, line);
2874 pr_debug ("insert field: %ld <= %lld <= %ld in 0x%08llx\n",
2875 min, val, max, insn);
2877 if ((operand->flags & ARC_OPERAND_ALIGNED32)
2878 && (val & 0x03))
2879 as_bad_where (file, line,
2880 _("Unaligned operand. Needs to be 32bit aligned"));
2882 if ((operand->flags & ARC_OPERAND_ALIGNED16)
2883 && (val & 0x01))
2884 as_bad_where (file, line,
2885 _("Unaligned operand. Needs to be 16bit aligned"));
2887 if (operand->insert)
2889 const char *errmsg = NULL;
2891 insn = (*operand->insert) (insn, val, &errmsg);
2892 if (errmsg)
2893 as_warn_where (file, line, "%s", errmsg);
2895 else
2897 if (operand->flags & ARC_OPERAND_TRUNCATE)
2899 if (operand->flags & ARC_OPERAND_ALIGNED32)
2900 val >>= 2;
2901 if (operand->flags & ARC_OPERAND_ALIGNED16)
2902 val >>= 1;
2904 insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift);
2906 return insn;
2909 /* Apply a fixup to the object code. At this point all symbol values
2910 should be fully resolved, and we attempt to completely resolve the
2911 reloc. If we can not do that, we determine the correct reloc code
2912 and put it back in the fixup. To indicate that a fixup has been
2913 eliminated, set fixP->fx_done. */
2915 void
2916 md_apply_fix (fixS *fixP,
2917 valueT *valP,
2918 segT seg)
2920 char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
2921 valueT value = *valP;
2922 unsigned insn = 0;
2923 symbolS *fx_addsy, *fx_subsy;
2924 offsetT fx_offset;
2925 segT add_symbol_segment = absolute_section;
2926 segT sub_symbol_segment = absolute_section;
2927 const struct arc_operand *operand = NULL;
2928 extended_bfd_reloc_code_real_type reloc;
2930 pr_debug ("%s:%u: apply_fix: r_type=%d (%s) value=0x%lX offset=0x%lX\n",
2931 fixP->fx_file, fixP->fx_line, fixP->fx_r_type,
2932 ((int) fixP->fx_r_type < 0) ? "Internal":
2933 bfd_get_reloc_code_name (fixP->fx_r_type), value,
2934 fixP->fx_offset);
2936 fx_addsy = fixP->fx_addsy;
2937 fx_subsy = fixP->fx_subsy;
2938 fx_offset = 0;
2940 if (fx_addsy)
2942 add_symbol_segment = S_GET_SEGMENT (fx_addsy);
2945 if (fx_subsy
2946 && fixP->fx_r_type != BFD_RELOC_ARC_TLS_DTPOFF
2947 && fixP->fx_r_type != BFD_RELOC_ARC_TLS_DTPOFF_S9
2948 && fixP->fx_r_type != BFD_RELOC_ARC_TLS_GD_LD)
2950 resolve_symbol_value (fx_subsy);
2951 sub_symbol_segment = S_GET_SEGMENT (fx_subsy);
2953 if (sub_symbol_segment == absolute_section)
2955 /* The symbol is really a constant. */
2956 fx_offset -= S_GET_VALUE (fx_subsy);
2957 fx_subsy = NULL;
2959 else
2961 as_bad_subtract (fixP);
2962 return;
2966 if (fx_addsy
2967 && !S_IS_WEAK (fx_addsy))
2969 if (add_symbol_segment == seg
2970 && fixP->fx_pcrel)
2972 value += S_GET_VALUE (fx_addsy);
2973 value -= md_pcrel_from_section (fixP, seg);
2974 fx_addsy = NULL;
2975 fixP->fx_pcrel = false;
2977 else if (add_symbol_segment == absolute_section)
2979 value = fixP->fx_offset;
2980 fx_offset += S_GET_VALUE (fixP->fx_addsy);
2981 fx_addsy = NULL;
2982 fixP->fx_pcrel = false;
2986 if (!fx_addsy)
2987 fixP->fx_done = true;
2989 if (fixP->fx_pcrel)
2991 if (fx_addsy
2992 && ((S_IS_DEFINED (fx_addsy)
2993 && S_GET_SEGMENT (fx_addsy) != seg)
2994 || S_IS_WEAK (fx_addsy)))
2995 value += md_pcrel_from_section (fixP, seg);
2997 switch (fixP->fx_r_type)
2999 case BFD_RELOC_ARC_32_ME:
3000 /* This is a pc-relative value in a LIMM. Adjust it to the
3001 address of the instruction not to the address of the
3002 LIMM. Note: it is not any longer valid this affirmation as
3003 the linker consider ARC_PC32 a fixup to entire 64 bit
3004 insn. */
3005 fixP->fx_offset += fixP->fx_frag->fr_address;
3006 /* Fall through. */
3007 case BFD_RELOC_32:
3008 fixP->fx_r_type = BFD_RELOC_ARC_PC32;
3009 /* Fall through. */
3010 case BFD_RELOC_ARC_PC32:
3011 /* fixP->fx_offset += fixP->fx_where - fixP->fx_dot_value; */
3012 break;
3013 default:
3014 if ((int) fixP->fx_r_type < 0)
3015 as_bad_where (fixP->fx_file, fixP->fx_line,
3016 _("PC relative relocation not allowed for (internal)"
3017 " type %d"),
3018 fixP->fx_r_type);
3019 break;
3023 pr_debug ("%s:%u: apply_fix: r_type=%d (%s) value=0x%lX offset=0x%lX\n",
3024 fixP->fx_file, fixP->fx_line, fixP->fx_r_type,
3025 ((int) fixP->fx_r_type < 0) ? "Internal":
3026 bfd_get_reloc_code_name (fixP->fx_r_type), value,
3027 fixP->fx_offset);
3030 /* Now check for TLS relocations. */
3031 reloc = fixP->fx_r_type;
3032 switch (reloc)
3034 case BFD_RELOC_ARC_TLS_DTPOFF:
3035 case BFD_RELOC_ARC_TLS_LE_32:
3036 if (fixP->fx_done)
3037 break;
3038 /* Fall through. */
3039 case BFD_RELOC_ARC_TLS_GD_GOT:
3040 case BFD_RELOC_ARC_TLS_IE_GOT:
3041 S_SET_THREAD_LOCAL (fixP->fx_addsy);
3042 break;
3044 case BFD_RELOC_ARC_TLS_GD_LD:
3045 gas_assert (!fixP->fx_offset);
3046 if (fixP->fx_subsy)
3047 fixP->fx_offset
3048 = (S_GET_VALUE (fixP->fx_subsy)
3049 - fixP->fx_frag->fr_address- fixP->fx_where);
3050 fixP->fx_subsy = NULL;
3051 /* Fall through. */
3052 case BFD_RELOC_ARC_TLS_GD_CALL:
3053 /* These two relocs are there just to allow ld to change the tls
3054 model for this symbol, by patching the code. The offset -
3055 and scale, if any - will be installed by the linker. */
3056 S_SET_THREAD_LOCAL (fixP->fx_addsy);
3057 break;
3059 case BFD_RELOC_ARC_TLS_LE_S9:
3060 case BFD_RELOC_ARC_TLS_DTPOFF_S9:
3061 as_bad (_("TLS_*_S9 relocs are not supported yet"));
3062 break;
3064 default:
3065 break;
3068 if (!fixP->fx_done)
3070 return;
3073 /* Adjust the value if we have a constant. */
3074 value += fx_offset;
3076 /* For hosts with longs bigger than 32-bits make sure that the top
3077 bits of a 32-bit negative value read in by the parser are set,
3078 so that the correct comparisons are made. */
3079 if (value & 0x80000000)
3080 value |= (-1UL << 31);
3082 reloc = fixP->fx_r_type;
3083 switch (reloc)
3085 case BFD_RELOC_8:
3086 case BFD_RELOC_16:
3087 case BFD_RELOC_24:
3088 case BFD_RELOC_32:
3089 case BFD_RELOC_64:
3090 case BFD_RELOC_ARC_32_PCREL:
3091 md_number_to_chars (fixpos, value, fixP->fx_size);
3092 return;
3094 case BFD_RELOC_ARC_GOTPC32:
3095 /* I cannot fix an GOTPC relocation because I need to relax it
3096 from ld rx,[pcl,@sym@gotpc] to add rx,pcl,@sym@gotpc. */
3097 as_bad (_("Unsupported operation on reloc"));
3098 return;
3100 case BFD_RELOC_ARC_TLS_DTPOFF:
3101 case BFD_RELOC_ARC_TLS_LE_32:
3102 gas_assert (!fixP->fx_addsy);
3103 gas_assert (!fixP->fx_subsy);
3104 /* Fall through. */
3106 case BFD_RELOC_ARC_GOTOFF:
3107 case BFD_RELOC_ARC_32_ME:
3108 case BFD_RELOC_ARC_PC32:
3109 md_number_to_chars_midend (fixpos, value, fixP->fx_size);
3110 return;
3112 case BFD_RELOC_ARC_PLT32:
3113 md_number_to_chars_midend (fixpos, value, fixP->fx_size);
3114 return;
3116 case BFD_RELOC_ARC_S25H_PCREL_PLT:
3117 reloc = BFD_RELOC_ARC_S25W_PCREL;
3118 goto solve_plt;
3120 case BFD_RELOC_ARC_S21H_PCREL_PLT:
3121 reloc = BFD_RELOC_ARC_S21H_PCREL;
3122 goto solve_plt;
3124 case BFD_RELOC_ARC_S25W_PCREL_PLT:
3125 reloc = BFD_RELOC_ARC_S25W_PCREL;
3126 goto solve_plt;
3128 case BFD_RELOC_ARC_S21W_PCREL_PLT:
3129 reloc = BFD_RELOC_ARC_S21W_PCREL;
3130 /* Fall through. */
3132 case BFD_RELOC_ARC_S25W_PCREL:
3133 case BFD_RELOC_ARC_S21W_PCREL:
3134 case BFD_RELOC_ARC_S21H_PCREL:
3135 case BFD_RELOC_ARC_S25H_PCREL:
3136 case BFD_RELOC_ARC_S13_PCREL:
3137 solve_plt:
3138 operand = find_operand_for_reloc (reloc);
3139 gas_assert (operand);
3140 break;
3142 default:
3144 if ((int) fixP->fx_r_type >= 0)
3145 as_fatal (_("unhandled relocation type %s"),
3146 bfd_get_reloc_code_name (fixP->fx_r_type));
3148 /* The rest of these fixups needs to be completely resolved as
3149 constants. */
3150 if (fixP->fx_addsy != 0
3151 && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
3152 as_bad_where (fixP->fx_file, fixP->fx_line,
3153 _("non-absolute expression in constant field"));
3155 gas_assert (-(int) fixP->fx_r_type < (int) arc_num_operands);
3156 operand = &arc_operands[-(int) fixP->fx_r_type];
3157 break;
3161 if (target_big_endian)
3163 switch (fixP->fx_size)
3165 case 4:
3166 insn = bfd_getb32 (fixpos);
3167 break;
3168 case 2:
3169 insn = bfd_getb16 (fixpos);
3170 break;
3171 default:
3172 as_bad_where (fixP->fx_file, fixP->fx_line,
3173 _("unknown fixup size"));
3176 else
3178 insn = 0;
3179 switch (fixP->fx_size)
3181 case 4:
3182 insn = bfd_getl16 (fixpos) << 16 | bfd_getl16 (fixpos + 2);
3183 break;
3184 case 2:
3185 insn = bfd_getl16 (fixpos);
3186 break;
3187 default:
3188 as_bad_where (fixP->fx_file, fixP->fx_line,
3189 _("unknown fixup size"));
3193 insn = insert_operand (insn, operand, (offsetT) value,
3194 fixP->fx_file, fixP->fx_line);
3196 md_number_to_chars_midend (fixpos, insn, fixP->fx_size);
3199 /* Prepare machine-dependent frags for relaxation.
3201 Called just before relaxation starts. Any symbol that is now undefined
3202 will not become defined.
3204 Return the correct fr_subtype in the frag.
3206 Return the initial "guess for fr_var" to caller. The guess for fr_var
3207 is *actually* the growth beyond fr_fix. Whatever we do to grow fr_fix
3208 or fr_var contributes to our returned value.
3210 Although it may not be explicit in the frag, pretend
3211 fr_var starts with a value. */
3214 md_estimate_size_before_relax (fragS *fragP,
3215 segT segment)
3217 int growth;
3219 /* If the symbol is not located within the same section AND it's not
3220 an absolute section, use the maximum. OR if the symbol is a
3221 constant AND the insn is by nature not pc-rel, use the maximum.
3222 OR if the symbol is being equated against another symbol, use the
3223 maximum. OR if the symbol is weak use the maximum. */
3224 if ((S_GET_SEGMENT (fragP->fr_symbol) != segment
3225 && S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
3226 || (symbol_constant_p (fragP->fr_symbol)
3227 && !fragP->tc_frag_data.pcrel)
3228 || symbol_equated_p (fragP->fr_symbol)
3229 || S_IS_WEAK (fragP->fr_symbol))
3231 while (md_relax_table[fragP->fr_subtype].rlx_more != ARC_RLX_NONE)
3232 ++fragP->fr_subtype;
3235 growth = md_relax_table[fragP->fr_subtype].rlx_length;
3236 fragP->fr_var = growth;
3238 pr_debug ("%s:%d: md_estimate_size_before_relax: %d\n",
3239 fragP->fr_file, fragP->fr_line, growth);
3241 return growth;
3244 /* Translate internal representation of relocation info to BFD target
3245 format. */
3247 arelent *
3248 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
3249 fixS *fixP)
3251 arelent *reloc;
3252 bfd_reloc_code_real_type code;
3254 reloc = XNEW (arelent);
3255 reloc->sym_ptr_ptr = XNEW (asymbol *);
3256 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
3257 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
3259 /* Make sure none of our internal relocations make it this far.
3260 They'd better have been fully resolved by this point. */
3261 gas_assert ((int) fixP->fx_r_type > 0);
3263 code = fixP->fx_r_type;
3265 /* if we have something like add gp, pcl,
3266 _GLOBAL_OFFSET_TABLE_@gotpc. */
3267 if (code == BFD_RELOC_ARC_GOTPC32
3268 && GOT_symbol
3269 && fixP->fx_addsy == GOT_symbol)
3270 code = BFD_RELOC_ARC_GOTPC;
3272 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
3273 if (reloc->howto == NULL)
3275 as_bad_where (fixP->fx_file, fixP->fx_line,
3276 _("cannot represent `%s' relocation in object file"),
3277 bfd_get_reloc_code_name (code));
3278 return NULL;
3281 if (!fixP->fx_pcrel != !reloc->howto->pc_relative)
3282 as_fatal (_("internal error? cannot generate `%s' relocation"),
3283 bfd_get_reloc_code_name (code));
3285 gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
3287 reloc->addend = fixP->fx_offset;
3289 return reloc;
3292 /* Perform post-processing of machine-dependent frags after relaxation.
3293 Called after relaxation is finished.
3294 In: Address of frag.
3295 fr_type == rs_machine_dependent.
3296 fr_subtype is what the address relaxed to.
3298 Out: Any fixS:s and constants are set up. */
3300 void
3301 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
3302 segT segment ATTRIBUTE_UNUSED,
3303 fragS *fragP)
3305 const relax_typeS *table_entry;
3306 char *dest;
3307 const struct arc_opcode *opcode;
3308 struct arc_insn insn;
3309 int size, fix;
3310 struct arc_relax_type *relax_arg = &fragP->tc_frag_data;
3312 fix = fragP->fr_fix;
3313 dest = fragP->fr_literal + fix;
3314 table_entry = TC_GENERIC_RELAX_TABLE + fragP->fr_subtype;
3316 pr_debug ("%s:%d: md_convert_frag, subtype: %d, fix: %d, "
3317 "var: %" PRId64 "\n",
3318 fragP->fr_file, fragP->fr_line,
3319 fragP->fr_subtype, fix, (int64_t) fragP->fr_var);
3321 if (fragP->fr_subtype <= 0
3322 && fragP->fr_subtype >= arc_num_relax_opcodes)
3323 as_fatal (_("no relaxation found for this instruction."));
3325 opcode = &arc_relax_opcodes[fragP->fr_subtype];
3327 assemble_insn (opcode, relax_arg->tok, relax_arg->ntok, relax_arg->pflags,
3328 relax_arg->nflg, &insn);
3330 apply_fixups (&insn, fragP, fix);
3332 size = insn.len + (insn.has_limm ? 4 : 0);
3333 gas_assert (table_entry->rlx_length == size);
3334 emit_insn0 (&insn, dest, true);
3336 fragP->fr_fix += table_entry->rlx_length;
3337 fragP->fr_var = 0;
3340 /* We have no need to default values of symbols. We could catch
3341 register names here, but that is handled by inserting them all in
3342 the symbol table to begin with. */
3344 symbolS *
3345 md_undefined_symbol (char *name)
3347 /* The arc abi demands that a GOT[0] should be referencible as
3348 [pc+_DYNAMIC@gotpc]. Hence we convert a _DYNAMIC@gotpc to a
3349 GOTPC reference to _GLOBAL_OFFSET_TABLE_. */
3350 if (((*name == '_')
3351 && (*(name+1) == 'G')
3352 && (strcmp (name, GLOBAL_OFFSET_TABLE_NAME) == 0)))
3354 if (!GOT_symbol)
3356 if (symbol_find (name))
3357 as_bad ("GOT already in symbol table");
3359 GOT_symbol = symbol_new (GLOBAL_OFFSET_TABLE_NAME, undefined_section,
3360 &zero_address_frag, 0);
3362 return GOT_symbol;
3364 return NULL;
3367 /* Turn a string in input_line_pointer into a floating point constant
3368 of type type, and store the appropriate bytes in *litP. The number
3369 of LITTLENUMS emitted is stored in *sizeP. An error message is
3370 returned, or NULL on OK. */
3372 const char *
3373 md_atof (int type, char *litP, int *sizeP)
3375 return ieee_md_atof (type, litP, sizeP, target_big_endian);
3378 /* Called for any expression that can not be recognized. When the
3379 function is called, `input_line_pointer' will point to the start of
3380 the expression. We use it when we have complex operations like
3381 @label1 - @label2. */
3383 void
3384 md_operand (expressionS *expressionP)
3386 char *p = input_line_pointer;
3387 if (*p == '@')
3389 input_line_pointer++;
3390 expressionP->X_op = O_symbol;
3391 expressionP->X_md = O_absent;
3392 expression (expressionP);
3396 /* This function is called from the function 'expression', it attempts
3397 to parse special names (in our case register names). It fills in
3398 the expression with the identified register. It returns TRUE if
3399 it is a register and FALSE otherwise. */
3401 bool
3402 arc_parse_name (const char *name,
3403 struct expressionS *e)
3405 struct symbol *sym;
3407 if (!assembling_insn)
3408 return false;
3410 if (e->X_op == O_symbol
3411 && e->X_md == O_absent)
3412 return false;
3414 sym = str_hash_find (arc_reg_hash, name);
3415 if (sym)
3417 e->X_op = O_register;
3418 e->X_add_number = S_GET_VALUE (sym);
3419 return true;
3422 sym = str_hash_find (arc_addrtype_hash, name);
3423 if (sym)
3425 e->X_op = O_addrtype;
3426 e->X_add_number = S_GET_VALUE (sym);
3427 return true;
3430 return false;
3433 /* md_parse_option
3434 Invocation line includes a switch not recognized by the base assembler.
3435 See if it's a processor-specific option.
3437 New options (supported) are:
3439 -mcpu=<cpu name> Assemble for selected processor
3440 -EB/-mbig-endian Big-endian
3441 -EL/-mlittle-endian Little-endian
3442 -mrelax Enable relaxation
3444 The following CPU names are recognized:
3445 arc600, arc700, arcem, archs, nps400. */
3448 md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
3450 switch (c)
3452 case OPTION_ARC600:
3453 case OPTION_ARC601:
3454 return md_parse_option (OPTION_MCPU, "arc600");
3456 case OPTION_ARC700:
3457 return md_parse_option (OPTION_MCPU, "arc700");
3459 case OPTION_ARCEM:
3460 return md_parse_option (OPTION_MCPU, "arcem");
3462 case OPTION_ARCHS:
3463 return md_parse_option (OPTION_MCPU, "archs");
3465 case OPTION_MCPU:
3467 arc_select_cpu (arg, MACH_SELECTION_FROM_COMMAND_LINE);
3468 break;
3471 case OPTION_EB:
3472 arc_target_format = "elf32-bigarc";
3473 byte_order = BIG_ENDIAN;
3474 break;
3476 case OPTION_EL:
3477 arc_target_format = "elf32-littlearc";
3478 byte_order = LITTLE_ENDIAN;
3479 break;
3481 case OPTION_CD:
3482 selected_cpu.features |= CD;
3483 cl_features |= CD;
3484 arc_check_feature ();
3485 break;
3487 case OPTION_RELAX:
3488 relaxation_state = 1;
3489 break;
3491 case OPTION_NPS400:
3492 selected_cpu.features |= NPS400;
3493 cl_features |= NPS400;
3494 arc_check_feature ();
3495 break;
3497 case OPTION_SPFP:
3498 selected_cpu.features |= SPX;
3499 cl_features |= SPX;
3500 arc_check_feature ();
3501 break;
3503 case OPTION_DPFP:
3504 selected_cpu.features |= DPX;
3505 cl_features |= DPX;
3506 arc_check_feature ();
3507 break;
3509 case OPTION_FPUDA:
3510 selected_cpu.features |= DPA;
3511 cl_features |= DPA;
3512 arc_check_feature ();
3513 break;
3515 /* Dummy options are accepted but have no effect. */
3516 case OPTION_USER_MODE:
3517 case OPTION_LD_EXT_MASK:
3518 case OPTION_SWAP:
3519 case OPTION_NORM:
3520 case OPTION_BARREL_SHIFT:
3521 case OPTION_MIN_MAX:
3522 case OPTION_NO_MPY:
3523 case OPTION_EA:
3524 case OPTION_MUL64:
3525 case OPTION_SIMD:
3526 case OPTION_XMAC_D16:
3527 case OPTION_XMAC_24:
3528 case OPTION_DSP_PACKA:
3529 case OPTION_CRC:
3530 case OPTION_DVBF:
3531 case OPTION_TELEPHONY:
3532 case OPTION_XYMEMORY:
3533 case OPTION_LOCK:
3534 case OPTION_SWAPE:
3535 case OPTION_RTSC:
3536 break;
3538 default:
3539 return 0;
3542 return 1;
3545 /* Display the list of cpu names for use in the help text. */
3547 static void
3548 arc_show_cpu_list (FILE *stream)
3550 int i, offset;
3551 static const char *space_buf = " ";
3553 fprintf (stream, "%s", space_buf);
3554 offset = strlen (space_buf);
3555 for (i = 0; cpu_types[i].name != NULL; ++i)
3557 bool last = (cpu_types[i + 1].name == NULL);
3559 /* If displaying the new cpu name string, and the ', ' (for all
3560 but the last one) will take us past a target width of 80
3561 characters, then it's time for a new line. */
3562 if (offset + strlen (cpu_types[i].name) + (last ? 0 : 2) > 80)
3564 fprintf (stream, "\n%s", space_buf);
3565 offset = strlen (space_buf);
3568 fprintf (stream, "%s%s", cpu_types[i].name, (last ? "\n" : ", "));
3569 offset += strlen (cpu_types [i].name) + (last ? 0 : 2);
3573 void
3574 md_show_usage (FILE *stream)
3576 fprintf (stream, _("ARC-specific assembler options:\n"));
3578 fprintf (stream, " -mcpu=<cpu name>\t (default: %s), assemble for"
3579 " CPU <cpu name>, one of:\n", TARGET_WITH_CPU);
3580 arc_show_cpu_list (stream);
3581 fprintf (stream, "\n");
3582 fprintf (stream, " -mA6/-mARC600/-mARC601 same as -mcpu=arc600\n");
3583 fprintf (stream, " -mA7/-mARC700\t\t same as -mcpu=arc700\n");
3584 fprintf (stream, " -mEM\t\t\t same as -mcpu=arcem\n");
3585 fprintf (stream, " -mHS\t\t\t same as -mcpu=archs\n");
3587 fprintf (stream, " -mnps400\t\t enable NPS-400 extended instructions\n");
3588 fprintf (stream, " -mspfp\t\t enable single-precision floating point"
3589 " instructions\n");
3590 fprintf (stream, " -mdpfp\t\t enable double-precision floating point"
3591 " instructions\n");
3592 fprintf (stream, " -mfpuda\t\t enable double-precision assist floating "
3593 "point\n\t\t\t instructions for ARC EM\n");
3595 fprintf (stream,
3596 " -mcode-density\t enable code density option for ARC EM\n");
3598 fprintf (stream, _("\
3599 -EB assemble code for a big-endian cpu\n"));
3600 fprintf (stream, _("\
3601 -EL assemble code for a little-endian cpu\n"));
3602 fprintf (stream, _("\
3603 -mrelax enable relaxation\n"));
3605 fprintf (stream, _("The following ARC-specific assembler options are "
3606 "deprecated and are accepted\nfor compatibility only:\n"));
3608 fprintf (stream, _(" -mEA\n"
3609 " -mbarrel-shifter\n"
3610 " -mbarrel_shifter\n"
3611 " -mcrc\n"
3612 " -mdsp-packa\n"
3613 " -mdsp_packa\n"
3614 " -mdvbf\n"
3615 " -mld-extension-reg-mask\n"
3616 " -mlock\n"
3617 " -mmac-24\n"
3618 " -mmac-d16\n"
3619 " -mmac_24\n"
3620 " -mmac_d16\n"
3621 " -mmin-max\n"
3622 " -mmin_max\n"
3623 " -mmul64\n"
3624 " -mno-mpy\n"
3625 " -mnorm\n"
3626 " -mrtsc\n"
3627 " -msimd\n"
3628 " -mswap\n"
3629 " -mswape\n"
3630 " -mtelephony\n"
3631 " -muser-mode-only\n"
3632 " -mxy\n"));
3635 /* Find the proper relocation for the given opcode. */
3637 static extended_bfd_reloc_code_real_type
3638 find_reloc (const char *name,
3639 const char *opcodename,
3640 const struct arc_flags *pflags,
3641 int nflg,
3642 extended_bfd_reloc_code_real_type reloc)
3644 unsigned int i;
3645 int j;
3646 bool found_flag, tmp;
3647 extended_bfd_reloc_code_real_type ret = BFD_RELOC_UNUSED;
3649 for (i = 0; i < arc_num_equiv_tab; i++)
3651 const struct arc_reloc_equiv_tab *r = &arc_reloc_equiv[i];
3653 /* Find the entry. */
3654 if (strcmp (name, r->name))
3655 continue;
3656 if (r->mnemonic && (strcmp (r->mnemonic, opcodename)))
3657 continue;
3658 if (r->flags[0])
3660 if (!nflg)
3661 continue;
3662 found_flag = false;
3663 unsigned * psflg = (unsigned *)r->flags;
3666 tmp = false;
3667 for (j = 0; j < nflg; j++)
3668 if (!strcmp (pflags[j].name,
3669 arc_flag_operands[*psflg].name))
3671 tmp = true;
3672 break;
3674 if (!tmp)
3676 found_flag = false;
3677 break;
3679 else
3681 found_flag = true;
3683 ++ psflg;
3684 } while (*psflg);
3686 if (!found_flag)
3687 continue;
3690 if (reloc != r->oldreloc)
3691 continue;
3692 /* Found it. */
3693 ret = r->newreloc;
3694 break;
3697 if (ret == BFD_RELOC_UNUSED)
3698 as_bad (_("Unable to find %s relocation for instruction %s"),
3699 name, opcodename);
3700 return ret;
3703 /* All the symbol types that are allowed to be used for
3704 relaxation. */
3706 static bool
3707 may_relax_expr (expressionS tok)
3709 /* Check if we have unrelaxable relocs. */
3710 switch (tok.X_md)
3712 default:
3713 break;
3714 case O_plt:
3715 return false;
3718 switch (tok.X_op)
3720 case O_symbol:
3721 case O_multiply:
3722 case O_divide:
3723 case O_modulus:
3724 case O_add:
3725 case O_subtract:
3726 break;
3728 default:
3729 return false;
3731 return true;
3734 /* Checks if flags are in line with relaxable insn. */
3736 static bool
3737 relaxable_flag (const struct arc_relaxable_ins *ins,
3738 const struct arc_flags *pflags,
3739 int nflgs)
3741 unsigned flag_class,
3742 flag,
3743 flag_class_idx = 0,
3744 flag_idx = 0;
3746 const struct arc_flag_operand *flag_opand;
3747 int i, counttrue = 0;
3749 /* Iterate through flags classes. */
3750 while ((flag_class = ins->flag_classes[flag_class_idx]) != 0)
3752 /* Iterate through flags in flag class. */
3753 while ((flag = arc_flag_classes[flag_class].flags[flag_idx])
3754 != 0)
3756 flag_opand = &arc_flag_operands[flag];
3757 /* Iterate through flags in ins to compare. */
3758 for (i = 0; i < nflgs; ++i)
3760 if (strcmp (flag_opand->name, pflags[i].name) == 0)
3761 ++counttrue;
3764 ++flag_idx;
3767 ++flag_class_idx;
3768 flag_idx = 0;
3771 /* If counttrue == nflgs, then all flags have been found. */
3772 return counttrue == nflgs;
3775 /* Checks if operands are in line with relaxable insn. */
3777 static bool
3778 relaxable_operand (const struct arc_relaxable_ins *ins,
3779 const expressionS *tok,
3780 int ntok)
3782 const enum rlx_operand_type *operand = &ins->operands[0];
3783 int i = 0;
3785 while (*operand != EMPTY)
3787 const expressionS *epr = &tok[i];
3789 if (i != 0 && i >= ntok)
3790 return false;
3792 switch (*operand)
3794 case IMMEDIATE:
3795 if (!(epr->X_op == O_multiply
3796 || epr->X_op == O_divide
3797 || epr->X_op == O_modulus
3798 || epr->X_op == O_add
3799 || epr->X_op == O_subtract
3800 || epr->X_op == O_symbol))
3801 return false;
3802 break;
3804 case REGISTER_DUP:
3805 if ((i <= 0)
3806 || (epr->X_add_number != tok[i - 1].X_add_number))
3807 return false;
3808 /* Fall through. */
3809 case REGISTER:
3810 if (epr->X_op != O_register)
3811 return false;
3812 break;
3814 case REGISTER_S:
3815 if (epr->X_op != O_register)
3816 return false;
3818 switch (epr->X_add_number)
3820 case 0: case 1: case 2: case 3:
3821 case 12: case 13: case 14: case 15:
3822 break;
3823 default:
3824 return false;
3826 break;
3828 case REGISTER_NO_GP:
3829 if ((epr->X_op != O_register)
3830 || (epr->X_add_number == 26)) /* 26 is the gp register. */
3831 return false;
3832 break;
3834 case BRACKET:
3835 if (epr->X_op != O_bracket)
3836 return false;
3837 break;
3839 default:
3840 /* Don't understand, bail out. */
3841 return false;
3842 break;
3845 ++i;
3846 operand = &ins->operands[i];
3849 return i == ntok;
3852 /* Return TRUE if this OPDCODE is a candidate for relaxation. */
3854 static bool
3855 relax_insn_p (const struct arc_opcode *opcode,
3856 const expressionS *tok,
3857 int ntok,
3858 const struct arc_flags *pflags,
3859 int nflg)
3861 unsigned i;
3862 bool rv = false;
3864 /* Check the relaxation table. */
3865 for (i = 0; i < arc_num_relaxable_ins && relaxation_state; ++i)
3867 const struct arc_relaxable_ins *arc_rlx_ins = &arc_relaxable_insns[i];
3869 if ((strcmp (opcode->name, arc_rlx_ins->mnemonic_r) == 0)
3870 && may_relax_expr (tok[arc_rlx_ins->opcheckidx])
3871 && relaxable_operand (arc_rlx_ins, tok, ntok)
3872 && relaxable_flag (arc_rlx_ins, pflags, nflg))
3874 rv = true;
3875 frag_now->fr_subtype = arc_relaxable_insns[i].subtype;
3876 memcpy (&frag_now->tc_frag_data.tok, tok,
3877 sizeof (expressionS) * ntok);
3878 memcpy (&frag_now->tc_frag_data.pflags, pflags,
3879 sizeof (struct arc_flags) * nflg);
3880 frag_now->tc_frag_data.nflg = nflg;
3881 frag_now->tc_frag_data.ntok = ntok;
3882 break;
3886 return rv;
3889 /* Turn an opcode description and a set of arguments into
3890 an instruction and a fixup. */
3892 static void
3893 assemble_insn (const struct arc_opcode *opcode,
3894 const expressionS *tok,
3895 int ntok,
3896 const struct arc_flags *pflags,
3897 int nflg,
3898 struct arc_insn *insn)
3900 const expressionS *reloc_exp = NULL;
3901 unsigned long long image;
3902 const unsigned char *argidx;
3903 int i;
3904 int tokidx = 0;
3905 unsigned char pcrel = 0;
3906 bool needGOTSymbol;
3907 bool has_delay_slot = false;
3908 extended_bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
3910 memset (insn, 0, sizeof (*insn));
3911 image = opcode->opcode;
3913 pr_debug ("%s:%d: assemble_insn: %s using opcode %llx\n",
3914 frag_now->fr_file, frag_now->fr_line, opcode->name,
3915 opcode->opcode);
3917 /* Handle operands. */
3918 for (argidx = opcode->operands; *argidx; ++argidx)
3920 const struct arc_operand *operand = &arc_operands[*argidx];
3921 const expressionS *t = (const expressionS *) 0;
3923 if (ARC_OPERAND_IS_FAKE (operand))
3924 continue;
3926 if (operand->flags & ARC_OPERAND_DUPLICATE)
3928 /* Duplicate operand, already inserted. */
3929 tokidx ++;
3930 continue;
3933 if (tokidx >= ntok)
3935 abort ();
3937 else
3938 t = &tok[tokidx++];
3940 /* Regardless if we have a reloc or not mark the instruction
3941 limm if it is the case. */
3942 if (operand->flags & ARC_OPERAND_LIMM)
3943 insn->has_limm = true;
3945 switch (t->X_op)
3947 case O_register:
3948 image = insert_operand (image, operand, regno (t->X_add_number),
3949 NULL, 0);
3950 break;
3952 case O_constant:
3953 image = insert_operand (image, operand, t->X_add_number, NULL, 0);
3954 reloc_exp = t;
3955 if (operand->flags & ARC_OPERAND_LIMM)
3956 insn->limm = t->X_add_number;
3957 break;
3959 case O_bracket:
3960 case O_colon:
3961 case O_addrtype:
3962 /* Ignore brackets, colons, and address types. */
3963 break;
3965 case O_absent:
3966 gas_assert (operand->flags & ARC_OPERAND_IGNORE);
3967 break;
3969 case O_subtract:
3970 /* Maybe register range. */
3971 if ((t->X_add_number == 0)
3972 && contains_register (t->X_add_symbol)
3973 && contains_register (t->X_op_symbol))
3975 int regs;
3977 regs = get_register (t->X_add_symbol);
3978 regs <<= 16;
3979 regs |= get_register (t->X_op_symbol);
3980 image = insert_operand (image, operand, regs, NULL, 0);
3981 break;
3983 /* Fall through. */
3985 default:
3986 /* This operand needs a relocation. */
3987 needGOTSymbol = false;
3989 switch (t->X_md)
3991 case O_plt:
3992 if (opcode->insn_class == JUMP)
3993 as_bad (_("Unable to use @plt relocation for insn %s"),
3994 opcode->name);
3995 needGOTSymbol = true;
3996 reloc = find_reloc ("plt", opcode->name,
3997 pflags, nflg,
3998 operand->default_reloc);
3999 break;
4001 case O_gotoff:
4002 case O_gotpc:
4003 needGOTSymbol = true;
4004 reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
4005 break;
4006 case O_pcl:
4007 if (operand->flags & ARC_OPERAND_LIMM)
4009 reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
4010 if (arc_opcode_len (opcode) == 2
4011 || opcode->insn_class == JUMP)
4012 as_bad (_("Unable to use @pcl relocation for insn %s"),
4013 opcode->name);
4015 else
4017 /* This is a relaxed operand which initially was
4018 limm, choose whatever we have defined in the
4019 opcode as reloc. */
4020 reloc = operand->default_reloc;
4022 break;
4023 case O_sda:
4024 reloc = find_reloc ("sda", opcode->name,
4025 pflags, nflg,
4026 operand->default_reloc);
4027 break;
4028 case O_tlsgd:
4029 case O_tlsie:
4030 needGOTSymbol = true;
4031 /* Fall-through. */
4033 case O_tpoff:
4034 case O_dtpoff:
4035 reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
4036 break;
4038 case O_tpoff9: /*FIXME! Check for the conditionality of
4039 the insn. */
4040 case O_dtpoff9: /*FIXME! Check for the conditionality of
4041 the insn. */
4042 as_bad (_("TLS_*_S9 relocs are not supported yet"));
4043 break;
4045 default:
4046 /* Just consider the default relocation. */
4047 reloc = operand->default_reloc;
4048 break;
4051 if (needGOTSymbol && (GOT_symbol == NULL))
4052 GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
4054 reloc_exp = t;
4056 #if 0
4057 if (reloc > 0)
4059 /* sanity checks. */
4060 reloc_howto_type *reloc_howto
4061 = bfd_reloc_type_lookup (stdoutput,
4062 (bfd_reloc_code_real_type) reloc);
4063 unsigned reloc_bitsize = reloc_howto->bitsize;
4064 if (reloc_howto->rightshift)
4065 reloc_bitsize -= reloc_howto->rightshift;
4066 if (reloc_bitsize != operand->bits)
4068 as_bad (_("invalid relocation %s for field"),
4069 bfd_get_reloc_code_name (reloc));
4070 return;
4073 #endif
4074 if (insn->nfixups >= MAX_INSN_FIXUPS)
4075 as_fatal (_("too many fixups"));
4077 struct arc_fixup *fixup;
4078 fixup = &insn->fixups[insn->nfixups++];
4079 fixup->exp = *t;
4080 fixup->reloc = reloc;
4081 if ((int) reloc < 0)
4082 pcrel = (operand->flags & ARC_OPERAND_PCREL) ? 1 : 0;
4083 else
4085 reloc_howto_type *reloc_howto =
4086 bfd_reloc_type_lookup (stdoutput,
4087 (bfd_reloc_code_real_type) fixup->reloc);
4088 pcrel = reloc_howto->pc_relative;
4090 fixup->pcrel = pcrel;
4091 fixup->islong = (operand->flags & ARC_OPERAND_LIMM) != 0;
4092 break;
4096 /* Handle flags. */
4097 for (i = 0; i < nflg; i++)
4099 const struct arc_flag_operand *flg_operand = pflags[i].flgp;
4101 /* Check if the instruction has a delay slot. */
4102 if (!strcmp (flg_operand->name, "d"))
4103 has_delay_slot = true;
4105 /* There is an exceptional case when we cannot insert a flag just as
4106 it is. On ARCv2 the '.t' and '.nt' flags must be handled in
4107 relation with the relative address. Unfortunately, some of the
4108 ARC700 extensions (NPS400) also have a '.nt' flag that should be
4109 handled in the normal way.
4111 Flag operands don't have an architecture field, so we can't
4112 directly validate that FLAG_OPERAND is valid for the current
4113 architecture, what we do instead is just validate that we're
4114 assembling for an ARCv2 architecture. */
4115 if ((selected_cpu.flags & ARC_OPCODE_ARCV2)
4116 && (!strcmp (flg_operand->name, "t")
4117 || !strcmp (flg_operand->name, "nt")))
4119 unsigned bitYoperand = 0;
4120 /* FIXME! move selection bbit/brcc in arc-opc.c. */
4121 if (!strcmp (flg_operand->name, "t"))
4122 if (!strcmp (opcode->name, "bbit0")
4123 || !strcmp (opcode->name, "bbit1"))
4124 bitYoperand = arc_NToperand;
4125 else
4126 bitYoperand = arc_Toperand;
4127 else
4128 if (!strcmp (opcode->name, "bbit0")
4129 || !strcmp (opcode->name, "bbit1"))
4130 bitYoperand = arc_Toperand;
4131 else
4132 bitYoperand = arc_NToperand;
4134 gas_assert (reloc_exp != NULL);
4135 if (reloc_exp->X_op == O_constant)
4137 /* Check if we have a constant and solved it
4138 immediately. */
4139 offsetT val = reloc_exp->X_add_number;
4140 image |= insert_operand (image, &arc_operands[bitYoperand],
4141 val, NULL, 0);
4143 else
4145 struct arc_fixup *fixup;
4147 if (insn->nfixups >= MAX_INSN_FIXUPS)
4148 as_fatal (_("too many fixups"));
4150 fixup = &insn->fixups[insn->nfixups++];
4151 fixup->exp = *reloc_exp;
4152 fixup->reloc = -bitYoperand;
4153 fixup->pcrel = pcrel;
4154 fixup->islong = false;
4157 else
4158 image |= (flg_operand->code & ((1 << flg_operand->bits) - 1))
4159 << flg_operand->shift;
4162 insn->relax = relax_insn_p (opcode, tok, ntok, pflags, nflg);
4164 /* Instruction length. */
4165 insn->len = arc_opcode_len (opcode);
4167 insn->insn = image;
4169 /* Update last insn status. */
4170 arc_last_insns[1] = arc_last_insns[0];
4171 arc_last_insns[0].opcode = opcode;
4172 arc_last_insns[0].has_limm = insn->has_limm;
4173 arc_last_insns[0].has_delay_slot = has_delay_slot;
4175 /* Check if the current instruction is legally used. */
4176 if (arc_last_insns[1].has_delay_slot
4177 && is_br_jmp_insn_p (arc_last_insns[0].opcode))
4178 as_bad (_("Insn %s has a jump/branch instruction %s in its delay slot."),
4179 arc_last_insns[1].opcode->name,
4180 arc_last_insns[0].opcode->name);
4181 if (arc_last_insns[1].has_delay_slot
4182 && arc_last_insns[0].has_limm)
4183 as_bad (_("Insn %s has an instruction %s with limm in its delay slot."),
4184 arc_last_insns[1].opcode->name,
4185 arc_last_insns[0].opcode->name);
4188 void
4189 arc_handle_align (fragS* fragP)
4191 if ((fragP)->fr_type == rs_align_code)
4193 char *dest = (fragP)->fr_literal + (fragP)->fr_fix;
4194 valueT count = ((fragP)->fr_next->fr_address
4195 - (fragP)->fr_address - (fragP)->fr_fix);
4197 (fragP)->fr_var = 2;
4199 if (count & 1)/* Padding in the gap till the next 2-byte
4200 boundary with 0s. */
4202 (fragP)->fr_fix++;
4203 *dest++ = 0;
4205 /* Writing nop_s. */
4206 md_number_to_chars (dest, NOP_OPCODE_S, 2);
4210 /* Here we decide which fixups can be adjusted to make them relative
4211 to the beginning of the section instead of the symbol. Basically
4212 we need to make sure that the dynamic relocations are done
4213 correctly, so in some cases we force the original symbol to be
4214 used. */
4217 tc_arc_fix_adjustable (fixS *fixP)
4220 /* Prevent all adjustments to global symbols. */
4221 if (S_IS_EXTERNAL (fixP->fx_addsy))
4222 return 0;
4223 if (S_IS_WEAK (fixP->fx_addsy))
4224 return 0;
4226 /* Adjust_reloc_syms doesn't know about the GOT. */
4227 switch (fixP->fx_r_type)
4229 case BFD_RELOC_ARC_GOTPC32:
4230 case BFD_RELOC_ARC_PLT32:
4231 case BFD_RELOC_ARC_S25H_PCREL_PLT:
4232 case BFD_RELOC_ARC_S21H_PCREL_PLT:
4233 case BFD_RELOC_ARC_S25W_PCREL_PLT:
4234 case BFD_RELOC_ARC_S21W_PCREL_PLT:
4235 return 0;
4237 default:
4238 break;
4241 return 1;
4244 /* Compute the reloc type of an expression EXP. */
4246 static void
4247 arc_check_reloc (expressionS *exp,
4248 bfd_reloc_code_real_type *r_type_p)
4250 if (*r_type_p == BFD_RELOC_32
4251 && exp->X_op == O_subtract
4252 && exp->X_op_symbol != NULL
4253 && S_GET_SEGMENT (exp->X_op_symbol) == now_seg)
4254 *r_type_p = BFD_RELOC_ARC_32_PCREL;
4258 /* Add expression EXP of SIZE bytes to offset OFF of fragment FRAG. */
4260 void
4261 arc_cons_fix_new (fragS *frag,
4262 int off,
4263 int size,
4264 expressionS *exp,
4265 bfd_reloc_code_real_type r_type)
4267 r_type = BFD_RELOC_UNUSED;
4269 switch (size)
4271 case 1:
4272 r_type = BFD_RELOC_8;
4273 break;
4275 case 2:
4276 r_type = BFD_RELOC_16;
4277 break;
4279 case 3:
4280 r_type = BFD_RELOC_24;
4281 break;
4283 case 4:
4284 r_type = BFD_RELOC_32;
4285 arc_check_reloc (exp, &r_type);
4286 break;
4288 case 8:
4289 r_type = BFD_RELOC_64;
4290 break;
4292 default:
4293 as_bad (_("unsupported BFD relocation size %u"), size);
4294 r_type = BFD_RELOC_UNUSED;
4297 fix_new_exp (frag, off, size, exp, 0, r_type);
4300 /* The actual routine that checks the ZOL conditions. */
4302 static void
4303 check_zol (symbolS *s)
4305 switch (selected_cpu.mach)
4307 case bfd_mach_arc_arcv2:
4308 if (selected_cpu.flags & ARC_OPCODE_ARCv2EM)
4309 return;
4311 if (is_br_jmp_insn_p (arc_last_insns[0].opcode)
4312 || arc_last_insns[1].has_delay_slot)
4313 as_bad (_("Jump/Branch instruction detected at the end of the ZOL label @%s"),
4314 S_GET_NAME (s));
4316 break;
4317 case bfd_mach_arc_arc600:
4319 if (is_kernel_insn_p (arc_last_insns[0].opcode))
4320 as_bad (_("Kernel instruction detected at the end of the ZOL label @%s"),
4321 S_GET_NAME (s));
4323 if (arc_last_insns[0].has_limm
4324 && is_br_jmp_insn_p (arc_last_insns[0].opcode))
4325 as_bad (_("A jump instruction with long immediate detected at the \
4326 end of the ZOL label @%s"), S_GET_NAME (s));
4328 /* Fall through. */
4329 case bfd_mach_arc_arc700:
4330 if (arc_last_insns[0].has_delay_slot)
4331 as_bad (_("An illegal use of delay slot detected at the end of the ZOL label @%s"),
4332 S_GET_NAME (s));
4334 break;
4335 default:
4336 break;
4340 /* If ZOL end check the last two instruction for illegals. */
4341 void
4342 arc_frob_label (symbolS * sym)
4344 if (ARC_GET_FLAG (sym) & ARC_FLAG_ZOL)
4345 check_zol (sym);
4347 dwarf2_emit_label (sym);
4350 /* Used because generic relaxation assumes a pc-rel value whilst we
4351 also relax instructions that use an absolute value resolved out of
4352 relative values (if that makes any sense). An example: 'add r1,
4353 r2, @.L2 - .' The symbols . and @.L2 are relative to the section
4354 but if they're in the same section we can subtract the section
4355 offset relocation which ends up in a resolved value. So if @.L2 is
4356 .text + 0x50 and . is .text + 0x10, we can say that .text + 0x50 -
4357 .text + 0x40 = 0x10. */
4359 arc_pcrel_adjust (fragS *fragP)
4361 pr_debug ("arc_pcrel_adjust: address=%ld, fix=%ld, PCrel %s\n",
4362 fragP->fr_address, fragP->fr_fix,
4363 fragP->tc_frag_data.pcrel ? "Y" : "N");
4365 if (!fragP->tc_frag_data.pcrel)
4366 return fragP->fr_address + fragP->fr_fix;
4368 /* Take into account the PCL rounding. */
4369 return (fragP->fr_address + fragP->fr_fix) & 0x03;
4372 /* Initialize the DWARF-2 unwind information for this procedure. */
4374 void
4375 tc_arc_frame_initial_instructions (void)
4377 /* Stack pointer is register 28. */
4378 cfi_add_CFA_def_cfa (28, 0);
4382 tc_arc_regname_to_dw2regnum (char *regname)
4384 struct symbol *sym;
4386 sym = str_hash_find (arc_reg_hash, regname);
4387 if (sym)
4388 return S_GET_VALUE (sym);
4390 return -1;
4393 /* Adjust the symbol table. Delete found AUX register symbols. */
4395 void
4396 arc_adjust_symtab (void)
4398 symbolS * sym;
4400 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
4402 /* I've created a symbol during parsing process. Now, remove
4403 the symbol as it is found to be an AUX register. */
4404 if (ARC_GET_FLAG (sym) & ARC_FLAG_AUX)
4405 symbol_remove (sym, &symbol_rootP, &symbol_lastP);
4408 /* Now do generic ELF adjustments. */
4409 elf_adjust_symtab ();
4412 static void
4413 tokenize_extinsn (extInstruction_t *einsn)
4415 char *p, c;
4416 char *insn_name;
4417 unsigned char major_opcode;
4418 unsigned char sub_opcode;
4419 unsigned char syntax_class = 0;
4420 unsigned char syntax_class_modifiers = 0;
4421 unsigned char suffix_class = 0;
4422 unsigned int i;
4424 SKIP_WHITESPACE ();
4426 /* 1st: get instruction name. */
4427 p = input_line_pointer;
4428 c = get_symbol_name (&p);
4430 insn_name = xstrdup (p);
4431 restore_line_pointer (c);
4433 /* Convert to lower case. */
4434 for (p = insn_name; *p; ++p)
4435 *p = TOLOWER (*p);
4437 /* 2nd: get major opcode. */
4438 if (*input_line_pointer != ',')
4440 as_bad (_("expected comma after instruction name"));
4441 ignore_rest_of_line ();
4442 return;
4444 input_line_pointer++;
4445 major_opcode = get_absolute_expression ();
4447 /* 3rd: get sub-opcode. */
4448 SKIP_WHITESPACE ();
4450 if (*input_line_pointer != ',')
4452 as_bad (_("expected comma after major opcode"));
4453 ignore_rest_of_line ();
4454 return;
4456 input_line_pointer++;
4457 sub_opcode = get_absolute_expression ();
4459 /* 4th: get suffix class. */
4460 SKIP_WHITESPACE ();
4462 if (*input_line_pointer != ',')
4464 as_bad ("expected comma after sub opcode");
4465 ignore_rest_of_line ();
4466 return;
4468 input_line_pointer++;
4470 while (1)
4472 SKIP_WHITESPACE ();
4474 for (i = 0; i < ARRAY_SIZE (suffixclass); i++)
4476 if (!strncmp (suffixclass[i].name, input_line_pointer,
4477 suffixclass[i].len))
4479 suffix_class |= suffixclass[i].attr_class;
4480 input_line_pointer += suffixclass[i].len;
4481 break;
4485 if (i == ARRAY_SIZE (suffixclass))
4487 as_bad ("invalid suffix class");
4488 ignore_rest_of_line ();
4489 return;
4492 SKIP_WHITESPACE ();
4494 if (*input_line_pointer == '|')
4495 input_line_pointer++;
4496 else
4497 break;
4500 /* 5th: get syntax class and syntax class modifiers. */
4501 if (*input_line_pointer != ',')
4503 as_bad ("expected comma after suffix class");
4504 ignore_rest_of_line ();
4505 return;
4507 input_line_pointer++;
4509 while (1)
4511 SKIP_WHITESPACE ();
4513 for (i = 0; i < ARRAY_SIZE (syntaxclassmod); i++)
4515 if (!strncmp (syntaxclassmod[i].name,
4516 input_line_pointer,
4517 syntaxclassmod[i].len))
4519 syntax_class_modifiers |= syntaxclassmod[i].attr_class;
4520 input_line_pointer += syntaxclassmod[i].len;
4521 break;
4525 if (i == ARRAY_SIZE (syntaxclassmod))
4527 for (i = 0; i < ARRAY_SIZE (syntaxclass); i++)
4529 if (!strncmp (syntaxclass[i].name,
4530 input_line_pointer,
4531 syntaxclass[i].len))
4533 syntax_class |= syntaxclass[i].attr_class;
4534 input_line_pointer += syntaxclass[i].len;
4535 break;
4539 if (i == ARRAY_SIZE (syntaxclass))
4541 as_bad ("missing syntax class");
4542 ignore_rest_of_line ();
4543 return;
4547 SKIP_WHITESPACE ();
4549 if (*input_line_pointer == '|')
4550 input_line_pointer++;
4551 else
4552 break;
4555 demand_empty_rest_of_line ();
4557 einsn->name = insn_name;
4558 einsn->major = major_opcode;
4559 einsn->minor = sub_opcode;
4560 einsn->syntax = syntax_class;
4561 einsn->modsyn = syntax_class_modifiers;
4562 einsn->suffix = suffix_class;
4563 einsn->flags = syntax_class
4564 | (syntax_class_modifiers & ARC_OP1_IMM_IMPLIED ? 0x10 : 0);
4567 /* Generate an extension section. */
4569 static int
4570 arc_set_ext_seg (void)
4572 if (!arcext_section)
4574 arcext_section = subseg_new (".arcextmap", 0);
4575 bfd_set_section_flags (arcext_section, SEC_READONLY | SEC_HAS_CONTENTS);
4577 else
4578 subseg_set (arcext_section, 0);
4579 return 1;
4582 /* Create an extension instruction description in the arc extension
4583 section of the output file.
4584 The structure for an instruction is like this:
4585 [0]: Length of the record.
4586 [1]: Type of the record.
4588 [2]: Major opcode.
4589 [3]: Sub-opcode.
4590 [4]: Syntax (flags).
4591 [5]+ Name instruction.
4593 The sequence is terminated by an empty entry. */
4595 static void
4596 create_extinst_section (extInstruction_t *einsn)
4599 segT old_sec = now_seg;
4600 int old_subsec = now_subseg;
4601 char *p;
4602 int name_len = strlen (einsn->name);
4604 arc_set_ext_seg ();
4606 p = frag_more (1);
4607 *p = 5 + name_len + 1;
4608 p = frag_more (1);
4609 *p = EXT_INSTRUCTION;
4610 p = frag_more (1);
4611 *p = einsn->major;
4612 p = frag_more (1);
4613 *p = einsn->minor;
4614 p = frag_more (1);
4615 *p = einsn->flags;
4616 p = frag_more (name_len + 1);
4617 strcpy (p, einsn->name);
4619 subseg_set (old_sec, old_subsec);
4622 /* Handler .extinstruction pseudo-op. */
4624 static void
4625 arc_extinsn (int ignore ATTRIBUTE_UNUSED)
4627 extInstruction_t einsn;
4628 struct arc_opcode *arc_ext_opcodes;
4629 const char *errmsg = NULL;
4630 unsigned char moplow, mophigh;
4632 memset (&einsn, 0, sizeof (einsn));
4633 tokenize_extinsn (&einsn);
4635 /* Check if the name is already used. */
4636 if (arc_find_opcode (einsn.name))
4637 as_warn (_("Pseudocode already used %s"), einsn.name);
4639 /* Check the opcode ranges. */
4640 moplow = 0x05;
4641 mophigh = (selected_cpu.flags & (ARC_OPCODE_ARCv2EM
4642 | ARC_OPCODE_ARCv2HS)) ? 0x07 : 0x0a;
4644 if ((einsn.major > mophigh) || (einsn.major < moplow))
4645 as_fatal (_("major opcode not in range [0x%02x - 0x%02x]"), moplow, mophigh);
4647 if ((einsn.minor > 0x3f) && (einsn.major != 0x0a)
4648 && (einsn.major != 5) && (einsn.major != 9))
4649 as_fatal (_("minor opcode not in range [0x00 - 0x3f]"));
4651 switch (einsn.syntax & ARC_SYNTAX_MASK)
4653 case ARC_SYNTAX_3OP:
4654 if (einsn.modsyn & ARC_OP1_IMM_IMPLIED)
4655 as_fatal (_("Improper use of OP1_IMM_IMPLIED"));
4656 break;
4657 case ARC_SYNTAX_2OP:
4658 case ARC_SYNTAX_1OP:
4659 case ARC_SYNTAX_NOP:
4660 if (einsn.modsyn & ARC_OP1_MUST_BE_IMM)
4661 as_fatal (_("Improper use of OP1_MUST_BE_IMM"));
4662 break;
4663 default:
4664 break;
4667 arc_ext_opcodes = arcExtMap_genOpcode (&einsn, selected_cpu.flags, &errmsg);
4668 if (arc_ext_opcodes == NULL)
4670 if (errmsg)
4671 as_fatal ("%s", errmsg);
4672 else
4673 as_fatal (_("Couldn't generate extension instruction opcodes"));
4675 else if (errmsg)
4676 as_warn ("%s", errmsg);
4678 /* Insert the extension instruction. */
4679 arc_insert_opcode ((const struct arc_opcode *) arc_ext_opcodes);
4681 create_extinst_section (&einsn);
4684 static bool
4685 tokenize_extregister (extRegister_t *ereg, int opertype)
4687 char *name;
4688 char *mode;
4689 char c;
4690 char *p;
4691 int number, imode = 0;
4692 bool isCore_p = opertype == EXT_CORE_REGISTER;
4693 bool isReg_p = opertype == EXT_CORE_REGISTER || opertype == EXT_AUX_REGISTER;
4695 /* 1st: get register name. */
4696 SKIP_WHITESPACE ();
4697 p = input_line_pointer;
4698 c = get_symbol_name (&p);
4700 name = xstrdup (p);
4701 restore_line_pointer (c);
4703 /* 2nd: get register number. */
4704 SKIP_WHITESPACE ();
4706 if (*input_line_pointer != ',')
4708 as_bad (_("expected comma after name"));
4709 ignore_rest_of_line ();
4710 free (name);
4711 return false;
4713 input_line_pointer++;
4714 number = get_absolute_expression ();
4716 if ((number < 0)
4717 && (opertype != EXT_AUX_REGISTER))
4719 as_bad (_("%s second argument cannot be a negative number %d"),
4720 isCore_p ? "extCoreRegister's" : "extCondCode's",
4721 number);
4722 ignore_rest_of_line ();
4723 free (name);
4724 return false;
4727 if (isReg_p)
4729 /* 3rd: get register mode. */
4730 SKIP_WHITESPACE ();
4732 if (*input_line_pointer != ',')
4734 as_bad (_("expected comma after register number"));
4735 ignore_rest_of_line ();
4736 free (name);
4737 return false;
4740 input_line_pointer++;
4741 mode = input_line_pointer;
4743 if (startswith (mode, "r|w"))
4745 imode = 0;
4746 input_line_pointer += 3;
4748 else if (startswith (mode, "r"))
4750 imode = ARC_REGISTER_READONLY;
4751 input_line_pointer += 1;
4753 else if (!startswith (mode, "w"))
4755 as_bad (_("invalid mode"));
4756 ignore_rest_of_line ();
4757 free (name);
4758 return false;
4760 else
4762 imode = ARC_REGISTER_WRITEONLY;
4763 input_line_pointer += 1;
4767 if (isCore_p)
4769 /* 4th: get core register shortcut. */
4770 SKIP_WHITESPACE ();
4771 if (*input_line_pointer != ',')
4773 as_bad (_("expected comma after register mode"));
4774 ignore_rest_of_line ();
4775 free (name);
4776 return false;
4779 input_line_pointer++;
4781 if (startswith (input_line_pointer, "cannot_shortcut"))
4783 imode |= ARC_REGISTER_NOSHORT_CUT;
4784 input_line_pointer += 15;
4786 else if (!startswith (input_line_pointer, "can_shortcut"))
4788 as_bad (_("shortcut designator invalid"));
4789 ignore_rest_of_line ();
4790 free (name);
4791 return false;
4793 else
4795 input_line_pointer += 12;
4798 demand_empty_rest_of_line ();
4800 ereg->name = name;
4801 ereg->number = number;
4802 ereg->imode = imode;
4803 return true;
4806 /* Create an extension register/condition description in the arc
4807 extension section of the output file.
4809 The structure for an instruction is like this:
4810 [0]: Length of the record.
4811 [1]: Type of the record.
4813 For core regs and condition codes:
4814 [2]: Value.
4815 [3]+ Name.
4817 For auxiliary registers:
4818 [2..5]: Value.
4819 [6]+ Name
4821 The sequence is terminated by an empty entry. */
4823 static void
4824 create_extcore_section (extRegister_t *ereg, int opertype)
4826 segT old_sec = now_seg;
4827 int old_subsec = now_subseg;
4828 char *p;
4829 int name_len = strlen (ereg->name);
4831 arc_set_ext_seg ();
4833 switch (opertype)
4835 case EXT_COND_CODE:
4836 case EXT_CORE_REGISTER:
4837 p = frag_more (1);
4838 *p = 3 + name_len + 1;
4839 p = frag_more (1);
4840 *p = opertype;
4841 p = frag_more (1);
4842 *p = ereg->number;
4843 break;
4844 case EXT_AUX_REGISTER:
4845 p = frag_more (1);
4846 *p = 6 + name_len + 1;
4847 p = frag_more (1);
4848 *p = EXT_AUX_REGISTER;
4849 p = frag_more (1);
4850 *p = (ereg->number >> 24) & 0xff;
4851 p = frag_more (1);
4852 *p = (ereg->number >> 16) & 0xff;
4853 p = frag_more (1);
4854 *p = (ereg->number >> 8) & 0xff;
4855 p = frag_more (1);
4856 *p = (ereg->number) & 0xff;
4857 break;
4858 default:
4859 break;
4862 p = frag_more (name_len + 1);
4863 strcpy (p, ereg->name);
4865 subseg_set (old_sec, old_subsec);
4868 /* Handler .extCoreRegister pseudo-op. */
4870 static void
4871 arc_extcorereg (int opertype)
4873 extRegister_t ereg;
4874 struct arc_aux_reg *auxr;
4875 struct arc_flag_operand *ccode;
4877 memset (&ereg, 0, sizeof (ereg));
4878 if (!tokenize_extregister (&ereg, opertype))
4879 return;
4881 switch (opertype)
4883 case EXT_CORE_REGISTER:
4884 /* Core register. */
4885 if (ereg.number > 60)
4886 as_bad (_("core register %s value (%d) too large"), ereg.name,
4887 ereg.number);
4888 declare_register (ereg.name, ereg.number);
4889 break;
4890 case EXT_AUX_REGISTER:
4891 /* Auxiliary register. */
4892 auxr = XNEW (struct arc_aux_reg);
4893 auxr->name = ereg.name;
4894 auxr->cpu = selected_cpu.flags;
4895 auxr->subclass = NONE;
4896 auxr->address = ereg.number;
4897 if (str_hash_insert (arc_aux_hash, auxr->name, auxr, 0) != NULL)
4898 as_bad (_("duplicate aux register %s"), auxr->name);
4899 break;
4900 case EXT_COND_CODE:
4901 /* Condition code. */
4902 if (ereg.number > 31)
4903 as_bad (_("condition code %s value (%d) too large"), ereg.name,
4904 ereg.number);
4905 ext_condcode.size ++;
4906 ext_condcode.arc_ext_condcode =
4907 XRESIZEVEC (struct arc_flag_operand, ext_condcode.arc_ext_condcode,
4908 ext_condcode.size + 1);
4910 ccode = ext_condcode.arc_ext_condcode + ext_condcode.size - 1;
4911 ccode->name = ereg.name;
4912 ccode->code = ereg.number;
4913 ccode->bits = 5;
4914 ccode->shift = 0;
4915 ccode->favail = 0; /* not used. */
4916 ccode++;
4917 memset (ccode, 0, sizeof (struct arc_flag_operand));
4918 break;
4919 default:
4920 as_bad (_("Unknown extension"));
4921 break;
4923 create_extcore_section (&ereg, opertype);
4926 /* Parse a .arc_attribute directive. */
4928 static void
4929 arc_attribute (int ignored ATTRIBUTE_UNUSED)
4931 int tag = obj_elf_vendor_attribute (OBJ_ATTR_PROC);
4933 if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
4934 attributes_set_explicitly[tag] = true;
4937 /* Set an attribute if it has not already been set by the user. */
4939 static void
4940 arc_set_attribute_int (int tag, int value)
4942 if (tag < 1
4943 || tag >= NUM_KNOWN_OBJ_ATTRIBUTES
4944 || !attributes_set_explicitly[tag])
4945 if (!bfd_elf_add_proc_attr_int (stdoutput, tag, value))
4946 as_fatal (_("error adding attribute: %s"),
4947 bfd_errmsg (bfd_get_error ()));
4950 static void
4951 arc_set_attribute_string (int tag, const char *value)
4953 if (tag < 1
4954 || tag >= NUM_KNOWN_OBJ_ATTRIBUTES
4955 || !attributes_set_explicitly[tag])
4956 if (!bfd_elf_add_proc_attr_string (stdoutput, tag, value))
4957 as_fatal (_("error adding attribute: %s"),
4958 bfd_errmsg (bfd_get_error ()));
4961 /* Allocate and concatenate two strings. s1 can be NULL but not
4962 s2. s1 pointer is freed at end of this procedure. */
4964 static char *
4965 arc_stralloc (char * s1, const char * s2)
4967 char * p;
4968 int len = 0;
4970 if (s1)
4971 len = strlen (s1) + 1;
4973 /* Only s1 can be null. */
4974 gas_assert (s2);
4975 len += strlen (s2) + 1;
4977 p = (char *) xmalloc (len);
4979 if (s1)
4981 strcpy (p, s1);
4982 strcat (p, ",");
4983 strcat (p, s2);
4984 free (s1);
4986 else
4987 strcpy (p, s2);
4989 return p;
4992 /* Set the public ARC object attributes. */
4994 static void
4995 arc_set_public_attributes (void)
4997 int base = 0;
4998 char *s = NULL;
4999 unsigned int i;
5001 /* Tag_ARC_CPU_name. */
5002 arc_set_attribute_string (Tag_ARC_CPU_name, selected_cpu.name);
5004 /* Tag_ARC_CPU_base. */
5005 switch (selected_cpu.eflags & EF_ARC_MACH_MSK)
5007 case E_ARC_MACH_ARC600:
5008 case E_ARC_MACH_ARC601:
5009 base = TAG_CPU_ARC6xx;
5010 break;
5011 case E_ARC_MACH_ARC700:
5012 base = TAG_CPU_ARC7xx;
5013 break;
5014 case EF_ARC_CPU_ARCV2EM:
5015 base = TAG_CPU_ARCEM;
5016 break;
5017 case EF_ARC_CPU_ARCV2HS:
5018 base = TAG_CPU_ARCHS;
5019 break;
5020 default:
5021 base = 0;
5022 break;
5024 if (attributes_set_explicitly[Tag_ARC_CPU_base]
5025 && (base != bfd_elf_get_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
5026 Tag_ARC_CPU_base)))
5027 as_warn (_("Overwrite explicitly set Tag_ARC_CPU_base"));
5028 if (!bfd_elf_add_proc_attr_int (stdoutput, Tag_ARC_CPU_base, base))
5029 as_fatal (_("error adding attribute: %s"),
5030 bfd_errmsg (bfd_get_error ()));
5032 /* Tag_ARC_ABI_osver. */
5033 if (attributes_set_explicitly[Tag_ARC_ABI_osver])
5035 int val = bfd_elf_get_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
5036 Tag_ARC_ABI_osver);
5038 selected_cpu.eflags = ((selected_cpu.eflags & ~EF_ARC_OSABI_MSK)
5039 | (val & 0x0f << 8));
5041 else
5043 arc_set_attribute_int (Tag_ARC_ABI_osver, E_ARC_OSABI_CURRENT >> 8);
5046 /* Tag_ARC_ISA_config. */
5047 arc_check_feature();
5049 for (i = 0; i < ARRAY_SIZE (feature_list); i++)
5050 if (selected_cpu.features & feature_list[i].feature)
5051 s = arc_stralloc (s, feature_list[i].attr);
5053 if (s)
5054 arc_set_attribute_string (Tag_ARC_ISA_config, s);
5056 /* Tag_ARC_ISA_mpy_option. */
5057 arc_set_attribute_int (Tag_ARC_ISA_mpy_option, mpy_option);
5059 /* Tag_ARC_ABI_pic. */
5060 arc_set_attribute_int (Tag_ARC_ABI_pic, pic_option);
5062 /* Tag_ARC_ABI_sda. */
5063 arc_set_attribute_int (Tag_ARC_ABI_sda, sda_option);
5065 /* Tag_ARC_ABI_tls. */
5066 arc_set_attribute_int (Tag_ARC_ABI_tls, tls_option);
5068 /* Tag_ARC_ATR_version. */
5069 arc_set_attribute_int (Tag_ARC_ATR_version, 1);
5071 /* Tag_ARC_ABI_rf16. */
5072 if (attributes_set_explicitly[Tag_ARC_ABI_rf16]
5073 && bfd_elf_get_obj_attr_int (stdoutput, OBJ_ATTR_PROC,
5074 Tag_ARC_ABI_rf16)
5075 && !rf16_only)
5077 as_warn (_("Overwrite explicitly set Tag_ARC_ABI_rf16 to full "
5078 "register file"));
5079 if (!bfd_elf_add_proc_attr_int (stdoutput, Tag_ARC_ABI_rf16, 0))
5080 as_fatal (_("error adding attribute: %s"),
5081 bfd_errmsg (bfd_get_error ()));
5085 /* Add the default contents for the .ARC.attributes section. */
5087 void
5088 arc_md_finish (void)
5090 arc_set_public_attributes ();
5092 if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, selected_cpu.mach))
5093 as_fatal (_("could not set architecture and machine"));
5095 bfd_set_private_flags (stdoutput, selected_cpu.eflags);
5098 void arc_copy_symbol_attributes (symbolS *dest, symbolS *src)
5100 ARC_GET_FLAG (dest) = ARC_GET_FLAG (src);
5103 int arc_convert_symbolic_attribute (const char *name)
5105 static const struct
5107 const char * name;
5108 const int tag;
5110 attribute_table[] =
5112 #define T(tag) {#tag, tag}
5113 T (Tag_ARC_PCS_config),
5114 T (Tag_ARC_CPU_base),
5115 T (Tag_ARC_CPU_variation),
5116 T (Tag_ARC_CPU_name),
5117 T (Tag_ARC_ABI_rf16),
5118 T (Tag_ARC_ABI_osver),
5119 T (Tag_ARC_ABI_sda),
5120 T (Tag_ARC_ABI_pic),
5121 T (Tag_ARC_ABI_tls),
5122 T (Tag_ARC_ABI_enumsize),
5123 T (Tag_ARC_ABI_exceptions),
5124 T (Tag_ARC_ABI_double_size),
5125 T (Tag_ARC_ISA_config),
5126 T (Tag_ARC_ISA_apex),
5127 T (Tag_ARC_ISA_mpy_option),
5128 T (Tag_ARC_ATR_version)
5129 #undef T
5131 unsigned int i;
5133 if (name == NULL)
5134 return -1;
5136 for (i = 0; i < ARRAY_SIZE (attribute_table); i++)
5137 if (streq (name, attribute_table[i].name))
5138 return attribute_table[i].tag;
5140 return -1;
5143 /* Local variables:
5144 eval: (c-set-style "gnu")
5145 indent-tabs-mode: t
5146 End: */