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