cbf218045aac452c4d4c49ab523f4e4996e20f06
[external/binutils.git] / gas / config / tc-arc.c
1 /* tc-arc.c -- Assembler for the ARC
2    Copyright (C) 1994-2015 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 "safe-ctype.h"
28
29 #include "opcode/arc.h"
30 #include "elf/arc.h"
31
32 /* Defines section.  */
33
34 #define MAX_FLAG_NAME_LENGHT 3
35 #define MAX_INSN_FIXUPS      2
36 #define MAX_CONSTR_STR       20
37
38 #ifdef DEBUG
39 # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
40 #else
41 # define pr_debug(fmt, args...)
42 #endif
43
44 #define MAJOR_OPCODE(x)  (((x) & 0xF8000000) >> 27)
45 #define SUB_OPCODE(x)    (((x) & 0x003F0000) >> 16)
46 #define LP_INSN(x)       ((MAJOR_OPCODE (x) == 0x4) &&  \
47                           (SUB_OPCODE (x) == 0x28))
48
49 /* Equal to MAX_PRECISION in atof-ieee.c.  */
50 #define MAX_LITTLENUMS 6
51
52 /* Macros section.  */
53
54 #define regno(x)                ((x) & 0x3F)
55 #define is_ir_num(x)            (((x) & ~0x3F) == 0)
56 #define is_code_density_p(op)   (((op)->subclass == CD1 || (op)->subclass == CD2))
57 #define is_br_jmp_insn_p(op)    (((op)->class == BRANCH || (op)->class == JUMP))
58 #define is_kernel_insn_p(op)    (((op)->class == KERNEL))
59
60 /* Generic assembler global variables which must be defined by all
61    targets.  */
62
63 /* Characters which always start a comment.  */
64 const char comment_chars[] = "#;";
65
66 /* Characters which start a comment at the beginning of a line.  */
67 const char line_comment_chars[] = "#";
68
69 /* Characters which may be used to separate multiple commands on a
70    single line.  */
71 const char line_separator_chars[] = "`";
72
73 /* Characters which are used to indicate an exponent in a floating
74    point number.  */
75 const char EXP_CHARS[] = "eE";
76
77 /* Chars that mean this number is a floating point constant
78    As in 0f12.456 or 0d1.2345e12.  */
79 const char FLT_CHARS[] = "rRsSfFdD";
80
81 /* Byte order.  */
82 extern int target_big_endian;
83 const char *arc_target_format = DEFAULT_TARGET_FORMAT;
84 static int byte_order = DEFAULT_BYTE_ORDER;
85
86 extern int arc_get_mach (char *);
87
88 /* Forward declaration.  */
89 static void arc_lcomm (int);
90 static void arc_option (int);
91 static void arc_extra_reloc (int);
92
93 const pseudo_typeS md_pseudo_table[] =
94 {
95   /* Make sure that .word is 32 bits.  */
96   { "word", cons, 4 },
97
98   { "align",   s_align_bytes, 0 }, /* Defaulting is invalid (0).  */
99   { "lcomm",   arc_lcomm, 0 },
100   { "lcommon", arc_lcomm, 0 },
101   { "cpu",     arc_option, 0 },
102
103   { "tls_gd_ld",   arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_LD },
104   { "tls_gd_call", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_CALL },
105
106   { NULL, NULL, 0 }
107 };
108
109 const char *md_shortopts = "";
110
111 enum options
112 {
113   OPTION_EB = OPTION_MD_BASE,
114   OPTION_EL,
115
116   OPTION_ARC600,
117   OPTION_ARC601,
118   OPTION_ARC700,
119   OPTION_ARCEM,
120   OPTION_ARCHS,
121
122   OPTION_MCPU,
123   OPTION_CD,
124
125   /* The following options are deprecated and provided here only for
126      compatibility reasons.  */
127   OPTION_USER_MODE,
128   OPTION_LD_EXT_MASK,
129   OPTION_SWAP,
130   OPTION_NORM,
131   OPTION_BARREL_SHIFT,
132   OPTION_MIN_MAX,
133   OPTION_NO_MPY,
134   OPTION_EA,
135   OPTION_MUL64,
136   OPTION_SIMD,
137   OPTION_SPFP,
138   OPTION_DPFP,
139   OPTION_XMAC_D16,
140   OPTION_XMAC_24,
141   OPTION_DSP_PACKA,
142   OPTION_CRC,
143   OPTION_DVBF,
144   OPTION_TELEPHONY,
145   OPTION_XYMEMORY,
146   OPTION_LOCK,
147   OPTION_SWAPE,
148   OPTION_RTSC,
149   OPTION_FPUDA
150 };
151
152 struct option md_longopts[] =
153 {
154   { "EB",               no_argument,       NULL, OPTION_EB },
155   { "EL",               no_argument,       NULL, OPTION_EL },
156   { "mcpu",             required_argument, NULL, OPTION_MCPU },
157   { "mA6",              no_argument,       NULL, OPTION_ARC600 },
158   { "mARC600",          no_argument,       NULL, OPTION_ARC600 },
159   { "mARC601",          no_argument,       NULL, OPTION_ARC601 },
160   { "mARC700",          no_argument,       NULL, OPTION_ARC700 },
161   { "mA7",              no_argument,       NULL, OPTION_ARC700 },
162   { "mEM",              no_argument,       NULL, OPTION_ARCEM },
163   { "mHS",              no_argument,       NULL, OPTION_ARCHS },
164   { "mcode-density",    no_argument,       NULL, OPTION_CD },
165
166   /* The following options are deprecated and provided here only for
167      compatibility reasons.  */
168   { "mav2em", no_argument, NULL, OPTION_ARCEM },
169   { "mav2hs", no_argument, NULL, OPTION_ARCHS },
170   { "muser-mode-only", no_argument, NULL, OPTION_USER_MODE },
171   { "mld-extension-reg-mask", required_argument, NULL, OPTION_LD_EXT_MASK },
172   { "mswap", no_argument, NULL, OPTION_SWAP },
173   { "mnorm", no_argument, NULL, OPTION_NORM },
174   { "mbarrel-shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
175   { "mbarrel_shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
176   { "mmin-max", no_argument, NULL, OPTION_MIN_MAX },
177   { "mmin_max", no_argument, NULL, OPTION_MIN_MAX },
178   { "mno-mpy", no_argument, NULL, OPTION_NO_MPY },
179   { "mea", no_argument, NULL, OPTION_EA },
180   { "mEA", no_argument, NULL, OPTION_EA },
181   { "mmul64", no_argument, NULL, OPTION_MUL64 },
182   { "msimd", no_argument, NULL, OPTION_SIMD},
183   { "mspfp", no_argument, NULL, OPTION_SPFP},
184   { "mspfp-compact", no_argument, NULL, OPTION_SPFP},
185   { "mspfp_compact", no_argument, NULL, OPTION_SPFP},
186   { "mspfp-fast", no_argument, NULL, OPTION_SPFP},
187   { "mspfp_fast", no_argument, NULL, OPTION_SPFP},
188   { "mdpfp", no_argument, NULL, OPTION_DPFP},
189   { "mdpfp-compact", no_argument, NULL, OPTION_DPFP},
190   { "mdpfp_compact", no_argument, NULL, OPTION_DPFP},
191   { "mdpfp-fast", no_argument, NULL, OPTION_DPFP},
192   { "mdpfp_fast", no_argument, NULL, OPTION_DPFP},
193   { "mmac-d16", no_argument, NULL, OPTION_XMAC_D16},
194   { "mmac_d16", no_argument, NULL, OPTION_XMAC_D16},
195   { "mmac-24", no_argument, NULL, OPTION_XMAC_24},
196   { "mmac_24", no_argument, NULL, OPTION_XMAC_24},
197   { "mdsp-packa", no_argument, NULL, OPTION_DSP_PACKA},
198   { "mdsp_packa", no_argument, NULL, OPTION_DSP_PACKA},
199   { "mcrc", no_argument, NULL, OPTION_CRC},
200   { "mdvbf", no_argument, NULL, OPTION_DVBF},
201   { "mtelephony", no_argument, NULL, OPTION_TELEPHONY},
202   { "mxy", no_argument, NULL, OPTION_XYMEMORY},
203   { "mlock", no_argument, NULL, OPTION_LOCK},
204   { "mswape", no_argument, NULL, OPTION_SWAPE},
205   { "mrtsc", no_argument, NULL, OPTION_RTSC},
206   { "mfpuda", no_argument, NULL, OPTION_FPUDA},
207
208   { NULL,               no_argument, NULL, 0 }
209 };
210
211 size_t md_longopts_size = sizeof (md_longopts);
212
213 /* Local data and data types.  */
214
215 /* Used since new relocation types are introduced in this
216    file (DUMMY_RELOC_LITUSE_*).  */
217 typedef int extended_bfd_reloc_code_real_type;
218
219 struct arc_fixup
220 {
221   expressionS exp;
222
223   extended_bfd_reloc_code_real_type reloc;
224
225   /* index into arc_operands.  */
226   unsigned int opindex;
227
228   /* PC-relative, used by internals fixups.  */
229   unsigned char pcrel;
230
231   /* TRUE if this fixup is for LIMM operand.  */
232   bfd_boolean islong;
233 };
234
235 struct arc_insn
236 {
237   unsigned int insn;
238   int nfixups;
239   struct arc_fixup fixups[MAX_INSN_FIXUPS];
240   long limm;
241   bfd_boolean short_insn; /* Boolean value: TRUE if current insn is
242                              short.  */
243   bfd_boolean has_limm;   /* Boolean value: TRUE if limm field is
244                              valid.  */
245 };
246
247 /* Structure to hold any last two instructions.  */
248 static struct arc_last_insn
249 {
250   /* Saved instruction opcode.  */
251   const struct arc_opcode *opcode;
252
253   /* Boolean value: TRUE if current insn is short.  */
254   bfd_boolean has_limm;
255
256   /* Boolean value: TRUE if current insn has delay slot.  */
257   bfd_boolean has_delay_slot;
258 } arc_last_insns[2];
259
260 /* The cpu for which we are generating code.  */
261 static unsigned arc_target = ARC_OPCODE_BASE;
262 static const char *arc_target_name = "<all>";
263 static unsigned arc_features = 0x00;
264
265 /* The default architecture.  */
266 static int arc_mach_type = bfd_mach_arc_arcv2;
267
268 /* Non-zero if the cpu type has been explicitly specified.  */
269 static int mach_type_specified_p = 0;
270
271 /* The hash table of instruction opcodes.  */
272 static struct hash_control *arc_opcode_hash;
273
274 /* The hash table of register symbols.  */
275 static struct hash_control *arc_reg_hash;
276
277 /* A table of CPU names and opcode sets.  */
278 static const struct cpu_type
279 {
280   const char *name;
281   unsigned flags;
282   int mach;
283   unsigned eflags;
284   unsigned features;
285 }
286   cpu_types[] =
287 {
288   { "arc600", ARC_OPCODE_ARC600,  bfd_mach_arc_arc600,
289     E_ARC_MACH_ARC600,  0x00},
290   { "arc700", ARC_OPCODE_ARC700,  bfd_mach_arc_arc700,
291     E_ARC_MACH_ARC700,  0x00},
292   { "arcem",  ARC_OPCODE_ARCv2EM, bfd_mach_arc_arcv2,
293     EF_ARC_CPU_ARCV2EM, 0x00},
294   { "archs",  ARC_OPCODE_ARCv2HS, bfd_mach_arc_arcv2,
295     EF_ARC_CPU_ARCV2HS, ARC_CD},
296   { "all",    ARC_OPCODE_BASE,    bfd_mach_arc_arcv2,
297     0x00, 0x00 },
298   { 0, 0, 0, 0, 0 }
299 };
300
301 struct arc_flags
302 {
303   /* Name of the parsed flag.  */
304   char name[MAX_FLAG_NAME_LENGHT+1];
305
306   /* The code of the parsed flag.  Valid when is not zero.  */
307   unsigned char code;
308 };
309
310 /* Used by the arc_reloc_op table.  Order is important.  */
311 #define O_gotoff  O_md1     /* @gotoff relocation.  */
312 #define O_gotpc   O_md2     /* @gotpc relocation.  */
313 #define O_plt     O_md3     /* @plt relocation.  */
314 #define O_sda     O_md4     /* @sda relocation.  */
315 #define O_pcl     O_md5     /* @pcl relocation.  */
316 #define O_tlsgd   O_md6     /* @tlsgd relocation.  */
317 #define O_tlsie   O_md7     /* @tlsie relocation.  */
318 #define O_tpoff9  O_md8     /* @tpoff9 relocation.  */
319 #define O_tpoff   O_md9     /* @tpoff relocation.  */
320 #define O_dtpoff9 O_md10    /* @dtpoff9 relocation.  */
321 #define O_dtpoff  O_md11    /* @dtpoff relocation.  */
322 #define O_last    O_dtpoff
323
324 /* Used to define a bracket as operand in tokens.  */
325 #define O_bracket O_md32
326
327 /* Dummy relocation, to be sorted out.  */
328 #define DUMMY_RELOC_ARC_ENTRY     (BFD_RELOC_UNUSED + 1)
329
330 #define USER_RELOC_P(R) ((R) >= O_gotoff && (R) <= O_last)
331
332 /* A table to map the spelling of a relocation operand into an appropriate
333    bfd_reloc_code_real_type type.  The table is assumed to be ordered such
334    that op-O_literal indexes into it.  */
335 #define ARC_RELOC_TABLE(op)                             \
336   (&arc_reloc_op[ ((!USER_RELOC_P (op))                 \
337                    ? (abort (), 0)                      \
338                    : (int) (op) - (int) O_gotoff) ])
339
340 #define DEF(NAME, RELOC, REQ)                           \
341   { #NAME, sizeof (#NAME)-1, O_##NAME, RELOC, REQ}
342
343 static const struct arc_reloc_op_tag
344 {
345   /* String to lookup.  */
346   const char *name;
347   /* Size of the string.  */
348   size_t length;
349   /* Which operator to use.  */
350   operatorT op;
351   extended_bfd_reloc_code_real_type reloc;
352   /* Allows complex relocation expression like identifier@reloc +
353      const.  */
354   unsigned int complex_expr : 1;
355 }
356   arc_reloc_op[] =
357 {
358   DEF (gotoff,  BFD_RELOC_ARC_GOTOFF,           1),
359   DEF (gotpc,   BFD_RELOC_ARC_GOTPC32,          0),
360   DEF (plt,     BFD_RELOC_ARC_PLT32,            0),
361   DEF (sda,     DUMMY_RELOC_ARC_ENTRY,          1),
362   DEF (pcl,     BFD_RELOC_ARC_PC32,             1),
363   DEF (tlsgd,   BFD_RELOC_ARC_TLS_GD_GOT,       0),
364   DEF (tlsie,   BFD_RELOC_ARC_TLS_IE_GOT,       0),
365   DEF (tpoff9,  BFD_RELOC_ARC_TLS_LE_S9,        0),
366   DEF (tpoff,   BFD_RELOC_ARC_TLS_LE_32,        0),
367   DEF (dtpoff9, BFD_RELOC_ARC_TLS_DTPOFF_S9,    0),
368   DEF (dtpoff,  BFD_RELOC_ARC_TLS_DTPOFF,       0),
369 };
370
371 static const int arc_num_reloc_op
372 = sizeof (arc_reloc_op) / sizeof (*arc_reloc_op);
373
374 /* Flags to set in the elf header.  */
375 static flagword arc_eflag = 0x00;
376
377 /* Pre-defined "_GLOBAL_OFFSET_TABLE_".  */
378 symbolS * GOT_symbol = 0;
379
380 /* Set to TRUE when we assemble instructions.  */
381 static bfd_boolean assembling_insn = FALSE;
382
383 /* Functions declaration.  */
384
385 static void assemble_tokens (const char *, expressionS *, int,
386                              struct arc_flags *, int);
387 static const struct arc_opcode *find_opcode_match (const struct arc_opcode *,
388                                                    expressionS *, int *,
389                                                    struct arc_flags *,
390                                                    int, int *);
391 static void assemble_insn (const struct arc_opcode *, const expressionS *,
392                            int, const struct arc_flags *, int,
393                            struct arc_insn *);
394 static void emit_insn (struct arc_insn *);
395 static unsigned insert_operand (unsigned, const struct arc_operand *,
396                                 offsetT, char *, unsigned);
397 static const struct arc_opcode *find_special_case_flag (const char *,
398                                                         int *,
399                                                         struct arc_flags *);
400 static const struct arc_opcode *find_special_case (const char *,
401                                                    int *,
402                                                    struct arc_flags *,
403                                                    expressionS *, int *);
404 static const struct arc_opcode *find_special_case_pseudo (const char *,
405                                                           int *,
406                                                           expressionS *,
407                                                           int *,
408                                                           struct arc_flags *);
409
410 /* Functions implementation.  */
411
412 /* Like md_number_to_chars but used for limms.  The 4-byte limm value,
413    is encoded as 'middle-endian' for a little-endian target.  FIXME!
414    this function is used for regular 4 byte instructions as well.  */
415
416 static void
417 md_number_to_chars_midend (char *buf, valueT val, int n)
418 {
419   if (n == 4)
420     {
421       md_number_to_chars (buf,     (val & 0xffff0000) >> 16, 2);
422       md_number_to_chars (buf + 2, (val & 0xffff), 2);
423     }
424   else
425     {
426       md_number_to_chars (buf, val, n);
427     }
428 }
429
430 /* Here ends all the ARCompact extension instruction assembling
431    stuff.  */
432
433 static void
434 arc_extra_reloc (int r_type)
435 {
436   char *sym_name, c;
437   symbolS *sym, *lab = NULL;
438
439   if (*input_line_pointer == '@')
440     input_line_pointer++;
441   c = get_symbol_name (&sym_name);
442   sym = symbol_find_or_make (sym_name);
443   restore_line_pointer (c);
444   if (c == ',' && r_type == BFD_RELOC_ARC_TLS_GD_LD)
445     {
446       ++input_line_pointer;
447       char *lab_name;
448       c = get_symbol_name (&lab_name);
449       lab = symbol_find_or_make (lab_name);
450       restore_line_pointer (c);
451     }
452   fixS *fixP
453     = fix_new (frag_now,        /* Which frag?  */
454                frag_now_fix (), /* Where in that frag?  */
455                2,               /* size: 1, 2, or 4 usually.  */
456                sym,             /* X_add_symbol.  */
457                0,               /* X_add_number.  */
458                FALSE,           /* TRUE if PC-relative relocation.  */
459                r_type           /* Relocation type.  */);
460   fixP->fx_subsy = lab;
461 }
462
463 static symbolS *
464 arc_lcomm_internal (int ignore ATTRIBUTE_UNUSED,
465                     symbolS *symbolP, addressT size)
466 {
467   addressT align = 0;
468   SKIP_WHITESPACE ();
469
470   if (*input_line_pointer == ',')
471     {
472       align = parse_align (1);
473
474       if (align == (addressT) -1)
475         return NULL;
476     }
477   else
478     {
479       if (size >= 8)
480         align = 3;
481       else if (size >= 4)
482         align = 2;
483       else if (size >= 2)
484         align = 1;
485       else
486         align = 0;
487     }
488
489   bss_alloc (symbolP, size, align);
490   S_CLEAR_EXTERNAL (symbolP);
491
492   return symbolP;
493 }
494
495 static void
496 arc_lcomm (int ignore)
497 {
498   symbolS *symbolP = s_comm_internal (ignore, arc_lcomm_internal);
499
500   if (symbolP)
501     symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
502 }
503
504 /* Select the cpu we're assembling for.  */
505
506 static void
507 arc_option (int ignore ATTRIBUTE_UNUSED)
508 {
509   int mach = -1;
510   char c;
511   char *cpu;
512
513   c = get_symbol_name (&cpu);
514   mach = arc_get_mach (cpu);
515
516   if (mach == -1)
517     goto bad_cpu;
518
519   if (!mach_type_specified_p)
520     {
521       if ((!strcmp ("ARC600", cpu))
522           || (!strcmp ("ARC601", cpu))
523           || (!strcmp ("A6", cpu)))
524         {
525           md_parse_option (OPTION_MCPU, "arc600");
526         }
527       else if ((!strcmp ("ARC700", cpu))
528                || (!strcmp ("A7", cpu)))
529         {
530           md_parse_option (OPTION_MCPU, "arc700");
531         }
532       else if (!strcmp ("EM", cpu))
533         {
534           md_parse_option (OPTION_MCPU, "arcem");
535         }
536       else if (!strcmp ("HS", cpu))
537         {
538           md_parse_option (OPTION_MCPU, "archs");
539         }
540       else
541         as_fatal ("could not find the architecture");
542
543       if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach))
544         as_fatal ("could not set architecture and machine");
545     }
546   else
547     if (arc_mach_type != mach)
548       as_warn ("Command-line value overrides \".cpu\" directive");
549
550   restore_line_pointer (c);
551   demand_empty_rest_of_line ();
552   return;
553
554  bad_cpu:
555   restore_line_pointer (c);
556   as_bad ("invalid identifier for \".cpu\"");
557   ignore_rest_of_line ();
558 }
559
560 /* Smartly print an expression.  */
561
562 static void
563 debug_exp (expressionS *t)
564 {
565   const char *name ATTRIBUTE_UNUSED;
566   const char *namemd ATTRIBUTE_UNUSED;
567
568   pr_debug ("debug_exp: ");
569
570   switch (t->X_op)
571     {
572     default:                    name = "unknown";               break;
573     case O_illegal:             name = "O_illegal";             break;
574     case O_absent:              name = "O_absent";              break;
575     case O_constant:            name = "O_constant";            break;
576     case O_symbol:              name = "O_symbol";              break;
577     case O_symbol_rva:          name = "O_symbol_rva";          break;
578     case O_register:            name = "O_register";            break;
579     case O_big:                 name = "O_big";                 break;
580     case O_uminus:              name = "O_uminus";              break;
581     case O_bit_not:             name = "O_bit_not";             break;
582     case O_logical_not:         name = "O_logical_not";         break;
583     case O_multiply:            name = "O_multiply";            break;
584     case O_divide:              name = "O_divide";              break;
585     case O_modulus:             name = "O_modulus";             break;
586     case O_left_shift:          name = "O_left_shift";          break;
587     case O_right_shift:         name = "O_right_shift";         break;
588     case O_bit_inclusive_or:    name = "O_bit_inclusive_or";    break;
589     case O_bit_or_not:          name = "O_bit_or_not";          break;
590     case O_bit_exclusive_or:    name = "O_bit_exclusive_or";    break;
591     case O_bit_and:             name = "O_bit_and";             break;
592     case O_add:                 name = "O_add";                 break;
593     case O_subtract:            name = "O_subtract";            break;
594     case O_eq:                  name = "O_eq";                  break;
595     case O_ne:                  name = "O_ne";                  break;
596     case O_lt:                  name = "O_lt";                  break;
597     case O_le:                  name = "O_le";                  break;
598     case O_ge:                  name = "O_ge";                  break;
599     case O_gt:                  name = "O_gt";                  break;
600     case O_logical_and:         name = "O_logical_and";         break;
601     case O_logical_or:          name = "O_logical_or";          break;
602     case O_index:               name = "O_index";               break;
603     case O_bracket:             name = "O_bracket";             break;
604     }
605
606   switch (t->X_md)
607     {
608     default:                    namemd = "unknown";             break;
609     case O_gotoff:              namemd = "O_gotoff";            break;
610     case O_gotpc:               namemd = "O_gotpc";             break;
611     case O_plt:                 namemd = "O_plt";               break;
612     case O_sda:                 namemd = "O_sda";               break;
613     case O_pcl:                 namemd = "O_pcl";               break;
614     case O_tlsgd:               namemd = "O_tlsgd";             break;
615     case O_tlsie:               namemd = "O_tlsie";             break;
616     case O_tpoff9:              namemd = "O_tpoff9";            break;
617     case O_tpoff:               namemd = "O_tpoff";             break;
618     case O_dtpoff9:             namemd = "O_dtpoff9";           break;
619     case O_dtpoff:              namemd = "O_dtpoff";            break;
620     }
621
622   pr_debug ("%s (%s, %s, %d, %s)", name,
623             (t->X_add_symbol) ? S_GET_NAME (t->X_add_symbol) : "--",
624             (t->X_op_symbol) ? S_GET_NAME (t->X_op_symbol) : "--",
625             (int) t->X_add_number,
626             (t->X_md) ? namemd : "--");
627   pr_debug ("\n");
628   fflush (stderr);
629 }
630
631 /* Parse the arguments to an opcode.  */
632
633 static int
634 tokenize_arguments (char *str,
635                     expressionS *tok,
636                     int ntok)
637 {
638   char *old_input_line_pointer;
639   bfd_boolean saw_comma = FALSE;
640   bfd_boolean saw_arg = FALSE;
641   int brk_lvl = 0;
642   int num_args = 0;
643   int i;
644   size_t len;
645   const struct arc_reloc_op_tag *r;
646   expressionS tmpE;
647   char *reloc_name, c;
648
649   memset (tok, 0, sizeof (*tok) * ntok);
650
651   /* Save and restore input_line_pointer around this function.  */
652   old_input_line_pointer = input_line_pointer;
653   input_line_pointer = str;
654
655   while (*input_line_pointer)
656     {
657       SKIP_WHITESPACE ();
658       switch (*input_line_pointer)
659         {
660         case '\0':
661           goto fini;
662
663         case ',':
664           input_line_pointer++;
665           if (saw_comma || !saw_arg)
666             goto err;
667           saw_comma = TRUE;
668           break;
669
670         case '}':
671         case ']':
672           ++input_line_pointer;
673           --brk_lvl;
674           if (!saw_arg)
675             goto err;
676           tok->X_op = O_bracket;
677           ++tok;
678           ++num_args;
679           break;
680
681         case '{':
682         case '[':
683           input_line_pointer++;
684           if (brk_lvl)
685             goto err;
686           ++brk_lvl;
687           tok->X_op = O_bracket;
688           ++tok;
689           ++num_args;
690           break;
691
692         case '@':
693           /* We have labels, function names and relocations, all
694              starting with @ symbol.  Sort them out.  */
695           if (saw_arg && !saw_comma)
696             goto err;
697
698           /* Parse @label.  */
699           tok->X_op = O_symbol;
700           tok->X_md = O_absent;
701           expression (tok);
702           if (*input_line_pointer != '@')
703             goto normalsymbol; /* This is not a relocation.  */
704
705         relocationsym:
706
707           /* A relocation opernad has the following form
708              @identifier@relocation_type.  The identifier is already
709              in tok!  */
710           if (tok->X_op != O_symbol)
711             {
712               as_bad (_("No valid label relocation operand"));
713               goto err;
714             }
715
716           /* Parse @relocation_type.  */
717           input_line_pointer++;
718           c = get_symbol_name (&reloc_name);
719           len = input_line_pointer - reloc_name;
720           if (len == 0)
721             {
722               as_bad (_("No relocation operand"));
723               goto err;
724             }
725
726           /* Go through known relocation and try to find a match.  */
727           r = &arc_reloc_op[0];
728           for (i = arc_num_reloc_op - 1; i >= 0; i--, r++)
729             if (len == r->length
730                 && memcmp (reloc_name, r->name, len) == 0)
731               break;
732           if (i < 0)
733             {
734               as_bad (_("Unknown relocation operand: @%s"), reloc_name);
735               goto err;
736             }
737
738           *input_line_pointer = c;
739           SKIP_WHITESPACE_AFTER_NAME ();
740           /* Extra check for TLS: base.  */
741           if (*input_line_pointer == '@')
742             {
743               symbolS *base;
744               if (tok->X_op_symbol != NULL
745                   || tok->X_op != O_symbol)
746                 {
747                   as_bad (_("Unable to parse TLS base: %s"),
748                           input_line_pointer);
749                   goto err;
750                 }
751               input_line_pointer++;
752               char *sym_name;
753               c = get_symbol_name (&sym_name);
754               base = symbol_find_or_make (sym_name);
755               tok->X_op = O_subtract;
756               tok->X_op_symbol = base;
757               restore_line_pointer (c);
758               tmpE.X_add_number = 0;
759             }
760           else if ((*input_line_pointer != '+')
761                    && (*input_line_pointer != '-'))
762             {
763               tmpE.X_add_number = 0;
764             }
765           else
766             {
767               /* Parse the constant of a complex relocation expression
768                  like @identifier@reloc +/- const.  */
769               if (! r->complex_expr)
770                 {
771                   as_bad (_("@%s is not a complex relocation."), r->name);
772                   goto err;
773                 }
774               expression (&tmpE);
775               if (tmpE.X_op != O_constant)
776                 {
777                   as_bad (_("Bad expression: @%s + %s."),
778                           r->name, input_line_pointer);
779                   goto err;
780                 }
781             }
782
783           tok->X_md = r->op;
784           tok->X_add_number = tmpE.X_add_number;
785
786           debug_exp (tok);
787
788           saw_comma = FALSE;
789           saw_arg = TRUE;
790           tok++;
791           num_args++;
792           break;
793
794         case '%':
795           /* Can be a register.  */
796           ++input_line_pointer;
797           /* Fall through.  */
798         default:
799
800           if (saw_arg && !saw_comma)
801             goto err;
802
803           tok->X_op = O_absent;
804           tok->X_md = O_absent;
805           expression (tok);
806
807           /* Legacy: There are cases when we have
808              identifier@relocation_type, if it is the case parse the
809              relocation type as well.  */
810           if (*input_line_pointer == '@')
811             goto relocationsym;
812
813         normalsymbol:
814           debug_exp (tok);
815
816           if (tok->X_op == O_illegal || tok->X_op == O_absent)
817             goto err;
818
819           saw_comma = FALSE;
820           saw_arg = TRUE;
821           tok++;
822           num_args++;
823           break;
824         }
825     }
826
827  fini:
828   if (saw_comma || brk_lvl)
829     goto err;
830   input_line_pointer = old_input_line_pointer;
831
832   return num_args;
833
834  err:
835   if (brk_lvl)
836     as_bad (_("Brackets in operand field incorrect"));
837   else if (saw_comma)
838     as_bad (_("extra comma"));
839   else if (!saw_arg)
840     as_bad (_("missing argument"));
841   else
842     as_bad (_("missing comma or colon"));
843   input_line_pointer = old_input_line_pointer;
844   return -1;
845 }
846
847 /* Parse the flags to a structure.  */
848
849 static int
850 tokenize_flags (const char *str,
851                 struct arc_flags flags[],
852                 int nflg)
853 {
854   char *old_input_line_pointer;
855   bfd_boolean saw_flg = FALSE;
856   bfd_boolean saw_dot = FALSE;
857   int num_flags  = 0;
858   size_t flgnamelen;
859
860   memset (flags, 0, sizeof (*flags) * nflg);
861
862   /* Save and restore input_line_pointer around this function.  */
863   old_input_line_pointer = input_line_pointer;
864   input_line_pointer = (char *) str;
865
866   while (*input_line_pointer)
867     {
868       switch (*input_line_pointer)
869         {
870         case ' ':
871         case '\0':
872           goto fini;
873
874         case '.':
875           input_line_pointer++;
876           if (saw_dot)
877             goto err;
878           saw_dot = TRUE;
879           saw_flg = FALSE;
880           break;
881
882         default:
883           if (saw_flg && !saw_dot)
884             goto err;
885
886           if (num_flags >= nflg)
887             goto err;
888
889           flgnamelen = strspn (input_line_pointer, "abcdefghilmnopqrstvwxz");
890           if (flgnamelen > MAX_FLAG_NAME_LENGHT)
891             goto err;
892
893           memcpy (flags->name, input_line_pointer, flgnamelen);
894
895           input_line_pointer += flgnamelen;
896           flags++;
897           saw_dot = FALSE;
898           saw_flg = TRUE;
899           num_flags++;
900           break;
901         }
902     }
903
904  fini:
905   input_line_pointer = old_input_line_pointer;
906   return num_flags;
907
908  err:
909   if (saw_dot)
910     as_bad (_("extra dot"));
911   else if (!saw_flg)
912     as_bad (_("unrecognized flag"));
913   else
914     as_bad (_("failed to parse flags"));
915   input_line_pointer = old_input_line_pointer;
916   return -1;
917 }
918
919 /* The public interface to the instruction assembler.  */
920
921 void
922 md_assemble (char *str)
923 {
924   char *opname;
925   expressionS tok[MAX_INSN_ARGS];
926   int ntok, nflg;
927   size_t opnamelen;
928   struct arc_flags flags[MAX_INSN_FLGS];
929
930   /* Split off the opcode.  */
931   opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_0123468");
932   opname = xmalloc (opnamelen + 1);
933   memcpy (opname, str, opnamelen);
934   opname[opnamelen] = '\0';
935
936   /* Signalize we are assmbling the instructions.  */
937   assembling_insn = TRUE;
938
939   /* Tokenize the flags.  */
940   if ((nflg = tokenize_flags (str + opnamelen, flags, MAX_INSN_FLGS)) == -1)
941     {
942       as_bad (_("syntax error"));
943       return;
944     }
945
946   /* Scan up to the end of the mnemonic which must end in space or end
947      of string.  */
948   str += opnamelen;
949   for (; *str != '\0'; str++)
950     if (*str == ' ')
951       break;
952
953   /* Tokenize the rest of the line.  */
954   if ((ntok = tokenize_arguments (str, tok, MAX_INSN_ARGS)) < 0)
955     {
956       as_bad (_("syntax error"));
957       return;
958     }
959
960   /* Finish it off.  */
961   assemble_tokens (opname, tok, ntok, flags, nflg);
962   assembling_insn = FALSE;
963 }
964
965 /* Callback to insert a register into the hash table.  */
966
967 static void
968 declare_register (char *name, int number)
969 {
970   const char *err;
971   symbolS *regS = symbol_create (name, reg_section,
972                                  number, &zero_address_frag);
973
974   err = hash_insert (arc_reg_hash, S_GET_NAME (regS), (void *) regS);
975   if (err)
976     as_fatal ("Inserting \"%s\" into register table failed: %s",
977               name, err);
978 }
979
980 /* Construct symbols for each of the general registers.  */
981
982 static void
983 declare_register_set (void)
984 {
985   int i;
986   for (i = 0; i < 64; ++i)
987     {
988       char name[7];
989
990       sprintf (name, "r%d", i);
991       declare_register (name, i);
992       if ((i & 0x01) == 0)
993         {
994           sprintf (name, "r%dr%d", i, i+1);
995           declare_register (name, i);
996         }
997     }
998 }
999
1000 /* Port-specific assembler initialization.  This function is called
1001    once, at assembler startup time.  */
1002
1003 void
1004 md_begin (void)
1005 {
1006   unsigned int i;
1007
1008   /* The endianness can be chosen "at the factory".  */
1009   target_big_endian = byte_order == BIG_ENDIAN;
1010
1011   if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, arc_mach_type))
1012     as_warn (_("could not set architecture and machine"));
1013
1014   /* Set elf header flags.  */
1015   bfd_set_private_flags (stdoutput, arc_eflag);
1016
1017   /* Set up a hash table for the instructions.  */
1018   arc_opcode_hash = hash_new ();
1019   if (arc_opcode_hash == NULL)
1020     as_fatal (_("Virtual memory exhausted"));
1021
1022   /* Initialize the hash table with the insns.  */
1023   for (i = 0; i < arc_num_opcodes;)
1024     {
1025       const char *name, *retval;
1026
1027       name = arc_opcodes[i].name;
1028       retval = hash_insert (arc_opcode_hash, name, (void *) &arc_opcodes[i]);
1029       if (retval)
1030         as_fatal (_("internal error: can't hash opcode '%s': %s"),
1031                   name, retval);
1032
1033       while (++i < arc_num_opcodes
1034              && (arc_opcodes[i].name == name
1035                  || !strcmp (arc_opcodes[i].name, name)))
1036         continue;
1037     }
1038
1039   /* Register declaration.  */
1040   arc_reg_hash = hash_new ();
1041   if (arc_reg_hash == NULL)
1042     as_fatal (_("Virtual memory exhausted"));
1043
1044   declare_register_set ();
1045   declare_register ("gp", 26);
1046   declare_register ("fp", 27);
1047   declare_register ("sp", 28);
1048   declare_register ("ilink", 29);
1049   declare_register ("ilink1", 29);
1050   declare_register ("ilink2", 30);
1051   declare_register ("blink", 31);
1052
1053   declare_register ("mlo", 57);
1054   declare_register ("mmid", 58);
1055   declare_register ("mhi", 59);
1056
1057   declare_register ("acc1", 56);
1058   declare_register ("acc2", 57);
1059
1060   declare_register ("lp_count", 60);
1061   declare_register ("pcl", 63);
1062
1063   /* Initialize the last instructions.  */
1064   memset (&arc_last_insns[0], 0, sizeof (arc_last_insns));
1065 }
1066
1067 /* Write a value out to the object file, using the appropriate
1068    endianness.  */
1069
1070 void
1071 md_number_to_chars (char *buf,
1072                     valueT val,
1073                     int n)
1074 {
1075   if (target_big_endian)
1076     number_to_chars_bigendian (buf, val, n);
1077   else
1078     number_to_chars_littleendian (buf, val, n);
1079 }
1080
1081 /* Round up a section size to the appropriate boundary.  */
1082
1083 valueT
1084 md_section_align (segT segment,
1085                   valueT size)
1086 {
1087   int align = bfd_get_section_alignment (stdoutput, segment);
1088
1089   return ((size + (1 << align) - 1) & (-((valueT) 1 << align)));
1090 }
1091
1092 /* The location from which a PC relative jump should be calculated,
1093    given a PC relative reloc.  */
1094
1095 long
1096 md_pcrel_from_section (fixS *fixP,
1097                        segT sec)
1098 {
1099   offsetT base = fixP->fx_where + fixP->fx_frag->fr_address;
1100
1101   pr_debug ("pcrel_from_section, fx_offset = %d\n", (int) fixP->fx_offset);
1102
1103   if (fixP->fx_addsy != (symbolS *) NULL
1104       && (!S_IS_DEFINED (fixP->fx_addsy)
1105           || S_GET_SEGMENT (fixP->fx_addsy) != sec))
1106     {
1107       pr_debug ("Unknown pcrel symbol: %s\n", S_GET_NAME (fixP->fx_addsy));
1108
1109       /* The symbol is undefined (or is defined but not in this section).
1110          Let the linker figure it out.  */
1111       return 0;
1112     }
1113
1114   if ((int) fixP->fx_r_type < 0)
1115     {
1116       /* These are the "internal" relocations.  Align them to
1117          32 bit boundary (PCL), for the moment.  */
1118       base &= ~3;
1119     }
1120   else
1121     {
1122       switch (fixP->fx_r_type)
1123         {
1124         case BFD_RELOC_ARC_PC32:
1125           /* The hardware calculates relative to the start of the
1126              insn, but this relocation is relative to location of the
1127              LIMM, compensate.  The base always needs to be
1128              substracted by 4 as we do not support this type of PCrel
1129              relocation for short instructions.  */
1130           base -= 4;
1131           /* Fall through.  */
1132         case BFD_RELOC_ARC_PLT32:
1133         case BFD_RELOC_ARC_S25H_PCREL_PLT:
1134         case BFD_RELOC_ARC_S21H_PCREL_PLT:
1135         case BFD_RELOC_ARC_S25W_PCREL_PLT:
1136         case BFD_RELOC_ARC_S21W_PCREL_PLT:
1137
1138         case BFD_RELOC_ARC_S21H_PCREL:
1139         case BFD_RELOC_ARC_S25H_PCREL:
1140         case BFD_RELOC_ARC_S13_PCREL:
1141         case BFD_RELOC_ARC_S21W_PCREL:
1142         case BFD_RELOC_ARC_S25W_PCREL:
1143           base &= ~3;
1144           break;
1145         default:
1146           as_bad_where (fixP->fx_file, fixP->fx_line,
1147                         _("unhandled reloc %s in md_pcrel_from_section"),
1148                   bfd_get_reloc_code_name (fixP->fx_r_type));
1149           break;
1150         }
1151     }
1152
1153   pr_debug ("pcrel from %x + %lx = %x, symbol: %s (%x)\n",
1154             fixP->fx_frag->fr_address, fixP->fx_where, base,
1155             fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "(null)",
1156             fixP->fx_addsy ? S_GET_VALUE (fixP->fx_addsy) : 0);
1157
1158   return base;
1159 }
1160
1161 /* Given a BFD relocation find the coresponding operand.  */
1162
1163 static const struct arc_operand *
1164 find_operand_for_reloc (extended_bfd_reloc_code_real_type reloc)
1165 {
1166   unsigned i;
1167
1168   for (i = 0; i < arc_num_operands; i++)
1169     if (arc_operands[i].default_reloc == reloc)
1170       return  &arc_operands[i];
1171   return NULL;
1172 }
1173
1174 /* Apply a fixup to the object code.  At this point all symbol values
1175    should be fully resolved, and we attempt to completely resolve the
1176    reloc.  If we can not do that, we determine the correct reloc code
1177    and put it back in the fixup.  To indicate that a fixup has been
1178    eliminated, set fixP->fx_done.  */
1179
1180 void
1181 md_apply_fix (fixS *fixP,
1182               valueT *valP,
1183               segT seg)
1184 {
1185   char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
1186   valueT value = *valP;
1187   unsigned insn = 0;
1188   symbolS *fx_addsy, *fx_subsy;
1189   offsetT fx_offset;
1190   segT add_symbol_segment = absolute_section;
1191   segT sub_symbol_segment = absolute_section;
1192   const struct arc_operand *operand = NULL;
1193   extended_bfd_reloc_code_real_type reloc;
1194
1195   pr_debug ("%s:%u: apply_fix: r_type=%d (%s) value=0x%lX offset=0x%lX\n",
1196             fixP->fx_file, fixP->fx_line, fixP->fx_r_type,
1197             ((int) fixP->fx_r_type < 0) ? "Internal":
1198             bfd_get_reloc_code_name (fixP->fx_r_type), value,
1199             fixP->fx_offset);
1200
1201   fx_addsy = fixP->fx_addsy;
1202   fx_subsy = fixP->fx_subsy;
1203   fx_offset = 0;
1204
1205   if (fx_addsy)
1206     {
1207       add_symbol_segment = S_GET_SEGMENT (fx_addsy);
1208     }
1209
1210   if (fx_subsy
1211       && fixP->fx_r_type != BFD_RELOC_ARC_TLS_DTPOFF
1212       && fixP->fx_r_type != BFD_RELOC_ARC_TLS_DTPOFF_S9
1213       && fixP->fx_r_type != BFD_RELOC_ARC_TLS_GD_LD)
1214     {
1215       resolve_symbol_value (fx_subsy);
1216       sub_symbol_segment = S_GET_SEGMENT (fx_subsy);
1217
1218       if (sub_symbol_segment == absolute_section)
1219         {
1220           /* The symbol is really a constant.  */
1221           fx_offset -= S_GET_VALUE (fx_subsy);
1222           fx_subsy = NULL;
1223         }
1224       else
1225         {
1226           as_bad_where (fixP->fx_file, fixP->fx_line,
1227                         _("can't resolve `%s' {%s section} - `%s' {%s section}"),
1228                         fx_addsy ? S_GET_NAME (fx_addsy) : "0",
1229                         segment_name (add_symbol_segment),
1230                         S_GET_NAME (fx_subsy),
1231                         segment_name (sub_symbol_segment));
1232           return;
1233         }
1234     }
1235
1236   if (fx_addsy
1237       && !S_IS_WEAK (fx_addsy))
1238     {
1239       if (add_symbol_segment == seg
1240           && fixP->fx_pcrel)
1241         {
1242           value += S_GET_VALUE (fx_addsy);
1243           value -= md_pcrel_from_section (fixP, seg);
1244           fx_addsy = NULL;
1245           fixP->fx_pcrel = FALSE;
1246         }
1247       else if (add_symbol_segment == absolute_section)
1248         {
1249           value = fixP->fx_offset;
1250           fx_offset += S_GET_VALUE (fixP->fx_addsy);
1251           fx_addsy = NULL;
1252           fixP->fx_pcrel = FALSE;
1253         }
1254     }
1255
1256   if (!fx_addsy)
1257     fixP->fx_done = TRUE;
1258
1259   if (fixP->fx_pcrel)
1260     {
1261       if (fx_addsy
1262           && ((S_IS_DEFINED (fx_addsy)
1263                && S_GET_SEGMENT (fx_addsy) != seg)
1264               || S_IS_WEAK (fx_addsy)))
1265         value += md_pcrel_from_section (fixP, seg);
1266
1267       switch (fixP->fx_r_type)
1268         {
1269         case BFD_RELOC_ARC_32_ME:
1270           /* This is a pc-relative value in a LIMM.  Adjust it to the
1271              address of the instruction not to the address of the
1272              LIMM.  Note: it is not anylonger valid this afirmation as
1273              the linker consider ARC_PC32 a fixup to entire 64 bit
1274              insn.  */
1275           fixP->fx_offset += fixP->fx_frag->fr_address;
1276           /* Fall through.  */
1277         case BFD_RELOC_32:
1278           fixP->fx_r_type = BFD_RELOC_ARC_PC32;
1279           /* Fall through.  */
1280         case BFD_RELOC_ARC_PC32:
1281           /* fixP->fx_offset += fixP->fx_where - fixP->fx_dot_value; */
1282           break;
1283         default:
1284           if ((int) fixP->fx_r_type < 0)
1285             as_fatal (_("PC relative relocation not allowed for (internal) type %d"),
1286                       fixP->fx_r_type);
1287           break;
1288         }
1289     }
1290
1291   pr_debug ("%s:%u: apply_fix: r_type=%d (%s) value=0x%lX offset=0x%lX\n",
1292             fixP->fx_file, fixP->fx_line, fixP->fx_r_type,
1293             ((int) fixP->fx_r_type < 0) ? "Internal":
1294             bfd_get_reloc_code_name (fixP->fx_r_type), value,
1295             fixP->fx_offset);
1296
1297
1298   /* Now check for TLS relocations.  */
1299   reloc = fixP->fx_r_type;
1300   switch (reloc)
1301     {
1302     case BFD_RELOC_ARC_TLS_DTPOFF:
1303     case BFD_RELOC_ARC_TLS_LE_32:
1304       fixP->fx_offset = 0;
1305       /* Fall through.  */
1306     case BFD_RELOC_ARC_TLS_GD_GOT:
1307     case BFD_RELOC_ARC_TLS_IE_GOT:
1308       S_SET_THREAD_LOCAL (fixP->fx_addsy);
1309       break;
1310
1311     case BFD_RELOC_ARC_TLS_GD_LD:
1312       gas_assert (!fixP->fx_offset);
1313       if (fixP->fx_subsy)
1314         fixP->fx_offset
1315           = (S_GET_VALUE (fixP->fx_subsy)
1316              - fixP->fx_frag->fr_address- fixP->fx_where);
1317       fixP->fx_subsy = NULL;
1318       /* Fall through.  */
1319     case BFD_RELOC_ARC_TLS_GD_CALL:
1320       /* These two relocs are there just to allow ld to change the tls
1321          model for this symbol, by patching the code.  The offset -
1322          and scale, if any - will be installed by the linker.  */
1323       S_SET_THREAD_LOCAL (fixP->fx_addsy);
1324       break;
1325
1326     case BFD_RELOC_ARC_TLS_LE_S9:
1327     case BFD_RELOC_ARC_TLS_DTPOFF_S9:
1328       as_bad (_("TLS_*_S9 relocs are not supported yet"));
1329       break;
1330
1331     default:
1332       break;
1333     }
1334
1335   if (!fixP->fx_done)
1336     {
1337       return;
1338     }
1339
1340   /* Addjust the value if we have a constant.  */
1341   value += fx_offset;
1342
1343   /* For hosts with longs bigger than 32-bits make sure that the top
1344      bits of a 32-bit negative value read in by the parser are set,
1345      so that the correct comparisons are made.  */
1346   if (value & 0x80000000)
1347     value |= (-1L << 31);
1348
1349   reloc = fixP->fx_r_type;
1350   switch (reloc)
1351     {
1352     case BFD_RELOC_8:
1353     case BFD_RELOC_16:
1354     case BFD_RELOC_24:
1355     case BFD_RELOC_32:
1356     case BFD_RELOC_64:
1357     case BFD_RELOC_ARC_32_PCREL:
1358       md_number_to_chars (fixpos, value, fixP->fx_size);
1359       return;
1360
1361     case BFD_RELOC_ARC_GOTPC32:
1362       /* I cannot fix an GOTPC relocation because I need to relax it
1363          from ld rx,[pcl,@sym@gotpc] to add rx,pcl,@sym@gotpc.  */
1364       as_bad (_("Unsupported operation on reloc"));
1365       return;
1366     case BFD_RELOC_ARC_GOTOFF:
1367     case BFD_RELOC_ARC_32_ME:
1368     case BFD_RELOC_ARC_PC32:
1369       md_number_to_chars_midend (fixpos, value, fixP->fx_size);
1370       return;
1371
1372     case BFD_RELOC_ARC_PLT32:
1373       md_number_to_chars_midend (fixpos, value, fixP->fx_size);
1374       return;
1375
1376     case BFD_RELOC_ARC_S25H_PCREL_PLT:
1377       reloc = BFD_RELOC_ARC_S25W_PCREL;
1378       goto solve_plt;
1379
1380     case BFD_RELOC_ARC_S21H_PCREL_PLT:
1381       reloc = BFD_RELOC_ARC_S21H_PCREL;
1382       goto solve_plt;
1383
1384     case BFD_RELOC_ARC_S25W_PCREL_PLT:
1385       reloc = BFD_RELOC_ARC_S25W_PCREL;
1386       goto solve_plt;
1387
1388     case BFD_RELOC_ARC_S21W_PCREL_PLT:
1389       reloc = BFD_RELOC_ARC_S21W_PCREL;
1390
1391     case BFD_RELOC_ARC_S25W_PCREL:
1392     case BFD_RELOC_ARC_S21W_PCREL:
1393     case BFD_RELOC_ARC_S21H_PCREL:
1394     case BFD_RELOC_ARC_S25H_PCREL:
1395     case BFD_RELOC_ARC_S13_PCREL:
1396     solve_plt:
1397       operand = find_operand_for_reloc (reloc);
1398       gas_assert (operand);
1399       break;
1400
1401     default:
1402       {
1403         if ((int) fixP->fx_r_type >= 0)
1404           as_fatal (_("unhandled relocation type %s"),
1405                     bfd_get_reloc_code_name (fixP->fx_r_type));
1406
1407         /* The rest of these fixups needs to be completely resolved as
1408            constants.  */
1409         if (fixP->fx_addsy != 0
1410             && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
1411           as_bad_where (fixP->fx_file, fixP->fx_line,
1412                         _("non-absolute expression in constant field"));
1413
1414         gas_assert (-(int) fixP->fx_r_type < (int) arc_num_operands);
1415         operand = &arc_operands[-(int) fixP->fx_r_type];
1416         break;
1417       }
1418     }
1419
1420   if (target_big_endian)
1421     {
1422       switch (fixP->fx_size)
1423         {
1424         case 4:
1425           insn = bfd_getb32 (fixpos);
1426           break;
1427         case 2:
1428           insn = bfd_getb16 (fixpos);
1429           break;
1430         default:
1431           as_bad_where (fixP->fx_file, fixP->fx_line,
1432                         _("unknown fixup size"));
1433         }
1434     }
1435   else
1436     {
1437       insn = 0;
1438       switch (fixP->fx_size)
1439         {
1440         case 4:
1441           insn = bfd_getl16 (fixpos) << 16 | bfd_getl16 (fixpos + 2);
1442           break;
1443         case 2:
1444           insn = bfd_getl16 (fixpos);
1445           break;
1446         default:
1447           as_bad_where (fixP->fx_file, fixP->fx_line,
1448                         _("unknown fixup size"));
1449         }
1450     }
1451
1452   insn = insert_operand (insn, operand, (offsetT) value,
1453                          fixP->fx_file, fixP->fx_line);
1454
1455   md_number_to_chars_midend (fixpos, insn, fixP->fx_size);
1456 }
1457
1458 /* Prepare machine-dependent frags for relaxation.
1459
1460    Called just before relaxation starts.  Any symbol that is now undefined
1461    will not become defined.
1462
1463    Return the correct fr_subtype in the frag.
1464
1465    Return the initial "guess for fr_var" to caller.  The guess for fr_var
1466    is *actually* the growth beyond fr_fix.  Whatever we do to grow fr_fix
1467    or fr_var contributes to our returned value.
1468
1469    Although it may not be explicit in the frag, pretend
1470    fr_var starts with a value.  */
1471
1472 int
1473 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
1474                                segT segment ATTRIBUTE_UNUSED)
1475 {
1476   int growth = 4;
1477
1478   fragP->fr_var = 4;
1479   pr_debug ("%s:%d: md_estimate_size_before_relax: %d\n",
1480            fragP->fr_file, fragP->fr_line, growth);
1481
1482   as_fatal (_("md_estimate_size_before_relax\n"));
1483   return growth;
1484 }
1485
1486 /* Translate internal representation of relocation info to BFD target
1487    format.  */
1488
1489 arelent *
1490 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
1491               fixS *fixP)
1492 {
1493   arelent *reloc;
1494   bfd_reloc_code_real_type code;
1495
1496   reloc = (arelent *) xmalloc (sizeof (* reloc));
1497   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1498   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
1499   reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
1500
1501   /* Make sure none of our internal relocations make it this far.
1502      They'd better have been fully resolved by this point.  */
1503   gas_assert ((int) fixP->fx_r_type > 0);
1504
1505   code = fixP->fx_r_type;
1506
1507   /* if we have something like add gp, pcl,
1508      _GLOBAL_OFFSET_TABLE_@gotpc.  */
1509   if (code == BFD_RELOC_ARC_GOTPC32
1510       && GOT_symbol
1511       && fixP->fx_addsy == GOT_symbol)
1512     code = BFD_RELOC_ARC_GOTPC;
1513
1514   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
1515   if (reloc->howto == NULL)
1516     {
1517       as_bad_where (fixP->fx_file, fixP->fx_line,
1518                     _("cannot represent `%s' relocation in object file"),
1519                     bfd_get_reloc_code_name (code));
1520       return NULL;
1521     }
1522
1523   if (!fixP->fx_pcrel != !reloc->howto->pc_relative)
1524     as_fatal (_("internal error? cannot generate `%s' relocation"),
1525               bfd_get_reloc_code_name (code));
1526
1527   gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
1528
1529   if (code == BFD_RELOC_ARC_TLS_DTPOFF
1530       || code ==  BFD_RELOC_ARC_TLS_DTPOFF_S9)
1531     {
1532       asymbol *sym
1533         = fixP->fx_subsy ? symbol_get_bfdsym (fixP->fx_subsy) : NULL;
1534       /* We just want to store a 24 bit index, but we have to wait
1535          till after write_contents has been called via
1536          bfd_map_over_sections before we can get the index from
1537          _bfd_elf_symbol_from_bfd_symbol.  Thus, the write_relocs
1538          function is elf32-arc.c has to pick up the slack.
1539          Unfortunately, this leads to problems with hosts that have
1540          pointers wider than long (bfd_vma).  There would be various
1541          ways to handle this, all error-prone :-(  */
1542       reloc->addend = (bfd_vma) sym;
1543       if ((asymbol *) reloc->addend != sym)
1544         {
1545           as_bad ("Can't store pointer\n");
1546           return NULL;
1547         }
1548     }
1549   else
1550     reloc->addend = fixP->fx_offset;
1551
1552   return reloc;
1553 }
1554
1555 /* Perform post-processing of machine-dependent frags after relaxation.
1556    Called after relaxation is finished.
1557    In:  Address of frag.
1558    fr_type == rs_machine_dependent.
1559    fr_subtype is what the address relaxed to.
1560
1561    Out: Any fixS:s and constants are set up.  */
1562
1563 void
1564 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
1565                  segT segment ATTRIBUTE_UNUSED,
1566                  fragS *fragP ATTRIBUTE_UNUSED)
1567 {
1568   pr_debug ("%s:%d: md_convert_frag, subtype: %d, fix: %d, var: %d\n",
1569             fragP->fr_file, fragP->fr_line,
1570             fragP->fr_subtype, fragP->fr_fix, fragP->fr_var);
1571   abort ();
1572 }
1573
1574 /* We have no need to default values of symbols.  We could catch
1575    register names here, but that is handled by inserting them all in
1576    the symbol table to begin with.  */
1577
1578 symbolS *
1579 md_undefined_symbol (char *name)
1580 {
1581   /* The arc abi demands that a GOT[0] should be referencible as
1582      [pc+_DYNAMIC@gotpc].  Hence we convert a _DYNAMIC@gotpc to a
1583      GOTPC reference to _GLOBAL_OFFSET_TABLE_.  */
1584   if (((*name == '_')
1585        && (*(name+1) == 'G')
1586        && (strcmp (name, GLOBAL_OFFSET_TABLE_NAME) == 0))
1587       || ((*name == '_')
1588           && (*(name+1) == 'D')
1589           && (strcmp (name, DYNAMIC_STRUCT_NAME) == 0)))
1590     {
1591       if (!GOT_symbol)
1592         {
1593           if (symbol_find (name))
1594             as_bad ("GOT already in symbol table");
1595
1596           GOT_symbol = symbol_new (GLOBAL_OFFSET_TABLE_NAME, undefined_section,
1597                                    (valueT) 0, &zero_address_frag);
1598         };
1599       return GOT_symbol;
1600     }
1601   return NULL;
1602 }
1603
1604 /* Turn a string in input_line_pointer into a floating point constant
1605    of type type, and store the appropriate bytes in *litP.  The number
1606    of LITTLENUMS emitted is stored in *sizeP.  An error message is
1607    returned, or NULL on OK.  */
1608
1609 char *
1610 md_atof (int type, char *litP, int *sizeP)
1611 {
1612   return ieee_md_atof (type, litP, sizeP, target_big_endian);
1613 }
1614
1615 /* Called for any expression that can not be recognized.  When the
1616    function is called, `input_line_pointer' will point to the start of
1617    the expression.  */
1618
1619 void
1620 md_operand (expressionS *expressionP ATTRIBUTE_UNUSED)
1621 {
1622   char *p = input_line_pointer;
1623   if (*p == '@')
1624     {
1625       input_line_pointer++;
1626       expressionP->X_op = O_symbol;
1627       expression (expressionP);
1628     }
1629 }
1630
1631 /* This function is called from the function 'expression', it attempts
1632    to parse special names (in our case register names).  It fills in
1633    the expression with the identified register.  It returns TRUE if
1634    it is a register and FALSE otherwise.  */
1635
1636 bfd_boolean
1637 arc_parse_name (const char *name,
1638                 struct expressionS *e)
1639 {
1640   struct symbol *sym;
1641
1642   if (!assembling_insn)
1643     return FALSE;
1644
1645   /* Handle only registers.  */
1646   if (e->X_op != O_absent)
1647     return FALSE;
1648
1649   sym = hash_find (arc_reg_hash, name);
1650   if (sym)
1651     {
1652       e->X_op = O_register;
1653       e->X_add_number = S_GET_VALUE (sym);
1654       return TRUE;
1655     }
1656   return FALSE;
1657 }
1658
1659 /* md_parse_option
1660    Invocation line includes a switch not recognized by the base assembler.
1661    See if it's a processor-specific option.
1662
1663    New options (supported) are:
1664
1665    -mcpu=<cpu name>              Assemble for selected processor
1666    -EB/-mbig-endian              Big-endian
1667    -EL/-mlittle-endian           Little-endian
1668
1669    The following CPU names are recognized:
1670    arc700, av2em, av2hs.  */
1671
1672 int
1673 md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
1674 {
1675   int cpu_flags = EF_ARC_CPU_GENERIC;
1676
1677   switch (c)
1678     {
1679     case OPTION_ARC600:
1680     case OPTION_ARC601:
1681       return md_parse_option (OPTION_MCPU, "arc600");
1682
1683     case OPTION_ARC700:
1684       return md_parse_option (OPTION_MCPU, "arc700");
1685
1686     case OPTION_ARCEM:
1687       return md_parse_option (OPTION_MCPU, "arcem");
1688
1689     case OPTION_ARCHS:
1690       return md_parse_option (OPTION_MCPU, "archs");
1691
1692     case OPTION_MCPU:
1693       {
1694         int i;
1695         char *s = alloca (strlen (arg) + 1);
1696
1697         {
1698           char *t = s;
1699           char *arg1 = arg;
1700
1701           do
1702             *t = TOLOWER (*arg1++);
1703           while (*t++);
1704         }
1705
1706         for (i = 0; cpu_types[i].name; ++i)
1707           {
1708             if (!strcmp (cpu_types[i].name, s))
1709               {
1710                 arc_target      = cpu_types[i].flags;
1711                 arc_target_name = cpu_types[i].name;
1712                 arc_features    = cpu_types[i].features;
1713                 arc_mach_type   = cpu_types[i].mach;
1714                 cpu_flags       = cpu_types[i].eflags;
1715
1716                 mach_type_specified_p = 1;
1717                 break;
1718               }
1719           }
1720
1721         if (!cpu_types[i].name)
1722           {
1723             as_fatal (_("unknown architecture: %s\n"), arg);
1724           }
1725         break;
1726       }
1727
1728     case OPTION_EB:
1729       arc_target_format = "elf32-bigarc";
1730       byte_order = BIG_ENDIAN;
1731       break;
1732
1733     case OPTION_EL:
1734       arc_target_format = "elf32-littlearc";
1735       byte_order = LITTLE_ENDIAN;
1736       break;
1737
1738     case OPTION_CD:
1739       /* This option has an effect only on ARC EM.  */
1740       if (arc_target & ARC_OPCODE_ARCv2EM)
1741         arc_features |= ARC_CD;
1742       break;
1743
1744     case OPTION_USER_MODE:
1745     case OPTION_LD_EXT_MASK:
1746     case OPTION_SWAP:
1747     case OPTION_NORM:
1748     case OPTION_BARREL_SHIFT:
1749     case OPTION_MIN_MAX:
1750     case OPTION_NO_MPY:
1751     case OPTION_EA:
1752     case OPTION_MUL64:
1753     case OPTION_SIMD:
1754     case OPTION_SPFP:
1755     case OPTION_DPFP:
1756     case OPTION_XMAC_D16:
1757     case OPTION_XMAC_24:
1758     case OPTION_DSP_PACKA:
1759     case OPTION_CRC:
1760     case OPTION_DVBF:
1761     case OPTION_TELEPHONY:
1762     case OPTION_XYMEMORY:
1763     case OPTION_LOCK:
1764     case OPTION_SWAPE:
1765     case OPTION_RTSC:
1766     case OPTION_FPUDA:
1767       /* Dummy options.  */
1768
1769     default:
1770       return 0;
1771     }
1772
1773   if (cpu_flags != EF_ARC_CPU_GENERIC)
1774     arc_eflag = (arc_eflag & ~EF_ARC_MACH_MSK) | cpu_flags;
1775
1776   return 1;
1777 }
1778
1779 void
1780 md_show_usage (FILE *stream)
1781 {
1782   fprintf (stream, _("ARC-specific assembler options:\n"));
1783
1784   fprintf (stream, "  -mcpu=<cpu name>\t  assemble for CPU <cpu name>\n");
1785   fprintf (stream,
1786            "  -mcode-density\t  enable code density option for ARC EM\n");
1787
1788   fprintf (stream, _("\
1789   -EB                     assemble code for a big-endian cpu\n"));
1790   fprintf (stream, _("\
1791   -EL                     assemble code for a little-endian cpu\n"));
1792 }
1793
1794 static void
1795 preprocess_operands (const struct arc_opcode *opcode,
1796                      expressionS *tok,
1797                      int ntok)
1798 {
1799   int i;
1800   size_t len;
1801   const char *p;
1802   unsigned j;
1803   const struct arc_aux_reg *auxr;
1804
1805   for (i = 0; i < ntok; i++)
1806     {
1807       switch (tok[i].X_op)
1808         {
1809         case O_illegal:
1810         case O_absent:
1811           break; /* Throw and error.  */
1812
1813         case O_symbol:
1814           if (opcode->class != AUXREG)
1815             break;
1816           /* Convert the symbol to a constant if possible.  */
1817           p = S_GET_NAME (tok[i].X_add_symbol);
1818           len = strlen (p);
1819
1820           auxr = &arc_aux_regs[0];
1821           for (j = 0; j < arc_num_aux_regs; j++, auxr++)
1822             if (len == auxr->length
1823                 && strcasecmp (auxr->name, p) == 0)
1824               {
1825                 tok[i].X_op = O_constant;
1826                 tok[i].X_add_number = auxr->address;
1827                 break;
1828               }
1829           break;
1830         default:
1831           break;
1832         }
1833     }
1834 }
1835
1836 /* Given an opcode name, pre-tockenized set of argumenst and the
1837    opcode flags, take it all the way through emission.  */
1838
1839 static void
1840 assemble_tokens (const char *opname,
1841                  expressionS *tok,
1842                  int ntok,
1843                  struct arc_flags *pflags,
1844                  int nflgs)
1845 {
1846   bfd_boolean found_something = FALSE;
1847   const struct arc_opcode *opcode;
1848   int cpumatch = 1;
1849
1850   /* Search opcodes.  */
1851   opcode = (const struct arc_opcode *) hash_find (arc_opcode_hash, opname);
1852
1853   /* Couldn't find opcode conventional way, try special cases.  */
1854   if (!opcode)
1855     opcode = find_special_case (opname, &nflgs, pflags, tok, &ntok);
1856
1857   if (opcode)
1858     {
1859       pr_debug ("%s:%d: assemble_tokens: %s trying opcode 0x%08X\n",
1860                 frag_now->fr_file, frag_now->fr_line, opcode->name,
1861                 opcode->opcode);
1862
1863       preprocess_operands (opcode, tok, ntok);
1864
1865       found_something = TRUE;
1866       opcode = find_opcode_match (opcode, tok, &ntok, pflags, nflgs, &cpumatch);
1867       if (opcode)
1868         {
1869           struct arc_insn insn;
1870           assemble_insn (opcode, tok, ntok, pflags, nflgs, &insn);
1871           emit_insn (&insn);
1872           return;
1873         }
1874     }
1875
1876   if (found_something)
1877     {
1878       if (cpumatch)
1879         as_bad (_("inappropriate arguments for opcode '%s'"), opname);
1880       else
1881         as_bad (_("opcode '%s' not supported for target %s"), opname,
1882                 arc_target_name);
1883     }
1884   else
1885     as_bad (_("unknown opcode '%s'"), opname);
1886 }
1887
1888 /* Used to find special case opcode.  */
1889
1890 static const struct arc_opcode *
1891 find_special_case (const char *opname,
1892                    int *nflgs,
1893                    struct arc_flags *pflags,
1894                    expressionS *tok,
1895                    int *ntok)
1896 {
1897   const struct arc_opcode *opcode;
1898
1899   opcode = find_special_case_pseudo (opname, ntok, tok, nflgs, pflags);
1900
1901   if (opcode == NULL)
1902     opcode = find_special_case_flag (opname, nflgs, pflags);
1903
1904   return opcode;
1905 }
1906
1907 /* Swap operand tokens.  */
1908
1909 static void
1910 swap_operand (expressionS *operand_array,
1911               unsigned source,
1912               unsigned destination)
1913 {
1914   expressionS cpy_operand;
1915   expressionS *src_operand;
1916   expressionS *dst_operand;
1917   size_t size;
1918
1919   if (source == destination)
1920     return;
1921
1922   src_operand = &operand_array[source];
1923   dst_operand = &operand_array[destination];
1924   size = sizeof (expressionS);
1925
1926   /* Make copy of operand to swap with and swap.  */
1927   memcpy (&cpy_operand, dst_operand, size);
1928   memcpy (dst_operand, src_operand, size);
1929   memcpy (src_operand, &cpy_operand, size);
1930 }
1931
1932 /* Check if *op matches *tok type.
1933    Returns FALSE if they don't match, TRUE if they match.  */
1934
1935 static bfd_boolean
1936 pseudo_operand_match (const expressionS *tok,
1937                       const struct arc_operand_operation *op)
1938 {
1939   offsetT min, max, val;
1940   bfd_boolean ret;
1941   const struct arc_operand *operand_real = &arc_operands[op->operand_idx];
1942
1943   ret = FALSE;
1944   switch (tok->X_op)
1945     {
1946     case O_constant:
1947       if (operand_real->bits == 32 && (operand_real->flags & ARC_OPERAND_LIMM))
1948         ret = 1;
1949       else if (!(operand_real->flags & ARC_OPERAND_IR))
1950         {
1951           val = tok->X_add_number + op->count;
1952           if (operand_real->flags & ARC_OPERAND_SIGNED)
1953             {
1954               max = (1 << (operand_real->bits - 1)) - 1;
1955               min = -(1 << (operand_real->bits - 1));
1956             }
1957           else
1958             {
1959               max = (1 << operand_real->bits) - 1;
1960               min = 0;
1961             }
1962           if (min <= val && val <= max)
1963             ret = TRUE;
1964         }
1965       break;
1966
1967     case O_symbol:
1968       /* Handle all symbols as long immediates or signed 9.  */
1969       if (operand_real->flags & ARC_OPERAND_LIMM ||
1970           ((operand_real->flags & ARC_OPERAND_SIGNED) && operand_real->bits == 9))
1971         ret = TRUE;
1972       break;
1973
1974     case O_register:
1975       if (operand_real->flags & ARC_OPERAND_IR)
1976         ret = TRUE;
1977       break;
1978
1979     case O_bracket:
1980       if (operand_real->flags & ARC_OPERAND_BRAKET)
1981         ret = TRUE;
1982       break;
1983
1984     default:
1985       /* Unknown.  */
1986       break;
1987     }
1988   return ret;
1989 }
1990
1991 /* Find pseudo instruction in array.  */
1992
1993 static const struct arc_pseudo_insn *
1994 find_pseudo_insn (const char *opname,
1995                   int ntok,
1996                   const expressionS *tok)
1997 {
1998   const struct arc_pseudo_insn *pseudo_insn = NULL;
1999   const struct arc_operand_operation *op;
2000   unsigned int i;
2001   int j;
2002
2003   for (i = 0; i < arc_num_pseudo_insn; ++i)
2004     {
2005       pseudo_insn = &arc_pseudo_insns[i];
2006       if (strcmp (pseudo_insn->mnemonic_p, opname) == 0)
2007         {
2008           op = pseudo_insn->operand;
2009           for (j = 0; j < ntok; ++j)
2010             if (!pseudo_operand_match (&tok[j], &op[j]))
2011               break;
2012
2013           /* Found the right instruction.  */
2014           if (j == ntok)
2015             return pseudo_insn;
2016         }
2017     }
2018   return NULL;
2019 }
2020
2021 /* Assumes the expressionS *tok is of sufficient size.  */
2022
2023 static const struct arc_opcode *
2024 find_special_case_pseudo (const char *opname,
2025                           int *ntok,
2026                           expressionS *tok,
2027                           int *nflgs,
2028                           struct arc_flags *pflags)
2029 {
2030   const struct arc_pseudo_insn *pseudo_insn = NULL;
2031   const struct arc_operand_operation *operand_pseudo;
2032   const struct arc_operand *operand_real;
2033   unsigned i;
2034   char construct_operand[MAX_CONSTR_STR];
2035
2036   /* Find whether opname is in pseudo instruction array.  */
2037   pseudo_insn = find_pseudo_insn (opname, *ntok, tok);
2038
2039   if (pseudo_insn == NULL)
2040     return NULL;
2041
2042   /* Handle flag, Limited to one flag at the moment.  */
2043   if (pseudo_insn->flag_r != NULL)
2044     *nflgs += tokenize_flags (pseudo_insn->flag_r, &pflags[*nflgs],
2045                               MAX_INSN_FLGS - *nflgs);
2046
2047   /* Handle operand operations.  */
2048   for (i = 0; i < pseudo_insn->operand_cnt; ++i)
2049     {
2050       operand_pseudo = &pseudo_insn->operand[i];
2051       operand_real = &arc_operands[operand_pseudo->operand_idx];
2052
2053       if (operand_real->flags & ARC_OPERAND_BRAKET &&
2054           !operand_pseudo->needs_insert)
2055         continue;
2056
2057       /* Has to be inserted (i.e. this token does not exist yet).  */
2058       if (operand_pseudo->needs_insert)
2059         {
2060           if (operand_real->flags & ARC_OPERAND_BRAKET)
2061             {
2062               tok[i].X_op = O_bracket;
2063               ++(*ntok);
2064               continue;
2065             }
2066
2067           /* Check if operand is a register or constant and handle it
2068              by type.  */
2069           if (operand_real->flags & ARC_OPERAND_IR)
2070             snprintf (construct_operand, MAX_CONSTR_STR, "r%d",
2071                       operand_pseudo->count);
2072           else
2073             snprintf (construct_operand, MAX_CONSTR_STR, "%d",
2074                       operand_pseudo->count);
2075
2076           tokenize_arguments (construct_operand, &tok[i], 1);
2077           ++(*ntok);
2078         }
2079
2080       else if (operand_pseudo->count)
2081         {
2082           /* Operand number has to be adjusted accordingly (by operand
2083              type).  */
2084           switch (tok[i].X_op)
2085             {
2086             case O_constant:
2087               tok[i].X_add_number += operand_pseudo->count;
2088               break;
2089
2090             case O_symbol:
2091               break;
2092
2093             default:
2094               /* Ignored.  */
2095               break;
2096             }
2097         }
2098     }
2099
2100   /* Swap operands if necessary.  Only supports one swap at the
2101      moment.  */
2102   for (i = 0; i < pseudo_insn->operand_cnt; ++i)
2103     {
2104       operand_pseudo = &pseudo_insn->operand[i];
2105
2106       if (operand_pseudo->swap_operand_idx == i)
2107         continue;
2108
2109       swap_operand (tok, i, operand_pseudo->swap_operand_idx);
2110
2111       /* Prevent a swap back later by breaking out.  */
2112       break;
2113     }
2114
2115   return (const struct arc_opcode *)
2116     hash_find (arc_opcode_hash, pseudo_insn->mnemonic_r);
2117 }
2118
2119 static const struct arc_opcode *
2120 find_special_case_flag (const char *opname,
2121                         int *nflgs,
2122                         struct arc_flags *pflags)
2123 {
2124   unsigned int i;
2125   const char *flagnm;
2126   unsigned flag_idx, flag_arr_idx;
2127   size_t flaglen, oplen;
2128   const struct arc_flag_special *arc_flag_special_opcode;
2129   const struct arc_opcode *opcode;
2130
2131   /* Search for special case instruction.  */
2132   for (i = 0; i < arc_num_flag_special; i++)
2133     {
2134       arc_flag_special_opcode = &arc_flag_special_cases[i];
2135       oplen = strlen (arc_flag_special_opcode->name);
2136
2137       if (strncmp (opname, arc_flag_special_opcode->name, oplen) != 0)
2138         continue;
2139
2140       /* Found a potential special case instruction, now test for
2141          flags.  */
2142       for (flag_arr_idx = 0;; ++flag_arr_idx)
2143         {
2144           flag_idx = arc_flag_special_opcode->flags[flag_arr_idx];
2145           if (flag_idx == 0)
2146             break;  /* End of array, nothing found.  */
2147
2148           flagnm = arc_flag_operands[flag_idx].name;
2149           flaglen = strlen (flagnm);
2150           if (strcmp (opname + oplen, flagnm) == 0)
2151             {
2152               opcode = (const struct arc_opcode *)
2153                 hash_find (arc_opcode_hash,
2154                            arc_flag_special_opcode->name);
2155
2156               if (*nflgs + 1 > MAX_INSN_FLGS)
2157                 break;
2158               memcpy (pflags[*nflgs].name, flagnm, flaglen);
2159               pflags[*nflgs].name[flaglen] = '\0';
2160               (*nflgs)++;
2161               return opcode;
2162             }
2163         }
2164     }
2165   return NULL;
2166 }
2167
2168 /* Check whether a symbol involves a register.  */
2169
2170 static int
2171 contains_register (symbolS *sym)
2172 {
2173   if (sym)
2174   {
2175     expressionS *ex = symbol_get_value_expression (sym);
2176     return ((O_register == ex->X_op)
2177             && !contains_register (ex->X_add_symbol)
2178             && !contains_register (ex->X_op_symbol));
2179   }
2180   else
2181     return 0;
2182 }
2183
2184 /* Returns the register number within a symbol.  */
2185
2186 static int
2187 get_register (symbolS *sym)
2188 {
2189   if (!contains_register (sym))
2190     return -1;
2191
2192   expressionS *ex = symbol_get_value_expression (sym);
2193   return regno (ex->X_add_number);
2194 }
2195
2196 /* Allocates a tok entry.  */
2197
2198 static int
2199 allocate_tok (expressionS *tok, int ntok, int cidx)
2200 {
2201   if (ntok > MAX_INSN_ARGS - 2)
2202     return 0; /* No space left.  */
2203
2204   if (cidx > ntok)
2205     return 0; /* Incorect args.  */
2206
2207   memcpy (&tok[ntok+1], &tok[ntok], sizeof (*tok));
2208
2209   if (cidx == ntok)
2210     return 1; /* Success.  */
2211   return allocate_tok (tok, ntok - 1, cidx);
2212 }
2213
2214 /* Return true if a RELOC is generic.  A generic reloc is PC-rel of a
2215    simple ME relocation (e.g. RELOC_ARC_32_ME, BFD_RELOC_ARC_PC32.  */
2216
2217 static bfd_boolean
2218 generic_reloc_p (extended_bfd_reloc_code_real_type reloc)
2219 {
2220   if (!reloc)
2221     return FALSE;
2222
2223   switch (reloc)
2224     {
2225     case BFD_RELOC_ARC_SDA_LDST:
2226     case BFD_RELOC_ARC_SDA_LDST1:
2227     case BFD_RELOC_ARC_SDA_LDST2:
2228     case BFD_RELOC_ARC_SDA16_LD:
2229     case BFD_RELOC_ARC_SDA16_LD1:
2230     case BFD_RELOC_ARC_SDA16_LD2:
2231     case BFD_RELOC_ARC_SDA16_ST2:
2232     case BFD_RELOC_ARC_SDA32_ME:
2233       return FALSE;
2234     default:
2235       break;
2236     }
2237   return TRUE;
2238 }
2239
2240 /* Search forward through all variants of an opcode looking for a
2241    syntax match.  */
2242
2243 static const struct arc_opcode *
2244 find_opcode_match (const struct arc_opcode *first_opcode,
2245                    expressionS *tok,
2246                    int *pntok,
2247                    struct arc_flags *first_pflag,
2248                    int nflgs,
2249                    int *pcpumatch)
2250 {
2251   const struct arc_opcode *opcode = first_opcode;
2252   int ntok = *pntok;
2253   int got_cpu_match = 0;
2254   expressionS bktok[MAX_INSN_ARGS];
2255   int bkntok;
2256   expressionS emptyE;
2257
2258   memset (&emptyE, 0, sizeof (emptyE));
2259   memcpy (bktok, tok, MAX_INSN_ARGS * sizeof (*tok));
2260   bkntok = ntok;
2261
2262   do
2263     {
2264       const unsigned char *opidx;
2265       const unsigned char *flgidx;
2266       int tokidx = 0;
2267       const expressionS *t = &emptyE;
2268
2269       pr_debug ("%s:%d: find_opcode_match: trying opcode 0x%08X ",
2270                 frag_now->fr_file, frag_now->fr_line, opcode->opcode);
2271
2272       /* Don't match opcodes that don't exist on this
2273          architecture.  */
2274       if (!(opcode->cpu & arc_target))
2275         goto match_failed;
2276
2277       if (is_code_density_p (opcode) && !(arc_features & ARC_CD))
2278         goto match_failed;
2279
2280       got_cpu_match = 1;
2281       pr_debug ("cpu ");
2282
2283       /* Check the operands.  */
2284       for (opidx = opcode->operands; *opidx; ++opidx)
2285         {
2286           const struct arc_operand *operand = &arc_operands[*opidx];
2287
2288           /* Only take input from real operands.  */
2289           if ((operand->flags & ARC_OPERAND_FAKE)
2290               && !(operand->flags & ARC_OPERAND_BRAKET))
2291             continue;
2292
2293           /* When we expect input, make sure we have it.  */
2294           if (tokidx >= ntok)
2295             goto match_failed;
2296
2297           /* Match operand type with expression type.  */
2298           switch (operand->flags & ARC_OPERAND_TYPECHECK_MASK)
2299             {
2300             case ARC_OPERAND_IR:
2301               /* Check to be a register.  */
2302               if ((tok[tokidx].X_op != O_register
2303                    || !is_ir_num (tok[tokidx].X_add_number))
2304                   && !(operand->flags & ARC_OPERAND_IGNORE))
2305                 goto match_failed;
2306
2307               /* If expect duplicate, make sure it is duplicate.  */
2308               if (operand->flags & ARC_OPERAND_DUPLICATE)
2309                 {
2310                   /* Check for duplicate.  */
2311                   if (t->X_op != O_register
2312                       || !is_ir_num (t->X_add_number)
2313                       || (regno (t->X_add_number) !=
2314                           regno (tok[tokidx].X_add_number)))
2315                     goto match_failed;
2316                 }
2317
2318               /* Special handling?  */
2319               if (operand->insert)
2320                 {
2321                   const char *errmsg = NULL;
2322                   (*operand->insert)(0,
2323                                      regno (tok[tokidx].X_add_number),
2324                                      &errmsg);
2325                   if (errmsg)
2326                     {
2327                       if (operand->flags & ARC_OPERAND_IGNORE)
2328                         {
2329                           /* Missing argument, create one.  */
2330                           if (!allocate_tok (tok, ntok - 1, tokidx))
2331                             goto match_failed;
2332
2333                           tok[tokidx].X_op = O_absent;
2334                           ++ntok;
2335                         }
2336                       else
2337                         goto match_failed;
2338                     }
2339                 }
2340
2341               t = &tok[tokidx];
2342               break;
2343
2344             case ARC_OPERAND_BRAKET:
2345               /* Check if bracket is also in opcode table as
2346                  operand.  */
2347               if (tok[tokidx].X_op != O_bracket)
2348                 goto match_failed;
2349               break;
2350
2351             case ARC_OPERAND_LIMM:
2352             case ARC_OPERAND_SIGNED:
2353             case ARC_OPERAND_UNSIGNED:
2354               switch (tok[tokidx].X_op)
2355                 {
2356                 case O_illegal:
2357                 case O_absent:
2358                 case O_register:
2359                   goto match_failed;
2360
2361                 case O_bracket:
2362                   /* Got an (too) early bracket, check if it is an
2363                      ignored operand.  N.B. This procedure works only
2364                      when bracket is the last operand!  */
2365                   if (!(operand->flags & ARC_OPERAND_IGNORE))
2366                     goto match_failed;
2367                   /* Insert the missing operand.  */
2368                   if (!allocate_tok (tok, ntok - 1, tokidx))
2369                     goto match_failed;
2370
2371                   tok[tokidx].X_op = O_absent;
2372                   ++ntok;
2373                   break;
2374
2375                 case O_constant:
2376                   /* Check the range.  */
2377                   if (operand->bits != 32
2378                       && !(operand->flags & ARC_OPERAND_NCHK))
2379                     {
2380                       offsetT min, max, val;
2381                       val = tok[tokidx].X_add_number;
2382
2383                       if (operand->flags & ARC_OPERAND_SIGNED)
2384                         {
2385                           max = (1 << (operand->bits - 1)) - 1;
2386                           min = -(1 << (operand->bits - 1));
2387                         }
2388                       else
2389                         {
2390                           max = (1 << operand->bits) - 1;
2391                           min = 0;
2392                         }
2393
2394                       if (val < min || val > max)
2395                         goto match_failed;
2396
2397                       /* Check alignmets.  */
2398                       if ((operand->flags & ARC_OPERAND_ALIGNED32)
2399                           && (val & 0x03))
2400                         goto match_failed;
2401
2402                       if ((operand->flags & ARC_OPERAND_ALIGNED16)
2403                           && (val & 0x01))
2404                         goto match_failed;
2405                     }
2406                   else if (operand->flags & ARC_OPERAND_NCHK)
2407                     {
2408                       if (operand->insert)
2409                         {
2410                           const char *errmsg = NULL;
2411                           (*operand->insert)(0,
2412                                              tok[tokidx].X_add_number,
2413                                              &errmsg);
2414                           if (errmsg)
2415                             goto match_failed;
2416                         }
2417                       else
2418                         goto match_failed;
2419                     }
2420                   break;
2421
2422                 case O_subtract:
2423                   /* Check if it is register range.  */
2424                   if ((tok[tokidx].X_add_number == 0)
2425                       && contains_register (tok[tokidx].X_add_symbol)
2426                       && contains_register (tok[tokidx].X_op_symbol))
2427                     {
2428                       int regs;
2429
2430                       regs = get_register (tok[tokidx].X_add_symbol);
2431                       regs <<= 16;
2432                       regs |= get_register (tok[tokidx].X_op_symbol);
2433                       if (operand->insert)
2434                         {
2435                           const char *errmsg = NULL;
2436                           (*operand->insert)(0,
2437                                              regs,
2438                                              &errmsg);
2439                           if (errmsg)
2440                             goto match_failed;
2441                         }
2442                       else
2443                         goto match_failed;
2444                       break;
2445                     }
2446                 default:
2447                   if (operand->default_reloc == 0)
2448                     goto match_failed; /* The operand needs relocation.  */
2449
2450                   /* Relocs requiring long immediate.  FIXME! make it
2451                      generic and move it to a function.  */
2452                   switch (tok[tokidx].X_md)
2453                     {
2454                     case O_gotoff:
2455                     case O_gotpc:
2456                     case O_pcl:
2457                     case O_tpoff:
2458                     case O_dtpoff:
2459                     case O_tlsgd:
2460                     case O_tlsie:
2461                       if (!(operand->flags & ARC_OPERAND_LIMM))
2462                         goto match_failed;
2463                     case O_absent:
2464                       if (!generic_reloc_p (operand->default_reloc))
2465                         goto match_failed;
2466                     default:
2467                       break;
2468                     }
2469                   break;
2470                 }
2471               /* If expect duplicate, make sure it is duplicate.  */
2472               if (operand->flags & ARC_OPERAND_DUPLICATE)
2473                 {
2474                   if (t->X_op == O_illegal
2475                       || t->X_op == O_absent
2476                       || t->X_op == O_register
2477                       || (t->X_add_number != tok[tokidx].X_add_number))
2478                     goto match_failed;
2479                 }
2480               t = &tok[tokidx];
2481               break;
2482
2483             default:
2484               /* Everything else should have been fake.  */
2485               abort ();
2486             }
2487
2488           ++tokidx;
2489         }
2490       pr_debug ("opr ");
2491
2492       /* Check the flags.  Iterate over the valid flag classes.  */
2493       int lnflg = nflgs;
2494
2495       for (flgidx = opcode->flags; *flgidx && lnflg; ++flgidx)
2496         {
2497           /* Get a valid flag class.  */
2498           const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
2499           const unsigned *flgopridx;
2500
2501           for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
2502             {
2503               const struct arc_flag_operand *flg_operand;
2504               struct arc_flags *pflag = first_pflag;
2505               int i;
2506
2507               flg_operand = &arc_flag_operands[*flgopridx];
2508               for (i = 0; i < nflgs; i++, pflag++)
2509                 {
2510                   /* Match against the parsed flags.  */
2511                   if (!strcmp (flg_operand->name, pflag->name))
2512                     {
2513                       /*TODO: Check if it is duplicated.  */
2514                       pflag->code = *flgopridx;
2515                       lnflg--;
2516                       break; /* goto next flag class and parsed flag.  */
2517                     }
2518                 }
2519             }
2520         }
2521       /* Did I check all the parsed flags?  */
2522       if (lnflg)
2523         goto match_failed;
2524
2525       pr_debug ("flg");
2526       /* Possible match -- did we use all of our input?  */
2527       if (tokidx == ntok)
2528         {
2529           *pntok = ntok;
2530           pr_debug ("\n");
2531           return opcode;
2532         }
2533
2534     match_failed:;
2535       pr_debug ("\n");
2536       /* Restore the original parameters.  */
2537       memcpy (tok, bktok, MAX_INSN_ARGS * sizeof (*tok));
2538       ntok = bkntok;
2539     }
2540   while (++opcode - arc_opcodes < (int) arc_num_opcodes
2541          && !strcmp (opcode->name, first_opcode->name));
2542
2543   if (*pcpumatch)
2544     *pcpumatch = got_cpu_match;
2545
2546   return NULL;
2547 }
2548
2549 /* Find the proper relocation for the given opcode.  */
2550
2551 static extended_bfd_reloc_code_real_type
2552 find_reloc (const char *name,
2553             const char *opcodename,
2554             const struct arc_flags *pflags,
2555             int nflg,
2556             extended_bfd_reloc_code_real_type reloc)
2557 {
2558   unsigned int i;
2559   int j;
2560   bfd_boolean found_flag, tmp;
2561   extended_bfd_reloc_code_real_type ret = BFD_RELOC_UNUSED;
2562
2563   for (i = 0; i < arc_num_equiv_tab; i++)
2564     {
2565       const struct arc_reloc_equiv_tab *r = &arc_reloc_equiv[i];
2566
2567       /* Find the entry.  */
2568       if (strcmp (name, r->name))
2569         continue;
2570       if (r->mnemonic && (strcmp (r->mnemonic, opcodename)))
2571         continue;
2572       if (r->flags[0])
2573         {
2574           if (!nflg)
2575             continue;
2576           found_flag = FALSE;
2577           unsigned * psflg = (unsigned *)r->flags;
2578           do
2579             {
2580               tmp = FALSE;
2581               for (j = 0; j < nflg; j++)
2582                 if (!strcmp (pflags[j].name,
2583                              arc_flag_operands[*psflg].name))
2584                   {
2585                     tmp = TRUE;
2586                     break;
2587                   }
2588               if (!tmp)
2589                 {
2590                   found_flag = FALSE;
2591                   break;
2592                 }
2593               else
2594                 {
2595                   found_flag = TRUE;
2596                 }
2597               ++ psflg;
2598             } while (*psflg);
2599
2600           if (!found_flag)
2601             continue;
2602         }
2603
2604       if (reloc != r->oldreloc)
2605         continue;
2606       /* Found it.  */
2607       ret = r->newreloc;
2608       break;
2609     }
2610
2611   if (ret == BFD_RELOC_UNUSED)
2612     as_bad (_("Unable to find %s relocation for instruction %s"),
2613             name, opcodename);
2614   return ret;
2615 }
2616
2617 /* Turn an opcode description and a set of arguments into
2618    an instruction and a fixup.  */
2619
2620 static void
2621 assemble_insn (const struct arc_opcode *opcode,
2622                const expressionS *tok,
2623                int ntok,
2624                const struct arc_flags *pflags,
2625                int nflg,
2626                struct arc_insn *insn)
2627 {
2628   const expressionS *reloc_exp = NULL;
2629   unsigned image;
2630   const unsigned char *argidx;
2631   int i;
2632   int tokidx = 0;
2633   unsigned char pcrel = 0;
2634   bfd_boolean needGOTSymbol;
2635   bfd_boolean has_delay_slot = FALSE;
2636   extended_bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
2637
2638   memset (insn, 0, sizeof (*insn));
2639   image = opcode->opcode;
2640
2641   pr_debug ("%s:%d: assemble_insn: %s using opcode %x\n",
2642             frag_now->fr_file, frag_now->fr_line, opcode->name,
2643             opcode->opcode);
2644
2645   /* Handle operands.  */
2646   for (argidx = opcode->operands; *argidx; ++argidx)
2647     {
2648       const struct arc_operand *operand = &arc_operands[*argidx];
2649       const expressionS *t = (const expressionS *) 0;
2650
2651       if ((operand->flags & ARC_OPERAND_FAKE)
2652           && !(operand->flags & ARC_OPERAND_BRAKET))
2653         continue;
2654
2655       if (operand->flags & ARC_OPERAND_DUPLICATE)
2656         {
2657           /* Duplicate operand, already inserted.  */
2658           tokidx ++;
2659           continue;
2660         }
2661
2662       if (tokidx >= ntok)
2663         {
2664           abort ();
2665         }
2666       else
2667         t = &tok[tokidx++];
2668
2669       /* Regardless if we have a reloc or not mark the instruction
2670          limm if it is the case.  */
2671       if (operand->flags & ARC_OPERAND_LIMM)
2672         insn->has_limm = TRUE;
2673
2674       switch (t->X_op)
2675         {
2676         case O_register:
2677           image = insert_operand (image, operand, regno (t->X_add_number),
2678                                   NULL, 0);
2679           break;
2680
2681         case O_constant:
2682           image = insert_operand (image, operand, t->X_add_number, NULL, 0);
2683           reloc_exp = t;
2684           if (operand->flags & ARC_OPERAND_LIMM)
2685             insn->limm = t->X_add_number;
2686           break;
2687
2688         case O_bracket:
2689           /* Ignore brackets.  */
2690           break;
2691
2692         case O_absent:
2693           gas_assert (operand->flags & ARC_OPERAND_IGNORE);
2694           break;
2695
2696         case O_subtract:
2697           /* Maybe register range.  */
2698           if ((t->X_add_number == 0)
2699               && contains_register (t->X_add_symbol)
2700               && contains_register (t->X_op_symbol))
2701             {
2702               int regs;
2703
2704               regs = get_register (t->X_add_symbol);
2705               regs <<= 16;
2706               regs |= get_register (t->X_op_symbol);
2707               image = insert_operand (image, operand, regs, NULL, 0);
2708               break;
2709             }
2710
2711         default:
2712           /* This operand needs a relocation.  */
2713           needGOTSymbol = FALSE;
2714
2715           switch (t->X_md)
2716             {
2717             case O_plt:
2718               needGOTSymbol = TRUE;
2719               reloc = find_reloc ("plt", opcode->name,
2720                                   pflags, nflg,
2721                                   operand->default_reloc);
2722               break;
2723
2724             case O_gotoff:
2725             case O_gotpc:
2726               needGOTSymbol = TRUE;
2727               reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
2728               break;
2729             case O_pcl:
2730               reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
2731               if (ARC_SHORT (opcode->mask))
2732                 as_bad_where (frag_now->fr_file, frag_now->fr_line,
2733                               _("Unable to use @pcl relocation for insn %s"),
2734                               opcode->name);
2735               break;
2736             case O_sda:
2737               reloc = find_reloc ("sda", opcode->name,
2738                                   pflags, nflg,
2739                                   operand->default_reloc);
2740               break;
2741             case O_tlsgd:
2742             case O_tlsie:
2743               needGOTSymbol = TRUE;
2744               /* Fall-through.  */
2745
2746             case O_tpoff:
2747             case O_dtpoff:
2748               reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
2749               break;
2750
2751             case O_tpoff9: /*FIXME! Check for the conditionality of
2752                              the insn.  */
2753             case O_dtpoff9: /*FIXME! Check for the conditionality of
2754                               the insn.  */
2755               as_bad (_("TLS_*_S9 relocs are not supported yet"));
2756               break;
2757
2758             default:
2759               /* Just consider the default relocation.  */
2760               reloc = operand->default_reloc;
2761               break;
2762             }
2763
2764           if (needGOTSymbol && (GOT_symbol == NULL))
2765             GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
2766
2767           reloc_exp = t;
2768
2769 #if 0
2770           if (reloc > 0)
2771             {
2772               /* sanity checks.  */
2773               reloc_howto_type *reloc_howto
2774                 = bfd_reloc_type_lookup (stdoutput,
2775                                          (bfd_reloc_code_real_type) reloc);
2776               unsigned reloc_bitsize = reloc_howto->bitsize;
2777               if (reloc_howto->rightshift)
2778                 reloc_bitsize -= reloc_howto->rightshift;
2779               if (reloc_bitsize != operand->bits)
2780                 {
2781                   as_bad (_("invalid relocation %s for field"),
2782                           bfd_get_reloc_code_name (reloc));
2783                   return;
2784                 }
2785             }
2786 #endif
2787           if (insn->nfixups >= MAX_INSN_FIXUPS)
2788             as_fatal (_("too many fixups"));
2789
2790           struct arc_fixup *fixup;
2791           fixup = &insn->fixups[insn->nfixups++];
2792           fixup->exp = *t;
2793           fixup->reloc = reloc;
2794           pcrel = (operand->flags & ARC_OPERAND_PCREL) ? 1 : 0;
2795           fixup->pcrel = pcrel;
2796           fixup->islong = (operand->flags & ARC_OPERAND_LIMM) ?
2797             TRUE : FALSE;
2798           break;
2799         }
2800     }
2801
2802   /* Handle flags.  */
2803   for (i = 0; i < nflg; i++)
2804     {
2805       const struct arc_flag_operand *flg_operand =
2806         &arc_flag_operands[pflags[i].code];
2807
2808       /* Check if the instruction has a delay slot.  */
2809       if (!strcmp (flg_operand->name, "d"))
2810         has_delay_slot = TRUE;
2811
2812       /* There is an exceptional case when we cannot insert a flag
2813          just as it is.  The .T flag must be handled in relation with
2814          the relative address.  */
2815       if (!strcmp (flg_operand->name, "t")
2816           || !strcmp (flg_operand->name, "nt"))
2817         {
2818           unsigned bitYoperand = 0;
2819           /* FIXME! move selection bbit/brcc in arc-opc.c.  */
2820           if (!strcmp (flg_operand->name, "t"))
2821             if (!strcmp (opcode->name, "bbit0")
2822                 || !strcmp (opcode->name, "bbit1"))
2823               bitYoperand = arc_NToperand;
2824             else
2825               bitYoperand = arc_Toperand;
2826           else
2827             if (!strcmp (opcode->name, "bbit0")
2828                 || !strcmp (opcode->name, "bbit1"))
2829               bitYoperand = arc_Toperand;
2830             else
2831               bitYoperand = arc_NToperand;
2832
2833           gas_assert (reloc_exp != NULL);
2834           if (reloc_exp->X_op == O_constant)
2835             {
2836               /* Check if we have a constant and solved it
2837                  immediately.  */
2838               offsetT val = reloc_exp->X_add_number;
2839               image |= insert_operand (image, &arc_operands[bitYoperand],
2840                                        val, NULL, 0);
2841             }
2842           else
2843             {
2844               struct arc_fixup *fixup;
2845
2846               if (insn->nfixups >= MAX_INSN_FIXUPS)
2847                 as_fatal (_("too many fixups"));
2848
2849               fixup = &insn->fixups[insn->nfixups++];
2850               fixup->exp = *reloc_exp;
2851               fixup->reloc = -bitYoperand;
2852               fixup->pcrel = pcrel;
2853               fixup->islong = FALSE;
2854             }
2855         }
2856       else
2857         image |= (flg_operand->code & ((1 << flg_operand->bits) - 1))
2858           << flg_operand->shift;
2859     }
2860
2861   /* Short instruction?  */
2862   insn->short_insn = ARC_SHORT (opcode->mask) ? TRUE : FALSE;
2863
2864   insn->insn = image;
2865
2866   /* Update last insn status.  */
2867   arc_last_insns[1]                = arc_last_insns[0];
2868   arc_last_insns[0].opcode         = opcode;
2869   arc_last_insns[0].has_limm       = insn->has_limm;
2870   arc_last_insns[0].has_delay_slot = has_delay_slot;
2871
2872   /* Check if the current instruction is legally used.  */
2873   if (arc_last_insns[1].has_delay_slot
2874       && is_br_jmp_insn_p (arc_last_insns[0].opcode))
2875     as_bad_where (frag_now->fr_file, frag_now->fr_line,
2876                   _("A jump/branch instruction in delay slot."));
2877 }
2878
2879 /* Actually output an instruction with its fixup.  */
2880
2881 static void
2882 emit_insn (struct arc_insn *insn)
2883 {
2884   char *f;
2885   int i;
2886
2887   pr_debug ("Emit insn : 0x%x\n", insn->insn);
2888   pr_debug ("\tShort   : 0x%d\n", insn->short_insn);
2889   pr_debug ("\tLong imm: 0x%lx\n", insn->limm);
2890
2891   /* Write out the instruction.  */
2892   if (insn->short_insn)
2893     {
2894       if (insn->has_limm)
2895         {
2896           f = frag_more (6);
2897           md_number_to_chars (f, insn->insn, 2);
2898           md_number_to_chars_midend (f + 2, insn->limm, 4);
2899           dwarf2_emit_insn (6);
2900         }
2901       else
2902         {
2903           f = frag_more (2);
2904           md_number_to_chars (f, insn->insn, 2);
2905           dwarf2_emit_insn (2);
2906         }
2907     }
2908   else
2909     {
2910       if (insn->has_limm)
2911         {
2912           f = frag_more (8);
2913           md_number_to_chars_midend (f, insn->insn, 4);
2914           md_number_to_chars_midend (f + 4, insn->limm, 4);
2915           dwarf2_emit_insn (8);
2916         }
2917       else
2918         {
2919           f = frag_more (4);
2920           md_number_to_chars_midend (f, insn->insn, 4);
2921           dwarf2_emit_insn (4);
2922         }
2923     }
2924
2925   /* Apply the fixups in order.  */
2926   for (i = 0; i < insn->nfixups; i++)
2927     {
2928       struct arc_fixup *fixup = &insn->fixups[i];
2929       int size, pcrel, offset = 0;
2930
2931       /*FIXME! the reloc size is wrong in the BFD file.  When it will
2932         be fixed please delete me.  */
2933       size = (insn->short_insn && !fixup->islong) ? 2 : 4;
2934
2935       if (fixup->islong)
2936         offset = (insn->short_insn) ? 2 : 4;
2937
2938       /* Some fixups are only used internally, thus no howto.  */
2939       if ((int) fixup->reloc < 0)
2940         {
2941           /*FIXME! the reloc size is wrong in the BFD file.  When it
2942             will be fixed please enable me.
2943             size = (insn->short_insn && !fixup->islong) ? 2 : 4; */
2944           pcrel = fixup->pcrel;
2945         }
2946       else
2947         {
2948           reloc_howto_type *reloc_howto =
2949             bfd_reloc_type_lookup (stdoutput,
2950                                    (bfd_reloc_code_real_type) fixup->reloc);
2951           gas_assert (reloc_howto);
2952           /*FIXME! the reloc size is wrong in the BFD file.  When it
2953             will be fixed please enable me.
2954             size = bfd_get_reloc_size (reloc_howto); */
2955           pcrel = reloc_howto->pc_relative;
2956         }
2957
2958       pr_debug ("%s:%d: emit_insn: new %s fixup (PCrel:%s) of size %d @ offset %d\n",
2959                 frag_now->fr_file, frag_now->fr_line,
2960                 (fixup->reloc < 0) ? "Internal" :
2961                 bfd_get_reloc_code_name (fixup->reloc),
2962                 pcrel ? "Y" : "N",
2963                 size, offset);
2964       fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
2965                    size, &fixup->exp, pcrel, fixup->reloc);
2966
2967       /* Check for ZOLs, and update symbol info if any.  */
2968       if (LP_INSN (insn->insn))
2969         {
2970           gas_assert (fixup->exp.X_add_symbol);
2971           ARC_SET_FLAG (fixup->exp.X_add_symbol, ARC_FLAG_ZOL);
2972         }
2973     }
2974 }
2975
2976 /* Insert an operand value into an instruction.  */
2977
2978 static unsigned
2979 insert_operand (unsigned insn,
2980                 const struct arc_operand *operand,
2981                 offsetT val,
2982                 char *file,
2983                 unsigned line)
2984 {
2985   offsetT min = 0, max = 0;
2986
2987   if (operand->bits != 32
2988       && !(operand->flags & ARC_OPERAND_NCHK)
2989       && !(operand->flags & ARC_OPERAND_FAKE))
2990     {
2991       if (operand->flags & ARC_OPERAND_SIGNED)
2992         {
2993           max = (1 << (operand->bits - 1)) - 1;
2994           min = -(1 << (operand->bits - 1));
2995         }
2996       else
2997         {
2998           max = (1 << operand->bits) - 1;
2999           min = 0;
3000         }
3001
3002       if (val < min || val > max)
3003         as_bad_value_out_of_range (_("operand"),
3004                                    val, min, max, file, line);
3005     }
3006
3007   pr_debug ("insert field: %ld <= %ld <= %ld in 0x%08x\n",
3008             min, val, max, insn);
3009
3010   if ((operand->flags & ARC_OPERAND_ALIGNED32)
3011       && (val & 0x03))
3012     as_bad_where (file, line,
3013                   _("Unaligned operand. Needs to be 32bit aligned"));
3014
3015   if ((operand->flags & ARC_OPERAND_ALIGNED16)
3016       && (val & 0x01))
3017     as_bad_where (file, line,
3018                   _("Unaligned operand. Needs to be 16bit aligned"));
3019
3020   if (operand->insert)
3021     {
3022       const char *errmsg = NULL;
3023
3024       insn = (*operand->insert) (insn, val, &errmsg);
3025       if (errmsg)
3026         as_warn_where (file, line, "%s", errmsg);
3027     }
3028   else
3029     {
3030       if (operand->flags & ARC_OPERAND_TRUNCATE)
3031         {
3032           if (operand->flags & ARC_OPERAND_ALIGNED32)
3033             val >>= 2;
3034           if (operand->flags & ARC_OPERAND_ALIGNED16)
3035             val >>= 1;
3036         }
3037       insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift);
3038     }
3039   return insn;
3040 }
3041
3042 void
3043 arc_handle_align (fragS* fragP)
3044 {
3045   if ((fragP)->fr_type == rs_align_code)
3046     {
3047       char *dest = (fragP)->fr_literal + (fragP)->fr_fix;
3048       valueT count = ((fragP)->fr_next->fr_address
3049                       - (fragP)->fr_address - (fragP)->fr_fix);
3050
3051       (fragP)->fr_var = 2;
3052
3053       if (count & 1)/* Padding in the gap till the next 2-byte
3054                        boundary with 0s.  */
3055         {
3056           (fragP)->fr_fix++;
3057           *dest++ = 0;
3058         }
3059       /* Writing nop_s.  */
3060       md_number_to_chars (dest, NOP_OPCODE_S, 2);
3061     }
3062 }
3063
3064 /* Here we decide which fixups can be adjusted to make them relative
3065    to the beginning of the section instead of the symbol.  Basically
3066    we need to make sure that the dynamic relocations are done
3067    correctly, so in some cases we force the original symbol to be
3068    used.  */
3069
3070 int
3071 tc_arc_fix_adjustable (fixS *fixP)
3072 {
3073
3074   /* Prevent all adjustments to global symbols.  */
3075   if (S_IS_EXTERNAL (fixP->fx_addsy))
3076     return 0;
3077   if (S_IS_WEAK (fixP->fx_addsy))
3078     return 0;
3079
3080   /* Adjust_reloc_syms doesn't know about the GOT.  */
3081   switch (fixP->fx_r_type)
3082     {
3083     case BFD_RELOC_ARC_GOTPC32:
3084     case BFD_RELOC_ARC_PLT32:
3085     case BFD_RELOC_ARC_S25H_PCREL_PLT:
3086     case BFD_RELOC_ARC_S21H_PCREL_PLT:
3087     case BFD_RELOC_ARC_S25W_PCREL_PLT:
3088     case BFD_RELOC_ARC_S21W_PCREL_PLT:
3089       return 0;
3090
3091     default:
3092       break;
3093     }
3094
3095   return 0; /* FIXME! return 1, fix it in the linker.  */
3096 }
3097
3098 /* Compute the reloc type of an expression EXP.  */
3099
3100 static void
3101 arc_check_reloc (expressionS *exp,
3102                  bfd_reloc_code_real_type *r_type_p)
3103 {
3104   if (*r_type_p == BFD_RELOC_32
3105       && exp->X_op == O_subtract
3106       && exp->X_op_symbol != NULL
3107       && exp->X_op_symbol->bsym->section == now_seg)
3108     *r_type_p = BFD_RELOC_ARC_32_PCREL;
3109 }
3110
3111
3112 /* Add expression EXP of SIZE bytes to offset OFF of fragment FRAG.  */
3113
3114 void
3115 arc_cons_fix_new (fragS *frag,
3116                   int off,
3117                   int size,
3118                   expressionS *exp,
3119                   bfd_reloc_code_real_type r_type)
3120 {
3121   r_type = BFD_RELOC_UNUSED;
3122
3123   switch (size)
3124     {
3125     case 1:
3126       r_type = BFD_RELOC_8;
3127       break;
3128
3129     case 2:
3130       r_type = BFD_RELOC_16;
3131       break;
3132
3133     case 3:
3134       r_type = BFD_RELOC_24;
3135       break;
3136
3137     case 4:
3138       r_type = BFD_RELOC_32;
3139       arc_check_reloc (exp, &r_type);
3140       break;
3141
3142     case 8:
3143       r_type = BFD_RELOC_64;
3144       break;
3145
3146     default:
3147       as_bad (_("unsupported BFD relocation size %u"), size);
3148       r_type = BFD_RELOC_UNUSED;
3149     }
3150
3151   fix_new_exp (frag, off, size, exp, 0, r_type);
3152 }
3153
3154 /* The actual routine that checks the ZOL conditions.  */
3155
3156 static void
3157 check_zol (symbolS *s)
3158 {
3159   switch (arc_mach_type)
3160     {
3161     case bfd_mach_arc_arcv2:
3162       if (arc_target & ARC_OPCODE_ARCv2EM)
3163         return;
3164
3165       if (is_br_jmp_insn_p (arc_last_insns[0].opcode)
3166           || arc_last_insns[1].has_delay_slot)
3167         as_bad (_("Jump/Branch instruction detected at the end of the ZOL label @%s"),
3168                 S_GET_NAME (s));
3169
3170       break;
3171     case bfd_mach_arc_arc600:
3172
3173       if (is_kernel_insn_p (arc_last_insns[0].opcode))
3174         as_bad (_("Kernel instruction detected at the end of the ZOL label @%s"),
3175                 S_GET_NAME (s));
3176
3177       if (arc_last_insns[0].has_limm
3178           && is_br_jmp_insn_p (arc_last_insns[0].opcode))
3179         as_bad (_("A jump instruction with long immediate detected at the \
3180 end of the ZOL label @%s"), S_GET_NAME (s));
3181
3182       /* Fall through.  */
3183     case bfd_mach_arc_arc700:
3184       if (arc_last_insns[0].has_delay_slot)
3185         as_bad (_("An illegal use of delay slot detected at the end of the ZOL label @%s"),
3186                 S_GET_NAME (s));
3187
3188       break;
3189     default:
3190       break;
3191     }
3192 }
3193
3194 /* If ZOL end check the last two instruction for illegals.  */
3195 void
3196 arc_frob_label (symbolS * sym)
3197 {
3198   if (ARC_GET_FLAG (sym) & ARC_FLAG_ZOL)
3199     check_zol (sym);
3200
3201   dwarf2_emit_label (sym);
3202 }