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