Home | History | Annotate | Line # | Download | only in config
tc-arc.c revision 1.1.1.1.2.1
      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       break;
   1751 
   1752     default:
   1753       return 0;
   1754     }
   1755 
   1756   if (cpu_flags != EF_ARC_CPU_GENERIC)
   1757     arc_eflag = (arc_eflag & ~EF_ARC_MACH_MSK) | cpu_flags;
   1758 
   1759   return 1;
   1760 }
   1761 
   1762 void
   1763 md_show_usage (FILE *stream)
   1764 {
   1765   fprintf (stream, _("ARC-specific assembler options:\n"));
   1766 
   1767   fprintf (stream, "  -mcpu=<cpu name>\t  assemble for CPU <cpu name>\n");
   1768   fprintf (stream,
   1769 	   "  -mcode-density\t  enable code density option for ARC EM\n");
   1770 
   1771   fprintf (stream, _("\
   1772   -EB                     assemble code for a big-endian cpu\n"));
   1773   fprintf (stream, _("\
   1774   -EL                     assemble code for a little-endian cpu\n"));
   1775 }
   1776 
   1777 static void
   1778 preprocess_operands (const struct arc_opcode *opcode,
   1779 		     expressionS *tok,
   1780 		     int ntok)
   1781 {
   1782   int i;
   1783   size_t len;
   1784   const char *p;
   1785   unsigned j;
   1786   const struct arc_aux_reg *auxr;
   1787 
   1788   for (i = 0; i < ntok; i++)
   1789     {
   1790       switch (tok[i].X_op)
   1791 	{
   1792 	case O_illegal:
   1793 	case O_absent:
   1794 	  break; /* Throw and error.  */
   1795 
   1796 	case O_symbol:
   1797 	  if (opcode->class != AUXREG)
   1798 	    break;
   1799 	  /* Convert the symbol to a constant if possible.  */
   1800 	  p = S_GET_NAME (tok[i].X_add_symbol);
   1801 	  len = strlen (p);
   1802 
   1803 	  auxr = &arc_aux_regs[0];
   1804 	  for (j = 0; j < arc_num_aux_regs; j++, auxr++)
   1805 	    if (len == auxr->length
   1806 		&& strcasecmp (auxr->name, p) == 0)
   1807 	      {
   1808 		tok[i].X_op = O_constant;
   1809 		tok[i].X_add_number = auxr->address;
   1810 		break;
   1811 	      }
   1812 	  break;
   1813 	default:
   1814 	  break;
   1815 	}
   1816     }
   1817 }
   1818 
   1819 /* Given an opcode name, pre-tockenized set of argumenst and the
   1820    opcode flags, take it all the way through emission.  */
   1821 
   1822 static void
   1823 assemble_tokens (const char *opname,
   1824 		 expressionS *tok,
   1825 		 int ntok,
   1826 		 struct arc_flags *pflags,
   1827 		 int nflgs)
   1828 {
   1829   bfd_boolean found_something = FALSE;
   1830   const struct arc_opcode *opcode;
   1831   int cpumatch = 1;
   1832 
   1833   /* Search opcodes.  */
   1834   opcode = (const struct arc_opcode *) hash_find (arc_opcode_hash, opname);
   1835 
   1836   /* Couldn't find opcode conventional way, try special cases.  */
   1837   if (!opcode)
   1838     opcode = find_special_case (opname, &nflgs, pflags, tok, &ntok);
   1839 
   1840   if (opcode)
   1841     {
   1842       pr_debug ("%s:%d: assemble_tokens: %s trying opcode 0x%08X\n",
   1843 		frag_now->fr_file, frag_now->fr_line, opcode->name,
   1844 		opcode->opcode);
   1845 
   1846       preprocess_operands (opcode, tok, ntok);
   1847 
   1848       found_something = TRUE;
   1849       opcode = find_opcode_match (opcode, tok, &ntok, pflags, nflgs, &cpumatch);
   1850       if (opcode)
   1851 	{
   1852 	  struct arc_insn insn;
   1853 	  assemble_insn (opcode, tok, ntok, pflags, nflgs, &insn);
   1854 	  emit_insn (&insn);
   1855 	  return;
   1856 	}
   1857     }
   1858 
   1859   if (found_something)
   1860     {
   1861       if (cpumatch)
   1862 	as_bad (_("inappropriate arguments for opcode '%s'"), opname);
   1863       else
   1864 	as_bad (_("opcode '%s' not supported for target %s"), opname,
   1865 		arc_target_name);
   1866     }
   1867   else
   1868     as_bad (_("unknown opcode '%s'"), opname);
   1869 }
   1870 
   1871 /* Used to find special case opcode.  */
   1872 
   1873 static const struct arc_opcode *
   1874 find_special_case (const char *opname,
   1875 		   int *nflgs,
   1876 		   struct arc_flags *pflags,
   1877 		   expressionS *tok,
   1878 		   int *ntok)
   1879 {
   1880   const struct arc_opcode *opcode;
   1881 
   1882   opcode = find_special_case_pseudo (opname, ntok, tok, nflgs, pflags);
   1883 
   1884   if (opcode == NULL)
   1885     opcode = find_special_case_flag (opname, nflgs, pflags);
   1886 
   1887   return opcode;
   1888 }
   1889 
   1890 /* Swap operand tokens.  */
   1891 
   1892 static void
   1893 swap_operand (expressionS *operand_array,
   1894 	      unsigned source,
   1895 	      unsigned destination)
   1896 {
   1897   expressionS cpy_operand;
   1898   expressionS *src_operand;
   1899   expressionS *dst_operand;
   1900   size_t size;
   1901 
   1902   if (source == destination)
   1903     return;
   1904 
   1905   src_operand = &operand_array[source];
   1906   dst_operand = &operand_array[destination];
   1907   size = sizeof (expressionS);
   1908 
   1909   /* Make copy of operand to swap with and swap.  */
   1910   memcpy (&cpy_operand, dst_operand, size);
   1911   memcpy (dst_operand, src_operand, size);
   1912   memcpy (src_operand, &cpy_operand, size);
   1913 }
   1914 
   1915 /* Check if *op matches *tok type.
   1916    Returns FALSE if they don't match, TRUE if they match.  */
   1917 
   1918 static bfd_boolean
   1919 pseudo_operand_match (const expressionS *tok,
   1920 		      const struct arc_operand_operation *op)
   1921 {
   1922   offsetT min, max, val;
   1923   bfd_boolean ret;
   1924   const struct arc_operand *operand_real = &arc_operands[op->operand_idx];
   1925 
   1926   ret = FALSE;
   1927   switch (tok->X_op)
   1928     {
   1929     case O_constant:
   1930       if (operand_real->bits == 32 && (operand_real->flags & ARC_OPERAND_LIMM))
   1931 	ret = 1;
   1932       else if (!(operand_real->flags & ARC_OPERAND_IR))
   1933 	{
   1934 	  val = tok->X_add_number;
   1935 	  if (operand_real->flags & ARC_OPERAND_SIGNED)
   1936 	    {
   1937 	      max = (1 << (operand_real->bits - 1)) - 1;
   1938 	      min = -(1 << (operand_real->bits - 1));
   1939 	    }
   1940 	  else
   1941 	    {
   1942 	      max = (1 << operand_real->bits) - 1;
   1943 	      min = 0;
   1944 	    }
   1945 	  if (min <= val && val <= max)
   1946 	    ret = TRUE;
   1947 	}
   1948       break;
   1949 
   1950     case O_symbol:
   1951       /* Handle all symbols as long immediates or signed 9.  */
   1952       if (operand_real->flags & ARC_OPERAND_LIMM ||
   1953 	  ((operand_real->flags & ARC_OPERAND_SIGNED) && operand_real->bits == 9))
   1954 	ret = TRUE;
   1955       break;
   1956 
   1957     case O_register:
   1958       if (operand_real->flags & ARC_OPERAND_IR)
   1959 	ret = TRUE;
   1960       break;
   1961 
   1962     case O_bracket:
   1963       if (operand_real->flags & ARC_OPERAND_BRAKET)
   1964 	ret = TRUE;
   1965       break;
   1966 
   1967     default:
   1968       /* Unknown.  */
   1969       break;
   1970     }
   1971   return ret;
   1972 }
   1973 
   1974 /* Find pseudo instruction in array.  */
   1975 
   1976 static const struct arc_pseudo_insn *
   1977 find_pseudo_insn (const char *opname,
   1978 		  int ntok,
   1979 		  const expressionS *tok)
   1980 {
   1981   const struct arc_pseudo_insn *pseudo_insn = NULL;
   1982   const struct arc_operand_operation *op;
   1983   unsigned int i;
   1984   int j;
   1985 
   1986   for (i = 0; i < arc_num_pseudo_insn; ++i)
   1987     {
   1988       pseudo_insn = &arc_pseudo_insns[i];
   1989       if (strcmp (pseudo_insn->mnemonic_p, opname) == 0)
   1990 	{
   1991 	  op = pseudo_insn->operand;
   1992 	  for (j = 0; j < ntok; ++j)
   1993 	    if (!pseudo_operand_match (&tok[j], &op[j]))
   1994 	      break;
   1995 
   1996 	  /* Found the right instruction.  */
   1997 	  if (j == ntok)
   1998 	    return pseudo_insn;
   1999 	}
   2000     }
   2001   return NULL;
   2002 }
   2003 
   2004 /* Assumes the expressionS *tok is of sufficient size.  */
   2005 
   2006 static const struct arc_opcode *
   2007 find_special_case_pseudo (const char *opname,
   2008 			  int *ntok,
   2009 			  expressionS *tok,
   2010 			  int *nflgs,
   2011 			  struct arc_flags *pflags)
   2012 {
   2013   const struct arc_pseudo_insn *pseudo_insn = NULL;
   2014   const struct arc_operand_operation *operand_pseudo;
   2015   const struct arc_operand *operand_real;
   2016   unsigned i;
   2017   char construct_operand[MAX_CONSTR_STR];
   2018 
   2019   /* Find whether opname is in pseudo instruction array.  */
   2020   pseudo_insn = find_pseudo_insn (opname, *ntok, tok);
   2021 
   2022   if (pseudo_insn == NULL)
   2023     return NULL;
   2024 
   2025   /* Handle flag, Limited to one flag at the moment.  */
   2026   if (pseudo_insn->flag_r != NULL)
   2027     *nflgs += tokenize_flags (pseudo_insn->flag_r, &pflags[*nflgs],
   2028 			      MAX_INSN_FLGS - *nflgs);
   2029 
   2030   /* Handle operand operations.  */
   2031   for (i = 0; i < pseudo_insn->operand_cnt; ++i)
   2032     {
   2033       operand_pseudo = &pseudo_insn->operand[i];
   2034       operand_real = &arc_operands[operand_pseudo->operand_idx];
   2035 
   2036       if (operand_real->flags & ARC_OPERAND_BRAKET &&
   2037 	  !operand_pseudo->needs_insert)
   2038 	continue;
   2039 
   2040       /* Has to be inserted (i.e. this token does not exist yet).  */
   2041       if (operand_pseudo->needs_insert)
   2042 	{
   2043 	  if (operand_real->flags & ARC_OPERAND_BRAKET)
   2044 	    {
   2045 	      tok[i].X_op = O_bracket;
   2046 	      ++(*ntok);
   2047 	      continue;
   2048 	    }
   2049 
   2050 	  /* Check if operand is a register or constant and handle it
   2051 	     by type.  */
   2052 	  if (operand_real->flags & ARC_OPERAND_IR)
   2053 	    snprintf (construct_operand, MAX_CONSTR_STR, "r%d",
   2054 		      operand_pseudo->count);
   2055 	  else
   2056 	    snprintf (construct_operand, MAX_CONSTR_STR, "%d",
   2057 		      operand_pseudo->count);
   2058 
   2059 	  tokenize_arguments (construct_operand, &tok[i], 1);
   2060 	  ++(*ntok);
   2061 	}
   2062 
   2063       else if (operand_pseudo->count)
   2064 	{
   2065 	  /* Operand number has to be adjusted accordingly (by operand
   2066 	     type).  */
   2067 	  switch (tok[i].X_op)
   2068 	    {
   2069 	    case O_constant:
   2070 	      tok[i].X_add_number += operand_pseudo->count;
   2071 	      break;
   2072 
   2073 	    case O_symbol:
   2074 	      break;
   2075 
   2076 	    default:
   2077 	      /* Ignored.  */
   2078 	      break;
   2079 	    }
   2080 	}
   2081     }
   2082 
   2083   /* Swap operands if necessary.  Only supports one swap at the
   2084      moment.  */
   2085   for (i = 0; i < pseudo_insn->operand_cnt; ++i)
   2086     {
   2087       operand_pseudo = &pseudo_insn->operand[i];
   2088 
   2089       if (operand_pseudo->swap_operand_idx == i)
   2090 	continue;
   2091 
   2092       swap_operand (tok, i, operand_pseudo->swap_operand_idx);
   2093 
   2094       /* Prevent a swap back later by breaking out.  */
   2095       break;
   2096     }
   2097 
   2098   return (const struct arc_opcode *)
   2099     hash_find (arc_opcode_hash,	pseudo_insn->mnemonic_r);
   2100 }
   2101 
   2102 static const struct arc_opcode *
   2103 find_special_case_flag (const char *opname,
   2104 			int *nflgs,
   2105 			struct arc_flags *pflags)
   2106 {
   2107   unsigned int i;
   2108   const char *flagnm;
   2109   unsigned flag_idx, flag_arr_idx;
   2110   size_t flaglen, oplen;
   2111   const struct arc_flag_special *arc_flag_special_opcode;
   2112   const struct arc_opcode *opcode;
   2113 
   2114   /* Search for special case instruction.  */
   2115   for (i = 0; i < arc_num_flag_special; i++)
   2116     {
   2117       arc_flag_special_opcode = &arc_flag_special_cases[i];
   2118       oplen = strlen (arc_flag_special_opcode->name);
   2119 
   2120       if (strncmp (opname, arc_flag_special_opcode->name, oplen) != 0)
   2121 	continue;
   2122 
   2123       /* Found a potential special case instruction, now test for
   2124 	 flags.  */
   2125       for (flag_arr_idx = 0;; ++flag_arr_idx)
   2126 	{
   2127 	  flag_idx = arc_flag_special_opcode->flags[flag_arr_idx];
   2128 	  if (flag_idx == 0)
   2129 	    break;  /* End of array, nothing found.  */
   2130 
   2131 	  flagnm = arc_flag_operands[flag_idx].name;
   2132 	  flaglen = strlen (flagnm);
   2133 	  if (strcmp (opname + oplen, flagnm) == 0)
   2134 	    {
   2135 	      opcode = (const struct arc_opcode *)
   2136 		hash_find (arc_opcode_hash,
   2137 			   arc_flag_special_opcode->name);
   2138 
   2139 	      if (*nflgs + 1 > MAX_INSN_FLGS)
   2140 		break;
   2141 	      memcpy (pflags[*nflgs].name, flagnm, flaglen);
   2142 	      pflags[*nflgs].name[flaglen] = '\0';
   2143 	      (*nflgs)++;
   2144 	      return opcode;
   2145 	    }
   2146 	}
   2147     }
   2148   return NULL;
   2149 }
   2150 
   2151 /* Check whether a symbol involves a register.  */
   2152 
   2153 static int
   2154 contains_register (symbolS *sym)
   2155 {
   2156   if (sym)
   2157   {
   2158     expressionS *ex = symbol_get_value_expression (sym);
   2159     return ((O_register == ex->X_op)
   2160 	    && !contains_register (ex->X_add_symbol)
   2161 	    && !contains_register (ex->X_op_symbol));
   2162   }
   2163   else
   2164     return 0;
   2165 }
   2166 
   2167 /* Returns the register number within a symbol.  */
   2168 
   2169 static int
   2170 get_register (symbolS *sym)
   2171 {
   2172   if (!contains_register (sym))
   2173     return -1;
   2174 
   2175   expressionS *ex = symbol_get_value_expression (sym);
   2176   return regno (ex->X_add_number);
   2177 }
   2178 
   2179 /* Allocates a tok entry.  */
   2180 
   2181 static int
   2182 allocate_tok (expressionS *tok, int ntok, int cidx)
   2183 {
   2184   if (ntok > MAX_INSN_ARGS - 2)
   2185     return 0; /* No space left.  */
   2186 
   2187   if (cidx > ntok)
   2188     return 0; /* Incorect args.  */
   2189 
   2190   memcpy (&tok[ntok+1], &tok[ntok], sizeof (*tok));
   2191 
   2192   if (cidx == ntok)
   2193     return 1; /* Success.  */
   2194   return allocate_tok (tok, ntok - 1, cidx);
   2195 }
   2196 
   2197 /* Return true if a RELOC is generic.  A generic reloc is PC-rel of a
   2198    simple ME relocation (e.g. RELOC_ARC_32_ME, BFD_RELOC_ARC_PC32.  */
   2199 
   2200 static bfd_boolean
   2201 generic_reloc_p (extended_bfd_reloc_code_real_type reloc)
   2202 {
   2203   if (!reloc)
   2204     return FALSE;
   2205 
   2206   switch (reloc)
   2207     {
   2208     case BFD_RELOC_ARC_SDA_LDST:
   2209     case BFD_RELOC_ARC_SDA_LDST1:
   2210     case BFD_RELOC_ARC_SDA_LDST2:
   2211     case BFD_RELOC_ARC_SDA16_LD:
   2212     case BFD_RELOC_ARC_SDA16_LD1:
   2213     case BFD_RELOC_ARC_SDA16_LD2:
   2214     case BFD_RELOC_ARC_SDA16_ST2:
   2215     case BFD_RELOC_ARC_SDA32_ME:
   2216       return FALSE;
   2217     default:
   2218       break;
   2219     }
   2220   return TRUE;
   2221 }
   2222 
   2223 /* Search forward through all variants of an opcode looking for a
   2224    syntax match.  */
   2225 
   2226 static const struct arc_opcode *
   2227 find_opcode_match (const struct arc_opcode *first_opcode,
   2228 		   expressionS *tok,
   2229 		   int *pntok,
   2230 		   struct arc_flags *first_pflag,
   2231 		   int nflgs,
   2232 		   int *pcpumatch)
   2233 {
   2234   const struct arc_opcode *opcode = first_opcode;
   2235   int ntok = *pntok;
   2236   int got_cpu_match = 0;
   2237   expressionS bktok[MAX_INSN_ARGS];
   2238   int bkntok;
   2239   expressionS emptyE;
   2240 
   2241   memset (&emptyE, 0, sizeof (emptyE));
   2242   memcpy (bktok, tok, MAX_INSN_ARGS * sizeof (*tok));
   2243   bkntok = ntok;
   2244 
   2245   do
   2246     {
   2247       const unsigned char *opidx;
   2248       const unsigned char *flgidx;
   2249       int tokidx = 0;
   2250       const expressionS *t = &emptyE;
   2251 
   2252       pr_debug ("%s:%d: find_opcode_match: trying opcode 0x%08X ",
   2253 		frag_now->fr_file, frag_now->fr_line, opcode->opcode);
   2254 
   2255       /* Don't match opcodes that don't exist on this
   2256 	 architecture.  */
   2257       if (!(opcode->cpu & arc_target))
   2258 	goto match_failed;
   2259 
   2260       if (is_code_density_p (opcode) && !(arc_features & ARC_CD))
   2261 	goto match_failed;
   2262 
   2263       got_cpu_match = 1;
   2264       pr_debug ("cpu ");
   2265 
   2266       /* Check the operands.  */
   2267       for (opidx = opcode->operands; *opidx; ++opidx)
   2268 	{
   2269 	  const struct arc_operand *operand = &arc_operands[*opidx];
   2270 
   2271 	  /* Only take input from real operands.  */
   2272 	  if ((operand->flags & ARC_OPERAND_FAKE)
   2273 	      && !(operand->flags & ARC_OPERAND_BRAKET))
   2274 	    continue;
   2275 
   2276 	  /* When we expect input, make sure we have it.  */
   2277 	  if (tokidx >= ntok)
   2278 	    goto match_failed;
   2279 
   2280 	  /* Match operand type with expression type.  */
   2281 	  switch (operand->flags & ARC_OPERAND_TYPECHECK_MASK)
   2282 	    {
   2283 	    case ARC_OPERAND_IR:
   2284 	      /* Check to be a register.  */
   2285 	      if ((tok[tokidx].X_op != O_register
   2286 		   || !is_ir_num (tok[tokidx].X_add_number))
   2287 		  && !(operand->flags & ARC_OPERAND_IGNORE))
   2288 		goto match_failed;
   2289 
   2290 	      /* If expect duplicate, make sure it is duplicate.  */
   2291 	      if (operand->flags & ARC_OPERAND_DUPLICATE)
   2292 		{
   2293 		  /* Check for duplicate.  */
   2294 		  if (t->X_op != O_register
   2295 		      || !is_ir_num (t->X_add_number)
   2296 		      || (regno (t->X_add_number) !=
   2297 			  regno (tok[tokidx].X_add_number)))
   2298 		    goto match_failed;
   2299 		}
   2300 
   2301 	      /* Special handling?  */
   2302 	      if (operand->insert)
   2303 		{
   2304 		  const char *errmsg = NULL;
   2305 		  (*operand->insert)(0,
   2306 				     regno (tok[tokidx].X_add_number),
   2307 				     &errmsg);
   2308 		  if (errmsg)
   2309 		    {
   2310 		      if (operand->flags & ARC_OPERAND_IGNORE)
   2311 			{
   2312 			  /* Missing argument, create one.  */
   2313 			  if (!allocate_tok (tok, ntok - 1, tokidx))
   2314 			    goto match_failed;
   2315 
   2316 			  tok[tokidx].X_op = O_absent;
   2317 			  ++ntok;
   2318 			}
   2319 		      else
   2320 			goto match_failed;
   2321 		    }
   2322 		}
   2323 
   2324 	      t = &tok[tokidx];
   2325 	      break;
   2326 
   2327 	    case ARC_OPERAND_BRAKET:
   2328 	      /* Check if bracket is also in opcode table as
   2329 		 operand.  */
   2330 	      if (tok[tokidx].X_op != O_bracket)
   2331 		goto match_failed;
   2332 	      break;
   2333 
   2334 	    case ARC_OPERAND_LIMM:
   2335 	    case ARC_OPERAND_SIGNED:
   2336 	    case ARC_OPERAND_UNSIGNED:
   2337 	      switch (tok[tokidx].X_op)
   2338 		{
   2339 		case O_illegal:
   2340 		case O_absent:
   2341 		case O_register:
   2342 		  goto match_failed;
   2343 
   2344 		case O_bracket:
   2345 		  /* Got an (too) early bracket, check if it is an
   2346 		     ignored operand.  N.B. This procedure works only
   2347 		     when bracket is the last operand!  */
   2348 		  if (!(operand->flags & ARC_OPERAND_IGNORE))
   2349 		    goto match_failed;
   2350 		  /* Insert the missing operand.  */
   2351 		  if (!allocate_tok (tok, ntok - 1, tokidx))
   2352 		    goto match_failed;
   2353 
   2354 		  tok[tokidx].X_op = O_absent;
   2355 		  ++ntok;
   2356 		  break;
   2357 
   2358 		case O_constant:
   2359 		  /* Check the range.  */
   2360 		  if (operand->bits != 32
   2361 		      && !(operand->flags & ARC_OPERAND_NCHK))
   2362 		    {
   2363 		      offsetT min, max, val;
   2364 		      val = tok[tokidx].X_add_number;
   2365 
   2366 		      if (operand->flags & ARC_OPERAND_SIGNED)
   2367 			{
   2368 			  max = (1 << (operand->bits - 1)) - 1;
   2369 			  min = -(1 << (operand->bits - 1));
   2370 			}
   2371 		      else
   2372 			{
   2373 			  max = (1 << operand->bits) - 1;
   2374 			  min = 0;
   2375 			}
   2376 
   2377 		      if (val < min || val > max)
   2378 			goto match_failed;
   2379 
   2380 		      /* Check alignmets.  */
   2381 		      if ((operand->flags & ARC_OPERAND_ALIGNED32)
   2382 			  && (val & 0x03))
   2383 			goto match_failed;
   2384 
   2385 		      if ((operand->flags & ARC_OPERAND_ALIGNED16)
   2386 			  && (val & 0x01))
   2387 			goto match_failed;
   2388 		    }
   2389 		  else if (operand->flags & ARC_OPERAND_NCHK)
   2390 		    {
   2391 		      if (operand->insert)
   2392 			{
   2393 			  const char *errmsg = NULL;
   2394 			  (*operand->insert)(0,
   2395 					     tok[tokidx].X_add_number,
   2396 					     &errmsg);
   2397 			  if (errmsg)
   2398 			    goto match_failed;
   2399 			}
   2400 		      else
   2401 			goto match_failed;
   2402 		    }
   2403 		  break;
   2404 
   2405 		case O_subtract:
   2406 		  /* Check if it is register range.  */
   2407 		  if ((tok[tokidx].X_add_number == 0)
   2408 		      && contains_register (tok[tokidx].X_add_symbol)
   2409 		      && contains_register (tok[tokidx].X_op_symbol))
   2410 		    {
   2411 		      int regs;
   2412 
   2413 		      regs = get_register (tok[tokidx].X_add_symbol);
   2414 		      regs <<= 16;
   2415 		      regs |= get_register (tok[tokidx].X_op_symbol);
   2416 		      if (operand->insert)
   2417 			{
   2418 			  const char *errmsg = NULL;
   2419 			  (*operand->insert)(0,
   2420 					     regs,
   2421 					     &errmsg);
   2422 			  if (errmsg)
   2423 			    goto match_failed;
   2424 			}
   2425 		      else
   2426 			goto match_failed;
   2427 		      break;
   2428 		    }
   2429 		default:
   2430 		  if (operand->default_reloc == 0)
   2431 		    goto match_failed; /* The operand needs relocation.  */
   2432 
   2433 		  /* Relocs requiring long immediate.  FIXME! make it
   2434 		     generic and move it to a function.  */
   2435 		  switch (tok[tokidx].X_md)
   2436 		    {
   2437 		    case O_gotoff:
   2438 		    case O_gotpc:
   2439 		    case O_pcl:
   2440 		    case O_tpoff:
   2441 		    case O_dtpoff:
   2442 		    case O_tlsgd:
   2443 		    case O_tlsie:
   2444 		      if (!(operand->flags & ARC_OPERAND_LIMM))
   2445 			goto match_failed;
   2446 		    case O_absent:
   2447 		      if (!generic_reloc_p (operand->default_reloc))
   2448 			goto match_failed;
   2449 		    default:
   2450 		      break;
   2451 		    }
   2452 		  break;
   2453 		}
   2454 	      /* If expect duplicate, make sure it is duplicate.  */
   2455 	      if (operand->flags & ARC_OPERAND_DUPLICATE)
   2456 		{
   2457 		  if (t->X_op == O_illegal
   2458 		      || t->X_op == O_absent
   2459 		      || t->X_op == O_register
   2460 		      || (t->X_add_number != tok[tokidx].X_add_number))
   2461 		    goto match_failed;
   2462 		}
   2463 	      t = &tok[tokidx];
   2464 	      break;
   2465 
   2466 	    default:
   2467 	      /* Everything else should have been fake.  */
   2468 	      abort ();
   2469 	    }
   2470 
   2471 	  ++tokidx;
   2472 	}
   2473       pr_debug ("opr ");
   2474 
   2475       /* Check the flags.  Iterate over the valid flag classes.  */
   2476       int lnflg = nflgs;
   2477 
   2478       for (flgidx = opcode->flags; *flgidx && lnflg; ++flgidx)
   2479 	{
   2480 	  /* Get a valid flag class.  */
   2481 	  const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
   2482 	  const unsigned *flgopridx;
   2483 
   2484 	  for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
   2485 	    {
   2486 	      const struct arc_flag_operand *flg_operand;
   2487 	      struct arc_flags *pflag = first_pflag;
   2488 	      int i;
   2489 
   2490 	      flg_operand = &arc_flag_operands[*flgopridx];
   2491 	      for (i = 0; i < nflgs; i++, pflag++)
   2492 		{
   2493 		  /* Match against the parsed flags.  */
   2494 		  if (!strcmp (flg_operand->name, pflag->name))
   2495 		    {
   2496 		      /*TODO: Check if it is duplicated.  */
   2497 		      pflag->code = *flgopridx;
   2498 		      lnflg--;
   2499 		      break; /* goto next flag class and parsed flag.  */
   2500 		    }
   2501 		}
   2502 	    }
   2503 	}
   2504       /* Did I check all the parsed flags?  */
   2505       if (lnflg)
   2506 	goto match_failed;
   2507 
   2508       pr_debug ("flg");
   2509       /* Possible match -- did we use all of our input?  */
   2510       if (tokidx == ntok)
   2511 	{
   2512 	  *pntok = ntok;
   2513 	  pr_debug ("\n");
   2514 	  return opcode;
   2515 	}
   2516 
   2517     match_failed:;
   2518       pr_debug ("\n");
   2519       /* Restore the original parameters.  */
   2520       memcpy (tok, bktok, MAX_INSN_ARGS * sizeof (*tok));
   2521       ntok = bkntok;
   2522     }
   2523   while (++opcode - arc_opcodes < (int) arc_num_opcodes
   2524 	 && !strcmp (opcode->name, first_opcode->name));
   2525 
   2526   if (*pcpumatch)
   2527     *pcpumatch = got_cpu_match;
   2528 
   2529   return NULL;
   2530 }
   2531 
   2532 /* Find the proper relocation for the given opcode.  */
   2533 
   2534 static extended_bfd_reloc_code_real_type
   2535 find_reloc (const char *name,
   2536 	    const char *opcodename,
   2537 	    const struct arc_flags *pflags,
   2538 	    int nflg,
   2539 	    extended_bfd_reloc_code_real_type reloc)
   2540 {
   2541   unsigned int i;
   2542   int j;
   2543   bfd_boolean found_flag;
   2544   extended_bfd_reloc_code_real_type ret = BFD_RELOC_UNUSED;
   2545 
   2546   for (i = 0; i < arc_num_equiv_tab; i++)
   2547     {
   2548       const struct arc_reloc_equiv_tab *r = &arc_reloc_equiv[i];
   2549 
   2550       /* Find the entry.  */
   2551       if (strcmp (name, r->name))
   2552 	continue;
   2553       if (r->mnemonic && (strcmp (r->mnemonic, opcodename)))
   2554 	continue;
   2555       if (r->flagcode)
   2556 	{
   2557 	  if (!nflg)
   2558 	    continue;
   2559 	  found_flag = FALSE;
   2560 	  for (j = 0; j < nflg; j++)
   2561 	    if (pflags[i].code == r->flagcode)
   2562 	      {
   2563 		found_flag = TRUE;
   2564 		break;
   2565 	      }
   2566 	  if (!found_flag)
   2567 	    continue;
   2568 	}
   2569 
   2570       if (reloc != r->oldreloc)
   2571 	continue;
   2572       /* Found it.  */
   2573       ret = r->newreloc;
   2574       break;
   2575     }
   2576 
   2577   if (ret == BFD_RELOC_UNUSED)
   2578     as_bad (_("Unable to find %s relocation for instruction %s"),
   2579 	    name, opcodename);
   2580   return ret;
   2581 }
   2582 
   2583 /* Turn an opcode description and a set of arguments into
   2584    an instruction and a fixup.  */
   2585 
   2586 static void
   2587 assemble_insn (const struct arc_opcode *opcode,
   2588 	       const expressionS *tok,
   2589 	       int ntok,
   2590 	       const struct arc_flags *pflags,
   2591 	       int nflg,
   2592 	       struct arc_insn *insn)
   2593 {
   2594   const expressionS *reloc_exp = NULL;
   2595   unsigned image;
   2596   const unsigned char *argidx;
   2597   int i;
   2598   int tokidx = 0;
   2599   unsigned char pcrel = 0;
   2600   bfd_boolean needGOTSymbol;
   2601   bfd_boolean has_delay_slot = FALSE;
   2602   extended_bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
   2603 
   2604   memset (insn, 0, sizeof (*insn));
   2605   image = opcode->opcode;
   2606 
   2607   pr_debug ("%s:%d: assemble_insn: %s using opcode %x\n",
   2608 	    frag_now->fr_file, frag_now->fr_line, opcode->name,
   2609 	    opcode->opcode);
   2610 
   2611   /* Handle operands.  */
   2612   for (argidx = opcode->operands; *argidx; ++argidx)
   2613     {
   2614       const struct arc_operand *operand = &arc_operands[*argidx];
   2615       const expressionS *t = (const expressionS *) 0;
   2616 
   2617       if ((operand->flags & ARC_OPERAND_FAKE)
   2618 	  && !(operand->flags & ARC_OPERAND_BRAKET))
   2619 	continue;
   2620 
   2621       if (operand->flags & ARC_OPERAND_DUPLICATE)
   2622 	{
   2623 	  /* Duplicate operand, already inserted.  */
   2624 	  tokidx ++;
   2625 	  continue;
   2626 	}
   2627 
   2628       if (tokidx >= ntok)
   2629 	{
   2630 	  abort ();
   2631 	}
   2632       else
   2633 	t = &tok[tokidx++];
   2634 
   2635       /* Regardless if we have a reloc or not mark the instruction
   2636 	 limm if it is the case.  */
   2637       if (operand->flags & ARC_OPERAND_LIMM)
   2638 	insn->has_limm = TRUE;
   2639 
   2640       switch (t->X_op)
   2641 	{
   2642 	case O_register:
   2643 	  image = insert_operand (image, operand, regno (t->X_add_number),
   2644 				  NULL, 0);
   2645 	  break;
   2646 
   2647 	case O_constant:
   2648 	  image = insert_operand (image, operand, t->X_add_number, NULL, 0);
   2649 	  reloc_exp = t;
   2650 	  if (operand->flags & ARC_OPERAND_LIMM)
   2651 	    insn->limm = t->X_add_number;
   2652 	  break;
   2653 
   2654 	case O_bracket:
   2655 	  /* Ignore brackets.  */
   2656 	  break;
   2657 
   2658 	case O_absent:
   2659 	  gas_assert (operand->flags & ARC_OPERAND_IGNORE);
   2660 	  break;
   2661 
   2662 	case O_subtract:
   2663 	  /* Maybe register range.  */
   2664 	  if ((t->X_add_number == 0)
   2665 	      && contains_register (t->X_add_symbol)
   2666 	      && contains_register (t->X_op_symbol))
   2667 	    {
   2668 	      int regs;
   2669 
   2670 	      regs = get_register (t->X_add_symbol);
   2671 	      regs <<= 16;
   2672 	      regs |= get_register (t->X_op_symbol);
   2673 	      image = insert_operand (image, operand, regs, NULL, 0);
   2674 	      break;
   2675 	    }
   2676 
   2677 	default:
   2678 	  /* This operand needs a relocation.  */
   2679 	  needGOTSymbol = FALSE;
   2680 
   2681 	  switch (t->X_md)
   2682 	    {
   2683 	    case O_plt:
   2684 	      needGOTSymbol = TRUE;
   2685 	      reloc = find_reloc ("plt", opcode->name,
   2686 				  pflags, nflg,
   2687 				  operand->default_reloc);
   2688 	      break;
   2689 
   2690 	    case O_gotoff:
   2691 	    case O_gotpc:
   2692 	      needGOTSymbol = TRUE;
   2693 	      reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
   2694 	      break;
   2695 	    case O_pcl:
   2696 	      reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
   2697 	      if (ARC_SHORT (opcode->mask))
   2698 		as_bad_where (frag_now->fr_file, frag_now->fr_line,
   2699 			      _("Unable to use @pcl relocation for insn %s"),
   2700 			      opcode->name);
   2701 	      break;
   2702 	    case O_sda:
   2703 	      reloc = find_reloc ("sda", opcode->name,
   2704 				  pflags, nflg,
   2705 				  operand->default_reloc);
   2706 	      break;
   2707 	    case O_tlsgd:
   2708 	    case O_tlsie:
   2709 	      needGOTSymbol = TRUE;
   2710 	      /* Fall-through.  */
   2711 
   2712 	    case O_tpoff:
   2713 	    case O_dtpoff:
   2714 	      reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
   2715 	      break;
   2716 
   2717 	    case O_tpoff9: /*FIXME! Check for the conditionality of
   2718 			     the insn.  */
   2719 	    case O_dtpoff9: /*FIXME! Check for the conditionality of
   2720 			      the insn.  */
   2721 	      as_bad (_("TLS_*_S9 relocs are not supported yet"));
   2722 	      break;
   2723 
   2724 	    default:
   2725 	      /* Just consider the default relocation.  */
   2726 	      reloc = operand->default_reloc;
   2727 	      break;
   2728 	    }
   2729 
   2730 	  if (needGOTSymbol && (GOT_symbol == NULL))
   2731 	    GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
   2732 
   2733 	  reloc_exp = t;
   2734 
   2735 #if 0
   2736 	  if (reloc > 0)
   2737 	    {
   2738 	      /* sanity checks.  */
   2739 	      reloc_howto_type *reloc_howto
   2740 		= bfd_reloc_type_lookup (stdoutput,
   2741 					 (bfd_reloc_code_real_type) reloc);
   2742 	      unsigned reloc_bitsize = reloc_howto->bitsize;
   2743 	      if (reloc_howto->rightshift)
   2744 		reloc_bitsize -= reloc_howto->rightshift;
   2745 	      if (reloc_bitsize != operand->bits)
   2746 		{
   2747 		  as_bad (_("invalid relocation %s for field"),
   2748 			  bfd_get_reloc_code_name (reloc));
   2749 		  return;
   2750 		}
   2751 	    }
   2752 #endif
   2753 	  if (insn->nfixups >= MAX_INSN_FIXUPS)
   2754 	    as_fatal (_("too many fixups"));
   2755 
   2756 	  struct arc_fixup *fixup;
   2757 	  fixup = &insn->fixups[insn->nfixups++];
   2758 	  fixup->exp = *t;
   2759 	  fixup->reloc = reloc;
   2760 	  pcrel = (operand->flags & ARC_OPERAND_PCREL) ? 1 : 0;
   2761 	  fixup->pcrel = pcrel;
   2762 	  fixup->islong = (operand->flags & ARC_OPERAND_LIMM) ?
   2763 	    TRUE : FALSE;
   2764 	  break;
   2765 	}
   2766     }
   2767 
   2768   /* Handle flags.  */
   2769   for (i = 0; i < nflg; i++)
   2770     {
   2771       const struct arc_flag_operand *flg_operand =
   2772 	&arc_flag_operands[pflags[i].code];
   2773 
   2774       /* Check if the instruction has a delay slot.  */
   2775       if (!strcmp (flg_operand->name, "d"))
   2776 	has_delay_slot = TRUE;
   2777 
   2778       /* There is an exceptional case when we cannot insert a flag
   2779 	 just as it is.  The .T flag must be handled in relation with
   2780 	 the relative address.  */
   2781       if (!strcmp (flg_operand->name, "t")
   2782 	  || !strcmp (flg_operand->name, "nt"))
   2783 	{
   2784 	  unsigned bitYoperand = 0;
   2785 	  /* FIXME! move selection bbit/brcc in arc-opc.c.  */
   2786 	  if (!strcmp (flg_operand->name, "t"))
   2787 	    if (!strcmp (opcode->name, "bbit0")
   2788 		|| !strcmp (opcode->name, "bbit1"))
   2789 	      bitYoperand = arc_NToperand;
   2790 	    else
   2791 	      bitYoperand = arc_Toperand;
   2792 	  else
   2793 	    if (!strcmp (opcode->name, "bbit0")
   2794 		|| !strcmp (opcode->name, "bbit1"))
   2795 	      bitYoperand = arc_Toperand;
   2796 	    else
   2797 	      bitYoperand = arc_NToperand;
   2798 
   2799 	  gas_assert (reloc_exp != NULL);
   2800 	  if (reloc_exp->X_op == O_constant)
   2801 	    {
   2802 	      /* Check if we have a constant and solved it
   2803 		 immediately.  */
   2804 	      offsetT val = reloc_exp->X_add_number;
   2805 	      image |= insert_operand (image, &arc_operands[bitYoperand],
   2806 				       val, NULL, 0);
   2807 	    }
   2808 	  else
   2809 	    {
   2810 	      struct arc_fixup *fixup;
   2811 
   2812 	      if (insn->nfixups >= MAX_INSN_FIXUPS)
   2813 		as_fatal (_("too many fixups"));
   2814 
   2815 	      fixup = &insn->fixups[insn->nfixups++];
   2816 	      fixup->exp = *reloc_exp;
   2817 	      fixup->reloc = -bitYoperand;
   2818 	      fixup->pcrel = pcrel;
   2819 	      fixup->islong = FALSE;
   2820 	    }
   2821 	}
   2822       else
   2823 	image |= (flg_operand->code & ((1 << flg_operand->bits) - 1))
   2824 	  << flg_operand->shift;
   2825     }
   2826 
   2827   /* Short instruction?  */
   2828   insn->short_insn = ARC_SHORT (opcode->mask) ? TRUE : FALSE;
   2829 
   2830   insn->insn = image;
   2831 
   2832   /* Update last insn status.  */
   2833   arc_last_insns[1]		   = arc_last_insns[0];
   2834   arc_last_insns[0].opcode	   = opcode;
   2835   arc_last_insns[0].has_limm	   = insn->has_limm;
   2836   arc_last_insns[0].has_delay_slot = has_delay_slot;
   2837 
   2838   /* Check if the current instruction is legally used.  */
   2839   if (arc_last_insns[1].has_delay_slot
   2840       && is_br_jmp_insn_p (arc_last_insns[0].opcode))
   2841     as_bad_where (frag_now->fr_file, frag_now->fr_line,
   2842 		  _("A jump/branch instruction in delay slot."));
   2843 }
   2844 
   2845 /* Actually output an instruction with its fixup.  */
   2846 
   2847 static void
   2848 emit_insn (struct arc_insn *insn)
   2849 {
   2850   char *f;
   2851   int i;
   2852 
   2853   pr_debug ("Emit insn : 0x%x\n", insn->insn);
   2854   pr_debug ("\tShort   : 0x%d\n", insn->short_insn);
   2855   pr_debug ("\tLong imm: 0x%lx\n", insn->limm);
   2856 
   2857   /* Write out the instruction.  */
   2858   if (insn->short_insn)
   2859     {
   2860       if (insn->has_limm)
   2861 	{
   2862 	  f = frag_more (6);
   2863 	  md_number_to_chars (f, insn->insn, 2);
   2864 	  md_number_to_chars_midend (f + 2, insn->limm, 4);
   2865 	  dwarf2_emit_insn (6);
   2866 	}
   2867       else
   2868 	{
   2869 	  f = frag_more (2);
   2870 	  md_number_to_chars (f, insn->insn, 2);
   2871 	  dwarf2_emit_insn (2);
   2872 	}
   2873     }
   2874   else
   2875     {
   2876       if (insn->has_limm)
   2877 	{
   2878 	  f = frag_more (8);
   2879 	  md_number_to_chars_midend (f, insn->insn, 4);
   2880 	  md_number_to_chars_midend (f + 4, insn->limm, 4);
   2881 	  dwarf2_emit_insn (8);
   2882 	}
   2883       else
   2884 	{
   2885 	  f = frag_more (4);
   2886 	  md_number_to_chars_midend (f, insn->insn, 4);
   2887 	  dwarf2_emit_insn (4);
   2888 	}
   2889     }
   2890 
   2891   /* Apply the fixups in order.  */
   2892   for (i = 0; i < insn->nfixups; i++)
   2893     {
   2894       struct arc_fixup *fixup = &insn->fixups[i];
   2895       int size, pcrel, offset = 0;
   2896 
   2897       /*FIXME! the reloc size is wrong in the BFD file.  When it will
   2898 	be fixed please delete me.  */
   2899       size = (insn->short_insn && !fixup->islong) ? 2 : 4;
   2900 
   2901       if (fixup->islong)
   2902 	offset = (insn->short_insn) ? 2 : 4;
   2903 
   2904       /* Some fixups are only used internally, thus no howto.  */
   2905       if ((int) fixup->reloc < 0)
   2906 	{
   2907 	  /*FIXME! the reloc size is wrong in the BFD file.  When it
   2908 	    will be fixed please enable me.
   2909 	    size = (insn->short_insn && !fixup->islong) ? 2 : 4; */
   2910 	  pcrel = fixup->pcrel;
   2911 	}
   2912       else
   2913 	{
   2914 	  reloc_howto_type *reloc_howto =
   2915 	    bfd_reloc_type_lookup (stdoutput,
   2916 				   (bfd_reloc_code_real_type) fixup->reloc);
   2917 	  gas_assert (reloc_howto);
   2918 	  /*FIXME! the reloc size is wrong in the BFD file.  When it
   2919 	    will be fixed please enable me.
   2920 	    size = bfd_get_reloc_size (reloc_howto); */
   2921 	  pcrel = reloc_howto->pc_relative;
   2922 	}
   2923 
   2924       pr_debug ("%s:%d: emit_insn: new %s fixup (PCrel:%s) of size %d @ offset %d\n",
   2925 		frag_now->fr_file, frag_now->fr_line,
   2926 		(fixup->reloc < 0) ? "Internal" :
   2927 		bfd_get_reloc_code_name (fixup->reloc),
   2928 		pcrel ? "Y" : "N",
   2929 		size, offset);
   2930       fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
   2931 		   size, &fixup->exp, pcrel, fixup->reloc);
   2932 
   2933       /* Check for ZOLs, and update symbol info if any.  */
   2934       if (LP_INSN (insn->insn))
   2935 	{
   2936 	  gas_assert (fixup->exp.X_add_symbol);
   2937 	  ARC_SET_FLAG (fixup->exp.X_add_symbol, ARC_FLAG_ZOL);
   2938 	}
   2939     }
   2940 }
   2941 
   2942 /* Insert an operand value into an instruction.  */
   2943 
   2944 static unsigned
   2945 insert_operand (unsigned insn,
   2946 		const struct arc_operand *operand,
   2947 		offsetT val,
   2948 		char *file,
   2949 		unsigned line)
   2950 {
   2951   offsetT min = 0, max = 0;
   2952 
   2953   if (operand->bits != 32
   2954       && !(operand->flags & ARC_OPERAND_NCHK)
   2955       && !(operand->flags & ARC_OPERAND_FAKE))
   2956     {
   2957       if (operand->flags & ARC_OPERAND_SIGNED)
   2958 	{
   2959 	  max = (1 << (operand->bits - 1)) - 1;
   2960 	  min = -(1 << (operand->bits - 1));
   2961 	}
   2962       else
   2963 	{
   2964 	  max = (1 << operand->bits) - 1;
   2965 	  min = 0;
   2966 	}
   2967 
   2968       if (val < min || val > max)
   2969 	as_bad_value_out_of_range (_("operand"),
   2970 				   val, min, max, file, line);
   2971     }
   2972 
   2973   pr_debug ("insert field: %ld <= %ld <= %ld in 0x%08x\n",
   2974 	    min, val, max, insn);
   2975 
   2976   if ((operand->flags & ARC_OPERAND_ALIGNED32)
   2977       && (val & 0x03))
   2978     as_bad_where (file, line,
   2979 		  _("Unaligned operand. Needs to be 32bit aligned"));
   2980 
   2981   if ((operand->flags & ARC_OPERAND_ALIGNED16)
   2982       && (val & 0x01))
   2983     as_bad_where (file, line,
   2984 		  _("Unaligned operand. Needs to be 16bit aligned"));
   2985 
   2986   if (operand->insert)
   2987     {
   2988       const char *errmsg = NULL;
   2989 
   2990       insn = (*operand->insert) (insn, val, &errmsg);
   2991       if (errmsg)
   2992 	as_warn_where (file, line, "%s", errmsg);
   2993     }
   2994   else
   2995     {
   2996       if (operand->flags & ARC_OPERAND_TRUNCATE)
   2997 	{
   2998 	  if (operand->flags & ARC_OPERAND_ALIGNED32)
   2999 	    val >>= 2;
   3000 	  if (operand->flags & ARC_OPERAND_ALIGNED16)
   3001 	    val >>= 1;
   3002 	}
   3003       insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift);
   3004     }
   3005   return insn;
   3006 }
   3007 
   3008 void
   3009 arc_handle_align (fragS* fragP)
   3010 {
   3011   if ((fragP)->fr_type == rs_align_code)
   3012     {
   3013       char *dest = (fragP)->fr_literal + (fragP)->fr_fix;
   3014       valueT count = ((fragP)->fr_next->fr_address
   3015 		      - (fragP)->fr_address - (fragP)->fr_fix);
   3016 
   3017       (fragP)->fr_var = 2;
   3018 
   3019       if (count & 1)/* Padding in the gap till the next 2-byte
   3020 		       boundary with 0s.  */
   3021 	{
   3022 	  (fragP)->fr_fix++;
   3023 	  *dest++ = 0;
   3024 	}
   3025       /* Writing nop_s.  */
   3026       md_number_to_chars (dest, NOP_OPCODE_S, 2);
   3027     }
   3028 }
   3029 
   3030 /* Here we decide which fixups can be adjusted to make them relative
   3031    to the beginning of the section instead of the symbol.  Basically
   3032    we need to make sure that the dynamic relocations are done
   3033    correctly, so in some cases we force the original symbol to be
   3034    used.  */
   3035 
   3036 int
   3037 tc_arc_fix_adjustable (fixS *fixP)
   3038 {
   3039 
   3040   /* Prevent all adjustments to global symbols.  */
   3041   if (S_IS_EXTERNAL (fixP->fx_addsy))
   3042     return 0;
   3043   if (S_IS_WEAK (fixP->fx_addsy))
   3044     return 0;
   3045 
   3046   /* Adjust_reloc_syms doesn't know about the GOT.  */
   3047   switch (fixP->fx_r_type)
   3048     {
   3049     case BFD_RELOC_ARC_GOTPC32:
   3050     case BFD_RELOC_ARC_PLT32:
   3051     case BFD_RELOC_ARC_S25H_PCREL_PLT:
   3052     case BFD_RELOC_ARC_S21H_PCREL_PLT:
   3053     case BFD_RELOC_ARC_S25W_PCREL_PLT:
   3054     case BFD_RELOC_ARC_S21W_PCREL_PLT:
   3055       return 0;
   3056 
   3057     default:
   3058       break;
   3059     }
   3060 
   3061   return 0; /* FIXME! return 1, fix it in the linker.  */
   3062 }
   3063 
   3064 /* Compute the reloc type of an expression EXP.  */
   3065 
   3066 static void
   3067 arc_check_reloc (expressionS *exp,
   3068 		 bfd_reloc_code_real_type *r_type_p)
   3069 {
   3070   if (*r_type_p == BFD_RELOC_32
   3071       && exp->X_op == O_subtract
   3072       && exp->X_op_symbol != NULL
   3073       && exp->X_op_symbol->bsym->section == now_seg)
   3074     *r_type_p = BFD_RELOC_ARC_32_PCREL;
   3075 }
   3076 
   3077 
   3078 /* Add expression EXP of SIZE bytes to offset OFF of fragment FRAG.  */
   3079 
   3080 void
   3081 arc_cons_fix_new (fragS *frag,
   3082 		  int off,
   3083 		  int size,
   3084 		  expressionS *exp,
   3085 		  bfd_reloc_code_real_type r_type)
   3086 {
   3087   r_type = BFD_RELOC_UNUSED;
   3088 
   3089   switch (size)
   3090     {
   3091     case 1:
   3092       r_type = BFD_RELOC_8;
   3093       break;
   3094 
   3095     case 2:
   3096       r_type = BFD_RELOC_16;
   3097       break;
   3098 
   3099     case 3:
   3100       r_type = BFD_RELOC_24;
   3101       break;
   3102 
   3103     case 4:
   3104       r_type = BFD_RELOC_32;
   3105       arc_check_reloc (exp, &r_type);
   3106       break;
   3107 
   3108     case 8:
   3109       r_type = BFD_RELOC_64;
   3110       break;
   3111 
   3112     default:
   3113       as_bad (_("unsupported BFD relocation size %u"), size);
   3114       r_type = BFD_RELOC_UNUSED;
   3115     }
   3116 
   3117   fix_new_exp (frag, off, size, exp, 0, r_type);
   3118 }
   3119 
   3120 /* The actual routine that checks the ZOL conditions.  */
   3121 
   3122 static void
   3123 check_zol (symbolS *s)
   3124 {
   3125   switch (arc_mach_type)
   3126     {
   3127     case bfd_mach_arc_arcv2:
   3128       if (arc_target & ARC_OPCODE_ARCv2EM)
   3129 	return;
   3130 
   3131       if (is_br_jmp_insn_p (arc_last_insns[0].opcode)
   3132 	  || arc_last_insns[1].has_delay_slot)
   3133 	as_bad (_("Jump/Branch instruction detected at the end of the ZOL label @%s"),
   3134 		S_GET_NAME (s));
   3135 
   3136       break;
   3137     case bfd_mach_arc_arc600:
   3138 
   3139       if (is_kernel_insn_p (arc_last_insns[0].opcode))
   3140 	as_bad (_("Kernel instruction detected at the end of the ZOL label @%s"),
   3141 		S_GET_NAME (s));
   3142 
   3143       if (arc_last_insns[0].has_limm
   3144 	  && is_br_jmp_insn_p (arc_last_insns[0].opcode))
   3145 	as_bad (_("A jump instruction with long immediate detected at the \
   3146 end of the ZOL label @%s"), S_GET_NAME (s));
   3147 
   3148       /* Fall through.  */
   3149     case bfd_mach_arc_arc700:
   3150       if (arc_last_insns[0].has_delay_slot)
   3151 	as_bad (_("An illegal use of delay slot detected at the end of the ZOL label @%s"),
   3152 		S_GET_NAME (s));
   3153 
   3154       break;
   3155     default:
   3156       break;
   3157     }
   3158 }
   3159 
   3160 /* If ZOL end check the last two instruction for illegals.  */
   3161 void
   3162 arc_frob_label (symbolS * sym)
   3163 {
   3164   if (ARC_GET_FLAG (sym) & ARC_FLAG_ZOL)
   3165     check_zol (sym);
   3166 
   3167   dwarf2_emit_label (sym);
   3168 }
   3169